 25-akpm/Documentation/scsi/aic79xx.txt                   |  314 ++-
 25-akpm/Documentation/scsi/aic7xxx.txt                   |  141 +
 25-akpm/drivers/scsi/aic7xxx/Kconfig.aic7xxx             |    8 
 25-akpm/drivers/scsi/aic7xxx/Makefile                    |   24 
 25-akpm/drivers/scsi/aic7xxx/aic7770.c                   |   17 
 25-akpm/drivers/scsi/aic7xxx/aic7770_osm.c               |  215 +-
 25-akpm/drivers/scsi/aic7xxx/aic79xx.h                   |   86 
 25-akpm/drivers/scsi/aic7xxx/aic79xx.reg                 |   61 
 25-akpm/drivers/scsi/aic7xxx/aic79xx.seq                 |  152 +
 25-akpm/drivers/scsi/aic7xxx/aic79xx_core.c              | 1420 ++++++++++----
 25-akpm/drivers/scsi/aic7xxx/aic79xx_inline.h            |   82 
 25-akpm/drivers/scsi/aic7xxx/aic79xx_osm.c               | 1425 +++++++--------
 25-akpm/drivers/scsi/aic7xxx/aic79xx_osm.h               |  904 ---------
 25-akpm/drivers/scsi/aic7xxx/aic79xx_osm_pci.c           |  128 -
 25-akpm/drivers/scsi/aic7xxx/aic79xx_pci.c               |  168 -
 25-akpm/drivers/scsi/aic7xxx/aic79xx_proc.c              |   25 
 25-akpm/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped       |  135 -
 25-akpm/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped |  129 -
 25-akpm/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped       |  737 +++----
 25-akpm/drivers/scsi/aic7xxx/aic7xxx.h                   |   43 
 25-akpm/drivers/scsi/aic7xxx/aic7xxx.reg                 |    4 
 25-akpm/drivers/scsi/aic7xxx/aic7xxx.seq                 |    5 
 25-akpm/drivers/scsi/aic7xxx/aic7xxx_93cx6.c             |   38 
 25-akpm/drivers/scsi/aic7xxx/aic7xxx_core.c              |  653 +++++-
 25-akpm/drivers/scsi/aic7xxx/aic7xxx_inline.h            |   26 
 25-akpm/drivers/scsi/aic7xxx/aic7xxx_osm.c               | 1393 +++++++-------
 25-akpm/drivers/scsi/aic7xxx/aic7xxx_osm.h               |  873 ---------
 25-akpm/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c           |  122 -
 25-akpm/drivers/scsi/aic7xxx/aic7xxx_pci.c               |  184 +
 25-akpm/drivers/scsi/aic7xxx/aic7xxx_proc.c              |   32 
 25-akpm/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped       |    6 
 25-akpm/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped |   22 
 25-akpm/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped       |  933 ++++-----
 25-akpm/drivers/scsi/aic7xxx/aicasm/Makefile             |    8 
 25-akpm/drivers/scsi/aic7xxx/aicasm/aicasm.c             |   23 
 25-akpm/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l  |    3 
 25-akpm/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l        |   16 
 25-akpm/drivers/scsi/aic7xxx/aiclib.c                    |  343 +++
 25-akpm/drivers/scsi/aic7xxx/aiclib.h                    | 1281 +++++++++++++
 25-akpm/drivers/scsi/aic7xxx/aiclib_pci.c                |   79 
 40 files changed, 6933 insertions(+), 5325 deletions(-)

diff -puN Documentation/scsi/aic79xx.txt~aic7xxx-aic79xx-update Documentation/scsi/aic79xx.txt
--- 25/Documentation/scsi/aic79xx.txt~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/Documentation/scsi/aic79xx.txt	Wed Dec 24 12:15:38 2003
@@ -1,5 +1,5 @@
 ====================================================================
-=             Adaptec Ultra320 Family Manager Set v1.3.0           =
+=             Adaptec Ultra320 Family Manager Set v2.0.5           =
 =                                                                  =
 =                            README for                            =
 =                    The Linux Operating System                    =
@@ -19,57 +19,274 @@ The following information is available i
    The following Adaptec SCSI Host Adapters are supported by this 
    driver set. 
 
-   Ultra320 Adapters         Description
+   Ultra320 ASIC              Description
    ----------------------------------------------------------------
-   Adaptec SCSI Card 39320   Dual Channel 64-bit PCI-X 133MHz to
-                             Ultra320 SCSI Card (one external 
-                             68-pin, two internal 68-pin)
-   Adaptec SCSI Card 39320D  Dual Channel 64-bit PCI-X 133MHz to
-                             Ultra320 SCSI Card (two external VHDC
-                             and one internal 68-pin)
-   Adaptec SCSI Card 39320D  Dual Channel 64-bit PCI-X 133MHz to
-                             Ultra320 SCSI Card (two external VHDC
-                             and one internal 68-pin) based on the
-                             AIC-7902B ASIC
-   Adaptec SCSI Card 29320   Single Channel 64-bit PCI-X 133MHz to
-                             Ultra320 SCSI Card (one external 
-                             68-pin, two internal 68-pin, one
-                             internal 50-pin)
-   Adaptec SCSI Card 29320LP Single Channel 64-bit Low Profile
-                             PCI-X 133MHz to Ultra320 SCSI Card
-                             (One external VHDC, one internal
-                             68-pin)
-   AIC-7901A                 Single Channel 64-bit PCI-X 133MHz to 
-                             Ultra320 SCSI ASIC
-   AIC-7902A4                Dual Channel 64-bit PCI-X 133MHz to 
-                             Ultra320 SCSI ASIC
-   AIC-7902B                 Dual Channel 64-bit PCI-X 133MHz to
-                             Ultra320 SCSI ASIC
-
+   AIC-7901A                  Single Channel 64-bit PCI-X 133MHz to 
+                              Ultra320 SCSI ASIC
+   AIC-7901B                  Single Channel 64-bit PCI-X 133MHz to 
+                              Ultra320 SCSI ASIC with Retained Training
+   AIC-7902A4                 Dual Channel 64-bit PCI-X 133MHz to 
+                              Ultra320 SCSI ASIC
+   AIC-7902B                  Dual Channel 64-bit PCI-X 133MHz to
+                              Ultra320 SCSI ASIC with Retained Training
+
+   Ultra320 Adapters          Description                              ASIC
+   --------------------------------------------------------------------------
+   Adaptec SCSI Card 39320    Dual Channel 64-bit PCI-X 133MHz to   7902A4/7902B
+                              Ultra320 SCSI Card (one external 
+                              68-pin, two internal 68-pin)
+   Adaptec SCSI Card 39320A   Dual Channel 64-bit PCI-X 133MHz to      7902B
+                              Ultra320 SCSI Card (one external 
+                              68-pin, two internal 68-pin)
+   Adaptec SCSI Card 39320D   Dual Channel 64-bit PCI-X 133MHz to      7902A4
+                              Ultra320 SCSI Card (two external VHDC
+                              and one internal 68-pin)
+   Adaptec SCSI Card 39320D   Dual Channel 64-bit PCI-X 133MHz to      7902A4
+                              Ultra320 SCSI Card (two external VHDC
+                              and one internal 68-pin) based on the
+                              AIC-7902B ASIC
+   Adaptec SCSI Card 29320    Single Channel 64-bit PCI-X 133MHz to    7901A
+                              Ultra320 SCSI Card (one external 
+                              68-pin, two internal 68-pin, one
+                              internal 50-pin)
+   Adaptec SCSI Card 29320A   Single Channel 64-bit PCI-X 133MHz to    7901B
+                              Ultra320 SCSI Card (one external 
+                              68-pin, two internal 68-pin, one
+                              internal 50-pin)
+   Adaptec SCSI Card 29320LP  Single Channel 64-bit Low Profile        7901A
+                              PCI-X 133MHz to Ultra320 SCSI Card
+                              (One external VHDC, one internal
+                              68-pin)
+   Adaptec SCSI Card 29320ALP Single Channel 64-bit Low Profile        7901B
+                              PCI-X 133MHz to Ultra320 SCSI Card
+                              (One external VHDC, one internal
+                              68-pin)
 2. Version History
 
-   (V1.3.0, January 2003) Full regression testing for all U320 products
-   completed.
-
-   (V1.3.0 ALPHA, November 2002) Initial Alpha release.
-   Added abort and target/lun reset error recovery handler and
-   interrupt coalessing.
-
-   (V1.2.0, November 2002) Added support for Domain Validation and
-   Hewlett-Packard version of the 39320D and AIC-7902 adapters.
-   Support for previous adapters has not been fully tested and should
-   only be used at the customer's own risk.
-
-   (V1.1.1, September 2002) Added support for the Linux 2.5.X kernel series
-
-   (V1.1.0, August 2002) Added support for four additional SCSI
-   products: ASC-39320, ASC-29320, ASC-29320LP, AIC-7901.
-
-   (V1.1, August 2002) Added support for four additional SCSI
-   products: ASC-39320, ASC-29320, ASC-29320LP, AIC-7901.
+   2.0.5 (December 22nd, 2003)
+        - Correct a bug preventing the driver from renegotiating
+          during auto-request operations when a check condition
+          occurred for a zero length command.
+        - Sniff sense information returned by targets for unit
+          attention errors that may indicate that the device has
+          been changed.  If we see such status for non Domain
+          Validation related commands, start a DV scan for the
+          target.  In the past, DV would only occur for hot-plugged
+          devices if no target had been previously probed for a
+          particular ID.  This change guarantees that the DV process
+          will occur even if the user swaps devices without any
+          interveining I/O to tell us that a device has gone missing.
+          The old behavior, among other things, would fail to spin up
+          drives that were hot-plugged since the Linux mid-layer
+          will only spin-up drives on initial attach.
+        - Correct several issues in the rundown of the good status
+          FIFO during error recovery.  The typical failure scenario
+          evidenced by this defect was the loss of several commands
+          under high load when	 several queue full conditions occured
+          back to back.
+
+   2.0.4 (November 6th, 2003)
+        - Support the 2.6.0-test9 kernel
+        - Fix rare deadlock caused by using del_timer_sync from within
+          a timer handler.
+
+   2.0.3 (October 21st, 2003)
+        - On 7902A4 hardware, use the slow slew rate for transfer
+          rates slower than U320.  This behavior matches the Windows
+          driver.
+        - Fix some issues with the ahd_flush_qoutfifo() routine.
+        - Add a delay in the loop waiting for selection activity
+          to cease.  Otherwise we may exhaust the loop counter too
+          quickly on fast machines.
+        - Return to processing bad status completions through the
+          qoutfifo.  This reduces the amount of time the controller
+          is paused for these kinds of errors.
+        - Move additional common routines to the aiclib OSM library
+          to reduce code duplication.
+        - Leave removal of softcs from the global list of softcs to
+          the OSM.  This allows us to avoid holding the list_lock during
+          device destruction.
+        - Enforce a bus settle delay for bus resets that the
+          driver initiates.
+        - Fall back to basic DV for U160 devices that lack an
+          echo buffer.
+
+   2.0.2 (September 4th, 2003)
+        - Move additional common routines to the aiclib OSM library
+          to reduce code duplication.
+        - Avoid an inadvertant reset of the controller during the
+          memory mapped I/O test should the controller be left in
+          the reset state prior to driver initialization.  On some
+          systems, this extra reset resulted in a system hang due
+          to a chip access that occurred too soon after reset.
+        - Correct an endian bug in ahd_swap_with_next_hscb.  This
+          corrects strong-arm support.
+        - Reset the bus for transactions that timeout waiting for
+          the bus to go free after a disconnect or command complete
+          message.
+
+   2.0.1 (August 26th, 2003)
+        - Add magic sysrq handler that causes a card dump to be output
+          to the console for each controller.
+        - Avoid waking the mid-layer's error recovery handler during
+          timeout recovery by returning DID_ERROR instead of DID_TIMEOUT
+          for timed-out commands that have been aborted.
+        - Move additional common routines to the aiclib OSM library
+          to reduce code duplication.
+
+   2.0.0 (August 20th, 2003)
+        - Remove MMAPIO definition and allow memory mapped
+          I/O for any platform that supports PCI.
+        - Avoid clearing ENBUSFREE during single stepping to avoid
+          spurious "unexpected busfree while idle" messages.
+        - Correct deadlock in ahd_run_qoutfifo() processing.
+        - Optimize support for the 7901B.
+        - Correct a few cases where an explicit flush of pending
+          register writes was required to ensure acuracy in delays.
+        - Correct problems in manually flushing completed commands
+          on the controller.  The FIFOs are now flushed to ensure
+          that completed commands that are still draining to the
+          host are completed correctly.
+        - Correct incomplete CDB delivery detection on the 790XB.
+        - Ignore the cmd->underflow field since userland applications
+          using the legacy command pass-thru interface do not set
+          it correctly.  Honoring this field led to spurious errors
+          when users used the "scsi_unique_id" program.
+        - Perform timeout recovery within the driver instead of relying
+          on the Linux SCSI mid-layer to perform this function.  The
+          mid-layer does not know the full state of the SCSI bus and
+          is therefore prone to looping for several minutes to effect
+          recovery.  The new scheme recovers within 15 seconds of the
+          failure.
+        - Correct support for manual termination settings.
+        - Increase maximum wait time for serial eeprom writes allowing
+          writes to function correctly.
+
+   1.3.12 (August 11, 2003)
+        - Implement new error recovery thread that supercedes the existing
+          Linux SCSI error recovery code.
+        - Fix termination logic for 29320ALP.
+        - Fix SEEPROM delay to compensate for write ops taking longer.
+
+   1.3.11 (July 11, 2003)
+        - Fix several deadlock issues.
+        - Add 29320ALP and 39320B Id's.
+
+   1.3.10 (June 3rd, 2003)
+        - Align the SCB_TAG field on a 16byte boundary.  This avoids
+          SCB corruption on some PCI-33 busses.
+        - Correct non-zero luns on Rev B. hardware.
+        - Update for change in 2.5.X SCSI proc FS interface.
+        - When negotiation async via an 8bit WDTR message, send
+          an SDTR with an offset of 0 to be sure the target
+          knows we are async.  This works around a firmware defect
+          in the Quantum Atlas 10K.
+        - Implement controller susupend and resume.
+        - Clear PCI error state during driver attach so that we
+          don't disable memory mapped I/O due to a stray write
+          by some other driver probe that occurred before we
+          claimed the controller.
+
+   1.3.9 (May 22nd, 2003)
+        - Fix compiler errors.
+        - Remove S/G splitting for segments that cross a 4GB boundary.
+          This is guaranteed not to happen in Linux.
+        - Add support for scsi_report_device_reset() found in
+          2.5.X kernels.
+        - Add 7901B support.
+        - Simplify handling of the packtized lun Rev A workaround.
+        - Correct and simplify handling of the ignore wide residue
+          message.  The previous code would fail to report a residual
+          if the transaction data length was even and we received
+          an IWR message.
+
+   1.3.8 (April 29th, 2003)
+        - Fix types accessed via the command line interface code.
+        - Perform a few firmware optimizations.
+        - Fix "Unexpected PKT busfree" errors.
+        - Use a sequencer interrupt to notify the host of
+          commands with bad status.  We defer the notification
+          until there are no outstanding selections to ensure
+          that the host is interrupted for as short a time as
+          possible.
+        - Remove pre-2.2.X support.
+        - Add support for new 2.5.X interrupt API.
+        - Correct big-endian architecture support.
+
+   1.3.7 (April 16th, 2003)
+        - Use del_timer_sync() to ensure that no timeouts
+          are pending during controller shutdown.
+        - For pre-2.5.X kernels, carefully adjust our segment
+          list size to avoid SCSI malloc pool fragmentation.
+        - Cleanup channel display in our /proc output.
+        - Workaround duplicate device entries in the mid-layer
+          devlice list during add-single-device.
+
+   1.3.6 (March 28th, 2003)
+        - Correct a double free in the Domain Validation code.
+        - Correct a reference to free'ed memory during controller
+          shutdown.
+        - Reset the bus on an SE->LVD change.  This is required
+          to reset our transcievers.
+
+   1.3.5 (March 24th, 2003)
+        - Fix a few register window mode bugs.
+        - Include read streaming in the PPR flags we display in
+          diagnostics as well as /proc.
+        - Add PCI hot plug support for 2.5.X kernels.
+        - Correct default precompensation value for RevA hardware.
+        - Fix Domain Validation thread shutdown.
+        - Add a firmware workaround to make the LED blink
+          brighter during packetized operations on the H2A4.
+        - Correct /proc display of user read streaming settings.
+        - Simplify driver locking by releasing the io_request_lock
+          upon driver entry from the mid-layer.
+        - Cleanup command line parsing and move much of this code
+          to aiclib.
+
+   1.3.4 (February 28th, 2003)
+        - Correct a race condition in our error recovery handler.
+        - Allow Test Unit Ready commands to take a full 5 seconds
+          during Domain Validation.
+
+   1.3.2 (February 19th, 2003)
+        - Correct a Rev B. regression due to the GEM318
+          compatibility fix included in 1.3.1.
+          
+   1.3.1 (February 11th, 2003)
+        - Add support for the 39320A.
+        - Improve recovery for certain PCI-X errors.
+        - Fix handling of LQ/DATA/LQ/DATA for the
+          same write transaction that can occur without
+          interveining training.
+        - Correct compatibility issues with the GEM318
+          enclosure services device.
+        - Correct data corruption issue that occurred under
+          high tag depth write loads.
+        - Adapt to a change in the 2.5.X daemonize() API.
+        - Correct a "Missing case in ahd_handle_scsiint" panic.
+
+   1.3.0 (January 21st, 2003)
+        - Full regression testing for all U320 products completed.
+        - Added abort and target/lun reset error recovery handler and
+          interrupt coalessing.
+
+   1.2.0 (November 14th, 2002)
+        - Added support for Domain Validation
+        - Add support for the Hewlett-Packard version of the 39320D
+          and AIC-7902 adapters.
+        Support for previous adapters has not been fully tested and should
+        only be used at the customer's own risk.
+
+   1.1.1 (September 24th, 2002)
+        - Added support for the Linux 2.5.X kernel series
+
+   1.1.0 (September 17th, 2002)
+        - Added support for four additional SCSI products:
+          ASC-39320, ASC-29320, ASC-29320LP, AIC-7901.
 
-   (V1.0, May 2002) This is the initial release of the 
-   Ultra320 FMS.  The following is a list of supported features:
+   1.0.0 (May 30th, 2002)
+        - Initial driver release.
 
    2.1. Software/Hardware Features
         - Support for the SPI-4 "Ultra320" standard:
@@ -82,6 +299,7 @@ The following information is available i
           supported)
         - Support for the PCI-X standard up to 133MHz
         - Support for the PCI v2.2 standard
+	- Domain Validation
 
    2.2. Operating System Support:
         - Redhat Linux 7.2, 7.3, 8.0, Advanced Server 2.1
diff -puN Documentation/scsi/aic7xxx.txt~aic7xxx-aic79xx-update Documentation/scsi/aic7xxx.txt
--- 25/Documentation/scsi/aic7xxx.txt~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/Documentation/scsi/aic7xxx.txt	Wed Dec 24 12:15:38 2003
@@ -1,5 +1,5 @@
 ====================================================================
-=    Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v6.2.28   =
+=    Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v6.3.4    =
 =                            README for                            =
 =                     The Linux Operating System                   =
 ====================================================================
@@ -132,26 +132,127 @@ The following information is available i
 
 2. Version History
 
-        6.2.34 - Fix locking regression instroduced in 6.2.29 that
-                 could cuase a lock order reversal between the io_request_lock
-                 and our per-softc lock.  This was only possible on RH9,
-                 SuSE, and kernel.org 2.4.X kernels.
-
-        6.2.33 - Dynamically disable PCI parity error reporting after
-		 10 errors are reported to the user.  These errors are
-		 the result of some other device issuing PCI transactions
-		 with bad parity.  Once the user has been informed of the
-		 problem, continuing to report the errors just degrades
-		 our performance.
-
-        6.2.32 - Dynamically sized S/G lists to avoid SCSI malloc
-		 pool fragmentation and SCSI mid-layer deadlock.
-
-        6.2.28 - Domain Validation Fixes
-                 PCI parity error disable
-                 Enhanced Memory Mapped I/O probe
+   6.3.4 (December 22nd, 2003)
+        - Provide a better description string for the 2915/30LP.
+        - Sniff sense information returned by targets for unit
+          attention errors that may indicate that the device has
+          been changed.  If we see such status for non Domain
+          Validation related commands, start a DV scan for the
+          target.  In the past, DV would only occur for hot-plugged
+          devices if no target had been previously probed for a
+          particular ID.  This change guarantees that the DV process
+          will occur even if the user swaps devices without any
+          interveining I/O to tell us that a device has gone missing.
+          The old behavior, among other things, would fail to spin up
+          drives that were hot-plugged since the Linux mid-layer
+          will only spin-up drives on initial attach.
+
+   6.3.3 (November 6th, 2003)
+        - Support the 2.6.0-test9 kernel
+        - Fix rare deadlock caused by using del_timer_sync from within
+          a timer handler.
+
+   6.3.2 (October 28th, 2003)
+        - Enforce a bus settle delay for bus resets that the
+          driver initiates.
+        - Fall back to basic DV for U160 devices that lack an
+          echo buffer.
+        - Correctly detect that left over BIOS data has not
+          been initialized when the CHPRST status bit is set
+          during driver initialization.
+
+   6.3.1 (October 21st, 2003)
+        - Fix a compiler error when building with only EISA or PCI
+          support compiled into the kernel.
+        - Add chained dependencies to both the driver and aicasm Makefiles
+          to avoid problems with parallel builds.
+        - Move additional common routines to the aiclib OSM library
+          to reduce code duplication.
+        - Fix a bug in the testing of the AHC_TMODE_WIDEODD_BUG that
+          could cause target mode operations to hang.
+        - Leave removal of softcs from the global list of softcs to
+          the OSM.  This allows us to avoid holding the list_lock during
+          device destruction.
+
+   6.3.0 (September 8th, 2003)
+        - Move additional common routines to the aiclib OSM library
+          to reduce code duplication.
+        - Bump minor number to reflect change in error recovery strategy.
+
+   6.2.38 (August 31st, 2003)
+        - Avoid an inadvertant reset of the controller during the
+          memory mapped I/O test should the controller be left in
+          the reset state prior to driver initialization.  On some
+          systems, this extra reset resulted in a system hang due
+          to a chip access that occurred too soon after reset.
+        - Move additional common routines to the aiclib OSM library
+          to reduce code duplication.
+        - Add magic sysrq handler that causes a card dump to be output
+          to the console for each controller.
+
+   6.2.37 (August 12th, 2003)
+        - Perform timeout recovery within the driver instead of relying
+          on the Linux SCSI mid-layer to perform this function.  The
+          mid-layer does not know the full state of the SCSI bus and
+          is therefore prone to looping for several minutes to effect
+          recovery.  The new scheme recovers within 15 seconds of the
+          failure.
+        - Support writing 93c56/66 SEEPROM on newer cards.
+	- Avoid clearing ENBUSFREE during single stepping to avoid
+          spurious "unexpected busfree while idle" messages.
+        - Enable the use of the "Auto-Access-Pause" feature on the
+          aic7880 and aic7870 chips.  It was disabled due to an
+          oversight.  Using this feature drastically reduces command
+          delivery latency.
+
+   6.2.36 (June 3rd, 2003)
+        - Correct code that disables PCI parity error checking.
+        - Correct and simplify handling of the ignore wide residue
+          message.  The previous code would fail to report a residual
+          if the transaction data length was even and we received
+          an IWR message.
+        - Add support for the 2.5.X EISA framework.
+        - Update for change in 2.5.X SCSI proc FS interface.
+        - Correct Domain Validation command-line option parsing.
+        - When negotiation async via an 8bit WDTR message, send
+          an SDTR with an offset of 0 to be sure the target
+          knows we are async.  This works around a firmware defect
+          in the Quantum Atlas 10K.
+        - Clear PCI error state during driver attach so that we
+          don't disable memory mapped I/O due to a stray write
+          by some other driver probe that occurred before we
+          claimed the controller.
+
+   6.2.35 (May 14th, 2003)
+        - Fix a few GCC 3.3 compiler warnings.
+        - Correct operation on EISA Twin Channel controller.
+        - Add support for 2.5.X's scsi_report_device_reset().
+
+   6.2.34 (May 5th, 2003)
+        - Fix locking regression instroduced in 6.2.29 that
+          could cuase a lock order reversal between the io_request_lock
+          and our per-softc lock.  This was only possible on RH9,
+          SuSE, and kernel.org 2.4.X kernels.
+
+   6.2.33 (April 30th, 2003)
+        - Dynamically disable PCI parity error reporting after
+          10 errors are reported to the user.  These errors are
+          the result of some other device issuing PCI transactions
+          with bad parity.  Once the user has been informed of the
+          problem, continuing to report the errors just degrades
+          our performance.
+
+   6.2.32 (March 28th, 2003)
+        - Dynamically sized S/G lists to avoid SCSI malloc
+          pool fragmentation and SCSI mid-layer deadlock.
+
+   6.2.28 (January 20th, 2003)
+        - Domain Validation Fixes
+        - Add ability to disable PCI parity error checking.
+        - Enhanced Memory Mapped I/O probe
 
-        6.2.20 - Added Domain Validation
+   6.2.20 (November 7th, 2002)
+        - Added Domain Validation.
 
 3. Command Line Options
 
diff -puN drivers/scsi/aic7xxx/aic7770.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7770.c
--- 25/drivers/scsi/aic7xxx/aic7770.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7770.c	Wed Dec 24 12:15:38 2003
@@ -37,9 +37,7 @@
  * 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#30 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic7770.c#34 $
  */
 
 #ifdef __linux__
@@ -47,6 +45,8 @@
 #include "aic7xxx_inline.h"
 #include "aic7xxx_93cx6.h"
 #else
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 #include <dev/aic7xxx/aic7xxx_osm.h>
 #include <dev/aic7xxx/aic7xxx_inline.h>
 #include <dev/aic7xxx/aic7xxx_93cx6.h>
@@ -67,8 +67,7 @@ static ahc_device_setup_t ahc_aic7770_VL
 static ahc_device_setup_t ahc_aic7770_EISA_setup;;
 static ahc_device_setup_t ahc_aic7770_setup;
 
-
-struct aic7770_identity aic7770_ident_table [] =
+struct aic7770_identity aic7770_ident_table[] =
 {
 	{
 		ID_AHA_274x,
@@ -83,6 +82,12 @@ struct aic7770_identity aic7770_ident_ta
 		ahc_aic7770_VL_setup
 	},
 	{
+		ID_AHA_284x,
+		0xFFFFFFFE,
+		"Adaptec 284X SCSI adapter (BIOS Disabled)",
+		ahc_aic7770_VL_setup
+	},
+	{
 		ID_OLV_274x,
 		0xFFFFFFFF,
 		"Adaptec (Olivetti OEM) 274X SCSI adapter",
@@ -154,7 +159,7 @@ aic7770_config(struct ahc_softc *ahc, st
 	ahc->bus_suspend = aic7770_suspend;
 	ahc->bus_resume = aic7770_resume;
 
-	error = ahc_reset(ahc);
+	error = ahc_reset(ahc, /*reinit*/FALSE);
 	if (error != 0)
 		return (error);
 
diff -puN drivers/scsi/aic7xxx/aic7770_osm.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7770_osm.c
--- 25/drivers/scsi/aic7xxx/aic7770_osm.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7770_osm.c	Wed Dec 24 12:15:38 2003
@@ -1,7 +1,7 @@
 /*
  * Linux driver attachment glue for aic7770 based controllers.
  *
- * Copyright (c) 2000-2001 Adaptec Inc.
+ * Copyright (c) 2000-2003 Adaptec Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,27 +36,90 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7770_osm.c#13 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7770_osm.c#16 $
  */
 
 #include "aic7xxx_osm.h"
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <linux/device.h>
+#include <linux/eisa.h>
+
+#define EISA_MFCTR_CHAR0(ID) (char)(((ID>>26) & 0x1F) | '@')  /* Bits 26-30 */
+#define EISA_MFCTR_CHAR1(ID) (char)(((ID>>21) & 0x1F) | '@')  /* Bits 21-25 */
+#define EISA_MFCTR_CHAR2(ID) (char)(((ID>>16) & 0x1F) | '@')  /* Bits 16-20 */
+#define EISA_PRODUCT_ID(ID)  (short)((ID>>4)  & 0xFFF)        /* Bits  4-15 */
+#define EISA_REVISION_ID(ID) (uint8_t)(ID & 0x0F)             /* Bits  0-3  */
+
+static int aic7770_eisa_dev_probe(struct device *dev);
+static int aic7770_eisa_dev_remove(struct device *dev);
+static struct eisa_driver aic7770_driver = {
+	.driver = {
+		.name   = "aic7xxx",
+		.probe  = aic7770_eisa_dev_probe,
+		.remove = aic7770_eisa_dev_remove,
+	}
+};
+
+typedef  struct device *aic7770_dev_t;
+#else
 #define MINSLOT			1
 #define NUMSLOTS		16
 #define IDOFFSET		0x80
 
-int
-aic7770_linux_probe(Scsi_Host_Template *template)
+typedef void *aic7770_dev_t;
+#endif
+
+static int aic7770_linux_config(struct aic7770_identity *entry,
+				aic7770_dev_t dev, u_int eisaBase);
+
+void
+ahc_linux_eisa_init(void)
 {
-#if defined(__i386__) || defined(__alpha__)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	struct eisa_device_id *eid;
+	struct aic7770_identity *id;
+	int i;
+
+	if (aic7xxx_probe_eisa_vl == 0)
+		return;
+
+	/*
+	 * Linux requires the EISA IDs to be specified in
+	 * the EISA ID string format.  Perform the conversion
+	 * and setup a table with a NUL terminal entry.
+	 */
+	aic7770_driver.id_table = malloc(sizeof(struct eisa_device_id) *
+					 (ahc_num_aic7770_devs + 1),
+					 M_DEVBUF, M_NOWAIT);
+	if (aic7770_driver.id_table == NULL)
+		return;
+
+	for (eid = (struct eisa_device_id *)aic7770_driver.id_table,
+	     id = aic7770_ident_table, i = 0;
+	     i < ahc_num_aic7770_devs; eid++, id++, i++) {
+
+		sprintf(eid->sig, "%c%c%c%03X%01X",
+			EISA_MFCTR_CHAR0(id->full_id),
+			EISA_MFCTR_CHAR1(id->full_id),
+			EISA_MFCTR_CHAR2(id->full_id),
+			EISA_PRODUCT_ID(id->full_id),
+			EISA_REVISION_ID(id->full_id));
+		eid->driver_data = i;
+	}
+	eid->sig[0] = 0;
+
+	eisa_driver_register(&aic7770_driver);
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) */
 	struct aic7770_identity *entry;
-	struct ahc_softc *ahc;
-	int i, slot;
-	int eisaBase;
-	int found;
+	u_int  slot;
+	u_int  eisaBase;
+	u_int  i;
+
+	if (aic7xxx_probe_eisa_vl == 0)
+		return;
 
 	eisaBase = 0x1000 + AHC_EISA_SLOT_OFFSET;
-	found = 0;
 	for (slot = 1; slot < NUMSLOTS; eisaBase+=0x1000, slot++) {
 		uint32_t eisa_id;
 		size_t	 id_size;
@@ -83,45 +146,65 @@ aic7770_linux_probe(Scsi_Host_Template *
 			continue;  /* no EISA card in slot */
 
 		entry = aic7770_find_device(eisa_id);
-		if (entry != NULL) {
-			char	 buf[80];
-			char	*name;
-			int	 error;
-
-			/*
-			 * Allocate a softc for this card and
-			 * set it up for attachment by our
-			 * common detect routine.
-			 */
-			sprintf(buf, "ahc_eisa:%d", slot);
-			name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
-			if (name == NULL)
-				break;
-			strcpy(name, buf);
-			ahc = ahc_alloc(template, name);
-			if (ahc == NULL) {
-				/*
-				 * If we can't allocate this one,
-				 * chances are we won't be able to
-				 * allocate future card structures.
-				 */
-				break;
-			}
-			error = aic7770_config(ahc, entry, eisaBase);
-			if (error != 0) {
-				ahc->bsh.ioport = 0;
-				ahc_free(ahc);
-				continue;
-			}
-			found++;
-		}
+		if (entry != NULL)
+			aic7770_linux_config(entry, NULL, eisaBase);
+	}
+#endif
+}
+
+void
+ahc_linux_eisa_exit(void)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	if (aic7xxx_probe_eisa_vl == 0)
+		return;
+
+	if (aic7770_driver.id_table != NULL) {
+		eisa_driver_unregister(&aic7770_driver);
+		free(aic7770_driver.id_table, M_DEVBUF);
 	}
-	return (found);
-#else
-	return (0);
 #endif
 }
 
+static int
+aic7770_linux_config(struct aic7770_identity *entry, aic7770_dev_t dev,
+		     u_int eisaBase)
+{
+	struct	ahc_softc *ahc;
+	char	buf[80];
+	char   *name;
+	int	error;
+
+	/*
+	 * Allocate a softc for this card and
+	 * set it up for attachment by our
+	 * common detect routine.
+	 */
+	sprintf(buf, "ahc_eisa:%d", eisaBase >> 12);
+	name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
+	if (name == NULL)
+		return (ENOMEM);
+	strcpy(name, buf);
+	ahc = ahc_alloc(&aic7xxx_driver_template, name);
+	if (ahc == NULL) {
+		free(name, M_DEVBUF);
+		return (ENOMEM);
+	}
+	ahc->dev_softc = dev;
+	error = aic7770_config(ahc, entry, eisaBase);
+	if (error != 0) {
+		ahc->bsh.ioport = 0;
+		ahc_free(ahc);
+		return (error);
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	dev->driver_data = (void *)ahc;
+	if (aic7xxx_detect_complete)
+		error = ahc_linux_register_host(ahc, &aic7xxx_driver_template);
+#endif
+	return (error);
+}
+
 int
 aic7770_map_registers(struct ahc_softc *ahc, u_int port)
 {
@@ -129,6 +212,8 @@ aic7770_map_registers(struct ahc_softc *
 	 * Lock out other contenders for our i/o space.
 	 */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+	if (check_region(port, AHC_EISA_IOSIZE) != 0)
+		return (ENOMEM);
 	request_region(port, AHC_EISA_IOSIZE, "aic7xxx");
 #else
 	if (request_region(port, AHC_EISA_IOSIZE, "aic7xxx") == 0)
@@ -155,3 +240,43 @@ aic7770_map_int(struct ahc_softc *ahc, u
 	
 	return (-error);
 }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+static int
+aic7770_eisa_dev_probe(struct device *dev)
+{
+	struct eisa_device *edev;
+
+	edev = to_eisa_device(dev);
+	return (aic7770_linux_config(aic7770_ident_table + edev->id.driver_data,
+				    dev, edev->base_addr+AHC_EISA_SLOT_OFFSET));
+}
+
+static int
+aic7770_eisa_dev_remove(struct device *dev)
+{
+	struct ahc_softc *ahc;
+	u_long l;
+
+	/*
+	 * We should be able to just perform
+	 * the free directly, but check our
+	 * list for extra sanity.
+	 */
+	ahc_list_lock(&l);
+	ahc = ahc_find_softc((struct ahc_softc *)dev->driver_data);
+	if (ahc != NULL) {
+		u_long s;
+
+		TAILQ_REMOVE(&ahc_tailq, ahc, links);
+		ahc_list_unlock(&l);
+		ahc_lock(ahc, &s);
+		ahc_intr_enable(ahc, FALSE);
+		ahc_unlock(ahc, &s);
+		ahc_free(ahc);
+	} else
+		ahc_list_unlock(&l);
+
+	return (0);
+}
+#endif
diff -puN drivers/scsi/aic7xxx/aic79xx_core.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic79xx_core.c
--- 25/drivers/scsi/aic7xxx/aic79xx_core.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic79xx_core.c	Wed Dec 24 12:15:38 2003
@@ -37,9 +37,7 @@
  * 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#194 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#224 $
  */
 
 #ifdef __linux__
@@ -47,6 +45,8 @@
 #include "aic79xx_inline.h"
 #include "aicasm/aicasm_insformat.h"
 #else
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 #include <dev/aic7xxx/aic79xx_osm.h>
 #include <dev/aic7xxx/aic79xx_inline.h>
 #include <dev/aic7xxx/aicasm/aicasm_insformat.h>
@@ -224,6 +224,14 @@ static u_int		ahd_resolve_seqaddr(struct
 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,
+					  struct scb *scb);
+
 #ifdef AHD_TARGET_MODE
 static void		ahd_queue_lstate_event(struct ahd_softc *ahd,
 					       struct ahd_tmode_lstate *lstate,
@@ -328,10 +336,7 @@ ahd_restart(struct ahd_softc *ahd)
 	/* Always allow reselection */
 	ahd_outb(ahd, SCSISEQ1,
 		 ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));
-	/* Ensure that no DMA operations are in progress */
 	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
-	ahd_outb(ahd, SCBHCNT, 0);
-	ahd_outb(ahd, CCSCBCTL, CCSCBRESET);
 	ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
 	ahd_unpause(ahd);
 }
@@ -371,31 +376,119 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd
 	u_int		next_scbid;
 
 	saved_modes = ahd_save_modes(ahd);
-	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
+
+	/*
+	 * 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);
+	while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) {
+		u_int fifo_mode;
+		u_int i;
+		
+		scbid = ahd_inw(ahd, GSFIFO);
+		scb = ahd_lookup_scb(ahd, scbid);
+		if (scb == NULL) {
+			printf("%s: Warning - GSFIFO SCB %d invalid\n",
+			       ahd_name(ahd), scbid);
+			continue;
+		}
+		/*
+		 * Determine if this transaction is still active in
+		 * any FIFO.  If it is, we must flush that FIFO to
+		 * the host before completing the  command.
+		 */
+		fifo_mode = 0;
+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);
+
+			/*
+			 * 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.
+			 */
+			aic_delay(200);
+			goto rescan_fifos;
+		}
+		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
+		ahd_set_scbptr(ahd, scbid);
+		if ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_LIST_NULL) == 0
+		 && ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_FULL_RESID) != 0
+		  || (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR)
+		      & SG_LIST_NULL) != 0)) {
+			u_int comp_head;
+
+			/*
+			 * The transfer completed with a residual.
+			 * Place this SCB on the complete DMA list
+			 * so that we update our in-core copy of the
+			 * SCB before completing the command.
+			 */
+			ahd_outb(ahd, SCB_SCSI_STATUS, 0);
+			ahd_outb(ahd, SCB_SGPTR,
+				 ahd_inb_scbram(ahd, SCB_SGPTR)
+				 | SG_STATUS_VALID);
+			ahd_outw(ahd, SCB_TAG, SCB_GET_TAG(scb));
+			comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
+			ahd_outw(ahd, SCB_NEXT_COMPLETE, comp_head);
+			ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_GET_TAG(scb));
+		} else
+			ahd_complete_scb(ahd, scb);
+	}
+	ahd_set_scbptr(ahd, saved_scbptr);
+
+	/*
+	 * Setup for command channel portion of flush.
+	 */
+	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
 
 	/*
 	 * Wait for any inprogress DMA to complete and clear DMA state
 	 * if this if for an SCB in the qinfifo.
 	 */
-	while ((ccscbctl = ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN)) != 0) {
+	while (((ccscbctl = ahd_inb(ahd, CCSCBCTL)) & (CCARREN|CCSCBEN)) != 0) {
 
 		if ((ccscbctl & (CCSCBDIR|CCARREN)) == (CCSCBDIR|CCARREN)) {
 			if ((ccscbctl & ARRDONE) != 0)
 				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.
+	 * Complete any SCBs that just finished
+	 * being DMA'ed into the qoutfifo.
 	 */
 	ahd_run_qoutfifo(ahd);
 
+	saved_scbptr = ahd_get_scbptr(ahd);
 	/*
 	 * Manually update/complete any completed SCBs that are waiting to be
 	 * DMA'ed back up to the host.
@@ -438,31 +531,272 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd
 		scbid = next_scbid;
 	}
 	ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
-	ahd_set_scbptr(ahd, saved_scbptr);
-
-	/*
-	 * Flush the good status FIFO for compelted packetized commands.
-	 */
-	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
-	while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) {
-		scbid = (ahd_inb(ahd, GSFIFO+1) << 8)
-		      | ahd_inb(ahd, GSFIFO);
-		scb = ahd_lookup_scb(ahd, scbid);
-		if (scb == NULL) {
-			printf("%s: Warning - GSFIFO SCB %d invalid\n",
-			       ahd_name(ahd), scbid);
-			continue;
-		}
-		ahd_complete_scb(ahd, scb);
-	}
 
 	/*
 	 * Restore state.
 	 */
+	ahd_set_scbptr(ahd, saved_scbptr);
 	ahd_restore_modes(ahd, saved_modes);
 	ahd->flags |= AHD_UPDATE_PEND_CMDS;
 }
 
+/*
+ * Determine if an SCB for a packetized transaction
+ * is active in a FIFO.
+ */
+static int
+ahd_scb_active_in_fifo(struct ahd_softc *ahd, struct scb *scb)
+{
+
+	/*
+	 * The FIFO is only active for our transaction if
+	 * the SCBPTR matches the SCB's ID and the firmware
+	 * has installed a handler for the FIFO or we have
+	 * a pending SAVEPTRS or CFG4DATA interrupt.
+	 */
+	if (ahd_get_scbptr(ahd) != SCB_GET_TAG(scb)
+	 || ((ahd_inb(ahd, LONGJMP_ADDR+1) & INVALID_ADDR) != 0
+	  && (ahd_inb(ahd, SEQINTSRC) & (CFG4DATA|SAVEPTRS)) == 0))
+		return (0);
+
+	return (1);
+}
+
+/*
+ * Run a data fifo to completion for a transaction we know
+ * has completed across the SCSI bus (good status has been
+ * received).  We are already set to the correct FIFO mode
+ * on entry to this routine.
+ *
+ * This function attempts to operate exactly as the firmware
+ * would when running this FIFO.  Care must be taken to update
+ * this routine any time the firmware's FIFO algorithm is
+ * changed.
+ */
+static void
+ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
+{
+	u_int seqintsrc;
+
+	seqintsrc = ahd_inb(ahd, SEQINTSRC);
+	if ((seqintsrc & CFG4DATA) != 0) {
+		uint32_t datacnt;
+		uint32_t sgptr;
+
+		/*
+		 * Clear full residual flag.
+		 */
+		sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
+		ahd_outb(ahd, SCB_SGPTR, sgptr);
+
+		/*
+		 * Load datacnt and address.
+		 */
+		datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
+		if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
+			sgptr |= LAST_SEG;
+			ahd_outb(ahd, SG_STATE, 0);
+		} else
+			ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
+		ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
+		ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
+		ahd_outb(ahd, SG_CACHE_PRE, sgptr);
+		ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
+
+		/*
+		 * Initialize Residual Fields.
+		 */
+		ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
+		ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
+
+		/*
+		 * Mark the SCB as having a FIFO in use.
+		 */
+		ahd_outb(ahd, SCB_FIFO_USE_COUNT,
+			 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
+
+		/*
+		 * Install a "fake" handler for this FIFO.
+		 */
+		ahd_outw(ahd, LONGJMP_ADDR, 0);
+
+		/*
+		 * Notify the hardware that we have satisfied
+		 * this sequencer interrupt.
+		 */
+		ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
+	} else if ((seqintsrc & SAVEPTRS) != 0) {
+		uint32_t sgptr;
+		uint32_t resid;
+
+		if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
+			/*
+			 * Snapshot Save Pointers.  All that
+			 * is necessary to clear the snapshot
+			 * is a CLRCHN.
+			 */
+			goto clrchn;
+		}
+
+		/*
+		 * Disable S/G fetch so the DMA engine
+		 * is available to future users.
+		 */
+		if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
+			ahd_outb(ahd, CCSGCTL, 0);
+		ahd_outb(ahd, SG_STATE, 0);
+
+		/*
+		 * Flush the data FIFO.  Strickly only
+		 * necessary for Rev A parts.
+		 */
+		ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
+
+		/*
+		 * Calculate residual.
+		 */
+		sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
+		resid = ahd_inl(ahd, SHCNT);
+		resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
+		ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
+		if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
+			/*
+			 * Must back up to the correct S/G element.
+			 * Typically this just means resetting our
+			 * low byte to the offset in the SG_CACHE,
+			 * but if we wrapped, we have to correct
+			 * the other bytes of the sgptr too.
+			 */
+			if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
+			 && (sgptr & 0x80) == 0)
+				sgptr -= 0x100;
+			sgptr &= ~0xFF;
+			sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
+			       & SG_ADDR_MASK;
+			ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
+			ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
+		} else if ((resid & AHD_SG_LEN_MASK) == 0) {
+			ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
+				 sgptr | SG_LIST_NULL);
+		}
+		/*
+		 * Save Pointers.
+		 */
+		ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
+		ahd_outl(ahd, SCB_DATACNT, resid);
+		ahd_outl(ahd, SCB_SGPTR, sgptr);
+		ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
+		ahd_outb(ahd, SEQIMODE,
+			 ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
+		/*
+		 * If the data is to the SCSI bus, we are
+		 * done, otherwise wait for FIFOEMP.
+		 */
+		if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
+			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;
+
+		/*
+		 * 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
+			 * element to load.
+			 */
+			sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
+			sgptr &= SG_PTR_MASK;
+			if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
+				struct ahd_dma64_seg *sg;
+
+				sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
+				data_addr = sg->addr;
+				data_len = sg->len;
+				sgptr += sizeof(*sg);
+			} else {
+				struct	ahd_dma_seg *sg;
+
+				sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
+				data_addr = sg->len & AHD_SG_HIGH_ADDR_MASK;
+				data_addr <<= 8;
+				data_addr |= sg->addr;
+				data_len = sg->len;
+				sgptr += sizeof(*sg);
+			}
+
+			/*
+			 * Update residual information.
+			 */
+			ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, data_len >> 24);
+			ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
+
+			/*
+			 * Load the S/G.
+			 */
+			if (data_len & AHD_DMA_LAST_SEG) {
+				sgptr |= LAST_SEG;
+				ahd_outb(ahd, SG_STATE, 0);
+			}
+			ahd_outq(ahd, HADDR, data_addr);
+			ahd_outl(ahd, HCNT, data_len & AHD_SG_LEN_MASK);
+			ahd_outb(ahd, SG_CACHE_PRE, sgptr & 0xFF);
+
+			/*
+			 * Advertise the segment to the hardware.
+			 */
+			dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;
+			if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {
+				/*
+				 * Use SCSIENWRDIS so that SCSIEN
+				 * is never modified by this
+				 * operation.
+				 */
+				dfcntrl |= SCSIENWRDIS;
+			}
+			ahd_outb(ahd, DFCNTRL, dfcntrl);
+		}
+	} else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) {
+
+		/*
+		 * Transfer completed to the end of SG list
+		 * and has flushed to the host.
+		 */
+		ahd_outb(ahd, SCB_SGPTR,
+			 ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
+		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);
+	}
+}
+
 void
 ahd_run_qoutfifo(struct ahd_softc *ahd)
 {
@@ -476,7 +810,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) {
@@ -556,26 +890,6 @@ ahd_handle_seqint(struct ahd_softc *ahd,
 		       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 {
-			printf("%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;
@@ -589,7 +903,7 @@ ahd_handle_seqint(struct ahd_softc *ahd,
 			/*
 			 * Somehow need to know if this
 			 * is from a selection or reselection.
-			 * From that, we can termine target
+			 * From that, we can determine target
 			 * ID so we at least have an I_T nexus.
 			 */
 		} else {
@@ -740,11 +1054,11 @@ ahd_handle_seqint(struct ahd_softc *ahd,
 			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
@@ -796,7 +1110,8 @@ ahd_handle_seqint(struct ahd_softc *ahd,
 			 * attempt to complete this bogus SCB.
 			 */
 			ahd_outb(ahd, SCB_CONTROL,
-				 ahd_inb(ahd, SCB_CONTROL) & ~STATUS_RCVD);
+				 ahd_inb_scbram(ahd, SCB_CONTROL)
+				 & ~STATUS_RCVD);
 		}
 		break;
 	}
@@ -991,7 +1306,7 @@ ahd_handle_seqint(struct ahd_softc *ahd,
 			       "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
@@ -1001,8 +1316,8 @@ ahd_handle_seqint(struct ahd_softc *ahd,
 		 * 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:
@@ -1029,7 +1344,7 @@ ahd_handle_seqint(struct ahd_softc *ahd,
 					   ROLE_INITIATOR, /*status*/0,
 					   SEARCH_REMOVE);
 		ahd_outb(ahd, SCB_CONTROL,
-			 ahd_inb(ahd, SCB_CONTROL) & ~MK_MESSAGE);
+			 ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE);
 		break;
 	}
 	case TASKMGMT_FUNC_COMPLETE:
@@ -1263,7 +1578,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd
 			 */
 			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);
@@ -1710,8 +2025,8 @@ ahd_handle_pkt_busfree(struct ahd_softc 
 			}
 			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. */
@@ -1853,7 +2168,7 @@ ahd_handle_nonpkt_busfree(struct ahd_sof
 			 && 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",
@@ -1880,21 +2195,32 @@ ahd_handle_nonpkt_busfree(struct ahd_sof
 			tinfo->goal.ppr_options = 0;
 			ahd_qinfifo_requeue_tail(ahd, scb);
 			printerror = 0;
-		} else if ((ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE)
-			 || ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE))
+		} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE)
 			&& ppr_busfree == 0) {
 			/*
-			 * Negotiation Rejected.  Go-async and
+			 * Negotiation Rejected.  Go-narrow and
 			 * retry command.
 			 */
 #ifdef AHD_DEBUG
 			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
-				printf("Negotiation rejected busfree.\n");
+				printf("WDTR negotiation rejected busfree.\n");
 #endif
 			ahd_set_width(ahd, &devinfo,
 				      MSG_EXT_WDTR_BUS_8_BIT,
 				      AHD_TRANS_CUR|AHD_TRANS_GOAL,
 				      /*paused*/TRUE);
+			ahd_qinfifo_requeue_tail(ahd, scb);
+			printerror = 0;
+		} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE)
+			&& ppr_busfree == 0) {
+			/*
+			 * Negotiation Rejected.  Go-async and
+			 * retry command.
+			 */
+#ifdef AHD_DEBUG
+			if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
+				printf("SDTR negotiation rejected busfree.\n");
+#endif
 			ahd_set_syncrate(ahd, &devinfo,
 					/*period*/0, /*offset*/0,
 					/*ppr_options*/0,
@@ -1933,8 +2259,8 @@ ahd_handle_nonpkt_busfree(struct ahd_sof
 	 && ((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),
@@ -1978,8 +2304,7 @@ ahd_handle_nonpkt_busfree(struct ahd_sof
 		       "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. */
@@ -2023,7 +2348,7 @@ ahd_handle_proto_violation(struct ahd_so
 		printf("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);
 			printf("No or incomplete CDB sent to device.\n");
@@ -2142,8 +2467,7 @@ ahd_clear_critical_section(struct ahd_so
 		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++) {
@@ -2187,8 +2511,14 @@ ahd_clear_critical_section(struct ahd_so
 			ahd_outb(ahd, LQOMODE0, 0);
 			ahd_outb(ahd, LQOMODE1, 0);
 			ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
-  			simode1 = ahd_inb(ahd, SIMODE1);
-  			ahd_outb(ahd, SIMODE1, ENBUSFREE);
+			simode1 = ahd_inb(ahd, SIMODE1);
+			/*
+			 * We don't clear ENBUSFREE.  Unfortunately
+			 * we cannot re-enable busfree detection within
+			 * the current connection, so we must leave it
+			 * on while single stepping.
+			 */
+			ahd_outb(ahd, SIMODE1, simode1 & ENBUSFREE);
 			ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) | STEP);
 			stepping = TRUE;
 		}
@@ -2196,9 +2526,8 @@ ahd_clear_critical_section(struct ahd_so
 		ahd_outb(ahd, CLRINT, CLRSCSIINT);
 		ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
 		ahd_outb(ahd, HCNTRL, ahd->unpause);
-		do {
-			ahd_delay(200);
-		} while (!ahd_is_paused(ahd));
+		while (!ahd_is_paused(ahd))
+			aic_delay(200);
 		ahd_update_modes(ahd);
 	}
 	if (stepping) {
@@ -2274,10 +2603,10 @@ ahd_print_scb(struct scb *scb)
 	for (i = 0; i < sizeof(hscb->shared_data.idata.cdb); i++)
 		printf("%#02x", hscb->shared_data.idata.cdb[i]);
 	printf("        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);
 }
@@ -2296,8 +2625,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);
 				printf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
 				       i,
 				       (uint32_t)((addr >> 32) & 0xFFFFFFFF),
@@ -2313,11 +2642,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);
 				printf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
 				       i,
-				       (len >> 24) & SG_HIGH_ADDR_BITS,
-				       ahd_le32toh(sg_list[i].addr),
+				       (len & AHD_SG_HIGH_ADDR_MASK) >> 24,
+				       aic_le32toh(sg_list[i].addr),
 				       len & AHD_SG_LEN_MASK,
 				       len & AHD_DMA_LAST_SEG ? " Last" : "");
 			}
@@ -2859,14 +3188,25 @@ ahd_update_neg_table(struct ahd_softc *a
 		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);
@@ -2904,7 +3244,7 @@ ahd_update_pending_scbs(struct ahd_softc
 {
 	struct		scb *pending_scb;
 	int		pending_scb_count;
-	int		i;
+	u_int		scb_tag;
 	int		paused;
 	u_int		saved_scbptr;
 	ahd_mode_state	saved_modes;
@@ -2962,17 +3302,14 @@ ahd_update_pending_scbs(struct ahd_softc
 	ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
 	saved_scbptr = ahd_get_scbptr(ahd);
 	/* Ensure that the hscbs down on the card match the new information */
-	for (i = 0; i < ahd->scb_data.maxhscbs; i++) {
+	for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) {
 		struct	hardware_scb *pending_hscb;
 		u_int	control;
-		u_int	scb_tag;
 
-		ahd_set_scbptr(ahd, i);
-		scb_tag = i;
 		pending_scb = ahd_lookup_scb(ahd, scb_tag);
 		if (pending_scb == NULL)
 			continue;
-
+		ahd_set_scbptr(ahd, scb_tag);
 		pending_hscb = pending_scb->hscb;
 		control = ahd_inb_scbram(ahd, SCB_CONTROL);
 		control &= ~MK_MESSAGE;
@@ -3187,7 +3524,7 @@ ahd_setup_initiator_msgout(struct ahd_so
 		       devinfo->target_mask);
 		panic("SCB = %d, SCB Control = %x:%x, MSG_OUT = %x "
 		      "SCB flags = %x", SCB_GET_TAG(scb), scb->hscb->control,
-		      ahd_inb(ahd, SCB_CONTROL), ahd_inb(ahd, MSG_OUT),
+		      ahd_inb_scbram(ahd, SCB_CONTROL), ahd_inb(ahd, MSG_OUT),
 		      scb->flags);
 	}
 
@@ -3232,6 +3569,7 @@ ahd_build_transfer_msg(struct ahd_softc 
 	 * may change.
 	 */
 	period = tinfo->goal.period;
+	offset = tinfo->goal.offset;
 	ppr_options = tinfo->goal.ppr_options;
 	/* Target initiated PPR is not allowed in the SCSI spec */
 	if (devinfo->role == ROLE_TARGET)
@@ -3239,7 +3577,7 @@ ahd_build_transfer_msg(struct ahd_softc 
 	ahd_devlimited_syncrate(ahd, tinfo, &period,
 				&ppr_options, devinfo->role);
 	dowide = tinfo->curr.width != tinfo->goal.width;
-	dosync = tinfo->curr.period != period;
+	dosync = tinfo->curr.offset != offset || tinfo->curr.period != period;
 	/*
 	 * Only use PPR if we have options that need it, even if the device
 	 * claims to support it.  There might be an expander in the way
@@ -3249,7 +3587,7 @@ ahd_build_transfer_msg(struct ahd_softc 
 
 	if (!dowide && !dosync && !doppr) {
 		dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT;
-		dosync = tinfo->goal.period != 0;
+		dosync = tinfo->goal.offset != 0;
 	}
 
 	if (!dowide && !dosync && !doppr) {
@@ -3725,8 +4063,13 @@ reswitch:
 		if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0) {
 			printf("%s: Returning to Idle Loop\n",
 			       ahd_name(ahd));
-			ahd_outb(ahd, LASTPHASE, P_BUSFREE);
 			ahd_clear_msg_state(ahd);
+
+			/*
+			 * Perform the equivalent of a clear_target_state.
+			 */
+			ahd_outb(ahd, LASTPHASE, P_BUSFREE);
+			ahd_outb(ahd, SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT);
 			ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
 		} else {
 			ahd_clear_msg_state(ahd);
@@ -3983,22 +4326,30 @@ ahd_parse_msg(struct ahd_softc *ahd, str
 				response = TRUE;
 				sending_reply = TRUE;
 			}
+			/*
+			 * After a wide message, we are async, but
+			 * some devices don't seem to honor this portion
+			 * of the spec.  Force a renegotiation of the
+			 * sync component of our transfer agreement even
+			 * if our goal is async.  By updating our width
+			 * after forcing the negotiation, we avoid
+			 * renegotiating for width.
+			 */
+			ahd_update_neg_request(ahd, devinfo, tstate,
+					       tinfo, AHD_NEG_ALWAYS);
 			ahd_set_width(ahd, devinfo, bus_width,
 				      AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
 				      /*paused*/TRUE);
-			/* After a wide message, we are async */
-			ahd_set_syncrate(ahd, devinfo, /*period*/0,
-					 /*offset*/0, /*ppr_options*/0,
-					 AHD_TRANS_ACTIVE, /*paused*/TRUE);
 			if (sending_reply == FALSE && reject == FALSE) {
 
-				if (tinfo->goal.offset) {
-					ahd->msgout_index = 0;
-					ahd->msgout_len = 0;
-					ahd_build_transfer_msg(ahd, devinfo);
-					ahd->msgout_index = 0;
-					response = TRUE;
-				}
+				/*
+				 * We will always have an SDTR to send.
+				 */
+				ahd->msgout_index = 0;
+				ahd->msgout_len = 0;
+				ahd_build_transfer_msg(ahd, devinfo);
+				ahd->msgout_index = 0;
+				response = TRUE;
 			}
 			done = MSGLOOP_MSGCOMPLETE;
 			break;
@@ -4326,7 +4677,7 @@ ahd_handle_msg_reject(struct ahd_softc *
 		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);
@@ -4384,7 +4735,7 @@ ahd_handle_ign_wide_residue(struct ahd_s
 	 * 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.
@@ -4401,7 +4752,8 @@ ahd_handle_ign_wide_residue(struct ahd_s
 
 		sgptr = ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);
 		if ((sgptr & SG_LIST_NULL) != 0
-		 && (ahd_inb(ahd, SCB_TASK_ATTRIBUTE) & SCB_XFERLEN_ODD) != 0) {
+		 && (ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)
+		     & SCB_XFERLEN_ODD) != 0) {
 			/*
 			 * If the residual occurred on the last
 			 * transfer and the transfer request was
@@ -4438,18 +4790,18 @@ ahd_handle_ign_wide_residue(struct ahd_s
 				 * 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;
 
@@ -4471,18 +4823,18 @@ ahd_handle_ign_wide_residue(struct ahd_s
 				 * 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;
 
@@ -4502,7 +4854,8 @@ ahd_handle_ign_wide_residue(struct ahd_s
 			 * correct for subsequent data transfers.
 			 */
 			ahd_outb(ahd, SCB_TASK_ATTRIBUTE,
-			    ahd_inb(ahd, SCB_TASK_ATTRIBUTE) ^ SCB_XFERLEN_ODD);
+			    ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)
+			    ^ SCB_XFERLEN_ODD);
 
 			ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
 			ahd_outl(ahd, SCB_RESIDUAL_DATACNT, data_cnt);
@@ -4542,9 +4895,8 @@ ahd_reinitialize_dataptrs(struct ahd_sof
 	 */
 	ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
 	wait = 1000;
-	do {
-		ahd_delay(100);
-	} while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE));
+	while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE))
+		aic_delay(100);
 	if (wait == 0) {
 		ahd_print_path(ahd, scb);
 		printf("ahd_reinitialize_dataptrs: Forcing FIFO free.\n");
@@ -4560,10 +4912,7 @@ ahd_reinitialize_dataptrs(struct ahd_sof
 	 * 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)
@@ -4578,13 +4927,10 @@ ahd_reinitialize_dataptrs(struct ahd_sof
 		/* 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;
 
@@ -4593,16 +4939,13 @@ ahd_reinitialize_dataptrs(struct ahd_sof
 		/* 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);
@@ -4796,8 +5139,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;
@@ -4833,24 +5176,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 {
@@ -4915,27 +5258,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:
@@ -4943,7 +5286,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);
@@ -4996,19 +5339,24 @@ 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);
+	ahd_reset(ahd, /*reinit*/FALSE);
 }
 
 /*
  * Reset the controller and record some information about it
- * that is only available just after a reset.
+ * that is only available just after a reset.  If "reinit" is
+ * non-zero, this reset occured after initial configuration
+ * and the caller requests that the chip be fully reinitialized
+ * to a runable state.  Chip interrupts are *not* enabled after
+ * a reinitialization.  The caller must enable interrupts via
+ * ahd_intr_enable().
  */
 int
-ahd_reset(struct ahd_softc *ahd)
+ahd_reset(struct ahd_softc *ahd, int reinit)
 {
 	u_int	 sxfrctl1;
 	int	 wait;
@@ -5024,7 +5372,7 @@ ahd_reset(struct ahd_softc *ahd)
 	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;
 
@@ -5038,7 +5386,7 @@ ahd_reset(struct ahd_softc *ahd)
 		 * 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);
@@ -5051,7 +5399,7 @@ ahd_reset(struct ahd_softc *ahd)
 	 */
 	wait = 1000;
 	do {
-		ahd_delay(1000);
+		aic_delay(1000);
 	} while (--wait && !(ahd_inb(ahd, HCNTRL) & CHIPRSTACK));
 
 	if (wait == 0) {
@@ -5065,9 +5413,9 @@ ahd_reset(struct ahd_softc *ahd)
 		 * 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);
 	}
 
@@ -5101,7 +5449,7 @@ ahd_reset(struct ahd_softc *ahd)
 	 * If a recovery action has forced a chip reset,
 	 * re-initialize the chip to our liking.
 	 */
-	if (ahd->init_level > 0)
+	if (reinit != 0)
 		ahd_chip_init(ahd);
 
 	return (0);
@@ -5194,7 +5542,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,
@@ -5208,7 +5556,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,
@@ -5227,7 +5575,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,
@@ -5315,13 +5663,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);
 			free(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:
@@ -5330,13 +5678,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);
 			free(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:
@@ -5345,13 +5693,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);
 			free(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:
@@ -5382,6 +5730,7 @@ ahd_setup_iocell_workaround(struct ahd_s
 		printf("%s: Setting up iocell workaround\n", ahd_name(ahd));
 #endif
 	ahd_restore_modes(ahd, saved_modes);
+	ahd->flags &= ~AHD_HAD_FIRST_SEL;
 }
 
 static void
@@ -5390,6 +5739,8 @@ ahd_iocell_first_selection(struct ahd_so
 	ahd_mode_state	saved_modes;
 	u_int		sblkctl;
 
+	if ((ahd->flags & AHD_HAD_FIRST_SEL) != 0)
+		return;
 	saved_modes = ahd_save_modes(ahd);
 	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
 	sblkctl = ahd_inb(ahd, SBLKCTL);
@@ -5409,6 +5760,7 @@ ahd_iocell_first_selection(struct ahd_so
 	ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) & ~(ENSELDO|ENSELDI));
 	ahd_outb(ahd, CLRINT, CLRSCSIINT);
 	ahd_restore_modes(ahd, saved_modes);
+	ahd->flags |= AHD_HAD_FIRST_SEL;
 }
 
 /*************************** SCB Management ***********************************/
@@ -5552,7 +5904,7 @@ ahd_free_scb(struct ahd_softc *ahd, stru
 				 scb, links.le);
 	}
 
-	ahd_platform_scb_free(ahd, scb);
+	aic_platform_scb_free(ahd, scb);
 }
 
 void
@@ -5583,7 +5935,7 @@ 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 = malloc(sizeof(*hscb_map), M_DEVBUF, M_NOWAIT);
 
@@ -5591,7 +5943,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
 			return;
 
 		/* 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) {
 			free(hscb_map, M_DEVBUF);
@@ -5600,12 +5952,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);
 	}
 
@@ -5616,7 +5968,7 @@ 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 = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
 
@@ -5624,7 +5976,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
 			return;
 
 		/* 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) {
 			free(sg_map, M_DEVBUF);
@@ -5633,12 +5985,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
@@ -5653,7 +6005,7 @@ 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 = malloc(sizeof(*sense_map), M_DEVBUF, M_NOWAIT);
 
@@ -5661,7 +6013,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
 			return;
 
 		/* 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) {
 			free(sense_map, M_DEVBUF);
@@ -5670,12 +6022,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)
@@ -5716,7 +6068,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.
@@ -5731,7 +6083,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) {
 			free(next_scb, M_DEVBUF);
@@ -5739,7 +6091,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)
@@ -5799,7 +6151,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;
@@ -5842,7 +6193,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
@@ -5873,7 +6224,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,
@@ -5888,21 +6239,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);
@@ -5923,7 +6277,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++;
 
@@ -6014,7 +6369,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);
 }
@@ -6075,7 +6430,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);
@@ -6174,7 +6529,7 @@ ahd_chip_init(struct ahd_softc *ahd)
 		ahd_outb(ahd, LUNLEN,
 			 sizeof(ahd->next_queued_hscb->pkt_long_lun) - 1);
 	} else {
-		ahd_outb(ahd, LUNLEN, sizeof(ahd->next_queued_hscb->lun) - 1);
+		ahd_outb(ahd, LUNLEN, LUNLEN_SINGLE_LEVEL_LUN);
 	}
 	ahd_outb(ahd, CDBLIMIT, SCB_CDB_LEN_PTR - 1);
 	ahd_outb(ahd, MAXCMD, 0xFF);
@@ -6215,6 +6570,7 @@ ahd_chip_init(struct ahd_softc *ahd)
 	ahd_outb(ahd, CLRSINT3, NTRAMPERR|OSRAMPERR);
 	ahd_outb(ahd, CLRINT, CLRSCSIINT);
 
+#if NEEDS_MORE_TESTING
 	/*
 	 * Always enable abort on incoming L_Qs if this feature is
 	 * supported.  We use this to catch invalid SCB references.
@@ -6222,6 +6578,7 @@ ahd_chip_init(struct ahd_softc *ahd)
 	if ((ahd->bugs & AHD_ABORT_LQI_BUG) == 0)
 		ahd_outb(ahd, LQCTL1, ABORTPENDING);
 	else
+#endif
 		ahd_outb(ahd, LQCTL1, 0);
 
 	/* All of our queues are empty */
@@ -6271,15 +6628,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.
@@ -6327,11 +6678,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.
@@ -6652,6 +7000,12 @@ ahd_pause_and_flushwork(struct ahd_softc
 		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);
@@ -6703,141 +7057,24 @@ ahd_pause_and_flushwork(struct ahd_softc
 int
 ahd_suspend(struct ahd_softc *ahd)
 {
-#if 0
-	uint8_t *ptr;
-	int	 i;
 
 	ahd_pause_and_flushwork(ahd);
 
-	if (LIST_FIRST(&ahd->pending_scbs) != NULL)
-		return (EBUSY);
-
-#if AHD_TARGET_MODE
-	/*
-	 * XXX What about ATIOs that have not yet been serviced?
-	 * Perhaps we should just refuse to be suspended if we
-	 * are acting in a target role.
-	 */
-	if (ahd->pending_device != NULL)
+	if (LIST_FIRST(&ahd->pending_scbs) != NULL) {
+		ahd_unpause(ahd);
 		return (EBUSY);
-#endif
-
-	/* Save volatile registers */
-	ahd->suspend_state.channel[0].scsiseq = ahd_inb(ahd, SCSISEQ0);
-	ahd->suspend_state.channel[0].sxfrctl0 = ahd_inb(ahd, SXFRCTL0);
-	ahd->suspend_state.channel[0].sxfrctl1 = ahd_inb(ahd, SXFRCTL1);
-	ahd->suspend_state.channel[0].simode0 = ahd_inb(ahd, SIMODE0);
-	ahd->suspend_state.channel[0].simode1 = ahd_inb(ahd, SIMODE1);
-	ahd->suspend_state.channel[0].seltimer = ahd_inb(ahd, SELTIMER);
-	ahd->suspend_state.channel[0].seqctl = ahd_inb(ahd, SEQCTL0);
-	ahd->suspend_state.dscommand0 = ahd_inb(ahd, DSCOMMAND0);
-	ahd->suspend_state.dspcistatus = ahd_inb(ahd, DSPCISTATUS);
-
-	if ((ahd->features & AHD_DT) != 0) {
-		u_int sfunct;
-
-		sfunct = ahd_inb(ahd, SFUNCT) & ~ALT_MODE;
-		ahd_outb(ahd, SFUNCT, sfunct | ALT_MODE);
-		ahd->suspend_state.optionmode = ahd_inb(ahd, OPTIONMODE);
-		ahd_outb(ahd, SFUNCT, sfunct);
-		ahd->suspend_state.crccontrol1 = ahd_inb(ahd, CRCCONTROL1);
-	}
-
-	if ((ahd->features & AHD_MULTI_FUNC) != 0)
-		ahd->suspend_state.scbbaddr = ahd_inb(ahd, SCBBADDR);
-
-	if ((ahd->features & AHD_ULTRA2) != 0)
-		ahd->suspend_state.dff_thrsh = ahd_inb(ahd, DFF_THRSH);
-
-	ptr = ahd->suspend_state.scratch_ram;
-	for (i = 0; i < 64; i++)
-		*ptr++ = ahd_inb(ahd, SRAM_BASE + i);
-
-	if ((ahd->features & AHD_MORE_SRAM) != 0) {
-		for (i = 0; i < 16; i++)
-			*ptr++ = ahd_inb(ahd, TARG_OFFSET + i);
-	}
-
-	ptr = ahd->suspend_state.btt;
-	for (i = 0;i < AHD_NUM_TARGETS; i++) {
-		int j;
-
-		for (j = 0;j < AHD_NUM_LUNS_NONPKT; j++) {
-			u_int tcl;
-
-			tcl = BUILD_TCL_RAW(i, 'A', j);
-			*ptr = ahd_find_busy_tcl(ahd, tcl);
-		}
 	}
 	ahd_shutdown(ahd);
-#endif
 	return (0);
 }
 
 int
 ahd_resume(struct ahd_softc *ahd)
 {
-#if 0
-	uint8_t *ptr;
-	int	 i;
-
-	ahd_reset(ahd);
-
-	ahd_build_free_scb_list(ahd);
-
-	/* Restore volatile registers */
-	ahd_outb(ahd, SCSISEQ0, ahd->suspend_state.channel[0].scsiseq);
-	ahd_outb(ahd, SXFRCTL0, ahd->suspend_state.channel[0].sxfrctl0);
-	ahd_outb(ahd, SXFRCTL1, ahd->suspend_state.channel[0].sxfrctl1);
-	ahd_outb(ahd, SIMODE0, ahd->suspend_state.channel[0].simode0);
-	ahd_outb(ahd, SIMODE1, ahd->suspend_state.channel[0].simode1);
-	ahd_outb(ahd, SELTIMER, ahd->suspend_state.channel[0].seltimer);
-	ahd_outb(ahd, SEQCTL0, ahd->suspend_state.channel[0].seqctl);
-	if ((ahd->features & AHD_ULTRA2) != 0)
-		ahd_outb(ahd, SCSIID_ULTRA2, ahd->our_id);
-	else
-		ahd_outb(ahd, SCSIID, ahd->our_id);
-
-	ahd_outb(ahd, DSCOMMAND0, ahd->suspend_state.dscommand0);
-	ahd_outb(ahd, DSPCISTATUS, ahd->suspend_state.dspcistatus);
-
-	if ((ahd->features & AHD_DT) != 0) {
-		u_int sfunct;
-
-		sfunct = ahd_inb(ahd, SFUNCT) & ~ALT_MODE;
-		ahd_outb(ahd, SFUNCT, sfunct | ALT_MODE);
-		ahd_outb(ahd, OPTIONMODE, ahd->suspend_state.optionmode);
-		ahd_outb(ahd, SFUNCT, sfunct);
-		ahd_outb(ahd, CRCCONTROL1, ahd->suspend_state.crccontrol1);
-	}
 
-	if ((ahd->features & AHD_MULTI_FUNC) != 0)
-		ahd_outb(ahd, SCBBADDR, ahd->suspend_state.scbbaddr);
-
-	if ((ahd->features & AHD_ULTRA2) != 0)
-		ahd_outb(ahd, DFF_THRSH, ahd->suspend_state.dff_thrsh);
-
-	ptr = ahd->suspend_state.scratch_ram;
-	for (i = 0; i < 64; i++)
-		ahd_outb(ahd, SRAM_BASE + i, *ptr++);
-
-	if ((ahd->features & AHD_MORE_SRAM) != 0) {
-		for (i = 0; i < 16; i++)
-			ahd_outb(ahd, TARG_OFFSET + i, *ptr++);
-	}
-
-	ptr = ahd->suspend_state.btt;
-	for (i = 0;i < AHD_NUM_TARGETS; i++) {
-		int j;
-
-		for (j = 0;j < AHD_NUM_LUNS; j++) {
-			u_int tcl;
-
-			tcl = BUILD_TCL(i << 4, j);
-			ahd_busy_tcl(ahd, tcl, *ptr);
-		}
-	}
-#endif
+	ahd_reset(ahd, /*reinit*/TRUE);
+	ahd_intr_enable(ahd, TRUE); 
+	ahd_restart(ahd);
 	return (0);
 }
 
@@ -6980,11 +7217,8 @@ ahd_qinfifo_requeue(struct ahd_softc *ah
 	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, 
@@ -7090,11 +7324,8 @@ ahd_search_qinfifo(struct ahd_softc *ahd
 	 * 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]);
@@ -7115,13 +7346,13 @@ ahd_search_qinfifo(struct ahd_softc *ahd
 				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)
 					printf("Inactive SCB in qinfifo\n");
 				ahd_done(ahd, scb);
@@ -7257,12 +7488,12 @@ ahd_search_scb_list(struct ahd_softc *ah
 			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)
 				printf("Inactive SCB in Waiting List\n");
 			ahd_done(ahd, scb);
@@ -7453,11 +7684,11 @@ ahd_abort_scbs(struct ahd_softc *ahd, in
 		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)
 				printf("Inactive SCB on pending list\n");
 			ahd_done(ahd, scbp);
@@ -7479,9 +7710,12 @@ ahd_reset_current_bus(struct ahd_softc *
 	ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~ENSCSIRST);
 	scsiseq = ahd_inb(ahd, SCSISEQ0) & ~(ENSELO|ENARBO|SCSIRSTO);
 	ahd_outb(ahd, SCSISEQ0, scsiseq | SCSIRSTO);
-	ahd_delay(AHD_BUSRESET_DELAY);
+	ahd_flush_device_writes(ahd);
+	aic_delay(AHD_BUSRESET_DELAY);
 	/* Turn off the bus reset */
 	ahd_outb(ahd, SCSISEQ0, scsiseq);
+	ahd_flush_device_writes(ahd);
+	aic_delay(AHD_BUSRESET_DELAY);
 	if ((ahd->bugs & AHD_SCSIRST_BUG) != 0) {
 		/*
 		 * 2A Razor #474
@@ -7489,8 +7723,7 @@ ahd_reset_current_bus(struct ahd_softc *
 		 * SCSI bus resets that we initiate, so
 		 * we must reset the chip.
 		 */
-		ahd_delay(AHD_BUSRESET_DELAY);
-		ahd_reset(ahd);
+		ahd_reset(ahd, /*reinit*/TRUE);
 		ahd_intr_enable(ahd, /*enable*/TRUE);
 		AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
 	}
@@ -7550,7 +7783,7 @@ ahd_reset_channel(struct ahd_softc *ahd,
 		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.
 		 */
@@ -7563,7 +7796,7 @@ ahd_reset_channel(struct ahd_softc *ahd,
 	 */
 	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);
@@ -7645,8 +7878,8 @@ ahd_reset_channel(struct ahd_softc *ahd,
 	 */
 	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);
 }
@@ -7674,7 +7907,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(ahd, &s);
@@ -7689,7 +7922,7 @@ ahd_reset_poll(void *arg)
 	ahd_unpause(ahd);
 	ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
 	ahd_unlock(ahd, &s);
-	ahd_release_simq(ahd);
+	aic_release_simq(ahd);
 	ahd_list_unlock(&l);
 }
 
@@ -7732,7 +7965,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(ahd, &s);
 	ahd_list_unlock(&l);
@@ -7753,8 +7986,9 @@ ahd_handle_scb_status(struct ahd_softc *
 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
@@ -7764,9 +7998,16 @@ ahd_handle_scsi_status(struct ahd_softc 
 	 */
 	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) {
 		printf("%s: Bad status with 0 qfreeze count!\n", ahd_name(ahd));
@@ -7778,6 +8019,9 @@ ahd_handle_scsi_status(struct ahd_softc 
 		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) {
 		/*
@@ -7785,12 +8029,12 @@ ahd_handle_scsi_status(struct ahd_softc 
 		 * 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:
 	{
@@ -7798,7 +8042,7 @@ ahd_handle_scsi_status(struct ahd_softc 
 
 		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);
@@ -7839,7 +8083,7 @@ ahd_handle_scsi_status(struct ahd_softc 
 				}
 			}
 			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) {
@@ -7869,7 +8113,7 @@ ahd_handle_scsi_status(struct ahd_softc 
 		}
 #endif
 
-		if (ahd_perform_autosense(scb) == 0)
+		if (aic_perform_autosense(scb) == 0)
 			break;
 
 		ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb),
@@ -7897,7 +8141,7 @@ ahd_handle_scsi_status(struct ahd_softc 
 #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;
@@ -7906,7 +8150,7 @@ ahd_handle_scsi_status(struct ahd_softc 
 			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;
 
 		/*
@@ -7926,7 +8170,7 @@ ahd_handle_scsi_status(struct ahd_softc 
 		 * 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);
@@ -7945,7 +8189,7 @@ ahd_handle_scsi_status(struct ahd_softc 
 		 * 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:
@@ -7987,7 +8231,7 @@ ahd_calc_residual(struct ahd_softc *ahd,
 	 */
 
 	hscb = scb->hscb;
-	sgptr = ahd_le32toh(hscb->sgptr);
+	sgptr = aic_le32toh(hscb->sgptr);
 	if ((sgptr & SG_STATUS_VALID) == 0)
 		/* Case 1 */
 		return;
@@ -8004,10 +8248,10 @@ ahd_calc_residual(struct ahd_softc *ahd,
 	 * 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;
@@ -8016,8 +8260,8 @@ ahd_calc_residual(struct ahd_softc *ahd,
 		printf("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);
@@ -8029,7 +8273,7 @@ ahd_calc_residual(struct ahd_softc *ahd,
 		 * 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 */
@@ -8040,15 +8284,15 @@ ahd_calc_residual(struct ahd_softc *ahd,
 		 * 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) {
@@ -8160,8 +8404,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];
 
@@ -8276,8 +8519,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) {
@@ -8406,7 +8648,7 @@ ahd_download_instr(struct ahd_softc *ahd
 	/*
 	 * 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;
@@ -8454,7 +8696,7 @@ ahd_download_instr(struct ahd_softc *ahd
 			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;
 	}
@@ -8580,11 +8822,15 @@ ahd_dump_card_state(struct ahd_softc *ah
 	printf(">>>>>>>>>>>>>>>>>> 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)
 		printf("Card was paused\n");
+
+	if (ahd_check_cmdcmpltqueues(ahd))
+		printf("Completions are pending\n");
+
 	/*
 	 * Mode independent registers.
 	 */
@@ -8634,10 +8880,12 @@ ahd_dump_card_state(struct ahd_softc *ah
 		if (i++ > AHD_SCB_MAX)
 			break;
 		cur_col = printf("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb),
-				 ahd_inb(ahd, SCB_FIFO_USE_COUNT));
+				 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT));
 		ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
-		ahd_scb_control_print(ahd_inb(ahd, SCB_CONTROL), &cur_col, 60);
-		ahd_scb_scsiid_print(ahd_inb(ahd, SCB_SCSIID), &cur_col, 60);
+		ahd_scb_control_print(ahd_inb_scbram(ahd, SCB_CONTROL),
+				      &cur_col, 60);
+		ahd_scb_scsiid_print(ahd_inb_scbram(ahd, SCB_SCSIID),
+				     &cur_col, 60);
 	}
 	printf("\nTotal %d\n", i);
 
@@ -8666,7 +8914,7 @@ ahd_dump_card_state(struct ahd_softc *ah
 	while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
 		ahd_set_scbptr(ahd, scb_index);
 		printf("%d ", scb_index);
-		scb_index = ahd_inw(ahd, SCB_NEXT_COMPLETE);
+		scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
 	}
 	printf("\n");
 
@@ -8676,7 +8924,7 @@ ahd_dump_card_state(struct ahd_softc *ah
 	while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
 		ahd_set_scbptr(ahd, scb_index);
 		printf("%d ", scb_index);
-		scb_index = ahd_inw(ahd, SCB_NEXT_COMPLETE);
+		scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
 	}
 	printf("\n");
 
@@ -8687,7 +8935,7 @@ ahd_dump_card_state(struct ahd_softc *ah
 	while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
 		ahd_set_scbptr(ahd, scb_index);
 		printf("%d ", scb_index);
-		scb_index = ahd_inw(ahd, SCB_NEXT_COMPLETE);
+		scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
 	}
 	printf("\n");
 	ahd_set_scbptr(ahd, saved_scb_index);
@@ -8766,15 +9014,16 @@ ahd_dump_card_state(struct ahd_softc *ah
 	       ahd_name(ahd), ahd_inw(ahd, REG0), ahd_inw(ahd, SINDEX),
 	       ahd_inw(ahd, DINDEX));
 	printf("%s: SCBPTR == 0x%x, SCB_NEXT == 0x%x, SCB_NEXT2 == 0x%x\n",
-	       ahd_name(ahd), ahd_get_scbptr(ahd), ahd_inw(ahd, SCB_NEXT),
-	       ahd_inw(ahd, SCB_NEXT2));
+	       ahd_name(ahd), ahd_get_scbptr(ahd),
+	       ahd_inw_scbram(ahd, SCB_NEXT),
+	       ahd_inw_scbram(ahd, SCB_NEXT2));
 	printf("CDB %x %x %x %x %x %x\n",
-	       ahd_inb(ahd, SCB_CDB_STORE),
-	       ahd_inb(ahd, SCB_CDB_STORE+1),
-	       ahd_inb(ahd, SCB_CDB_STORE+2),
-	       ahd_inb(ahd, SCB_CDB_STORE+3),
-	       ahd_inb(ahd, SCB_CDB_STORE+4),
-	       ahd_inb(ahd, SCB_CDB_STORE+5));
+	       ahd_inb_scbram(ahd, SCB_CDB_STORE),
+	       ahd_inb_scbram(ahd, SCB_CDB_STORE+1),
+	       ahd_inb_scbram(ahd, SCB_CDB_STORE+2),
+	       ahd_inb_scbram(ahd, SCB_CDB_STORE+3),
+	       ahd_inb_scbram(ahd, SCB_CDB_STORE+4),
+	       ahd_inb_scbram(ahd, SCB_CDB_STORE+5));
 	printf("STACK:");
 	for (i = 0; i < ahd->stack_size; i++) {
 		ahd->saved_stack[i] =
@@ -8806,16 +9055,292 @@ ahd_dump_scbs(struct ahd_softc *ahd)
 		ahd_set_scbptr(ahd, i);
 		printf("%3d", i);
 		printf("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n",
-		       ahd_inb(ahd, SCB_CONTROL),
-		       ahd_inb(ahd, SCB_SCSIID), ahd_inw(ahd, SCB_NEXT),
-		       ahd_inw(ahd, SCB_NEXT2), ahd_inl(ahd, SCB_SGPTR),
-		       ahd_inl(ahd, SCB_RESIDUAL_SGPTR));
+		       ahd_inb_scbram(ahd, SCB_CONTROL),
+		       ahd_inb_scbram(ahd, SCB_SCSIID),
+		       ahd_inw_scbram(ahd, SCB_NEXT),
+		       ahd_inw_scbram(ahd, SCB_NEXT2),
+		       ahd_inl_scbram(ahd, SCB_SGPTR),
+		       ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR));
 	}
 	printf("\n");
 	ahd_set_scbptr(ahd, saved_scb_index);
 	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;
+	long	s;
+	int	found;
+	int	was_paused;
+	u_int	active_scbptr;
+	u_int	last_phase;
+
+	ahd_lock(ahd, &s);
+
+	/*
+	 * 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.
+		 */
+		printf("%s: Timedout SCBs already complete. "
+		       "Interrupts may not be functioning.\n", ahd_name(ahd));
+		ahd_unpause(ahd);
+		ahd_unlock(ahd, &s);
+		return;
+	}
+
+	printf("%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);
+		printf("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);
+			printf("%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);
+			printf("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.
+			 */
+			printf("%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);
+			printf("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(ahd, &s);
+}
+
+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);
+	printf("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
@@ -8922,9 +9447,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);
@@ -9066,7 +9591,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);
@@ -9192,6 +9717,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd,
 			ahd->flags &= ~AHD_INITIATORROLE;
 		ahd_pause(ahd);
 		ahd_loadseq(ahd);
+		ahd_restart(ahd);
 		ahd_unlock(ahd, &s);
 	}
 	cel = &ccb->cel;
@@ -9267,13 +9793,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd,
 			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;
@@ -9387,14 +9909,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd,
 				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);
 				}
 			}
@@ -9425,6 +9942,11 @@ ahd_handle_en_lun(struct ahd_softc *ahd,
 				ahd->flags |= AHD_INITIATORROLE;
 				ahd_pause(ahd);
 				ahd_loadseq(ahd);
+				ahd_restart(ahd);
+				/*
+				 * Unpaused.  The extra unpause
+				 * that follows is harmless.
+				 */
 			}
 		}
 		ahd_unpause(ahd);
diff -puN drivers/scsi/aic7xxx/aic79xx.h~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic79xx.h
--- 25/drivers/scsi/aic7xxx/aic79xx.h~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic79xx.h	Wed Dec 24 12:15:38 2003
@@ -37,7 +37,7 @@
  * 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#90 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#101 $
  *
  * $FreeBSD$
  */
@@ -74,9 +74,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)	\
@@ -118,7 +118,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
@@ -229,8 +229,10 @@ 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,
 	AHD_AIC7902_FE		= AHD_MULTI_FUNC
 } ahd_feature;
 
@@ -372,7 +374,9 @@ typedef enum {
 	AHD_HP_BOARD	      = 0x100000,
 	AHD_RESET_POLL_ACTIVE = 0x200000,
 	AHD_UPDATE_PEND_CMDS  = 0x400000,
-	AHD_RUNNING_QOUTFIFO  = 0x800000
+	AHD_RUNNING_QOUTFIFO  = 0x800000,
+	AHD_HAD_FIRST_SEL     = 0x1000000,
+	AHD_SHUTDOWN_RECOVERY = 0x2000000 /* Terminate recovery thread. */
 } ahd_flag;
 
 /************************* Hardware  SCB Definition ***************************/
@@ -494,21 +498,21 @@ struct hardware_scb {
  *	  transfer.
  */ 
 #define SG_PTR_MASK	0xFFFFFFF8
-/*16*/	uint64_t dataptr;
-/*24*/	uint32_t datacnt;	/* Byte 3 is spare. */
-/*28*/	uint32_t sgptr;
-/*32*/	uint32_t hscb_busaddr;
-/*36*/	uint32_t next_hscb_busaddr;
-/*40*/	uint8_t  control;	/* See SCB_CONTROL in aic79xx.reg for details */
-/*41*/	uint8_t	 scsiid;	/*
+/*16*/	uint16_t tag;		/* Reused by Sequencer. */
+/*18*/	uint8_t  control;	/* See SCB_CONTROL in aic79xx.reg for details */
+/*19*/	uint8_t	 scsiid;	/*
 				 * Selection out Id
 				 * Our Id (bits 0-3) Their ID (bits 4-7)
 				 */
-/*42*/	uint8_t  lun;
-/*43*/	uint8_t  task_attribute;
-/*44*/	uint8_t  cdb_len;
-/*45*/	uint8_t  task_management;
-/*46*/	uint16_t tag;		/* Reused by Sequencer. */
+/*20*/	uint8_t  lun;
+/*21*/	uint8_t  task_attribute;
+/*22*/	uint8_t  cdb_len;
+/*23*/	uint8_t  task_management;
+/*24*/	uint64_t dataptr;
+/*32*/	uint32_t datacnt;	/* Byte 3 is spare. */
+/*36*/	uint32_t sgptr;
+/*40*/	uint32_t hscb_busaddr;
+/*44*/	uint32_t next_hscb_busaddr;
 /********** Long lun field only downloaded for full 8 byte lun support ********/
 /*48*/  uint8_t	 pkt_long_lun[8];
 /******* Fields below are not Downloaded (Sequencer may use for scratch) ******/
@@ -546,7 +550,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;
 };
@@ -588,12 +592,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 {
@@ -610,8 +618,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__
@@ -1059,6 +1068,7 @@ 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
@@ -1066,6 +1076,11 @@ struct ahd_softc {
 	LIST_HEAD(, scb)	  pending_scbs;
 
 	/*
+	 * SCBs whose timeout routine has been called.
+	 */
+	LIST_HEAD(, scb)	  timedout_scbs;
+
+	/*
 	 * Current register window mode information.
 	 */
 	ahd_mode		  dst_mode;
@@ -1086,7 +1101,7 @@ struct ahd_softc {
 	/*
 	 * Platform specific device information.
 	 */
-	ahd_dev_softc_t		  dev_softc;
+	aic_dev_softc_t		  dev_softc;
 
 	/*
 	 * Bus specific device information.
@@ -1116,8 +1131,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.
@@ -1194,8 +1209,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;
@@ -1296,9 +1310,9 @@ struct ahd_devinfo {
 };
 
 /****************************** PCI Structures ********************************/
-#define AHD_PCI_IOADDR0	PCIR_MAPS	/* I/O BAR*/
-#define AHD_PCI_MEMADDR	(PCIR_MAPS + 4)	/* Memory BAR */
-#define AHD_PCI_IOADDR1	(PCIR_MAPS + 12)/* Second I/O BAR */
+#define AHD_PCI_IOADDR0	PCIR_BAR(0)	/* I/O BAR*/
+#define AHD_PCI_MEMADDR	PCIR_BAR(1)	/* Memory BAR */
+#define AHD_PCI_IOADDR1	PCIR_BAR(3)	/* Second I/O BAR */
 
 typedef int (ahd_device_setup_t)(struct ahd_softc *);
 
@@ -1338,7 +1352,7 @@ ahd_unbusy_tcl(struct ahd_softc *ahd, u_
 }
 
 /***************************** 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 *);
@@ -1379,13 +1393,13 @@ struct scb		*ahd_get_scb(struct ahd_soft
 void			 ahd_free_scb(struct ahd_softc *ahd, struct scb *scb);
 void			 ahd_alloc_scbs(struct ahd_softc *ahd);
 void			 ahd_free(struct ahd_softc *ahd);
-int			 ahd_reset(struct ahd_softc *ahd);
+int			 ahd_reset(struct ahd_softc *ahd, int reinit);
 void			 ahd_shutdown(void *arg);
-int			ahd_write_flexport(struct ahd_softc *ahd,
-					   u_int addr, u_int value);
-int			ahd_read_flexport(struct ahd_softc *ahd, u_int addr,
-					  uint8_t *value);
-int			ahd_wait_flexport(struct ahd_softc *ahd);
+int			 ahd_write_flexport(struct ahd_softc *ahd,
+					    u_int addr, u_int value);
+int			 ahd_read_flexport(struct ahd_softc *ahd, u_int addr,
+					   uint8_t *value);
+int			 ahd_wait_flexport(struct ahd_softc *ahd);
 
 /*************************** Interrupt Services *******************************/
 void			ahd_pci_intr(struct ahd_softc *ahd);
@@ -1430,6 +1444,8 @@ void			ahd_handle_scsi_status(struct 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);
diff -puN drivers/scsi/aic7xxx/aic79xx_inline.h~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic79xx_inline.h
--- 25/drivers/scsi/aic7xxx/aic79xx_inline.h~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic79xx_inline.h	Wed Dec 24 12:15:38 2003
@@ -37,7 +37,7 @@
  * 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#50 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#55 $
  *
  * $FreeBSD$
  */
@@ -250,15 +250,15 @@ ahd_sg_setup(struct ahd_softc *ahd, stru
 		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);
 	}
@@ -273,7 +273,7 @@ ahd_setup_scb_common(struct ahd_softc *a
 		/* 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;
@@ -282,7 +282,7 @@ ahd_setup_scb_common(struct ahd_softc *a
 	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
@@ -308,8 +308,8 @@ ahd_setup_data_scb(struct ahd_softc *ahd
 		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;
 	}
@@ -319,13 +319,13 @@ ahd_setup_data_scb(struct ahd_softc *ahd
 	 * 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;
 }
@@ -383,7 +383,7 @@ ahd_sg_virt_to_bus(struct ahd_softc *ahd
 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);
@@ -395,7 +395,7 @@ ahd_sync_sglist(struct ahd_softc *ahd, s
 	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);
@@ -404,7 +404,7 @@ ahd_sync_sglist(struct ahd_softc *ahd, s
 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);
@@ -455,6 +455,8 @@ static __inline u_int	ahd_inb_scbram(str
 static __inline u_int	ahd_inw_scbram(struct ahd_softc *ahd, u_int offset);
 static __inline uint32_t
 			ahd_inl_scbram(struct ahd_softc *ahd, u_int offset);
+static __inline uint64_t
+			ahd_inq_scbram(struct ahd_softc *ahd, u_int offset);
 static __inline void	ahd_swap_with_next_hscb(struct ahd_softc *ahd,
 						struct scb *scb);
 static __inline void	ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb);
@@ -470,7 +472,7 @@ ahd_complete_scb(struct ahd_softc *ahd, 
 {
 	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
@@ -486,7 +488,7 @@ ahd_update_residual(struct ahd_softc *ah
 {
 	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);
 }
@@ -520,12 +522,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);
 }
@@ -697,10 +708,15 @@ ahd_inw_scbram(struct ahd_softc *ahd, u_
 static __inline uint32_t
 ahd_inl_scbram(struct ahd_softc *ahd, u_int offset)
 {
-	return (ahd_inb_scbram(ahd, offset)
-	      | (ahd_inb_scbram(ahd, offset+1) << 8)
-	      | (ahd_inb_scbram(ahd, offset+2) << 16)
-	      | (ahd_inb_scbram(ahd, offset+3) << 24));
+	return (ahd_inw_scbram(ahd, offset)
+	      | (ahd_inw_scbram(ahd, offset+2) << 16));
+}
+
+static __inline uint64_t
+ahd_inq_scbram(struct ahd_softc *ahd, u_int offset)
+{
+	return (ahd_inl_scbram(ahd, offset)
+	      | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32);
 }
 
 static __inline struct scb *
@@ -720,7 +736,8 @@ ahd_lookup_scb(struct ahd_softc *ahd, u_
 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;
 
 	/*
@@ -736,6 +753,7 @@ ahd_swap_with_next_hscb(struct ahd_softc
 	 * 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;
@@ -743,7 +761,9 @@ ahd_swap_with_next_hscb(struct ahd_softc
 
 	/* 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;
@@ -783,13 +803,13 @@ ahd_queue_scb(struct ahd_softc *ahd, str
 	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);
 		printf("%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 */
@@ -817,8 +837,8 @@ static __inline int	ahd_intr(struct 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
@@ -826,8 +846,8 @@ ahd_sync_tqinfifo(struct ahd_softc *ahd,
 {
 #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);
@@ -847,7 +867,7 @@ ahd_check_cmdcmpltqueues(struct ahd_soft
 	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]
@@ -856,8 +876,8 @@ ahd_check_cmdcmpltqueues(struct ahd_soft
 #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);
diff -puN drivers/scsi/aic7xxx/aic79xx_osm.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic79xx_osm.c
--- 25/drivers/scsi/aic7xxx/aic79xx_osm.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic79xx_osm.c	Wed Dec 24 12:15:38 2003
@@ -1,7 +1,7 @@
 /*
  * Adaptec AIC79xx device driver for Linux.
  *
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#169 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#193 $
  *
  * --------------------------------------------------------------------------
  * Copyright (c) 1994-2000 Justin T. Gibbs.
@@ -62,6 +62,16 @@
 
 #include <linux/mm.h>		/* For fetching system memory size */
 
+/************************* Magic SysReq Support *******************************/
+static struct aic_sysrq_key_op ahd_sysrq_op =
+{
+	aic_sysrq_handler,
+	"aic79xxstatedump",
+	"Dump aic79xx controller information to Console"
+};
+
+static int ahd_sysrq_key;
+
 /*
  * Lock protecting manipulation of the ahd softc list.
  */
@@ -425,7 +435,7 @@ static char *aic79xx = NULL;
 static char dummy_buffer[60] = "Please don't trounce on me insmod!!\n";
 
 MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
-MODULE_DESCRIPTION("Adaptec Aic77XX/78XX SCSI Host Bus Adapter driver");
+MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver");
 #ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual BSD/GPL");
 #endif
@@ -466,7 +476,7 @@ MODULE_PARM_DESC(aic79xx,
 #endif
 
 static void ahd_linux_handle_scsi_status(struct ahd_softc *,
-					 struct ahd_linux_device *,
+					 struct aic_linux_device *,
 					 struct scb *);
 static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd,
 					 Scsi_Cmnd *cmd);
@@ -478,21 +488,20 @@ static void ahd_linux_initialize_scsi_bu
 static void ahd_linux_size_nseg(void);
 static void ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd);
 static void ahd_linux_start_dv(struct ahd_softc *ahd);
-static void ahd_linux_dv_timeout(struct scsi_cmnd *cmd);
 static int  ahd_linux_dv_thread(void *data);
 static void ahd_linux_kill_dv_thread(struct ahd_softc *ahd);
 static void ahd_linux_dv_target(struct ahd_softc *ahd, u_int target);
 static void ahd_linux_dv_transition(struct ahd_softc *ahd,
 				    struct scsi_cmnd *cmd,
 				    struct ahd_devinfo *devinfo,
-				    struct ahd_linux_target *targ);
+				    struct aic_linux_target *targ);
 static void ahd_linux_dv_fill_cmd(struct ahd_softc *ahd,
 				  struct scsi_cmnd *cmd,
 				  struct ahd_devinfo *devinfo);
 static void ahd_linux_dv_inq(struct ahd_softc *ahd,
 			     struct scsi_cmnd *cmd,
 			     struct ahd_devinfo *devinfo,
-			     struct ahd_linux_target *targ,
+			     struct aic_linux_target *targ,
 			     u_int request_length);
 static void ahd_linux_dv_tur(struct ahd_softc *ahd,
 			     struct scsi_cmnd *cmd,
@@ -500,19 +509,19 @@ static void ahd_linux_dv_tur(struct ahd_
 static void ahd_linux_dv_rebd(struct ahd_softc *ahd,
 			      struct scsi_cmnd *cmd,
 			      struct ahd_devinfo *devinfo,
-			      struct ahd_linux_target *targ);
+			      struct aic_linux_target *targ);
 static void ahd_linux_dv_web(struct ahd_softc *ahd,
 			     struct scsi_cmnd *cmd,
 			     struct ahd_devinfo *devinfo,
-			     struct ahd_linux_target *targ);
+			     struct aic_linux_target *targ);
 static void ahd_linux_dv_reb(struct ahd_softc *ahd,
 			     struct scsi_cmnd *cmd,
 			     struct ahd_devinfo *devinfo,
-			     struct ahd_linux_target *targ);
+			     struct aic_linux_target *targ);
 static void ahd_linux_dv_su(struct ahd_softc *ahd,
 			    struct scsi_cmnd *cmd,
 			    struct ahd_devinfo *devinfo,
-			    struct ahd_linux_target *targ);
+			    struct aic_linux_target *targ);
 static __inline int
 	   ahd_linux_dv_fallback(struct ahd_softc *ahd,
 				 struct ahd_devinfo *devinfo);
@@ -520,103 +529,57 @@ static int ahd_linux_fallback(struct ahd
 			      struct ahd_devinfo *devinfo);
 static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd,
 					  struct ahd_devinfo *devinfo);
-static void ahd_linux_dv_complete(Scsi_Cmnd *cmd);
-static void ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ);
+static void ahd_linux_generate_dv_pattern(struct aic_linux_target *targ);
 static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd,
 				     struct ahd_devinfo *devinfo);
 static u_int ahd_linux_user_dv_setting(struct ahd_softc *ahd);
 static void ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd);
-static void ahd_linux_device_queue_depth(struct ahd_softc *ahd,
-					 struct ahd_linux_device *dev);
-static struct ahd_linux_target*	ahd_linux_alloc_target(struct ahd_softc*,
+static void aic_linux_device_queue_depth(struct ahd_softc *ahd,
+					 struct aic_linux_device *dev);
+static struct aic_linux_target*	ahd_linux_alloc_target(struct ahd_softc*,
 						       u_int, u_int);
 static void			ahd_linux_free_target(struct ahd_softc*,
-						      struct ahd_linux_target*);
-static struct ahd_linux_device*	ahd_linux_alloc_device(struct ahd_softc*,
-						       struct ahd_linux_target*,
+						      struct aic_linux_target*);
+static struct aic_linux_device*	ahd_linux_alloc_device(struct ahd_softc*,
+						       struct aic_linux_target*,
 						       u_int);
 static void			ahd_linux_free_device(struct ahd_softc*,
-						      struct ahd_linux_device*);
-static void ahd_linux_run_device_queue(struct ahd_softc*,
-				       struct ahd_linux_device*);
+						      struct aic_linux_device*);
 static void ahd_linux_setup_tag_info_global(char *p);
 static aic_option_callback_t ahd_linux_setup_tag_info;
 static aic_option_callback_t ahd_linux_setup_rd_strm_info;
 static aic_option_callback_t ahd_linux_setup_dv;
 static aic_option_callback_t ahd_linux_setup_iocell_info;
 static int ahd_linux_next_unit(void);
-static void ahd_runq_tasklet(unsigned long data);
 static int aic79xx_setup(char *c);
 
 /****************************** Inlines ***************************************/
 static __inline void ahd_schedule_completeq(struct ahd_softc *ahd);
-static __inline void ahd_schedule_runq(struct ahd_softc *ahd);
-static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd);
-static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd);
-static __inline struct ahd_linux_device*
+static __inline struct aic_linux_device*
 		     ahd_linux_get_device(struct ahd_softc *ahd, u_int channel,
 					  u_int target, u_int lun, int alloc);
-static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd);
-static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd,
-						  struct ahd_linux_device *dev);
-static __inline struct ahd_linux_device *
-		     ahd_linux_next_device_to_run(struct ahd_softc *ahd);
-static __inline void ahd_linux_run_device_queues(struct ahd_softc *ahd);
 static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
-
-static __inline int ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb,
-		 		      struct ahd_dma_seg *sg,
-				      bus_addr_t addr, bus_size_t len);
+static __inline struct ahd_dma_seg*
+		     ahd_linux_sg_setup(struct ahd_softc *ahd, struct scb *scb,
+					struct ahd_dma_seg *sg, bus_addr_t addr,
+					bus_size_t len, int last_seg);
 
 static __inline void
 ahd_schedule_completeq(struct ahd_softc *ahd)
 {
-	if ((ahd->platform_data->flags & AHD_RUN_CMPLT_Q_TIMER) == 0) {
-		ahd->platform_data->flags |= AHD_RUN_CMPLT_Q_TIMER;
+	if ((ahd->platform_data->flags & AIC_RUN_CMPLT_Q_TIMER) == 0) {
+		ahd->platform_data->flags |= AIC_RUN_CMPLT_Q_TIMER;
 		ahd->platform_data->completeq_timer.expires = jiffies;
 		add_timer(&ahd->platform_data->completeq_timer);
 	}
 }
 
-/*
- * Must be called with our lock held.
- */
-static __inline void
-ahd_schedule_runq(struct ahd_softc *ahd)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	tasklet_schedule(&ahd->platform_data->runq_tasklet);
-#else
-	/*
-	 * Tasklets are not available, so run inline.
-	 */
-	ahd_runq_tasklet((unsigned long)ahd);
-#endif
-}
-
-static __inline
-void ahd_setup_runq_tasklet(struct ahd_softc *ahd)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	tasklet_init(&ahd->platform_data->runq_tasklet, ahd_runq_tasklet,
-		     (unsigned long)ahd);
-#endif
-}
-
-static __inline void
-ahd_teardown_runq_tasklet(struct ahd_softc *ahd)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	tasklet_kill(&ahd->platform_data->runq_tasklet);
-#endif
-}
-
-static __inline struct ahd_linux_device*
+static __inline struct aic_linux_device*
 ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target,
 		     u_int lun, int alloc)
 {
-	struct ahd_linux_target *targ;
-	struct ahd_linux_device *dev;
+	struct aic_linux_target *targ;
+	struct aic_linux_device *dev;
 	u_int target_offset;
 
 	target_offset = target;
@@ -638,10 +601,10 @@ ahd_linux_get_device(struct ahd_softc *a
 }
 
 #define AHD_LINUX_MAX_RETURNED_ERRORS 4
-static struct ahd_cmd *
+static struct aic_cmd *
 ahd_linux_run_complete_queue(struct ahd_softc *ahd)
 {	
-	struct	ahd_cmd *acmd;
+	struct	aic_cmd *acmd;
 	u_long	done_flags;
 	int	with_errors;
 
@@ -666,7 +629,7 @@ ahd_linux_run_complete_queue(struct ahd_
 			     acmd, acmd_links.tqe);
 		cmd = &acmd_scsi_cmd(acmd);
 		cmd->host_scribble = NULL;
-		if (ahd_cmd_get_transaction_status(cmd) != DID_OK
+		if (aic_cmd_get_transaction_status(cmd) != DID_OK
 		 || (cmd->result & 0xFF) != SCSI_STATUS_OK)
 			with_errors++;
 
@@ -677,46 +640,6 @@ ahd_linux_run_complete_queue(struct ahd_
 }
 
 static __inline void
-ahd_linux_check_device_queue(struct ahd_softc *ahd,
-			     struct ahd_linux_device *dev)
-{
-	if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) != 0
-	 && dev->active == 0) {
-		dev->flags &= ~AHD_DEV_FREEZE_TIL_EMPTY;
-		dev->qfrozen--;
-	}
-
-	if (TAILQ_FIRST(&dev->busyq) == NULL
-	 || dev->openings == 0 || dev->qfrozen != 0)
-		return;
-
-	ahd_linux_run_device_queue(ahd, dev);
-}
-
-static __inline struct ahd_linux_device *
-ahd_linux_next_device_to_run(struct ahd_softc *ahd)
-{
-	
-	if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0
-	 || (ahd->platform_data->qfrozen != 0
-	  && AHD_DV_SIMQ_FROZEN(ahd) == 0))
-		return (NULL);
-	return (TAILQ_FIRST(&ahd->platform_data->device_runq));
-}
-
-static __inline void
-ahd_linux_run_device_queues(struct ahd_softc *ahd)
-{
-	struct ahd_linux_device *dev;
-
-	while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) {
-		TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links);
-		dev->flags &= ~AHD_DEV_ON_RUN_LIST;
-		ahd_linux_check_device_queue(ahd, dev);
-	}
-}
-
-static __inline void
 ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
 {
 	Scsi_Cmnd *cmd;
@@ -729,34 +652,22 @@ ahd_linux_unmap_scb(struct ahd_softc *ah
 		struct scatterlist *sg;
 
 		sg = (struct scatterlist *)cmd->request_buffer;
-		pci_unmap_sg(ahd->dev_softc, sg, cmd->use_sg, direction);
+		aic_unmap_sg(ahd, sg, cmd->use_sg, direction);
 	} else if (cmd->request_bufflen != 0) {
-		pci_unmap_single(ahd->dev_softc,
+		aic_unmap_single(ahd,
 				 scb->platform_data->buf_busaddr,
 				 cmd->request_bufflen, direction);
 	}
 }
 
-static __inline int
-ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb,
-		  struct ahd_dma_seg *sg, bus_addr_t addr, bus_size_t len)
+static __inline struct ahd_dma_seg*
+ahd_linux_sg_setup(struct ahd_softc *ahd, struct scb *scb,
+		   struct ahd_dma_seg *sg, bus_addr_t addr,
+		   bus_size_t len, int last_seg)
 {
-	int	 consumed;
-
-	if ((scb->sg_count + 1) > AHD_NSEG)
-		panic("Too few segs for dma mapping.  "
-		      "Increase AHD_NSEG\n");
-
-	consumed = 1;
-	sg->addr = ahd_htole32(addr & 0xFFFFFFFF);
+	sg = ahd_sg_setup(ahd, scb, sg, addr, len, last_seg);
 	scb->platform_data->xfer_len += len;
-
-	if (sizeof(bus_addr_t) > 4
-	 && (ahd->flags & AHD_39BIT_ADDRESSING) != 0)
-		len |= (addr >> 8) & AHD_SG_HIGH_ADDR_MASK;
-
-	sg->len = ahd_htole32(len);
-	return (consumed);
+	return (sg);
 }
 
 /******************************** Macros **************************************/
@@ -797,7 +708,7 @@ static int	   ahd_linux_abort(Scsi_Cmnd 
  * number of segments needed for the current transfer.  Since the code that
  * sizes the SCSI malloc pool does not take into consideration fragmentation
  * of the pool, executing transactions numbering just a fraction of our
- * concurrent transaction limit with SG list lengths aproaching AHC_NSEG will
+ * concurrent transaction limit with SG list lengths aproaching AHD_NSEG will
  * quickly depleat the SCSI malloc pool of usable space.  Unfortunately, the
  * mid-layer does not properly handle this scsi malloc failures for the S/G
  * array and the result can be a lockup of the I/O subsystem.  We try to size
@@ -848,6 +759,165 @@ ahd_linux_size_nseg(void)
 #endif
 }
 
+/************************** Error Recovery ************************************/
+static int ahd_linux_recovery_thread(void *arg);
+
+static int
+ahd_linux_recovery_thread(void *arg)
+{
+	struct ahd_softc *ahd;
+	u_long s;
+
+	ahd = (struct ahd_softc *)arg;
+
+	/*
+	 * Complete thread creation.
+	 */
+	lock_kernel();
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60)
+	/*
+	 * Don't care about any signals.
+	 */
+	siginitsetinv(&current->blocked, 0);
+
+	daemonize();
+	sprintf(current->comm, "ahd_recovery_%d", ahd->unit);
+#else
+	daemonize("ahd_recovery_%d", ahd->unit);
+#endif
+	unlock_kernel();
+
+	while (1) {
+
+		/*
+		 * Use down_interruptible() rather than down() to
+		 * avoid inclusion in the load average.
+		 */
+		down_interruptible(&ahd->platform_data->recovery_sem);
+
+		ahd_lock(ahd, &s);
+		if ((ahd->flags & AHD_SHUTDOWN_RECOVERY) != 0) {
+			ahd_unlock(ahd, &s);
+			break;
+		}
+
+		/*
+		 * Don't bother the recovery handler if the
+		 * list has been cleared by a previous run
+		 * of the handler.  This can happen when
+		 * several SCBs timeout before our handler
+		 * can run causing our semaphore to be up'ed
+		 * repeatedly.  The extra calls need to be
+		 * avoided so that the recovery handler doesn't
+		 * confuse this case with timeouts occuring
+		 * due to interrupts failing to function.
+		 */
+		if (LIST_EMPTY(&ahd->timedout_scbs) != 0) {
+			ahd_unlock(ahd, &s);
+			continue;
+		}
+
+		ahd_unlock(ahd, &s);
+		ahd_recover_commands(ahd);
+
+		/*
+		 * Process any pent up completions.
+		 */
+		ahd_lock(ahd, &s);
+		aic_schedule_runq(ahd);
+		ahd_linux_run_complete_queue(ahd);
+		ahd_unlock(ahd, &s);
+	}
+	up(&ahd->platform_data->recovery_ending_sem);
+	return(0);
+}
+
+int
+ahd_spawn_recovery_thread(struct ahd_softc *ahd)
+{
+	ahd->platform_data->recovery_pid =
+	    kernel_thread(ahd_linux_recovery_thread, ahd, 0);
+	
+	if (ahd->platform_data->recovery_pid < 0)
+		return (-ahd->platform_data->recovery_pid);
+
+	return (0);
+}
+
+void
+ahd_terminate_recovery_thread(struct ahd_softc *ahd)
+{
+	u_long s;
+
+	ahd_lock(ahd, &s);
+	if (ahd->platform_data->recovery_pid != 0) {
+		ahd->flags |= AHD_SHUTDOWN_RECOVERY;
+		ahd_unlock(ahd, &s);
+		up(&ahd->platform_data->recovery_sem);
+
+		/*
+		 * Use the recovery_ending_sem as an indicator that
+		 * the dv thread is exiting.  Note that the dv
+		 * thread must still return after performing
+		 * the up on our semaphore before it has
+		 * completely exited this module.  Unfortunately,
+		 * there seems to be no easy way to wait for the
+		 * exit of a thread for which you are not the
+		 * parent (dv threads are parented by init).
+		 * Cross your fingers...
+		 */
+		down(&ahd->platform_data->recovery_ending_sem);
+
+		/*
+		 * Mark the recovery thread as already dead.  This
+		 * avoids attempting to kill it a second time.
+		 * This is necessary because we must kill the
+		 * our threads before calling ahd_free() in the
+		 * module shutdown case to avoid bogus locking
+		 * in the SCSI mid-layer, but when ahd_free() is
+		 * called without killing the DV thread in the
+		 * instance detach case, so ahd_platform_free()
+		 * calls us again to verify that the DV thread
+		 * is dead.
+		 */
+		ahd->platform_data->recovery_pid = 0;
+	} else {
+		ahd_unlock(ahd, &s);
+	}
+}
+
+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 commands are queued to us while we
+		 * try to fix this problem.
+		 */
+		if ((scb->platform_data->flags & AIC_RELEASE_SIMQ) == 0) {
+			aic_freeze_simq(ahd);
+			scb->platform_data->flags |= AIC_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) {
+
+			scsi_delete_timer(list_scb->io_ctx);
+			list_scb->platform_data->flags &= ~AIC_TIMEOUT_ACTIVE;
+		}
+	}
+}
+
+/********************** Host Template Entry Points ****************************/
 /*
  * Try to detect an Adaptec 79XX controller.
  */
@@ -870,7 +940,7 @@ ahd_linux_detect(Scsi_Host_Template *tem
 	 * that some of our hacks^H^H^H^H^Hassumptions aren't
 	 * violated.
 	 */
-	if (offsetof(struct ahd_cmd_internal, end)
+	if (offsetof(struct aic_cmd_internal, end)
 	  > offsetof(struct scsi_cmnd, host_scribble)) {
 		printf("ahd_linux_detect: SCSI data structures changed.\n");
 		printf("ahd_linux_detect: Unable to attach\n");
@@ -938,7 +1008,6 @@ ahd_linux_release(struct Scsi_Host * hos
 	struct ahd_softc *ahd;
 	u_long l;
 
-	ahd_list_lock(&l);
 	if (host != NULL) {
 
 		/*
@@ -946,17 +1015,20 @@ ahd_linux_release(struct Scsi_Host * hos
 		 * the free directly, but check our
 		 * list for extra sanity.
 		 */
+		ahd_list_lock(&l);
 		ahd = ahd_find_softc(*(struct ahd_softc **)host->hostdata);
 		if (ahd != NULL) {
 			u_long s;
 
+			TAILQ_REMOVE(&ahd_tailq, ahd, links);
+			ahd_list_unlock(&l);
 			ahd_lock(ahd, &s);
 			ahd_intr_enable(ahd, FALSE);
 			ahd_unlock(ahd, &s);
 			ahd_free(ahd);
-		}
+		} else
+			ahd_list_unlock(&l);
 	}
-	ahd_list_unlock(&l);
 	return (0);
 }
 #endif
@@ -996,7 +1068,7 @@ static int
 ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
 {
 	struct	 ahd_softc *ahd;
-	struct	 ahd_linux_device *dev;
+	struct	 aic_linux_device *dev;
 	u_long	 flags;
 
 	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
@@ -1015,9 +1087,9 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*
 	 * perform DV.
 	 */
 	if (ahd->platform_data->qfrozen != 0
-	 && AHD_DV_CMD(cmd) == 0) {
+	 && AIC_DV_CMD(cmd) == 0) {
 
-		ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
+		aic_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
 		ahd_linux_queue_cmd_complete(ahd, cmd);
 		ahd_schedule_completeq(ahd);
 		ahd_midlayer_entrypoint_unlock(ahd, &flags);
@@ -1027,7 +1099,8 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*
 				   cmd->device->id, cmd->device->lun,
 				   /*alloc*/TRUE);
 	if (dev == NULL) {
-		ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
+
+		aic_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
 		ahd_linux_queue_cmd_complete(ahd, cmd);
 		ahd_schedule_completeq(ahd);
 		ahd_midlayer_entrypoint_unlock(ahd, &flags);
@@ -1035,14 +1108,30 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*
 		       ahd_name(ahd));
 		return (0);
 	}
-	if (cmd->cmd_len > MAX_CDB_LEN)
-		return (-EINVAL);
+
+	if (cmd->cmd_len > MAX_CDB_LEN) {
+
+		aic_cmd_set_transaction_status(cmd, CAM_REQ_INVALID);
+		ahd_linux_queue_cmd_complete(ahd, cmd);
+		ahd_schedule_completeq(ahd);
+		ahd_midlayer_entrypoint_unlock(ahd, &flags);
+		printf("%s: aic79xx_linux_queue -"
+		       "CDB length of %d exceeds max!\n",
+		       ahd_name(ahd), cmd->cmd_len);
+		return (0);
+	}
+
+	/*
+	 * We perform our own timeout handling.
+	 */
+	scsi_delete_timer(cmd);
+
 	cmd->result = CAM_REQ_INPROG << 16;
-	TAILQ_INSERT_TAIL(&dev->busyq, (struct ahd_cmd *)cmd, acmd_links.tqe);
-	if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) {
+	TAILQ_INSERT_TAIL(&dev->busyq, (struct aic_cmd *)cmd, acmd_links.tqe);
+	if ((dev->flags & AIC_DEV_ON_RUN_LIST) == 0) {
 		TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links);
-		dev->flags |= AHD_DEV_ON_RUN_LIST;
-		ahd_linux_run_device_queues(ahd);
+		dev->flags |= AIC_DEV_ON_RUN_LIST;
+		aic_linux_run_device_queues(ahd);
 	}
 	ahd_midlayer_entrypoint_unlock(ahd, &flags);
 	return (0);
@@ -1064,7 +1153,7 @@ static int
 ahd_linux_slave_configure(Scsi_Device *device)
 {
 	struct	ahd_softc *ahd;
-	struct	ahd_linux_device *dev;
+	struct	aic_linux_device *dev;
 	u_long	flags;
 
 	ahd = *((struct ahd_softc **)device->host->hostdata);
@@ -1080,10 +1169,10 @@ ahd_linux_slave_configure(Scsi_Device *d
 				   device->id, device->lun,
 				   /*alloc*/TRUE);
 	if (dev != NULL) {
-		dev->flags &= ~AHD_DEV_UNCONFIGURED;
-		dev->flags |= AHD_DEV_SLAVE_CONFIGURED;
+		dev->flags &= ~AIC_DEV_UNCONFIGURED;
+		dev->flags |= AIC_DEV_SLAVE_CONFIGURED;
 		dev->scsi_device = device;
-		ahd_linux_device_queue_depth(ahd, dev);
+		aic_linux_device_queue_depth(ahd, dev);
 	}
 	ahd_midlayer_entrypoint_unlock(ahd, &flags);
 	return (0);
@@ -1093,7 +1182,7 @@ static void
 ahd_linux_slave_destroy(Scsi_Device *device)
 {
 	struct	ahd_softc *ahd;
-	struct	ahd_linux_device *dev;
+	struct	aic_linux_device *dev;
 	u_long	flags;
 
 	ahd = *((struct ahd_softc **)device->host->hostdata);
@@ -1112,11 +1201,10 @@ ahd_linux_slave_destroy(Scsi_Device *dev
 	 * the refcounting process.
 	 */
 	if (dev != NULL
-	 && (dev->flags & AHD_DEV_SLAVE_CONFIGURED) != 0) {
-		dev->flags |= AHD_DEV_UNCONFIGURED;
+	 && (dev->flags & AIC_DEV_SLAVE_CONFIGURED) != 0) {
+		dev->flags |= AIC_DEV_UNCONFIGURED;
 		if (TAILQ_EMPTY(&dev->busyq)
-		 && dev->active == 0
-		 && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0)
+		 && dev->active == 0)
 			ahd_linux_free_device(ahd, dev);
 	}
 	ahd_midlayer_entrypoint_unlock(ahd, &flags);
@@ -1156,7 +1244,7 @@ ahd_linux_select_queue_depth(struct Scsi
 			continue;
 
 		if (device->host == host) {
-			struct	 ahd_linux_device *dev;
+			struct	 aic_linux_device *dev;
 
 			/*
 			 * Since Linux has attached to the device, configure
@@ -1167,13 +1255,13 @@ ahd_linux_select_queue_depth(struct Scsi
 						   device->id, device->lun,
 						   /*alloc*/TRUE);
 			if (dev != NULL) {
-				dev->flags &= ~AHD_DEV_UNCONFIGURED;
+				dev->flags &= ~AIC_DEV_UNCONFIGURED;
 				dev->scsi_device = device;
-				ahd_linux_device_queue_depth(ahd, dev);
+				aic_linux_device_queue_depth(ahd, dev);
 				device->queue_depth = dev->openings
 						    + dev->active;
-				if ((dev->flags & (AHD_DEV_Q_BASIC
-						| AHD_DEV_Q_TAGGED)) == 0) {
+				if ((dev->flags & (AIC_DEV_Q_BASIC
+						| AIC_DEV_Q_TAGGED)) == 0) {
 					/*
 					 * We allow the OS to queue 2 untagged
 					 * transactions to us at any time even
@@ -1262,9 +1350,9 @@ static int
 ahd_linux_abort(Scsi_Cmnd *cmd)
 {
 	struct ahd_softc *ahd;
-	struct ahd_cmd *acmd;
-	struct ahd_cmd *list_acmd;
-	struct ahd_linux_device *dev;
+	struct aic_cmd *acmd;
+	struct aic_cmd *list_acmd;
+	struct aic_linux_device *dev;
 	struct scb *pending_scb;
 	u_long s;
 	u_int  saved_scbptr;
@@ -1282,7 +1370,7 @@ ahd_linux_abort(Scsi_Cmnd *cmd)
 	paused = FALSE;
 	wait = FALSE;
 	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
-	acmd = (struct ahd_cmd *)cmd;
+	acmd = (struct aic_cmd *)cmd;
 
 	printf("%s:%d:%d:%d: Attempting to abort cmd %p:",
 	       ahd_name(ahd), cmd->device->channel, cmd->device->id,
@@ -1341,6 +1429,17 @@ ahd_linux_abort(Scsi_Cmnd *cmd)
 		       cmd->device->lun);
 		TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe);
 		cmd->result = DID_ABORT << 16;
+		/*
+		 * The completion handler believes that
+		 * commands without active timers running
+		 * have lost the race of completing before
+		 * their timer expires.  Since commands in
+		 * our busy queues do not have timers running,
+		 * appease the mid-layer by adding a timer
+		 * now.  This timer will be immediately
+		 * canceled by the midlayer.
+		 */
+		scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout);
 		ahd_linux_queue_cmd_complete(ahd, cmd);
 		retval = SUCCESS;
 		goto done;
@@ -1516,7 +1615,7 @@ done:
 		struct timer_list timer;
 		int ret;
 
-		pending_scb->platform_data->flags |= AHD_SCB_UP_EH_SEM;
+		pending_scb->platform_data->flags |= AIC_SCB_UP_EH_SEM;
 		spin_unlock_irq(&ahd->platform_data->spin_lock);
 		init_timer(&timer);
 		timer.data = (u_long)pending_scb;
@@ -1533,7 +1632,7 @@ done:
 		}
 		spin_lock_irq(&ahd->platform_data->spin_lock);
 	}
-	ahd_schedule_runq(ahd);
+	aic_schedule_runq(ahd);
 	ahd_linux_run_complete_queue(ahd);
 	ahd_midlayer_entrypoint_unlock(ahd, &s);
 	return (retval);
@@ -1554,7 +1653,7 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd)
 {
 	struct	ahd_softc *ahd;
 	struct	scsi_cmnd *recovery_cmd;
-	struct	ahd_linux_device *dev;
+	struct	aic_linux_device *dev;
 	struct	ahd_initiator_tinfo *tinfo;
 	struct	ahd_tmode_tstate *tstate;
 	struct	scb *scb;
@@ -1592,9 +1691,11 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd)
 	recovery_cmd->host_scribble = (char *)scb;
 	scb->io_ctx = recovery_cmd;
 	scb->platform_data->dev = dev;
+	scb->platform_data->flags = 0;
 	scb->sg_count = 0;
-	ahd_set_residual(scb, 0);
-	ahd_set_sense_residual(scb, 0);
+	aic_set_residual(scb, 0);
+	aic_set_sense_residual(scb, 0);
+	scb->platform_data->xfer_len = 0;
 	hscb = scb->hscb;
 	hscb->control = 0;
 	hscb->scsiid = BUILD_SCSIID(ahd, cmd);
@@ -1613,7 +1714,7 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd)
 	LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
 	ahd_queue_scb(ahd, scb);
 
-	scb->platform_data->flags |= AHD_SCB_UP_EH_SEM;
+	scb->platform_data->flags |= AIC_SCB_UP_EH_SEM;
 	spin_unlock_irq(&ahd->platform_data->spin_lock);
 	init_timer(&timer);
 	timer.data = (u_long)scb;
@@ -1629,7 +1730,7 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd)
 		retval = FAILED;
 	}
 	spin_lock_irq(&ahd->platform_data->spin_lock);
-	ahd_schedule_runq(ahd);
+	aic_schedule_runq(ahd);
 	ahd_linux_run_complete_queue(ahd);
 	ahd_midlayer_entrypoint_unlock(ahd, &s);
 	printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval);
@@ -1665,189 +1766,8 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd)
 	return (SUCCESS);
 }
 
-Scsi_Host_Template aic79xx_driver_template = {
-	.module			= THIS_MODULE,
-	.name			= "aic79xx",
-	.proc_info		= ahd_linux_proc_info,
-	.info			= ahd_linux_info,
-	.queuecommand		= ahd_linux_queue,
-	.eh_abort_handler	= ahd_linux_abort,
-	.eh_device_reset_handler = ahd_linux_dev_reset,
-	.eh_bus_reset_handler	= ahd_linux_bus_reset,
-#if defined(__i386__)
-	.bios_param		= ahd_linux_biosparam,
-#endif
-	.can_queue		= AHD_MAX_QUEUE,
-	.this_id		= -1,
-	.cmd_per_lun		= 2,
-	.use_clustering		= ENABLE_CLUSTERING,
-	.slave_alloc		= ahd_linux_slave_alloc,
-	.slave_configure	= ahd_linux_slave_configure,
-	.slave_destroy		= ahd_linux_slave_destroy,
-};
-
-/**************************** Tasklet Handler *********************************/
-
-/*
- * In 2.4.X and above, this routine is called from a tasklet,
- * so we must re-acquire our lock prior to executing this code.
- * In all prior kernels, ahd_schedule_runq() calls this routine
- * directly and ahd_schedule_runq() is called with our lock held.
- */
-static void
-ahd_runq_tasklet(unsigned long data)
-{
-	struct ahd_softc* ahd;
-	struct ahd_linux_device *dev;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	u_long flags;
-#endif
-
-	ahd = (struct ahd_softc *)data;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	ahd_lock(ahd, &flags);
-#endif
-	while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) {
-	
-		TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links);
-		dev->flags &= ~AHD_DEV_ON_RUN_LIST;
-		ahd_linux_check_device_queue(ahd, dev);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-		/* Yeild to our interrupt handler */
-		ahd_unlock(ahd, &flags);
-		ahd_lock(ahd, &flags);
-#endif
-	}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	ahd_unlock(ahd, &flags);
-#endif
-}
-
-/******************************** Bus DMA *************************************/
-int
-ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent,
-		   bus_size_t alignment, bus_size_t boundary,
-		   bus_addr_t lowaddr, bus_addr_t highaddr,
-		   bus_dma_filter_t *filter, void *filterarg,
-		   bus_size_t maxsize, int nsegments,
-		   bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag)
-{
-	bus_dma_tag_t dmat;
-
-	dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT);
-	if (dmat == NULL)
-		return (ENOMEM);
-
-	/*
-	 * Linux is very simplistic about DMA memory.  For now don't
-	 * maintain all specification information.  Once Linux supplies
-	 * better facilities for doing these operations, or the
-	 * needs of this particular driver change, we might need to do
-	 * more here.
-	 */
-	dmat->alignment = alignment;
-	dmat->boundary = boundary;
-	dmat->maxsize = maxsize;
-	*ret_tag = dmat;
-	return (0);
-}
-
-void
-ahd_dma_tag_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat)
-{
-	free(dmat, M_DEVBUF);
-}
-
-int
-ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr,
-		 int flags, bus_dmamap_t *mapp)
-{
-	bus_dmamap_t map;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT);
-	if (map == NULL)
-		return (ENOMEM);
-	/*
-	 * Although we can dma data above 4GB, our
-	 * "consistent" memory is below 4GB for
-	 * space efficiency reasons (only need a 4byte
-	 * address).  For this reason, we have to reset
-	 * our dma mask when doing allocations.
-	 */
-	if (ahd->dev_softc != NULL)
-		ahd_pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF);
-	*vaddr = pci_alloc_consistent(ahd->dev_softc,
-				      dmat->maxsize, &map->bus_addr);
-	if (ahd->dev_softc != NULL)
-		ahd_pci_set_dma_mask(ahd->dev_softc,
-				     ahd->platform_data->hw_dma_mask);
-#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */
-	/*
-	 * At least in 2.2.14, malloc is a slab allocator so all
-	 * allocations are aligned.  We assume for these kernel versions
-	 * that all allocations will be bellow 4Gig, physically contiguous,
-	 * and accessible via DMA by the controller.
-	 */
-	map = NULL; /* No additional information to store */
-	*vaddr = malloc(dmat->maxsize, M_DEVBUF, M_NOWAIT);
-#endif
-	if (*vaddr == NULL)
-		return (ENOMEM);
-	*mapp = map;
-	return(0);
-}
-
-void
-ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat,
-		void* vaddr, bus_dmamap_t map)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	pci_free_consistent(ahd->dev_softc, dmat->maxsize,
-			    vaddr, map->bus_addr);
-#else
-	free(vaddr, M_DEVBUF);
-#endif
-}
-
-int
-ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map,
-		void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb,
-		void *cb_arg, int flags)
-{
-	/*
-	 * Assume for now that this will only be used during
-	 * initialization and not for per-transaction buffer mapping.
-	 */
-	bus_dma_segment_t stack_sg;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	stack_sg.ds_addr = map->bus_addr;
-#else
-#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a))
-	stack_sg.ds_addr = VIRT_TO_BUS(buf);
-#endif
-	stack_sg.ds_len = dmat->maxsize;
-	cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);
-	return (0);
-}
-
-void
-ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
-{
-	/*
-	 * The map may is NULL in our < 2.3.X implementation.
-	 */
-	if (map != NULL)
-		free(map, M_DEVBUF);
-}
-
-int
-ahd_dmamap_unload(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
-{
-	/* Nothing to do */
-	return (0);
-}
+Scsi_Host_Template aic79xx_driver_template = 
+	AIC_TEMPLATE_INITIALIZER("aic79xx", /*max_sectors*/8192);
 
 /********************* Platform Dependent Functions ***************************/
 /*
@@ -1883,19 +1803,19 @@ ahd_softc_comp(struct ahd_softc *lahd, s
 
 	/* Still equal.  Sort by bus/slot/func. */
 	if (aic79xx_reverse_scan != 0)
-		value = ahd_get_pci_bus(lahd->dev_softc)
-		      - ahd_get_pci_bus(rahd->dev_softc);
+		value = aic_get_pci_bus(lahd->dev_softc)
+		      - aic_get_pci_bus(rahd->dev_softc);
 	else
-		value = ahd_get_pci_bus(rahd->dev_softc)
-		      - ahd_get_pci_bus(lahd->dev_softc);
+		value = aic_get_pci_bus(rahd->dev_softc)
+		      - aic_get_pci_bus(lahd->dev_softc);
 	if (value != 0)
 		return (value);
 	if (aic79xx_reverse_scan != 0)
-		value = ahd_get_pci_slot(lahd->dev_softc)
-		      - ahd_get_pci_slot(rahd->dev_softc);
+		value = aic_get_pci_slot(lahd->dev_softc)
+		      - aic_get_pci_slot(rahd->dev_softc);
 	else
-		value = ahd_get_pci_slot(rahd->dev_softc)
-		      - ahd_get_pci_slot(lahd->dev_softc);
+		value = aic_get_pci_slot(rahd->dev_softc)
+		      - aic_get_pci_slot(lahd->dev_softc);
 	if (value != 0)
 		return (value);
 
@@ -2072,9 +1992,16 @@ ahd_linux_register_host(struct ahd_softc
 	char	*new_name;
 	u_long	s;
 	u_long	target;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	int	error;
+#endif
 
 	template->name = ahd->description;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 	host = scsi_host_alloc(template, sizeof(struct ahd_softc *));
+#else
+	host = scsi_register(template, sizeof(struct ahd_softc *));
+#endif
 	if (host == NULL)
 		return (ENOMEM);
 
@@ -2083,8 +2010,12 @@ ahd_linux_register_host(struct ahd_softc
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 	scsi_assign_lock(host, &ahd->platform_data->spin_lock);
 #elif AHD_SCSI_HAS_HOST_LOCK != 0
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,21)
+	host->host_lock = &ahd->platform_data->spin_lock;
+#else
 	host->lock = &ahd->platform_data->spin_lock;
 #endif
+#endif
 	ahd->platform_data->host = host;
 	host->can_queue = AHD_MAX_QUEUE;
 	host->cmd_per_lun = 2;
@@ -2110,13 +2041,20 @@ ahd_linux_register_host(struct ahd_softc
 	ahd_linux_setup_user_rd_strm_settings(ahd);
 	ahd_linux_initialize_scsi_bus(ahd);
 	ahd_unlock(ahd, &s);
+	ahd_sysrq_key = aic_install_sysrq(&ahd_sysrq_op);
+	ahd_spawn_recovery_thread(ahd);
+	if (ahd->platform_data->recovery_pid < 0) {
+		printf("%s: Failed to create recovery thread, error= %d\n",
+		       ahd_name(ahd), ahd->platform_data->recovery_pid);
+		return (-ahd->platform_data->recovery_pid);
+	}
 	ahd->platform_data->dv_pid = kernel_thread(ahd_linux_dv_thread, ahd, 0);
-	ahd_lock(ahd, &s);
 	if (ahd->platform_data->dv_pid < 0) {
 		printf("%s: Failed to create DV thread, error= %d\n",
 		       ahd_name(ahd), ahd->platform_data->dv_pid);
 		return (-ahd->platform_data->dv_pid);
 	}
+	ahd_lock(ahd, &s);
 	/*
 	 * Initially allocate *all* of our linux target objects
 	 * so that the DV thread will scan them all in parallel
@@ -2136,7 +2074,7 @@ ahd_linux_register_host(struct ahd_softc
 		 * It is expected that either an external application
 		 * or a modified kernel will be used to probe this
 		 * ID if it is appropriate.  To accommodate these
-		 * installations, ahc_linux_alloc_target() will allocate
+		 * installations, ahd_linux_alloc_target() will allocate
 		 * for our ID if asked to do so.
 		 */
 		if (target == ahd->our_id) 
@@ -2149,7 +2087,9 @@ ahd_linux_register_host(struct ahd_softc
 	ahd_unlock(ahd, &s);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-	scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */
+	error = scsi_add_host(host, ahd->dev_softc);
+	if (error != 0)
+		return (-error);
 	scsi_scan_host(host);
 #endif
 	return (0);
@@ -2225,17 +2165,6 @@ ahd_linux_initialize_scsi_bus(struct ahd
 		ahd_update_neg_request(ahd, &devinfo, tstate,
 				       tinfo, AHD_NEG_ALWAYS);
 	}
-	/* Give the bus some time to recover */
-	if ((ahd->flags & AHD_RESET_BUS_A) != 0) {
-		ahd_freeze_simq(ahd);
-		init_timer(&ahd->platform_data->reset_timer);
-		ahd->platform_data->reset_timer.data = (u_long)ahd;
-		ahd->platform_data->reset_timer.expires =
-		    jiffies + (AIC79XX_RESET_DELAY * HZ)/1000;
-		ahd->platform_data->reset_timer.function =
-		    (ahd_linux_callback_t *)ahd_release_simq;
-		add_timer(&ahd->platform_data->reset_timer);
-	}
 }
 
 int
@@ -2248,24 +2177,32 @@ ahd_platform_alloc(struct ahd_softc *ahd
 	memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data));
 	TAILQ_INIT(&ahd->platform_data->completeq);
 	TAILQ_INIT(&ahd->platform_data->device_runq);
-	ahd->platform_data->irq = AHD_LINUX_NOIRQ;
+	ahd->platform_data->irq = AIC_LINUX_NOIRQ;
 	ahd->platform_data->hw_dma_mask = 0xFFFFFFFF;
 	ahd_lockinit(ahd);
 	ahd_done_lockinit(ahd);
+	init_timer(&ahd->platform_data->bus_settle_timer);
+	ahd->platform_data->bus_settle_timer.data = (u_long)ahd;
+	ahd->platform_data->bus_settle_timer.function =
+	    (aic_linux_callback_t *)aic_bus_settle_complete;
 	init_timer(&ahd->platform_data->completeq_timer);
 	ahd->platform_data->completeq_timer.data = (u_long)ahd;
 	ahd->platform_data->completeq_timer.function =
-	    (ahd_linux_callback_t *)ahd_linux_thread_run_complete_queue;
+	    (aic_linux_callback_t *)ahd_linux_thread_run_complete_queue;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
 	init_MUTEX_LOCKED(&ahd->platform_data->eh_sem);
 	init_MUTEX_LOCKED(&ahd->platform_data->dv_sem);
 	init_MUTEX_LOCKED(&ahd->platform_data->dv_cmd_sem);
+	init_MUTEX_LOCKED(&ahd->platform_data->recovery_sem);
+	init_MUTEX_LOCKED(&ahd->platform_data->recovery_ending_sem);
 #else
 	ahd->platform_data->eh_sem = MUTEX_LOCKED;
 	ahd->platform_data->dv_sem = MUTEX_LOCKED;
 	ahd->platform_data->dv_cmd_sem = MUTEX_LOCKED;
+	ahd->platform_data->recovery_sem = MUTEX_LOCKED;
+	ahd->platform_data->recovery_ending_sem = MUTEX_LOCKED;
 #endif
-	ahd_setup_runq_tasklet(ahd);
+	aic_setup_tasklets(ahd);
 	ahd->seltime = (aic79xx_seltime & 0x3) << 4;
 	return (0);
 }
@@ -2273,19 +2210,22 @@ ahd_platform_alloc(struct ahd_softc *ahd
 void
 ahd_platform_free(struct ahd_softc *ahd)
 {
-	struct ahd_linux_target *targ;
-	struct ahd_linux_device *dev;
+	struct aic_linux_target *targ;
+	struct aic_linux_device *dev;
 	int i, j;
 
+	aic_remove_sysrq(ahd_sysrq_key, &ahd_sysrq_op);
 	if (ahd->platform_data != NULL) {
 		del_timer_sync(&ahd->platform_data->completeq_timer);
 		ahd_linux_kill_dv_thread(ahd);
-		ahd_teardown_runq_tasklet(ahd);
+		aic_teardown_tasklets(ahd);
 		if (ahd->platform_data->host != NULL) {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 			scsi_remove_host(ahd->platform_data->host);
-#endif
 			scsi_host_put(ahd->platform_data->host);
+#else
+			scsi_unregister(ahd->platform_data->host);
+#endif
 		}
 
 		/* destroy all of the device and target objects */
@@ -2299,6 +2239,7 @@ ahd_platform_free(struct ahd_softc *ahd)
 					if (targ->devices[j] == NULL)
 						continue;
 					dev = targ->devices[j];
+					del_timer_sync(&dev->timer);
 					ahd_linux_free_device(ahd, dev);
 				}
 				/*
@@ -2309,7 +2250,7 @@ ahd_platform_free(struct ahd_softc *ahd)
 			}
 		}
 
-		if (ahd->platform_data->irq != AHD_LINUX_NOIRQ)
+		if (ahd->platform_data->irq != AIC_LINUX_NOIRQ)
 			free_irq(ahd->platform_data->irq, ahd);
 		if (ahd->tags[0] == BUS_SPACE_PIO
 		 && ahd->bshs[0].ioport != 0)
@@ -2377,7 +2318,7 @@ void
 ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
 		      ahd_queue_alg alg)
 {
-	struct ahd_linux_device *dev;
+	struct aic_linux_device *dev;
 	int was_queuing;
 	int now_queuing;
 
@@ -2386,27 +2327,27 @@ ahd_platform_set_tags(struct ahd_softc *
 				   devinfo->lun, /*alloc*/FALSE);
 	if (dev == NULL)
 		return;
-	was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED);
+	was_queuing = dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED);
 	switch (alg) {
 	default:
 	case AHD_QUEUE_NONE:
 		now_queuing = 0;
 		break; 
 	case AHD_QUEUE_BASIC:
-		now_queuing = AHD_DEV_Q_BASIC;
+		now_queuing = AIC_DEV_Q_BASIC;
 		break;
 	case AHD_QUEUE_TAGGED:
-		now_queuing = AHD_DEV_Q_TAGGED;
+		now_queuing = AIC_DEV_Q_TAGGED;
 		break;
 	}
-	if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) == 0
+	if ((dev->flags & AIC_DEV_FREEZE_TIL_EMPTY) == 0
 	 && (was_queuing != now_queuing)
 	 && (dev->active != 0)) {
-		dev->flags |= AHD_DEV_FREEZE_TIL_EMPTY;
+		dev->flags |= AIC_DEV_FREEZE_TIL_EMPTY;
 		dev->qfrozen++;
 	}
 
-	dev->flags &= ~(AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED|AHD_DEV_PERIODIC_OTAG);
+	dev->flags &= ~(AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED|AIC_DEV_PERIODIC_OTAG);
 	if (now_queuing) {
 		u_int usertags;
 
@@ -2426,11 +2367,11 @@ ahd_platform_set_tags(struct ahd_softc *
 			 */
 			dev->openings = 1;
 		} else if (alg == AHD_QUEUE_TAGGED) {
-			dev->flags |= AHD_DEV_Q_TAGGED;
+			dev->flags |= AIC_DEV_Q_TAGGED;
 			if (aic79xx_periodic_otag != 0)
-				dev->flags |= AHD_DEV_PERIODIC_OTAG;
+				dev->flags |= AIC_DEV_PERIODIC_OTAG;
 		} else
-			dev->flags |= AHD_DEV_Q_BASIC;
+			dev->flags |= AIC_DEV_Q_BASIC;
 	} else {
 		/* We can only have one opening. */
 		dev->maxtags = 0;
@@ -2438,13 +2379,13 @@ ahd_platform_set_tags(struct ahd_softc *
 	}
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 	if (dev->scsi_device != NULL) {
-		switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
-		case AHD_DEV_Q_BASIC:
+		switch ((dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED))) {
+		case AIC_DEV_Q_BASIC:
 			scsi_adjust_queue_depth(dev->scsi_device,
 						MSG_SIMPLE_TASK,
 						dev->openings + dev->active);
 			break;
-		case AHD_DEV_Q_TAGGED:
+		case AIC_DEV_Q_TAGGED:
 			scsi_adjust_queue_depth(dev->scsi_device,
 						MSG_ORDERED_TASK,
 						dev->openings + dev->active);
@@ -2497,9 +2438,9 @@ ahd_platform_abort_scbs(struct ahd_softc
 	for (; targ < maxtarg; targ++) {
 
 		for (; clun < maxlun; clun++) {
-			struct ahd_linux_device *dev;
-			struct ahd_busyq *busyq;
-			struct ahd_cmd *acmd;
+			struct aic_linux_device *dev;
+			struct aic_busyq *busyq;
+			struct aic_cmd *acmd;
 
 			dev = ahd_linux_get_device(ahd, /*chan*/0, targ,
 						   clun, /*alloc*/FALSE);
@@ -2515,6 +2456,18 @@ ahd_platform_abort_scbs(struct ahd_softc
 					     acmd_links.tqe);
 				count++;
 				cmd->result = status << 16;
+				/*
+				 * The completion handler believes that
+				 * commands without active timers running
+				 * have lost the race of completing before
+				 * their timer expires.  Since commands in
+				 * our busy queues do not have timers running,
+				 * appease the mid-layer by adding a timer
+				 * now.  This timer will be immediately
+				 * canceled by the midlayer.
+				 */
+				scsi_add_timer(cmd, 60*HZ,
+					       aic_linux_midlayer_timeout);
 				ahd_linux_queue_cmd_complete(ahd, cmd);
 			}
 		}
@@ -2530,7 +2483,7 @@ ahd_linux_thread_run_complete_queue(stru
 
 	ahd_lock(ahd, &flags);
 	del_timer(&ahd->platform_data->completeq_timer);
-	ahd->platform_data->flags &= ~AHD_RUN_CMPLT_Q_TIMER;
+	ahd->platform_data->flags &= ~AIC_RUN_CMPLT_Q_TIMER;
 	ahd_linux_run_complete_queue(ahd);
 	ahd_unlock(ahd, &flags);
 }
@@ -2543,14 +2496,23 @@ ahd_linux_start_dv(struct ahd_softc *ahd
 	 * Freeze the simq and signal ahd_linux_queue to not let any
 	 * more commands through
 	 */
-	if ((ahd->platform_data->flags & AHD_DV_ACTIVE) == 0) {
+	if ((ahd->platform_data->flags & AIC_DV_ACTIVE) == 0) {
 #ifdef AHD_DEBUG
 		if (ahd_debug & AHD_SHOW_DV)
 			printf("%s: Starting DV\n", ahd_name(ahd));
 #endif
 
-		ahd->platform_data->flags |= AHD_DV_ACTIVE;
-		ahd_freeze_simq(ahd);
+		ahd->platform_data->flags |= AIC_DV_ACTIVE;
+
+		/*
+		 * Prevent upper layer from sending any
+		 * commands to us.
+		 */
+		aic_freeze_simq(ahd);
+		scsi_block_requests(ahd->platform_data->host);
+		ahd_platform_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
+					CAM_LUN_WILDCARD, SCB_LIST_NULL,
+					ROLE_INITIATOR, CAM_REQUEUE_REQ);
 
 		/* Wake up the DV kthread */
 		up(&ahd->platform_data->dv_sem);
@@ -2589,6 +2551,7 @@ ahd_linux_dv_thread(void *data)
 	unlock_kernel();
 
 	while (1) {
+
 		/*
 		 * Use down_interruptible() rather than down() to
 		 * avoid inclusion in the load average.
@@ -2597,7 +2560,7 @@ ahd_linux_dv_thread(void *data)
 
 		/* Check to see if we've been signaled to exit */
 		ahd_lock(ahd, &s);
-		if ((ahd->platform_data->flags & AHD_DV_SHUTDOWN) != 0) {
+		if ((ahd->platform_data->flags & AIC_DV_SHUTDOWN) != 0) {
 			ahd_unlock(ahd, &s);
 			break;
 		}
@@ -2614,7 +2577,7 @@ ahd_linux_dv_thread(void *data)
 		 */
 		ahd_lock(ahd, &s);
 		while (LIST_FIRST(&ahd->pending_scbs) != NULL) {
-			ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_EMPTY;
+			ahd->platform_data->flags |= AIC_DV_WAIT_SIMQ_EMPTY;
 			ahd_unlock(ahd, &s);
 			down_interruptible(&ahd->platform_data->dv_sem);
 			ahd_lock(ahd, &s);
@@ -2624,8 +2587,8 @@ ahd_linux_dv_thread(void *data)
 		 * Wait for the SIMQ to be released so that DV is the
 		 * only reason the queue is frozen.
 		 */
-		while (AHD_DV_SIMQ_FROZEN(ahd) == 0) {
-			ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE;
+		while (AIC_DV_SIMQ_FROZEN(ahd) == 0) {
+			ahd->platform_data->flags |= AIC_DV_WAIT_SIMQ_RELEASE;
 			ahd_unlock(ahd, &s);
 			down_interruptible(&ahd->platform_data->dv_sem);
 			ahd_lock(ahd, &s);
@@ -2636,14 +2599,17 @@ ahd_linux_dv_thread(void *data)
 			ahd_linux_dv_target(ahd, target);
 
 		ahd_lock(ahd, &s);
-		ahd->platform_data->flags &= ~AHD_DV_ACTIVE;
-		ahd_unlock(ahd, &s);
+		ahd->platform_data->flags &= ~AIC_DV_ACTIVE;
 
 		/*
 		 * Release the SIMQ so that normal commands are
 		 * allowed to continue on the bus.
 		 */
-		ahd_release_simq(ahd);
+		aic_release_simq_locked(ahd);
+
+		ahd_unlock(ahd, &s);
+
+		scsi_unblock_requests(ahd->platform_data->host);
 	}
 	up(&ahd->platform_data->eh_sem);
 	return (0);
@@ -2656,7 +2622,7 @@ ahd_linux_kill_dv_thread(struct ahd_soft
 
 	ahd_lock(ahd, &s);
 	if (ahd->platform_data->dv_pid != 0) {
-		ahd->platform_data->flags |= AHD_DV_SHUTDOWN;
+		ahd->platform_data->flags |= AIC_DV_SHUTDOWN;
 		ahd_unlock(ahd, &s);
 		up(&ahd->platform_data->dv_sem);
 
@@ -2676,10 +2642,10 @@ ahd_linux_kill_dv_thread(struct ahd_soft
 		/*
 		 * Mark the dv thread as already dead.  This
 		 * avoids attempting to kill it a second time.
-		 * This is necessary because we must kill the
-		 * DV thread before calling ahd_free() in the
+		 * This is necessary because we must kill our
+		 * threads before calling ahd_free() in the
 		 * module shutdown case to avoid bogus locking
-		 * in the SCSI mid-layer, but we ahd_free() is
+		 * in the SCSI mid-layer, but when ahd_free() is
 		 * called without killing the DV thread in the
 		 * instance detach case, so ahd_platform_free()
 		 * calls us again to verify that the DV thread
@@ -2699,10 +2665,10 @@ ahd_linux_kill_dv_thread(struct ahd_soft
 	ahd_set_dv_state(ahd, targ, newstate, __LINE__)
 
 static __inline void
-ahd_set_dv_state(struct ahd_softc *ahd, struct ahd_linux_target *targ,
-		 ahd_dv_state newstate, u_int line)
+ahd_set_dv_state(struct ahd_softc *ahd, struct aic_linux_target *targ,
+		 aic_dv_state newstate, u_int line)
 {
-	ahd_dv_state oldstate;
+	aic_dv_state oldstate;
 
 	oldstate = targ->dv_state;
 #ifdef AHD_DEBUG
@@ -2722,7 +2688,7 @@ static void
 ahd_linux_dv_target(struct ahd_softc *ahd, u_int target_offset)
 {
 	struct	 ahd_devinfo devinfo;
-	struct	 ahd_linux_target *targ;
+	struct	 aic_linux_target *targ;
 	struct	 scsi_cmnd *cmd;
 	struct	 scsi_device *scsi_dev;
 	struct	 scsi_sense_data *sense;
@@ -2736,7 +2702,7 @@ ahd_linux_dv_target(struct ahd_softc *ah
 	echo_size = 0;
 	ahd_lock(ahd, &s);
 	targ = ahd->platform_data->targets[target_offset];
-	if (targ == NULL || (targ->flags & AHD_DV_REQUIRED) == 0) {
+	if (targ == NULL || (targ->flags & AIC_DV_REQUIRED) == 0) {
 		ahd_unlock(ahd, &s);
 		return;
 	}
@@ -2759,14 +2725,14 @@ ahd_linux_dv_target(struct ahd_softc *ah
 	scsi_dev->channel = devinfo.channel - 'A';
 	ahd->platform_data->dv_scsi_dev = scsi_dev;
 
-	AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_SHORT_ASYNC);
+	AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_INQ_SHORT_ASYNC);
 
-	while (targ->dv_state != AHD_DV_STATE_EXIT) {
+	while (targ->dv_state != AIC_DV_STATE_EXIT) {
 		timeout = AHD_LINUX_DV_TIMEOUT;
 		switch (targ->dv_state) {
-		case AHD_DV_STATE_INQ_SHORT_ASYNC:
-		case AHD_DV_STATE_INQ_ASYNC:
-		case AHD_DV_STATE_INQ_ASYNC_VERIFY:
+		case AIC_DV_STATE_INQ_SHORT_ASYNC:
+		case AIC_DV_STATE_INQ_ASYNC:
+		case AIC_DV_STATE_INQ_ASYNC_VERIFY:
 			/*
 			 * Set things to async narrow to reduce the
 			 * chance that the INQ will fail.
@@ -2778,36 +2744,36 @@ ahd_linux_dv_target(struct ahd_softc *ah
 				      AHD_TRANS_GOAL, /*paused*/FALSE);
 			ahd_unlock(ahd, &s);
 			timeout = 10 * HZ;
-			targ->flags &= ~AHD_INQ_VALID;
+			targ->flags &= ~AIC_INQ_VALID;
 			/* FALLTHROUGH */
-		case AHD_DV_STATE_INQ_VERIFY:
+		case AIC_DV_STATE_INQ_VERIFY:
 		{
 			u_int inq_len;
 
-			if (targ->dv_state == AHD_DV_STATE_INQ_SHORT_ASYNC)
+			if (targ->dv_state == AIC_DV_STATE_INQ_SHORT_ASYNC)
 				inq_len = AHD_LINUX_DV_INQ_SHORT_LEN;
 			else
 				inq_len = targ->inq_data->additional_length + 5;
 			ahd_linux_dv_inq(ahd, cmd, &devinfo, targ, inq_len);
 			break;
 		}
-		case AHD_DV_STATE_TUR:
-		case AHD_DV_STATE_BUSY:
+		case AIC_DV_STATE_TUR:
+		case AIC_DV_STATE_BUSY:
 			timeout = 5 * HZ;
 			ahd_linux_dv_tur(ahd, cmd, &devinfo);
 			break;
-		case AHD_DV_STATE_REBD:
+		case AIC_DV_STATE_REBD:
 			ahd_linux_dv_rebd(ahd, cmd, &devinfo, targ);
 			break;
-		case AHD_DV_STATE_WEB:
+		case AIC_DV_STATE_WEB:
 			ahd_linux_dv_web(ahd, cmd, &devinfo, targ);
 			break;
 
-		case AHD_DV_STATE_REB:
+		case AIC_DV_STATE_REB:
 			ahd_linux_dv_reb(ahd, cmd, &devinfo, targ);
 			break;
 
-		case AHD_DV_STATE_SU:
+		case AIC_DV_STATE_SU:
 			ahd_linux_dv_su(ahd, cmd, &devinfo, targ);
 			timeout = 50 * HZ;
 			break;
@@ -2819,8 +2785,6 @@ ahd_linux_dv_target(struct ahd_softc *ah
 		}
 
 		/* Queue the command and wait for it to complete */
-		/* Abuse eh_timeout in the scsi_cmnd struct for our purposes */
-		init_timer(&cmd->eh_timeout);
 #ifdef AHD_DEBUG
 		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
 			/*
@@ -2830,7 +2794,9 @@ ahd_linux_dv_target(struct ahd_softc *ah
 			 */
 			timeout += HZ;
 #endif
-		scsi_add_timer(cmd, timeout, ahd_linux_dv_timeout);
+		init_timer(&cmd->eh_timeout);
+		cmd->timeout_per_command = timeout;
+
 		/*
 		 * In 2.5.X, it is assumed that all calls from the
 		 * "midlayer" (which we are emulating) will have the
@@ -2849,13 +2815,14 @@ ahd_linux_dv_target(struct ahd_softc *ah
 		spin_unlock_irqrestore(&io_request_lock, s);
 #endif
 		down_interruptible(&ahd->platform_data->dv_cmd_sem);
+
 		/*
 		 * Wait for the SIMQ to be released so that DV is the
 		 * only reason the queue is frozen.
 		 */
 		ahd_lock(ahd, &s);
-		while (AHD_DV_SIMQ_FROZEN(ahd) == 0) {
-			ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE;
+		while (AIC_DV_SIMQ_FROZEN(ahd) == 0) {
+			ahd->platform_data->flags |= AIC_DV_WAIT_SIMQ_RELEASE;
 			ahd_unlock(ahd, &s);
 			down_interruptible(&ahd->platform_data->dv_sem);
 			ahd_lock(ahd, &s);
@@ -2866,7 +2833,7 @@ ahd_linux_dv_target(struct ahd_softc *ah
 	}
 
 out:
-	if ((targ->flags & AHD_INQ_VALID) != 0
+	if ((targ->flags & AIC_INQ_VALID) != 0
 	 && ahd_linux_get_device(ahd, devinfo.channel - 'A',
 				 devinfo.target, devinfo.lun,
 				 /*alloc*/FALSE) == NULL) {
@@ -2877,7 +2844,7 @@ out:
 		 * parameters found in the inquiry string.
 		 */
 		ahd_linux_filter_inquiry(ahd, &devinfo);
-		if ((targ->flags & (AHD_BASIC_DV|AHD_ENHANCED_DV)) != 0) {
+		if ((targ->flags & (AIC_BASIC_DV|AIC_ENHANCED_DV)) != 0) {
 			ahd_print_devinfo(ahd, &devinfo);
 			printf("DV failed to configure device.  "
 			       "Please file a bug report against "
@@ -2902,7 +2869,7 @@ out:
 		free(targ->dv_buffer1, M_DEVBUF);
 		targ->dv_buffer1 = NULL;
 	}
-	targ->flags &= ~AHD_DV_REQUIRED;
+	targ->flags &= ~AIC_DV_REQUIRED;
 	if (targ->refcount == 0)
 		ahd_linux_free_target(ahd, targ);
 	ahd_unlock(ahd, &s);
@@ -2911,13 +2878,13 @@ out:
 static void
 ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
 			struct ahd_devinfo *devinfo,
-			struct ahd_linux_target *targ)
+			struct aic_linux_target *targ)
 {
 	u_int32_t status;
 
 	status = aic_error_action(cmd, targ->inq_data,
-				  ahd_cmd_get_transaction_status(cmd),
-				  ahd_cmd_get_scsi_status(cmd));
+				  aic_cmd_get_transaction_status(cmd),
+				  aic_cmd_get_scsi_status(cmd));
 
 	
 #ifdef AHD_DEBUG
@@ -2930,8 +2897,8 @@ ahd_linux_dv_transition(struct ahd_softc
 #endif
 
 	switch (targ->dv_state) {
-	case AHD_DV_STATE_INQ_SHORT_ASYNC:
-	case AHD_DV_STATE_INQ_ASYNC:
+	case AIC_DV_STATE_INQ_SHORT_ASYNC:
+	case AIC_DV_STATE_INQ_ASYNC:
 		switch (status & SS_MASK) {
 		case SS_NOP:
 		{
@@ -2940,21 +2907,21 @@ ahd_linux_dv_transition(struct ahd_softc
 		}
 		case SS_INQ_REFRESH:
 			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		case SS_TUR:
 		case SS_RETRY:
 			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ)
 				targ->dv_state_retry--;
 			if ((status & SS_ERRMASK) == EBUSY)
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
+				AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_BUSY);
 			if (targ->dv_state_retry < 10)
 				break;
 			/* FALLTHROUGH */
 		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+			AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 #ifdef AHD_DEBUG
 			if (ahd_debug & AHD_SHOW_DV) {
 				ahd_print_devinfo(ahd, devinfo);
@@ -2964,7 +2931,7 @@ ahd_linux_dv_transition(struct ahd_softc
 			break;
 		}
 		break;
-	case AHD_DV_STATE_INQ_ASYNC_VERIFY:
+	case AIC_DV_STATE_INQ_ASYNC_VERIFY:
 		switch (status & SS_MASK) {
 		case SS_NOP:
 		{
@@ -2978,12 +2945,12 @@ ahd_linux_dv_transition(struct ahd_softc
 				 * Try from the top again.
 				 */
 				AHD_SET_DV_STATE(ahd, targ,
-						 AHD_DV_STATE_INQ_SHORT_ASYNC);
+						 AIC_DV_STATE_INQ_SHORT_ASYNC);
 				break;
 			}
 
 			AHD_SET_DV_STATE(ahd, targ, targ->dv_state+1);
-			targ->flags |= AHD_INQ_VALID;
+			targ->flags |= AIC_INQ_VALID;
 			if (ahd_linux_user_dv_setting(ahd) == 0)
 				break;
 
@@ -2996,33 +2963,33 @@ ahd_linux_dv_transition(struct ahd_softc
 			default:
 			case SID_SPI_CLOCK_ST:
 				/* Assume only basic DV is supported. */
-				targ->flags |= AHD_BASIC_DV;
+				targ->flags |= AIC_BASIC_DV;
 				break;
 			case SID_SPI_CLOCK_DT:
 			case SID_SPI_CLOCK_DT_ST:
-				targ->flags |= AHD_ENHANCED_DV;
+				targ->flags |= AIC_ENHANCED_DV;
 				break;
 			}
 			break;
 		}
 		case SS_INQ_REFRESH:
 			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		case SS_TUR:
 		case SS_RETRY:
 			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ)
 				targ->dv_state_retry--;
 
 			if ((status & SS_ERRMASK) == EBUSY)
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
+				AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_BUSY);
 			if (targ->dv_state_retry < 10)
 				break;
 			/* FALLTHROUGH */
 		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+			AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 #ifdef AHD_DEBUG
 			if (ahd_debug & AHD_SHOW_DV) {
 				ahd_print_devinfo(ahd, devinfo);
@@ -3032,14 +2999,14 @@ ahd_linux_dv_transition(struct ahd_softc
 			break;
 		}
 		break;
-	case AHD_DV_STATE_INQ_VERIFY:
+	case AIC_DV_STATE_INQ_VERIFY:
 		switch (status & SS_MASK) {
 		case SS_NOP:
 		{
 
 			if (memcmp(targ->inq_data, targ->dv_buffer,
 				   AHD_LINUX_DV_INQ_LEN) == 0) {
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+				AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 				break;
 			}
 
@@ -3061,7 +3028,7 @@ ahd_linux_dv_transition(struct ahd_softc
 #endif
 
 			if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+				AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 				break;
 			}
 			/*
@@ -3074,18 +3041,18 @@ ahd_linux_dv_transition(struct ahd_softc
 		}
 		case SS_INQ_REFRESH:
 			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		case SS_TUR:
 		case SS_RETRY:
 			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ) {
 				targ->dv_state_retry--;
 			} else if ((status & SSQ_FALLBACK) != 0) {
 				if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
 					AHD_SET_DV_STATE(ahd, targ,
-							 AHD_DV_STATE_EXIT);
+							 AIC_DV_STATE_EXIT);
 					break;
 				}
 				/*
@@ -3094,12 +3061,12 @@ ahd_linux_dv_transition(struct ahd_softc
 				 */
 				targ->dv_state_retry = 0;
 			} else if ((status & SS_ERRMASK) == EBUSY)
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
+				AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_BUSY);
 			if (targ->dv_state_retry < 10)
 				break;
 			/* FALLTHROUGH */
 		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+			AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 #ifdef AHD_DEBUG
 			if (ahd_debug & AHD_SHOW_DV) {
 				ahd_print_devinfo(ahd, devinfo);
@@ -3110,33 +3077,33 @@ ahd_linux_dv_transition(struct ahd_softc
 		}
 		break;
 
-	case AHD_DV_STATE_TUR:
+	case AIC_DV_STATE_TUR:
 		switch (status & SS_MASK) {
 		case SS_NOP:
-			if ((targ->flags & AHD_BASIC_DV) != 0) {
+			if ((targ->flags & AIC_BASIC_DV) != 0) {
 				ahd_linux_filter_inquiry(ahd, devinfo);
 				AHD_SET_DV_STATE(ahd, targ,
-						 AHD_DV_STATE_INQ_VERIFY);
-			} else if ((targ->flags & AHD_ENHANCED_DV) != 0) {
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REBD);
+						 AIC_DV_STATE_INQ_VERIFY);
+			} else if ((targ->flags & AIC_ENHANCED_DV) != 0) {
+				AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_REBD);
 			} else {
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+				AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 			}
 			break;
 		case SS_RETRY:
 		case SS_TUR:
 			if ((status & SS_ERRMASK) == EBUSY) {
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
+				AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_BUSY);
 				break;
 			}
 			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ) {
 				targ->dv_state_retry--;
 			} else if ((status & SSQ_FALLBACK) != 0) {
 				if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
 					AHD_SET_DV_STATE(ahd, targ,
-							 AHD_DV_STATE_EXIT);
+							 AIC_DV_STATE_EXIT);
 					break;
 				}
 				/*
@@ -3152,7 +3119,7 @@ ahd_linux_dv_transition(struct ahd_softc
 					printf("DV TUR reties exhausted\n");
 				}
 #endif
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+				AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 				break;
 			}
 			if (status & SSQ_DELAY)
@@ -3160,25 +3127,25 @@ ahd_linux_dv_transition(struct ahd_softc
 
 			break;
 		case SS_START:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_SU);
+			AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_SU);
 			break;
 		case SS_INQ_REFRESH:
 			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+			AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 			break;
 		}
 		break;
 
-	case AHD_DV_STATE_REBD:
+	case AIC_DV_STATE_REBD:
 		switch (status & SS_MASK) {
 		case SS_NOP:
 		{
 			uint32_t echo_size;
 
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB);
+			AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_WEB);
 			echo_size = scsi_3btoul(&targ->dv_buffer[1]);
 			echo_size &= 0x1FFF;
 #ifdef AHD_DEBUG
@@ -3188,7 +3155,17 @@ ahd_linux_dv_transition(struct ahd_softc
 			}
 #endif
 			if (echo_size == 0) {
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+				/*
+				 * Fall back to basic DV.
+				 */
+				if (bootverbose) {
+					ahd_print_devinfo(ahd, devinfo);
+					printf("Echo Buffer unavailable.  "
+					       "Performing basic DV.\n");
+				}
+				targ->flags &= ~AIC_ENHANCED_DV;
+				targ->flags |= AIC_BASIC_DV;
+				AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_TUR);
 				break;
 			}
 
@@ -3203,11 +3180,11 @@ ahd_linux_dv_transition(struct ahd_softc
 		}
 		case SS_INQ_REFRESH:
 			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		case SS_RETRY:
 			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ)
 				targ->dv_state_retry--;
 			if (targ->dv_state_retry <= 10)
@@ -3226,30 +3203,30 @@ ahd_linux_dv_transition(struct ahd_softc
 			 * and try level 1 DV.
 			 */
 			ahd_linux_filter_inquiry(ahd, devinfo);
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_VERIFY);
+			AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_INQ_VERIFY);
 			targ->dv_echo_size = 0;
 			break;
 		}
 		break;
 
-	case AHD_DV_STATE_WEB:
+	case AIC_DV_STATE_WEB:
 		switch (status & SS_MASK) {
 		case SS_NOP:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REB);
+			AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_REB);
 			break;
 		case SS_INQ_REFRESH:
 			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		case SS_RETRY:
 			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ) {
 				targ->dv_state_retry--;
 			} else if ((status & SSQ_FALLBACK) != 0) {
 				if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
 					AHD_SET_DV_STATE(ahd, targ,
-							 AHD_DV_STATE_EXIT);
+							 AIC_DV_STATE_EXIT);
 					break;
 				}
 				/*
@@ -3268,22 +3245,22 @@ ahd_linux_dv_transition(struct ahd_softc
 			}
 #endif
 		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+			AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 			break;
 		}
 		break;
 
-	case AHD_DV_STATE_REB:
+	case AIC_DV_STATE_REB:
 		switch (status & SS_MASK) {
 		case SS_NOP:
 			if (memcmp(targ->dv_buffer, targ->dv_buffer1,
 				   targ->dv_echo_size) != 0) {
 				if (ahd_linux_dv_fallback(ahd, devinfo) != 0)
 					AHD_SET_DV_STATE(ahd, targ,
-							 AHD_DV_STATE_EXIT);
+							 AIC_DV_STATE_EXIT);
 				else
 					AHD_SET_DV_STATE(ahd, targ,
-							 AHD_DV_STATE_WEB);
+							 AIC_DV_STATE_WEB);
 				break;
 			}
 			
@@ -3295,24 +3272,24 @@ ahd_linux_dv_transition(struct ahd_softc
 				free(targ->dv_buffer1, M_DEVBUF);
 				targ->dv_buffer1 = NULL;
 			}
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+			AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 			break;
 		case SS_INQ_REFRESH:
 			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		case SS_RETRY:
 			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ) {
 				targ->dv_state_retry--;
 			} else if ((status & SSQ_FALLBACK) != 0) {
 				if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
 					AHD_SET_DV_STATE(ahd, targ,
-							 AHD_DV_STATE_EXIT);
+							 AIC_DV_STATE_EXIT);
 					break;
 				}
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB);
+				AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_WEB);
 			}
 			if (targ->dv_state_retry <= 10) {
 				if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0)
@@ -3327,35 +3304,35 @@ ahd_linux_dv_transition(struct ahd_softc
 #endif
 			/* FALLTHROUGH */
 		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+			AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 			break;
 		}
 		break;
 
-	case AHD_DV_STATE_SU:
+	case AIC_DV_STATE_SU:
 		switch (status & SS_MASK) {
 		case SS_NOP:
 		case SS_INQ_REFRESH:
 			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+			AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 			break;
 		}
 		break;
 
-	case AHD_DV_STATE_BUSY:
+	case AIC_DV_STATE_BUSY:
 		switch (status & SS_MASK) {
 		case SS_NOP:
 		case SS_INQ_REFRESH:
 			AHD_SET_DV_STATE(ahd, targ,
-					 AHD_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		case SS_TUR:
 		case SS_RETRY:
 			AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
-			if (ahd_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ) {
 				targ->dv_state_retry--;
 			} else if (targ->dv_state_retry < 60) {
@@ -3368,11 +3345,11 @@ ahd_linux_dv_transition(struct ahd_softc
 					printf("DV BUSY reties exhausted\n");
 				}
 #endif
-				AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+				AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 			}
 			break;
 		default:
-			AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+			AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 			break;
 		}
 		break;
@@ -3380,7 +3357,7 @@ ahd_linux_dv_transition(struct ahd_softc
 	default:
 		printf("%s: Invalid DV completion state %d\n", ahd_name(ahd),
 		       targ->dv_state);
-		AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+		AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT);
 		break;
 	}
 }
@@ -3400,7 +3377,7 @@ ahd_linux_dv_fill_cmd(struct ahd_softc *
  */
 static void
 ahd_linux_dv_inq(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-		 struct ahd_devinfo *devinfo, struct ahd_linux_target *targ,
+		 struct ahd_devinfo *devinfo, struct aic_linux_target *targ,
 		 u_int request_length)
 {
 
@@ -3413,7 +3390,7 @@ ahd_linux_dv_inq(struct ahd_softc *ahd, 
 	if (targ->inq_data == NULL)
 		targ->inq_data = malloc(AHD_LINUX_DV_INQ_LEN,
 					M_DEVBUF, M_WAITOK);
-	if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC) {
+	if (targ->dv_state > AIC_DV_STATE_INQ_ASYNC) {
 		if (targ->dv_buffer != NULL)
 			free(targ->dv_buffer, M_DEVBUF);
 		targ->dv_buffer = malloc(AHD_LINUX_DV_INQ_LEN,
@@ -3426,7 +3403,7 @@ ahd_linux_dv_inq(struct ahd_softc *ahd, 
 	cmd->cmnd[0] = INQUIRY;
 	cmd->cmnd[4] = request_length;
 	cmd->request_bufflen = request_length;
-	if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC)
+	if (targ->dv_state > AIC_DV_STATE_INQ_ASYNC)
 		cmd->request_buffer = targ->dv_buffer;
 	else
 		cmd->request_buffer = targ->inq_data;
@@ -3455,7 +3432,7 @@ ahd_linux_dv_tur(struct ahd_softc *ahd, 
 
 static void
 ahd_linux_dv_rebd(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-		 struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
+		 struct ahd_devinfo *devinfo, struct aic_linux_target *targ)
 {
 
 #ifdef AHD_DEBUG
@@ -3480,7 +3457,7 @@ ahd_linux_dv_rebd(struct ahd_softc *ahd,
 
 static void
 ahd_linux_dv_web(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-		 struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
+		 struct ahd_devinfo *devinfo, struct aic_linux_target *targ)
 {
 
 #ifdef AHD_DEBUG
@@ -3502,7 +3479,7 @@ ahd_linux_dv_web(struct ahd_softc *ahd, 
 
 static void
 ahd_linux_dv_reb(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
-		 struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
+		 struct ahd_devinfo *devinfo, struct aic_linux_target *targ)
 {
 
 #ifdef AHD_DEBUG
@@ -3525,7 +3502,7 @@ ahd_linux_dv_reb(struct ahd_softc *ahd, 
 static void
 ahd_linux_dv_su(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
 		struct ahd_devinfo *devinfo,
-		struct ahd_linux_target *targ)
+		struct aic_linux_target *targ)
 {
 	u_int le;
 
@@ -3560,7 +3537,7 @@ ahd_linux_dv_fallback(struct ahd_softc *
 static int
 ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
 {
-	struct	ahd_linux_target *targ;
+	struct	aic_linux_target *targ;
 	struct	ahd_initiator_tinfo *tinfo;
 	struct	ahd_transinfo *goal;
 	struct	ahd_tmode_tstate *tstate;
@@ -3731,7 +3708,7 @@ ahd_linux_fallback(struct ahd_softc *ahd
 	return (0);
 }
 
-static void
+void
 ahd_linux_dv_timeout(struct scsi_cmnd *cmd)
 {
 	struct	ahd_softc *ahd;
@@ -3765,29 +3742,18 @@ ahd_linux_dv_timeout(struct scsi_cmnd *c
 	 * error code.
 	 */
 	if ((scb->flags & SCB_SENSE) != 0)
-		ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
+		aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
 	else
-		ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
+		aic_set_transaction_status(scb, CAM_CMD_TIMEOUT);
 	ahd_reset_channel(ahd, cmd->device->channel + 'A', /*initiate*/TRUE);
 
-	/*
-	 * Add a minimal bus settle delay for devices that are slow to
-	 * respond after bus resets.
-	 */
-	ahd_freeze_simq(ahd);
-	init_timer(&ahd->platform_data->reset_timer);
-	ahd->platform_data->reset_timer.data = (u_long)ahd;
-	ahd->platform_data->reset_timer.expires = jiffies + HZ / 2;
-	ahd->platform_data->reset_timer.function =
-	    (ahd_linux_callback_t *)ahd_release_simq;
-	add_timer(&ahd->platform_data->reset_timer);
-	if (ahd_linux_next_device_to_run(ahd) != NULL)
-		ahd_schedule_runq(ahd);
+	if (aic_linux_next_device_to_run(ahd) != NULL)
+		aic_schedule_runq(ahd);
 	ahd_linux_run_complete_queue(ahd);
 	ahd_unlock(ahd, &flags);
 }
 
-static void
+void
 ahd_linux_dv_complete(struct scsi_cmnd *cmd)
 {
 	struct ahd_softc *ahd;
@@ -3809,7 +3775,7 @@ ahd_linux_dv_complete(struct scsi_cmnd *
 }
 
 static void
-ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ)
+ahd_linux_generate_dv_pattern(struct aic_linux_target *targ)
 {
 	uint16_t b;
 	u_int	 i;
@@ -3975,8 +3941,8 @@ ahd_linux_setup_user_rd_strm_settings(st
  * Determines the queue depth for a given device.
  */
 static void
-ahd_linux_device_queue_depth(struct ahd_softc *ahd,
-			     struct ahd_linux_device *dev)
+aic_linux_device_queue_depth(struct ahd_softc *ahd,
+			     struct aic_linux_device *dev)
 {
 	struct	ahd_devinfo devinfo;
 	u_int	tags;
@@ -3999,10 +3965,10 @@ ahd_linux_device_queue_depth(struct ahd_
 	}
 }
 
-static void
-ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev)
+void
+ahd_linux_run_device_queue(struct ahd_softc *ahd, struct aic_linux_device *dev)
 {
-	struct	 ahd_cmd *acmd;
+	struct	 aic_cmd *acmd;
 	struct	 scsi_cmnd *cmd;
 	struct	 scb *scb;
 	struct	 hardware_scb *hscb;
@@ -4011,7 +3977,7 @@ ahd_linux_run_device_queue(struct ahd_so
 	u_int	 col_idx;
 	uint16_t mask;
 
-	if ((dev->flags & AHD_DEV_ON_RUN_LIST) != 0)
+	if ((dev->flags & AIC_DEV_ON_RUN_LIST) != 0)
 		panic("running device on run list");
 
 	while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL
@@ -4022,11 +3988,11 @@ ahd_linux_run_device_queue(struct ahd_so
 		 * running is because the whole controller Q is frozen.
 		 */
 		if (ahd->platform_data->qfrozen != 0
-		 && AHD_DV_SIMQ_FROZEN(ahd) == 0) {
+		 && AIC_DV_SIMQ_FROZEN(ahd) == 0) {
 
 			TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq,
 					  dev, links);
-			dev->flags |= AHD_DEV_ON_RUN_LIST;
+			dev->flags |= AIC_DEV_ON_RUN_LIST;
 			return;
 		}
 
@@ -4037,7 +4003,7 @@ ahd_linux_run_device_queue(struct ahd_so
 		 */
 		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
 					    cmd->device->id, &tstate);
-		if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0
+		if ((dev->flags & (AIC_DEV_Q_TAGGED|AIC_DEV_Q_BASIC)) == 0
 		 || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
 			col_idx = AHD_NEVER_COL_IDX;
 		} else {
@@ -4047,13 +4013,14 @@ ahd_linux_run_device_queue(struct ahd_so
 		if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
 			TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq,
 					 dev, links);
-			dev->flags |= AHD_DEV_ON_RUN_LIST;
+			dev->flags |= AIC_DEV_ON_RUN_LIST;
 			ahd->flags |= AHD_RESOURCE_SHORTAGE;
 			return;
 		}
 		TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe);
 		scb->io_ctx = cmd;
 		scb->platform_data->dev = dev;
+		scb->platform_data->flags = 0;
 		hscb = scb->hscb;
 		cmd->host_scribble = (char *)scb;
 
@@ -4069,7 +4036,7 @@ ahd_linux_run_device_queue(struct ahd_so
 		if ((ahd->user_discenable & mask) != 0)
 			hscb->control |= DISCENB;
 
-	 	if (AHD_DV_CMD(cmd) != 0)
+	 	if (AIC_DV_CMD(cmd) != 0)
 			scb->flags |= SCB_SILENT;
 
 		if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
@@ -4080,7 +4047,7 @@ ahd_linux_run_device_queue(struct ahd_so
 			scb->hscb->control |= MK_MESSAGE;
 		}
 
-		if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
+		if ((dev->flags & (AIC_DEV_Q_TAGGED|AIC_DEV_Q_BASIC)) != 0) {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 			int	msg_bytes;
 			uint8_t tag_msgs[2];
@@ -4092,8 +4059,8 @@ ahd_linux_run_device_queue(struct ahd_so
 					dev->commands_since_idle_or_otag = 0;
 			} else
 #endif
-			if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH
-			 && (dev->flags & AHD_DEV_Q_TAGGED) != 0) {
+			if (dev->commands_since_idle_or_otag == AIC_OTAG_THRESH
+			 && (dev->flags & AIC_DEV_Q_TAGGED) != 0) {
 				hscb->control |= MSG_ORDERED_TASK;
 				dev->commands_since_idle_or_otag = 0;
 			} else {
@@ -4105,8 +4072,9 @@ ahd_linux_run_device_queue(struct ahd_so
 		memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len);
 
 		scb->sg_count = 0;
-		ahd_set_residual(scb, 0);
-		ahd_set_sense_residual(scb, 0);
+		aic_set_residual(scb, 0);
+		aic_set_sense_residual(scb, 0);
+		scb->platform_data->xfer_len = 0;
 		if (cmd->use_sg != 0) {
 			void	*sg;
 			struct	 scatterlist *cur_seg;
@@ -4115,18 +4083,15 @@ ahd_linux_run_device_queue(struct ahd_so
 
 			cur_seg = (struct scatterlist *)cmd->request_buffer;
 			dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
-			nseg = pci_map_sg(ahd->dev_softc, cur_seg,
-					  cmd->use_sg, dir);
-			scb->platform_data->xfer_len = 0;
+			nseg = aic_map_sg(ahd, cur_seg, cmd->use_sg, dir);
 			for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) {
 				bus_addr_t addr;
 				bus_size_t len;
 
 				addr = sg_dma_address(cur_seg);
 				len = sg_dma_len(cur_seg);
-				scb->platform_data->xfer_len += len;
-				sg = ahd_sg_setup(ahd, scb, sg, addr, len,
-						  /*last*/nseg == 1);
+				sg = ahd_linux_sg_setup(ahd, scb, sg, addr, len,
+							/*last*/nseg == 1);
 			}
 		} else if (cmd->request_bufflen != 0) {
 			void *sg;
@@ -4135,13 +4100,13 @@ ahd_linux_run_device_queue(struct ahd_so
 
 			sg = scb->sg_list;
 			dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
-			addr = pci_map_single(ahd->dev_softc,
+			addr = aic_map_single(ahd,
 					      cmd->request_buffer,
 					      cmd->request_bufflen, dir);
-			scb->platform_data->xfer_len = cmd->request_bufflen;
 			scb->platform_data->buf_busaddr = addr;
-			sg = ahd_sg_setup(ahd, scb, sg, addr,
-					  cmd->request_bufflen, /*last*/TRUE);
+			sg = ahd_linux_sg_setup(ahd, scb, sg, addr,
+						cmd->request_bufflen,
+						/*last*/TRUE);
 		}
 
 		LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
@@ -4157,9 +4122,10 @@ ahd_linux_run_device_queue(struct ahd_so
 				dev->target->cmds_since_error = 0;
 		}
 
-		if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0)
+		if ((dev->flags & AIC_DEV_PERIODIC_OTAG) != 0)
 			dev->commands_since_idle_or_otag++;
 		scb->flags |= SCB_ACTIVE;
+		aic_scb_timer_start(scb);
 		ahd_queue_scb(ahd, scb);
 	}
 }
@@ -4177,8 +4143,8 @@ ahd_linux_isr(int irq, void *dev_id, str
 	ahd = (struct ahd_softc *) dev_id;
 	ahd_lock(ahd, &flags); 
 	ours = ahd_intr(ahd);
-	if (ahd_linux_next_device_to_run(ahd) != NULL)
-		ahd_schedule_runq(ahd);
+	if (aic_linux_next_device_to_run(ahd) != NULL)
+		aic_schedule_runq(ahd);
 	ahd_linux_run_complete_queue(ahd);
 	ahd_unlock(ahd, &flags);
 	return IRQ_RETVAL(ours);
@@ -4192,10 +4158,10 @@ ahd_platform_flushwork(struct ahd_softc 
 		;
 }
 
-static struct ahd_linux_target*
+static struct aic_linux_target*
 ahd_linux_alloc_target(struct ahd_softc *ahd, u_int channel, u_int target)
 {
-	struct ahd_linux_target *targ;
+	struct aic_linux_target *targ;
 
 	targ = malloc(sizeof(*targ), M_DEVBUF, M_NOWAIT);
 	if (targ == NULL)
@@ -4203,14 +4169,14 @@ ahd_linux_alloc_target(struct ahd_softc 
 	memset(targ, 0, sizeof(*targ));
 	targ->channel = channel;
 	targ->target = target;
-	targ->ahd = ahd;
-	targ->flags = AHD_DV_REQUIRED;
+	targ->softc = ahd;
+	targ->flags = AIC_DV_REQUIRED;
 	ahd->platform_data->targets[target] = targ;
 	return (targ);
 }
 
 static void
-ahd_linux_free_target(struct ahd_softc *ahd, struct ahd_linux_target *targ)
+ahd_linux_free_target(struct ahd_softc *ahd, struct aic_linux_target *targ)
 {
 	struct ahd_devinfo devinfo;
 	struct ahd_initiator_tinfo *tinfo;
@@ -4246,11 +4212,11 @@ ahd_linux_free_target(struct ahd_softc *
 	free(targ, M_DEVBUF);
 }
 
-static struct ahd_linux_device*
+static struct aic_linux_device*
 ahd_linux_alloc_device(struct ahd_softc *ahd,
-		 struct ahd_linux_target *targ, u_int lun)
+		 struct aic_linux_target *targ, u_int lun)
 {
-	struct ahd_linux_device *dev;
+	struct aic_linux_device *dev;
 
 	dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT);
 	if (dev == NULL)
@@ -4258,7 +4224,7 @@ ahd_linux_alloc_device(struct ahd_softc 
 	memset(dev, 0, sizeof(*dev));
 	init_timer(&dev->timer);
 	TAILQ_INIT(&dev->busyq);
-	dev->flags = AHD_DEV_UNCONFIGURED;
+	dev->flags = AIC_DEV_UNCONFIGURED;
 	dev->lun = lun;
 	dev->target = targ;
 
@@ -4281,9 +4247,9 @@ ahd_linux_alloc_device(struct ahd_softc 
 }
 
 static void
-ahd_linux_free_device(struct ahd_softc *ahd, struct ahd_linux_device *dev)
+ahd_linux_free_device(struct ahd_softc *ahd, struct aic_linux_device *dev)
 {
-	struct ahd_linux_target *targ;
+	struct aic_linux_target *targ;
 
 	del_timer(&dev->timer);
 	targ = dev->target;
@@ -4291,7 +4257,7 @@ ahd_linux_free_device(struct ahd_softc *
 	free(dev, M_DEVBUF);
 	targ->refcount--;
 	if (targ->refcount == 0
-	 && (targ->flags & AHD_DV_REQUIRED) == 0)
+	 && (targ->flags & AIC_DV_REQUIRED) == 0)
 		ahd_linux_free_target(ahd, targ);
 }
 
@@ -4303,7 +4269,7 @@ ahd_send_async(struct ahd_softc *ahd, ch
 	case AC_TRANSFER_NEG:
 	{
 		char	buf[80];
-		struct	ahd_linux_target *targ;
+		struct	aic_linux_target *targ;
 		struct	info_str info;
 		struct	ahd_initiator_tinfo *tinfo;
 		struct	ahd_tmode_tstate *tstate;
@@ -4391,6 +4357,20 @@ ahd_send_async(struct ahd_softc *ahd, ch
 					      channel - 'A');
 		}
 #endif
+		/*
+		 * Add a minimal bus settle delay for devices that are slow to
+		 * respond after bus resets.
+		 */
+		if ((ahd->platform_data->flags & AIC_BUS_SETTLE_TIMER) == 0) {
+			aic_freeze_simq(ahd);
+			ahd->platform_data->flags |= AIC_BUS_SETTLE_TIMER;
+			ahd->platform_data->bus_settle_timer.expires =
+			    jiffies + (AIC79XX_RESET_DELAY * HZ)/1000;
+			add_timer(&ahd->platform_data->bus_settle_timer);
+		} else {
+			mod_timer(&ahd->platform_data->bus_settle_timer,
+				  jiffies + (AIC79XX_RESET_DELAY * HZ)/1000);
+		}
                 break;
         default:
                 panic("ahd_send_async: Unexpected async event");
@@ -4404,14 +4384,18 @@ void
 ahd_done(struct ahd_softc *ahd, struct scb *scb)
 {
 	Scsi_Cmnd *cmd;
-	struct	  ahd_linux_device *dev;
+	struct	  aic_linux_device *dev;
 
 	if ((scb->flags & SCB_ACTIVE) == 0) {
 		printf("SCB %d done'd twice\n", SCB_GET_TAG(scb));
 		ahd_dump_card_state(ahd);
 		panic("Stopping for safety");
 	}
+
 	LIST_REMOVE(scb, pending_links);
+	if ((scb->flags & SCB_TIMEDOUT) != 0)
+		LIST_REMOVE(scb, timedout_links);
+
 	cmd = scb->io_ctx;
 	dev = scb->platform_data->dev;
 	dev->active--;
@@ -4429,11 +4413,11 @@ ahd_done(struct ahd_softc *ahd, struct s
 	 * the sense buffer looks "sane".
 	 */
 	cmd->sense_buffer[0] = 0;
-	if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG) {
+	if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) {
 		uint32_t amount_xferred;
 
 		amount_xferred =
-		    ahd_get_transfer_length(scb) - ahd_get_residual(scb);
+		    aic_get_transfer_length(scb) - aic_get_residual(scb);
 		if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) {
 #ifdef AHD_DEBUG
 			if ((ahd_debug & AHD_SHOW_MISC) != 0) {
@@ -4441,7 +4425,17 @@ ahd_done(struct ahd_softc *ahd, struct s
 				printf("Set CAM_UNCOR_PARITY\n");
 			}
 #endif
-			ahd_set_transaction_status(scb, CAM_UNCOR_PARITY);
+			aic_set_transaction_status(scb, CAM_UNCOR_PARITY);
+#ifdef AHD_REPORT_UNDERFLOWS
+		/*
+		 * This code is disabled by default as some
+		 * clients of the SCSI system do not properly
+		 * initialize the underflow parameter.  This
+		 * results in spurious termination of commands
+		 * that complete as expected (e.g. underflow is
+		 * allowed as command can return variable amounts
+		 * of data.
+		 */
 		} else if (amount_xferred < scb->io_ctx->underflow) {
 			u_int i;
 
@@ -4453,30 +4447,31 @@ ahd_done(struct ahd_softc *ahd, struct s
 			ahd_print_path(ahd, scb);
 			printf("Saw underflow (%ld of %ld bytes). "
 			       "Treated as error\n",
-				ahd_get_residual(scb),
-				ahd_get_transfer_length(scb));
-			ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR);
+				aic_get_residual(scb),
+				aic_get_transfer_length(scb));
+			aic_set_transaction_status(scb, CAM_DATA_RUN_ERR);
+#endif
 		} else {
-			ahd_set_transaction_status(scb, CAM_REQ_CMP);
+			aic_set_transaction_status(scb, CAM_REQ_CMP);
 		}
-	} else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
+	} else if (aic_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
 		ahd_linux_handle_scsi_status(ahd, dev, scb);
-	} else if (ahd_get_transaction_status(scb) == CAM_SEL_TIMEOUT) {
-		dev->flags |= AHD_DEV_UNCONFIGURED;
-		if (AHD_DV_CMD(cmd) == FALSE)
-			dev->target->flags &= ~AHD_DV_REQUIRED;
+	} else if (aic_get_transaction_status(scb) == CAM_SEL_TIMEOUT) {
+		dev->flags |= AIC_DEV_UNCONFIGURED;
+		if (AIC_DV_CMD(cmd) == FALSE)
+			dev->target->flags &= ~AIC_DV_REQUIRED;
 	}
 	/*
 	 * Start DV for devices that require it assuming the first command
 	 * sent does not result in a selection timeout.
 	 */
-	if (ahd_get_transaction_status(scb) != CAM_SEL_TIMEOUT
-	 && (dev->target->flags & AHD_DV_REQUIRED) != 0)
+	if (aic_get_transaction_status(scb) != CAM_SEL_TIMEOUT
+	 && (dev->target->flags & AIC_DV_REQUIRED) != 0)
 		ahd_linux_start_dv(ahd);
 
 	if (dev->openings == 1
-	 && ahd_get_transaction_status(scb) == CAM_REQ_CMP
-	 && ahd_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL)
+	 && aic_get_transaction_status(scb) == CAM_REQ_CMP
+	 && aic_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL)
 		dev->tag_success_count++;
 	/*
 	 * Some devices deal with temporary internal resource
@@ -4485,7 +4480,7 @@ ahd_done(struct ahd_softc *ahd, struct s
 	 * back to our previous queue depth.
 	 */
 	if ((dev->openings + dev->active) < dev->maxtags
-	 && dev->tag_success_count > AHD_TAG_SUCCESS_INTERVAL) {
+	 && dev->tag_success_count > AIC_TAG_SUCCESS_INTERVAL) {
 		dev->tag_success_count = 0;
 		dev->openings++;
 	}
@@ -4494,39 +4489,68 @@ ahd_done(struct ahd_softc *ahd, struct s
 		dev->commands_since_idle_or_otag = 0;
 
 	if (TAILQ_EMPTY(&dev->busyq)) {
-		if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0
-		 && dev->active == 0
-		 && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0)
+		if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0
+		 && dev->active == 0)
 			ahd_linux_free_device(ahd, dev);
-	} else if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) {
+	} else if ((dev->flags & AIC_DEV_ON_RUN_LIST) == 0) {
 		TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links);
-		dev->flags |= AHD_DEV_ON_RUN_LIST;
+		dev->flags |= AIC_DEV_ON_RUN_LIST;
 	}
 
 	if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
 		printf("Recovery SCB completes\n");
-		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 ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
-			scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
+		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);
+		if ((scb->platform_data->flags & AIC_SCB_UP_EH_SEM) != 0) {
+			scb->platform_data->flags &= ~AIC_SCB_UP_EH_SEM;
 			up(&ahd->platform_data->eh_sem);
+		} else {
+			struct  scb *list_scb;
+
+			/*
+			 * We were able to complete the command successfully,
+			 * so reinstate the timeouts for all other pending
+			 * commands.
+			 */
+			LIST_FOREACH(list_scb,
+				     &ahd->pending_scbs, pending_links) {
+
+				aic_scb_timer_start(list_scb);
+                	}
 		}
 	}
 
+	if ((scb->platform_data->flags & AIC_TIMEOUT_ACTIVE) == 0) {
+		/*
+		 * The completion handler believes that
+		 * commands without active timers running
+		 * have lost the race of completing before
+		 * their timer expires.  Since commands in
+		 * our busy queues do not have timers running,
+		 * appease the mid-layer by adding a timer
+		 * now.  This timer will be immediately
+		 * canceled by the midlayer.
+		 */
+		scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout);
+	}
+
+	if ((scb->platform_data->flags & AIC_RELEASE_SIMQ) != 0)
+		aic_release_simq_locked(ahd);
+
 	ahd_free_scb(ahd, scb);
 	ahd_linux_queue_cmd_complete(ahd, cmd);
 
-	if ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_EMPTY) != 0
+	if ((ahd->platform_data->flags & AIC_DV_WAIT_SIMQ_EMPTY) != 0
 	 && LIST_FIRST(&ahd->pending_scbs) == NULL) {
-		ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_EMPTY;
+		ahd->platform_data->flags &= ~AIC_DV_WAIT_SIMQ_EMPTY;
 		up(&ahd->platform_data->dv_sem);
 	}
 }
 
 static void
 ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
-			     struct ahd_linux_device *dev, struct scb *scb)
+			     struct aic_linux_device *dev, struct scb *scb)
 {
 	struct	ahd_devinfo devinfo;
 
@@ -4546,7 +4570,7 @@ ahd_linux_handle_scsi_status(struct ahd_
 	 * we don't clobber the device with too many
 	 * commands.
 	 */
-	switch (ahd_get_scsi_status(scb)) {
+	switch (aic_get_scsi_status(scb)) {
 	default:
 		break;
 	case SCSI_STATUS_CHECK_COND:
@@ -4560,13 +4584,15 @@ ahd_linux_handle_scsi_status(struct ahd_
 		 */
 		cmd = scb->io_ctx;
 		if ((scb->flags & (SCB_SENSE|SCB_PKT_SENSE)) != 0) {
-			struct scsi_status_iu_header *siu;
-			u_int sense_size;
-			u_int sense_offset;
+			struct	scsi_status_iu_header *siu;
+			struct	scsi_sense_data *sense;
+			u_int	sense_size;
+			u_int	sense_offset;
+			int	error_code, sense_key, asc, ascq;
 
 			if (scb->flags & SCB_SENSE) {
 				sense_size = MIN(sizeof(struct scsi_sense_data)
-					       - ahd_get_sense_residual(scb),
+					       - aic_get_sense_residual(scb),
 						 sizeof(cmd->sense_buffer));
 				sense_offset = 0;
 			} else {
@@ -4581,10 +4607,10 @@ ahd_linux_handle_scsi_status(struct ahd_
 				sense_offset = SIU_SENSE_OFFSET(siu);
 			}
 
+			sense = (struct scsi_sense_data *)
+			    (ahd_get_sense_buf(ahd, scb) + sense_offset);
 			memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
-			memcpy(cmd->sense_buffer,
-			       ahd_get_sense_buf(ahd, scb)
-			       + sense_offset, sense_size);
+			memcpy(cmd->sense_buffer, sense, sense_size);
 			cmd->result |= (DRIVER_SENSE << 24);
 
 #ifdef AHD_DEBUG
@@ -4601,6 +4627,23 @@ ahd_linux_handle_scsi_status(struct ahd_
 				printf("\n");
 			}
 #endif
+			/*
+			 * If this is not a DV command and the target
+			 * provides some status that makes us believe
+			 * that the target has changed (power on reset,
+			 * etc.) kick off a DV scan to re-validate the
+			 * device.
+			 */
+	 		if (AIC_DV_CMD(cmd) != 0)
+				break;
+
+			scsi_extract_sense(sense, &error_code,
+					   &sense_key, &asc, &ascq);
+			if (error_code == SSD_CURRENT_ERROR
+			 && sense_key == SSD_KEY_UNIT_ATTENTION
+			 && asc == 0x29
+			 && (ascq == 0 || ascq == 1))
+				dev->target->flags |= AIC_DV_REQUIRED;
 		}
 		break;
 	}
@@ -4640,7 +4683,7 @@ ahd_linux_handle_scsi_status(struct ahd_
 				 * this device.
 				 */
 				if (dev->last_queuefull_same_count
-				 == AHD_LOCK_TAGS_COUNT) {
+				 == AIC_LOCK_TAGS_COUNT) {
 					dev->maxtags = dev->active;
 					ahd_print_path(ahd, scb);
 					printf("Locking max tag count at %d\n",
@@ -4650,10 +4693,10 @@ ahd_linux_handle_scsi_status(struct ahd_
 				dev->tags_on_last_queuefull = dev->active;
 				dev->last_queuefull_same_count = 0;
 			}
-			ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
-			ahd_set_scsi_status(scb, SCSI_STATUS_OK);
+			aic_set_transaction_status(scb, CAM_REQUEUE_REQ);
+			aic_set_scsi_status(scb, SCSI_STATUS_OK);
 			ahd_platform_set_tags(ahd, &devinfo,
-				     (dev->flags & AHD_DEV_Q_BASIC)
+				     (dev->flags & AIC_DEV_Q_BASIC)
 				   ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
 			break;
 		}
@@ -4663,9 +4706,9 @@ ahd_linux_handle_scsi_status(struct ahd_
 		 */
 		dev->openings = 1;
 		ahd_platform_set_tags(ahd, &devinfo,
-			     (dev->flags & AHD_DEV_Q_BASIC)
+			     (dev->flags & AIC_DEV_Q_BASIC)
 			   ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
-		ahd_set_scsi_status(scb, SCSI_STATUS_BUSY);
+		aic_set_scsi_status(scb, SCSI_STATUS_BUSY);
 		/* FALLTHROUGH */
 	}
 	case SCSI_STATUS_BUSY:
@@ -4673,13 +4716,13 @@ ahd_linux_handle_scsi_status(struct ahd_
 		 * Set a short timer to defer sending commands for
 		 * a bit since Linux will not delay in this case.
 		 */
-		if ((dev->flags & AHD_DEV_TIMER_ACTIVE) != 0) {
+		if ((dev->flags & AIC_DEV_TIMER_ACTIVE) != 0) {
 			printf("%s:%c:%d: Device Timer still active during "
 			       "busy processing\n", ahd_name(ahd),
 				dev->target->channel, dev->target->target);
 			break;
 		}
-		dev->flags |= AHD_DEV_TIMER_ACTIVE;
+		dev->flags |= AIC_DEV_TIMER_ACTIVE;
 		dev->qfrozen++;
 		init_timer(&dev->timer);
 		dev->timer.data = (u_long)dev;
@@ -4705,9 +4748,9 @@ ahd_linux_queue_cmd_complete(struct ahd_
 	 * not guarantee the order that aborted commands will be
 	 * returned to us.
 	 */
-	struct ahd_completeq *completeq;
-	struct ahd_cmd *list_cmd;
-	struct ahd_cmd *acmd;
+	struct aic_completeq *completeq;
+	struct aic_cmd *list_cmd;
+	struct aic_cmd *acmd;
 
 	/*
 	 * Map CAM error codes into Linux Error codes.  We
@@ -4715,13 +4758,13 @@ ahd_linux_queue_cmd_complete(struct ahd_
 	 * full error information available when making
 	 * state change decisions.
 	 */
-	if (AHD_DV_CMD(cmd) == FALSE) {
+	if (AIC_DV_CMD(cmd) == FALSE) {
 		uint32_t status;
 		u_int new_status;
 
-		status = ahd_cmd_get_transaction_status(cmd);
+		status = aic_cmd_get_transaction_status(cmd);
 		if (status != CAM_REQ_CMP) {
-			struct ahd_linux_device *dev;
+			struct aic_linux_device *dev;
 			struct ahd_devinfo devinfo;
 			cam_status cam_status;
 			uint32_t action;
@@ -4741,8 +4784,8 @@ ahd_linux_queue_cmd_complete(struct ahd_
 					    dev->target->channel == 0 ? 'A':'B',
 					    ROLE_INITIATOR);
 
-			scsi_status = ahd_cmd_get_scsi_status(cmd);
-			cam_status = ahd_cmd_get_transaction_status(cmd);
+			scsi_status = aic_cmd_get_scsi_status(cmd);
+			cam_status = aic_cmd_get_transaction_status(cmd);
 			action = aic_error_action(cmd, dev->target->inq_data,
 						  cam_status, scsi_status);
 			if ((action & SSQ_FALLBACK) != 0) {
@@ -4785,7 +4828,17 @@ no_fallback:
 			new_status = DID_PARITY;
 			break;
 		case CAM_CMD_TIMEOUT:
-			new_status = DID_TIME_OUT;
+			/*
+			 *  Returning DID_TIME_OUT will 
+			 *  wake up the error recovery
+			 *  thread instead of doing the
+			 *  command retry we desire. Since
+			 *  we have already recovered the
+			 *  command, returning DID_ERROR
+			 *  will cause a retry up to the
+			 *  retry limit for this command.
+			 */
+			new_status = DID_ERROR;
 			break;
 		case CAM_UA_ABORT:
 		case CAM_REQ_CMP_ERR:
@@ -4815,7 +4868,7 @@ no_fallback:
 			if (cmd->retries > 0)
 				cmd->retries--;
 			new_status = DID_OK;
-			ahd_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND);
+			aic_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND);
 			cmd->result |= (DRIVER_SENSE << 24);
 			memset(cmd->sense_buffer, 0,
 			       sizeof(cmd->sense_buffer));
@@ -4829,12 +4882,12 @@ no_fallback:
 			break;
 		}
 
-		ahd_cmd_set_transaction_status(cmd, new_status);
+		aic_cmd_set_transaction_status(cmd, new_status);
 	}
 
 	completeq = &ahd->platform_data->completeq;
 	list_cmd = TAILQ_FIRST(completeq);
-	acmd = (struct ahd_cmd *)cmd;
+	acmd = (struct aic_cmd *)cmd;
 	while (list_cmd != NULL
 	    && acmd_scsi_cmd(list_cmd).serial_number
 	     < acmd_scsi_cmd(acmd).serial_number)
@@ -4854,7 +4907,7 @@ ahd_linux_filter_inquiry(struct ahd_soft
 	struct	ahd_transinfo *goal;
 	struct	ahd_transinfo *curr;
 	struct	ahd_tmode_tstate *tstate;
-	struct	ahd_linux_device *dev;
+	struct	aic_linux_device *dev;
 	u_int	width;
 	u_int	period;
 	u_int	offset;
@@ -4876,9 +4929,9 @@ ahd_linux_filter_inquiry(struct ahd_soft
 	sid = (struct scsi_inquiry_data *)dev->target->inq_data;
 	if (SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) {
 
-		dev->flags &= ~AHD_DEV_UNCONFIGURED;
+		dev->flags &= ~AIC_DEV_UNCONFIGURED;
 	} else {
-		dev->flags |= AHD_DEV_UNCONFIGURED;
+		dev->flags |= AIC_DEV_UNCONFIGURED;
 		return;
 	}
 
@@ -4944,48 +4997,6 @@ ahd_linux_filter_inquiry(struct ahd_soft
 			 AHD_TRANS_GOAL, /*paused*/FALSE);
 }
 
-void
-ahd_freeze_simq(struct ahd_softc *ahd)
-{
-	ahd->platform_data->qfrozen++;
-	if (ahd->platform_data->qfrozen == 1) {
-		scsi_block_requests(ahd->platform_data->host);
-		ahd_platform_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
-					CAM_LUN_WILDCARD, SCB_LIST_NULL,
-					ROLE_INITIATOR, CAM_REQUEUE_REQ);
-	}
-}
-
-void
-ahd_release_simq(struct ahd_softc *ahd)
-{
-	u_long s;
-	int    unblock_reqs;
-
-	unblock_reqs = 0;
-	ahd_lock(ahd, &s);
-	if (ahd->platform_data->qfrozen > 0)
-		ahd->platform_data->qfrozen--;
-	if (ahd->platform_data->qfrozen == 0) {
-		unblock_reqs = 1;
-	}
-	if (AHD_DV_SIMQ_FROZEN(ahd)
-	 && ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_RELEASE) != 0)) {
-		ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_RELEASE;
-		up(&ahd->platform_data->dv_sem);
-	}
-	ahd_schedule_runq(ahd);
-	ahd_unlock(ahd, &s);
-	/*
-	 * There is still a race here.  The mid-layer
-	 * should keep its own freeze count and use
-	 * a bottom half handler to run the queues
-	 * so we can unblock with our own lock held.
-	 */
-	if (unblock_reqs)
-		scsi_unblock_requests(ahd->platform_data->host);
-}
-
 static void
 ahd_linux_sem_timeout(u_long arg)
 {
@@ -4996,8 +5007,8 @@ ahd_linux_sem_timeout(u_long arg)
 	scb = (struct scb *)arg;
 	ahd = scb->ahd_softc;
 	ahd_lock(ahd, &s);
-	if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
-		scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
+	if ((scb->platform_data->flags & AIC_SCB_UP_EH_SEM) != 0) {
+		scb->platform_data->flags &= ~AIC_SCB_UP_EH_SEM;
 		up(&ahd->platform_data->eh_sem);
 	}
 	ahd_unlock(ahd, &s);
@@ -5006,20 +5017,21 @@ ahd_linux_sem_timeout(u_long arg)
 static void
 ahd_linux_dev_timed_unfreeze(u_long arg)
 {
-	struct ahd_linux_device *dev;
+	struct aic_linux_device *dev;
 	struct ahd_softc *ahd;
 	u_long s;
 
-	dev = (struct ahd_linux_device *)arg;
-	ahd = dev->target->ahd;
+	dev = (struct aic_linux_device *)arg;
+	ahd = dev->target->softc;
 	ahd_lock(ahd, &s);
-	dev->flags &= ~AHD_DEV_TIMER_ACTIVE;
+	dev->flags &= ~AIC_DEV_TIMER_ACTIVE;
 	if (dev->qfrozen > 0)
 		dev->qfrozen--;
 	if (dev->qfrozen == 0
-	 && (dev->flags & AHD_DEV_ON_RUN_LIST) == 0)
+	 && (dev->flags & AIC_DEV_ON_RUN_LIST) == 0)
 		ahd_linux_run_device_queue(ahd, dev);
-	if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0
+	if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0
+	 && TAILQ_EMPTY(&dev->busyq)
 	 && dev->active == 0)
 		ahd_linux_free_device(ahd, dev);
 	ahd_unlock(ahd, &s);
@@ -5028,17 +5040,26 @@ ahd_linux_dev_timed_unfreeze(u_long arg)
 void
 ahd_platform_dump_card_state(struct ahd_softc *ahd)
 {
-	struct ahd_linux_device *dev;
+	struct Scsi_Host *host;
+	struct aic_linux_device *dev;
 	int target;
 	int maxtarget;
 	int lun;
 	int i;
 
+	host = ahd->platform_data->host;
+	printf("%s: Host Status: Failed(%d) %s%s%s\n",
+	       ahd_name(ahd),
+	       host->host_failed,
+	       host->eh_active ? "eh_active " : "",
+	       host->host_blocked ? "host_blocked " : "",
+	       host->host_self_blocked ? "host_self_blocked " : "");
+	       
 	maxtarget = (ahd->features & AHD_WIDE) ? 15 : 7;
 	for (target = 0; target <=maxtarget; target++) {
 
 		for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
-			struct ahd_cmd *acmd;
+			struct aic_cmd *acmd;
 
 			dev = ahd_linux_get_device(ahd, 0, target,
 						   lun, /*alloc*/FALSE);
@@ -5077,20 +5098,18 @@ static void __exit
 ahd_linux_exit(void)
 {
 	struct ahd_softc *ahd;
-	u_long l;
 
 	/*
-	 * Shutdown DV threads before going into the SCSI mid-layer.
+	 * Shutdown our threads before going into the SCSI mid-layer.
 	 * This avoids situations where the mid-layer locks the entire
 	 * kernel so that waiting for our DV threads to exit leads
 	 * to deadlock.
 	 */
-	ahd_list_lock(&l);
 	TAILQ_FOREACH(ahd, &ahd_tailq, links) {
 
 		ahd_linux_kill_dv_thread(ahd);
+		ahd_terminate_recovery_thread(ahd);
 	}
-	ahd_list_unlock(&l);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	/*
 	 * In 2.4 we have to unregister from the PCI core _after_
diff -puN drivers/scsi/aic7xxx/aic79xx_osm.h~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic79xx_osm.h
--- 25/drivers/scsi/aic7xxx/aic79xx_osm.h~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic79xx_osm.h	Wed Dec 24 12:15:38 2003
@@ -36,51 +36,22 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#133 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#153 $
  *
  */
 #ifndef _AIC79XX_LINUX_H_
 #define _AIC79XX_LINUX_H_
 
-#include <linux/types.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/smp_lock.h>
 #include <linux/version.h>
-#include <linux/module.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
 
 #ifndef KERNEL_VERSION
 #define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
 #endif
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-#include <linux/interrupt.h> /* For tasklet support. */
 #include <linux/config.h>
-#include <linux/slab.h>
-#else
-#include <linux/malloc.h>
 #endif
 
-/* Core SCSI definitions */
-#define AIC_LIB_PREFIX ahd
-#include "scsi.h"
-#include "hosts.h"
-
-/* Name space conflict with BSD queue macros */
-#ifdef LIST_HEAD
-#undef LIST_HEAD
-#endif
-
-#include "cam.h"
-#include "queue.h"
-#include "scsi_message.h"
-#include "scsi_iu.h"
-#include "aiclib.h"
-
 /*********************************** Debugging ********************************/
 #ifdef CONFIG_AIC79XX_DEBUG_ENABLE
 #ifdef CONFIG_AIC79XX_DEBUG_MASK
@@ -96,188 +67,27 @@
 /* No debugging code. */
 #endif
 
-/********************************** Misc Macros *******************************/
-#define	roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
-#define	powerof2(x)	((((x)-1)&(x))==0)
-
-/************************* Forward Declarations *******************************/
-struct ahd_softc;
-typedef struct pci_dev *ahd_dev_softc_t;
-typedef Scsi_Cmnd      *ahd_io_ctx_t;
-
-/******************************* Byte Order ***********************************/
-#define ahd_htobe16(x)	cpu_to_be16(x)
-#define ahd_htobe32(x)	cpu_to_be32(x)
-#define ahd_htobe64(x)	cpu_to_be64(x)
-#define ahd_htole16(x)	cpu_to_le16(x)
-#define ahd_htole32(x)	cpu_to_le32(x)
-#define ahd_htole64(x)	cpu_to_le64(x)
-
-#define ahd_be16toh(x)	be16_to_cpu(x)
-#define ahd_be32toh(x)	be32_to_cpu(x)
-#define ahd_be64toh(x)	be64_to_cpu(x)
-#define ahd_le16toh(x)	le16_to_cpu(x)
-#define ahd_le32toh(x)	le32_to_cpu(x)
-#define ahd_le64toh(x)	le64_to_cpu(x)
-
-#ifndef LITTLE_ENDIAN
-#define LITTLE_ENDIAN 1234
-#endif
-
-#ifndef BIG_ENDIAN
-#define BIG_ENDIAN 4321
-#endif
-
-#ifndef BYTE_ORDER
-#if defined(__BIG_ENDIAN)
-#define BYTE_ORDER BIG_ENDIAN
-#endif
-#if defined(__LITTLE_ENDIAN)
-#define BYTE_ORDER LITTLE_ENDIAN
-#endif
-#endif /* BYTE_ORDER */
-
-/************************* Configuration Data *********************************/
-extern uint32_t aic79xx_allow_memio;
-extern int aic79xx_detect_complete;
-extern Scsi_Host_Template aic79xx_driver_template;
-
-/***************************** Bus Space/DMA **********************************/
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17)
-typedef dma_addr_t bus_addr_t;
-#else
-typedef uint32_t bus_addr_t;
-#endif
-typedef uint32_t bus_size_t;
-
-typedef enum {
-	BUS_SPACE_MEMIO,
-	BUS_SPACE_PIO
-} bus_space_tag_t;
-
-typedef union {
-	u_long		  ioport;
-	volatile uint8_t *maddr;
-} bus_space_handle_t;
-
-typedef struct bus_dma_segment
-{
-	bus_addr_t	ds_addr;
-	bus_size_t	ds_len;
-} bus_dma_segment_t;
-
-struct ahd_linux_dma_tag
-{
-	bus_size_t	alignment;
-	bus_size_t	boundary;
-	bus_size_t	maxsize;
-};
-typedef struct ahd_linux_dma_tag* bus_dma_tag_t;
-
-struct ahd_linux_dmamap
-{
-	bus_addr_t	bus_addr;
-};
-typedef struct ahd_linux_dmamap* bus_dmamap_t;
-
-typedef int bus_dma_filter_t(void*, bus_addr_t);
-typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
-
-#define BUS_DMA_WAITOK		0x0
-#define BUS_DMA_NOWAIT		0x1
-#define BUS_DMA_ALLOCNOW	0x2
-#define BUS_DMA_LOAD_SEGS	0x4	/*
-					 * Argument is an S/G list not
-					 * a single buffer.
-					 */
-
-#define BUS_SPACE_MAXADDR	0xFFFFFFFF
-#define BUS_SPACE_MAXADDR_32BIT	0xFFFFFFFF
-#define BUS_SPACE_MAXSIZE_32BIT	0xFFFFFFFF
-
-int	ahd_dma_tag_create(struct ahd_softc *, bus_dma_tag_t /*parent*/,
-			   bus_size_t /*alignment*/, bus_size_t /*boundary*/,
-			   bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/,
-			   bus_dma_filter_t*/*filter*/, void */*filterarg*/,
-			   bus_size_t /*maxsize*/, int /*nsegments*/,
-			   bus_size_t /*maxsegsz*/, int /*flags*/,
-			   bus_dma_tag_t */*dma_tagp*/);
-
-void	ahd_dma_tag_destroy(struct ahd_softc *, bus_dma_tag_t /*tag*/);
-
-int	ahd_dmamem_alloc(struct ahd_softc *, bus_dma_tag_t /*dmat*/,
-			 void** /*vaddr*/, int /*flags*/,
-			 bus_dmamap_t* /*mapp*/);
-
-void	ahd_dmamem_free(struct ahd_softc *, bus_dma_tag_t /*dmat*/,
-			void* /*vaddr*/, bus_dmamap_t /*map*/);
-
-void	ahd_dmamap_destroy(struct ahd_softc *, bus_dma_tag_t /*tag*/,
-			   bus_dmamap_t /*map*/);
-
-int	ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t /*dmat*/,
-			bus_dmamap_t /*map*/, void * /*buf*/,
-			bus_size_t /*buflen*/, bus_dmamap_callback_t *,
-			void */*callback_arg*/, int /*flags*/);
-
-int	ahd_dmamap_unload(struct ahd_softc *, bus_dma_tag_t, bus_dmamap_t);
-
-/*
- * Operations performed by ahd_dmamap_sync().
- */
-#define BUS_DMASYNC_PREREAD	0x01	/* pre-read synchronization */
-#define BUS_DMASYNC_POSTREAD	0x02	/* post-read synchronization */
-#define BUS_DMASYNC_PREWRITE	0x04	/* pre-write synchronization */
-#define BUS_DMASYNC_POSTWRITE	0x08	/* post-write synchronization */
-
-/*
- * XXX
- * ahd_dmamap_sync is only used on buffers allocated with
- * the pci_alloc_consistent() API.  Although I'm not sure how
- * this works on architectures with a write buffer, Linux does
- * not have an API to sync "coherent" memory.  Perhaps we need
- * to do an mb()?
- */
-#define ahd_dmamap_sync(ahd, dma_tag, dmamap, offset, len, op)
-
-/************************** Timer DataStructures ******************************/
-typedef struct timer_list ahd_timer_t;
-
 /********************************** Includes **********************************/
+/* Core SCSI definitions */
+#define AIC_LIB_PREFIX ahd
+#define AIC_CONST_PREFIX AHD
+
 #ifdef CONFIG_AIC79XX_REG_PRETTY_PRINT
 #define AIC_DEBUG_REGISTERS 1
 #else
 #define AIC_DEBUG_REGISTERS 0
 #endif
-#include "aic79xx.h"
-
-/***************************** Timer Facilities *******************************/
-#define ahd_timer_init init_timer
-#define ahd_timer_stop del_timer_sync
-typedef void ahd_linux_callback_t (u_long);  
-static __inline void ahd_timer_reset(ahd_timer_t *timer, u_int usec,
-				     ahd_callback_t *func, void *arg);
-static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec);
-
-static __inline void
-ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg)
-{
-	struct ahd_softc *ahd;
+#define AIC_CORE_INCLUDE "aic79xx.h"
+#include "aiclib.h"
 
-	ahd = (struct ahd_softc *)arg;
-	del_timer(timer);
-	timer->data = (u_long)arg;
-	timer->expires = jiffies + (usec * HZ)/1000000;
-	timer->function = (ahd_linux_callback_t*)func;
-	add_timer(timer);
-}
+/************************* Configuration Data *********************************/
+extern uint32_t aic79xx_allow_memio;
+extern int aic79xx_detect_complete;
+extern Scsi_Host_Template aic79xx_driver_template;
 
-static __inline void
-ahd_scb_timer_reset(struct scb *scb, u_int usec)
-{
-	mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000);
-}
+/***************************** Domain Validation ******************************/
+void ahd_linux_dv_complete(Scsi_Cmnd *cmd);
+void ahd_linux_dv_timeout(struct scsi_cmnd *cmd);
 
 /***************************** SMP support ************************************/
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17)
@@ -292,193 +102,7 @@ ahd_scb_timer_reset(struct scb *scb, u_i
 #define AHD_SCSI_HAS_HOST_LOCK 0
 #endif
 
-#define AIC79XX_DRIVER_VERSION "1.3.9"
-
-/**************************** Front End Queues ********************************/
-/*
- * Data structure used to cast the Linux struct scsi_cmnd to something
- * that allows us to use the queue macros.  The linux structure has
- * plenty of space to hold the links fields as required by the queue
- * macros, but the queue macors require them to have the correct type.
- */
-struct ahd_cmd_internal {
-	/* Area owned by the Linux scsi layer. */
-	uint8_t	private[offsetof(struct scsi_cmnd, SCp.Status)];
-	union {
-		STAILQ_ENTRY(ahd_cmd)	ste;
-		LIST_ENTRY(ahd_cmd)	le;
-		TAILQ_ENTRY(ahd_cmd)	tqe;
-	} links;
-	uint32_t			end;
-};
-
-struct ahd_cmd {
-	union {
-		struct ahd_cmd_internal	icmd;
-		struct scsi_cmnd	scsi_cmd;
-	} un;
-};
-
-#define acmd_icmd(cmd) ((cmd)->un.icmd)
-#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd)
-#define acmd_links un.icmd.links
-
-/*************************** Device Data Structures ***************************/
-/*
- * A per probed device structure used to deal with some error recovery
- * scenarios that the Linux mid-layer code just doesn't know how to
- * handle.  The structure allocated for a device only becomes persistent
- * after a successfully completed inquiry command to the target when
- * that inquiry data indicates a lun is present.
- */
-TAILQ_HEAD(ahd_busyq, ahd_cmd);
-typedef enum {
-	AHD_DEV_UNCONFIGURED	 = 0x01,
-	AHD_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
-	AHD_DEV_TIMER_ACTIVE	 = 0x04, /* Our timer is active */
-	AHD_DEV_ON_RUN_LIST	 = 0x08, /* Queued to be run later */
-	AHD_DEV_Q_BASIC		 = 0x10, /* Allow basic device queuing */
-	AHD_DEV_Q_TAGGED	 = 0x20, /* Allow full SCSI2 command queueing */
-	AHD_DEV_PERIODIC_OTAG	 = 0x40, /* Send OTAG to prevent starvation */
-	AHD_DEV_SLAVE_CONFIGURED = 0x80	 /* slave_configure() has been called */
-} ahd_linux_dev_flags;
-
-struct ahd_linux_target;
-struct ahd_linux_device {
-	TAILQ_ENTRY(ahd_linux_device) links;
-	struct			ahd_busyq busyq;
-
-	/*
-	 * The number of transactions currently
-	 * queued to the device.
-	 */
-	int			active;
-
-	/*
-	 * The currently allowed number of 
-	 * transactions that can be queued to
-	 * the device.  Must be signed for
-	 * conversion from tagged to untagged
-	 * mode where the device may have more
-	 * than one outstanding active transaction.
-	 */
-	int			openings;
-
-	/*
-	 * A positive count indicates that this
-	 * device's queue is halted.
-	 */
-	u_int			qfrozen;
-	
-	/*
-	 * Cumulative command counter.
-	 */
-	u_long			commands_issued;
-
-	/*
-	 * The number of tagged transactions when
-	 * running at our current opening level
-	 * that have been successfully received by
-	 * this device since the last QUEUE FULL.
-	 */
-	u_int			tag_success_count;
-#define AHD_TAG_SUCCESS_INTERVAL 50
-
-	ahd_linux_dev_flags	flags;
-
-	/*
-	 * Per device timer.
-	 */
-	struct timer_list	timer;
-
-	/*
-	 * The high limit for the tags variable.
-	 */
-	u_int			maxtags;
-
-	/*
-	 * The computed number of tags outstanding
-	 * at the time of the last QUEUE FULL event.
-	 */
-	u_int			tags_on_last_queuefull;
-
-	/*
-	 * How many times we have seen a queue full
-	 * with the same number of tags.  This is used
-	 * to stop our adaptive queue depth algorithm
-	 * on devices with a fixed number of tags.
-	 */
-	u_int			last_queuefull_same_count;
-#define AHD_LOCK_TAGS_COUNT 50
-
-	/*
-	 * How many transactions have been queued
-	 * without the device going idle.  We use
-	 * this statistic to determine when to issue
-	 * an ordered tag to prevent transaction
-	 * starvation.  This statistic is only updated
-	 * if the AHD_DEV_PERIODIC_OTAG flag is set
-	 * on this device.
-	 */
-	u_int			commands_since_idle_or_otag;
-#define AHD_OTAG_THRESH	500
-
-	int			lun;
-	Scsi_Device	       *scsi_device;
-	struct			ahd_linux_target *target;
-};
-
-typedef enum {
-	AHD_DV_REQUIRED		 = 0x01,
-	AHD_INQ_VALID		 = 0x02,
-	AHD_BASIC_DV		 = 0x04,
-	AHD_ENHANCED_DV		 = 0x08
-} ahd_linux_targ_flags;
-
-/* DV States */
-typedef enum {
-	AHD_DV_STATE_EXIT = 0,
-	AHD_DV_STATE_INQ_SHORT_ASYNC,
-	AHD_DV_STATE_INQ_ASYNC,
-	AHD_DV_STATE_INQ_ASYNC_VERIFY,
-	AHD_DV_STATE_TUR,
-	AHD_DV_STATE_REBD,
-	AHD_DV_STATE_INQ_VERIFY,
-	AHD_DV_STATE_WEB,
-	AHD_DV_STATE_REB,
-	AHD_DV_STATE_SU,
-	AHD_DV_STATE_BUSY
-} ahd_dv_state;
-
-struct ahd_linux_target {
-	struct ahd_linux_device	 *devices[AHD_NUM_LUNS];
-	int			  channel;
-	int			  target;
-	int			  refcount;
-	struct ahd_transinfo	  last_tinfo;
-	struct ahd_softc	 *ahd;
-	ahd_linux_targ_flags	  flags;
-	struct scsi_inquiry_data *inq_data;
-	/*
-	 * The next "fallback" period to use for narrow/wide transfers.
-	 */
-	uint8_t			  dv_next_narrow_period;
-	uint8_t			  dv_next_wide_period;
-	uint8_t			  dv_max_width;
-	uint8_t			  dv_max_ppr_options;
-	uint8_t			  dv_last_ppr_options;
-	u_int			  dv_echo_size;
-	ahd_dv_state		  dv_state;
-	u_int			  dv_state_retry;
-	uint8_t			 *dv_buffer;
-	uint8_t			 *dv_buffer1;
-
-	/*
-	 * Cumulative counter of errors.
-	 */
-	u_long			errors_detected;
-	u_long			cmds_since_error;
-};
+#define AIC79XX_DRIVER_VERSION "2.0.5"
 
 /********************* Definitions Required by the Core ***********************/
 /*
@@ -500,100 +124,21 @@ extern u_int ahd_linux_nseg;
 #define	AHD_NSEG 128
 #endif
 
-/*
- * Per-SCB OSM storage.
- */
-typedef enum {
-	AHD_SCB_UP_EH_SEM = 0x1
-} ahd_linux_scb_flags;
-
-struct scb_platform_data {
-	struct ahd_linux_device	*dev;
-	bus_addr_t		 buf_busaddr;
-	uint32_t		 xfer_len;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-	uint32_t		 resid;		/* Transfer residual */
-#endif
-	uint32_t		 sense_resid;	/* Auto-Sense residual */
-	ahd_linux_scb_flags	 flags;
-};
-
-/*
- * Define a structure used for each host adapter.  All members are
- * aligned on a boundary >= the size of the member to honor the
- * alignment restrictions of the various platforms supported by
- * this driver.
- */
-typedef enum {
-	AHD_DV_WAIT_SIMQ_EMPTY	 = 0x01,
-	AHD_DV_WAIT_SIMQ_RELEASE = 0x02,
-	AHD_DV_ACTIVE		 = 0x04,
-	AHD_DV_SHUTDOWN		 = 0x08,
-	AHD_RUN_CMPLT_Q_TIMER	 = 0x10
-} ahd_linux_softc_flags;
-
-TAILQ_HEAD(ahd_completeq, ahd_cmd);
-
-struct ahd_platform_data {
-	/*
-	 * Fields accessed from interrupt context.
-	 */
-	struct ahd_linux_target *targets[AHD_NUM_TARGETS]; 
-	TAILQ_HEAD(, ahd_linux_device) device_runq;
-	struct ahd_completeq	 completeq;
-
-	spinlock_t		 spin_lock;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	struct tasklet_struct	 runq_tasklet;
-#endif
-	u_int			 qfrozen;
-	pid_t			 dv_pid;
-	struct timer_list	 completeq_timer;
-	struct timer_list	 reset_timer;
-	struct timer_list	 stats_timer;
-	struct semaphore	 eh_sem;
-	struct semaphore	 dv_sem;
-	struct semaphore	 dv_cmd_sem;	/* XXX This needs to be in
-						 * the target struct
-						 */
-	struct scsi_device	*dv_scsi_dev;
-	struct Scsi_Host        *host;		/* pointer to scsi host */
-#define AHD_LINUX_NOIRQ	((uint32_t)~0)
-	uint32_t		 irq;		/* IRQ for this adapter */
-	uint32_t		 bios_address;
-	uint32_t		 mem_busaddr;	/* Mem Base Addr */
-	bus_addr_t		 hw_dma_mask;
-	ahd_linux_softc_flags	 flags;
-};
-
-/************************** OS Utility Wrappers *******************************/
-#define printf printk
-#define M_NOWAIT GFP_ATOMIC
-#define M_WAITOK 0
-#define malloc(size, type, flags) kmalloc(size, flags)
-#define free(ptr, type) kfree(ptr)
-
-static __inline void ahd_delay(long);
-static __inline void
-ahd_delay(long usec)
-{
-	/*
-	 * udelay on Linux can have problems for
-	 * multi-millisecond waits.  Wait at most
-	 * 1024us per call.
-	 */
-	while (usec > 0) {
-		udelay(usec % 1024);
-		usec -= 1024;
-	}
-}
-
+/************************** Error Recovery ************************************/
+static __inline void	ahd_wakeup_recovery_thread(struct ahd_softc *ahd); 
+  
+static __inline void
+ahd_wakeup_recovery_thread(struct ahd_softc *ahd)
+{ 
+	up(&ahd->platform_data->recovery_sem);
+}
+ 
+int			ahd_spawn_recovery_thread(struct ahd_softc *ahd);
+void			ahd_terminate_recovery_thread(struct ahd_softc *ahd);
+void			ahd_set_recoveryscb(struct ahd_softc *ahd,
+					    struct scb *scb);
 
 /***************************** Low Level I/O **********************************/
-#if defined(__powerpc__) || defined(__i386__) || defined(__ia64__)
-#define MMAPIO
-#endif
-
 static __inline uint8_t ahd_inb(struct ahd_softc * ahd, long port);
 static __inline uint16_t ahd_inw_atomic(struct ahd_softc * ahd, long port);
 static __inline void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
@@ -603,21 +148,18 @@ static __inline void ahd_outsb(struct ah
 			       uint8_t *, int count);
 static __inline void ahd_insb(struct ahd_softc * ahd, long port,
 			       uint8_t *, int count);
+static __inline void ahd_flush_device_writes(struct ahd_softc *);
 
 static __inline uint8_t
 ahd_inb(struct ahd_softc * ahd, long port)
 {
 	uint8_t x;
-#ifdef MMAPIO
 
 	if (ahd->tags[0] == BUS_SPACE_MEMIO) {
 		x = readb(ahd->bshs[0].maddr + port);
 	} else {
 		x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
 	}
-#else
-	x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
-#endif
 	mb();
 	return (x);
 }
@@ -626,16 +168,12 @@ static __inline uint16_t
 ahd_inw_atomic(struct ahd_softc * ahd, long port)
 {
 	uint8_t x;
-#ifdef MMAPIO
 
 	if (ahd->tags[0] == BUS_SPACE_MEMIO) {
 		x = readw(ahd->bshs[0].maddr + port);
 	} else {
 		x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
 	}
-#else
-	x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
-#endif
 	mb();
 	return (x);
 }
@@ -643,30 +181,22 @@ ahd_inw_atomic(struct ahd_softc * ahd, l
 static __inline void
 ahd_outb(struct ahd_softc * ahd, long port, uint8_t val)
 {
-#ifdef MMAPIO
 	if (ahd->tags[0] == BUS_SPACE_MEMIO) {
 		writeb(val, ahd->bshs[0].maddr + port);
 	} else {
 		outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
 	}
-#else
-	outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
-#endif
 	mb();
 }
 
 static __inline void
 ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val)
 {
-#ifdef MMAPIO
 	if (ahd->tags[0] == BUS_SPACE_MEMIO) {
 		writew(val, ahd->bshs[0].maddr + port);
 	} else {
 		outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
 	}
-#else
-	outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
-#endif
 	mb();
 }
 
@@ -698,6 +228,13 @@ ahd_insb(struct ahd_softc * ahd, long po
 		*array++ = ahd_inb(ahd, port);
 }
 
+static __inline void
+ahd_flush_device_writes(struct ahd_softc *ahd)
+{
+	/* XXX Is this sufficient for all architectures??? */
+	ahd_inb(ahd, INTSTAT);
+}
+
 /**************************** Initialization **********************************/
 int		ahd_linux_register_host(struct ahd_softc *,
 					Scsi_Host_Template *);
@@ -826,384 +363,29 @@ ahd_list_unlock(unsigned long *flags)
 }
 
 /******************************* PCI Definitions ******************************/
-/*
- * PCIM_xxx: mask to locate subfield in register
- * PCIR_xxx: config register offset
- * PCIC_xxx: device class
- * PCIS_xxx: device subclass
- * PCIP_xxx: device programming interface
- * PCIV_xxx: PCI vendor ID (only required to fixup ancient devices)
- * PCID_xxx: device ID
- */
-#define PCIR_DEVVENDOR		0x00
-#define PCIR_VENDOR		0x00
-#define PCIR_DEVICE		0x02
-#define PCIR_COMMAND		0x04
-#define PCIM_CMD_PORTEN		0x0001
-#define PCIM_CMD_MEMEN		0x0002
-#define PCIM_CMD_BUSMASTEREN	0x0004
-#define PCIM_CMD_MWRICEN	0x0010
-#define PCIM_CMD_PERRESPEN	0x0040
-#define	PCIM_CMD_SERRESPEN	0x0100
-#define PCIR_STATUS		0x06
-#define PCIR_REVID		0x08
-#define PCIR_PROGIF		0x09
-#define PCIR_SUBCLASS		0x0a
-#define PCIR_CLASS		0x0b
-#define PCIR_CACHELNSZ		0x0c
-#define PCIR_LATTIMER		0x0d
-#define PCIR_HEADERTYPE		0x0e
-#define PCIM_MFDEV		0x80
-#define PCIR_BIST		0x0f
-#define PCIR_CAP_PTR		0x34
-
-/* config registers for header type 0 devices */
-#define PCIR_MAPS	0x10
-#define PCIR_SUBVEND_0	0x2c
-#define PCIR_SUBDEV_0	0x2e
-
-/****************************** PCI-X definitions *****************************/
-#define PCIXR_COMMAND	0x96
-#define PCIXR_DEVADDR	0x98
-#define PCIXM_DEVADDR_FNUM	0x0003	/* Function Number */
-#define PCIXM_DEVADDR_DNUM	0x00F8	/* Device Number */
-#define PCIXM_DEVADDR_BNUM	0xFF00	/* Bus Number */
-#define PCIXR_STATUS	0x9A
-#define PCIXM_STATUS_64BIT	0x0001	/* Active 64bit connection to device. */
-#define PCIXM_STATUS_133CAP	0x0002	/* Device is 133MHz capable */
-#define PCIXM_STATUS_SCDISC	0x0004	/* Split Completion Discarded */
-#define PCIXM_STATUS_UNEXPSC	0x0008	/* Unexpected Split Completion */
-#define PCIXM_STATUS_CMPLEXDEV	0x0010	/* Device Complexity (set == bridge) */
-#define PCIXM_STATUS_MAXMRDBC	0x0060	/* Maximum Burst Read Count */
-#define PCIXM_STATUS_MAXSPLITS	0x0380	/* Maximum Split Transactions */
-#define PCIXM_STATUS_MAXCRDS	0x1C00	/* Maximum Cumulative Read Size */
-#define PCIXM_STATUS_RCVDSCEM	0x2000	/* Received a Split Comp w/Error msg */
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 extern struct pci_driver aic79xx_pci_driver;
 #endif
 
-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);
-
 /******************************* PCI Routines *********************************/
 int			 ahd_linux_pci_init(void);
 void			 ahd_linux_pci_exit(void);
 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);
-
-static __inline uint32_t
-ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width)
-{
-	switch (width) {
-	case 1:
-	{
-		uint8_t retval;
-
-		pci_read_config_byte(pci, reg, &retval);
-		return (retval);
-	}
-	case 2:
-	{
-		uint16_t retval;
-		pci_read_config_word(pci, reg, &retval);
-		return (retval);
-	}
-	case 4:
-	{
-		uint32_t retval;
-		pci_read_config_dword(pci, reg, &retval);
-		return (retval);
-	}
-	default:
-		panic("ahd_pci_read_config: Read size too big");
-		/* NOTREACHED */
-		return (0);
-	}
-}
-
-static __inline void ahd_pci_write_config(ahd_dev_softc_t pci,
-					  int reg, uint32_t value,
-					  int width);
-
-static __inline void
-ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width)
-{
-	switch (width) {
-	case 1:
-		pci_write_config_byte(pci, reg, value);
-		break;
-	case 2:
-		pci_write_config_word(pci, reg, value);
-		break;
-	case 4:
-		pci_write_config_dword(pci, reg, value);
-		break;
-	default:
-		panic("ahd_pci_write_config: Write size too big");
-		/* NOTREACHED */
-	}
-}
-
-static __inline int ahd_get_pci_function(ahd_dev_softc_t);
-static __inline int
-ahd_get_pci_function(ahd_dev_softc_t pci)
-{
-	return (PCI_FUNC(pci->devfn));
-}
-
-static __inline int ahd_get_pci_slot(ahd_dev_softc_t);
-static __inline int
-ahd_get_pci_slot(ahd_dev_softc_t pci)
-{
-	return (PCI_SLOT(pci->devfn));
-}
-
-static __inline int ahd_get_pci_bus(ahd_dev_softc_t);
-static __inline int
-ahd_get_pci_bus(ahd_dev_softc_t pci)
-{
-	return (pci->bus->number);
-}
-
-static __inline void ahd_flush_device_writes(struct ahd_softc *);
-static __inline void
-ahd_flush_device_writes(struct ahd_softc *ahd)
-{
-	/* XXX Is this sufficient for all architectures??? */
-	ahd_inb(ahd, INTSTAT);
-}
-
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0)
-#define pci_map_sg(pdev, sg_list, nseg, direction) (nseg)
-#define pci_unmap_sg(pdev, sg_list, nseg, direction)
-#define sg_dma_address(sg) (VIRT_TO_BUS((sg)->address))
-#define sg_dma_len(sg) ((sg)->length)
-#define pci_map_single(pdev, buffer, bufflen, direction) \
-	(VIRT_TO_BUS(buffer))
-#define pci_unmap_single(pdev, buffer, buflen, direction)
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
-#define ahd_pci_set_dma_mask pci_set_dma_mask
-#else
-/*
- * Always "return" 0 for success.
- */
-#define ahd_pci_set_dma_mask(dev_softc, mask)	\
-	(((dev_softc)->dma_mask = mask) && 0)
-#endif
 /**************************** Proc FS Support *********************************/
-int	ahd_linux_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
-
-/*************************** Domain Validation ********************************/
-#define AHD_DV_CMD(cmd) ((cmd)->scsi_done == ahd_linux_dv_complete)
-#define AHD_DV_SIMQ_FROZEN(ahd)					\
-	((((ahd)->platform_data->flags & AHD_DV_ACTIVE) != 0)	\
-	 && (ahd)->platform_data->qfrozen == 1)
-
-/*********************** Transaction Access Wrappers **************************/
-static __inline void ahd_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t);
-static __inline void ahd_set_transaction_status(struct scb *, uint32_t);
-static __inline void ahd_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t);
-static __inline void ahd_set_scsi_status(struct scb *, uint32_t);
-static __inline uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd);
-static __inline uint32_t ahd_get_transaction_status(struct scb *);
-static __inline uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd);
-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 *scb, u_long resid);
-static __inline u_long ahd_get_residual(struct scb *);
-static __inline u_long ahd_get_sense_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_notify_xfer_settings_change(struct ahd_softc *,
-						     struct ahd_devinfo *);
-static __inline void ahd_platform_scb_free(struct ahd_softc *ahd,
-					   struct scb *scb);
-static __inline void ahd_freeze_scb(struct scb *scb);
-
-static __inline
-void ahd_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status)
-{
-	cmd->result &= ~(CAM_STATUS_MASK << 16);
-	cmd->result |= status << 16;
-}
-
-static __inline
-void ahd_set_transaction_status(struct scb *scb, uint32_t status)
-{
-	ahd_cmd_set_transaction_status(scb->io_ctx,status);
-}
-
-static __inline
-void ahd_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status)
-{
-	cmd->result &= ~0xFFFF;
-	cmd->result |= status;
-}
-
-static __inline
-void ahd_set_scsi_status(struct scb *scb, uint32_t status)
-{
-	ahd_cmd_set_scsi_status(scb->io_ctx, status);
-}
-
-static __inline
-uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd)
-{
-	return ((cmd->result >> 16) & CAM_STATUS_MASK);
-}
-
-static __inline
-uint32_t ahd_get_transaction_status(struct scb *scb)
-{
-	return (ahd_cmd_get_transaction_status(scb->io_ctx));
-}
-
-static __inline
-uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd)
-{
-	return (cmd->result & 0xFFFF);
-}
-
-static __inline
-uint32_t ahd_get_scsi_status(struct scb *scb)
-{
-	return (ahd_cmd_get_scsi_status(scb->io_ctx));
-}
-
-static __inline
-void ahd_set_transaction_tag(struct scb *scb, int enabled, u_int type)
-{
-	/*
-	 * Nothing to do for linux as the incoming transaction
-	 * has no concept of tag/non tagged, etc.
-	 */
-}
-
-static __inline
-u_long ahd_get_transfer_length(struct scb *scb)
-{
-	return (scb->platform_data->xfer_len);
-}
-
-static __inline
-int ahd_get_transfer_dir(struct scb *scb)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40)
-	return (scb->io_ctx->sc_data_direction);
-#else
-	if (scb->io_ctx->bufflen == 0)
-		return (CAM_DIR_NONE);
-
-	switch(scb->io_ctx->cmnd[0]) {
-	case 0x08:  /* READ(6)  */
-	case 0x28:  /* READ(10) */
-	case 0xA8:  /* READ(12) */
-		return (CAM_DIR_IN);
-        case 0x0A:  /* WRITE(6)  */
-        case 0x2A:  /* WRITE(10) */
-        case 0xAA:  /* WRITE(12) */
-		return (CAM_DIR_OUT);
-        default:
-		return (CAM_DIR_NONE);
-        }
-#endif
-}
-
-static __inline
-void ahd_set_residual(struct scb *scb, u_long resid)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	scb->io_ctx->resid = resid;
-#else
-	scb->platform_data->resid = resid;
-#endif
-}
-
-static __inline
-void ahd_set_sense_residual(struct scb *scb, u_long resid)
-{
-	scb->platform_data->sense_resid = resid;
-}
-
-static __inline
-u_long ahd_get_residual(struct scb *scb)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	return (scb->io_ctx->resid);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+int	ahd_linux_proc_info(char *, char **, off_t, int, int, int);
 #else
-	return (scb->platform_data->resid);
+int	ahd_linux_proc_info(struct Scsi_Host *, char *, char **,
+			    off_t, int, int);
 #endif
-}
-
-static __inline
-u_long ahd_get_sense_residual(struct scb *scb)
-{
-	return (scb->platform_data->sense_resid);
-}
-
-static __inline
-int ahd_perform_autosense(struct scb *scb)
-{
-	/*
-	 * We always perform autosense in Linux.
-	 * On other platforms this is set on a
-	 * per-transaction basis.
-	 */
-	return (1);
-}
-
-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_notify_xfer_settings_change(struct ahd_softc *ahd,
-				struct ahd_devinfo *devinfo)
-{
-	/* Nothing to do here for linux */
-}
-
-static __inline void
-ahd_platform_scb_free(struct ahd_softc *ahd, struct scb *scb)
-{
-	ahd->flags &= ~AHD_RESOURCE_SHORTAGE;
-}
 
+/*********************** Transaction Access Wrappers **************************/
 int	ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg);
 void	ahd_platform_free(struct ahd_softc *ahd);
 void	ahd_platform_init(struct ahd_softc *ahd);
 void	ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb);
-void	ahd_freeze_simq(struct ahd_softc *ahd);
-void	ahd_release_simq(struct ahd_softc *ahd);
-
-static __inline void
-ahd_freeze_scb(struct scb *scb)
-{
-	if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) {
-                scb->io_ctx->result |= CAM_DEV_QFRZN << 16;
-                scb->platform_data->dev->qfrozen++;
-        }
-}
 
 void	ahd_platform_set_tags(struct ahd_softc *ahd,
 			      struct ahd_devinfo *devinfo, ahd_queue_alg);
@@ -1221,9 +403,9 @@ void	ahd_print_path(struct ahd_softc *, 
 void	ahd_platform_dump_card_state(struct ahd_softc *ahd);
 
 #ifdef CONFIG_PCI
-#define AHD_PCI_CONFIG 1
+#define AIC_PCI_CONFIG 1
 #else
-#define AHD_PCI_CONFIG 0
+#define AIC_PCI_CONFIG 0
 #endif
 #define bootverbose aic79xx_verbose
 extern uint32_t aic79xx_verbose;
diff -puN drivers/scsi/aic7xxx/aic79xx_osm_pci.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic79xx_osm_pci.c
--- 25/drivers/scsi/aic7xxx/aic79xx_osm_pci.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic79xx_osm_pci.c	Wed Dec 24 12:15:38 2003
@@ -36,12 +36,18 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm_pci.c#23 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm_pci.c#29 $
  */
 
 #include "aic79xx_osm.h"
 #include "aic79xx_inline.h"
 
+/*
+ * Include aiclib_pci.c as part of our
+ * "module dependencies are hard" work around.
+ */
+#include "aiclib_pci.c"
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
 struct pci_device_id
 {
@@ -52,11 +58,9 @@ static int	ahd_linux_pci_dev_probe(struc
 					const struct pci_device_id *ent);
 static int	ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd,
 						 u_long *base, u_long *base2);
-#ifdef MMAPIO
 static int	ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
 						 u_long *bus_addr,
 						 uint8_t **maddr);
-#endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 static void	ahd_linux_pci_dev_remove(struct pci_dev *pdev);
 
@@ -94,12 +98,14 @@ ahd_linux_pci_dev_remove(struct pci_dev 
 	if (ahd != NULL) {
 		u_long s;
 
+		TAILQ_REMOVE(&ahd_tailq, ahd, links);
+		ahd_list_unlock(&l);
 		ahd_lock(ahd, &s);
 		ahd_intr_enable(ahd, FALSE);
 		ahd_unlock(ahd, &s);
 		ahd_free(ahd);
-	}
-	ahd_list_unlock(&l);
+	} else
+		ahd_list_unlock(&l);
 }
 #endif /* !LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) */
 
@@ -108,7 +114,7 @@ ahd_linux_pci_dev_probe(struct pci_dev *
 {
 	char		 buf[80];
 	struct		 ahd_softc *ahd;
-	ahd_dev_softc_t	 pci;
+	aic_dev_softc_t	 dev;
 	struct		 ahd_pci_identity *entry;
 	char		*name;
 	int		 error;
@@ -119,7 +125,7 @@ ahd_linux_pci_dev_probe(struct pci_dev *
 	TAILQ_FOREACH(ahd, &ahd_tailq, links) {
 		struct pci_dev *probed_pdev;
 
-		probed_pdev = ahd->dev_softc;
+		probed_pdev = aic_pci_dev(ahd);
 		if (probed_pdev->bus->number == pdev->bus->number
 		 && probed_pdev->devfn == pdev->devfn)
 			break;
@@ -129,8 +135,8 @@ ahd_linux_pci_dev_probe(struct pci_dev *
 		return (-ENODEV);
 	}
 
-	pci = pdev;
-	entry = ahd_find_pci_device(pci);
+	dev = aic_pci_dev_to_dev(pdev);
+	entry = ahd_find_pci_device(dev);
 	if (entry == NULL)
 		return (-ENODEV);
 
@@ -140,9 +146,9 @@ ahd_linux_pci_dev_probe(struct pci_dev *
 	 * common detect routine.
 	 */
 	sprintf(buf, "ahd_pci:%d:%d:%d",
-		ahd_get_pci_bus(pci),
-		ahd_get_pci_slot(pci),
-		ahd_get_pci_function(pci));
+		aic_get_pci_bus(dev),
+		aic_get_pci_slot(dev),
+		aic_get_pci_function(dev));
 	name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
 	if (name == NULL)
 		return (-ENOMEM);
@@ -150,6 +156,7 @@ ahd_linux_pci_dev_probe(struct pci_dev *
 	ahd = ahd_alloc(NULL, name);
 	if (ahd == NULL)
 		return (-ENOMEM);
+	ahd->dev_softc = dev;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 	if (pci_enable_device(pdev)) {
 		ahd_free(ahd);
@@ -163,23 +170,22 @@ ahd_linux_pci_dev_probe(struct pci_dev *
 		bus_addr_t mask_39bit;
 
 		memsize = ahd_linux_get_memsize();
-		mask_64bit = (bus_addr_t)(0xFFFFFFFFFFFFFFFFULL&(bus_addr_t)~0);
-		mask_39bit = (bus_addr_t)(0x7FFFFFFFFFULL&(bus_addr_t)~0);
+		mask_64bit = (bus_addr_t)0xFFFFFFFFFFFFFFFFULL;
+		mask_39bit = (bus_addr_t)0x7FFFFFFFFFULL;
 		if (memsize >= 0x8000000000ULL
-	 	 && ahd_pci_set_dma_mask(pdev, mask_64bit) == 0) {
+	 	 && aic_set_dma_mask(ahd, mask_64bit) == 0) {
 			ahd->flags |= AHD_64BIT_ADDRESSING;
 			ahd->platform_data->hw_dma_mask = mask_64bit;
 		} else if (memsize > 0x80000000
-			&& ahd_pci_set_dma_mask(pdev, mask_39bit) == 0) {
+			&& aic_set_dma_mask(ahd, mask_39bit) == 0) {
 			ahd->flags |= AHD_39BIT_ADDRESSING;
 			ahd->platform_data->hw_dma_mask = mask_39bit;
 		}
 	} else {
-		ahd_pci_set_dma_mask(pdev, 0xFFFFFFFF);
+		aic_set_dma_mask(ahd, 0xFFFFFFFF);
 		ahd->platform_data->hw_dma_mask = 0xFFFFFFFF;
 	}
 #endif
-	ahd->dev_softc = pci;
 	error = ahd_pci_config(ahd, entry);
 	if (error != 0) {
 		ahd_free(ahd);
@@ -218,10 +224,8 @@ ahd_linux_pci_init(void)
 	pdev = NULL;
 	class = PCI_CLASS_STORAGE_SCSI << 8;
 	while ((pdev = pci_find_class(class, pdev)) != NULL) {
-		ahd_dev_softc_t pci;
 		int error;
 
-		pci = pdev;
 		error = ahd_linux_pci_dev_probe(pdev, /*pci_devid*/NULL);
 		if (error == 0)
 			found++;
@@ -240,17 +244,18 @@ static int
 ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base,
 				 u_long *base2)
 {
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	*base = pci_resource_start(ahd->dev_softc, 0);
+	*base = pci_resource_start(aic_pci_dev(ahd), 0);
 	/*
 	 * This is really the 3rd bar and should be at index 2,
 	 * but the Linux PCI code doesn't know how to "count" 64bit
 	 * bars.
 	 */
-	*base2 = pci_resource_start(ahd->dev_softc, 3);
+	*base2 = pci_resource_start(aic_pci_dev(ahd), 3);
 #else
-	*base = ahd_pci_read_config(ahd->dev_softc, AHD_PCI_IOADDR0, 4);
-	*base2 = ahd_pci_read_config(ahd->dev_softc, AHD_PCI_IOADDR1, 4);
+	*base = aic_pci_read_config(ahd->dev_softc, AHD_PCI_IOADDR0, 4);
+	*base2 = aic_pci_read_config(ahd->dev_softc, AHD_PCI_IOADDR1, 4);
 	*base &= PCI_BASE_ADDRESS_IO_MASK;
 	*base2 &= PCI_BASE_ADDRESS_IO_MASK;
 #endif
@@ -273,7 +278,6 @@ ahd_linux_pci_reserve_io_regions(struct 
 	return (0);
 }
 
-#ifdef MMAPIO
 static int
 ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
 				 u_long *bus_addr,
@@ -292,11 +296,11 @@ ahd_linux_pci_reserve_mem_region(struct 
 
 	error = 0;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	start = pci_resource_start(ahd->dev_softc, 1);
+	start = pci_resource_start(aic_pci_dev(ahd), 1);
 	base_page = start & PAGE_MASK;
 	base_offset = start - base_page;
 #else
-	start = ahd_pci_read_config(ahd->dev_softc, PCIR_MAPS+4, 4);
+	start = aic_pci_read_config(ahd->dev_softc, PCIR_MAPS+4, 4);
 	base_offset = start & PCI_BASE_ADDRESS_MEM_MASK;
 	base_page = base_offset & PAGE_MASK;
 	base_offset -= base_page;
@@ -321,7 +325,6 @@ ahd_linux_pci_reserve_mem_region(struct 
 		error = ENOMEM;
 	return (error);
 }
-#endif
 
 int
 ahd_pci_map_registers(struct ahd_softc *ahd)
@@ -334,11 +337,10 @@ ahd_pci_map_registers(struct ahd_softc *
 	/*
 	 * If its allowed, we prefer memory mapped access.
 	 */
-	command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 4);
+	command = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 4);
 	command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN);
 	base = 0;
 	maddr = NULL;
-#ifdef MMAPIO
 	error = ahd_linux_pci_reserve_mem_region(ahd, &base, &maddr);
 	if (error == 0) {
 		ahd->platform_data->mem_busaddr = base;
@@ -346,16 +348,16 @@ ahd_pci_map_registers(struct ahd_softc *
 		ahd->bshs[0].maddr = maddr;
 		ahd->tags[1] = BUS_SPACE_MEMIO;
 		ahd->bshs[1].maddr = maddr + 0x100;
-		ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
+		aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
 				     command | PCIM_CMD_MEMEN, 4);
 
 		if (ahd_pci_test_register_access(ahd) != 0) {
 
 			printf("aic79xx: 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));
 			iounmap((void *)((u_long)maddr & PAGE_MASK));
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 			release_mem_region(ahd->platform_data->mem_busaddr,
@@ -368,12 +370,11 @@ ahd_pci_map_registers(struct ahd_softc *
 	} else if (bootverbose) {
 		printf("aic79xx: PCI%d:%d:%d MEM region 0x%lx "
 		       "unavailable. Cannot memory map device.\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),
 		       base);
 	}
-#endif
 
 	if (maddr == NULL) {
 		u_long	 base2;
@@ -388,13 +389,13 @@ ahd_pci_map_registers(struct ahd_softc *
 		} else {
 			printf("aic79xx: PCI%d:%d:%d IO regions 0x%lx and 0x%lx"
 			       "unavailable. Cannot map device.\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),
 			       base, base2);
 		}
 	}
-	ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4);
+	aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4);
 	return (error);
 }
 
@@ -403,49 +404,10 @@ ahd_pci_map_int(struct ahd_softc *ahd)
 {
 	int error;
 
-	error = request_irq(ahd->dev_softc->irq, ahd_linux_isr,
+	error = request_irq(aic_pci_dev(ahd)->irq, ahd_linux_isr,
 			    SA_SHIRQ, "aic79xx", ahd);
 	if (error == 0)
-		ahd->platform_data->irq = ahd->dev_softc->irq;
+		ahd->platform_data->irq = aic_pci_dev(ahd)->irq;
 	
 	return (-error);
 }
-
-void
-ahd_power_state_change(struct ahd_softc *ahd, ahd_power_state new_state)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	pci_set_power_state(ahd->dev_softc, new_state);
-#else
-	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*/4);
-			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;
-	}
-#endif 
-}
diff -puN drivers/scsi/aic7xxx/aic79xx_pci.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic79xx_pci.c
--- 25/drivers/scsi/aic7xxx/aic79xx_pci.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic79xx_pci.c	Wed Dec 24 12:15:38 2003
@@ -38,15 +38,15 @@
  * 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#73 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#84 $
  */
 
 #ifdef __linux__
 #include "aic79xx_osm.h"
 #include "aic79xx_inline.h"
 #else
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 #include <dev/aic7xxx/aic79xx_osm.h>
 #include <dev/aic7xxx/aic79xx_inline.h>
 #endif
@@ -75,13 +75,13 @@ ahd_compose_id(u_int device, u_int vendo
 #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
@@ -117,6 +117,7 @@ ahd_compose_id(u_int device, u_int vendo
 static ahd_device_setup_t ahd_aic7901_setup;
 static ahd_device_setup_t ahd_aic7901A_setup;
 static ahd_device_setup_t ahd_aic7902_setup;
+static ahd_device_setup_t ahd_aic790X_setup;
 
 struct ahd_pci_identity ahd_pci_ident_table [] =
 {
@@ -135,24 +136,24 @@ struct ahd_pci_identity ahd_pci_ident_ta
 	},
 	/* 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,
@@ -195,18 +196,6 @@ struct ahd_pci_identity ahd_pci_ident_ta
 		"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,
@@ -274,7 +263,7 @@ static void	ahd_configure_termination(st
 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;
@@ -284,10 +273,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,
@@ -320,7 +309,7 @@ ahd_pci_config(struct ahd_softc *ahd, st
 	/*
 	 * 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;
@@ -329,7 +318,7 @@ ahd_pci_config(struct ahd_softc *ahd, st
 	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. */
@@ -339,7 +328,7 @@ ahd_pci_config(struct ahd_softc *ahd, st
 	}
 	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)
@@ -357,17 +346,17 @@ ahd_pci_config(struct ahd_softc *ahd, st
 		if (bootverbose)
 			printf("%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)
@@ -375,12 +364,12 @@ ahd_pci_config(struct ahd_softc *ahd, st
 
 	ahd->bus_intr = ahd_pci_intr;
 
-	error = ahd_reset(ahd);
+	error = ahd_reset(ahd, /*reinit*/FALSE);
 	if (error != 0)
 		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;
 
@@ -418,9 +407,11 @@ ahd_pci_config(struct ahd_softc *ahd, st
 int
 ahd_pci_test_register_access(struct ahd_softc *ahd)
 {
-	uint32_t	cmd;
-	int		error;
-	uint8_t		hcntrl;
+	uint32_t cmd;
+	u_int	 targpcistat;
+	u_int	 pci_status1;
+	int	 error;
+	uint8_t	 hcntrl;
 
 	error = EIO;
 
@@ -428,8 +419,8 @@ ahd_pci_test_register_access(struct 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);
 
 	/*
@@ -449,11 +440,25 @@ ahd_pci_test_register_access(struct ahd_
 	 * or read prefetching could be initiated by the
 	 * CPU or host bridge.  Our device does not support
 	 * either, so look for data corruption and/or flaged
-	 * PCI errors.
+	 * PCI errors.  First pause without causing another
+	 * chip reset.
 	 */
+	hcntrl &= ~CHIPRST;
 	ahd_outb(ahd, HCNTRL, hcntrl|PAUSE);
 	while (ahd_is_paused(ahd) == 0)
 		;
+
+	/* Clear any PCI errors that occurred before our driver attached. */
+	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
+	targpcistat = ahd_inb(ahd, TARGPCISTAT);
+	ahd_outb(ahd, TARGPCISTAT, targpcistat);
+	pci_status1 = aic_pci_read_config(ahd->dev_softc,
+					  PCIR_STATUS + 1, /*bytes*/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);
+
 	ahd_outb(ahd, SEQCTL0, PERRORDIS);
 	ahd_outl(ahd, SRAM_BASE, 0x5aa555aa);
 	if (ahd_inl(ahd, SRAM_BASE) != 0x5aa555aa)
@@ -472,23 +477,20 @@ ahd_pci_test_register_access(struct ahd_
 
 fail:
 	if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {
-		u_int targpcistat;
-		u_int pci_status1;
 
 		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
 		targpcistat = ahd_inb(ahd, TARGPCISTAT);
 
 		/* 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);
 }
 
@@ -637,14 +639,14 @@ ahd_configure_termination(struct ahd_sof
 	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)
 		printf("%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) {
@@ -689,6 +691,7 @@ ahd_configure_termination(struct ahd_sof
 	 * 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;
@@ -821,9 +824,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);
@@ -845,7 +848,7 @@ ahd_pci_split_intr(struct ahd_softc *ahd
 	 * 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);
 	printf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n",
 	       ahd_name(ahd), pcix_status);
@@ -894,7 +897,7 @@ ahd_pci_split_intr(struct ahd_softc *ahd
 	/*
 	 * 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);
@@ -903,44 +906,44 @@ ahd_pci_split_intr(struct ahd_softc *ahd
 static int
 ahd_aic7901_setup(struct ahd_softc *ahd)
 {
-	int error;
 
-	error = ahd_aic7902_setup(ahd);
-	if (error != 0)
-		return (error);
 	ahd->chip = AHD_AIC7901;
-	return (0);
+	ahd->features = AHD_AIC7901_FE;
+	return (ahd_aic790X_setup(ahd));
 }
 
 static int
 ahd_aic7901A_setup(struct ahd_softc *ahd)
 {
-	int error;
 
-	error = ahd_aic7902_setup(ahd);
-	if (error != 0)
-		return (error);
 	ahd->chip = AHD_AIC7901A;
-	return (0);
+	ahd->features = AHD_AIC7901A_FE;
+	return (ahd_aic790X_setup(ahd));
 }
 
 static int
 ahd_aic7902_setup(struct ahd_softc *ahd)
 {
-	ahd_dev_softc_t pci;
+	ahd->chip = AHD_AIC7902;
+	ahd->features = AHD_AIC7902_FE;
+	return (ahd_aic790X_setup(ahd));
+}
+
+static int
+ahd_aic790X_setup(struct ahd_softc *ahd)
+{
+	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) {
 		printf("%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->chip = AHD_AIC7902;
-	ahd->features = AHD_AIC7902_FE;
+	ahd->channel = aic_get_pci_function(pci) + 'A';
 	if (rev < ID_AIC7902_PCI_REV_B0) {
 		/*
 		 * Enable A series workarounds.
@@ -968,9 +971,14 @@ ahd_aic7902_setup(struct ahd_softc *ahd)
 		u_int devconfig1;
 
 		ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS
-			      |  AHD_NEW_DFCNTRL_OPTS;
-		ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_ABORT_LQI_BUG
-			  |  AHD_INTCOLLISION_BUG|AHD_EARLY_REQ_BUG;
+			      |  AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY;
+		ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG;
+
+		/*
+		 * Some issues have been resolved in the 7901B.
+		 */
+		if ((ahd->features & AHD_MULTI_FUNC) != 0)
+			ahd->bugs |= AHD_INTCOLLISION_BUG|AHD_ABORT_LQI_BUG;
 
 		/*
 		 * IO Cell paramter setup.
@@ -985,10 +993,10 @@ ahd_aic7902_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);
diff -puN drivers/scsi/aic7xxx/aic79xx_proc.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic79xx_proc.c
--- 25/drivers/scsi/aic7xxx/aic79xx_proc.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic79xx_proc.c	Wed Dec 24 12:15:38 2003
@@ -37,7 +37,7 @@
  * String handling code courtesy of Gerard Roudier's <groudier@club-internet.fr>
  * sym driver.
  *
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#17 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#20 $
  */
 #include "aic79xx_osm.h"
 #include "aic79xx_inline.h"
@@ -49,7 +49,7 @@ static void	ahd_dump_target_state(struct
 				      u_int our_id, char channel,
 				      u_int target_id, u_int target_offset);
 static void	ahd_dump_device_state(struct info_str *info,
-				      struct ahd_linux_device *dev);
+				      struct aic_linux_device *dev);
 static int	ahd_proc_write_seeprom(struct ahd_softc *ahd,
 				       char *buffer, int length);
 
@@ -166,7 +166,7 @@ ahd_dump_target_state(struct ahd_softc *
 		      u_int our_id, char channel, u_int target_id,
 		      u_int target_offset)
 {
-	struct	ahd_linux_target *targ;
+	struct	aic_linux_target *targ;
 	struct	ahd_initiator_tinfo *tinfo;
 	struct	ahd_tmode_tstate *tstate;
 	int	lun;
@@ -187,7 +187,7 @@ ahd_dump_target_state(struct ahd_softc *
 	copy_info(info, "\tTransmission Errors %ld\n", targ->errors_detected);
 
 	for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
-		struct ahd_linux_device *dev;
+		struct aic_linux_device *dev;
 
 		dev = targ->devices[lun];
 
@@ -199,7 +199,7 @@ ahd_dump_target_state(struct ahd_softc *
 }
 
 static void
-ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev)
+ahd_dump_device_state(struct info_str *info, struct aic_linux_device *dev)
 {
 	copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
 		  dev->target->channel + 'A', dev->target->target, dev->lun);
@@ -278,8 +278,13 @@ done:
  * Return information to handle /proc support for the driver.
  */
 int
-ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset,
-		  int length, int inout)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ahd_linux_proc_info(char *buffer, char **start, off_t offset,
+		    int length, int hostno, int inout)
+#else
+ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
+		    off_t offset, int length, int inout)
+#endif
 {
 	struct	ahd_softc *ahd;
 	struct	info_str info;
@@ -291,10 +296,14 @@ ahd_linux_proc_info(struct Scsi_Host *sh
 
 	retval = -EINVAL;
 	ahd_list_lock(&l);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	TAILQ_FOREACH(ahd, &ahd_tailq, links) {
-		if (ahd->platform_data->host == shost)
+		if (ahd->platform_data->host->host_no == hostno)
 			break;
 	}
+#else
+	ahd = ahd_find_softc(*(struct ahd_softc **)shost->hostdata);
+#endif
 
 	if (ahd == NULL)
 		goto done;
diff -puN drivers/scsi/aic7xxx/aic79xx.reg~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic79xx.reg
--- 25/drivers/scsi/aic7xxx/aic79xx.reg~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic79xx.reg	Wed Dec 24 12:15:38 2003
@@ -39,7 +39,7 @@
  *
  * $FreeBSD$
  */
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#69 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $"
 
 /*
  * This file is processed by the aic7xxx_asm utility for use in assembling
@@ -1377,7 +1377,10 @@ register LUNLEN {
 	address			0x030
 	access_mode	RW
 	modes		M_CFG
+	mask		ILUNLEN	0x0F
+	mask		TLUNLEN	0xF0
 }
+const LUNLEN_SINGLE_LEVEL_LUN 0xF
 
 /*
  * CDB Limit
@@ -3797,32 +3800,8 @@ scb {
 		size	4
 		alias	SCB_NEXT_COMPLETE
 	}
-	SCB_DATAPTR {
-		size	8
-	}
-	SCB_DATACNT {
-		/*
-		 * The last byte is really the high address bits for
-		 * the data address.
-		 */
-		size	4
-		field	SG_LAST_SEG		0x80	/* In the fourth byte */
-		field	SG_HIGH_ADDR_BITS	0x7F	/* In the fourth byte */
-	}
-	SCB_SGPTR {
-		size	4
-		field	SG_STATUS_VALID	0x04	/* In the first byte */
-		field	SG_FULL_RESID	0x02	/* In the first byte */
-		field	SG_LIST_NULL	0x01	/* In the first byte */
-	}
-	SCB_BUSADDR {
-		size	4
-	}
-	SCB_NEXT {
-		alias	SCB_NEXT_SCB_BUSADDR
-		size	2
-	}
-	SCB_NEXT2 {
+	SCB_TAG {
+		alias	SCB_FIFO_USE_COUNT
 		size	2
 	}
 	SCB_CONTROL {
@@ -3859,8 +3838,32 @@ scb {
 	SCB_TASK_MANAGEMENT {
 		size	1
 	}
-	SCB_TAG {
-		alias	SCB_FIFO_USE_COUNT
+	SCB_DATAPTR {
+		size	8
+	}
+	SCB_DATACNT {
+		/*
+		 * The last byte is really the high address bits for
+		 * the data address.
+		 */
+		size	4
+		field	SG_LAST_SEG		0x80	/* In the fourth byte */
+		field	SG_HIGH_ADDR_BITS	0x7F	/* In the fourth byte */
+	}
+	SCB_SGPTR {
+		size	4
+		field	SG_STATUS_VALID	0x04	/* In the first byte */
+		field	SG_FULL_RESID	0x02	/* In the first byte */
+		field	SG_LIST_NULL	0x01	/* In the first byte */
+	}
+	SCB_BUSADDR {
+		size	4
+	}
+	SCB_NEXT {
+		alias	SCB_NEXT_SCB_BUSADDR
+		size	2
+	}
+	SCB_NEXT2 {
 		size	2
 	}
 	SCB_SPARE {
diff -puN drivers/scsi/aic7xxx/aic79xx_reg.h_shipped~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
--- 25/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped	Wed Dec 24 12:15:38 2003
@@ -2,8 +2,8 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#69 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#107 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
  */
 typedef int (ahd_reg_print_t)(u_int, u_int *, u_int);
 typedef struct ahd_reg_parse_entry {
@@ -2239,94 +2239,94 @@ ahd_reg_print_t ahd_scb_sense_busaddr_pr
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_dataptr_print;
+ahd_reg_print_t ahd_scb_tag_print;
 #else
-#define ahd_scb_dataptr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_DATAPTR", 0x190, regvalue, cur_col, wrap)
+#define ahd_scb_tag_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_TAG", 0x190, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_datacnt_print;
+ahd_reg_print_t ahd_scb_control_print;
 #else
-#define ahd_scb_datacnt_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_DATACNT", 0x198, regvalue, cur_col, wrap)
+#define ahd_scb_control_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_CONTROL", 0x192, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_sgptr_print;
+ahd_reg_print_t ahd_scb_scsiid_print;
 #else
-#define ahd_scb_sgptr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_SGPTR", 0x19c, regvalue, cur_col, wrap)
+#define ahd_scb_scsiid_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_SCSIID", 0x193, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_busaddr_print;
+ahd_reg_print_t ahd_scb_lun_print;
 #else
-#define ahd_scb_busaddr_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_BUSADDR", 0x1a0, regvalue, cur_col, wrap)
+#define ahd_scb_lun_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_LUN", 0x194, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_next_print;
+ahd_reg_print_t ahd_scb_task_attribute_print;
 #else
-#define ahd_scb_next_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_NEXT", 0x1a4, regvalue, cur_col, wrap)
+#define ahd_scb_task_attribute_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_TASK_ATTRIBUTE", 0x195, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_next2_print;
+ahd_reg_print_t ahd_scb_cdb_len_print;
 #else
-#define ahd_scb_next2_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_NEXT2", 0x1a6, regvalue, cur_col, wrap)
+#define ahd_scb_cdb_len_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_CDB_LEN", 0x196, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_control_print;
+ahd_reg_print_t ahd_scb_task_management_print;
 #else
-#define ahd_scb_control_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_CONTROL", 0x1a8, regvalue, cur_col, wrap)
+#define ahd_scb_task_management_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT", 0x197, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_scsiid_print;
+ahd_reg_print_t ahd_scb_dataptr_print;
 #else
-#define ahd_scb_scsiid_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_SCSIID", 0x1a9, regvalue, cur_col, wrap)
+#define ahd_scb_dataptr_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_DATAPTR", 0x198, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_lun_print;
+ahd_reg_print_t ahd_scb_datacnt_print;
 #else
-#define ahd_scb_lun_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_LUN", 0x1aa, regvalue, cur_col, wrap)
+#define ahd_scb_datacnt_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_DATACNT", 0x1a0, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_task_attribute_print;
+ahd_reg_print_t ahd_scb_sgptr_print;
 #else
-#define ahd_scb_task_attribute_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_TASK_ATTRIBUTE", 0x1ab, regvalue, cur_col, wrap)
+#define ahd_scb_sgptr_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_SGPTR", 0x1a4, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_cdb_len_print;
+ahd_reg_print_t ahd_scb_busaddr_print;
 #else
-#define ahd_scb_cdb_len_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_CDB_LEN", 0x1ac, regvalue, cur_col, wrap)
+#define ahd_scb_busaddr_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_BUSADDR", 0x1a8, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_task_management_print;
+ahd_reg_print_t ahd_scb_next_print;
 #else
-#define ahd_scb_task_management_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT", 0x1ad, regvalue, cur_col, wrap)
+#define ahd_scb_next_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_NEXT", 0x1ac, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scb_tag_print;
+ahd_reg_print_t ahd_scb_next2_print;
 #else
-#define ahd_scb_tag_print(regvalue, cur_col, wrap) \
-    ahd_print_register(NULL, 0, "SCB_TAG", 0x1ae, regvalue, cur_col, wrap)
+#define ahd_scb_next2_print(regvalue, cur_col, wrap) \
+    ahd_print_register(NULL, 0, "SCB_NEXT2", 0x1ae, regvalue, cur_col, wrap)
 #endif
 
 #if AIC_DEBUG_REGISTERS
@@ -2557,6 +2557,8 @@ ahd_reg_print_t ahd_scb_disconnected_lis
 #define	SHORTTHRESH     		0x2f
 
 #define	LUNLEN          		0x30
+#define		TLUNLEN         	0xf0
+#define		ILUNLEN         	0x0f
 
 #define	CDBLIMIT        		0x31
 
@@ -3648,25 +3650,10 @@ ahd_reg_print_t ahd_scb_disconnected_lis
 #define	SCB_SENSE_BUSADDR		0x18c
 #define	SCB_NEXT_COMPLETE		0x18c
 
-#define	SCB_DATAPTR     		0x190
-
-#define	SCB_DATACNT     		0x198
-#define		SG_LAST_SEG     	0x80
-#define		SG_HIGH_ADDR_BITS	0x7f
-
-#define	SCB_SGPTR       		0x19c
-#define		SG_STATUS_VALID 	0x04
-#define		SG_FULL_RESID   	0x02
-#define		SG_LIST_NULL    	0x01
+#define	SCB_TAG         		0x190
+#define	SCB_FIFO_USE_COUNT		0x190
 
-#define	SCB_BUSADDR     		0x1a0
-
-#define	SCB_NEXT        		0x1a4
-#define	SCB_NEXT_SCB_BUSADDR		0x1a4
-
-#define	SCB_NEXT2       		0x1a6
-
-#define	SCB_CONTROL     		0x1a8
+#define	SCB_CONTROL     		0x192
 #define		TARGET_SCB      	0x80
 #define		DISCENB         	0x40
 #define		TAG_ENB         	0x20
@@ -3675,23 +3662,38 @@ ahd_reg_print_t ahd_scb_disconnected_lis
 #define		DISCONNECTED    	0x04
 #define		SCB_TAG_TYPE    	0x03
 
-#define	SCB_SCSIID      		0x1a9
+#define	SCB_SCSIID      		0x193
 #define		TID             	0xf0
 #define		OID             	0x0f
 
-#define	SCB_LUN         		0x1aa
+#define	SCB_LUN         		0x194
 #define		LID             	0xff
 
-#define	SCB_TASK_ATTRIBUTE		0x1ab
+#define	SCB_TASK_ATTRIBUTE		0x195
 #define		SCB_XFERLEN_ODD 	0x01
 
-#define	SCB_CDB_LEN     		0x1ac
+#define	SCB_CDB_LEN     		0x196
 #define		SCB_CDB_LEN_PTR 	0x80
 
-#define	SCB_TASK_MANAGEMENT		0x1ad
+#define	SCB_TASK_MANAGEMENT		0x197
+
+#define	SCB_DATAPTR     		0x198
+
+#define	SCB_DATACNT     		0x1a0
+#define		SG_LAST_SEG     	0x80
+#define		SG_HIGH_ADDR_BITS	0x7f
+
+#define	SCB_SGPTR       		0x1a4
+#define		SG_STATUS_VALID 	0x04
+#define		SG_FULL_RESID   	0x02
+#define		SG_LIST_NULL    	0x01
+
+#define	SCB_BUSADDR     		0x1a8
+
+#define	SCB_NEXT        		0x1ac
+#define	SCB_NEXT_SCB_BUSADDR		0x1ac
 
-#define	SCB_TAG         		0x1ae
-#define	SCB_FIFO_USE_COUNT		0x1ae
+#define	SCB_NEXT2       		0x1ae
 
 #define	SCB_SPARE       		0x1b0
 #define	SCB_PKT_LUN     		0x1b0
@@ -3720,6 +3722,7 @@ ahd_reg_print_t ahd_scb_disconnected_lis
 #define	AHD_PRECOMP_CUTBACK_29	0x06
 #define	AHD_NUM_PER_DEV_ANNEXCOLS	0x04
 #define	B_CURRFIFO_0	0x02
+#define	LUNLEN_SINGLE_LEVEL_LUN	0x0f
 #define	NVRAM_SCB_OFFSET	0x2c
 #define	AHD_TIMER_MAX_US	0x18ffe7
 #define	AHD_TIMER_MAX_TICKS	0xffff
diff -puN drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
--- 25/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped	Wed Dec 24 12:15:38 2003
@@ -2,8 +2,8 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#93 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#68 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#107 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
  */
 
 #include "aic79xx_osm.h"
@@ -489,10 +489,15 @@ ahd_shortthresh_print(u_int regvalue, u_
 	    0x2f, regvalue, cur_col, wrap));
 }
 
+static ahd_reg_parse_entry_t LUNLEN_parse_table[] = {
+	{ "ILUNLEN",		0x0f, 0x0f },
+	{ "TLUNLEN",		0xf0, 0xf0 }
+};
+
 int
 ahd_lunlen_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "LUNLEN",
+	return (ahd_print_register(LUNLEN_parse_table, 2, "LUNLEN",
 	    0x30, regvalue, cur_col, wrap));
 }
 
@@ -3486,58 +3491,12 @@ ahd_scb_sense_busaddr_print(u_int regval
 }
 
 int
-ahd_scb_dataptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_scb_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "SCB_DATAPTR",
+	return (ahd_print_register(NULL, 0, "SCB_TAG",
 	    0x190, regvalue, cur_col, wrap));
 }
 
-static ahd_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
-	{ "SG_HIGH_ADDR_BITS",	0x7f, 0x7f },
-	{ "SG_LAST_SEG",	0x80, 0x80 }
-};
-
-int
-ahd_scb_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(SCB_DATACNT_parse_table, 2, "SCB_DATACNT",
-	    0x198, regvalue, cur_col, wrap));
-}
-
-static ahd_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
-	{ "SG_LIST_NULL",	0x01, 0x01 },
-	{ "SG_FULL_RESID",	0x02, 0x02 },
-	{ "SG_STATUS_VALID",	0x04, 0x04 }
-};
-
-int
-ahd_scb_sgptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(SCB_SGPTR_parse_table, 3, "SCB_SGPTR",
-	    0x19c, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scb_busaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(NULL, 0, "SCB_BUSADDR",
-	    0x1a0, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scb_next_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(NULL, 0, "SCB_NEXT",
-	    0x1a4, regvalue, cur_col, wrap));
-}
-
-int
-ahd_scb_next2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahd_print_register(NULL, 0, "SCB_NEXT2",
-	    0x1a6, regvalue, cur_col, wrap));
-}
-
 static ahd_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
 	{ "SCB_TAG_TYPE",	0x03, 0x03 },
 	{ "DISCONNECTED",	0x04, 0x04 },
@@ -3552,7 +3511,7 @@ int
 ahd_scb_control_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(SCB_CONTROL_parse_table, 7, "SCB_CONTROL",
-	    0x1a8, regvalue, cur_col, wrap));
+	    0x192, regvalue, cur_col, wrap));
 }
 
 static ahd_reg_parse_entry_t SCB_SCSIID_parse_table[] = {
@@ -3564,7 +3523,7 @@ int
 ahd_scb_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(SCB_SCSIID_parse_table, 2, "SCB_SCSIID",
-	    0x1a9, regvalue, cur_col, wrap));
+	    0x193, regvalue, cur_col, wrap));
 }
 
 static ahd_reg_parse_entry_t SCB_LUN_parse_table[] = {
@@ -3575,14 +3534,18 @@ int
 ahd_scb_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(SCB_LUN_parse_table, 1, "SCB_LUN",
-	    0x1aa, regvalue, cur_col, wrap));
+	    0x194, regvalue, cur_col, wrap));
 }
 
+static ahd_reg_parse_entry_t SCB_TASK_ATTRIBUTE_parse_table[] = {
+	{ "SCB_XFERLEN_ODD",	0x01, 0x01 }
+};
+
 int
 ahd_scb_task_attribute_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "SCB_TASK_ATTRIBUTE",
-	    0x1ab, regvalue, cur_col, wrap));
+	return (ahd_print_register(SCB_TASK_ATTRIBUTE_parse_table, 1, "SCB_TASK_ATTRIBUTE",
+	    0x195, regvalue, cur_col, wrap));
 }
 
 static ahd_reg_parse_entry_t SCB_CDB_LEN_parse_table[] = {
@@ -3593,20 +3556,66 @@ int
 ahd_scb_cdb_len_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(SCB_CDB_LEN_parse_table, 1, "SCB_CDB_LEN",
-	    0x1ac, regvalue, cur_col, wrap));
+	    0x196, regvalue, cur_col, wrap));
 }
 
 int
 ahd_scb_task_management_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
 	return (ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT",
-	    0x1ad, regvalue, cur_col, wrap));
+	    0x197, regvalue, cur_col, wrap));
 }
 
 int
-ahd_scb_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_scb_dataptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahd_print_register(NULL, 0, "SCB_TAG",
+	return (ahd_print_register(NULL, 0, "SCB_DATAPTR",
+	    0x198, regvalue, cur_col, wrap));
+}
+
+static ahd_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
+	{ "SG_HIGH_ADDR_BITS",	0x7f, 0x7f },
+	{ "SG_LAST_SEG",	0x80, 0x80 }
+};
+
+int
+ahd_scb_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(SCB_DATACNT_parse_table, 2, "SCB_DATACNT",
+	    0x1a0, regvalue, cur_col, wrap));
+}
+
+static ahd_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
+	{ "SG_LIST_NULL",	0x01, 0x01 },
+	{ "SG_FULL_RESID",	0x02, 0x02 },
+	{ "SG_STATUS_VALID",	0x04, 0x04 }
+};
+
+int
+ahd_scb_sgptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(SCB_SGPTR_parse_table, 3, "SCB_SGPTR",
+	    0x1a4, regvalue, cur_col, wrap));
+}
+
+int
+ahd_scb_busaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "SCB_BUSADDR",
+	    0x1a8, regvalue, cur_col, wrap));
+}
+
+int
+ahd_scb_next_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "SCB_NEXT",
+	    0x1ac, regvalue, cur_col, wrap));
+}
+
+int
+ahd_scb_next2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+	return (ahd_print_register(NULL, 0, "SCB_NEXT2",
 	    0x1ae, regvalue, cur_col, wrap));
 }
 
diff -puN drivers/scsi/aic7xxx/aic79xx.seq~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic79xx.seq
--- 25/drivers/scsi/aic7xxx/aic79xx.seq~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic79xx.seq	Wed Dec 24 12:15:38 2003
@@ -40,7 +40,7 @@
  * $FreeBSD$
  */
 
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#107 $"
 PATCH_ARG_LIST = "struct ahd_softc *ahd"
 PREFIX = "ahd_"
 
@@ -90,6 +90,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;
@@ -101,9 +108,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;
 	/*
@@ -152,25 +159,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;
@@ -180,26 +190,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;
@@ -208,6 +210,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:
 	/*
@@ -276,7 +279,7 @@ fetch_new_scb_done:
 	 * knows the correct location to store the SCB.
 	 * Set it to zero before processing the SCB.
 	 */
-	mov	SCB_FIFO_USE_COUNT, ALLZEROS;
+	clr	SCB_FIFO_USE_COUNT;
 	/* Update the next SCB address to download. */
 	bmov	NEXT_QUEUED_SCB_ADDR, SCB_NEXT_SCB_BUSADDR, 4;
 	mvi	SCB_NEXT[1], SCB_LIST_NULL;
@@ -490,14 +493,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;
 	}
@@ -527,6 +546,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) {
 		/*
@@ -582,9 +616,6 @@ found_last_sent_scb:
 		bmov	CURRSCB, SCBPTR, 2;
 curscb_ww_done:
 	} else {
-		/*
-		 * Untested - Verify with Rev B.
-		 */
 		bmov	SCBPTR, CURRSCB, 2;
 	}
 
@@ -651,12 +682,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;
 	}
@@ -729,13 +761,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;
 
@@ -1061,8 +1118,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;
@@ -1073,9 +1132,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
@@ -1122,8 +1183,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)
 
@@ -1178,11 +1249,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) {
 		/*
@@ -1634,7 +1700,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).
 		 */
@@ -1643,7 +1709,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;
@@ -1810,7 +1876,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.
@@ -1819,7 +1884,6 @@ END_CRITICAL;
  * Check for overrun and see if we can complete this command.
  */
 pkt_last_seg_done:
-BEGIN_CRITICAL;
 	/*
 	 * Mark transfer as completed.
 	 */
@@ -1959,12 +2023,14 @@ SET_DST_MODE	M_SCSI;
 	test	SSTAT0, SELDO jnz return;
 	mvi	SCBPTR[1], SCB_LIST_NULL;
 unexpected_nonpkt_phase:
-	test	MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) jnz . + 3;
+	test	MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1))
+		jnz unexpected_nonpkt_mode_cleared;
 SET_SRC_MODE	M_DFF0;
 SET_DST_MODE	M_DFF0;
 	or	LONGJMP_ADDR[1], INVALID_ADDR;
 	dec	SCB_FIFO_USE_COUNT;
 	mvi	DFFSXFRCTL, CLRCHN;
+unexpected_nonpkt_mode_cleared:
 	mvi	CLRSINT2, CLRNONPACKREQ;
 	test	SCSIPHASE, ~(MSG_IN_PHASE|MSG_OUT_PHASE) jnz illegal_phase;
 	SET_SEQINTCODE(ENTERING_NONPACK)
diff -puN drivers/scsi/aic7xxx/aic79xx_seq.h_shipped~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
--- 25/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped	Wed Dec 24 12:15:38 2003
@@ -2,25 +2,25 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#69 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#107 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
  */
 static uint8_t seqprog[] = {
 	0xff, 0x02, 0x06, 0x78,
-	0x00, 0xea, 0x50, 0x59,
+	0x00, 0xea, 0x46, 0x59,
 	0x01, 0xea, 0x04, 0x30,
 	0xff, 0x04, 0x0c, 0x78,
-	0x19, 0xea, 0x50, 0x59,
+	0x19, 0xea, 0x46, 0x59,
 	0x19, 0xea, 0x04, 0x00,
-	0x33, 0xea, 0x44, 0x59,
+	0x33, 0xea, 0x3a, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x60, 0x3a, 0x1a, 0x68,
 	0x04, 0x47, 0x1b, 0x68,
 	0xff, 0x21, 0x1b, 0x70,
-	0x40, 0x4b, 0x92, 0x69,
-	0x00, 0xe2, 0x54, 0x59,
-	0x40, 0x4b, 0x92, 0x69,
-	0x20, 0x4b, 0x82, 0x69,
+	0x40, 0x4b, 0x8c, 0x69,
+	0x00, 0xe2, 0x4a, 0x59,
+	0x40, 0x4b, 0x8c, 0x69,
+	0x20, 0x4b, 0x78, 0x69,
 	0xfc, 0x42, 0x24, 0x78,
 	0x10, 0x40, 0x24, 0x78,
 	0x00, 0xe2, 0xc4, 0x5d,
@@ -35,70 +35,65 @@ static uint8_t seqprog[] = {
 	0x00, 0xe2, 0x56, 0x58,
 	0x00, 0xe2, 0x66, 0x58,
 	0x00, 0xe2, 0x06, 0x40,
-	0x33, 0xea, 0x44, 0x59,
+	0x33, 0xea, 0x3a, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x01, 0x52, 0x64, 0x78,
 	0x02, 0x58, 0x50, 0x31,
 	0xff, 0xea, 0x10, 0x0b,
-	0xff, 0xad, 0x4f, 0x78,
+	0xff, 0x97, 0x4f, 0x78,
 	0x50, 0x4b, 0x4a, 0x68,
 	0xbf, 0x3a, 0x74, 0x08,
-	0x14, 0xea, 0x50, 0x59,
+	0x14, 0xea, 0x46, 0x59,
 	0x14, 0xea, 0x04, 0x00,
-	0x08, 0xa8, 0x51, 0x03,
-	0xff, 0xae, 0x3f, 0x68,
-	0x00, 0xe2, 0x56, 0x5b,
+	0x08, 0x92, 0x25, 0x03,
+	0xff, 0x90, 0x3f, 0x68,
+	0x00, 0xe2, 0x58, 0x5b,
 	0x00, 0xe2, 0x3e, 0x40,
-	0x00, 0xea, 0x44, 0x59,
+	0x00, 0xea, 0x3a, 0x59,
 	0x01, 0xea, 0x00, 0x30,
 	0x80, 0xf9, 0x5e, 0x68,
-	0x00, 0xe2, 0x42, 0x59,
-	0x11, 0xea, 0x44, 0x59,
+	0x00, 0xe2, 0x38, 0x59,
+	0x11, 0xea, 0x3a, 0x59,
 	0x11, 0xea, 0x00, 0x00,
-	0x80, 0xf9, 0x42, 0x79,
+	0x80, 0xf9, 0x38, 0x79,
 	0xff, 0xea, 0xd4, 0x0d,
-	0x22, 0xea, 0x44, 0x59,
+	0x22, 0xea, 0x3a, 0x59,
 	0x22, 0xea, 0x00, 0x00,
 	0x10, 0x16, 0x70, 0x78,
-	0x01, 0x0b, 0xa2, 0x32,
 	0x10, 0x16, 0x2c, 0x00,
-	0x18, 0xad, 0x00, 0x79,
-	0x04, 0xad, 0xca, 0x68,
+	0x01, 0x0b, 0xa2, 0x32,
+	0x18, 0xad, 0xf6, 0x78,
+	0x04, 0xad, 0xc0, 0x68,
 	0x80, 0xad, 0x64, 0x78,
-	0x10, 0xad, 0x98, 0x78,
-	0xff, 0x88, 0x83, 0x68,
-	0xe7, 0xad, 0x5a, 0x09,
-	0x02, 0x8c, 0x59, 0x32,
-	0x02, 0x28, 0x19, 0x33,
-	0x02, 0xa8, 0x50, 0x36,
-	0x33, 0xea, 0x44, 0x59,
+	0x10, 0xad, 0x8e, 0x78,
+	0xff, 0x88, 0x87, 0x78,
+	0x33, 0xea, 0x3a, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x40, 0x3a, 0x64, 0x68,
 	0x50, 0x4b, 0x64, 0x68,
-	0x22, 0xea, 0x44, 0x59,
+	0x22, 0xea, 0x3a, 0x59,
 	0x22, 0xea, 0x00, 0x00,
 	0xe7, 0xad, 0x5a, 0x09,
 	0x02, 0x8c, 0x59, 0x32,
-	0x1a, 0xea, 0x50, 0x59,
-	0x1a, 0xea, 0x04, 0x00,
-	0xff, 0xea, 0xd4, 0x0d,
+	0x02, 0x28, 0x19, 0x33,
+	0x02, 0xa8, 0x50, 0x36,
 	0xe7, 0xad, 0x5a, 0x09,
-	0x00, 0xe2, 0xa6, 0x58,
+	0x00, 0xe2, 0x9c, 0x58,
 	0xff, 0xea, 0x56, 0x02,
 	0x04, 0x7c, 0x78, 0x32,
 	0x20, 0x16, 0x64, 0x78,
 	0x04, 0x38, 0x79, 0x32,
 	0x80, 0x37, 0x6f, 0x16,
-	0xff, 0x2d, 0xb5, 0x60,
-	0xff, 0x29, 0xb5, 0x60,
-	0x40, 0x51, 0xc5, 0x78,
-	0xff, 0x4f, 0xb5, 0x68,
+	0xff, 0x2d, 0xab, 0x60,
+	0xff, 0x29, 0xab, 0x60,
+	0x40, 0x51, 0xbb, 0x78,
+	0xff, 0x4f, 0xab, 0x68,
 	0xff, 0x4d, 0xc1, 0x19,
 	0x00, 0x4e, 0xd5, 0x19,
-	0x00, 0xe2, 0xc4, 0x50,
+	0x00, 0xe2, 0xba, 0x50,
 	0x01, 0x4c, 0xc1, 0x31,
 	0x00, 0x50, 0xd5, 0x19,
-	0x00, 0xe2, 0xc4, 0x48,
+	0x00, 0xe2, 0xba, 0x48,
 	0x80, 0x18, 0x64, 0x78,
 	0x02, 0x4a, 0x1d, 0x30,
 	0x10, 0xea, 0x18, 0x00,
@@ -113,30 +108,30 @@ static uint8_t seqprog[] = {
 	0xff, 0xea, 0xc0, 0x09,
 	0x01, 0x4e, 0x9d, 0x1a,
 	0x00, 0x4f, 0x9f, 0x22,
-	0x01, 0xaa, 0x6d, 0x33,
-	0x01, 0xea, 0x5c, 0x33,
-	0x04, 0xa4, 0x49, 0x32,
-	0xff, 0xea, 0x4a, 0x03,
-	0xff, 0xea, 0x4e, 0x03,
+	0x01, 0x94, 0x6d, 0x33,
+	0xff, 0xea, 0x20, 0x0b,
+	0x04, 0xac, 0x49, 0x32,
+	0xff, 0xea, 0x5a, 0x03,
+	0xff, 0xea, 0x5e, 0x03,
 	0x01, 0x10, 0xd4, 0x31,
-	0x10, 0xa8, 0xf5, 0x68,
-	0x3d, 0xa9, 0xc5, 0x29,
+	0x10, 0x92, 0xeb, 0x68,
+	0x3d, 0x93, 0xc5, 0x29,
 	0xfe, 0xe2, 0xc4, 0x09,
 	0x01, 0xea, 0xc6, 0x01,
 	0x02, 0xe2, 0xc8, 0x31,
 	0x02, 0xec, 0x50, 0x31,
 	0x02, 0xa0, 0xda, 0x31,
-	0xff, 0xa9, 0xf4, 0x70,
-	0x02, 0xa0, 0x48, 0x37,
-	0xff, 0x21, 0xfd, 0x70,
+	0xff, 0xa9, 0xea, 0x70,
+	0x02, 0xa0, 0x58, 0x37,
+	0xff, 0x21, 0xf3, 0x70,
 	0x02, 0x22, 0x51, 0x31,
-	0x02, 0xa0, 0x4c, 0x33,
+	0x02, 0xa0, 0x5c, 0x33,
 	0x02, 0xa0, 0x44, 0x36,
 	0x02, 0xa0, 0x40, 0x32,
 	0x02, 0xa0, 0x44, 0x36,
-	0x04, 0x47, 0x05, 0x69,
-	0x40, 0x16, 0x30, 0x69,
-	0xff, 0x2d, 0x35, 0x61,
+	0x04, 0x47, 0xfb, 0x68,
+	0x40, 0x16, 0x26, 0x69,
+	0xff, 0x2d, 0x2b, 0x61,
 	0xff, 0x29, 0x65, 0x70,
 	0x01, 0x37, 0xc1, 0x31,
 	0x02, 0x28, 0x55, 0x32,
@@ -149,20 +144,20 @@ static uint8_t seqprog[] = {
 	0x01, 0x50, 0xa1, 0x1a,
 	0xff, 0x4e, 0x9d, 0x1a,
 	0xff, 0x4f, 0x9f, 0x22,
-	0xff, 0x8d, 0x29, 0x71,
-	0x80, 0xac, 0x28, 0x71,
-	0x20, 0x16, 0x28, 0x69,
+	0xff, 0x8d, 0x1f, 0x71,
+	0x80, 0xac, 0x1e, 0x71,
+	0x20, 0x16, 0x1e, 0x69,
 	0x02, 0x8c, 0x51, 0x31,
-	0x00, 0xe2, 0x12, 0x41,
+	0x00, 0xe2, 0x08, 0x41,
 	0x01, 0xac, 0x08, 0x31,
 	0x09, 0xea, 0x5a, 0x01,
 	0x02, 0x8c, 0x51, 0x32,
 	0xff, 0xea, 0x1a, 0x07,
 	0x04, 0x24, 0xf9, 0x30,
-	0x1d, 0xea, 0x3a, 0x41,
+	0x1d, 0xea, 0x30, 0x41,
 	0x02, 0x2c, 0x51, 0x31,
-	0x04, 0xa0, 0xf9, 0x30,
-	0x19, 0xea, 0x3a, 0x41,
+	0x04, 0xa8, 0xf9, 0x30,
+	0x19, 0xea, 0x30, 0x41,
 	0x06, 0xea, 0x08, 0x81,
 	0x01, 0xe2, 0x5a, 0x35,
 	0x02, 0xf2, 0xf0, 0x35,
@@ -179,26 +174,28 @@ static uint8_t seqprog[] = {
 	0x02, 0x20, 0xbd, 0x30,
 	0x02, 0x20, 0xb9, 0x30,
 	0x02, 0x20, 0x51, 0x31,
-	0x4c, 0xa9, 0xd7, 0x28,
-	0x10, 0xa8, 0x63, 0x79,
+	0x4c, 0x93, 0xd7, 0x28,
+	0x10, 0x92, 0x59, 0x79,
 	0x01, 0x6b, 0xc0, 0x30,
 	0x02, 0x64, 0xc8, 0x00,
 	0x40, 0x3a, 0x74, 0x04,
 	0x00, 0xe2, 0x56, 0x58,
-	0x33, 0xea, 0x44, 0x59,
+	0x33, 0xea, 0x3a, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x30, 0x3f, 0xc0, 0x09,
-	0x30, 0xe0, 0x64, 0x61,
-	0x20, 0x3f, 0x7a, 0x69,
-	0x10, 0x3f, 0x64, 0x79,
+	0x30, 0xe0, 0x5a, 0x61,
+	0x20, 0x3f, 0x70, 0x69,
+	0x10, 0x3f, 0x5a, 0x79,
 	0x02, 0xea, 0x7e, 0x00,
-	0x00, 0xea, 0x44, 0x59,
+	0x00, 0xea, 0x3a, 0x59,
 	0x01, 0xea, 0x00, 0x30,
 	0x02, 0x48, 0x51, 0x35,
 	0x01, 0xea, 0x7e, 0x00,
-	0x11, 0xea, 0x44, 0x59,
+	0x11, 0xea, 0x3a, 0x59,
 	0x11, 0xea, 0x00, 0x00,
 	0x02, 0x48, 0x51, 0x35,
+	0xc0, 0x4a, 0x94, 0x00,
+	0x04, 0x41, 0x7e, 0x79,
 	0x08, 0xea, 0x98, 0x00,
 	0x08, 0x57, 0xae, 0x00,
 	0x08, 0x3c, 0x78, 0x00,
@@ -206,11 +203,12 @@ static uint8_t seqprog[] = {
 	0x0f, 0x67, 0xc0, 0x09,
 	0x00, 0x34, 0x69, 0x02,
 	0x20, 0xea, 0x96, 0x00,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x40, 0x3a, 0xae, 0x69,
+	0x00, 0xe2, 0xf6, 0x41,
+	0xc0, 0x4a, 0x94, 0x00,
+	0x40, 0x3a, 0xaa, 0x69,
 	0x02, 0x55, 0x06, 0x68,
-	0x02, 0x56, 0xae, 0x69,
-	0xff, 0x5b, 0xae, 0x61,
+	0x02, 0x56, 0xaa, 0x69,
+	0xff, 0x5b, 0xaa, 0x61,
 	0x02, 0x20, 0x51, 0x31,
 	0x80, 0xea, 0xb2, 0x01,
 	0x44, 0xea, 0x00, 0x00,
@@ -218,146 +216,149 @@ static uint8_t seqprog[] = {
 	0x33, 0xea, 0x00, 0x00,
 	0xff, 0xea, 0xb2, 0x09,
 	0xff, 0xe0, 0xc0, 0x19,
-	0xff, 0xe0, 0xb0, 0x79,
-	0x02, 0xa4, 0x51, 0x31,
-	0x00, 0xe2, 0xa6, 0x41,
+	0xff, 0xe0, 0xac, 0x79,
+	0x02, 0xac, 0x51, 0x31,
+	0x00, 0xe2, 0xa2, 0x41,
 	0x02, 0x5e, 0x50, 0x31,
 	0x02, 0xa8, 0xb8, 0x30,
 	0x02, 0x5c, 0x50, 0x31,
-	0xff, 0xa5, 0xc1, 0x71,
-	0x02, 0xa4, 0x41, 0x31,
+	0xff, 0xad, 0xbd, 0x71,
+	0x02, 0xac, 0x41, 0x31,
 	0x02, 0x22, 0x51, 0x31,
-	0x02, 0xa0, 0x4c, 0x33,
+	0x02, 0xa0, 0x5c, 0x33,
 	0x02, 0xa0, 0x44, 0x32,
-	0x00, 0xe2, 0xca, 0x41,
-	0x10, 0xa8, 0xcb, 0x69,
-	0x3d, 0xa9, 0xc9, 0x29,
+	0x00, 0xe2, 0xc6, 0x41,
+	0x10, 0x92, 0xc7, 0x69,
+	0x3d, 0x93, 0xc9, 0x29,
 	0x01, 0xe4, 0xc8, 0x01,
 	0x01, 0xea, 0xca, 0x01,
 	0xff, 0xea, 0xda, 0x01,
 	0x02, 0x20, 0x51, 0x31,
-	0x02, 0xa6, 0x41, 0x32,
-	0xff, 0x21, 0xd3, 0x61,
+	0x02, 0xae, 0x41, 0x32,
+	0xff, 0x21, 0xcf, 0x61,
 	0xff, 0xea, 0x46, 0x02,
 	0x02, 0x5c, 0x50, 0x31,
 	0x40, 0xea, 0x96, 0x00,
 	0x02, 0x56, 0xcc, 0x6d,
 	0x01, 0x55, 0xcc, 0x6d,
-	0x10, 0xa8, 0xdf, 0x79,
-	0x10, 0x40, 0xe8, 0x69,
-	0x01, 0x56, 0xe8, 0x79,
-	0xff, 0xad, 0x07, 0x78,
-	0x13, 0xea, 0x50, 0x59,
+	0x10, 0x92, 0xdb, 0x79,
+	0x10, 0x40, 0xe4, 0x69,
+	0x01, 0x56, 0xe4, 0x79,
+	0xff, 0x97, 0x07, 0x78,
+	0x13, 0xea, 0x46, 0x59,
 	0x13, 0xea, 0x04, 0x00,
 	0x00, 0xe2, 0x06, 0x40,
 	0xbf, 0x3a, 0x74, 0x08,
+	0x04, 0x41, 0xea, 0x79,
 	0x08, 0xea, 0x98, 0x00,
 	0x08, 0x57, 0xae, 0x00,
-	0x01, 0xa9, 0x69, 0x32,
-	0x01, 0xaa, 0x6b, 0x32,
+	0x01, 0x93, 0x69, 0x32,
+	0x01, 0x94, 0x6b, 0x32,
 	0x40, 0xea, 0x66, 0x02,
 	0x08, 0x3c, 0x78, 0x00,
 	0x80, 0xea, 0x62, 0x02,
 	0x00, 0xe2, 0xb8, 0x5b,
 	0x01, 0x36, 0xc1, 0x31,
 	0x9f, 0xe0, 0x4c, 0x7c,
-	0x80, 0xe0, 0x0c, 0x72,
-	0xa0, 0xe0, 0x44, 0x72,
-	0xc0, 0xe0, 0x3a, 0x72,
-	0xe0, 0xe0, 0x74, 0x72,
-	0x01, 0xea, 0x50, 0x59,
+	0x80, 0xe0, 0x0a, 0x72,
+	0xa0, 0xe0, 0x46, 0x72,
+	0xc0, 0xe0, 0x3c, 0x72,
+	0xe0, 0xe0, 0x76, 0x72,
+	0x01, 0xea, 0x46, 0x59,
 	0x01, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x80, 0x33, 0x13, 0x7a,
-	0x03, 0xea, 0x50, 0x59,
+	0x00, 0xe2, 0xf6, 0x41,
+	0x80, 0x33, 0x11, 0x7a,
+	0x03, 0xea, 0x46, 0x59,
 	0x03, 0xea, 0x04, 0x00,
-	0xee, 0x00, 0x1a, 0x6a,
+	0xee, 0x00, 0x18, 0x6a,
 	0x05, 0xea, 0xb4, 0x00,
-	0x33, 0xea, 0x44, 0x59,
+	0x33, 0xea, 0x3a, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x02, 0xa8, 0x90, 0x32,
-	0x00, 0xe2, 0x6a, 0x59,
-	0xef, 0xac, 0xd5, 0x19,
-	0x00, 0xe2, 0x2a, 0x52,
+	0x00, 0xe2, 0x60, 0x59,
+	0xef, 0x96, 0xd5, 0x19,
+	0x00, 0xe2, 0x28, 0x52,
 	0x09, 0x80, 0xe1, 0x30,
 	0x02, 0xea, 0x36, 0x00,
 	0xa8, 0xea, 0x32, 0x00,
-	0x00, 0xe2, 0x30, 0x42,
-	0x01, 0xac, 0xd1, 0x30,
+	0x00, 0xe2, 0x2e, 0x42,
+	0x01, 0x96, 0xd1, 0x30,
 	0x10, 0x80, 0x89, 0x31,
 	0x20, 0xea, 0x32, 0x00,
 	0xbf, 0x33, 0x67, 0x0a,
-	0x20, 0x19, 0x32, 0x6a,
-	0x02, 0x4d, 0xf8, 0x69,
+	0x10, 0x4c, 0x38, 0x6a,
+	0x20, 0x19, 0x30, 0x6a,
+	0x20, 0x19, 0x34, 0x6a,
+	0x02, 0x4d, 0xf6, 0x69,
 	0x40, 0x33, 0x67, 0x02,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x80, 0x33, 0xb5, 0x6a,
+	0x00, 0xe2, 0xf6, 0x41,
+	0x80, 0x33, 0xb7, 0x6a,
 	0x01, 0x44, 0x10, 0x33,
-	0x08, 0xa8, 0x51, 0x03,
-	0x00, 0xe2, 0xf8, 0x41,
+	0x08, 0x92, 0x25, 0x03,
+	0x00, 0xe2, 0xf6, 0x41,
 	0x10, 0xea, 0x80, 0x00,
 	0x01, 0x31, 0xc5, 0x31,
-	0x80, 0xe2, 0x60, 0x62,
-	0x10, 0xa8, 0x85, 0x6a,
-	0xc0, 0xaa, 0xc5, 0x01,
-	0x40, 0xa8, 0x51, 0x6a,
+	0x80, 0xe2, 0x62, 0x62,
+	0x10, 0x92, 0x87, 0x6a,
+	0xc0, 0x94, 0xc5, 0x01,
+	0x40, 0x92, 0x53, 0x6a,
 	0xbf, 0xe2, 0xc4, 0x09,
-	0x20, 0xa8, 0x65, 0x7a,
+	0x20, 0x92, 0x67, 0x7a,
 	0x01, 0xe2, 0x88, 0x30,
 	0x00, 0xe2, 0xb8, 0x5b,
-	0xa0, 0x36, 0x6d, 0x62,
-	0x23, 0xa8, 0x89, 0x08,
+	0xa0, 0x36, 0x6f, 0x62,
+	0x23, 0x92, 0x89, 0x08,
 	0x00, 0xe2, 0xb8, 0x5b,
-	0xa0, 0x36, 0x6d, 0x62,
-	0x00, 0xa8, 0x64, 0x42,
-	0xff, 0xe2, 0x64, 0x62,
-	0x00, 0xe2, 0x84, 0x42,
+	0xa0, 0x36, 0x6f, 0x62,
+	0x00, 0xa8, 0x66, 0x42,
+	0xff, 0xe2, 0x66, 0x62,
+	0x00, 0xe2, 0x86, 0x42,
 	0x40, 0xea, 0x98, 0x00,
 	0x01, 0xe2, 0x88, 0x30,
 	0x00, 0xe2, 0xb8, 0x5b,
-	0xa0, 0x36, 0x43, 0x72,
+	0xa0, 0x36, 0x45, 0x72,
 	0x40, 0xea, 0x98, 0x00,
 	0x01, 0x31, 0x89, 0x32,
 	0x08, 0xea, 0x62, 0x02,
-	0x00, 0xe2, 0xf8, 0x41,
+	0x00, 0xe2, 0xf6, 0x41,
 	0xe0, 0xea, 0xd4, 0x5b,
-	0x80, 0xe0, 0xc0, 0x6a,
-	0x04, 0xe0, 0x66, 0x73,
-	0x02, 0xe0, 0x96, 0x73,
-	0x00, 0xea, 0x1e, 0x73,
-	0x03, 0xe0, 0xa6, 0x73,
-	0x23, 0xe0, 0x96, 0x72,
-	0x08, 0xe0, 0xbc, 0x72,
+	0x80, 0xe0, 0xc2, 0x6a,
+	0x04, 0xe0, 0x68, 0x73,
+	0x02, 0xe0, 0x9a, 0x73,
+	0x00, 0xea, 0x20, 0x73,
+	0x03, 0xe0, 0xaa, 0x73,
+	0x23, 0xe0, 0x98, 0x72,
+	0x08, 0xe0, 0xbe, 0x72,
 	0x00, 0xe2, 0xb8, 0x5b,
-	0x07, 0xea, 0x50, 0x59,
+	0x07, 0xea, 0x46, 0x59,
 	0x07, 0xea, 0x04, 0x00,
-	0x08, 0x42, 0xf9, 0x71,
-	0x04, 0x42, 0x93, 0x62,
+	0x08, 0x42, 0xf7, 0x71,
+	0x04, 0x42, 0x95, 0x62,
 	0x01, 0x43, 0x89, 0x30,
-	0x00, 0xe2, 0x84, 0x42,
+	0x00, 0xe2, 0x86, 0x42,
 	0x01, 0x44, 0xd4, 0x31,
-	0x00, 0xe2, 0x84, 0x42,
+	0x00, 0xe2, 0x86, 0x42,
 	0x01, 0x00, 0x60, 0x32,
-	0x33, 0xea, 0x44, 0x59,
+	0x33, 0xea, 0x3a, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x4c, 0x34, 0xc1, 0x28,
 	0x01, 0x64, 0xc0, 0x31,
-	0x00, 0x30, 0x45, 0x59,
+	0x00, 0x30, 0x3b, 0x59,
 	0x01, 0x30, 0x01, 0x30,
-	0x01, 0xe0, 0xba, 0x7a,
+	0x01, 0xe0, 0xbc, 0x7a,
 	0xa0, 0xea, 0xca, 0x5b,
-	0x01, 0xa0, 0xba, 0x62,
-	0x01, 0x84, 0xaf, 0x7a,
-	0x01, 0xab, 0xbd, 0x6a,
-	0x05, 0xea, 0x50, 0x59,
+	0x01, 0xa0, 0xbc, 0x62,
+	0x01, 0x84, 0xb1, 0x7a,
+	0x01, 0x95, 0xbf, 0x6a,
+	0x05, 0xea, 0x46, 0x59,
 	0x05, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xbc, 0x42,
-	0x03, 0xea, 0x50, 0x59,
+	0x00, 0xe2, 0xbe, 0x42,
+	0x03, 0xea, 0x46, 0x59,
 	0x03, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xbc, 0x42,
+	0x00, 0xe2, 0xbe, 0x42,
 	0x07, 0xea, 0xdc, 0x5b,
 	0x01, 0x44, 0xd4, 0x31,
-	0x00, 0xe2, 0xf8, 0x41,
+	0x00, 0xe2, 0xf6, 0x41,
 	0x3f, 0xe0, 0x6a, 0x0a,
 	0xc0, 0x34, 0xc1, 0x09,
 	0x00, 0x35, 0x51, 0x01,
@@ -368,54 +369,54 @@ static uint8_t seqprog[] = {
 	0x01, 0xea, 0xc6, 0x01,
 	0x02, 0xe2, 0xc8, 0x31,
 	0x02, 0xec, 0x40, 0x31,
-	0xff, 0xa1, 0xdc, 0x72,
+	0xff, 0xa1, 0xde, 0x72,
 	0x02, 0xe8, 0xda, 0x31,
 	0x02, 0xa0, 0x50, 0x31,
-	0x00, 0xe2, 0xfe, 0x42,
+	0x00, 0xe2, 0x00, 0x43,
 	0x80, 0x33, 0x67, 0x02,
 	0x01, 0x44, 0xd4, 0x31,
 	0x00, 0xe2, 0xb8, 0x5b,
 	0x01, 0x33, 0x67, 0x02,
-	0xe0, 0x36, 0x19, 0x63,
+	0xe0, 0x36, 0x1b, 0x63,
 	0x02, 0x33, 0x67, 0x02,
-	0x20, 0x46, 0x12, 0x63,
+	0x20, 0x46, 0x14, 0x63,
 	0xff, 0xea, 0x52, 0x09,
 	0xa8, 0xea, 0xca, 0x5b,
-	0x04, 0xa8, 0xf9, 0x7a,
+	0x04, 0x92, 0xfb, 0x7a,
 	0x01, 0x34, 0xc1, 0x31,
-	0x00, 0xa9, 0xf9, 0x62,
+	0x00, 0x93, 0xfb, 0x62,
 	0x01, 0x35, 0xc1, 0x31,
-	0x00, 0xaa, 0x03, 0x73,
+	0x00, 0x94, 0x05, 0x73,
 	0x01, 0xa9, 0x52, 0x11,
-	0xff, 0xa9, 0xee, 0x6a,
-	0x00, 0xe2, 0x12, 0x43,
+	0xff, 0xa9, 0xf0, 0x6a,
+	0x00, 0xe2, 0x14, 0x43,
 	0x10, 0x33, 0x67, 0x02,
-	0x04, 0xa8, 0x13, 0x7b,
-	0xfb, 0xa8, 0x51, 0x0b,
+	0x04, 0x92, 0x15, 0x7b,
+	0xfb, 0x92, 0x25, 0x0b,
 	0xff, 0xea, 0x66, 0x0a,
-	0x01, 0x9c, 0x0d, 0x6b,
+	0x01, 0xa4, 0x0f, 0x6b,
 	0x02, 0xa8, 0x90, 0x32,
-	0x00, 0xe2, 0x6a, 0x59,
-	0x10, 0xa8, 0xbd, 0x7a,
+	0x00, 0xe2, 0x60, 0x59,
+	0x10, 0x92, 0xbf, 0x7a,
 	0xff, 0xea, 0xdc, 0x5b,
-	0x00, 0xe2, 0xbc, 0x42,
-	0x04, 0xea, 0x50, 0x59,
+	0x00, 0xe2, 0xbe, 0x42,
+	0x04, 0xea, 0x46, 0x59,
 	0x04, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xbc, 0x42,
-	0x04, 0xea, 0x50, 0x59,
+	0x00, 0xe2, 0xbe, 0x42,
+	0x04, 0xea, 0x46, 0x59,
 	0x04, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x08, 0xa8, 0xb5, 0x7a,
-	0xc0, 0x33, 0x29, 0x7b,
-	0x80, 0x33, 0xb5, 0x6a,
-	0xff, 0x88, 0x29, 0x6b,
-	0x40, 0x33, 0xb5, 0x6a,
-	0x10, 0xa8, 0x2f, 0x7b,
-	0x0a, 0xea, 0x50, 0x59,
+	0x00, 0xe2, 0xf6, 0x41,
+	0x08, 0x92, 0xb7, 0x7a,
+	0xc0, 0x33, 0x2b, 0x7b,
+	0x80, 0x33, 0xb7, 0x6a,
+	0xff, 0x88, 0x2b, 0x6b,
+	0x40, 0x33, 0xb7, 0x6a,
+	0x10, 0x92, 0x31, 0x7b,
+	0x0a, 0xea, 0x46, 0x59,
 	0x0a, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x4e, 0x5b,
-	0x00, 0xe2, 0x82, 0x43,
-	0x50, 0x4b, 0x36, 0x6b,
+	0x00, 0xe2, 0x50, 0x5b,
+	0x00, 0xe2, 0x84, 0x43,
+	0x50, 0x4b, 0x38, 0x6b,
 	0xbf, 0x3a, 0x74, 0x08,
 	0x01, 0xe0, 0xf4, 0x31,
 	0xff, 0xea, 0xc0, 0x09,
@@ -425,25 +426,25 @@ static uint8_t seqprog[] = {
 	0x01, 0xfa, 0xc0, 0x35,
 	0x02, 0xa8, 0x84, 0x32,
 	0x02, 0xea, 0xb4, 0x00,
-	0x33, 0xea, 0x44, 0x59,
+	0x33, 0xea, 0x3a, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x02, 0x42, 0x51, 0x31,
-	0xff, 0xae, 0x65, 0x68,
-	0xff, 0x88, 0x5b, 0x6b,
-	0x01, 0x9c, 0x57, 0x6b,
-	0x02, 0x9c, 0x5f, 0x6b,
-	0x01, 0x84, 0x5f, 0x7b,
+	0xff, 0x90, 0x65, 0x68,
+	0xff, 0x88, 0x5d, 0x6b,
+	0x01, 0xa4, 0x59, 0x6b,
+	0x02, 0xa4, 0x61, 0x6b,
+	0x01, 0x84, 0x61, 0x7b,
 	0x02, 0x28, 0x19, 0x33,
 	0x02, 0xa8, 0x50, 0x36,
-	0xff, 0x88, 0x5f, 0x73,
-	0x00, 0xe2, 0x32, 0x5b,
-	0x02, 0xa8, 0x5c, 0x33,
+	0xff, 0x88, 0x61, 0x73,
+	0x00, 0xe2, 0x34, 0x5b,
+	0x02, 0xa8, 0x20, 0x33,
 	0x02, 0x2c, 0x19, 0x33,
 	0x02, 0xa8, 0x58, 0x32,
-	0x04, 0x9c, 0x39, 0x07,
-	0xc0, 0x33, 0xb5, 0x6a,
-	0x04, 0xa8, 0x51, 0x03,
-	0x20, 0xa8, 0x83, 0x6b,
+	0x04, 0xa4, 0x49, 0x07,
+	0xc0, 0x33, 0xb7, 0x6a,
+	0x04, 0x92, 0x25, 0x03,
+	0x20, 0x92, 0x85, 0x6b,
 	0x02, 0xa8, 0x40, 0x31,
 	0xc0, 0x34, 0xc1, 0x09,
 	0x00, 0x35, 0x51, 0x01,
@@ -458,30 +459,29 @@ static uint8_t seqprog[] = {
 	0xf7, 0x57, 0xae, 0x08,
 	0x08, 0xea, 0x98, 0x00,
 	0x01, 0x44, 0xd4, 0x31,
-	0xee, 0x00, 0x8c, 0x6b,
+	0xee, 0x00, 0x8e, 0x6b,
 	0x02, 0xea, 0xb4, 0x00,
-	0x00, 0xe2, 0xb4, 0x5b,
-	0x09, 0x4c, 0x8e, 0x7b,
+	0xc0, 0xea, 0x66, 0x02,
+	0x09, 0x4c, 0x90, 0x7b,
+	0x01, 0xea, 0x6c, 0x02,
 	0x08, 0x4c, 0x06, 0x68,
-	0x0b, 0xea, 0x50, 0x59,
+	0x0b, 0xea, 0x46, 0x59,
 	0x0b, 0xea, 0x04, 0x00,
 	0x01, 0x44, 0xd4, 0x31,
-	0x20, 0x33, 0xf9, 0x79,
-	0x00, 0xe2, 0x9e, 0x5b,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x01, 0x84, 0xa3, 0x7b,
-	0x01, 0x9c, 0x39, 0x07,
-	0x08, 0x60, 0x20, 0x33,
-	0x08, 0x80, 0x31, 0x37,
+	0x20, 0x33, 0xf7, 0x79,
+	0x00, 0xe2, 0xa2, 0x5b,
+	0x00, 0xe2, 0xf6, 0x41,
+	0x01, 0x84, 0xa7, 0x7b,
+	0x01, 0xa4, 0x49, 0x07,
+	0x08, 0x60, 0x30, 0x33,
+	0x08, 0x80, 0x41, 0x37,
 	0xdf, 0x33, 0x67, 0x0a,
-	0xee, 0x00, 0xb0, 0x6b,
+	0xee, 0x00, 0xb4, 0x6b,
 	0x05, 0xea, 0xb4, 0x00,
-	0x33, 0xea, 0x44, 0x59,
+	0x33, 0xea, 0x3a, 0x59,
 	0x33, 0xea, 0x00, 0x00,
-	0x00, 0xe2, 0x6a, 0x59,
-	0x00, 0xe2, 0xbc, 0x42,
-	0x01, 0xea, 0x6c, 0x02,
-	0xc0, 0xea, 0x66, 0x06,
+	0x00, 0xe2, 0x60, 0x59,
+	0x00, 0xe2, 0xbe, 0x42,
 	0xff, 0x42, 0xc4, 0x6b,
 	0x01, 0x41, 0xb8, 0x6b,
 	0x02, 0x41, 0xb8, 0x7b,
@@ -495,7 +495,7 @@ static uint8_t seqprog[] = {
 	0xff, 0x42, 0xcc, 0x7b,
 	0x04, 0x4c, 0xcc, 0x6b,
 	0xe0, 0x41, 0x6c, 0x0a,
-	0xe0, 0x36, 0xf9, 0x61,
+	0xe0, 0x36, 0xf7, 0x61,
 	0xff, 0xea, 0xca, 0x09,
 	0x01, 0xe2, 0xc8, 0x31,
 	0x01, 0x46, 0xda, 0x35,
@@ -542,42 +542,42 @@ static uint8_t seqprog[] = {
 	0x01, 0xac, 0xd4, 0x99,
 	0x00, 0xe2, 0x64, 0x50,
 	0xfe, 0xa6, 0x4c, 0x0d,
-	0x0b, 0x90, 0xe1, 0x30,
-	0xfd, 0x9c, 0x49, 0x09,
-	0x80, 0x9b, 0x39, 0x7c,
+	0x0b, 0x98, 0xe1, 0x30,
+	0xfd, 0xa4, 0x49, 0x09,
+	0x80, 0xa3, 0x39, 0x7c,
 	0x02, 0xa4, 0x48, 0x01,
 	0x01, 0xa4, 0x36, 0x30,
 	0xa8, 0xea, 0x32, 0x00,
-	0xfd, 0x9c, 0x39, 0x0b,
-	0x05, 0x9b, 0x07, 0x33,
+	0xfd, 0xa4, 0x49, 0x0b,
+	0x05, 0xa3, 0x07, 0x33,
 	0x80, 0x83, 0x45, 0x6c,
 	0x02, 0xea, 0x4c, 0x05,
 	0xff, 0xea, 0x4c, 0x0d,
-	0x00, 0xe2, 0x3e, 0x59,
+	0x00, 0xe2, 0x34, 0x59,
 	0x02, 0xa6, 0xe6, 0x6b,
 	0x80, 0xf9, 0xf2, 0x05,
 	0xc0, 0x33, 0x53, 0x7c,
-	0x03, 0xea, 0x50, 0x59,
+	0x03, 0xea, 0x46, 0x59,
 	0x03, 0xea, 0x04, 0x00,
 	0x20, 0x33, 0x77, 0x7c,
 	0x01, 0x84, 0x5d, 0x6c,
-	0x06, 0xea, 0x50, 0x59,
+	0x06, 0xea, 0x46, 0x59,
 	0x06, 0xea, 0x04, 0x00,
 	0x00, 0xe2, 0x7a, 0x44,
 	0x01, 0x00, 0x60, 0x32,
 	0xee, 0x00, 0x66, 0x6c,
 	0x05, 0xea, 0xb4, 0x00,
-	0x33, 0xea, 0x44, 0x59,
+	0x33, 0xea, 0x3a, 0x59,
 	0x33, 0xea, 0x00, 0x00,
 	0x80, 0x3d, 0x7a, 0x00,
 	0xfc, 0x42, 0x68, 0x7c,
 	0x7f, 0x3d, 0x7a, 0x08,
-	0x00, 0x30, 0x45, 0x59,
+	0x00, 0x30, 0x3b, 0x59,
 	0x01, 0x30, 0x01, 0x30,
-	0x09, 0xea, 0x50, 0x59,
+	0x09, 0xea, 0x46, 0x59,
 	0x09, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x01, 0x9c, 0x5d, 0x6c,
+	0x00, 0xe2, 0xf6, 0x41,
+	0x01, 0xa4, 0x5d, 0x6c,
 	0x00, 0xe2, 0x30, 0x5c,
 	0x20, 0x33, 0x67, 0x02,
 	0x01, 0x00, 0x60, 0x32,
@@ -586,7 +586,7 @@ static uint8_t seqprog[] = {
 	0x00, 0xe2, 0x56, 0x58,
 	0x00, 0xe2, 0x66, 0x58,
 	0x00, 0xe2, 0x3a, 0x58,
-	0x00, 0x30, 0x45, 0x59,
+	0x00, 0x30, 0x3b, 0x59,
 	0x01, 0x30, 0x01, 0x30,
 	0x20, 0x19, 0x82, 0x6c,
 	0x00, 0xe2, 0xb2, 0x5c,
@@ -601,11 +601,11 @@ static uint8_t seqprog[] = {
 	0x03, 0x42, 0x4c, 0x6c,
 	0x00, 0xe2, 0xe0, 0x5b,
 	0x80, 0xf9, 0xf2, 0x01,
-	0x04, 0x33, 0xf9, 0x79,
-	0x00, 0xe2, 0xf8, 0x41,
+	0x04, 0x33, 0xf7, 0x79,
+	0x00, 0xe2, 0xf6, 0x41,
 	0x08, 0x5d, 0xba, 0x6c,
 	0x00, 0xe2, 0x56, 0x58,
-	0x00, 0x30, 0x45, 0x59,
+	0x00, 0x30, 0x3b, 0x59,
 	0x01, 0x30, 0x01, 0x30,
 	0x02, 0x1b, 0xaa, 0x7c,
 	0x08, 0x5d, 0xb8, 0x7c,
@@ -619,7 +619,7 @@ static uint8_t seqprog[] = {
 	0xf8, 0x1b, 0x08, 0x0b,
 	0xff, 0xea, 0x06, 0x0b,
 	0x03, 0x68, 0x00, 0x37,
-	0x00, 0xe2, 0xc4, 0x58,
+	0x00, 0xe2, 0xba, 0x58,
 	0x10, 0xea, 0x18, 0x00,
 	0xf9, 0xd9, 0xb2, 0x0d,
 	0x01, 0xd9, 0xb2, 0x05,
@@ -631,7 +631,7 @@ static uint8_t seqprog[] = {
 	0x11, 0x00, 0x00, 0x10,
 	0x04, 0x19, 0x08, 0x7d,
 	0xdf, 0x19, 0x32, 0x08,
-	0x60, 0x5b, 0xe6, 0x6c,
+	0x60, 0x5b, 0x08, 0x6d,
 	0x01, 0x4c, 0xe2, 0x7c,
 	0x20, 0x19, 0x32, 0x00,
 	0x01, 0xd9, 0xb2, 0x05,
@@ -641,29 +641,29 @@ static uint8_t seqprog[] = {
 	0x08, 0x5b, 0x0a, 0x6d,
 	0x20, 0x5b, 0xfa, 0x6c,
 	0x02, 0x5b, 0x2a, 0x6d,
-	0x0e, 0xea, 0x50, 0x59,
+	0x0e, 0xea, 0x46, 0x59,
 	0x0e, 0xea, 0x04, 0x00,
 	0x80, 0xf9, 0xea, 0x6c,
 	0xdf, 0x5c, 0xb8, 0x08,
 	0x01, 0xd9, 0xb2, 0x05,
-	0x01, 0x9c, 0xe5, 0x6d,
+	0x01, 0xa4, 0xe5, 0x6d,
 	0x00, 0xe2, 0x30, 0x5c,
 	0x00, 0xe2, 0x34, 0x5d,
-	0x01, 0xae, 0x5d, 0x1b,
+	0x01, 0x90, 0x21, 0x1b,
 	0x01, 0xd9, 0xb2, 0x05,
-	0x00, 0xe2, 0x32, 0x5b,
-	0xf3, 0xac, 0xd5, 0x19,
+	0x00, 0xe2, 0x34, 0x5b,
+	0xf3, 0x96, 0xd5, 0x19,
 	0x00, 0xe2, 0x18, 0x55,
-	0x80, 0xac, 0x19, 0x6d,
-	0x0f, 0xea, 0x50, 0x59,
+	0x80, 0x96, 0x19, 0x6d,
+	0x0f, 0xea, 0x46, 0x59,
 	0x0f, 0xea, 0x04, 0x00,
 	0x00, 0xe2, 0x20, 0x45,
 	0x04, 0x8c, 0xe1, 0x30,
 	0x01, 0xea, 0xf2, 0x00,
 	0x02, 0xea, 0x36, 0x00,
 	0xa8, 0xea, 0x32, 0x00,
-	0xff, 0xad, 0x27, 0x7d,
-	0x14, 0xea, 0x50, 0x59,
+	0xff, 0x97, 0x27, 0x7d,
+	0x14, 0xea, 0x46, 0x59,
 	0x14, 0xea, 0x04, 0x00,
 	0x00, 0xe2, 0x96, 0x5d,
 	0x01, 0xd9, 0xb2, 0x05,
@@ -673,14 +673,14 @@ static uint8_t seqprog[] = {
 	0x00, 0xe2, 0x8e, 0x5d,
 	0x01, 0xd9, 0xb2, 0x05,
 	0x02, 0xa6, 0x44, 0x7d,
-	0x00, 0xe2, 0x3e, 0x59,
+	0x00, 0xe2, 0x34, 0x59,
 	0x20, 0x5b, 0x52, 0x6d,
 	0xfc, 0x42, 0x3e, 0x7d,
 	0x10, 0x40, 0x40, 0x6d,
 	0x20, 0x4d, 0x42, 0x7d,
 	0x08, 0x5d, 0x52, 0x6d,
 	0x02, 0xa6, 0xe6, 0x6b,
-	0x00, 0xe2, 0x3e, 0x59,
+	0x00, 0xe2, 0x34, 0x59,
 	0x20, 0x5b, 0x52, 0x6d,
 	0x01, 0x1b, 0x72, 0x6d,
 	0xfc, 0x42, 0x4e, 0x7d,
@@ -690,22 +690,22 @@ static uint8_t seqprog[] = {
 	0x02, 0x19, 0x32, 0x00,
 	0x01, 0x5b, 0x40, 0x31,
 	0x00, 0xe2, 0xb2, 0x5c,
-	0x00, 0xe2, 0x9e, 0x5b,
+	0x00, 0xe2, 0xa2, 0x5b,
 	0x20, 0xea, 0xb6, 0x00,
 	0x00, 0xe2, 0xe0, 0x5b,
 	0x20, 0x5c, 0xb8, 0x00,
 	0x04, 0x19, 0x68, 0x6d,
 	0x01, 0x1a, 0x68, 0x6d,
-	0x00, 0xe2, 0x3e, 0x59,
+	0x00, 0xe2, 0x34, 0x59,
 	0x01, 0x1a, 0x64, 0x78,
 	0x80, 0xf9, 0xf2, 0x01,
 	0x20, 0xa0, 0xcc, 0x7d,
-	0xff, 0xae, 0x5d, 0x1b,
-	0x08, 0xa8, 0x43, 0x6b,
+	0xff, 0x90, 0x21, 0x1b,
+	0x08, 0x92, 0x45, 0x6b,
 	0x02, 0xea, 0xb4, 0x04,
-	0x01, 0x9c, 0x39, 0x03,
+	0x01, 0xa4, 0x49, 0x03,
 	0x40, 0x5b, 0x82, 0x6d,
-	0x00, 0xe2, 0x3e, 0x59,
+	0x00, 0xe2, 0x34, 0x59,
 	0x40, 0x5b, 0x82, 0x6d,
 	0x04, 0x5d, 0xe6, 0x7d,
 	0x01, 0x1a, 0xe6, 0x7d,
@@ -714,14 +714,14 @@ static uint8_t seqprog[] = {
 	0x04, 0x5d, 0xe6, 0x7d,
 	0x01, 0x1a, 0xe6, 0x7d,
 	0x80, 0xf9, 0xf2, 0x01,
-	0xff, 0xae, 0x5d, 0x1b,
-	0x08, 0xa8, 0x43, 0x6b,
+	0xff, 0x90, 0x21, 0x1b,
+	0x08, 0x92, 0x45, 0x6b,
 	0x02, 0xea, 0xb4, 0x04,
-	0x00, 0xe2, 0x3e, 0x59,
+	0x00, 0xe2, 0x34, 0x59,
 	0x01, 0x1b, 0x64, 0x78,
 	0x80, 0xf9, 0xf2, 0x01,
 	0x02, 0xea, 0xb4, 0x04,
-	0x00, 0xe2, 0x3e, 0x59,
+	0x00, 0xe2, 0x34, 0x59,
 	0x01, 0x1b, 0xaa, 0x6d,
 	0x40, 0x5b, 0xb8, 0x7d,
 	0x01, 0x1b, 0xaa, 0x6d,
@@ -729,45 +729,45 @@ static uint8_t seqprog[] = {
 	0x01, 0x1a, 0x64, 0x78,
 	0x80, 0xf9, 0xf2, 0x01,
 	0xff, 0xea, 0x10, 0x03,
-	0x08, 0xa8, 0x51, 0x03,
-	0x00, 0xe2, 0x42, 0x43,
+	0x08, 0x92, 0x25, 0x03,
+	0x00, 0xe2, 0x44, 0x43,
 	0x01, 0x1a, 0xb4, 0x7d,
 	0x40, 0x5b, 0xb0, 0x7d,
 	0x01, 0x1a, 0x9e, 0x6d,
 	0xfc, 0x42, 0x64, 0x78,
 	0x01, 0x1a, 0xb8, 0x6d,
-	0x10, 0xea, 0x50, 0x59,
+	0x10, 0xea, 0x46, 0x59,
 	0x10, 0xea, 0x04, 0x00,
 	0xfc, 0x42, 0x64, 0x78,
 	0x10, 0x40, 0xbe, 0x6d,
 	0x20, 0x4d, 0x64, 0x78,
 	0x40, 0x5b, 0x9e, 0x6d,
 	0x01, 0x1a, 0x64, 0x78,
-	0x01, 0xae, 0x5d, 0x1b,
+	0x01, 0x90, 0x21, 0x1b,
 	0x30, 0x3f, 0xc0, 0x09,
 	0x30, 0xe0, 0x64, 0x60,
 	0x40, 0x4b, 0x64, 0x68,
 	0xff, 0xea, 0x52, 0x01,
-	0xee, 0x00, 0xd2, 0x6d,
+	0xee, 0x00, 0xd4, 0x6d,
 	0x80, 0xf9, 0xf2, 0x01,
-	0xff, 0xae, 0x5d, 0x1b,
+	0xff, 0x90, 0x21, 0x1b,
 	0x02, 0xea, 0xb4, 0x00,
 	0x20, 0xea, 0x9a, 0x00,
 	0xf3, 0x42, 0xde, 0x6d,
-	0x12, 0xea, 0x50, 0x59,
+	0x12, 0xea, 0x46, 0x59,
 	0x12, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x0d, 0xea, 0x50, 0x59,
+	0x00, 0xe2, 0xf6, 0x41,
+	0x0d, 0xea, 0x46, 0x59,
 	0x0d, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0xf8, 0x41,
-	0x01, 0xae, 0x5d, 0x1b,
-	0x11, 0xea, 0x50, 0x59,
+	0x00, 0xe2, 0xf6, 0x41,
+	0x01, 0x90, 0x21, 0x1b,
+	0x11, 0xea, 0x46, 0x59,
 	0x11, 0xea, 0x04, 0x00,
-	0x00, 0xe2, 0x32, 0x5b,
+	0x00, 0xe2, 0x34, 0x5b,
 	0x08, 0x5a, 0xb4, 0x00,
 	0x00, 0xe2, 0x0c, 0x5e,
 	0xa8, 0xea, 0x32, 0x00,
-	0x00, 0xe2, 0x3e, 0x59,
+	0x00, 0xe2, 0x34, 0x59,
 	0x80, 0x1a, 0xfa, 0x7d,
 	0x00, 0xe2, 0x0c, 0x5e,
 	0x80, 0x19, 0x32, 0x00,
@@ -776,9 +776,9 @@ static uint8_t seqprog[] = {
 	0x20, 0x4d, 0x64, 0x78,
 	0x02, 0x84, 0x09, 0x03,
 	0x40, 0x5b, 0xcc, 0x7d,
-	0xff, 0xae, 0x5d, 0x1b,
+	0xff, 0x90, 0x21, 0x1b,
 	0x80, 0xf9, 0xf2, 0x01,
-	0x08, 0xa8, 0x43, 0x6b,
+	0x08, 0x92, 0x45, 0x6b,
 	0x02, 0xea, 0xb4, 0x04,
 	0x01, 0x38, 0xe1, 0x30,
 	0x05, 0x39, 0xe3, 0x98,
@@ -794,12 +794,20 @@ static uint8_t seqprog[] = {
 };
 
 typedef int ahd_patch_func_t (struct ahd_softc *ahd);
+static ahd_patch_func_t ahd_patch23_func;
+
+static int
+ahd_patch23_func(struct ahd_softc *ahd)
+{
+	return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0);
+}
+
 static ahd_patch_func_t ahd_patch22_func;
 
 static int
 ahd_patch22_func(struct ahd_softc *ahd)
 {
-	return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0);
+	return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0);
 }
 
 static ahd_patch_func_t ahd_patch21_func;
@@ -807,7 +815,7 @@ static ahd_patch_func_t ahd_patch21_func
 static int
 ahd_patch21_func(struct ahd_softc *ahd)
 {
-	return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0);
+	return ((ahd->features & AHD_RTI) == 0);
 }
 
 static ahd_patch_func_t ahd_patch20_func;
@@ -815,7 +823,7 @@ static ahd_patch_func_t ahd_patch20_func
 static int
 ahd_patch20_func(struct ahd_softc *ahd)
 {
-	return ((ahd->features & AHD_RTI) == 0);
+	return ((ahd->flags & AHD_INITIATORROLE) != 0);
 }
 
 static ahd_patch_func_t ahd_patch19_func;
@@ -823,7 +831,7 @@ static ahd_patch_func_t ahd_patch19_func
 static int
 ahd_patch19_func(struct ahd_softc *ahd)
 {
-	return ((ahd->flags & AHD_INITIATORROLE) != 0);
+	return ((ahd->flags & AHD_TARGETROLE) != 0);
 }
 
 static ahd_patch_func_t ahd_patch18_func;
@@ -831,7 +839,7 @@ static ahd_patch_func_t ahd_patch18_func
 static int
 ahd_patch18_func(struct ahd_softc *ahd)
 {
-	return ((ahd->flags & AHD_TARGETROLE) != 0);
+	return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0);
 }
 
 static ahd_patch_func_t ahd_patch17_func;
@@ -839,7 +847,7 @@ static ahd_patch_func_t ahd_patch17_func
 static int
 ahd_patch17_func(struct ahd_softc *ahd)
 {
-	return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0);
+	return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0);
 }
 
 static ahd_patch_func_t ahd_patch16_func;
@@ -847,7 +855,7 @@ static ahd_patch_func_t ahd_patch16_func
 static int
 ahd_patch16_func(struct ahd_softc *ahd)
 {
-	return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0);
+	return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0);
 }
 
 static ahd_patch_func_t ahd_patch15_func;
@@ -855,7 +863,7 @@ static ahd_patch_func_t ahd_patch15_func
 static int
 ahd_patch15_func(struct ahd_softc *ahd)
 {
-	return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0);
+	return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0);
 }
 
 static ahd_patch_func_t ahd_patch14_func;
@@ -863,7 +871,7 @@ static ahd_patch_func_t ahd_patch14_func
 static int
 ahd_patch14_func(struct ahd_softc *ahd)
 {
-	return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0);
+	return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0);
 }
 
 static ahd_patch_func_t ahd_patch13_func;
@@ -871,7 +879,7 @@ static ahd_patch_func_t ahd_patch13_func
 static int
 ahd_patch13_func(struct ahd_softc *ahd)
 {
-	return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0);
+	return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0);
 }
 
 static ahd_patch_func_t ahd_patch12_func;
@@ -879,7 +887,7 @@ static ahd_patch_func_t ahd_patch12_func
 static int
 ahd_patch12_func(struct ahd_softc *ahd)
 {
-	return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0);
+	return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0);
 }
 
 static ahd_patch_func_t ahd_patch11_func;
@@ -887,7 +895,7 @@ static ahd_patch_func_t ahd_patch11_func
 static int
 ahd_patch11_func(struct ahd_softc *ahd)
 {
-	return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0);
+	return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0);
 }
 
 static ahd_patch_func_t ahd_patch10_func;
@@ -895,7 +903,7 @@ static ahd_patch_func_t ahd_patch10_func
 static int
 ahd_patch10_func(struct ahd_softc *ahd)
 {
-	return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0);
+	return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0);
 }
 
 static ahd_patch_func_t ahd_patch9_func;
@@ -903,7 +911,7 @@ static ahd_patch_func_t ahd_patch9_func;
 static int
 ahd_patch9_func(struct ahd_softc *ahd)
 {
-	return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0);
+	return ((ahd->features & AHD_FAST_CDB_DELIVERY) != 0);
 }
 
 static ahd_patch_func_t ahd_patch8_func;
@@ -1003,73 +1011,75 @@ static struct patch {
 	{ ahd_patch0_func, 48, 1, 1 },
 	{ ahd_patch2_func, 51, 1, 2 },
 	{ ahd_patch0_func, 52, 1, 1 },
+	{ ahd_patch2_func, 61, 1, 2 },
+	{ ahd_patch0_func, 62, 1, 1 },
 	{ ahd_patch2_func, 65, 1, 2 },
 	{ ahd_patch0_func, 66, 1, 1 },
-	{ ahd_patch2_func, 69, 1, 2 },
-	{ ahd_patch0_func, 70, 1, 1 },
-	{ ahd_patch1_func, 73, 1, 2 },
-	{ ahd_patch0_func, 74, 1, 1 },
-	{ ahd_patch4_func, 107, 1, 1 },
-	{ ahd_patch2_func, 162, 6, 1 },
-	{ ahd_patch1_func, 168, 2, 1 },
-	{ ahd_patch5_func, 170, 1, 1 },
-	{ ahd_patch2_func, 179, 1, 2 },
-	{ ahd_patch0_func, 180, 1, 1 },
-	{ ahd_patch6_func, 181, 2, 2 },
-	{ ahd_patch0_func, 183, 6, 3 },
-	{ ahd_patch2_func, 186, 1, 2 },
-	{ ahd_patch0_func, 187, 1, 1 },
-	{ ahd_patch2_func, 190, 1, 2 },
-	{ ahd_patch0_func, 191, 1, 1 },
-	{ ahd_patch7_func, 193, 2, 1 },
-	{ ahd_patch5_func, 201, 16, 2 },
-	{ ahd_patch0_func, 217, 1, 1 },
-	{ ahd_patch8_func, 237, 2, 1 },
-	{ ahd_patch1_func, 241, 1, 2 },
-	{ ahd_patch0_func, 242, 1, 1 },
-	{ ahd_patch7_func, 245, 2, 1 },
-	{ ahd_patch1_func, 259, 1, 2 },
-	{ ahd_patch0_func, 260, 1, 1 },
-	{ ahd_patch1_func, 263, 1, 2 },
-	{ ahd_patch0_func, 264, 1, 1 },
-	{ ahd_patch2_func, 267, 1, 2 },
-	{ ahd_patch0_func, 268, 1, 1 },
-	{ ahd_patch1_func, 323, 1, 2 },
-	{ ahd_patch0_func, 324, 1, 1 },
-	{ ahd_patch2_func, 332, 1, 2 },
-	{ ahd_patch0_func, 333, 1, 1 },
-	{ ahd_patch2_func, 336, 1, 2 },
-	{ ahd_patch0_func, 337, 1, 1 },
-	{ ahd_patch1_func, 343, 1, 2 },
-	{ ahd_patch0_func, 344, 1, 1 },
-	{ ahd_patch1_func, 346, 1, 2 },
-	{ ahd_patch0_func, 347, 1, 1 },
-	{ ahd_patch9_func, 366, 1, 1 },
-	{ ahd_patch9_func, 369, 1, 1 },
-	{ ahd_patch9_func, 371, 1, 1 },
-	{ ahd_patch9_func, 383, 1, 1 },
-	{ ahd_patch1_func, 393, 1, 2 },
-	{ ahd_patch0_func, 394, 1, 1 },
-	{ ahd_patch1_func, 396, 1, 2 },
-	{ ahd_patch0_func, 397, 1, 1 },
-	{ ahd_patch1_func, 405, 1, 2 },
-	{ ahd_patch0_func, 406, 1, 1 },
-	{ ahd_patch2_func, 419, 1, 2 },
-	{ ahd_patch0_func, 420, 1, 1 },
-	{ ahd_patch10_func, 450, 1, 1 },
-	{ ahd_patch1_func, 457, 1, 2 },
-	{ ahd_patch0_func, 458, 1, 1 },
-	{ ahd_patch2_func, 470, 1, 2 },
-	{ ahd_patch0_func, 471, 1, 1 },
-	{ ahd_patch11_func, 476, 6, 2 },
+	{ ahd_patch4_func, 102, 1, 1 },
+	{ ahd_patch2_func, 157, 6, 1 },
+	{ ahd_patch1_func, 163, 2, 1 },
+	{ ahd_patch5_func, 165, 1, 1 },
+	{ ahd_patch2_func, 174, 1, 2 },
+	{ ahd_patch0_func, 175, 1, 1 },
+	{ ahd_patch6_func, 176, 2, 2 },
+	{ ahd_patch0_func, 178, 6, 3 },
+	{ ahd_patch2_func, 181, 1, 2 },
+	{ ahd_patch0_func, 182, 1, 1 },
+	{ ahd_patch2_func, 185, 1, 2 },
+	{ ahd_patch0_func, 186, 1, 1 },
+	{ ahd_patch3_func, 188, 1, 1 },
+	{ ahd_patch7_func, 189, 3, 1 },
+	{ ahd_patch3_func, 198, 1, 1 },
+	{ ahd_patch5_func, 199, 16, 2 },
+	{ ahd_patch0_func, 215, 1, 1 },
+	{ ahd_patch8_func, 235, 2, 1 },
+	{ ahd_patch1_func, 239, 1, 2 },
+	{ ahd_patch0_func, 240, 1, 1 },
+	{ ahd_patch7_func, 243, 3, 1 },
+	{ ahd_patch1_func, 258, 1, 2 },
+	{ ahd_patch0_func, 259, 1, 1 },
+	{ ahd_patch1_func, 262, 1, 2 },
+	{ ahd_patch0_func, 263, 1, 1 },
+	{ ahd_patch2_func, 266, 1, 2 },
+	{ ahd_patch0_func, 267, 1, 1 },
+	{ ahd_patch9_func, 280, 2, 2 },
+	{ ahd_patch0_func, 282, 1, 1 },
+	{ ahd_patch1_func, 324, 1, 2 },
+	{ ahd_patch0_func, 325, 1, 1 },
+	{ ahd_patch2_func, 333, 1, 2 },
+	{ ahd_patch0_func, 334, 1, 1 },
+	{ ahd_patch2_func, 337, 1, 2 },
+	{ ahd_patch0_func, 338, 1, 1 },
+	{ ahd_patch1_func, 344, 1, 2 },
+	{ ahd_patch0_func, 345, 1, 1 },
+	{ ahd_patch1_func, 347, 1, 2 },
+	{ ahd_patch0_func, 348, 1, 1 },
+	{ ahd_patch10_func, 367, 1, 1 },
+	{ ahd_patch10_func, 370, 1, 1 },
+	{ ahd_patch10_func, 372, 1, 1 },
+	{ ahd_patch10_func, 384, 1, 1 },
+	{ ahd_patch1_func, 394, 1, 2 },
+	{ ahd_patch0_func, 395, 1, 1 },
+	{ ahd_patch1_func, 397, 1, 2 },
+	{ ahd_patch0_func, 398, 1, 1 },
+	{ ahd_patch1_func, 406, 1, 2 },
+	{ ahd_patch0_func, 407, 1, 1 },
+	{ ahd_patch2_func, 420, 1, 2 },
+	{ ahd_patch0_func, 421, 1, 1 },
+	{ ahd_patch11_func, 451, 1, 1 },
+	{ ahd_patch1_func, 459, 1, 2 },
+	{ ahd_patch0_func, 460, 1, 1 },
+	{ ahd_patch2_func, 472, 1, 2 },
+	{ ahd_patch0_func, 473, 1, 1 },
+	{ ahd_patch12_func, 476, 6, 2 },
 	{ ahd_patch0_func, 482, 1, 1 },
-	{ ahd_patch12_func, 505, 1, 1 },
-	{ ahd_patch13_func, 514, 1, 1 },
-	{ ahd_patch14_func, 515, 1, 2 },
+	{ ahd_patch13_func, 505, 1, 1 },
+	{ ahd_patch14_func, 514, 1, 1 },
+	{ ahd_patch15_func, 515, 1, 2 },
 	{ ahd_patch0_func, 516, 1, 1 },
-	{ ahd_patch15_func, 519, 1, 1 },
-	{ ahd_patch14_func, 520, 1, 1 },
-	{ ahd_patch16_func, 531, 1, 2 },
+	{ ahd_patch16_func, 519, 1, 1 },
+	{ ahd_patch15_func, 520, 1, 1 },
+	{ ahd_patch17_func, 531, 1, 2 },
 	{ ahd_patch0_func, 532, 1, 1 },
 	{ ahd_patch1_func, 551, 1, 2 },
 	{ ahd_patch0_func, 552, 1, 1 },
@@ -1083,25 +1093,25 @@ static struct patch {
 	{ ahd_patch0_func, 569, 1, 1 },
 	{ ahd_patch2_func, 580, 1, 2 },
 	{ ahd_patch0_func, 581, 1, 1 },
-	{ ahd_patch17_func, 585, 1, 1 },
-	{ ahd_patch18_func, 590, 1, 1 },
-	{ ahd_patch19_func, 591, 2, 1 },
-	{ ahd_patch18_func, 595, 1, 2 },
+	{ ahd_patch18_func, 585, 1, 1 },
+	{ ahd_patch19_func, 590, 1, 1 },
+	{ ahd_patch20_func, 591, 2, 1 },
+	{ ahd_patch19_func, 595, 1, 2 },
 	{ ahd_patch0_func, 596, 1, 1 },
 	{ ahd_patch2_func, 599, 1, 2 },
 	{ ahd_patch0_func, 600, 1, 1 },
 	{ ahd_patch2_func, 615, 1, 2 },
 	{ ahd_patch0_func, 616, 1, 1 },
-	{ ahd_patch20_func, 617, 14, 1 },
+	{ ahd_patch21_func, 617, 14, 1 },
 	{ ahd_patch1_func, 635, 1, 2 },
 	{ ahd_patch0_func, 636, 1, 1 },
-	{ ahd_patch20_func, 637, 1, 1 },
+	{ ahd_patch21_func, 637, 1, 1 },
 	{ ahd_patch1_func, 649, 1, 2 },
 	{ ahd_patch0_func, 650, 1, 1 },
 	{ ahd_patch1_func, 657, 1, 2 },
 	{ ahd_patch0_func, 658, 1, 1 },
-	{ ahd_patch17_func, 681, 1, 1 },
-	{ ahd_patch17_func, 719, 1, 1 },
+	{ ahd_patch18_func, 681, 1, 1 },
+	{ ahd_patch18_func, 719, 1, 1 },
 	{ ahd_patch1_func, 730, 1, 2 },
 	{ ahd_patch0_func, 731, 1, 1 },
 	{ ahd_patch1_func, 748, 1, 2 },
@@ -1110,11 +1120,11 @@ static struct patch {
 	{ ahd_patch0_func, 752, 1, 1 },
 	{ ahd_patch1_func, 755, 1, 2 },
 	{ ahd_patch0_func, 756, 1, 1 },
-	{ ahd_patch21_func, 758, 1, 2 },
+	{ ahd_patch22_func, 758, 1, 2 },
 	{ ahd_patch0_func, 759, 2, 1 },
-	{ ahd_patch22_func, 762, 4, 2 },
+	{ ahd_patch23_func, 762, 4, 2 },
 	{ ahd_patch0_func, 766, 1, 1 },
-	{ ahd_patch22_func, 774, 11, 1 }
+	{ ahd_patch23_func, 774, 11, 1 }
 };
 
 static struct cs {
@@ -1123,15 +1133,18 @@ static struct cs {
 } critical_sections[] = {
 	{ 11, 12 },
 	{ 13, 14 },
-	{ 29, 42 },
-	{ 56, 59 },
-	{ 101, 128 },
-	{ 129, 157 },
-	{ 159, 162 },
-	{ 170, 178 },
-	{ 201, 250 },
-	{ 681, 697 },
-	{ 697, 711 },
+	{ 31, 42 },
+	{ 45, 47 },
+	{ 49, 50 },
+	{ 56, 78 },
+	{ 96, 123 },
+	{ 124, 152 },
+	{ 154, 157 },
+	{ 165, 173 },
+	{ 198, 249 },
+	{ 428, 430 },
+	{ 433, 436 },
+	{ 681, 711 },
 	{ 721, 725 }
 };
 
diff -puN drivers/scsi/aic7xxx/aic7xxx_93cx6.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7xxx_93cx6.c
--- 25/drivers/scsi/aic7xxx/aic7xxx_93cx6.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7xxx_93cx6.c	Wed Dec 24 12:15:38 2003
@@ -28,9 +28,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#17 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#19 $
  */
 
 /*
@@ -64,7 +62,6 @@
  *   is preceded by an initial zero (leading 0, followed by 16-bits, MSB
  *   first).  The clock cycling from low to high initiates the next data
  *   bit to be sent from the chip.
- *
  */
 
 #ifdef __linux__
@@ -72,6 +69,8 @@
 #include "aic7xxx_inline.h"
 #include "aic7xxx_93cx6.h"
 #else
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 #include <dev/aic7xxx/aic7xxx_osm.h>
 #include <dev/aic7xxx/aic7xxx_inline.h>
 #include <dev/aic7xxx/aic7xxx_93cx6.h>
@@ -81,14 +80,22 @@
  * Right now, we only have to read the SEEPROM.  But we make it easier to
  * add other 93Cx6 functions.
  */
-static struct seeprom_cmd {
+struct seeprom_cmd {
   	uint8_t len;
- 	uint8_t bits[9];
-} seeprom_read = {3, {1, 1, 0}};
+ 	uint8_t bits[11];
+};
 
+/* Short opcodes for the c46 */
 static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
 static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+/* Long opcodes for the C56/C66 */
+static struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
+static struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+/* Common opcodes */
 static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
+static struct seeprom_cmd seeprom_read  = {3, {1, 1, 0}};
 
 /*
  * Wait for the SEERDY to go high; about 800 ns.
@@ -222,12 +229,25 @@ int
 ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
 		  u_int start_addr, u_int count)
 {
+	struct seeprom_cmd *ewen, *ewds;
 	uint16_t v;
 	uint8_t temp;
 	int i, k;
 
 	/* Place the chip into write-enable mode */
-	send_seeprom_cmd(sd, &seeprom_ewen);
+	if (sd->sd_chip == C46) {
+		ewen = &seeprom_ewen;
+		ewds = &seeprom_ewds;
+	} else if (sd->sd_chip == C56_66) {
+		ewen = &seeprom_long_ewen;
+		ewds = &seeprom_long_ewds;
+	} else {
+		printf("ahc_write_seeprom: unsupported seeprom type %d\n",
+		       sd->sd_chip);
+		return (0);
+	}
+
+	send_seeprom_cmd(sd, ewen);
 	reset_seeprom(sd);
 
 	/* Write all requested data out to the seeprom. */
@@ -277,7 +297,7 @@ ahc_write_seeprom(struct seeprom_descrip
 	}
 
 	/* Put the chip back into write-protect mode */
-	send_seeprom_cmd(sd, &seeprom_ewds);
+	send_seeprom_cmd(sd, ewds);
 	reset_seeprom(sd);
 
 	return (1);
diff -puN drivers/scsi/aic7xxx/aic7xxx_core.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7xxx_core.c
--- 25/drivers/scsi/aic7xxx/aic7xxx_core.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7xxx_core.c	Wed Dec 24 12:15:38 2003
@@ -37,9 +37,7 @@
  * 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#131 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#147 $
  */
 
 #ifdef __linux__
@@ -47,6 +45,8 @@
 #include "aic7xxx_inline.h"
 #include "aicasm/aicasm_insformat.h"
 #else
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 #include <dev/aic7xxx/aic7xxx_osm.h>
 #include <dev/aic7xxx/aic7xxx_inline.h>
 #include <dev/aic7xxx/aicasm/aicasm_insformat.h>
@@ -320,7 +320,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);
@@ -458,14 +458,14 @@ ahc_handle_seqint(struct ahc_softc *ahc,
 			 * 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:
 			printf("%s: Interrupted for staus of 0???\n",
@@ -487,7 +487,7 @@ ahc_handle_seqint(struct ahc_softc *ahc,
 			}
 #endif
 
-			if (ahc_perform_autosense(scb) == 0)
+			if (aic_perform_autosense(scb) == 0)
 				break;
 
 			targ_info = ahc_fetch_transinfo(ahc,
@@ -509,12 +509,12 @@ ahc_handle_seqint(struct ahc_softc *ahc,
 			}
 #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;
@@ -543,8 +543,8 @@ ahc_handle_seqint(struct ahc_softc *ahc,
 			 * 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);
@@ -558,7 +558,7 @@ ahc_handle_seqint(struct ahc_softc *ahc,
 			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);
@@ -567,7 +567,7 @@ ahc_handle_seqint(struct ahc_softc *ahc,
 			 * 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:
@@ -768,7 +768,7 @@ ahc_handle_seqint(struct ahc_softc *ahc,
 					if ((ahc_inb(ahc, SCSISIGI)
 					  & (CDI|MSGI)) != 0)
 						break;
-					ahc_delay(100);
+					aic_delay(100);
 				}
 				ahc_outb(ahc, SXFRCTL1,
 					 ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET);
@@ -782,7 +782,7 @@ ahc_handle_seqint(struct ahc_softc *ahc,
 					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);
@@ -820,16 +820,16 @@ ahc_handle_seqint(struct ahc_softc *ahc,
 		ahc_print_path(ahc, scb);
 		printf("%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++) {
 
 				printf("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);
 			}
 		}
@@ -839,12 +839,12 @@ ahc_handle_seqint(struct ahc_softc *ahc,
 		 */
 		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) {
 			/*
@@ -1188,7 +1188,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc
 			 */
 			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);
@@ -1270,7 +1270,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc
 						  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,
@@ -1304,17 +1304,23 @@ ahc_handle_scsiint(struct ahc_softc *ahc
 				ahc_qinfifo_requeue_tail(ahc, scb);
 				printerror = 0;
 			} else if (ahc_sent_msg(ahc, AHCMSG_EXT,
-						MSG_EXT_WDTR, FALSE)
-				|| ahc_sent_msg(ahc, AHCMSG_EXT,
-						MSG_EXT_SDTR, FALSE)) {
+						MSG_EXT_WDTR, FALSE)) {
 				/*
-				 * Negotiation Rejected.  Go-async and
+				 * Negotiation Rejected.  Go-narrow and
 				 * retry command.
 				 */
 				ahc_set_width(ahc, &devinfo,
 					      MSG_EXT_WDTR_BUS_8_BIT,
 					      AHC_TRANS_CUR|AHC_TRANS_GOAL,
 					      /*paused*/TRUE);
+				ahc_qinfifo_requeue_tail(ahc, scb);
+				printerror = 0;
+			} else if (ahc_sent_msg(ahc, AHCMSG_EXT,
+						MSG_EXT_SDTR, FALSE)) {
+				/*
+				 * Negotiation Rejected.  Go-async and
+				 * retry command.
+				 */
 				ahc_set_syncrate(ahc, &devinfo,
 						/*syncrate*/NULL,
 						/*period*/0, /*offset*/0,
@@ -1463,7 +1469,7 @@ ahc_clear_critical_section(struct ahc_so
 				 * current connection, so we must
 				 * leave it on while single stepping.
 				 */
-				ahc_outb(ahc, SIMODE1, ENBUSFREE);
+				ahc_outb(ahc, SIMODE1, simode1 & ENBUSFREE);
 			else
 				ahc_outb(ahc, SIMODE1, 0);
 			ahc_outb(ahc, CLRINT, CLRSCSIINT);
@@ -1476,7 +1482,7 @@ ahc_clear_critical_section(struct ahc_so
 		}
 		ahc_outb(ahc, HCNTRL, ahc->unpause);
 		while (!ahc_is_paused(ahc))
-			ahc_delay(200);
+			aic_delay(200);
 	}
 	if (stepping) {
 		ahc_outb(ahc, SIMODE0, simode0);
@@ -1524,18 +1530,18 @@ ahc_print_scb(struct scb *scb)
 	for (i = 0; i < sizeof(hscb->shared_data.cdb); i++)
 		printf("%#02x", hscb->shared_data.cdb[i]);
 	printf("        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++) {
 			printf("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));
 		}
 	}
 }
@@ -2373,6 +2379,7 @@ ahc_build_transfer_msg(struct ahc_softc 
 	 * may change.
 	 */
 	period = tinfo->goal.period;
+	offset = tinfo->goal.offset;
 	ppr_options = tinfo->goal.ppr_options;
 	/* Target initiated PPR is not allowed in the SCSI spec */
 	if (devinfo->role == ROLE_TARGET)
@@ -2380,7 +2387,7 @@ ahc_build_transfer_msg(struct ahc_softc 
 	rate = ahc_devlimited_syncrate(ahc, tinfo, &period,
 				       &ppr_options, devinfo->role);
 	dowide = tinfo->curr.width != tinfo->goal.width;
-	dosync = tinfo->curr.period != period;
+	dosync = tinfo->curr.offset != offset || tinfo->curr.period != period;
 	/*
 	 * Only use PPR if we have options that need it, even if the device
 	 * claims to support it.  There might be an expander in the way
@@ -2568,7 +2575,7 @@ ahc_handle_proto_violation(struct ahc_so
 		printf("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);
 			printf("No or incomplete CDB sent to device.\n");
@@ -3176,23 +3183,30 @@ ahc_parse_msg(struct ahc_softc *ahc, str
 				response = TRUE;
 				sending_reply = TRUE;
 			}
+			/*
+			 * After a wide message, we are async, but
+			 * some devices don't seem to honor this portion
+			 * of the spec.  Force a renegotiation of the
+			 * sync component of our transfer agreement even
+			 * if our goal is async.  By updating our width
+			 * after forcing the negotiation, we avoid
+			 * renegotiating for width.
+			 */
+			ahc_update_neg_request(ahc, devinfo, tstate,
+					       tinfo, AHC_NEG_ALWAYS);
 			ahc_set_width(ahc, devinfo, bus_width,
 				      AHC_TRANS_ACTIVE|AHC_TRANS_GOAL,
 				      /*paused*/TRUE);
-			/* After a wide message, we are async */
-			ahc_set_syncrate(ahc, devinfo,
-					 /*syncrate*/NULL, /*period*/0,
-					 /*offset*/0, /*ppr_options*/0,
-					 AHC_TRANS_ACTIVE, /*paused*/TRUE);
 			if (sending_reply == FALSE && reject == FALSE) {
 
-				if (tinfo->goal.offset) {
-					ahc->msgout_index = 0;
-					ahc->msgout_len = 0;
-					ahc_build_transfer_msg(ahc, devinfo);
-					ahc->msgout_index = 0;
-					response = TRUE;
-				}
+				/*
+				 * We will always have an SDTR to send.
+				 */
+				ahc->msgout_index = 0;
+				ahc->msgout_len = 0;
+				ahc_build_transfer_msg(ahc, devinfo);
+				ahc->msgout_index = 0;
+				response = TRUE;
 			}
 			done = MSGLOOP_MSGCOMPLETE;
 			break;
@@ -3499,7 +3513,7 @@ ahc_handle_msg_reject(struct ahc_softc *
 		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);
@@ -3556,7 +3570,7 @@ ahc_handle_ign_wide_residue(struct ahc_s
 	 * 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.
@@ -3612,18 +3626,18 @@ ahc_handle_ign_wide_residue(struct ahc_s
 			 * 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;
 
 				/*
@@ -3679,8 +3693,8 @@ ahc_reinitialize_dataptrs(struct ahc_sof
 	      | (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;
@@ -3688,7 +3702,7 @@ ahc_reinitialize_dataptrs(struct ahc_sof
 		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);
@@ -3869,7 +3883,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.
@@ -3877,17 +3891,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 {
@@ -3955,27 +3969,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:
@@ -3983,7 +3997,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);
@@ -4033,7 +4047,7 @@ ahc_shutdown(void *arg)
 	ahc = (struct ahc_softc *)arg;
 
 	/* This will reset most registers to 0, but not all */
-	ahc_reset(ahc);
+	ahc_reset(ahc, /*reinit*/FALSE);
 	ahc_outb(ahc, SCSISEQ, 0);
 	ahc_outb(ahc, SXFRCTL0, 0);
 	ahc_outb(ahc, DSPCISTATUS, 0);
@@ -4044,10 +4058,15 @@ ahc_shutdown(void *arg)
 
 /*
  * Reset the controller and record some information about it
- * that is only available just after a reset.
+ * that is only available just after a reset.  If "reinit" is
+ * non-zero, this reset occured after initial configuration
+ * and the caller requests that the chip be fully reinitialized
+ * to a runable state.  Chip interrupts are *not* enabled after
+ * a reinitialization.  The caller must enable interrupts via
+ * ahc_intr_enable().
  */
 int
-ahc_reset(struct ahc_softc *ahc)
+ahc_reset(struct ahc_softc *ahc, int reinit)
 {
 	u_int	sblkctl;
 	u_int	sxfrctl1_a, sxfrctl1_b;
@@ -4060,14 +4079,6 @@ ahc_reset(struct ahc_softc *ahc)
 	 * 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;
@@ -4093,7 +4104,7 @@ ahc_reset(struct ahc_softc *ahc)
 	 */
 	wait = 1000;
 	do {
-		ahc_delay(1000);
+		aic_delay(1000);
 	} while (--wait && !(ahc_inb(ahc, HCNTRL) & CHIPRSTACK));
 
 	if (wait == 0) {
@@ -4143,7 +4154,7 @@ ahc_reset(struct ahc_softc *ahc)
 	ahc_outb(ahc, SXFRCTL1, sxfrctl1_a);
 
 	error = 0;
-	if (ahc->init_level > 0)
+	if (reinit != 0)
 		/*
 		 * If a recovery action has forced a chip reset,
 		 * re-initialize the chip to our liking.
@@ -4273,7 +4284,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,
@@ -4288,7 +4299,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;
@@ -4297,7 +4308,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);
@@ -4305,7 +4316,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,
@@ -4320,7 +4331,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;
@@ -4329,7 +4340,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);
@@ -4337,7 +4348,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,
@@ -4394,35 +4405,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);
 			free(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;
@@ -4455,7 +4466,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc)
 		return;
 
 	/* 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) {
 		free(sg_map, M_DEVBUF);
@@ -4464,7 +4475,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);
 
@@ -4491,9 +4502,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;
@@ -4725,14 +4736,12 @@ ahc_chip_init(struct ahc_softc *ahc)
 		 * never settle, so don't complain if we
 		 * fail here.
 		 */
-		ahc_pause(ahc);
 		for (wait = 5000;
 		     (ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait;
 		     wait--)
-			ahc_delay(100);
-		ahc_unpause(ahc);
+			aic_delay(100);
 	}
-
+	ahc_restart(ahc);
 	return (0);
 }
 
@@ -4743,6 +4752,7 @@ int
 ahc_init(struct ahc_softc *ahc)
 {
 	int	 max_targ;
+	int	 error;
 	u_int	 i;
 	u_int	 scsi_conf;
 	u_int	 ultraenb;
@@ -4800,7 +4810,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
@@ -4831,7 +4841,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,
@@ -4846,7 +4856,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);
@@ -4855,7 +4865,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);
 
@@ -4898,6 +4908,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 {
@@ -5095,8 +5112,14 @@ ahc_pause_and_flushwork(struct ahc_softc
 	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;
@@ -5145,7 +5168,9 @@ int
 ahc_resume(struct ahc_softc *ahc)
 {
 
-	ahc_reset(ahc);
+	ahc_reset(ahc, /*reinit*/TRUE);
+	ahc_intr_enable(ahc, TRUE); 
+	ahc_restart(ahc);
 	return (0);
 }
 
@@ -5380,12 +5405,12 @@ ahc_search_qinfifo(struct ahc_softc *ahc
 				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)
 					printf("Inactive SCB in qinfifo\n");
 				ahc_done(ahc, scb);
@@ -5492,13 +5517,13 @@ ahc_search_qinfifo(struct ahc_softc *ahc
 				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)
 					printf("Inactive SCB in Waiting List\n");
 				ahc_done(ahc, scb);
@@ -5520,7 +5545,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc
 	}
 	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)
@@ -5529,7 +5554,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc
 }
 
 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)
 {
@@ -5600,12 +5625,12 @@ ahc_search_untagged_queues(struct ahc_so
 				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)
 					printf("Inactive SCB in untaggedQ\n");
 				ahc_done(ahc, scb);
@@ -5904,11 +5929,11 @@ ahc_abort_scbs(struct ahc_softc *ahc, in
 		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)
 				printf("Inactive SCB on pending list\n");
 			ahc_done(ahc, scbp);
@@ -5930,7 +5955,7 @@ ahc_reset_current_bus(struct ahc_softc *
 	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);
 
@@ -6137,7 +6162,7 @@ ahc_calc_residual(struct ahc_softc *ahc,
 	 */
 
 	hscb = scb->hscb;
-	sgptr = ahc_le32toh(hscb->sgptr);
+	sgptr = aic_le32toh(hscb->sgptr);
 	if ((sgptr & SG_RESID_VALID) == 0)
 		/* Case 1 */
 		return;
@@ -6148,10 +6173,10 @@ ahc_calc_residual(struct ahc_softc *ahc,
 		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;
@@ -6164,7 +6189,7 @@ ahc_calc_residual(struct ahc_softc *ahc,
 		 * 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 */
@@ -6175,15 +6200,15 @@ ahc_calc_residual(struct ahc_softc *ahc,
 		 * 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) {
@@ -6407,7 +6432,6 @@ ahc_loadseq(struct ahc_softc *ahc)
 		memcpy(ahc->critical_sections, cs_table, cs_count);
 	}
 	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE);
-	ahc_restart(ahc);
 
 	if (bootverbose) {
 		printf(" %d instructions downloaded\n", downloaded);
@@ -6464,7 +6488,7 @@ ahc_download_instr(struct ahc_softc *ahc
 	/*
 	 * 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;
@@ -6569,7 +6593,7 @@ ahc_download_instr(struct ahc_softc *ahc
 			}
 		}
 		/* 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:
@@ -6809,6 +6833,324 @@ ahc_dump_card_state(struct ahc_softc *ah
 		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;
+	long	s;
+	int	found;
+	int	restart_needed;
+	u_int	last_phase;
+
+	ahc_lock(ahc, &s);
+
+	/*
+	 * 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.
+		 */
+		printf("%s: Timedout SCBs already complete. "
+		       "Interrupts may not be functioning.\n", ahc_name(ahc));
+		ahc_unpause(ahc);
+		ahc_unlock(ahc, &s);
+		return;
+	}
+
+	restart_needed = 0;
+	printf("%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);
+		printf("SCB 0x%x - timed out\n", scb->hscb->tag);
+		if (scb->sg_count > 0) {
+			for (i = 0; i < scb->sg_count; i++) {
+				printf("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);
+			printf("%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);
+				printf("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);
+			printf("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.
+			 */
+			printf("%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 */
+				printf("%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);
+				printf("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);
+				printf("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(ahc, &s);
+}
+
 /************************* Target Mode ****************************************/
 #ifdef AHC_TARGET_MODE
 cam_status
@@ -6968,11 +7310,12 @@ ahc_handle_en_lun(struct ahc_softc *ahc,
 			 */
 			ahc->flags = saved_flags;
 			(void)ahc_loadseq(ahc);
-			ahc_unpause(ahc);
+			ahc_restart(ahc);
 			ahc_unlock(ahc, &s);
 			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
 			return;
 		}
+		ahc_restart(ahc);
 		ahc_unlock(ahc, &s);
 	}
 	cel = &ccb->cel;
@@ -7207,12 +7550,16 @@ ahc_handle_en_lun(struct ahc_softc *ahc,
 				printf("Configuring Initiator Mode\n");
 				ahc->flags &= ~AHC_TARGETROLE;
 				ahc->flags |= AHC_INITIATORROLE;
-				ahc_pause(ahc);
 				/*
 				 * Returning to a configuration that
 				 * fit previously will always succeed.
 				 */
 				(void)ahc_loadseq(ahc);
+				ahc_restart(ahc);
+				/*
+				 * Unpaused.  The extra unpause
+				 * that follows is harmless.
+				 */
 			}
 		}
 		ahc_unpause(ahc);
@@ -7282,7 +7629,7 @@ ahc_run_tqinfifo(struct ahc_softc *ahc, 
 			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),
@@ -7419,7 +7766,7 @@ ahc_handle_target_cmd(struct ahc_softc *
 		       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);
diff -puN drivers/scsi/aic7xxx/aic7xxx.h~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7xxx.h
--- 25/drivers/scsi/aic7xxx/aic7xxx.h~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7xxx.h	Wed Dec 24 12:15:38 2003
@@ -37,7 +37,7 @@
  * 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#77 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#85 $
  *
  * $FreeBSD$
  */
@@ -243,7 +243,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
@@ -366,7 +366,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 ***************************/
@@ -411,6 +412,7 @@ struct target_data {
 	uint8_t  initiator_tag;		/* Initiator's transaction tag */
 };
 
+#define MAX_CDB_LEN 16
 struct hardware_scb {
 /*0*/	union {
 		/*
@@ -530,7 +532,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
@@ -560,12 +562,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 {
@@ -575,7 +581,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
 	 * the lock is decremented to 0, all queues in the
@@ -958,7 +970,7 @@ struct ahc_softc {
 	/*
 	 * Platform specific device information.
 	 */
-	ahc_dev_softc_t		  dev_softc;
+	aic_dev_softc_t		  dev_softc;
 
 	/*
 	 * Bus specific device information.
@@ -1135,6 +1147,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 {
@@ -1143,17 +1158,17 @@ struct ahc_pci_identity {
 	char			*name;
 	ahc_device_setup_t	*setup;
 };
-extern struct ahc_pci_identity ahc_pci_ident_table [];
+extern struct ahc_pci_identity ahc_pci_ident_table[];
 extern const u_int ahc_num_pci_devs;
 
 /***************************** VL/EISA Declarations ***************************/
 struct aic7770_identity {
 	uint32_t		 full_id;
 	uint32_t		 id_mask;
-	char			*name;
+	const char		*name;
 	ahc_device_setup_t	*setup;
 };
-extern struct aic7770_identity aic7770_ident_table [];
+extern struct aic7770_identity aic7770_ident_table[];
 extern const int ahc_num_aic7770_devs;
 
 #define AHC_EISA_SLOT_OFFSET	0xc00
@@ -1167,7 +1182,7 @@ void			ahc_busy_tcl(struct ahc_softc *ah
 				     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 *);
@@ -1205,7 +1220,7 @@ void			 ahc_set_unit(struct ahc_softc *,
 void			 ahc_set_name(struct ahc_softc *, char *);
 void			 ahc_alloc_scbs(struct ahc_softc *ahc);
 void			 ahc_free(struct ahc_softc *ahc);
-int			 ahc_reset(struct ahc_softc *ahc);
+int			 ahc_reset(struct ahc_softc *ahc, int reinit);
 void			 ahc_shutdown(void *arg);
 
 /*************************** Interrupt Services *******************************/
@@ -1231,7 +1246,7 @@ int			ahc_search_qinfifo(struct ahc_soft
 					   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);
@@ -1248,6 +1263,8 @@ int			ahc_abort_scbs(struct ahc_softc *a
 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);
diff -puN drivers/scsi/aic7xxx/aic7xxx_inline.h~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7xxx_inline.h
--- 25/drivers/scsi/aic7xxx/aic7xxx_inline.h~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7xxx_inline.h	Wed Dec 24 12:15:38 2003
@@ -37,7 +37,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#43 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#47 $
  *
  * $FreeBSD$
  */
@@ -196,7 +196,7 @@ ahc_hscb_busaddr(struct ahc_softc *ahc, 
 static __inline void
 ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op)
 {
-	ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat,
+	aic_dmamap_sync(ahc, ahc->scb_data->hscb_dmat,
 			ahc->scb_data->hscb_dmamap,
 			/*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb),
 			/*len*/sizeof(*scb->hscb), op);
@@ -208,7 +208,7 @@ ahc_sync_sglist(struct ahc_softc *ahc, s
 	if (scb->sg_count == 0)
 		return;
 
-	ahc_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap,
+	aic_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap,
 			/*offset*/(scb->sg_list - scb->sg_map->sg_vaddr)
 				* sizeof(struct ahc_dma_seg),
 			/*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op);
@@ -272,7 +272,7 @@ ahc_update_residual(struct ahc_softc *ah
 {
 	uint32_t sgptr;
 
-	sgptr = ahc_le32toh(scb->hscb->sgptr);
+	sgptr = aic_le32toh(scb->hscb->sgptr);
 	if ((sgptr & SG_RESID_VALID) != 0)
 		ahc_calc_residual(ahc, scb);
 }
@@ -383,13 +383,13 @@ ahc_free_scb(struct ahc_softc *ahc, stru
 	hscb = scb->hscb;
 	/* Clean up for the next user */
 	ahc->scb_data->scbindex[hscb->tag] = NULL;
-	scb->flags = SCB_FREE;
+	scb->flags = SCB_FLAG_NONE;
 	hscb->control = 0;
 
 	SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle);
 
 	/* Notify the OSM that a resource is now available. */
-	ahc_platform_scb_free(ahc, scb);
+	aic_platform_scb_free(ahc, scb);
 }
 
 static __inline struct scb *
@@ -427,7 +427,7 @@ ahc_swap_with_next_hscb(struct ahc_softc
 	memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
 	if ((scb->flags & SCB_CDB32_PTR) != 0) {
 		q_hscb->shared_data.cdb_ptr =
-		    ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag)
+		    aic_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag)
 			      + offsetof(struct hardware_scb, cdb32));
 	}
 	q_hscb->tag = saved_tag;
@@ -458,7 +458,7 @@ ahc_queue_scb(struct ahc_softc *ahc, str
 	 * Setup data "oddness".
 	 */
 	scb->hscb->lun &= LID;
-	if (ahc_get_transfer_length(scb) & 0x1)
+	if (aic_get_transfer_length(scb) & 0x1)
 		scb->hscb->lun |= SCB_XFERLEN_ODD;
 
 	/*
@@ -512,7 +512,7 @@ static __inline int	ahc_intr(struct ahc_
 static __inline void
 ahc_sync_qoutfifo(struct ahc_softc *ahc, int op)
 {
-	ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
+	aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
 			/*offset*/0, /*len*/256, op);
 }
 
@@ -521,7 +521,7 @@ ahc_sync_tqinfifo(struct ahc_softc *ahc,
 {
 #ifdef AHC_TARGET_MODE
 	if ((ahc->flags & AHC_TARGETROLE) != 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, 0),
 				sizeof(struct target_cmd) * AHC_TMODE_CMDS,
@@ -542,7 +542,7 @@ ahc_check_cmdcmpltqueues(struct ahc_soft
 	u_int retval;
 
 	retval = 0;
-	ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
+	aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
 			/*offset*/ahc->qoutfifonext, /*len*/1,
 			BUS_DMASYNC_POSTREAD);
 	if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL)
@@ -550,7 +550,7 @@ ahc_check_cmdcmpltqueues(struct ahc_soft
 #ifdef AHC_TARGET_MODE
 	if ((ahc->flags & AHC_TARGETROLE) != 0
 	 && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 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->tqinfifofnext),
 				/*len*/sizeof(struct target_cmd),
@@ -593,7 +593,7 @@ ahc_intr(struct ahc_softc *ahc)
 	}
 
 	if ((intstat & INT_PEND) == 0) {
-#if AHC_PCI_CONFIG > 0
+#if AIC_PCI_CONFIG > 0
 		if (ahc->unsolicited_ints > 500) {
 			ahc->unsolicited_ints = 0;
 			if ((ahc->chip & AHC_PCI) != 0
diff -puN drivers/scsi/aic7xxx/aic7xxx_osm.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7xxx_osm.c
--- 25/drivers/scsi/aic7xxx/aic7xxx_osm.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7xxx_osm.c	Wed Dec 24 12:15:38 2003
@@ -1,7 +1,7 @@
 /*
  * Adaptec AIC7xxx device driver for Linux.
  *
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#232 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#256 $
  *
  * Copyright (c) 1994 John Aycock
  *   The University of Calgary Department of Computer Science.
@@ -139,7 +139,16 @@
 #endif
 
 #include <linux/mm.h>		/* For fetching system memory size */
-#include <linux/blkdev.h>		/* For block_size() */
+
+/************************* Magic SysReq Support *******************************/
+static struct aic_sysrq_key_op ahc_sysrq_op =
+{
+	aic_sysrq_handler,
+	"aic7xxxstatedump",
+	"Dump aic7xxx controller information to Console"
+};
+
+static int ahc_sysrq_key;
 
 /*
  * Lock protecting manipulation of the ahc softc list.
@@ -293,7 +302,7 @@ static adapter_tag_info_t aic7xxx_tag_in
 #define AIC7XXX_CONFIGED_DV -1
 #endif
 
-static uint8_t aic7xxx_dv_settings[] =
+static int8_t aic7xxx_dv_settings[] =
 {
 	AIC7XXX_CONFIGED_DV,
 	AIC7XXX_CONFIGED_DV,
@@ -391,9 +400,9 @@ static uint32_t aic7xxx_pci_parity = ~0;
  * would result in never finding any devices :)
  */
 #ifndef CONFIG_AIC7XXX_PROBE_EISA_VL
-static uint32_t aic7xxx_probe_eisa_vl;
+uint32_t aic7xxx_probe_eisa_vl;
 #else
-static uint32_t aic7xxx_probe_eisa_vl = ~0;
+uint32_t aic7xxx_probe_eisa_vl = ~0;
 #endif
 
 /*
@@ -482,35 +491,32 @@ MODULE_PARM_DESC(aic7xxx,
 #endif
 
 static void ahc_linux_handle_scsi_status(struct ahc_softc *,
-					 struct ahc_linux_device *,
+					 struct aic_linux_device *,
 					 struct scb *);
 static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
 					 Scsi_Cmnd *cmd);
 static void ahc_linux_filter_inquiry(struct ahc_softc*, struct ahc_devinfo*);
 static void ahc_linux_sem_timeout(u_long arg);
-static void ahc_linux_freeze_simq(struct ahc_softc *ahc);
-static void ahc_linux_release_simq(u_long arg);
 static void ahc_linux_dev_timed_unfreeze(u_long arg);
 static int  ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag);
 static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
 static void ahc_linux_size_nseg(void);
 static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc);
 static void ahc_linux_start_dv(struct ahc_softc *ahc);
-static void ahc_linux_dv_timeout(struct scsi_cmnd *cmd);
 static int  ahc_linux_dv_thread(void *data);
 static void ahc_linux_kill_dv_thread(struct ahc_softc *ahc);
 static void ahc_linux_dv_target(struct ahc_softc *ahc, u_int target);
 static void ahc_linux_dv_transition(struct ahc_softc *ahc,
 				    struct scsi_cmnd *cmd,
 				    struct ahc_devinfo *devinfo,
-				    struct ahc_linux_target *targ);
+				    struct aic_linux_target *targ);
 static void ahc_linux_dv_fill_cmd(struct ahc_softc *ahc,
 				  struct scsi_cmnd *cmd,
 				  struct ahc_devinfo *devinfo);
 static void ahc_linux_dv_inq(struct ahc_softc *ahc,
 			     struct scsi_cmnd *cmd,
 			     struct ahc_devinfo *devinfo,
-			     struct ahc_linux_target *targ,
+			     struct aic_linux_target *targ,
 			     u_int request_length);
 static void ahc_linux_dv_tur(struct ahc_softc *ahc,
 			     struct scsi_cmnd *cmd,
@@ -518,58 +524,48 @@ static void ahc_linux_dv_tur(struct ahc_
 static void ahc_linux_dv_rebd(struct ahc_softc *ahc,
 			      struct scsi_cmnd *cmd,
 			      struct ahc_devinfo *devinfo,
-			      struct ahc_linux_target *targ);
+			      struct aic_linux_target *targ);
 static void ahc_linux_dv_web(struct ahc_softc *ahc,
 			     struct scsi_cmnd *cmd,
 			     struct ahc_devinfo *devinfo,
-			     struct ahc_linux_target *targ);
+			     struct aic_linux_target *targ);
 static void ahc_linux_dv_reb(struct ahc_softc *ahc,
 			     struct scsi_cmnd *cmd,
 			     struct ahc_devinfo *devinfo,
-			     struct ahc_linux_target *targ);
+			     struct aic_linux_target *targ);
 static void ahc_linux_dv_su(struct ahc_softc *ahc,
 			    struct scsi_cmnd *cmd,
 			    struct ahc_devinfo *devinfo,
-			    struct ahc_linux_target *targ);
+			    struct aic_linux_target *targ);
 static int ahc_linux_fallback(struct ahc_softc *ahc,
 			      struct ahc_devinfo *devinfo);
-static void ahc_linux_dv_complete(Scsi_Cmnd *cmd);
-static void ahc_linux_generate_dv_pattern(struct ahc_linux_target *targ);
+static void ahc_linux_generate_dv_pattern(struct aic_linux_target *targ);
 static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
 				     struct ahc_devinfo *devinfo);
 static u_int ahc_linux_user_dv_setting(struct ahc_softc *ahc);
-static void ahc_linux_device_queue_depth(struct ahc_softc *ahc,
-					 struct ahc_linux_device *dev);
-static struct ahc_linux_target*	ahc_linux_alloc_target(struct ahc_softc*,
+static void aic_linux_device_queue_depth(struct ahc_softc *ahc,
+					 struct aic_linux_device *dev);
+static struct aic_linux_target*	ahc_linux_alloc_target(struct ahc_softc*,
 						       u_int, u_int);
 static void			ahc_linux_free_target(struct ahc_softc*,
-						      struct ahc_linux_target*);
-static struct ahc_linux_device*	ahc_linux_alloc_device(struct ahc_softc*,
-						       struct ahc_linux_target*,
+						      struct aic_linux_target*);
+static struct aic_linux_device*	ahc_linux_alloc_device(struct ahc_softc*,
+						       struct aic_linux_target*,
 						       u_int);
 static void			ahc_linux_free_device(struct ahc_softc*,
-						      struct ahc_linux_device*);
-static void ahc_linux_run_device_queue(struct ahc_softc*,
-				       struct ahc_linux_device*);
+						      struct aic_linux_device*);
 static void ahc_linux_setup_tag_info_global(char *p);
 static aic_option_callback_t ahc_linux_setup_tag_info;
 static aic_option_callback_t ahc_linux_setup_dv;
 static int  aic7xxx_setup(char *s);
 static int  ahc_linux_next_unit(void);
-static void ahc_runq_tasklet(unsigned long data);
-static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc);
+static struct aic_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc);
 
 /********************************* Inlines ************************************/
-static __inline void ahc_schedule_runq(struct ahc_softc *ahc);
-static __inline struct ahc_linux_device*
+static __inline struct aic_linux_device*
 		     ahc_linux_get_device(struct ahc_softc *ahc, u_int channel,
 					  u_int target, u_int lun, int alloc);
 static __inline void ahc_schedule_completeq(struct ahc_softc *ahc);
-static __inline void ahc_linux_check_device_queue(struct ahc_softc *ahc,
-						  struct ahc_linux_device *dev);
-static __inline struct ahc_linux_device *
-		     ahc_linux_next_device_to_run(struct ahc_softc *ahc);
-static __inline void ahc_linux_run_device_queues(struct ahc_softc *ahc);
 static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
 
 static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
@@ -579,35 +575,19 @@ static __inline int ahc_linux_map_seg(st
 static __inline void
 ahc_schedule_completeq(struct ahc_softc *ahc)
 {
-	if ((ahc->platform_data->flags & AHC_RUN_CMPLT_Q_TIMER) == 0) {
-		ahc->platform_data->flags |= AHC_RUN_CMPLT_Q_TIMER;
+	if ((ahc->platform_data->flags & AIC_RUN_CMPLT_Q_TIMER) == 0) {
+		ahc->platform_data->flags |= AIC_RUN_CMPLT_Q_TIMER;
 		ahc->platform_data->completeq_timer.expires = jiffies;
 		add_timer(&ahc->platform_data->completeq_timer);
 	}
 }
 
-/*
- * Must be called with our lock held.
- */
-static __inline void
-ahc_schedule_runq(struct ahc_softc *ahc)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	tasklet_schedule(&ahc->platform_data->runq_tasklet);
-#else
-	/*
-	 * Tasklets are not available, so run inline.
-	 */
-	ahc_runq_tasklet((unsigned long)ahc);
-#endif
-}
-
-static __inline struct ahc_linux_device*
+static __inline struct aic_linux_device*
 ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target,
 		     u_int lun, int alloc)
 {
-	struct ahc_linux_target *targ;
-	struct ahc_linux_device *dev;
+	struct aic_linux_target *targ;
+	struct aic_linux_device *dev;
 	u_int target_offset;
 
 	target_offset = target;
@@ -629,10 +609,10 @@ ahc_linux_get_device(struct ahc_softc *a
 }
 
 #define AHC_LINUX_MAX_RETURNED_ERRORS 4
-static struct ahc_cmd *
+static struct aic_cmd *
 ahc_linux_run_complete_queue(struct ahc_softc *ahc)
 {
-	struct	ahc_cmd *acmd;
+	struct	aic_cmd *acmd;
 	u_long	done_flags;
 	int	with_errors;
 
@@ -657,7 +637,7 @@ ahc_linux_run_complete_queue(struct ahc_
 			     acmd, acmd_links.tqe);
 		cmd = &acmd_scsi_cmd(acmd);
 		cmd->host_scribble = NULL;
-		if (ahc_cmd_get_transaction_status(cmd) != DID_OK
+		if (aic_cmd_get_transaction_status(cmd) != DID_OK
 		 || (cmd->result & 0xFF) != SCSI_STATUS_OK)
 			with_errors++;
 
@@ -666,47 +646,6 @@ ahc_linux_run_complete_queue(struct ahc_
 	ahc_done_unlock(ahc, &done_flags);
 	return (acmd);
 }
-
-static __inline void
-ahc_linux_check_device_queue(struct ahc_softc *ahc,
-			     struct ahc_linux_device *dev)
-{
-	if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) != 0
-	 && dev->active == 0) {
-		dev->flags &= ~AHC_DEV_FREEZE_TIL_EMPTY;
-		dev->qfrozen--;
-	}
-
-	if (TAILQ_FIRST(&dev->busyq) == NULL
-	 || dev->openings == 0 || dev->qfrozen != 0)
-		return;
-
-	ahc_linux_run_device_queue(ahc, dev);
-}
-
-static __inline struct ahc_linux_device *
-ahc_linux_next_device_to_run(struct ahc_softc *ahc)
-{
-	
-	if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0
-	 || (ahc->platform_data->qfrozen != 0
-	  && AHC_DV_SIMQ_FROZEN(ahc) == 0))
-		return (NULL);
-	return (TAILQ_FIRST(&ahc->platform_data->device_runq));
-}
-
-static __inline void
-ahc_linux_run_device_queues(struct ahc_softc *ahc)
-{
-	struct ahc_linux_device *dev;
-
-	while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) {
-		TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links);
-		dev->flags &= ~AHC_DEV_ON_RUN_LIST;
-		ahc_linux_check_device_queue(ahc, dev);
-	}
-}
-
 static __inline void
 ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb)
 {
@@ -718,10 +657,10 @@ ahc_linux_unmap_scb(struct ahc_softc *ah
 		struct scatterlist *sg;
 
 		sg = (struct scatterlist *)cmd->request_buffer;
-		pci_unmap_sg(ahc->dev_softc, sg, cmd->use_sg,
+		aic_unmap_sg(ahc, sg, cmd->use_sg,
 			     scsi_to_pci_dma_dir(cmd->sc_data_direction));
 	} else if (cmd->request_bufflen != 0) {
-		pci_unmap_single(ahc->dev_softc,
+		aic_unmap_single(ahc,
 				 scb->platform_data->buf_busaddr,
 				 cmd->request_bufflen,
 				 scsi_to_pci_dma_dir(cmd->sc_data_direction));
@@ -739,20 +678,19 @@ ahc_linux_map_seg(struct ahc_softc *ahc,
 		      "Increase AHC_NSEG\n");
 
 	consumed = 1;
-	sg->addr = ahc_htole32(addr & 0xFFFFFFFF);
+	sg->addr = aic_htole32(addr & 0xFFFFFFFF);
 	scb->platform_data->xfer_len += len;
 
 	if (sizeof(bus_addr_t) > 4
 	 && (ahc->flags & AHC_39BIT_ADDRESSING) != 0)
 		len |= (addr >> 8) & AHC_SG_HIGH_ADDR_MASK;
 
-	sg->len = ahc_htole32(len);
+	sg->len = aic_htole32(len);
 	return (consumed);
 }
 
 /************************  Host template entry points *************************/
 static int	   ahc_linux_detect(Scsi_Host_Template *);
-static int	   ahc_linux_release(struct Scsi_Host *);
 static int	   ahc_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
 static const char *ahc_linux_info(struct Scsi_Host *);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
@@ -765,6 +703,7 @@ static int	   ahc_linux_biosparam(struct
 				       sector_t, int[]);
 #endif
 #else
+static int	   ahc_linux_release(struct Scsi_Host *);
 static void	   ahc_linux_select_queue_depth(struct Scsi_Host *host,
 						Scsi_Device *scsi_devs);
 #if defined(__i386__)
@@ -836,6 +775,164 @@ ahc_linux_size_nseg(void)
 #endif
 }
 
+/************************** Error Recovery ************************************/
+static int ahc_linux_recovery_thread(void *arg);
+
+static int
+ahc_linux_recovery_thread(void *arg)
+{
+	struct ahc_softc *ahc;
+	u_long s;
+
+	ahc = (struct ahc_softc *)arg;
+
+	/*
+	 * Complete thread creation.
+	 */
+	lock_kernel();
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60)
+	/*
+	 * Don't care about any signals.
+	 */
+	siginitsetinv(&current->blocked, 0);
+
+	daemonize();
+	sprintf(current->comm, "ahc_recovery_%d", ahc->unit);
+#else
+	daemonize("ahc_recovery_%d", ahc->unit);
+#endif
+	unlock_kernel();
+
+	while (1) {
+
+		/*
+		 * Use down_interruptible() rather than down() to
+		 * avoid inclusion in the load average.
+		 */
+		down_interruptible(&ahc->platform_data->recovery_sem);
+
+		ahc_lock(ahc, &s);
+		if ((ahc->flags & AHC_SHUTDOWN_RECOVERY) != 0) {
+			ahc_unlock(ahc, &s);
+			break;
+		}
+
+		/*
+		 * Don't bother the recovery handler if the
+		 * list has been cleared by a previous run
+		 * of the handler.  This can happen when
+		 * several SCBs timeout before our handler
+		 * can run causing our semaphore to be up'ed
+		 * repeatedly.  The extra calls need to be
+		 * avoided so that the recovery handler doesn't
+		 * confuse this case with timeouts occuring
+		 * due to interrupts failing to function.
+		 */
+		if (LIST_EMPTY(&ahc->timedout_scbs) != 0) {
+			ahc_unlock(ahc, &s);
+			continue;
+		}
+		ahc_unlock(ahc, &s);
+		ahc_recover_commands(ahc);
+
+		/*
+		 * Process any pent up completions.
+		 */
+		ahc_lock(ahc, &s);
+		aic_schedule_runq(ahc);
+		ahc_linux_run_complete_queue(ahc);
+		ahc_unlock(ahc, &s);
+	}
+	up(&ahc->platform_data->recovery_ending_sem);
+	return(0);
+}
+
+int
+ahc_spawn_recovery_thread(struct ahc_softc *ahc)
+{
+	ahc->platform_data->recovery_pid =
+	    kernel_thread(ahc_linux_recovery_thread, ahc, 0);
+
+	if (ahc->platform_data->recovery_pid < 0)
+		return (-ahc->platform_data->recovery_pid);
+
+	return (0);
+}
+
+void
+ahc_terminate_recovery_thread(struct ahc_softc *ahc)
+{
+	u_long s;
+
+	ahc_lock(ahc, &s);
+	if (ahc->platform_data->recovery_pid != 0) {
+		ahc->flags |= AHC_SHUTDOWN_RECOVERY;
+		ahc_unlock(ahc, &s);
+		up(&ahc->platform_data->recovery_sem);
+
+		/*
+		 * Use the recovery_ending_sem as an indicator that
+		 * the dv thread is exiting.  Note that the dv
+		 * thread must still return after performing
+		 * the up on our semaphore before it has
+		 * completely exited this module.  Unfortunately,
+		 * there seems to be no easy way to wait for the
+		 * exit of a thread for which you are not the
+		 * parent (dv threads are parented by init).
+		 * Cross your fingers...
+		 */
+		down(&ahc->platform_data->recovery_ending_sem);
+
+		/*
+		 * Mark the recovery thread as already dead.  This
+		 * avoids attempting to kill it a second time.
+		 * This is necessary because we must kill the
+		 * our threads before calling ahc_free() in the
+		 * module shutdown case to avoid bogus locking
+		 * in the SCSI mid-layer, but when ahc_free() is
+		 * called without killing the DV thread in the
+		 * instance detach case, so ahc_platform_free()
+		 * calls us again to verify that the DV thread
+		 * is dead.
+		 */
+		ahc->platform_data->recovery_pid = 0;
+	} else {
+		ahc_unlock(ahc, &s);
+	}
+}
+
+void
+ahc_set_recoveryscb(struct ahc_softc *ahc, 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 commands are queued to us while we
+		 * try to fix this problem.
+		 */
+		if ((scb->platform_data->flags & AIC_RELEASE_SIMQ) == 0) {
+			aic_freeze_simq(ahc);
+			scb->platform_data->flags |= AIC_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, &ahc->pending_scbs, pending_links) {
+
+			scsi_delete_timer(list_scb->io_ctx);
+			list_scb->platform_data->flags &= ~AIC_TIMEOUT_ACTIVE;
+		}
+	}
+}
+
+/************************ Linux Entry Points **********************************/
 /*
  * Try to detect an Adaptec 7XXX controller.
  */
@@ -858,7 +955,7 @@ ahc_linux_detect(Scsi_Host_Template *tem
 	 * that some of our hacks^H^H^H^H^Hassumptions aren't
 	 * violated.
 	 */
-	if (offsetof(struct ahc_cmd_internal, end)
+	if (offsetof(struct aic_cmd_internal, end)
 	  > offsetof(struct scsi_cmnd, host_scribble)) {
 		printf("ahc_linux_detect: SCSI data structures changed.\n");
 		printf("ahc_linux_detect: Unable to attach\n");
@@ -895,8 +992,9 @@ ahc_linux_detect(Scsi_Host_Template *tem
 	ahc_linux_pci_init();
 #endif
 
-	if (aic7xxx_probe_eisa_vl != 0)
-		aic7770_linux_probe(template);
+#ifdef CONFIG_EISA
+	ahc_linux_eisa_init();
+#endif
 
 	/*
 	 * Register with the SCSI layer all
@@ -915,6 +1013,7 @@ ahc_linux_detect(Scsi_Host_Template *tem
 	return (found);
 }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 /*
  * Free the passed in Scsi_Host memory structures prior to unloading the
  * module.
@@ -925,7 +1024,6 @@ ahc_linux_release(struct Scsi_Host * hos
 	struct ahc_softc *ahc;
 	u_long l;
 
-	ahc_list_lock(&l);
 	if (host != NULL) {
 
 		/*
@@ -933,19 +1031,23 @@ ahc_linux_release(struct Scsi_Host * hos
 		 * the free directly, but check our
 		 * list for extra sanity.
 		 */
+		ahc_list_lock(&l);
 		ahc = ahc_find_softc(*(struct ahc_softc **)host->hostdata);
 		if (ahc != NULL) {
 			u_long s;
 
+			TAILQ_REMOVE(&ahc_tailq, ahc, links);
+			ahc_list_unlock(&l);
 			ahc_lock(ahc, &s);
 			ahc_intr_enable(ahc, FALSE);
 			ahc_unlock(ahc, &s);
 			ahc_free(ahc);
-		}
+		} else
+			ahc_list_unlock(&l);
 	}
-	ahc_list_unlock(&l);
 	return (0);
 }
+#endif
 
 /*
  * Return a string describing the driver.
@@ -982,7 +1084,7 @@ static int
 ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
 {
 	struct	 ahc_softc *ahc;
-	struct	 ahc_linux_device *dev;
+	struct	 aic_linux_device *dev;
 	u_long	 flags;
 
 	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
@@ -1001,9 +1103,9 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*
 	 * perform DV.
 	 */
 	if (ahc->platform_data->qfrozen != 0
-	 && AHC_DV_CMD(cmd) == 0) {
+	 && AIC_DV_CMD(cmd) == 0) {
 
-		ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
+		aic_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
 		ahc_linux_queue_cmd_complete(ahc, cmd);
 		ahc_schedule_completeq(ahc);
 		ahc_midlayer_entrypoint_unlock(ahc, &flags);
@@ -1012,7 +1114,8 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*
 	dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
 				   cmd->device->lun, /*alloc*/TRUE);
 	if (dev == NULL) {
-		ahc_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
+
+		aic_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
 		ahc_linux_queue_cmd_complete(ahc, cmd);
 		ahc_schedule_completeq(ahc);
 		ahc_midlayer_entrypoint_unlock(ahc, &flags);
@@ -1020,12 +1123,30 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*
 		       ahc_name(ahc));
 		return (0);
 	}
+
+	if (cmd->cmd_len > MAX_CDB_LEN) {
+
+		aic_cmd_set_transaction_status(cmd, CAM_REQ_INVALID);
+		ahc_linux_queue_cmd_complete(ahc, cmd);
+		ahc_schedule_completeq(ahc);
+		ahc_midlayer_entrypoint_unlock(ahc, &flags);
+		printf("%s: aic7xxx_linux_queue -"
+		       "CDB length of %d exceeds max!\n",
+		       ahc_name(ahc), cmd->cmd_len);
+		return (0);
+	}
+
+	/*
+	 * We perform our own timeout handling.
+	 */
+	scsi_delete_timer(cmd);
+
 	cmd->result = CAM_REQ_INPROG << 16;
-	TAILQ_INSERT_TAIL(&dev->busyq, (struct ahc_cmd *)cmd, acmd_links.tqe);
-	if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) {
+	TAILQ_INSERT_TAIL(&dev->busyq, (struct aic_cmd *)cmd, acmd_links.tqe);
+	if ((dev->flags & AIC_DEV_ON_RUN_LIST) == 0) {
 		TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links);
-		dev->flags |= AHC_DEV_ON_RUN_LIST;
-		ahc_linux_run_device_queues(ahc);
+		dev->flags |= AIC_DEV_ON_RUN_LIST;
+		aic_linux_run_device_queues(ahc);
 	}
 	ahc_midlayer_entrypoint_unlock(ahc, &flags);
 	return (0);
@@ -1047,7 +1168,7 @@ static int
 ahc_linux_slave_configure(Scsi_Device *device)
 {
 	struct	ahc_softc *ahc;
-	struct	ahc_linux_device *dev;
+	struct	aic_linux_device *dev;
 	u_long	flags;
 
 	ahc = *((struct ahc_softc **)device->host->hostdata);
@@ -1063,9 +1184,9 @@ ahc_linux_slave_configure(Scsi_Device *d
 				   device->id, device->lun,
 				   /*alloc*/TRUE);
 	if (dev != NULL) {
-		dev->flags &= ~AHC_DEV_UNCONFIGURED;
+		dev->flags &= ~AIC_DEV_UNCONFIGURED;
 		dev->scsi_device = device;
-		ahc_linux_device_queue_depth(ahc, dev);
+		aic_linux_device_queue_depth(ahc, dev);
 	}
 	ahc_midlayer_entrypoint_unlock(ahc, &flags);
 	return (0);
@@ -1075,7 +1196,7 @@ static void
 ahc_linux_slave_destroy(Scsi_Device *device)
 {
 	struct	ahc_softc *ahc;
-	struct	ahc_linux_device *dev;
+	struct	aic_linux_device *dev;
 	u_long	flags;
 
 	ahc = *((struct ahc_softc **)device->host->hostdata);
@@ -1093,11 +1214,10 @@ ahc_linux_slave_destroy(Scsi_Device *dev
 	 * the refcounting process.
 	 */
 	if (dev != NULL
-	 && (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) {
-		dev->flags |= AHC_DEV_UNCONFIGURED;
+	 && (dev->flags & AIC_DEV_SLAVE_CONFIGURED) != 0) {
+		dev->flags |= AIC_DEV_UNCONFIGURED;
 		if (TAILQ_EMPTY(&dev->busyq)
-		 && dev->active == 0
-	 	 && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
+		 && dev->active == 0)
 			ahc_linux_free_device(ahc, dev);
 	}
 	ahc_midlayer_entrypoint_unlock(ahc, &flags);
@@ -1136,7 +1256,7 @@ ahc_linux_select_queue_depth(struct Scsi
 			continue;
 
 		if (device->host == host) {
-			struct	 ahc_linux_device *dev;
+			struct	 aic_linux_device *dev;
 
 			/*
 			 * Since Linux has attached to the device, configure
@@ -1147,13 +1267,13 @@ ahc_linux_select_queue_depth(struct Scsi
 						   device->id, device->lun,
 						   /*alloc*/TRUE);
 			if (dev != NULL) {
-				dev->flags &= ~AHC_DEV_UNCONFIGURED;
+				dev->flags &= ~AIC_DEV_UNCONFIGURED;
 				dev->scsi_device = device;
-				ahc_linux_device_queue_depth(ahc, dev);
+				aic_linux_device_queue_depth(ahc, dev);
 				device->queue_depth = dev->openings
 						    + dev->active;
-				if ((dev->flags & (AHC_DEV_Q_BASIC
-						| AHC_DEV_Q_TAGGED)) == 0) {
+				if ((dev->flags & (AIC_DEV_Q_BASIC
+						| AIC_DEV_Q_TAGGED)) == 0) {
 					/*
 					 * We allow the OS to queue 2 untagged
 					 * transactions to us at any time even
@@ -1291,63 +1411,8 @@ ahc_linux_bus_reset(Scsi_Cmnd *cmd)
 	return SUCCESS;
 }
 
-Scsi_Host_Template aic7xxx_driver_template = {
-	.module			= THIS_MODULE,
-	.name			= "aic7xxx",
-	.proc_info		= ahc_linux_proc_info,
-	.info			= ahc_linux_info,
-	.queuecommand		= ahc_linux_queue,
-	.eh_abort_handler	= ahc_linux_abort,
-	.eh_device_reset_handler = ahc_linux_dev_reset,
-	.eh_bus_reset_handler	= ahc_linux_bus_reset,
-#if defined(__i386__)
-	.bios_param		= ahc_linux_biosparam,
-#endif
-	.can_queue		= AHC_MAX_QUEUE,
-	.this_id		= -1,
-	.cmd_per_lun		= 2,
-	.use_clustering		= ENABLE_CLUSTERING,
-	.slave_alloc		= ahc_linux_slave_alloc,
-	.slave_configure	= ahc_linux_slave_configure,
-	.slave_destroy		= ahc_linux_slave_destroy,
-};
-
-/**************************** Tasklet Handler *********************************/
-
-/*
- * In 2.4.X and above, this routine is called from a tasklet,
- * so we must re-acquire our lock prior to executing this code.
- * In all prior kernels, ahc_schedule_runq() calls this routine
- * directly and ahc_schedule_runq() is called with our lock held.
- */
-static void
-ahc_runq_tasklet(unsigned long data)
-{
-	struct ahc_softc* ahc;
-	struct ahc_linux_device *dev;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	u_long flags;
-#endif
-
-	ahc = (struct ahc_softc *)data;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	ahc_lock(ahc, &flags);
-#endif
-	while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) {
-	
-		TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links);
-		dev->flags &= ~AHC_DEV_ON_RUN_LIST;
-		ahc_linux_check_device_queue(ahc, dev);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-		/* Yeild to our interrupt handler */
-		ahc_unlock(ahc, &flags);
-		ahc_lock(ahc, &flags);
-#endif
-	}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	ahc_unlock(ahc, &flags);
-#endif
-}
+Scsi_Host_Template aic7xxx_driver_template =
+	AIC_TEMPLATE_INITIALIZER("aic7xxx", /* max_sectors*/8192);
 
 /******************************** Macros **************************************/
 #define BUILD_SCSIID(ahc, cmd)						    \
@@ -1355,132 +1420,6 @@ ahc_runq_tasklet(unsigned long data)
 	| (((cmd)->device->channel == 0) ? (ahc)->our_id : (ahc)->our_id_b) \
 	| (((cmd)->device->channel == 0) ? 0 : TWIN_CHNLB))
 
-/******************************** Bus DMA *************************************/
-int
-ahc_dma_tag_create(struct ahc_softc *ahc, bus_dma_tag_t parent,
-		   bus_size_t alignment, bus_size_t boundary,
-		   bus_addr_t lowaddr, bus_addr_t highaddr,
-		   bus_dma_filter_t *filter, void *filterarg,
-		   bus_size_t maxsize, int nsegments,
-		   bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag)
-{
-	bus_dma_tag_t dmat;
-
-	dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT);
-	if (dmat == NULL)
-		return (ENOMEM);
-
-	/*
-	 * Linux is very simplistic about DMA memory.  For now don't
-	 * maintain all specification information.  Once Linux supplies
-	 * better facilities for doing these operations, or the
-	 * needs of this particular driver change, we might need to do
-	 * more here.
-	 */
-	dmat->alignment = alignment;
-	dmat->boundary = boundary;
-	dmat->maxsize = maxsize;
-	*ret_tag = dmat;
-	return (0);
-}
-
-void
-ahc_dma_tag_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat)
-{
-	free(dmat, M_DEVBUF);
-}
-
-int
-ahc_dmamem_alloc(struct ahc_softc *ahc, bus_dma_tag_t dmat, void** vaddr,
-		 int flags, bus_dmamap_t *mapp)
-{
-	bus_dmamap_t map;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT);
-	if (map == NULL)
-		return (ENOMEM);
-	/*
-	 * Although we can dma data above 4GB, our
-	 * "consistent" memory is below 4GB for
-	 * space efficiency reasons (only need a 4byte
-	 * address).  For this reason, we have to reset
-	 * our dma mask when doing allocations.
-	 */
-	if (ahc->dev_softc != NULL)
-		ahc_pci_set_dma_mask(ahc->dev_softc, 0xFFFFFFFF);
-	*vaddr = pci_alloc_consistent(ahc->dev_softc,
-				      dmat->maxsize, &map->bus_addr);
-	if (ahc->dev_softc != NULL)
-		ahc_pci_set_dma_mask(ahc->dev_softc,
-				     ahc->platform_data->hw_dma_mask);
-#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */
-	/*
-	 * At least in 2.2.14, malloc is a slab allocator so all
-	 * allocations are aligned.  We assume for these kernel versions
-	 * that all allocations will be bellow 4Gig, physically contiguous,
-	 * and accessible via DMA by the controller.
-	 */
-	map = NULL; /* No additional information to store */
-	*vaddr = malloc(dmat->maxsize, M_DEVBUF, M_NOWAIT);
-#endif
-	if (*vaddr == NULL)
-		return (ENOMEM);
-	*mapp = map;
-	return(0);
-}
-
-void
-ahc_dmamem_free(struct ahc_softc *ahc, bus_dma_tag_t dmat,
-		void* vaddr, bus_dmamap_t map)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	pci_free_consistent(ahc->dev_softc, dmat->maxsize,
-			    vaddr, map->bus_addr);
-#else
-	free(vaddr, M_DEVBUF);
-#endif
-}
-
-int
-ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map,
-		void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb,
-		void *cb_arg, int flags)
-{
-	/*
-	 * Assume for now that this will only be used during
-	 * initialization and not for per-transaction buffer mapping.
-	 */
-	bus_dma_segment_t stack_sg;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	stack_sg.ds_addr = map->bus_addr;
-#else
-#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a))
-	stack_sg.ds_addr = VIRT_TO_BUS(buf);
-#endif
-	stack_sg.ds_len = dmat->maxsize;
-	cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);
-	return (0);
-}
-
-void
-ahc_dmamap_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map)
-{
-	/*
-	 * The map may is NULL in our < 2.3.X implementation.
-	 */
-	if (map != NULL)
-		free(map, M_DEVBUF);
-}
-
-int
-ahc_dmamap_unload(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map)
-{
-	/* Nothing to do */
-	return (0);
-}
-
 /********************* Platform Dependent Functions ***************************/
 /*
  * Compare "left hand" softc with "right hand" softc, returning:
@@ -1525,24 +1464,25 @@ ahc_softc_comp(struct ahc_softc *lahc, s
 
 	/* Still equal.  Sort by BIOS address, ioport, or bus/slot/func. */
 	switch (rvalue) {
+#ifdef CONFIG_PCI
 	case AHC_PCI:
 	{
 		char primary_channel;
 
 		if (aic7xxx_reverse_scan != 0)
-			value = ahc_get_pci_bus(lahc->dev_softc)
-			      - ahc_get_pci_bus(rahc->dev_softc);
+			value = aic_get_pci_bus(lahc->dev_softc)
+			      - aic_get_pci_bus(rahc->dev_softc);
 		else
-			value = ahc_get_pci_bus(rahc->dev_softc)
-			      - ahc_get_pci_bus(lahc->dev_softc);
+			value = aic_get_pci_bus(rahc->dev_softc)
+			      - aic_get_pci_bus(lahc->dev_softc);
 		if (value != 0)
 			break;
 		if (aic7xxx_reverse_scan != 0)
-			value = ahc_get_pci_slot(lahc->dev_softc)
-			      - ahc_get_pci_slot(rahc->dev_softc);
+			value = aic_get_pci_slot(lahc->dev_softc)
+			      - aic_get_pci_slot(rahc->dev_softc);
 		else
-			value = ahc_get_pci_slot(rahc->dev_softc)
-			      - ahc_get_pci_slot(lahc->dev_softc);
+			value = aic_get_pci_slot(rahc->dev_softc)
+			      - aic_get_pci_slot(lahc->dev_softc);
 		if (value != 0)
 			break;
 		/*
@@ -1557,6 +1497,8 @@ ahc_softc_comp(struct ahc_softc *lahc, s
 			value = 1;
 		break;
 	}
+#endif
+#ifdef CONFIG_EISA
 	case AHC_EISA:
 		if ((rahc->flags & AHC_BIOS_ENABLED) != 0) {
 			value = rahc->platform_data->bios_address
@@ -1566,6 +1508,7 @@ ahc_softc_comp(struct ahc_softc *lahc, s
 			      - lahc->bsh.ioport; 
 		}
 		break;
+#endif
 	default:
 		panic("ahc_softc_sort: invalid bus type");
 	}
@@ -1699,9 +1642,16 @@ ahc_linux_register_host(struct ahc_softc
 	char	*new_name;
 	u_long	 s;
 	u_int	 targ_offset;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	int	 error;
+#endif
 
 	template->name = ahc->description;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 	host = scsi_host_alloc(template, sizeof(struct ahc_softc *));
+#else
+	host = scsi_register(template, sizeof(struct ahc_softc *));
+#endif
 	if (host == NULL)
 		return (ENOMEM);
 
@@ -1710,8 +1660,12 @@ ahc_linux_register_host(struct ahc_softc
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 	scsi_assign_lock(host, &ahc->platform_data->spin_lock);
 #elif AHC_SCSI_HAS_HOST_LOCK != 0
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,21)
+	host->host_lock = &ahc->platform_data->spin_lock;
+#else
 	host->lock = &ahc->platform_data->spin_lock;
 #endif
+#endif
 	ahc->platform_data->host = host;
 	host->can_queue = AHC_MAX_QUEUE;
 	host->cmd_per_lun = 2;
@@ -1736,13 +1690,20 @@ ahc_linux_register_host(struct ahc_softc
 #endif
 	ahc_linux_initialize_scsi_bus(ahc);
 	ahc_unlock(ahc, &s);
+	ahc_sysrq_key = aic_install_sysrq(&ahc_sysrq_op);
+	ahc_spawn_recovery_thread(ahc);
+	if (ahc->platform_data->recovery_pid < 0) {
+		printf("%s: Failed to create recovery thread, error= %d\n",
+		       ahc_name(ahc), ahc->platform_data->recovery_pid);
+		return (-ahc->platform_data->recovery_pid);
+	}
 	ahc->platform_data->dv_pid = kernel_thread(ahc_linux_dv_thread, ahc, 0);
-	ahc_lock(ahc, &s);
 	if (ahc->platform_data->dv_pid < 0) {
 		printf("%s: Failed to create DV thread, error= %d\n",
 		       ahc_name(ahc), ahc->platform_data->dv_pid);
 		return (-ahc->platform_data->dv_pid);
 	}
+	ahc_lock(ahc, &s);
 	/*
 	 * Initially allocate *all* of our linux target objects
 	 * so that the DV thread will scan them all in parallel
@@ -1787,7 +1748,9 @@ ahc_linux_register_host(struct ahc_softc
 	ahc_unlock(ahc, &s);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-	scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* XXX handle failure */
+	error = scsi_add_host(host, ahc->dev_softc);
+	if (error != 0)
+		return (-error);
 	scsi_scan_host(host);
 #endif
 	return (0);
@@ -1885,17 +1848,6 @@ ahc_linux_initialize_scsi_bus(struct ahc
 		ahc_update_neg_request(ahc, &devinfo, tstate,
 				       tinfo, AHC_NEG_ALWAYS);
 	}
-	/* Give the bus some time to recover */
-	if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) {
-		ahc_linux_freeze_simq(ahc);
-		init_timer(&ahc->platform_data->reset_timer);
-		ahc->platform_data->reset_timer.data = (u_long)ahc;
-		ahc->platform_data->reset_timer.expires =
-		    jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000;
-		ahc->platform_data->reset_timer.function =
-		    ahc_linux_release_simq;
-		add_timer(&ahc->platform_data->reset_timer);
-	}
 }
 
 int
@@ -1909,27 +1861,32 @@ ahc_platform_alloc(struct ahc_softc *ahc
 	memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data));
 	TAILQ_INIT(&ahc->platform_data->completeq);
 	TAILQ_INIT(&ahc->platform_data->device_runq);
-	ahc->platform_data->irq = AHC_LINUX_NOIRQ;
+	ahc->platform_data->irq = AIC_LINUX_NOIRQ;
 	ahc->platform_data->hw_dma_mask = 0xFFFFFFFF;
 	ahc_lockinit(ahc);
 	ahc_done_lockinit(ahc);
+	init_timer(&ahc->platform_data->bus_settle_timer);
+	ahc->platform_data->bus_settle_timer.data = (u_long)ahc;
+	ahc->platform_data->bus_settle_timer.function =
+	    (aic_linux_callback_t *)aic_bus_settle_complete;
 	init_timer(&ahc->platform_data->completeq_timer);
 	ahc->platform_data->completeq_timer.data = (u_long)ahc;
 	ahc->platform_data->completeq_timer.function =
-	    (ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue;
+	    (aic_linux_callback_t *)ahc_linux_thread_run_complete_queue;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
 	init_MUTEX_LOCKED(&ahc->platform_data->eh_sem);
 	init_MUTEX_LOCKED(&ahc->platform_data->dv_sem);
 	init_MUTEX_LOCKED(&ahc->platform_data->dv_cmd_sem);
+	init_MUTEX_LOCKED(&ahc->platform_data->recovery_sem);
+	init_MUTEX_LOCKED(&ahc->platform_data->recovery_ending_sem);
 #else
 	ahc->platform_data->eh_sem = MUTEX_LOCKED;
 	ahc->platform_data->dv_sem = MUTEX_LOCKED;
 	ahc->platform_data->dv_cmd_sem = MUTEX_LOCKED;
+	ahc->platform_data->recovery_sem = MUTEX_LOCKED;
+	ahc->platform_data->recovery_ending_sem = MUTEX_LOCKED;
 #endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet,
-		     (unsigned long)ahc);
-#endif
+	aic_setup_tasklets(ahc);
 	ahc->seltime = (aic7xxx_seltime & 0x3) << 4;
 	ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4;
 	if (aic7xxx_pci_parity == 0)
@@ -1941,21 +1898,22 @@ ahc_platform_alloc(struct ahc_softc *ahc
 void
 ahc_platform_free(struct ahc_softc *ahc)
 {
-	struct ahc_linux_target *targ;
-	struct ahc_linux_device *dev;
+	struct aic_linux_target *targ;
+	struct aic_linux_device *dev;
 	int i, j;
 
+	aic_remove_sysrq(ahc_sysrq_key, &ahc_sysrq_op);
 	if (ahc->platform_data != NULL) {
 		del_timer_sync(&ahc->platform_data->completeq_timer);
 		ahc_linux_kill_dv_thread(ahc);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-		tasklet_kill(&ahc->platform_data->runq_tasklet);
-#endif
+		aic_teardown_tasklets(ahc);
 		if (ahc->platform_data->host != NULL) {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 			scsi_remove_host(ahc->platform_data->host);
-#endif
 			scsi_host_put(ahc->platform_data->host);
+#else
+			scsi_unregister(ahc->platform_data->host);
+#endif
 		}
 
 		/* destroy all of the device and target objects */
@@ -1969,6 +1927,7 @@ ahc_platform_free(struct ahc_softc *ahc)
 					if (targ->devices[j] == NULL)
 						continue;
 					dev = targ->devices[j];
+					del_timer_sync(&dev->timer);
 					ahc_linux_free_device(ahc, dev);
 				}
 				/*
@@ -1979,7 +1938,7 @@ ahc_platform_free(struct ahc_softc *ahc)
  			}
  		}
 
-		if (ahc->platform_data->irq != AHC_LINUX_NOIRQ)
+		if (ahc->platform_data->irq != AIC_LINUX_NOIRQ)
 			free_irq(ahc->platform_data->irq, ahc);
 		if (ahc->tag == BUS_SPACE_PIO
 		 && ahc->bsh.ioport != 0)
@@ -2024,7 +1983,7 @@ void
 ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
 		      ahc_queue_alg alg)
 {
-	struct ahc_linux_device *dev;
+	struct aic_linux_device *dev;
 	int was_queuing;
 	int now_queuing;
 
@@ -2033,27 +1992,27 @@ ahc_platform_set_tags(struct ahc_softc *
 				   devinfo->lun, /*alloc*/FALSE);
 	if (dev == NULL)
 		return;
-	was_queuing = dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED);
+	was_queuing = dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED);
 	switch (alg) {
 	default:
 	case AHC_QUEUE_NONE:
 		now_queuing = 0;
 		break; 
 	case AHC_QUEUE_BASIC:
-		now_queuing = AHC_DEV_Q_BASIC;
+		now_queuing = AIC_DEV_Q_BASIC;
 		break;
 	case AHC_QUEUE_TAGGED:
-		now_queuing = AHC_DEV_Q_TAGGED;
+		now_queuing = AIC_DEV_Q_TAGGED;
 		break;
 	}
-	if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) == 0
+	if ((dev->flags & AIC_DEV_FREEZE_TIL_EMPTY) == 0
 	 && (was_queuing != now_queuing)
 	 && (dev->active != 0)) {
-		dev->flags |= AHC_DEV_FREEZE_TIL_EMPTY;
+		dev->flags |= AIC_DEV_FREEZE_TIL_EMPTY;
 		dev->qfrozen++;
 	}
 
-	dev->flags &= ~(AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED|AHC_DEV_PERIODIC_OTAG);
+	dev->flags &= ~(AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED|AIC_DEV_PERIODIC_OTAG);
 	if (now_queuing) {
 		u_int usertags;
 
@@ -2073,11 +2032,11 @@ ahc_platform_set_tags(struct ahc_softc *
 			 */
 			dev->openings = 1;
 		} else if (alg == AHC_QUEUE_TAGGED) {
-			dev->flags |= AHC_DEV_Q_TAGGED;
+			dev->flags |= AIC_DEV_Q_TAGGED;
 			if (aic7xxx_periodic_otag != 0)
-				dev->flags |= AHC_DEV_PERIODIC_OTAG;
+				dev->flags |= AIC_DEV_PERIODIC_OTAG;
 		} else
-			dev->flags |= AHC_DEV_Q_BASIC;
+			dev->flags |= AIC_DEV_Q_BASIC;
 	} else {
 		/* We can only have one opening. */
 		dev->maxtags = 0;
@@ -2085,13 +2044,13 @@ ahc_platform_set_tags(struct ahc_softc *
 	}
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 	if (dev->scsi_device != NULL) {
-		switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) {
-		case AHC_DEV_Q_BASIC:
+		switch ((dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED))) {
+		case AIC_DEV_Q_BASIC:
 			scsi_adjust_queue_depth(dev->scsi_device,
 						MSG_SIMPLE_TASK,
 						dev->openings + dev->active);
 			break;
-		case AHC_DEV_Q_TAGGED:
+		case AIC_DEV_Q_TAGGED:
 			scsi_adjust_queue_depth(dev->scsi_device,
 						MSG_ORDERED_TASK,
 						dev->openings + dev->active);
@@ -2155,9 +2114,9 @@ ahc_platform_abort_scbs(struct ahc_softc
 		for (; targ < maxtarg; targ++) {
 
 			for (; clun < maxlun; clun++) {
-				struct ahc_linux_device *dev;
-				struct ahc_busyq *busyq;
-				struct ahc_cmd *acmd;
+				struct aic_linux_device *dev;
+				struct aic_busyq *busyq;
+				struct aic_cmd *acmd;
 
 				dev = ahc_linux_get_device(ahc, chan,
 							   targ, clun,
@@ -2174,6 +2133,20 @@ ahc_platform_abort_scbs(struct ahc_softc
 						     acmd_links.tqe);
 					count++;
 					cmd->result = status << 16;
+					/*
+					 * The completion handler believes that
+					 * commands without active timers
+					 * running have lost the race of
+					 * completing before their timer
+					 * expires.  Since commands in our
+					 * busy queues do not have timers
+					 * running, appease the mid-layer by
+					 * adding a timer now.  This timer will
+					 * be immediately canceled by the
+					 * midlayer.
+					 */
+					scsi_add_timer(cmd, 60*HZ,
+					    aic_linux_midlayer_timeout);
 					ahc_linux_queue_cmd_complete(ahc, cmd);
 				}
 			}
@@ -2190,7 +2163,7 @@ ahc_linux_thread_run_complete_queue(stru
 
 	ahc_lock(ahc, &flags);
 	del_timer(&ahc->platform_data->completeq_timer);
-	ahc->platform_data->flags &= ~AHC_RUN_CMPLT_Q_TIMER;
+	ahc->platform_data->flags &= ~AIC_RUN_CMPLT_Q_TIMER;
 	ahc_linux_run_complete_queue(ahc);
 	ahc_unlock(ahc, &flags);
 }
@@ -2203,14 +2176,23 @@ ahc_linux_start_dv(struct ahc_softc *ahc
 	 * Freeze the simq and signal ahc_linux_queue to not let any
 	 * more commands through.
 	 */
-	if ((ahc->platform_data->flags & AHC_DV_ACTIVE) == 0) {
+	if ((ahc->platform_data->flags & AIC_DV_ACTIVE) == 0) {
 #ifdef AHC_DEBUG
 		if (ahc_debug & AHC_SHOW_DV)
 			printf("%s: Waking DV thread\n", ahc_name(ahc));
 #endif
 
-		ahc->platform_data->flags |= AHC_DV_ACTIVE;
-		ahc_linux_freeze_simq(ahc);
+		ahc->platform_data->flags |= AIC_DV_ACTIVE;
+
+		/*
+		 * Prevent upper layer from sending any
+		 * commands to us.
+		 */
+		aic_freeze_simq(ahc);
+		scsi_block_requests(ahc->platform_data->host);
+		ahc_platform_abort_scbs(ahc, CAM_TARGET_WILDCARD, ALL_CHANNELS,
+					CAM_LUN_WILDCARD, SCB_LIST_NULL,
+					ROLE_INITIATOR, CAM_REQUEUE_REQ);
 
 		/* Wake up the DV kthread */
 		up(&ahc->platform_data->dv_sem);
@@ -2224,7 +2206,7 @@ ahc_linux_kill_dv_thread(struct ahc_soft
 
 	ahc_lock(ahc, &s);
 	if (ahc->platform_data->dv_pid != 0) {
-		ahc->platform_data->flags |= AHC_DV_SHUTDOWN;
+		ahc->platform_data->flags |= AIC_DV_SHUTDOWN;
 		ahc_unlock(ahc, &s);
 		up(&ahc->platform_data->dv_sem);
 
@@ -2299,7 +2281,7 @@ ahc_linux_dv_thread(void *data)
 
 		/* Check to see if we've been signaled to exit */
 		ahc_lock(ahc, &s);
-		if ((ahc->platform_data->flags & AHC_DV_SHUTDOWN) != 0) {
+		if ((ahc->platform_data->flags & AIC_DV_SHUTDOWN) != 0) {
 			ahc_unlock(ahc, &s);
 			break;
 		}
@@ -2316,7 +2298,7 @@ ahc_linux_dv_thread(void *data)
 		 */
 		ahc_lock(ahc, &s);
 		while (LIST_FIRST(&ahc->pending_scbs) != NULL) {
-			ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_EMPTY;
+			ahc->platform_data->flags |= AIC_DV_WAIT_SIMQ_EMPTY;
 			ahc_unlock(ahc, &s);
 			down_interruptible(&ahc->platform_data->dv_sem);
 			ahc_lock(ahc, &s);
@@ -2326,8 +2308,8 @@ ahc_linux_dv_thread(void *data)
 		 * Wait for the SIMQ to be released so that DV is the
 		 * only reason the queue is frozen.
 		 */
-		while (AHC_DV_SIMQ_FROZEN(ahc) == 0) {
-			ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_RELEASE;
+		while (AIC_DV_SIMQ_FROZEN(ahc) == 0) {
+			ahc->platform_data->flags |= AIC_DV_WAIT_SIMQ_RELEASE;
 			ahc_unlock(ahc, &s);
 			down_interruptible(&ahc->platform_data->dv_sem);
 			ahc_lock(ahc, &s);
@@ -2338,14 +2320,16 @@ ahc_linux_dv_thread(void *data)
 			ahc_linux_dv_target(ahc, target);
 
 		ahc_lock(ahc, &s);
-		ahc->platform_data->flags &= ~AHC_DV_ACTIVE;
-		ahc_unlock(ahc, &s);
+		ahc->platform_data->flags &= ~AIC_DV_ACTIVE;
 
 		/*
 		 * Release the SIMQ so that normal commands are
 		 * allowed to continue on the bus.
 		 */
-		ahc_linux_release_simq((u_long)ahc);
+		aic_release_simq_locked(ahc);
+		ahc_unlock(ahc, &s);
+
+		scsi_unblock_requests(ahc->platform_data->host);
 	}
 	up(&ahc->platform_data->eh_sem);
 	return (0);
@@ -2359,10 +2343,10 @@ ahc_linux_dv_thread(void *data)
 	ahc_set_dv_state(ahc, targ, newstate, __LINE__)
 
 static __inline void
-ahc_set_dv_state(struct ahc_softc *ahc, struct ahc_linux_target *targ,
-		 ahc_dv_state newstate, u_int line)
+ahc_set_dv_state(struct ahc_softc *ahc, struct aic_linux_target *targ,
+		 aic_dv_state newstate, u_int line)
 {
-	ahc_dv_state oldstate;
+	aic_dv_state oldstate;
 
 	oldstate = targ->dv_state;
 #ifdef AHC_DEBUG
@@ -2382,7 +2366,7 @@ static void
 ahc_linux_dv_target(struct ahc_softc *ahc, u_int target_offset)
 {
 	struct	 ahc_devinfo devinfo;
-	struct	 ahc_linux_target *targ;
+	struct	 aic_linux_target *targ;
 	struct	 scsi_cmnd *cmd;
 	struct	 scsi_device *scsi_dev;
 	struct	 scsi_sense_data *sense;
@@ -2396,7 +2380,7 @@ ahc_linux_dv_target(struct ahc_softc *ah
 	echo_size = 0;
 	ahc_lock(ahc, &s);
 	targ = ahc->platform_data->targets[target_offset];
-	if (targ == NULL || (targ->flags & AHC_DV_REQUIRED) == 0) {
+	if (targ == NULL || (targ->flags & AIC_DV_REQUIRED) == 0) {
 		ahc_unlock(ahc, &s);
 		return;
 	}
@@ -2421,14 +2405,14 @@ ahc_linux_dv_target(struct ahc_softc *ah
 	scsi_dev->channel = devinfo.channel - 'A';
 	ahc->platform_data->dv_scsi_dev = scsi_dev;
 
-	AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_SHORT_ASYNC);
+	AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_INQ_SHORT_ASYNC);
 
-	while (targ->dv_state != AHC_DV_STATE_EXIT) {
+	while (targ->dv_state != AIC_DV_STATE_EXIT) {
 		timeout = AHC_LINUX_DV_TIMEOUT;
 		switch (targ->dv_state) {
-		case AHC_DV_STATE_INQ_SHORT_ASYNC:
-		case AHC_DV_STATE_INQ_ASYNC:
-		case AHC_DV_STATE_INQ_ASYNC_VERIFY:
+		case AIC_DV_STATE_INQ_SHORT_ASYNC:
+		case AIC_DV_STATE_INQ_ASYNC:
+		case AIC_DV_STATE_INQ_ASYNC_VERIFY:
 			/*
 			 * Set things to async narrow to reduce the
 			 * chance that the INQ will fail.
@@ -2440,36 +2424,36 @@ ahc_linux_dv_target(struct ahc_softc *ah
 				      AHC_TRANS_GOAL, /*paused*/FALSE);
 			ahc_unlock(ahc, &s);
 			timeout = 10 * HZ;
-			targ->flags &= ~AHC_INQ_VALID;
+			targ->flags &= ~AIC_INQ_VALID;
 			/* FALLTHROUGH */
-		case AHC_DV_STATE_INQ_VERIFY:
+		case AIC_DV_STATE_INQ_VERIFY:
 		{
 			u_int inq_len;
 
-			if (targ->dv_state == AHC_DV_STATE_INQ_SHORT_ASYNC)
+			if (targ->dv_state == AIC_DV_STATE_INQ_SHORT_ASYNC)
 				inq_len = AHC_LINUX_DV_INQ_SHORT_LEN;
 			else
 				inq_len = targ->inq_data->additional_length + 5;
 			ahc_linux_dv_inq(ahc, cmd, &devinfo, targ, inq_len);
 			break;
 		}
-		case AHC_DV_STATE_TUR:
-		case AHC_DV_STATE_BUSY:
+		case AIC_DV_STATE_TUR:
+		case AIC_DV_STATE_BUSY:
 			timeout = 5 * HZ;
 			ahc_linux_dv_tur(ahc, cmd, &devinfo);
 			break;
-		case AHC_DV_STATE_REBD:
+		case AIC_DV_STATE_REBD:
 			ahc_linux_dv_rebd(ahc, cmd, &devinfo, targ);
 			break;
-		case AHC_DV_STATE_WEB:
+		case AIC_DV_STATE_WEB:
 			ahc_linux_dv_web(ahc, cmd, &devinfo, targ);
 			break;
 
-		case AHC_DV_STATE_REB:
+		case AIC_DV_STATE_REB:
 			ahc_linux_dv_reb(ahc, cmd, &devinfo, targ);
 			break;
 
-		case AHC_DV_STATE_SU:
+		case AIC_DV_STATE_SU:
 			ahc_linux_dv_su(ahc, cmd, &devinfo, targ);
 			timeout = 50 * HZ;
 			break;
@@ -2481,8 +2465,6 @@ ahc_linux_dv_target(struct ahc_softc *ah
 		}
 
 		/* Queue the command and wait for it to complete */
-		/* Abuse eh_timeout in the scsi_cmnd struct for our purposes */
-		init_timer(&cmd->eh_timeout);
 #ifdef AHC_DEBUG
 		if ((ahc_debug & AHC_SHOW_MESSAGES) != 0)
 			/*
@@ -2492,7 +2474,9 @@ ahc_linux_dv_target(struct ahc_softc *ah
 			 */
 			timeout += HZ;
 #endif
-		scsi_add_timer(cmd, timeout, ahc_linux_dv_timeout);
+		init_timer(&cmd->eh_timeout);
+		cmd->timeout_per_command = timeout;
+
 		/*
 		 * In 2.5.X, it is assumed that all calls from the
 		 * "midlayer" (which we are emulating) will have the
@@ -2516,8 +2500,8 @@ ahc_linux_dv_target(struct ahc_softc *ah
 		 * only reason the queue is frozen.
 		 */
 		ahc_lock(ahc, &s);
-		while (AHC_DV_SIMQ_FROZEN(ahc) == 0) {
-			ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_RELEASE;
+		while (AIC_DV_SIMQ_FROZEN(ahc) == 0) {
+			ahc->platform_data->flags |= AIC_DV_WAIT_SIMQ_RELEASE;
 			ahc_unlock(ahc, &s);
 			down_interruptible(&ahc->platform_data->dv_sem);
 			ahc_lock(ahc, &s);
@@ -2528,7 +2512,7 @@ ahc_linux_dv_target(struct ahc_softc *ah
 	}
 
 out:
-	if ((targ->flags & AHC_INQ_VALID) != 0
+	if ((targ->flags & AIC_INQ_VALID) != 0
 	 && ahc_linux_get_device(ahc, devinfo.channel - 'A',
 				 devinfo.target, devinfo.lun,
 				 /*alloc*/FALSE) == NULL) {
@@ -2539,7 +2523,7 @@ out:
 		 * parameters found in the inquiry string.
 		 */
 		ahc_linux_filter_inquiry(ahc, &devinfo);
-		if ((targ->flags & (AHC_BASIC_DV|AHC_ENHANCED_DV)) != 0) {
+		if ((targ->flags & (AIC_BASIC_DV|AIC_ENHANCED_DV)) != 0) {
 			ahc_print_devinfo(ahc, &devinfo);
 			printf("DV failed to configure device.  "
 			       "Please file a bug report against "
@@ -2564,7 +2548,7 @@ out:
 		free(targ->dv_buffer1, M_DEVBUF);
 		targ->dv_buffer1 = NULL;
 	}
-	targ->flags &= ~AHC_DV_REQUIRED;
+	targ->flags &= ~AIC_DV_REQUIRED;
 	if (targ->refcount == 0)
 		ahc_linux_free_target(ahc, targ);
 	ahc_unlock(ahc, &s);
@@ -2573,13 +2557,13 @@ out:
 static void
 ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
 			struct ahc_devinfo *devinfo,
-			struct ahc_linux_target *targ)
+			struct aic_linux_target *targ)
 {
 	u_int32_t status;
 
 	status = aic_error_action(cmd, targ->inq_data,
-				  ahc_cmd_get_transaction_status(cmd),
-				  ahc_cmd_get_scsi_status(cmd));
+				  aic_cmd_get_transaction_status(cmd),
+				  aic_cmd_get_scsi_status(cmd));
 	
 #ifdef AHC_DEBUG
 	if (ahc_debug & AHC_SHOW_DV) {
@@ -2591,8 +2575,8 @@ ahc_linux_dv_transition(struct ahc_softc
 #endif
 
 	switch (targ->dv_state) {
-	case AHC_DV_STATE_INQ_SHORT_ASYNC:
-	case AHC_DV_STATE_INQ_ASYNC:
+	case AIC_DV_STATE_INQ_SHORT_ASYNC:
+	case AIC_DV_STATE_INQ_ASYNC:
 		switch (status & SS_MASK) {
 		case SS_NOP:
 		{
@@ -2601,21 +2585,21 @@ ahc_linux_dv_transition(struct ahc_softc
 		}
 		case SS_INQ_REFRESH:
 			AHC_SET_DV_STATE(ahc, targ,
-					 AHC_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		case SS_TUR:
 		case SS_RETRY:
 			AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
-			if (ahc_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ)
 				targ->dv_state_retry--;
 			if ((status & SS_ERRMASK) == EBUSY)
-				AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY);
+				AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_BUSY);
 			if (targ->dv_state_retry < 10)
 				break;
 			/* FALLTHROUGH */
 		default:
-			AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+			AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 #ifdef AHC_DEBUG
 			if (ahc_debug & AHC_SHOW_DV) {
 				ahc_print_devinfo(ahc, devinfo);
@@ -2625,7 +2609,7 @@ ahc_linux_dv_transition(struct ahc_softc
 			break;
 		}
 		break;
-	case AHC_DV_STATE_INQ_ASYNC_VERIFY:
+	case AIC_DV_STATE_INQ_ASYNC_VERIFY:
 		switch (status & SS_MASK) {
 		case SS_NOP:
 		{
@@ -2639,12 +2623,12 @@ ahc_linux_dv_transition(struct ahc_softc
 				 * Try from the top again.
 				 */
 				AHC_SET_DV_STATE(ahc, targ,
-						 AHC_DV_STATE_INQ_SHORT_ASYNC);
+						 AIC_DV_STATE_INQ_SHORT_ASYNC);
 				break;
 			}
 
 			AHC_SET_DV_STATE(ahc, targ, targ->dv_state+1);
-			targ->flags |= AHC_INQ_VALID;
+			targ->flags |= AIC_INQ_VALID;
 			if (ahc_linux_user_dv_setting(ahc) == 0)
 				break;
 
@@ -2657,33 +2641,33 @@ ahc_linux_dv_transition(struct ahc_softc
 			default:
 			case SID_SPI_CLOCK_ST:
 				/* Assume only basic DV is supported. */
-				targ->flags |= AHC_BASIC_DV;
+				targ->flags |= AIC_BASIC_DV;
 				break;
 			case SID_SPI_CLOCK_DT:
 			case SID_SPI_CLOCK_DT_ST:
-				targ->flags |= AHC_ENHANCED_DV;
+				targ->flags |= AIC_ENHANCED_DV;
 				break;
 			}
 			break;
 		}
 		case SS_INQ_REFRESH:
 			AHC_SET_DV_STATE(ahc, targ,
-					 AHC_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		case SS_TUR:
 		case SS_RETRY:
 			AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
-			if (ahc_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ)
 				targ->dv_state_retry--;
 
 			if ((status & SS_ERRMASK) == EBUSY)
-				AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY);
+				AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_BUSY);
 			if (targ->dv_state_retry < 10)
 				break;
 			/* FALLTHROUGH */
 		default:
-			AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+			AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 #ifdef AHC_DEBUG
 			if (ahc_debug & AHC_SHOW_DV) {
 				ahc_print_devinfo(ahc, devinfo);
@@ -2693,14 +2677,14 @@ ahc_linux_dv_transition(struct ahc_softc
 			break;
 		}
 		break;
-	case AHC_DV_STATE_INQ_VERIFY:
+	case AIC_DV_STATE_INQ_VERIFY:
 		switch (status & SS_MASK) {
 		case SS_NOP:
 		{
 
 			if (memcmp(targ->inq_data, targ->dv_buffer,
 				   AHC_LINUX_DV_INQ_LEN) == 0) {
-				AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+				AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 				break;
 			}
 #ifdef AHC_DEBUG
@@ -2721,7 +2705,7 @@ ahc_linux_dv_transition(struct ahc_softc
 #endif
 
 			if (ahc_linux_fallback(ahc, devinfo) != 0) {
-				AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+				AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 				break;
 			}
 			/*
@@ -2734,18 +2718,18 @@ ahc_linux_dv_transition(struct ahc_softc
 		}
 		case SS_INQ_REFRESH:
 			AHC_SET_DV_STATE(ahc, targ,
-					 AHC_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		case SS_TUR:
 		case SS_RETRY:
 			AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
-			if (ahc_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ) {
 				targ->dv_state_retry--;
 			} else if ((status & SSQ_FALLBACK) != 0) {
 				if (ahc_linux_fallback(ahc, devinfo) != 0) {
 					AHC_SET_DV_STATE(ahc, targ,
-							 AHC_DV_STATE_EXIT);
+							 AIC_DV_STATE_EXIT);
 					break;
 				}
 				/*
@@ -2754,12 +2738,12 @@ ahc_linux_dv_transition(struct ahc_softc
 				 */
 				targ->dv_state_retry = 0;
 			} else if ((status & SS_ERRMASK) == EBUSY)
-				AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY);
+				AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_BUSY);
 			if (targ->dv_state_retry < 10)
 				break;
 			/* FALLTHROUGH */
 		default:
-			AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+			AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 #ifdef AHC_DEBUG
 			if (ahc_debug & AHC_SHOW_DV) {
 				ahc_print_devinfo(ahc, devinfo);
@@ -2770,33 +2754,33 @@ ahc_linux_dv_transition(struct ahc_softc
 		}
 		break;
 
-	case AHC_DV_STATE_TUR:
+	case AIC_DV_STATE_TUR:
 		switch (status & SS_MASK) {
 		case SS_NOP:
-			if ((targ->flags & AHC_BASIC_DV) != 0) {
+			if ((targ->flags & AIC_BASIC_DV) != 0) {
 				ahc_linux_filter_inquiry(ahc, devinfo);
 				AHC_SET_DV_STATE(ahc, targ,
-						 AHC_DV_STATE_INQ_VERIFY);
-			} else if ((targ->flags & AHC_ENHANCED_DV) != 0) {
-				AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_REBD);
+						 AIC_DV_STATE_INQ_VERIFY);
+			} else if ((targ->flags & AIC_ENHANCED_DV) != 0) {
+				AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_REBD);
 			} else {
-				AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+				AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 			}
 			break;
 		case SS_RETRY:
 		case SS_TUR:
 			if ((status & SS_ERRMASK) == EBUSY) {
-				AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY);
+				AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_BUSY);
 				break;
 			}
 			AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
-			if (ahc_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ) {
 				targ->dv_state_retry--;
 			} else if ((status & SSQ_FALLBACK) != 0) {
 				if (ahc_linux_fallback(ahc, devinfo) != 0) {
 					AHC_SET_DV_STATE(ahc, targ,
-							 AHC_DV_STATE_EXIT);
+							 AIC_DV_STATE_EXIT);
 					break;
 				}
 				/*
@@ -2812,7 +2796,7 @@ ahc_linux_dv_transition(struct ahc_softc
 					printf("DV TUR reties exhausted\n");
 				}
 #endif
-				AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+				AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 				break;
 			}
 			if (status & SSQ_DELAY)
@@ -2820,25 +2804,25 @@ ahc_linux_dv_transition(struct ahc_softc
 
 			break;
 		case SS_START:
-			AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_SU);
+			AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_SU);
 			break;
 		case SS_INQ_REFRESH:
 			AHC_SET_DV_STATE(ahc, targ,
-					 AHC_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		default:
-			AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+			AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 			break;
 		}
 		break;
 
-	case AHC_DV_STATE_REBD:
+	case AIC_DV_STATE_REBD:
 		switch (status & SS_MASK) {
 		case SS_NOP:
 		{
 			uint32_t echo_size;
 
-			AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_WEB);
+			AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_WEB);
 			echo_size = scsi_3btoul(&targ->dv_buffer[1]);
 			echo_size &= 0x1FFF;
 #ifdef AHC_DEBUG
@@ -2848,7 +2832,17 @@ ahc_linux_dv_transition(struct ahc_softc
 			}
 #endif
 			if (echo_size == 0) {
-				AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+				/*
+				 * Fall back to basic DV.
+				 */
+				if (bootverbose) {
+					ahc_print_devinfo(ahc, devinfo);
+					printf("Echo Buffer unavailable.  "
+					       "Performing basic DV.\n");
+				}
+				targ->flags &= ~AIC_ENHANCED_DV;
+				targ->flags |= AIC_BASIC_DV;
+				AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_TUR);
 				break;
 			}
 
@@ -2863,11 +2857,11 @@ ahc_linux_dv_transition(struct ahc_softc
 		}
 		case SS_INQ_REFRESH:
 			AHC_SET_DV_STATE(ahc, targ,
-					 AHC_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		case SS_RETRY:
 			AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
-			if (ahc_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ)
 				targ->dv_state_retry--;
 			if (targ->dv_state_retry <= 10)
@@ -2886,30 +2880,30 @@ ahc_linux_dv_transition(struct ahc_softc
 			 * and try level 1 DV.
 			 */
 			ahc_linux_filter_inquiry(ahc, devinfo);
-			AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_VERIFY);
+			AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_INQ_VERIFY);
 			targ->dv_echo_size = 0;
 			break;
 		}
 		break;
 
-	case AHC_DV_STATE_WEB:
+	case AIC_DV_STATE_WEB:
 		switch (status & SS_MASK) {
 		case SS_NOP:
-			AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_REB);
+			AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_REB);
 			break;
 		case SS_INQ_REFRESH:
 			AHC_SET_DV_STATE(ahc, targ,
-					 AHC_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		case SS_RETRY:
 			AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
-			if (ahc_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ) {
 				targ->dv_state_retry--;
 			} else if ((status & SSQ_FALLBACK) != 0) {
 				if (ahc_linux_fallback(ahc, devinfo) != 0) {
 					AHC_SET_DV_STATE(ahc, targ,
-							 AHC_DV_STATE_EXIT);
+							 AIC_DV_STATE_EXIT);
 					break;
 				}
 				/*
@@ -2928,22 +2922,22 @@ ahc_linux_dv_transition(struct ahc_softc
 			}
 #endif
 		default:
-			AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+			AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 			break;
 		}
 		break;
 
-	case AHC_DV_STATE_REB:
+	case AIC_DV_STATE_REB:
 		switch (status & SS_MASK) {
 		case SS_NOP:
 			if (memcmp(targ->dv_buffer, targ->dv_buffer1,
 				   targ->dv_echo_size) != 0) {
 				if (ahc_linux_fallback(ahc, devinfo) != 0)
 					AHC_SET_DV_STATE(ahc, targ,
-							 AHC_DV_STATE_EXIT);
+							 AIC_DV_STATE_EXIT);
 				else
 					AHC_SET_DV_STATE(ahc, targ,
-							 AHC_DV_STATE_WEB);
+							 AIC_DV_STATE_WEB);
 				break;
 			}
 			
@@ -2955,24 +2949,24 @@ ahc_linux_dv_transition(struct ahc_softc
 				free(targ->dv_buffer1, M_DEVBUF);
 				targ->dv_buffer1 = NULL;
 			}
-			AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+			AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 			break;
 		case SS_INQ_REFRESH:
 			AHC_SET_DV_STATE(ahc, targ,
-					 AHC_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		case SS_RETRY:
 			AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
-			if (ahc_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ) {
 				targ->dv_state_retry--;
 			} else if ((status & SSQ_FALLBACK) != 0) {
 				if (ahc_linux_fallback(ahc, devinfo) != 0) {
 					AHC_SET_DV_STATE(ahc, targ,
-							 AHC_DV_STATE_EXIT);
+							 AIC_DV_STATE_EXIT);
 					break;
 				}
-				AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_WEB);
+				AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_WEB);
 			}
 			if (targ->dv_state_retry <= 10) {
 				if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0)
@@ -2987,35 +2981,35 @@ ahc_linux_dv_transition(struct ahc_softc
 #endif
 			/* FALLTHROUGH */
 		default:
-			AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+			AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 			break;
 		}
 		break;
 
-	case AHC_DV_STATE_SU:
+	case AIC_DV_STATE_SU:
 		switch (status & SS_MASK) {
 		case SS_NOP:
 		case SS_INQ_REFRESH:
 			AHC_SET_DV_STATE(ahc, targ,
-					 AHC_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		default:
-			AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+			AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 			break;
 		}
 		break;
 
-	case AHC_DV_STATE_BUSY:
+	case AIC_DV_STATE_BUSY:
 		switch (status & SS_MASK) {
 		case SS_NOP:
 		case SS_INQ_REFRESH:
 			AHC_SET_DV_STATE(ahc, targ,
-					 AHC_DV_STATE_INQ_SHORT_ASYNC);
+					 AIC_DV_STATE_INQ_SHORT_ASYNC);
 			break;
 		case SS_TUR:
 		case SS_RETRY:
 			AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
-			if (ahc_cmd_get_transaction_status(cmd)
+			if (aic_cmd_get_transaction_status(cmd)
 			 == CAM_REQUEUE_REQ) {
 				targ->dv_state_retry--;
 			} else if (targ->dv_state_retry < 60) {
@@ -3028,11 +3022,11 @@ ahc_linux_dv_transition(struct ahc_softc
 					printf("DV BUSY reties exhausted\n");
 				}
 #endif
-				AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+				AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 			}
 			break;
 		default:
-			AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+			AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 			break;
 		}
 		break;
@@ -3040,7 +3034,7 @@ ahc_linux_dv_transition(struct ahc_softc
 	default:
 		printf("%s: Invalid DV completion state %d\n", ahc_name(ahc),
 		       targ->dv_state);
-		AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+		AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT);
 		break;
 	}
 }
@@ -3060,7 +3054,7 @@ ahc_linux_dv_fill_cmd(struct ahc_softc *
  */
 static void
 ahc_linux_dv_inq(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
-		 struct ahc_devinfo *devinfo, struct ahc_linux_target *targ,
+		 struct ahc_devinfo *devinfo, struct aic_linux_target *targ,
 		 u_int request_length)
 {
 
@@ -3073,7 +3067,7 @@ ahc_linux_dv_inq(struct ahc_softc *ahc, 
 	if (targ->inq_data == NULL)
 		targ->inq_data = malloc(AHC_LINUX_DV_INQ_LEN,
 					M_DEVBUF, M_WAITOK);
-	if (targ->dv_state > AHC_DV_STATE_INQ_ASYNC) {
+	if (targ->dv_state > AIC_DV_STATE_INQ_ASYNC) {
 		if (targ->dv_buffer != NULL)
 			free(targ->dv_buffer, M_DEVBUF);
 		targ->dv_buffer = malloc(AHC_LINUX_DV_INQ_LEN,
@@ -3086,7 +3080,7 @@ ahc_linux_dv_inq(struct ahc_softc *ahc, 
 	cmd->cmnd[0] = INQUIRY;
 	cmd->cmnd[4] = request_length;
 	cmd->request_bufflen = request_length;
-	if (targ->dv_state > AHC_DV_STATE_INQ_ASYNC)
+	if (targ->dv_state > AIC_DV_STATE_INQ_ASYNC)
 		cmd->request_buffer = targ->dv_buffer;
 	else
 		cmd->request_buffer = targ->inq_data;
@@ -3115,7 +3109,7 @@ ahc_linux_dv_tur(struct ahc_softc *ahc, 
 
 static void
 ahc_linux_dv_rebd(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
-		 struct ahc_devinfo *devinfo, struct ahc_linux_target *targ)
+		 struct ahc_devinfo *devinfo, struct aic_linux_target *targ)
 {
 
 #ifdef AHC_DEBUG
@@ -3140,7 +3134,7 @@ ahc_linux_dv_rebd(struct ahc_softc *ahc,
 
 static void
 ahc_linux_dv_web(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
-		 struct ahc_devinfo *devinfo, struct ahc_linux_target *targ)
+		 struct ahc_devinfo *devinfo, struct aic_linux_target *targ)
 {
 
 #ifdef AHC_DEBUG
@@ -3162,7 +3156,7 @@ ahc_linux_dv_web(struct ahc_softc *ahc, 
 
 static void
 ahc_linux_dv_reb(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
-		 struct ahc_devinfo *devinfo, struct ahc_linux_target *targ)
+		 struct ahc_devinfo *devinfo, struct aic_linux_target *targ)
 {
 
 #ifdef AHC_DEBUG
@@ -3185,7 +3179,7 @@ ahc_linux_dv_reb(struct ahc_softc *ahc, 
 static void
 ahc_linux_dv_su(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
 		struct ahc_devinfo *devinfo,
-		struct ahc_linux_target *targ)
+		struct aic_linux_target *targ)
 {
 	u_int le;
 
@@ -3207,7 +3201,7 @@ ahc_linux_dv_su(struct ahc_softc *ahc, s
 static int
 ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
 {
-	struct	ahc_linux_target *targ;
+	struct	aic_linux_target *targ;
 	struct	ahc_initiator_tinfo *tinfo;
 	struct	ahc_transinfo *goal;
 	struct	ahc_tmode_tstate *tstate;
@@ -3386,7 +3380,7 @@ ahc_linux_fallback(struct ahc_softc *ahc
 	return (0);
 }
 
-static void
+void
 ahc_linux_dv_timeout(struct scsi_cmnd *cmd)
 {
 	struct	ahc_softc *ahc;
@@ -3420,29 +3414,19 @@ ahc_linux_dv_timeout(struct scsi_cmnd *c
 	 * error code.
 	 */
 	if ((scb->flags & SCB_SENSE) != 0)
-		ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
+		aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
 	else
-		ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT);
+		aic_set_transaction_status(scb, CAM_CMD_TIMEOUT);
 	ahc_reset_channel(ahc, cmd->device->channel + 'A', /*initiate*/TRUE);
 
-	/*
-	 * Add a minimal bus settle delay for devices that are slow to
-	 * respond after bus resets.
-	 */
-	ahc_linux_freeze_simq(ahc);
-	init_timer(&ahc->platform_data->reset_timer);
-	ahc->platform_data->reset_timer.data = (u_long)ahc;
-	ahc->platform_data->reset_timer.expires = jiffies + HZ / 2;
-	ahc->platform_data->reset_timer.function =
-	    (ahc_linux_callback_t *)ahc_linux_release_simq;
-	add_timer(&ahc->platform_data->reset_timer);
-	if (ahc_linux_next_device_to_run(ahc) != NULL)
-		ahc_schedule_runq(ahc);
+	if (aic_linux_next_device_to_run(ahc) != NULL)
+		aic_schedule_runq(ahc);
+
 	ahc_linux_run_complete_queue(ahc);
 	ahc_unlock(ahc, &flags);
 }
 
-static void
+void
 ahc_linux_dv_complete(struct scsi_cmnd *cmd)
 {
 	struct ahc_softc *ahc;
@@ -3464,7 +3448,7 @@ ahc_linux_dv_complete(struct scsi_cmnd *
 }
 
 static void
-ahc_linux_generate_dv_pattern(struct ahc_linux_target *targ)
+ahc_linux_generate_dv_pattern(struct aic_linux_target *targ)
 {
 	uint16_t b;
 	u_int	 i;
@@ -3596,8 +3580,8 @@ ahc_linux_user_dv_setting(struct ahc_sof
  * Determines the queue depth for a given device.
  */
 static void
-ahc_linux_device_queue_depth(struct ahc_softc *ahc,
-			     struct ahc_linux_device *dev)
+aic_linux_device_queue_depth(struct ahc_softc *ahc,
+			     struct aic_linux_device *dev)
 {
 	struct	ahc_devinfo devinfo;
 	u_int	tags;
@@ -3621,10 +3605,10 @@ ahc_linux_device_queue_depth(struct ahc_
 	}
 }
 
-static void
-ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev)
+void
+ahc_linux_run_device_queue(struct ahc_softc *ahc, struct aic_linux_device *dev)
 {
-	struct	 ahc_cmd *acmd;
+	struct	 aic_cmd *acmd;
 	struct	 scsi_cmnd *cmd;
 	struct	 scb *scb;
 	struct	 hardware_scb *hscb;
@@ -3632,7 +3616,7 @@ ahc_linux_run_device_queue(struct ahc_so
 	struct	 ahc_tmode_tstate *tstate;
 	uint16_t mask;
 
-	if ((dev->flags & AHC_DEV_ON_RUN_LIST) != 0)
+	if ((dev->flags & AIC_DEV_ON_RUN_LIST) != 0)
 		panic("running device on run list");
 
 	while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL
@@ -3643,10 +3627,10 @@ ahc_linux_run_device_queue(struct ahc_so
 		 * running is because the whole controller Q is frozen.
 		 */
 		if (ahc->platform_data->qfrozen != 0
-	 	 && AHC_DV_SIMQ_FROZEN(ahc) == 0) {
+	 	 && AIC_DV_SIMQ_FROZEN(ahc) == 0) {
 			TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq,
 					  dev, links);
-			dev->flags |= AHC_DEV_ON_RUN_LIST;
+			dev->flags |= AIC_DEV_ON_RUN_LIST;
 			return;
 		}
 		/*
@@ -3655,7 +3639,7 @@ ahc_linux_run_device_queue(struct ahc_so
 		if ((scb = ahc_get_scb(ahc)) == NULL) {
 			TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq,
 					 dev, links);
-			dev->flags |= AHC_DEV_ON_RUN_LIST;
+			dev->flags |= AIC_DEV_ON_RUN_LIST;
 			ahc->flags |= AHC_RESOURCE_SHORTAGE;
 			return;
 		}
@@ -3663,6 +3647,7 @@ ahc_linux_run_device_queue(struct ahc_so
 		cmd = &acmd_scsi_cmd(acmd);
 		scb->io_ctx = cmd;
 		scb->platform_data->dev = dev;
+		scb->platform_data->flags = 0;
 		hscb = scb->hscb;
 		cmd->host_scribble = (char *)scb;
 
@@ -3684,7 +3669,7 @@ ahc_linux_run_device_queue(struct ahc_so
 		if ((ahc->user_discenable & mask) != 0)
 			hscb->control |= DISCENB;
 
-	 	if (AHC_DV_CMD(cmd) != 0)
+	 	if (AIC_DV_CMD(cmd) != 0)
 			scb->flags |= SCB_SILENT;
 
 		if ((tstate->auto_negotiate & mask) != 0) {
@@ -3692,7 +3677,7 @@ ahc_linux_run_device_queue(struct ahc_so
 			scb->hscb->control |= MK_MESSAGE;
 		}
 
-		if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) {
+		if ((dev->flags & (AIC_DEV_Q_TAGGED|AIC_DEV_Q_BASIC)) != 0) {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 			int	msg_bytes;
 			uint8_t tag_msgs[2];
@@ -3704,8 +3689,8 @@ ahc_linux_run_device_queue(struct ahc_so
 					dev->commands_since_idle_or_otag = 0;
 			} else
 #endif
-			if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH
-			 && (dev->flags & AHC_DEV_Q_TAGGED) != 0) {
+			if (dev->commands_since_idle_or_otag == AIC_OTAG_THRESH
+			 && (dev->flags & AIC_DEV_Q_TAGGED) != 0) {
 				hscb->control |= MSG_ORDERED_TASK;
 				dev->commands_since_idle_or_otag = 0;
 			} else {
@@ -3722,8 +3707,8 @@ ahc_linux_run_device_queue(struct ahc_so
 		}
 
 		scb->platform_data->xfer_len = 0;
-		ahc_set_residual(scb, 0);
-		ahc_set_sense_residual(scb, 0);
+		aic_set_residual(scb, 0);
+		aic_set_sense_residual(scb, 0);
 		scb->sg_count = 0;
 		if (cmd->use_sg != 0) {
 			struct	ahc_dma_seg *sg;
@@ -3732,7 +3717,7 @@ ahc_linux_run_device_queue(struct ahc_so
 			int	nseg;
 
 			cur_seg = (struct scatterlist *)cmd->request_buffer;
-			nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg,
+			nseg = aic_map_sg(ahc, cur_seg, cmd->use_sg,
 			    scsi_to_pci_dma_dir(cmd->sc_data_direction));
 			end_seg = cur_seg + nseg;
 			/* Copy the segments into the SG list. */
@@ -3755,13 +3740,13 @@ ahc_linux_run_device_queue(struct ahc_so
 				cur_seg++;
 			}
 			sg--;
-			sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
+			sg->len |= aic_htole32(AHC_DMA_LAST_SEG);
 
 			/*
 			 * Reset the sg list pointer.
 			 */
 			scb->hscb->sgptr =
-			    ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
+			    aic_htole32(scb->sg_list_phys | SG_FULL_RESID);
 
 			/*
 			 * Copy the first SG into the "current"
@@ -3774,7 +3759,7 @@ ahc_linux_run_device_queue(struct ahc_so
 			bus_addr_t addr;
 
 			sg = scb->sg_list;
-			addr = pci_map_single(ahc->dev_softc,
+			addr = aic_map_single(ahc,
 			       cmd->request_buffer,
 			       cmd->request_bufflen,
 			       scsi_to_pci_dma_dir(cmd->sc_data_direction));
@@ -3782,13 +3767,13 @@ ahc_linux_run_device_queue(struct ahc_so
 			scb->sg_count = ahc_linux_map_seg(ahc, scb,
 							  sg, addr,
 							  cmd->request_bufflen);
-			sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
+			sg->len |= aic_htole32(AHC_DMA_LAST_SEG);
 
 			/*
 			 * Reset the sg list pointer.
 			 */
 			scb->hscb->sgptr =
-			    ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
+			    aic_htole32(scb->sg_list_phys | SG_FULL_RESID);
 
 			/*
 			 * Copy the first SG into the "current"
@@ -3797,7 +3782,7 @@ ahc_linux_run_device_queue(struct ahc_so
 			scb->hscb->dataptr = sg->addr;
 			scb->hscb->datacnt = sg->len;
 		} else {
-			scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL);
+			scb->hscb->sgptr = aic_htole32(SG_LIST_NULL);
 			scb->hscb->dataptr = 0;
 			scb->hscb->datacnt = 0;
 			scb->sg_count = 0;
@@ -3808,7 +3793,7 @@ ahc_linux_run_device_queue(struct ahc_so
 		dev->openings--;
 		dev->active++;
 		dev->commands_issued++;
-		if ((dev->flags & AHC_DEV_PERIODIC_OTAG) != 0)
+		if ((dev->flags & AIC_DEV_PERIODIC_OTAG) != 0)
 			dev->commands_since_idle_or_otag++;
 
 		/*
@@ -3830,6 +3815,7 @@ ahc_linux_run_device_queue(struct ahc_so
 				continue;
 		}
 		scb->flags |= SCB_ACTIVE;
+		aic_scb_timer_start(scb);
 		ahc_queue_scb(ahc, scb);
 	}
 }
@@ -3847,8 +3833,8 @@ ahc_linux_isr(int irq, void *dev_id, str
 	ahc = (struct ahc_softc *) dev_id;
 	ahc_lock(ahc, &flags); 
 	ours = ahc_intr(ahc);
-	if (ahc_linux_next_device_to_run(ahc) != NULL)
-		ahc_schedule_runq(ahc);
+	if (aic_linux_next_device_to_run(ahc) != NULL)
+		aic_schedule_runq(ahc);
 	ahc_linux_run_complete_queue(ahc);
 	ahc_unlock(ahc, &flags);
 	return IRQ_RETVAL(ours);
@@ -3862,10 +3848,10 @@ ahc_platform_flushwork(struct ahc_softc 
 		;
 }
 
-static struct ahc_linux_target*
+static struct aic_linux_target*
 ahc_linux_alloc_target(struct ahc_softc *ahc, u_int channel, u_int target)
 {
-	struct ahc_linux_target *targ;
+	struct aic_linux_target *targ;
 	u_int target_offset;
 
 	target_offset = target;
@@ -3878,14 +3864,14 @@ ahc_linux_alloc_target(struct ahc_softc 
 	memset(targ, 0, sizeof(*targ));
 	targ->channel = channel;
 	targ->target = target;
-	targ->ahc = ahc;
-	targ->flags = AHC_DV_REQUIRED;
+	targ->softc = ahc;
+	targ->flags = AIC_DV_REQUIRED;
 	ahc->platform_data->targets[target_offset] = targ;
 	return (targ);
 }
 
 static void
-ahc_linux_free_target(struct ahc_softc *ahc, struct ahc_linux_target *targ)
+ahc_linux_free_target(struct ahc_softc *ahc, struct aic_linux_target *targ)
 {
 	struct ahc_devinfo devinfo;
 	struct ahc_initiator_tinfo *tinfo;
@@ -3925,11 +3911,11 @@ ahc_linux_free_target(struct ahc_softc *
 	free(targ, M_DEVBUF);
 }
 
-static struct ahc_linux_device*
+static struct aic_linux_device*
 ahc_linux_alloc_device(struct ahc_softc *ahc,
-		 struct ahc_linux_target *targ, u_int lun)
+		 struct aic_linux_target *targ, u_int lun)
 {
-	struct ahc_linux_device *dev;
+	struct aic_linux_device *dev;
 
 	dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT);
 	if (dev == NULL)
@@ -3937,7 +3923,7 @@ ahc_linux_alloc_device(struct ahc_softc 
 	memset(dev, 0, sizeof(*dev));
 	init_timer(&dev->timer);
 	TAILQ_INIT(&dev->busyq);
-	dev->flags = AHC_DEV_UNCONFIGURED;
+	dev->flags = AIC_DEV_UNCONFIGURED;
 	dev->lun = lun;
 	dev->target = targ;
 
@@ -3960,17 +3946,17 @@ ahc_linux_alloc_device(struct ahc_softc 
 }
 
 static void
-ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
+ahc_linux_free_device(struct ahc_softc *ahc, struct aic_linux_device *dev)
 {
-	struct ahc_linux_target *targ;
+	struct aic_linux_target *targ;
 
-	del_timer_sync(&dev->timer);
+	del_timer(&dev->timer);
 	targ = dev->target;
 	targ->devices[dev->lun] = NULL;
 	free(dev, M_DEVBUF);
 	targ->refcount--;
 	if (targ->refcount == 0
-	 && (targ->flags & AHC_DV_REQUIRED) == 0)
+	 && (targ->flags & AIC_DV_REQUIRED) == 0)
 		ahc_linux_free_target(ahc, targ);
 }
 
@@ -3982,7 +3968,7 @@ ahc_send_async(struct ahc_softc *ahc, ch
 	case AC_TRANSFER_NEG:
 	{
 		char	buf[80];
-		struct	ahc_linux_target *targ;
+		struct	aic_linux_target *targ;
 		struct	info_str info;
 		struct	ahc_initiator_tinfo *tinfo;
 		struct	ahc_tmode_tstate *tstate;
@@ -4076,6 +4062,20 @@ ahc_send_async(struct ahc_softc *ahc, ch
 					      channel - 'A');
 		}
 #endif
+		/*
+		 * Add a minimal bus settle delay for devices that are slow to
+		 * respond after bus resets.
+		 */
+		if ((ahc->platform_data->flags & AIC_BUS_SETTLE_TIMER) == 0) {
+			aic_freeze_simq(ahc);
+			ahc->platform_data->flags |= AIC_BUS_SETTLE_TIMER;
+			ahc->platform_data->bus_settle_timer.expires =
+			    jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000;
+			add_timer(&ahc->platform_data->bus_settle_timer);
+		} else {
+			mod_timer(&ahc->platform_data->bus_settle_timer,
+				  jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000);
+		}
                 break;
         default:
                 panic("ahc_send_async: Unexpected async event");
@@ -4089,9 +4089,11 @@ void
 ahc_done(struct ahc_softc *ahc, struct scb *scb)
 {
 	Scsi_Cmnd *cmd;
-	struct	   ahc_linux_device *dev;
+	struct	   aic_linux_device *dev;
 
 	LIST_REMOVE(scb, pending_links);
+	if ((scb->flags & SCB_TIMEDOUT) != 0)
+		LIST_REMOVE(scb, timedout_links);
 	if ((scb->flags & SCB_UNTAGGEDQ) != 0) {
 		struct scb_tailq *untagged_q;
 		int target_offset;
@@ -4124,11 +4126,11 @@ ahc_done(struct ahc_softc *ahc, struct s
 	 * the sense buffer looks "sane".
 	 */
 	cmd->sense_buffer[0] = 0;
-	if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) {
+	if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) {
 		uint32_t amount_xferred;
 
 		amount_xferred =
-		    ahc_get_transfer_length(scb) - ahc_get_residual(scb);
+		    aic_get_transfer_length(scb) - aic_get_residual(scb);
 		if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) {
 #ifdef AHC_DEBUG
 			if ((ahc_debug & AHC_SHOW_MISC) != 0) {
@@ -4136,7 +4138,17 @@ ahc_done(struct ahc_softc *ahc, struct s
 				printf("Set CAM_UNCOR_PARITY\n");
 			}
 #endif
-			ahc_set_transaction_status(scb, CAM_UNCOR_PARITY);
+			aic_set_transaction_status(scb, CAM_UNCOR_PARITY);
+#ifdef AHC_REPORT_UNDERFLOWS
+		/*
+		 * This code is disabled by default as some
+		 * clients of the SCSI system do not properly
+		 * initialize the underflow parameter.  This
+		 * results in spurious termination of commands
+		 * that complete as expected (e.g. underflow is
+		 * allowed as command can return variable amounts
+		 * of data.
+		 */
 		} else if (amount_xferred < scb->io_ctx->underflow) {
 			u_int i;
 
@@ -4148,30 +4160,31 @@ ahc_done(struct ahc_softc *ahc, struct s
 			ahc_print_path(ahc, scb);
 			printf("Saw underflow (%ld of %ld bytes). "
 			       "Treated as error\n",
-				ahc_get_residual(scb),
-				ahc_get_transfer_length(scb));
-			ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR);
+				aic_get_residual(scb),
+				aic_get_transfer_length(scb));
+			aic_set_transaction_status(scb, CAM_DATA_RUN_ERR);
+#endif
 		} else {
-			ahc_set_transaction_status(scb, CAM_REQ_CMP);
+			aic_set_transaction_status(scb, CAM_REQ_CMP);
 		}
-	} else if (ahc_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
+	} else if (aic_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
 		ahc_linux_handle_scsi_status(ahc, dev, scb);
-	} else if (ahc_get_transaction_status(scb) == CAM_SEL_TIMEOUT) {
-		dev->flags |= AHC_DEV_UNCONFIGURED;
-		if (AHC_DV_CMD(cmd) == FALSE)
-			dev->target->flags &= ~AHC_DV_REQUIRED;
+	} else if (aic_get_transaction_status(scb) == CAM_SEL_TIMEOUT) {
+		dev->flags |= AIC_DEV_UNCONFIGURED;
+		if (AIC_DV_CMD(cmd) == FALSE)
+			dev->target->flags &= ~AIC_DV_REQUIRED;
 	}
 	/*
 	 * Start DV for devices that require it assuming the first command
 	 * sent does not result in a selection timeout.
 	 */
-	if (ahc_get_transaction_status(scb) != CAM_SEL_TIMEOUT
-	 && (dev->target->flags & AHC_DV_REQUIRED) != 0)
+	if (aic_get_transaction_status(scb) != CAM_SEL_TIMEOUT
+	 && (dev->target->flags & AIC_DV_REQUIRED) != 0)
 		ahc_linux_start_dv(ahc);
 
 	if (dev->openings == 1
-	 && ahc_get_transaction_status(scb) == CAM_REQ_CMP
-	 && ahc_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL)
+	 && aic_get_transaction_status(scb) == CAM_REQ_CMP
+	 && aic_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL)
 		dev->tag_success_count++;
 	/*
 	 * Some devices deal with temporary internal resource
@@ -4180,7 +4193,7 @@ ahc_done(struct ahc_softc *ahc, struct s
 	 * back to our previous queue depth.
 	 */
 	if ((dev->openings + dev->active) < dev->maxtags
-	 && dev->tag_success_count > AHC_TAG_SUCCESS_INTERVAL) {
+	 && dev->tag_success_count > AIC_TAG_SUCCESS_INTERVAL) {
 		dev->tag_success_count = 0;
 		dev->openings++;
 	}
@@ -4189,32 +4202,61 @@ ahc_done(struct ahc_softc *ahc, struct s
 		dev->commands_since_idle_or_otag = 0;
 
 	if (TAILQ_EMPTY(&dev->busyq)) {
-		if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0
-		 && dev->active == 0
-	 	 && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
+		if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0
+		 && dev->active == 0)
 			ahc_linux_free_device(ahc, dev);
-	} else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) {
+	} else if ((dev->flags & AIC_DEV_ON_RUN_LIST) == 0) {
 		TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links);
-		dev->flags |= AHC_DEV_ON_RUN_LIST;
+		dev->flags |= AIC_DEV_ON_RUN_LIST;
 	}
 
 	if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
 		printf("Recovery SCB completes\n");
-		if (ahc_get_transaction_status(scb) == CAM_BDR_SENT
-		 || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED)
-			ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT);
-		if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) {
-			ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE;
+		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);
+		if ((scb->platform_data->flags & AIC_SCB_UP_EH_SEM) != 0) {
+			scb->platform_data->flags &= ~AIC_SCB_UP_EH_SEM;
 			up(&ahc->platform_data->eh_sem);
+		} else {
+			struct  scb *list_scb;
+
+			/*
+			 * We were able to complete the command successfully,
+			 * so reinstate the timeouts for all other pending
+			 * commands.
+			 */
+			LIST_FOREACH(list_scb,
+				     &ahc->pending_scbs, pending_links) {
+
+				aic_scb_timer_start(list_scb);
+                	}
 		}
 	}
 
+	if ((scb->platform_data->flags & AIC_TIMEOUT_ACTIVE) == 0) {
+		/*
+		 * The completion handler believes that
+		 * commands without active timers running
+		 * have lost the race of completing before
+		 * their timer expires.  Since commands in
+		 * our busy queues do not have timers running,
+		 * appease the mid-layer by adding a timer
+		 * now.  This timer will be immediately
+		 * canceled by the midlayer.
+		 */
+		scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout);
+	}
+
+	if ((scb->platform_data->flags & AIC_RELEASE_SIMQ) != 0)
+		aic_release_simq_locked(ahc);
+
 	ahc_free_scb(ahc, scb);
 	ahc_linux_queue_cmd_complete(ahc, cmd);
 
-	if ((ahc->platform_data->flags & AHC_DV_WAIT_SIMQ_EMPTY) != 0
+	if ((ahc->platform_data->flags & AIC_DV_WAIT_SIMQ_EMPTY) != 0
 	 && LIST_FIRST(&ahc->pending_scbs) == NULL) {
-		ahc->platform_data->flags &= ~AHC_DV_WAIT_SIMQ_EMPTY;
+		ahc->platform_data->flags &= ~AIC_DV_WAIT_SIMQ_EMPTY;
 		up(&ahc->platform_data->dv_sem);
 	}
 		
@@ -4222,7 +4264,7 @@ ahc_done(struct ahc_softc *ahc, struct s
 
 static void
 ahc_linux_handle_scsi_status(struct ahc_softc *ahc,
-			     struct ahc_linux_device *dev, struct scb *scb)
+			     struct aic_linux_device *dev, struct scb *scb)
 {
 	struct	ahc_devinfo devinfo;
 
@@ -4242,7 +4284,7 @@ ahc_linux_handle_scsi_status(struct ahc_
 	 * we don't clobber the device with too many
 	 * commands.
 	 */
-	switch (ahc_get_scsi_status(scb)) {
+	switch (aic_get_scsi_status(scb)) {
 	default:
 		break;
 	case SCSI_STATUS_CHECK_COND:
@@ -4256,13 +4298,15 @@ ahc_linux_handle_scsi_status(struct ahc_
 		 */
 		cmd = scb->io_ctx;
 		if (scb->flags & SCB_SENSE) {
-			u_int sense_size;
+			struct	scsi_sense_data *sense;
+			u_int	sense_size;
+			int	error_code, sense_key, asc, ascq;
 
+			sense = ahc_get_sense_buf(ahc, scb);
 			sense_size = MIN(sizeof(struct scsi_sense_data)
-				       - ahc_get_sense_residual(scb),
+				       - aic_get_sense_residual(scb),
 					 sizeof(cmd->sense_buffer));
-			memcpy(cmd->sense_buffer,
-			       ahc_get_sense_buf(ahc, scb), sense_size);
+			memcpy(cmd->sense_buffer, sense, sense_size);
 			if (sense_size < sizeof(cmd->sense_buffer))
 				memset(&cmd->sense_buffer[sense_size], 0,
 				       sizeof(cmd->sense_buffer) - sense_size);
@@ -4281,6 +4325,23 @@ ahc_linux_handle_scsi_status(struct ahc_
 				printf("\n");
 			}
 #endif
+			/*
+			 * If this is not a DV command and the target
+			 * provides some status that makes us believe
+			 * that the target has changed (power on reset,
+			 * etc.) kick off a DV scan to re-validate the
+			 * device.
+			 */
+	 		if (AIC_DV_CMD(cmd) != 0)
+				break;
+
+			scsi_extract_sense(sense, &error_code,
+					   &sense_key, &asc, &ascq);
+			if (error_code == SSD_CURRENT_ERROR
+			 && sense_key == SSD_KEY_UNIT_ATTENTION
+			 && asc == 0x29
+			 && (ascq == 0 || ascq == 1))
+				dev->target->flags |= AIC_DV_REQUIRED;
 		}
 		break;
 	}
@@ -4317,7 +4378,7 @@ ahc_linux_handle_scsi_status(struct ahc_
 				 * this device.
 				 */
 				if (dev->last_queuefull_same_count
-				 == AHC_LOCK_TAGS_COUNT) {
+				 == AIC_LOCK_TAGS_COUNT) {
 					dev->maxtags = dev->active;
 					ahc_print_path(ahc, scb);
 					printf("Locking max tag count at %d\n",
@@ -4327,10 +4388,10 @@ ahc_linux_handle_scsi_status(struct ahc_
 				dev->tags_on_last_queuefull = dev->active;
 				dev->last_queuefull_same_count = 0;
 			}
-			ahc_set_transaction_status(scb, CAM_REQUEUE_REQ);
-			ahc_set_scsi_status(scb, SCSI_STATUS_OK);
+			aic_set_transaction_status(scb, CAM_REQUEUE_REQ);
+			aic_set_scsi_status(scb, SCSI_STATUS_OK);
 			ahc_platform_set_tags(ahc, &devinfo,
-				     (dev->flags & AHC_DEV_Q_BASIC)
+				     (dev->flags & AIC_DEV_Q_BASIC)
 				   ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED);
 			break;
 		}
@@ -4339,9 +4400,9 @@ ahc_linux_handle_scsi_status(struct ahc_
 		 * as if the target returned BUSY SCSI status.
 		 */
 		dev->openings = 1;
-		ahc_set_scsi_status(scb, SCSI_STATUS_BUSY);
+		aic_set_scsi_status(scb, SCSI_STATUS_BUSY);
 		ahc_platform_set_tags(ahc, &devinfo,
-			     (dev->flags & AHC_DEV_Q_BASIC)
+			     (dev->flags & AIC_DEV_Q_BASIC)
 			   ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED);
 		/* FALLTHROUGH */
 	}
@@ -4351,13 +4412,13 @@ ahc_linux_handle_scsi_status(struct ahc_
 		 * Set a short timer to defer sending commands for
 		 * a bit since Linux will not delay in this case.
 		 */
-		if ((dev->flags & AHC_DEV_TIMER_ACTIVE) != 0) {
+		if ((dev->flags & AIC_DEV_TIMER_ACTIVE) != 0) {
 			printf("%s:%c:%d: Device Timer still active during "
 			       "busy processing\n", ahc_name(ahc),
 				dev->target->channel, dev->target->target);
 			break;
 		}
-		dev->flags |= AHC_DEV_TIMER_ACTIVE;
+		dev->flags |= AIC_DEV_TIMER_ACTIVE;
 		dev->qfrozen++;
 		init_timer(&dev->timer);
 		dev->timer.data = (u_long)dev;
@@ -4384,9 +4445,9 @@ ahc_linux_queue_cmd_complete(struct ahc_
 	 * not guarantee the order that aborted commands will be
 	 * returned to us.
 	 */
-	struct ahc_completeq *completeq;
-	struct ahc_cmd *list_cmd;
-	struct ahc_cmd *acmd;
+	struct aic_completeq *completeq;
+	struct aic_cmd *list_cmd;
+	struct aic_cmd *acmd;
 
 	/*
 	 * Map CAM error codes into Linux Error codes.  We
@@ -4394,10 +4455,10 @@ ahc_linux_queue_cmd_complete(struct ahc_
 	 * full error information available when making
 	 * state change decisions.
 	 */
-	if (AHC_DV_CMD(cmd) == FALSE) {
+	if (AIC_DV_CMD(cmd) == FALSE) {
 		u_int new_status;
 
-		switch (ahc_cmd_get_transaction_status(cmd)) {
+		switch (aic_cmd_get_transaction_status(cmd)) {
 		case CAM_REQ_INPROG:
 		case CAM_REQ_CMP:
 		case CAM_SCSI_STATUS_ERROR:
@@ -4424,7 +4485,17 @@ ahc_linux_queue_cmd_complete(struct ahc_
 			new_status = DID_PARITY;
 			break;
 		case CAM_CMD_TIMEOUT:
-			new_status = DID_TIME_OUT;
+			/*
+			 *  Returning DID_TIME_OUT will 
+			 *  wake up the error recovery
+			 *  thread instead of doing the
+			 *  command retry we desire. Since
+			 *  we have already recovered the
+			 *  command, returning DID_ERROR
+			 *  will cause a retry up to the
+			 *  retry limit for this command.
+			 */
+			new_status = DID_ERROR;
 			break;
 		case CAM_UA_ABORT:
 		case CAM_REQ_CMP_ERR:
@@ -4454,7 +4525,7 @@ ahc_linux_queue_cmd_complete(struct ahc_
 			if (cmd->retries > 0)
 				cmd->retries--;
 			new_status = DID_OK;
-			ahc_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND);
+			aic_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND);
 			cmd->result |= (DRIVER_SENSE << 24);
 			memset(cmd->sense_buffer, 0,
 			       sizeof(cmd->sense_buffer));
@@ -4468,12 +4539,12 @@ ahc_linux_queue_cmd_complete(struct ahc_
 			break;
 		}
 
-		ahc_cmd_set_transaction_status(cmd, new_status);
+		aic_cmd_set_transaction_status(cmd, new_status);
 	}
 
 	completeq = &ahc->platform_data->completeq;
 	list_cmd = TAILQ_FIRST(completeq);
-	acmd = (struct ahc_cmd *)cmd;
+	acmd = (struct aic_cmd *)cmd;
 	while (list_cmd != NULL
 	    && acmd_scsi_cmd(list_cmd).serial_number
 	     < acmd_scsi_cmd(acmd).serial_number)
@@ -4494,7 +4565,7 @@ ahc_linux_filter_inquiry(struct ahc_soft
 	struct	ahc_transinfo *curr;
 	struct	ahc_tmode_tstate *tstate;
 	struct	ahc_syncrate *syncrate;
-	struct	ahc_linux_device *dev;
+	struct	aic_linux_device *dev;
 	u_int	maxsync;
 	u_int	width;
 	u_int	period;
@@ -4517,9 +4588,9 @@ ahc_linux_filter_inquiry(struct ahc_soft
 	sid = (struct scsi_inquiry_data *)dev->target->inq_data;
 	if (SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) {
 
-		dev->flags &= ~AHC_DEV_UNCONFIGURED;
+		dev->flags &= ~AIC_DEV_UNCONFIGURED;
 	} else {
-		dev->flags |= AHC_DEV_UNCONFIGURED;
+		dev->flags |= AIC_DEV_UNCONFIGURED;
 		return;
 	}
 
@@ -4596,82 +4667,38 @@ ahc_linux_filter_inquiry(struct ahc_soft
 static void
 ahc_linux_sem_timeout(u_long arg)
 {
+	struct	scb *scb;
 	struct	ahc_softc *ahc;
 	u_long	s;
 
-	ahc = (struct ahc_softc *)arg;
-
+	scb = (struct scb *)arg;
+	ahc = scb->ahc_softc;
 	ahc_lock(ahc, &s);
-	if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) {
-		ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE;
+	if ((scb->platform_data->flags & AIC_SCB_UP_EH_SEM) != 0) {
+		scb->platform_data->flags &= ~AIC_SCB_UP_EH_SEM;
 		up(&ahc->platform_data->eh_sem);
 	}
 	ahc_unlock(ahc, &s);
 }
 
 static void
-ahc_linux_freeze_simq(struct ahc_softc *ahc)
-{
-	ahc->platform_data->qfrozen++;
-	if (ahc->platform_data->qfrozen == 1) {
-		scsi_block_requests(ahc->platform_data->host);
-
-		/* XXX What about Twin channels? */
-		ahc_platform_abort_scbs(ahc, CAM_TARGET_WILDCARD, ALL_CHANNELS,
-					CAM_LUN_WILDCARD, SCB_LIST_NULL,
-					ROLE_INITIATOR, CAM_REQUEUE_REQ);
-	}
-}
-
-static void
-ahc_linux_release_simq(u_long arg)
-{
-	struct ahc_softc *ahc;
-	u_long s;
-	int    unblock_reqs;
-
-	ahc = (struct ahc_softc *)arg;
-
-	unblock_reqs = 0;
-	ahc_lock(ahc, &s);
-	if (ahc->platform_data->qfrozen > 0)
-		ahc->platform_data->qfrozen--;
-	if (ahc->platform_data->qfrozen == 0)
-		unblock_reqs = 1;
-	if (AHC_DV_SIMQ_FROZEN(ahc)
-	 && ((ahc->platform_data->flags & AHC_DV_WAIT_SIMQ_RELEASE) != 0)) {
-		ahc->platform_data->flags &= ~AHC_DV_WAIT_SIMQ_RELEASE;
-		up(&ahc->platform_data->dv_sem);
-	}
-	ahc_schedule_runq(ahc);
-	ahc_unlock(ahc, &s);
-	/*
-	 * There is still a race here.  The mid-layer
-	 * should keep its own freeze count and use
-	 * a bottom half handler to run the queues
-	 * so we can unblock with our own lock held.
-	 */
-	if (unblock_reqs)
-		scsi_unblock_requests(ahc->platform_data->host);
-}
-
-static void
 ahc_linux_dev_timed_unfreeze(u_long arg)
 {
-	struct ahc_linux_device *dev;
+	struct aic_linux_device *dev;
 	struct ahc_softc *ahc;
 	u_long s;
 
-	dev = (struct ahc_linux_device *)arg;
-	ahc = dev->target->ahc;
+	dev = (struct aic_linux_device *)arg;
+	ahc = dev->target->softc;
 	ahc_lock(ahc, &s);
-	dev->flags &= ~AHC_DEV_TIMER_ACTIVE;
+	dev->flags &= ~AIC_DEV_TIMER_ACTIVE;
 	if (dev->qfrozen > 0)
 		dev->qfrozen--;
 	if (dev->qfrozen == 0
-	 && (dev->flags & AHC_DEV_ON_RUN_LIST) == 0)
+	 && (dev->flags & AIC_DEV_ON_RUN_LIST) == 0)
 		ahc_linux_run_device_queue(ahc, dev);
-	if (TAILQ_EMPTY(&dev->busyq)
+	if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0
+	 && TAILQ_EMPTY(&dev->busyq)
 	 && dev->active == 0)
 		ahc_linux_free_device(ahc, dev);
 	ahc_unlock(ahc, &s);
@@ -4681,9 +4708,9 @@ static int
 ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
 {
 	struct ahc_softc *ahc;
-	struct ahc_cmd *acmd;
-	struct ahc_cmd *list_acmd;
-	struct ahc_linux_device *dev;
+	struct aic_cmd *acmd;
+	struct aic_cmd *list_acmd;
+	struct aic_linux_device *dev;
 	struct scb *pending_scb;
 	u_long s;
 	u_int  saved_scbptr;
@@ -4701,7 +4728,7 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *
 	paused = FALSE;
 	wait = FALSE;
 	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
-	acmd = (struct ahc_cmd *)cmd;
+	acmd = (struct aic_cmd *)cmd;
 
 	printf("%s:%d:%d:%d: Attempting to queue a%s message\n",
 	       ahc_name(ahc), cmd->device->channel,
@@ -4763,13 +4790,24 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *
 		if (flag == SCB_ABORT) {
 			TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe);
 			cmd->result = DID_ABORT << 16;
+			/*
+			 * The completion handler believes that
+			 * commands without active timers running
+			 * have lost the race of completing before
+			 * their timer expires.  Since commands in our
+			 * busy queues do not have timers running,
+			 * appease the mid-layer by adding a timer
+			 * now.  This timer will be immediately
+			 * canceled by the midlayer.
+			 */
+			scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout);
 			ahc_linux_queue_cmd_complete(ahc, cmd);
 			retval = SUCCESS;
 			goto done;
 		}
 	}
 
-	if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0
+	if ((dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED)) == 0
 	 && ahc_search_untagged_queues(ahc, cmd, cmd->device->id,
 				       cmd->device->channel + 'A',
 				       cmd->device->lun,
@@ -4985,10 +5023,10 @@ done:
 		struct timer_list timer;
 		int ret;
 
-		ahc->platform_data->flags |= AHC_UP_EH_SEMAPHORE;
+		pending_scb->platform_data->flags |= AIC_SCB_UP_EH_SEM;
 		spin_unlock_irq(&ahc->platform_data->spin_lock);
 		init_timer(&timer);
-		timer.data = (u_long)ahc;
+		timer.data = (u_long)pending_scb;
 		timer.expires = jiffies + (5 * HZ);
 		timer.function = ahc_linux_sem_timeout;
 		add_timer(&timer);
@@ -5002,7 +5040,7 @@ done:
 		}
 		spin_lock_irq(&ahc->platform_data->spin_lock);
 	}
-	ahc_schedule_runq(ahc);
+	aic_schedule_runq(ahc);
 	ahc_linux_run_complete_queue(ahc);
 	ahc_midlayer_entrypoint_unlock(ahc, &s);
 	return (retval);
@@ -5011,7 +5049,8 @@ done:
 void
 ahc_platform_dump_card_state(struct ahc_softc *ahc)
 {
-	struct ahc_linux_device *dev;
+	struct Scsi_Host *host;
+	struct aic_linux_device *dev;
 	int channel;
 	int maxchannel;
 	int target;
@@ -5019,6 +5058,14 @@ ahc_platform_dump_card_state(struct ahc_
 	int lun;
 	int i;
 
+	host = ahc->platform_data->host;
+	printf("%s: Host Status: Failed(%d) %s%s%s\n",
+	       ahc_name(ahc),
+	       host->host_failed,
+	       host->eh_active ? "eh_active " : "",
+	       host->host_blocked ? "host_blocked " : "",
+	       host->host_self_blocked ? "host_self_blocked " : "");
+	       
 	maxchannel = (ahc->features & AHC_TWIN) ? 1 : 0;
 	maxtarget = (ahc->features & AHC_WIDE) ? 15 : 7;
 	for (channel = 0; channel <= maxchannel; channel++) {
@@ -5026,7 +5073,7 @@ ahc_platform_dump_card_state(struct ahc_
 		for (target = 0; target <=maxtarget; target++) {
 
 			for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
-				struct ahc_cmd *acmd;
+				struct aic_cmd *acmd;
 
 				dev = ahc_linux_get_device(ahc, channel, target,
 							   lun, /*alloc*/FALSE);
@@ -5068,41 +5115,33 @@ static void __exit
 ahc_linux_exit(void)
 {
 	struct ahc_softc *ahc;
-	u_long l;
 
 	/*
-	 * Shutdown DV threads before going into the SCSI mid-layer.
+	 * Shutdown our threads before going into the SCSI mid-layer.
 	 * This avoids situations where the mid-layer locks the entire
 	 * kernel so that waiting for our DV threads to exit leads
 	 * to deadlock.
 	 */
-	ahc_list_lock(&l);
 	TAILQ_FOREACH(ahc, &ahc_tailq, links) {
 
 		ahc_linux_kill_dv_thread(ahc);
+		ahc_terminate_recovery_thread(ahc);
 	}
-	ahc_list_unlock(&l);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-
-	ahc_linux_pci_exit();
-
-	/*
-	 * Get rid of the non-pci devices.  
-	 *
-	 * XXX(hch): switch over eisa support to new LDM-based API
-	 */
-	TAILQ_FOREACH(ahc, &ahc_tailq, links)
-		ahc_linux_release(ahc->platform_data->host);
-#else
-	scsi_unregister_module(MODULE_SCSI_HA, &aic7xxx_driver_template);
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	/*
 	 * In 2.4 we have to unregister from the PCI core _after_
 	 * unregistering from the scsi midlayer to avoid dangling
 	 * references.
 	 */
+	scsi_unregister_module(MODULE_SCSI_HA, &aic7xxx_driver_template);
+#endif
+#ifdef CONFIG_PCI
 	ahc_linux_pci_exit();
 #endif
+#ifdef CONFIG_EISA
+	ahc_linux_eisa_exit();
+#endif
 }
 
 module_init(ahc_linux_init);
diff -puN drivers/scsi/aic7xxx/aic7xxx_osm.h~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7xxx_osm.h
--- 25/drivers/scsi/aic7xxx/aic7xxx_osm.h~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7xxx_osm.h	Wed Dec 24 12:15:38 2003
@@ -53,50 +53,22 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#147 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#166 $
  *
  */
 #ifndef _AIC7XXX_LINUX_H_
 #define _AIC7XXX_LINUX_H_
 
-#include <linux/types.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/smp_lock.h>
 #include <linux/version.h>
-#include <linux/module.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
 
 #ifndef KERNEL_VERSION
 #define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
 #endif
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-#include <linux/interrupt.h> /* For tasklet support. */
 #include <linux/config.h>
-#include <linux/slab.h>
-#else
-#include <linux/malloc.h>
 #endif
 
-/* Core SCSI definitions */
-#define AIC_LIB_PREFIX ahc
-#include "scsi.h"
-#include "hosts.h"
-
-/* Name space conflict with BSD queue macros */
-#ifdef LIST_HEAD
-#undef LIST_HEAD
-#endif
-
-#include "cam.h"
-#include "queue.h"
-#include "scsi_message.h"
-#include "aiclib.h"
-
 /*********************************** Debugging ********************************/
 #ifdef CONFIG_AIC7XXX_DEBUG_ENABLE
 #ifdef CONFIG_AIC7XXX_DEBUG_MASK
@@ -111,42 +83,18 @@
 /* No debugging code. */
 #endif
 
-/************************* Forward Declarations *******************************/
-struct ahc_softc;
-typedef struct pci_dev *ahc_dev_softc_t;
-typedef Scsi_Cmnd      *ahc_io_ctx_t;
-
-/******************************* Byte Order ***********************************/
-#define ahc_htobe16(x)	cpu_to_be16(x)
-#define ahc_htobe32(x)	cpu_to_be32(x)
-#define ahc_htobe64(x)	cpu_to_be64(x)
-#define ahc_htole16(x)	cpu_to_le16(x)
-#define ahc_htole32(x)	cpu_to_le32(x)
-#define ahc_htole64(x)	cpu_to_le64(x)
-
-#define ahc_be16toh(x)	be16_to_cpu(x)
-#define ahc_be32toh(x)	be32_to_cpu(x)
-#define ahc_be64toh(x)	be64_to_cpu(x)
-#define ahc_le16toh(x)	le16_to_cpu(x)
-#define ahc_le32toh(x)	le32_to_cpu(x)
-#define ahc_le64toh(x)	le64_to_cpu(x)
-
-#ifndef LITTLE_ENDIAN
-#define LITTLE_ENDIAN 1234
-#endif
-
-#ifndef BIG_ENDIAN
-#define BIG_ENDIAN 4321
-#endif
+/********************************** Includes **********************************/
+/* Core SCSI definitions */
+#define AIC_LIB_PREFIX ahc
+#define AIC_CONST_PREFIX AHC
 
-#ifndef BYTE_ORDER
-#if defined(__BIG_ENDIAN)
-#define BYTE_ORDER BIG_ENDIAN
-#endif
-#if defined(__LITTLE_ENDIAN)
-#define BYTE_ORDER LITTLE_ENDIAN
+#ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT
+#define AIC_DEBUG_REGISTERS 1
+#else
+#define AIC_DEBUG_REGISTERS 0
 #endif
-#endif /* BYTE_ORDER */
+#define	AIC_CORE_INCLUDE "aic7xxx.h"
+#include "aiclib.h"
 
 /************************* Configuration Data *********************************/
 extern u_int aic7xxx_no_probe;
@@ -154,142 +102,9 @@ extern u_int aic7xxx_allow_memio;
 extern int aic7xxx_detect_complete;
 extern Scsi_Host_Template aic7xxx_driver_template;
 
-/***************************** Bus Space/DMA **********************************/
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17)
-typedef dma_addr_t bus_addr_t;
-#else
-typedef uint32_t bus_addr_t;
-#endif
-typedef uint32_t bus_size_t;
-
-typedef enum {
-	BUS_SPACE_MEMIO,
-	BUS_SPACE_PIO
-} bus_space_tag_t;
-
-typedef union {
-	u_long		  ioport;
-	volatile uint8_t *maddr;
-} bus_space_handle_t;
-
-typedef struct bus_dma_segment
-{
-	bus_addr_t	ds_addr;
-	bus_size_t	ds_len;
-} bus_dma_segment_t;
-
-struct ahc_linux_dma_tag
-{
-	bus_size_t	alignment;
-	bus_size_t	boundary;
-	bus_size_t	maxsize;
-};
-typedef struct ahc_linux_dma_tag* bus_dma_tag_t;
-
-struct ahc_linux_dmamap
-{
-	bus_addr_t	bus_addr;
-};
-typedef struct ahc_linux_dmamap* bus_dmamap_t;
-
-typedef int bus_dma_filter_t(void*, bus_addr_t);
-typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
-
-#define BUS_DMA_WAITOK		0x0
-#define BUS_DMA_NOWAIT		0x1
-#define BUS_DMA_ALLOCNOW	0x2
-#define BUS_DMA_LOAD_SEGS	0x4	/*
-					 * Argument is an S/G list not
-					 * a single buffer.
-					 */
-
-#define BUS_SPACE_MAXADDR	0xFFFFFFFF
-#define BUS_SPACE_MAXADDR_32BIT	0xFFFFFFFF
-#define BUS_SPACE_MAXSIZE_32BIT	0xFFFFFFFF
-
-int	ahc_dma_tag_create(struct ahc_softc *, bus_dma_tag_t /*parent*/,
-			   bus_size_t /*alignment*/, bus_size_t /*boundary*/,
-			   bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/,
-			   bus_dma_filter_t*/*filter*/, void */*filterarg*/,
-			   bus_size_t /*maxsize*/, int /*nsegments*/,
-			   bus_size_t /*maxsegsz*/, int /*flags*/,
-			   bus_dma_tag_t */*dma_tagp*/);
-
-void	ahc_dma_tag_destroy(struct ahc_softc *, bus_dma_tag_t /*tag*/);
-
-int	ahc_dmamem_alloc(struct ahc_softc *, bus_dma_tag_t /*dmat*/,
-			 void** /*vaddr*/, int /*flags*/,
-			 bus_dmamap_t* /*mapp*/);
-
-void	ahc_dmamem_free(struct ahc_softc *, bus_dma_tag_t /*dmat*/,
-			void* /*vaddr*/, bus_dmamap_t /*map*/);
-
-void	ahc_dmamap_destroy(struct ahc_softc *, bus_dma_tag_t /*tag*/,
-			   bus_dmamap_t /*map*/);
-
-int	ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t /*dmat*/,
-			bus_dmamap_t /*map*/, void * /*buf*/,
-			bus_size_t /*buflen*/, bus_dmamap_callback_t *,
-			void */*callback_arg*/, int /*flags*/);
-
-int	ahc_dmamap_unload(struct ahc_softc *, bus_dma_tag_t, bus_dmamap_t);
-
-/*
- * Operations performed by ahc_dmamap_sync().
- */
-#define BUS_DMASYNC_PREREAD	0x01	/* pre-read synchronization */
-#define BUS_DMASYNC_POSTREAD	0x02	/* post-read synchronization */
-#define BUS_DMASYNC_PREWRITE	0x04	/* pre-write synchronization */
-#define BUS_DMASYNC_POSTWRITE	0x08	/* post-write synchronization */
-
-/*
- * XXX
- * ahc_dmamap_sync is only used on buffers allocated with
- * the pci_alloc_consistent() API.  Although I'm not sure how
- * this works on architectures with a write buffer, Linux does
- * not have an API to sync "coherent" memory.  Perhaps we need
- * to do an mb()?
- */
-#define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op)
-
-/************************** Timer DataStructures ******************************/
-typedef struct timer_list ahc_timer_t;
-
-/********************************** Includes **********************************/
-#ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT
-#define AIC_DEBUG_REGISTERS 1
-#else
-#define AIC_DEBUG_REGISTERS 0
-#endif
-#include "aic7xxx.h"
-
-/***************************** Timer Facilities *******************************/
-#define ahc_timer_init init_timer
-#define ahc_timer_stop del_timer_sync
-typedef void ahc_linux_callback_t (u_long);  
-static __inline void ahc_timer_reset(ahc_timer_t *timer, int usec,
-				     ahc_callback_t *func, void *arg);
-static __inline void ahc_scb_timer_reset(struct scb *scb, u_int usec);
-
-static __inline void
-ahc_timer_reset(ahc_timer_t *timer, int usec, ahc_callback_t *func, void *arg)
-{
-	struct ahc_softc *ahc;
-
-	ahc = (struct ahc_softc *)arg;
-	del_timer(timer);
-	timer->data = (u_long)arg;
-	timer->expires = jiffies + (usec * HZ)/1000000;
-	timer->function = (ahc_linux_callback_t*)func;
-	add_timer(timer);
-}
-
-static __inline void
-ahc_scb_timer_reset(struct scb *scb, u_int usec)
-{
-	mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000);
-}
+/***************************** Domain Validation ******************************/
+void ahc_linux_dv_complete(Scsi_Cmnd *cmd);
+void ahc_linux_dv_timeout(struct scsi_cmnd *cmd);
 
 /***************************** SMP support ************************************/
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17)
@@ -304,187 +119,7 @@ ahc_scb_timer_reset(struct scb *scb, u_i
 #define AHC_SCSI_HAS_HOST_LOCK 0
 #endif
 
-#define AIC7XXX_DRIVER_VERSION "6.2.35"
-
-/**************************** Front End Queues ********************************/
-/*
- * Data structure used to cast the Linux struct scsi_cmnd to something
- * that allows us to use the queue macros.  The linux structure has
- * plenty of space to hold the links fields as required by the queue
- * macros, but the queue macors require them to have the correct type.
- */
-struct ahc_cmd_internal {
-	/* Area owned by the Linux scsi layer. */
-	uint8_t	private[offsetof(struct scsi_cmnd, SCp.Status)];
-	union {
-		STAILQ_ENTRY(ahc_cmd)	ste;
-		LIST_ENTRY(ahc_cmd)	le;
-		TAILQ_ENTRY(ahc_cmd)	tqe;
-	} links;
-	uint32_t			end;
-};
-
-struct ahc_cmd {
-	union {
-		struct ahc_cmd_internal	icmd;
-		struct scsi_cmnd	scsi_cmd;
-	} un;
-};
-
-#define acmd_icmd(cmd) ((cmd)->un.icmd)
-#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd)
-#define acmd_links un.icmd.links
-
-/*************************** Device Data Structures ***************************/
-/*
- * A per probed device structure used to deal with some error recovery
- * scenarios that the Linux mid-layer code just doesn't know how to
- * handle.  The structure allocated for a device only becomes persistent
- * after a successfully completed inquiry command to the target when
- * that inquiry data indicates a lun is present.
- */
-TAILQ_HEAD(ahc_busyq, ahc_cmd);
-typedef enum {
-	AHC_DEV_UNCONFIGURED	 = 0x01,
-	AHC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
-	AHC_DEV_TIMER_ACTIVE	 = 0x04, /* Our timer is active */
-	AHC_DEV_ON_RUN_LIST	 = 0x08, /* Queued to be run later */
-	AHC_DEV_Q_BASIC		 = 0x10, /* Allow basic device queuing */
-	AHC_DEV_Q_TAGGED	 = 0x20, /* Allow full SCSI2 command queueing */
-	AHC_DEV_PERIODIC_OTAG	 = 0x40, /* Send OTAG to prevent starvation */
-	AHC_DEV_SLAVE_CONFIGURED = 0x80	 /* slave_configure() has been called */
-} ahc_linux_dev_flags;
-
-struct ahc_linux_target;
-struct ahc_linux_device {
-	TAILQ_ENTRY(ahc_linux_device) links;
-	struct		ahc_busyq busyq;
-
-	/*
-	 * The number of transactions currently
-	 * queued to the device.
-	 */
-	int			active;
-
-	/*
-	 * The currently allowed number of 
-	 * transactions that can be queued to
-	 * the device.  Must be signed for
-	 * conversion from tagged to untagged
-	 * mode where the device may have more
-	 * than one outstanding active transaction.
-	 */
-	int			openings;
-
-	/*
-	 * A positive count indicates that this
-	 * device's queue is halted.
-	 */
-	u_int			qfrozen;
-	
-	/*
-	 * Cumulative command counter.
-	 */
-	u_long			commands_issued;
-
-	/*
-	 * The number of tagged transactions when
-	 * running at our current opening level
-	 * that have been successfully received by
-	 * this device since the last QUEUE FULL.
-	 */
-	u_int			tag_success_count;
-#define AHC_TAG_SUCCESS_INTERVAL 50
-
-	ahc_linux_dev_flags	flags;
-
-	/*
-	 * Per device timer.
-	 */
-	struct timer_list	timer;
-
-	/*
-	 * The high limit for the tags variable.
-	 */
-	u_int			maxtags;
-
-	/*
-	 * The computed number of tags outstanding
-	 * at the time of the last QUEUE FULL event.
-	 */
-	u_int			tags_on_last_queuefull;
-
-	/*
-	 * How many times we have seen a queue full
-	 * with the same number of tags.  This is used
-	 * to stop our adaptive queue depth algorithm
-	 * on devices with a fixed number of tags.
-	 */
-	u_int			last_queuefull_same_count;
-#define AHC_LOCK_TAGS_COUNT 50
-
-	/*
-	 * How many transactions have been queued
-	 * without the device going idle.  We use
-	 * this statistic to determine when to issue
-	 * an ordered tag to prevent transaction
-	 * starvation.  This statistic is only updated
-	 * if the AHC_DEV_PERIODIC_OTAG flag is set
-	 * on this device.
-	 */
-	u_int			commands_since_idle_or_otag;
-#define AHC_OTAG_THRESH	500
-
-	int			lun;
-	Scsi_Device	       *scsi_device;
-	struct			ahc_linux_target *target;
-};
-
-typedef enum {
-	AHC_DV_REQUIRED		 = 0x01,
-	AHC_INQ_VALID		 = 0x02,
-	AHC_BASIC_DV		 = 0x04,
-	AHC_ENHANCED_DV		 = 0x08
-} ahc_linux_targ_flags;
-
-/* DV States */
-typedef enum {
-	AHC_DV_STATE_EXIT = 0,
-	AHC_DV_STATE_INQ_SHORT_ASYNC,
-	AHC_DV_STATE_INQ_ASYNC,
-	AHC_DV_STATE_INQ_ASYNC_VERIFY,
-	AHC_DV_STATE_TUR,
-	AHC_DV_STATE_REBD,
-	AHC_DV_STATE_INQ_VERIFY,
-	AHC_DV_STATE_WEB,
-	AHC_DV_STATE_REB,
-	AHC_DV_STATE_SU,
-	AHC_DV_STATE_BUSY
-} ahc_dv_state;
-
-struct ahc_linux_target {
-	struct ahc_linux_device	 *devices[AHC_NUM_LUNS];
-	int			  channel;
-	int			  target;
-	int			  refcount;
-	struct ahc_transinfo	  last_tinfo;
-	struct ahc_softc	 *ahc;
-	ahc_linux_targ_flags	  flags;
-	struct scsi_inquiry_data *inq_data;
-	/*
-	 * The next "fallback" period to use for narrow/wide transfers.
-	 */
-	uint8_t			  dv_next_narrow_period;
-	uint8_t			  dv_next_wide_period;
-	uint8_t			  dv_max_width;
-	uint8_t			  dv_max_ppr_options;
-	uint8_t			  dv_last_ppr_options;
-	u_int			  dv_echo_size;
-	ahc_dv_state		  dv_state;
-	u_int			  dv_state_retry;
-	char			 *dv_buffer;
-	char			 *dv_buffer1;
-};
+#define AIC7XXX_DRIVER_VERSION "6.3.4"
 
 /********************* Definitions Required by the Core ***********************/
 /*
@@ -506,120 +141,39 @@ extern u_int ahc_linux_nseg;
 #define	AHC_NSEG 128
 #endif
 
-/*
- * Per-SCB OSM storage.
- */
-typedef enum {
-	AHC_UP_EH_SEMAPHORE = 0x1
-} ahc_linux_scb_flags;
-
-struct scb_platform_data {
-	struct ahc_linux_device	*dev;
-	bus_addr_t		 buf_busaddr;
-	uint32_t		 xfer_len;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-	uint32_t		 resid;		/* Transfer residual */
-#endif
-	uint32_t		 sense_resid;	/* Auto-Sense residual */
-	ahc_linux_scb_flags	 flags;
-};
-
-/*
- * Define a structure used for each host adapter.  All members are
- * aligned on a boundary >= the size of the member to honor the
- * alignment restrictions of the various platforms supported by
- * this driver.
- */
-typedef enum {
-	AHC_DV_WAIT_SIMQ_EMPTY	 = 0x01,
-	AHC_DV_WAIT_SIMQ_RELEASE = 0x02,
-	AHC_DV_ACTIVE		 = 0x04,
-	AHC_DV_SHUTDOWN		 = 0x08,
-	AHC_RUN_CMPLT_Q_TIMER	 = 0x10
-} ahc_linux_softc_flags;
-
-TAILQ_HEAD(ahc_completeq, ahc_cmd);
-
-struct ahc_platform_data {
-	/*
-	 * Fields accessed from interrupt context.
-	 */
-	struct ahc_linux_target *targets[AHC_NUM_TARGETS]; 
-	TAILQ_HEAD(, ahc_linux_device) device_runq;
-	struct ahc_completeq	 completeq;
-
-	spinlock_t		 spin_lock;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	struct tasklet_struct	 runq_tasklet;
-#endif
-	u_int			 qfrozen;
-	pid_t			 dv_pid;
-	struct timer_list	 completeq_timer;
-	struct timer_list	 reset_timer;
-	struct semaphore	 eh_sem;
-	struct semaphore	 dv_sem;
-	struct semaphore	 dv_cmd_sem;	/* XXX This needs to be in
-						 * the target struct
-						 */
-	struct scsi_device	*dv_scsi_dev;
-	struct Scsi_Host        *host;		/* pointer to scsi host */
-#define AHC_LINUX_NOIRQ	((uint32_t)~0)
-	uint32_t		 irq;		/* IRQ for this adapter */
-	uint32_t		 bios_address;
-	uint32_t		 mem_busaddr;	/* Mem Base Addr */
-	bus_addr_t		 hw_dma_mask;
-	ahc_linux_softc_flags	 flags;
-};
-
-/************************** OS Utility Wrappers *******************************/
-#define printf printk
-#define M_NOWAIT GFP_ATOMIC
-#define M_WAITOK 0
-#define malloc(size, type, flags) kmalloc(size, flags)
-#define free(ptr, type) kfree(ptr)
-
-static __inline void ahc_delay(long);
-static __inline void
-ahc_delay(long usec)
-{
-	/*
-	 * udelay on Linux can have problems for
-	 * multi-millisecond waits.  Wait at most
-	 * 1024us per call.
-	 */
-	while (usec > 0) {
-		udelay(usec % 1024);
-		usec -= 1024;
-	}
-}
-
+/************************** Error Recovery ************************************/
+static __inline void	ahc_wakeup_recovery_thread(struct ahc_softc *ahc); 
+  
+static __inline void
+ahc_wakeup_recovery_thread(struct ahc_softc *ahc)
+{ 
+	up(&ahc->platform_data->recovery_sem);
+}
+ 
+int			ahc_spawn_recovery_thread(struct ahc_softc *ahc);
+void			ahc_terminate_recovery_thread(struct ahc_softc *ahc);
+void			ahc_set_recoveryscb(struct ahc_softc *ahc,
+					    struct scb *scb);
 
 /***************************** Low Level I/O **********************************/
-#if defined(__powerpc__) || defined(__i386__) || defined(__ia64__)
-#define MMAPIO
-#endif
-
 static __inline uint8_t ahc_inb(struct ahc_softc * ahc, long port);
 static __inline void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val);
 static __inline void ahc_outsb(struct ahc_softc * ahc, long port,
 			       uint8_t *, int count);
 static __inline void ahc_insb(struct ahc_softc * ahc, long port,
 			       uint8_t *, int count);
+static __inline void ahc_flush_device_writes(struct ahc_softc *);
 
 static __inline uint8_t
 ahc_inb(struct ahc_softc * ahc, long port)
 {
 	uint8_t x;
-#ifdef MMAPIO
 
 	if (ahc->tag == BUS_SPACE_MEMIO) {
 		x = readb(ahc->bsh.maddr + port);
 	} else {
 		x = inb(ahc->bsh.ioport + port);
 	}
-#else
-	x = inb(ahc->bsh.ioport + port);
-#endif
 	mb();
 	return (x);
 }
@@ -627,15 +181,11 @@ ahc_inb(struct ahc_softc * ahc, long por
 static __inline void
 ahc_outb(struct ahc_softc * ahc, long port, uint8_t val)
 {
-#ifdef MMAPIO
 	if (ahc->tag == BUS_SPACE_MEMIO) {
 		writeb(val, ahc->bsh.maddr + port);
 	} else {
 		outb(val, ahc->bsh.ioport + port);
 	}
-#else
-	outb(val, ahc->bsh.ioport + port);
-#endif
 	mb();
 }
 
@@ -667,6 +217,13 @@ ahc_insb(struct ahc_softc * ahc, long po
 		*array++ = ahc_inb(ahc, port);
 }
 
+static __inline void
+ahc_flush_device_writes(struct ahc_softc *ahc)
+{
+	/* XXX Is this sufficient for all architectures??? */
+	ahc_inb(ahc, INTSTAT);
+}
+
 /**************************** Initialization **********************************/
 int		ahc_linux_register_host(struct ahc_softc *,
 					Scsi_Host_Template *);
@@ -795,174 +352,41 @@ ahc_list_unlock(unsigned long *flags)
 }
 
 /******************************* PCI Definitions ******************************/
-/*
- * PCIM_xxx: mask to locate subfield in register
- * PCIR_xxx: config register offset
- * PCIC_xxx: device class
- * PCIS_xxx: device subclass
- * PCIP_xxx: device programming interface
- * PCIV_xxx: PCI vendor ID (only required to fixup ancient devices)
- * PCID_xxx: device ID
- */
-#define PCIR_DEVVENDOR		0x00
-#define PCIR_VENDOR		0x00
-#define PCIR_DEVICE		0x02
-#define PCIR_COMMAND		0x04
-#define PCIM_CMD_PORTEN		0x0001
-#define PCIM_CMD_MEMEN		0x0002
-#define PCIM_CMD_BUSMASTEREN	0x0004
-#define PCIM_CMD_MWRICEN	0x0010
-#define PCIM_CMD_PERRESPEN	0x0040
-#define	PCIM_CMD_SERRESPEN	0x0100
-#define PCIR_STATUS		0x06
-#define PCIR_REVID		0x08
-#define PCIR_PROGIF		0x09
-#define PCIR_SUBCLASS		0x0a
-#define PCIR_CLASS		0x0b
-#define PCIR_CACHELNSZ		0x0c
-#define PCIR_LATTIMER		0x0d
-#define PCIR_HEADERTYPE		0x0e
-#define PCIM_MFDEV		0x80
-#define PCIR_BIST		0x0f
-#define PCIR_CAP_PTR		0x34
-
-/* config registers for header type 0 devices */
-#define PCIR_MAPS	0x10
-#define PCIR_SUBVEND_0	0x2c
-#define PCIR_SUBDEV_0	0x2e
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 extern struct pci_driver aic7xxx_pci_driver;
 #endif
 
-typedef enum
-{
-	AHC_POWER_STATE_D0,
-	AHC_POWER_STATE_D1,
-	AHC_POWER_STATE_D2,
-	AHC_POWER_STATE_D3
-} ahc_power_state;
-
-void ahc_power_state_change(struct ahc_softc *ahc,
-			    ahc_power_state new_state);
 /**************************** VL/EISA Routines ********************************/
-int			 aic7770_linux_probe(Scsi_Host_Template *);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) \
+  && (defined(__i386__) || defined(__alpha__)) \
+  && (!defined(CONFIG_EISA)))
+#define CONFIG_EISA
+#endif
+
+#ifdef CONFIG_EISA
+extern uint32_t aic7xxx_probe_eisa_vl;
+void			 ahc_linux_eisa_init(void);
+void			 ahc_linux_eisa_exit(void);
 int			 aic7770_map_registers(struct ahc_softc *ahc,
 					       u_int port);
 int			 aic7770_map_int(struct ahc_softc *ahc, u_int irq);
+#endif
 
 /******************************* PCI Routines *********************************/
+#ifdef CONFIG_PCI
 int			 ahc_linux_pci_init(void);
 void			 ahc_linux_pci_exit(void);
 int			 ahc_pci_map_registers(struct ahc_softc *ahc);
 int			 ahc_pci_map_int(struct ahc_softc *ahc);
+#endif 
 
-static __inline uint32_t ahc_pci_read_config(ahc_dev_softc_t pci,
-					     int reg, int width);
-
-static __inline uint32_t
-ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width)
-{
-	switch (width) {
-	case 1:
-	{
-		uint8_t retval;
-
-		pci_read_config_byte(pci, reg, &retval);
-		return (retval);
-	}
-	case 2:
-	{
-		uint16_t retval;
-		pci_read_config_word(pci, reg, &retval);
-		return (retval);
-	}
-	case 4:
-	{
-		uint32_t retval;
-		pci_read_config_dword(pci, reg, &retval);
-		return (retval);
-	}
-	default:
-		panic("ahc_pci_read_config: Read size too big");
-		/* NOTREACHED */
-		return (0);
-	}
-}
-
-static __inline void ahc_pci_write_config(ahc_dev_softc_t pci,
-					  int reg, uint32_t value,
-					  int width);
-
-static __inline void
-ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width)
-{
-	switch (width) {
-	case 1:
-		pci_write_config_byte(pci, reg, value);
-		break;
-	case 2:
-		pci_write_config_word(pci, reg, value);
-		break;
-	case 4:
-		pci_write_config_dword(pci, reg, value);
-		break;
-	default:
-		panic("ahc_pci_write_config: Write size too big");
-		/* NOTREACHED */
-	}
-}
-
-static __inline int ahc_get_pci_function(ahc_dev_softc_t);
-static __inline int
-ahc_get_pci_function(ahc_dev_softc_t pci)
-{
-	return (PCI_FUNC(pci->devfn));
-}
-
-static __inline int ahc_get_pci_slot(ahc_dev_softc_t);
-static __inline int
-ahc_get_pci_slot(ahc_dev_softc_t pci)
-{
-	return (PCI_SLOT(pci->devfn));
-}
-
-static __inline int ahc_get_pci_bus(ahc_dev_softc_t);
-static __inline int
-ahc_get_pci_bus(ahc_dev_softc_t pci)
-{
-	return (pci->bus->number);
-}
-
-static __inline void ahc_flush_device_writes(struct ahc_softc *);
-static __inline void
-ahc_flush_device_writes(struct ahc_softc *ahc)
-{
-	/* XXX Is this sufficient for all architectures??? */
-	ahc_inb(ahc, INTSTAT);
-}
-
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0)
-#define pci_map_sg(pdev, sg_list, nseg, direction) (nseg)
-#define pci_unmap_sg(pdev, sg_list, nseg, direction)
-#define sg_dma_address(sg) (VIRT_TO_BUS((sg)->address))
-#define sg_dma_len(sg) ((sg)->length)
-#define pci_map_single(pdev, buffer, bufflen, direction) \
-	(VIRT_TO_BUS(buffer))
-#define pci_unmap_single(pdev, buffer, buflen, direction)
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
-#define ahc_pci_set_dma_mask pci_set_dma_mask
+/**************************** Proc FS Support *********************************/
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+int	ahc_linux_proc_info(char *, char **, off_t, int, int, int);
 #else
-/*
- * Always "return" 0 for success.
- */
-#define ahc_pci_set_dma_mask(dev_softc, mask)  			\
-	(((dev_softc)->dma_mask = mask) && 0)
+int	ahc_linux_proc_info(struct Scsi_Host *, char *, char **,
+			    off_t, int, int);
 #endif
-/**************************** Proc FS Support *********************************/
-int	ahc_linux_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
 
 /*************************** Domain Validation ********************************/
 #define AHC_DV_CMD(cmd) ((cmd)->scsi_done == ahc_linux_dv_complete)
@@ -971,194 +395,9 @@ int	ahc_linux_proc_info(struct Scsi_Host
 	 && (ahc)->platform_data->qfrozen == 1)
 
 /*********************** Transaction Access Wrappers *************************/
-static __inline void ahc_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t);
-static __inline void ahc_set_transaction_status(struct scb *, uint32_t);
-static __inline void ahc_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t);
-static __inline void ahc_set_scsi_status(struct scb *, uint32_t);
-static __inline uint32_t ahc_cmd_get_transaction_status(Scsi_Cmnd *cmd);
-static __inline uint32_t ahc_get_transaction_status(struct scb *);
-static __inline uint32_t ahc_cmd_get_scsi_status(Scsi_Cmnd *cmd);
-static __inline uint32_t ahc_get_scsi_status(struct scb *);
-static __inline void ahc_set_transaction_tag(struct scb *, int, u_int);
-static __inline u_long ahc_get_transfer_length(struct scb *);
-static __inline int ahc_get_transfer_dir(struct scb *);
-static __inline void ahc_set_residual(struct scb *, u_long);
-static __inline void ahc_set_sense_residual(struct scb *scb, u_long resid);
-static __inline u_long ahc_get_residual(struct scb *);
-static __inline u_long ahc_get_sense_residual(struct scb *);
-static __inline int ahc_perform_autosense(struct scb *);
-static __inline uint32_t ahc_get_sense_bufsize(struct ahc_softc *,
-					       struct scb *);
-static __inline void ahc_notify_xfer_settings_change(struct ahc_softc *,
-						     struct ahc_devinfo *);
-static __inline void ahc_platform_scb_free(struct ahc_softc *ahc,
-					   struct scb *scb);
-static __inline void ahc_freeze_scb(struct scb *scb);
-
-static __inline
-void ahc_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status)
-{
-	cmd->result &= ~(CAM_STATUS_MASK << 16);
-	cmd->result |= status << 16;
-}
-
-static __inline
-void ahc_set_transaction_status(struct scb *scb, uint32_t status)
-{
-	ahc_cmd_set_transaction_status(scb->io_ctx,status);
-}
-
-static __inline
-void ahc_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status)
-{
-	cmd->result &= ~0xFFFF;
-	cmd->result |= status;
-}
-
-static __inline
-void ahc_set_scsi_status(struct scb *scb, uint32_t status)
-{
-	ahc_cmd_set_scsi_status(scb->io_ctx, status);
-}
-
-static __inline
-uint32_t ahc_cmd_get_transaction_status(Scsi_Cmnd *cmd)
-{
-	return ((cmd->result >> 16) & CAM_STATUS_MASK);
-}
-
-static __inline
-uint32_t ahc_get_transaction_status(struct scb *scb)
-{
-	return (ahc_cmd_get_transaction_status(scb->io_ctx));
-}
-
-static __inline
-uint32_t ahc_cmd_get_scsi_status(Scsi_Cmnd *cmd)
-{
-	return (cmd->result & 0xFFFF);
-}
-
-static __inline
-uint32_t ahc_get_scsi_status(struct scb *scb)
-{
-	return (ahc_cmd_get_scsi_status(scb->io_ctx));
-}
-
-static __inline
-void ahc_set_transaction_tag(struct scb *scb, int enabled, u_int type)
-{
-	/*
-	 * Nothing to do for linux as the incoming transaction
-	 * has no concept of tag/non tagged, etc.
-	 */
-}
-
-static __inline
-u_long ahc_get_transfer_length(struct scb *scb)
-{
-	return (scb->platform_data->xfer_len);
-}
-
-static __inline
-int ahc_get_transfer_dir(struct scb *scb)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40)
-	return (scb->io_ctx->sc_data_direction);
-#else
-	if (scb->io_ctx->bufflen == 0)
-		return (CAM_DIR_NONE);
-
-	switch(scb->io_ctx->cmnd[0]) {
-	case 0x08:  /* READ(6)  */
-	case 0x28:  /* READ(10) */
-	case 0xA8:  /* READ(12) */
-		return (CAM_DIR_IN);
-        case 0x0A:  /* WRITE(6)  */
-        case 0x2A:  /* WRITE(10) */
-        case 0xAA:  /* WRITE(12) */
-		return (CAM_DIR_OUT);
-        default:
-		return (CAM_DIR_NONE);
-        }
-#endif
-}
-
-static __inline
-void ahc_set_residual(struct scb *scb, u_long resid)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	scb->io_ctx->resid = resid;
-#else
-	scb->platform_data->resid = resid;
-#endif
-}
-
-static __inline
-void ahc_set_sense_residual(struct scb *scb, u_long resid)
-{
-	scb->platform_data->sense_resid = resid;
-}
-
-static __inline
-u_long ahc_get_residual(struct scb *scb)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	return (scb->io_ctx->resid);
-#else
-	return (scb->platform_data->resid);
-#endif
-}
-
-static __inline
-u_long ahc_get_sense_residual(struct scb *scb)
-{
-	return (scb->platform_data->sense_resid);
-}
-
-static __inline
-int ahc_perform_autosense(struct scb *scb)
-{
-	/*
-	 * We always perform autosense in Linux.
-	 * On other platforms this is set on a
-	 * per-transaction basis.
-	 */
-	return (1);
-}
-
-static __inline uint32_t
-ahc_get_sense_bufsize(struct ahc_softc *ahc, struct scb *scb)
-{
-	return (sizeof(struct scsi_sense_data));
-}
-
-static __inline void
-ahc_notify_xfer_settings_change(struct ahc_softc *ahc,
-				struct ahc_devinfo *devinfo)
-{
-	/* Nothing to do here for linux */
-}
-
-static __inline void
-ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb)
-{
-	ahc->flags &= ~AHC_RESOURCE_SHORTAGE;
-}
-
 int	ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg);
 void	ahc_platform_free(struct ahc_softc *ahc);
 void	ahc_platform_freeze_devq(struct ahc_softc *ahc, struct scb *scb);
-
-static __inline void
-ahc_freeze_scb(struct scb *scb)
-{
-	if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) {
-                scb->io_ctx->result |= CAM_DEV_QFRZN << 16;
-                scb->platform_data->dev->qfrozen++;
-        }
-}
-
 void	ahc_platform_set_tags(struct ahc_softc *ahc,
 			      struct ahc_devinfo *devinfo, ahc_queue_alg);
 int	ahc_platform_abort_scbs(struct ahc_softc *ahc, int target,
@@ -1175,9 +414,9 @@ void	ahc_print_path(struct ahc_softc *, 
 void	ahc_platform_dump_card_state(struct ahc_softc *ahc);
 
 #ifdef CONFIG_PCI
-#define AHC_PCI_CONFIG 1
+#define AIC_PCI_CONFIG 1
 #else
-#define AHC_PCI_CONFIG 0
+#define AIC_PCI_CONFIG 0
 #endif
 #define bootverbose aic7xxx_verbose
 extern u_int aic7xxx_verbose;
diff -puN drivers/scsi/aic7xxx/aic7xxx_osm_pci.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
--- 25/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c	Wed Dec 24 12:15:38 2003
@@ -36,11 +36,17 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c#45 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c#52 $
  */
 
 #include "aic7xxx_osm.h"
 
+/*
+ * Include aiclib_pci.c as part of our
+ * "module dependencies are hard" work around.
+ */
+#include "aiclib_pci.c"
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
 struct pci_device_id
 {
@@ -51,11 +57,9 @@ static int	ahc_linux_pci_dev_probe(struc
 					const struct pci_device_id *ent);
 static int	ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc,
 						u_long *base);
-#ifdef MMAPIO
 static int	ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
 						 u_long *bus_addr,
 						 uint8_t **maddr);
-#endif /* MMAPIO */
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 static void	ahc_linux_pci_dev_remove(struct pci_dev *pdev);
 
@@ -97,12 +101,14 @@ ahc_linux_pci_dev_remove(struct pci_dev 
 	if (ahc != NULL) {
 		u_long s;
 
+		TAILQ_REMOVE(&ahc_tailq, ahc, links);
+		ahc_list_unlock(&l);
 		ahc_lock(ahc, &s);
 		ahc_intr_enable(ahc, FALSE);
 		ahc_unlock(ahc, &s);
 		ahc_free(ahc);
-	}
-	ahc_list_unlock(&l);
+	} else
+		ahc_list_unlock(&l);
 }
 #endif /* !LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) */
 
@@ -112,7 +118,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *
 	char		 buf[80];
 	bus_addr_t	 mask_39bit;
 	struct		 ahc_softc *ahc;
-	ahc_dev_softc_t	 pci;
+	aic_dev_softc_t	 dev;
 	struct		 ahc_pci_identity *entry;
 	char		*name;
 	int		 error;
@@ -123,7 +129,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *
 	TAILQ_FOREACH(ahc, &ahc_tailq, links) {
 		struct pci_dev *probed_pdev;
 
-		probed_pdev = ahc->dev_softc;
+		probed_pdev = aic_dev_to_pci_dev(ahc->dev_softc);
 		if (probed_pdev->bus->number == pdev->bus->number
 		 && probed_pdev->devfn == pdev->devfn)
 			break;
@@ -133,8 +139,8 @@ ahc_linux_pci_dev_probe(struct pci_dev *
 		return (-ENODEV);
 	}
 
-	pci = pdev;
-	entry = ahc_find_pci_device(pci);
+	dev = aic_pci_dev_to_dev(pdev);
+	entry = ahc_find_pci_device(dev);
 	if (entry == NULL)
 		return (-ENODEV);
 
@@ -144,9 +150,9 @@ ahc_linux_pci_dev_probe(struct pci_dev *
 	 * common detect routine.
 	 */
 	sprintf(buf, "ahc_pci:%d:%d:%d",
-		ahc_get_pci_bus(pci),
-		ahc_get_pci_slot(pci),
-		ahc_get_pci_function(pci));
+		aic_get_pci_bus(dev),
+		aic_get_pci_slot(dev),
+		aic_get_pci_function(dev));
 	name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
 	if (name == NULL)
 		return (-ENOMEM);
@@ -154,6 +160,8 @@ ahc_linux_pci_dev_probe(struct pci_dev *
 	ahc = ahc_alloc(NULL, name);
 	if (ahc == NULL)
 		return (-ENOMEM);
+	ahc->dev_softc = dev;
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 	if (pci_enable_device(pdev)) {
 		ahc_free(ahc);
@@ -161,18 +169,17 @@ ahc_linux_pci_dev_probe(struct pci_dev *
 	}
 	pci_set_master(pdev);
 
-	mask_39bit = (bus_addr_t)(0x7FFFFFFFFFULL & (bus_addr_t)~0);
+	mask_39bit = (bus_addr_t)0x7FFFFFFFFFULL;
 	if (sizeof(bus_addr_t) > 4
 	 && ahc_linux_get_memsize() > 0x80000000
-	 && ahc_pci_set_dma_mask(pdev, mask_39bit) == 0) {
+	 && aic_set_dma_mask(ahc, mask_39bit) == 0) {
 		ahc->flags |= AHC_39BIT_ADDRESSING;
 		ahc->platform_data->hw_dma_mask = mask_39bit;
 	} else {
-		ahc_pci_set_dma_mask(pdev, 0xFFFFFFFF);
+		aic_set_dma_mask(ahc, 0xFFFFFFFF);
 		ahc->platform_data->hw_dma_mask = 0xFFFFFFFF;
 	}
 #endif
-	ahc->dev_softc = pci;
 	error = ahc_pci_config(ahc, entry);
 	if (error != 0) {
 		ahc_free(ahc);
@@ -211,10 +218,8 @@ ahc_linux_pci_init(void)
 	pdev = NULL;
 	class = PCI_CLASS_STORAGE_SCSI << 8;
 	while ((pdev = pci_find_class(class, pdev)) != NULL) {
-		ahc_dev_softc_t pci;
 		int error;
 
-		pci = pdev;
 		error = ahc_linux_pci_dev_probe(pdev, /*pci_devid*/NULL);
 		if (error == 0)
 			found++;
@@ -236,9 +241,9 @@ ahc_linux_pci_reserve_io_region(struct a
 		return (ENOMEM);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	*base = pci_resource_start(ahc->dev_softc, 0);
+	*base = pci_resource_start(aic_pci_dev(ahc), 0);
 #else
-	*base = ahc_pci_read_config(ahc->dev_softc, PCIR_MAPS, 4);
+	*base = aic_pci_read_config(ahc->dev_softc, PCIR_MAPS, 4);
 	*base &= PCI_BASE_ADDRESS_IO_MASK;
 #endif
 	if (*base == 0)
@@ -254,7 +259,6 @@ ahc_linux_pci_reserve_io_region(struct a
 	return (0);
 }
 
-#ifdef MMAPIO
 static int
 ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
 				 u_long *bus_addr,
@@ -267,11 +271,11 @@ ahc_linux_pci_reserve_mem_region(struct 
 
 	error = 0;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	start = pci_resource_start(ahc->dev_softc, 1);
+	start = pci_resource_start(aic_pci_dev(ahc), 1);
 	base_page = start & PAGE_MASK;
 	base_offset = start - base_page;
 #else
-	start = ahc_pci_read_config(ahc->dev_softc, PCIR_MAPS+4, 4);
+	start = aic_pci_read_config(ahc->dev_softc, PCIR_MAPS+4, 4);
 	base_offset = start & PCI_BASE_ADDRESS_MEM_MASK;
 	base_page = base_offset & PAGE_MASK;
 	base_offset -= base_page;
@@ -296,7 +300,6 @@ ahc_linux_pci_reserve_mem_region(struct 
 		error = ENOMEM;
 	return (error);
 }
-#endif /* MMAPIO */
 
 int
 ahc_pci_map_registers(struct ahc_softc *ahc)
@@ -309,17 +312,16 @@ ahc_pci_map_registers(struct ahc_softc *
 	/*
 	 * If its allowed, we prefer memory mapped access.
 	 */
-	command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, 4);
+	command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, 4);
 	command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN);
 	base = 0;
 	maddr = NULL;
-#ifdef MMAPIO
 	error = ahc_linux_pci_reserve_mem_region(ahc, &base, &maddr);
 	if (error == 0) {
 		ahc->platform_data->mem_busaddr = base;
 		ahc->tag = BUS_SPACE_MEMIO;
 		ahc->bsh.maddr = maddr;
-		ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
+		aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
 				     command | PCIM_CMD_MEMEN, 4);
 
 		/*
@@ -330,9 +332,9 @@ ahc_pci_map_registers(struct ahc_softc *
 
 			printf("aic7xxx: 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));
 			iounmap((void *)((u_long)maddr & PAGE_MASK));
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 			release_mem_region(ahc->platform_data->mem_busaddr,
@@ -345,12 +347,11 @@ ahc_pci_map_registers(struct ahc_softc *
 	} else {
 		printf("aic7xxx: PCI%d:%d:%d MEM region 0x%lx "
 		       "unavailable. Cannot memory map device.\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),
 		       base);
 	}
-#endif /* MMAPIO */
 
 	/*
 	 * We always prefer memory mapped access.
@@ -358,20 +359,20 @@ ahc_pci_map_registers(struct ahc_softc *
 	if (maddr == NULL) {
 
 		error = ahc_linux_pci_reserve_io_region(ahc, &base);
-		if (error == 0) {
+		if (error == 0 && ahc_pci_test_register_access(ahc) == 0) {
 			ahc->tag = BUS_SPACE_PIO;
 			ahc->bsh.ioport = base;
 			command |= PCIM_CMD_PORTEN;
 		} else {
 			printf("aic7xxx: PCI%d:%d:%d IO region 0x%lx[0..255] "
 			       "unavailable. Cannot map device.\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),
 			       base);
 		}
 	}
-	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, 4);
+	aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, 4);
 	return (error);
 }
 
@@ -380,49 +381,10 @@ ahc_pci_map_int(struct ahc_softc *ahc)
 {
 	int error;
 
-	error = request_irq(ahc->dev_softc->irq, ahc_linux_isr,
+	error = request_irq(aic_pci_dev(ahc)->irq, ahc_linux_isr,
 			    SA_SHIRQ, "aic7xxx", ahc);
 	if (error == 0)
-		ahc->platform_data->irq = ahc->dev_softc->irq;
+		ahc->platform_data->irq = aic_pci_dev(ahc)->irq;
 	
 	return (-error);
 }
-
-void
-ahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	pci_set_power_state(ahc->dev_softc, new_state);
-#else
-	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*/4);
-			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 
-}
diff -puN drivers/scsi/aic7xxx/aic7xxx_pci.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7xxx_pci.c
--- 25/drivers/scsi/aic7xxx/aic7xxx_pci.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7xxx_pci.c	Wed Dec 24 12:15:38 2003
@@ -39,9 +39,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#66 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#78 $
  */
 
 #ifdef __linux__
@@ -49,14 +47,13 @@
 #include "aic7xxx_inline.h"
 #include "aic7xxx_93cx6.h"
 #else
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 #include <dev/aic7xxx/aic7xxx_osm.h>
 #include <dev/aic7xxx/aic7xxx_inline.h>
 #include <dev/aic7xxx/aic7xxx_93cx6.h>
 #endif
 
-#define AHC_PCI_IOADDR	PCIR_MAPS	/* I/O Address */
-#define AHC_PCI_MEMADDR	(PCIR_MAPS + 4)	/* Mem I/O Address */
-
 static __inline uint64_t
 ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
 {
@@ -76,7 +73,7 @@ ahc_compose_id(u_int device, u_int vendo
 #define ID_9005_SISL_MASK		0x000FFFFF00000000ull
 #define ID_9005_SISL_ID			0x0005900500000000ull
 #define ID_AIC7850			0x5078900400000000ull
-#define ID_AHA_2902_04_10_15_20_30C	0x5078900478509004ull
+#define ID_AHA_2902_04_10_15_20C_30C	0x5078900478509004ull
 #define ID_AIC7855			0x5578900400000000ull
 #define ID_AIC7859			0x3860900400000000ull
 #define ID_AHA_2930CU			0x3860900438699004ull
@@ -133,6 +130,7 @@ ahc_compose_id(u_int device, u_int vendo
 #define ID_AHA_29160C			0x0080900562209005ull
 #define ID_AHA_29160B			0x00809005E2209005ull
 #define ID_AHA_19160B			0x0081900562A19005ull
+#define ID_AHA_2915_30LP		0x0082900502109005ull
 
 #define ID_AIC7896			0x005F9005FFFF9005ull
 #define ID_AIC7896_ARO			0x00539005FFFF9005ull
@@ -245,9 +243,9 @@ struct ahc_pci_identity ahc_pci_ident_ta
 {
 	/* aic7850 based controllers */
 	{
-		ID_AHA_2902_04_10_15_20_30C,
+		ID_AHA_2902_04_10_15_20C_30C,
 		ID_ALL_MASK,
-		"Adaptec 2902/04/10/15/20/30C SCSI adapter",
+		"Adaptec 2902/04/10/15/20C/30C SCSI adapter",
 		ahc_aic785X_setup
 	},
 	/* aic7860 based controllers */
@@ -470,6 +468,12 @@ struct ahc_pci_identity ahc_pci_ident_ta
 		"Adaptec aic7892 Ultra160 SCSI adapter (ARO)",
 		ahc_aic7892_setup
 	},
+	{
+		ID_AHA_2915_30LP,
+		ID_ALL_MASK,
+		"Adaptec 2915/30LP Ultra160 SCSI adapter",
+		ahc_aic7892_setup
+	},
 	/* aic7895 based controllers */	
 	{
 		ID_AHA_2940U_DUAL,
@@ -738,7 +742,7 @@ ahc_9005_subdevinfo_valid(uint16_t devic
 }
 
 struct ahc_pci_identity *
-ahc_find_pci_device(ahc_dev_softc_t pci)
+ahc_find_pci_device(aic_dev_softc_t pci)
 {
 	uint64_t  full_id;
 	uint16_t  device;
@@ -748,10 +752,10 @@ ahc_find_pci_device(ahc_dev_softc_t pci)
 	struct	  ahc_pci_identity *entry;
 	u_int	  i;
 
-	vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
-	device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);
-	subvendor = ahc_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2);
-	subdevice = ahc_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 = ahc_compose_id(device, vendor, subdevice, subvendor);
 
 	/*
@@ -761,7 +765,7 @@ ahc_find_pci_device(ahc_dev_softc_t pci)
 	 * to sanity check it prior to accepting the subdevice
 	 * ID as valid.
 	 */
-	if (ahc_get_pci_function(pci) > 0
+	if (aic_get_pci_function(pci) > 0
 	 && ahc_9005_subdevinfo_valid(vendor, device, subvendor, subdevice)
 	 && SUBID_9005_MFUNCENB(subdevice) == 0)
 		return (NULL);
@@ -798,7 +802,7 @@ ahc_pci_config(struct ahc_softc *ahc, st
 	ahc->chip |= AHC_PCI;
 	ahc->description = entry->name;
 
-	ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
+	aic_power_state_change(ahc, AIC_POWER_STATE_D0);
 
 	error = ahc_pci_map_registers(ahc);
 	if (error != 0)
@@ -812,7 +816,7 @@ ahc_pci_config(struct ahc_softc *ahc, st
 	 */
 	ahc_intr_enable(ahc, FALSE);
 
-	devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
+	devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
 
 	/*
 	 * If we need to support high memory, enable dual
@@ -831,13 +835,13 @@ ahc_pci_config(struct ahc_softc *ahc, st
 	/* Ensure that pci error generation, a test feature, is disabled. */
 	devconfig |= PCIERRGENDIS;
 
-	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
+	aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
 
 	/* Ensure busmastering is enabled */
-	command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
+	command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
 	command |= PCIM_CMD_BUSMASTEREN;
 
-	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2);
+	aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2);
 
 	/* On all PCI adapters, we allow SCB paging */
 	ahc->flags |= AHC_PAGESCBS;
@@ -877,7 +881,7 @@ ahc_pci_config(struct ahc_softc *ahc, st
 		scsiseq = 0;
 	}
 
-	error = ahc_reset(ahc);
+	error = ahc_reset(ahc, /*reinit*/FALSE);
 	if (error != 0)
 		return (ENXIO);
 
@@ -920,14 +924,14 @@ ahc_pci_config(struct ahc_softc *ahc, st
 	ahc_outb(ahc, DSCOMMAND0, dscommand0);
 
 	ahc->pci_cachesize =
-	    ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME,
+	    aic_pci_read_config(ahc->dev_softc, CSIZE_LATTIME,
 				/*bytes*/1) & CACHESIZE;
 	ahc->pci_cachesize *= 4;
 
 	if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0
 	 && ahc->pci_cachesize == 4) {
 
-		ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
+		aic_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
 				     0, /*bytes*/1);
 		ahc->pci_cachesize = 0;
 	}
@@ -939,7 +943,7 @@ ahc_pci_config(struct ahc_softc *ahc, st
 	if ((ahc->features & AHC_ULTRA) != 0) {
 		uint32_t devconfig;
 
-		devconfig = ahc_pci_read_config(ahc->dev_softc,
+		devconfig = aic_pci_read_config(ahc->dev_softc,
 						DEVCONFIG, /*bytes*/4);
 		if ((devconfig & REXTVALID) == 0)
 			ahc->features &= ~AHC_ULTRA;
@@ -1005,11 +1009,11 @@ ahc_pci_config(struct ahc_softc *ahc, st
 	 * that occur during runtime and resume events.
 	 */
 	ahc->bus_softc.pci_softc.devconfig =
-	    ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
+	    aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
 	ahc->bus_softc.pci_softc.command =
-	    ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
+	    aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
 	ahc->bus_softc.pci_softc.csize_lattime =
-	    ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1);
+	    aic_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1);
 	ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0);
 	ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS);
 	if ((ahc->features & AHC_DT) != 0) {
@@ -1063,7 +1067,7 @@ ahc_ext_scbram_present(struct ahc_softc 
 	uint32_t devconfig;
 
 	chip = ahc->chip & AHC_CHIPID_MASK;
-	devconfig = ahc_pci_read_config(ahc->dev_softc,
+	devconfig = aic_pci_read_config(ahc->dev_softc,
 					DEVCONFIG, /*bytes*/4);
 	single_user = (devconfig & MPORTMODE) != 0;
 
@@ -1101,13 +1105,13 @@ ahc_scbram_config(struct ahc_softc *ahc,
 		 * Set the SCB Base addr (highest address bit)
 		 * depending on which channel we are.
 		 */
-		ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc));
+		ahc_outb(ahc, SCBBADDR, aic_get_pci_function(ahc->dev_softc));
 	}
 
 	ahc->flags &= ~AHC_LSCBS_ENABLED;
 	if (large)
 		ahc->flags |= AHC_LSCBS_ENABLED;
-	devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
+	devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
 	if ((ahc->features & AHC_ULTRA2) != 0) {
 		u_int dscommand0;
 
@@ -1140,7 +1144,7 @@ ahc_scbram_config(struct ahc_softc *ahc,
 	else
 		devconfig &= ~EXTSCBPEN;
 
-	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
+	aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
 }
 
 /*
@@ -1263,8 +1267,8 @@ ahc_pci_test_register_access(struct ahc_
 	 * Enable PCI error interrupt status, but suppress NMIs
 	 * generated by SERR raised due to target aborts.
 	 */
-	cmd = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
-	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
+	cmd = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
+	aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
 			     cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);
 
 	/*
@@ -1276,26 +1280,46 @@ ahc_pci_test_register_access(struct ahc_
 	 * use for this test.
 	 */
 	hcntrl = ahc_inb(ahc, HCNTRL);
+
 	if (hcntrl == 0xFF)
 		goto fail;
 
+	if ((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;
+	}
+
 	/*
 	 * Next create a situation where write combining
 	 * or read prefetching could be initiated by the
 	 * CPU or host bridge.  Our device does not support
 	 * either, so look for data corruption and/or flagged
-	 * PCI errors.
+	 * PCI errors.  First pause without causing another
+	 * chip reset.
 	 */
+	hcntrl &= ~CHIPRST;
 	ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
 	while (ahc_is_paused(ahc) == 0)
 		;
+
+	/* Clear any PCI errors that occurred before our driver attached. */
+	status1 = aic_pci_read_config(ahc->dev_softc,
+				      PCIR_STATUS + 1, /*bytes*/1);
+	aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
+			     status1, /*bytes*/1);
+	ahc_outb(ahc, CLRINT, CLRPARERR);
+
 	ahc_outb(ahc, SEQCTL, PERRORDIS);
 	ahc_outb(ahc, SCBPTR, 0);
 	ahc_outl(ahc, SCB_BASE, 0x5aa555aa);
 	if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa)
 		goto fail;
 
-	status1 = ahc_pci_read_config(ahc->dev_softc,
+	status1 = aic_pci_read_config(ahc->dev_softc,
 				      PCIR_STATUS + 1, /*bytes*/1);
 	if ((status1 & STA) != 0)
 		goto fail;
@@ -1304,13 +1328,13 @@ ahc_pci_test_register_access(struct ahc_
 
 fail:
 	/* Silently clear any latched errors. */
-	status1 = ahc_pci_read_config(ahc->dev_softc,
+	status1 = aic_pci_read_config(ahc->dev_softc,
 				      PCIR_STATUS + 1, /*bytes*/1);
-	ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
+	aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
 			     status1, /*bytes*/1);
 	ahc_outb(ahc, CLRINT, CLRPARERR);
 	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);
-	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
+	aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
 	return (error);
 }
 
@@ -1380,6 +1404,10 @@ check_extport(struct ahc_softc *ahc, u_i
 			sd.sd_chip = C56_66;
 		}
 		ahc_release_seeprom(&sd);
+
+		/* Remember the SEEPROM type for later */
+		if (sd.sd_chip == C56_66)
+			ahc->flags |= AHC_LARGE_SEEPROM;
 	}
 
 	if (!have_seeprom) {
@@ -1565,12 +1593,12 @@ ahc_parse_pci_eeprom(struct ahc_softc *a
 		uint32_t devconfig;
 
 		/* Honor the STPWLEVEL settings */
-		devconfig = ahc_pci_read_config(ahc->dev_softc,
+		devconfig = aic_pci_read_config(ahc->dev_softc,
 						DEVCONFIG, /*bytes*/4);
 		devconfig &= ~STPWLEVEL;
 		if ((sc->bios_control & CFSTPWLEVEL) != 0)
 			devconfig |= STPWLEVEL;
-		ahc_pci_write_config(ahc->dev_softc, DEVCONFIG,
+		aic_pci_write_config(ahc->dev_softc, DEVCONFIG,
 				     devconfig, /*bytes*/4);
 	}
 	/* Set SCSICONF info */
@@ -1883,10 +1911,10 @@ aic785X_cable_detect(struct ahc_softc *a
 	ahc_outb(ahc, SPIOCAP, spiocap);
 	ahc_outb(ahc, BRDCTL, BRDRW|BRDCS);
 	ahc_flush_device_writes(ahc);
-	ahc_delay(500);
+	aic_delay(500);
 	ahc_outb(ahc, BRDCTL, 0);
 	ahc_flush_device_writes(ahc);
-	ahc_delay(500);
+	aic_delay(500);
 	brdctl = ahc_inb(ahc, BRDCTL);
 	*internal50_present = (brdctl & BRDDAT5) ? 0 : 1;
 	*externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
@@ -1912,7 +1940,7 @@ ahc_acquire_seeprom(struct ahc_softc *ah
 	SEEPROM_OUTB(sd, sd->sd_MS);
 	wait = 1000;  /* 1 second timeout in msec */
 	while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) {
-		ahc_delay(1000);  /* delay 1 msec */
+		aic_delay(1000);  /* delay 1 msec */
 	}
 	if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) {
 		SEEPROM_OUTB(sd, 0); 
@@ -1992,7 +2020,7 @@ ahc_pci_intr(struct ahc_softc *ahc)
 	if ((error & PCIERRSTAT) == 0)
 		return;
 
-	status1 = ahc_pci_read_config(ahc->dev_softc,
+	status1 = aic_pci_read_config(ahc->dev_softc,
 				      PCIR_STATUS + 1, /*bytes*/1);
 
 	printf("%s: PCI error Interrupt at seqaddr = 0x%x\n",
@@ -2022,7 +2050,7 @@ ahc_pci_intr(struct ahc_softc *ahc)
 	}
 
 	/* Clear latched errors. */
-	ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
+	aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
 			     status1, /*bytes*/1);
 
 	if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) {
@@ -2083,7 +2111,7 @@ static int
 ahc_pci_resume(struct ahc_softc *ahc)
 {
 
-	ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
+	aic_power_state_change(ahc, AIC_POWER_STATE_D0);
 
 	/*
 	 * We assume that the OS has restored our register
@@ -2091,11 +2119,11 @@ ahc_pci_resume(struct ahc_softc *ahc)
 	 * that the OS doesn't know about and rely on our chip
 	 * reset handler to handle the rest.
 	 */
-	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4,
+	aic_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4,
 			     ahc->bus_softc.pci_softc.devconfig);
-	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1,
+	aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1,
 			     ahc->bus_softc.pci_softc.command);
-	ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1,
+	aic_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1,
 			     ahc->bus_softc.pci_softc.csize_lattime);
 	if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) {
 		struct	seeprom_descriptor sd;
@@ -2118,7 +2146,7 @@ ahc_pci_resume(struct ahc_softc *ahc)
 static int
 ahc_aic785X_setup(struct ahc_softc *ahc)
 {
-	ahc_dev_softc_t pci;
+	aic_dev_softc_t pci;
 	uint8_t rev;
 
 	pci = ahc->dev_softc;
@@ -2126,7 +2154,7 @@ ahc_aic785X_setup(struct ahc_softc *ahc)
 	ahc->chip = AHC_AIC7850;
 	ahc->features = AHC_AIC7850_FE;
 	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
-	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
+	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
 	if (rev >= 1)
 		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
 	ahc->instruction_ram_size = 512;
@@ -2136,7 +2164,7 @@ ahc_aic785X_setup(struct ahc_softc *ahc)
 static int
 ahc_aic7860_setup(struct ahc_softc *ahc)
 {
-	ahc_dev_softc_t pci;
+	aic_dev_softc_t pci;
 	uint8_t rev;
 
 	pci = ahc->dev_softc;
@@ -2144,7 +2172,7 @@ ahc_aic7860_setup(struct ahc_softc *ahc)
 	ahc->chip = AHC_AIC7860;
 	ahc->features = AHC_AIC7860_FE;
 	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
-	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
+	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
 	if (rev >= 1)
 		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
 	ahc->instruction_ram_size = 512;
@@ -2211,7 +2239,7 @@ ahc_aha494X_setup(struct ahc_softc *ahc)
 static int
 ahc_aic7880_setup(struct ahc_softc *ahc)
 {
-	ahc_dev_softc_t pci;
+	aic_dev_softc_t pci;
 	uint8_t rev;
 
 	pci = ahc->dev_softc;
@@ -2219,7 +2247,7 @@ ahc_aic7880_setup(struct ahc_softc *ahc)
 	ahc->chip = AHC_AIC7880;
 	ahc->features = AHC_AIC7880_FE;
 	ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
-	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
+	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
 	if (rev >= 1) {
 		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
 	} else {
@@ -2262,7 +2290,7 @@ ahc_aha398XU_setup(struct ahc_softc *ahc
 static int
 ahc_aic7890_setup(struct ahc_softc *ahc)
 {
-	ahc_dev_softc_t pci;
+	aic_dev_softc_t pci;
 	uint8_t rev;
 
 	pci = ahc->dev_softc;
@@ -2270,7 +2298,7 @@ ahc_aic7890_setup(struct ahc_softc *ahc)
 	ahc->chip = AHC_AIC7890;
 	ahc->features = AHC_AIC7890_FE;
 	ahc->flags |= AHC_NEWEEPROM_FMT;
-	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
+	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
 	if (rev == 0)
 		ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG;
 	ahc->instruction_ram_size = 768;
@@ -2293,15 +2321,15 @@ ahc_aic7892_setup(struct ahc_softc *ahc)
 static int
 ahc_aic7895_setup(struct ahc_softc *ahc)
 {
-	ahc_dev_softc_t pci;
+	aic_dev_softc_t pci;
 	uint8_t rev;
 
 	pci = ahc->dev_softc;
-	ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A';
+	ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A';
 	/*
 	 * The 'C' revision of the aic7895 has a few additional features.
 	 */
-	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
+	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
 	if (rev >= 4) {
 		ahc->chip = AHC_AIC7895C;
 		ahc->features = AHC_AIC7895C_FE;
@@ -2317,9 +2345,9 @@ ahc_aic7895_setup(struct ahc_softc *ahc)
 		 * we have.  Disabling MWI reduces performance, so
 		 * turn it on again.
 		 */
-		command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1);
+		command = aic_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1);
 		command |= PCIM_CMD_MWRICEN;
-		ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1);
+		aic_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1);
 		ahc->bugs |= AHC_PCI_MWI_BUG;
 	}
 	/*
@@ -2336,10 +2364,10 @@ ahc_aic7895_setup(struct ahc_softc *ahc)
 	 * Cachesize must also be zero due to stray DAC
 	 * problem when sitting behind some bridges.
 	 */
-	ahc_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1);
-	devconfig = ahc_pci_read_config(pci, DEVCONFIG, /*bytes*/1);
+	aic_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1);
+	devconfig = aic_pci_read_config(pci, DEVCONFIG, /*bytes*/1);
 	devconfig |= MRDCEN;
-	ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1);
+	aic_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1);
 #endif
 	ahc->flags |= AHC_NEWEEPROM_FMT;
 	ahc->instruction_ram_size = 512;
@@ -2349,10 +2377,10 @@ ahc_aic7895_setup(struct ahc_softc *ahc)
 static int
 ahc_aic7896_setup(struct ahc_softc *ahc)
 {
-	ahc_dev_softc_t pci;
+	aic_dev_softc_t pci;
 
 	pci = ahc->dev_softc;
-	ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A';
+	ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A';
 	ahc->chip = AHC_AIC7896;
 	ahc->features = AHC_AIC7896_FE;
 	ahc->flags |= AHC_NEWEEPROM_FMT;
@@ -2364,10 +2392,10 @@ ahc_aic7896_setup(struct ahc_softc *ahc)
 static int
 ahc_aic7899_setup(struct ahc_softc *ahc)
 {
-	ahc_dev_softc_t pci;
+	aic_dev_softc_t pci;
 
 	pci = ahc->dev_softc;
-	ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A';
+	ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A';
 	ahc->chip = AHC_AIC7899;
 	ahc->features = AHC_AIC7899_FE;
 	ahc->flags |= AHC_NEWEEPROM_FMT;
@@ -2398,10 +2426,10 @@ ahc_raid_setup(struct ahc_softc *ahc)
 static int
 ahc_aha394XX_setup(struct ahc_softc *ahc)
 {
-	ahc_dev_softc_t pci;
+	aic_dev_softc_t pci;
 
 	pci = ahc->dev_softc;
-	switch (ahc_get_pci_slot(pci)) {
+	switch (aic_get_pci_slot(pci)) {
 	case AHC_394X_SLOT_CHANNEL_A:
 		ahc->channel = 'A';
 		break;
@@ -2411,7 +2439,7 @@ ahc_aha394XX_setup(struct ahc_softc *ahc
 	default:
 		printf("adapter at unexpected slot %d\n"
 		       "unable to map to a channel\n",
-		       ahc_get_pci_slot(pci));
+		       aic_get_pci_slot(pci));
 		ahc->channel = 'A';
 	}
 	return (0);
@@ -2420,10 +2448,10 @@ ahc_aha394XX_setup(struct ahc_softc *ahc
 static int
 ahc_aha398XX_setup(struct ahc_softc *ahc)
 {
-	ahc_dev_softc_t pci;
+	aic_dev_softc_t pci;
 
 	pci = ahc->dev_softc;
-	switch (ahc_get_pci_slot(pci)) {
+	switch (aic_get_pci_slot(pci)) {
 	case AHC_398X_SLOT_CHANNEL_A:
 		ahc->channel = 'A';
 		break;
@@ -2436,7 +2464,7 @@ ahc_aha398XX_setup(struct ahc_softc *ahc
 	default:
 		printf("adapter at unexpected slot %d\n"
 		       "unable to map to a channel\n",
-		       ahc_get_pci_slot(pci));
+		       aic_get_pci_slot(pci));
 		ahc->channel = 'A';
 		break;
 	}
@@ -2447,10 +2475,10 @@ ahc_aha398XX_setup(struct ahc_softc *ahc
 static int
 ahc_aha494XX_setup(struct ahc_softc *ahc)
 {
-	ahc_dev_softc_t pci;
+	aic_dev_softc_t pci;
 
 	pci = ahc->dev_softc;
-	switch (ahc_get_pci_slot(pci)) {
+	switch (aic_get_pci_slot(pci)) {
 	case AHC_494X_SLOT_CHANNEL_A:
 		ahc->channel = 'A';
 		break;
@@ -2466,7 +2494,7 @@ ahc_aha494XX_setup(struct ahc_softc *ahc
 	default:
 		printf("adapter at unexpected slot %d\n"
 		       "unable to map to a channel\n",
-		       ahc_get_pci_slot(pci));
+		       aic_get_pci_slot(pci));
 		ahc->channel = 'A';
 	}
 	ahc->flags |= AHC_LARGE_SEEPROM;
diff -puN drivers/scsi/aic7xxx/aic7xxx_proc.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7xxx_proc.c
--- 25/drivers/scsi/aic7xxx/aic7xxx_proc.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7xxx_proc.c	Wed Dec 24 12:15:38 2003
@@ -37,7 +37,7 @@
  * String handling code courtesy of Gerard Roudier's <groudier@club-internet.fr>
  * sym driver.
  *
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#27 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#32 $
  */
 #include "aic7xxx_osm.h"
 #include "aic7xxx_inline.h"
@@ -50,7 +50,7 @@ static void	ahc_dump_target_state(struct
 				      u_int our_id, char channel,
 				      u_int target_id, u_int target_offset);
 static void	ahc_dump_device_state(struct info_str *info,
-				      struct ahc_linux_device *dev);
+				      struct aic_linux_device *dev);
 static int	ahc_proc_write_seeprom(struct ahc_softc *ahc,
 				       char *buffer, int length);
 
@@ -141,7 +141,7 @@ ahc_dump_target_state(struct ahc_softc *
 		      u_int our_id, char channel, u_int target_id,
 		      u_int target_offset)
 {
-	struct	ahc_linux_target *targ;
+	struct	aic_linux_target *targ;
 	struct	ahc_initiator_tinfo *tinfo;
 	struct	ahc_tmode_tstate *tstate;
 	int	lun;
@@ -163,7 +163,7 @@ ahc_dump_target_state(struct ahc_softc *
 	ahc_format_transinfo(info, &tinfo->curr);
 
 	for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
-		struct ahc_linux_device *dev;
+		struct aic_linux_device *dev;
 
 		dev = targ->devices[lun];
 
@@ -175,7 +175,7 @@ ahc_dump_target_state(struct ahc_softc *
 }
 
 static void
-ahc_dump_device_state(struct info_str *info, struct ahc_linux_device *dev)
+ahc_dump_device_state(struct info_str *info, struct aic_linux_device *dev)
 {
 	copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
 		  dev->target->channel + 'A', dev->target->target, dev->lun);
@@ -204,7 +204,8 @@ ahc_proc_write_seeprom(struct ahc_softc 
 		ahc_pause(ahc);
 
 	if (length != sizeof(struct seeprom_config)) {
-		printf("ahc_proc_write_seeprom: incorrect buffer size\n");
+		printf("ahc_proc_write_seeprom: incorrect buffer size %d\n",
+		       length);
 		goto done;
 	}
 
@@ -215,7 +216,7 @@ ahc_proc_write_seeprom(struct ahc_softc 
 	}
 
 	sd.sd_ahc = ahc;
-#if AHC_PCI_CONFIG > 0
+#if AIC_PCI_CONFIG > 0
 	if ((ahc->chip & AHC_PCI) != 0) {
 		sd.sd_control_offset = SEECTL;
 		sd.sd_status_offset = SEECTL;
@@ -271,7 +272,7 @@ ahc_proc_write_seeprom(struct ahc_softc 
 				  sizeof(struct seeprom_config)/2);
 		ahc_read_seeprom(&sd, (uint16_t *)ahc->seep_config,
 				 start_addr, sizeof(struct seeprom_config)/2);
-#if AHC_PCI_CONFIG > 0
+#if AIC_PCI_CONFIG > 0
 		if ((ahc->chip & AHC_VL) == 0)
 			ahc_release_seeprom(&sd);
 #endif
@@ -289,8 +290,13 @@ done:
  * Return information to handle /proc support for the driver.
  */
 int
-ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset,
-		  int length, int inout)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ahc_linux_proc_info(char *buffer, char **start, off_t offset,
+		    int length, int hostno, int inout)
+#else
+ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
+		    off_t offset, int length, int inout)
+#endif
 {
 	struct	ahc_softc *ahc;
 	struct	info_str info;
@@ -302,10 +308,14 @@ ahc_linux_proc_info(struct Scsi_Host *sh
 
 	retval = -EINVAL;
 	ahc_list_lock(&s);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	TAILQ_FOREACH(ahc, &ahc_tailq, links) {
-		if (ahc->platform_data->host == shost)
+		if (ahc->platform_data->host->host_no == hostno)
 			break;
 	}
+#else
+	ahc = ahc_find_softc(*(struct ahc_softc **)shost->hostdata);
+#endif
 
 	if (ahc == NULL)
 		goto done;
diff -puN drivers/scsi/aic7xxx/aic7xxx.reg~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7xxx.reg
--- 25/drivers/scsi/aic7xxx/aic7xxx.reg~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7xxx.reg	Wed Dec 24 12:15:38 2003
@@ -39,7 +39,7 @@
  *
  * $FreeBSD$
  */
-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
@@ -1306,7 +1306,6 @@ scratch_ram {
 	 */
 	MWI_RESIDUAL {
 		size		1
-		alias	TARG_IMMEDIATE_SCB
 	}
 	/*
 	 * SCBID of the next SCB to be started by the controller.
@@ -1461,6 +1460,7 @@ scratch_ram {
 	 */
 	LAST_MSG {
 		size		1
+		alias	TARG_IMMEDIATE_SCB
 	}
 
 	/*
diff -puN drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
--- 25/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped	Wed Dec 24 12:15:38 2003
@@ -2,8 +2,8 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
  */
 typedef int (ahc_reg_print_t)(u_int, u_int *, u_int);
 typedef struct ahc_reg_parse_entry {
@@ -1298,7 +1298,6 @@ ahc_reg_print_t ahc_sg_cache_pre_print;
 #define	CMDSIZE_TABLE_TAIL		0x34
 
 #define	MWI_RESIDUAL    		0x38
-#define	TARG_IMMEDIATE_SCB		0x38
 
 #define	NEXT_QUEUED_SCB 		0x39
 
@@ -1380,6 +1379,7 @@ ahc_reg_print_t ahc_sg_cache_pre_print;
 #define	RETURN_2        		0x52
 
 #define	LAST_MSG        		0x53
+#define	TARG_IMMEDIATE_SCB		0x53
 
 #define	SCSISEQ_TEMPLATE		0x54
 #define		ENSELO          	0x40
diff -puN drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
--- 25/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped	Wed Dec 24 12:15:38 2003
@@ -2,8 +2,8 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#54 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#38 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
  */
 
 #include "aic7xxx_osm.h"
@@ -747,13 +747,6 @@ ahc_scsiseq_template_print(u_int regvalu
 	    0x54, regvalue, cur_col, wrap));
 }
 
-int
-ahc_data_count_odd_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
-	return (ahc_print_register(NULL, 0, "DATA_COUNT_ODD",
-	    0x55, regvalue, cur_col, wrap));
-}
-
 static ahc_reg_parse_entry_t HA_274_BIOSGLOBAL_parse_table[] = {
 	{ "HA_274_EXTENDED_TRANS",0x01, 0x01 }
 };
@@ -1416,13 +1409,14 @@ ahc_scb_scsiid_print(u_int regvalue, u_i
 }
 
 static ahc_reg_parse_entry_t SCB_LUN_parse_table[] = {
-	{ "LID",		0xff, 0xff }
+	{ "SCB_XFERLEN_ODD",	0x80, 0x80 },
+	{ "LID",		0x3f, 0x3f }
 };
 
 int
 ahc_scb_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahc_print_register(SCB_LUN_parse_table, 1, "SCB_LUN",
+	return (ahc_print_register(SCB_LUN_parse_table, 2, "SCB_LUN",
 	    0xba, regvalue, cur_col, wrap));
 }
 
@@ -1662,28 +1656,26 @@ ahc_dff_thrsh_print(u_int regvalue, u_in
 static ahc_reg_parse_entry_t SG_CACHE_SHADOW_parse_table[] = {
 	{ "LAST_SEG_DONE",	0x01, 0x01 },
 	{ "LAST_SEG",		0x02, 0x02 },
-	{ "ODD_SEG",		0x04, 0x04 },
 	{ "SG_ADDR_MASK",	0xf8, 0xf8 }
 };
 
 int
 ahc_sg_cache_shadow_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahc_print_register(SG_CACHE_SHADOW_parse_table, 4, "SG_CACHE_SHADOW",
+	return (ahc_print_register(SG_CACHE_SHADOW_parse_table, 3, "SG_CACHE_SHADOW",
 	    0xfc, regvalue, cur_col, wrap));
 }
 
 static ahc_reg_parse_entry_t SG_CACHE_PRE_parse_table[] = {
 	{ "LAST_SEG_DONE",	0x01, 0x01 },
 	{ "LAST_SEG",		0x02, 0x02 },
-	{ "ODD_SEG",		0x04, 0x04 },
 	{ "SG_ADDR_MASK",	0xf8, 0xf8 }
 };
 
 int
 ahc_sg_cache_pre_print(u_int regvalue, u_int *cur_col, u_int wrap)
 {
-	return (ahc_print_register(SG_CACHE_PRE_parse_table, 4, "SG_CACHE_PRE",
+	return (ahc_print_register(SG_CACHE_PRE_parse_table, 3, "SG_CACHE_PRE",
 	    0xfc, regvalue, cur_col, wrap));
 }
 
diff -puN drivers/scsi/aic7xxx/aic7xxx.seq~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7xxx.seq
--- 25/drivers/scsi/aic7xxx/aic7xxx.seq~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7xxx.seq	Wed Dec 24 12:15:38 2003
@@ -40,7 +40,7 @@
  * $FreeBSD$
  */
 
-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_"
 
@@ -679,6 +679,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;
@@ -1097,7 +1098,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;
 			}
 		}
diff -puN drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
--- 25/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped	Wed Dec 24 12:15:38 2003
@@ -2,13 +2,13 @@
  * DO NOT EDIT - This file is automatically generated
  *		 from the following source files:
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
  */
 static uint8_t seqprog[] = {
 	0xb2, 0x00, 0x00, 0x08,
 	0xf7, 0x11, 0x22, 0x08,
-	0x00, 0x65, 0xec, 0x59,
+	0x00, 0x65, 0xee, 0x59,
 	0xf7, 0x01, 0x02, 0x08,
 	0xff, 0x6a, 0x24, 0x08,
 	0x40, 0x00, 0x40, 0x68,
@@ -21,15 +21,15 @@ static uint8_t seqprog[] = {
 	0x01, 0x4d, 0xc8, 0x30,
 	0x00, 0x4c, 0x12, 0x70,
 	0x01, 0x39, 0xa2, 0x30,
-	0x00, 0x6a, 0xc0, 0x5e,
+	0x00, 0x6a, 0xc2, 0x5e,
 	0x01, 0x51, 0x20, 0x31,
 	0x01, 0x57, 0xae, 0x00,
 	0x0d, 0x6a, 0x76, 0x00,
-	0x00, 0x51, 0x12, 0x5e,
+	0x00, 0x51, 0x14, 0x5e,
 	0x01, 0x51, 0xc8, 0x30,
 	0x00, 0x39, 0xc8, 0x60,
 	0x00, 0xbb, 0x30, 0x70,
-	0xc1, 0x6a, 0xd8, 0x5e,
+	0xc1, 0x6a, 0xda, 0x5e,
 	0x01, 0xbf, 0x72, 0x30,
 	0x01, 0x40, 0x7e, 0x31,
 	0x01, 0x90, 0x80, 0x30,
@@ -49,10 +49,10 @@ static uint8_t seqprog[] = {
 	0x08, 0x6a, 0x78, 0x00,
 	0x01, 0x50, 0xc8, 0x30,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x48, 0x6a, 0xfc, 0x5d,
+	0x48, 0x6a, 0xfe, 0x5d,
 	0x01, 0x6a, 0xdc, 0x01,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x48, 0x6a, 0xfc, 0x5d,
+	0x48, 0x6a, 0xfe, 0x5d,
 	0x01, 0x6a, 0x26, 0x01,
 	0xf0, 0x19, 0x7a, 0x08,
 	0x0f, 0x18, 0xc8, 0x08,
@@ -93,7 +93,7 @@ static uint8_t seqprog[] = {
 	0x00, 0x65, 0x20, 0x41,
 	0x02, 0x57, 0xae, 0x00,
 	0x00, 0x65, 0x9e, 0x40,
-	0x61, 0x6a, 0xd8, 0x5e,
+	0x61, 0x6a, 0xda, 0x5e,
 	0x08, 0x51, 0x20, 0x71,
 	0x02, 0x0b, 0xb2, 0x78,
 	0x00, 0x65, 0xae, 0x40,
@@ -106,7 +106,7 @@ static uint8_t seqprog[] = {
 	0x80, 0x3d, 0x7a, 0x00,
 	0x20, 0x6a, 0x16, 0x00,
 	0x00, 0x65, 0xcc, 0x41,
-	0x00, 0x65, 0xb2, 0x5e,
+	0x00, 0x65, 0xb4, 0x5e,
 	0x00, 0x65, 0x12, 0x40,
 	0x20, 0x11, 0xd2, 0x68,
 	0x20, 0x6a, 0x18, 0x00,
@@ -140,27 +140,27 @@ static uint8_t seqprog[] = {
 	0x80, 0x0b, 0xc4, 0x79,
 	0x12, 0x01, 0x02, 0x00,
 	0x01, 0xab, 0xac, 0x30,
-	0xe4, 0x6a, 0x6e, 0x5d,
+	0xe4, 0x6a, 0x70, 0x5d,
 	0x40, 0x6a, 0x16, 0x00,
-	0x80, 0x3e, 0x84, 0x5d,
+	0x80, 0x3e, 0x86, 0x5d,
 	0x20, 0xb8, 0x18, 0x79,
-	0x20, 0x6a, 0x84, 0x5d,
-	0x00, 0xab, 0x84, 0x5d,
+	0x20, 0x6a, 0x86, 0x5d,
+	0x00, 0xab, 0x86, 0x5d,
 	0x01, 0xa9, 0x78, 0x30,
 	0x10, 0xb8, 0x20, 0x79,
-	0xe4, 0x6a, 0x6e, 0x5d,
+	0xe4, 0x6a, 0x70, 0x5d,
 	0x00, 0x65, 0xae, 0x40,
 	0x10, 0x03, 0x3c, 0x69,
 	0x08, 0x3c, 0x5a, 0x69,
 	0x04, 0x3c, 0x92, 0x69,
 	0x02, 0x3c, 0x98, 0x69,
 	0x01, 0x3c, 0x44, 0x79,
-	0xff, 0x6a, 0x70, 0x00,
+	0xff, 0x6a, 0xa6, 0x00,
 	0x00, 0x65, 0xa4, 0x59,
-	0x00, 0x6a, 0xc0, 0x5e,
-	0xff, 0x38, 0x30, 0x71,
+	0x00, 0x6a, 0xc2, 0x5e,
+	0xff, 0x53, 0x30, 0x71,
 	0x0d, 0x6a, 0x76, 0x00,
-	0x00, 0x38, 0x12, 0x5e,
+	0x00, 0x53, 0x14, 0x5e,
 	0x00, 0x65, 0xea, 0x58,
 	0x12, 0x01, 0x02, 0x00,
 	0x00, 0x65, 0x18, 0x41,
@@ -168,10 +168,10 @@ static uint8_t seqprog[] = {
 	0x00, 0x65, 0xf2, 0x58,
 	0xfd, 0x57, 0xae, 0x08,
 	0x00, 0x65, 0xae, 0x40,
-	0xe4, 0x6a, 0x6e, 0x5d,
+	0xe4, 0x6a, 0x70, 0x5d,
 	0x20, 0x3c, 0x4a, 0x79,
-	0x02, 0x6a, 0x84, 0x5d,
-	0x04, 0x6a, 0x84, 0x5d,
+	0x02, 0x6a, 0x86, 0x5d,
+	0x04, 0x6a, 0x86, 0x5d,
 	0x01, 0x03, 0x4c, 0x69,
 	0xf7, 0x11, 0x22, 0x08,
 	0xff, 0x6a, 0x24, 0x08,
@@ -182,13 +182,13 @@ static uint8_t seqprog[] = {
 	0x80, 0x86, 0xc8, 0x08,
 	0x01, 0x4f, 0xc8, 0x30,
 	0x00, 0x50, 0x6c, 0x61,
-	0xc4, 0x6a, 0x6e, 0x5d,
+	0xc4, 0x6a, 0x70, 0x5d,
 	0x40, 0x3c, 0x68, 0x79,
-	0x28, 0x6a, 0x84, 0x5d,
+	0x28, 0x6a, 0x86, 0x5d,
 	0x00, 0x65, 0x4c, 0x41,
-	0x08, 0x6a, 0x84, 0x5d,
+	0x08, 0x6a, 0x86, 0x5d,
 	0x00, 0x65, 0x4c, 0x41,
-	0x84, 0x6a, 0x6e, 0x5d,
+	0x84, 0x6a, 0x70, 0x5d,
 	0x00, 0x65, 0xf2, 0x58,
 	0x01, 0x66, 0xc8, 0x30,
 	0x01, 0x64, 0xd8, 0x31,
@@ -208,16 +208,16 @@ static uint8_t seqprog[] = {
 	0xf7, 0x3c, 0x78, 0x08,
 	0x00, 0x65, 0x20, 0x41,
 	0x40, 0xaa, 0x7e, 0x10,
-	0x04, 0xaa, 0x6e, 0x5d,
-	0x00, 0x65, 0x56, 0x42,
-	0xc4, 0x6a, 0x6e, 0x5d,
+	0x04, 0xaa, 0x70, 0x5d,
+	0x00, 0x65, 0x58, 0x42,
+	0xc4, 0x6a, 0x70, 0x5d,
 	0xc0, 0x6a, 0x7e, 0x00,
-	0x00, 0xa8, 0x84, 0x5d,
+	0x00, 0xa8, 0x86, 0x5d,
 	0xe4, 0x6a, 0x06, 0x00,
-	0x00, 0x6a, 0x84, 0x5d,
+	0x00, 0x6a, 0x86, 0x5d,
 	0x00, 0x65, 0x4c, 0x41,
 	0x10, 0x3c, 0xa8, 0x69,
-	0x00, 0xbb, 0x8a, 0x44,
+	0x00, 0xbb, 0x8c, 0x44,
 	0x18, 0x6a, 0xda, 0x01,
 	0x01, 0x69, 0xd8, 0x31,
 	0x1c, 0x6a, 0xd0, 0x01,
@@ -227,31 +227,32 @@ static uint8_t seqprog[] = {
 	0x01, 0x93, 0x26, 0x01,
 	0x03, 0x6a, 0x2a, 0x01,
 	0x01, 0x69, 0x32, 0x31,
-	0x1c, 0x6a, 0xe0, 0x5d,
+	0x1c, 0x6a, 0xe2, 0x5d,
 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0xa8, 0x5e,
+	0x00, 0x65, 0xaa, 0x5e,
 	0x01, 0x50, 0xa0, 0x18,
 	0x02, 0x6a, 0x22, 0x05,
 	0x1a, 0x01, 0x02, 0x00,
 	0x80, 0x6a, 0x74, 0x00,
 	0x40, 0x6a, 0x78, 0x00,
 	0x40, 0x6a, 0x16, 0x00,
-	0x00, 0x65, 0xd8, 0x5d,
+	0x00, 0x65, 0xda, 0x5d,
 	0x01, 0x3f, 0xc8, 0x30,
-	0xbf, 0x64, 0x56, 0x7a,
-	0x80, 0x64, 0x9e, 0x73,
-	0xa0, 0x64, 0x00, 0x74,
-	0xc0, 0x64, 0xf4, 0x73,
-	0xe0, 0x64, 0x30, 0x74,
-	0x01, 0x6a, 0xd8, 0x5e,
+	0xbf, 0x64, 0x58, 0x7a,
+	0x80, 0x64, 0xa0, 0x73,
+	0xa0, 0x64, 0x02, 0x74,
+	0xc0, 0x64, 0xf6, 0x73,
+	0xe0, 0x64, 0x32, 0x74,
+	0x01, 0x6a, 0xda, 0x5e,
 	0x00, 0x65, 0xcc, 0x41,
 	0xf7, 0x11, 0x22, 0x08,
 	0x01, 0x06, 0xd4, 0x30,
 	0xff, 0x6a, 0x24, 0x08,
 	0xf7, 0x01, 0x02, 0x08,
-	0x09, 0x0c, 0xe6, 0x79,
+	0xc0, 0x6a, 0x78, 0x00,
+	0x09, 0x0c, 0xe8, 0x79,
 	0x08, 0x0c, 0x04, 0x68,
-	0xb1, 0x6a, 0xd8, 0x5e,
+	0xb1, 0x6a, 0xda, 0x5e,
 	0xff, 0x6a, 0x26, 0x09,
 	0x12, 0x01, 0x02, 0x00,
 	0x02, 0x6a, 0x08, 0x30,
@@ -264,29 +265,29 @@ static uint8_t seqprog[] = {
 	0x00, 0xa5, 0x4a, 0x21,
 	0x00, 0xa6, 0x4c, 0x21,
 	0x00, 0xa7, 0x4e, 0x25,
-	0x08, 0xeb, 0xdc, 0x7e,
-	0x80, 0xeb, 0x06, 0x7a,
+	0x08, 0xeb, 0xde, 0x7e,
+	0x80, 0xeb, 0x08, 0x7a,
 	0xff, 0x6a, 0xd6, 0x09,
-	0x08, 0xeb, 0x0a, 0x6a,
+	0x08, 0xeb, 0x0c, 0x6a,
 	0xff, 0x6a, 0xd4, 0x0c,
-	0x80, 0xa3, 0xdc, 0x6e,
-	0x88, 0xeb, 0x20, 0x72,
-	0x08, 0xeb, 0xdc, 0x6e,
-	0x04, 0xea, 0x24, 0xe2,
-	0x08, 0xee, 0xdc, 0x6e,
+	0x80, 0xa3, 0xde, 0x6e,
+	0x88, 0xeb, 0x22, 0x72,
+	0x08, 0xeb, 0xde, 0x6e,
+	0x04, 0xea, 0x26, 0xe2,
+	0x08, 0xee, 0xde, 0x6e,
 	0x04, 0x6a, 0xd0, 0x81,
 	0x05, 0xa4, 0xc0, 0x89,
 	0x03, 0xa5, 0xc2, 0x31,
 	0x09, 0x6a, 0xd6, 0x05,
-	0x00, 0x65, 0x08, 0x5a,
+	0x00, 0x65, 0x0a, 0x5a,
 	0x06, 0xa4, 0xd4, 0x89,
-	0x80, 0x94, 0xdc, 0x7e,
+	0x80, 0x94, 0xde, 0x7e,
 	0x07, 0xe9, 0x10, 0x31,
 	0x01, 0xe9, 0x46, 0x31,
-	0x00, 0xa3, 0xba, 0x5e,
-	0x00, 0x65, 0xfa, 0x59,
+	0x00, 0xa3, 0xbc, 0x5e,
+	0x00, 0x65, 0xfc, 0x59,
 	0x01, 0xa4, 0xca, 0x30,
-	0x80, 0xa3, 0x34, 0x7a,
+	0x80, 0xa3, 0x36, 0x7a,
 	0x02, 0x65, 0xca, 0x00,
 	0x01, 0x65, 0xf8, 0x31,
 	0x80, 0x93, 0x26, 0x01,
@@ -294,162 +295,162 @@ static uint8_t seqprog[] = {
 	0x01, 0x8c, 0xc8, 0x30,
 	0x00, 0x88, 0xc8, 0x18,
 	0x02, 0x64, 0xc8, 0x88,
-	0xff, 0x64, 0xdc, 0x7e,
-	0xff, 0x8d, 0x4a, 0x6a,
-	0xff, 0x8e, 0x4a, 0x6a,
+	0xff, 0x64, 0xde, 0x7e,
+	0xff, 0x8d, 0x4c, 0x6a,
+	0xff, 0x8e, 0x4c, 0x6a,
 	0x03, 0x8c, 0xd4, 0x98,
-	0x00, 0x65, 0xdc, 0x56,
+	0x00, 0x65, 0xde, 0x56,
 	0x01, 0x64, 0x70, 0x30,
 	0xff, 0x64, 0xc8, 0x10,
 	0x01, 0x64, 0xc8, 0x18,
 	0x00, 0x8c, 0x18, 0x19,
 	0xff, 0x8d, 0x1a, 0x21,
 	0xff, 0x8e, 0x1c, 0x25,
-	0xc0, 0x3c, 0x5a, 0x7a,
-	0x21, 0x6a, 0xd8, 0x5e,
+	0xc0, 0x3c, 0x5c, 0x7a,
+	0x21, 0x6a, 0xda, 0x5e,
 	0xa8, 0x6a, 0x76, 0x00,
 	0x79, 0x6a, 0x76, 0x00,
-	0x40, 0x3f, 0x62, 0x6a,
+	0x40, 0x3f, 0x64, 0x6a,
 	0x04, 0x3b, 0x76, 0x00,
 	0x04, 0x6a, 0xd4, 0x81,
-	0x20, 0x3c, 0x6a, 0x7a,
-	0x51, 0x6a, 0xd8, 0x5e,
-	0x00, 0x65, 0x82, 0x42,
+	0x20, 0x3c, 0x6c, 0x7a,
+	0x51, 0x6a, 0xda, 0x5e,
+	0x00, 0x65, 0x84, 0x42,
 	0x20, 0x3c, 0x78, 0x00,
-	0x00, 0xb3, 0xba, 0x5e,
+	0x00, 0xb3, 0xbc, 0x5e,
 	0x07, 0xac, 0x10, 0x31,
 	0x05, 0xb3, 0x46, 0x31,
 	0x88, 0x6a, 0xcc, 0x00,
-	0xac, 0x6a, 0xee, 0x5d,
+	0xac, 0x6a, 0xf0, 0x5d,
 	0xa3, 0x6a, 0xcc, 0x00,
-	0xb3, 0x6a, 0xf2, 0x5d,
-	0x00, 0x65, 0x3a, 0x5a,
+	0xb3, 0x6a, 0xf4, 0x5d,
+	0x00, 0x65, 0x3c, 0x5a,
 	0xfd, 0xa4, 0x48, 0x09,
 	0x03, 0x8c, 0x10, 0x30,
-	0x00, 0x65, 0xe6, 0x5d,
-	0x01, 0xa4, 0x94, 0x7a,
+	0x00, 0x65, 0xe8, 0x5d,
+	0x01, 0xa4, 0x96, 0x7a,
 	0x04, 0x3b, 0x76, 0x08,
 	0x01, 0x3b, 0x26, 0x31,
 	0x80, 0x02, 0x04, 0x00,
-	0x10, 0x0c, 0x8a, 0x7a,
-	0x03, 0x9e, 0x8c, 0x6a,
+	0x10, 0x0c, 0x8c, 0x7a,
+	0x03, 0x9e, 0x8e, 0x6a,
 	0x7f, 0x02, 0x04, 0x08,
-	0x91, 0x6a, 0xd8, 0x5e,
+	0x91, 0x6a, 0xda, 0x5e,
 	0x00, 0x65, 0xcc, 0x41,
 	0x01, 0xa4, 0xca, 0x30,
-	0x80, 0xa3, 0x9a, 0x7a,
+	0x80, 0xa3, 0x9c, 0x7a,
 	0x02, 0x65, 0xca, 0x00,
 	0x01, 0x65, 0xf8, 0x31,
 	0x01, 0x3b, 0x26, 0x31,
-	0x00, 0x65, 0x0e, 0x5a,
-	0x01, 0xfc, 0xa8, 0x6a,
-	0x80, 0x0b, 0x9e, 0x6a,
-	0x10, 0x0c, 0x9e, 0x7a,
-	0x20, 0x93, 0x9e, 0x6a,
+	0x00, 0x65, 0x10, 0x5a,
+	0x01, 0xfc, 0xaa, 0x6a,
+	0x80, 0x0b, 0xa0, 0x6a,
+	0x10, 0x0c, 0xa0, 0x7a,
+	0x20, 0x93, 0xa0, 0x6a,
 	0x02, 0x93, 0x26, 0x01,
-	0x02, 0xfc, 0xb2, 0x7a,
-	0x40, 0x0d, 0xc6, 0x6a,
+	0x02, 0xfc, 0xb4, 0x7a,
+	0x40, 0x0d, 0xc8, 0x6a,
 	0x01, 0xa4, 0x48, 0x01,
-	0x00, 0x65, 0xc6, 0x42,
-	0x40, 0x0d, 0xb8, 0x6a,
-	0x00, 0x65, 0x0e, 0x5a,
-	0x00, 0x65, 0xaa, 0x42,
-	0x80, 0xfc, 0xc2, 0x7a,
-	0x80, 0xa4, 0xc2, 0x6a,
+	0x00, 0x65, 0xc8, 0x42,
+	0x40, 0x0d, 0xba, 0x6a,
+	0x00, 0x65, 0x10, 0x5a,
+	0x00, 0x65, 0xac, 0x42,
+	0x80, 0xfc, 0xc4, 0x7a,
+	0x80, 0xa4, 0xc4, 0x6a,
 	0xff, 0xa5, 0x4a, 0x19,
 	0xff, 0xa6, 0x4c, 0x21,
 	0xff, 0xa7, 0x4e, 0x21,
 	0xf8, 0xfc, 0x48, 0x09,
 	0x7f, 0xa3, 0x46, 0x09,
-	0x04, 0x3b, 0xe2, 0x6a,
+	0x04, 0x3b, 0xe4, 0x6a,
 	0x02, 0x93, 0x26, 0x01,
-	0x01, 0x94, 0xc8, 0x7a,
-	0x01, 0x94, 0xc8, 0x7a,
-	0x01, 0x94, 0xc8, 0x7a,
-	0x01, 0x94, 0xc8, 0x7a,
-	0x01, 0x94, 0xc8, 0x7a,
-	0x01, 0xa4, 0xe0, 0x7a,
-	0x01, 0xfc, 0xd6, 0x7a,
-	0x01, 0x94, 0xe2, 0x6a,
-	0x01, 0x94, 0xe2, 0x6a,
-	0x01, 0x94, 0xe2, 0x6a,
-	0x00, 0x65, 0x82, 0x42,
-	0x01, 0x94, 0xe0, 0x7a,
-	0x10, 0x94, 0xe2, 0x6a,
+	0x01, 0x94, 0xca, 0x7a,
+	0x01, 0x94, 0xca, 0x7a,
+	0x01, 0x94, 0xca, 0x7a,
+	0x01, 0x94, 0xca, 0x7a,
+	0x01, 0x94, 0xca, 0x7a,
+	0x01, 0xa4, 0xe2, 0x7a,
+	0x01, 0xfc, 0xd8, 0x7a,
+	0x01, 0x94, 0xe4, 0x6a,
+	0x01, 0x94, 0xe4, 0x6a,
+	0x01, 0x94, 0xe4, 0x6a,
+	0x00, 0x65, 0x84, 0x42,
+	0x01, 0x94, 0xe2, 0x7a,
+	0x10, 0x94, 0xe4, 0x6a,
 	0xd7, 0x93, 0x26, 0x09,
-	0x28, 0x93, 0xe6, 0x6a,
+	0x28, 0x93, 0xe8, 0x6a,
 	0x01, 0x85, 0x0a, 0x01,
-	0x02, 0xfc, 0xee, 0x6a,
+	0x02, 0xfc, 0xf0, 0x6a,
 	0x01, 0x14, 0x46, 0x31,
 	0xff, 0x6a, 0x10, 0x09,
 	0xfe, 0x85, 0x0a, 0x09,
-	0xff, 0x38, 0xfc, 0x6a,
-	0x80, 0xa3, 0xfc, 0x7a,
-	0x80, 0x0b, 0xfa, 0x7a,
-	0x04, 0x3b, 0xfc, 0x7a,
+	0xff, 0x38, 0xfe, 0x6a,
+	0x80, 0xa3, 0xfe, 0x7a,
+	0x80, 0x0b, 0xfc, 0x7a,
+	0x04, 0x3b, 0xfe, 0x7a,
 	0xbf, 0x3b, 0x76, 0x08,
 	0x01, 0x3b, 0x26, 0x31,
-	0x00, 0x65, 0x0e, 0x5a,
-	0x01, 0x0b, 0x0a, 0x6b,
-	0x10, 0x0c, 0xfe, 0x7a,
-	0x04, 0x93, 0x08, 0x6b,
-	0x01, 0x94, 0x06, 0x7b,
-	0x10, 0x94, 0x08, 0x6b,
+	0x00, 0x65, 0x10, 0x5a,
+	0x01, 0x0b, 0x0c, 0x6b,
+	0x10, 0x0c, 0x00, 0x7b,
+	0x04, 0x93, 0x0a, 0x6b,
+	0x01, 0x94, 0x08, 0x7b,
+	0x10, 0x94, 0x0a, 0x6b,
 	0xc7, 0x93, 0x26, 0x09,
 	0x01, 0x99, 0xd4, 0x30,
-	0x38, 0x93, 0x0c, 0x6b,
-	0xff, 0x08, 0x5a, 0x6b,
-	0xff, 0x09, 0x5a, 0x6b,
-	0xff, 0x0a, 0x5a, 0x6b,
-	0xff, 0x38, 0x28, 0x7b,
+	0x38, 0x93, 0x0e, 0x6b,
+	0xff, 0x08, 0x5c, 0x6b,
+	0xff, 0x09, 0x5c, 0x6b,
+	0xff, 0x0a, 0x5c, 0x6b,
+	0xff, 0x38, 0x2a, 0x7b,
 	0x04, 0x14, 0x10, 0x31,
 	0x01, 0x38, 0x18, 0x31,
 	0x02, 0x6a, 0x1a, 0x31,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x14, 0x6a, 0xf4, 0x5d,
-	0x00, 0x38, 0xe0, 0x5d,
+	0x14, 0x6a, 0xf6, 0x5d,
+	0x00, 0x38, 0xe2, 0x5d,
 	0xff, 0x6a, 0x70, 0x08,
-	0x00, 0x65, 0x54, 0x43,
-	0x80, 0xa3, 0x2e, 0x7b,
+	0x00, 0x65, 0x56, 0x43,
+	0x80, 0xa3, 0x30, 0x7b,
 	0x01, 0xa4, 0x48, 0x01,
-	0x00, 0x65, 0x5a, 0x43,
-	0x08, 0xeb, 0x34, 0x7b,
-	0x00, 0x65, 0x0e, 0x5a,
-	0x08, 0xeb, 0x30, 0x6b,
+	0x00, 0x65, 0x5c, 0x43,
+	0x08, 0xeb, 0x36, 0x7b,
+	0x00, 0x65, 0x10, 0x5a,
+	0x08, 0xeb, 0x32, 0x6b,
 	0x07, 0xe9, 0x10, 0x31,
 	0x01, 0xe9, 0xca, 0x30,
 	0x01, 0x65, 0x46, 0x31,
-	0x00, 0x6a, 0xba, 0x5e,
+	0x00, 0x6a, 0xbc, 0x5e,
 	0x88, 0x6a, 0xcc, 0x00,
-	0xa4, 0x6a, 0xf4, 0x5d,
-	0x08, 0x6a, 0xe0, 0x5d,
+	0xa4, 0x6a, 0xf6, 0x5d,
+	0x08, 0x6a, 0xe2, 0x5d,
 	0x0d, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0xa8, 0x5e,
+	0x00, 0x65, 0xaa, 0x5e,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x00, 0x65, 0x8a, 0x5e,
+	0x00, 0x65, 0x8c, 0x5e,
 	0x01, 0x99, 0x46, 0x31,
-	0x00, 0xa3, 0xba, 0x5e,
+	0x00, 0xa3, 0xbc, 0x5e,
 	0x01, 0x88, 0x10, 0x31,
-	0x00, 0x65, 0x3a, 0x5a,
-	0x00, 0x65, 0xfa, 0x59,
+	0x00, 0x65, 0x3c, 0x5a,
+	0x00, 0x65, 0xfc, 0x59,
 	0x03, 0x8c, 0x10, 0x30,
-	0x00, 0x65, 0xe6, 0x5d,
-	0x80, 0x0b, 0x82, 0x6a,
-	0x80, 0x0b, 0x62, 0x6b,
-	0x01, 0x0c, 0x5c, 0x7b,
-	0x10, 0x0c, 0x82, 0x7a,
-	0x03, 0x9e, 0x82, 0x6a,
-	0x00, 0x65, 0x04, 0x5a,
-	0x00, 0x6a, 0xba, 0x5e,
-	0x01, 0xa4, 0x82, 0x6b,
-	0xff, 0x38, 0x78, 0x7b,
+	0x00, 0x65, 0xe8, 0x5d,
+	0x80, 0x0b, 0x84, 0x6a,
+	0x80, 0x0b, 0x64, 0x6b,
+	0x01, 0x0c, 0x5e, 0x7b,
+	0x10, 0x0c, 0x84, 0x7a,
+	0x03, 0x9e, 0x84, 0x6a,
+	0x00, 0x65, 0x06, 0x5a,
+	0x00, 0x6a, 0xbc, 0x5e,
+	0x01, 0xa4, 0x84, 0x6b,
+	0xff, 0x38, 0x7a, 0x7b,
 	0x01, 0x38, 0xc8, 0x30,
 	0x00, 0x08, 0x40, 0x19,
 	0xff, 0x6a, 0xc8, 0x08,
 	0x00, 0x09, 0x42, 0x21,
 	0x00, 0x0a, 0x44, 0x21,
 	0xff, 0x6a, 0x70, 0x08,
-	0x00, 0x65, 0x7a, 0x43,
+	0x00, 0x65, 0x7c, 0x43,
 	0x03, 0x08, 0x40, 0x31,
 	0x03, 0x08, 0x40, 0x31,
 	0x01, 0x08, 0x40, 0x31,
@@ -461,16 +462,16 @@ static uint8_t seqprog[] = {
 	0x04, 0x3c, 0xcc, 0x79,
 	0xfb, 0x3c, 0x78, 0x08,
 	0x04, 0x93, 0x20, 0x79,
-	0x01, 0x0c, 0x8e, 0x6b,
+	0x01, 0x0c, 0x90, 0x6b,
 	0x80, 0xba, 0x20, 0x79,
 	0x80, 0x04, 0x20, 0x79,
-	0xe4, 0x6a, 0x6e, 0x5d,
-	0x23, 0x6a, 0x84, 0x5d,
-	0x01, 0x6a, 0x84, 0x5d,
+	0xe4, 0x6a, 0x70, 0x5d,
+	0x23, 0x6a, 0x86, 0x5d,
+	0x01, 0x6a, 0x86, 0x5d,
 	0x00, 0x65, 0x20, 0x41,
 	0x00, 0x65, 0xcc, 0x41,
-	0x80, 0x3c, 0xa2, 0x7b,
-	0x21, 0x6a, 0xd8, 0x5e,
+	0x80, 0x3c, 0xa4, 0x7b,
+	0x21, 0x6a, 0xda, 0x5e,
 	0x01, 0xbc, 0x18, 0x31,
 	0x02, 0x6a, 0x1a, 0x31,
 	0x02, 0x6a, 0xf8, 0x01,
@@ -480,16 +481,16 @@ static uint8_t seqprog[] = {
 	0xff, 0x6a, 0x12, 0x08,
 	0xff, 0x6a, 0x14, 0x08,
 	0xf3, 0xbc, 0xd4, 0x18,
-	0xa0, 0x6a, 0xc8, 0x53,
+	0xa0, 0x6a, 0xca, 0x53,
 	0x04, 0xa0, 0x10, 0x31,
 	0xac, 0x6a, 0x26, 0x01,
 	0x04, 0xa0, 0x10, 0x31,
 	0x03, 0x08, 0x18, 0x31,
 	0x88, 0x6a, 0xcc, 0x00,
-	0xa0, 0x6a, 0xf4, 0x5d,
-	0x00, 0xbc, 0xe0, 0x5d,
+	0xa0, 0x6a, 0xf6, 0x5d,
+	0x00, 0xbc, 0xe2, 0x5d,
 	0x3d, 0x6a, 0x26, 0x01,
-	0x00, 0x65, 0xe0, 0x43,
+	0x00, 0x65, 0xe2, 0x43,
 	0xff, 0x6a, 0x10, 0x09,
 	0xa4, 0x6a, 0x26, 0x01,
 	0x0c, 0xa0, 0x32, 0x31,
@@ -499,128 +500,128 @@ static uint8_t seqprog[] = {
 	0x36, 0x6a, 0x26, 0x01,
 	0x02, 0x93, 0x26, 0x01,
 	0x35, 0x6a, 0x26, 0x01,
-	0x00, 0x65, 0x9c, 0x5e,
-	0x00, 0x65, 0x9c, 0x5e,
+	0x00, 0x65, 0x9e, 0x5e,
+	0x00, 0x65, 0x9e, 0x5e,
 	0x02, 0x93, 0x26, 0x01,
 	0xbf, 0x3c, 0x78, 0x08,
-	0x04, 0x0b, 0xe6, 0x6b,
-	0x10, 0x0c, 0xe2, 0x7b,
-	0x01, 0x03, 0xe6, 0x6b,
-	0x20, 0x93, 0xe8, 0x6b,
-	0x04, 0x0b, 0xee, 0x6b,
+	0x04, 0x0b, 0xe8, 0x6b,
+	0x10, 0x0c, 0xe4, 0x7b,
+	0x01, 0x03, 0xe8, 0x6b,
+	0x20, 0x93, 0xea, 0x6b,
+	0x04, 0x0b, 0xf0, 0x6b,
 	0x40, 0x3c, 0x78, 0x00,
 	0xc7, 0x93, 0x26, 0x09,
-	0x38, 0x93, 0xf0, 0x6b,
+	0x38, 0x93, 0xf2, 0x6b,
 	0x00, 0x65, 0xcc, 0x41,
-	0x80, 0x3c, 0x56, 0x6c,
+	0x80, 0x3c, 0x58, 0x6c,
 	0x01, 0x06, 0x50, 0x31,
 	0x80, 0xb8, 0x70, 0x01,
 	0x00, 0x65, 0xcc, 0x41,
 	0x10, 0x3f, 0x06, 0x00,
 	0x10, 0x6a, 0x06, 0x00,
 	0x01, 0x3a, 0xca, 0x30,
-	0x80, 0x65, 0x1c, 0x64,
-	0x10, 0xb8, 0x40, 0x6c,
+	0x80, 0x65, 0x1e, 0x64,
+	0x10, 0xb8, 0x42, 0x6c,
 	0xc0, 0x3e, 0xca, 0x00,
-	0x40, 0xb8, 0x0c, 0x6c,
+	0x40, 0xb8, 0x0e, 0x6c,
 	0xbf, 0x65, 0xca, 0x08,
-	0x20, 0xb8, 0x20, 0x7c,
+	0x20, 0xb8, 0x22, 0x7c,
 	0x01, 0x65, 0x0c, 0x30,
-	0x00, 0x65, 0xd8, 0x5d,
-	0xa0, 0x3f, 0x28, 0x64,
+	0x00, 0x65, 0xda, 0x5d,
+	0xa0, 0x3f, 0x2a, 0x64,
 	0x23, 0xb8, 0x0c, 0x08,
-	0x00, 0x65, 0xd8, 0x5d,
-	0xa0, 0x3f, 0x28, 0x64,
-	0x00, 0xbb, 0x20, 0x44,
-	0xff, 0x65, 0x20, 0x64,
-	0x00, 0x65, 0x40, 0x44,
+	0x00, 0x65, 0xda, 0x5d,
+	0xa0, 0x3f, 0x2a, 0x64,
+	0x00, 0xbb, 0x22, 0x44,
+	0xff, 0x65, 0x22, 0x64,
+	0x00, 0x65, 0x42, 0x44,
 	0x40, 0x6a, 0x18, 0x00,
 	0x01, 0x65, 0x0c, 0x30,
-	0x00, 0x65, 0xd8, 0x5d,
-	0xa0, 0x3f, 0xfc, 0x73,
+	0x00, 0x65, 0xda, 0x5d,
+	0xa0, 0x3f, 0xfe, 0x73,
 	0x40, 0x6a, 0x18, 0x00,
 	0x01, 0x3a, 0xa6, 0x30,
 	0x08, 0x6a, 0x74, 0x00,
 	0x00, 0x65, 0xcc, 0x41,
-	0x64, 0x6a, 0x68, 0x5d,
-	0x80, 0x64, 0xd8, 0x6c,
-	0x04, 0x64, 0x9a, 0x74,
-	0x02, 0x64, 0xaa, 0x74,
-	0x00, 0x6a, 0x60, 0x74,
-	0x03, 0x64, 0xc8, 0x74,
-	0x23, 0x64, 0x48, 0x74,
-	0x08, 0x64, 0x5c, 0x74,
-	0x61, 0x6a, 0xd8, 0x5e,
-	0x00, 0x65, 0xd8, 0x5d,
+	0x64, 0x6a, 0x6a, 0x5d,
+	0x80, 0x64, 0xda, 0x6c,
+	0x04, 0x64, 0x9c, 0x74,
+	0x02, 0x64, 0xac, 0x74,
+	0x00, 0x6a, 0x62, 0x74,
+	0x03, 0x64, 0xca, 0x74,
+	0x23, 0x64, 0x4a, 0x74,
+	0x08, 0x64, 0x5e, 0x74,
+	0x61, 0x6a, 0xda, 0x5e,
+	0x00, 0x65, 0xda, 0x5d,
 	0x08, 0x51, 0xce, 0x71,
-	0x00, 0x65, 0x40, 0x44,
-	0x80, 0x04, 0x5a, 0x7c,
-	0x51, 0x6a, 0x5e, 0x5d,
-	0x01, 0x51, 0x5a, 0x64,
-	0x01, 0xa4, 0x52, 0x7c,
-	0x80, 0xba, 0x5c, 0x6c,
-	0x41, 0x6a, 0xd8, 0x5e,
-	0x00, 0x65, 0x5c, 0x44,
-	0x21, 0x6a, 0xd8, 0x5e,
-	0x00, 0x65, 0x5c, 0x44,
-	0x07, 0x6a, 0x54, 0x5d,
+	0x00, 0x65, 0x42, 0x44,
+	0x80, 0x04, 0x5c, 0x7c,
+	0x51, 0x6a, 0x60, 0x5d,
+	0x01, 0x51, 0x5c, 0x64,
+	0x01, 0xa4, 0x54, 0x7c,
+	0x80, 0xba, 0x5e, 0x6c,
+	0x41, 0x6a, 0xda, 0x5e,
+	0x00, 0x65, 0x5e, 0x44,
+	0x21, 0x6a, 0xda, 0x5e,
+	0x00, 0x65, 0x5e, 0x44,
+	0x07, 0x6a, 0x56, 0x5d,
 	0x01, 0x06, 0xd4, 0x30,
 	0x00, 0x65, 0xcc, 0x41,
-	0x80, 0xb8, 0x56, 0x7c,
-	0xc0, 0x3c, 0x6a, 0x7c,
-	0x80, 0x3c, 0x56, 0x6c,
-	0xff, 0xa8, 0x6a, 0x6c,
-	0x40, 0x3c, 0x56, 0x6c,
-	0x10, 0xb8, 0x6e, 0x7c,
-	0xa1, 0x6a, 0xd8, 0x5e,
-	0x01, 0xb4, 0x74, 0x6c,
-	0x02, 0xb4, 0x76, 0x6c,
-	0x01, 0xa4, 0x76, 0x7c,
-	0xff, 0xa8, 0x86, 0x7c,
+	0x80, 0xb8, 0x58, 0x7c,
+	0xc0, 0x3c, 0x6c, 0x7c,
+	0x80, 0x3c, 0x58, 0x6c,
+	0xff, 0xa8, 0x6c, 0x6c,
+	0x40, 0x3c, 0x58, 0x6c,
+	0x10, 0xb8, 0x70, 0x7c,
+	0xa1, 0x6a, 0xda, 0x5e,
+	0x01, 0xb4, 0x76, 0x6c,
+	0x02, 0xb4, 0x78, 0x6c,
+	0x01, 0xa4, 0x78, 0x7c,
+	0xff, 0xa8, 0x88, 0x7c,
 	0x04, 0xb4, 0x68, 0x01,
 	0x01, 0x6a, 0x76, 0x00,
-	0x00, 0xbb, 0x12, 0x5e,
-	0xff, 0xa8, 0x86, 0x7c,
-	0x71, 0x6a, 0xd8, 0x5e,
-	0x40, 0x51, 0x86, 0x64,
-	0x00, 0x65, 0xb2, 0x5e,
+	0x00, 0xbb, 0x14, 0x5e,
+	0xff, 0xa8, 0x88, 0x7c,
+	0x71, 0x6a, 0xda, 0x5e,
+	0x40, 0x51, 0x88, 0x64,
+	0x00, 0x65, 0xb4, 0x5e,
 	0x00, 0x65, 0xde, 0x41,
-	0x00, 0xbb, 0x8a, 0x5c,
+	0x00, 0xbb, 0x8c, 0x5c,
 	0x00, 0x65, 0xde, 0x41,
-	0x00, 0x65, 0xb2, 0x5e,
+	0x00, 0x65, 0xb4, 0x5e,
 	0x01, 0x65, 0xa2, 0x30,
 	0x01, 0xf8, 0xc8, 0x30,
 	0x01, 0x4e, 0xc8, 0x30,
-	0x00, 0x6a, 0xb6, 0xdd,
-	0x00, 0x51, 0xc8, 0x5d,
+	0x00, 0x6a, 0xb8, 0xdd,
+	0x00, 0x51, 0xca, 0x5d,
 	0x01, 0x4e, 0x9c, 0x18,
 	0x02, 0x6a, 0x22, 0x05,
-	0xc0, 0x3c, 0x56, 0x6c,
+	0xc0, 0x3c, 0x58, 0x6c,
 	0x04, 0xb8, 0x70, 0x01,
-	0x00, 0x65, 0xd4, 0x5e,
+	0x00, 0x65, 0xd6, 0x5e,
 	0x20, 0xb8, 0xde, 0x69,
 	0x01, 0xbb, 0xa2, 0x30,
 	0x3f, 0xba, 0x7c, 0x08,
-	0x00, 0xb9, 0xce, 0x5c,
+	0x00, 0xb9, 0xd0, 0x5c,
 	0x00, 0x65, 0xde, 0x41,
 	0x01, 0x06, 0xd4, 0x30,
 	0x20, 0x3c, 0xcc, 0x79,
-	0x20, 0x3c, 0x5c, 0x7c,
-	0x01, 0xa4, 0xb8, 0x7c,
+	0x20, 0x3c, 0x5e, 0x7c,
+	0x01, 0xa4, 0xba, 0x7c,
 	0x01, 0xb4, 0x68, 0x01,
 	0x00, 0x65, 0xcc, 0x41,
-	0x00, 0x65, 0x5c, 0x44,
+	0x00, 0x65, 0x5e, 0x44,
 	0x04, 0x14, 0x58, 0x31,
 	0x01, 0x06, 0xd4, 0x30,
 	0x08, 0xa0, 0x60, 0x31,
 	0xac, 0x6a, 0xcc, 0x00,
-	0x14, 0x6a, 0xf4, 0x5d,
+	0x14, 0x6a, 0xf6, 0x5d,
 	0x01, 0x06, 0xd4, 0x30,
-	0xa0, 0x6a, 0xec, 0x5d,
+	0xa0, 0x6a, 0xee, 0x5d,
 	0x00, 0x65, 0xcc, 0x41,
 	0xdf, 0x3c, 0x78, 0x08,
 	0x12, 0x01, 0x02, 0x00,
-	0x00, 0x65, 0x5c, 0x44,
+	0x00, 0x65, 0x5e, 0x44,
 	0x4c, 0x65, 0xcc, 0x28,
 	0x01, 0x3e, 0x20, 0x31,
 	0xd0, 0x66, 0xcc, 0x18,
@@ -631,102 +632,102 @@ static uint8_t seqprog[] = {
 	0xd0, 0x65, 0xca, 0x18,
 	0x01, 0x3e, 0x20, 0x31,
 	0x30, 0x65, 0xd4, 0x18,
-	0x00, 0x65, 0xe6, 0x4c,
+	0x00, 0x65, 0xe8, 0x4c,
 	0xe1, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
 	0x20, 0x65, 0xd4, 0x18,
-	0x00, 0x65, 0xee, 0x54,
+	0x00, 0x65, 0xf0, 0x54,
 	0xe1, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
 	0x20, 0x65, 0xca, 0x18,
 	0xe0, 0x65, 0xd4, 0x18,
-	0x00, 0x65, 0xf8, 0x4c,
+	0x00, 0x65, 0xfa, 0x4c,
 	0xe1, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
 	0xd0, 0x65, 0xd4, 0x18,
-	0x00, 0x65, 0x00, 0x55,
+	0x00, 0x65, 0x02, 0x55,
 	0xe1, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
 	0x01, 0x6c, 0xa2, 0x30,
-	0xff, 0x51, 0x12, 0x75,
-	0x00, 0x51, 0x8e, 0x5d,
+	0xff, 0x51, 0x14, 0x75,
+	0x00, 0x51, 0x90, 0x5d,
 	0x01, 0x51, 0x20, 0x31,
-	0x00, 0x65, 0x34, 0x45,
+	0x00, 0x65, 0x36, 0x45,
 	0x3f, 0xba, 0xc8, 0x08,
-	0x00, 0x3e, 0x34, 0x75,
-	0x00, 0x65, 0xb0, 0x5e,
+	0x00, 0x3e, 0x36, 0x75,
+	0x00, 0x65, 0xb2, 0x5e,
 	0x80, 0x3c, 0x78, 0x00,
 	0x01, 0x06, 0xd4, 0x30,
-	0x00, 0x65, 0xd8, 0x5d,
+	0x00, 0x65, 0xda, 0x5d,
 	0x01, 0x3c, 0x78, 0x00,
-	0xe0, 0x3f, 0x50, 0x65,
+	0xe0, 0x3f, 0x52, 0x65,
 	0x02, 0x3c, 0x78, 0x00,
-	0x20, 0x12, 0x50, 0x65,
-	0x51, 0x6a, 0x5e, 0x5d,
-	0x00, 0x51, 0x8e, 0x5d,
-	0x51, 0x6a, 0x5e, 0x5d,
+	0x20, 0x12, 0x52, 0x65,
+	0x51, 0x6a, 0x60, 0x5d,
+	0x00, 0x51, 0x90, 0x5d,
+	0x51, 0x6a, 0x60, 0x5d,
 	0x01, 0x51, 0x20, 0x31,
 	0x04, 0x3c, 0x78, 0x00,
 	0x01, 0xb9, 0xc8, 0x30,
-	0x00, 0x3d, 0x4e, 0x65,
+	0x00, 0x3d, 0x50, 0x65,
 	0x08, 0x3c, 0x78, 0x00,
 	0x3f, 0xba, 0xc8, 0x08,
-	0x00, 0x3e, 0x4e, 0x65,
+	0x00, 0x3e, 0x50, 0x65,
 	0x10, 0x3c, 0x78, 0x00,
-	0x04, 0xb8, 0x4e, 0x7d,
+	0x04, 0xb8, 0x50, 0x7d,
 	0xfb, 0xb8, 0x70, 0x09,
-	0x20, 0xb8, 0x44, 0x6d,
+	0x20, 0xb8, 0x46, 0x6d,
 	0x01, 0x90, 0xc8, 0x30,
 	0xff, 0x6a, 0xa2, 0x00,
-	0x00, 0x3d, 0xce, 0x5c,
+	0x00, 0x3d, 0xd0, 0x5c,
 	0x01, 0x64, 0x20, 0x31,
 	0xff, 0x6a, 0x78, 0x08,
 	0x00, 0x65, 0xea, 0x58,
-	0x10, 0xb8, 0x5c, 0x7c,
-	0xff, 0x6a, 0x54, 0x5d,
-	0x00, 0x65, 0x5c, 0x44,
-	0x00, 0x65, 0xb0, 0x5e,
-	0x31, 0x6a, 0xd8, 0x5e,
-	0x00, 0x65, 0x5c, 0x44,
+	0x10, 0xb8, 0x5e, 0x7c,
+	0xff, 0x6a, 0x56, 0x5d,
+	0x00, 0x65, 0x5e, 0x44,
+	0x00, 0x65, 0xb2, 0x5e,
+	0x31, 0x6a, 0xda, 0x5e,
+	0x00, 0x65, 0x5e, 0x44,
 	0x10, 0x3f, 0x06, 0x00,
 	0x10, 0x6a, 0x06, 0x00,
 	0x01, 0x65, 0x74, 0x34,
-	0x81, 0x6a, 0xd8, 0x5e,
-	0x00, 0x65, 0x60, 0x45,
+	0x81, 0x6a, 0xda, 0x5e,
+	0x00, 0x65, 0x62, 0x45,
 	0x01, 0x06, 0xd4, 0x30,
-	0x01, 0x0c, 0x60, 0x7d,
-	0x04, 0x0c, 0x5a, 0x6d,
+	0x01, 0x0c, 0x62, 0x7d,
+	0x04, 0x0c, 0x5c, 0x6d,
 	0xe0, 0x03, 0x7e, 0x08,
 	0xe0, 0x3f, 0xcc, 0x61,
 	0x01, 0x65, 0xcc, 0x30,
 	0x01, 0x12, 0xda, 0x34,
 	0x01, 0x06, 0xd4, 0x34,
-	0x01, 0x03, 0x6e, 0x6d,
+	0x01, 0x03, 0x70, 0x6d,
 	0x40, 0x03, 0xcc, 0x08,
 	0x01, 0x65, 0x06, 0x30,
 	0x40, 0x65, 0xc8, 0x08,
-	0x00, 0x66, 0x7c, 0x75,
-	0x40, 0x65, 0x7c, 0x7d,
-	0x00, 0x65, 0x7c, 0x5d,
+	0x00, 0x66, 0x7e, 0x75,
+	0x40, 0x65, 0x7e, 0x7d,
+	0x00, 0x65, 0x7e, 0x5d,
 	0xff, 0x6a, 0xd4, 0x08,
 	0xff, 0x6a, 0xd4, 0x08,
 	0xff, 0x6a, 0xd4, 0x08,
 	0xff, 0x6a, 0xd4, 0x0c,
 	0x08, 0x01, 0x02, 0x00,
-	0x02, 0x0b, 0x86, 0x7d,
+	0x02, 0x0b, 0x88, 0x7d,
 	0x01, 0x65, 0x0c, 0x30,
-	0x02, 0x0b, 0x8a, 0x7d,
+	0x02, 0x0b, 0x8c, 0x7d,
 	0xf7, 0x01, 0x02, 0x0c,
 	0x01, 0x65, 0xc8, 0x30,
-	0xff, 0x41, 0xae, 0x75,
+	0xff, 0x41, 0xb0, 0x75,
 	0x01, 0x41, 0x20, 0x31,
 	0xff, 0x6a, 0xa4, 0x00,
-	0x00, 0x65, 0x9e, 0x45,
-	0xff, 0xbf, 0xae, 0x75,
+	0x00, 0x65, 0xa0, 0x45,
+	0xff, 0xbf, 0xb0, 0x75,
 	0x01, 0x90, 0xa4, 0x30,
 	0x01, 0xbf, 0x20, 0x31,
-	0x00, 0xbb, 0x98, 0x65,
-	0xff, 0x52, 0xac, 0x75,
+	0x00, 0xbb, 0x9a, 0x65,
+	0xff, 0x52, 0xae, 0x75,
 	0x01, 0xbf, 0xcc, 0x30,
 	0x01, 0x90, 0xca, 0x30,
 	0x01, 0x52, 0x20, 0x31,
@@ -734,28 +735,28 @@ static uint8_t seqprog[] = {
 	0x01, 0x65, 0x20, 0x35,
 	0x01, 0xbf, 0x82, 0x34,
 	0x01, 0x64, 0xa2, 0x30,
-	0x00, 0x6a, 0xc0, 0x5e,
+	0x00, 0x6a, 0xc2, 0x5e,
 	0x0d, 0x6a, 0x76, 0x00,
-	0x00, 0x51, 0x12, 0x46,
+	0x00, 0x51, 0x14, 0x46,
 	0x01, 0x65, 0xa4, 0x30,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x48, 0x6a, 0x06, 0x5e,
+	0x48, 0x6a, 0x08, 0x5e,
 	0x01, 0x6a, 0xd0, 0x01,
 	0x01, 0x6a, 0xdc, 0x05,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x48, 0x6a, 0x06, 0x5e,
-	0x01, 0x6a, 0xe0, 0x5d,
+	0x48, 0x6a, 0x08, 0x5e,
+	0x01, 0x6a, 0xe2, 0x5d,
 	0x01, 0x6a, 0x26, 0x05,
 	0x01, 0x65, 0xd8, 0x31,
 	0x09, 0xee, 0xdc, 0x01,
-	0x80, 0xee, 0xcc, 0x7d,
+	0x80, 0xee, 0xce, 0x7d,
 	0xff, 0x6a, 0xdc, 0x0d,
 	0x01, 0x65, 0x32, 0x31,
 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0xa8, 0x46,
-	0x81, 0x6a, 0xd8, 0x5e,
-	0x01, 0x0c, 0xd8, 0x7d,
-	0x04, 0x0c, 0xd6, 0x6d,
+	0x00, 0x65, 0xaa, 0x46,
+	0x81, 0x6a, 0xda, 0x5e,
+	0x01, 0x0c, 0xda, 0x7d,
+	0x04, 0x0c, 0xd8, 0x6d,
 	0xe0, 0x03, 0x06, 0x08,
 	0xe0, 0x03, 0x7e, 0x0c,
 	0x01, 0x65, 0x18, 0x31,
@@ -774,7 +775,7 @@ static uint8_t seqprog[] = {
 	0x01, 0x6c, 0xda, 0x34,
 	0x3d, 0x64, 0xa4, 0x28,
 	0x55, 0x64, 0xc8, 0x28,
-	0x00, 0x65, 0x06, 0x46,
+	0x00, 0x65, 0x08, 0x46,
 	0x2e, 0x64, 0xa4, 0x28,
 	0x66, 0x64, 0xc8, 0x28,
 	0x00, 0x6c, 0xda, 0x18,
@@ -785,63 +786,63 @@ static uint8_t seqprog[] = {
 	0x00, 0x6c, 0xda, 0x24,
 	0x01, 0x65, 0xc8, 0x30,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x44, 0x6a, 0x02, 0x5e,
+	0x44, 0x6a, 0x04, 0x5e,
 	0x01, 0x90, 0xe2, 0x31,
-	0x04, 0x3b, 0x26, 0x7e,
+	0x04, 0x3b, 0x28, 0x7e,
 	0x30, 0x6a, 0xd0, 0x01,
 	0x20, 0x6a, 0xd0, 0x01,
 	0x1d, 0x6a, 0xdc, 0x01,
-	0xdc, 0xee, 0x22, 0x66,
-	0x00, 0x65, 0x3e, 0x46,
+	0xdc, 0xee, 0x24, 0x66,
+	0x00, 0x65, 0x40, 0x46,
 	0x20, 0x6a, 0xd0, 0x01,
 	0x01, 0x6a, 0xdc, 0x01,
 	0x20, 0xa0, 0xd8, 0x31,
 	0x09, 0xee, 0xdc, 0x01,
-	0x80, 0xee, 0x2e, 0x7e,
+	0x80, 0xee, 0x30, 0x7e,
 	0x11, 0x6a, 0xdc, 0x01,
-	0x50, 0xee, 0x32, 0x66,
+	0x50, 0xee, 0x34, 0x66,
 	0x20, 0x6a, 0xd0, 0x01,
 	0x09, 0x6a, 0xdc, 0x01,
-	0x88, 0xee, 0x38, 0x66,
+	0x88, 0xee, 0x3a, 0x66,
 	0x19, 0x6a, 0xdc, 0x01,
-	0xd8, 0xee, 0x3c, 0x66,
+	0xd8, 0xee, 0x3e, 0x66,
 	0xff, 0x6a, 0xdc, 0x09,
-	0x18, 0xee, 0x40, 0x6e,
+	0x18, 0xee, 0x42, 0x6e,
 	0xff, 0x6a, 0xd4, 0x0c,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x44, 0x6a, 0x02, 0x5e,
-	0x20, 0x6a, 0xe0, 0x5d,
+	0x44, 0x6a, 0x04, 0x5e,
+	0x20, 0x6a, 0xe2, 0x5d,
 	0x01, 0x3b, 0x26, 0x31,
-	0x04, 0x3b, 0x5a, 0x6e,
+	0x04, 0x3b, 0x5c, 0x6e,
 	0xa0, 0x6a, 0xca, 0x00,
 	0x20, 0x65, 0xc8, 0x18,
-	0x00, 0x65, 0x98, 0x5e,
-	0x00, 0x65, 0x52, 0x66,
+	0x00, 0x65, 0x9a, 0x5e,
+	0x00, 0x65, 0x54, 0x66,
 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0xa8, 0x46,
+	0x00, 0x65, 0xaa, 0x46,
 	0xa0, 0x6a, 0xcc, 0x00,
 	0xff, 0x6a, 0xc8, 0x08,
-	0x20, 0x94, 0x5e, 0x6e,
-	0x10, 0x94, 0x60, 0x6e,
-	0x08, 0x94, 0x7a, 0x6e,
-	0x08, 0x94, 0x7a, 0x6e,
-	0x08, 0x94, 0x7a, 0x6e,
+	0x20, 0x94, 0x60, 0x6e,
+	0x10, 0x94, 0x62, 0x6e,
+	0x08, 0x94, 0x7c, 0x6e,
+	0x08, 0x94, 0x7c, 0x6e,
+	0x08, 0x94, 0x7c, 0x6e,
 	0xff, 0x8c, 0xc8, 0x10,
 	0xc1, 0x64, 0xc8, 0x18,
 	0xf8, 0x64, 0xc8, 0x08,
 	0x01, 0x99, 0xda, 0x30,
-	0x00, 0x66, 0x6e, 0x66,
-	0xc0, 0x66, 0xaa, 0x76,
+	0x00, 0x66, 0x70, 0x66,
+	0xc0, 0x66, 0xac, 0x76,
 	0x60, 0x66, 0xc8, 0x18,
 	0x3d, 0x64, 0xc8, 0x28,
-	0x00, 0x65, 0x5e, 0x46,
+	0x00, 0x65, 0x60, 0x46,
 	0xf7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0x7c, 0x6e,
+	0x08, 0x93, 0x7e, 0x6e,
 	0x00, 0x62, 0xc4, 0x18,
-	0x00, 0x65, 0xa8, 0x5e,
-	0x00, 0x65, 0x88, 0x5e,
-	0x00, 0x65, 0x88, 0x5e,
-	0x00, 0x65, 0x88, 0x5e,
+	0x00, 0x65, 0xaa, 0x5e,
+	0x00, 0x65, 0x8a, 0x5e,
+	0x00, 0x65, 0x8a, 0x5e,
+	0x00, 0x65, 0x8a, 0x5e,
 	0x01, 0x99, 0xda, 0x30,
 	0x01, 0x99, 0xda, 0x30,
 	0x01, 0x99, 0xda, 0x30,
@@ -858,11 +859,11 @@ static uint8_t seqprog[] = {
 	0x01, 0x6c, 0x32, 0x31,
 	0x01, 0x6c, 0x32, 0x31,
 	0x01, 0x6c, 0x32, 0x35,
-	0x08, 0x94, 0xa8, 0x7e,
+	0x08, 0x94, 0xaa, 0x7e,
 	0xf7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0xac, 0x6e,
+	0x08, 0x93, 0xae, 0x6e,
 	0xff, 0x6a, 0xd4, 0x0c,
-	0x04, 0xb8, 0xd4, 0x6e,
+	0x04, 0xb8, 0xd6, 0x6e,
 	0x01, 0x42, 0x7e, 0x31,
 	0xff, 0x6a, 0x76, 0x01,
 	0x01, 0x90, 0x84, 0x34,
@@ -870,14 +871,14 @@ static uint8_t seqprog[] = {
 	0x01, 0x85, 0x0a, 0x01,
 	0x7f, 0x65, 0x10, 0x09,
 	0xfe, 0x85, 0x0a, 0x0d,
-	0xff, 0x42, 0xd0, 0x66,
-	0xff, 0x41, 0xc8, 0x66,
-	0xd1, 0x6a, 0xd8, 0x5e,
+	0xff, 0x42, 0xd2, 0x66,
+	0xff, 0x41, 0xca, 0x66,
+	0xd1, 0x6a, 0xda, 0x5e,
 	0xff, 0x6a, 0xca, 0x04,
 	0x01, 0x41, 0x20, 0x31,
 	0x01, 0xbf, 0x82, 0x30,
 	0x01, 0x6a, 0x76, 0x00,
-	0x00, 0xbb, 0x12, 0x46,
+	0x00, 0xbb, 0x14, 0x46,
 	0x01, 0x42, 0x20, 0x31,
 	0x01, 0xbf, 0x84, 0x34,
 	0x01, 0x41, 0x7e, 0x31,
@@ -941,7 +942,7 @@ static ahc_patch_func_t ahc_patch17_func
 static int
 ahc_patch17_func(struct ahc_softc *ahc)
 {
-	return ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0);
+	return ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0);
 }
 
 static ahc_patch_func_t ahc_patch16_func;
@@ -1142,152 +1143,152 @@ static struct patch {
 	{ ahc_patch0_func, 196, 1, 1 },
 	{ ahc_patch9_func, 212, 6, 2 },
 	{ ahc_patch0_func, 218, 6, 1 },
-	{ ahc_patch8_func, 226, 20, 2 },
+	{ ahc_patch8_func, 226, 21, 2 },
 	{ ahc_patch1_func, 241, 1, 1 },
-	{ ahc_patch1_func, 248, 1, 2 },
-	{ ahc_patch0_func, 249, 2, 2 },
-	{ ahc_patch11_func, 250, 1, 1 },
-	{ ahc_patch9_func, 258, 27, 3 },
-	{ ahc_patch1_func, 274, 10, 2 },
-	{ ahc_patch13_func, 277, 1, 1 },
-	{ ahc_patch14_func, 285, 14, 1 },
-	{ ahc_patch1_func, 301, 1, 2 },
-	{ ahc_patch0_func, 302, 1, 1 },
-	{ ahc_patch9_func, 305, 1, 1 },
-	{ ahc_patch13_func, 310, 1, 1 },
-	{ ahc_patch9_func, 311, 2, 2 },
-	{ ahc_patch0_func, 313, 4, 1 },
-	{ ahc_patch14_func, 317, 1, 1 },
-	{ ahc_patch15_func, 319, 2, 3 },
-	{ ahc_patch9_func, 319, 1, 2 },
-	{ ahc_patch0_func, 320, 1, 1 },
-	{ ahc_patch6_func, 325, 1, 2 },
-	{ ahc_patch0_func, 326, 1, 1 },
-	{ ahc_patch1_func, 330, 47, 11 },
-	{ ahc_patch6_func, 337, 2, 4 },
-	{ ahc_patch7_func, 337, 1, 1 },
-	{ ahc_patch8_func, 338, 1, 1 },
-	{ ahc_patch0_func, 339, 1, 1 },
-	{ ahc_patch16_func, 340, 1, 1 },
-	{ ahc_patch6_func, 356, 6, 3 },
-	{ ahc_patch16_func, 356, 5, 1 },
-	{ ahc_patch0_func, 362, 7, 1 },
-	{ ahc_patch13_func, 372, 5, 1 },
-	{ ahc_patch0_func, 377, 52, 17 },
-	{ ahc_patch14_func, 377, 1, 1 },
-	{ ahc_patch7_func, 379, 2, 2 },
-	{ ahc_patch17_func, 380, 1, 1 },
-	{ ahc_patch9_func, 383, 1, 1 },
-	{ ahc_patch18_func, 390, 1, 1 },
-	{ ahc_patch14_func, 395, 9, 3 },
-	{ ahc_patch9_func, 396, 3, 2 },
-	{ ahc_patch0_func, 399, 3, 1 },
-	{ ahc_patch9_func, 407, 6, 2 },
-	{ ahc_patch0_func, 413, 9, 2 },
-	{ ahc_patch13_func, 413, 1, 1 },
-	{ ahc_patch13_func, 422, 2, 1 },
-	{ ahc_patch14_func, 424, 1, 1 },
-	{ ahc_patch9_func, 426, 1, 2 },
-	{ ahc_patch0_func, 427, 1, 1 },
-	{ ahc_patch7_func, 428, 1, 1 },
+	{ ahc_patch1_func, 249, 1, 2 },
+	{ ahc_patch0_func, 250, 2, 2 },
+	{ ahc_patch11_func, 251, 1, 1 },
+	{ ahc_patch9_func, 259, 27, 3 },
+	{ ahc_patch1_func, 275, 10, 2 },
+	{ ahc_patch13_func, 278, 1, 1 },
+	{ ahc_patch14_func, 286, 14, 1 },
+	{ ahc_patch1_func, 302, 1, 2 },
+	{ ahc_patch0_func, 303, 1, 1 },
+	{ ahc_patch9_func, 306, 1, 1 },
+	{ ahc_patch13_func, 311, 1, 1 },
+	{ ahc_patch9_func, 312, 2, 2 },
+	{ ahc_patch0_func, 314, 4, 1 },
+	{ ahc_patch14_func, 318, 1, 1 },
+	{ ahc_patch15_func, 320, 2, 3 },
+	{ ahc_patch9_func, 320, 1, 2 },
+	{ ahc_patch0_func, 321, 1, 1 },
+	{ ahc_patch6_func, 326, 1, 2 },
+	{ ahc_patch0_func, 327, 1, 1 },
+	{ ahc_patch1_func, 331, 47, 11 },
+	{ ahc_patch6_func, 338, 2, 4 },
+	{ ahc_patch7_func, 338, 1, 1 },
+	{ ahc_patch8_func, 339, 1, 1 },
+	{ ahc_patch0_func, 340, 1, 1 },
+	{ ahc_patch16_func, 341, 1, 1 },
+	{ ahc_patch6_func, 357, 6, 3 },
+	{ ahc_patch16_func, 357, 5, 1 },
+	{ ahc_patch0_func, 363, 7, 1 },
+	{ ahc_patch13_func, 373, 5, 1 },
+	{ ahc_patch0_func, 378, 52, 17 },
+	{ ahc_patch14_func, 378, 1, 1 },
+	{ ahc_patch7_func, 380, 2, 2 },
+	{ ahc_patch17_func, 381, 1, 1 },
+	{ ahc_patch9_func, 384, 1, 1 },
+	{ ahc_patch18_func, 391, 1, 1 },
+	{ ahc_patch14_func, 396, 9, 3 },
+	{ ahc_patch9_func, 397, 3, 2 },
+	{ ahc_patch0_func, 400, 3, 1 },
+	{ ahc_patch9_func, 408, 6, 2 },
+	{ ahc_patch0_func, 414, 9, 2 },
+	{ ahc_patch13_func, 414, 1, 1 },
+	{ ahc_patch13_func, 423, 2, 1 },
+	{ ahc_patch14_func, 425, 1, 1 },
+	{ ahc_patch9_func, 427, 1, 2 },
+	{ ahc_patch0_func, 428, 1, 1 },
 	{ ahc_patch7_func, 429, 1, 1 },
-	{ ahc_patch8_func, 430, 3, 3 },
-	{ ahc_patch6_func, 431, 1, 2 },
-	{ ahc_patch0_func, 432, 1, 1 },
-	{ ahc_patch9_func, 433, 1, 1 },
-	{ ahc_patch15_func, 434, 1, 2 },
-	{ ahc_patch13_func, 434, 1, 1 },
-	{ ahc_patch14_func, 436, 9, 4 },
-	{ ahc_patch9_func, 436, 1, 1 },
-	{ ahc_patch9_func, 443, 2, 1 },
-	{ ahc_patch0_func, 445, 4, 3 },
-	{ ahc_patch9_func, 445, 1, 2 },
-	{ ahc_patch0_func, 446, 3, 1 },
-	{ ahc_patch1_func, 450, 2, 1 },
-	{ ahc_patch7_func, 452, 10, 2 },
-	{ ahc_patch0_func, 462, 1, 1 },
-	{ ahc_patch8_func, 463, 118, 22 },
-	{ ahc_patch1_func, 465, 3, 2 },
-	{ ahc_patch0_func, 468, 5, 3 },
-	{ ahc_patch9_func, 468, 2, 2 },
-	{ ahc_patch0_func, 470, 3, 1 },
-	{ ahc_patch1_func, 475, 2, 2 },
-	{ ahc_patch0_func, 477, 6, 3 },
-	{ ahc_patch9_func, 477, 2, 2 },
-	{ ahc_patch0_func, 479, 3, 1 },
-	{ ahc_patch1_func, 485, 2, 2 },
-	{ ahc_patch0_func, 487, 9, 7 },
-	{ ahc_patch9_func, 487, 5, 6 },
-	{ ahc_patch19_func, 487, 1, 2 },
-	{ ahc_patch0_func, 488, 1, 1 },
-	{ ahc_patch19_func, 490, 1, 2 },
-	{ ahc_patch0_func, 491, 1, 1 },
-	{ ahc_patch0_func, 492, 4, 1 },
-	{ ahc_patch6_func, 497, 3, 2 },
-	{ ahc_patch0_func, 500, 1, 1 },
-	{ ahc_patch6_func, 510, 1, 2 },
-	{ ahc_patch0_func, 511, 1, 1 },
-	{ ahc_patch20_func, 548, 7, 1 },
-	{ ahc_patch3_func, 583, 1, 2 },
-	{ ahc_patch0_func, 584, 1, 1 },
-	{ ahc_patch21_func, 587, 1, 1 },
-	{ ahc_patch8_func, 589, 106, 33 },
-	{ ahc_patch4_func, 591, 1, 1 },
-	{ ahc_patch1_func, 597, 2, 2 },
-	{ ahc_patch0_func, 599, 1, 1 },
-	{ ahc_patch1_func, 602, 1, 2 },
-	{ ahc_patch0_func, 603, 1, 1 },
-	{ ahc_patch9_func, 604, 3, 3 },
-	{ ahc_patch15_func, 605, 1, 1 },
-	{ ahc_patch0_func, 607, 4, 1 },
-	{ ahc_patch19_func, 616, 2, 2 },
-	{ ahc_patch0_func, 618, 1, 1 },
-	{ ahc_patch19_func, 622, 10, 3 },
-	{ ahc_patch5_func, 624, 8, 1 },
-	{ ahc_patch0_func, 632, 9, 2 },
-	{ ahc_patch5_func, 633, 8, 1 },
-	{ ahc_patch4_func, 643, 1, 2 },
-	{ ahc_patch0_func, 644, 1, 1 },
-	{ ahc_patch19_func, 645, 1, 2 },
-	{ ahc_patch0_func, 646, 3, 2 },
-	{ ahc_patch4_func, 648, 1, 1 },
-	{ ahc_patch5_func, 649, 1, 1 },
-	{ ahc_patch5_func, 652, 1, 1 },
-	{ ahc_patch5_func, 654, 1, 1 },
-	{ ahc_patch4_func, 656, 2, 2 },
-	{ ahc_patch0_func, 658, 2, 1 },
-	{ ahc_patch5_func, 660, 1, 1 },
-	{ ahc_patch5_func, 663, 1, 1 },
-	{ ahc_patch5_func, 666, 1, 1 },
-	{ ahc_patch19_func, 670, 1, 1 },
-	{ ahc_patch19_func, 673, 1, 1 },
-	{ ahc_patch4_func, 679, 1, 1 },
-	{ ahc_patch6_func, 682, 1, 2 },
-	{ ahc_patch0_func, 683, 1, 1 },
-	{ ahc_patch7_func, 695, 16, 1 },
-	{ ahc_patch4_func, 711, 20, 1 },
-	{ ahc_patch9_func, 732, 4, 2 },
-	{ ahc_patch0_func, 736, 4, 1 },
-	{ ahc_patch9_func, 740, 4, 2 },
-	{ ahc_patch0_func, 744, 3, 1 },
-	{ ahc_patch6_func, 750, 1, 1 },
-	{ ahc_patch22_func, 752, 14, 1 },
-	{ ahc_patch7_func, 766, 3, 1 },
-	{ ahc_patch9_func, 778, 24, 8 },
-	{ ahc_patch19_func, 782, 1, 2 },
-	{ ahc_patch0_func, 783, 1, 1 },
-	{ ahc_patch15_func, 788, 4, 2 },
-	{ ahc_patch0_func, 792, 7, 3 },
-	{ ahc_patch23_func, 792, 5, 2 },
-	{ ahc_patch0_func, 797, 2, 1 },
-	{ ahc_patch0_func, 802, 42, 3 },
-	{ ahc_patch18_func, 814, 18, 2 },
-	{ ahc_patch0_func, 832, 1, 1 },
-	{ ahc_patch4_func, 856, 1, 1 },
-	{ ahc_patch4_func, 857, 3, 2 },
-	{ ahc_patch0_func, 860, 1, 1 },
-	{ ahc_patch13_func, 861, 3, 1 },
-	{ ahc_patch4_func, 864, 12, 1 }
+	{ ahc_patch7_func, 430, 1, 1 },
+	{ ahc_patch8_func, 431, 3, 3 },
+	{ ahc_patch6_func, 432, 1, 2 },
+	{ ahc_patch0_func, 433, 1, 1 },
+	{ ahc_patch9_func, 434, 1, 1 },
+	{ ahc_patch15_func, 435, 1, 2 },
+	{ ahc_patch13_func, 435, 1, 1 },
+	{ ahc_patch14_func, 437, 9, 4 },
+	{ ahc_patch9_func, 437, 1, 1 },
+	{ ahc_patch9_func, 444, 2, 1 },
+	{ ahc_patch0_func, 446, 4, 3 },
+	{ ahc_patch9_func, 446, 1, 2 },
+	{ ahc_patch0_func, 447, 3, 1 },
+	{ ahc_patch1_func, 451, 2, 1 },
+	{ ahc_patch7_func, 453, 10, 2 },
+	{ ahc_patch0_func, 463, 1, 1 },
+	{ ahc_patch8_func, 464, 118, 22 },
+	{ ahc_patch1_func, 466, 3, 2 },
+	{ ahc_patch0_func, 469, 5, 3 },
+	{ ahc_patch9_func, 469, 2, 2 },
+	{ ahc_patch0_func, 471, 3, 1 },
+	{ ahc_patch1_func, 476, 2, 2 },
+	{ ahc_patch0_func, 478, 6, 3 },
+	{ ahc_patch9_func, 478, 2, 2 },
+	{ ahc_patch0_func, 480, 3, 1 },
+	{ ahc_patch1_func, 486, 2, 2 },
+	{ ahc_patch0_func, 488, 9, 7 },
+	{ ahc_patch9_func, 488, 5, 6 },
+	{ ahc_patch19_func, 488, 1, 2 },
+	{ ahc_patch0_func, 489, 1, 1 },
+	{ ahc_patch19_func, 491, 1, 2 },
+	{ ahc_patch0_func, 492, 1, 1 },
+	{ ahc_patch0_func, 493, 4, 1 },
+	{ ahc_patch6_func, 498, 3, 2 },
+	{ ahc_patch0_func, 501, 1, 1 },
+	{ ahc_patch6_func, 511, 1, 2 },
+	{ ahc_patch0_func, 512, 1, 1 },
+	{ ahc_patch20_func, 549, 7, 1 },
+	{ ahc_patch3_func, 584, 1, 2 },
+	{ ahc_patch0_func, 585, 1, 1 },
+	{ ahc_patch21_func, 588, 1, 1 },
+	{ ahc_patch8_func, 590, 106, 33 },
+	{ ahc_patch4_func, 592, 1, 1 },
+	{ ahc_patch1_func, 598, 2, 2 },
+	{ ahc_patch0_func, 600, 1, 1 },
+	{ ahc_patch1_func, 603, 1, 2 },
+	{ ahc_patch0_func, 604, 1, 1 },
+	{ ahc_patch9_func, 605, 3, 3 },
+	{ ahc_patch15_func, 606, 1, 1 },
+	{ ahc_patch0_func, 608, 4, 1 },
+	{ ahc_patch19_func, 617, 2, 2 },
+	{ ahc_patch0_func, 619, 1, 1 },
+	{ ahc_patch19_func, 623, 10, 3 },
+	{ ahc_patch5_func, 625, 8, 1 },
+	{ ahc_patch0_func, 633, 9, 2 },
+	{ ahc_patch5_func, 634, 8, 1 },
+	{ ahc_patch4_func, 644, 1, 2 },
+	{ ahc_patch0_func, 645, 1, 1 },
+	{ ahc_patch19_func, 646, 1, 2 },
+	{ ahc_patch0_func, 647, 3, 2 },
+	{ ahc_patch4_func, 649, 1, 1 },
+	{ ahc_patch5_func, 650, 1, 1 },
+	{ ahc_patch5_func, 653, 1, 1 },
+	{ ahc_patch5_func, 655, 1, 1 },
+	{ ahc_patch4_func, 657, 2, 2 },
+	{ ahc_patch0_func, 659, 2, 1 },
+	{ ahc_patch5_func, 661, 1, 1 },
+	{ ahc_patch5_func, 664, 1, 1 },
+	{ ahc_patch5_func, 667, 1, 1 },
+	{ ahc_patch19_func, 671, 1, 1 },
+	{ ahc_patch19_func, 674, 1, 1 },
+	{ ahc_patch4_func, 680, 1, 1 },
+	{ ahc_patch6_func, 683, 1, 2 },
+	{ ahc_patch0_func, 684, 1, 1 },
+	{ ahc_patch7_func, 696, 16, 1 },
+	{ ahc_patch4_func, 712, 20, 1 },
+	{ ahc_patch9_func, 733, 4, 2 },
+	{ ahc_patch0_func, 737, 4, 1 },
+	{ ahc_patch9_func, 741, 4, 2 },
+	{ ahc_patch0_func, 745, 3, 1 },
+	{ ahc_patch6_func, 751, 1, 1 },
+	{ ahc_patch22_func, 753, 14, 1 },
+	{ ahc_patch7_func, 767, 3, 1 },
+	{ ahc_patch9_func, 779, 24, 8 },
+	{ ahc_patch19_func, 783, 1, 2 },
+	{ ahc_patch0_func, 784, 1, 1 },
+	{ ahc_patch15_func, 789, 4, 2 },
+	{ ahc_patch0_func, 793, 7, 3 },
+	{ ahc_patch23_func, 793, 5, 2 },
+	{ ahc_patch0_func, 798, 2, 1 },
+	{ ahc_patch0_func, 803, 42, 3 },
+	{ ahc_patch18_func, 815, 18, 2 },
+	{ ahc_patch0_func, 833, 1, 1 },
+	{ ahc_patch4_func, 857, 1, 1 },
+	{ ahc_patch4_func, 858, 3, 2 },
+	{ ahc_patch0_func, 861, 1, 1 },
+	{ ahc_patch13_func, 862, 3, 1 },
+	{ ahc_patch4_func, 865, 12, 1 }
 };
 
 static struct cs {
@@ -1296,11 +1297,11 @@ static struct cs {
 } critical_sections[] = {
 	{ 11, 18 },
 	{ 21, 30 },
-	{ 711, 727 },
-	{ 857, 860 },
-	{ 864, 870 },
-	{ 872, 874 },
-	{ 874, 876 }
+	{ 712, 728 },
+	{ 858, 861 },
+	{ 865, 871 },
+	{ 873, 875 },
+	{ 875, 877 }
 };
 
 static const int num_critical_sections = sizeof(critical_sections)
diff -puN drivers/scsi/aic7xxx/aicasm/aicasm.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aicasm/aicasm.c
--- 25/drivers/scsi/aic7xxx/aicasm/aicasm.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aicasm/aicasm.c	Wed Dec 24 12:15:38 2003
@@ -37,7 +37,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#22 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#23 $
  *
  * $FreeBSD$
  */
@@ -609,10 +609,10 @@ output_listing(char *ifilename)
 
 		while (line < cur_instr->srcline) {
 			fgets(buf, sizeof(buf), ifile);
-				fprintf(listfile, "\t\t%s", buf);
+				fprintf(listfile, "             \t%s", buf);
 				line++;
 		}
-		fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr,
+		fprintf(listfile, "%04x %02x%02x%02x%02x", instrptr,
 #if BYTE_ORDER == LITTLE_ENDIAN
 			cur_instr->format.bytes[0],
 			cur_instr->format.bytes[1],
@@ -624,14 +624,23 @@ output_listing(char *ifilename)
 			cur_instr->format.bytes[1],
 			cur_instr->format.bytes[0]);
 #endif
-		fgets(buf, sizeof(buf), ifile);
-		fprintf(listfile, "\t%s", buf);
-		line++;
+		/*
+		 * Macro expansions can cause several instructions
+		 * to be output for a single source line.  Only
+		 * advance the line once in these cases.
+		 */
+		if (line == cur_instr->srcline) {
+			fgets(buf, sizeof(buf), ifile);
+			fprintf(listfile, "\t%s", buf);
+			line++;
+		} else {
+			fprintf(listfile, "\n");
+		}
 		instrptr++;
 	}
 	/* Dump the remainder of the file */
 	while(fgets(buf, sizeof(buf), ifile) != NULL)
-		fprintf(listfile, "\t\t%s", buf);
+		fprintf(listfile, "             %s", buf);
 
 	fclose(ifile);
 }
diff -puN drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l
--- 25/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l	Wed Dec 24 12:15:38 2003
@@ -38,7 +38,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_macro_scan.l#7 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_macro_scan.l#8 $
  *
  * $FreeBSD$
  */
@@ -78,6 +78,7 @@ MCARG		[^(), \t]+
 \n			{
 				++yylineno;
 			}
+\r			;
 <ARGLIST>{SPACE}	;
 <ARGLIST>\(		{
 				parren_count++;
diff -puN drivers/scsi/aic7xxx/aicasm/aicasm_scan.l~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
--- 25/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l	Wed Dec 24 12:15:38 2003
@@ -38,7 +38,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#18 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#19 $
  *
  * $FreeBSD$
  */
@@ -87,6 +87,7 @@ MBODY		((\\[^\n])*[^\n\\]*)+
 
 %%
 \n			{ ++yylineno; }
+\r			;
 "/*"			{ BEGIN COMMENT;  /* Enter comment eating state */ }
 <COMMENT>"/*"		{ fprintf(stderr, "Warning! Comment within comment."); }
 <COMMENT>\n		{ ++yylineno; }
@@ -114,6 +115,7 @@ if[ \t]*\(		{
 				}
 			}
 <CEXPR>\n		{ ++yylineno; }
+<CEXPR>\r		;
 <CEXPR>[^()\n]+	{
 				char *yptr;
 
@@ -359,6 +361,7 @@ else			{ return T_ELSE; }
 				/* Eat escaped newlines. */
 				++yylineno;
 			}
+<MACROBODY>\r		;
 <MACROBODY>\n		{
 				/* Macros end on the first unescaped newline. */
 				BEGIN INITIAL;
@@ -369,10 +372,17 @@ else			{ return T_ELSE; }
 			}
 <MACROBODY>{MBODY}	{
 				char *yptr;
+				char c;
 
 				yptr = yytext;
-				while (*yptr)
-					*string_buf_ptr++ = *yptr++;
+				while (c = *yptr++) {
+					/*
+					 * Strip carriage returns.
+					 */
+					if (c == '\r')
+						continue;
+					*string_buf_ptr++ = c;
+				}
 			}
 {WORD}\(		{
 				char *yptr;
diff -puN drivers/scsi/aic7xxx/aicasm/Makefile~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aicasm/Makefile
--- 25/drivers/scsi/aic7xxx/aicasm/Makefile~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aicasm/Makefile	Wed Dec 24 12:15:38 2003
@@ -49,11 +49,19 @@ aicdb.h:
 clean:
 	rm -f $(clean-files)
 
+# Create a dependency chain in generated files
+# to avoid concurrent invocations of the single
+# rule that builds them all.
+aicasm_gram.c: aicasm_gram.h
 aicasm_gram.c aicasm_gram.h: aicasm_gram.y
 	$(YACC) $(YFLAGS) -b $(<:.y=) $<
 	mv $(<:.y=).tab.c $(<:.y=.c)
 	mv $(<:.y=).tab.h $(<:.y=.h)
 
+# Create a dependency chain in generated files
+# to avoid concurrent invocations of the single
+# rule that builds them all.
+aicasm_macro_gram.c: aicasm_macro_gram.h
 aicasm_macro_gram.c aicasm_macro_gram.h: aicasm_macro_gram.y
 	$(YACC) $(YFLAGS) -b $(<:.y=) -p mm $<
 	mv $(<:.y=).tab.c $(<:.y=.c)
diff -puN drivers/scsi/aic7xxx/aiclib.c~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aiclib.c
--- 25/drivers/scsi/aic7xxx/aiclib.c~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aiclib.c	Wed Dec 24 12:15:38 2003
@@ -30,16 +30,6 @@
  * $Id$
  */
 
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/version.h>
-
-/* Core SCSI definitions */
-#include "scsi.h"
-#include "hosts.h"
-#include "aiclib.h"
-#include "cam.h"
-
 #ifndef FALSE
 #define FALSE   0
 #endif /* FALSE */
@@ -1410,3 +1400,336 @@ aic_parse_brace_option(char *opt_name, c
 	}
 	return (opt_arg);
 }
+
+/************************* Magic SysReq Support *******************************/
+void
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+aic_sysrq_handler(int key, struct pt_regs *unused, struct kbd_struct *unused1,
+		  struct tty_struct *unused2)
+#else
+aic_sysrq_handler(int key, struct pt_regs *unused, struct tty_struct *unused2)
+#endif
+{
+#ifdef CONFIG_MAGIC_SYSRQ
+	struct aic_softc *aic;
+	u_long l;
+
+	aic_list_lock(&l);
+
+	TAILQ_FOREACH(aic, &aic_tailq, links) {
+		u_long s;
+
+		aic_lock(aic, &s);
+		aic_dump_card_state(aic);
+		aic_unlock(aic, &s);
+	}
+	aic_list_unlock(&l);
+#endif
+}
+
+int
+aic_install_sysrq(struct aic_sysrq_key_op *key_op)
+{
+#ifdef CONFIG_MAGIC_SYSRQ
+	char *str;
+	int len;
+	int i;
+
+	str = key_op->help_msg;
+	len = strlen(str);
+	for (i = 0; i < len; i++) {
+		int key;
+
+		key = str[i];
+		if (register_sysrq_key(key, key_op) == 0) {
+
+			if (key >= 'a' && key <= 'z')
+				str[i] = key + ('A' - 'a');
+			return (key);
+		}
+	}
+#endif
+	return (0);
+}
+
+void
+aic_remove_sysrq(int key, struct aic_sysrq_key_op *key_op)
+{
+#ifdef CONFIG_MAGIC_SYSRQ
+	unregister_sysrq_key(key, key_op);
+#endif
+}
+
+/******************************** Bus DMA *************************************/
+int
+aic_dma_tag_create(struct aic_softc *aic, bus_dma_tag_t parent,
+		   bus_size_t alignment, bus_size_t boundary,
+		   bus_addr_t lowaddr, bus_addr_t highaddr,
+		   bus_dma_filter_t *filter, void *filterarg,
+		   bus_size_t maxsize, int nsegments,
+		   bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag)
+{
+	bus_dma_tag_t dmat;
+
+	dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT);
+	if (dmat == NULL)
+		return (ENOMEM);
+
+	/*
+	 * Linux is very simplistic about DMA memory.  For now don't
+	 * maintain all specification information.  Once Linux supplies
+	 * better facilities for doing these operations, or the
+	 * needs of this particular driver change, we might need to do
+	 * more here.
+	 */
+	dmat->alignment = alignment;
+	dmat->boundary = boundary;
+	dmat->maxsize = maxsize;
+	*ret_tag = dmat;
+	return (0);
+}
+
+void
+aic_dma_tag_destroy(struct aic_softc *aic, bus_dma_tag_t dmat)
+{
+	free(dmat, M_DEVBUF);
+}
+
+int
+aic_dmamem_alloc(struct aic_softc *aic, bus_dma_tag_t dmat, void** vaddr,
+		 int flags, bus_dmamap_t *mapp)
+{
+	bus_dmamap_t map;
+
+	map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT);
+	if (map == NULL)
+		return (ENOMEM);
+	/*
+	 * Although we can dma data above 4GB, our
+	 * coherent memory is below 4GB for
+	 * space efficiency reasons (only need a 4byte
+	 * address).  For this reason, we have to reset
+	 * our dma mask when doing allocations.
+	 */
+	aic_set_dma_mask(aic, 0xFFFFFFFF);
+	*vaddr = aic_alloc_coherent(aic, dmat->maxsize, &map->bus_addr);
+	aic_set_dma_mask(aic, aic->platform_data->hw_dma_mask);
+	if (*vaddr == NULL)
+		return (ENOMEM);
+	*mapp = map;
+	return(0);
+}
+
+void
+aic_dmamem_free(struct aic_softc *aic, bus_dma_tag_t dmat,
+		void* vaddr, bus_dmamap_t map)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+	aic_free_coherent(aic, dmat->maxsize, vaddr, map->bus_addr);
+#else
+	free(vaddr, M_DEVBUF);
+#endif
+}
+
+int
+aic_dmamap_load(struct aic_softc *aic, bus_dma_tag_t dmat, bus_dmamap_t map,
+		void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb,
+		void *cb_arg, int flags)
+{
+	/*
+	 * Assume for now that this will only be used during
+	 * initialization and not for per-transaction buffer mapping.
+	 */
+	bus_dma_segment_t stack_sg;
+
+	stack_sg.ds_addr = map->bus_addr;
+	stack_sg.ds_len = dmat->maxsize;
+	cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);
+	return (0);
+}
+
+void
+aic_dmamap_destroy(struct aic_softc *aic, bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+	free(map, M_DEVBUF);
+}
+
+int
+aic_dmamap_unload(struct aic_softc *aic, bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+	/* Nothing to do */
+	return (0);
+}
+
+/***************************** Queue Handling ********************************/
+/*
+ * In 2.4.X and above, this routine is called from a tasklet,
+ * so we must re-acquire our lock prior to executing this code.
+ * In all prior kernels, aic_schedule_runq() calls this routine
+ * directly and aic_schedule_runq() is called with our lock held.
+ */
+void
+aic_runq_tasklet(unsigned long data)
+{
+	struct aic_softc* aic;
+	struct aic_linux_device *dev;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	u_long flags;
+#endif
+
+	aic = (struct aic_softc *)data;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	aic_lock(aic, &flags);
+#endif
+	while ((dev = aic_linux_next_device_to_run(aic)) != NULL) {
+	
+		TAILQ_REMOVE(&aic->platform_data->device_runq, dev, links);
+		dev->flags &= ~AIC_DEV_ON_RUN_LIST;
+		aic_linux_check_device_queue(aic, dev);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+		/* Yeild to our interrupt handler */
+		aic_unlock(aic, &flags);
+		aic_lock(aic, &flags);
+#endif
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	aic_unlock(aic, &flags);
+#endif
+}
+
+void
+aic_unblock_tasklet(unsigned long data)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	struct aic_softc* aic;
+
+	aic = (struct aic_softc *)data;
+	scsi_unblock_requests(aic->platform_data->host);
+#else
+#error "Fix 2.2.X Kernel Support"
+#endif
+}
+
+void
+aic_bus_settle_complete(u_long data)
+{
+	struct aic_softc *aic;
+	u_long s;
+
+	aic = (struct aic_softc *)data;
+	/*
+	 * Guard against our bottom half scheduling another
+	 * bus settle delay just as our timer runs.  If this
+	 * occurs, do nothing.  The newly scheduled timer will
+	 * take care of things.
+	 */
+	aic_lock(aic, &s);
+	if (timer_pending(&aic->platform_data->bus_settle_timer) == 0) {
+		aic->platform_data->flags &= ~AIC_BUS_SETTLE_TIMER;
+		aic_release_simq_locked(aic);
+	}
+	aic_unlock(aic, &s);
+}
+
+void
+aic_freeze_simq(struct aic_softc *aic)
+{
+	aic->platform_data->qfrozen++;
+	if (aic->platform_data->qfrozen == 1)
+		scsi_block_requests(aic->platform_data->host);
+}
+
+void
+aic_release_simq(struct aic_softc *aic)
+{
+	u_long s;
+
+	aic_lock(aic, &s);
+	aic_release_simq_locked(aic);
+	aic_unlock(aic, &s);
+}
+
+void
+aic_release_simq_locked(struct aic_softc *aic)
+{
+
+	if (aic->platform_data->qfrozen > 0)
+		aic->platform_data->qfrozen--;
+	if (AIC_DV_SIMQ_FROZEN(aic)
+	 && ((aic->platform_data->flags & AIC_DV_WAIT_SIMQ_RELEASE) != 0)) {
+		aic->platform_data->flags &= ~AIC_DV_WAIT_SIMQ_RELEASE;
+		up(&aic->platform_data->dv_sem);
+	}
+	if (aic->platform_data->qfrozen == 0) {
+		aic_schedule_unblock(aic);
+		aic_schedule_runq(aic);
+	}
+}
+
+/***************************** Timer Facilities *******************************/
+void
+aic_platform_timeout(struct scsi_cmnd *cmd)
+{
+
+	if (AIC_DV_CMD(cmd) != 0) {
+
+		aic_linux_dv_timeout(cmd);
+	} else {
+		struct	scb *scb;
+		struct	aic_softc *aic;
+		u_long	s;
+
+		scb = (struct scb *)cmd->host_scribble;
+		aic = scb->aic_softc;
+		aic_lock(aic, &s);
+
+		if (scb == NULL
+		 || scb->flags == SCB_FLAG_NONE) {
+			int done_late;
+
+			/*
+			 * Handle timeout/completion races.
+			 * If the command is still sitting on
+			 * our completion queue, just re-instate
+			 * the timeout.  If we've already completed
+			 * the command, the function pointer in our
+			 * timer will be cleared and we will need to
+			 * additionally complete it again to the mid-layer.
+			 *
+			 * Since done_late is cleared by adding a
+			 * timer, we must save off its value first.
+			 */
+			done_late = cmd->eh_timeout.function == NULL;
+			scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout);
+			if (done_late)
+				cmd->scsi_done(cmd);
+		} else if ((scb->platform_data->flags & AIC_TIMEOUT_ACTIVE)) {
+
+			/*
+			 * Handle the case of timeouts that expire just
+			 * as we delete timers during recovery by skipping
+			 * SCBs that don't have timers active.
+			 */
+			scb->platform_data->flags &= ~AIC_TIMEOUT_ACTIVE;
+
+			/*
+			 * We must clear out the function pointer so that
+			 * scsi_add_timer does not believe that a del_timer
+			 * is required before setting up a new timer for
+			 * this command.
+			 */
+			scb->io_ctx->eh_timeout.function = NULL;
+			aic_timeout(scb);
+		}
+		aic_unlock(aic, &s);
+	}
+}
+
+void
+aic_linux_midlayer_timeout(struct scsi_cmnd *cmd)
+{
+	struct aic_softc *aic;
+
+	aic = *(struct aic_softc **)cmd->device->host->hostdata;
+	printf("%s: midlayer_timeout\n", aic_name(aic));
+}
diff -puN drivers/scsi/aic7xxx/aiclib.h~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/aiclib.h
--- 25/drivers/scsi/aic7xxx/aiclib.h~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/aiclib.h	Wed Dec 24 12:15:38 2003
@@ -1,4 +1,5 @@
 /*
+ * SCSI definitions...
  * Largely written by Julian Elischer (julian@tfs.com)
  * for TRW Financial Systems.
  *
@@ -57,6 +58,42 @@
 #ifndef	_AICLIB_H
 #define _AICLIB_H
 
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/smp_lock.h>
+#include <linux/module.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#include <linux/slab.h>
+#else
+#include <linux/malloc.h>
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#include <linux/interrupt.h> /* For tasklet support. */
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include <linux/blk.h>
+#endif
+#include <linux/blkdev.h>
+
+#include "scsi.h"
+#include "hosts.h"
+
+/* Name space conflict with BSD queue macros */
+#ifdef LIST_HEAD
+#undef LIST_HEAD
+#endif
+#include "cam.h"
+#include "queue.h"
+#include "scsi_message.h"
+#include "scsi_iu.h"
+
 /*
  * Linux Interrupt Support.
  */
@@ -66,9 +103,731 @@ typedef void irqreturn_t;
 #endif
 
 /*
- * SCSI command format
+ * Linux Timer Support.
+ */
+#define AIC_USECS_PER_JIFFY (1000000/HZ)
+
+/**************************** Module Library Hack *****************************/
+/*
+ * What we'd like to do is have a single "scsi library" module that both the
+ * aic7xxx and aic79xx drivers could load and depend on.  A cursory examination
+ * of implementing module dependencies in Linux (handling the install and
+ * initrd cases) does not look promissing.  For now, we just duplicate this
+ * code in both drivers using a simple symbol renaming scheme that hides this
+ * hack from the drivers.
+ */
+#define AIC_LIB_ENTRY_CONCAT(x, prefix)	prefix ## x
+#define	AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix)
+#define AIC_LIB_ENTRY(x)		AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX)
+
+#define AIC_CONST_ENTRY(x)		AIC_LIB_ENTRY_EXPAND(x,AIC_CONST_PREFIX)
+
+#define	aic_sense_desc			AIC_LIB_ENTRY(_sense_desc)
+#define	aic_sense_error_action		AIC_LIB_ENTRY(_sense_error_action)
+#define	aic_error_action		AIC_LIB_ENTRY(_error_action)
+#define	aic_op_desc			AIC_LIB_ENTRY(_op_desc)
+#define	aic_cdb_string			AIC_LIB_ENTRY(_cdb_string)
+#define aic_print_inquiry		AIC_LIB_ENTRY(_print_inquiry)
+#define aic_calc_syncsrate		AIC_LIB_ENTRY(_calc_syncrate)
+#define	aic_calc_syncparam		AIC_LIB_ENTRY(_calc_syncparam)
+#define	aic_calc_speed			AIC_LIB_ENTRY(_calc_speed)
+#define	aic_inquiry_match		AIC_LIB_ENTRY(_inquiry_match)
+#define	aic_static_inquiry_match	AIC_LIB_ENTRY(_static_inquiry_match)
+#define	aic_parse_brace_option		AIC_LIB_ENTRY(_parse_brace_option)
+#define	aic_power_state_change		AIC_LIB_ENTRY(_power_state_change)
+#define	aic_sysrq_handler		AIC_LIB_ENTRY(_sysrq_handler)
+#define	aic_install_sysrq		AIC_LIB_ENTRY(_install_sysrq)
+#define	aic_remove_sysrq		AIC_LIB_ENTRY(_remove_sysrq)
+#define	aic_list_lock			AIC_LIB_ENTRY(_list_lock)
+#define	aic_list_unlock			AIC_LIB_ENTRY(_list_unlock)
+#define	aic_lock			AIC_LIB_ENTRY(_lock)
+#define	aic_unlock			AIC_LIB_ENTRY(_unlock)
+#define	aic_dump_card_state		AIC_LIB_ENTRY(_dump_card_state)
+#define	aic_linux_dv_complete		AIC_LIB_ENTRY(_linux_dv_complete)
+#define	aic_linux_run_device_queue	AIC_LIB_ENTRY(_linux_run_device_queue)
+#define	aic_linux_dv_timeout		AIC_LIB_ENTRY(_linux_dv_timeout)
+#define	aic_linux_midlayer_timeout	AIC_LIB_ENTRY(_linux_midlayer_timeout)
+#define	aic_freeze_simq			AIC_LIB_ENTRY(_freeze_simq)
+#define	aic_bus_settle_complete		AIC_LIB_ENTRY(_bus_settle_complete)
+#define	aic_release_simq		AIC_LIB_ENTRY(_release_simq)
+#define	aic_release_simq		AIC_LIB_ENTRY(_release_simq)
+#define	aic_release_simq_locked		AIC_LIB_ENTRY(_release_simq_locked)
+#define	aic_dma_tag_create		AIC_LIB_ENTRY(_dma_tag_create)
+#define	aic_dma_tag_destroy		AIC_LIB_ENTRY(_dma_tag_destroy)
+#define	aic_dmamem_alloc		AIC_LIB_ENTRY(_dmamem_alloc)
+#define	aic_dmamem_free			AIC_LIB_ENTRY(_dmamem_free)
+#define	aic_dmamap_create		AIC_LIB_ENTRY(_dmamap_create)
+#define	aic_dmamap_destroy		AIC_LIB_ENTRY(_dmamap_destroy)
+#define	aic_dmamap_load			AIC_LIB_ENTRY(_dmamap_load)
+#define	aic_dmamap_unload		AIC_LIB_ENTRY(_dmamap_unload)
+#define	aic_dmamap_destroy		AIC_LIB_ENTRY(_dmamap_destroy)
+#define	aic_timeout			AIC_LIB_ENTRY(_timeout)
+#define	aic_runq_tasklet		AIC_LIB_ENTRY(_runq_tasklet)
+#define	aic_unblock_tasklet		AIC_LIB_ENTRY(_unblock_tasklet)
+#define	aic_platform_timeout		AIC_LIB_ENTRY(_platform_timeout)
+#define	aic_name			AIC_LIB_ENTRY(_name)
+
+#define	aic_tailq			AIC_LIB_ENTRY(_tailq)
+#define	aic_softc			AIC_LIB_ENTRY(_softc)
+#define	aic_transinfo			AIC_LIB_ENTRY(_transinfo)
+#define	aic_platform_data		AIC_LIB_ENTRY(_platform_data)
+#define	aic_devinfo			AIC_LIB_ENTRY(_devinfo)
+#define	aic_callback_t			AIC_LIB_ENTRY(_callback_t)
+
+#define	AIC_NUM_LUNS			AIC_CONST_ENTRY(_NUM_LUNS)
+#define	AIC_NUM_TARGETS			AIC_CONST_ENTRY(_NUM_TARGETS)
+#define	AIC_RESOURCE_SHORTAGE		AIC_CONST_ENTRY(_RESOURCE_SHORTAGE)
+
+/*************************** Forward Declarations *****************************/
+struct aic_softc;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+typedef struct device *aic_dev_softc_t;
+#else
+typedef struct pci_dev *aic_dev_softc_t;
+#endif
+typedef Scsi_Cmnd     *aic_io_ctx_t;
+
+/*************************** Timer DataStructures *****************************/
+typedef struct timer_list aic_timer_t;
+
+/***************************** Bus Space/DMA **********************************/
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17)
+typedef dma_addr_t bus_addr_t;
+#else
+typedef uint32_t bus_addr_t;
+#endif
+typedef uint32_t bus_size_t;
+
+typedef enum {
+	BUS_SPACE_MEMIO,
+	BUS_SPACE_PIO
+} bus_space_tag_t;
+
+typedef union {
+	u_long		  ioport;
+	volatile uint8_t *maddr;
+} bus_space_handle_t;
+
+typedef struct bus_dma_segment
+{
+	bus_addr_t	ds_addr;
+	bus_size_t	ds_len;
+} bus_dma_segment_t;
+
+struct aic_linux_dma_tag
+{
+	bus_size_t	alignment;
+	bus_size_t	boundary;
+	bus_size_t	maxsize;
+};
+typedef struct aic_linux_dma_tag* bus_dma_tag_t;
+
+struct aic_linux_dmamap
+{
+	bus_addr_t	bus_addr;
+};
+typedef struct aic_linux_dmamap* bus_dmamap_t;
+
+typedef int bus_dma_filter_t(void*, bus_addr_t);
+typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
+
+#define BUS_DMA_WAITOK		0x0
+#define BUS_DMA_NOWAIT		0x1
+#define BUS_DMA_ALLOCNOW	0x2
+#define BUS_DMA_LOAD_SEGS	0x4	/*
+					 * Argument is an S/G list not
+					 * a single buffer.
+					 */
+
+#define BUS_SPACE_MAXADDR	0xFFFFFFFF
+#define BUS_SPACE_MAXADDR_32BIT	0xFFFFFFFF
+#define BUS_SPACE_MAXSIZE_32BIT	0xFFFFFFFF
+
+int	aic_dma_tag_create(struct aic_softc *, bus_dma_tag_t /*parent*/,
+			   bus_size_t /*alignment*/, bus_size_t /*boundary*/,
+			   bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/,
+			   bus_dma_filter_t*/*filter*/, void */*filterarg*/,
+			   bus_size_t /*maxsize*/, int /*nsegments*/,
+			   bus_size_t /*maxsegsz*/, int /*flags*/,
+			   bus_dma_tag_t */*dma_tagp*/);
+
+void	aic_dma_tag_destroy(struct aic_softc *, bus_dma_tag_t /*tag*/);
+
+int	aic_dmamem_alloc(struct aic_softc *, bus_dma_tag_t /*dmat*/,
+			 void** /*vaddr*/, int /*flags*/,
+			 bus_dmamap_t* /*mapp*/);
+
+void	aic_dmamem_free(struct aic_softc *, bus_dma_tag_t /*dmat*/,
+			void* /*vaddr*/, bus_dmamap_t /*map*/);
+
+void	aic_dmamap_destroy(struct aic_softc *, bus_dma_tag_t /*tag*/,
+			   bus_dmamap_t /*map*/);
+
+int	aic_dmamap_load(struct aic_softc *aic, bus_dma_tag_t /*dmat*/,
+			bus_dmamap_t /*map*/, void * /*buf*/,
+			bus_size_t /*buflen*/, bus_dmamap_callback_t *,
+			void */*callback_arg*/, int /*flags*/);
+
+int	aic_dmamap_unload(struct aic_softc *, bus_dma_tag_t, bus_dmamap_t);
+
+/*
+ * Operations performed by aic_dmamap_sync().
  */
+#define BUS_DMASYNC_PREREAD	0x01	/* pre-read synchronization */
+#define BUS_DMASYNC_POSTREAD	0x02	/* post-read synchronization */
+#define BUS_DMASYNC_PREWRITE	0x04	/* pre-write synchronization */
+#define BUS_DMASYNC_POSTWRITE	0x08	/* post-write synchronization */
+
+/*
+ * XXX
+ * aic_dmamap_sync is only used on buffers allocated with
+ * the pci_alloc_consistent() API.  Although I'm not sure how
+ * this works on architectures with a write buffer, Linux does
+ * not have an API to sync "coherent" memory.  Perhaps we need
+ * to do an mb()?
+ */
+#define aic_dmamap_sync(aic, dma_tag, dmamap, offset, len, op)
+
+/*************************** Linux DMA Wrappers *******************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define	aic_alloc_coherent(aic, size, bus_addr_ptr) \
+	dma_alloc_coherent(aic->dev_softc, size, bus_addr_ptr, /*flag*/0)
+
+#define	aic_free_coherent(aic, size, vaddr, bus_addr) \
+	dma_free_coherent(aic->dev_softc, size, vaddr, bus_addr)
+
+#define	aic_map_single(aic, buf, size, direction) \
+	dma_map_single(aic->dev_softc, buf, size, direction)
+
+#define	aic_unmap_single(aic, busaddr, size, direction) \
+	dma_unmap_single(aic->dev_softc, busaddr, size, direction)
+
+#define	aic_map_sg(aic, sg_list, num_sg, direction) \
+	dma_map_sg(aic->dev_softc, sg_list, num_sg, direction)
+
+#define	aic_unmap_sg(aic, sg_list, num_sg, direction) \
+	dma_unmap_sg(aic->dev_softc, sg_list, num_sg, direction)
+
+#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
+
+#define	aic_alloc_coherent(aic, size, bus_addr_ptr) \
+	pci_alloc_consistent(aic->dev_softc, size, bus_addr_ptr)
+
+#define	aic_free_coherent(aic, size, vaddr, bus_addr) \
+	pci_free_consistent(aic->dev_softc, size, vaddr, bus_addr)
+
+#define	aic_map_single(aic, buf, size, direction) \
+	pci_map_single(aic->dev_softc, buf, size, direction)
+
+#define	aic_unmap_single(aic, busaddr, size, direction) \
+	pci_unmap_single(aic->dev_softc, busaddr, size, direction)
+
+#define	aic_map_sg(aic, sg_list, num_sg, direction) \
+	pci_map_sg(aic->dev_softc, sg_list, num_sg, direction)
+
+#define	aic_unmap_sg(aic, sg_list, num_sg, direction) \
+	pci_unmap_sg(aic->dev_softc, sg_list, num_sg, direction)
+
+#else
+
+static __inline void *aic_alloc_coherent(struct aic_softc *aic,
+					 bus_size_t size, bus_addr_t *baddrp);
+
+/*
+ * At least in 2.2.14, malloc is a slab allocator so all
+ * allocations are aligned.  We assume for these kernel versions
+ * that all allocations will be bellow 4Gig, physically contiguous,
+ * and accessible via DMA by the controller.
+ */
+static __inline void *
+aic_alloc_coherent(struct aic_softc *aic, bus_size_t size, bus_addr_t *baddrp)
+{
+	void *vaddr;
+
+	vaddr_ = malloc(size, M_DEVBUF, M_NOWAIT);
+	if (vaddr != NULL)
+		*baddrp = virt_to_bus(vaddr);
+	return (vaddr);
+}
+
+#define	aic_free_coherent(aic, size, vaddr, bus_addr) \
+	free(vaddr, M_DEVBUF)
+
+#define aic_map_sg(pdev, sg_list, nseg, direction) (nseg)
+#define aic_unmap_sg(pdev, sg_list, nseg, direction)
+#define aic_map_single(pdev, buffer, bufflen, direction) \
+	(VIRT_TO_BUS(buffer))
+#define aic_unmap_single(pdev, buffer, buflen, direction)
+#define sg_dma_address(sg) (VIRT_TO_BUS((sg)->address))
+#define sg_dma_len(sg) ((sg)->length)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+
+#define aic_set_dma_mask(aic, mask) dma_set_mask(aic->dev_softc, mask)
+
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
+
+/*
+ * Device softc is NULL for EISA devices.
+ */
+#define aic_set_dma_mask(aic, mask) 			\
+	((aic)->dev_softc == NULL ? 0 : pci_set_dma_mask(aic->dev_softc, mask))
+
+#else
+/*
+ * Device softc is NULL for EISA devices.
+ * Always "return" 0 for success.
+ */
+#define aic_set_dma_mask(aic, mask)			\
+    (((aic)->dev_softc == NULL)				\
+     ? 0						\
+     : (((aic)->dev_softc->dma_mask = mask) && 0))
+#endif
+
+/************************* Host Template Macros *******************************/
+#if defined CONFIG_HIGHIO
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10)
+/* Assume RedHat Distribution with its different HIGHIO conventions. */
+#define	AIC_TEMPLATE_DMA_SETTINGS()	\
+	.can_dma_32		= 1,	\
+	.single_sg_okay		= 1,
+#else
+#define	AIC_TEMPLATE_DMA_SETTINGS()	\
+	.highmem_io		= 1,
+#endif
+#else
+#define	AIC_TEMPLATE_DMA_SETTINGS()
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
+#define	AIC_TEMPLATE_MAX_SECTORS(sectors) \
+	.max_sectors		= (sectors),
+#else
+#define	AIC_TEMPLATE_MAX_SECTORS(sectors)
+#endif
+
+#if defined(__i386__)
+#define	AIC_TEMPLATE_BIOSPARAM() \
+	.bios_param		= AIC_LIB_ENTRY(_linux_biosparam),
+#else
+#define	AIC_TEMPLATE_BIOSPARAM()
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define	AIC_TEMPLATE_VERSIONED_ENTRIES() \
+	.slave_alloc		= AIC_LIB_ENTRY(_linux_slave_alloc), \
+	.slave_configure	= AIC_LIB_ENTRY(_linux_slave_configure), \
+	.slave_destroy		= AIC_LIB_ENTRY(_linux_slave_destroy)
+#else
+#define	AIC_TEMPLATE_VERSIONED_ENTRIES() \
+	.detect			= AIC_LIB_ENTRY(_linux_detect), \
+	.release		= AIC_LIB_ENTRY(_linux_release), \
+	.select_queue_depths	= AIC_LIB_ENTRY(_linux_select_queue_depth), \
+	.use_new_eh_code	= 1
+#endif
+
+#define AIC_TEMPLATE_INITIALIZER(NAME, MAX_SECTORS)			\
+{									\
+	.module			= THIS_MODULE,				\
+	.name			= NAME,					\
+	.proc_info		= AIC_LIB_ENTRY(_linux_proc_info),	\
+	.info			= AIC_LIB_ENTRY(_linux_info),		\
+	.queuecommand		= AIC_LIB_ENTRY(_linux_queue),		\
+	.eh_abort_handler	= AIC_LIB_ENTRY(_linux_abort),		\
+	.eh_device_reset_handler = AIC_LIB_ENTRY(_linux_dev_reset),	\
+	.eh_bus_reset_handler	= AIC_LIB_ENTRY(_linux_bus_reset),	\
+	.can_queue		= AIC_CONST_ENTRY(_MAX_QUEUE),		\
+	.this_id		= -1,					\
+	.cmd_per_lun		= 2,					\
+	.use_clustering		= ENABLE_CLUSTERING,			\
+	AIC_TEMPLATE_MAX_SECTORS(MAX_SECTORS)				\
+	AIC_TEMPLATE_DMA_SETTINGS()					\
+	AIC_TEMPLATE_BIOSPARAM()					\
+	AIC_TEMPLATE_VERSIONED_ENTRIES()				\
+}
+
+/************************** OS Utility Wrappers *******************************/
+#define printf printk
+#define M_NOWAIT GFP_ATOMIC
+#define M_WAITOK 0
+#define malloc(size, type, flags) kmalloc(size, flags)
+#define free(ptr, type) kfree(ptr)
+
+static __inline void aic_delay(long);
+static __inline void
+aic_delay(long usec)
+{
+	/*
+	 * udelay on Linux can have problems for
+	 * multi-millisecond waits.  Wait at most
+	 * 1024us per call.
+	 */
+	while (usec > 0) {
+		udelay(usec % 1024);
+		usec -= 1024;
+	}
+}
+
+/********************************** Misc Macros *******************************/
+#define	roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
+#define	powerof2(x)	((((x)-1)&(x))==0)
+
+/******************************* Byte Order ***********************************/
+#define aic_htobe16(x)	cpu_to_be16(x)
+#define aic_htobe32(x)	cpu_to_be32(x)
+#define aic_htobe64(x)	cpu_to_be64(x)
+#define aic_htole16(x)	cpu_to_le16(x)
+#define aic_htole32(x)	cpu_to_le32(x)
+#define aic_htole64(x)	cpu_to_le64(x)
+
+#define aic_be16toh(x)	be16_to_cpu(x)
+#define aic_be32toh(x)	be32_to_cpu(x)
+#define aic_be64toh(x)	be64_to_cpu(x)
+#define aic_le16toh(x)	le16_to_cpu(x)
+#define aic_le32toh(x)	le32_to_cpu(x)
+#define aic_le64toh(x)	le64_to_cpu(x)
+
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN 1234
+#endif
+
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN 4321
+#endif
+
+#ifndef BYTE_ORDER
+#if defined(__BIG_ENDIAN)
+#define BYTE_ORDER BIG_ENDIAN
+#endif
+#if defined(__LITTLE_ENDIAN)
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+#endif /* BYTE_ORDER */
+
+/********************************* Core Includes ******************************/
+#include AIC_CORE_INCLUDE
+
+/**************************** Front End Queues ********************************/
+/*
+ * Data structure used to cast the Linux struct scsi_cmnd to something
+ * that allows us to use the queue macros.  The linux structure has
+ * plenty of space to hold the links fields as required by the queue
+ * macros, but the queue macors require them to have the correct type.
+ */
+struct aic_cmd_internal {
+	/* Area owned by the Linux scsi layer. */
+	uint8_t	private[offsetof(struct scsi_cmnd, SCp.Status)];
+	union {
+		STAILQ_ENTRY(aic_cmd)	ste;
+		LIST_ENTRY(aic_cmd)	le;
+		TAILQ_ENTRY(aic_cmd)	tqe;
+	} links;
+	uint32_t			end;
+};
+
+struct aic_cmd {
+	union {
+		struct aic_cmd_internal	icmd;
+		struct scsi_cmnd	scsi_cmd;
+	} un;
+};
+
+#define acmd_icmd(cmd) ((cmd)->un.icmd)
+#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd)
+#define acmd_links un.icmd.links
+
+/*************************** Device Data Structures ***************************/
+/*
+ * A per probed device structure used to deal with some error recovery
+ * scenarios that the Linux mid-layer code just doesn't know how to
+ * handle.  The structure allocated for a device only becomes persistent
+ * after a successfully completed inquiry command to the target when
+ * that inquiry data indicates a lun is present.
+ */
+TAILQ_HEAD(aic_busyq, aic_cmd);
+typedef enum {
+	AIC_DEV_UNCONFIGURED	 = 0x01,
+	AIC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
+	AIC_DEV_TIMER_ACTIVE	 = 0x04, /* Our timer is active */
+	AIC_DEV_ON_RUN_LIST	 = 0x08, /* Queued to be run later */
+	AIC_DEV_Q_BASIC		 = 0x10, /* Allow basic device queuing */
+	AIC_DEV_Q_TAGGED	 = 0x20, /* Allow full SCSI2 command queueing */
+	AIC_DEV_PERIODIC_OTAG	 = 0x40, /* Send OTAG to prevent starvation */
+	AIC_DEV_SLAVE_CONFIGURED = 0x80	 /* slave_configure() has been called */
+} aic_linux_dev_flags;
+
+struct aic_linux_target;
+struct aic_linux_device {
+	TAILQ_ENTRY(aic_linux_device) links;
+	struct			aic_busyq busyq;
+
+	/*
+	 * The number of transactions currently
+	 * queued to the device.
+	 */
+	int			active;
+
+	/*
+	 * The currently allowed number of 
+	 * transactions that can be queued to
+	 * the device.  Must be signed for
+	 * conversion from tagged to untagged
+	 * mode where the device may have more
+	 * than one outstanding active transaction.
+	 */
+	int			openings;
+
+	/*
+	 * A positive count indicates that this
+	 * device's queue is halted.
+	 */
+	u_int			qfrozen;
+	
+	/*
+	 * Cumulative command counter.
+	 */
+	u_long			commands_issued;
+
+	/*
+	 * The number of tagged transactions when
+	 * running at our current opening level
+	 * that have been successfully received by
+	 * this device since the last QUEUE FULL.
+	 */
+	u_int			tag_success_count;
+#define AIC_TAG_SUCCESS_INTERVAL 50
+
+	aic_linux_dev_flags	flags;
+
+	/*
+	 * Per device timer.
+	 */
+	struct timer_list	timer;
+
+	/*
+	 * The high limit for the tags variable.
+	 */
+	u_int			maxtags;
+
+	/*
+	 * The computed number of tags outstanding
+	 * at the time of the last QUEUE FULL event.
+	 */
+	u_int			tags_on_last_queuefull;
+
+	/*
+	 * How many times we have seen a queue full
+	 * with the same number of tags.  This is used
+	 * to stop our adaptive queue depth algorithm
+	 * on devices with a fixed number of tags.
+	 */
+	u_int			last_queuefull_same_count;
+#define AIC_LOCK_TAGS_COUNT 50
+
+	/*
+	 * How many transactions have been queued
+	 * without the device going idle.  We use
+	 * this statistic to determine when to issue
+	 * an ordered tag to prevent transaction
+	 * starvation.  This statistic is only updated
+	 * if the AIC_DEV_PERIODIC_OTAG flag is set
+	 * on this device.
+	 */
+	u_int			commands_since_idle_or_otag;
+#define AIC_OTAG_THRESH	500
+
+	int			lun;
+	Scsi_Device	       *scsi_device;
+	struct			aic_linux_target *target;
+};
+
+typedef enum {
+	AIC_DV_REQUIRED		 = 0x01,
+	AIC_INQ_VALID		 = 0x02,
+	AIC_BASIC_DV		 = 0x04,
+	AIC_ENHANCED_DV		 = 0x08
+} aic_linux_targ_flags;
+
+/* DV States */
+typedef enum {
+	AIC_DV_STATE_EXIT = 0,
+	AIC_DV_STATE_INQ_SHORT_ASYNC,
+	AIC_DV_STATE_INQ_ASYNC,
+	AIC_DV_STATE_INQ_ASYNC_VERIFY,
+	AIC_DV_STATE_TUR,
+	AIC_DV_STATE_REBD,
+	AIC_DV_STATE_INQ_VERIFY,
+	AIC_DV_STATE_WEB,
+	AIC_DV_STATE_REB,
+	AIC_DV_STATE_SU,
+	AIC_DV_STATE_BUSY
+} aic_dv_state;
+
+struct aic_linux_target {
+	struct aic_linux_device	 *devices[AIC_NUM_LUNS];
+	int			  channel;
+	int			  target;
+	int			  refcount;
+	struct aic_transinfo	  last_tinfo;
+	struct aic_softc	 *softc;
+	aic_linux_targ_flags	  flags;
+	struct scsi_inquiry_data *inq_data;
+	/*
+	 * The next "fallback" period to use for narrow/wide transfers.
+	 */
+	uint8_t			  dv_next_narrow_period;
+	uint8_t			  dv_next_wide_period;
+	uint8_t			  dv_max_width;
+	uint8_t			  dv_max_ppr_options;
+	uint8_t			  dv_last_ppr_options;
+	u_int			  dv_echo_size;
+	aic_dv_state		  dv_state;
+	u_int			  dv_state_retry;
+	uint8_t			 *dv_buffer;
+	uint8_t			 *dv_buffer1;
+
+	/*
+	 * Cumulative counter of errors.
+	 */
+	u_long			errors_detected;
+	u_long			cmds_since_error;
+};
+
+/*************** OSM Dependent Components of Core Datastructures **************/
+/*
+ * Per-SCB OSM storage.
+ */
+typedef enum {
+	AIC_SCB_UP_EH_SEM	= 0x1,
+	AIC_TIMEOUT_ACTIVE	= 0x2,
+	AIC_RELEASE_SIMQ	= 0x4
+} aic_linux_scb_flags;
+
+struct scb_platform_data {
+	struct aic_linux_device	*dev;
+	bus_addr_t		 buf_busaddr;
+	uint32_t		 xfer_len;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+	uint32_t		 resid;		/* Transfer residual */
+#endif
+	uint32_t		 sense_resid;	/* Auto-Sense residual */
+	aic_linux_scb_flags	 flags;
+};
+
+/*
+ * Define a structure used for each host adapter.  All members are
+ * aligned on a boundary >= the size of the member to honor the
+ * alignment restrictions of the various platforms supported by
+ * this driver.
+ */
+typedef enum {
+	AIC_DV_WAIT_SIMQ_EMPTY	 = 0x01,
+	AIC_DV_WAIT_SIMQ_RELEASE = 0x02,
+	AIC_DV_ACTIVE		 = 0x04,
+	AIC_DV_SHUTDOWN		 = 0x08,
+	AIC_RUN_CMPLT_Q_TIMER	 = 0x10,
+	AIC_BUS_SETTLE_TIMER	 = 0x20
+} aic_linux_softc_flags;
+
+TAILQ_HEAD(aic_completeq, aic_cmd);
+
+struct aic_platform_data {
+	/*
+	 * Fields accessed from interrupt context.
+	 */
+	struct aic_linux_target *targets[AIC_NUM_TARGETS]; 
+	TAILQ_HEAD(, aic_linux_device) device_runq;
+	struct aic_completeq	 completeq;
+
+	spinlock_t		 spin_lock;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	struct tasklet_struct	 runq_tasklet;
+	struct tasklet_struct	 unblock_tasklet;
+#endif
+	u_int			 qfrozen;
+	pid_t			 dv_pid;
+	pid_t			 recovery_pid;
+	struct timer_list	 completeq_timer;
+	struct timer_list	 bus_settle_timer;
+	struct timer_list	 stats_timer;
+	struct semaphore	 eh_sem;
+	struct semaphore	 dv_sem;
+	struct semaphore	 dv_cmd_sem;
+	struct semaphore	 recovery_sem;
+	struct semaphore	 recovery_ending_sem;
+	struct scsi_device	*dv_scsi_dev;
+	struct Scsi_Host        *host;		/* pointer to scsi host */
+#define AIC_LINUX_NOIRQ	((uint32_t)~0)
+	uint32_t		 irq;		/* IRQ for this adapter */
+	uint32_t		 bios_address;
+	uint32_t		 mem_busaddr;	/* Mem Base Addr */
+	bus_addr_t		 hw_dma_mask;
+	aic_linux_softc_flags	 flags;
+};
+
+/***************************** Timer Facilities *******************************/
+typedef void aic_linux_callback_t (u_long);  
+void aic_platform_timeout(struct scsi_cmnd *);
+void aic_linux_midlayer_timeout(struct scsi_cmnd *);
+
+#define aic_timer_init init_timer
+#define aic_timer_stop del_timer_sync
+static __inline void aic_timer_reset(aic_timer_t *timer, uint32_t usec,
+				     aic_callback_t *func, void *arg);
+static __inline uint32_t aic_get_timeout(struct scb *);
+static __inline void aic_scb_timer_start(struct scb *scb);
+static __inline void aic_scb_timer_reset(struct scb *scb, uint32_t usec);
 
+static __inline void
+aic_timer_reset(aic_timer_t *timer, uint32_t usec,
+		aic_callback_t *func, void *arg)
+{
+	struct aic_softc *aic;
+
+	aic = (struct aic_softc *)arg;
+	del_timer(timer);
+	timer->data = (u_long)arg;
+	timer->expires = jiffies + (usec / AIC_USECS_PER_JIFFY);
+	timer->function = (aic_linux_callback_t*)func;
+	add_timer(timer);
+}
+
+static __inline uint32_t
+aic_get_timeout(struct scb *scb)
+{
+
+	/*
+	 * Convert from jiffies to usec.
+	 */
+	return (scb->io_ctx->timeout_per_command * AIC_USECS_PER_JIFFY);
+}
+
+static __inline void
+aic_scb_timer_start(struct scb *scb)
+{
+	scb->platform_data->flags |= AIC_TIMEOUT_ACTIVE;
+	scsi_add_timer(scb->io_ctx, scb->io_ctx->timeout_per_command,
+		       aic_platform_timeout);
+}
+
+static __inline void
+aic_scb_timer_reset(struct scb *scb, uint32_t usec)
+{
+	/*
+	 * Restore timer data that is clobbered by scsi_delete_timer().
+	 */
+	scb->io_ctx->eh_timeout.data = (unsigned long)scb->io_ctx;
+	scb->io_ctx->eh_timeout.function =
+	    (void (*)(unsigned long))aic_platform_timeout;
+	scb->platform_data->flags |= AIC_TIMEOUT_ACTIVE;
+	mod_timer(&scb->io_ctx->eh_timeout,
+		  jiffies + (usec / AIC_USECS_PER_JIFFY));
+}
+
+/************************* SCSI command formats *******************************/
 /*
  * Define dome bits that are in ALL (or a lot of) scsi commands
  */
@@ -865,6 +1624,368 @@ typedef enum {
 
 extern const char *scsi_sense_key_text[];
 
+/*************************** Domain Validation ********************************/
+#define AIC_DV_CMD(cmd) ((cmd)->scsi_done == aic_linux_dv_complete)
+#define AIC_DV_SIMQ_FROZEN(aic)					\
+	((((aic)->platform_data->flags & AIC_DV_ACTIVE) != 0)	\
+	 && (aic)->platform_data->qfrozen == 1)
+
+/*********************** Transaction Access Wrappers **************************/
+static __inline void aic_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t);
+static __inline void aic_set_transaction_status(struct scb *, uint32_t);
+static __inline void aic_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t);
+static __inline void aic_set_scsi_status(struct scb *, uint32_t);
+static __inline uint32_t aic_cmd_get_transaction_status(Scsi_Cmnd *cmd);
+static __inline uint32_t aic_get_transaction_status(struct scb *);
+static __inline uint32_t aic_cmd_get_scsi_status(Scsi_Cmnd *cmd);
+static __inline uint32_t aic_get_scsi_status(struct scb *);
+static __inline void aic_set_transaction_tag(struct scb *, int, u_int);
+static __inline u_long aic_get_transfer_length(struct scb *);
+static __inline int aic_get_transfer_dir(struct scb *);
+static __inline void aic_set_residual(struct scb *, u_long);
+static __inline void aic_set_sense_residual(struct scb *scb, u_long resid);
+static __inline u_long aic_get_residual(struct scb *);
+static __inline u_long aic_get_sense_residual(struct scb *);
+static __inline int aic_perform_autosense(struct scb *);
+static __inline uint32_t aic_get_sense_bufsize(struct aic_softc *,
+					       struct scb *);
+static __inline void aic_notify_xfer_settings_change(struct aic_softc *,
+						     struct aic_devinfo *);
+static __inline void aic_platform_scb_free(struct aic_softc *aic,
+					   struct scb *scb);
+static __inline void aic_freeze_scb(struct scb *scb);
+
+static __inline
+void aic_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status)
+{
+	cmd->result &= ~(CAM_STATUS_MASK << 16);
+	cmd->result |= status << 16;
+}
+
+static __inline
+void aic_set_transaction_status(struct scb *scb, uint32_t status)
+{
+	aic_cmd_set_transaction_status(scb->io_ctx,status);
+}
+
+static __inline
+void aic_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status)
+{
+	cmd->result &= ~0xFFFF;
+	cmd->result |= status;
+}
+
+static __inline
+void aic_set_scsi_status(struct scb *scb, uint32_t status)
+{
+	aic_cmd_set_scsi_status(scb->io_ctx, status);
+}
+
+static __inline
+uint32_t aic_cmd_get_transaction_status(Scsi_Cmnd *cmd)
+{
+	return ((cmd->result >> 16) & CAM_STATUS_MASK);
+}
+
+static __inline
+uint32_t aic_get_transaction_status(struct scb *scb)
+{
+	return (aic_cmd_get_transaction_status(scb->io_ctx));
+}
+
+static __inline
+uint32_t aic_cmd_get_scsi_status(Scsi_Cmnd *cmd)
+{
+	return (cmd->result & 0xFFFF);
+}
+
+static __inline
+uint32_t aic_get_scsi_status(struct scb *scb)
+{
+	return (aic_cmd_get_scsi_status(scb->io_ctx));
+}
+
+static __inline
+void aic_set_transaction_tag(struct scb *scb, int enabled, u_int type)
+{
+	/*
+	 * Nothing to do for linux as the incoming transaction
+	 * has no concept of tag/non tagged, etc.
+	 */
+}
+
+static __inline
+u_long aic_get_transfer_length(struct scb *scb)
+{
+	return (scb->platform_data->xfer_len);
+}
+
+static __inline
+int aic_get_transfer_dir(struct scb *scb)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40)
+	return (scb->io_ctx->sc_data_direction);
+#else
+	if (scb->io_ctx->bufflen == 0)
+		return (CAM_DIR_NONE);
+
+	switch(scb->io_ctx->cmnd[0]) {
+	case 0x08:  /* READ(6)  */
+	case 0x28:  /* READ(10) */
+	case 0xA8:  /* READ(12) */
+		return (CAM_DIR_IN);
+        case 0x0A:  /* WRITE(6)  */
+        case 0x2A:  /* WRITE(10) */
+        case 0xAA:  /* WRITE(12) */
+		return (CAM_DIR_OUT);
+        default:
+		return (CAM_DIR_NONE);
+        }
+#endif
+}
+
+static __inline
+void aic_set_residual(struct scb *scb, u_long resid)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+	scb->io_ctx->resid = resid;
+#else
+	scb->platform_data->resid = resid;
+#endif
+}
+
+static __inline
+void aic_set_sense_residual(struct scb *scb, u_long resid)
+{
+	scb->platform_data->sense_resid = resid;
+}
+
+static __inline
+u_long aic_get_residual(struct scb *scb)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+	return (scb->io_ctx->resid);
+#else
+	return (scb->platform_data->resid);
+#endif
+}
+
+static __inline
+u_long aic_get_sense_residual(struct scb *scb)
+{
+	return (scb->platform_data->sense_resid);
+}
+
+static __inline
+int aic_perform_autosense(struct scb *scb)
+{
+	/*
+	 * We always perform autosense in Linux.
+	 * On other platforms this is set on a
+	 * per-transaction basis.
+	 */
+	return (1);
+}
+
+static __inline uint32_t
+aic_get_sense_bufsize(struct aic_softc *aic, struct scb *scb)
+{
+	return (sizeof(struct scsi_sense_data));
+}
+
+static __inline void
+aic_notify_xfer_settings_change(struct aic_softc *aic,
+				struct aic_devinfo *devinfo)
+{
+	/* Nothing to do here for linux */
+}
+
+static __inline void
+aic_platform_scb_free(struct aic_softc *aic, struct scb *scb)
+{
+	aic->flags &= ~AIC_RESOURCE_SHORTAGE;
+}
+
+static __inline void
+aic_freeze_scb(struct scb *scb)
+{
+	if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) {
+                scb->io_ctx->result |= CAM_DEV_QFRZN << 16;
+                scb->platform_data->dev->qfrozen++;
+        }
+}
+
+/******************************* PCI Definitions ******************************/
+/*
+ * PCIM_xxx: mask to locate subfield in register
+ * PCIR_xxx: config register offset
+ * PCIC_xxx: device class
+ * PCIS_xxx: device subclass
+ * PCIP_xxx: device programming interface
+ * PCIV_xxx: PCI vendor ID (only required to fixup ancient devices)
+ * PCID_xxx: device ID
+ */
+#define PCIR_DEVVENDOR		0x00
+#define PCIR_VENDOR		0x00
+#define PCIR_DEVICE		0x02
+#define PCIR_COMMAND		0x04
+#define PCIM_CMD_PORTEN		0x0001
+#define PCIM_CMD_MEMEN		0x0002
+#define PCIM_CMD_BUSMASTEREN	0x0004
+#define PCIM_CMD_MWRICEN	0x0010
+#define PCIM_CMD_PERRESPEN	0x0040
+#define	PCIM_CMD_SERRESPEN	0x0100
+#define PCIR_STATUS		0x06
+#define PCIR_REVID		0x08
+#define PCIR_PROGIF		0x09
+#define PCIR_SUBCLASS		0x0a
+#define PCIR_CLASS		0x0b
+#define PCIR_CACHELNSZ		0x0c
+#define PCIR_LATTIMER		0x0d
+#define PCIR_HEADERTYPE		0x0e
+#define PCIM_MFDEV		0x80
+#define PCIR_BIST		0x0f
+#define PCIR_CAP_PTR		0x34
+
+/* config registers for header type 0 devices */
+#define PCIR_MAPS	0x10
+#define PCIR_BARS	PCIR_MAPS
+#define PCIR_BAR(x)	(PCIR_BARS + (x) * 4)
+#define PCIR_SUBVEND_0	0x2c
+#define PCIR_SUBDEV_0	0x2e
+
+typedef enum
+{
+	AIC_POWER_STATE_D0,
+	AIC_POWER_STATE_D1,
+	AIC_POWER_STATE_D2,
+	AIC_POWER_STATE_D3
+} aic_power_state;
+
+/****************************** PCI-X definitions *****************************/
+#define PCIXR_COMMAND	0x96
+#define PCIXR_DEVADDR	0x98
+#define PCIXM_DEVADDR_FNUM	0x0003	/* Function Number */
+#define PCIXM_DEVADDR_DNUM	0x00F8	/* Device Number */
+#define PCIXM_DEVADDR_BNUM	0xFF00	/* Bus Number */
+#define PCIXR_STATUS	0x9A
+#define PCIXM_STATUS_64BIT	0x0001	/* Active 64bit connection to device. */
+#define PCIXM_STATUS_133CAP	0x0002	/* Device is 133MHz capable */
+#define PCIXM_STATUS_SCDISC	0x0004	/* Split Completion Discarded */
+#define PCIXM_STATUS_UNEXPSC	0x0008	/* Unexpected Split Completion */
+#define PCIXM_STATUS_CMPLEXDEV	0x0010	/* Device Complexity (set == bridge) */
+#define PCIXM_STATUS_MAXMRDBC	0x0060	/* Maximum Burst Read Count */
+#define PCIXM_STATUS_MAXSPLITS	0x0380	/* Maximum Split Transactions */
+#define PCIXM_STATUS_MAXCRDS	0x1C00	/* Maximum Cumulative Read Size */
+#define PCIXM_STATUS_RCVDSCEM	0x2000	/* Received a Split Comp w/Error msg */
+
+/**************************** KObject Wrappers ********************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define	aic_dev_to_pci_dev(dev)		to_pci_dev(dev)
+#define	aic_dev_to_eisa_dev(dev)	to_eisa_dev(dev)
+#define	aic_pci_dev_to_dev(pci)		(&pci->dev)
+#define	aic_eisa_dev_to_dev(eisa)	(&eisa->dev)
+#else
+#define	aic_dev_to_pci_dev(dev)		(dev)
+#define	aic_dev_to_eisa_dev(dev)	(NULL)
+#define	aic_pci_dev_to_dev(pci)		(pci)
+#define	aic_eisa_dev_to_dev(eisa)	(NULL)
+#endif
+
+#define	aic_pci_dev(aic)		aic_dev_to_pci_dev((aic)->dev_softc)
+#define	aic_eisa_dev(aic)		aic_dev_to_eisa_dev((aic)->dev_softc)
+/***************************** PCI Routines ***********************************/
+static __inline uint32_t aic_pci_read_config(aic_dev_softc_t dev,
+					     int reg, int width);
+static __inline void aic_pci_write_config(aic_dev_softc_t dev,
+					  int reg, uint32_t value,
+					  int width);
+static __inline int aic_get_pci_function(aic_dev_softc_t);
+static __inline int aic_get_pci_slot(aic_dev_softc_t);
+static __inline int aic_get_pci_bus(aic_dev_softc_t);
+
+static __inline uint32_t
+aic_pci_read_config(aic_dev_softc_t dev, int reg, int width)
+{
+	struct pci_dev *pci;
+
+	pci = aic_dev_to_pci_dev(dev);
+	switch (width) {
+	case 1:
+	{
+		uint8_t retval;
+
+		pci_read_config_byte(pci, reg, &retval);
+		return (retval);
+	}
+	case 2:
+	{
+		uint16_t retval;
+		pci_read_config_word(pci, reg, &retval);
+		return (retval);
+	}
+	case 4:
+	{
+		uint32_t retval;
+		pci_read_config_dword(pci, reg, &retval);
+		return (retval);
+	}
+	default:
+		panic("aic_pci_read_config: Read size too big");
+		/* NOTREACHED */
+		return (0);
+	}
+}
+
+static __inline void
+aic_pci_write_config(aic_dev_softc_t dev, int reg, uint32_t value, int width)
+{
+	struct pci_dev *pci;
+
+	pci = aic_dev_to_pci_dev(dev);
+	switch (width) {
+	case 1:
+		pci_write_config_byte(pci, reg, value);
+		break;
+	case 2:
+		pci_write_config_word(pci, reg, value);
+		break;
+	case 4:
+		pci_write_config_dword(pci, reg, value);
+		break;
+	default:
+		panic("aic_pci_write_config: Write size too big");
+		/* NOTREACHED */
+	}
+}
+
+static __inline int
+aic_get_pci_function(aic_dev_softc_t dev)
+{
+	struct pci_dev *pci;
+
+	pci = aic_dev_to_pci_dev(dev);
+	return (PCI_FUNC(pci->devfn));
+}
+
+static __inline int
+aic_get_pci_slot(aic_dev_softc_t dev)
+{
+	struct pci_dev *pci;
+
+	pci = aic_dev_to_pci_dev(dev);
+	return (PCI_SLOT(pci->devfn));
+}
+
+static __inline int
+aic_get_pci_bus(aic_dev_softc_t dev)
+{
+	struct pci_dev *pci;
+
+	pci = aic_dev_to_pci_dev(dev);
+	return (pci->bus->number);
+}
+
 /************************* Large Disk Handling ********************************/
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 static __inline int aic_sector_div(u_long capacity, int heads, int sectors);
@@ -886,34 +2007,31 @@ aic_sector_div(sector_t capacity, int he
 }
 #endif
 
-/**************************** Module Library Hack *****************************/
-/*
- * What we'd like to do is have a single "scsi library" module that both the
- * aic7xxx and aic79xx drivers could load and depend on.  A cursory examination
- * of implementing module dependencies in Linux (handling the install and
- * initrd cases) does not look promissing.  For now, we just duplicate this
- * code in both drivers using a simple symbol renaming scheme that hides this
- * hack from the drivers.
- */
-#define AIC_LIB_ENTRY_CONCAT(x, prefix)	prefix ## x
-#define	AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix)
-#define AIC_LIB_ENTRY(x)		AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX)
+/************************* Magic SysReq Support *******************************/
+#include <linux/sysrq.h>
 
-#define	aic_sense_desc			AIC_LIB_ENTRY(_sense_desc)
-#define	aic_sense_error_action		AIC_LIB_ENTRY(_sense_error_action)
-#define	aic_error_action		AIC_LIB_ENTRY(_error_action)
-#define	aic_op_desc			AIC_LIB_ENTRY(_op_desc)
-#define	aic_cdb_string			AIC_LIB_ENTRY(_cdb_string)
-#define aic_print_inquiry		AIC_LIB_ENTRY(_print_inquiry)
-#define aic_calc_syncsrate		AIC_LIB_ENTRY(_calc_syncrate)
-#define	aic_calc_syncparam		AIC_LIB_ENTRY(_calc_syncparam)
-#define	aic_calc_speed			AIC_LIB_ENTRY(_calc_speed)
-#define	aic_inquiry_match		AIC_LIB_ENTRY(_inquiry_match)
-#define	aic_static_inquiry_match	AIC_LIB_ENTRY(_static_inquiry_match)
-#define	aic_parse_brace_option		AIC_LIB_ENTRY(_parse_brace_option)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+typedef void aic_sysrq_handler_t (int, struct pt_regs *, struct kbd_struct *,
+				  struct tty_struct *);
+#else
+typedef void aic_sysrq_handler_t (int, struct pt_regs *, struct tty_struct *);
+#endif
 
-/******************************************************************************/
+#ifdef CONFIG_MAGIC_SYSRQ
+#define	aic_sysrq_key_op sysrq_key_op
+#else
+struct aic_sysrq_key_op {
+	aic_sysrq_handler_t *handler;
+	char *help_msg;
+	char *action_msg;
+};
+#endif
 
+aic_sysrq_handler_t	aic_sysrq_handler;
+int			aic_install_sysrq(struct aic_sysrq_key_op *);
+void			aic_remove_sysrq(int key,
+					 struct aic_sysrq_key_op *key_op);
+/************************ SCSI Library Functions *****************************/
 void			aic_sense_desc(int /*sense_key*/, int /*asc*/,
 				       int /*ascq*/, struct scsi_inquiry_data*,
 				       const char** /*sense_key_desc*/,
@@ -1043,4 +2161,115 @@ scsi_4btoul(uint8_t *bytes)
 	return (rv);
 }
 
+/******************************* PCI Funcitons ********************************/
+void aic_power_state_change(struct aic_softc *aic, aic_power_state new_state);
+
+/******************************* Queue Handling *******************************/
+void		     aic_runq_tasklet(unsigned long data);
+void		     aic_unblock_tasklet(unsigned long data);
+void		     aic_linux_run_device_queue(struct aic_softc*,
+						struct aic_linux_device*);
+void		     aic_bus_settle_complete(u_long data);
+void		     aic_freeze_simq(struct aic_softc *aic);
+void		     aic_release_simq(struct aic_softc *aic);
+void		     aic_release_simq_locked(struct aic_softc *aic);
+static __inline void aic_schedule_runq(struct aic_softc *aic);
+static __inline void aic_schedule_unblock(struct aic_softc *aic);
+static __inline struct aic_linux_device *
+		     aic_linux_next_device_to_run(struct aic_softc *aic);
+static __inline void aic_linux_check_device_queue(struct aic_softc *aic,
+						  struct aic_linux_device *dev);
+static __inline void aic_linux_run_device_queues(struct aic_softc *aic);
+
+/*
+ * Must be called with our lock held.
+ */
+static __inline void
+aic_schedule_runq(struct aic_softc *aic)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	tasklet_schedule(&aic->platform_data->runq_tasklet);
+#else
+	/*
+	 * Tasklets are not available, so run inline.
+	 */
+	aic_runq_tasklet((unsigned long)aic);
+#endif
+}
+
+static __inline void
+aic_schedule_unblock(struct aic_softc *aic)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	tasklet_schedule(&aic->platform_data->unblock_tasklet);
+#else
+#error "Fix 2.2.X Kernel Support"
+#endif
+}
+
+static __inline struct aic_linux_device *
+aic_linux_next_device_to_run(struct aic_softc *aic)
+{
+	
+	if ((aic->flags & AIC_RESOURCE_SHORTAGE) != 0
+	 || (aic->platform_data->qfrozen != 0
+	  && AIC_DV_SIMQ_FROZEN(aic) == 0))
+		return (NULL);
+	return (TAILQ_FIRST(&aic->platform_data->device_runq));
+}
+
+static __inline void
+aic_linux_check_device_queue(struct aic_softc *aic,
+			     struct aic_linux_device *dev)
+{
+	if ((dev->flags & AIC_DEV_FREEZE_TIL_EMPTY) != 0
+	 && dev->active == 0) {
+		dev->flags &= ~AIC_DEV_FREEZE_TIL_EMPTY;
+		dev->qfrozen--;
+	}
+
+	if (TAILQ_FIRST(&dev->busyq) == NULL
+	 || dev->openings == 0 || dev->qfrozen != 0)
+		return;
+
+	aic_linux_run_device_queue(aic, dev);
+}
+
+static __inline void
+aic_linux_run_device_queues(struct aic_softc *aic)
+{
+	struct aic_linux_device *dev;
+
+	while ((dev = aic_linux_next_device_to_run(aic)) != NULL) {
+		TAILQ_REMOVE(&aic->platform_data->device_runq, dev, links);
+		dev->flags &= ~AIC_DEV_ON_RUN_LIST;
+		aic_linux_check_device_queue(aic, dev);
+	}
+}
+
+/****************************** Tasklet Support *******************************/
+static __inline void	aic_setup_tasklets(struct aic_softc *aic);
+static __inline void	aic_teardown_tasklets(struct aic_softc *aic);
+
+static __inline void
+aic_setup_tasklets(struct aic_softc *aic)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	tasklet_init(&aic->platform_data->runq_tasklet, aic_runq_tasklet,
+		     (unsigned long)aic);
+	tasklet_init(&aic->platform_data->unblock_tasklet, aic_unblock_tasklet,
+		     (unsigned long)aic);
+#endif
+}
+
+static __inline void
+aic_teardown_tasklets(struct aic_softc *aic)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	tasklet_kill(&aic->platform_data->runq_tasklet);
+	tasklet_kill(&aic->platform_data->unblock_tasklet);
+#endif
+}
+
+
 #endif /*_AICLIB_H */
diff -puN /dev/null drivers/scsi/aic7xxx/aiclib_pci.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/drivers/scsi/aic7xxx/aiclib_pci.c	Wed Dec 24 12:15:38 2003
@@ -0,0 +1,79 @@
+/*
+ * Implementation of Utility functions for PCI controller types.
+ *
+ * Copyright (c) 2000-2003 Adaptec Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm_pci.c#25 $
+ */
+
+void
+aic_power_state_change(struct aic_softc *aic, aic_power_state new_state)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	pci_set_power_state(aic_dev_to_pci_dev(aic->dev_softc), new_state);
+#else
+	uint32_t cap;
+	u_int cap_offset;
+
+	/*
+	 * Traverse the capability list looking for
+	 * the power management capability.
+	 */
+	cap = 0;
+	cap_offset = aic_pci_read_config(aic->dev_softc,
+					 PCIR_CAP_PTR, /*bytes*/1);
+	while (cap_offset != 0) {
+
+		cap = aic_pci_read_config(aic->dev_softc,
+					  cap_offset, /*bytes*/4);
+		if ((cap & 0xFF) == 1
+		 && ((cap >> 16) & 0x3) > 0) {
+			uint32_t pm_control;
+
+			pm_control = aic_pci_read_config(aic->dev_softc,
+							 cap_offset + 4,
+							 /*bytes*/4);
+			pm_control &= ~0x3;
+			pm_control |= new_state;
+			aic_pci_write_config(aic->dev_softc,
+					     cap_offset + 4,
+					     pm_control, /*bytes*/2);
+			break;
+		}
+		cap_offset = (cap >> 8) & 0xFF;
+	}
+#endif 
+}
diff -puN drivers/scsi/aic7xxx/Kconfig.aic7xxx~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/Kconfig.aic7xxx
--- 25/drivers/scsi/aic7xxx/Kconfig.aic7xxx~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/Kconfig.aic7xxx	Wed Dec 24 12:15:38 2003
@@ -1,18 +1,16 @@
 #
 # AIC7XXX and AIC79XX 2.5.X Kernel configuration File.
-# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Kconfig.aic7xxx#6 $
+# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Kconfig.aic7xxx#8 $
 #
 config SCSI_AIC7XXX
 	tristate "Adaptec AIC7xxx Fast -> U160 support (New Driver)"
+	depends on PCI || EISA
 	---help---
 	This driver supports all of Adaptec's Fast through Ultra 160 PCI
 	based SCSI controllers as well as the aic7770 based EISA and VLB
 	SCSI controllers (the 274x and 284x series).  For AAA and ARO based
 	configurations, only SCSI functionality is provided.
 
-	To compile this driver as a module, choose M here: the
-	module will be called aic7xxx.
-
 config AIC7XXX_CMDS_PER_DEVICE
 	int "Maximum number of TCQ commands per device"
 	depends on SCSI_AIC7XXX
@@ -50,7 +48,7 @@ config AIC7XXX_RESET_DELAY_MS
 
 config AIC7XXX_PROBE_EISA_VL
 	bool "Probe for EISA and VL AIC7XXX Adapters"
-	depends on SCSI_AIC7XXX
+	depends on SCSI_AIC7XXX && EISA
 	help
 	Probe for EISA and VLB Aic7xxx controllers.  In many newer systems,
 	the invasive probes necessary to detect these controllers can cause
diff -puN drivers/scsi/aic7xxx/Makefile~aic7xxx-aic79xx-update drivers/scsi/aic7xxx/Makefile
--- 25/drivers/scsi/aic7xxx/Makefile~aic7xxx-aic79xx-update	Wed Dec 24 12:15:38 2003
+++ 25-akpm/drivers/scsi/aic7xxx/Makefile	Wed Dec 24 12:15:38 2003
@@ -1,7 +1,7 @@
 #
 # Makefile for the Linux aic7xxx SCSI driver.
 #
-# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Makefile#6 $
+# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Makefile#8 $
 #
 
 # Let kbuild descend into aicasm when cleaning
@@ -12,15 +12,15 @@ obj-$(CONFIG_SCSI_AIC79XX)	+= aic79xx.o
 
 # Core Fast -> U160 files
 aic7xxx-y					+= aic7xxx_core.o	\
-						   aic7xxx_93cx6.o	\
-						   aic7770.o
+						   aic7xxx_93cx6.o
+aic7xxx-$(CONFIG_EISA)				+= aic7770.o
 aic7xxx-$(CONFIG_PCI)				+= aic7xxx_pci.o
 aic7xxx-$(CONFIG_AIC7XXX_REG_PRETTY_PRINT)	+= aic7xxx_reg_print.o
 
 # Platform Specific Fast -> U160 Files
 aic7xxx-y					+= aic7xxx_osm.o	\
-						   aic7xxx_proc.o	\
-						   aic7770_osm.o
+						   aic7xxx_proc.o
+aic7xxx-$(CONFIG_EISA)				+= aic7770_osm.o
 aic7xxx-$(CONFIG_PCI)				+= aic7xxx_osm_pci.o
 
 # Core U320 files
@@ -58,6 +58,13 @@ aicasm-7xxx-opts-$(CONFIG_AIC7XXX_REG_PR
 	-p $(obj)/aic7xxx_reg_print.c -i aic7xxx_osm.h
 
 ifeq ($(CONFIG_AIC7XXX_BUILD_FIRMWARE),y)
+# Create a dependency chain in generated files
+# to avoid concurrent invocations of the single
+# rule that builds them all.
+aic7xxx_seq.h: aic7xxx_reg.h
+ifeq ($(CONFIG_AIC7XXX_REG_PRETTY_PRINT),y)
+aic7xxx_reg.h: aic7xxx_reg_print.c
+endif
 $(aic7xxx-gen-y): $(src)/aic7xxx.seq $(src)/aic7xxx.reg $(obj)/aicasm/aicasm
 	$(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic7xxx_reg.h \
 			      $(aicasm-7xxx-opts-y) -o $(obj)/aic7xxx_seq.h \
@@ -72,6 +79,13 @@ aicasm-79xx-opts-$(CONFIG_AIC79XX_REG_PR
 	-p $(obj)/aic79xx_reg_print.c -i aic79xx_osm.h
 
 ifeq ($(CONFIG_AIC79XX_BUILD_FIRMWARE),y)
+# Create a dependency chain in generated files
+# to avoid concurrent invocations of the single
+# rule that builds them all.
+aic79xx_seq.h: aic79xx_reg.h
+ifeq ($(CONFIG_AIC79XX_REG_PRETTY_PRINT),y)
+aic79xx_reg.h: aic79xx_reg_print.c
+endif
 $(aic79xx-gen-y): $(src)/aic79xx.seq $(src)/aic79xx.reg $(obj)/aicasm/aicasm
 	$(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic79xx_reg.h \
 			      $(aicasm-79xx-opts-y) -o $(obj)/aic79xx_seq.h \

_
