Fix a race condition in the flushing of commands that
authorPeter Avalos <pavalos@dragonflybsd.org>
Thu, 5 Jul 2007 04:39:25 +0000 (04:39 +0000)
committerPeter Avalos <pavalos@dragonflybsd.org>
Thu, 5 Jul 2007 04:39:25 +0000 (04:39 +0000)
have completed across the bus but not to the host before
processing of an exception condition (busfree, bus reset,
etc.).  When flushing the controller of completed commands,
we also look for packetized commands that have completed
with good status and are stored in the "good status fifo".
The hardware will post to the good status fifo even if
data for that command is still active in a FIFO.  In
one particular failure case, a command outstanding on the
bus reconnected, transferred data into a FIFO, and provided
good status while the host driver was processing an expected
busfree event (PPR message negotiation).  This resulted in
an entry in the good status fifo that we completed, but
since the sequencer was paused, the data in the data FIFO
for this command had never been transferred to the host.
Once the busfree processing was complete, the sequencer
was unpaused, and the data completed its transfer to the
host.  In some instances, the client for the data was notified
of the completion and attempted to view the data before
it arrived.  This case only occurred during the
multi-target probe of the SCSI bus while some devices are
negotiating to go packetized and some devices are already
running in packetized.

The fix is to run and FIFOs active with a context in the
good status fifo to completion before completing the command
to the SCSI layer.  This requies duplicating the FIFO rundown
operations in the host driver that would usually be handled
by the firmware, but there is no other alternative.

Don't blindly shutdown the SCB dma engine when restarting
the sequencer.  We may be killing an operation that is
not supposed to be cancelled.  The cases where we need to
shutdown these dma engines are already handled elsewhere in
the driver.

Fix a few more ahd_in?() -> ahd_in?_scbram() instances.

Obtained-from: FreeBSD

sys/dev/disk/aic7xxx/aic79xx.c

index 1c7a3f3..63667c0 100644 (file)
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#201 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#202 $
  *
- * $FreeBSD: src/sys/dev/aic7xxx/aic79xx.c,v 1.23 2003/06/28 04:45:25 gibbs Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx.c,v 1.16 2007/07/05 02:47:43 pavalos Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/aic79xx.c,v 1.24 2003/06/28 04:46:54 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx.c,v 1.17 2007/07/05 04:39:25 pavalos Exp $
  */
 
 #include "aic79xx_osm.h"
@@ -219,6 +219,11 @@ static u_int               ahd_resolve_seqaddr(struct ahd_softc *ahd,
 static void            ahd_download_instr(struct ahd_softc *ahd,
                                           u_int instrptr, uint8_t *dconsts);
 static int             ahd_probe_stack_size(struct ahd_softc *ahd);
+static int             ahd_scb_active_in_fifo(struct ahd_softc *ahd,
+                                              struct scb *scb);
+static void            ahd_run_data_fifo(struct ahd_softc *ahd,
+                                         struct scb *scb);
+
 #ifdef AHD_TARGET_MODE
 static void            ahd_queue_lstate_event(struct ahd_softc *ahd,
                                               struct ahd_tmode_lstate *lstate,
@@ -323,10 +328,7 @@ ahd_restart(struct ahd_softc *ahd)
        /* Always allow reselection */
        ahd_outb(ahd, SCSISEQ1,
                 ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));
-       /* Ensure that no DMA operations are in progress */
        ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
-       ahd_outb(ahd, SCBHCNT, 0);
-       ahd_outb(ahd, CCSCBCTL, CCSCBRESET);
        ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
        ahd_unpause(ahd);
 }
@@ -366,8 +368,86 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
        u_int           next_scbid;
 
        saved_modes = ahd_save_modes(ahd);
-       ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
+
+       /*
+        * Complete any SCBs that just finished being
+        * DMA'ed into the qoutfifo.
+        */
+       ahd_run_qoutfifo(ahd);
+
+       /*
+        * Flush the good status FIFO for compelted packetized commands.
+        */
+       ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
        saved_scbptr = ahd_get_scbptr(ahd);
