diff -urN linux-2.4.25/drivers/scsi/aic7xxx/Makefile linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/Makefile --- linux-2.4.25/drivers/scsi/aic7xxx/Makefile Wed Jul 30 09:18:49 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/Makefile Tue Feb 10 01:47:04 2004 @@ -14,6 +14,10 @@ endif EXTRA_CFLAGS += -I$(TOPDIR)/drivers/scsi -Werror +ifeq ($(wildcard $(TOPDIR)/include/linux/rhconfig.h), \ + $(TOPDIR)/include/linux/rhconfig.h) +EXTRA_CFLAGS += -DAIC_RED_HAT_LINUX_KERNEL +endif #EXTRA_CFLAGS += -g # Platform Specific Files @@ -64,8 +68,13 @@ $(LD) $(LD_RFLAG) -r -o $@ $(obj-aic79xx) ifeq ($(CONFIG_AIC7XXX_BUILD_FIRMWARE),y) +# Create a dependency chain in generated files +# to avoid concurrent invocations of the single +# rule that builds them all. +aic7xxx_seq.h: aic7xxx_reg.h aic7xxx_gen = aic7xxx_seq.h aic7xxx_reg.h ifeq ($(CONFIG_AIC7XXX_REG_PRETTY_PRINT),y) +aic7xxx_reg.h: aic7xxx_reg_print.c aic7xxx_gen += aic7xxx_reg_print.c aic7xxx_asm_cmd = aicasm/aicasm -I. -r aic7xxx_reg.h \ -p aic7xxx_reg_print.c -i aic7xxx_osm.h \ @@ -79,8 +88,13 @@ endif ifeq ($(CONFIG_AIC79XX_BUILD_FIRMWARE),y) +# Create a dependency chain in generated files +# to avoid concurrent invocations of the single +# rule that builds them all. +aic79xx_seq.h: aic79xx_reg.h aic79xx_gen = aic79xx_seq.h aic79xx_reg.h ifeq ($(CONFIG_AIC79XX_REG_PRETTY_PRINT),y) +aic79xx_reg.h: aic79xx_reg_print.c aic79xx_gen += aic79xx_reg_print.c aic79xx_asm_cmd = aicasm/aicasm -I. -r aic79xx_reg.h \ -p aic79xx_reg_print.c -i aic79xx_osm.h \ diff -urN linux-2.4.25/drivers/scsi/aic7xxx/README.aic79xx linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/README.aic79xx --- linux-2.4.25/drivers/scsi/aic7xxx/README.aic79xx Wed Jul 30 09:18:49 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/README.aic79xx Tue Feb 10 01:47:04 2004 @@ -1,5 +1,5 @@ ==================================================================== -= Adaptec Ultra320 Family Manager Set v1.3.0 = += Adaptec Ultra320 Family Manager Set v2.0.5 = = = = README for = = The Linux Operating System = @@ -19,34 +19,195 @@ 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 + + 2.0.6 (February 6th, 2004) + - Force a renegotiation on all inqury commands so that + the negotiated transfer parameters are correct even + if the device has been externally reset since our last + command. Devices are not allowed to report unit attention + conditions in response to inquiry requests otherwise we'd + not need to treat inquiry commands specially. + - Remove all vestiges of pre-2.4.X support. + - Close a very rare race-condition in RevA 790X controllers. + If both FIFOs are allocated before the sequencer's idle + loop is able to service the FIFO that was allocated first, + the sequencer could handle them out of order. This could + lead to a deadlock where the FIFO attached to the SCSI bus + is being serviced by the sequencer, but the other FIFO is + required to handle a snapshot. The sequencer now detects + this condition and always handles FIFOs that are not currently + on the bus first. + - Close a few race conditions by adding critical section + markers into the firmware. These windows might have caused + issues during error recovery. + - Switch the complete DMA SCB list to a tailq so that multiple + SCBs completing with non-zero status do not interfere with + the state for the SCB currently being uploaded. + - Use the comparison of a kernel and a sequencer qfreeze + count to control the freezing of outgoing selections. This + allows the kernel to handle non-zero SCB completions without + having to clear firmware critical sections. + - Change the completion FIFO mechanism so that all completion + entries are guaranteed aligned on a 64bit boundary. This + avoids SCB DMA engine bugs that are triggered if the transfer + is interrupted (e.g. PCI disconnect) on a non-aligned boundary. + In some cases, these bugs would result in duplicate completions. + - Use one byte in the new completion entry to indicate if the + SCB completed without a residual or non-zero SCSI status. This + avoids an extra memory reference in our interrupt handler. + + 2.0.5 (December 22nd, 2003) + - Correct a bug preventing the driver from renegotiating + during auto-request sense operations when a check + condition occurred for a zero length command. + - Sniff sense information returned by targets for unit + attention errors that may indicate that the device has + been changed. If we see such status for non Domain + Validation related commands, start a DV scan for the + target. In the past, DV would only occur for hot-plugged + devices if no target had been previously probed for a + particular ID. This change guarantees that the DV process + will occur even if the user swaps devices without any + interveining I/O to tell us that a device has gone missing. + The old behavior, among other things, would fail to spin up + drives that were hot-plugged since the Linux mid-layer + will only spin-up drives on initial attach. + - Correct several issues in the rundown of the good status + FIFO during error recovery. The typical failure scenario + evidenced by this defect was the loss of several commands + under high load when several queue full conditions occured + back to back. + + 2.0.4 (November 6th, 2003) + - Support the 2.6.0-test9 kernel + - Fix rare deadlock caused by using del_timer_sync from within + a timer handler. + + 2.0.3 (October 21st, 2003) + - On 7902A4 hardware, use the slow slew rate for transfer + rates slower than U320. This behavior matches the Windows + driver. + - Fix some issues with the ahd_flush_qoutfifo() routine. + - Add a delay in the loop waiting for selection activity + to cease. Otherwise we may exhaust the loop counter too + quickly on fast machines. + - Return to processing bad status completions through the + qoutfifo. This reduces the amount of time the controller + is paused for these kinds of errors. + - Move additional common routines to the aiclib OSM library + to reduce code duplication. + - Leave removal of softcs from the global list of softcs to + the OSM. This allows us to avoid holding the list_lock during + device destruction. + - Enforce a bus settle delay for bus resets that the + driver initiates. + - Fall back to basic DV for U160 devices that lack an + echo buffer. + + 2.0.2 (September 4th, 2003) + - Move additional common routines to the aiclib OSM library + to reduce code duplication. + - Avoid an inadvertant reset of the controller during the + memory mapped I/O test should the controller be left in + the reset state prior to driver initialization. On some + systems, this extra reset resulted in a system hang due + to a chip access that occurred too soon after reset. + - Correct an endian bug in ahd_swap_with_next_hscb. This + corrects strong-arm support. + - Reset the bus for transactions that timeout waiting for + the bus to go free after a disconnect or command complete + message. + + 2.0.1 (August 26th, 2003) + - Add magic sysrq handler that causes a card dump to be output + to the console for each controller. + - Avoid waking the mid-layer's error recovery handler during + timeout recovery by returning DID_ERROR instead of DID_TIMEOUT + for timed-out commands that have been aborted. + - Move additional common routines to the aiclib OSM library + to reduce code duplication. + + 2.0.0 (August 20th, 2003) + - Remove MMAPIO definition and allow memory mapped + I/O for any platform that supports PCI. + - Avoid clearing ENBUSFREE during single stepping to avoid + spurious "unexpected busfree while idle" messages. + - Correct deadlock in ahd_run_qoutfifo() processing. + - Optimize support for the 7901B. + - Correct a few cases where an explicit flush of pending + register writes was required to ensure acuracy in delays. + - Correct problems in manually flushing completed commands + on the controller. The FIFOs are now flushed to ensure + that completed commands that are still draining to the + host are completed correctly. + - Correct incomplete CDB delivery detection on the 790XB. + - Ignore the cmd->underflow field since userland applications + using the legacy command pass-thru interface do not set + it correctly. Honoring this field led to spurious errors + when users used the "scsi_unique_id" program. + - Perform timeout recovery within the driver instead of relying + on the Linux SCSI mid-layer to perform this function. The + mid-layer does not know the full state of the SCSI bus and + is therefore prone to looping for several minutes to effect + recovery. The new scheme recovers within 15 seconds of the + failure. + - Correct support for manual termination settings. + - Increase maximum wait time for serial eeprom writes allowing + writes to function correctly. + + 1.3.12 (August 11, 2003) + - Implement new error recovery thread that supercedes the existing + Linux SCSI error recovery code. + - Fix termination logic for 29320ALP. + - Fix SEEPROM delay to compensate for write ops taking longer. + + 1.3.11 (July 11, 2003) + - Fix several deadlock issues. + - Add 29320ALP and 39320B Id's. + 1.3.10 (June 3rd, 2003) - Align the SCB_TAG field on a 16byte boundary. This avoids SCB corruption on some PCI-33 busses. @@ -174,7 +335,7 @@ supported) - Support for the PCI-X standard up to 133MHz - Support for the PCI v2.2 standard - - Domain Validation + - Domain Validation 2.2. Operating System Support: - Redhat Linux 7.2, 7.3, 8.0, Advanced Server 2.1 diff -urN linux-2.4.25/drivers/scsi/aic7xxx/README.aic7xxx linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/README.aic7xxx --- linux-2.4.25/drivers/scsi/aic7xxx/README.aic7xxx Wed Jul 30 09:18:49 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/README.aic7xxx Tue Feb 10 01:47:04 2004 @@ -1,5 +1,5 @@ ==================================================================== -= Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v6.2.28 = += Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v6.3.4 = = README for = = The Linux Operating System = ==================================================================== @@ -131,6 +131,90 @@ SCSI "stub" effects. 2. Version History + + 6.3.5 (February 22nd, 2004) + - Force a renegotiation on all inqury commands so that + the negotiated transfer parameters are correct even + if the device has been externally reset since our last + command. Devices are not allowed to report unit attention + conditions in response to inquiry requests otherwise we'd + not need to treat inquiry commands specially. + - Remove all vestiges of pre-2.4.X support. + - Move all lock and DMA API support to the aiclib. + + 6.3.4 (December 22nd, 2003) + - Provide a better description string for the 2915/30LP. + - Sniff sense information returned by targets for unit + attention errors that may indicate that the device has + been changed. If we see such status for non Domain + Validation related commands, start a DV scan for the + target. In the past, DV would only occur for hot-plugged + devices if no target had been previously probed for a + particular ID. This change guarantees that the DV process + will occur even if the user swaps devices without any + interveining I/O to tell us that a device has gone missing. + The old behavior, among other things, would fail to spin up + drives that were hot-plugged since the Linux mid-layer + will only spin-up drives on initial attach. + + 6.3.3 (November 6th, 2003) + - Support the 2.6.0-test9 kernel + - Fix rare deadlock caused by using del_timer_sync from within + a timer handler. + + 6.3.2 (October 28th, 2003) + - Enforce a bus settle delay for bus resets that the + driver initiates. + - Fall back to basic DV for U160 devices that lack an + echo buffer. + - Correctly detect that left over BIOS data has not + been initialized when the CHPRST status bit is set + during driver initialization. + + 6.3.1 (October 21st, 2003) + - Fix a compiler error when building with only EISA or PCI + support compiled into the kernel. + - Add chained dependencies to both the driver and aicasm Makefiles + to avoid problems with parallel builds. + - Move additional common routines to the aiclib OSM library + to reduce code duplication. + - Fix a bug in the testing of the AHC_TMODE_WIDEODD_BUG that + could cause target mode operations to hang. + - Leave removal of softcs from the global list of softcs to + the OSM. This allows us to avoid holding the list_lock during + device destruction. + + 6.3.0 (September 8th, 2003) + - Move additional common routines to the aiclib OSM library + to reduce code duplication. + - Bump minor number to reflect change in error recovery strategy. + + 6.2.38 (August 31st, 2003) + - Avoid an inadvertant reset of the controller during the + memory mapped I/O test should the controller be left in + the reset state prior to driver initialization. On some + systems, this extra reset resulted in a system hang due + to a chip access that occurred too soon after reset. + - Move additional common routines to the aiclib OSM library + to reduce code duplication. + - Add magic sysrq handler that causes a card dump to be output + to the console for each controller. + + 6.2.37 (August 12th, 2003) + - Perform timeout recovery within the driver instead of relying + on the Linux SCSI mid-layer to perform this function. The + mid-layer does not know the full state of the SCSI bus and + is therefore prone to looping for several minutes to effect + recovery. The new scheme recovers within 15 seconds of the + failure. + - Support writing 93c56/66 SEEPROM on newer cards. + - Avoid clearing ENBUSFREE during single stepping to avoid + spurious "unexpected busfree while idle" messages. + - Enable the use of the "Auto-Access-Pause" feature on the + aic7880 and aic7870 chips. It was disabled due to an + oversight. Using this feature drastically reduces command + delivery latency. + 6.2.36 (June 3rd, 2003) - Correct code that disables PCI parity error checking. - Correct and simplify handling of the ignore wide residue diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7770.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7770.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic7770.c Wed Jul 30 09:18:49 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7770.c Tue Feb 10 00:15:15 2004 @@ -37,9 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7770.c#32 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic7770.c#34 $ */ #ifdef __linux__ @@ -47,6 +45,8 @@ #include "aic7xxx_inline.h" #include "aic7xxx_93cx6.h" #else +#include +__FBSDID("$FreeBSD$"); #include #include #include @@ -175,7 +175,7 @@ case 15: break; default: - printf("aic7770_config: illegal irq setting %d\n", intdef); + printf("aic7770_config: invalid irq setting %d\n", intdef); return (ENXIO); } diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7770_osm.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7770_osm.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic7770_osm.c Wed Jul 30 09:18:49 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7770_osm.c Tue Feb 10 01:47:04 2004 @@ -36,7 +36,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7770_osm.c#14 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7770_osm.c#19 $ */ #include "aic7xxx_osm.h" @@ -73,7 +73,7 @@ static int aic7770_linux_config(struct aic7770_identity *entry, aic7770_dev_t dev, u_int eisaBase); -void +int ahc_linux_eisa_init(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) @@ -82,7 +82,7 @@ int i; if (aic7xxx_probe_eisa_vl == 0) - return; + return (0); /* * Linux requires the EISA IDs to be specified in @@ -93,7 +93,7 @@ (ahc_num_aic7770_devs + 1), M_DEVBUF, M_NOWAIT); if (aic7770_driver.id_table == NULL) - return; + return (-ENOMEM); for (eid = (struct eisa_device_id *)aic7770_driver.id_table, id = aic7770_ident_table, i = 0; @@ -109,7 +109,7 @@ } eid->sig[0] = 0; - eisa_driver_register(&aic7770_driver); + return (eisa_driver_register(&aic7770_driver)); #else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) */ struct aic7770_identity *entry; u_int slot; @@ -117,21 +117,15 @@ u_int i; if (aic7xxx_probe_eisa_vl == 0) - return; + return (0); eisaBase = 0x1000 + AHC_EISA_SLOT_OFFSET; for (slot = 1; slot < NUMSLOTS; eisaBase+=0x1000, slot++) { uint32_t eisa_id; size_t id_size; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - if (check_region(eisaBase, AHC_EISA_IOSIZE) != 0) - continue; - request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx"); -#else if (request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx") == 0) continue; -#endif eisa_id = 0; id_size = sizeof(eisa_id); @@ -149,6 +143,7 @@ if (entry != NULL) aic7770_linux_config(entry, NULL, eisaBase); } + return (0); #endif } @@ -190,6 +185,14 @@ free(name, M_DEVBUF); return (ENOMEM); } + ahc->dev_softc = dev; + if (aic_set_dma_mask(ahc, 0xFFFFFFFF) != 0 + /*|| aic_set_consistent_dma_mask(ahc, 0xFFFFFFFF) != 0 */) { + printk(KERN_WARNING "aic7xxx: Unable to set DMA masks.\n"); + ahc_free(ahc); + return (-ENOMEM); + } + ahc->platform_data->hw_dma_mask = 0xFFFFFFFF; error = aic7770_config(ahc, entry, eisaBase); if (error != 0) { ahc->bsh.ioport = 0; @@ -210,14 +213,8 @@ /* * 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 (ENOMEM); -#endif ahc->tag = BUS_SPACE_PIO; ahc->bsh.ioport = port; return (0); @@ -267,12 +264,14 @@ if (ahc != NULL) { u_long s; + TAILQ_REMOVE(&ahc_tailq, ahc, links); + ahc_list_unlock(&l); ahc_lock(ahc, &s); ahc_intr_enable(ahc, FALSE); ahc_unlock(ahc, &s); ahc_free(ahc); - } - ahc_list_unlock(&l); + } else + ahc_list_unlock(&l); return (0); } diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic79xx.h linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx.h --- linux-2.4.25/drivers/scsi/aic7xxx/aic79xx.h Wed Jul 30 12:18:02 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx.h Tue Feb 10 01:47:04 2004 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#92 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#106 $ * * $FreeBSD$ */ @@ -74,9 +74,8 @@ #define ALL_TARGETS_MASK 0xFFFF #define INITIATOR_WILDCARD (~0) #define SCB_LIST_NULL 0xFF00 -#define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL)) -#define QOUTFIFO_ENTRY_VALID 0x8000 -#define QOUTFIFO_ENTRY_VALID_LE (ahd_htole16(0x8000)) +#define SCB_LIST_NULL_LE (aic_htole16(SCB_LIST_NULL)) +#define QOUTFIFO_ENTRY_VALID 0x80 #define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL) #define SCSIID_TARGET(ahd, scsiid) \ @@ -118,7 +117,7 @@ ((lun) | ((target) << 8)) #define SCB_GET_TAG(scb) \ - ahd_le16toh(scb->hscb->tag) + aic_le16toh(scb->hscb->tag) #ifndef AHD_TARGET_MODE #undef AHD_TMODE_ENABLE @@ -202,6 +201,8 @@ #define AHD_BUSRESET_DELAY 25 /******************* Chip Characteristics/Operating Settings *****************/ +extern uint32_t ahd_attach_to_HostRAID_controllers; + /* * Chip Type * The chip order is from least sophisticated to most sophisticated. @@ -229,8 +230,10 @@ AHD_RTI = 0x04000,/* Retained Training Support */ AHD_NEW_IOCELL_OPTS = 0x08000,/* More Signal knobs in the IOCELL */ AHD_NEW_DFCNTRL_OPTS = 0x10000,/* SCSIENWRDIS bit */ + AHD_FAST_CDB_DELIVERY = 0x20000,/* CDB acks released to Output Sync */ AHD_REMOVABLE = 0x00000,/* Hot-Swap supported - None so far*/ AHD_AIC7901_FE = AHD_FENONE, + AHD_AIC7901A_FE = AHD_FENONE, AHD_AIC7902_FE = AHD_MULTI_FUNC } ahd_feature; @@ -372,7 +375,10 @@ AHD_HP_BOARD = 0x100000, AHD_RESET_POLL_ACTIVE = 0x200000, AHD_UPDATE_PEND_CMDS = 0x400000, - AHD_RUNNING_QOUTFIFO = 0x800000 + AHD_RUNNING_QOUTFIFO = 0x800000, + AHD_HAD_FIRST_SEL = 0x1000000, + AHD_SHUTDOWN_RECOVERY = 0x2000000, /* Terminate recovery thread. */ + AHD_HOSTRAID_BOARD = 0x4000000 } ahd_flag; /************************* Hardware SCB Definition ***************************/ @@ -546,7 +552,7 @@ struct map_node { bus_dmamap_t dmamap; - bus_addr_t physaddr; + bus_addr_t busaddr; uint8_t *vaddr; SLIST_ENTRY(map_node) links; }; @@ -588,12 +594,16 @@ SCB_PKT_SENSE = 0x02000, SCB_CMDPHASE_ABORT = 0x04000, SCB_ON_COL_LIST = 0x08000, - SCB_SILENT = 0x10000 /* + SCB_SILENT = 0x10000,/* * Be quiet about transmission type * errors. They are expected and we * don't want to upset the user. This * flag is typically used during DV. */ + SCB_TIMEDOUT = 0x20000/* + * SCB has timed out and is on the + * timedout list. + */ } scb_flag; struct scb { @@ -610,8 +620,9 @@ } links2; #define pending_links links2.le #define collision_links links2.le + LIST_ENTRY(scb) timedout_links; struct scb *col_scb; - ahd_io_ctx_t io_ctx; + aic_io_ctx_t io_ctx; struct ahd_softc *ahd_softc; scb_flag flags; #ifndef __linux__ @@ -1050,6 +1061,14 @@ typedef void ahd_callback_t (void *); +struct ahd_completion +{ + uint16_t tag; + uint8_t sg_status; + uint8_t pad[4]; + uint8_t valid_tag; +}; + struct ahd_softc { bus_space_tag_t tags[2]; bus_space_handle_t bshs[2]; @@ -1059,6 +1078,7 @@ struct scb_data scb_data; struct hardware_scb *next_queued_hscb; + struct map_node *next_queued_hscb_map; /* * SCBs that have been sent to the controller @@ -1066,6 +1086,11 @@ LIST_HEAD(, scb) pending_scbs; /* + * SCBs whose timeout routine has been called. + */ + LIST_HEAD(, scb) timedout_scbs; + + /* * Current register window mode information. */ ahd_mode dst_mode; @@ -1086,7 +1111,7 @@ /* * Platform specific device information. */ - ahd_dev_softc_t dev_softc; + aic_dev_softc_t dev_softc; /* * Bus specific device information. @@ -1116,8 +1141,8 @@ /* * Timer handles for timer driven callbacks. */ - ahd_timer_t reset_timer; - ahd_timer_t stat_timer; + aic_timer_t reset_timer; + aic_timer_t stat_timer; /* * Statistics. @@ -1137,16 +1162,23 @@ ahd_flag flags; struct seeprom_config *seep_config; - /* Values to store in the SEQCTL register for pause and unpause */ - uint8_t unpause; - uint8_t pause; - /* Command Queues */ + struct ahd_completion *qoutfifo; uint16_t qoutfifonext; uint16_t qoutfifonext_valid_tag; uint16_t qinfifonext; uint16_t qinfifo[AHD_SCB_MAX]; - uint16_t *qoutfifo; + + /* + * Our qfreeze count. The sequencer compares + * this value with its own counter to determine + * whether to allow selections to occur. + */ + uint16_t qfreeze_cnt; + + /* Values to store in the SEQCTL register for pause and unpause */ + uint8_t unpause; + uint8_t pause; /* Critical Section Data */ struct cs *critical_sections; @@ -1194,8 +1226,7 @@ */ bus_dma_tag_t parent_dmat; bus_dma_tag_t shared_data_dmat; - bus_dmamap_t shared_data_dmamap; - bus_addr_t shared_data_busaddr; + struct map_node shared_data_map; /* Information saved through suspend/resume cycles */ struct ahd_suspend_state suspend_state; @@ -1296,9 +1327,9 @@ }; /****************************** PCI Structures ********************************/ -#define AHD_PCI_IOADDR0 PCIR_MAPS /* I/O BAR*/ -#define AHD_PCI_MEMADDR (PCIR_MAPS + 4) /* Memory BAR */ -#define AHD_PCI_IOADDR1 (PCIR_MAPS + 12)/* Second I/O BAR */ +#define AHD_PCI_IOADDR0 PCIR_BAR(0) /* I/O BAR*/ +#define AHD_PCI_MEMADDR PCIR_BAR(1) /* Memory BAR */ +#define AHD_PCI_IOADDR1 PCIR_BAR(3) /* Second I/O BAR */ typedef int (ahd_device_setup_t)(struct ahd_softc *); @@ -1338,7 +1369,7 @@ } /***************************** PCI Front End *********************************/ -struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t); +struct ahd_pci_identity *ahd_find_pci_device(aic_dev_softc_t); int ahd_pci_config(struct ahd_softc *, struct ahd_pci_identity *); int ahd_pci_test_register_access(struct ahd_softc *); @@ -1430,6 +1461,8 @@ struct scb *scb); void ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb); +void ahd_timeout(struct scb *scb); +void ahd_recover_commands(struct ahd_softc *ahd); /*************************** Utility Functions ********************************/ struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase); diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic79xx.reg linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx.reg --- linux-2.4.25/drivers/scsi/aic7xxx/aic79xx.reg Wed Jul 30 09:18:49 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx.reg Tue Feb 10 01:47:04 2004 @@ -39,7 +39,7 @@ * * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $" /* * This file is processed by the aic7xxx_asm utility for use in assembling @@ -65,13 +65,6 @@ mvi MODE_PTR, MK_MODE(src, dst); \ } -#define TOGGLE_DFF_MODE \ - if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \ - call toggle_dff_mode_work_around; \ - } else { \ - xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); \ - } - #define RESTORE_MODE(mode) \ if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \ mov mode call set_mode_work_around; \ @@ -3542,10 +3535,34 @@ COMPLETE_DMA_SCB_HEAD { size 2 } - /* Counting semaphore to prevent new select-outs */ + /* + * tail of list of SCBs that have + * completed but need to be uploaded + * to the host prior to being completed. + */ + COMPLETE_DMA_SCB_TAIL { + size 2 + } + /* + * head of list of SCBs that have + * been uploaded to the host, but cannot + * be completed until the QFREEZE is in + * full effect (i.e. no selections pending). + */ + COMPLETE_ON_QFREEZE_HEAD { + size 2 + } + /* + * Counting semaphore to prevent new select-outs + * The queue is frozen so long as the sequencer + * and kernel freeze counts differ. + */ QFREEZE_COUNT { size 2 } + KERNEL_QFREEZE_COUNT { + size 2 + } /* * Mode to restore on legacy idle loop exit. */ @@ -3625,6 +3642,17 @@ size 1 } /* + * Kernel and sequencer offsets into the queue of + * incoming target mode command descriptors. The + * queue is full when the KERNEL_TQINPOS == TQINPOS. + */ + KERNEL_TQINPOS { + size 1 + } + TQINPOS { + size 1 + } + /* * Base address of our shared data with the kernel driver in host * memory. This includes the qoutfifo and target mode * incoming command queue. @@ -3638,17 +3666,6 @@ */ QOUTFIFO_NEXT_ADDR { size 4 - } - /* - * Kernel and sequencer offsets into the queue of - * incoming target mode command descriptors. The - * queue is full when the KERNEL_TQINPOS == TQINPOS. - */ - KERNEL_TQINPOS { - size 1 - } - TQINPOS { - size 1 } ARG_1 { size 1 diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic79xx.seq linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx.seq --- linux-2.4.25/drivers/scsi/aic7xxx/aic79xx.seq Wed Jul 30 09:18:49 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx.seq Tue Feb 10 01:47:04 2004 @@ -40,7 +40,7 @@ * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $" PATCH_ARG_LIST = "struct ahd_softc *ahd" PREFIX = "ahd_" @@ -68,13 +68,47 @@ } SET_MODE(M_SCSI, M_SCSI) test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus; - test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus; + test SEQ_FLAGS2, SELECTOUT_QFROZEN jz check_waiting_list; + /* + * If the kernel has caught up with us, thaw the queue. + */ + mov A, KERNEL_QFREEZE_COUNT; + cmp QFREEZE_COUNT, A jne check_frozen_completions; + mov A, KERNEL_QFREEZE_COUNT[1]; + cmp QFREEZE_COUNT[1], A jne check_frozen_completions; + and SEQ_FLAGS2, ~SELECTOUT_QFROZEN; + jmp check_waiting_list; +check_frozen_completions: + test SSTAT0, SELDO|SELINGO jnz idle_loop_checkbus; +BEGIN_CRITICAL; + /* + * If we have completions stalled waiting for the qfreeze + * to take effect, move them over to the complete_scb list + * now that no selections are pending. + */ + cmp COMPLETE_ON_QFREEZE_HEAD[1],SCB_LIST_NULL je idle_loop_checkbus; + /* + * Find the end of the qfreeze list. The first element has + * to be treated specially. + */ + bmov SCBPTR, COMPLETE_ON_QFREEZE_HEAD, 2; + cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je join_lists; + /* + * Now the normal loop. + */ + bmov SCBPTR, SCB_NEXT_COMPLETE, 2; + cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . - 1; +join_lists: + bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; + bmov COMPLETE_SCB_HEAD, COMPLETE_ON_QFREEZE_HEAD, 2; + mvi COMPLETE_ON_QFREEZE_HEAD[1], SCB_LIST_NULL; + jmp idle_loop_checkbus; +check_waiting_list: cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus; /* * ENSELO is cleared by a SELDO, so we must test for SELDO * one last time. */ -BEGIN_CRITICAL; test SSTAT0, SELDO jnz select_out; END_CRITICAL; call start_selection; @@ -90,6 +124,13 @@ test SSTAT2, NONPACKREQ jz . + 2; call unexpected_nonpkt_phase_find_ctxt; if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { + /* + * On Rev A. hardware, the busy LED is only + * turned on automaically during selections + * and re-selections. Make the LED status + * more useful by forcing it to be on so + * long as one of our data FIFOs is active. + */ and A, FIFO0FREE|FIFO1FREE, DFFSTAT; cmp A, FIFO0FREE|FIFO1FREE jne . + 3; and SBLKCTL, ~DIAGLEDEN|DIAGLEDON; @@ -101,9 +142,9 @@ call idle_loop_cchan; jmp idle_loop; -BEGIN_CRITICAL; idle_loop_gsfifo: SET_MODE(M_SCSI, M_SCSI) +BEGIN_CRITICAL; idle_loop_gsfifo_in_scsi_mode: test LQISTAT2, LQIGSAVAIL jz return; /* @@ -152,25 +193,28 @@ idle_loop_service_fifos: SET_MODE(M_DFF0, M_DFF0) +BEGIN_CRITICAL; test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo; call longjmp; +END_CRITICAL; idle_loop_next_fifo: SET_MODE(M_DFF1, M_DFF1) +BEGIN_CRITICAL; test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp; +END_CRITICAL; return: ret; idle_loop_cchan: SET_MODE(M_CCHAN, M_CCHAN) test QOFF_CTLSTA, HS_MAILBOX_ACT jz hs_mailbox_empty; - mov LOCAL_HS_MAILBOX, HS_MAILBOX; or QOFF_CTLSTA, HS_MAILBOX_ACT; + mov LOCAL_HS_MAILBOX, HS_MAILBOX; hs_mailbox_empty: BEGIN_CRITICAL; test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle; test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog; test CCSCBCTL, CCSCBDONE jz return; -END_CRITICAL; /* FALLTHROUGH */ scbdma_tohost_done: test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone; @@ -180,26 +224,18 @@ * bad SCSI status (currently only for underruns), we * queue the SCB for normal completion. Otherwise, we * wait until any select-out activity has halted, and - * then notify the host so that the transaction can be - * dealt with. + * then queue the completion. */ - test SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host; and CCSCBCTL, ~(CCARREN|CCSCBEN); bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; + cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . + 2; + mvi COMPLETE_DMA_SCB_TAIL[1], SCB_LIST_NULL; + test SCB_SCSI_STATUS, 0xff jz scbdma_queue_completion; + bmov SCB_NEXT_COMPLETE, COMPLETE_ON_QFREEZE_HEAD, 2; + bmov COMPLETE_ON_QFREEZE_HEAD, SCBPTR, 2 ret; +scbdma_queue_completion: bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; -scbdma_notify_host: - SET_MODE(M_SCSI, M_SCSI) - test SCSISEQ0, ENSELO jnz return; - test SSTAT0, (SELDO|SELINGO) jnz return; - SET_MODE(M_CCHAN, M_CCHAN) - /* - * Remove SCB and notify host. - */ - and CCSCBCTL, ~(CCARREN|CCSCBEN); - bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; - SET_SEQINTCODE(BAD_SCB_STATUS) - ret; fill_qoutfifo_dmadone: and CCSCBCTL, ~(CCARREN|CCSCBEN); call qoutfifo_updated; @@ -208,6 +244,7 @@ test QOFF_CTLSTA, SDSCB_ROLLOVR jz return; bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4; xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret; +END_CRITICAL; qoutfifo_updated: /* @@ -276,7 +313,7 @@ * 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; @@ -324,14 +361,15 @@ * Keep track of the SCBs we are dmaing just * in case the DMA fails or is aborted. */ - mov A, QOUTFIFO_ENTRY_VALID_TAG; bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2; mvi CCSCBCTL, CCSCBRESET; bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4; bmov SCBPTR, COMPLETE_SCB_HEAD, 2; fill_qoutfifo_loop: - mov CCSCBRAM, SCBPTR; - or CCSCBRAM, A, SCBPTR[1]; + bmov CCSCBRAM, SCBPTR, 2; + mov CCSCBRAM, SCB_SGPTR[0]; + bmov CCSCBRAM, ALLZEROS, 4; + mov CCSCBRAM, QOUTFIFO_ENTRY_VALID_TAG; mov NONE, SDSCB_QOFF; inc INT_COALESCING_CMDCOUNT; add CMDS_PENDING, -1; @@ -354,7 +392,6 @@ bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2; bmov SCBHADDR, SCB_BUSADDR, 4; mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb; -END_CRITICAL; /* * Either post or fetch an SCB from host memory. The caller @@ -371,9 +408,19 @@ mvi SCBHCNT, SCB_TRANSFER_SIZE; mov CCSCBCTL, SINDEX ret; -BEGIN_CRITICAL; setjmp: - bmov LONGJMP_ADDR, STACK, 2 ret; + /* + * At least on the A, a return in the same + * instruction as the bmov results in a return + * to the caller, not to the new address at the + * top of the stack. Since we want the latter + * (we use setjmp to register a handler from an + * interrupt context but not invoke that handler + * until we return to our idle loop), use a + * separate ret instruction. + */ + bmov LONGJMP_ADDR, STACK, 2; + ret; setjmp_inline: bmov LONGJMP_ADDR, STACK, 2; longjmp: @@ -392,11 +439,6 @@ mvi SEQINTCTL, INTVEC1DSL; mov MODE_PTR, SINDEX; clr SEQINTCTL ret; - -toggle_dff_mode_work_around: - mvi SEQINTCTL, INTVEC1DSL; - xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); - clr SEQINTCTL ret; } @@ -490,14 +532,30 @@ SET_SRC_MODE M_SCSI; SET_DST_MODE M_SCSI; select_in: + if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { + /* + * On Rev A. hardware, the busy LED is only + * turned on automaically during selections + * and re-selections. Make the LED status + * more useful by forcing it to be on from + * the point of selection until our idle + * loop determines that neither of our FIFOs + * are busy. This handles the non-packetized + * case nicely as we will not return to the + * idle loop until the busfree at the end of + * each transaction. + */ + or SBLKCTL, DIAGLEDEN|DIAGLEDON; + } if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { /* - * This exposes a window whereby a - * busfree just after a selection will - * be missed, but there is no other safe - * way to enable busfree detection if - * the busfreerev function is broken. + * Test to ensure that the bus has not + * already gone free prior to clearing + * any stale busfree status. This avoids + * a window whereby a busfree just after + * a selection could be missed. */ + test SCSISIGI, BSYI jz . + 2; mvi CLRSINT1,CLRBUSFREE; or SIMODE1, ENBUSFREE; } @@ -527,6 +585,21 @@ SET_DST_MODE M_SCSI; select_out: BEGIN_CRITICAL; + if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { + /* + * On Rev A. hardware, the busy LED is only + * turned on automaically during selections + * and re-selections. Make the LED status + * more useful by forcing it to be on from + * the point of re-selection until our idle + * loop determines that neither of our FIFOs + * are busy. This handles the non-packetized + * case nicely as we will not return to the + * idle loop until the busfree at the end of + * each transaction. + */ + or SBLKCTL, DIAGLEDEN|DIAGLEDON; + } /* Clear out all SCBs that have been successfully sent. */ if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) { /* @@ -582,9 +655,6 @@ bmov CURRSCB, SCBPTR, 2; curscb_ww_done: } else { - /* - * Untested - Verify with Rev B. - */ bmov SCBPTR, CURRSCB, 2; } @@ -651,12 +721,13 @@ and SCSISEQ0, ~ENSELO; if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { /* - * This exposes a window whereby a - * busfree just after a selection will - * be missed, but there is no other safe - * way to enable busfree detection if - * the busfreerev function is broken. + * Test to ensure that the bus has not + * already gone free prior to clearing + * any stale busfree status. This avoids + * a window whereby a busfree just after + * a selection could be missed. */ + test SCSISIGI, BSYI jz . + 2; mvi CLRSINT1,CLRBUSFREE; or SIMODE1, ENBUSFREE; } @@ -729,13 +800,38 @@ 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; @@ -976,15 +1072,9 @@ /* * We received a "command complete" message. Put the SCB on the complete * queue and trigger a completion interrupt via the idle loop. Before doing - * so, check to see if there - * is a residual or the status byte is something other than STATUS_GOOD (0). - * In either of these conditions, we upload the SCB back to the host so it can - * process this information. In the case of a non zero status byte, we - * additionally interrupt the kernel driver synchronously, allowing it to - * decide if sense should be retrieved. If the kernel driver wishes to request - * sense, it will fill the kernel SCB with a request sense command, requeue - * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting - * RETURN_1 to SEND_SENSE. + * so, check to see if there is a residual or the status byte is something + * other than STATUS_GOOD (0). In either of these conditions, we upload the + * SCB back to the host so it can process this information. */ mesgin_complete: @@ -1029,6 +1119,7 @@ call queue_scb_completion; jmp await_busfree; +BEGIN_CRITICAL; freeze_queue: /* Cancel any pending select-out. */ test SSTAT0, SELDO|SELINGO jnz . + 2; @@ -1039,6 +1130,7 @@ adc QFREEZE_COUNT[1], A; or SEQ_FLAGS2, SELECTOUT_QFROZEN; mov A, ACCUM_SAVE ret; +END_CRITICAL; /* * Complete the current FIFO's SCB if data for this same @@ -1061,8 +1153,10 @@ test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */ test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb; complete: +BEGIN_CRITICAL; bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; +END_CRITICAL; bad_status: cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb; call freeze_queue; @@ -1073,9 +1167,18 @@ * it on the host. */ bmov SCB_TAG, SCBPTR, 2; - bmov SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2; +BEGIN_CRITICAL; + or SCB_SGPTR, SG_STATUS_VALID; + mvi SCB_NEXT_COMPLETE[1], SCB_LIST_NULL; + cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne add_dma_scb_tail; bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2; - or SCB_SGPTR, SG_STATUS_VALID ret; + bmov COMPLETE_DMA_SCB_TAIL, SCBPTR, 2 ret; +add_dma_scb_tail: + bmov REG0, SCBPTR, 2; + bmov SCBPTR, COMPLETE_DMA_SCB_TAIL, 2; + bmov SCB_NEXT_COMPLETE, REG0, 2; + bmov COMPLETE_DMA_SCB_TAIL, REG0, 2 ret; +END_CRITICAL; /* * Is it a disconnect message? Set a flag in the SCB to remind us @@ -1122,8 +1225,18 @@ await_busfree_clrchn: mvi DFFSXFRCTL, CLRCHN; await_busfree_not_m_dff: - call clear_target_state; + /* clear target specific flags */ + mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT; test SSTAT1,REQINIT|BUSFREE jz .; + /* + * We only set BUSFREE status once either a new + * phase has been detected or we are really + * BUSFREE. This allows the driver to know + * that we are active on the bus even though + * no identified transaction exists should a + * timeout occur while awaiting busfree. + */ + mvi LASTPHASE, P_BUSFREE; test SSTAT1, BUSFREE jnz idle_loop; SET_SEQINTCODE(MISSED_BUSFREE) @@ -1178,11 +1291,6 @@ call allocate_fifo; jmp mesgin_done; -clear_target_state: - mvi LASTPHASE, P_BUSFREE; - /* clear target specific flags */ - mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret; - phase_lock: if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) { /* @@ -1274,6 +1382,47 @@ test CCSGCTL, CCSGENACK jnz return; /* + * Should the other FIFO get the S/G cache first? If + * both FIFOs have been allocated since we last checked + * any FIFO, it is important that we service a FIFO + * that is not actively on the bus first. This guarantees + * that a FIFO will be freed to handle snapshot requests for + * any FIFO that is still on the bus. Chips with RTI do not + * perform snapshots, so don't bother with this test there. + */ + if ((ahd->features & AHD_RTI) == 0) { + /* + * If we're not still receiving SCSI data, + * it is safe to allocate the S/G cache to + * this FIFO. + */ + test DFCNTRL, SCSIEN jz idle_sgfetch_start; + + /* + * Switch to the other FIFO. Non-RTI chips + * also have the "set mode" bug, so we must + * disable interrupts during the switch. + */ + mvi SEQINTCTL, INTVEC1DSL; + xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); + + /* + * If the other FIFO needs loading, then it + * must not have claimed the S/G cache yet + * (SG_CACHE_AVAIL would have been cleared in + * the orginal FIFO mode and we test this above). + * Return to the idle loop so we can process the + * FIFO not currently on the bus first. + */ + test SG_STATE, LOADING_NEEDED jz idle_sgfetch_okay; + clr SEQINTCTL ret; +idle_sgfetch_okay: + xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); + clr SEQINTCTL; + } + +idle_sgfetch_start: + /* * We fetch a "cacheline aligned" and sized amount of data * so we don't end up referencing a non-existant page. * Cacheline aligned is in quotes because the kernel will @@ -1284,7 +1433,7 @@ mvi SGHCNT, SG_PREFETCH_CNT; if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) { /* - * Need two instruction between "touches" of SGHADDR. + * Need two instructions between "touches" of SGHADDR. */ nop; } @@ -1634,7 +1783,7 @@ * savepointer in the current FIFO. We do this so that * a pending CTXTDONE or SAVEPTR is visible in the active * FIFO. This status is the only way we can detect if we - * have lost the race (e.g. host paused us) and our attepts + * have lost the race (e.g. host paused us) and our attempts * to disable the channel occurred after all REQs were * already seen and acked (REQINIT never comes true). */ @@ -1643,7 +1792,7 @@ test DFCNTRL, DIRECTION jz interrupt_return; and DFCNTRL, ~SCSIEN; snapshot_wait_data_valid: - test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid; + test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return; test SSTAT1, REQINIT jz snapshot_wait_data_valid; snapshot_data_valid: or DFCNTRL, SCSIEN; @@ -1810,7 +1959,6 @@ dec SCB_FIFO_USE_COUNT; test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; mvi DFFSXFRCTL, CLRCHN ret; -END_CRITICAL; /* * LAST_SEG_DONE status has been seen in the current FIFO. @@ -1819,7 +1967,6 @@ * Check for overrun and see if we can complete this command. */ pkt_last_seg_done: -BEGIN_CRITICAL; /* * Mark transfer as completed. */ @@ -1959,12 +2106,14 @@ test SSTAT0, SELDO jnz return; mvi SCBPTR[1], SCB_LIST_NULL; unexpected_nonpkt_phase: - test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) jnz . + 3; + test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) + jnz unexpected_nonpkt_mode_cleared; SET_SRC_MODE M_DFF0; SET_DST_MODE M_DFF0; or LONGJMP_ADDR[1], INVALID_ADDR; dec SCB_FIFO_USE_COUNT; mvi DFFSXFRCTL, CLRCHN; +unexpected_nonpkt_mode_cleared: mvi CLRSINT2, CLRNONPACKREQ; test SCSIPHASE, ~(MSG_IN_PHASE|MSG_OUT_PHASE) jnz illegal_phase; SET_SEQINTCODE(ENTERING_NONPACK) diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_core.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_core.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_core.c Wed Jul 30 09:18:49 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_core.c Tue Feb 10 01:47:04 2004 @@ -37,9 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#197 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#238 $ */ #ifdef __linux__ @@ -47,6 +45,8 @@ #include "aic79xx_inline.h" #include "aicasm/aicasm_insformat.h" #else +#include +__FBSDID("$FreeBSD$"); #include #include #include @@ -54,6 +54,7 @@ /******************************** Globals *************************************/ struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq); +uint32_t ahd_attach_to_HostRAID_controllers = 1; /***************************** Lookup Tables **********************************/ char *ahd_chip_names[] = @@ -224,6 +225,14 @@ static void ahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts); static int ahd_probe_stack_size(struct ahd_softc *ahd); +static void ahd_other_scb_timeout(struct ahd_softc *ahd, + struct scb *scb, + struct scb *other_scb); +static int ahd_scb_active_in_fifo(struct ahd_softc *ahd, + struct scb *scb); +static void ahd_run_data_fifo(struct ahd_softc *ahd, + struct scb *scb); + #ifdef AHD_TARGET_MODE static void ahd_queue_lstate_event(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate, @@ -328,10 +337,7 @@ /* Always allow reselection */ ahd_outb(ahd, SCSISEQ1, ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP)); - /* Ensure that no DMA operations are in progress */ ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); - ahd_outb(ahd, SCBHCNT, 0); - ahd_outb(ahd, CCSCBCTL, CCSCBRESET); ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET); ahd_unpause(ahd); } @@ -371,31 +377,130 @@ u_int next_scbid; saved_modes = ahd_save_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); + + /* + * Flush the good status FIFO for completed packetized commands. + */ + ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); saved_scbptr = ahd_get_scbptr(ahd); + while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) { + u_int fifo_mode; + u_int i; + + scbid = ahd_inw(ahd, GSFIFO); + scb = ahd_lookup_scb(ahd, scbid); + if (scb == NULL) { + printf("%s: Warning - GSFIFO SCB %d invalid\n", + ahd_name(ahd), scbid); + continue; + } + /* + * Determine if this transaction is still active in + * any FIFO. If it is, we must flush that FIFO to + * the host before completing the command. + */ + fifo_mode = 0; +rescan_fifos: + for (i = 0; i < 2; i++) { + /* Toggle to the other mode. */ + fifo_mode ^= 1; + ahd_set_modes(ahd, fifo_mode, fifo_mode); + + if (ahd_scb_active_in_fifo(ahd, scb) == 0) + continue; + + ahd_run_data_fifo(ahd, scb); + + /* + * Running this FIFO may cause a CFG4DATA for + * this same transaction to assert in the other + * FIFO or a new snapshot SAVEPTRS interrupt + * in this FIFO. Even running a FIFO may not + * clear the transaction if we are still waiting + * for data to drain to the host. We must loop + * until the transaction is not active in either + * FIFO just to be sure. Reset our loop counter + * so we will visit both FIFOs again before + * declaring this transaction finished. We + * also delay a bit so that status has a chance + * to change before we look at this FIFO again. + */ + aic_delay(200); + goto rescan_fifos; + } + ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); + ahd_set_scbptr(ahd, scbid); + if ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_LIST_NULL) == 0 + && ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_FULL_RESID) != 0 + || (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR) + & SG_LIST_NULL) != 0)) { + u_int comp_head; + + /* + * The transfer completed with a residual. + * Place this SCB on the complete DMA list + * so that we update our in-core copy of the + * SCB before completing the command. + */ + ahd_outb(ahd, SCB_SCSI_STATUS, 0); + ahd_outb(ahd, SCB_SGPTR, + ahd_inb_scbram(ahd, SCB_SGPTR) + | SG_STATUS_VALID); + ahd_outw(ahd, SCB_TAG, scbid); + ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL); + comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD); + if (SCBID_IS_NULL(comp_head)) { + ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid); + } else { + u_int tail; + + tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL); + ahd_set_scbptr(ahd, tail); + ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid); + ahd_set_scbptr(ahd, scbid); + } + } else + ahd_complete_scb(ahd, scb); + } + ahd_set_scbptr(ahd, saved_scbptr); + + /* + * Setup for command channel portion of flush. + */ + ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); /* * Wait for any inprogress DMA to complete and clear DMA state * if this if for an SCB in the qinfifo. */ - while ((ccscbctl = ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN)) != 0) { + while (((ccscbctl = ahd_inb(ahd, CCSCBCTL)) & (CCARREN|CCSCBEN)) != 0) { if ((ccscbctl & (CCSCBDIR|CCARREN)) == (CCSCBDIR|CCARREN)) { if ((ccscbctl & ARRDONE) != 0) break; } else if ((ccscbctl & CCSCBDONE) != 0) break; - ahd_delay(200); + aic_delay(200); } - if ((ccscbctl & CCSCBDIR) != 0) + /* + * We leave the sequencer to cleanup in the case of DMA's to + * update the qoutfifo. In all other cases (DMA's to the + * chip or a push of an SCB from the COMPLETE_DMA_SCB list), + * we disable the DMA engine so that the sequencer will not + * attempt to handle the DMA completion. + */ + if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0) ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN)); /* - * Complete any SCBs that just finished being - * DMA'ed into the qoutfifo. + * Complete any SCBs that just finished + * being DMA'ed into the qoutfifo. */ ahd_run_qoutfifo(ahd); + saved_scbptr = ahd_get_scbptr(ahd); /* * Manually update/complete any completed SCBs that are waiting to be * DMA'ed back up to the host. @@ -421,15 +526,16 @@ scbid = next_scbid; } ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL); - scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD); + scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD); while (!SCBID_IS_NULL(scbid)) { ahd_set_scbptr(ahd, scbid); next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: Warning - Complete SCB %d invalid\n", + printf("%s: Warning - Complete Qfrz SCB %d invalid\n", ahd_name(ahd), scbid); continue; } @@ -437,35 +543,304 @@ ahd_complete_scb(ahd, scb); scbid = next_scbid; } - ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL); - ahd_set_scbptr(ahd, saved_scbptr); + ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL); - /* - * Flush the good status FIFO for compelted packetized commands. - */ - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) { - scbid = (ahd_inb(ahd, GSFIFO+1) << 8) - | ahd_inb(ahd, GSFIFO); + scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD); + while (!SCBID_IS_NULL(scbid)) { + + ahd_set_scbptr(ahd, scbid); + next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: Warning - GSFIFO SCB %d invalid\n", + printf("%s: Warning - Complete SCB %d invalid\n", ahd_name(ahd), scbid); continue; } + ahd_complete_scb(ahd, scb); + 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) +{ + + /* + * The FIFO is only active for our transaction if + * the SCBPTR matches the SCB's ID and the firmware + * has installed a handler for the FIFO or we have + * a pending SAVEPTRS or CFG4DATA interrupt. + */ + if (ahd_get_scbptr(ahd) != SCB_GET_TAG(scb) + || ((ahd_inb(ahd, LONGJMP_ADDR+1) & INVALID_ADDR) != 0 + && (ahd_inb(ahd, SEQINTSRC) & (CFG4DATA|SAVEPTRS)) == 0)) + return (0); + + return (1); +} + +/* + * Run a data fifo to completion for a transaction we know + * has completed across the SCSI bus (good status has been + * received). We are already set to the correct FIFO mode + * on entry to this routine. + * + * This function attempts to operate exactly as the firmware + * would when running this FIFO. Care must be taken to update + * this routine any time the firmware's FIFO algorithm is + * changed. + */ +static void +ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) +{ + u_int seqintsrc; + + seqintsrc = ahd_inb(ahd, SEQINTSRC); + if ((seqintsrc & CFG4DATA) != 0) { + uint32_t datacnt; + uint32_t sgptr; + + /* + * Clear full residual flag. + */ + sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID; + ahd_outb(ahd, SCB_SGPTR, sgptr); + + /* + * Load datacnt and address. + */ + datacnt = ahd_inl_scbram(ahd, SCB_DATACNT); + if ((datacnt & AHD_DMA_LAST_SEG) != 0) { + sgptr |= LAST_SEG; + ahd_outb(ahd, SG_STATE, 0); + } else + ahd_outb(ahd, SG_STATE, LOADING_NEEDED); + ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR)); + ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK); + ahd_outb(ahd, SG_CACHE_PRE, sgptr); + ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN); + + /* + * Initialize Residual Fields. + */ + ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24); + ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK); + + /* + * Mark the SCB as having a FIFO in use. + */ + ahd_outb(ahd, SCB_FIFO_USE_COUNT, + ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1); + + /* + * Install a "fake" handler for this FIFO. + */ + ahd_outw(ahd, LONGJMP_ADDR, 0); + + /* + * Notify the hardware that we have satisfied + * this sequencer interrupt. + */ + ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA); + } else if ((seqintsrc & SAVEPTRS) != 0) { + uint32_t sgptr; + uint32_t resid; + + if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) { + /* + * Snapshot Save Pointers. All that + * is necessary to clear the snapshot + * is a CLRCHN. + */ + goto clrchn; + } + + /* + * Disable S/G fetch so the DMA engine + * is available to future users. + */ + if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) + ahd_outb(ahd, CCSGCTL, 0); + ahd_outb(ahd, SG_STATE, 0); + + /* + * Flush the data FIFO. Strickly only + * necessary for Rev A parts. + */ + ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH); + + /* + * Calculate residual. + */ + sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); + resid = ahd_inl(ahd, SHCNT); + resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24; + ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid); + if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) { + /* + * Must back up to the correct S/G element. + * Typically this just means resetting our + * low byte to the offset in the SG_CACHE, + * but if we wrapped, we have to correct + * the other bytes of the sgptr too. + */ + if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0 + && (sgptr & 0x80) == 0) + sgptr -= 0x100; + sgptr &= ~0xFF; + sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW) + & SG_ADDR_MASK; + ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr); + ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0); + } else if ((resid & AHD_SG_LEN_MASK) == 0) { + ahd_outb(ahd, SCB_RESIDUAL_SGPTR, + sgptr | SG_LIST_NULL); + } + /* + * Save Pointers. + */ + ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR)); + ahd_outl(ahd, SCB_DATACNT, resid); + ahd_outl(ahd, SCB_SGPTR, sgptr); + ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS); + ahd_outb(ahd, SEQIMODE, + ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS); + /* + * If the data is to the SCSI bus, we are + * done, otherwise wait for FIFOEMP. + */ + if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0) + goto clrchn; + } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) { + uint32_t sgptr; + uint64_t data_addr; + uint32_t data_len; + u_int dfcntrl; + + /* + * Disable S/G fetch so the DMA engine + * is available to future users. We won't + * be using the DMA engine to load segments. + */ + if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) { + ahd_outb(ahd, CCSGCTL, 0); + ahd_outb(ahd, SG_STATE, LOADING_NEEDED); + } + + /* + * Wait for the DMA engine to notice that the + * host transfer is enabled and that there is + * space in the S/G FIFO for new segments before + * loading more segments. + */ + if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0 + && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) { + + /* + * Determine the offset of the next S/G + * element to load. + */ + sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); + sgptr &= SG_PTR_MASK; + if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { + struct ahd_dma64_seg *sg; + + sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); + data_addr = sg->addr; + data_len = sg->len; + sgptr += sizeof(*sg); + } else { + struct ahd_dma_seg *sg; + + sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); + data_addr = sg->len & AHD_SG_HIGH_ADDR_MASK; + data_addr <<= 8; + data_addr |= sg->addr; + data_len = sg->len; + sgptr += sizeof(*sg); + } + + /* + * Update residual information. + */ + ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, data_len >> 24); + ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr); + + /* + * Load the S/G. + */ + if (data_len & AHD_DMA_LAST_SEG) { + sgptr |= LAST_SEG; + ahd_outb(ahd, SG_STATE, 0); + } + ahd_outq(ahd, HADDR, data_addr); + ahd_outl(ahd, HCNT, data_len & AHD_SG_LEN_MASK); + ahd_outb(ahd, SG_CACHE_PRE, sgptr & 0xFF); + + /* + * Advertise the segment to the hardware. + */ + dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN; + if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) { + /* + * Use SCSIENWRDIS so that SCSIEN + * is never modified by this + * operation. + */ + dfcntrl |= SCSIENWRDIS; + } + ahd_outb(ahd, DFCNTRL, dfcntrl); + } + } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) { + + /* + * Transfer completed to the end of SG list + * and has flushed to the host. + */ + ahd_outb(ahd, SCB_SGPTR, + ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL); + goto clrchn; + } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) { +clrchn: + /* + * Clear any handler for this FIFO, decrement + * the FIFO use count for the SCB, and release + * the FIFO. + */ + ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR); + ahd_outb(ahd, SCB_FIFO_USE_COUNT, + ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1); + ahd_outb(ahd, DFFSXFRCTL, CLRCHN); + } +} + +/* + * Look for entries in the QoutFIFO that have completed. + * The valid_tag completion field indicates the validity + * of the entry - the valid value toggles each time through + * the queue. We use the sg_status field in the completion + * entry to avoid referencing the hscb if the completion + * occurred with no errors and no residual. sg_status is + * a copy of the first byte (little endian) of the sgptr + * hscb field. + */ void ahd_run_qoutfifo(struct ahd_softc *ahd) { + struct ahd_completion *completion; struct scb *scb; u_int scb_index; @@ -473,11 +848,13 @@ panic("ahd_run_qoutfifo recursion"); ahd->flags |= AHD_RUNNING_QOUTFIFO; ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD); - while ((ahd->qoutfifo[ahd->qoutfifonext] - & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) { + for (;;) { + completion = &ahd->qoutfifo[ahd->qoutfifonext]; + + if (completion->valid_tag != ahd->qoutfifonext_valid_tag) + break; - scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext] - & ~QOUTFIFO_ENTRY_VALID_LE); + scb_index = aic_le16toh(completion->tag); scb = ahd_lookup_scb(ahd, scb_index); if (scb == NULL) { printf("%s: WARNING no command for scb %d " @@ -485,12 +862,15 @@ ahd_name(ahd), scb_index, ahd->qoutfifonext); ahd_dump_card_state(ahd); - } else - ahd_complete_scb(ahd, scb); + } else if ((completion->sg_status & SG_STATUS_VALID) != 0) { + ahd_handle_scb_status(ahd, scb); + } else { + ahd_done(ahd, scb); + } ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1); if (ahd->qoutfifonext == 0) - ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID_LE; + ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID; } ahd->flags &= ~AHD_RUNNING_QOUTFIFO; } @@ -556,26 +936,6 @@ ahd_name(ahd), seqintcode); #endif switch (seqintcode) { - case BAD_SCB_STATUS: - { - struct scb *scb; - u_int scbid; - int cmds_pending; - - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - if (scb != NULL) { - ahd_complete_scb(ahd, scb); - } else { - printf("%s: WARNING no command for scb %d " - "(bad status)\n", ahd_name(ahd), scbid); - ahd_dump_card_state(ahd); - } - cmds_pending = ahd_inw(ahd, CMDS_PENDING); - if (cmds_pending > 0) - ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1); - break; - } case ENTERING_NONPACK: { struct scb *scb; @@ -589,7 +949,7 @@ /* * Somehow need to know if this * is from a selection or reselection. - * From that, we can termine target + * From that, we can determine target * ID so we at least have an I_T nexus. */ } else { @@ -740,11 +1100,11 @@ ahd_outb(ahd, SAVED_LUN, 0); ahd_outb(ahd, SEQ_FLAGS, 0); ahd_assert_atn(ahd); - scb->flags &= ~(SCB_PACKETIZED); + scb->flags &= ~SCB_PACKETIZED; scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT; ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_REQUEUE_REQ); + aic_freeze_scb(scb); /* * Allow the sequencer to continue with @@ -796,7 +1156,8 @@ * attempt to complete this bogus SCB. */ ahd_outb(ahd, SCB_CONTROL, - ahd_inb(ahd, SCB_CONTROL) & ~STATUS_RCVD); + ahd_inb_scbram(ahd, SCB_CONTROL) + & ~STATUS_RCVD); } break; } @@ -991,7 +1352,7 @@ "NumSGs = %d.\n", ahd_inb(ahd, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't", - ahd_get_transfer_length(scb), scb->sg_count); + aic_get_transfer_length(scb), scb->sg_count); ahd_dump_sglist(scb); } #endif @@ -1001,8 +1362,8 @@ * target does a command complete. */ ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); + aic_freeze_scb(scb); break; } case MKMSG_FAILED: @@ -1029,7 +1390,7 @@ ROLE_INITIATOR, /*status*/0, SEARCH_REMOVE); ahd_outb(ahd, SCB_CONTROL, - ahd_inb(ahd, SCB_CONTROL) & ~MK_MESSAGE); + ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE); break; } case TASKMGMT_FUNC_COMPLETE: @@ -1263,7 +1624,7 @@ */ ahd_scb_devinfo(ahd, &devinfo, scb); ahd_force_renegotiation(ahd, &devinfo); - ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT); + aic_set_transaction_status(scb, CAM_SEL_TIMEOUT); ahd_freeze_devq(ahd, scb); } ahd_outb(ahd, CLRINT, CLRSCSIINT); @@ -1338,7 +1699,15 @@ clear_fifo = 0; packetized = (lqostat1 & LQOBUSFREE) != 0; if (!packetized - && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) + && ahd_inb(ahd, LASTPHASE) == P_BUSFREE + && ((ahd_inb(ahd, SSTAT0) & SELDO) == 0 + || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0)) + /* + * Assume packetized if we are not + * on the bus in a non-packetized + * capacity and any pending selection + * was a packetized selection. + */ packetized = 1; break; } @@ -1710,8 +2079,8 @@ } scb->crc_retry_count++; } else { - ahd_set_transaction_status(scb, CAM_UNCOR_PARITY); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_UNCOR_PARITY); + aic_freeze_scb(scb); ahd_freeze_devq(ahd, scb); } /* Return unpausing the sequencer. */ @@ -1853,7 +2222,7 @@ && ahd_match_scb(ahd, scb, target, 'A', CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_INITIATOR)) - ahd_set_transaction_status(scb, CAM_REQ_CMP); + aic_set_transaction_status(scb, CAM_REQ_CMP); #endif ahd_handle_devreset(ahd, &devinfo, CAM_LUN_WILDCARD, CAM_BDR_SENT, "Bus Device Reset", @@ -1944,8 +2313,8 @@ && ((ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0)) { ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_REQUEUE_REQ); + aic_freeze_scb(scb); if ((ahd->msg_flags & MSG_FLAG_IU_REQ_CHANGED) != 0) { ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), SCB_GET_CHANNEL(ahd, scb), @@ -1989,8 +2358,7 @@ "PRGMCNT == 0x%x\n", ahd_lookup_phase_entry(lastphase)->phasemsg, aborted, - ahd_inb(ahd, PRGMCNT) - | (ahd_inb(ahd, PRGMCNT+1) << 8)); + ahd_inw(ahd, PRGMCNT)); ahd_dump_card_state(ahd); } /* Always restart the sequencer. */ @@ -2034,7 +2402,7 @@ printf("No SCB found during protocol violation\n"); goto proto_violation_reset; } else { - ahd_set_transaction_status(scb, CAM_SEQUENCE_FAIL); + aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL); if ((seq_flags & NO_CDB_SENT) != 0) { ahd_print_path(ahd, scb); printf("No or incomplete CDB sent to device.\n"); @@ -2153,8 +2521,7 @@ u_int i; ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - seqaddr = ahd_inb(ahd, CURADDR) - | (ahd_inb(ahd, CURADDR+1) << 8); + seqaddr = ahd_inw(ahd, CURADDR); cs = ahd->critical_sections; for (i = 0; i < ahd->num_critical_sections; i++, cs++) { @@ -2198,8 +2565,14 @@ 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; } @@ -2207,9 +2580,8 @@ ahd_outb(ahd, CLRINT, CLRSCSIINT); ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); ahd_outb(ahd, HCNTRL, ahd->unpause); - do { - ahd_delay(200); - } while (!ahd_is_paused(ahd)); + while (!ahd_is_paused(ahd)) + aic_delay(200); ahd_update_modes(ahd); } if (stepping) { @@ -2285,10 +2657,10 @@ for (i = 0; i < sizeof(hscb->shared_data.idata.cdb); i++) printf("%#02x", hscb->shared_data.idata.cdb[i]); printf(" dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n", - (uint32_t)((ahd_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF), - (uint32_t)(ahd_le64toh(hscb->dataptr) & 0xFFFFFFFF), - ahd_le32toh(hscb->datacnt), - ahd_le32toh(hscb->sgptr), + (uint32_t)((aic_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF), + (uint32_t)(aic_le64toh(hscb->dataptr) & 0xFFFFFFFF), + aic_le32toh(hscb->datacnt), + aic_le32toh(hscb->sgptr), SCB_GET_TAG(scb)); ahd_dump_sglist(scb); } @@ -2307,8 +2679,8 @@ uint64_t addr; uint32_t len; - addr = ahd_le64toh(sg_list[i].addr); - len = ahd_le32toh(sg_list[i].len); + addr = aic_le64toh(sg_list[i].addr); + len = aic_le32toh(sg_list[i].len); printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", i, (uint32_t)((addr >> 32) & 0xFFFFFFFF), @@ -2324,11 +2696,11 @@ for (i = 0; i < scb->sg_count; i++) { uint32_t len; - len = ahd_le32toh(sg_list[i].len); + len = aic_le32toh(sg_list[i].len); printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", i, - (len >> 24) & SG_HIGH_ADDR_BITS, - ahd_le32toh(sg_list[i].addr), + (len & AHD_SG_HIGH_ADDR_MASK) >> 24, + aic_le32toh(sg_list[i].addr), len & AHD_SG_LEN_MASK, len & AHD_DMA_LAST_SEG ? " Last" : ""); } @@ -2870,14 +3242,25 @@ iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK; if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0 - && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0) { + && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0 + && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) { /* * Slow down our CRC interval to be - * compatible with devices that can't - * handle a CRC at full speed. + * compatible with non-packetized + * U160 devices that can't handle a + * CRC at full speed. */ con_opts |= ENSLOWCRC; } + + if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) { + /* + * On H2A4, revert to a slower slewrate + * on non-paced transfers. + */ + iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= + ~AHD_SLEWRATE_MASK; + } } ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW); @@ -2915,7 +3298,7 @@ { 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; @@ -2973,17 +3356,14 @@ 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; @@ -3198,7 +3578,7 @@ 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); } @@ -3737,8 +4117,13 @@ 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); @@ -4346,7 +4731,7 @@ ahd_outb(ahd, SCB_CONTROL, ahd_inb_scbram(ahd, SCB_CONTROL) & mask); scb->hscb->control &= mask; - ahd_set_transaction_tag(scb, /*enabled*/FALSE, + aic_set_transaction_tag(scb, /*enabled*/FALSE, /*type*/MSG_SIMPLE_TASK); ahd_outb(ahd, MSG_OUT, MSG_IDENTIFYFLAG); ahd_assert_atn(ahd); @@ -4404,7 +4789,7 @@ * Perhaps add datadir to some spare bits in the hscb? */ if ((ahd_inb(ahd, SEQ_FLAGS) & DPHASE) == 0 - || ahd_get_transfer_dir(scb) != CAM_DIR_IN) { + || aic_get_transfer_dir(scb) != CAM_DIR_IN) { /* * Ignore the message if we haven't * seen an appropriate data phase yet. @@ -4421,7 +4806,8 @@ 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 @@ -4458,18 +4844,18 @@ * to load so we must go back one. */ sg--; - sglen = ahd_le32toh(sg->len) & AHD_SG_LEN_MASK; + sglen = aic_le32toh(sg->len) & AHD_SG_LEN_MASK; if (sg != scb->sg_list && sglen < (data_cnt & AHD_SG_LEN_MASK)) { sg--; - sglen = ahd_le32toh(sg->len); + sglen = aic_le32toh(sg->len); /* * Preserve High Address and SG_LIST * bits while setting the count to 1. */ data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK)); - data_addr = ahd_le64toh(sg->addr) + data_addr = aic_le64toh(sg->addr) + (sglen & AHD_SG_LEN_MASK) - 1; @@ -4491,18 +4877,18 @@ * to load so we must go back one. */ sg--; - sglen = ahd_le32toh(sg->len) & AHD_SG_LEN_MASK; + sglen = aic_le32toh(sg->len) & AHD_SG_LEN_MASK; if (sg != scb->sg_list && sglen < (data_cnt & AHD_SG_LEN_MASK)) { sg--; - sglen = ahd_le32toh(sg->len); + sglen = aic_le32toh(sg->len); /* * Preserve High Address and SG_LIST * bits while setting the count to 1. */ data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK)); - data_addr = ahd_le32toh(sg->addr) + data_addr = aic_le32toh(sg->addr) + (sglen & AHD_SG_LEN_MASK) - 1; @@ -4522,7 +4908,8 @@ * 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); @@ -4562,9 +4949,8 @@ */ ahd_outb(ahd, DFFSXFRCTL, CLRCHN); wait = 1000; - do { - ahd_delay(100); - } while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE)); + while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE)) + aic_delay(100); if (wait == 0) { ahd_print_path(ahd, scb); printf("ahd_reinitialize_dataptrs: Forcing FIFO free.\n"); @@ -4580,10 +4966,7 @@ * Determine initial values for data_addr and data_cnt * for resuming the data phase. */ - sgptr = (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8) - | ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR); + sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); sgptr &= SG_PTR_MASK; resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16) @@ -4598,13 +4981,10 @@ /* The residual sg_ptr always points to the next sg */ sg--; - dataptr = ahd_le64toh(sg->addr) - + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK) + dataptr = aic_le64toh(sg->addr) + + (aic_le32toh(sg->len) & AHD_SG_LEN_MASK) - resid; - ahd_outb(ahd, HADDR + 7, dataptr >> 56); - ahd_outb(ahd, HADDR + 6, dataptr >> 48); - ahd_outb(ahd, HADDR + 5, dataptr >> 40); - ahd_outb(ahd, HADDR + 4, dataptr >> 32); + ahd_outl(ahd, HADDR + 4, dataptr >> 32); } else { struct ahd_dma_seg *sg; @@ -4613,16 +4993,13 @@ /* The residual sg_ptr always points to the next sg */ sg--; - dataptr = ahd_le32toh(sg->addr) - + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK) + dataptr = aic_le32toh(sg->addr) + + (aic_le32toh(sg->len) & AHD_SG_LEN_MASK) - resid; ahd_outb(ahd, HADDR + 4, - (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24); + (aic_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24); } - ahd_outb(ahd, HADDR + 3, dataptr >> 24); - ahd_outb(ahd, HADDR + 2, dataptr >> 16); - ahd_outb(ahd, HADDR + 1, dataptr >> 8); - ahd_outb(ahd, HADDR, dataptr); + ahd_outl(ahd, HADDR, dataptr); ahd_outb(ahd, HCNT + 2, resid >> 16); ahd_outb(ahd, HCNT + 1, resid >> 8); ahd_outb(ahd, HCNT, resid); @@ -4816,8 +5193,8 @@ ahd->bugs = AHD_BUGNONE; ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A | AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A; - ahd_timer_init(&ahd->reset_timer); - ahd_timer_init(&ahd->stat_timer); + aic_timer_init(&ahd->reset_timer); + aic_timer_init(&ahd->stat_timer); ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT; ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT; ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT; @@ -4853,24 +5230,24 @@ { struct ahd_softc *list_ahd; -#if AHD_PCI_CONFIG > 0 +#if AIC_PCI_CONFIG > 0 /* * Second Function PCI devices need to inherit some * settings from function 0. */ if ((ahd->features & AHD_MULTI_FUNC) != 0) { TAILQ_FOREACH(list_ahd, &ahd_tailq, links) { - ahd_dev_softc_t list_pci; - ahd_dev_softc_t pci; + aic_dev_softc_t list_pci; + aic_dev_softc_t pci; list_pci = list_ahd->dev_softc; pci = ahd->dev_softc; - if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci) - && ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) { + if (aic_get_pci_slot(list_pci) == aic_get_pci_slot(pci) + && aic_get_pci_bus(list_pci) == aic_get_pci_bus(pci)) { struct ahd_softc *master; struct ahd_softc *slave; - if (ahd_get_pci_function(list_pci) == 0) { + if (aic_get_pci_function(list_pci) == 0) { master = list_ahd; slave = ahd; } else { @@ -4935,27 +5312,27 @@ { int i; + ahd_terminate_recovery_thread(ahd); switch (ahd->init_level) { default: case 5: ahd_shutdown(ahd); - TAILQ_REMOVE(&ahd_tailq, ahd, links); /* FALLTHROUGH */ case 4: - ahd_dmamap_unload(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap); + aic_dmamap_unload(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap); /* FALLTHROUGH */ case 3: - ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo, - ahd->shared_data_dmamap); - ahd_dmamap_destroy(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap); + aic_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo, + ahd->shared_data_map.dmamap); + aic_dmamap_destroy(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap); /* FALLTHROUGH */ case 2: - ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat); + aic_dma_tag_destroy(ahd, ahd->shared_data_dmat); case 1: #ifndef __linux__ - ahd_dma_tag_destroy(ahd, ahd->buffer_dmat); + aic_dma_tag_destroy(ahd, ahd->buffer_dmat); #endif break; case 0: @@ -4963,7 +5340,7 @@ } #ifndef __linux__ - ahd_dma_tag_destroy(ahd, ahd->parent_dmat); + aic_dma_tag_destroy(ahd, ahd->parent_dmat); #endif ahd_platform_free(ahd); ahd_fini_scbdata(ahd); @@ -5016,8 +5393,8 @@ /* * Stop periodic timer callbacks. */ - ahd_timer_stop(&ahd->reset_timer); - ahd_timer_stop(&ahd->stat_timer); + aic_timer_stop(&ahd->reset_timer); + aic_timer_stop(&ahd->stat_timer); /* This will reset most registers to 0, but not all */ ahd_reset(ahd, /*reinit*/FALSE); @@ -5049,7 +5426,7 @@ ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); sxfrctl1 = ahd_inb(ahd, SXFRCTL1); - cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); + cmd = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) { uint32_t mod_cmd; @@ -5063,7 +5440,7 @@ * PERR and SERR responses during the CHIPRST. */ mod_cmd = cmd & ~(PCIM_CMD_PERRESPEN|PCIM_CMD_SERRESPEN); - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, mod_cmd, /*bytes*/2); } ahd_outb(ahd, HCNTRL, CHIPRST | ahd->pause); @@ -5076,7 +5453,7 @@ */ wait = 1000; do { - ahd_delay(1000); + aic_delay(1000); } while (--wait && !(ahd_inb(ahd, HCNTRL) & CHIPRSTACK)); if (wait == 0) { @@ -5090,9 +5467,9 @@ * Clear any latched PCI error status and restore * previous SERR and PERR response enables. */ - ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, 0xFF, /*bytes*/1); - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); } @@ -5219,7 +5596,7 @@ */ /* DMA tag for our hardware scb structures */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -5233,7 +5610,7 @@ scb_data->init_level++; /* DMA tag for our S/G structures. */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/8, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/8, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -5252,7 +5629,7 @@ scb_data->init_level++; /* DMA tag for our sense buffers. We allocate in page sized chunks */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -5340,13 +5717,13 @@ while ((sns_map = SLIST_FIRST(&scb_data->sense_maps)) != NULL) { SLIST_REMOVE_HEAD(&scb_data->sense_maps, links); - ahd_dmamap_unload(ahd, scb_data->sense_dmat, + aic_dmamap_unload(ahd, scb_data->sense_dmat, sns_map->dmamap); - ahd_dmamem_free(ahd, scb_data->sense_dmat, + aic_dmamem_free(ahd, scb_data->sense_dmat, sns_map->vaddr, sns_map->dmamap); free(sns_map, M_DEVBUF); } - ahd_dma_tag_destroy(ahd, scb_data->sense_dmat); + aic_dma_tag_destroy(ahd, scb_data->sense_dmat); /* FALLTHROUGH */ } case 6: @@ -5355,13 +5732,13 @@ while ((sg_map = SLIST_FIRST(&scb_data->sg_maps)) != NULL) { SLIST_REMOVE_HEAD(&scb_data->sg_maps, links); - ahd_dmamap_unload(ahd, scb_data->sg_dmat, + aic_dmamap_unload(ahd, scb_data->sg_dmat, sg_map->dmamap); - ahd_dmamem_free(ahd, scb_data->sg_dmat, + aic_dmamem_free(ahd, scb_data->sg_dmat, sg_map->vaddr, sg_map->dmamap); free(sg_map, M_DEVBUF); } - ahd_dma_tag_destroy(ahd, scb_data->sg_dmat); + aic_dma_tag_destroy(ahd, scb_data->sg_dmat); /* FALLTHROUGH */ } case 5: @@ -5370,13 +5747,13 @@ while ((hscb_map = SLIST_FIRST(&scb_data->hscb_maps)) != NULL) { SLIST_REMOVE_HEAD(&scb_data->hscb_maps, links); - ahd_dmamap_unload(ahd, scb_data->hscb_dmat, + aic_dmamap_unload(ahd, scb_data->hscb_dmat, hscb_map->dmamap); - ahd_dmamem_free(ahd, scb_data->hscb_dmat, + aic_dmamem_free(ahd, scb_data->hscb_dmat, hscb_map->vaddr, hscb_map->dmamap); free(hscb_map, M_DEVBUF); } - ahd_dma_tag_destroy(ahd, scb_data->hscb_dmat); + aic_dma_tag_destroy(ahd, scb_data->hscb_dmat); /* FALLTHROUGH */ } case 4: @@ -5407,6 +5784,7 @@ 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 @@ -5415,6 +5793,8 @@ 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); @@ -5434,6 +5814,7 @@ 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 ***********************************/ @@ -5577,7 +5958,7 @@ scb, links.le); } - ahd_platform_scb_free(ahd, scb); + aic_platform_scb_free(ahd, scb); } void @@ -5608,7 +5989,7 @@ offset = (PAGE_SIZE / sizeof(*hscb)) - scb_data->scbs_left; hscb_map = SLIST_FIRST(&scb_data->hscb_maps); hscb = &((struct hardware_scb *)hscb_map->vaddr)[offset]; - hscb_busaddr = hscb_map->physaddr + (offset * sizeof(*hscb)); + hscb_busaddr = hscb_map->busaddr + (offset * sizeof(*hscb)); } else { hscb_map = malloc(sizeof(*hscb_map), M_DEVBUF, M_NOWAIT); @@ -5616,7 +5997,7 @@ return; /* Allocate the next batch of hardware SCBs */ - if (ahd_dmamem_alloc(ahd, scb_data->hscb_dmat, + if (aic_dmamem_alloc(ahd, scb_data->hscb_dmat, (void **)&hscb_map->vaddr, BUS_DMA_NOWAIT, &hscb_map->dmamap) != 0) { free(hscb_map, M_DEVBUF); @@ -5625,13 +6006,29 @@ SLIST_INSERT_HEAD(&scb_data->hscb_maps, hscb_map, links); - ahd_dmamap_load(ahd, scb_data->hscb_dmat, hscb_map->dmamap, + aic_dmamap_load(ahd, scb_data->hscb_dmat, hscb_map->dmamap, hscb_map->vaddr, PAGE_SIZE, ahd_dmamap_cb, - &hscb_map->physaddr, /*flags*/0); + &hscb_map->busaddr, /*flags*/0); hscb = (struct hardware_scb *)hscb_map->vaddr; - hscb_busaddr = hscb_map->physaddr; + hscb_busaddr = hscb_map->busaddr; scb_data->scbs_left = PAGE_SIZE / sizeof(*hscb); + if (ahd->next_queued_hscb == NULL) { + /* + * We need one HSCB to serve as the "next HSCB". Since + * the tag identifier in this HSCB will never be used, + * there is no point in using a valid SCB from the + * free pool for it. So, we allocate this "sentinel" + * specially. + */ + ahd->next_queued_hscb = hscb; + ahd->next_queued_hscb_map = hscb_map; + memset(hscb, 0, sizeof(*hscb)); + hscb->hscb_busaddr = aic_htole32(hscb_busaddr); + hscb++; + hscb_busaddr += sizeof(*hscb); + scb_data->scbs_left--; + } } if (scb_data->sgs_left != 0) { @@ -5641,7 +6038,7 @@ - scb_data->sgs_left) * ahd_sglist_size(ahd); sg_map = SLIST_FIRST(&scb_data->sg_maps); segs = sg_map->vaddr + offset; - sg_busaddr = sg_map->physaddr + offset; + sg_busaddr = sg_map->busaddr + offset; } else { sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); @@ -5649,7 +6046,7 @@ return; /* Allocate the next batch of S/G lists */ - if (ahd_dmamem_alloc(ahd, scb_data->sg_dmat, + if (aic_dmamem_alloc(ahd, scb_data->sg_dmat, (void **)&sg_map->vaddr, BUS_DMA_NOWAIT, &sg_map->dmamap) != 0) { free(sg_map, M_DEVBUF); @@ -5658,12 +6055,12 @@ SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links); - ahd_dmamap_load(ahd, scb_data->sg_dmat, sg_map->dmamap, + aic_dmamap_load(ahd, scb_data->sg_dmat, sg_map->dmamap, sg_map->vaddr, ahd_sglist_allocsize(ahd), - ahd_dmamap_cb, &sg_map->physaddr, /*flags*/0); + ahd_dmamap_cb, &sg_map->busaddr, /*flags*/0); segs = sg_map->vaddr; - sg_busaddr = sg_map->physaddr; + sg_busaddr = sg_map->busaddr; scb_data->sgs_left = ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd); #ifdef AHD_DEBUG @@ -5678,7 +6075,7 @@ offset = PAGE_SIZE - (AHD_SENSE_BUFSIZE * scb_data->sense_left); sense_map = SLIST_FIRST(&scb_data->sense_maps); sense_data = sense_map->vaddr + offset; - sense_busaddr = sense_map->physaddr + offset; + sense_busaddr = sense_map->busaddr + offset; } else { sense_map = malloc(sizeof(*sense_map), M_DEVBUF, M_NOWAIT); @@ -5686,7 +6083,7 @@ return; /* Allocate the next batch of sense buffers */ - if (ahd_dmamem_alloc(ahd, scb_data->sense_dmat, + if (aic_dmamem_alloc(ahd, scb_data->sense_dmat, (void **)&sense_map->vaddr, BUS_DMA_NOWAIT, &sense_map->dmamap) != 0) { free(sense_map, M_DEVBUF); @@ -5695,12 +6092,12 @@ SLIST_INSERT_HEAD(&scb_data->sense_maps, sense_map, links); - ahd_dmamap_load(ahd, scb_data->sense_dmat, sense_map->dmamap, + aic_dmamap_load(ahd, scb_data->sense_dmat, sense_map->dmamap, sense_map->vaddr, PAGE_SIZE, ahd_dmamap_cb, - &sense_map->physaddr, /*flags*/0); + &sense_map->busaddr, /*flags*/0); sense_data = sense_map->vaddr; - sense_busaddr = sense_map->physaddr; + sense_busaddr = sense_map->busaddr; scb_data->sense_left = PAGE_SIZE / AHD_SENSE_BUFSIZE; #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_MEMORY) @@ -5715,12 +6112,12 @@ scb_data->scbs_left -= newcount; scb_data->sgs_left -= newcount; for (i = 0; i < newcount; i++) { - u_int col_tag; - struct scb_platform_data *pdata; + u_int col_tag; #ifndef __linux__ int error; #endif + next_scb = (struct scb *)malloc(sizeof(*next_scb), M_DEVBUF, M_NOWAIT); if (next_scb == NULL) @@ -5741,7 +6138,7 @@ next_scb->sense_busaddr = sense_busaddr; memset(hscb, 0, sizeof(*hscb)); next_scb->hscb = hscb; - hscb->hscb_busaddr = ahd_htole32(hscb_busaddr); + hscb->hscb_busaddr = aic_htole32(hscb_busaddr); /* * The sequencer always starts with the second entry. @@ -5756,7 +6153,7 @@ next_scb->ahd_softc = ahd; next_scb->flags = SCB_FLAG_NONE; #ifndef __linux__ - error = ahd_dmamap_create(ahd, ahd->buffer_dmat, /*flags*/0, + error = aic_dmamap_create(ahd, ahd->buffer_dmat, /*flags*/0, &next_scb->dmamap); if (error != 0) { free(next_scb, M_DEVBUF); @@ -5764,7 +6161,7 @@ break; } #endif - next_scb->hscb->tag = ahd_htole16(scb_data->numscbs); + next_scb->hscb->tag = aic_htole16(scb_data->numscbs); col_tag = scb_data->numscbs ^ 0x100; next_scb->col_scb = ahd_find_scb_by_tag(ahd, col_tag); if (next_scb->col_scb != NULL) @@ -5824,7 +6221,6 @@ int ahd_init(struct ahd_softc *ahd) { - uint8_t *base_vaddr; uint8_t *next_vaddr; bus_addr_t next_baddr; size_t driver_data_size; @@ -5867,7 +6263,7 @@ #ifndef __linux__ /* DMA tag for mapping buffers into device visible space. */ - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/ahd->flags & AHD_39BIT_ADDRESSING ? (bus_addr_t)0x7FFFFFFFFFULL @@ -5892,13 +6288,12 @@ * for the target mode role, we must additionally provide space for * the incoming target command fifo. */ - driver_data_size = AHD_SCB_MAX * sizeof(uint16_t) - + sizeof(struct hardware_scb); + driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo); if ((ahd->features & AHD_TARGETMODE) != 0) driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd); if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) driver_data_size += PKT_OVERRUN_BUFSIZE; - if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -5913,21 +6308,24 @@ ahd->init_level++; /* Allocation of driver data */ - if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat, - (void **)&base_vaddr, - BUS_DMA_NOWAIT, &ahd->shared_data_dmamap) != 0) { + if (aic_dmamem_alloc(ahd, ahd->shared_data_dmat, + (void **)&ahd->shared_data_map.vaddr, + BUS_DMA_NOWAIT, + &ahd->shared_data_map.dmamap) != 0) { return (ENOMEM); } ahd->init_level++; /* And permanently map it in */ - ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - base_vaddr, driver_data_size, ahd_dmamap_cb, - &ahd->shared_data_busaddr, /*flags*/0); - ahd->qoutfifo = (uint16_t *)base_vaddr; + aic_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + ahd->shared_data_map.vaddr, driver_data_size, + ahd_dmamap_cb, &ahd->shared_data_map.busaddr, + /*flags*/0); + ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr; next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE]; - next_baddr = ahd->shared_data_busaddr + AHD_QOUT_SIZE*sizeof(uint16_t); + next_baddr = ahd->shared_data_map.busaddr + + AHD_QOUT_SIZE*sizeof(struct ahd_completion); if ((ahd->features & AHD_TARGETMODE) != 0) { ahd->targetcmds = (struct target_cmd *)next_vaddr; next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd); @@ -5940,16 +6338,6 @@ next_baddr += PKT_OVERRUN_BUFSIZE; } - /* - * We need one SCB to serve as the "next SCB". Since the - * tag identifier in this SCB will never be used, there is - * no point in using a valid HSCB tag from an SCB pulled from - * the standard free pool. So, we allocate this "sentinel" - * specially from the DMA safe memory chunk used for the QOUTFIFO. - */ - ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr; - ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr); - ahd->init_level++; /* Allocate SCB data now that buffer_dmat is initialized */ @@ -6039,7 +6427,7 @@ } init_done: ahd_restart(ahd); - ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, + aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, ahd_stat_timer, ahd); return (0); } @@ -6100,7 +6488,7 @@ for (wait = 10000; (ahd_inb(ahd, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait; wait--) - ahd_delay(100); + aic_delay(100); /* Clear any false bus resets due to the transceivers settling */ ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI); @@ -6240,6 +6628,7 @@ 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. @@ -6247,14 +6636,15 @@ 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 */ ahd->qoutfifonext = 0; - ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID_LE; - ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID >> 8); + ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID; + ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID); for (i = 0; i < AHD_QOUT_SIZE; i++) - ahd->qoutfifo[i] = 0; + ahd->qoutfifo[i].valid_tag = 0; ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD); ahd->qinfifonext = 0; @@ -6287,24 +6677,22 @@ ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL); ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL); ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL); + ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL); /* * The Freeze Count is 0. */ + ahd->qfreeze_cnt = 0; ahd_outw(ahd, QFREEZE_COUNT, 0); + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0); /* * Tell the sequencer where it can find our arrays in memory. */ - busaddr = ahd->shared_data_busaddr; - ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 3, (busaddr >> 24) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR, busaddr & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 3, (busaddr >> 24) & 0xFF); + busaddr = ahd->shared_data_map.busaddr; + ahd_outl(ahd, SHARED_DATA_ADDR, busaddr); + ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr); /* * Setup the allowed SCSI Sequences based on operational mode. @@ -6352,11 +6740,8 @@ /* * Tell the sequencer which SCB will be the next one it receives. */ - busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); /* * Default to coalescing disabled. @@ -6660,23 +7045,28 @@ { u_int intstat; u_int maxloops; - u_int qfreeze_cnt; maxloops = 1000; ahd->flags |= AHD_ALL_INTERRUPTS; ahd_pause(ahd); /* - * Increment the QFreeze Count so that the sequencer - * will not start new selections. We do this only + * Freeze the outgoing selections. We do this only * until we are safely paused without further selections * pending. */ - ahd_outw(ahd, QFREEZE_COUNT, ahd_inw(ahd, QFREEZE_COUNT) + 1); + ahd->qfreeze_cnt--; + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN); do { struct scb *waiting_scb; ahd_unpause(ahd); + /* + * Give the sequencer some time to service + * any active selections. + */ + aic_delay(200); + ahd_intr(ahd); ahd_pause(ahd); ahd_clear_critical_section(ahd); @@ -6707,17 +7097,8 @@ printf("Infinite interrupt loop, INTSTAT = %x", ahd_inb(ahd, INTSTAT)); } - qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); - if (qfreeze_cnt == 0) { - printf("%s: ahd_pause_and_flushwork with 0 qfreeze count!\n", - ahd_name(ahd)); - } else { - qfreeze_cnt--; - } - ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt); - if (qfreeze_cnt == 0) - ahd_outb(ahd, SEQ_FLAGS2, - ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN); + ahd->qfreeze_cnt++; + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); ahd_flush_qoutfifo(ahd); @@ -6888,11 +7269,8 @@ if (prev_scb == NULL) { uint32_t busaddr; - busaddr = ahd_le32toh(scb->hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + busaddr = aic_le32toh(scb->hscb->hscb_busaddr); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); } else { prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; ahd_sync_scb(ahd, prev_scb, @@ -6998,11 +7376,8 @@ * for removal will be re-added to the queue as we go. */ ahd->qinfifonext = qinstart; - busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); while (qinpos != qintail) { scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]); @@ -7023,13 +7398,13 @@ cam_status ostat; cam_status cstat; - ostat = ahd_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scb, + aic_set_transaction_status(scb, status); - cstat = ahd_get_transaction_status(scb); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahd_freeze_scb(scb); + aic_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) printf("Inactive SCB in qinfifo\n"); ahd_done(ahd, scb); @@ -7064,6 +7439,7 @@ * appropriate, traverse the SCBs of each "their id" * looking for matches. */ + ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); savedscbptr = ahd_get_scbptr(ahd); tid_next = ahd_inw(ahd, WAITING_TID_HEAD); tid_prev = SCB_LIST_NULL; @@ -7133,7 +7509,7 @@ u_int prev; int found; - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); found = 0; prev = SCB_LIST_NULL; next = *list_head; @@ -7165,12 +7541,12 @@ cam_status ostat; cam_status cstat; - ostat = ahd_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scb, status); - cstat = ahd_get_transaction_status(scb); + aic_set_transaction_status(scb, status); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahd_freeze_scb(scb); + aic_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) printf("Inactive SCB in Waiting List\n"); ahd_done(ahd, scb); @@ -7200,7 +7576,7 @@ ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev, u_int tid_cur, u_int tid_next) { - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); if (SCBID_IS_NULL(tid_cur)) { @@ -7240,7 +7616,7 @@ { u_int tail_offset; - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); if (!SCBID_IS_NULL(prev)) { ahd_set_scbptr(ahd, prev); ahd_outw(ahd, SCB_NEXT, next); @@ -7361,11 +7737,11 @@ if (ahd_match_scb(ahd, scbp, target, channel, lun, tag, role)) { cam_status ostat; - ostat = ahd_get_transaction_status(scbp); + ostat = aic_get_transaction_status(scbp); if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scbp, status); - if (ahd_get_transaction_status(scbp) != CAM_REQ_CMP) - ahd_freeze_scb(scbp); + aic_set_transaction_status(scbp, status); + if (aic_get_transaction_status(scbp) != CAM_REQ_CMP) + aic_freeze_scb(scbp); if ((scbp->flags & SCB_ACTIVE) == 0) printf("Inactive SCB on pending list\n"); ahd_done(ahd, scbp); @@ -7387,9 +7763,12 @@ ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~ENSCSIRST); scsiseq = ahd_inb(ahd, SCSISEQ0) & ~(ENSELO|ENARBO|SCSIRSTO); ahd_outb(ahd, SCSISEQ0, scsiseq | SCSIRSTO); - ahd_delay(AHD_BUSRESET_DELAY); + ahd_flush_device_writes(ahd); + aic_delay(AHD_BUSRESET_DELAY); /* Turn off the bus reset */ ahd_outb(ahd, SCSISEQ0, scsiseq); + ahd_flush_device_writes(ahd); + aic_delay(AHD_BUSRESET_DELAY); if ((ahd->bugs & AHD_SCSIRST_BUG) != 0) { /* * 2A Razor #474 @@ -7397,7 +7776,6 @@ * SCSI bus resets that we initiate, so * we must reset the chip. */ - ahd_delay(AHD_BUSRESET_DELAY); ahd_reset(ahd, /*reinit*/TRUE); ahd_intr_enable(ahd, /*enable*/TRUE); AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); @@ -7458,7 +7836,7 @@ ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) & ~(SCSIEN|HDMAEN)); while ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) - ahd_delay(10); + aic_delay(10); /* * Set CURRFIFO to the now inactive channel. */ @@ -7471,7 +7849,7 @@ */ ahd_clear_msg_state(ahd); ahd_outb(ahd, SIMODE1, - ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE)); + ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST)); if (initiate_reset) ahd_reset_current_bus(ahd); @@ -7553,8 +7931,8 @@ */ if ((ahd->flags & AHD_RESET_POLL_ACTIVE) == 0) { ahd->flags |= AHD_RESET_POLL_ACTIVE; - ahd_freeze_simq(ahd); - ahd_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd); + aic_freeze_simq(ahd); + aic_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd); } return (found); } @@ -7582,7 +7960,7 @@ ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI); if ((ahd_inb(ahd, SSTAT1) & SCSIRSTI) != 0) { - ahd_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US, + aic_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US, ahd_reset_poll, ahd); ahd_unpause(ahd); ahd_unlock(ahd, &s); @@ -7597,7 +7975,7 @@ ahd_unpause(ahd); ahd->flags &= ~AHD_RESET_POLL_ACTIVE; ahd_unlock(ahd, &s); - ahd_release_simq(ahd); + aic_release_simq(ahd); ahd_list_unlock(&l); } @@ -7640,7 +8018,7 @@ ahd->cmdcmplt_bucket = (ahd->cmdcmplt_bucket+1) & (AHD_STAT_BUCKETS-1); ahd->cmdcmplt_total -= ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]; ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket] = 0; - ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, + aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, ahd_stat_timer, ahd); ahd_unlock(ahd, &s); ahd_list_unlock(&l); @@ -7661,30 +8039,35 @@ void ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) { - struct hardware_scb *hscb; - u_int qfreeze_cnt; + struct hardware_scb *hscb; + int paused; /* * The sequencer freezes its select-out queue * anytime a SCSI status error occurs. We must - * handle the error and decrement the QFREEZE count - * to allow the sequencer to continue. + * handle the error and increment our qfreeze count + * to allow the sequencer to continue. We don't + * bother clearing critical sections here since all + * operations are on data structures that the sequencer + * is not touching once the queue is frozen. */ hscb = scb->hscb; - /* Freeze the queue until the client sees the error. */ - ahd_freeze_devq(ahd, scb); - ahd_freeze_scb(scb); - qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); - if (qfreeze_cnt == 0) { - printf("%s: Bad status with 0 qfreeze count!\n", ahd_name(ahd)); + if (ahd_is_paused(ahd)) { + paused = 1; } else { - qfreeze_cnt--; - ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt); + paused = 0; + ahd_pause(ahd); } - if (qfreeze_cnt == 0) - ahd_outb(ahd, SEQ_FLAGS2, - ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN); + + /* Freeze the queue until the client sees the error. */ + ahd_freeze_devq(ahd, scb); + aic_freeze_scb(scb); + ahd->qfreeze_cnt++; + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); + + if (paused == 0) + ahd_unpause(ahd); /* Don't want to clobber the original sense code */ if ((scb->flags & SCB_SENSE) != 0) { @@ -7693,12 +8076,12 @@ * a normal command completion. */ scb->flags &= ~SCB_SENSE; - ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); + aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); ahd_done(ahd, scb); return; } - ahd_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); - ahd_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status); + aic_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); + aic_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status); switch (hscb->shared_data.istatus.scsi_status) { case STATUS_PKT_SENSE: { @@ -7706,7 +8089,7 @@ ahd_sync_sense(ahd, scb, BUS_DMASYNC_POSTREAD); siu = (struct scsi_status_iu_header *)scb->sense_data; - ahd_set_scsi_status(scb, siu->status); + aic_set_scsi_status(scb, siu->status); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_SENSE) != 0) { ahd_print_path(ahd, scb); @@ -7747,7 +8130,7 @@ } } if (siu->status == SCSI_STATUS_OK) - ahd_set_transaction_status(scb, + aic_set_transaction_status(scb, CAM_REQ_CMP_ERR); } if ((siu->flags & SIU_SNSVALID) != 0) { @@ -7777,7 +8160,7 @@ } #endif - if (ahd_perform_autosense(scb) == 0) + if (aic_perform_autosense(scb) == 0) break; ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb), @@ -7805,7 +8188,7 @@ #endif scb->sg_count = 0; sg = ahd_sg_setup(ahd, scb, sg, ahd_get_sense_bufaddr(ahd, scb), - ahd_get_sense_bufsize(ahd, scb), + aic_get_sense_bufsize(ahd, scb), /*last*/TRUE); sc->opcode = REQUEST_SENSE; sc->byte2 = 0; @@ -7814,7 +8197,7 @@ sc->byte2 = SCB_GET_LUN(scb) << 5; sc->unused[0] = 0; sc->unused[1] = 0; - sc->length = ahd_get_sense_bufsize(ahd, scb); + sc->length = aic_get_sense_bufsize(ahd, scb); sc->control = 0; /* @@ -7834,7 +8217,7 @@ * errors will be reported before any data * phases occur. */ - if (ahd_get_residual(scb) == ahd_get_transfer_length(scb)) { + if (aic_get_residual(scb) == aic_get_transfer_length(scb)) { ahd_update_neg_request(ahd, &devinfo, tstate, targ_info, AHD_NEG_IF_NON_ASYNC); @@ -7853,7 +8236,7 @@ * Ensure we have enough time to actually * retrieve the sense. */ - ahd_scb_timer_reset(scb, 5 * 1000000); + aic_scb_timer_reset(scb, 5 * 1000000); break; } case SCSI_STATUS_OK: @@ -7895,7 +8278,7 @@ */ hscb = scb->hscb; - sgptr = ahd_le32toh(hscb->sgptr); + sgptr = aic_le32toh(hscb->sgptr); if ((sgptr & SG_STATUS_VALID) == 0) /* Case 1 */ return; @@ -7912,10 +8295,10 @@ * regardless of the role for this SCB. */ spkt = &hscb->shared_data.istatus; - resid_sgptr = ahd_le32toh(spkt->residual_sgptr); + resid_sgptr = aic_le32toh(spkt->residual_sgptr); if ((sgptr & SG_FULL_RESID) != 0) { /* Case 3 */ - resid = ahd_get_transfer_length(scb); + resid = aic_get_transfer_length(scb); } else if ((resid_sgptr & SG_LIST_NULL) != 0) { /* Case 4 */ return; @@ -7924,8 +8307,8 @@ printf("data overrun detected Tag == 0x%x.\n", SCB_GET_TAG(scb)); ahd_freeze_devq(ahd, scb); - ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR); - ahd_freeze_scb(scb); + aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); + aic_freeze_scb(scb); return; } else if ((resid_sgptr & ~SG_PTR_MASK) != 0) { panic("Bogus resid sgptr value 0x%x\n", resid_sgptr); @@ -7937,7 +8320,7 @@ * Remainder of the SG where the transfer * stopped. */ - resid = ahd_le32toh(spkt->residual_datacnt) & AHD_SG_LEN_MASK; + resid = aic_le32toh(spkt->residual_datacnt) & AHD_SG_LEN_MASK; sg = ahd_sg_bus_to_virt(ahd, scb, resid_sgptr & SG_PTR_MASK); /* The residual sg_ptr always points to the next sg */ @@ -7948,15 +8331,15 @@ * SG segments that are after the SG where * the transfer stopped. */ - while ((ahd_le32toh(sg->len) & AHD_DMA_LAST_SEG) == 0) { + while ((aic_le32toh(sg->len) & AHD_DMA_LAST_SEG) == 0) { sg++; - resid += ahd_le32toh(sg->len) & AHD_SG_LEN_MASK; + resid += aic_le32toh(sg->len) & AHD_SG_LEN_MASK; } } if ((scb->flags & SCB_SENSE) == 0) - ahd_set_residual(scb, resid); + aic_set_residual(scb, resid); else - ahd_set_sense_residual(scb, resid); + aic_set_sense_residual(scb, resid); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) { @@ -8068,8 +8451,7 @@ max_prog = 2048; ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); - ahd_outb(ahd, PRGMCNT, 0); - ahd_outb(ahd, PRGMCNT+1, 0); + ahd_outw(ahd, PRGMCNT, 0); for (i = 0; i < max_prog; i++) { uint8_t ins_bytes[4]; @@ -8184,8 +8566,7 @@ downloaded = 0; skip_addr = 0; ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); - ahd_outb(ahd, PRGMCNT, 0); - ahd_outb(ahd, PRGMCNT+1, 0); + ahd_outw(ahd, PRGMCNT, 0); for (i = 0; i < sizeof(seqprog)/4; i++) { if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) { @@ -8314,7 +8695,7 @@ /* * The firmware is always compiled into a little endian format. */ - instr.integer = ahd_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); + instr.integer = aic_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); fmt1_ins = &instr.format1; fmt3_ins = NULL; @@ -8362,7 +8743,7 @@ instr.format1.parity = 1; /* The sequencer is a little endian cpu */ - instr.integer = ahd_htole32(instr.integer); + instr.integer = aic_htole32(instr.integer); ahd_outsb(ahd, SEQRAM, instr.bytes, 4); break; } @@ -8488,11 +8869,15 @@ printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" "%s: Dumping Card State at program address 0x%x Mode 0x%x\n", ahd_name(ahd), - ahd_inb(ahd, CURADDR) | (ahd_inb(ahd, CURADDR+1) << 8), + ahd_inw(ahd, CURADDR), ahd_build_mode_state(ahd, ahd->saved_src_mode, ahd->saved_dst_mode)); if (paused) printf("Card was paused\n"); + + if (ahd_check_cmdcmpltqueues(ahd)) + printf("Completions are pending\n"); + /* * Mode independent registers. */ @@ -8542,10 +8927,12 @@ 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); @@ -8574,7 +8961,7 @@ 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"); @@ -8584,7 +8971,7 @@ 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"); @@ -8595,7 +8982,16 @@ 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"); + printf("Sequencer On QFreeze and Complete list: "); + scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD); + i = 0; + while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { + ahd_set_scbptr(ahd, scb_index); + printf("%d ", scb_index); + scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); } printf("\n"); ahd_set_scbptr(ahd, saved_scb_index); @@ -8674,15 +9070,16 @@ 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] = @@ -8714,16 +9111,292 @@ ahd_set_scbptr(ahd, i); printf("%3d", i); printf("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n", - ahd_inb(ahd, SCB_CONTROL), - ahd_inb(ahd, SCB_SCSIID), ahd_inw(ahd, SCB_NEXT), - ahd_inw(ahd, SCB_NEXT2), ahd_inl(ahd, SCB_SGPTR), - ahd_inl(ahd, SCB_RESIDUAL_SGPTR)); + ahd_inb_scbram(ahd, SCB_CONTROL), + ahd_inb_scbram(ahd, SCB_SCSIID), + ahd_inw_scbram(ahd, SCB_NEXT), + ahd_inw_scbram(ahd, SCB_NEXT2), + ahd_inl_scbram(ahd, SCB_SGPTR), + ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR)); } printf("\n"); ahd_set_scbptr(ahd, saved_scb_index); ahd_restore_modes(ahd, saved_modes); } + +/*************************** Timeout Handling *********************************/ +void +ahd_timeout(struct scb *scb) +{ + struct ahd_softc *ahd; + + ahd = scb->ahd_softc; + if ((scb->flags & SCB_ACTIVE) != 0) { + if ((scb->flags & SCB_TIMEDOUT) == 0) { + LIST_INSERT_HEAD(&ahd->timedout_scbs, scb, + timedout_links); + scb->flags |= SCB_TIMEDOUT; + } + ahd_wakeup_recovery_thread(ahd); + } +} + +/* + * ahd_recover_commands determines if any of the commands that have currently + * timedout are the root cause for this timeout. Innocent commands are given + * a new timeout while we wait for the command executing on the bus to timeout. + * This routine is invoked from a thread context so we are allowed to sleep. + * Our lock is not held on entry. + */ +void +ahd_recover_commands(struct ahd_softc *ahd) +{ + struct scb *scb; + struct scb *active_scb; + long s; + int found; + int was_paused; + u_int active_scbptr; + u_int last_phase; + + ahd_lock(ahd, &s); + + /* + * Pause the controller and manually flush any + * commands that have just completed but that our + * interrupt handler has yet to see. + */ + was_paused = ahd_is_paused(ahd); + ahd_pause_and_flushwork(ahd); + + if (LIST_EMPTY(&ahd->timedout_scbs) != 0) { + /* + * The timedout commands have already + * completed. This typically means + * that either the timeout value was on + * the hairy edge of what the device + * requires or - more likely - interrupts + * are not happening. + */ + printf("%s: Timedout SCBs already complete. " + "Interrupts may not be functioning.\n", ahd_name(ahd)); + ahd_unpause(ahd); + ahd_unlock(ahd, &s); + return; + } + + printf("%s: Recovery Initiated - Card was %spaused\n", ahd_name(ahd), + was_paused ? "" : "not "); + ahd_dump_card_state(ahd); + + /* + * Determine identity of SCB acting on the bus. + * This test only catches non-packetized transactions. + * Due to the fleeting nature of packetized operations, + * we can't easily determine that a packetized operation + * is on the bus. + */ + ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); + last_phase = ahd_inb(ahd, LASTPHASE); + active_scbptr = ahd_get_scbptr(ahd); + active_scb = NULL; + if (last_phase != P_BUSFREE + || (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) + active_scb = ahd_lookup_scb(ahd, active_scbptr); + + while ((scb = LIST_FIRST(&ahd->timedout_scbs)) != NULL) { + int target; + int lun; + char channel; + + target = SCB_GET_TARGET(ahd, scb); + channel = SCB_GET_CHANNEL(ahd, scb); + lun = SCB_GET_LUN(scb); + + ahd_print_path(ahd, scb); + printf("SCB 0x%x - timed out\n", scb->hscb->tag); + + if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) { + /* + * Been down this road before. + * Do a full bus reset. + */ + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); +bus_reset: + found = ahd_reset_channel(ahd, channel, + /*Initiate Reset*/TRUE); + printf("%s: Issued Channel %c Bus Reset. " + "%d SCBs aborted\n", ahd_name(ahd), channel, + found); + continue; + } + + /* + * Remove the command from the timedout list in + * preparation for requeing it. + */ + LIST_REMOVE(scb, timedout_links); + scb->flags &= ~SCB_TIMEDOUT; + + if (active_scb != NULL) { + + if (active_scb != scb) { + /* + * If the active SCB is not us, assume that + * the active SCB has a longer timeout than + * the timedout SCB, and wait for the active + * SCB to timeout. + */ + ahd_other_scb_timeout(ahd, scb, active_scb); + continue; + } + + /* + * We're active on the bus, so assert ATN + * and hope that the target responds. + */ + ahd_set_recoveryscb(ahd, active_scb); + active_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET; + ahd_outb(ahd, MSG_OUT, HOST_MSG); + ahd_outb(ahd, SCSISIGO, last_phase|ATNO); + ahd_print_path(ahd, active_scb); + printf("BDR message in message buffer\n"); + aic_scb_timer_reset(scb, 2 * 1000000); + break; + } else if (last_phase != P_BUSFREE + && ahd_inb(ahd, SCSIPHASE) == 0) { + /* + * SCB is not identified, there + * is no pending REQ, and the sequencer + * has not seen a busfree. Looks like + * a stuck connection waiting to + * go busfree. Reset the bus. + */ + printf("%s: Connection stuck awaiting busfree or " + "Identify Msg.\n", ahd_name(ahd)); + goto bus_reset; + } else if (ahd_search_qinfifo(ahd, target, channel, lun, + scb->hscb->tag, ROLE_INITIATOR, + /*status*/0, SEARCH_COUNT) > 0) { + + /* + * We haven't even gone out on the bus + * yet, so the timeout must be due to + * some other command. Reset the timer + * and go on. + */ + ahd_other_scb_timeout(ahd, scb, scb); + } else { + /* + * This SCB is for a disconnected transaction + * and we haven't found a better candidate on + * the bus to explain this timeout. + */ + ahd_set_recoveryscb(ahd, scb); + + /* + * Actually re-queue this SCB in an attempt + * to select the device before it reconnects. + * In either case (selection or reselection), + * we will now issue a target reset to the + * timed-out device. + * + * Set the MK_MESSAGE control bit indicating + * that we desire to send a message. We + * also set the disconnected flag since + * in the paging case there is no guarantee + * that our SCB control byte matches the + * version on the card. We don't want the + * sequencer to abort the command thinking + * an unsolicited reselection occurred. + */ + scb->flags |= SCB_DEVICE_RESET; + scb->hscb->cdb_len = 0; + scb->hscb->task_attribute = 0; + scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK; + + ahd_set_scbptr(ahd, SCB_GET_TAG(scb)); + if ((scb->flags & SCB_PACKETIZED) != 0) { + /* + * Mark the SCB has having an outstanding + * task management function. Should the command + * complete normally before the task management + * function can be sent, the host will be + * notified to abort our requeued SCB. + */ + ahd_outb(ahd, SCB_TASK_MANAGEMENT, + scb->hscb->task_management); + } else { + /* + * If non-packetized, set the MK_MESSAGE control + * bit indicating that we desire to send a + * message. We also set the disconnected flag + * since there is no guarantee that our SCB + * control byte matches the version on the + * card. We don't want the sequencer to abort + * the command thinking an unsolicited + * reselection occurred. + */ + scb->hscb->control |= MK_MESSAGE|DISCONNECTED; + + /* + * The sequencer will never re-reference the + * in-core SCB. To make sure we are notified + * during reslection, set the MK_MESSAGE flag in + * the card's copy of the SCB. + */ + ahd_outb(ahd, SCB_CONTROL, + ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE); + } + + /* + * Clear out any entries in the QINFIFO first + * so we are the next SCB for this target + * to run. + */ + ahd_search_qinfifo(ahd, target, channel, lun, + SCB_LIST_NULL, ROLE_INITIATOR, + CAM_REQUEUE_REQ, SEARCH_COMPLETE); + ahd_qinfifo_requeue_tail(ahd, scb); + ahd_set_scbptr(ahd, active_scbptr); + ahd_print_path(ahd, scb); + printf("Queuing a BDR SCB\n"); + aic_scb_timer_reset(scb, 2 * 1000000); + break; + } + } + + /* + * Any remaining SCBs were not the "culprit", so remove + * them from the timeout list. The timer for these commands + * will be reset once the recovery SCB completes. + */ + while ((scb = LIST_FIRST(&ahd->timedout_scbs)) != NULL) { + + LIST_REMOVE(scb, timedout_links); + scb->flags &= ~SCB_TIMEDOUT; + } + + ahd_unpause(ahd); + ahd_unlock(ahd, &s); +} + +static void +ahd_other_scb_timeout(struct ahd_softc *ahd, struct scb *scb, + struct scb *other_scb) +{ + u_int newtimeout; + + ahd_print_path(ahd, scb); + printf("Other SCB Timeout%s", + (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0 + ? " again\n" : "\n"); + scb->flags |= SCB_OTHERTCL_TIMEOUT; + newtimeout = MAX(aic_get_timeout(other_scb), + aic_get_timeout(scb)); + aic_scb_timer_reset(scb, newtimeout); +} + /**************************** Flexport Logic **********************************/ /* * Read count 16bit words from 16bit word address start_addr from the @@ -8830,9 +9503,9 @@ { int cnt; - cnt = 20; + cnt = 5000; while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt) - ahd_delay(5); + aic_delay(5); if (cnt == 0) return (ETIMEDOUT); @@ -8974,7 +9647,7 @@ AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); cnt = 1000000 * 2 / 5; while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt) - ahd_delay(5); + aic_delay(5); if (cnt == 0) return (ETIMEDOUT); @@ -9176,13 +9849,9 @@ if ((ahd->features & AHD_MULTI_TID) != 0) { u_int targid_mask; - targid_mask = ahd_inb(ahd, TARGID) - | (ahd_inb(ahd, TARGID + 1) << 8); - + targid_mask = ahd_inw(ahd, TARGID); targid_mask |= target_mask; - ahd_outb(ahd, TARGID, targid_mask); - ahd_outb(ahd, TARGID+1, (targid_mask >> 8)); - + ahd_outw(ahd, TARGID, targid_mask); ahd_update_scsiid(ahd, targid_mask); } else { u_int our_id; @@ -9296,14 +9965,9 @@ if (ahd->features & AHD_MULTI_TID) { u_int targid_mask; - targid_mask = ahd_inb(ahd, TARGID) - | (ahd_inb(ahd, TARGID + 1) - << 8); - + targid_mask = ahd_inw(ahd, TARGID); targid_mask &= ~target_mask; - ahd_outb(ahd, TARGID, targid_mask); - ahd_outb(ahd, TARGID+1, - (targid_mask >> 8)); + ahd_outw(ahd, TARGID, targid_mask); ahd_update_scsiid(ahd, targid_mask); } } diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_inline.h linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_inline.h --- linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_inline.h Wed Jul 30 09:18:49 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_inline.h Tue Feb 10 01:47:04 2004 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#50 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#56 $ * * $FreeBSD$ */ @@ -250,15 +250,15 @@ struct ahd_dma64_seg *sg; sg = (struct ahd_dma64_seg *)sgptr; - sg->addr = ahd_htole64(addr); - sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0)); + sg->addr = aic_htole64(addr); + sg->len = aic_htole32(len | (last ? AHD_DMA_LAST_SEG : 0)); return (sg + 1); } else { struct ahd_dma_seg *sg; sg = (struct ahd_dma_seg *)sgptr; - sg->addr = ahd_htole32(addr & 0xFFFFFFFF); - sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000) + sg->addr = aic_htole32(addr & 0xFFFFFFFF); + sg->len = aic_htole32(len | ((addr >> 8) & 0x7F000000) | (last ? AHD_DMA_LAST_SEG : 0)); return (sg + 1); } @@ -273,7 +273,7 @@ /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */ scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE; } else { - if (ahd_get_transfer_length(scb) & 0x01) + if (aic_get_transfer_length(scb) & 0x01) scb->hscb->task_attribute = SCB_XFERLEN_ODD; else scb->hscb->task_attribute = 0; @@ -282,7 +282,7 @@ if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0) scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr = - ahd_htole32(scb->sense_busaddr); + aic_htole32(scb->sense_busaddr); } static __inline void @@ -308,8 +308,8 @@ if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) { uint64_t high_addr; - high_addr = ahd_le32toh(sg->len) & 0x7F000000; - scb->hscb->dataptr |= ahd_htole64(high_addr << 8); + high_addr = aic_le32toh(sg->len) & 0x7F000000; + scb->hscb->dataptr |= aic_htole64(high_addr << 8); } scb->hscb->datacnt = sg->len; } @@ -319,13 +319,13 @@ * sequencer will clear as soon as a data transfer * occurs. */ - scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID); + scb->hscb->sgptr = aic_htole32(scb->sg_list_busaddr|SG_FULL_RESID); } static __inline void ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb) { - scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL); + scb->hscb->sgptr = aic_htole32(SG_LIST_NULL); scb->hscb->dataptr = 0; scb->hscb->datacnt = 0; } @@ -383,7 +383,7 @@ static __inline void ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op) { - ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat, + aic_dmamap_sync(ahd, ahd->scb_data.hscb_dmat, scb->hscb_map->dmamap, /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr, /*len*/sizeof(*scb->hscb), op); @@ -395,7 +395,7 @@ if (scb->sg_count == 0) return; - ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat, + aic_dmamap_sync(ahd, ahd->scb_data.sg_dmat, scb->sg_map->dmamap, /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd), /*len*/ahd_sg_size(ahd) * scb->sg_count, op); @@ -404,7 +404,7 @@ static __inline void ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op) { - ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat, + aic_dmamap_sync(ahd, ahd->scb_data.sense_dmat, scb->sense_map->dmamap, /*offset*/scb->sense_busaddr, /*len*/AHD_SENSE_BUFSIZE, op); @@ -455,6 +455,8 @@ static __inline u_int ahd_inw_scbram(struct ahd_softc *ahd, u_int offset); static __inline uint32_t ahd_inl_scbram(struct ahd_softc *ahd, u_int offset); +static __inline uint64_t + ahd_inq_scbram(struct ahd_softc *ahd, u_int offset); static __inline void ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb); static __inline void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb); @@ -470,7 +472,7 @@ { uint32_t sgptr; - sgptr = ahd_le32toh(scb->hscb->sgptr); + sgptr = aic_le32toh(scb->hscb->sgptr); if ((sgptr & SG_STATUS_VALID) != 0) ahd_handle_scb_status(ahd, scb); else @@ -486,7 +488,7 @@ { uint32_t sgptr; - sgptr = ahd_le32toh(scb->hscb->sgptr); + sgptr = aic_le32toh(scb->hscb->sgptr); if ((sgptr & SG_STATUS_VALID) != 0) ahd_calc_residual(ahd, scb); } @@ -520,12 +522,21 @@ static __inline uint16_t ahd_inw(struct ahd_softc *ahd, u_int port) { + /* + * Read high byte first as some registers increment + * or have other side effects when the low byte is + * read. + */ return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port)); } static __inline void ahd_outw(struct ahd_softc *ahd, u_int port, u_int value) { + /* + * Write low byte first to accomodate registers + * such as PRGMCNT where the order maters. + */ ahd_outb(ahd, port, value & 0xFF); ahd_outb(ahd, port+1, (value >> 8) & 0xFF); } @@ -697,10 +708,15 @@ static __inline uint32_t ahd_inl_scbram(struct ahd_softc *ahd, u_int offset) { - return (ahd_inb_scbram(ahd, offset) - | (ahd_inb_scbram(ahd, offset+1) << 8) - | (ahd_inb_scbram(ahd, offset+2) << 16) - | (ahd_inb_scbram(ahd, offset+3) << 24)); + return (ahd_inw_scbram(ahd, offset) + | (ahd_inw_scbram(ahd, offset+2) << 16)); +} + +static __inline uint64_t +ahd_inq_scbram(struct ahd_softc *ahd, u_int offset) +{ + return (ahd_inl_scbram(ahd, offset) + | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32); } static __inline struct scb * @@ -720,7 +736,8 @@ static __inline void ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) { - struct hardware_scb *q_hscb; + struct hardware_scb *q_hscb; + struct map_node *q_hscb_map; uint32_t saved_hscb_busaddr; /* @@ -736,6 +753,7 @@ * locate the correct SCB by SCB_TAG. */ q_hscb = ahd->next_queued_hscb; + q_hscb_map = ahd->next_queued_hscb_map; saved_hscb_busaddr = q_hscb->hscb_busaddr; memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); q_hscb->hscb_busaddr = saved_hscb_busaddr; @@ -743,7 +761,9 @@ /* Now swap HSCB pointers. */ ahd->next_queued_hscb = scb->hscb; + ahd->next_queued_hscb_map = scb->hscb_map; scb->hscb = q_hscb; + scb->hscb_map = q_hscb_map; /* Now define the mapping from tag to SCB in the scbindex */ ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; @@ -783,13 +803,13 @@ if ((ahd_debug & AHD_SHOW_QUEUE) != 0) { uint64_t host_dataptr; - host_dataptr = ahd_le64toh(scb->hscb->dataptr); + host_dataptr = aic_le64toh(scb->hscb->dataptr); printf("%s: Queueing SCB 0x%x bus addr 0x%x - 0x%x%x/0x%x\n", ahd_name(ahd), - SCB_GET_TAG(scb), ahd_le32toh(scb->hscb->hscb_busaddr), + SCB_GET_TAG(scb), aic_le32toh(scb->hscb->hscb_busaddr), (u_int)((host_dataptr >> 32) & 0xFFFFFFFF), (u_int)(host_dataptr & 0xFFFFFFFF), - ahd_le32toh(scb->hscb->datacnt)); + aic_le32toh(scb->hscb->datacnt)); } #endif /* Tell the adapter about the newly queued SCB */ @@ -817,8 +837,9 @@ static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) { - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - /*offset*/0, /*len*/AHC_SCB_MAX * sizeof(uint16_t), op); + aic_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + /*offset*/0, + /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op); } static __inline void @@ -826,8 +847,8 @@ { #ifdef AHD_TARGET_MODE if ((ahd->flags & AHD_TARGETROLE) != 0) { - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap, + aic_dmamap_sync(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap, ahd_targetcmd_offset(ahd, 0), sizeof(struct target_cmd) * AHD_TMODE_CMDS, op); @@ -847,17 +868,17 @@ u_int retval; retval = 0; - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - /*offset*/ahd->qoutfifonext, /*len*/2, - BUS_DMASYNC_POSTREAD); - if ((ahd->qoutfifo[ahd->qoutfifonext] - & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) + aic_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo), + /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD); + if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag + == ahd->qoutfifonext_valid_tag) retval |= AHD_RUN_QOUTFIFO; #ifdef AHD_TARGET_MODE if ((ahd->flags & AHD_TARGETROLE) != 0 && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) { - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap, + aic_dmamap_sync(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap, ahd_targetcmd_offset(ahd, ahd->tqinfifofnext), /*len*/sizeof(struct target_cmd), BUS_DMASYNC_POSTREAD); diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_osm.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_osm.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_osm.c Wed Jul 30 09:18:49 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_osm.c Tue Feb 10 01:47:04 2004 @@ -1,7 +1,7 @@ /* * Adaptec AIC79xx device driver for Linux. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#169 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#201 $ * * -------------------------------------------------------------------------- * Copyright (c) 1994-2000 Justin T. Gibbs. @@ -52,9 +52,7 @@ */ #include "aiclib.c" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) #include /* __setup */ -#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "sd.h" /* For geometry detection */ @@ -62,19 +60,27 @@ #include /* For fetching system memory size */ +/************************* Magic SysReq Support *******************************/ +static struct aic_sysrq_key_op ahd_sysrq_op = +{ + aic_sysrq_handler, + "aic79xxstatedump", + "Dump aic79xx controller information to Console" +}; + +static int ahd_sysrq_key; + +/***************************** Global Data ************************************/ +/* + * Driver Initialization Status. Used by ahd_linux_exit(). + */ +int ahd_init_status; + /* * Lock protecting manipulation of the ahd softc list. */ spinlock_t ahd_list_spinlock; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -struct proc_dir_entry proc_scsi_aic79xx = { - PROC_SCSI_AIC79XX, 7, "aic79xx", - S_IFDIR | S_IRUGO | S_IXUGO, 2, - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; -#endif - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* For dynamic sglist size calculation. */ u_int ahd_linux_nseg; @@ -425,7 +431,7 @@ static char dummy_buffer[60] = "Please don't trounce on me insmod!!\n"; MODULE_AUTHOR("Maintainer: Justin T. Gibbs "); -MODULE_DESCRIPTION("Adaptec Aic77XX/78XX SCSI Host Bus Adapter driver"); +MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver"); #ifdef MODULE_LICENSE MODULE_LICENSE("Dual BSD/GPL"); #endif @@ -433,6 +439,7 @@ MODULE_PARM_DESC(aic79xx, "period delimited, options string.\n" " verbose Enable verbose/diagnostic logging\n" +" attach_HostRAID: Attach to controllers in HostRAID mode\n" " allow_memio Allow device registers to be memory mapped\n" " debug Bitmask of debug values to enable\n" " no_reset Supress initial bus resets\n" @@ -466,33 +473,34 @@ #endif static void ahd_linux_handle_scsi_status(struct ahd_softc *, - struct ahd_linux_device *, + struct aic_linux_device *, struct scb *); static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, Scsi_Cmnd *cmd); static void ahd_linux_filter_inquiry(struct ahd_softc *ahd, struct ahd_devinfo *devinfo); +static int __init ahd_linux_init(void); +static void ahd_linux_exit(void); static void ahd_linux_dev_timed_unfreeze(u_long arg); static void ahd_linux_sem_timeout(u_long arg); static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); static void ahd_linux_size_nseg(void); static void ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd); static void ahd_linux_start_dv(struct ahd_softc *ahd); -static void ahd_linux_dv_timeout(struct scsi_cmnd *cmd); static int ahd_linux_dv_thread(void *data); static void ahd_linux_kill_dv_thread(struct ahd_softc *ahd); static void ahd_linux_dv_target(struct ahd_softc *ahd, u_int target); static void ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ); + struct aic_linux_target *targ); static void ahd_linux_dv_fill_cmd(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo); static void ahd_linux_dv_inq(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ, + struct aic_linux_target *targ, u_int request_length); static void ahd_linux_dv_tur(struct ahd_softc *ahd, struct scsi_cmnd *cmd, @@ -500,19 +508,19 @@ static void ahd_linux_dv_rebd(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ); + struct aic_linux_target *targ); static void ahd_linux_dv_web(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ); + struct aic_linux_target *targ); static void ahd_linux_dv_reb(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ); + struct aic_linux_target *targ); static void ahd_linux_dv_su(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ); + struct aic_linux_target *targ); static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo); @@ -520,103 +528,57 @@ struct ahd_devinfo *devinfo); static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo); -static void ahd_linux_dv_complete(Scsi_Cmnd *cmd); -static void ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ); +static void ahd_linux_generate_dv_pattern(struct aic_linux_target *targ); static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo); static u_int ahd_linux_user_dv_setting(struct ahd_softc *ahd); static void ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd); -static void ahd_linux_device_queue_depth(struct ahd_softc *ahd, - struct ahd_linux_device *dev); -static struct ahd_linux_target* ahd_linux_alloc_target(struct ahd_softc*, +static void aic_linux_device_queue_depth(struct ahd_softc *ahd, + struct aic_linux_device *dev); +static struct aic_linux_target* ahd_linux_alloc_target(struct ahd_softc*, u_int, u_int); static void ahd_linux_free_target(struct ahd_softc*, - struct ahd_linux_target*); -static struct ahd_linux_device* ahd_linux_alloc_device(struct ahd_softc*, - struct ahd_linux_target*, + struct aic_linux_target*); +static struct aic_linux_device* ahd_linux_alloc_device(struct ahd_softc*, + struct aic_linux_target*, u_int); static void ahd_linux_free_device(struct ahd_softc*, - struct ahd_linux_device*); -static void ahd_linux_run_device_queue(struct ahd_softc*, - struct ahd_linux_device*); + struct aic_linux_device*); static void ahd_linux_setup_tag_info_global(char *p); static aic_option_callback_t ahd_linux_setup_tag_info; static aic_option_callback_t ahd_linux_setup_rd_strm_info; static aic_option_callback_t ahd_linux_setup_dv; static aic_option_callback_t ahd_linux_setup_iocell_info; static int ahd_linux_next_unit(void); -static void ahd_runq_tasklet(unsigned long data); static int aic79xx_setup(char *c); /****************************** Inlines ***************************************/ static __inline void ahd_schedule_completeq(struct ahd_softc *ahd); -static __inline void ahd_schedule_runq(struct ahd_softc *ahd); -static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd); -static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd); -static __inline struct ahd_linux_device* +static __inline struct aic_linux_device* ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target, u_int lun, int alloc); -static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd); -static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd, - struct ahd_linux_device *dev); -static __inline struct ahd_linux_device * - ahd_linux_next_device_to_run(struct ahd_softc *ahd); -static __inline void ahd_linux_run_device_queues(struct ahd_softc *ahd); static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*); - -static __inline int ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb, - struct ahd_dma_seg *sg, - bus_addr_t addr, bus_size_t len); +static __inline struct ahd_dma_seg* + ahd_linux_sg_setup(struct ahd_softc *ahd, struct scb *scb, + struct ahd_dma_seg *sg, bus_addr_t addr, + bus_size_t len, int last_seg); static __inline void ahd_schedule_completeq(struct ahd_softc *ahd) { - if ((ahd->platform_data->flags & AHD_RUN_CMPLT_Q_TIMER) == 0) { - ahd->platform_data->flags |= AHD_RUN_CMPLT_Q_TIMER; + if ((ahd->platform_data->flags & AIC_RUN_CMPLT_Q_TIMER) == 0) { + ahd->platform_data->flags |= AIC_RUN_CMPLT_Q_TIMER; ahd->platform_data->completeq_timer.expires = jiffies; add_timer(&ahd->platform_data->completeq_timer); } } -/* - * Must be called with our lock held. - */ -static __inline void -ahd_schedule_runq(struct ahd_softc *ahd) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_schedule(&ahd->platform_data->runq_tasklet); -#else - /* - * Tasklets are not available, so run inline. - */ - ahd_runq_tasklet((unsigned long)ahd); -#endif -} - -static __inline -void ahd_setup_runq_tasklet(struct ahd_softc *ahd) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_init(&ahd->platform_data->runq_tasklet, ahd_runq_tasklet, - (unsigned long)ahd); -#endif -} - -static __inline void -ahd_teardown_runq_tasklet(struct ahd_softc *ahd) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_kill(&ahd->platform_data->runq_tasklet); -#endif -} - -static __inline struct ahd_linux_device* +static __inline struct aic_linux_device* ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target, u_int lun, int alloc) { - struct ahd_linux_target *targ; - struct ahd_linux_device *dev; + struct aic_linux_target *targ; + struct aic_linux_device *dev; u_int target_offset; target_offset = target; @@ -638,15 +600,13 @@ } #define AHD_LINUX_MAX_RETURNED_ERRORS 4 -static struct ahd_cmd * +static struct aic_cmd * ahd_linux_run_complete_queue(struct ahd_softc *ahd) { - struct ahd_cmd *acmd; - u_long done_flags; + struct aic_cmd *acmd; int with_errors; with_errors = 0; - ahd_done_lock(ahd, &done_flags); while ((acmd = TAILQ_FIRST(&ahd->platform_data->completeq)) != NULL) { Scsi_Cmnd *cmd; @@ -666,57 +626,13 @@ acmd, acmd_links.tqe); cmd = &acmd_scsi_cmd(acmd); cmd->host_scribble = NULL; - if (ahd_cmd_get_transaction_status(cmd) != DID_OK - || (cmd->result & 0xFF) != SCSI_STATUS_OK) - with_errors++; - cmd->scsi_done(cmd); + with_errors++; } - ahd_done_unlock(ahd, &done_flags); return (acmd); } static __inline void -ahd_linux_check_device_queue(struct ahd_softc *ahd, - struct ahd_linux_device *dev) -{ - if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) != 0 - && dev->active == 0) { - dev->flags &= ~AHD_DEV_FREEZE_TIL_EMPTY; - dev->qfrozen--; - } - - if (TAILQ_FIRST(&dev->busyq) == NULL - || dev->openings == 0 || dev->qfrozen != 0) - return; - - ahd_linux_run_device_queue(ahd, dev); -} - -static __inline struct ahd_linux_device * -ahd_linux_next_device_to_run(struct ahd_softc *ahd) -{ - - if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0 - || (ahd->platform_data->qfrozen != 0 - && AHD_DV_SIMQ_FROZEN(ahd) == 0)) - return (NULL); - return (TAILQ_FIRST(&ahd->platform_data->device_runq)); -} - -static __inline void -ahd_linux_run_device_queues(struct ahd_softc *ahd) -{ - struct ahd_linux_device *dev; - - while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) { - TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links); - dev->flags &= ~AHD_DEV_ON_RUN_LIST; - ahd_linux_check_device_queue(ahd, dev); - } -} - -static __inline void ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) { Scsi_Cmnd *cmd; @@ -729,34 +645,22 @@ struct scatterlist *sg; sg = (struct scatterlist *)cmd->request_buffer; - pci_unmap_sg(ahd->dev_softc, sg, cmd->use_sg, direction); + aic_unmap_sg(ahd, sg, cmd->use_sg, direction); } else if (cmd->request_bufflen != 0) { - pci_unmap_single(ahd->dev_softc, + aic_unmap_single(ahd, scb->platform_data->buf_busaddr, cmd->request_bufflen, direction); } } -static __inline int -ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb, - struct ahd_dma_seg *sg, bus_addr_t addr, bus_size_t len) +static __inline struct ahd_dma_seg* +ahd_linux_sg_setup(struct ahd_softc *ahd, struct scb *scb, + struct ahd_dma_seg *sg, bus_addr_t addr, + bus_size_t len, int last_seg) { - int consumed; - - if ((scb->sg_count + 1) > AHD_NSEG) - panic("Too few segs for dma mapping. " - "Increase AHD_NSEG\n"); - - consumed = 1; - sg->addr = ahd_htole32(addr & 0xFFFFFFFF); + sg = ahd_sg_setup(ahd, scb, sg, addr, len, last_seg); scb->platform_data->xfer_len += len; - - if (sizeof(bus_addr_t) > 4 - && (ahd->flags & AHD_39BIT_ADDRESSING) != 0) - len |= (addr >> 8) & AHD_SG_HIGH_ADDR_MASK; - - sg->len = ahd_htole32(len); - return (consumed); + return (sg); } /******************************** Macros **************************************/ @@ -797,7 +701,7 @@ * number of segments needed for the current transfer. Since the code that * sizes the SCSI malloc pool does not take into consideration fragmentation * of the pool, executing transactions numbering just a fraction of our - * concurrent transaction limit with SG list lengths aproaching AHC_NSEG will + * concurrent transaction limit with SG list lengths aproaching AHD_NSEG will * quickly depleat the SCSI malloc pool of usable space. Unfortunately, the * mid-layer does not properly handle this scsi malloc failures for the S/G * array and the result can be a lockup of the I/O subsystem. We try to size @@ -848,6 +752,165 @@ #endif } +/************************** Error Recovery ************************************/ +static int ahd_linux_recovery_thread(void *arg); + +static int +ahd_linux_recovery_thread(void *arg) +{ + struct ahd_softc *ahd; + u_long s; + + ahd = (struct ahd_softc *)arg; + + /* + * Complete thread creation. + */ + lock_kernel(); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60) + /* + * Don't care about any signals. + */ + siginitsetinv(¤t->blocked, 0); + + daemonize(); + sprintf(current->comm, "ahd_recovery_%d", ahd->unit); +#else + daemonize("ahd_recovery_%d", ahd->unit); +#endif + unlock_kernel(); + + while (1) { + + /* + * Use down_interruptible() rather than down() to + * avoid inclusion in the load average. + */ + down_interruptible(&ahd->platform_data->recovery_sem); + + ahd_lock(ahd, &s); + if ((ahd->flags & AHD_SHUTDOWN_RECOVERY) != 0) { + ahd_unlock(ahd, &s); + break; + } + + /* + * Don't bother the recovery handler if the + * list has been cleared by a previous run + * of the handler. This can happen when + * several SCBs timeout before our handler + * can run causing our semaphore to be up'ed + * repeatedly. The extra calls need to be + * avoided so that the recovery handler doesn't + * confuse this case with timeouts occuring + * due to interrupts failing to function. + */ + if (LIST_EMPTY(&ahd->timedout_scbs) != 0) { + ahd_unlock(ahd, &s); + continue; + } + + ahd_unlock(ahd, &s); + ahd_recover_commands(ahd); + + /* + * Process any pent up completions. + */ + ahd_lock(ahd, &s); + aic_schedule_runq(ahd); + ahd_linux_run_complete_queue(ahd); + ahd_unlock(ahd, &s); + } + up(&ahd->platform_data->recovery_ending_sem); + return(0); +} + +int +ahd_spawn_recovery_thread(struct ahd_softc *ahd) +{ + ahd->platform_data->recovery_pid = + kernel_thread(ahd_linux_recovery_thread, ahd, 0); + + if (ahd->platform_data->recovery_pid < 0) + return (-ahd->platform_data->recovery_pid); + + return (0); +} + +void +ahd_terminate_recovery_thread(struct ahd_softc *ahd) +{ + u_long s; + + ahd_lock(ahd, &s); + if (ahd->platform_data->recovery_pid != 0) { + ahd->flags |= AHD_SHUTDOWN_RECOVERY; + ahd_unlock(ahd, &s); + up(&ahd->platform_data->recovery_sem); + + /* + * Use the recovery_ending_sem as an indicator that + * the dv thread is exiting. Note that the dv + * thread must still return after performing + * the up on our semaphore before it has + * completely exited this module. Unfortunately, + * there seems to be no easy way to wait for the + * exit of a thread for which you are not the + * parent (dv threads are parented by init). + * Cross your fingers... + */ + down(&ahd->platform_data->recovery_ending_sem); + + /* + * Mark the recovery thread as already dead. This + * avoids attempting to kill it a second time. + * This is necessary because we must kill the + * our threads before calling ahd_free() in the + * module shutdown case to avoid bogus locking + * in the SCSI mid-layer, but when ahd_free() is + * called without killing the DV thread in the + * instance detach case, so ahd_platform_free() + * calls us again to verify that the DV thread + * is dead. + */ + ahd->platform_data->recovery_pid = 0; + } else { + ahd_unlock(ahd, &s); + } +} + +void +ahd_set_recoveryscb(struct ahd_softc *ahd, struct scb *scb) +{ + if ((scb->flags & SCB_RECOVERY_SCB) == 0) { + struct scb *list_scb; + + scb->flags |= SCB_RECOVERY_SCB; + + /* + * Take all queued, but not sent SCBs out of the equation. + * Also ensure that no new commands are queued to us while we + * try to fix this problem. + */ + if ((scb->platform_data->flags & AIC_RELEASE_SIMQ) == 0) { + aic_freeze_simq(ahd); + scb->platform_data->flags |= AIC_RELEASE_SIMQ; + } + + /* + * Go through all of our pending SCBs and remove + * any scheduled timeouts for them. We will reschedule + * them after we've successfully fixed this problem. + */ + LIST_FOREACH(list_scb, &ahd->pending_scbs, pending_links) { + + scsi_delete_timer(list_scb->io_ctx); + list_scb->platform_data->flags &= ~AIC_TIMEOUT_ACTIVE; + } + } +} + +/********************** Host Template Entry Points ****************************/ /* * Try to detect an Adaptec 79XX controller. */ @@ -864,17 +927,19 @@ */ spin_unlock_irq(&io_request_lock); #endif + found = 0; /* * Sanity checking of Linux SCSI data structures so * that some of our hacks^H^H^H^H^Hassumptions aren't * violated. */ - if (offsetof(struct ahd_cmd_internal, end) + if (offsetof(struct aic_cmd_internal, end) > offsetof(struct scsi_cmnd, host_scribble)) { printf("ahd_linux_detect: SCSI data structures changed.\n"); printf("ahd_linux_detect: Unable to attach\n"); - return (0); + ahd_init_status = -EINVAL; + goto done; } /* * Determine an appropriate size for our Scatter Gatther lists. @@ -894,11 +959,7 @@ "aic79xx: insmod or else it might trash certain memory areas.\n"); #endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) template->proc_name = "aic79xx"; -#else - template->proc_dir = &proc_scsi_aic79xx; -#endif /* * Initialize our softc list lock prior to @@ -907,7 +968,9 @@ ahd_list_lockinit(); #ifdef CONFIG_PCI - ahd_linux_pci_init(); + ahd_init_status = ahd_linux_pci_init(); + if (ahd_init_status != 0) + goto done; #endif /* @@ -920,6 +983,7 @@ if (ahd_linux_register_host(ahd, template) == 0) found++; } +done: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) spin_lock_irq(&io_request_lock); #endif @@ -938,7 +1002,6 @@ struct ahd_softc *ahd; u_long l; - ahd_list_lock(&l); if (host != NULL) { /* @@ -946,17 +1009,20 @@ * the free directly, but check our * list for extra sanity. */ + ahd_list_lock(&l); ahd = ahd_find_softc(*(struct ahd_softc **)host->hostdata); if (ahd != NULL) { u_long s; + TAILQ_REMOVE(&ahd_tailq, ahd, links); + ahd_list_unlock(&l); ahd_lock(ahd, &s); ahd_intr_enable(ahd, FALSE); ahd_unlock(ahd, &s); ahd_free(ahd); - } + } else + ahd_list_unlock(&l); } - ahd_list_unlock(&l); return (0); } #endif @@ -996,7 +1062,7 @@ ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) { struct ahd_softc *ahd; - struct ahd_linux_device *dev; + struct aic_linux_device *dev; u_long flags; ahd = *(struct ahd_softc **)cmd->device->host->hostdata; @@ -1006,7 +1072,7 @@ */ cmd->scsi_done = scsi_done; - ahd_midlayer_entrypoint_lock(ahd, &flags); + ahd_entrypoint_lock(ahd, &flags); /* * Close the race of a command that was in the process of @@ -1015,36 +1081,53 @@ * perform DV. */ if (ahd->platform_data->qfrozen != 0 - && AHD_DV_CMD(cmd) == 0) { + && AIC_DV_CMD(cmd) == 0) { - ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); + aic_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); ahd_linux_queue_cmd_complete(ahd, cmd); ahd_schedule_completeq(ahd); - ahd_midlayer_entrypoint_unlock(ahd, &flags); + ahd_entrypoint_unlock(ahd, &flags); return (0); } dev = ahd_linux_get_device(ahd, cmd->device->channel, cmd->device->id, cmd->device->lun, /*alloc*/TRUE); if (dev == NULL) { - ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); + + aic_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); ahd_linux_queue_cmd_complete(ahd, cmd); ahd_schedule_completeq(ahd); - ahd_midlayer_entrypoint_unlock(ahd, &flags); + ahd_entrypoint_unlock(ahd, &flags); printf("%s: aic79xx_linux_queue - Unable to allocate device!\n", ahd_name(ahd)); return (0); } - if (cmd->cmd_len > MAX_CDB_LEN) - return (-EINVAL); + + if (cmd->cmd_len > MAX_CDB_LEN) { + + aic_cmd_set_transaction_status(cmd, CAM_REQ_INVALID); + ahd_linux_queue_cmd_complete(ahd, cmd); + ahd_schedule_completeq(ahd); + ahd_entrypoint_unlock(ahd, &flags); + printf("%s: aic79xx_linux_queue -" + "CDB length of %d exceeds max!\n", + ahd_name(ahd), cmd->cmd_len); + return (0); + } + + /* + * We perform our own timeout handling. + */ + scsi_delete_timer(cmd); + cmd->result = CAM_REQ_INPROG << 16; - TAILQ_INSERT_TAIL(&dev->busyq, (struct ahd_cmd *)cmd, acmd_links.tqe); - if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) { + TAILQ_INSERT_TAIL(&dev->busyq, (struct aic_cmd *)cmd, acmd_links.tqe); + if ((dev->flags & AIC_DEV_ON_RUN_LIST) == 0) { TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); - dev->flags |= AHD_DEV_ON_RUN_LIST; - ahd_linux_run_device_queues(ahd); + dev->flags |= AIC_DEV_ON_RUN_LIST; + aic_linux_run_device_queues(ahd); } - ahd_midlayer_entrypoint_unlock(ahd, &flags); + ahd_entrypoint_unlock(ahd, &flags); return (0); } @@ -1064,13 +1147,13 @@ ahd_linux_slave_configure(Scsi_Device *device) { struct ahd_softc *ahd; - struct ahd_linux_device *dev; + struct aic_linux_device *dev; u_long flags; ahd = *((struct ahd_softc **)device->host->hostdata); if (bootverbose) printf("%s: Slave Configure %d\n", ahd_name(ahd), device->id); - ahd_midlayer_entrypoint_lock(ahd, &flags); + ahd_entrypoint_lock(ahd, &flags); /* * Since Linux has attached to the device, configure * it so we don't free and allocate the device @@ -1080,12 +1163,12 @@ device->id, device->lun, /*alloc*/TRUE); if (dev != NULL) { - dev->flags &= ~AHD_DEV_UNCONFIGURED; - dev->flags |= AHD_DEV_SLAVE_CONFIGURED; + dev->flags &= ~AIC_DEV_UNCONFIGURED; + dev->flags |= AIC_DEV_SLAVE_CONFIGURED; dev->scsi_device = device; - ahd_linux_device_queue_depth(ahd, dev); + aic_linux_device_queue_depth(ahd, dev); } - ahd_midlayer_entrypoint_unlock(ahd, &flags); + ahd_entrypoint_unlock(ahd, &flags); return (0); } @@ -1093,13 +1176,13 @@ ahd_linux_slave_destroy(Scsi_Device *device) { struct ahd_softc *ahd; - struct ahd_linux_device *dev; + struct aic_linux_device *dev; u_long flags; ahd = *((struct ahd_softc **)device->host->hostdata); if (bootverbose) printf("%s: Slave Destroy %d\n", ahd_name(ahd), device->id); - ahd_midlayer_entrypoint_lock(ahd, &flags); + ahd_entrypoint_lock(ahd, &flags); dev = ahd_linux_get_device(ahd, device->channel, device->id, device->lun, /*alloc*/FALSE); @@ -1112,14 +1195,13 @@ * the refcounting process. */ if (dev != NULL - && (dev->flags & AHD_DEV_SLAVE_CONFIGURED) != 0) { - dev->flags |= AHD_DEV_UNCONFIGURED; + && (dev->flags & AIC_DEV_SLAVE_CONFIGURED) != 0) { + dev->flags |= AIC_DEV_UNCONFIGURED; if (TAILQ_EMPTY(&dev->busyq) - && dev->active == 0 - && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0) + && dev->active == 0) ahd_linux_free_device(ahd, dev); } - ahd_midlayer_entrypoint_unlock(ahd, &flags); + ahd_entrypoint_unlock(ahd, &flags); } #else /* @@ -1156,7 +1238,7 @@ continue; if (device->host == host) { - struct ahd_linux_device *dev; + struct aic_linux_device *dev; /* * Since Linux has attached to the device, configure @@ -1167,13 +1249,13 @@ device->id, device->lun, /*alloc*/TRUE); if (dev != NULL) { - dev->flags &= ~AHD_DEV_UNCONFIGURED; + dev->flags &= ~AIC_DEV_UNCONFIGURED; dev->scsi_device = device; - ahd_linux_device_queue_depth(ahd, dev); + aic_linux_device_queue_depth(ahd, dev); device->queue_depth = dev->openings + dev->active; - if ((dev->flags & (AHD_DEV_Q_BASIC - | AHD_DEV_Q_TAGGED)) == 0) { + if ((dev->flags & (AIC_DEV_Q_BASIC + | AIC_DEV_Q_TAGGED)) == 0) { /* * We allow the OS to queue 2 untagged * transactions to us at any time even @@ -1262,9 +1344,9 @@ ahd_linux_abort(Scsi_Cmnd *cmd) { struct ahd_softc *ahd; - struct ahd_cmd *acmd; - struct ahd_cmd *list_acmd; - struct ahd_linux_device *dev; + struct aic_cmd *acmd; + struct aic_cmd *list_acmd; + struct aic_linux_device *dev; struct scb *pending_scb; u_long s; u_int saved_scbptr; @@ -1282,7 +1364,7 @@ paused = FALSE; wait = FALSE; ahd = *(struct ahd_softc **)cmd->device->host->hostdata; - acmd = (struct ahd_cmd *)cmd; + acmd = (struct aic_cmd *)cmd; printf("%s:%d:%d:%d: Attempting to abort cmd %p:", ahd_name(ahd), cmd->device->channel, cmd->device->id, @@ -1305,7 +1387,7 @@ * by acquiring either the io_request_lock or our own * lock, this *should* be safe. */ - ahd_midlayer_entrypoint_lock(ahd, &s); + ahd_entrypoint_lock(ahd, &s); /* * First determine if we currently own this command. @@ -1341,6 +1423,17 @@ cmd->device->lun); TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe); cmd->result = DID_ABORT << 16; + /* + * The completion handler believes that + * commands without active timers running + * have lost the race of completing before + * their timer expires. Since commands in + * our busy queues do not have timers running, + * appease the mid-layer by adding a timer + * now. This timer will be immediately + * canceled by the midlayer. + */ + scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout); ahd_linux_queue_cmd_complete(ahd, cmd); retval = SUCCESS; goto done; @@ -1516,7 +1609,7 @@ struct timer_list timer; int ret; - pending_scb->platform_data->flags |= AHD_SCB_UP_EH_SEM; + pending_scb->platform_data->flags |= AIC_SCB_UP_EH_SEM; spin_unlock_irq(&ahd->platform_data->spin_lock); init_timer(&timer); timer.data = (u_long)pending_scb; @@ -1533,9 +1626,9 @@ } spin_lock_irq(&ahd->platform_data->spin_lock); } - ahd_schedule_runq(ahd); + aic_schedule_runq(ahd); ahd_linux_run_complete_queue(ahd); - ahd_midlayer_entrypoint_unlock(ahd, &s); + ahd_entrypoint_unlock(ahd, &s); return (retval); } @@ -1554,7 +1647,7 @@ { struct ahd_softc *ahd; struct scsi_cmnd *recovery_cmd; - struct ahd_linux_device *dev; + struct aic_linux_device *dev; struct ahd_initiator_tinfo *tinfo; struct ahd_tmode_tstate *tstate; struct scb *scb; @@ -1574,16 +1667,16 @@ ahd_name(ahd), cmd->device->channel, cmd->device->id, cmd->device->lun, cmd); #endif - ahd_midlayer_entrypoint_lock(ahd, &s); + ahd_entrypoint_lock(ahd, &s); dev = ahd_linux_get_device(ahd, cmd->device->channel, cmd->device->id, cmd->device->lun, /*alloc*/FALSE); if (dev == NULL) { - ahd_midlayer_entrypoint_unlock(ahd, &s); + ahd_entrypoint_unlock(ahd, &s); return (FAILED); } if ((scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX)) == NULL) { - ahd_midlayer_entrypoint_unlock(ahd, &s); + ahd_entrypoint_unlock(ahd, &s); return (FAILED); } tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, @@ -1592,9 +1685,11 @@ recovery_cmd->host_scribble = (char *)scb; scb->io_ctx = recovery_cmd; scb->platform_data->dev = dev; + scb->platform_data->flags = 0; scb->sg_count = 0; - ahd_set_residual(scb, 0); - ahd_set_sense_residual(scb, 0); + aic_set_residual(scb, 0); + aic_set_sense_residual(scb, 0); + scb->platform_data->xfer_len = 0; hscb = scb->hscb; hscb->control = 0; hscb->scsiid = BUILD_SCSIID(ahd, cmd); @@ -1613,7 +1708,7 @@ LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); ahd_queue_scb(ahd, scb); - scb->platform_data->flags |= AHD_SCB_UP_EH_SEM; + scb->platform_data->flags |= AIC_SCB_UP_EH_SEM; spin_unlock_irq(&ahd->platform_data->spin_lock); init_timer(&timer); timer.data = (u_long)scb; @@ -1629,9 +1724,9 @@ retval = FAILED; } spin_lock_irq(&ahd->platform_data->spin_lock); - ahd_schedule_runq(ahd); + aic_schedule_runq(ahd); ahd_linux_run_complete_queue(ahd); - ahd_midlayer_entrypoint_unlock(ahd, &s); + ahd_entrypoint_unlock(ahd, &s); printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval); return (retval); } @@ -1652,11 +1747,11 @@ printf("%s: Bus reset called for cmd %p\n", ahd_name(ahd), cmd); #endif - ahd_midlayer_entrypoint_lock(ahd, &s); + ahd_entrypoint_lock(ahd, &s); found = ahd_reset_channel(ahd, cmd->device->channel + 'A', /*initiate reset*/TRUE); ahd_linux_run_complete_queue(ahd); - ahd_midlayer_entrypoint_unlock(ahd, &s); + ahd_entrypoint_unlock(ahd, &s); if (bootverbose) printf("%s: SCSI bus reset delivered. " @@ -1665,213 +1760,8 @@ return (SUCCESS); } -Scsi_Host_Template aic79xx_driver_template = { - .module = THIS_MODULE, - .name = "aic79xx", - .proc_info = ahd_linux_proc_info, - .info = ahd_linux_info, - .queuecommand = ahd_linux_queue, - .eh_abort_handler = ahd_linux_abort, - .eh_device_reset_handler = ahd_linux_dev_reset, - .eh_bus_reset_handler = ahd_linux_bus_reset, -#if defined(__i386__) - .bios_param = ahd_linux_biosparam, -#endif - .can_queue = AHD_MAX_QUEUE, - .this_id = -1, - .cmd_per_lun = 2, - .use_clustering = ENABLE_CLUSTERING, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) - /* - * We can only map 16MB per-SG - * so create a sector limit of - * "16MB" in 2K sectors. - */ - .max_sectors = 8192, -#endif -#if defined CONFIG_HIGHIO || LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) -/* Assume RedHat Distribution with its different HIGHIO conventions. */ - .can_dma_32 = 1, - .single_sg_okay = 1, -#else - .highmem_io = 1, -#endif -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - .slave_alloc = ahd_linux_slave_alloc, - .slave_configure = ahd_linux_slave_configure, - .slave_destroy = ahd_linux_slave_destroy, -#else - .detect = ahd_linux_detect, - .release = ahd_linux_release, - .select_queue_depths = ahd_linux_select_queue_depth, - .use_new_eh_code = 1, -#endif -}; - -/**************************** Tasklet Handler *********************************/ - -/* - * In 2.4.X and above, this routine is called from a tasklet, - * so we must re-acquire our lock prior to executing this code. - * In all prior kernels, ahd_schedule_runq() calls this routine - * directly and ahd_schedule_runq() is called with our lock held. - */ -static void -ahd_runq_tasklet(unsigned long data) -{ - struct ahd_softc* ahd; - struct ahd_linux_device *dev; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - u_long flags; -#endif - - ahd = (struct ahd_softc *)data; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - ahd_lock(ahd, &flags); -#endif - while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) { - - TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links); - dev->flags &= ~AHD_DEV_ON_RUN_LIST; - ahd_linux_check_device_queue(ahd, dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /* Yeild to our interrupt handler */ - ahd_unlock(ahd, &flags); - ahd_lock(ahd, &flags); -#endif - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - ahd_unlock(ahd, &flags); -#endif -} - -/******************************** Bus DMA *************************************/ -int -ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, - bus_size_t alignment, bus_size_t boundary, - bus_addr_t lowaddr, bus_addr_t highaddr, - bus_dma_filter_t *filter, void *filterarg, - bus_size_t maxsize, int nsegments, - bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag) -{ - bus_dma_tag_t dmat; - - dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT); - if (dmat == NULL) - return (ENOMEM); - - /* - * Linux is very simplistic about DMA memory. For now don't - * maintain all specification information. Once Linux supplies - * better facilities for doing these operations, or the - * needs of this particular driver change, we might need to do - * more here. - */ - dmat->alignment = alignment; - dmat->boundary = boundary; - dmat->maxsize = maxsize; - *ret_tag = dmat; - return (0); -} - -void -ahd_dma_tag_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat) -{ - free(dmat, M_DEVBUF); -} - -int -ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr, - int flags, bus_dmamap_t *mapp) -{ - bus_dmamap_t map; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT); - if (map == NULL) - return (ENOMEM); - /* - * Although we can dma data above 4GB, our - * "consistent" memory is below 4GB for - * space efficiency reasons (only need a 4byte - * address). For this reason, we have to reset - * our dma mask when doing allocations. - */ - if (ahd->dev_softc != NULL) - ahd_pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF); - *vaddr = pci_alloc_consistent(ahd->dev_softc, - dmat->maxsize, &map->bus_addr); - if (ahd->dev_softc != NULL) - ahd_pci_set_dma_mask(ahd->dev_softc, - ahd->platform_data->hw_dma_mask); -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */ - /* - * At least in 2.2.14, malloc is a slab allocator so all - * allocations are aligned. We assume for these kernel versions - * that all allocations will be bellow 4Gig, physically contiguous, - * and accessible via DMA by the controller. - */ - map = NULL; /* No additional information to store */ - *vaddr = malloc(dmat->maxsize, M_DEVBUF, M_NOWAIT); -#endif - if (*vaddr == NULL) - return (ENOMEM); - *mapp = map; - return(0); -} - -void -ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat, - void* vaddr, bus_dmamap_t map) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - pci_free_consistent(ahd->dev_softc, dmat->maxsize, - vaddr, map->bus_addr); -#else - free(vaddr, M_DEVBUF); -#endif -} - -int -ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map, - void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb, - void *cb_arg, int flags) -{ - /* - * Assume for now that this will only be used during - * initialization and not for per-transaction buffer mapping. - */ - bus_dma_segment_t stack_sg; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - stack_sg.ds_addr = map->bus_addr; -#else -#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a)) - stack_sg.ds_addr = VIRT_TO_BUS(buf); -#endif - stack_sg.ds_len = dmat->maxsize; - cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); - return (0); -} - -void -ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) -{ - /* - * The map may is NULL in our < 2.3.X implementation. - */ - if (map != NULL) - free(map, M_DEVBUF); -} - -int -ahd_dmamap_unload(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) -{ - /* Nothing to do */ - return (0); -} +Scsi_Host_Template aic79xx_driver_template = + AIC_TEMPLATE_INITIALIZER("aic79xx", /*max_sectors*/8192); /********************* Platform Dependent Functions ***************************/ /* @@ -1907,19 +1797,19 @@ /* Still equal. Sort by bus/slot/func. */ if (aic79xx_reverse_scan != 0) - value = ahd_get_pci_bus(lahd->dev_softc) - - ahd_get_pci_bus(rahd->dev_softc); + value = aic_get_pci_bus(lahd->dev_softc) + - aic_get_pci_bus(rahd->dev_softc); else - value = ahd_get_pci_bus(rahd->dev_softc) - - ahd_get_pci_bus(lahd->dev_softc); + value = aic_get_pci_bus(rahd->dev_softc) + - aic_get_pci_bus(lahd->dev_softc); if (value != 0) return (value); if (aic79xx_reverse_scan != 0) - value = ahd_get_pci_slot(lahd->dev_softc) - - ahd_get_pci_slot(rahd->dev_softc); + value = aic_get_pci_slot(lahd->dev_softc) + - aic_get_pci_slot(rahd->dev_softc); else - value = ahd_get_pci_slot(rahd->dev_softc) - - ahd_get_pci_slot(lahd->dev_softc); + value = aic_get_pci_slot(rahd->dev_softc) + - aic_get_pci_slot(lahd->dev_softc); if (value != 0) return (value); @@ -2011,6 +1901,7 @@ { "extended", &aic79xx_extended }, { "no_reset", &aic79xx_no_reset }, { "verbose", &aic79xx_verbose }, + { "attach_HostRAID", &ahd_attach_to_HostRAID_controllers }, { "allow_memio", &aic79xx_allow_memio}, #ifdef AHD_DEBUG { "debug", &ahd_debug }, @@ -2082,9 +1973,7 @@ return 1; } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) __setup("aic79xx=", aic79xx_setup); -#endif uint32_t aic79xx_verbose; @@ -2096,20 +1985,23 @@ char *new_name; u_long s; u_long target; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + int error; +#endif template->name = ahd->description; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + host = scsi_host_alloc(template, sizeof(struct ahd_softc *)); +#else host = scsi_register(template, sizeof(struct ahd_softc *)); +#endif if (host == NULL) return (ENOMEM); *((struct ahd_softc **)host->hostdata) = ahd; ahd_lock(ahd, &s); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - scsi_assign_lock(host, &ahd->platform_data->spin_lock); -#elif AHD_SCSI_HAS_HOST_LOCK != 0 - host->lock = &ahd->platform_data->spin_lock; -#endif ahd->platform_data->host = host; + aic_assign_host_lock(ahd); host->can_queue = AHD_MAX_QUEUE; host->cmd_per_lun = 2; host->sg_tablesize = AHD_NSEG; @@ -2134,13 +2026,20 @@ ahd_linux_setup_user_rd_strm_settings(ahd); ahd_linux_initialize_scsi_bus(ahd); ahd_unlock(ahd, &s); + ahd_sysrq_key = aic_install_sysrq(&ahd_sysrq_op); + ahd_spawn_recovery_thread(ahd); + if (ahd->platform_data->recovery_pid < 0) { + printf("%s: Failed to create recovery thread, error= %d\n", + ahd_name(ahd), ahd->platform_data->recovery_pid); + return (-ahd->platform_data->recovery_pid); + } ahd->platform_data->dv_pid = kernel_thread(ahd_linux_dv_thread, ahd, 0); - ahd_lock(ahd, &s); if (ahd->platform_data->dv_pid < 0) { printf("%s: Failed to create DV thread, error= %d\n", ahd_name(ahd), ahd->platform_data->dv_pid); return (-ahd->platform_data->dv_pid); } + ahd_lock(ahd, &s); /* * Initially allocate *all* of our linux target objects * so that the DV thread will scan them all in parallel @@ -2160,7 +2059,7 @@ * It is expected that either an external application * or a modified kernel will be used to probe this * ID if it is appropriate. To accommodate these - * installations, ahc_linux_alloc_target() will allocate + * installations, ahd_linux_alloc_target() will allocate * for our ID if asked to do so. */ if (target == ahd->our_id) @@ -2173,7 +2072,10 @@ ahd_unlock(ahd, &s); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - scsi_add_host(host, &ahd->dev_softc->dev); + error = scsi_add_host(host, ahd->dev_softc); + if (error != 0) + return (-error); + scsi_scan_host(host); #endif return (0); } @@ -2248,17 +2150,6 @@ ahd_update_neg_request(ahd, &devinfo, tstate, tinfo, AHD_NEG_ALWAYS); } - /* Give the bus some time to recover */ - if ((ahd->flags & AHD_RESET_BUS_A) != 0) { - ahd_freeze_simq(ahd); - init_timer(&ahd->platform_data->reset_timer); - ahd->platform_data->reset_timer.data = (u_long)ahd; - ahd->platform_data->reset_timer.expires = - jiffies + (AIC79XX_RESET_DELAY * HZ)/1000; - ahd->platform_data->reset_timer.function = - (ahd_linux_callback_t *)ahd_release_simq; - add_timer(&ahd->platform_data->reset_timer); - } } int @@ -2271,24 +2162,23 @@ memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data)); TAILQ_INIT(&ahd->platform_data->completeq); TAILQ_INIT(&ahd->platform_data->device_runq); - ahd->platform_data->irq = AHD_LINUX_NOIRQ; + ahd->platform_data->irq = AIC_LINUX_NOIRQ; ahd->platform_data->hw_dma_mask = 0xFFFFFFFF; ahd_lockinit(ahd); - ahd_done_lockinit(ahd); + init_timer(&ahd->platform_data->bus_settle_timer); + ahd->platform_data->bus_settle_timer.data = (u_long)ahd; + ahd->platform_data->bus_settle_timer.function = + (aic_linux_callback_t *)aic_bus_settle_complete; init_timer(&ahd->platform_data->completeq_timer); ahd->platform_data->completeq_timer.data = (u_long)ahd; ahd->platform_data->completeq_timer.function = - (ahd_linux_callback_t *)ahd_linux_thread_run_complete_queue; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) + (aic_linux_callback_t *)ahd_linux_thread_run_complete_queue; init_MUTEX_LOCKED(&ahd->platform_data->eh_sem); init_MUTEX_LOCKED(&ahd->platform_data->dv_sem); init_MUTEX_LOCKED(&ahd->platform_data->dv_cmd_sem); -#else - ahd->platform_data->eh_sem = MUTEX_LOCKED; - ahd->platform_data->dv_sem = MUTEX_LOCKED; - ahd->platform_data->dv_cmd_sem = MUTEX_LOCKED; -#endif - ahd_setup_runq_tasklet(ahd); + init_MUTEX_LOCKED(&ahd->platform_data->recovery_sem); + init_MUTEX_LOCKED(&ahd->platform_data->recovery_ending_sem); + aic_setup_tasklets(ahd); ahd->seltime = (aic79xx_seltime & 0x3) << 4; return (0); } @@ -2296,19 +2186,22 @@ void ahd_platform_free(struct ahd_softc *ahd) { - struct ahd_linux_target *targ; - struct ahd_linux_device *dev; + struct aic_linux_target *targ; + struct aic_linux_device *dev; int i, j; + aic_remove_sysrq(ahd_sysrq_key, &ahd_sysrq_op); if (ahd->platform_data != NULL) { del_timer_sync(&ahd->platform_data->completeq_timer); ahd_linux_kill_dv_thread(ahd); - ahd_teardown_runq_tasklet(ahd); + aic_teardown_tasklets(ahd); if (ahd->platform_data->host != NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) scsi_remove_host(ahd->platform_data->host); -#endif + scsi_host_put(ahd->platform_data->host); +#else scsi_unregister(ahd->platform_data->host); +#endif } /* destroy all of the device and target objects */ @@ -2322,6 +2215,7 @@ if (targ->devices[j] == NULL) continue; dev = targ->devices[j]; + del_timer_sync(&dev->timer); ahd_linux_free_device(ahd, dev); } /* @@ -2332,7 +2226,7 @@ } } - if (ahd->platform_data->irq != AHD_LINUX_NOIRQ) + if (ahd->platform_data->irq != AIC_LINUX_NOIRQ) free_irq(ahd->platform_data->irq, ahd); if (ahd->tags[0] == BUS_SPACE_PIO && ahd->bshs[0].ioport != 0) @@ -2347,10 +2241,8 @@ base_addr = (u_long)ahd->bshs[0].maddr; base_addr &= PAGE_MASK; iounmap((void *)base_addr); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(ahd->platform_data->mem_busaddr, 0x1000); -#endif } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) && \ LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) @@ -2400,7 +2292,7 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd_queue_alg alg) { - struct ahd_linux_device *dev; + struct aic_linux_device *dev; int was_queuing; int now_queuing; @@ -2409,27 +2301,27 @@ devinfo->lun, /*alloc*/FALSE); if (dev == NULL) return; - was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED); + was_queuing = dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED); switch (alg) { default: case AHD_QUEUE_NONE: now_queuing = 0; break; case AHD_QUEUE_BASIC: - now_queuing = AHD_DEV_Q_BASIC; + now_queuing = AIC_DEV_Q_BASIC; break; case AHD_QUEUE_TAGGED: - now_queuing = AHD_DEV_Q_TAGGED; + now_queuing = AIC_DEV_Q_TAGGED; break; } - if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) == 0 + if ((dev->flags & AIC_DEV_FREEZE_TIL_EMPTY) == 0 && (was_queuing != now_queuing) && (dev->active != 0)) { - dev->flags |= AHD_DEV_FREEZE_TIL_EMPTY; + dev->flags |= AIC_DEV_FREEZE_TIL_EMPTY; dev->qfrozen++; } - dev->flags &= ~(AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED|AHD_DEV_PERIODIC_OTAG); + dev->flags &= ~(AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED|AIC_DEV_PERIODIC_OTAG); if (now_queuing) { u_int usertags; @@ -2449,11 +2341,11 @@ */ dev->openings = 1; } else if (alg == AHD_QUEUE_TAGGED) { - dev->flags |= AHD_DEV_Q_TAGGED; + dev->flags |= AIC_DEV_Q_TAGGED; if (aic79xx_periodic_otag != 0) - dev->flags |= AHD_DEV_PERIODIC_OTAG; + dev->flags |= AIC_DEV_PERIODIC_OTAG; } else - dev->flags |= AHD_DEV_Q_BASIC; + dev->flags |= AIC_DEV_Q_BASIC; } else { /* We can only have one opening. */ dev->maxtags = 0; @@ -2461,13 +2353,13 @@ } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) if (dev->scsi_device != NULL) { - switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) { - case AHD_DEV_Q_BASIC: + switch ((dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED))) { + case AIC_DEV_Q_BASIC: scsi_adjust_queue_depth(dev->scsi_device, MSG_SIMPLE_TASK, dev->openings + dev->active); break; - case AHD_DEV_Q_TAGGED: + case AIC_DEV_Q_TAGGED: scsi_adjust_queue_depth(dev->scsi_device, MSG_ORDERED_TASK, dev->openings + dev->active); @@ -2520,9 +2412,9 @@ for (; targ < maxtarg; targ++) { for (; clun < maxlun; clun++) { - struct ahd_linux_device *dev; - struct ahd_busyq *busyq; - struct ahd_cmd *acmd; + struct aic_linux_device *dev; + struct aic_busyq *busyq; + struct aic_cmd *acmd; dev = ahd_linux_get_device(ahd, /*chan*/0, targ, clun, /*alloc*/FALSE); @@ -2538,6 +2430,18 @@ acmd_links.tqe); count++; cmd->result = status << 16; + /* + * The completion handler believes that + * commands without active timers running + * have lost the race of completing before + * their timer expires. Since commands in + * our busy queues do not have timers running, + * appease the mid-layer by adding a timer + * now. This timer will be immediately + * canceled by the midlayer. + */ + scsi_add_timer(cmd, 60*HZ, + aic_linux_midlayer_timeout); ahd_linux_queue_cmd_complete(ahd, cmd); } } @@ -2553,7 +2457,7 @@ ahd_lock(ahd, &flags); del_timer(&ahd->platform_data->completeq_timer); - ahd->platform_data->flags &= ~AHD_RUN_CMPLT_Q_TIMER; + ahd->platform_data->flags &= ~AIC_RUN_CMPLT_Q_TIMER; ahd_linux_run_complete_queue(ahd); ahd_unlock(ahd, &flags); } @@ -2566,14 +2470,23 @@ * Freeze the simq and signal ahd_linux_queue to not let any * more commands through */ - if ((ahd->platform_data->flags & AHD_DV_ACTIVE) == 0) { + if ((ahd->platform_data->flags & AIC_DV_ACTIVE) == 0) { #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_DV) printf("%s: Starting DV\n", ahd_name(ahd)); #endif - ahd->platform_data->flags |= AHD_DV_ACTIVE; - ahd_freeze_simq(ahd); + ahd->platform_data->flags |= AIC_DV_ACTIVE; + + /* + * Prevent upper layer from sending any + * commands to us. + */ + aic_freeze_simq(ahd); + scsi_block_requests(ahd->platform_data->host); + ahd_platform_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS, + CAM_LUN_WILDCARD, SCB_LIST_NULL, + ROLE_INITIATOR, CAM_REQUEUE_REQ); /* Wake up the DV kthread */ up(&ahd->platform_data->dv_sem); @@ -2612,6 +2525,7 @@ unlock_kernel(); while (1) { + /* * Use down_interruptible() rather than down() to * avoid inclusion in the load average. @@ -2620,7 +2534,7 @@ /* Check to see if we've been signaled to exit */ ahd_lock(ahd, &s); - if ((ahd->platform_data->flags & AHD_DV_SHUTDOWN) != 0) { + if ((ahd->platform_data->flags & AIC_DV_SHUTDOWN) != 0) { ahd_unlock(ahd, &s); break; } @@ -2637,7 +2551,7 @@ */ ahd_lock(ahd, &s); while (LIST_FIRST(&ahd->pending_scbs) != NULL) { - ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_EMPTY; + ahd->platform_data->flags |= AIC_DV_WAIT_SIMQ_EMPTY; ahd_unlock(ahd, &s); down_interruptible(&ahd->platform_data->dv_sem); ahd_lock(ahd, &s); @@ -2647,8 +2561,8 @@ * Wait for the SIMQ to be released so that DV is the * only reason the queue is frozen. */ - while (AHD_DV_SIMQ_FROZEN(ahd) == 0) { - ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE; + while (AIC_DV_SIMQ_FROZEN(ahd) == 0) { + ahd->platform_data->flags |= AIC_DV_WAIT_SIMQ_RELEASE; ahd_unlock(ahd, &s); down_interruptible(&ahd->platform_data->dv_sem); ahd_lock(ahd, &s); @@ -2659,14 +2573,17 @@ ahd_linux_dv_target(ahd, target); ahd_lock(ahd, &s); - ahd->platform_data->flags &= ~AHD_DV_ACTIVE; - ahd_unlock(ahd, &s); + ahd->platform_data->flags &= ~AIC_DV_ACTIVE; /* * Release the SIMQ so that normal commands are * allowed to continue on the bus. */ - ahd_release_simq(ahd); + aic_release_simq_locked(ahd); + + ahd_unlock(ahd, &s); + + scsi_unblock_requests(ahd->platform_data->host); } up(&ahd->platform_data->eh_sem); return (0); @@ -2679,7 +2596,7 @@ ahd_lock(ahd, &s); if (ahd->platform_data->dv_pid != 0) { - ahd->platform_data->flags |= AHD_DV_SHUTDOWN; + ahd->platform_data->flags |= AIC_DV_SHUTDOWN; ahd_unlock(ahd, &s); up(&ahd->platform_data->dv_sem); @@ -2699,10 +2616,10 @@ /* * Mark the dv thread as already dead. This * avoids attempting to kill it a second time. - * This is necessary because we must kill the - * DV thread before calling ahd_free() in the + * This is necessary because we must kill our + * threads before calling ahd_free() in the * module shutdown case to avoid bogus locking - * in the SCSI mid-layer, but we ahd_free() is + * in the SCSI mid-layer, but when ahd_free() is * called without killing the DV thread in the * instance detach case, so ahd_platform_free() * calls us again to verify that the DV thread @@ -2722,10 +2639,10 @@ ahd_set_dv_state(ahd, targ, newstate, __LINE__) static __inline void -ahd_set_dv_state(struct ahd_softc *ahd, struct ahd_linux_target *targ, - ahd_dv_state newstate, u_int line) +ahd_set_dv_state(struct ahd_softc *ahd, struct aic_linux_target *targ, + aic_dv_state newstate, u_int line) { - ahd_dv_state oldstate; + aic_dv_state oldstate; oldstate = targ->dv_state; #ifdef AHD_DEBUG @@ -2745,7 +2662,7 @@ ahd_linux_dv_target(struct ahd_softc *ahd, u_int target_offset) { struct ahd_devinfo devinfo; - struct ahd_linux_target *targ; + struct aic_linux_target *targ; struct scsi_cmnd *cmd; struct scsi_device *scsi_dev; struct scsi_sense_data *sense; @@ -2759,7 +2676,7 @@ echo_size = 0; ahd_lock(ahd, &s); targ = ahd->platform_data->targets[target_offset]; - if (targ == NULL || (targ->flags & AHD_DV_REQUIRED) == 0) { + if (targ == NULL || (targ->flags & AIC_DV_REQUIRED) == 0) { ahd_unlock(ahd, &s); return; } @@ -2782,14 +2699,14 @@ scsi_dev->channel = devinfo.channel - 'A'; ahd->platform_data->dv_scsi_dev = scsi_dev; - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_SHORT_ASYNC); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_INQ_SHORT_ASYNC); - while (targ->dv_state != AHD_DV_STATE_EXIT) { + while (targ->dv_state != AIC_DV_STATE_EXIT) { timeout = AHD_LINUX_DV_TIMEOUT; switch (targ->dv_state) { - case AHD_DV_STATE_INQ_SHORT_ASYNC: - case AHD_DV_STATE_INQ_ASYNC: - case AHD_DV_STATE_INQ_ASYNC_VERIFY: + case AIC_DV_STATE_INQ_SHORT_ASYNC: + case AIC_DV_STATE_INQ_ASYNC: + case AIC_DV_STATE_INQ_ASYNC_VERIFY: /* * Set things to async narrow to reduce the * chance that the INQ will fail. @@ -2801,36 +2718,36 @@ AHD_TRANS_GOAL, /*paused*/FALSE); ahd_unlock(ahd, &s); timeout = 10 * HZ; - targ->flags &= ~AHD_INQ_VALID; + targ->flags &= ~AIC_INQ_VALID; /* FALLTHROUGH */ - case AHD_DV_STATE_INQ_VERIFY: + case AIC_DV_STATE_INQ_VERIFY: { u_int inq_len; - if (targ->dv_state == AHD_DV_STATE_INQ_SHORT_ASYNC) + if (targ->dv_state == AIC_DV_STATE_INQ_SHORT_ASYNC) inq_len = AHD_LINUX_DV_INQ_SHORT_LEN; else inq_len = targ->inq_data->additional_length + 5; ahd_linux_dv_inq(ahd, cmd, &devinfo, targ, inq_len); break; } - case AHD_DV_STATE_TUR: - case AHD_DV_STATE_BUSY: + case AIC_DV_STATE_TUR: + case AIC_DV_STATE_BUSY: timeout = 5 * HZ; ahd_linux_dv_tur(ahd, cmd, &devinfo); break; - case AHD_DV_STATE_REBD: + case AIC_DV_STATE_REBD: ahd_linux_dv_rebd(ahd, cmd, &devinfo, targ); break; - case AHD_DV_STATE_WEB: + case AIC_DV_STATE_WEB: ahd_linux_dv_web(ahd, cmd, &devinfo, targ); break; - case AHD_DV_STATE_REB: + case AIC_DV_STATE_REB: ahd_linux_dv_reb(ahd, cmd, &devinfo, targ); break; - case AHD_DV_STATE_SU: + case AIC_DV_STATE_SU: ahd_linux_dv_su(ahd, cmd, &devinfo, targ); timeout = 50 * HZ; break; @@ -2842,8 +2759,6 @@ } /* Queue the command and wait for it to complete */ - /* Abuse eh_timeout in the scsi_cmnd struct for our purposes */ - init_timer(&cmd->eh_timeout); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) /* @@ -2853,32 +2768,35 @@ */ timeout += HZ; #endif - scsi_add_timer(cmd, timeout, ahd_linux_dv_timeout); + init_timer(&cmd->eh_timeout); + cmd->timeout_per_command = timeout; + /* * In 2.5.X, it is assumed that all calls from the * "midlayer" (which we are emulating) will have the * ahd host lock held. For other kernels, the * io_request_lock must be held. */ -#if AHD_SCSI_HAS_HOST_LOCK != 0 +#if AIC_SCSI_HAS_HOST_LOCK != 0 ahd_lock(ahd, &s); #else spin_lock_irqsave(&io_request_lock, s); #endif ahd_linux_queue(cmd, ahd_linux_dv_complete); -#if AHD_SCSI_HAS_HOST_LOCK != 0 +#if AIC_SCSI_HAS_HOST_LOCK != 0 ahd_unlock(ahd, &s); #else spin_unlock_irqrestore(&io_request_lock, s); #endif down_interruptible(&ahd->platform_data->dv_cmd_sem); + /* * Wait for the SIMQ to be released so that DV is the * only reason the queue is frozen. */ ahd_lock(ahd, &s); - while (AHD_DV_SIMQ_FROZEN(ahd) == 0) { - ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE; + while (AIC_DV_SIMQ_FROZEN(ahd) == 0) { + ahd->platform_data->flags |= AIC_DV_WAIT_SIMQ_RELEASE; ahd_unlock(ahd, &s); down_interruptible(&ahd->platform_data->dv_sem); ahd_lock(ahd, &s); @@ -2889,7 +2807,7 @@ } out: - if ((targ->flags & AHD_INQ_VALID) != 0 + if ((targ->flags & AIC_INQ_VALID) != 0 && ahd_linux_get_device(ahd, devinfo.channel - 'A', devinfo.target, devinfo.lun, /*alloc*/FALSE) == NULL) { @@ -2900,7 +2818,7 @@ * parameters found in the inquiry string. */ ahd_linux_filter_inquiry(ahd, &devinfo); - if ((targ->flags & (AHD_BASIC_DV|AHD_ENHANCED_DV)) != 0) { + if ((targ->flags & (AIC_BASIC_DV|AIC_ENHANCED_DV)) != 0) { ahd_print_devinfo(ahd, &devinfo); printf("DV failed to configure device. " "Please file a bug report against " @@ -2925,7 +2843,7 @@ free(targ->dv_buffer1, M_DEVBUF); targ->dv_buffer1 = NULL; } - targ->flags &= ~AHD_DV_REQUIRED; + targ->flags &= ~AIC_DV_REQUIRED; if (targ->refcount == 0) ahd_linux_free_target(ahd, targ); ahd_unlock(ahd, &s); @@ -2934,13 +2852,13 @@ static void ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ) + struct aic_linux_target *targ) { u_int32_t status; status = aic_error_action(cmd, targ->inq_data, - ahd_cmd_get_transaction_status(cmd), - ahd_cmd_get_scsi_status(cmd)); + aic_cmd_get_transaction_status(cmd), + aic_cmd_get_scsi_status(cmd)); #ifdef AHD_DEBUG @@ -2953,8 +2871,8 @@ #endif switch (targ->dv_state) { - case AHD_DV_STATE_INQ_SHORT_ASYNC: - case AHD_DV_STATE_INQ_ASYNC: + case AIC_DV_STATE_INQ_SHORT_ASYNC: + case AIC_DV_STATE_INQ_ASYNC: switch (status & SS_MASK) { case SS_NOP: { @@ -2963,21 +2881,21 @@ } case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) targ->dv_state_retry--; if ((status & SS_ERRMASK) == EBUSY) - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_BUSY); if (targ->dv_state_retry < 10) break; /* FALLTHROUGH */ default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_DV) { ahd_print_devinfo(ahd, devinfo); @@ -2987,7 +2905,7 @@ break; } break; - case AHD_DV_STATE_INQ_ASYNC_VERIFY: + case AIC_DV_STATE_INQ_ASYNC_VERIFY: switch (status & SS_MASK) { case SS_NOP: { @@ -3001,12 +2919,12 @@ * Try from the top again. */ AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; } AHD_SET_DV_STATE(ahd, targ, targ->dv_state+1); - targ->flags |= AHD_INQ_VALID; + targ->flags |= AIC_INQ_VALID; if (ahd_linux_user_dv_setting(ahd) == 0) break; @@ -3019,33 +2937,33 @@ default: case SID_SPI_CLOCK_ST: /* Assume only basic DV is supported. */ - targ->flags |= AHD_BASIC_DV; + targ->flags |= AIC_BASIC_DV; break; case SID_SPI_CLOCK_DT: case SID_SPI_CLOCK_DT_ST: - targ->flags |= AHD_ENHANCED_DV; + targ->flags |= AIC_ENHANCED_DV; break; } break; } case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) targ->dv_state_retry--; if ((status & SS_ERRMASK) == EBUSY) - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_BUSY); if (targ->dv_state_retry < 10) break; /* FALLTHROUGH */ default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_DV) { ahd_print_devinfo(ahd, devinfo); @@ -3055,14 +2973,14 @@ break; } break; - case AHD_DV_STATE_INQ_VERIFY: + case AIC_DV_STATE_INQ_VERIFY: switch (status & SS_MASK) { case SS_NOP: { if (memcmp(targ->inq_data, targ->dv_buffer, AHD_LINUX_DV_INQ_LEN) == 0) { - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } @@ -3084,7 +3002,7 @@ #endif if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } /* @@ -3097,18 +3015,18 @@ } case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } /* @@ -3117,12 +3035,12 @@ */ targ->dv_state_retry = 0; } else if ((status & SS_ERRMASK) == EBUSY) - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_BUSY); if (targ->dv_state_retry < 10) break; /* FALLTHROUGH */ default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_DV) { ahd_print_devinfo(ahd, devinfo); @@ -3133,33 +3051,33 @@ } break; - case AHD_DV_STATE_TUR: + case AIC_DV_STATE_TUR: switch (status & SS_MASK) { case SS_NOP: - if ((targ->flags & AHD_BASIC_DV) != 0) { + if ((targ->flags & AIC_BASIC_DV) != 0) { ahd_linux_filter_inquiry(ahd, devinfo); AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_VERIFY); - } else if ((targ->flags & AHD_ENHANCED_DV) != 0) { - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REBD); + AIC_DV_STATE_INQ_VERIFY); + } else if ((targ->flags & AIC_ENHANCED_DV) != 0) { + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_REBD); } else { - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); } break; case SS_RETRY: case SS_TUR: if ((status & SS_ERRMASK) == EBUSY) { - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_BUSY); break; } AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } /* @@ -3175,7 +3093,7 @@ printf("DV TUR reties exhausted\n"); } #endif - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } if (status & SSQ_DELAY) @@ -3183,25 +3101,25 @@ break; case SS_START: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_SU); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_SU); break; case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } break; - case AHD_DV_STATE_REBD: + case AIC_DV_STATE_REBD: switch (status & SS_MASK) { case SS_NOP: { uint32_t echo_size; - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_WEB); echo_size = scsi_3btoul(&targ->dv_buffer[1]); echo_size &= 0x1FFF; #ifdef AHD_DEBUG @@ -3211,7 +3129,17 @@ } #endif if (echo_size == 0) { - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + /* + * Fall back to basic DV. + */ + if (bootverbose) { + ahd_print_devinfo(ahd, devinfo); + printf("Echo Buffer unavailable. " + "Performing basic DV.\n"); + } + targ->flags &= ~AIC_ENHANCED_DV; + targ->flags |= AIC_BASIC_DV; + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_TUR); break; } @@ -3226,11 +3154,11 @@ } case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_RETRY: AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) targ->dv_state_retry--; if (targ->dv_state_retry <= 10) @@ -3249,30 +3177,30 @@ * and try level 1 DV. */ ahd_linux_filter_inquiry(ahd, devinfo); - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_VERIFY); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_INQ_VERIFY); targ->dv_echo_size = 0; break; } break; - case AHD_DV_STATE_WEB: + case AIC_DV_STATE_WEB: switch (status & SS_MASK) { case SS_NOP: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REB); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_REB); break; case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_RETRY: AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } /* @@ -3291,22 +3219,22 @@ } #endif default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } break; - case AHD_DV_STATE_REB: + case AIC_DV_STATE_REB: switch (status & SS_MASK) { case SS_NOP: if (memcmp(targ->dv_buffer, targ->dv_buffer1, targ->dv_echo_size) != 0) { if (ahd_linux_dv_fallback(ahd, devinfo) != 0) AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); else AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_WEB); + AIC_DV_STATE_WEB); break; } @@ -3318,24 +3246,24 @@ free(targ->dv_buffer1, M_DEVBUF); targ->dv_buffer1 = NULL; } - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_RETRY: AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahd_linux_dv_fallback(ahd, devinfo) != 0) { AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_WEB); } if (targ->dv_state_retry <= 10) { if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0) @@ -3350,35 +3278,35 @@ #endif /* FALLTHROUGH */ default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } break; - case AHD_DV_STATE_SU: + case AIC_DV_STATE_SU: switch (status & SS_MASK) { case SS_NOP: case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } break; - case AHD_DV_STATE_BUSY: + case AIC_DV_STATE_BUSY: switch (status & SS_MASK) { case SS_NOP: case SS_INQ_REFRESH: AHD_SET_DV_STATE(ahd, targ, - AHD_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHD_SET_DV_STATE(ahd, targ, targ->dv_state); - if (ahd_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if (targ->dv_state_retry < 60) { @@ -3391,11 +3319,11 @@ printf("DV BUSY reties exhausted\n"); } #endif - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); } break; default: - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } break; @@ -3403,7 +3331,7 @@ default: printf("%s: Invalid DV completion state %d\n", ahd_name(ahd), targ->dv_state); - AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT); + AHD_SET_DV_STATE(ahd, targ, AIC_DV_STATE_EXIT); break; } } @@ -3423,7 +3351,7 @@ */ static void ahd_linux_dv_inq(struct ahd_softc *ahd, struct scsi_cmnd *cmd, - struct ahd_devinfo *devinfo, struct ahd_linux_target *targ, + struct ahd_devinfo *devinfo, struct aic_linux_target *targ, u_int request_length) { @@ -3436,7 +3364,7 @@ if (targ->inq_data == NULL) targ->inq_data = malloc(AHD_LINUX_DV_INQ_LEN, M_DEVBUF, M_WAITOK); - if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC) { + if (targ->dv_state > AIC_DV_STATE_INQ_ASYNC) { if (targ->dv_buffer != NULL) free(targ->dv_buffer, M_DEVBUF); targ->dv_buffer = malloc(AHD_LINUX_DV_INQ_LEN, @@ -3449,7 +3377,7 @@ cmd->cmnd[0] = INQUIRY; cmd->cmnd[4] = request_length; cmd->request_bufflen = request_length; - if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC) + if (targ->dv_state > AIC_DV_STATE_INQ_ASYNC) cmd->request_buffer = targ->dv_buffer; else cmd->request_buffer = targ->inq_data; @@ -3478,7 +3406,7 @@ static void ahd_linux_dv_rebd(struct ahd_softc *ahd, struct scsi_cmnd *cmd, - struct ahd_devinfo *devinfo, struct ahd_linux_target *targ) + struct ahd_devinfo *devinfo, struct aic_linux_target *targ) { #ifdef AHD_DEBUG @@ -3503,7 +3431,7 @@ static void ahd_linux_dv_web(struct ahd_softc *ahd, struct scsi_cmnd *cmd, - struct ahd_devinfo *devinfo, struct ahd_linux_target *targ) + struct ahd_devinfo *devinfo, struct aic_linux_target *targ) { #ifdef AHD_DEBUG @@ -3525,7 +3453,7 @@ static void ahd_linux_dv_reb(struct ahd_softc *ahd, struct scsi_cmnd *cmd, - struct ahd_devinfo *devinfo, struct ahd_linux_target *targ) + struct ahd_devinfo *devinfo, struct aic_linux_target *targ) { #ifdef AHD_DEBUG @@ -3548,7 +3476,7 @@ static void ahd_linux_dv_su(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, - struct ahd_linux_target *targ) + struct aic_linux_target *targ) { u_int le; @@ -3583,7 +3511,7 @@ static int ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) { - struct ahd_linux_target *targ; + struct aic_linux_target *targ; struct ahd_initiator_tinfo *tinfo; struct ahd_transinfo *goal; struct ahd_tmode_tstate *tstate; @@ -3754,7 +3682,7 @@ return (0); } -static void +void ahd_linux_dv_timeout(struct scsi_cmnd *cmd) { struct ahd_softc *ahd; @@ -3788,29 +3716,18 @@ * error code. */ if ((scb->flags & SCB_SENSE) != 0) - ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); + aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); else - ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); ahd_reset_channel(ahd, cmd->device->channel + 'A', /*initiate*/TRUE); - /* - * Add a minimal bus settle delay for devices that are slow to - * respond after bus resets. - */ - ahd_freeze_simq(ahd); - init_timer(&ahd->platform_data->reset_timer); - ahd->platform_data->reset_timer.data = (u_long)ahd; - ahd->platform_data->reset_timer.expires = jiffies + HZ / 2; - ahd->platform_data->reset_timer.function = - (ahd_linux_callback_t *)ahd_release_simq; - add_timer(&ahd->platform_data->reset_timer); - if (ahd_linux_next_device_to_run(ahd) != NULL) - ahd_schedule_runq(ahd); + if (aic_linux_next_device_to_run(ahd) != NULL) + aic_schedule_runq(ahd); ahd_linux_run_complete_queue(ahd); ahd_unlock(ahd, &flags); } -static void +void ahd_linux_dv_complete(struct scsi_cmnd *cmd) { struct ahd_softc *ahd; @@ -3832,7 +3749,7 @@ } static void -ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ) +ahd_linux_generate_dv_pattern(struct aic_linux_target *targ) { uint16_t b; u_int i; @@ -3998,8 +3915,8 @@ * Determines the queue depth for a given device. */ static void -ahd_linux_device_queue_depth(struct ahd_softc *ahd, - struct ahd_linux_device *dev) +aic_linux_device_queue_depth(struct ahd_softc *ahd, + struct aic_linux_device *dev) { struct ahd_devinfo devinfo; u_int tags; @@ -4022,10 +3939,10 @@ } } -static void -ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev) +void +ahd_linux_run_device_queue(struct ahd_softc *ahd, struct aic_linux_device *dev) { - struct ahd_cmd *acmd; + struct aic_cmd *acmd; struct scsi_cmnd *cmd; struct scb *scb; struct hardware_scb *hscb; @@ -4034,7 +3951,7 @@ u_int col_idx; uint16_t mask; - if ((dev->flags & AHD_DEV_ON_RUN_LIST) != 0) + if ((dev->flags & AIC_DEV_ON_RUN_LIST) != 0) panic("running device on run list"); while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL @@ -4045,11 +3962,11 @@ * running is because the whole controller Q is frozen. */ if (ahd->platform_data->qfrozen != 0 - && AHD_DV_SIMQ_FROZEN(ahd) == 0) { + && AIC_DV_SIMQ_FROZEN(ahd) == 0) { TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); - dev->flags |= AHD_DEV_ON_RUN_LIST; + dev->flags |= AIC_DEV_ON_RUN_LIST; return; } @@ -4060,7 +3977,7 @@ */ tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, cmd->device->id, &tstate); - if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0 + if ((dev->flags & (AIC_DEV_Q_TAGGED|AIC_DEV_Q_BASIC)) == 0 || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { col_idx = AHD_NEVER_COL_IDX; } else { @@ -4070,13 +3987,15 @@ if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) { TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); - dev->flags |= AHD_DEV_ON_RUN_LIST; - ahd->flags |= AHD_RESOURCE_SHORTAGE; + dev->flags |= AIC_DEV_ON_RUN_LIST; + ahd->flags |= AIC_RESOURCE_SHORTAGE; + ahd->platform_data->qfrozen++; return; } TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe); scb->io_ctx = cmd; scb->platform_data->dev = dev; + scb->platform_data->flags = 0; hscb = scb->hscb; cmd->host_scribble = (char *)scb; @@ -4092,7 +4011,7 @@ if ((ahd->user_discenable & mask) != 0) hscb->control |= DISCENB; - if (AHD_DV_CMD(cmd) != 0) + if (AIC_DV_CMD(cmd) != 0) scb->flags |= SCB_SILENT; if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) @@ -4101,9 +4020,33 @@ if ((tstate->auto_negotiate & mask) != 0) { scb->flags |= SCB_AUTO_NEGOTIATE; scb->hscb->control |= MK_MESSAGE; + } else if (cmd->cmnd[0] == INQUIRY + && (tinfo->curr.offset != 0 + || tinfo->curr.width != MSG_EXT_WDTR_BUS_8_BIT + || tinfo->curr.ppr_options != 0) + && (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)==0) { + /* + * The SCSI spec requires inquiry + * commands to complete without + * reporting unit attention conditions. + * Because of this, an inquiry command + * that occurs just after a device is + * reset will result in a data phase + * with mismatched negotiated rates. + * The core already forces a renegotiation + * for reset events that are visible to + * our controller or that we initiate, + * but a third party device reset or a + * hot-plug insertion can still cause this + * issue. Therefore, we force a re-negotiation + * for every inquiry command unless we + * are async. + */ + scb->flags |= SCB_NEGOTIATE; + scb->hscb->control |= MK_MESSAGE; } - if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { + if ((dev->flags & (AIC_DEV_Q_TAGGED|AIC_DEV_Q_BASIC)) != 0) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) int msg_bytes; uint8_t tag_msgs[2]; @@ -4115,8 +4058,8 @@ dev->commands_since_idle_or_otag = 0; } else #endif - if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH - && (dev->flags & AHD_DEV_Q_TAGGED) != 0) { + if (dev->commands_since_idle_or_otag == AIC_OTAG_THRESH + && (dev->flags & AIC_DEV_Q_TAGGED) != 0) { hscb->control |= MSG_ORDERED_TASK; dev->commands_since_idle_or_otag = 0; } else { @@ -4128,8 +4071,9 @@ memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len); scb->sg_count = 0; - ahd_set_residual(scb, 0); - ahd_set_sense_residual(scb, 0); + aic_set_residual(scb, 0); + aic_set_sense_residual(scb, 0); + scb->platform_data->xfer_len = 0; if (cmd->use_sg != 0) { void *sg; struct scatterlist *cur_seg; @@ -4138,18 +4082,15 @@ cur_seg = (struct scatterlist *)cmd->request_buffer; dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); - nseg = pci_map_sg(ahd->dev_softc, cur_seg, - cmd->use_sg, dir); - scb->platform_data->xfer_len = 0; + nseg = aic_map_sg(ahd, cur_seg, cmd->use_sg, dir); for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) { bus_addr_t addr; bus_size_t len; addr = sg_dma_address(cur_seg); len = sg_dma_len(cur_seg); - scb->platform_data->xfer_len += len; - sg = ahd_sg_setup(ahd, scb, sg, addr, len, - /*last*/nseg == 1); + sg = ahd_linux_sg_setup(ahd, scb, sg, addr, len, + /*last*/nseg == 1); } } else if (cmd->request_bufflen != 0) { void *sg; @@ -4158,13 +4099,13 @@ sg = scb->sg_list; dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); - addr = pci_map_single(ahd->dev_softc, + addr = aic_map_single(ahd, cmd->request_buffer, cmd->request_bufflen, dir); - scb->platform_data->xfer_len = cmd->request_bufflen; scb->platform_data->buf_busaddr = addr; - sg = ahd_sg_setup(ahd, scb, sg, addr, - cmd->request_bufflen, /*last*/TRUE); + sg = ahd_linux_sg_setup(ahd, scb, sg, addr, + cmd->request_bufflen, + /*last*/TRUE); } LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); @@ -4180,9 +4121,10 @@ dev->target->cmds_since_error = 0; } - if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0) + if ((dev->flags & AIC_DEV_PERIODIC_OTAG) != 0) dev->commands_since_idle_or_otag++; scb->flags |= SCB_ACTIVE; + aic_scb_timer_start(scb); ahd_queue_scb(ahd, scb); } } @@ -4200,8 +4142,8 @@ ahd = (struct ahd_softc *) dev_id; ahd_lock(ahd, &flags); ours = ahd_intr(ahd); - if (ahd_linux_next_device_to_run(ahd) != NULL) - ahd_schedule_runq(ahd); + if (aic_linux_next_device_to_run(ahd) != NULL) + aic_schedule_runq(ahd); ahd_linux_run_complete_queue(ahd); ahd_unlock(ahd, &flags); return IRQ_RETVAL(ours); @@ -4215,10 +4157,10 @@ ; } -static struct ahd_linux_target* +static struct aic_linux_target* ahd_linux_alloc_target(struct ahd_softc *ahd, u_int channel, u_int target) { - struct ahd_linux_target *targ; + struct aic_linux_target *targ; targ = malloc(sizeof(*targ), M_DEVBUF, M_NOWAIT); if (targ == NULL) @@ -4226,14 +4168,14 @@ memset(targ, 0, sizeof(*targ)); targ->channel = channel; targ->target = target; - targ->ahd = ahd; - targ->flags = AHD_DV_REQUIRED; + targ->softc = ahd; + targ->flags = AIC_DV_REQUIRED; ahd->platform_data->targets[target] = targ; return (targ); } static void -ahd_linux_free_target(struct ahd_softc *ahd, struct ahd_linux_target *targ) +ahd_linux_free_target(struct ahd_softc *ahd, struct aic_linux_target *targ) { struct ahd_devinfo devinfo; struct ahd_initiator_tinfo *tinfo; @@ -4269,11 +4211,11 @@ free(targ, M_DEVBUF); } -static struct ahd_linux_device* +static struct aic_linux_device* ahd_linux_alloc_device(struct ahd_softc *ahd, - struct ahd_linux_target *targ, u_int lun) + struct aic_linux_target *targ, u_int lun) { - struct ahd_linux_device *dev; + struct aic_linux_device *dev; dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT); if (dev == NULL) @@ -4281,7 +4223,7 @@ memset(dev, 0, sizeof(*dev)); init_timer(&dev->timer); TAILQ_INIT(&dev->busyq); - dev->flags = AHD_DEV_UNCONFIGURED; + dev->flags = AIC_DEV_UNCONFIGURED; dev->lun = lun; dev->target = targ; @@ -4304,9 +4246,9 @@ } static void -ahd_linux_free_device(struct ahd_softc *ahd, struct ahd_linux_device *dev) +ahd_linux_free_device(struct ahd_softc *ahd, struct aic_linux_device *dev) { - struct ahd_linux_target *targ; + struct aic_linux_target *targ; del_timer(&dev->timer); targ = dev->target; @@ -4314,7 +4256,7 @@ free(dev, M_DEVBUF); targ->refcount--; if (targ->refcount == 0 - && (targ->flags & AHD_DV_REQUIRED) == 0) + && (targ->flags & AIC_DV_REQUIRED) == 0) ahd_linux_free_target(ahd, targ); } @@ -4326,7 +4268,7 @@ case AC_TRANSFER_NEG: { char buf[80]; - struct ahd_linux_target *targ; + struct aic_linux_target *targ; struct info_str info; struct ahd_initiator_tinfo *tinfo; struct ahd_tmode_tstate *tstate; @@ -4387,7 +4329,7 @@ WARN_ON(lun != CAM_LUN_WILDCARD); scsi_report_device_reset(ahd->platform_data->host, channel - 'A', target); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) Scsi_Device *scsi_dev; /* @@ -4408,12 +4350,24 @@ break; } case AC_BUS_RESET: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) if (ahd->platform_data->host != NULL) { scsi_report_bus_reset(ahd->platform_data->host, channel - 'A'); } -#endif + /* + * Add a minimal bus settle delay for devices that are slow to + * respond after bus resets. + */ + if ((ahd->platform_data->flags & AIC_BUS_SETTLE_TIMER) == 0) { + aic_freeze_simq(ahd); + ahd->platform_data->flags |= AIC_BUS_SETTLE_TIMER; + ahd->platform_data->bus_settle_timer.expires = + jiffies + (AIC79XX_RESET_DELAY * HZ)/1000; + add_timer(&ahd->platform_data->bus_settle_timer); + } else { + mod_timer(&ahd->platform_data->bus_settle_timer, + jiffies + (AIC79XX_RESET_DELAY * HZ)/1000); + } break; default: panic("ahd_send_async: Unexpected async event"); @@ -4427,14 +4381,18 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb) { Scsi_Cmnd *cmd; - struct ahd_linux_device *dev; + struct aic_linux_device *dev; if ((scb->flags & SCB_ACTIVE) == 0) { printf("SCB %d done'd twice\n", SCB_GET_TAG(scb)); ahd_dump_card_state(ahd); panic("Stopping for safety"); } + LIST_REMOVE(scb, pending_links); + if ((scb->flags & SCB_TIMEDOUT) != 0) + LIST_REMOVE(scb, timedout_links); + cmd = scb->io_ctx; dev = scb->platform_data->dev; dev->active--; @@ -4452,11 +4410,11 @@ * the sense buffer looks "sane". */ cmd->sense_buffer[0] = 0; - if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG) { + if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) { uint32_t amount_xferred; amount_xferred = - ahd_get_transfer_length(scb) - ahd_get_residual(scb); + aic_get_transfer_length(scb) - aic_get_residual(scb); if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) { @@ -4464,7 +4422,17 @@ printf("Set CAM_UNCOR_PARITY\n"); } #endif - ahd_set_transaction_status(scb, CAM_UNCOR_PARITY); + aic_set_transaction_status(scb, CAM_UNCOR_PARITY); +#ifdef AHD_REPORT_UNDERFLOWS + /* + * This code is disabled by default as some + * clients of the SCSI system do not properly + * initialize the underflow parameter. This + * results in spurious termination of commands + * that complete as expected (e.g. underflow is + * allowed as command can return variable amounts + * of data. + */ } else if (amount_xferred < scb->io_ctx->underflow) { u_int i; @@ -4476,30 +4444,31 @@ ahd_print_path(ahd, scb); printf("Saw underflow (%ld of %ld bytes). " "Treated as error\n", - ahd_get_residual(scb), - ahd_get_transfer_length(scb)); - ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR); + aic_get_residual(scb), + aic_get_transfer_length(scb)); + aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); +#endif } else { - ahd_set_transaction_status(scb, CAM_REQ_CMP); + aic_set_transaction_status(scb, CAM_REQ_CMP); } - } else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { + } else if (aic_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { ahd_linux_handle_scsi_status(ahd, dev, scb); - } else if (ahd_get_transaction_status(scb) == CAM_SEL_TIMEOUT) { - dev->flags |= AHD_DEV_UNCONFIGURED; - if (AHD_DV_CMD(cmd) == FALSE) - dev->target->flags &= ~AHD_DV_REQUIRED; + } else if (aic_get_transaction_status(scb) == CAM_SEL_TIMEOUT) { + dev->flags |= AIC_DEV_UNCONFIGURED; + if (AIC_DV_CMD(cmd) == FALSE) + dev->target->flags &= ~AIC_DV_REQUIRED; } /* * Start DV for devices that require it assuming the first command * sent does not result in a selection timeout. */ - if (ahd_get_transaction_status(scb) != CAM_SEL_TIMEOUT - && (dev->target->flags & AHD_DV_REQUIRED) != 0) + if (aic_get_transaction_status(scb) != CAM_SEL_TIMEOUT + && (dev->target->flags & AIC_DV_REQUIRED) != 0) ahd_linux_start_dv(ahd); if (dev->openings == 1 - && ahd_get_transaction_status(scb) == CAM_REQ_CMP - && ahd_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL) + && aic_get_transaction_status(scb) == CAM_REQ_CMP + && aic_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL) dev->tag_success_count++; /* * Some devices deal with temporary internal resource @@ -4508,7 +4477,7 @@ * back to our previous queue depth. */ if ((dev->openings + dev->active) < dev->maxtags - && dev->tag_success_count > AHD_TAG_SUCCESS_INTERVAL) { + && dev->tag_success_count > AIC_TAG_SUCCESS_INTERVAL) { dev->tag_success_count = 0; dev->openings++; } @@ -4517,39 +4486,68 @@ dev->commands_since_idle_or_otag = 0; if (TAILQ_EMPTY(&dev->busyq)) { - if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0 - && dev->active == 0 - && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0) + if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0 + && dev->active == 0) ahd_linux_free_device(ahd, dev); - } else if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) { + } else if ((dev->flags & AIC_DEV_ON_RUN_LIST) == 0) { TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); - dev->flags |= AHD_DEV_ON_RUN_LIST; + dev->flags |= AIC_DEV_ON_RUN_LIST; } if ((scb->flags & SCB_RECOVERY_SCB) != 0) { printf("Recovery SCB completes\n"); - if (ahd_get_transaction_status(scb) == CAM_BDR_SENT - || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED) - ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); - if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { - scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; + if (aic_get_transaction_status(scb) == CAM_BDR_SENT + || aic_get_transaction_status(scb) == CAM_REQ_ABORTED) + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); + if ((scb->platform_data->flags & AIC_SCB_UP_EH_SEM) != 0) { + scb->platform_data->flags &= ~AIC_SCB_UP_EH_SEM; up(&ahd->platform_data->eh_sem); + } else { + struct scb *list_scb; + + /* + * We were able to complete the command successfully, + * so reinstate the timeouts for all other pending + * commands. + */ + LIST_FOREACH(list_scb, + &ahd->pending_scbs, pending_links) { + + aic_scb_timer_start(list_scb); + } } } + if ((scb->platform_data->flags & AIC_TIMEOUT_ACTIVE) == 0) { + /* + * The completion handler believes that + * commands without active timers running + * have lost the race of completing before + * their timer expires. Since commands in + * our busy queues do not have timers running, + * appease the mid-layer by adding a timer + * now. This timer will be immediately + * canceled by the midlayer. + */ + scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout); + } + + if ((scb->platform_data->flags & AIC_RELEASE_SIMQ) != 0) + aic_release_simq_locked(ahd); + ahd_free_scb(ahd, scb); ahd_linux_queue_cmd_complete(ahd, cmd); - if ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_EMPTY) != 0 + if ((ahd->platform_data->flags & AIC_DV_WAIT_SIMQ_EMPTY) != 0 && LIST_FIRST(&ahd->pending_scbs) == NULL) { - ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_EMPTY; + ahd->platform_data->flags &= ~AIC_DV_WAIT_SIMQ_EMPTY; up(&ahd->platform_data->dv_sem); } } static void ahd_linux_handle_scsi_status(struct ahd_softc *ahd, - struct ahd_linux_device *dev, struct scb *scb) + struct aic_linux_device *dev, struct scb *scb) { struct ahd_devinfo devinfo; @@ -4569,7 +4567,7 @@ * we don't clobber the device with too many * commands. */ - switch (ahd_get_scsi_status(scb)) { + switch (aic_get_scsi_status(scb)) { default: break; case SCSI_STATUS_CHECK_COND: @@ -4583,13 +4581,15 @@ */ cmd = scb->io_ctx; if ((scb->flags & (SCB_SENSE|SCB_PKT_SENSE)) != 0) { - struct scsi_status_iu_header *siu; - u_int sense_size; - u_int sense_offset; + struct scsi_status_iu_header *siu; + struct scsi_sense_data *sense; + u_int sense_size; + u_int sense_offset; + int error_code, sense_key, asc, ascq; if (scb->flags & SCB_SENSE) { sense_size = MIN(sizeof(struct scsi_sense_data) - - ahd_get_sense_residual(scb), + - aic_get_sense_residual(scb), sizeof(cmd->sense_buffer)); sense_offset = 0; } else { @@ -4604,10 +4604,10 @@ sense_offset = SIU_SENSE_OFFSET(siu); } + sense = (struct scsi_sense_data *) + (ahd_get_sense_buf(ahd, scb) + sense_offset); memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); - memcpy(cmd->sense_buffer, - ahd_get_sense_buf(ahd, scb) - + sense_offset, sense_size); + memcpy(cmd->sense_buffer, sense, sense_size); cmd->result |= (DRIVER_SENSE << 24); #ifdef AHD_DEBUG @@ -4624,6 +4624,23 @@ printf("\n"); } #endif + /* + * If this is not a DV command and the target + * provides some status that makes us believe + * that the target has changed (power on reset, + * etc.) kick off a DV scan to re-validate the + * device. + */ + if (AIC_DV_CMD(cmd) != 0) + break; + + scsi_extract_sense(sense, &error_code, + &sense_key, &asc, &ascq); + if (error_code == SSD_CURRENT_ERROR + && sense_key == SSD_KEY_UNIT_ATTENTION + && asc == 0x29 + && (ascq == 0 || ascq == 1)) + dev->target->flags |= AIC_DV_REQUIRED; } break; } @@ -4663,7 +4680,7 @@ * this device. */ if (dev->last_queuefull_same_count - == AHD_LOCK_TAGS_COUNT) { + == AIC_LOCK_TAGS_COUNT) { dev->maxtags = dev->active; ahd_print_path(ahd, scb); printf("Locking max tag count at %d\n", @@ -4673,10 +4690,10 @@ dev->tags_on_last_queuefull = dev->active; dev->last_queuefull_same_count = 0; } - ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); - ahd_set_scsi_status(scb, SCSI_STATUS_OK); + aic_set_transaction_status(scb, CAM_REQUEUE_REQ); + aic_set_scsi_status(scb, SCSI_STATUS_OK); ahd_platform_set_tags(ahd, &devinfo, - (dev->flags & AHD_DEV_Q_BASIC) + (dev->flags & AIC_DEV_Q_BASIC) ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED); break; } @@ -4686,9 +4703,9 @@ */ dev->openings = 1; ahd_platform_set_tags(ahd, &devinfo, - (dev->flags & AHD_DEV_Q_BASIC) + (dev->flags & AIC_DEV_Q_BASIC) ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED); - ahd_set_scsi_status(scb, SCSI_STATUS_BUSY); + aic_set_scsi_status(scb, SCSI_STATUS_BUSY); /* FALLTHROUGH */ } case SCSI_STATUS_BUSY: @@ -4696,13 +4713,13 @@ * Set a short timer to defer sending commands for * a bit since Linux will not delay in this case. */ - if ((dev->flags & AHD_DEV_TIMER_ACTIVE) != 0) { + if ((dev->flags & AIC_DEV_TIMER_ACTIVE) != 0) { printf("%s:%c:%d: Device Timer still active during " "busy processing\n", ahd_name(ahd), dev->target->channel, dev->target->target); break; } - dev->flags |= AHD_DEV_TIMER_ACTIVE; + dev->flags |= AIC_DEV_TIMER_ACTIVE; dev->qfrozen++; init_timer(&dev->timer); dev->timer.data = (u_long)dev; @@ -4728,9 +4745,9 @@ * not guarantee the order that aborted commands will be * returned to us. */ - struct ahd_completeq *completeq; - struct ahd_cmd *list_cmd; - struct ahd_cmd *acmd; + struct aic_completeq *completeq; + struct aic_cmd *list_cmd; + struct aic_cmd *acmd; /* * Map CAM error codes into Linux Error codes. We @@ -4738,13 +4755,13 @@ * full error information available when making * state change decisions. */ - if (AHD_DV_CMD(cmd) == FALSE) { + if (AIC_DV_CMD(cmd) == FALSE) { uint32_t status; u_int new_status; - status = ahd_cmd_get_transaction_status(cmd); + status = aic_cmd_get_transaction_status(cmd); if (status != CAM_REQ_CMP) { - struct ahd_linux_device *dev; + struct aic_linux_device *dev; struct ahd_devinfo devinfo; cam_status cam_status; uint32_t action; @@ -4764,8 +4781,8 @@ dev->target->channel == 0 ? 'A':'B', ROLE_INITIATOR); - scsi_status = ahd_cmd_get_scsi_status(cmd); - cam_status = ahd_cmd_get_transaction_status(cmd); + scsi_status = aic_cmd_get_scsi_status(cmd); + cam_status = aic_cmd_get_transaction_status(cmd); action = aic_error_action(cmd, dev->target->inq_data, cam_status, scsi_status); if ((action & SSQ_FALLBACK) != 0) { @@ -4808,7 +4825,17 @@ new_status = DID_PARITY; break; case CAM_CMD_TIMEOUT: - new_status = DID_TIME_OUT; + /* + * Returning DID_TIME_OUT will + * wake up the error recovery + * thread instead of doing the + * command retry we desire. Since + * we have already recovered the + * command, returning DID_ERROR + * will cause a retry up to the + * retry limit for this command. + */ + new_status = DID_ERROR; break; case CAM_UA_ABORT: case CAM_REQ_CMP_ERR: @@ -4838,7 +4865,7 @@ if (cmd->retries > 0) cmd->retries--; new_status = DID_OK; - ahd_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND); + aic_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND); cmd->result |= (DRIVER_SENSE << 24); memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); @@ -4852,12 +4879,21 @@ break; } - ahd_cmd_set_transaction_status(cmd, new_status); + aic_cmd_set_transaction_status(cmd, new_status); + } + + /* + * Commands that have completed successfully + * can be completed to the OS immediately. + */ + if (cmd->result == (DID_OK << 16)) { + cmd->scsi_done(cmd); + return; } completeq = &ahd->platform_data->completeq; list_cmd = TAILQ_FIRST(completeq); - acmd = (struct ahd_cmd *)cmd; + acmd = (struct aic_cmd *)cmd; while (list_cmd != NULL && acmd_scsi_cmd(list_cmd).serial_number < acmd_scsi_cmd(acmd).serial_number) @@ -4877,7 +4913,7 @@ struct ahd_transinfo *goal; struct ahd_transinfo *curr; struct ahd_tmode_tstate *tstate; - struct ahd_linux_device *dev; + struct aic_linux_device *dev; u_int width; u_int period; u_int offset; @@ -4899,9 +4935,9 @@ sid = (struct scsi_inquiry_data *)dev->target->inq_data; if (SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) { - dev->flags &= ~AHD_DEV_UNCONFIGURED; + dev->flags &= ~AIC_DEV_UNCONFIGURED; } else { - dev->flags |= AHD_DEV_UNCONFIGURED; + dev->flags |= AIC_DEV_UNCONFIGURED; return; } @@ -4967,48 +5003,6 @@ AHD_TRANS_GOAL, /*paused*/FALSE); } -void -ahd_freeze_simq(struct ahd_softc *ahd) -{ - ahd->platform_data->qfrozen++; - if (ahd->platform_data->qfrozen == 1) { - scsi_block_requests(ahd->platform_data->host); - ahd_platform_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS, - CAM_LUN_WILDCARD, SCB_LIST_NULL, - ROLE_INITIATOR, CAM_REQUEUE_REQ); - } -} - -void -ahd_release_simq(struct ahd_softc *ahd) -{ - u_long s; - int unblock_reqs; - - unblock_reqs = 0; - ahd_lock(ahd, &s); - if (ahd->platform_data->qfrozen > 0) - ahd->platform_data->qfrozen--; - if (ahd->platform_data->qfrozen == 0) { - unblock_reqs = 1; - } - if (AHD_DV_SIMQ_FROZEN(ahd) - && ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_RELEASE) != 0)) { - ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_RELEASE; - up(&ahd->platform_data->dv_sem); - } - ahd_schedule_runq(ahd); - ahd_unlock(ahd, &s); - /* - * There is still a race here. The mid-layer - * should keep its own freeze count and use - * a bottom half handler to run the queues - * so we can unblock with our own lock held. - */ - if (unblock_reqs) - scsi_unblock_requests(ahd->platform_data->host); -} - static void ahd_linux_sem_timeout(u_long arg) { @@ -5019,8 +5013,8 @@ scb = (struct scb *)arg; ahd = scb->ahd_softc; ahd_lock(ahd, &s); - if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { - scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; + if ((scb->platform_data->flags & AIC_SCB_UP_EH_SEM) != 0) { + scb->platform_data->flags &= ~AIC_SCB_UP_EH_SEM; up(&ahd->platform_data->eh_sem); } ahd_unlock(ahd, &s); @@ -5029,20 +5023,21 @@ static void ahd_linux_dev_timed_unfreeze(u_long arg) { - struct ahd_linux_device *dev; + struct aic_linux_device *dev; struct ahd_softc *ahd; u_long s; - dev = (struct ahd_linux_device *)arg; - ahd = dev->target->ahd; + dev = (struct aic_linux_device *)arg; + ahd = dev->target->softc; ahd_lock(ahd, &s); - dev->flags &= ~AHD_DEV_TIMER_ACTIVE; + dev->flags &= ~AIC_DEV_TIMER_ACTIVE; if (dev->qfrozen > 0) dev->qfrozen--; if (dev->qfrozen == 0 - && (dev->flags & AHD_DEV_ON_RUN_LIST) == 0) + && (dev->flags & AIC_DEV_ON_RUN_LIST) == 0) ahd_linux_run_device_queue(ahd, dev); - if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0 + if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0 + && TAILQ_EMPTY(&dev->busyq) && dev->active == 0) ahd_linux_free_device(ahd, dev); ahd_unlock(ahd, &s); @@ -5051,17 +5046,26 @@ void ahd_platform_dump_card_state(struct ahd_softc *ahd) { - struct ahd_linux_device *dev; + struct Scsi_Host *host; + struct aic_linux_device *dev; int target; int maxtarget; int lun; int i; + host = ahd->platform_data->host; + printf("%s: Host Status: Failed(%d) %s%s%s\n", + ahd_name(ahd), + host->host_failed, + host->eh_active ? "eh_active " : "", + host->host_blocked ? "host_blocked " : "", + host->host_self_blocked ? "host_self_blocked " : ""); + maxtarget = (ahd->features & AHD_WIDE) ? 15 : 7; for (target = 0; target <=maxtarget; target++) { for (lun = 0; lun < AHD_NUM_LUNS; lun++) { - struct ahd_cmd *acmd; + struct aic_cmd *acmd; dev = ahd_linux_get_device(ahd, 0, target, lun, /*alloc*/FALSE); @@ -5082,38 +5086,46 @@ static int __init ahd_linux_init(void) { + int found; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - return (ahd_linux_detect(&aic79xx_driver_template) ? 0 : -ENODEV); + found = ahd_linux_detect(&aic79xx_driver_template); #else scsi_register_module(MODULE_SCSI_HA, &aic79xx_driver_template); - if (aic79xx_driver_template.present == 0) { - scsi_unregister_module(MODULE_SCSI_HA, - &aic79xx_driver_template); - return (-ENODEV); - } - - return (0); + found = aic79xx_driver_template.present; #endif +#ifdef MODULE + if (found == 0) + ahd_init_status = -ENODEV; +#endif + if (ahd_init_status != 0) { + /* + * Linux will not call our exit + * routine if we fail to load. + * Force cleanup if initialization + * is not successful. + */ + ahd_linux_exit(); + } + return (ahd_init_status); } -static void __exit +static void ahd_linux_exit(void) { struct ahd_softc *ahd; - u_long l; /* - * Shutdown DV threads before going into the SCSI mid-layer. + * Shutdown our threads before going into the SCSI mid-layer. * This avoids situations where the mid-layer locks the entire * kernel so that waiting for our DV threads to exit leads * to deadlock. */ - ahd_list_lock(&l); TAILQ_FOREACH(ahd, &ahd_tailq, links) { ahd_linux_kill_dv_thread(ahd); + ahd_terminate_recovery_thread(ahd); } - ahd_list_unlock(&l); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* * In 2.4 we have to unregister from the PCI core _after_ diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_osm.h linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_osm.h --- linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_osm.h Sat Feb 7 17:03:39 2004 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_osm.h Tue Feb 10 01:47:04 2004 @@ -36,51 +36,19 @@ * 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#135 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#157 $ * */ #ifndef _AIC79XX_LINUX_H_ #define _AIC79XX_LINUX_H_ -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #ifndef KERNEL_VERSION #define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -#include /* For tasklet support. */ #include -#include -#else -#include -#endif - -/* Core SCSI definitions */ -#define AIC_LIB_PREFIX ahd -#include "scsi.h" -#include "hosts.h" - -/* Name space conflict with BSD queue macros */ -#ifdef LIST_HEAD -#undef LIST_HEAD -#endif - -#include "cam.h" -#include "queue.h" -#include "scsi_message.h" -#include "scsi_iu.h" -#include "aiclib.h" /*********************************** Debugging ********************************/ #ifdef CONFIG_AIC79XX_DEBUG_ENABLE @@ -97,188 +65,27 @@ /* No debugging code. */ #endif -/********************************** Misc Macros *******************************/ -#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) -#define powerof2(x) ((((x)-1)&(x))==0) - -/************************* Forward Declarations *******************************/ -struct ahd_softc; -typedef struct pci_dev *ahd_dev_softc_t; -typedef Scsi_Cmnd *ahd_io_ctx_t; - -/******************************* Byte Order ***********************************/ -#define ahd_htobe16(x) cpu_to_be16(x) -#define ahd_htobe32(x) cpu_to_be32(x) -#define ahd_htobe64(x) cpu_to_be64(x) -#define ahd_htole16(x) cpu_to_le16(x) -#define ahd_htole32(x) cpu_to_le32(x) -#define ahd_htole64(x) cpu_to_le64(x) - -#define ahd_be16toh(x) be16_to_cpu(x) -#define ahd_be32toh(x) be32_to_cpu(x) -#define ahd_be64toh(x) be64_to_cpu(x) -#define ahd_le16toh(x) le16_to_cpu(x) -#define ahd_le32toh(x) le32_to_cpu(x) -#define ahd_le64toh(x) le64_to_cpu(x) - -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1234 -#endif - -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 4321 -#endif - -#ifndef BYTE_ORDER -#if defined(__BIG_ENDIAN) -#define BYTE_ORDER BIG_ENDIAN -#endif -#if defined(__LITTLE_ENDIAN) -#define BYTE_ORDER LITTLE_ENDIAN -#endif -#endif /* BYTE_ORDER */ - -/************************* Configuration Data *********************************/ -extern uint32_t aic79xx_allow_memio; -extern int aic79xx_detect_complete; -extern Scsi_Host_Template aic79xx_driver_template; - -/***************************** Bus Space/DMA **********************************/ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17) -typedef dma_addr_t bus_addr_t; -#else -typedef uint32_t bus_addr_t; -#endif -typedef uint32_t bus_size_t; - -typedef enum { - BUS_SPACE_MEMIO, - BUS_SPACE_PIO -} bus_space_tag_t; - -typedef union { - u_long ioport; - volatile uint8_t *maddr; -} bus_space_handle_t; - -typedef struct bus_dma_segment -{ - bus_addr_t ds_addr; - bus_size_t ds_len; -} bus_dma_segment_t; - -struct ahd_linux_dma_tag -{ - bus_size_t alignment; - bus_size_t boundary; - bus_size_t maxsize; -}; -typedef struct ahd_linux_dma_tag* bus_dma_tag_t; - -struct ahd_linux_dmamap -{ - bus_addr_t bus_addr; -}; -typedef struct ahd_linux_dmamap* bus_dmamap_t; - -typedef int bus_dma_filter_t(void*, bus_addr_t); -typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); - -#define BUS_DMA_WAITOK 0x0 -#define BUS_DMA_NOWAIT 0x1 -#define BUS_DMA_ALLOCNOW 0x2 -#define BUS_DMA_LOAD_SEGS 0x4 /* - * Argument is an S/G list not - * a single buffer. - */ - -#define BUS_SPACE_MAXADDR 0xFFFFFFFF -#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF -#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF - -int ahd_dma_tag_create(struct ahd_softc *, bus_dma_tag_t /*parent*/, - bus_size_t /*alignment*/, bus_size_t /*boundary*/, - bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/, - bus_dma_filter_t*/*filter*/, void */*filterarg*/, - bus_size_t /*maxsize*/, int /*nsegments*/, - bus_size_t /*maxsegsz*/, int /*flags*/, - bus_dma_tag_t */*dma_tagp*/); - -void ahd_dma_tag_destroy(struct ahd_softc *, bus_dma_tag_t /*tag*/); - -int ahd_dmamem_alloc(struct ahd_softc *, bus_dma_tag_t /*dmat*/, - void** /*vaddr*/, int /*flags*/, - bus_dmamap_t* /*mapp*/); - -void ahd_dmamem_free(struct ahd_softc *, bus_dma_tag_t /*dmat*/, - void* /*vaddr*/, bus_dmamap_t /*map*/); - -void ahd_dmamap_destroy(struct ahd_softc *, bus_dma_tag_t /*tag*/, - bus_dmamap_t /*map*/); - -int ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t /*dmat*/, - bus_dmamap_t /*map*/, void * /*buf*/, - bus_size_t /*buflen*/, bus_dmamap_callback_t *, - void */*callback_arg*/, int /*flags*/); - -int ahd_dmamap_unload(struct ahd_softc *, bus_dma_tag_t, bus_dmamap_t); - -/* - * Operations performed by ahd_dmamap_sync(). - */ -#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ -#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ -#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ -#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ - -/* - * XXX - * ahd_dmamap_sync is only used on buffers allocated with - * the pci_alloc_consistent() API. Although I'm not sure how - * this works on architectures with a write buffer, Linux does - * not have an API to sync "coherent" memory. Perhaps we need - * to do an mb()? - */ -#define ahd_dmamap_sync(ahd, dma_tag, dmamap, offset, len, op) - -/************************** Timer DataStructures ******************************/ -typedef struct timer_list ahd_timer_t; - /********************************** Includes **********************************/ +/* Core SCSI definitions */ +#define AIC_LIB_PREFIX ahd +#define AIC_CONST_PREFIX AHD + #ifdef CONFIG_AIC79XX_REG_PRETTY_PRINT #define AIC_DEBUG_REGISTERS 1 #else #define AIC_DEBUG_REGISTERS 0 #endif -#include "aic79xx.h" - -/***************************** Timer Facilities *******************************/ -#define ahd_timer_init init_timer -#define ahd_timer_stop del_timer_sync -typedef void ahd_linux_callback_t (u_long); -static __inline void ahd_timer_reset(ahd_timer_t *timer, u_int usec, - ahd_callback_t *func, void *arg); -static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec); - -static __inline void -ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg) -{ - struct ahd_softc *ahd; +#define AIC_CORE_INCLUDE "aic79xx.h" +#include "aiclib.h" - ahd = (struct ahd_softc *)arg; - del_timer(timer); - timer->data = (u_long)arg; - timer->expires = jiffies + (usec * HZ)/1000000; - timer->function = (ahd_linux_callback_t*)func; - add_timer(timer); -} +/************************* Configuration Data *********************************/ +extern uint32_t aic79xx_allow_memio; +extern int aic79xx_detect_complete; +extern Scsi_Host_Template aic79xx_driver_template; -static __inline void -ahd_scb_timer_reset(struct scb *scb, u_int usec) -{ - mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000); -} +/***************************** Domain Validation ******************************/ +void ahd_linux_dv_complete(Scsi_Cmnd *cmd); +void ahd_linux_dv_timeout(struct scsi_cmnd *cmd); /***************************** SMP support ************************************/ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17) @@ -287,199 +94,7 @@ #include #endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK)) -#define AHD_SCSI_HAS_HOST_LOCK 1 -#else -#define AHD_SCSI_HAS_HOST_LOCK 0 -#endif - -#define AIC79XX_DRIVER_VERSION "1.3.10" - -/**************************** Front End Queues ********************************/ -/* - * Data structure used to cast the Linux struct scsi_cmnd to something - * that allows us to use the queue macros. The linux structure has - * plenty of space to hold the links fields as required by the queue - * macros, but the queue macors require them to have the correct type. - */ -struct ahd_cmd_internal { - /* Area owned by the Linux scsi layer. */ - uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)]; - union { - STAILQ_ENTRY(ahd_cmd) ste; - LIST_ENTRY(ahd_cmd) le; - TAILQ_ENTRY(ahd_cmd) tqe; - } links; - uint32_t end; -}; - -struct ahd_cmd { - union { - struct ahd_cmd_internal icmd; - struct scsi_cmnd scsi_cmd; - } un; -}; - -#define acmd_icmd(cmd) ((cmd)->un.icmd) -#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd) -#define acmd_links un.icmd.links - -/*************************** Device Data Structures ***************************/ -/* - * A per probed device structure used to deal with some error recovery - * scenarios that the Linux mid-layer code just doesn't know how to - * handle. The structure allocated for a device only becomes persistent - * after a successfully completed inquiry command to the target when - * that inquiry data indicates a lun is present. - */ -TAILQ_HEAD(ahd_busyq, ahd_cmd); -typedef enum { - AHD_DEV_UNCONFIGURED = 0x01, - AHD_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */ - AHD_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */ - AHD_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */ - AHD_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */ - AHD_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */ - AHD_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */ - AHD_DEV_SLAVE_CONFIGURED = 0x80 /* slave_configure() has been called */ -} ahd_linux_dev_flags; - -struct ahd_linux_target; -struct ahd_linux_device { - TAILQ_ENTRY(ahd_linux_device) links; - struct ahd_busyq busyq; - - /* - * The number of transactions currently - * queued to the device. - */ - int active; - - /* - * The currently allowed number of - * transactions that can be queued to - * the device. Must be signed for - * conversion from tagged to untagged - * mode where the device may have more - * than one outstanding active transaction. - */ - int openings; - - /* - * A positive count indicates that this - * device's queue is halted. - */ - u_int qfrozen; - - /* - * Cumulative command counter. - */ - u_long commands_issued; - - /* - * The number of tagged transactions when - * running at our current opening level - * that have been successfully received by - * this device since the last QUEUE FULL. - */ - u_int tag_success_count; -#define AHD_TAG_SUCCESS_INTERVAL 50 - - ahd_linux_dev_flags flags; - - /* - * Per device timer. - */ - struct timer_list timer; - - /* - * The high limit for the tags variable. - */ - u_int maxtags; - - /* - * The computed number of tags outstanding - * at the time of the last QUEUE FULL event. - */ - u_int tags_on_last_queuefull; - - /* - * How many times we have seen a queue full - * with the same number of tags. This is used - * to stop our adaptive queue depth algorithm - * on devices with a fixed number of tags. - */ - u_int last_queuefull_same_count; -#define AHD_LOCK_TAGS_COUNT 50 - - /* - * How many transactions have been queued - * without the device going idle. We use - * this statistic to determine when to issue - * an ordered tag to prevent transaction - * starvation. This statistic is only updated - * if the AHD_DEV_PERIODIC_OTAG flag is set - * on this device. - */ - u_int commands_since_idle_or_otag; -#define AHD_OTAG_THRESH 500 - - int lun; - Scsi_Device *scsi_device; - struct ahd_linux_target *target; -}; - -typedef enum { - AHD_DV_REQUIRED = 0x01, - AHD_INQ_VALID = 0x02, - AHD_BASIC_DV = 0x04, - AHD_ENHANCED_DV = 0x08 -} ahd_linux_targ_flags; - -/* DV States */ -typedef enum { - AHD_DV_STATE_EXIT = 0, - AHD_DV_STATE_INQ_SHORT_ASYNC, - AHD_DV_STATE_INQ_ASYNC, - AHD_DV_STATE_INQ_ASYNC_VERIFY, - AHD_DV_STATE_TUR, - AHD_DV_STATE_REBD, - AHD_DV_STATE_INQ_VERIFY, - AHD_DV_STATE_WEB, - AHD_DV_STATE_REB, - AHD_DV_STATE_SU, - AHD_DV_STATE_BUSY -} ahd_dv_state; - -struct ahd_linux_target { - struct ahd_linux_device *devices[AHD_NUM_LUNS]; - int channel; - int target; - int refcount; - struct ahd_transinfo last_tinfo; - struct ahd_softc *ahd; - ahd_linux_targ_flags flags; - struct scsi_inquiry_data *inq_data; - /* - * The next "fallback" period to use for narrow/wide transfers. - */ - uint8_t dv_next_narrow_period; - uint8_t dv_next_wide_period; - uint8_t dv_max_width; - uint8_t dv_max_ppr_options; - uint8_t dv_last_ppr_options; - u_int dv_echo_size; - ahd_dv_state dv_state; - u_int dv_state_retry; - uint8_t *dv_buffer; - uint8_t *dv_buffer1; - - /* - * Cumulative counter of errors. - */ - u_long errors_detected; - u_long cmds_since_error; -}; +#define AIC79XX_DRIVER_VERSION "2.0.6" /********************* Definitions Required by the Core ***********************/ /* @@ -501,100 +116,21 @@ #define AHD_NSEG 128 #endif -/* - * Per-SCB OSM storage. - */ -typedef enum { - AHD_SCB_UP_EH_SEM = 0x1 -} ahd_linux_scb_flags; - -struct scb_platform_data { - struct ahd_linux_device *dev; - bus_addr_t buf_busaddr; - uint32_t xfer_len; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - uint32_t resid; /* Transfer residual */ -#endif - uint32_t sense_resid; /* Auto-Sense residual */ - ahd_linux_scb_flags flags; -}; - -/* - * Define a structure used for each host adapter. All members are - * aligned on a boundary >= the size of the member to honor the - * alignment restrictions of the various platforms supported by - * this driver. - */ -typedef enum { - AHD_DV_WAIT_SIMQ_EMPTY = 0x01, - AHD_DV_WAIT_SIMQ_RELEASE = 0x02, - AHD_DV_ACTIVE = 0x04, - AHD_DV_SHUTDOWN = 0x08, - AHD_RUN_CMPLT_Q_TIMER = 0x10 -} ahd_linux_softc_flags; - -TAILQ_HEAD(ahd_completeq, ahd_cmd); - -struct ahd_platform_data { - /* - * Fields accessed from interrupt context. - */ - struct ahd_linux_target *targets[AHD_NUM_TARGETS]; - TAILQ_HEAD(, ahd_linux_device) device_runq; - struct ahd_completeq completeq; - - spinlock_t spin_lock; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - struct tasklet_struct runq_tasklet; -#endif - u_int qfrozen; - pid_t dv_pid; - struct timer_list completeq_timer; - struct timer_list reset_timer; - struct timer_list stats_timer; - struct semaphore eh_sem; - struct semaphore dv_sem; - struct semaphore dv_cmd_sem; /* XXX This needs to be in - * the target struct - */ - struct scsi_device *dv_scsi_dev; - struct Scsi_Host *host; /* pointer to scsi host */ -#define AHD_LINUX_NOIRQ ((uint32_t)~0) - uint32_t irq; /* IRQ for this adapter */ - uint32_t bios_address; - uint32_t mem_busaddr; /* Mem Base Addr */ - bus_addr_t hw_dma_mask; - ahd_linux_softc_flags flags; -}; - -/************************** OS Utility Wrappers *******************************/ -#define printf printk -#define M_NOWAIT GFP_ATOMIC -#define M_WAITOK 0 -#define malloc(size, type, flags) kmalloc(size, flags) -#define free(ptr, type) kfree(ptr) - -static __inline void ahd_delay(long); -static __inline void -ahd_delay(long usec) -{ - /* - * udelay on Linux can have problems for - * multi-millisecond waits. Wait at most - * 1024us per call. - */ - while (usec > 0) { - udelay(usec % 1024); - usec -= 1024; - } -} - +/************************** Error Recovery ************************************/ +static __inline void ahd_wakeup_recovery_thread(struct ahd_softc *ahd); + +static __inline void +ahd_wakeup_recovery_thread(struct ahd_softc *ahd) +{ + up(&ahd->platform_data->recovery_sem); +} + +int ahd_spawn_recovery_thread(struct ahd_softc *ahd); +void ahd_terminate_recovery_thread(struct ahd_softc *ahd); +void ahd_set_recoveryscb(struct ahd_softc *ahd, + struct scb *scb); /***************************** Low Level I/O **********************************/ -#if defined(__powerpc__) || defined(__i386__) || defined(__ia64__) -#define MMAPIO -#endif - static __inline uint8_t ahd_inb(struct ahd_softc * ahd, long port); static __inline uint16_t ahd_inw_atomic(struct ahd_softc * ahd, long port); static __inline void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val); @@ -604,21 +140,18 @@ uint8_t *, int count); static __inline void ahd_insb(struct ahd_softc * ahd, long port, uint8_t *, int count); +static __inline void ahd_flush_device_writes(struct ahd_softc *); static __inline uint8_t ahd_inb(struct ahd_softc * ahd, long port) { uint8_t x; -#ifdef MMAPIO if (ahd->tags[0] == BUS_SPACE_MEMIO) { x = readb(ahd->bshs[0].maddr + port); } else { x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); } -#else - x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); -#endif mb(); return (x); } @@ -627,16 +160,12 @@ 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); } @@ -644,30 +173,22 @@ 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(); } @@ -699,7 +220,15 @@ *array++ = ahd_inb(ahd, port); } +static __inline void +ahd_flush_device_writes(struct ahd_softc *ahd) +{ + /* XXX Is this sufficient for all architectures??? */ + ahd_inb(ahd, INTSTAT); +} + /**************************** Initialization **********************************/ +extern int ahd_init_status; int ahd_linux_register_host(struct ahd_softc *, Scsi_Host_Template *); @@ -716,184 +245,8 @@ void ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo); -/******************************** Locking *************************************/ -/* Lock protecting internal data structures */ -static __inline void ahd_lockinit(struct ahd_softc *); -static __inline void ahd_lock(struct ahd_softc *, unsigned long *flags); -static __inline void ahd_unlock(struct ahd_softc *, unsigned long *flags); - -/* Lock acquisition and release of the above lock in midlayer entry points. */ -static __inline void ahd_midlayer_entrypoint_lock(struct ahd_softc *, - unsigned long *flags); -static __inline void ahd_midlayer_entrypoint_unlock(struct ahd_softc *, - unsigned long *flags); - -/* Lock held during command compeletion to the upper layer */ -static __inline void ahd_done_lockinit(struct ahd_softc *); -static __inline void ahd_done_lock(struct ahd_softc *, unsigned long *flags); -static __inline void ahd_done_unlock(struct ahd_softc *, unsigned long *flags); - -/* Lock held during ahd_list manipulation and ahd softc frees */ -extern spinlock_t ahd_list_spinlock; -static __inline void ahd_list_lockinit(void); -static __inline void ahd_list_lock(unsigned long *flags); -static __inline void ahd_list_unlock(unsigned long *flags); - -static __inline void -ahd_lockinit(struct ahd_softc *ahd) -{ - spin_lock_init(&ahd->platform_data->spin_lock); -} - -static __inline void -ahd_lock(struct ahd_softc *ahd, unsigned long *flags) -{ - spin_lock_irqsave(&ahd->platform_data->spin_lock, *flags); -} - -static __inline void -ahd_unlock(struct ahd_softc *ahd, unsigned long *flags) -{ - spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags); -} - -static __inline void -ahd_midlayer_entrypoint_lock(struct ahd_softc *ahd, unsigned long *flags) -{ - /* - * In 2.5.X and some 2.4.X versions, the midlayer takes our - * lock just before calling us, so we avoid locking again. - * For other kernel versions, the io_request_lock is taken - * just before our entry point is called. In this case, we - * trade the io_request_lock for our per-softc lock. - */ -#if AHD_SCSI_HAS_HOST_LOCK == 0 - spin_unlock(&io_request_lock); - spin_lock(&ahd->platform_data->spin_lock); -#endif -} - -static __inline void -ahd_midlayer_entrypoint_unlock(struct ahd_softc *ahd, unsigned long *flags) -{ -#if AHD_SCSI_HAS_HOST_LOCK == 0 - spin_unlock(&ahd->platform_data->spin_lock); - spin_lock(&io_request_lock); -#endif -} - -static __inline void -ahd_done_lockinit(struct ahd_softc *ahd) -{ - /* - * In 2.5.X, our own lock is held during completions. - * In previous versions, the io_request_lock is used. - * In either case, we can't initialize this lock again. - */ -} - -static __inline void -ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags) -{ -#if AHD_SCSI_HAS_HOST_LOCK == 0 - spin_lock(&io_request_lock); -#endif -} - -static __inline void -ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags) -{ -#if AHD_SCSI_HAS_HOST_LOCK == 0 - spin_unlock(&io_request_lock); -#endif -} - -static __inline void -ahd_list_lockinit() -{ - spin_lock_init(&ahd_list_spinlock); -} - -static __inline void -ahd_list_lock(unsigned long *flags) -{ - spin_lock_irqsave(&ahd_list_spinlock, *flags); -} - -static __inline void -ahd_list_unlock(unsigned long *flags) -{ - spin_unlock_irqrestore(&ahd_list_spinlock, *flags); -} - /******************************* PCI Definitions ******************************/ -/* - * PCIM_xxx: mask to locate subfield in register - * PCIR_xxx: config register offset - * PCIC_xxx: device class - * PCIS_xxx: device subclass - * PCIP_xxx: device programming interface - * PCIV_xxx: PCI vendor ID (only required to fixup ancient devices) - * PCID_xxx: device ID - */ -#define PCIR_DEVVENDOR 0x00 -#define PCIR_VENDOR 0x00 -#define PCIR_DEVICE 0x02 -#define PCIR_COMMAND 0x04 -#define PCIM_CMD_PORTEN 0x0001 -#define PCIM_CMD_MEMEN 0x0002 -#define PCIM_CMD_BUSMASTEREN 0x0004 -#define PCIM_CMD_MWRICEN 0x0010 -#define PCIM_CMD_PERRESPEN 0x0040 -#define PCIM_CMD_SERRESPEN 0x0100 -#define PCIR_STATUS 0x06 -#define PCIR_REVID 0x08 -#define PCIR_PROGIF 0x09 -#define PCIR_SUBCLASS 0x0a -#define PCIR_CLASS 0x0b -#define PCIR_CACHELNSZ 0x0c -#define PCIR_LATTIMER 0x0d -#define PCIR_HEADERTYPE 0x0e -#define PCIM_MFDEV 0x80 -#define PCIR_BIST 0x0f -#define PCIR_CAP_PTR 0x34 - -/* config registers for header type 0 devices */ -#define PCIR_MAPS 0x10 -#define PCIR_SUBVEND_0 0x2c -#define PCIR_SUBDEV_0 0x2e - -/****************************** PCI-X definitions *****************************/ -#define PCIXR_COMMAND 0x96 -#define PCIXR_DEVADDR 0x98 -#define PCIXM_DEVADDR_FNUM 0x0003 /* Function Number */ -#define PCIXM_DEVADDR_DNUM 0x00F8 /* Device Number */ -#define PCIXM_DEVADDR_BNUM 0xFF00 /* Bus Number */ -#define PCIXR_STATUS 0x9A -#define PCIXM_STATUS_64BIT 0x0001 /* Active 64bit connection to device. */ -#define PCIXM_STATUS_133CAP 0x0002 /* Device is 133MHz capable */ -#define PCIXM_STATUS_SCDISC 0x0004 /* Split Completion Discarded */ -#define PCIXM_STATUS_UNEXPSC 0x0008 /* Unexpected Split Completion */ -#define PCIXM_STATUS_CMPLEXDEV 0x0010 /* Device Complexity (set == bridge) */ -#define PCIXM_STATUS_MAXMRDBC 0x0060 /* Maximum Burst Read Count */ -#define PCIXM_STATUS_MAXSPLITS 0x0380 /* Maximum Split Transactions */ -#define PCIXM_STATUS_MAXCRDS 0x1C00 /* Maximum Cumulative Read Size */ -#define PCIXM_STATUS_RCVDSCEM 0x2000 /* Received a Split Comp w/Error msg */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) extern struct pci_driver aic79xx_pci_driver; -#endif - -typedef enum -{ - AHD_POWER_STATE_D0, - AHD_POWER_STATE_D1, - AHD_POWER_STATE_D2, - AHD_POWER_STATE_D3 -} ahd_power_state; - -void ahd_power_state_change(struct ahd_softc *ahd, - ahd_power_state new_state); /******************************* PCI Routines *********************************/ int ahd_linux_pci_init(void); @@ -901,110 +254,6 @@ int ahd_pci_map_registers(struct ahd_softc *ahd); int ahd_pci_map_int(struct ahd_softc *ahd); -static __inline uint32_t ahd_pci_read_config(ahd_dev_softc_t pci, - int reg, int width); - -static __inline uint32_t -ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width) -{ - switch (width) { - case 1: - { - uint8_t retval; - - pci_read_config_byte(pci, reg, &retval); - return (retval); - } - case 2: - { - uint16_t retval; - pci_read_config_word(pci, reg, &retval); - return (retval); - } - case 4: - { - uint32_t retval; - pci_read_config_dword(pci, reg, &retval); - return (retval); - } - default: - panic("ahd_pci_read_config: Read size too big"); - /* NOTREACHED */ - return (0); - } -} - -static __inline void ahd_pci_write_config(ahd_dev_softc_t pci, - int reg, uint32_t value, - int width); - -static __inline void -ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width) -{ - switch (width) { - case 1: - pci_write_config_byte(pci, reg, value); - break; - case 2: - pci_write_config_word(pci, reg, value); - break; - case 4: - pci_write_config_dword(pci, reg, value); - break; - default: - panic("ahd_pci_write_config: Write size too big"); - /* NOTREACHED */ - } -} - -static __inline int ahd_get_pci_function(ahd_dev_softc_t); -static __inline int -ahd_get_pci_function(ahd_dev_softc_t pci) -{ - return (PCI_FUNC(pci->devfn)); -} - -static __inline int ahd_get_pci_slot(ahd_dev_softc_t); -static __inline int -ahd_get_pci_slot(ahd_dev_softc_t pci) -{ - return (PCI_SLOT(pci->devfn)); -} - -static __inline int ahd_get_pci_bus(ahd_dev_softc_t); -static __inline int -ahd_get_pci_bus(ahd_dev_softc_t pci) -{ - return (pci->bus->number); -} - -static __inline void ahd_flush_device_writes(struct ahd_softc *); -static __inline void -ahd_flush_device_writes(struct ahd_softc *ahd) -{ - /* XXX Is this sufficient for all architectures??? */ - ahd_inb(ahd, INTSTAT); -} - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0) -#define pci_map_sg(pdev, sg_list, nseg, direction) (nseg) -#define pci_unmap_sg(pdev, sg_list, nseg, direction) -#define sg_dma_address(sg) (VIRT_TO_BUS((sg)->address)) -#define sg_dma_len(sg) ((sg)->length) -#define pci_map_single(pdev, buffer, bufflen, direction) \ - (VIRT_TO_BUS(buffer)) -#define pci_unmap_single(pdev, buffer, buflen, direction) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) -#define ahd_pci_set_dma_mask pci_set_dma_mask -#else -/* - * Always "return" 0 for success. - */ -#define ahd_pci_set_dma_mask(dev_softc, mask) \ - (((dev_softc)->dma_mask = mask) && 0) -#endif /**************************** Proc FS Support *********************************/ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) int ahd_linux_proc_info(char *, char **, off_t, int, int, int); @@ -1013,203 +262,11 @@ off_t, int, int); #endif -/*************************** Domain Validation ********************************/ -#define AHD_DV_CMD(cmd) ((cmd)->scsi_done == ahd_linux_dv_complete) -#define AHD_DV_SIMQ_FROZEN(ahd) \ - ((((ahd)->platform_data->flags & AHD_DV_ACTIVE) != 0) \ - && (ahd)->platform_data->qfrozen == 1) - /*********************** Transaction Access Wrappers **************************/ -static __inline void ahd_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t); -static __inline void ahd_set_transaction_status(struct scb *, uint32_t); -static __inline void ahd_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t); -static __inline void ahd_set_scsi_status(struct scb *, uint32_t); -static __inline uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd); -static __inline uint32_t ahd_get_transaction_status(struct scb *); -static __inline uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd); -static __inline uint32_t ahd_get_scsi_status(struct scb *); -static __inline void ahd_set_transaction_tag(struct scb *, int, u_int); -static __inline u_long ahd_get_transfer_length(struct scb *); -static __inline int ahd_get_transfer_dir(struct scb *); -static __inline void ahd_set_residual(struct scb *, u_long); -static __inline void ahd_set_sense_residual(struct scb *scb, u_long resid); -static __inline u_long ahd_get_residual(struct scb *); -static __inline u_long ahd_get_sense_residual(struct scb *); -static __inline int ahd_perform_autosense(struct scb *); -static __inline uint32_t ahd_get_sense_bufsize(struct ahd_softc *, - struct scb *); -static __inline void ahd_notify_xfer_settings_change(struct ahd_softc *, - struct ahd_devinfo *); -static __inline void ahd_platform_scb_free(struct ahd_softc *ahd, - struct scb *scb); -static __inline void ahd_freeze_scb(struct scb *scb); - -static __inline -void ahd_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status) -{ - cmd->result &= ~(CAM_STATUS_MASK << 16); - cmd->result |= status << 16; -} - -static __inline -void ahd_set_transaction_status(struct scb *scb, uint32_t status) -{ - ahd_cmd_set_transaction_status(scb->io_ctx,status); -} - -static __inline -void ahd_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status) -{ - cmd->result &= ~0xFFFF; - cmd->result |= status; -} - -static __inline -void ahd_set_scsi_status(struct scb *scb, uint32_t status) -{ - ahd_cmd_set_scsi_status(scb->io_ctx, status); -} - -static __inline -uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd) -{ - return ((cmd->result >> 16) & CAM_STATUS_MASK); -} - -static __inline -uint32_t ahd_get_transaction_status(struct scb *scb) -{ - return (ahd_cmd_get_transaction_status(scb->io_ctx)); -} - -static __inline -uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd) -{ - return (cmd->result & 0xFFFF); -} - -static __inline -uint32_t ahd_get_scsi_status(struct scb *scb) -{ - return (ahd_cmd_get_scsi_status(scb->io_ctx)); -} - -static __inline -void ahd_set_transaction_tag(struct scb *scb, int enabled, u_int type) -{ - /* - * Nothing to do for linux as the incoming transaction - * has no concept of tag/non tagged, etc. - */ -} - -static __inline -u_long ahd_get_transfer_length(struct scb *scb) -{ - return (scb->platform_data->xfer_len); -} - -static __inline -int ahd_get_transfer_dir(struct scb *scb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40) - return (scb->io_ctx->sc_data_direction); -#else - if (scb->io_ctx->bufflen == 0) - return (CAM_DIR_NONE); - - switch(scb->io_ctx->cmnd[0]) { - case 0x08: /* READ(6) */ - case 0x28: /* READ(10) */ - case 0xA8: /* READ(12) */ - return (CAM_DIR_IN); - case 0x0A: /* WRITE(6) */ - case 0x2A: /* WRITE(10) */ - case 0xAA: /* WRITE(12) */ - return (CAM_DIR_OUT); - default: - return (CAM_DIR_NONE); - } -#endif -} - -static __inline -void ahd_set_residual(struct scb *scb, u_long resid) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - scb->io_ctx->resid = resid; -#else - scb->platform_data->resid = resid; -#endif -} - -static __inline -void ahd_set_sense_residual(struct scb *scb, u_long resid) -{ - scb->platform_data->sense_resid = resid; -} - -static __inline -u_long ahd_get_residual(struct scb *scb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - return (scb->io_ctx->resid); -#else - return (scb->platform_data->resid); -#endif -} - -static __inline -u_long ahd_get_sense_residual(struct scb *scb) -{ - return (scb->platform_data->sense_resid); -} - -static __inline -int ahd_perform_autosense(struct scb *scb) -{ - /* - * We always perform autosense in Linux. - * On other platforms this is set on a - * per-transaction basis. - */ - return (1); -} - -static __inline uint32_t -ahd_get_sense_bufsize(struct ahd_softc *ahd, struct scb *scb) -{ - return (sizeof(struct scsi_sense_data)); -} - -static __inline void -ahd_notify_xfer_settings_change(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo) -{ - /* Nothing to do here for linux */ -} - -static __inline void -ahd_platform_scb_free(struct ahd_softc *ahd, struct scb *scb) -{ - ahd->flags &= ~AHD_RESOURCE_SHORTAGE; -} - int ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg); void ahd_platform_free(struct ahd_softc *ahd); void ahd_platform_init(struct ahd_softc *ahd); void ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb); -void ahd_freeze_simq(struct ahd_softc *ahd); -void ahd_release_simq(struct ahd_softc *ahd); - -static __inline void -ahd_freeze_scb(struct scb *scb) -{ - if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) { - scb->io_ctx->result |= CAM_DEV_QFRZN << 16; - scb->platform_data->dev->qfrozen++; - } -} void ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd_queue_alg); @@ -1227,9 +284,9 @@ void ahd_platform_dump_card_state(struct ahd_softc *ahd); #ifdef CONFIG_PCI -#define AHD_PCI_CONFIG 1 +#define AIC_PCI_CONFIG 1 #else -#define AHD_PCI_CONFIG 0 +#define AIC_PCI_CONFIG 0 #endif #define bootverbose aic79xx_verbose extern uint32_t aic79xx_verbose; diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_osm_pci.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_osm_pci.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_osm_pci.c Wed Jul 30 09:18:49 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_osm_pci.c Tue Feb 10 01:47:04 2004 @@ -36,17 +36,19 @@ * 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#24 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm_pci.c#33 $ */ #include "aic79xx_osm.h" #include "aic79xx_inline.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -struct pci_device_id -{ -}; -#endif +/* + * Include aiclib_pci.c as part of our + * "module dependencies are hard" work around. + */ +#include "aiclib_pci.c" + +static int ahd_pci_module_registered; static int ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent); @@ -55,7 +57,6 @@ static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, u_long *bus_addr, uint8_t **maddr); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) static void ahd_linux_pci_dev_remove(struct pci_dev *pdev); /* We do our own ID filtering. So, grab all SCSI storage class devices. */ @@ -64,16 +65,20 @@ 0x9005, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SCSI << 8, 0xFFFF00, 0 }, + { + 0x9005, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_RAID << 8, 0xFFFF00, 0 + }, { 0 } }; MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table); struct pci_driver aic79xx_pci_driver = { - name: "aic79xx", - probe: ahd_linux_pci_dev_probe, - remove: ahd_linux_pci_dev_remove, - id_table: ahd_linux_pci_id_table + .name = "aic79xx", + .probe = ahd_linux_pci_dev_probe, + .remove = ahd_linux_pci_dev_remove, + .id_table = ahd_linux_pci_id_table }; static void @@ -92,21 +97,22 @@ if (ahd != NULL) { u_long s; + TAILQ_REMOVE(&ahd_tailq, ahd, links); + ahd_list_unlock(&l); ahd_lock(ahd, &s); ahd_intr_enable(ahd, FALSE); ahd_unlock(ahd, &s); ahd_free(ahd); - } - ahd_list_unlock(&l); + } else + ahd_list_unlock(&l); } -#endif /* !LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) */ static int ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { char buf[80]; struct ahd_softc *ahd; - ahd_dev_softc_t pci; + aic_dev_softc_t dev; struct ahd_pci_identity *entry; char *name; int error; @@ -117,7 +123,7 @@ TAILQ_FOREACH(ahd, &ahd_tailq, links) { struct pci_dev *probed_pdev; - probed_pdev = ahd->dev_softc; + probed_pdev = aic_pci_dev(ahd); if (probed_pdev->bus->number == pdev->bus->number && probed_pdev->devfn == pdev->devfn) break; @@ -127,8 +133,8 @@ return (-ENODEV); } - pci = pdev; - entry = ahd_find_pci_device(pci); + dev = aic_pci_dev_to_dev(pdev); + entry = ahd_find_pci_device(dev); if (entry == NULL) return (-ENODEV); @@ -138,9 +144,9 @@ * common detect routine. */ sprintf(buf, "ahd_pci:%d:%d:%d", - ahd_get_pci_bus(pci), - ahd_get_pci_slot(pci), - ahd_get_pci_function(pci)); + aic_get_pci_bus(dev), + aic_get_pci_slot(dev), + aic_get_pci_function(dev)); name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); if (name == NULL) return (-ENOMEM); @@ -148,13 +154,19 @@ ahd = ahd_alloc(NULL, name); if (ahd == NULL) return (-ENOMEM); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + ahd->dev_softc = dev; if (pci_enable_device(pdev)) { ahd_free(ahd); return (-ENODEV); } pci_set_master(pdev); + if (aic_set_consistent_dma_mask(ahd, 0xFFFFFFFF) != 0) { + printk(KERN_WARNING "aic79xx: Unable to set" + "coherent DMA mask.\n"); + ahd_free(ahd); + return (-ENOMEM); + } if (sizeof(bus_addr_t) > 4) { uint64_t memsize; bus_addr_t mask_64bit; @@ -164,26 +176,28 @@ mask_64bit = (bus_addr_t)0xFFFFFFFFFFFFFFFFULL; mask_39bit = (bus_addr_t)0x7FFFFFFFFFULL; if (memsize >= 0x8000000000ULL - && ahd_pci_set_dma_mask(pdev, mask_64bit) == 0) { + && aic_set_dma_mask(ahd, mask_64bit) == 0) { ahd->flags |= AHD_64BIT_ADDRESSING; ahd->platform_data->hw_dma_mask = mask_64bit; } else if (memsize > 0x80000000 - && ahd_pci_set_dma_mask(pdev, mask_39bit) == 0) { + && aic_set_dma_mask(ahd, mask_39bit) == 0) { ahd->flags |= AHD_39BIT_ADDRESSING; ahd->platform_data->hw_dma_mask = mask_39bit; } } else { - ahd_pci_set_dma_mask(pdev, 0xFFFFFFFF); + if (aic_set_dma_mask(ahd, 0xFFFFFFFF) != 0) { + printk(KERN_WARNING "aic79xx: Unable to set data " + "DMA mask.\n"); + ahd_free(ahd); + return (-ENOMEM); + } ahd->platform_data->hw_dma_mask = 0xFFFFFFFF; } -#endif - ahd->dev_softc = pci; error = ahd_pci_config(ahd, entry); if (error != 0) { ahd_free(ahd); return (-error); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_set_drvdata(pdev, ahd); if (aic79xx_detect_complete) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) @@ -194,80 +208,48 @@ return (-ENODEV); #endif } -#endif return (0); } int ahd_linux_pci_init(void) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - return (pci_module_init(&aic79xx_pci_driver)); -#else - struct pci_dev *pdev; - u_int class; - int found; - - /* If we don't have a PCI bus, we can't find any adapters. */ - if (pci_present() == 0) - return (0); - - found = 0; - pdev = NULL; - class = PCI_CLASS_STORAGE_SCSI << 8; - while ((pdev = pci_find_class(class, pdev)) != NULL) { - ahd_dev_softc_t pci; - int error; - - pci = pdev; - error = ahd_linux_pci_dev_probe(pdev, /*pci_devid*/NULL); - if (error == 0) - found++; - } - return (found); -#endif + int error; + + error = pci_module_init(&aic79xx_pci_driver); + if (error == 0) + ahd_pci_module_registered = 1; + return (error); } void ahd_linux_pci_exit(void) { - pci_unregister_driver(&aic79xx_pci_driver); + if (ahd_pci_module_registered != 0) + pci_unregister_driver(&aic79xx_pci_driver); } static int ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base, u_long *base2) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - *base = pci_resource_start(ahd->dev_softc, 0); + + *base = pci_resource_start(aic_pci_dev(ahd), 0); + /* * This is really the 3rd bar and should be at index 2, * but the Linux PCI code doesn't know how to "count" 64bit * bars. */ - *base2 = pci_resource_start(ahd->dev_softc, 3); -#else - *base = ahd_pci_read_config(ahd->dev_softc, AHD_PCI_IOADDR0, 4); - *base2 = ahd_pci_read_config(ahd->dev_softc, AHD_PCI_IOADDR1, 4); - *base &= PCI_BASE_ADDRESS_IO_MASK; - *base2 &= PCI_BASE_ADDRESS_IO_MASK; -#endif + *base2 = pci_resource_start(aic_pci_dev(ahd), 3); if (*base == 0 || *base2 == 0) return (ENOMEM); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - if (check_region(*base, 256) != 0 - || check_region(*base2, 256) != 0) - return (ENOMEM); - request_region(*base, 256, "aic79xx"); - request_region(*base2, 256, "aic79xx"); -#else if (request_region(*base, 256, "aic79xx") == 0) return (ENOMEM); if (request_region(*base2, 256, "aic79xx") == 0) { release_region(*base2, 256); return (ENOMEM); } -#endif return (0); } @@ -288,29 +270,18 @@ return (ENOMEM); error = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - start = pci_resource_start(ahd->dev_softc, 1); + start = pci_resource_start(aic_pci_dev(ahd), 1); base_page = start & PAGE_MASK; base_offset = start - base_page; -#else - start = ahd_pci_read_config(ahd->dev_softc, PCIR_MAPS+4, 4); - base_offset = start & PCI_BASE_ADDRESS_MEM_MASK; - base_page = base_offset & PAGE_MASK; - base_offset -= base_page; -#endif if (start != 0) { *bus_addr = start; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) if (request_mem_region(start, 0x1000, "aic79xx") == 0) error = ENOMEM; -#endif if (error == 0) { *maddr = ioremap_nocache(base_page, base_offset + 256); if (*maddr == NULL) { error = ENOMEM; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(start, 0x1000); -#endif } else *maddr += base_offset; } @@ -330,11 +301,10 @@ /* * If its allowed, we prefer memory mapped access. */ - command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 4); + command = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 4); command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN); base = 0; maddr = NULL; -#ifdef MMAPIO error = ahd_linux_pci_reserve_mem_region(ahd, &base, &maddr); if (error == 0) { ahd->platform_data->mem_busaddr = base; @@ -342,21 +312,19 @@ ahd->bshs[0].maddr = maddr; ahd->tags[1] = BUS_SPACE_MEMIO; ahd->bshs[1].maddr = maddr + 0x100; - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command | PCIM_CMD_MEMEN, 4); if (ahd_pci_test_register_access(ahd) != 0) { printf("aic79xx: PCI Device %d:%d:%d " "failed memory mapped test. Using PIO.\n", - ahd_get_pci_bus(ahd->dev_softc), - ahd_get_pci_slot(ahd->dev_softc), - ahd_get_pci_function(ahd->dev_softc)); + aic_get_pci_bus(ahd->dev_softc), + aic_get_pci_slot(ahd->dev_softc), + aic_get_pci_function(ahd->dev_softc)); iounmap((void *)((u_long)maddr & PAGE_MASK)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(ahd->platform_data->mem_busaddr, 0x1000); -#endif ahd->bshs[0].maddr = NULL; maddr = NULL; } else @@ -364,12 +332,11 @@ } else if (bootverbose) { printf("aic79xx: PCI%d:%d:%d MEM region 0x%lx " "unavailable. Cannot memory map device.\n", - ahd_get_pci_bus(ahd->dev_softc), - ahd_get_pci_slot(ahd->dev_softc), - ahd_get_pci_function(ahd->dev_softc), + aic_get_pci_bus(ahd->dev_softc), + aic_get_pci_slot(ahd->dev_softc), + aic_get_pci_function(ahd->dev_softc), base); } -#endif if (maddr == NULL) { u_long base2; @@ -384,13 +351,13 @@ } else { printf("aic79xx: PCI%d:%d:%d IO regions 0x%lx and 0x%lx" "unavailable. Cannot map device.\n", - ahd_get_pci_bus(ahd->dev_softc), - ahd_get_pci_slot(ahd->dev_softc), - ahd_get_pci_function(ahd->dev_softc), + aic_get_pci_bus(ahd->dev_softc), + aic_get_pci_slot(ahd->dev_softc), + aic_get_pci_function(ahd->dev_softc), base, base2); } } - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4); + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4); return (error); } @@ -399,49 +366,10 @@ { int error; - error = request_irq(ahd->dev_softc->irq, ahd_linux_isr, + error = request_irq(aic_pci_dev(ahd)->irq, ahd_linux_isr, SA_SHIRQ, "aic79xx", ahd); if (error == 0) - ahd->platform_data->irq = ahd->dev_softc->irq; + ahd->platform_data->irq = aic_pci_dev(ahd)->irq; return (-error); -} - -void -ahd_power_state_change(struct ahd_softc *ahd, ahd_power_state new_state) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pci_set_power_state(ahd->dev_softc, new_state); -#else - uint32_t cap; - u_int cap_offset; - - /* - * Traverse the capability list looking for - * the power management capability. - */ - cap = 0; - cap_offset = ahd_pci_read_config(ahd->dev_softc, - PCIR_CAP_PTR, /*bytes*/1); - while (cap_offset != 0) { - - cap = ahd_pci_read_config(ahd->dev_softc, - cap_offset, /*bytes*/4); - if ((cap & 0xFF) == 1 - && ((cap >> 16) & 0x3) > 0) { - uint32_t pm_control; - - pm_control = ahd_pci_read_config(ahd->dev_softc, - cap_offset + 4, - /*bytes*/4); - pm_control &= ~0x3; - pm_control |= new_state; - ahd_pci_write_config(ahd->dev_softc, - cap_offset + 4, - pm_control, /*bytes*/2); - break; - } - cap_offset = (cap >> 8) & 0xFF; - } -#endif } diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_pci.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_pci.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_pci.c Wed Jul 30 09:18:49 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_pci.c Tue Feb 10 01:47:04 2004 @@ -38,15 +38,15 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#75 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#86 $ */ #ifdef __linux__ #include "aic79xx_osm.h" #include "aic79xx_inline.h" #else +#include +__FBSDID("$FreeBSD$"); #include #include #endif @@ -65,23 +65,23 @@ } #define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull -#define ID_ALL_IROC_MASK 0xFFFFFF7FFFFFFFFFull +#define ID_ALL_IROC_MASK 0xFF7FFFFFFFFFFFFFull #define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull #define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull -#define ID_9005_GENERIC_IROC_MASK 0xFFF0FF7F00000000ull +#define ID_9005_GENERIC_IROC_MASK 0xFF70FFFF00000000ull #define ID_AIC7901 0x800F9005FFFF9005ull #define ID_AHA_29320A 0x8000900500609005ull #define ID_AHA_29320ALP 0x8017900500449005ull #define ID_AIC7901A 0x801E9005FFFF9005ull -#define ID_AHA_29320 0x8012900500429005ull -#define ID_AHA_29320B 0x8013900500439005ull #define ID_AHA_29320LP 0x8014900500449005ull #define ID_AIC7902 0x801F9005FFFF9005ull #define ID_AIC7902_B 0x801D9005FFFF9005ull #define ID_AHA_39320 0x8010900500409005ull +#define ID_AHA_29320 0x8012900500429005ull +#define ID_AHA_29320B 0x8013900500439005ull #define ID_AHA_39320_B 0x8015900500409005ull #define ID_AHA_39320A 0x8016900500409005ull #define ID_AHA_39320D 0x8011900500419005ull @@ -92,10 +92,11 @@ #define ID_AIC7902_PCI_REV_B0 0x10 #define SUBID_HP 0x0E11 +#define DEVID_9005_HOSTRAID(id) ((id) & 0x80) + #define DEVID_9005_TYPE(id) ((id) & 0xF) #define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ #define DEVID_9005_TYPE_HBA_2EXT 0x1 /* 2 External Ports */ -#define DEVID_9005_TYPE_IROC 0x8 /* Raid(0,1,10) Card */ #define DEVID_9005_TYPE_MB 0xF /* On Motherboard */ #define DEVID_9005_MFUNC(id) ((id) & 0x10) @@ -117,6 +118,7 @@ static ahd_device_setup_t ahd_aic7901_setup; static ahd_device_setup_t ahd_aic7901A_setup; static ahd_device_setup_t ahd_aic7902_setup; +static ahd_device_setup_t ahd_aic790X_setup; struct ahd_pci_identity ahd_pci_ident_table [] = { @@ -135,24 +137,24 @@ }, /* aic7901A based controllers */ { - ID_AHA_29320, + ID_AHA_29320LP, ID_ALL_MASK, - "Adaptec 29320 Ultra320 SCSI adapter", + "Adaptec 29320LP Ultra320 SCSI adapter", ahd_aic7901A_setup }, + /* aic7902 based controllers */ { - ID_AHA_29320B, + ID_AHA_29320, ID_ALL_MASK, - "Adaptec 29320B Ultra320 SCSI adapter", - ahd_aic7901A_setup + "Adaptec 29320 Ultra320 SCSI adapter", + ahd_aic7902_setup }, { - ID_AHA_29320LP, + ID_AHA_29320B, ID_ALL_MASK, - "Adaptec 29320LP Ultra320 SCSI adapter", - ahd_aic7901A_setup + "Adaptec 29320B Ultra320 SCSI adapter", + ahd_aic7902_setup }, - /* aic7902 based controllers */ { ID_AHA_39320, ID_ALL_MASK, @@ -195,21 +197,9 @@ "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter", ahd_aic7902_setup }, - { - ID_AHA_29320, - ID_ALL_MASK, - "Adaptec 29320 Ultra320 SCSI adapter", - ahd_aic7902_setup - }, - { - ID_AHA_29320B, - ID_ALL_MASK, - "Adaptec 29320B Ultra320 SCSI adapter", - ahd_aic7902_setup - }, /* Generic chip probes for devices we don't know 'exactly' */ { - ID_AIC7901 & ID_DEV_VENDOR_MASK, + ID_AIC7901 & ID_9005_GENERIC_MASK, ID_DEV_VENDOR_MASK, "Adaptec AIC7901 Ultra320 SCSI adapter", ahd_aic7901_setup @@ -274,7 +264,7 @@ static void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat); struct ahd_pci_identity * -ahd_find_pci_device(ahd_dev_softc_t pci) +ahd_find_pci_device(aic_dev_softc_t pci) { uint64_t full_id; uint16_t device; @@ -284,15 +274,23 @@ struct ahd_pci_identity *entry; u_int i; - vendor = ahd_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); - device = ahd_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); - subvendor = ahd_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); - subdevice = ahd_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); + vendor = aic_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); + device = aic_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); + subvendor = aic_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); + subdevice = aic_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); full_id = ahd_compose_id(device, vendor, subdevice, subvendor); + /* + * If we are configured to attach to HostRAID + * controllers, mask out the IROC/HostRAID bit + * in the + */ + if (ahd_attach_to_HostRAID_controllers) + full_id &= ID_ALL_IROC_MASK; + for (i = 0; i < ahd_num_pci_devs; i++) { entry = &ahd_pci_ident_table[i]; if (entry->full_id == (full_id & entry->id_mask)) { @@ -312,15 +310,24 @@ u_long l; u_int command; uint32_t devconfig; + uint16_t device; uint16_t subvendor; int error; shared_scb_data = NULL; ahd->description = entry->name; /* + * Record if this is a HostRAID board. + */ + device = aic_pci_read_config(ahd->dev_softc, + PCIR_DEVICE, /*bytes*/2); + if (DEVID_9005_HOSTRAID(device)) + ahd->flags |= AHD_HOSTRAID_BOARD; + + /* * Record if this is an HP board. */ - subvendor = ahd_pci_read_config(ahd->dev_softc, + subvendor = aic_pci_read_config(ahd->dev_softc, PCIR_SUBVEND_0, /*bytes*/2); if (subvendor == SUBID_HP) ahd->flags |= AHD_HP_BOARD; @@ -329,7 +336,7 @@ if (error != 0) return (error); - devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); + devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) { ahd->chip |= AHD_PCI; /* Disable PCIX workarounds when running in PCI mode. */ @@ -339,7 +346,7 @@ } ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)]; - ahd_power_state_change(ahd, AHD_POWER_STATE_D0); + aic_power_state_change(ahd, AIC_POWER_STATE_D0); error = ahd_pci_map_registers(ahd); if (error != 0) @@ -357,17 +364,17 @@ if (bootverbose) printf("%s: Enabling 39Bit Addressing\n", ahd_name(ahd)); - devconfig = ahd_pci_read_config(ahd->dev_softc, + devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); devconfig |= DACEN; - ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, + aic_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); } /* Ensure busmastering is enabled */ - command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); + command = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); command |= PCIM_CMD_BUSMASTEREN; - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2); + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2); error = ahd_softc_init(ahd); if (error != 0) @@ -380,7 +387,7 @@ return (ENXIO); ahd->pci_cachesize = - ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, + aic_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, /*bytes*/1) & CACHESIZE; ahd->pci_cachesize *= 4; @@ -430,8 +437,8 @@ * Enable PCI error interrupt status, but suppress NMIs * generated by SERR raised due to target aborts. */ - cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, + cmd = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2); /* @@ -451,8 +458,10 @@ * or read prefetching could be initiated by the * CPU or host bridge. Our device does not support * either, so look for data corruption and/or flaged - * PCI errors. + * PCI errors. First pause without causing another + * chip reset. */ + hcntrl &= ~CHIPRST; ahd_outb(ahd, HCNTRL, hcntrl|PAUSE); while (ahd_is_paused(ahd) == 0) ; @@ -461,9 +470,9 @@ ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); targpcistat = ahd_inb(ahd, TARGPCISTAT); ahd_outb(ahd, TARGPCISTAT, targpcistat); - pci_status1 = ahd_pci_read_config(ahd->dev_softc, + pci_status1 = aic_pci_read_config(ahd->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, pci_status1, /*bytes*/1); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_outb(ahd, CLRINT, CLRPCIINT); @@ -492,14 +501,14 @@ /* Silently clear any latched errors. */ ahd_outb(ahd, TARGPCISTAT, targpcistat); - pci_status1 = ahd_pci_read_config(ahd->dev_softc, + pci_status1 = aic_pci_read_config(ahd->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, pci_status1, /*bytes*/1); ahd_outb(ahd, CLRINT, CLRPCIINT); } ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS); - ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); + aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); return (error); } @@ -648,14 +657,14 @@ uint8_t termctl; uint32_t devconfig; - devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); + devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); devconfig &= ~STPWLEVEL; if ((ahd->flags & AHD_STPWLEVEL_A) != 0) devconfig |= STPWLEVEL; if (bootverbose) printf("%s: STPWLEVEL is %s\n", ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off"); - ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); + aic_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); /* Make sure current sensing is off. */ if ((ahd->flags & AHD_CURRENT_SENSING) != 0) { @@ -700,6 +709,7 @@ * Now set the termination based on what we found. */ sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN; + ahd->flags &= ~AHD_TERM_ENB_A; if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) { ahd->flags |= AHD_TERM_ENB_A; sxfrctl1 |= STPWEN; @@ -832,9 +842,9 @@ } } } - pci_status1 = ahd_pci_read_config(ahd->dev_softc, + pci_status1 = aic_pci_read_config(ahd->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, pci_status1, /*bytes*/1); ahd_restore_modes(ahd, saved_modes); ahd_outb(ahd, CLRINT, CLRPCIINT); @@ -856,7 +866,7 @@ * Check for splits in all modes. Modes 0 and 1 * additionally have SG engine splits to look at. */ - pcix_status = ahd_pci_read_config(ahd->dev_softc, PCIXR_STATUS, + pcix_status = aic_pci_read_config(ahd->dev_softc, PCIXR_STATUS, /*bytes*/2); printf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n", ahd_name(ahd), pcix_status); @@ -905,7 +915,7 @@ /* * Clear PCI-X status bits. */ - ahd_pci_write_config(ahd->dev_softc, PCIXR_STATUS, + aic_pci_write_config(ahd->dev_softc, PCIXR_STATUS, pcix_status, /*bytes*/2); ahd_outb(ahd, CLRINT, CLRSPLTINT); ahd_restore_modes(ahd, saved_modes); @@ -914,44 +924,44 @@ static int ahd_aic7901_setup(struct ahd_softc *ahd) { - int error; - error = ahd_aic7902_setup(ahd); - if (error != 0) - return (error); ahd->chip = AHD_AIC7901; - return (0); + ahd->features = AHD_AIC7901_FE; + return (ahd_aic790X_setup(ahd)); } static int ahd_aic7901A_setup(struct ahd_softc *ahd) { - int error; - error = ahd_aic7902_setup(ahd); - if (error != 0) - return (error); ahd->chip = AHD_AIC7901A; - return (0); + ahd->features = AHD_AIC7901A_FE; + return (ahd_aic790X_setup(ahd)); } static int ahd_aic7902_setup(struct ahd_softc *ahd) { - ahd_dev_softc_t pci; + ahd->chip = AHD_AIC7902; + ahd->features = AHD_AIC7902_FE; + return (ahd_aic790X_setup(ahd)); +} + +static int +ahd_aic790X_setup(struct ahd_softc *ahd) +{ + aic_dev_softc_t pci; u_int rev; pci = ahd->dev_softc; - rev = ahd_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev < ID_AIC7902_PCI_REV_A4) { printf("%s: Unable to attach to unsupported chip revision %d\n", ahd_name(ahd), rev); - ahd_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2); + aic_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2); return (ENXIO); } - ahd->channel = ahd_get_pci_function(pci) + 'A'; - ahd->chip = AHD_AIC7902; - ahd->features = AHD_AIC7902_FE; + ahd->channel = aic_get_pci_function(pci) + 'A'; if (rev < ID_AIC7902_PCI_REV_B0) { /* * Enable A series workarounds. @@ -979,9 +989,14 @@ 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. @@ -996,10 +1011,10 @@ * XXX - Find out exactly what this does from the hardware * folks! */ - devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); - ahd_pci_write_config(pci, DEVCONFIG1, + devconfig1 = aic_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); + aic_pci_write_config(pci, DEVCONFIG1, devconfig1|PREQDIS, /*bytes*/1); - devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); + devconfig1 = aic_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); } return (0); diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_proc.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_proc.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_proc.c Wed Jul 30 09:18:49 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_proc.c Tue Feb 10 00:15:16 2004 @@ -37,7 +37,7 @@ * String handling code courtesy of Gerard Roudier's * sym driver. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#19 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#20 $ */ #include "aic79xx_osm.h" #include "aic79xx_inline.h" @@ -49,7 +49,7 @@ u_int our_id, char channel, u_int target_id, u_int target_offset); static void ahd_dump_device_state(struct info_str *info, - struct ahd_linux_device *dev); + struct aic_linux_device *dev); static int ahd_proc_write_seeprom(struct ahd_softc *ahd, char *buffer, int length); @@ -166,7 +166,7 @@ u_int our_id, char channel, u_int target_id, u_int target_offset) { - struct ahd_linux_target *targ; + struct aic_linux_target *targ; struct ahd_initiator_tinfo *tinfo; struct ahd_tmode_tstate *tstate; int lun; @@ -187,7 +187,7 @@ copy_info(info, "\tTransmission Errors %ld\n", targ->errors_detected); for (lun = 0; lun < AHD_NUM_LUNS; lun++) { - struct ahd_linux_device *dev; + struct aic_linux_device *dev; dev = targ->devices[lun]; @@ -199,7 +199,7 @@ } static void -ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev) +ahd_dump_device_state(struct info_str *info, struct aic_linux_device *dev) { copy_info(info, "\tChannel %c Target %d Lun %d Settings\n", dev->target->channel + 'A', dev->target->target, dev->lun); diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_reg.h linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_reg.h --- linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_reg.h Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_reg.h Tue Feb 10 01:47:04 2004 @@ -2,8 +2,8 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $ */ typedef int (ahd_reg_print_t)(u_int, u_int *, u_int); typedef struct ahd_reg_parse_entry { @@ -83,17 +83,17 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_clrseqintstat_print; +ahd_reg_print_t ahd_seqintstat_print; #else -#define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap) +#define ahd_seqintstat_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SEQINTSTAT", 0x0c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_seqintstat_print; +ahd_reg_print_t ahd_clrseqintstat_print; #else -#define ahd_seqintstat_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SEQINTSTAT", 0x0c, regvalue, cur_col, wrap) +#define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -412,17 +412,17 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_businitid_print; +ahd_reg_print_t ahd_dlcount_print; #else -#define ahd_businitid_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap) +#define ahd_dlcount_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dlcount_print; +ahd_reg_print_t ahd_businitid_print; #else -#define ahd_dlcount_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap) +#define ahd_businitid_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -517,13 +517,6 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sblkctl_print; -#else -#define ahd_sblkctl_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_optionmode_print; #else #define ahd_optionmode_print(regvalue, cur_col, wrap) \ @@ -531,10 +524,10 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sstat0_print; +ahd_reg_print_t ahd_sblkctl_print; #else -#define ahd_sstat0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap) +#define ahd_sblkctl_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -545,6 +538,13 @@ #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_sstat0_print; +#else +#define ahd_sstat0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_simode0_print; #else #define ahd_simode0_print(regvalue, cur_col, wrap) \ @@ -573,17 +573,17 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_clrsint2_print; +ahd_reg_print_t ahd_simode2_print; #else -#define ahd_clrsint2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap) +#define ahd_simode2_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_simode2_print; +ahd_reg_print_t ahd_clrsint2_print; #else -#define ahd_simode2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap) +#define ahd_clrsint2_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -685,13 +685,6 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_lqomode0_print; -#else -#define ahd_lqomode0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_lqostat0_print; #else #define ahd_lqostat0_print(regvalue, cur_col, wrap) \ @@ -706,6 +699,20 @@ #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_lqomode0_print; +#else +#define ahd_lqomode0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_lqomode1_print; +#else +#define ahd_lqomode1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_lqostat1_print; #else #define ahd_lqostat1_print(regvalue, cur_col, wrap) \ @@ -720,13 +727,6 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_lqomode1_print; -#else -#define ahd_lqomode1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_lqostat2_print; #else #define ahd_lqostat2_print(regvalue, cur_col, wrap) \ @@ -909,17 +909,17 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_scschkn_print; +ahd_reg_print_t ahd_annexdat_print; #else -#define ahd_scschkn_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap) +#define ahd_annexdat_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "ANNEXDAT", 0x66, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_annexdat_print; +ahd_reg_print_t ahd_scschkn_print; #else -#define ahd_annexdat_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "ANNEXDAT", 0x66, regvalue, cur_col, wrap) +#define ahd_scschkn_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1000,17 +1000,17 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_pll400cnt0_print; +ahd_reg_print_t ahd_unfairness_print; #else -#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap) +#define ahd_unfairness_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_unfairness_print; +ahd_reg_print_t ahd_pll400cnt0_print; #else -#define ahd_unfairness_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap) +#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1056,13 +1056,6 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sghaddr_print; -#else -#define ahd_sghaddr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_scbhaddr_print; #else #define ahd_scbhaddr_print(regvalue, cur_col, wrap) \ @@ -1070,10 +1063,10 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sghcnt_print; +ahd_reg_print_t ahd_sghaddr_print; #else -#define ahd_sghcnt_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap) +#define ahd_sghaddr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1084,6 +1077,13 @@ #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_sghcnt_print; +#else +#define ahd_sghcnt_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dff_thrsh_print; #else #define ahd_dff_thrsh_print(regvalue, cur_col, wrap) \ @@ -1154,13 +1154,6 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dchrxmsg1_print; -#else -#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_cmcrxmsg1_print; #else #define ahd_cmcrxmsg1_print(regvalue, cur_col, wrap) \ @@ -1168,17 +1161,17 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dchrxmsg2_print; +ahd_reg_print_t ahd_dchrxmsg1_print; #else -#define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap) +#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ovlyrxmsg2_print; +ahd_reg_print_t ahd_dchrxmsg2_print; #else -#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap) +#define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1196,6 +1189,13 @@ #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_ovlyrxmsg2_print; +#else +#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dchrxmsg3_print; #else #define ahd_dchrxmsg3_print(regvalue, cur_col, wrap) \ @@ -1203,6 +1203,13 @@ #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_ovlyrxmsg3_print; +#else +#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_cmcrxmsg3_print; #else #define ahd_cmcrxmsg3_print(regvalue, cur_col, wrap) \ @@ -1217,13 +1224,6 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ovlyrxmsg3_print; -#else -#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_ovlyseqbcnt_print; #else #define ahd_ovlyseqbcnt_print(regvalue, cur_col, wrap) \ @@ -1231,13 +1231,6 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_cmcseqbcnt_print; -#else -#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dchseqbcnt_print; #else #define ahd_dchseqbcnt_print(regvalue, cur_col, wrap) \ @@ -1245,17 +1238,17 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_cmcspltstat0_print; +ahd_reg_print_t ahd_cmcseqbcnt_print; #else -#define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap) +#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ovlyspltstat0_print; +ahd_reg_print_t ahd_cmcspltstat0_print; #else -#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap) +#define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1266,10 +1259,10 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dchspltstat1_print; +ahd_reg_print_t ahd_ovlyspltstat0_print; #else -#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap) +#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1287,6 +1280,13 @@ #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_dchspltstat1_print; +#else +#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_sgrxmsg0_print; #else #define ahd_sgrxmsg0_print(regvalue, cur_col, wrap) \ @@ -1378,17 +1378,17 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sfunct_print; +ahd_reg_print_t ahd_sgspltstat1_print; #else -#define ahd_sfunct_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap) +#define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sgspltstat1_print; +ahd_reg_print_t ahd_sfunct_print; #else -#define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap) +#define ahd_sfunct_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1504,17 +1504,17 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ccscbaddr_print; +ahd_reg_print_t ahd_ccscbadr_bk_print; #else -#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap) +#define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ccscbadr_bk_print; +ahd_reg_print_t ahd_ccscbaddr_print; #else -#define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap) +#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1525,17 +1525,17 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ccsgctl_print; +ahd_reg_print_t ahd_ccscbctl_print; #else -#define ahd_ccsgctl_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap) +#define ahd_ccscbctl_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CCSCBCTL", 0xad, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ccscbctl_print; +ahd_reg_print_t ahd_ccsgctl_print; #else -#define ahd_ccscbctl_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CCSCBCTL", 0xad, regvalue, cur_col, wrap) +#define ahd_ccsgctl_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1707,13 +1707,6 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dfptrs_print; -#else -#define ahd_dfptrs_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_rcvrbiascalc_print; #else #define ahd_rcvrbiascalc_print(regvalue, cur_col, wrap) \ @@ -1721,10 +1714,10 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dfbkptr_print; +ahd_reg_print_t ahd_dfptrs_print; #else -#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap) +#define ahd_dfptrs_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1735,6 +1728,13 @@ #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_dfbkptr_print; +#else +#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dfdbctl_print; #else #define ahd_dfdbctl_print(regvalue, cur_col, wrap) \ @@ -1826,17 +1826,17 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_brkaddr1_print; +ahd_reg_print_t ahd_brkaddr0_print; #else -#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap) +#define ahd_brkaddr0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_brkaddr0_print; +ahd_reg_print_t ahd_brkaddr1_print; #else -#define ahd_brkaddr0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap) +#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1889,13 +1889,6 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_curaddr_print; -#else -#define ahd_curaddr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_intvec1_addr_print; #else #define ahd_intvec1_addr_print(regvalue, cur_col, wrap) \ @@ -1903,10 +1896,10 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_intvec2_addr_print; +ahd_reg_print_t ahd_curaddr_print; #else -#define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap) +#define ahd_curaddr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1917,6 +1910,13 @@ #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_intvec2_addr_print; +#else +#define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_longjmp_addr_print; #else #define ahd_longjmp_addr_print(regvalue, cur_col, wrap) \ @@ -1994,192 +1994,213 @@ #endif #if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_complete_dma_scb_tail_print; +#else +#define ahd_complete_dma_scb_tail_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL", 0x12e, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_complete_on_qfreeze_head_print; +#else +#define ahd_complete_on_qfreeze_head_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD", 0x130, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_qfreeze_count_print; #else #define ahd_qfreeze_count_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x12e, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x132, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_kernel_qfreeze_count_print; +#else +#define ahd_kernel_qfreeze_count_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT", 0x134, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_saved_mode_print; #else #define ahd_saved_mode_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SAVED_MODE", 0x130, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SAVED_MODE", 0x136, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_msg_out_print; #else #define ahd_msg_out_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "MSG_OUT", 0x131, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "MSG_OUT", 0x137, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dmaparams_print; #else #define ahd_dmaparams_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DMAPARAMS", 0x132, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "DMAPARAMS", 0x138, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_seq_flags_print; #else #define ahd_seq_flags_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x133, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x139, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_saved_scsiid_print; #else #define ahd_saved_scsiid_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x134, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x13a, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_saved_lun_print; #else #define ahd_saved_lun_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SAVED_LUN", 0x135, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SAVED_LUN", 0x13b, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_lastphase_print; #else #define ahd_lastphase_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LASTPHASE", 0x136, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "LASTPHASE", 0x13c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_qoutfifo_entry_valid_tag_print; #else #define ahd_qoutfifo_entry_valid_tag_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x137, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x13d, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_shared_data_addr_print; +ahd_reg_print_t ahd_kernel_tqinpos_print; #else -#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x138, regvalue, cur_col, wrap) +#define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x13e, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_qoutfifo_next_addr_print; +ahd_reg_print_t ahd_tqinpos_print; #else -#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x13c, regvalue, cur_col, wrap) +#define ahd_tqinpos_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "TQINPOS", 0x13f, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_kernel_tqinpos_print; +ahd_reg_print_t ahd_shared_data_addr_print; #else -#define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x140, regvalue, cur_col, wrap) +#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x140, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_tqinpos_print; +ahd_reg_print_t ahd_qoutfifo_next_addr_print; #else -#define ahd_tqinpos_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "TQINPOS", 0x141, regvalue, cur_col, wrap) +#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x144, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_arg_1_print; #else #define ahd_arg_1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "ARG_1", 0x142, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "ARG_1", 0x148, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_arg_2_print; #else #define ahd_arg_2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "ARG_2", 0x143, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "ARG_2", 0x149, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_last_msg_print; #else #define ahd_last_msg_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LAST_MSG", 0x144, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "LAST_MSG", 0x14a, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_scsiseq_template_print; #else #define ahd_scsiseq_template_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x145, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x14b, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_initiator_tag_print; #else #define ahd_initiator_tag_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x146, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x14c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_seq_flags2_print; #else #define ahd_seq_flags2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x147, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x14d, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_allocfifo_scbptr_print; #else #define ahd_allocfifo_scbptr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x148, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x14e, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_int_coalescing_timer_print; #else #define ahd_int_coalescing_timer_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x14a, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x150, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_int_coalescing_maxcmds_print; #else #define ahd_int_coalescing_maxcmds_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x14c, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x152, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_int_coalescing_mincmds_print; #else #define ahd_int_coalescing_mincmds_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x14d, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x153, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_cmds_pending_print; #else #define ahd_cmds_pending_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CMDS_PENDING", 0x14e, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "CMDS_PENDING", 0x154, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_int_coalescing_cmdcount_print; #else #define ahd_int_coalescing_cmdcount_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x150, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x156, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_local_hs_mailbox_print; #else #define ahd_local_hs_mailbox_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x151, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x157, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_cmdsize_table_print; #else #define ahd_cmdsize_table_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x152, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x158, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -2434,13 +2455,6 @@ #define HOST_TQINPOS 0x80 #define ENINT_COALESCE 0x40 -#define CLRSEQINTSTAT 0x0c -#define CLRSEQ_SWTMRTO 0x10 -#define CLRSEQ_SEQINT 0x08 -#define CLRSEQ_SCSIINT 0x04 -#define CLRSEQ_PCIINT 0x02 -#define CLRSEQ_SPLTINT 0x01 - #define SEQINTSTAT 0x0c #define SEQ_SWTMRTO 0x10 #define SEQ_SEQINT 0x08 @@ -2448,6 +2462,13 @@ #define SEQ_PCIINT 0x02 #define SEQ_SPLTINT 0x01 +#define CLRSEQINTSTAT 0x0c +#define CLRSEQ_SWTMRTO 0x10 +#define CLRSEQ_SEQINT 0x08 +#define CLRSEQ_SCSIINT 0x04 +#define CLRSEQ_PCIINT 0x02 +#define CLRSEQ_SPLTINT 0x01 + #define SWTIMER 0x0e #define SNSCB_QOFF 0x10 @@ -2623,10 +2644,10 @@ #define BIOSCANCELEN 0x10 #define SPIOEN 0x08 -#define BUSINITID 0x3c - #define DLCOUNT 0x3c +#define BUSINITID 0x3c + #define SXFRCTL1 0x3d #define BITBUCKET 0x80 #define ENSACHK 0x40 @@ -2693,13 +2714,6 @@ #define SELID_MASK 0xf0 #define ONEBIT 0x08 -#define SBLKCTL 0x4a -#define DIAGLEDEN 0x80 -#define DIAGLEDON 0x40 -#define ENAB40 0x08 -#define ENAB20 0x04 -#define SELWIDE 0x02 - #define OPTIONMODE 0x4a #define OPTIONMODE_DEFAULTS 0x02 #define BIOSCANCTL 0x80 @@ -2709,15 +2723,12 @@ #define ENDGFORMCHK 0x04 #define AUTO_MSGOUT_DE 0x02 -#define SSTAT0 0x4b -#define TARGET 0x80 -#define SELDO 0x40 -#define SELDI 0x20 -#define SELINGO 0x10 -#define IOERR 0x08 -#define OVERRUN 0x04 -#define SPIORDY 0x02 -#define ARBDO 0x01 +#define SBLKCTL 0x4a +#define DIAGLEDEN 0x80 +#define DIAGLEDON 0x40 +#define ENAB40 0x08 +#define ENAB20 0x04 +#define SELWIDE 0x02 #define CLRSINT0 0x4b #define CLRSELDO 0x40 @@ -2728,6 +2739,16 @@ #define CLRSPIORDY 0x02 #define CLRARBDO 0x01 +#define SSTAT0 0x4b +#define TARGET 0x80 +#define SELDO 0x40 +#define SELDI 0x20 +#define SELINGO 0x10 +#define IOERR 0x08 +#define OVERRUN 0x04 +#define SPIORDY 0x02 +#define ARBDO 0x01 + #define SIMODE0 0x4b #define ENSELDO 0x40 #define ENSELDI 0x20 @@ -2768,17 +2789,17 @@ #define BUSFREE_DFF0 0x80 #define BUSFREE_LQO 0x40 +#define SIMODE2 0x4d +#define ENWIDE_RES 0x04 +#define ENSDONE 0x02 +#define ENDMADONE 0x01 + #define CLRSINT2 0x4d #define CLRNONPACKREQ 0x20 #define CLRWIDE_RES 0x04 #define CLRSDONE 0x02 #define CLRDMADONE 0x01 -#define SIMODE2 0x4d -#define ENWIDE_RES 0x04 -#define ENSDONE 0x02 -#define ENDMADONE 0x01 - #define PERRDIAG 0x4e #define HIZERO 0x80 #define HIPERR 0x40 @@ -2871,13 +2892,6 @@ #define CLRNTRAMPERR 0x02 #define CLROSRAMPERR 0x01 -#define LQOMODE0 0x54 -#define ENLQOTARGSCBPERR 0x10 -#define ENLQOSTOPT2 0x08 -#define ENLQOATNLQ 0x04 -#define ENLQOATNPKT 0x02 -#define ENLQOTCRC 0x01 - #define LQOSTAT0 0x54 #define LQOTARGSCBPERR 0x10 #define LQOSTOPT2 0x08 @@ -2892,6 +2906,20 @@ #define CLRLQOATNPKT 0x02 #define CLRLQOTCRC 0x01 +#define LQOMODE0 0x54 +#define ENLQOTARGSCBPERR 0x10 +#define ENLQOSTOPT2 0x08 +#define ENLQOATNLQ 0x04 +#define ENLQOATNPKT 0x02 +#define ENLQOTCRC 0x01 + +#define LQOMODE1 0x55 +#define ENLQOINITSCBPERR 0x10 +#define ENLQOSTOPI2 0x08 +#define ENLQOBADQAS 0x04 +#define ENLQOBUSFREE 0x02 +#define ENLQOPHACHGINPKT 0x01 + #define LQOSTAT1 0x55 #define LQOINITSCBPERR 0x10 #define LQOSTOPI2 0x08 @@ -2906,13 +2934,6 @@ #define CLRLQOBUSFREE 0x02 #define CLRLQOPHACHGINPKT 0x01 -#define LQOMODE1 0x55 -#define ENLQOINITSCBPERR 0x10 -#define ENLQOSTOPI2 0x08 -#define ENLQOBADQAS 0x04 -#define ENLQOBUSFREE 0x02 -#define ENLQOPHACHGINPKT 0x01 - #define LQOSTAT2 0x56 #define LQOPKT 0xe0 #define LQOWAITFIFO 0x10 @@ -3028,6 +3049,8 @@ #define ANNEXCOL 0x65 +#define ANNEXDAT 0x66 + #define SCSCHKN 0x66 #define STSELSKIDDIS 0x40 #define CURRFIFODEF 0x20 @@ -3037,8 +3060,6 @@ #define SHVALIDSTDIS 0x02 #define LSTSGCLRDIS 0x01 -#define ANNEXDAT 0x66 - #define IOWNID 0x67 #define PLL960CTL0 0x68 @@ -3071,10 +3092,10 @@ #define PLL_CNTCLR 0x40 #define PLL_RST 0x01 -#define PLL400CNT0 0x6e - #define UNFAIRNESS 0x6e +#define PLL400CNT0 0x6e + #define HADDR 0x70 #define PLLDELAY 0x70 @@ -3088,14 +3109,14 @@ #define HODMAEN 0x7a -#define SGHADDR 0x7c - #define SCBHADDR 0x7c -#define SGHCNT 0x84 +#define SGHADDR 0x7c #define SCBHCNT 0x84 +#define SGHCNT 0x84 + #define DFF_THRSH 0x88 #define WR_DFTHRSH 0x70 #define RD_DFTHRSH 0x07 @@ -3113,8 +3134,8 @@ #define RD_DFTHRSH_63 0x03 #define RD_DFTHRSH_50 0x02 #define RD_DFTHRSH_25 0x01 -#define WR_DFTHRSH_MIN 0x00 #define RD_DFTHRSH_MIN 0x00 +#define WR_DFTHRSH_MIN 0x00 #define ROMADDR 0x8a @@ -3150,20 +3171,22 @@ #define DCH1NSEN 0x02 #define DCH0NSEN 0x01 -#define DCHRXMSG1 0x91 - #define CMCRXMSG1 0x91 -#define DCHRXMSG2 0x92 +#define DCHRXMSG1 0x91 -#define OVLYRXMSG2 0x92 +#define DCHRXMSG2 0x92 #define CMCRXMSG2 0x92 #define OST 0x92 +#define OVLYRXMSG2 0x92 + #define DCHRXMSG3 0x93 +#define OVLYRXMSG3 0x93 + #define CMCRXMSG3 0x93 #define PCIXCTL 0x93 @@ -3175,26 +3198,24 @@ #define TSCSERREN 0x02 #define CMPABCDIS 0x01 -#define OVLYRXMSG3 0x93 - #define OVLYSEQBCNT 0x94 -#define CMCSEQBCNT 0x94 - #define DCHSEQBCNT 0x94 -#define CMCSPLTSTAT0 0x96 +#define CMCSEQBCNT 0x94 -#define OVLYSPLTSTAT0 0x96 +#define CMCSPLTSTAT0 0x96 #define DCHSPLTSTAT0 0x96 -#define DCHSPLTSTAT1 0x97 +#define OVLYSPLTSTAT0 0x96 #define CMCSPLTSTAT1 0x97 #define OVLYSPLTSTAT1 0x97 +#define DCHSPLTSTAT1 0x97 + #define SGRXMSG0 0x98 #define CDNUM 0xf8 #define CFNUM 0x07 @@ -3244,13 +3265,13 @@ #define RXSCEMSG 0x02 #define RXSPLTRSP 0x01 +#define SGSPLTSTAT1 0x9f +#define RXDATABUCKET 0x01 + #define SFUNCT 0x9f #define TEST_GROUP 0xf0 #define TEST_NUM 0x0f -#define SGSPLTSTAT1 0x9f -#define RXDATABUCKET 0x01 - #define DF0PCISTAT 0xa0 #define REG0 0xa0 @@ -3299,10 +3320,10 @@ #define CCSGADDR 0xac -#define CCSCBADDR 0xac - #define CCSCBADR_BK 0xac +#define CCSCBADDR 0xac + #define CMC_RAMBIST 0xad #define SG_ELEMENT_SIZE 0x80 #define SCBRAMBIST_FAIL 0x40 @@ -3311,14 +3332,6 @@ #define CMC_BUFFER_BIST_FAIL 0x02 #define CMC_BUFFER_BIST_EN 0x01 -#define CCSGCTL 0xad -#define CCSGEN 0x0c -#define CCSGDONE 0x80 -#define SG_CACHE_AVAIL 0x10 -#define CCSGENACK 0x08 -#define SG_FETCH_REQ 0x02 -#define CCSGRESET 0x01 - #define CCSCBCTL 0xad #define CCSCBDONE 0x80 #define ARRDONE 0x40 @@ -3327,6 +3340,14 @@ #define CCSCBDIR 0x04 #define CCSCBRESET 0x01 +#define CCSGCTL 0xad +#define CCSGEN 0x0c +#define CCSGDONE 0x80 +#define SG_CACHE_AVAIL 0x10 +#define CCSGENACK 0x08 +#define SG_FETCH_REQ 0x02 +#define CCSGRESET 0x01 + #define CCSGRAM 0xb0 #define FLEXADR 0xb0 @@ -3356,8 +3377,8 @@ #define SEEDAT 0xbc #define SEECTL 0xbe -#define SEEOP_EWEN 0x40 #define SEEOP_WALL 0x40 +#define SEEOP_EWEN 0x40 #define SEEOP_EWDS 0x40 #define SEEOPCODE 0x70 #define SEERST 0x02 @@ -3414,14 +3435,14 @@ #define WRTBIASCALC 0xc7 -#define DFPTRS 0xc8 - #define RCVRBIASCALC 0xc8 -#define DFBKPTR 0xc9 +#define DFPTRS 0xc8 #define SKEWCALC 0xc9 +#define DFBKPTR 0xc9 + #define DFDBCTL 0xcb #define DFF_CIO_WR_RDY 0x20 #define DFF_CIO_RD_RDY 0x10 @@ -3475,11 +3496,11 @@ #define DINDEX 0xe4 +#define BRKADDR0 0xe6 + #define BRKADDR1 0xe6 #define BRKDIS 0x80 -#define BRKADDR0 0xe6 - #define ALLONES 0xe8 #define ALLZEROS 0xea @@ -3494,14 +3515,14 @@ #define STACK 0xf2 -#define CURADDR 0xf4 - #define INTVEC1_ADDR 0xf4 -#define INTVEC2_ADDR 0xf6 +#define CURADDR 0xf4 #define LASTADDR 0xf6 +#define INTVEC2_ADDR 0xf6 + #define LONGJMP_ADDR 0xf8 #define ACCUM_SAVE 0xfa @@ -3524,25 +3545,31 @@ #define COMPLETE_DMA_SCB_HEAD 0x12c -#define QFREEZE_COUNT 0x12e +#define COMPLETE_DMA_SCB_TAIL 0x12e + +#define COMPLETE_ON_QFREEZE_HEAD 0x130 + +#define QFREEZE_COUNT 0x132 -#define SAVED_MODE 0x130 +#define KERNEL_QFREEZE_COUNT 0x134 -#define MSG_OUT 0x131 +#define SAVED_MODE 0x136 -#define DMAPARAMS 0x132 +#define MSG_OUT 0x137 + +#define DMAPARAMS 0x138 #define PRELOADEN 0x80 #define WIDEODD 0x40 #define SCSIEN 0x20 #define SDMAEN 0x10 #define SDMAENACK 0x10 -#define HDMAENACK 0x08 #define HDMAEN 0x08 +#define HDMAENACK 0x08 #define DIRECTION 0x04 #define FIFOFLUSH 0x02 #define FIFORESET 0x01 -#define SEQ_FLAGS 0x133 +#define SEQ_FLAGS 0x139 #define NOT_IDENTIFIED 0x80 #define NO_CDB_SENT 0x40 #define TARGET_CMD_IS_TAGGED 0x40 @@ -3553,11 +3580,11 @@ #define SPHASE_PENDING 0x02 #define NO_DISCONNECT 0x01 -#define SAVED_SCSIID 0x134 +#define SAVED_SCSIID 0x13a -#define SAVED_LUN 0x135 +#define SAVED_LUN 0x13b -#define LASTPHASE 0x136 +#define LASTPHASE 0x13c #define PHASE_MASK 0xe0 #define CDI 0x80 #define IOI 0x40 @@ -3572,18 +3599,18 @@ #define P_DATAOUT_DT 0x20 #define P_DATAOUT 0x00 -#define QOUTFIFO_ENTRY_VALID_TAG 0x137 +#define QOUTFIFO_ENTRY_VALID_TAG 0x13d -#define SHARED_DATA_ADDR 0x138 +#define KERNEL_TQINPOS 0x13e -#define QOUTFIFO_NEXT_ADDR 0x13c +#define TQINPOS 0x13f -#define KERNEL_TQINPOS 0x140 +#define SHARED_DATA_ADDR 0x140 -#define TQINPOS 0x141 +#define QOUTFIFO_NEXT_ADDR 0x144 -#define ARG_1 0x142 -#define RETURN_1 0x142 +#define ARG_1 0x148 +#define RETURN_1 0x148 #define SEND_MSG 0x80 #define SEND_SENSE 0x40 #define SEND_REJ 0x20 @@ -3593,12 +3620,12 @@ #define CONT_MSG_LOOP_READ 0x03 #define CONT_MSG_LOOP_TARG 0x02 -#define ARG_2 0x143 -#define RETURN_2 0x143 +#define ARG_2 0x149 +#define RETURN_2 0x149 -#define LAST_MSG 0x144 +#define LAST_MSG 0x14a -#define SCSISEQ_TEMPLATE 0x145 +#define SCSISEQ_TEMPLATE 0x14b #define MANUALCTL 0x40 #define ENSELI 0x20 #define ENRSELI 0x10 @@ -3606,27 +3633,27 @@ #define ENAUTOATNP 0x02 #define ALTSTIM 0x01 -#define INITIATOR_TAG 0x146 +#define INITIATOR_TAG 0x14c -#define SEQ_FLAGS2 0x147 +#define SEQ_FLAGS2 0x14d #define SELECTOUT_QFROZEN 0x04 #define TARGET_MSG_PENDING 0x02 -#define ALLOCFIFO_SCBPTR 0x148 +#define ALLOCFIFO_SCBPTR 0x14e -#define INT_COALESCING_TIMER 0x14a +#define INT_COALESCING_TIMER 0x150 -#define INT_COALESCING_MAXCMDS 0x14c +#define INT_COALESCING_MAXCMDS 0x152 -#define INT_COALESCING_MINCMDS 0x14d +#define INT_COALESCING_MINCMDS 0x153 -#define CMDS_PENDING 0x14e +#define CMDS_PENDING 0x154 -#define INT_COALESCING_CMDCOUNT 0x150 +#define INT_COALESCING_CMDCOUNT 0x156 -#define LOCAL_HS_MAILBOX 0x151 +#define LOCAL_HS_MAILBOX 0x157 -#define CMDSIZE_TABLE 0x152 +#define CMDSIZE_TABLE 0x158 #define SCB_BASE 0x180 @@ -3701,6 +3728,16 @@ #define SCB_DISCONNECTED_LISTS 0x1b8 +#define AHD_TIMER_MAX_US 0x18ffe7 +#define AHD_TIMER_MAX_TICKS 0xffff +#define AHD_SENSE_BUFSIZE 0x100 +#define BUS_8_BIT 0x00 +#define TARGET_CMD_CMPLT 0xfe +#define SEEOP_WRAL_ADDR 0x40 +#define AHD_AMPLITUDE_DEF 0x07 +#define AHD_PRECOMP_CUTBACK_37 0x07 +#define AHD_PRECOMP_SHIFT 0x00 +#define AHD_ANNEXCOL_PRECOMP_SLEW 0x04 #define AHD_TIMER_US_PER_TICK 0x19 #define SCB_TRANSFER_SIZE_FULL_LUN 0x38 #define STATUS_QUEUE_FULL 0x28 @@ -3724,28 +3761,18 @@ #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 #define STATUS_PKT_SENSE 0xff #define CMD_GROUP_CODE_SHIFT 0x05 -#define AHD_SENSE_BUFSIZE 0x100 #define MAX_OFFSET_PACED_BUG 0x7f -#define BUS_8_BIT 0x00 #define STIMESEL_BUG_ADJ 0x08 #define STIMESEL_MIN 0x18 #define STIMESEL_SHIFT 0x03 #define CCSGRAM_MAXSEGS 0x10 #define INVALID_ADDR 0x80 -#define TARGET_CMD_CMPLT 0xfe -#define SEEOP_WRAL_ADDR 0x40 #define SEEOP_ERAL_ADDR 0x80 -#define AHD_AMPLITUDE_DEF 0x07 #define AHD_SLEWRATE_DEF_REVB 0x08 -#define AHD_PRECOMP_CUTBACK_37 0x07 #define AHD_PRECOMP_CUTBACK_17 0x04 -#define AHD_PRECOMP_SHIFT 0x00 #define AHD_PRECOMP_MASK 0x07 -#define AHD_ANNEXCOL_PRECOMP_SLEW 0x04 #define SRC_MODE_SHIFT 0x00 #define PKT_OVERRUN_BUFSIZE 0x200 #define SCB_TRANSFER_SIZE_1BYTE_LUN 0x30 @@ -3772,5 +3799,5 @@ /* Exported Labels */ -#define LABEL_seq_isr 0x269 -#define LABEL_timer_isr 0x265 +#define LABEL_seq_isr 0x283 +#define LABEL_timer_isr 0x27f diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_reg_print.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_reg_print.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_reg_print.c Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_reg_print.c Tue Feb 10 01:47:04 2004 @@ -2,8 +2,8 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $ */ #include "aic79xx_osm.h" @@ -172,21 +172,6 @@ 0x0b, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = { - { "CLRSEQ_SPLTINT", 0x01, 0x01 }, - { "CLRSEQ_PCIINT", 0x02, 0x02 }, - { "CLRSEQ_SCSIINT", 0x04, 0x04 }, - { "CLRSEQ_SEQINT", 0x08, 0x08 }, - { "CLRSEQ_SWTMRTO", 0x10, 0x10 } -}; - -int -ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT", - 0x0c, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = { { "SEQ_SPLTINT", 0x01, 0x01 }, { "SEQ_PCIINT", 0x02, 0x02 }, @@ -202,6 +187,21 @@ 0x0c, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = { + { "CLRSEQ_SPLTINT", 0x01, 0x01 }, + { "CLRSEQ_PCIINT", 0x02, 0x02 }, + { "CLRSEQ_SCSIINT", 0x04, 0x04 }, + { "CLRSEQ_SEQINT", 0x08, 0x08 }, + { "CLRSEQ_SWTMRTO", 0x10, 0x10 } +}; + +int +ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT", + 0x0c, regvalue, cur_col, wrap)); +} + int ahd_swtimer_print(u_int regvalue, u_int *cur_col, u_int wrap) { @@ -670,16 +670,16 @@ } int -ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "BUSINITID", + return (ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap)); } int -ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "DLCOUNT", + return (ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap)); } @@ -859,21 +859,6 @@ 0x49, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = { - { "SELWIDE", 0x02, 0x02 }, - { "ENAB20", 0x04, 0x04 }, - { "ENAB40", 0x08, 0x08 }, - { "DIAGLEDON", 0x40, 0x40 }, - { "DIAGLEDEN", 0x80, 0x80 } -}; - -int -ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL", - 0x4a, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = { { "AUTO_MSGOUT_DE", 0x02, 0x02 }, { "ENDGFORMCHK", 0x04, 0x04 }, @@ -891,22 +876,19 @@ 0x4a, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SSTAT0_parse_table[] = { - { "ARBDO", 0x01, 0x01 }, - { "SPIORDY", 0x02, 0x02 }, - { "OVERRUN", 0x04, 0x04 }, - { "IOERR", 0x08, 0x08 }, - { "SELINGO", 0x10, 0x10 }, - { "SELDI", 0x20, 0x20 }, - { "SELDO", 0x40, 0x40 }, - { "TARGET", 0x80, 0x80 } +static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = { + { "SELWIDE", 0x02, 0x02 }, + { "ENAB20", 0x04, 0x04 }, + { "ENAB40", 0x08, 0x08 }, + { "DIAGLEDON", 0x40, 0x40 }, + { "DIAGLEDEN", 0x80, 0x80 } }; int -ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0", - 0x4b, regvalue, cur_col, wrap)); + return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL", + 0x4a, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t CLRSINT0_parse_table[] = { @@ -926,6 +908,24 @@ 0x4b, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t SSTAT0_parse_table[] = { + { "ARBDO", 0x01, 0x01 }, + { "SPIORDY", 0x02, 0x02 }, + { "OVERRUN", 0x04, 0x04 }, + { "IOERR", 0x08, 0x08 }, + { "SELINGO", 0x10, 0x10 }, + { "SELDI", 0x20, 0x20 }, + { "SELDO", 0x40, 0x40 }, + { "TARGET", 0x80, 0x80 } +}; + +int +ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0", + 0x4b, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t SIMODE0_parse_table[] = { { "ENARBDO", 0x01, 0x01 }, { "ENSPIORDY", 0x02, 0x02 }, @@ -998,30 +998,30 @@ 0x4d, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = { - { "CLRDMADONE", 0x01, 0x01 }, - { "CLRSDONE", 0x02, 0x02 }, - { "CLRWIDE_RES", 0x04, 0x04 }, - { "CLRNONPACKREQ", 0x20, 0x20 } +static ahd_reg_parse_entry_t SIMODE2_parse_table[] = { + { "ENDMADONE", 0x01, 0x01 }, + { "ENSDONE", 0x02, 0x02 }, + { "ENWIDE_RES", 0x04, 0x04 } }; int -ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2", + return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2", 0x4d, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SIMODE2_parse_table[] = { - { "ENDMADONE", 0x01, 0x01 }, - { "ENSDONE", 0x02, 0x02 }, - { "ENWIDE_RES", 0x04, 0x04 } +static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = { + { "CLRDMADONE", 0x01, 0x01 }, + { "CLRSDONE", 0x02, 0x02 }, + { "CLRWIDE_RES", 0x04, 0x04 }, + { "CLRNONPACKREQ", 0x20, 0x20 } }; int -ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2", + return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2", 0x4d, regvalue, cur_col, wrap)); } @@ -1220,21 +1220,6 @@ 0x53, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = { - { "ENLQOTCRC", 0x01, 0x01 }, - { "ENLQOATNPKT", 0x02, 0x02 }, - { "ENLQOATNLQ", 0x04, 0x04 }, - { "ENLQOSTOPT2", 0x08, 0x08 }, - { "ENLQOTARGSCBPERR", 0x10, 0x10 } -}; - -int -ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0", - 0x54, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = { { "LQOTCRC", 0x01, 0x01 }, { "LQOATNPKT", 0x02, 0x02 }, @@ -1265,6 +1250,36 @@ 0x54, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = { + { "ENLQOTCRC", 0x01, 0x01 }, + { "ENLQOATNPKT", 0x02, 0x02 }, + { "ENLQOATNLQ", 0x04, 0x04 }, + { "ENLQOSTOPT2", 0x08, 0x08 }, + { "ENLQOTARGSCBPERR", 0x10, 0x10 } +}; + +int +ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0", + 0x54, regvalue, cur_col, wrap)); +} + +static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = { + { "ENLQOPHACHGINPKT", 0x01, 0x01 }, + { "ENLQOBUSFREE", 0x02, 0x02 }, + { "ENLQOBADQAS", 0x04, 0x04 }, + { "ENLQOSTOPI2", 0x08, 0x08 }, + { "ENLQOINITSCBPERR", 0x10, 0x10 } +}; + +int +ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1", + 0x55, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = { { "LQOPHACHGINPKT", 0x01, 0x01 }, { "LQOBUSFREE", 0x02, 0x02 }, @@ -1295,21 +1310,6 @@ 0x55, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = { - { "ENLQOPHACHGINPKT", 0x01, 0x01 }, - { "ENLQOBUSFREE", 0x02, 0x02 }, - { "ENLQOBADQAS", 0x04, 0x04 }, - { "ENLQOSTOPI2", 0x08, 0x08 }, - { "ENLQOINITSCBPERR", 0x10, 0x10 } -}; - -int -ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1", - 0x55, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = { { "LQOSTOP0", 0x01, 0x01 }, { "LQOPHACHGOUTPKT", 0x02, 0x02 }, @@ -1594,6 +1594,13 @@ 0x65, regvalue, cur_col, wrap)); } +int +ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "ANNEXDAT", + 0x66, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t SCSCHKN_parse_table[] = { { "LSTSGCLRDIS", 0x01, 0x01 }, { "SHVALIDSTDIS", 0x02, 0x02 }, @@ -1612,13 +1619,6 @@ } int -ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(NULL, 0, "ANNEXDAT", - 0x66, regvalue, cur_col, wrap)); -} - -int ahd_iownid_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "IOWNID", @@ -1728,16 +1728,16 @@ } int -ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "PLL400CNT0", + return (ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap)); } int -ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "UNFAIRNESS", + return (ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap)); } @@ -1788,30 +1788,30 @@ } int -ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SGHADDR", + return (ahd_print_register(NULL, 0, "SCBHADDR", 0x7c, regvalue, cur_col, wrap)); } int -ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SCBHADDR", + return (ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)); } int -ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SGHCNT", + return (ahd_print_register(NULL, 0, "SCBHCNT", 0x84, regvalue, cur_col, wrap)); } int -ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SCBHCNT", + return (ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)); } @@ -1950,25 +1950,25 @@ 0x91, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = { +static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = { { "CBNUM", 0xff, 0xff } }; int -ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1", + return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1", 0x91, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = { +static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = { { "CBNUM", 0xff, 0xff } }; int -ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1", + return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap)); } @@ -1983,17 +1983,6 @@ 0x92, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = { - { "MINDEX", 0xff, 0xff } -}; - -int -ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2", - 0x92, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t CMCRXMSG2_parse_table[] = { { "MINDEX", 0xff, 0xff } }; @@ -2012,6 +2001,17 @@ 0x92, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = { + { "MINDEX", 0xff, 0xff } +}; + +int +ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2", + 0x92, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t DCHRXMSG3_parse_table[] = { { "MCLASS", 0x0f, 0x0f } }; @@ -2023,6 +2023,17 @@ 0x93, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = { + { "MCLASS", 0x0f, 0x0f } +}; + +int +ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3", + 0x93, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t CMCRXMSG3_parse_table[] = { { "MCLASS", 0x0f, 0x0f } }; @@ -2051,17 +2062,6 @@ 0x93, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = { - { "MCLASS", 0x0f, 0x0f } -}; - -int -ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3", - 0x93, regvalue, cur_col, wrap)); -} - int ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { @@ -2070,16 +2070,16 @@ } int -ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "CMCSEQBCNT", + return (ahd_print_register(NULL, 0, "DCHSEQBCNT", 0x94, regvalue, cur_col, wrap)); } int -ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "DCHSEQBCNT", + return (ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap)); } @@ -2101,7 +2101,7 @@ 0x96, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = { +static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = { { "RXSPLTRSP", 0x01, 0x01 }, { "RXSCEMSG", 0x02, 0x02 }, { "RXOVRUN", 0x04, 0x04 }, @@ -2113,13 +2113,13 @@ }; int -ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0", + return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0", 0x96, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = { +static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = { { "RXSPLTRSP", 0x01, 0x01 }, { "RXSCEMSG", 0x02, 0x02 }, { "RXOVRUN", 0x04, 0x04 }, @@ -2131,42 +2131,42 @@ }; int -ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0", + return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = { +static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = { { "RXDATABUCKET", 0x01, 0x01 } }; int -ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1", + return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1", 0x97, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = { +static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = { { "RXDATABUCKET", 0x01, 0x01 } }; int -ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1", + return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1", 0x97, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = { +static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = { { "RXDATABUCKET", 0x01, 0x01 } }; int -ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1", + return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap)); } @@ -2320,26 +2320,26 @@ 0x9e, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SFUNCT_parse_table[] = { - { "TEST_NUM", 0x0f, 0x0f }, - { "TEST_GROUP", 0xf0, 0xf0 } +static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = { + { "RXDATABUCKET", 0x01, 0x01 } }; int -ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT", + return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = { - { "RXDATABUCKET", 0x01, 0x01 } +static ahd_reg_parse_entry_t SFUNCT_parse_table[] = { + { "TEST_NUM", 0x0f, 0x0f }, + { "TEST_GROUP", 0xf0, 0xf0 } }; int -ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1", + return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT", 0x9f, regvalue, cur_col, wrap)); } @@ -2537,16 +2537,16 @@ } int -ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "CCSCBADDR", + return (ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap)); } int -ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "CCSCBADR_BK", + return (ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap)); } @@ -2566,22 +2566,6 @@ 0xad, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = { - { "CCSGRESET", 0x01, 0x01 }, - { "SG_FETCH_REQ", 0x02, 0x02 }, - { "CCSGENACK", 0x08, 0x08 }, - { "SG_CACHE_AVAIL", 0x10, 0x10 }, - { "CCSGDONE", 0x80, 0x80 }, - { "CCSGEN", 0x0c, 0x0c } -}; - -int -ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL", - 0xad, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = { { "CCSCBRESET", 0x01, 0x01 }, { "CCSCBDIR", 0x04, 0x04 }, @@ -2598,6 +2582,22 @@ 0xad, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = { + { "CCSGRESET", 0x01, 0x01 }, + { "SG_FETCH_REQ", 0x02, 0x02 }, + { "CCSGENACK", 0x08, 0x08 }, + { "SG_CACHE_AVAIL", 0x10, 0x10 }, + { "CCSGDONE", 0x80, 0x80 }, + { "CCSGEN", 0x0c, 0x0c } +}; + +int +ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL", + 0xad, regvalue, cur_col, wrap)); +} + int ahd_ccsgram_print(u_int regvalue, u_int *cur_col, u_int wrap) { @@ -2841,30 +2841,30 @@ } int -ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "DFPTRS", + return (ahd_print_register(NULL, 0, "RCVRBIASCALC", 0xc8, regvalue, cur_col, wrap)); } int -ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "RCVRBIASCALC", + return (ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap)); } int -ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "DFBKPTR", + return (ahd_print_register(NULL, 0, "SKEWCALC", 0xc9, regvalue, cur_col, wrap)); } int -ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SKEWCALC", + return (ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap)); } @@ -3001,6 +3001,13 @@ 0xe4, regvalue, cur_col, wrap)); } +int +ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "BRKADDR0", + 0xe6, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t BRKADDR1_parse_table[] = { { "BRKDIS", 0x80, 0x80 } }; @@ -3013,13 +3020,6 @@ } int -ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(NULL, 0, "BRKADDR0", - 0xe6, regvalue, cur_col, wrap)); -} - -int ahd_allones_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "ALLONES", @@ -3069,30 +3069,30 @@ } int -ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "CURADDR", + return (ahd_print_register(NULL, 0, "INTVEC1_ADDR", 0xf4, regvalue, cur_col, wrap)); } int -ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "INTVEC1_ADDR", + return (ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap)); } int -ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "INTVEC2_ADDR", + return (ahd_print_register(NULL, 0, "LASTADDR", 0xf6, regvalue, cur_col, wrap)); } int -ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "LASTADDR", + return (ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap)); } @@ -3174,24 +3174,45 @@ } int +ahd_complete_dma_scb_tail_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL", + 0x12e, regvalue, cur_col, wrap)); +} + +int +ahd_complete_on_qfreeze_head_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD", + 0x130, regvalue, cur_col, wrap)); +} + +int ahd_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "QFREEZE_COUNT", - 0x12e, regvalue, cur_col, wrap)); + 0x132, regvalue, cur_col, wrap)); +} + +int +ahd_kernel_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT", + 0x134, regvalue, cur_col, wrap)); } int ahd_saved_mode_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "SAVED_MODE", - 0x130, regvalue, cur_col, wrap)); + 0x136, regvalue, cur_col, wrap)); } int ahd_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "MSG_OUT", - 0x131, regvalue, cur_col, wrap)); + 0x137, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = { @@ -3211,7 +3232,7 @@ ahd_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(DMAPARAMS_parse_table, 10, "DMAPARAMS", - 0x132, regvalue, cur_col, wrap)); + 0x138, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = { @@ -3230,21 +3251,21 @@ ahd_seq_flags_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(SEQ_FLAGS_parse_table, 9, "SEQ_FLAGS", - 0x133, regvalue, cur_col, wrap)); + 0x139, regvalue, cur_col, wrap)); } int ahd_saved_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "SAVED_SCSIID", - 0x134, regvalue, cur_col, wrap)); + 0x13a, regvalue, cur_col, wrap)); } int ahd_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "SAVED_LUN", - 0x135, regvalue, cur_col, wrap)); + 0x13b, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t LASTPHASE_parse_table[] = { @@ -3267,42 +3288,42 @@ ahd_lastphase_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(LASTPHASE_parse_table, 13, "LASTPHASE", - 0x136, regvalue, cur_col, wrap)); + 0x13c, regvalue, cur_col, wrap)); } int ahd_qoutfifo_entry_valid_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", - 0x137, regvalue, cur_col, wrap)); + 0x13d, regvalue, cur_col, wrap)); } int -ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", - 0x138, regvalue, cur_col, wrap)); + return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS", + 0x13e, regvalue, cur_col, wrap)); } int -ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", - 0x13c, regvalue, cur_col, wrap)); + return (ahd_print_register(NULL, 0, "TQINPOS", + 0x13f, regvalue, cur_col, wrap)); } int -ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS", + return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x140, regvalue, cur_col, wrap)); } int -ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "TQINPOS", - 0x141, regvalue, cur_col, wrap)); + return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", + 0x144, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t ARG_1_parse_table[] = { @@ -3320,21 +3341,21 @@ ahd_arg_1_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(ARG_1_parse_table, 8, "ARG_1", - 0x142, regvalue, cur_col, wrap)); + 0x148, regvalue, cur_col, wrap)); } int ahd_arg_2_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "ARG_2", - 0x143, regvalue, cur_col, wrap)); + 0x149, regvalue, cur_col, wrap)); } int ahd_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "LAST_MSG", - 0x144, regvalue, cur_col, wrap)); + 0x14a, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = { @@ -3350,14 +3371,14 @@ ahd_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(SCSISEQ_TEMPLATE_parse_table, 6, "SCSISEQ_TEMPLATE", - 0x145, regvalue, cur_col, wrap)); + 0x14b, regvalue, cur_col, wrap)); } int ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INITIATOR_TAG", - 0x146, regvalue, cur_col, wrap)); + 0x14c, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = { @@ -3369,63 +3390,63 @@ ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(SEQ_FLAGS2_parse_table, 2, "SEQ_FLAGS2", - 0x147, regvalue, cur_col, wrap)); + 0x14d, regvalue, cur_col, wrap)); } int ahd_allocfifo_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", - 0x148, regvalue, cur_col, wrap)); + 0x14e, regvalue, cur_col, wrap)); } int ahd_int_coalescing_timer_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", - 0x14a, regvalue, cur_col, wrap)); + 0x150, regvalue, cur_col, wrap)); } int ahd_int_coalescing_maxcmds_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", - 0x14c, regvalue, cur_col, wrap)); + 0x152, regvalue, cur_col, wrap)); } int ahd_int_coalescing_mincmds_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", - 0x14d, regvalue, cur_col, wrap)); + 0x153, regvalue, cur_col, wrap)); } int ahd_cmds_pending_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "CMDS_PENDING", - 0x14e, regvalue, cur_col, wrap)); + 0x154, regvalue, cur_col, wrap)); } int ahd_int_coalescing_cmdcount_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", - 0x150, regvalue, cur_col, wrap)); + 0x156, regvalue, cur_col, wrap)); } int ahd_local_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", - 0x151, regvalue, cur_col, wrap)); + 0x157, regvalue, cur_col, wrap)); } int ahd_cmdsize_table_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "CMDSIZE_TABLE", - 0x152, regvalue, cur_col, wrap)); + 0x158, regvalue, cur_col, wrap)); } int diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_seq.h linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_seq.h --- linux-2.4.25/drivers/scsi/aic7xxx/aic79xx_seq.h Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic79xx_seq.h Tue Feb 10 01:47:04 2004 @@ -2,215 +2,226 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $ */ static uint8_t seqprog[] = { 0xff, 0x02, 0x06, 0x78, - 0x00, 0xea, 0x50, 0x59, + 0x00, 0xea, 0x60, 0x59, 0x01, 0xea, 0x04, 0x30, 0xff, 0x04, 0x0c, 0x78, - 0x19, 0xea, 0x50, 0x59, + 0x19, 0xea, 0x60, 0x59, 0x19, 0xea, 0x04, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x60, 0x3a, 0x1a, 0x68, - 0x04, 0x47, 0x1b, 0x68, - 0xff, 0x21, 0x1b, 0x70, - 0x40, 0x4b, 0x92, 0x69, - 0x00, 0xe2, 0x54, 0x59, - 0x40, 0x4b, 0x92, 0x69, - 0x20, 0x4b, 0x82, 0x69, - 0xfc, 0x42, 0x24, 0x78, - 0x10, 0x40, 0x24, 0x78, - 0x00, 0xe2, 0xc4, 0x5d, - 0x20, 0x4d, 0x28, 0x78, - 0x00, 0xe2, 0xc4, 0x5d, + 0x60, 0x3a, 0x3a, 0x68, + 0x04, 0x4d, 0x35, 0x78, + 0x01, 0x34, 0xc1, 0x31, + 0x00, 0x32, 0x21, 0x60, + 0x01, 0x35, 0xc1, 0x31, + 0x00, 0x33, 0x21, 0x60, + 0xfb, 0x4d, 0x9b, 0x0a, + 0x00, 0xe2, 0x34, 0x40, + 0x50, 0x4b, 0x3a, 0x68, + 0xff, 0x31, 0x3b, 0x70, + 0x02, 0x30, 0x51, 0x31, + 0xff, 0x8d, 0x2d, 0x70, + 0x02, 0x8c, 0x51, 0x31, + 0xff, 0x8d, 0x29, 0x60, + 0x02, 0x28, 0x19, 0x33, + 0x02, 0x30, 0x51, 0x32, + 0xff, 0xea, 0x62, 0x02, + 0x00, 0xe2, 0x3a, 0x40, + 0xff, 0x21, 0x3b, 0x70, + 0x40, 0x4b, 0xa6, 0x69, + 0x00, 0xe2, 0x64, 0x59, + 0x40, 0x4b, 0xa6, 0x69, + 0x20, 0x4b, 0x92, 0x69, + 0xfc, 0x42, 0x44, 0x78, + 0x10, 0x40, 0x44, 0x78, + 0x00, 0xe2, 0xf8, 0x5d, + 0x20, 0x4d, 0x48, 0x78, + 0x00, 0xe2, 0xf8, 0x5d, 0x30, 0x3f, 0xc0, 0x09, - 0x30, 0xe0, 0x30, 0x60, + 0x30, 0xe0, 0x50, 0x60, 0x7f, 0x4a, 0x94, 0x08, - 0x00, 0xe2, 0x32, 0x40, + 0x00, 0xe2, 0x52, 0x40, 0xc0, 0x4a, 0x94, 0x00, - 0x00, 0xe2, 0x3e, 0x58, - 0x00, 0xe2, 0x56, 0x58, - 0x00, 0xe2, 0x66, 0x58, + 0x00, 0xe2, 0x5e, 0x58, + 0x00, 0xe2, 0x76, 0x58, + 0x00, 0xe2, 0x86, 0x58, 0x00, 0xe2, 0x06, 0x40, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x01, 0x52, 0x64, 0x78, + 0x01, 0x52, 0x84, 0x78, 0x02, 0x58, 0x50, 0x31, 0xff, 0xea, 0x10, 0x0b, - 0xff, 0x97, 0x4f, 0x78, - 0x50, 0x4b, 0x4a, 0x68, + 0xff, 0x97, 0x6f, 0x78, + 0x50, 0x4b, 0x6a, 0x68, 0xbf, 0x3a, 0x74, 0x08, - 0x14, 0xea, 0x50, 0x59, + 0x14, 0xea, 0x60, 0x59, 0x14, 0xea, 0x04, 0x00, 0x08, 0x92, 0x25, 0x03, - 0xff, 0x90, 0x3f, 0x68, - 0x00, 0xe2, 0x56, 0x5b, - 0x00, 0xe2, 0x3e, 0x40, - 0x00, 0xea, 0x44, 0x59, + 0xff, 0x90, 0x5f, 0x68, + 0x00, 0xe2, 0x72, 0x5b, + 0x00, 0xe2, 0x5e, 0x40, + 0x00, 0xea, 0x5a, 0x59, 0x01, 0xea, 0x00, 0x30, - 0x80, 0xf9, 0x5e, 0x68, - 0x00, 0xe2, 0x42, 0x59, - 0x11, 0xea, 0x44, 0x59, + 0x80, 0xf9, 0x7e, 0x68, + 0x00, 0xe2, 0x58, 0x59, + 0x11, 0xea, 0x5a, 0x59, 0x11, 0xea, 0x00, 0x00, - 0x80, 0xf9, 0x42, 0x79, + 0x80, 0xf9, 0x58, 0x79, 0xff, 0xea, 0xd4, 0x0d, - 0x22, 0xea, 0x44, 0x59, + 0x22, 0xea, 0x5a, 0x59, 0x22, 0xea, 0x00, 0x00, - 0x10, 0x16, 0x70, 0x78, - 0x01, 0x0b, 0xa2, 0x32, + 0x10, 0x16, 0x90, 0x78, 0x10, 0x16, 0x2c, 0x00, - 0x18, 0xad, 0x00, 0x79, - 0x04, 0xad, 0xca, 0x68, - 0x80, 0xad, 0x64, 0x78, - 0x10, 0xad, 0x98, 0x78, - 0xff, 0x88, 0x83, 0x68, + 0x01, 0x0b, 0xae, 0x32, + 0x18, 0xad, 0x12, 0x79, + 0x04, 0xad, 0xdc, 0x68, + 0x80, 0xad, 0x84, 0x78, + 0x10, 0xad, 0xaa, 0x78, 0xe7, 0xad, 0x5a, 0x09, 0x02, 0x8c, 0x59, 0x32, + 0xff, 0x8d, 0xa1, 0x60, + 0xff, 0xea, 0x5e, 0x02, + 0xff, 0x88, 0xa7, 0x78, + 0x02, 0x30, 0x19, 0x33, + 0x02, 0xa8, 0x60, 0x36, 0x02, 0x28, 0x19, 0x33, 0x02, 0xa8, 0x50, 0x36, - 0x33, 0xea, 0x44, 0x59, - 0x33, 0xea, 0x00, 0x00, - 0x40, 0x3a, 0x64, 0x68, - 0x50, 0x4b, 0x64, 0x68, - 0x22, 0xea, 0x44, 0x59, - 0x22, 0xea, 0x00, 0x00, - 0xe7, 0xad, 0x5a, 0x09, - 0x02, 0x8c, 0x59, 0x32, - 0x1a, 0xea, 0x50, 0x59, - 0x1a, 0xea, 0x04, 0x00, - 0xff, 0xea, 0xd4, 0x0d, 0xe7, 0xad, 0x5a, 0x09, - 0x00, 0xe2, 0xa6, 0x58, + 0x00, 0xe2, 0xb8, 0x58, 0xff, 0xea, 0x56, 0x02, - 0x04, 0x7c, 0x78, 0x32, - 0x20, 0x16, 0x64, 0x78, - 0x04, 0x38, 0x79, 0x32, - 0x80, 0x37, 0x6f, 0x16, - 0xff, 0x2d, 0xb5, 0x60, - 0xff, 0x29, 0xb5, 0x60, - 0x40, 0x51, 0xc5, 0x78, - 0xff, 0x4f, 0xb5, 0x68, - 0xff, 0x4d, 0xc1, 0x19, - 0x00, 0x4e, 0xd5, 0x19, - 0x00, 0xe2, 0xc4, 0x50, - 0x01, 0x4c, 0xc1, 0x31, - 0x00, 0x50, 0xd5, 0x19, - 0x00, 0xe2, 0xc4, 0x48, - 0x80, 0x18, 0x64, 0x78, - 0x02, 0x4a, 0x1d, 0x30, + 0x04, 0x7c, 0x88, 0x32, + 0x20, 0x16, 0x84, 0x78, + 0x04, 0x40, 0x89, 0x32, + 0x80, 0x3d, 0x7b, 0x16, + 0xff, 0x2d, 0xc7, 0x60, + 0xff, 0x29, 0xc7, 0x60, + 0x40, 0x57, 0xd7, 0x78, + 0xff, 0x55, 0xc7, 0x68, + 0xff, 0x53, 0xc1, 0x19, + 0x00, 0x54, 0xd5, 0x19, + 0x00, 0xe2, 0xd6, 0x50, + 0x01, 0x52, 0xc1, 0x31, + 0x00, 0x56, 0xd5, 0x19, + 0x00, 0xe2, 0xd6, 0x48, + 0x80, 0x18, 0x84, 0x78, + 0x02, 0x50, 0x1d, 0x30, 0x10, 0xea, 0x18, 0x00, 0x60, 0x18, 0x30, 0x00, 0x7f, 0x18, 0x30, 0x0c, 0x02, 0xea, 0x02, 0x00, - 0xff, 0xea, 0xa0, 0x0a, + 0xff, 0xea, 0xac, 0x0a, 0x80, 0x18, 0x30, 0x04, - 0x40, 0xad, 0x64, 0x78, + 0x40, 0xad, 0x84, 0x78, 0xe7, 0xad, 0x5a, 0x09, 0x02, 0xa8, 0x40, 0x31, 0xff, 0xea, 0xc0, 0x09, - 0x01, 0x4e, 0x9d, 0x1a, - 0x00, 0x4f, 0x9f, 0x22, + 0x01, 0x54, 0xa9, 0x1a, + 0x00, 0x55, 0xab, 0x22, 0x01, 0x94, 0x6d, 0x33, - 0x01, 0xea, 0x20, 0x33, + 0xff, 0xea, 0x20, 0x0b, 0x04, 0xac, 0x49, 0x32, 0xff, 0xea, 0x5a, 0x03, 0xff, 0xea, 0x5e, 0x03, 0x01, 0x10, 0xd4, 0x31, - 0x10, 0x92, 0xf5, 0x68, + 0x10, 0x92, 0x07, 0x69, 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, + 0xff, 0xa9, 0x06, 0x71, 0x02, 0xa0, 0x58, 0x37, - 0xff, 0x21, 0xfd, 0x70, + 0xff, 0x21, 0x0f, 0x71, 0x02, 0x22, 0x51, 0x31, 0x02, 0xa0, 0x5c, 0x33, 0x02, 0xa0, 0x44, 0x36, 0x02, 0xa0, 0x40, 0x32, 0x02, 0xa0, 0x44, 0x36, - 0x04, 0x47, 0x05, 0x69, - 0x40, 0x16, 0x30, 0x69, - 0xff, 0x2d, 0x35, 0x61, - 0xff, 0x29, 0x65, 0x70, - 0x01, 0x37, 0xc1, 0x31, + 0x04, 0x4d, 0x17, 0x69, + 0x40, 0x16, 0x44, 0x69, + 0xff, 0x2d, 0x49, 0x61, + 0xff, 0x29, 0x85, 0x70, 0x02, 0x28, 0x55, 0x32, 0x01, 0xea, 0x5a, 0x01, - 0x04, 0x3c, 0xf9, 0x30, + 0x04, 0x44, 0xf9, 0x30, 0x02, 0x28, 0x51, 0x31, - 0x01, 0xa8, 0x60, 0x31, - 0x00, 0xa9, 0x60, 0x01, + 0x02, 0xa8, 0x60, 0x31, + 0x01, 0xa4, 0x61, 0x31, + 0x04, 0xea, 0x60, 0x31, + 0x01, 0x3d, 0x61, 0x31, 0x01, 0x14, 0xd4, 0x31, - 0x01, 0x50, 0xa1, 0x1a, - 0xff, 0x4e, 0x9d, 0x1a, - 0xff, 0x4f, 0x9f, 0x22, - 0xff, 0x8d, 0x29, 0x71, - 0x80, 0xac, 0x28, 0x71, - 0x20, 0x16, 0x28, 0x69, + 0x01, 0x56, 0xad, 0x1a, + 0xff, 0x54, 0xa9, 0x1a, + 0xff, 0x55, 0xab, 0x22, + 0xff, 0x8d, 0x3d, 0x71, + 0x80, 0xac, 0x3c, 0x71, + 0x20, 0x16, 0x3c, 0x69, 0x02, 0x8c, 0x51, 0x31, - 0x00, 0xe2, 0x12, 0x41, + 0x00, 0xe2, 0x22, 0x41, 0x01, 0xac, 0x08, 0x31, 0x09, 0xea, 0x5a, 0x01, 0x02, 0x8c, 0x51, 0x32, 0xff, 0xea, 0x1a, 0x07, 0x04, 0x24, 0xf9, 0x30, - 0x1d, 0xea, 0x3a, 0x41, + 0x1d, 0xea, 0x4e, 0x41, 0x02, 0x2c, 0x51, 0x31, 0x04, 0xa8, 0xf9, 0x30, - 0x19, 0xea, 0x3a, 0x41, + 0x19, 0xea, 0x4e, 0x41, 0x06, 0xea, 0x08, 0x81, 0x01, 0xe2, 0x5a, 0x35, - 0x02, 0xf2, 0xf0, 0x35, + 0x02, 0xf2, 0xf0, 0x31, + 0xff, 0xea, 0xd4, 0x0d, 0x02, 0xf2, 0xf0, 0x31, 0x02, 0xf8, 0xe4, 0x35, 0x80, 0xea, 0xb2, 0x01, 0x01, 0xe2, 0x00, 0x30, 0xff, 0xea, 0xb2, 0x0d, - 0x80, 0xea, 0xb2, 0x01, - 0x11, 0x00, 0x00, 0x10, - 0xff, 0xea, 0xb2, 0x0d, 0x01, 0xe2, 0x04, 0x30, 0x01, 0xea, 0x04, 0x34, 0x02, 0x20, 0xbd, 0x30, 0x02, 0x20, 0xb9, 0x30, 0x02, 0x20, 0x51, 0x31, 0x4c, 0x93, 0xd7, 0x28, - 0x10, 0x92, 0x63, 0x79, + 0x10, 0x92, 0x73, 0x79, 0x01, 0x6b, 0xc0, 0x30, 0x02, 0x64, 0xc8, 0x00, 0x40, 0x3a, 0x74, 0x04, - 0x00, 0xe2, 0x56, 0x58, - 0x33, 0xea, 0x44, 0x59, + 0x00, 0xe2, 0x76, 0x58, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, 0x30, 0x3f, 0xc0, 0x09, - 0x30, 0xe0, 0x64, 0x61, - 0x20, 0x3f, 0x7a, 0x69, - 0x10, 0x3f, 0x64, 0x79, + 0x30, 0xe0, 0x74, 0x61, + 0x20, 0x3f, 0x8a, 0x69, + 0x10, 0x3f, 0x74, 0x79, 0x02, 0xea, 0x7e, 0x00, - 0x00, 0xea, 0x44, 0x59, + 0x00, 0xea, 0x5a, 0x59, 0x01, 0xea, 0x00, 0x30, - 0x02, 0x48, 0x51, 0x35, + 0x02, 0x4e, 0x51, 0x35, 0x01, 0xea, 0x7e, 0x00, - 0x11, 0xea, 0x44, 0x59, + 0x11, 0xea, 0x5a, 0x59, 0x11, 0xea, 0x00, 0x00, - 0x02, 0x48, 0x51, 0x35, + 0x02, 0x4e, 0x51, 0x35, + 0xc0, 0x4a, 0x94, 0x00, + 0x04, 0x41, 0x98, 0x79, 0x08, 0xea, 0x98, 0x00, 0x08, 0x57, 0xae, 0x00, 0x08, 0x3c, 0x78, 0x00, - 0xf0, 0x49, 0x68, 0x0a, + 0xf0, 0x49, 0x74, 0x0a, 0x0f, 0x67, 0xc0, 0x09, - 0x00, 0x34, 0x69, 0x02, + 0x00, 0x3a, 0x75, 0x02, 0x20, 0xea, 0x96, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x40, 0x3a, 0xae, 0x69, + 0x00, 0xe2, 0x10, 0x42, + 0xc0, 0x4a, 0x94, 0x00, + 0x40, 0x3a, 0xc4, 0x69, 0x02, 0x55, 0x06, 0x68, - 0x02, 0x56, 0xae, 0x69, - 0xff, 0x5b, 0xae, 0x61, + 0x02, 0x56, 0xc4, 0x69, + 0xff, 0x5b, 0xc4, 0x61, 0x02, 0x20, 0x51, 0x31, 0x80, 0xea, 0xb2, 0x01, 0x44, 0xea, 0x00, 0x00, @@ -218,237 +229,246 @@ 0x33, 0xea, 0x00, 0x00, 0xff, 0xea, 0xb2, 0x09, 0xff, 0xe0, 0xc0, 0x19, - 0xff, 0xe0, 0xb0, 0x79, + 0xff, 0xe0, 0xc6, 0x79, 0x02, 0xac, 0x51, 0x31, - 0x00, 0xe2, 0xa6, 0x41, + 0x00, 0xe2, 0xbc, 0x41, 0x02, 0x5e, 0x50, 0x31, 0x02, 0xa8, 0xb8, 0x30, 0x02, 0x5c, 0x50, 0x31, - 0xff, 0xad, 0xc1, 0x71, + 0xff, 0xad, 0xd7, 0x71, 0x02, 0xac, 0x41, 0x31, 0x02, 0x22, 0x51, 0x31, 0x02, 0xa0, 0x5c, 0x33, 0x02, 0xa0, 0x44, 0x32, - 0x00, 0xe2, 0xca, 0x41, - 0x10, 0x92, 0xcb, 0x69, + 0x00, 0xe2, 0xe0, 0x41, + 0x10, 0x92, 0xe1, 0x69, 0x3d, 0x93, 0xc9, 0x29, 0x01, 0xe4, 0xc8, 0x01, 0x01, 0xea, 0xca, 0x01, 0xff, 0xea, 0xda, 0x01, 0x02, 0x20, 0x51, 0x31, 0x02, 0xae, 0x41, 0x32, - 0xff, 0x21, 0xd3, 0x61, + 0xff, 0x21, 0xe9, 0x61, 0xff, 0xea, 0x46, 0x02, 0x02, 0x5c, 0x50, 0x31, 0x40, 0xea, 0x96, 0x00, - 0x02, 0x56, 0xcc, 0x6d, - 0x01, 0x55, 0xcc, 0x6d, - 0x10, 0x92, 0xdf, 0x79, - 0x10, 0x40, 0xe8, 0x69, - 0x01, 0x56, 0xe8, 0x79, + 0x02, 0x56, 0x00, 0x6e, + 0x01, 0x55, 0x00, 0x6e, + 0x10, 0x92, 0xf5, 0x79, + 0x10, 0x40, 0xfe, 0x69, + 0x01, 0x56, 0xfe, 0x79, 0xff, 0x97, 0x07, 0x78, - 0x13, 0xea, 0x50, 0x59, + 0x13, 0xea, 0x60, 0x59, 0x13, 0xea, 0x04, 0x00, 0x00, 0xe2, 0x06, 0x40, 0xbf, 0x3a, 0x74, 0x08, + 0x04, 0x41, 0x04, 0x7a, 0x08, 0xea, 0x98, 0x00, 0x08, 0x57, 0xae, 0x00, - 0x01, 0x93, 0x69, 0x32, - 0x01, 0x94, 0x6b, 0x32, - 0x40, 0xea, 0x66, 0x02, + 0x01, 0x93, 0x75, 0x32, + 0x01, 0x94, 0x77, 0x32, + 0x40, 0xea, 0x72, 0x02, 0x08, 0x3c, 0x78, 0x00, - 0x80, 0xea, 0x62, 0x02, - 0x00, 0xe2, 0xb8, 0x5b, - 0x01, 0x36, 0xc1, 0x31, - 0x9f, 0xe0, 0x4c, 0x7c, - 0x80, 0xe0, 0x0c, 0x72, - 0xa0, 0xe0, 0x44, 0x72, - 0xc0, 0xe0, 0x3a, 0x72, - 0xe0, 0xe0, 0x74, 0x72, - 0x01, 0xea, 0x50, 0x59, + 0x80, 0xea, 0x6e, 0x02, + 0x00, 0xe2, 0xde, 0x5b, + 0x01, 0x3c, 0xc1, 0x31, + 0x9f, 0xe0, 0x80, 0x7c, + 0x80, 0xe0, 0x24, 0x72, + 0xa0, 0xe0, 0x60, 0x72, + 0xc0, 0xe0, 0x56, 0x72, + 0xe0, 0xe0, 0x90, 0x72, + 0x01, 0xea, 0x60, 0x59, 0x01, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x80, 0x33, 0x13, 0x7a, - 0x03, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x10, 0x42, + 0x80, 0x39, 0x2b, 0x7a, + 0x03, 0xea, 0x60, 0x59, 0x03, 0xea, 0x04, 0x00, - 0xee, 0x00, 0x1a, 0x6a, + 0xee, 0x00, 0x32, 0x6a, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x02, 0xa8, 0x90, 0x32, - 0x00, 0xe2, 0x6a, 0x59, + 0x02, 0xa8, 0x9c, 0x32, + 0x00, 0xe2, 0x7a, 0x59, 0xef, 0x96, 0xd5, 0x19, - 0x00, 0xe2, 0x2a, 0x52, + 0x00, 0xe2, 0x42, 0x52, 0x09, 0x80, 0xe1, 0x30, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0x30, 0x42, + 0x00, 0xe2, 0x48, 0x42, 0x01, 0x96, 0xd1, 0x30, 0x10, 0x80, 0x89, 0x31, 0x20, 0xea, 0x32, 0x00, - 0xbf, 0x33, 0x67, 0x0a, - 0x20, 0x19, 0x32, 0x6a, - 0x02, 0x4d, 0xf8, 0x69, - 0x40, 0x33, 0x67, 0x02, - 0x00, 0xe2, 0xf8, 0x41, - 0x80, 0x33, 0xb5, 0x6a, + 0xbf, 0x39, 0x73, 0x0a, + 0x10, 0x4c, 0x52, 0x6a, + 0x20, 0x19, 0x4a, 0x6a, + 0x20, 0x19, 0x4e, 0x6a, + 0x02, 0x4d, 0x10, 0x6a, + 0x40, 0x39, 0x73, 0x02, + 0x00, 0xe2, 0x10, 0x42, + 0x80, 0x39, 0xd1, 0x6a, 0x01, 0x44, 0x10, 0x33, 0x08, 0x92, 0x25, 0x03, - 0x00, 0xe2, 0xf8, 0x41, + 0x00, 0xe2, 0x10, 0x42, 0x10, 0xea, 0x80, 0x00, - 0x01, 0x31, 0xc5, 0x31, - 0x80, 0xe2, 0x60, 0x62, - 0x10, 0x92, 0x85, 0x6a, + 0x01, 0x37, 0xc5, 0x31, + 0x80, 0xe2, 0x7c, 0x62, + 0x10, 0x92, 0xa1, 0x6a, 0xc0, 0x94, 0xc5, 0x01, - 0x40, 0x92, 0x51, 0x6a, + 0x40, 0x92, 0x6d, 0x6a, 0xbf, 0xe2, 0xc4, 0x09, - 0x20, 0x92, 0x65, 0x7a, + 0x20, 0x92, 0x81, 0x7a, 0x01, 0xe2, 0x88, 0x30, - 0x00, 0xe2, 0xb8, 0x5b, - 0xa0, 0x36, 0x6d, 0x62, + 0x00, 0xe2, 0xde, 0x5b, + 0xa0, 0x3c, 0x89, 0x62, 0x23, 0x92, 0x89, 0x08, - 0x00, 0xe2, 0xb8, 0x5b, - 0xa0, 0x36, 0x6d, 0x62, - 0x00, 0xa8, 0x64, 0x42, - 0xff, 0xe2, 0x64, 0x62, - 0x00, 0xe2, 0x84, 0x42, + 0x00, 0xe2, 0xde, 0x5b, + 0xa0, 0x3c, 0x89, 0x62, + 0x00, 0xa8, 0x80, 0x42, + 0xff, 0xe2, 0x80, 0x62, + 0x00, 0xe2, 0xa0, 0x42, 0x40, 0xea, 0x98, 0x00, 0x01, 0xe2, 0x88, 0x30, - 0x00, 0xe2, 0xb8, 0x5b, - 0xa0, 0x36, 0x43, 0x72, + 0x00, 0xe2, 0xde, 0x5b, + 0xa0, 0x3c, 0x5f, 0x72, 0x40, 0xea, 0x98, 0x00, - 0x01, 0x31, 0x89, 0x32, - 0x08, 0xea, 0x62, 0x02, - 0x00, 0xe2, 0xf8, 0x41, - 0xe0, 0xea, 0xd4, 0x5b, - 0x80, 0xe0, 0xc0, 0x6a, - 0x04, 0xe0, 0x66, 0x73, - 0x02, 0xe0, 0x96, 0x73, - 0x00, 0xea, 0x1e, 0x73, - 0x03, 0xe0, 0xa6, 0x73, - 0x23, 0xe0, 0x96, 0x72, - 0x08, 0xe0, 0xbc, 0x72, - 0x00, 0xe2, 0xb8, 0x5b, - 0x07, 0xea, 0x50, 0x59, + 0x01, 0x37, 0x95, 0x32, + 0x08, 0xea, 0x6e, 0x02, + 0x00, 0xe2, 0x10, 0x42, + 0xe0, 0xea, 0xfa, 0x5b, + 0x80, 0xe0, 0xdc, 0x6a, + 0x04, 0xe0, 0x8e, 0x73, + 0x02, 0xe0, 0xc0, 0x73, + 0x00, 0xea, 0x3a, 0x73, + 0x03, 0xe0, 0xd0, 0x73, + 0x23, 0xe0, 0xb2, 0x72, + 0x08, 0xe0, 0xd8, 0x72, + 0x00, 0xe2, 0xde, 0x5b, + 0x07, 0xea, 0x60, 0x59, 0x07, 0xea, 0x04, 0x00, - 0x08, 0x42, 0xf9, 0x71, - 0x04, 0x42, 0x93, 0x62, - 0x01, 0x43, 0x89, 0x30, - 0x00, 0xe2, 0x84, 0x42, + 0x08, 0x48, 0x11, 0x72, + 0x04, 0x48, 0xaf, 0x62, + 0x01, 0x49, 0x89, 0x30, + 0x00, 0xe2, 0xa0, 0x42, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0x84, 0x42, - 0x01, 0x00, 0x60, 0x32, - 0x33, 0xea, 0x44, 0x59, + 0x00, 0xe2, 0xa0, 0x42, + 0x01, 0x00, 0x6c, 0x32, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x4c, 0x34, 0xc1, 0x28, + 0x4c, 0x3a, 0xc1, 0x28, 0x01, 0x64, 0xc0, 0x31, - 0x00, 0x30, 0x45, 0x59, - 0x01, 0x30, 0x01, 0x30, - 0x01, 0xe0, 0xba, 0x7a, - 0xa0, 0xea, 0xca, 0x5b, - 0x01, 0xa0, 0xba, 0x62, - 0x01, 0x84, 0xaf, 0x7a, - 0x01, 0x95, 0xbd, 0x6a, - 0x05, 0xea, 0x50, 0x59, + 0x00, 0x36, 0x5b, 0x59, + 0x01, 0x36, 0x01, 0x30, + 0x01, 0xe0, 0xd6, 0x7a, + 0xa0, 0xea, 0xf0, 0x5b, + 0x01, 0xa0, 0xd6, 0x62, + 0x01, 0x84, 0xcb, 0x7a, + 0x01, 0x95, 0xd9, 0x6a, + 0x05, 0xea, 0x60, 0x59, 0x05, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xbc, 0x42, - 0x03, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0xd8, 0x42, + 0x03, 0xea, 0x60, 0x59, 0x03, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xbc, 0x42, - 0x07, 0xea, 0xdc, 0x5b, + 0x00, 0xe2, 0xd8, 0x42, + 0x07, 0xea, 0x02, 0x5c, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0xf8, 0x41, - 0x3f, 0xe0, 0x6a, 0x0a, - 0xc0, 0x34, 0xc1, 0x09, - 0x00, 0x35, 0x51, 0x01, + 0x00, 0xe2, 0x10, 0x42, + 0x3f, 0xe0, 0x76, 0x0a, + 0xc0, 0x3a, 0xc1, 0x09, + 0x00, 0x3b, 0x51, 0x01, 0xff, 0xea, 0x52, 0x09, - 0x30, 0x34, 0xc5, 0x09, + 0x30, 0x3a, 0xc5, 0x09, 0x3d, 0xe2, 0xc4, 0x29, 0xb8, 0xe2, 0xc4, 0x19, 0x01, 0xea, 0xc6, 0x01, 0x02, 0xe2, 0xc8, 0x31, 0x02, 0xec, 0x40, 0x31, - 0xff, 0xa1, 0xdc, 0x72, + 0xff, 0xa1, 0xf8, 0x72, 0x02, 0xe8, 0xda, 0x31, 0x02, 0xa0, 0x50, 0x31, - 0x00, 0xe2, 0xfe, 0x42, - 0x80, 0x33, 0x67, 0x02, + 0x00, 0xe2, 0x1a, 0x43, + 0x80, 0x39, 0x73, 0x02, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0xb8, 0x5b, - 0x01, 0x33, 0x67, 0x02, - 0xe0, 0x36, 0x19, 0x63, - 0x02, 0x33, 0x67, 0x02, - 0x20, 0x46, 0x12, 0x63, + 0x00, 0xe2, 0xde, 0x5b, + 0x01, 0x39, 0x73, 0x02, + 0xe0, 0x3c, 0x35, 0x63, + 0x02, 0x39, 0x73, 0x02, + 0x20, 0x46, 0x2e, 0x63, 0xff, 0xea, 0x52, 0x09, - 0xa8, 0xea, 0xca, 0x5b, - 0x04, 0x92, 0xf9, 0x7a, - 0x01, 0x34, 0xc1, 0x31, - 0x00, 0x93, 0xf9, 0x62, - 0x01, 0x35, 0xc1, 0x31, - 0x00, 0x94, 0x03, 0x73, + 0xa8, 0xea, 0xf0, 0x5b, + 0x04, 0x92, 0x15, 0x7b, + 0x01, 0x3a, 0xc1, 0x31, + 0x00, 0x93, 0x15, 0x63, + 0x01, 0x3b, 0xc1, 0x31, + 0x00, 0x94, 0x1f, 0x73, 0x01, 0xa9, 0x52, 0x11, - 0xff, 0xa9, 0xee, 0x6a, - 0x00, 0xe2, 0x12, 0x43, - 0x10, 0x33, 0x67, 0x02, - 0x04, 0x92, 0x13, 0x7b, + 0xff, 0xa9, 0x0a, 0x6b, + 0x00, 0xe2, 0x2e, 0x43, + 0x10, 0x39, 0x73, 0x02, + 0x04, 0x92, 0x2f, 0x7b, 0xfb, 0x92, 0x25, 0x0b, - 0xff, 0xea, 0x66, 0x0a, - 0x01, 0xa4, 0x0d, 0x6b, - 0x02, 0xa8, 0x90, 0x32, - 0x00, 0xe2, 0x6a, 0x59, - 0x10, 0x92, 0xbd, 0x7a, - 0xff, 0xea, 0xdc, 0x5b, - 0x00, 0xe2, 0xbc, 0x42, - 0x04, 0xea, 0x50, 0x59, + 0xff, 0xea, 0x72, 0x0a, + 0x01, 0xa4, 0x29, 0x6b, + 0x02, 0xa8, 0x9c, 0x32, + 0x00, 0xe2, 0x7a, 0x59, + 0x10, 0x92, 0xd9, 0x7a, + 0xff, 0xea, 0x02, 0x5c, + 0x00, 0xe2, 0xd8, 0x42, + 0x04, 0xea, 0x60, 0x59, 0x04, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xbc, 0x42, - 0x04, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0xd8, 0x42, + 0x04, 0xea, 0x60, 0x59, 0x04, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x08, 0x92, 0xb5, 0x7a, - 0xc0, 0x33, 0x29, 0x7b, - 0x80, 0x33, 0xb5, 0x6a, - 0xff, 0x88, 0x29, 0x6b, - 0x40, 0x33, 0xb5, 0x6a, - 0x10, 0x92, 0x2f, 0x7b, - 0x0a, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x10, 0x42, + 0x08, 0x92, 0xd1, 0x7a, + 0xc0, 0x39, 0x45, 0x7b, + 0x80, 0x39, 0xd1, 0x6a, + 0xff, 0x88, 0x45, 0x6b, + 0x40, 0x39, 0xd1, 0x6a, + 0x10, 0x92, 0x4b, 0x7b, + 0x0a, 0xea, 0x60, 0x59, 0x0a, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x4e, 0x5b, - 0x00, 0xe2, 0x82, 0x43, - 0x50, 0x4b, 0x36, 0x6b, + 0x00, 0xe2, 0x6a, 0x5b, + 0x00, 0xe2, 0xaa, 0x43, + 0x50, 0x4b, 0x52, 0x6b, 0xbf, 0x3a, 0x74, 0x08, 0x01, 0xe0, 0xf4, 0x31, 0xff, 0xea, 0xc0, 0x09, - 0x01, 0x2e, 0x5d, 0x1a, - 0x00, 0x2f, 0x5f, 0x22, - 0x04, 0x47, 0x8f, 0x02, + 0x01, 0x32, 0x65, 0x1a, + 0x00, 0x33, 0x67, 0x22, + 0x04, 0x4d, 0x9b, 0x02, 0x01, 0xfa, 0xc0, 0x35, - 0x02, 0xa8, 0x84, 0x32, + 0x02, 0xa8, 0x90, 0x32, 0x02, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x02, 0x42, 0x51, 0x31, - 0xff, 0x90, 0x65, 0x68, - 0xff, 0x88, 0x5b, 0x6b, - 0x01, 0xa4, 0x57, 0x6b, - 0x02, 0xa4, 0x5f, 0x6b, - 0x01, 0x84, 0x5f, 0x7b, + 0x02, 0x48, 0x51, 0x31, + 0xff, 0x90, 0x85, 0x68, + 0xff, 0x88, 0x77, 0x6b, + 0x01, 0xa4, 0x73, 0x6b, + 0x02, 0xa4, 0x7b, 0x6b, + 0x01, 0x84, 0x7b, 0x7b, 0x02, 0x28, 0x19, 0x33, 0x02, 0xa8, 0x50, 0x36, - 0xff, 0x88, 0x5f, 0x73, - 0x00, 0xe2, 0x32, 0x5b, + 0xff, 0x88, 0x7b, 0x73, + 0x00, 0xe2, 0x4e, 0x5b, 0x02, 0xa8, 0x20, 0x33, - 0x02, 0x2c, 0x19, 0x33, + 0x04, 0xa4, 0x49, 0x03, + 0xff, 0xea, 0x1a, 0x03, + 0xff, 0x2d, 0x87, 0x63, 0x02, 0xa8, 0x58, 0x32, - 0x04, 0xa4, 0x49, 0x07, - 0xc0, 0x33, 0xb5, 0x6a, + 0x02, 0xa8, 0x5c, 0x36, + 0x02, 0xa8, 0x40, 0x31, + 0x02, 0x2e, 0x51, 0x31, + 0x02, 0xa0, 0x18, 0x33, + 0x02, 0xa0, 0x5c, 0x36, + 0xc0, 0x39, 0xd1, 0x6a, 0x04, 0x92, 0x25, 0x03, - 0x20, 0x92, 0x83, 0x6b, + 0x20, 0x92, 0xab, 0x6b, 0x02, 0xa8, 0x40, 0x31, - 0xc0, 0x34, 0xc1, 0x09, - 0x00, 0x35, 0x51, 0x01, + 0xc0, 0x3a, 0xc1, 0x09, + 0x00, 0x3b, 0x51, 0x01, 0xff, 0xea, 0x52, 0x09, - 0x30, 0x34, 0xc5, 0x09, + 0x30, 0x3a, 0xc5, 0x09, 0x3d, 0xe2, 0xc4, 0x29, 0xb8, 0xe2, 0xc4, 0x19, 0x01, 0xea, 0xc6, 0x01, @@ -458,69 +478,75 @@ 0xf7, 0x57, 0xae, 0x08, 0x08, 0xea, 0x98, 0x00, 0x01, 0x44, 0xd4, 0x31, - 0xee, 0x00, 0x8c, 0x6b, + 0xee, 0x00, 0xb4, 0x6b, 0x02, 0xea, 0xb4, 0x00, - 0x00, 0xe2, 0xb4, 0x5b, - 0x09, 0x4c, 0x8e, 0x7b, + 0xc0, 0xea, 0x72, 0x02, + 0x09, 0x4c, 0xb6, 0x7b, + 0x01, 0xea, 0x78, 0x02, 0x08, 0x4c, 0x06, 0x68, - 0x0b, 0xea, 0x50, 0x59, + 0x0b, 0xea, 0x60, 0x59, 0x0b, 0xea, 0x04, 0x00, 0x01, 0x44, 0xd4, 0x31, - 0x20, 0x33, 0xf9, 0x79, - 0x00, 0xe2, 0x9e, 0x5b, - 0x00, 0xe2, 0xf8, 0x41, - 0x01, 0x84, 0xa3, 0x7b, + 0x20, 0x39, 0x11, 0x7a, + 0x00, 0xe2, 0xc8, 0x5b, + 0x00, 0xe2, 0x10, 0x42, + 0x01, 0x84, 0xcd, 0x7b, 0x01, 0xa4, 0x49, 0x07, 0x08, 0x60, 0x30, 0x33, 0x08, 0x80, 0x41, 0x37, - 0xdf, 0x33, 0x67, 0x0a, - 0xee, 0x00, 0xb0, 0x6b, + 0xdf, 0x39, 0x73, 0x0a, + 0xee, 0x00, 0xda, 0x6b, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x00, 0xe2, 0x6a, 0x59, - 0x00, 0xe2, 0xbc, 0x42, - 0x01, 0xea, 0x6c, 0x02, - 0xc0, 0xea, 0x66, 0x06, - 0xff, 0x42, 0xc4, 0x6b, - 0x01, 0x41, 0xb8, 0x6b, - 0x02, 0x41, 0xb8, 0x7b, - 0xff, 0x42, 0xc4, 0x6b, - 0x01, 0x41, 0xb8, 0x6b, - 0x02, 0x41, 0xb8, 0x7b, - 0xff, 0x42, 0xc4, 0x7b, - 0x04, 0x4c, 0xb8, 0x6b, - 0xe0, 0x41, 0x6c, 0x0e, + 0x00, 0xe2, 0x7a, 0x59, + 0x00, 0xe2, 0xd8, 0x42, + 0xff, 0x42, 0xea, 0x6b, + 0x01, 0x41, 0xde, 0x6b, + 0x02, 0x41, 0xde, 0x7b, + 0xff, 0x42, 0xea, 0x6b, + 0x01, 0x41, 0xde, 0x6b, + 0x02, 0x41, 0xde, 0x7b, + 0xff, 0x42, 0xea, 0x7b, + 0x04, 0x4c, 0xde, 0x6b, + 0xe0, 0x41, 0x78, 0x0e, 0x01, 0x44, 0xd4, 0x31, - 0xff, 0x42, 0xcc, 0x7b, - 0x04, 0x4c, 0xcc, 0x6b, - 0xe0, 0x41, 0x6c, 0x0a, - 0xe0, 0x36, 0xf9, 0x61, + 0xff, 0x42, 0xf2, 0x7b, + 0x04, 0x4c, 0xf2, 0x6b, + 0xe0, 0x41, 0x78, 0x0a, + 0xe0, 0x3c, 0x11, 0x62, 0xff, 0xea, 0xca, 0x09, 0x01, 0xe2, 0xc8, 0x31, 0x01, 0x46, 0xda, 0x35, 0x01, 0x44, 0xd4, 0x35, 0x10, 0xea, 0x80, 0x00, - 0x01, 0xe2, 0x62, 0x36, - 0x04, 0xa6, 0xe4, 0x7b, + 0x01, 0xe2, 0x6e, 0x36, + 0x04, 0xa6, 0x0a, 0x7c, 0xff, 0xea, 0x5a, 0x09, 0xff, 0xea, 0x4c, 0x0d, - 0x01, 0xa6, 0x02, 0x6c, - 0x10, 0xad, 0x64, 0x78, - 0x80, 0xad, 0xfa, 0x6b, - 0x08, 0xad, 0x64, 0x68, + 0x01, 0xa6, 0x36, 0x6c, + 0x10, 0xad, 0x84, 0x78, + 0x80, 0xad, 0x2e, 0x6c, + 0x08, 0xad, 0x84, 0x68, + 0x20, 0x19, 0x22, 0x7c, + 0x80, 0xea, 0xb2, 0x01, + 0x11, 0x00, 0x00, 0x10, + 0x02, 0xa6, 0x1e, 0x7c, + 0xff, 0xea, 0xb2, 0x0d, + 0x11, 0x00, 0x00, 0x10, + 0xff, 0xea, 0xb2, 0x09, 0x04, 0x84, 0xf9, 0x30, 0x00, 0xea, 0x08, 0x81, 0xff, 0xea, 0xd4, 0x09, 0x02, 0x84, 0xf9, 0x88, 0x0d, 0xea, 0x5a, 0x01, 0x04, 0xa6, 0x4c, 0x05, - 0x04, 0xa6, 0x64, 0x78, + 0x04, 0xa6, 0x84, 0x78, 0xff, 0xea, 0x5a, 0x09, 0x03, 0x84, 0x59, 0x89, 0x03, 0xea, 0x4c, 0x01, - 0x80, 0x1a, 0x64, 0x78, - 0x08, 0x19, 0x64, 0x78, + 0x80, 0x1a, 0x84, 0x78, + 0x08, 0x19, 0x84, 0x78, 0x08, 0xb0, 0xe0, 0x30, 0x04, 0xb0, 0xe0, 0x30, 0x03, 0xb0, 0xf0, 0x30, @@ -533,259 +559,259 @@ 0x00, 0x86, 0x0d, 0x23, 0x00, 0x87, 0x0f, 0x23, 0x01, 0x84, 0xc5, 0x31, - 0x80, 0x83, 0x25, 0x7c, + 0x80, 0x83, 0x59, 0x7c, 0x02, 0xe2, 0xc4, 0x01, 0xff, 0xea, 0x4c, 0x09, 0x01, 0xe2, 0x36, 0x30, 0xc8, 0x19, 0x32, 0x00, 0x88, 0x19, 0x32, 0x00, 0x01, 0xac, 0xd4, 0x99, - 0x00, 0xe2, 0x64, 0x50, + 0x00, 0xe2, 0x84, 0x50, 0xfe, 0xa6, 0x4c, 0x0d, 0x0b, 0x98, 0xe1, 0x30, 0xfd, 0xa4, 0x49, 0x09, - 0x80, 0xa3, 0x39, 0x7c, + 0x80, 0xa3, 0x6d, 0x7c, 0x02, 0xa4, 0x48, 0x01, 0x01, 0xa4, 0x36, 0x30, 0xa8, 0xea, 0x32, 0x00, 0xfd, 0xa4, 0x49, 0x0b, 0x05, 0xa3, 0x07, 0x33, - 0x80, 0x83, 0x45, 0x6c, + 0x80, 0x83, 0x79, 0x6c, 0x02, 0xea, 0x4c, 0x05, 0xff, 0xea, 0x4c, 0x0d, - 0x00, 0xe2, 0x3e, 0x59, - 0x02, 0xa6, 0xe6, 0x6b, + 0x00, 0xe2, 0x52, 0x59, + 0x02, 0xa6, 0x0c, 0x6c, 0x80, 0xf9, 0xf2, 0x05, - 0xc0, 0x33, 0x53, 0x7c, - 0x03, 0xea, 0x50, 0x59, + 0xc0, 0x39, 0x87, 0x7c, + 0x03, 0xea, 0x60, 0x59, 0x03, 0xea, 0x04, 0x00, - 0x20, 0x33, 0x77, 0x7c, - 0x01, 0x84, 0x5d, 0x6c, - 0x06, 0xea, 0x50, 0x59, + 0x20, 0x39, 0xab, 0x7c, + 0x01, 0x84, 0x91, 0x6c, + 0x06, 0xea, 0x60, 0x59, 0x06, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x7a, 0x44, - 0x01, 0x00, 0x60, 0x32, - 0xee, 0x00, 0x66, 0x6c, + 0x00, 0xe2, 0xae, 0x44, + 0x01, 0x00, 0x6c, 0x32, + 0xee, 0x00, 0x9a, 0x6c, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5a, 0x59, 0x33, 0xea, 0x00, 0x00, 0x80, 0x3d, 0x7a, 0x00, - 0xfc, 0x42, 0x68, 0x7c, + 0xfc, 0x42, 0x9c, 0x7c, 0x7f, 0x3d, 0x7a, 0x08, - 0x00, 0x30, 0x45, 0x59, - 0x01, 0x30, 0x01, 0x30, - 0x09, 0xea, 0x50, 0x59, + 0x00, 0x36, 0x5b, 0x59, + 0x01, 0x36, 0x01, 0x30, + 0x09, 0xea, 0x60, 0x59, 0x09, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x01, 0xa4, 0x5d, 0x6c, - 0x00, 0xe2, 0x30, 0x5c, - 0x20, 0x33, 0x67, 0x02, - 0x01, 0x00, 0x60, 0x32, - 0x02, 0xa6, 0x82, 0x7c, - 0x00, 0xe2, 0x46, 0x5c, - 0x00, 0xe2, 0x56, 0x58, - 0x00, 0xe2, 0x66, 0x58, - 0x00, 0xe2, 0x3a, 0x58, - 0x00, 0x30, 0x45, 0x59, - 0x01, 0x30, 0x01, 0x30, - 0x20, 0x19, 0x82, 0x6c, - 0x00, 0xe2, 0xb2, 0x5c, - 0x04, 0x19, 0x9c, 0x6c, + 0x00, 0xe2, 0x10, 0x42, + 0x01, 0xa4, 0x91, 0x6c, + 0x00, 0xe2, 0x64, 0x5c, + 0x20, 0x39, 0x73, 0x02, + 0x01, 0x00, 0x6c, 0x32, + 0x02, 0xa6, 0xb6, 0x7c, + 0x00, 0xe2, 0x7a, 0x5c, + 0x00, 0xe2, 0x76, 0x58, + 0x00, 0xe2, 0x86, 0x58, + 0x00, 0xe2, 0x5a, 0x58, + 0x00, 0x36, 0x5b, 0x59, + 0x01, 0x36, 0x01, 0x30, + 0x20, 0x19, 0xb6, 0x6c, + 0x00, 0xe2, 0xe6, 0x5c, + 0x04, 0x19, 0xd0, 0x6c, 0x02, 0x19, 0x32, 0x00, - 0x01, 0x84, 0x9d, 0x7c, - 0x01, 0x1b, 0x96, 0x7c, - 0x01, 0x1a, 0x9c, 0x6c, - 0x00, 0xe2, 0x4c, 0x44, - 0x80, 0x4b, 0xa2, 0x6c, - 0x01, 0x4c, 0x9e, 0x7c, - 0x03, 0x42, 0x4c, 0x6c, - 0x00, 0xe2, 0xe0, 0x5b, + 0x01, 0x84, 0xd1, 0x7c, + 0x01, 0x1b, 0xca, 0x7c, + 0x01, 0x1a, 0xd0, 0x6c, + 0x00, 0xe2, 0x80, 0x44, + 0x80, 0x4b, 0xd6, 0x6c, + 0x01, 0x4c, 0xd2, 0x7c, + 0x03, 0x42, 0x80, 0x6c, + 0x00, 0xe2, 0x06, 0x5c, 0x80, 0xf9, 0xf2, 0x01, - 0x04, 0x33, 0xf9, 0x79, - 0x00, 0xe2, 0xf8, 0x41, - 0x08, 0x5d, 0xba, 0x6c, - 0x00, 0xe2, 0x56, 0x58, - 0x00, 0x30, 0x45, 0x59, - 0x01, 0x30, 0x01, 0x30, - 0x02, 0x1b, 0xaa, 0x7c, - 0x08, 0x5d, 0xb8, 0x7c, + 0x04, 0x39, 0x11, 0x7a, + 0x00, 0xe2, 0x10, 0x42, + 0x08, 0x5d, 0xee, 0x6c, + 0x00, 0xe2, 0x76, 0x58, + 0x00, 0x36, 0x5b, 0x59, + 0x01, 0x36, 0x01, 0x30, + 0x02, 0x1b, 0xde, 0x7c, + 0x08, 0x5d, 0xec, 0x7c, 0x03, 0x68, 0x00, 0x37, 0x01, 0x84, 0x09, 0x07, - 0x80, 0x1b, 0xc4, 0x7c, - 0x80, 0x84, 0xc5, 0x6c, + 0x80, 0x1b, 0xf8, 0x7c, + 0x80, 0x84, 0xf9, 0x6c, 0xff, 0x85, 0x0b, 0x1b, 0xff, 0x86, 0x0d, 0x23, 0xff, 0x87, 0x0f, 0x23, 0xf8, 0x1b, 0x08, 0x0b, 0xff, 0xea, 0x06, 0x0b, 0x03, 0x68, 0x00, 0x37, - 0x00, 0xe2, 0xc4, 0x58, + 0x00, 0xe2, 0xd6, 0x58, 0x10, 0xea, 0x18, 0x00, 0xf9, 0xd9, 0xb2, 0x0d, 0x01, 0xd9, 0xb2, 0x05, 0x01, 0x52, 0x48, 0x31, - 0x20, 0xa4, 0xee, 0x7c, - 0x20, 0x5b, 0xee, 0x7c, - 0x80, 0xf9, 0xfc, 0x7c, + 0x20, 0xa4, 0x22, 0x7d, + 0x20, 0x5b, 0x22, 0x7d, + 0x80, 0xf9, 0x30, 0x7d, 0x02, 0xea, 0xb4, 0x00, 0x11, 0x00, 0x00, 0x10, - 0x04, 0x19, 0x08, 0x7d, + 0x04, 0x19, 0x3c, 0x7d, 0xdf, 0x19, 0x32, 0x08, - 0x60, 0x5b, 0xe6, 0x6c, - 0x01, 0x4c, 0xe2, 0x7c, + 0x60, 0x5b, 0x3c, 0x6d, + 0x01, 0x4c, 0x16, 0x7d, 0x20, 0x19, 0x32, 0x00, 0x01, 0xd9, 0xb2, 0x05, 0x02, 0xea, 0xb4, 0x00, 0x01, 0xd9, 0xb2, 0x05, - 0x10, 0x5b, 0x00, 0x6d, - 0x08, 0x5b, 0x0a, 0x6d, - 0x20, 0x5b, 0xfa, 0x6c, - 0x02, 0x5b, 0x2a, 0x6d, - 0x0e, 0xea, 0x50, 0x59, + 0x10, 0x5b, 0x34, 0x6d, + 0x08, 0x5b, 0x3e, 0x6d, + 0x20, 0x5b, 0x2e, 0x6d, + 0x02, 0x5b, 0x5e, 0x6d, + 0x0e, 0xea, 0x60, 0x59, 0x0e, 0xea, 0x04, 0x00, - 0x80, 0xf9, 0xea, 0x6c, + 0x80, 0xf9, 0x1e, 0x6d, 0xdf, 0x5c, 0xb8, 0x08, 0x01, 0xd9, 0xb2, 0x05, - 0x01, 0xa4, 0xe5, 0x6d, - 0x00, 0xe2, 0x30, 0x5c, - 0x00, 0xe2, 0x34, 0x5d, + 0x01, 0xa4, 0x19, 0x6e, + 0x00, 0xe2, 0x64, 0x5c, + 0x00, 0xe2, 0x68, 0x5d, 0x01, 0x90, 0x21, 0x1b, 0x01, 0xd9, 0xb2, 0x05, - 0x00, 0xe2, 0x32, 0x5b, + 0x00, 0xe2, 0x4e, 0x5b, 0xf3, 0x96, 0xd5, 0x19, - 0x00, 0xe2, 0x18, 0x55, - 0x80, 0x96, 0x19, 0x6d, - 0x0f, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x4c, 0x55, + 0x80, 0x96, 0x4d, 0x6d, + 0x0f, 0xea, 0x60, 0x59, 0x0f, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x20, 0x45, + 0x00, 0xe2, 0x54, 0x45, 0x04, 0x8c, 0xe1, 0x30, 0x01, 0xea, 0xf2, 0x00, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0xff, 0x97, 0x27, 0x7d, - 0x14, 0xea, 0x50, 0x59, + 0xff, 0x97, 0x5b, 0x7d, + 0x14, 0xea, 0x60, 0x59, 0x14, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x96, 0x5d, + 0x00, 0xe2, 0xca, 0x5d, 0x01, 0xd9, 0xb2, 0x05, 0x09, 0x80, 0xe1, 0x30, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0x8e, 0x5d, + 0x00, 0xe2, 0xc2, 0x5d, 0x01, 0xd9, 0xb2, 0x05, - 0x02, 0xa6, 0x44, 0x7d, - 0x00, 0xe2, 0x3e, 0x59, - 0x20, 0x5b, 0x52, 0x6d, - 0xfc, 0x42, 0x3e, 0x7d, - 0x10, 0x40, 0x40, 0x6d, - 0x20, 0x4d, 0x42, 0x7d, - 0x08, 0x5d, 0x52, 0x6d, - 0x02, 0xa6, 0xe6, 0x6b, - 0x00, 0xe2, 0x3e, 0x59, - 0x20, 0x5b, 0x52, 0x6d, - 0x01, 0x1b, 0x72, 0x6d, - 0xfc, 0x42, 0x4e, 0x7d, - 0x10, 0x40, 0x50, 0x6d, - 0x20, 0x4d, 0x64, 0x78, - 0x08, 0x5d, 0x64, 0x78, + 0x02, 0xa6, 0x78, 0x7d, + 0x00, 0xe2, 0x52, 0x59, + 0x20, 0x5b, 0x86, 0x6d, + 0xfc, 0x42, 0x72, 0x7d, + 0x10, 0x40, 0x74, 0x6d, + 0x20, 0x4d, 0x76, 0x7d, + 0x08, 0x5d, 0x86, 0x6d, + 0x02, 0xa6, 0x0c, 0x6c, + 0x00, 0xe2, 0x52, 0x59, + 0x20, 0x5b, 0x86, 0x6d, + 0x01, 0x1b, 0xa6, 0x6d, + 0xfc, 0x42, 0x82, 0x7d, + 0x10, 0x40, 0x84, 0x6d, + 0x20, 0x4d, 0x84, 0x78, + 0x08, 0x5d, 0x84, 0x78, 0x02, 0x19, 0x32, 0x00, 0x01, 0x5b, 0x40, 0x31, - 0x00, 0xe2, 0xb2, 0x5c, - 0x00, 0xe2, 0x9e, 0x5b, + 0x00, 0xe2, 0xe6, 0x5c, + 0x00, 0xe2, 0xc8, 0x5b, 0x20, 0xea, 0xb6, 0x00, - 0x00, 0xe2, 0xe0, 0x5b, + 0x00, 0xe2, 0x06, 0x5c, 0x20, 0x5c, 0xb8, 0x00, - 0x04, 0x19, 0x68, 0x6d, - 0x01, 0x1a, 0x68, 0x6d, - 0x00, 0xe2, 0x3e, 0x59, - 0x01, 0x1a, 0x64, 0x78, + 0x04, 0x19, 0x9c, 0x6d, + 0x01, 0x1a, 0x9c, 0x6d, + 0x00, 0xe2, 0x52, 0x59, + 0x01, 0x1a, 0x84, 0x78, 0x80, 0xf9, 0xf2, 0x01, - 0x20, 0xa0, 0xcc, 0x7d, + 0x20, 0xa0, 0x00, 0x7e, 0xff, 0x90, 0x21, 0x1b, - 0x08, 0x92, 0x43, 0x6b, + 0x08, 0x92, 0x5f, 0x6b, 0x02, 0xea, 0xb4, 0x04, 0x01, 0xa4, 0x49, 0x03, - 0x40, 0x5b, 0x82, 0x6d, - 0x00, 0xe2, 0x3e, 0x59, - 0x40, 0x5b, 0x82, 0x6d, - 0x04, 0x5d, 0xe6, 0x7d, - 0x01, 0x1a, 0xe6, 0x7d, - 0x20, 0x4d, 0x64, 0x78, - 0x40, 0x5b, 0xcc, 0x7d, - 0x04, 0x5d, 0xe6, 0x7d, - 0x01, 0x1a, 0xe6, 0x7d, + 0x40, 0x5b, 0xb6, 0x6d, + 0x00, 0xe2, 0x52, 0x59, + 0x40, 0x5b, 0xb6, 0x6d, + 0x04, 0x5d, 0x1a, 0x7e, + 0x01, 0x1a, 0x1a, 0x7e, + 0x20, 0x4d, 0x84, 0x78, + 0x40, 0x5b, 0x00, 0x7e, + 0x04, 0x5d, 0x1a, 0x7e, + 0x01, 0x1a, 0x1a, 0x7e, 0x80, 0xf9, 0xf2, 0x01, 0xff, 0x90, 0x21, 0x1b, - 0x08, 0x92, 0x43, 0x6b, + 0x08, 0x92, 0x5f, 0x6b, 0x02, 0xea, 0xb4, 0x04, - 0x00, 0xe2, 0x3e, 0x59, - 0x01, 0x1b, 0x64, 0x78, + 0x00, 0xe2, 0x52, 0x59, + 0x01, 0x1b, 0x84, 0x78, 0x80, 0xf9, 0xf2, 0x01, 0x02, 0xea, 0xb4, 0x04, - 0x00, 0xe2, 0x3e, 0x59, - 0x01, 0x1b, 0xaa, 0x6d, - 0x40, 0x5b, 0xb8, 0x7d, - 0x01, 0x1b, 0xaa, 0x6d, + 0x00, 0xe2, 0x52, 0x59, + 0x01, 0x1b, 0xde, 0x6d, + 0x40, 0x5b, 0xec, 0x7d, + 0x01, 0x1b, 0xde, 0x6d, 0x02, 0x19, 0x32, 0x00, - 0x01, 0x1a, 0x64, 0x78, + 0x01, 0x1a, 0x84, 0x78, 0x80, 0xf9, 0xf2, 0x01, 0xff, 0xea, 0x10, 0x03, 0x08, 0x92, 0x25, 0x03, - 0x00, 0xe2, 0x42, 0x43, - 0x01, 0x1a, 0xb4, 0x7d, - 0x40, 0x5b, 0xb0, 0x7d, - 0x01, 0x1a, 0x9e, 0x6d, - 0xfc, 0x42, 0x64, 0x78, - 0x01, 0x1a, 0xb8, 0x6d, - 0x10, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x5e, 0x43, + 0x01, 0x1a, 0xe8, 0x7d, + 0x40, 0x5b, 0xe4, 0x7d, + 0x01, 0x1a, 0xd2, 0x6d, + 0xfc, 0x42, 0x84, 0x78, + 0x01, 0x1a, 0xec, 0x6d, + 0x10, 0xea, 0x60, 0x59, 0x10, 0xea, 0x04, 0x00, - 0xfc, 0x42, 0x64, 0x78, - 0x10, 0x40, 0xbe, 0x6d, - 0x20, 0x4d, 0x64, 0x78, - 0x40, 0x5b, 0x9e, 0x6d, - 0x01, 0x1a, 0x64, 0x78, + 0xfc, 0x42, 0x84, 0x78, + 0x10, 0x40, 0xf2, 0x6d, + 0x20, 0x4d, 0x84, 0x78, + 0x40, 0x5b, 0xd2, 0x6d, + 0x01, 0x1a, 0x84, 0x78, 0x01, 0x90, 0x21, 0x1b, 0x30, 0x3f, 0xc0, 0x09, - 0x30, 0xe0, 0x64, 0x60, - 0x40, 0x4b, 0x64, 0x68, + 0x30, 0xe0, 0x84, 0x60, + 0x40, 0x4b, 0x84, 0x68, 0xff, 0xea, 0x52, 0x01, - 0xee, 0x00, 0xd2, 0x6d, + 0xee, 0x00, 0x08, 0x6e, 0x80, 0xf9, 0xf2, 0x01, 0xff, 0x90, 0x21, 0x1b, 0x02, 0xea, 0xb4, 0x00, 0x20, 0xea, 0x9a, 0x00, - 0xf3, 0x42, 0xde, 0x6d, - 0x12, 0xea, 0x50, 0x59, + 0xf3, 0x42, 0x12, 0x6e, + 0x12, 0xea, 0x60, 0x59, 0x12, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x0d, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x10, 0x42, + 0x0d, 0xea, 0x60, 0x59, 0x0d, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, + 0x00, 0xe2, 0x10, 0x42, 0x01, 0x90, 0x21, 0x1b, - 0x11, 0xea, 0x50, 0x59, + 0x11, 0xea, 0x60, 0x59, 0x11, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x32, 0x5b, + 0x00, 0xe2, 0x4e, 0x5b, 0x08, 0x5a, 0xb4, 0x00, - 0x00, 0xe2, 0x0c, 0x5e, + 0x00, 0xe2, 0x40, 0x5e, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0x3e, 0x59, - 0x80, 0x1a, 0xfa, 0x7d, - 0x00, 0xe2, 0x0c, 0x5e, + 0x00, 0xe2, 0x52, 0x59, + 0x80, 0x1a, 0x2e, 0x7e, + 0x00, 0xe2, 0x40, 0x5e, 0x80, 0x19, 0x32, 0x00, - 0x40, 0x5b, 0x00, 0x6e, - 0x08, 0x5a, 0x00, 0x7e, - 0x20, 0x4d, 0x64, 0x78, + 0x40, 0x5b, 0x34, 0x6e, + 0x08, 0x5a, 0x34, 0x7e, + 0x20, 0x4d, 0x84, 0x78, 0x02, 0x84, 0x09, 0x03, - 0x40, 0x5b, 0xcc, 0x7d, + 0x40, 0x5b, 0x00, 0x7e, 0xff, 0x90, 0x21, 0x1b, 0x80, 0xf9, 0xf2, 0x01, - 0x08, 0x92, 0x43, 0x6b, + 0x08, 0x92, 0x5f, 0x6b, 0x02, 0xea, 0xb4, 0x04, - 0x01, 0x38, 0xe1, 0x30, - 0x05, 0x39, 0xe3, 0x98, + 0x01, 0x40, 0xe1, 0x30, + 0x05, 0x41, 0xe3, 0x98, 0x01, 0xe0, 0xf4, 0x31, 0xff, 0xea, 0xc0, 0x09, - 0x00, 0x3a, 0xe5, 0x20, - 0x00, 0x3b, 0xe7, 0x20, + 0x00, 0x42, 0xe5, 0x20, + 0x00, 0x43, 0xe7, 0x20, 0x01, 0xfa, 0xc0, 0x31, 0x04, 0xea, 0xe8, 0x30, 0xff, 0xea, 0xf0, 0x08, @@ -794,12 +820,20 @@ }; typedef int ahd_patch_func_t (struct ahd_softc *ahd); +static ahd_patch_func_t ahd_patch23_func; + +static int +ahd_patch23_func(struct ahd_softc *ahd) +{ + return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0); +} + static ahd_patch_func_t ahd_patch22_func; static int ahd_patch22_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0); + return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0); } static ahd_patch_func_t ahd_patch21_func; @@ -807,7 +841,7 @@ static int ahd_patch21_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0); + return ((ahd->flags & AHD_INITIATORROLE) != 0); } static ahd_patch_func_t ahd_patch20_func; @@ -815,7 +849,7 @@ static int ahd_patch20_func(struct ahd_softc *ahd) { - return ((ahd->features & AHD_RTI) == 0); + return ((ahd->flags & AHD_TARGETROLE) != 0); } static ahd_patch_func_t ahd_patch19_func; @@ -823,7 +857,7 @@ static int ahd_patch19_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_INITIATORROLE) != 0); + return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0); } static ahd_patch_func_t ahd_patch18_func; @@ -831,7 +865,7 @@ static int ahd_patch18_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_TARGETROLE) != 0); + return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0); } static ahd_patch_func_t ahd_patch17_func; @@ -839,7 +873,7 @@ static int ahd_patch17_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0); + return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0); } static ahd_patch_func_t ahd_patch16_func; @@ -847,7 +881,7 @@ static int ahd_patch16_func(struct ahd_softc *ahd) { - return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0); + return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0); } static ahd_patch_func_t ahd_patch15_func; @@ -855,7 +889,7 @@ static int ahd_patch15_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0); + return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0); } static ahd_patch_func_t ahd_patch14_func; @@ -863,7 +897,7 @@ static int ahd_patch14_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0); + return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0); } static ahd_patch_func_t ahd_patch13_func; @@ -871,7 +905,7 @@ static int ahd_patch13_func(struct ahd_softc *ahd) { - return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0); + return ((ahd->features & AHD_RTI) == 0); } static ahd_patch_func_t ahd_patch12_func; @@ -879,7 +913,7 @@ static int ahd_patch12_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0); + return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0); } static ahd_patch_func_t ahd_patch11_func; @@ -887,7 +921,7 @@ static int ahd_patch11_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0); + return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0); } static ahd_patch_func_t ahd_patch10_func; @@ -895,7 +929,7 @@ static int ahd_patch10_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0); + return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0); } static ahd_patch_func_t ahd_patch9_func; @@ -903,7 +937,7 @@ static int ahd_patch9_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0); + return ((ahd->features & AHD_FAST_CDB_DELIVERY) != 0); } static ahd_patch_func_t ahd_patch8_func; @@ -992,147 +1026,149 @@ { ahd_patch0_func, 5, 1, 1 }, { ahd_patch2_func, 6, 1, 2 }, { ahd_patch0_func, 7, 1, 1 }, - { ahd_patch3_func, 20, 5, 1 }, - { ahd_patch2_func, 29, 1, 2 }, - { ahd_patch0_func, 30, 1, 1 }, - { ahd_patch1_func, 37, 1, 2 }, - { ahd_patch0_func, 38, 1, 1 }, - { ahd_patch2_func, 43, 1, 2 }, - { ahd_patch0_func, 44, 1, 1 }, - { ahd_patch2_func, 47, 1, 2 }, - { ahd_patch0_func, 48, 1, 1 }, - { ahd_patch2_func, 51, 1, 2 }, - { ahd_patch0_func, 52, 1, 1 }, - { ahd_patch2_func, 65, 1, 2 }, - { ahd_patch0_func, 66, 1, 1 }, - { ahd_patch2_func, 69, 1, 2 }, - { ahd_patch0_func, 70, 1, 1 }, - { ahd_patch1_func, 73, 1, 2 }, - { ahd_patch0_func, 74, 1, 1 }, - { ahd_patch4_func, 107, 1, 1 }, - { ahd_patch2_func, 162, 6, 1 }, - { ahd_patch1_func, 168, 2, 1 }, - { ahd_patch5_func, 170, 1, 1 }, - { ahd_patch2_func, 179, 1, 2 }, - { ahd_patch0_func, 180, 1, 1 }, - { ahd_patch6_func, 181, 2, 2 }, - { ahd_patch0_func, 183, 6, 3 }, - { ahd_patch2_func, 186, 1, 2 }, - { ahd_patch0_func, 187, 1, 1 }, - { ahd_patch2_func, 190, 1, 2 }, - { ahd_patch0_func, 191, 1, 1 }, - { ahd_patch7_func, 193, 2, 1 }, - { ahd_patch5_func, 201, 16, 2 }, - { ahd_patch0_func, 217, 1, 1 }, - { ahd_patch8_func, 237, 2, 1 }, - { ahd_patch1_func, 241, 1, 2 }, - { ahd_patch0_func, 242, 1, 1 }, - { ahd_patch7_func, 245, 2, 1 }, - { ahd_patch1_func, 259, 1, 2 }, - { ahd_patch0_func, 260, 1, 1 }, - { ahd_patch1_func, 263, 1, 2 }, - { ahd_patch0_func, 264, 1, 1 }, - { ahd_patch2_func, 267, 1, 2 }, - { ahd_patch0_func, 268, 1, 1 }, - { ahd_patch1_func, 323, 1, 2 }, - { ahd_patch0_func, 324, 1, 1 }, - { ahd_patch2_func, 332, 1, 2 }, - { ahd_patch0_func, 333, 1, 1 }, - { ahd_patch2_func, 336, 1, 2 }, - { ahd_patch0_func, 337, 1, 1 }, - { ahd_patch1_func, 343, 1, 2 }, - { ahd_patch0_func, 344, 1, 1 }, - { ahd_patch1_func, 346, 1, 2 }, + { ahd_patch3_func, 36, 5, 1 }, + { ahd_patch2_func, 45, 1, 2 }, + { ahd_patch0_func, 46, 1, 1 }, + { ahd_patch1_func, 53, 1, 2 }, + { ahd_patch0_func, 54, 1, 1 }, + { ahd_patch2_func, 59, 1, 2 }, + { ahd_patch0_func, 60, 1, 1 }, + { ahd_patch2_func, 63, 1, 2 }, + { ahd_patch0_func, 64, 1, 1 }, + { ahd_patch2_func, 67, 1, 2 }, + { ahd_patch0_func, 68, 1, 1 }, + { ahd_patch4_func, 116, 1, 1 }, + { ahd_patch2_func, 173, 3, 1 }, + { ahd_patch1_func, 176, 2, 1 }, + { ahd_patch5_func, 178, 1, 1 }, + { ahd_patch2_func, 187, 1, 2 }, + { ahd_patch0_func, 188, 1, 1 }, + { ahd_patch6_func, 189, 2, 2 }, + { ahd_patch0_func, 191, 6, 3 }, + { ahd_patch2_func, 194, 1, 2 }, + { ahd_patch0_func, 195, 1, 1 }, + { ahd_patch2_func, 198, 1, 2 }, + { ahd_patch0_func, 199, 1, 1 }, + { ahd_patch3_func, 201, 1, 1 }, + { ahd_patch7_func, 202, 3, 1 }, + { ahd_patch3_func, 211, 1, 1 }, + { ahd_patch5_func, 212, 16, 2 }, + { ahd_patch0_func, 228, 1, 1 }, + { ahd_patch8_func, 248, 2, 1 }, + { ahd_patch1_func, 252, 1, 2 }, + { ahd_patch0_func, 253, 1, 1 }, + { ahd_patch7_func, 256, 3, 1 }, + { ahd_patch1_func, 271, 1, 2 }, + { ahd_patch0_func, 272, 1, 1 }, + { ahd_patch1_func, 275, 1, 2 }, + { ahd_patch0_func, 276, 1, 1 }, + { ahd_patch2_func, 279, 1, 2 }, + { ahd_patch0_func, 280, 1, 1 }, + { ahd_patch9_func, 293, 2, 2 }, + { ahd_patch0_func, 295, 1, 1 }, + { ahd_patch1_func, 337, 1, 2 }, + { ahd_patch0_func, 338, 1, 1 }, + { ahd_patch2_func, 346, 1, 2 }, { ahd_patch0_func, 347, 1, 1 }, - { ahd_patch9_func, 366, 1, 1 }, - { ahd_patch9_func, 369, 1, 1 }, - { ahd_patch9_func, 371, 1, 1 }, - { ahd_patch9_func, 383, 1, 1 }, - { ahd_patch1_func, 393, 1, 2 }, - { ahd_patch0_func, 394, 1, 1 }, - { ahd_patch1_func, 396, 1, 2 }, - { ahd_patch0_func, 397, 1, 1 }, - { ahd_patch1_func, 405, 1, 2 }, - { ahd_patch0_func, 406, 1, 1 }, - { ahd_patch2_func, 419, 1, 2 }, + { ahd_patch2_func, 350, 1, 2 }, + { ahd_patch0_func, 351, 1, 1 }, + { ahd_patch1_func, 357, 1, 2 }, + { ahd_patch0_func, 358, 1, 1 }, + { ahd_patch1_func, 360, 1, 2 }, + { ahd_patch0_func, 361, 1, 1 }, + { ahd_patch10_func, 380, 1, 1 }, + { ahd_patch10_func, 383, 1, 1 }, + { ahd_patch10_func, 385, 1, 1 }, + { ahd_patch10_func, 397, 1, 1 }, + { ahd_patch1_func, 407, 1, 2 }, + { ahd_patch0_func, 408, 1, 1 }, + { ahd_patch1_func, 410, 1, 2 }, + { ahd_patch0_func, 411, 1, 1 }, + { ahd_patch1_func, 419, 1, 2 }, { ahd_patch0_func, 420, 1, 1 }, - { ahd_patch10_func, 450, 1, 1 }, - { ahd_patch1_func, 457, 1, 2 }, - { ahd_patch0_func, 458, 1, 1 }, - { ahd_patch2_func, 470, 1, 2 }, - { ahd_patch0_func, 471, 1, 1 }, - { ahd_patch11_func, 476, 6, 2 }, - { ahd_patch0_func, 482, 1, 1 }, - { ahd_patch12_func, 505, 1, 1 }, - { ahd_patch13_func, 514, 1, 1 }, - { ahd_patch14_func, 515, 1, 2 }, - { ahd_patch0_func, 516, 1, 1 }, - { ahd_patch15_func, 519, 1, 1 }, - { ahd_patch14_func, 520, 1, 1 }, - { ahd_patch16_func, 531, 1, 2 }, - { ahd_patch0_func, 532, 1, 1 }, - { ahd_patch1_func, 551, 1, 2 }, - { ahd_patch0_func, 552, 1, 1 }, - { ahd_patch1_func, 555, 1, 2 }, - { ahd_patch0_func, 556, 1, 1 }, - { ahd_patch2_func, 561, 1, 2 }, - { ahd_patch0_func, 562, 1, 1 }, - { ahd_patch2_func, 566, 1, 2 }, - { ahd_patch0_func, 567, 1, 1 }, - { ahd_patch1_func, 568, 1, 2 }, - { ahd_patch0_func, 569, 1, 1 }, - { ahd_patch2_func, 580, 1, 2 }, - { ahd_patch0_func, 581, 1, 1 }, - { ahd_patch17_func, 585, 1, 1 }, - { ahd_patch18_func, 590, 1, 1 }, - { ahd_patch19_func, 591, 2, 1 }, - { ahd_patch18_func, 595, 1, 2 }, - { ahd_patch0_func, 596, 1, 1 }, - { ahd_patch2_func, 599, 1, 2 }, - { ahd_patch0_func, 600, 1, 1 }, - { ahd_patch2_func, 615, 1, 2 }, - { ahd_patch0_func, 616, 1, 1 }, - { ahd_patch20_func, 617, 14, 1 }, - { ahd_patch1_func, 635, 1, 2 }, - { ahd_patch0_func, 636, 1, 1 }, - { ahd_patch20_func, 637, 1, 1 }, - { ahd_patch1_func, 649, 1, 2 }, - { ahd_patch0_func, 650, 1, 1 }, - { ahd_patch1_func, 657, 1, 2 }, - { ahd_patch0_func, 658, 1, 1 }, - { ahd_patch17_func, 681, 1, 1 }, - { ahd_patch17_func, 719, 1, 1 }, - { ahd_patch1_func, 730, 1, 2 }, - { ahd_patch0_func, 731, 1, 1 }, - { ahd_patch1_func, 748, 1, 2 }, - { ahd_patch0_func, 749, 1, 1 }, - { ahd_patch1_func, 751, 1, 2 }, - { ahd_patch0_func, 752, 1, 1 }, - { ahd_patch1_func, 755, 1, 2 }, - { ahd_patch0_func, 756, 1, 1 }, - { ahd_patch21_func, 758, 1, 2 }, - { ahd_patch0_func, 759, 2, 1 }, - { ahd_patch22_func, 762, 4, 2 }, - { ahd_patch0_func, 766, 1, 1 }, - { ahd_patch22_func, 774, 11, 1 } + { ahd_patch2_func, 433, 1, 2 }, + { ahd_patch0_func, 434, 1, 1 }, + { ahd_patch11_func, 470, 1, 1 }, + { ahd_patch1_func, 478, 1, 2 }, + { ahd_patch0_func, 479, 1, 1 }, + { ahd_patch2_func, 491, 1, 2 }, + { ahd_patch0_func, 492, 1, 1 }, + { ahd_patch12_func, 495, 6, 2 }, + { ahd_patch0_func, 501, 1, 1 }, + { ahd_patch13_func, 522, 7, 1 }, + { ahd_patch14_func, 531, 1, 1 }, + { ahd_patch15_func, 540, 1, 1 }, + { ahd_patch16_func, 541, 1, 2 }, + { ahd_patch0_func, 542, 1, 1 }, + { ahd_patch17_func, 545, 1, 1 }, + { ahd_patch16_func, 546, 1, 1 }, + { ahd_patch18_func, 557, 1, 2 }, + { ahd_patch0_func, 558, 1, 1 }, + { ahd_patch1_func, 577, 1, 2 }, + { ahd_patch0_func, 578, 1, 1 }, + { ahd_patch1_func, 581, 1, 2 }, + { ahd_patch0_func, 582, 1, 1 }, + { ahd_patch2_func, 587, 1, 2 }, + { ahd_patch0_func, 588, 1, 1 }, + { ahd_patch2_func, 592, 1, 2 }, + { ahd_patch0_func, 593, 1, 1 }, + { ahd_patch1_func, 594, 1, 2 }, + { ahd_patch0_func, 595, 1, 1 }, + { ahd_patch2_func, 606, 1, 2 }, + { ahd_patch0_func, 607, 1, 1 }, + { ahd_patch19_func, 611, 1, 1 }, + { ahd_patch20_func, 616, 1, 1 }, + { ahd_patch21_func, 617, 2, 1 }, + { ahd_patch20_func, 621, 1, 2 }, + { ahd_patch0_func, 622, 1, 1 }, + { ahd_patch2_func, 625, 1, 2 }, + { ahd_patch0_func, 626, 1, 1 }, + { ahd_patch2_func, 641, 1, 2 }, + { ahd_patch0_func, 642, 1, 1 }, + { ahd_patch13_func, 643, 14, 1 }, + { ahd_patch1_func, 661, 1, 2 }, + { ahd_patch0_func, 662, 1, 1 }, + { ahd_patch13_func, 663, 1, 1 }, + { ahd_patch1_func, 675, 1, 2 }, + { ahd_patch0_func, 676, 1, 1 }, + { ahd_patch1_func, 683, 1, 2 }, + { ahd_patch0_func, 684, 1, 1 }, + { ahd_patch19_func, 707, 1, 1 }, + { ahd_patch19_func, 745, 1, 1 }, + { ahd_patch1_func, 756, 1, 2 }, + { ahd_patch0_func, 757, 1, 1 }, + { ahd_patch1_func, 774, 1, 2 }, + { ahd_patch0_func, 775, 1, 1 }, + { ahd_patch1_func, 777, 1, 2 }, + { ahd_patch0_func, 778, 1, 1 }, + { ahd_patch1_func, 781, 1, 2 }, + { ahd_patch0_func, 782, 1, 1 }, + { ahd_patch22_func, 784, 1, 2 }, + { ahd_patch0_func, 785, 2, 1 }, + { ahd_patch23_func, 788, 4, 2 }, + { ahd_patch0_func, 792, 1, 1 }, + { ahd_patch23_func, 800, 11, 1 } }; static struct cs { uint16_t begin; uint16_t end; } critical_sections[] = { - { 11, 12 }, - { 13, 14 }, - { 29, 42 }, - { 56, 59 }, - { 101, 128 }, - { 129, 157 }, - { 159, 162 }, - { 170, 178 }, - { 201, 250 }, - { 681, 697 }, - { 697, 711 }, - { 721, 725 } + { 17, 28 }, + { 29, 30 }, + { 47, 58 }, + { 61, 63 }, + { 65, 66 }, + { 72, 92 }, + { 110, 137 }, + { 138, 173 }, + { 178, 186 }, + { 211, 262 }, + { 423, 431 }, + { 441, 443 }, + { 446, 455 }, + { 707, 737 }, + { 747, 751 } }; static const int num_critical_sections = sizeof(critical_sections) diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx.h linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx.h --- linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx.h Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx.h Tue Feb 10 00:15:16 2004 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#79 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#85 $ * * $FreeBSD$ */ @@ -243,7 +243,7 @@ */ AHC_AIC7850_FE = AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA, AHC_AIC7860_FE = AHC_AIC7850_FE, - AHC_AIC7870_FE = AHC_TARGETMODE, + AHC_AIC7870_FE = AHC_TARGETMODE|AHC_AUTOPAUSE, AHC_AIC7880_FE = AHC_AIC7870_FE|AHC_ULTRA, /* * Although we have space for both the initiator and @@ -366,7 +366,8 @@ AHC_SCB_CONFIG_USED = 0x4000000, /* No SEEPROM but SCB2 had info. */ AHC_NO_BIOS_INIT = 0x8000000, /* No BIOS left over settings. */ AHC_DISABLE_PCI_PERR = 0x10000000, - AHC_HAS_TERM_LOGIC = 0x20000000 + AHC_HAS_TERM_LOGIC = 0x20000000, + AHC_SHUTDOWN_RECOVERY = 0x40000000 /* Terminate recovery thread. */ } ahc_flag; /************************* Hardware SCB Definition ***************************/ @@ -411,6 +412,7 @@ uint8_t initiator_tag; /* Initiator's transaction tag */ }; +#define MAX_CDB_LEN 16 struct hardware_scb { /*0*/ union { /* @@ -530,7 +532,7 @@ * The current state of this SCB. */ typedef enum { - SCB_FREE = 0x0000, + SCB_FLAG_NONE = 0x0000, SCB_OTHERTCL_TIMEOUT = 0x0002,/* * Another device was active * during the first timeout for @@ -560,12 +562,16 @@ * to report the error. */ SCB_TARGET_SCB = 0x2000, - SCB_SILENT = 0x4000 /* + SCB_SILENT = 0x4000,/* * Be quiet about transmission type * errors. They are expected and we * don't want to upset the user. This * flag is typically used during DV. */ + SCB_TIMEDOUT = 0x8000 /* + * SCB has timed out and is on the + * timedout list. + */ } scb_flag; struct scb { @@ -575,7 +581,8 @@ TAILQ_ENTRY(scb) tqe; } links; LIST_ENTRY(scb) pending_links; - ahc_io_ctx_t io_ctx; + LIST_ENTRY(scb) timedout_links; + aic_io_ctx_t io_ctx; struct ahc_softc *ahc_softc; scb_flag flags; #ifndef __linux__ @@ -929,6 +936,11 @@ LIST_HEAD(, scb) pending_scbs; /* + * SCBs whose timeout routine has been called. + */ + LIST_HEAD(, scb) timedout_scbs; + + /* * Counting lock for deferring the release of additional * untagged transactions from the untagged_queues. When * the lock is decremented to 0, all queues in the @@ -958,7 +970,7 @@ /* * Platform specific device information. */ - ahc_dev_softc_t dev_softc; + aic_dev_softc_t dev_softc; /* * Bus specific device information. @@ -1135,6 +1147,9 @@ }; /****************************** PCI Structures ********************************/ +#define AHC_PCI_IOADDR PCIR_BAR(0) /* I/O Address */ +#define AHC_PCI_MEMADDR PCIR_BAR(1) /* Mem I/O Address */ + typedef int (ahc_device_setup_t)(struct ahc_softc *); struct ahc_pci_identity { @@ -1167,7 +1182,7 @@ u_int tcl, u_int busyid); /***************************** PCI Front End *********************************/ -struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t); +struct ahc_pci_identity *ahc_find_pci_device(aic_dev_softc_t); int ahc_pci_config(struct ahc_softc *, struct ahc_pci_identity *); int ahc_pci_test_register_access(struct ahc_softc *); @@ -1231,7 +1246,7 @@ role_t role, uint32_t status, ahc_search_action action); int ahc_search_untagged_queues(struct ahc_softc *ahc, - ahc_io_ctx_t ctx, + aic_io_ctx_t ctx, int target, char channel, int lun, uint32_t status, ahc_search_action action); @@ -1248,6 +1263,8 @@ void ahc_restart(struct ahc_softc *ahc); void ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb); +void ahc_timeout(struct scb *scb); +void ahc_recover_commands(struct ahc_softc *ahc); /*************************** Utility Functions ********************************/ struct ahc_phase_table_entry* ahc_lookup_phase_entry(int phase); diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx.reg linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx.reg --- linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx.reg Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx.reg Tue Feb 10 00:15:16 2004 @@ -39,7 +39,7 @@ * * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $" /* * This file is processed by the aic7xxx_asm utility for use in assembling @@ -1306,7 +1306,6 @@ */ MWI_RESIDUAL { size 1 - alias TARG_IMMEDIATE_SCB } /* * SCBID of the next SCB to be started by the controller. @@ -1461,6 +1460,7 @@ */ LAST_MSG { size 1 + alias TARG_IMMEDIATE_SCB } /* diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx.seq linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx.seq --- linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx.seq Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx.seq Tue Feb 10 00:15:16 2004 @@ -40,7 +40,7 @@ * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $" PATCH_ARG_LIST = "struct ahc_softc *ahc" PREFIX = "ahc_" @@ -679,6 +679,7 @@ clr SCSIBUSL; /* Prevent bit leakage durint SELTO */ } and SXFRCTL0, ~SPIOEN; + mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT; test SSTAT1,REQINIT|BUSFREE jz .; test SSTAT1, BUSFREE jnz poll_for_work; mvi MISSED_BUSFREE call set_seqint; @@ -1097,7 +1098,7 @@ test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg; if ((ahc->flags & AHC_TARGETROLE) != 0) { test SSTAT0, TARGET jz dma_last_sg; - if ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0) { + if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0) { test DMAPARAMS, DIRECTION jz dma_mid_sg; } } diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_93cx6.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_93cx6.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_93cx6.c Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_93cx6.c Tue Feb 10 00:15:16 2004 @@ -28,9 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#17 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#19 $ */ /* @@ -64,7 +62,6 @@ * is preceded by an initial zero (leading 0, followed by 16-bits, MSB * first). The clock cycling from low to high initiates the next data * bit to be sent from the chip. - * */ #ifdef __linux__ @@ -72,6 +69,8 @@ #include "aic7xxx_inline.h" #include "aic7xxx_93cx6.h" #else +#include +__FBSDID("$FreeBSD$"); #include #include #include @@ -81,14 +80,22 @@ * Right now, we only have to read the SEEPROM. But we make it easier to * add other 93Cx6 functions. */ -static struct seeprom_cmd { +struct seeprom_cmd { uint8_t len; - uint8_t bits[9]; -} seeprom_read = {3, {1, 1, 0}}; + uint8_t bits[11]; +}; +/* Short opcodes for the c46 */ static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; + +/* Long opcodes for the C56/C66 */ +static struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; +static struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; + +/* Common opcodes */ static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}}; +static struct seeprom_cmd seeprom_read = {3, {1, 1, 0}}; /* * Wait for the SEERDY to go high; about 800 ns. @@ -222,12 +229,25 @@ ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, u_int start_addr, u_int count) { + struct seeprom_cmd *ewen, *ewds; uint16_t v; uint8_t temp; int i, k; /* Place the chip into write-enable mode */ - send_seeprom_cmd(sd, &seeprom_ewen); + if (sd->sd_chip == C46) { + ewen = &seeprom_ewen; + ewds = &seeprom_ewds; + } else if (sd->sd_chip == C56_66) { + ewen = &seeprom_long_ewen; + ewds = &seeprom_long_ewds; + } else { + printf("ahc_write_seeprom: unsupported seeprom type %d\n", + sd->sd_chip); + return (0); + } + + send_seeprom_cmd(sd, ewen); reset_seeprom(sd); /* Write all requested data out to the seeprom. */ @@ -277,7 +297,7 @@ } /* Put the chip back into write-protect mode */ - send_seeprom_cmd(sd, &seeprom_ewds); + send_seeprom_cmd(sd, ewds); reset_seeprom(sd); return (1); diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_core.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_core.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_core.c Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_core.c Tue Feb 10 01:47:06 2004 @@ -37,9 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#133 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#148 $ */ #ifdef __linux__ @@ -47,6 +45,8 @@ #include "aic7xxx_inline.h" #include "aicasm/aicasm_insformat.h" #else +#include +__FBSDID("$FreeBSD$"); #include #include #include @@ -320,7 +320,7 @@ */ modnext = ahc->qoutfifonext & ~0x3; *((uint32_t *)(&ahc->qoutfifo[modnext])) = 0xFFFFFFFFUL; - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, /*offset*/modnext, /*len*/4, BUS_DMASYNC_PREREAD); @@ -458,14 +458,14 @@ * complete. */ scb->flags &= ~SCB_SENSE; - ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); + aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); break; } - ahc_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); + aic_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR); /* Freeze the queue until the client sees the error. */ ahc_freeze_devq(ahc, scb); - ahc_freeze_scb(scb); - ahc_set_scsi_status(scb, hscb->shared_data.status.scsi_status); + aic_freeze_scb(scb); + aic_set_scsi_status(scb, hscb->shared_data.status.scsi_status); switch (hscb->shared_data.status.scsi_status) { case SCSI_STATUS_OK: printf("%s: Interrupted for staus of 0???\n", @@ -487,7 +487,7 @@ } #endif - if (ahc_perform_autosense(scb) == 0) + if (aic_perform_autosense(scb) == 0) break; targ_info = ahc_fetch_transinfo(ahc, @@ -509,12 +509,12 @@ } #endif sg->addr = ahc_get_sense_bufaddr(ahc, scb); - sg->len = ahc_get_sense_bufsize(ahc, scb); + sg->len = aic_get_sense_bufsize(ahc, scb); sg->len |= AHC_DMA_LAST_SEG; /* Fixup byte order */ - sg->addr = ahc_htole32(sg->addr); - sg->len = ahc_htole32(sg->len); + sg->addr = aic_htole32(sg->addr); + sg->len = aic_htole32(sg->len); sc->opcode = REQUEST_SENSE; sc->byte2 = 0; @@ -543,8 +543,8 @@ * errors will be reported before any data * phases occur. */ - if (ahc_get_residual(scb) - == ahc_get_transfer_length(scb)) { + if (aic_get_residual(scb) + == aic_get_transfer_length(scb)) { ahc_update_neg_request(ahc, &devinfo, tstate, targ_info, AHC_NEG_IF_NON_ASYNC); @@ -558,7 +558,7 @@ hscb->dataptr = sg->addr; hscb->datacnt = sg->len; hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID; - hscb->sgptr = ahc_htole32(hscb->sgptr); + hscb->sgptr = aic_htole32(hscb->sgptr); scb->sg_count = 1; scb->flags |= SCB_SENSE; ahc_qinfifo_requeue_tail(ahc, scb); @@ -567,7 +567,7 @@ * Ensure we have enough time to actually * retrieve the sense. */ - ahc_scb_timer_reset(scb, 5 * 1000000); + aic_scb_timer_reset(scb, 5 * 1000000); break; } default: @@ -768,7 +768,7 @@ if ((ahc_inb(ahc, SCSISIGI) & (CDI|MSGI)) != 0) break; - ahc_delay(100); + aic_delay(100); } ahc_outb(ahc, SXFRCTL1, ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET); @@ -782,7 +782,7 @@ scb_index = ahc_inb(ahc, SCB_TAG); scb = ahc_lookup_scb(ahc, scb_index); if (scb != NULL) - ahc_set_transaction_status(scb, + aic_set_transaction_status(scb, CAM_UNCOR_PARITY); ahc_reset_channel(ahc, devinfo.channel, /*init reset*/TRUE); @@ -820,16 +820,16 @@ ahc_print_path(ahc, scb); printf("%s seen Data Phase. Length = %ld. NumSGs = %d.\n", ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't", - ahc_get_transfer_length(scb), scb->sg_count); + aic_get_transfer_length(scb), scb->sg_count); if (scb->sg_count > 0) { for (i = 0; i < scb->sg_count; i++) { printf("sg[%d] - Addr 0x%x%x : Length %d\n", i, - (ahc_le32toh(scb->sg_list[i].len) >> 24 + (aic_le32toh(scb->sg_list[i].len) >> 24 & SG_HIGH_ADDR_BITS), - ahc_le32toh(scb->sg_list[i].addr), - ahc_le32toh(scb->sg_list[i].len) + aic_le32toh(scb->sg_list[i].addr), + aic_le32toh(scb->sg_list[i].len) & AHC_SG_LEN_MASK); } } @@ -839,12 +839,12 @@ */ ahc_freeze_devq(ahc, scb); if ((scb->flags & SCB_SENSE) == 0) { - ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR); + aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); } else { scb->flags &= ~SCB_SENSE; - ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); + aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); } - ahc_freeze_scb(scb); + aic_freeze_scb(scb); if ((ahc->features & AHC_ULTRA2) != 0) { /* @@ -1188,7 +1188,7 @@ */ ahc_scb_devinfo(ahc, &devinfo, scb); ahc_force_renegotiation(ahc, &devinfo); - ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT); + aic_set_transaction_status(scb, CAM_SEL_TIMEOUT); ahc_freeze_devq(ahc, scb); } ahc_outb(ahc, CLRINT, CLRSCSIINT); @@ -1270,7 +1270,7 @@ CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_INITIATOR)) { - ahc_set_transaction_status(scb, CAM_REQ_CMP); + aic_set_transaction_status(scb, CAM_REQ_CMP); } #endif ahc_compile_devinfo(&devinfo, @@ -1469,7 +1469,7 @@ * 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); @@ -1482,7 +1482,7 @@ } ahc_outb(ahc, HCNTRL, ahc->unpause); while (!ahc_is_paused(ahc)) - ahc_delay(200); + aic_delay(200); } if (stepping) { ahc_outb(ahc, SIMODE0, simode0); @@ -1530,18 +1530,18 @@ for (i = 0; i < sizeof(hscb->shared_data.cdb); i++) printf("%#02x", hscb->shared_data.cdb[i]); printf(" dataptr:%#x datacnt:%#x sgptr:%#x tag:%#x\n", - ahc_le32toh(hscb->dataptr), - ahc_le32toh(hscb->datacnt), - ahc_le32toh(hscb->sgptr), + aic_le32toh(hscb->dataptr), + aic_le32toh(hscb->datacnt), + aic_le32toh(hscb->sgptr), hscb->tag); if (scb->sg_count > 0) { for (i = 0; i < scb->sg_count; i++) { printf("sg[%d] - Addr 0x%x%x : Length %d\n", i, - (ahc_le32toh(scb->sg_list[i].len) >> 24 + (aic_le32toh(scb->sg_list[i].len) >> 24 & SG_HIGH_ADDR_BITS), - ahc_le32toh(scb->sg_list[i].addr), - ahc_le32toh(scb->sg_list[i].len)); + aic_le32toh(scb->sg_list[i].addr), + aic_le32toh(scb->sg_list[i].len)); } } } @@ -2575,7 +2575,7 @@ printf("No SCB found during protocol violation\n"); goto proto_violation_reset; } else { - ahc_set_transaction_status(scb, CAM_SEQUENCE_FAIL); + aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL); if ((seq_flags & NO_CDB_SENT) != 0) { ahc_print_path(ahc, scb); printf("No or incomplete CDB sent to device.\n"); @@ -3513,7 +3513,7 @@ ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL) & mask); scb->hscb->control &= mask; - ahc_set_transaction_tag(scb, /*enabled*/FALSE, + aic_set_transaction_tag(scb, /*enabled*/FALSE, /*type*/MSG_SIMPLE_TASK); ahc_outb(ahc, MSG_OUT, MSG_IDENTIFYFLAG); ahc_assert_atn(ahc); @@ -3570,7 +3570,7 @@ * Perhaps add datadir to some spare bits in the hscb? */ if ((ahc_inb(ahc, SEQ_FLAGS) & DPHASE) == 0 - || ahc_get_transfer_dir(scb) != CAM_DIR_IN) { + || aic_get_transfer_dir(scb) != CAM_DIR_IN) { /* * Ignore the message if we haven't * seen an appropriate data phase yet. @@ -3626,18 +3626,18 @@ * to load so we must go back one. */ sg--; - sglen = ahc_le32toh(sg->len) & AHC_SG_LEN_MASK; + sglen = aic_le32toh(sg->len) & AHC_SG_LEN_MASK; if (sg != scb->sg_list && sglen < (data_cnt & AHC_SG_LEN_MASK)) { sg--; - sglen = ahc_le32toh(sg->len); + sglen = aic_le32toh(sg->len); /* * Preserve High Address and SG_LIST bits * while setting the count to 1. */ data_cnt = 1 | (sglen & (~AHC_SG_LEN_MASK)); - data_addr = ahc_le32toh(sg->addr) + data_addr = aic_le32toh(sg->addr) + (sglen & AHC_SG_LEN_MASK) - 1; /* @@ -3693,8 +3693,8 @@ | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT + 1) << 8) | ahc_inb(ahc, SCB_RESIDUAL_DATACNT); - dataptr = ahc_le32toh(sg->addr) - + (ahc_le32toh(sg->len) & AHC_SG_LEN_MASK) + dataptr = aic_le32toh(sg->addr) + + (aic_le32toh(sg->len) & AHC_SG_LEN_MASK) - resid; if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { u_int dscommand1; @@ -3702,7 +3702,7 @@ dscommand1 = ahc_inb(ahc, DSCOMMAND1); ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0); ahc_outb(ahc, HADDR, - (ahc_le32toh(sg->len) >> 24) & SG_HIGH_ADDR_BITS); + (aic_le32toh(sg->len) >> 24) & SG_HIGH_ADDR_BITS); ahc_outb(ahc, DSCOMMAND1, dscommand1); } ahc_outb(ahc, HADDR + 3, dataptr >> 24); @@ -3883,7 +3883,7 @@ { struct ahc_softc *list_ahc; -#if AHC_PCI_CONFIG > 0 +#if AIC_PCI_CONFIG > 0 /* * Second Function PCI devices need to inherit some * settings from function 0. @@ -3891,17 +3891,17 @@ if ((ahc->chip & AHC_BUS_MASK) == AHC_PCI && (ahc->features & AHC_MULTI_FUNC) != 0) { TAILQ_FOREACH(list_ahc, &ahc_tailq, links) { - ahc_dev_softc_t list_pci; - ahc_dev_softc_t pci; + aic_dev_softc_t list_pci; + aic_dev_softc_t pci; list_pci = list_ahc->dev_softc; pci = ahc->dev_softc; - if (ahc_get_pci_slot(list_pci) == ahc_get_pci_slot(pci) - && ahc_get_pci_bus(list_pci) == ahc_get_pci_bus(pci)) { + if (aic_get_pci_slot(list_pci) == aic_get_pci_slot(pci) + && aic_get_pci_bus(list_pci) == aic_get_pci_bus(pci)) { struct ahc_softc *master; struct ahc_softc *slave; - if (ahc_get_pci_function(list_pci) == 0) { + if (aic_get_pci_function(list_pci) == 0) { master = list_ahc; slave = ahc; } else { @@ -3969,27 +3969,27 @@ { int i; + ahc_terminate_recovery_thread(ahc); switch (ahc->init_level) { default: case 5: ahc_shutdown(ahc); - TAILQ_REMOVE(&ahc_tailq, ahc, links); /* FALLTHROUGH */ case 4: - ahc_dmamap_unload(ahc, ahc->shared_data_dmat, + aic_dmamap_unload(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap); /* FALLTHROUGH */ case 3: - ahc_dmamem_free(ahc, ahc->shared_data_dmat, ahc->qoutfifo, + aic_dmamem_free(ahc, ahc->shared_data_dmat, ahc->qoutfifo, ahc->shared_data_dmamap); - ahc_dmamap_destroy(ahc, ahc->shared_data_dmat, + aic_dmamap_destroy(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap); /* FALLTHROUGH */ case 2: - ahc_dma_tag_destroy(ahc, ahc->shared_data_dmat); + aic_dma_tag_destroy(ahc, ahc->shared_data_dmat); case 1: #ifndef __linux__ - ahc_dma_tag_destroy(ahc, ahc->buffer_dmat); + aic_dma_tag_destroy(ahc, ahc->buffer_dmat); #endif break; case 0: @@ -3997,7 +3997,7 @@ } #ifndef __linux__ - ahc_dma_tag_destroy(ahc, ahc->parent_dmat); + aic_dma_tag_destroy(ahc, ahc->parent_dmat); #endif ahc_platform_free(ahc); ahc_fini_scbdata(ahc); @@ -4079,14 +4079,6 @@ * to disturb the integrity of the bus. */ ahc_pause(ahc); - if ((ahc_inb(ahc, HCNTRL) & CHIPRST) != 0) { - /* - * The chip has not been initialized since - * PCI/EISA/VLB bus reset. Don't trust - * "left over BIOS data". - */ - ahc->flags |= AHC_NO_BIOS_INIT; - } sxfrctl1_b = 0; if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) { u_int sblkctl; @@ -4112,7 +4104,7 @@ */ wait = 1000; do { - ahc_delay(1000); + aic_delay(1000); } while (--wait && !(ahc_inb(ahc, HCNTRL) & CHIPRSTACK)); if (wait == 0) { @@ -4292,7 +4284,7 @@ */ /* DMA tag for our hardware scb structures */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -4307,7 +4299,7 @@ scb_data->init_level++; /* Allocation for our hscbs */ - if (ahc_dmamem_alloc(ahc, scb_data->hscb_dmat, + if (aic_dmamem_alloc(ahc, scb_data->hscb_dmat, (void **)&scb_data->hscbs, BUS_DMA_NOWAIT, &scb_data->hscb_dmamap) != 0) { goto error_exit; @@ -4316,7 +4308,7 @@ scb_data->init_level++; /* And permanently map them */ - ahc_dmamap_load(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap, + aic_dmamap_load(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap, scb_data->hscbs, AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb), ahc_dmamap_cb, &scb_data->hscb_busaddr, /*flags*/0); @@ -4324,7 +4316,7 @@ scb_data->init_level++; /* DMA tag for our sense buffers */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -4339,7 +4331,7 @@ scb_data->init_level++; /* Allocate them */ - if (ahc_dmamem_alloc(ahc, scb_data->sense_dmat, + if (aic_dmamem_alloc(ahc, scb_data->sense_dmat, (void **)&scb_data->sense, BUS_DMA_NOWAIT, &scb_data->sense_dmamap) != 0) { goto error_exit; @@ -4348,7 +4340,7 @@ scb_data->init_level++; /* And permanently map them */ - ahc_dmamap_load(ahc, scb_data->sense_dmat, scb_data->sense_dmamap, + aic_dmamap_load(ahc, scb_data->sense_dmat, scb_data->sense_dmamap, scb_data->sense, AHC_SCB_MAX_ALLOC * sizeof(struct scsi_sense_data), ahc_dmamap_cb, &scb_data->sense_busaddr, /*flags*/0); @@ -4356,7 +4348,7 @@ scb_data->init_level++; /* DMA tag for our S/G structures. We allocate in page sized chunks */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/8, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/8, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -4413,35 +4405,35 @@ while ((sg_map = SLIST_FIRST(&scb_data->sg_maps))!= NULL) { SLIST_REMOVE_HEAD(&scb_data->sg_maps, links); - ahc_dmamap_unload(ahc, scb_data->sg_dmat, + aic_dmamap_unload(ahc, scb_data->sg_dmat, sg_map->sg_dmamap); - ahc_dmamem_free(ahc, scb_data->sg_dmat, + aic_dmamem_free(ahc, scb_data->sg_dmat, sg_map->sg_vaddr, sg_map->sg_dmamap); free(sg_map, M_DEVBUF); } - ahc_dma_tag_destroy(ahc, scb_data->sg_dmat); + aic_dma_tag_destroy(ahc, scb_data->sg_dmat); } case 6: - ahc_dmamap_unload(ahc, scb_data->sense_dmat, + aic_dmamap_unload(ahc, scb_data->sense_dmat, scb_data->sense_dmamap); case 5: - ahc_dmamem_free(ahc, scb_data->sense_dmat, scb_data->sense, + aic_dmamem_free(ahc, scb_data->sense_dmat, scb_data->sense, scb_data->sense_dmamap); - ahc_dmamap_destroy(ahc, scb_data->sense_dmat, + aic_dmamap_destroy(ahc, scb_data->sense_dmat, scb_data->sense_dmamap); case 4: - ahc_dma_tag_destroy(ahc, scb_data->sense_dmat); + aic_dma_tag_destroy(ahc, scb_data->sense_dmat); case 3: - ahc_dmamap_unload(ahc, scb_data->hscb_dmat, + aic_dmamap_unload(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap); case 2: - ahc_dmamem_free(ahc, scb_data->hscb_dmat, scb_data->hscbs, + aic_dmamem_free(ahc, scb_data->hscb_dmat, scb_data->hscbs, scb_data->hscb_dmamap); - ahc_dmamap_destroy(ahc, scb_data->hscb_dmat, + aic_dmamap_destroy(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap); case 1: - ahc_dma_tag_destroy(ahc, scb_data->hscb_dmat); + aic_dma_tag_destroy(ahc, scb_data->hscb_dmat); break; case 0: break; @@ -4474,7 +4466,7 @@ return; /* Allocate S/G space for the next batch of SCBS */ - if (ahc_dmamem_alloc(ahc, scb_data->sg_dmat, + if (aic_dmamem_alloc(ahc, scb_data->sg_dmat, (void **)&sg_map->sg_vaddr, BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) { free(sg_map, M_DEVBUF); @@ -4483,7 +4475,7 @@ SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links); - ahc_dmamap_load(ahc, scb_data->sg_dmat, sg_map->sg_dmamap, + aic_dmamap_load(ahc, scb_data->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr, PAGE_SIZE, ahc_dmamap_cb, &sg_map->sg_physaddr, /*flags*/0); @@ -4510,9 +4502,9 @@ */ next_scb->sg_list_phys = physaddr + sizeof(struct ahc_dma_seg); next_scb->ahc_softc = ahc; - next_scb->flags = SCB_FREE; + next_scb->flags = SCB_FLAG_NONE; #ifndef __linux__ - error = ahc_dmamap_create(ahc, ahc->buffer_dmat, /*flags*/0, + error = aic_dmamap_create(ahc, ahc->buffer_dmat, /*flags*/0, &next_scb->dmamap); if (error != 0) break; @@ -4747,7 +4739,7 @@ for (wait = 5000; (ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait; wait--) - ahc_delay(100); + aic_delay(100); } ahc_restart(ahc); return (0); @@ -4760,6 +4752,7 @@ ahc_init(struct ahc_softc *ahc) { int max_targ; + int error; u_int i; u_int scsi_conf; u_int ultraenb; @@ -4817,7 +4810,7 @@ #ifndef __linux__ /* DMA tag for mapping buffers into device visible space. */ - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/ahc->flags & AHC_39BIT_ADDRESSING ? (bus_addr_t)0x7FFFFFFFFFULL @@ -4848,7 +4841,7 @@ if ((ahc->features & AHC_TARGETMODE) != 0) driver_data_size += AHC_TMODE_CMDS * sizeof(struct target_cmd) + /*DMA WideOdd Bug Buffer*/1; - if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, + if (aic_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -4863,7 +4856,7 @@ ahc->init_level++; /* Allocation of driver data */ - if (ahc_dmamem_alloc(ahc, ahc->shared_data_dmat, + if (aic_dmamem_alloc(ahc, ahc->shared_data_dmat, (void **)&ahc->qoutfifo, BUS_DMA_NOWAIT, &ahc->shared_data_dmamap) != 0) { return (ENOMEM); @@ -4872,7 +4865,7 @@ ahc->init_level++; /* And permanently map it in */ - ahc_dmamap_load(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, + aic_dmamap_load(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, ahc->qoutfifo, driver_data_size, ahc_dmamap_cb, &ahc->shared_data_busaddr, /*flags*/0); @@ -4915,6 +4908,13 @@ } } + /* + * Fire up a recovery thread for this controller. + */ + error = ahc_spawn_recovery_thread(ahc); + if (error != 0) + return (error); + if (ahc->scb_data->maxhscbs < AHC_SCB_MAX_ALLOC) { ahc->flags |= AHC_PAGESCBS; } else { @@ -5112,8 +5112,14 @@ ahc->flags |= AHC_ALL_INTERRUPTS; paused = FALSE; do { - if (paused) + if (paused) { ahc_unpause(ahc); + /* + * Give the sequencer some time to service + * any active selections. + */ + aic_delay(200); + } ahc_intr(ahc); ahc_pause(ahc); paused = TRUE; @@ -5399,12 +5405,12 @@ cam_status ostat; cam_status cstat; - ostat = ahc_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scb, status); - cstat = ahc_get_transaction_status(scb); + aic_set_transaction_status(scb, status); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahc_freeze_scb(scb); + aic_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) printf("Inactive SCB in qinfifo\n"); ahc_done(ahc, scb); @@ -5511,15 +5517,15 @@ cam_status ostat; cam_status cstat; - ostat = ahc_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scb, + aic_set_transaction_status(scb, status); - cstat = ahc_get_transaction_status(scb); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahc_freeze_scb(scb); + aic_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in Waiting List\n"); + printf("Inactive SCB in Wait List\n"); ahc_done(ahc, scb); /* FALLTHROUGH */ } @@ -5539,7 +5545,7 @@ } ahc_outb(ahc, SCBPTR, curscbptr); - found += ahc_search_untagged_queues(ahc, /*ahc_io_ctx_t*/NULL, target, + found += ahc_search_untagged_queues(ahc, /*aic_io_ctx_t*/NULL, target, channel, lun, status, action); if (action == SEARCH_COMPLETE) @@ -5548,7 +5554,7 @@ } int -ahc_search_untagged_queues(struct ahc_softc *ahc, ahc_io_ctx_t ctx, +ahc_search_untagged_queues(struct ahc_softc *ahc, aic_io_ctx_t ctx, int target, char channel, int lun, uint32_t status, ahc_search_action action) { @@ -5619,14 +5625,12 @@ cam_status ostat; cam_status cstat; - ostat = ahc_get_transaction_status(scb); + ostat = aic_get_transaction_status(scb); if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scb, status); - cstat = ahc_get_transaction_status(scb); + aic_set_transaction_status(scb, status); + cstat = aic_get_transaction_status(scb); if (cstat != CAM_REQ_CMP) - ahc_freeze_scb(scb); - if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in untaggedQ\n"); + aic_freeze_scb(scb); ahc_done(ahc, scb); break; } @@ -5923,11 +5927,11 @@ if (ahc_match_scb(ahc, scbp, target, channel, lun, tag, role)) { cam_status ostat; - ostat = ahc_get_transaction_status(scbp); + ostat = aic_get_transaction_status(scbp); if (ostat == CAM_REQ_INPROG) - ahc_set_transaction_status(scbp, status); - if (ahc_get_transaction_status(scbp) != CAM_REQ_CMP) - ahc_freeze_scb(scbp); + aic_set_transaction_status(scbp, status); + if (aic_get_transaction_status(scbp) != CAM_REQ_CMP) + aic_freeze_scb(scbp); if ((scbp->flags & SCB_ACTIVE) == 0) printf("Inactive SCB on pending list\n"); ahc_done(ahc, scbp); @@ -5949,7 +5953,7 @@ scsiseq = ahc_inb(ahc, SCSISEQ); ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO); ahc_flush_device_writes(ahc); - ahc_delay(AHC_BUSRESET_DELAY); + aic_delay(AHC_BUSRESET_DELAY); /* Turn off the bus reset */ ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO); @@ -6156,7 +6160,7 @@ */ hscb = scb->hscb; - sgptr = ahc_le32toh(hscb->sgptr); + sgptr = aic_le32toh(hscb->sgptr); if ((sgptr & SG_RESID_VALID) == 0) /* Case 1 */ return; @@ -6167,10 +6171,10 @@ return; spkt = &hscb->shared_data.status; - resid_sgptr = ahc_le32toh(spkt->residual_sg_ptr); + resid_sgptr = aic_le32toh(spkt->residual_sg_ptr); if ((sgptr & SG_FULL_RESID) != 0) { /* Case 3 */ - resid = ahc_get_transfer_length(scb); + resid = aic_get_transfer_length(scb); } else if ((resid_sgptr & SG_LIST_NULL) != 0) { /* Case 4 */ return; @@ -6183,7 +6187,7 @@ * Remainder of the SG where the transfer * stopped. */ - resid = ahc_le32toh(spkt->residual_datacnt) & AHC_SG_LEN_MASK; + resid = aic_le32toh(spkt->residual_datacnt) & AHC_SG_LEN_MASK; sg = ahc_sg_bus_to_virt(scb, resid_sgptr & SG_PTR_MASK); /* The residual sg_ptr always points to the next sg */ @@ -6194,15 +6198,15 @@ * SG segments that are after the SG where * the transfer stopped. */ - while ((ahc_le32toh(sg->len) & AHC_DMA_LAST_SEG) == 0) { + while ((aic_le32toh(sg->len) & AHC_DMA_LAST_SEG) == 0) { sg++; - resid += ahc_le32toh(sg->len) & AHC_SG_LEN_MASK; + resid += aic_le32toh(sg->len) & AHC_SG_LEN_MASK; } } if ((scb->flags & SCB_SENSE) == 0) - ahc_set_residual(scb, resid); + aic_set_residual(scb, resid); else - ahc_set_sense_residual(scb, resid); + aic_set_sense_residual(scb, resid); #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MISC) != 0) { @@ -6482,7 +6486,7 @@ /* * The firmware is always compiled into a little endian format. */ - instr.integer = ahc_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); + instr.integer = aic_le32toh(*(uint32_t*)&seqprog[instrptr * 4]); fmt1_ins = &instr.format1; fmt3_ins = NULL; @@ -6587,7 +6591,7 @@ } } /* The sequencer is a little endian cpu */ - instr.integer = ahc_htole32(instr.integer); + instr.integer = aic_htole32(instr.integer); ahc_outsb(ahc, SEQRAM, instr.bytes, 4); break; default: @@ -6827,6 +6831,324 @@ ahc_unpause(ahc); } +/*************************** Timeout Handling *********************************/ +void +ahc_timeout(struct scb *scb) +{ + struct ahc_softc *ahc; + + ahc = scb->ahc_softc; + if ((scb->flags & SCB_ACTIVE) != 0) { + if ((scb->flags & SCB_TIMEDOUT) == 0) { + LIST_INSERT_HEAD(&ahc->timedout_scbs, scb, + timedout_links); + scb->flags |= SCB_TIMEDOUT; + } + ahc_wakeup_recovery_thread(ahc); + } +} + +/* + * ahc_recover_commands determines if any of the commands that have currently + * timedout are the root cause for this timeout. Innocent commands are given + * a new timeout while we wait for the command executing on the bus to timeout. + * This routine is invoked from a thread context so we are allowed to sleep. + * Our lock is not held on entry. + */ +void +ahc_recover_commands(struct ahc_softc *ahc) +{ + struct scb *scb; + long s; + int found; + int restart_needed; + u_int last_phase; + + ahc_lock(ahc, &s); + + /* + * Pause the controller and manually flush any + * commands that have just completed but that our + * interrupt handler has yet to see. + */ + ahc_pause_and_flushwork(ahc); + + if (LIST_EMPTY(&ahc->timedout_scbs) != 0) { + /* + * The timedout commands have already + * completed. This typically means + * that either the timeout value was on + * the hairy edge of what the device + * requires or - more likely - interrupts + * are not happening. + */ + printf("%s: Timedout SCBs already complete. " + "Interrupts may not be functioning.\n", ahc_name(ahc)); + ahc_unpause(ahc); + ahc_unlock(ahc, &s); + return; + } + + restart_needed = 0; + printf("%s: Recovery Initiated\n", ahc_name(ahc)); + ahc_dump_card_state(ahc); + + last_phase = ahc_inb(ahc, LASTPHASE); + while ((scb = LIST_FIRST(&ahc->timedout_scbs)) != NULL) { + u_int active_scb_index; + u_int saved_scbptr; + int target; + int lun; + int i; + char channel; + + target = SCB_GET_TARGET(ahc, scb); + channel = SCB_GET_CHANNEL(ahc, scb); + lun = SCB_GET_LUN(scb); + + ahc_print_path(ahc, scb); + printf("SCB 0x%x - timed out\n", scb->hscb->tag); + if (scb->sg_count > 0) { + for (i = 0; i < scb->sg_count; i++) { + printf("sg[%d] - Addr 0x%x : Length %d\n", + i, + scb->sg_list[i].addr, + scb->sg_list[i].len & AHC_SG_LEN_MASK); + } + } + if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) { + /* + * Been down this road before. + * Do a full bus reset. + */ + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); +bus_reset: + found = ahc_reset_channel(ahc, channel, + /*Initiate Reset*/TRUE); + printf("%s: Issued Channel %c Bus Reset. " + "%d SCBs aborted\n", ahc_name(ahc), channel, + found); + continue; + } + + /* + * Remove the command from the timedout list in + * preparation for requeing it. + */ + LIST_REMOVE(scb, timedout_links); + scb->flags &= ~SCB_TIMEDOUT; + + /* + * If we are a target, transition to bus free and report + * the timeout. + * + * The target/initiator that is holding up the bus may not + * be the same as the one that triggered this timeout + * (different commands have different timeout lengths). + * If the bus is idle and we are actiing as the initiator + * for this request, queue a BDR message to the timed out + * target. Otherwise, if the timed out transaction is + * active: + * Initiator transaction: + * Stuff the message buffer with a BDR message and assert + * ATN in the hopes that the target will let go of the bus + * and go to the mesgout phase. If this fails, we'll + * get another timeout 2 seconds later which will attempt + * a bus reset. + * + * Target transaction: + * Transition to BUS FREE and report the error. + * It's good to be the target! + */ + saved_scbptr = ahc_inb(ahc, SCBPTR); + active_scb_index = ahc_inb(ahc, SCB_TAG); + + if ((ahc_inb(ahc, SEQ_FLAGS) & NOT_IDENTIFIED) == 0 + && (active_scb_index < ahc->scb_data->numscbs)) { + struct scb *active_scb; + + /* + * If the active SCB is not us, assume that + * the active SCB has a longer timeout than + * the timedout SCB, and wait for the active + * SCB to timeout. + */ + active_scb = ahc_lookup_scb(ahc, active_scb_index); + if (active_scb != scb) { + u_int newtimeout; + + ahc_print_path(ahc, scb); + printf("Other SCB Timeout%s", + (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0 + ? " again\n" : "\n"); + scb->flags |= SCB_OTHERTCL_TIMEOUT; + newtimeout = + MAX(aic_get_timeout(active_scb), + aic_get_timeout(scb)); + aic_scb_timer_reset(scb, newtimeout); + continue; + } + + /* It's us */ + if ((scb->flags & SCB_TARGET_SCB) != 0) { + + /* + * Send back any queued up transactions + * and properly record the error condition. + */ + ahc_abort_scbs(ahc, SCB_GET_TARGET(ahc, scb), + SCB_GET_CHANNEL(ahc, scb), + SCB_GET_LUN(scb), + scb->hscb->tag, + ROLE_TARGET, + CAM_CMD_TIMEOUT); + + /* Will clear us from the bus */ + restart_needed = 1; + break; + } + + ahc_set_recoveryscb(ahc, active_scb); + ahc_outb(ahc, MSG_OUT, HOST_MSG); + ahc_outb(ahc, SCSISIGO, last_phase|ATNO); + ahc_print_path(ahc, active_scb); + printf("BDR message in message buffer\n"); + active_scb->flags |= SCB_DEVICE_RESET; + aic_scb_timer_reset(scb, 2 * 1000000); + } else if (last_phase != P_BUSFREE + && (ahc_inb(ahc, SSTAT1) & REQINIT) == 0) { + /* + * SCB is not identified, there + * is no pending REQ, and the sequencer + * has not seen a busfree. Looks like + * a stuck connection waiting to + * go busfree. Reset the bus. + */ + printf("%s: Connection stuck awaiting busfree or " + "Identify Msg.\n", ahc_name(ahc)); + goto bus_reset; + } else { + int disconnected; + + if (last_phase != P_BUSFREE + && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) { + /* Hung target selection. Goto busfree */ + printf("%s: Hung target selection\n", + ahc_name(ahc)); + restart_needed = 1; + break; + } + + /* XXX Shouldn't panic. Just punt instead? */ + if ((scb->flags & SCB_TARGET_SCB) != 0) + panic("Timed-out target SCB but bus idle"); + + if (ahc_search_qinfifo(ahc, target, channel, lun, + scb->hscb->tag, ROLE_INITIATOR, + /*status*/0, SEARCH_COUNT) > 0) { + disconnected = FALSE; + } else { + disconnected = TRUE; + } + + if (disconnected) { + + ahc_set_recoveryscb(ahc, scb); + /* + * Actually re-queue this SCB in an attempt + * to select the device before it reconnects. + * In either case (selection or reselection), + * we will now issue a target reset to the + * timed-out device. + * + * Set the MK_MESSAGE control bit indicating + * that we desire to send a message. We + * also set the disconnected flag since + * in the paging case there is no guarantee + * that our SCB control byte matches the + * version on the card. We don't want the + * sequencer to abort the command thinking + * an unsolicited reselection occurred. + */ + scb->hscb->control |= MK_MESSAGE|DISCONNECTED; + scb->flags |= SCB_DEVICE_RESET; + + /* + * Remove any cached copy of this SCB in the + * disconnected list in preparation for the + * queuing of our abort SCB. We use the + * same element in the SCB, SCB_NEXT, for + * both the qinfifo and the disconnected list. + */ + ahc_search_disc_list(ahc, target, channel, + lun, scb->hscb->tag, + /*stop_on_first*/TRUE, + /*remove*/TRUE, + /*save_state*/FALSE); + + /* + * In the non-paging case, the sequencer will + * never re-reference the in-core SCB. + * To make sure we are notified during + * reslection, set the MK_MESSAGE flag in + * the card's copy of the SCB. + */ + if ((ahc->flags & AHC_PAGESCBS) == 0) { + ahc_outb(ahc, SCBPTR, scb->hscb->tag); + ahc_outb(ahc, SCB_CONTROL, + ahc_inb(ahc, SCB_CONTROL) + | MK_MESSAGE); + } + + /* + * Clear out any entries in the QINFIFO first + * so we are the next SCB for this target + * to run. + */ + ahc_search_qinfifo(ahc, + SCB_GET_TARGET(ahc, scb), + channel, SCB_GET_LUN(scb), + SCB_LIST_NULL, + ROLE_INITIATOR, + CAM_REQUEUE_REQ, + SEARCH_COMPLETE); + ahc_print_path(ahc, scb); + printf("Queuing a BDR SCB\n"); + ahc_qinfifo_requeue_tail(ahc, scb); + ahc_outb(ahc, SCBPTR, saved_scbptr); + aic_scb_timer_reset(scb, 2 * 1000000); + } else { + /* Go "immediatly" to the bus reset */ + /* This shouldn't happen */ + ahc_set_recoveryscb(ahc, scb); + ahc_print_path(ahc, scb); + printf("SCB %d: Immediate reset. " + "Flags = 0x%x\n", scb->hscb->tag, + scb->flags); + goto bus_reset; + } + } + break; + } + + /* + * Any remaining SCBs were not the "culprit", so remove + * them from the timeout list. The timer for these commands + * will be reset once the recovery SCB completes. + */ + while ((scb = LIST_FIRST(&ahc->timedout_scbs)) != NULL) { + + LIST_REMOVE(scb, timedout_links); + scb->flags &= ~SCB_TIMEDOUT; + } + + if (restart_needed) + ahc_restart(ahc); + else + ahc_unpause(ahc); + ahc_unlock(ahc, &s); +} + /************************* Target Mode ****************************************/ #ifdef AHC_TARGET_MODE cam_status @@ -7305,7 +7627,7 @@ break; cmd->cmd_valid = 0; - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, ahc_targetcmd_offset(ahc, ahc->tqinfifonext), sizeof(struct target_cmd), @@ -7442,7 +7764,7 @@ initiator, target, lun, ahc->pending_device); #endif ahc->pending_device = lstate; - ahc_freeze_ccb((union ccb *)atio); + aic_freeze_ccb((union ccb *)atio); atio->ccb_h.flags |= CAM_DIS_DISCONNECT; } xpt_done((union ccb*)atio); diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_inline.h linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_inline.h --- linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_inline.h Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_inline.h Tue Feb 10 00:15:16 2004 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#43 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#47 $ * * $FreeBSD$ */ @@ -196,7 +196,7 @@ static __inline void ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op) { - ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat, + aic_dmamap_sync(ahc, ahc->scb_data->hscb_dmat, ahc->scb_data->hscb_dmamap, /*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb), /*len*/sizeof(*scb->hscb), op); @@ -208,7 +208,7 @@ if (scb->sg_count == 0) return; - ahc_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap, + aic_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap, /*offset*/(scb->sg_list - scb->sg_map->sg_vaddr) * sizeof(struct ahc_dma_seg), /*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op); @@ -272,7 +272,7 @@ { uint32_t sgptr; - sgptr = ahc_le32toh(scb->hscb->sgptr); + sgptr = aic_le32toh(scb->hscb->sgptr); if ((sgptr & SG_RESID_VALID) != 0) ahc_calc_residual(ahc, scb); } @@ -383,13 +383,13 @@ hscb = scb->hscb; /* Clean up for the next user */ ahc->scb_data->scbindex[hscb->tag] = NULL; - scb->flags = SCB_FREE; + scb->flags = SCB_FLAG_NONE; hscb->control = 0; SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle); /* Notify the OSM that a resource is now available. */ - ahc_platform_scb_free(ahc, scb); + aic_platform_scb_free(ahc, scb); } static __inline struct scb * @@ -427,7 +427,7 @@ memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); if ((scb->flags & SCB_CDB32_PTR) != 0) { q_hscb->shared_data.cdb_ptr = - ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag) + aic_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag) + offsetof(struct hardware_scb, cdb32)); } q_hscb->tag = saved_tag; @@ -458,7 +458,7 @@ * Setup data "oddness". */ scb->hscb->lun &= LID; - if (ahc_get_transfer_length(scb) & 0x1) + if (aic_get_transfer_length(scb) & 0x1) scb->hscb->lun |= SCB_XFERLEN_ODD; /* @@ -512,7 +512,7 @@ static __inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op) { - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, /*offset*/0, /*len*/256, op); } @@ -521,7 +521,7 @@ { #ifdef AHC_TARGET_MODE if ((ahc->flags & AHC_TARGETROLE) != 0) { - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, ahc_targetcmd_offset(ahc, 0), sizeof(struct target_cmd) * AHC_TMODE_CMDS, @@ -542,7 +542,7 @@ u_int retval; retval = 0; - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, /*offset*/ahc->qoutfifonext, /*len*/1, BUS_DMASYNC_POSTREAD); if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) @@ -550,7 +550,7 @@ #ifdef AHC_TARGET_MODE if ((ahc->flags & AHC_TARGETROLE) != 0 && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) { - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + aic_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, ahc_targetcmd_offset(ahc, ahc->tqinfifofnext), /*len*/sizeof(struct target_cmd), @@ -593,7 +593,7 @@ } if ((intstat & INT_PEND) == 0) { -#if AHC_PCI_CONFIG > 0 +#if AIC_PCI_CONFIG > 0 if (ahc->unsolicited_ints > 500) { ahc->unsolicited_ints = 0; if ((ahc->chip & AHC_PCI) != 0 diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_osm.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_osm.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_osm.c Fri Oct 31 10:44:20 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_osm.c Tue Feb 10 01:47:06 2004 @@ -1,7 +1,7 @@ /* * Adaptec AIC7xxx device driver for Linux. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#234 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#264 $ * * Copyright (c) 1994 John Aycock * The University of Calgary Department of Computer Science. @@ -129,9 +129,7 @@ */ #include "aiclib.c" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) #include /* __setup */ -#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) @@ -139,7 +137,22 @@ #endif #include /* For fetching system memory size */ -#include /* For block_size() */ + +/************************* Magic SysReq Support *******************************/ +static struct aic_sysrq_key_op ahc_sysrq_op = +{ + aic_sysrq_handler, + "aic7xxxstatedump", + "Dump aic7xxx controller information to Console" +}; + +static int ahc_sysrq_key; + +/***************************** Global Data ************************************/ +/* + * Driver Initialization Status. Used by ahc_linux_exit(). + */ +int ahc_init_status; /* * Lock protecting manipulation of the ahc softc list. @@ -151,14 +164,6 @@ u_int ahc_linux_nseg; #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -struct proc_dir_entry proc_scsi_aic7xxx = { - PROC_SCSI_AIC7XXX, 7, "aic7xxx", - S_IFDIR | S_IRUGO | S_IXUGO, 2, - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; -#endif - /* * Set this to the delay in seconds after SCSI bus reset. * Note, we honor this only for the initial bus reset. @@ -482,35 +487,34 @@ #endif static void ahc_linux_handle_scsi_status(struct ahc_softc *, - struct ahc_linux_device *, + struct aic_linux_device *, struct scb *); static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, Scsi_Cmnd *cmd); static void ahc_linux_filter_inquiry(struct ahc_softc*, struct ahc_devinfo*); static void ahc_linux_sem_timeout(u_long arg); -static void ahc_linux_freeze_simq(struct ahc_softc *ahc); -static void ahc_linux_release_simq(u_long arg); static void ahc_linux_dev_timed_unfreeze(u_long arg); +static int __init ahc_linux_init(void); +static void ahc_linux_exit(void); static int ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag); static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); static void ahc_linux_size_nseg(void); static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc); static void ahc_linux_start_dv(struct ahc_softc *ahc); -static void ahc_linux_dv_timeout(struct scsi_cmnd *cmd); static int ahc_linux_dv_thread(void *data); static void ahc_linux_kill_dv_thread(struct ahc_softc *ahc); static void ahc_linux_dv_target(struct ahc_softc *ahc, u_int target); static void ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ); + struct aic_linux_target *targ); static void ahc_linux_dv_fill_cmd(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo); static void ahc_linux_dv_inq(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ, + struct aic_linux_target *targ, u_int request_length); static void ahc_linux_dv_tur(struct ahc_softc *ahc, struct scsi_cmnd *cmd, @@ -518,58 +522,48 @@ static void ahc_linux_dv_rebd(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ); + struct aic_linux_target *targ); static void ahc_linux_dv_web(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ); + struct aic_linux_target *targ); static void ahc_linux_dv_reb(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ); + struct aic_linux_target *targ); static void ahc_linux_dv_su(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ); + struct aic_linux_target *targ); static int ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo); -static void ahc_linux_dv_complete(Scsi_Cmnd *cmd); -static void ahc_linux_generate_dv_pattern(struct ahc_linux_target *targ); +static void ahc_linux_generate_dv_pattern(struct aic_linux_target *targ); static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo); static u_int ahc_linux_user_dv_setting(struct ahc_softc *ahc); -static void ahc_linux_device_queue_depth(struct ahc_softc *ahc, - struct ahc_linux_device *dev); -static struct ahc_linux_target* ahc_linux_alloc_target(struct ahc_softc*, +static void aic_linux_device_queue_depth(struct ahc_softc *ahc, + struct aic_linux_device *dev); +static struct aic_linux_target* ahc_linux_alloc_target(struct ahc_softc*, u_int, u_int); static void ahc_linux_free_target(struct ahc_softc*, - struct ahc_linux_target*); -static struct ahc_linux_device* ahc_linux_alloc_device(struct ahc_softc*, - struct ahc_linux_target*, + struct aic_linux_target*); +static struct aic_linux_device* ahc_linux_alloc_device(struct ahc_softc*, + struct aic_linux_target*, u_int); static void ahc_linux_free_device(struct ahc_softc*, - struct ahc_linux_device*); -static void ahc_linux_run_device_queue(struct ahc_softc*, - struct ahc_linux_device*); + struct aic_linux_device*); static void ahc_linux_setup_tag_info_global(char *p); static aic_option_callback_t ahc_linux_setup_tag_info; static aic_option_callback_t ahc_linux_setup_dv; static int aic7xxx_setup(char *s); static int ahc_linux_next_unit(void); -static void ahc_runq_tasklet(unsigned long data); -static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc); +static struct aic_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc); /********************************* Inlines ************************************/ -static __inline void ahc_schedule_runq(struct ahc_softc *ahc); -static __inline struct ahc_linux_device* +static __inline struct aic_linux_device* ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, u_int lun, int alloc); static __inline void ahc_schedule_completeq(struct ahc_softc *ahc); -static __inline void ahc_linux_check_device_queue(struct ahc_softc *ahc, - struct ahc_linux_device *dev); -static __inline struct ahc_linux_device * - ahc_linux_next_device_to_run(struct ahc_softc *ahc); -static __inline void ahc_linux_run_device_queues(struct ahc_softc *ahc); static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, @@ -579,35 +573,19 @@ static __inline void ahc_schedule_completeq(struct ahc_softc *ahc) { - if ((ahc->platform_data->flags & AHC_RUN_CMPLT_Q_TIMER) == 0) { - ahc->platform_data->flags |= AHC_RUN_CMPLT_Q_TIMER; + if ((ahc->platform_data->flags & AIC_RUN_CMPLT_Q_TIMER) == 0) { + ahc->platform_data->flags |= AIC_RUN_CMPLT_Q_TIMER; ahc->platform_data->completeq_timer.expires = jiffies; add_timer(&ahc->platform_data->completeq_timer); } } -/* - * Must be called with our lock held. - */ -static __inline void -ahc_schedule_runq(struct ahc_softc *ahc) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_schedule(&ahc->platform_data->runq_tasklet); -#else - /* - * Tasklets are not available, so run inline. - */ - ahc_runq_tasklet((unsigned long)ahc); -#endif -} - -static __inline struct ahc_linux_device* +static __inline struct aic_linux_device* ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, u_int lun, int alloc) { - struct ahc_linux_target *targ; - struct ahc_linux_device *dev; + struct aic_linux_target *targ; + struct aic_linux_device *dev; u_int target_offset; target_offset = target; @@ -629,15 +607,13 @@ } #define AHC_LINUX_MAX_RETURNED_ERRORS 4 -static struct ahc_cmd * +static struct aic_cmd * ahc_linux_run_complete_queue(struct ahc_softc *ahc) { - struct ahc_cmd *acmd; - u_long done_flags; + struct aic_cmd *acmd; int with_errors; with_errors = 0; - ahc_done_lock(ahc, &done_flags); while ((acmd = TAILQ_FIRST(&ahc->platform_data->completeq)) != NULL) { Scsi_Cmnd *cmd; @@ -657,56 +633,11 @@ acmd, acmd_links.tqe); cmd = &acmd_scsi_cmd(acmd); cmd->host_scribble = NULL; - if (ahc_cmd_get_transaction_status(cmd) != DID_OK - || (cmd->result & 0xFF) != SCSI_STATUS_OK) - with_errors++; - cmd->scsi_done(cmd); + with_errors++; } - ahc_done_unlock(ahc, &done_flags); return (acmd); } - -static __inline void -ahc_linux_check_device_queue(struct ahc_softc *ahc, - struct ahc_linux_device *dev) -{ - if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) != 0 - && dev->active == 0) { - dev->flags &= ~AHC_DEV_FREEZE_TIL_EMPTY; - dev->qfrozen--; - } - - if (TAILQ_FIRST(&dev->busyq) == NULL - || dev->openings == 0 || dev->qfrozen != 0) - return; - - ahc_linux_run_device_queue(ahc, dev); -} - -static __inline struct ahc_linux_device * -ahc_linux_next_device_to_run(struct ahc_softc *ahc) -{ - - if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0 - || (ahc->platform_data->qfrozen != 0 - && AHC_DV_SIMQ_FROZEN(ahc) == 0)) - return (NULL); - return (TAILQ_FIRST(&ahc->platform_data->device_runq)); -} - -static __inline void -ahc_linux_run_device_queues(struct ahc_softc *ahc) -{ - struct ahc_linux_device *dev; - - while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) { - TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links); - dev->flags &= ~AHC_DEV_ON_RUN_LIST; - ahc_linux_check_device_queue(ahc, dev); - } -} - static __inline void ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb) { @@ -718,10 +649,10 @@ struct scatterlist *sg; sg = (struct scatterlist *)cmd->request_buffer; - pci_unmap_sg(ahc->dev_softc, sg, cmd->use_sg, + aic_unmap_sg(ahc, sg, cmd->use_sg, scsi_to_pci_dma_dir(cmd->sc_data_direction)); } else if (cmd->request_bufflen != 0) { - pci_unmap_single(ahc->dev_softc, + aic_unmap_single(ahc, scb->platform_data->buf_busaddr, cmd->request_bufflen, scsi_to_pci_dma_dir(cmd->sc_data_direction)); @@ -739,14 +670,14 @@ "Increase AHC_NSEG\n"); consumed = 1; - sg->addr = ahc_htole32(addr & 0xFFFFFFFF); + sg->addr = aic_htole32(addr & 0xFFFFFFFF); scb->platform_data->xfer_len += len; if (sizeof(bus_addr_t) > 4 && (ahc->flags & AHC_39BIT_ADDRESSING) != 0) len |= (addr >> 8) & AHC_SG_HIGH_ADDR_MASK; - sg->len = ahc_htole32(len); + sg->len = aic_htole32(len); return (consumed); } @@ -836,6 +767,164 @@ #endif } +/************************** Error Recovery ************************************/ +static int ahc_linux_recovery_thread(void *arg); + +static int +ahc_linux_recovery_thread(void *arg) +{ + struct ahc_softc *ahc; + u_long s; + + ahc = (struct ahc_softc *)arg; + + /* + * Complete thread creation. + */ + lock_kernel(); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60) + /* + * Don't care about any signals. + */ + siginitsetinv(¤t->blocked, 0); + + daemonize(); + sprintf(current->comm, "ahc_recovery_%d", ahc->unit); +#else + daemonize("ahc_recovery_%d", ahc->unit); +#endif + unlock_kernel(); + + while (1) { + + /* + * Use down_interruptible() rather than down() to + * avoid inclusion in the load average. + */ + down_interruptible(&ahc->platform_data->recovery_sem); + + ahc_lock(ahc, &s); + if ((ahc->flags & AHC_SHUTDOWN_RECOVERY) != 0) { + ahc_unlock(ahc, &s); + break; + } + + /* + * Don't bother the recovery handler if the + * list has been cleared by a previous run + * of the handler. This can happen when + * several SCBs timeout before our handler + * can run causing our semaphore to be up'ed + * repeatedly. The extra calls need to be + * avoided so that the recovery handler doesn't + * confuse this case with timeouts occuring + * due to interrupts failing to function. + */ + if (LIST_EMPTY(&ahc->timedout_scbs) != 0) { + ahc_unlock(ahc, &s); + continue; + } + ahc_unlock(ahc, &s); + ahc_recover_commands(ahc); + + /* + * Process any pent up completions. + */ + ahc_lock(ahc, &s); + aic_schedule_runq(ahc); + ahc_linux_run_complete_queue(ahc); + ahc_unlock(ahc, &s); + } + up(&ahc->platform_data->recovery_ending_sem); + return(0); +} + +int +ahc_spawn_recovery_thread(struct ahc_softc *ahc) +{ + ahc->platform_data->recovery_pid = + kernel_thread(ahc_linux_recovery_thread, ahc, 0); + + if (ahc->platform_data->recovery_pid < 0) + return (-ahc->platform_data->recovery_pid); + + return (0); +} + +void +ahc_terminate_recovery_thread(struct ahc_softc *ahc) +{ + u_long s; + + ahc_lock(ahc, &s); + if (ahc->platform_data->recovery_pid != 0) { + ahc->flags |= AHC_SHUTDOWN_RECOVERY; + ahc_unlock(ahc, &s); + up(&ahc->platform_data->recovery_sem); + + /* + * Use the recovery_ending_sem as an indicator that + * the dv thread is exiting. Note that the dv + * thread must still return after performing + * the up on our semaphore before it has + * completely exited this module. Unfortunately, + * there seems to be no easy way to wait for the + * exit of a thread for which you are not the + * parent (dv threads are parented by init). + * Cross your fingers... + */ + down(&ahc->platform_data->recovery_ending_sem); + + /* + * Mark the recovery thread as already dead. This + * avoids attempting to kill it a second time. + * This is necessary because we must kill the + * our threads before calling ahc_free() in the + * module shutdown case to avoid bogus locking + * in the SCSI mid-layer, but when ahc_free() is + * called without killing the DV thread in the + * instance detach case, so ahc_platform_free() + * calls us again to verify that the DV thread + * is dead. + */ + ahc->platform_data->recovery_pid = 0; + } else { + ahc_unlock(ahc, &s); + } +} + +void +ahc_set_recoveryscb(struct ahc_softc *ahc, struct scb *scb) +{ + if ((scb->flags & SCB_RECOVERY_SCB) == 0) { + struct scb *list_scb; + + scb->flags |= SCB_RECOVERY_SCB; + + /* + * Take all queued, but not sent SCBs out of the equation. + * Also ensure that no new commands are queued to us while we + * try to fix this problem. + */ + if ((scb->platform_data->flags & AIC_RELEASE_SIMQ) == 0) { + aic_freeze_simq(ahc); + scb->platform_data->flags |= AIC_RELEASE_SIMQ; + } + + /* + * Go through all of our pending SCBs and remove + * any scheduled timeouts for them. We will reschedule + * them after we've successfully fixed this problem. + */ + LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) { + + scsi_delete_timer(list_scb->io_ctx); + list_scb->platform_data->flags &= ~AIC_TIMEOUT_ACTIVE; + } + } +} + +/************************ Linux Entry Points **********************************/ /* * Try to detect an Adaptec 7XXX controller. */ @@ -852,17 +941,19 @@ */ spin_unlock_irq(&io_request_lock); #endif + found = 0; /* * Sanity checking of Linux SCSI data structures so * that some of our hacks^H^H^H^H^Hassumptions aren't * violated. */ - if (offsetof(struct ahc_cmd_internal, end) + if (offsetof(struct aic_cmd_internal, end) > offsetof(struct scsi_cmnd, host_scribble)) { printf("ahc_linux_detect: SCSI data structures changed.\n"); printf("ahc_linux_detect: Unable to attach\n"); - return (0); + ahc_init_status = -EINVAL; + goto done; } ahc_linux_size_nseg(); #ifdef MODULE @@ -879,11 +970,7 @@ "aic7xxx: insmod or else it might trash certain memory areas.\n"); #endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) template->proc_name = "aic7xxx"; -#else - template->proc_dir = &proc_scsi_aic7xxx; -#endif /* * Initialize our softc list lock prior to @@ -892,11 +979,15 @@ ahc_list_lockinit(); #ifdef CONFIG_PCI - ahc_linux_pci_init(); + ahc_init_status = ahc_linux_pci_init(); + if (ahc_init_status != 0) + goto done; #endif #ifdef CONFIG_EISA - ahc_linux_eisa_init(); + ahc_init_status = ahc_linux_eisa_init(); + if (ahc_init_status != 0) + goto done; #endif /* @@ -909,6 +1000,7 @@ if (ahc_linux_register_host(ahc, template) == 0) found++; } +done: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) spin_lock_irq(&io_request_lock); #endif @@ -927,7 +1019,6 @@ struct ahc_softc *ahc; u_long l; - ahc_list_lock(&l); if (host != NULL) { /* @@ -935,17 +1026,20 @@ * the free directly, but check our * list for extra sanity. */ + ahc_list_lock(&l); ahc = ahc_find_softc(*(struct ahc_softc **)host->hostdata); if (ahc != NULL) { u_long s; + TAILQ_REMOVE(&ahc_tailq, ahc, links); + ahc_list_unlock(&l); ahc_lock(ahc, &s); ahc_intr_enable(ahc, FALSE); ahc_unlock(ahc, &s); ahc_free(ahc); - } + } else + ahc_list_unlock(&l); } - ahc_list_unlock(&l); return (0); } #endif @@ -985,7 +1079,7 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) { struct ahc_softc *ahc; - struct ahc_linux_device *dev; + struct aic_linux_device *dev; u_long flags; ahc = *(struct ahc_softc **)cmd->device->host->hostdata; @@ -995,7 +1089,7 @@ */ cmd->scsi_done = scsi_done; - ahc_midlayer_entrypoint_lock(ahc, &flags); + ahc_entrypoint_lock(ahc, &flags); /* * Close the race of a command that was in the process of @@ -1004,33 +1098,52 @@ * perform DV. */ if (ahc->platform_data->qfrozen != 0 - && AHC_DV_CMD(cmd) == 0) { + && AIC_DV_CMD(cmd) == 0) { - ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); + aic_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); ahc_linux_queue_cmd_complete(ahc, cmd); ahc_schedule_completeq(ahc); - ahc_midlayer_entrypoint_unlock(ahc, &flags); + ahc_entrypoint_unlock(ahc, &flags); return (0); } dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id, cmd->device->lun, /*alloc*/TRUE); if (dev == NULL) { - ahc_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); + + aic_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); ahc_linux_queue_cmd_complete(ahc, cmd); ahc_schedule_completeq(ahc); - ahc_midlayer_entrypoint_unlock(ahc, &flags); + ahc_entrypoint_unlock(ahc, &flags); printf("%s: aic7xxx_linux_queue - Unable to allocate device!\n", ahc_name(ahc)); return (0); } + + if (cmd->cmd_len > MAX_CDB_LEN) { + + aic_cmd_set_transaction_status(cmd, CAM_REQ_INVALID); + ahc_linux_queue_cmd_complete(ahc, cmd); + ahc_schedule_completeq(ahc); + ahc_entrypoint_unlock(ahc, &flags); + printf("%s: aic7xxx_linux_queue -" + "CDB length of %d exceeds max!\n", + ahc_name(ahc), cmd->cmd_len); + return (0); + } + + /* + * We perform our own timeout handling. + */ + scsi_delete_timer(cmd); + cmd->result = CAM_REQ_INPROG << 16; - TAILQ_INSERT_TAIL(&dev->busyq, (struct ahc_cmd *)cmd, acmd_links.tqe); - if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) { + TAILQ_INSERT_TAIL(&dev->busyq, (struct aic_cmd *)cmd, acmd_links.tqe); + if ((dev->flags & AIC_DEV_ON_RUN_LIST) == 0) { TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; - ahc_linux_run_device_queues(ahc); + dev->flags |= AIC_DEV_ON_RUN_LIST; + aic_linux_run_device_queues(ahc); } - ahc_midlayer_entrypoint_unlock(ahc, &flags); + ahc_entrypoint_unlock(ahc, &flags); return (0); } @@ -1050,13 +1163,13 @@ ahc_linux_slave_configure(Scsi_Device *device) { struct ahc_softc *ahc; - struct ahc_linux_device *dev; + struct aic_linux_device *dev; u_long flags; ahc = *((struct ahc_softc **)device->host->hostdata); if (bootverbose) printf("%s: Slave Configure %d\n", ahc_name(ahc), device->id); - ahc_midlayer_entrypoint_lock(ahc, &flags); + ahc_entrypoint_lock(ahc, &flags); /* * Since Linux has attached to the device, configure * it so we don't free and allocate the device @@ -1066,11 +1179,11 @@ device->id, device->lun, /*alloc*/TRUE); if (dev != NULL) { - dev->flags &= ~AHC_DEV_UNCONFIGURED; + dev->flags &= ~AIC_DEV_UNCONFIGURED; dev->scsi_device = device; - ahc_linux_device_queue_depth(ahc, dev); + aic_linux_device_queue_depth(ahc, dev); } - ahc_midlayer_entrypoint_unlock(ahc, &flags); + ahc_entrypoint_unlock(ahc, &flags); return (0); } @@ -1078,13 +1191,13 @@ ahc_linux_slave_destroy(Scsi_Device *device) { struct ahc_softc *ahc; - struct ahc_linux_device *dev; + struct aic_linux_device *dev; u_long flags; ahc = *((struct ahc_softc **)device->host->hostdata); if (bootverbose) printf("%s: Slave Destroy %d\n", ahc_name(ahc), device->id); - ahc_midlayer_entrypoint_lock(ahc, &flags); + ahc_entrypoint_lock(ahc, &flags); dev = ahc_linux_get_device(ahc, device->channel, device->id, device->lun, /*alloc*/FALSE); @@ -1096,14 +1209,13 @@ * the refcounting process. */ if (dev != NULL - && (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) { - dev->flags |= AHC_DEV_UNCONFIGURED; + && (dev->flags & AIC_DEV_SLAVE_CONFIGURED) != 0) { + dev->flags |= AIC_DEV_UNCONFIGURED; if (TAILQ_EMPTY(&dev->busyq) - && dev->active == 0 - && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0) + && dev->active == 0) ahc_linux_free_device(ahc, dev); } - ahc_midlayer_entrypoint_unlock(ahc, &flags); + ahc_entrypoint_unlock(ahc, &flags); } #else /* @@ -1139,7 +1251,7 @@ continue; if (device->host == host) { - struct ahc_linux_device *dev; + struct aic_linux_device *dev; /* * Since Linux has attached to the device, configure @@ -1150,13 +1262,13 @@ device->id, device->lun, /*alloc*/TRUE); if (dev != NULL) { - dev->flags &= ~AHC_DEV_UNCONFIGURED; + dev->flags &= ~AIC_DEV_UNCONFIGURED; dev->scsi_device = device; - ahc_linux_device_queue_depth(ahc, dev); + aic_linux_device_queue_depth(ahc, dev); device->queue_depth = dev->openings + dev->active; - if ((dev->flags & (AHC_DEV_Q_BASIC - | AHC_DEV_Q_TAGGED)) == 0) { + if ((dev->flags & (AIC_DEV_Q_BASIC + | AIC_DEV_Q_TAGGED)) == 0) { /* * We allow the OS to queue 2 untagged * transactions to us at any time even @@ -1281,11 +1393,11 @@ int found; ahc = *(struct ahc_softc **)cmd->device->host->hostdata; - ahc_midlayer_entrypoint_lock(ahc, &s); + ahc_entrypoint_lock(ahc, &s); found = ahc_reset_channel(ahc, cmd->device->channel + 'A', /*initiate reset*/TRUE); ahc_linux_run_complete_queue(ahc); - ahc_midlayer_entrypoint_unlock(ahc, &s); + ahc_entrypoint_unlock(ahc, &s); if (bootverbose) printf("%s: SCSI bus reset delivered. " @@ -1294,87 +1406,8 @@ return SUCCESS; } -Scsi_Host_Template aic7xxx_driver_template = { - .module = THIS_MODULE, - .name = "aic7xxx", - .proc_info = ahc_linux_proc_info, - .info = ahc_linux_info, - .queuecommand = ahc_linux_queue, - .eh_abort_handler = ahc_linux_abort, - .eh_device_reset_handler = ahc_linux_dev_reset, - .eh_bus_reset_handler = ahc_linux_bus_reset, -#if defined(__i386__) - .bios_param = ahc_linux_biosparam, -#endif - .can_queue = AHC_MAX_QUEUE, - .this_id = -1, - .cmd_per_lun = 2, - .use_clustering = ENABLE_CLUSTERING, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) - /* - * We can only map 16MB per-SG - * so create a sector limit of - * "16MB" in 2K sectors. - */ - .max_sectors = 8192, -#endif -#if defined CONFIG_HIGHIO || LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) -/* Assume RedHat Distribution with its different HIGHIO conventions. */ - .can_dma_32 = 1, - .single_sg_okay = 1, -#else - .highmem_io = 1, -#endif -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - .slave_alloc = ahc_linux_slave_alloc, - .slave_configure = ahc_linux_slave_configure, - .slave_destroy = ahc_linux_slave_destroy, -#else - .detect = ahc_linux_detect, - .release = ahc_linux_release, - .select_queue_depths = ahc_linux_select_queue_depth, - .use_new_eh_code = 1, -#endif -}; - -/**************************** Tasklet Handler *********************************/ - -/* - * In 2.4.X and above, this routine is called from a tasklet, - * so we must re-acquire our lock prior to executing this code. - * In all prior kernels, ahc_schedule_runq() calls this routine - * directly and ahc_schedule_runq() is called with our lock held. - */ -static void -ahc_runq_tasklet(unsigned long data) -{ - struct ahc_softc* ahc; - struct ahc_linux_device *dev; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - u_long flags; -#endif - - ahc = (struct ahc_softc *)data; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - ahc_lock(ahc, &flags); -#endif - while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) { - - TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links); - dev->flags &= ~AHC_DEV_ON_RUN_LIST; - ahc_linux_check_device_queue(ahc, dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /* Yeild to our interrupt handler */ - ahc_unlock(ahc, &flags); - ahc_lock(ahc, &flags); -#endif - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - ahc_unlock(ahc, &flags); -#endif -} +Scsi_Host_Template aic7xxx_driver_template = + AIC_TEMPLATE_INITIALIZER("aic7xxx", /* max_sectors*/8192); /******************************** Macros **************************************/ #define BUILD_SCSIID(ahc, cmd) \ @@ -1382,132 +1415,6 @@ | (((cmd)->device->channel == 0) ? (ahc)->our_id : (ahc)->our_id_b) \ | (((cmd)->device->channel == 0) ? 0 : TWIN_CHNLB)) -/******************************** Bus DMA *************************************/ -int -ahc_dma_tag_create(struct ahc_softc *ahc, bus_dma_tag_t parent, - bus_size_t alignment, bus_size_t boundary, - bus_addr_t lowaddr, bus_addr_t highaddr, - bus_dma_filter_t *filter, void *filterarg, - bus_size_t maxsize, int nsegments, - bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag) -{ - bus_dma_tag_t dmat; - - dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT); - if (dmat == NULL) - return (ENOMEM); - - /* - * Linux is very simplistic about DMA memory. For now don't - * maintain all specification information. Once Linux supplies - * better facilities for doing these operations, or the - * needs of this particular driver change, we might need to do - * more here. - */ - dmat->alignment = alignment; - dmat->boundary = boundary; - dmat->maxsize = maxsize; - *ret_tag = dmat; - return (0); -} - -void -ahc_dma_tag_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat) -{ - free(dmat, M_DEVBUF); -} - -int -ahc_dmamem_alloc(struct ahc_softc *ahc, bus_dma_tag_t dmat, void** vaddr, - int flags, bus_dmamap_t *mapp) -{ - bus_dmamap_t map; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT); - if (map == NULL) - return (ENOMEM); - /* - * Although we can dma data above 4GB, our - * "consistent" memory is below 4GB for - * space efficiency reasons (only need a 4byte - * address). For this reason, we have to reset - * our dma mask when doing allocations. - */ - if (ahc->dev_softc != NULL) - ahc_pci_set_dma_mask(ahc->dev_softc, 0xFFFFFFFF); - *vaddr = pci_alloc_consistent(ahc->dev_softc, - dmat->maxsize, &map->bus_addr); - if (ahc->dev_softc != NULL) - ahc_pci_set_dma_mask(ahc->dev_softc, - ahc->platform_data->hw_dma_mask); -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */ - /* - * At least in 2.2.14, malloc is a slab allocator so all - * allocations are aligned. We assume for these kernel versions - * that all allocations will be bellow 4Gig, physically contiguous, - * and accessible via DMA by the controller. - */ - map = NULL; /* No additional information to store */ - *vaddr = malloc(dmat->maxsize, M_DEVBUF, M_NOWAIT); -#endif - if (*vaddr == NULL) - return (ENOMEM); - *mapp = map; - return(0); -} - -void -ahc_dmamem_free(struct ahc_softc *ahc, bus_dma_tag_t dmat, - void* vaddr, bus_dmamap_t map) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - pci_free_consistent(ahc->dev_softc, dmat->maxsize, - vaddr, map->bus_addr); -#else - free(vaddr, M_DEVBUF); -#endif -} - -int -ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map, - void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb, - void *cb_arg, int flags) -{ - /* - * Assume for now that this will only be used during - * initialization and not for per-transaction buffer mapping. - */ - bus_dma_segment_t stack_sg; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - stack_sg.ds_addr = map->bus_addr; -#else -#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a)) - stack_sg.ds_addr = VIRT_TO_BUS(buf); -#endif - stack_sg.ds_len = dmat->maxsize; - cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); - return (0); -} - -void -ahc_dmamap_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map) -{ - /* - * The map may is NULL in our < 2.3.X implementation. - */ - if (map != NULL) - free(map, M_DEVBUF); -} - -int -ahc_dmamap_unload(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map) -{ - /* Nothing to do */ - return (0); -} - /********************* Platform Dependent Functions ***************************/ /* * Compare "left hand" softc with "right hand" softc, returning: @@ -1558,19 +1465,19 @@ char primary_channel; if (aic7xxx_reverse_scan != 0) - value = ahc_get_pci_bus(lahc->dev_softc) - - ahc_get_pci_bus(rahc->dev_softc); + value = aic_get_pci_bus(lahc->dev_softc) + - aic_get_pci_bus(rahc->dev_softc); else - value = ahc_get_pci_bus(rahc->dev_softc) - - ahc_get_pci_bus(lahc->dev_softc); + value = aic_get_pci_bus(rahc->dev_softc) + - aic_get_pci_bus(lahc->dev_softc); if (value != 0) break; if (aic7xxx_reverse_scan != 0) - value = ahc_get_pci_slot(lahc->dev_softc) - - ahc_get_pci_slot(rahc->dev_softc); + value = aic_get_pci_slot(lahc->dev_softc) + - aic_get_pci_slot(rahc->dev_softc); else - value = ahc_get_pci_slot(rahc->dev_softc) - - ahc_get_pci_slot(lahc->dev_softc); + value = aic_get_pci_slot(rahc->dev_softc) + - aic_get_pci_slot(lahc->dev_softc); if (value != 0) break; /* @@ -1716,9 +1623,7 @@ return 1; } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) __setup("aic7xxx=", aic7xxx_setup); -#endif uint32_t aic7xxx_verbose; @@ -1730,20 +1635,23 @@ char *new_name; u_long s; u_int targ_offset; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + int error; +#endif template->name = ahc->description; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + host = scsi_host_alloc(template, sizeof(struct ahc_softc *)); +#else host = scsi_register(template, sizeof(struct ahc_softc *)); +#endif if (host == NULL) return (ENOMEM); *((struct ahc_softc **)host->hostdata) = ahc; ahc_lock(ahc, &s); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - scsi_assign_lock(host, &ahc->platform_data->spin_lock); -#elif AHC_SCSI_HAS_HOST_LOCK != 0 - host->lock = &ahc->platform_data->spin_lock; -#endif ahc->platform_data->host = host; + aic_assign_host_lock(ahc); host->can_queue = AHC_MAX_QUEUE; host->cmd_per_lun = 2; /* XXX No way to communicate the ID for multiple channels */ @@ -1767,13 +1675,20 @@ #endif ahc_linux_initialize_scsi_bus(ahc); ahc_unlock(ahc, &s); + ahc_sysrq_key = aic_install_sysrq(&ahc_sysrq_op); + ahc_spawn_recovery_thread(ahc); + if (ahc->platform_data->recovery_pid < 0) { + printf("%s: Failed to create recovery thread, error= %d\n", + ahc_name(ahc), ahc->platform_data->recovery_pid); + return (-ahc->platform_data->recovery_pid); + } ahc->platform_data->dv_pid = kernel_thread(ahc_linux_dv_thread, ahc, 0); - ahc_lock(ahc, &s); if (ahc->platform_data->dv_pid < 0) { printf("%s: Failed to create DV thread, error= %d\n", ahc_name(ahc), ahc->platform_data->dv_pid); return (-ahc->platform_data->dv_pid); } + ahc_lock(ahc, &s); /* * Initially allocate *all* of our linux target objects * so that the DV thread will scan them all in parallel @@ -1818,7 +1733,10 @@ ahc_unlock(ahc, &s); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); + error = scsi_add_host(host, ahc->dev_softc); + if (error != 0) + return (-error); + scsi_scan_host(host); #endif return (0); } @@ -1915,17 +1833,6 @@ ahc_update_neg_request(ahc, &devinfo, tstate, tinfo, AHC_NEG_ALWAYS); } - /* Give the bus some time to recover */ - if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) { - ahc_linux_freeze_simq(ahc); - init_timer(&ahc->platform_data->reset_timer); - ahc->platform_data->reset_timer.data = (u_long)ahc; - ahc->platform_data->reset_timer.expires = - jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000; - ahc->platform_data->reset_timer.function = - ahc_linux_release_simq; - add_timer(&ahc->platform_data->reset_timer); - } } int @@ -1939,27 +1846,23 @@ memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); TAILQ_INIT(&ahc->platform_data->completeq); TAILQ_INIT(&ahc->platform_data->device_runq); - ahc->platform_data->irq = AHC_LINUX_NOIRQ; + ahc->platform_data->irq = AIC_LINUX_NOIRQ; ahc->platform_data->hw_dma_mask = 0xFFFFFFFF; ahc_lockinit(ahc); - ahc_done_lockinit(ahc); + init_timer(&ahc->platform_data->bus_settle_timer); + ahc->platform_data->bus_settle_timer.data = (u_long)ahc; + ahc->platform_data->bus_settle_timer.function = + (aic_linux_callback_t *)aic_bus_settle_complete; init_timer(&ahc->platform_data->completeq_timer); ahc->platform_data->completeq_timer.data = (u_long)ahc; ahc->platform_data->completeq_timer.function = - (ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) + (aic_linux_callback_t *)ahc_linux_thread_run_complete_queue; init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); init_MUTEX_LOCKED(&ahc->platform_data->dv_sem); init_MUTEX_LOCKED(&ahc->platform_data->dv_cmd_sem); -#else - ahc->platform_data->eh_sem = MUTEX_LOCKED; - ahc->platform_data->dv_sem = MUTEX_LOCKED; - ahc->platform_data->dv_cmd_sem = MUTEX_LOCKED; -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet, - (unsigned long)ahc); -#endif + init_MUTEX_LOCKED(&ahc->platform_data->recovery_sem); + init_MUTEX_LOCKED(&ahc->platform_data->recovery_ending_sem); + aic_setup_tasklets(ahc); ahc->seltime = (aic7xxx_seltime & 0x3) << 4; ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4; if (aic7xxx_pci_parity == 0) @@ -1971,21 +1874,22 @@ void ahc_platform_free(struct ahc_softc *ahc) { - struct ahc_linux_target *targ; - struct ahc_linux_device *dev; + struct aic_linux_target *targ; + struct aic_linux_device *dev; int i, j; + aic_remove_sysrq(ahc_sysrq_key, &ahc_sysrq_op); if (ahc->platform_data != NULL) { del_timer_sync(&ahc->platform_data->completeq_timer); ahc_linux_kill_dv_thread(ahc); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - tasklet_kill(&ahc->platform_data->runq_tasklet); -#endif + aic_teardown_tasklets(ahc); if (ahc->platform_data->host != NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) scsi_remove_host(ahc->platform_data->host); -#endif + scsi_host_put(ahc->platform_data->host); +#else scsi_unregister(ahc->platform_data->host); +#endif } /* destroy all of the device and target objects */ @@ -1999,6 +1903,7 @@ if (targ->devices[j] == NULL) continue; dev = targ->devices[j]; + del_timer_sync(&dev->timer); ahc_linux_free_device(ahc, dev); } /* @@ -2009,7 +1914,7 @@ } } - if (ahc->platform_data->irq != AHC_LINUX_NOIRQ) + if (ahc->platform_data->irq != AIC_LINUX_NOIRQ) free_irq(ahc->platform_data->irq, ahc); if (ahc->tag == BUS_SPACE_PIO && ahc->bsh.ioport != 0) @@ -2021,10 +1926,8 @@ base_addr = (u_long)ahc->bsh.maddr; base_addr &= PAGE_MASK; iounmap((void *)base_addr); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(ahc->platform_data->mem_busaddr, 0x1000); -#endif } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) && \ LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) @@ -2054,7 +1957,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, ahc_queue_alg alg) { - struct ahc_linux_device *dev; + struct aic_linux_device *dev; int was_queuing; int now_queuing; @@ -2063,27 +1966,27 @@ devinfo->lun, /*alloc*/FALSE); if (dev == NULL) return; - was_queuing = dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED); + was_queuing = dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED); switch (alg) { default: case AHC_QUEUE_NONE: now_queuing = 0; break; case AHC_QUEUE_BASIC: - now_queuing = AHC_DEV_Q_BASIC; + now_queuing = AIC_DEV_Q_BASIC; break; case AHC_QUEUE_TAGGED: - now_queuing = AHC_DEV_Q_TAGGED; + now_queuing = AIC_DEV_Q_TAGGED; break; } - if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) == 0 + if ((dev->flags & AIC_DEV_FREEZE_TIL_EMPTY) == 0 && (was_queuing != now_queuing) && (dev->active != 0)) { - dev->flags |= AHC_DEV_FREEZE_TIL_EMPTY; + dev->flags |= AIC_DEV_FREEZE_TIL_EMPTY; dev->qfrozen++; } - dev->flags &= ~(AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED|AHC_DEV_PERIODIC_OTAG); + dev->flags &= ~(AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED|AIC_DEV_PERIODIC_OTAG); if (now_queuing) { u_int usertags; @@ -2103,11 +2006,11 @@ */ dev->openings = 1; } else if (alg == AHC_QUEUE_TAGGED) { - dev->flags |= AHC_DEV_Q_TAGGED; + dev->flags |= AIC_DEV_Q_TAGGED; if (aic7xxx_periodic_otag != 0) - dev->flags |= AHC_DEV_PERIODIC_OTAG; + dev->flags |= AIC_DEV_PERIODIC_OTAG; } else - dev->flags |= AHC_DEV_Q_BASIC; + dev->flags |= AIC_DEV_Q_BASIC; } else { /* We can only have one opening. */ dev->maxtags = 0; @@ -2115,13 +2018,13 @@ } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) if (dev->scsi_device != NULL) { - switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) { - case AHC_DEV_Q_BASIC: + switch ((dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED))) { + case AIC_DEV_Q_BASIC: scsi_adjust_queue_depth(dev->scsi_device, MSG_SIMPLE_TASK, dev->openings + dev->active); break; - case AHC_DEV_Q_TAGGED: + case AIC_DEV_Q_TAGGED: scsi_adjust_queue_depth(dev->scsi_device, MSG_ORDERED_TASK, dev->openings + dev->active); @@ -2185,9 +2088,9 @@ for (; targ < maxtarg; targ++) { for (; clun < maxlun; clun++) { - struct ahc_linux_device *dev; - struct ahc_busyq *busyq; - struct ahc_cmd *acmd; + struct aic_linux_device *dev; + struct aic_busyq *busyq; + struct aic_cmd *acmd; dev = ahc_linux_get_device(ahc, chan, targ, clun, @@ -2204,6 +2107,20 @@ acmd_links.tqe); count++; cmd->result = status << 16; + /* + * The completion handler believes that + * commands without active timers + * running have lost the race of + * completing before their timer + * expires. Since commands in our + * busy queues do not have timers + * running, appease the mid-layer by + * adding a timer now. This timer will + * be immediately canceled by the + * midlayer. + */ + scsi_add_timer(cmd, 60*HZ, + aic_linux_midlayer_timeout); ahc_linux_queue_cmd_complete(ahc, cmd); } } @@ -2220,7 +2137,7 @@ ahc_lock(ahc, &flags); del_timer(&ahc->platform_data->completeq_timer); - ahc->platform_data->flags &= ~AHC_RUN_CMPLT_Q_TIMER; + ahc->platform_data->flags &= ~AIC_RUN_CMPLT_Q_TIMER; ahc_linux_run_complete_queue(ahc); ahc_unlock(ahc, &flags); } @@ -2233,14 +2150,23 @@ * Freeze the simq and signal ahc_linux_queue to not let any * more commands through. */ - if ((ahc->platform_data->flags & AHC_DV_ACTIVE) == 0) { + if ((ahc->platform_data->flags & AIC_DV_ACTIVE) == 0) { #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOW_DV) printf("%s: Waking DV thread\n", ahc_name(ahc)); #endif - ahc->platform_data->flags |= AHC_DV_ACTIVE; - ahc_linux_freeze_simq(ahc); + ahc->platform_data->flags |= AIC_DV_ACTIVE; + + /* + * Prevent upper layer from sending any + * commands to us. + */ + aic_freeze_simq(ahc); + scsi_block_requests(ahc->platform_data->host); + ahc_platform_abort_scbs(ahc, CAM_TARGET_WILDCARD, ALL_CHANNELS, + CAM_LUN_WILDCARD, SCB_LIST_NULL, + ROLE_INITIATOR, CAM_REQUEUE_REQ); /* Wake up the DV kthread */ up(&ahc->platform_data->dv_sem); @@ -2254,7 +2180,7 @@ ahc_lock(ahc, &s); if (ahc->platform_data->dv_pid != 0) { - ahc->platform_data->flags |= AHC_DV_SHUTDOWN; + ahc->platform_data->flags |= AIC_DV_SHUTDOWN; ahc_unlock(ahc, &s); up(&ahc->platform_data->dv_sem); @@ -2329,7 +2255,7 @@ /* Check to see if we've been signaled to exit */ ahc_lock(ahc, &s); - if ((ahc->platform_data->flags & AHC_DV_SHUTDOWN) != 0) { + if ((ahc->platform_data->flags & AIC_DV_SHUTDOWN) != 0) { ahc_unlock(ahc, &s); break; } @@ -2346,7 +2272,7 @@ */ ahc_lock(ahc, &s); while (LIST_FIRST(&ahc->pending_scbs) != NULL) { - ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_EMPTY; + ahc->platform_data->flags |= AIC_DV_WAIT_SIMQ_EMPTY; ahc_unlock(ahc, &s); down_interruptible(&ahc->platform_data->dv_sem); ahc_lock(ahc, &s); @@ -2356,8 +2282,8 @@ * Wait for the SIMQ to be released so that DV is the * only reason the queue is frozen. */ - while (AHC_DV_SIMQ_FROZEN(ahc) == 0) { - ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_RELEASE; + while (AIC_DV_SIMQ_FROZEN(ahc) == 0) { + ahc->platform_data->flags |= AIC_DV_WAIT_SIMQ_RELEASE; ahc_unlock(ahc, &s); down_interruptible(&ahc->platform_data->dv_sem); ahc_lock(ahc, &s); @@ -2368,14 +2294,16 @@ ahc_linux_dv_target(ahc, target); ahc_lock(ahc, &s); - ahc->platform_data->flags &= ~AHC_DV_ACTIVE; - ahc_unlock(ahc, &s); + ahc->platform_data->flags &= ~AIC_DV_ACTIVE; /* * Release the SIMQ so that normal commands are * allowed to continue on the bus. */ - ahc_linux_release_simq((u_long)ahc); + aic_release_simq_locked(ahc); + ahc_unlock(ahc, &s); + + scsi_unblock_requests(ahc->platform_data->host); } up(&ahc->platform_data->eh_sem); return (0); @@ -2389,10 +2317,10 @@ ahc_set_dv_state(ahc, targ, newstate, __LINE__) static __inline void -ahc_set_dv_state(struct ahc_softc *ahc, struct ahc_linux_target *targ, - ahc_dv_state newstate, u_int line) +ahc_set_dv_state(struct ahc_softc *ahc, struct aic_linux_target *targ, + aic_dv_state newstate, u_int line) { - ahc_dv_state oldstate; + aic_dv_state oldstate; oldstate = targ->dv_state; #ifdef AHC_DEBUG @@ -2412,7 +2340,7 @@ ahc_linux_dv_target(struct ahc_softc *ahc, u_int target_offset) { struct ahc_devinfo devinfo; - struct ahc_linux_target *targ; + struct aic_linux_target *targ; struct scsi_cmnd *cmd; struct scsi_device *scsi_dev; struct scsi_sense_data *sense; @@ -2426,7 +2354,7 @@ echo_size = 0; ahc_lock(ahc, &s); targ = ahc->platform_data->targets[target_offset]; - if (targ == NULL || (targ->flags & AHC_DV_REQUIRED) == 0) { + if (targ == NULL || (targ->flags & AIC_DV_REQUIRED) == 0) { ahc_unlock(ahc, &s); return; } @@ -2451,14 +2379,14 @@ scsi_dev->channel = devinfo.channel - 'A'; ahc->platform_data->dv_scsi_dev = scsi_dev; - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_SHORT_ASYNC); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_INQ_SHORT_ASYNC); - while (targ->dv_state != AHC_DV_STATE_EXIT) { + while (targ->dv_state != AIC_DV_STATE_EXIT) { timeout = AHC_LINUX_DV_TIMEOUT; switch (targ->dv_state) { - case AHC_DV_STATE_INQ_SHORT_ASYNC: - case AHC_DV_STATE_INQ_ASYNC: - case AHC_DV_STATE_INQ_ASYNC_VERIFY: + case AIC_DV_STATE_INQ_SHORT_ASYNC: + case AIC_DV_STATE_INQ_ASYNC: + case AIC_DV_STATE_INQ_ASYNC_VERIFY: /* * Set things to async narrow to reduce the * chance that the INQ will fail. @@ -2470,36 +2398,36 @@ AHC_TRANS_GOAL, /*paused*/FALSE); ahc_unlock(ahc, &s); timeout = 10 * HZ; - targ->flags &= ~AHC_INQ_VALID; + targ->flags &= ~AIC_INQ_VALID; /* FALLTHROUGH */ - case AHC_DV_STATE_INQ_VERIFY: + case AIC_DV_STATE_INQ_VERIFY: { u_int inq_len; - if (targ->dv_state == AHC_DV_STATE_INQ_SHORT_ASYNC) + if (targ->dv_state == AIC_DV_STATE_INQ_SHORT_ASYNC) inq_len = AHC_LINUX_DV_INQ_SHORT_LEN; else inq_len = targ->inq_data->additional_length + 5; ahc_linux_dv_inq(ahc, cmd, &devinfo, targ, inq_len); break; } - case AHC_DV_STATE_TUR: - case AHC_DV_STATE_BUSY: + case AIC_DV_STATE_TUR: + case AIC_DV_STATE_BUSY: timeout = 5 * HZ; ahc_linux_dv_tur(ahc, cmd, &devinfo); break; - case AHC_DV_STATE_REBD: + case AIC_DV_STATE_REBD: ahc_linux_dv_rebd(ahc, cmd, &devinfo, targ); break; - case AHC_DV_STATE_WEB: + case AIC_DV_STATE_WEB: ahc_linux_dv_web(ahc, cmd, &devinfo, targ); break; - case AHC_DV_STATE_REB: + case AIC_DV_STATE_REB: ahc_linux_dv_reb(ahc, cmd, &devinfo, targ); break; - case AHC_DV_STATE_SU: + case AIC_DV_STATE_SU: ahc_linux_dv_su(ahc, cmd, &devinfo, targ); timeout = 50 * HZ; break; @@ -2511,8 +2439,6 @@ } /* Queue the command and wait for it to complete */ - /* Abuse eh_timeout in the scsi_cmnd struct for our purposes */ - init_timer(&cmd->eh_timeout); #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) /* @@ -2522,20 +2448,22 @@ */ timeout += HZ; #endif - scsi_add_timer(cmd, timeout, ahc_linux_dv_timeout); + init_timer(&cmd->eh_timeout); + cmd->timeout_per_command = timeout; + /* * In 2.5.X, it is assumed that all calls from the * "midlayer" (which we are emulating) will have the * ahc host lock held. For other kernels, the * io_request_lock must be held. */ -#if AHC_SCSI_HAS_HOST_LOCK != 0 +#if AIC_SCSI_HAS_HOST_LOCK != 0 ahc_lock(ahc, &s); #else spin_lock_irqsave(&io_request_lock, s); #endif ahc_linux_queue(cmd, ahc_linux_dv_complete); -#if AHC_SCSI_HAS_HOST_LOCK != 0 +#if AIC_SCSI_HAS_HOST_LOCK != 0 ahc_unlock(ahc, &s); #else spin_unlock_irqrestore(&io_request_lock, s); @@ -2546,8 +2474,8 @@ * only reason the queue is frozen. */ ahc_lock(ahc, &s); - while (AHC_DV_SIMQ_FROZEN(ahc) == 0) { - ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_RELEASE; + while (AIC_DV_SIMQ_FROZEN(ahc) == 0) { + ahc->platform_data->flags |= AIC_DV_WAIT_SIMQ_RELEASE; ahc_unlock(ahc, &s); down_interruptible(&ahc->platform_data->dv_sem); ahc_lock(ahc, &s); @@ -2558,7 +2486,7 @@ } out: - if ((targ->flags & AHC_INQ_VALID) != 0 + if ((targ->flags & AIC_INQ_VALID) != 0 && ahc_linux_get_device(ahc, devinfo.channel - 'A', devinfo.target, devinfo.lun, /*alloc*/FALSE) == NULL) { @@ -2569,7 +2497,7 @@ * parameters found in the inquiry string. */ ahc_linux_filter_inquiry(ahc, &devinfo); - if ((targ->flags & (AHC_BASIC_DV|AHC_ENHANCED_DV)) != 0) { + if ((targ->flags & (AIC_BASIC_DV|AIC_ENHANCED_DV)) != 0) { ahc_print_devinfo(ahc, &devinfo); printf("DV failed to configure device. " "Please file a bug report against " @@ -2594,7 +2522,7 @@ free(targ->dv_buffer1, M_DEVBUF); targ->dv_buffer1 = NULL; } - targ->flags &= ~AHC_DV_REQUIRED; + targ->flags &= ~AIC_DV_REQUIRED; if (targ->refcount == 0) ahc_linux_free_target(ahc, targ); ahc_unlock(ahc, &s); @@ -2603,13 +2531,13 @@ static void ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ) + struct aic_linux_target *targ) { u_int32_t status; status = aic_error_action(cmd, targ->inq_data, - ahc_cmd_get_transaction_status(cmd), - ahc_cmd_get_scsi_status(cmd)); + aic_cmd_get_transaction_status(cmd), + aic_cmd_get_scsi_status(cmd)); #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOW_DV) { @@ -2621,8 +2549,8 @@ #endif switch (targ->dv_state) { - case AHC_DV_STATE_INQ_SHORT_ASYNC: - case AHC_DV_STATE_INQ_ASYNC: + case AIC_DV_STATE_INQ_SHORT_ASYNC: + case AIC_DV_STATE_INQ_ASYNC: switch (status & SS_MASK) { case SS_NOP: { @@ -2631,21 +2559,21 @@ } case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) targ->dv_state_retry--; if ((status & SS_ERRMASK) == EBUSY) - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_BUSY); if (targ->dv_state_retry < 10) break; /* FALLTHROUGH */ default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOW_DV) { ahc_print_devinfo(ahc, devinfo); @@ -2655,7 +2583,7 @@ break; } break; - case AHC_DV_STATE_INQ_ASYNC_VERIFY: + case AIC_DV_STATE_INQ_ASYNC_VERIFY: switch (status & SS_MASK) { case SS_NOP: { @@ -2669,12 +2597,12 @@ * Try from the top again. */ AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; } AHC_SET_DV_STATE(ahc, targ, targ->dv_state+1); - targ->flags |= AHC_INQ_VALID; + targ->flags |= AIC_INQ_VALID; if (ahc_linux_user_dv_setting(ahc) == 0) break; @@ -2687,33 +2615,33 @@ default: case SID_SPI_CLOCK_ST: /* Assume only basic DV is supported. */ - targ->flags |= AHC_BASIC_DV; + targ->flags |= AIC_BASIC_DV; break; case SID_SPI_CLOCK_DT: case SID_SPI_CLOCK_DT_ST: - targ->flags |= AHC_ENHANCED_DV; + targ->flags |= AIC_ENHANCED_DV; break; } break; } case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) targ->dv_state_retry--; if ((status & SS_ERRMASK) == EBUSY) - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_BUSY); if (targ->dv_state_retry < 10) break; /* FALLTHROUGH */ default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOW_DV) { ahc_print_devinfo(ahc, devinfo); @@ -2723,14 +2651,14 @@ break; } break; - case AHC_DV_STATE_INQ_VERIFY: + case AIC_DV_STATE_INQ_VERIFY: switch (status & SS_MASK) { case SS_NOP: { if (memcmp(targ->inq_data, targ->dv_buffer, AHC_LINUX_DV_INQ_LEN) == 0) { - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } #ifdef AHC_DEBUG @@ -2751,7 +2679,7 @@ #endif if (ahc_linux_fallback(ahc, devinfo) != 0) { - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } /* @@ -2764,18 +2692,18 @@ } case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahc_linux_fallback(ahc, devinfo) != 0) { AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } /* @@ -2784,12 +2712,12 @@ */ targ->dv_state_retry = 0; } else if ((status & SS_ERRMASK) == EBUSY) - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_BUSY); if (targ->dv_state_retry < 10) break; /* FALLTHROUGH */ default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOW_DV) { ahc_print_devinfo(ahc, devinfo); @@ -2800,33 +2728,33 @@ } break; - case AHC_DV_STATE_TUR: + case AIC_DV_STATE_TUR: switch (status & SS_MASK) { case SS_NOP: - if ((targ->flags & AHC_BASIC_DV) != 0) { + if ((targ->flags & AIC_BASIC_DV) != 0) { ahc_linux_filter_inquiry(ahc, devinfo); AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_VERIFY); - } else if ((targ->flags & AHC_ENHANCED_DV) != 0) { - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_REBD); + AIC_DV_STATE_INQ_VERIFY); + } else if ((targ->flags & AIC_ENHANCED_DV) != 0) { + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_REBD); } else { - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); } break; case SS_RETRY: case SS_TUR: if ((status & SS_ERRMASK) == EBUSY) { - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_BUSY); break; } AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahc_linux_fallback(ahc, devinfo) != 0) { AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } /* @@ -2842,7 +2770,7 @@ printf("DV TUR reties exhausted\n"); } #endif - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } if (status & SSQ_DELAY) @@ -2850,25 +2778,25 @@ break; case SS_START: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_SU); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_SU); break; case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } break; - case AHC_DV_STATE_REBD: + case AIC_DV_STATE_REBD: switch (status & SS_MASK) { case SS_NOP: { uint32_t echo_size; - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_WEB); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_WEB); echo_size = scsi_3btoul(&targ->dv_buffer[1]); echo_size &= 0x1FFF; #ifdef AHC_DEBUG @@ -2878,7 +2806,17 @@ } #endif if (echo_size == 0) { - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + /* + * Fall back to basic DV. + */ + if (bootverbose) { + ahc_print_devinfo(ahc, devinfo); + printf("Echo Buffer unavailable. " + "Performing basic DV.\n"); + } + targ->flags &= ~AIC_ENHANCED_DV; + targ->flags |= AIC_BASIC_DV; + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_TUR); break; } @@ -2893,11 +2831,11 @@ } case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_RETRY: AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) targ->dv_state_retry--; if (targ->dv_state_retry <= 10) @@ -2916,30 +2854,30 @@ * and try level 1 DV. */ ahc_linux_filter_inquiry(ahc, devinfo); - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_VERIFY); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_INQ_VERIFY); targ->dv_echo_size = 0; break; } break; - case AHC_DV_STATE_WEB: + case AIC_DV_STATE_WEB: switch (status & SS_MASK) { case SS_NOP: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_REB); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_REB); break; case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_RETRY: AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahc_linux_fallback(ahc, devinfo) != 0) { AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } /* @@ -2958,22 +2896,22 @@ } #endif default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } break; - case AHC_DV_STATE_REB: + case AIC_DV_STATE_REB: switch (status & SS_MASK) { case SS_NOP: if (memcmp(targ->dv_buffer, targ->dv_buffer1, targ->dv_echo_size) != 0) { if (ahc_linux_fallback(ahc, devinfo) != 0) AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); else AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_WEB); + AIC_DV_STATE_WEB); break; } @@ -2985,24 +2923,24 @@ free(targ->dv_buffer1, M_DEVBUF); targ->dv_buffer1 = NULL; } - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_RETRY: AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if ((status & SSQ_FALLBACK) != 0) { if (ahc_linux_fallback(ahc, devinfo) != 0) { AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_EXIT); + AIC_DV_STATE_EXIT); break; } - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_WEB); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_WEB); } if (targ->dv_state_retry <= 10) { if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0) @@ -3017,35 +2955,35 @@ #endif /* FALLTHROUGH */ default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } break; - case AHC_DV_STATE_SU: + case AIC_DV_STATE_SU: switch (status & SS_MASK) { case SS_NOP: case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } break; - case AHC_DV_STATE_BUSY: + case AIC_DV_STATE_BUSY: switch (status & SS_MASK) { case SS_NOP: case SS_INQ_REFRESH: AHC_SET_DV_STATE(ahc, targ, - AHC_DV_STATE_INQ_SHORT_ASYNC); + AIC_DV_STATE_INQ_SHORT_ASYNC); break; case SS_TUR: case SS_RETRY: AHC_SET_DV_STATE(ahc, targ, targ->dv_state); - if (ahc_cmd_get_transaction_status(cmd) + if (aic_cmd_get_transaction_status(cmd) == CAM_REQUEUE_REQ) { targ->dv_state_retry--; } else if (targ->dv_state_retry < 60) { @@ -3058,11 +2996,11 @@ printf("DV BUSY reties exhausted\n"); } #endif - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); } break; default: - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } break; @@ -3070,7 +3008,7 @@ default: printf("%s: Invalid DV completion state %d\n", ahc_name(ahc), targ->dv_state); - AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT); + AHC_SET_DV_STATE(ahc, targ, AIC_DV_STATE_EXIT); break; } } @@ -3090,7 +3028,7 @@ */ static void ahc_linux_dv_inq(struct ahc_softc *ahc, struct scsi_cmnd *cmd, - struct ahc_devinfo *devinfo, struct ahc_linux_target *targ, + struct ahc_devinfo *devinfo, struct aic_linux_target *targ, u_int request_length) { @@ -3103,7 +3041,7 @@ if (targ->inq_data == NULL) targ->inq_data = malloc(AHC_LINUX_DV_INQ_LEN, M_DEVBUF, M_WAITOK); - if (targ->dv_state > AHC_DV_STATE_INQ_ASYNC) { + if (targ->dv_state > AIC_DV_STATE_INQ_ASYNC) { if (targ->dv_buffer != NULL) free(targ->dv_buffer, M_DEVBUF); targ->dv_buffer = malloc(AHC_LINUX_DV_INQ_LEN, @@ -3116,7 +3054,7 @@ cmd->cmnd[0] = INQUIRY; cmd->cmnd[4] = request_length; cmd->request_bufflen = request_length; - if (targ->dv_state > AHC_DV_STATE_INQ_ASYNC) + if (targ->dv_state > AIC_DV_STATE_INQ_ASYNC) cmd->request_buffer = targ->dv_buffer; else cmd->request_buffer = targ->inq_data; @@ -3145,7 +3083,7 @@ static void ahc_linux_dv_rebd(struct ahc_softc *ahc, struct scsi_cmnd *cmd, - struct ahc_devinfo *devinfo, struct ahc_linux_target *targ) + struct ahc_devinfo *devinfo, struct aic_linux_target *targ) { #ifdef AHC_DEBUG @@ -3170,7 +3108,7 @@ static void ahc_linux_dv_web(struct ahc_softc *ahc, struct scsi_cmnd *cmd, - struct ahc_devinfo *devinfo, struct ahc_linux_target *targ) + struct ahc_devinfo *devinfo, struct aic_linux_target *targ) { #ifdef AHC_DEBUG @@ -3192,7 +3130,7 @@ static void ahc_linux_dv_reb(struct ahc_softc *ahc, struct scsi_cmnd *cmd, - struct ahc_devinfo *devinfo, struct ahc_linux_target *targ) + struct ahc_devinfo *devinfo, struct aic_linux_target *targ) { #ifdef AHC_DEBUG @@ -3215,7 +3153,7 @@ static void ahc_linux_dv_su(struct ahc_softc *ahc, struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, - struct ahc_linux_target *targ) + struct aic_linux_target *targ) { u_int le; @@ -3237,7 +3175,7 @@ static int ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) { - struct ahc_linux_target *targ; + struct aic_linux_target *targ; struct ahc_initiator_tinfo *tinfo; struct ahc_transinfo *goal; struct ahc_tmode_tstate *tstate; @@ -3416,7 +3354,7 @@ return (0); } -static void +void ahc_linux_dv_timeout(struct scsi_cmnd *cmd) { struct ahc_softc *ahc; @@ -3450,29 +3388,19 @@ * error code. */ if ((scb->flags & SCB_SENSE) != 0) - ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); + aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL); else - ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); ahc_reset_channel(ahc, cmd->device->channel + 'A', /*initiate*/TRUE); - /* - * Add a minimal bus settle delay for devices that are slow to - * respond after bus resets. - */ - ahc_linux_freeze_simq(ahc); - init_timer(&ahc->platform_data->reset_timer); - ahc->platform_data->reset_timer.data = (u_long)ahc; - ahc->platform_data->reset_timer.expires = jiffies + HZ / 2; - ahc->platform_data->reset_timer.function = - (ahc_linux_callback_t *)ahc_linux_release_simq; - add_timer(&ahc->platform_data->reset_timer); - if (ahc_linux_next_device_to_run(ahc) != NULL) - ahc_schedule_runq(ahc); + if (aic_linux_next_device_to_run(ahc) != NULL) + aic_schedule_runq(ahc); + ahc_linux_run_complete_queue(ahc); ahc_unlock(ahc, &flags); } -static void +void ahc_linux_dv_complete(struct scsi_cmnd *cmd) { struct ahc_softc *ahc; @@ -3494,7 +3422,7 @@ } static void -ahc_linux_generate_dv_pattern(struct ahc_linux_target *targ) +ahc_linux_generate_dv_pattern(struct aic_linux_target *targ) { uint16_t b; u_int i; @@ -3626,8 +3554,8 @@ * Determines the queue depth for a given device. */ static void -ahc_linux_device_queue_depth(struct ahc_softc *ahc, - struct ahc_linux_device *dev) +aic_linux_device_queue_depth(struct ahc_softc *ahc, + struct aic_linux_device *dev) { struct ahc_devinfo devinfo; u_int tags; @@ -3651,10 +3579,10 @@ } } -static void -ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev) +void +ahc_linux_run_device_queue(struct ahc_softc *ahc, struct aic_linux_device *dev) { - struct ahc_cmd *acmd; + struct aic_cmd *acmd; struct scsi_cmnd *cmd; struct scb *scb; struct hardware_scb *hscb; @@ -3662,7 +3590,7 @@ struct ahc_tmode_tstate *tstate; uint16_t mask; - if ((dev->flags & AHC_DEV_ON_RUN_LIST) != 0) + if ((dev->flags & AIC_DEV_ON_RUN_LIST) != 0) panic("running device on run list"); while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL @@ -3673,10 +3601,10 @@ * running is because the whole controller Q is frozen. */ if (ahc->platform_data->qfrozen != 0 - && AHC_DV_SIMQ_FROZEN(ahc) == 0) { + && AIC_DV_SIMQ_FROZEN(ahc) == 0) { TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; + dev->flags |= AIC_DEV_ON_RUN_LIST; return; } /* @@ -3685,14 +3613,16 @@ if ((scb = ahc_get_scb(ahc)) == NULL) { TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; - ahc->flags |= AHC_RESOURCE_SHORTAGE; + dev->flags |= AIC_DEV_ON_RUN_LIST; + ahc->flags |= AIC_RESOURCE_SHORTAGE; + ahc->platform_data->qfrozen++; return; } TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe); cmd = &acmd_scsi_cmd(acmd); scb->io_ctx = cmd; scb->platform_data->dev = dev; + scb->platform_data->flags = 0; hscb = scb->hscb; cmd->host_scribble = (char *)scb; @@ -3714,15 +3644,37 @@ if ((ahc->user_discenable & mask) != 0) hscb->control |= DISCENB; - if (AHC_DV_CMD(cmd) != 0) + if (AIC_DV_CMD(cmd) != 0) scb->flags |= SCB_SILENT; if ((tstate->auto_negotiate & mask) != 0) { scb->flags |= SCB_AUTO_NEGOTIATE; scb->hscb->control |= MK_MESSAGE; + } else if (cmd->cmnd[0] == INQUIRY + && (tinfo->curr.offset != 0 + || tinfo->curr.width != MSG_EXT_WDTR_BUS_8_BIT)) { + /* + * The SCSI spec requires inquiry + * commands to complete without + * reporting unit attention conditions. + * Because of this, an inquiry command + * that occurs just after a device is + * reset will result in a data phase + * with mismatched negotiated rates. + * The core already forces a renegotiation + * for reset events that are visible to + * our controller or that we initiate, + * but a third party device reset or a + * hot-plug insertion can still cause this + * issue. Therefore, we force a re-negotiation + * for every inquiry command unless we + * are async. + */ + scb->flags |= SCB_NEGOTIATE; + scb->hscb->control |= MK_MESSAGE; } - if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) { + if ((dev->flags & (AIC_DEV_Q_TAGGED|AIC_DEV_Q_BASIC)) != 0) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) int msg_bytes; uint8_t tag_msgs[2]; @@ -3734,8 +3686,8 @@ dev->commands_since_idle_or_otag = 0; } else #endif - if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH - && (dev->flags & AHC_DEV_Q_TAGGED) != 0) { + if (dev->commands_since_idle_or_otag == AIC_OTAG_THRESH + && (dev->flags & AIC_DEV_Q_TAGGED) != 0) { hscb->control |= MSG_ORDERED_TASK; dev->commands_since_idle_or_otag = 0; } else { @@ -3752,8 +3704,8 @@ } scb->platform_data->xfer_len = 0; - ahc_set_residual(scb, 0); - ahc_set_sense_residual(scb, 0); + aic_set_residual(scb, 0); + aic_set_sense_residual(scb, 0); scb->sg_count = 0; if (cmd->use_sg != 0) { struct ahc_dma_seg *sg; @@ -3762,7 +3714,7 @@ int nseg; cur_seg = (struct scatterlist *)cmd->request_buffer; - nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg, + nseg = aic_map_sg(ahc, cur_seg, cmd->use_sg, scsi_to_pci_dma_dir(cmd->sc_data_direction)); end_seg = cur_seg + nseg; /* Copy the segments into the SG list. */ @@ -3785,13 +3737,13 @@ cur_seg++; } sg--; - sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); + sg->len |= aic_htole32(AHC_DMA_LAST_SEG); /* * Reset the sg list pointer. */ scb->hscb->sgptr = - ahc_htole32(scb->sg_list_phys | SG_FULL_RESID); + aic_htole32(scb->sg_list_phys | SG_FULL_RESID); /* * Copy the first SG into the "current" @@ -3804,7 +3756,7 @@ bus_addr_t addr; sg = scb->sg_list; - addr = pci_map_single(ahc->dev_softc, + addr = aic_map_single(ahc, cmd->request_buffer, cmd->request_bufflen, scsi_to_pci_dma_dir(cmd->sc_data_direction)); @@ -3812,13 +3764,13 @@ scb->sg_count = ahc_linux_map_seg(ahc, scb, sg, addr, cmd->request_bufflen); - sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); + sg->len |= aic_htole32(AHC_DMA_LAST_SEG); /* * Reset the sg list pointer. */ scb->hscb->sgptr = - ahc_htole32(scb->sg_list_phys | SG_FULL_RESID); + aic_htole32(scb->sg_list_phys | SG_FULL_RESID); /* * Copy the first SG into the "current" @@ -3827,7 +3779,7 @@ scb->hscb->dataptr = sg->addr; scb->hscb->datacnt = sg->len; } else { - scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL); + scb->hscb->sgptr = aic_htole32(SG_LIST_NULL); scb->hscb->dataptr = 0; scb->hscb->datacnt = 0; scb->sg_count = 0; @@ -3838,7 +3790,7 @@ dev->openings--; dev->active++; dev->commands_issued++; - if ((dev->flags & AHC_DEV_PERIODIC_OTAG) != 0) + if ((dev->flags & AIC_DEV_PERIODIC_OTAG) != 0) dev->commands_since_idle_or_otag++; /* @@ -3860,6 +3812,7 @@ continue; } scb->flags |= SCB_ACTIVE; + aic_scb_timer_start(scb); ahc_queue_scb(ahc, scb); } } @@ -3877,8 +3830,8 @@ ahc = (struct ahc_softc *) dev_id; ahc_lock(ahc, &flags); ours = ahc_intr(ahc); - if (ahc_linux_next_device_to_run(ahc) != NULL) - ahc_schedule_runq(ahc); + if (aic_linux_next_device_to_run(ahc) != NULL) + aic_schedule_runq(ahc); ahc_linux_run_complete_queue(ahc); ahc_unlock(ahc, &flags); return IRQ_RETVAL(ours); @@ -3892,10 +3845,10 @@ ; } -static struct ahc_linux_target* +static struct aic_linux_target* ahc_linux_alloc_target(struct ahc_softc *ahc, u_int channel, u_int target) { - struct ahc_linux_target *targ; + struct aic_linux_target *targ; u_int target_offset; target_offset = target; @@ -3908,14 +3861,14 @@ memset(targ, 0, sizeof(*targ)); targ->channel = channel; targ->target = target; - targ->ahc = ahc; - targ->flags = AHC_DV_REQUIRED; + targ->softc = ahc; + targ->flags = AIC_DV_REQUIRED; ahc->platform_data->targets[target_offset] = targ; return (targ); } static void -ahc_linux_free_target(struct ahc_softc *ahc, struct ahc_linux_target *targ) +ahc_linux_free_target(struct ahc_softc *ahc, struct aic_linux_target *targ) { struct ahc_devinfo devinfo; struct ahc_initiator_tinfo *tinfo; @@ -3955,11 +3908,11 @@ free(targ, M_DEVBUF); } -static struct ahc_linux_device* +static struct aic_linux_device* ahc_linux_alloc_device(struct ahc_softc *ahc, - struct ahc_linux_target *targ, u_int lun) + struct aic_linux_target *targ, u_int lun) { - struct ahc_linux_device *dev; + struct aic_linux_device *dev; dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT); if (dev == NULL) @@ -3967,7 +3920,7 @@ memset(dev, 0, sizeof(*dev)); init_timer(&dev->timer); TAILQ_INIT(&dev->busyq); - dev->flags = AHC_DEV_UNCONFIGURED; + dev->flags = AIC_DEV_UNCONFIGURED; dev->lun = lun; dev->target = targ; @@ -3990,17 +3943,17 @@ } static void -ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev) +ahc_linux_free_device(struct ahc_softc *ahc, struct aic_linux_device *dev) { - struct ahc_linux_target *targ; + struct aic_linux_target *targ; - del_timer_sync(&dev->timer); + del_timer(&dev->timer); targ = dev->target; targ->devices[dev->lun] = NULL; free(dev, M_DEVBUF); targ->refcount--; if (targ->refcount == 0 - && (targ->flags & AHC_DV_REQUIRED) == 0) + && (targ->flags & AIC_DV_REQUIRED) == 0) ahc_linux_free_target(ahc, targ); } @@ -4012,7 +3965,7 @@ case AC_TRANSFER_NEG: { char buf[80]; - struct ahc_linux_target *targ; + struct aic_linux_target *targ; struct info_str info; struct ahc_initiator_tinfo *tinfo; struct ahc_tmode_tstate *tstate; @@ -4079,7 +4032,7 @@ WARN_ON(lun != CAM_LUN_WILDCARD); scsi_report_device_reset(ahc->platform_data->host, channel - 'A', target); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) Scsi_Device *scsi_dev; /* @@ -4100,12 +4053,24 @@ break; } case AC_BUS_RESET: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) if (ahc->platform_data->host != NULL) { scsi_report_bus_reset(ahc->platform_data->host, channel - 'A'); } -#endif + /* + * Add a minimal bus settle delay for devices that are slow to + * respond after bus resets. + */ + if ((ahc->platform_data->flags & AIC_BUS_SETTLE_TIMER) == 0) { + aic_freeze_simq(ahc); + ahc->platform_data->flags |= AIC_BUS_SETTLE_TIMER; + ahc->platform_data->bus_settle_timer.expires = + jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000; + add_timer(&ahc->platform_data->bus_settle_timer); + } else { + mod_timer(&ahc->platform_data->bus_settle_timer, + jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000); + } break; default: panic("ahc_send_async: Unexpected async event"); @@ -4119,9 +4084,11 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) { Scsi_Cmnd *cmd; - struct ahc_linux_device *dev; + struct aic_linux_device *dev; LIST_REMOVE(scb, pending_links); + if ((scb->flags & SCB_TIMEDOUT) != 0) + LIST_REMOVE(scb, timedout_links); if ((scb->flags & SCB_UNTAGGEDQ) != 0) { struct scb_tailq *untagged_q; int target_offset; @@ -4130,13 +4097,17 @@ untagged_q = &(ahc->untagged_queues[target_offset]); TAILQ_REMOVE(untagged_q, scb, links.tqe); ahc_run_untagged_queue(ahc, untagged_q); - } - - if ((scb->flags & SCB_ACTIVE) == 0) { + } else if ((scb->flags & SCB_ACTIVE) == 0) { + /* + * Transactions aborted from the untagged queue may + * not have been dispatched to the controller, so + * only check the SCB_ACTIVE flag for tagged transactions. + */ printf("SCB %d done'd twice\n", scb->hscb->tag); ahc_dump_card_state(ahc); panic("Stopping for safety"); } + cmd = scb->io_ctx; dev = scb->platform_data->dev; dev->active--; @@ -4154,11 +4125,11 @@ * the sense buffer looks "sane". */ cmd->sense_buffer[0] = 0; - if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) { + if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) { uint32_t amount_xferred; amount_xferred = - ahc_get_transfer_length(scb) - ahc_get_residual(scb); + aic_get_transfer_length(scb) - aic_get_residual(scb); if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) { #ifdef AHC_DEBUG if ((ahc_debug & AHC_SHOW_MISC) != 0) { @@ -4166,7 +4137,17 @@ printf("Set CAM_UNCOR_PARITY\n"); } #endif - ahc_set_transaction_status(scb, CAM_UNCOR_PARITY); + aic_set_transaction_status(scb, CAM_UNCOR_PARITY); +#ifdef AHC_REPORT_UNDERFLOWS + /* + * This code is disabled by default as some + * clients of the SCSI system do not properly + * initialize the underflow parameter. This + * results in spurious termination of commands + * that complete as expected (e.g. underflow is + * allowed as command can return variable amounts + * of data. + */ } else if (amount_xferred < scb->io_ctx->underflow) { u_int i; @@ -4178,30 +4159,31 @@ ahc_print_path(ahc, scb); printf("Saw underflow (%ld of %ld bytes). " "Treated as error\n", - ahc_get_residual(scb), - ahc_get_transfer_length(scb)); - ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR); + aic_get_residual(scb), + aic_get_transfer_length(scb)); + aic_set_transaction_status(scb, CAM_DATA_RUN_ERR); +#endif } else { - ahc_set_transaction_status(scb, CAM_REQ_CMP); + aic_set_transaction_status(scb, CAM_REQ_CMP); } - } else if (ahc_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { + } else if (aic_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { ahc_linux_handle_scsi_status(ahc, dev, scb); - } else if (ahc_get_transaction_status(scb) == CAM_SEL_TIMEOUT) { - dev->flags |= AHC_DEV_UNCONFIGURED; - if (AHC_DV_CMD(cmd) == FALSE) - dev->target->flags &= ~AHC_DV_REQUIRED; + } else if (aic_get_transaction_status(scb) == CAM_SEL_TIMEOUT) { + dev->flags |= AIC_DEV_UNCONFIGURED; + if (AIC_DV_CMD(cmd) == FALSE) + dev->target->flags &= ~AIC_DV_REQUIRED; } /* * Start DV for devices that require it assuming the first command * sent does not result in a selection timeout. */ - if (ahc_get_transaction_status(scb) != CAM_SEL_TIMEOUT - && (dev->target->flags & AHC_DV_REQUIRED) != 0) + if (aic_get_transaction_status(scb) != CAM_SEL_TIMEOUT + && (dev->target->flags & AIC_DV_REQUIRED) != 0) ahc_linux_start_dv(ahc); if (dev->openings == 1 - && ahc_get_transaction_status(scb) == CAM_REQ_CMP - && ahc_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL) + && aic_get_transaction_status(scb) == CAM_REQ_CMP + && aic_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL) dev->tag_success_count++; /* * Some devices deal with temporary internal resource @@ -4210,7 +4192,7 @@ * back to our previous queue depth. */ if ((dev->openings + dev->active) < dev->maxtags - && dev->tag_success_count > AHC_TAG_SUCCESS_INTERVAL) { + && dev->tag_success_count > AIC_TAG_SUCCESS_INTERVAL) { dev->tag_success_count = 0; dev->openings++; } @@ -4219,32 +4201,61 @@ dev->commands_since_idle_or_otag = 0; if (TAILQ_EMPTY(&dev->busyq)) { - if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0 - && dev->active == 0 - && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0) + if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0 + && dev->active == 0) ahc_linux_free_device(ahc, dev); - } else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) { + } else if ((dev->flags & AIC_DEV_ON_RUN_LIST) == 0) { TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; + dev->flags |= AIC_DEV_ON_RUN_LIST; } if ((scb->flags & SCB_RECOVERY_SCB) != 0) { printf("Recovery SCB completes\n"); - if (ahc_get_transaction_status(scb) == CAM_BDR_SENT - || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED) - ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); - if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) { - ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE; + if (aic_get_transaction_status(scb) == CAM_BDR_SENT + || aic_get_transaction_status(scb) == CAM_REQ_ABORTED) + aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); + if ((scb->platform_data->flags & AIC_SCB_UP_EH_SEM) != 0) { + scb->platform_data->flags &= ~AIC_SCB_UP_EH_SEM; up(&ahc->platform_data->eh_sem); + } else { + struct scb *list_scb; + + /* + * We were able to complete the command successfully, + * so reinstate the timeouts for all other pending + * commands. + */ + LIST_FOREACH(list_scb, + &ahc->pending_scbs, pending_links) { + + aic_scb_timer_start(list_scb); + } } } + if ((scb->platform_data->flags & AIC_TIMEOUT_ACTIVE) == 0) { + /* + * The completion handler believes that + * commands without active timers running + * have lost the race of completing before + * their timer expires. Since commands in + * our busy queues do not have timers running, + * appease the mid-layer by adding a timer + * now. This timer will be immediately + * canceled by the midlayer. + */ + scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout); + } + + if ((scb->platform_data->flags & AIC_RELEASE_SIMQ) != 0) + aic_release_simq_locked(ahc); + ahc_free_scb(ahc, scb); ahc_linux_queue_cmd_complete(ahc, cmd); - if ((ahc->platform_data->flags & AHC_DV_WAIT_SIMQ_EMPTY) != 0 + if ((ahc->platform_data->flags & AIC_DV_WAIT_SIMQ_EMPTY) != 0 && LIST_FIRST(&ahc->pending_scbs) == NULL) { - ahc->platform_data->flags &= ~AHC_DV_WAIT_SIMQ_EMPTY; + ahc->platform_data->flags &= ~AIC_DV_WAIT_SIMQ_EMPTY; up(&ahc->platform_data->dv_sem); } @@ -4252,7 +4263,7 @@ static void ahc_linux_handle_scsi_status(struct ahc_softc *ahc, - struct ahc_linux_device *dev, struct scb *scb) + struct aic_linux_device *dev, struct scb *scb) { struct ahc_devinfo devinfo; @@ -4272,7 +4283,7 @@ * we don't clobber the device with too many * commands. */ - switch (ahc_get_scsi_status(scb)) { + switch (aic_get_scsi_status(scb)) { default: break; case SCSI_STATUS_CHECK_COND: @@ -4286,13 +4297,15 @@ */ cmd = scb->io_ctx; if (scb->flags & SCB_SENSE) { - u_int sense_size; + struct scsi_sense_data *sense; + u_int sense_size; + int error_code, sense_key, asc, ascq; + sense = ahc_get_sense_buf(ahc, scb); sense_size = MIN(sizeof(struct scsi_sense_data) - - ahc_get_sense_residual(scb), + - aic_get_sense_residual(scb), sizeof(cmd->sense_buffer)); - memcpy(cmd->sense_buffer, - ahc_get_sense_buf(ahc, scb), sense_size); + memcpy(cmd->sense_buffer, sense, sense_size); if (sense_size < sizeof(cmd->sense_buffer)) memset(&cmd->sense_buffer[sense_size], 0, sizeof(cmd->sense_buffer) - sense_size); @@ -4311,6 +4324,23 @@ printf("\n"); } #endif + /* + * If this is not a DV command and the target + * provides some status that makes us believe + * that the target has changed (power on reset, + * etc.) kick off a DV scan to re-validate the + * device. + */ + if (AIC_DV_CMD(cmd) != 0) + break; + + scsi_extract_sense(sense, &error_code, + &sense_key, &asc, &ascq); + if (error_code == SSD_CURRENT_ERROR + && sense_key == SSD_KEY_UNIT_ATTENTION + && asc == 0x29 + && (ascq == 0 || ascq == 1)) + dev->target->flags |= AIC_DV_REQUIRED; } break; } @@ -4347,7 +4377,7 @@ * this device. */ if (dev->last_queuefull_same_count - == AHC_LOCK_TAGS_COUNT) { + == AIC_LOCK_TAGS_COUNT) { dev->maxtags = dev->active; ahc_print_path(ahc, scb); printf("Locking max tag count at %d\n", @@ -4357,10 +4387,10 @@ dev->tags_on_last_queuefull = dev->active; dev->last_queuefull_same_count = 0; } - ahc_set_transaction_status(scb, CAM_REQUEUE_REQ); - ahc_set_scsi_status(scb, SCSI_STATUS_OK); + aic_set_transaction_status(scb, CAM_REQUEUE_REQ); + aic_set_scsi_status(scb, SCSI_STATUS_OK); ahc_platform_set_tags(ahc, &devinfo, - (dev->flags & AHC_DEV_Q_BASIC) + (dev->flags & AIC_DEV_Q_BASIC) ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED); break; } @@ -4369,9 +4399,9 @@ * as if the target returned BUSY SCSI status. */ dev->openings = 1; - ahc_set_scsi_status(scb, SCSI_STATUS_BUSY); + aic_set_scsi_status(scb, SCSI_STATUS_BUSY); ahc_platform_set_tags(ahc, &devinfo, - (dev->flags & AHC_DEV_Q_BASIC) + (dev->flags & AIC_DEV_Q_BASIC) ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED); /* FALLTHROUGH */ } @@ -4381,13 +4411,13 @@ * Set a short timer to defer sending commands for * a bit since Linux will not delay in this case. */ - if ((dev->flags & AHC_DEV_TIMER_ACTIVE) != 0) { + if ((dev->flags & AIC_DEV_TIMER_ACTIVE) != 0) { printf("%s:%c:%d: Device Timer still active during " "busy processing\n", ahc_name(ahc), dev->target->channel, dev->target->target); break; } - dev->flags |= AHC_DEV_TIMER_ACTIVE; + dev->flags |= AIC_DEV_TIMER_ACTIVE; dev->qfrozen++; init_timer(&dev->timer); dev->timer.data = (u_long)dev; @@ -4414,9 +4444,9 @@ * not guarantee the order that aborted commands will be * returned to us. */ - struct ahc_completeq *completeq; - struct ahc_cmd *list_cmd; - struct ahc_cmd *acmd; + struct aic_completeq *completeq; + struct aic_cmd *list_cmd; + struct aic_cmd *acmd; /* * Map CAM error codes into Linux Error codes. We @@ -4424,10 +4454,10 @@ * full error information available when making * state change decisions. */ - if (AHC_DV_CMD(cmd) == FALSE) { + if (AIC_DV_CMD(cmd) == FALSE) { u_int new_status; - switch (ahc_cmd_get_transaction_status(cmd)) { + switch (aic_cmd_get_transaction_status(cmd)) { case CAM_REQ_INPROG: case CAM_REQ_CMP: case CAM_SCSI_STATUS_ERROR: @@ -4454,7 +4484,17 @@ new_status = DID_PARITY; break; case CAM_CMD_TIMEOUT: - new_status = DID_TIME_OUT; + /* + * Returning DID_TIME_OUT will + * wake up the error recovery + * thread instead of doing the + * command retry we desire. Since + * we have already recovered the + * command, returning DID_ERROR + * will cause a retry up to the + * retry limit for this command. + */ + new_status = DID_ERROR; break; case CAM_UA_ABORT: case CAM_REQ_CMP_ERR: @@ -4484,7 +4524,7 @@ if (cmd->retries > 0) cmd->retries--; new_status = DID_OK; - ahc_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND); + aic_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND); cmd->result |= (DRIVER_SENSE << 24); memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); @@ -4498,12 +4538,21 @@ break; } - ahc_cmd_set_transaction_status(cmd, new_status); + aic_cmd_set_transaction_status(cmd, new_status); + } + + /* + * Commands that have completed successfully + * can be completed to the OS immediately. + */ + if (cmd->result == (DID_OK << 16)) { + cmd->scsi_done(cmd); + return; } completeq = &ahc->platform_data->completeq; list_cmd = TAILQ_FIRST(completeq); - acmd = (struct ahc_cmd *)cmd; + acmd = (struct aic_cmd *)cmd; while (list_cmd != NULL && acmd_scsi_cmd(list_cmd).serial_number < acmd_scsi_cmd(acmd).serial_number) @@ -4524,7 +4573,7 @@ struct ahc_transinfo *curr; struct ahc_tmode_tstate *tstate; struct ahc_syncrate *syncrate; - struct ahc_linux_device *dev; + struct aic_linux_device *dev; u_int maxsync; u_int width; u_int period; @@ -4547,9 +4596,9 @@ sid = (struct scsi_inquiry_data *)dev->target->inq_data; if (SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) { - dev->flags &= ~AHC_DEV_UNCONFIGURED; + dev->flags &= ~AIC_DEV_UNCONFIGURED; } else { - dev->flags |= AHC_DEV_UNCONFIGURED; + dev->flags |= AIC_DEV_UNCONFIGURED; return; } @@ -4626,82 +4675,38 @@ static void ahc_linux_sem_timeout(u_long arg) { + struct scb *scb; struct ahc_softc *ahc; u_long s; - ahc = (struct ahc_softc *)arg; - + scb = (struct scb *)arg; + ahc = scb->ahc_softc; ahc_lock(ahc, &s); - if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) { - ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE; + if ((scb->platform_data->flags & AIC_SCB_UP_EH_SEM) != 0) { + scb->platform_data->flags &= ~AIC_SCB_UP_EH_SEM; up(&ahc->platform_data->eh_sem); } ahc_unlock(ahc, &s); } static void -ahc_linux_freeze_simq(struct ahc_softc *ahc) -{ - ahc->platform_data->qfrozen++; - if (ahc->platform_data->qfrozen == 1) { - scsi_block_requests(ahc->platform_data->host); - - /* XXX What about Twin channels? */ - ahc_platform_abort_scbs(ahc, CAM_TARGET_WILDCARD, ALL_CHANNELS, - CAM_LUN_WILDCARD, SCB_LIST_NULL, - ROLE_INITIATOR, CAM_REQUEUE_REQ); - } -} - -static void -ahc_linux_release_simq(u_long arg) -{ - struct ahc_softc *ahc; - u_long s; - int unblock_reqs; - - ahc = (struct ahc_softc *)arg; - - unblock_reqs = 0; - ahc_lock(ahc, &s); - if (ahc->platform_data->qfrozen > 0) - ahc->platform_data->qfrozen--; - if (ahc->platform_data->qfrozen == 0) - unblock_reqs = 1; - if (AHC_DV_SIMQ_FROZEN(ahc) - && ((ahc->platform_data->flags & AHC_DV_WAIT_SIMQ_RELEASE) != 0)) { - ahc->platform_data->flags &= ~AHC_DV_WAIT_SIMQ_RELEASE; - up(&ahc->platform_data->dv_sem); - } - ahc_schedule_runq(ahc); - ahc_unlock(ahc, &s); - /* - * There is still a race here. The mid-layer - * should keep its own freeze count and use - * a bottom half handler to run the queues - * so we can unblock with our own lock held. - */ - if (unblock_reqs) - scsi_unblock_requests(ahc->platform_data->host); -} - -static void ahc_linux_dev_timed_unfreeze(u_long arg) { - struct ahc_linux_device *dev; + struct aic_linux_device *dev; struct ahc_softc *ahc; u_long s; - dev = (struct ahc_linux_device *)arg; - ahc = dev->target->ahc; + dev = (struct aic_linux_device *)arg; + ahc = dev->target->softc; ahc_lock(ahc, &s); - dev->flags &= ~AHC_DEV_TIMER_ACTIVE; + dev->flags &= ~AIC_DEV_TIMER_ACTIVE; if (dev->qfrozen > 0) dev->qfrozen--; if (dev->qfrozen == 0 - && (dev->flags & AHC_DEV_ON_RUN_LIST) == 0) + && (dev->flags & AIC_DEV_ON_RUN_LIST) == 0) ahc_linux_run_device_queue(ahc, dev); - if (TAILQ_EMPTY(&dev->busyq) + if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0 + && TAILQ_EMPTY(&dev->busyq) && dev->active == 0) ahc_linux_free_device(ahc, dev); ahc_unlock(ahc, &s); @@ -4711,9 +4716,9 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag) { struct ahc_softc *ahc; - struct ahc_cmd *acmd; - struct ahc_cmd *list_acmd; - struct ahc_linux_device *dev; + struct aic_cmd *acmd; + struct aic_cmd *list_acmd; + struct aic_linux_device *dev; struct scb *pending_scb; u_long s; u_int saved_scbptr; @@ -4731,7 +4736,7 @@ paused = FALSE; wait = FALSE; ahc = *(struct ahc_softc **)cmd->device->host->hostdata; - acmd = (struct ahc_cmd *)cmd; + acmd = (struct aic_cmd *)cmd; printf("%s:%d:%d:%d: Attempting to queue a%s message\n", ahc_name(ahc), cmd->device->channel, @@ -4757,7 +4762,7 @@ * by acquiring either the io_request_lock or our own * lock, this *should* be safe. */ - ahc_midlayer_entrypoint_lock(ahc, &s); + ahc_entrypoint_lock(ahc, &s); /* * First determine if we currently own this command. @@ -4793,13 +4798,24 @@ if (flag == SCB_ABORT) { TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe); cmd->result = DID_ABORT << 16; + /* + * The completion handler believes that + * commands without active timers running + * have lost the race of completing before + * their timer expires. Since commands in our + * busy queues do not have timers running, + * appease the mid-layer by adding a timer + * now. This timer will be immediately + * canceled by the midlayer. + */ + scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout); ahc_linux_queue_cmd_complete(ahc, cmd); retval = SUCCESS; goto done; } } - if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0 + if ((dev->flags & (AIC_DEV_Q_BASIC|AIC_DEV_Q_TAGGED)) == 0 && ahc_search_untagged_queues(ahc, cmd, cmd->device->id, cmd->device->channel + 'A', cmd->device->lun, @@ -5015,10 +5031,10 @@ struct timer_list timer; int ret; - ahc->platform_data->flags |= AHC_UP_EH_SEMAPHORE; + pending_scb->platform_data->flags |= AIC_SCB_UP_EH_SEM; spin_unlock_irq(&ahc->platform_data->spin_lock); init_timer(&timer); - timer.data = (u_long)ahc; + timer.data = (u_long)pending_scb; timer.expires = jiffies + (5 * HZ); timer.function = ahc_linux_sem_timeout; add_timer(&timer); @@ -5032,16 +5048,17 @@ } spin_lock_irq(&ahc->platform_data->spin_lock); } - ahc_schedule_runq(ahc); + aic_schedule_runq(ahc); ahc_linux_run_complete_queue(ahc); - ahc_midlayer_entrypoint_unlock(ahc, &s); + ahc_entrypoint_unlock(ahc, &s); return (retval); } void ahc_platform_dump_card_state(struct ahc_softc *ahc) { - struct ahc_linux_device *dev; + struct Scsi_Host *host; + struct aic_linux_device *dev; int channel; int maxchannel; int target; @@ -5049,6 +5066,14 @@ int lun; int i; + host = ahc->platform_data->host; + printf("%s: Host Status: Failed(%d) %s%s%s\n", + ahc_name(ahc), + host->host_failed, + host->eh_active ? "eh_active " : "", + host->host_blocked ? "host_blocked " : "", + host->host_self_blocked ? "host_self_blocked " : ""); + maxchannel = (ahc->features & AHC_TWIN) ? 1 : 0; maxtarget = (ahc->features & AHC_WIDE) ? 15 : 7; for (channel = 0; channel <= maxchannel; channel++) { @@ -5056,7 +5081,7 @@ for (target = 0; target <=maxtarget; target++) { for (lun = 0; lun < AHC_NUM_LUNS; lun++) { - struct ahc_cmd *acmd; + struct aic_cmd *acmd; dev = ahc_linux_get_device(ahc, channel, target, lun, /*alloc*/FALSE); @@ -5080,38 +5105,46 @@ static int __init ahc_linux_init(void) { + int found; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - return (ahc_linux_detect(&aic7xxx_driver_template) ? 0 : -ENODEV); + found = ahc_linux_detect(&aic7xxx_driver_template); #else scsi_register_module(MODULE_SCSI_HA, &aic7xxx_driver_template); - if (aic7xxx_driver_template.present == 0) { - scsi_unregister_module(MODULE_SCSI_HA, - &aic7xxx_driver_template); - return (-ENODEV); - } - - return (0); + found = aic7xxx_driver_template.present; +#endif +#ifdef MODULE + if (found == 0) + ahc_init_status = -ENODEV; #endif + if (ahc_init_status != 0) { + /* + * Linux will not call our exit + * routine if we fail to load. + * Force cleanup if initialization + * is not successful. + */ + ahc_linux_exit(); + } + return (ahc_init_status); } -static void __exit +static void ahc_linux_exit(void) { struct ahc_softc *ahc; - u_long l; /* - * Shutdown DV threads before going into the SCSI mid-layer. + * Shutdown our threads before going into the SCSI mid-layer. * This avoids situations where the mid-layer locks the entire * kernel so that waiting for our DV threads to exit leads * to deadlock. */ - ahc_list_lock(&l); TAILQ_FOREACH(ahc, &ahc_tailq, links) { ahc_linux_kill_dv_thread(ahc); + ahc_terminate_recovery_thread(ahc); } - ahc_list_unlock(&l); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_osm.h linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_osm.h --- linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_osm.h Sat Feb 7 17:03:30 2004 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_osm.h Tue Feb 10 01:47:06 2004 @@ -53,51 +53,22 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#150 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#169 $ * */ #ifndef _AIC7XXX_LINUX_H_ #define _AIC7XXX_LINUX_H_ -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #ifndef KERNEL_VERSION #define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -#include /* For tasklet support. */ #include -#include -#else -#include -#endif - -/* Core SCSI definitions */ -#define AIC_LIB_PREFIX ahc -#include "scsi.h" -#include "hosts.h" - -/* Name space conflict with BSD queue macros */ -#ifdef LIST_HEAD -#undef LIST_HEAD #endif -#include "cam.h" -#include "queue.h" -#include "scsi_message.h" -#include "aiclib.h" - /*********************************** Debugging ********************************/ #ifdef CONFIG_AIC7XXX_DEBUG_ENABLE #ifdef CONFIG_AIC7XXX_DEBUG_MASK @@ -112,42 +83,18 @@ /* No debugging code. */ #endif -/************************* Forward Declarations *******************************/ -struct ahc_softc; -typedef struct pci_dev *ahc_dev_softc_t; -typedef Scsi_Cmnd *ahc_io_ctx_t; - -/******************************* Byte Order ***********************************/ -#define ahc_htobe16(x) cpu_to_be16(x) -#define ahc_htobe32(x) cpu_to_be32(x) -#define ahc_htobe64(x) cpu_to_be64(x) -#define ahc_htole16(x) cpu_to_le16(x) -#define ahc_htole32(x) cpu_to_le32(x) -#define ahc_htole64(x) cpu_to_le64(x) - -#define ahc_be16toh(x) be16_to_cpu(x) -#define ahc_be32toh(x) be32_to_cpu(x) -#define ahc_be64toh(x) be64_to_cpu(x) -#define ahc_le16toh(x) le16_to_cpu(x) -#define ahc_le32toh(x) le32_to_cpu(x) -#define ahc_le64toh(x) le64_to_cpu(x) - -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1234 -#endif - -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 4321 -#endif +/********************************** Includes **********************************/ +/* Core SCSI definitions */ +#define AIC_LIB_PREFIX ahc +#define AIC_CONST_PREFIX AHC -#ifndef BYTE_ORDER -#if defined(__BIG_ENDIAN) -#define BYTE_ORDER BIG_ENDIAN -#endif -#if defined(__LITTLE_ENDIAN) -#define BYTE_ORDER LITTLE_ENDIAN +#ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT +#define AIC_DEBUG_REGISTERS 1 +#else +#define AIC_DEBUG_REGISTERS 0 #endif -#endif /* BYTE_ORDER */ +#define AIC_CORE_INCLUDE "aic7xxx.h" +#include "aiclib.h" /************************* Configuration Data *********************************/ extern u_int aic7xxx_no_probe; @@ -155,142 +102,9 @@ extern int aic7xxx_detect_complete; extern Scsi_Host_Template aic7xxx_driver_template; -/***************************** Bus Space/DMA **********************************/ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17) -typedef dma_addr_t bus_addr_t; -#else -typedef uint32_t bus_addr_t; -#endif -typedef uint32_t bus_size_t; - -typedef enum { - BUS_SPACE_MEMIO, - BUS_SPACE_PIO -} bus_space_tag_t; - -typedef union { - u_long ioport; - volatile uint8_t *maddr; -} bus_space_handle_t; - -typedef struct bus_dma_segment -{ - bus_addr_t ds_addr; - bus_size_t ds_len; -} bus_dma_segment_t; - -struct ahc_linux_dma_tag -{ - bus_size_t alignment; - bus_size_t boundary; - bus_size_t maxsize; -}; -typedef struct ahc_linux_dma_tag* bus_dma_tag_t; - -struct ahc_linux_dmamap -{ - bus_addr_t bus_addr; -}; -typedef struct ahc_linux_dmamap* bus_dmamap_t; - -typedef int bus_dma_filter_t(void*, bus_addr_t); -typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); - -#define BUS_DMA_WAITOK 0x0 -#define BUS_DMA_NOWAIT 0x1 -#define BUS_DMA_ALLOCNOW 0x2 -#define BUS_DMA_LOAD_SEGS 0x4 /* - * Argument is an S/G list not - * a single buffer. - */ - -#define BUS_SPACE_MAXADDR 0xFFFFFFFF -#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF -#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF - -int ahc_dma_tag_create(struct ahc_softc *, bus_dma_tag_t /*parent*/, - bus_size_t /*alignment*/, bus_size_t /*boundary*/, - bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/, - bus_dma_filter_t*/*filter*/, void */*filterarg*/, - bus_size_t /*maxsize*/, int /*nsegments*/, - bus_size_t /*maxsegsz*/, int /*flags*/, - bus_dma_tag_t */*dma_tagp*/); - -void ahc_dma_tag_destroy(struct ahc_softc *, bus_dma_tag_t /*tag*/); - -int ahc_dmamem_alloc(struct ahc_softc *, bus_dma_tag_t /*dmat*/, - void** /*vaddr*/, int /*flags*/, - bus_dmamap_t* /*mapp*/); - -void ahc_dmamem_free(struct ahc_softc *, bus_dma_tag_t /*dmat*/, - void* /*vaddr*/, bus_dmamap_t /*map*/); - -void ahc_dmamap_destroy(struct ahc_softc *, bus_dma_tag_t /*tag*/, - bus_dmamap_t /*map*/); - -int ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t /*dmat*/, - bus_dmamap_t /*map*/, void * /*buf*/, - bus_size_t /*buflen*/, bus_dmamap_callback_t *, - void */*callback_arg*/, int /*flags*/); - -int ahc_dmamap_unload(struct ahc_softc *, bus_dma_tag_t, bus_dmamap_t); - -/* - * Operations performed by ahc_dmamap_sync(). - */ -#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ -#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ -#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ -#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ - -/* - * XXX - * ahc_dmamap_sync is only used on buffers allocated with - * the pci_alloc_consistent() API. Although I'm not sure how - * this works on architectures with a write buffer, Linux does - * not have an API to sync "coherent" memory. Perhaps we need - * to do an mb()? - */ -#define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op) - -/************************** Timer DataStructures ******************************/ -typedef struct timer_list ahc_timer_t; - -/********************************** Includes **********************************/ -#ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT -#define AIC_DEBUG_REGISTERS 1 -#else -#define AIC_DEBUG_REGISTERS 0 -#endif -#include "aic7xxx.h" - -/***************************** Timer Facilities *******************************/ -#define ahc_timer_init init_timer -#define ahc_timer_stop del_timer_sync -typedef void ahc_linux_callback_t (u_long); -static __inline void ahc_timer_reset(ahc_timer_t *timer, int usec, - ahc_callback_t *func, void *arg); -static __inline void ahc_scb_timer_reset(struct scb *scb, u_int usec); - -static __inline void -ahc_timer_reset(ahc_timer_t *timer, int usec, ahc_callback_t *func, void *arg) -{ - struct ahc_softc *ahc; - - ahc = (struct ahc_softc *)arg; - del_timer(timer); - timer->data = (u_long)arg; - timer->expires = jiffies + (usec * HZ)/1000000; - timer->function = (ahc_linux_callback_t*)func; - add_timer(timer); -} - -static __inline void -ahc_scb_timer_reset(struct scb *scb, u_int usec) -{ - mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000); -} +/***************************** Domain Validation ******************************/ +void ahc_linux_dv_complete(Scsi_Cmnd *cmd); +void ahc_linux_dv_timeout(struct scsi_cmnd *cmd); /***************************** SMP support ************************************/ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17) @@ -299,193 +113,7 @@ #include #endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK)) -#define AHC_SCSI_HAS_HOST_LOCK 1 -#else -#define AHC_SCSI_HAS_HOST_LOCK 0 -#endif - -#define AIC7XXX_DRIVER_VERSION "6.2.36" - -/**************************** Front End Queues ********************************/ -/* - * Data structure used to cast the Linux struct scsi_cmnd to something - * that allows us to use the queue macros. The linux structure has - * plenty of space to hold the links fields as required by the queue - * macros, but the queue macors require them to have the correct type. - */ -struct ahc_cmd_internal { - /* Area owned by the Linux scsi layer. */ - uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)]; - union { - STAILQ_ENTRY(ahc_cmd) ste; - LIST_ENTRY(ahc_cmd) le; - TAILQ_ENTRY(ahc_cmd) tqe; - } links; - uint32_t end; -}; - -struct ahc_cmd { - union { - struct ahc_cmd_internal icmd; - struct scsi_cmnd scsi_cmd; - } un; -}; - -#define acmd_icmd(cmd) ((cmd)->un.icmd) -#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd) -#define acmd_links un.icmd.links - -/*************************** Device Data Structures ***************************/ -/* - * A per probed device structure used to deal with some error recovery - * scenarios that the Linux mid-layer code just doesn't know how to - * handle. The structure allocated for a device only becomes persistent - * after a successfully completed inquiry command to the target when - * that inquiry data indicates a lun is present. - */ -TAILQ_HEAD(ahc_busyq, ahc_cmd); -typedef enum { - AHC_DEV_UNCONFIGURED = 0x01, - AHC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */ - AHC_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */ - AHC_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */ - AHC_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */ - AHC_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */ - AHC_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */ - AHC_DEV_SLAVE_CONFIGURED = 0x80 /* slave_configure() has been called */ -} ahc_linux_dev_flags; - -struct ahc_linux_target; -struct ahc_linux_device { - TAILQ_ENTRY(ahc_linux_device) links; - struct ahc_busyq busyq; - - /* - * The number of transactions currently - * queued to the device. - */ - int active; - - /* - * The currently allowed number of - * transactions that can be queued to - * the device. Must be signed for - * conversion from tagged to untagged - * mode where the device may have more - * than one outstanding active transaction. - */ - int openings; - - /* - * A positive count indicates that this - * device's queue is halted. - */ - u_int qfrozen; - - /* - * Cumulative command counter. - */ - u_long commands_issued; - - /* - * The number of tagged transactions when - * running at our current opening level - * that have been successfully received by - * this device since the last QUEUE FULL. - */ - u_int tag_success_count; -#define AHC_TAG_SUCCESS_INTERVAL 50 - - ahc_linux_dev_flags flags; - - /* - * Per device timer. - */ - struct timer_list timer; - - /* - * The high limit for the tags variable. - */ - u_int maxtags; - - /* - * The computed number of tags outstanding - * at the time of the last QUEUE FULL event. - */ - u_int tags_on_last_queuefull; - - /* - * How many times we have seen a queue full - * with the same number of tags. This is used - * to stop our adaptive queue depth algorithm - * on devices with a fixed number of tags. - */ - u_int last_queuefull_same_count; -#define AHC_LOCK_TAGS_COUNT 50 - - /* - * How many transactions have been queued - * without the device going idle. We use - * this statistic to determine when to issue - * an ordered tag to prevent transaction - * starvation. This statistic is only updated - * if the AHC_DEV_PERIODIC_OTAG flag is set - * on this device. - */ - u_int commands_since_idle_or_otag; -#define AHC_OTAG_THRESH 500 - - int lun; - Scsi_Device *scsi_device; - struct ahc_linux_target *target; -}; - -typedef enum { - AHC_DV_REQUIRED = 0x01, - AHC_INQ_VALID = 0x02, - AHC_BASIC_DV = 0x04, - AHC_ENHANCED_DV = 0x08 -} ahc_linux_targ_flags; - -/* DV States */ -typedef enum { - AHC_DV_STATE_EXIT = 0, - AHC_DV_STATE_INQ_SHORT_ASYNC, - AHC_DV_STATE_INQ_ASYNC, - AHC_DV_STATE_INQ_ASYNC_VERIFY, - AHC_DV_STATE_TUR, - AHC_DV_STATE_REBD, - AHC_DV_STATE_INQ_VERIFY, - AHC_DV_STATE_WEB, - AHC_DV_STATE_REB, - AHC_DV_STATE_SU, - AHC_DV_STATE_BUSY -} ahc_dv_state; - -struct ahc_linux_target { - struct ahc_linux_device *devices[AHC_NUM_LUNS]; - int channel; - int target; - int refcount; - struct ahc_transinfo last_tinfo; - struct ahc_softc *ahc; - ahc_linux_targ_flags flags; - struct scsi_inquiry_data *inq_data; - /* - * The next "fallback" period to use for narrow/wide transfers. - */ - uint8_t dv_next_narrow_period; - uint8_t dv_next_wide_period; - uint8_t dv_max_width; - uint8_t dv_max_ppr_options; - uint8_t dv_last_ppr_options; - u_int dv_echo_size; - ahc_dv_state dv_state; - u_int dv_state_retry; - char *dv_buffer; - char *dv_buffer1; -}; +#define AIC7XXX_DRIVER_VERSION "6.3.5" /********************* Definitions Required by the Core ***********************/ /* @@ -507,120 +135,39 @@ #define AHC_NSEG 128 #endif -/* - * Per-SCB OSM storage. - */ -typedef enum { - AHC_UP_EH_SEMAPHORE = 0x1 -} ahc_linux_scb_flags; - -struct scb_platform_data { - struct ahc_linux_device *dev; - bus_addr_t buf_busaddr; - uint32_t xfer_len; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - uint32_t resid; /* Transfer residual */ -#endif - uint32_t sense_resid; /* Auto-Sense residual */ - ahc_linux_scb_flags flags; -}; - -/* - * Define a structure used for each host adapter. All members are - * aligned on a boundary >= the size of the member to honor the - * alignment restrictions of the various platforms supported by - * this driver. - */ -typedef enum { - AHC_DV_WAIT_SIMQ_EMPTY = 0x01, - AHC_DV_WAIT_SIMQ_RELEASE = 0x02, - AHC_DV_ACTIVE = 0x04, - AHC_DV_SHUTDOWN = 0x08, - AHC_RUN_CMPLT_Q_TIMER = 0x10 -} ahc_linux_softc_flags; - -TAILQ_HEAD(ahc_completeq, ahc_cmd); - -struct ahc_platform_data { - /* - * Fields accessed from interrupt context. - */ - struct ahc_linux_target *targets[AHC_NUM_TARGETS]; - TAILQ_HEAD(, ahc_linux_device) device_runq; - struct ahc_completeq completeq; - - spinlock_t spin_lock; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - struct tasklet_struct runq_tasklet; -#endif - u_int qfrozen; - pid_t dv_pid; - struct timer_list completeq_timer; - struct timer_list reset_timer; - struct semaphore eh_sem; - struct semaphore dv_sem; - struct semaphore dv_cmd_sem; /* XXX This needs to be in - * the target struct - */ - struct scsi_device *dv_scsi_dev; - struct Scsi_Host *host; /* pointer to scsi host */ -#define AHC_LINUX_NOIRQ ((uint32_t)~0) - uint32_t irq; /* IRQ for this adapter */ - uint32_t bios_address; - uint32_t mem_busaddr; /* Mem Base Addr */ - bus_addr_t hw_dma_mask; - ahc_linux_softc_flags flags; -}; - -/************************** OS Utility Wrappers *******************************/ -#define printf printk -#define M_NOWAIT GFP_ATOMIC -#define M_WAITOK 0 -#define malloc(size, type, flags) kmalloc(size, flags) -#define free(ptr, type) kfree(ptr) - -static __inline void ahc_delay(long); -static __inline void -ahc_delay(long usec) -{ - /* - * udelay on Linux can have problems for - * multi-millisecond waits. Wait at most - * 1024us per call. - */ - while (usec > 0) { - udelay(usec % 1024); - usec -= 1024; - } -} - +/************************** Error Recovery ************************************/ +static __inline void ahc_wakeup_recovery_thread(struct ahc_softc *ahc); + +static __inline void +ahc_wakeup_recovery_thread(struct ahc_softc *ahc) +{ + up(&ahc->platform_data->recovery_sem); +} + +int ahc_spawn_recovery_thread(struct ahc_softc *ahc); +void ahc_terminate_recovery_thread(struct ahc_softc *ahc); +void ahc_set_recoveryscb(struct ahc_softc *ahc, + struct scb *scb); /***************************** Low Level I/O **********************************/ -#if defined(__powerpc__) || defined(__i386__) || defined(__ia64__) -#define MMAPIO -#endif - static __inline uint8_t ahc_inb(struct ahc_softc * ahc, long port); static __inline void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val); static __inline void ahc_outsb(struct ahc_softc * ahc, long port, uint8_t *, int count); static __inline void ahc_insb(struct ahc_softc * ahc, long port, uint8_t *, int count); +static __inline void ahc_flush_device_writes(struct ahc_softc *); static __inline uint8_t ahc_inb(struct ahc_softc * ahc, long port) { uint8_t x; -#ifdef MMAPIO if (ahc->tag == BUS_SPACE_MEMIO) { x = readb(ahc->bsh.maddr + port); } else { x = inb(ahc->bsh.ioport + port); } -#else - x = inb(ahc->bsh.ioport + port); -#endif mb(); return (x); } @@ -628,15 +175,11 @@ 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(); } @@ -668,7 +211,15 @@ *array++ = ahc_inb(ahc, port); } +static __inline void +ahc_flush_device_writes(struct ahc_softc *ahc) +{ + /* XXX Is this sufficient for all architectures??? */ + ahc_inb(ahc, INTSTAT); +} + /**************************** Initialization **********************************/ +extern int ahc_init_status; int ahc_linux_register_host(struct ahc_softc *, Scsi_Host_Template *); @@ -685,165 +236,11 @@ void ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo); -/******************************** Locking *************************************/ -/* Lock protecting internal data structures */ -static __inline void ahc_lockinit(struct ahc_softc *); -static __inline void ahc_lock(struct ahc_softc *, unsigned long *flags); -static __inline void ahc_unlock(struct ahc_softc *, unsigned long *flags); - -/* Lock acquisition and release of the above lock in midlayer entry points. */ -static __inline void ahc_midlayer_entrypoint_lock(struct ahc_softc *, - unsigned long *flags); -static __inline void ahc_midlayer_entrypoint_unlock(struct ahc_softc *, - unsigned long *flags); - -/* Lock held during command compeletion to the upper layer */ -static __inline void ahc_done_lockinit(struct ahc_softc *); -static __inline void ahc_done_lock(struct ahc_softc *, unsigned long *flags); -static __inline void ahc_done_unlock(struct ahc_softc *, unsigned long *flags); - -/* Lock held during ahc_list manipulation and ahc softc frees */ -extern spinlock_t ahc_list_spinlock; -static __inline void ahc_list_lockinit(void); -static __inline void ahc_list_lock(unsigned long *flags); -static __inline void ahc_list_unlock(unsigned long *flags); - -static __inline void -ahc_lockinit(struct ahc_softc *ahc) -{ - spin_lock_init(&ahc->platform_data->spin_lock); -} - -static __inline void -ahc_lock(struct ahc_softc *ahc, unsigned long *flags) -{ - spin_lock_irqsave(&ahc->platform_data->spin_lock, *flags); -} - -static __inline void -ahc_unlock(struct ahc_softc *ahc, unsigned long *flags) -{ - spin_unlock_irqrestore(&ahc->platform_data->spin_lock, *flags); -} - -static __inline void -ahc_midlayer_entrypoint_lock(struct ahc_softc *ahc, unsigned long *flags) -{ - /* - * In 2.5.X and some 2.4.X versions, the midlayer takes our - * lock just before calling us, so we avoid locking again. - * For other kernel versions, the io_request_lock is taken - * just before our entry point is called. In this case, we - * trade the io_request_lock for our per-softc lock. - */ -#if AHC_SCSI_HAS_HOST_LOCK == 0 - spin_unlock(&io_request_lock); - spin_lock(&ahc->platform_data->spin_lock); -#endif -} - -static __inline void -ahc_midlayer_entrypoint_unlock(struct ahc_softc *ahc, unsigned long *flags) -{ -#if AHC_SCSI_HAS_HOST_LOCK == 0 - spin_unlock(&ahc->platform_data->spin_lock); - spin_lock(&io_request_lock); -#endif -} - -static __inline void -ahc_done_lockinit(struct ahc_softc *ahc) -{ - /* - * In 2.5.X, our own lock is held during completions. - * In previous versions, the io_request_lock is used. - * In either case, we can't initialize this lock again. - */ -} - -static __inline void -ahc_done_lock(struct ahc_softc *ahc, unsigned long *flags) -{ -#if AHC_SCSI_HAS_HOST_LOCK == 0 - spin_lock_irqsave(&io_request_lock, *flags); -#endif -} - -static __inline void -ahc_done_unlock(struct ahc_softc *ahc, unsigned long *flags) -{ -#if AHC_SCSI_HAS_HOST_LOCK == 0 - spin_unlock_irqrestore(&io_request_lock, *flags); -#endif -} - -static __inline void -ahc_list_lockinit(void) -{ - spin_lock_init(&ahc_list_spinlock); -} - -static __inline void -ahc_list_lock(unsigned long *flags) -{ - spin_lock_irqsave(&ahc_list_spinlock, *flags); -} - -static __inline void -ahc_list_unlock(unsigned long *flags) -{ - spin_unlock_irqrestore(&ahc_list_spinlock, *flags); -} - /******************************* PCI Definitions ******************************/ -/* - * PCIM_xxx: mask to locate subfield in register - * PCIR_xxx: config register offset - * PCIC_xxx: device class - * PCIS_xxx: device subclass - * PCIP_xxx: device programming interface - * PCIV_xxx: PCI vendor ID (only required to fixup ancient devices) - * PCID_xxx: device ID - */ -#define PCIR_DEVVENDOR 0x00 -#define PCIR_VENDOR 0x00 -#define PCIR_DEVICE 0x02 -#define PCIR_COMMAND 0x04 -#define PCIM_CMD_PORTEN 0x0001 -#define PCIM_CMD_MEMEN 0x0002 -#define PCIM_CMD_BUSMASTEREN 0x0004 -#define PCIM_CMD_MWRICEN 0x0010 -#define PCIM_CMD_PERRESPEN 0x0040 -#define PCIM_CMD_SERRESPEN 0x0100 -#define PCIR_STATUS 0x06 -#define PCIR_REVID 0x08 -#define PCIR_PROGIF 0x09 -#define PCIR_SUBCLASS 0x0a -#define PCIR_CLASS 0x0b -#define PCIR_CACHELNSZ 0x0c -#define PCIR_LATTIMER 0x0d -#define PCIR_HEADERTYPE 0x0e -#define PCIM_MFDEV 0x80 -#define PCIR_BIST 0x0f -#define PCIR_CAP_PTR 0x34 - -/* config registers for header type 0 devices */ -#define PCIR_MAPS 0x10 -#define PCIR_SUBVEND_0 0x2c -#define PCIR_SUBDEV_0 0x2e - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) extern struct pci_driver aic7xxx_pci_driver; #endif -typedef enum -{ - AHC_POWER_STATE_D0, - AHC_POWER_STATE_D1, - AHC_POWER_STATE_D2, - AHC_POWER_STATE_D3 -} ahc_power_state; - /**************************** VL/EISA Routines ********************************/ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) \ && (defined(__i386__) || defined(__alpha__)) \ @@ -853,7 +250,7 @@ #ifdef CONFIG_EISA extern uint32_t aic7xxx_probe_eisa_vl; -void ahc_linux_eisa_init(void); +int ahc_linux_eisa_init(void); void ahc_linux_eisa_exit(void); int aic7770_map_registers(struct ahc_softc *ahc, u_int port); @@ -862,118 +259,12 @@ /******************************* 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); int ahc_pci_map_int(struct ahc_softc *ahc); +#endif -static __inline uint32_t ahc_pci_read_config(ahc_dev_softc_t pci, - int reg, int width); - -static __inline uint32_t -ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width) -{ - switch (width) { - case 1: - { - uint8_t retval; - - pci_read_config_byte(pci, reg, &retval); - return (retval); - } - case 2: - { - uint16_t retval; - pci_read_config_word(pci, reg, &retval); - return (retval); - } - case 4: - { - uint32_t retval; - pci_read_config_dword(pci, reg, &retval); - return (retval); - } - default: - panic("ahc_pci_read_config: Read size too big"); - /* NOTREACHED */ - return (0); - } -} - -static __inline void ahc_pci_write_config(ahc_dev_softc_t pci, - int reg, uint32_t value, - int width); - -static __inline void -ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width) -{ - switch (width) { - case 1: - pci_write_config_byte(pci, reg, value); - break; - case 2: - pci_write_config_word(pci, reg, value); - break; - case 4: - pci_write_config_dword(pci, reg, value); - break; - default: - panic("ahc_pci_write_config: Write size too big"); - /* NOTREACHED */ - } -} - -static __inline int ahc_get_pci_function(ahc_dev_softc_t); -static __inline int -ahc_get_pci_function(ahc_dev_softc_t pci) -{ - return (PCI_FUNC(pci->devfn)); -} - -static __inline int ahc_get_pci_slot(ahc_dev_softc_t); -static __inline int -ahc_get_pci_slot(ahc_dev_softc_t pci) -{ - return (PCI_SLOT(pci->devfn)); -} - -static __inline int ahc_get_pci_bus(ahc_dev_softc_t); -static __inline int -ahc_get_pci_bus(ahc_dev_softc_t pci) -{ - return (pci->bus->number); -} -#endif - -static __inline void ahc_flush_device_writes(struct ahc_softc *); -static __inline void -ahc_flush_device_writes(struct ahc_softc *ahc) -{ - /* XXX Is this sufficient for all architectures??? */ - ahc_inb(ahc, INTSTAT); -} - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0) -#define pci_map_sg(pdev, sg_list, nseg, direction) (nseg) -#define pci_unmap_sg(pdev, sg_list, nseg, direction) -#define sg_dma_address(sg) (VIRT_TO_BUS((sg)->address)) -#define sg_dma_len(sg) ((sg)->length) -#define pci_map_single(pdev, buffer, bufflen, direction) \ - (VIRT_TO_BUS(buffer)) -#define pci_unmap_single(pdev, buffer, buflen, direction) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) -#define ahc_pci_set_dma_mask pci_set_dma_mask -#else -/* - * Always "return" 0 for success. - */ -#define ahc_pci_set_dma_mask(dev_softc, mask) \ - (((dev_softc)->dma_mask = mask) && 0) -#endif /**************************** Proc FS Support *********************************/ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) int ahc_linux_proc_info(char *, char **, off_t, int, int, int); @@ -989,194 +280,9 @@ && (ahc)->platform_data->qfrozen == 1) /*********************** Transaction Access Wrappers *************************/ -static __inline void ahc_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t); -static __inline void ahc_set_transaction_status(struct scb *, uint32_t); -static __inline void ahc_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t); -static __inline void ahc_set_scsi_status(struct scb *, uint32_t); -static __inline uint32_t ahc_cmd_get_transaction_status(Scsi_Cmnd *cmd); -static __inline uint32_t ahc_get_transaction_status(struct scb *); -static __inline uint32_t ahc_cmd_get_scsi_status(Scsi_Cmnd *cmd); -static __inline uint32_t ahc_get_scsi_status(struct scb *); -static __inline void ahc_set_transaction_tag(struct scb *, int, u_int); -static __inline u_long ahc_get_transfer_length(struct scb *); -static __inline int ahc_get_transfer_dir(struct scb *); -static __inline void ahc_set_residual(struct scb *, u_long); -static __inline void ahc_set_sense_residual(struct scb *scb, u_long resid); -static __inline u_long ahc_get_residual(struct scb *); -static __inline u_long ahc_get_sense_residual(struct scb *); -static __inline int ahc_perform_autosense(struct scb *); -static __inline uint32_t ahc_get_sense_bufsize(struct ahc_softc *, - struct scb *); -static __inline void ahc_notify_xfer_settings_change(struct ahc_softc *, - struct ahc_devinfo *); -static __inline void ahc_platform_scb_free(struct ahc_softc *ahc, - struct scb *scb); -static __inline void ahc_freeze_scb(struct scb *scb); - -static __inline -void ahc_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status) -{ - cmd->result &= ~(CAM_STATUS_MASK << 16); - cmd->result |= status << 16; -} - -static __inline -void ahc_set_transaction_status(struct scb *scb, uint32_t status) -{ - ahc_cmd_set_transaction_status(scb->io_ctx,status); -} - -static __inline -void ahc_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status) -{ - cmd->result &= ~0xFFFF; - cmd->result |= status; -} - -static __inline -void ahc_set_scsi_status(struct scb *scb, uint32_t status) -{ - ahc_cmd_set_scsi_status(scb->io_ctx, status); -} - -static __inline -uint32_t ahc_cmd_get_transaction_status(Scsi_Cmnd *cmd) -{ - return ((cmd->result >> 16) & CAM_STATUS_MASK); -} - -static __inline -uint32_t ahc_get_transaction_status(struct scb *scb) -{ - return (ahc_cmd_get_transaction_status(scb->io_ctx)); -} - -static __inline -uint32_t ahc_cmd_get_scsi_status(Scsi_Cmnd *cmd) -{ - return (cmd->result & 0xFFFF); -} - -static __inline -uint32_t ahc_get_scsi_status(struct scb *scb) -{ - return (ahc_cmd_get_scsi_status(scb->io_ctx)); -} - -static __inline -void ahc_set_transaction_tag(struct scb *scb, int enabled, u_int type) -{ - /* - * Nothing to do for linux as the incoming transaction - * has no concept of tag/non tagged, etc. - */ -} - -static __inline -u_long ahc_get_transfer_length(struct scb *scb) -{ - return (scb->platform_data->xfer_len); -} - -static __inline -int ahc_get_transfer_dir(struct scb *scb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40) - return (scb->io_ctx->sc_data_direction); -#else - if (scb->io_ctx->bufflen == 0) - return (CAM_DIR_NONE); - - switch(scb->io_ctx->cmnd[0]) { - case 0x08: /* READ(6) */ - case 0x28: /* READ(10) */ - case 0xA8: /* READ(12) */ - return (CAM_DIR_IN); - case 0x0A: /* WRITE(6) */ - case 0x2A: /* WRITE(10) */ - case 0xAA: /* WRITE(12) */ - return (CAM_DIR_OUT); - default: - return (CAM_DIR_NONE); - } -#endif -} - -static __inline -void ahc_set_residual(struct scb *scb, u_long resid) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - scb->io_ctx->resid = resid; -#else - scb->platform_data->resid = resid; -#endif -} - -static __inline -void ahc_set_sense_residual(struct scb *scb, u_long resid) -{ - scb->platform_data->sense_resid = resid; -} - -static __inline -u_long ahc_get_residual(struct scb *scb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - return (scb->io_ctx->resid); -#else - return (scb->platform_data->resid); -#endif -} - -static __inline -u_long ahc_get_sense_residual(struct scb *scb) -{ - return (scb->platform_data->sense_resid); -} - -static __inline -int ahc_perform_autosense(struct scb *scb) -{ - /* - * We always perform autosense in Linux. - * On other platforms this is set on a - * per-transaction basis. - */ - return (1); -} - -static __inline uint32_t -ahc_get_sense_bufsize(struct ahc_softc *ahc, struct scb *scb) -{ - return (sizeof(struct scsi_sense_data)); -} - -static __inline void -ahc_notify_xfer_settings_change(struct ahc_softc *ahc, - struct ahc_devinfo *devinfo) -{ - /* Nothing to do here for linux */ -} - -static __inline void -ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb) -{ - ahc->flags &= ~AHC_RESOURCE_SHORTAGE; -} - int ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg); void ahc_platform_free(struct ahc_softc *ahc); void ahc_platform_freeze_devq(struct ahc_softc *ahc, struct scb *scb); - -static __inline void -ahc_freeze_scb(struct scb *scb) -{ - if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) { - scb->io_ctx->result |= CAM_DEV_QFRZN << 16; - scb->platform_data->dev->qfrozen++; - } -} - void ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, ahc_queue_alg); int ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, @@ -1193,9 +299,9 @@ void ahc_platform_dump_card_state(struct ahc_softc *ahc); #ifdef CONFIG_PCI -#define AHC_PCI_CONFIG 1 +#define AIC_PCI_CONFIG 1 #else -#define AHC_PCI_CONFIG 0 +#define AIC_PCI_CONFIG 0 #endif #define bootverbose aic7xxx_verbose extern u_int aic7xxx_verbose; diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c Tue Feb 10 01:47:06 2004 @@ -36,27 +36,26 @@ * 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#46 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c#56 $ */ #include "aic7xxx_osm.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -struct pci_device_id -{ -}; -#endif +/* + * Include aiclib_pci.c as part of our + * "module dependencies are hard" work around. + */ +#include "aiclib_pci.c" + +static int ahc_pci_module_registered; static int ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent); static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base); -#ifdef MMAPIO static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, u_long *bus_addr, uint8_t **maddr); -#endif /* MMAPIO */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) static void ahc_linux_pci_dev_remove(struct pci_dev *pdev); /* We do our own ID filtering. So, grab all SCSI storage class devices. */ @@ -75,10 +74,10 @@ MODULE_DEVICE_TABLE(pci, ahc_linux_pci_id_table); struct pci_driver aic7xxx_pci_driver = { - name: "aic7xxx", - probe: ahc_linux_pci_dev_probe, - remove: ahc_linux_pci_dev_remove, - id_table: ahc_linux_pci_id_table + .name = "aic7xxx", + .probe = ahc_linux_pci_dev_probe, + .remove = ahc_linux_pci_dev_remove, + .id_table = ahc_linux_pci_id_table }; static void @@ -97,14 +96,15 @@ if (ahc != NULL) { u_long s; + TAILQ_REMOVE(&ahc_tailq, ahc, links); + ahc_list_unlock(&l); ahc_lock(ahc, &s); ahc_intr_enable(ahc, FALSE); ahc_unlock(ahc, &s); ahc_free(ahc); - } - ahc_list_unlock(&l); + } else + ahc_list_unlock(&l); } -#endif /* !LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) */ static int ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -112,7 +112,7 @@ char buf[80]; bus_addr_t mask_39bit; struct ahc_softc *ahc; - ahc_dev_softc_t pci; + aic_dev_softc_t dev; struct ahc_pci_identity *entry; char *name; int error; @@ -123,7 +123,7 @@ TAILQ_FOREACH(ahc, &ahc_tailq, links) { struct pci_dev *probed_pdev; - probed_pdev = ahc->dev_softc; + probed_pdev = aic_dev_to_pci_dev(ahc->dev_softc); if (probed_pdev->bus->number == pdev->bus->number && probed_pdev->devfn == pdev->devfn) break; @@ -133,8 +133,8 @@ return (-ENODEV); } - pci = pdev; - entry = ahc_find_pci_device(pci); + dev = aic_pci_dev_to_dev(pdev); + entry = ahc_find_pci_device(dev); if (entry == NULL) return (-ENODEV); @@ -144,9 +144,9 @@ * common detect routine. */ sprintf(buf, "ahc_pci:%d:%d:%d", - ahc_get_pci_bus(pci), - ahc_get_pci_slot(pci), - ahc_get_pci_function(pci)); + aic_get_pci_bus(dev), + aic_get_pci_slot(dev), + aic_get_pci_function(dev)); name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); if (name == NULL) return (-ENOMEM); @@ -154,31 +154,41 @@ ahc = ahc_alloc(NULL, name); if (ahc == NULL) return (-ENOMEM); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + ahc->dev_softc = dev; + if (pci_enable_device(pdev)) { ahc_free(ahc); return (-ENODEV); } pci_set_master(pdev); + if (aic_set_consistent_dma_mask(ahc, 0xFFFFFFFF) != 0) { + printk(KERN_WARNING "aic7xxx: Unable to set" + "coherent DMA mask.\n"); + ahc_free(ahc); + return (-ENOMEM); + } + mask_39bit = (bus_addr_t)0x7FFFFFFFFFULL; if (sizeof(bus_addr_t) > 4 && ahc_linux_get_memsize() > 0x80000000 - && ahc_pci_set_dma_mask(pdev, mask_39bit) == 0) { + && aic_set_dma_mask(ahc, mask_39bit) == 0) { ahc->flags |= AHC_39BIT_ADDRESSING; ahc->platform_data->hw_dma_mask = mask_39bit; } else { - ahc_pci_set_dma_mask(pdev, 0xFFFFFFFF); + if (aic_set_dma_mask(ahc, 0xFFFFFFFF) != 0) { + printk(KERN_WARNING "aic7xxx: Unable to set data " + "DMA mask.\n"); + ahc_free(ahc); + return (-ENOMEM); + } ahc->platform_data->hw_dma_mask = 0xFFFFFFFF; } -#endif - ahc->dev_softc = pci; error = ahc_pci_config(ahc, entry); if (error != 0) { ahc_free(ahc); return (-error); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_set_drvdata(pdev, ahc); if (aic7xxx_detect_complete) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) @@ -189,44 +199,25 @@ return (-ENODEV); #endif } -#endif return (0); } int ahc_linux_pci_init(void) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - return (pci_module_init(&aic7xxx_pci_driver)); -#else - struct pci_dev *pdev; - u_int class; - int found; - - /* If we don't have a PCI bus, we can't find any adapters. */ - if (pci_present() == 0) - return (0); - - found = 0; - pdev = NULL; - class = PCI_CLASS_STORAGE_SCSI << 8; - while ((pdev = pci_find_class(class, pdev)) != NULL) { - ahc_dev_softc_t pci; - int error; - - pci = pdev; - error = ahc_linux_pci_dev_probe(pdev, /*pci_devid*/NULL); - if (error == 0) - found++; - } - return (found); -#endif + int error; + + error = pci_module_init(&aic7xxx_pci_driver); + if (error == 0) + ahc_pci_module_registered = 1; + return (error); } void ahc_linux_pci_exit(void) { - pci_unregister_driver(&aic7xxx_pci_driver); + if (ahc_pci_module_registered != 0) + pci_unregister_driver(&aic7xxx_pci_driver); } static int @@ -235,26 +226,14 @@ if (aic7xxx_allow_memio == 0) return (ENOMEM); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - *base = pci_resource_start(ahc->dev_softc, 0); -#else - *base = ahc_pci_read_config(ahc->dev_softc, PCIR_MAPS, 4); - *base &= PCI_BASE_ADDRESS_IO_MASK; -#endif + *base = pci_resource_start(aic_pci_dev(ahc), 0); if (*base == 0) return (ENOMEM); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - if (check_region(*base, 256) != 0) - return (ENOMEM); - request_region(*base, 256, "aic7xxx"); -#else if (request_region(*base, 256, "aic7xxx") == 0) return (ENOMEM); -#endif return (0); } -#ifdef MMAPIO static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, u_long *bus_addr, @@ -266,29 +245,18 @@ int error; error = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - start = pci_resource_start(ahc->dev_softc, 1); + start = pci_resource_start(aic_pci_dev(ahc), 1); base_page = start & PAGE_MASK; base_offset = start - base_page; -#else - start = ahc_pci_read_config(ahc->dev_softc, PCIR_MAPS+4, 4); - base_offset = start & PCI_BASE_ADDRESS_MEM_MASK; - base_page = base_offset & PAGE_MASK; - base_offset -= base_page; -#endif if (start != 0) { *bus_addr = start; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) if (request_mem_region(start, 0x1000, "aic7xxx") == 0) error = ENOMEM; -#endif if (error == 0) { *maddr = ioremap_nocache(base_page, base_offset + 256); if (*maddr == NULL) { error = ENOMEM; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(start, 0x1000); -#endif } else *maddr += base_offset; } @@ -296,7 +264,6 @@ error = ENOMEM; return (error); } -#endif /* MMAPIO */ int ahc_pci_map_registers(struct ahc_softc *ahc) @@ -309,17 +276,16 @@ /* * If its allowed, we prefer memory mapped access. */ - command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, 4); + command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, 4); command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN); base = 0; maddr = NULL; -#ifdef MMAPIO error = ahc_linux_pci_reserve_mem_region(ahc, &base, &maddr); if (error == 0) { ahc->platform_data->mem_busaddr = base; ahc->tag = BUS_SPACE_MEMIO; ahc->bsh.maddr = maddr; - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command | PCIM_CMD_MEMEN, 4); /* @@ -330,14 +296,12 @@ printf("aic7xxx: PCI Device %d:%d:%d " "failed memory mapped test. Using PIO.\n", - ahc_get_pci_bus(ahc->dev_softc), - ahc_get_pci_slot(ahc->dev_softc), - ahc_get_pci_function(ahc->dev_softc)); + aic_get_pci_bus(ahc->dev_softc), + aic_get_pci_slot(ahc->dev_softc), + aic_get_pci_function(ahc->dev_softc)); iounmap((void *)((u_long)maddr & PAGE_MASK)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(ahc->platform_data->mem_busaddr, 0x1000); -#endif ahc->bsh.maddr = NULL; maddr = NULL; } else @@ -345,12 +309,11 @@ } else { printf("aic7xxx: PCI%d:%d:%d MEM region 0x%lx " "unavailable. Cannot memory map device.\n", - ahc_get_pci_bus(ahc->dev_softc), - ahc_get_pci_slot(ahc->dev_softc), - ahc_get_pci_function(ahc->dev_softc), + aic_get_pci_bus(ahc->dev_softc), + aic_get_pci_slot(ahc->dev_softc), + aic_get_pci_function(ahc->dev_softc), base); } -#endif /* MMAPIO */ /* * We always prefer memory mapped access. @@ -358,20 +321,20 @@ if (maddr == NULL) { error = ahc_linux_pci_reserve_io_region(ahc, &base); - if (error == 0) { + if (error == 0 && ahc_pci_test_register_access(ahc) == 0) { ahc->tag = BUS_SPACE_PIO; ahc->bsh.ioport = base; command |= PCIM_CMD_PORTEN; } else { printf("aic7xxx: PCI%d:%d:%d IO region 0x%lx[0..255] " "unavailable. Cannot map device.\n", - ahc_get_pci_bus(ahc->dev_softc), - ahc_get_pci_slot(ahc->dev_softc), - ahc_get_pci_function(ahc->dev_softc), + aic_get_pci_bus(ahc->dev_softc), + aic_get_pci_slot(ahc->dev_softc), + aic_get_pci_function(ahc->dev_softc), base); } } - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, 4); + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, 4); return (error); } @@ -380,49 +343,10 @@ { int error; - error = request_irq(ahc->dev_softc->irq, ahc_linux_isr, + error = request_irq(aic_pci_dev(ahc)->irq, ahc_linux_isr, SA_SHIRQ, "aic7xxx", ahc); if (error == 0) - ahc->platform_data->irq = ahc->dev_softc->irq; + ahc->platform_data->irq = aic_pci_dev(ahc)->irq; return (-error); -} - -void -ahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - pci_set_power_state(ahc->dev_softc, new_state); -#else - uint32_t cap; - u_int cap_offset; - - /* - * Traverse the capability list looking for - * the power management capability. - */ - cap = 0; - cap_offset = ahc_pci_read_config(ahc->dev_softc, - PCIR_CAP_PTR, /*bytes*/1); - while (cap_offset != 0) { - - cap = ahc_pci_read_config(ahc->dev_softc, - cap_offset, /*bytes*/4); - if ((cap & 0xFF) == 1 - && ((cap >> 16) & 0x3) > 0) { - uint32_t pm_control; - - pm_control = ahc_pci_read_config(ahc->dev_softc, - cap_offset + 4, - /*bytes*/4); - pm_control &= ~0x3; - pm_control |= new_state; - ahc_pci_write_config(ahc->dev_softc, - cap_offset + 4, - pm_control, /*bytes*/2); - break; - } - cap_offset = (cap >> 8) & 0xFF; - } -#endif } diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_pci.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_pci.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_pci.c Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_pci.c Tue Feb 10 00:15:16 2004 @@ -39,9 +39,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#69 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#78 $ */ #ifdef __linux__ @@ -49,14 +47,13 @@ #include "aic7xxx_inline.h" #include "aic7xxx_93cx6.h" #else +#include +__FBSDID("$FreeBSD$"); #include #include #include #endif -#define AHC_PCI_IOADDR PCIR_MAPS /* I/O Address */ -#define AHC_PCI_MEMADDR (PCIR_MAPS + 4) /* Mem I/O Address */ - static __inline uint64_t ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) { @@ -133,6 +130,7 @@ #define ID_AHA_29160C 0x0080900562209005ull #define ID_AHA_29160B 0x00809005E2209005ull #define ID_AHA_19160B 0x0081900562A19005ull +#define ID_AHA_2915_30LP 0x0082900502109005ull #define ID_AIC7896 0x005F9005FFFF9005ull #define ID_AIC7896_ARO 0x00539005FFFF9005ull @@ -470,6 +468,12 @@ "Adaptec aic7892 Ultra160 SCSI adapter (ARO)", ahc_aic7892_setup }, + { + ID_AHA_2915_30LP, + ID_ALL_MASK, + "Adaptec 2915/30LP Ultra160 SCSI adapter", + ahc_aic7892_setup + }, /* aic7895 based controllers */ { ID_AHA_2940U_DUAL, @@ -738,7 +742,7 @@ } struct ahc_pci_identity * -ahc_find_pci_device(ahc_dev_softc_t pci) +ahc_find_pci_device(aic_dev_softc_t pci) { uint64_t full_id; uint16_t device; @@ -748,10 +752,10 @@ struct ahc_pci_identity *entry; u_int i; - vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); - device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); - subvendor = ahc_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); - subdevice = ahc_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); + vendor = aic_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); + device = aic_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); + subvendor = aic_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); + subdevice = aic_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); full_id = ahc_compose_id(device, vendor, subdevice, subvendor); /* @@ -761,7 +765,7 @@ * to sanity check it prior to accepting the subdevice * ID as valid. */ - if (ahc_get_pci_function(pci) > 0 + if (aic_get_pci_function(pci) > 0 && ahc_9005_subdevinfo_valid(vendor, device, subvendor, subdevice) && SUBID_9005_MFUNCENB(subdevice) == 0) return (NULL); @@ -798,7 +802,7 @@ ahc->chip |= AHC_PCI; ahc->description = entry->name; - ahc_power_state_change(ahc, AHC_POWER_STATE_D0); + aic_power_state_change(ahc, AIC_POWER_STATE_D0); error = ahc_pci_map_registers(ahc); if (error != 0) @@ -812,7 +816,7 @@ */ ahc_intr_enable(ahc, FALSE); - devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); /* * If we need to support high memory, enable dual @@ -831,13 +835,13 @@ /* Ensure that pci error generation, a test feature, is disabled. */ devconfig |= PCIERRGENDIS; - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); + aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); /* Ensure busmastering is enabled */ - command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); + command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); command |= PCIM_CMD_BUSMASTEREN; - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2); + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2); /* On all PCI adapters, we allow SCB paging */ ahc->flags |= AHC_PAGESCBS; @@ -920,14 +924,14 @@ ahc_outb(ahc, DSCOMMAND0, dscommand0); ahc->pci_cachesize = - ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, + aic_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1) & CACHESIZE; ahc->pci_cachesize *= 4; if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0 && ahc->pci_cachesize == 4) { - ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, + aic_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, 0, /*bytes*/1); ahc->pci_cachesize = 0; } @@ -939,7 +943,7 @@ if ((ahc->features & AHC_ULTRA) != 0) { uint32_t devconfig; - devconfig = ahc_pci_read_config(ahc->dev_softc, + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); if ((devconfig & REXTVALID) == 0) ahc->features &= ~AHC_ULTRA; @@ -1005,11 +1009,11 @@ * that occur during runtime and resume events. */ ahc->bus_softc.pci_softc.devconfig = - ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); + aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); ahc->bus_softc.pci_softc.command = - ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); + aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); ahc->bus_softc.pci_softc.csize_lattime = - ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1); + aic_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1); ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0); ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS); if ((ahc->features & AHC_DT) != 0) { @@ -1063,7 +1067,7 @@ uint32_t devconfig; chip = ahc->chip & AHC_CHIPID_MASK; - devconfig = ahc_pci_read_config(ahc->dev_softc, + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); single_user = (devconfig & MPORTMODE) != 0; @@ -1101,13 +1105,13 @@ * Set the SCB Base addr (highest address bit) * depending on which channel we are. */ - ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc)); + ahc_outb(ahc, SCBBADDR, aic_get_pci_function(ahc->dev_softc)); } ahc->flags &= ~AHC_LSCBS_ENABLED; if (large) ahc->flags |= AHC_LSCBS_ENABLED; - devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); if ((ahc->features & AHC_ULTRA2) != 0) { u_int dscommand0; @@ -1140,7 +1144,7 @@ else devconfig &= ~EXTSCBPEN; - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); + aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); } /* @@ -1263,8 +1267,8 @@ * Enable PCI error interrupt status, but suppress NMIs * generated by SERR raised due to target aborts. */ - cmd = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, + cmd = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2); /* @@ -1276,24 +1280,36 @@ * use for this test. */ hcntrl = ahc_inb(ahc, HCNTRL); + if (hcntrl == 0xFF) goto fail; + if ((hcntrl & CHIPRST) != 0) { + /* + * The chip has not been initialized since + * PCI/EISA/VLB bus reset. Don't trust + * "left over BIOS data". + */ + ahc->flags |= AHC_NO_BIOS_INIT; + } + /* * Next create a situation where write combining * or read prefetching could be initiated by the * CPU or host bridge. Our device does not support * either, so look for data corruption and/or flagged - * PCI errors. + * PCI errors. First pause without causing another + * chip reset. */ + hcntrl &= ~CHIPRST; ahc_outb(ahc, HCNTRL, hcntrl|PAUSE); while (ahc_is_paused(ahc) == 0) ; /* Clear any PCI errors that occurred before our driver attached. */ - status1 = ahc_pci_read_config(ahc->dev_softc, + status1 = aic_pci_read_config(ahc->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, status1, /*bytes*/1); ahc_outb(ahc, CLRINT, CLRPARERR); @@ -1303,7 +1319,7 @@ if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa) goto fail; - status1 = ahc_pci_read_config(ahc->dev_softc, + status1 = aic_pci_read_config(ahc->dev_softc, PCIR_STATUS + 1, /*bytes*/1); if ((status1 & STA) != 0) goto fail; @@ -1312,13 +1328,13 @@ fail: /* Silently clear any latched errors. */ - status1 = ahc_pci_read_config(ahc->dev_softc, + status1 = aic_pci_read_config(ahc->dev_softc, PCIR_STATUS + 1, /*bytes*/1); - ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, status1, /*bytes*/1); ahc_outb(ahc, CLRINT, CLRPARERR); ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS); - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); return (error); } @@ -1388,6 +1404,10 @@ sd.sd_chip = C56_66; } ahc_release_seeprom(&sd); + + /* Remember the SEEPROM type for later */ + if (sd.sd_chip == C56_66) + ahc->flags |= AHC_LARGE_SEEPROM; } if (!have_seeprom) { @@ -1573,12 +1593,12 @@ uint32_t devconfig; /* Honor the STPWLEVEL settings */ - devconfig = ahc_pci_read_config(ahc->dev_softc, + devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); devconfig &= ~STPWLEVEL; if ((sc->bios_control & CFSTPWLEVEL) != 0) devconfig |= STPWLEVEL; - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, + aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); } /* Set SCSICONF info */ @@ -1891,10 +1911,10 @@ ahc_outb(ahc, SPIOCAP, spiocap); ahc_outb(ahc, BRDCTL, BRDRW|BRDCS); ahc_flush_device_writes(ahc); - ahc_delay(500); + aic_delay(500); ahc_outb(ahc, BRDCTL, 0); ahc_flush_device_writes(ahc); - ahc_delay(500); + aic_delay(500); brdctl = ahc_inb(ahc, BRDCTL); *internal50_present = (brdctl & BRDDAT5) ? 0 : 1; *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; @@ -1920,7 +1940,7 @@ SEEPROM_OUTB(sd, sd->sd_MS); wait = 1000; /* 1 second timeout in msec */ while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) { - ahc_delay(1000); /* delay 1 msec */ + aic_delay(1000); /* delay 1 msec */ } if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) { SEEPROM_OUTB(sd, 0); @@ -2000,7 +2020,7 @@ if ((error & PCIERRSTAT) == 0) return; - status1 = ahc_pci_read_config(ahc->dev_softc, + status1 = aic_pci_read_config(ahc->dev_softc, PCIR_STATUS + 1, /*bytes*/1); printf("%s: PCI error Interrupt at seqaddr = 0x%x\n", @@ -2030,7 +2050,7 @@ } /* Clear latched errors. */ - ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, + aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, status1, /*bytes*/1); if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) { @@ -2091,7 +2111,7 @@ ahc_pci_resume(struct ahc_softc *ahc) { - ahc_power_state_change(ahc, AHC_POWER_STATE_D0); + aic_power_state_change(ahc, AIC_POWER_STATE_D0); /* * We assume that the OS has restored our register @@ -2099,11 +2119,11 @@ * that the OS doesn't know about and rely on our chip * reset handler to handle the rest. */ - ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4, + aic_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4, ahc->bus_softc.pci_softc.devconfig); - ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1, + aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1, ahc->bus_softc.pci_softc.command); - ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1, + aic_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1, ahc->bus_softc.pci_softc.csize_lattime); if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) { struct seeprom_descriptor sd; @@ -2126,7 +2146,7 @@ static int ahc_aic785X_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; @@ -2134,7 +2154,7 @@ ahc->chip = AHC_AIC7850; ahc->features = AHC_AIC7850_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; ahc->instruction_ram_size = 512; @@ -2144,7 +2164,7 @@ static int ahc_aic7860_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; @@ -2152,7 +2172,7 @@ ahc->chip = AHC_AIC7860; ahc->features = AHC_AIC7860_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; ahc->instruction_ram_size = 512; @@ -2219,7 +2239,7 @@ static int ahc_aic7880_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; @@ -2227,7 +2247,7 @@ ahc->chip = AHC_AIC7880; ahc->features = AHC_AIC7880_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) { ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; } else { @@ -2270,7 +2290,7 @@ static int ahc_aic7890_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; @@ -2278,7 +2298,7 @@ ahc->chip = AHC_AIC7890; ahc->features = AHC_AIC7890_FE; ahc->flags |= AHC_NEWEEPROM_FMT; - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev == 0) ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG; ahc->instruction_ram_size = 768; @@ -2301,15 +2321,15 @@ static int ahc_aic7895_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; - ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; + ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A'; /* * The 'C' revision of the aic7895 has a few additional features. */ - rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); + rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 4) { ahc->chip = AHC_AIC7895C; ahc->features = AHC_AIC7895C_FE; @@ -2325,9 +2345,9 @@ * we have. Disabling MWI reduces performance, so * turn it on again. */ - command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1); + command = aic_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1); command |= PCIM_CMD_MWRICEN; - ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1); + aic_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1); ahc->bugs |= AHC_PCI_MWI_BUG; } /* @@ -2344,10 +2364,10 @@ * Cachesize must also be zero due to stray DAC * problem when sitting behind some bridges. */ - ahc_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1); - devconfig = ahc_pci_read_config(pci, DEVCONFIG, /*bytes*/1); + aic_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1); + devconfig = aic_pci_read_config(pci, DEVCONFIG, /*bytes*/1); devconfig |= MRDCEN; - ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1); + aic_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1); #endif ahc->flags |= AHC_NEWEEPROM_FMT; ahc->instruction_ram_size = 512; @@ -2357,10 +2377,10 @@ static int ahc_aic7896_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; + ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A'; ahc->chip = AHC_AIC7896; ahc->features = AHC_AIC7896_FE; ahc->flags |= AHC_NEWEEPROM_FMT; @@ -2372,10 +2392,10 @@ static int ahc_aic7899_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; + ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A'; ahc->chip = AHC_AIC7899; ahc->features = AHC_AIC7899_FE; ahc->flags |= AHC_NEWEEPROM_FMT; @@ -2406,10 +2426,10 @@ static int ahc_aha394XX_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - switch (ahc_get_pci_slot(pci)) { + switch (aic_get_pci_slot(pci)) { case AHC_394X_SLOT_CHANNEL_A: ahc->channel = 'A'; break; @@ -2419,7 +2439,7 @@ default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", - ahc_get_pci_slot(pci)); + aic_get_pci_slot(pci)); ahc->channel = 'A'; } return (0); @@ -2428,10 +2448,10 @@ static int ahc_aha398XX_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - switch (ahc_get_pci_slot(pci)) { + switch (aic_get_pci_slot(pci)) { case AHC_398X_SLOT_CHANNEL_A: ahc->channel = 'A'; break; @@ -2444,7 +2464,7 @@ default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", - ahc_get_pci_slot(pci)); + aic_get_pci_slot(pci)); ahc->channel = 'A'; break; } @@ -2455,10 +2475,10 @@ static int ahc_aha494XX_setup(struct ahc_softc *ahc) { - ahc_dev_softc_t pci; + aic_dev_softc_t pci; pci = ahc->dev_softc; - switch (ahc_get_pci_slot(pci)) { + switch (aic_get_pci_slot(pci)) { case AHC_494X_SLOT_CHANNEL_A: ahc->channel = 'A'; break; @@ -2474,7 +2494,7 @@ default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", - ahc_get_pci_slot(pci)); + aic_get_pci_slot(pci)); ahc->channel = 'A'; } ahc->flags |= AHC_LARGE_SEEPROM; diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_proc.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_proc.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_proc.c Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_proc.c Tue Feb 10 00:15:16 2004 @@ -37,7 +37,7 @@ * String handling code courtesy of Gerard Roudier's * sym driver. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#29 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#32 $ */ #include "aic7xxx_osm.h" #include "aic7xxx_inline.h" @@ -50,7 +50,7 @@ u_int our_id, char channel, u_int target_id, u_int target_offset); static void ahc_dump_device_state(struct info_str *info, - struct ahc_linux_device *dev); + struct aic_linux_device *dev); static int ahc_proc_write_seeprom(struct ahc_softc *ahc, char *buffer, int length); @@ -141,7 +141,7 @@ u_int our_id, char channel, u_int target_id, u_int target_offset) { - struct ahc_linux_target *targ; + struct aic_linux_target *targ; struct ahc_initiator_tinfo *tinfo; struct ahc_tmode_tstate *tstate; int lun; @@ -163,7 +163,7 @@ ahc_format_transinfo(info, &tinfo->curr); for (lun = 0; lun < AHC_NUM_LUNS; lun++) { - struct ahc_linux_device *dev; + struct aic_linux_device *dev; dev = targ->devices[lun]; @@ -175,7 +175,7 @@ } static void -ahc_dump_device_state(struct info_str *info, struct ahc_linux_device *dev) +ahc_dump_device_state(struct info_str *info, struct aic_linux_device *dev) { copy_info(info, "\tChannel %c Target %d Lun %d Settings\n", dev->target->channel + 'A', dev->target->target, dev->lun); @@ -204,7 +204,8 @@ ahc_pause(ahc); if (length != sizeof(struct seeprom_config)) { - printf("ahc_proc_write_seeprom: incorrect buffer size\n"); + printf("ahc_proc_write_seeprom: incorrect buffer size %d\n", + length); goto done; } @@ -215,7 +216,7 @@ } sd.sd_ahc = ahc; -#if AHC_PCI_CONFIG > 0 +#if AIC_PCI_CONFIG > 0 if ((ahc->chip & AHC_PCI) != 0) { sd.sd_control_offset = SEECTL; sd.sd_status_offset = SEECTL; @@ -271,7 +272,7 @@ sizeof(struct seeprom_config)/2); ahc_read_seeprom(&sd, (uint16_t *)ahc->seep_config, start_addr, sizeof(struct seeprom_config)/2); -#if AHC_PCI_CONFIG > 0 +#if AIC_PCI_CONFIG > 0 if ((ahc->chip & AHC_VL) == 0) ahc_release_seeprom(&sd); #endif diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_reg.h linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_reg.h --- linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_reg.h Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_reg.h Tue Feb 10 00:15:16 2004 @@ -2,8 +2,8 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $ - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $ */ typedef int (ahc_reg_print_t)(u_int, u_int *, u_int); typedef struct ahc_reg_parse_entry { @@ -1298,7 +1298,6 @@ #define CMDSIZE_TABLE_TAIL 0x34 #define MWI_RESIDUAL 0x38 -#define TARG_IMMEDIATE_SCB 0x38 #define NEXT_QUEUED_SCB 0x39 @@ -1380,6 +1379,7 @@ #define RETURN_2 0x52 #define LAST_MSG 0x53 +#define TARG_IMMEDIATE_SCB 0x53 #define SCSISEQ_TEMPLATE 0x54 #define ENSELO 0x40 diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_reg_print.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_reg_print.c --- linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_reg_print.c Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_reg_print.c Tue Feb 10 00:15:16 2004 @@ -2,8 +2,8 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $ - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $ */ #include "aic7xxx_osm.h" diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_seq.h linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_seq.h --- linux-2.4.25/drivers/scsi/aic7xxx/aic7xxx_seq.h Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aic7xxx_seq.h Tue Feb 10 00:15:16 2004 @@ -2,13 +2,13 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $ - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $ */ static uint8_t seqprog[] = { 0xb2, 0x00, 0x00, 0x08, 0xf7, 0x11, 0x22, 0x08, - 0x00, 0x65, 0xec, 0x59, + 0x00, 0x65, 0xee, 0x59, 0xf7, 0x01, 0x02, 0x08, 0xff, 0x6a, 0x24, 0x08, 0x40, 0x00, 0x40, 0x68, @@ -21,15 +21,15 @@ 0x01, 0x4d, 0xc8, 0x30, 0x00, 0x4c, 0x12, 0x70, 0x01, 0x39, 0xa2, 0x30, - 0x00, 0x6a, 0xc0, 0x5e, + 0x00, 0x6a, 0xc2, 0x5e, 0x01, 0x51, 0x20, 0x31, 0x01, 0x57, 0xae, 0x00, 0x0d, 0x6a, 0x76, 0x00, - 0x00, 0x51, 0x12, 0x5e, + 0x00, 0x51, 0x14, 0x5e, 0x01, 0x51, 0xc8, 0x30, 0x00, 0x39, 0xc8, 0x60, 0x00, 0xbb, 0x30, 0x70, - 0xc1, 0x6a, 0xd8, 0x5e, + 0xc1, 0x6a, 0xda, 0x5e, 0x01, 0xbf, 0x72, 0x30, 0x01, 0x40, 0x7e, 0x31, 0x01, 0x90, 0x80, 0x30, @@ -49,10 +49,10 @@ 0x08, 0x6a, 0x78, 0x00, 0x01, 0x50, 0xc8, 0x30, 0xe0, 0x6a, 0xcc, 0x00, - 0x48, 0x6a, 0xfc, 0x5d, + 0x48, 0x6a, 0xfe, 0x5d, 0x01, 0x6a, 0xdc, 0x01, 0x88, 0x6a, 0xcc, 0x00, - 0x48, 0x6a, 0xfc, 0x5d, + 0x48, 0x6a, 0xfe, 0x5d, 0x01, 0x6a, 0x26, 0x01, 0xf0, 0x19, 0x7a, 0x08, 0x0f, 0x18, 0xc8, 0x08, @@ -93,7 +93,7 @@ 0x00, 0x65, 0x20, 0x41, 0x02, 0x57, 0xae, 0x00, 0x00, 0x65, 0x9e, 0x40, - 0x61, 0x6a, 0xd8, 0x5e, + 0x61, 0x6a, 0xda, 0x5e, 0x08, 0x51, 0x20, 0x71, 0x02, 0x0b, 0xb2, 0x78, 0x00, 0x65, 0xae, 0x40, @@ -106,7 +106,7 @@ 0x80, 0x3d, 0x7a, 0x00, 0x20, 0x6a, 0x16, 0x00, 0x00, 0x65, 0xcc, 0x41, - 0x00, 0x65, 0xb2, 0x5e, + 0x00, 0x65, 0xb4, 0x5e, 0x00, 0x65, 0x12, 0x40, 0x20, 0x11, 0xd2, 0x68, 0x20, 0x6a, 0x18, 0x00, @@ -140,27 +140,27 @@ 0x80, 0x0b, 0xc4, 0x79, 0x12, 0x01, 0x02, 0x00, 0x01, 0xab, 0xac, 0x30, - 0xe4, 0x6a, 0x6e, 0x5d, + 0xe4, 0x6a, 0x70, 0x5d, 0x40, 0x6a, 0x16, 0x00, - 0x80, 0x3e, 0x84, 0x5d, + 0x80, 0x3e, 0x86, 0x5d, 0x20, 0xb8, 0x18, 0x79, - 0x20, 0x6a, 0x84, 0x5d, - 0x00, 0xab, 0x84, 0x5d, + 0x20, 0x6a, 0x86, 0x5d, + 0x00, 0xab, 0x86, 0x5d, 0x01, 0xa9, 0x78, 0x30, 0x10, 0xb8, 0x20, 0x79, - 0xe4, 0x6a, 0x6e, 0x5d, + 0xe4, 0x6a, 0x70, 0x5d, 0x00, 0x65, 0xae, 0x40, 0x10, 0x03, 0x3c, 0x69, 0x08, 0x3c, 0x5a, 0x69, 0x04, 0x3c, 0x92, 0x69, 0x02, 0x3c, 0x98, 0x69, 0x01, 0x3c, 0x44, 0x79, - 0xff, 0x6a, 0x70, 0x00, + 0xff, 0x6a, 0xa6, 0x00, 0x00, 0x65, 0xa4, 0x59, - 0x00, 0x6a, 0xc0, 0x5e, - 0xff, 0x38, 0x30, 0x71, + 0x00, 0x6a, 0xc2, 0x5e, + 0xff, 0x53, 0x30, 0x71, 0x0d, 0x6a, 0x76, 0x00, - 0x00, 0x38, 0x12, 0x5e, + 0x00, 0x53, 0x14, 0x5e, 0x00, 0x65, 0xea, 0x58, 0x12, 0x01, 0x02, 0x00, 0x00, 0x65, 0x18, 0x41, @@ -168,10 +168,10 @@ 0x00, 0x65, 0xf2, 0x58, 0xfd, 0x57, 0xae, 0x08, 0x00, 0x65, 0xae, 0x40, - 0xe4, 0x6a, 0x6e, 0x5d, + 0xe4, 0x6a, 0x70, 0x5d, 0x20, 0x3c, 0x4a, 0x79, - 0x02, 0x6a, 0x84, 0x5d, - 0x04, 0x6a, 0x84, 0x5d, + 0x02, 0x6a, 0x86, 0x5d, + 0x04, 0x6a, 0x86, 0x5d, 0x01, 0x03, 0x4c, 0x69, 0xf7, 0x11, 0x22, 0x08, 0xff, 0x6a, 0x24, 0x08, @@ -182,13 +182,13 @@ 0x80, 0x86, 0xc8, 0x08, 0x01, 0x4f, 0xc8, 0x30, 0x00, 0x50, 0x6c, 0x61, - 0xc4, 0x6a, 0x6e, 0x5d, + 0xc4, 0x6a, 0x70, 0x5d, 0x40, 0x3c, 0x68, 0x79, - 0x28, 0x6a, 0x84, 0x5d, + 0x28, 0x6a, 0x86, 0x5d, 0x00, 0x65, 0x4c, 0x41, - 0x08, 0x6a, 0x84, 0x5d, + 0x08, 0x6a, 0x86, 0x5d, 0x00, 0x65, 0x4c, 0x41, - 0x84, 0x6a, 0x6e, 0x5d, + 0x84, 0x6a, 0x70, 0x5d, 0x00, 0x65, 0xf2, 0x58, 0x01, 0x66, 0xc8, 0x30, 0x01, 0x64, 0xd8, 0x31, @@ -208,16 +208,16 @@ 0xf7, 0x3c, 0x78, 0x08, 0x00, 0x65, 0x20, 0x41, 0x40, 0xaa, 0x7e, 0x10, - 0x04, 0xaa, 0x6e, 0x5d, - 0x00, 0x65, 0x56, 0x42, - 0xc4, 0x6a, 0x6e, 0x5d, + 0x04, 0xaa, 0x70, 0x5d, + 0x00, 0x65, 0x58, 0x42, + 0xc4, 0x6a, 0x70, 0x5d, 0xc0, 0x6a, 0x7e, 0x00, - 0x00, 0xa8, 0x84, 0x5d, + 0x00, 0xa8, 0x86, 0x5d, 0xe4, 0x6a, 0x06, 0x00, - 0x00, 0x6a, 0x84, 0x5d, + 0x00, 0x6a, 0x86, 0x5d, 0x00, 0x65, 0x4c, 0x41, 0x10, 0x3c, 0xa8, 0x69, - 0x00, 0xbb, 0x8a, 0x44, + 0x00, 0xbb, 0x8c, 0x44, 0x18, 0x6a, 0xda, 0x01, 0x01, 0x69, 0xd8, 0x31, 0x1c, 0x6a, 0xd0, 0x01, @@ -227,31 +227,32 @@ 0x01, 0x93, 0x26, 0x01, 0x03, 0x6a, 0x2a, 0x01, 0x01, 0x69, 0x32, 0x31, - 0x1c, 0x6a, 0xe0, 0x5d, + 0x1c, 0x6a, 0xe2, 0x5d, 0x0a, 0x93, 0x26, 0x01, - 0x00, 0x65, 0xa8, 0x5e, + 0x00, 0x65, 0xaa, 0x5e, 0x01, 0x50, 0xa0, 0x18, 0x02, 0x6a, 0x22, 0x05, 0x1a, 0x01, 0x02, 0x00, 0x80, 0x6a, 0x74, 0x00, 0x40, 0x6a, 0x78, 0x00, 0x40, 0x6a, 0x16, 0x00, - 0x00, 0x65, 0xd8, 0x5d, + 0x00, 0x65, 0xda, 0x5d, 0x01, 0x3f, 0xc8, 0x30, - 0xbf, 0x64, 0x56, 0x7a, - 0x80, 0x64, 0x9e, 0x73, - 0xa0, 0x64, 0x00, 0x74, - 0xc0, 0x64, 0xf4, 0x73, - 0xe0, 0x64, 0x30, 0x74, - 0x01, 0x6a, 0xd8, 0x5e, + 0xbf, 0x64, 0x58, 0x7a, + 0x80, 0x64, 0xa0, 0x73, + 0xa0, 0x64, 0x02, 0x74, + 0xc0, 0x64, 0xf6, 0x73, + 0xe0, 0x64, 0x32, 0x74, + 0x01, 0x6a, 0xda, 0x5e, 0x00, 0x65, 0xcc, 0x41, 0xf7, 0x11, 0x22, 0x08, 0x01, 0x06, 0xd4, 0x30, 0xff, 0x6a, 0x24, 0x08, 0xf7, 0x01, 0x02, 0x08, - 0x09, 0x0c, 0xe6, 0x79, + 0xc0, 0x6a, 0x78, 0x00, + 0x09, 0x0c, 0xe8, 0x79, 0x08, 0x0c, 0x04, 0x68, - 0xb1, 0x6a, 0xd8, 0x5e, + 0xb1, 0x6a, 0xda, 0x5e, 0xff, 0x6a, 0x26, 0x09, 0x12, 0x01, 0x02, 0x00, 0x02, 0x6a, 0x08, 0x30, @@ -264,29 +265,29 @@ 0x00, 0xa5, 0x4a, 0x21, 0x00, 0xa6, 0x4c, 0x21, 0x00, 0xa7, 0x4e, 0x25, - 0x08, 0xeb, 0xdc, 0x7e, - 0x80, 0xeb, 0x06, 0x7a, + 0x08, 0xeb, 0xde, 0x7e, + 0x80, 0xeb, 0x08, 0x7a, 0xff, 0x6a, 0xd6, 0x09, - 0x08, 0xeb, 0x0a, 0x6a, + 0x08, 0xeb, 0x0c, 0x6a, 0xff, 0x6a, 0xd4, 0x0c, - 0x80, 0xa3, 0xdc, 0x6e, - 0x88, 0xeb, 0x20, 0x72, - 0x08, 0xeb, 0xdc, 0x6e, - 0x04, 0xea, 0x24, 0xe2, - 0x08, 0xee, 0xdc, 0x6e, + 0x80, 0xa3, 0xde, 0x6e, + 0x88, 0xeb, 0x22, 0x72, + 0x08, 0xeb, 0xde, 0x6e, + 0x04, 0xea, 0x26, 0xe2, + 0x08, 0xee, 0xde, 0x6e, 0x04, 0x6a, 0xd0, 0x81, 0x05, 0xa4, 0xc0, 0x89, 0x03, 0xa5, 0xc2, 0x31, 0x09, 0x6a, 0xd6, 0x05, - 0x00, 0x65, 0x08, 0x5a, + 0x00, 0x65, 0x0a, 0x5a, 0x06, 0xa4, 0xd4, 0x89, - 0x80, 0x94, 0xdc, 0x7e, + 0x80, 0x94, 0xde, 0x7e, 0x07, 0xe9, 0x10, 0x31, 0x01, 0xe9, 0x46, 0x31, - 0x00, 0xa3, 0xba, 0x5e, - 0x00, 0x65, 0xfa, 0x59, + 0x00, 0xa3, 0xbc, 0x5e, + 0x00, 0x65, 0xfc, 0x59, 0x01, 0xa4, 0xca, 0x30, - 0x80, 0xa3, 0x34, 0x7a, + 0x80, 0xa3, 0x36, 0x7a, 0x02, 0x65, 0xca, 0x00, 0x01, 0x65, 0xf8, 0x31, 0x80, 0x93, 0x26, 0x01, @@ -294,162 +295,162 @@ 0x01, 0x8c, 0xc8, 0x30, 0x00, 0x88, 0xc8, 0x18, 0x02, 0x64, 0xc8, 0x88, - 0xff, 0x64, 0xdc, 0x7e, - 0xff, 0x8d, 0x4a, 0x6a, - 0xff, 0x8e, 0x4a, 0x6a, + 0xff, 0x64, 0xde, 0x7e, + 0xff, 0x8d, 0x4c, 0x6a, + 0xff, 0x8e, 0x4c, 0x6a, 0x03, 0x8c, 0xd4, 0x98, - 0x00, 0x65, 0xdc, 0x56, + 0x00, 0x65, 0xde, 0x56, 0x01, 0x64, 0x70, 0x30, 0xff, 0x64, 0xc8, 0x10, 0x01, 0x64, 0xc8, 0x18, 0x00, 0x8c, 0x18, 0x19, 0xff, 0x8d, 0x1a, 0x21, 0xff, 0x8e, 0x1c, 0x25, - 0xc0, 0x3c, 0x5a, 0x7a, - 0x21, 0x6a, 0xd8, 0x5e, + 0xc0, 0x3c, 0x5c, 0x7a, + 0x21, 0x6a, 0xda, 0x5e, 0xa8, 0x6a, 0x76, 0x00, 0x79, 0x6a, 0x76, 0x00, - 0x40, 0x3f, 0x62, 0x6a, + 0x40, 0x3f, 0x64, 0x6a, 0x04, 0x3b, 0x76, 0x00, 0x04, 0x6a, 0xd4, 0x81, - 0x20, 0x3c, 0x6a, 0x7a, - 0x51, 0x6a, 0xd8, 0x5e, - 0x00, 0x65, 0x82, 0x42, + 0x20, 0x3c, 0x6c, 0x7a, + 0x51, 0x6a, 0xda, 0x5e, + 0x00, 0x65, 0x84, 0x42, 0x20, 0x3c, 0x78, 0x00, - 0x00, 0xb3, 0xba, 0x5e, + 0x00, 0xb3, 0xbc, 0x5e, 0x07, 0xac, 0x10, 0x31, 0x05, 0xb3, 0x46, 0x31, 0x88, 0x6a, 0xcc, 0x00, - 0xac, 0x6a, 0xee, 0x5d, + 0xac, 0x6a, 0xf0, 0x5d, 0xa3, 0x6a, 0xcc, 0x00, - 0xb3, 0x6a, 0xf2, 0x5d, - 0x00, 0x65, 0x3a, 0x5a, + 0xb3, 0x6a, 0xf4, 0x5d, + 0x00, 0x65, 0x3c, 0x5a, 0xfd, 0xa4, 0x48, 0x09, 0x03, 0x8c, 0x10, 0x30, - 0x00, 0x65, 0xe6, 0x5d, - 0x01, 0xa4, 0x94, 0x7a, + 0x00, 0x65, 0xe8, 0x5d, + 0x01, 0xa4, 0x96, 0x7a, 0x04, 0x3b, 0x76, 0x08, 0x01, 0x3b, 0x26, 0x31, 0x80, 0x02, 0x04, 0x00, - 0x10, 0x0c, 0x8a, 0x7a, - 0x03, 0x9e, 0x8c, 0x6a, + 0x10, 0x0c, 0x8c, 0x7a, + 0x03, 0x9e, 0x8e, 0x6a, 0x7f, 0x02, 0x04, 0x08, - 0x91, 0x6a, 0xd8, 0x5e, + 0x91, 0x6a, 0xda, 0x5e, 0x00, 0x65, 0xcc, 0x41, 0x01, 0xa4, 0xca, 0x30, - 0x80, 0xa3, 0x9a, 0x7a, + 0x80, 0xa3, 0x9c, 0x7a, 0x02, 0x65, 0xca, 0x00, 0x01, 0x65, 0xf8, 0x31, 0x01, 0x3b, 0x26, 0x31, - 0x00, 0x65, 0x0e, 0x5a, - 0x01, 0xfc, 0xa8, 0x6a, - 0x80, 0x0b, 0x9e, 0x6a, - 0x10, 0x0c, 0x9e, 0x7a, - 0x20, 0x93, 0x9e, 0x6a, + 0x00, 0x65, 0x10, 0x5a, + 0x01, 0xfc, 0xaa, 0x6a, + 0x80, 0x0b, 0xa0, 0x6a, + 0x10, 0x0c, 0xa0, 0x7a, + 0x20, 0x93, 0xa0, 0x6a, 0x02, 0x93, 0x26, 0x01, - 0x02, 0xfc, 0xb2, 0x7a, - 0x40, 0x0d, 0xc6, 0x6a, + 0x02, 0xfc, 0xb4, 0x7a, + 0x40, 0x0d, 0xc8, 0x6a, 0x01, 0xa4, 0x48, 0x01, - 0x00, 0x65, 0xc6, 0x42, - 0x40, 0x0d, 0xb8, 0x6a, - 0x00, 0x65, 0x0e, 0x5a, - 0x00, 0x65, 0xaa, 0x42, - 0x80, 0xfc, 0xc2, 0x7a, - 0x80, 0xa4, 0xc2, 0x6a, + 0x00, 0x65, 0xc8, 0x42, + 0x40, 0x0d, 0xba, 0x6a, + 0x00, 0x65, 0x10, 0x5a, + 0x00, 0x65, 0xac, 0x42, + 0x80, 0xfc, 0xc4, 0x7a, + 0x80, 0xa4, 0xc4, 0x6a, 0xff, 0xa5, 0x4a, 0x19, 0xff, 0xa6, 0x4c, 0x21, 0xff, 0xa7, 0x4e, 0x21, 0xf8, 0xfc, 0x48, 0x09, 0x7f, 0xa3, 0x46, 0x09, - 0x04, 0x3b, 0xe2, 0x6a, + 0x04, 0x3b, 0xe4, 0x6a, 0x02, 0x93, 0x26, 0x01, - 0x01, 0x94, 0xc8, 0x7a, - 0x01, 0x94, 0xc8, 0x7a, - 0x01, 0x94, 0xc8, 0x7a, - 0x01, 0x94, 0xc8, 0x7a, - 0x01, 0x94, 0xc8, 0x7a, - 0x01, 0xa4, 0xe0, 0x7a, - 0x01, 0xfc, 0xd6, 0x7a, - 0x01, 0x94, 0xe2, 0x6a, - 0x01, 0x94, 0xe2, 0x6a, - 0x01, 0x94, 0xe2, 0x6a, - 0x00, 0x65, 0x82, 0x42, - 0x01, 0x94, 0xe0, 0x7a, - 0x10, 0x94, 0xe2, 0x6a, + 0x01, 0x94, 0xca, 0x7a, + 0x01, 0x94, 0xca, 0x7a, + 0x01, 0x94, 0xca, 0x7a, + 0x01, 0x94, 0xca, 0x7a, + 0x01, 0x94, 0xca, 0x7a, + 0x01, 0xa4, 0xe2, 0x7a, + 0x01, 0xfc, 0xd8, 0x7a, + 0x01, 0x94, 0xe4, 0x6a, + 0x01, 0x94, 0xe4, 0x6a, + 0x01, 0x94, 0xe4, 0x6a, + 0x00, 0x65, 0x84, 0x42, + 0x01, 0x94, 0xe2, 0x7a, + 0x10, 0x94, 0xe4, 0x6a, 0xd7, 0x93, 0x26, 0x09, - 0x28, 0x93, 0xe6, 0x6a, + 0x28, 0x93, 0xe8, 0x6a, 0x01, 0x85, 0x0a, 0x01, - 0x02, 0xfc, 0xee, 0x6a, + 0x02, 0xfc, 0xf0, 0x6a, 0x01, 0x14, 0x46, 0x31, 0xff, 0x6a, 0x10, 0x09, 0xfe, 0x85, 0x0a, 0x09, - 0xff, 0x38, 0xfc, 0x6a, - 0x80, 0xa3, 0xfc, 0x7a, - 0x80, 0x0b, 0xfa, 0x7a, - 0x04, 0x3b, 0xfc, 0x7a, + 0xff, 0x38, 0xfe, 0x6a, + 0x80, 0xa3, 0xfe, 0x7a, + 0x80, 0x0b, 0xfc, 0x7a, + 0x04, 0x3b, 0xfe, 0x7a, 0xbf, 0x3b, 0x76, 0x08, 0x01, 0x3b, 0x26, 0x31, - 0x00, 0x65, 0x0e, 0x5a, - 0x01, 0x0b, 0x0a, 0x6b, - 0x10, 0x0c, 0xfe, 0x7a, - 0x04, 0x93, 0x08, 0x6b, - 0x01, 0x94, 0x06, 0x7b, - 0x10, 0x94, 0x08, 0x6b, + 0x00, 0x65, 0x10, 0x5a, + 0x01, 0x0b, 0x0c, 0x6b, + 0x10, 0x0c, 0x00, 0x7b, + 0x04, 0x93, 0x0a, 0x6b, + 0x01, 0x94, 0x08, 0x7b, + 0x10, 0x94, 0x0a, 0x6b, 0xc7, 0x93, 0x26, 0x09, 0x01, 0x99, 0xd4, 0x30, - 0x38, 0x93, 0x0c, 0x6b, - 0xff, 0x08, 0x5a, 0x6b, - 0xff, 0x09, 0x5a, 0x6b, - 0xff, 0x0a, 0x5a, 0x6b, - 0xff, 0x38, 0x28, 0x7b, + 0x38, 0x93, 0x0e, 0x6b, + 0xff, 0x08, 0x5c, 0x6b, + 0xff, 0x09, 0x5c, 0x6b, + 0xff, 0x0a, 0x5c, 0x6b, + 0xff, 0x38, 0x2a, 0x7b, 0x04, 0x14, 0x10, 0x31, 0x01, 0x38, 0x18, 0x31, 0x02, 0x6a, 0x1a, 0x31, 0x88, 0x6a, 0xcc, 0x00, - 0x14, 0x6a, 0xf4, 0x5d, - 0x00, 0x38, 0xe0, 0x5d, + 0x14, 0x6a, 0xf6, 0x5d, + 0x00, 0x38, 0xe2, 0x5d, 0xff, 0x6a, 0x70, 0x08, - 0x00, 0x65, 0x54, 0x43, - 0x80, 0xa3, 0x2e, 0x7b, + 0x00, 0x65, 0x56, 0x43, + 0x80, 0xa3, 0x30, 0x7b, 0x01, 0xa4, 0x48, 0x01, - 0x00, 0x65, 0x5a, 0x43, - 0x08, 0xeb, 0x34, 0x7b, - 0x00, 0x65, 0x0e, 0x5a, - 0x08, 0xeb, 0x30, 0x6b, + 0x00, 0x65, 0x5c, 0x43, + 0x08, 0xeb, 0x36, 0x7b, + 0x00, 0x65, 0x10, 0x5a, + 0x08, 0xeb, 0x32, 0x6b, 0x07, 0xe9, 0x10, 0x31, 0x01, 0xe9, 0xca, 0x30, 0x01, 0x65, 0x46, 0x31, - 0x00, 0x6a, 0xba, 0x5e, + 0x00, 0x6a, 0xbc, 0x5e, 0x88, 0x6a, 0xcc, 0x00, - 0xa4, 0x6a, 0xf4, 0x5d, - 0x08, 0x6a, 0xe0, 0x5d, + 0xa4, 0x6a, 0xf6, 0x5d, + 0x08, 0x6a, 0xe2, 0x5d, 0x0d, 0x93, 0x26, 0x01, - 0x00, 0x65, 0xa8, 0x5e, + 0x00, 0x65, 0xaa, 0x5e, 0x88, 0x6a, 0xcc, 0x00, - 0x00, 0x65, 0x8a, 0x5e, + 0x00, 0x65, 0x8c, 0x5e, 0x01, 0x99, 0x46, 0x31, - 0x00, 0xa3, 0xba, 0x5e, + 0x00, 0xa3, 0xbc, 0x5e, 0x01, 0x88, 0x10, 0x31, - 0x00, 0x65, 0x3a, 0x5a, - 0x00, 0x65, 0xfa, 0x59, + 0x00, 0x65, 0x3c, 0x5a, + 0x00, 0x65, 0xfc, 0x59, 0x03, 0x8c, 0x10, 0x30, - 0x00, 0x65, 0xe6, 0x5d, - 0x80, 0x0b, 0x82, 0x6a, - 0x80, 0x0b, 0x62, 0x6b, - 0x01, 0x0c, 0x5c, 0x7b, - 0x10, 0x0c, 0x82, 0x7a, - 0x03, 0x9e, 0x82, 0x6a, - 0x00, 0x65, 0x04, 0x5a, - 0x00, 0x6a, 0xba, 0x5e, - 0x01, 0xa4, 0x82, 0x6b, - 0xff, 0x38, 0x78, 0x7b, + 0x00, 0x65, 0xe8, 0x5d, + 0x80, 0x0b, 0x84, 0x6a, + 0x80, 0x0b, 0x64, 0x6b, + 0x01, 0x0c, 0x5e, 0x7b, + 0x10, 0x0c, 0x84, 0x7a, + 0x03, 0x9e, 0x84, 0x6a, + 0x00, 0x65, 0x06, 0x5a, + 0x00, 0x6a, 0xbc, 0x5e, + 0x01, 0xa4, 0x84, 0x6b, + 0xff, 0x38, 0x7a, 0x7b, 0x01, 0x38, 0xc8, 0x30, 0x00, 0x08, 0x40, 0x19, 0xff, 0x6a, 0xc8, 0x08, 0x00, 0x09, 0x42, 0x21, 0x00, 0x0a, 0x44, 0x21, 0xff, 0x6a, 0x70, 0x08, - 0x00, 0x65, 0x7a, 0x43, + 0x00, 0x65, 0x7c, 0x43, 0x03, 0x08, 0x40, 0x31, 0x03, 0x08, 0x40, 0x31, 0x01, 0x08, 0x40, 0x31, @@ -461,16 +462,16 @@ 0x04, 0x3c, 0xcc, 0x79, 0xfb, 0x3c, 0x78, 0x08, 0x04, 0x93, 0x20, 0x79, - 0x01, 0x0c, 0x8e, 0x6b, + 0x01, 0x0c, 0x90, 0x6b, 0x80, 0xba, 0x20, 0x79, 0x80, 0x04, 0x20, 0x79, - 0xe4, 0x6a, 0x6e, 0x5d, - 0x23, 0x6a, 0x84, 0x5d, - 0x01, 0x6a, 0x84, 0x5d, + 0xe4, 0x6a, 0x70, 0x5d, + 0x23, 0x6a, 0x86, 0x5d, + 0x01, 0x6a, 0x86, 0x5d, 0x00, 0x65, 0x20, 0x41, 0x00, 0x65, 0xcc, 0x41, - 0x80, 0x3c, 0xa2, 0x7b, - 0x21, 0x6a, 0xd8, 0x5e, + 0x80, 0x3c, 0xa4, 0x7b, + 0x21, 0x6a, 0xda, 0x5e, 0x01, 0xbc, 0x18, 0x31, 0x02, 0x6a, 0x1a, 0x31, 0x02, 0x6a, 0xf8, 0x01, @@ -480,16 +481,16 @@ 0xff, 0x6a, 0x12, 0x08, 0xff, 0x6a, 0x14, 0x08, 0xf3, 0xbc, 0xd4, 0x18, - 0xa0, 0x6a, 0xc8, 0x53, + 0xa0, 0x6a, 0xca, 0x53, 0x04, 0xa0, 0x10, 0x31, 0xac, 0x6a, 0x26, 0x01, 0x04, 0xa0, 0x10, 0x31, 0x03, 0x08, 0x18, 0x31, 0x88, 0x6a, 0xcc, 0x00, - 0xa0, 0x6a, 0xf4, 0x5d, - 0x00, 0xbc, 0xe0, 0x5d, + 0xa0, 0x6a, 0xf6, 0x5d, + 0x00, 0xbc, 0xe2, 0x5d, 0x3d, 0x6a, 0x26, 0x01, - 0x00, 0x65, 0xe0, 0x43, + 0x00, 0x65, 0xe2, 0x43, 0xff, 0x6a, 0x10, 0x09, 0xa4, 0x6a, 0x26, 0x01, 0x0c, 0xa0, 0x32, 0x31, @@ -499,128 +500,128 @@ 0x36, 0x6a, 0x26, 0x01, 0x02, 0x93, 0x26, 0x01, 0x35, 0x6a, 0x26, 0x01, - 0x00, 0x65, 0x9c, 0x5e, - 0x00, 0x65, 0x9c, 0x5e, + 0x00, 0x65, 0x9e, 0x5e, + 0x00, 0x65, 0x9e, 0x5e, 0x02, 0x93, 0x26, 0x01, 0xbf, 0x3c, 0x78, 0x08, - 0x04, 0x0b, 0xe6, 0x6b, - 0x10, 0x0c, 0xe2, 0x7b, - 0x01, 0x03, 0xe6, 0x6b, - 0x20, 0x93, 0xe8, 0x6b, - 0x04, 0x0b, 0xee, 0x6b, + 0x04, 0x0b, 0xe8, 0x6b, + 0x10, 0x0c, 0xe4, 0x7b, + 0x01, 0x03, 0xe8, 0x6b, + 0x20, 0x93, 0xea, 0x6b, + 0x04, 0x0b, 0xf0, 0x6b, 0x40, 0x3c, 0x78, 0x00, 0xc7, 0x93, 0x26, 0x09, - 0x38, 0x93, 0xf0, 0x6b, + 0x38, 0x93, 0xf2, 0x6b, 0x00, 0x65, 0xcc, 0x41, - 0x80, 0x3c, 0x56, 0x6c, + 0x80, 0x3c, 0x58, 0x6c, 0x01, 0x06, 0x50, 0x31, 0x80, 0xb8, 0x70, 0x01, 0x00, 0x65, 0xcc, 0x41, 0x10, 0x3f, 0x06, 0x00, 0x10, 0x6a, 0x06, 0x00, 0x01, 0x3a, 0xca, 0x30, - 0x80, 0x65, 0x1c, 0x64, - 0x10, 0xb8, 0x40, 0x6c, + 0x80, 0x65, 0x1e, 0x64, + 0x10, 0xb8, 0x42, 0x6c, 0xc0, 0x3e, 0xca, 0x00, - 0x40, 0xb8, 0x0c, 0x6c, + 0x40, 0xb8, 0x0e, 0x6c, 0xbf, 0x65, 0xca, 0x08, - 0x20, 0xb8, 0x20, 0x7c, + 0x20, 0xb8, 0x22, 0x7c, 0x01, 0x65, 0x0c, 0x30, - 0x00, 0x65, 0xd8, 0x5d, - 0xa0, 0x3f, 0x28, 0x64, + 0x00, 0x65, 0xda, 0x5d, + 0xa0, 0x3f, 0x2a, 0x64, 0x23, 0xb8, 0x0c, 0x08, - 0x00, 0x65, 0xd8, 0x5d, - 0xa0, 0x3f, 0x28, 0x64, - 0x00, 0xbb, 0x20, 0x44, - 0xff, 0x65, 0x20, 0x64, - 0x00, 0x65, 0x40, 0x44, + 0x00, 0x65, 0xda, 0x5d, + 0xa0, 0x3f, 0x2a, 0x64, + 0x00, 0xbb, 0x22, 0x44, + 0xff, 0x65, 0x22, 0x64, + 0x00, 0x65, 0x42, 0x44, 0x40, 0x6a, 0x18, 0x00, 0x01, 0x65, 0x0c, 0x30, - 0x00, 0x65, 0xd8, 0x5d, - 0xa0, 0x3f, 0xfc, 0x73, + 0x00, 0x65, 0xda, 0x5d, + 0xa0, 0x3f, 0xfe, 0x73, 0x40, 0x6a, 0x18, 0x00, 0x01, 0x3a, 0xa6, 0x30, 0x08, 0x6a, 0x74, 0x00, 0x00, 0x65, 0xcc, 0x41, - 0x64, 0x6a, 0x68, 0x5d, - 0x80, 0x64, 0xd8, 0x6c, - 0x04, 0x64, 0x9a, 0x74, - 0x02, 0x64, 0xaa, 0x74, - 0x00, 0x6a, 0x60, 0x74, - 0x03, 0x64, 0xc8, 0x74, - 0x23, 0x64, 0x48, 0x74, - 0x08, 0x64, 0x5c, 0x74, - 0x61, 0x6a, 0xd8, 0x5e, - 0x00, 0x65, 0xd8, 0x5d, + 0x64, 0x6a, 0x6a, 0x5d, + 0x80, 0x64, 0xda, 0x6c, + 0x04, 0x64, 0x9c, 0x74, + 0x02, 0x64, 0xac, 0x74, + 0x00, 0x6a, 0x62, 0x74, + 0x03, 0x64, 0xca, 0x74, + 0x23, 0x64, 0x4a, 0x74, + 0x08, 0x64, 0x5e, 0x74, + 0x61, 0x6a, 0xda, 0x5e, + 0x00, 0x65, 0xda, 0x5d, 0x08, 0x51, 0xce, 0x71, - 0x00, 0x65, 0x40, 0x44, - 0x80, 0x04, 0x5a, 0x7c, - 0x51, 0x6a, 0x5e, 0x5d, - 0x01, 0x51, 0x5a, 0x64, - 0x01, 0xa4, 0x52, 0x7c, - 0x80, 0xba, 0x5c, 0x6c, - 0x41, 0x6a, 0xd8, 0x5e, - 0x00, 0x65, 0x5c, 0x44, - 0x21, 0x6a, 0xd8, 0x5e, - 0x00, 0x65, 0x5c, 0x44, - 0x07, 0x6a, 0x54, 0x5d, + 0x00, 0x65, 0x42, 0x44, + 0x80, 0x04, 0x5c, 0x7c, + 0x51, 0x6a, 0x60, 0x5d, + 0x01, 0x51, 0x5c, 0x64, + 0x01, 0xa4, 0x54, 0x7c, + 0x80, 0xba, 0x5e, 0x6c, + 0x41, 0x6a, 0xda, 0x5e, + 0x00, 0x65, 0x5e, 0x44, + 0x21, 0x6a, 0xda, 0x5e, + 0x00, 0x65, 0x5e, 0x44, + 0x07, 0x6a, 0x56, 0x5d, 0x01, 0x06, 0xd4, 0x30, 0x00, 0x65, 0xcc, 0x41, - 0x80, 0xb8, 0x56, 0x7c, - 0xc0, 0x3c, 0x6a, 0x7c, - 0x80, 0x3c, 0x56, 0x6c, - 0xff, 0xa8, 0x6a, 0x6c, - 0x40, 0x3c, 0x56, 0x6c, - 0x10, 0xb8, 0x6e, 0x7c, - 0xa1, 0x6a, 0xd8, 0x5e, - 0x01, 0xb4, 0x74, 0x6c, - 0x02, 0xb4, 0x76, 0x6c, - 0x01, 0xa4, 0x76, 0x7c, - 0xff, 0xa8, 0x86, 0x7c, + 0x80, 0xb8, 0x58, 0x7c, + 0xc0, 0x3c, 0x6c, 0x7c, + 0x80, 0x3c, 0x58, 0x6c, + 0xff, 0xa8, 0x6c, 0x6c, + 0x40, 0x3c, 0x58, 0x6c, + 0x10, 0xb8, 0x70, 0x7c, + 0xa1, 0x6a, 0xda, 0x5e, + 0x01, 0xb4, 0x76, 0x6c, + 0x02, 0xb4, 0x78, 0x6c, + 0x01, 0xa4, 0x78, 0x7c, + 0xff, 0xa8, 0x88, 0x7c, 0x04, 0xb4, 0x68, 0x01, 0x01, 0x6a, 0x76, 0x00, - 0x00, 0xbb, 0x12, 0x5e, - 0xff, 0xa8, 0x86, 0x7c, - 0x71, 0x6a, 0xd8, 0x5e, - 0x40, 0x51, 0x86, 0x64, - 0x00, 0x65, 0xb2, 0x5e, + 0x00, 0xbb, 0x14, 0x5e, + 0xff, 0xa8, 0x88, 0x7c, + 0x71, 0x6a, 0xda, 0x5e, + 0x40, 0x51, 0x88, 0x64, + 0x00, 0x65, 0xb4, 0x5e, 0x00, 0x65, 0xde, 0x41, - 0x00, 0xbb, 0x8a, 0x5c, + 0x00, 0xbb, 0x8c, 0x5c, 0x00, 0x65, 0xde, 0x41, - 0x00, 0x65, 0xb2, 0x5e, + 0x00, 0x65, 0xb4, 0x5e, 0x01, 0x65, 0xa2, 0x30, 0x01, 0xf8, 0xc8, 0x30, 0x01, 0x4e, 0xc8, 0x30, - 0x00, 0x6a, 0xb6, 0xdd, - 0x00, 0x51, 0xc8, 0x5d, + 0x00, 0x6a, 0xb8, 0xdd, + 0x00, 0x51, 0xca, 0x5d, 0x01, 0x4e, 0x9c, 0x18, 0x02, 0x6a, 0x22, 0x05, - 0xc0, 0x3c, 0x56, 0x6c, + 0xc0, 0x3c, 0x58, 0x6c, 0x04, 0xb8, 0x70, 0x01, - 0x00, 0x65, 0xd4, 0x5e, + 0x00, 0x65, 0xd6, 0x5e, 0x20, 0xb8, 0xde, 0x69, 0x01, 0xbb, 0xa2, 0x30, 0x3f, 0xba, 0x7c, 0x08, - 0x00, 0xb9, 0xce, 0x5c, + 0x00, 0xb9, 0xd0, 0x5c, 0x00, 0x65, 0xde, 0x41, 0x01, 0x06, 0xd4, 0x30, 0x20, 0x3c, 0xcc, 0x79, - 0x20, 0x3c, 0x5c, 0x7c, - 0x01, 0xa4, 0xb8, 0x7c, + 0x20, 0x3c, 0x5e, 0x7c, + 0x01, 0xa4, 0xba, 0x7c, 0x01, 0xb4, 0x68, 0x01, 0x00, 0x65, 0xcc, 0x41, - 0x00, 0x65, 0x5c, 0x44, + 0x00, 0x65, 0x5e, 0x44, 0x04, 0x14, 0x58, 0x31, 0x01, 0x06, 0xd4, 0x30, 0x08, 0xa0, 0x60, 0x31, 0xac, 0x6a, 0xcc, 0x00, - 0x14, 0x6a, 0xf4, 0x5d, + 0x14, 0x6a, 0xf6, 0x5d, 0x01, 0x06, 0xd4, 0x30, - 0xa0, 0x6a, 0xec, 0x5d, + 0xa0, 0x6a, 0xee, 0x5d, 0x00, 0x65, 0xcc, 0x41, 0xdf, 0x3c, 0x78, 0x08, 0x12, 0x01, 0x02, 0x00, - 0x00, 0x65, 0x5c, 0x44, + 0x00, 0x65, 0x5e, 0x44, 0x4c, 0x65, 0xcc, 0x28, 0x01, 0x3e, 0x20, 0x31, 0xd0, 0x66, 0xcc, 0x18, @@ -631,102 +632,102 @@ 0xd0, 0x65, 0xca, 0x18, 0x01, 0x3e, 0x20, 0x31, 0x30, 0x65, 0xd4, 0x18, - 0x00, 0x65, 0xe6, 0x4c, + 0x00, 0x65, 0xe8, 0x4c, 0xe1, 0x6a, 0x22, 0x01, 0xff, 0x6a, 0xd4, 0x08, 0x20, 0x65, 0xd4, 0x18, - 0x00, 0x65, 0xee, 0x54, + 0x00, 0x65, 0xf0, 0x54, 0xe1, 0x6a, 0x22, 0x01, 0xff, 0x6a, 0xd4, 0x08, 0x20, 0x65, 0xca, 0x18, 0xe0, 0x65, 0xd4, 0x18, - 0x00, 0x65, 0xf8, 0x4c, + 0x00, 0x65, 0xfa, 0x4c, 0xe1, 0x6a, 0x22, 0x01, 0xff, 0x6a, 0xd4, 0x08, 0xd0, 0x65, 0xd4, 0x18, - 0x00, 0x65, 0x00, 0x55, + 0x00, 0x65, 0x02, 0x55, 0xe1, 0x6a, 0x22, 0x01, 0xff, 0x6a, 0xd4, 0x08, 0x01, 0x6c, 0xa2, 0x30, - 0xff, 0x51, 0x12, 0x75, - 0x00, 0x51, 0x8e, 0x5d, + 0xff, 0x51, 0x14, 0x75, + 0x00, 0x51, 0x90, 0x5d, 0x01, 0x51, 0x20, 0x31, - 0x00, 0x65, 0x34, 0x45, + 0x00, 0x65, 0x36, 0x45, 0x3f, 0xba, 0xc8, 0x08, - 0x00, 0x3e, 0x34, 0x75, - 0x00, 0x65, 0xb0, 0x5e, + 0x00, 0x3e, 0x36, 0x75, + 0x00, 0x65, 0xb2, 0x5e, 0x80, 0x3c, 0x78, 0x00, 0x01, 0x06, 0xd4, 0x30, - 0x00, 0x65, 0xd8, 0x5d, + 0x00, 0x65, 0xda, 0x5d, 0x01, 0x3c, 0x78, 0x00, - 0xe0, 0x3f, 0x50, 0x65, + 0xe0, 0x3f, 0x52, 0x65, 0x02, 0x3c, 0x78, 0x00, - 0x20, 0x12, 0x50, 0x65, - 0x51, 0x6a, 0x5e, 0x5d, - 0x00, 0x51, 0x8e, 0x5d, - 0x51, 0x6a, 0x5e, 0x5d, + 0x20, 0x12, 0x52, 0x65, + 0x51, 0x6a, 0x60, 0x5d, + 0x00, 0x51, 0x90, 0x5d, + 0x51, 0x6a, 0x60, 0x5d, 0x01, 0x51, 0x20, 0x31, 0x04, 0x3c, 0x78, 0x00, 0x01, 0xb9, 0xc8, 0x30, - 0x00, 0x3d, 0x4e, 0x65, + 0x00, 0x3d, 0x50, 0x65, 0x08, 0x3c, 0x78, 0x00, 0x3f, 0xba, 0xc8, 0x08, - 0x00, 0x3e, 0x4e, 0x65, + 0x00, 0x3e, 0x50, 0x65, 0x10, 0x3c, 0x78, 0x00, - 0x04, 0xb8, 0x4e, 0x7d, + 0x04, 0xb8, 0x50, 0x7d, 0xfb, 0xb8, 0x70, 0x09, - 0x20, 0xb8, 0x44, 0x6d, + 0x20, 0xb8, 0x46, 0x6d, 0x01, 0x90, 0xc8, 0x30, 0xff, 0x6a, 0xa2, 0x00, - 0x00, 0x3d, 0xce, 0x5c, + 0x00, 0x3d, 0xd0, 0x5c, 0x01, 0x64, 0x20, 0x31, 0xff, 0x6a, 0x78, 0x08, 0x00, 0x65, 0xea, 0x58, - 0x10, 0xb8, 0x5c, 0x7c, - 0xff, 0x6a, 0x54, 0x5d, - 0x00, 0x65, 0x5c, 0x44, - 0x00, 0x65, 0xb0, 0x5e, - 0x31, 0x6a, 0xd8, 0x5e, - 0x00, 0x65, 0x5c, 0x44, + 0x10, 0xb8, 0x5e, 0x7c, + 0xff, 0x6a, 0x56, 0x5d, + 0x00, 0x65, 0x5e, 0x44, + 0x00, 0x65, 0xb2, 0x5e, + 0x31, 0x6a, 0xda, 0x5e, + 0x00, 0x65, 0x5e, 0x44, 0x10, 0x3f, 0x06, 0x00, 0x10, 0x6a, 0x06, 0x00, 0x01, 0x65, 0x74, 0x34, - 0x81, 0x6a, 0xd8, 0x5e, - 0x00, 0x65, 0x60, 0x45, + 0x81, 0x6a, 0xda, 0x5e, + 0x00, 0x65, 0x62, 0x45, 0x01, 0x06, 0xd4, 0x30, - 0x01, 0x0c, 0x60, 0x7d, - 0x04, 0x0c, 0x5a, 0x6d, + 0x01, 0x0c, 0x62, 0x7d, + 0x04, 0x0c, 0x5c, 0x6d, 0xe0, 0x03, 0x7e, 0x08, 0xe0, 0x3f, 0xcc, 0x61, 0x01, 0x65, 0xcc, 0x30, 0x01, 0x12, 0xda, 0x34, 0x01, 0x06, 0xd4, 0x34, - 0x01, 0x03, 0x6e, 0x6d, + 0x01, 0x03, 0x70, 0x6d, 0x40, 0x03, 0xcc, 0x08, 0x01, 0x65, 0x06, 0x30, 0x40, 0x65, 0xc8, 0x08, - 0x00, 0x66, 0x7c, 0x75, - 0x40, 0x65, 0x7c, 0x7d, - 0x00, 0x65, 0x7c, 0x5d, + 0x00, 0x66, 0x7e, 0x75, + 0x40, 0x65, 0x7e, 0x7d, + 0x00, 0x65, 0x7e, 0x5d, 0xff, 0x6a, 0xd4, 0x08, 0xff, 0x6a, 0xd4, 0x08, 0xff, 0x6a, 0xd4, 0x08, 0xff, 0x6a, 0xd4, 0x0c, 0x08, 0x01, 0x02, 0x00, - 0x02, 0x0b, 0x86, 0x7d, + 0x02, 0x0b, 0x88, 0x7d, 0x01, 0x65, 0x0c, 0x30, - 0x02, 0x0b, 0x8a, 0x7d, + 0x02, 0x0b, 0x8c, 0x7d, 0xf7, 0x01, 0x02, 0x0c, 0x01, 0x65, 0xc8, 0x30, - 0xff, 0x41, 0xae, 0x75, + 0xff, 0x41, 0xb0, 0x75, 0x01, 0x41, 0x20, 0x31, 0xff, 0x6a, 0xa4, 0x00, - 0x00, 0x65, 0x9e, 0x45, - 0xff, 0xbf, 0xae, 0x75, + 0x00, 0x65, 0xa0, 0x45, + 0xff, 0xbf, 0xb0, 0x75, 0x01, 0x90, 0xa4, 0x30, 0x01, 0xbf, 0x20, 0x31, - 0x00, 0xbb, 0x98, 0x65, - 0xff, 0x52, 0xac, 0x75, + 0x00, 0xbb, 0x9a, 0x65, + 0xff, 0x52, 0xae, 0x75, 0x01, 0xbf, 0xcc, 0x30, 0x01, 0x90, 0xca, 0x30, 0x01, 0x52, 0x20, 0x31, @@ -734,28 +735,28 @@ 0x01, 0x65, 0x20, 0x35, 0x01, 0xbf, 0x82, 0x34, 0x01, 0x64, 0xa2, 0x30, - 0x00, 0x6a, 0xc0, 0x5e, + 0x00, 0x6a, 0xc2, 0x5e, 0x0d, 0x6a, 0x76, 0x00, - 0x00, 0x51, 0x12, 0x46, + 0x00, 0x51, 0x14, 0x46, 0x01, 0x65, 0xa4, 0x30, 0xe0, 0x6a, 0xcc, 0x00, - 0x48, 0x6a, 0x06, 0x5e, + 0x48, 0x6a, 0x08, 0x5e, 0x01, 0x6a, 0xd0, 0x01, 0x01, 0x6a, 0xdc, 0x05, 0x88, 0x6a, 0xcc, 0x00, - 0x48, 0x6a, 0x06, 0x5e, - 0x01, 0x6a, 0xe0, 0x5d, + 0x48, 0x6a, 0x08, 0x5e, + 0x01, 0x6a, 0xe2, 0x5d, 0x01, 0x6a, 0x26, 0x05, 0x01, 0x65, 0xd8, 0x31, 0x09, 0xee, 0xdc, 0x01, - 0x80, 0xee, 0xcc, 0x7d, + 0x80, 0xee, 0xce, 0x7d, 0xff, 0x6a, 0xdc, 0x0d, 0x01, 0x65, 0x32, 0x31, 0x0a, 0x93, 0x26, 0x01, - 0x00, 0x65, 0xa8, 0x46, - 0x81, 0x6a, 0xd8, 0x5e, - 0x01, 0x0c, 0xd8, 0x7d, - 0x04, 0x0c, 0xd6, 0x6d, + 0x00, 0x65, 0xaa, 0x46, + 0x81, 0x6a, 0xda, 0x5e, + 0x01, 0x0c, 0xda, 0x7d, + 0x04, 0x0c, 0xd8, 0x6d, 0xe0, 0x03, 0x06, 0x08, 0xe0, 0x03, 0x7e, 0x0c, 0x01, 0x65, 0x18, 0x31, @@ -774,7 +775,7 @@ 0x01, 0x6c, 0xda, 0x34, 0x3d, 0x64, 0xa4, 0x28, 0x55, 0x64, 0xc8, 0x28, - 0x00, 0x65, 0x06, 0x46, + 0x00, 0x65, 0x08, 0x46, 0x2e, 0x64, 0xa4, 0x28, 0x66, 0x64, 0xc8, 0x28, 0x00, 0x6c, 0xda, 0x18, @@ -785,63 +786,63 @@ 0x00, 0x6c, 0xda, 0x24, 0x01, 0x65, 0xc8, 0x30, 0xe0, 0x6a, 0xcc, 0x00, - 0x44, 0x6a, 0x02, 0x5e, + 0x44, 0x6a, 0x04, 0x5e, 0x01, 0x90, 0xe2, 0x31, - 0x04, 0x3b, 0x26, 0x7e, + 0x04, 0x3b, 0x28, 0x7e, 0x30, 0x6a, 0xd0, 0x01, 0x20, 0x6a, 0xd0, 0x01, 0x1d, 0x6a, 0xdc, 0x01, - 0xdc, 0xee, 0x22, 0x66, - 0x00, 0x65, 0x3e, 0x46, + 0xdc, 0xee, 0x24, 0x66, + 0x00, 0x65, 0x40, 0x46, 0x20, 0x6a, 0xd0, 0x01, 0x01, 0x6a, 0xdc, 0x01, 0x20, 0xa0, 0xd8, 0x31, 0x09, 0xee, 0xdc, 0x01, - 0x80, 0xee, 0x2e, 0x7e, + 0x80, 0xee, 0x30, 0x7e, 0x11, 0x6a, 0xdc, 0x01, - 0x50, 0xee, 0x32, 0x66, + 0x50, 0xee, 0x34, 0x66, 0x20, 0x6a, 0xd0, 0x01, 0x09, 0x6a, 0xdc, 0x01, - 0x88, 0xee, 0x38, 0x66, + 0x88, 0xee, 0x3a, 0x66, 0x19, 0x6a, 0xdc, 0x01, - 0xd8, 0xee, 0x3c, 0x66, + 0xd8, 0xee, 0x3e, 0x66, 0xff, 0x6a, 0xdc, 0x09, - 0x18, 0xee, 0x40, 0x6e, + 0x18, 0xee, 0x42, 0x6e, 0xff, 0x6a, 0xd4, 0x0c, 0x88, 0x6a, 0xcc, 0x00, - 0x44, 0x6a, 0x02, 0x5e, - 0x20, 0x6a, 0xe0, 0x5d, + 0x44, 0x6a, 0x04, 0x5e, + 0x20, 0x6a, 0xe2, 0x5d, 0x01, 0x3b, 0x26, 0x31, - 0x04, 0x3b, 0x5a, 0x6e, + 0x04, 0x3b, 0x5c, 0x6e, 0xa0, 0x6a, 0xca, 0x00, 0x20, 0x65, 0xc8, 0x18, - 0x00, 0x65, 0x98, 0x5e, - 0x00, 0x65, 0x52, 0x66, + 0x00, 0x65, 0x9a, 0x5e, + 0x00, 0x65, 0x54, 0x66, 0x0a, 0x93, 0x26, 0x01, - 0x00, 0x65, 0xa8, 0x46, + 0x00, 0x65, 0xaa, 0x46, 0xa0, 0x6a, 0xcc, 0x00, 0xff, 0x6a, 0xc8, 0x08, - 0x20, 0x94, 0x5e, 0x6e, - 0x10, 0x94, 0x60, 0x6e, - 0x08, 0x94, 0x7a, 0x6e, - 0x08, 0x94, 0x7a, 0x6e, - 0x08, 0x94, 0x7a, 0x6e, + 0x20, 0x94, 0x60, 0x6e, + 0x10, 0x94, 0x62, 0x6e, + 0x08, 0x94, 0x7c, 0x6e, + 0x08, 0x94, 0x7c, 0x6e, + 0x08, 0x94, 0x7c, 0x6e, 0xff, 0x8c, 0xc8, 0x10, 0xc1, 0x64, 0xc8, 0x18, 0xf8, 0x64, 0xc8, 0x08, 0x01, 0x99, 0xda, 0x30, - 0x00, 0x66, 0x6e, 0x66, - 0xc0, 0x66, 0xaa, 0x76, + 0x00, 0x66, 0x70, 0x66, + 0xc0, 0x66, 0xac, 0x76, 0x60, 0x66, 0xc8, 0x18, 0x3d, 0x64, 0xc8, 0x28, - 0x00, 0x65, 0x5e, 0x46, + 0x00, 0x65, 0x60, 0x46, 0xf7, 0x93, 0x26, 0x09, - 0x08, 0x93, 0x7c, 0x6e, + 0x08, 0x93, 0x7e, 0x6e, 0x00, 0x62, 0xc4, 0x18, - 0x00, 0x65, 0xa8, 0x5e, - 0x00, 0x65, 0x88, 0x5e, - 0x00, 0x65, 0x88, 0x5e, - 0x00, 0x65, 0x88, 0x5e, + 0x00, 0x65, 0xaa, 0x5e, + 0x00, 0x65, 0x8a, 0x5e, + 0x00, 0x65, 0x8a, 0x5e, + 0x00, 0x65, 0x8a, 0x5e, 0x01, 0x99, 0xda, 0x30, 0x01, 0x99, 0xda, 0x30, 0x01, 0x99, 0xda, 0x30, @@ -858,11 +859,11 @@ 0x01, 0x6c, 0x32, 0x31, 0x01, 0x6c, 0x32, 0x31, 0x01, 0x6c, 0x32, 0x35, - 0x08, 0x94, 0xa8, 0x7e, + 0x08, 0x94, 0xaa, 0x7e, 0xf7, 0x93, 0x26, 0x09, - 0x08, 0x93, 0xac, 0x6e, + 0x08, 0x93, 0xae, 0x6e, 0xff, 0x6a, 0xd4, 0x0c, - 0x04, 0xb8, 0xd4, 0x6e, + 0x04, 0xb8, 0xd6, 0x6e, 0x01, 0x42, 0x7e, 0x31, 0xff, 0x6a, 0x76, 0x01, 0x01, 0x90, 0x84, 0x34, @@ -870,14 +871,14 @@ 0x01, 0x85, 0x0a, 0x01, 0x7f, 0x65, 0x10, 0x09, 0xfe, 0x85, 0x0a, 0x0d, - 0xff, 0x42, 0xd0, 0x66, - 0xff, 0x41, 0xc8, 0x66, - 0xd1, 0x6a, 0xd8, 0x5e, + 0xff, 0x42, 0xd2, 0x66, + 0xff, 0x41, 0xca, 0x66, + 0xd1, 0x6a, 0xda, 0x5e, 0xff, 0x6a, 0xca, 0x04, 0x01, 0x41, 0x20, 0x31, 0x01, 0xbf, 0x82, 0x30, 0x01, 0x6a, 0x76, 0x00, - 0x00, 0xbb, 0x12, 0x46, + 0x00, 0xbb, 0x14, 0x46, 0x01, 0x42, 0x20, 0x31, 0x01, 0xbf, 0x84, 0x34, 0x01, 0x41, 0x7e, 0x31, @@ -941,7 +942,7 @@ static int ahc_patch17_func(struct ahc_softc *ahc) { - return ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0); + return ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0); } static ahc_patch_func_t ahc_patch16_func; @@ -1142,152 +1143,152 @@ { ahc_patch0_func, 196, 1, 1 }, { ahc_patch9_func, 212, 6, 2 }, { ahc_patch0_func, 218, 6, 1 }, - { ahc_patch8_func, 226, 20, 2 }, + { ahc_patch8_func, 226, 21, 2 }, { ahc_patch1_func, 241, 1, 1 }, - { ahc_patch1_func, 248, 1, 2 }, - { ahc_patch0_func, 249, 2, 2 }, - { ahc_patch11_func, 250, 1, 1 }, - { ahc_patch9_func, 258, 27, 3 }, - { ahc_patch1_func, 274, 10, 2 }, - { ahc_patch13_func, 277, 1, 1 }, - { ahc_patch14_func, 285, 14, 1 }, - { ahc_patch1_func, 301, 1, 2 }, - { ahc_patch0_func, 302, 1, 1 }, - { ahc_patch9_func, 305, 1, 1 }, - { ahc_patch13_func, 310, 1, 1 }, - { ahc_patch9_func, 311, 2, 2 }, - { ahc_patch0_func, 313, 4, 1 }, - { ahc_patch14_func, 317, 1, 1 }, - { ahc_patch15_func, 319, 2, 3 }, - { ahc_patch9_func, 319, 1, 2 }, - { ahc_patch0_func, 320, 1, 1 }, - { ahc_patch6_func, 325, 1, 2 }, - { ahc_patch0_func, 326, 1, 1 }, - { ahc_patch1_func, 330, 47, 11 }, - { ahc_patch6_func, 337, 2, 4 }, - { ahc_patch7_func, 337, 1, 1 }, - { ahc_patch8_func, 338, 1, 1 }, - { ahc_patch0_func, 339, 1, 1 }, - { ahc_patch16_func, 340, 1, 1 }, - { ahc_patch6_func, 356, 6, 3 }, - { ahc_patch16_func, 356, 5, 1 }, - { ahc_patch0_func, 362, 7, 1 }, - { ahc_patch13_func, 372, 5, 1 }, - { ahc_patch0_func, 377, 52, 17 }, - { ahc_patch14_func, 377, 1, 1 }, - { ahc_patch7_func, 379, 2, 2 }, - { ahc_patch17_func, 380, 1, 1 }, - { ahc_patch9_func, 383, 1, 1 }, - { ahc_patch18_func, 390, 1, 1 }, - { ahc_patch14_func, 395, 9, 3 }, - { ahc_patch9_func, 396, 3, 2 }, - { ahc_patch0_func, 399, 3, 1 }, - { ahc_patch9_func, 407, 6, 2 }, - { ahc_patch0_func, 413, 9, 2 }, - { ahc_patch13_func, 413, 1, 1 }, - { ahc_patch13_func, 422, 2, 1 }, - { ahc_patch14_func, 424, 1, 1 }, - { ahc_patch9_func, 426, 1, 2 }, - { ahc_patch0_func, 427, 1, 1 }, - { ahc_patch7_func, 428, 1, 1 }, + { ahc_patch1_func, 249, 1, 2 }, + { ahc_patch0_func, 250, 2, 2 }, + { ahc_patch11_func, 251, 1, 1 }, + { ahc_patch9_func, 259, 27, 3 }, + { ahc_patch1_func, 275, 10, 2 }, + { ahc_patch13_func, 278, 1, 1 }, + { ahc_patch14_func, 286, 14, 1 }, + { ahc_patch1_func, 302, 1, 2 }, + { ahc_patch0_func, 303, 1, 1 }, + { ahc_patch9_func, 306, 1, 1 }, + { ahc_patch13_func, 311, 1, 1 }, + { ahc_patch9_func, 312, 2, 2 }, + { ahc_patch0_func, 314, 4, 1 }, + { ahc_patch14_func, 318, 1, 1 }, + { ahc_patch15_func, 320, 2, 3 }, + { ahc_patch9_func, 320, 1, 2 }, + { ahc_patch0_func, 321, 1, 1 }, + { ahc_patch6_func, 326, 1, 2 }, + { ahc_patch0_func, 327, 1, 1 }, + { ahc_patch1_func, 331, 47, 11 }, + { ahc_patch6_func, 338, 2, 4 }, + { ahc_patch7_func, 338, 1, 1 }, + { ahc_patch8_func, 339, 1, 1 }, + { ahc_patch0_func, 340, 1, 1 }, + { ahc_patch16_func, 341, 1, 1 }, + { ahc_patch6_func, 357, 6, 3 }, + { ahc_patch16_func, 357, 5, 1 }, + { ahc_patch0_func, 363, 7, 1 }, + { ahc_patch13_func, 373, 5, 1 }, + { ahc_patch0_func, 378, 52, 17 }, + { ahc_patch14_func, 378, 1, 1 }, + { ahc_patch7_func, 380, 2, 2 }, + { ahc_patch17_func, 381, 1, 1 }, + { ahc_patch9_func, 384, 1, 1 }, + { ahc_patch18_func, 391, 1, 1 }, + { ahc_patch14_func, 396, 9, 3 }, + { ahc_patch9_func, 397, 3, 2 }, + { ahc_patch0_func, 400, 3, 1 }, + { ahc_patch9_func, 408, 6, 2 }, + { ahc_patch0_func, 414, 9, 2 }, + { ahc_patch13_func, 414, 1, 1 }, + { ahc_patch13_func, 423, 2, 1 }, + { ahc_patch14_func, 425, 1, 1 }, + { ahc_patch9_func, 427, 1, 2 }, + { ahc_patch0_func, 428, 1, 1 }, { ahc_patch7_func, 429, 1, 1 }, - { ahc_patch8_func, 430, 3, 3 }, - { ahc_patch6_func, 431, 1, 2 }, - { ahc_patch0_func, 432, 1, 1 }, - { ahc_patch9_func, 433, 1, 1 }, - { ahc_patch15_func, 434, 1, 2 }, - { ahc_patch13_func, 434, 1, 1 }, - { ahc_patch14_func, 436, 9, 4 }, - { ahc_patch9_func, 436, 1, 1 }, - { ahc_patch9_func, 443, 2, 1 }, - { ahc_patch0_func, 445, 4, 3 }, - { ahc_patch9_func, 445, 1, 2 }, - { ahc_patch0_func, 446, 3, 1 }, - { ahc_patch1_func, 450, 2, 1 }, - { ahc_patch7_func, 452, 10, 2 }, - { ahc_patch0_func, 462, 1, 1 }, - { ahc_patch8_func, 463, 118, 22 }, - { ahc_patch1_func, 465, 3, 2 }, - { ahc_patch0_func, 468, 5, 3 }, - { ahc_patch9_func, 468, 2, 2 }, - { ahc_patch0_func, 470, 3, 1 }, - { ahc_patch1_func, 475, 2, 2 }, - { ahc_patch0_func, 477, 6, 3 }, - { ahc_patch9_func, 477, 2, 2 }, - { ahc_patch0_func, 479, 3, 1 }, - { ahc_patch1_func, 485, 2, 2 }, - { ahc_patch0_func, 487, 9, 7 }, - { ahc_patch9_func, 487, 5, 6 }, - { ahc_patch19_func, 487, 1, 2 }, - { ahc_patch0_func, 488, 1, 1 }, - { ahc_patch19_func, 490, 1, 2 }, - { ahc_patch0_func, 491, 1, 1 }, - { ahc_patch0_func, 492, 4, 1 }, - { ahc_patch6_func, 497, 3, 2 }, - { ahc_patch0_func, 500, 1, 1 }, - { ahc_patch6_func, 510, 1, 2 }, - { ahc_patch0_func, 511, 1, 1 }, - { ahc_patch20_func, 548, 7, 1 }, - { ahc_patch3_func, 583, 1, 2 }, - { ahc_patch0_func, 584, 1, 1 }, - { ahc_patch21_func, 587, 1, 1 }, - { ahc_patch8_func, 589, 106, 33 }, - { ahc_patch4_func, 591, 1, 1 }, - { ahc_patch1_func, 597, 2, 2 }, - { ahc_patch0_func, 599, 1, 1 }, - { ahc_patch1_func, 602, 1, 2 }, - { ahc_patch0_func, 603, 1, 1 }, - { ahc_patch9_func, 604, 3, 3 }, - { ahc_patch15_func, 605, 1, 1 }, - { ahc_patch0_func, 607, 4, 1 }, - { ahc_patch19_func, 616, 2, 2 }, - { ahc_patch0_func, 618, 1, 1 }, - { ahc_patch19_func, 622, 10, 3 }, - { ahc_patch5_func, 624, 8, 1 }, - { ahc_patch0_func, 632, 9, 2 }, - { ahc_patch5_func, 633, 8, 1 }, - { ahc_patch4_func, 643, 1, 2 }, - { ahc_patch0_func, 644, 1, 1 }, - { ahc_patch19_func, 645, 1, 2 }, - { ahc_patch0_func, 646, 3, 2 }, - { ahc_patch4_func, 648, 1, 1 }, - { ahc_patch5_func, 649, 1, 1 }, - { ahc_patch5_func, 652, 1, 1 }, - { ahc_patch5_func, 654, 1, 1 }, - { ahc_patch4_func, 656, 2, 2 }, - { ahc_patch0_func, 658, 2, 1 }, - { ahc_patch5_func, 660, 1, 1 }, - { ahc_patch5_func, 663, 1, 1 }, - { ahc_patch5_func, 666, 1, 1 }, - { ahc_patch19_func, 670, 1, 1 }, - { ahc_patch19_func, 673, 1, 1 }, - { ahc_patch4_func, 679, 1, 1 }, - { ahc_patch6_func, 682, 1, 2 }, - { ahc_patch0_func, 683, 1, 1 }, - { ahc_patch7_func, 695, 16, 1 }, - { ahc_patch4_func, 711, 20, 1 }, - { ahc_patch9_func, 732, 4, 2 }, - { ahc_patch0_func, 736, 4, 1 }, - { ahc_patch9_func, 740, 4, 2 }, - { ahc_patch0_func, 744, 3, 1 }, - { ahc_patch6_func, 750, 1, 1 }, - { ahc_patch22_func, 752, 14, 1 }, - { ahc_patch7_func, 766, 3, 1 }, - { ahc_patch9_func, 778, 24, 8 }, - { ahc_patch19_func, 782, 1, 2 }, - { ahc_patch0_func, 783, 1, 1 }, - { ahc_patch15_func, 788, 4, 2 }, - { ahc_patch0_func, 792, 7, 3 }, - { ahc_patch23_func, 792, 5, 2 }, - { ahc_patch0_func, 797, 2, 1 }, - { ahc_patch0_func, 802, 42, 3 }, - { ahc_patch18_func, 814, 18, 2 }, - { ahc_patch0_func, 832, 1, 1 }, - { ahc_patch4_func, 856, 1, 1 }, - { ahc_patch4_func, 857, 3, 2 }, - { ahc_patch0_func, 860, 1, 1 }, - { ahc_patch13_func, 861, 3, 1 }, - { ahc_patch4_func, 864, 12, 1 } + { ahc_patch7_func, 430, 1, 1 }, + { ahc_patch8_func, 431, 3, 3 }, + { ahc_patch6_func, 432, 1, 2 }, + { ahc_patch0_func, 433, 1, 1 }, + { ahc_patch9_func, 434, 1, 1 }, + { ahc_patch15_func, 435, 1, 2 }, + { ahc_patch13_func, 435, 1, 1 }, + { ahc_patch14_func, 437, 9, 4 }, + { ahc_patch9_func, 437, 1, 1 }, + { ahc_patch9_func, 444, 2, 1 }, + { ahc_patch0_func, 446, 4, 3 }, + { ahc_patch9_func, 446, 1, 2 }, + { ahc_patch0_func, 447, 3, 1 }, + { ahc_patch1_func, 451, 2, 1 }, + { ahc_patch7_func, 453, 10, 2 }, + { ahc_patch0_func, 463, 1, 1 }, + { ahc_patch8_func, 464, 118, 22 }, + { ahc_patch1_func, 466, 3, 2 }, + { ahc_patch0_func, 469, 5, 3 }, + { ahc_patch9_func, 469, 2, 2 }, + { ahc_patch0_func, 471, 3, 1 }, + { ahc_patch1_func, 476, 2, 2 }, + { ahc_patch0_func, 478, 6, 3 }, + { ahc_patch9_func, 478, 2, 2 }, + { ahc_patch0_func, 480, 3, 1 }, + { ahc_patch1_func, 486, 2, 2 }, + { ahc_patch0_func, 488, 9, 7 }, + { ahc_patch9_func, 488, 5, 6 }, + { ahc_patch19_func, 488, 1, 2 }, + { ahc_patch0_func, 489, 1, 1 }, + { ahc_patch19_func, 491, 1, 2 }, + { ahc_patch0_func, 492, 1, 1 }, + { ahc_patch0_func, 493, 4, 1 }, + { ahc_patch6_func, 498, 3, 2 }, + { ahc_patch0_func, 501, 1, 1 }, + { ahc_patch6_func, 511, 1, 2 }, + { ahc_patch0_func, 512, 1, 1 }, + { ahc_patch20_func, 549, 7, 1 }, + { ahc_patch3_func, 584, 1, 2 }, + { ahc_patch0_func, 585, 1, 1 }, + { ahc_patch21_func, 588, 1, 1 }, + { ahc_patch8_func, 590, 106, 33 }, + { ahc_patch4_func, 592, 1, 1 }, + { ahc_patch1_func, 598, 2, 2 }, + { ahc_patch0_func, 600, 1, 1 }, + { ahc_patch1_func, 603, 1, 2 }, + { ahc_patch0_func, 604, 1, 1 }, + { ahc_patch9_func, 605, 3, 3 }, + { ahc_patch15_func, 606, 1, 1 }, + { ahc_patch0_func, 608, 4, 1 }, + { ahc_patch19_func, 617, 2, 2 }, + { ahc_patch0_func, 619, 1, 1 }, + { ahc_patch19_func, 623, 10, 3 }, + { ahc_patch5_func, 625, 8, 1 }, + { ahc_patch0_func, 633, 9, 2 }, + { ahc_patch5_func, 634, 8, 1 }, + { ahc_patch4_func, 644, 1, 2 }, + { ahc_patch0_func, 645, 1, 1 }, + { ahc_patch19_func, 646, 1, 2 }, + { ahc_patch0_func, 647, 3, 2 }, + { ahc_patch4_func, 649, 1, 1 }, + { ahc_patch5_func, 650, 1, 1 }, + { ahc_patch5_func, 653, 1, 1 }, + { ahc_patch5_func, 655, 1, 1 }, + { ahc_patch4_func, 657, 2, 2 }, + { ahc_patch0_func, 659, 2, 1 }, + { ahc_patch5_func, 661, 1, 1 }, + { ahc_patch5_func, 664, 1, 1 }, + { ahc_patch5_func, 667, 1, 1 }, + { ahc_patch19_func, 671, 1, 1 }, + { ahc_patch19_func, 674, 1, 1 }, + { ahc_patch4_func, 680, 1, 1 }, + { ahc_patch6_func, 683, 1, 2 }, + { ahc_patch0_func, 684, 1, 1 }, + { ahc_patch7_func, 696, 16, 1 }, + { ahc_patch4_func, 712, 20, 1 }, + { ahc_patch9_func, 733, 4, 2 }, + { ahc_patch0_func, 737, 4, 1 }, + { ahc_patch9_func, 741, 4, 2 }, + { ahc_patch0_func, 745, 3, 1 }, + { ahc_patch6_func, 751, 1, 1 }, + { ahc_patch22_func, 753, 14, 1 }, + { ahc_patch7_func, 767, 3, 1 }, + { ahc_patch9_func, 779, 24, 8 }, + { ahc_patch19_func, 783, 1, 2 }, + { ahc_patch0_func, 784, 1, 1 }, + { ahc_patch15_func, 789, 4, 2 }, + { ahc_patch0_func, 793, 7, 3 }, + { ahc_patch23_func, 793, 5, 2 }, + { ahc_patch0_func, 798, 2, 1 }, + { ahc_patch0_func, 803, 42, 3 }, + { ahc_patch18_func, 815, 18, 2 }, + { ahc_patch0_func, 833, 1, 1 }, + { ahc_patch4_func, 857, 1, 1 }, + { ahc_patch4_func, 858, 3, 2 }, + { ahc_patch0_func, 861, 1, 1 }, + { ahc_patch13_func, 862, 3, 1 }, + { ahc_patch4_func, 865, 12, 1 } }; static struct cs { @@ -1296,11 +1297,11 @@ } critical_sections[] = { { 11, 18 }, { 21, 30 }, - { 711, 727 }, - { 857, 860 }, - { 864, 870 }, - { 872, 874 }, - { 874, 876 } + { 712, 728 }, + { 858, 861 }, + { 865, 871 }, + { 873, 875 }, + { 875, 877 } }; static const int num_critical_sections = sizeof(critical_sections) diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aicasm/Makefile linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aicasm/Makefile --- linux-2.4.25/drivers/scsi/aic7xxx/aicasm/Makefile Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aicasm/Makefile Tue Feb 10 01:47:07 2004 @@ -34,9 +34,7 @@ $(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) $(LIBS) aicdb.h: - @if [ -e "/usr/include/db4/db_185.h" ]; then \ - echo "#include " > aicdb.h; \ - elif [ -e "/usr/include/db3/db_185.h" ]; then \ + @if [ -e "/usr/include/db3/db_185.h" ]; then \ echo "#include " > aicdb.h; \ elif [ -e "/usr/include/db2/db_185.h" ]; then \ echo "#include " > aicdb.h; \ @@ -51,11 +49,19 @@ clean: rm -f $(clean-files) +# Create a dependency chain in generated files +# to avoid concurrent invocations of the single +# rule that builds them all. +aicasm_gram.c: aicasm_gram.h aicasm_gram.c aicasm_gram.h: aicasm_gram.y $(YACC) $(YFLAGS) -b $(<:.y=) $< mv $(<:.y=).tab.c $(<:.y=.c) mv $(<:.y=).tab.h $(<:.y=.h) +# Create a dependency chain in generated files +# to avoid concurrent invocations of the single +# rule that builds them all. +aicasm_macro_gram.c: aicasm_macro_gram.h aicasm_macro_gram.c aicasm_macro_gram.h: aicasm_macro_gram.y $(YACC) $(YFLAGS) -b $(<:.y=) -p mm $< mv $(<:.y=).tab.c $(<:.y=.c) diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aicasm/aicasm.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aicasm/aicasm.c --- linux-2.4.25/drivers/scsi/aic7xxx/aicasm/aicasm.c Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aicasm/aicasm.c Tue Feb 10 01:47:07 2004 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#22 $ + * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#23 $ * * $FreeBSD$ */ @@ -609,10 +609,10 @@ while (line < cur_instr->srcline) { fgets(buf, sizeof(buf), ifile); - fprintf(listfile, "\t\t%s", buf); + fprintf(listfile, " \t%s", buf); line++; } - fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr, + fprintf(listfile, "%04x %02x%02x%02x%02x", instrptr, #if BYTE_ORDER == LITTLE_ENDIAN cur_instr->format.bytes[0], cur_instr->format.bytes[1], @@ -624,14 +624,23 @@ cur_instr->format.bytes[1], cur_instr->format.bytes[0]); #endif - fgets(buf, sizeof(buf), ifile); - fprintf(listfile, "\t%s", buf); - line++; + /* + * Macro expansions can cause several instructions + * to be output for a single source line. Only + * advance the line once in these cases. + */ + if (line == cur_instr->srcline) { + fgets(buf, sizeof(buf), ifile); + fprintf(listfile, "\t%s", buf); + line++; + } else { + fprintf(listfile, "\n"); + } instrptr++; } /* Dump the remainder of the file */ while(fgets(buf, sizeof(buf), ifile) != NULL) - fprintf(listfile, "\t\t%s", buf); + fprintf(listfile, " %s", buf); fclose(ifile); } diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l --- linux-2.4.25/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l Tue Feb 10 01:47:07 2004 @@ -38,7 +38,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_macro_scan.l#7 $ + * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_macro_scan.l#8 $ * * $FreeBSD$ */ @@ -78,6 +78,7 @@ \n { ++yylineno; } +\r ; {SPACE} ; \( { parren_count++; diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l --- linux-2.4.25/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l Tue Feb 10 01:47:07 2004 @@ -38,7 +38,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#18 $ + * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#19 $ * * $FreeBSD$ */ @@ -87,6 +87,7 @@ %% \n { ++yylineno; } +\r ; "/*" { BEGIN COMMENT; /* Enter comment eating state */ } "/*" { fprintf(stderr, "Warning! Comment within comment."); } \n { ++yylineno; } @@ -114,6 +115,7 @@ } } \n { ++yylineno; } +\r ; [^()\n]+ { char *yptr; @@ -359,6 +361,7 @@ /* Eat escaped newlines. */ ++yylineno; } +\r ; \n { /* Macros end on the first unescaped newline. */ BEGIN INITIAL; @@ -369,10 +372,17 @@ } {MBODY} { char *yptr; + char c; yptr = yytext; - while (*yptr) - *string_buf_ptr++ = *yptr++; + while (c = *yptr++) { + /* + * Strip carriage returns. + */ + if (c == '\r') + continue; + *string_buf_ptr++ = c; + } } {WORD}\( { char *yptr; diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aiclib.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aiclib.c --- linux-2.4.25/drivers/scsi/aic7xxx/aiclib.c Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aiclib.c Tue Feb 10 01:47:06 2004 @@ -30,17 +30,6 @@ * $Id$ */ -#include -#include -#include -#include - -/* Core SCSI definitions */ -#include "scsi.h" -#include "hosts.h" -#include "aiclib.h" -#include "cam.h" - #ifndef FALSE #define FALSE 0 #endif /* FALSE */ @@ -1410,4 +1399,326 @@ } } return (opt_arg); +} + +/************************* Magic SysReq Support *******************************/ +void +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +aic_sysrq_handler(int key, struct pt_regs *unused, struct kbd_struct *unused1, + struct tty_struct *unused2) +#else +aic_sysrq_handler(int key, struct pt_regs *unused, struct tty_struct *unused2) +#endif +{ +#ifdef CONFIG_MAGIC_SYSRQ + struct aic_softc *aic; + u_long l; + + aic_list_lock(&l); + + TAILQ_FOREACH(aic, &aic_tailq, links) { + u_long s; + + aic_lock(aic, &s); + aic_dump_card_state(aic); + aic_unlock(aic, &s); + } + aic_list_unlock(&l); +#endif +} + +int +aic_install_sysrq(struct aic_sysrq_key_op *key_op) +{ +#ifdef CONFIG_MAGIC_SYSRQ + char *str; + int len; + int i; + + str = key_op->help_msg; + len = strlen(str); + for (i = 0; i < len; i++) { + int key; + + key = str[i]; + if (register_sysrq_key(key, key_op) == 0) { + + if (key >= 'a' && key <= 'z') + str[i] = key + ('A' - 'a'); + return (key); + } + } +#endif + return (0); +} + +void +aic_remove_sysrq(int key, struct aic_sysrq_key_op *key_op) +{ +#ifdef CONFIG_MAGIC_SYSRQ + unregister_sysrq_key(key, key_op); +#endif +} + +/******************************** Bus DMA *************************************/ +int +aic_dma_tag_create(struct aic_softc *aic, bus_dma_tag_t parent, + bus_size_t alignment, bus_size_t boundary, + bus_addr_t lowaddr, bus_addr_t highaddr, + bus_dma_filter_t *filter, void *filterarg, + bus_size_t maxsize, int nsegments, + bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag) +{ + bus_dma_tag_t dmat; + + dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT); + if (dmat == NULL) + return (ENOMEM); + + /* + * Linux is very simplistic about DMA memory. For now don't + * maintain all specification information. Once Linux supplies + * better facilities for doing these operations, or the + * needs of this particular driver change, we might need to do + * more here. + */ + dmat->alignment = alignment; + dmat->boundary = boundary; + dmat->maxsize = maxsize; + *ret_tag = dmat; + return (0); +} + +void +aic_dma_tag_destroy(struct aic_softc *aic, bus_dma_tag_t dmat) +{ + free(dmat, M_DEVBUF); +} + +int +aic_dmamem_alloc(struct aic_softc *aic, bus_dma_tag_t dmat, void** vaddr, + int flags, bus_dmamap_t *mapp) +{ + bus_dmamap_t map; + + map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT); + if (map == NULL) + return (ENOMEM); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + /* + * Although we can dma data above 4GB, our + * coherent memory is below 4GB for + * space efficiency reasons (only need a 4byte + * address). For this reason, we have to reset + * our dma mask when doing allocations. + */ + aic_set_dma_mask(aic, 0xFFFFFFFF); +#endif + *vaddr = aic_alloc_coherent(aic, dmat->maxsize, &map->bus_addr); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + aic_set_dma_mask(aic, aic->platform_data->hw_dma_mask); +#endif + if (*vaddr == NULL) + return (ENOMEM); + *mapp = map; + return(0); +} + +void +aic_dmamem_free(struct aic_softc *aic, bus_dma_tag_t dmat, + void* vaddr, bus_dmamap_t map) +{ + aic_free_coherent(aic, dmat->maxsize, vaddr, map->bus_addr); +} + +int +aic_dmamap_load(struct aic_softc *aic, bus_dma_tag_t dmat, bus_dmamap_t map, + void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb, + void *cb_arg, int flags) +{ + /* + * Assume for now that this will only be used during + * initialization and not for per-transaction buffer mapping. + */ + bus_dma_segment_t stack_sg; + + stack_sg.ds_addr = map->bus_addr; + stack_sg.ds_len = dmat->maxsize; + cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); + return (0); +} + +void +aic_dmamap_destroy(struct aic_softc *aic, bus_dma_tag_t dmat, bus_dmamap_t map) +{ + free(map, M_DEVBUF); +} + +int +aic_dmamap_unload(struct aic_softc *aic, bus_dma_tag_t dmat, bus_dmamap_t map) +{ + /* Nothing to do */ + return (0); +} + +/***************************** Queue Handling ********************************/ +/* + * In 2.4.X and above, this routine is called from a tasklet, + * so we must re-acquire our lock prior to executing this code. + * In all prior kernels, aic_schedule_runq() calls this routine + * directly and aic_schedule_runq() is called with our lock held. + */ +void +aic_runq_tasklet(unsigned long data) +{ + struct aic_softc* aic; + struct aic_linux_device *dev; + u_long flags; + + aic = (struct aic_softc *)data; + aic_lock(aic, &flags); + while ((dev = aic_linux_next_device_to_run(aic)) != NULL) { + + TAILQ_REMOVE(&aic->platform_data->device_runq, dev, links); + dev->flags &= ~AIC_DEV_ON_RUN_LIST; + aic_linux_check_device_queue(aic, dev); + /* Yeild to our interrupt handler */ + aic_unlock(aic, &flags); + aic_lock(aic, &flags); + } + aic_unlock(aic, &flags); +} + +void +aic_unblock_tasklet(unsigned long data) +{ + struct aic_softc* aic; + + aic = (struct aic_softc *)data; + scsi_unblock_requests(aic->platform_data->host); +} + +void +aic_bus_settle_complete(u_long data) +{ + struct aic_softc *aic; + u_long s; + + aic = (struct aic_softc *)data; + /* + * Guard against our bottom half scheduling another + * bus settle delay just as our timer runs. If this + * occurs, do nothing. The newly scheduled timer will + * take care of things. + */ + aic_lock(aic, &s); + if (timer_pending(&aic->platform_data->bus_settle_timer) == 0) { + aic->platform_data->flags &= ~AIC_BUS_SETTLE_TIMER; + aic_release_simq_locked(aic); + } + aic_unlock(aic, &s); +} + +void +aic_freeze_simq(struct aic_softc *aic) +{ + aic->platform_data->qfrozen++; + if (aic->platform_data->qfrozen == 1) + scsi_block_requests(aic->platform_data->host); +} + +void +aic_release_simq(struct aic_softc *aic) +{ + u_long s; + + aic_lock(aic, &s); + aic_release_simq_locked(aic); + aic_unlock(aic, &s); +} + +void +aic_release_simq_locked(struct aic_softc *aic) +{ + + if (aic->platform_data->qfrozen > 0) + aic->platform_data->qfrozen--; + if (AIC_DV_SIMQ_FROZEN(aic) + && ((aic->platform_data->flags & AIC_DV_WAIT_SIMQ_RELEASE) != 0)) { + aic->platform_data->flags &= ~AIC_DV_WAIT_SIMQ_RELEASE; + up(&aic->platform_data->dv_sem); + } + if (aic->platform_data->qfrozen == 0) { + aic_schedule_unblock(aic); + aic_schedule_runq(aic); + } +} + +/***************************** Timer Facilities *******************************/ +void +aic_platform_timeout(struct scsi_cmnd *cmd) +{ + + if (AIC_DV_CMD(cmd) != 0) { + + aic_linux_dv_timeout(cmd); + } else { + struct scb *scb; + struct aic_softc *aic; + u_long s; + + scb = (struct scb *)cmd->host_scribble; + aic = scb->aic_softc; + aic_lock(aic, &s); + + if (scb == NULL + || scb->flags == SCB_FLAG_NONE) { + int done_late; + + /* + * Handle timeout/completion races. + * If the command is still sitting on + * our completion queue, just re-instate + * the timeout. If we've already completed + * the command, the function pointer in our + * timer will be cleared and we will need to + * additionally complete it again to the mid-layer. + * + * Since done_late is cleared by adding a + * timer, we must save off its value first. + */ + done_late = cmd->eh_timeout.function == NULL; + scsi_add_timer(cmd, 60*HZ, aic_linux_midlayer_timeout); + if (done_late) + cmd->scsi_done(cmd); + } else if ((scb->platform_data->flags & AIC_TIMEOUT_ACTIVE)) { + + /* + * Handle the case of timeouts that expire just + * as we delete timers during recovery by skipping + * SCBs that don't have timers active. + */ + scb->platform_data->flags &= ~AIC_TIMEOUT_ACTIVE; + + /* + * We must clear out the function pointer so that + * scsi_add_timer does not believe that a del_timer + * is required before setting up a new timer for + * this command. + */ + scb->io_ctx->eh_timeout.function = NULL; + aic_timeout(scb); + } + aic_unlock(aic, &s); + } +} + +void +aic_linux_midlayer_timeout(struct scsi_cmnd *cmd) +{ + struct aic_softc *aic; + + aic = *(struct aic_softc **)cmd->device->host->hostdata; + printf("%s: midlayer_timeout\n", aic_name(aic)); } diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aiclib.h linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aiclib.h --- linux-2.4.25/drivers/scsi/aic7xxx/aiclib.h Wed Jul 30 09:18:50 2003 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aiclib.h Tue Feb 10 01:47:06 2004 @@ -1,4 +1,5 @@ /* + * SCSI definitions... * Largely written by Julian Elischer (julian@tfs.com) * for TRW Financial Systems. * @@ -16,7 +17,7 @@ * * $FreeBSD: src/sys/cam/scsi/scsi_all.h,v 1.21 2002/10/08 17:12:44 ken Exp $ * - * Copyright (c) 2003 Adaptec Inc. + * Copyright (c) 2003, 2004 Adaptec Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,6 +58,35 @@ #ifndef _AICLIB_H #define _AICLIB_H +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include /* For tasklet support. */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#include +#endif +#include + +#include "scsi.h" +#include "hosts.h" + +/* Name space conflict with BSD queue macros */ +#ifdef LIST_HEAD +#undef LIST_HEAD +#endif +#include "cam.h" +#include "queue.h" +#include "scsi_message.h" +#include "scsi_iu.h" + /* * Linux Interrupt Support. */ @@ -66,9 +96,812 @@ #endif /* - * SCSI command format + * Linux Timer Support. */ +#define AIC_USECS_PER_JIFFY (1000000/HZ) + +/**************************** Module Library Hack *****************************/ +/* + * What we'd like to do is have a single "scsi library" module that both the + * aic7xxx and aic79xx drivers could load and depend on. A cursory examination + * of implementing module dependencies in Linux (handling the install and + * initrd cases) does not look promissing. For now, we just duplicate this + * code in both drivers using a simple symbol renaming scheme that hides this + * hack from the drivers. + */ +#define AIC_LIB_ENTRY_CONCAT(x, prefix) prefix ## x +#define AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix) +#define AIC_LIB_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX) + +#define AIC_CONST_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x,AIC_CONST_PREFIX) + +#define aic_sense_desc AIC_LIB_ENTRY(_sense_desc) +#define aic_sense_error_action AIC_LIB_ENTRY(_sense_error_action) +#define aic_error_action AIC_LIB_ENTRY(_error_action) +#define aic_op_desc AIC_LIB_ENTRY(_op_desc) +#define aic_cdb_string AIC_LIB_ENTRY(_cdb_string) +#define aic_print_inquiry AIC_LIB_ENTRY(_print_inquiry) +#define aic_calc_syncsrate AIC_LIB_ENTRY(_calc_syncrate) +#define aic_calc_syncparam AIC_LIB_ENTRY(_calc_syncparam) +#define aic_calc_speed AIC_LIB_ENTRY(_calc_speed) +#define aic_inquiry_match AIC_LIB_ENTRY(_inquiry_match) +#define aic_static_inquiry_match AIC_LIB_ENTRY(_static_inquiry_match) +#define aic_parse_brace_option AIC_LIB_ENTRY(_parse_brace_option) +#define aic_power_state_change AIC_LIB_ENTRY(_power_state_change) +#define aic_sysrq_handler AIC_LIB_ENTRY(_sysrq_handler) +#define aic_install_sysrq AIC_LIB_ENTRY(_install_sysrq) +#define aic_remove_sysrq AIC_LIB_ENTRY(_remove_sysrq) +#define aic_list_lockinit AIC_LIB_ENTRY(_list_lockinit) +#define aic_list_lock AIC_LIB_ENTRY(_list_lock) +#define aic_list_unlock AIC_LIB_ENTRY(_list_unlock) +#define aic_entrypoint_lock AIC_LIB_ENTRY(_entrypoint_lock) +#define aic_entrypoint_unlock AIC_LIB_ENTRY(_entrypoint_unlock) +#define aic_lockinit AIC_LIB_ENTRY(_lockinit) +#define aic_lock AIC_LIB_ENTRY(_lock) +#define aic_unlock AIC_LIB_ENTRY(_unlock) +#define aic_dump_card_state AIC_LIB_ENTRY(_dump_card_state) +#define aic_linux_dv_complete AIC_LIB_ENTRY(_linux_dv_complete) +#define aic_linux_run_device_queue AIC_LIB_ENTRY(_linux_run_device_queue) +#define aic_linux_dv_timeout AIC_LIB_ENTRY(_linux_dv_timeout) +#define aic_linux_midlayer_timeout AIC_LIB_ENTRY(_linux_midlayer_timeout) +#define aic_freeze_simq AIC_LIB_ENTRY(_freeze_simq) +#define aic_bus_settle_complete AIC_LIB_ENTRY(_bus_settle_complete) +#define aic_release_simq AIC_LIB_ENTRY(_release_simq) +#define aic_release_simq AIC_LIB_ENTRY(_release_simq) +#define aic_release_simq_locked AIC_LIB_ENTRY(_release_simq_locked) +#define aic_dma_tag_create AIC_LIB_ENTRY(_dma_tag_create) +#define aic_dma_tag_destroy AIC_LIB_ENTRY(_dma_tag_destroy) +#define aic_dmamem_alloc AIC_LIB_ENTRY(_dmamem_alloc) +#define aic_dmamem_free AIC_LIB_ENTRY(_dmamem_free) +#define aic_dmamap_create AIC_LIB_ENTRY(_dmamap_create) +#define aic_dmamap_destroy AIC_LIB_ENTRY(_dmamap_destroy) +#define aic_dmamap_load AIC_LIB_ENTRY(_dmamap_load) +#define aic_dmamap_unload AIC_LIB_ENTRY(_dmamap_unload) +#define aic_dmamap_destroy AIC_LIB_ENTRY(_dmamap_destroy) +#define aic_timeout AIC_LIB_ENTRY(_timeout) +#define aic_runq_tasklet AIC_LIB_ENTRY(_runq_tasklet) +#define aic_unblock_tasklet AIC_LIB_ENTRY(_unblock_tasklet) +#define aic_platform_timeout AIC_LIB_ENTRY(_platform_timeout) +#define aic_name AIC_LIB_ENTRY(_name) + +#define aic_list_spinlock AIC_LIB_ENTRY(_list_spinlock) +#define aic_tailq AIC_LIB_ENTRY(_tailq) +#define aic_softc AIC_LIB_ENTRY(_softc) +#define aic_transinfo AIC_LIB_ENTRY(_transinfo) +#define aic_platform_data AIC_LIB_ENTRY(_platform_data) +#define aic_devinfo AIC_LIB_ENTRY(_devinfo) +#define aic_callback_t AIC_LIB_ENTRY(_callback_t) + +#define AIC_NUM_LUNS AIC_CONST_ENTRY(_NUM_LUNS) +#define AIC_NUM_TARGETS AIC_CONST_ENTRY(_NUM_TARGETS) +#define AIC_RESOURCE_SHORTAGE AIC_CONST_ENTRY(_RESOURCE_SHORTAGE) + +/*************************** Forward Declarations *****************************/ +struct aic_softc; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) +typedef struct device *aic_dev_softc_t; +#else +typedef struct pci_dev *aic_dev_softc_t; +#endif +typedef Scsi_Cmnd *aic_io_ctx_t; + +/*************************** Timer DataStructures *****************************/ +typedef struct timer_list aic_timer_t; + +/***************************** Bus Space/DMA **********************************/ + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17) +typedef dma_addr_t bus_addr_t; +#else +typedef uint32_t bus_addr_t; +#endif +typedef uint32_t bus_size_t; + +typedef enum { + BUS_SPACE_MEMIO, + BUS_SPACE_PIO +} bus_space_tag_t; + +typedef union { + u_long ioport; + volatile uint8_t *maddr; +} bus_space_handle_t; + +typedef struct bus_dma_segment +{ + bus_addr_t ds_addr; + bus_size_t ds_len; +} bus_dma_segment_t; + +struct aic_linux_dma_tag +{ + bus_size_t alignment; + bus_size_t boundary; + bus_size_t maxsize; +}; +typedef struct aic_linux_dma_tag* bus_dma_tag_t; + +struct aic_linux_dmamap +{ + bus_addr_t bus_addr; +}; +typedef struct aic_linux_dmamap* bus_dmamap_t; + +typedef int bus_dma_filter_t(void*, bus_addr_t); +typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); + +#define BUS_DMA_WAITOK 0x0 +#define BUS_DMA_NOWAIT 0x1 +#define BUS_DMA_ALLOCNOW 0x2 +#define BUS_DMA_LOAD_SEGS 0x4 /* + * Argument is an S/G list not + * a single buffer. + */ + +#define BUS_SPACE_MAXADDR 0xFFFFFFFF +#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF +#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF + +int aic_dma_tag_create(struct aic_softc *, bus_dma_tag_t /*parent*/, + bus_size_t /*alignment*/, bus_size_t /*boundary*/, + bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/, + bus_dma_filter_t*/*filter*/, void */*filterarg*/, + bus_size_t /*maxsize*/, int /*nsegments*/, + bus_size_t /*maxsegsz*/, int /*flags*/, + bus_dma_tag_t */*dma_tagp*/); + +void aic_dma_tag_destroy(struct aic_softc *, bus_dma_tag_t /*tag*/); + +int aic_dmamem_alloc(struct aic_softc *, bus_dma_tag_t /*dmat*/, + void** /*vaddr*/, int /*flags*/, + bus_dmamap_t* /*mapp*/); + +void aic_dmamem_free(struct aic_softc *, bus_dma_tag_t /*dmat*/, + void* /*vaddr*/, bus_dmamap_t /*map*/); + +void aic_dmamap_destroy(struct aic_softc *, bus_dma_tag_t /*tag*/, + bus_dmamap_t /*map*/); + +int aic_dmamap_load(struct aic_softc *aic, bus_dma_tag_t /*dmat*/, + bus_dmamap_t /*map*/, void * /*buf*/, + bus_size_t /*buflen*/, bus_dmamap_callback_t *, + void */*callback_arg*/, int /*flags*/); + +int aic_dmamap_unload(struct aic_softc *, bus_dma_tag_t, bus_dmamap_t); + +/* + * Operations performed by aic_dmamap_sync(). + */ +#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ +#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ +#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ +#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ + +/* + * XXX + * aic_dmamap_sync is only used on buffers allocated with + * the pci_alloc_consistent() API. Although I'm not sure how + * this works on architectures with a write buffer, Linux does + * not have an API to sync "coherent" memory. Perhaps we need + * to do an mb()? + */ +#define aic_dmamap_sync(aic, dma_tag, dmamap, offset, len, op) + +/*************************** Linux DMA Wrappers *******************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define aic_alloc_coherent(aic, size, bus_addr_ptr) \ + dma_alloc_coherent(aic->dev_softc, size, bus_addr_ptr, /*flag*/0) + +#define aic_free_coherent(aic, size, vaddr, bus_addr) \ + dma_free_coherent(aic->dev_softc, size, vaddr, bus_addr) + +#define aic_map_single(aic, buf, size, direction) \ + dma_map_single(aic->dev_softc, buf, size, direction) + +#define aic_unmap_single(aic, busaddr, size, direction) \ + dma_unmap_single(aic->dev_softc, busaddr, size, direction) + +#define aic_map_sg(aic, sg_list, num_sg, direction) \ + dma_map_sg(aic->dev_softc, sg_list, num_sg, direction) + +#define aic_unmap_sg(aic, sg_list, num_sg, direction) \ + dma_unmap_sg(aic->dev_softc, sg_list, num_sg, direction) + +#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) */ + +#define aic_alloc_coherent(aic, size, bus_addr_ptr) \ + pci_alloc_consistent(aic->dev_softc, size, bus_addr_ptr) + +#define aic_free_coherent(aic, size, vaddr, bus_addr) \ + pci_free_consistent(aic->dev_softc, size, vaddr, bus_addr) + +#define aic_map_single(aic, buf, size, direction) \ + pci_map_single(aic->dev_softc, buf, size, direction) + +#define aic_unmap_single(aic, busaddr, size, direction) \ + pci_unmap_single(aic->dev_softc, busaddr, size, direction) + +#define aic_map_sg(aic, sg_list, num_sg, direction) \ + pci_map_sg(aic->dev_softc, sg_list, num_sg, direction) + +#define aic_unmap_sg(aic, sg_list, num_sg, direction) \ + pci_unmap_sg(aic->dev_softc, sg_list, num_sg, direction) +#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + +#define aic_set_dma_mask(aic, mask) dma_set_mask(aic->dev_softc, mask) +#define aic_set_consistent_dma_mask(aic, mask) \ + pci_set_consistent_dma_mask(aic_dev_to_pci_dev(aic->dev_softc), mask) + +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) + +/* + * Device softc is NULL for EISA devices. + */ +#define aic_set_dma_mask(aic, mask) \ + ((aic)->dev_softc == NULL ? 0 : pci_set_dma_mask(aic->dev_softc, mask)) + +/* Always successfull in 2.4.X kernels */ +#define aic_set_consistent_dma_mask(aic, mask) (0) + +#else +/* + * Device softc is NULL for EISA devices. + * Always "return" 0 for success. + */ +#define aic_set_dma_mask(aic, mask) \ + (((aic)->dev_softc == NULL) \ + ? 0 \ + : (((aic)->dev_softc->dma_mask = mask) && 0)) + +/* Always successfull in 2.4.X kernels */ +#define aic_set_consistent_dma_mask(aic, mask) (0) + +#endif + +/************************* Host Template Macros *******************************/ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK)) +#define AIC_SCSI_HAS_HOST_LOCK 1 + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define aic_assign_host_lock(aic) \ + scsi_assign_lock((aic)->platform_data->host, \ + &(aic)->platform_data->spin_lock) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,21) \ + && defined(AIC_RED_HAT_LINUX_KERNEL) +#define aic_assign_host_lock(aic) \ +do { \ + (aic)->platform_data->host->host_lock = \ + &(aic)->platform_data->spin_lock; \ +} while (0) +#else +#define aic_assign_host_lock(aic) \ +do { \ + (aic)->platform_data->host->lock = \ + &(aic)->platform_data->spin_lock; \ +} while (0) +#endif +#else /* !AIC_SCSI_HAS_HOST_LOCK */ +#define AIC_SCSI_HAS_HOST_LOCK 0 +#define aic_assign_host_lock(aic) +#endif /* !AIC_SCSI_HAS_HOST_LOCK */ + +#if defined CONFIG_HIGHIO +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) +/* Assume RedHat Distribution with its different HIGHIO conventions. */ +#define AIC_TEMPLATE_DMA_SETTINGS() \ + .can_dma_32 = 1, \ + .single_sg_okay = 1, +#else +#define AIC_TEMPLATE_DMA_SETTINGS() \ + .highmem_io = 1, +#endif +#else +#define AIC_TEMPLATE_DMA_SETTINGS() +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) +#define AIC_TEMPLATE_MAX_SECTORS(sectors) \ + .max_sectors = (sectors), +#else +#define AIC_TEMPLATE_MAX_SECTORS(sectors) +#endif + +#if defined(__i386__) +#define AIC_TEMPLATE_BIOSPARAM() \ + .bios_param = AIC_LIB_ENTRY(_linux_biosparam), +#else +#define AIC_TEMPLATE_BIOSPARAM() +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define AIC_TEMPLATE_VERSIONED_ENTRIES() \ + .slave_alloc = AIC_LIB_ENTRY(_linux_slave_alloc), \ + .slave_configure = AIC_LIB_ENTRY(_linux_slave_configure), \ + .slave_destroy = AIC_LIB_ENTRY(_linux_slave_destroy) +#else +#define AIC_TEMPLATE_VERSIONED_ENTRIES() \ + .detect = AIC_LIB_ENTRY(_linux_detect), \ + .release = AIC_LIB_ENTRY(_linux_release), \ + .select_queue_depths = AIC_LIB_ENTRY(_linux_select_queue_depth), \ + .use_new_eh_code = 1 +#endif + +#define AIC_TEMPLATE_INITIALIZER(NAME, MAX_SECTORS) \ +{ \ + .module = THIS_MODULE, \ + .name = NAME, \ + .proc_info = AIC_LIB_ENTRY(_linux_proc_info), \ + .info = AIC_LIB_ENTRY(_linux_info), \ + .queuecommand = AIC_LIB_ENTRY(_linux_queue), \ + .eh_abort_handler = AIC_LIB_ENTRY(_linux_abort), \ + .eh_device_reset_handler = AIC_LIB_ENTRY(_linux_dev_reset), \ + .eh_bus_reset_handler = AIC_LIB_ENTRY(_linux_bus_reset), \ + .can_queue = AIC_CONST_ENTRY(_MAX_QUEUE), \ + .this_id = -1, \ + .cmd_per_lun = 2, \ + .use_clustering = ENABLE_CLUSTERING, \ + AIC_TEMPLATE_MAX_SECTORS(MAX_SECTORS) \ + AIC_TEMPLATE_DMA_SETTINGS() \ + AIC_TEMPLATE_BIOSPARAM() \ + AIC_TEMPLATE_VERSIONED_ENTRIES() \ +} + +/************************** OS Utility Wrappers *******************************/ +#define printf printk +#define M_NOWAIT GFP_ATOMIC +#define M_WAITOK 0 +#define malloc(size, type, flags) kmalloc(size, flags) +#define free(ptr, type) kfree(ptr) + +static __inline void aic_delay(long); +static __inline void +aic_delay(long usec) +{ + /* + * udelay on Linux can have problems for + * multi-millisecond waits. Wait at most + * 1024us per call. + */ + while (usec > 0) { + udelay(usec % 1024); + usec -= 1024; + } +} + +/********************************** Misc Macros *******************************/ +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#define powerof2(x) ((((x)-1)&(x))==0) + +/******************************* Byte Order ***********************************/ +#define aic_htobe16(x) cpu_to_be16(x) +#define aic_htobe32(x) cpu_to_be32(x) +#define aic_htobe64(x) cpu_to_be64(x) +#define aic_htole16(x) cpu_to_le16(x) +#define aic_htole32(x) cpu_to_le32(x) +#define aic_htole64(x) cpu_to_le64(x) + +#define aic_be16toh(x) be16_to_cpu(x) +#define aic_be32toh(x) be32_to_cpu(x) +#define aic_be64toh(x) be64_to_cpu(x) +#define aic_le16toh(x) le16_to_cpu(x) +#define aic_le32toh(x) le32_to_cpu(x) +#define aic_le64toh(x) le64_to_cpu(x) + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#ifndef BYTE_ORDER +#if defined(__BIG_ENDIAN) +#define BYTE_ORDER BIG_ENDIAN +#endif +#if defined(__LITTLE_ENDIAN) +#define BYTE_ORDER LITTLE_ENDIAN +#endif +#endif /* BYTE_ORDER */ + +/********************************* Core Includes ******************************/ +#include AIC_CORE_INCLUDE + +/**************************** Front End Queues ********************************/ +/* + * Data structure used to cast the Linux struct scsi_cmnd to something + * that allows us to use the queue macros. The linux structure has + * plenty of space to hold the links fields as required by the queue + * macros, but the queue macors require them to have the correct type. + */ +struct aic_cmd_internal { + /* Area owned by the Linux scsi layer. */ + uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)]; + union { + STAILQ_ENTRY(aic_cmd) ste; + LIST_ENTRY(aic_cmd) le; + TAILQ_ENTRY(aic_cmd) tqe; + } links; + uint32_t end; +}; + +struct aic_cmd { + union { + struct aic_cmd_internal icmd; + struct scsi_cmnd scsi_cmd; + } un; +}; + +#define acmd_icmd(cmd) ((cmd)->un.icmd) +#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd) +#define acmd_links un.icmd.links + +/*************************** Device Data Structures ***************************/ +/* + * A per probed device structure used to deal with some error recovery + * scenarios that the Linux mid-layer code just doesn't know how to + * handle. The structure allocated for a device only becomes persistent + * after a successfully completed inquiry command to the target when + * that inquiry data indicates a lun is present. + */ +TAILQ_HEAD(aic_busyq, aic_cmd); +typedef enum { + AIC_DEV_UNCONFIGURED = 0x01, + AIC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */ + AIC_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */ + AIC_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */ + AIC_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */ + AIC_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */ + AIC_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */ + AIC_DEV_SLAVE_CONFIGURED = 0x80 /* slave_configure() has been called */ +} aic_linux_dev_flags; + +struct aic_linux_target; +struct aic_linux_device { + TAILQ_ENTRY(aic_linux_device) links; + struct aic_busyq busyq; + + /* + * The number of transactions currently + * queued to the device. + */ + int active; + + /* + * The currently allowed number of + * transactions that can be queued to + * the device. Must be signed for + * conversion from tagged to untagged + * mode where the device may have more + * than one outstanding active transaction. + */ + int openings; + + /* + * A positive count indicates that this + * device's queue is halted. + */ + u_int qfrozen; + + /* + * Cumulative command counter. + */ + u_long commands_issued; + + /* + * The number of tagged transactions when + * running at our current opening level + * that have been successfully received by + * this device since the last QUEUE FULL. + */ + u_int tag_success_count; +#define AIC_TAG_SUCCESS_INTERVAL 50 + + aic_linux_dev_flags flags; + + /* + * Per device timer. + */ + struct timer_list timer; + + /* + * The high limit for the tags variable. + */ + u_int maxtags; + + /* + * The computed number of tags outstanding + * at the time of the last QUEUE FULL event. + */ + u_int tags_on_last_queuefull; + + /* + * How many times we have seen a queue full + * with the same number of tags. This is used + * to stop our adaptive queue depth algorithm + * on devices with a fixed number of tags. + */ + u_int last_queuefull_same_count; +#define AIC_LOCK_TAGS_COUNT 50 + + /* + * How many transactions have been queued + * without the device going idle. We use + * this statistic to determine when to issue + * an ordered tag to prevent transaction + * starvation. This statistic is only updated + * if the AIC_DEV_PERIODIC_OTAG flag is set + * on this device. + */ + u_int commands_since_idle_or_otag; +#define AIC_OTAG_THRESH 500 + + int lun; + Scsi_Device *scsi_device; + struct aic_linux_target *target; +}; + +typedef enum { + AIC_DV_REQUIRED = 0x01, + AIC_INQ_VALID = 0x02, + AIC_BASIC_DV = 0x04, + AIC_ENHANCED_DV = 0x08 +} aic_linux_targ_flags; + +/* DV States */ +typedef enum { + AIC_DV_STATE_EXIT = 0, + AIC_DV_STATE_INQ_SHORT_ASYNC, + AIC_DV_STATE_INQ_ASYNC, + AIC_DV_STATE_INQ_ASYNC_VERIFY, + AIC_DV_STATE_TUR, + AIC_DV_STATE_REBD, + AIC_DV_STATE_INQ_VERIFY, + AIC_DV_STATE_WEB, + AIC_DV_STATE_REB, + AIC_DV_STATE_SU, + AIC_DV_STATE_BUSY +} aic_dv_state; + +struct aic_linux_target { + struct aic_linux_device *devices[AIC_NUM_LUNS]; + int channel; + int target; + int refcount; + struct aic_transinfo last_tinfo; + struct aic_softc *softc; + aic_linux_targ_flags flags; + struct scsi_inquiry_data *inq_data; + /* + * The next "fallback" period to use for narrow/wide transfers. + */ + uint8_t dv_next_narrow_period; + uint8_t dv_next_wide_period; + uint8_t dv_max_width; + uint8_t dv_max_ppr_options; + uint8_t dv_last_ppr_options; + u_int dv_echo_size; + aic_dv_state dv_state; + u_int dv_state_retry; + uint8_t *dv_buffer; + uint8_t *dv_buffer1; + + /* + * Cumulative counter of errors. + */ + u_long errors_detected; + u_long cmds_since_error; +}; + +/*************** OSM Dependent Components of Core Datastructures **************/ +/* + * Per-SCB OSM storage. + */ +typedef enum { + AIC_SCB_UP_EH_SEM = 0x1, + AIC_TIMEOUT_ACTIVE = 0x2, + AIC_RELEASE_SIMQ = 0x4 +} aic_linux_scb_flags; + +struct scb_platform_data { + struct aic_linux_device *dev; + bus_addr_t buf_busaddr; + uint32_t xfer_len; + uint32_t sense_resid; /* Auto-Sense residual */ + aic_linux_scb_flags flags; +}; + +/* + * Define a structure used for each host adapter. All members are + * aligned on a boundary >= the size of the member to honor the + * alignment restrictions of the various platforms supported by + * this driver. + */ +typedef enum { + AIC_DV_WAIT_SIMQ_EMPTY = 0x01, + AIC_DV_WAIT_SIMQ_RELEASE = 0x02, + AIC_DV_ACTIVE = 0x04, + AIC_DV_SHUTDOWN = 0x08, + AIC_RUN_CMPLT_Q_TIMER = 0x10, + AIC_BUS_SETTLE_TIMER = 0x20 +} aic_linux_softc_flags; + +TAILQ_HEAD(aic_completeq, aic_cmd); + +struct aic_platform_data { + /* + * Fields accessed from interrupt context. + */ + struct aic_linux_target *targets[AIC_NUM_TARGETS]; + TAILQ_HEAD(, aic_linux_device) device_runq; + struct aic_completeq completeq; + + spinlock_t spin_lock; + struct tasklet_struct runq_tasklet; + struct tasklet_struct unblock_tasklet; + u_int qfrozen; + pid_t dv_pid; + pid_t recovery_pid; + struct timer_list completeq_timer; + struct timer_list bus_settle_timer; + struct timer_list stats_timer; + struct semaphore eh_sem; + struct semaphore dv_sem; + struct semaphore dv_cmd_sem; + struct semaphore recovery_sem; + struct semaphore recovery_ending_sem; + struct scsi_device *dv_scsi_dev; + struct Scsi_Host *host; /* pointer to scsi host */ +#define AIC_LINUX_NOIRQ ((uint32_t)~0) + uint32_t irq; /* IRQ for this adapter */ + uint32_t bios_address; + uint32_t mem_busaddr; /* Mem Base Addr */ + bus_addr_t hw_dma_mask; + aic_linux_softc_flags flags; +}; + +/******************************** Locking *************************************/ +/* Lock protecting internal data structures */ +static __inline void aic_lockinit(struct aic_softc *); +static __inline void aic_lock(struct aic_softc *, unsigned long *flags); +static __inline void aic_unlock(struct aic_softc *, unsigned long *flags); + +/* Lock acquisition and release of the above lock in midlayer entry points. */ +static __inline void aic_entrypoint_lock(struct aic_softc *, + unsigned long *flags); +static __inline void aic_entrypoint_unlock(struct aic_softc *, + unsigned long *flags); + +/* Lock held during aic_list manipulation and aic softc frees */ +extern spinlock_t aic_list_spinlock; +static __inline void aic_list_lockinit(void); +static __inline void aic_list_lock(unsigned long *flags); +static __inline void aic_list_unlock(unsigned long *flags); + +static __inline void +aic_lockinit(struct aic_softc *aic) +{ + spin_lock_init(&aic->platform_data->spin_lock); +} + +static __inline void +aic_lock(struct aic_softc *aic, unsigned long *flags) +{ + spin_lock_irqsave(&aic->platform_data->spin_lock, *flags); +} + +static __inline void +aic_unlock(struct aic_softc *aic, unsigned long *flags) +{ + spin_unlock_irqrestore(&aic->platform_data->spin_lock, *flags); +} + +static __inline void +aic_entrypoint_lock(struct aic_softc *aic, unsigned long *flags) +{ + /* + * In 2.5.X and some 2.4.X versions, the midlayer takes our + * lock just before calling us, so we avoid locking again. + * For other kernel versions, the io_request_lock is taken + * just before our entry point is called. In this case, we + * trade the io_request_lock for our per-softc lock. + */ +#if AIC_SCSI_HAS_HOST_LOCK == 0 + spin_unlock(&io_request_lock); + spin_lock(&aic->platform_data->spin_lock); +#endif +} +static __inline void +aic_entrypoint_unlock(struct aic_softc *aic, unsigned long *flags) +{ +#if AIC_SCSI_HAS_HOST_LOCK == 0 + spin_unlock(&aic->platform_data->spin_lock); + spin_lock(&io_request_lock); +#endif +} + +static __inline void +aic_list_lockinit(void) +{ + spin_lock_init(&aic_list_spinlock); +} + +static __inline void +aic_list_lock(unsigned long *flags) +{ + spin_lock_irqsave(&aic_list_spinlock, *flags); +} + +static __inline void +aic_list_unlock(unsigned long *flags) +{ + spin_unlock_irqrestore(&aic_list_spinlock, *flags); +} + +/***************************** Timer Facilities *******************************/ +typedef void aic_linux_callback_t (u_long); +void aic_platform_timeout(struct scsi_cmnd *); +void aic_linux_midlayer_timeout(struct scsi_cmnd *); + +#define aic_timer_init init_timer +#define aic_timer_stop del_timer_sync +static __inline void aic_timer_reset(aic_timer_t *timer, uint32_t usec, + aic_callback_t *func, void *arg); +static __inline uint32_t aic_get_timeout(struct scb *); +static __inline void aic_scb_timer_start(struct scb *scb); +static __inline void aic_scb_timer_reset(struct scb *scb, uint32_t usec); + +static __inline void +aic_timer_reset(aic_timer_t *timer, uint32_t usec, + aic_callback_t *func, void *arg) +{ + struct aic_softc *aic; + + aic = (struct aic_softc *)arg; + del_timer(timer); + timer->data = (u_long)arg; + timer->expires = jiffies + (usec / AIC_USECS_PER_JIFFY); + timer->function = (aic_linux_callback_t*)func; + add_timer(timer); +} + +static __inline uint32_t +aic_get_timeout(struct scb *scb) +{ + + /* + * Convert from jiffies to usec. + */ + return (scb->io_ctx->timeout_per_command * AIC_USECS_PER_JIFFY); +} + +static __inline void +aic_scb_timer_start(struct scb *scb) +{ + scb->platform_data->flags |= AIC_TIMEOUT_ACTIVE; + scsi_add_timer(scb->io_ctx, scb->io_ctx->timeout_per_command, + aic_platform_timeout); +} + +static __inline void +aic_scb_timer_reset(struct scb *scb, uint32_t usec) +{ + /* + * Restore timer data that is clobbered by scsi_delete_timer(). + */ + scb->io_ctx->eh_timeout.data = (unsigned long)scb->io_ctx; + scb->io_ctx->eh_timeout.function = + (void (*)(unsigned long))aic_platform_timeout; + scb->platform_data->flags |= AIC_TIMEOUT_ACTIVE; + mod_timer(&scb->io_ctx->eh_timeout, + jiffies + (usec / AIC_USECS_PER_JIFFY)); +} + +/************************* SCSI command formats *******************************/ /* * Define dome bits that are in ALL (or a lot of) scsi commands */ @@ -865,6 +1698,183 @@ extern const char *scsi_sense_key_text[]; +/*************************** Domain Validation ********************************/ +#define AIC_DV_CMD(cmd) ((cmd)->scsi_done == aic_linux_dv_complete) +#define AIC_DV_SIMQ_FROZEN(aic) \ + ((((aic)->platform_data->flags & AIC_DV_ACTIVE) != 0) \ + && (aic)->platform_data->qfrozen == 1) + +/******************************* PCI Definitions ******************************/ +/* + * PCIM_xxx: mask to locate subfield in register + * PCIR_xxx: config register offset + * PCIC_xxx: device class + * PCIS_xxx: device subclass + * PCIP_xxx: device programming interface + * PCIV_xxx: PCI vendor ID (only required to fixup ancient devices) + * PCID_xxx: device ID + */ +#define PCIR_DEVVENDOR 0x00 +#define PCIR_VENDOR 0x00 +#define PCIR_DEVICE 0x02 +#define PCIR_COMMAND 0x04 +#define PCIM_CMD_PORTEN 0x0001 +#define PCIM_CMD_MEMEN 0x0002 +#define PCIM_CMD_BUSMASTEREN 0x0004 +#define PCIM_CMD_MWRICEN 0x0010 +#define PCIM_CMD_PERRESPEN 0x0040 +#define PCIM_CMD_SERRESPEN 0x0100 +#define PCIR_STATUS 0x06 +#define PCIR_REVID 0x08 +#define PCIR_PROGIF 0x09 +#define PCIR_SUBCLASS 0x0a +#define PCIR_CLASS 0x0b +#define PCIR_CACHELNSZ 0x0c +#define PCIR_LATTIMER 0x0d +#define PCIR_HEADERTYPE 0x0e +#define PCIM_MFDEV 0x80 +#define PCIR_BIST 0x0f +#define PCIR_CAP_PTR 0x34 + +/* config registers for header type 0 devices */ +#define PCIR_MAPS 0x10 +#define PCIR_BARS PCIR_MAPS +#define PCIR_BAR(x) (PCIR_BARS + (x) * 4) +#define PCIR_SUBVEND_0 0x2c +#define PCIR_SUBDEV_0 0x2e + +typedef enum +{ + AIC_POWER_STATE_D0, + AIC_POWER_STATE_D1, + AIC_POWER_STATE_D2, + AIC_POWER_STATE_D3 +} aic_power_state; + +/****************************** PCI-X definitions *****************************/ +#define PCIXR_COMMAND 0x96 +#define PCIXR_DEVADDR 0x98 +#define PCIXM_DEVADDR_FNUM 0x0003 /* Function Number */ +#define PCIXM_DEVADDR_DNUM 0x00F8 /* Device Number */ +#define PCIXM_DEVADDR_BNUM 0xFF00 /* Bus Number */ +#define PCIXR_STATUS 0x9A +#define PCIXM_STATUS_64BIT 0x0001 /* Active 64bit connection to device. */ +#define PCIXM_STATUS_133CAP 0x0002 /* Device is 133MHz capable */ +#define PCIXM_STATUS_SCDISC 0x0004 /* Split Completion Discarded */ +#define PCIXM_STATUS_UNEXPSC 0x0008 /* Unexpected Split Completion */ +#define PCIXM_STATUS_CMPLEXDEV 0x0010 /* Device Complexity (set == bridge) */ +#define PCIXM_STATUS_MAXMRDBC 0x0060 /* Maximum Burst Read Count */ +#define PCIXM_STATUS_MAXSPLITS 0x0380 /* Maximum Split Transactions */ +#define PCIXM_STATUS_MAXCRDS 0x1C00 /* Maximum Cumulative Read Size */ +#define PCIXM_STATUS_RCVDSCEM 0x2000 /* Received a Split Comp w/Error msg */ + +/**************************** KObject Wrappers ********************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define aic_dev_to_pci_dev(dev) to_pci_dev(dev) +#define aic_dev_to_eisa_dev(dev) to_eisa_dev(dev) +#define aic_pci_dev_to_dev(pci) (&pci->dev) +#define aic_eisa_dev_to_dev(eisa) (&eisa->dev) +#else +#define aic_dev_to_pci_dev(dev) (dev) +#define aic_dev_to_eisa_dev(dev) (NULL) +#define aic_pci_dev_to_dev(pci) (pci) +#define aic_eisa_dev_to_dev(eisa) (NULL) +#endif + +#define aic_pci_dev(aic) aic_dev_to_pci_dev((aic)->dev_softc) +#define aic_eisa_dev(aic) aic_dev_to_eisa_dev((aic)->dev_softc) +/***************************** PCI Routines ***********************************/ +static __inline uint32_t aic_pci_read_config(aic_dev_softc_t dev, + int reg, int width); +static __inline void aic_pci_write_config(aic_dev_softc_t dev, + int reg, uint32_t value, + int width); +static __inline int aic_get_pci_function(aic_dev_softc_t); +static __inline int aic_get_pci_slot(aic_dev_softc_t); +static __inline int aic_get_pci_bus(aic_dev_softc_t); + +static __inline uint32_t +aic_pci_read_config(aic_dev_softc_t dev, int reg, int width) +{ + struct pci_dev *pci; + + pci = aic_dev_to_pci_dev(dev); + switch (width) { + case 1: + { + uint8_t retval; + + pci_read_config_byte(pci, reg, &retval); + return (retval); + } + case 2: + { + uint16_t retval; + pci_read_config_word(pci, reg, &retval); + return (retval); + } + case 4: + { + uint32_t retval; + pci_read_config_dword(pci, reg, &retval); + return (retval); + } + default: + panic("aic_pci_read_config: Read size too big"); + /* NOTREACHED */ + return (0); + } +} + +static __inline void +aic_pci_write_config(aic_dev_softc_t dev, int reg, uint32_t value, int width) +{ + struct pci_dev *pci; + + pci = aic_dev_to_pci_dev(dev); + switch (width) { + case 1: + pci_write_config_byte(pci, reg, value); + break; + case 2: + pci_write_config_word(pci, reg, value); + break; + case 4: + pci_write_config_dword(pci, reg, value); + break; + default: + panic("aic_pci_write_config: Write size too big"); + /* NOTREACHED */ + } +} + +static __inline int +aic_get_pci_function(aic_dev_softc_t dev) +{ + struct pci_dev *pci; + + pci = aic_dev_to_pci_dev(dev); + return (PCI_FUNC(pci->devfn)); +} + +static __inline int +aic_get_pci_slot(aic_dev_softc_t dev) +{ + struct pci_dev *pci; + + pci = aic_dev_to_pci_dev(dev); + return (PCI_SLOT(pci->devfn)); +} + +static __inline int +aic_get_pci_bus(aic_dev_softc_t dev) +{ + struct pci_dev *pci; + + pci = aic_dev_to_pci_dev(dev); + return (pci->bus->number); +} + /************************* Large Disk Handling ********************************/ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) static __inline int aic_sector_div(u_long capacity, int heads, int sectors); @@ -886,34 +1896,31 @@ } #endif -/**************************** Module Library Hack *****************************/ -/* - * What we'd like to do is have a single "scsi library" module that both the - * aic7xxx and aic79xx drivers could load and depend on. A cursory examination - * of implementing module dependencies in Linux (handling the install and - * initrd cases) does not look promissing. For now, we just duplicate this - * code in both drivers using a simple symbol renaming scheme that hides this - * hack from the drivers. - */ -#define AIC_LIB_ENTRY_CONCAT(x, prefix) prefix ## x -#define AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix) -#define AIC_LIB_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX) +/************************* Magic SysReq Support *******************************/ +#include -#define aic_sense_desc AIC_LIB_ENTRY(_sense_desc) -#define aic_sense_error_action AIC_LIB_ENTRY(_sense_error_action) -#define aic_error_action AIC_LIB_ENTRY(_error_action) -#define aic_op_desc AIC_LIB_ENTRY(_op_desc) -#define aic_cdb_string AIC_LIB_ENTRY(_cdb_string) -#define aic_print_inquiry AIC_LIB_ENTRY(_print_inquiry) -#define aic_calc_syncsrate AIC_LIB_ENTRY(_calc_syncrate) -#define aic_calc_syncparam AIC_LIB_ENTRY(_calc_syncparam) -#define aic_calc_speed AIC_LIB_ENTRY(_calc_speed) -#define aic_inquiry_match AIC_LIB_ENTRY(_inquiry_match) -#define aic_static_inquiry_match AIC_LIB_ENTRY(_static_inquiry_match) -#define aic_parse_brace_option AIC_LIB_ENTRY(_parse_brace_option) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +typedef void aic_sysrq_handler_t (int, struct pt_regs *, struct kbd_struct *, + struct tty_struct *); +#else +typedef void aic_sysrq_handler_t (int, struct pt_regs *, struct tty_struct *); +#endif -/******************************************************************************/ +#ifdef CONFIG_MAGIC_SYSRQ +#define aic_sysrq_key_op sysrq_key_op +#else +struct aic_sysrq_key_op { + aic_sysrq_handler_t *handler; + char *help_msg; + char *action_msg; +}; +#endif +aic_sysrq_handler_t aic_sysrq_handler; +int aic_install_sysrq(struct aic_sysrq_key_op *); +void aic_remove_sysrq(int key, + struct aic_sysrq_key_op *key_op); +/************************ SCSI Library Functions *****************************/ void aic_sense_desc(int /*sense_key*/, int /*asc*/, int /*ascq*/, struct scsi_inquiry_data*, const char** /*sense_key_desc*/, @@ -1041,6 +2048,280 @@ (bytes[2] << 8) | bytes[3]; return (rv); +} + +/******************************* PCI Funcitons ********************************/ +void aic_power_state_change(struct aic_softc *aic, aic_power_state new_state); + +/******************************* Queue Handling *******************************/ +void aic_runq_tasklet(unsigned long data); +void aic_unblock_tasklet(unsigned long data); +void aic_linux_run_device_queue(struct aic_softc*, + struct aic_linux_device*); +void aic_bus_settle_complete(u_long data); +void aic_freeze_simq(struct aic_softc *aic); +void aic_release_simq(struct aic_softc *aic); +void aic_release_simq_locked(struct aic_softc *aic); +static __inline void aic_schedule_runq(struct aic_softc *aic); +static __inline void aic_schedule_unblock(struct aic_softc *aic); +static __inline struct aic_linux_device * + aic_linux_next_device_to_run(struct aic_softc *aic); +static __inline void aic_linux_check_device_queue(struct aic_softc *aic, + struct aic_linux_device *dev); +static __inline void aic_linux_run_device_queues(struct aic_softc *aic); + +/* + * Must be called with our lock held. + */ +static __inline void +aic_schedule_runq(struct aic_softc *aic) +{ + tasklet_schedule(&aic->platform_data->runq_tasklet); +} + +static __inline void +aic_schedule_unblock(struct aic_softc *aic) +{ + tasklet_schedule(&aic->platform_data->unblock_tasklet); +} + +static __inline struct aic_linux_device * +aic_linux_next_device_to_run(struct aic_softc *aic) +{ + + if (aic->platform_data->qfrozen != 0 + && AIC_DV_SIMQ_FROZEN(aic) == 0) + return (NULL); + return (TAILQ_FIRST(&aic->platform_data->device_runq)); +} + +static __inline void +aic_linux_check_device_queue(struct aic_softc *aic, + struct aic_linux_device *dev) +{ + if ((dev->flags & AIC_DEV_FREEZE_TIL_EMPTY) != 0 + && dev->active == 0) { + dev->flags &= ~AIC_DEV_FREEZE_TIL_EMPTY; + dev->qfrozen--; + } + + if (TAILQ_FIRST(&dev->busyq) == NULL + || dev->openings == 0 || dev->qfrozen != 0) + return; + + aic_linux_run_device_queue(aic, dev); +} + +static __inline void +aic_linux_run_device_queues(struct aic_softc *aic) +{ + struct aic_linux_device *dev; + + while ((dev = aic_linux_next_device_to_run(aic)) != NULL) { + TAILQ_REMOVE(&aic->platform_data->device_runq, dev, links); + dev->flags &= ~AIC_DEV_ON_RUN_LIST; + aic_linux_check_device_queue(aic, dev); + } +} + +/****************************** Tasklet Support *******************************/ +static __inline void aic_setup_tasklets(struct aic_softc *aic); +static __inline void aic_teardown_tasklets(struct aic_softc *aic); + +static __inline void +aic_setup_tasklets(struct aic_softc *aic) +{ + tasklet_init(&aic->platform_data->runq_tasklet, aic_runq_tasklet, + (unsigned long)aic); + tasklet_init(&aic->platform_data->unblock_tasklet, aic_unblock_tasklet, + (unsigned long)aic); +} + +static __inline void +aic_teardown_tasklets(struct aic_softc *aic) +{ + tasklet_kill(&aic->platform_data->runq_tasklet); + tasklet_kill(&aic->platform_data->unblock_tasklet); +} + +/*********************** Transaction Access Wrappers **************************/ +static __inline void aic_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t); +static __inline void aic_set_transaction_status(struct scb *, uint32_t); +static __inline void aic_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t); +static __inline void aic_set_scsi_status(struct scb *, uint32_t); +static __inline uint32_t aic_cmd_get_transaction_status(Scsi_Cmnd *cmd); +static __inline uint32_t aic_get_transaction_status(struct scb *); +static __inline uint32_t aic_cmd_get_scsi_status(Scsi_Cmnd *cmd); +static __inline uint32_t aic_get_scsi_status(struct scb *); +static __inline void aic_set_transaction_tag(struct scb *, int, u_int); +static __inline u_long aic_get_transfer_length(struct scb *); +static __inline int aic_get_transfer_dir(struct scb *); +static __inline void aic_set_residual(struct scb *, u_long); +static __inline void aic_set_sense_residual(struct scb *scb, u_long resid); +static __inline u_long aic_get_residual(struct scb *); +static __inline u_long aic_get_sense_residual(struct scb *); +static __inline int aic_perform_autosense(struct scb *); +static __inline uint32_t aic_get_sense_bufsize(struct aic_softc *, + struct scb *); +static __inline void aic_notify_xfer_settings_change(struct aic_softc *, + struct aic_devinfo *); +static __inline void aic_platform_scb_free(struct aic_softc *aic, + struct scb *scb); +static __inline void aic_freeze_scb(struct scb *scb); + +static __inline +void aic_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status) +{ + cmd->result &= ~(CAM_STATUS_MASK << 16); + cmd->result |= status << 16; +} + +static __inline +void aic_set_transaction_status(struct scb *scb, uint32_t status) +{ + aic_cmd_set_transaction_status(scb->io_ctx,status); +} + +static __inline +void aic_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status) +{ + cmd->result &= ~0xFFFF; + cmd->result |= status; +} + +static __inline +void aic_set_scsi_status(struct scb *scb, uint32_t status) +{ + aic_cmd_set_scsi_status(scb->io_ctx, status); +} + +static __inline +uint32_t aic_cmd_get_transaction_status(Scsi_Cmnd *cmd) +{ + return ((cmd->result >> 16) & CAM_STATUS_MASK); +} + +static __inline +uint32_t aic_get_transaction_status(struct scb *scb) +{ + return (aic_cmd_get_transaction_status(scb->io_ctx)); +} + +static __inline +uint32_t aic_cmd_get_scsi_status(Scsi_Cmnd *cmd) +{ + return (cmd->result & 0xFFFF); +} + +static __inline +uint32_t aic_get_scsi_status(struct scb *scb) +{ + return (aic_cmd_get_scsi_status(scb->io_ctx)); +} + +static __inline +void aic_set_transaction_tag(struct scb *scb, int enabled, u_int type) +{ + /* + * Nothing to do for linux as the incoming transaction + * has no concept of tag/non tagged, etc. + */ +} + +static __inline +u_long aic_get_transfer_length(struct scb *scb) +{ + return (scb->platform_data->xfer_len); +} + +static __inline +int aic_get_transfer_dir(struct scb *scb) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40) + return (scb->io_ctx->sc_data_direction); +#else + if (scb->io_ctx->bufflen == 0) + return (CAM_DIR_NONE); + + switch(scb->io_ctx->cmnd[0]) { + case 0x08: /* READ(6) */ + case 0x28: /* READ(10) */ + case 0xA8: /* READ(12) */ + return (CAM_DIR_IN); + case 0x0A: /* WRITE(6) */ + case 0x2A: /* WRITE(10) */ + case 0xAA: /* WRITE(12) */ + return (CAM_DIR_OUT); + default: + return (CAM_DIR_NONE); + } +#endif +} + +static __inline +void aic_set_residual(struct scb *scb, u_long resid) +{ + scb->io_ctx->resid = resid; +} + +static __inline +void aic_set_sense_residual(struct scb *scb, u_long resid) +{ + scb->platform_data->sense_resid = resid; +} + +static __inline +u_long aic_get_residual(struct scb *scb) +{ + return (scb->io_ctx->resid); +} + +static __inline +u_long aic_get_sense_residual(struct scb *scb) +{ + return (scb->platform_data->sense_resid); +} + +static __inline +int aic_perform_autosense(struct scb *scb) +{ + /* + * We always perform autosense in Linux. + * On other platforms this is set on a + * per-transaction basis. + */ + return (1); +} + +static __inline uint32_t +aic_get_sense_bufsize(struct aic_softc *aic, struct scb *scb) +{ + return (sizeof(struct scsi_sense_data)); +} + +static __inline void +aic_notify_xfer_settings_change(struct aic_softc *aic, + struct aic_devinfo *devinfo) +{ + /* Nothing to do here for linux */ +} + +static __inline void +aic_platform_scb_free(struct aic_softc *aic, struct scb *scb) +{ + if ((aic->flags & AIC_RESOURCE_SHORTAGE) != 0) { + aic->flags &= ~AIC_RESOURCE_SHORTAGE; + aic_release_simq_locked(aic); + } +} + +static __inline void +aic_freeze_scb(struct scb *scb) +{ + if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) { + scb->io_ctx->result |= CAM_DEV_QFRZN << 16; + scb->platform_data->dev->qfrozen++; + } } #endif /*_AICLIB_H */ diff -urN linux-2.4.25/drivers/scsi/aic7xxx/aiclib_pci.c linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aiclib_pci.c --- linux-2.4.25/drivers/scsi/aic7xxx/aiclib_pci.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.25-aic79xx-0209/drivers/scsi/aic7xxx/aiclib_pci.c Tue Feb 10 00:15:16 2004 @@ -0,0 +1,79 @@ +/* + * Implementation of Utility functions for PCI controller types. + * + * Copyright (c) 2000-2003 Adaptec Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm_pci.c#25 $ + */ + +void +aic_power_state_change(struct aic_softc *aic, aic_power_state new_state) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + pci_set_power_state(aic_dev_to_pci_dev(aic->dev_softc), new_state); +#else + uint32_t cap; + u_int cap_offset; + + /* + * Traverse the capability list looking for + * the power management capability. + */ + cap = 0; + cap_offset = aic_pci_read_config(aic->dev_softc, + PCIR_CAP_PTR, /*bytes*/1); + while (cap_offset != 0) { + + cap = aic_pci_read_config(aic->dev_softc, + cap_offset, /*bytes*/4); + if ((cap & 0xFF) == 1 + && ((cap >> 16) & 0x3) > 0) { + uint32_t pm_control; + + pm_control = aic_pci_read_config(aic->dev_softc, + cap_offset + 4, + /*bytes*/4); + pm_control &= ~0x3; + pm_control |= new_state; + aic_pci_write_config(aic->dev_softc, + cap_offset + 4, + pm_control, /*bytes*/2); + break; + } + cap_offset = (cap >> 8) & 0xFF; + } +#endif +}