====================================================================
-= Adaptec Ultra320 Family Manager Set v1.3.0 =
+= Adaptec Ultra320 Family Manager Set v1.3.11 =
= =
= README for =
= The Linux Operating System =
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:
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
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
#
# 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
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
#
# 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
# 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
* 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$
*/
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,
"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,
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);
/*
* Linux driver attachment glue for aic7770 based controllers.
*
- * Copyright (c) 2000-2001 Adaptec Inc.
+ * Copyright (c) 2000-2003 Adaptec Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7770_osm.c#13 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7770_osm.c#14 $
*/
#include "aic7xxx_osm.h"
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <linux/device.h>
+#include <linux/eisa.h>
+
+#define EISA_MFCTR_CHAR0(ID) (char)(((ID>>26) & 0x1F) | '@') /* Bits 26-30 */
+#define EISA_MFCTR_CHAR1(ID) (char)(((ID>>21) & 0x1F) | '@') /* Bits 21-25 */
+#define EISA_MFCTR_CHAR2(ID) (char)(((ID>>16) & 0x1F) | '@') /* Bits 16-20 */
+#define EISA_PRODUCT_ID(ID) (short)((ID>>4) & 0xFFF) /* Bits 4-15 */
+#define EISA_REVISION_ID(ID) (uint8_t)(ID & 0x0F) /* Bits 0-3 */
+
+static int aic7770_eisa_dev_probe(struct device *dev);
+static int aic7770_eisa_dev_remove(struct device *dev);
+static struct eisa_driver aic7770_driver = {
+ .driver = {
+ .name = "aic7xxx",
+ .probe = aic7770_eisa_dev_probe,
+ .remove = aic7770_eisa_dev_remove,
+ }
+};
+
+typedef struct device *aic7770_dev_t;
+#else
#define MINSLOT 1
#define NUMSLOTS 16
#define IDOFFSET 0x80
-int
-aic7770_linux_probe(Scsi_Host_Template *template)
+typedef void *aic7770_dev_t;
+#endif
+
+static int aic7770_linux_config(struct aic7770_identity *entry,
+ aic7770_dev_t dev, u_int eisaBase);
+
+void
+ahc_linux_eisa_init(void)
{
-#if defined(__i386__) || defined(__alpha__)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ struct eisa_device_id *eid;
+ struct aic7770_identity *id;
+ int i;
+
+ if (aic7xxx_probe_eisa_vl == 0)
+ return;
+
+ /*
+ * Linux requires the EISA IDs to be specified in
+ * the EISA ID string format. Perform the conversion
+ * and setup a table with a NUL terminal entry.
+ */
+ aic7770_driver.id_table = malloc(sizeof(struct eisa_device_id) *
+ (ahc_num_aic7770_devs + 1),
+ M_DEVBUF, M_NOWAIT);
+ if (aic7770_driver.id_table == NULL)
+ return;
+
+ for (eid = (struct eisa_device_id *)aic7770_driver.id_table,
+ id = aic7770_ident_table, i = 0;
+ i < ahc_num_aic7770_devs; eid++, id++, i++) {
+
+ sprintf(eid->sig, "%c%c%c%03X%01X",
+ EISA_MFCTR_CHAR0(id->full_id),
+ EISA_MFCTR_CHAR1(id->full_id),
+ EISA_MFCTR_CHAR2(id->full_id),
+ EISA_PRODUCT_ID(id->full_id),
+ EISA_REVISION_ID(id->full_id));
+ eid->driver_data = i;
+ }
+ eid->sig[0] = 0;
+
+ eisa_driver_register(&aic7770_driver);
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) */
struct aic7770_identity *entry;
- struct ahc_softc *ahc;
- int i, slot;
- int eisaBase;
- int found;
+ u_int slot;
+ u_int eisaBase;
+ u_int i;
+
+ if (aic7xxx_probe_eisa_vl == 0)
+ return;
eisaBase = 0x1000 + AHC_EISA_SLOT_OFFSET;
- found = 0;
for (slot = 1; slot < NUMSLOTS; eisaBase+=0x1000, slot++) {
uint32_t eisa_id;
size_t id_size;
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)
{
* 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)
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
* 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$
*/
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;
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 ***************************/
* 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) ******/
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);
*
* $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
address 0x030
access_mode RW
modes M_CFG
+ mask ILUNLEN 0x0F
+ mask TLUNLEN 0xF0
}
+const LUNLEN_SINGLE_LEVEL_LUN 0xF
/*
* CDB Limit
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 {
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 {
* $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_"
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;
* 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;
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;
}
bmov CURRSCB, SCBPTR, 2;
curscb_ww_done:
} else {
- /*
- * Untested - Verify with Rev B.
- */
bmov SCBPTR, CURRSCB, 2;
}
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;
}
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;
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)
* 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$
*/
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,
/* 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);
}
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)
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.
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
/*
* 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 {
* 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;
}
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:
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,
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;
}
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) {
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" : "");
{
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;
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;
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);
}
* 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)
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
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) {
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);
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;
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
* 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);
*/
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");
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;
* 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);
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
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);
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 ***********************************/
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);
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.
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 */
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);
}
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
* 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);
}
ahd->saved_dst_mode));
if (paused)
printf("Card was paused\n");
+
+ if (ahd_check_cmdcmpltqueues(ahd))
+ printf("Completions are pending\n");
+
/*
* Mode independent registers.
*/
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);
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");
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");
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);
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] =
ahd_set_scbptr(ahd, i);
printf("%3d", i);
printf("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n",
- ahd_inb(ahd, SCB_CONTROL),
- ahd_inb(ahd, SCB_SCSIID), ahd_inw(ahd, SCB_NEXT),
- ahd_inw(ahd, SCB_NEXT2), ahd_inl(ahd, SCB_SGPTR),
- ahd_inl(ahd, SCB_RESIDUAL_SGPTR));
+ ahd_inb_scbram(ahd, SCB_CONTROL),
+ ahd_inb_scbram(ahd, SCB_SCSIID),
+ ahd_inw_scbram(ahd, SCB_NEXT),
+ ahd_inw_scbram(ahd, SCB_NEXT2),
+ ahd_inl_scbram(ahd, SCB_SGPTR),
+ ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR));
}
printf("\n");
ahd_set_scbptr(ahd, saved_scb_index);
ahd->flags &= ~AHD_INITIATORROLE;
ahd_pause(ahd);
ahd_loadseq(ahd);
+ ahd_restart(ahd);
ahd_unlock(ahd, &s);
}
cel = &ccb->cel;
ahd->flags |= AHD_INITIATORROLE;
ahd_pause(ahd);
ahd_loadseq(ahd);
+ ahd_restart(ahd);
+ /*
+ * Unpaused. The extra unpause
+ * that follows is harmless.
+ */
}
}
ahd_unpause(ahd);
* 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$
*/
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);
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 *
/*
* 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.
static char dummy_buffer[60] = "Please don't trounce on me insmod!!\n";
MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
-MODULE_DESCRIPTION("Adaptec Aic77XX/78XX SCSI Host Bus Adapter driver");
+MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver");
#ifdef MODULE_LICENSE
MODULE_LICENSE("Dual BSD/GPL");
#endif
}
#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;
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);
}
* 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_
#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 ********************************/
/*
/***************************** 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);
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);
}
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);
}
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();
}
(((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)
* 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"
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);
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;
return (0);
}
-#ifdef MMAPIO
static int
ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
u_long *bus_addr,
error = ENOMEM;
return (error);
}
-#endif
int
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;
ahd_get_pci_function(ahd->dev_softc),
base);
}
-#endif
if (maddr == NULL) {
u_long base2;
* 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$
*/
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 [] =
{
ahd->bus_intr = ahd_pci_intr;
- error = ahd_reset(ahd);
+ error = ahd_reset(ahd, /*reinit*/FALSE);
if (error != 0)
return (ENXIO);
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;
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)
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);
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);
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;
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.
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.
* String handling code courtesy of Gerard Roudier's <groudier@club-internet.fr>
* sym driver.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#17 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#19 $
*/
#include "aic79xx_osm.h"
#include "aic79xx_inline.h"
* 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;
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;
* 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 {
#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
#define SHORTTHRESH 0x2f
#define LUNLEN 0x30
+#define TLUNLEN 0xf0
+#define ILUNLEN 0x0f
#define CDBLIMIT 0x31
#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
#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
#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
* 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"
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));
}
}
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 },
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[] = {
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[] = {
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[] = {
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));
}
* 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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
* 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$
*/
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
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 *******************************/
* 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$
*/
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,
* 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);
* 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)
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
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;
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);
/*
* 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;
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.
* 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);
}
ahc_resume(struct ahc_softc *ahc)
{
- ahc_reset(ahc);
+ ahc_reset(ahc, /*reinit*/TRUE);
+ ahc_intr_enable(ahc, TRUE);
+ ahc_restart(ahc);
return (0);
}
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);
*/
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;
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);
/*
* 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.
#define AIC7XXX_CONFIGED_DV -1
#endif
-static uint8_t aic7xxx_dv_settings[] =
+static int8_t aic7xxx_dv_settings[] =
{
AIC7XXX_CONFIGED_DV,
AIC7XXX_CONFIGED_DV,
* 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
/*
/************************ 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)
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__)
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
return (found);
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/*
* Free the passed in Scsi_Host memory structures prior to unloading the
* module.
ahc_list_unlock(&l);
return (0);
}
+#endif
/*
* Return a string describing the driver.
}
#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;
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);
}
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);
* 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_
#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 ********************************/
/*
/***************************** 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,
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);
}
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();
}
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);
{
return (pci->bus->number);
}
+#endif
static __inline void ahc_flush_device_writes(struct ahc_softc *);
static __inline void
(((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)
* 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"
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);
}
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) {
return (0);
}
-#ifdef MMAPIO
static int
ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
u_long *bus_addr,
error = ENOMEM;
return (error);
}
-#endif /* MMAPIO */
int
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;
ahc_get_pci_function(ahc->dev_softc),
base);
}
-#endif /* MMAPIO */
/*
* We always prefer memory mapped access.
* 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$
*/
#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
{
/* 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 */
scsiseq = 0;
}
- error = ahc_reset(ahc);
+ error = ahc_reset(ahc, /*reinit*/FALSE);
if (error != 0)
return (ENXIO);
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);
* String handling code courtesy of Gerard Roudier's <groudier@club-internet.fr>
* sym driver.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#27 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#29 $
*/
#include "aic7xxx_osm.h"
#include "aic7xxx_inline.h"
* 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;
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;
* 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"
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 }
};
}
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));
}
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));
}
* 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$
*/
\n {
++yylineno;
}
+\r ;
<ARGLIST>{SPACE} ;
<ARGLIST>\( {
parren_count++;
* 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$
*/
%%
\n { ++yylineno; }
+\r ;
"/*" { BEGIN COMMENT; /* Enter comment eating state */ }
<COMMENT>"/*" { fprintf(stderr, "Warning! Comment within comment."); }
<COMMENT>\n { ++yylineno; }
}
}
<CEXPR>\n { ++yylineno; }
+<CEXPR>\r ;
<CEXPR>[^()\n]+ {
char *yptr;
/* Eat escaped newlines. */
++yylineno;
}
+<MACROBODY>\r ;
<MACROBODY>\n {
/* Macros end on the first unescaped newline. */
BEGIN INITIAL;
}
<MACROBODY>{MBODY} {
char *yptr;
+ char c;
yptr = yytext;
- while (*yptr)
- *string_buf_ptr++ = *yptr++;
+ while (c = *yptr++) {
+ /*
+ * Strip carriage returns.
+ */
+ if (c == '\r')
+ continue;
+ *string_buf_ptr++ = c;
+ }
}
{WORD}\( {
char *yptr;