wdsc driver hacked from amiga driver by Steve Woodford
authorderaadt <deraadt@openbsd.org>
Sun, 28 Apr 1996 11:24:33 +0000 (11:24 +0000)
committerderaadt <deraadt@openbsd.org>
Sun, 28 Apr 1996 11:24:33 +0000 (11:24 +0000)
sys/arch/mvme68k/conf/GENERIC
sys/arch/mvme68k/conf/MVME147
sys/arch/mvme68k/conf/MVME162
sys/arch/mvme68k/conf/MVME167
sys/arch/mvme68k/dev/dmavar.h
sys/arch/mvme68k/dev/sbic.c
sys/arch/mvme68k/dev/sbicreg.h
sys/arch/mvme68k/dev/sbicvar.h
sys/arch/mvme68k/dev/wdsc.c [new file with mode: 0644]
sys/arch/mvme68k/dev/wdscreg.h [new file with mode: 0644]

index 306768a..649d126 100644 (file)
@@ -1,4 +1,4 @@
-#      $Id: GENERIC,v 1.4 1995/11/23 13:13:26 deraadt Exp $
+#      $OpenBSD: GENERIC,v 1.5 1996/04/28 11:24:33 deraadt Exp $
 
 machine                mvme68k m68k
 
@@ -59,7 +59,7 @@ nvram0        at pcc0 offset 0x0000
 zs0    at pcc0 offset 0x3000 ipl 4
 zs1    at pcc0 offset 0x3800 ipl 4
 le0    at pcc0 offset 0x1800 ipl 1
-sbic0  at pcc0 offset 0x4000 ipl 2
+wdsc0  at pcc0 offset 0x4000 ipl 2
 lp0    at pcc0 ipl 1
 vme0   at pcc0 offset 0x2000
 
@@ -98,7 +98,7 @@ bugtty0 at mainbus0
 vmes0  at vme0
 vmel0  at vme0
 
-scsibus* at sbic?
+scsibus* at wdsc?
 scsibus* at siop?
 
 sd*    at scsibus? target ? lun ?
index a1d2f86..7a1cc2f 100644 (file)
@@ -1,4 +1,4 @@
-#      $Id: MVME147,v 1.4 1995/11/23 13:13:27 deraadt Exp $
+#      $OpenBSD: MVME147,v 1.5 1996/04/28 11:24:34 deraadt Exp $
 
 machine                mvme68k m68k
 
@@ -53,14 +53,14 @@ nvram0      at pcc0 offset 0x0000
 zs0    at pcc0 offset 0x3000 ipl 4
 zs1    at pcc0 offset 0x3800 ipl 4
 le0    at pcc0 offset 0x1800 ipl 1
-sbic0  at pcc0 offset 0x4000 ipl 2
+wdsc0  at pcc0 offset 0x4000 ipl 2
 lp0    at pcc0 ipl 1
 vme0   at pcc0 offset 0x2000
 
 vmes0  at vme0
 vmel0  at vme0
 
-scsibus* at sbic?
+scsibus* at wdsc?
 
 sd*    at scsibus? target ? lun ?
 st*    at scsibus? target ? lun ?
index a0d92a8..b81919a 100644 (file)
@@ -1,4 +1,4 @@
-#      $Id: MVME162,v 1.4 1995/11/23 13:13:28 deraadt Exp $
+#      $OpenBSD: MVME162,v 1.5 1996/04/28 11:24:38 deraadt Exp $
 
 machine                mvme68k m68k
 
@@ -57,7 +57,7 @@ mainbus0 at root
 #zs0   at pcc0 offset 0x3000 ipl 4
 #zs1   at pcc0 offset 0x3800 ipl 4
 #le0   at pcc0 offset 0x1800 ipl 1
-#sbic0 at pcc0 offset 0x4000 ipl 2
+#wdsc0 at pcc0 offset 0x4000 ipl 2
 ##lp0  at pcc0 ipl 1
 #vme0  at pcc0 offset 0x2000
 
@@ -100,7 +100,7 @@ vmel0       at vme0
 #xdc0  at vmel0 addr 0xff00ee80 ipl 2 vec 0x44
 #xd*   at xdc? target ?
 
-#scsibus* at sbic?
+#scsibus* at wdsc?
 scsibus* at siop?
 
 sd*    at scsibus? target ? lun ?
index 7c2f4b6..fb3ab77 100644 (file)
@@ -1,4 +1,4 @@
-#      $Id: MVME167,v 1.4 1995/11/23 13:13:28 deraadt Exp $
+#      $OpenBSD: MVME167,v 1.5 1996/04/28 11:24:39 deraadt Exp $
 
 machine                mvme68k m68k
 
@@ -57,7 +57,7 @@ mainbus0 at root
 #zs0   at pcc0 offset 0x3000 ipl 4
 #zs1   at pcc0 offset 0x3800 ipl 4
 #le0   at pcc0 offset 0x1800 ipl 1
-#sbic0 at pcc0 offset 0x4000 ipl 2
+#wdsc0 at pcc0 offset 0x4000 ipl 2
 ##lp0  at pcc0 ipl 1
 #vme0  at pcc0 offset 0x2000
 
@@ -99,7 +99,7 @@ vmel0 at vme0
 #xdc0  at vmel0 addr 0xff00ee80 ipl 2 vec 0x44
 #xd*   at xdc? target ?
 
-#scsibus* at sbic?
+#scsibus* at wdsc?
 scsibus* at siop?
 
 sd*    at scsibus? target ? lun ?
index a47d161..b473a90 100644 (file)
@@ -1,9 +1,9 @@
-/*     $Id: dmavar.h,v 1.2 1995/11/07 08:48:54 deraadt Exp $ */
+/*     $OpenBSD: dmavar.h,v 1.3 1996/04/28 11:24:43 deraadt Exp $ */
 
 /*
  * Copyright (c) 1982, 1990 The Regents of the University of California.
  * All rights reserved.
- *   
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *   This product includes software developed by the University of
- *   California, Berkeley and its contributors.
+ *  This product includes software developed by the University of
+ *  California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
- *   
+ *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *   @(#)dmavar.h   7.2 (Berkeley) 11/4/90
- *   $Id: dmavar.h,v 1.2 1995/11/07 08:48:54 deraadt Exp $
+ *  @(#)dmavar.h    7.2 (Berkeley) 11/4/90
  */
 
-/* dmago flags */   
-#define   DMAGO_READ     0x08 /* transfer is a read */
-#define   DMAGO_NOINT    0x80 /* don't interrupt on completion */ 
+/* dmago flags */
+#define DMAGO_READ  0x08    /* transfer is a read */
+#define DMAGO_NOINT 0x80    /* don't interrupt on completion */
 
-#ifdef KERNEL
-typedef void (*dmafree_t) __P((void *dev));
-typedef int  (*dmago_t)   __P((void *dev, char *, int, int));
-typedef int  (*dmanext_t) __P((void *dev));
-typedef void (*dmastop_t) __P((void *dev)); 
+#ifdef _KERNEL
+typedef void (*dmafree_t) (void *dev);
+typedef int  (*dmago_t)   (void *dev, char *, int, int);
+typedef int  (*dmanext_t) (void *dev);
+typedef void (*dmastop_t) (void *dev);
 #endif
-
index 79849f1..d8faa00 100644 (file)
@@ -1,7 +1,8 @@
-/*     $Id: sbic.c,v 1.2 1995/11/07 08:49:24 deraadt Exp $ */
+/*     $OpenBSD: sbic.c,v 1.3 1996/04/28 11:24:44 deraadt Exp $ */
 
 /*
- * Copyright (c) 1994 Christian E. Hopps
+ * Changes Copyright (c) 1996 Steve Woodford
+ * Original Copyright (c) 1994 Christian E. Hopps
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
  *
@@ -18,8 +19,8 @@
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
+ *  This product includes software developed by the University of
+ *  California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)scsi.c      7.5 (Berkeley) 5/4/91
+ *  @(#)scsi.c  7.5 (Berkeley) 5/4/91
  */
 
 /*
- * AMD 33C93 scsi adaptor driver
+ * Steve Woodford (SCW), Apr, 1996
+ * MVME147S WD33C93 Scsi Bus Interface Controller driver,
+ *
+ * Basically a de-loused and tidied up version of the Amiga AMD 33C93 driver.
+ *
+ * The original driver used features which required at least a WD33C93A
+ * chip. The '147 has the original WD33C93 chip (no 'A' suffix).
+ *
+ * This version of the driver is pretty well generic, so should work with
+ * any flavour of WD33C93 chip.
  */
 
 #include <sys/param.h>
 #include <vm/vm.h>
 #include <vm/vm_kern.h>
 #include <vm/vm_page.h>
+#include <vm/pmap.h>
 #include <machine/pmap.h>
-#include <machine/autoconf.h>
 #include <mvme68k/dev/dmavar.h>
 #include <mvme68k/dev/sbicreg.h>
 #include <mvme68k/dev/sbicvar.h>
+#include <machine/autoconf.h>
+#include <mvme68k/dev/pccreg.h>
 
-#include <vm/pmap.h>
 
-/* Since I can't find this in any other header files */
-#define SCSI_PHASE(reg)        (reg&0x07)
+/*
+ * 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.
  */
-#define        SBIC_CMD_WAIT   50000   /* wait per step of 'immediate' cmds */
-#define        SBIC_DATA_WAIT  50000   /* wait per data in/out step */
-#define        SBIC_INIT_WAIT  50000   /* wait per step (both) during init */
+#define SBIC_CMD_WAIT   50000   /* wait per step of 'immediate' cmds */
+#define SBIC_DATA_WAIT  50000   /* wait per data in/out step */
+#define SBIC_INIT_WAIT  50000   /* wait per step (both) during init */
 
-#define        b_cylin         b_resid
+/*
+ * Convenience macro for waiting for a particular sbic event
+ */
 #define SBIC_WAIT(regs, until, timeo) sbicwait(regs, until, timeo, __LINE__)
 
 extern u_int kvtop();
 
-int  sbicicmd __P((struct sbic_softc *, int, int, void *, int, void *, int));
-int  sbicgo __P((struct sbic_softc *, struct scsi_xfer *));
-int  sbicdmaok __P((struct sbic_softc *, struct scsi_xfer *));
-int  sbicwait __P((sbic_regmap_p, char, int , int));
-int  sbiccheckdmap __P((void *, u_long, u_long));
-int  sbicselectbus __P((struct sbic_softc *, sbic_regmap_p, u_char, u_char, u_char));
-int  sbicxfstart __P((sbic_regmap_p, int, u_char, int));
-int  sbicxfout __P((sbic_regmap_p regs, int, void *, int));
-int  sbicfromscsiperiod __P((struct sbic_softc *, sbic_regmap_p, int));
-int  sbictoscsiperiod __P((struct sbic_softc *, sbic_regmap_p, int));
-int  sbicintr __P((struct sbic_softc *));
-int  sbicpoll __P((struct sbic_softc *));
-int  sbicnextstate __P((struct sbic_softc *, u_char, u_char));
-int  sbicmsgin __P((struct sbic_softc *));
-int  sbicxfin __P((sbic_regmap_p regs, int, void *));
-int  sbicabort __P((struct sbic_softc *, sbic_regmap_p, char *));
-void sbicxfdone __P((struct sbic_softc *, sbic_regmap_p, int));
-void sbicerror __P((struct sbic_softc *, sbic_regmap_p, u_char));
-void sbicstart __P((struct sbic_softc *));
-void sbicreset __P((struct sbic_softc *));
-void sbic_scsidone __P((struct sbic_acb *, int));
-void sbic_sched __P((struct sbic_softc *));
-void sbic_save_ptrs __P((struct sbic_softc *, sbic_regmap_p,int,int));
-void sbic_load_ptrs __P((struct sbic_softc *, sbic_regmap_p,int,int));
+int     sbicicmd            __P((struct sbic_softc *, void *, int, void *, int));
+int     sbicgo              __P((struct sbic_softc *, struct scsi_xfer *));
+int     sbicdmaok           __P((struct sbic_softc *, struct scsi_xfer *));
+int     sbicwait            __P((sbic_regmap_p, u_char, int , int));
+int     sbiccheckdmap       __P((void *, u_long, u_long));
+u_char  sbicselectbus       __P((struct sbic_softc *));
+int     sbicxfout           __P((sbic_regmap_p, int, void *));
+int     sbicxfin            __P((sbic_regmap_p, int, void *));
+int     sbicfromscsiperiod  __P((struct sbic_softc *, int));
+int     sbictoscsiperiod    __P((struct sbic_softc *, int));
+int     sbicintr            __P((struct sbic_softc *));
+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_save_ptrs      __P((struct sbic_softc *));
+void    sbic_load_ptrs      __P((struct sbic_softc *));
 
 /*
  * Synch xfer parameters, and timing conversions
  */
-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_data_wait = SBIC_DATA_WAIT;
-int sbic_init_wait = SBIC_INIT_WAIT;
+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_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.
  */
-int sbic_inhibit_sync = 1;
-int sbic_enable_reselect = 1;
-int sbic_clock_override = 0;
-int sbic_no_dma = 0;
-int sbic_parallel_operations = 1;
+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 */
 
+/*
+ * Some useful stuff for debugging purposes
+ */
 #ifdef DEBUG
-sbic_regmap_p debug_sbic_regs;
-int    sbicdma_ops = 0;        /* total DMA operations */
-int    sbicdma_bounces = 0;    /* number operations using bounce buffer */
-int    sbicdma_hits = 0;       /* number of DMA chains that were contiguous */
-int    sbicdma_misses = 0;     /* number of DMA chains that were not contiguous */
-int     sbicdma_saves = 0;
+int     sbicdma_ops     = 0;    /* total DMA operations */
+int     sbicdma_hits    = 0;    /* number of DMA chains that were contiguous */
+int     sbicdma_misses  = 0;    /* number of DMA chains that were not contiguous */
+int     sbicdma_saves   = 0;
+
 #define QPRINTF(a) if (sbic_debug > 1) printf a
-int    sbic_debug = 0;
-int    sync_debug = 0;
-int    sbic_dma_debug = 0;
-int    reselect_debug = 0;
-int    report_sense = 0;
-int    data_pointer_debug = 0;
-int    sbic_timeout = 0;
-u_char debug_asr, debug_csr, timeout_active=0, routine;
-void sbictimeout __P((struct sbic_softc *dev));
+
+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     report_sense    = 0;    /* Always print Sense information */
+int     data_pointer_debug = 0; /* Debug Data Pointer related things */
+
+void    sbictimeout __P((struct sbic_softc *dev));
+
 #else
-#define QPRINTF
+#define QPRINTF(a)  /* */
 #endif
 
+
 /*
  * default minphys routine for sbic based controllers
  */
 void
 sbic_minphys(bp)
-       struct buf *bp;
+    struct buf *bp;
 {
-
-       /*
-        * No max transfer at this level.
-        */
-       minphys(bp);
+    /*
+     * No max transfer at this level.
+     */
+    minphys(bp);
 }
 
+
 /*
  * Save DMA pointers.  Take into account partial transfer. Shut down DMA.
  */
 void
-sbic_save_ptrs(dev, regs, target, lun)
-       struct sbic_softc *dev;
-       sbic_regmap_p regs;
-       int target, lun;
+sbic_save_ptrs(dev)
+    struct sbic_softc   *dev;
 {
-       int count, asr, csr, s;
-       unsigned long ptr;
-       char *vptr;
-       struct sbic_acb* acb;
-
-       extern vm_offset_t vm_first_phys;
-
-       if( !dev->sc_cur ) return;
-       if( !(dev->sc_flags & SBICF_INDMA) ) return; /* DMA not active */
-
-       s = splbio();
-
-       acb = dev->sc_nexus;
-       count = -1;
-       do {
-               GET_SBIC_asr(regs, asr);
-               if( asr & SBIC_ASR_DBR ) {
-                       printf("sbic_save_ptrs: asr %02x canceled!\n", asr);
-                       splx(s);
-                       return;
-               }
-       } while( asr & (SBIC_ASR_BSY|SBIC_ASR_CIP) );
-
-       /* Save important state */
-       /* must be done before dmastop */
-       acb->sc_dmacmd = dev->sc_dmacmd;
-       SBIC_TC_GET(regs, count);
-
-       /* Shut down DMA ====CAREFUL==== */
-       dev->sc_dmastop(dev);
-       dev->sc_flags &= ~SBICF_INDMA;
-       SBIC_TC_PUT(regs, 0);
+    sbic_regmap_p       regs;
+    struct sbic_acb*    acb;
+    int                 count,
+                        asr,
+                        s;
+
+    /*
+     * Only need to save pointers if DMA was active...
+     */
+    if ( dev->sc_cur == NULL || (dev->sc_flags & SBICF_INDMA) == 0 )
+        return;
+
+    regs = dev->sc_sbicp;
+
+    s = splbio();
+
+    /*
+     * Wait until WD chip is idle
+     */
+    do {
+        GET_SBIC_asr(regs, asr);
+        if( asr & SBIC_ASR_DBR ) {
+            printf("sbic_save_ptrs: asr %02x canceled!\n", asr);
+            splx(s);
+            return;
+        }
+    } while( asr & (SBIC_ASR_BSY|SBIC_ASR_CIP) );
+
+
+    /*
+     * Save important state.
+     * must be done before dmastop
+     */
+    acb            = dev->sc_nexus;
+    acb->sc_dmacmd = dev->sc_dmacmd;
+
+    /*
+     * Fetch the residual count
+     */
+    SBIC_TC_GET(regs, count);
+
+    /*
+     * Shut down DMA
+     */
+    dev->sc_dmastop(dev);
+
+    /*
+     * No longer in DMA
+     */
+    dev->sc_flags &= ~SBICF_INDMA;
+
+    /*
+     * Ensure the WD chip is back in polled I/O mode, with nothing to
+     * transfer.
+     */
+    SBIC_TC_PUT(regs, 0);
+    SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
+
+    /*
+     * Update current count...
+     */
+    acb->sc_tcnt = count;
+
+    /*
+     * Work out how many bytes were actually transferred
+     */
+    count        = dev->sc_tcnt - count;
+    dev->sc_tcnt = acb->sc_tcnt;
+
+    /*
+     * Fixup partial xfers
+     */
+    acb->sc_kv.dc_addr  += count;
+    acb->sc_kv.dc_count -= count;
+    acb->sc_pa.dc_addr  += count;
+    acb->sc_pa.dc_count -= count >> 1;
 
 #ifdef DEBUG
-       if(!count && sbic_debug) printf("%dcount0",target);
-       if(data_pointer_debug == -1)
-               printf("SBIC saving target %d data pointers from (%x,%x)%xASR:%02x",
-                      target, dev->sc_cur->dc_addr, dev->sc_cur->dc_count,
-                      acb->sc_dmacmd, asr);
+    if ( data_pointer_debug )
+        printf("save at (%x,%x):%x\n",
+               dev->sc_cur->dc_addr, dev->sc_cur->dc_count,count);
+    sbicdma_saves++;
 #endif
 
-       /* Fixup partial xfers */
-       acb->sc_kv.dc_addr += (dev->sc_tcnt - count);
-       acb->sc_kv.dc_count -= (dev->sc_tcnt - count);
-       acb->sc_pa.dc_addr += (dev->sc_tcnt - count);
-       acb->sc_pa.dc_count -= ((dev->sc_tcnt - count)>>1);
-
-       acb->sc_tcnt = dev->sc_tcnt = count;
-#ifdef DEBUG
-       if(data_pointer_debug)
-               printf(" at (%x,%x):%x\n",
-                      dev->sc_cur->dc_addr, dev->sc_cur->dc_count,count);
-       sbicdma_saves++;
-#endif
-       splx(s);
+    splx(s);
 }
 
 
 /*
  * DOES NOT RESTART DMA!!!
  */
-void sbic_load_ptrs(dev, regs, target, lun)
-       struct sbic_softc *dev;
-       sbic_regmap_p regs;
-       int target, lun;
+void
+sbic_load_ptrs(dev)
+    struct sbic_softc   *dev;
 {
-       int i, s, asr, count;
-       char* vaddr, * paddr;
-       struct sbic_acb *acb;
+    struct sbic_acb *acb = dev->sc_nexus;
+    int             s;
 
-       acb = dev->sc_nexus;
-       if( !acb->sc_kv.dc_count )
-               /* No data to xfer */
-               return;
+    if ( acb->sc_kv.dc_count == 0 ) {
+        /*
+         * No data to xfer
+         */
+        return;
+    }
 
-       s = splbio();
+    s = splbio();
 
-       dev->sc_last = dev->sc_cur = &acb->sc_pa;
-       dev->sc_tcnt = acb->sc_tcnt;
-       dev->sc_dmacmd = acb->sc_dmacmd;
+    /*
+     * Reset the Scatter-Gather chain
+     */
+    dev->sc_last = dev->sc_cur = &acb->sc_pa;
 
-#ifdef DEBUG
-       sbicdma_ops++;
-#endif
-       if( !dev->sc_tcnt ) {
-               /* sc_tcnt == 0 implies end of segment */
-
-               /* do kvm to pa mappings */
-               paddr = acb->sc_pa.dc_addr =
-                       (char *) kvtop(acb->sc_kv.dc_addr);
-
-               vaddr = acb->sc_kv.dc_addr;
-               count = acb->sc_kv.dc_count;
-               for(count = (NBPG - ((int)vaddr & PGOFSET));
-                   count < acb->sc_kv.dc_count
-                   && (char*)kvtop(vaddr + count + 4) == paddr + count + 4;
-                   count += NBPG);
-               /* If it's all contiguous... */
-               if(count > acb->sc_kv.dc_count ) {
-                       count = acb->sc_kv.dc_count;
-#ifdef DEBUG
-                       sbicdma_hits++;
-#endif
-               } else {
-#ifdef DEBUG
-                       sbicdma_misses++;
-#endif
-               }
-               acb->sc_tcnt = count;
-               acb->sc_pa.dc_count = count >> 1;
+    /*
+     * Restore the Transfer Count and DMA specific data
+     */
+    dev->sc_tcnt   = acb->sc_tcnt;
+    dev->sc_dmacmd = acb->sc_dmacmd;
 
 #ifdef DEBUG
-               if(data_pointer_debug)
-                       printf("DMA recalc:kv(%x,%x)pa(%x,%x)\n",
-                              acb->sc_kv.dc_addr,
-                              acb->sc_kv.dc_count,
-                              acb->sc_pa.dc_addr,
-                              acb->sc_tcnt);
-#endif
-       }
-       splx(s);
+    sbicdma_ops++;
+#endif
+
+    /*
+     * Need to fixup new segment?
+     */
+    if ( dev->sc_tcnt == 0 ) {
+        /*
+         * sc_tcnt == 0 implies end of segment
+         */
+        char    *vaddr, *paddr;
+        int     count;
+
+        /*
+         * do kvm to pa mappings
+         */
+        vaddr = acb->sc_kv.dc_addr;
+        paddr = acb->sc_pa.dc_addr = (char *) kvtop(vaddr);
+
+        for (count = (NBPG - ((int)vaddr & PGOFSET));
+             count < acb->sc_kv.dc_count &&
+                     (char*)kvtop(vaddr + count + 4) == paddr + count + 4;
+             count += NBPG)
+            ;   /* Do nothing */
+
+        /*
+         * If it's all contiguous...
+         */
+        if ( count > acb->sc_kv.dc_count ) {
+            count = acb->sc_kv.dc_count;
+#ifdef  DEBUG
+            sbicdma_hits++;
+#endif
+        }
+#ifdef  DEBUG
+        else
+            sbicdma_misses++;
+#endif
+
+        acb->sc_tcnt        = count;
+        acb->sc_pa.dc_count = count >> 1;
+
 #ifdef DEBUG
-       if(data_pointer_debug)
-               printf("SBIC restoring target %d data pointers at (%x,%x)%x\n",
-                      target, dev->sc_cur->dc_addr, dev->sc_cur->dc_count,
-                      dev->sc_dmacmd);
+        if ( data_pointer_debug )
+            printf("DMA recalc:kv(%x,%x)pa(%x,%x)\n", acb->sc_kv.dc_addr,
+                                                      acb->sc_kv.dc_count,
+                                                      acb->sc_pa.dc_addr,
+                                                      acb->sc_tcnt);
 #endif
+
+    }
+
+    splx(s);
 }
 
 /*
@@ -306,99 +363,107 @@ void sbic_load_ptrs(dev, regs, target, lun)
  */
 int
 sbic_scsicmd(xs)
-       struct scsi_xfer *xs;
+    struct scsi_xfer *xs;
 {
-       struct sbic_acb *acb;
-       struct sbic_softc *dev;
-       struct scsi_link *slp;
-       int flags, s, stat;
+    struct scsi_link    *slp = xs->sc_link;
+    struct sbic_softc   *dev = slp->adapter_softc;
+    struct sbic_acb     *acb;
+    int                 flags = xs->flags,
+                        s;
+
+    if ( flags & SCSI_DATA_UIO )
+        panic("sbic: scsi data uio requested");
 
-       slp = xs->sc_link;
-       dev = slp->adapter_softc;
-       flags = xs->flags;
+    if ( dev->sc_nexus && (flags & SCSI_POLL) )
+        panic("sbic_scsicmd: busy");
 
-       if (flags & SCSI_DATA_UIO)
-               panic("sbic: scsi data uio requested");
+    if ( slp->target == slp->adapter_target )
+        return ESCAPE_NOT_SUPPORTED;
 
-       if (dev->sc_nexus && flags & SCSI_POLL)
-               panic("sbic_scsicmd: busy");
+    s = splbio();
 
-       if (slp->target == slp->adapter_target)
-               return ESCAPE_NOT_SUPPORTED;
+    if ( (acb = dev->free_list.tqh_first) != NULL )
+        TAILQ_REMOVE(&dev->free_list, acb, chain);
 
-       s = splbio();
-       acb = dev->free_list.tqh_first;
-       if (acb)
-               TAILQ_REMOVE(&dev->free_list, acb, chain);
-       splx(s);
+    splx(s);
 
-       if (acb == NULL) {
+    if ( acb == NULL ) {
 #ifdef DEBUG
-               printf("sbic_scsicmd: unable to queue request for target %d\n",
-                   slp->target);
+        printf("sbic_scsicmd: unable to queue request for target %d\n",
+            slp->target);
 #ifdef DDB
-               Debugger();
+        Debugger();
 #endif
 #endif
-               xs->error = XS_DRIVER_STUFFUP;
-               return(TRY_AGAIN_LATER);
-       }
-
-       acb->flags = ACB_ACTIVE;
-       if (flags & SCSI_DATA_IN)
-               acb->flags |= ACB_DATAIN;
-       acb->xs = xs;
-       bcopy(xs->cmd, &acb->cmd, xs->cmdlen);
-       acb->clen = xs->cmdlen;
-       acb->sc_kv.dc_addr = xs->data;
-       acb->sc_kv.dc_count = xs->datalen;
-       acb->pa_addr = xs->data ? (char *)kvtop(xs->data) : 0;  /* XXXX check */
-
-       if (flags & SCSI_POLL) {
-               s = splbio();
-               /*
-                * This has major side effects -- it locks up the machine
-                */
-
-               dev->sc_flags |= SBICF_ICMD;
-               do {
-                       while(dev->sc_nexus)
-                               sbicpoll(dev);
-                       dev->sc_nexus = acb;
-                       dev->sc_stat[0] = -1;
-                       dev->sc_xs = xs;
-                       dev->target = slp->target;
-                       dev->lun = slp->lun;
-                       stat = sbicicmd(dev, slp->target, slp->lun,
-                                       &acb->cmd, acb->clen,
-                                       acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
-               } while (dev->sc_nexus != acb);
-               sbic_scsidone(acb, stat);
-
-               splx(s);
-               return(COMPLETE);
-       }
-
-       s = splbio();
-       TAILQ_INSERT_TAIL(&dev->ready_list, acb, chain);
-
-       if (dev->sc_nexus) {
-               splx(s);
-               return(SUCCESSFULLY_QUEUED);
-       }
-
-       /*
-        * nothing is active, try to start it now.
-        */
-       sbic_sched(dev);
-       splx(s);
-
-/* TODO:  add sbic_poll to do SCSI_POLL operations */
-#if 0
-       if (flags & SCSI_POLL)
-               return(COMPLETE);
-#endif
-       return(SUCCESSFULLY_QUEUED);
+        xs->error = XS_DRIVER_STUFFUP;
+
+        return(TRY_AGAIN_LATER);
+    }
+
+    if ( flags & SCSI_DATA_IN )
+        acb->flags = ACB_ACTIVE | ACB_DATAIN;
+    else
+        acb->flags = ACB_ACTIVE;
+
+    acb->xs             = xs;
+    acb->clen           = xs->cmdlen;
+    acb->sc_kv.dc_addr  = xs->data;
+    acb->sc_kv.dc_count = xs->datalen;
+    acb->pa_addr        = xs->data ? (char *)kvtop(xs->data) : 0;
+    bcopy(xs->cmd, &acb->cmd, xs->cmdlen);
+
+    if ( flags & SCSI_POLL ) {
+        /*
+         * This has major side effects -- it locks up the machine
+         */
+        int stat;
+
+        s = splbio();
+
+        dev->sc_flags |= SBICF_ICMD;
+
+        do {
+            /*
+             * If we already had a nexus, while away the time until idle...
+             * This is likely only to happen if a reselection occurs between
+             * here and our earlier check for ICMD && sc_nexus (which would
+             * have resulted in a panic() had it been true).
+             */
+            while ( dev->sc_nexus )
+                sbicpoll(dev);
+
+            /*
+             * Fix up the new nexus
+             */
+            dev->sc_nexus   = acb;
+            dev->sc_xs      = xs;
+            dev->target     = slp->target;
+            dev->lun        = slp->lun;
+
+            stat = sbicicmd(dev, &acb->cmd, acb->clen,
+                            acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
+
+        } while ( dev->sc_nexus != acb );
+
+        sbic_scsidone(acb, stat);
+
+        splx(s);
+
+        return(COMPLETE);
+    }
+
+    s = splbio();
+    TAILQ_INSERT_TAIL(&dev->ready_list, acb, chain);
+
+    /*
+     * If nothing is active, try to start it now.
+     */
+    if ( dev->sc_nexus == NULL )
+        sbic_sched(dev);
+
+    splx(s);
+
+    return(SUCCESSFULLY_QUEUED);
 }
 
 /*
@@ -406,846 +471,827 @@ sbic_scsicmd(xs)
  */
 void
 sbic_sched(dev)
-       struct sbic_softc *dev;
+    struct sbic_softc *dev;
 {
-       struct scsi_xfer *xs;
-       struct scsi_link *slp;
-       struct sbic_acb *acb;
-       int flags, /*phase,*/ stat, i;
-
-       if (dev->sc_nexus)
-               return;                 /* a command is current active */
-
-       for (acb = dev->ready_list.tqh_first; acb; acb = acb->chain.tqe_next) {
-               slp = acb->xs->sc_link;
-               i = slp->target;
-               if (!(dev->sc_tinfo[i].lubusy & (1 << slp->lun))) {
-                       struct sbic_tinfo *ti = &dev->sc_tinfo[i];
-
-                       TAILQ_REMOVE(&dev->ready_list, acb, chain);
-                       dev->sc_nexus = acb;
-                       slp = acb->xs->sc_link;
-                       ti = &dev->sc_tinfo[slp->target];
-                       ti->lubusy |= (1 << slp->lun);
-                       acb->sc_pa.dc_addr = acb->pa_addr;      /* XXXX check */
-                       break;
-               }
-       }
-
-       if (acb == NULL)
-               return;                 /* did not find an available command */
-
-       dev->sc_xs = xs = acb->xs;
-       slp = xs->sc_link;
-       flags = xs->flags;
-
-       if (flags & SCSI_RESET)
-               sbicreset(dev);
+    struct scsi_xfer    *xs;
+    struct scsi_link    *slp = NULL;    /* Gag the compiler */
+    struct sbic_acb     *acb;
+    int                 flags,
+                        stat;
+
+    /*
+     * XXXSCW
+     * I'll keep this test here, even though I can't see any obvious way
+     * in which sbic_sched() could be called with sc_nexus non NULL
+     */
+    if ( dev->sc_nexus )
+        return;         /* a command is current active */
+
+    /*
+     * Loop through the ready list looking for work to do...
+     */
+    for (acb = dev->ready_list.tqh_first; acb; acb = acb->chain.tqe_next) {
+        int     i, j;
+
+        slp = acb->xs->sc_link;
+        i   = slp->target;
+        j   = 1 << slp->lun;
+
+        /*
+         * We've found a potential command, but is the target/lun busy?
+         */
+        if ( (dev->sc_tinfo[i].lubusy & j) == 0 ) {
+            /*
+             * Nope, it's not busy, so we can use it.
+             */
+            dev->sc_tinfo[i].lubusy |= j;
+            TAILQ_REMOVE(&dev->ready_list, acb, chain);
+            dev->sc_nexus = acb;
+            acb->sc_pa.dc_addr = acb->pa_addr;  /* XXXX check */
+            break;
+        }
+    }
+
+    if ( acb == NULL ) {
+        QPRINTF(("sbicsched: no work\n"));
+        return;         /* did not find an available command */
+    }
 
 #ifdef DEBUG
-       if( data_pointer_debug > 1 )
-               printf("sbic_sched(%d,%d)\n",slp->target,slp->lun);
+    if ( data_pointer_debug > 1 )
+        printf("sbic_sched(%d,%d)\n", slp->target, slp->lun);
 #endif
-       dev->sc_stat[0] = -1;
-       dev->target = slp->target;
-       dev->lun = slp->lun;
-       if ( flags & SCSI_POLL || ( !sbic_parallel_operations
-                                  && (/*phase == STATUS_PHASE ||*/
-                                      sbicdmaok(dev, xs) == 0) ) )
-               stat = sbicicmd(dev, slp->target, slp->lun, &acb->cmd,
-                   acb->clen, acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
-       else if (sbicgo(dev, xs) == 0)
-               return;
-       else
-               stat = dev->sc_stat[0];
-
-       sbic_scsidone(acb, stat);
+
+    dev->sc_xs = xs = acb->xs;
+    flags      = xs->flags;
+
+    if ( flags & SCSI_RESET )
+        sbicreset(dev);
+
+    dev->sc_stat[0] = -1;
+    dev->target     = slp->target;
+    dev->lun        = slp->lun;
+
+    if ( flags & SCSI_POLL || (!sbic_parallel_operations &&
+                              (sbicdmaok(dev, xs) == 0)) )
+        stat = sbicicmd(dev, &acb->cmd, acb->clen,
+                        acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
+    else
+    if ( sbicgo(dev, xs) == 0 )
+        return;
+    else
+        stat = dev->sc_stat[0];
+
+    sbic_scsidone(acb, stat);
 }
 
 void
 sbic_scsidone(acb, stat)
-       struct sbic_acb *acb;
-       int stat;
+    struct sbic_acb *acb;
+    int             stat;
 {
-       struct scsi_xfer *xs;
-       struct scsi_link *slp;
-       struct sbic_softc *dev;
-       int s, dosched = 0;
-
-       xs = acb->xs;
-       slp = xs->sc_link;
-       dev = slp->adapter_softc;
+    struct scsi_xfer    *xs  = acb->xs;
+    struct scsi_link    *slp = xs->sc_link;
+    struct sbic_softc   *dev = slp->adapter_softc;
+    int                 dosched = 0;
+
 #ifdef DIAGNOSTIC
-       if (acb == NULL || xs == NULL) {
-               printf("sbic_scsidone -- (%d,%d) no scsi_xfer\n",
-                      dev->target, dev->lun);
+    if ( acb == NULL || xs == NULL ) {
+        printf("sbic_scsidone -- (%d,%d) no scsi_xfer\n", dev->target, dev->lun);
 #ifdef DDB
-               Debugger();
-#endif
-               return;
-       }
+        Debugger();
 #endif
-#if 1
-       if (((struct device *)(slp->device_softc))->dv_unit < dk_ndrive)
-               ++dk_xfer[((struct device *)(slp->device_softc))->dv_unit];
+        return;
+    }
 #endif
-       /*
-        * is this right?
-        */
-       xs->status = stat;
+
+    if ( slp->device_softc &&
+        ((struct device *)(slp->device_softc))->dv_unit < dk_ndrive)
+        ++dk_xfer[((struct device *)(slp->device_softc))->dv_unit];
+
+    /*
+     * is this right?
+     */
+    xs->status = stat;
 
 #ifdef DEBUG
-       if( data_pointer_debug > 1 )
-               printf("scsidone: (%d,%d)->(%d,%d)%02x\n",
-                      slp->target, slp->lun,
-                      dev->target,  dev->lun,  stat);
-       if( xs->sc_link->target == dev->sc_link.adapter_target )
-               panic("target == hostid");
+    if ( data_pointer_debug > 1 )
+        printf("scsidone: (%d,%d)->(%d,%d)%02x\n", slp->target, slp->lun,
+                                                   dev->target, dev->lun, stat);
+
+    if ( xs->sc_link->target == dev->sc_link.adapter_target )
+        panic("target == hostid");
 #endif
 
-       if (xs->error == XS_NOERROR && !(acb->flags & ACB_CHKSENSE)) {
-               if (stat == SCSI_CHECK) {
-                       /* Schedule a REQUEST SENSE */
-                       struct scsi_sense *ss = (void *)&acb->cmd;
+    if ( xs->error == XS_NOERROR && (acb->flags & ACB_CHKSENSE) == 0 ) {
+
+        if ( stat == SCSI_CHECK ) {
+            /*
+             * Schedule a REQUEST SENSE
+             */
+            struct scsi_sense *ss = (void *)&acb->cmd;
+
 #ifdef DEBUG
-                       if (report_sense)
-                               printf("sbic_scsidone: autosense %02x targ %d lun %d",
-                                   acb->cmd.opcode, slp->target, slp->lun);
+            if ( report_sense )
+                printf("sbic_scsidone: autosense %02x targ %d lun %d",
+                        acb->cmd.opcode, slp->target, slp->lun);
 #endif
-                       bzero(ss, sizeof(*ss));
-                       ss->opcode = REQUEST_SENSE;
-                       ss->byte2 = slp->lun << 5;
-                       ss->length = sizeof(struct scsi_sense_data);
-                       acb->clen = sizeof(*ss);
-                       acb->sc_kv.dc_addr = (char *)&xs->sense;
-                       acb->sc_kv.dc_count = sizeof(struct scsi_sense_data);
-                       acb->pa_addr = (char *)kvtop(&xs->sense); /* XXX check */
-                       acb->flags = ACB_ACTIVE | ACB_CHKSENSE | ACB_DATAIN;
-                       TAILQ_INSERT_HEAD(&dev->ready_list, acb, chain);
-                       dev->sc_tinfo[slp->target].lubusy &=
-                           ~(1 << slp->lun);
-                       dev->sc_tinfo[slp->target].senses++;
-                       if (dev->sc_nexus == acb) {
-                               dev->sc_nexus = NULL;
-                               sbic_sched(dev);
-                       }
-                       return;
-               }
-       }
-       if (xs->error == XS_NOERROR && (acb->flags & ACB_CHKSENSE)) {
-               xs->error = XS_SENSE;
+
+            bzero(ss, sizeof(*ss));
+
+            ss->opcode          = REQUEST_SENSE;
+            ss->byte2           = slp->lun << 5;
+            ss->length          = sizeof(struct scsi_sense_data);
+
+            acb->clen           = sizeof(*ss);
+            acb->sc_kv.dc_addr  = (char *)&xs->sense;
+            acb->sc_kv.dc_count = sizeof(struct scsi_sense_data);
+            acb->pa_addr        = (char *)kvtop(&xs->sense); /* XXX check */
+            acb->flags          = ACB_ACTIVE | ACB_CHKSENSE | ACB_DATAIN;
+
+            TAILQ_INSERT_HEAD(&dev->ready_list, acb, chain);
+
+            dev->sc_tinfo[slp->target].lubusy &= ~(1 << slp->lun);
+            dev->sc_tinfo[slp->target].senses++;
+
+            if ( dev->sc_nexus == acb ) {
+                dev->sc_nexus = NULL;
+                dev->sc_xs = NULL;
+                sbic_sched(dev);
+            }
+            return;
+        }
+    }
+
+    if ( xs->error == XS_NOERROR && (acb->flags & ACB_CHKSENSE) != 0 ) {
+
+        xs->error = XS_SENSE;
+
 #ifdef DEBUG
-               if (report_sense)
-                       printf(" => %02x %02x\n", xs->sense.extended_flags,
-                           xs->sense.extended_extra_bytes[3]);
-#endif
-       } else {
-               xs->resid = 0;          /* XXXX */
-       }
-#if whataboutthisone
-               case SCSI_BUSY:
-                       xs->error = XS_BUSY;
-                       break;
+        if (report_sense)
+            printf(" => %02x %02x\n", xs->sense.flags, 
+                       xs->sense.extra_bytes[3]);
 #endif
-       xs->flags |= ITSDONE;
-
-       /*
-        * Remove the ACB from whatever queue it's on.  We have to do a bit of
-        * a hack to figure out which queue it's on.  Note that it is *not*
-        * necessary to cdr down the ready queue, but we must cdr down the
-        * nexus queue and see if it's there, so we can mark the unit as no
-        * longer busy.  This code is sickening, but it works.
-        */
-       if (acb == dev->sc_nexus) {
-               dev->sc_nexus = NULL;
-               dev->sc_tinfo[slp->target].lubusy &= ~(1<<slp->lun);
-               if (dev->ready_list.tqh_first)
-                       dosched = 1;    /* start next command */
-       } else if (dev->ready_list.tqh_last == &acb->chain.tqe_next) {
-               TAILQ_REMOVE(&dev->ready_list, acb, chain);
-       } else {
-               register struct sbic_acb *acb2;
-               for (acb2 = dev->nexus_list.tqh_first; acb2;
-                   acb2 = acb2->chain.tqe_next)
-                       if (acb2 == acb) {
-                               TAILQ_REMOVE(&dev->nexus_list, acb, chain);
-                               dev->sc_tinfo[slp->target].lubusy
-                                       &= ~(1<<slp->lun);
-                               break;
-                       }
-               if (acb2)
-                       ;
-               else if (acb->chain.tqe_next) {
-                       TAILQ_REMOVE(&dev->ready_list, acb, chain);
-               } else {
-                       printf("%s: can't find matching acb\n",
-                           dev->sc_dev.dv_xname);
+
+    } else {
+        xs->resid = 0;      /* XXXX */
+    }
+
+    xs->flags |= ITSDONE;
+
+    /*
+     * Remove the ACB from whatever queue it's on.  We have to do a bit of
+     * a hack to figure out which queue it's on.  Note that it is *not*
+     * necessary to cdr down the ready queue, but we must cdr down the
+     * nexus queue and see if it's there, so we can mark the unit as no
+     * longer busy.  This code is sickening, but it works.
+     */
+    if ( acb == dev->sc_nexus ) {
+
+        dev->sc_nexus = NULL;
+        dev->sc_xs    = NULL;
+
+        dev->sc_tinfo[slp->target].lubusy &= ~(1 << slp->lun);
+
+        if ( dev->ready_list.tqh_first )
+            dosched = 1;    /* start next command */
+
+    } else
+    if ( dev->ready_list.tqh_last == &acb->chain.tqe_next ) {
+
+        TAILQ_REMOVE(&dev->ready_list, acb, chain);
+
+    } else {
+
+        register struct sbic_acb *a;
+
+        for (a = dev->nexus_list.tqh_first; a; a = a->chain.tqe_next) {
+            if ( a == acb ) {
+                TAILQ_REMOVE(&dev->nexus_list, acb, chain);
+                dev->sc_tinfo[slp->target].lubusy &= ~(1 << slp->lun);
+                break;
+            }
+        }
+
+        if ( a )
+            ;
+        else if ( acb->chain.tqe_next ) {
+            TAILQ_REMOVE(&dev->ready_list, acb, chain);
+        } else {
+            printf("%s: can't find matching acb\n", dev->sc_dev.dv_xname);
 #ifdef DDB
-                       Debugger();
+            Debugger();
 #endif
-               }
-       }
-       /* Put it on the free list. */
-       acb->flags = ACB_FREE;
-       TAILQ_INSERT_HEAD(&dev->free_list, acb, chain);
+        }
+    }
+
+    /*
+     * Put it on the free list.
+     */
+    acb->flags = ACB_FREE;
+    TAILQ_INSERT_HEAD(&dev->free_list, acb, chain);
 
-       dev->sc_tinfo[slp->target].cmds++;
+    dev->sc_tinfo[slp->target].cmds++;
 
-       scsi_done(xs);
+    scsi_done(xs);
 
-       if (dosched)
-               sbic_sched(dev);
+    if ( dosched )
+        sbic_sched(dev);
 }
 
 int
 sbicdmaok(dev, xs)
-       struct sbic_softc *dev;
-       struct scsi_xfer *xs;
+    struct sbic_softc   *dev;
+    struct scsi_xfer    *xs;
 {
-       if (sbic_no_dma || xs->datalen & 0x1 || (u_int)xs->data & 0x3)
-               return(0);
-       /*
-        * controller supports dma to any addresses?
-        */
-       else if ((dev->sc_flags & SBICF_BADDMA) == 0)
-               return(1);
-       /*
-        * this address is ok for dma?
-        */
-       else if (sbiccheckdmap(xs->data, xs->datalen, dev->sc_dmamask) == 0)
-               return(1);
-#if 0
-       /*
-        * we have a bounce buffer?
-        */
-       else if (dev->sc_tinfo[xs->sc_link->target].bounce)
-               return(1);
-       /*
-        * try to get one
-        */
-       else if (dev->sc_tinfo[xs->sc_link->target].bounce
-                = (char *)alloc_z2mem(MAXPHYS)) {
-               if (isztwomem(dev->sc_tinfo[xs->sc_link->target].bounce))
-                       printf("alloc ZII target %d bounce pa 0x%x\n",
-                              xs->sc_link->target,
-                              kvtop(dev->sc_tinfo[xs->sc_link->target].bounce));
-               else if (dev->sc_tinfo[xs->sc_link->target].bounce)
-                       printf("alloc CHIP target %d bounce pa 0x%x\n",
-                              xs->sc_link->target,
-                              PREP_DMA_MEM(dev->sc_tinfo[xs->sc_link->target].bounce));
-               return(1);
-       }
-#endif
-
-       return(0);
+    if ( sbic_no_dma || xs->datalen & 0x03 || (int)xs->data & 0x03)
+        return(0);
+
+    /*
+     * controller supports dma to any addresses?
+     */
+    if ( (dev->sc_flags & SBICF_BADDMA) == 0 )
+        return(1);
+
+    /*
+     * this address is ok for dma?
+     */
+    if ( sbiccheckdmap(xs->data, xs->datalen, dev->sc_dmamask) == 0 )
+        return(1);
+
+    return(0);
 }
 
-
 int
 sbicwait(regs, until, timeo, line)
-       sbic_regmap_p regs;
-       char until;
-       int timeo;
-       int line;
-{
-       u_char val;
-       int csr;
-
-       if (timeo == 0)
-               timeo = 10000;  /* some large value.. */
-
-       GET_SBIC_asr(regs,val);
-       while ((val & until) == 0) {
-               if (timeo-- == 0) {
-                       GET_SBIC_csr(regs, csr);
-                       printf("sbicwait TIMEO @%d with asr=x%x csr=x%x\n",
-                           line, val, csr);
-#if defined(DDB) && defined(DEBUG)
-                       Debugger();
-#endif
-                       return(val); /* Maybe I should abort */
-                       break;
-               }
-               DELAY(1);
-               GET_SBIC_asr(regs,val);
-       }
-       return(val);
-}
-
-int
-sbicabort(dev, regs, where)
-       struct sbic_softc *dev;
-       sbic_regmap_p regs;
-       char *where;
+    sbic_regmap_p   regs;
+    u_char          until;
+    int             timeo;
+    int             line;
 {
-       u_char csr, asr;
+    u_char  val;
 
-       GET_SBIC_csr(regs, csr);
-       GET_SBIC_asr(regs, asr);
+    if ( timeo == 0 )
+        timeo = 1000000;    /* some large value.. */
 
-       printf ("%s: abort %s: csr = 0x%02x, asr = 0x%02x\n",
-           dev->sc_dev.dv_xname, where, csr, asr);
+    GET_SBIC_asr(regs, val);
 
+    while ( (val & until) == 0 ) {
 
-#if 0
-       /* Clean up running command */
-       if (dev->sc_nexus != NULL) {
-               dev->sc_nexus->xs->error = XS_DRIVER_STUFFUP;
-               sbic_scsidone(dev->sc_nexus, dev->sc_stat[0]);
-       }
-       while (acb = dev->nexus_list.tqh_first) {
-               acb->xs->error = XS_DRIVER_STUFFUP;
-               sbic_scsidone(acb, -1 /*acb->stat[0]*/);
-       }
+        if ( timeo-- == 0 ) {
+            int csr;
+            GET_SBIC_csr(regs, csr);
+            printf("sbicwait TIMEO @%d with asr=x%x csr=x%x\n", line, val, csr);
+#if defined(DDB) && defined(DEBUG)
+            Debugger();
 #endif
+            return(val); /* Maybe I should abort */
+            break;
+        }
+
+        DELAY(1);
+        GET_SBIC_asr(regs, val);
+    }
+
+    return(val);
+}
 
-       /* Clean up chip itself */
-       if (dev->sc_flags & SBICF_SELECTED) {
-               while( asr & SBIC_ASR_DBR ) {
-                       /* sbic is jammed w/data. need to clear it */
-                       /* But we don't know what direction it needs to go */
-                       GET_SBIC_data(regs, asr);
-                       printf("%s: abort %s: clearing data buffer 0x%02x\n",
-                              dev->sc_dev.dv_xname, where, asr);
-                       GET_SBIC_asr(regs, asr);
-                       if( asr & SBIC_ASR_DBR ) /* Not the read direction, then */
-                               SET_SBIC_data(regs, asr);
-                       GET_SBIC_asr(regs, asr);
-               }
-               WAIT_CIP(regs);
-               SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
-               WAIT_CIP(regs);
-
-               GET_SBIC_asr(regs, asr);
-               if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI)) {
-                       /* ok, get more drastic.. */
-
-                       sbicreset(dev);
-                       dev->sc_flags &= ~SBICF_SELECTED;
-                       return -1;
-               }
-               SET_SBIC_cmd(regs, SBIC_CMD_DISC);
-
-               do {
-                       SBIC_WAIT (regs, SBIC_ASR_INT, 0);
-                       GET_SBIC_csr (regs, csr);
-               } while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
-                   && (csr != SBIC_CSR_CMD_INVALID));
-
-               /* lets just hope it worked.. */
-               dev->sc_flags &= ~SBICF_SELECTED;
-       }
-       return -1;
+int
+sbicabort(dev, where)
+    struct sbic_softc   *dev;
+    char                *where;
+{
+    sbic_regmap_p   regs = dev->sc_sbicp;
+    u_char          csr,
+                    asr;
+
+    GET_SBIC_asr(regs, asr);
+    GET_SBIC_csr(regs, csr);
+
+    printf ("%s: abort %s: csr = 0x%02x, asr = 0x%02x\n",
+            dev->sc_dev.dv_xname, where, csr, asr);
+
+    /*
+     * Clean up chip itself
+     */
+    if ( dev->sc_flags & SBICF_SELECTED ) {
+
+        while ( asr & SBIC_ASR_DBR ) {
+            /*
+             * sbic is jammed w/data. need to clear it
+             * But we don't know what direction it needs to go
+             */
+            GET_SBIC_data(regs, asr);
+            printf("%s: abort %s: clearing data buffer 0x%02x\n",
+                   dev->sc_dev.dv_xname, where, asr);
+            GET_SBIC_asr(regs, asr);
+            if ( asr & SBIC_ASR_DBR ) /* Not the read direction, then */
+                SET_SBIC_data(regs, asr);
+            GET_SBIC_asr(regs, asr);
+        }
+
+        WAIT_CIP(regs);
+
+        printf("%s: sbicabort - sending ABORT command\n", dev->sc_dev.dv_xname);
+        SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
+        WAIT_CIP(regs);
+
+        GET_SBIC_asr(regs, asr);
+
+        if ( asr & (SBIC_ASR_BSY|SBIC_ASR_LCI) ) {
+            /*
+             * ok, get more drastic..
+             */
+            printf("%s: sbicabort - asr %x, trying to reset\n",
+                    dev->sc_dev.dv_xname, asr);
+            sbicreset(dev);
+            dev->sc_flags &= ~SBICF_SELECTED;
+            return -1;
+        }
+
+        printf("%s: sbicabort - sending DISC command\n", dev->sc_dev.dv_xname);
+        SET_SBIC_cmd(regs, SBIC_CMD_DISC);
+
+        do {
+            SBIC_WAIT (regs, SBIC_ASR_INT, 0);
+            GET_SBIC_asr(regs, asr);
+            GET_SBIC_csr (regs, csr);
+            QPRINTF(("csr: 0x%02x, asr: 0x%02x\n", csr, asr));
+        } while ( (csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1) &&
+                  (csr != SBIC_CSR_CMD_INVALID) );
+
+        /*
+         * lets just hope it worked..
+         */
+        dev->sc_flags &= ~SBICF_SELECTED;
+    }
+
+    return -1;
 }
 
 
 /*
  * Initialize driver-private structures
  */
-
 void
 sbicinit(dev)
-       struct sbic_softc *dev;
+    struct sbic_softc *dev;
 {
-       sbic_regmap_p regs;
-       u_int my_id, i, s;
-       u_char csr;
-       struct sbic_acb *acb;
-
-       regs = dev->sc_sbicp;
-
-       if ((dev->sc_flags & SBICF_ALIVE) == 0) {
-               TAILQ_INIT(&dev->ready_list);
-               TAILQ_INIT(&dev->nexus_list);
-               TAILQ_INIT(&dev->free_list);
-               dev->sc_nexus = NULL;
-               dev->sc_xs = NULL;
-               acb = dev->sc_acb;
-               bzero(acb, sizeof(dev->sc_acb));
-               for (i = 0; i < sizeof(dev->sc_acb) / sizeof(*acb); i++) {
-                       TAILQ_INSERT_TAIL(&dev->free_list, acb, chain);
-                       acb++;
-               }
-               bzero(dev->sc_tinfo, sizeof(dev->sc_tinfo));
-       } else panic("sbic: reinitializing driver!");
-
-       dev->sc_flags |= SBICF_ALIVE;
-       dev->sc_flags &= ~SBICF_SELECTED;
-
-       sbicreset(dev);
-}
+    u_int   i;
 
-void
-sbicreset(dev)
-       struct sbic_softc *dev;
-{
-       sbic_regmap_p regs;
-       u_int my_id, i, s;
-       u_char csr;
-       struct sbic_acb *acb;
+    extern u_long   scsi_nosync;
+    extern int      shift_nosync;
 
-       regs = dev->sc_sbicp;
-#if 0
-       if (dev->sc_flags & SBICF_ALIVE) {
-               SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
-               WAIT_CIP(regs);
-       }
-#else
-               SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
-               WAIT_CIP(regs);
-#endif
-       s = splbio();
-       my_id = dev->sc_link.adapter_target & SBIC_ID_MASK;
-
-       /* Enable advanced mode */
-       my_id |= SBIC_ID_EAF /*| SBIC_ID_EHP*/ ;
-       SET_SBIC_myid(regs, my_id);
-
-       /*
-        * Disable interrupts (in dmainit) then reset the chip
-        */
-       SET_SBIC_cmd(regs, SBIC_CMD_RESET);
-       DELAY(25);
-       SBIC_WAIT(regs, SBIC_ASR_INT, 0);
-       GET_SBIC_csr(regs, csr);       /* clears interrupt also */
-
-       if (dev->sc_clkfreq < 110)
-               my_id |= SBIC_ID_FS_8_10;
-       else if (dev->sc_clkfreq < 160)
-               my_id |= SBIC_ID_FS_12_15;
-       else if (dev->sc_clkfreq < 210)
-               my_id |= SBIC_ID_FS_16_20;
-
-       SET_SBIC_myid(regs, my_id);
-
-       /*
-        * Set up various chip parameters
-        */
-       SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI /* | SBIC_CTL_HSP */
-           | SBIC_MACHINE_DMA_MODE);
-       /*
-        * don't allow (re)selection (SBIC_RID_ES)
-        * until we can handle target mode!!
-        */
-       SET_SBIC_rselid(regs, SBIC_RID_ER);
-       SET_SBIC_syn(regs, 0);     /* asynch for now */
-
-       /*
-        * anything else was zeroed by reset
-        */
-       splx(s);
+    if ( (dev->sc_flags & SBICF_ALIVE) == 0 ) {
 
-#if 0
-       if ((dev->sc_flags & SBICF_ALIVE) == 0) {
-               TAILQ_INIT(&dev->ready_list);
-               TAILQ_INIT(&dev->nexus_list);
-               TAILQ_INIT(&dev->free_list);
-               dev->sc_nexus = NULL;
-               dev->sc_xs = NULL;
-               acb = dev->sc_acb;
-               bzero(acb, sizeof(dev->sc_acb));
-               for (i = 0; i < sizeof(dev->sc_acb) / sizeof(*acb); i++) {
-                       TAILQ_INSERT_TAIL(&dev->free_list, acb, chain);
-                       acb++;
-               }
-               bzero(dev->sc_tinfo, sizeof(dev->sc_tinfo));
-       } else {
-               if (dev->sc_nexus != NULL) {
-                       dev->sc_nexus->xs->error = XS_DRIVER_STUFFUP;
-                       sbic_scsidone(dev->sc_nexus, dev->sc_stat[0]);
-               }
-               while (acb = dev->nexus_list.tqh_first) {
-                       acb->xs->error = XS_DRIVER_STUFFUP;
-                       sbic_scsidone(acb, -1 /*acb->stat[0]*/);
-               }
-       }
-
-       dev->sc_flags |= SBICF_ALIVE;
-#endif
-       dev->sc_flags &= ~SBICF_SELECTED;
-}
+        struct sbic_acb *acb;
 
-void
-sbicerror(dev, regs, csr)
-       struct sbic_softc *dev;
-       sbic_regmap_p regs;
-       u_char csr;
-{
-       struct scsi_xfer *xs;
+        TAILQ_INIT(&dev->ready_list);
+        TAILQ_INIT(&dev->nexus_list);
+        TAILQ_INIT(&dev->free_list);
 
-       xs = dev->sc_xs;
+        dev->sc_nexus = NULL;
+        dev->sc_xs    = NULL;
 
-#ifdef DIAGNOSTIC
-       if (xs == NULL)
-               panic("sbicerror");
-#endif
-       if (xs->flags & SCSI_SILENT)
-               return;
+        acb = dev->sc_acb;
+        bzero(acb, sizeof(dev->sc_acb));
 
-       printf("%s: ", dev->sc_dev.dv_xname);
-       printf("csr == 0x%02x\n", csr); /* XXX */
-}
+        for (i = 0; i < sizeof(dev->sc_acb) / sizeof(*acb); i++) {
+            TAILQ_INSERT_TAIL(&dev->free_list, acb, chain);
+            acb++;
+        }
 
-/*
- * select the bus, return when selected or error.
- */
-int
-sbicselectbus(dev, regs, target, lun, our_addr)
-        struct sbic_softc *dev;
-       sbic_regmap_p regs;
-       u_char target, lun, our_addr;
-{
-       u_char asr, csr, id;
+        bzero(dev->sc_tinfo, sizeof(dev->sc_tinfo));
 
-       QPRINTF(("sbicselectbus %d\n", target));
+#ifdef DEBUG
+        /*
+         * make sure timeout is really not needed
+         */
+        timeout((void *)sbictimeout, dev, 30 * hz);
+#endif
 
-       /*
-        * if we're already selected, return (XXXX panic maybe?)
-        */
-       if (dev->sc_flags & SBICF_SELECTED)
-               return(1);
+    } else
+        panic("sbic: reinitializing driver!");
 
-       SET_SBIC_rselid (regs, 0);
-#if 0
-       GET_SBIC_asr(regs, asr);
-       if( asr & (SBIC_ASR_INT|SBIC_ASR_BSY) ) {
-               /* This means we got ourselves reselected upon */
-/*             printf("sbicselectbus: weird asr %02x\n", asr);*/
-#ifdef DDB
-/*             Debugger();*/
-#endif
-               SET_SBIC_rselid (regs, SBIC_RID_ER);
-               return 1;
-       }
-#endif
-       /*
-        * issue select
-        */
-       SBIC_TC_PUT(regs, 0);
-       SET_SBIC_selid(regs, target);
-       SET_SBIC_timeo(regs, SBIC_TIMEOUT(250,dev->sc_clkfreq));
-
-       /*
-        * set sync or async
-        */
-       if (dev->sc_sync[target].state == SYNC_DONE)
-               SET_SBIC_syn(regs, SBIC_SYN (dev->sc_sync[target].offset,
-                   dev->sc_sync[target].period));
-       else
-               SET_SBIC_syn(regs, SBIC_SYN (0, sbic_min_period));
-
-       GET_SBIC_asr(regs, asr);
-       if( asr & (SBIC_ASR_INT|SBIC_ASR_BSY) ) {
-               /* This means we got ourselves reselected upon */
-/*             printf("sbicselectbus: INT/BSY asr %02x\n", asr);*/
-#ifdef DDB
-/*             Debugger();*/
-#endif
-               return 1;
-       }
+    dev->sc_flags |=  SBICF_ALIVE;
+    dev->sc_flags &= ~SBICF_SELECTED;
 
-       SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN);
+    /*
+     * initialize inhibit array
+     */
+    if ( scsi_nosync ) {
 
-       /*
-        * wait for select (merged from seperate function may need
-        * cleanup)
-        */
-       WAIT_CIP(regs);
-#if 0
-       GET_SBIC_asr(regs, asr);
-       if( asr & SBIC_ASR_LCI ) {
-               /* This means we got ourselves reselected upon */
-#ifdef DEBUG
-               if (reselect_debug)
-                       printf("sbicselectbus: LCI asr %02x\n", asr);
-/*             Debugger();*/
-#endif
-               return 1;
-       }
-#endif
-       do {
-               asr = SBIC_WAIT(regs, SBIC_ASR_INT | SBIC_ASR_LCI, 0);
-               if (asr & SBIC_ASR_LCI) {
-#ifdef DEBUG
-                       if (reselect_debug)
-                               printf("sbicselectbus: late LCI asr %02x\n", asr);
-#endif
-                       return 1;
-               }
-               GET_SBIC_csr (regs, csr);
-               QPRINTF(("%02x ", csr));
-               if( csr == SBIC_CSR_RSLT_NI || csr == SBIC_CSR_RSLT_IFY) {
-#ifdef DEBUG
-                       if( reselect_debug || 1 )
-                               printf("sbicselectbus: reselected asr %02x\n", asr);
-#endif
-                       /* We need to handle this now so we don't lock up later */
-                       sbicnextstate(dev, csr, asr);
-                       return 1;
-               }
-               if( csr == SBIC_CSR_SLT || csr == SBIC_CSR_SLT_ATN) {
-                       panic("sbicselectbus: target issued select!");
-                       return 1;
-               }
-       } while (csr != (SBIC_CSR_MIS_2|MESG_OUT_PHASE)
-           && csr != (SBIC_CSR_MIS_2|CMD_PHASE) && csr != SBIC_CSR_SEL_TIMEO);
-
-       /* Enable (or not) reselection */
-       if( (dev->sc_xs->flags & SCSI_POLL
-          || (dev->sc_flags & SBICF_ICMD)
-          || !sbic_enable_reselect)
-          && dev->nexus_list.tqh_first == NULL )
-               SET_SBIC_rselid (regs, 0);
-       else
-               SET_SBIC_rselid (regs, SBIC_RID_ER);
-
-       if (csr == (SBIC_CSR_MIS_2|CMD_PHASE)) {
-               dev->sc_flags |= SBICF_SELECTED;        /* device ignored ATN */
-               GET_SBIC_selid(regs, id);
-               dev->target = id;
-               GET_SBIC_tlun(regs,dev->lun);
-               if( dev->lun & SBIC_TLUN_VALID )
-                       dev->lun &= SBIC_TLUN_MASK;
-               else
-                       dev->lun = lun;
-       } else if (csr == (SBIC_CSR_MIS_2|MESG_OUT_PHASE)) {
-               /*
-                * Send identify message
-                * (SCSI-2 requires an identify msg (?))
-                */
-               GET_SBIC_selid(regs, id);
-               dev->target = id;
-               GET_SBIC_tlun(regs,dev->lun);
-               if( dev->lun & SBIC_TLUN_VALID )
-                       dev->lun &= SBIC_TLUN_MASK;
-               else
-                       dev->lun = lun;
-               /*
-                * handle drives that don't want to be asked
-                * whether to go sync at all.
-                */
-               if (sbic_inhibit_sync && dev->sc_sync[id].state == SYNC_START) {
-#ifdef DEBUG
-                       if (sync_debug)
-                               printf("Forcing target %d asynchronous.\n", id);
-#endif
-                       dev->sc_sync[id].offset = 0;
-                       dev->sc_sync[id].period = sbic_min_period;
-                       dev->sc_sync[id].state = SYNC_DONE;
-               }
-
-
-               if (dev->sc_sync[id].state != SYNC_START){
-                       if( dev->sc_xs->flags & SCSI_POLL
-                          || (dev->sc_flags & SBICF_ICMD)
-                          || !sbic_enable_reselect )
-                               SEND_BYTE (regs, MSG_IDENTIFY | lun);
-                       else
-                               SEND_BYTE (regs, MSG_IDENTIFY_DR | lun);
-               } else {
-                       /*
-                        * try to initiate a sync transfer.
-                        * So compose the sync message we're going
-                        * to send to the target
-                        */
+        u_int inhibit_sync = (scsi_nosync >> shift_nosync) & 0xff;
 
-#ifdef DEBUG
-                       if (sync_debug)
-                               printf("Sending sync request to target %d ... ",
-                                   id);
-#endif
-                       /*
-                        * setup scsi message sync message request
-                        */
-                       dev->sc_msg[0] = MSG_IDENTIFY | lun;
-                       dev->sc_msg[1] = MSG_EXT_MESSAGE;
-                       dev->sc_msg[2] = 3;
-                       dev->sc_msg[3] = MSG_SYNC_REQ;
-                       dev->sc_msg[4] = sbictoscsiperiod(dev, regs,
-                           sbic_min_period);
-                       dev->sc_msg[5] = sbic_max_offset;
-
-                       if (sbicxfstart(regs, 6, MESG_OUT_PHASE, sbic_cmd_wait))
-                               sbicxfout(regs, 6, dev->sc_msg, MESG_OUT_PHASE);
-
-                       dev->sc_sync[id].state = SYNC_SENT;
-#ifdef DEBUG
-                       if (sync_debug)
-                               printf ("sent\n");
-#endif
-               }
+        shift_nosync += 8;
 
-               SBIC_WAIT (regs, SBIC_ASR_INT, 0);
-               GET_SBIC_csr (regs, csr);
-               QPRINTF(("[%02x]", csr));
 #ifdef DEBUG
-               if (sync_debug && dev->sc_sync[id].state == SYNC_SENT)
-                       printf("csr-result of last msgout: 0x%x\n", csr);
+        if ( inhibit_sync )
+            printf("%s: Inhibiting synchronous transfer %02x\n",
+                        dev->sc_dev.dv_xname, inhibit_sync);
 #endif
+        for (i = 0; i < 8; ++i) {
+            if ( inhibit_sync & (1 << i) )
+                sbic_inhibit_sync[i] = 1;
+        }
+    }
 
-               if (csr != SBIC_CSR_SEL_TIMEO)
-                       dev->sc_flags |= SBICF_SELECTED;
-       }
-       if (csr == SBIC_CSR_SEL_TIMEO)
-               dev->sc_xs->error = XS_SELTIMEOUT;
-
-       QPRINTF(("\n"));
-
-       return(csr == SBIC_CSR_SEL_TIMEO);
-}
-
-int
-sbicxfstart(regs, len, phase, wait)
-       sbic_regmap_p regs;
-       int len, wait;
-       u_char phase;
-{
-       u_char id;
-
-       switch (phase) {
-       case DATA_IN_PHASE:
-       case MESG_IN_PHASE:
-               GET_SBIC_selid (regs, id);
-               id |= SBIC_SID_FROM_SCSI;
-               SET_SBIC_selid (regs, id);
-               SBIC_TC_PUT (regs, (unsigned)len);
-               break;
-       case DATA_OUT_PHASE:
-       case MESG_OUT_PHASE:
-       case CMD_PHASE:
-               GET_SBIC_selid (regs, id);
-               id &= ~SBIC_SID_FROM_SCSI;
-               SET_SBIC_selid (regs, id);
-               SBIC_TC_PUT (regs, (unsigned)len);
-               break;
-       default:
-               SBIC_TC_PUT (regs, 0);
-       }
-       QPRINTF(("sbicxfstart %d, %d, %d\n", len, phase, wait));
-
-       return(1);
+    sbicreset(dev);
 }
 
-int
-sbicxfout(regs, len, bp, phase)
-       sbic_regmap_p regs;
-       int len;
-       void *bp;
-       int phase;
+void
+sbicreset(dev)
+    struct sbic_softc *dev;
 {
-       u_char orig_csr, csr, asr, *buf;
-       int wait;
-
-       buf = bp;
-       wait = sbic_data_wait;
-
-       QPRINTF(("sbicxfout {%d} %02x %02x %02x %02x %02x "
-           "%02x %02x %02x %02x %02x\n", len, buf[0], buf[1], buf[2],
-           buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]));
-
-       GET_SBIC_csr (regs, orig_csr);
-
-       /*
-        * sigh.. WD-PROTO strikes again.. sending the command in one go
-        * causes the chip to lock up if talking to certain (misbehaving?)
-        * targets. Anyway, this procedure should work for all targets, but
-        * it's slightly slower due to the overhead
-        */
-       WAIT_CIP (regs);
-       SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
-       for (;len > 0; len--) {
-               GET_SBIC_asr (regs, asr);
-               while ((asr & SBIC_ASR_DBR) == 0) {
-                       if ((asr & SBIC_ASR_INT) || --wait < 0) {
-#ifdef DEBUG
-                               if (sbic_debug)
-                                       printf("sbicxfout fail: l%d i%x w%d\n",
-                                           len, asr, wait);
-#endif
-                               return (len);
-                       }
-/*                     DELAY(1);*/
-                       GET_SBIC_asr (regs, asr);
-               }
-
-               SET_SBIC_data (regs, *buf);
-               buf++;
-       }
-       SBIC_TC_GET(regs, len);
-       QPRINTF(("sbicxfout done %d bytes\n", len));
-       /*
-        * this leaves with one csr to be read
-        */
-       return(0);
+    sbic_regmap_p   regs = dev->sc_sbicp;
+    u_int           my_id,
+                    s;
+    u_char          csr;
+
+    s = splbio();
+
+    my_id = dev->sc_link.adapter_target & SBIC_ID_MASK;
+
+    if (dev->sc_clkfreq < 110)
+        my_id |= SBIC_ID_FS_8_10;
+    else if (dev->sc_clkfreq < 160)
+        my_id |= SBIC_ID_FS_12_15;
+    else if (dev->sc_clkfreq < 210)
+        my_id |= SBIC_ID_FS_16_20;
+
+    SET_SBIC_myid(regs, my_id);
+
+    /*
+     * Reset the chip
+     */
+    SET_SBIC_cmd(regs, SBIC_CMD_RESET);
+    DELAY(25);
+
+    SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+    GET_SBIC_csr(regs, csr);       /* clears interrupt also */
+
+    /*
+     * Set up various chip parameters
+     */
+    SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
+
+    /*
+     * don't allow Selection (SBIC_RID_ES)
+     * until we can handle target mode!!
+     */
+    SET_SBIC_rselid(regs, SBIC_RID_ER);
+
+    /*
+     * Asynchronous for now
+     */
+    SET_SBIC_syn(regs, 0);
+
+    /*
+     * Anything else was zeroed by reset
+     */
+    splx(s);
+
+    dev->sc_flags &= ~SBICF_SELECTED;
 }
 
-/* returns # bytes left to read */
-int
-sbicxfin(regs, len, bp)
-       sbic_regmap_p regs;
-       int len;
-       void *bp;
+void
+sbicerror(dev, csr)
+    struct sbic_softc   *dev;
+    u_char              csr;
 {
-       int wait, read;
-       u_char *obp, *buf;
-       u_char orig_csr, csr, asr;
+    struct scsi_xfer    *xs  = dev->sc_xs;
 
-       wait = sbic_data_wait;
-       obp = bp;
-       buf = bp;
+#ifdef DIAGNOSTIC
+    if ( xs == NULL )
+        panic("sbicerror: dev->sc_xs == NULL");
+#endif
 
-       GET_SBIC_csr (regs, orig_csr);
+    if ( xs->flags & SCSI_SILENT )
+        return;
 
-       QPRINTF(("sbicxfin %d, csr=%02x\n", len, orig_csr));
+    printf("%s: csr == 0x%02x\n", dev->sc_dev.dv_xname, csr);
+}
 
-       WAIT_CIP (regs);
-       SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
-       for (;len > 0; len--) {
-               GET_SBIC_asr (regs, asr);
-               if((asr & SBIC_ASR_PE)) {
+/*
+ * select the bus, return when selected or error.
+ *
+ * Returns the current CSR following selection and optionally MSG out phase.
+ * i.e. the returned CSR *should* indicate CMD phase...
+ * If the return value is 0, some error happened.
+ */
+u_char
+sbicselectbus(dev)
+    struct sbic_softc   *dev;
+{
+    sbic_regmap_p   regs   = dev->sc_sbicp;
+    u_char          target = dev->target,
+                    lun    = dev->lun,
+                    asr,
+                    csr,
+                    id;
+
+    /*
+     * if we're already selected, return (XXXX panic maybe?)
+     */
+    if ( dev->sc_flags & SBICF_SELECTED )
+        return(0);
+
+    QPRINTF(("sbicselectbus %d: ", target));
+
+    /*
+     * issue select
+     */
+    SET_SBIC_selid(regs, target);
+    SET_SBIC_timeo(regs, SBIC_TIMEOUT(250, dev->sc_clkfreq));
+
+    /*
+     * set sync or async
+     */
+    if ( dev->sc_sync[target].state == SYNC_DONE )
+        SET_SBIC_syn(regs, SBIC_SYN(dev->sc_sync[target].offset,
+                                    dev->sc_sync[target].period));
+    else
+        SET_SBIC_syn(regs, SBIC_SYN(0, sbic_min_period));
+
+    GET_SBIC_asr(regs, asr);
+
+    if ( asr & (SBIC_ASR_INT|SBIC_ASR_BSY) ) {
+        /*
+         * This means we got ourselves reselected upon
+         */
+        QPRINTF(("WD busy (reselect?)\n"));
+        return 0;
+    }
+
+    SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN);
+
+    /*
+     * wait for select (merged from seperate function may need
+     * cleanup)
+     */
+    WAIT_CIP(regs);
+
+    do {
+
+        asr = SBIC_WAIT(regs, SBIC_ASR_INT | SBIC_ASR_LCI, 0);
+
+        if ( asr & SBIC_ASR_LCI ) {
+            QPRINTF(("late LCI: asr %02x\n", asr));
+            return 0;
+        }
+
+        /*
+         * Clear interrupt
+         */
+        GET_SBIC_csr (regs, csr);
+
+        QPRINTF(("%02x ", csr));
+
+        /*
+         * Reselected from under our feet?
+         */
+        if ( csr == SBIC_CSR_RSLT_NI || csr == SBIC_CSR_RSLT_IFY ) {
+            QPRINTF(("got reselected, asr %02x\n", asr));
+            /*
+             * We need to handle this now so we don't lock up later
+             */
+            sbicnextstate(dev, csr, asr);
+
+            return 0;
+        }
+
+        /*
+         * Whoops!
+         */
+        if ( csr == SBIC_CSR_SLT || csr == SBIC_CSR_SLT_ATN ) {
+            panic("sbicselectbus: target issued select!");
+            return 0;
+        }
+
+    } while (csr != (SBIC_CSR_MIS_2 | MESG_OUT_PHASE) &&
+             csr != (SBIC_CSR_MIS_2 | CMD_PHASE) &&
+             csr != SBIC_CSR_SEL_TIMEO);
+
+    /*
+     * Anyone at home?
+     */
+    if ( csr == SBIC_CSR_SEL_TIMEO ) {
+        dev->sc_xs->error = XS_SELTIMEOUT;
+        QPRINTF(("Selection Timeout\n"));
+        return 0;
+    }
+
+    QPRINTF(("Selection Complete\n"));
+
+    /*
+     * Assume we're now selected
+     */
+    GET_SBIC_selid(regs, id);
+    dev->target    = id;
+    dev->lun       = lun;
+    dev->sc_flags |= SBICF_SELECTED;
+
+    /*
+     * Enable (or not) reselection
+     * XXXSCW This is probably not necessary since we don't use use the
+     * Select-and-Xfer-with-ATN command to initialte a selection...
+     */
+    if ( !sbic_enable_reselect && dev->nexus_list.tqh_first == NULL)
+        SET_SBIC_rselid (regs, 0);
+    else
+        SET_SBIC_rselid (regs, SBIC_RID_ER);
+
+    /*
+     * We only really need to do anything when the target goes to MSG out
+     * If the device ignored ATN, it's probably old and brain-dead,
+     * but we'll try to support it anyhow.
+     * If it doesn't support message out, it definately doesn't
+     * support synchronous transfers, so no point in even asking...
+     */
+    if ( csr == (SBIC_CSR_MIS_2 | MESG_OUT_PHASE) ) {
+        /*
+         * Send identify message (SCSI-2 requires an identify msg)
+         */
+        if ( sbic_inhibit_sync[id] && dev->sc_sync[id].state == SYNC_START ) {
+            /*
+             * Handle drives that don't want to be asked
+             * whether to go sync at all.
+             */
+            dev->sc_sync[id].offset = 0;
+            dev->sc_sync[id].period = sbic_min_period;
+            dev->sc_sync[id].state  = SYNC_DONE;
+        }
+
+        /*
+         * Do we need to negotiate Synchronous Xfers for this target?
+         */
+        if ( dev->sc_sync[id].state != SYNC_START ) {
+            /*
+             * Nope, we've already negotiated.
+             * Now see if we should allow the target to disconnect/reselect...
+             */
+            if ( dev->sc_xs->flags & SCSI_POLL || dev->sc_flags & SBICF_ICMD ||
+                                                  !sbic_enable_reselect )
+                SEND_BYTE (regs, MSG_IDENTIFY | lun);
+            else
+                SEND_BYTE (regs, MSG_IDENTIFY_DR | lun);
+
+        } else {
+            /*
+             * try to initiate a sync transfer.
+             * So compose the sync message we're going
+             * to send to the target
+             */
 #ifdef DEBUG
-                       printf("sbicxfin parity error: l%d i%x w%d\n",
-                              len, asr, wait);
-/*                     return ((unsigned long)buf - (unsigned long)bp); */
-#ifdef DDB
-                       Debugger();
-#endif
-#endif
-               }
-               while ((asr & SBIC_ASR_DBR) == 0) {
-                       if ((asr & SBIC_ASR_INT) || --wait < 0) {
+            if ( sync_debug )
+                printf("\nSending sync request to target %d ... ", id);
+#endif
+            /*
+             * setup scsi message sync message request
+             */
+            dev->sc_msg[0] = MSG_IDENTIFY | lun;
+            dev->sc_msg[1] = MSG_EXT_MESSAGE;
+            dev->sc_msg[2] = 3;
+            dev->sc_msg[3] = MSG_SYNC_REQ;
+            dev->sc_msg[4] = sbictoscsiperiod(dev, sbic_min_period);
+            dev->sc_msg[5] = sbic_max_offset;
+
+            sbicxfout(regs, 6, dev->sc_msg);
+
+            dev->sc_sync[id].state = SYNC_SENT;
 #ifdef DEBUG
-                               if (sbic_debug) {
-       QPRINTF(("sbicxfin fail:{%d} %02x %02x %02x %02x %02x %02x "
-           "%02x %02x %02x %02x\n", len, obp[0], obp[1], obp[2],
-           obp[3], obp[4], obp[5], obp[6], obp[7], obp[8], obp[9]));
-                                       printf("sbicxfin fail: l%d i%x w%d\n",
-                                           len, asr, wait);
-}
+            if ( sync_debug )
+                printf ("sent\n");
 #endif
-                               return len;
-                       }
+        }
 
-                       if( ! asr & SBIC_ASR_BSY ) {
-                               GET_SBIC_csr(regs, csr);
-                               QPRINTF(("[CSR%02xASR%02x]", csr, asr));
-                       }
+        /*
+         * There's one interrupt still to come: the change to CMD phase...
+         */
+        SBIC_WAIT(regs, SBIC_ASR_INT , 0);
+        GET_SBIC_csr(regs, csr);
+    }
 
-/*                     DELAY(1);*/
-                       GET_SBIC_asr (regs, asr);
-               }
-
-               GET_SBIC_data (regs, *buf);
-/*             QPRINTF(("asr=%02x, csr=%02x, data=%02x\n", asr, csr, *buf));*/
-               buf++;
-       }
+    return csr;
+}
 
-       QPRINTF(("sbicxfin {%d} %02x %02x %02x %02x %02x %02x "
-           "%02x %02x %02x %02x\n", len, obp[0], obp[1], obp[2],
-           obp[3], obp[4], obp[5], obp[6], obp[7], obp[8], obp[9]));
+/*
+ * Information Transfer *to* a Scsi Target
+ */
+int
+sbicxfout(regs, len, bp)
+    sbic_regmap_p   regs;
+    int             len;
+    void            *bp;
+{
+    int     wait = sbic_data_wait;
+    u_char  asr,
+            *buf = bp;
+
+    QPRINTF(("sbicxfout {%d} %02x %02x %02x %02x %02x "
+        "%02x %02x %02x %02x %02x\n", len, buf[0], buf[1], buf[2],
+        buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]));
+
+    /*
+     * sigh.. WD-PROTO strikes again.. sending the command in one go
+     * causes the chip to lock up if talking to certain (misbehaving?)
+     * targets. Anyway, this procedure should work for all targets, but
+     * it's slightly slower due to the overhead
+     */
+    WAIT_CIP (regs);
+
+    SBIC_TC_PUT (regs, 0);
+    SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
+    SBIC_TC_PUT (regs, (unsigned)len);
+    SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
+
+    /*
+     * Loop for each byte transferred
+     */
+    do {
+
+        GET_SBIC_asr (regs, asr);
+
+        if ( asr & SBIC_ASR_DBR ) {
+            if ( len ) {
+                SET_SBIC_data (regs, *buf);
+                buf++;
+                len--;
+            } else {
+                SET_SBIC_data (regs, 0);
+            }
+            wait = sbic_data_wait;
+        }
+
+    } while ( (asr & SBIC_ASR_INT) == 0 && wait-- > 0 );
+
+    SBIC_TC_GET(regs, len);
+    SBIC_TC_PUT(regs, 0);
+
+#ifdef  DEBUG
+    QPRINTF(("sbicxfout done: %d bytes remaining (wait:%d)\n", len, wait));
+#endif
+
+    /*
+     * this leaves with one csr to be read
+     */
+    return(len);
+}
 
