Complete overhaul of WD33c93 SCSI driver
- Full support for SCSI-2 Tagged commands (enabled by default) - Implement save and restore datapointer messages - Formalize interface between MI and MD drivers. - decouple interface between MD driver and DMA routines - Use scsipi layer where appropriate (Tags, Sync Negotiations etc) - control blocks stored using kernel pool(9) functions - evcnt(9) compliant counters - Enable advanced features on later WD33c93 chips. (Identify message out phase is hardware assisted) - Improved timeout support (one per active control block) - Improved MESG_IN and MESG_OUT handling - Start to tidy up debugging output - Numerous bug fixes and cleanups throughout Changes are based largely on the NCR53c9x MI driver for ideas on how to DTRT.
This commit is contained in:
parent
9a07d795e3
commit
de81761c50
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: hpcdma.h,v 1.1 2001/08/19 03:16:21 wdk Exp $ */
|
||||
/* $NetBSD: hpcdma.h,v 1.2 2001/11/10 07:32:42 wdk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wayne Knowles
|
||||
|
@ -36,8 +36,8 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SGIMIPS_BUS_DMA_H
|
||||
#define _SGIMIPS_BUS_DMA_H
|
||||
#ifndef _SGIMIPS_HPC_DMA_H
|
||||
#define _SGIMIPS_HPC_DMA_H
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
|
@ -47,13 +47,15 @@ struct hpc_dma_softc {
|
|||
bus_dma_tag_t sc_dmat;
|
||||
|
||||
u_int32_t sc_flags;
|
||||
#define HPC_DMA_ACTIVE 0x80
|
||||
#define HPC_DMA_READ 0x20
|
||||
#define HPCDMA_READ 0x20 /* direction of transfer */
|
||||
#define HPCDMA_LOADED 0x40 /* bus_dmamap loaded */
|
||||
#define HPCDMA_ACTIVE 0x80 /* DMA engine is busy */
|
||||
u_int32_t sc_dmacmd;
|
||||
int sc_ndesc;
|
||||
bus_dmamap_t sc_dmamap;
|
||||
struct hpc_dma_desc *sc_desc_kva; /* Virtual address */
|
||||
struct hpc_dma_desc *sc_desc_pa; /* Physical address */
|
||||
ssize_t sc_dlen; /* number of bytes transfered */
|
||||
};
|
||||
|
||||
|
||||
|
@ -62,4 +64,4 @@ void hpcdma_sglist_create(struct hpc_dma_softc *, bus_dmamap_t);
|
|||
void hpcdma_cntl(struct hpc_dma_softc *, u_int32_t);
|
||||
void hpcdma_flush(struct hpc_dma_softc *);
|
||||
|
||||
#endif
|
||||
#endif /* _SGIMIPS_HPC_DMA_H */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sbicreg.h,v 1.1 2001/08/19 03:16:22 wdk Exp $ */
|
||||
/* $NetBSD: sbicreg.h,v 1.2 2001/11/10 07:32:42 wdk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wayne Knowles
|
||||
|
@ -84,6 +84,9 @@
|
|||
#define SBIC_csr 23
|
||||
#define SBIC_cmd 24
|
||||
#define SBIC_data 25
|
||||
#define SBIC_queue_tag 26
|
||||
#define SBIC_aux_status 27
|
||||
|
||||
/* sbic_asr is addressed directly */
|
||||
|
||||
/*
|
||||
|
@ -107,9 +110,10 @@
|
|||
*/
|
||||
|
||||
#define SBIC_ID_FS_8_10 0x00 /* Input clock is 8-10 Mhz */
|
||||
/* 11 Mhz is invalid */
|
||||
/* 11 Mhz is invalid */
|
||||
#define SBIC_ID_FS_12_15 0x40 /* Input clock is 12-15 Mhz */
|
||||
#define SBIC_ID_FS_16_20 0x80 /* Input clock is 16-20 Mhz */
|
||||
#define SBIC_ID_RAF 0x20 /* */
|
||||
#define SBIC_ID_EHP 0x10 /* Enable host parity */
|
||||
#define SBIC_ID_EAF 0x08 /* Enable Advanced Features */
|
||||
#define SBIC_ID_MASK 0x07
|
||||
|
@ -304,6 +308,21 @@
|
|||
#define SBIC_CMD_RESELECT_SEND 0x0b /* (DT ) lev II */
|
||||
#define SBIC_CMD_WAIT_SEL_RECV 0x0c /* (DT ) lev II */
|
||||
|
||||
|
||||
#define PHASE_MASK 0x07 /* mask for psns/pctl phase */
|
||||
#define DATA_OUT_PHASE 0x00
|
||||
#define DATA_IN_PHASE 0x01
|
||||
#define CMD_PHASE 0x02
|
||||
#define STATUS_PHASE 0x03
|
||||
#define BUS_FREE_PHASE 0x04
|
||||
#define ARB_SEL_PHASE 0x05 /* Fuji chip combines bus arb with sel. */
|
||||
#define MESG_OUT_PHASE 0x06
|
||||
#define MESG_IN_PHASE 0x07
|
||||
|
||||
#define SCSI_PHASE(reg) ((reg) & PHASE_MASK)
|
||||
|
||||
#define SCSI_STATUS_MASK 0x3e /* Mask unused bits in status byte */
|
||||
|
||||
/* approximate, but we won't do SBT on selects */
|
||||
#define sbic_isa_select(cmd) (((cmd) > 0x5) && ((cmd) < 0xa))
|
||||
|
||||
|
@ -387,6 +406,8 @@ typedef volatile sbic_padded_ind_regmap_t *sbic_regmap_p;
|
|||
#define GET_SBIC_cmd(sc,val) sbic_read_reg(sc,SBIC_cmd,val)
|
||||
#define SET_SBIC_data(sc,val) sbic_write_reg(sc,SBIC_data,val)
|
||||
#define GET_SBIC_data(sc,val) sbic_read_reg(sc,SBIC_data,val)
|
||||
#define SET_SBIC_queue_tag(sc,val) sbic_write_reg(sc,SBIC_queue_tag,val)
|
||||
#define GET_SBIC_queue_tag(sc,val) sbic_read_reg(sc,SBIC_queue_tag,val)
|
||||
|
||||
#define SBIC_TC_PUT(sc,val) \
|
||||
do { \
|
||||
|
@ -411,12 +432,12 @@ typedef volatile sbic_padded_ind_regmap_t *sbic_regmap_p;
|
|||
int n = (cmdsize) - 1; \
|
||||
char *ptr = (char *)(cmd); \
|
||||
sbic_write_reg(regs, SBIC_cdb1, *ptr++); \
|
||||
while(n-- > 0) /* (regs)->sbic_value = *ptr++; */ \
|
||||
while(n-- > 0) \
|
||||
bus_space_write_1((sc)->sc_regt, (sc)->sc_regh, \
|
||||
SBIC_VAL, *ptr++); /* XXX write_multi */ \
|
||||
} while (0)
|
||||
|
||||
#define GET_SBIC_asr(sc,val) /* (val) = (regs)->sbic_asr */ \
|
||||
#define GET_SBIC_asr(sc,val) \
|
||||
do { \
|
||||
(val) = bus_space_read_1((sc)->sc_regt,(sc)->sc_regh,SBIC_ASR); \
|
||||
} while (0)
|
||||
|
@ -424,7 +445,6 @@ typedef volatile sbic_padded_ind_regmap_t *sbic_regmap_p;
|
|||
|
||||
#define WAIT_CIP(sc) \
|
||||
do { \
|
||||
/* while ((regs)->sbic_asr & SBIC_ASR_CIP) */ \
|
||||
while (bus_space_read_1((sc)->sc_regt,(sc)->sc_regh, \
|
||||
SBIC_ASR) & SBIC_ASR_CIP) \
|
||||
/*nop*/; \
|
||||
|
@ -432,7 +452,7 @@ typedef volatile sbic_padded_ind_regmap_t *sbic_regmap_p;
|
|||
|
||||
/*
|
||||
* transmit a byte in programmed I/O mode
|
||||
**/
|
||||
*/
|
||||
#define SEND_BYTE(sc, ch) \
|
||||
do { \
|
||||
WAIT_CIP(sc); \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sbicvar.h,v 1.1 2001/08/19 03:16:22 wdk Exp $ */
|
||||
/* $NetBSD: sbicvar.h,v 1.2 2001/11/10 07:32:43 wdk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
|
@ -42,37 +42,43 @@
|
|||
#include <sys/callout.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
/*
|
||||
* DMA chains are used for Scatter-Gather DMA.
|
||||
*/
|
||||
struct dma_chain {
|
||||
int dc_count;
|
||||
char *dc_addr;
|
||||
};
|
||||
#define SBIC_NTARG 8
|
||||
#define SBIC_NLUN 8
|
||||
#define SBIC_NTAGS 256
|
||||
|
||||
#define SBIC_MAX_MSGLEN 8
|
||||
|
||||
#define SBIC_ABORT_TIMEOUT 2000 /* time to wait for abort */
|
||||
#define SBIC_SENSE_TIMEOUT 1000 /* time to wait for sense */
|
||||
|
||||
/*
|
||||
* ACB. Holds additional information for each SCSI command Comments: We
|
||||
* need a separate scsi command block because we may need to overwrite it
|
||||
* with a request sense command. Basicly, we refrain from fiddling with
|
||||
* with a request sense command. Basically, we refrain from fiddling with
|
||||
* the scsi_xfer struct (except do the expected updating of return values).
|
||||
* We'll generally update: xs->{flags,resid,error,sense,status} and
|
||||
* occasionally xs->retries.
|
||||
*/
|
||||
struct sbic_acb {
|
||||
TAILQ_ENTRY(sbic_acb) chain;
|
||||
struct scsipi_xfer *xs; /* SCSI xfer ctrl block from above */
|
||||
int flags; /* Status */
|
||||
#define ACB_FREE 0x00
|
||||
#define ACB_ACTIVE 0x01
|
||||
#define ACB_DONE 0x04
|
||||
#define ACB_BBUF 0x10 /* DMA input needs to be copied from bounce */
|
||||
#define ACB_DATAIN 0x20 /* DMA direction flag */
|
||||
TAILQ_ENTRY(sbic_acb) chain;
|
||||
struct scsipi_xfer *xs; /* SCSI xfer ctrl block from above */
|
||||
int flags; /* Status */
|
||||
#define ACB_FREE 0x00
|
||||
#define ACB_ACTIVE 0x01
|
||||
#define ACB_READY 0x02 /* ACB is on ready list */
|
||||
#define ACB_DONE 0x04
|
||||
#define ACB_SENSE 0x08 /* ACB Requesting sense */
|
||||
#define ACB_COMPLETE 0x10 /* Disconnected at end of xfer */
|
||||
#define ACB_RESET 0x20 /* Require Reset */
|
||||
#define ACB_ABORT 0x40 /* Require Abort */
|
||||
|
||||
struct scsi_generic cmd; /* SCSI command block */
|
||||
int clen;
|
||||
struct dma_chain sc_kv; /* Virtual address of whole DMA */
|
||||
u_long sc_tcnt; /* number of bytes for this DMA */
|
||||
u_short sc_usedma; /* Internal data for this DMA */
|
||||
int timeout;
|
||||
struct scsi_generic cmd; /* SCSI command block */
|
||||
int clen;
|
||||
char *daddr; /* kva for data */
|
||||
size_t dleft; /* bytes remaining */
|
||||
u_char tag_type; /* TAG Type (0x20-0x22, 0=No Tags) */
|
||||
u_char tag_id; /* TAG id number */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -80,127 +86,173 @@ struct sbic_acb {
|
|||
* probably have been a "per target+lunit" structure, but we'll leave it at
|
||||
* this for now. Is there a way to reliably hook it up to sc->fordriver??
|
||||
*/
|
||||
struct sbic_tinfo {
|
||||
int cmds; /* #commands processed */
|
||||
int dconns; /* #disconnects */
|
||||
int lubusy; /* What local units/subr. are busy? */
|
||||
} tinfo_t;
|
||||
|
||||
struct sbic_softc {
|
||||
struct device sc_dev;
|
||||
struct target_sync {
|
||||
u_char state;
|
||||
u_char period;
|
||||
u_char offset;
|
||||
} sc_sync[8];
|
||||
u_char target; /* Currently active target */
|
||||
u_char lun;
|
||||
struct scsipi_channel sc_channel; /* proto for sub devices */
|
||||
struct scsipi_adapter sc_adapter;
|
||||
|
||||
/* HPC registers */
|
||||
bus_space_tag_t sc_hpct;
|
||||
bus_space_handle_t sc_hpch;
|
||||
|
||||
/* HPC external ethernet registers: aka Seeq 8003 registers */
|
||||
bus_space_tag_t sc_regt;
|
||||
bus_space_handle_t sc_regh;
|
||||
|
||||
bus_dma_tag_t sc_dmat;
|
||||
bus_dmamap_t sc_dmamap; /* DMA Map for this transfer */
|
||||
|
||||
void *sc_driver; /* driver specific field */
|
||||
|
||||
struct callout sc_timo_ch;
|
||||
|
||||
/* Lists of command blocks */
|
||||
TAILQ_HEAD(acb_list, sbic_acb) free_list,
|
||||
ready_list,
|
||||
nexus_list;
|
||||
|
||||
struct sbic_acb *sc_nexus; /* current command */
|
||||
struct sbic_acb sc_acb[8]; /* the real command blocks */
|
||||
struct sbic_tinfo sc_tinfo[8];
|
||||
|
||||
struct scsipi_xfer *sc_xs; /* transfer from high level code */
|
||||
u_int32_t sc_flags;
|
||||
u_char sc_stat[2];
|
||||
u_char sc_msg[7];
|
||||
u_long sc_clkfreq;
|
||||
u_long sc_tcnt; /* number of bytes transfered */
|
||||
u_short sc_usedma; /* used by dma drivers */
|
||||
#ifdef DEBUG
|
||||
u_short sc_dmatimo; /* dma timeout */
|
||||
#endif
|
||||
int (*sc_dmasetup) __P((struct sbic_softc *, bus_dmamap_t, int));
|
||||
int (*sc_dmago) __P((struct sbic_softc *));
|
||||
void (*sc_enintr) __P((struct sbic_softc *));
|
||||
void (*sc_dmastop) __P((struct sbic_softc *));
|
||||
struct sbic_linfo {
|
||||
LIST_ENTRY(sbic_linfo) link;
|
||||
time_t last_used;
|
||||
int lun;
|
||||
int used; /* # slots in use */
|
||||
int avail; /* where to start scanning */
|
||||
u_char state;
|
||||
#define L_STATE_IDLE 0
|
||||
#define L_STATE_BUSY 1
|
||||
#define L_STATE_ESTAT 2
|
||||
struct sbic_acb *untagged;
|
||||
struct sbic_acb *queued[SBIC_NTAGS];
|
||||
};
|
||||
|
||||
/*
|
||||
* sc_flags
|
||||
*/
|
||||
#define SBICF_ALIVE 0x01 /* controller initialized */
|
||||
#define SBICF_DCFLUSH 0x02 /* need flush for overlap after dma finishes */
|
||||
#define SBICF_SELECTED 0x04 /* bus is in selected state. */
|
||||
#define SBICF_ICMD 0x08 /* Immediate command in execution */
|
||||
#define SBICF_BADDMA 0x10 /* controller can only DMA */
|
||||
#define SBICF_DMALOADED 0x20 /* bus_dmamap loaded */
|
||||
#define SBICF_INTR 0x40 /* SBICF interrupt expected */
|
||||
#define SBICF_INDMA 0x80 /* not used yet, DMA I/O in progress */
|
||||
struct sbic_tinfo {
|
||||
int cmds; /* # of commands processed */
|
||||
int dconns; /* # of disconnects */
|
||||
|
||||
/*
|
||||
* sync states
|
||||
*/
|
||||
#define SYNC_START 0 /* no sync handshake started */
|
||||
#define SYNC_SENT 1 /* we sent sync request, no answer yet */
|
||||
#define SYNC_DONE 2 /* target accepted our (or inferior) settings,
|
||||
or it rejected the request and we stay async */
|
||||
u_char flags;
|
||||
#define T_NEED_RESET 0x01 /* Should send a BUS_DEV_RESET */
|
||||
#define T_NEGOTIATE 0x02 /* (Re)Negotiate synchronous options */
|
||||
#define T_BUSY 0x04 /* Target is busy */
|
||||
#define T_SYNCMODE 0x08 /* SYNC mode has been negotiated */
|
||||
#define T_NOSYNC 0x10 /* Force ASYNC mode */
|
||||
#define T_NODISC 0x20 /* Don't allow disconnect */
|
||||
#define T_TAG 0x40 /* Turn on TAG QUEUEs */
|
||||
u_char period; /* Period suggestion */
|
||||
u_char offset; /* Offset suggestion */
|
||||
u_char nextag; /* Next available tag */
|
||||
struct sbic_linfo *lun[SBIC_NLUN]; /* LUN list for this target */
|
||||
} tinfo_t;
|
||||
|
||||
#define PHASE 0x07 /* mask for psns/pctl phase */
|
||||
#define DATA_OUT_PHASE 0x00
|
||||
#define DATA_IN_PHASE 0x01
|
||||
#define CMD_PHASE 0x02
|
||||
#define STATUS_PHASE 0x03
|
||||
#define BUS_FREE_PHASE 0x04
|
||||
#define ARB_SEL_PHASE 0x05 /* Fuji chip combines arbitration with sel. */
|
||||
#define MESG_OUT_PHASE 0x06
|
||||
#define MESG_IN_PHASE 0x07
|
||||
/* Look up a lun in a tinfo */
|
||||
#define TINFO_LUN(t, l) ((t)->lun[(l)])
|
||||
|
||||
#define MSG_CMD_COMPLETE 0x00
|
||||
#define MSG_EXT_MESSAGE 0x01
|
||||
#define MSG_SAVE_DATA_PTR 0x02
|
||||
#define MSG_RESTORE_PTR 0x03
|
||||
#define MSG_DISCONNECT 0x04
|
||||
#define MSG_INIT_DETECT_ERROR 0x05
|
||||
#define MSG_ABORT 0x06
|
||||
#define MSG_REJECT 0x07
|
||||
#define MSG_NOOP 0x08
|
||||
#define MSG_PARITY_ERROR 0x09
|
||||
#define MSG_BUS_DEVICE_RESET 0x0C
|
||||
#define MSG_IDENTIFY 0x80
|
||||
#define MSG_IDENTIFY_DR 0xc0 /* (disconnect/reconnect allowed) */
|
||||
#define MSG_SYNC_REQ 0x01
|
||||
struct sbic_softc {
|
||||
struct device sc_dev;
|
||||
|
||||
#define MSG_ISIDENTIFY(x) ((x) & MSG_IDENTIFY)
|
||||
struct scsipi_channel sc_channel; /* proto for sub devices */
|
||||
struct scsipi_adapter sc_adapter;
|
||||
struct device *sc_child; /* attached scsibus, if any */
|
||||
struct callout sc_watchdog;
|
||||
void *sc_driver; /* driver specific field */
|
||||
|
||||
int target; /* Currently active target */
|
||||
int lun; /* Currently active LUN */
|
||||
|
||||
/* WD33c93 registers */
|
||||
bus_space_tag_t sc_regt;
|
||||
bus_space_handle_t sc_regh;
|
||||
|
||||
|
||||
#define STS_CHECKCOND 0x02 /* Check Condition (ie., read sense) */
|
||||
#define STS_CONDMET 0x04 /* Condition Met (ie., search worked) */
|
||||
#define STS_BUSY 0x08
|
||||
#define STS_INTERMED 0x10 /* Intermediate status sent */
|
||||
#define STS_EXT 0x80 /* Extended status valid */
|
||||
/* Data about the current nexus (updated for every cmd switch) */
|
||||
caddr_t sc_daddr; /* Current data pointer */
|
||||
size_t sc_dleft; /* Data left to transfer */
|
||||
ssize_t sc_tcnt; /* number of bytes transfered */
|
||||
|
||||
/* Lists of command blocks */
|
||||
TAILQ_HEAD(acb_list, sbic_acb) ready_list;
|
||||
|
||||
struct sbic_acb *sc_nexus; /* current command */
|
||||
struct sbic_tinfo sc_tinfo[8];
|
||||
|
||||
u_short sc_state;
|
||||
u_short sc_status;
|
||||
int sc_disc; /* current # of active nexus's */
|
||||
int sc_flags;
|
||||
|
||||
/* Message stuff */
|
||||
u_short sc_msgify; /* Last IDENTIFY message */
|
||||
u_short sc_msgout; /* Current message out */
|
||||
u_short sc_msgpriq; /* mesg_out queue (bitmap) */
|
||||
u_short sc_msgoutq; /* mesg_out queue */
|
||||
|
||||
u_char sc_imsg[SBIC_MAX_MSGLEN];
|
||||
u_char sc_omsg[SBIC_MAX_MSGLEN];
|
||||
u_char sc_imsglen;
|
||||
u_char sc_omsglen;
|
||||
|
||||
/* Static hardware attributes */
|
||||
int sc_id; /* SCSI ID for controller */
|
||||
int sc_clkfreq; /* wd33c93 clk freq * 10Mhz */
|
||||
int sc_chip; /* Chip variation */
|
||||
int sc_rev; /* Chip revision */
|
||||
int sc_cfflags; /* Copy of config flags */
|
||||
int sc_maxxfer; /* Maximum transfer size */
|
||||
int sc_minsync; /* Minimum sync period (4ns units) */
|
||||
int sc_maxoffset; /* Maximum sync ofset (bytes) */
|
||||
|
||||
int (*sc_dmasetup) __P((struct sbic_softc *,caddr_t *,
|
||||
size_t *,int,size_t *));
|
||||
int (*sc_dmago) __P((struct sbic_softc *));
|
||||
void (*sc_dmastop) __P((struct sbic_softc *));
|
||||
};
|
||||
|
||||
/* values for sc_flags */
|
||||
#define SBICF_SELECTED 0x01 /* bus is in selected state. */
|
||||
#define SBICF_NODMA 0x02 /* Polled transfer */
|
||||
#define SBICF_INDMA 0x04 /* DMA I/O in progress */
|
||||
#define SBICF_SYNCNEGO 0x08 /* Sync negotiation in progress */
|
||||
#define SBICF_ABORTING 0x10 /* Aborting */
|
||||
|
||||
/* values for sc_state */
|
||||
#define SBIC_UNINITIALIZED 0 /* Driver not initialized */
|
||||
#define SBIC_IDLE 1 /* waiting for something to do */
|
||||
#define SBIC_SELECTING 2 /* SCSI command is arbiting */
|
||||
#define SBIC_RESELECTED 3 /* Has been reselected */
|
||||
#define SBIC_IDENTIFIED 4 /* Has gotten IFY but not TAG */
|
||||
#define SBIC_CONNECTED 5 /* Actively using the SCSI bus */
|
||||
#define SBIC_DISCONNECT 6 /* MSG_DISCONNECT received */
|
||||
#define SBIC_CMDCOMPLETE 7 /* MSG_CMDCOMPLETE received */
|
||||
#define SBIC_ERROR 8 /* Error has occured */
|
||||
#define SBIC_SELTIMEOUT 9 /* Select Timeout */
|
||||
#define SBIC_CLEANING 10 /* Scrubbing ACB's */
|
||||
#define SBIC_BUSRESET 11 /* SCSI RST has been issued */
|
||||
|
||||
/* values for sc_msgout */
|
||||
#define SEND_DEV_RESET 0x0001
|
||||
#define SEND_PARITY_ERROR 0x0002
|
||||
#define SEND_INIT_DET_ERR 0x0004
|
||||
#define SEND_REJECT 0x0008
|
||||
#define SEND_IDENTIFY 0x0010
|
||||
#define SEND_ABORT 0x0020
|
||||
#define SEND_WDTR 0x0040
|
||||
#define SEND_SDTR 0x0080
|
||||
#define SEND_TAG 0x0100
|
||||
|
||||
/* WD33c93 chipset revisions - values for sc_rev */
|
||||
#define SBIC_CHIP_UNKNOWN 0
|
||||
#define SBIC_CHIP_WD33C93 1
|
||||
#define SBIC_CHIP_WD33C93A 2
|
||||
#define SBIC_CHIP_WD33C93B 3
|
||||
|
||||
#define SBIC_CHIP_LIST {"UNKNOWN", "WD33C93", "WD33C93A", "WD33C93B"}
|
||||
|
||||
/*
|
||||
* States returned by our state machine
|
||||
*/
|
||||
#define SBIC_STATE_ERROR -1
|
||||
#define SBIC_STATE_DONE 0
|
||||
#define SBIC_STATE_RUNNING 1
|
||||
#define SBIC_STATE_DISCONNECT 2
|
||||
|
||||
#define SBIC_STATE_ERROR -1
|
||||
#define SBIC_STATE_DONE 0
|
||||
#define SBIC_STATE_RUNNING 1
|
||||
#define SBIC_STATE_DISCONNECT 2
|
||||
#define DEBUG_ACBS 0x01
|
||||
#define DEBUG_INTS 0x02
|
||||
#define DEBUG_CMDS 0x04
|
||||
#define DEBUG_MISC 0x08
|
||||
#define DEBUG_TRAC 0x10
|
||||
#define DEBUG_RSEL 0x20
|
||||
#define DEBUG_PHASE 0x40
|
||||
#define DEBUG_DMA 0x80
|
||||
#define DEBUG_CCMDS 0x100
|
||||
#define DEBUG_MSGS 0x200
|
||||
#define DEBUG_TAGS 0x400
|
||||
#define DEBUG_SYNC 0x800
|
||||
|
||||
#ifdef DEBUG
|
||||
extern int sbic_debug_flags;
|
||||
#define SBIC_DEBUG(level, str) \
|
||||
do { \
|
||||
if (sbic_debug & __CONCAT(DEBUG_,level)) \
|
||||
printf str; \
|
||||
} while (0)
|
||||
#else
|
||||
#define SBIC_DEBUG(level, str)
|
||||
#endif
|
||||
|
||||
struct buf;
|
||||
struct scsipi_xfer;
|
||||
|
@ -208,7 +260,7 @@ struct scsipi_xfer;
|
|||
void sbic_minphys __P((struct buf *bp));
|
||||
void sbic_scsi_request __P((struct scsipi_channel *,
|
||||
scsipi_adapter_req_t, void *));
|
||||
void sbicinit __P((struct sbic_softc *));
|
||||
int sbicintr __P((struct sbic_softc *));
|
||||
void sbic_attach __P((struct sbic_softc *));
|
||||
int sbic_intr __P((struct sbic_softc *));
|
||||
|
||||
#endif /* _SBICVAR_H_ */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: wdsc.c,v 1.1 2001/08/19 03:16:22 wdk Exp $ */
|
||||
/* $NetBSD: wdsc.c,v 1.2 2001/11/10 07:32:43 wdk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wayne Knowles
|
||||
|
@ -38,13 +38,7 @@
|
|||
|
||||
/*
|
||||
* TODO:
|
||||
*
|
||||
* Support for 2nd SCSI controller
|
||||
* evcnt(9) hooks
|
||||
* remove struct dma_chain
|
||||
* dma{setup,stop,go} API similar to NCR93c9x MI driver
|
||||
* improve hpcdma functions
|
||||
* cleanup softc stuff
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
|
@ -68,9 +62,17 @@
|
|||
#include <sgimips/hpc/sbicreg.h>
|
||||
#include <sgimips/hpc/sbicvar.h>
|
||||
|
||||
#include <opt_kgdb.h>
|
||||
#include <sys/kgdb.h>
|
||||
|
||||
struct wdsc_softc {
|
||||
struct sbic_softc sc_sbic; /* Must be first */
|
||||
|
||||
struct evcnt sc_intrcnt; /* Interrupt counter */
|
||||
bus_dma_tag_t sc_dmat;
|
||||
bus_dmamap_t sc_dmamap;
|
||||
int sc_flags;
|
||||
#define WDSC_DMA_ACTIVE 0x1
|
||||
#define WDSC_DMA_MAPLOADED 0x2
|
||||
struct hpc_dma_softc sc_hpcdma;
|
||||
};
|
||||
|
||||
|
@ -84,8 +86,8 @@ struct cfattach wdsc_ca = {
|
|||
|
||||
extern struct cfdriver wdsc_cd;
|
||||
|
||||
void wdsc_enintr __P((struct sbic_softc *));
|
||||
int wdsc_dmasetup __P((struct sbic_softc *, bus_dmamap_t, int));
|
||||
int wdsc_dmasetup __P((struct sbic_softc *, caddr_t *,size_t *,
|
||||
int, size_t *));
|
||||
int wdsc_dmago __P((struct sbic_softc *));
|
||||
void wdsc_dmastop __P((struct sbic_softc *));
|
||||
int wdsc_dmaintr __P((void *));
|
||||
|
@ -101,15 +103,15 @@ int wdsc_scsiintr __P((void *));
|
|||
*/
|
||||
int
|
||||
wdsc_match(pdp, cf, auxp)
|
||||
struct device *pdp;
|
||||
struct cfdata *cf;
|
||||
void *auxp;
|
||||
struct device *pdp;
|
||||
struct cfdata *cf;
|
||||
void *auxp;
|
||||
{
|
||||
struct hpc_attach_args *haa = auxp;
|
||||
struct hpc_attach_args *haa = auxp;
|
||||
|
||||
if (strcmp(haa->ha_name, wdsc_cd.cd_name))
|
||||
return (0);
|
||||
return (1);
|
||||
if (strcmp(haa->ha_name, wdsc_cd.cd_name))
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -117,134 +119,102 @@ wdsc_match(pdp, cf, auxp)
|
|||
*/
|
||||
void
|
||||
wdsc_attach(pdp, dp, auxp)
|
||||
struct device *pdp, *dp;
|
||||
void *auxp;
|
||||
struct device *pdp, *dp;
|
||||
void *auxp;
|
||||
{
|
||||
struct sbic_softc *sc = (void *)dp;
|
||||
struct wdsc_softc *wdsc = (void *)dp;
|
||||
struct hpc_attach_args *haa = auxp;
|
||||
int err;
|
||||
struct sbic_softc *sc = (void *)dp;
|
||||
struct wdsc_softc *wsc = (void *)dp;
|
||||
struct hpc_attach_args *haa = auxp;
|
||||
int err;
|
||||
|
||||
sc->sc_regt = haa->ha_iot;
|
||||
sc->sc_dmat = haa->ha_dmat;
|
||||
sc->sc_regt = haa->ha_iot;
|
||||
wsc->sc_dmat = haa->ha_dmat;
|
||||
|
||||
if ((err = bus_space_subregion(haa->ha_iot, haa->ha_ioh,
|
||||
if ((err = bus_space_subregion(haa->ha_iot, haa->ha_ioh,
|
||||
HPC_SCSI0_DEVREGS,
|
||||
HPC_SCSI0_DEVREGS_SIZE,
|
||||
&sc->sc_regh)) != 0) {
|
||||
printf(": unable to map WD33C93 regs, err=%d\n", err);
|
||||
goto fail;
|
||||
}
|
||||
printf(": unable to map regs, err=%d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bus_dmamap_create(sc->sc_dmat, MAX_DMA_SZ,
|
||||
if (bus_dmamap_create(wsc->sc_dmat, MAX_DMA_SZ,
|
||||
DMA_SEGS, MAX_SEG_SZ, MAX_SEG_SZ,
|
||||
BUS_DMA_WAITOK,
|
||||
&sc->sc_dmamap) != 0) {
|
||||
&wsc->sc_dmamap) != 0) {
|
||||
printf(": failed to create dmamap\n");
|
||||
goto fail;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
hpcdma_init(haa, &wdsc->sc_hpcdma, DMA_SEGS);
|
||||
sc->sc_dmasetup = wdsc_dmasetup;
|
||||
sc->sc_dmago = wdsc_dmago;
|
||||
sc->sc_dmastop = wdsc_dmastop;
|
||||
|
||||
sc->sc_enintr = wdsc_enintr;
|
||||
sc->sc_dmasetup = wdsc_dmasetup;
|
||||
sc->sc_dmago = wdsc_dmago;
|
||||
sc->sc_dmastop = wdsc_dmastop;
|
||||
sc->sc_adapter.adapt_request = sbic_scsi_request;
|
||||
sc->sc_adapter.adapt_minphys = minphys;
|
||||
|
||||
sc->sc_adapter.adapt_dev = &sc->sc_dev;
|
||||
sc->sc_adapter.adapt_nchannels = 1;
|
||||
sc->sc_adapter.adapt_openings = 7;
|
||||
sc->sc_adapter.adapt_max_periph = 1;
|
||||
sc->sc_adapter.adapt_ioctl = NULL;
|
||||
sc->sc_adapter.adapt_minphys = minphys;
|
||||
sc->sc_adapter.adapt_request = sbic_scsi_request;
|
||||
sc->sc_channel.chan_adapter = &sc->sc_adapter;
|
||||
sc->sc_channel.chan_bustype = &scsi_bustype;
|
||||
sc->sc_channel.chan_channel = 0;
|
||||
sc->sc_channel.chan_ntargets = 8;
|
||||
sc->sc_channel.chan_nluns = 8;
|
||||
sc->sc_channel.chan_id = 7;
|
||||
sc->sc_id = 7; /* Host ID = 7 */
|
||||
sc->sc_clkfreq = 200; /* 20MHz Clock */
|
||||
|
||||
printf(": WD33C93 SCSI, target %d\n", sc->sc_channel.chan_id);
|
||||
evcnt_attach_dynamic(&wsc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
|
||||
sc->sc_dev.dv_xname, "intr");
|
||||
|
||||
/*
|
||||
* Controller clock frequency * 10
|
||||
*/
|
||||
sc->sc_clkfreq = 200;
|
||||
|
||||
/*
|
||||
* Initialise the hardware
|
||||
*/
|
||||
sbicinit(sc);
|
||||
|
||||
/* XXX: 1 = IRQ_LOCAL0 + 1 */
|
||||
if ((cpu_intr_establish(1, IPL_BIO, wdsc_scsiintr, sc)) == NULL) {
|
||||
/* XXX: 1 = IRQ_LOCAL0 + 1 */
|
||||
if ((cpu_intr_establish(1, IPL_BIO, wdsc_scsiintr, sc)) == NULL) {
|
||||
printf(": unable to establish interrupt!\n");
|
||||
goto fail;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
(void)config_found(dp, &sc->sc_channel, scsiprint);
|
||||
|
||||
fail:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable DMA interrupts
|
||||
*/
|
||||
void
|
||||
wdsc_enintr(dev)
|
||||
struct sbic_softc *dev;
|
||||
{
|
||||
dev->sc_flags |= SBICF_INTR;
|
||||
hpcdma_init(haa, &wsc->sc_hpcdma, DMA_SEGS);
|
||||
sbic_attach(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prime the hardware for a DMA transfer
|
||||
*
|
||||
* Requires splbio() interrupts to be disabled by the caller
|
||||
*/
|
||||
int
|
||||
wdsc_dmasetup(dev, dmamap, flags)
|
||||
struct sbic_softc *dev;
|
||||
bus_dmamap_t dmamap;
|
||||
int flags;
|
||||
wdsc_dmasetup(dev, addr, len, datain, dmasize)
|
||||
struct sbic_softc *dev;
|
||||
caddr_t *addr;
|
||||
size_t *len;
|
||||
int datain;
|
||||
size_t *dmasize;
|
||||
{
|
||||
struct hpc_dma_softc *dsc = &((struct wdsc_softc *)dev)->sc_hpcdma;
|
||||
struct sbic_acb *acb = dev->sc_nexus;
|
||||
int s;
|
||||
int count, err;
|
||||
void *vaddr;
|
||||
struct wdsc_softc *wsc = (void *)dev;
|
||||
struct hpc_dma_softc *dsc = &wsc->sc_hpcdma;
|
||||
int count, err;
|
||||
void *vaddr;
|
||||
|
||||
KASSERT((dsc->sc_flags & HPC_DMA_ACTIVE) == 0);
|
||||
KASSERT((wsc->sc_flags & WDSC_DMA_ACTIVE) == 0);
|
||||
|
||||
vaddr = acb->sc_kv.dc_addr;
|
||||
count = acb->sc_kv.dc_count;
|
||||
vaddr = *addr;
|
||||
count = dsc->sc_dlen = *len;
|
||||
if (count) {
|
||||
KASSERT((wsc->sc_flags & WDSC_DMA_MAPLOADED) == 0);
|
||||
|
||||
if (count) {
|
||||
s = splbio();
|
||||
|
||||
/* have dmamap for the transfering addresses */
|
||||
if ((err=bus_dmamap_load(dev->sc_dmat, dev->sc_dmamap,
|
||||
/* Build list of physical addresses for this transfer */
|
||||
if ((err=bus_dmamap_load(wsc->sc_dmat, wsc->sc_dmamap,
|
||||
vaddr, count,
|
||||
NULL /* kernel address */,
|
||||
BUS_DMA_NOWAIT)) != 0)
|
||||
panic("%s: bus_dmamap_load err=%d",
|
||||
dev->sc_dev.dv_xname, err);
|
||||
|
||||
dev->sc_flags |= SBICF_DMALOADED; /* XXX - Move to MD */
|
||||
dev->sc_flags |= SBICF_INTR;
|
||||
panic("%s: bus_dmamap_load err=%d",
|
||||
dev->sc_dev.dv_xname, err);
|
||||
|
||||
hpcdma_sglist_create(dsc, dev->sc_dmamap);
|
||||
hpcdma_sglist_create(dsc, wsc->sc_dmamap);
|
||||
wsc->sc_flags |= WDSC_DMA_MAPLOADED;
|
||||
|
||||
dsc->sc_dmacmd = HPC_DMACTL_ACTIVE; /* XXX - remove tests in MI */
|
||||
if (flags & ACB_DATAIN) {
|
||||
dsc->sc_flags |= HPC_DMA_READ;
|
||||
} else {
|
||||
dsc->sc_dmacmd |= HPC_DMACTL_DIR;
|
||||
dsc->sc_flags &= ~HPC_DMA_READ;
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
return(count);
|
||||
if (datain) {
|
||||
dsc->sc_dmacmd = HPC_DMACTL_ACTIVE;
|
||||
dsc->sc_flags |= HPCDMA_READ;
|
||||
} else {
|
||||
dsc->sc_dmacmd = HPC_DMACTL_ACTIVE | HPC_DMACTL_DIR;
|
||||
dsc->sc_flags &= ~HPCDMA_READ;
|
||||
}
|
||||
}
|
||||
return(count);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -252,57 +222,64 @@ wdsc_dmasetup(dev, dmamap, flags)
|
|||
*/
|
||||
int
|
||||
wdsc_dmago(dev)
|
||||
struct sbic_softc *dev;
|
||||
struct sbic_softc *dev;
|
||||
{
|
||||
struct hpc_dma_softc *dsc = &((struct wdsc_softc *)dev)->sc_hpcdma;
|
||||
struct wdsc_softc *wsc = (void *)dev;
|
||||
struct hpc_dma_softc *dsc = &wsc->sc_hpcdma;
|
||||
|
||||
if (dev->sc_tcnt == 0) {
|
||||
return(0);
|
||||
}
|
||||
if (dsc->sc_dlen == 0)
|
||||
return(0);
|
||||
|
||||
KASSERT((dsc->sc_flags & HPC_DMA_ACTIVE) == 0);
|
||||
dsc->sc_flags |= HPC_DMA_ACTIVE;
|
||||
KASSERT((wsc->sc_flags & WDSC_DMA_ACTIVE) == 0);
|
||||
KASSERT((wsc->sc_flags & WDSC_DMA_MAPLOADED));
|
||||
|
||||
bus_dmamap_sync(dev->sc_dmat, dev->sc_dmamap, 0, dev->sc_tcnt,
|
||||
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
|
||||
wsc->sc_flags |= WDSC_DMA_ACTIVE;
|
||||
|
||||
hpcdma_cntl(dsc, dsc->sc_dmacmd); /* Thunderbirds are go! */
|
||||
bus_dmamap_sync(wsc->sc_dmat, wsc->sc_dmamap, 0,
|
||||
wsc->sc_dmamap->dm_mapsize,
|
||||
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
|
||||
|
||||
return(dev->sc_dmamap->dm_mapsize);
|
||||
hpcdma_cntl(dsc, dsc->sc_dmacmd); /* Thunderbirds are go! */
|
||||
|
||||
return(wsc->sc_dmamap->dm_mapsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop DMA, and disable interrupts
|
||||
* Stop DMA and unload active DMA maps
|
||||
*/
|
||||
void
|
||||
wdsc_dmastop(dev)
|
||||
struct sbic_softc *dev;
|
||||
struct sbic_softc *dev;
|
||||
{
|
||||
struct hpc_dma_softc *dsc = &((struct wdsc_softc *)dev)->sc_hpcdma;
|
||||
struct wdsc_softc *wsc = (void *)dev;
|
||||
struct hpc_dma_softc *dsc = &wsc->sc_hpcdma;
|
||||
|
||||
if (dsc->sc_flags & HPC_DMA_ACTIVE) {
|
||||
if (dsc->sc_flags & HPC_DMA_READ)
|
||||
hpcdma_flush(dsc);
|
||||
hpcdma_cntl(dsc, 0); /* Stop DMA */
|
||||
bus_dmamap_sync(dev->sc_dmat, dev->sc_dmamap, 0,
|
||||
dev->sc_dmamap->dm_mapsize,
|
||||
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
|
||||
dsc->sc_flags &= ~HPC_DMA_ACTIVE;
|
||||
}
|
||||
if (dev->sc_flags & SBICF_DMALOADED)
|
||||
bus_dmamap_unload(dev->sc_dmat, dev->sc_dmamap);
|
||||
if (wsc->sc_flags & WDSC_DMA_ACTIVE) {
|
||||
if (dsc->sc_flags & HPCDMA_READ)
|
||||
hpcdma_flush(dsc);
|
||||
hpcdma_cntl(dsc, 0); /* Stop DMA */
|
||||
bus_dmamap_sync(wsc->sc_dmat, wsc->sc_dmamap, 0,
|
||||
wsc->sc_dmamap->dm_mapsize,
|
||||
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
|
||||
}
|
||||
if (wsc->sc_flags & WDSC_DMA_MAPLOADED)
|
||||
bus_dmamap_unload(wsc->sc_dmat, wsc->sc_dmamap);
|
||||
wsc->sc_flags &= ~(WDSC_DMA_ACTIVE | WDSC_DMA_MAPLOADED);
|
||||
}
|
||||
|
||||
/*
|
||||
* SCSI controller interrupt
|
||||
* WD33c93 SCSI controller interrupt
|
||||
*/
|
||||
int
|
||||
wdsc_scsiintr(arg)
|
||||
void *arg;
|
||||
void *arg;
|
||||
{
|
||||
struct sbic_softc *dev = arg;
|
||||
int found;
|
||||
struct sbic_softc *dev = arg;
|
||||
struct wdsc_softc *wsc = arg;
|
||||
int found;
|
||||
|
||||
found = sbicintr(dev);
|
||||
return(found);
|
||||
found = sbic_intr(dev);
|
||||
if (found)
|
||||
wsc->sc_intrcnt.ev_count++;
|
||||
return(found);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue