From c21e8b9222807579fa86c115783a493f570dddf1 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 30 Dec 2003 00:13:16 -0600 Subject: [PATCH] Update aic79xx to 1.3.11, aic7xxx to 6.2.36 From: "Justin T. Gibbs" --- Documentation/scsi/aic79xx.txt | 211 ++++-- Documentation/scsi/aic7xxx.txt | 59 +- drivers/scsi/aic7xxx/Kconfig.aic7xxx | 5 +- drivers/scsi/aic7xxx/Makefile | 10 +- drivers/scsi/aic7xxx/aic7770.c | 13 +- drivers/scsi/aic7xxx/aic7770_osm.c | 212 ++++-- drivers/scsi/aic7xxx/aic79xx.h | 43 +- drivers/scsi/aic7xxx/aic79xx.reg | 61 +- drivers/scsi/aic7xxx/aic79xx.seq | 62 +- drivers/scsi/aic7xxx/aic79xx_core.c | 684 ++++++++++++------ drivers/scsi/aic7xxx/aic79xx_inline.h | 17 +- drivers/scsi/aic7xxx/aic79xx_osm.c | 15 +- drivers/scsi/aic7xxx/aic79xx_osm.h | 31 +- drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 12 +- drivers/scsi/aic7xxx/aic79xx_pci.c | 63 +- drivers/scsi/aic7xxx/aic79xx_proc.c | 17 +- drivers/scsi/aic7xxx/aic79xx_reg.h_shipped | 133 ++-- .../scsi/aic7xxx/aic79xx_reg_print.c_shipped | 129 ++-- drivers/scsi/aic7xxx/aic79xx_seq.h_shipped | 154 ++-- drivers/scsi/aic7xxx/aic7xxx.h | 10 +- drivers/scsi/aic7xxx/aic7xxx_core.c | 83 ++- drivers/scsi/aic7xxx/aic7xxx_osm.c | 48 +- drivers/scsi/aic7xxx/aic7xxx_osm.h | 41 +- drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 10 +- drivers/scsi/aic7xxx/aic7xxx_pci.c | 18 +- drivers/scsi/aic7xxx/aic7xxx_proc.c | 17 +- .../scsi/aic7xxx/aic7xxx_reg_print.c_shipped | 22 +- .../scsi/aic7xxx/aicasm/aicasm_macro_scan.l | 3 +- drivers/scsi/aic7xxx/aicasm/aicasm_scan.l | 16 +- 29 files changed, 1423 insertions(+), 776 deletions(-) diff --git a/Documentation/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt index aa953bbc4775d..486c98d461ff2 100644 --- a/Documentation/scsi/aic79xx.txt +++ b/Documentation/scsi/aic79xx.txt @@ -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 diff --git a/Documentation/scsi/aic7xxx.txt b/Documentation/scsi/aic7xxx.txt index 4e88255e27e91..bd605974eef21 100644 --- a/Documentation/scsi/aic7xxx.txt +++ b/Documentation/scsi/aic7xxx.txt @@ -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 diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx index f5d76019bdc5b..a88cad2ae6bb5 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx +++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx @@ -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 diff --git a/drivers/scsi/aic7xxx/Makefile b/drivers/scsi/aic7xxx/Makefile index 301dc7c6c7f84..0dc6f0331bbb7 100644 --- a/drivers/scsi/aic7xxx/Makefile +++ b/drivers/scsi/aic7xxx/Makefile @@ -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 diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c index e62e8499bddcb..c6ef9b7972852 100644 --- a/drivers/scsi/aic7xxx/aic7770.c +++ b/drivers/scsi/aic7xxx/aic7770.c @@ -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); diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c index a374f84f22388..2eeed5ffeb5bf 100644 --- a/drivers/scsi/aic7xxx/aic7770_osm.c +++ b/drivers/scsi/aic7xxx/aic7770_osm.c @@ -1,7 +1,7 @@ /* * Linux driver attachment glue for aic7770 based controllers. * - * Copyright (c) 2000-2001 Adaptec Inc. + * Copyright (c) 2000-2003 Adaptec Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,27 +36,90 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7770_osm.c#13 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7770_osm.c#14 $ */ #include "aic7xxx_osm.h" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#include +#include + +#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 diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 43abefabdec98..be65968acd39b 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -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); diff --git a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg index 2cfdca5e956ad..449fe95ae6242 100644 --- a/drivers/scsi/aic7xxx/aic79xx.reg +++ b/drivers/scsi/aic7xxx/aic79xx.reg @@ -39,7 +39,7 @@ * * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#69 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $" /* * This file is processed by the aic7xxx_asm utility for use in assembling @@ -1377,7 +1377,10 @@ register LUNLEN { address 0x030 access_mode RW modes M_CFG + mask ILUNLEN 0x0F + mask TLUNLEN 0xF0 } +const LUNLEN_SINGLE_LEVEL_LUN 0xF /* * CDB Limit @@ -3797,32 +3800,8 @@ scb { size 4 alias SCB_NEXT_COMPLETE } - SCB_DATAPTR { - size 8 - } - SCB_DATACNT { - /* - * The last byte is really the high address bits for - * the data address. - */ - size 4 - field SG_LAST_SEG 0x80 /* In the fourth byte */ - field SG_HIGH_ADDR_BITS 0x7F /* In the fourth byte */ - } - SCB_SGPTR { - size 4 - field SG_STATUS_VALID 0x04 /* In the first byte */ - field SG_FULL_RESID 0x02 /* In the first byte */ - field SG_LIST_NULL 0x01 /* In the first byte */ - } - SCB_BUSADDR { - size 4 - } - SCB_NEXT { - alias SCB_NEXT_SCB_BUSADDR - size 2 - } - SCB_NEXT2 { + SCB_TAG { + alias SCB_FIFO_USE_COUNT size 2 } SCB_CONTROL { @@ -3859,8 +3838,32 @@ scb { SCB_TASK_MANAGEMENT { size 1 } - SCB_TAG { - alias SCB_FIFO_USE_COUNT + SCB_DATAPTR { + size 8 + } + SCB_DATACNT { + /* + * The last byte is really the high address bits for + * the data address. + */ + size 4 + field SG_LAST_SEG 0x80 /* In the fourth byte */ + field SG_HIGH_ADDR_BITS 0x7F /* In the fourth byte */ + } + SCB_SGPTR { + size 4 + field SG_STATUS_VALID 0x04 /* In the first byte */ + field SG_FULL_RESID 0x02 /* In the first byte */ + field SG_LIST_NULL 0x01 /* In the first byte */ + } + SCB_BUSADDR { + size 4 + } + SCB_NEXT { + alias SCB_NEXT_SCB_BUSADDR + size 2 + } + SCB_NEXT2 { size 2 } SCB_SPARE { diff --git a/drivers/scsi/aic7xxx/aic79xx.seq b/drivers/scsi/aic7xxx/aic79xx.seq index 7ac55616a73c4..65339bc1ca99c 100644 --- a/drivers/scsi/aic7xxx/aic79xx.seq +++ b/drivers/scsi/aic7xxx/aic79xx.seq @@ -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) diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index f1066067175fe..611d84b67dfe2 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -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); diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h index 9346d47dde1b9..440212af4419b 100644 --- a/drivers/scsi/aic7xxx/aic79xx_inline.h +++ b/drivers/scsi/aic7xxx/aic79xx_inline.h @@ -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 * diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 3857ed2508b8e..e75e25d88b1a2 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -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 "); -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); } diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index 8e989067179bd..9d73eb357c5ab 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -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) diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index e9d4eb145f94e..d30823d008a06 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -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; diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index b4da62704d690..913984539ae8f 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -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. diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c index 1c084a04eb3d5..e01cd6175e34d 100644 --- a/drivers/scsi/aic7xxx/aic79xx_proc.c +++ b/drivers/scsi/aic7xxx/aic79xx_proc.c @@ -37,7 +37,7 @@ * String handling code courtesy of Gerard Roudier's * 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; diff --git a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped index a4295858fea5b..c01ac39090d98 100644 --- a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped +++ b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped @@ -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 diff --git a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped index 476e84691313d..3098a757e3d76 100644 --- a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped +++ b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped @@ -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)); } diff --git a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped index 1c4109999d6c3..77c471f934e06 100644 --- a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped +++ b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped @@ -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, diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index 13dd811911331..ef1214c3149ea 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -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 *******************************/ diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 75f9757920264..22944e89f6d3a 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -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); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 599f0e3066296..75333b4fb4ba3 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -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); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index 76cc4473c5657..12f040d034b0a 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -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) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index b361ed9c085a6..04195c6ea5c83 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -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. diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index 377307d32f297..01cfab0e31340 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c @@ -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); diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c index 15391048111a5..85e80eecc9d04 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_proc.c +++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c @@ -37,7 +37,7 @@ * String handling code courtesy of Gerard Roudier's * 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; diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped index b0687b13a656f..9c713775d44a9 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped +++ b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped @@ -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)); } diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l b/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l index d781443f56a39..f06e7035cb357 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l +++ b/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l @@ -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 ; {SPACE} ; \( { parren_count++; diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l b/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l index e4dc6fd359baf..45c0b233d0bc2 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l +++ b/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l @@ -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 */ } "/*" { fprintf(stderr, "Warning! Comment within comment."); } \n { ++yylineno; } @@ -114,6 +115,7 @@ if[ \t]*\( { } } \n { ++yylineno; } +\r ; [^()\n]+ { char *yptr; @@ -359,6 +361,7 @@ else { return T_ELSE; } /* Eat escaped newlines. */ ++yylineno; } +\r ; \n { /* Macros end on the first unescaped newline. */ BEGIN INITIAL; @@ -369,10 +372,17 @@ else { return T_ELSE; } } {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; -- 2.53.0