diff options
Diffstat (limited to 'drivers/scsi/aic7xxx_old')
-rw-r--r-- | drivers/scsi/aic7xxx_old/aic7xxx.h | 28 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx_old/aic7xxx.reg | 1401 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx_old/aic7xxx.seq | 1539 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx_old/aic7xxx_proc.c | 374 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx_old/aic7xxx_reg.h | 629 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx_old/aic7xxx_seq.c | 817 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx_old/scsi_message.h | 49 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx_old/sequencer.h | 135 |
8 files changed, 4972 insertions, 0 deletions
diff --git a/drivers/scsi/aic7xxx_old/aic7xxx.h b/drivers/scsi/aic7xxx_old/aic7xxx.h new file mode 100644 index 000000000000..0116c8128a6b --- /dev/null +++ b/drivers/scsi/aic7xxx_old/aic7xxx.h @@ -0,0 +1,28 @@ +/*+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 "5.2.0" + +#endif /* _aic7xxx_h */ diff --git a/drivers/scsi/aic7xxx_old/aic7xxx.reg b/drivers/scsi/aic7xxx_old/aic7xxx.reg new file mode 100644 index 000000000000..f67b4bced01c --- /dev/null +++ b/drivers/scsi/aic7xxx_old/aic7xxx.reg @@ -0,0 +1,1401 @@ +/* + * Aic7xxx register and scratch ram definitions. + * + * Copyright (c) 1994-1998 Justin Gibbs. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Where this Software is combined with software released under the terms of + * the GNU General Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: aic7xxx.reg,v 1.4 1997/06/27 19:38:39 gibbs Exp $ + */ + +/* + * This file is processed by the aic7xxx_asm utility for use in assembling + * firmware for the aic7xxx family of SCSI host adapters as well as to generate + * a C header file for use in the kernel portion of the Aic7xxx driver. + * + * All page numbers refer to the Adaptec AIC-7770 Data Book available from + * Adaptec's Technical Documents Department 1-800-934-2766 + */ + +/* + * SCSI Sequence Control (p. 3-11). + * Each bit, when set starts a specific SCSI sequence on the bus + */ +register SCSISEQ { + address 0x000 + access_mode RW + bit TEMODE 0x80 + bit ENSELO 0x40 + bit ENSELI 0x20 + bit ENRSELI 0x10 + bit ENAUTOATNO 0x08 + bit ENAUTOATNI 0x04 + bit ENAUTOATNP 0x02 + bit SCSIRSTO 0x01 +} + +/* + * SCSI Transfer Control 0 Register (pp. 3-13). + * Controls the SCSI module data path. + */ +register SXFRCTL0 { + address 0x001 + access_mode RW + bit DFON 0x80 + bit DFPEXP 0x40 + bit FAST20 0x20 + bit CLRSTCNT 0x10 + bit SPIOEN 0x08 + bit SCAMEN 0x04 + bit CLRCHN 0x02 +} + +/* + * SCSI Transfer Control 1 Register (pp. 3-14,15). + * Controls the SCSI module data path. + */ +register SXFRCTL1 { + address 0x002 + access_mode RW + bit BITBUCKET 0x80 + bit SWRAPEN 0x40 + bit ENSPCHK 0x20 + mask STIMESEL 0x18 + bit ENSTIMER 0x04 + bit ACTNEGEN 0x02 + bit STPWEN 0x01 /* Powered Termination */ +} + +/* + * SCSI Control Signal Read Register (p. 3-15). + * Reads the actual state of the SCSI bus pins + */ +register SCSISIGI { + address 0x003 + access_mode RO + bit CDI 0x80 + bit IOI 0x40 + bit MSGI 0x20 + bit ATNI 0x10 + bit SELI 0x08 + bit BSYI 0x04 + bit REQI 0x02 + bit ACKI 0x01 +/* + * Possible phases in SCSISIGI + */ + mask PHASE_MASK CDI|IOI|MSGI + mask P_DATAOUT 0x00 + mask P_DATAIN IOI + mask P_COMMAND CDI + mask P_MESGOUT CDI|MSGI + mask P_STATUS CDI|IOI + mask P_MESGIN CDI|IOI|MSGI +} + +/* + * SCSI Control Signal Write Register (p. 3-16). + * Writing to this register modifies the control signals on the bus. Only + * those signals that are allowed in the current mode (Initiator/Target) are + * asserted. + */ +register SCSISIGO { + address 0x003 + access_mode WO + bit CDO 0x80 + bit IOO 0x40 + bit MSGO 0x20 + bit ATNO 0x10 + bit SELO 0x08 + bit BSYO 0x04 + bit REQO 0x02 + bit ACKO 0x01 +/* + * Possible phases to write into SCSISIG0 + */ + mask PHASE_MASK CDI|IOI|MSGI + mask P_DATAOUT 0x00 + mask P_DATAIN IOI + mask P_COMMAND CDI + mask P_MESGOUT CDI|MSGI + mask P_STATUS CDI|IOI + mask P_MESGIN CDI|IOI|MSGI +} + +/* + * SCSI Rate Control (p. 3-17). + * Contents of this register determine the Synchronous SCSI data transfer + * rate and the maximum synchronous Req/Ack offset. An offset of 0 in the + * SOFS (3:0) bits disables synchronous data transfers. Any offset value + * greater than 0 enables synchronous transfers. + */ +register SCSIRATE { + address 0x004 + access_mode RW + bit WIDEXFER 0x80 /* Wide transfer control */ + mask SXFR 0x70 /* Sync transfer rate */ + mask SXFR_ULTRA2 0x7f /* Sync transfer rate */ + mask SOFS 0x0f /* Sync offset */ +} + +/* + * SCSI ID (p. 3-18). + * Contains the ID of the board and the current target on the + * selected channel. + */ +register SCSIID { + address 0x005 + access_mode RW + mask TID 0xf0 /* Target ID mask */ + mask OID 0x0f /* Our ID mask */ + /* + * SCSI Maximum Offset (p. 4-61 aic7890/91 Data Book) + * The aic7890/91 allow an offset of up to 127 transfers in both wide + * and narrow mode. + */ + alias SCSIOFFSET + mask SOFS_ULTRA2 0x7f /* Sync offset U2 chips */ +} + +/* + * SCSI Latched Data (p. 3-19). + * Read/Write latches used to transfer data on the SCSI bus during + * Automatic or Manual PIO mode. SCSIDATH can be used for the + * upper byte of a 16bit wide asynchronouse data phase transfer. + */ +register SCSIDATL { + address 0x006 + access_mode RW +} + +register SCSIDATH { + address 0x007 + access_mode RW +} + +/* + * SCSI Transfer Count (pp. 3-19,20) + * These registers count down the number of bytes transferred + * across the SCSI bus. The counter is decremented only once + * the data has been safely transferred. SDONE in SSTAT0 is + * set when STCNT goes to 0 + */ +register STCNT { + address 0x008 + size 3 + access_mode RW +} + +/* + * Option Mode Register (Alternate Mode) (p. 5-198) + * This register is used to set certain options on Ultra3 based chips. + * The chip must be in alternate mode (bit ALT_MODE in SFUNCT must be set) + */ +register OPTIONMODE { + address 0x008 + access_mode RW + bit AUTORATEEN 0x80 + bit AUTOACKEN 0x40 + bit ATNMGMNTEN 0x20 + bit BUSFREEREV 0x10 + bit EXPPHASEDIS 0x08 + bit SCSIDATL_IMGEN 0x04 + bit AUTO_MSGOUT_DE 0x02 + bit DIS_MSGIN_DUALEDGE 0x01 +} + + +/* + * Clear SCSI Interrupt 0 (p. 3-20) + * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT0. + */ +register CLRSINT0 { + address 0x00b + access_mode WO + bit CLRSELDO 0x40 + bit CLRSELDI 0x20 + bit CLRSELINGO 0x10 + bit CLRSWRAP 0x08 + bit CLRSPIORDY 0x02 +} + +/* + * SCSI Status 0 (p. 3-21) + * Contains one set of SCSI Interrupt codes + * These are most likely of interest to the sequencer + */ +register SSTAT0 { + address 0x00b + access_mode RO + bit TARGET 0x80 /* Board acting as target */ + bit SELDO 0x40 /* Selection Done */ + bit SELDI 0x20 /* Board has been selected */ + bit SELINGO 0x10 /* Selection In Progress */ + bit SWRAP 0x08 /* 24bit counter wrap */ + bit IOERR 0x08 /* LVD Tranceiver mode changed */ + bit SDONE 0x04 /* STCNT = 0x000000 */ + bit SPIORDY 0x02 /* SCSI PIO Ready */ + bit DMADONE 0x01 /* DMA transfer completed */ +} + +/* + * Clear SCSI Interrupt 1 (p. 3-23) + * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT1. + */ +register CLRSINT1 { + address 0x00c + access_mode WO + bit CLRSELTIMEO 0x80 + bit CLRATNO 0x40 + bit CLRSCSIRSTI 0x20 + bit CLRBUSFREE 0x08 + bit CLRSCSIPERR 0x04 + bit CLRPHASECHG 0x02 + bit CLRREQINIT 0x01 +} + +/* + * SCSI Status 1 (p. 3-24) + */ +register SSTAT1 { + address 0x00c + access_mode RO + bit SELTO 0x80 + bit ATNTARG 0x40 + bit SCSIRSTI 0x20 + bit PHASEMIS 0x10 + bit BUSFREE 0x08 + bit SCSIPERR 0x04 + bit PHASECHG 0x02 + bit REQINIT 0x01 +} + +/* + * SCSI Status 2 (pp. 3-25,26) + */ +register SSTAT2 { + address 0x00d + access_mode RO + bit OVERRUN 0x80 + bit SHVALID 0x40 + bit WIDE_RES 0x20 + bit EXP_ACTIVE 0x10 /* SCSI Expander Active */ + bit CRCVALERR 0x08 /* CRC Value Error */ + bit CRCENDERR 0x04 /* CRC End Error */ + bit CRCREQERR 0x02 /* CRC REQ Error */ + bit DUAL_EDGE_ERROR 0x01 /* Invalid pins for Dual Edge phase */ + mask SFCNT 0x1f +} + +/* + * SCSI Status 3 (p. 3-26) + */ +register SSTAT3 { + address 0x00e + access_mode RO + mask SCSICNT 0xf0 + mask OFFCNT 0x0f +} + +/* + * SCSI ID for the aic7890/91 chips + */ +register SCSIID_ULTRA2 { + address 0x00f + access_mode RW + mask TID 0xf0 /* Target ID mask */ + mask OID 0x0f /* Our ID mask */ +} + +/* + * SCSI Interrupt Mode 1 (p. 3-28) + * Setting any bit will enable the corresponding function + * in SIMODE0 to interrupt via the IRQ pin. + */ +register SIMODE0 { + address 0x010 + access_mode RW + bit ENSELDO 0x40 + bit ENSELDI 0x20 + bit ENSELINGO 0x10 + bit ENSWRAP 0x08 + bit ENIOERR 0x08 /* LVD Tranceiver mode changes */ + bit ENSDONE 0x04 + bit ENSPIORDY 0x02 + bit ENDMADONE 0x01 +} + +/* + * SCSI Interrupt Mode 1 (pp. 3-28,29) + * Setting any bit will enable the corresponding function + * in SIMODE1 to interrupt via the IRQ pin. + */ +register SIMODE1 { + address 0x011 + access_mode RW + bit ENSELTIMO 0x80 + bit ENATNTARG 0x40 + bit ENSCSIRST 0x20 + bit ENPHASEMIS 0x10 + bit ENBUSFREE 0x08 + bit ENSCSIPERR 0x04 + bit ENPHASECHG 0x02 + bit ENREQINIT 0x01 +} + +/* + * SCSI Data Bus (High) (p. 3-29) + * This register reads data on the SCSI Data bus directly. + */ +register SCSIBUSL { + address 0x012 + access_mode RO +} + +register SCSIBUSH { + address 0x013 + access_mode RO +} + +/* + * SCSI/Host Address (p. 3-30) + * These registers hold the host address for the byte about to be + * transferred on the SCSI bus. They are counted up in the same + * manner as STCNT is counted down. SHADDR should always be used + * to determine the address of the last byte transferred since HADDR + * can be skewed by write ahead. + */ +register SHADDR { + address 0x014 + size 4 + access_mode RO +} + +/* + * Selection Timeout Timer (p. 3-30) + */ +register SELTIMER { + address 0x018 + access_mode RW + bit STAGE6 0x20 + bit STAGE5 0x10 + bit STAGE4 0x08 + bit STAGE3 0x04 + bit STAGE2 0x02 + bit STAGE1 0x01 +} + +/* + * Selection/Reselection ID (p. 3-31) + * Upper four bits are the device id. The ONEBIT is set when the re/selecting + * device did not set its own ID. + */ +register SELID { + address 0x019 + access_mode RW + mask SELID_MASK 0xf0 + bit ONEBIT 0x08 +} + +/* + * Serial Port I/O Cabability register (p. 4-95 aic7860 Data Book) + * Indicates if external logic has been attached to the chip to + * perform the tasks of accessing a serial eeprom, testing termination + * strength, and performing cable detection. On the aic7860, most of + * these features are handled on chip, but on the aic7855 an attached + * aic3800 does the grunt work. + */ +register SPIOCAP { + address 0x01b + access_mode RW + bit SOFT1 0x80 + bit SOFT0 0x40 + bit SOFTCMDEN 0x20 + bit HAS_BRDCTL 0x10 /* External Board control */ + bit SEEPROM 0x08 /* External serial eeprom logic */ + bit EEPROM 0x04 /* Writable external BIOS ROM */ + bit ROM 0x02 /* Logic for accessing external ROM */ + bit SSPIOCPS 0x01 /* Termination and cable detection */ +} + +/* + * SCSI Block Control (p. 3-32) + * Controls Bus type and channel selection. In a twin channel configuration + * addresses 0x00-0x1e are gated to the appropriate channel based on this + * register. SELWIDE allows for the coexistence of 8bit and 16bit devices + * on a wide bus. + */ +register SBLKCTL { + address 0x01f + access_mode RW + bit DIAGLEDEN 0x80 /* Aic78X0 only */ + bit DIAGLEDON 0x40 /* Aic78X0 only */ + bit AUTOFLUSHDIS 0x20 + bit SELBUSB 0x08 + bit ENAB40 0x08 /* LVD transceiver active */ + bit ENAB20 0x04 /* SE/HVD transceiver active */ + bit SELWIDE 0x02 + bit XCVR 0x01 /* External transceiver active */ +} + +/* + * Sequencer Control (p. 3-33) + * Error detection mode and speed configuration + */ +register SEQCTL { + address 0x060 + access_mode RW + bit PERRORDIS 0x80 + bit PAUSEDIS 0x40 + bit FAILDIS 0x20 + bit FASTMODE 0x10 + bit BRKADRINTEN 0x08 + bit STEP 0x04 + bit SEQRESET 0x02 + bit LOADRAM 0x01 +} + +/* + * Sequencer RAM Data (p. 3-34) + * Single byte window into the Scratch Ram area starting at the address + * specified by SEQADDR0 and SEQADDR1. To write a full word, simply write + * four bytes in succession. The SEQADDRs will increment after the most + * significant byte is written + */ +register SEQRAM { + address 0x061 + access_mode RW +} + +/* + * Sequencer Address Registers (p. 3-35) + * Only the first bit of SEQADDR1 holds addressing information + */ +register SEQADDR0 { + address 0x062 + access_mode RW +} + +register SEQADDR1 { + address 0x063 + access_mode RW + mask SEQADDR1_MASK 0x01 +} + +/* + * Accumulator + * We cheat by passing arguments in the Accumulator up to the kernel driver + */ +register ACCUM { + address 0x064 + access_mode RW + accumulator +} + +register SINDEX { + address 0x065 + access_mode RW + sindex +} + +register DINDEX { + address 0x066 + access_mode RW +} + +register ALLONES { + address 0x069 + access_mode RO + allones +} + +register ALLZEROS { + address 0x06a + access_mode RO + allzeros +} + +register NONE { + address 0x06a + access_mode WO + none +} + +register FLAGS { + address 0x06b + access_mode RO + bit ZERO 0x02 + bit CARRY 0x01 +} + +register SINDIR { + address 0x06c + access_mode RO +} + +register DINDIR { + address 0x06d + access_mode WO +} + +register FUNCTION1 { + address 0x06e + access_mode RW +} + +register STACK { + address 0x06f + access_mode RO +} + +/* + * Board Control (p. 3-43) + */ +register BCTL { + address 0x084 + access_mode RW + bit ACE 0x08 + bit ENABLE 0x01 +} + +register DSCOMMAND0 { + address 0x084 + access_mode RW + bit CACHETHEN 0x80 + bit DPARCKEN 0x40 + bit MPARCKEN 0x20 + bit EXTREQLCK 0x10 + bit INTSCBRAMSEL 0x08 + bit RAMPS 0x04 + bit USCBSIZE32 0x02 + bit CIOPARCKEN 0x01 +} + +/* + * On the aic78X0 chips, Board Control is replaced by the DSCommand + * register (p. 4-64) + */ +register DSCOMMAND { + address 0x084 + access_mode RW + bit CACHETHEN 0x80 /* Cache Threshold enable */ + bit DPARCKEN 0x40 /* Data Parity Check Enable */ + bit MPARCKEN 0x20 /* Memory Parity Check Enable */ + bit EXTREQLCK 0x10 /* External Request Lock */ +} + +/* + * Bus On/Off Time (p. 3-44) + */ +register BUSTIME { + address 0x085 + access_mode RW + mask BOFF 0xf0 + mask BON 0x0f +} + +/* + * Bus Speed (p. 3-45) + */ +register BUSSPD { + address 0x086 + access_mode RW + mask DFTHRSH 0xc0 + mask STBOFF 0x38 + mask STBON 0x07 + mask DFTHRSH_100 0xc0 +} + +/* + * Host Control (p. 3-47) R/W + * Overall host control of the device. + */ +register HCNTRL { + address 0x087 + access_mode RW + bit POWRDN 0x40 + bit SWINT 0x10 + bit IRQMS 0x08 + bit PAUSE 0x04 + bit INTEN 0x02 + bit CHIPRST 0x01 + bit CHIPRSTACK 0x01 +} + +/* + * Host Address (p. 3-48) + * This register contains the address of the byte about + * to be transferred across the host bus. + */ +register HADDR { + address 0x088 + size 4 + access_mode RW +} + +register HCNT { + address 0x08c + size 3 + access_mode RW +} + +/* + * SCB Pointer (p. 3-49) + * Gate one of the four SCBs into the SCBARRAY window. + */ +register SCBPTR { + address 0x090 + access_mode RW +} + +/* + * Interrupt Status (p. 3-50) + * Status for system interrupts + */ +register INTSTAT { + address 0x091 + access_mode RW + bit BRKADRINT 0x08 + bit SCSIINT 0x04 + bit CMDCMPLT 0x02 + bit SEQINT 0x01 + mask BAD_PHASE SEQINT /* unknown scsi bus phase */ + mask SEND_REJECT 0x10|SEQINT /* sending a message reject */ + mask NO_IDENT 0x20|SEQINT /* no IDENTIFY after reconnect*/ + mask NO_MATCH 0x30|SEQINT /* no cmd match for reconnect */ + mask EXTENDED_MSG 0x40|SEQINT /* Extended message received */ + mask WIDE_RESIDUE 0x50|SEQINT /* need kernel to back up */ + /* the SG array for us */ + mask REJECT_MSG 0x60|SEQINT /* Reject message received */ + mask BAD_STATUS 0x70|SEQINT /* Bad status from target */ + mask RESIDUAL 0x80|SEQINT /* Residual byte count != 0 */ + mask AWAITING_MSG 0xa0|SEQINT /* + * Kernel requested to specify + * a message to this target + * (command was null), so tell + * it that it can fill the + * message buffer. + */ + 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 + * when we were expecting + * another msgin byte. + */ + mask DATA_OVERRUN 0xe0|SEQINT /* + * Target attempted to write + * beyond the bounds of its + * command. + */ + + mask SEQINT_MASK 0xf0|SEQINT /* SEQINT Status Codes */ + mask INT_PEND (BRKADRINT|SEQINT|SCSIINT|CMDCMPLT) +} + +/* + * Hard Error (p. 3-53) + * Reporting of catastrophic errors. You usually cannot recover from + * these without a full board reset. + */ +register ERROR { + address 0x092 + access_mode RO + bit CIOPARERR 0x80 /* Ultra2 only */ + bit PCIERRSTAT 0x40 /* PCI only */ + bit MPARERR 0x20 /* PCI only */ + bit DPARERR 0x10 /* PCI only */ + bit SQPARERR 0x08 + bit ILLOPCODE 0x04 + bit ILLSADDR 0x02 + bit DSCTMOUT 0x02 /* Ultra3 only */ + bit ILLHADDR 0x01 +} + +/* + * Clear Interrupt Status (p. 3-52) + */ +register CLRINT { + address 0x092 + access_mode WO + bit CLRPARERR 0x10 /* PCI only */ + bit CLRBRKADRINT 0x08 + bit CLRSCSIINT 0x04 + bit CLRCMDINT 0x02 + bit CLRSEQINT 0x01 +} + +register DFCNTRL { + address 0x093 + access_mode RW + bit PRELOADEN 0x80 /* aic7890 only */ + bit WIDEODD 0x40 + bit SCSIEN 0x20 + bit SDMAEN 0x10 + bit SDMAENACK 0x10 + bit HDMAEN 0x08 + bit HDMAENACK 0x08 + bit DIRECTION 0x04 + bit FIFOFLUSH 0x02 + bit FIFORESET 0x01 +} + +register DFSTATUS { + address 0x094 + access_mode RO + bit PRELOAD_AVAIL 0x80 + bit DWORDEMP 0x20 + bit MREQPEND 0x10 + bit HDONE 0x08 + bit DFTHRESH 0x04 + bit FIFOFULL 0x02 + bit FIFOEMP 0x01 +} + +register DFDAT { + address 0x099 + access_mode RW +} + +/* + * SCB Auto Increment (p. 3-59) + * Byte offset into the SCB Array and an optional bit to allow auto + * incrementing of the address during download and upload operations + */ +register SCBCNT { + address 0x09a + access_mode RW + bit SCBAUTO 0x80 + mask SCBCNT_MASK 0x1f +} + +/* + * Queue In FIFO (p. 3-60) + * Input queue for queued SCBs (commands that the seqencer has yet to start) + */ +register QINFIFO { + address 0x09b + access_mode RW +} + +/* + * Queue In Count (p. 3-60) + * Number of queued SCBs + */ +register QINCNT { + address 0x09c + access_mode RO +} + +/* + * SCSIDATL IMAGE Register (p. 5-104) + * Write to this register also go to SCSIDATL but this register will preserve + * the data for later reading as long as the SCSIDATL_IMGEN bit in the + * OPTIONMODE register is set. + */ +register SCSIDATL_IMG { + address 0x09c + access_mode RW +} + +/* + * Queue Out FIFO (p. 3-61) + * Queue of SCBs that have completed and await the host + */ +register QOUTFIFO { + address 0x09d + access_mode WO +} + +/* + * CRC Control 1 Register (p. 5-105) + * Control bits for the Ultra 160/m CRC facilities + */ +register CRCCONTROL1 { + address 0x09d + access_mode RW + bit CRCONSEEN 0x80 /* CRC ON Single Edge ENable */ + bit CRCVALCHKEN 0x40 /* CRC Value Check Enable */ + bit CRCENDCHKEN 0x20 /* CRC End Check Enable */ + bit CRCREQCHKEN 0x10 + bit TARGCRCENDEN 0x08 /* Enable End CRC transfer when target */ + bit TARGCRCCNTEN 0x04 /* Enable CRC transfer when target */ +} + +/* + * Queue Out Count (p. 3-61) + * Number of queued SCBs in the Out FIFO + */ +register QOUTCNT { + address 0x09e + access_mode RO +} + +/* + * SCSI Phase Register (p. 5-106) + * Current bus phase + */ +register SCSIPHASE { + address 0x09e + access_mode RO + bit SP_STATUS 0x20 + bit SP_COMMAND 0x10 + bit SP_MSG_IN 0x08 + bit SP_MSG_OUT 0x04 + bit SP_DATA_IN 0x02 + bit SP_DATA_OUT 0x01 +} + +/* + * Special Function + */ +register SFUNCT { + address 0x09f + access_mode RW + bit ALT_MODE 0x80 +} + +/* + * SCB Definition (p. 5-4) + */ +scb { + address 0x0a0 + SCB_CONTROL { + size 1 + bit MK_MESSAGE 0x80 + bit DISCENB 0x40 + bit TAG_ENB 0x20 + bit DISCONNECTED 0x04 + mask SCB_TAG_TYPE 0x03 + } + SCB_TCL { + size 1 + bit SELBUSB 0x08 + mask TID 0xf0 + mask LID 0x07 + } + SCB_TARGET_STATUS { + size 1 + } + SCB_SGCOUNT { + size 1 + } + SCB_SGPTR { + size 4 + } + SCB_RESID_SGCNT { + size 1 + } + SCB_RESID_DCNT { + size 3 + } + SCB_DATAPTR { + size 4 + } + SCB_DATACNT { + /* + * Really only 3 bytes, but padded to make + * the kernel's job easier. + */ + size 4 + } + SCB_CMDPTR { + size 4 + } + SCB_CMDLEN { + size 1 + } + SCB_TAG { + size 1 + } + SCB_NEXT { + size 1 + } + SCB_PREV { + size 1 + } + SCB_BUSYTARGETS { + size 4 + } +} + +const SG_SIZEOF 0x08 /* sizeof(struct ahc_dma) */ + +/* --------------------- AHA-2840-only definitions -------------------- */ + +register SEECTL_2840 { + address 0x0c0 + access_mode RW + bit CS_2840 0x04 + bit CK_2840 0x02 + bit DO_2840 0x01 +} + +register STATUS_2840 { + address 0x0c1 + access_mode RW + bit EEPROM_TF 0x80 + mask BIOS_SEL 0x60 + mask ADSEL 0x1e + bit DI_2840 0x01 +} + +/* --------------------- AIC-7870-only definitions -------------------- */ + +register DSPCISTATUS { + address 0x086 + mask DFTHRSH_100 0xc0 +} + +register CCHADDR { + address 0x0E0 + size 8 +} + +register CCHCNT { + address 0x0E8 +} + +register CCSGRAM { + address 0x0E9 +} + +register CCSGADDR { + address 0x0EA +} + +register CCSGCTL { + address 0x0EB + bit CCSGDONE 0x80 + bit CCSGEN 0x08 + bit FLAG 0x02 + bit CCSGRESET 0x01 +} + +register CCSCBCNT { + address 0xEF +} + +register CCSCBCTL { + address 0x0EE + bit CCSCBDONE 0x80 + bit ARRDONE 0x40 /* SCB Array prefetch done */ + bit CCARREN 0x10 + bit CCSCBEN 0x08 + bit CCSCBDIR 0x04 + bit CCSCBRESET 0x01 +} + +register CCSCBADDR { + address 0x0ED +} + +register CCSCBRAM { + address 0xEC +} + +register CCSCBPTR { + address 0x0F1 +} + +register HNSCB_QOFF { + address 0x0F4 +} + +register HESCB_QOFF { + address 0x0F5 +} + +register SNSCB_QOFF { + address 0x0F6 +} + +register SESCB_QOFF { + address 0x0F7 +} + +register SDSCB_QOFF { + address 0x0F8 +} + +register QOFF_CTLSTA { + address 0x0FA + bit ESTABLISH_SCB_AVAIL 0x80 + bit SCB_AVAIL 0x40 + bit SNSCB_ROLLOVER 0x20 + bit SDSCB_ROLLOVER 0x10 + bit SESCB_ROLLOVER 0x08 + mask SCB_QSIZE 0x07 + mask SCB_QSIZE_256 0x06 +} + +register DFF_THRSH { + address 0x0FB + mask WR_DFTHRSH 0x70 + mask RD_DFTHRSH 0x07 + mask RD_DFTHRSH_MIN 0x00 + mask RD_DFTHRSH_25 0x01 + mask RD_DFTHRSH_50 0x02 + mask RD_DFTHRSH_63 0x03 + mask RD_DFTHRSH_75 0x04 + mask RD_DFTHRSH_85 0x05 + mask RD_DFTHRSH_90 0x06 + mask RD_DFTHRSH_MAX 0x07 + mask WR_DFTHRSH_MIN 0x00 + mask WR_DFTHRSH_25 0x10 + mask WR_DFTHRSH_50 0x20 + mask WR_DFTHRSH_63 0x30 + mask WR_DFTHRSH_75 0x40 + mask WR_DFTHRSH_85 0x50 + mask WR_DFTHRSH_90 0x60 + mask WR_DFTHRSH_MAX 0x70 +} + +register SG_CACHEPTR { + access_mode RW + address 0x0fc + mask SG_USER_DATA 0xfc + bit LAST_SEG 0x02 + bit LAST_SEG_DONE 0x01 +} + +register BRDCTL { + address 0x01d + bit BRDDAT7 0x80 + bit BRDDAT6 0x40 + bit BRDDAT5 0x20 + bit BRDSTB 0x10 + bit BRDCS 0x08 + bit BRDRW 0x04 + bit BRDCTL1 0x02 + bit BRDCTL0 0x01 + /* 7890 Definitions */ + bit BRDDAT4 0x10 + bit BRDDAT3 0x08 + bit BRDDAT2 0x04 + bit BRDRW_ULTRA2 0x02 + bit BRDSTB_ULTRA2 0x01 +} + +/* + * Serial EEPROM Control (p. 4-92 in 7870 Databook) + * Controls the reading and writing of an external serial 1-bit + * EEPROM Device. In order to access the serial EEPROM, you must + * first set the SEEMS bit that generates a request to the memory + * port for access to the serial EEPROM device. When the memory + * port is not busy servicing another request, it reconfigures + * to allow access to the serial EEPROM. When this happens, SEERDY + * gets set high to verify that the memory port access has been + * granted. + * + * After successful arbitration for the memory port, the SEECS bit of + * the SEECTL register is connected to the chip select. The SEECK, + * SEEDO, and SEEDI are connected to the clock, data out, and data in + * lines respectively. The SEERDY bit of SEECTL is useful in that it + * gives us an 800 nsec timer. After a write to the SEECTL register, + * the SEERDY goes high 800 nsec later. The one exception to this is + * when we first request access to the memory port. The SEERDY goes + * high to signify that access has been granted and, for this case, has + * no implied timing. + * + * See 93cx6.c for detailed information on the protocol necessary to + * read the serial EEPROM. + */ +register SEECTL { + address 0x01e + bit EXTARBACK 0x80 + bit EXTARBREQ 0x40 + bit SEEMS 0x20 + bit SEERDY 0x10 + bit SEECS 0x08 + bit SEECK 0x04 + bit SEEDO 0x02 + bit SEEDI 0x01 +} +/* ---------------------- Scratch RAM Offsets ------------------------- */ +/* These offsets are either to values that are initialized by the board's + * BIOS or are specified by the sequencer code. + * + * The host adapter card (at least the BIOS) uses 20-2f for SCSI + * device information, 32-33 and 5a-5f as well. As it turns out, the + * BIOS trashes 20-2f, writing the synchronous negotiation results + * on top of the BIOS values, so we re-use those for our per-target + * scratchspace (actually a value that can be copied directly into + * SCSIRATE). The kernel driver will enable synchronous negotiation + * for all targets that have a value other than 0 in the lower four + * bits of the target scratch space. This should work regardless of + * whether the bios has been installed. + */ + +scratch_ram { + address 0x020 + + /* + * 1 byte per target starting at this address for configuration values + */ + TARG_SCSIRATE { + size 16 + } + /* + * Bit vector of targets that have ULTRA enabled. + */ + ULTRA_ENB { + size 2 + } + /* + * Bit vector of targets that have disconnection disabled. + */ + DISC_DSB { + size 2 + } + /* + * Single byte buffer used to designate the type or message + * to send to a target. + */ + MSG_OUT { + size 1 + } + /* Parameters for DMA Logic */ + DMAPARAMS { + size 1 + bit PRELOADEN 0x80 + bit WIDEODD 0x40 + bit SCSIEN 0x20 + bit SDMAEN 0x10 + bit SDMAENACK 0x10 + bit HDMAEN 0x08 + bit HDMAENACK 0x08 + bit DIRECTION 0x04 + bit FIFOFLUSH 0x02 + bit FIFORESET 0x01 + } + SEQ_FLAGS { + size 1 + bit IDENTIFY_SEEN 0x80 + bit SCBPTR_VALID 0x20 + bit DPHASE 0x10 + bit AMTARGET 0x08 + bit WIDE_BUS 0x02 + bit TWIN_BUS 0x01 + } + /* + * Temporary storage for the + * target/channel/lun of a + * reconnecting target + */ + SAVED_TCL { + size 1 + } + /* Working value of the number of SG segments left */ + SG_COUNT { + size 1 + } + /* Working value of SG pointer */ + SG_NEXT { + size 4 + } + /* + * The last bus phase as seen by the sequencer. + */ + LASTPHASE { + size 1 + bit CDI 0x80 + bit IOI 0x40 + bit MSGI 0x20 + mask PHASE_MASK CDI|IOI|MSGI + mask P_DATAOUT 0x00 + mask P_DATAIN IOI + mask P_COMMAND CDI + mask P_MESGOUT CDI|MSGI + mask P_STATUS CDI|IOI + mask P_MESGIN CDI|IOI|MSGI + mask P_BUSFREE 0x01 + } + /* + * head of list of SCBs awaiting + * selection + */ + WAITING_SCBH { + size 1 + } + /* + * head of list of SCBs that are + * disconnected. Used for SCB + * paging. + */ + DISCONNECTED_SCBH { + size 1 + } + /* + * head of list of SCBs that are + * not in use. Used for SCB paging. + */ + FREE_SCBH { + size 1 + } + /* + * Address of the hardware scb array in the host. + */ + HSCB_ADDR { + size 4 + } + /* + * Address of the 256 byte array storing the SCBID of outstanding + * untagged SCBs indexed by TCL. + */ + SCBID_ADDR { + size 4 + } + /* + * Address of the array of command descriptors used to store + * information about incoming selections. + */ + TMODE_CMDADDR { + size 4 + } + KERNEL_QINPOS { + size 1 + } + QINPOS { + size 1 + } + QOUTPOS { + size 1 + } + /* + * Offset into the command descriptor array for the next + * available desciptor to use. + */ + TMODE_CMDADDR_NEXT { + size 1 + } + ARG_1 { + size 1 + mask SEND_MSG 0x80 + mask SEND_SENSE 0x40 + mask SEND_REJ 0x20 + mask MSGOUT_PHASEMIS 0x10 + alias RETURN_1 + } + ARG_2 { + size 1 + alias RETURN_2 + } + + /* + * Snapshot of MSG_OUT taken after each message is sent. + */ + LAST_MSG { + size 1 + } + + /* + * Number of times we have filled the CCSGRAM with prefetched + * SG elements. + */ + PREFETCH_CNT { + size 1 + } + + + /* + * These are reserved registers in the card's scratch ram. Some of + * the values are specified in the AHA2742 technical reference manual + * and are initialized by the BIOS at boot time. + */ + SCSICONF { + address 0x05a + size 1 + bit TERM_ENB 0x80 + bit RESET_SCSI 0x40 + mask HSCSIID 0x07 /* our SCSI ID */ + mask HWSCSIID 0x0f /* our SCSI ID if Wide Bus */ + } + HOSTCONF { + address 0x05d + size 1 + } + HA_274_BIOSCTRL { + address 0x05f + size 1 + mask BIOSMODE 0x30 + mask BIOSDISABLED 0x30 + bit CHANNEL_B_PRIMARY 0x08 + } + /* + * Per target SCSI offset values for Ultra2 controllers. + */ + TARG_OFFSET { + address 0x070 + size 16 + } +} + +const SCB_LIST_NULL 0xff + +const CCSGADDR_MAX 0x80 +const CCSGRAM_MAXSEGS 16 + +/* Offsets into the SCBID array where different data is stored */ +const UNTAGGEDSCB_OFFSET 0 +const QOUTFIFO_OFFSET 1 +const QINFIFO_OFFSET 2 + +/* WDTR Message values */ +const BUS_8_BIT 0x00 +const BUS_16_BIT 0x01 +const BUS_32_BIT 0x02 + +/* Offset maximums */ +const MAX_OFFSET_8BIT 0x0f +const MAX_OFFSET_16BIT 0x08 +const MAX_OFFSET_ULTRA2 0x7f +const HOST_MSG 0xff + +/* Target mode command processing constants */ +const CMD_GROUP_CODE_SHIFT 0x05 +const CMD_GROUP0_BYTE_DELTA -4 +const CMD_GROUP2_BYTE_DELTA -6 +const CMD_GROUP4_BYTE_DELTA 4 +const CMD_GROUP5_BYTE_DELTA 11 + +/* + * Downloaded (kernel inserted) constants + */ + +/* + * Number of command descriptors in the command descriptor array. + */ +const TMODE_NUMCMDS download diff --git a/drivers/scsi/aic7xxx_old/aic7xxx.seq b/drivers/scsi/aic7xxx_old/aic7xxx.seq new file mode 100644 index 000000000000..f6fc4b75b5a5 --- /dev/null +++ b/drivers/scsi/aic7xxx_old/aic7xxx.seq @@ -0,0 +1,1539 @@ +/* + * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD. + * + * Copyright (c) 1994-1999 Justin Gibbs. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Where this Software is combined with software released under the terms of + * the GNU General Public License (GPL) and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: aic7xxx.seq,v 1.77 1998/06/28 02:58:57 gibbs Exp $ + */ + +#include "aic7xxx.reg" +#include "scsi_message.h" + +/* + * A few words on the waiting SCB list: + * After starting the selection hardware, we check for reconnecting targets + * as well as for our selection to complete just in case the reselection wins + * bus arbitration. The problem with this is that we must keep track of the + * SCB that we've already pulled from the QINFIFO and started the selection + * on just in case the reselection wins so that we can retry the selection at + * a later time. This problem cannot be resolved by holding a single entry + * in scratch ram since a reconnecting target can request sense and this will + * create yet another SCB waiting for selection. The solution used here is to + * use byte 27 of the SCB as a pseudo-next pointer and to thread a list + * of SCBs that are awaiting selection. Since 0-0xfe are valid SCB indexes, + * SCB_LIST_NULL is 0xff which is out of range. An entry is also added to + * this list everytime a request sense occurs or after completing a non-tagged + * command for which a second SCB has been queued. The sequencer will + * automatically consume the entries. + */ + +reset: + clr SCSISIGO; /* De-assert BSY */ + and SXFRCTL1, ~BITBUCKET; + /* Always allow reselection */ + mvi SCSISEQ, ENRSELI|ENAUTOATNP; + + if ((p->features & AHC_CMD_CHAN) != 0) { + /* Ensure that no DMA operations are in progress */ + clr CCSGCTL; + clr CCSCBCTL; + } + + call clear_target_state; +poll_for_work: + and SXFRCTL0, ~SPIOEN; + if ((p->features & AHC_QUEUE_REGS) == 0) { + mov A, QINPOS; + } +poll_for_work_loop: + if ((p->features & AHC_QUEUE_REGS) == 0) { + and SEQCTL, ~PAUSEDIS; + } + test SSTAT0, SELDO|SELDI jnz selection; + test SCSISEQ, ENSELO jnz poll_for_work; + if ((p->features & AHC_TWIN) != 0) { + /* + * Twin channel devices cannot handle things like SELTO + * interrupts on the "background" channel. So, if we + * are selecting, keep polling the current channel util + * either a selection or reselection occurs. + */ + xor SBLKCTL,SELBUSB; /* Toggle to the other bus */ + test SSTAT0, SELDO|SELDI jnz selection; + test SCSISEQ, ENSELO jnz poll_for_work; + xor SBLKCTL,SELBUSB; /* Toggle back */ + } + cmp WAITING_SCBH,SCB_LIST_NULL jne start_waiting; +test_queue: + /* Has the driver posted any work for us? */ + if ((p->features & AHC_QUEUE_REGS) != 0) { + test QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop; + mov NONE, SNSCB_QOFF; + inc QINPOS; + } else { + or SEQCTL, PAUSEDIS; + cmp KERNEL_QINPOS, A je poll_for_work_loop; + inc QINPOS; + and SEQCTL, ~PAUSEDIS; + } + +/* + * We have at least one queued SCB now and we don't have any + * SCBs in the list of SCBs awaiting selection. If we have + * any SCBs available for use, pull the tag from the QINFIFO + * and get to work on it. + */ + if ((p->flags & AHC_PAGESCBS) != 0) { + mov ALLZEROS call get_free_or_disc_scb; + } + +dequeue_scb: + add A, -1, QINPOS; + mvi QINFIFO_OFFSET call fetch_byte; + + if ((p->flags & AHC_PAGESCBS) == 0) { + /* In the non-paging case, the SCBID == hardware SCB index */ + mov SCBPTR, RETURN_2; + } +dma_queued_scb: +/* + * DMA the SCB from host ram into the current SCB location. + */ + mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; + mov RETURN_2 call dma_scb; + +/* + * Preset the residual fields in case we never go through a data phase. + * This isn't done by the host so we can avoid a DMA to clear these + * fields for the normal case of I/O that completes without underrun + * or overrun conditions. + */ + if ((p->features & AHC_CMD_CHAN) != 0) { + bmov SCB_RESID_DCNT, SCB_DATACNT, 3; + } else { + mov SCB_RESID_DCNT[0],SCB_DATACNT[0]; + mov SCB_RESID_DCNT[1],SCB_DATACNT[1]; + mov SCB_RESID_DCNT[2],SCB_DATACNT[2]; + } + mov SCB_RESID_SGCNT, SCB_SGCOUNT; + +start_scb: + /* + * Place us on the waiting list in case our selection + * doesn't win during bus arbitration. + */ + mov SCB_NEXT,WAITING_SCBH; + mov WAITING_SCBH, SCBPTR; +start_waiting: + /* + * Pull the first entry off of the waiting SCB list. + */ + mov SCBPTR, WAITING_SCBH; + call start_selection; + jmp poll_for_work; + +start_selection: + if ((p->features & AHC_TWIN) != 0) { + and SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */ + and A,SELBUSB,SCB_TCL; /* Get new channel bit */ + or SINDEX,A; + mov SBLKCTL,SINDEX; /* select channel */ + } +initialize_scsiid: + if ((p->features & AHC_ULTRA2) != 0) { + and A, TID, SCB_TCL; /* Get target ID */ + and SCSIID_ULTRA2, OID; /* Clear old target */ + or SCSIID_ULTRA2, A; + } else { + and A, TID, SCB_TCL; /* Get target ID */ + and SCSIID, OID; /* Clear old target */ + or SCSIID, A; + } + mov SCSIDATL, ALLZEROS; /* clear out the latched */ + /* data register, this */ + /* fixes a bug on some */ + /* controllers where the */ + /* last byte written to */ + /* this register can leak */ + /* onto the data bus at */ + /* bad times, such as during */ + /* selection timeouts */ + mvi SCSISEQ, ENSELO|ENAUTOATNO|ENRSELI|ENAUTOATNP ret; + +/* + * Initialize Ultra mode setting and clear the SCSI channel. + * SINDEX should contain any additional bit's the client wants + * set in SXFRCTL0. + */ +initialize_channel: + or SXFRCTL0, CLRSTCNT|CLRCHN, SINDEX; + if ((p->features & AHC_ULTRA) != 0) { +ultra: + mvi SINDEX, ULTRA_ENB+1; + test SAVED_TCL, 0x80 jnz ultra_2; /* Target ID > 7 */ + dec SINDEX; +ultra_2: + mov FUNCTION1,SAVED_TCL; + mov A,FUNCTION1; + test SINDIR, A jz ndx_dtr; + or SXFRCTL0, FAST20; + } +/* + * Initialize SCSIRATE with the appropriate value for this target. + * The SCSIRATE settings for each target are stored in an array + * based at TARG_SCSIRATE. + */ +ndx_dtr: + shr A,4,SAVED_TCL; + if ((p->features & AHC_TWIN) != 0) { + test SBLKCTL,SELBUSB jz ndx_dtr_2; + or SAVED_TCL, SELBUSB; + or A,0x08; /* Channel B entries add 8 */ +ndx_dtr_2: + } + + if ((p->features & AHC_ULTRA2) != 0) { + add SINDEX, TARG_OFFSET, A; + mov SCSIOFFSET, SINDIR; + } + + add SINDEX,TARG_SCSIRATE,A; + mov SCSIRATE,SINDIR ret; + + +selection: + test SSTAT0,SELDO jnz select_out; +/* + * Reselection has been initiated by a target. Make a note that we've been + * reselected, but haven't seen an IDENTIFY message from the target yet. + */ +initiator_reselect: + mvi CLRSINT0, CLRSELDI; + /* XXX test for and handle ONE BIT condition */ + and SAVED_TCL, SELID_MASK, SELID; + mvi CLRSINT1,CLRBUSFREE; + or SIMODE1, ENBUSFREE; /* + * We aren't expecting a + * bus free, so interrupt + * the kernel driver if it + * happens. + */ + mvi SPIOEN call initialize_channel; + mvi MSG_OUT, MSG_NOOP; /* No message to send */ + jmp ITloop; + +/* + * After the selection, remove this SCB from the "waiting SCB" + * list. This is achieved by simply moving our "next" pointer into + * WAITING_SCBH. Our next pointer will be set to null the next time this + * SCB is used, so don't bother with it now. + */ +select_out: + /* Turn off the selection hardware */ + mvi SCSISEQ, ENRSELI|ENAUTOATNP; /* + * ATN on parity errors + * for "in" phases + */ + mvi CLRSINT0, CLRSELDO; + mov SCBPTR, WAITING_SCBH; + mov WAITING_SCBH,SCB_NEXT; + mov SAVED_TCL, SCB_TCL; + mvi CLRSINT1,CLRBUSFREE; + or SIMODE1, ENBUSFREE; /* + * We aren't expecting a + * bus free, so interrupt + * the kernel driver if it + * happens. + */ + mvi SPIOEN call initialize_channel; +/* + * As soon as we get a successful selection, the target should go + * into the message out phase since we have ATN asserted. + */ + mvi MSG_OUT, MSG_IDENTIFYFLAG; + or SEQ_FLAGS, IDENTIFY_SEEN; + +/* + * Main loop for information transfer phases. Wait for the target + * to assert REQ before checking MSG, C/D and I/O for the bus phase. + */ +ITloop: + call phase_lock; + + mov A, LASTPHASE; + + 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; + cmp A,P_MESGIN je p_mesgin; + + mvi INTSTAT,BAD_PHASE; /* unknown phase - signal driver */ + jmp ITloop; /* Try reading the bus again. */ + +await_busfree: + and SIMODE1, ~ENBUSFREE; + call clear_target_state; + mov NONE, SCSIDATL; /* Ack the last byte */ + and SXFRCTL0, ~SPIOEN; + test SSTAT1,REQINIT|BUSFREE jz .; + test SSTAT1, BUSFREE jnz poll_for_work; + mvi INTSTAT, BAD_PHASE; + +clear_target_state: + /* + * We assume that the kernel driver may reset us + * at any time, even in the middle of a DMA, so + * clear DFCNTRL too. + */ + clr DFCNTRL; + + /* + * We don't know the target we will connect to, + * so default to narrow transfers to avoid + * parity problems. + */ + if ((p->features & AHC_ULTRA2) != 0) { + bmov SCSIRATE, ALLZEROS, 2; + } else { + clr SCSIRATE; + and SXFRCTL0, ~(FAST20); + } + mvi LASTPHASE, P_BUSFREE; + /* clear target specific flags */ + clr SEQ_FLAGS ret; + + +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. + */ + 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) { + mvi DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN; + } else { + 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 */ + /* + * 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) { + bmov HADDR, SCB_DATAPTR, 7; + bmov SG_COUNT, SCB_SGCOUNT, 5; + if ((p->features & AHC_ULTRA2) == 0) { + bmov STCNT, HCNT, 3; + } + } 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_ULTRA2) != 0) { + bmov HCNT, ALLONES, 3; + } + if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { + bmov STCNT, ALLONES, 3; + } + if ((p->features & AHC_CMD_CHAN) == 0) { + mvi STCNT[0], 0xFF; + mvi STCNT[1], 0xFF; + mvi STCNT[2], 0xFF; + } + +data_phase_inbounds: +/* If we are the last SG block, tell the hardware. */ + if ((p->features & AHC_ULTRA2) != 0) { + shl A, 2, SG_COUNT; + cmp SG_COUNT,0x01 jne data_phase_wideodd; + or A, LAST_SEG; + } else { + cmp SG_COUNT,0x01 jne data_phase_wideodd; + and DMAPARAMS, ~WIDEODD; + } +data_phase_wideodd: + if ((p->features & AHC_ULTRA2) != 0) { + mov SG_CACHEPTR, A; + mov DFCNTRL, DMAPARAMS; /* start the operation */ + test SXFRCTL1, BITBUCKET jnz data_phase_overrun; +u2_preload_wait: + test SSTAT1, PHASEMIS jnz u2_phasemis; + test DFSTATUS, PRELOAD_AVAIL jz u2_preload_wait; + } 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; + } +/* + * Advance the scatter-gather pointers + */ +sg_advance: + if ((p->features & AHC_ULTRA2) != 0) { + cmp SG_COUNT, 0x01 je u2_data_phase_finish; + } else { + dec SG_COUNT; + test SG_COUNT, 0xff jz data_phase_finish; + } + + 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; + if ((p->features & AHC_ULTRA2) == 0) { + bmov STCNT, HCNT, 3; + } else { + dec SG_COUNT; + } + } else { + mvi DINDEX, HADDR; + mvi SG_NEXT call bcopy_4; + + mvi HCNT[0],SG_SIZEOF; + clr HCNT[1]; + clr HCNT[2]; + + 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 DINDEX, 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; + + if ((p->features & AHC_ULTRA2) != 0) { + jmp data_phase_loop; + } else { + test SSTAT1, REQINIT jz .; + test SSTAT1,PHASEMIS jz data_phase_loop; + } + + +/* + * 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. + */ + if ((p->features & AHC_ULTRA2) != 0) { +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 data_phase_loop; +u2_phasemis: + call ultra2_dmafinish; + test SG_CACHEPTR, LAST_SEG_DONE jnz data_phase_finish; + test SSTAT2, SHVALID jnz u2_fixup_residual; + mvi INTSTAT, SEQ_SG_FIXUP; + jmp data_phase_finish; +u2_fixup_residual: + shr ARG_1, 2, SG_CACHEPTR; +u2_phasemis_loop: + and A, 0x3f, SG_COUNT; + cmp ARG_1, A je data_phase_finish; +/* + * 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; + } + +data_phase_finish: +/* + * After a DMA finishes, save the SG and STCNT residuals back into the SCB + * 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_CMD_CHAN) != 0) { + bmov SCB_RESID_DCNT, STCNT, 3; + mov SCB_RESID_SGCNT, SG_COUNT; + if ((p->features & AHC_ULTRA2) != 0) { + or SXFRCTL0, CLRSTCNT|CLRCHN; + } + } else { + mov SCB_RESID_DCNT[0],STCNT[0]; + mov SCB_RESID_DCNT[1],STCNT[1]; + mov SCB_RESID_DCNT[2],STCNT[2]; + mov SCB_RESID_SGCNT, SG_COUNT; + } + + jmp ITloop; + +data_phase_overrun: +/* + * Turn off BITBUCKET mode and notify the host + */ + if ((p->features & AHC_ULTRA2) != 0) { +/* + * Wait for the target to quit transferring data on the SCSI bus + */ + test SSTAT1, PHASEMIS jz .; + call ultra2_dmafinish; + } + and SXFRCTL1, ~BITBUCKET; + mvi INTSTAT,DATA_OVERRUN; + 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. + */ + if ((p->features & AHC_ULTRA2) != 0) { +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; + } +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; + } + +/* + * Command phase. Set up the DMA registers and let 'er rip. + */ +p_command: + call assert; + +/* + * Load HADDR and HCNT. + */ + if ((p->features & AHC_CMD_CHAN) != 0) { + bmov HADDR, SCB_CMDPTR, 5; + bmov HCNT[1], ALLZEROS, 2; + if ((p->features & AHC_ULTRA2) == 0) { + bmov STCNT, HCNT, 3; + } + } else { + mvi DINDEX, HADDR; + mvi SCB_CMDPTR call bcopy_5; + clr HCNT[1]; + clr HCNT[2]; + call set_stcnt_from_hcnt; + } + + if ((p->features & AHC_ULTRA2) == 0) { + mvi (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET) call dma; + } else { + mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION); + test SSTAT0, SDONE jnz .; +p_command_dma_loop: + test SSTAT0, SDONE jnz p_command_ultra2_dma_done; + test SSTAT1,PHASEMIS jz p_command_dma_loop; /* ie. underrun */ +p_command_ultra2_dma_done: + test SCSISIGI, REQI jz p_command_ultra2_shutdown; + test SSTAT1, (PHASEMIS|REQINIT) jz p_command_ultra2_dma_done; +p_command_ultra2_shutdown: + and DFCNTRL, ~(HDMAEN|SCSIEN); + test DFCNTRL, (HDMAEN|SCSIEN) jnz .; + or SXFRCTL0, CLRSTCNT|CLRCHN; + } + jmp ITloop; + +/* + * Status phase. Wait for the data byte to appear, then read it + * and store it into the SCB. + */ +p_status: + call assert; + + mov SCB_TARGET_STATUS, SCSIDATL; + jmp ITloop; + +/* + * Message out phase. If MSG_OUT is 0x80, build I full indentify message + * sequence and send it to the target. In addition, if the MK_MESSAGE bit + * is set in the SCB_CONTROL byte, interrupt the host and allow it to send + * it's own message. + * + * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message. + * This is done to allow the hsot to send messages outside of an identify + * sequence while protecting the seqencer from testing the MK_MESSAGE bit + * on an SCB that might not be for the current nexus. (For example, a + * BDR message in responce to a bad reselection would leave us pointed to + * an SCB that doesn't have anything to do with the current target). + * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag, + * bus device reset). + * + * When there are no messages to send, MSG_OUT should be set to MSG_NOOP, + * in case the target decides to put us in this phase for some strange + * reason. + */ +p_mesgout_retry: + or SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */ +p_mesgout: + mov SINDEX, MSG_OUT; + cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host; +p_mesgout_identify: + if ((p->features & AHC_WIDE) != 0) { + and SINDEX,0xf,SCB_TCL; /* lun */ + } else { + and SINDEX,0x7,SCB_TCL; /* lun */ + } + and A,DISCENB,SCB_CONTROL; /* mask off disconnect privledge */ + or SINDEX,A; /* or in disconnect privledge */ + or SINDEX,MSG_IDENTIFYFLAG; +p_mesgout_mk_message: + test SCB_CONTROL,MK_MESSAGE jz p_mesgout_tag; + mov SCSIDATL, SINDEX; /* Send the last byte */ + jmp p_mesgout_from_host + 1;/* Skip HOST_MSG test */ +/* + * Send a tag message if TAG_ENB is set in the SCB control block. + * Use SCB_TAG (the position in the kernel's SCB array) as the tag value. + */ +p_mesgout_tag: + test SCB_CONTROL,TAG_ENB jz p_mesgout_onebyte; + mov SCSIDATL, SINDEX; /* Send the identify message */ + call phase_lock; + cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; + and SCSIDATL,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL; + call phase_lock; + cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; + mov SCB_TAG jmp p_mesgout_onebyte; +/* + * Interrupt the driver, and allow it to send a message + * if it asks. + */ +p_mesgout_from_host: + cmp SINDEX, HOST_MSG jne p_mesgout_onebyte; + mvi INTSTAT,AWAITING_MSG; + nop; + /* + * Did the host detect a phase change? + */ + cmp RETURN_1, MSGOUT_PHASEMIS je p_mesgout_done; + +p_mesgout_onebyte: + mvi CLRSINT1, CLRATNO; + mov SCSIDATL, SINDEX; + +/* + * If the next bus phase after ATN drops is a message out, it means + * that the target is requesting that the last message(s) be resent. + */ + call phase_lock; + cmp LASTPHASE, P_MESGOUT je p_mesgout_retry; + +p_mesgout_done: + mvi CLRSINT1,CLRATNO; /* Be sure to turn ATNO off */ + mov LAST_MSG, MSG_OUT; + cmp MSG_OUT, MSG_IDENTIFYFLAG jne . + 2; + and SCB_CONTROL, ~MK_MESSAGE; + mvi MSG_OUT, MSG_NOOP; /* No message left */ + jmp ITloop; + +/* + * Message in phase. Bytes are read using Automatic PIO mode. + */ +p_mesgin: + mvi ACCUM call inb_first; /* read the 1st message byte */ + + test A,MSG_IDENTIFYFLAG jnz mesgin_identify; + cmp A,MSG_DISCONNECT je mesgin_disconnect; + cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs; + cmp ALLZEROS,A je mesgin_complete; + cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs; + cmp A,MSG_EXTENDED je mesgin_extended; + cmp A,MSG_MESSAGE_REJECT je mesgin_reject; + cmp A,MSG_NOOP je mesgin_done; + cmp A,MSG_IGN_WIDE_RESIDUE je mesgin_wide_residue; + +rej_mesgin: +/* + * We have no idea what this message in is, so we issue a message reject + * and hope for the best. In any case, rejection should be a rare + * occurrence - signal the driver when it happens. + */ + mvi INTSTAT,SEND_REJECT; /* let driver know */ + + mvi MSG_MESSAGE_REJECT call mk_mesg; + +mesgin_done: + mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ + jmp ITloop; + + +mesgin_complete: +/* + * We got a "command complete" message, so put the SCB_TAG into the QOUTFIFO, + * and trigger a completion interrupt. Before doing so, check to see if there + * is a residual or the status byte is something other than STATUS_GOOD (0). + * In either of these conditions, we upload the SCB back to the host so it can + * process this information. In the case of a non zero status byte, we + * additionally interrupt the kernel driver synchronously, allowing it to + * decide if sense should be retrieved. If the kernel driver wishes to request + * sense, it will fill the kernel SCB with a request sense command and set + * RETURN_1 to SEND_SENSE. If RETURN_1 is set to SEND_SENSE we redownload + * the SCB, and process it as the next command by adding it to the waiting list. + * If the kernel driver does not wish to request sense, it need only clear + * RETURN_1, and the command is allowed to complete normally. We don't bother + * to post to the QOUTFIFO in the error cases since it would require extra + * work in the kernel driver to ensure that the entry was removed before the + * command complete code tried processing it. + */ + +/* + * First check for residuals + */ + test SCB_RESID_SGCNT,0xff jnz upload_scb; + test SCB_TARGET_STATUS,0xff jz complete; /* Good Status? */ +upload_scb: + mvi DMAPARAMS, FIFORESET; + mov SCB_TAG call dma_scb; +check_status: + test SCB_TARGET_STATUS,0xff jz complete; /* Just a residual? */ + mvi INTSTAT,BAD_STATUS; /* let driver know */ + nop; + cmp RETURN_1, SEND_SENSE jne complete; + /* This SCB becomes the next to execute as it will retrieve sense */ + mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; + mov SCB_TAG call dma_scb; +add_to_waiting_list: + mov SCB_NEXT,WAITING_SCBH; + mov WAITING_SCBH, SCBPTR; + /* + * Prepare our selection hardware before the busfree so we have a + * high probability of winning arbitration. + */ + call start_selection; + jmp await_busfree; + +complete: + /* If we are untagged, clear our address up in host ram */ + test SCB_CONTROL, TAG_ENB jnz complete_post; + mov A, SAVED_TCL; + mvi UNTAGGEDSCB_OFFSET call post_byte_setup; + mvi SCB_LIST_NULL call post_byte; + +complete_post: + /* Post the SCB and issue an interrupt */ + if ((p->features & AHC_QUEUE_REGS) != 0) { + mov A, SDSCB_QOFF; + } else { + mov A, QOUTPOS; + } + mvi QOUTFIFO_OFFSET call post_byte_setup; + mov SCB_TAG call post_byte; + if ((p->features & AHC_QUEUE_REGS) == 0) { + inc QOUTPOS; + } + mvi INTSTAT,CMDCMPLT; + +add_to_free_list: + call add_scb_to_free_list; + jmp await_busfree; + +/* + * Is it an extended message? Copy the message to our message buffer and + * notify the host. The host will tell us whether to reject this message, + * respond to it with the message that the host placed in our message buffer, + * or simply to do nothing. + */ +mesgin_extended: + mvi INTSTAT,EXTENDED_MSG; /* let driver know */ + jmp ITloop; + +/* + * Is it a disconnect message? Set a flag in the SCB to remind us + * and await the bus going free. + */ +mesgin_disconnect: + or SCB_CONTROL,DISCONNECTED; + call add_scb_to_disc_list; + jmp await_busfree; + +/* + * Save data pointers message: + * Copying RAM values back to SCB, for Save Data Pointers message, but + * only if we've actually been into a data phase to change them. This + * protects against bogus data in scratch ram and the residual counts + * since they are only initialized when we go into data_in or data_out. + */ +mesgin_sdptrs: + test SEQ_FLAGS, DPHASE jz mesgin_done; + /* + * The SCB SGPTR becomes the next one we'll download, + * and the SCB DATAPTR becomes the current SHADDR. + * Use the residual number since STCNT is corrupted by + * any message transfer. + */ + if ((p->features & AHC_CMD_CHAN) != 0) { + bmov SCB_SGCOUNT, SG_COUNT, 5; + bmov SCB_DATAPTR, SHADDR, 4; + bmov SCB_DATACNT, SCB_RESID_DCNT, 3; + } else { + mvi DINDEX, SCB_SGCOUNT; + mvi SG_COUNT call bcopy_5; + mvi DINDEX, SCB_DATAPTR; + mvi SHADDR call bcopy_4; + mvi SCB_RESID_DCNT call bcopy_3; + } + jmp mesgin_done; + +/* + * Restore pointers message? Data pointers are recopied from the + * SCB anytime we enter a data phase for the first time, so all + * we need to do is clear the DPHASE flag and let the data phase + * code do the rest. + */ +mesgin_rdptrs: + and SEQ_FLAGS, ~DPHASE; /* + * We'll reload them + * the next time through + * the dataphase. + */ + jmp mesgin_done; + +/* + * Identify message? For a reconnecting target, this tells us the lun + * that the reconnection is for - find the correct SCB and switch to it, + * clearing the "disconnected" bit so we don't "find" it by accident later. + */ +mesgin_identify: + + if ((p->features & AHC_WIDE) != 0) { + and A,0x0f; /* lun in lower four bits */ + } else { + and A,0x07; /* lun in lower three bits */ + } + or SAVED_TCL,A; /* SAVED_TCL should be complete now */ + + mvi ARG_2, SCB_LIST_NULL; /* SCBID of prev SCB in disc List */ + call get_untagged_SCBID; + cmp ARG_1, SCB_LIST_NULL je snoop_tag; + if ((p->flags & AHC_PAGESCBS) != 0) { + test SEQ_FLAGS, SCBPTR_VALID jz use_retrieveSCB; + } + /* + * If the SCB was found in the disconnected list (as is + * always the case in non-paging scenarios), SCBPTR is already + * set to the correct SCB. So, simply setup the SCB and get + * on with things. + */ + mov SCBPTR call rem_scb_from_disc_list; + jmp setup_SCB; +/* + * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message. + * If we get one, we use the tag returned to find the proper + * SCB. With SCB paging, this requires using search for both tagged + * and non-tagged transactions since the SCB may exist in any slot. + * If we're not using SCB paging, we can use the tag as the direct + * index to the SCB. + */ +snoop_tag: + mov NONE,SCSIDATL; /* ACK Identify MSG */ +snoop_tag_loop: + call phase_lock; + cmp LASTPHASE, P_MESGIN jne not_found; + cmp SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found; +get_tag: + mvi ARG_1 call inb_next; /* tag value */ + +use_retrieveSCB: + call retrieveSCB; +setup_SCB: + mov A, SAVED_TCL; + cmp SCB_TCL, A jne not_found_cleanup_scb; + test SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb; + and SCB_CONTROL,~DISCONNECTED; + or SEQ_FLAGS,IDENTIFY_SEEN; /* make note of IDENTIFY */ + /* See if the host wants to send a message upon reconnection */ + test SCB_CONTROL, MK_MESSAGE jz mesgin_done; + and SCB_CONTROL, ~MK_MESSAGE; + mvi HOST_MSG call mk_mesg; + jmp mesgin_done; + +not_found_cleanup_scb: + test SCB_CONTROL, DISCONNECTED jz . + 3; + call add_scb_to_disc_list; + jmp not_found; + call add_scb_to_free_list; +not_found: + mvi INTSTAT, NO_MATCH; + mvi MSG_BUS_DEV_RESET call mk_mesg; + jmp mesgin_done; + +/* + * Message reject? Let the kernel driver handle this. If we have an + * outstanding WDTR or SDTR negotiation, assume that it's a response from + * the target selecting 8bit or asynchronous transfer, otherwise just ignore + * it since we have no clue what it pertains to. + */ +mesgin_reject: + mvi INTSTAT, REJECT_MSG; + jmp mesgin_done; + +/* + * Wide Residue. We handle the simple cases, but pass of the one hard case + * to the kernel (when the residue byte happened to cause us to advance our + * sg element array, so we know have to back that advance out). + */ +mesgin_wide_residue: + mvi ARG_1 call inb_next; /* ACK the wide_residue and get */ + /* the size byte */ +/* + * In order for this to be reliable, we have to do all sorts of horrible + * magic in terms of resetting the datafifo and reloading the shadow layer + * with the correct new values (so that a subsequent save data pointers + * message will do the right thing). We let the kernel do that work. + */ + mvi INTSTAT, WIDE_RESIDUE; + jmp mesgin_done; + +/* + * [ ADD MORE MESSAGE HANDLING HERE ] + */ + +/* + * Locking the driver out, build a one-byte message passed in SINDEX + * if there is no active message already. SINDEX is returned intact. + */ +mk_mesg: + or SCSISIGO,ATNO,LASTPHASE;/* turn on ATNO */ + mov MSG_OUT,SINDEX ret; + +/* + * Functions to read data in Automatic PIO mode. + * + * According to Adaptec's documentation, an ACK is not sent on input from + * the target until SCSIDATL is read from. So we wait until SCSIDATL is + * latched (the usual way), then read the data byte directly off the bus + * using SCSIBUSL. When we have pulled the ATN line, or we just want to + * acknowledge the byte, then we do a dummy read from SCISDATL. The SCSI + * spec guarantees that the target will hold the data byte on the bus until + * we send our ACK. + * + * The assumption here is that these are called in a particular sequence, + * and that REQ is already set when inb_first is called. inb_{first,next} + * use the same calling convention as inb. + */ + +inb_next: + mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ +inb_next_wait: + /* + * If there is a parity error, wait for the kernel to + * see the interrupt and prepare our message response + * before continuing. + */ + test SSTAT1, REQINIT jz inb_next_wait; + test SSTAT1, SCSIPERR jnz .; + and LASTPHASE, PHASE_MASK, SCSISIGI; + cmp LASTPHASE, P_MESGIN jne mesgin_phasemis; +inb_first: + mov DINDEX,SINDEX; + mov DINDIR,SCSIBUSL ret; /*read byte directly from bus*/ +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 + */ + mvi INTSTAT, MSGIN_PHASEMIS; + jmp ITloop; + +/* + * DMA data transfer. HADDR and HCNT must be loaded first, and + * SINDEX should contain the value to load DFCNTRL with - 0x3d for + * host->scsi, or 0x39 for scsi->host. The SCSI channel is cleared + * during initialization. + */ +if ((p->features & AHC_ULTRA2) == 0) { +dma: + mov DFCNTRL,SINDEX; +dma_loop: + test SSTAT0,DMADONE jnz dma_dmadone; + test SSTAT1,PHASEMIS jz dma_loop; /* ie. underrun */ +dma_phasemis: + test SSTAT0,SDONE jnz dma_checkfifo; + mov SINDEX,ALLZEROS; /* Notify caller of phasemiss */ + +/* + * We will be "done" DMAing when the transfer count goes to zero, or + * the target changes the phase (in light of this, it makes sense that + * the DMA circuitry doesn't ACK when PHASEMIS is active). If we are + * doing a SCSI->Host transfer, the data FIFO should be flushed auto- + * magically on STCNT=0 or a phase change, so just wait for FIFO empty + * status. + */ +dma_checkfifo: + test DFCNTRL,DIRECTION jnz dma_fifoempty; +dma_fifoflush: + test DFSTATUS,FIFOEMP jz dma_fifoflush; + +dma_fifoempty: + /* Don't clobber an inprogress host data transfer */ + test DFSTATUS, MREQPEND jnz dma_fifoempty; +/* + * Now shut the DMA enables off and make sure that the DMA enables are + * actually off first lest we get an ILLSADDR. + */ +dma_dmadone: + cmp LASTPHASE, P_COMMAND je dma_await_nreq; + test SCSIRATE, 0x0f jnz dma_shutdown; +dma_await_nreq: + test SCSISIGI, REQI jz dma_shutdown; + test SSTAT1, (PHASEMIS|REQINIT) jz dma_await_nreq; +dma_shutdown: + and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN); +dma_halt: + /* + * Some revisions of the aic7880 have a problem where, if the + * data fifo is full, but the PCI input latch is not empty, + * HDMAEN cannot be cleared. The fix used here is to attempt + * to drain the data fifo until there is space for the input + * latch to drain and HDMAEN de-asserts. + */ + if ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0) { + mov NONE, DFDAT; + } + test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt; +} +return: + ret; + +/* + * Assert that if we've been reselected, then we've seen an IDENTIFY + * message. + */ +assert: + test SEQ_FLAGS,IDENTIFY_SEEN jnz return; /* seen IDENTIFY? */ + + mvi INTSTAT,NO_IDENT ret; /* no - tell the kernel */ + +/* + * Locate a disconnected SCB either by SAVED_TCL (ARG_1 is SCB_LIST_NULL) + * or by the SCBID ARG_1. The search begins at the SCB index passed in + * via SINDEX which is an SCB that must be on the disconnected list. If + * the SCB cannot be found, SINDEX will be SCB_LIST_NULL, otherwise, SCBPTR + * is set to the proper SCB. + */ +findSCB: + mov SCBPTR,SINDEX; /* Initialize SCBPTR */ + cmp ARG_1, SCB_LIST_NULL jne findSCB_by_SCBID; + mov A, SAVED_TCL; + mvi SCB_TCL jmp findSCB_loop; /* &SCB_TCL -> SINDEX */ +findSCB_by_SCBID: + mov A, ARG_1; /* Tag passed in ARG_1 */ + mvi SCB_TAG jmp findSCB_loop; /* &SCB_TAG -> SINDEX */ +findSCB_next: + mov ARG_2, SCBPTR; + cmp SCB_NEXT, SCB_LIST_NULL je notFound; + mov SCBPTR,SCB_NEXT; + dec SINDEX; /* Last comparison moved us too far */ +findSCB_loop: + cmp SINDIR, A jne findSCB_next; + mov SINDEX, SCBPTR ret; +notFound: + mvi SINDEX, SCB_LIST_NULL ret; + +/* + * Retrieve an SCB by SCBID first searching the disconnected list falling + * back to DMA'ing the SCB down from the host. This routine assumes that + * ARG_1 is the SCBID of interrest and that SINDEX is the position in the + * disconnected list to start the search from. If SINDEX is SCB_LIST_NULL, + * we go directly to the host for the SCB. + */ +retrieveSCB: + test SEQ_FLAGS, SCBPTR_VALID jz retrieve_from_host; + mov SCBPTR call findSCB; /* Continue the search */ + cmp SINDEX, SCB_LIST_NULL je retrieve_from_host; + +/* + * This routine expects SINDEX to contain the index of the SCB to be + * removed, SCBPTR to be pointing to that SCB, and ARG_2 to be the + * SCBID of the SCB just previous to this one in the list or SCB_LIST_NULL + * if it is at the head. + */ +rem_scb_from_disc_list: +/* Remove this SCB from the disconnection list */ + cmp ARG_2, SCB_LIST_NULL je rHead; + mov DINDEX, SCB_NEXT; + mov SCBPTR, ARG_2; + mov SCB_NEXT, DINDEX; + mov SCBPTR, SINDEX ret; +rHead: + mov DISCONNECTED_SCBH,SCB_NEXT ret; + +retrieve_from_host: +/* + * We didn't find it. Pull an SCB and DMA down the one we want. + * We should never get here in the non-paging case. + */ + mov ALLZEROS call get_free_or_disc_scb; + mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; + /* Jump instead of call as we want to return anyway */ + mov ARG_1 jmp dma_scb; + +/* + * Determine whether a target is using tagged or non-tagged transactions + * by first looking for a matching transaction based on the TCL and if + * that fails, looking up this device in the host's untagged SCB array. + * The TCL to search for is assumed to be in SAVED_TCL. The value is + * returned in ARG_1 (SCB_LIST_NULL for tagged, SCBID for non-tagged). + * The SCBPTR_VALID bit is set in SEQ_FLAGS if we found the information + * in an SCB instead of having to go to the host. + */ +get_untagged_SCBID: + cmp DISCONNECTED_SCBH, SCB_LIST_NULL je get_SCBID_from_host; + mvi ARG_1, SCB_LIST_NULL; + mov DISCONNECTED_SCBH call findSCB; + cmp SINDEX, SCB_LIST_NULL je get_SCBID_from_host; + or SEQ_FLAGS, SCBPTR_VALID;/* Was in disconnected list */ + test SCB_CONTROL, TAG_ENB jnz . + 2; + mov ARG_1, SCB_TAG ret; + mvi ARG_1, SCB_LIST_NULL ret; + +/* + * Fetch a byte from host memory given an index of (A + (256 * SINDEX)) + * and a base address of SCBID_ADDR. The byte is returned in RETURN_2. + */ +fetch_byte: + mov ARG_2, SINDEX; + if ((p->features & AHC_CMD_CHAN) != 0) { + mvi DINDEX, CCHADDR; + mvi SCBID_ADDR call set_1byte_addr; + mvi CCHCNT, 1; + mvi CCSGCTL, CCSGEN|CCSGRESET; + test CCSGCTL, CCSGDONE jz .; + mvi CCSGCTL, CCSGRESET; + bmov RETURN_2, CCSGRAM, 1 ret; + } else { + mvi DINDEX, HADDR; + mvi SCBID_ADDR call set_1byte_addr; + mvi HCNT[0], 1; + clr HCNT[1]; + clr HCNT[2]; + mvi DFCNTRL, HDMAEN|DIRECTION|FIFORESET; + call dma_finish; + mov RETURN_2, DFDAT ret; + } + +/* + * Prepare the hardware to post a byte to host memory given an + * index of (A + (256 * SINDEX)) and a base address of SCBID_ADDR. + */ +post_byte_setup: + mov ARG_2, SINDEX; + if ((p->features & AHC_CMD_CHAN) != 0) { + mvi DINDEX, CCHADDR; + mvi SCBID_ADDR call set_1byte_addr; + mvi CCHCNT, 1; + mvi CCSCBCTL, CCSCBRESET ret; + } else { + mvi DINDEX, HADDR; + mvi SCBID_ADDR call set_1byte_addr; + mvi HCNT[0], 1; + clr HCNT[1]; + clr HCNT[2]; + mvi DFCNTRL, FIFORESET ret; + } + +post_byte: + if ((p->features & AHC_CMD_CHAN) != 0) { + bmov CCSCBRAM, SINDEX, 1; + or CCSCBCTL, CCSCBEN|CCSCBRESET; + test CCSCBCTL, CCSCBDONE jz .; + clr CCSCBCTL ret; + } else { + mov DFDAT, SINDEX; + or DFCNTRL, HDMAEN|FIFOFLUSH; + jmp dma_finish; + } + +get_SCBID_from_host: + mov A, SAVED_TCL; + mvi UNTAGGEDSCB_OFFSET call fetch_byte; + mov RETURN_1, RETURN_2 ret; + +phase_lock: + test SSTAT1, REQINIT jz phase_lock; + test SSTAT1, SCSIPERR jnz phase_lock; + and SCSISIGO, PHASE_MASK, SCSISIGI; + and LASTPHASE, PHASE_MASK, SCSISIGI ret; + +if ((p->features & AHC_CMD_CHAN) == 0) { +set_stcnt_from_hcnt: + mov STCNT[0], HCNT[0]; + mov STCNT[1], HCNT[1]; + mov STCNT[2], HCNT[2] ret; + +bcopy_7: + mov DINDIR, SINDIR; + mov DINDIR, SINDIR; +bcopy_5: + mov DINDIR, SINDIR; +bcopy_4: + mov DINDIR, SINDIR; +bcopy_3: + mov DINDIR, SINDIR; + mov DINDIR, SINDIR; + mov DINDIR, SINDIR ret; +} + +/* + * Setup addr assuming that A is an index into + * an array of 32byte objects, SINDEX contains + * the base address of that array, and DINDEX + * contains the base address of the location + * to store the indexed address. + */ +set_32byte_addr: + shr ARG_2, 3, A; + shl A, 5; +/* + * Setup addr assuming that A + (ARG_1 * 256) is an + * index into an array of 1byte objects, SINDEX contains + * the base address of that array, and DINDEX contains + * the base address of the location to store the computed + * address. + */ +set_1byte_addr: + add DINDIR, A, SINDIR; + mov A, ARG_2; + adc DINDIR, A, SINDIR; + clr A; + adc DINDIR, A, SINDIR; + adc DINDIR, A, SINDIR ret; + +/* + * Either post or fetch and SCB from host memory based on the + * DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX. + */ +dma_scb: + mov A, SINDEX; + if ((p->features & AHC_CMD_CHAN) != 0) { + mvi DINDEX, CCHADDR; + mvi HSCB_ADDR call set_32byte_addr; + mov CCSCBPTR, SCBPTR; + mvi CCHCNT, 32; + test DMAPARAMS, DIRECTION jz dma_scb_tohost; + mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET; + cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .; + jmp dma_scb_finish; +dma_scb_tohost: + if ((p->features & AHC_ULTRA2) == 0) { + mvi CCSCBCTL, CCSCBRESET; + bmov CCSCBRAM, SCB_CONTROL, 32; + or CCSCBCTL, CCSCBEN|CCSCBRESET; + test CCSCBCTL, CCSCBDONE jz .; + } + if ((p->features & AHC_ULTRA2) != 0) { + 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 .; + } + } +dma_scb_finish: + clr CCSCBCTL; + test CCSCBCTL, CCARREN|CCSCBEN jnz .; + ret; + } + if ((p->features & AHC_CMD_CHAN) == 0) { + mvi DINDEX, HADDR; + mvi HSCB_ADDR call set_32byte_addr; + mvi HCNT[0], 32; + clr HCNT[1]; + clr HCNT[2]; + mov DFCNTRL, DMAPARAMS; + test DMAPARAMS, DIRECTION jnz dma_scb_fromhost; + /* Fill it with the SCB data */ +copy_scb_tofifo: + mvi SINDEX, SCB_CONTROL; + add A, 32, SINDEX; +copy_scb_tofifo_loop: + mov DFDAT,SINDIR; + mov DFDAT,SINDIR; + mov DFDAT,SINDIR; + mov DFDAT,SINDIR; + mov DFDAT,SINDIR; + mov DFDAT,SINDIR; + mov DFDAT,SINDIR; + mov DFDAT,SINDIR; + cmp SINDEX, A jne copy_scb_tofifo_loop; + or DFCNTRL, HDMAEN|FIFOFLUSH; + jmp dma_finish; +dma_scb_fromhost: + 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 DINDIR,DFDAT; + mov DINDIR,DFDAT; + mov DINDIR,DFDAT; + mov DINDIR,DFDAT; + mov DINDIR,DFDAT; + mov DINDIR,DFDAT; + mov DINDIR,DFDAT ret; + } + + +/* + * Wait for DMA from host memory to data FIFO to complete, then disable + * DMA and wait for it to acknowledge that it's off. + */ +if ((p->features & AHC_CMD_CHAN) == 0) { +dma_finish: + test DFSTATUS,HDONE jz dma_finish; + /* Turn off DMA */ + and DFCNTRL, ~HDMAEN; + test DFCNTRL, HDMAEN jnz .; + ret; +} + +add_scb_to_free_list: + if ((p->flags & AHC_PAGESCBS) != 0) { + mov SCB_NEXT, FREE_SCBH; + mov FREE_SCBH, SCBPTR; + } + mvi SCB_TAG, SCB_LIST_NULL ret; + +if ((p->flags & AHC_PAGESCBS) != 0) { +get_free_or_disc_scb: + cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb; + cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb; +return_error: + mvi SINDEX, SCB_LIST_NULL ret; +dequeue_disc_scb: + mov SCBPTR, DISCONNECTED_SCBH; +dma_up_scb: + mvi DMAPARAMS, FIFORESET; + mov SCB_TAG call dma_scb; +unlink_disc_scb: + mov DISCONNECTED_SCBH, SCB_NEXT ret; +dequeue_free_scb: + mov SCBPTR, FREE_SCBH; + mov FREE_SCBH, SCB_NEXT ret; +} + +add_scb_to_disc_list: +/* + * Link this SCB into the DISCONNECTED list. This list holds the + * candidates for paging out an SCB if one is needed for a new command. + * Modifying the disconnected list is a critical(pause dissabled) section. + */ + mov SCB_NEXT, DISCONNECTED_SCBH; + mov DISCONNECTED_SCBH, SCBPTR ret; diff --git a/drivers/scsi/aic7xxx_old/aic7xxx_proc.c b/drivers/scsi/aic7xxx_old/aic7xxx_proc.c new file mode 100644 index 000000000000..3bf334931a8a --- /dev/null +++ b/drivers/scsi/aic7xxx_old/aic7xxx_proc.c @@ -0,0 +1,374 @@ +/*+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 \ +" 0 - 4K 4 - 16K 16 - 64K 64 - 256K 256K - 1M 1M+" + +#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*************************************************************************/ +static 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 ( struct Scsi_Host *HBAptr, char *buffer, char **start, off_t offset, int length, + int inout) +{ + struct aic7xxx_host *p; + struct aic_dev_data *aic_dev; + struct scsi_device *sdptr; + int size = 0; + unsigned char i; + unsigned char tindex; + + for(p=first_aic7xxx; p && p->host != HBAptr; p=p->next) + ; + + if (!p) + { + size += sprintf(buffer, "Can't find adapter for host number %d\n", HBAptr->host_no); + if (size > length) + { + return (size); + } + else + { + return (length); + } + } + + 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; + list_for_each_entry(aic_dev, &p->aic_devs, list) + size += 512; + 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, "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, "Default Tag Queue Depth: %d\n", aic7xxx_default_queue_depth); + 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, "\n"); + size += sprintf(BLS, "Statistics:\n\n"); + list_for_each_entry(aic_dev, &p->aic_devs, list) + { + sdptr = aic_dev->SDptr; + tindex = sdptr->channel << 3 | sdptr->id; + size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n", + p->host_no, sdptr->channel, sdptr->id, sdptr->lun); + size += sprintf(BLS, " Device using %s/%s", + (aic_dev->cur.width == MSG_EXT_WDTR_BUS_16_BIT) ? + "Wide" : "Narrow", + (aic_dev->cur.offset != 0) ? + "Sync transfers at " : "Async transfers.\n" ); + if (aic_dev->cur.offset != 0) + { + struct aic7xxx_syncrate *sync_rate; + unsigned char options = aic_dev->cur.options; + int period = aic_dev->cur.period; + int rate = (aic_dev->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], + aic_dev->cur.offset ); + } + else + { + size += sprintf(BLS, "3.3 MByte/sec, offset %d\n", + aic_dev->cur.offset ); + } + } + size += sprintf(BLS, " Transinfo settings: "); + size += sprintf(BLS, "current(%d/%d/%d/%d), ", + aic_dev->cur.period, + aic_dev->cur.offset, + aic_dev->cur.width, + aic_dev->cur.options); + size += sprintf(BLS, "goal(%d/%d/%d/%d), ", + aic_dev->goal.period, + aic_dev->goal.offset, + aic_dev->goal.width, + aic_dev->goal.options); + size += sprintf(BLS, "user(%d/%d/%d/%d)\n", + p->user[tindex].period, + p->user[tindex].offset, + p->user[tindex].width, + p->user[tindex].options); + if(sdptr->simple_tags) + { + size += sprintf(BLS, " Tagged Command Queueing Enabled, Ordered Tags %s, Depth %d/%d\n", sdptr->ordered_tags ? "Enabled" : "Disabled", sdptr->queue_depth, aic_dev->max_q_depth); + } + if(aic_dev->barrier_total) + size += sprintf(BLS, " Total transfers %ld:\n (%ld/%ld/%ld/%ld reads/writes/REQ_BARRIER/Ordered Tags)\n", + aic_dev->r_total+aic_dev->w_total, aic_dev->r_total, aic_dev->w_total, + aic_dev->barrier_total, aic_dev->ordered_total); + else + size += sprintf(BLS, " Total transfers %ld:\n (%ld/%ld reads/writes)\n", + aic_dev->r_total+aic_dev->w_total, aic_dev->r_total, aic_dev->w_total); + size += sprintf(BLS, "%s\n", HDRB); + size += sprintf(BLS, " Reads:"); + for (i = 0; i < ARRAY_SIZE(aic_dev->r_bins); i++) + { + size += sprintf(BLS, " %10ld", aic_dev->r_bins[i]); + } + size += sprintf(BLS, "\n"); + size += sprintf(BLS, " Writes:"); + for (i = 0; i < ARRAY_SIZE(aic_dev->w_bins); i++) + { + size += sprintf(BLS, " %10ld", aic_dev->w_bins[i]); + } + size += sprintf(BLS, "\n"); + 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_t(int, 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 --git a/drivers/scsi/aic7xxx_old/aic7xxx_reg.h b/drivers/scsi/aic7xxx_old/aic7xxx_reg.h new file mode 100644 index 000000000000..27f2334abc71 --- /dev/null +++ b/drivers/scsi/aic7xxx_old/aic7xxx_reg.h @@ -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 --git a/drivers/scsi/aic7xxx_old/aic7xxx_seq.c b/drivers/scsi/aic7xxx_old/aic7xxx_seq.c new file mode 100644 index 000000000000..e1bc140e9735 --- /dev/null +++ b/drivers/scsi/aic7xxx_old/aic7xxx_seq.c @@ -0,0 +1,817 @@ +/* + * 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, 0xca, 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, 0x86, 0x5c, + 0xff, 0x4e, 0xc8, 0x18, + 0x02, 0x6a, 0x70, 0x5b, + 0xff, 0x52, 0x20, 0x09, + 0x0d, 0x6a, 0x6a, 0x00, + 0x00, 0x52, 0xe6, 0x5b, + 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, 0xba, 0x5b, + 0xff, 0x3d, 0xc8, 0x08, + 0xbf, 0x64, 0xe2, 0x78, + 0x80, 0x64, 0xc8, 0x71, + 0xa0, 0x64, 0xf8, 0x71, + 0xc0, 0x64, 0xf0, 0x71, + 0xe0, 0x64, 0x38, 0x72, + 0x01, 0x6a, 0x22, 0x01, + 0x00, 0x65, 0xaa, 0x40, + 0xf7, 0x11, 0x22, 0x08, + 0x00, 0x65, 0xca, 0x58, + 0xff, 0x06, 0xd4, 0x08, + 0xf7, 0x01, 0x02, 0x08, + 0x09, 0x0c, 0xc4, 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, + 0x03, 0xa9, 0x10, 0x30, + 0x08, 0x6a, 0xcc, 0x00, + 0xa9, 0x6a, 0xd0, 0x5b, + 0x00, 0x65, 0x02, 0x41, + 0xa8, 0x6a, 0x6a, 0x00, + 0x79, 0x6a, 0x6a, 0x00, + 0x40, 0x3d, 0xea, 0x68, + 0x04, 0x35, 0x6a, 0x00, + 0x00, 0x65, 0x2a, 0x5b, + 0x80, 0x6a, 0xd4, 0x01, + 0x10, 0x36, 0xd6, 0x68, + 0x10, 0x36, 0x6c, 0x00, + 0x07, 0xac, 0x10, 0x31, + 0x05, 0xa3, 0x70, 0x30, + 0x03, 0x8c, 0x10, 0x30, + 0x88, 0x6a, 0xcc, 0x00, + 0xac, 0x6a, 0xc8, 0x5b, + 0x00, 0x65, 0xc2, 0x5b, + 0x38, 0x6a, 0xcc, 0x00, + 0xa3, 0x6a, 0xcc, 0x5b, + 0xff, 0x38, 0x12, 0x69, + 0x80, 0x02, 0x04, 0x00, + 0xe7, 0x35, 0x6a, 0x08, + 0x03, 0x69, 0x18, 0x31, + 0x03, 0x69, 0x10, 0x30, + 0xff, 0x6a, 0x10, 0x00, + 0xff, 0x6a, 0x12, 0x00, + 0xff, 0x6a, 0x14, 0x00, + 0x22, 0x38, 0xc8, 0x28, + 0x01, 0x38, 0x1c, 0x61, + 0x02, 0x64, 0xc8, 0x00, + 0x01, 0x38, 0x1c, 0x61, + 0xbf, 0x35, 0x6a, 0x08, + 0xff, 0x64, 0xf8, 0x09, + 0xff, 0x35, 0x26, 0x09, + 0x80, 0x02, 0xa4, 0x69, + 0x10, 0x0c, 0x7a, 0x69, + 0x80, 0x94, 0x22, 0x79, + 0x00, 0x35, 0x0a, 0x5b, + 0x80, 0x02, 0xa4, 0x69, + 0xff, 0x65, 0x94, 0x79, + 0x01, 0x38, 0x70, 0x71, + 0xff, 0x38, 0x70, 0x18, + 0xff, 0x38, 0x94, 0x79, + 0x80, 0xea, 0x4a, 0x61, + 0xef, 0x38, 0xc8, 0x18, + 0x80, 0x6a, 0xc8, 0x00, + 0x00, 0x65, 0x3c, 0x49, + 0x33, 0x38, 0xc8, 0x28, + 0xff, 0x64, 0xd0, 0x09, + 0x04, 0x39, 0xc0, 0x31, + 0x09, 0x6a, 0xd6, 0x01, + 0x80, 0xeb, 0x42, 0x79, + 0xf7, 0xeb, 0xd6, 0x09, + 0x08, 0xeb, 0x46, 0x69, + 0x01, 0x6a, 0xd6, 0x01, + 0x08, 0xe9, 0x10, 0x31, + 0x03, 0x8c, 0x10, 0x30, + 0xff, 0x38, 0x70, 0x18, + 0x88, 0x6a, 0xcc, 0x00, + 0x39, 0x6a, 0xce, 0x5b, + 0x08, 0x6a, 0x18, 0x01, + 0xff, 0x6a, 0x1a, 0x09, + 0xff, 0x6a, 0x1c, 0x09, + 0x0d, 0x93, 0x26, 0x01, + 0x00, 0x65, 0x78, 0x5c, + 0x88, 0x6a, 0xcc, 0x00, + 0x00, 0x65, 0x6a, 0x5c, + 0x00, 0x65, 0xc2, 0x5b, + 0xff, 0x6a, 0xc8, 0x08, + 0x08, 0x39, 0x72, 0x18, + 0x00, 0x3a, 0x74, 0x20, + 0x00, 0x65, 0x02, 0x41, + 0x01, 0x0c, 0x6c, 0x79, + 0x10, 0x0c, 0x02, 0x79, + 0x10, 0x0c, 0x7a, 0x69, + 0x01, 0xfc, 0x70, 0x79, + 0xff, 0x6a, 0x70, 0x08, + 0x01, 0x0c, 0x76, 0x79, + 0x10, 0x0c, 0x02, 0x79, + 0x00, 0x65, 0xae, 0x59, + 0x01, 0xfc, 0x94, 0x69, + 0x40, 0x0d, 0x84, 0x69, + 0xb1, 0x6a, 0x22, 0x01, + 0x00, 0x65, 0x94, 0x41, + 0x2e, 0xfc, 0xa2, 0x28, + 0x3f, 0x38, 0xc8, 0x08, + 0x00, 0x51, 0x94, 0x71, + 0xff, 0x6a, 0xc8, 0x08, + 0xf8, 0x39, 0x72, 0x18, + 0xff, 0x3a, 0x74, 0x20, + 0x01, 0x38, 0x70, 0x18, + 0x00, 0x65, 0x86, 0x41, + 0x03, 0x08, 0x52, 0x31, + 0xff, 0x38, 0x50, 0x09, + 0x12, 0x01, 0x02, 0x00, + 0xff, 0x08, 0x52, 0x09, + 0xff, 0x09, 0x54, 0x09, + 0xff, 0x0a, 0x56, 0x09, + 0xff, 0x38, 0x50, 0x09, + 0x00, 0x65, 0xaa, 0x40, + 0x10, 0x0c, 0xa4, 0x79, + 0x00, 0x65, 0xae, 0x59, + 0x7f, 0x02, 0x04, 0x08, + 0xe1, 0x6a, 0x22, 0x01, + 0x00, 0x65, 0xaa, 0x40, + 0x04, 0x93, 0xc2, 0x69, + 0xdf, 0x93, 0x26, 0x09, + 0x20, 0x93, 0xb2, 0x69, + 0x02, 0x93, 0x26, 0x01, + 0x01, 0x94, 0xb6, 0x79, + 0x01, 0x94, 0xb6, 0x79, + 0x01, 0x94, 0xb6, 0x79, + 0x01, 0x94, 0xb6, 0x79, + 0x01, 0x94, 0xb6, 0x79, + 0x10, 0x94, 0xc0, 0x69, + 0xd7, 0x93, 0x26, 0x09, + 0x28, 0x93, 0xc4, 0x69, + 0xff, 0x6a, 0xd4, 0x0c, + 0x00, 0x65, 0x2a, 0x5b, + 0x05, 0xb4, 0x10, 0x31, + 0x02, 0x6a, 0x1a, 0x31, + 0x03, 0x8c, 0x10, 0x30, + 0x88, 0x6a, 0xcc, 0x00, + 0xb4, 0x6a, 0xcc, 0x5b, + 0xff, 0x6a, 0x1a, 0x09, + 0xff, 0x6a, 0x1c, 0x09, + 0x00, 0x65, 0xc2, 0x5b, + 0x3d, 0x6a, 0x0a, 0x5b, + 0xac, 0x6a, 0x26, 0x01, + 0x04, 0x0b, 0xde, 0x69, + 0x04, 0x0b, 0xe4, 0x69, + 0x10, 0x0c, 0xe0, 0x79, + 0x02, 0x03, 0xe8, 0x79, + 0x11, 0x0c, 0xe4, 0x79, + 0xd7, 0x93, 0x26, 0x09, + 0x28, 0x93, 0xea, 0x69, + 0x12, 0x01, 0x02, 0x00, + 0x00, 0x65, 0xaa, 0x40, + 0x00, 0x65, 0x2a, 0x5b, + 0xff, 0x06, 0x44, 0x09, + 0x00, 0x65, 0xaa, 0x40, + 0x10, 0x3d, 0x06, 0x00, + 0xff, 0x34, 0xca, 0x08, + 0x80, 0x65, 0x1c, 0x62, + 0x0f, 0xa1, 0xca, 0x08, + 0x07, 0xa1, 0xca, 0x08, + 0x40, 0xa0, 0xc8, 0x08, + 0x00, 0x65, 0xca, 0x00, + 0x80, 0x65, 0xca, 0x00, + 0x80, 0xa0, 0x0c, 0x7a, + 0xff, 0x65, 0x0c, 0x08, + 0x00, 0x65, 0x1e, 0x42, + 0x20, 0xa0, 0x24, 0x7a, + 0xff, 0x65, 0x0c, 0x08, + 0x00, 0x65, 0xba, 0x5b, + 0xa0, 0x3d, 0x2c, 0x62, + 0x23, 0xa0, 0x0c, 0x08, + 0x00, 0x65, 0xba, 0x5b, + 0xa0, 0x3d, 0x2c, 0x62, + 0x00, 0xb9, 0x24, 0x42, + 0xff, 0x65, 0x24, 0x62, + 0xa1, 0x6a, 0x22, 0x01, + 0xff, 0x6a, 0xd4, 0x08, + 0x10, 0x51, 0x2c, 0x72, + 0x40, 0x6a, 0x18, 0x00, + 0xff, 0x65, 0x0c, 0x08, + 0x00, 0x65, 0xba, 0x5b, + 0xa0, 0x3d, 0xf6, 0x71, + 0x40, 0x6a, 0x18, 0x00, + 0xff, 0x34, 0xa6, 0x08, + 0x80, 0x34, 0x34, 0x62, + 0x7f, 0xa0, 0x40, 0x09, + 0x08, 0x6a, 0x68, 0x00, + 0x00, 0x65, 0xaa, 0x40, + 0x64, 0x6a, 0x00, 0x5b, + 0x80, 0x64, 0xaa, 0x6a, + 0x04, 0x64, 0x8c, 0x72, + 0x02, 0x64, 0x92, 0x72, + 0x00, 0x6a, 0x54, 0x72, + 0x03, 0x64, 0xa6, 0x72, + 0x01, 0x64, 0x88, 0x72, + 0x07, 0x64, 0xe8, 0x72, + 0x08, 0x64, 0x50, 0x72, + 0x23, 0x64, 0xec, 0x72, + 0x11, 0x6a, 0x22, 0x01, + 0x07, 0x6a, 0xf2, 0x5a, + 0xff, 0x06, 0xd4, 0x08, + 0x00, 0x65, 0xaa, 0x40, + 0xff, 0xa8, 0x58, 0x6a, + 0xff, 0xa2, 0x70, 0x7a, + 0x01, 0x6a, 0x6a, 0x00, + 0x00, 0xb9, 0xe6, 0x5b, + 0xff, 0xa2, 0x70, 0x7a, + 0x71, 0x6a, 0x22, 0x01, + 0xff, 0x6a, 0xd4, 0x08, + 0x40, 0x51, 0x70, 0x62, + 0x0d, 0x6a, 0x6a, 0x00, + 0x00, 0xb9, 0xe6, 0x5b, + 0xff, 0x3e, 0x74, 0x09, + 0xff, 0x90, 0x7c, 0x08, + 0x00, 0x65, 0x4e, 0x58, + 0x00, 0x65, 0xbc, 0x40, + 0x20, 0xa0, 0x78, 0x6a, + 0xff, 0x37, 0xc8, 0x08, + 0x00, 0x6a, 0x90, 0x5b, + 0xff, 0x6a, 0xa6, 0x5b, + 0xff, 0xf8, 0xc8, 0x08, + 0xff, 0x4f, 0xc8, 0x08, + 0x01, 0x6a, 0x90, 0x5b, + 0x00, 0xb9, 0xa6, 0x5b, + 0x01, 0x4f, 0x9e, 0x18, + 0x02, 0x6a, 0x22, 0x01, + 0x00, 0x65, 0x80, 0x5c, + 0x00, 0x65, 0xbc, 0x40, + 0x41, 0x6a, 0x22, 0x01, + 0x00, 0x65, 0xaa, 0x40, + 0x04, 0xa0, 0x40, 0x01, + 0x00, 0x65, 0x98, 0x5c, + 0x00, 0x65, 0xbc, 0x40, + 0x10, 0x36, 0x50, 0x7a, + 0x05, 0x38, 0x46, 0x31, + 0x04, 0x14, 0x58, 0x31, + 0x03, 0xa9, 0x60, 0x31, + 0xa3, 0x6a, 0xcc, 0x00, + 0x38, 0x6a, 0xcc, 0x5b, + 0xac, 0x6a, 0xcc, 0x00, + 0x14, 0x6a, 0xce, 0x5b, + 0xa9, 0x6a, 0xd0, 0x5b, + 0x00, 0x65, 0x50, 0x42, + 0xef, 0x36, 0x6c, 0x08, + 0x00, 0x65, 0x50, 0x42, + 0x0f, 0x64, 0xc8, 0x08, + 0x07, 0x64, 0xc8, 0x08, + 0x00, 0x37, 0x6e, 0x00, + 0xff, 0x6a, 0xa4, 0x00, + 0x00, 0x65, 0x60, 0x5b, + 0xff, 0x51, 0xbc, 0x72, + 0x20, 0x36, 0xc6, 0x7a, + 0x00, 0x90, 0x4e, 0x5b, + 0x00, 0x65, 0xc8, 0x42, + 0xff, 0x06, 0xd4, 0x08, + 0x00, 0x65, 0xba, 0x5b, + 0xe0, 0x3d, 0xe2, 0x62, + 0x20, 0x12, 0xe2, 0x62, + 0x51, 0x6a, 0xf6, 0x5a, + 0x00, 0x65, 0x48, 0x5b, + 0xff, 0x37, 0xc8, 0x08, + 0x00, 0xa1, 0xda, 0x62, + 0x04, 0xa0, 0xda, 0x7a, + 0xfb, 0xa0, 0x40, 0x09, + 0x80, 0x36, 0x6c, 0x00, + 0x80, 0xa0, 0x50, 0x7a, + 0x7f, 0xa0, 0x40, 0x09, + 0xff, 0x6a, 0xf2, 0x5a, + 0x00, 0x65, 0x50, 0x42, + 0x04, 0xa0, 0xe0, 0x7a, + 0x00, 0x65, 0x98, 0x5c, + 0x00, 0x65, 0xe2, 0x42, + 0x00, 0x65, 0x80, 0x5c, + 0x31, 0x6a, 0x22, 0x01, + 0x0c, 0x6a, 0xf2, 0x5a, + 0x00, 0x65, 0x50, 0x42, + 0x61, 0x6a, 0x22, 0x01, + 0x00, 0x65, 0x50, 0x42, + 0x51, 0x6a, 0xf6, 0x5a, + 0x51, 0x6a, 0x22, 0x01, + 0x00, 0x65, 0x50, 0x42, + 0x10, 0x3d, 0x06, 0x00, + 0xff, 0x65, 0x68, 0x0c, + 0xff, 0x06, 0xd4, 0x08, + 0x01, 0x0c, 0xf8, 0x7a, + 0x04, 0x0c, 0xfa, 0x6a, + 0xe0, 0x03, 0x7a, 0x08, + 0xe0, 0x3d, 0x06, 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, 0x1a, 0x6b, + 0x10, 0x0c, 0x0c, 0x7b, + 0x04, 0x0b, 0x14, 0x6b, + 0xff, 0x6a, 0xca, 0x08, + 0x04, 0x93, 0x18, 0x6b, + 0x01, 0x94, 0x16, 0x7b, + 0x10, 0x94, 0x18, 0x6b, + 0x80, 0x3d, 0x1e, 0x73, + 0x0f, 0x04, 0x22, 0x6b, + 0x02, 0x03, 0x22, 0x7b, + 0x11, 0x0c, 0x1e, 0x7b, + 0xc7, 0x93, 0x26, 0x09, + 0xff, 0x99, 0xd4, 0x08, + 0x38, 0x93, 0x24, 0x6b, + 0xff, 0x6a, 0xd4, 0x0c, + 0x80, 0x36, 0x28, 0x6b, + 0x21, 0x6a, 0x22, 0x05, + 0xff, 0x65, 0x20, 0x09, + 0xff, 0x51, 0x36, 0x63, + 0xff, 0x37, 0xc8, 0x08, + 0xa1, 0x6a, 0x42, 0x43, + 0xff, 0x51, 0xc8, 0x08, + 0xb9, 0x6a, 0x42, 0x43, + 0xff, 0x90, 0xa4, 0x08, + 0xff, 0xba, 0x46, 0x73, + 0xff, 0xba, 0x20, 0x09, + 0xff, 0x65, 0xca, 0x18, + 0x00, 0x6c, 0x3a, 0x63, + 0xff, 0x90, 0xca, 0x0c, + 0xff, 0x6a, 0xca, 0x04, + 0x20, 0x36, 0x5a, 0x7b, + 0x00, 0x90, 0x2e, 0x5b, + 0xff, 0x65, 0x5a, 0x73, + 0xff, 0x52, 0x58, 0x73, + 0xff, 0xba, 0xcc, 0x08, + 0xff, 0x52, 0x20, 0x09, + 0xff, 0x66, 0x74, 0x09, + 0xff, 0x65, 0x20, 0x0d, + 0xff, 0xba, 0x7e, 0x0c, + 0x00, 0x6a, 0x86, 0x5c, + 0x0d, 0x6a, 0x6a, 0x00, + 0x00, 0x51, 0xe6, 0x43, + 0xff, 0x3f, 0xb4, 0x73, + 0xff, 0x6a, 0xa2, 0x00, + 0x00, 0x3f, 0x2e, 0x5b, + 0xff, 0x65, 0xb4, 0x73, + 0x20, 0x36, 0x6c, 0x00, + 0x20, 0xa0, 0x6e, 0x6b, + 0xff, 0xb9, 0xa2, 0x0c, + 0xff, 0x6a, 0xa2, 0x04, + 0xff, 0x65, 0xa4, 0x08, + 0xe0, 0x6a, 0xcc, 0x00, + 0x45, 0x6a, 0xda, 0x5b, + 0x01, 0x6a, 0xd0, 0x01, + 0x09, 0x6a, 0xd6, 0x01, + 0x80, 0xeb, 0x7a, 0x7b, + 0x01, 0x6a, 0xd6, 0x01, + 0x01, 0xe9, 0xa4, 0x34, + 0x88, 0x6a, 0xcc, 0x00, + 0x45, 0x6a, 0xda, 0x5b, + 0x01, 0x6a, 0x18, 0x01, + 0xff, 0x6a, 0x1a, 0x09, + 0xff, 0x6a, 0x1c, 0x09, + 0x0d, 0x6a, 0x26, 0x01, + 0x00, 0x65, 0x78, 0x5c, + 0xff, 0x99, 0xa4, 0x0c, + 0xff, 0x65, 0xa4, 0x08, + 0xe0, 0x6a, 0xcc, 0x00, + 0x45, 0x6a, 0xda, 0x5b, + 0x01, 0x6a, 0xd0, 0x01, + 0x01, 0x6a, 0xdc, 0x05, + 0x88, 0x6a, 0xcc, 0x00, + 0x45, 0x6a, 0xda, 0x5b, + 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, 0xaa, 0x7b, + 0xff, 0x6a, 0xdc, 0x0d, + 0xff, 0x65, 0x32, 0x09, + 0x0a, 0x93, 0x26, 0x01, + 0x00, 0x65, 0x78, 0x44, + 0xff, 0x37, 0xc8, 0x08, + 0x00, 0x6a, 0x70, 0x5b, + 0xff, 0x52, 0xa2, 0x0c, + 0x01, 0x0c, 0xba, 0x7b, + 0x04, 0x0c, 0xba, 0x6b, + 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, 0xd6, 0x5b, + 0xff, 0x90, 0xe2, 0x09, + 0x20, 0x6a, 0xd0, 0x01, + 0x04, 0x35, 0xf8, 0x7b, + 0x1d, 0x6a, 0xdc, 0x01, + 0xdc, 0xee, 0xf4, 0x63, + 0x00, 0x65, 0x0e, 0x44, + 0x01, 0x6a, 0xdc, 0x01, + 0x20, 0xa0, 0xd8, 0x31, + 0x09, 0xee, 0xdc, 0x01, + 0x80, 0xee, 0xfe, 0x7b, + 0x11, 0x6a, 0xdc, 0x01, + 0x50, 0xee, 0x02, 0x64, + 0x20, 0x6a, 0xd0, 0x01, + 0x09, 0x6a, 0xdc, 0x01, + 0x88, 0xee, 0x08, 0x64, + 0x19, 0x6a, 0xdc, 0x01, + 0xd8, 0xee, 0x0c, 0x64, + 0xff, 0x6a, 0xdc, 0x09, + 0x18, 0xee, 0x10, 0x6c, + 0xff, 0x6a, 0xd4, 0x0c, + 0x88, 0x6a, 0xcc, 0x00, + 0x41, 0x6a, 0xd6, 0x5b, + 0x20, 0x6a, 0x18, 0x01, + 0xff, 0x6a, 0x1a, 0x09, + 0xff, 0x6a, 0x1c, 0x09, + 0xff, 0x35, 0x26, 0x09, + 0x04, 0x35, 0x3c, 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, 0x26, 0x64, + 0x0a, 0x93, 0x26, 0x01, + 0x00, 0x65, 0x78, 0x44, + 0xa0, 0x6a, 0xcc, 0x00, + 0xe8, 0x6a, 0xc8, 0x00, + 0x01, 0x94, 0x40, 0x6c, + 0x10, 0x94, 0x42, 0x6c, + 0x08, 0x94, 0x54, 0x6c, + 0x08, 0x94, 0x54, 0x6c, + 0x08, 0x94, 0x54, 0x6c, + 0x00, 0x65, 0x68, 0x5c, + 0x08, 0x64, 0xc8, 0x18, + 0x00, 0x8c, 0xca, 0x18, + 0x00, 0x65, 0x4a, 0x4c, + 0x00, 0x65, 0x40, 0x44, + 0xf7, 0x93, 0x26, 0x09, + 0x08, 0x93, 0x56, 0x6c, + 0x00, 0x65, 0x68, 0x5c, + 0x08, 0x64, 0xc8, 0x18, + 0x08, 0x64, 0x58, 0x64, + 0xff, 0x6a, 0xd4, 0x0c, + 0x00, 0x65, 0x78, 0x5c, + 0x00, 0x65, 0x68, 0x5c, + 0x00, 0x65, 0x68, 0x5c, + 0x00, 0x65, 0x68, 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, 0x78, 0x7c, + 0xf7, 0x93, 0x26, 0x09, + 0x08, 0x93, 0x7c, 0x6c, + 0xff, 0x6a, 0xd4, 0x0c, + 0xff, 0x40, 0x74, 0x09, + 0xff, 0x90, 0x80, 0x08, + 0xff, 0x6a, 0x72, 0x05, + 0xff, 0x40, 0x94, 0x64, + 0xff, 0x3f, 0x8c, 0x64, + 0xff, 0x6a, 0xca, 0x04, + 0xff, 0x3f, 0x20, 0x09, + 0x01, 0x6a, 0x6a, 0x00, + 0x00, 0xb9, 0xe6, 0x5b, + 0xff, 0xba, 0x7e, 0x0c, + 0xff, 0x40, 0x20, 0x09, + 0xff, 0xba, 0x80, 0x0c, + 0xff, 0x3f, 0x74, 0x09, + 0xff, 0x90, 0x7e, 0x0c, +}; + +static int aic7xxx_patch15_func(struct aic7xxx_host *p); + +static int +aic7xxx_patch15_func(struct aic7xxx_host *p) +{ + return ((p->bugs & AHC_BUG_SCBCHAN_UPLOAD) != 0); +} + +static int aic7xxx_patch14_func(struct aic7xxx_host *p); + +static int +aic7xxx_patch14_func(struct aic7xxx_host *p) +{ + return ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0); +} + +static int aic7xxx_patch13_func(struct aic7xxx_host *p); + +static int +aic7xxx_patch13_func(struct aic7xxx_host *p) +{ + return ((p->features & AHC_WIDE) != 0); +} + +static int aic7xxx_patch12_func(struct aic7xxx_host *p); + +static int +aic7xxx_patch12_func(struct aic7xxx_host *p) +{ + return ((p->bugs & AHC_BUG_AUTOFLUSH) != 0); +} + +static int aic7xxx_patch11_func(struct aic7xxx_host *p); + +static int +aic7xxx_patch11_func(struct aic7xxx_host *p) +{ + return ((p->features & AHC_ULTRA2) == 0); +} + +static int aic7xxx_patch10_func(struct aic7xxx_host *p); + +static int +aic7xxx_patch10_func(struct aic7xxx_host *p) +{ + return ((p->features & AHC_CMD_CHAN) == 0); +} + +static int aic7xxx_patch9_func(struct aic7xxx_host *p); + +static int +aic7xxx_patch9_func(struct aic7xxx_host *p) +{ + return ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895); +} + +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, 102, 1, 2 }, + { aic7xxx_patch0_func, 103, 2, 1 }, + { aic7xxx_patch7_func, 107, 2, 1 }, + { aic7xxx_patch9_func, 109, 1, 1 }, + { aic7xxx_patch10_func, 110, 2, 1 }, + { aic7xxx_patch7_func, 113, 1, 2 }, + { aic7xxx_patch0_func, 114, 1, 1 }, + { aic7xxx_patch1_func, 118, 1, 1 }, + { aic7xxx_patch1_func, 121, 3, 3 }, + { aic7xxx_patch11_func, 123, 1, 1 }, + { aic7xxx_patch0_func, 124, 5, 1 }, + { aic7xxx_patch7_func, 132, 1, 1 }, + { aic7xxx_patch9_func, 133, 1, 1 }, + { aic7xxx_patch10_func, 134, 3, 1 }, + { aic7xxx_patch7_func, 137, 3, 2 }, + { aic7xxx_patch0_func, 140, 2, 1 }, + { aic7xxx_patch7_func, 142, 5, 2 }, + { aic7xxx_patch0_func, 147, 3, 1 }, + { aic7xxx_patch7_func, 150, 1, 2 }, + { aic7xxx_patch0_func, 151, 2, 1 }, + { aic7xxx_patch1_func, 153, 15, 4 }, + { aic7xxx_patch11_func, 166, 1, 2 }, + { aic7xxx_patch0_func, 167, 1, 1 }, + { aic7xxx_patch0_func, 168, 10, 1 }, + { aic7xxx_patch7_func, 181, 1, 2 }, + { aic7xxx_patch0_func, 182, 2, 1 }, + { aic7xxx_patch7_func, 184, 18, 1 }, + { aic7xxx_patch1_func, 202, 3, 3 }, + { aic7xxx_patch7_func, 204, 1, 1 }, + { aic7xxx_patch0_func, 205, 4, 1 }, + { aic7xxx_patch7_func, 210, 2, 1 }, + { aic7xxx_patch7_func, 215, 13, 3 }, + { aic7xxx_patch12_func, 218, 1, 1 }, + { aic7xxx_patch12_func, 219, 4, 1 }, + { aic7xxx_patch1_func, 229, 3, 3 }, + { aic7xxx_patch11_func, 231, 1, 1 }, + { aic7xxx_patch0_func, 232, 5, 1 }, + { aic7xxx_patch11_func, 237, 1, 2 }, + { aic7xxx_patch0_func, 238, 9, 1 }, + { aic7xxx_patch13_func, 254, 1, 2 }, + { aic7xxx_patch0_func, 255, 1, 1 }, + { aic7xxx_patch4_func, 316, 1, 2 }, + { aic7xxx_patch0_func, 317, 1, 1 }, + { aic7xxx_patch2_func, 320, 1, 1 }, + { aic7xxx_patch1_func, 330, 3, 2 }, + { aic7xxx_patch0_func, 333, 5, 1 }, + { aic7xxx_patch13_func, 341, 1, 2 }, + { aic7xxx_patch0_func, 342, 1, 1 }, + { aic7xxx_patch5_func, 347, 1, 1 }, + { aic7xxx_patch11_func, 389, 15, 2 }, + { aic7xxx_patch14_func, 402, 1, 1 }, + { aic7xxx_patch1_func, 441, 7, 2 }, + { aic7xxx_patch0_func, 448, 8, 1 }, + { aic7xxx_patch1_func, 457, 4, 2 }, + { aic7xxx_patch0_func, 461, 6, 1 }, + { aic7xxx_patch1_func, 467, 4, 2 }, + { aic7xxx_patch0_func, 471, 3, 1 }, + { aic7xxx_patch10_func, 481, 10, 1 }, + { aic7xxx_patch1_func, 500, 22, 5 }, + { aic7xxx_patch11_func, 508, 4, 1 }, + { aic7xxx_patch7_func, 512, 7, 3 }, + { aic7xxx_patch15_func, 512, 5, 2 }, + { aic7xxx_patch0_func, 517, 2, 1 }, + { aic7xxx_patch10_func, 522, 50, 3 }, + { aic7xxx_patch14_func, 543, 17, 2 }, + { aic7xxx_patch0_func, 560, 4, 1 }, + { aic7xxx_patch10_func, 572, 4, 1 }, + { aic7xxx_patch5_func, 576, 2, 1 }, + { aic7xxx_patch5_func, 579, 9, 1 }, + +}; diff --git a/drivers/scsi/aic7xxx_old/scsi_message.h b/drivers/scsi/aic7xxx_old/scsi_message.h new file mode 100644 index 000000000000..a79f89c65173 --- /dev/null +++ b/drivers/scsi/aic7xxx_old/scsi_message.h @@ -0,0 +1,49 @@ +/* Messages (1 byte) */ /* I/T (M)andatory or (O)ptional */ +#define MSG_CMDCOMPLETE 0x00 /* M/M */ +#define MSG_EXTENDED 0x01 /* O/O */ +#define MSG_SAVEDATAPOINTER 0x02 /* O/O */ +#define MSG_RESTOREPOINTERS 0x03 /* O/O */ +#define MSG_DISCONNECT 0x04 /* O/O */ +#define MSG_INITIATOR_DET_ERR 0x05 /* M/M */ +#define MSG_ABORT 0x06 /* O/M */ +#define MSG_MESSAGE_REJECT 0x07 /* M/M */ +#define MSG_NOOP 0x08 /* M/M */ +#define MSG_PARITY_ERROR 0x09 /* M/M */ +#define MSG_LINK_CMD_COMPLETE 0x0a /* O/O */ +#define MSG_LINK_CMD_COMPLETEF 0x0b /* O/O */ +#define MSG_BUS_DEV_RESET 0x0c /* O/M */ +#define MSG_ABORT_TAG 0x0d /* O/O */ +#define MSG_CLEAR_QUEUE 0x0e /* O/O */ +#define MSG_INIT_RECOVERY 0x0f /* O/O */ +#define MSG_REL_RECOVERY 0x10 /* O/O */ +#define MSG_TERM_IO_PROC 0x11 /* O/O */ + +/* Messages (2 byte) */ +#define MSG_SIMPLE_Q_TAG 0x20 /* O/O */ +#define MSG_HEAD_OF_Q_TAG 0x21 /* O/O */ +#define MSG_ORDERED_Q_TAG 0x22 /* O/O */ +#define MSG_IGN_WIDE_RESIDUE 0x23 /* O/O */ + +/* Identify message */ /* M/M */ +#define MSG_IDENTIFYFLAG 0x80 +#define MSG_IDENTIFY_DISCFLAG 0x40 +#define MSG_IDENTIFY(lun, disc) (((disc) ? 0xc0 : MSG_IDENTIFYFLAG) | (lun)) +#define MSG_ISIDENTIFY(m) ((m) & MSG_IDENTIFYFLAG) + +/* Extended messages (opcode and length) */ +#define MSG_EXT_SDTR 0x01 +#define MSG_EXT_SDTR_LEN 0x03 + +#define MSG_EXT_WDTR 0x03 +#define MSG_EXT_WDTR_LEN 0x02 +#define MSG_EXT_WDTR_BUS_8_BIT 0x00 +#define MSG_EXT_WDTR_BUS_16_BIT 0x01 +#define MSG_EXT_WDTR_BUS_32_BIT 0x02 + +#define MSG_EXT_PPR 0x04 +#define MSG_EXT_PPR_LEN 0x06 +#define MSG_EXT_PPR_OPTION_ST 0x00 +#define MSG_EXT_PPR_OPTION_DT_CRC 0x02 +#define MSG_EXT_PPR_OPTION_DT_UNITS 0x03 +#define MSG_EXT_PPR_OPTION_DT_CRC_QUICK 0x04 +#define MSG_EXT_PPR_OPTION_DT_UNITS_QUICK 0x05 diff --git a/drivers/scsi/aic7xxx_old/sequencer.h b/drivers/scsi/aic7xxx_old/sequencer.h new file mode 100644 index 000000000000..ee66855222b1 --- /dev/null +++ b/drivers/scsi/aic7xxx_old/sequencer.h @@ -0,0 +1,135 @@ +/* + * Instruction formats for the sequencer program downloaded to + * Aic7xxx SCSI host adapters + * + * Copyright (c) 1997, 1998 Justin T. Gibbs. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Where this Software is combined with software released under the terms of + * the GNU General Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: sequencer.h,v 1.3 1997/09/27 19:37:31 gibbs Exp $ + */ + +#ifdef __LITTLE_ENDIAN_BITFIELD +struct ins_format1 { + unsigned int + immediate : 8, + source : 9, + destination : 9, + ret : 1, + opcode : 4, + parity : 1; +}; + +struct ins_format2 { + unsigned int + shift_control : 8, + source : 9, + destination : 9, + ret : 1, + opcode : 4, + parity : 1; +}; + +struct ins_format3 { + unsigned int + immediate : 8, + source : 9, + address : 10, + opcode : 4, + parity : 1; +}; +#elif defined(__BIG_ENDIAN_BITFIELD) +struct ins_format1 { + unsigned int + parity : 1, + opcode : 4, + ret : 1, + destination : 9, + source : 9, + immediate : 8; +}; + +struct ins_format2 { + unsigned int + parity : 1, + opcode : 4, + ret : 1, + destination : 9, + source : 9, + shift_control : 8; +}; + +struct ins_format3 { + unsigned int + parity : 1, + opcode : 4, + address : 10, + source : 9, + immediate : 8; +}; +#endif + +union ins_formats { + struct ins_format1 format1; + struct ins_format2 format2; + struct ins_format3 format3; + unsigned char bytes[4]; + unsigned int integer; +}; +struct instruction { + union ins_formats format; + unsigned int srcline; + struct symbol *patch_label; + struct { + struct instruction *stqe_next; + } links; +}; + +#define AIC_OP_OR 0x0 +#define AIC_OP_AND 0x1 +#define AIC_OP_XOR 0x2 +#define AIC_OP_ADD 0x3 +#define AIC_OP_ADC 0x4 +#define AIC_OP_ROL 0x5 +#define AIC_OP_BMOV 0x6 + +#define AIC_OP_JMP 0x8 +#define AIC_OP_JC 0x9 +#define AIC_OP_JNC 0xa +#define AIC_OP_CALL 0xb +#define AIC_OP_JNE 0xc +#define AIC_OP_JNZ 0xd +#define AIC_OP_JE 0xe +#define AIC_OP_JZ 0xf + +/* Pseudo Ops */ +#define AIC_OP_SHL 0x10 +#define AIC_OP_SHR 0x20 +#define AIC_OP_ROR 0x30 |