]> git.hungrycats.org Git - linux/commitdiff
Update aic79xx to 1.3.11, aic7xxx to 6.2.36
authorJames Bottomley <jejb@raven.il.steeleye.com>
Tue, 30 Dec 2003 06:13:16 +0000 (00:13 -0600)
committerJames Bottomley <jejb@raven.il.steeleye.com>
Tue, 30 Dec 2003 06:13:16 +0000 (00:13 -0600)
From: "Justin T. Gibbs" <gibbs@scsiguy.com>

29 files changed:
Documentation/scsi/aic79xx.txt
Documentation/scsi/aic7xxx.txt
drivers/scsi/aic7xxx/Kconfig.aic7xxx
drivers/scsi/aic7xxx/Makefile
drivers/scsi/aic7xxx/aic7770.c
drivers/scsi/aic7xxx/aic7770_osm.c
drivers/scsi/aic7xxx/aic79xx.h
drivers/scsi/aic7xxx/aic79xx.reg
drivers/scsi/aic7xxx/aic79xx.seq
drivers/scsi/aic7xxx/aic79xx_core.c
drivers/scsi/aic7xxx/aic79xx_inline.h
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx/aic79xx_osm.h
drivers/scsi/aic7xxx/aic79xx_osm_pci.c
drivers/scsi/aic7xxx/aic79xx_pci.c
drivers/scsi/aic7xxx/aic79xx_proc.c
drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
drivers/scsi/aic7xxx/aic7xxx.h
drivers/scsi/aic7xxx/aic7xxx_core.c
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.h
drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
drivers/scsi/aic7xxx/aic7xxx_pci.c
drivers/scsi/aic7xxx/aic7xxx_proc.c
drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l
drivers/scsi/aic7xxx/aicasm/aicasm_scan.l

index aa953bbc4775d34543197ecf095e664c933ca9f6..486c98d461ff2572c366d293daad8c017956c219 100644 (file)
@@ -1,5 +1,5 @@
 ====================================================================
-=             Adaptec Ultra320 Family Manager Set v1.3.0           =
+=             Adaptec Ultra320 Family Manager Set v1.3.11          =
 =                                                                  =
 =                            README for                            =
 =                    The Linux Operating System                    =
@@ -19,57 +19,169 @@ The following information is available in this file:
    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.
-
-   (V1.0, May 2002) This is the initial release of the 
-   Ultra320 FMS.  The following is a list of supported features:
+   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.
+
+   1.0.0 (May 30th, 2002)
+        - Initial driver release.
 
    2.1. Software/Hardware Features
         - Support for the SPI-4 "Ultra320" standard:
@@ -82,6 +194,7 @@ The following information is available in this file:
           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
index 4e88255e27e91fc891f54e6fcd1e3749760ca8ff..bd605974eef21087d307a5ffc93c0b63ff6bd0fe 100644 (file)
@@ -131,27 +131,54 @@ The following information is available in this file:
       SCSI "stub" effects.
 
 2. Version History
+   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.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.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.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.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.32 - Dynamically sized S/G lists to avoid SCSI malloc
-                pool fragmentation and SCSI mid-layer deadlock.
+   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.28 - Domain Validation Fixes
-                 PCI parity error disable
-                 Enhanced Memory Mapped I/O probe
+   6.2.32 (March 28th, 2003)
+        - Dynamically sized S/G lists to avoid SCSI malloc
+          pool fragmentation and SCSI mid-layer deadlock.
 
-        6.2.20 - Added Domain Validation
+   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 (November 7th, 2002)
+        - Added Domain Validation.
 
 3. Command Line Options
 
index f5d76019bdc5bc39b4d8d401e58fec0153daae02..a88cad2ae6bb5bd97b05eb5d2b4204af5f11b17d 100644 (file)
@@ -1,9 +1,10 @@
 #
 # 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#7 $
 #
 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
@@ -50,7 +51,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
index 301dc7c6c7f8465af61309b71546527c6fd45b62..0dc6f0331bbb79422d236bcc6438c362e34d9d51 100644 (file)
@@ -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#7 $
 #
 
 # 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
index e62e8499bddcb720999574038f3ce7f24562e128..c6ef9b7972852e6166b305299fc1ccbbbfdaf00b 100644 (file)
@@ -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/aic7770.c#30 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7770.c#32 $
  *
  * $FreeBSD$
  */
@@ -67,8 +67,7 @@ static ahc_device_setup_t ahc_aic7770_VL_setup;
 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,
@@ -82,6 +81,12 @@ struct aic7770_identity aic7770_ident_table [] =
                "Adaptec 284X SCSI adapter",
                ahc_aic7770_VL_setup
        },
+       {
+               ID_AHA_284x,
+               0xFFFFFFFE,
+               "Adaptec 284X SCSI adapter (BIOS Disabled)",
+               ahc_aic7770_VL_setup
+       },
        {
                ID_OLV_274x,
                0xFFFFFFFF,
@@ -154,7 +159,7 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
        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);
 
index a374f84f22388e6865169826f5051b0c734e0a0a..2eeed5ffeb5bf70813dd84375d59e0e1ecd4362c 100644 (file)
@@ -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
  * 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#14 $
  */
 
 #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,64 @@ aic7770_linux_probe(Scsi_Host_Template *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);
+       }
+       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 +211,8 @@ aic7770_map_registers(struct ahc_softc *ahc, u_int port)
         * 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 +239,41 @@ aic7770_map_int(struct ahc_softc *ahc, u_int irq)
        
        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;
+
+               ahc_lock(ahc, &s);
+               ahc_intr_enable(ahc, FALSE);
+               ahc_unlock(ahc, &s);
+               ahc_free(ahc);
+       }
+       ahc_list_unlock(&l);
+
+       return (0);
+}
+#endif
index 43abefabdec98c2fe9ddd08eaf207dd8ab266494..be65968acd39bd3e4b407a4c6e74582e53651c4a 100644 (file)
@@ -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#95 $
  *
  * $FreeBSD$
  */
@@ -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,8 @@ 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_flag;
 
 /************************* Hardware  SCB Definition ***************************/
@@ -494,21 +497,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) ******/
@@ -1379,13 +1382,13 @@ struct scb              *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx);
 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);
index 2cfdca5e956ad8883a1c078d50374e88938e10c6..449fe95ae62427b70ea0a6e40b0b7dd7a2381542 100644 (file)
@@ -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 {
index 7ac55616a73c487d44bd81a1e9f48f9e00e62c9b..65339bc1ca99cd3f9b960703aa2b5e3c1520d452 100644 (file)
@@ -40,7 +40,7 @@
  * $FreeBSD$
  */
 
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#99 $"
 PATCH_ARG_LIST = "struct ahd_softc *ahd"
 PREFIX = "ahd_"
 
@@ -163,8 +163,8 @@ return:
 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;
@@ -276,7 +276,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;
@@ -492,12 +492,13 @@ SET_DST_MODE      M_SCSI;
 select_in:
        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;
        }
@@ -582,9 +583,6 @@ found_last_sent_scb:
                bmov    CURRSCB, SCBPTR, 2;
 curscb_ww_done:
        } else {
-               /*
-                * Untested - Verify with Rev B.
-                */
                bmov    SCBPTR, CURRSCB, 2;
        }
 