-       /* this leaves with one csr to be read */
-       return len;
+/*
+ * Information Transfer *from* a Scsi Target
+ * returns # bytes left to read
+ */
+int
+sbicxfin(regs, len, bp)
+    sbic_regmap_p   regs;
+    int             len;
+    void            *bp;
+{
+    int     wait = sbic_data_wait;
+    u_char  *buf = bp;
+    u_char  asr;
+#ifdef  DEBUG
+    u_char  *obp = bp;
+#endif
+
+    WAIT_CIP (regs);
+
+    SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
+    SBIC_TC_PUT (regs, (unsigned)len);
+    SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
+
+    /*
+     * Loop for each byte transferred
+     */
+    do {
+
+        GET_SBIC_asr (regs, asr);
+
+        if ( asr & SBIC_ASR_DBR ) {
+            if ( len ) {
+                GET_SBIC_data (regs, *buf);
+                buf++;
+                len--;
+            } else {
+                u_char foo;
+                GET_SBIC_data (regs, foo);
+            }
+            wait = sbic_data_wait;
+        }
+
+    } while ( (asr & SBIC_ASR_INT) == 0 && wait-- > 0 );
+
+    QPRINTF(("sbicxfin {%d} %02x %02x %02x %02x %02x %02x "
+        "%02x %02x %02x %02x\n", len, obp[0], obp[1], obp[2],
+        obp[3], obp[4], obp[5], obp[6], obp[7], obp[8], obp[9]));
+
+    SBIC_TC_PUT (regs, 0);
+
+    /*
+     * this leaves with one csr to be read
+     */
+    return len;
 }
 
 /*
@@ -1258,242 +1304,186 @@ sbicxfin(regs, len, bp)
  * command must supply no data.
  */
 int
-sbicicmd(dev, target, lun, cbuf, clen, buf, len)
-       struct sbic_softc *dev;
-       void *cbuf, *buf;
-       int clen, len;
+sbicicmd(dev, cbuf, clen, buf, len)
+    struct sbic_softc   *dev;
+    void                *cbuf,
+                        *buf;
+    int                 clen,
+                        len;
 {
-       sbic_regmap_p regs;
-       u_char phase, csr, asr;
-       int wait, newtarget, cmd_sent, parity_err;
-       struct sbic_acb *acb;
-
-       int discon;
-       int i;
-
-#define CSR_LOG_BUF_SIZE 0
-#if CSR_LOG_BUF_SIZE
-       int bufptr;
-       int csrbuf[CSR_LOG_BUF_SIZE];
-       bufptr=0;
-#endif
-
-       regs = dev->sc_sbicp;
-       acb = dev->sc_nexus;
-
-       /* Make sure pointers are OK */
-       dev->sc_last = dev->sc_cur = &acb->sc_pa;
-       dev->sc_tcnt = acb->sc_tcnt = 0;
-       acb->sc_pa.dc_count = 0; /* No DMA */
-       acb->sc_kv.dc_addr = buf;
-       acb->sc_kv.dc_count = len;
-
-#ifdef DEBUG
-       routine = 3;
-       debug_sbic_regs = regs; /* store this to allow debug calls */
-       if( data_pointer_debug > 1 )
-               printf("sbicicmd(%d,%d):%d\n", target, lun,
-                      acb->sc_kv.dc_count);
-#endif
-
-       /*
-        * set the sbic into non-DMA mode
-        */
-       SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI /*| SBIC_CTL_HSP*/);
-
-       dev->sc_stat[0] = 0xff;
-       dev->sc_msg[0] = 0xff;
-       i = 1; /* pre-load */
-
-       /* We're stealing the SCSI bus */
-       dev->sc_flags |= SBICF_ICMD;
-
-       do {
-               /*
-                * select the SCSI bus (it's an error if bus isn't free)
-                */
-               if (!( dev->sc_flags & SBICF_SELECTED )
-                   && sbicselectbus(dev, regs, target, lun, dev->sc_scsiaddr)) {
-                       /*printf("sbicicmd trying to select busy bus!\n");*/
-                       dev->sc_flags &= ~SBICF_ICMD;
-                       return(-1);
-               }
-
-               /*
-                * Wait for a phase change (or error) then let the device sequence
-                * us through the various SCSI phases.
-                */
-
-               wait = sbic_cmd_wait;
-
-               GET_SBIC_asr (regs, asr);
-               GET_SBIC_csr (regs, csr);
-               QPRINTF((">ASR:%02xCSR:%02x<", asr, csr));
-
-#if CSR_LOG_BUF_SIZE
-               csrbuf[bufptr++] = csr;
-#endif
-
-
-               switch (csr) {
-               case SBIC_CSR_S_XFERRED:
-               case SBIC_CSR_DISC:
-               case SBIC_CSR_DISC_1:
-                       dev->sc_flags &= ~SBICF_SELECTED;
-                       GET_SBIC_cmd_phase (regs, phase);
-                       if (phase == 0x60) {
-                               GET_SBIC_tlun (regs, dev->sc_stat[0]);
-                               i = 0; /* done */
-/*                             break; /* Bypass all the state gobldygook */
-                       } else {
+    sbic_regmap_p   regs = dev->sc_sbicp;
+    struct sbic_acb *acb = dev->sc_nexus;
+    u_char          csr,
+                    asr;
+    int             still_busy = 1;
+
+    /*
+     * Make sure pointers are OK
+     */
+    dev->sc_last = dev->sc_cur = &acb->sc_pa;
+    dev->sc_tcnt = acb->sc_tcnt = 0;
+
+    acb->sc_dmacmd      = 0;
+    acb->sc_pa.dc_count = 0; /* No DMA */
+    acb->sc_kv.dc_addr  = buf;
+    acb->sc_kv.dc_count = len;
+
+#ifdef  DEBUG
+    if ( data_pointer_debug > 1 )
+        printf("sbicicmd(%d,%d):%d\n", dev->target, dev->lun, acb->sc_kv.dc_count);
+#endif
+
+    /*
+     * set the sbic into non-DMA mode
+     */
+    SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
+
+    dev->sc_stat[0] = 0xff;
+    dev->sc_msg[0]  = 0xff;
+
+    /*
+     * We're stealing the SCSI bus
+     */
+    dev->sc_flags |= SBICF_ICMD;
+
+    do {
+        GET_SBIC_asr (regs, asr);
+
+        /*
+         * select the SCSI bus (it's an error if bus isn't free)
+         */
+        if ( (dev->sc_flags & SBICF_SELECTED) == 0 ) {
+            if ( (csr = sbicselectbus(dev)) == 0 ) {
+                dev->sc_flags &= ~SBICF_ICMD;
+                return(-1);
+            }
+        } else
+            GET_SBIC_csr(regs, csr);
+
+        QPRINTF((">ASR:0x%02x CSR:0x%02x <", asr, csr));
+
+        switch ( csr ) {
+
+          case SBIC_CSR_S_XFERRED:
+          case SBIC_CSR_DISC:
+          case SBIC_CSR_DISC_1:
+            {
+                u_char  phase;
+
+                dev->sc_flags &= ~SBICF_SELECTED;
+                GET_SBIC_cmd_phase (regs, phase);
+
+                if ( phase == 0x60 ) {
+                    GET_SBIC_tlun (regs, dev->sc_stat[0]);
+                    still_busy = 0; /* done */
+                } else {
 #ifdef DEBUG
-                               if(reselect_debug>1)
-                                       printf("sbicicmd: handling disconnect\n");
-#endif
-                               i = SBIC_STATE_DISCONNECT;
-                       }
-                       break;
-
-               case SBIC_CSR_XFERRED|CMD_PHASE:
-               case SBIC_CSR_MIS|CMD_PHASE:
-               case SBIC_CSR_MIS_1|CMD_PHASE:
-               case SBIC_CSR_MIS_2|CMD_PHASE:
-                       if (sbicxfstart(regs, clen, CMD_PHASE, sbic_cmd_wait))
-                               if (sbicxfout(regs, clen,
-                                             cbuf, CMD_PHASE))
-                                       i = sbicabort(dev, regs,"icmd sending cmd");
-#if 0
-                       GET_SBIC_csr(regs, csr); /* Lets us reload tcount */
-                       WAIT_CIP(regs);
-                       GET_SBIC_asr(regs, asr);
-                       if( asr & (SBIC_ASR_BSY|SBIC_ASR_LCI|SBIC_ASR_CIP) )
-                               printf("next: cmd sent asr %02x, csr %02x\n",
-                                      asr, csr);
-#endif
-                       break;
-
-#if 0
-               case SBIC_CSR_XFERRED|DATA_OUT_PHASE:
-               case SBIC_CSR_XFERRED|DATA_IN_PHASE:
-               case SBIC_CSR_MIS|DATA_OUT_PHASE:
-               case SBIC_CSR_MIS|DATA_IN_PHASE:
-               case SBIC_CSR_MIS_1|DATA_OUT_PHASE:
-               case SBIC_CSR_MIS_1|DATA_IN_PHASE:
-               case SBIC_CSR_MIS_2|DATA_OUT_PHASE:
-               case SBIC_CSR_MIS_2|DATA_IN_PHASE:
-                       if (acb->sc_kv.dc_count <= 0)
-                               i = sbicabort(dev, regs, "icmd out of data");
-                       else {
-                         wait = sbic_data_wait;
-                         if (sbicxfstart(regs,
-                                         acb->sc_kv.dc_count,
-                                         SBIC_PHASE(csr), wait))
-                           if (csr & 0x01)
-                             /* data in? */
-                             i=sbicxfin(regs,
-                                        acb->sc_kv.dc_count,
-                                        acb->sc_kv.dc_addr);
-                           else
-                             i=sbicxfout(regs,
-                                         acb->sc_kv.dc_count,
-                                         acb->sc_kv.dc_addr,
-                                            SBIC_PHASE(csr));
-                         acb->sc_kv.dc_addr +=
-                                 (acb->sc_kv.dc_count - i);
-                         acb->sc_kv.dc_count = i;
-                         i = 1;
-                       }
-                       break;
-
-#endif
-               case SBIC_CSR_XFERRED|STATUS_PHASE:
-               case SBIC_CSR_MIS|STATUS_PHASE:
-               case SBIC_CSR_MIS_1|STATUS_PHASE:
-               case SBIC_CSR_MIS_2|STATUS_PHASE:
-                       /*
-                        * the sbic does the status/cmd-complete reading ok,
-                        * so do this with its hi-level commands.
-                        */
+                    if ( reselect_debug > 1 )
+                        printf("sbicicmd: handling disconnect\n");
+#endif
+                    still_busy = SBIC_STATE_DISCONNECT;
+                }
+            }
+            break;
+
+          case SBIC_CSR_XFERRED | CMD_PHASE:
+          case SBIC_CSR_MIS     | CMD_PHASE:
+          case SBIC_CSR_MIS_1   | CMD_PHASE:
+          case SBIC_CSR_MIS_2   | CMD_PHASE:
+            {
+                if ( sbicxfout(regs, clen, cbuf) )
+                    still_busy = sbicabort(dev, "icmd sending cmd");
+            }
+            break;
+
+          case SBIC_CSR_XFERRED | STATUS_PHASE:
+          case SBIC_CSR_MIS     | STATUS_PHASE:
+          case SBIC_CSR_MIS_1   | STATUS_PHASE:
+          case SBIC_CSR_MIS_2   | STATUS_PHASE:
+            {
+                /*
+                 * The sbic does the status/cmd-complete reading ok,
+                 * so do this with its hi-level commands.
+                 */
 #ifdef DEBUG
-                       if(sbic_debug)
-                               printf("SBICICMD status phase\n");
-#endif
-                       SBIC_TC_PUT(regs, 0);
-                       SET_SBIC_cmd_phase(regs, 0x46);
-                       SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER);
-                       break;
-
-#if THIS_IS_A_RESERVED_STATE
-               case BUS_FREE_PHASE:            /* This is not legal */
-                       if( dev->sc_stat[0] != 0xff )
-                               goto out;
-                       break;
-#endif
-
-               default:
-                       i = sbicnextstate(dev, csr, asr);
-               }
-
-               /*
-                * make sure the last command was taken,
-                * ie. we're not hunting after an ignored command..
-                */
-               GET_SBIC_asr(regs, asr);
-
-               /* tapes may take a loooong time.. */
-               while (asr & SBIC_ASR_BSY){
-                       if(asr & SBIC_ASR_DBR) {
-                               printf("sbicicmd: Waiting while sbic is jammed, CSR:%02x,ASR:%02x\n",
-                                      csr,asr);
+                if ( sbic_debug )
+                    printf("SBICICMD status phase (bsy=%d)\n", still_busy);
+#endif
+                SET_SBIC_cmd_phase(regs, 0x46);
+                SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER);
+            }
+            break;
+
+          default:
+            {
+                still_busy = sbicnextstate(dev, csr, asr);
+            }
+            break;
+        }
+
+        /*
+         * make sure the last command was taken,
+         * ie. we're not hunting after an ignored command..
+         */
+        GET_SBIC_asr(regs, asr);
+
+        /*
+         * tapes may take a loooong time..
+         */
+        while (asr & SBIC_ASR_BSY ) {
+
+            if ( asr & SBIC_ASR_DBR ) {
+                int     i;
+
+                printf("sbicicmd: Waiting while sbic is jammed, CSR:%02x,ASR:%02x\n", csr,asr);
 #ifdef DDB
-                               Debugger();
-#endif
-                               /* SBIC is jammed */
-                               /* DUNNO which direction */
-                               /* Try old direction */
-                               GET_SBIC_data(regs,i);
-                               GET_SBIC_asr(regs, asr);
-                               if( asr & SBIC_ASR_DBR) /* Wants us to write */
-                                       SET_SBIC_data(regs,i);
-                       }
-                       GET_SBIC_asr(regs, asr);
-               }
-
-               /*
-                * wait for last command to complete
-                */
-               if (asr & SBIC_ASR_LCI) {
-                       printf("sbicicmd: last command ignored\n");
-               }
-               else if( i == 1 ) /* Bsy */
-                       SBIC_WAIT (regs, SBIC_ASR_INT, wait);
-
-               /*
-                * do it again
-                */
-       } while ( i > 0 && dev->sc_stat[0] == 0xff);
-
-       /* Sometimes we need to do an extra read of the CSR */
-       GET_SBIC_csr(regs, csr);
-
-#if CSR_LOG_BUF_SIZE
-       if(reselect_debug>1)
-               for(i=0; i<bufptr; i++)
-                       printf("CSR:%02x", csrbuf[i]);
-#endif
+                Debugger();
+#endif
+                /*
+                 * SBIC is jammed
+                 * DUNNO which direction
+                 * Try old direction
+                 */
+                GET_SBIC_data(regs, i);
+                GET_SBIC_asr(regs, asr);
+
+                if ( asr & SBIC_ASR_DBR ) /* Wants us to write */
+                    SET_SBIC_data(regs, i);
+            }
+
+            GET_SBIC_asr(regs, asr);
+        }
+
+        /*
+         * wait for last command to complete
+         */
+        if ( asr & SBIC_ASR_LCI ) {
+            printf("sbicicmd: last command ignored\n");
+        }
+        else
+        if ( still_busy == 1 ) /* Bsy */
+            SBIC_WAIT (regs, SBIC_ASR_INT, sbic_cmd_wait);
+
+        /*
+         * do it again
+         */
+    } while ( still_busy > 0 && dev->sc_stat[0] == 0xff );
+
+    /*
+     * Sometimes we need to do an extra read of the CSR
+     */
+    GET_SBIC_csr(regs, csr);
 
 #ifdef DEBUG
-       if(data_pointer_debug > 1)
-               printf("sbicicmd done(%d,%d):%d =%d=\n",
-                      dev->target, lun,
-                      acb->sc_kv.dc_count,
-                      dev->sc_stat[0]);
+    if ( data_pointer_debug > 1 )
+        printf("sbicicmd done(%d,%d):%d =%d=\n", dev->target, dev->lun,
+                                                 acb->sc_kv.dc_count,
+                                                 dev->sc_stat[0]);
 #endif
 
-       QPRINTF(("=STS:%02x=", dev->sc_stat[0]));
-       dev->sc_flags &= ~SBICF_ICMD;
+    dev->sc_flags &= ~SBICF_ICMD;
 
-       return(dev->sc_stat[0]);
+    return(dev->sc_stat[0]);
 }
 
 /*
@@ -1503,1059 +1493,1176 @@ sbicicmd(dev, target, lun, cbuf, clen, buf, len)
  * skip (and don't allow) the select, cmd out and data in/out phases.
  */
 void
-sbicxfdone(dev, regs, target)
-       struct sbic_softc *dev;
-       sbic_regmap_p regs;
-       int target;
+sbicxfdone(dev)
+    struct sbic_softc   *dev;
 {
-       u_char phase, csr;
-       int s;
-
-       QPRINTF(("{"));
-       s = splbio();
-
-       /*
-        * have the sbic complete on its own
-        */
-       SBIC_TC_PUT(regs, 0);
-       SET_SBIC_cmd_phase(regs, 0x46);
-       SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER);
-
-       do {
-               SBIC_WAIT (regs, SBIC_ASR_INT, 0);
-               GET_SBIC_csr (regs, csr);
-               QPRINTF(("%02x:", csr));
-       } while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
-           && (csr != SBIC_CSR_S_XFERRED));
-
-       dev->sc_flags &= ~SBICF_SELECTED;
-
-       GET_SBIC_cmd_phase (regs, phase);
-       QPRINTF(("}%02x", phase));
-       if (phase == 0x60)
-               GET_SBIC_tlun(regs, dev->sc_stat[0]);
-       else
-               sbicerror(dev, regs, csr);
-
-       QPRINTF(("=STS:%02x=\n", dev->sc_stat[0]));
-       splx(s);
-}
+    sbic_regmap_p   regs = dev->sc_sbicp;
+    u_char          phase,
+                    csr;
+    int             s;
+
+    QPRINTF(("{"));
+    s = splbio();
+
+    /*
+     * have the sbic complete on its own
+     */
+    SBIC_TC_PUT(regs, 0);
+    SET_SBIC_cmd_phase(regs, 0x46);
+    SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER);
+
+    do {
 
-       /*
-        * No DMA chains
-        */
+        SBIC_WAIT (regs, SBIC_ASR_INT, 0);
+        GET_SBIC_csr (regs, csr);
+        QPRINTF(("%02x:", csr));
 
+    } while ( (csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1) &&
+              (csr != SBIC_CSR_S_XFERRED));
+
+    dev->sc_flags &= ~SBICF_SELECTED;
+
+    GET_SBIC_cmd_phase (regs, phase);
+    QPRINTF(("}%02x", phase));
+
+    if ( phase == 0x60 )
+        GET_SBIC_tlun(regs, dev->sc_stat[0]);
+    else
+        sbicerror(dev, csr);
+
+    QPRINTF(("=STS:%02x=\n", dev->sc_stat[0]));
+
+    splx(s);
+}
+
+/*
+ * No DMA chains
+ */
 int
 sbicgo(dev, xs)
-       struct sbic_softc *dev;
-       struct scsi_xfer *xs;
+    struct sbic_softc   *dev;
+    struct scsi_xfer    *xs;
 {
-       int i, dmaflags, count, wait, usedma;
-       u_char csr, asr, cmd, *addr;
-       sbic_regmap_p regs;
-       struct sbic_acb *acb;
+    struct sbic_acb *acb = dev->sc_nexus;
+    sbic_regmap_p   regs = dev->sc_sbicp;
+    int             i,
+                    dmaflags,
+                    count,
+                    usedma;
+    u_char          csr,
+                    asr,
+                    *addr;
 
-       dev->target = xs->sc_link->target;
-       dev->lun = xs->sc_link->lun;
-       acb = dev->sc_nexus;
-       regs = dev->sc_sbicp;
+    dev->target = xs->sc_link->target;
+    dev->lun    = xs->sc_link->lun;
+
+    usedma = sbicdmaok(dev, xs);
 
-       usedma = sbicdmaok(dev, xs);
 #ifdef DEBUG
-       routine = 1;
-       debug_sbic_regs = regs; /* store this to allow debug calls */
-       if( data_pointer_debug > 1 )
-               printf("sbicgo(%d,%d)\n", dev->target, dev->lun);
+    if ( data_pointer_debug > 1 )
+        printf("sbicgo(%d,%d): usedma=%d\n", dev->target, dev->lun, usedma);
 #endif
 
-       /*
-        * set the sbic into DMA mode
-        */
-       if( usedma )
-               SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI |
-                                SBIC_MACHINE_DMA_MODE);
-       else
-               SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
-
-
-       /*
-        * select the SCSI bus (it's an error if bus isn't free)
-        */
-       if (sbicselectbus(dev, regs, dev->target, dev->lun,
-           dev->sc_scsiaddr)) {
-/*             printf("sbicgo: Trying to select busy bus!\n"); */
-               return(0); /* Not done: needs to be rescheduled */
-       }
-       dev->sc_stat[0] = 0xff;
-
-       /*
-        * Calculate DMA chains now
-        */
-
-       dmaflags = 0;
-       if (acb->flags & ACB_DATAIN)
-               dmaflags |= DMAGO_READ;
-
-
-       /*
-        * Deal w/bounce buffers.
-        */
-
-       addr = acb->sc_kv.dc_addr;
-       count = acb->sc_kv.dc_count;
-       if (count && (char *)kvtop(addr) != acb->sc_pa.dc_addr) { /* XXXX check */
-               printf("sbic: DMA buffer mapping changed %x->%x\n",
-                   acb->sc_pa.dc_addr, kvtop(addr));
+    /*
+     * select the SCSI bus (it's an error if bus isn't free)
+     */
+    if ( (csr = sbicselectbus(dev)) == 0 )
+        return(0); /* Not done: needs to be rescheduled */
+
+    dev->sc_stat[0] = 0xff;
+
+    /*
+     * Calculate DMA chains now
+     */
+    if ( acb->flags & ACB_DATAIN )
+        dmaflags = DMAGO_READ;
+    else
+        dmaflags = 0;
+
+    addr  = acb->sc_kv.dc_addr;
+    count = acb->sc_kv.dc_count;
+
+    if ( count && ((char *)kvtop(addr) != acb->sc_pa.dc_addr) ) {
+        printf("sbic: DMA buffer mapping changed %x->%x\n",
+                acb->sc_pa.dc_addr, kvtop(addr));
 #ifdef DDB
-               Debugger();
+        Debugger();
 #endif
-       }
+    }
 
 #ifdef DEBUG
-       ++sbicdma_ops;                  /* count total DMA operations */
-#endif
-       if (count && usedma && dev->sc_flags & SBICF_BADDMA &&
-           sbiccheckdmap(addr, count, dev->sc_dmamask)) {
-               /*
-                * need to bounce the dma.
-                */
-               if (dmaflags & DMAGO_READ) {
-                       acb->flags |= ACB_BBUF;
-                       acb->sc_dmausrbuf = addr;
-                       acb->sc_dmausrlen = count;
-                       acb->sc_usrbufpa = (u_char *)kvtop(addr);
-                       if(!dev->sc_tinfo[dev->target].bounce) {
-                               printf("sbicgo: HELP! no bounce allocated for %d\n",
-                                      dev->target);
-                               printf("xfer: (%x->%x,%x)\n", acb->sc_dmausrbuf,
-                                      acb->sc_usrbufpa, acb->sc_dmausrlen);
-#if 0
-                               dev->sc_tinfo[xs->sc_link->target].bounce
-                                       = (char *)alloc_z2mem(MAXPHYS);
-                               if (isztwomem(dev->sc_tinfo[xs->sc_link->target].bounce))
-                                       printf("alloc ZII target %d bounce pa 0x%x\n",
-                                              xs->sc_link->target,
-                                              kvtop(dev->sc_tinfo[xs->sc_link->target].bounce));
-                               else if (dev->sc_tinfo[xs->sc_link->target].bounce)
-                                       printf("alloc CHIP target %d bounce pa 0x%x\n",
-                                              xs->sc_link->target,
-                                              PREP_DMA_MEM(dev->sc_tinfo[xs->sc_link->target].bounce));
+    ++sbicdma_ops;          /* count total DMA operations */
 #endif
 
-                               printf("Allocating %d bounce at %x\n",
-                                      dev->target,
-                                      kvtop(dev->sc_tinfo[dev->target].bounce));
-                       }
-               } else {        /* write: copy to dma buffer */
+    /*
+     * Allocate the DMA chain
+     * Mark end of segment...
+     */
+    acb->sc_tcnt        = dev->sc_tcnt = 0;
+    acb->sc_pa.dc_count = 0;
+
+    sbic_load_ptrs(dev);
+
+    /*
+     * Enable interrupts but don't do any DMA
+     * enintr() also enables interrupts for the sbic
+     */
+    dev->sc_enintr(dev);
+
+    if ( usedma ) {
+        dev->sc_tcnt = dev->sc_dmago(dev, acb->sc_pa.dc_addr,
+                                          acb->sc_pa.dc_count, dmaflags);
 #ifdef DEBUG
-                       if(data_pointer_debug)
-                       printf("sbicgo: copying %x bytes to target %d bounce %x\n",
-                              count, dev->target,
-                              kvtop(dev->sc_tinfo[dev->target].bounce));
+        dev->sc_dmatimo = dev->sc_tcnt ? 1 : 0;
 #endif
-                       bcopy (addr, dev->sc_tinfo[dev->target].bounce, count);
-               }
-               addr = dev->sc_tinfo[dev->target].bounce;/* and use dma buffer */
-               acb->sc_kv.dc_addr = addr;
+    } else
+        dev->sc_dmacmd = 0; /* Don't use DMA */
+
+    acb->sc_dmacmd = dev->sc_dmacmd;
+
 #ifdef DEBUG
-               ++sbicdma_bounces;              /* count number of bounced */
+    if ( data_pointer_debug > 1 ) {
+        printf("sbicgo dmago:%d(%x:%x) dmacmd=0x%02x\n", dev->target,
+                                           dev->sc_cur->dc_addr,
+                                           dev->sc_tcnt,
+                                           dev->sc_dmacmd);
+    }
 #endif
-       }
 
-       /*
-        * Allocate the DMA chain
-        */
+    /*
+     * Lets cycle a while then let the interrupt handler take over.
+     */
+    GET_SBIC_asr(regs, asr);
 