+       while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) {
+               u_int fifo_mode;
+               u_int i;
+               
+               scbid = (ahd_inb(ahd, GSFIFO+1) << 8)
+                     | ahd_inb(ahd, GSFIFO);
+               scb = ahd_lookup_scb(ahd, scbid);
+               if (scb == NULL) {
+                       kprintf("%s: Warning - GSFIFO SCB %d invalid\n",
+                              ahd_name(ahd), scbid);
+                       continue;
+               }
+               /*
+                * Determine if this transaction is still active in
+                * any FIFO.  If it is, we must flush that FIFO to
+                * the host before completing the  command.
+                */
+               fifo_mode = 0;
+               for (i = 0; i < 2; i++) {
+                       /* Toggle to the other mode. */
+                       fifo_mode ^= 1;
+                       ahd_set_modes(ahd, fifo_mode, fifo_mode);
+                       if (ahd_scb_active_in_fifo(ahd, scb) == 0)
+                               continue;
+
+                       ahd_run_data_fifo(ahd, scb);
+
+                       /*
+                        * Clearing this transaction in this FIFO may
+                        * cause a CFG4DATA for this same transaction
+                        * to assert in the other FIFO.  Make sure we
+                        * loop one more time and check the other FIFO.
+                        */
+                       i = 0;
+               }
+               ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
+               ahd_set_scbptr(ahd, scbid);
+               if ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_LIST_NULL) == 0
+                && ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_FULL_RESID) != 0
+                 || (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR)
+                     & SG_LIST_NULL) != 0)) {
+                       u_int comp_head;
+
+                       /*
+                        * The transfer completed with a residual.
+                        * Place this SCB on the complete DMA list
+                        * so that we Update our in-core copy of the
+                        * SCB before completing the command.
+                        */
+                       ahd_outb(ahd, SCB_SCSI_STATUS, 0);
+                       ahd_outb(ahd, SCB_SGPTR,
+                                ahd_inb_scbram(ahd, SCB_SGPTR)
+                                | SG_STATUS_VALID);
+                       ahd_outw(ahd, SCB_TAG, SCB_GET_TAG(scb));
+                       comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
+                       ahd_outw(ahd, SCB_NEXT_COMPLETE, comp_head);
+                       if (SCBID_IS_NULL(comp_head))
+                               ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD,
+                                        SCB_GET_TAG(scb));
+               } else
+                       ahd_complete_scb(ahd, scb);
+       }
+       ahd_set_scbptr(ahd, saved_scbptr);
+
+       /*
+        * Setup for command channel portion of flush.
+        */
+       ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
 
        /*
         * Wait for any inprogress DMA to complete and clear DMA state
@@ -385,12 +465,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
        if ((ccscbctl & CCSCBDIR) != 0)
                ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN));
 
-       /*
-        * Complete any SCBs that just finished being
-        * DMA'ed into the qoutfifo.
-        */
-       ahd_run_qoutfifo(ahd);
-
+       saved_scbptr = ahd_get_scbptr(ahd);
        /*
         * Manually update/complete any completed SCBs that are waiting to be
         * DMA'ed back up to the host.
@@ -433,29 +508,276 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
                scbid = next_scbid;
        }
        ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
+
+       /*
+        * Restore state.
+        */
        ahd_set_scbptr(ahd, saved_scbptr);