@@ -651,12 +649,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 +728,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;
 
@@ -1959,12 +1983,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)
index f1066067175fe5e4afe778503b558b79f161ce4e..611d84b67dfe2544d1d3bd66525b9ea02df14b96 100644 (file)
@@ -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.c#194 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#202 $
  *
  * $FreeBSD$
  */
@@ -224,6 +224,11 @@ static u_int               ahd_resolve_seqaddr(struct ahd_softc *ahd,
 static void            ahd_download_instr(struct ahd_softc *ahd,
                                           u_int instrptr, uint8_t *dconsts);
 static int             ahd_probe_stack_size(struct ahd_softc *ahd);
+static int             ahd_scb_active_in_fifo(struct ahd_softc *ahd,
+                                              struct scb *scb);
+static void            ahd_run_data_fifo(struct ahd_softc *ahd,
+                                         struct scb *scb);
+
 #ifdef AHD_TARGET_MODE
 static void            ahd_queue_lstate_event(struct ahd_softc *ahd,
                                               struct ahd_tmode_lstate *lstate,
@@ -328,10 +333,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,14 +373,92 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
        u_int           next_scbid;
 
        saved_modes = ahd_save_modes(ahd);
-       ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
+
+       /*
+        * Complete any SCBs that just finished being
+        * DMA'ed into the qoutfifo.
+        */
+       ahd_run_qoutfifo(ahd);
+
+       /*
+        * Flush the good status FIFO for compelted packetized commands.
+        */
+       ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
        saved_scbptr = ahd_get_scbptr(ahd);
+       while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) {
+               u_int fifo_mode;
+               u_int i;
+               
+               scbid = (ahd_inb(ahd, GSFIFO+1) << 8)
+                     | ahd_inb(ahd, GSFIFO);
+               scb = ahd_lookup_scb(ahd, scbid);
+               if (scb == NULL) {
+                       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;
+               for (i = 0; i < 2; i++) {
+                       /* Toggle to the other mode. */
+                       fifo_mode ^= 1;
+                       ahd_set_modes(ahd, fifo_mode, fifo_mode);
+                       if (ahd_scb_active_in_fifo(ahd, scb) == 0)
+                               continue;
+
+                       ahd_run_data_fifo(ahd, scb);
+
+                       /*
+                        * Clearing this transaction in this FIFO may
+                        * cause a CFG4DATA for this same transaction
+                        * to assert in the other FIFO.  Make sure we
+                        * loop one more time and check the other FIFO.
+                        */
+                       i = 0;
+               }
+               ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
+               ahd_set_scbptr(ahd, scbid);
+               if ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_LIST_NULL) == 0
+                && ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_FULL_RESID) != 0
+                 || (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR)
+                     & SG_LIST_NULL) != 0)) {
+                       u_int comp_head;
+
+                       /*
+                        * The transfer completed with a residual.
+                        * Place this SCB on the complete DMA list
+                        * so that we Update our in-core copy of the
+                        * SCB before completing the command.
+                        */
+                       ahd_outb(ahd, SCB_SCSI_STATUS, 0);
+                       ahd_outb(ahd, SCB_SGPTR,
+                                ahd_inb_scbram(ahd, SCB_SGPTR)
+                                | SG_STATUS_VALID);
+                       ahd_outw(ahd, SCB_TAG, SCB_GET_TAG(scb));
+                       comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
+                       ahd_outw(ahd, SCB_NEXT_COMPLETE, comp_head);
+                       if (SCBID_IS_NULL(comp_head))
+                               ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD,
+                                        SCB_GET_TAG(scb));
+               } else
+                       ahd_complete_scb(ahd, scb);
+       }
+       ahd_set_scbptr(ahd, saved_scbptr);
+
+       /*
+        * Setup for command channel portion of flush.
+        */
+       ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
 
        /*
         * Wait for any inprogress DMA to complete and clear DMA state
         * 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)
@@ -390,12 +470,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
        if ((ccscbctl & CCSCBDIR) != 0)
                ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN));
 
-       /*
-        * Complete any SCBs that just finished being
-        * DMA'ed into the qoutfifo.
-        */
-       ahd_run_qoutfifo(ahd);
-
+       saved_scbptr = ahd_get_scbptr(ahd);
        /*
         * Manually update/complete any completed SCBs that are waiting to be
         * DMA'ed back up to the host.
@@ -438,29 +513,276 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
                scbid = next_scbid;
        }
        ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
+
+       /*
+        * Restore state.
+        */
        ahd_set_scbptr(ahd, saved_scbptr);
