ahc_eisa.c:
authorPeter Avalos <pavalos@dragonflybsd.org>
Fri, 6 Jul 2007 00:01:16 +0000 (00:01 +0000)
committerPeter Avalos <pavalos@dragonflybsd.org>
Fri, 6 Jul 2007 00:01:16 +0000 (00:01 +0000)
ahc_pci.c:
ahd_pci.c:
aic7xxx.c:
aic79xx.c:
aic_osm_lib.c:
aic_osm_lib.h:
Use common OSM routines from aic_osm_lib for bus dma operations,
delay routines, accessing CCBs, byte swapping, etc.

aic7xxx_pci.c:
Provide a better description for the 2915/30LP on attach.

aic79xx.h:
aic79xx_pci.c:
aic79xx.seq:
To speed up non-packetized CDB delivery in Rev B, all CDB
acks are "released" to the output sync as soon as the
command phase starts.  There is only one problem with this
approach.  If the target changes phase before all data are
sent, we have left over acks that can go out on the bus in
a data phase.  Due to other chip contraints, this only
happens if the target goes to data-in, but if the acks go
out before we can test SDONE, we'll think that the transfer
has completed successfully.  Work around this by taking
advantage of the 400ns or 800ns dead time between command
phase and the REQ of the new phase.  If the transfer has
completed successfully, SCSIEN should fall *long* before we
see a phase change.  We thus treat any phasemiss that
occurs before SCSIEN falls as an incomplete transfer.

aic79xx.h:
Add the AHD_FAST_CDB_DELIVERY feature.

aic79xx_pci.c:
Set AHD_FAST_CDB_DELIVERY for all Rev. B parts.

aic79xx.seq:
Test for PHASEMIS in the command phase for
all AHD_FAST_CDB_DELIVERY controlelrs.

ahd_pci.c:
ahc_pci.c:
aic7xxx.h:
aic79xx.h:
Move definition of controller BAR offsets to core header files.

aic7xxx.c:
aic79xx.c:
In the softc free routine, leave removal of a softc from the
global list of softcs to the OSM (the caller of this routine).
This allows us to avoid holding the softc list_lock during device
destruction where we may have to sleep waiting for our recovery
thread to halt.

ahc_pci.c:
Use ahc_pci_test_register access to validate I/O mapped in
addition to the tests already performed for memory mapped
access.

Remove unused ahc_power_state_change() function.

ahd_pci.c:
Remove reduntant definition of controller BAR offsets.  These
are also defined in aic79xx.h.

Remove unused ahd_power_state_change() function.

aic7xxx.c:
aic79xx.c:
aic79xx.h:
aic7xxx.h:
aic7xxx_osm.c:
aic79xx_osm.c:
Move timeout handling to the driver cores.  In the case
of the aic79xx driver, the algorithm has been enhanced
to try target resets before performing a bus reset.  For
the aic7xxx driver, the algorithm is unchanged.  Although
the drivers do not currently sleep during recovery (recovery
is timeout driven), the cores do expect all processing to
be performed via a recovery thread.  Our timeout handlers
are now little stubs that wakeup the recovery thread.

aic79xx.c:
aic79xx.h:
aic79xx_inline.h:
Change shared_data allocation to use a map_node so
that the sentinel hscb can use this map node in
ahd_swap_with_next_hscb.  This routine now swaps
the hscb_map pointer in additon to the hscb
contents so that any sync operations occur on
the correct map.

physaddr -> busaddr

Pointed out by: Jason Thorpe <thorpej@wasabisystems.com>

aic79xx.c:
Make more use of the in/out/w/l/q macros for accessing
byte registers in the chip.

Correct some issues in the ahd_flush_qoutfifo() routine.
    o Run the qoutfifo only once the command channel
      DMA engine has been halted.  This closes a window
      where we might have missed some entries.
    o Change ahd_run_data_fifo() to not loop to completion.
      If we happen to start on the wrong FIFO and the other
      FIFO has a snapshot savepointers, we might deadlock.
      This required our delay between FIFO tests to be
      moved to the ahd_flush_qoutfifo() routine.
    o Update/add comments.
    o Remove spurious test for COMPLETE_DMA list being empty
      when completing transactions from the GSFIFO with
      residuals.  The SCB must be put on the COMPLETE_DMA
      scb list unconditionally.
    o When halting command channel DMA activity, we must
      disable the DMA channel in all cases but an update
      of the QOUTFIFO.  The latter case is required so
      that the sequencer will update its position in the
      QOUTFIFO.  Previously, we left the channel enabled
      for all "push" DMAs.  This left us vulnerable to
      the sequencer handling an SCB push long after that
      SCB was already processed manually by this routine.
    o Correct the polarity of tests involving
      ahd_scb_active_in_fifo().  This routine returns
      non-zero for true.

Return to processing bad status completions through
the qoutfifo.  This reduces the time that the sequencer
is kept paused when handling transactions with bad
status or underruns.

When waiting for the controller to quiece selections,
add a delay to our loop.  Otherwise we may fail to wait
long enough for the sequencer to comply.

On H2A4 hardware, use the slow slewrate for non-paced
transfers.  This mirrors what the Adaptec Windows
drivers do.

On the Rev B. only slow down the CRC timing for
older U160 devices that might need the slower timing.
We define "older" as devices that do not support
packetized protocol.

Wait up to 5000 * 5us for the SEEPROM to become unbusy.
Write ops seem to take much longer than read ops.

aic79xx.seq:
For controllers with the FAINT_LED bug, turn the diagnostic
led feature on during selection and reselection.  This covers
the non-packetized case.  The LED will be disabled for
non-packetized transfers once we return to the top level idle
loop.  Add more comments about the busy LED workaround.

Extend a critical section around the entire
command channel idle loop process.  Previously
the portion of this handler that directly manipulated
the linked list of completed SCBs was not protected.
This is the likely cause of the recent reports of
commands being completed twice by the driver.

Extend critical sections across the test for,
and the longjump to, longjump routines.  This
prevents the firmware from trying to jump to
a longjmp handler that was just cleared by the
host.

Improve the locations of several critical section
begin and end points.  Typically these changes
remove instructions that did not need to be
inside a critical section.

Close the "busfree after selection, but before busfree
interrupts can be enabled" race to just a single sequencer
instruction.  We now test the BSY line explicitly before
clearing the busfree status and enabling the busfree
interrupt.

Close a race condition in the processing of HS_MAILBOX
updates.  We now clear the "updated" status before the
copy.  This ensures that we don't accidentally clear
the status incorrectly when the host sneaks in an update
just after our last copy, but before we clear the status.
This race has never been observed.

Don't re-enable SCSIEN if we lose the race to disable SCSIEN
in our interrupt handler's workaround for the RevA data-valid
too early issue.

aic79xx_inline.h:
Add comments indicating that the order in which bytes are
read or written in ahd_inw and ahd_outw is important.  This
allows us to use these inlines when accessing registers with
side-effects.

aic79xx_pci.c:
The 29320 and the 29320B are 7902 not 7901 based products.
Correct the driver banner.

aic7xxx.h:
Enable the use of the auto-access pause feature
on the aic7870 and aic7880.  It was disabled due
to an oversight.

aic7xxx.reg:
Move TARG_IMMEDIATE_SCB to alias LAST_MSG to
avoid leaving garbage in MWI_RESIDUAL.  This
prevents spurious overflows whn operating target
mode on controllers that require the MWI_RESIDUAL
work-around.

aic7xxx.seq:
AHC_TMODE_WIDEODD_BUG is a bug, not a softc flag.
Reference the correct softc field when testing
for its presence.

Set the NOT_IDENTIFIED and NO_CDB_SENT bits
in SEQ_FLAGS to indicate that the nexus is
invalid in await busfree.

aic7xxx_93cx6.c:
Add support for the C56/C66 versions of the EWEN and EWDS
commands.

aic7xxx.c:
aic7xxx_pci.c:
Move test for the validity of left over BIOS data
to ahc_test_register_access().  This guarantees that
any left over CHIPRST value is not clobbered by our
register access test and lost to the test that was
in ahc_reset.

Obtained-from: FreeBSD

22 files changed:
sys/dev/disk/aic7xxx/ahc_eisa.c
sys/dev/disk/aic7xxx/ahc_pci.c
sys/dev/disk/aic7xxx/ahd_pci.c
sys/dev/disk/aic7xxx/aic7770.c
sys/dev/disk/aic7xxx/aic79xx.c
sys/dev/disk/aic7xxx/aic79xx.h
sys/dev/disk/aic7xxx/aic79xx.seq
sys/dev/disk/aic7xxx/aic79xx_inline.h
sys/dev/disk/aic7xxx/aic79xx_osm.c
sys/dev/disk/aic7xxx/aic79xx_osm.h
sys/dev/disk/aic7xxx/aic79xx_pci.c
sys/dev/disk/aic7xxx/aic7xxx.c
sys/dev/disk/aic7xxx/aic7xxx.h
sys/dev/disk/aic7xxx/aic7xxx.reg
sys/dev/disk/aic7xxx/aic7xxx.seq
sys/dev/disk/aic7xxx/aic7xxx_93cx6.c
sys/dev/disk/aic7xxx/aic7xxx_inline.h
sys/dev/disk/aic7xxx/aic7xxx_osm.c
sys/dev/disk/aic7xxx/aic7xxx_osm.h
sys/dev/disk/aic7xxx/aic7xxx_pci.c
sys/dev/disk/aic7xxx/aic_osm_lib.c [new file with mode: 0644]
sys/dev/disk/aic7xxx/aic_osm_lib.h [new file with mode: 0644]

index a098cb2..482d21e 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahc_eisa.c#11 $
+ * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahc_eisa.c#13 $
  *
- * $FreeBSD: src/sys/dev/aic7xxx/ahc_eisa.c,v 1.15.2.11 2003/06/10 03:26:07 gibbs Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/ahc_eisa.c,v 1.6 2006/12/22 23:26:15 swildner Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/ahc_eisa.c,v 1.32 2003/12/17 00:02:09 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/ahc_eisa.c,v 1.7 2007/07/06 00:01:16 pavalos Exp $
  */
 
 #include "aic7xxx_osm.h"
@@ -130,7 +130,7 @@ aic7770_attach(device_t dev)
 
        /* Allocate a dmatag for our SCB DMA maps */
        /* XXX Should be a child of the PCI bus dma tag */
-       error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1,
+       error = aic_dma_tag_create(ahc, /*parent*/NULL, /*alignment*/1,
                                   /*boundary*/0,
                                   /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
                                   /*highaddr*/BUS_SPACE_MAXADDR,
index 5d19169..f244f76 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahc_pci.c#13 $
+ * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahc_pci.c#19 $
  *
- * $FreeBSD: src/sys/dev/aic7xxx/ahc_pci.c,v 1.56 2003/09/02 17:30:34 jhb Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/ahc_pci.c,v 1.9 2007/07/05 05:08:32 pavalos Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/ahc_pci.c,v 1.60 2003/12/17 00:02:09 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/ahc_pci.c,v 1.10 2007/07/06 00:01:16 pavalos Exp $
  */
 
 #include "aic7xxx_osm.h"
 
 #ifdef AHC_PCI_CONFIG
 
-#define        AHC_PCI_IOADDR  PCIR_BAR(0)     /* I/O Address */
-#define        AHC_PCI_MEMADDR PCIR_BAR(1)     /* Mem I/O Address */
-
 static int ahc_pci_probe(device_t dev);
 static int ahc_pci_attach(device_t dev);
 
@@ -110,7 +107,7 @@ ahc_pci_attach(device_t dev)
 
        /* Allocate a dmatag for our SCB DMA maps */
        /* XXX Should be a child of the PCI bus dma tag */
-       error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1,
+       error = aic_dma_tag_create(ahc, /*parent*/NULL, /*alignment*/1,
                                   /*boundary*/0,
                                   (ahc->flags & AHC_39BIT_ADDRESSING)
                                   ? 0x7FFFFFFFFFULL
@@ -149,7 +146,7 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
        int     regs_id;
        int     allow_memio;
 
-       command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
+       command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
        regs = NULL;
        regs_type = 0;
        regs_id = 0;
@@ -189,15 +186,15 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
                                device_printf(ahc->dev_softc,
                                       "PCI Device %d:%d:%d failed memory "
                                       "mapped test.  Using PIO.\n",
-                                      ahc_get_pci_bus(ahc->dev_softc),
-                                      ahc_get_pci_slot(ahc->dev_softc),
-                                      ahc_get_pci_function(ahc->dev_softc));
+                                      aic_get_pci_bus(ahc->dev_softc),
+                                      aic_get_pci_slot(ahc->dev_softc),
+                                      aic_get_pci_function(ahc->dev_softc));
                                bus_release_resource(ahc->dev_softc, regs_type,
                                                     regs_id, regs);
                                regs = NULL;
                        } else {
                                command &= ~PCIM_CMD_PORTEN;
-                               ahc_pci_write_config(ahc->dev_softc,
+                               aic_pci_write_config(ahc->dev_softc,
                                                     PCIR_COMMAND,
                                                     command, /*bytes*/1);
                        }
@@ -212,9 +209,22 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
                if (regs != NULL) {
                        ahc->tag = rman_get_bustag(regs);
                        ahc->bsh = rman_get_bushandle(regs);
-                       command &= ~PCIM_CMD_MEMEN;
-                       ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
-                                            command, /*bytes*/1);
+                       if (ahc_pci_test_register_access(ahc) != 0) {
+                               device_printf(ahc->dev_softc,
+                                      "PCI Device %d:%d:%d failed I/O "
+                                      "mapped test.\n",
+                                      aic_get_pci_bus(ahc->dev_softc),
+                                      aic_get_pci_slot(ahc->dev_softc),
+                                      aic_get_pci_function(ahc->dev_softc));
+                               bus_release_resource(ahc->dev_softc, regs_type,
+                                                    regs_id, regs);
+                               regs = NULL;
+                       } else {
+                               command &= ~PCIM_CMD_MEMEN;
+                               aic_pci_write_config(ahc->dev_softc,
+                                                    PCIR_COMMAND,
+                                                    command, /*bytes*/1);
+                       }
                }
        }
        if (regs == NULL) {
@@ -246,39 +256,5 @@ ahc_pci_map_int(struct ahc_softc *ahc)
        return (ahc_map_int(ahc));
 }
 
-void
-ahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state)
-{
-       uint32_t cap;
-       u_int cap_offset;
-
-       /*
-        * Traverse the capability list looking for
-        * the power management capability.
-        */
-       cap = 0;
-       cap_offset = ahc_pci_read_config(ahc->dev_softc,
-                                        PCIR_CAP_PTR, /*bytes*/1);
-       while (cap_offset != 0) {
-
-               cap = ahc_pci_read_config(ahc->dev_softc,
-                                         cap_offset, /*bytes*/4);
-               if ((cap & 0xFF) == 1
-                && ((cap >> 16) & 0x3) > 0) {
-                       uint32_t pm_control;
-
-                       pm_control = ahc_pci_read_config(ahc->dev_softc,
-                                                        cap_offset + 4,
-                                                        /*bytes*/2);
-                       pm_control &= ~0x3;
-                       pm_control |= new_state;
-                       ahc_pci_write_config(ahc->dev_softc,
-                                            cap_offset + 4,
-                                            pm_control, /*bytes*/2);
-                       break;
-               }
-               cap_offset = (cap >> 8) & 0xFF;
-       }
-}
 
 #endif
index f2cabd1..d0b8565 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahd_pci.c#13 $
+ * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahd_pci.c#17 $
  *
- * $FreeBSD: src/sys/dev/aic7xxx/ahd_pci.c,v 1.11 2003/09/02 17:30:34 jhb Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/ahd_pci.c,v 1.8 2007/07/05 05:08:32 pavalos Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/ahd_pci.c,v 1.15 2003/12/17 00:02:09 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/ahd_pci.c,v 1.9 2007/07/06 00:01:16 pavalos Exp $
  */
 
 #include "aic79xx_osm.h"
 
-#define        AHD_PCI_IOADDR0 PCIR_BAR(0)     /* Primary I/O BAR */
-#define        AHD_PCI_MEMADDR PCIR_BAR(1)     /* Mem I/O Address */
-#define        AHD_PCI_IOADDR1 PCIR_BAR(3)     /* Secondary I/O BAR */
-
 static int ahd_pci_probe(device_t dev);
 static int ahd_pci_attach(device_t dev);
 
@@ -111,7 +107,7 @@ ahd_pci_attach(device_t dev)
 
        /* Allocate a dmatag for our SCB DMA maps */
        /* XXX Should be a child of the PCI bus dma tag */
-       error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1,
+       error = aic_dma_tag_create(ahd, /*parent*/NULL, /*alignment*/1,
                                   /*boundary*/0,
                                   (ahd->flags & AHD_39BIT_ADDRESSING)
                                   ? 0x7FFFFFFFFFULL
@@ -152,7 +148,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd)
        int     regs_id2;
        int     allow_memio;
 
-       command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1);
+       command = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1);
        regs = NULL;
        regs2 = NULL;
        regs_type = 0;
@@ -194,15 +190,15 @@ ahd_pci_map_registers(struct ahd_softc *ahd)
                                device_printf(ahd->dev_softc,
                                       "PCI Device %d:%d:%d failed memory "
                                       "mapped test.  Using PIO.\n",
-                                      ahd_get_pci_bus(ahd->dev_softc),
-                                      ahd_get_pci_slot(ahd->dev_softc),
-                                      ahd_get_pci_function(ahd->dev_softc));
+                                      aic_get_pci_bus(ahd->dev_softc),
+                                      aic_get_pci_slot(ahd->dev_softc),
+                                      aic_get_pci_function(ahd->dev_softc));
                                bus_release_resource(ahd->dev_softc, regs_type,
                                                     regs_id, regs);
                                regs = NULL;
                        } else {
                                command &= ~PCIM_CMD_PORTEN;
-                               ahd_pci_write_config(ahd->dev_softc,
+                               aic_pci_write_config(ahd->dev_softc,
                                                     PCIR_COMMAND,
                                                     command, /*bytes*/1);
                        }
@@ -233,7 +229,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd)
                ahd->tags[1] = rman_get_bustag(regs2);
                ahd->bshs[1] = rman_get_bushandle(regs2);
                command &= ~PCIM_CMD_MEMEN;
-               ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
+               aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
                                     command, /*bytes*/1);
                ahd->platform_data->regs_res_type[1] = regs_type;
                ahd->platform_data->regs_res_id[1] = regs_id2;
@@ -259,38 +255,3 @@ ahd_pci_map_int(struct ahd_softc *ahd)
        ahd->platform_data->irq_res_type = SYS_RES_IRQ;
        return (ahd_map_int(ahd));
 }
-
-void
-ahd_power_state_change(struct ahd_softc *ahd, ahd_power_state new_state)
-{
-       uint32_t cap;
-       u_int cap_offset;
-
-       /*
-        * Traverse the capability list looking for
-        * the power management capability.
-        */
-       cap = 0;
-       cap_offset = ahd_pci_read_config(ahd->dev_softc,
-                                        PCIR_CAP_PTR, /*bytes*/1);
-       while (cap_offset != 0) {
-
-               cap = ahd_pci_read_config(ahd->dev_softc,
-                                         cap_offset, /*bytes*/4);
-               if ((cap & 0xFF) == 1
-                && ((cap >> 16) & 0x3) > 0) {
-                       uint32_t pm_control;
-
-                       pm_control = ahd_pci_read_config(ahd->dev_softc,
-                                                        cap_offset + 4,
-                                                        /*bytes*/2);
-                       pm_control &= ~0x3;
-                       pm_control |= new_state;
-                       ahd_pci_write_config(ahd->dev_softc,
-                                            cap_offset + 4,
-                                            pm_control, /*bytes*/2);
-                       break;
-               }
-               cap_offset = (cap >> 8) & 0xFF;
-       }
-}
index 709b245..fcef375 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/aic7770.c#32 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7770.c#34 $
  *
- * $FreeBSD: src/sys/dev/aic7xxx/aic7770.c,v 1.1.2.9 2003/06/10 03:26:07 gibbs Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/aic7770.c,v 1.7 2007/01/27 15:03:25 swildner Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/aic7770.c,v 1.16 2003/12/17 00:02:09 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/aic7770.c,v 1.8 2007/07/06 00:01:16 pavalos Exp $
  */
 
 #ifdef __linux__
@@ -175,7 +175,7 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
        case 15:
                break;
        default:
-               kprintf("aic7770_config: illegal irq setting %d\n", intdef);
+               kprintf("aic7770_config: invalid irq setting %d\n", intdef);
                return (ENXIO);
        }
 
index 63667c0..47144e5 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#202 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#224 $
  *
- * $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 $
+ * $FreeBSD: src/sys/dev/aic7xxx/aic79xx.c,v 1.27 2003/12/19 04:17:43 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx.c,v 1.18 2007/07/06 00:01:16 pavalos Exp $
  */
 
 #include "aic79xx_osm.h"
@@ -219,6 +219,9 @@ 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 void            ahd_other_scb_timeout(struct ahd_softc *ahd,
+                                             struct scb *scb,
+                                             struct scb *other_scb);
 static int             ahd_scb_active_in_fifo(struct ahd_softc *ahd,
                                               struct scb *scb);
 static void            ahd_run_data_fifo(struct ahd_softc *ahd,
@@ -370,13 +373,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
        saved_modes = ahd_save_modes(ahd);
 
        /*
-        * 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.
+        * Flush the good status FIFO for completed packetized commands.
         */
        ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
        saved_scbptr = ahd_get_scbptr(ahd);
@@ -384,8 +381,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
                u_int fifo_mode;
                u_int i;
                
-               scbid = (ahd_inb(ahd, GSFIFO+1) << 8)
-                     | ahd_inb(ahd, GSFIFO);
+               scbid = ahd_inw(ahd, GSFIFO);
                scb = ahd_lookup_scb(ahd, scbid);
                if (scb == NULL) {
                        kprintf("%s: Warning - GSFIFO SCB %d invalid\n",
@@ -398,22 +394,33 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
                 * the host before completing the  command.
                 */
                fifo_mode = 0;
+rescan_fifos:
                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.
+                        * Running this FIFO may cause a CFG4DATA for
+                        * this same transaction to assert in the other
+                        * FIFO or a new snapshot SAVEPTRS interrupt
+                        * in this FIFO.  Even running a FIFO may not
+                        * clear the transaction if we are still waiting
+                        * for data to drain to the host. We must loop
+                        * until the transaction is not active in either
+                        * FIFO just to be sure.  Reset our loop counter
+                        * so we will visit both FIFOs again before
+                        * declaring this transaction finished.  We
+                        * also delay a bit so that status has a chance
+                        * to change before we look at this FIFO again.
                         */
-                       i = 0;
+                       aic_delay(200);
+                       goto rescan_fifos;
                }
                ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
                ahd_set_scbptr(ahd, scbid);
@@ -426,7 +433,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
                        /*
                         * The transfer completed with a residual.
                         * Place this SCB on the complete DMA list
-                        * so that we Update our in-core copy of the
+                        * so that we update our in-core copy of the
                         * SCB before completing the command.
                         */
                        ahd_outb(ahd, SCB_SCSI_STATUS, 0);
@@ -436,9 +443,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
                        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));
+                       ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_GET_TAG(scb));
                } else
                        ahd_complete_scb(ahd, scb);
        }
@@ -460,11 +465,24 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
                                break;
                } else if ((ccscbctl & CCSCBDONE) != 0)
                        break;
-               ahd_delay(200);
+               aic_delay(200);
        }
-       if ((ccscbctl & CCSCBDIR) != 0)
+       /*
+        * We leave the sequencer to cleanup in the case of DMA's to
+        * update the qoutfifo.  In all other cases (DMA's to the
+        * chip or a push of an SCB from the COMPLETE_DMA_SCB list),
+        * we disable the DMA engine so that the sequencer will not
+        * attempt to handle the DMA completion.
+        */
+       if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 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
@@ -555,150 +573,146 @@ 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);
+       seqintsrc = ahd_inb(ahd, SEQINTSRC);
+       if ((seqintsrc & CFG4DATA) != 0) {
+               uint32_t datacnt;
+               uint32_t 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);
+               /*
+                * Clear full residual flag.
+                */
+               sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
+               ahd_outb(ahd, SCB_SGPTR, sgptr);
 
-                       /*
-                        * Initialize Residual Fields.
-                        */
-                       ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
-                       ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
+               /*
+                * 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);
 
-                       /*
-                        * 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);
+               /*
+                * Initialize Residual Fields.
+                */
+               ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
+               ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
 
-                       /*
-                        * Install a "fake" handler for this FIFO.
-                        */
-                       ahd_outw(ahd, LONGJMP_ADDR, 0);
+               /*
+                * 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);
 
-                       /*
-                        * 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;
+               /*
+                * Install a "fake" handler for this FIFO.
+                */
+               ahd_outw(ahd, LONGJMP_ADDR, 0);
 
-                       if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
-                               /*
-                                * Snapshot Save Pointers.  Clear
-                                * the snapshot and continue.
-                                */
-                               ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
-                               continue;
-                       }
+               /*
+                * 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) {
                        /*
-                        * Disable S/G fetch so the DMA engine
-                        * is available to future users.
+                        * Snapshot Save Pointers.  All that
+                        * is necessary to clear the snapshot
+                        * is a CLRCHN.
                         */
-                       if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
-                               ahd_outb(ahd, CCSGCTL, 0);
-                       ahd_outb(ahd, SG_STATE, 0);
+                       goto clrchn;
+               }
 
