/*
* Aic7xxx register and scratch ram definitions.
*
* Copyright (c) 1994-2001 Justin T. Gibbs.
* Copyright (c) 2000-2001 Adaptec Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions, and the following disclaimer,
*    without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
*    substantially similar to the "NO WARRANTY" disclaimer below
*    ("Disclaimer") and any redistribution must be conditioned upon
*    including a substantially similar Disclaimer requirement for further
*    binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
*    of any contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $FreeBSD: /repoman/r/ncvs/src/sys/dev/aic7xxx/aic7xxx.reg,v 1.43 2003/01/20 20:44:55 gibbs Exp $
*/
VERSION = "$NetBSD: aic7xxx.reg,v 1.8 2025/08/18 20:59:56 andvar 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
       field   TEMODE          0x80
       field   ENSELO          0x40
       field   ENSELI          0x20
       field   ENRSELI         0x10
       field   ENAUTOATNO      0x08
       field   ENAUTOATNI      0x04
       field   ENAUTOATNP      0x02
       field   SCSIRSTO        0x01
}

/*
* SCSI Transfer Control 0 Register (pp. 3-13).
* Controls the SCSI module data path.
*/
register SXFRCTL0 {
       address                 0x001
       access_mode RW
       field   DFON            0x80
       field   DFPEXP          0x40
       field   FAST20          0x20
       field   CLRSTCNT        0x10
       field   SPIOEN          0x08
       field   SCAMEN          0x04
       field   CLRCHN          0x02
}

/*
* SCSI Transfer Control 1 Register (pp. 3-14,15).
* Controls the SCSI module data path.
*/
register SXFRCTL1 {
       address                 0x002
       access_mode RW
       field   BITBUCKET       0x80
       field   SWRAPEN         0x40
       field   ENSPCHK         0x20
       mask    STIMESEL        0x18
       field   ENSTIMER        0x04
       field   ACTNEGEN        0x02
       field   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
       field   CDI             0x80
       field   IOI             0x40
       field   MSGI            0x20
       field   ATNI            0x10
       field   SELI            0x08
       field   BSYI            0x04
       field   REQI            0x02
       field   ACKI            0x01
/*
* Possible phases in SCSISIGI
*/
       mask    PHASE_MASK      CDI|IOI|MSGI
       mask    P_DATAOUT       0x00
       mask    P_DATAIN        IOI
       mask    P_DATAOUT_DT    P_DATAOUT|MSGI
       mask    P_DATAIN_DT     P_DATAIN|MSGI
       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
       field   CDO             0x80
       field   IOO             0x40
       field   MSGO            0x20
       field   ATNO            0x10
       field   SELO            0x08
       field   BSYO            0x04
       field   REQO            0x02
       field   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
       field   WIDEXFER        0x80            /* Wide transfer control */
       field   ENABLE_CRC      0x40            /* CRC for D-Phases */
       field   SINGLE_EDGE     0x10            /* Disable DT Transfers */
       mask    SXFR            0x70            /* Sync transfer rate */
       mask    SXFR_ULTRA2     0x0f            /* 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    TWIN_TID        0x70
       field   TWIN_CHNLB      0x80
       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
}

/* ALT_MODE registers (Ultra2 and Ultra160 chips) */
register SXFRCTL2 {
       address                 0x013
       access_mode RW
       field   AUTORSTDIS      0x10
       field   CMDDMAEN        0x08
       mask    ASYNC_SETUP     0x07
}

/* ALT_MODE register on Ultra160 chips */
register OPTIONMODE {
       address                 0x008
       access_mode RW
       field   AUTORATEEN              0x80
       field   AUTOACKEN               0x40
       field   ATNMGMNTEN              0x20
       field   BUSFREEREV              0x10
       field   EXPPHASEDIS             0x08
       field   SCSIDATL_IMGEN          0x04
       field   AUTO_MSGOUT_DE          0x02
       field   DIS_MSGIN_DUALEDGE      0x01
       mask    OPTIONMODE_DEFAULTS     AUTO_MSGOUT_DE|DIS_MSGIN_DUALEDGE
}

/* ALT_MODE register on Ultra160 chips */
register TARGCRCCNT {
       address                 0x00a
       size    2
       access_mode RW
}

/*
* 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
       field   CLRSELDO        0x40
       field   CLRSELDI        0x20
       field   CLRSELINGO      0x10
       field   CLRSWRAP        0x08
       field   CLRIOERR        0x08    /* Ultra2 Only */
       field   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
       field   TARGET          0x80    /* Board acting as target */
       field   SELDO           0x40    /* Selection Done */
       field   SELDI           0x20    /* Board has been selected */
       field   SELINGO         0x10    /* Selection In Progress */
       field   SWRAP           0x08    /* 24bit counter wrap */
       field   IOERR           0x08    /* LVD Transceiver mode changed */
       field   SDONE           0x04    /* STCNT = 0x000000 */
       field   SPIORDY         0x02    /* SCSI PIO Ready */
       field   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
       field   CLRSELTIMEO     0x80
       field   CLRATNO         0x40
       field   CLRSCSIRSTI     0x20
       field   CLRBUSFREE      0x08
       field   CLRSCSIPERR     0x04
       field   CLRPHASECHG     0x02
       field   CLRREQINIT      0x01
}