+       ahd_restore_modes(ahd, saved_modes);
+       ahd->flags |= AHD_UPDATE_PEND_CMDS;
+}
+
+/*
+ * Determine if an SCB for a packetized transaction
+ * is active in a FIFO.
+ */
+static int
+ahd_scb_active_in_fifo(struct ahd_softc *ahd, struct scb *scb)
+{
 
        /*
-        * Flush the good status FIFO for compelted packetized commands.
+        * The FIFO is only active for our transaction if
+        * the SCBPTR matches the SCB's ID and the firmware
+        * has installed a handler for the FIFO or we have
+        * a pending SAVEPTRS or CFG4DATA interrupt.
         */
-       ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
-       while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) {
-               scbid = (ahd_inb(ahd, GSFIFO+1) << 8)
-                     | ahd_inb(ahd, GSFIFO);
-               scb = ahd_lookup_scb(ahd, scbid);
-               if (scb == NULL) {
-                       kprintf("%s: Warning - GSFIFO SCB %d invalid\n",
-                              ahd_name(ahd), scbid);
-                       continue;
+       if (ahd_get_scbptr(ahd) != SCB_GET_TAG(scb)
+        || ((ahd_inb(ahd, LONGJMP_ADDR+1) & INVALID_ADDR) != 0
+         && (ahd_inb(ahd, SEQINTSRC) & (CFG4DATA|SAVEPTRS)) == 0))
+               return (0);
+
+       return (1);
+}
+
+/*
+ * Run a data fifo to completion for a transaction we know
+ * has completed across the SCSI bus (good status has been
+ * received).  We are already set to the correct FIFO mode
+ * on entry to this routine.
+ *
+ * This function attempts to operate exactly as the firmware
+ * would when running this FIFO.  Care must be taken to update
+ * this routine any time the firmware's FIFO algorithm is
+ * changed.
+ */
+static void
+ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
+{
+       u_int seqintsrc;
+
+       while (1) {
+               seqintsrc = ahd_inb(ahd, SEQINTSRC);
+               if ((seqintsrc & CFG4DATA) != 0) {
+                       uint32_t datacnt;
+                       uint32_t sgptr;
+
+                       /*
+                        * Clear full residual flag.
+                        */
+                       sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
+                       ahd_outb(ahd, SCB_SGPTR, sgptr);
+
+                       /*
+                        * Load datacnt and address.
+                        */
+                       datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
+                       if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
+                               sgptr |= LAST_SEG;
+                               ahd_outb(ahd, SG_STATE, 0);
+                       } else
+                               ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
+                       ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
+                       ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
+                       ahd_outb(ahd, SG_CACHE_PRE, sgptr);
+                       ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
+
+                       /*
+                        * Initialize Residual Fields.
+                        */
+                       ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
+                       ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
+
+                       /*
+                        * Mark the SCB as having a FIFO in use.
+                        */
+                       ahd_outb(ahd, SCB_FIFO_USE_COUNT,
+                                ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
+
+                       /*
+                        * Install a "fake" handler for this FIFO.
+                        */
+                       ahd_outw(ahd, LONGJMP_ADDR, 0);
+
+                       /*
+                        * Notify the hardware that we have satisfied
+                        * this sequencer interrupt.
+                        */
+                       ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
+               } else if ((seqintsrc & SAVEPTRS) != 0) {
+                       uint32_t sgptr;
+                       uint32_t resid;
+
+                       if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
+                               /*
+                                * Snapshot Save Pointers.  Clear
+                                * the snapshot and continue.
+                                */
+                               ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
+                               continue;
+                       }
+
+                       /*
+                        * Disable S/G fetch so the DMA engine
+                        * is available to future users.
+                        */
+                       if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
+                               ahd_outb(ahd, CCSGCTL, 0);
+                       ahd_outb(ahd, SG_STATE, 0);
+
+                       /*
+                        * Flush the data FIFO.  Strickly only
+                        * necessary for Rev A parts.
+                        */
+                       ahd_outb(ahd, DFCNTRL,
+                                ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
+
+                       /*
+                        * Calculate residual.
+                        */
+                       sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
+                       resid = ahd_inl(ahd, SHCNT);
+                       resid |=
+                           ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
+                       ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
+                       if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
+                               /*
+                                * Must back up to the correct S/G element.
+                                * Typically this just means resetting our
+                                * low byte to the offset in the SG_CACHE,
+                                * but if we wrapped, we have to correct
+                                * the other bytes of the sgptr too.
+                                */
+                               if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
+                                && (sgptr & 0x80) == 0)
+                                       sgptr -= 0x100;
+                               sgptr &= ~0xFF;
+                               sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
+                                      & SG_ADDR_MASK;
+                               ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
+                               ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
+                       } else if ((resid & AHD_SG_LEN_MASK) == 0) {
+                               ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
+                                        sgptr | SG_LIST_NULL);
+                       }
+                       /*
+                        * Save Pointers.
+                        */
+                       ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
+                       ahd_outl(ahd, SCB_DATACNT, resid);
+                       ahd_outl(ahd, SCB_SGPTR, sgptr);
+                       ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
+                       ahd_outb(ahd, SEQIMODE,
+                                ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
+                       /*
+                        * If the data is to the SCSI bus, we are
+                        * done, otherwise wait for FIFOEMP.
+                        */
+                       if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
+                               break;
+               } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
+                       uint32_t sgptr;
+                       uint64_t data_addr;
+                       uint32_t data_len;
+                       u_int    dfcntrl;
+
+                       /*
+                        * Disable S/G fetch so the DMA engine
+                        * is available to future users.
+                        */
+                       if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
+                               ahd_outb(ahd, CCSGCTL, 0);
+                               ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
+                       }
+
+                       /*
+                        * Wait for the DMA engine to notice that the
+                        * host transfer is enabled and that there is
+                        * space in the S/G FIFO for new segments before
+                        * loading more segments.
+                        */
+                       if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) == 0)
+                               continue;
+                       if ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) == 0)
+                               continue;
+
+                       /*
+                        * Determine the offset of the next S/G
+                        * element to load.
+                        */
+                       sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
+                       sgptr &= SG_PTR_MASK;
+                       if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
+                               struct ahd_dma64_seg *sg;
+
+                               sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
+                               data_addr = sg->addr;
+                               data_len = sg->len;
+                               sgptr += sizeof(*sg);
+                       } else {
+                               struct  ahd_dma_seg *sg;
+
+                               sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
+                               data_addr = sg->len & AHD_SG_HIGH_ADDR_MASK;
+                               data_addr <<= 8;
+                               data_addr |= sg->addr;
+                               data_len = sg->len;
+                               sgptr += sizeof(*sg);
+                       }
+
+                       /*
+                        * Update residual information.
+                        */
+                       ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, data_len >> 24);
+                       ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
+
+                       /*
+                        * Load the S/G.
+                        */
+                       if (data_len & AHD_DMA_LAST_SEG) {
+                               sgptr |= LAST_SEG;
+                               ahd_outb(ahd, SG_STATE, 0);
+                       }
+                       ahd_outq(ahd, HADDR, data_addr);
+                       ahd_outl(ahd, HCNT, data_len & AHD_SG_LEN_MASK);
+                       ahd_outb(ahd, SG_CACHE_PRE, sgptr & 0xFF);
+
+                       /*
+                        * Advertise the segment to the hardware.
+                        */
+                       dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;
+                       if ((ahd->features & AHD_NEW_DFCNTRL_OPTS)!=0) {
+                               /*
+                                * Use SCSIENWRDIS so that SCSIEN
+                                * is never modified by this
+                                * operation.
+                                */
+                               dfcntrl |= SCSIENWRDIS;
+                       }
+                       ahd_outb(ahd, DFCNTRL, dfcntrl);
+               } else if ((ahd_inb(ahd, SG_CACHE_SHADOW)
+                        & LAST_SEG_DONE) != 0) {
+
+                       /*
+                        * Transfer completed to the end of SG list
+                        * and has flushed to the host.
+                        */
+                       ahd_outb(ahd, SCB_SGPTR,
+                                ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
+                       break;
+               } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
+                       break;
                }