-                       /*
-                        * Flush the data FIFO.  Strickly only
-                        * necessary for Rev A parts.
-                        */
-                       ahd_outb(ahd, DFCNTRL,
-                                ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
+               /*
+                * 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);
 
-                       /*
-                        * 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;
+               /*
+                * 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) {
                        /*
-                        * Disable S/G fetch so the DMA engine
-                        * is available to future users.
+                        * 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_STATE) & FETCH_INPROG) != 0) {
-                               ahd_outb(ahd, CCSGCTL, 0);
-                               ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
-                       }
+                       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)
+                       goto clrchn;
+       } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
+               uint32_t sgptr;
+               uint64_t data_addr;
+               uint32_t data_len;
+               u_int    dfcntrl;
 
-                       /*
-                        * 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;
+               /*
+                * Disable S/G fetch so the DMA engine
+                * is available to future users.  We won't
+                * be using the DMA engine to load segments.
+                */
+               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
+                && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) {
 
                        /*
                         * Determine the offset of the next S/G
@@ -745,7 +759,7 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
                         * Advertise the segment to the hardware.
                         */
                        dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;
-                       if ((ahd->features & AHD_NEW_DFCNTRL_OPTS)!=0) {
+                       if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {
                                /*
                                 * Use SCSIENWRDIS so that SCSIEN
                                 * is never modified by this
@@ -754,30 +768,28 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
                                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_delay(200);
+       } 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);
+               goto clrchn;
+       } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
+clrchn:
+               /*
+                * Clear any handler for this FIFO, decrement
+                * the FIFO use count for the SCB, and release
+                * the FIFO.
+                */
+               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);
        }
-       /*
-        * Clear any handler for this FIFO, decrement
-        * the FIFO use count for the SCB, and release
-        * the FIFO.
-        */
-       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
@@ -793,7 +805,7 @@ ahd_run_qoutfifo(struct ahd_softc *ahd)
        while ((ahd->qoutfifo[ahd->qoutfifonext]
             & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) {
 
-               scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext]
+               scb_index = aic_le16toh(ahd->qoutfifo[ahd->qoutfifonext]
                                      & ~QOUTFIFO_ENTRY_VALID_LE);
                scb = ahd_lookup_scb(ahd, scb_index);
                if (scb == NULL) {
@@ -873,26 +885,6 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
                       ahd_name(ahd), seqintcode);
 #endif
        switch (seqintcode) {
-       case BAD_SCB_STATUS:
-       {
-               struct  scb *scb;
-               u_int   scbid;
-               int     cmds_pending;
-
-               scbid = ahd_get_scbptr(ahd);
-               scb = ahd_lookup_scb(ahd, scbid);
-               if (scb != NULL) {
-                       ahd_complete_scb(ahd, scb);
-               } else {
-                       kprintf("%s: WARNING no command for scb %d "
-                              "(bad status)\n", ahd_name(ahd), scbid);
-                       ahd_dump_card_state(ahd);
-               }
-               cmds_pending = ahd_inw(ahd, CMDS_PENDING);
-               if (cmds_pending > 0)
-                       ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1);
-               break;
-       }
        case ENTERING_NONPACK:
        {
                struct  scb *scb;
@@ -1057,11 +1049,11 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
                        ahd_outb(ahd, SAVED_LUN, 0);
                        ahd_outb(ahd, SEQ_FLAGS, 0);
                        ahd_assert_atn(ahd);
-                       scb->flags &= ~(SCB_PACKETIZED);
+                       scb->flags &= ~SCB_PACKETIZED;
                        scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;
                        ahd_freeze_devq(ahd, scb);
-                       ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
-                       ahd_freeze_scb(scb);
+                       aic_set_transaction_status(scb, CAM_REQUEUE_REQ);
+                       aic_freeze_scb(scb);
 
                        /*
                         * Allow the sequencer to continue with
@@ -1309,7 +1301,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
                               "NumSGs = %d.\n",
                               ahd_inb(ahd, SEQ_FLAGS) & DPHASE
                               ? "Have" : "Haven't",
-                              ahd_get_transfer_length(scb), scb->sg_count);
+                              aic_get_transfer_length(scb), scb->sg_count);
                        ahd_dump_sglist(scb);
                }
 #endif
@@ -1319,8 +1311,8 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
                 * target does a command complete.
                 */
                ahd_freeze_devq(ahd, scb);
-               ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR);
-               ahd_freeze_scb(scb);
+               aic_set_transaction_status(scb, CAM_DATA_RUN_ERR);
+               aic_freeze_scb(scb);
                break;
        }
        case MKMSG_FAILED:
@@ -1581,7 +1573,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
                         */
                        ahd_scb_devinfo(ahd, &devinfo, scb);
                        ahd_force_renegotiation(ahd, &devinfo);
-                       ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT);
+                       aic_set_transaction_status(scb, CAM_SEL_TIMEOUT);
                        ahd_freeze_devq(ahd, scb);
                }
                ahd_outb(ahd, CLRINT, CLRSCSIINT);
@@ -2028,8 +2020,8 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
                        }
                        scb->crc_retry_count++;
                } else {
-                       ahd_set_transaction_status(scb, CAM_UNCOR_PARITY);
-                       ahd_freeze_scb(scb);
+                       aic_set_transaction_status(scb, CAM_UNCOR_PARITY);
+                       aic_freeze_scb(scb);
                        ahd_freeze_devq(ahd, scb);
                }
                /* Return unpausing the sequencer. */
@@ -2171,7 +2163,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
                         && ahd_match_scb(ahd, scb, target, 'A',
                                          CAM_LUN_WILDCARD, SCB_LIST_NULL,
                                          ROLE_INITIATOR))
-                               ahd_set_transaction_status(scb, CAM_REQ_CMP);
+                               aic_set_transaction_status(scb, CAM_REQ_CMP);
 #endif
                        ahd_handle_devreset(ahd, &devinfo, CAM_LUN_WILDCARD,
                                            CAM_BDR_SENT, "Bus Device Reset",
@@ -2262,8 +2254,8 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
         && ((ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0)) {
 
                ahd_freeze_devq(ahd, scb);
-               ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
-               ahd_freeze_scb(scb);
+               aic_set_transaction_status(scb, CAM_REQUEUE_REQ);
+               aic_freeze_scb(scb);
                if ((ahd->msg_flags & MSG_FLAG_IU_REQ_CHANGED) != 0) {
                        ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
                                       SCB_GET_CHANNEL(ahd, scb),
@@ -2307,8 +2299,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
                       "PRGMCNT == 0x%x\n",
                       ahd_lookup_phase_entry(lastphase)->phasemsg,
                       aborted,
-                      ahd_inb(ahd, PRGMCNT)
-                       | (ahd_inb(ahd, PRGMCNT+1) << 8));
+                      ahd_inw(ahd, PRGMCNT));
                ahd_dump_card_state(ahd);
        }
        /* Always restart the sequencer. */
@@ -2352,7 +2343,7 @@ ahd_handle_proto_violation(struct ahd_softc *ahd)
                kprintf("No SCB found during protocol violation\n");
                goto proto_violation_reset;
        } else {
-               ahd_set_transaction_status(scb, CAM_SEQUENCE_FAIL);
+               aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL);
                if ((seq_flags & NO_CDB_SENT) != 0) {
                        ahd_print_path(ahd, scb);
                        kprintf("No or incomplete CDB sent to device.\n");
@@ -2471,8 +2462,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd)
                u_int   i;
 
                ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
-               seqaddr = ahd_inb(ahd, CURADDR)
-                       | (ahd_inb(ahd, CURADDR+1) << 8);
+               seqaddr = ahd_inw(ahd, CURADDR);
 
                cs = ahd->critical_sections;
                for (i = 0; i < ahd->num_critical_sections; i++, cs++) {
@@ -2532,7 +2522,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd)
                ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
                ahd_outb(ahd, HCNTRL, ahd->unpause);
                while (!ahd_is_paused(ahd))
-                       ahd_delay(200);
+                       aic_delay(200);
                ahd_update_modes(ahd);
        }
        if (stepping) {
@@ -2608,10 +2598,10 @@ ahd_print_scb(struct scb *scb)
        for (i = 0; i < sizeof(hscb->shared_data.idata.cdb); i++)
                kprintf("%#02x", hscb->shared_data.idata.cdb[i]);
        kprintf("        dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n",
-              (uint32_t)((ahd_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF),
-              (uint32_t)(ahd_le64toh(hscb->dataptr) & 0xFFFFFFFF),
-              ahd_le32toh(hscb->datacnt),
-              ahd_le32toh(hscb->sgptr),
+              (uint32_t)((aic_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF),
+              (uint32_t)(aic_le64toh(hscb->dataptr) & 0xFFFFFFFF),
+              aic_le32toh(hscb->datacnt),
+              aic_le32toh(hscb->sgptr),
               SCB_GET_TAG(scb));
        ahd_dump_sglist(scb);
 }
@@ -2630,8 +2620,8 @@ ahd_dump_sglist(struct scb *scb)
                                uint64_t addr;
                                uint32_t len;
 
-                               addr = ahd_le64toh(sg_list[i].addr);
-                               len = ahd_le32toh(sg_list[i].len);
+                               addr = aic_le64toh(sg_list[i].addr);
+                               len = aic_le32toh(sg_list[i].len);
                                kprintf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
                                       i,
                                       (uint32_t)((addr >> 32) & 0xFFFFFFFF),
@@ -2647,11 +2637,11 @@ ahd_dump_sglist(struct scb *scb)
                        for (i = 0; i < scb->sg_count; i++) {
                                uint32_t len;
 
-                               len = ahd_le32toh(sg_list[i].len);
+                               len = aic_le32toh(sg_list[i].len);
                                kprintf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
                                       i,
                                       (len & AHD_SG_HIGH_ADDR_MASK) >> 24,
-                                      ahd_le32toh(sg_list[i].addr),
+                                      aic_le32toh(sg_list[i].addr),
                                       len & AHD_SG_LEN_MASK,
                                       len & AHD_DMA_LAST_SEG ? " Last" : "");
                        }
@@ -3191,14 +3181,25 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
                iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK;
 
                if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0
-                && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0) {
+                && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0
+                && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) {
                        /*
                         * Slow down our CRC interval to be
-                        * compatible with devices that can't
-                        * handle a CRC at full speed.
+                        * compatible with non-packetized
+                        * U160 devices that can't handle a
+                        * CRC at full speed.
                         */
                        con_opts |= ENSLOWCRC;
                }
+
+               if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {
+                       /*
+                        * On H2A4, revert to a slower slewrate
+                        * on non-paced transfers.
+                        */
+                       iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=
+                           ~AHD_SLEWRATE_MASK;
+               }
        }
 
        ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW);
@@ -4669,7 +4670,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
                ahd_outb(ahd, SCB_CONTROL,
                         ahd_inb_scbram(ahd, SCB_CONTROL) & mask);
                scb->hscb->control &= mask;
-               ahd_set_transaction_tag(scb, /*enabled*/FALSE,
+               aic_set_transaction_tag(scb, /*enabled*/FALSE,
                                        /*type*/MSG_SIMPLE_TASK);
                ahd_outb(ahd, MSG_OUT, MSG_IDENTIFYFLAG);
                ahd_assert_atn(ahd);
@@ -4727,7 +4728,7 @@ ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
         * Perhaps add datadir to some spare bits in the hscb?
         */
        if ((ahd_inb(ahd, SEQ_FLAGS) & DPHASE) == 0
-        || ahd_get_transfer_dir(scb) != CAM_DIR_IN) {
+        || aic_get_transfer_dir(scb) != CAM_DIR_IN) {
                /*
                 * Ignore the message if we haven't
                 * seen an appropriate data phase yet.
@@ -4782,18 +4783,18 @@ ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
                                 * to load so we must go back one.
                                 */
                                sg--;
-                               sglen = ahd_le32toh(sg->len) & AHD_SG_LEN_MASK;
+                               sglen = aic_le32toh(sg->len) & AHD_SG_LEN_MASK;
                                if (sg != scb->sg_list
                                 && sglen < (data_cnt & AHD_SG_LEN_MASK)) {
 
                                        sg--;
-                                       sglen = ahd_le32toh(sg->len);
+                                       sglen = aic_le32toh(sg->len);
                                        /*
                                         * Preserve High Address and SG_LIST
                                         * bits while setting the count to 1.
                                         */
                                        data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK));
-                                       data_addr = ahd_le64toh(sg->addr)
+                                       data_addr = aic_le64toh(sg->addr)
                                                  + (sglen & AHD_SG_LEN_MASK)
                                                  - 1;
 
@@ -4815,18 +4816,18 @@ ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
                                 * to load so we must go back one.
                                 */
                                sg--;
-                               sglen = ahd_le32toh(sg->len) & AHD_SG_LEN_MASK;
+                               sglen = aic_le32toh(sg->len) & AHD_SG_LEN_MASK;
                                if (sg != scb->sg_list
                                 && sglen < (data_cnt & AHD_SG_LEN_MASK)) {
 
                                        sg--;
-                                       sglen = ahd_le32toh(sg->len);
+                                       sglen = aic_le32toh(sg->len);
                                        /*
                                         * Preserve High Address and SG_LIST
                                         * bits while setting the count to 1.
                                         */
                                        data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK));
-                                       data_addr = ahd_le32toh(sg->addr)
+                                       data_addr = aic_le32toh(sg->addr)
                                                  + (sglen & AHD_SG_LEN_MASK)
                                                  - 1;
 
@@ -4888,7 +4889,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
        ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
        wait = 1000;
        while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE))
-               ahd_delay(100);
+               aic_delay(100);
        if (wait == 0) {
                ahd_print_path(ahd, scb);
                kprintf("ahd_reinitialize_dataptrs: Forcing FIFO free.\n");
@@ -4904,10 +4905,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
         * Determine initial values for data_addr and data_cnt
         * for resuming the data phase.
         */
-       sgptr = (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24)
-             | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16)
-             | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8)
-             | ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);
+       sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
        sgptr &= SG_PTR_MASK;
 
        resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16)
@@ -4922,13 +4920,10 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
                /* The residual sg_ptr always points to the next sg */
                sg--;
 
-               dataptr = ahd_le64toh(sg->addr)
-                       + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK)
+               dataptr = aic_le64toh(sg->addr)
+                       + (aic_le32toh(sg->len) & AHD_SG_LEN_MASK)
                        - resid;
-               ahd_outb(ahd, HADDR + 7, dataptr >> 56);
-               ahd_outb(ahd, HADDR + 6, dataptr >> 48);
-               ahd_outb(ahd, HADDR + 5, dataptr >> 40);
-               ahd_outb(ahd, HADDR + 4, dataptr >> 32);
+               ahd_outl(ahd, HADDR + 4, dataptr >> 32);
        } else {
                struct   ahd_dma_seg *sg;
 
@@ -4937,16 +4932,13 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
                /* The residual sg_ptr always points to the next sg */
                sg--;
 
-               dataptr = ahd_le32toh(sg->addr)
-                       + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK)
+               dataptr = aic_le32toh(sg->addr)
+                       + (aic_le32toh(sg->len) & AHD_SG_LEN_MASK)
                        - resid;
                ahd_outb(ahd, HADDR + 4,
-                        (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24);
+                        (aic_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24);
        }
-       ahd_outb(ahd, HADDR + 3, dataptr >> 24);
-       ahd_outb(ahd, HADDR + 2, dataptr >> 16);
-       ahd_outb(ahd, HADDR + 1, dataptr >> 8);
-       ahd_outb(ahd, HADDR, dataptr);
+       ahd_outl(ahd, HADDR, dataptr);
        ahd_outb(ahd, HCNT + 2, resid >> 16);
        ahd_outb(ahd, HCNT + 1, resid >> 8);
        ahd_outb(ahd, HCNT, resid);
@@ -5127,8 +5119,8 @@ ahd_alloc(void *platform_arg, char *name)
        ahd->bugs = AHD_BUGNONE;
        ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A
                   | AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A;
-       ahd_timer_init(&ahd->reset_timer);
-       ahd_timer_init(&ahd->stat_timer);
+       aic_timer_init(&ahd->reset_timer);
+       aic_timer_init(&ahd->stat_timer);
        ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT;
        ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT;
        ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT;
@@ -5164,24 +5156,24 @@ ahd_softc_insert(struct ahd_softc *ahd)
 {
        struct ahd_softc *list_ahd;
 
-#if AHD_PCI_CONFIG > 0
+#if AIC_PCI_CONFIG > 0
        /*
         * Second Function PCI devices need to inherit some
         * settings from function 0.
         */
        if ((ahd->features & AHD_MULTI_FUNC) != 0) {
                TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
-                       ahd_dev_softc_t list_pci;
-                       ahd_dev_softc_t pci;
+                       aic_dev_softc_t list_pci;
+                       aic_dev_softc_t pci;
 
                        list_pci = list_ahd->dev_softc;
                        pci = ahd->dev_softc;
-                       if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci)
-                        && ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) {
+                       if (aic_get_pci_slot(list_pci) == aic_get_pci_slot(pci)
+                        && aic_get_pci_bus(list_pci) == aic_get_pci_bus(pci)) {
                                struct ahd_softc *master;
                                struct ahd_softc *slave;
 
-                               if (ahd_get_pci_function(list_pci) == 0) {
+                               if (aic_get_pci_function(list_pci) == 0) {
                                        master = list_ahd;
                                        slave = ahd;
                                } else {
@@ -5246,27 +5238,27 @@ ahd_free(struct ahd_softc *ahd)
 {
        int i;
 
+       ahd_terminate_recovery_thread(ahd);
        switch (ahd->init_level) {
        default:
        case 5:
                ahd_shutdown(ahd);
-               TAILQ_REMOVE(&ahd_tailq, ahd, links);
                /* FALLTHROUGH */
        case 4:
-               ahd_dmamap_unload(ahd, ahd->shared_data_dmat,
-                                 ahd->shared_data_dmamap);
+               aic_dmamap_unload(ahd, ahd->shared_data_dmat,
+                                 ahd->shared_data_map.dmamap);
                /* FALLTHROUGH */
        case 3:
-               ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo,
-                               ahd->shared_data_dmamap);
-               ahd_dmamap_destroy(ahd, ahd->shared_data_dmat,
-                                  ahd->shared_data_dmamap);
+               aic_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo,
+                               ahd->shared_data_map.dmamap);
+               aic_dmamap_destroy(ahd, ahd->shared_data_dmat,
+                                  ahd->shared_data_map.dmamap);
                /* FALLTHROUGH */
        case 2:
-               ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat);
+               aic_dma_tag_destroy(ahd, ahd->shared_data_dmat);
        case 1:
 #ifndef __linux__
-               ahd_dma_tag_destroy(ahd, ahd->buffer_dmat);
+               aic_dma_tag_destroy(ahd, ahd->buffer_dmat);
 #endif
                break;
        case 0:
@@ -5274,7 +5266,7 @@ ahd_free(struct ahd_softc *ahd)
        }
 
 #ifndef __linux__
-       ahd_dma_tag_destroy(ahd, ahd->parent_dmat);
+       aic_dma_tag_destroy(ahd, ahd->parent_dmat);
 #endif
        ahd_platform_free(ahd);
        ahd_fini_scbdata(ahd);
@@ -5327,8 +5319,8 @@ ahd_shutdown(void *arg)
        /*
         * Stop periodic timer callbacks.
         */
-       ahd_timer_stop(&ahd->reset_timer);
-       ahd_timer_stop(&ahd->stat_timer);
+       aic_timer_stop(&ahd->reset_timer);
+       aic_timer_stop(&ahd->stat_timer);
 
        /* This will reset most registers to 0, but not all */
        ahd_reset(ahd, /*reinit*/FALSE);
@@ -5360,7 +5352,7 @@ ahd_reset(struct ahd_softc *ahd, int reinit)
        ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
        sxfrctl1 = ahd_inb(ahd, SXFRCTL1);
 
-       cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);
+       cmd = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);
        if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) {
                uint32_t mod_cmd;
 
@@ -5374,7 +5366,7 @@ ahd_reset(struct ahd_softc *ahd, int reinit)
                 * PERR and SERR responses during the CHIPRST.
                 */
                mod_cmd = cmd & ~(PCIM_CMD_PERRESPEN|PCIM_CMD_SERRESPEN);
-               ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
+               aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
                                     mod_cmd, /*bytes*/2);
        }
        ahd_outb(ahd, HCNTRL, CHIPRST | ahd->pause);
@@ -5387,7 +5379,7 @@ ahd_reset(struct ahd_softc *ahd, int reinit)
         */
        wait = 1000;
        do {
-               ahd_delay(1000);
+               aic_delay(1000);
        } while (--wait && !(ahd_inb(ahd, HCNTRL) & CHIPRSTACK));
 
        if (wait == 0) {
@@ -5401,9 +5393,9 @@ ahd_reset(struct ahd_softc *ahd, int reinit)
                 * Clear any latched PCI error status and restore
                 * previous SERR and PERR response enables.
                 */
-               ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
+               aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
                                     0xFF, /*bytes*/1);
-               ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
+               aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
                                     cmd, /*bytes*/2);
        }
 
@@ -5530,7 +5522,7 @@ ahd_init_scbdata(struct ahd_softc *ahd)
         */
 
        /* DMA tag for our hardware scb structures */
-       if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
+       if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
                               /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
                               /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
                               /*highaddr*/BUS_SPACE_MAXADDR,
@@ -5544,7 +5536,7 @@ ahd_init_scbdata(struct ahd_softc *ahd)
        scb_data->init_level++;
 
        /* DMA tag for our S/G structures. */
-       if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/8,
+       if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/8,
                               /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
                               /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
                               /*highaddr*/BUS_SPACE_MAXADDR,
@@ -5563,7 +5555,7 @@ ahd_init_scbdata(struct ahd_softc *ahd)
        scb_data->init_level++;
 
        /* DMA tag for our sense buffers.  We allocate in page sized chunks */
-       if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
+       if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
                               /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
                               /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
                               /*highaddr*/BUS_SPACE_MAXADDR,
@@ -5651,13 +5643,13 @@ ahd_fini_scbdata(struct ahd_softc *ahd)
 
                while ((sns_map = SLIST_FIRST(&scb_data->sense_maps)) != NULL) {
                        SLIST_REMOVE_HEAD(&scb_data->sense_maps, links);
-                       ahd_dmamap_unload(ahd, scb_data->sense_dmat,
+                       aic_dmamap_unload(ahd, scb_data->sense_dmat,
                                          sns_map->dmamap);
-                       ahd_dmamem_free(ahd, scb_data->sense_dmat,
+                       aic_dmamem_free(ahd, scb_data->sense_dmat,
                                        sns_map->vaddr, sns_map->dmamap);
                        kfree(sns_map, M_DEVBUF);
                }
-               ahd_dma_tag_destroy(ahd, scb_data->sense_dmat);
+               aic_dma_tag_destroy(ahd, scb_data->sense_dmat);
                /* FALLTHROUGH */
        }
        case 6:
@@ -5666,13 +5658,13 @@ ahd_fini_scbdata(struct ahd_softc *ahd)
 
                while ((sg_map = SLIST_FIRST(&scb_data->sg_maps)) != NULL) {
                        SLIST_REMOVE_HEAD(&scb_data->sg_maps, links);
-                       ahd_dmamap_unload(ahd, scb_data->sg_dmat,
+                       aic_dmamap_unload(ahd, scb_data->sg_dmat,
                                          sg_map->dmamap);
-                       ahd_dmamem_free(ahd, scb_data->sg_dmat,
+                       aic_dmamem_free(ahd, scb_data->sg_dmat,
                                        sg_map->vaddr, sg_map->dmamap);
                        kfree(sg_map, M_DEVBUF);
                }
-               ahd_dma_tag_destroy(ahd, scb_data->sg_dmat);
+               aic_dma_tag_destroy(ahd, scb_data->sg_dmat);
                /* FALLTHROUGH */
        }
        case 5:
@@ -5681,13 +5673,13 @@ ahd_fini_scbdata(struct ahd_softc *ahd)
 
                while ((hscb_map = SLIST_FIRST(&scb_data->hscb_maps)) != NULL) {
                        SLIST_REMOVE_HEAD(&scb_data->hscb_maps, links);
-                       ahd_dmamap_unload(ahd, scb_data->hscb_dmat,
+                       aic_dmamap_unload(ahd, scb_data->hscb_dmat,
                                          hscb_map->dmamap);
-                       ahd_dmamem_free(ahd, scb_data->hscb_dmat,
+                       aic_dmamem_free(ahd, scb_data->hscb_dmat,
                                        hscb_map->vaddr, hscb_map->dmamap);
                        kfree(hscb_map, M_DEVBUF);
                }
-               ahd_dma_tag_destroy(ahd, scb_data->hscb_dmat);
+               aic_dma_tag_destroy(ahd, scb_data->hscb_dmat);
                /* FALLTHROUGH */
        }
        case 4:
@@ -5892,7 +5884,7 @@ ahd_free_scb(struct ahd_softc *ahd, struct scb *scb)
                                 scb, links.le);
        }
 
-       ahd_platform_scb_free(ahd, scb);
+       aic_platform_scb_free(ahd, scb);
 }
 
 void
@@ -5923,12 +5915,12 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
                offset = (PAGE_SIZE / sizeof(*hscb)) - scb_data->scbs_left;
                hscb_map = SLIST_FIRST(&scb_data->hscb_maps);
                hscb = &((struct hardware_scb *)hscb_map->vaddr)[offset];
