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