+       ahd_restore_modes(ahd, saved_modes);
+       ahd->flags |= AHD_UPDATE_PEND_CMDS;
+}
+
+/*
+ * Determine if an SCB for a packetized transaction
+ * is active in a FIFO.
+ */
+static int
+ahd_scb_active_in_fifo(struct ahd_softc *ahd, struct scb *scb)
+{
 
        /*
-        * Flush the good status FIFO for compelted packetized commands.
+        * The FIFO is only active for our transaction if
+        * the SCBPTR matches the SCB's ID and the firmware
+        * has installed a handler for the FIFO or we have
+        * a pending SAVEPTRS or CFG4DATA interrupt.
         */
-       ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
-       while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) {
-               scbid = (ahd_inb(ahd, GSFIFO+1) << 8)
-                     | ahd_inb(ahd, GSFIFO);
-               scb = ahd_lookup_scb(ahd, scbid);
-               if (scb == NULL) {
-                       printf("%s: Warning - GSFIFO SCB %d invalid\n",
-                              ahd_name(ahd), scbid);
-                       continue;
+       if (ahd_get_scbptr(ahd) != SCB_GET_TAG(scb)
+        || ((ahd_inb(ahd, LONGJMP_ADDR+1) & INVALID_ADDR) != 0
+         && (ahd_inb(ahd, SEQINTSRC) & (CFG4DATA|SAVEPTRS)) == 0))
+               return (0);
+
+       return (1);
+}
+
+/*
+ * Run a data fifo to completion for a transaction we know
+ * has completed across the SCSI bus (good status has been
+ * received).  We are already set to the correct FIFO mode
+ * on entry to this routine.
+ *
+ * This function attempts to operate exactly as the firmware
+ * would when running this FIFO.  Care must be taken to update
+ * this routine any time the firmware's FIFO algorithm is
+ * changed.
+ */
+static void
+ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
+{
+       u_int seqintsrc;
+
+       while (1) {
+               seqintsrc = ahd_inb(ahd, SEQINTSRC);
+               if ((seqintsrc & CFG4DATA) != 0) {
+                       uint32_t datacnt;
+                       uint32_t sgptr;
+
+                       /*
+                        * Clear full residual flag.
+                        */
+                       sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
+                       ahd_outb(ahd, SCB_SGPTR, sgptr);
+
+                       /*
+                        * Load datacnt and address.
+                        */
+                       datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
+                       if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
+                               sgptr |= LAST_SEG;
+                               ahd_outb(ahd, SG_STATE, 0);
+                       } else
+                               ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
+                       ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
+                       ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
+                       ahd_outb(ahd, SG_CACHE_PRE, sgptr);
+                       ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
+
+                       /*
+                        * Initialize Residual Fields.
+                        */
+                       ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
+                       ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
+
+                       /*
+                        * Mark the SCB as having a FIFO in use.
+                        */
+                       ahd_outb(ahd, SCB_FIFO_USE_COUNT,
+                                ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
+
+                       /*
+                        * Install a "fake" handler for this FIFO.
+                        */
+                       ahd_outw(ahd, LONGJMP_ADDR, 0);
+
+                       /*
+                        * Notify the hardware that we have satisfied
+                        * this sequencer interrupt.
+                        */
+                       ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
+               } else if ((seqintsrc & SAVEPTRS) != 0) {
+                       uint32_t sgptr;
+                       uint32_t resid;
+
+                       if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
+                               /*
+                                * Snapshot Save Pointers.  Clear
+                                * the snapshot and continue.
+                                */
+                               ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
+                               continue;
+                       }
+
+                       /*
+                        * Disable S/G fetch so the DMA engine
+                        * is available to future users.
+                        */
+                       if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
+                               ahd_outb(ahd, CCSGCTL, 0);
+                       ahd_outb(ahd, SG_STATE, 0);
+
+                       /*
+                        * Flush the data FIFO.  Strickly only
+                        * necessary for Rev A parts.
+                        */
+                       ahd_outb(ahd, DFCNTRL,
+                                ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
+
+                       /*
+                        * Calculate residual.
+                        */
+                       sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
+                       resid = ahd_inl(ahd, SHCNT);
+                       resid |=
+                           ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
+                       ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
+                       if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
+                               /*
+                                * Must back up to the correct S/G element.
+                                * Typically this just means resetting our
+                                * low byte to the offset in the SG_CACHE,
+                                * but if we wrapped, we have to correct
+                                * the other bytes of the sgptr too.
+                                */
+                               if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
+                                && (sgptr & 0x80) == 0)
+                                       sgptr -= 0x100;
+                               sgptr &= ~0xFF;
+                               sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
+                                      & SG_ADDR_MASK;
+                               ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
+                               ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
+                       } else if ((resid & AHD_SG_LEN_MASK) == 0) {
+                               ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
+                                        sgptr | SG_LIST_NULL);
+                       }
+                       /*
+                        * Save Pointers.
+                        */
+                       ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
+                       ahd_outl(ahd, SCB_DATACNT, resid);
+                       ahd_outl(ahd, SCB_SGPTR, sgptr);
+                       ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
+                       ahd_outb(ahd, SEQIMODE,
+                                ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
+                       /*
+                        * If the data is to the SCSI bus, we are
+                        * done, otherwise wait for FIFOEMP.
+                        */
+                       if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
+                               break;
+               } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
+                       uint32_t sgptr;
+                       uint64_t data_addr;
+                       uint32_t data_len;
+                       u_int    dfcntrl;
+
+                       /*
+                        * Disable S/G fetch so the DMA engine
+                        * is available to future users.
+                        */
+                       if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
+                               ahd_outb(ahd, CCSGCTL, 0);
+                               ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
+                       }
+
+                       /*
+                        * Wait for the DMA engine to notice that the
+                        * host transfer is enabled and that there is
+                        * space in the S/G FIFO for new segments before
+                        * loading more segments.
+                        */
+                       if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) == 0)
+                               continue;
+                       if ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) == 0)
+                               continue;
+
+                       /*
+                        * Determine the offset of the next S/G
+                        * element to load.
+                        */
+                       sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
+                       sgptr &= SG_PTR_MASK;
+                       if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
+                               struct ahd_dma64_seg *sg;
+
+                               sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
+                               data_addr = sg->addr;
+                               data_len = sg->len;
+                               sgptr += sizeof(*sg);
+                       } else {
+                               struct  ahd_dma_seg *sg;
+
+                               sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
+                               data_addr = sg->len & AHD_SG_HIGH_ADDR_MASK;
+                               data_addr <<= 8;
+                               data_addr |= sg->addr;
+                               data_len = sg->len;
+                               sgptr += sizeof(*sg);
+                       }
+
+                       /*
+                        * Update residual information.
+                        */
+                       ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, data_len >> 24);
+                       ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
+
+                       /*
+                        * Load the S/G.
+                        */
+                       if (data_len & AHD_DMA_LAST_SEG) {
+                               sgptr |= LAST_SEG;
+                               ahd_outb(ahd, SG_STATE, 0);
+                       }
+                       ahd_outq(ahd, HADDR, data_addr);
+                       ahd_outl(ahd, HCNT, data_len & AHD_SG_LEN_MASK);
+                       ahd_outb(ahd, SG_CACHE_PRE, sgptr & 0xFF);
+
+                       /*
+                        * Advertise the segment to the hardware.
+                        */
+                       dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;
+                       if ((ahd->features & AHD_NEW_DFCNTRL_OPTS)!=0) {
+                               /*
+                                * Use SCSIENWRDIS so that SCSIEN
+                                * is never modified by this
+                                * operation.
+                                */
+                               dfcntrl |= SCSIENWRDIS;
+                       }
+                       ahd_outb(ahd, DFCNTRL, dfcntrl);
+               } else if ((ahd_inb(ahd, SG_CACHE_SHADOW)
+                        & LAST_SEG_DONE) != 0) {
+
+                       /*
+                        * Transfer completed to the end of SG list
+                        * and has flushed to the host.
+                        */
+                       ahd_outb(ahd, SCB_SGPTR,
+                                ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
+                       break;
+               } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
+                       break;
                }
-               ahd_complete_scb(ahd, scb);
+               ahd_delay(200);
        }
-
        /*
-        * Restore state.
+        * Clear any handler for this FIFO, decrement
+        * the FIFO use count for the SCB, and release
+        * the FIFO.
         */
-       ahd_restore_modes(ahd, saved_modes);
-       ahd->flags |= AHD_UPDATE_PEND_CMDS;
+       ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
+       ahd_outb(ahd, SCB_FIFO_USE_COUNT,
+                ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
+       ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
 }
 
 void
@@ -589,7 +911,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
                        /*
                         * 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 {
@@ -796,7 +1118,8 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
                         * attempt to complete this bogus SCB.
                         */
                        ahd_outb(ahd, SCB_CONTROL,
-                                ahd_inb(ahd, SCB_CONTROL) & ~STATUS_RCVD);
+                                ahd_inb_scbram(ahd, SCB_CONTROL)
+                                & ~STATUS_RCVD);
                }
                break;
        }
@@ -1029,7 +1352,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
                                           ROLE_INITIATOR, /*status*/0,
                                           SEARCH_REMOVE);
                ahd_outb(ahd, SCB_CONTROL,
-                        ahd_inb(ahd, SCB_CONTROL) & ~MK_MESSAGE);
+                        ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE);
                break;
        }
        case TASKMGMT_FUNC_COMPLETE:
@@ -1880,21 +2203,32 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
                        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,
@@ -2187,8 +2521,14 @@ ahd_clear_critical_section(struct ahd_softc *ahd)
                        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 +2536,8 @@ ahd_clear_critical_section(struct ahd_softc *ahd)
                ahd_outb(ahd, CLRINT, CLRSCSIINT);
                ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
                ahd_outb(ahd, HCNTRL, ahd->unpause);