-               hscb_busaddr = hscb_map->physaddr + (offset * sizeof(*hscb));
+               hscb_busaddr = hscb_map->busaddr + (offset * sizeof(*hscb));
        } else {
                hscb_map = kmalloc(sizeof(*hscb_map), M_DEVBUF, M_INTWAIT);
 
                /* Allocate the next batch of hardware SCBs */
-               if (ahd_dmamem_alloc(ahd, scb_data->hscb_dmat,
+               if (aic_dmamem_alloc(ahd, scb_data->hscb_dmat,
                                     (void **)&hscb_map->vaddr,
                                     BUS_DMA_NOWAIT, &hscb_map->dmamap) != 0) {
                        kfree(hscb_map, M_DEVBUF);
@@ -5937,12 +5929,12 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
 
                SLIST_INSERT_HEAD(&scb_data->hscb_maps, hscb_map, links);
 
-               ahd_dmamap_load(ahd, scb_data->hscb_dmat, hscb_map->dmamap,
+               aic_dmamap_load(ahd, scb_data->hscb_dmat, hscb_map->dmamap,
                                hscb_map->vaddr, PAGE_SIZE, ahd_dmamap_cb,
-                               &hscb_map->physaddr, /*flags*/0);
+                               &hscb_map->busaddr, /*flags*/0);
 
                hscb = (struct hardware_scb *)hscb_map->vaddr;
-               hscb_busaddr = hscb_map->physaddr;
+               hscb_busaddr = hscb_map->busaddr;
                scb_data->scbs_left = PAGE_SIZE / sizeof(*hscb);
        }
 
@@ -5953,12 +5945,12 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
                       - scb_data->sgs_left) * ahd_sglist_size(ahd);
                sg_map = SLIST_FIRST(&scb_data->sg_maps);
                segs = sg_map->vaddr + offset;
-               sg_busaddr = sg_map->physaddr + offset;
+               sg_busaddr = sg_map->busaddr + offset;
        } else {
                sg_map = kmalloc(sizeof(*sg_map), M_DEVBUF, M_INTWAIT);
 
                /* Allocate the next batch of S/G lists */
-               if (ahd_dmamem_alloc(ahd, scb_data->sg_dmat,
+               if (aic_dmamem_alloc(ahd, scb_data->sg_dmat,
                                     (void **)&sg_map->vaddr,
                                     BUS_DMA_NOWAIT, &sg_map->dmamap) != 0) {
                        kfree(sg_map, M_DEVBUF);
@@ -5967,12 +5959,12 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
 
                SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links);
 
-               ahd_dmamap_load(ahd, scb_data->sg_dmat, sg_map->dmamap,
+               aic_dmamap_load(ahd, scb_data->sg_dmat, sg_map->dmamap,
                                sg_map->vaddr, ahd_sglist_allocsize(ahd),
-                               ahd_dmamap_cb, &sg_map->physaddr, /*flags*/0);
+                               ahd_dmamap_cb, &sg_map->busaddr, /*flags*/0);
 
                segs = sg_map->vaddr;
-               sg_busaddr = sg_map->physaddr;
+               sg_busaddr = sg_map->busaddr;
                scb_data->sgs_left =
                    ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd);
 #ifdef AHD_DEBUG
@@ -5987,12 +5979,12 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
                offset = PAGE_SIZE - (AHD_SENSE_BUFSIZE * scb_data->sense_left);
                sense_map = SLIST_FIRST(&scb_data->sense_maps);
                sense_data = sense_map->vaddr + offset;
-               sense_busaddr = sense_map->physaddr + offset;
+               sense_busaddr = sense_map->busaddr + offset;
        } else {
                sense_map = kmalloc(sizeof(*sense_map), M_DEVBUF, M_INTWAIT);
 
                /* Allocate the next batch of sense buffers */
-               if (ahd_dmamem_alloc(ahd, scb_data->sense_dmat,
+               if (aic_dmamem_alloc(ahd, scb_data->sense_dmat,
                                     (void **)&sense_map->vaddr,
                                     BUS_DMA_NOWAIT, &sense_map->dmamap) != 0) {
                        kfree(sense_map, M_DEVBUF);
@@ -6001,12 +5993,12 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
 
                SLIST_INSERT_HEAD(&scb_data->sense_maps, sense_map, links);
 
-               ahd_dmamap_load(ahd, scb_data->sense_dmat, sense_map->dmamap,
+               aic_dmamap_load(ahd, scb_data->sense_dmat, sense_map->dmamap,
                                sense_map->vaddr, PAGE_SIZE, ahd_dmamap_cb,
-                               &sense_map->physaddr, /*flags*/0);
+                               &sense_map->busaddr, /*flags*/0);
 
                sense_data = sense_map->vaddr;
-               sense_busaddr = sense_map->physaddr;
+               sense_busaddr = sense_map->busaddr;
                scb_data->sense_left = PAGE_SIZE / AHD_SENSE_BUFSIZE;
 #ifdef AHD_DEBUG
                if (ahd_debug & AHD_SHOW_MEMORY)
@@ -6038,7 +6030,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
                next_scb->sense_busaddr = sense_busaddr;
                memset(hscb, 0, sizeof(*hscb));
                next_scb->hscb = hscb;
-               hscb->hscb_busaddr = ahd_htole32(hscb_busaddr);
+               hscb->hscb_busaddr = aic_htole32(hscb_busaddr);
 
                /*
                 * The sequencer always starts with the second entry.
@@ -6053,7 +6045,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
                next_scb->ahd_softc = ahd;
                next_scb->flags = SCB_FLAG_NONE;
 #ifndef __linux__
-               error = ahd_dmamap_create(ahd, ahd->buffer_dmat, /*flags*/0,
+               error = aic_dmamap_create(ahd, ahd->buffer_dmat, /*flags*/0,
                                          &next_scb->dmamap);
                if (error != 0) {
                        kfree(next_scb, M_DEVBUF);
@@ -6061,7 +6053,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
                        break;
                }
 #endif
-               next_scb->hscb->tag = ahd_htole16(scb_data->numscbs);
+               next_scb->hscb->tag = aic_htole16(scb_data->numscbs);
                col_tag = scb_data->numscbs ^ 0x100;
                next_scb->col_scb = ahd_find_scb_by_tag(ahd, col_tag);
                if (next_scb->col_scb != NULL)
@@ -6122,7 +6114,6 @@ static const char *termstat_strings[] = {
 int
 ahd_init(struct ahd_softc *ahd)
 {
-       uint8_t         *base_vaddr;
        uint8_t         *next_vaddr;
        bus_addr_t       next_baddr;
        size_t           driver_data_size;
@@ -6163,7 +6154,7 @@ ahd_init(struct ahd_softc *ahd)
 
 #ifndef __linux__
        /* DMA tag for mapping buffers into device visible space. */
-       if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
+       if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
                               /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
                               /*lowaddr*/ahd->flags & AHD_39BIT_ADDRESSING
                                        ? (bus_addr_t)0x7FFFFFFFFFULL
@@ -6194,7 +6185,7 @@ ahd_init(struct ahd_softc *ahd)
                driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd);
        if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0)
                driver_data_size += PKT_OVERRUN_BUFSIZE;
-       if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
+       if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,
                               /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
                               /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
                               /*highaddr*/BUS_SPACE_MAXADDR,
@@ -6209,21 +6200,24 @@ ahd_init(struct ahd_softc *ahd)
        ahd->init_level++;
 
        /* Allocation of driver data */
-       if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat,
-                            (void **)&base_vaddr,
-                            BUS_DMA_NOWAIT, &ahd->shared_data_dmamap) != 0) {
+       if (aic_dmamem_alloc(ahd, ahd->shared_data_dmat,
+                            (void **)&ahd->shared_data_map.vaddr,
+                            BUS_DMA_NOWAIT,
+                            &ahd->shared_data_map.dmamap) != 0) {
                return (ENOMEM);
        }
 
        ahd->init_level++;
 
        /* And permanently map it in */
-       ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
-                       base_vaddr, driver_data_size, ahd_dmamap_cb,
-                       &ahd->shared_data_busaddr, /*flags*/0);
-       ahd->qoutfifo = (uint16_t *)base_vaddr;
+       aic_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+                       ahd->shared_data_map.vaddr, driver_data_size,
+                       ahd_dmamap_cb, &ahd->shared_data_map.busaddr,
+                       /*flags*/0);
+       ahd->qoutfifo = (uint16_t *)ahd->shared_data_map.vaddr;
        next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE];
-       next_baddr = ahd->shared_data_busaddr + AHD_QOUT_SIZE*sizeof(uint16_t);
+       next_baddr = ahd->shared_data_map.busaddr
+                  + AHD_QOUT_SIZE*sizeof(uint16_t);
        if ((ahd->features & AHD_TARGETMODE) != 0) {
                ahd->targetcmds = (struct target_cmd *)next_vaddr;
                next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);
@@ -6244,7 +6238,8 @@ ahd_init(struct ahd_softc *ahd)
         * specially from the DMA safe memory chunk used for the QOUTFIFO.
         */
        ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;
-       ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr);
+       ahd->next_queued_hscb_map = &ahd->shared_data_map;
+       ahd->next_queued_hscb->hscb_busaddr = aic_htole32(next_baddr);
 
        ahd->init_level++;
 
@@ -6335,7 +6330,7 @@ ahd_init(struct ahd_softc *ahd)
        }
 init_done:
        ahd_restart(ahd);
-       ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US,
+       aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US,
                        ahd_stat_timer, ahd);
        return (0);
 }
@@ -6396,7 +6391,7 @@ ahd_chip_init(struct ahd_softc *ahd)
        for (wait = 10000;
             (ahd_inb(ahd, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait;
             wait--)
-               ahd_delay(100);
+               aic_delay(100);
 
        /* Clear any false bus resets due to the transceivers settling */
        ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
@@ -6594,15 +6589,9 @@ ahd_chip_init(struct ahd_softc *ahd)
        /*
         * Tell the sequencer where it can find our arrays in memory.
         */
-       busaddr = ahd->shared_data_busaddr;
-       ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF);
-       ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF);
-       ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF);
-       ahd_outb(ahd, SHARED_DATA_ADDR + 3, (busaddr >> 24) & 0xFF);
-       ahd_outb(ahd, QOUTFIFO_NEXT_ADDR, busaddr & 0xFF);
-       ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 1, (busaddr >> 8) & 0xFF);
-       ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 2, (busaddr >> 16) & 0xFF);
-       ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 3, (busaddr >> 24) & 0xFF);
+       busaddr = ahd->shared_data_map.busaddr;
+       ahd_outl(ahd, SHARED_DATA_ADDR, busaddr);
+       ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr);
 
        /*
         * Setup the allowed SCSI Sequences based on operational mode.
@@ -6650,11 +6639,8 @@ ahd_chip_init(struct ahd_softc *ahd)
        /*
         * Tell the sequencer which SCB will be the next one it receives.
         */
-       busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);
-       ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);
-       ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
-       ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
-       ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
+       busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr);
+       ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
 
        /*
         * Default to coalescing disabled.
@@ -6975,6 +6961,12 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
                struct scb *waiting_scb;
 
                ahd_unpause(ahd);
+               /*
+                * Give the sequencer some time to service
+                * any active selections.
+                */
+               aic_delay(200);
+
                ahd_intr(ahd);
                ahd_pause(ahd);
                ahd_clear_critical_section(ahd);
@@ -7186,11 +7178,8 @@ ahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb,
        if (prev_scb == NULL) {
                uint32_t busaddr;
 
-               busaddr = ahd_le32toh(scb->hscb->hscb_busaddr);
-               ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);
-               ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
-               ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
-               ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
+               busaddr = aic_le32toh(scb->hscb->hscb_busaddr);
+               ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
        } else {
                prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
                ahd_sync_scb(ahd, prev_scb, 
@@ -7296,11 +7285,8 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
         * for removal will be re-added to the queue as we go.
         */
        ahd->qinfifonext = qinstart;
-       busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);
-       ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);
-       ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
-       ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
-       ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
+       busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr);
+       ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
 
        while (qinpos != qintail) {
                scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]);
@@ -7321,13 +7307,13 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
                                cam_status ostat;
                                cam_status cstat;
 
-                               ostat = ahd_get_transaction_status(scb);
+                               ostat = aic_get_transaction_status(scb);
                                if (ostat == CAM_REQ_INPROG)
-                                       ahd_set_transaction_status(scb,
+                                       aic_set_transaction_status(scb,
                                                                   status);
-                               cstat = ahd_get_transaction_status(scb);
+                               cstat = aic_get_transaction_status(scb);
                                if (cstat != CAM_REQ_CMP)
-                                       ahd_freeze_scb(scb);
+                                       aic_freeze_scb(scb);
                                if ((scb->flags & SCB_ACTIVE) == 0)
                                        kprintf("Inactive SCB in qinfifo\n");
                                ahd_done(ahd, scb);
@@ -7463,12 +7449,12 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel,
                        cam_status ostat;
                        cam_status cstat;
 
-                       ostat = ahd_get_transaction_status(scb);
+                       ostat = aic_get_transaction_status(scb);
                        if (ostat == CAM_REQ_INPROG)
-                               ahd_set_transaction_status(scb, status);
-                       cstat = ahd_get_transaction_status(scb);
+                               aic_set_transaction_status(scb, status);
+                       cstat = aic_get_transaction_status(scb);
                        if (cstat != CAM_REQ_CMP)
-                               ahd_freeze_scb(scb);
+                               aic_freeze_scb(scb);
                        if ((scb->flags & SCB_ACTIVE) == 0)
                                kprintf("Inactive SCB in Waiting List\n");
                        ahd_done(ahd, scb);
@@ -7659,11 +7645,11 @@ ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel,
                if (ahd_match_scb(ahd, scbp, target, channel, lun, tag, role)) {
                        cam_status ostat;
 
-                       ostat = ahd_get_transaction_status(scbp);
+                       ostat = aic_get_transaction_status(scbp);
                        if (ostat == CAM_REQ_INPROG)
-                               ahd_set_transaction_status(scbp, status);
-                       if (ahd_get_transaction_status(scbp) != CAM_REQ_CMP)
-                               ahd_freeze_scb(scbp);
+                               aic_set_transaction_status(scbp, status);
+                       if (aic_get_transaction_status(scbp) != CAM_REQ_CMP)
+                               aic_freeze_scb(scbp);
                        if ((scbp->flags & SCB_ACTIVE) == 0)
                                kprintf("Inactive SCB on pending list\n");
                        ahd_done(ahd, scbp);
@@ -7686,11 +7672,11 @@ ahd_reset_current_bus(struct ahd_softc *ahd)
        scsiseq = ahd_inb(ahd, SCSISEQ0) & ~(ENSELO|ENARBO|SCSIRSTO);
        ahd_outb(ahd, SCSISEQ0, scsiseq | SCSIRSTO);
        ahd_flush_device_writes(ahd);
-       ahd_delay(AHD_BUSRESET_DELAY);
+       aic_delay(AHD_BUSRESET_DELAY);
        /* Turn off the bus reset */
        ahd_outb(ahd, SCSISEQ0, scsiseq);
        ahd_flush_device_writes(ahd);
-       ahd_delay(AHD_BUSRESET_DELAY);
+       aic_delay(AHD_BUSRESET_DELAY);
        if ((ahd->bugs & AHD_SCSIRST_BUG) != 0) {
                /*
                 * 2A Razor #474
@@ -7758,7 +7744,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
                ahd_outb(ahd, DFCNTRL,
                         ahd_inb(ahd, DFCNTRL) & ~(SCSIEN|HDMAEN));
                while ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0)
-                       ahd_delay(10);
+                       aic_delay(10);
                /*
                 * Set CURRFIFO to the now inactive channel.
                 */
@@ -7771,7 +7757,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
         */
        ahd_clear_msg_state(ahd);
        ahd_outb(ahd, SIMODE1,
-                ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE));
+                ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));
 
        if (initiate_reset)
                ahd_reset_current_bus(ahd);
@@ -7853,8 +7839,8 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
         */
        if ((ahd->flags & AHD_RESET_POLL_ACTIVE) == 0) {
                ahd->flags |= AHD_RESET_POLL_ACTIVE;
-               ahd_freeze_simq(ahd);
-               ahd_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd);
+               aic_freeze_simq(ahd);
+               aic_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd);
        }
        return (found);
 }
@@ -7878,7 +7864,7 @@ ahd_reset_poll(void *arg)
        ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
        ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
        if ((ahd_inb(ahd, SSTAT1) & SCSIRSTI) != 0) {
-               ahd_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US,
+               aic_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US,
                                ahd_reset_poll, ahd);
                ahd_unpause(ahd);
                ahd_unlock();
@@ -7892,7 +7878,7 @@ ahd_reset_poll(void *arg)
        ahd_unpause(ahd);
        ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
        ahd_unlock();
-       ahd_release_simq(ahd);
+       aic_release_simq(ahd);
 }
 
 /**************************** Statistics Processing ***************************/
@@ -7930,7 +7916,7 @@ ahd_stat_timer(void *arg)
        ahd->cmdcmplt_bucket = (ahd->cmdcmplt_bucket+1) & (AHD_STAT_BUCKETS-1);
        ahd->cmdcmplt_total -= ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket];
        ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket] = 0;
-       ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US,
+       aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US,
                        ahd_stat_timer, ahd);
        ahd_unlock();
 }
@@ -7950,8 +7936,9 @@ ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb)
 void
 ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
 {
-       struct hardware_scb *hscb;
-       u_int  qfreeze_cnt;
+       struct  hardware_scb *hscb;
+       u_int   qfreeze_cnt;
+       int     paused;
 
        /*
         * The sequencer freezes its select-out queue
@@ -7961,9 +7948,16 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
         */
        hscb = scb->hscb; 
 
+       if (ahd_is_paused(ahd)) {
+               paused = 1;
+       } else {
+               paused = 0;
+               ahd_pause(ahd);
+       }
+
        /* Freeze the queue until the client sees the error. */
        ahd_freeze_devq(ahd, scb);
-       ahd_freeze_scb(scb);
+       aic_freeze_scb(scb);
        qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT);
        if (qfreeze_cnt == 0) {
                kprintf("%s: Bad status with 0 qfreeze count!\n", ahd_name(ahd));
@@ -7975,6 +7969,9 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
                ahd_outb(ahd, SEQ_FLAGS2,
                         ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);
 
+       if (paused == 0)
+               ahd_unpause(ahd);
+
        /* Don't want to clobber the original sense code */
        if ((scb->flags & SCB_SENSE) != 0) {
                /*
@@ -7982,12 +7979,12 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
                 * a normal command completion.
                 */
                scb->flags &= ~SCB_SENSE;
-               ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
+               aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
                ahd_done(ahd, scb);
                return;
        }
-       ahd_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR);
-       ahd_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status);
+       aic_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR);
+       aic_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status);
        switch (hscb->shared_data.istatus.scsi_status) {
        case STATUS_PKT_SENSE:
        {
@@ -7995,7 +7992,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
 
                ahd_sync_sense(ahd, scb, BUS_DMASYNC_POSTREAD);
                siu = (struct scsi_status_iu_header *)scb->sense_data;
-               ahd_set_scsi_status(scb, siu->status);
+               aic_set_scsi_status(scb, siu->status);
 #ifdef AHD_DEBUG
                if ((ahd_debug & AHD_SHOW_SENSE) != 0) {
                        ahd_print_path(ahd, scb);
@@ -8036,7 +8033,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
                                }
                        }
                        if (siu->status == SCSI_STATUS_OK)
-                               ahd_set_transaction_status(scb,
+                               aic_set_transaction_status(scb,
                                                           CAM_REQ_CMP_ERR);
                }
                if ((siu->flags & SIU_SNSVALID) != 0) {
@@ -8066,7 +8063,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
                }
 #endif
 
-               if (ahd_perform_autosense(scb) == 0)
+               if (aic_perform_autosense(scb) == 0)
                        break;
 
                ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb),
@@ -8094,7 +8091,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
 #endif
                scb->sg_count = 0;
                sg = ahd_sg_setup(ahd, scb, sg, ahd_get_sense_bufaddr(ahd, scb),
-                                 ahd_get_sense_bufsize(ahd, scb),
+                                 aic_get_sense_bufsize(ahd, scb),
                                  /*last*/TRUE);
                sc->opcode = REQUEST_SENSE;
                sc->byte2 = 0;
@@ -8103,7 +8100,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
                        sc->byte2 = SCB_GET_LUN(scb) << 5;
                sc->unused[0] = 0;
                sc->unused[1] = 0;
-               sc->length = ahd_get_sense_bufsize(ahd, scb);
+               sc->length = aic_get_sense_bufsize(ahd, scb);
                sc->control = 0;
 
                /*
@@ -8123,7 +8120,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
                 * errors will be reported before any data
                 * phases occur.
                 */
-               if (ahd_get_residual(scb) == ahd_get_transfer_length(scb)) {
+               if (aic_get_residual(scb) == aic_get_transfer_length(scb)) {
                        ahd_update_neg_request(ahd, &devinfo,
                                               tstate, targ_info,
                                               AHD_NEG_IF_NON_ASYNC);
@@ -8142,7 +8139,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
                 * Ensure we have enough time to actually
                 * retrieve the sense.
                 */
-               ahd_scb_timer_reset(scb, 5 * 1000000);
+               aic_scb_timer_reset(scb, 5 * 1000000);
                break;
        }
        case SCSI_STATUS_OK:
@@ -8184,7 +8181,7 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb)
         */
 
        hscb = scb->hscb;
-       sgptr = ahd_le32toh(hscb->sgptr);
+       sgptr = aic_le32toh(hscb->sgptr);
        if ((sgptr & SG_STATUS_VALID) == 0)
                /* Case 1 */
                return;
@@ -8201,10 +8198,10 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb)
         * regardless of the role for this SCB.
         */
        spkt = &hscb->shared_data.istatus;
-       resid_sgptr = ahd_le32toh(spkt->residual_sgptr);
+       resid_sgptr = aic_le32toh(spkt->residual_sgptr);
        if ((sgptr & SG_FULL_RESID) != 0) {
                /* Case 3 */
-               resid = ahd_get_transfer_length(scb);
+               resid = aic_get_transfer_length(scb);
        } else if ((resid_sgptr & SG_LIST_NULL) != 0) {
                /* Case 4 */
                return;
@@ -8213,8 +8210,8 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb)
                kprintf("data overrun detected Tag == 0x%x.\n",
                       SCB_GET_TAG(scb));
                ahd_freeze_devq(ahd, scb);
-               ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR);
-               ahd_freeze_scb(scb);
+               aic_set_transaction_status(scb, CAM_DATA_RUN_ERR);
+               aic_freeze_scb(scb);
                return;
        } else if ((resid_sgptr & ~SG_PTR_MASK) != 0) {
                panic("Bogus resid sgptr value 0x%x\n", resid_sgptr);
@@ -8226,7 +8223,7 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb)
                 * Remainder of the SG where the transfer
                 * stopped.  
                 */
-               resid = ahd_le32toh(spkt->residual_datacnt) & AHD_SG_LEN_MASK;
+               resid = aic_le32toh(spkt->residual_datacnt) & AHD_SG_LEN_MASK;
                sg = ahd_sg_bus_to_virt(ahd, scb, resid_sgptr & SG_PTR_MASK);
 
                /* The residual sg_ptr always points to the next sg */
@@ -8237,15 +8234,15 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb)
                 * SG segments that are after the SG where
                 * the transfer stopped.
                 */
-               while ((ahd_le32toh(sg->len) & AHD_DMA_LAST_SEG) == 0) {
+               while ((aic_le32toh(sg->len) & AHD_DMA_LAST_SEG) == 0) {
                        sg++;
-                       resid += ahd_le32toh(sg->len) & AHD_SG_LEN_MASK;
+                       resid += aic_le32toh(sg->len) & AHD_SG_LEN_MASK;
                }
        }
        if ((scb->flags & SCB_SENSE) == 0)
-               ahd_set_residual(scb, resid);
+               aic_set_residual(scb, resid);
        else
-               ahd_set_sense_residual(scb, resid);
+               aic_set_sense_residual(scb, resid);
 
 #ifdef AHD_DEBUG
        if ((ahd_debug & AHD_SHOW_MISC) != 0) {
@@ -8357,8 +8354,7 @@ ahd_dumpseq(struct ahd_softc* ahd)
        max_prog = 2048;
 
        ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
-       ahd_outb(ahd, PRGMCNT, 0);
-       ahd_outb(ahd, PRGMCNT+1, 0);
+       ahd_outw(ahd, PRGMCNT, 0);
        for (i = 0; i < max_prog; i++) {
                uint8_t ins_bytes[4];
 
@@ -8473,8 +8469,7 @@ ahd_loadseq(struct ahd_softc *ahd)
        downloaded = 0;
        skip_addr = 0;
        ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
-       ahd_outb(ahd, PRGMCNT, 0);
-       ahd_outb(ahd, PRGMCNT+1, 0);
+       ahd_outw(ahd, PRGMCNT, 0);
 
        for (i = 0; i < sizeof(seqprog)/4; i++) {
                if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) {
@@ -8600,7 +8595,7 @@ ahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts)
        /*
         * The firmware is always compiled into a little endian format.
         */
-       instr.integer = ahd_le32toh(*(uint32_t*)&seqprog[instrptr * 4]);
+       instr.integer = aic_le32toh(*(uint32_t*)&seqprog[instrptr * 4]);
 
        fmt1_ins = &instr.format1;
        fmt3_ins = NULL;
@@ -8648,7 +8643,7 @@ ahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts)
                        instr.format1.parity = 1;
 
                /* The sequencer is a little endian cpu */
-               instr.integer = ahd_htole32(instr.integer);
+               instr.integer = aic_htole32(instr.integer);
                ahd_outsb(ahd, SEQRAM, instr.bytes, 4);
                break;
        }
@@ -8774,7 +8769,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
        kprintf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n"
               "%s: Dumping Card State at program address 0x%x Mode 0x%x\n",
               ahd_name(ahd), 
-              ahd_inb(ahd, CURADDR) | (ahd_inb(ahd, CURADDR+1) << 8),
+              ahd_inw(ahd, CURADDR),
               ahd_build_mode_state(ahd, ahd->saved_src_mode,
                                    ahd->saved_dst_mode));
        if (paused)
@@ -9019,6 +9014,279 @@ ahd_dump_scbs(struct ahd_softc *ahd)
        ahd_restore_modes(ahd, saved_modes);
 }
 