/*
* SCSI Status 1 (p. 3-24)
*/
register SSTAT1 {
       address                 0x00c
       access_mode RO
       field   SELTO           0x80
       field   ATNTARG         0x40
       field   SCSIRSTI        0x20
       field   PHASEMIS        0x10
       field   BUSFREE         0x08
       field   SCSIPERR        0x04
       field   PHASECHG        0x02
       field   REQINIT         0x01
}

/*
* SCSI Status 2 (pp. 3-25,26)
*/
register SSTAT2 {
       address                 0x00d
       access_mode RO
       field   OVERRUN         0x80
       field   SHVALID         0x40    /* Shadow Layer non-zero */
       field   EXP_ACTIVE      0x10    /* SCSI Expander Active */
       field   CRCVALERR       0x08    /* CRC doesn't match (U3 only) */
       field   CRCENDERR       0x04    /* No terminal CRC packet (U3 only) */
       field   CRCREQERR       0x02    /* Illegal CRC packet req (U3 only) */
       field   DUAL_EDGE_ERR   0x01    /* Incorrect data phase (U3 only) */
       mask    SFCNT           0x1f
}

/*
* SCSI Status 3 (p. 3-26)
*/
register SSTAT3 {
       address                 0x00e
       access_mode RO
       mask    SCSICNT         0xf0
       mask    OFFCNT          0x0f
       mask    U2OFFCNT        0x7f
}

/*
* 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
       field   ENSELDO         0x40
       field   ENSELDI         0x20
       field   ENSELINGO       0x10
       field   ENSWRAP         0x08
       field   ENIOERR         0x08    /* LVD Transceiver mode changes */
       field   ENSDONE         0x04
       field   ENSPIORDY       0x02
       field   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
       field   ENSELTIMO       0x80
       field   ENATNTARG       0x40
       field   ENSCSIRST       0x20
       field   ENPHASEMIS      0x10
       field   ENBUSFREE       0x08
       field   ENSCSIPERR      0x04
       field   ENPHASECHG      0x02
       field   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 RW
}

register SCSIBUSH {
       address                 0x013
       access_mode RW
}

/*
* 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
       field   STAGE6          0x20
       field   STAGE5          0x10
       field   STAGE4          0x08
       field   STAGE3          0x04
       field   STAGE2          0x02
       field   STAGE1          0x01
       alias   TARGIDIN
}

/*
* 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
       field   ONEBIT          0x08
}

register SCAMCTL {
       address                 0x01a
       access_mode RW
       field   ENSCAMSELO      0x80
       field   CLRSCAMSELID    0x40
       field   ALTSTIM         0x20
       field   DFLTTID         0x10
       mask    SCAMLVL         0x03
}

/*
* Target Mode Selecting in ID bitmask (aic7890/91/96/97)
*/
register TARGID {
       address                 0x01b
       size                    2
       access_mode RW
}