-               do {
+               while (!ahd_is_paused(ahd))
                        ahd_delay(200);
-               } while (!ahd_is_paused(ahd));
                ahd_update_modes(ahd);
        }
        if (stepping) {
@@ -2316,7 +2655,7 @@ ahd_dump_sglist(struct scb *scb)
                                len = ahd_le32toh(sg_list[i].len);
                                printf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
                                       i,
-                                      (len >> 24) & SG_HIGH_ADDR_BITS,
+                                      (len & AHD_SG_HIGH_ADDR_MASK) >> 24,
                                       ahd_le32toh(sg_list[i].addr),
                                       len & AHD_SG_LEN_MASK,
                                       len & AHD_DMA_LAST_SEG ? " Last" : "");
@@ -2904,7 +3243,7 @@ ahd_update_pending_scbs(struct ahd_softc *ahd)
 {
        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 +3301,14 @@ ahd_update_pending_scbs(struct ahd_softc *ahd)
        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 +3523,7 @@ ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
                       devinfo->target_mask);
                panic("SCB = %d, SCB Control = %x:%x, MSG_OUT = %x "
                      "SCB flags = %x", SCB_GET_TAG(scb), scb->hscb->control,
-                     ahd_inb(ahd, SCB_CONTROL), ahd_inb(ahd, MSG_OUT),
+                     ahd_inb_scbram(ahd, SCB_CONTROL), ahd_inb(ahd, MSG_OUT),
                      scb->flags);
        }
 
@@ -3232,6 +3568,7 @@ ahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
         * 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 +3576,7 @@ ahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
        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 +3586,7 @@ ahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
 
        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 +4062,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 +4325,30 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
                                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;
@@ -4401,7 +4751,8 @@ ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
 
                sgptr = ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);
                if ((sgptr & SG_LIST_NULL) != 0
-                && (ahd_inb(ahd, SCB_TASK_ATTRIBUTE) & SCB_XFERLEN_ODD) != 0) {
+                && (ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)
+                    & SCB_XFERLEN_ODD) != 0) {
                        /*
                         * If the residual occurred on the last
                         * transfer and the transfer request was
@@ -4502,7 +4853,8 @@ ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
                         * correct for subsequent data transfers.
                         */
                        ahd_outb(ahd, SCB_TASK_ATTRIBUTE,
-                           ahd_inb(ahd, SCB_TASK_ATTRIBUTE) ^ SCB_XFERLEN_ODD);
+                           ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)
+                           ^ SCB_XFERLEN_ODD);
 
                        ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
                        ahd_outl(ahd, SCB_RESIDUAL_DATACNT, data_cnt);
@@ -4542,9 +4894,8 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
         */
        ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
        wait = 1000;
-       do {
+       while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE))
                ahd_delay(100);
-       } while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE));
        if (wait == 0) {
                ahd_print_path(ahd, scb);
                printf("ahd_reinitialize_dataptrs: Forcing FIFO free.\n");
@@ -5000,15 +5351,20 @@ ahd_shutdown(void *arg)
        ahd_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;
@@ -5101,7 +5457,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);
@@ -5382,6 +5738,7 @@ ahd_setup_iocell_workaround(struct ahd_softc *ahd)
                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 +5747,8 @@ ahd_iocell_first_selection(struct ahd_softc *ahd)
        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 +5768,7 @@ ahd_iocell_first_selection(struct ahd_softc *ahd)
        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 ***********************************/
@@ -6174,7 +6534,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 +6575,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 +6583,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 */
@@ -6703,141 +7065,24 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
 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);
 }
 
@@ -7479,9 +7724,12 @@ ahd_reset_current_bus(struct ahd_softc *ahd)
        ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~ENSCSIRST);
        scsiseq = ahd_inb(ahd, SCSISEQ0) & ~(ENSELO|ENARBO|SCSIRSTO);
        ahd_outb(ahd, SCSISEQ0, scsiseq | SCSIRSTO);
+       ahd_flush_device_writes(ahd);
        ahd_delay(AHD_BUSRESET_DELAY);
        /* Turn off the bus reset */
        ahd_outb(ahd, SCSISEQ0, scsiseq);
+       ahd_flush_device_writes(ahd);
+       ahd_delay(AHD_BUSRESET_DELAY);
        if ((ahd->bugs & AHD_SCSIRST_BUG) != 0) {
                /*
                 * 2A Razor #474
@@ -7489,8 +7737,7 @@ ahd_reset_current_bus(struct ahd_softc *ahd)
                 * 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);
        }
@@ -8585,6 +8832,10 @@ ahd_dump_card_state(struct ahd_softc *ahd)
                                    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 +8885,12 @@ ahd_dump_card_state(struct ahd_softc *ahd)
                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 +8919,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
        while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
                ahd_set_scbptr(ahd, scb_index);
                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 +8929,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
        while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
                ahd_set_scbptr(ahd, scb_index);
                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 +8940,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
        while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
                ahd_set_scbptr(ahd, scb_index);
                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 +9019,16 @@ ahd_dump_card_state(struct ahd_softc *ahd)
               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,10 +9060,12 @@ 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);
@@ -9192,6 +9448,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
                        ahd->flags &= ~AHD_INITIATORROLE;
                ahd_pause(ahd);
                ahd_loadseq(ahd);
+               ahd_restart(ahd);
                ahd_unlock(ahd, &s);
        }
        cel = &ccb->cel;
@@ -9425,6 +9682,11 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
                                ahd->flags |= AHD_INITIATORROLE;
                                ahd_pause(ahd);
                                ahd_loadseq(ahd);
+                               ahd_restart(ahd);
+                               /*
+                                * Unpaused.  The extra unpause
+                                * that follows is harmless.
+                                */
                        }
                }
                ahd_unpause(ahd);
index 9346d47dde1b990d2c974a38ac2c3fccb9be937a..440212af4419b8cecb46d3a232616df26af7fa6f 100644 (file)
@@ -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#51 $
  *
  * $FreeBSD$
  */
@@ -455,6 +455,8 @@ static __inline u_int       ahd_inb_scbram(struct ahd_softc *ahd, u_int offset);
 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);
@@ -697,10 +699,15 @@ ahd_inw_scbram(struct ahd_softc *ahd, u_int offset)
 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 *
index 3857ed2508b8e57a41e1a52d515df43f0292dd26..e75e25d88b1a272e2f348a5bf72f2b43de6aafd0 100644 (file)
@@ -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#171 $
  *
  * --------------------------------------------------------------------------
  * Copyright (c) 1994-2000 Justin T. Gibbs.
@@ -425,7 +425,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
@@ -4442,6 +4442,16 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
                        }
 #endif
                        ahd_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;
 
@@ -4456,6 +4466,7 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
                                ahd_get_residual(scb),
                                ahd_get_transfer_length(scb));
                        ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR);
+#endif
                } else {
                        ahd_set_transaction_status(scb, CAM_REQ_CMP);
                }
index 8e989067179bd598ff3a54e65261c74522b74d3f..9d73eb357c5ab308efb63f19a8aa1613270e38bf 100644 (file)
@@ -36,7 +36,7 @@
  * 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#137 $
  *
  */
 #ifndef _AIC79XX_LINUX_H_