+
+/*************************** Timeout Handling *********************************/
+void
+ahd_timeout(struct scb *scb)
+{
+       struct ahd_softc *ahd;
+
+       ahd = scb->ahd_softc;
+       if ((scb->flags & SCB_ACTIVE) != 0) {
+               if ((scb->flags & SCB_TIMEDOUT) == 0) {
+                       LIST_INSERT_HEAD(&ahd->timedout_scbs, scb,
+                                        timedout_links);
+                       scb->flags |= SCB_TIMEDOUT;
+               }
+               ahd_wakeup_recovery_thread(ahd);
+       }
+}
+
+/*
+ * ahd_recover_commands determines if any of the commands that have currently
+ * timedout are the root cause for this timeout.  Innocent commands are given
+ * a new timeout while we wait for the command executing on the bus to timeout.
+ * This routine is invoked from a thread context so we are allowed to sleep.
+ * Our lock is not held on entry.
+ */
+void
+ahd_recover_commands(struct ahd_softc *ahd)
+{
+       struct  scb *scb;
+       struct  scb *active_scb;
+       int     found;
+       int     was_paused;
+       u_int   active_scbptr;
+       u_int   last_phase;
+
+       ahd_lock();
+
+       /*
+        * Pause the controller and manually flush any
+        * commands that have just completed but that our
+        * interrupt handler has yet to see.
+        */
+       was_paused = ahd_is_paused(ahd);
+       ahd_pause_and_flushwork(ahd);
+
+       if (LIST_EMPTY(&ahd->timedout_scbs) != 0) {
+               /*
+                * The timedout commands have already
+                * completed.  This typically means
+                * that either the timeout value was on
+                * the hairy edge of what the device
+                * requires or - more likely - interrupts
+                * are not happening.
+                */
+               kprintf("%s: Timedout SCBs already complete. "
+                      "Interrupts may not be functioning.\n", ahd_name(ahd));
+               ahd_unpause(ahd);
+               ahd_unlock();
+               return;
+       }
+
+       kprintf("%s: Recovery Initiated - Card was %spaused\n", ahd_name(ahd),
+              was_paused ? "" : "not ");
+       ahd_dump_card_state(ahd);
+
+       /*
+        * Determine identity of SCB acting on the bus.
+        * This test only catches non-packetized transactions.
+        * Due to the fleeting nature of packetized operations,
+        * we can't easily determine that a packetized operation
+        * is on the bus.
+        */
+       ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
+       last_phase = ahd_inb(ahd, LASTPHASE);
+       active_scbptr = ahd_get_scbptr(ahd);
+       active_scb = NULL;
+       if (last_phase != P_BUSFREE
+        || (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)
+               active_scb = ahd_lookup_scb(ahd, active_scbptr);
+
+       while ((scb = LIST_FIRST(&ahd->timedout_scbs)) != NULL) {
+               int     target;
+               int     lun;
+               char    channel;
+
+               target = SCB_GET_TARGET(ahd, scb);
+               channel = SCB_GET_CHANNEL(ahd, scb);
+               lun = SCB_GET_LUN(scb);
+
+               ahd_print_path(ahd, scb);
+               kprintf("SCB 0x%x - timed out\n", scb->hscb->tag);
+
+               if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) {
+                       /*
+                        * Been down this road before.
+                        * Do a full bus reset.
+                        */
+                       aic_set_transaction_status(scb, CAM_CMD_TIMEOUT);
+bus_reset:
+                       found = ahd_reset_channel(ahd, channel,
+                                                 /*Initiate Reset*/TRUE);
+                       kprintf("%s: Issued Channel %c Bus Reset. "
+                              "%d SCBs aborted\n", ahd_name(ahd), channel,
+                              found);
+                       continue;
+               }
+
+               /*
+                * Remove the command from the timedout list in
+                * preparation for requeing it.
+                */
+               LIST_REMOVE(scb, timedout_links);
+               scb->flags &= ~SCB_TIMEDOUT;
+
+               if (active_scb != NULL) {
+
+                       if (active_scb != scb) {
+                               /*
+                                * If the active SCB is not us, assume that
+                                * the active SCB has a longer timeout than
+                                * the timedout SCB, and wait for the active
+                                * SCB to timeout.
+                                */ 
+                               ahd_other_scb_timeout(ahd, scb, active_scb);
+                               continue;
+                       } 
+
+                       /*
+                        * We're active on the bus, so assert ATN
+                        * and hope that the target responds.
+                        */
+                       ahd_set_recoveryscb(ahd, active_scb);
+                       active_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET;
+                       ahd_outb(ahd, MSG_OUT, HOST_MSG);
+                       ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
+                       ahd_print_path(ahd, active_scb);
+                       kprintf("BDR message in message buffer\n");
+                       aic_scb_timer_reset(scb, 2 * 1000000);
+                       break;
+               } else if (last_phase != P_BUSFREE
+                       && ahd_inb(ahd, SCSIPHASE) == 0) {
+                       /*
+                        * SCB is not identified, there
+                        * is no pending REQ, and the sequencer
+                        * has not seen a busfree.  Looks like
+                        * a stuck connection waiting to
+                        * go busfree.  Reset the bus.
+                        */
+                       kprintf("%s: Connection stuck awaiting busfree or "
+                              "Identify Msg.\n", ahd_name(ahd));
+                       goto bus_reset;
+               } else if (ahd_search_qinfifo(ahd, target, channel, lun,
+                                             scb->hscb->tag, ROLE_INITIATOR,
+                                             /*status*/0, SEARCH_COUNT) > 0) {
+
+                       /*
+                        * We haven't even gone out on the bus
+                        * yet, so the timeout must be due to
+                        * some other command.  Reset the timer
+                        * and go on.
+                        */
+                       ahd_other_scb_timeout(ahd, scb, scb);
+               } else {
+                       /*
+                        * This SCB is for a disconnected transaction
+                        * and we haven't found a better candidate on
+                        * the bus to explain this timeout.
+                        */
+                       ahd_set_recoveryscb(ahd, scb);
+
+                       /*
+                        * Actually re-queue this SCB in an attempt
+                        * to select the device before it reconnects.
+                        * In either case (selection or reselection),
+                        * we will now issue a target reset to the
+                        * timed-out device.
+                        *
+                        * Set the MK_MESSAGE control bit indicating
+                        * that we desire to send a message.  We
+                        * also set the disconnected flag since
+                        * in the paging case there is no guarantee
+                        * that our SCB control byte matches the
+                        * version on the card.  We don't want the
+                        * sequencer to abort the command thinking
+                        * an unsolicited reselection occurred.
+                        */
+                       scb->flags |= SCB_DEVICE_RESET;
+                       scb->hscb->cdb_len = 0;
+                       scb->hscb->task_attribute = 0;
+                       scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
+
+                       ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
+                       if ((scb->flags & SCB_PACKETIZED) != 0) {
+                               /*
+                                * Mark the SCB has having an outstanding
+                                * task management function.  Should the command
+                                * complete normally before the task management
+                                * function can be sent, the host will be
+                                * notified to abort our requeued SCB.
+                                */
+                               ahd_outb(ahd, SCB_TASK_MANAGEMENT,
+                                        scb->hscb->task_management);
+                       } else {
+                               /*
+                                * If non-packetized, set the MK_MESSAGE control
+                                * bit indicating that we desire to send a
+                                * message.  We also set the disconnected flag
+                                * since there is no guarantee that our SCB
+                                * control byte matches the version on the
+                                * card.  We don't want the sequencer to abort
+                                * the command thinking an unsolicited
+                                * reselection occurred.
+                                */
+                               scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
+
+                               /*
+                                * The sequencer will never re-reference the
+                                * in-core SCB.  To make sure we are notified
+                                * during reslection, set the MK_MESSAGE flag in
+                                * the card's copy of the SCB.
+                                */
+                               ahd_outb(ahd, SCB_CONTROL,
+                                        ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
+                       }
+
+                       /*
+                        * Clear out any entries in the QINFIFO first
+                        * so we are the next SCB for this target
+                        * to run.
+                        */
+                       ahd_search_qinfifo(ahd, target, channel, lun,
+                                          SCB_LIST_NULL, ROLE_INITIATOR,
+                                          CAM_REQUEUE_REQ, SEARCH_COMPLETE);
+                       ahd_qinfifo_requeue_tail(ahd, scb);
+                       ahd_set_scbptr(ahd, active_scbptr);
+                       ahd_print_path(ahd, scb);
+                       kprintf("Queuing a BDR SCB\n");
+                       aic_scb_timer_reset(scb, 2 * 1000000);
+                       break;
+               }
+       }
+       
+       /*
+        * Any remaining SCBs were not the "culprit", so remove
+        * them from the timeout list.  The timer for these commands
+        * will be reset once the recovery SCB completes.
+        */
+       while ((scb = LIST_FIRST(&ahd->timedout_scbs)) != NULL) {
+
+               LIST_REMOVE(scb, timedout_links);
+               scb->flags &= ~SCB_TIMEDOUT;
+       }
+
+       ahd_unpause(ahd);
+       ahd_unlock();
+}
+
+static void
+ahd_other_scb_timeout(struct ahd_softc *ahd, struct scb *scb,
+                     struct scb *other_scb)
+{
+       u_int   newtimeout;
+
+       ahd_print_path(ahd, scb);
+       kprintf("Other SCB Timeout%s",
+              (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0
+              ? " again\n" : "\n");
+       scb->flags |= SCB_OTHERTCL_TIMEOUT;
+       newtimeout = MAX(aic_get_timeout(other_scb),
+                        aic_get_timeout(scb));
+       aic_scb_timer_reset(scb, newtimeout);
+}
+
 /**************************** Flexport Logic **********************************/
 /*
  * Read count 16bit words from 16bit word address start_addr from the
@@ -9125,9 +9393,9 @@ ahd_wait_seeprom(struct ahd_softc *ahd)
 {
        int cnt;
 
-       cnt = 20;
+       cnt = 5000;
        while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt)
-               ahd_delay(5);
+               aic_delay(5);
 
        if (cnt == 0)
                return (ETIMEDOUT);
@@ -9269,7 +9537,7 @@ ahd_wait_flexport(struct ahd_softc *ahd)
        AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
        cnt = 1000000 * 2 / 5;
        while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt)
-               ahd_delay(5);
+               aic_delay(5);
 
        if (cnt == 0)
                return (ETIMEDOUT);
@@ -9464,13 +9732,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
                        if ((ahd->features & AHD_MULTI_TID) != 0) {
                                u_int targid_mask;
 
-                               targid_mask = ahd_inb(ahd, TARGID)
-                                           | (ahd_inb(ahd, TARGID + 1) << 8);
-
+                               targid_mask = ahd_inw(ahd, TARGID);
                                targid_mask |= target_mask;
-                               ahd_outb(ahd, TARGID, targid_mask);
-                               ahd_outb(ahd, TARGID+1, (targid_mask >> 8));
-                               
+                               ahd_outw(ahd, TARGID, targid_mask);
                                ahd_update_scsiid(ahd, targid_mask);
                        } else {
                                u_int our_id;
@@ -9584,14 +9848,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
                                if (ahd->features & AHD_MULTI_TID) {
                                        u_int targid_mask;
 
-                                       targid_mask = ahd_inb(ahd, TARGID)
-                                                   | (ahd_inb(ahd, TARGID + 1)
-                                                      << 8);
-
+                                       targid_mask = ahd_inw(ahd, TARGID);
                                        targid_mask &= ~target_mask;
-                                       ahd_outb(ahd, TARGID, targid_mask);
-                                       ahd_outb(ahd, TARGID+1,
-                                                (targid_mask >> 8));
+                                       ahd_outw(ahd, TARGID, targid_mask);
                                        ahd_update_scsiid(ahd, targid_mask);
                                }
                        }
index ecb6aa0..8450bcd 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.h#94 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#101 $
  *
- * $FreeBSD: src/sys/dev/aic7xxx/aic79xx.h,v 1.16 2003/09/02 17:30:34 jhb Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx.h,v 1.5 2007/07/05 05:08:32 pavalos Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/aic79xx.h,v 1.17 2003/12/17 00:02:09 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx.h,v 1.6 2007/07/06 00:01:16 pavalos Exp $
  */
 
 #ifndef _AIC79XX_H_
@@ -75,9 +75,9 @@ struct scb_platform_data;
 #define ALL_TARGETS_MASK 0xFFFF
 #define INITIATOR_WILDCARD     (~0)
 #define        SCB_LIST_NULL           0xFF00
-#define        SCB_LIST_NULL_LE        (ahd_htole16(SCB_LIST_NULL))
+#define        SCB_LIST_NULL_LE        (aic_htole16(SCB_LIST_NULL))
 #define QOUTFIFO_ENTRY_VALID 0x8000
-#define QOUTFIFO_ENTRY_VALID_LE (ahd_htole16(0x8000))
+#define QOUTFIFO_ENTRY_VALID_LE (aic_htole16(0x8000))
 #define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL)
 
 #define SCSIID_TARGET(ahd, scsiid)     \
@@ -119,7 +119,7 @@ struct scb_platform_data;
        ((lun) | ((target) << 8))
 
 #define SCB_GET_TAG(scb) \
-       ahd_le16toh(scb->hscb->tag)
+       aic_le16toh(scb->hscb->tag)
 
 #ifndef        AHD_TARGET_MODE
 #undef AHD_TMODE_ENABLE
@@ -230,6 +230,7 @@ typedef enum {
        AHD_RTI                 = 0x04000,/* Retained Training Support */
        AHD_NEW_IOCELL_OPTS     = 0x08000,/* More Signal knobs in the IOCELL */
        AHD_NEW_DFCNTRL_OPTS    = 0x10000,/* SCSIENWRDIS bit */
+       AHD_FAST_CDB_DELIVERY   = 0x20000,/* CDB acks released to Output Sync */
        AHD_REMOVABLE           = 0x00000,/* Hot-Swap supported - None so far*/
        AHD_AIC7901_FE          = AHD_FENONE,
        AHD_AIC7901A_FE         = AHD_FENONE,
@@ -375,7 +376,8 @@ typedef enum {
        AHD_RESET_POLL_ACTIVE = 0x200000,
        AHD_UPDATE_PEND_CMDS  = 0x400000,
        AHD_RUNNING_QOUTFIFO  = 0x800000,
-       AHD_HAD_FIRST_SEL     = 0x1000000
+       AHD_HAD_FIRST_SEL     = 0x1000000,
+       AHD_SHUTDOWN_RECOVERY = 0x2000000 /* Terminate recovery thread. */
 } ahd_flag;
 
 /************************* Hardware  SCB Definition ***************************/
@@ -549,7 +551,7 @@ struct ahd_dma64_seg {
 
 struct map_node {
        bus_dmamap_t             dmamap;
-       bus_addr_t               physaddr;
+       bus_addr_t               busaddr;
        uint8_t                 *vaddr;
        SLIST_ENTRY(map_node)    links;
 };
@@ -591,12 +593,16 @@ typedef enum {
        SCB_PKT_SENSE           = 0x02000,
        SCB_CMDPHASE_ABORT      = 0x04000,
        SCB_ON_COL_LIST         = 0x08000,
-       SCB_SILENT              = 0x10000 /*
+       SCB_SILENT              = 0x10000,/*
                                           * Be quiet about transmission type
                                           * errors.  They are expected and we
                                           * don't want to upset the user.  This
                                           * flag is typically used during DV.
                                           */
+       SCB_TIMEDOUT            = 0x20000/*
+                                         * SCB has timed out and is on the
+                                         * timedout list.
+                                         */
 } scb_flag;
 
 struct scb {
@@ -613,8 +619,9 @@ struct scb {
        } links2;
 #define pending_links links2.le
 #define collision_links links2.le
+       LIST_ENTRY(scb)           timedout_links;
        struct scb               *col_scb;
-       ahd_io_ctx_t              io_ctx;
+       aic_io_ctx_t              io_ctx;
        struct ahd_softc         *ahd_softc;
        scb_flag                  flags;
 #ifndef __linux__
@@ -1062,12 +1069,18 @@ struct ahd_softc {
        struct scb_data           scb_data;
 
        struct hardware_scb      *next_queued_hscb;
+       struct map_node          *next_queued_hscb_map;
 
        /*
         * SCBs that have been sent to the controller
         */
        LIST_HEAD(, scb)          pending_scbs;
 
+       /*
+        * SCBs whose timeout routine has been called.
+        */
+       LIST_HEAD(, scb)          timedout_scbs;
+
        /*
         * Current register window mode information.
         */
@@ -1089,7 +1102,7 @@ struct ahd_softc {
        /*
         * Platform specific device information.
         */
-       ahd_dev_softc_t           dev_softc;
+       aic_dev_softc_t           dev_softc;
 
        /*
         * Bus specific device information.
@@ -1119,8 +1132,8 @@ struct ahd_softc {
        /*
         * Timer handles for timer driven callbacks.
         */
-       ahd_timer_t               reset_timer;
-       ahd_timer_t               stat_timer;
+       aic_timer_t               reset_timer;
+       aic_timer_t               stat_timer;
 
        /*
         * Statistics.
@@ -1197,8 +1210,7 @@ struct ahd_softc {
         */
        bus_dma_tag_t             parent_dmat;
        bus_dma_tag_t             shared_data_dmat;
-       bus_dmamap_t              shared_data_dmamap;
-       bus_addr_t                shared_data_busaddr;
+       struct map_node           shared_data_map;
 
        /* Information saved through suspend/resume cycles */
        struct ahd_suspend_state  suspend_state;
@@ -1341,7 +1353,7 @@ ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl)
 }
 
 /***************************** PCI Front End *********************************/
-struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t);
+struct ahd_pci_identity *ahd_find_pci_device(aic_dev_softc_t);
 int                      ahd_pci_config(struct ahd_softc *,
                                         struct ahd_pci_identity *);
 int    ahd_pci_test_register_access(struct ahd_softc *);
@@ -1433,6 +1445,8 @@ void                      ahd_handle_scsi_status(struct ahd_softc *ahd,
                                               struct scb *scb);
 void                   ahd_calc_residual(struct ahd_softc *ahd,
                                          struct scb *scb);
+void                   ahd_timeout(struct scb *scb);
+void                   ahd_recover_commands(struct ahd_softc *ahd);
 /*************************** Utility Functions ********************************/
 struct ahd_phase_table_entry*
                        ahd_lookup_phase_entry(int phase);
index 518256a..0cced95 100644 (file)
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $FreeBSD: src/sys/dev/aic7xxx/aic79xx.seq,v 1.13 2003/06/28 04:44:10 gibbs Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx.seq,v 1.4 2007/07/05 01:21:56 pavalos Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/aic79xx.seq,v 1.14 2003/12/17 00:02:09 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx.seq,v 1.5 2007/07/06 00:01:16 pavalos Exp $
  */
 
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#96 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#107 $"
 PATCH_ARG_LIST = "struct ahd_softc *ahd"
 PREFIX = "ahd_"
 
@@ -91,6 +91,13 @@ idle_loop_check_nonpackreq:
        test    SSTAT2, NONPACKREQ jz . + 2;
        call    unexpected_nonpkt_phase_find_ctxt;
        if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+               /*
+                * On Rev A. hardware, the busy LED is only
+                * turned on automaically during selections
+                * and re-selections.  Make the LED status
+                * more useful by forcing it to be on so
+                * long as one of our data FIFOs is active.
+                */
                and     A, FIFO0FREE|FIFO1FREE, DFFSTAT;
                cmp     A, FIFO0FREE|FIFO1FREE jne . + 3;
                and     SBLKCTL, ~DIAGLEDEN|DIAGLEDON;
@@ -102,9 +109,9 @@ idle_loop_check_nonpackreq:
        call    idle_loop_cchan;
        jmp     idle_loop;
 
-BEGIN_CRITICAL;
 idle_loop_gsfifo:
        SET_MODE(M_SCSI, M_SCSI)
+BEGIN_CRITICAL;
 idle_loop_gsfifo_in_scsi_mode:
        test    LQISTAT2, LQIGSAVAIL jz return;
        /*
@@ -153,25 +160,28 @@ END_CRITICAL;
 
 idle_loop_service_fifos:
        SET_MODE(M_DFF0, M_DFF0)
+BEGIN_CRITICAL;
        test    LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo;
        call    longjmp;
+END_CRITICAL;
 idle_loop_next_fifo:
        SET_MODE(M_DFF1, M_DFF1)
+BEGIN_CRITICAL;
        test    LONGJMP_ADDR[1], INVALID_ADDR jz longjmp;
+END_CRITICAL;
 return:
        ret;
 
 idle_loop_cchan:
        SET_MODE(M_CCHAN, M_CCHAN)
        test    QOFF_CTLSTA, HS_MAILBOX_ACT jz  hs_mailbox_empty;
-       mov     LOCAL_HS_MAILBOX, HS_MAILBOX;
        or      QOFF_CTLSTA, HS_MAILBOX_ACT;
+       mov     LOCAL_HS_MAILBOX, HS_MAILBOX;
 hs_mailbox_empty:
 BEGIN_CRITICAL;
        test    CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle;
        test    CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog;
        test    CCSCBCTL, CCSCBDONE jz return;
-END_CRITICAL;
        /* FALLTHROUGH */
 scbdma_tohost_done:
        test    CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone;
@@ -181,26 +191,18 @@ scbdma_tohost_done:
         * bad SCSI status (currently only for underruns), we
         * queue the SCB for normal completion.  Otherwise, we
         * wait until any select-out activity has halted, and
-        * then notify the host so that the transaction can be
-        * dealt with.
+        * then queue the completion.
         */
-       test    SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host;
-       and     CCSCBCTL, ~(CCARREN|CCSCBEN);
-       bmov    COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
-       bmov    SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
-       bmov    COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
-scbdma_notify_host:
+       test    SCB_SCSI_STATUS, 0xff jz scbdma_queue_completion;
        SET_MODE(M_SCSI, M_SCSI)
        test    SCSISEQ0, ENSELO jnz return;
        test    SSTAT0, (SELDO|SELINGO) jnz return;
        SET_MODE(M_CCHAN, M_CCHAN)
-       /*
-        * Remove SCB and notify host.
-        */
+scbdma_queue_completion:
        and     CCSCBCTL, ~(CCARREN|CCSCBEN);
        bmov    COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
-       SET_SEQINTCODE(BAD_SCB_STATUS)
-       ret;
+       bmov    SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
+       bmov    COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
 fill_qoutfifo_dmadone:
        and     CCSCBCTL, ~(CCARREN|CCSCBEN);
        call    qoutfifo_updated;
@@ -209,6 +211,7 @@ fill_qoutfifo_dmadone:
        test    QOFF_CTLSTA, SDSCB_ROLLOVR jz return;
        bmov    QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4;
        xor     QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret;
+END_CRITICAL;
 
 qoutfifo_updated:
        /*
@@ -491,14 +494,30 @@ allocate_fifo1:
 SET_SRC_MODE   M_SCSI;
 SET_DST_MODE   M_SCSI;
 select_in:
+       if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+               /*
+                * On Rev A. hardware, the busy LED is only
+                * turned on automaically during selections
+                * and re-selections.  Make the LED status
+                * more useful by forcing it to be on from
+                * the point of selection until our idle
+                * loop determines that neither of our FIFOs
+                * are busy.  This handles the non-packetized
+                * case nicely as we will not return to the
+                * idle loop until the busfree at the end of
+                * each transaction.
+                */
+               or      SBLKCTL, DIAGLEDEN|DIAGLEDON;
+       }
        if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
                /*
-                * This exposes a window whereby a
-                * busfree just after a selection will
-                * be missed, but there is no other safe
-                * way to enable busfree detection if
-                * the busfreerev function is broken.
+                * Test to ensure that the bus has not
+                * already gone free prior to clearing
+                * any stale busfree status.  This avoids
+                * a window whereby a busfree just after
+                * a selection could be missed.
                 */
+               test    SCSISIGI, BSYI jz . + 2;
                mvi     CLRSINT1,CLRBUSFREE;
                or      SIMODE1, ENBUSFREE;
        }
@@ -528,6 +547,21 @@ SET_SRC_MODE       M_SCSI;
 SET_DST_MODE   M_SCSI;
 select_out:
 BEGIN_CRITICAL;
+       if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+               /*
+                * On Rev A. hardware, the busy LED is only
+                * turned on automaically during selections
+                * and re-selections.  Make the LED status
+                * more useful by forcing it to be on from
+                * the point of re-selection until our idle
+                * loop determines that neither of our FIFOs
+                * are busy.  This handles the non-packetized
+                * case nicely as we will not return to the
+                * idle loop until the busfree at the end of
+                * each transaction.
+                */
+               or      SBLKCTL, DIAGLEDEN|DIAGLEDON;
+       }
        /* Clear out all SCBs that have been successfully sent. */
        if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) {
                /*
@@ -649,12 +683,13 @@ select_out_non_packetized:
        and     SCSISEQ0, ~ENSELO;
        if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
                /*
-                * This exposes a window whereby a
-                * busfree just after a selection will
-                * be missed, but there is no other safe
-                * way to enable busfree detection if
-                * the busfreerev function is broken.
+                * Test to ensure that the bus has not
+                * already gone free prior to clearing
+                * any stale busfree status.  This avoids
+                * a window whereby a busfree just after
+                * a selection could be missed.
                 */
+               test    SCSISIGI, BSYI jz . + 2;
                mvi     CLRSINT1,CLRBUSFREE;
                or      SIMODE1, ENBUSFREE;
        }
@@ -727,13 +762,38 @@ p_command_embedded:
        mvi     DFCNTRL, SCSIEN;
 p_command_xfer:
        and     SEQ_FLAGS, ~NO_CDB_SENT;
-       test    DFCNTRL, SCSIEN jnz .;
+       if ((ahd->features & AHD_FAST_CDB_DELIVERY) != 0) {
+               /*
+                * To speed up CDB delivery in Rev B, all CDB acks
+                * are "released" to the output sync as soon as the
+                * command phase starts.  There is only one problem
+                * with this approach.  If the target changes phase
+                * before all data are sent, we have left over acks
+                * that can go out on the bus in a data phase.  Due
+                * to other chip contraints, this only happens if
+                * the target goes to data-in, but if the acks go
+                * out before we can test SDONE, we'll think that
+                * the transfer has completed successfully.  Work
+                * around this by taking advantage of the 400ns or
+                * 800ns dead time between command phase and the REQ
+                * of the new phase.  If the transfer has completed
+                * successfully, SCSIEN should fall *long* before we
+                * see a phase change.  We thus treat any phasemiss
+                * that occurs before SCSIEN falls as an incomplete
+                * transfer.
+                */
+               test    SSTAT1, PHASEMIS jnz p_command_xfer_failed;
+               test    DFCNTRL, SCSIEN jnz . - 1;
+       } else {
+               test    DFCNTRL, SCSIEN jnz .;
+       }
        /*
         * DMA Channel automatically disabled.
         * Don't allow a data phase if the command
         * was not fully transferred.
         */
        test    SSTAT2, SDONE jnz ITloop;
+p_command_xfer_failed:
        or      SEQ_FLAGS, NO_CDB_SENT;
        jmp     ITloop;
 
@@ -1059,8 +1119,10 @@ queue_scb_completion:
        test    SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */
        test    SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;
 complete:
+BEGIN_CRITICAL;
        bmov    SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
        bmov    COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
+END_CRITICAL;
 bad_status:
        cmp     SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb;
        call    freeze_queue;
@@ -1071,9 +1133,11 @@ upload_scb:
         * it on the host.
         */
        bmov    SCB_TAG, SCBPTR, 2;
+BEGIN_CRITICAL;
        bmov    SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2;
        bmov    COMPLETE_DMA_SCB_HEAD, SCBPTR, 2;
        or      SCB_SGPTR, SG_STATUS_VALID ret;
+END_CRITICAL;
 
 /*
  * Is it a disconnect message?  Set a flag in the SCB to remind us
@@ -1120,8 +1184,18 @@ SET_DST_MODE     M_DFF1;
 await_busfree_clrchn:
        mvi     DFFSXFRCTL, CLRCHN;
 await_busfree_not_m_dff:
-       call    clear_target_state;
+       /* clear target specific flags */
+       mvi     SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;
        test    SSTAT1,REQINIT|BUSFREE  jz .;
+       /*
+        * We only set BUSFREE status once either a new
+        * phase has been detected or we are really
+        * BUSFREE.  This allows the driver to know
+        * that we are active on the bus even though
+        * no identified transaction exists should a
+        * timeout occur while awaiting busfree.
+        */
+       mvi     LASTPHASE, P_BUSFREE;
        test    SSTAT1, BUSFREE jnz idle_loop;
        SET_SEQINTCODE(MISSED_BUSFREE)
 
@@ -1176,11 +1250,6 @@ msgin_rdptrs_get_fifo:
        call    allocate_fifo;
        jmp     mesgin_done;
 
-clear_target_state:
-       mvi     LASTPHASE, P_BUSFREE;
-       /* clear target specific flags */
-       mvi     SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret;
-
 phase_lock:     
        if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) {
                /*
@@ -1632,7 +1701,7 @@ export seq_isr:
                 * savepointer in the current FIFO.  We do this so that
                 * a pending CTXTDONE or SAVEPTR is visible in the active
                 * FIFO.  This status is the only way we can detect if we
-                * have lost the race (e.g. host paused us) and our attepts
+                * have lost the race (e.g. host paused us) and our attempts
                 * to disable the channel occurred after all REQs were
                 * already seen and acked (REQINIT never comes true).
                 */
@@ -1641,7 +1710,7 @@ export seq_isr:
                test    DFCNTRL, DIRECTION jz interrupt_return;
                and     DFCNTRL, ~SCSIEN;
 snapshot_wait_data_valid:
-               test    SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid;
+               test    SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return;
                test    SSTAT1, REQINIT jz snapshot_wait_data_valid;
 snapshot_data_valid:
                or      DFCNTRL, SCSIEN;
@@ -1808,7 +1877,6 @@ pkt_saveptrs_check_status:
        dec     SCB_FIFO_USE_COUNT;
        test    SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;
        mvi     DFFSXFRCTL, CLRCHN ret;
-END_CRITICAL;
 
 /*
  * LAST_SEG_DONE status has been seen in the current FIFO.
@@ -1817,7 +1885,6 @@ END_CRITICAL;
  * Check for overrun and see if we can complete this command.
  */
 pkt_last_seg_done:
-BEGIN_CRITICAL;
        /*
         * Mark transfer as completed.
         */
index c8dcf86..8b41c92 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_inline.h#51 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#55 $
  *
- * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_inline.h,v 1.12 2003/06/28 04:43:19 gibbs Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx_inline.h,v 1.4 2007/07/05 01:13:05 pavalos Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_inline.h,v 1.13 2003/12/17 00:02:09 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx_inline.h,v 1.5 2007/07/06 00:01:16 pavalos Exp $
  */
 
 #ifndef _AIC79XX_INLINE_H_
@@ -251,15 +251,15 @@ ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
                struct ahd_dma64_seg *sg;
 
                sg = (struct ahd_dma64_seg *)sgptr;
-               sg->addr = ahd_htole64(addr);
-               sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0));
+               sg->addr = aic_htole64(addr);
+               sg->len = aic_htole32(len | (last ? AHD_DMA_LAST_SEG : 0));
                return (sg + 1);
        } else {
                struct ahd_dma_seg *sg;
 
                sg = (struct ahd_dma_seg *)sgptr;
-               sg->addr = ahd_htole32(addr & 0xFFFFFFFF);
-               sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000)
+               sg->addr = aic_htole32(addr & 0xFFFFFFFF);
+               sg->len = aic_htole32(len | ((addr >> 8) & 0x7F000000)
                                    | (last ? AHD_DMA_LAST_SEG : 0));
                return (sg + 1);
        }