-       /* Set start KVM addresses */
-#if 0
-       acb->sc_kv.dc_addr = addr;
-       acb->sc_kv.dc_count = count;
-#endif
+    do {
 
-       /* Mark end of segment */
-       acb->sc_tcnt = dev->sc_tcnt = 0;
-       acb->sc_pa.dc_count = 0;
-
-       sbic_load_ptrs(dev, regs, dev->target, dev->lun);
-       /* Enable interrupts but don't do any DMA */
-       dev->sc_tcnt = dev->sc_dmago(dev, acb->sc_pa.dc_addr,
-                                    acb->sc_pa.dc_count,
-                                    dmaflags);
-       dev->sc_flags |= SBICF_INDMA;
-        if( !usedma )
-               dev->sc_dmacmd = 0; /* Don't use DMA */
-/*     SBIC_TC_PUT(regs, dev->sc_tcnt); /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-       sbic_save_ptrs(dev, regs, dev->target, dev->lun);
-
-       /*
-        * push the data cache ( I think this won't work (EH))
-        */
-#if defined(M68040)
-       if (mmutype == MMU_68040 && usedma && count) {
-               dma_cachectl(addr, count);
-               if (((u_int)addr & 0xF) || (((u_int)addr + count) & 0xF))
-                       dev->sc_flags |= SBICF_DCFLUSH;
-       }
-#endif
+        QPRINTF(("go "));
 
-       /*
-        * dmago() also enables interrupts for the sbic
-        */
-#ifdef DEBUG
-       if( data_pointer_debug > 1 )
-               printf("sbicgo dmago:%d(%x:%x)\n",
-                      dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt);
-       if( sbic_timeout && !timeout_active ) {
-               timeout((void *)sbictimeout, (void*)dev, sbic_timeout * hz);
-               timeout_active = 1;
-       }
-       debug_asr = asr;
-       debug_csr = csr;
+        /*
+         * Handle the new phase
+         */
+        i = sbicnextstate(dev, csr, asr);
+#if 0
+        WAIT_CIP(regs);
 #endif
+        if ( i == SBIC_STATE_RUNNING ) {
+            GET_SBIC_asr(regs, asr);
 
-       /*
-        * Lets cycle a while then let the interrupt handler take over
-        */
+            if ( asr & SBIC_ASR_LCI )
+                printf("sbicgo: LCI asr:%02x csr:%02x\n", asr, csr);
 
-       GET_SBIC_asr(regs, asr);
-       do {
-               GET_SBIC_csr(regs, csr);
-#ifdef DEBUG
-               debug_csr = csr;
-               routine = 1;
-#endif
-               QPRINTF(("go[0x%x]", csr));
+            if ( asr & SBIC_ASR_INT )
+                GET_SBIC_csr(regs, csr);
+        }
 
-               i = sbicnextstate(dev, csr, asr);
+    } while ( i == SBIC_STATE_RUNNING && asr & (SBIC_ASR_INT|SBIC_ASR_LCI) );
 
-               WAIT_CIP(regs);
-               GET_SBIC_asr(regs, asr);
-#ifdef DEBUG
-               debug_asr = asr;
+    if ( i == SBIC_STATE_DONE ) {
+        if ( dev->sc_stat[0] == 0xff )
+#if 0
+            printf("sbicgo: done & stat = 0xff\n");
+#else
+            ;
 #endif
-               if(asr & SBIC_ASR_LCI) printf("sbicgo: LCI asr:%02x csr:%02x\n",
-                                             asr,csr);
-       } while( i == SBIC_STATE_RUNNING
-               && asr & (SBIC_ASR_INT|SBIC_ASR_LCI) );
-
-       if (i == SBIC_STATE_DONE && dev->sc_stat[0] != 0xff) { 
-               /* Did we really finish that fast? */
-               return 1;
-       }
-       return 0;
+        else
+            return 1;   /* Did we really finish that fast? */
+    }
+
+    return 0;
 }
 
 
 int
 sbicintr(dev)
-       struct sbic_softc *dev;
+    struct sbic_softc   *dev;
 {
-       sbic_regmap_p regs;
-       struct dma_chain *df, *dl;
-       u_char asr, csr, *tmpaddr;
-       struct sbic_acb *acb;
-       int i, newtarget, newlun;
-       unsigned tcnt;
-
-       regs = dev->sc_sbicp;
-
-       /*
-        * pending interrupt?
-        */
-       GET_SBIC_asr (regs, asr);
-       if ((asr & SBIC_ASR_INT) == 0)
-               return(0);
-
-       do {
-               GET_SBIC_csr(regs, csr);
-#ifdef DEBUG
-               debug_csr = csr;
-               routine = 2;
-#endif
-               QPRINTF(("intr[0x%x]", csr));
+    sbic_regmap_p       regs = dev->sc_sbicp;
+    u_char              asr,
+                        csr;
+    int                 i;
 
-               i = sbicnextstate(dev, csr, asr);
+    /*
+     * pending interrupt?
+     */
+    GET_SBIC_asr (regs, asr);
+    if ( (asr & SBIC_ASR_INT) == 0 )
+        return(0);
 
-               WAIT_CIP(regs);
-               GET_SBIC_asr(regs, asr);
-#ifdef DEBUG
-               debug_asr = asr;
-#endif
+    do {
+
+        if ( asr & SBIC_ASR_INT )
+            GET_SBIC_csr(regs, csr);
+
+        QPRINTF(("intr[0x%x]", csr));
+
+        i = sbicnextstate(dev, csr, asr);
 #if 0
-               if(asr & SBIC_ASR_LCI) printf("sbicintr: LCI asr:%02x csr:%02x\n",
-                                             asr,csr);
+        WAIT_CIP(regs);
 #endif
-       } while(i == SBIC_STATE_RUNNING &&
-               asr & (SBIC_ASR_INT|SBIC_ASR_LCI));
-       return(1);
+        GET_SBIC_asr(regs, asr);
+
+    } while ( i == SBIC_STATE_RUNNING && asr & (SBIC_ASR_INT|SBIC_ASR_LCI) );
+
+    QPRINTF(("intr done. state=%d, asr=0x%02x\n", i, asr));
+
+    return(1);
 }
 
 /*
- * Run commands and wait for disconnect
+ * Run commands and wait for disconnect.
+ * This is only ever called when a command is in progress, when we
+ * want to busy wait for it to finish.
  */
 int
 sbicpoll(dev)
-       struct sbic_softc *dev;
+    struct sbic_softc   *dev;
 {
-       sbic_regmap_p regs;
-       u_char asr, csr;
-       struct sbic_pending* pendp;
-       int i;
-       unsigned tcnt;
+    sbic_regmap_p       regs = dev->sc_sbicp;
+    u_char              asr,
+                        csr;
+    int                 i;
 
-       regs = dev->sc_sbicp;
+    /*
+     * Wait for the next interrupt
+     */
+    SBIC_WAIT(regs, SBIC_ASR_INT, sbic_cmd_wait);
 
-       do {
-               GET_SBIC_asr (regs, asr);
-#ifdef DEBUG
-               debug_asr = asr;
-#endif
-               GET_SBIC_csr(regs, csr);
-#ifdef DEBUG
-               debug_csr = csr;
-               routine = 2;
-#endif
-               QPRINTF(("poll[0x%x]", csr));
+    do {
+        GET_SBIC_asr (regs, asr);
+
+        if ( asr & SBIC_ASR_INT )
+            GET_SBIC_csr(regs, csr);
+
+        QPRINTF(("poll[0x%x]", csr));
 
-               i = sbicnextstate(dev, csr, asr);
+        /*
+         * Handle it
+         */
+        i = sbicnextstate(dev, csr, asr);
 
-               WAIT_CIP(regs);
-               GET_SBIC_asr(regs, asr);
-               /* tapes may take a loooong time.. */
-               while (asr & SBIC_ASR_BSY){
-                       if(asr & SBIC_ASR_DBR) {
-                               printf("sbipoll: Waiting while sbic is jammed, CSR:%02x,ASR:%02x\n",
-                                      csr,asr);
+        WAIT_CIP(regs);
+        GET_SBIC_asr(regs, asr);
+
+        /*
+         * tapes may take a loooong time..
+         */
+        while ( asr & SBIC_ASR_BSY ) {
+
+            if ( asr & SBIC_ASR_DBR ) {
+                printf("sbipoll: Waiting while sbic is jammed, CSR:%02x,ASR:%02x\n", csr,asr);
 #ifdef DDB
-                               Debugger();
+                Debugger();
 #endif
-                               /* SBIC is jammed */
-                               /* DUNNO which direction */
-                               /* Try old direction */
-                               GET_SBIC_data(regs,i);
-                               GET_SBIC_asr(regs, asr);
-                               if( asr & SBIC_ASR_DBR) /* Wants us to write */
-                                       SET_SBIC_data(regs,i);
-                       }
-                       GET_SBIC_asr(regs, asr);
-               }
-
-               if(asr & SBIC_ASR_LCI) printf("sbicpoll: LCI asr:%02x csr:%02x\n",
-                                             asr,csr);
-               else if( i == 1 ) /* BSY */
-                       SBIC_WAIT(regs, SBIC_ASR_INT, sbic_cmd_wait);
-       } while(i == SBIC_STATE_RUNNING);
-       return(1);
+                /*
+                 * SBIC is jammed
+                 * DUNNO which direction
+                 * Try old direction
+                 */
+                GET_SBIC_data(regs, i);
+                GET_SBIC_asr(regs, asr);
+
+                if ( asr & SBIC_ASR_DBR ) /* Wants us to write */
+                    SET_SBIC_data(regs, i);
+            }
+
+            GET_SBIC_asr(regs, asr);
+        }
+
+        if ( asr & SBIC_ASR_LCI )
+            printf("sbicpoll: LCI asr:%02x csr:%02x\n", asr,csr);
+        else
+        if ( i == 1 ) /* BSY */
+            SBIC_WAIT(regs, SBIC_ASR_INT, sbic_cmd_wait);
+
+    } while ( i == SBIC_STATE_RUNNING );
+
+    return(1);
 }
 
 /*
  * Handle a single msgin
  */
-
 int
 sbicmsgin(dev)
-       struct sbic_softc *dev;
+    struct sbic_softc   *dev;
 {
-       sbic_regmap_p regs;
-       int recvlen;
-       u_char asr, csr, *tmpaddr;
+    sbic_regmap_p       regs = dev->sc_sbicp;
+    int                 recvlen = 1;
+    u_char              asr,
+                        csr,
+                        *tmpaddr,
+                        *msgaddr;
+
+    tmpaddr = msgaddr = dev->sc_msg;
 
-       regs = dev->sc_sbicp;
+    tmpaddr[0] = 0xff;
+    tmpaddr[1] = 0xff;
 
-       dev->sc_msg[0] = 0xff;
-       dev->sc_msg[1] = 0xff;
+    GET_SBIC_asr(regs, asr);
 
-       GET_SBIC_asr(regs, asr);
 #ifdef DEBUG
-       if(reselect_debug>1)
-               printf("sbicmsgin asr=%02x\n", asr);
+    if ( reselect_debug > 1 )
+        printf("sbicmsgin asr=%02x\n", asr);
 #endif
 
-       sbic_save_ptrs(dev, regs, dev->target, dev->lun);
-
-       GET_SBIC_selid (regs, csr);
-       SET_SBIC_selid (regs, csr | SBIC_SID_FROM_SCSI);
-
-       SBIC_TC_PUT(regs, 0);
-       tmpaddr = dev->sc_msg;
-       recvlen = 1;
-       do {
-               while( recvlen-- ) {
-                       GET_SBIC_asr(regs, asr);
-                       GET_SBIC_csr(regs, csr);
-                       QPRINTF(("sbicmsgin ready to go (csr,asr)=(%02x,%02x)\n",
-                                csr, asr));
-
-                       RECV_BYTE(regs, *tmpaddr);
-#if 1
-                       /*
-                        * get the command completion interrupt, or we
-                        * can't send a new command (LCI)
-                        */
-                       SBIC_WAIT(regs, SBIC_ASR_INT, 0);
-                       GET_SBIC_csr(regs, csr);
-#else
-                       WAIT_CIP(regs);
-                       do {
-                               GET_SBIC_asr(regs, asr);
-                               csr = 0xff;
-                               GET_SBIC_csr(regs, csr);
-                               if( csr == 0xff )
-                                       printf("sbicmsgin waiting: csr %02x asr %02x\n", csr, asr);
-                       } while( csr == 0xff );
-#endif
+    GET_SBIC_selid (regs, csr);
+    SET_SBIC_selid (regs, csr | SBIC_SID_FROM_SCSI);
+
+    SBIC_TC_PUT(regs, 0);
+    SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
+
+    do {
+        while( recvlen-- ) {
+
+            /*
+             * Fetch the next byte of the message
+             */
+            RECV_BYTE(regs, *tmpaddr);
+
+            /*
+             * get the command completion interrupt, or we
+             * can't send a new command (LCI)
+             */
+            SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+            GET_SBIC_csr(regs, csr);
+
 #ifdef DEBUG
-                       if(reselect_debug>1)
-                               printf("sbicmsgin: got %02x csr %02x asr %02x\n",
-                                      *tmpaddr, csr, asr);
-#endif
-#if do_parity_check
-                       if( asr & SBIC_ASR_PE ) {
-                               printf ("Parity error");
-                               /* This code simply does not work. */
-                               WAIT_CIP(regs);
-                               SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
-                               WAIT_CIP(regs);
-                               GET_SBIC_asr(regs, asr);
-                               WAIT_CIP(regs);
-                               SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
-                               WAIT_CIP(regs);
-                               if( !(asr & SBIC_ASR_LCI) )
-                                       /* Target wants to send garbled msg*/
-                                       continue;
-                               printf("--fixing\n");
-                               /* loop until a msgout phase occurs on target */
-                               while(csr & 0x07 != MESG_OUT_PHASE) {
-                                       while( asr & SBIC_ASR_BSY &&
-                                             !(asr & SBIC_ASR_DBR|SBIC_ASR_INT) )
-                                               GET_SBIC_asr(regs, asr);
-                                       if( asr & SBIC_ASR_DBR )
-                                               panic("msgin: jammed again!\n");
-                                       GET_SBIC_csr(regs, csr);
-                                       if( csr & 0x07 != MESG_OUT_PHASE ) {
-                                               sbicnextstate(dev, csr, asr);
-                                               sbic_save_ptrs(dev, regs,
-                                                              dev->target,
-                                                              dev->lun);
-                                       }
-                               }
-                               /* Should be msg out by now */
-                               SEND_BYTE(regs, MSG_PARITY_ERROR);
-                       }
-                       else
+            if ( reselect_debug > 1 )
+                printf("sbicmsgin: got %02x csr %02x\n", *tmpaddr, csr);
 #endif
-                               tmpaddr++;
-
-                       if(recvlen) {
-                               /* Clear ACK */
-                               WAIT_CIP(regs);
-                               GET_SBIC_asr(regs, asr);
-                               GET_SBIC_csr(regs, csr);
-                               QPRINTF(("sbicmsgin pre byte CLR_ACK (csr,asr)=(%02x,%02x)\n",
-                                        csr, asr));
-                               SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
-                               SBIC_WAIT(regs, SBIC_ASR_INT, 0);
-                       }
-
-               };
-
-               if(dev->sc_msg[0] == 0xff) {
-                       printf("sbicmsgin: sbic swallowed our message\n");
-                       break;
-               }
+
+            tmpaddr++;
+
+            if ( recvlen ) {
+                /*
+                 * Clear ACK, and wait for the interrupt for the next byte
+                 */
+                SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
+                SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+                GET_SBIC_csr(regs, csr);
+            }
+        }
+
+        if ( msgaddr[0] == 0xff ) {
+            printf("sbicmsgin: sbic swallowed our message\n");
+            break;
+        }
+
 #ifdef DEBUG
-               if (sync_debug)
-                       printf("msgin done csr 0x%x asr 0x%x msg 0x%x\n",
-                              csr, asr, dev->sc_msg[0]);
-#endif
-               /*
-                * test whether this is a reply to our sync
-                * request
-                */
-               if (MSG_ISIDENTIFY(dev->sc_msg[0])) {
-                       QPRINTF(("IFFY"));
-#if 0
-                       /* There is an implied load-ptrs here */
-                       sbic_load_ptrs(dev, regs, dev->target, dev->lun);
-#endif
-                       /* Got IFFY msg -- ack it */
-               } else if (dev->sc_msg[0] == MSG_REJECT
-                          && dev->sc_sync[dev->target].state == SYNC_SENT) {
-                       QPRINTF(("REJECT of SYN"));
+        if ( sync_debug ) {
+            GET_SBIC_asr(regs, asr);
+            printf("msgin done csr 0x%x asr 0x%x msg 0x%x\n", csr, asr, msgaddr[0]);
+        }
+#endif
+        /*
+         * test whether this is a reply to our sync
+         * request
+         */
+        if ( MSG_ISIDENTIFY(msgaddr[0]) ) {
+
+            /*
+             * Got IFFY msg -- ack it
+             */
+            QPRINTF(("IFFY"));
+
+        } else
+        if ( msgaddr[0] == MSG_REJECT &&
+             dev->sc_sync[dev->target].state == SYNC_SENT) {
+
+            /*
+             * Target probably rejected our Sync negotiation.
+             */
+            QPRINTF(("REJECT of SYN"));
+
 #ifdef DEBUG
-                       if (sync_debug)
-                               printf("target %d rejected sync, going async\n",
-                                      dev->target);
+            if ( sync_debug )
+                printf("target %d rejected sync, going async\n", dev->target);
 #endif
-                       dev->sc_sync[dev->target].period = sbic_min_period;
-                       dev->sc_sync[dev->target].offset = 0;
-                       dev->sc_sync[dev->target].state = SYNC_DONE;
-                       SET_SBIC_syn(regs,
-                                    SBIC_SYN(dev->sc_sync[dev->target].offset,
-                                             dev->sc_sync[dev->target].period));
-               } else if ((dev->sc_msg[0] == MSG_REJECT)) {
-                       QPRINTF(("REJECT"));
-                       /*
-                        * we'll never REJECt a REJECT message..
-                        */
-               } else if ((dev->sc_msg[0] == MSG_SAVE_DATA_PTR)) {
-                       QPRINTF(("MSG_SAVE_DATA_PTR"));
-                       /*
-                        * don't reject this either.
-                        */
-               } else if ((dev->sc_msg[0] == MSG_DISCONNECT)) {
-                       QPRINTF(("DISCONNECT"));
+
+            dev->sc_sync[dev->target].period = sbic_min_period;
+            dev->sc_sync[dev->target].offset = 0;
+            dev->sc_sync[dev->target].state  = SYNC_DONE;
+            SET_SBIC_syn(regs, SBIC_SYN(dev->sc_sync[dev->target].offset,
+                                        dev->sc_sync[dev->target].period));
+
+        } else
+        if ( msgaddr[0] == MSG_REJECT ) {
+
+            /*
+             * we'll never REJECt a REJECT message..
+             */
+            QPRINTF(("REJECT"));
+
+        } else
+        if ( msgaddr[0] == MSG_SAVE_DATA_PTR ) {
+
+            /*
+             * don't reject this either.
+             */
+            QPRINTF(("MSG_SAVE_DATA_PTR"));
+
+        } else
+        if ( msgaddr[0] == MSG_RESTORE_PTR ) {
+
+            /*
+             * don't reject this either.
+             */
+            QPRINTF(("MSG_RESTORE_PTR"));
+
+        } else
+        if ( msgaddr[0] == MSG_DISCONNECT ) {
+
+            /*
+             * Target is disconnecting...
+             */
+            QPRINTF(("DISCONNECT"));
+
 #ifdef DEBUG
-                       if( reselect_debug>1 && dev->sc_msg[0] == MSG_DISCONNECT )
-                               printf("sbicmsgin: got disconnect msg %s\n",
-                                      (dev->sc_flags & SBICF_ICMD)?"rejecting":"");
-#endif
-                       if( dev->sc_flags & SBICF_ICMD ) {
-                               /* We're in immediate mode. Prevent disconnects. */
-                               /* prepare to reject the message, NACK */
-                               SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
-                               WAIT_CIP(regs);
-                       }
-               } else if (dev->sc_msg[0] == MSG_CMD_COMPLETE ) {
-                       QPRINTF(("CMD_COMPLETE"));
-                       /* !! KLUDGE ALERT !! quite a few drives don't seem to
-                        * really like the current way of sending the
-                        * sync-handshake together with the ident-message, and
-                        * they react by sending command-complete and
-                        * disconnecting right after returning the valid sync
-                        * handshake. So, all I can do is reselect the drive,
-                        * and hope it won't disconnect again. I don't think
-                        * this is valid behavior, but I can't help fixing a
-                        * problem that apparently exists.
-                        *
-                        * Note: we should not get here on `normal' command
-                        * completion, as that condition is handled by the
-                        * high-level sel&xfer resume command used to walk
-                        * thru status/cc-phase.
-                        */
+            if ( reselect_debug > 1 && msgaddr[0] == MSG_DISCONNECT )
+                printf("sbicmsgin: got disconnect msg %s\n",
+                       (dev->sc_flags & SBICF_ICMD) ? "rejecting" : "");
+#endif
+
+            if ( dev->sc_flags & SBICF_ICMD ) {
+                /*
+                 * We're in immediate mode. Prevent disconnects.
+                 * prepare to reject the message, NACK
+                 */
+                SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
+                WAIT_CIP(regs);
+            }
+
+        } else
+        if ( msgaddr[0] == MSG_CMD_COMPLETE ) {
+
+            /*
+             * !! KLUDGE ALERT !! quite a few drives don't seem to
+             * really like the current way of sending the
+             * sync-handshake together with the ident-message, and
+             * they react by sending command-complete and
+             * disconnecting right after returning the valid sync
+             * handshake. So, all I can do is reselect the drive,
+             * and hope it won't disconnect again. I don't think
+             * this is valid behavior, but I can't help fixing a
+             * problem that apparently exists.
+             *
+             * Note: we should not get here on `normal' command
+             * completion, as that condition is handled by the
+             * high-level sel&xfer resume command used to walk
+             * thru status/cc-phase.
+             */
+            QPRINTF(("CMD_COMPLETE"));
 
 #ifdef DEBUG
-                       if (sync_debug)
-                               printf ("GOT MSG %d! target %d acting weird.."
-                                       " waiting for disconnect...\n",
-                                       dev->sc_msg[0], dev->target);
-#endif
-                       /* Check to see if sbic is handling this */
-                       GET_SBIC_asr(regs, asr);
-                       if(asr & SBIC_ASR_BSY)
-                               return SBIC_STATE_RUNNING;
-
-                       /* Let's try this: Assume it works and set status to 00 */
-                       dev->sc_stat[0] = 0;
-               } else if (dev->sc_msg[0] == MSG_EXT_MESSAGE
-                          && tmpaddr == &dev->sc_msg[1]) {
-                       QPRINTF(("ExtMSG\n"));
-                       /* Read in whole extended message */
-                       SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
-                       SBIC_WAIT(regs, SBIC_ASR_INT, 0);
-                       GET_SBIC_asr(regs, asr);
-                       GET_SBIC_csr(regs, csr);
-                       QPRINTF(("CLR ACK asr %02x, csr %02x\n", asr, csr));
-                       RECV_BYTE(regs, *tmpaddr);
-                       /* Wait for command completion IRQ */
-                       SBIC_WAIT(regs, SBIC_ASR_INT, 0);
-                       recvlen = *tmpaddr++;
-                       QPRINTF(("Recving ext msg, asr %02x csr %02x len %02x\n",
-                              asr, csr, recvlen));
-               } else if (dev->sc_msg[0] == MSG_EXT_MESSAGE && dev->sc_msg[1] == 3
-                          && dev->sc_msg[2] == MSG_SYNC_REQ) {
-                       QPRINTF(("SYN"));
-                       dev->sc_sync[dev->target].period =
-                               sbicfromscsiperiod(dev,
-                                                  regs, dev->sc_msg[3]);
-                       dev->sc_sync[dev->target].offset = dev->sc_msg[4];
-                       dev->sc_sync[dev->target].state = SYNC_DONE;
-                       SET_SBIC_syn(regs,
-                                    SBIC_SYN(dev->sc_sync[dev->target].offset,
-                                             dev->sc_sync[dev->target].period));
-                       printf("%s: target %d now synchronous,"
-                              " period=%dns, offset=%d.\n",
-                              dev->sc_dev.dv_xname, dev->target,
-                              dev->sc_msg[3] * 4, dev->sc_msg[4]);
-               } else {
+            if ( sync_debug )
+                printf ("GOT MSG %d! target %d acting weird.."
+                        " waiting for disconnect...\n", msgaddr[0], dev->target);
+#endif
+
+            /*
+             * Check to see if sbic is handling this
+             */
+            GET_SBIC_asr(regs, asr);
+
+            /*
+             * XXXSCW: I'm not convinced of this, we haven't negated ACK yet...
+             */
+            if ( asr & SBIC_ASR_BSY )
+                return SBIC_STATE_RUNNING;
+
+            /*
+             * Let's try this: Assume it works and set status to 00
+             */
+            dev->sc_stat[0] = 0;
+
+        } else
+        if ( msgaddr[0] == MSG_EXT_MESSAGE && tmpaddr == &(msgaddr[1]) ) {
+
+            /*
+             * Target is sending us an extended message. We'll assume it's
+             * the response to our Sync. negotiation.
+             */
+            QPRINTF(("ExtMSG\n"));
+
+            /*
+             * Read in whole extended message. First, negate ACK to accept
+             * the MSG_EXT_MESSAGE byte...
+             */
+            SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
+
+            /*
+             * Wait for the interrupt for the next byte (length)
+             */
+            SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+            GET_SBIC_csr(regs, csr);
+
+#ifdef  DEBUG
+            QPRINTF(("CLR ACK csr %02x\n", csr));
+#endif
+
+            /*
+             * Read the length byte
+             */
+            RECV_BYTE(regs, *tmpaddr);
+
+            /*
+             * Wait for command completion IRQ
+             */
+            SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+            GET_SBIC_csr(regs, csr);
+
+            /*
+             * Reload the loop counter
+             */
+            recvlen = *tmpaddr++;
+
+            QPRINTF(("Recving ext msg, csr %02x len %02x\n", csr, recvlen));
+
+        } else
+        if ( msgaddr[0] == MSG_EXT_MESSAGE && msgaddr[1] == 3 &&
+             msgaddr[2] == MSG_SYNC_REQ ) {
+
+            /*
+             * We've received the complete Extended Message Sync. Request...
+             */
+            QPRINTF(("SYN"));
+
+            /*
+             * Compute the required Transfer Period for the WD chip...
+             */
+            dev->sc_sync[dev->target].period = sbicfromscsiperiod(dev, msgaddr[3]);
+            dev->sc_sync[dev->target].offset = msgaddr[4];
+            dev->sc_sync[dev->target].state  = SYNC_DONE;
+
+            /*
+             * Put the WD chip in synchronous mode
+             */
+            SET_SBIC_syn(regs, SBIC_SYN(dev->sc_sync[dev->target].offset,
+                                        dev->sc_sync[dev->target].period));
+
+            printf("%s: target %d now synchronous, period=%dns, offset=%d.\n",
+                   dev->sc_dev.dv_xname, dev->target,
+                   msgaddr[3] * 4, msgaddr[4]);
+
+        } else {
+
+            /*
+             * We don't support whatever this message is...
+             */
 #ifdef DEBUG
-                       if (sbic_debug || sync_debug)
-                               printf ("sbicmsgin: Rejecting message 0x%02x\n",
-                                       dev->sc_msg[0]);
-#endif
-                       /* prepare to reject the message, NACK */
-                       SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
-                       WAIT_CIP(regs);
-               }
-               /* Clear ACK */
-               WAIT_CIP(regs);
-               GET_SBIC_asr(regs, asr);
-               GET_SBIC_csr(regs, csr);
-               QPRINTF(("sbicmsgin pre CLR_ACK (csr,asr)=(%02x,%02x)%d\n",
-                        csr, asr, recvlen));
-               SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
-               SBIC_WAIT(regs, SBIC_ASR_INT, 0);
-       }
-#if 0
-       while((csr == SBIC_CSR_MSGIN_W_ACK)
-             || (SBIC_PHASE(csr) == MESG_IN_PHASE));
-#else
-       while (recvlen>0);
-#endif
-
-       QPRINTF(("sbicmsgin finished: csr %02x, asr %02x\n",csr, asr));
-
-       /* Should still have one CSR to read */
-       return SBIC_STATE_RUNNING;
+            if ( sbic_debug || sync_debug )
+                printf ("sbicmsgin: Rejecting message 0x%02x\n", msgaddr[0]);
+#endif
+
+            /*
+             * prepare to reject the message, NACK
+             */
+            SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
+            WAIT_CIP(regs);
+        }
+
+        /*
+         * Negate ACK to complete the transfer
+         */
+        SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
+
+        /*
+         * Wait for the interrupt for the next byte, or phase change.
+         * Only read the CSR if we have more data to transfer.
+         * XXXSCW: We should really verify that we're still in MSG IN phase
+         * before blindly going back around this loop, but that would mean
+         * we read the CSR... <sigh>
+         */
+        SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+        if ( recvlen > 0 )
+            GET_SBIC_csr(regs, csr);
+
+    } while ( recvlen > 0 );
+
+    /*
+     * Should still have one CSR to read
+     */
+    return SBIC_STATE_RUNNING;
 }
 
 
 /*
  * sbicnextstate()
  * return:
- *             0  == done
- *             1  == working
- *             2  == disconnected
- *             -1 == error
+ *      0  == done
+ *      1  == working
+ *      2  == disconnected
+ *      -1 == error
  */
 int
 sbicnextstate(dev, csr, asr)