@@ -292,7 +292,7 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec)
 #define AHD_SCSI_HAS_HOST_LOCK 0
 #endif
 
-#define AIC79XX_DRIVER_VERSION "1.3.9"
+#define AIC79XX_DRIVER_VERSION "1.3.11"
 
 /**************************** Front End Queues ********************************/
 /*
@@ -590,10 +590,6 @@ ahd_delay(long usec)
 
 
 /***************************** 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);
@@ -608,16 +604,12 @@ 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 +618,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 +631,22 @@ ahd_inw_atomic(struct ahd_softc * ahd, long port)
 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();
 }
 
@@ -1005,7 +985,12 @@ ahd_flush_device_writes(struct ahd_softc *ahd)
        (((dev_softc)->dma_mask = mask) && 0)
 #endif
 /**************************** Proc FS Support *********************************/
-int    ahd_linux_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+int    ahd_linux_proc_info(char *, char **, off_t, int, int, int);
+#else
+int    ahd_linux_proc_info(struct Scsi_Host *, char *, char **,
+                           off_t, int, int);
+#endif
 
 /*************************** Domain Validation ********************************/
 #define AHD_DV_CMD(cmd) ((cmd)->scsi_done == ahd_linux_dv_complete)
index e9d4eb145f94e7c6ddb92611f7d264e882e428f9..d30823d008a060ea13b83eadaa0f3d8ac542f3e7 100644 (file)
@@ -36,7 +36,7 @@
  * 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#25 $
  */
 
 #include "aic79xx_osm.h"
@@ -52,11 +52,9 @@ static int   ahd_linux_pci_dev_probe(struct pci_dev *pdev,
                                        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);
 
@@ -163,8 +161,8 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                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) {
                        ahd->flags |= AHD_64BIT_ADDRESSING;
@@ -273,7 +271,6 @@ ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base,
        return (0);
 }
 
-#ifdef MMAPIO
 static int
 ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
                                 u_long *bus_addr,
@@ -321,7 +318,6 @@ ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
                error = ENOMEM;
        return (error);
 }
-#endif
 
 int
 ahd_pci_map_registers(struct ahd_softc *ahd)
@@ -338,7 +334,6 @@ ahd_pci_map_registers(struct ahd_softc *ahd)
        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;
@@ -373,7 +368,6 @@ ahd_pci_map_registers(struct ahd_softc *ahd)
                       ahd_get_pci_function(ahd->dev_softc),
                       base);
        }
-#endif
 
        if (maddr == NULL) {
                u_long   base2;
index b4da62704d6909fda7904fd89d507a6f101cfc94..913984539ae8fac2d2c75048f639f49ffc5a6261 100644 (file)
@@ -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/aic79xx_pci.c#73 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#77 $
  *
  * $FreeBSD$
  */
@@ -117,6 +117,7 @@ ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
 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 [] =
 {
@@ -375,7 +376,7 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
 
        ahd->bus_intr = ahd_pci_intr;
 
-       error = ahd_reset(ahd);
+       error = ahd_reset(ahd, /*reinit*/FALSE);
        if (error != 0)
                return (ENXIO);
 
@@ -418,9 +419,11 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
 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;
 
@@ -454,6 +457,18 @@ ahd_pci_test_register_access(struct ahd_softc *ahd)
        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 = ahd_pci_read_config(ahd->dev_softc,
+                                         PCIR_STATUS + 1, /*bytes*/1);
+       ahd_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,8 +487,6 @@ ahd_pci_test_register_access(struct ahd_softc *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);
@@ -486,7 +499,6 @@ fail:
                                     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);
        return (error);
@@ -903,29 +915,31 @@ ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat)
 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->chip = AHD_AIC7902;
+       ahd->features = AHD_AIC7902_FE;
+       return (ahd_aic790X_setup(ahd));
+}
+
+static int
+ahd_aic790X_setup(struct ahd_softc *ahd)
 {
        ahd_dev_softc_t pci;
        u_int rev;
@@ -939,8 +953,6 @@ ahd_aic7902_setup(struct ahd_softc *ahd)
                return (ENXIO);
        }
        ahd->channel = ahd_get_pci_function(pci) + 'A';
-       ahd->chip = AHD_AIC7902;
-       ahd->features = AHD_AIC7902_FE;
        if (rev < ID_AIC7902_PCI_REV_B0) {
                /*
                 * Enable A series workarounds.
@@ -968,9 +980,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.
index 1c084a04eb3d5369e2302fb7ede59a5fd92dc2bd..e01cd6175e34d36d83d6d1b29534daf0aaa54198 100644 (file)
@@ -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#19 $
  */
 #include "aic79xx_osm.h"
 #include "aic79xx_inline.h"
@@ -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 *shost, char *buffer, char **start, off_t o
 
        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;
index a4295858fea5b8016f00f6f67fb5e6a0b05977b7..c01ac39090d98d02473734cfce5118ce6198f43c 100644 (file)
@@ -3,7 +3,7 @@
  *              from the following source files:
  *
  * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#69 $
+ * $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_print;
 #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_lists_print;
 #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_lists_print;
 #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_lists_print;
 #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_lists_print;
 #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
index 476e84691313db03c15ca62e13f6a6dad33de309..3098a757e3d762e32c6fa0877d2565cdf95ef255 100644 (file)
@@ -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#94 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
  */
 
 #include "aic79xx_osm.h"
@@ -489,10 +489,15 @@ ahd_shortthresh_print(u_int regvalue, u_int *cur_col, u_int wrap)
            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 regvalue, u_int *cur_col, u_int wrap)
 }
 
 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));
 }
 
