| Kernel v2.2.19pre10 /aic7xxx-5.1.32.patch |
|---|
| Filename: | /aic7xxx-5.1.32.patch |
| Lines Added: | 7633 |
| Lines Deleted: | 0 |
| Also changed in: |
(Previous) (Following) |
 2.2.19pre10
 aic7xxx-5.1.32.patch
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/aic7xxx-5.1.32.patch linux.19p10/aic7xxx-5.1.32.patch
--- linux.vanilla/aic7xxx-5.1.32.patch Thu Jan 1 01:00:00 1970
+++ linux.19p10/aic7xxx-5.1.32.patch Mon Feb 12 14:57:06 2001
@@ -0,0 +1,7633 @@
+diff -U 3 -rN linux-2.2.17/drivers/scsi/Config.in linux/drivers/scsi/Config.in
+--- linux-2.2.17/drivers/scsi/Config.in Wed May 3 20:16:44 2000
++++ linux/drivers/scsi/Config.in Tue Feb 6 03:50:13 2001
+@@ -28,10 +28,9 @@
+ dep_tristate 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 $CONFIG_SCSI
+ dep_tristate 'Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI
+ if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then
+- bool ' Enable Tagged Command Queueing (TCQ) by default' CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
+- int ' Maximum number of TCQ commands per device' CONFIG_AIC7XXX_CMDS_PER_DEVICE 8
+- bool ' Collect statistics to report in /proc' CONFIG_AIC7XXX_PROC_STATS N
+- int ' Delay in seconds after SCSI bus reset' CONFIG_AIC7XXX_RESET_DELAY 5
++ bool ' Enable Tagged Command Queueing (TCQ) by default' CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT y
++ int ' Maximum number of TCQ commands per device' CONFIG_AIC7XXX_CMDS_PER_DEVICE 24
++ bool ' Collect statistics to report in /proc' CONFIG_AIC7XXX_PROC_STATS y
+ fi
+ dep_tristate 'IBM ServeRAID support' CONFIG_SCSI_IPS $CONFIG_SCSI
+ dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
+diff -U 3 -rN linux-2.2.17/drivers/scsi/README.aic7xxx linux/drivers/scsi/README.aic7xxx
+--- linux-2.2.17/drivers/scsi/README.aic7xxx Wed May 3 20:16:44 2000
++++ linux/drivers/scsi/README.aic7xxx Tue Feb 6 03:49:36 2001
+@@ -14,50 +14,17 @@
+ Adaptec Cards
+ ----------------------------
+ AHA-274x
+- AHA-274xT
+- AHA-2842
+- AHA-2910B
+- AHA-2920C
+- AHA-2930
+- AHA-2930U
+- AHA-2930CU
+- AHA-2930U2
+- AHA-2940
+- AHA-2940W
+- AHA-2940U
+- AHA-2940UW
+- AHA-2940UW-PRO
+- AHA-2940AU
+- AHA-2940U2W
+- AHA-2940U2
+- AHA-2940U2B
+- AHA-2940U2BOEM
+- AHA-2944D
+- AHA-2944WD
+- AHA-2944UD
+- AHA-2944UWD
+- AHA-2950U2
+- AHA-2950U2W
+- AHA-2950U2B
+- AHA-29160M
+- AHA-3940
+- AHA-3940U
+- AHA-3940W
+- AHA-3940UW
+- AHA-3940AUW
+- AHA-3940U2W
+- AHA-3950U2B
+- AHA-3950U2D
+- AHA-3960D
+- AHA-39160M
+- AHA-3985
+- AHA-3985U
+- AHA-3985W
+- AHA-3985UW
++ AHA-274xT
++ AHA-274xW
++ AHA-284x
++ AHA-284xW
++ All PCI based cards using any of the chipsets listed under motherboard
++ chipsets. In general, this means *all* of the Adaptec SCSI controllers
++ except the ones specifically excluded later on in this document.
+
+ Motherboard Chipsets
+ ----------------------------
+- AIC-777x
++ AIC-777x
+ AIC-785x
+ AIC-786x
+ AIC-787x
+@@ -71,15 +38,14 @@
+ SCSI-1/SCSI-2 50pin devices, transfer rates up to 20MB/s.
+ U - Ultra SCSI, transfer rates up to 40MB/s.
+ U2- Ultra 2 SCSI, transfer rates up to 80MB/s.
++ U3- Ultra 3 SCSI, transfer rates up to 160MB/s.
+ D - Differential SCSI.
+ T - Twin Channel SCSI. Up to 14 SCSI devices.
+
+ AHA-274x - EISA SCSI controller
+ AHA-284x - VLB SCSI controller
+ AHA-29xx - PCI SCSI controller
+- AHA-394x - PCI controllers with two separate SCSI controllers on-board.
+- AHA-398x - PCI RAID controllers with three separate SCSI controllers
+- on-board.
++ AHA-39xx - PCI controllers with multiple separate SCSI channels on-board.
+
+ Not Supported Devices
+ ------------------------------
+@@ -93,7 +59,7 @@
+
+ Motherboard Chipsets
+ ----------------------------
+- AIC-7810
++ AIC-781x
+
+ Bus Types
+ ----------------------------
+diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx.h linux/drivers/scsi/aic7xxx/aic7xxx.h
+--- linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx.h Wed Dec 31 19:00:00 1969
++++ linux/drivers/scsi/aic7xxx/aic7xxx.h Tue Feb 6 03:49:36 2001
+@@ -0,0 +1,114 @@
++/*+M*************************************************************************
++ * Adaptec AIC7xxx device driver for Linux.
++ *
++ * Copyright (c) 1994 John Aycock
++ * The University of Calgary Department of Computer Science.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * $Id: aic7xxx.h,v 3.2 1996/07/23 03:37:26 deang Exp $
++ *-M*************************************************************************/
++#ifndef _aic7xxx_h
++#define _aic7xxx_h
++
++#define AIC7XXX_H_VERSION "3.2.4"
++
++#ifndef LINUX_VERSION_CODE
++#include <linux/version.h>
++#endif
++
++#ifndef KERNEL_VERSION
++#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
++#endif
++
++#if defined(__i386__)
++# define AIC7XXX_BIOSPARAM aic7xxx_biosparam
++#else
++# define AIC7XXX_BIOSPARAM NULL
++#endif
++
++/*
++ * Scsi_Host_Template (see hosts.h) for AIC-7xxx - some fields
++ * to do with card config are filled in after the card is detected.
++ */
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,65)
++#define AIC7XXX { \
++ next: NULL, \
++ module: NULL, \
++ proc_dir: NULL, \
++ proc_info: aic7xxx_proc_info, \
++ name: NULL, \
++ detect: aic7xxx_detect, \
++ release: aic7xxx_release, \
++ info: aic7xxx_info, \
++ command: NULL, \
++ queuecommand: aic7xxx_queue, \
++ eh_strategy_handler: NULL, \
++ eh_abort_handler: NULL, \
++ eh_device_reset_handler: NULL, \
++ eh_bus_reset_handler: NULL, \
++ eh_host_reset_handler: NULL, \
++ abort: aic7xxx_abort, \
++ reset: aic7xxx_reset, \
++ slave_attach: NULL, \
++ bios_param: AIC7XXX_BIOSPARAM, \
++ can_queue: 255, /* max simultaneous cmds */\
++ this_id: -1, /* scsi id of host adapter */\
++ sg_tablesize: 0, /* max scatter-gather cmds */\
++ cmd_per_lun: 3, /* cmds per lun (linked cmds) */\
++ present: 0, /* number of 7xxx's present */\
++ unchecked_isa_dma: 0, /* no memory DMA restrictions */\
++ use_clustering: ENABLE_CLUSTERING, \
++ use_new_eh_code: 0 \
++}
++#else
++#define AIC7XXX { \
++ next: NULL, \
++ usage_count: NULL, \
++ proc_dir: NULL, \
++ proc_info: aic7xxx_proc_info, \
++ name: NULL, \
++ detect: aic7xxx_detect, \
++ release: aic7xxx_release, \
++ info: aic7xxx_info, \
++ command: NULL, \
++ queuecommand: aic7xxx_queue, \
++ abort: aic7xxx_abort, \
++ reset: aic7xxx_reset, \
++ slave_attach: NULL, \
++ bios_param: AIC7XXX_BIOSPARAM, \
++ can_queue: 255, /* max simultaneous cmds */\
++ this_id: -1, /* scsi id of host adapter */\
++ sg_tablesize: 0, /* max scatter-gather cmds */\
++ cmd_per_lun: 3, /* cmds per lun (linked cmds) */\
++ present: 0, /* number of 7xxx's present */\
++ unchecked_isa_dma: 0, /* no memory DMA restrictions */\
++ use_clustering: ENABLE_CLUSTERING \
++}
++#endif
++
++extern int aic7xxx_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
++extern int aic7xxx_biosparam(Disk *, kdev_t, int[]);
++extern int aic7xxx_detect(Scsi_Host_Template *);
++extern int aic7xxx_command(Scsi_Cmnd *);
++extern int aic7xxx_reset(Scsi_Cmnd *, unsigned int);
++extern int aic7xxx_abort(Scsi_Cmnd *);
++extern int aic7xxx_release(struct Scsi_Host *);
++
++extern const char *aic7xxx_info(struct Scsi_Host *);
++
++extern int aic7xxx_proc_info(char *, char **, off_t, int, int, int);
++
++#endif /* _aic7xxx_h */
+diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx.reg linux/drivers/scsi/aic7xxx/aic7xxx.reg
+--- linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx.reg Wed May 3 20:16:44 2000
++++ linux/drivers/scsi/aic7xxx/aic7xxx.reg Tue Feb 6 03:49:36 2001
+@@ -703,7 +703,12 @@
+ * it that it can fill the
+ * message buffer.
+ */
+- mask TRACEPOINT 0xb0|SEQINT
++ mask SEQ_SG_FIXUP 0xb0|SEQINT /* need help with fixing up
++ * the sg array pointer after
++ * a phasemis with no valid
++ * sg elements in the shadow
++ * pipeline.
++ */
+ mask TRACEPOINT2 0xc0|SEQINT
+ mask MSGIN_PHASEMIS 0xd0|SEQINT /*
+ * Target changed phase on us
+diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx.seq linux/drivers/scsi/aic7xxx/aic7xxx.seq
+--- linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx.seq Mon Sep 4 13:39:20 2000
++++ linux/drivers/scsi/aic7xxx/aic7xxx.seq Tue Feb 6 03:49:36 2001
+@@ -291,7 +291,11 @@
+
+ mov A, LASTPHASE;
+
+- test A, ~P_DATAIN jz p_data;
++ if ((p->features & AHC_ULTRA2) != 0) {
++ test A, ~P_DATAIN jz u2_p_data;
++ } else {
++ test A, ~P_DATAIN jz p_data;
++ }
+ cmp A,P_COMMAND je p_command;
+ cmp A,P_MESGOUT je p_mesgout;
+ cmp A,P_STATUS je p_status;
+@@ -332,133 +336,73 @@
+ /* clear target specific flags */
+ clr SEQ_FLAGS ret;
+
++ if ((p->features & AHC_ULTRA2) != 0) {
++
++
++
++u2_data_phase_reinit:
+ /*
+ * If we re-enter the data phase after going through another phase, the
+ * STCNT may have been cleared, so restore it from the residual field.
++ * On Ultra2, we have to put it into the HCNT field because we have to
++ * drop the data down into the shadow layer via the preload ability.
+ */
+-data_phase_reinit:
+- if ((p->features & AHC_ULTRA2) != 0) {
+ bmov HADDR, SHADDR, 4;
+ bmov HCNT, SCB_RESID_DCNT, 3;
+- }
+- if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
+- bmov STCNT, SCB_RESID_DCNT, 3;
+- }
+- if ((p->features & AHC_CMD_CHAN) == 0) {
+- mvi DINDEX, STCNT;
+- mvi SCB_RESID_DCNT call bcopy_3;
+- }
+- jmp data_phase_loop;
+-
+-p_data:
+- if ((p->features & AHC_ULTRA2) != 0) {
++ jmp u2_data_phase_loop;
++u2_p_data:
+ mvi DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN;
+- } else {
+- mvi DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET;
+- }
+- test LASTPHASE, IOI jnz . + 2;
+- or DMAPARAMS, DIRECTION;
+- call assert; /*
++ test LASTPHASE, IOI jnz . + 2;
++ or DMAPARAMS, DIRECTION;
++ call assert; /*
+ * Ensure entering a data
+ * phase is okay - seen identify, etc.
+ */
+- if ((p->features & AHC_CMD_CHAN) != 0) {
+ mvi CCSGADDR, CCSGADDR_MAX;
+- }
+- test SEQ_FLAGS, DPHASE jnz data_phase_reinit;
+-
+- /* We have seen a data phase */
+- or SEQ_FLAGS, DPHASE;
+-
+- /*
+- * Initialize the DMA address and counter from the SCB.
+- * Also set SG_COUNT and SG_NEXT in memory since we cannot
+- * modify the values in the SCB itself until we see a
+- * save data pointers message.
+- */
+- if ((p->features & AHC_CMD_CHAN) != 0) {
++ test SEQ_FLAGS, DPHASE jnz u2_data_phase_reinit;
++ or SEQ_FLAGS, DPHASE; /* we've seen a data phase */
++ /*
++ * Initialize the DMA address and counter from the SCB.
++ * Also set SG_COUNT and SG_NEXT in memory since we cannot
++ * modify the values in the SCB itself until we see a
++ * save data pointers message.
++ */
+ bmov HADDR, SCB_DATAPTR, 7;
+- bmov STCNT, HCNT, 3;
+ bmov SG_COUNT, SCB_SGCOUNT, 5;
+- } else {
+- mvi DINDEX, HADDR;
+- mvi SCB_DATAPTR call bcopy_7;
+- call set_stcnt_from_hcnt;
+- mvi DINDEX, SG_COUNT;
+- mvi SCB_SGCOUNT call bcopy_5;
+- }
+-
+-data_phase_loop:
+-/* Guard against overruns */
+- test SG_COUNT, 0xff jnz data_phase_inbounds;
++u2_data_phase_loop:
++ /* Guard against overruns */
++ test SG_COUNT, 0xff jnz u2_data_phase_inbounds;
+ /*
+ * Turn on 'Bit Bucket' mode, set the transfer count to
+ * 16meg and let the target run until it changes phase.
+ * When the transfer completes, notify the host that we
+ * had an overrun.
+ */
+- or SXFRCTL1,BITBUCKET;
+- and DMAPARAMS, ~(HDMAEN|SDMAEN);
+- if ((p->features & AHC_CMD_CHAN) != 0) {
+- if ((p->features & AHC_ULTRA2) != 0) {
+- bmov HCNT, ALLONES, 3;
+- }
+- bmov STCNT, ALLONES, 3;
+- } else {
+- mvi STCNT[0], 0xFF;
+- mvi STCNT[1], 0xFF;
+- mvi STCNT[2], 0xFF;
+- }
+-data_phase_inbounds:
++ or SXFRCTL1,BITBUCKET;
++ and DMAPARAMS, DIRECTION;
++ bmov HCNT, ALLONES, 3;
++u2_data_phase_inbounds:
+ /* If we are the last SG block, tell the hardware. */
+- cmp SG_COUNT,0x01 jne data_phase_wideodd;
+- if ((p->features & AHC_ULTRA2) == 0) {
+- and DMAPARAMS, ~WIDEODD;
+- } else {
+- mvi SG_CACHEPTR, LAST_SEG;
+- }
+-data_phase_wideodd:
+- if ((p->features & AHC_ULTRA2) != 0) {
+- mov SINDEX, ALLONES;
+- mov DFCNTRL, DMAPARAMS;
+- test SSTAT0, SDONE jnz .;
+-data_phase_dma_loop:
+- test SSTAT0, SDONE jnz data_phase_dma_done;
+- test SSTAT1,PHASEMIS jz data_phase_dma_loop; /* ie. underrun */
+-data_phase_dma_phasemis:
+- test SSTAT0,SDONE jnz data_phase_dma_done;
+- clr SINDEX; /* Remember the phasemiss */
+- } else {
+- mov DMAPARAMS call dma;
+- }
+-
+-data_phase_dma_done:
+-/* Go tell the host about any overruns */
+- test SXFRCTL1,BITBUCKET jnz data_phase_overrun;
+-
+-/* Exit if we had an underrun. dma clears SINDEX in this case. */
+- test SINDEX,0xff jz data_phase_finish;
+-
++ shl A, 2, SG_COUNT;
++ cmp SG_COUNT,0x01 jne u2_data_phase_lastseg;
++ or A, LAST_SEG;
++u2_data_phase_lastseg:
++ mov SG_CACHEPTR, A;
++ mov DFCNTRL, DMAPARAMS; /* start the operation */
++ test SXFRCTL1, BITBUCKET jnz u2_data_phase_overrun;
++u2_preload_wait:
++ test SSTAT1, PHASEMIS jnz u2_phasemis;
++ test DFSTATUS, PRELOAD_AVAIL jz u2_preload_wait;
+ /*
+- * Advance the scatter-gather pointers if needed
++ * Advance the scatter-gather pointers
+ */
+-sg_advance:
+- dec SG_COUNT; /* one less segment to go */
++u2_sg_advance:
++ cmp SG_COUNT, 0x01 je u2_data_phase_finish;
+
+- test SG_COUNT, 0xff jz data_phase_finish; /* Are we done? */
+-/*
+- * Load a struct scatter and set up the data address and length.
+- * If the working value of the SG count is nonzero, then
+- * we need to load a new set of values.
+- *
+- * This, like all DMA's, assumes little-endian host data storage.
+- */
+-sg_load:
+- if ((p->features & AHC_CMD_CHAN) != 0) {
+ /*
+ * Do we have any prefetch left???
+ */
+- cmp CCSGADDR, CCSGADDR_MAX jne prefetched_segs_avail;
++ cmp CCSGADDR, CCSGADDR_MAX jne u2_prefetch_avail;
+
+ /*
+ * Fetch MIN(CCSGADDR_MAX, (SG_COUNT * 8)) bytes.
+@@ -474,48 +418,263 @@
+ and CCSGCTL, ~CCSGEN;
+ test CCSGCTL, CCSGEN jnz .;
+ mvi CCSGCTL, CCSGRESET;
+-prefetched_segs_avail:
+- bmov HADDR, CCSGRAM, 8;
+- if ((p->features & AHC_ULTRA2) == 0) {
+- bmov STCNT, HCNT, 3;
++u2_prefetch_avail:
++ /* Test for a phasemis before we drop the stuff into the
++ * host regs. We might have actually missed the phasemis
++ * while doing the dma of the sg segs.
++ */
++ test SSTAT1, PHASEMIS jnz u2_phasemis;
++ dec SG_COUNT; /* one less segment to go */
++ bmov HADDR, CCSGRAM, 8; /* drop the address in place */
++ clr A; /* Advance the SG pointer by */
++ add SG_NEXT[0],SG_SIZEOF; /* adding SG_SIZEOF to addr0 */
++ adc SG_NEXT[1],A; /* and adding any carry to */
++ jmp u2_data_phase_loop; /* addr1 */
++
++
++/*
++ * We've loaded all of our segments into the preload layer. Now, we simply
++ * have to wait for it to finish or for us to get a phasemis. And, since
++ * we'll get a phasemis if we do finish, all we really need to do is wait
++ * for a phasemis then check if we did actually complete all the segments.
++ */
++u2_data_phase_finish:
++ test SSTAT1, PHASEMIS jnz u2_phasemis;
++ test SG_CACHEPTR, LAST_SEG_DONE jz u2_data_phase_finish;
++ clr SG_COUNT;
++ test SSTAT1, REQINIT jz .;
++ test SSTAT1, PHASEMIS jz u2_data_phase_loop;
++u2_phasemis:
++ call ultra2_dmafinish;
++ test SG_CACHEPTR, LAST_SEG_DONE jnz u2_phasemis_end;
++ test SSTAT2, SHVALID jnz u2_fixup_residual;
++ mvi INTSTAT, SEQ_SG_FIXUP;
++ jmp u2_phasemis_end;
++u2_fixup_residual:
++ shr ARG_1, 2, SG_CACHEPTR;
++u2_phasemis_loop:
++ and A, 0x3f, SG_COUNT;
++ cmp ARG_1, A je u2_phasemis_end;
++/*
++ * Subtract SG_SIZEOF from the SG_NEXT pointer and add 1 to the SG_COUNT
++ */
++ clr A;
++ add SG_NEXT[0], -SG_SIZEOF;
++ adc SG_NEXT[1], 0xff;
++ inc SG_COUNT;
++ jmp u2_phasemis_loop;
++u2_phasemis_end:
++ bmov SCB_RESID_DCNT, STCNT, 3;
++ mov SCB_RESID_SGCNT, SG_COUNT;
++ or SXFRCTL0, CLRSTCNT|CLRCHN;
++ jmp ITloop;
++
++
++
++/*
++ * Actually turn off the DMA hardware, save our current position into the
++ * proper residual variables, wait for the next REQ signal, then jump to
++ * the ITloop. Jumping to the ITloop ensures that if we happen to get
++ * brought into the data phase again (or are still in it after our last
++ * segment) that we will properly signal an overrun to the kernel.
++ */
++ultra2_dmafinish:
++ test DFCNTRL, DIRECTION jnz ultra2_dmahalt;
++ and DFCNTRL, ~SCSIEN;
++ test DFCNTRL, SCSIEN jnz .;
++ if ((p->bugs & AHC_BUG_AUTOFLUSH) != 0) {
++ or DFCNTRL, FIFOFLUSH;
+ }
+- } else {
+- mvi DINDEX, HADDR;
+- mvi SG_NEXT call bcopy_4;
++ultra2_dmafifoflush:
++ if ((p->bugs & AHC_BUG_AUTOFLUSH) != 0) {
++ /*
++ * hardware bug alert! This needless set of jumps
++ * works around a glitch in the silicon. When the
++ * PCI DMA fifo goes empty, but there is still SCSI
++ * data to be flushed into the PCI DMA fifo (and from
++ * there on into main memory), the FIFOEMP bit will
++ * come on between the time when the PCI DMA buffer
++ * went empty and the next bit of data is copied from
++ * the SCSI fifo into the PCI fifo. It should only
++ * come on when both FIFOs (meaning the entire FIFO
++ * chain) are emtpy. Since it can take up to 4 cycles
++ * for new data to be copied from the SCSI fifo into
++ * the PCI fifo, testing for FIFOEMP status for 4
++ * extra times gives the needed time for any
++ * remaining SCSI fifo data to be put in the PCI fifo
++ * before we declare it *truly* empty.
++ */
++ test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
++ test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
++ test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
++ test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
++ }
++ test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
++ test DFSTATUS, MREQPEND jnz .;
++ultra2_dmahalt:
++ and DFCNTRL, ~(HDMAEN|SCSIEN);
++ test DFCNTRL, (HDMAEN|SCSIEN) jnz .;
++ ret;
+
+- mvi HCNT[0],SG_SIZEOF;
+- clr HCNT[1];
+- clr HCNT[2];
++u2_data_phase_overrun:
++/*
++ * Wait for the target to quit transferring data on the SCSI bus
++ */
++ test SSTAT1, PHASEMIS jz .;
++ call ultra2_dmafinish;
++/*
++ * Turn off BITBUCKET mode and notify the host
++ */
++ and SXFRCTL1, ~BITBUCKET;
++ mvi INTSTAT,DATA_OVERRUN;
++ jmp ITloop;
++
++
++
++ } else { /* NOT Ultra2 */
+
+- or DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
+
+- call dma_finish;
+
++data_phase_reinit:
++/*
++ * If we re-enter the data phase after going through another phase, the
++ * STCNT may have been cleared, so restore it from the residual field.
++ */
++ if ((p->features & AHC_CMD_CHAN) != 0) {
++ bmov STCNT, SCB_RESID_DCNT, 3;
++ } else {
++ mvi DINDEX, STCNT;
++ mvi SCB_RESID_DCNT call bcopy_3;
++ }
++ jmp data_phase_loop;
++p_data:
++ mvi DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET;
++ test LASTPHASE, IOI jnz . + 2;
++ or DMAPARAMS, DIRECTION;
++ call assert; /*
++ * Ensure entering a data
++ * phase is okay - seen identify, etc.
++ */
++ if ((p->features & AHC_CMD_CHAN) != 0) {
++ mvi CCSGADDR, CCSGADDR_MAX;
++ }
++ test SEQ_FLAGS, DPHASE jnz data_phase_reinit;
++ or SEQ_FLAGS, DPHASE; /* we've seen a data phase */
+ /*
+- * Copy data from FIFO into SCB data pointer and data count.
+- * This assumes that the SG segments are of the form:
+- * struct ahc_dma_seg {
+- * u_int32_t addr; four bytes, little-endian order
+- * u_int32_t len; four bytes, little endian order
+- * };
++ * Initialize the DMA address and counter from the SCB.
++ * Also set SG_COUNT and SG_NEXT in memory since we cannot
++ * modify the values in the SCB itself until we see a
++ * save data pointers message.
+ */
+- mvi HADDR call dfdat_in_7;
+- call set_stcnt_from_hcnt;
+- }
++ if ((p->features & AHC_CMD_CHAN) != 0) {
++ bmov HADDR, SCB_DATAPTR, 7;
++ bmov STCNT, HCNT, 3;
++ bmov SG_COUNT, SCB_SGCOUNT, 5;
++ } else {
++ mvi DINDEX, HADDR;
++ mvi SCB_DATAPTR call bcopy_7;
++ call set_stcnt_from_hcnt;
++ mvi DINDEX, SG_COUNT;
++ mvi SCB_SGCOUNT call bcopy_5;
++ }
++data_phase_loop:
++ /* Guard against overruns */
++ test SG_COUNT, 0xff jnz data_phase_inbounds;
++/*
++ * Turn on 'Bit Bucket' mode, set the transfer count to
++ * 16meg and let the target run until it changes phase.
++ * When the transfer completes, notify the host that we
++ * had an overrun.
++ */
++ or SXFRCTL1,BITBUCKET;
++ and DMAPARAMS, ~(HDMAEN|SDMAEN);
++ if ((p->features & AHC_CMD_CHAN) != 0) {
++ bmov STCNT, ALLONES, 3;
++ } else {
++ mvi STCNT[0], 0xFF;
++ mvi STCNT[1], 0xFF;
++ mvi STCNT[2], 0xFF;
++ }
+
+-/* Advance the SG pointer */
+- clr A; /* add sizeof(struct scatter) */
+- add SG_NEXT[0],SG_SIZEOF;
+- adc SG_NEXT[1],A;
++data_phase_inbounds:
++/* If we are the last SG block, tell the hardware. */
++ cmp SG_COUNT,0x01 jne data_phase_wideodd;
++ and DMAPARAMS, ~WIDEODD;
++data_phase_wideodd:
++ mov DMAPARAMS call dma;
++data_phase_dma_done:
++/* Go tell the host about any overruns */
++ test SXFRCTL1,BITBUCKET jnz data_phase_overrun;
++
++/* Exit if we had an underrun. dma clears SINDEX in this case. */
++ test SINDEX,0xff jz data_phase_finish;
++/*
++ * Advance the scatter-gather pointers if needed
++ */
++sg_advance:
++ cmp SG_COUNT, 0x01 je data_phase_finish; /* Are we done? */
++ dec SG_COUNT; /* one less segment to go */
++/*
++ * Load a struct scatter and set up the data address and length.
++ * If the working value of the SG count is nonzero, then
++ * we need to load a new set of values.
++ *
++ * This, like all DMA's, assumes little-endian host data storage.
++ */
++sg_load:
++ if ((p->features & AHC_CMD_CHAN) != 0) {
++ /*
++ * Do we have any prefetch left???
++ */
++ cmp CCSGADDR, CCSGADDR_MAX jne prefetch_avail;
++
++ /*
++ * Fetch MIN(CCSGADDR_MAX, (SG_COUNT * 8)) bytes.
++ */
++ add A, -(CCSGRAM_MAXSEGS + 1), SG_COUNT;
++ mvi A, CCSGADDR_MAX;
++ jc . + 2;
++ shl A, 3, SG_COUNT;
++ mov CCHCNT, A;
++ bmov CCHADDR, SG_NEXT, 4;
++ mvi CCSGCTL, CCSGEN|CCSGRESET;
++ test CCSGCTL, CCSGDONE jz .;
++ and CCSGCTL, ~CCSGEN;
++ test CCSGCTL, CCSGEN jnz .;
++ mvi CCSGCTL, CCSGRESET;
++prefetch_avail:
++ bmov HADDR, CCSGRAM, 8;
++ bmov STCNT, HCNT, 3;
++ } else {
++ mvi DINDEX, HADDR;
++ mvi SG_NEXT call bcopy_4;
+
+- test SSTAT1, REQINIT jz .;
+- test SSTAT1,PHASEMIS jz data_phase_loop;
++ mvi HCNT[0],SG_SIZEOF;
++ clr HCNT[1];
++ clr HCNT[2];
+
+-/* This drops the last SG segment down to the shadow layer for us */
+- if ((p->features & AHC_ULTRA2) != 0) {
+- mov DFCNTRL, DMAPARAMS;
+- test SSTAT0, SDONE jnz .;
+- }
++ or DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
++
++ call dma_finish;
++
++/*
++ * Copy data from FIFO into SCB data pointer and data count.
++ * This assumes that the SG segments are of the form:
++ * struct ahc_dma_seg {
++ * u_int32_t addr; four bytes, little-endian order
++ * u_int32_t len; four bytes, little endian order
++ * };
++ */
++ mvi HADDR call dfdat_in_7;
++ call set_stcnt_from_hcnt;
++ }
++/* Advance the SG pointer */
++ clr A; /* add sizeof(struct scatter) */
++ add SG_NEXT[0],SG_SIZEOF;
++ adc SG_NEXT[1],A;
++
++ test SSTAT1, REQINIT jz .;
++ test SSTAT1,PHASEMIS jz data_phase_loop;
+
+ data_phase_finish:
+ /*
+@@ -523,10 +682,7 @@
+ * We use STCNT instead of HCNT, since it's a reflection of how many bytes
+ * were transferred on the SCSI (as opposed to the host) bus.
+ */
+- if ((p->features & AHC_ULTRA2) != 0) {
+- call ultra2_dmafinish;
+- }
+- if ((p->features & AHC_ULTRA2) == 0) {
++ clr SG_COUNT;
+ if ((p->features & AHC_CMD_CHAN) != 0) {
+ bmov SCB_RESID_DCNT, STCNT, 3;
+ mov SCB_RESID_SGCNT, SG_COUNT;
+@@ -536,52 +692,19 @@
+ mov SCB_RESID_DCNT[2],STCNT[2];
+ mov SCB_RESID_SGCNT, SG_COUNT;
+ }
+- }
+
+- jmp ITloop;
++ jmp ITloop;
+
+ data_phase_overrun:
+- if ((p->features & AHC_ULTRA2) != 0) {
+- call ultra2_dmafinish;
+- }
+ /*
+ * Turn off BITBUCKET mode and notify the host
+ */
+- and SXFRCTL1, ~BITBUCKET;
+- mvi INTSTAT,DATA_OVERRUN;
+- jmp ITloop;
++ and SXFRCTL1, ~BITBUCKET;
++ mvi INTSTAT,DATA_OVERRUN;
++ jmp ITloop;
++
++
+
+-ultra2_dmafinish:
+- if ((p->features & AHC_ULTRA2) != 0) {
+- test DFCNTRL, DIRECTION jnz ultra2_dmahalt;
+- and DFCNTRL, ~SCSIEN;
+- test DFCNTRL, SCSIEN jnz .;
+-ultra2_dmafifoflush:
+- or DFCNTRL, FIFOFLUSH;
+- test DFSTATUS, FIFOEMP jz . - 1;
+- /*
+- * hardware bug alert! This needless set of jumps is to
+- * protect against a FIFOEMP status bit glitch in the
+- * silicon.
+- */
+- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+- test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
+- test DFSTATUS, MREQPEND jnz .;
+-ultra2_dmahalt:
+- test SCSIOFFSET, 0x7f jnz ultra2_shutdown;
+-ultra2_await_nreq:
+- test SCSISIGI, REQI jz ultra2_shutdown;
+- test SSTAT1, (PHASEMIS|REQINIT) jz ultra2_await_nreq;
+-ultra2_shutdown:
+- and DFCNTRL, ~(HDMAEN|SCSIEN);
+- test DFCNTRL, (HDMAEN|SCSIEN) jnz .;
+- bmov SCB_RESID_DCNT, STCNT, 3;
+- mov SCB_RESID_SGCNT, SG_COUNT;
+- or SXFRCTL0, CLRSTCNT|CLRCHN;
+- ret;
+ }
+
+ /*
+@@ -1021,6 +1144,7 @@
+ inb_last:
+ mov NONE,SCSIDATL ret; /*dummy read from latch to ACK*/
+
++
+ mesgin_phasemis:
+ /*
+ * We expected to receive another byte, but the target changed phase
+@@ -1080,7 +1204,9 @@
+ * to drain the data fifo until there is space for the input
+ * latch to drain and HDMAEN de-asserts.
+ */
+- mov NONE, DFDAT;
++ if ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0) {
++ mov NONE, DFDAT;
++ }
+ test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt;
+ }
+ return:
+@@ -1306,11 +1432,17 @@
+ cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .;
+ jmp dma_scb_finish;
+ dma_scb_tohost:
+- if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
++ if ((p->features & AHC_ULTRA2) == 0) {
+ mvi CCSCBCTL, CCSCBRESET;
+ bmov CCSCBRAM, SCB_CONTROL, 32;
+ or CCSCBCTL, CCSCBEN|CCSCBRESET;
+ test CCSCBCTL, CCSCBDONE jz .;
++ } else if ((p->bugs & AHC_BUG_SCBCHAN_UPLOAD) != 0) {
++ mvi CCSCBCTL, CCARREN|CCSCBRESET;
++ cmp CCSCBCTL, ARRDONE|CCARREN jne .;
++ mvi CCHCNT, 32;
++ mvi CCSCBCTL, CCSCBEN|CCSCBRESET;
++ cmp CCSCBCTL, CCSCBDONE|CCSCBEN jne .;
+ } else {
+ mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET;
+ cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .;
+@@ -1342,17 +1474,81 @@
+ mov DFDAT,SINDIR;
+ cmp SINDEX, A jne copy_scb_tofifo_loop;
+ or DFCNTRL, HDMAEN|FIFOFLUSH;
++ jmp dma_finish;
+ dma_scb_fromhost:
+- call dma_finish;
+- /* If we were putting the SCB, we are done */
+- test DMAPARAMS, DIRECTION jz return;
+- mvi SCB_CONTROL call dfdat_in_7;
+- call dfdat_in_7_continued;
+- call dfdat_in_7_continued;
+- jmp dfdat_in_7_continued;
++ mvi DINDEX, SCB_CONTROL;
++ if ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0) {
++ /*
++ * Set the A to -24. It it hits 0, then we let
++ * our code fall through to dfdat_in_8 to complete
++ * the last of the copy.
++ *
++ * Also, things happen 8 bytes at a time in this
++ * case, so we may need to drain the fifo at most
++ * 3 times to keep things flowing
++ */
++ mvi A, -24;
++dma_scb_hang_fifo:
++ /* Wait for the first bit of data to hit the fifo */
++ test DFSTATUS, FIFOEMP jnz .;
++dma_scb_hang_wait:
++ /* OK, now they've started to transfer into the fifo,
++ * so wait for them to stop trying to transfer any
++ * more data.
++ */
++ test DFSTATUS, MREQPEND jnz .;
++ /*
++ * OK, they started, then they stopped, now see if they
++ * managed to complete the job before stopping. Try
++ * it multiple times to give the chip a few cycles to
++ * set the flag if it did complete.
++ */
++ test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
++ test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
++ test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
++ /*
++ * Too bad, the chip didn't complete the DMA, but there
++ * aren't any more memory requests pending, so that
++ * means it stopped part way through and hung. That's
++ * our bug, so now we drain what data there is in the
++ * fifo in order to get things going again.
++ */
++dma_scb_hang_empty_fifo:
++ call dfdat_in_8;
++ add A, 8;
++ add SINDEX, A, HCNT;
++ /*
++ * If there are another 8 bytes of data waiting in the
++ * fifo, then the carry bit will be set as a result
++ * of the above add command (unless A is non-negative,
++ * in which case the carry bit won't be set).
++ */
++ jc dma_scb_hang_empty_fifo;
++ /*
++ * We've emptied the fifo now, but we wouldn't have got
++ * here if the memory transfer hadn't stopped part way
++ * through, so go back up to the beginning of the
++ * loop and start over. When it succeeds in getting
++ * all the data down, HDONE will be set and we'll
++ * jump to the code just below here.
++ */
++ jmp dma_scb_hang_fifo;
++dma_scb_hang_dma_done:
++ and DFCNTRL, ~HDMAEN;
++ test DFCNTRL, HDMAEN jnz .;
++ call dfdat_in_8;
++ add A, 8;
++ cmp A, 8 jne . - 2;
++ ret;
++ } else {
++ call dma_finish;
++ call dfdat_in_8;
++ call dfdat_in_8;
++ call dfdat_in_8;
++ }
++dfdat_in_8:
++ mov DINDIR,DFDAT;
+ dfdat_in_7:
+- mov DINDEX,SINDEX;
+-dfdat_in_7_continued:
+ mov DINDIR,DFDAT;
+ mov DINDIR,DFDAT;
+ mov DINDIR,DFDAT;
+diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx_proc.c linux/drivers/scsi/aic7xxx/aic7xxx_proc.c
+--- linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx_proc.c Wed Dec 31 19:00:00 1969
++++ linux/drivers/scsi/aic7xxx/aic7xxx_proc.c Tue Feb 6 03:49:36 2001
+@@ -0,0 +1,414 @@
++/*+M*************************************************************************
++ * Adaptec AIC7xxx device driver proc support for Linux.
++ *
++ * Copyright (c) 1995, 1996 Dean W. Gehnert
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * ----------------------------------------------------------------
++ * o Modified from the EATA-DMA /proc support.
++ * o Additional support for device block statistics provided by
++ * Matthew Jacob.
++ * o Correction of overflow by Heinz Mauelshagen
++ * o Adittional corrections by Doug Ledford
++ *
++ * Dean W. Gehnert, deang@teleport.com, 05/01/96
++ *
++ * $Id: aic7xxx_proc.c,v 4.1 1997/06/97 08:23:42 deang Exp $
++ *-M*************************************************************************/
++
++#include <linux/config.h>
++
++#define BLS (&aic7xxx_buffer[size])
++#define HDRB \
++" < 2K 2K+ 4K+ 8K+ 16K+ 32K+ 64K+ 128K+"
++
++#ifdef PROC_DEBUG
++extern int vsprintf(char *, const char *, va_list);
++
++static void
++proc_debug(const char *fmt, ...)
++{
++ va_list ap;
++ char buf[256];
++
++ va_start(ap, fmt);
++ vsprintf(buf, fmt, ap);
++ printk(buf);
++ va_end(ap);
++}
++#else /* PROC_DEBUG */
++# define proc_debug(fmt, args...)
++#endif /* PROC_DEBUG */
++
++static int aic7xxx_buffer_size = 0;
++static char *aic7xxx_buffer = NULL;
++
++
++/*+F*************************************************************************
++ * Function:
++ * aic7xxx_set_info
++ *
++ * Description:
++ * Set parameters for the driver from the /proc filesystem.
++ *-F*************************************************************************/
++int
++aic7xxx_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
++{
++ proc_debug("aic7xxx_set_info(): %s\n", buffer);
++ return (-ENOSYS); /* Currently this is a no-op */
++}
++
++
++/*+F*************************************************************************
++ * Function:
++ * aic7xxx_proc_info
++ *
++ * Description:
++ * Return information to handle /proc support for the driver.
++ *-F*************************************************************************/
++int
++aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length,
++ int hostno, int inout)
++{
++ struct Scsi_Host *HBAptr;
++ struct aic7xxx_host *p;
++ int size = 0;
++ unsigned char i;
++ struct aic7xxx_xferstats *sp;
++ unsigned char target;
++
++ HBAptr = NULL;
++
++ for(p=first_aic7xxx; p->host->host_no != hostno; p=p->next)
++ ;
++
++ if (!p)
++ {
++ size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno);
++ if (size > length)
++ {
++ return (size);
++ }
++ else
++ {
++ return (length);
++ }
++ }
++
++ HBAptr = p->host;
++
++ if (inout == TRUE) /* Has data been written to the file? */
++ {
++ return (aic7xxx_set_info(buffer, length, HBAptr));
++ }
++
++ p = (struct aic7xxx_host *) HBAptr->hostdata;
++
++ /*
++ * It takes roughly 1K of space to hold all relevant card info, not
++ * counting any proc stats, so we start out with a 1.5k buffer size and
++ * if proc_stats is defined, then we sweep the stats structure to see
++ * how many drives we will be printing out for and add 384 bytes per
++ * device with active stats.
++ *
++ * Hmmmm...that 1.5k seems to keep growing as items get added so they
++ * can be easily viewed for debugging purposes. So, we bumped that
++ * 1.5k to 4k so we can quit having to bump it all the time.
++ */
++
++ size = 4096;
++ for (target = 0; target < MAX_TARGETS; target++)
++ {
++ if (p->dev_flags[target] & DEVICE_PRESENT)
++#ifdef AIC7XXX_PROC_STATS
++ size += 512;
++#else
++ size += 256;
++#endif
++ }
++ if (aic7xxx_buffer_size != size)
++ {
++ if (aic7xxx_buffer != NULL)
++ {
++ kfree(aic7xxx_buffer);
++ aic7xxx_buffer_size = 0;
++ }
++ aic7xxx_buffer = kmalloc(size, GFP_KERNEL);
++ }
++ if (aic7xxx_buffer == NULL)
++ {
++ size = sprintf(buffer, "AIC7xxx - kmalloc error at line %d\n",
++ __LINE__);
++ return size;
++ }
++ aic7xxx_buffer_size = size;
++
++ size = 0;
++ size += sprintf(BLS, "Adaptec AIC7xxx driver version: ");
++ size += sprintf(BLS, "%s/", AIC7XXX_C_VERSION);
++ size += sprintf(BLS, "%s", AIC7XXX_H_VERSION);
++ size += sprintf(BLS, "\n");
++ size += sprintf(BLS, "Compile Options:\n");
++#ifdef CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
++ size += sprintf(BLS, " TCQ Enabled By Default : Enabled\n");
++#else
++ size += sprintf(BLS, " TCQ Enabled By Default : Disabled\n");
++#endif
++#ifdef AIC7XXX_PROC_STATS
++ size += sprintf(BLS, " AIC7XXX_PROC_STATS : Enabled\n");
++#else
++ size += sprintf(BLS, " AIC7XXX_PROC_STATS : Disabled\n");
++#endif
++ size += sprintf(BLS, " AIC7XXX_RESET_DELAY : %d\n", AIC7XXX_RESET_DELAY);
++ size += sprintf(BLS, "\n");
++ size += sprintf(BLS, "Adapter Configuration:\n");
++ size += sprintf(BLS, " SCSI Adapter: %s\n",
++ board_names[p->board_name_index]);
++ if (p->flags & AHC_TWIN)
++ size += sprintf(BLS, " Twin Channel Controller ");
++ else
++ {
++ char *channel = "";
++ char *ultra = "";
++ char *wide = "Narrow ";
++ if (p->flags & AHC_MULTI_CHANNEL)
++ {
++ channel = " Channel A";
++ if (p->flags & (AHC_CHNLB|AHC_CHNLC))
++ channel = (p->flags & AHC_CHNLB) ? " Channel B" : " Channel C";
++ }
++ if (p->features & AHC_WIDE)
++ wide = "Wide ";
++ if (p->features & AHC_ULTRA3)
++ {
++ switch(p->chip & AHC_CHIPID_MASK)
++ {
++ case AHC_AIC7892:
++ case AHC_AIC7899:
++ ultra = "Ultra-160/m LVD/SE ";
++ break;
++ default:
++ ultra = "Ultra-3 LVD/SE ";
++ break;
++ }
++ }
++ else if (p->features & AHC_ULTRA2)
++ ultra = "Ultra-2 LVD/SE ";
++ else if (p->features & AHC_ULTRA)
++ ultra = "Ultra ";
++ size += sprintf(BLS, " %s%sController%s ",
++ ultra, wide, channel);
++ }
++ switch(p->chip & ~AHC_CHIPID_MASK)
++ {
++ case AHC_VL:
++ size += sprintf(BLS, "at VLB slot %d\n", p->pci_device_fn);
++ break;
++ case AHC_EISA:
++ size += sprintf(BLS, "at EISA slot %d\n", p->pci_device_fn);
++ break;
++ default:
++ size += sprintf(BLS, "at PCI %d/%d/%d\n", p->pci_bus,
++ PCI_SLOT(p->pci_device_fn), PCI_FUNC(p->pci_device_fn));
++ break;
++ }
++ if( !(p->maddr) )
++ {
++ size += sprintf(BLS, " Programmed I/O Base: %lx\n", p->base);
++ }
++ else
++ {
++ size += sprintf(BLS, " PCI MMAPed I/O Base: 0x%lx\n", p->mbase);
++ }
++ if( (p->chip & (AHC_VL | AHC_EISA)) )
++ {
++ size += sprintf(BLS, " BIOS Memory Address: 0x%08x\n", p->bios_address);
++ }
++ size += sprintf(BLS, " Adapter SEEPROM Config: %s\n",
++ (p->flags & AHC_SEEPROM_FOUND) ? "SEEPROM found and used." :
++ ((p->flags & AHC_USEDEFAULTS) ? "SEEPROM not found, using defaults." :
++ "SEEPROM not found, using leftover BIOS values.") );
++ size += sprintf(BLS, " Adaptec SCSI BIOS: %s\n",
++ (p->flags & AHC_BIOS_ENABLED) ? "Enabled" : "Disabled");
++ size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq);
++ size += sprintf(BLS, " SCBs: Active %d, Max Active %d,\n",
++ p->activescbs, p->max_activescbs);
++ size += sprintf(BLS, " Allocated %d, HW %d, "
++ "Page %d\n", p->scb_data->numscbs, p->scb_data->maxhscbs,
++ p->scb_data->maxscbs);
++ if (p->flags & AHC_EXTERNAL_SRAM)
++ size += sprintf(BLS, " Using External SCB SRAM\n");
++ size += sprintf(BLS, " Interrupts: %ld", p->isr_count);
++ if (p->chip & AHC_EISA)
++ {
++ size += sprintf(BLS, " %s\n",
++ (p->pause & IRQMS) ? "(Level Sensitive)" : "(Edge Triggered)");
++ }
++ else
++ {
++ size += sprintf(BLS, "\n");
++ }
++ size += sprintf(BLS, " BIOS Control Word: 0x%04x\n",
++ p->bios_control);
++ size += sprintf(BLS, " Adapter Control Word: 0x%04x\n",
++ p->adapter_control);
++ size += sprintf(BLS, " Extended Translation: %sabled\n",
++ (p->flags & AHC_EXTEND_TRANS_A) ? "En" : "Dis");
++ size += sprintf(BLS, "Disconnect Enable Flags: 0x%04x\n", p->discenable);
++ if (p->features & (AHC_ULTRA | AHC_ULTRA2))
++ {
++ size += sprintf(BLS, " Ultra Enable Flags: 0x%04x\n", p->ultraenb);
++ }
++ size += sprintf(BLS, " Tag Queue Enable Flags: 0x%04x\n", p->tagenable);
++ size += sprintf(BLS, "Ordered Queue Tag Flags: 0x%04x\n", p->orderedtag);
++ size += sprintf(BLS, "Default Tag Queue Depth: %d\n", AIC7XXX_CMDS_PER_DEVICE);
++ size += sprintf(BLS, " Tagged Queue By Device array for aic7xxx host "
++ "instance %d:\n", p->instance);
++ size += sprintf(BLS, " {");
++ for(i=0; i < (MAX_TARGETS - 1); i++)
++ size += sprintf(BLS, "%d,",aic7xxx_tag_info[p->instance].tag_commands[i]);
++ size += sprintf(BLS, "%d}\n",aic7xxx_tag_info[p->instance].tag_commands[i]);
++ size += sprintf(BLS, " Actual queue depth per device for aic7xxx host "
++ "instance %d:\n", p->instance);
++ size += sprintf(BLS, " {");
++ for(i=0; i < (MAX_TARGETS - 1); i++)
++ size += sprintf(BLS, "%d,", p->dev_max_queue_depth[i]);
++ size += sprintf(BLS, "%d}\n", p->dev_max_queue_depth[i]);
++
++ size += sprintf(BLS, "\n");
++ size += sprintf(BLS, "Statistics:\n\n");
++ for (target = 0; target < MAX_TARGETS; target++)
++ {
++ sp = &p->stats[target];
++ if ((p->dev_flags[target] & DEVICE_PRESENT) == 0)
++ {
++ continue;
++ }
++ if (p->features & AHC_TWIN)
++ {
++ size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
++ p->host_no, (target >> 3), (target & 0x7), 0);
++ }
++ else
++ {
++ size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
++ p->host_no, 0, target, 0);
++ }
++ size += sprintf(BLS, " Device using %s/%s",
++ (p->transinfo[target].cur_width == MSG_EXT_WDTR_BUS_16_BIT) ?
++ "Wide" : "Narrow",
++ (p->transinfo[target].cur_offset != 0) ?
++ "Sync transfers at " : "Async transfers.\n" );
++ if (p->transinfo[target].cur_offset != 0)
++ {
++ struct aic7xxx_syncrate *sync_rate;
++ unsigned char options = p->transinfo[target].cur_options;
++ int period = p->transinfo[target].cur_period;
++ int rate = (p->transinfo[target].cur_width ==
++ MSG_EXT_WDTR_BUS_16_BIT) ? 1 : 0;
++
++ sync_rate = aic7xxx_find_syncrate(p, &period, 0, &options);
++ if (sync_rate != NULL)
++ {
++ size += sprintf(BLS, "%s MByte/sec, offset %d\n",
++ sync_rate->rate[rate],
++ p->transinfo[target].cur_offset );
++ }
++ else
++ {
++ size += sprintf(BLS, "3.3 MByte/sec, offset %d\n",
++ p->transinfo[target].cur_offset );
++ }
++ }
++ size += sprintf(BLS, " Transinfo settings: ");
++ size += sprintf(BLS, "current(%d/%d/%d/%d), ",
++ p->transinfo[target].cur_period,
++ p->transinfo[target].cur_offset,
++ p->transinfo[target].cur_width,
++ p->transinfo[target].cur_options);
++ size += sprintf(BLS, "goal(%d/%d/%d/%d), ",
++ p->transinfo[target].goal_period,
++ p->transinfo[target].goal_offset,
++ p->transinfo[target].goal_width,
++ p->transinfo[target].goal_options);
++ size += sprintf(BLS, "user(%d/%d/%d/%d)\n",
++ p->transinfo[target].user_period,
++ p->transinfo[target].user_offset,
++ p->transinfo[target].user_width,
++ p->transinfo[target].user_options);
++#ifdef AIC7XXX_PROC_STATS
++ size += sprintf(BLS, " Total transfers %ld (%ld reads and %ld writes)\n",
++ sp->r_total + sp->w_total, sp->r_total, sp->w_total);
++ size += sprintf(BLS, "%s\n", HDRB);
++ size += sprintf(BLS, " Reads:");
++ for (i = 0; i < NUMBER(sp->r_bins); i++)
++ {
++ size += sprintf(BLS, " %7ld", sp->r_bins[i]);
++ }
++ size += sprintf(BLS, "\n");
++ size += sprintf(BLS, " Writes:");
++ for (i = 0; i < NUMBER(sp->w_bins); i++)
++ {
++ size += sprintf(BLS, " %7ld", sp->w_bins[i]);
++ }
++ size += sprintf(BLS, "\n");
++#else
++ size += sprintf(BLS, " Total transfers %ld (%ld reads and %ld writes)\n",
++ sp->r_total + sp->w_total, sp->r_total, sp->w_total);
++#endif /* AIC7XXX_PROC_STATS */
++ size += sprintf(BLS, "\n\n");
++ }
++
++ if (size >= aic7xxx_buffer_size)
++ {
++ printk(KERN_WARNING "aic7xxx: Overflow in aic7xxx_proc.c\n");
++ }
++
++ if (offset > size - 1)
++ {
++ kfree(aic7xxx_buffer);
++ aic7xxx_buffer = NULL;
++ aic7xxx_buffer_size = length = 0;
++ *start = NULL;
++ }
++ else
++ {
++ *start = buffer;
++ length = MIN(length, size - offset);
++ memcpy(buffer, &aic7xxx_buffer[offset], length);
++ }
++
++ return (length);
++}
++
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * Emacs will notice this stuff at the end of the file and automatically
++ * adjust the settings for this buffer only. This must remain at the end
++ * of the file.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-indent-level: 2
++ * c-brace-imaginary-offset: 0
++ * c-brace-offset: -2
++ * c-argdecl-indent: 2
++ * c-label-offset: -2
++ * c-continued-statement-offset: 2
++ * c-continued-brace-offset: 0
++ * indent-tabs-mode: nil
++ * tab-width: 8
++ * End:
++ */
+diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx_reg.h linux/drivers/scsi/aic7xxx/aic7xxx_reg.h
+--- linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx_reg.h Wed Dec 31 19:00:00 1969
++++ linux/drivers/scsi/aic7xxx/aic7xxx_reg.h Tue Feb 6 03:49:36 2001
+@@ -0,0 +1,629 @@
++/*
++ * DO NOT EDIT - This file is automatically generated.
++ */
++
++#define SCSISEQ 0x00
++#define TEMODE 0x80
++#define ENSELO 0x40
++#define ENSELI 0x20
++#define ENRSELI 0x10
++#define ENAUTOATNO 0x08
++#define ENAUTOATNI 0x04
++#define ENAUTOATNP 0x02
++#define SCSIRSTO 0x01
++
++#define SXFRCTL0 0x01
++#define DFON 0x80
++#define DFPEXP 0x40
++#define FAST20 0x20
++#define CLRSTCNT 0x10
++#define SPIOEN 0x08
++#define SCAMEN 0x04
++#define CLRCHN 0x02
++
++#define SXFRCTL1 0x02
++#define BITBUCKET 0x80
++#define SWRAPEN 0x40
++#define ENSPCHK 0x20
++#define STIMESEL 0x18
++#define ENSTIMER 0x04
++#define ACTNEGEN 0x02
++#define STPWEN 0x01
++
++#define SCSISIGO 0x03
++#define CDO 0x80
++#define IOO 0x40
++#define MSGO 0x20
++#define ATNO 0x10
++#define SELO 0x08
++#define BSYO 0x04
++#define REQO 0x02
++#define ACKO 0x01
++
++#define SCSISIGI 0x03
++#define ATNI 0x10
++#define SELI 0x08
++#define BSYI 0x04
++#define REQI 0x02
++#define ACKI 0x01
++
++#define SCSIRATE 0x04
++#define WIDEXFER 0x80
++#define SXFR_ULTRA2 0x7f
++#define SXFR 0x70
++#define SOFS 0x0f
++
++#define SCSIID 0x05
++#define SCSIOFFSET 0x05
++#define SOFS_ULTRA2 0x7f
++
++#define SCSIDATL 0x06
++
++#define SCSIDATH 0x07
++
++#define STCNT 0x08
++
++#define OPTIONMODE 0x08
++#define AUTORATEEN 0x80
++#define AUTOACKEN 0x40
++#define ATNMGMNTEN 0x20
++#define BUSFREEREV 0x10
++#define EXPPHASEDIS 0x08
++#define SCSIDATL_IMGEN 0x04
++#define AUTO_MSGOUT_DE 0x02
++#define DIS_MSGIN_DUALEDGE 0x01
++
++#define CLRSINT0 0x0b
++#define CLRSELDO 0x40
++#define CLRSELDI 0x20
++#define CLRSELINGO 0x10
++#define CLRSWRAP 0x08
++#define CLRSPIORDY 0x02
++
++#define SSTAT0 0x0b
++#define TARGET 0x80
++#define SELDO 0x40
++#define SELDI 0x20
++#define SELINGO 0x10
++#define IOERR 0x08
++#define SWRAP 0x08
++#define SDONE 0x04
++#define SPIORDY 0x02
++#define DMADONE 0x01
++
++#define CLRSINT1 0x0c
++#define CLRSELTIMEO 0x80
++#define CLRATNO 0x40
++#define CLRSCSIRSTI 0x20
++#define CLRBUSFREE 0x08
++#define CLRSCSIPERR 0x04
++#define CLRPHASECHG 0x02
++#define CLRREQINIT 0x01
++
++#define SSTAT1 0x0c
++#define SELTO 0x80
++#define ATNTARG 0x40
++#define SCSIRSTI 0x20
++#define PHASEMIS 0x10
++#define BUSFREE 0x08
++#define SCSIPERR 0x04
++#define PHASECHG 0x02
++#define REQINIT 0x01
++
++#define SSTAT2 0x0d
++#define OVERRUN 0x80
++#define SHVALID 0x40
++#define WIDE_RES 0x20
++#define SFCNT 0x1f
++#define EXP_ACTIVE 0x10
++#define CRCVALERR 0x08
++#define CRCENDERR 0x04
++#define CRCREQERR 0x02
++#define DUAL_EDGE_ERROR 0x01
++
++#define SSTAT3 0x0e
++#define SCSICNT 0xf0
++#define OFFCNT 0x0f
++
++#define SCSIID_ULTRA2 0x0f
++#define OID 0x0f
++
++#define SIMODE0 0x10
++#define ENSELDO 0x40
++#define ENSELDI 0x20
++#define ENSELINGO 0x10
++#define ENIOERR 0x08
++#define ENSWRAP 0x08
++#define ENSDONE 0x04
++#define ENSPIORDY 0x02
++#define ENDMADONE 0x01
++
++#define SIMODE1 0x11
++#define ENSELTIMO 0x80
++#define ENATNTARG 0x40
++#define ENSCSIRST 0x20
++#define ENPHASEMIS 0x10
++#define ENBUSFREE 0x08
++#define ENSCSIPERR 0x04
++#define ENPHASECHG 0x02
++#define ENREQINIT 0x01
++
++#define SCSIBUSL 0x12
++
++#define SCSIBUSH 0x13
++
++#define SHADDR 0x14
++
++#define SELTIMER 0x18
++#define STAGE6 0x20
++#define STAGE5 0x10
++#define STAGE4 0x08
++#define STAGE3 0x04
++#define STAGE2 0x02
++#define STAGE1 0x01
++
++#define SELID 0x19
++#define SELID_MASK 0xf0
++#define ONEBIT 0x08
++
++#define SPIOCAP 0x1b
++#define SOFT1 0x80
++#define SOFT0 0x40
++#define SOFTCMDEN 0x20
++#define HAS_BRDCTL 0x10
++#define SEEPROM 0x08
++#define EEPROM 0x04
++#define ROM 0x02
++#define SSPIOCPS 0x01
++
++#define BRDCTL 0x1d
++#define BRDDAT7 0x80
++#define BRDDAT6 0x40
++#define BRDDAT5 0x20
++#define BRDDAT4 0x10
++#define BRDSTB 0x10
++#define BRDCS 0x08
++#define BRDDAT3 0x08
++#define BRDDAT2 0x04
++#define BRDRW 0x04
++#define BRDRW_ULTRA2 0x02
++#define BRDCTL1 0x02
++#define BRDSTB_ULTRA2 0x01
++#define BRDCTL0 0x01
++
++#define SEECTL 0x1e
++#define EXTARBACK 0x80
++#define EXTARBREQ 0x40
++#define SEEMS 0x20
++#define SEERDY 0x10
++#define SEECS 0x08
++#define SEECK 0x04
++#define SEEDO 0x02
++#define SEEDI 0x01
++
++#define SBLKCTL 0x1f
++#define DIAGLEDEN 0x80
++#define DIAGLEDON 0x40
++#define AUTOFLUSHDIS 0x20
++#define ENAB40 0x08
++#define ENAB20 0x04
++#define SELWIDE 0x02
++#define XCVR 0x01
++
++#define SRAM_BASE 0x20
++
++#define TARG_SCSIRATE 0x20
++
++#define ULTRA_ENB 0x30
++
++#define DISC_DSB 0x32
++
++#define MSG_OUT 0x34
++
++#define DMAPARAMS 0x35
++#define PRELOADEN 0x80
++#define WIDEODD 0x40
++#define SCSIEN 0x20
++#define SDMAENACK 0x10
++#define SDMAEN 0x10
++#define HDMAEN 0x08
++#define HDMAENACK 0x08
++#define DIRECTION 0x04
++#define FIFOFLUSH 0x02
++#define FIFORESET 0x01
++
++#define SEQ_FLAGS 0x36
++#define IDENTIFY_SEEN 0x80
++#define SCBPTR_VALID 0x20
++#define DPHASE 0x10
++#define AMTARGET 0x08
++#define WIDE_BUS 0x02
++#define TWIN_BUS 0x01
++
++#define SAVED_TCL 0x37
++
++#define SG_COUNT 0x38
++
++#define SG_NEXT 0x39
++
++#define LASTPHASE 0x3d
++#define P_MESGIN 0xe0
++#define PHASE_MASK 0xe0
++#define P_STATUS 0xc0
++#define P_MESGOUT 0xa0
++#define P_COMMAND 0x80
++#define CDI 0x80
++#define IOI 0x40
++#define P_DATAIN 0x40
++#define MSGI 0x20
++#define P_BUSFREE 0x01
++#define P_DATAOUT 0x00
++
++#define WAITING_SCBH 0x3e
++
++#define DISCONNECTED_SCBH 0x3f
++
++#define FREE_SCBH 0x40
++
++#define HSCB_ADDR 0x41
++
++#define SCBID_ADDR 0x45
++
++#define TMODE_CMDADDR 0x49
++
++#define KERNEL_QINPOS 0x4d
++
++#define QINPOS 0x4e
++
++#define QOUTPOS 0x4f
++
++#define TMODE_CMDADDR_NEXT 0x50
++
++#define ARG_1 0x51
++#define RETURN_1 0x51
++#define SEND_MSG 0x80
++#define SEND_SENSE 0x40
++#define SEND_REJ 0x20
++#define MSGOUT_PHASEMIS 0x10
++
++#define ARG_2 0x52
++#define RETURN_2 0x52
++
++#define LAST_MSG 0x53
++
++#define PREFETCH_CNT 0x54
++
++#define SCSICONF 0x5a
++#define TERM_ENB 0x80
++#define RESET_SCSI 0x40
++#define HWSCSIID 0x0f
++#define HSCSIID 0x07
++
++#define HOSTCONF 0x5d
++
++#define HA_274_BIOSCTRL 0x5f
++#define BIOSMODE 0x30
++#define BIOSDISABLED 0x30
++#define CHANNEL_B_PRIMARY 0x08
++
++#define SEQCTL 0x60
++#define PERRORDIS 0x80
++#define PAUSEDIS 0x40
++#define FAILDIS 0x20
++#define FASTMODE 0x10
++#define BRKADRINTEN 0x08
++#define STEP 0x04
++#define SEQRESET 0x02
++#define LOADRAM 0x01
++
++#define SEQRAM 0x61
++
++#define SEQADDR0 0x62
++
++#define SEQADDR1 0x63
++#define SEQADDR1_MASK 0x01
++
++#define ACCUM 0x64
++
++#define SINDEX 0x65
++
++#define DINDEX 0x66
++
++#define ALLONES 0x69
++
++#define ALLZEROS 0x6a
++
++#define NONE 0x6a
++
++#define FLAGS 0x6b
++#define ZERO 0x02
++#define CARRY 0x01
++
++#define SINDIR 0x6c
++
++#define DINDIR 0x6d
++
++#define FUNCTION1 0x6e
++
++#define STACK 0x6f
++
++#define TARG_OFFSET 0x70
++
++#define BCTL 0x84
++#define ACE 0x08
++#define ENABLE 0x01
++
++#define DSCOMMAND0 0x84
++#define INTSCBRAMSEL 0x08
++#define RAMPS 0x04
++#define USCBSIZE32 0x02
++#define CIOPARCKEN 0x01
++
++#define DSCOMMAND 0x84
++#define CACHETHEN 0x80
++#define DPARCKEN 0x40
++#define MPARCKEN 0x20
++#define EXTREQLCK 0x10
++
++#define BUSTIME 0x85
++#define BOFF 0xf0
++#define BON 0x0f
++
++#define BUSSPD 0x86
++#define DFTHRSH 0xc0
++#define STBOFF 0x38
++#define STBON 0x07
++
++#define DSPCISTATUS 0x86
++#define DFTHRSH_100 0xc0
++
++#define HCNTRL 0x87
++#define POWRDN 0x40
++#define SWINT 0x10
++#define IRQMS 0x08
++#define PAUSE 0x04
++#define INTEN 0x02
++#define CHIPRST 0x01
++#define CHIPRSTACK 0x01
++
++#define HADDR 0x88
++
++#define HCNT 0x8c
++
++#define SCBPTR 0x90
++
++#define INTSTAT 0x91
++#define SEQINT_MASK 0xf1
++#define DATA_OVERRUN 0xe1
++#define MSGIN_PHASEMIS 0xd1
++#define TRACEPOINT2 0xc1
++#define SEQ_SG_FIXUP 0xb1
++#define AWAITING_MSG 0xa1
++#define RESIDUAL 0x81
++#define BAD_STATUS 0x71
++#define REJECT_MSG 0x61
++#define WIDE_RESIDUE 0x51
++#define EXTENDED_MSG 0x41
++#define NO_MATCH 0x31
++#define NO_IDENT 0x21
++#define SEND_REJECT 0x11
++#define INT_PEND 0x0f
++#define BRKADRINT 0x08
++#define SCSIINT 0x04
++#define CMDCMPLT 0x02
++#define BAD_PHASE 0x01
++#define SEQINT 0x01
++
++#define CLRINT 0x92
++#define CLRPARERR 0x10
++#define CLRBRKADRINT 0x08
++#define CLRSCSIINT 0x04
++#define CLRCMDINT 0x02
++#define CLRSEQINT 0x01
++
++#define ERROR 0x92
++#define CIOPARERR 0x80
++#define PCIERRSTAT 0x40
++#define MPARERR 0x20
++#define DPARERR 0x10
++#define SQPARERR 0x08
++#define ILLOPCODE 0x04
++#define DSCTMOUT 0x02
++#define ILLSADDR 0x02
++#define ILLHADDR 0x01
++
++#define DFCNTRL 0x93
++
++#define DFSTATUS 0x94
++#define PRELOAD_AVAIL 0x80
++#define DWORDEMP 0x20
++#define MREQPEND 0x10
++#define HDONE 0x08
++#define DFTHRESH 0x04
++#define FIFOFULL 0x02
++#define FIFOEMP 0x01
++
++#define DFDAT 0x99
++
++#define SCBCNT 0x9a
++#define SCBAUTO 0x80
++#define SCBCNT_MASK 0x1f
++
++#define QINFIFO 0x9b
++
++#define QINCNT 0x9c
++
++#define SCSIDATL_IMG 0x9c
++
++#define QOUTFIFO 0x9d
++
++#define CRCCONTROL1 0x9d
++#define CRCONSEEN 0x80
++#define CRCVALCHKEN 0x40
++#define CRCENDCHKEN 0x20
++#define CRCREQCHKEN 0x10
++#define TARGCRCENDEN 0x08
++#define TARGCRCCNTEN 0x04
++
++#define SCSIPHASE 0x9e
++#define SP_STATUS 0x20
++#define SP_COMMAND 0x10
++#define SP_MSG_IN 0x08
++#define SP_MSG_OUT 0x04
++#define SP_DATA_IN 0x02
++#define SP_DATA_OUT 0x01
++
++#define QOUTCNT 0x9e
++
++#define SFUNCT 0x9f
++#define ALT_MODE 0x80
++
++#define SCB_CONTROL 0xa0
++#define MK_MESSAGE 0x80
++#define DISCENB 0x40
++#define TAG_ENB 0x20
++#define DISCONNECTED 0x04
++#define SCB_TAG_TYPE 0x03
++
++#define SCB_BASE 0xa0
++
++#define SCB_TCL 0xa1
++#define TID 0xf0
++#define SELBUSB 0x08
++#define LID 0x07
++
++#define SCB_TARGET_STATUS 0xa2
++
++#define SCB_SGCOUNT 0xa3
++
++#define SCB_SGPTR 0xa4
++
++#define SCB_RESID_SGCNT 0xa8
++
++#define SCB_RESID_DCNT 0xa9
++
++#define SCB_DATAPTR 0xac
++
++#define SCB_DATACNT 0xb0
++
++#define SCB_CMDPTR 0xb4
++
++#define SCB_CMDLEN 0xb8
++
++#define SCB_TAG 0xb9
++
++#define SCB_NEXT 0xba
++
++#define SCB_PREV 0xbb
++
++#define SCB_BUSYTARGETS 0xbc
++
++#define SEECTL_2840 0xc0
++#define CS_2840 0x04
++#define CK_2840 0x02
++#define DO_2840 0x01
++
++#define STATUS_2840 0xc1
++#define EEPROM_TF 0x80
++#define BIOS_SEL 0x60
++#define ADSEL 0x1e
++#define DI_2840 0x01
++
++#define CCHADDR 0xe0
++
++#define CCHCNT 0xe8
++
++#define CCSGRAM 0xe9
++
++#define CCSGADDR 0xea
++
++#define CCSGCTL 0xeb
++#define CCSGDONE 0x80
++#define CCSGEN 0x08
++#define FLAG 0x02
++#define CCSGRESET 0x01
++
++#define CCSCBRAM 0xec
++
++#define CCSCBADDR 0xed
++
++#define CCSCBCTL 0xee
++#define CCSCBDONE 0x80
++#define ARRDONE 0x40
++#define CCARREN 0x10
++#define CCSCBEN 0x08
++#define CCSCBDIR 0x04
++#define CCSCBRESET 0x01
++
++#define CCSCBCNT 0xef
++
++#define CCSCBPTR 0xf1
++
++#define HNSCB_QOFF 0xf4
++
++#define HESCB_QOFF 0xf5
++
++#define SNSCB_QOFF 0xf6
++
++#define SESCB_QOFF 0xf7
++
++#define SDSCB_QOFF 0xf8
++
++#define QOFF_CTLSTA 0xfa
++#define ESTABLISH_SCB_AVAIL 0x80
++#define SCB_AVAIL 0x40
++#define SNSCB_ROLLOVER 0x20
++#define SDSCB_ROLLOVER 0x10
++#define SESCB_ROLLOVER 0x08
++#define SCB_QSIZE 0x07
++#define SCB_QSIZE_256 0x06
++
++#define DFF_THRSH 0xfb
++#define WR_DFTHRSH 0x70
++#define WR_DFTHRSH_MAX 0x70
++#define WR_DFTHRSH_90 0x60
++#define WR_DFTHRSH_85 0x50
++#define WR_DFTHRSH_75 0x40
++#define WR_DFTHRSH_63 0x30
++#define WR_DFTHRSH_50 0x20
++#define WR_DFTHRSH_25 0x10
++#define RD_DFTHRSH_MAX 0x07
++#define RD_DFTHRSH 0x07
++#define RD_DFTHRSH_90 0x06
++#define RD_DFTHRSH_85 0x05
++#define RD_DFTHRSH_75 0x04
++#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 SG_CACHEPTR 0xfc
++#define SG_USER_DATA 0xfc
++#define LAST_SEG 0x02
++#define LAST_SEG_DONE 0x01
++
++
++#define CMD_GROUP2_BYTE_DELTA 0xfa
++#define MAX_OFFSET_8BIT 0x0f
++#define BUS_16_BIT 0x01
++#define QINFIFO_OFFSET 0x02
++#define CMD_GROUP5_BYTE_DELTA 0x0b
++#define CMD_GROUP_CODE_SHIFT 0x05
++#define MAX_OFFSET_ULTRA2 0x7f
++#define MAX_OFFSET_16BIT 0x08
++#define BUS_8_BIT 0x00
++#define QOUTFIFO_OFFSET 0x01
++#define UNTAGGEDSCB_OFFSET 0x00
++#define CCSGRAM_MAXSEGS 0x10
++#define SCB_LIST_NULL 0xff
++#define SG_SIZEOF 0x08
++#define CMD_GROUP4_BYTE_DELTA 0x04
++#define CMD_GROUP0_BYTE_DELTA 0xfc
++#define HOST_MSG 0xff
++#define BUS_32_BIT 0x02
++#define CCSGADDR_MAX 0x80
++
++
++/* Downloaded Constant Definitions */
++#define TMODE_NUMCMDS 0x00
+diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx_seq.c linux/drivers/scsi/aic7xxx/aic7xxx_seq.c
+--- linux-2.2.17/drivers/scsi/aic7xxx/aic7xxx_seq.c Wed Dec 31 19:00:00 1969
++++ linux/drivers/scsi/aic7xxx/aic7xxx_seq.c Tue Feb 6 03:49:36 2001
+@@ -0,0 +1,830 @@
++/*
++ * DO NOT EDIT - This file is automatically generated.
++ */
++static unsigned char seqprog[] = {
++ 0xff, 0x6a, 0x06, 0x08,
++ 0x7f, 0x02, 0x04, 0x08,
++ 0x12, 0x6a, 0x00, 0x00,
++ 0xff, 0x6a, 0xd6, 0x09,
++ 0xff, 0x6a, 0xdc, 0x09,
++ 0x00, 0x65, 0xcc, 0x58,
++ 0xf7, 0x01, 0x02, 0x08,
++ 0xff, 0x4e, 0xc8, 0x08,
++ 0xbf, 0x60, 0xc0, 0x08,
++ 0x60, 0x0b, 0x86, 0x68,
++ 0x40, 0x00, 0x0c, 0x68,
++ 0x08, 0x1f, 0x3e, 0x10,
++ 0x60, 0x0b, 0x86, 0x68,
++ 0x40, 0x00, 0x0c, 0x68,
++ 0x08, 0x1f, 0x3e, 0x10,
++ 0xff, 0x3e, 0x48, 0x60,
++ 0x40, 0xfa, 0x10, 0x78,
++ 0xff, 0xf6, 0xd4, 0x08,
++ 0x01, 0x4e, 0x9c, 0x18,
++ 0x40, 0x60, 0xc0, 0x00,
++ 0x00, 0x4d, 0x10, 0x70,
++ 0x01, 0x4e, 0x9c, 0x18,
++ 0xbf, 0x60, 0xc0, 0x08,
++ 0x00, 0x6a, 0xce, 0x5c,
++ 0xff, 0x4e, 0xc8, 0x18,
++ 0x02, 0x6a, 0xb8, 0x5b,
++ 0xff, 0x52, 0x20, 0x09,
++ 0x0d, 0x6a, 0x6a, 0x00,
++ 0x00, 0x52, 0x2e, 0x5c,
++ 0x03, 0xb0, 0x52, 0x31,
++ 0xff, 0xb0, 0x52, 0x09,
++ 0xff, 0xb1, 0x54, 0x09,
++ 0xff, 0xb2, 0x56, 0x09,
++ 0xff, 0xa3, 0x50, 0x09,
++ 0xff, 0x3e, 0x74, 0x09,
++ 0xff, 0x90, 0x7c, 0x08,
++ 0xff, 0x3e, 0x20, 0x09,
++ 0x00, 0x65, 0x4e, 0x58,
++ 0x00, 0x65, 0x0c, 0x40,
++ 0xf7, 0x1f, 0xca, 0x08,
++ 0x08, 0xa1, 0xc8, 0x08,
++ 0x00, 0x65, 0xca, 0x00,
++ 0xff, 0x65, 0x3e, 0x08,
++ 0xf0, 0xa1, 0xc8, 0x08,
++ 0x0f, 0x0f, 0x1e, 0x08,
++ 0x00, 0x0f, 0x1e, 0x00,
++ 0xf0, 0xa1, 0xc8, 0x08,
++ 0x0f, 0x05, 0x0a, 0x08,
++ 0x00, 0x05, 0x0a, 0x00,
++ 0xff, 0x6a, 0x0c, 0x08,
++ 0x5a, 0x6a, 0x00, 0x04,
++ 0x12, 0x65, 0x02, 0x00,
++ 0x31, 0x6a, 0xca, 0x00,
++ 0x80, 0x37, 0x6e, 0x68,
++ 0xff, 0x65, 0xca, 0x18,
++ 0xff, 0x37, 0xdc, 0x08,
++ 0xff, 0x6e, 0xc8, 0x08,
++ 0x00, 0x6c, 0x76, 0x78,
++ 0x20, 0x01, 0x02, 0x00,
++ 0x4c, 0x37, 0xc8, 0x28,
++ 0x08, 0x1f, 0x7e, 0x78,
++ 0x08, 0x37, 0x6e, 0x00,
++ 0x08, 0x64, 0xc8, 0x00,
++ 0x70, 0x64, 0xca, 0x18,
++ 0xff, 0x6c, 0x0a, 0x08,
++ 0x20, 0x64, 0xca, 0x18,
++ 0xff, 0x6c, 0x08, 0x0c,
++ 0x40, 0x0b, 0x96, 0x68,
++ 0x20, 0x6a, 0x16, 0x00,
++ 0xf0, 0x19, 0x6e, 0x08,
++ 0x08, 0x6a, 0x18, 0x00,
++ 0x08, 0x11, 0x22, 0x00,
++ 0x08, 0x6a, 0x66, 0x58,
++ 0x08, 0x6a, 0x68, 0x00,
++ 0x00, 0x65, 0xaa, 0x40,
++ 0x12, 0x6a, 0x00, 0x00,
++ 0x40, 0x6a, 0x16, 0x00,
++ 0xff, 0x3e, 0x20, 0x09,
++ 0xff, 0xba, 0x7c, 0x08,
++ 0xff, 0xa1, 0x6e, 0x08,
++ 0x08, 0x6a, 0x18, 0x00,
++ 0x08, 0x11, 0x22, 0x00,
++ 0x08, 0x6a, 0x66, 0x58,
++ 0x80, 0x6a, 0x68, 0x00,
++ 0x80, 0x36, 0x6c, 0x00,
++ 0x00, 0x65, 0x02, 0x5c,
++ 0xff, 0x3d, 0xc8, 0x08,
++ 0xbf, 0x64, 0xde, 0x78,
++ 0xbf, 0x64, 0x88, 0x79,
++ 0x80, 0x64, 0x10, 0x72,
++ 0xa0, 0x64, 0x40, 0x72,
++ 0xc0, 0x64, 0x38, 0x72,
++ 0xe0, 0x64, 0x80, 0x72,
++ 0x01, 0x6a, 0x22, 0x01,
++ 0x00, 0x65, 0xaa, 0x40,
++ 0xf7, 0x11, 0x22, 0x08,
++ 0x00, 0x65, 0xcc, 0x58,
++ 0xff, 0x06, 0xd4, 0x08,
++ 0xf7, 0x01, 0x02, 0x08,
++ 0x09, 0x0c, 0xc6, 0x78,
++ 0x08, 0x0c, 0x0c, 0x68,
++ 0x01, 0x6a, 0x22, 0x01,
++ 0xff, 0x6a, 0x26, 0x09,
++ 0x02, 0x6a, 0x08, 0x30,
++ 0xff, 0x6a, 0x08, 0x08,
++ 0xdf, 0x01, 0x02, 0x08,
++ 0x01, 0x6a, 0x7a, 0x00,
++ 0xff, 0x6a, 0x6c, 0x0c,
++ 0x04, 0x14, 0x10, 0x31,
++ 0x03, 0xa9, 0x18, 0x31,
++ 0x00, 0x65, 0xf0, 0x40,
++ 0xa8, 0x6a, 0x6a, 0x00,
++ 0x40, 0x3d, 0xe4, 0x68,
++ 0x04, 0x35, 0x6a, 0x00,
++ 0x00, 0x65, 0x72, 0x5b,
++ 0x80, 0x6a, 0xd4, 0x01,
++ 0x10, 0x36, 0xd8, 0x68,
++ 0x10, 0x36, 0x6c, 0x00,
++ 0x07, 0xac, 0x10, 0x31,
++ 0x05, 0xa3, 0x70, 0x30,
++ 0xff, 0x38, 0xf8, 0x68,
++ 0x80, 0x02, 0x04, 0x00,
++ 0x04, 0x35, 0x6a, 0x08,
++ 0x03, 0x69, 0x18, 0x31,
++ 0x22, 0x38, 0xc8, 0x28,
++ 0x01, 0x38, 0xfe, 0x60,
++ 0x02, 0x64, 0xc8, 0x00,
++ 0xff, 0x64, 0xf8, 0x09,
++ 0xff, 0x35, 0x26, 0x09,
++ 0x80, 0x02, 0x76, 0x69,
++ 0x10, 0x0c, 0x3a, 0x69,
++ 0x80, 0x94, 0x04, 0x79,
++ 0x01, 0x38, 0x30, 0x71,
++ 0x80, 0xea, 0x22, 0x61,
++ 0xef, 0x38, 0xc8, 0x18,
++ 0x80, 0x6a, 0xc8, 0x00,
++ 0x00, 0x65, 0x14, 0x49,
++ 0x33, 0x38, 0xc8, 0x28,
++ 0xff, 0x64, 0xd0, 0x09,
++ 0x04, 0x39, 0xc0, 0x31,
++ 0x09, 0x6a, 0xd6, 0x01,
++ 0x80, 0xeb, 0x1a, 0x79,
++ 0xf7, 0xeb, 0xd6, 0x09,
++ 0x08, 0xeb, 0x1e, 0x69,
++ 0x01, 0x6a, 0xd6, 0x01,
++ 0x10, 0x0c, 0x3a, 0x69,
++ 0xff, 0x38, 0x70, 0x18,
++ 0x08, 0xe9, 0x10, 0x31,
++ 0xff, 0x6a, 0xc8, 0x08,
++ 0x08, 0x39, 0x72, 0x18,
++ 0x00, 0x3a, 0x74, 0x20,
++ 0x00, 0x65, 0xf0, 0x40,
++ 0x10, 0x0c, 0x3a, 0x69,
++ 0x01, 0xfc, 0x30, 0x79,
++ 0xff, 0x6a, 0x70, 0x08,
++ 0x01, 0x0c, 0x36, 0x79,
++ 0x10, 0x0c, 0xf0, 0x78,
++ 0x00, 0x65, 0x5c, 0x59,
++ 0x01, 0xfc, 0x54, 0x69,
++ 0x40, 0x0d, 0x44, 0x69,
++ 0xb1, 0x6a, 0x22, 0x01,
++ 0x00, 0x65, 0x54, 0x41,
++ 0x2e, 0xfc, 0xa2, 0x28,
++ 0x3f, 0x38, 0xc8, 0x08,
++ 0x00, 0x51, 0x54, 0x71,
++ 0xff, 0x6a, 0xc8, 0x08,
++ 0xf8, 0x39, 0x72, 0x18,
++ 0xff, 0x3a, 0x74, 0x20,
++ 0x01, 0x38, 0x70, 0x18,
++ 0x00, 0x65, 0x46, 0x41,
++ 0x03, 0x08, 0x52, 0x31,
++ 0xff, 0x38, 0x50, 0x09,
++ 0x12, 0x01, 0x02, 0x00,
++ 0x00, 0x65, 0xaa, 0x40,
++ 0x04, 0x93, 0x70, 0x69,
++ 0xdf, 0x93, 0x26, 0x09,
++ 0x20, 0x93, 0x60, 0x69,
++ 0x02, 0x93, 0x26, 0x01,
++ 0x01, 0x94, 0x64, 0x79,
++ 0x01, 0x94, 0x64, 0x79,
++ 0x01, 0x94, 0x64, 0x79,
++ 0x01, 0x94, 0x64, 0x79,
++ 0x01, 0x94, 0x64, 0x79,
++ 0x10, 0x94, 0x6e, 0x69,
++ 0xd7, 0x93, 0x26, 0x09,
++ 0x28, 0x93, 0x72, 0x69,
++ 0xff, 0x6a, 0xd4, 0x0c,
++ 0x10, 0x0c, 0x76, 0x79,
++ 0x00, 0x65, 0x5c, 0x59,
++ 0x7f, 0x02, 0x04, 0x08,
++ 0xe1, 0x6a, 0x22, 0x01,
++ 0x00, 0x65, 0xaa, 0x40,
++ 0x03, 0xa9, 0x10, 0x30,
++ 0x08, 0x6a, 0xcc, 0x00,
++ 0xa9, 0x6a, 0x18, 0x5c,
++ 0x00, 0x65, 0xa6, 0x41,
++ 0x79, 0x6a, 0x6a, 0x00,
++ 0x40, 0x3d, 0x8e, 0x69,
++ 0x04, 0x35, 0x6a, 0x00,
++ 0x00, 0x65, 0x72, 0x5b,
++ 0x80, 0x6a, 0xd4, 0x01,
++ 0x10, 0x36, 0x80, 0x69,
++ 0x10, 0x36, 0x6c, 0x00,
++ 0x07, 0xac, 0x10, 0x31,
++ 0x03, 0x8c, 0x10, 0x30,
++ 0x05, 0xa3, 0x70, 0x30,
++ 0x88, 0x6a, 0xcc, 0x00,
++ 0xac, 0x6a, 0x10, 0x5c,
++ 0x00, 0x65, 0x0a, 0x5c,
++ 0x38, 0x6a, 0xcc, 0x00,
++ 0xa3, 0x6a, 0x14, 0x5c,
++ 0xff, 0x38, 0xb4, 0x69,
++ 0x80, 0x02, 0x04, 0x00,
++ 0xe7, 0x35, 0x6a, 0x08,
++ 0x03, 0x69, 0x10, 0x30,
++ 0xff, 0x6a, 0x10, 0x00,
++ 0xff, 0x6a, 0x12, 0x00,
++ 0xff, 0x6a, 0x14, 0x00,
++ 0x01, 0x38, 0xb8, 0x61,
++ 0xbf, 0x35, 0x6a, 0x08,
++ 0x00, 0x35, 0x52, 0x5b,
++ 0x80, 0x02, 0x0a, 0x6a,
++ 0xff, 0x65, 0xfa, 0x79,
++ 0x01, 0x38, 0xfa, 0x71,
++ 0xff, 0x38, 0x70, 0x18,
++ 0x80, 0xea, 0xda, 0x61,
++ 0xef, 0x38, 0xc8, 0x18,
++ 0x80, 0x6a, 0xc8, 0x00,
++ 0x00, 0x65, 0xcc, 0x49,
++ 0x33, 0x38, 0xc8, 0x28,
++ 0xff, 0x64, 0xd0, 0x09,
++ 0x04, 0x39, 0xc0, 0x31,
++ 0x09, 0x6a, 0xd6, 0x01,
++ 0x80, 0xeb, 0xd2, 0x79,
++ 0xf7, 0xeb, 0xd6, 0x09,
++ 0x08, 0xeb, 0xd6, 0x69,
++ 0x01, 0x6a, 0xd6, 0x01,
++ 0x08, 0xe9, 0x10, 0x31,
++ 0x03, 0x8c, 0x10, 0x30,
++ 0x88, 0x6a, 0xcc, 0x00,
++ 0x39, 0x6a, 0x16, 0x5c,
++ 0x08, 0x6a, 0x18, 0x01,
++ 0xff, 0x6a, 0x1a, 0x09,
++ 0xff, 0x6a, 0x1c, 0x09,
++ 0x0d, 0x93, 0x26, 0x01,
++ 0x00, 0x65, 0xc0, 0x5c,
++ 0x88, 0x6a, 0xb2, 0x5c,
++ 0x00, 0x65, 0x0a, 0x5c,
++ 0xff, 0x6a, 0xc8, 0x08,
++ 0x08, 0x39, 0x72, 0x18,
++ 0x00, 0x3a, 0x74, 0x20,
++ 0x01, 0x0c, 0xf6, 0x79,
++ 0x10, 0x0c, 0xa6, 0x79,
++ 0xff, 0x6a, 0x70, 0x08,
++ 0x03, 0x08, 0x52, 0x31,
++ 0xff, 0x38, 0x50, 0x09,
++ 0xff, 0x08, 0x52, 0x09,
++ 0xff, 0x09, 0x54, 0x09,
++ 0xff, 0x0a, 0x56, 0x09,
++ 0xff, 0x38, 0x50, 0x09,
++ 0x00, 0x65, 0xaa, 0x40,
++ 0x7f, 0x02, 0x04, 0x08,
++ 0xe1, 0x6a, 0x22, 0x01,
++ 0x00, 0x65, 0xaa, 0x40,
++ 0x00, 0x65, 0x72, 0x5b,
++ 0x05, 0xb4, 0x10, 0x31,
++ 0x02, 0x6a, 0x1a, 0x31,
++ 0x03, 0x8c, 0x10, 0x30,
++ 0x88, 0x6a, 0xcc, 0x00,
++ 0xb4, 0x6a, 0x14, 0x5c,
++ 0xff, 0x6a, 0x1a, 0x09,
++ 0xff, 0x6a, 0x1c, 0x09,
++ 0x00, 0x65, 0x0a, 0x5c,
++ 0x3d, 0x6a, 0x52, 0x5b,
++ 0xac, 0x6a, 0x26, 0x01,
++ 0x04, 0x0b, 0x26, 0x6a,
++ 0x04, 0x0b, 0x2c, 0x6a,
++ 0x10, 0x0c, 0x28, 0x7a,
++ 0x02, 0x03, 0x30, 0x7a,
++ 0x11, 0x0c, 0x2c, 0x7a,
++ 0xd7, 0x93, 0x26, 0x09,
++ 0x28, 0x93, 0x32, 0x6a,
++ 0x12, 0x01, 0x02, 0x00,
++ 0x00, 0x65, 0xaa, 0x40,
++ 0x00, 0x65, 0x72, 0x5b,
++ 0xff, 0x06, 0x44, 0x09,
++ 0x00, 0x65, 0xaa, 0x40,
++ 0x10, 0x3d, 0x06, 0x00,
++ 0xff, 0x34, 0xca, 0x08,
++ 0x80, 0x65, 0x64, 0x62,
++ 0x0f, 0xa1, 0xca, 0x08,
++ 0x07, 0xa1, 0xca, 0x08,
++ 0x40, 0xa0, 0xc8, 0x08,
++ 0x00, 0x65, 0xca, 0x00,
++ 0x80, 0x65, 0xca, 0x00,
++ 0x80, 0xa0, 0x54, 0x7a,
++ 0xff, 0x65, 0x0c, 0x08,
++ 0x00, 0x65, 0x66, 0x42,
++ 0x20, 0xa0, 0x6c, 0x7a,
++ 0xff, 0x65, 0x0c, 0x08,
++ 0x00, 0x65, 0x02, 0x5c,
++ 0xa0, 0x3d, 0x74, 0x62,
++ 0x23, 0xa0, 0x0c, 0x08,
++ 0x00, 0x65, 0x02, 0x5c,
++ 0xa0, 0x3d, 0x74, 0x62,
++ 0x00, 0xb9, 0x6c, 0x42,
++ 0xff, 0x65, 0x6c, 0x62,
++ 0xa1, 0x6a, 0x22, 0x01,
++ 0xff, 0x6a, 0xd4, 0x08,
++ 0x10, 0x51, 0x74, 0x72,
++ 0x40, 0x6a, 0x18, 0x00,
++ 0xff, 0x65, 0x0c, 0x08,
++ 0x00, 0x65, 0x02, 0x5c,
++ 0xa0, 0x3d, 0x3e, 0x72,
++ 0x40, 0x6a, 0x18, 0x00,
++ 0xff, 0x34, 0xa6, 0x08,
++ 0x80, 0x34, 0x7c, 0x62,
++ 0x7f, 0xa0, 0x40, 0x09,
++ 0x08, 0x6a, 0x68, 0x00,
++ 0x00, 0x65, 0xaa, 0x40,
++ 0x64, 0x6a, 0x48, 0x5b,
++ 0x80, 0x64, 0xf2, 0x6a,
++ 0x04, 0x64, 0xd4, 0x72,
++ 0x02, 0x64, 0xda, 0x72,
++ 0x00, 0x6a, 0x9c, 0x72,
++ 0x03, 0x64, 0xee, 0x72,
++ 0x01, 0x64, 0xd0, 0x72,
++ 0x07, 0x64, 0x30, 0x73,
++ 0x08, 0x64, 0x98, 0x72,
++ 0x23, 0x64, 0x34, 0x73,
++ 0x11, 0x6a, 0x22, 0x01,
++ 0x07, 0x6a, 0x3a, 0x5b,
++ 0xff, 0x06, 0xd4, 0x08,
++ 0x00, 0x65, 0xaa, 0x40,
++ 0xff, 0xa8, 0xa0, 0x6a,
++ 0xff, 0xa2, 0xb8, 0x7a,
++ 0x01, 0x6a, 0x6a, 0x00,
++ 0x00, 0xb9, 0x2e, 0x5c,
++ 0xff, 0xa2, 0xb8, 0x7a,
++ 0x71, 0x6a, 0x22, 0x01,
++ 0xff, 0x6a, 0xd4, 0x08,
++ 0x40, 0x51, 0xb8, 0x62,
++ 0x0d, 0x6a, 0x6a, 0x00,
++ 0x00, 0xb9, 0x2e, 0x5c,
++ 0xff, 0x3e, 0x74, 0x09,
++ 0xff, 0x90, 0x7c, 0x08,
++ 0x00, 0x65, 0x4e, 0x58,
++ 0x00, 0x65, 0xbe, 0x40,
++ 0x20, 0xa0, 0xc0, 0x6a,
++ 0xff, 0x37, 0xc8, 0x08,
++ 0x00, 0x6a, 0xd8, 0x5b,
++ 0xff, 0x6a, 0xee, 0x5b,
++ 0xff, 0xf8, 0xc8, 0x08,
++ 0xff, 0x4f, 0xc8, 0x08,
++ 0x01, 0x6a, 0xd8, 0x5b,
++ 0x00, 0xb9, 0xee, 0x5b,
++ 0x01, 0x4f, 0x9e, 0x18,
++ 0x02, 0x6a, 0x22, 0x01,
++ 0x00, 0x65, 0xc8, 0x5c,
++ 0x00, 0x65, 0xbe, 0x40,
++ 0x41, 0x6a, 0x22, 0x01,
++ 0x00, 0x65, 0xaa, 0x40,
++ 0x04, 0xa0, 0x40, 0x01,
++ 0x00, 0x65, 0xe0, 0x5c,
++ 0x00, 0x65, 0xbe, 0x40,
++ 0x10, 0x36, 0x98, 0x7a,
++ 0x05, 0x38, 0x46, 0x31,
++ 0x04, 0x14, 0x58, 0x31,
++ 0x03, 0xa9, 0x60, 0x31,
++ 0xa3, 0x6a, 0xcc, 0x00,
++ 0x38, 0x6a, 0x14, 0x5c,
++ 0xac, 0x6a, 0xcc, 0x00,
++ 0x14, 0x6a, 0x16, 0x5c,
++ 0xa9, 0x6a, 0x18, 0x5c,
++ 0x00, 0x65, 0x98, 0x42,
++ 0xef, 0x36, 0x6c, 0x08,
++ 0x00, 0x65, 0x98, 0x42,
++ 0x0f, 0x64, 0xc8, 0x08,
++ 0x07, 0x64, 0xc8, 0x08,
++ 0x00, 0x37, 0x6e, 0x00,
++ 0xff, 0x6a, 0xa4, 0x00,
++ 0x00, 0x65, 0xa8, 0x5b,
++ 0xff, 0x51, 0x04, 0x73,
++ 0x20, 0x36, 0x0e, 0x7b,
++ 0x00, 0x90, 0x96, 0x5b,
++ 0x00, 0x65, 0x10, 0x43,
++ 0xff, 0x06, 0xd4, 0x08,
++ 0x00, 0x65, 0x02, 0x5c,
++ 0xe0, 0x3d, 0x2a, 0x63,
++ 0x20, 0x12, 0x2a, 0x63,
++ 0x51, 0x6a, 0x3e, 0x5b,
++ 0x00, 0x65, 0x90, 0x5b,
++ 0xff, 0x37, 0xc8, 0x08,
++ 0x00, 0xa1, 0x22, 0x63,
++ 0x04, 0xa0, 0x22, 0x7b,
++ 0xfb, 0xa0, 0x40, 0x09,
++ 0x80, 0x36, 0x6c, 0x00,
++ 0x80, 0xa0, 0x98, 0x7a,
++ 0x7f, 0xa0, 0x40, 0x09,
++ 0xff, 0x6a, 0x3a, 0x5b,
++ 0x00, 0x65, 0x98, 0x42,
++ 0x04, 0xa0, 0x28, 0x7b,
++ 0x00, 0x65, 0xe0, 0x5c,
++ 0x00, 0x65, 0x2a, 0x43,
++ 0x00, 0x65, 0xc8, 0x5c,
++ 0x31, 0x6a, 0x22, 0x01,
++ 0x0c, 0x6a, 0x3a, 0x5b,
++ 0x00, 0x65, 0x98, 0x42,
++ 0x61, 0x6a, 0x22, 0x01,
++ 0x00, 0x65, 0x98, 0x42,
++ 0x51, 0x6a, 0x3e, 0x5b,
++ 0x51, 0x6a, 0x22, 0x01,
++ 0x00, 0x65, 0x98, 0x42,
++ 0x10, 0x3d, 0x06, 0x00,
++ 0xff, 0x65, 0x68, 0x0c,
++ 0xff, 0x06, 0xd4, 0x08,
++ 0x01, 0x0c, 0x40, 0x7b,
++ 0x04, 0x0c, 0x42, 0x6b,
++ 0xe0, 0x03, 0x7a, 0x08,
++ 0xe0, 0x3d, 0x4e, 0x63,
++ 0xff, 0x65, 0xcc, 0x08,
++ 0xff, 0x12, 0xda, 0x0c,
++ 0xff, 0x06, 0xd4, 0x0c,
++ 0xd1, 0x6a, 0x22, 0x01,
++ 0x00, 0x65, 0xaa, 0x40,
++ 0xff, 0x65, 0x26, 0x09,
++ 0x01, 0x0b, 0x62, 0x6b,
++ 0x10, 0x0c, 0x54, 0x7b,
++ 0x04, 0x0b, 0x5c, 0x6b,
++ 0xff, 0x6a, 0xca, 0x08,
++ 0x04, 0x93, 0x60, 0x6b,
++ 0x01, 0x94, 0x5e, 0x7b,
++ 0x10, 0x94, 0x60, 0x6b,
++ 0x80, 0x3d, 0x66, 0x73,
++ 0x0f, 0x04, 0x6a, 0x6b,
++ 0x02, 0x03, 0x6a, 0x7b,
++ 0x11, 0x0c, 0x66, 0x7b,
++ 0xc7, 0x93, 0x26, 0x09,
++ 0xff, 0x99, 0xd4, 0x08,
++ 0x38, 0x93, 0x6c, 0x6b,
++ 0xff, 0x6a, 0xd4, 0x0c,
++ 0x80, 0x36, 0x70, 0x6b,
++ 0x21, 0x6a, 0x22, 0x05,
++ 0xff, 0x65, 0x20, 0x09,
++ 0xff, 0x51, 0x7e, 0x63,
++ 0xff, 0x37, 0xc8, 0x08,
++ 0xa1, 0x6a, 0x8a, 0x43,
++ 0xff, 0x51, 0xc8, 0x08,
++ 0xb9, 0x6a, 0x8a, 0x43,
++ 0xff, 0x90, 0xa4, 0x08,
++ 0xff, 0xba, 0x8e, 0x73,
++ 0xff, 0xba, 0x20, 0x09,
++ 0xff, 0x65, 0xca, 0x18,
++ 0x00, 0x6c, 0x82, 0x63,
++ 0xff, 0x90, 0xca, 0x0c,
++ 0xff, 0x6a, 0xca, 0x04,
++ 0x20, 0x36, 0xa2, 0x7b,
++ 0x00, 0x90, 0x76, 0x5b,
++ 0xff, 0x65, 0xa2, 0x73,
++ 0xff, 0x52, 0xa0, 0x73,
++ 0xff, 0xba, 0xcc, 0x08,
++ 0xff, 0x52, 0x20, 0x09,
++ 0xff, 0x66, 0x74, 0x09,
++ 0xff, 0x65, 0x20, 0x0d,
++ 0xff, 0xba, 0x7e, 0x0c,
++ 0x00, 0x6a, 0xce, 0x5c,
++ 0x0d, 0x6a, 0x6a, 0x00,
++ 0x00, 0x51, 0x2e, 0x44,
++ 0xff, 0x3f, 0xfc, 0x73,
++ 0xff, 0x6a, 0xa2, 0x00,
++ 0x00, 0x3f, 0x76, 0x5b,
++ 0xff, 0x65, 0xfc, 0x73,
++ 0x20, 0x36, 0x6c, 0x00,
++ 0x20, 0xa0, 0xb6, 0x6b,
++ 0xff, 0xb9, 0xa2, 0x0c,
++ 0xff, 0x6a, 0xa2, 0x04,
++ 0xff, 0x65, 0xa4, 0x08,
++ 0xe0, 0x6a, 0xcc, 0x00,
++ 0x45, 0x6a, 0x22, 0x5c,
++ 0x01, 0x6a, 0xd0, 0x01,
++ 0x09, 0x6a, 0xd6, 0x01,
++ 0x80, 0xeb, 0xc2, 0x7b,
++ 0x01, 0x6a, 0xd6, 0x01,
++ 0x01, 0xe9, 0xa4, 0x34,
++ 0x88, 0x6a, 0xcc, 0x00,
++ 0x45, 0x6a, 0x22, 0x5c,
++ 0x01, 0x6a, 0x18, 0x01,
++ 0xff, 0x6a, 0x1a, 0x09,
++ 0xff, 0x6a, 0x1c, 0x09,
++ 0x0d, 0x6a, 0x26, 0x01,
++ 0x00, 0x65, 0xc0, 0x5c,
++ 0xff, 0x99, 0xa4, 0x0c,
++ 0xff, 0x65, 0xa4, 0x08,
++ 0xe0, 0x6a, 0xcc, 0x00,
++ 0x45, 0x6a, 0x22, 0x5c,
++ 0x01, 0x6a, 0xd0, 0x01,
++ 0x01, 0x6a, 0xdc, 0x05,
++ 0x88, 0x6a, 0xcc, 0x00,
++ 0x45, 0x6a, 0x22, 0x5c,
++ 0x01, 0x6a, 0x18, 0x01,
++ 0xff, 0x6a, 0x1a, 0x09,
++ 0xff, 0x6a, 0x1c, 0x09,
++ 0x01, 0x6a, 0x26, 0x05,
++ 0x01, 0x65, 0xd8, 0x31,
++ 0x09, 0xee, 0xdc, 0x01,
++ 0x80, 0xee, 0xf2, 0x7b,
++ 0xff, 0x6a, 0xdc, 0x0d,
++ 0xff, 0x65, 0x32, 0x09,
++ 0x0a, 0x93, 0x26, 0x01,
++ 0x00, 0x65, 0xc0, 0x44,
++ 0xff, 0x37, 0xc8, 0x08,
++ 0x00, 0x6a, 0xb8, 0x5b,
++ 0xff, 0x52, 0xa2, 0x0c,
++ 0x01, 0x0c, 0x02, 0x7c,
++ 0x04, 0x0c, 0x02, 0x6c,
++ 0xe0, 0x03, 0x06, 0x08,
++ 0xe0, 0x03, 0x7a, 0x0c,
++ 0xff, 0x8c, 0x10, 0x08,
++ 0xff, 0x8d, 0x12, 0x08,
++ 0xff, 0x8e, 0x14, 0x0c,
++ 0xff, 0x6c, 0xda, 0x08,
++ 0xff, 0x6c, 0xda, 0x08,
++ 0xff, 0x6c, 0xda, 0x08,
++ 0xff, 0x6c, 0xda, 0x08,
++ 0xff, 0x6c, 0xda, 0x08,
++ 0xff, 0x6c, 0xda, 0x08,
++ 0xff, 0x6c, 0xda, 0x0c,
++ 0x3d, 0x64, 0xa4, 0x28,
++ 0x55, 0x64, 0xc8, 0x28,
++ 0x00, 0x6c, 0xda, 0x18,
++ 0xff, 0x52, 0xc8, 0x08,
++ 0x00, 0x6c, 0xda, 0x20,
++ 0xff, 0x6a, 0xc8, 0x08,
++ 0x00, 0x6c, 0xda, 0x20,
++ 0x00, 0x6c, 0xda, 0x24,
++ 0xff, 0x65, 0xc8, 0x08,
++ 0xe0, 0x6a, 0xcc, 0x00,
++ 0x41, 0x6a, 0x1e, 0x5c,
++ 0xff, 0x90, 0xe2, 0x09,
++ 0x20, 0x6a, 0xd0, 0x01,
++ 0x04, 0x35, 0x40, 0x7c,
++ 0x1d, 0x6a, 0xdc, 0x01,
++ 0xdc, 0xee, 0x3c, 0x64,
++ 0x00, 0x65, 0x56, 0x44,
++ 0x01, 0x6a, 0xdc, 0x01,
++ 0x20, 0xa0, 0xd8, 0x31,
++ 0x09, 0xee, 0xdc, 0x01,
++ 0x80, 0xee, 0x46, 0x7c,
++ 0x11, 0x6a, 0xdc, 0x01,
++ 0x50, 0xee, 0x4a, 0x64,
++ 0x20, 0x6a, 0xd0, 0x01,
++ 0x09, 0x6a, 0xdc, 0x01,
++ 0x88, 0xee, 0x50, 0x64,
++ 0x19, 0x6a, 0xdc, 0x01,
++ 0xd8, 0xee, 0x54, 0x64,
++ 0xff, 0x6a, 0xdc, 0x09,
++ 0x18, 0xee, 0x58, 0x6c,
++ 0xff, 0x6a, 0xd4, 0x0c,
++ 0x88, 0x6a, 0xcc, 0x00,
++ 0x41, 0x6a, 0x1e, 0x5c,
++ 0x20, 0x6a, 0x18, 0x01,
++ 0xff, 0x6a, 0x1a, 0x09,
++ 0xff, 0x6a, 0x1c, 0x09,
++ 0xff, 0x35, 0x26, 0x09,
++ 0x04, 0x35, 0x84, 0x6c,
++ 0xa0, 0x6a, 0xca, 0x00,
++ 0x20, 0x65, 0xc8, 0x18,
++ 0xff, 0x6c, 0x32, 0x09,
++ 0xff, 0x6c, 0x32, 0x09,
++ 0xff, 0x6c, 0x32, 0x09,
++ 0xff, 0x6c, 0x32, 0x09,
++ 0xff, 0x6c, 0x32, 0x09,
++ 0xff, 0x6c, 0x32, 0x09,
++ 0xff, 0x6c, 0x32, 0x09,
++ 0xff, 0x6c, 0x32, 0x09,
++ 0x00, 0x65, 0x6e, 0x64,
++ 0x0a, 0x93, 0x26, 0x01,
++ 0x00, 0x65, 0xc0, 0x44,
++ 0xa0, 0x6a, 0xcc, 0x00,
++ 0xe8, 0x6a, 0xc8, 0x00,
++ 0x01, 0x94, 0x88, 0x6c,
++ 0x10, 0x94, 0x8a, 0x6c,
++ 0x08, 0x94, 0x9c, 0x6c,
++ 0x08, 0x94, 0x9c, 0x6c,
++ 0x08, 0x94, 0x9c, 0x6c,
++ 0x00, 0x65, 0xb0, 0x5c,
++ 0x08, 0x64, 0xc8, 0x18,
++ 0x00, 0x8c, 0xca, 0x18,
++ 0x00, 0x65, 0x92, 0x4c,
++ 0x00, 0x65, 0x88, 0x44,
++ 0xf7, 0x93, 0x26, 0x09,
++ 0x08, 0x93, 0x9e, 0x6c,
++ 0x00, 0x65, 0xb0, 0x5c,
++ 0x08, 0x64, 0xc8, 0x18,
++ 0x08, 0x64, 0xa0, 0x64,
++ 0xff, 0x6a, 0xd4, 0x0c,
++ 0x00, 0x65, 0xc0, 0x5c,
++ 0x00, 0x65, 0xb0, 0x5c,
++ 0x00, 0x65, 0xb0, 0x5c,
++ 0x00, 0x65, 0xb0, 0x5c,
++ 0xff, 0x99, 0xda, 0x08,
++ 0xff, 0x99, 0xda, 0x08,
++ 0xff, 0x99, 0xda, 0x08,
++ 0xff, 0x99, 0xda, 0x08,
++ 0xff, 0x99, 0xda, 0x08,
++ 0xff, 0x99, 0xda, 0x08,
++ 0xff, 0x99, 0xda, 0x08,
++ 0xff, 0x99, 0xda, 0x0c,
++ 0x08, 0x94, 0xc0, 0x7c,
++ 0xf7, 0x93, 0x26, 0x09,
++ 0x08, 0x93, 0xc4, 0x6c,
++ 0xff, 0x6a, 0xd4, 0x0c,
++ 0xff, 0x40, 0x74, 0x09,
++ 0xff, 0x90, 0x80, 0x08,
++ 0xff, 0x6a, 0x72, 0x05,
++ 0xff, 0x40, 0xdc, 0x64,
++ 0xff, 0x3f, 0xd4, 0x64,
++ 0xff, 0x6a, 0xca, 0x04,
++ 0xff, 0x3f, 0x20, 0x09,
++ 0x01, 0x6a, 0x6a, 0x00,
++ 0x00, 0xb9, 0x2e, 0x5c,
++ 0xff, 0xba, 0x7e, 0x0c,
++ 0xff, 0x40, 0x20, 0x09,
++ 0xff, 0xba, 0x80, 0x0c,
++ 0xff, 0x3f, 0x74, 0x09,
++ 0xff, 0x90, 0x7e, 0x0c,
++};
++
++static int aic7xxx_patch14_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch14_func(struct aic7xxx_host *p)
++{
++ return ((p->bugs & AHC_BUG_SCBCHAN_UPLOAD) != 0);
++}
++
++static int aic7xxx_patch13_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch13_func(struct aic7xxx_host *p)
++{
++ return ((p->features & AHC_CMD_CHAN) == 0);
++}
++
++static int aic7xxx_patch12_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch12_func(struct aic7xxx_host *p)
++{
++ return ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0);
++}
++
++static int aic7xxx_patch11_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch11_func(struct aic7xxx_host *p)
++{
++ return ((p->features & AHC_WIDE) != 0);
++}
++
++static int aic7xxx_patch10_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch10_func(struct aic7xxx_host *p)
++{
++ return ((p->features & AHC_ULTRA2) == 0);
++}
++
++static int aic7xxx_patch9_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch9_func(struct aic7xxx_host *p)
++{
++ return ((p->bugs & AHC_BUG_AUTOFLUSH) != 0);
++}
++
++static int aic7xxx_patch8_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch8_func(struct aic7xxx_host *p)
++{
++ return ((p->features & AHC_ULTRA) != 0);
++}
++
++static int aic7xxx_patch7_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch7_func(struct aic7xxx_host *p)
++{
++ return ((p->features & AHC_ULTRA2) != 0);
++}
++
++static int aic7xxx_patch6_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch6_func(struct aic7xxx_host *p)
++{
++ return ((p->flags & AHC_PAGESCBS) == 0);
++}
++
++static int aic7xxx_patch5_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch5_func(struct aic7xxx_host *p)
++{
++ return ((p->flags & AHC_PAGESCBS) != 0);
++}
++
++static int aic7xxx_patch4_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch4_func(struct aic7xxx_host *p)
++{
++ return ((p->features & AHC_QUEUE_REGS) != 0);
++}
++
++static int aic7xxx_patch3_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch3_func(struct aic7xxx_host *p)
++{
++ return ((p->features & AHC_TWIN) != 0);
++}
++
++static int aic7xxx_patch2_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch2_func(struct aic7xxx_host *p)
++{
++ return ((p->features & AHC_QUEUE_REGS) == 0);
++}
++
++static int aic7xxx_patch1_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch1_func(struct aic7xxx_host *p)
++{
++ return ((p->features & AHC_CMD_CHAN) != 0);
++}
++
++static int aic7xxx_patch0_func(struct aic7xxx_host *p);
++
++static int
++aic7xxx_patch0_func(struct aic7xxx_host *p)
++{
++ return (0);
++}
++
++struct sequencer_patch {
++ int (*patch_func)(struct aic7xxx_host *);
++ unsigned int begin :10,
++ skip_instr :10,
++ skip_patch :12;
++} sequencer_patches[] = {
++ { aic7xxx_patch1_func, 3, 2, 1 },
++ { aic7xxx_patch2_func, 7, 1, 1 },
++ { aic7xxx_patch2_func, 8, 1, 1 },
++ { aic7xxx_patch3_func, 11, 4, 1 },
++ { aic7xxx_patch4_func, 16, 3, 2 },
++ { aic7xxx_patch0_func, 19, 4, 1 },
++ { aic7xxx_patch5_func, 23, 1, 1 },
++ { aic7xxx_patch6_func, 26, 1, 1 },
++ { aic7xxx_patch1_func, 29, 1, 2 },
++ { aic7xxx_patch0_func, 30, 3, 1 },
++ { aic7xxx_patch3_func, 39, 4, 1 },
++ { aic7xxx_patch7_func, 43, 3, 2 },
++ { aic7xxx_patch0_func, 46, 3, 1 },
++ { aic7xxx_patch8_func, 52, 7, 1 },
++ { aic7xxx_patch3_func, 60, 3, 1 },
++ { aic7xxx_patch7_func, 63, 2, 1 },
++ { aic7xxx_patch7_func, 87, 1, 2 },
++ { aic7xxx_patch0_func, 88, 1, 1 },
++ { aic7xxx_patch7_func, 103, 1, 2 },
++ { aic7xxx_patch0_func, 104, 2, 1 },
++ { aic7xxx_patch7_func, 108, 84, 15 },
++ { aic7xxx_patch9_func, 177, 1, 1 },
++ { aic7xxx_patch9_func, 178, 4, 1 },
++ { aic7xxx_patch0_func, 192, 72, 12 },
++ { aic7xxx_patch1_func, 192, 1, 2 },
++ { aic7xxx_patch0_func, 193, 2, 1 },
++ { aic7xxx_patch1_func, 200, 1, 1 },
++ { aic7xxx_patch1_func, 203, 3, 2 },
++ { aic7xxx_patch0_func, 206, 5, 1 },
++ { aic7xxx_patch1_func, 214, 1, 2 },
++ { aic7xxx_patch0_func, 215, 3, 1 },
++ { aic7xxx_patch1_func, 225, 14, 2 },
++ { aic7xxx_patch0_func, 239, 9, 1 },
++ { aic7xxx_patch1_func, 254, 2, 2 },
++ { aic7xxx_patch0_func, 256, 4, 1 },
++ { aic7xxx_patch1_func, 265, 3, 3 },
++ { aic7xxx_patch10_func, 267, 1, 1 },
++ { aic7xxx_patch0_func, 268, 5, 1 },
++ { aic7xxx_patch10_func, 273, 1, 2 },
++ { aic7xxx_patch0_func, 274, 9, 1 },
++ { aic7xxx_patch11_func, 290, 1, 2 },
++ { aic7xxx_patch0_func, 291, 1, 1 },
++ { aic7xxx_patch4_func, 352, 1, 2 },
++ { aic7xxx_patch0_func, 353, 1, 1 },
++ { aic7xxx_patch2_func, 356, 1, 1 },
++ { aic7xxx_patch1_func, 366, 3, 2 },
++ { aic7xxx_patch0_func, 369, 5, 1 },
++ { aic7xxx_patch11_func, 377, 1, 2 },
++ { aic7xxx_patch0_func, 378, 1, 1 },
++ { aic7xxx_patch5_func, 383, 1, 1 },
++ { aic7xxx_patch10_func, 425, 15, 2 },
++ { aic7xxx_patch12_func, 438, 1, 1 },
++ { aic7xxx_patch1_func, 477, 7, 2 },
++ { aic7xxx_patch0_func, 484, 8, 1 },
++ { aic7xxx_patch1_func, 493, 4, 2 },
++ { aic7xxx_patch0_func, 497, 6, 1 },
++ { aic7xxx_patch1_func, 503, 4, 2 },
++ { aic7xxx_patch0_func, 507, 3, 1 },
++ { aic7xxx_patch13_func, 517, 10, 1 },
++ { aic7xxx_patch1_func, 536, 22, 8 },
++ { aic7xxx_patch10_func, 544, 4, 4 },
++ { aic7xxx_patch0_func, 548, 7, 3 },
++ { aic7xxx_patch14_func, 548, 5, 2 },
++ { aic7xxx_patch0_func, 553, 2, 1 },
++ { aic7xxx_patch0_func, 558, 50, 3 },
++ { aic7xxx_patch12_func, 579, 17, 2 },
++ { aic7xxx_patch0_func, 596, 4, 1 },
++ { aic7xxx_patch13_func, 608, 4, 1 },
++ { aic7xxx_patch5_func, 612, 2, 1 },
++ { aic7xxx_patch5_func, 615, 9, 1 },
++
++};
+diff -U 3 -rN linux-2.2.17/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
+--- linux-2.2.17/drivers/scsi/aic7xxx.c Mon Sep 4 13:39:21 2000
++++ linux/drivers/scsi/aic7xxx.c Tue Feb 6 03:49:37 2001
+@@ -246,11 +246,11 @@
+ #include "sd.h"
+ #include "scsi.h"
+ #include "hosts.h"
+-#include "aic7xxx.h"
++#include "aic7xxx/aic7xxx.h"
+
+ #include "aic7xxx/sequencer.h"
+ #include "aic7xxx/scsi_message.h"
+-#include "aic7xxx_reg.h"
++#include "aic7xxx/aic7xxx_reg.h"
+ #include <scsi/scsicam.h>
+
+ #include <linux/stat.h>
+@@ -270,7 +270,7 @@
+ 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+ };
+
+-#define AIC7XXX_C_VERSION "5.1.31"
++#define AIC7XXX_C_VERSION "5.1.32"
+
+ #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0]))
+ #define MIN(a,b) (((a) < (b)) ? (a) : (b))
+@@ -790,6 +790,7 @@
+
+ typedef enum {
+ SCB_FREE = 0x0000,
++ SCB_DTR_SCB = 0x0001,
+ SCB_WAITINGQ = 0x0002,
+ SCB_ACTIVE = 0x0004,
+ SCB_SENSE = 0x0008,
+@@ -896,6 +897,17 @@
+ AHC_AIC7899_FE = AHC_AIC7890_FE|AHC_ULTRA3,
+ } ahc_feature;
+
++typedef enum {
++ AHC_BUG_NONE = 0x0000,
++ AHC_BUG_TMODE_WIDEODD = 0x0001,
++ AHC_BUG_AUTOFLUSH = 0x0002,
++ AHC_BUG_CACHETHEN = 0x0004,
++ AHC_BUG_CACHETHEN_DIS = 0x0008,
++ AHC_BUG_PCI_2_1_RETRY = 0x0010,
++ AHC_BUG_PCI_MWI = 0x0020,
++ AHC_BUG_SCBCHAN_UPLOAD = 0x0040,
++} ahc_bugs;
++
+ struct aic7xxx_scb {
+ struct aic7xxx_hwscb *hscb; /* corresponding hardware scb */
+ Scsi_Cmnd *cmd; /* Scsi_Cmnd for this scb */
+@@ -1004,7 +1016,6 @@
+ unsigned long isr_count; /* Interrupt count */
+ unsigned long spurious_int;
+ scb_data_type *scb_data;
+- volatile unsigned short needdv;
+ volatile unsigned short needppr;
+ volatile unsigned short needsdtr;
+ volatile unsigned short needwdtr;
+@@ -1032,10 +1043,9 @@
+ #define BUS_DEVICE_RESET_PENDING 0x02
+ #define DEVICE_RESET_DELAY 0x04
+ #define DEVICE_PRINT_DTR 0x08
+-#define DEVICE_PARITY_ERROR 0x10
+-#define DEVICE_WAS_BUSY 0x20
+-#define DEVICE_SCSI_3 0x40
+-#define DEVICE_SCANNED 0x80
++#define DEVICE_WAS_BUSY 0x10
++#define DEVICE_SCSI_3 0x20
++#define DEVICE_DTR_SCANNED 0x40
+ volatile unsigned char dev_flags[MAX_TARGETS];
+ volatile unsigned char dev_active_cmds[MAX_TARGETS];
+ volatile unsigned char dev_temp_queue_depth[MAX_TARGETS];
+@@ -1051,10 +1061,6 @@
+ #endif
+
+
+- Scsi_Cmnd *dev_dtr_cmnd[MAX_TARGETS];
+-
+- unsigned int dev_checksum[MAX_TARGETS];
+-
+ unsigned char dev_last_queue_full[MAX_TARGETS];
+ unsigned char dev_last_queue_full_count[MAX_TARGETS];
+ unsigned char dev_max_queue_depth[MAX_TARGETS];
+@@ -1111,6 +1117,7 @@
+ int host_no; /* SCSI host number */
+ unsigned long mbase; /* I/O memory address */
+ ahc_chip chip; /* chip type */
++ ahc_bugs bugs; /* hardware bugs this chip has */
+
+ /*
+ * Statistics Kept:
+@@ -1712,7 +1719,7 @@
+ * prototype, our code has to be ordered that way, it's a left-over from
+ * the original driver days.....I should fix it some time DL).
+ */
+-#include "aic7xxx_seq.c"
++#include "aic7xxx/aic7xxx_seq.c"
+
+ /*+F*************************************************************************
+ * Function:
+@@ -2876,138 +2883,98 @@
+ {
+ p->flags &= ~AHC_ABORT_PENDING;
+ }
+- if (scb->flags & SCB_RESET)
++ if (scb->flags & (SCB_RESET|SCB_ABORT))
+ {
+- cmd->result = (DID_RESET << 16) | (cmd->result & 0xffff);
++ cmd->result |= (DID_RESET << 16);
+ }
+- else if (scb->flags & SCB_ABORT)
+- {
+- cmd->result = (DID_RESET << 16) | (cmd->result & 0xffff);
+- }
+- else if (!(p->dev_flags[tindex] & DEVICE_SCANNED))
++
++ if (!(p->dev_flags[tindex] & DEVICE_PRESENT))
+ {
+ if ( (cmd->cmnd[0] == INQUIRY) && (cmd->result == DID_OK) )
+ {
+- char *buffer;
+-
++
+ p->dev_flags[tindex] |= DEVICE_PRESENT;
+- if(cmd->use_sg)
+- {
+- struct scatterlist *sg;
+-
+- sg = (struct scatterlist *)cmd->request_buffer;
+- buffer = (char *)sg[0].address;
+- }
+- else
+- {
+- buffer = (char *)cmd->request_buffer;
+- }
+ #define WIDE_INQUIRY_BITS 0x60
+ #define SYNC_INQUIRY_BITS 0x10
+ #define SCSI_VERSION_BITS 0x07
+ #define SCSI_DT_BIT 0x04
+- if ( (buffer[7] & WIDE_INQUIRY_BITS) &&
+- (p->features & AHC_WIDE) )
+- {
+- p->needwdtr |= (1<<tindex);
+- p->needwdtr_copy |= (1<<tindex);
+- p->transinfo[tindex].goal_width = p->transinfo[tindex].user_width;
+- }
+- else
+- {
+- p->needwdtr &= ~(1<<tindex);
+- p->needwdtr_copy &= ~(1<<tindex);
+- pause_sequencer(p);
+- aic7xxx_set_width(p, cmd->target, cmd->channel, cmd->lun,
+- MSG_EXT_WDTR_BUS_8_BIT, (AHC_TRANS_ACTIVE |
+- AHC_TRANS_GOAL |
+- AHC_TRANS_CUR) );
+- unpause_sequencer(p, FALSE);
+- }
+- if ( (buffer[7] & SYNC_INQUIRY_BITS) &&
+- p->transinfo[tindex].user_offset )
+- {
+- p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period;
+- p->transinfo[tindex].goal_options = p->transinfo[tindex].user_options;
+- if (p->features & AHC_ULTRA2)
+- p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+- else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
+- p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
++ if(!(p->dev_flags[tindex] & DEVICE_DTR_SCANNED)) {
++ char *buffer;
++
++ if(cmd->use_sg)
++ {
++ struct scatterlist *sg;
++
++ sg = (struct scatterlist *)cmd->request_buffer;
++ buffer = (char *)sg[0].address;
++ }
++ else
++ {
++ buffer = (char *)cmd->request_buffer;
++ }
++
++
++ if ( (buffer[7] & WIDE_INQUIRY_BITS) &&
++ (p->features & AHC_WIDE) )
++ {
++ p->needwdtr |= (1<<tindex);
++ p->needwdtr_copy |= (1<<tindex);
++ p->transinfo[tindex].goal_width = p->transinfo[tindex].user_width;
++ }
+ else
+- p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+- if ( (((buffer[2] & SCSI_VERSION_BITS) == 3) ||
+- (buffer[56] & SCSI_DT_BIT) ||
+- (p->dev_flags[tindex] & DEVICE_SCSI_3) ) &&
+- (p->transinfo[tindex].user_period <= 9) &&
+- (p->transinfo[tindex].user_options) )
+ {
+- p->needppr |= (1<<tindex);
+- p->needppr_copy |= (1<<tindex);
+- p->needsdtr &= ~(1<<tindex);
+- p->needsdtr_copy &= ~(1<<tindex);
+ p->needwdtr &= ~(1<<tindex);
+ p->needwdtr_copy &= ~(1<<tindex);
+- p->dev_flags[tindex] |= DEVICE_SCSI_3;
++ pause_sequencer(p);
++ aic7xxx_set_width(p, cmd->target, cmd->channel, cmd->lun,
++ MSG_EXT_WDTR_BUS_8_BIT, (AHC_TRANS_ACTIVE |
++ AHC_TRANS_GOAL |
++ AHC_TRANS_CUR) );
++ unpause_sequencer(p, FALSE);
+ }
+- else
++ if ( (buffer[7] & SYNC_INQUIRY_BITS) &&
++ p->transinfo[tindex].user_offset )
+ {
+- p->needsdtr |= (1<<tindex);
+- p->needsdtr_copy |= (1<<tindex);
+- p->transinfo[tindex].goal_period =
+- MAX(10, p->transinfo[tindex].goal_period);
+- p->transinfo[tindex].goal_options = 0;
++ p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period;
++ p->transinfo[tindex].goal_options = p->transinfo[tindex].user_options;
++ if (p->features & AHC_ULTRA2)
++ p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
++ else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
++ p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
++ else
++ p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
++ if ( (((buffer[2] & SCSI_VERSION_BITS) >= 3) ||
++ (buffer[56] & SCSI_DT_BIT) ||
++ (p->dev_flags[tindex] & DEVICE_SCSI_3) ) &&
++ (p->transinfo[tindex].user_period <= 9) &&
++ (p->transinfo[tindex].user_options) )
++ {
++ p->needppr |= (1<<tindex);
++ p->needppr_copy |= (1<<tindex);
++ p->needsdtr &= ~(1<<tindex);
++ p->needsdtr_copy &= ~(1<<tindex);
++ p->needwdtr &= ~(1<<tindex);
++ p->needwdtr_copy &= ~(1<<tindex);
++ p->dev_flags[tindex] |= DEVICE_SCSI_3;
++ }
++ else
++ {
++ p->needsdtr |= (1<<tindex);
++ p->needsdtr_copy |= (1<<tindex);
++ p->transinfo[tindex].goal_period =
++ MAX(10, p->transinfo[tindex].goal_period);
++ p->transinfo[tindex].goal_options = 0;
++ }
+ }
+- }
+- else
+- {
+- p->needsdtr &= ~(1<<tindex);
+- p->needsdtr_copy &= ~(1<<tindex);
+- p->transinfo[tindex].goal_period = 255;
+- p->transinfo[tindex].goal_offset = 0;
+- p->transinfo[tindex].goal_options = 0;
+- }
+- /*
+- * This is needed to work around a sequencer bug for now. Regardless
+- * of the controller in use, if we have a Quantum drive, we need to
+- * limit the speed to 80MByte/sec. As soon as I get a fixed version
+- * of the sequencer, this code will get yanked.
+- */
+- if(!strncmp(buffer + 8, "QUANTUM", 7) &&
+- p->transinfo[tindex].goal_options )
+- {
+- p->transinfo[tindex].goal_period =
+- MAX(p->transinfo[tindex].goal_period, 10);
+- p->transinfo[tindex].goal_options = 0;
+- p->needppr &= ~(1<<tindex);
+- p->needppr_copy &= ~(1<<tindex);
+- p->needsdtr |= (1<<tindex);
+- p->needsdtr_copy |= (1<<tindex);
+- p->needwdtr |= (1<<tindex);
+- p->needwdtr_copy |= (1<<tindex);
+- }
+- /*
+- * Get the INQUIRY checksum. We use this on Ultra 160/m
+- * and older devices both. It allows us to drop speed on any bus type
+- * while at the same time giving us the needed domain validation for
+- * Ultra 160/m
+- *
+- * Note: We only get the checksum and set the SCANNED bit if this is
+- * one of our dtr commands. If we don't do this, then we end up
+- * getting bad checksum results on the mid-level SCSI code's INQUIRY
+- * commands.
+- */
+- if(p->dev_dtr_cmnd[tindex] == cmd) {
+- unsigned int checksum = 0;
+- int *ibuffer;
+- int i=0;
+-
+- ibuffer = (int *)buffer;
+- for( i = 0; i < (cmd->request_bufflen >> 2); i++)
++ else
+ {
+- checksum += ibuffer[i];
++ p->needsdtr &= ~(1<<tindex);
++ p->needsdtr_copy &= ~(1<<tindex);
++ p->transinfo[tindex].goal_period = 255;
++ p->transinfo[tindex].goal_offset = 0;
++ p->transinfo[tindex].goal_options = 0;
+ }
+- p->dev_checksum[tindex] = checksum;
+- p->dev_flags[tindex] |= DEVICE_SCANNED;
++ p->dev_flags[tindex] |= DEVICE_DTR_SCANNED;
+ p->dev_flags[tindex] |= DEVICE_PRINT_DTR;
+ }
+ #undef WIDE_INQUIRY_BITS
+@@ -3016,7 +2983,8 @@
+ #undef SCSI_DT_BIT
+ }
+ }
+- else if ((scb->flags & SCB_MSGOUT_BITS) != 0)
++
++ if ((scb->flags & SCB_MSGOUT_BITS) != 0)
+ {
+ unsigned short mask;
+ int message_error = FALSE;
+@@ -3036,7 +3004,6 @@
+
+ if (scb->flags & SCB_MSGOUT_WDTR)
+ {
+- p->dtr_pending &= ~mask;
+ if (message_error)
+ {
+ if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
+@@ -3055,7 +3022,6 @@
+ }
+ if (scb->flags & SCB_MSGOUT_SDTR)
+ {
+- p->dtr_pending &= ~mask;
+ if (message_error)
+ {
+ if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
+@@ -3075,7 +3041,6 @@
+ }
+ if (scb->flags & SCB_MSGOUT_PPR)
+ {
+- p->dtr_pending &= ~mask;
+ if(message_error)
+ {
+ if ( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
+@@ -3100,6 +3065,7 @@
+ }
+ }
+ }
++
+ queue_depth = p->dev_temp_queue_depth[tindex];
+ if (queue_depth >= p->dev_active_cmds[tindex])
+ {
+@@ -3133,9 +3099,18 @@
+ }
+ }
+ }
+- if ( !(scb->tag_action) && (p->tagenable & (1<<tindex)) )
++ if (!(scb->tag_action))
++ {
++ aic7xxx_index_busy_target(p, scb->hscb->target_channel_lun,
++ /* unbusy */ TRUE);
++ if (p->tagenable & (1<<tindex))
++ {
++ p->dev_temp_queue_depth[tindex] = p->dev_max_queue_depth[tindex];
++ }
++ }
++ if(scb->flags & SCB_DTR_SCB)
+ {
+- p->dev_temp_queue_depth[tindex] = p->dev_max_queue_depth[tindex];
++ p->dtr_pending &= ~(1 << tindex);
+ }
+ p->dev_active_cmds[tindex]--;
+ p->activescbs--;
+@@ -3244,6 +3219,14 @@
+ printk(INFO_LEAD "Aborting scb %d\n",
+ p->host_no, CTL_OF_SCB(scb), scb->hscb->tag);
+ found++;
++ /*
++ * Clear any residual information since the normal aic7xxx_done() path
++ * doesn't touch the residuals.
++ */
++ scb->hscb->residual_SG_segment_count = 0;
++ scb->hscb->residual_data_count[0] = 0;
++ scb->hscb->residual_data_count[1] = 0;
++ scb->hscb->residual_data_count[2] = 0;
+ aic7xxx_done(p, scb);
+ }
+ }
+@@ -3456,8 +3439,22 @@
+ active_scb = aic_inb(p, SCBPTR);
+
+ if (aic7xxx_verbose & (VERBOSE_RESET_PROCESS | VERBOSE_ABORT_PROCESS))
++ {
+ printk(INFO_LEAD "Reset device, active_scb %d\n",
+ p->host_no, channel, target, lun, active_scb);
++ printk(INFO_LEAD "Current scb_tag %d, SEQADDR 0x%x, LASTPHASE "
++ "0x%x\n",
++ p->host_no, channel, target, lun, aic_inb(p, SCB_TAG),
++ aic_inb(p, SEQADDR0) | (aic_inb(p, SEQADDR1) << 8),
++ aic_inb(p, LASTPHASE));
++ printk(INFO_LEAD "SG_CACHEPTR 0x%x, SG_COUNT %d, SCSISIGI 0x%x\n",
++ p->host_no, channel, target, lun,
++ (p->features & AHC_ULTRA2) ? aic_inb(p, SG_CACHEPTR) : 0,
++ aic_inb(p, SG_COUNT), aic_inb(p, SCSISIGI));
++ printk(INFO_LEAD "SSTAT0 0x%x, SSTAT1 0x%x, SSTAT2 0x%x\n",
++ p->host_no, channel, target, lun, aic_inb(p, SSTAT0),
++ aic_inb(p, SSTAT1), aic_inb(p, SSTAT2));
++ }
+ /*
+ * Deal with the busy target and linked next issues.
+ */
+@@ -3501,11 +3498,11 @@
+ if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS))
+ printk(INFO_LEAD "Cleaning up status information "
+ "and delayed_scbs.\n", p->host_no, channel, i, lun);
+- p->dev_flags[i] &= ~(BUS_DEVICE_RESET_PENDING | DEVICE_PARITY_ERROR);
++ p->dev_flags[i] &= ~BUS_DEVICE_RESET_PENDING;
+ if ( tag == SCB_LIST_NULL )
+ {
+ p->dev_flags[i] |= DEVICE_PRINT_DTR | DEVICE_RESET_DELAY;
+- p->dev_expires[i] = jiffies + (4 * HZ);
++ p->dev_expires[i] = jiffies + (1 * HZ);
+ p->dev_timer_active |= (0x01 << i);
+ p->dev_last_queue_full_count[i] = 0;
+ p->dev_last_queue_full[i] = 0;
+@@ -3550,7 +3547,7 @@
+ prev_scbp->flags |= SCB_RESET | SCB_QUEUED_FOR_DONE;
+ }
+ }
+- if ( j > (p->scb_data->maxscbs + 1) )
++ if ( j > (p->scb_data->numscbs + 1) )
+ {
+ if (aic7xxx_verbose & (VERBOSE_ABORT | VERBOSE_RESET))
+ printk(WARN_LEAD "Yikes!! There's a loop in the "
+@@ -3611,7 +3608,7 @@
+ prev_scbp->flags |= SCB_RESET | SCB_QUEUED_FOR_DONE;
+ }
+ }
+- if ( j > (p->scb_data->maxscbs + 1) )
++ if ( j > (p->scb_data->numscbs + 1) )
+ {
+ if (aic7xxx_verbose & (VERBOSE_ABORT | VERBOSE_RESET))
+ printk(WARN_LEAD "Yikes!! There's a loop in the "
+@@ -4375,11 +4372,25 @@
+ if (actual < cmd->underflow)
+ {
+ if (aic7xxx_verbose & VERBOSE_MINOR_ERROR)
++ {
+ printk(INFO_LEAD "Underflow - Wanted %u, %s %u, residual SG "
+ "count %d.\n", p->host_no, CTL_OF_SCB(scb), cmd->underflow,
+ (cmd->request.cmd == WRITE) ? "wrote" : "read", actual,
+ hscb->residual_SG_segment_count);
++ printk(INFO_LEAD "status 0x%x.\n", p->host_no, CTL_OF_SCB(scb),
++ hscb->target_status);
++ }
++ /*
++ * In 2.4, only send back the residual information, don't flag this
++ * as an error. Before 2.4 we had to flag this as an error because
++ * the mid layer didn't check residual data counts to see if the
++ * command needs retried.
++ */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
++ cmd->resid = scb->sg_length - actual;
++#else
+ aic7xxx_error(cmd) = DID_RETRY_COMMAND;
++#endif
+ aic7xxx_status(cmd) = hscb->target_status;
+ }
+ }
+@@ -4698,7 +4709,6 @@
+ */
+ p->needwdtr &= ~target_mask;
+ p->needwdtr_copy &= ~target_mask;
+- p->dtr_pending &= ~target_mask;
+ scb->flags &= ~SCB_MSGOUT_BITS;
+ aic7xxx_set_width(p, target, channel, lun, MSG_EXT_WDTR_BUS_8_BIT,
+ (AHC_TRANS_ACTIVE|AHC_TRANS_GOAL|AHC_TRANS_CUR));
+@@ -4718,8 +4728,7 @@
+ */
+ p->needsdtr &= ~target_mask;
+ p->needsdtr_copy &= ~target_mask;
+- p->dtr_pending &= ~target_mask;
+- scb->flags &= ~SCB_MSGOUT_SDTR;
++ scb->flags &= ~SCB_MSGOUT_BITS;
+ aic7xxx_set_syncrate(p, NULL, target, channel, 0, 0, 0,
+ (AHC_TRANS_CUR|AHC_TRANS_ACTIVE|AHC_TRANS_GOAL));
+ if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+@@ -4852,6 +4861,8 @@
+ aic7xxx_error(cmd) = DID_OK;
+ break;
+ } /* first time sense, no errors */
++ printk(INFO_LEAD "CHECK_CONDITION on REQUEST_SENSE, returning "
++ "an error.\n", p->host_no, CTL_OF_SCB(scb));
+ aic7xxx_error(cmd) = DID_ERROR;
+ scb->flags &= ~SCB_SENSE;
+ break;
+@@ -5214,12 +5225,21 @@
+ printk(KERN_WARNING " %s seen Data Phase. Length=%d, NumSGs=%d.\n",
+ (aic_inb(p, SEQ_FLAGS) & DPHASE) ? "Have" : "Haven't",
+ scb->sg_length, scb->sg_count);
+- for (i = 0; i < scb->sg_count; i++)
++ printk(KERN_WARNING " Raw SCSI Command: 0x");
++ for (i = 0; i < scb->hscb->SCSI_cmd_length; i++)
++ {
++ printk("%02x ", scb->cmd->cmnd[i]);
++ }
++ printk("\n");
++ if(aic7xxx_verbose > 0xffff)
+ {
+- printk(KERN_WARNING " sg[%d] - Addr 0x%x : Length %d\n",
++ for (i = 0; i < scb->sg_count; i++)
++ {
++ printk(KERN_WARNING " sg[%d] - Addr 0x%x : Length %d\n",
+ i,
+ le32_to_cpu(scb->sg_list[i].address),
+ le32_to_cpu(scb->sg_list[i].length) );
++ }
+ }
+ aic7xxx_error(scb->cmd) = DID_ERROR;
+ }
+@@ -5234,7 +5254,7 @@
+ unsigned char resid_sgcnt, index;
+ unsigned char scb_index = aic_inb(p, SCB_TAG);
+ unsigned int cur_addr, resid_dcnt;
+- unsigned int native_addr, native_length;
++ unsigned int native_addr, native_length, sg_addr;
+ int i;
+
+ if(scb_index > p->scb_data->numscbs)
+@@ -5254,6 +5274,9 @@
+ scb->flags, (unsigned int)scb->cmd);
+ break;
+ }
++ if(aic7xxx_verbose & VERBOSE_MINOR_ERROR)
++ printk(INFO_LEAD "Got WIDE_RESIDUE message, patching up data "
++ "pointer.\n", p->host_no, CTL_OF_SCB(scb));
+
+ /*
+ * We have a valid scb to use on this WIDE_RESIDUE message, so
+@@ -5266,132 +5289,87 @@
+ */
+ cur_addr = aic_inb(p, SHADDR) | (aic_inb(p, SHADDR + 1) << 8) |
+ (aic_inb(p, SHADDR + 2) << 16) | (aic_inb(p, SHADDR + 3) << 24);
++ sg_addr = aic_inb(p, SG_COUNT + 1) | (aic_inb(p, SG_COUNT + 2) << 8) |
++ (aic_inb(p, SG_COUNT + 3) << 16) | (aic_inb(p, SG_COUNT + 4) << 24);
+ resid_sgcnt = aic_inb(p, SCB_RESID_SGCNT);
+ resid_dcnt = aic_inb(p, SCB_RESID_DCNT) |
+ (aic_inb(p, SCB_RESID_DCNT + 1) << 8) |
+ (aic_inb(p, SCB_RESID_DCNT + 2) << 16);
+- index = scb->sg_count - (resid_sgcnt + 1);
++ index = scb->sg_count - ((resid_sgcnt) ? resid_sgcnt : 1);
+ native_addr = le32_to_cpu(scb->sg_list[index].address);
+ native_length = le32_to_cpu(scb->sg_list[index].length);
+ /*
+- * Make sure this is a valid sg_seg for the given pointer
++ * If resid_dcnt == native_length, then we just loaded this SG
++ * segment and we need to back it up one...
+ */
+- if(cur_addr < native_addr ||
+- cur_addr > (native_addr + native_length + 1))
+- {
+- printk(WARN_LEAD "invalid cur_addr:0x%x during WIDE_RESIDUE\n",
+- p->host_no, CTL_OF_SCB(scb), cur_addr);
+- if(index > 0)
+- printk(WARN_LEAD " sg_address[-1]:0x%x sg_length[-1]:%d\n",
+- p->host_no, CTL_OF_SCB(scb),
+- le32_to_cpu(scb->sg_list[index - 1].address),
+- le32_to_cpu(scb->sg_list[index - 1].length));
+- printk(WARN_LEAD " sg_address:0x%x sg_length:%d\n",
+- p->host_no, CTL_OF_SCB(scb),
+- native_addr, native_length);
+- if(resid_sgcnt > 1)
+- printk(WARN_LEAD " sg_address[1]:0x%x sg_length[1]:%d\n",
+- p->host_no, CTL_OF_SCB(scb),
+- le32_to_cpu(scb->sg_list[index + 1].address),
+- le32_to_cpu(scb->sg_list[index + 1].length));
+- printk(WARN_LEAD " cur_address:0x%x resid_dcnt:0x%06x\n",
+- p->host_no, CTL_OF_SCB(scb),
+- cur_addr, resid_dcnt);
+- break;
+- }
+-
+- if( (resid_sgcnt == 0) &&
+- ((resid_dcnt == 0) || (resid_dcnt == 0xffffff)))
++ if(resid_dcnt == native_length)
+ {
+- /*
+- * We are at the end of the transfer and this is about a byte
+- * we ignored already (because the sequencer knew this was
+- * the last segment and set the adapter to ignore any wide
+- * residue bytes that might come through, which is only done
+- * on the last scatter gather segment of transfers).
+- */
+- break;
+- }
+- else if(cur_addr == native_addr)
+- {
+- /*
+- * If our current address matches the sg_seg->address then we
+- * have to back up the sg array to the previous segment and set
+- * it up to have only one byte of transfer left to go.
+- */
+ if(index == 0)
+ {
+- printk(WARN_LEAD "bogus WIDE_RESIDUE message, no data has been "
+- "transferred.\n", p->host_no, CTL_OF_SCB(scb));
++ /*
++ * Oops, this isn't right, we can't back up to before the
++ * beginning. This must be a bogus message, ignore it.
++ */
+ break;
+ }
+- resid_sgcnt++;
+- index--;
+- cur_addr = le32_to_cpu(scb->sg_list[index].address) +
+- le32_to_cpu(scb->sg_list[index].length) - 1;
+- native_addr = aic_inb(p, SG_NEXT) | (aic_inb(p, SG_NEXT + 1) << 8)
+- | (aic_inb(p, SG_NEXT + 2) << 16) | (aic_inb(p, SG_NEXT + 3) << 24);
+- native_addr -= SG_SIZEOF;
+- aic_outb(p, resid_sgcnt, SG_COUNT);
+- aic_outb(p, resid_sgcnt, SCB_RESID_SGCNT);
+- aic_outb(p, native_addr & 0xff, SG_NEXT);
+- aic_outb(p, (native_addr >> 8) & 0xff, SG_NEXT + 1);
+- aic_outb(p, (native_addr >> 16) & 0xff, SG_NEXT + 2);
+- aic_outb(p, (native_addr >> 24) & 0xff, SG_NEXT + 3);
+- aic_outb(p, 1, SCB_RESID_DCNT);
+- aic_outb(p, 0, SCB_RESID_DCNT + 1);
+- aic_outb(p, 0, SCB_RESID_DCNT + 2);
+- aic_outb(p, 1, HCNT);
+- aic_outb(p, 0, HCNT + 1);
+- aic_outb(p, 0, HCNT + 2);
+- aic_outb(p, cur_addr & 0xff, HADDR);
+- aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1);
+- aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2);
+- aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3);
++ resid_dcnt = 1;
++ resid_sgcnt += 1;
++ native_addr = le32_to_cpu(scb->sg_list[index - 1].address);
++ native_length = le32_to_cpu(scb->sg_list[index - 1].length);
++ cur_addr = native_addr + (native_length - 1);
++ sg_addr -= sizeof(struct hw_scatterlist);
+ }
+ else
+ {
+ /*
+- * Back the data pointer up by one and add one to the remaining
+- * byte count. Then store that in the HCNT and HADDR registers.
++ * resid_dcnt != native_length, so we are in the middle of a SG
++ * element. Back it up one byte and leave the rest alone.
+ */
+- cur_addr--;
+- resid_dcnt++;
+- aic_outb(p, resid_dcnt & 0xff, SCB_RESID_DCNT);
+- aic_outb(p, (resid_dcnt >> 8) & 0xff, SCB_RESID_DCNT + 1);
+- aic_outb(p, (resid_dcnt >> 16) & 0xff, SCB_RESID_DCNT + 2);
+- aic_outb(p, resid_dcnt & 0xff, HCNT);
+- aic_outb(p, (resid_dcnt >> 8) & 0xff, HCNT + 1);
+- aic_outb(p, (resid_dcnt >> 16) & 0xff, HCNT + 2);
+- aic_outb(p, cur_addr & 0xff, HADDR);
+- aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1);
+- aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2);
+- aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3);
++ resid_dcnt += 1;
++ cur_addr -= 1;
+ }
++
++ /*
++ * Output the new addres |