@@ -274,7 +274,7 @@ ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb)
                /* XXX what about ACA??  It is type 4, but TAG_TYPE == 0x3. */
                scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE;
        } else {
-               if (ahd_get_transfer_length(scb) & 0x01)
+               if (aic_get_transfer_length(scb) & 0x01)
                        scb->hscb->task_attribute = SCB_XFERLEN_ODD;
                else
                        scb->hscb->task_attribute = 0;
@@ -283,7 +283,7 @@ ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb)
        if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR
         || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0)
                scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr =
-                   ahd_htole32(scb->sense_busaddr);
+                   aic_htole32(scb->sense_busaddr);
 }
 
 static __inline void
@@ -309,8 +309,8 @@ ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)
                if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) {
                        uint64_t high_addr;
 
-                       high_addr = ahd_le32toh(sg->len) & 0x7F000000;
-                       scb->hscb->dataptr |= ahd_htole64(high_addr << 8);
+                       high_addr = aic_le32toh(sg->len) & 0x7F000000;
+                       scb->hscb->dataptr |= aic_htole64(high_addr << 8);
                }
                scb->hscb->datacnt = sg->len;
        }
@@ -320,13 +320,13 @@ ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)
         * sequencer will clear as soon as a data transfer
         * occurs.
         */
-       scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID);
+       scb->hscb->sgptr = aic_htole32(scb->sg_list_busaddr|SG_FULL_RESID);
 }
 
 static __inline void
 ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb)
 {
-       scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL);
+       scb->hscb->sgptr = aic_htole32(SG_LIST_NULL);
        scb->hscb->dataptr = 0;
        scb->hscb->datacnt = 0;
 }
@@ -384,7 +384,7 @@ ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg)
 static __inline void
 ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op)
 {
-       ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat,
+       aic_dmamap_sync(ahd, ahd->scb_data.hscb_dmat,
                        scb->hscb_map->dmamap,
                        /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr,
                        /*len*/sizeof(*scb->hscb), op);
@@ -396,7 +396,7 @@ ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op)
        if (scb->sg_count == 0)
                return;
 
-       ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat,
+       aic_dmamap_sync(ahd, ahd->scb_data.sg_dmat,
                        scb->sg_map->dmamap,
                        /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd),
                        /*len*/ahd_sg_size(ahd) * scb->sg_count, op);
@@ -405,7 +405,7 @@ ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op)
 static __inline void
 ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op)
 {
-       ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat,
+       aic_dmamap_sync(ahd, ahd->scb_data.sense_dmat,
                        scb->sense_map->dmamap,
                        /*offset*/scb->sense_busaddr,
                        /*len*/AHD_SENSE_BUFSIZE, op);
@@ -473,7 +473,7 @@ ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb)
 {
        uint32_t sgptr;
 
-       sgptr = ahd_le32toh(scb->hscb->sgptr);
+       sgptr = aic_le32toh(scb->hscb->sgptr);
        if ((sgptr & SG_STATUS_VALID) != 0)
                ahd_handle_scb_status(ahd, scb);
        else
@@ -489,7 +489,7 @@ ahd_update_residual(struct ahd_softc *ahd, struct scb *scb)
 {
        uint32_t sgptr;
 
-       sgptr = ahd_le32toh(scb->hscb->sgptr);
+       sgptr = aic_le32toh(scb->hscb->sgptr);
        if ((sgptr & SG_STATUS_VALID) != 0)
                ahd_calc_residual(ahd, scb);
 }
@@ -523,12 +523,21 @@ do {                                                              \
 static __inline uint16_t
 ahd_inw(struct ahd_softc *ahd, u_int port)
 {
+       /*
+        * Read high byte first as some registers increment
+        * or have other side effects when the low byte is
+        * read.
+        */
        return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port));
 }
 
 static __inline void
 ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
 {
+       /*
+        * Write low byte first to accomodate registers
+        * such as PRGMCNT where the order maters.
+        */
        ahd_outb(ahd, port, value & 0xFF);
        ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
 }
@@ -728,7 +737,8 @@ ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
 static __inline void
 ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
 {
-       struct hardware_scb *q_hscb;
+       struct   hardware_scb *q_hscb;
+       struct   map_node *q_hscb_map;
        uint32_t saved_hscb_busaddr;
 
        /*
@@ -744,6 +754,7 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
         * locate the correct SCB by SCB_TAG.
         */
        q_hscb = ahd->next_queued_hscb;
+       q_hscb_map = ahd->next_queued_hscb_map;
        saved_hscb_busaddr = q_hscb->hscb_busaddr;
        memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
        q_hscb->hscb_busaddr = saved_hscb_busaddr;
@@ -751,7 +762,9 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
 
        /* Now swap HSCB pointers. */
        ahd->next_queued_hscb = scb->hscb;
+       ahd->next_queued_hscb_map = scb->hscb_map;
        scb->hscb = q_hscb;
+       scb->hscb_map = q_hscb_map;
 
        /* Now define the mapping from tag to SCB in the scbindex */
        ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
@@ -791,13 +804,13 @@ ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
        if ((ahd_debug & AHD_SHOW_QUEUE) != 0) {
                uint64_t host_dataptr;
 
-               host_dataptr = ahd_le64toh(scb->hscb->dataptr);
+               host_dataptr = aic_le64toh(scb->hscb->dataptr);
                kprintf("%s: Queueing SCB 0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
                       ahd_name(ahd),
-                      SCB_GET_TAG(scb), ahd_le32toh(scb->hscb->hscb_busaddr),
+                      SCB_GET_TAG(scb), aic_le32toh(scb->hscb->hscb_busaddr),
                       (u_int)((host_dataptr >> 32) & 0xFFFFFFFF),
                       (u_int)(host_dataptr & 0xFFFFFFFF),
-                      ahd_le32toh(scb->hscb->datacnt));
+                      aic_le32toh(scb->hscb->datacnt));
        }
 #endif
        /* Tell the adapter about the newly queued SCB */
@@ -825,8 +838,8 @@ static __inline int ahd_intr(struct ahd_softc *ahd);
 static __inline void
 ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
 {
-       ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
-                       /*offset*/0, /*len*/AHC_SCB_MAX * sizeof(uint16_t), op);
+       aic_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+                       /*offset*/0, /*len*/AHD_SCB_MAX * sizeof(uint16_t), op);
 }
 
 static __inline void
@@ -834,8 +847,8 @@ ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
 {
 #ifdef AHD_TARGET_MODE
        if ((ahd->flags & AHD_TARGETROLE) != 0) {
-               ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
-                               ahd->shared_data_dmamap,
+               aic_dmamap_sync(ahd, ahd->shared_data_dmat,
+                               ahd->shared_data_map.dmamap,
                                ahd_targetcmd_offset(ahd, 0),
                                sizeof(struct target_cmd) * AHD_TMODE_CMDS,
                                op);
@@ -855,7 +868,7 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
        u_int retval;
 
        retval = 0;
-       ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
+       aic_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
                        /*offset*/ahd->qoutfifonext, /*len*/2,
                        BUS_DMASYNC_POSTREAD);
        if ((ahd->qoutfifo[ahd->qoutfifonext]
@@ -864,8 +877,8 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
 #ifdef AHD_TARGET_MODE
        if ((ahd->flags & AHD_TARGETROLE) != 0
         && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
-               ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
-                               ahd->shared_data_dmamap,
+               aic_dmamap_sync(ahd, ahd->shared_data_dmat,
+                               ahd->shared_data_map.dmamap,
                                ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
                                /*len*/sizeof(struct target_cmd),
                                BUS_DMASYNC_POSTREAD);
index 9d20c67..4ce5055 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Bus independent FreeBSD shim for the aic7xxx based adaptec SCSI controllers
+ * Bus independent FreeBSD shim for the aic79xx based Adaptec SCSI controllers
  *
  * Copyright (c) 1994-2002 Justin T. Gibbs.
  * Copyright (c) 2001-2002 Adaptec Inc.
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.c#27 $
+ * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.c#35 $
  *
- * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_osm.c,v 1.14 2003/06/14 22:17:39 njl Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx_osm.c,v 1.14 2007/07/03 20:55:42 pavalos Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_osm.c,v 1.16 2003/12/17 00:02:09 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx_osm.c,v 1.15 2007/07/06 00:01:16 pavalos Exp $
  */
 
 #include "aic79xx_osm.h"
 #include "aic79xx_inline.h"
 
+#include <sys/kthread.h>
+
 #include "opt_ddb.h"
 #ifdef DDB
 #include <ddb/ddb.h>
@@ -47,6 +49,8 @@
 #define AHD_TMODE_ENABLE 0
 #endif
 
+#include "aic_osm_lib.c"
+
 #define ccb_scb_ptr spriv_ptr0
 
 #if UNUSED
@@ -73,21 +77,13 @@ static int  ahd_create_path(struct ahd_softc *ahd,
                                char channel, u_int target, u_int lun,
                                struct cam_path **path);
 
-#if NOT_YET
-static void    ahd_set_recoveryscb(struct ahd_softc *ahd, struct scb *scb);
-#endif
-
 static int
 ahd_create_path(struct ahd_softc *ahd, char channel, u_int target,
                u_int lun, struct cam_path **path)
 {
        path_id_t path_id;
 
-       if (channel == 'B')
-               path_id = cam_sim_path(ahd->platform_data->sim_b);
-       else 
-               path_id = cam_sim_path(ahd->platform_data->sim);
-
+       path_id = cam_sim_path(ahd->platform_data->sim);
        return (xpt_create_path(path, /*periph*/NULL,
                                path_id, target, lun));
 }
@@ -122,6 +118,12 @@ ahd_attach(struct ahd_softc *ahd)
        count = 0;
        sim = NULL;
 
+       /*
+        * Create a thread to perform all recovery.
+        */
+       if (ahd_spawn_recovery_thread(ahd) != 0)
+               goto fail;
+
        ahd_controller_info(ahd, ahd_info);
        kprintf("%s\n", ahd_info);
        ahd_lock();
@@ -201,6 +203,8 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
 
        ccb = scb->io_ctx;
        LIST_REMOVE(scb, pending_links);
+       if ((scb->flags & SCB_TIMEDOUT) != 0)
+               LIST_REMOVE(scb, timedout_links);
 
        callout_stop(&ccb->ccb_h.timeout_ch);
 
@@ -238,7 +242,7 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
                        }
                }
 
-               if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG)
+               if (aic_get_transaction_status(scb) == CAM_REQ_INPROG)
                        ccb->ccb_h.status |= CAM_REQ_CMP;
                ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
                ahd_free_scb(ahd, scb);
@@ -271,19 +275,19 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
                        time *= hz;
                        time /= 1000;
                        callout_reset(&ccb->ccb_h.timeout_ch, time,
-                           ahd_timeout, list_scb);
+                           ahd_platform_timeout, list_scb);
                }
 
-               if (ahd_get_transaction_status(scb) == CAM_BDR_SENT
-                || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED)
-                       ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
+               if (aic_get_transaction_status(scb) == CAM_BDR_SENT
+                || aic_get_transaction_status(scb) == CAM_REQ_ABORTED)
+                       aic_set_transaction_status(scb, CAM_CMD_TIMEOUT);
                ahd_print_path(ahd, scb);
                kprintf("no longer in timeout, status = %x\n",
                       ccb->ccb_h.status);
        }
 
        /* Don't clobber any existing error state */
-       if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG) {
+       if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) {
                ccb->ccb_h.status |= CAM_REQ_CMP;
        } else if ((scb->flags & SCB_SENSE) != 0) {
                /*
@@ -539,10 +543,7 @@ ahd_action(struct cam_sim *sim, union ccb *ccb)
        }
        case XPT_CALC_GEOMETRY:
        {
-               int       extended;
-
-               extended = ahd->flags & AHD_EXTENDED_TRANS_A;
-               cam_calc_geometry(&ccb->ccg, extended);
+               cam_calc_geometry(&ccb->ccg, ahd->flags & AHD_EXTENDED_TRANS_A);
                xpt_done(ccb);
                break;
        }
@@ -1013,9 +1014,9 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
 
        if (error != 0) {
                if (error == EFBIG)
-                       ahd_set_transaction_status(scb, CAM_REQ_TOO_BIG);
+                       aic_set_transaction_status(scb, CAM_REQ_TOO_BIG);
                else
-                       ahd_set_transaction_status(scb, CAM_REQ_CMP_ERR);
+                       aic_set_transaction_status(scb, CAM_REQ_CMP_ERR);
                if (nsegments != 0)
                        bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap);
                ahd_lock();
@@ -1064,7 +1065,7 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
         * Last time we need to check if this SCB needs to
         * be aborted.
         */
-       if (ahd_get_transaction_status(scb) != CAM_REQ_INPROG) {
+       if (aic_get_transaction_status(scb) != CAM_REQ_INPROG) {
                if (nsegments != 0)
                        bus_dmamap_unload(ahd->buffer_dmat,
                                          scb->dmamap);
@@ -1115,7 +1116,8 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
                time = ccb->ccb_h.timeout;
                time *= hz;
                time /= 1000;
-               callout_reset(&ccb->ccb_h.timeout_ch, time, ahd_timeout, scb);
+               callout_reset(&ccb->ccb_h.timeout_ch, time,
+                   ahd_platform_timeout, scb);
        }
 
        if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
@@ -1161,7 +1163,7 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
                                 * greater than 16 bytes, we could use
                                 * the sense buffer to store the CDB.
                                 */
-                               ahd_set_transaction_status(scb,
+                               aic_set_transaction_status(scb,
                                                           CAM_REQ_INVALID);
                                ahd_lock();
                                ahd_free_scb(ahd, scb);
@@ -1171,7 +1173,7 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
                        }
                        if ((ccb_h->flags & CAM_CDB_PHYS) != 0) {
                                hscb->shared_data.idata.cdb_from_host.cdbptr =
-                                  ahd_htole64((uintptr_t)csio->cdb_io.cdb_ptr);
+                                  aic_htole64((uintptr_t)csio->cdb_io.cdb_ptr);
                                hscb->shared_data.idata.cdb_from_host.cdblen =
                                   csio->cdb_len;
                                hscb->cdb_len |= SCB_CDB_LEN_PTR;
@@ -1182,7 +1184,7 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
                        }
                } else {
                        if (hscb->cdb_len > MAX_CDB_LEN) {
-                               ahd_set_transaction_status(scb,
+                               aic_set_transaction_status(scb,
                                                           CAM_REQ_INVALID);
                                ahd_lock();
                                ahd_free_scb(ahd, scb);
@@ -1255,298 +1257,6 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
        }
 }
 
-#if NOT_YET
-static void
-ahd_set_recoveryscb(struct ahd_softc *ahd, struct scb *scb) {
-
-       if ((scb->flags & SCB_RECOVERY_SCB) == 0) {
-               struct scb *list_scb;
-
-               scb->flags |= SCB_RECOVERY_SCB;
-
-               /*
-                * Take all queued, but not sent SCBs out of the equation.
-                * Also ensure that no new CCBs are queued to us while we
-                * try to fix this problem.
-                */
-               if ((scb->io_ctx->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
-                       xpt_freeze_simq(SCB_GET_SIM(ahd, scb), /*count*/1);
-                       scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ;
-               }
-
-               /*
-                * Go through all of our pending SCBs and remove
-                * any scheduled timeouts for them.  We will reschedule
-                * them after we've successfully fixed this problem.
-                */
-               LIST_FOREACH(list_scb, &ahd->pending_scbs, pending_links) {
-                       union ccb *ccb;
-
-                       ccb = list_scb->io_ctx;
-                       callout_stop(&ccb->ccb_h.timeout_ch);
-               }
-       }
-}
-#endif
-
-void
-ahd_timeout(void *arg)
-{
-       struct  scb       *scb;
-       struct  ahd_softc *ahd;
-       ahd_mode_state     saved_modes;
-       int                target;
-       int                lun;
-       char               channel;
-
-#if NOT_YET
-       int                i;
-       int                found;
-       u_int              last_phase;
-#endif
-
-       scb = (struct scb *)arg; 
-       ahd = (struct ahd_softc *)scb->ahd_softc;
-
-       ahd_lock();
-
-       ahd_pause_and_flushwork(ahd);
-
-       saved_modes = ahd_save_modes(ahd);
-#if 0
-       ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
-       ahd_outb(ahd, SCSISIGO, ACKO);
-       kprintf("set ACK\n");
-       ahd_outb(ahd, SCSISIGO, 0);
-       kprintf("clearing Ack\n");
-       ahd_restore_modes(ahd, saved_modes);
-#endif
-       if ((scb->flags & SCB_ACTIVE) == 0) {
-               /* Previous timeout took care of me already */
-               kprintf("%s: Timedout SCB already complete. "
-                      "Interrupts may not be functioning.\n", ahd_name(ahd));
-               ahd_unpause(ahd);
-               ahd_unlock();
-               return;
-       }
-
-       target = SCB_GET_TARGET(ahd, scb);
-       channel = SCB_GET_CHANNEL(ahd, scb);
-       lun = SCB_GET_LUN(scb);
-
-       ahd_print_path(ahd, scb);
-       kprintf("SCB 0x%x - timed out\n", SCB_GET_TAG(scb));
-       ahd_dump_card_state(ahd);
-       ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim),
-                         /*initiate reset*/TRUE);
-       ahd_unlock();
-       return;
-#if NOT_YET
-       last_phase = ahd_inb(ahd, LASTPHASE);
-       if (scb->sg_count > 0) {
-               for (i = 0; i < scb->sg_count; i++) {
-                       kprintf("sg[%d] - Addr 0x%x : Length %d\n",
-                              i,
-                              ((struct ahd_dma_seg *)scb->sg_list)[i].addr,
-                              ((struct ahd_dma_seg *)scb->sg_list)[i].len
-                               & AHD_SG_LEN_MASK);
-               }
-       }
-       if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) {
-               /*
-                * Been down this road before.
-                * Do a full bus reset.
-                */
-bus_reset:
-               ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
-               found = ahd_reset_channel(ahd, channel, /*Initiate Reset*/TRUE);
-               kprintf("%s: Issued Channel %c Bus Reset. "
-                      "%d SCBs aborted\n", ahd_name(ahd), channel, found);
-       } else {
-               /*
-                * If we are a target, transition to bus free and report
-                * the timeout.
-                * 
-                * The target/initiator that is holding up the bus may not
-                * be the same as the one that triggered this timeout
-                * (different commands have different timeout lengths).
-                * If the bus is idle and we are actiing as the initiator
-                * for this request, queue a BDR message to the timed out
-                * target.  Otherwise, if the timed out transaction is
-                * active:
-                *   Initiator transaction:
-                *      Stuff the message buffer with a BDR message and assert
-                *      ATN in the hopes that the target will let go of the bus
-                *      and go to the mesgout phase.  If this fails, we'll
-                *      get another timeout 2 seconds later which will attempt
-                *      a bus reset.
-                *
-                *   Target transaction:
-                *      Transition to BUS FREE and report the error.
-                *      It's good to be the target!
-                */
-               u_int active_scb_index;
-               u_int saved_scbptr;
-
-               saved_scbptr = ahd_get_scbptr(ahd);
-               active_scb_index = saved_scbptr;
-
-               if (last_phase != P_BUSFREE 
-                 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0
-                 && (active_scb_index < ahd->scb_data.numscbs)) {
-                       struct scb *active_scb;
-
-                       /*
-                        * If the active SCB is not us, assume that
-                        * the active SCB has a longer timeout than
-                        * the timedout SCB, and wait for the active
-                        * SCB to timeout.
-                        */ 
-                       active_scb = ahd_lookup_scb(ahd, active_scb_index);
-                       if (active_scb != scb) {
-                               struct   ccb_hdr *ccbh;
-                               uint64_t newtimeout;
-
-                               ahd_print_path(ahd, scb);
-                               kprintf("Other SCB Timeout%s",
-                                      (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0
-                                      ? " again\n" : "\n");
-                               scb->flags |= SCB_OTHERTCL_TIMEOUT;
-                               newtimeout =
-                                   MAX(active_scb->io_ctx->ccb_h.timeout,
-                                       scb->io_ctx->ccb_h.timeout);
-                               newtimeout *= hz;
-                               newtimeout /= 1000;
-                               ccbh = &scb->io_ctx->ccb_h;
-                               callout_reset(&scb->io_ctx->ccb_h.timeout_ch,
-                                   newtimeout, ahd_timeout, scb);
-                               ahd_unpause(ahd);
-                               ahd_unlock();
-                               return;
-                       } 
-
-                       /* It's us */
-                       if ((scb->hscb->control & TARGET_SCB) != 0) {
-
-                               /*
-                                * Send back any queued up transactions
-                                * and properly record the error condition.
-                                */
-                               ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
-                                              SCB_GET_CHANNEL(ahd, scb),
-                                              SCB_GET_LUN(scb),
-                                              SCB_GET_TAG(scb),
-                                              ROLE_TARGET,
-                                              CAM_CMD_TIMEOUT);
-
-                               /* Will clear us from the bus */
-                               ahd_restart(ahd);
-                               ahd_unlock();
-                               return;
-                       }
-
-                       ahd_set_recoveryscb(ahd, active_scb);
-                       ahd_outb(ahd, MSG_OUT, HOST_MSG);
-                       ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
-                       ahd_print_path(ahd, active_scb);
-                       kprintf("BDR message in message buffer\n");
-                       active_scb->flags |= SCB_DEVICE_RESET;
-                       callout_reset(&active_scb->io_ctx->ccb_h.timeout_ch,
-                           2 * hz, ahd_timeout, active_scb);
-                       ahd_unpause(ahd);
-               } else {
-                       int      disconnected;
-
-                       /* XXX Shouldn't panic.  Just punt instead? */
-                       if ((scb->hscb->control & TARGET_SCB) != 0)
-                               panic("Timed-out target SCB but bus idle");
-
-                       if (last_phase != P_BUSFREE
-                        && (ahd_inb(ahd, SSTAT0) & TARGET) != 0) {
-                               /* XXX What happened to the SCB? */
-                               /* Hung target selection.  Goto busfree */
-                               kprintf("%s: Hung target selection\n",
-                                      ahd_name(ahd));
-                               ahd_restart(ahd);
-                               ahd_unlock();
-                               return;
-                       }
-
-                       if (ahd_search_qinfifo(ahd, target, channel, lun,
-                                              SCB_GET_TAG(scb), ROLE_INITIATOR,
-                                              /*status*/0, SEARCH_COUNT) > 0) {
-                               disconnected = FALSE;
-                       } else {
-                               disconnected = TRUE;
-                       }
-
-                       if (disconnected) {
-
-                               ahd_set_recoveryscb(ahd, scb);
-                               /*
-                                * Actually re-queue this SCB in an attempt
-                                * to select the device before it reconnects.
-                                * In either case (selection or reselection),
-                                * we will now issue a target reset to the
-                                * timed-out device.
-                                *
-                                * Set the MK_MESSAGE control bit indicating
-                                * that we desire to send a message.  We
-                                * also set the disconnected flag since
-                                * in the paging case there is no guarantee
-                                * that our SCB control byte matches the
-                                * version on the card.  We don't want the
-                                * sequencer to abort the command thinking
-                                * an unsolicited reselection occurred.
-                                */
-                               scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
-                               scb->flags |= SCB_DEVICE_RESET;
-
-                               /*
-                                * The sequencer will never re-reference the
-                                * in-core SCB.  To make sure we are notified
-                                * during reslection, set the MK_MESSAGE flag
-                                * in the card's copy of the SCB.
-                                */
-                               ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
-                               ahd_outb(ahd, SCB_CONTROL,
-                                        ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
-
-                               /*
-                                * Clear out any entries in the QINFIFO first
-                                * so we are the next SCB for this target
-                                * to run.
-                                */
-                               ahd_search_qinfifo(ahd,
-                                                  SCB_GET_TARGET(ahd, scb),
-                                                  channel, SCB_GET_LUN(scb),
-                                                  SCB_LIST_NULL,
-                                                  ROLE_INITIATOR,
-                                                  CAM_REQUEUE_REQ,
-                                                  SEARCH_COMPLETE);
-                               ahd_print_path(ahd, scb);
-                               kprintf("Queuing a BDR SCB\n");
-                               ahd_qinfifo_requeue_tail(ahd, scb);
-                               ahd_set_scbptr(ahd, saved_scbptr);
-                               callout_reset(&scb->io_ctx->ccb_h.timeout_ch,
-                                   2 * hz, ahd_timeout, scb);
-                               ahd_unpause(ahd);
-                       } else {
-                               /* Go "immediatly" to the bus reset */
-                               /* This shouldn't happen */
-                               ahd_set_recoveryscb(ahd, scb);
-                               ahd_print_path(ahd, scb);
-                               kprintf("SCB %d: Immediate reset.  "
-                                       "Flags = 0x%x\n", SCB_GET_TAG(scb),
-                                       scb->flags);
-                               goto bus_reset;
-                       }
-               }
-       }
-       ahd_unlock();
-#endif
-}
-
 static void
 ahd_abort_ccb(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
 {
@@ -1730,12 +1440,6 @@ ahd_platform_free(struct ahd_softc *ahd)
                                             pdata->irq_res_type,
                                             0, pdata->irq);
 
-               if (pdata->sim_b != NULL) {
-                       xpt_async(AC_LOST_DEVICE, pdata->path_b, NULL);
-                       xpt_free_path(pdata->path_b);
-                       xpt_bus_deregister(cam_sim_path(pdata->sim_b));
-                       cam_sim_free(pdata->sim_b);
-               }
                if (pdata->sim != NULL) {
                        xpt_async(AC_LOST_DEVICE, pdata->path, NULL);
                        xpt_free_path(pdata->path);
@@ -1767,6 +1471,7 @@ ahd_detach(device_t dev)
                device_printf(dev, "aic7xxx already detached\n");
                return (ENOENT);
        }
+       TAILQ_REMOVE(&ahd_tailq, ahd, links);
        ahd_lock();
        ahd_intr_enable(ahd, FALSE);
        bus_teardown_intr(dev, ahd->platform_data->irq, ahd->platform_data->ih);
index 7ac9ddd..3107cbe 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.h#20 $
+ * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.h#23 $
  *
- * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_osm.h,v 1.4.2.3 2003/06/10 03:26:07 gibbs Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx_osm.h,v 1.8 2007/01/27 15:03:25 swildner Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_osm.h,v 1.13 2003/12/17 00:02:09 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx_osm.h,v 1.9 2007/07/06 00:01:16 pavalos Exp $
  */
 
 #ifndef _AIC79XX_FREEBSD_H_
@@ -53,7 +53,7 @@
 #include <sys/queue.h>
 #include <sys/thread2.h>
 
-#define AHD_PCI_CONFIG 1
+#define AIC_PCI_CONFIG 1
 #include <machine/endian.h>
 #include <machine/clock.h>
 
 #ifndef offsetof
 #define offsetof(type, member)  ((size_t)(&((type *)0)->member))
 #endif
-/************************* Forward Declarations *******************************/
-typedef device_t ahd_dev_softc_t;
-typedef union ccb *ahd_io_ctx_t;
-
-/***************************** Bus Space/DMA **********************************/
-#define ahd_dma_tag_create(ahd, parent_tag, alignment, boundary,       \
-                          lowaddr, highaddr, filter, filterarg,        \
-                          maxsize, nsegments, maxsegsz, flags,         \
-                          dma_tagp)                                    \
-       bus_dma_tag_create(parent_tag, alignment, boundary,             \
-                          lowaddr, highaddr, filter, filterarg,        \
-                          maxsize, nsegments, maxsegsz, flags,         \
-                          dma_tagp)
-
-#define ahd_dma_tag_destroy(ahd, tag)                                  \
-       bus_dma_tag_destroy(tag)
-
-#define ahd_dmamem_alloc(ahd, dmat, vaddr, flags, mapp)                        \
-       bus_dmamem_alloc(dmat, vaddr, flags, mapp)
-
-#define ahd_dmamem_free(ahd, dmat, vaddr, map)                         \
-       bus_dmamem_free(dmat, vaddr, map)
-
-#define ahd_dmamap_create(ahd, tag, flags, mapp)                       \
-       bus_dmamap_create(tag, flags, mapp)
-
-#define ahd_dmamap_destroy(ahd, tag, map)                              \
-       bus_dmamap_destroy(tag, map)
-
-#define ahd_dmamap_load(ahd, dmat, map, addr, buflen, callback,                \
-                       callback_arg, flags)                            \
-       bus_dmamap_load(dmat, map, addr, buflen, callback, callback_arg, flags)
-
-#define ahd_dmamap_unload(ahd, tag, map)                               \
-       bus_dmamap_unload(tag, map)
-
-/* XXX Need to update Bus DMA for partial map syncs */
-#define ahd_dmamap_sync(ahd, dma_tag, dmamap, offset, len, op)         \
-       bus_dmamap_sync(dma_tag, dmamap, op)
 
 /************************ Tunable Driver Parameters  **************************/
 /*
@@ -161,9 +122,7 @@ struct ahd_platform_data {
         * Hooks into the XPT.
         */
        struct  cam_sim         *sim;