/*
* Serial Port I/O Capability 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
       field   SOFT1           0x80
       field   SOFT0           0x40
       field   SOFTCMDEN       0x20
       field   EXT_BRDCTL      0x10    /* External Board control */
       field   SEEPROM         0x08    /* External serial eeprom logic */
       field   EEPROM          0x04    /* Writable external BIOS ROM */
       field   ROM             0x02    /* Logic for accessing external ROM */
       field   SSPIOCPS        0x01    /* Termination and cable detection */
}

register BRDCTL {
       address                 0x01d
       field   BRDDAT7         0x80
       field   BRDDAT6         0x40
       field   BRDDAT5         0x20
       field   BRDSTB          0x10
       field   BRDCS           0x08
       field   BRDRW           0x04
       field   BRDCTL1         0x02
       field   BRDCTL0         0x01
       /* 7890 Definitions */
       field   BRDDAT4         0x10
       field   BRDDAT3         0x08
       field   BRDDAT2         0x04
       field   BRDRW_ULTRA2    0x02
       field   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
       field   EXTARBACK       0x80
       field   EXTARBREQ       0x40
       field   SEEMS           0x20
       field   SEERDY          0x10
       field   SEECS           0x08
       field   SEECK           0x04
       field   SEEDO           0x02
       field   SEEDI           0x01
}
/*
* 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
       field   DIAGLEDEN       0x80    /* Aic78X0 only */
       field   DIAGLEDON       0x40    /* Aic78X0 only */
       field   AUTOFLUSHDIS    0x20
       field   SELBUSB         0x08
       field   ENAB40          0x08    /* LVD transceiver active */
       field   ENAB20          0x04    /* SE/HVD transceiver active */
       field   SELWIDE         0x02
       field   XCVR            0x01    /* External transceiver active */
}

/*
* Sequencer Control (p. 3-33)
* Error detection mode and speed configuration
*/
register SEQCTL {
       address                 0x060
       access_mode RW
       field   PERRORDIS       0x80
       field   PAUSEDIS        0x40
       field   FAILDIS         0x20
       field   FASTMODE        0x10
       field   BRKADRINTEN     0x08
       field   STEP            0x04
       field   SEQRESET        0x02
       field   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
       field   ZERO            0x02
       field   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
}

const   STACK_SIZE      4

/*
* Board Control (p. 3-43)
*/
register BCTL {
       address                 0x084
       access_mode RW
       field   ACE             0x08
       field   ENABLE          0x01
}

/*
* On the aic78X0 chips, Board Control is replaced by the DSCommand
* register (p. 4-64)
*/
register DSCOMMAND0 {
       address                 0x084
       access_mode RW
       field   CACHETHEN       0x80    /* Cache Threshold enable */
       field   DPARCKEN        0x40    /* Data Parity Check Enable */
       field   MPARCKEN        0x20    /* Memory Parity Check Enable */
       field   EXTREQLCK       0x10    /* External Request Lock */
       /* aic7890/91/96/97 only */
       field   INTSCBRAMSEL    0x08    /* Internal SCB RAM Select */
       field   RAMPS           0x04    /* External SCB RAM Present */
       field   USCBSIZE32      0x02    /* Use 32byte SCB Page Size */
       field   CIOPARCKEN      0x01    /* Internal bus parity error enable */
}

register DSCOMMAND1 {
       address                 0x085
       access_mode RW
       mask    DSLATT          0xfc    /* PCI latency timer (non-ultra2) */
       field   HADDLDSEL1      0x02    /* Host Address Load Select Bits */
       field   HADDLDSEL0      0x01
}