-               ahd_complete_scb(ahd, scb);
+               ahd_delay(200);
        }
-
        /*
-        * Restore state.
+        * Clear any handler for this FIFO, decrement
+        * the FIFO use count for the SCB, and release
+        * the FIFO.
         */
-       ahd_restore_modes(ahd, saved_modes);
-       ahd->flags |= AHD_UPDATE_PEND_CMDS;
+       ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
+       ahd_outb(ahd, SCB_FIFO_USE_COUNT,
+                ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
+       ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
 }
 
 void
@@ -791,7 +1113,8 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
                         * attempt to complete this bogus SCB.
                         */
                        ahd_outb(ahd, SCB_CONTROL,
-                                ahd_inb(ahd, SCB_CONTROL) & ~STATUS_RCVD);
+                                ahd_inb_scbram(ahd, SCB_CONTROL)
+                                & ~STATUS_RCVD);
                }
                break;
        }
@@ -1024,7 +1347,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
                                           ROLE_INITIATOR, /*status*/0,
                                           SEARCH_REMOVE);
                ahd_outb(ahd, SCB_CONTROL,
-                        ahd_inb(ahd, SCB_CONTROL) & ~MK_MESSAGE);
+                        ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE);
                break;
        }
        case TASKMGMT_FUNC_COMPLETE:
@@ -3193,7 +3516,7 @@ ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
                       devinfo->target_mask);
                panic("SCB = %d, SCB Control = %x:%x, MSG_OUT = %x "
                      "SCB flags = %x", SCB_GET_TAG(scb), scb->hscb->control,
-                     ahd_inb(ahd, SCB_CONTROL), ahd_inb(ahd, MSG_OUT),
+                     ahd_inb_scbram(ahd, SCB_CONTROL), ahd_inb(ahd, MSG_OUT),
                      scb->flags);
        }
 
@@ -4421,7 +4744,8 @@ ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
 
                sgptr = ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);
                if ((sgptr & SG_LIST_NULL) != 0
-                && (ahd_inb(ahd, SCB_TASK_ATTRIBUTE) & SCB_XFERLEN_ODD) != 0) {
+                && (ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)
+                    & SCB_XFERLEN_ODD) != 0) {
                        /*
                         * If the residual occurred on the last
                         * transfer and the transfer request was
@@ -4522,7 +4846,8 @@ ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
                         * correct for subsequent data transfers.
                         */
                        ahd_outb(ahd, SCB_TASK_ATTRIBUTE,
-                           ahd_inb(ahd, SCB_TASK_ATTRIBUTE) ^ SCB_XFERLEN_ODD);
+                           ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)
+                           ^ SCB_XFERLEN_ODD);
 
                        ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
                        ahd_outl(ahd, SCB_RESIDUAL_DATACNT, data_cnt);