-       struct sbic_softc *dev;
-       u_char csr, asr;
+    struct sbic_softc   *dev;
+    u_char              csr,
+                        asr;
 {
-       sbic_regmap_p regs;
-       struct dma_chain *df, *dl;
-       struct sbic_acb *acb;
-       int i, newtarget, newlun, wait;
-       unsigned tcnt;
-
-       regs = dev->sc_sbicp;
-       acb = dev->sc_nexus;
-
-       QPRINTF(("next[%02x,%02x]",asr,csr));
-
-       switch (csr) {
-       case SBIC_CSR_XFERRED|CMD_PHASE:
-       case SBIC_CSR_MIS|CMD_PHASE:
-       case SBIC_CSR_MIS_1|CMD_PHASE:
-       case SBIC_CSR_MIS_2|CMD_PHASE:
-               sbic_save_ptrs(dev, regs, dev->target, dev->lun);
-               if (sbicxfstart(regs, acb->clen, CMD_PHASE, sbic_cmd_wait))
-                       if (sbicxfout(regs, acb->clen,
-                                     &acb->cmd, CMD_PHASE))
-                               goto abort;
-               break;
-
-       case SBIC_CSR_XFERRED|STATUS_PHASE:
-       case SBIC_CSR_MIS|STATUS_PHASE:
-       case SBIC_CSR_MIS_1|STATUS_PHASE:
-       case SBIC_CSR_MIS_2|STATUS_PHASE:
-               /*
-                * this should be the normal i/o completion case.
-                * get the status & cmd complete msg then let the
-                * device driver look at what happened.
-                */
-               sbicxfdone(dev,regs,dev->target);
-               /*
-                * check for overlapping cache line, flush if so
-                */
-#ifdef M68040
-               if (dev->sc_flags & SBICF_DCFLUSH) {
-#if 0
-                       printf("sbic: 68040 DMA cache flush needs fixing? %x:%x\n",
-                           dev->sc_xs->data, dev->sc_xs->datalen);
-#endif
-               }
-#endif
+    sbic_regmap_p       regs = dev->sc_sbicp;
+    struct sbic_acb     *acb = dev->sc_nexus;
+
+    QPRINTF(("next[%02x,%02x]: ",asr,csr));
+
+    switch (csr) {
+
+      case SBIC_CSR_XFERRED | CMD_PHASE:
+      case SBIC_CSR_MIS     | CMD_PHASE:
+      case SBIC_CSR_MIS_1   | CMD_PHASE:
+      case SBIC_CSR_MIS_2   | CMD_PHASE:
+        {
+            if ( sbicxfout(regs, acb->clen, &acb->cmd) )
+                goto abort;
+        }
+        break;
+
+      case SBIC_CSR_XFERRED | STATUS_PHASE:
+      case SBIC_CSR_MIS     | STATUS_PHASE:
+      case SBIC_CSR_MIS_1   | STATUS_PHASE:
+      case SBIC_CSR_MIS_2   | STATUS_PHASE:
+        {
+            SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
+
+            /*
+             * this should be the normal i/o completion case.
+             * get the status & cmd complete msg then let the
+             * device driver look at what happened.
+             */
+            sbicxfdone(dev);
+
 #ifdef DEBUG
-               if( data_pointer_debug > 1 )
-                       printf("next dmastop: %d(%x:%x)\n",
-                              dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt);
-#endif
-               dev->sc_dmastop(dev); /* was dmafree */
-               if (acb->flags & ACB_BBUF) {
-                       if ((u_char *)kvtop(acb->sc_dmausrbuf) != acb->sc_usrbufpa)
-                               printf("%s: WARNING - buffer mapping changed %x->%x\n",
-                                   dev->sc_dev.dv_xname, acb->sc_usrbufpa,
-                                   kvtop(acb->sc_dmausrbuf));
+            dev->sc_dmatimo = 0;
+            if ( data_pointer_debug > 1 )
+                printf("next dmastop: %d(%x:%x)\n", dev->target,
+                                                    dev->sc_cur->dc_addr,
+                                                    dev->sc_tcnt);
+#endif
+            /*
+             * Stop the DMA chip
+             */
+            dev->sc_dmastop(dev);
+
+            dev->sc_flags &= ~(SBICF_INDMA | SBICF_DCFLUSH);
+
+            /*
+             * Indicate to the upper layers that the command is done
+             */
+            sbic_scsidone(acb, dev->sc_stat[0]);
+
+            return SBIC_STATE_DONE;
+        }
+
+      case SBIC_CSR_XFERRED | DATA_OUT_PHASE:
+      case SBIC_CSR_XFERRED | DATA_IN_PHASE:
+      case SBIC_CSR_MIS     | DATA_OUT_PHASE:
+      case SBIC_CSR_MIS     | DATA_IN_PHASE:
+      case SBIC_CSR_MIS_1   | DATA_OUT_PHASE:
+      case SBIC_CSR_MIS_1   | DATA_IN_PHASE:
+      case SBIC_CSR_MIS_2   | DATA_OUT_PHASE:
+      case SBIC_CSR_MIS_2   | DATA_IN_PHASE:
+        {
+            /*
+             * Verify that we expected to transfer data...
+             */
+            if ( acb->sc_kv.dc_count <= 0 ) {
+                printf("next: DATA phase with xfer count == %d, asr:0x%02x csr:0x%02x\n",
+                        acb->sc_kv.dc_count, asr, csr);
+                goto abort;
+            }
+
+            /*
+             * Should we transfer using PIO or DMA ?
+             */
+            if ( dev->sc_xs->flags & SCSI_POLL || dev->sc_flags & SBICF_ICMD ||
+                 acb->sc_dmacmd == 0 ) {
+
+                /*
+                 * Do PIO transfer
+                 */
+                int     i;
+
 #ifdef DEBUG
-                       if(data_pointer_debug)
-                       printf("sbicgo:copying %x bytes from target %d bounce %x\n",
-                              acb->sc_dmausrlen,
-                              dev->target,
-                              kvtop(dev->sc_tinfo[dev->target].bounce));
-#endif
-                       bcopy(dev->sc_tinfo[dev->target].bounce,
-                             acb->sc_dmausrbuf,
-                             acb->sc_dmausrlen);
-               }
-               dev->sc_flags &= ~(SBICF_INDMA | SBICF_DCFLUSH);
-               sbic_scsidone(acb, dev->sc_stat[0]);
-               return SBIC_STATE_DONE;
-
-       case SBIC_CSR_XFERRED|DATA_OUT_PHASE:
-       case SBIC_CSR_XFERRED|DATA_IN_PHASE:
-       case SBIC_CSR_MIS|DATA_OUT_PHASE:
-       case SBIC_CSR_MIS|DATA_IN_PHASE:
-       case SBIC_CSR_MIS_1|DATA_OUT_PHASE:
-       case SBIC_CSR_MIS_1|DATA_IN_PHASE:
-       case SBIC_CSR_MIS_2|DATA_OUT_PHASE:
-       case SBIC_CSR_MIS_2|DATA_IN_PHASE:
-               if( dev->sc_xs->flags & SCSI_POLL || dev->sc_flags & SBICF_ICMD
-                  || acb->sc_dmacmd == 0 ) {
-                       /* Do PIO */
-                       SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
-                       if (acb->sc_kv.dc_count <= 0) {
-                               printf("sbicnextstate:xfer count %d asr%x csr%x\n",
-                                      acb->sc_kv.dc_count, asr, csr);
-                               goto abort;
-                       }
-                       wait = sbic_data_wait;
-                       if( sbicxfstart(regs,
-                                       acb->sc_kv.dc_count,
-                                       SBIC_PHASE(csr), wait))
-                               if( SBIC_PHASE(csr) == DATA_IN_PHASE )
-                                       /* data in? */
-                                       i=sbicxfin(regs,
-                                                  acb->sc_kv.dc_count,
-                                                  acb->sc_kv.dc_addr);
-                               else
-                                       i=sbicxfout(regs,
-                                                   acb->sc_kv.dc_count,
-                                                   acb->sc_kv.dc_addr,
-                                                   SBIC_PHASE(csr));
-                       acb->sc_kv.dc_addr +=
-                               (acb->sc_kv.dc_count - i);
-                       acb->sc_kv.dc_count = i;
-               } else {
-                       /*
-                        * do scatter-gather dma
-                        * hacking the controller chip, ouch..
-                        */
-                       SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI |
-                                        SBIC_MACHINE_DMA_MODE);
-                       /*
-                        * set next dma addr and dec count
-                        */
-#if 0
-                       SBIC_TC_GET(regs, tcnt);
-                       dev->sc_cur->dc_count -= ((dev->sc_tcnt - tcnt) >> 1);
-                       dev->sc_cur->dc_addr += (dev->sc_tcnt - tcnt);
-                       dev->sc_tcnt = acb->sc_tcnt = tcnt;
-#else
-                       sbic_save_ptrs(dev, regs, dev->target, dev->lun);
-                       sbic_load_ptrs(dev, regs, dev->target, dev->lun);
-#endif
+                if ( data_pointer_debug > 1 )
+                    printf("next PIO: %d(%x:%x)\n", dev->target,
+                                                    acb->sc_kv.dc_addr,
+                                                    acb->sc_kv.dc_count);
+#endif
+
+                if ( SBIC_PHASE(csr) == DATA_IN_PHASE )
+                    /*
+                     * data in
+                     */
+                    i = sbicxfin(regs, acb->sc_kv.dc_count,
+                                       acb->sc_kv.dc_addr);
+                else
+                    /*
+                     * data out
+                     */
+                    i = sbicxfout(regs, acb->sc_kv.dc_count,
+                                        acb->sc_kv.dc_addr);
+
+                acb->sc_kv.dc_addr += (acb->sc_kv.dc_count - i);
+                acb->sc_kv.dc_count = i;
+
+                /*
+                 * Update current count...
+                 */
+                acb->sc_tcnt = dev->sc_tcnt = i;
+
+                dev->sc_flags &= ~SBICF_INDMA;
+
+            } else {
+
+                /*
+                 * Do DMA transfer
+                 * set next dma addr and dec count
+                 */
+                sbic_save_ptrs(dev);
+                sbic_load_ptrs(dev);
+
+                SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI |
+                                       SBIC_MACHINE_DMA_MODE);
+
 #ifdef DEBUG
-                       if( data_pointer_debug > 1 )
-                               printf("next dmanext: %d(%x:%x)\n",
-                                      dev->target,dev->sc_cur->dc_addr,
-                                      dev->sc_tcnt);
-#endif
-                       dev->sc_tcnt = dev->sc_dmanext(dev);
-                       SBIC_TC_PUT(regs, (unsigned)dev->sc_tcnt);
-                       SET_SBIC_cmd(regs, SBIC_CMD_XFER_INFO);
-                       dev->sc_flags |= SBICF_INDMA;
-               }
-               break;
-
-       case SBIC_CSR_XFERRED|MESG_IN_PHASE:
-       case SBIC_CSR_MIS|MESG_IN_PHASE:
-       case SBIC_CSR_MIS_1|MESG_IN_PHASE:
-       case SBIC_CSR_MIS_2|MESG_IN_PHASE:
-               return sbicmsgin(dev);
-
-       case SBIC_CSR_MSGIN_W_ACK:
-               SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK); /* Dunno what I'm ACKing */
-               printf("Acking unknown msgin CSR:%02x",csr);
-               break;
-
-       case SBIC_CSR_XFERRED|MESG_OUT_PHASE:
-       case SBIC_CSR_MIS|MESG_OUT_PHASE:
-       case SBIC_CSR_MIS_1|MESG_OUT_PHASE:
-       case SBIC_CSR_MIS_2|MESG_OUT_PHASE:
+                dev->sc_dmatimo = 1;
+                if ( data_pointer_debug > 1 )
+                    printf("next DMA: %d(%x:%x)\n", dev->target,
+                                                    dev->sc_cur->dc_addr,
+                                                    dev->sc_tcnt);
+#endif
+                /*
+                 * Start the DMA chip going
+                 */
+                dev->sc_tcnt = dev->sc_dmanext(dev);
+
+                /*
+                 * Tell the WD chip how much to transfer this time around
+                 */
+                SBIC_TC_PUT(regs, (unsigned)dev->sc_tcnt);
+
+                /*
+                 * Start the transfer
+                 */
+                SET_SBIC_cmd(regs, SBIC_CMD_XFER_INFO);
+
+                /*
+                 * Indicate that we're in DMA mode
+                 */
+                dev->sc_flags |= SBICF_INDMA;
+            }
+        }
+        break;
+
+      case SBIC_CSR_XFERRED | MESG_IN_PHASE:
+      case SBIC_CSR_MIS     | MESG_IN_PHASE:
+      case SBIC_CSR_MIS_1   | MESG_IN_PHASE:
+      case SBIC_CSR_MIS_2   | MESG_IN_PHASE:
+        {
+            sbic_save_ptrs(dev);
+
+            /*
+             * Handle a single message in...
+             */
+            return sbicmsgin(dev);
+        }
+
+      case SBIC_CSR_MSGIN_W_ACK:
+        {
+            /*
+             * We should never see this since it's handled in 'sbicmsgin()'
+             * but just for the sake of paranoia...
+             */
+            SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK); /* Dunno what I'm ACKing */
+            printf("Acking unknown msgin CSR:%02x",csr);
+        }
+        break;
+
+      case SBIC_CSR_XFERRED | MESG_OUT_PHASE:
+      case SBIC_CSR_MIS     | MESG_OUT_PHASE:
+      case SBIC_CSR_MIS_1   | MESG_OUT_PHASE:
+      case SBIC_CSR_MIS_2   | MESG_OUT_PHASE:
+        {
+            /*
+             * We only ever handle a message out phase here for sending a
+             * REJECT message.
+             */
+            sbic_save_ptrs(dev);
+
 #ifdef DEBUG
-               if (sync_debug)
-                       printf ("sending REJECT msg to last msg.\n");
+            if (sync_debug)
+                printf ("sending REJECT msg to last msg.\n");
 #endif
 
-               sbic_save_ptrs(dev, regs, dev->target, dev->lun);
-               /*
-                * should only get here on reject,
-                * since it's always US that
-                * initiate a sync transfer
-                */
-               SEND_BYTE(regs, MSG_REJECT);
-               WAIT_CIP(regs);
-               if( asr & (SBIC_ASR_BSY|SBIC_ASR_LCI|SBIC_ASR_CIP) )
-                       printf("next: REJECT sent asr %02x\n", asr);
-               return SBIC_STATE_RUNNING;
-
-       case SBIC_CSR_DISC:
-       case SBIC_CSR_DISC_1:
-               dev->sc_flags &= ~(SBICF_INDMA|SBICF_SELECTED);
-
-               /* Try to schedule another target */
+            SEND_BYTE(regs, MSG_REJECT);
+            WAIT_CIP(regs);
+        }
+        break;
+
+      case SBIC_CSR_DISC:
+      case SBIC_CSR_DISC_1:
+        {
+            /*
+             * Try to schedule another target
+             */
+            sbic_save_ptrs(dev);
+
+            dev->sc_flags &= ~SBICF_SELECTED;
+
 #ifdef DEBUG
-               if(reselect_debug>1)
-                       printf("sbicnext target %d disconnected\n", dev->target);
+            if ( reselect_debug > 1 )
+                printf("sbicnext target %d disconnected\n", dev->target);
 #endif
-               TAILQ_INSERT_HEAD(&dev->nexus_list, acb, chain);
-               ++dev->sc_tinfo[dev->target].dconns;
-               dev->sc_nexus = NULL;
-               dev->sc_xs = NULL;
-
-               if( acb->xs->flags & SCSI_POLL
-                  || (dev->sc_flags & SBICF_ICMD)
-                  || !sbic_parallel_operations )
-                       return SBIC_STATE_DISCONNECT;
-               sbic_sched(dev);
-               return SBIC_STATE_DISCONNECT;
-
-       case SBIC_CSR_RSLT_NI:
-       case SBIC_CSR_RSLT_IFY:
-               GET_SBIC_rselid(regs, newtarget);
-               /* check SBIC_RID_SIV? */
-               newtarget &= SBIC_RID_MASK;
-               if (csr == SBIC_CSR_RSLT_IFY) {
-                       /* Read IFY msg to avoid lockup */
-                       GET_SBIC_data(regs, newlun);
-                       WAIT_CIP(regs);
-                       newlun &= SBIC_TLUN_MASK;
-               } else {
-                       /* Need to get IFY message */
-                       for (newlun = 256; newlun; --newlun) {
-                               GET_SBIC_asr(regs, asr);
-                               if (asr & SBIC_ASR_INT)
-                                       break;
-                               delay(1);
-                       }
-                       newlun = 0;     /* XXXX */
-                       if ((asr & SBIC_ASR_INT) == 0) {
+
+            TAILQ_INSERT_HEAD(&dev->nexus_list, acb, chain);
+
+            ++dev->sc_tinfo[dev->target].dconns;
+
+            dev->sc_nexus = NULL;
+            dev->sc_xs    = NULL;
+
+            if ( acb->xs->flags & SCSI_POLL || dev->sc_flags & SBICF_ICMD ||
+                                               !sbic_parallel_operations )
+                return SBIC_STATE_DISCONNECT;
+
+            QPRINTF(("sbicnext: calling sbic_sched\n"));
+
+            sbic_sched(dev);
+
+            QPRINTF(("sbicnext: sbic_sched returned\n"));
+
+            return SBIC_STATE_DISCONNECT;
+        }
+
+      case SBIC_CSR_RSLT_NI:
+      case SBIC_CSR_RSLT_IFY:
+        {
+            /*
+             * A reselection.
+             * Note that since we don't enable Advanced Features (assuming
+             * the WD chip is at least the 'A' revision), we're only ever
+             * likely to see the 'SBIC_CSR_RSLT_NI' status. But for the
+             * hell of it, we'll handle it anyway, for all the extra code
+             * it needs...
+             */
+            u_char  newtarget,
+                    newlun;
+
+            GET_SBIC_rselid(regs, newtarget);
+
+            /*
+             * check SBIC_RID_SIV?
+             */
+            newtarget &= SBIC_RID_MASK;
+
+            if ( csr == SBIC_CSR_RSLT_IFY ) {
+
+                /*
+                 * Read Identify msg to avoid lockup
+                 */
+                GET_SBIC_data(regs, newlun);
+                WAIT_CIP(regs);
+                newlun &= SBIC_TLUN_MASK;
+
+            } else {
+
+                /*
+                 * Need to read Identify message the hard way, assuming
+                 * the target even sends us one...
+                 */
+                for (newlun = 255; newlun; --newlun) {
+                    GET_SBIC_asr(regs, asr);
+                    if (asr & SBIC_ASR_INT)
+                        break;
+                    delay(1);
+                }
+
+                /*
+                 * If we didn't get an interrupt, somethink's up
+                 */
+                if ( (asr & SBIC_ASR_INT) == 0 ) {
 #ifdef DEBUG
-                               if (reselect_debug)
-                                       printf("RSLT_NI - no IFFY message? asr %x\n", asr);
-#endif
-                       } else {
-                               GET_SBIC_csr(regs,csr);
-                               if (csr == SBIC_CSR_MIS|MESG_IN_PHASE ||
-                                   csr == SBIC_CSR_MIS_1|MESG_IN_PHASE ||
-                                   csr == SBIC_CSR_MIS_2|MESG_IN_PHASE) {
-                                       sbicmsgin(dev);
-                                       newlun = dev->sc_msg[0] & 7;
-                               } else {
-                                       printf("RSLT_NI - not MESG_IN_PHASE %x\n",
-                                           csr);
-                               }
-                       }
-               }
+                    if ( reselect_debug )
+                        printf("RSLT_NI - no IFFY message? asr %x\n", asr);
+#endif
+                    newlun = 0; /* XXXX */
+
+                } else {
+                    /*
+                     * We got an interrupt, verify that it's a change to
+                     * message in phase, and if so read the message.
+                     */
+                    GET_SBIC_csr(regs,csr);
+
+                    if ( csr == SBIC_CSR_MIS   | MESG_IN_PHASE ||
+                         csr == SBIC_CSR_MIS_1 | MESG_IN_PHASE ||
+                         csr == SBIC_CSR_MIS_2 | MESG_IN_PHASE ) {
+                        /*
+                         * Yup, gone to message in. Fetch the target LUN
+                         */
+                        sbicmsgin(dev);
+                        newlun = dev->sc_msg[0] & 0x07;
+
+                    } else {
+                        /*
+                         * Whoops! Target didn't go to message in phase!!
+                         */
+                        printf("RSLT_NI - not MESG_IN_PHASE %x\n", csr);
+                        newlun = 0; /* XXXSCW */
+                    }
+                }
+            }
+
+            /*
+             * Ok, we have the identity of the reselecting target.
+             */
 #ifdef DEBUG
-               if(reselect_debug>1 || (reselect_debug && csr==SBIC_CSR_RSLT_NI))
-                       printf("sbicnext: reselect %s from targ %d lun %d\n",
-                           csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY",
-                           newtarget, newlun);
-#endif
-               if (dev->sc_nexus) {
+            if ( reselect_debug > 1 ||
+                (reselect_debug && csr == SBIC_CSR_RSLT_NI) ) {
+                printf("sbicnext: reselect %s from targ %d lun %d\n",
+                        csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY", newtarget, newlun);
+            }
+#endif
+
+            if ( dev->sc_nexus ) {
+                /*
+                 * Whoops! We've been reselected with an command in progress!
+                 * The best we can do is to put the current command back on the
+                 * ready list and hope for the best.
+                 */
 #ifdef DEBUG
-                       if (reselect_debug > 1)
-                               printf("%s: reselect %s with active command\n",
-                                   dev->sc_dev.dv_xname,
-                                   csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY");
-#ifdef DDB
-/*                     Debugger();*/
-#endif
-#endif
-                       TAILQ_INSERT_HEAD(&dev->ready_list, dev->sc_nexus, chain);
-                       dev->sc_tinfo[dev->target].lubusy &= ~(1 << dev->lun);
-               }
-               /* Reload sync values for this target */
-               if (dev->sc_sync[newtarget].state == SYNC_DONE)
-                       SET_SBIC_syn(regs, SBIC_SYN (dev->sc_sync[newtarget].offset,
-                           dev->sc_sync[newtarget].period));
-               else
-                       SET_SBIC_syn(regs, SBIC_SYN (0, sbic_min_period));
-               for (acb = dev->nexus_list.tqh_first; acb;
-                   acb = acb->chain.tqe_next) {
-                       if (acb->xs->sc_link->target != newtarget ||
-                           acb->xs->sc_link->lun != newlun)
-                               continue;
-                       TAILQ_REMOVE(&dev->nexus_list, acb, chain);
-                       dev->sc_nexus = acb;
-                       dev->sc_xs = acb->xs;
-                       dev->sc_flags |= SBICF_SELECTED;
-                       dev->target = newtarget;
-                       dev->lun = newlun;
-                       break;
-               }
-               if (acb == NULL) {
-                       printf("%s: reselect %s targ %d not in nexus_list %x\n",
-                           dev->sc_dev.dv_xname,
-                           csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY", newtarget,
-                           &dev->nexus_list.tqh_first);
-                       panic("bad reselect in sbic");
-               }
-               if (csr == SBIC_CSR_RSLT_IFY)
-                       SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
-               break;
-
-       default:
+                if ( reselect_debug > 1 ) {
+                    printf("%s: reselect %s with active command\n",
+                        dev->sc_dev.dv_xname,
+                        csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY");
+                }
+#endif
+
+                TAILQ_INSERT_HEAD(&dev->ready_list, dev->sc_nexus, chain);
+
+                dev->sc_tinfo[dev->target].lubusy &= ~(1 << dev->lun);
+
+                dev->sc_nexus = NULL;
+                dev->sc_xs    = NULL;
+            }
+
+            /*
+             * Reload sync values for this target
+             */
+            if ( dev->sc_sync[newtarget].state == SYNC_DONE )
+                SET_SBIC_syn(regs, SBIC_SYN (dev->sc_sync[newtarget].offset,
+                                             dev->sc_sync[newtarget].period));
+            else
+                SET_SBIC_syn(regs, SBIC_SYN (0, sbic_min_period));
+
+            /*
+             * Loop through the nexus list until we find the saved entry
+             * for the reselecting target...
+             */
+            for (acb = dev->nexus_list.tqh_first; acb;
+                                                  acb = acb->chain.tqe_next) {
+
+                if ( acb->xs->sc_link->target == newtarget &&
+                     acb->xs->sc_link->lun    == newlun) {
+                    /*
+                     * We've found the saved entry. Dequeue it, and 
+                     * make it current again.
+                     */
+                    TAILQ_REMOVE(&dev->nexus_list, acb, chain);
+
+                    dev->sc_nexus  = acb;
+                    dev->sc_xs     = acb->xs;
+                    dev->sc_flags |= SBICF_SELECTED;
+                    dev->target    = newtarget;
+                    dev->lun       = newlun;
+                    break;
+                }
+            }
+
+            if ( acb == NULL ) {
+                printf("%s: reselect %s targ %d not in nexus_list %x\n",
+                        dev->sc_dev.dv_xname,
+                        csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY", newtarget,
+                        &dev->nexus_list.tqh_first);
+                panic("bad reselect in sbic");
+            }
+
+            if ( csr == SBIC_CSR_RSLT_IFY )
+                SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
+        }
+        break;
+
+      default:
         abort:
-               /*
-                * Something unexpected happened -- deal with it.
-                */
-               printf("sbicnextstate: aborting csr %02x asr %02x\n", csr, asr);
+        {
+            /*
+             * Something unexpected happened -- deal with it.
+             */
+            printf("next: aborting asr 0x%02x csr 0x%02x\n", asr, csr);
+
 #ifdef DDB
-               Debugger();
+            Debugger();
 #endif
+
 #ifdef DEBUG
-               if( data_pointer_debug > 1 )
-                       printf("next dmastop: %d(%x:%x)\n",
-                              dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt);
-#endif
-               dev->sc_dmastop(dev);
-               sbicerror(dev, regs, csr);
-               sbicabort(dev, regs, "next");
-               if (dev->sc_flags & SBICF_INDMA) {
-                       /*
-                        * check for overlapping cache line, flush if so
-                        */
-#ifdef M68040
-                       if (dev->sc_flags & SBICF_DCFLUSH) {
-#if 0
-                               printf("sibc: 68040 DMA cache flush needs fixing? %x:%x\n",
-                                   dev->sc_xs->data, dev->sc_xs->datalen);
-#endif
-                       }
+            dev->sc_dmatimo = 0;
+            if ( data_pointer_debug > 1 )
+                printf("next dmastop: %d(%x:%x)\n", dev->target,
+                                                    dev->sc_cur->dc_addr,
+                                                    dev->sc_tcnt);
 #endif
-                       dev->sc_flags &=
-                               ~(SBICF_INDMA | SBICF_DCFLUSH);
+
+            dev->sc_dmastop(dev);
+            SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
+            if ( dev->sc_xs ) sbicerror(dev, csr);
+            sbicabort(dev, "next");
+
+            if ( dev->sc_flags & SBICF_INDMA ) {
+                dev->sc_flags &= ~(SBICF_INDMA | SBICF_DCFLUSH);
+
 #ifdef DEBUG
-               if( data_pointer_debug > 1 )
-                       printf("next dmastop: %d(%x:%x)\n",
-                              dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt);
+                dev->sc_dmatimo = 0;
+                if ( data_pointer_debug > 1 )
+                    printf("next dmastop: %d(%x:%x)\n", dev->target,
+                                                        dev->sc_cur->dc_addr,
+                                                        dev->sc_tcnt);
 #endif
-                       dev->sc_dmastop(dev);
-                       sbic_scsidone(acb, -1);
-               }
-                return SBIC_STATE_ERROR;
-       }
+                sbic_scsidone(acb, -1);
+            }
+
+            return SBIC_STATE_ERROR;
+        }
+    }
 
-       return(SBIC_STATE_RUNNING);
+    return(SBIC_STATE_RUNNING);
 }
 
 
 /*
  * Check if DMA can not be used with specified buffer
  */