/*
* Bus On/Off Time (p. 3-44) aic7770 only
*/
register BUSTIME {
       address                 0x085
       access_mode RW
       mask    BOFF            0xf0
       mask    BON             0x0f
}

/*
* Bus Speed (p. 3-45) aic7770 only
*/
register BUSSPD {
       address                 0x086
       access_mode RW
       mask    DFTHRSH         0xc0
       mask    STBOFF          0x38
       mask    STBON           0x07
       mask    DFTHRSH_100     0xc0
       mask    DFTHRSH_75      0x80
}

/* aic7850/55/60/70/80/95 only */
register DSPCISTATUS {
       address                 0x086
       mask    DFTHRSH_100     0xc0
}

/* aic7890/91/96/97 only */
register HS_MAILBOX {
       address                 0x086
       mask    HOST_MAILBOX    0xF0
       mask    SEQ_MAILBOX     0x0F
       mask    HOST_TQINPOS    0x80    /* Boundary at either 0 or 128 */
}

const   HOST_MAILBOX_SHIFT      4
const   SEQ_MAILBOX_SHIFT       0

/*
* Host Control (p. 3-47) R/W
* Overall host control of the device.
*/
register HCNTRL {
       address                 0x087
       access_mode RW
       field   POWRDN          0x40
       field   SWINT           0x10
       field   IRQMS           0x08
       field   PAUSE           0x04
       field   INTEN           0x02
       field   CHIPRST         0x01
       field   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 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
       field   BRKADRINT 0x08
       field   SCSIINT   0x04
       field   CMDCMPLT  0x02
       field   SEQINT    0x01
       mask    BAD_PHASE       SEQINT          /* unknown scsi bus phase */
       mask    SEND_REJECT     0x10|SEQINT     /* sending a message reject */
       mask    PROTO_VIOLATION 0x20|SEQINT     /* SCSI protocol violation */
       mask    NO_MATCH        0x30|SEQINT     /* no cmd match for reconnect */
       mask    IGN_WIDE_RES    0x40|SEQINT     /* Complex IGN Wide Res Msg */
       mask    PDATA_REINIT    0x50|SEQINT     /*
                                                * Returned to data phase
                                                * that requires data
                                                * transfer pointers to be
                                                * recalculated from the
                                                * transfer residual.
                                                */
       mask    HOST_MSG_LOOP   0x60|SEQINT     /*
                                                * The bus is ready for the
                                                * host to perform another
                                                * message transaction.  This
                                                * mechanism is used for things
                                                * like sync/wide negotiation
                                                * that require a kernel based
                                                * message state engine.
                                                */
       mask    BAD_STATUS      0x70|SEQINT     /* Bad status from target */
       mask    PERR_DETECTED   0x80|SEQINT     /*
                                                * Either the phase_lock
                                                * or inb_next routine has
                                                * noticed a parity error.
                                                */
       mask    DATA_OVERRUN    0x90|SEQINT     /*
                                                * Target attempted to write
                                                * beyond the bounds of its
                                                * command.
                                                */
       mask    MKMSG_FAILED    0xa0|SEQINT     /*
                                                * Target completed command
                                                * without honoring our ATN
                                                * request to issue a message.
                                                */
       mask    MISSED_BUSFREE  0xb0|SEQINT     /*
                                                * The sequencer never saw
                                                * the bus go free after
                                                * either a command complete
                                                * or disconnect message.
                                                */
       mask    SCB_MISMATCH    0xc0|SEQINT     /*
                                                * Downloaded SCB's tag does
                                                * not match the entry we
                                                * intended to download.
                                                */
       mask    NO_FREE_SCB     0xd0|SEQINT     /*
                                                * get_free_or_disc_scb failed.
                                                */
       mask    OUT_OF_RANGE    0xe0|SEQINT

       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
       field   CIOPARERR       0x80    /* Ultra2 only */
       field   PCIERRSTAT      0x40    /* PCI only */
       field   MPARERR         0x20    /* PCI only */
       field   DPARERR         0x10    /* PCI only */
       field   SQPARERR        0x08
       field   ILLOPCODE       0x04
       field   ILLSADDR        0x02
       field   ILLHADDR        0x01
}