@@ -8507,10 +8832,12 @@ ahd_dump_card_state(struct ahd_softc *ahd)
                if (i++ > AHD_SCB_MAX)
                        break;
                cur_col = kprintf("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb),
-                                ahd_inb(ahd, SCB_FIFO_USE_COUNT));
+                                ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT));
                ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
-               ahd_scb_control_print(ahd_inb(ahd, SCB_CONTROL), &cur_col, 60);
-               ahd_scb_scsiid_print(ahd_inb(ahd, SCB_SCSIID), &cur_col, 60);
+               ahd_scb_control_print(ahd_inb_scbram(ahd, SCB_CONTROL),
+                                     &cur_col, 60);
+               ahd_scb_scsiid_print(ahd_inb_scbram(ahd, SCB_SCSIID),
+                                    &cur_col, 60);
        }
        kprintf("\nTotal %d\n", i);
 
@@ -8539,7 +8866,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
        while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
                ahd_set_scbptr(ahd, scb_index);
                kprintf("%d ", scb_index);
-               scb_index = ahd_inw(ahd, SCB_NEXT_COMPLETE);
+               scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
        }
        kprintf("\n");
 
@@ -8549,7 +8876,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
        while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
                ahd_set_scbptr(ahd, scb_index);
                kprintf("%d ", scb_index);
-               scb_index = ahd_inw(ahd, SCB_NEXT_COMPLETE);
+               scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
        }
        kprintf("\n");
 
@@ -8560,7 +8887,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
        while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
                ahd_set_scbptr(ahd, scb_index);
                kprintf("%d ", scb_index);
-               scb_index = ahd_inw(ahd, SCB_NEXT_COMPLETE);
+               scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
        }
        kprintf("\n");
        ahd_set_scbptr(ahd, saved_scb_index);
@@ -8639,15 +8966,16 @@ ahd_dump_card_state(struct ahd_softc *ahd)
               ahd_name(ahd), ahd_inw(ahd, REG0), ahd_inw(ahd, SINDEX),
               ahd_inw(ahd, DINDEX));
        kprintf("%s: SCBPTR == 0x%x, SCB_NEXT == 0x%x, SCB_NEXT2 == 0x%x\n",
-              ahd_name(ahd), ahd_get_scbptr(ahd), ahd_inw(ahd, SCB_NEXT),
-              ahd_inw(ahd, SCB_NEXT2));
+              ahd_name(ahd), ahd_get_scbptr(ahd),
+              ahd_inw_scbram(ahd, SCB_NEXT),
+              ahd_inw_scbram(ahd, SCB_NEXT2));
        kprintf("CDB %x %x %x %x %x %x\n",
-              ahd_inb(ahd, SCB_CDB_STORE),
-              ahd_inb(ahd, SCB_CDB_STORE+1),
-              ahd_inb(ahd, SCB_CDB_STORE+2),
-              ahd_inb(ahd, SCB_CDB_STORE+3),
-              ahd_inb(ahd, SCB_CDB_STORE+4),
-              ahd_inb(ahd, SCB_CDB_STORE+5));
+              ahd_inb_scbram(ahd, SCB_CDB_STORE),
+              ahd_inb_scbram(ahd, SCB_CDB_STORE+1),
+              ahd_inb_scbram(ahd, SCB_CDB_STORE+2),
+              ahd_inb_scbram(ahd, SCB_CDB_STORE+3),
+              ahd_inb_scbram(ahd, SCB_CDB_STORE+4),
+              ahd_inb_scbram(ahd, SCB_CDB_STORE+5));
        kprintf("STACK:");
        for (i = 0; i < ahd->stack_size; i++) {
                ahd->saved_stack[i] =
@@ -8679,10 +9007,12 @@ ahd_dump_scbs(struct ahd_softc *ahd)
                ahd_set_scbptr(ahd, i);
                kprintf("%3d", i);
                kprintf("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n",
-                      ahd_inb(ahd, SCB_CONTROL),
-                      ahd_inb(ahd, SCB_SCSIID), ahd_inw(ahd, SCB_NEXT),
-                      ahd_inw(ahd, SCB_NEXT2), ahd_inl(ahd, SCB_SGPTR),
-                      ahd_inl(ahd, SCB_RESIDUAL_SGPTR));
+                      ahd_inb_scbram(ahd, SCB_CONTROL),
+                      ahd_inb_scbram(ahd, SCB_SCSIID),
+                      ahd_inw_scbram(ahd, SCB_NEXT),
+                      ahd_inw_scbram(ahd, SCB_NEXT2),
+                      ahd_inl_scbram(ahd, SCB_SGPTR),
+                      ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR));
        }
        kprintf("\n");
        ahd_set_scbptr(ahd, saved_scb_index);