index 1c4109999d6c323723f994bd9ff5fbd1154202e9..77c471f934e0665da99c75622627528be86d527f 100644 (file)
@@ -3,7 +3,7 @@
  *              from the following source files:
  *
  * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#69 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
  */
 static uint8_t seqprog[] = {
        0xff, 0x02, 0x06, 0x78,
@@ -40,13 +40,13 @@ static uint8_t seqprog[] = {
        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, 0x04, 0x00,
-       0x08, 0xa8, 0x51, 0x03,
-       0xff, 0xae, 0x3f, 0x68,
+       0x08, 0x92, 0x25, 0x03,
+       0xff, 0x90, 0x3f, 0x68,
        0x00, 0xe2, 0x56, 0x5b,
        0x00, 0xe2, 0x3e, 0x40,
        0x00, 0xea, 0x44, 0x59,
@@ -113,24 +113,24 @@ 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,
+       0x01, 0xea, 0x20, 0x33,
+       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, 0xf5, 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,
+       0x02, 0xa0, 0x58, 0x37,
        0xff, 0x21, 0xfd, 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,
@@ -161,7 +161,7 @@ static uint8_t seqprog[] = {
        0x04, 0x24, 0xf9, 0x30,
        0x1d, 0xea, 0x3a, 0x41,
        0x02, 0x2c, 0x51, 0x31,
-       0x04, 0xa0, 0xf9, 0x30,
+       0x04, 0xa8, 0xf9, 0x30,
        0x19, 0xea, 0x3a, 0x41,
        0x06, 0xea, 0x08, 0x81,
        0x01, 0xe2, 0x5a, 0x35,
@@ -179,8 +179,8 @@ 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, 0x63, 0x79,
        0x01, 0x6b, 0xc0, 0x30,
        0x02, 0x64, 0xc8, 0x00,
        0x40, 0x3a, 0x74, 0x04,
@@ -219,42 +219,42 @@ static uint8_t seqprog[] = {
        0xff, 0xea, 0xb2, 0x09,
        0xff, 0xe0, 0xc0, 0x19,
        0xff, 0xe0, 0xb0, 0x79,
-       0x02, 0xa4, 0x51, 0x31,
+       0x02, 0xac, 0x51, 0x31,
        0x00, 0xe2, 0xa6, 0x41,
        0x02, 0x5e, 0x50, 0x31,
        0x02, 0xa8, 0xb8, 0x30,
        0x02, 0x5c, 0x50, 0x31,
-       0xff, 0xa5, 0xc1, 0x71,
-       0x02, 0xa4, 0x41, 0x31,
+       0xff, 0xad, 0xc1, 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,
+       0x10, 0x92, 0xcb, 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,
+       0x02, 0xae, 0x41, 0x32,
        0xff, 0x21, 0xd3, 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, 0x92, 0xdf, 0x79,
        0x10, 0x40, 0xe8, 0x69,
        0x01, 0x56, 0xe8, 0x79,
-       0xff, 0xad, 0x07, 0x78,
+       0xff, 0x97, 0x07, 0x78,
        0x13, 0xea, 0x50, 0x59,
        0x13, 0xea, 0x04, 0x00,
        0x00, 0xe2, 0x06, 0x40,
        0xbf, 0x3a, 0x74, 0x08,
        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,
@@ -277,13 +277,13 @@ static uint8_t seqprog[] = {
        0x33, 0xea, 0x00, 0x00,
        0x02, 0xa8, 0x90, 0x32,
        0x00, 0xe2, 0x6a, 0x59,
-       0xef, 0xac, 0xd5, 0x19,
+       0xef, 0x96, 0xd5, 0x19,
        0x00, 0xe2, 0x2a, 0x52,
        0x09, 0x80, 0xe1, 0x30,
        0x02, 0xea, 0x36, 0x00,
        0xa8, 0xea, 0x32, 0x00,
        0x00, 0xe2, 0x30, 0x42,
-       0x01, 0xac, 0xd1, 0x30,
+       0x01, 0x96, 0xd1, 0x30,
        0x10, 0x80, 0x89, 0x31,
        0x20, 0xea, 0x32, 0x00,
        0xbf, 0x33, 0x67, 0x0a,
@@ -293,20 +293,20 @@ static uint8_t seqprog[] = {
        0x00, 0xe2, 0xf8, 0x41,
        0x80, 0x33, 0xb5, 0x6a,
        0x01, 0x44, 0x10, 0x33,
-       0x08, 0xa8, 0x51, 0x03,
+       0x08, 0x92, 0x25, 0x03,
        0x00, 0xe2, 0xf8, 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,
+       0x10, 0x92, 0x85, 0x6a,
+       0xc0, 0x94, 0xc5, 0x01,
+       0x40, 0x92, 0x51, 0x6a,
        0xbf, 0xe2, 0xc4, 0x09,
-       0x20, 0xa8, 0x65, 0x7a,
+       0x20, 0x92, 0x65, 0x7a,
        0x01, 0xe2, 0x88, 0x30,
        0x00, 0xe2, 0xb8, 0x5b,
        0xa0, 0x36, 0x6d, 0x62,
-       0x23, 0xa8, 0x89, 0x08,
+       0x23, 0x92, 0x89, 0x08,
        0x00, 0xe2, 0xb8, 0x5b,
        0xa0, 0x36, 0x6d, 0x62,
        0x00, 0xa8, 0x64, 0x42,
@@ -348,7 +348,7 @@ static uint8_t seqprog[] = {
        0xa0, 0xea, 0xca, 0x5b,
        0x01, 0xa0, 0xba, 0x62,
        0x01, 0x84, 0xaf, 0x7a,
-       0x01, 0xab, 0xbd, 0x6a,
+       0x01, 0x95, 0xbd, 0x6a,
        0x05, 0xea, 0x50, 0x59,
        0x05, 0xea, 0x04, 0x00,
        0x00, 0xe2, 0xbc, 0x42,
@@ -381,22 +381,22 @@ static uint8_t seqprog[] = {
        0x20, 0x46, 0x12, 0x63,
        0xff, 0xea, 0x52, 0x09,
        0xa8, 0xea, 0xca, 0x5b,
-       0x04, 0xa8, 0xf9, 0x7a,
+       0x04, 0x92, 0xf9, 0x7a,
        0x01, 0x34, 0xc1, 0x31,
-       0x00, 0xa9, 0xf9, 0x62,
+       0x00, 0x93, 0xf9, 0x62,
        0x01, 0x35, 0xc1, 0x31,
-       0x00, 0xaa, 0x03, 0x73,
+       0x00, 0x94, 0x03, 0x73,
        0x01, 0xa9, 0x52, 0x11,
        0xff, 0xa9, 0xee, 0x6a,
        0x00, 0xe2, 0x12, 0x43,
        0x10, 0x33, 0x67, 0x02,
-       0x04, 0xa8, 0x13, 0x7b,
-       0xfb, 0xa8, 0x51, 0x0b,
+       0x04, 0x92, 0x13, 0x7b,
+       0xfb, 0x92, 0x25, 0x0b,
        0xff, 0xea, 0x66, 0x0a,
-       0x01, 0x9c, 0x0d, 0x6b,
+       0x01, 0xa4, 0x0d, 0x6b,
        0x02, 0xa8, 0x90, 0x32,
        0x00, 0xe2, 0x6a, 0x59,
-       0x10, 0xa8, 0xbd, 0x7a,
+       0x10, 0x92, 0xbd, 0x7a,
        0xff, 0xea, 0xdc, 0x5b,
        0x00, 0xe2, 0xbc, 0x42,
        0x04, 0xea, 0x50, 0x59,
@@ -405,12 +405,12 @@ static uint8_t seqprog[] = {
        0x04, 0xea, 0x50, 0x59,
        0x04, 0xea, 0x04, 0x00,
        0x00, 0xe2, 0xf8, 0x41,
-       0x08, 0xa8, 0xb5, 0x7a,
+       0x08, 0x92, 0xb5, 0x7a,
        0xc0, 0x33, 0x29, 0x7b,
        0x80, 0x33, 0xb5, 0x6a,
        0xff, 0x88, 0x29, 0x6b,
        0x40, 0x33, 0xb5, 0x6a,
-       0x10, 0xa8, 0x2f, 0x7b,
+       0x10, 0x92, 0x2f, 0x7b,
        0x0a, 0xea, 0x50, 0x59,
        0x0a, 0xea, 0x04, 0x00,
        0x00, 0xe2, 0x4e, 0x5b,
@@ -428,22 +428,22 @@ static uint8_t seqprog[] = {
        0x33, 0xea, 0x44, 0x59,
        0x33, 0xea, 0x00, 0x00,
        0x02, 0x42, 0x51, 0x31,
-       0xff, 0xae, 0x65, 0x68,
+       0xff, 0x90, 0x65, 0x68,
        0xff, 0x88, 0x5b, 0x6b,
-       0x01, 0x9c, 0x57, 0x6b,
-       0x02, 0x9c, 0x5f, 0x6b,
+       0x01, 0xa4, 0x57, 0x6b,
+       0x02, 0xa4, 0x5f, 0x6b,
        0x01, 0x84, 0x5f, 0x7b,
        0x02, 0x28, 0x19, 0x33,
        0x02, 0xa8, 0x50, 0x36,
        0xff, 0x88, 0x5f, 0x73,
        0x00, 0xe2, 0x32, 0x5b,
-       0x02, 0xa8, 0x5c, 0x33,
+       0x02, 0xa8, 0x20, 0x33,
        0x02, 0x2c, 0x19, 0x33,
        0x02, 0xa8, 0x58, 0x32,
-       0x04, 0x9c, 0x39, 0x07,
+       0x04, 0xa4, 0x49, 0x07,
        0xc0, 0x33, 0xb5, 0x6a,
-       0x04, 0xa8, 0x51, 0x03,
-       0x20, 0xa8, 0x83, 0x6b,
+       0x04, 0x92, 0x25, 0x03,
+       0x20, 0x92, 0x83, 0x6b,
        0x02, 0xa8, 0x40, 0x31,
        0xc0, 0x34, 0xc1, 0x09,
        0x00, 0x35, 0x51, 0x01,
@@ -470,9 +470,9 @@ static uint8_t seqprog[] = {
        0x00, 0xe2, 0x9e, 0x5b,
        0x00, 0xe2, 0xf8, 0x41,
        0x01, 0x84, 0xa3, 0x7b,
-       0x01, 0x9c, 0x39, 0x07,
-       0x08, 0x60, 0x20, 0x33,
-       0x08, 0x80, 0x31, 0x37,
+       0x01, 0xa4, 0x49, 0x07,
+       0x08, 0x60, 0x30, 0x33,
+       0x08, 0x80, 0x41, 0x37,
        0xdf, 0x33, 0x67, 0x0a,
        0xee, 0x00, 0xb0, 0x6b,
        0x05, 0xea, 0xb4, 0x00,
@@ -542,14 +542,14 @@ 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,
@@ -577,7 +577,7 @@ static uint8_t seqprog[] = {
        0x09, 0xea, 0x50, 0x59,
        0x09, 0xea, 0x04, 0x00,
        0x00, 0xe2, 0xf8, 0x41,
-       0x01, 0x9c, 0x5d, 0x6c,
+       0x01, 0xa4, 0x5d, 0x6c,
        0x00, 0xe2, 0x30, 0x5c,
        0x20, 0x33, 0x67, 0x02,
        0x01, 0x00, 0x60, 0x32,
@@ -646,15 +646,15 @@ static uint8_t seqprog[] = {
        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,
+       0xf3, 0x96, 0xd5, 0x19,
        0x00, 0xe2, 0x18, 0x55,
-       0x80, 0xac, 0x19, 0x6d,
+       0x80, 0x96, 0x19, 0x6d,
        0x0f, 0xea, 0x50, 0x59,
        0x0f, 0xea, 0x04, 0x00,
        0x00, 0xe2, 0x20, 0x45,
@@ -662,7 +662,7 @@ static uint8_t seqprog[] = {
        0x01, 0xea, 0xf2, 0x00,
        0x02, 0xea, 0x36, 0x00,
        0xa8, 0xea, 0x32, 0x00,
-       0xff, 0xad, 0x27, 0x7d,
+       0xff, 0x97, 0x27, 0x7d,
        0x14, 0xea, 0x50, 0x59,
        0x14, 0xea, 0x04, 0x00,
        0x00, 0xe2, 0x96, 0x5d,
@@ -700,10 +700,10 @@ static uint8_t seqprog[] = {
        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, 0x43, 0x6b,
        0x02, 0xea, 0xb4, 0x04,
-       0x01, 0x9c, 0x39, 0x03,
+       0x01, 0xa4, 0x49, 0x03,
        0x40, 0x5b, 0x82, 0x6d,
        0x00, 0xe2, 0x3e, 0x59,
        0x40, 0x5b, 0x82, 0x6d,
@@ -714,8 +714,8 @@ 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, 0x43, 0x6b,
        0x02, 0xea, 0xb4, 0x04,
        0x00, 0xe2, 0x3e, 0x59,
        0x01, 0x1b, 0x64, 0x78,
@@ -729,7 +729,7 @@ static uint8_t seqprog[] = {
        0x01, 0x1a, 0x64, 0x78,
        0x80, 0xf9, 0xf2, 0x01,
        0xff, 0xea, 0x10, 0x03,
-       0x08, 0xa8, 0x51, 0x03,
+       0x08, 0x92, 0x25, 0x03,
        0x00, 0xe2, 0x42, 0x43,
        0x01, 0x1a, 0xb4, 0x7d,
        0x40, 0x5b, 0xb0, 0x7d,
@@ -743,14 +743,14 @@ static uint8_t seqprog[] = {
        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,
        0x80, 0xf9, 0xf2, 0x01,
-       0xff, 0xae, 0x5d, 0x1b,
+       0xff, 0x90, 0x21, 0x1b,
        0x02, 0xea, 0xb4, 0x00,
        0x20, 0xea, 0x9a, 0x00,
        0xf3, 0x42, 0xde, 0x6d,
@@ -760,7 +760,7 @@ static uint8_t seqprog[] = {
        0x0d, 0xea, 0x50, 0x59,
        0x0d, 0xea, 0x04, 0x00,
        0x00, 0xe2, 0xf8, 0x41,
-       0x01, 0xae, 0x5d, 0x1b,
+       0x01, 0x90, 0x21, 0x1b,
        0x11, 0xea, 0x50, 0x59,
        0x11, 0xea, 0x04, 0x00,
        0x00, 0xe2, 0x32, 0x5b,
@@ -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, 0x43, 0x6b,
        0x02, 0xea, 0xb4, 0x04,
        0x01, 0x38, 0xe1, 0x30,
        0x05, 0x39, 0xe3, 0x98,
index 13dd8119113316193b6bfe5c8688affee539f86d..ef1214c3149eaddec192aeb65dd49f25dbd4d547 100644 (file)
@@ -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#79 $
  *
  * $FreeBSD$
  */
@@ -1143,17 +1143,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
@@ -1205,7 +1205,7 @@ void                       ahc_set_unit(struct ahc_softc *, int);
 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 *******************************/
index 75f9757920264f35e3771179b1eb117ec3f0cbde..22944e89f6d3a277d57487b4d17d0ab0df4646f2 100644 (file)
@@ -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.c#131 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#134 $
  *
  * $FreeBSD$
  */
@@ -1304,17 +1304,23 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
                                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_softc *ahc)
                                 * 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);
@@ -2373,6 +2379,7 @@ ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
         * 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 *ahc, struct ahc_devinfo *devinfo)
        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
@@ -3176,23 +3183,30 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
                                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;
@@ -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;
@@ -4143,7 +4162,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.
@@ -4725,14 +4744,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);
        }
-
+       ahc_restart(ahc);
        return (0);
 }
 
@@ -5145,7 +5162,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);
 }
 
@@ -6407,7 +6426,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);
@@ -6968,11 +6986,12 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
                         */
                        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 +7226,16 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
                                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);
index 599f0e3066296bc8e1269299a120a5630507a47e..75333b4fb4ba34a264105c300c90865549f00cf7 100644 (file)
@@ -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#235 $
  *
  * Copyright (c) 1994 John Aycock
  *   The University of Calgary Department of Computer Science.
@@ -293,7 +293,7 @@ static adapter_tag_info_t aic7xxx_tag_info[] =
 #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 +391,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
 
 /*
@@ -752,7 +752,6 @@ ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
 
 /************************  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 +764,7 @@ static int     ahc_linux_biosparam(struct scsi_device*,
                                       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__)
@@ -895,8 +895,9 @@ ahc_linux_detect(Scsi_Host_Template *template)
        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 +916,7 @@ ahc_linux_detect(Scsi_Host_Template *template)
        return (found);
 }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 /*
  * Free the passed in Scsi_Host memory structures prior to unloading the
  * module.
@@ -946,6 +948,7 @@ ahc_linux_release(struct Scsi_Host * host)
        ahc_list_unlock(&l);
        return (0);
 }
+#endif
 
 /*
  * Return a string describing the driver.
@@ -4137,6 +4140,16 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
                        }
 #endif
                        ahc_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;
 
@@ -4151,6 +4164,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
                                ahc_get_residual(scb),
                                ahc_get_transfer_length(scb));
                        ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR);
+#endif
                } else {
                        ahc_set_transaction_status(scb, CAM_REQ_CMP);
                }
@@ -5082,27 +5096,21 @@ ahc_linux_exit(void)
                ahc_linux_kill_dv_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);
index 76cc4473c56578c14df4f5d3fb47876c67accf82..12f040d034b0aa4baaeb383ac6de5a50afc04937 100644 (file)
@@ -53,7 +53,7 @@
  * 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#151 $
  *
  */
 #ifndef _AIC7XXX_LINUX_H_
@@ -304,7 +304,7 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec)
 #define AHC_SCSI_HAS_HOST_LOCK 0
 #endif
 
-#define AIC7XXX_DRIVER_VERSION "6.2.35"
+#define AIC7XXX_DRIVER_VERSION "6.2.36"
 
 /**************************** Front End Queues ********************************/
 /*
@@ -595,10 +595,6 @@ ahc_delay(long usec)
 
 
 /***************************** 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,
@@ -610,16 +606,12 @@ 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 +619,11 @@ ahc_inb(struct ahc_softc * ahc, long port)
 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();
 }
 
@@ -843,15 +831,26 @@ typedef enum
        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
+void                    ahc_power_state_change(struct ahc_softc *ahc,
+                                               ahc_power_state new_state);
 int                     ahc_linux_pci_init(void);
 void                    ahc_linux_pci_exit(void);
 int                     ahc_pci_map_registers(struct ahc_softc *ahc);
@@ -933,6 +932,7 @@ ahc_get_pci_bus(ahc_dev_softc_t pci)
 {
        return (pci->bus->number);
 }
+#endif
 
 static __inline void ahc_flush_device_writes(struct ahc_softc *);
 static __inline void
@@ -962,7 +962,12 @@ ahc_flush_device_writes(struct ahc_softc *ahc)
        (((dev_softc)->dma_mask = mask) && 0)
 #endif
 /**************************** Proc FS Support *********************************/
-int    ahc_linux_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+int    ahc_linux_proc_info(char *, char **, off_t, int, int, int);
+#else
+int    ahc_linux_proc_info(struct Scsi_Host *, char *, char **,
+                           off_t, int, int);
+#endif
 
 /*************************** Domain Validation ********************************/
 #define AHC_DV_CMD(cmd) ((cmd)->scsi_done == ahc_linux_dv_complete)
index b361ed9c085a6847f25f15fa7a4f8859dd3596dd..04195c6ea5c830ef60bc400903ea4fc536ac21e1 100644 (file)
@@ -36,7 +36,7 @@
  * 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#47 $
  */
 
 #include "aic7xxx_osm.h"
@@ -51,11 +51,9 @@ static int   ahc_linux_pci_dev_probe(struct pci_dev *pdev,
                                        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);
 
@@ -161,7 +159,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
        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) {
@@ -254,7 +252,6 @@ ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base)
        return (0);
 }
 
-#ifdef MMAPIO
 static int
 ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
                                 u_long *bus_addr,
@@ -296,7 +293,6 @@ ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
                error = ENOMEM;
        return (error);
 }
-#endif /* MMAPIO */
 
 int
 ahc_pci_map_registers(struct ahc_softc *ahc)
@@ -313,7 +309,6 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
        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;
@@ -350,7 +345,6 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
                       ahc_get_pci_function(ahc->dev_softc),
                       base);
        }
-#endif /* MMAPIO */
 
        /*
         * We always prefer memory mapped access.
index 377307d32f29762c85c49ba8bddc1b0c4ef5ae52..01cfab0e31340d89aceb4cd4ded1bfc3a437b7fc 100644 (file)
@@ -39,7 +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 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#69 $
  *
  * $FreeBSD$
  */
@@ -76,7 +76,7 @@ ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
 #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
@@ -245,9 +245,9 @@ struct ahc_pci_identity ahc_pci_ident_table [] =
 {
        /* 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 */
@@ -877,7 +877,7 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
                scsiseq = 0;
        }
 
-       error = ahc_reset(ahc);
+       error = ahc_reset(ahc, /*reinit*/FALSE);
        if (error != 0)
                return (ENXIO);
 
@@ -1289,6 +1289,14 @@ ahc_pci_test_register_access(struct ahc_softc *ahc)
        ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
        while (ahc_is_paused(ahc) == 0)
                ;
+
+       /* Clear any PCI errors that occurred before our driver attached. */
+       status1 = ahc_pci_read_config(ahc->dev_softc,
+                                     PCIR_STATUS + 1, /*bytes*/1);
+       ahc_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);
index 15391048111a515eb93572c867d500b528df1a8e..85e80eecc9d044c539bc75a5b3d91d9a736ab6aa 100644 (file)
@@ -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#29 $
  */
 #include "aic7xxx_osm.h"
 #include "aic7xxx_inline.h"
@@ -289,8 +289,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 +307,14 @@ ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t o
 
        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;
index b0687b13a656fcee9353b35072ba7a8ee05863b9..9c713775d44a9bd1caadfbb1e201b66eed32fb69 100644 (file)
@@ -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#56 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $
  */
 
 #include "aic7xxx_osm.h"
@@ -747,13 +747,6 @@ ahc_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap)
            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_int *cur_col, u_int wrap)
 }
 
 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_int *cur_col, u_int wrap)
 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));
 }
 
index d781443f56a395c1c1df017259686cf4b7c28c2b..f06e7035cb35765c7718edde3240f8c5577c468e 100644 (file)
@@ -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++;
index e4dc6fd359bafdd1698c2284268735f6814b6a41..45c0b233d0bc239ba99acbf39b8765f7e8bce7da 100644 (file)
@@ -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;