/*
* Clear Interrupt Status (p. 3-52)
*/
register CLRINT {
       address                 0x092
       access_mode WO
       field   CLRPARERR       0x10    /* PCI only */
       field   CLRBRKADRINT    0x08
       field   CLRSCSIINT      0x04
       field   CLRCMDINT       0x02
       field   CLRSEQINT       0x01
}

register DFCNTRL {
       address                 0x093
       access_mode RW
       field   PRELOADEN       0x80    /* aic7890 only */
       field   WIDEODD         0x40
       field   SCSIEN          0x20
       field   SDMAEN          0x10
       field   SDMAENACK       0x10
       field   HDMAEN          0x08
       field   HDMAENACK       0x08
       field   DIRECTION       0x04
       field   FIFOFLUSH       0x02
       field   FIFORESET       0x01
}

register DFSTATUS {
       address                 0x094
       access_mode RO
       field   PRELOAD_AVAIL   0x80
       field   DFCACHETH       0x40
       field   FIFOQWDEMP      0x20
       field   MREQPEND        0x10
       field   HDONE           0x08
       field   DFTHRESH        0x04
       field   FIFOFULL        0x02
       field   FIFOEMP         0x01
}

register DFWADDR {
       address                 0x95
       access_mode RW
}

register DFRADDR {
       address                 0x97
       access_mode RW
}

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
       field   SCBAUTO         0x80
       mask    SCBCNT_MASK     0x1f
}

/*
* Queue In FIFO (p. 3-60)
* Input queue for queued SCBs (commands that the sequencer 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
}

/*
* Queue Out FIFO (p. 3-61)
* Queue of SCBs that have completed and await the host
*/
register QOUTFIFO {
       address                 0x09d
       access_mode WO
}

register CRCCONTROL1 {
       address                 0x09d
       access_mode RW
       field   CRCONSEEN               0x80
       field   CRCVALCHKEN             0x40
       field   CRCENDCHKEN             0x20
       field   CRCREQCHKEN             0x10
       field   TARGCRCENDEN            0x08
       field   TARGCRCCNTEN            0x04
}


/*
* Queue Out Count (p. 3-61)
* Number of queued SCBs in the Out FIFO
*/
register QOUTCNT {
       address                 0x09e
       access_mode RO
}

register SCSIPHASE {
       address                 0x09e
       access_mode RO
       field   STATUS_PHASE    0x20
       field   COMMAND_PHASE   0x10
       field   MSG_IN_PHASE    0x08
       field   MSG_OUT_PHASE   0x04
       field   DATA_IN_PHASE   0x02
       field   DATA_OUT_PHASE  0x01
       mask    DATA_PHASE_MASK 0x03
}

/*
* Special Function
*/
register SFUNCT {
       address                 0x09f
       access_mode RW
       field   ALT_MODE        0x80
}