-       struct  cam_sim         *sim_b;
        struct  cam_path        *path;
-       struct  cam_path        *path_b;
 
        int                      regs_res_type[2];
        int                      regs_res_id[2];
@@ -172,74 +131,22 @@ struct ahd_platform_data {
        struct resource         *irq;
        void                    *ih;
        eventhandler_tag         eh;
+       struct thread           *recovery_thread;
 };
 
 struct scb_platform_data {
 };
 
-/********************************* Byte Order *********************************/
-#if defined(__FreeBSD___) && __FreeBSD_version >= 500000
-#define ahd_htobe16(x) htobe16(x)
-#define ahd_htobe32(x) htobe32(x)
-#define ahd_htobe64(x) htobe64(x)
-#define ahd_htole16(x) htole16(x)
-#define ahd_htole32(x) htole32(x)
-#define ahd_htole64(x) htole64(x)
-
-#define ahd_be16toh(x) be16toh(x)
-#define ahd_be32toh(x) be32toh(x)
-#define ahd_be64toh(x) be64toh(x)
-#define ahd_le16toh(x) le16toh(x)
-#define ahd_le32toh(x) le32toh(x)
-#define ahd_le64toh(x) le64toh(x)
-#else
-#define ahd_htobe16(x) (x)
-#define ahd_htobe32(x) (x)
-#define ahd_htobe64(x) (x)
-#define ahd_htole16(x) (x)
-#define ahd_htole32(x) (x)
-#define ahd_htole64(x) (x)
-
-#define ahd_be16toh(x) (x)
-#define ahd_be32toh(x) (x)
-#define ahd_be64toh(x) (x)
-#define ahd_le16toh(x) (x)
-#define ahd_le32toh(x) (x)
-#define ahd_le64toh(x) (x)
-#endif
-
-/************************** Timer DataStructures ******************************/
-typedef struct callout ahd_timer_t;
-
 /***************************** Core Includes **********************************/
 #if AHD_REG_PRETTY_PRINT
 #define AIC_DEBUG_REGISTERS 1
 #else
 #define AIC_DEBUG_REGISTERS 0
 #endif
-#include "aic79xx.h"
-
-/***************************** Timer Facilities *******************************/
-timeout_t ahd_timeout;
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
-#define ahd_timer_init(timer) callout_init(timer, /*mpsafe*/0)
-#else
-#define ahd_timer_init callout_init
-#endif
-#define ahd_timer_stop callout_stop
-
-static __inline void
-ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg)
-{
-       callout_reset(timer, (usec * hz)/1000000, func, arg);
-}
-
-static __inline void
-ahd_scb_timer_reset(struct scb *scb, u_int usec)
-{
-       callout_reset(&scb->io_ctx->ccb_h.timeout_ch, (usec * hz)/1000000,
-                     ahd_timeout, scb);
-}
+#define        AIC_CORE_INCLUDE "aic79xx.h"
+#define        AIC_LIB_PREFIX ahd
+#define        AIC_CONST_PREFIX AHD
+#include "aic_osm_lib.h"
 
 /*************************** Device Access ************************************/
 #define ahd_inb(ahd, port)                                     \
@@ -251,13 +158,13 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec)
                          (ahd)->bshs[(port) >> 8], (port) & 0xFF, value)
 
 #define ahd_inw_atomic(ahd, port)                              \
-       ahd_le16toh(bus_space_read_2((ahd)->tags[(port) >> 8],  \
+       aic_le16toh(bus_space_read_2((ahd)->tags[(port) >> 8],  \
                                     (ahd)->bshs[(port) >> 8], (port) & 0xFF))
 
 #define ahd_outw_atomic(ahd, port, value)                      \
        bus_space_write_2((ahd)->tags[(port) >> 8],             \
                          (ahd)->bshs[(port) >> 8],             \
-                         (port & 0xFF), ahd_htole16(value))
+                         (port & 0xFF), aic_htole16(value))
 
 #define ahd_outsb(ahd, port, valp, count)                      \
        bus_space_write_multi_1((ahd)->tags[(port) >> 8],       \
@@ -295,222 +202,26 @@ ahd_unlock(void)
        crit_exit();
 }
 
-/****************************** OS Primitives *********************************/
-#define ahd_delay DELAY
+/********************************** PCI ***************************************/
+int ahd_pci_map_registers(struct ahd_softc *ahd);
+int ahd_pci_map_int(struct ahd_softc *ahd);
 
 /************************** Transaction Operations ****************************/
-static __inline void ahd_set_transaction_status(struct scb *, uint32_t);
-static __inline void ahd_set_scsi_status(struct scb *, uint32_t);
-static __inline uint32_t ahd_get_transaction_status(struct scb *);
-static __inline uint32_t ahd_get_scsi_status(struct scb *);
-static __inline void ahd_set_transaction_tag(struct scb *, int, u_int);
-static __inline u_long ahd_get_transfer_length(struct scb *);
-static __inline int ahd_get_transfer_dir(struct scb *);
-static __inline void ahd_set_residual(struct scb *, u_long);
-static __inline void ahd_set_sense_residual(struct scb *, u_long);
-static __inline u_long ahd_get_residual(struct scb *);
-static __inline int ahd_perform_autosense(struct scb *);
-static __inline uint32_t ahd_get_sense_bufsize(struct ahd_softc*, struct scb*);
-static __inline void ahd_freeze_simq(struct ahd_softc *);
-static __inline void ahd_release_simq(struct ahd_softc *);
-static __inline void ahd_freeze_ccb(union ccb *ccb);
-static __inline void ahd_freeze_scb(struct scb *scb);
-static __inline void ahd_platform_freeze_devq(struct ahd_softc *, struct scb *);
-static __inline int  ahd_platform_abort_scbs(struct ahd_softc *ahd, int target,
-                                            char channel, int lun, u_int tag,
-                                            role_t role, uint32_t status);
-
-static __inline
-void ahd_set_transaction_status(struct scb *scb, uint32_t status)
-{
-       scb->io_ctx->ccb_h.status &= ~CAM_STATUS_MASK;
-       scb->io_ctx->ccb_h.status |= status;
-}
-
-static __inline
-void ahd_set_scsi_status(struct scb *scb, uint32_t status)
-{
-       scb->io_ctx->csio.scsi_status = status;
-}
-
-static __inline
-uint32_t ahd_get_transaction_status(struct scb *scb)
-{
-       return (scb->io_ctx->ccb_h.status & CAM_STATUS_MASK);
-}
-
-static __inline
-uint32_t ahd_get_scsi_status(struct scb *scb)
-{
-       return (scb->io_ctx->csio.scsi_status);
-}
-
-static __inline
-void ahd_set_transaction_tag(struct scb *scb, int enabled, u_int type)
-{
-       scb->io_ctx->csio.tag_action = type;
-       if (enabled)
-               scb->io_ctx->ccb_h.flags |= CAM_TAG_ACTION_VALID;
-       else
-               scb->io_ctx->ccb_h.flags &= ~CAM_TAG_ACTION_VALID;
-}
-
-static __inline
-u_long ahd_get_transfer_length(struct scb *scb)
-{
-       return (scb->io_ctx->csio.dxfer_len);
-}
-
-static __inline
-int ahd_get_transfer_dir(struct scb *scb)
-{
-       return (scb->io_ctx->ccb_h.flags & CAM_DIR_MASK);
-}
-
-static __inline
-void ahd_set_residual(struct scb *scb, u_long resid)
-{
-       scb->io_ctx->csio.resid = resid;
-}
-
-static __inline
-void ahd_set_sense_residual(struct scb *scb, u_long resid)
-{
-       scb->io_ctx->csio.sense_resid = resid;
-}
-
-static __inline
-u_long ahd_get_residual(struct scb *scb)
-{
-       return (scb->io_ctx->csio.resid);
-}
-
-static __inline
-int ahd_perform_autosense(struct scb *scb)
-{
-       return (!(scb->io_ctx->ccb_h.flags & CAM_DIS_AUTOSENSE));
-}
-
-static __inline uint32_t
-ahd_get_sense_bufsize(struct ahd_softc *ahd, struct scb *scb)
-{
-       return (sizeof(struct scsi_sense_data));
-}
-
-static __inline void
-ahd_freeze_simq(struct ahd_softc *ahd)
-{
-       xpt_freeze_simq(ahd->platform_data->sim, /*count*/1);
-}
+static __inline void aic_freeze_simq(struct aic_softc*);
+static __inline void aic_release_simq(struct aic_softc*);
 
 static __inline void
-ahd_release_simq(struct ahd_softc *ahd)
+aic_freeze_simq(struct aic_softc *aic)
 {
-       xpt_release_simq(ahd->platform_data->sim, /*run queue*/TRUE);
+       xpt_freeze_simq(aic->platform_data->sim, /*count*/1);
 }
 
 static __inline void
-ahd_freeze_ccb(union ccb *ccb)
+aic_release_simq(struct aic_softc *aic)
 {
-       if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
-               ccb->ccb_h.status |= CAM_DEV_QFRZN;
-               xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
-       }
+       xpt_release_simq(aic->platform_data->sim, /*run queue*/TRUE);
 }
 
-static __inline void
-ahd_freeze_scb(struct scb *scb)
-{
-       ahd_freeze_ccb(scb->io_ctx);
-}
-
-static __inline void
-ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb)
-{
-       /* Nothing to do here for FreeBSD */
-}
-
-static __inline int
-ahd_platform_abort_scbs(struct ahd_softc *ahd, int target,
-                       char channel, int lun, u_int tag,
-                       role_t role, uint32_t status)
-{
-       /* Nothing to do here for FreeBSD */
-       return (0);
-}
-
-static __inline void
-ahd_platform_scb_free(struct ahd_softc *ahd, struct scb *scb)
-{
-       /* What do we do to generically handle driver resource shortages??? */
-       if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0
-        && scb->io_ctx != NULL
-        && (scb->io_ctx->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
-               scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ;
-               ahd->flags &= ~AHD_RESOURCE_SHORTAGE;
-       }
-       scb->io_ctx = NULL;
-}
-
-/********************************** PCI ***************************************/
-#ifdef AHD_PCI_CONFIG
-static __inline uint32_t ahd_pci_read_config(ahd_dev_softc_t pci,
-                                            int reg, int width);
-static __inline void    ahd_pci_write_config(ahd_dev_softc_t pci,
-                                             int reg, uint32_t value,
-                                             int width);
-static __inline int     ahd_get_pci_function(ahd_dev_softc_t);
-static __inline int     ahd_get_pci_slot(ahd_dev_softc_t);
-static __inline int     ahd_get_pci_bus(ahd_dev_softc_t);
-
-int                     ahd_pci_map_registers(struct ahd_softc *ahd);
-int                     ahd_pci_map_int(struct ahd_softc *ahd);
-
-static __inline uint32_t
-ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width)
-{
-       return (pci_read_config(pci, reg, width));
-}
-
-static __inline void
-ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width)
-{
-       pci_write_config(pci, reg, value, width);
-}
-
-static __inline int
-ahd_get_pci_function(ahd_dev_softc_t pci)
-{
-       return (pci_get_function(pci));
-}
-
-static __inline int
-ahd_get_pci_slot(ahd_dev_softc_t pci)
-{
-       return (pci_get_slot(pci));
-}
-
-static __inline int
-ahd_get_pci_bus(ahd_dev_softc_t pci)
-{
-       return (pci_get_bus(pci));
-}
-
-typedef enum
-{
-       AHD_POWER_STATE_D0,
-       AHD_POWER_STATE_D1,
-       AHD_POWER_STATE_D2,
-       AHD_POWER_STATE_D3
-} ahd_power_state;
-
-void ahd_power_state_change(struct ahd_softc *ahd,
-                           ahd_power_state new_state);
-#endif
-/******************************** VL/EISA *************************************/
-int aic7770_map_registers(struct ahd_softc *ahd);
-int aic7770_map_int(struct ahd_softc *ahd, int irq);
-
 /********************************* Debug **************************************/
 static __inline void   ahd_print_path(struct ahd_softc *, struct scb *);
 static __inline void   ahd_platform_dump_card_state(struct ahd_softc *ahd);
index 98a9b66..aa33f69 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_pci.c#80 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#84 $
  *
- * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_pci.c,v 1.16 2003/09/25 23:36:41 scottl Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx_pci.c,v 1.8 2007/07/05 05:17:39 pavalos Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_pci.c,v 1.17 2003/12/17 00:02:09 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx_pci.c,v 1.9 2007/07/06 00:01:16 pavalos Exp $
  */
 
 #ifdef __linux__
@@ -76,13 +76,13 @@ ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
 #define ID_AHA_29320ALP                        0x8017900500449005ull
 
 #define ID_AIC7901A                    0x801E9005FFFF9005ull
-#define ID_AHA_29320                   0x8012900500429005ull
-#define ID_AHA_29320B                  0x8013900500439005ull
 #define ID_AHA_29320LP                 0x8014900500449005ull
 
 #define ID_AIC7902                     0x801F9005FFFF9005ull
 #define ID_AIC7902_B                   0x801D9005FFFF9005ull
 #define ID_AHA_39320                   0x8010900500409005ull
+#define ID_AHA_29320                   0x8012900500429005ull
+#define ID_AHA_29320B                  0x8013900500439005ull
 #define ID_AHA_39320_B                 0x8015900500409005ull
 #define ID_AHA_39320A                  0x8016900500409005ull
 #define ID_AHA_39320D                  0x8011900500419005ull
@@ -137,24 +137,24 @@ struct ahd_pci_identity ahd_pci_ident_table [] =
        },
        /* aic7901A based controllers */
        {
-               ID_AHA_29320,
+               ID_AHA_29320LP,
                ID_ALL_MASK,
-               "Adaptec 29320 Ultra320 SCSI adapter",
+               "Adaptec 29320LP Ultra320 SCSI adapter",
                ahd_aic7901A_setup
        },
+       /* aic7902 based controllers */ 
        {
-               ID_AHA_29320B,
+               ID_AHA_29320,
                ID_ALL_MASK,
-               "Adaptec 29320B Ultra320 SCSI adapter",
-               ahd_aic7901A_setup
+               "Adaptec 29320 Ultra320 SCSI adapter",
+               ahd_aic7902_setup
        },
        {
-               ID_AHA_29320LP,
+               ID_AHA_29320B,
                ID_ALL_MASK,
-               "Adaptec 29320LP Ultra320 SCSI adapter",
-               ahd_aic7901A_setup
+               "Adaptec 29320B Ultra320 SCSI adapter",
+               ahd_aic7902_setup
        },
-       /* aic7902 based controllers */ 
        {
                ID_AHA_39320,
                ID_ALL_MASK,
@@ -197,18 +197,6 @@ struct ahd_pci_identity ahd_pci_ident_table [] =
                "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter",
                ahd_aic7902_setup
        },
-       {
-               ID_AHA_29320,
-               ID_ALL_MASK,
-               "Adaptec 29320 Ultra320 SCSI adapter",
-               ahd_aic7902_setup
-       },
-       {
-               ID_AHA_29320B,
-               ID_ALL_MASK,
-               "Adaptec 29320B Ultra320 SCSI adapter",
-               ahd_aic7902_setup
-       },
        /* Generic chip probes for devices we don't know 'exactly' */
        {
                ID_AIC7901 & ID_DEV_VENDOR_MASK,
@@ -276,7 +264,7 @@ static void ahd_configure_termination(struct ahd_softc *ahd,
 static void    ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat);
 
 struct ahd_pci_identity *
-ahd_find_pci_device(ahd_dev_softc_t pci)
+ahd_find_pci_device(aic_dev_softc_t pci)
 {
        uint64_t  full_id;
        uint16_t  device;
@@ -286,10 +274,10 @@ ahd_find_pci_device(ahd_dev_softc_t pci)
        struct    ahd_pci_identity *entry;
        u_int     i;
 
-       vendor = ahd_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
-       device = ahd_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);
-       subvendor = ahd_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2);
-       subdevice = ahd_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2);
+       vendor = aic_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
+       device = aic_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);
+       subvendor = aic_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2);
+       subdevice = aic_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2);
        full_id = ahd_compose_id(device,
                                 vendor,
                                 subdevice,
@@ -321,7 +309,7 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
        /*
         * Record if this is an HP board.
         */
-       subvendor = ahd_pci_read_config(ahd->dev_softc,
+       subvendor = aic_pci_read_config(ahd->dev_softc,
                                        PCIR_SUBVEND_0, /*bytes*/2);
        if (subvendor == SUBID_HP)
                ahd->flags |= AHD_HP_BOARD;
@@ -330,7 +318,7 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
        if (error != 0)
                return (error);
        
-       devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);
+       devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);
        if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) {
                ahd->chip |= AHD_PCI;
                /* Disable PCIX workarounds when running in PCI mode. */
@@ -340,7 +328,7 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
        }
        ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)];
 
-       ahd_power_state_change(ahd, AHD_POWER_STATE_D0);
+       aic_power_state_change(ahd, AIC_POWER_STATE_D0);
 
        error = ahd_pci_map_registers(ahd);
        if (error != 0)
@@ -358,17 +346,17 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
                if (bootverbose)
                        kprintf("%s: Enabling 39Bit Addressing\n",
                               ahd_name(ahd));
-               devconfig = ahd_pci_read_config(ahd->dev_softc,
+               devconfig = aic_pci_read_config(ahd->dev_softc,
                                                DEVCONFIG, /*bytes*/4);
                devconfig |= DACEN;
-               ahd_pci_write_config(ahd->dev_softc, DEVCONFIG,
+               aic_pci_write_config(ahd->dev_softc, DEVCONFIG,
                                     devconfig, /*bytes*/4);
        }
        
        /* Ensure busmastering is enabled */
-       command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);
+       command = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);
        command |= PCIM_CMD_BUSMASTEREN;
-       ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2);
+       aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2);
 
        error = ahd_softc_init(ahd);
        if (error != 0)
@@ -381,7 +369,7 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
                return (ENXIO);
 
        ahd->pci_cachesize =
-           ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME,
+           aic_pci_read_config(ahd->dev_softc, CSIZE_LATTIME,
                                /*bytes*/1) & CACHESIZE;
        ahd->pci_cachesize *= 4;
 
@@ -429,8 +417,8 @@ ahd_pci_test_register_access(struct ahd_softc *ahd)
         * Enable PCI error interrupt status, but suppress NMIs
         * generated by SERR raised due to target aborts.
         */
-       cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);
-       ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
+       cmd = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);
+       aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
                             cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);
 
        /*
@@ -462,9 +450,9 @@ ahd_pci_test_register_access(struct ahd_softc *ahd)
        ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
        targpcistat = ahd_inb(ahd, TARGPCISTAT);
        ahd_outb(ahd, TARGPCISTAT, targpcistat);
-       pci_status1 = ahd_pci_read_config(ahd->dev_softc,
+       pci_status1 = aic_pci_read_config(ahd->dev_softc,
                                          PCIR_STATUS + 1, /*bytes*/1);
-       ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
+       aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
                             pci_status1, /*bytes*/1);
        ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
        ahd_outb(ahd, CLRINT, CLRPCIINT);
@@ -493,14 +481,14 @@ fail:
 
                /* Silently clear any latched errors. */
                ahd_outb(ahd, TARGPCISTAT, targpcistat);
-               pci_status1 = ahd_pci_read_config(ahd->dev_softc,
+               pci_status1 = aic_pci_read_config(ahd->dev_softc,
                                                  PCIR_STATUS + 1, /*bytes*/1);
-               ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
+               aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
                                     pci_status1, /*bytes*/1);
                ahd_outb(ahd, CLRINT, CLRPCIINT);
        }
        ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS);
-       ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
+       aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
        return (error);
 }
 
@@ -649,14 +637,14 @@ ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control)
        uint8_t  termctl;
        uint32_t devconfig;
 
-       devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);
+       devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);
        devconfig &= ~STPWLEVEL;
        if ((ahd->flags & AHD_STPWLEVEL_A) != 0)
                devconfig |= STPWLEVEL;
        if (bootverbose)
                kprintf("%s: STPWLEVEL is %s\n",
                       ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off");
-       ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
+       aic_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
  
        /* Make sure current sensing is off. */
        if ((ahd->flags & AHD_CURRENT_SENSING) != 0) {
@@ -701,6 +689,7 @@ ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control)
         * Now set the termination based on what we found.
         */
        sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;
+       ahd->flags &= ~AHD_TERM_ENB_A;
        if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {
                ahd->flags |= AHD_TERM_ENB_A;
                sxfrctl1 |= STPWEN;
@@ -833,9 +822,9 @@ ahd_pci_intr(struct ahd_softc *ahd)
                        }
                }       
        }
-       pci_status1 = ahd_pci_read_config(ahd->dev_softc,
+       pci_status1 = aic_pci_read_config(ahd->dev_softc,
                                          PCIR_STATUS + 1, /*bytes*/1);
-       ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
+       aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
                             pci_status1, /*bytes*/1);
        ahd_restore_modes(ahd, saved_modes);
        ahd_outb(ahd, CLRINT, CLRPCIINT);
@@ -857,7 +846,7 @@ ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat)
         * Check for splits in all modes.  Modes 0 and 1
         * additionally have SG engine splits to look at.
         */
-       pcix_status = ahd_pci_read_config(ahd->dev_softc, PCIXR_STATUS,
+       pcix_status = aic_pci_read_config(ahd->dev_softc, PCIXR_STATUS,
                                          /*bytes*/2);
        kprintf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n",
               ahd_name(ahd), pcix_status);
@@ -906,7 +895,7 @@ ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat)
        /*
         * Clear PCI-X status bits.
         */
-       ahd_pci_write_config(ahd->dev_softc, PCIXR_STATUS,
+       aic_pci_write_config(ahd->dev_softc, PCIXR_STATUS,
                             pcix_status, /*bytes*/2);
        ahd_outb(ahd, CLRINT, CLRSPLTINT);
        ahd_restore_modes(ahd, saved_modes);
@@ -941,18 +930,18 @@ ahd_aic7902_setup(struct ahd_softc *ahd)
 static int
 ahd_aic790X_setup(struct ahd_softc *ahd)
 {
-       ahd_dev_softc_t pci;
+       aic_dev_softc_t pci;
        u_int rev;
 
        pci = ahd->dev_softc;
-       rev = ahd_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
+       rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
        if (rev < ID_AIC7902_PCI_REV_A4) {
                kprintf("%s: Unable to attach to unsupported chip revision %d\n",
                       ahd_name(ahd), rev);
-               ahd_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2);
+               aic_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2);
                return (ENXIO);
        }
-       ahd->channel = ahd_get_pci_function(pci) + 'A';
+       ahd->channel = aic_get_pci_function(pci) + 'A';
        if (rev < ID_AIC7902_PCI_REV_B0) {
                /*
                 * Enable A series workarounds.
@@ -980,7 +969,7 @@ ahd_aic790X_setup(struct ahd_softc *ahd)
                u_int devconfig1;
 
                ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS
-                             |  AHD_NEW_DFCNTRL_OPTS;
+                             |  AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY;
                ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG;
 
                /*
@@ -1002,10 +991,10 @@ ahd_aic790X_setup(struct ahd_softc *ahd)
                 * XXX - Find out exactly what this does from the hardware
                 *       folks!
                 */
-               devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);
-               ahd_pci_write_config(pci, DEVCONFIG1,
+               devconfig1 = aic_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);
+               aic_pci_write_config(pci, DEVCONFIG1,
                                     devconfig1|PREQDIS, /*bytes*/1);
-               devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);
+               devconfig1 = aic_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);
        }
 
        return (0);
index 4b0ac3f..140a842 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/aic7xxx.c#134 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#147 $
  *
- * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.c,v 1.41.2.27 2003/06/10 03:26:08 gibbs Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/aic7xxx.c,v 1.14 2007/05/13 18:33:57 swildner Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.c,v 1.98 2003/12/19 18:10:59 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/aic7xxx.c,v 1.15 2007/07/06 00:01:16 pavalos Exp $
  */
 
 #include "aic7xxx_osm.h"
@@ -315,7 +315,7 @@ ahc_run_qoutfifo(struct ahc_softc *ahc)
                         */
                        modnext = ahc->qoutfifonext & ~0x3;
                        *((uint32_t *)(&ahc->qoutfifo[modnext])) = 0xFFFFFFFFUL;
-                       ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
+                       aic_dmamap_sync(ahc, ahc->shared_data_dmat,
                                        ahc->shared_data_dmamap,
                                        /*offset*/modnext, /*len*/4,
                                        BUS_DMASYNC_PREREAD);