-
 int
 sbiccheckdmap(bp, len, mask)
-       void *bp;
-       u_long len, mask;
+    void    *bp;
+    u_long  len,
+            mask;
 {
-       u_char *buffer;
-       u_long phy_buf;
-       u_long phy_len;
-
-       buffer = bp;
-
-       if (len == 0)
-               return(0);
-
-       while (len) {
-               phy_buf = kvtop(buffer);
-               if (len < (phy_len = NBPG - ((int) buffer & PGOFSET)))
-                       phy_len = len;
-               if (phy_buf & mask)
-                       return(1);
-               buffer += phy_len;
-               len -= phy_len;
-       }
-       return(0);
+    u_char  *buffer;
+    u_long  phy_buf;
+    u_long  phy_len;
+
+    buffer = bp;
+
+    if ( len == 0 )
+        return(1);
+
+    while ( len ) {
+
+        phy_buf = kvtop(buffer);
+        phy_len = NBPG - ((int) buffer & PGOFSET);
+
+        if ( len < phy_len )
+            phy_len = len;
+
+        if ( phy_buf & mask )
+            return(1);
+
+        buffer += phy_len;
+        len    -= phy_len;
+    }
+
+    return(0);
 }
 
 int
-sbictoscsiperiod(dev, regs, a)
-       struct sbic_softc *dev;
-       sbic_regmap_p regs;
-       int a;
+sbictoscsiperiod(dev, a)
+    struct sbic_softc   *dev;
+    int                 a;
 {
-       unsigned int fs;
-
-       /*
-        * cycle = DIV / (2*CLK)
-        * DIV = FS+2
-        * best we can do is 200ns at 20Mhz, 2 cycles
-        */
-
-       GET_SBIC_myid(regs,fs);
-       fs = (fs >>6) + 2;              /* DIV */
-       fs = (fs * 10000) / (dev->sc_clkfreq<<1);       /* Cycle, in ns */
-       if (a < 2) a = 8;               /* map to Cycles */
-       return ((fs*a)>>2);             /* in 4 ns units */
+    unsigned int fs;
+
+    /*
+     * cycle = DIV / (2 * CLK)
+     * DIV = FS + 2
+     * best we can do is 200ns at 20Mhz, 2 cycles
+     */
+
+    GET_SBIC_myid(dev->sc_sbicp, fs);
+
+    fs = (fs >> 6) + 2;         /* DIV */
+
+    fs = (fs * 10000) / (dev->sc_clkfreq << 1); /* Cycle, in ns */
+
+    if ( a < 2 )
+        a = 8;                  /* map to Cycles */
+
+    return ( (fs * a) >> 2 );   /* in 4 ns units */
 }
 
 int
-sbicfromscsiperiod(dev, regs, p)
-       struct sbic_softc *dev;
-       sbic_regmap_p regs;
-       int p;
+sbicfromscsiperiod(dev, p)
+    struct sbic_softc   *dev;
+    int                 p;
 {
-       register unsigned int fs, ret;
+    unsigned    fs,
+                ret;
+
+    /*
+     * Just the inverse of the above
+     */
+    GET_SBIC_myid(dev->sc_sbicp, fs);
+
+    fs = (fs >> 6) + 2;     /* DIV */
+
+    fs = (fs * 10000) / (dev->sc_clkfreq << 1); /* Cycle, in ns */
 
-       /* Just the inverse of the above */
+    ret = p << 2;           /* in ns units */
+    ret = ret / fs;         /* in Cycles */
 
-       GET_SBIC_myid(regs,fs);
-       fs = (fs >>6) + 2;              /* DIV */
-       fs = (fs * 10000) / (dev->sc_clkfreq<<1);   /* Cycle, in ns */
+    if ( ret < sbic_min_period )
+        return(sbic_min_period);
 
-       ret = p << 2;                   /* in ns units */
-       ret = ret / fs;                 /* in Cycles */
-       if (ret < sbic_min_period)
-               return(sbic_min_period);
+    /*
+     * verify rounding
+     */
+    if ( sbictoscsiperiod(dev, ret) < p )
+        ret++;
 
-       /* verify rounding */
-       if (sbictoscsiperiod(dev, regs, ret) < p)
-               ret++;
-       return (ret >= 8) ? 0 : ret;
+    return( (ret >= 8) ? 0 : ret );
 }
 
 #ifdef DEBUG
-
-void sbicdumpstate()
+void
+sbictimeout(dev)
+    struct sbic_softc   *dev;
 {
-       u_char csr, asr;
+    int     s,
+            asr;
 
-       GET_SBIC_asr(debug_sbic_regs,asr);
-       GET_SBIC_csr(debug_sbic_regs,csr);
-       printf("%s: asr:csr(%02x:%02x)->(%02x:%02x)\n",
-              (routine==1)?"sbicgo":
-              (routine==2)?"sbicintr":
-              (routine==3)?"sbicicmd":
-              (routine==4)?"sbicnext":"unknown",
-              debug_asr, debug_csr, asr, csr);
+    s = splbio();
 
-}
+    if ( dev->sc_dmatimo ) {
 
-void sbictimeout(dev)
-       struct sbic_softc *dev;
-{
-       int s, asr;
-
-       /* Dump this every second while there's an active command */
-       if( dev->sc_nexus ) {
-               s = splbio();
-               GET_SBIC_asr(dev->sc_sbicp, asr);
-               if( asr & SBIC_ASR_INT ) {
-                       /* We need to service a missed IRQ */
-                       printf("Servicing a missed int:(%02x,%02x)->(%02x,??)\n",
-                              debug_asr, debug_csr, asr);
-                       sbicintr(dev);
-               }
-               splx(s);
-               sbicdumpstate();
-               timeout((void *)sbictimeout, (void*)dev, sbic_timeout * hz);
-       } else timeout_active = 0;
-}
+        if ( dev->sc_dmatimo > 1 ) {
+
+            printf("%s: dma timeout #%d\n", dev->sc_dev.dv_xname,
+                                            dev->sc_dmatimo - 1);
 
+            GET_SBIC_asr(dev->sc_sbicp, asr);
+
+            if ( asr & SBIC_ASR_INT ) {
+                /*
+                 * We need to service a missed IRQ
+                 */
+                sbicintr(dev);
+            }
+        }
+
+        dev->sc_dmatimo++;
+    }
+
+    splx(s);
+
+    timeout((void *)sbictimeout, dev, 30 * hz);
+}
 #endif
index 1d645cf..ad3c3d1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: sbicreg.h,v 1.2 1995/11/07 08:49:27 deraadt Exp $ */
+/*     $OpenBSD: sbicreg.h,v 1.3 1996/04/28 11:24:46 deraadt Exp $ */
 
 /*
  * Copyright (c) 1990 The Regents of the University of California.
@@ -17,8 +17,8 @@
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
+ *  This product includes software developed by the University of
+ *  California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)scsireg.h   7.3 (Berkeley) 2/5/91
+ *  @(#)scsireg.h   7.3 (Berkeley) 2/5/91
  */
 
 /*
- * AMD AM33C93A SCSI interface hardware description.
+ * WD33C93 SCSI interface hardware description.
  *
  * Using parts of the Mach scsi driver for the 33C93
  */
 
-#define        SBIC_myid       0
-#define        SBIC_cdbsize    0
-#define        SBIC_control    1
-#define        SBIC_timeo      2
-#define        SBIC_cdb1       3
-#define        SBIC_tsecs      3
-#define        SBIC_cdb2       4
-#define        SBIC_theads     4
-#define        SBIC_cdb3       5
-#define        SBIC_tcyl_hi    5
-#define        SBIC_cdb4       6
-#define        SBIC_tcyl_lo    6
-#define        SBIC_cdb5       7
-#define        SBIC_addr_hi    7
-#define        SBIC_cdb6       8
-#define        SBIC_addr_2     8
-#define        SBIC_cdb7       9
-#define        SBIC_addr_3     9
-#define        SBIC_cdb8       10
-#define        SBIC_addr_lo    10
-#define        SBIC_cdb9       11
-#define        SBIC_secno      11
-#define        SBIC_cdb10      12
-#define        SBIC_headno     12
-#define        SBIC_cdb11      13
-#define        SBIC_cylno_hi   13
-#define        SBIC_cdb12      14
-#define        SBIC_cylno_lo   14
-#define        SBIC_tlun       15
-#define        SBIC_cmd_phase  16
-#define        SBIC_syn        17
-#define        SBIC_count_hi   18
-#define        SBIC_count_med  19
-#define        SBIC_count_lo   20
-#define        SBIC_selid      21
-#define        SBIC_rselid     22
-#define        SBIC_csr        23
-#define        SBIC_cmd        24
-#define        SBIC_data       25
+#define SBIC_myid       0
+#define SBIC_cdbsize    0
+#define SBIC_control    1
+#define SBIC_timeo      2
+#define SBIC_cdb1       3
+#define SBIC_tsecs      3
+#define SBIC_cdb2       4
+#define SBIC_theads     4
+#define SBIC_cdb3       5
+#define SBIC_tcyl_hi    5
+#define SBIC_cdb4       6
+#define SBIC_tcyl_lo    6
+#define SBIC_cdb5       7
+#define SBIC_addr_hi    7
+#define SBIC_cdb6       8
+#define SBIC_addr_2     8
+#define SBIC_cdb7       9
+#define SBIC_addr_3     9
+#define SBIC_cdb8       10
+#define SBIC_addr_lo    10
+#define SBIC_cdb9       11
+#define SBIC_secno      11
+#define SBIC_cdb10      12
+#define SBIC_headno     12
+#define SBIC_cdb11      13
+#define SBIC_cylno_hi   13
+#define SBIC_cdb12      14
+#define SBIC_cylno_lo   14
+#define SBIC_tlun       15
+#define SBIC_cmd_phase  16
+#define SBIC_syn        17
+#define SBIC_count_hi   18
+#define SBIC_count_med  19
+#define SBIC_count_lo   20
+#define SBIC_selid      21
+#define SBIC_rselid     22
+#define SBIC_csr        23
+#define SBIC_cmd        24
+#define SBIC_data       25
 /* sbic_asr is addressed directly */
 
 /*
- *     Register defines
+ *  Register defines
  */
 
 /*
  * Auxiliary Status Register
  */
 
-#define SBIC_ASR_INT           0x80    /* Interrupt pending */
-#define SBIC_ASR_LCI           0x40    /* Last command ignored */
-#define SBIC_ASR_BSY           0x20    /* Busy, only cmd/data/asr readable */
-#define SBIC_ASR_CIP           0x10    /* Busy, cmd unavail also */
-#define SBIC_ASR_xxx           0x0c
-#define SBIC_ASR_PE            0x02    /* Parity error (even) */
-#define SBIC_ASR_DBR           0x01    /* Data Buffer Ready */
+#define SBIC_ASR_INT            0x80    /* Interrupt pending */
+#define SBIC_ASR_LCI            0x40    /* Last command ignored */
+#define SBIC_ASR_BSY            0x20    /* Busy, only cmd/data/asr readable */
+#define SBIC_ASR_CIP            0x10    /* Busy, cmd unavail also */
+#define SBIC_ASR_xxx            0x0c
+#define SBIC_ASR_PE             0x02    /* Parity error (even) */
+#define SBIC_ASR_DBR            0x01    /* Data Buffer Ready */
 
 /*
  * My ID register, and/or CDB Size
  */
 
-#define SBIC_ID_FS_8_10                0x00    /* Input clock is  8-10 Mhz */
-                                       /* 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_EHP            0x10    /* Enable host parity */
-#define SBIC_ID_EAF            0x08    /* Enable Advanced Features */
-#define SBIC_ID_MASK           0x07
-#define SBIC_ID_CBDSIZE_MASK   0x0f    /* if unk SCSI cmd group */
+#define SBIC_ID_FS_8_10         0x00    /* Input clock is  8-10 Mhz */
+                                    /* 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_EHP             0x10    /* Enable host parity */
+#define SBIC_ID_EAF             0x08    /* Enable Advanced Features */
+#define SBIC_ID_MASK            0x07
+#define SBIC_ID_CBDSIZE_MASK    0x0f    /* if unk SCSI cmd group */
 
 /*
  * Control register
  */
 
-#define SBIC_CTL_DMA           0x80    /* Single byte dma */
-#define SBIC_CTL_DBA_DMA       0x40    /* direct buffer acces (bus master)*/
-#define SBIC_CTL_BURST_DMA     0x20    /* continuous mode (8237) */
-#define SBIC_CTL_NO_DMA                0x00    /* Programmed I/O */
-#define SBIC_CTL_HHP           0x10    /* Halt on host parity error */
-#define SBIC_CTL_EDI           0x08    /* Ending disconnect interrupt */
-#define SBIC_CTL_IDI           0x04    /* Intermediate disconnect interrupt*/
-#define SBIC_CTL_HA            0x02    /* Halt on ATN */
-#define SBIC_CTL_HSP           0x01    /* Halt on SCSI parity error */
+#define SBIC_CTL_DMA            0x80    /* Single byte dma */
+#define SBIC_CTL_DBA_DMA        0x40    /* direct buffer acces (bus master)*/
+#define SBIC_CTL_BURST_DMA      0x20    /* continuous mode (8237) */
+#define SBIC_CTL_NO_DMA         0x00    /* Programmed I/O */
+#define SBIC_CTL_HHP            0x10    /* Halt on host parity error */
+#define SBIC_CTL_EDI            0x08    /* Ending disconnect interrupt */
+#define SBIC_CTL_IDI            0x04    /* Intermediate disconnect interrupt*/
+#define SBIC_CTL_HA             0x02    /* Halt on ATN */
+#define SBIC_CTL_HSP            0x01    /* Halt on SCSI parity error */
 
 /*
  * Timeout period register
  * [val in msecs, input clk in 0.1 Mhz]
  */
 
-#define        SBIC_TIMEOUT(val,clk)   ((((val) * (clk)) / 800) + 1)
+#define SBIC_TIMEOUT(val,clk)   ((((val) * (clk)) / 800) + 1)
 
 /*
  * CDBn registers, note that
- *     cdb11 is used for status byte in target mode (send-status-and-cc)
- *     cdb12 sez if linked command complete, and w/flag if so
+ *  cdb11 is used for status byte in target mode (send-status-and-cc)
+ *  cdb12 sez if linked command complete, and w/flag if so
  */
 
 /*
  * [holds target status when select-and-xfer]
  */
 
-#define        SBIC_TLUN_VALID 0x80    /* did we receive an Identify msg */
-#define        SBIC_TLUN_DOK   0x40    /* Disconnect OK */
-#define        SBIC_TLUN_xxx   0x38
-#define        SBIC_TLUN_MASK  0x07
+#define SBIC_TLUN_VALID         0x80    /* did we receive an Identify msg */
+#define SBIC_TLUN_DOK           0x40    /* Disconnect OK */
+#define SBIC_TLUN_xxx           0x38
+#define SBIC_TLUN_MASK          0x07
 
 /*
  * Command Phase register
  */
 
-#define        SBIC_CPH_MASK   0x7f    /* values/restarts are cmd specific */
-#define        SBIC_CPH(p)     ((p) & SBIC_CPH_MASK)
+#define SBIC_CPH_MASK           0x7f    /* values/restarts are cmd specific */
+#define SBIC_CPH(p)             ((p) & SBIC_CPH_MASK)
 
 /*
  * FIFO register
  */
 
-#define SBIC_FIFO_DEEP 12
+#define SBIC_FIFO_DEEP          12
 
 /*
  * maximum possible size in TC registers. Since this is 24 bit, it's easy
  */
-#define SBIC_TC_MAX    ((1 << 24) - 1)
+#define SBIC_TC_MAX             ((1 << 24) - 1)
 
 /*
  * Synchronous xfer register
  */
 
-#define        SBIC_SYN_OFF_MASK       0x0f
-#define        SBIC_SYN_MAX_OFFSET     SBIC_FIFO_DEEP
-#define        SBIC_SYN_PER_MASK       0x70
-#define        SBIC_SYN_MIN_PERIOD     2               /* upto 8, encoded as 0 */
+#define SBIC_SYN_OFF_MASK       0x0f
+#define SBIC_SYN_MAX_OFFSET     SBIC_FIFO_DEEP
+#define SBIC_SYN_PER_MASK       0x70
+#define SBIC_SYN_MIN_PERIOD     2       /* upto 8, encoded as 0 */
 
-#define        SBIC_SYN(o,p) \
+#define SBIC_SYN(o,p) \
     (((o) & SBIC_SYN_OFF_MASK) | (((p) << 4) & SBIC_SYN_PER_MASK))
 
 /*
  * Destination ID (selid) register
  */
 
-#define        SBIC_SID_SCC            0x80    /* Select command chaining (tgt) */
-#define        SBIC_SID_DPD            0x40    /* Data phase direction (inittor) */
-#define        SBIC_SID_FROM_SCSI      0x40
-#define        SBIC_SID_TO_SCSI        0x00
-#define        SBIC_SID_xxx            0x38
-#define        SBIC_SID_IDMASK         0x07
+#define SBIC_SID_SCC            0x80    /* Select command chaining (tgt) */
+#define SBIC_SID_DPD            0x40    /* Data phase direction (inittor) */
+#define SBIC_SID_FROM_SCSI      0x40
+#define SBIC_SID_TO_SCSI        0x00
+#define SBIC_SID_xxx            0x38
+#define SBIC_SID_IDMASK         0x07
 
 /*
  * Source ID (rselid) register
  */
 
-#define        SBIC_RID_ER             0x80    /* Enable reselection */
-#define        SBIC_RID_ES             0x40    /* Enable selection */
-#define        SBIC_RID_DSP            0x20    /* Disable select parity */
-#define        SBIC_RID_SIV            0x08    /* Source ID valid */
-#define        SBIC_RID_MASK           0x07
+#define SBIC_RID_ER             0x80    /* Enable reselection */
+#define SBIC_RID_ES             0x40    /* Enable selection */
+#define SBIC_RID_DSP            0x20    /* Disable select parity */
+#define SBIC_RID_SIV            0x08    /* Source ID valid */
+#define SBIC_RID_MASK           0x07
 
 /*
  * Status register
  */
 
-#define        SBIC_CSR_CAUSE          0xf0
-#define        SBIC_CSR_RESET          0x00    /* chip was reset */
-#define        SBIC_CSR_CMD_DONE       0x10    /* cmd completed */
-#define        SBIC_CSR_CMD_STOPPED    0x20    /* interrupted or abrted*/
-#define        SBIC_CSR_CMD_ERR        0x40    /* end with error */
-#define        SBIC_CSR_BUS_SERVICE    0x80    /* REQ pending on the bus */
+#define SBIC_CSR_CAUSE          0xf0
+#define SBIC_CSR_RESET          0x00    /* chip was reset */
+#define SBIC_CSR_CMD_DONE       0x10    /* cmd completed */
+#define SBIC_CSR_CMD_STOPPED    0x20    /* interrupted or abrted*/
+#define SBIC_CSR_CMD_ERR        0x40    /* end with error */
+#define SBIC_CSR_BUS_SERVICE    0x80    /* REQ pending on the bus */
 
 
-#define        SBIC_CSR_QUALIFIER      0x0f
+#define SBIC_CSR_QUALIFIER      0x0f
 /* Reset State Interrupts */
-#define        SBIC_CSR_RESET          0x00    /* reset w/advanced features*/
-#define        SBIC_CSR_RESET_AM       0x01    /* reset w/advanced features*/
+#define SBIC_CSR_RESET          0x00    /* reset w/advanced features*/
+#define SBIC_CSR_RESET_AM       0x01    /* reset w/advanced features*/
 /* Successful Completion Interrupts */
-#define        SBIC_CSR_TARGET         0x10    /* reselect complete */
-#define        SBIC_CSR_INITIATOR      0x11    /* select complete */
-#define        SBIC_CSR_WO_ATN         0x13    /* tgt mode completion */
-#define        SBIC_CSR_W_ATN          0x14    /* ditto */
-#define        SBIC_CSR_XLATED         0x15    /* translate address cmd */
-#define        SBIC_CSR_S_XFERRED      0x16    /* initiator mode completion*/
-#define        SBIC_CSR_XFERRED        0x18    /* phase in low bits */
+#define SBIC_CSR_TARGET         0x10    /* reselect complete */
+#define SBIC_CSR_INITIATOR      0x11    /* select complete */
+#define SBIC_CSR_WO_ATN         0x13    /* tgt mode completion */
+#define SBIC_CSR_W_ATN          0x14    /* ditto */
+#define SBIC_CSR_XLATED         0x15    /* translate address cmd */
+#define SBIC_CSR_S_XFERRED      0x16    /* initiator mode completion*/
+#define SBIC_CSR_XFERRED        0x18    /* phase in low bits */
 /* Paused or Aborted Interrupts */
-#define        SBIC_CSR_MSGIN_W_ACK    0x20    /* (I) msgin, ACK asserted*/
-#define        SBIC_CSR_SDP            0x21    /* (I) SDP msg received */
-#define        SBIC_CSR_SEL_ABRT       0x22    /* sel/resel aborted */
-#define        SBIC_CSR_XFR_PAUSED     0x23    /* (T) no ATN */
-#define        SBIC_CSR_XFR_PAUSED_ATN 0x24    /* (T) ATN is asserted */
-#define        SBIC_CSR_RSLT_AM        0x27    /* (I) lost selection (AM) */
-#define        SBIC_CSR_MIS            0x28    /* (I) xfer aborted, ph mis */
+#define SBIC_CSR_MSGIN_W_ACK    0x20    /* (I) msgin, ACK asserted*/
+#define SBIC_CSR_SDP            0x21    /* (I) SDP msg received */
+#define SBIC_CSR_SEL_ABRT       0x22    /* sel/resel aborted */
+#define SBIC_CSR_XFR_PAUSED     0x23    /* (T) no ATN */
+#define SBIC_CSR_XFR_PAUSED_ATN 0x24    /* (T) ATN is asserted */
+#define SBIC_CSR_RSLT_AM        0x27    /* (I) lost selection (AM) */
+#define SBIC_CSR_MIS            0x28    /* (I) xfer aborted, ph mis */
 /* Terminated Interrupts */
-#define        SBIC_CSR_CMD_INVALID    0x40
-#define        SBIC_CSR_DISC           0x41    /* (I) tgt disconnected */
-#define        SBIC_CSR_SEL_TIMEO      0x42
-#define        SBIC_CSR_PE             0x43    /* parity error */
-#define        SBIC_CSR_PE_ATN         0x44    /* ditto, ATN is asserted */
-#define        SBIC_CSR_XLATE_TOOBIG   0x45
-#define        SBIC_CSR_RSLT_NOAM      0x46    /* (I) lost sel, no AM mode */
-#define        SBIC_CSR_BAD_STATUS     0x47    /* status byte was nok */
-#define        SBIC_CSR_MIS_1          0x48    /* ph mis, see low bits */
+#define SBIC_CSR_CMD_INVALID    0x40
+#define SBIC_CSR_DISC           0x41    /* (I) tgt disconnected */
+#define SBIC_CSR_SEL_TIMEO      0x42
+#define SBIC_CSR_PE             0x43    /* parity error */
+#define SBIC_CSR_PE_ATN         0x44    /* ditto, ATN is asserted */
+#define SBIC_CSR_XLATE_TOOBIG   0x45
+#define SBIC_CSR_RSLT_NOAM      0x46    /* (I) lost sel, no AM mode */
+#define SBIC_CSR_BAD_STATUS     0x47    /* status byte was nok */
+#define SBIC_CSR_MIS_1          0x48    /* ph mis, see low bits */
 /* Service Required Interrupts */
-#define        SBIC_CSR_RSLT_NI        0x80    /* reselected, no ify msg */
-#define        SBIC_CSR_RSLT_IFY       0x81    /* ditto, AM mode, got ify */
-#define        SBIC_CSR_SLT            0x82    /* selected, no ATN */
-#define        SBIC_CSR_SLT_ATN        0x83    /* selected with ATN */
-#define        SBIC_CSR_ATN            0x84    /* (T) ATN asserted */
-#define        SBIC_CSR_DISC_1         0x85    /* (I) bus is free */
-#define        SBIC_CSR_UNK_GROUP      0x87    /* strange CDB1 */
-#define        SBIC_CSR_MIS_2          0x88    /* (I) ph mis, see low bits */
+#define SBIC_CSR_RSLT_NI        0x80    /* reselected, no ify msg */
+#define SBIC_CSR_RSLT_IFY       0x81    /* ditto, AM mode, got ify */
+#define SBIC_CSR_SLT            0x82    /* selected, no ATN */
+#define SBIC_CSR_SLT_ATN        0x83    /* selected with ATN */
+#define SBIC_CSR_ATN            0x84    /* (T) ATN asserted */
+#define SBIC_CSR_DISC_1         0x85    /* (I) bus is free */
+#define SBIC_CSR_UNK_GROUP      0x87    /* strange CDB1 */
+#define SBIC_CSR_MIS_2          0x88    /* (I) ph mis, see low bits */
 
-#define        SBIC_PHASE(csr)         SCSI_PHASE(csr)
+#define SBIC_PHASE(csr)         SCSI_PHASE(csr)
 
 /*
  * Command register (command codes)
  */
 
-#define SBIC_CMD_SBT           0x80    /* Single byte xfer qualifier */
-#define        SBIC_CMD_MASK           0x7f
-
-                                       /* Miscellaneous */
-#define SBIC_CMD_RESET         0x00    /* (DTI) lev I */
-#define SBIC_CMD_ABORT         0x01    /* (DTI) lev I */
-#define SBIC_CMD_DISC          0x04    /* ( TI) lev I */
-#define SBIC_CMD_SSCC          0x0d    /* ( TI) lev I */
-#define SBIC_CMD_SET_IDI       0x0f    /* (DTI) lev I */
-#define SBIC_CMD_XLATE         0x18    /* (DT ) lev II */
-
-                                       /* Initiator state */
-#define SBIC_CMD_SET_ATN       0x02    /* (  I) lev I */
-#define SBIC_CMD_CLR_ACK       0x03    /* (  I) lev I */
-#define SBIC_CMD_XFER_PAD      0x19    /* (  I) lev II */
-#define SBIC_CMD_XFER_INFO     0x20    /* (  I) lev II */
-
-                                       /* Target state */
-#define SBIC_CMD_SND_DISC      0x0e    /* ( T ) lev II */
-#define SBIC_CMD_RCV_CMD       0x10    /* ( T ) lev II */
-#define SBIC_CMD_RCV_DATA      0x11    /* ( T ) lev II */
-#define SBIC_CMD_RCV_MSG_OUT   0x12    /* ( T ) lev II */
-#define SBIC_CMD_RCV           0x13    /* ( T ) lev II */
-#define SBIC_CMD_SND_STATUS    0x14    /* ( T ) lev II */
-#define SBIC_CMD_SND_DATA      0x15    /* ( T ) lev II */
-#define SBIC_CMD_SND_MSG_IN    0x16    /* ( T ) lev II */
-#define SBIC_CMD_SND           0x17    /* ( T ) lev II */
-
-                                       /* Disconnected state */
-#define SBIC_CMD_RESELECT      0x05    /* (D  ) lev II */
-#define SBIC_CMD_SEL_ATN       0x06    /* (D  ) lev II */
-#define SBIC_CMD_SEL           0x07    /* (D  ) lev II */
-#define SBIC_CMD_SEL_ATN_XFER  0x08    /* (D I) lev II */
-#define SBIC_CMD_SEL_XFER      0x09    /* (D I) lev II */
-#define SBIC_CMD_RESELECT_RECV 0x0a    /* (DT ) lev II */
-#define SBIC_CMD_RESELECT_SEND 0x0b    /* (DT ) lev II */
-#define SBIC_CMD_WAIT_SEL_RECV 0x0c    /* (DT ) lev II */
+#define SBIC_CMD_SBT            0x80    /* Single byte xfer qualifier */
+#define SBIC_CMD_MASK           0x7f
+
+                    /* Miscellaneous */
+#define SBIC_CMD_RESET          0x00    /* (DTI) lev I */
+#define SBIC_CMD_ABORT          0x01    /* (DTI) lev I */
+#define SBIC_CMD_DISC           0x04    /* ( TI) lev I */
+#define SBIC_CMD_SSCC           0x0d    /* ( TI) lev I */
+#define SBIC_CMD_SET_IDI        0x0f    /* (DTI) lev I */
+#define SBIC_CMD_XLATE          0x18    /* (DT ) lev II */
+
+                    /* Initiator state */
+#define SBIC_CMD_SET_ATN        0x02    /* (  I) lev I */
+#define SBIC_CMD_CLR_ACK        0x03    /* (  I) lev I */
+#define SBIC_CMD_XFER_PAD       0x19    /* (  I) lev II */
+#define SBIC_CMD_XFER_INFO      0x20    /* (  I) lev II */
+
+                    /* Target state */
+#define SBIC_CMD_SND_DISC       0x0e    /* ( T ) lev II */
+#define SBIC_CMD_RCV_CMD        0x10    /* ( T ) lev II */
+#define SBIC_CMD_RCV_DATA       0x11    /* ( T ) lev II */
+#define SBIC_CMD_RCV_MSG_OUT    0x12    /* ( T ) lev II */
+#define SBIC_CMD_RCV            0x13    /* ( T ) lev II */
+#define SBIC_CMD_SND_STATUS     0x14    /* ( T ) lev II */
+#define SBIC_CMD_SND_DATA       0x15    /* ( T ) lev II */
+#define SBIC_CMD_SND_MSG_IN     0x16    /* ( T ) lev II */
+#define SBIC_CMD_SND            0x17    /* ( T ) lev II */
+
+                    /* Disconnected state */
+#define SBIC_CMD_RESELECT       0x05    /* (D  ) lev II */
+#define SBIC_CMD_SEL_ATN        0x06    /* (D  ) lev II */
+#define SBIC_CMD_SEL            0x07    /* (D  ) lev II */
+#define SBIC_CMD_SEL_ATN_XFER   0x08    /* (D I) lev II */
+#define SBIC_CMD_SEL_XFER       0x09    /* (D I) lev II */
+#define SBIC_CMD_RESELECT_RECV  0x0a    /* (DT ) lev II */
+#define SBIC_CMD_RESELECT_SEND  0x0b    /* (DT ) lev II */
+#define SBIC_CMD_WAIT_SEL_RECV  0x0c    /* (DT ) lev II */
 
 /* approximate, but we won't do SBT on selects */