/*
* SCB Definition (p. 5-4)
*/
scb {
       address         0x0a0
       size            64

       SCB_CDB_PTR {
               size    4
               alias   SCB_RESIDUAL_DATACNT
               alias   SCB_CDB_STORE
       }
       SCB_RESIDUAL_SGPTR {
               size    4
       }
       SCB_SCSI_STATUS {
               size    1
       }
       SCB_TARGET_PHASES {
               size    1
       }
       SCB_TARGET_DATA_DIR {
               size    1
       }
       SCB_TARGET_ITAG {
               size    1
       }
       SCB_DATAPTR {
               size    4
       }
       SCB_DATACNT {
               /*
                * The last byte is really the high address bits for
                * the data address.
                */
               size    4
               field   SG_LAST_SEG             0x80    /* In the fourth byte */
               mask    SG_HIGH_ADDR_BITS       0x7F    /* In the fourth byte */
       }
       SCB_SGPTR {
               size    4
               field   SG_RESID_VALID  0x04    /* In the first byte */
               field   SG_FULL_RESID   0x02    /* In the first byte */
               field   SG_LIST_NULL    0x01    /* In the first byte */
       }
       SCB_CONTROL {
               size    1
               field   TARGET_SCB                      0x80
               field   STATUS_RCVD                     0x80
               field   DISCENB                         0x40
               field   TAG_ENB                         0x20
               field   MK_MESSAGE                      0x10
               field   ULTRAENB                        0x08
               field   DISCONNECTED                    0x04
               mask    SCB_TAG_TYPE                    0x03
       }
       SCB_SCSIID {
               size    1
               field   TWIN_CHNLB                      0x80
               mask    TWIN_TID                        0x70
               mask    TID                             0xf0
               mask    OID                             0x0f
       }
       SCB_LUN {
               mask    LID                             0xff
               size    1
       }
       SCB_TAG {
               size    1
       }
       SCB_CDB_LEN {
               size    1
       }
       SCB_SCSIRATE {
               size    1
       }
       SCB_SCSIOFFSET {
               size    1
       }
       SCB_NEXT {
               size    1
       }
       SCB_64_SPARE {
               size    16
       }
       SCB_64_BTT {
               size    16
       }
}

const   SCB_UPLOAD_SIZE         32
const   SCB_DOWNLOAD_SIZE       32
const   SCB_DOWNLOAD_SIZE_64    48

const   SG_SIZEOF       0x08            /* sizeof(struct ahc_dma) */

/* --------------------- AHA-2840-only definitions -------------------- */

register SEECTL_2840 {
       address                 0x0c0
       access_mode RW
       field   CS_2840         0x04
       field   CK_2840         0x02
       field   DO_2840         0x01
}

register STATUS_2840 {
       address                 0x0c1
       access_mode RW
       field   EEPROM_TF       0x80
       mask    BIOS_SEL        0x60
       mask    ADSEL           0x1e
       field   DI_2840         0x01
}

/* --------------------- AIC-7870-only definitions -------------------- */

register CCHADDR {
       address                 0x0E0
       size 8
}

register CCHCNT {
       address                 0x0E8
}

register CCSGRAM {
       address                 0x0E9
}

register CCSGADDR {
       address                 0x0EA
}

register CCSGCTL {
       address                 0x0EB
       field   CCSGDONE        0x80
       field   CCSGEN          0x08
       field   SG_FETCH_NEEDED 0x02    /* Bit used for software state */
       field   CCSGRESET       0x01
}

register CCSCBCNT {
       address                 0xEF
}

register CCSCBCTL {
       address                 0x0EE
       field   CCSCBDONE       0x80
       field   ARRDONE         0x40    /* SCB Array prefetch done */
       field   CCARREN         0x10
       field   CCSCBEN         0x08
       field   CCSCBDIR        0x04
       field   CCSCBRESET      0x01
}

register CCSCBADDR {
       address                 0x0ED
}

register CCSCBRAM {
       address                 0xEC
}

/*
* SCB bank address (7895/7896/97 only)
*/
register SCBBADDR {
       address                 0x0F0
       access_mode RW
}

register CCSCBPTR {
       address                 0x0F1
}

register HNSCB_QOFF {
       address                 0x0F4
}

register SNSCB_QOFF {
       address                 0x0F6
}

register SDSCB_QOFF {
       address                 0x0F8
}

