Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/sgimips/hpc Complete overhaul of WD33c93 SCSI driver
details: https://anonhg.NetBSD.org/src/rev/a644a010376c
branches: trunk
changeset: 517298:a644a010376c
user: wdk <wdk%NetBSD.org@localhost>
date: Sat Nov 10 07:32:42 2001 +0000
description:
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.
diffstat:
sys/arch/sgimips/hpc/hpcdma.h | 14 +-
sys/arch/sgimips/hpc/sbic.c | 3970 +++++++++++++++++++--------------------
sys/arch/sgimips/hpc/sbicreg.h | 32 +-
sys/arch/sgimips/hpc/sbicvar.h | 302 +-
sys/arch/sgimips/hpc/wdsc.c | 265 +-
5 files changed, 2293 insertions(+), 2290 deletions(-)
diffs (truncated from 5243 to 300 lines):
diff -r 5443fb867697 -r a644a010376c sys/arch/sgimips/hpc/hpcdma.h
--- a/sys/arch/sgimips/hpc/hpcdma.h Sat Nov 10 07:13:07 2001 +0000
+++ b/sys/arch/sgimips/hpc/hpcdma.h Sat Nov 10 07:32:42 2001 +0000
@@ -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 @@
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_cntl(struct hpc_dma_softc *, u_int32_t);
void hpcdma_flush(struct hpc_dma_softc *);
-#endif
+#endif /* _SGIMIPS_HPC_DMA_H */
diff -r 5443fb867697 -r a644a010376c sys/arch/sgimips/hpc/sbic.c
--- a/sys/arch/sgimips/hpc/sbic.c Sat Nov 10 07:13:07 2001 +0000
+++ b/sys/arch/sgimips/hpc/sbic.c Sat Nov 10 07:32:42 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sbic.c,v 1.1 2001/08/19 03:16:22 wdk Exp $ */
+/* $NetBSD: sbic.c,v 1.2 2001/11/10 07:32:42 wdk Exp $ */
/*
* Changes Copyright (c) 2001 Wayne Knowles
@@ -58,6 +58,7 @@
#include <dev/scsipi/scsi_all.h>
#include <dev/scsipi/scsipi_all.h>
#include <dev/scsipi/scsiconf.h>
+#include <dev/scsipi/scsi_message.h>
#include <uvm/uvm_extern.h>
@@ -67,11 +68,6 @@
#include <sgimips/hpc/sbicvar.h>
/*
- * Since I can't find this in any other header files
- */
-#define SCSI_PHASE(reg) (reg&0x07)
-
-/*
* SCSI delays
* In u-seconds, primarily for state changes on the SPC.
*/
@@ -79,182 +75,387 @@
#define SBIC_DATA_WAIT 50000 /* wait per data in/out step */
#define SBIC_INIT_WAIT 50000 /* wait per step (both) during init */
+#define STATUS_UNKNOWN 0xff /* uninitialized status */
+
/*
* Convenience macro for waiting for a particular sbic event
*/
-#define SBIC_WAIT(regs, until, timeo) sbicwait(regs, until, timeo, __LINE__)
+#define SBIC_WAIT(regs, until, timeo) sbic_wait(regs, until, timeo, __LINE__)
+
+/* Convert SCSI timeout from millisecs to hz avoiding overflow */
+#define SCSI_TIMEOUT(t) ((t)>1000000 ? ((t)/1000)*hz : ((t)*hz)/1000)
-int sbicicmd __P((struct sbic_softc *, void *, int, void *, int));
-int sbicgo __P((struct sbic_softc *, struct scsipi_xfer *));
-int sbicdmaok __P((struct sbic_softc *, struct scsipi_xfer *));
-int sbicwait __P((struct sbic_softc *, u_char, int , int));
-u_char sbicselectbus __P((struct sbic_softc *));
-int sbicxfout __P((struct sbic_softc *, int, void *));
-int sbicxfin __P((struct sbic_softc *, int, void *));
-int sbicfromscsiperiod __P((struct sbic_softc *, int));
-int sbictoscsiperiod __P((struct sbic_softc *, int));
-int sbicpoll __P((struct sbic_softc *));
-int sbicnextstate __P((struct sbic_softc *, u_char, u_char));
-int sbicmsgin __P((struct sbic_softc *));
-int sbicabort __P((struct sbic_softc *, char *));
-void sbicxfdone __P((struct sbic_softc *));
-void sbicerror __P((struct sbic_softc *,u_char));
-void sbicreset __P((struct sbic_softc *));
-void sbic_scsidone __P((struct sbic_acb *, int));
-void sbic_sched __P((struct sbic_softc *));
-void sbic_dma_stop __P((struct sbic_softc *));
-void sbic_dma_setup __P((struct sbic_softc *));
+void sbic_init __P((struct sbic_softc *));
+void sbic_reset __P((struct sbic_softc *));
+int sbic_go __P((struct sbic_softc *, struct sbic_acb *));
+int sbic_dmaok __P((struct sbic_softc *, struct scsipi_xfer *));
+int sbic_wait __P((struct sbic_softc *, u_char, int , int));
+u_char sbic_selectbus __P((struct sbic_softc *, struct sbic_acb *));
+int sbic_xfout __P((struct sbic_softc *, int, void *));
+int sbic_xfin __P((struct sbic_softc *, int, void *));
+int sbic_poll __P((struct sbic_softc *, struct sbic_acb *));
+int sbic_nextstate __P((struct sbic_softc *, struct sbic_acb *,
+ u_char, u_char));
+int sbic_abort __P((struct sbic_softc *, struct sbic_acb *, char *));
+void sbic_xferdone __P((struct sbic_softc *));
+void sbic_error __P((struct sbic_softc *, struct sbic_acb *));
+void sbic_scsidone __P((struct sbic_softc *, struct sbic_acb *, int));
+void sbic_sched __P((struct sbic_softc *));
+void sbic_dequeue __P((struct sbic_softc *, struct sbic_acb *));
+void sbic_dma_stop __P((struct sbic_softc *));
+void sbic_dma_setup __P((struct sbic_softc *, int));
+int sbic_msgin_phase __P((struct sbic_softc *, int));
+void sbic_msgin __P((struct sbic_softc *, u_char *, int));
+void sbic_reselect __P((struct sbic_softc *, int, int, int, int));
+void sbic_sched_msgout __P((struct sbic_softc *, u_short));
+void sbic_msgout __P((struct sbic_softc *));
+void sbic_timeout __P((void *arg));
+void sbic_watchdog __P((void *arg));
+int sbic_div2stp __P((struct sbic_softc *, int));
+int sbic_stp2div __P((struct sbic_softc *, int));
+void sbic_setsync __P((struct sbic_softc *, struct sbic_tinfo *ti));
+void sbic_update_xfer_mode __P((struct sbic_softc *, int));
+void sbic_hexdump __P((u_char *, int));
+
+static struct pool sbic_pool; /* Adapter Control Blocks */
+static int sbic_pool_initialized = 0;
/*
- * Synch xfer parameters, and timing conversions
+ * Timeouts
*/
-int sbic_min_period = SBIC_SYN_MIN_PERIOD; /* in cycles = f(ICLK,FSn) */
-int sbic_max_offset = SBIC_SYN_MAX_OFFSET; /* pure number */
-int sbic_cmd_wait = SBIC_CMD_WAIT;
+int sbic_cmd_wait = SBIC_CMD_WAIT;
int sbic_data_wait = SBIC_DATA_WAIT;
int sbic_init_wait = SBIC_INIT_WAIT;
-/*
- * was broken before.. now if you want this you get it for all drives
- * on sbic controllers.
- */
-u_char sbic_inhibit_sync[8];
-int sbic_enable_reselect = 1; /* Allow Disconnect / Reselect */
-int sbic_no_dma = 0; /* Use PIO transfers instead of DMA */
-int sbic_parallel_operations = 1; /* Allow command queues */
+int sbic_nodma = 0; /* Use polled IO transfers */
+int sbic_nodisc = 0; /* Allow command queues */
+int sbic_notags = 0; /* No Tags */
/*
* Some useful stuff for debugging purposes
*/
#ifdef DEBUG
-#define QPRINTF(a) if (sbic_debug) printf a
+#define QPRINTF(a) SBIC_DEBUG(MISC, a)
-int sbic_debug = 0; /* Debug all chip related things */
-int sync_debug = 0; /* Debug all Synchronous Scsi related things */
-int reselect_debug = 0; /* Debug all reselection related things */
+int sbic_debug = 0; /* Debug all chip related things */
int data_pointer_debug = 0; /* Debug Data Pointer related things */
-void sbictimeout __P((struct sbic_softc *dev));
+void sbic_print_csr __P((u_char));
#else
#define QPRINTF(a) /* */
#endif
+static const char *sbic_chip_names[] = SBIC_CHIP_LIST;
+
+/*
+ * Attach instance of driver and probe for sub devices
+ */
+void
+sbic_attach(dev)
+ struct sbic_softc *dev;
+{
+ struct scsipi_adapter *adapt = &dev->sc_adapter;
+ struct scsipi_channel *chan = &dev->sc_channel;
+
+ adapt->adapt_dev = &dev->sc_dev;
+ adapt->adapt_nchannels = 1;
+ adapt->adapt_openings = 256;
+ adapt->adapt_max_periph = 256; /* Max tags per device */
+ adapt->adapt_ioctl = NULL;
+ /* adapt_request initialized by MD interface */
+ /* adapt_minphys initialized by MD interface */
+
+ memset(chan, 0, sizeof(*chan));
+ chan->chan_adapter = &dev->sc_adapter;
+ chan->chan_bustype = &scsi_bustype;
+ chan->chan_channel = 0;
+ chan->chan_ntargets = SBIC_NTARG;
+ chan->chan_nluns = SBIC_NLUN;
+ chan->chan_id = dev->sc_id;
+
+ callout_init(&dev->sc_watchdog);
+
+ dev->sc_minsync = 200/4; /* Min SCSI sync rate in 4ns units */
+ dev->sc_maxoffset = SBIC_SYN_MAX_OFFSET; /* Max Sync Offset */
+
+ /*
+ * Add reference to adapter so that we drop the reference after
+ * config_found() to make sure the adatper is disabled.
+ */
+ if (scsipi_adapter_addref(&dev->sc_adapter) != 0) {
+ printf("%s: unable to enable controller\n",
+ dev->sc_dev.dv_xname);
+ return;
+ }
+
+ dev->sc_cfflags = dev->sc_dev.dv_cfdata->cf_flags;
+ sbic_init(dev);
+
+ dev->sc_child = config_found(&dev->sc_dev, &dev->sc_channel,
+ scsiprint);
+ scsipi_adapter_delref(&dev->sc_adapter);
+}
+
+/*
+ * Initialize driver-private structures
+ */
+void
+sbic_init(dev)
+ struct sbic_softc *dev;
+{
+ u_int i;
+
+ if (!sbic_pool_initialized) {
+ /* All instances share the same pool */
+ pool_init(&sbic_pool, sizeof(struct sbic_acb), 0, 0, 0,
+ "sbic_acb", 0, NULL, NULL, 0);
+ ++sbic_pool_initialized;
+ }
+
+ if (dev->sc_state == 0) {
+ TAILQ_INIT(&dev->ready_list);
+
+ dev->sc_nexus = NULL;
+ dev->sc_disc = 0;
+ memset(dev->sc_tinfo, 0, sizeof(dev->sc_tinfo));
+
+ callout_reset(&dev->sc_watchdog, 60 * hz, sbic_watchdog, dev);
+ } else
+ panic("sbic: reinitializing driver!");
+
+ dev->sc_flags = 0;
+ dev->sc_state = SBIC_IDLE;
+ sbic_reset(dev);
+
+ for (i = 0; i < 8; i++) {
+ struct sbic_tinfo *ti = &dev->sc_tinfo[i];
+ /*
+ * sc_flags = 0xTTRRSS
+ *
+ * TT = Bitmask to disable Tagged Queues
+ * RR = Bitmask to disable disconnect/reselect
+ * SS = Bitmask to diable Sync negotiation
+ */
+ ti->flags = T_NEED_RESET;
+ if (dev->sc_minsync == 0 || (dev->sc_cfflags & (1<<(i+8))))
+ ti->flags |= T_NOSYNC;
+ if (dev->sc_cfflags & (1<<i) || sbic_nodisc)
+ ti->flags |= T_NODISC;
+ ti->period = dev->sc_minsync;
+ ti->offset = 0;
+ }
+}
+
+void
+sbic_reset(dev)
+ struct sbic_softc *dev;
+{
+ u_int my_id, s;
+ u_char csr, reg;
+
+ SET_SBIC_cmd(dev, SBIC_CMD_ABORT);
+ WAIT_CIP(dev);
+
+ s = splbio();
+
Home |
Main Index |
Thread Index |
Old Index