@@ -453,14 +453,14 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
                         * complete.
                         */
                        scb->flags &= ~SCB_SENSE;
-                       ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
+                       aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
                        break;
                }
-               ahc_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR);
+               aic_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR);
                /* Freeze the queue until the client sees the error. */
                ahc_freeze_devq(ahc, scb);
-               ahc_freeze_scb(scb);
-               ahc_set_scsi_status(scb, hscb->shared_data.status.scsi_status);
+               aic_freeze_scb(scb);
+               aic_set_scsi_status(scb, hscb->shared_data.status.scsi_status);
                switch (hscb->shared_data.status.scsi_status) {
                case SCSI_STATUS_OK:
                        kprintf("%s: Interrupted for staus of 0???\n",
@@ -482,7 +482,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
                        }
 #endif
 
-                       if (ahc_perform_autosense(scb) == 0)
+                       if (aic_perform_autosense(scb) == 0)
                                break;
 
                        targ_info = ahc_fetch_transinfo(ahc,
@@ -504,12 +504,12 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
                        }
 #endif
                        sg->addr = ahc_get_sense_bufaddr(ahc, scb);
-                       sg->len = ahc_get_sense_bufsize(ahc, scb);
+                       sg->len = aic_get_sense_bufsize(ahc, scb);
                        sg->len |= AHC_DMA_LAST_SEG;
 
                        /* Fixup byte order */
-                       sg->addr = ahc_htole32(sg->addr);
-                       sg->len = ahc_htole32(sg->len);
+                       sg->addr = aic_htole32(sg->addr);
+                       sg->len = aic_htole32(sg->len);
 
                        sc->opcode = REQUEST_SENSE;
                        sc->byte2 = 0;
@@ -538,8 +538,8 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
                         * errors will be reported before any data
                         * phases occur.
                         */
-                       if (ahc_get_residual(scb) 
-                        == ahc_get_transfer_length(scb)) {
+                       if (aic_get_residual(scb) 
+                        == aic_get_transfer_length(scb)) {
                                ahc_update_neg_request(ahc, &devinfo,
                                                       tstate, targ_info,
                                                       AHC_NEG_IF_NON_ASYNC);
@@ -553,7 +553,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
                        hscb->dataptr = sg->addr; 
                        hscb->datacnt = sg->len;
                        hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID;
-                       hscb->sgptr = ahc_htole32(hscb->sgptr);
+                       hscb->sgptr = aic_htole32(hscb->sgptr);
                        scb->sg_count = 1;
                        scb->flags |= SCB_SENSE;
                        ahc_qinfifo_requeue_tail(ahc, scb);
@@ -562,7 +562,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
                         * Ensure we have enough time to actually
                         * retrieve the sense.
                         */
-                       ahc_scb_timer_reset(scb, 5 * 1000000);
+                       aic_scb_timer_reset(scb, 5 * 1000000);
                        break;
                }
                default:
@@ -763,7 +763,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
                                        if ((ahc_inb(ahc, SCSISIGI)
                                          & (CDI|MSGI)) != 0)
                                                break;
-                                       ahc_delay(100);
+                                       aic_delay(100);
                                }
                                ahc_outb(ahc, SXFRCTL1,
                                         ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET);
@@ -777,7 +777,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
                                        scb_index = ahc_inb(ahc, SCB_TAG);
                                        scb = ahc_lookup_scb(ahc, scb_index);
                                        if (scb != NULL)
-                                               ahc_set_transaction_status(scb,
+                                               aic_set_transaction_status(scb,
                                                    CAM_UNCOR_PARITY);
                                        ahc_reset_channel(ahc, devinfo.channel, 
                                                          /*init reset*/TRUE);
@@ -815,16 +815,16 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
                ahc_print_path(ahc, scb);
                kprintf("%s seen Data Phase.  Length = %ld.  NumSGs = %d.\n",
                       ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't",
-                      ahc_get_transfer_length(scb), scb->sg_count);
+                      aic_get_transfer_length(scb), scb->sg_count);
                if (scb->sg_count > 0) {
                        for (i = 0; i < scb->sg_count; i++) {
 
                                kprintf("sg[%d] - Addr 0x%x%x : Length %d\n",
                                       i,
-                                      (ahc_le32toh(scb->sg_list[i].len) >> 24
+                                      (aic_le32toh(scb->sg_list[i].len) >> 24
                                        & SG_HIGH_ADDR_BITS),
-                                      ahc_le32toh(scb->sg_list[i].addr),
-                                      ahc_le32toh(scb->sg_list[i].len)
+                                      aic_le32toh(scb->sg_list[i].addr),
+                                      aic_le32toh(scb->sg_list[i].len)
                                       & AHC_SG_LEN_MASK);
                        }
                }
@@ -834,12 +834,12 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
                 */
                ahc_freeze_devq(ahc, scb);
                if ((scb->flags & SCB_SENSE) == 0) {
-                       ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR);
+                       aic_set_transaction_status(scb, CAM_DATA_RUN_ERR);
                } else {
                        scb->flags &= ~SCB_SENSE;
-                       ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
+                       aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
                }
-               ahc_freeze_scb(scb);
+               aic_freeze_scb(scb);
 
                if ((ahc->features & AHC_ULTRA2) != 0) {
                        /*
@@ -1183,7 +1183,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
                         */
                        ahc_scb_devinfo(ahc, &devinfo, scb);
                        ahc_force_renegotiation(ahc, &devinfo);
-                       ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
+                       aic_set_transaction_status(scb, CAM_SEL_TIMEOUT);
                        ahc_freeze_devq(ahc, scb);
                }
                ahc_outb(ahc, CLRINT, CLRSCSIINT);
@@ -1265,7 +1265,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
                                                  CAM_LUN_WILDCARD,
                                                  SCB_LIST_NULL,
                                                  ROLE_INITIATOR)) {
-                                       ahc_set_transaction_status(scb, CAM_REQ_CMP);
+                                       aic_set_transaction_status(scb, CAM_REQ_CMP);
                                }
 #endif
                                ahc_compile_devinfo(&devinfo,
@@ -1477,7 +1477,7 @@ ahc_clear_critical_section(struct ahc_softc *ahc)
                }
                ahc_outb(ahc, HCNTRL, ahc->unpause);
                while (!ahc_is_paused(ahc))
-                       ahc_delay(200);
+                       aic_delay(200);
        }
        if (stepping) {
                ahc_outb(ahc, SIMODE0, simode0);
@@ -1525,18 +1525,18 @@ ahc_print_scb(struct scb *scb)
        for (i = 0; i < sizeof(hscb->shared_data.cdb); i++)
                kprintf("%#02x", hscb->shared_data.cdb[i]);
        kprintf("        dataptr:%#x datacnt:%#x sgptr:%#x tag:%#x\n",
-               ahc_le32toh(hscb->dataptr),
-               ahc_le32toh(hscb->datacnt),
-               ahc_le32toh(hscb->sgptr),
+               aic_le32toh(hscb->dataptr),
+               aic_le32toh(hscb->datacnt),
+               aic_le32toh(hscb->sgptr),
                hscb->tag);
        if (scb->sg_count > 0) {
                for (i = 0; i < scb->sg_count; i++) {
                        kprintf("sg[%d] - Addr 0x%x%x : Length %d\n",
                               i,
-                              (ahc_le32toh(scb->sg_list[i].len) >> 24
+                              (aic_le32toh(scb->sg_list[i].len) >> 24
                                & SG_HIGH_ADDR_BITS),
-                              ahc_le32toh(scb->sg_list[i].addr),
-                              ahc_le32toh(scb->sg_list[i].len));
+                              aic_le32toh(scb->sg_list[i].addr),
+                              aic_le32toh(scb->sg_list[i].len));
                }
        }
 }