register QOFF_CTLSTA {
       address                 0x0FA
       field   SCB_AVAIL       0x40
       field   SNSCB_ROLLOVER  0x20
       field   SDSCB_ROLLOVER  0x10
       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_CACHE_PRE {
       access_mode WO
       address                 0x0fc
       mask    SG_ADDR_MASK    0xf8
       field   ODD_SEG         0x04
       field   LAST_SEG        0x02
       field   LAST_SEG_DONE   0x01
}

register SG_CACHE_SHADOW {
       access_mode RO
       address                 0x0fc
       mask    SG_ADDR_MASK    0xf8
       field   ODD_SEG         0x04
       field   LAST_SEG        0x02
       field   LAST_SEG_DONE   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
       size            58

       /*
        * 1 byte per target starting at this address for configuration values
        */
       BUSY_TARGETS {
               alias           TARG_SCSIRATE
               size            16
       }
       /*
        * Bit vector of targets that have ULTRA enabled as set by
        * the BIOS.  The Sequencer relies on a per-SCB field to
        * control whether to enable Ultra transfers or not.  During
        * initialization, we read this field and reuse it for 2
        * entries in the busy target table.
        */
       ULTRA_ENB {
               alias           CMDSIZE_TABLE
               size            2
       }
       /*
        * Bit vector of targets that have disconnection disabled as set by
        * the BIOS.  The Sequencer relies in a per-SCB field to control the
        * disconnect priveldge.  During initialization, we read this field
        * and reuse it for 2 entries in the busy target table.
        */
       DISC_DSB {
               size            2
       }
       CMDSIZE_TABLE_TAIL {
               size            4
       }
       /*
        * Partial transfer past cacheline end to be
        * transferred using an extra S/G.
        */
       MWI_RESIDUAL {
               size            1
               alias   TARG_IMMEDIATE_SCB
       }
       /*
        * SCBID of the next SCB to be started by the controller.
        */
       NEXT_QUEUED_SCB {
               size            1
       }
       /*
        * 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
               field   PRELOADEN       0x80
               field   WIDEODD         0x40
               field   SCSIEN          0x20
               field   SDMAEN          0x10
               field   SDMAENACK       0x10
               field   HDMAEN          0x08
               field   HDMAENACK       0x08
               field   DIRECTION       0x04    /* Set indicates PCI->SCSI */
               field   FIFOFLUSH       0x02
               field   FIFORESET       0x01
       }
       SEQ_FLAGS {
               size            1
               field   NOT_IDENTIFIED          0x80
               field   NO_CDB_SENT             0x40
               field   TARGET_CMD_IS_TAGGED    0x40
               field   DPHASE                  0x20
               /* Target flags */
               field   TARG_CMD_PENDING        0x10
               field   CMDPHASE_PENDING        0x08
               field   DPHASE_PENDING          0x04
               field   SPHASE_PENDING          0x02
               field   NO_DISCONNECT           0x01
       }
       /*
        * Temporary storage for the
        * target/channel/lun of a
        * reconnecting target
        */
       SAVED_SCSIID {
               size            1
       }
       SAVED_LUN {
               size            1
       }
       /*
        * The last bus phase as seen by the sequencer.
        */
       LASTPHASE {
               size            1
               field   CDI             0x80
               field   IOI             0x40
               field   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
       }
       /*
        * head of list of SCBs that have
        * completed but have not been
        * put into the qoutfifo.
        */
       COMPLETE_SCBH {
               size            1
       }
       /*
        * Address of the hardware scb array in the host.
        */
       HSCB_ADDR {
               size            4
       }
       /*
        * Base address of our shared data with the kernel driver in host
        * memory.  This includes the qoutfifo and target mode
        * incoming command queue.
        */
       SHARED_DATA_ADDR {
               size            4
       }
       KERNEL_QINPOS {
               size            1
       }
       QINPOS {
               size            1
       }
       QOUTPOS {
               size            1
       }
       /*
        * Kernel and sequencer offsets into the queue of
        * incoming target mode command descriptors.  The
        * queue is full when the KERNEL_TQINPOS == TQINPOS.
        */
       KERNEL_TQINPOS {
               size            1
       }
       TQINPOS {
               size            1
       }
       ARG_1 {
               size            1
               mask    SEND_MSG                0x80
               mask    SEND_SENSE              0x40
               mask    SEND_REJ                0x20
               mask    MSGOUT_PHASEMIS         0x10
               mask    EXIT_MSG_LOOP           0x08
               mask    CONT_MSG_LOOP           0x04
               mask    CONT_TARG_SESSION       0x02
               alias   RETURN_1
       }
       ARG_2 {
               size            1
               alias   RETURN_2
       }

       /*
        * Snapshot of MSG_OUT taken after each message is sent.
        */
       LAST_MSG {
               size            1
       }

       /*
        * Sequences the kernel driver has okayed for us.  This allows
        * the driver to do things like prevent initiator or target
        * operations.
        */
       SCSISEQ_TEMPLATE {
               size            1
               field   ENSELO          0x40
               field   ENSELI          0x20
               field   ENRSELI         0x10
               field   ENAUTOATNO      0x08
               field   ENAUTOATNI      0x04
               field   ENAUTOATNP      0x02
       }

       /*
        * Track whether the transfer byte count for
        * the current data phase is odd.
        */
       DATA_COUNT_ODD {
               size            1
       }
}