-#define        sbic_isa_select(cmd)    (((cmd) > 0x5) && ((cmd) < 0xa))
+#define sbic_isa_select(cmd)    (((cmd) > 0x5) && ((cmd) < 0xa))
 
-#define PAD(n)         char n;
-#define SBIC_MACHINE_DMA_MODE  SBIC_CTL_DMA
+#define PAD(n)  char n;
+#define SBIC_MACHINE_DMA_MODE   SBIC_CTL_DMA
 
 typedef struct {
-        volatile unsigned char  sbic_asr;      /* r : Aux Status Register */
-#define sbic_address sbic_asr                  /* w : desired register no */
-        /* PAD(pad1); */
-        volatile unsigned char  sbic_value;    /* rw: register value */
+        volatile unsigned char  sbic_asr;   /* r : Aux Status Register */
+#define sbic_address            sbic_asr    /* w : desired register no */
+        volatile unsigned char  sbic_value; /* rw: register value */
 } sbic_padded_ind_regmap_t;
 typedef volatile sbic_padded_ind_regmap_t *sbic_regmap_p;
 
-#define        sbic_read_reg(regs,regno,val) do { \
-               (regs)->sbic_address = (regno); \
-               (val) = (regs)->sbic_value;     \
-       } while (0)
+#define sbic_read_reg(regs,regno,val)   \
+    do {                                \
+        (regs)->sbic_address = (regno); \
+        (val) = (regs)->sbic_value;     \
+    } while (0)
 
-#define        sbic_write_reg(regs,regno,val)  do { \
-               (regs)->sbic_address = (regno); \
-               (regs)->sbic_value = (val);     \
-       } while (0)
+#define sbic_write_reg(regs,regno,val)  \
+    do {                                \
+        (regs)->sbic_address = (regno); \
+        (regs)->sbic_value = (val);     \
+    } while (0)
 
 #define SET_SBIC_myid(regs,val)         sbic_write_reg(regs,SBIC_myid,val)
 #define GET_SBIC_myid(regs,val)         sbic_read_reg(regs,SBIC_myid,val)
@@ -382,43 +383,55 @@ typedef volatile sbic_padded_ind_regmap_t *sbic_regmap_p;
 #define SET_SBIC_data(regs,val)         sbic_write_reg(regs,SBIC_data,val)
 #define GET_SBIC_data(regs,val)         sbic_read_reg(regs,SBIC_data,val)
 
-#define SBIC_TC_PUT(regs,val) do { \
-       sbic_write_reg(regs,SBIC_count_hi,((val)>>16)); \
-       (regs)->sbic_value = (val)>>8; \
-       (regs)->sbic_value = (val); \
-} while (0)
-#define SBIC_TC_GET(regs,val) do { \
-       sbic_read_reg(regs,SBIC_count_hi,(val)); \
-       (val) = ((val)<<8) | (regs)->sbic_value; \
-       (val) = ((val)<<8) | (regs)->sbic_value; \
-} while (0)
-
-#define SBIC_LOAD_COMMAND(regs,cmd,cmdsize) do { \
-       int n=(cmdsize)-1; \
-       char *ptr = (char*)(cmd); \
-       sbic_write_reg(regs,SBIC_cdb1,*ptr++); \
-       while (n-- > 0) (regs)->sbic_value = *ptr++; \
-} while (0)
+#define SBIC_TC_PUT(regs,val)                           \
+    do {                                                \
+        sbic_write_reg(regs,SBIC_count_hi,((val)>>16)); \
+        (regs)->sbic_value = (val)>>8;                  \
+        (regs)->sbic_value = (val);                     \
+    } while (0)
+
+#define SBIC_TC_GET(regs,val)                           \
+    do {                                                \
+        sbic_read_reg(regs,SBIC_count_hi,(val));        \
+        (val) = ((val)<<8) | (regs)->sbic_value;        \
+        (val) = ((val)<<8) | (regs)->sbic_value;        \
+    } while (0)
+
+#define SBIC_LOAD_COMMAND(regs,cmd,cmdsize)         \
+    do {                                            \
+        int   n   = (cmdsize) - 1;                  \
+        char *ptr = (char *)(cmd);                  \
+        sbic_write_reg(regs, SBIC_cdb1, *ptr++);    \
+        while(n-- > 0) (regs)->sbic_value = *ptr++; \
+    } while (0)
 
 #define GET_SBIC_asr(regs,val)          (val) = (regs)->sbic_asr
 
-#define WAIT_CIP(regs) do { \
-       while ((regs)->sbic_asr & SBIC_ASR_CIP) \
-               ; \
-} while (0)
-
-/* transmit a byte in programmed I/O mode */
-#define SEND_BYTE(regs, ch) do { \
-  WAIT_CIP(regs); \
-  SET_SBIC_cmd(regs, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO); \
-  SBIC_WAIT(regs, SBIC_ASR_DBR, 0); \
-  SET_SBIC_data(regs, ch); \
-  } while (0)
-
-/* receive a byte in programmed I/O mode */
-#define RECV_BYTE(regs, ch) do { \
-  WAIT_CIP(regs); \
-  SET_SBIC_cmd(regs, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO); \
-  SBIC_WAIT(regs, SBIC_ASR_DBR, 0); \
-  GET_SBIC_data(regs, ch); \
-  } while (0)
+#define WAIT_CIP(regs)                          \
+    do {                                        \
+        while ((regs)->sbic_asr & SBIC_ASR_CIP) \
+            ;                                   \
+    } while (0)
+
+/*
+ * transmit a byte in programmed I/O mode
+ **/
+#define SEND_BYTE(regs, ch)                                     \
+    do {                                                        \
+        WAIT_CIP(regs);                                         \
+        SET_SBIC_cmd(regs, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO);  \
+        SBIC_WAIT(regs, SBIC_ASR_DBR, 0);                       \
+        SET_SBIC_data(regs, ch);                                \
+    } while (0)
+
+/*
+ * receive a byte in programmed I/O mode
+ */
+#define RECV_BYTE(regs, ch)                                     \
+    do {                                                        \
+        WAIT_CIP(regs);                                         \
+        SET_SBIC_cmd(regs, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO);  \
+        SBIC_WAIT(regs, SBIC_ASR_DBR, 0);                       \
+        GET_SBIC_data(regs, ch);                                \
+    } while (0)
+
index c198db3..bbf9659 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: sbicvar.h,v 1.2 1995/11/07 08:49:28 deraadt Exp $ */
+/*     $OpenBSD: sbicvar.h,v 1.3 1996/04/28 11:24:47 deraadt Exp $ */
 
 /*
  * Copyright (c) 1990 The Regents of the University of California.
@@ -17,8 +17,8 @@
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
+ *  This product includes software developed by the University of
+ *  California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)scsivar.h   7.1 (Berkeley) 5/8/90
+ *  @(#)scsivar.h   7.1 (Berkeley) 5/8/90
  */
 #ifndef _SBICVAR_H_
 #define _SBICVAR_H_
 #include <sys/malloc.h>
 
+
 /*
- * The largest single request will be MAXPHYS bytes which will require
- * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of
- * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the
- * buffer is not page aligned (+1).
+ * DMA chains are used for Scatter-Gather DMA.
  */
-#define        DMAMAXIO        (MAXPHYS/NBPG+1)
-
-struct dma_chain {
-       int     dc_count;
-       char    *dc_addr;
+struct  dma_chain {
+    int     dc_count;
+    char    *dc_addr;
 };
 
 /*
@@ -63,25 +59,23 @@ struct      dma_chain {
  * occasionally xs->retries.
  */
 struct sbic_acb {
-       TAILQ_ENTRY(sbic_acb) chain;
-       struct scsi_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_CHKSENSE   0x08
-#define ACB_BBUF       0x10    /* DMA input needs to be copied from bounce */
-#define        ACB_DATAIN      0x20    /* DMA direction flag */
-       struct scsi_generic cmd;        /* SCSI command block */
-       int      clen;
-       struct  dma_chain sc_kv;        /* Virtual address of whole DMA */
-       struct  dma_chain sc_pa;        /* Physical address of DMA segment */
-       u_long  sc_tcnt;                /* number of bytes for this DMA */
-       u_char *sc_dmausrbuf;           /* user buffer kva - for bounce copy */
-       u_long  sc_dmausrlen;           /* length of bounce copy */
-       u_short sc_dmacmd;              /* Internal data for this DMA */
-       char *pa_addr;                  /* XXXX initial phys addr */
-       u_char *sc_usrbufpa;            /* user buffer phys addr */
+    TAILQ_ENTRY(sbic_acb)   chain;
+    struct scsi_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_CHKSENSE    0x08
+#define ACB_BBUF        0x10    /* DMA input needs to be copied from bounce */
+#define ACB_DATAIN      0x20    /* DMA direction flag */
+
+    struct  scsi_generic    cmd;        /* SCSI command block */
+    int                     clen;
+    struct  dma_chain       sc_kv;      /* Virtual address of whole DMA */
+    struct  dma_chain       sc_pa;      /* Physical address of DMA segment */
+    u_long                  sc_tcnt;    /* number of bytes for this DMA */
+    u_short                 sc_dmacmd;  /* Internal data for this DMA */
+    char                    *pa_addr;   /* XXXX initial phys addr */
 };
 
 /*
@@ -90,136 +84,119 @@ struct sbic_acb {
  * 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     touts;          /* #timeouts */
-       int     perrs;          /* #parity errors */
-       int     senses;         /* #request sense commands sent */
-       u_char* bounce;         /* Bounce buffer for this device */
-       ushort  lubusy;         /* What local units/subr. are busy? */
-       u_char  flags;
-       u_char  period;         /* Period suggestion */
-       u_char  offset;         /* Offset suggestion */
+    int                     cmds;       /* #commands processed */
+    int                     dconns;     /* #disconnects */
+    int                     senses;     /* #request sense commands sent */
+    int                     lubusy;     /* What local units/subr. are busy? */
 } tinfo_t;
 
-struct sbic_softc {
-       struct  device sc_dev;
-       struct  intrhand sc_ih, sc_dmaih;
-       struct  evcnt   sc_intrcnt, sc_dmaintrcnt;
-       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  scsi_link sc_link;      /* proto for sub devices */
-       sbic_regmap_p   sc_sbicp;       /* the SBIC */
-       volatile void   *sc_cregs;      /* driver specific regs */
-
-       /* 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  scsi_xfer *sc_xs;       /* transfer from high level code */
-       u_char  sc_flags;
-       u_char  sc_scsiaddr;
-       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_dmacmd;              /* used by dma drivers */
-       u_short sc_dmatimo;             /* dma timeout */
-       u_long  sc_dmamask;             /* dma valid mem mask */
-       struct  dma_chain *sc_cur;
-       struct  dma_chain *sc_last;
-       int  (*sc_dmago)        __P((struct sbic_softc *, char *, int, int));
-       int  (*sc_dmanext)      __P((struct sbic_softc *));
-       void (*sc_dmafree)      __P((struct sbic_softc *));
-       void (*sc_dmastop)      __P((struct sbic_softc *));
-       u_short gtsc_bankmask;          /* GVP specific bank selected */
-};
-
-/* 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 to ztwobus space */
-#define        SBICF_INTR      0x40    /* SBICF interrupt expected */
-#define        SBICF_INDMA     0x80    /* not used yet, DMA I/O in progress */
-
-/* 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 */
+struct  sbic_softc {
+    struct  device          sc_dev;
+    struct  intrhand       sc_dmaih;
+    struct  intrhand       sc_sbicih;
+    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  scsi_link       sc_link;    /* proto for sub devices */
+    sbic_regmap_p           sc_sbicp;   /* the SBIC */
+    void                    *sc_cregs;  /* driver specific regs */
+    int                     sc_ipl;
+
+    /* 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  scsi_xfer       *sc_xs;     /* transfer from high level code */
+    u_char                  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_dmacmd;  /* used by dma drivers */
+    u_long                  sc_dmamask; /* dma valid mem mask */
 #ifdef DEBUG
-#define        DDB_FOLLOW      0x04
-#define DDB_IO         0x08
+    u_short                 sc_dmatimo; /* dma timeout */
 #endif
-extern int sbic_inhibit_sync;
-extern int sbic_no_dma;
-extern int sbic_clock_override;
-
-#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
-
-#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
-
-#define MSG_ISIDENTIFY(x) (x&MSG_IDENTIFY)
-#define IFY_TRN                0x20
-#define IFY_LUNTRN(x)  (x&0x07)
-#define IFY_LUN(x)     (!(x&0x20))
-
-/* Check if high bit set */
-
-#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 */
-
-
-/* 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
+    struct  dma_chain       *sc_cur;
+    struct  dma_chain       *sc_last;
+    int  (*sc_dmago)        __P((struct sbic_softc *, char *, int, int));
+    int  (*sc_dmanext)      __P((struct sbic_softc *));
+    void (*sc_enintr)       __P((struct sbic_softc *));
+    void (*sc_dmastop)      __P((struct sbic_softc *));
+};
 
 /*
- * XXXX
+ * sc_flags
  */
-struct scsi_fmt_cdb {
-       int len;                /* cdb length (in bytes) */
-       u_char cdb[28];         /* cdb to use on next read/write */
-};
+#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 to ztwobus space */
+#define SBICF_INTR          0x40    /* SBICF interrupt expected */
+#define SBICF_INDMA         0x80    /* not used yet, DMA I/O in progress */
+
+/*
+ * 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 */
+
+#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
+
+#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
+
+#define MSG_ISIDENTIFY(x)   ((x) & MSG_IDENTIFY)
+
+
+#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 */
+
+
+/*
+ * 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
+
 
 struct buf;
 struct scsi_xfer;
diff --git a/sys/arch/mvme68k/dev/wdsc.c b/sys/arch/mvme68k/dev/wdsc.c
new file mode 100644 (file)
index 0000000..c8e1bd7
--- /dev/null
@@ -0,0 +1,349 @@
+/*     $OpenBSD: wdsc.c,v 1.1 1996/04/28 11:24:48 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1996 Steve Woodford
+ * Copyright (c) 1982, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *  This product includes software developed by the University of
+ *  California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *  @(#)wdsc.c
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <mvme68k/dev/dmavar.h>
+#include <mvme68k/dev/sbicreg.h>
+#include <mvme68k/dev/sbicvar.h>
+#include <mvme68k/dev/wdscreg.h>
+#include <machine/autoconf.h>
+#include <mvme68k/dev/pccreg.h>
+
+int     wdscprint       __P((void *auxp, char *));
+void    wdscattach      __P((struct device *, struct device *, void *));
+int     wdscmatch       __P((struct device *, struct cfdata *, void *));
+
+void    wdsc_enintr     __P((struct sbic_softc *));
+int     wdsc_dmago      __P((struct sbic_softc *, char *, int, int));
+int     wdsc_dmanext    __P((struct sbic_softc *));
+void    wdsc_dmastop    __P((struct sbic_softc *));
+int     wdsc_dmaintr    __P((struct sbic_softc *));
+int     wdsc_scsiintr   __P((struct sbic_softc *));
+
+struct scsi_adapter wdsc_scsiswitch = {
+    sbic_scsicmd,
+    sbic_minphys,
+    0,          /* no lun support */
+    0,          /* no lun support */
+};
+
+struct scsi_device wdsc_scsidev = {
+    NULL,       /* use default error handler */
+    NULL,       /* do not have a start functio */
+    NULL,       /* have no async handler */
+    NULL,       /* Use default done routine */
+};
+
+struct cfattach wdsc_ca = {
+       sizeof(struct sbic_softc), (cfmatch_t)wdscmatch, wdscattach
+};
+
+struct cfdriver wdsc_cd = {
+    NULL, "wdsc", DV_DULL, NULL, 0 
+};
+
+/*
+ * Define 'scsi_nosync = 0x00' to enable sync SCSI mode.
+ * This is untested as yet, use at your own risk...
+ */
+u_long      scsi_nosync  = 0xff;
+int         shift_nosync = 0;
+
+/*
+ * Match for SCSI devices on the onboard WD33C93 chip
+ */
+int
+wdscmatch(pdp, cdp, auxp)
+    struct device *pdp;
+    struct cfdata *cdp;
+    void *auxp;
+{
+    /*
+     * Match everything
+     */
+    return(1);
+}
+
+
+/*
+ * Attach the wdsc driver
+ */
+void
+wdscattach(pdp, dp, auxp)
+    struct device *pdp, *dp;
+    void *auxp;
+{
+    struct sbic_softc   *sc = (struct sbic_softc *)dp;
+    struct confargs *ca = auxp;
+    struct pccreg *pcc = (struct pccreg *)ca->ca_master;
+    int                 ipl;
+
+    sc->sc_enintr  = wdsc_enintr;
+    sc->sc_dmago   = wdsc_dmago;
+    sc->sc_dmanext = wdsc_dmanext;
+    sc->sc_dmastop = wdsc_dmastop;
+    sc->sc_dmacmd  = 0;
+
+    sc->sc_link.adapter_softc  = sc;
+    sc->sc_link.adapter_target = 7;
+    sc->sc_link.adapter        = &wdsc_scsiswitch;
+    sc->sc_link.device         = &wdsc_scsidev;
+    sc->sc_link.openings       = 2;
+
+    printf(": target %d\n", sc->sc_link.adapter_target);
+
+    sc->sc_cregs = (void *)pcc;
+    sc->sc_sbicp = (sbic_regmap_p)ca->ca_vaddr;
+
+    /*
+     * Eveything is a valid dma address.
+     * 
+     */
+    sc->sc_dmamask = 0;
+
+    /*
+     * The onboard WD33C93 of the '147 is usually clocked at 10MHz...
+     * (We use 10 times this for accuracy in later calculations)
+     */
+    sc->sc_clkfreq = 100;
+
+    /*
+     * Initialise the hardware
+     */
+    sbicinit(sc);
+
+    /*
+     * Fix up the interrupts
+     */
+    sc->sc_dmaih.ih_fn = wdsc_dmaintr;
+    sc->sc_dmaih.ih_arg = sc;
+    sc->sc_dmaih.ih_ipl = ca->ca_ipl;
+    pcctwointr_establish(PCCV_DMA, &sc->sc_dmaih);
+
+    sc->sc_sbicih.ih_fn = wdsc_scsiintr;
+    sc->sc_sbicih.ih_arg = sc;
+    sc->sc_sbicih.ih_ipl = ca->ca_ipl;
+    pcctwointr_establish(PCCV_SBIC, &sc->sc_dmaih);
+
+    pcc->pcc_sbicirq = ca->ca_ipl | PCC_IRQ_IEN;
+    pcc->pcc_dmairq = ca->ca_ipl | PCC_IRQ_IEN;
+    pcc->pcc_dmacsr  = 0;
+
+    pcc->pcc_sbicirq = ca->ca_ipl | PCC_IRQ_IEN /* | PCC_IRQ_INT */;
+
+    /*
+     * Attach all scsi units on us
+     */
+    config_found(dp, &sc->sc_link, wdscprint);
+}
+
+/*
+ * print diag if pnp is NULL else just extra
+ */
+int
+wdscprint(auxp, pnp)
+    void *auxp;
+    char *pnp;
+{
+    if (pnp == NULL)
+        return(UNCONF);
+    return(QUIET);
+}
+
+
+/*
+ * Enable DMA interrupts
+ */
+void
+wdsc_enintr(dev)
+    struct sbic_softc *dev;
+{
+    struct pccreg *pcc = dev->sc_cregs;
+
+    dev->sc_flags |= SBICF_INTR;
+
+    pcc->pcc_dmairq = dev->sc_ipl | PCC_IRQ_IEN /*| PCC_IRQ_INT*/;
+}
+
+/*
+ * Prime the hardware for a DMA transfer
+ */
+int
+wdsc_dmago(dev, addr, count, flags)
+    struct sbic_softc *dev;
+    char *addr;
+    int count, flags;
+{
+    volatile struct pccreg *pc = dev->sc_cregs;
+
+    /*
+     * Set up the command word based on flags
+     */
+    if ( (flags & DMAGO_READ) == 0 )
+        dev->sc_dmacmd = DMAC_CSR_ENABLE | DMAC_CSR_WRITE;
+    else
+        dev->sc_dmacmd = DMAC_CSR_ENABLE;
+
+    dev->sc_flags |= SBICF_INTR;
+    dev->sc_tcnt   = dev->sc_cur->dc_count << 1;
+
+    /*
+     * Prime the hardware.
+     * Note, it's probably not necessary to do this here, since dmanext
+     * is called just prior to the actual transfer.
+     */
+    pc->pcc_dmacsr   = 0;
+    pc->pcc_dmairq   = dev->sc_ipl | PCC_IRQ_IEN | PCC_IRQ_INT;
+    pc->pcc_dmadaddr = (unsigned long)dev->sc_cur->dc_addr;
+    pc->pcc_dmabcnt  = (unsigned long)dev->sc_tcnt | (1 << 24);
+    pc->pcc_dmacsr   = dev->sc_dmacmd;
+
+    return(dev->sc_tcnt);
+}
+
+/*
+ * Prime the hardware for the next DMA transfer
+ */
+int
+wdsc_dmanext(dev)
+    struct sbic_softc *dev;
+{
+    volatile struct pccreg *pc = dev->sc_cregs;
+
+    if ( dev->sc_cur > dev->sc_last ) {
+        /*
+         * Shouldn't happen !!
+         */
+        printf("wdsc_dmanext at end !!!\n");
+        wdsc_dmastop(dev);
+        return(0);
+    }
+
+    dev->sc_tcnt = dev->sc_cur->dc_count << 1;
+
+    /* 
+     * Load the next DMA address
+     */
+    pc->pcc_dmacsr   = 0;
+    pc->pcc_dmairq   = dev->sc_ipl | PCC_IRQ_IEN | PCC_IRQ_INT;
+    pc->pcc_dmadaddr = (unsigned long)dev->sc_cur->dc_addr;
+    pc->pcc_dmabcnt  = (unsigned long)dev->sc_tcnt | (1 << 24);
+    pc->pcc_dmacsr   = dev->sc_dmacmd;
+
+    return(dev->sc_tcnt);
+}
+
+/*
+ * Stop DMA, and disable interrupts
+ */
+void
+wdsc_dmastop(dev)
+    struct sbic_softc *dev;
+{
+    volatile struct pccreg *pc = dev->sc_cregs;
+    int                 s;
+
+    s = splbio();
+
+    pc->pcc_dmacsr    = 0;
+    pc->pcc_dmairq    = dev->sc_ipl | PCC_IRQ_INT;
+
+    splx(s);
+}
+
+/*
+ * Come here following a DMA interrupt
+ */
+int
+wdsc_dmaintr(dev)
+    struct sbic_softc *dev;
+{
+    volatile struct pccreg *pc = dev->sc_cregs;
+    int                 found = 0;
+
+    /*
+     * Really a DMA interrupt?
+     */
+    if ( (pc->pcc_dmairq & 0x80) == 0 )
+        return(0);
+
+    /*
+     * Was it a completion interrupt?
+     * XXXSCW Note: Support for other DMA interrupts is required, eg. buserr
+     */
+    if ( pc->pcc_dmacsr & DMAC_CSR_DONE ) {
+        ++found;
+
+        pc->pcc_dmairq = dev->sc_ipl | PCC_IRQ_IEN | PCC_IRQ_INT;
+    }
+
+    return(found);
+}
+
+/*
+ * Come here for SCSI interrupts
+ */
+int
+wdsc_scsiintr(dev)
+    struct sbic_softc *dev;
+{
+    volatile struct pccreg *pc = dev->sc_cregs;
+    int                 found;
+
+    /*
+     * Really a SCSI interrupt?
+     */
+    if ( (pc->pcc_sbicirq & 0x80) == 0 )
+        return(0);
+
+    /*
+     * Go handle it
+     */
+    found = sbicintr(dev);
+
+    /*
+     * Acknowledge and clear the interrupt
+     */
+    pc->pcc_sbicirq = dev->sc_ipl | PCC_IRQ_IEN | PCC_IRQ_INT;
+
+    return(found);
+}
diff --git a/sys/arch/mvme68k/dev/wdscreg.h b/sys/arch/mvme68k/dev/wdscreg.h
new file mode 100644 (file)
index 0000000..e439e62
--- /dev/null
@@ -0,0 +1,53 @@
+/*     $OpenBSD: wdscreg.h,v 1.1 1996/04/28 11:24:49 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps
+ * Copyright (c) 1982, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *  This product includes software developed by the University of
+ *  California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *  @(#)dmareg.h
+ */
+#ifndef _MVME68K_DEV_WDSCREG_H_
+#define _MVME68K_DEV_WDSCREG_H_
+
+#define DMAC_CSR_ENABLE     (1 << 0)    /* Enable the DMAC */
+#define DMAC_CSR_TABLE      (1 << 1)    /* Select Table Mode */
+#define DMAC_CSR_WRITE      (1 << 2)    /* Write data from RAM to SCSI */
+#define DMAC_CSR_TBUSERR    (1 << 3)    /* Bus error during table walk */
+#define DMAC_CSR_DBUSERR    (1 << 4)    /* Bus error during data xfer */
+#define DMAC_CSR_TSIZE      (1 << 5)    /* Table addr. not in 32 bits */
+#define DMAC_CSR_8BITS      (1 << 6)    /* Non-8 bit handshake */
+#define DMAC_CSR_DONE       (1 << 7)    /* Transfer complete, or error */
+
+#define DMAC_SR_HOLDING     0x0f        /* Data holding state */
+#define DMAC_SR_INCREMENT   0xf0        /* Increment value */
+
+#endif