@@ -2567,7 +2567,7 @@ ahc_handle_proto_violation(struct ahc_softc *ahc)
                kprintf("No SCB found during protocol violation\n");
                goto proto_violation_reset;
        } else {
-               ahc_set_transaction_status(scb, CAM_SEQUENCE_FAIL);
+               aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL);
                if ((seq_flags & NO_CDB_SENT) != 0) {
                        ahc_print_path(ahc, scb);
                        kprintf("No or incomplete CDB sent to device.\n");
@@ -3505,7 +3505,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
                ahc_outb(ahc, SCB_CONTROL,
                         ahc_inb(ahc, SCB_CONTROL) & mask);
                scb->hscb->control &= mask;
-               ahc_set_transaction_tag(scb, /*enabled*/FALSE,
+               aic_set_transaction_tag(scb, /*enabled*/FALSE,
                                        /*type*/MSG_SIMPLE_TASK);
                ahc_outb(ahc, MSG_OUT, MSG_IDENTIFYFLAG);
                ahc_assert_atn(ahc);
@@ -3562,7 +3562,7 @@ ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
         * Perhaps add datadir to some spare bits in the hscb?
         */
        if ((ahc_inb(ahc, SEQ_FLAGS) & DPHASE) == 0
-        || ahc_get_transfer_dir(scb) != CAM_DIR_IN) {
+        || aic_get_transfer_dir(scb) != CAM_DIR_IN) {
                /*
                 * Ignore the message if we haven't
                 * seen an appropriate data phase yet.
@@ -3618,18 +3618,18 @@ ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
                         * to load so we must go back one.
                         */
                        sg--;
-                       sglen = ahc_le32toh(sg->len) & AHC_SG_LEN_MASK;
+                       sglen = aic_le32toh(sg->len) & AHC_SG_LEN_MASK;
                        if (sg != scb->sg_list
                         && sglen < (data_cnt & AHC_SG_LEN_MASK)) {
 
                                sg--;
-                               sglen = ahc_le32toh(sg->len);
+                               sglen = aic_le32toh(sg->len);
                                /*
                                 * Preserve High Address and SG_LIST bits
                                 * while setting the count to 1.
                                 */
                                data_cnt = 1 | (sglen & (~AHC_SG_LEN_MASK));
-                               data_addr = ahc_le32toh(sg->addr)
+                               data_addr = aic_le32toh(sg->addr)
                                          + (sglen & AHC_SG_LEN_MASK) - 1;
 
                                /*
@@ -3685,8 +3685,8 @@ ahc_reinitialize_dataptrs(struct ahc_softc *ahc)
              | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT + 1) << 8)
              | ahc_inb(ahc, SCB_RESIDUAL_DATACNT);
 
-       dataptr = ahc_le32toh(sg->addr)
-               + (ahc_le32toh(sg->len) & AHC_SG_LEN_MASK)
+       dataptr = aic_le32toh(sg->addr)
+               + (aic_le32toh(sg->len) & AHC_SG_LEN_MASK)
                - resid;
        if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
                u_int dscommand1;
@@ -3694,7 +3694,7 @@ ahc_reinitialize_dataptrs(struct ahc_softc *ahc)
                dscommand1 = ahc_inb(ahc, DSCOMMAND1);
                ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0);
                ahc_outb(ahc, HADDR,
-                        (ahc_le32toh(sg->len) >> 24) & SG_HIGH_ADDR_BITS);
+                        (aic_le32toh(sg->len) >> 24) & SG_HIGH_ADDR_BITS);
                ahc_outb(ahc, DSCOMMAND1, dscommand1);
        }
        ahc_outb(ahc, HADDR + 3, dataptr >> 24);
@@ -3860,7 +3860,7 @@ ahc_softc_insert(struct ahc_softc *ahc)
 {
        struct ahc_softc *list_ahc;
 
-#if AHC_PCI_CONFIG > 0
+#if AIC_PCI_CONFIG > 0
        /*
         * Second Function PCI devices need to inherit some
         * settings from function 0.
@@ -3868,17 +3868,17 @@ ahc_softc_insert(struct ahc_softc *ahc)
        if ((ahc->chip & AHC_BUS_MASK) == AHC_PCI
         && (ahc->features & AHC_MULTI_FUNC) != 0) {
                TAILQ_FOREACH(list_ahc, &ahc_tailq, links) {
-                       ahc_dev_softc_t list_pci;
-                       ahc_dev_softc_t pci;
+                       aic_dev_softc_t list_pci;
+                       aic_dev_softc_t pci;
 
                        list_pci = list_ahc->dev_softc;
                        pci = ahc->dev_softc;
-                       if (ahc_get_pci_slot(list_pci) == ahc_get_pci_slot(pci)
-                        && ahc_get_pci_bus(list_pci) == ahc_get_pci_bus(pci)) {
+                       if (aic_get_pci_slot(list_pci) == aic_get_pci_slot(pci)
+                        && aic_get_pci_bus(list_pci) == aic_get_pci_bus(pci)) {
                                struct ahc_softc *master;
                                struct ahc_softc *slave;
 
-                               if (ahc_get_pci_function(list_pci) == 0) {
+                               if (aic_get_pci_function(list_pci) == 0) {
                                        master = list_ahc;
                                        slave = ahc;
                                } else {
@@ -3946,27 +3946,27 @@ ahc_free(struct ahc_softc *ahc)
 {
        int i;
 
+       ahc_terminate_recovery_thread(ahc);
        switch (ahc->init_level) {
        default:
        case 5:
                ahc_shutdown(ahc);
-               TAILQ_REMOVE(&ahc_tailq, ahc, links);
                /* FALLTHROUGH */
        case 4:
-               ahc_dmamap_unload(ahc, ahc->shared_data_dmat,
+               aic_dmamap_unload(ahc, ahc->shared_data_dmat,
                                  ahc->shared_data_dmamap);
                /* FALLTHROUGH */
        case 3:
-               ahc_dmamem_free(ahc, ahc->shared_data_dmat, ahc->qoutfifo,
+               aic_dmamem_free(ahc, ahc->shared_data_dmat, ahc->qoutfifo,
                                ahc->shared_data_dmamap);
-               ahc_dmamap_destroy(ahc, ahc->shared_data_dmat,
+               aic_dmamap_destroy(ahc, ahc->shared_data_dmat,
                                   ahc->shared_data_dmamap);
                /* FALLTHROUGH */
        case 2:
-               ahc_dma_tag_destroy(ahc, ahc->shared_data_dmat);
+               aic_dma_tag_destroy(ahc, ahc->shared_data_dmat);
        case 1:
 #ifndef __linux__
-               ahc_dma_tag_destroy(ahc, ahc->buffer_dmat);
+               aic_dma_tag_destroy(ahc, ahc->buffer_dmat);
 #endif
                break;
        case 0:
@@ -3974,7 +3974,7 @@ ahc_free(struct ahc_softc *ahc)
        }
 
 #ifndef __linux__
-       ahc_dma_tag_destroy(ahc, ahc->parent_dmat);
+       aic_dma_tag_destroy(ahc, ahc->parent_dmat);
 #endif
        ahc_platform_free(ahc);
        ahc_fini_scbdata(ahc);
@@ -4056,14 +4056,6 @@ ahc_reset(struct ahc_softc *ahc, int reinit)
         * to disturb the integrity of the bus.
         */
        ahc_pause(ahc);
-       if ((ahc_inb(ahc, HCNTRL) & CHIPRST) != 0) {
-               /*
-                * The chip has not been initialized since
-                * PCI/EISA/VLB bus reset.  Don't trust
-                * "left over BIOS data".
-                */
-               ahc->flags |= AHC_NO_BIOS_INIT;
-       }
        sxfrctl1_b = 0;
        if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) {
                u_int sblkctl;
@@ -4089,7 +4081,7 @@ ahc_reset(struct ahc_softc *ahc, int reinit)
         */
        wait = 1000;
        do {
-               ahc_delay(1000);
+               aic_delay(1000);
        } while (--wait && !(ahc_inb(ahc, HCNTRL) & CHIPRSTACK));
 
        if (wait == 0) {
@@ -4265,7 +4257,7 @@ ahc_init_scbdata(struct ahc_softc *ahc)
         */
 
        /* DMA tag for our hardware scb structures */
-       if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1,
+       if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1,
                               /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
                               /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
                               /*highaddr*/BUS_SPACE_MAXADDR,
@@ -4280,7 +4272,7 @@ ahc_init_scbdata(struct ahc_softc *ahc)
        scb_data->init_level++;
 
        /* Allocation for our hscbs */
-       if (ahc_dmamem_alloc(ahc, scb_data->hscb_dmat,
+       if (aic_dmamem_alloc(ahc, scb_data->hscb_dmat,
                             (void **)&scb_data->hscbs,
                             BUS_DMA_NOWAIT, &scb_data->hscb_dmamap) != 0) {
                goto error_exit;
@@ -4289,7 +4281,7 @@ ahc_init_scbdata(struct ahc_softc *ahc)
        scb_data->init_level++;
 
        /* And permanently map them */
-       ahc_dmamap_load(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap,
+       aic_dmamap_load(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap,
                        scb_data->hscbs,
                        AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb),
                        ahc_dmamap_cb, &scb_data->hscb_busaddr, /*flags*/0);
@@ -4297,7 +4289,7 @@ ahc_init_scbdata(struct ahc_softc *ahc)
        scb_data->init_level++;
 
        /* DMA tag for our sense buffers */
-       if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1,
+       if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1,
                               /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
                               /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
                               /*highaddr*/BUS_SPACE_MAXADDR,
@@ -4312,7 +4304,7 @@ ahc_init_scbdata(struct ahc_softc *ahc)
        scb_data->init_level++;
 
        /* Allocate them */
-       if (ahc_dmamem_alloc(ahc, scb_data->sense_dmat,
+       if (aic_dmamem_alloc(ahc, scb_data->sense_dmat,
                             (void **)&scb_data->sense,
                             BUS_DMA_NOWAIT, &scb_data->sense_dmamap) != 0) {
                goto error_exit;
@@ -4321,7 +4313,7 @@ ahc_init_scbdata(struct ahc_softc *ahc)
        scb_data->init_level++;
 
        /* And permanently map them */
-       ahc_dmamap_load(ahc, scb_data->sense_dmat, scb_data->sense_dmamap,
+       aic_dmamap_load(ahc, scb_data->sense_dmat, scb_data->sense_dmamap,
                        scb_data->sense,
                        AHC_SCB_MAX_ALLOC * sizeof(struct scsi_sense_data),
                        ahc_dmamap_cb, &scb_data->sense_busaddr, /*flags*/0);
@@ -4329,7 +4321,7 @@ ahc_init_scbdata(struct ahc_softc *ahc)
        scb_data->init_level++;
 
        /* DMA tag for our S/G structures.  We allocate in page sized chunks */
-       if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/8,
+       if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/8,
                               /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
                               /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
                               /*highaddr*/BUS_SPACE_MAXADDR,
@@ -4386,35 +4378,35 @@ ahc_fini_scbdata(struct ahc_softc *ahc)
 
                while ((sg_map = SLIST_FIRST(&scb_data->sg_maps))!= NULL) {
                        SLIST_REMOVE_HEAD(&scb_data->sg_maps, links);
-                       ahc_dmamap_unload(ahc, scb_data->sg_dmat,
+                       aic_dmamap_unload(ahc, scb_data->sg_dmat,
                                          sg_map->sg_dmamap);
-                       ahc_dmamem_free(ahc, scb_data->sg_dmat,
+                       aic_dmamem_free(ahc, scb_data->sg_dmat,
                                        sg_map->sg_vaddr,
                                        sg_map->sg_dmamap);
                        kfree(sg_map, M_DEVBUF);
                }
-               ahc_dma_tag_destroy(ahc, scb_data->sg_dmat);
+               aic_dma_tag_destroy(ahc, scb_data->sg_dmat);
        }
        case 6:
-               ahc_dmamap_unload(ahc, scb_data->sense_dmat,
+               aic_dmamap_unload(ahc, scb_data->sense_dmat,
                                  scb_data->sense_dmamap);
        case 5:
-               ahc_dmamem_free(ahc, scb_data->sense_dmat, scb_data->sense,
+               aic_dmamem_free(ahc, scb_data->sense_dmat, scb_data->sense,
                                scb_data->sense_dmamap);
-               ahc_dmamap_destroy(ahc, scb_data->sense_dmat,
+               aic_dmamap_destroy(ahc, scb_data->sense_dmat,
                                   scb_data->sense_dmamap);
        case 4:
-               ahc_dma_tag_destroy(ahc, scb_data->sense_dmat);
+               aic_dma_tag_destroy(ahc, scb_data->sense_dmat);
        case 3:
-               ahc_dmamap_unload(ahc, scb_data->hscb_dmat,
+               aic_dmamap_unload(ahc, scb_data->hscb_dmat,
                                  scb_data->hscb_dmamap);
        case 2:
-               ahc_dmamem_free(ahc, scb_data->hscb_dmat, scb_data->hscbs,
+               aic_dmamem_free(ahc, scb_data->hscb_dmat, scb_data->hscbs,
                                scb_data->hscb_dmamap);
-               ahc_dmamap_destroy(ahc, scb_data->hscb_dmat,
+               aic_dmamap_destroy(ahc, scb_data->hscb_dmat,
                                   scb_data->hscb_dmamap);
        case 1:
-               ahc_dma_tag_destroy(ahc, scb_data->hscb_dmat);
+               aic_dma_tag_destroy(ahc, scb_data->hscb_dmat);
                break;
        case 0:
                break;
@@ -4444,7 +4436,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc)
        sg_map = kmalloc(sizeof(*sg_map), M_DEVBUF, M_INTWAIT);
 
        /* Allocate S/G space for the next batch of SCBS */
-       if (ahc_dmamem_alloc(ahc, scb_data->sg_dmat,
+       if (aic_dmamem_alloc(ahc, scb_data->sg_dmat,
                             (void **)&sg_map->sg_vaddr,
                             BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) {
                kfree(sg_map, M_DEVBUF);
@@ -4453,7 +4445,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc)
 
        SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links);
 
-       ahc_dmamap_load(ahc, scb_data->sg_dmat, sg_map->sg_dmamap,
+       aic_dmamap_load(ahc, scb_data->sg_dmat, sg_map->sg_dmamap,
                        sg_map->sg_vaddr, PAGE_SIZE, ahc_dmamap_cb,
                        &sg_map->sg_physaddr, /*flags*/0);
 
@@ -4477,9 +4469,9 @@ ahc_alloc_scbs(struct ahc_softc *ahc)
                 */
                next_scb->sg_list_phys = physaddr + sizeof(struct ahc_dma_seg);
                next_scb->ahc_softc = ahc;
-               next_scb->flags = SCB_FREE;
+               next_scb->flags = SCB_FLAG_NONE;
 #ifndef __linux__
-               error = ahc_dmamap_create(ahc, ahc->buffer_dmat, /*flags*/0,
+               error = aic_dmamap_create(ahc, ahc->buffer_dmat, /*flags*/0,
                                          &next_scb->dmamap);
                if (error != 0)
                        break;
@@ -4715,7 +4707,7 @@ ahc_chip_init(struct ahc_softc *ahc)
                for (wait = 5000;
                     (ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait;
                     wait--)
-                       ahc_delay(100);
+                       aic_delay(100);
        }
        ahc_restart(ahc);
        return (0);
@@ -4728,6 +4720,7 @@ int
 ahc_init(struct ahc_softc *ahc)
 {
        int      max_targ;
+       int      error;
        u_int    i;
        u_int    scsi_conf;
        u_int    ultraenb;
@@ -4785,7 +4778,7 @@ ahc_init(struct ahc_softc *ahc)
 
 #ifndef __linux__
        /* DMA tag for mapping buffers into device visible space. */
-       if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1,
+       if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1,
                               /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
                               /*lowaddr*/ahc->flags & AHC_39BIT_ADDRESSING
                                        ? (bus_addr_t)0x7FFFFFFFFFULL
@@ -4816,7 +4809,7 @@ ahc_init(struct ahc_softc *ahc)
        if ((ahc->features & AHC_TARGETMODE) != 0)
                driver_data_size += AHC_TMODE_CMDS * sizeof(struct target_cmd)
                                 + /*DMA WideOdd Bug Buffer*/1;
-       if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1,
+       if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1,
                               /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,
                               /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
                               /*highaddr*/BUS_SPACE_MAXADDR,
@@ -4831,7 +4824,7 @@ ahc_init(struct ahc_softc *ahc)
        ahc->init_level++;
 
        /* Allocation of driver data */
-       if (ahc_dmamem_alloc(ahc, ahc->shared_data_dmat,
+       if (aic_dmamem_alloc(ahc, ahc->shared_data_dmat,
                             (void **)&ahc->qoutfifo,
                             BUS_DMA_NOWAIT, &ahc->shared_data_dmamap) != 0) {
                return (ENOMEM);
@@ -4840,7 +4833,7 @@ ahc_init(struct ahc_softc *ahc)
        ahc->init_level++;
 
        /* And permanently map it in */
-       ahc_dmamap_load(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
+       aic_dmamap_load(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
                        ahc->qoutfifo, driver_data_size, ahc_dmamap_cb,
                        &ahc->shared_data_busaddr, /*flags*/0);
 
@@ -4883,6 +4876,13 @@ ahc_init(struct ahc_softc *ahc)
                }
        }
 
+       /*
+        * Fire up a recovery thread for this controller.
+        */
+       error = ahc_spawn_recovery_thread(ahc);
+       if (error != 0)
+               return (error);
+
        if (ahc->scb_data->maxhscbs < AHC_SCB_MAX_ALLOC) {
                ahc->flags |= AHC_PAGESCBS;
        } else {
@@ -5080,8 +5080,14 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc)
        ahc->flags |= AHC_ALL_INTERRUPTS;
        paused = FALSE;
        do {
-               if (paused)
+               if (paused) {
                        ahc_unpause(ahc);
+                       /*
+                        * Give the sequencer some time to service
+                        * any active selections.
+                        */
+                       aic_delay(200);
+               }
                ahc_intr(ahc);
                ahc_pause(ahc);
                paused = TRUE;
@@ -5367,12 +5373,12 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
                                cam_status ostat;
                                cam_status cstat;
 
-                               ostat = ahc_get_transaction_status(scb);
+                               ostat = aic_get_transaction_status(scb);
                                if (ostat == CAM_REQ_INPROG)
-                                       ahc_set_transaction_status(scb, status);
-                               cstat = ahc_get_transaction_status(scb);
+                                       aic_set_transaction_status(scb, status);
+                               cstat = aic_get_transaction_status(scb);
                                if (cstat != CAM_REQ_CMP)
-                                       ahc_freeze_scb(scb);
+                                       aic_freeze_scb(scb);
                                if ((scb->flags & SCB_ACTIVE) == 0)
                                        kprintf("Inactive SCB in qinfifo\n");
                                ahc_done(ahc, scb);
@@ -5479,13 +5485,13 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
                                cam_status ostat;
                                cam_status cstat;
 
-                               ostat = ahc_get_transaction_status(scb);
+                               ostat = aic_get_transaction_status(scb);
                                if (ostat == CAM_REQ_INPROG)
-                                       ahc_set_transaction_status(scb,
+                                       aic_set_transaction_status(scb,
                                                                   status);
-                               cstat = ahc_get_transaction_status(scb);
+                               cstat = aic_get_transaction_status(scb);
                                if (cstat != CAM_REQ_CMP)
-                                       ahc_freeze_scb(scb);
+                                       aic_freeze_scb(scb);
                                if ((scb->flags & SCB_ACTIVE) == 0)
                                        kprintf("Inactive SCB in Waiting List\n");
                                ahc_done(ahc, scb);
@@ -5507,7 +5513,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
        }
        ahc_outb(ahc, SCBPTR, curscbptr);
 
-       found += ahc_search_untagged_queues(ahc, /*ahc_io_ctx_t*/NULL, target,
+       found += ahc_search_untagged_queues(ahc, /*aic_io_ctx_t*/NULL, target,
                                            channel, lun, status, action);
 
        if (action == SEARCH_COMPLETE)
@@ -5516,7 +5522,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
 }
 
 int
-ahc_search_untagged_queues(struct ahc_softc *ahc, ahc_io_ctx_t ctx,
+ahc_search_untagged_queues(struct ahc_softc *ahc, aic_io_ctx_t ctx,
                           int target, char channel, int lun, uint32_t status,
                           ahc_search_action action)
 {
@@ -5587,12 +5593,12 @@ ahc_search_untagged_queues(struct ahc_softc *ahc, ahc_io_ctx_t ctx,
                                cam_status ostat;
                                cam_status cstat;
 
-                               ostat = ahc_get_transaction_status(scb);
+                               ostat = aic_get_transaction_status(scb);
                                if (ostat == CAM_REQ_INPROG)
-                                       ahc_set_transaction_status(scb, status);
-                               cstat = ahc_get_transaction_status(scb);
+                                       aic_set_transaction_status(scb, status);
+                               cstat = aic_get_transaction_status(scb);
                                if (cstat != CAM_REQ_CMP)
-                                       ahc_freeze_scb(scb);
+                                       aic_freeze_scb(scb);
                                if ((scb->flags & SCB_ACTIVE) == 0)
                                        kprintf("Inactive SCB in untaggedQ\n");
                                ahc_done(ahc, scb);
@@ -5891,11 +5897,11 @@ ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
                if (ahc_match_scb(ahc, scbp, target, channel, lun, tag, role)) {
                        cam_status ostat;
 
-                       ostat = ahc_get_transaction_status(scbp);
+                       ostat = aic_get_transaction_status(scbp);
                        if (ostat == CAM_REQ_INPROG)
-                               ahc_set_transaction_status(scbp, status);
-                       if (ahc_get_transaction_status(scbp) != CAM_REQ_CMP)
-                               ahc_freeze_scb(scbp);
+                               aic_set_transaction_status(scbp, status);
+                       if (aic_get_transaction_status(scbp) != CAM_REQ_CMP)
+                               aic_freeze_scb(scbp);
                        if ((scbp->flags & SCB_ACTIVE) == 0)
                                kprintf("Inactive SCB on pending list\n");
                        ahc_done(ahc, scbp);
@@ -5917,7 +5923,7 @@ ahc_reset_current_bus(struct ahc_softc *ahc)
        scsiseq = ahc_inb(ahc, SCSISEQ);
        ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO);
        ahc_flush_device_writes(ahc);
-       ahc_delay(AHC_BUSRESET_DELAY);
+       aic_delay(AHC_BUSRESET_DELAY);
        /* Turn off the bus reset */
        ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO);
 
@@ -6124,7 +6130,7 @@ ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb)
         */
 
        hscb = scb->hscb;
-       sgptr = ahc_le32toh(hscb->sgptr);
+       sgptr = aic_le32toh(hscb->sgptr);
        if ((sgptr & SG_RESID_VALID) == 0)
                /* Case 1 */
                return;
@@ -6135,10 +6141,10 @@ ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb)
                return;
 
        spkt = &hscb->shared_data.status;
-       resid_sgptr = ahc_le32toh(spkt->residual_sg_ptr);
+       resid_sgptr = aic_le32toh(spkt->residual_sg_ptr);
        if ((sgptr & SG_FULL_RESID) != 0) {
                /* Case 3 */
-               resid = ahc_get_transfer_length(scb);
+               resid = aic_get_transfer_length(scb);
        } else if ((resid_sgptr & SG_LIST_NULL) != 0) {
                /* Case 4 */
                return;
@@ -6151,7 +6157,7 @@ ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb)
                 * Remainder of the SG where the transfer
                 * stopped.  
                 */
-               resid = ahc_le32toh(spkt->residual_datacnt) & AHC_SG_LEN_MASK;
+               resid = aic_le32toh(spkt->residual_datacnt) & AHC_SG_LEN_MASK;
                sg = ahc_sg_bus_to_virt(scb, resid_sgptr & SG_PTR_MASK);
 
                /* The residual sg_ptr always points to the next sg */
@@ -6162,15 +6168,15 @@ ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb)
                 * SG segments that are after the SG where
                 * the transfer stopped.
                 */
-               while ((ahc_le32toh(sg->len) & AHC_DMA_LAST_SEG) == 0) {
+               while ((aic_le32toh(sg->len) & AHC_DMA_LAST_SEG) == 0) {
                        sg++;
-                       resid += ahc_le32toh(sg->len) & AHC_SG_LEN_MASK;
+                       resid += aic_le32toh(sg->len) & AHC_SG_LEN_MASK;
                }
        }
        if ((scb->flags & SCB_SENSE) == 0)
-               ahc_set_residual(scb, resid);
+               aic_set_residual(scb, resid);
        else
-               ahc_set_sense_residual(scb, resid);
+               aic_set_sense_residual(scb, resid);
 
 #ifdef AHC_DEBUG
        if ((ahc_debug & AHC_SHOW_MISC) != 0) {
@@ -6447,7 +6453,7 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts)
        /*
         * The firmware is always compiled into a little endian format.
         */
-       instr.integer = ahc_le32toh(*(uint32_t*)&seqprog[instrptr * 4]);
+       instr.integer = aic_le32toh(*(uint32_t*)&seqprog[instrptr * 4]);
 
        fmt1_ins = &instr.format1;
        fmt3_ins = NULL;
@@ -6552,7 +6558,7 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts)
                        }
                }
                /* The sequencer is a little endian cpu */
-               instr.integer = ahc_htole32(instr.integer);
+               instr.integer = aic_htole32(instr.integer);
                ahc_outsb(ahc, SEQRAM, instr.bytes, 4);
                break;
        default:
@@ -6792,6 +6798,323 @@ ahc_dump_card_state(struct ahc_softc *ahc)
                ahc_unpause(ahc);
 }
 
+/*************************** Timeout Handling *********************************/
+void
+ahc_timeout(struct scb *scb)
+{
+       struct ahc_softc *ahc;
+
+       ahc = scb->ahc_softc;
+       if ((scb->flags & SCB_ACTIVE) != 0) {
+               if ((scb->flags & SCB_TIMEDOUT) == 0) {
+                       LIST_INSERT_HEAD(&ahc->timedout_scbs, scb,
+                                        timedout_links);
+                       scb->flags |= SCB_TIMEDOUT;
+               }
+               ahc_wakeup_recovery_thread(ahc);
+       }
+}
+
+/*
+ * ahc_recover_commands determines if any of the commands that have currently
+ * timedout are the root cause for this timeout.  Innocent commands are given
+ * a new timeout while we wait for the command executing on the bus to timeout.
+ * This routine is invoked from a thread context so we are allowed to sleep.
+ * Our lock is not held on entry.
+ */
+void
+ahc_recover_commands(struct ahc_softc *ahc)
+{
+       struct  scb *scb;
+       int     found;
+       int     restart_needed;
+       u_int   last_phase;
+
+       ahc_lock();
+
+       /*
+        * Pause the controller and manually flush any
+        * commands that have just completed but that our
+        * interrupt handler has yet to see.
+        */
+       ahc_pause_and_flushwork(ahc);
+
+       if (LIST_EMPTY(&ahc->timedout_scbs) != 0) {
+               /*
+                * The timedout commands have already
+                * completed.  This typically means
+                * that either the timeout value was on
+                * the hairy edge of what the device
+                * requires or - more likely - interrupts
+                * are not happening.
+                */
+               kprintf("%s: Timedout SCBs already complete. "
+                      "Interrupts may not be functioning.\n", ahc_name(ahc));
+               ahc_unpause(ahc);
+               ahc_unlock();
+               return;
+       }
+
+       restart_needed = 0;
+       kprintf("%s: Recovery Initiated\n", ahc_name(ahc));
+       ahc_dump_card_state(ahc);
+
+       last_phase = ahc_inb(ahc, LASTPHASE);
+       while ((scb = LIST_FIRST(&ahc->timedout_scbs)) != NULL) {
+               u_int   active_scb_index;
+               u_int   saved_scbptr;
+               int     target;
+               int     lun;
+               int     i;
+               char    channel;
+
+               target = SCB_GET_TARGET(ahc, scb);
+               channel = SCB_GET_CHANNEL(ahc, scb);
+               lun = SCB_GET_LUN(scb);
+
+               ahc_print_path(ahc, scb);
+               kprintf("SCB 0x%x - timed out\n", scb->hscb->tag);
+               if (scb->sg_count > 0) {
+                       for (i = 0; i < scb->sg_count; i++) {
+                               kprintf("sg[%d] - Addr 0x%x : Length %d\n",
+                                      i,
+                                      scb->sg_list[i].addr,
+                                      scb->sg_list[i].len & AHC_SG_LEN_MASK);
+                       }
+               }
+               if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) {
+                       /*
+                        * Been down this road before.
+                        * Do a full bus reset.
+                        */
+                       aic_set_transaction_status(scb, CAM_CMD_TIMEOUT);
+bus_reset:
+                       found = ahc_reset_channel(ahc, channel,
+                                                 /*Initiate Reset*/TRUE);
+                       kprintf("%s: Issued Channel %c Bus Reset. "
+                              "%d SCBs aborted\n", ahc_name(ahc), channel,
+                              found);
+                       continue;
+               }
+
+               /*
+                * Remove the command from the timedout list in
+                * preparation for requeing it.
+                */
+               LIST_REMOVE(scb, timedout_links);
+               scb->flags &= ~SCB_TIMEDOUT;
+
+               /*
+                * If we are a target, transition to bus free and report
+                * the timeout.
+                * 
+                * The target/initiator that is holding up the bus may not
+                * be the same as the one that triggered this timeout
+                * (different commands have different timeout lengths).
+                * If the bus is idle and we are actiing as the initiator
+                * for this request, queue a BDR message to the timed out
+                * target.  Otherwise, if the timed out transaction is
+                * active:
+                *   Initiator transaction:
+                *      Stuff the message buffer with a BDR message and assert
+                *      ATN in the hopes that the target will let go of the bus
+                *      and go to the mesgout phase.  If this fails, we'll
+                *      get another timeout 2 seconds later which will attempt
+                *      a bus reset.
+                *
+                *   Target transaction:
+                *      Transition to BUS FREE and report the error.
+                *      It's good to be the target!
+                */
+               saved_scbptr = ahc_inb(ahc, SCBPTR);
+               active_scb_index = ahc_inb(ahc, SCB_TAG);
+
+               if ((ahc_inb(ahc, SEQ_FLAGS) & NOT_IDENTIFIED) == 0
+                 && (active_scb_index < ahc->scb_data->numscbs)) {
+                       struct scb *active_scb;
+
+                       /*
+                        * If the active SCB is not us, assume that
+                        * the active SCB has a longer timeout than
+                        * the timedout SCB, and wait for the active
+                        * SCB to timeout.
+                        */ 
+                       active_scb = ahc_lookup_scb(ahc, active_scb_index);
+                       if (active_scb != scb) {
+                               u_int   newtimeout;
+
+                               ahc_print_path(ahc, scb);
+                               kprintf("Other SCB Timeout%s",
+                                      (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0
+                                      ? " again\n" : "\n");
+                               scb->flags |= SCB_OTHERTCL_TIMEOUT;
+                               newtimeout =
+                                   MAX(aic_get_timeout(active_scb),
+                                       aic_get_timeout(scb));
+                               aic_scb_timer_reset(scb, newtimeout);
+                               continue;
+                       } 
+
+                       /* It's us */
+                       if ((scb->flags & SCB_TARGET_SCB) != 0) {
+
+                               /*
+                                * Send back any queued up transactions
+                                * and properly record the error condition.
+                                */
+                               ahc_abort_scbs(ahc, SCB_GET_TARGET(ahc, scb),
+                                              SCB_GET_CHANNEL(ahc, scb),
+                                              SCB_GET_LUN(scb),
+                                              scb->hscb->tag,
+                                              ROLE_TARGET,
+                                              CAM_CMD_TIMEOUT);
+
+                               /* Will clear us from the bus */
+                               restart_needed = 1;
+                               break;
+                       }
+
+                       ahc_set_recoveryscb(ahc, active_scb);
+                       ahc_outb(ahc, MSG_OUT, HOST_MSG);
+                       ahc_outb(ahc, SCSISIGO, last_phase|ATNO);
+                       ahc_print_path(ahc, active_scb);
+                       kprintf("BDR message in message buffer\n");
+                       active_scb->flags |= SCB_DEVICE_RESET;
+                       aic_scb_timer_reset(scb, 2 * 1000000);
+               } else if (last_phase != P_BUSFREE
+                       && (ahc_inb(ahc, SSTAT1) & REQINIT) == 0) {
+                       /*
+                        * SCB is not identified, there
+                        * is no pending REQ, and the sequencer
+                        * has not seen a busfree.  Looks like
+                        * a stuck connection waiting to
+                        * go busfree.  Reset the bus.
+                        */
+                       kprintf("%s: Connection stuck awaiting busfree or "
+                              "Identify Msg.\n", ahc_name(ahc));
+                       goto bus_reset;
+               } else {
+                       int      disconnected;
+
+                       if (last_phase != P_BUSFREE
+                        && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) {
+                               /* Hung target selection.  Goto busfree */
+                               kprintf("%s: Hung target selection\n",
+                                      ahc_name(ahc));
+                               restart_needed = 1;
+                               break;
+                       }
+
+                       /* XXX Shouldn't panic.  Just punt instead? */
+                       if ((scb->flags & SCB_TARGET_SCB) != 0)
+                               panic("Timed-out target SCB but bus idle");
+
+                       if (ahc_search_qinfifo(ahc, target, channel, lun,
+                                              scb->hscb->tag, ROLE_INITIATOR,
+                                              /*status*/0, SEARCH_COUNT) > 0) {
+                               disconnected = FALSE;
+                       } else {
+                               disconnected = TRUE;
+                       }
+
+                       if (disconnected) {
+
+                               ahc_set_recoveryscb(ahc, scb);
+                               /*
+                                * Actually re-queue this SCB in an attempt
+                                * to select the device before it reconnects.
+                                * In either case (selection or reselection),
+                                * we will now issue a target reset to the
+                                * timed-out device.
+                                *
+                                * Set the MK_MESSAGE control bit indicating
+                                * that we desire to send a message.  We
+                                * also set the disconnected flag since
+                                * in the paging case there is no guarantee
+                                * that our SCB control byte matches the
+                                * version on the card.  We don't want the
+                                * sequencer to abort the command thinking
+                                * an unsolicited reselection occurred.
+                                */
+                               scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
+                               scb->flags |= SCB_DEVICE_RESET;
+
+                               /*
+                                * Remove any cached copy of this SCB in the
+                                * disconnected list in preparation for the
+                                * queuing of our abort SCB.  We use the
+                                * same element in the SCB, SCB_NEXT, for
+                                * both the qinfifo and the disconnected list.
+                                */
+                               ahc_search_disc_list(ahc, target, channel,
+                                                    lun, scb->hscb->tag,
+                                                    /*stop_on_first*/TRUE,
+                                                    /*remove*/TRUE,
+                                                    /*save_state*/FALSE);
+
+                               /*
+                                * In the non-paging case, the sequencer will
+                                * never re-reference the in-core SCB.
+                                * To make sure we are notified during
+                                * reslection, set the MK_MESSAGE flag in
+                                * the card's copy of the SCB.
+                                */
+                               if ((ahc->flags & AHC_PAGESCBS) == 0) {
+                                       ahc_outb(ahc, SCBPTR, scb->hscb->tag);
+                                       ahc_outb(ahc, SCB_CONTROL,
+                                                ahc_inb(ahc, SCB_CONTROL)
+                                               | MK_MESSAGE);
+                               }
+
+                               /*
+                                * Clear out any entries in the QINFIFO first
+                                * so we are the next SCB for this target
+                                * to run.
+                                */
+                               ahc_search_qinfifo(ahc,
+                                                  SCB_GET_TARGET(ahc, scb),
+                                                  channel, SCB_GET_LUN(scb),
+                                                  SCB_LIST_NULL,
+                                                  ROLE_INITIATOR,
+                                                  CAM_REQUEUE_REQ,
+                                                  SEARCH_COMPLETE);
+                               ahc_print_path(ahc, scb);
+                               kprintf("Queuing a BDR SCB\n");
+                               ahc_qinfifo_requeue_tail(ahc, scb);
+                               ahc_outb(ahc, SCBPTR, saved_scbptr);
+                               aic_scb_timer_reset(scb, 2 * 1000000);
+                       } else {
+                               /* Go "immediatly" to the bus reset */
+                               /* This shouldn't happen */
+                               ahc_set_recoveryscb(ahc, scb);
+                               ahc_print_path(ahc, scb);
+                               kprintf("SCB %d: Immediate reset.  "
+                                       "Flags = 0x%x\n", scb->hscb->tag,
+                                       scb->flags);
+                               goto bus_reset;
+                       }
+               }
+               break;
+       }
+       
+       /*
+        * Any remaining SCBs were not the "culprit", so remove
+        * them from the timeout list.  The timer for these commands
+        * will be reset once the recovery SCB completes.
+        */
+       while ((scb = LIST_FIRST(&ahc->timedout_scbs)) != NULL) {
+
+               LIST_REMOVE(scb, timedout_links);
+               scb->flags &= ~SCB_TIMEDOUT;
+       }
+
+       if (restart_needed)
+               ahc_restart(ahc);
+       else
+               ahc_unpause(ahc);
+       ahc_unlock();
+}
+
 /************************* Target Mode ****************************************/
 #ifdef AHC_TARGET_MODE
 cam_status
@@ -7261,7 +7584,7 @@ ahc_run_tqinfifo(struct ahc_softc *ahc, int paused)
                        break;
 
                cmd->cmd_valid = 0;
-               ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
+               aic_dmamap_sync(ahc, ahc->shared_data_dmat,
                                ahc->shared_data_dmamap,
                                ahc_targetcmd_offset(ahc, ahc->tqinfifonext),
                                sizeof(struct target_cmd),
@@ -7398,7 +7721,7 @@ ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd)
                       initiator, target, lun, ahc->pending_device);
 #endif
                ahc->pending_device = lstate;
-               ahc_freeze_ccb((union ccb *)atio);
+               aic_freeze_ccb((union ccb *)atio);
                atio->ccb_h.flags |= CAM_DIS_DISCONNECT;
        }
        xpt_done((union ccb*)atio);
index 86918b9..fb7ca64 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/aic7xxx.h#79 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#85 $
  *
- * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.h,v 1.16.2.16 2003/06/10 03:26:08 gibbs Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/aic7xxx.h,v 1.2 2003/06/17 04:28:22 dillon Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.h,v 1.50 2003/12/17 00:02:09 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/aic7xxx.h,v 1.3 2007/07/06 00:01:16 pavalos Exp $
  */
 
 #ifndef _AIC7XXX_H_
@@ -244,7 +244,7 @@ typedef enum {
         */
        AHC_AIC7850_FE  = AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA,
        AHC_AIC7860_FE  = AHC_AIC7850_FE,
-       AHC_AIC7870_FE  = AHC_TARGETMODE,
+       AHC_AIC7870_FE  = AHC_TARGETMODE|AHC_AUTOPAUSE,
        AHC_AIC7880_FE  = AHC_AIC7870_FE|AHC_ULTRA,
        /*
         * Although we have space for both the initiator and
@@ -367,7 +367,8 @@ typedef enum {
        AHC_SCB_CONFIG_USED   = 0x4000000, /* No SEEPROM but SCB2 had info. */
        AHC_NO_BIOS_INIT      = 0x8000000, /* No BIOS left over settings. */
        AHC_DISABLE_PCI_PERR  = 0x10000000,
-       AHC_HAS_TERM_LOGIC    = 0x20000000
+       AHC_HAS_TERM_LOGIC    = 0x20000000,
+       AHC_SHUTDOWN_RECOVERY = 0x40000000 /* Terminate recovery thread. */
 } ahc_flag;
 
 /************************* Hardware  SCB Definition ***************************/
@@ -412,6 +413,7 @@ struct target_data {
        uint8_t  initiator_tag;         /* Initiator's transaction tag */
 };
 
+#define MAX_CDB_LEN 16
 struct hardware_scb {
 /*0*/  union {
                /*
@@ -531,7 +533,7 @@ struct sg_map_node {
  * The current state of this SCB.
  */
 typedef enum {
-       SCB_FREE                = 0x0000,
+       SCB_FLAG_NONE           = 0x0000,
        SCB_OTHERTCL_TIMEOUT    = 0x0002,/*
                                          * Another device was active
                                          * during the first timeout for
@@ -561,12 +563,16 @@ typedef enum {
                                          * to report the error.
                                          */
        SCB_TARGET_SCB          = 0x2000,
-       SCB_SILENT              = 0x4000 /*
+       SCB_SILENT              = 0x4000,/*
                                          * Be quiet about transmission type
                                          * errors.  They are expected and we
                                          * don't want to upset the user.  This
                                          * flag is typically used during DV.
                                          */
+       SCB_TIMEDOUT            = 0x8000 /*
+                                         * SCB has timed out and is on the
+                                         * timedout list.
+                                         */
 } scb_flag;
 
 struct scb {
@@ -576,7 +582,8 @@ struct scb {
                TAILQ_ENTRY(scb)  tqe;
        } links;
        LIST_ENTRY(scb)           pending_links;
-       ahc_io_ctx_t              io_ctx;
+       LIST_ENTRY(scb)           timedout_links;
+       aic_io_ctx_t              io_ctx;
        struct ahc_softc         *ahc_softc;
        scb_flag                  flags;
 #ifndef __linux__
@@ -929,6 +936,11 @@ struct ahc_softc {
         */
        LIST_HEAD(, scb)          pending_scbs;
 
+       /*
+        * SCBs whose timeout routine has been called.
+        */
+       LIST_HEAD(, scb)          timedout_scbs;
+
        /*
         * Counting lock for deferring the release of additional
         * untagged transactions from the untagged_queues.  When
@@ -959,7 +971,7 @@ struct ahc_softc {
        /*
         * Platform specific device information.
         */
-       ahc_dev_softc_t           dev_softc;
+       aic_dev_softc_t           dev_softc;
 
        /*
         * Bus specific device information.
@@ -1136,6 +1148,9 @@ struct ahc_devinfo {
 };
 
 /****************************** PCI Structures ********************************/
+#define        AHC_PCI_IOADDR  PCIR_BAR(0)     /* I/O Address */
+#define        AHC_PCI_MEMADDR PCIR_BAR(1)     /* Mem I/O Address */
+
 typedef int (ahc_device_setup_t)(struct ahc_softc *);
 
 struct ahc_pci_identity {
@@ -1168,7 +1183,7 @@ void                      ahc_busy_tcl(struct ahc_softc *ahc,
                                     u_int tcl, u_int busyid);
 
 /***************************** PCI Front End *********************************/
-struct ahc_pci_identity        *ahc_find_pci_device(ahc_dev_softc_t);
+struct ahc_pci_identity        *ahc_find_pci_device(aic_dev_softc_t);
 int                     ahc_pci_config(struct ahc_softc *,
                                        struct ahc_pci_identity *);
 int                     ahc_pci_test_register_access(struct ahc_softc *);
@@ -1232,7 +1247,7 @@ int                       ahc_search_qinfifo(struct ahc_softc *ahc, int target,
                                           role_t role, uint32_t status,
                                           ahc_search_action action);
 int                    ahc_search_untagged_queues(struct ahc_softc *ahc,
-                                                  ahc_io_ctx_t ctx,
+                                                  aic_io_ctx_t ctx,
                                                   int target, char channel,
                                                   int lun, uint32_t status,
                                                   ahc_search_action action);
@@ -1249,6 +1264,8 @@ int                       ahc_abort_scbs(struct ahc_softc *ahc, int target,
 void                   ahc_restart(struct ahc_softc *ahc);
 void                   ahc_calc_residual(struct ahc_softc *ahc,
                                          struct scb *scb);
+void                   ahc_timeout(struct scb *scb);
+void                   ahc_recover_commands(struct ahc_softc *ahc);
 /*************************** Utility Functions ********************************/
 struct ahc_phase_table_entry*
                        ahc_lookup_phase_entry(int phase);
index 1cbbb3f..4563865 100644 (file)
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.reg,v 1.20.2.14 2003/06/10 03:26:08 gibbs Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/aic7xxx.reg,v 1.2 2003/06/17 04:28:22 dillon Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.reg,v 1.46 2003/12/17 00:02:09 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/aic7xxx.reg,v 1.3 2007/07/06 00:01:16 pavalos Exp $
  */
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $"
 
 /*
  * This file is processed by the aic7xxx_asm utility for use in assembling
@@ -1307,7 +1307,6 @@ scratch_ram {
         */
        MWI_RESIDUAL {
                size            1
-               alias   TARG_IMMEDIATE_SCB
        }
        /*
         * SCBID of the next SCB to be started by the controller.
@@ -1462,6 +1461,7 @@ scratch_ram {
         */
        LAST_MSG {
                size            1
+               alias   TARG_IMMEDIATE_SCB
        }
 
        /*
index bc579f6..5c0733b 100644 (file)
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.seq,v 1.94.2.19 2003/06/10 03:26:08 gibbs Exp $
- * $DragonFly: src/sys/dev/disk/aic7xxx/aic7xxx.seq,v 1.2 2003/06/17 04:28:22 dillon Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.seq,v 1.126 2003/12/17 00:02:09 gibbs Exp $
+ * $DragonFly: src/sys/dev/disk/aic7xxx/aic7xxx.seq,v 1.3 2007/07/06 00:01:16 pavalos Exp $
  */
 
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $"
 PATCH_ARG_LIST = "struct ahc_softc *ahc"
 PREFIX = "ahc_"
 
@@ -680,6 +680,7 @@ await_busfree:
                clr     SCSIBUSL;       /* Prevent bit leakage durint SELTO */
        }
        and     SXFRCTL0, ~SPIOEN;
+       mvi     SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;
        test    SSTAT1,REQINIT|BUSFREE  jz .;
        test    SSTAT1, BUSFREE jnz poll_for_work;
        mvi     MISSED_BUSFREE call set_seqint;
@@ -1098,7 +1099,7 @@ ultra2_dmahalt:
                test    SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg;
                if ((ahc->flags & AHC_TARGETROLE) != 0) {
                        test    SSTAT0, TARGET jz dma_last_sg;
-                       if ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0) {
+                       if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0) {
                                test    DMAPARAMS, DIRECTION jz dma_mid_sg;
                        }
                }