scratch_ram {
       address         0x056
       size            4
       /*
        * These scratch ram locations are initialized by the 274X BIOS.
        * We reuse them after capturing the BIOS settings during
        * initialization.
        */

       /*
        * The initiator specified tag for this target mode transaction.
        */
       HA_274_BIOSGLOBAL {
               size    1
               field   HA_274_EXTENDED_TRANS   0x01
               alias   INITIATOR_TAG
       }

       SEQ_FLAGS2 {
               size    1
               field   SCB_DMA                 0x01
               field   TARGET_MSG_PENDING      0x02
       }
}

scratch_ram {
       address         0x05a
       size            6
       /*
        * These are reserved registers in the card's scratch ram on the 2742.
        * The EISA configuration chip is mapped here.  On Rev E. of the
        * aic7770, the sequencer can use this area for scratch, but the
        * host cannot directly access these registers.  On later chips, this
        * area can be read and written by both the host and the sequencer.
        * Even on later chips, many of these locations are initialized by
        * the BIOS.
        */
       SCSICONF {
               size            1
               field   TERM_ENB        0x80
               field   RESET_SCSI      0x40
               field   ENSPCHK         0x20
               mask    HSCSIID         0x07    /* our SCSI ID */
               mask    HWSCSIID        0x0f    /* our SCSI ID if Wide Bus */
       }
       INTDEF {
               address         0x05c
               size            1
               field   EDGE_TRIG       0x80
               mask    VECTOR          0x0f
       }
       HOSTCONF {
               address         0x05d
               size            1
       }
       HA_274_BIOSCTRL {
               address         0x05f
               size            1
               mask    BIOSMODE                0x30
               mask    BIOSDISABLED            0x30
               field   CHANNEL_B_PRIMARY       0x08
       }
}

scratch_ram {
       address         0x070
       size            16

       /*
        * Per target SCSI offset values for Ultra2 controllers.
        */
       TARG_OFFSET {
               size            16
       }
}

const TID_SHIFT         4
const SCB_LIST_NULL     0xff
const TARGET_CMD_CMPLT  0xfe

const CCSGADDR_MAX      0x80
const CCSGRAM_MAXSEGS   16

/* 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 MAX_OFFSET                0xff
const HOST_MSG                  0xff

/* Target mode command processing constants */
const CMD_GROUP_CODE_SHIFT      0x05

const STATUS_BUSY               0x08
const STATUS_QUEUE_FULL 0x28
const TARGET_DATA_IN            1

/*
* Downloaded (kernel inserted) constants
*/
/* Offsets into the SCBID array where different data is stored */
const QOUTFIFO_OFFSET download
const QINFIFO_OFFSET download
const CACHESIZE_MASK download
const INVERTED_CACHESIZE_MASK download
const SG_PREFETCH_CNT download
const SG_PREFETCH_ALIGN_MASK download
const SG_PREFETCH_ADDR_MASK download