summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/microcode/aic7xxx/Makefile10
-rw-r--r--sys/dev/microcode/aic7xxx/aic79xx.reg3961
-rw-r--r--sys/dev/microcode/aic7xxx/aic79xx.seq2034
-rw-r--r--sys/dev/microcode/aic7xxx/aic79xx_seq.h1140
-rw-r--r--sys/dev/microcode/aic7xxx/aic7xxx.reg956
-rw-r--r--sys/dev/microcode/aic7xxx/aic7xxx.seq2448
6 files changed, 8894 insertions, 1655 deletions
diff --git a/sys/dev/microcode/aic7xxx/Makefile b/sys/dev/microcode/aic7xxx/Makefile
index 1234df894d6..727fca11b29 100644
--- a/sys/dev/microcode/aic7xxx/Makefile
+++ b/sys/dev/microcode/aic7xxx/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.5 2002/06/30 18:25:58 smurph Exp $
+# $OpenBSD: Makefile,v 1.6 2003/12/24 22:40:16 krw Exp $
# $FreeBSD: src/sys/dev/aic7xxx/Makefile,v 1.6 1999/08/28 00:41:22 peter Exp $
PROG= aicasm
@@ -9,7 +9,7 @@ GENSRCS= aicasm_gram.c aicasm_scan.c aicasm_macro_gram.c aicasm_macro_scan.c
GENHDRS= y.tab.h
SRCS= ${GENSRCS} ${CSRCS}
-CLEANFILES+= ${GENSRCS} ${GENHDRS} y.output aic7xxxreg.h
+CLEANFILES+= ${GENSRCS} ${GENHDRS} y.output
DPADD+= ${LIBL}
LDADD+= -ll
@@ -32,15 +32,15 @@ LFLAGS+= -d
SEQFLAGS= -l seq.lst
.endif
-microcode aic7xxxreg.h aic7xxx_seq.h: aic7xxx.seq aic7xxx.reg
+microcode aic7xxx_reg.h aic7xxx_seq.h: aic7xxx.seq aic7xxx.reg
${OBJDIR}./aicasm -I/sys ${SEQFLAGS} -r tempreg.h -o tempseq.h ${.CURDIR}/aic7xxx.seq
grep OpenBSD: ${.CURDIR}/aic7xxx.seq | cat - tempseq.h > aic7xxx_seq.h
- grep OpenBSD: ${.CURDIR}/aic7xxx.reg | cat - tempreg.h > aic7xxxreg.h
+ grep OpenBSD: ${.CURDIR}/aic7xxx.reg | cat - tempreg.h > aic7xxx_reg.h
mv aic7xxx_seq.h /sys/dev/microcode/aic7xxx/
.ifdef DEBUG
mv seq.lst /sys/dev/microcode/aic7xxx/
.endif
- cp aic7xxxreg.h /sys/dev/ic/
+ mv aic7xxx_reg.h /sys/dev/microcode/aic7xxx/
rm -f tempseq.h tempreg.h
.include <bsd.prog.mk>
diff --git a/sys/dev/microcode/aic7xxx/aic79xx.reg b/sys/dev/microcode/aic7xxx/aic79xx.reg
new file mode 100644
index 00000000000..927974e69ab
--- /dev/null
+++ b/sys/dev/microcode/aic7xxx/aic79xx.reg
@@ -0,0 +1,3961 @@
+/* $OpenBSD: aic79xx.reg,v 1.1 2003/12/24 22:40:16 krw Exp $ */
+/* $NetBSD: aic79xx.reg,v 1.8 2003/08/29 03:45:59 thorpej Exp $ */
+
+/*
+ * Aic79xx register and scratch ram definitions.
+ *
+ * Copyright (c) 1994-2001 Justin T. Gibbs.
+ * Copyright (c) 2000-2002 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: src/sys/dev/aic7xxx/aic79xx.reg,v 1.15 2003/06/10 03:25:24 gibbs Exp $
+ */
+VERSION = "Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $"
+
+/*
+ * This file is processed by the aic7xxx_asm utility for use in assembling
+ * firmware for the aic79xx family of SCSI host adapters as well as to generate
+ * a C header file for use in the kernel portion of the Aic79xx driver.
+ */
+
+/* Register window Modes */
+#define M_DFF0 0
+#define M_DFF1 1
+#define M_CCHAN 2
+#define M_SCSI 3
+#define M_CFG 4
+#define M_DST_SHIFT 4
+
+#define MK_MODE(src, dst) ((src) | ((dst) << M_DST_SHIFT))
+#define SET_MODE(src, dst) \
+ SET_SRC_MODE src; \
+ SET_DST_MODE dst; \
+ if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \
+ mvi MK_MODE(src, dst) call set_mode_work_around; \
+ } else { \
+ mvi MODE_PTR, MK_MODE(src, dst); \
+ }
+
+#define TOGGLE_DFF_MODE \
+ if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \
+ call toggle_dff_mode_work_around; \
+ } else { \
+ xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); \
+ }
+
+#define RESTORE_MODE(mode) \
+ if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \
+ mov mode call set_mode_work_around; \
+ } else { \
+ mov MODE_PTR, mode; \
+ }
+
+#define SET_SEQINTCODE(code) \
+ if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) { \
+ mvi code call set_seqint_work_around; \
+ } else { \
+ mvi SEQINTCODE, code; \
+ }
+
+/*
+ * Mode Pointer
+ * Controls which of the 5, 512byte, address spaces should be used
+ * as the source and destination of any register accesses in our
+ * register window.
+ */
+register MODE_PTR {
+ address 0x000
+ access_mode RW
+ field DST_MODE 0x70
+ field SRC_MODE 0x07
+ mode_pointer
+}
+
+const SRC_MODE_SHIFT 0
+const DST_MODE_SHIFT 4
+
+/*
+ * Host Interrupt Status
+ */
+register INTSTAT {
+ address 0x001
+ access_mode RW
+ field HWERRINT 0x80
+ field BRKADRINT 0x40
+ field SWTMINT 0x20
+ field PCIINT 0x10
+ field SCSIINT 0x08
+ field SEQINT 0x04
+ field CMDCMPLT 0x02
+ field SPLTINT 0x01
+ mask INT_PEND 0xFF
+}
+
+/*
+ * Sequencer Interrupt Code
+ */
+register SEQINTCODE {
+ address 0x002
+ access_mode RW
+ field {
+ NO_SEQINT, /* No seqint pending. */
+ BAD_PHASE, /* unknown scsi bus phase */
+ SEND_REJECT, /* sending a message reject */
+ PROTO_VIOLATION, /* Protocol Violation */
+ NO_MATCH, /* no cmd match for reconnect */
+ IGN_WIDE_RES, /* Complex IGN Wide Res Msg */
+ PDATA_REINIT, /*
+ * Returned to data phase
+ * that requires data
+ * transfer pointers to be
+ * recalculated from the
+ * transfer residual.
+ */
+ HOST_MSG_LOOP, /*
+ * 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.
+ */
+ BAD_STATUS, /* Bad status from target */
+ DATA_OVERRUN, /*
+ * Target attempted to write
+ * beyond the bounds of its
+ * command.
+ */
+ MKMSG_FAILED, /*
+ * Target completed command
+ * without honoring our ATN
+ * request to issue a message.
+ */
+ MISSED_BUSFREE, /*
+ * The sequencer never saw
+ * the bus go free after
+ * either a command complete
+ * or disconnect message.
+ */
+ DUMP_CARD_STATE,
+ ILLEGAL_PHASE,
+ INVALID_SEQINT,
+ CFG4ISTAT_INTR,
+ STATUS_OVERRUN,
+ CFG4OVERRUN,
+ ENTERING_NONPACK,
+ TASKMGMT_FUNC_COMPLETE, /*
+ * Task management function
+ * request completed with
+ * an expected busfree.
+ */
+ TASKMGMT_CMD_CMPLT_OKAY, /*
+ * A command with a non-zero
+ * task management function
+ * has completed via the normal
+ * command completion method
+ * for commands with a zero
+ * task management function.
+ * This happens when an attempt
+ * to abort a command loses
+ * the race for the command to
+ * complete normally.
+ */
+ TRACEPOINT0,
+ TRACEPOINT1,
+ TRACEPOINT2,
+ TRACEPOINT3,
+ SAW_HWERR,
+ BAD_SCB_STATUS
+ }
+}
+
+/*
+ * Clear Host Interrupt
+ */
+register CLRINT {
+ address 0x003
+ access_mode WO
+ field CLRHWERRINT 0x80 /* Rev B or greater */
+ field CLRBRKADRINT 0x40
+ field CLRSWTMINT 0x20
+ field CLRPCIINT 0x10
+ field CLRSCSIINT 0x08
+ field CLRSEQINT 0x04
+ field CLRCMDINT 0x02
+ field CLRSPLTINT 0x01
+}
+
+/*
+ * Error Register
+ */
+register ERROR {
+ address 0x004
+ access_mode RO
+ field CIOPARERR 0x80
+ field CIOACCESFAIL 0x40 /* Rev B or greater */
+ field MPARERR 0x20
+ field DPARERR 0x10
+ field SQPARERR 0x08
+ field ILLOPCODE 0x04
+ field DSCTMOUT 0x02
+}
+
+/*
+ * Clear Error
+ */
+register CLRERR {
+ address 0x004
+ access_mode WO
+ field CLRCIOPARERR 0x80
+ field CLRCIOACCESFAIL 0x40 /* Rev B or greater */
+ field CLRMPARERR 0x20
+ field CLRDPARERR 0x10
+ field CLRSQPARERR 0x08
+ field CLRILLOPCODE 0x04
+ field CLRDSCTMOUT 0x02
+}
+
+/*
+ * Host Control Register
+ * Overall host control of the device.
+ */
+register HCNTRL {
+ address 0x005
+ access_mode RW
+ field SEQ_RESET 0x80 /* Rev B or greater */
+ field POWRDN 0x40
+ field SWINT 0x10
+ field SWTIMER_START_B 0x08 /* Rev B or greater */
+ field PAUSE 0x04
+ field INTEN 0x02
+ field CHIPRST 0x01
+ field CHIPRSTACK 0x01
+}
+
+/*
+ * Host New SCB Queue Offset
+ */
+register HNSCB_QOFF {
+ address 0x006
+ access_mode RW
+ size 2
+}
+
+/*
+ * Host Empty SCB Queue Offset
+ */
+register HESCB_QOFF {
+ address 0x008
+ access_mode RW
+}
+
+/*
+ * Host Mailbox
+ */
+register HS_MAILBOX {
+ address 0x00B
+ access_mode RW
+ mask HOST_TQINPOS 0x80 /* Boundary at either 0 or 128 */
+ mask ENINT_COALESCE 0x40 /* Perform interrupt coalescing */
+}
+
+/*
+ * Sequencer Interupt Status
+ */
+register SEQINTSTAT {
+ address 0x00C
+ access_mode RO
+ field SEQ_SWTMRTO 0x10
+ field SEQ_SEQINT 0x08
+ field SEQ_SCSIINT 0x04
+ field SEQ_PCIINT 0x02
+ field SEQ_SPLTINT 0x01
+}
+
+/*
+ * Clear SEQ Interrupt
+ */
+register CLRSEQINTSTAT {
+ address 0x00C
+ access_mode WO
+ field CLRSEQ_SWTMRTO 0x10
+ field CLRSEQ_SEQINT 0x08
+ field CLRSEQ_SCSIINT 0x04
+ field CLRSEQ_PCIINT 0x02
+ field CLRSEQ_SPLTINT 0x01
+}
+
+/*
+ * Software Timer
+ */
+register SWTIMER {
+ address 0x00E
+ access_mode RW
+ size 2
+}
+
+/*
+ * SEQ New SCB Queue Offset
+ */
+register SNSCB_QOFF {
+ address 0x010
+ access_mode RW
+ size 2
+ modes M_CCHAN
+}
+
+/*
+ * SEQ Empty SCB Queue Offset
+ */
+register SESCB_QOFF {
+ address 0x012
+ access_mode RW
+ modes M_CCHAN
+}
+
+/*
+ * SEQ Done SCB Queue Offset
+ */
+register SDSCB_QOFF {
+ address 0x014
+ access_mode RW
+ modes M_CCHAN
+ size 2
+}
+
+/*
+ * Queue Offset Control & Status
+ */
+register QOFF_CTLSTA {
+ address 0x016
+ access_mode RW
+ modes M_CCHAN
+ field EMPTY_SCB_AVAIL 0x80
+ field NEW_SCB_AVAIL 0x40
+ field SDSCB_ROLLOVR 0x20
+ field HS_MAILBOX_ACT 0x10
+ field SCB_QSIZE 0x0F {
+ SCB_QSIZE_4,
+ SCB_QSIZE_8,
+ SCB_QSIZE_16,
+ SCB_QSIZE_32,
+ SCB_QSIZE_64,
+ SCB_QSIZE_128,
+ SCB_QSIZE_256,
+ SCB_QSIZE_512,
+ SCB_QSIZE_1024,
+ SCB_QSIZE_2048,
+ SCB_QSIZE_4096,
+ SCB_QSIZE_8192,
+ SCB_QSIZE_16384
+ }
+}
+
+/*
+ * Interrupt Control
+ */
+register INTCTL {
+ address 0x018
+ access_mode RW
+ field SWTMINTMASK 0x80
+ field SWTMINTEN 0x40
+ field SWTIMER_START 0x20
+ field AUTOCLRCMDINT 0x10
+ field PCIINTEN 0x08
+ field SCSIINTEN 0x04
+ field SEQINTEN 0x02
+ field SPLTINTEN 0x01
+}
+
+/*
+ * Data FIFO Control
+ */
+register DFCNTRL {
+ address 0x019
+ access_mode RW
+ modes M_DFF0, M_DFF1
+ field PRELOADEN 0x80
+ field SCSIENWRDIS 0x40 /* Rev B only. */
+ field SCSIEN 0x20
+ field SCSIENACK 0x20
+ field HDMAEN 0x08
+ field HDMAENACK 0x08
+ field DIRECTION 0x04
+ field DIRECTIONACK 0x04
+ field FIFOFLUSH 0x02
+ field FIFOFLUSHACK 0x02
+ field DIRECTIONEN 0x01
+}
+
+/*
+ * Device Space Command 0
+ */
+register DSCOMMAND0 {
+ address 0x019
+ access_mode RW
+ modes M_CFG
+ 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 */
+ field DISABLE_TWATE 0x02 /* Rev B or greater */
+ field CIOPARCKEN 0x01 /* Internal bus parity error enable */
+}
+
+/*
+ * Data FIFO Status
+ */
+register DFSTATUS {
+ address 0x01A
+ access_mode RO
+ modes M_DFF0, M_DFF1
+ field PRELOAD_AVAIL 0x80
+ field PKT_PRELOAD_AVAIL 0x40
+ field MREQPEND 0x10
+ field HDONE 0x08
+ field DFTHRESH 0x04
+ field FIFOFULL 0x02
+ field FIFOEMP 0x01
+}
+
+/*
+ * S/G Cache Pointer
+ */
+register SG_CACHE_PRE {
+ address 0x01B
+ access_mode WO
+ modes M_DFF0, M_DFF1
+ field SG_ADDR_MASK 0xf8
+ field ODD_SEG 0x04
+ field LAST_SEG 0x02
+}
+
+register SG_CACHE_SHADOW {
+ address 0x01B
+ access_mode RO
+ modes M_DFF0, M_DFF1
+ field SG_ADDR_MASK 0xf8
+ field ODD_SEG 0x04
+ field LAST_SEG 0x02
+ field LAST_SEG_DONE 0x01
+}
+
+/*
+ * Arbiter Control
+ */
+register ARBCTL {
+ address 0x01B
+ access_mode RW
+ modes M_CFG
+ field RESET_HARB 0x80
+ field RETRY_SWEN 0x08
+ field USE_TIME 0x07
+}
+
+/*
+ * Data Channel Host Address
+ */
+register HADDR {
+ address 0x070
+ access_mode RW
+ size 8
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * Host Overlay DMA Address
+ */
+register HODMAADR {
+ address 0x070
+ access_mode RW
+ size 8
+ modes M_SCSI
+}
+
+/*
+ * PCI PLL Delay.
+ */
+register PLLDELAY {
+ address 0x070
+ access_mode RW
+ size 1
+ modes M_CFG
+ field SPLIT_DROP_REQ 0x80
+}
+
+/*
+ * Data Channel Host Count
+ */
+register HCNT {
+ address 0x078
+ access_mode RW
+ size 3
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * Host Overlay DMA Count
+ */
+register HODMACNT {
+ address 0x078
+ access_mode RW
+ size 2
+ modes M_SCSI
+}
+
+/*
+ * Host Overlay DMA Enable
+ */
+register HODMAEN {
+ address 0x07A
+ access_mode RW
+ modes M_SCSI
+}
+
+/*
+ * Scatter/Gather Host Address
+ */
+register SGHADDR {
+ address 0x07C
+ access_mode RW
+ size 8
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * SCB Host Address
+ */
+register SCBHADDR {
+ address 0x07C
+ access_mode RW
+ size 8
+ modes M_CCHAN
+}
+
+/*
+ * Scatter/Gather Host Count
+ */
+register SGHCNT {
+ address 0x084
+ access_mode RW
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * SCB Host Count
+ */
+register SCBHCNT {
+ address 0x084
+ access_mode RW
+ modes M_CCHAN
+}
+
+/*
+ * Data FIFO Threshold
+ */
+register DFF_THRSH {
+ address 0x088
+ access_mode RW
+ modes M_CFG
+ field WR_DFTHRSH 0x70 {
+ WR_DFTHRSH_MIN,
+ WR_DFTHRSH_25,
+ WR_DFTHRSH_50,
+ WR_DFTHRSH_63,
+ WR_DFTHRSH_75,
+ WR_DFTHRSH_85,
+ WR_DFTHRSH_90,
+ WR_DFTHRSH_MAX
+ }
+ field RD_DFTHRSH 0x07 {
+ RD_DFTHRSH_MIN,
+ RD_DFTHRSH_25,
+ RD_DFTHRSH_50,
+ RD_DFTHRSH_63,
+ RD_DFTHRSH_75,
+ RD_DFTHRSH_85,
+ RD_DFTHRSH_90,
+ RD_DFTHRSH_MAX
+ }
+}
+
+/*
+ * ROM Address
+ */
+register ROMADDR {
+ address 0x08A
+ access_mode RW
+ size 3
+}
+
+/*
+ * ROM Control
+ */
+register ROMCNTRL {
+ address 0x08D
+ access_mode RW
+ field ROMOP 0xE0
+ field ROMSPD 0x18
+ field REPEAT 0x02
+ field RDY 0x01
+}
+
+/*
+ * ROM Data
+ */
+register ROMDATA {
+ address 0x08E
+ access_mode RW
+}
+
+/*
+ * Data Channel Receive Message 0
+ */
+register DCHRXMSG0 {
+ address 0x090
+ access_mode RO
+ modes M_DFF0, M_DFF1
+ field CDNUM 0xF8
+ field CFNUM 0x07
+}
+
+/*
+ * CMC Recieve Message 0
+ */
+register CMCRXMSG0 {
+ address 0x090
+ access_mode RO
+ modes M_CCHAN
+ field CDNUM 0xF8
+ field CFNUM 0x07
+}
+
+/*
+ * Overlay Recieve Message 0
+ */
+register OVLYRXMSG0 {
+ address 0x090
+ access_mode RO
+ modes M_SCSI
+ field CDNUM 0xF8
+ field CFNUM 0x07
+}
+
+/*
+ * Relaxed Order Enable
+ */
+register ROENABLE {
+ address 0x090
+ access_mode RW
+ modes M_CFG
+ field MSIROEN 0x20
+ field OVLYROEN 0x10
+ field CMCROEN 0x08
+ field SGROEN 0x04
+ field DCH1ROEN 0x02
+ field DCH0ROEN 0x01
+}
+
+/*
+ * Data Channel Receive Message 1
+ */
+register DCHRXMSG1 {
+ address 0x091
+ access_mode RO
+ modes M_DFF0, M_DFF1
+ field CBNUM 0xFF
+}
+
+/*
+ * CMC Recieve Message 1
+ */
+register CMCRXMSG1 {
+ address 0x091
+ access_mode RO
+ modes M_CCHAN
+ field CBNUM 0xFF
+}
+
+/*
+ * Overlay Recieve Message 1
+ */
+register OVLYRXMSG1 {
+ address 0x091
+ access_mode RO
+ modes M_SCSI
+ field CBNUM 0xFF
+}
+
+/*
+ * No Snoop Enable
+ */
+register NSENABLE {
+ address 0x091
+ access_mode RW
+ modes M_CFG
+ field MSINSEN 0x20
+ field OVLYNSEN 0x10
+ field CMCNSEN 0x08
+ field SGNSEN 0x04
+ field DCH1NSEN 0x02
+ field DCH0NSEN 0x01
+}
+
+/*
+ * Data Channel Receive Message 2
+ */
+register DCHRXMSG2 {
+ address 0x092
+ access_mode RO
+ modes M_DFF0, M_DFF1
+ field MINDEX 0xFF
+}
+
+/*
+ * CMC Recieve Message 2
+ */
+register CMCRXMSG2 {
+ address 0x092
+ access_mode RO
+ modes M_CCHAN
+ field MINDEX 0xFF
+}
+
+/*
+ * Overlay Recieve Message 2
+ */
+register OVLYRXMSG2 {
+ address 0x092
+ access_mode RO
+ modes M_SCSI
+ field MINDEX 0xFF
+}
+
+/*
+ * Outstanding Split Transactions
+ */
+register OST {
+ address 0x092
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Data Channel Receive Message 3
+ */
+register DCHRXMSG3 {
+ address 0x093
+ access_mode RO
+ modes M_DFF0, M_DFF1
+ field MCLASS 0x0F
+}
+
+/*
+ * CMC Recieve Message 3
+ */
+register CMCRXMSG3 {
+ address 0x093
+ access_mode RO
+ modes M_CCHAN
+ field MCLASS 0x0F
+}
+
+/*
+ * Overlay Recieve Message 3
+ */
+register OVLYRXMSG3 {
+ address 0x093
+ access_mode RO
+ modes M_SCSI
+ field MCLASS 0x0F
+}
+
+/*
+ * PCI-X Control
+ */
+register PCIXCTL {
+ address 0x093
+ access_mode RW
+ modes M_CFG
+ field SERRPULSE 0x80
+ field UNEXPSCIEN 0x20
+ field SPLTSMADIS 0x10
+ field SPLTSTADIS 0x08
+ field SRSPDPEEN 0x04
+ field TSCSERREN 0x02
+ field CMPABCDIS 0x01
+}
+
+/*
+ * CMC Sequencer Byte Count
+ */
+register CMCSEQBCNT {
+ address 0x094
+ access_mode RO
+ modes M_CCHAN
+}
+
+/*
+ * Overlay Sequencer Byte Count
+ */
+register OVLYSEQBCNT {
+ address 0x094
+ access_mode RO
+ modes M_SCSI
+}
+
+/*
+ * Data Channel Sequencer Byte Count
+ */
+register DCHSEQBCNT {
+ address 0x094
+ access_mode RO
+ size 2
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * Data Channel Split Status 0
+ */
+register DCHSPLTSTAT0 {
+ address 0x096
+ access_mode RW
+ modes M_DFF0, M_DFF1
+ field STAETERM 0x80
+ field SCBCERR 0x40
+ field SCADERR 0x20
+ field SCDATBUCKET 0x10
+ field CNTNOTCMPLT 0x08
+ field RXOVRUN 0x04
+ field RXSCEMSG 0x02
+ field RXSPLTRSP 0x01
+}
+
+/*
+ * CMC Split Status 0
+ */
+register CMCSPLTSTAT0 {
+ address 0x096
+ access_mode RW
+ modes M_CCHAN
+ field STAETERM 0x80
+ field SCBCERR 0x40
+ field SCADERR 0x20
+ field SCDATBUCKET 0x10
+ field CNTNOTCMPLT 0x08
+ field RXOVRUN 0x04
+ field RXSCEMSG 0x02
+ field RXSPLTRSP 0x01
+}
+
+/*
+ * Overlay Split Status 0
+ */
+register OVLYSPLTSTAT0 {
+ address 0x096
+ access_mode RW
+ modes M_SCSI
+ field STAETERM 0x80
+ field SCBCERR 0x40
+ field SCADERR 0x20
+ field SCDATBUCKET 0x10
+ field CNTNOTCMPLT 0x08
+ field RXOVRUN 0x04
+ field RXSCEMSG 0x02
+ field RXSPLTRSP 0x01
+}
+
+/*
+ * Data Channel Split Status 1
+ */
+register DCHSPLTSTAT1 {
+ address 0x097
+ access_mode RW
+ modes M_DFF0, M_DFF1
+ field RXDATABUCKET 0x01
+}
+
+/*
+ * CMC Split Status 1
+ */
+register CMCSPLTSTAT1 {
+ address 0x097
+ access_mode RW
+ modes M_CCHAN
+ field RXDATABUCKET 0x01
+}
+
+/*
+ * Overlay Split Status 1
+ */
+register OVLYSPLTSTAT1 {
+ address 0x097
+ access_mode RW
+ modes M_SCSI
+ field RXDATABUCKET 0x01
+}
+
+/*
+ * S/G Receive Message 0
+ */
+register SGRXMSG0 {
+ address 0x098
+ access_mode RO
+ modes M_DFF0, M_DFF1
+ field CDNUM 0xF8
+ field CFNUM 0x07
+}
+
+/*
+ * S/G Receive Message 1
+ */
+register SGRXMSG1 {
+ address 0x099
+ access_mode RO
+ modes M_DFF0, M_DFF1
+ field CBNUM 0xFF
+}
+
+/*
+ * S/G Receive Message 2
+ */
+register SGRXMSG2 {
+ address 0x09A
+ access_mode RO
+ modes M_DFF0, M_DFF1
+ field MINDEX 0xFF
+}
+
+/*
+ * S/G Receive Message 3
+ */
+register SGRXMSG3 {
+ address 0x09B
+ access_mode RO
+ modes M_DFF0, M_DFF1
+ field MCLASS 0x0F
+}
+
+/*
+ * Slave Split Out Address 0
+ */
+register SLVSPLTOUTADR0 {
+ address 0x098
+ access_mode RO
+ modes M_SCSI
+ field LOWER_ADDR 0x7F
+}
+
+/*
+ * Slave Split Out Address 1
+ */
+register SLVSPLTOUTADR1 {
+ address 0x099
+ access_mode RO
+ modes M_SCSI
+ field REQ_DNUM 0xF8
+ field REQ_FNUM 0x07
+}
+
+/*
+ * Slave Split Out Address 2
+ */
+register SLVSPLTOUTADR2 {
+ address 0x09A
+ access_mode RO
+ modes M_SCSI
+ field REQ_BNUM 0xFF
+}
+
+/*
+ * Slave Split Out Address 3
+ */
+register SLVSPLTOUTADR3 {
+ address 0x09B
+ access_mode RO
+ modes M_SCSI
+ field RLXORD 020
+ field TAG_NUM 0x1F
+}
+
+/*
+ * SG Sequencer Byte Count
+ */
+register SGSEQBCNT {
+ address 0x09C
+ access_mode RO
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * Slave Split Out Attribute 0
+ */
+register SLVSPLTOUTATTR0 {
+ address 0x09C
+ access_mode RO
+ modes M_SCSI
+ field LOWER_BCNT 0xFF
+}
+
+/*
+ * Slave Split Out Attribute 1
+ */
+register SLVSPLTOUTATTR1 {
+ address 0x09D
+ access_mode RO
+ modes M_SCSI
+ field CMPLT_DNUM 0xF8
+ field CMPLT_FNUM 0x07
+}
+
+/*
+ * Slave Split Out Attribute 2
+ */
+register SLVSPLTOUTATTR2 {
+ address 0x09E
+ access_mode RO
+ size 2
+ modes M_SCSI
+ field CMPLT_BNUM 0xFF
+}
+/*
+ * S/G Split Status 0
+ */
+register SGSPLTSTAT0 {
+ address 0x09E
+ access_mode RW
+ modes M_DFF0, M_DFF1
+ field STAETERM 0x80
+ field SCBCERR 0x40
+ field SCADERR 0x20
+ field SCDATBUCKET 0x10
+ field CNTNOTCMPLT 0x08
+ field RXOVRUN 0x04
+ field RXSCEMSG 0x02
+ field RXSPLTRSP 0x01
+}
+
+/*
+ * S/G Split Status 1
+ */
+register SGSPLTSTAT1 {
+ address 0x09F
+ access_mode RW
+ modes M_DFF0, M_DFF1
+ field RXDATABUCKET 0x01
+}
+
+/*
+ * Special Function
+ */
+register SFUNCT {
+ address 0x09f
+ access_mode RW
+ modes M_CFG
+ field TEST_GROUP 0xF0
+ field TEST_NUM 0x0F
+}
+
+/*
+ * Data FIFO 0 PCI Status
+ */
+register DF0PCISTAT {
+ address 0x0A0
+ access_mode RW
+ modes M_CFG
+ field DPE 0x80
+ field SSE 0x40
+ field RMA 0x20
+ field RTA 0x10
+ field SCAAPERR 0x08
+ field RDPERR 0x04
+ field TWATERR 0x02
+ field DPR 0x01
+}
+
+/*
+ * Data FIFO 1 PCI Status
+ */
+register DF1PCISTAT {
+ address 0x0A1
+ access_mode RW
+ modes M_CFG
+ field DPE 0x80
+ field SSE 0x40
+ field RMA 0x20
+ field RTA 0x10
+ field SCAAPERR 0x08
+ field RDPERR 0x04
+ field TWATERR 0x02
+ field DPR 0x01
+}
+
+/*
+ * S/G PCI Status
+ */
+register SGPCISTAT {
+ address 0x0A2
+ access_mode RW
+ modes M_CFG
+ field DPE 0x80
+ field SSE 0x40
+ field RMA 0x20
+ field RTA 0x10
+ field SCAAPERR 0x08
+ field RDPERR 0x04
+ field DPR 0x01
+}
+
+/*
+ * CMC PCI Status
+ */
+register CMCPCISTAT {
+ address 0x0A3
+ access_mode RW
+ modes M_CFG
+ field DPE 0x80
+ field SSE 0x40
+ field RMA 0x20
+ field RTA 0x10
+ field SCAAPERR 0x08
+ field RDPERR 0x04
+ field TWATERR 0x02
+ field DPR 0x01
+}
+
+/*
+ * Overlay PCI Status
+ */
+register OVLYPCISTAT {
+ address 0x0A4
+ access_mode RW
+ modes M_CFG
+ field DPE 0x80
+ field SSE 0x40
+ field RMA 0x20
+ field RTA 0x10
+ field SCAAPERR 0x08
+ field RDPERR 0x04
+ field DPR 0x01
+}
+
+/*
+ * PCI Status for MSI Master DMA Transfer
+ */
+register MSIPCISTAT {
+ address 0x0A6
+ access_mode RW
+ modes M_CFG
+ field SSE 0x40
+ field RMA 0x20
+ field RTA 0x10
+ field CLRPENDMSI 0x08
+ field TWATERR 0x02
+ field DPR 0x01
+}
+
+/*
+ * PCI Status for Target
+ */
+register TARGPCISTAT {
+ address 0x0A7
+ access_mode RW
+ modes M_CFG
+ field DPE 0x80
+ field SSE 0x40
+ field STA 0x08
+ field TWATERR 0x02
+}
+
+/*
+ * LQ Packet In
+ * The last LQ Packet recieved
+ */
+register LQIN {
+ address 0x020
+ access_mode RW
+ size 20
+ modes M_DFF0, M_DFF1, M_SCSI
+}
+
+/*
+ * SCB Type Pointer
+ * SCB offset for Target Mode SCB type information
+ */
+register TYPEPTR {
+ address 0x020
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Queue Tag Pointer
+ * SCB offset to the Two Byte tag identifier used for target mode.
+ */
+register TAGPTR {
+ address 0x021
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Logical Unit Number Pointer
+ * SCB offset to the LSB (little endian) of the lun field.
+ */
+register LUNPTR {
+ address 0x022
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Data Length Pointer
+ * SCB offset for the 4 byte data length field in target mode.
+ */
+register DATALENPTR {
+ address 0x023
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Status Length Pointer
+ * SCB offset to the two byte status field in target SCBs.
+ */
+register STATLENPTR {
+ address 0x024
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Command Length Pointer
+ * Scb offset for the CDB length field in initiator SCBs.
+ */
+register CMDLENPTR {
+ address 0x025
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Task Attribute Pointer
+ * Scb offset for the byte field specifying the attribute byte
+ * to be used in command packets.
+ */
+register ATTRPTR {
+ address 0x026
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Task Management Flags Pointer
+ * Scb offset for the byte field specifying the attribute flags
+ * byte to be used in command packets.
+ */
+register FLAGPTR {
+ address 0x027
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Command Pointer
+ * Scb offset for the first byte in the CDB for initiator SCBs.
+ */
+register CMDPTR {
+ address 0x028
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Queue Next Pointer
+ * Scb offset for the 2 byte "next scb link".
+ */
+register QNEXTPTR {
+ address 0x029
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * SCSI ID Pointer
+ * Scb offset to the value to place in the SCSIID register
+ * during target mode connections.
+ */
+register IDPTR {
+ address 0x02A
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Command Aborted Byte Pointer
+ * Offset to the SCB flags field that includes the
+ * "SCB aborted" status bit.
+ */
+register ABRTBYTEPTR {
+ address 0x02B
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Command Aborted Bit Pointer
+ * Bit offset in the SCB flags field for "SCB aborted" status.
+ */
+register ABRTBITPTR {
+ address 0x02C
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Rev B or greater.
+ */
+register MAXCMDBYTES {
+ address 0x02D
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Rev B or greater.
+ */
+register MAXCMD2RCV {
+ address 0x02E
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Rev B or greater.
+ */
+register SHORTTHRESH {
+ address 0x02F
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Logical Unit Number Length
+ * The length, in bytes, of the SCB lun field.
+ */
+register LUNLEN {
+ address 0x030
+ access_mode RW
+ modes M_CFG
+ mask ILUNLEN 0x0F
+ mask TLUNLEN 0xF0
+}
+const LUNLEN_SINGLE_LEVEL_LUN 0xF
+
+/*
+ * CDB Limit
+ * The size, in bytes, of the embedded CDB field in initator SCBs.
+ */
+register CDBLIMIT {
+ address 0x031
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Maximum Commands
+ * The maximum number of commands to issue during a
+ * single packetized connection.
+ */
+register MAXCMD {
+ address 0x032
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * Maximum Command Counter
+ * The number of commands already sent during this connection
+ */
+register MAXCMDCNT {
+ address 0x033
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * LQ Packet Reserved Bytes
+ * The bytes to be sent in the currently reserved fileds
+ * of all LQ packets.
+ */
+register LQRSVD01 {
+ address 0x034
+ access_mode RW
+ modes M_SCSI
+}
+register LQRSVD16 {
+ address 0x035
+ access_mode RW
+ modes M_SCSI
+}
+register LQRSVD17 {
+ address 0x036
+ access_mode RW
+ modes M_SCSI
+}
+
+/*
+ * Command Reserved 0
+ * The byte to be sent for the reserved byte 0 of
+ * outgoing command packets.
+ */
+register CMDRSVD0 {
+ address 0x037
+ access_mode RW
+ modes M_CFG
+}
+
+/*
+ * LQ Manager Control 0
+ */
+register LQCTL0 {
+ address 0x038
+ access_mode RW
+ modes M_CFG
+ field LQITARGCLT 0xC0
+ field LQIINITGCLT 0x30
+ field LQ0TARGCLT 0x0C
+ field LQ0INITGCLT 0x03
+}
+
+/*
+ * LQ Manager Control 1
+ */
+register LQCTL1 {
+ address 0x038
+ access_mode RW
+ modes M_DFF0, M_DFF1, M_SCSI
+ field PCI2PCI 0x04
+ field SINGLECMD 0x02
+ field ABORTPENDING 0x01
+}
+
+/*
+ * LQ Manager Control 2
+ */
+register LQCTL2 {
+ address 0x039
+ access_mode RW
+ modes M_DFF0, M_DFF1, M_SCSI
+ field LQIRETRY 0x80
+ field LQICONTINUE 0x40
+ field LQITOIDLE 0x20
+ field LQIPAUSE 0x10
+ field LQORETRY 0x08
+ field LQOCONTINUE 0x04
+ field LQOTOIDLE 0x02
+ field LQOPAUSE 0x01
+}
+
+/*
+ * SCSI RAM BIST0
+ */
+register SCSBIST0 {
+ address 0x039
+ access_mode RW
+ modes M_CFG
+ field GSBISTERR 0x40
+ field GSBISTDONE 0x20
+ field GSBISTRUN 0x10
+ field OSBISTERR 0x04
+ field OSBISTDONE 0x02
+ field OSBISTRUN 0x01
+}
+
+/*
+ * SCSI Sequence Control0
+ */
+register SCSISEQ0 {
+ address 0x03A
+ access_mode RW
+ modes M_DFF0, M_DFF1, M_SCSI
+ field TEMODEO 0x80
+ field ENSELO 0x40
+ field ENARBO 0x20
+ field FORCEBUSFREE 0x10
+ field SCSIRSTO 0x01
+}
+
+/*
+ * SCSI RAM BIST 1
+ */
+register SCSBIST1 {
+ address 0x03A
+ access_mode RW
+ modes M_CFG
+ field NTBISTERR 0x04
+ field NTBISTDONE 0x02
+ field NTBISTRUN 0x01
+}
+
+/*
+ * SCSI Sequence Control 1
+ */
+register SCSISEQ1 {
+ address 0x03B
+ access_mode RW
+ modes M_DFF0, M_DFF1, M_SCSI
+ field MANUALCTL 0x40
+ field ENSELI 0x20
+ field ENRSELI 0x10
+ field MANUALP 0x0C
+ field ENAUTOATNP 0x02
+ field ALTSTIM 0x01
+}
+
+/*
+ * SCSI Transfer Control 0
+ */
+register SXFRCTL0 {
+ address 0x03C
+ access_mode RW
+ modes M_SCSI
+ field DFON 0x80
+ field DFPEXP 0x40
+ field BIOSCANCELEN 0x10
+ field SPIOEN 0x08
+}
+
+/*
+ * SCSI Transfer Control 1
+ */
+register SXFRCTL1 {
+ address 0x03D
+ access_mode RW
+ modes M_SCSI
+ field BITBUCKET 0x80
+ field ENSACHK 0x40
+ field ENSPCHK 0x20
+ field STIMESEL 0x18
+ field ENSTIMER 0x04
+ field ACTNEGEN 0x02
+ field STPWEN 0x01
+}
+
+/*
+ * SCSI Transfer Control 2
+ */
+register SXFRCTL2 {
+ address 0x03E
+ access_mode RW
+ modes M_SCSI
+ field AUTORSTDIS 0x10
+ field CMDDMAEN 0x08
+ field ASU 0x07
+}
+
+/*
+ * SCSI Bus Initiator IDs
+ * Bitmask of observed initiators on the bus.
+ */
+register BUSINITID {
+ address 0x03C
+ access_mode RW
+ modes M_CFG
+ size 2
+}
+
+/*
+ * Data Length Counters
+ * Packet byte counter.
+ */
+register DLCOUNT {
+ address 0x03C
+ access_mode RW
+ modes M_DFF0, M_DFF1
+ size 3
+}
+
+/*
+ * Data FIFO Status
+ */
+register DFFSTAT {
+ address 0x03F
+ access_mode RW
+ modes M_SCSI
+ field FIFO1FREE 0x20
+ field FIFO0FREE 0x10
+ /*
+ * On the B, this enum only works
+ * in the read direction. For writes,
+ * you must use the B version of the
+ * CURRFIFO_0 definition which is defined
+ * as a constant outside of this register
+ * definition to avoid confusing the
+ * register pretty printing code.
+ */
+ enum CURRFIFO 0x03 {
+ CURRFIFO_0,
+ CURRFIFO_1,
+ CURRFIFO_NONE 0x3
+ }
+}
+
+const B_CURRFIFO_0 0x2
+
+/*
+ * SCSI Bus Target IDs
+ * Bitmask of observed targets on the bus.
+ */
+register BUSTARGID {
+ address 0x03E
+ access_mode RW
+ modes M_CFG
+ size 2
+}
+
+/*
+ * SCSI Control Signal Out
+ */
+register SCSISIGO {
+ address 0x040
+ access_mode RW
+ modes M_DFF0, M_DFF1, M_SCSI
+ 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
+ */
+ enum PHASE_MASK CDO|IOO|MSGO {
+ P_DATAOUT 0x0,
+ P_DATAIN IOO,
+ P_DATAOUT_DT P_DATAOUT|MSGO,
+ P_DATAIN_DT P_DATAIN|MSGO,
+ P_COMMAND CDO,
+ P_MESGOUT CDO|MSGO,
+ P_STATUS CDO|IOO,
+ P_MESGIN CDO|IOO|MSGO
+ }
+}
+
+register SCSISIGI {
+ address 0x041
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+ 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
+ */
+ enum PHASE_MASK CDO|IOO|MSGO {
+ P_DATAOUT 0x0,
+ P_DATAIN IOO,
+ P_DATAOUT_DT P_DATAOUT|MSGO,
+ P_DATAIN_DT P_DATAIN|MSGO,
+ P_COMMAND CDO,
+ P_MESGOUT CDO|MSGO,
+ P_STATUS CDO|IOO,
+ P_MESGIN CDO|IOO|MSGO
+ }
+}
+
+/*
+ * Multiple Target IDs
+ * Bitmask of ids to respond as a target.
+ */
+register MULTARGID {
+ address 0x040
+ access_mode RW
+ modes M_CFG
+ size 2
+}
+
+/*
+ * SCSI Phase
+ */
+register SCSIPHASE {
+ address 0x042
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field STATUS_PHASE 0x20
+ field COMMAND_PHASE 0x10
+ field MSG_IN_PHASE 0x08
+ field MSG_OUT_PHASE 0x04
+ field DATA_PHASE_MASK 0x03 {
+ DATA_OUT_PHASE 0x01,
+ DATA_IN_PHASE 0x02
+ }
+}
+
+/*
+ * SCSI Data 0 Image
+ */
+register SCSIDAT0_IMG {
+ address 0x043
+ access_mode RW
+ modes M_DFF0, M_DFF1, M_SCSI
+}
+
+/*
+ * SCSI Latched Data
+ */
+register SCSIDAT {
+ address 0x044
+ access_mode RW
+ modes M_DFF0, M_DFF1, M_SCSI
+ size 2
+}
+
+/*
+ * SCSI Data Bus
+ */
+register SCSIBUS {
+ address 0x046
+ access_mode RW
+ modes M_DFF0, M_DFF1, M_SCSI
+ size 2
+}
+
+/*
+ * Target ID In
+ */
+register TARGIDIN {
+ address 0x048
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field CLKOUT 0x80
+ field TARGID 0x0F
+}
+
+/*
+ * Selection/Reselection ID
+ * 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 0x049
+ access_mode RW
+ modes M_DFF0, M_DFF1, M_SCSI
+ field SELID_MASK 0xf0
+ field ONEBIT 0x08
+}
+
+/*
+ * SCSI Block Control
+ * Controls Bus type and channel selection. SELWIDE allows for the
+ * coexistence of 8bit and 16bit devices on a wide bus.
+ */
+register SBLKCTL {
+ address 0x04A
+ access_mode RW
+ modes M_DFF0, M_DFF1, M_SCSI
+ field DIAGLEDEN 0x80
+ field DIAGLEDON 0x40
+ field ENAB40 0x08 /* LVD transceiver active */
+ field ENAB20 0x04 /* SE/HVD transceiver active */
+ field SELWIDE 0x02
+}
+
+/*
+ * Option Mode
+ */
+register OPTIONMODE {
+ address 0x04A
+ access_mode RW
+ modes M_CFG
+ field BIOSCANCTL 0x80
+ field AUTOACKEN 0x40
+ field BIASCANCTL 0x20
+ field BUSFREEREV 0x10
+ field ENDGFORMCHK 0x04
+ field AUTO_MSGOUT_DE 0x02
+ mask OPTIONMODE_DEFAULTS AUTO_MSGOUT_DE
+}
+
+/*
+ * SCSI Status 0
+ */
+register SSTAT0 {
+ address 0x04B
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+ 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 IOERR 0x08 /* LVD Tranceiver mode changed */
+ field OVERRUN 0x04 /* SCSI Offset overrun detected */
+ field SPIORDY 0x02 /* SCSI PIO Ready */
+ field ARBDO 0x01 /* Arbitration Done Out */
+}
+
+/*
+ * Clear SCSI Interrupt 0
+ * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT0.
+ */
+register CLRSINT0 {
+ address 0x04B
+ access_mode WO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field CLRSELDO 0x40
+ field CLRSELDI 0x20
+ field CLRSELINGO 0x10
+ field CLRIOERR 0x08
+ field CLROVERRUN 0x04
+ field CLRSPIORDY 0x02
+ field CLRARBDO 0x01
+}
+
+/*
+ * SCSI Interrupt Mode 0
+ * Setting any bit will enable the corresponding function
+ * in SIMODE0 to interrupt via the IRQ pin.
+ */
+register SIMODE0 {
+ address 0x04B
+ access_mode RW
+ modes M_CFG
+ field ENSELDO 0x40
+ field ENSELDI 0x20
+ field ENSELINGO 0x10
+ field ENIOERR 0x08
+ field ENOVERRUN 0x04
+ field ENSPIORDY 0x02
+ field ENARBDO 0x01
+}
+
+/*
+ * SCSI Status 1
+ */
+register SSTAT1 {
+ address 0x04C
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field SELTO 0x80
+ field ATNTARG 0x40
+ field SCSIRSTI 0x20
+ field PHASEMIS 0x10
+ field BUSFREE 0x08
+ field SCSIPERR 0x04
+ field STRB2FAST 0x02
+ field REQINIT 0x01
+}
+
+/*
+ * Clear SCSI Interrupt 1
+ * Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT1.
+ */
+register CLRSINT1 {
+ address 0x04C
+ access_mode WO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field CLRSELTIMEO 0x80
+ field CLRATNO 0x40
+ field CLRSCSIRSTI 0x20
+ field CLRBUSFREE 0x08
+ field CLRSCSIPERR 0x04
+ field CLRSTRB2FAST 0x02
+ field CLRREQINIT 0x01
+}
+
+/*
+ * SCSI Status 2
+ */
+register SSTAT2 {
+ address 0x04d
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field BUSFREETIME 0xc0 {
+ BUSFREE_LQO 0x40,
+ BUSFREE_DFF0 0x80,
+ BUSFREE_DFF1 0xC0
+ }
+ field NONPACKREQ 0x20
+ field EXP_ACTIVE 0x10 /* SCSI Expander Active */
+ field BSYX 0x08 /* Busy Expander */
+ field WIDE_RES 0x04 /* Modes 0 and 1 only */
+ field SDONE 0x02 /* Modes 0 and 1 only */
+ field DMADONE 0x01 /* Modes 0 and 1 only */
+}
+
+/*
+ * Clear SCSI Interrupt 2
+ */
+register CLRSINT2 {
+ address 0x04D
+ access_mode WO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field CLRNONPACKREQ 0x20
+ field CLRWIDE_RES 0x04 /* Modes 0 and 1 only */
+ field CLRSDONE 0x02 /* Modes 0 and 1 only */
+ field CLRDMADONE 0x01 /* Modes 0 and 1 only */
+}
+
+/*
+ * SCSI Interrupt Mode 2
+ */
+register SIMODE2 {
+ address 0x04D
+ access_mode RW
+ modes M_CFG
+ field ENWIDE_RES 0x04
+ field ENSDONE 0x02
+ field ENDMADONE 0x01
+}
+
+/*
+ * Physical Error Diagnosis
+ */
+register PERRDIAG {
+ address 0x04E
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field HIZERO 0x80
+ field HIPERR 0x40
+ field PREVPHASE 0x20
+ field PARITYERR 0x10
+ field AIPERR 0x08
+ field CRCERR 0x04
+ field DGFORMERR 0x02
+ field DTERR 0x01
+}
+
+/*
+ * LQI Manager Current State
+ */
+register LQISTATE {
+ address 0x04E
+ access_mode RO
+ modes M_CFG
+}
+
+/*
+ * SCSI Offset Count
+ */
+register SOFFCNT {
+ address 0x04F
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+}
+
+/*
+ * LQO Manager Current State
+ */
+register LQOSTATE {
+ address 0x04F
+ access_mode RO
+ modes M_CFG
+}
+
+/*
+ * LQI Manager Status
+ */
+register LQISTAT0 {
+ address 0x050
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field LQIATNQAS 0x20
+ field LQICRCT1 0x10
+ field LQICRCT2 0x08
+ field LQIBADLQT 0x04
+ field LQIATNLQ 0x02
+ field LQIATNCMD 0x01
+}
+
+/*
+ * Clear LQI Interrupts 0
+ */
+register CLRLQIINT0 {
+ address 0x050
+ access_mode WO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field CLRLQIATNQAS 0x20
+ field CLRLQICRCT1 0x10
+ field CLRLQICRCT2 0x08
+ field CLRLQIBADLQT 0x04
+ field CLRLQIATNLQ 0x02
+ field CLRLQIATNCMD 0x01
+}
+
+/*
+ * LQI Manager Interrupt Mode 0
+ */
+register LQIMODE0 {
+ address 0x050
+ access_mode RW
+ modes M_CFG
+ field ENLQIATNQASK 0x20
+ field ENLQICRCT1 0x10
+ field ENLQICRCT2 0x08
+ field ENLQIBADLQT 0x04
+ field ENLQIATNLQ 0x02
+ field ENLQIATNCMD 0x01
+}
+
+/*
+ * LQI Manager Status 1
+ */
+register LQISTAT1 {
+ address 0x051
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field LQIPHASE_LQ 0x80
+ field LQIPHASE_NLQ 0x40
+ field LQIABORT 0x20
+ field LQICRCI_LQ 0x10
+ field LQICRCI_NLQ 0x08
+ field LQIBADLQI 0x04
+ field LQIOVERI_LQ 0x02
+ field LQIOVERI_NLQ 0x01
+}
+
+/*
+ * Clear LQI Manager Interrupts1
+ */
+register CLRLQIINT1 {
+ address 0x051
+ access_mode WO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field CLRLQIPHASE_LQ 0x80
+ field CLRLQIPHASE_NLQ 0x40
+ field CLRLIQABORT 0x20
+ field CLRLQICRCI_LQ 0x10
+ field CLRLQICRCI_NLQ 0x08
+ field CLRLQIBADLQI 0x04
+ field CLRLQIOVERI_LQ 0x02
+ field CLRLQIOVERI_NLQ 0x01
+}
+
+/*
+ * LQI Manager Interrupt Mode 1
+ */
+register LQIMODE1 {
+ address 0x051
+ access_mode RW
+ modes M_CFG
+ field ENLQIPHASE_LQ 0x80 /* LQIPHASE1 */
+ field ENLQIPHASE_NLQ 0x40 /* LQIPHASE2 */
+ field ENLIQABORT 0x20
+ field ENLQICRCI_LQ 0x10 /* LQICRCI1 */
+ field ENLQICRCI_NLQ 0x08 /* LQICRCI2 */
+ field ENLQIBADLQI 0x04
+ field ENLQIOVERI_LQ 0x02 /* LQIOVERI1 */
+ field ENLQIOVERI_NLQ 0x01 /* LQIOVERI2 */
+}
+
+/*
+ * LQI Manager Status 2
+ */
+register LQISTAT2 {
+ address 0x052
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field PACKETIZED 0x80
+ field LQIPHASE_OUTPKT 0x40
+ field LQIWORKONLQ 0x20
+ field LQIWAITFIFO 0x10
+ field LQISTOPPKT 0x08
+ field LQISTOPLQ 0x04
+ field LQISTOPCMD 0x02
+ field LQIGSAVAIL 0x01
+}
+
+/*
+ * SCSI Status 3
+ */
+register SSTAT3 {
+ address 0x053
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field NTRAMPERR 0x02
+ field OSRAMPERR 0x01
+}
+
+/*
+ * Clear SCSI Status 3
+ */
+register CLRSINT3 {
+ address 0x053
+ access_mode WO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field CLRNTRAMPERR 0x02
+ field CLROSRAMPERR 0x01
+}
+
+/*
+ * SCSI Interrupt Mode 3
+ */
+register SIMODE3 {
+ address 0x053
+ access_mode RW
+ modes M_CFG
+ field ENNTRAMPERR 0x02
+ field ENOSRAMPERR 0x01
+}
+
+/*
+ * LQO Manager Status 0
+ */
+register LQOSTAT0 {
+ address 0x054
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field LQOTARGSCBPERR 0x10
+ field LQOSTOPT2 0x08
+ field LQOATNLQ 0x04
+ field LQOATNPKT 0x02
+ field LQOTCRC 0x01
+}
+
+/*
+ * Clear LQO Manager interrupt 0
+ */
+register CLRLQOINT0 {
+ address 0x054
+ access_mode WO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field CLRLQOTARGSCBPERR 0x10
+ field CLRLQOSTOPT2 0x08
+ field CLRLQOATNLQ 0x04
+ field CLRLQOATNPKT 0x02
+ field CLRLQOTCRC 0x01
+}
+
+/*
+ * LQO Manager Interrupt Mode 0
+ */
+register LQOMODE0 {
+ address 0x054
+ access_mode RW
+ modes M_CFG
+ field ENLQOTARGSCBPERR 0x10
+ field ENLQOSTOPT2 0x08
+ field ENLQOATNLQ 0x04
+ field ENLQOATNPKT 0x02
+ field ENLQOTCRC 0x01
+}
+
+/*
+ * LQO Manager Status 1
+ */
+register LQOSTAT1 {
+ address 0x055
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field LQOINITSCBPERR 0x10
+ field LQOSTOPI2 0x08
+ field LQOBADQAS 0x04
+ field LQOBUSFREE 0x02
+ field LQOPHACHGINPKT 0x01
+}
+
+/*
+ * Clear LOQ Interrupt 1
+ */
+register CLRLQOINT1 {
+ address 0x055
+ access_mode WO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field CLRLQOINITSCBPERR 0x10
+ field CLRLQOSTOPI2 0x08
+ field CLRLQOBADQAS 0x04
+ field CLRLQOBUSFREE 0x02
+ field CLRLQOPHACHGINPKT 0x01
+}
+
+/*
+ * LQO Manager Interrupt Mode 1
+ */
+register LQOMODE1 {
+ address 0x055
+ access_mode RW
+ modes M_CFG
+ field ENLQOINITSCBPERR 0x10
+ field ENLQOSTOPI2 0x08
+ field ENLQOBADQAS 0x04
+ field ENLQOBUSFREE 0x02
+ field ENLQOPHACHGINPKT 0x01
+}
+
+/*
+ * LQO Manager Status 2
+ */
+register LQOSTAT2 {
+ address 0x056
+ access_mode RO
+ modes M_DFF0, M_DFF1, M_SCSI
+ field LQOPKT 0xE0
+ field LQOWAITFIFO 0x10
+ field LQOPHACHGOUTPKT 0x02 /* outside of packet boundaries. */
+ field LQOSTOP0 0x01 /* Stopped after sending all packets */
+}
+
+/*
+ * Output Synchronizer Space Count
+ */
+register OS_SPACE_CNT {
+ address 0x056
+ access_mode RO
+ modes M_CFG
+}
+
+/*
+ * SCSI Interrupt Mode 1
+ * Setting any bit will enable the corresponding function
+ * in SIMODE1 to interrupt via the IRQ pin.
+ */
+register SIMODE1 {
+ address 0x057
+ access_mode RW
+ modes M_DFF0, M_DFF1, M_SCSI
+ field ENSELTIMO 0x80
+ field ENATNTARG 0x40
+ field ENSCSIRST 0x20
+ field ENPHASEMIS 0x10
+ field ENBUSFREE 0x08
+ field ENSCSIPERR 0x04
+ field ENSTRB2FAST 0x02
+ field ENREQINIT 0x01
+}
+
+/*
+ * Good Status FIFO
+ */
+register GSFIFO {
+ address 0x058
+ access_mode RO
+ size 2
+ modes M_DFF0, M_DFF1, M_SCSI
+}
+
+/*
+ * Data FIFO SCSI Transfer Control
+ */
+register DFFSXFRCTL {
+ address 0x05A
+ access_mode RW
+ modes M_DFF0, M_DFF1
+ field DFFBITBUCKET 0x08
+ field CLRSHCNT 0x04
+ field CLRCHN 0x02
+ field RSTCHN 0x01
+}
+
+/*
+ * Next SCSI Control Block
+ */
+register NEXTSCB {
+ address 0x05A
+ access_mode RW
+ size 2
+ modes M_SCSI
+}
+
+/* Rev B only. */
+register LQOSCSCTL {
+ address 0x05A
+ access_mode RW
+ size 1
+ modes M_CFG
+ field LQOH2A_VERSION 0x80
+ field LQONOCHKOVER 0x01
+}
+
+/*
+ * SEQ Interrupts
+ */
+register SEQINTSRC {
+ address 0x05B
+ access_mode RO
+ modes M_DFF0, M_DFF1
+ field CTXTDONE 0x40
+ field SAVEPTRS 0x20
+ field CFG4DATA 0x10
+ field CFG4ISTAT 0x08
+ field CFG4TSTAT 0x04
+ field CFG4ICMD 0x02
+ field CFG4TCMD 0x01
+}
+
+/*
+ * Clear Arp Interrupts
+ */
+register CLRSEQINTSRC {
+ address 0x05B
+ access_mode WO
+ modes M_DFF0, M_DFF1
+ field CLRCTXTDONE 0x40
+ field CLRSAVEPTRS 0x20
+ field CLRCFG4DATA 0x10
+ field CLRCFG4ISTAT 0x08
+ field CLRCFG4TSTAT 0x04
+ field CLRCFG4ICMD 0x02
+ field CLRCFG4TCMD 0x01
+}
+
+/*
+ * SEQ Interrupt Enabled (Shared)
+ */
+register SEQIMODE {
+ address 0x05C
+ access_mode RW
+ modes M_DFF0, M_DFF1
+ field ENCTXTDONE 0x40
+ field ENSAVEPTRS 0x20
+ field ENCFG4DATA 0x10
+ field ENCFG4ISTAT 0x08
+ field ENCFG4TSTAT 0x04
+ field ENCFG4ICMD 0x02
+ field ENCFG4TCMD 0x01
+}
+
+/*
+ * Current SCSI Control Block
+ */
+register CURRSCB {
+ address 0x05C
+ access_mode RW
+ size 2
+ modes M_SCSI
+}
+
+/*
+ * Data FIFO Status
+ */
+register MDFFSTAT {
+ address 0x05D
+ access_mode RO
+ modes M_DFF0, M_DFF1
+ field SHCNTNEGATIVE 0x40 /* Rev B or higher */
+ field SHCNTMINUS1 0x20 /* Rev B or higher */
+ field LASTSDONE 0x10
+ field SHVALID 0x08
+ field DLZERO 0x04 /* FIFO data ends on packet boundary. */
+ field DATAINFIFO 0x02
+ field FIFOFREE 0x01
+}
+
+/*
+ * CRC Control
+ */
+register CRCCONTROL {
+ address 0x05d
+ access_mode RW
+ modes M_CFG
+ field CRCVALCHKEN 0x40
+}
+
+/*
+ * SCSI Test Control
+ */
+register SCSITEST {
+ address 0x05E
+ access_mode RW
+ modes M_CFG
+ field CNTRTEST 0x08
+ field SEL_TXPLL_DEBUG 0x04
+}
+
+/*
+ * Data FIFO Queue Tag
+ */
+register DFFTAG {
+ address 0x05E
+ access_mode RW
+ size 2
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * Last SCSI Control Block
+ */
+register LASTSCB {
+ address 0x05E
+ access_mode RW
+ size 2
+ modes M_SCSI
+}
+
+/*
+ * SCSI I/O Cell Power-down Control
+ */
+register IOPDNCTL {
+ address 0x05F
+ access_mode RW
+ modes M_CFG
+ field DISABLE_OE 0x80
+ field PDN_IDIST 0x04
+ field PDN_DIFFSENSE 0x01
+}
+
+/*
+ * Shaddow Host Address.
+ */
+register SHADDR {
+ address 0x060
+ access_mode RO
+ size 8
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * Data Group CRC Interval.
+ */
+register DGRPCRCI {
+ address 0x060
+ access_mode RW
+ size 2
+ modes M_CFG
+}
+
+/*
+ * Data Transfer Negotiation Address
+ */
+register NEGOADDR {
+ address 0x060
+ access_mode RW
+ modes M_SCSI
+}
+
+/*
+ * Data Transfer Negotiation Data - Period Byte
+ */
+register NEGPERIOD {
+ address 0x061
+ access_mode RW
+ modes M_SCSI
+}
+
+/*
+ * Packetized CRC Interval
+ */
+register PACKCRCI {
+ address 0x062
+ access_mode RW
+ size 2
+ modes M_CFG
+}
+
+/*
+ * Data Transfer Negotiation Data - Offset Byte
+ */
+register NEGOFFSET {
+ address 0x062
+ access_mode RW
+ modes M_SCSI
+}
+
+/*
+ * Data Transfer Negotiation Data - PPR Options
+ */
+register NEGPPROPTS {
+ address 0x063
+ access_mode RW
+ modes M_SCSI
+ field PPROPT_PACE 0x08
+ field PPROPT_QAS 0x04
+ field PPROPT_DT 0x02
+ field PPROPT_IUT 0x01
+}
+
+/*
+ * Data Transfer Negotiation Data - Connection Options
+ */
+register NEGCONOPTS {
+ address 0x064
+ access_mode RW
+ modes M_SCSI
+ field ENSNAPSHOT 0x40
+ field RTI_WRTDIS 0x20
+ field RTI_OVRDTRN 0x10
+ field ENSLOWCRC 0x08
+ field ENAUTOATNI 0x04
+ field ENAUTOATNO 0x02
+ field WIDEXFER 0x01
+}
+
+/*
+ * Negotiation Table Annex Column Index.
+ */
+register ANNEXCOL {
+ address 0x065
+ access_mode RW
+ modes M_SCSI
+}
+
+register SCSCHKN {
+ address 0x066
+ access_mode RW
+ modes M_CFG
+ field STSELSKIDDIS 0x40
+ field CURRFIFODEF 0x20
+ field WIDERESEN 0x10
+ field SDONEMSKDIS 0x08
+ field DFFACTCLR 0x04
+ field SHVALIDSTDIS 0x02
+ field LSTSGCLRDIS 0x01
+}
+
+const AHD_ANNEXCOL_PER_DEV0 4
+const AHD_NUM_PER_DEV_ANNEXCOLS 4
+const AHD_ANNEXCOL_PRECOMP_SLEW 4
+const AHD_PRECOMP_MASK 0x07
+const AHD_PRECOMP_SHIFT 0
+const AHD_PRECOMP_CUTBACK_17 0x04
+const AHD_PRECOMP_CUTBACK_29 0x06
+const AHD_PRECOMP_CUTBACK_37 0x07
+const AHD_SLEWRATE_MASK 0x78
+const AHD_SLEWRATE_SHIFT 3
+/*
+ * Rev A has only a single bit (high bit of field) of slew adjustment.
+ * Rev B has 4 bits. The current default happens to be the same for both.
+ */
+const AHD_SLEWRATE_DEF_REVA 0x08
+const AHD_SLEWRATE_DEF_REVB 0x08
+
+/* Rev A does not have any amplitude setting. */
+const AHD_ANNEXCOL_AMPLITUDE 6
+const AHD_AMPLITUDE_MASK 0x7
+const AHD_AMPLITUDE_SHIFT 0
+const AHD_AMPLITUDE_DEF 0x7
+
+/*
+ * Negotiation Table Annex Data Port.
+ */
+register ANNEXDAT {
+ address 0x066
+ access_mode RW
+ modes M_SCSI
+}
+
+/*
+ * Initiator's Own Id.
+ * The SCSI ID to use for Selection Out and seen during a reselection..
+ */
+register IOWNID {
+ address 0x067
+ access_mode RW
+ modes M_SCSI
+}
+
+/*
+ * 960MHz Phase-Locked Loop Control 0
+ */
+register PLL960CTL0 {
+ address 0x068
+ access_mode RW
+ modes M_CFG
+ field PLL_VCOSEL 0x80
+ field PLL_PWDN 0x40
+ field PLL_NS 0x30
+ field PLL_ENLUD 0x08
+ field PLL_ENLPF 0x04
+ field PLL_DLPF 0x02
+ field PLL_ENFBM 0x01
+}
+
+/*
+ * Target Own Id
+ */
+register TOWNID {
+ address 0x069
+ access_mode RW
+ modes M_SCSI
+}
+
+/*
+ * 960MHz Phase-Locked Loop Control 1
+ */
+register PLL960CTL1 {
+ address 0x069
+ access_mode RW
+ modes M_CFG
+ field PLL_CNTEN 0x80
+ field PLL_CNTCLR 0x40
+ field PLL_RST 0x01
+}
+
+/*
+ * Expander Signature
+ */
+register XSIG {
+ address 0x06A
+ access_mode RW
+ modes M_SCSI
+}
+
+/*
+ * Shadow Byte Count
+ */
+register SHCNT {
+ address 0x068
+ access_mode RW
+ size 3
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * Selection Out ID
+ */
+register SELOID {
+ address 0x06B
+ access_mode RW
+ modes M_SCSI
+}
+
+/*
+ * 960-MHz Phase-Locked Loop Test Count
+ */
+register PLL960CNT0 {
+ address 0x06A
+ access_mode RO
+ size 2
+ modes M_CFG
+}
+
+/*
+ * 400-MHz Phase-Locked Loop Control 0
+ */
+register PLL400CTL0 {
+ address 0x06C
+ access_mode RW
+ modes M_CFG
+ field PLL_VCOSEL 0x80
+ field PLL_PWDN 0x40
+ field PLL_NS 0x30
+ field PLL_ENLUD 0x08
+ field PLL_ENLPF 0x04
+ field PLL_DLPF 0x02
+ field PLL_ENFBM 0x01
+}
+
+/*
+ * Arbitration Fairness
+ */
+register FAIRNESS {
+ address 0x06C
+ access_mode RW
+ size 2
+ modes M_SCSI
+}
+
+/*
+ * 400-MHz Phase-Locked Loop Control 1
+ */
+register PLL400CTL1 {
+ address 0x06D
+ access_mode RW
+ modes M_CFG
+ field PLL_CNTEN 0x80
+ field PLL_CNTCLR 0x40
+ field PLL_RST 0x01
+}
+
+/*
+ * Arbitration Unfairness
+ */
+register UNFAIRNESS {
+ address 0x06E
+ access_mode RW
+ size 2
+ modes M_SCSI
+}
+
+/*
+ * 400-MHz Phase-Locked Loop Test Count
+ */
+register PLL400CNT0 {
+ address 0x06E
+ access_mode RO
+ size 2
+ modes M_CFG
+}
+
+/*
+ * SCB Page Pointer
+ */
+register SCBPTR {
+ address 0x0A8
+ access_mode RW
+ size 2
+ modes M_DFF0, M_DFF1, M_CCHAN, M_SCSI
+}
+
+/*
+ * CMC SCB Array Count
+ * Number of bytes to transfer between CMC SCB memory and SCBRAM.
+ * Transfers must be 8byte aligned and sized.
+ */
+register CCSCBACNT {
+ address 0x0AB
+ access_mode RW
+ modes M_CCHAN
+}
+
+/*
+ * SCB Autopointer
+ * SCB-Next Address Snooping logic. When an SCB is transferred to
+ * the card, the next SCB address to be used by the CMC array can
+ * be autoloaded from that transfer.
+ */
+register SCBAUTOPTR {
+ address 0x0AB
+ access_mode RW
+ modes M_CFG
+ field AUSCBPTR_EN 0x80
+ field SCBPTR_ADDR 0x38
+ field SCBPTR_OFF 0x07
+}
+
+/*
+ * CMC SG Ram Address Pointer
+ */
+register CCSGADDR {
+ address 0x0AC
+ access_mode RW
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * CMC SCB RAM Address Pointer
+ */
+register CCSCBADDR {
+ address 0x0AC
+ access_mode RW
+ modes M_CCHAN
+}
+
+/*
+ * CMC SCB Ram Back-up Address Pointer
+ * Indicates the true stop location of transfers halted prior
+ * to SCBHCNT going to 0.
+ */
+register CCSCBADR_BK {
+ address 0x0AC
+ access_mode RO
+ modes M_CFG
+}
+
+/*
+ * CMC SG Control
+ */
+register CCSGCTL {
+ address 0x0AD
+ access_mode RW
+ modes M_DFF0, M_DFF1
+ field CCSGDONE 0x80
+ field SG_CACHE_AVAIL 0x10
+ field CCSGENACK 0x08
+ mask CCSGEN 0x0C
+ field SG_FETCH_REQ 0x02
+ field CCSGRESET 0x01
+}
+
+/*
+ * CMD SCB Control
+ */
+register CCSCBCTL {
+ address 0x0AD
+ access_mode RW
+ modes M_CCHAN
+ field CCSCBDONE 0x80
+ field ARRDONE 0x40
+ field CCARREN 0x10
+ field CCSCBEN 0x08
+ field CCSCBDIR 0x04
+ field CCSCBRESET 0x01
+}
+
+/*
+ * CMC Ram BIST
+ */
+register CMC_RAMBIST {
+ address 0x0AD
+ access_mode RW
+ modes M_CFG
+ field SG_ELEMENT_SIZE 0x80
+ field SCBRAMBIST_FAIL 0x40
+ field SG_BIST_FAIL 0x20
+ field SG_BIST_EN 0x10
+ field CMC_BUFFER_BIST_FAIL 0x02
+ field CMC_BUFFER_BIST_EN 0x01
+}
+
+/*
+ * CMC SG RAM Data Port
+ */
+register CCSGRAM {
+ address 0x0B0
+ access_mode RW
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * CMC SCB RAM Data Port
+ */
+register CCSCBRAM {
+ address 0x0B0
+ access_mode RW
+ modes M_CCHAN
+}
+
+/*
+ * Flex DMA Address.
+ */
+register FLEXADR {
+ address 0x0B0
+ access_mode RW
+ size 3
+ modes M_SCSI
+}
+
+/*
+ * Flex DMA Byte Count
+ */
+register FLEXCNT {
+ address 0x0B3
+ access_mode RW
+ size 2
+ modes M_SCSI
+}
+
+/*
+ * Flex DMA Status
+ */
+register FLEXDMASTAT {
+ address 0x0B5
+ access_mode RW
+ modes M_SCSI
+ field FLEXDMAERR 0x02
+ field FLEXDMADONE 0x01
+}
+
+/*
+ * Flex DMA Data Port
+ */
+register FLEXDATA {
+ address 0x0B6
+ access_mode RW
+ modes M_SCSI
+}
+
+/*
+ * Board Data
+ */
+register BRDDAT {
+ address 0x0B8
+ access_mode RW
+ modes M_SCSI
+}
+
+/*
+ * Board Control
+ */
+register BRDCTL {
+ address 0x0B9
+ access_mode RW
+ modes M_SCSI
+ field FLXARBACK 0x80
+ field FLXARBREQ 0x40
+ field BRDADDR 0x38
+ field BRDEN 0x04
+ field BRDRW 0x02
+ field BRDSTB 0x01
+}
+
+/*
+ * Serial EEPROM Address
+ */
+register SEEADR {
+ address 0x0BA
+ access_mode RW
+ modes M_SCSI
+}
+
+/*
+ * Serial EEPROM Data
+ */
+register SEEDAT {
+ address 0x0BC
+ access_mode RW
+ size 2
+ modes M_SCSI
+}
+
+/*
+ * Serial EEPROM Status
+ */
+register SEESTAT {
+ address 0x0BE
+ access_mode RO
+ modes M_SCSI
+ field INIT_DONE 0x80
+ field SEEOPCODE 0x70
+ field LDALTID_L 0x08
+ field SEEARBACK 0x04
+ field SEEBUSY 0x02
+ field SEESTART 0x01
+}
+
+/*
+ * Serial EEPROM Control
+ */
+register SEECTL {
+ address 0x0BE
+ access_mode RW
+ modes M_SCSI
+ field SEEOPCODE 0x70 {
+ SEEOP_ERASE 0x70,
+ SEEOP_READ 0x60,
+ SEEOP_WRITE 0x50,
+ /*
+ * The following four commands use special
+ * addresses for differentiation.
+ */
+ SEEOP_ERAL 0x40
+ }
+ mask SEEOP_EWEN 0x40
+ mask SEEOP_WALL 0x40
+ mask SEEOP_EWDS 0x40
+ field SEERST 0x02
+ field SEESTART 0x01
+}
+
+const SEEOP_ERAL_ADDR 0x80
+const SEEOP_EWEN_ADDR 0xC0
+const SEEOP_WRAL_ADDR 0x40
+const SEEOP_EWDS_ADDR 0x00
+
+/*
+ * SCB Counter
+ */
+register SCBCNT {
+ address 0x0BF
+ access_mode RW
+ modes M_SCSI
+}
+
+/*
+ * Data FIFO Write Address
+ * Pointer to the next QWD location to be written to the data FIFO.
+ */
+register DFWADDR {
+ address 0x0C0
+ access_mode RW
+ size 2
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * DSP Filter Control
+ */
+register DSPFLTRCTL {
+ address 0x0C0
+ access_mode RW
+ modes M_CFG
+ field FLTRDISABLE 0x20
+ field EDGESENSE 0x10
+ field DSPFCNTSEL 0x0F
+}
+
+/*
+ * DSP Data Channel Control
+ */
+register DSPDATACTL {
+ address 0x0C1
+ access_mode RW
+ modes M_CFG
+ field BYPASSENAB 0x80
+ field DESQDIS 0x10
+ field RCVROFFSTDIS 0x04
+ field XMITOFFSTDIS 0x02
+}
+
+/*
+ * Data FIFO Read Address
+ * Pointer to the next QWD location to be read from the data FIFO.
+ */
+register DFRADDR {
+ address 0x0C2
+ access_mode RW
+ size 2
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * DSP REQ Control
+ */
+register DSPREQCTL {
+ address 0x0C2
+ access_mode RW
+ modes M_CFG
+ field MANREQCTL 0xC0
+ field MANREQDLY 0x3F
+}
+
+/*
+ * DSP ACK Control
+ */
+register DSPACKCTL {
+ address 0x0C3
+ access_mode RW
+ modes M_CFG
+ field MANACKCTL 0xC0
+ field MANACKDLY 0x3F
+}
+
+/*
+ * Data FIFO Data
+ * Read/Write byte port into the data FIFO. The read and write
+ * FIFO pointers increment with each read and write respectively
+ * to this port.
+ */
+register DFDAT {
+ address 0x0C4
+ access_mode RW
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * DSP Channel Select
+ */
+register DSPSELECT {
+ address 0x0C4
+ access_mode RW
+ modes M_CFG
+ field AUTOINCEN 0x80
+ field DSPSEL 0x1F
+}
+
+const NUMDSPS 0x14
+
+/*
+ * Write Bias Control
+ */
+register WRTBIASCTL {
+ address 0x0C5
+ access_mode WO
+ modes M_CFG
+ field AUTOXBCDIS 0x80
+ field XMITMANVAL 0x3F
+}
+
+/*
+ * Currently the WRTBIASCTL is the same as the default.
+ */
+const WRTBIASCTL_HP_DEFAULT 0x0
+
+/*
+ * Receiver Bias Control
+ */
+register RCVRBIOSCTL {
+ address 0x0C6
+ access_mode WO
+ modes M_CFG
+ field AUTORBCDIS 0x80
+ field RCVRMANVAL 0x3F
+}
+
+/*
+ * Write Bias Calculator
+ */
+register WRTBIASCALC {
+ address 0x0C7
+ access_mode RO
+ modes M_CFG
+}
+
+/*
+ * Data FIFO Pointers
+ * Contains the byte offset from DFWADDR and DWRADDR to the current
+ * FIFO write/read locations.
+ */
+register DFPTRS {
+ address 0x0C8
+ access_mode RW
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * Receiver Bias Calculator
+ */
+register RCVRBIASCALC {
+ address 0x0C8
+ access_mode RO
+ modes M_CFG
+}
+
+/*
+ * Data FIFO Backup Read Pointer
+ * Contains the data FIFO address to be restored if the last
+ * data accessed from the data FIFO was not transferred successfully.
+ */
+register DFBKPTR {
+ address 0x0C9
+ access_mode RW
+ size 2
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * Skew Calculator
+ */
+register SKEWCALC {
+ address 0x0C9
+ access_mode RO
+ modes M_CFG
+}
+
+/*
+ * Data FIFO Debug Control
+ */
+register DFDBCTL {
+ address 0x0CB
+ access_mode RW
+ modes M_DFF0, M_DFF1
+ field DFF_CIO_WR_RDY 0x20
+ field DFF_CIO_RD_RDY 0x10
+ field DFF_DIR_ERR 0x08
+ field DFF_RAMBIST_FAIL 0x04
+ field DFF_RAMBIST_DONE 0x02
+ field DFF_RAMBIST_EN 0x01
+}
+
+/*
+ * Data FIFO Space Count
+ * Number of FIFO locations that are free.
+ */
+register DFSCNT {
+ address 0x0CC
+ access_mode RO
+ size 2
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * Data FIFO Byte Count
+ * Number of filled FIFO locations.
+ */
+register DFBCNT {
+ address 0x0CE
+ access_mode RO
+ size 2
+ modes M_DFF0, M_DFF1
+}
+
+/*
+ * Sequencer Program Overlay Address.
+ * Low address must be written prior to high address.
+ */
+register OVLYADDR {
+ address 0x0D4
+ modes M_SCSI
+ size 2
+ access_mode RW
+}
+
+/*
+ * Sequencer Control 0
+ * Error detection mode, speed configuration,
+ * single step, breakpoints and program load.
+ */
+register SEQCTL0 {
+ address 0x0D6
+ 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 Control 1
+ * Instruction RAM Diagnostics
+ */
+register SEQCTL1 {
+ address 0x0D7
+ access_mode RW
+ field OVRLAY_DATA_CHK 0x08
+ field RAMBIST_DONE 0x04
+ field RAMBIST_FAIL 0x02
+ field RAMBIST_EN 0x01
+}
+
+/*
+ * Sequencer Flags
+ * Zero and Carry state of the ALU.
+ */
+register FLAGS {
+ address 0x0D8
+ access_mode RO
+ field ZERO 0x02
+ field CARRY 0x01
+}
+
+/*
+ * Sequencer Interrupt Control
+ */
+register SEQINTCTL {
+ address 0x0D9
+ access_mode RW
+ field INTVEC1DSL 0x80
+ field INT1_CONTEXT 0x20
+ field SCS_SEQ_INT1M1 0x10
+ field SCS_SEQ_INT1M0 0x08
+ field INTMASK2 0x04
+ field INTMASK1 0x02
+ field IRET 0x01
+}
+
+/*
+ * Sequencer RAM Data Port
+ * Single byte window into the Sequencer Instruction Ram area starting
+ * at the address specified by OVLYADDR. To write a full instruction word,
+ * simply write four bytes in succession. OVLYADDR will increment after the
+ * most significant instrution byte (the byte with the parity bit) is written.
+ */
+register SEQRAM {
+ address 0x0DA
+ access_mode RW
+}
+
+/*
+ * Sequencer Program Counter
+ * Low byte must be written prior to high byte.
+ */
+register PRGMCNT {
+ address 0x0DE
+ access_mode RW
+ size 2
+}
+
+/*
+ * Accumulator
+ */
+register ACCUM {
+ address 0x0E0
+ access_mode RW
+ accumulator
+}
+
+/*
+ * Source Index Register
+ * Incrementing index for reads of SINDIR and the destination (low byte only)
+ * for any immediate operands passed in jmp, jc, jnc, call instructions.
+ * Example:
+ * mvi 0xFF call some_routine;
+ *
+ * Will set SINDEX[0] to 0xFF and call the routine "some_routine.
+ */
+register SINDEX {
+ address 0x0E2
+ access_mode RW
+ size 2
+ sindex
+}
+
+/*
+ * Destination Index Register
+ * Incrementing index for writes to DINDIR. Can be used as a scratch register.
+ */
+register DINDEX {
+ address 0x0E4
+ access_mode RW
+ size 2
+}
+
+/*
+ * Break Address
+ * Sequencer instruction breakpoint address address.
+ */
+register BRKADDR0 {
+ address 0x0E6
+ access_mode RW
+}
+
+register BRKADDR1 {
+ address 0x0E6
+ access_mode RW
+ field BRKDIS 0x80 /* Disable Breakpoint */
+}
+
+/*
+ * All Ones
+ * All reads to this register return the value 0xFF.
+ */
+register ALLONES {
+ address 0x0E8
+ access_mode RO
+ allones
+}
+
+/*
+ * All Zeros
+ * All reads to this register return the value 0.
+ */
+register ALLZEROS {
+ address 0x0EA
+ access_mode RO
+ allzeros
+}
+
+/*
+ * No Destination
+ * Writes to this register have no effect.
+ */
+register NONE {
+ address 0x0EA
+ access_mode WO
+ none
+}
+
+/*
+ * Source Index Indirect
+ * Reading this register is equivalent to reading (register_base + SINDEX) and
+ * incrementing SINDEX by 1.
+ */
+register SINDIR {
+ address 0x0EC
+ access_mode RO
+}
+
+/*
+ * Destination Index Indirect
+ * Writing this register is equivalent to writing to (register_base + DINDEX)
+ * and incrementing DINDEX by 1.
+ */
+register DINDIR {
+ address 0x0ED
+ access_mode WO
+}
+
+/*
+ * Function One
+ * 2's complement to bit value conversion. Write the 2's complement value
+ * (0-7 only) to the top nibble and retrieve the bit indexed by that value
+ * on the next read of this register.
+ * Example:
+ * Write 0x60
+ * Read 0x40
+ */
+register FUNCTION1 {
+ address 0x0F0
+ access_mode RW
+}
+
+/*
+ * Stack
+ * Window into the stack. Each stack location is 10 bits wide reported
+ * low byte followed by high byte. There are 8 stack locations.
+ */
+register STACK {
+ address 0x0F2
+ access_mode RW
+}
+
+/*
+ * Interrupt Vector 1 Address
+ * Interrupt branch address for SCS SEQ_INT1 mode 0 and 1 interrupts.
+ */
+register INTVEC1_ADDR {
+ address 0x0F4
+ access_mode RW
+ size 2
+ modes M_CFG
+}
+
+/*
+ * Current Address
+ * Address of the SEQRAM instruction currently executing instruction.
+ */
+register CURADDR {
+ address 0x0F4
+ access_mode RW
+ size 2
+ modes M_SCSI
+}
+
+/*
+ * Interrupt Vector 2 Address
+ * Interrupt branch address for HST_SEQ_INT2 interrupts.
+ */
+register INTVEC2_ADDR {
+ address 0x0F6
+ access_mode RW
+ size 2
+ modes M_CFG
+}
+
+/*
+ * Last Address
+ * Address of the SEQRAM instruction executed prior to the current instruction.
+ */
+register LASTADDR {
+ address 0x0F6
+ access_mode RW
+ size 2
+ modes M_SCSI
+}
+
+register AHD_PCI_CONFIG_BASE {
+ address 0x100
+ access_mode RW
+ size 256
+ modes M_CFG
+}
+
+/* ---------------------- Scratch RAM Offsets ------------------------- */
+scratch_ram {
+ /* Mode Specific */
+ address 0x0A0
+ size 8
+ modes 0, 1, 2, 3
+ REG0 {
+ size 2
+ }
+ REG1 {
+ size 2
+ }
+ REG_ISR {
+ size 2
+ }
+ SG_STATE {
+ size 1
+ field SEGS_AVAIL 0x01
+ field LOADING_NEEDED 0x02
+ field FETCH_INPROG 0x04
+ }
+ /*
+ * Track whether the transfer byte count for
+ * the current data phase is odd.
+ */
+ DATA_COUNT_ODD {
+ size 1
+ }
+}
+
+scratch_ram {
+ /* Mode Specific */
+ address 0x0F8
+ size 8
+ modes 0, 1, 2, 3
+ LONGJMP_ADDR {
+ size 2
+ }
+ ACCUM_SAVE {
+ size 1
+ }
+}
+
+
+scratch_ram {
+ address 0x100
+ size 128
+ modes 0, 1, 2, 3
+ /*
+ * Per "other-id" execution queues. We use an array of
+ * tail pointers into lists of SCBs sorted by "other-id".
+ * The execution head pointer threads the head SCBs for
+ * each list.
+ */
+ WAITING_SCB_TAILS {
+ size 32
+ }
+ WAITING_TID_HEAD {
+ size 2
+ }
+ WAITING_TID_TAIL {
+ size 2
+ }
+ /*
+ * SCBID of the next SCB in the new SCB queue.
+ */
+ NEXT_QUEUED_SCB_ADDR {
+ size 4
+ }
+ /*
+ * head of list of SCBs that have
+ * completed but have not been
+ * put into the qoutfifo.
+ */
+ COMPLETE_SCB_HEAD {
+ size 2
+ }
+ /*
+ * The list of completed SCBs in
+ * the active DMA.
+ */
+ COMPLETE_SCB_DMAINPROG_HEAD {
+ size 2
+ }
+ /*
+ * head of list of SCBs that have
+ * completed but need to be uploaded
+ * to the host prior to being completed.
+ */
+ COMPLETE_DMA_SCB_HEAD {
+ size 2
+ }
+ /* Counting semaphore to prevent new select-outs */
+ QFREEZE_COUNT {
+ size 2
+ }
+ /*
+ * Mode to restore on legacy idle loop exit.
+ */
+ SAVED_MODE {
+ 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
+ field P_BUSFREE 0x01
+ enum PHASE_MASK CDO|IOO|MSGO {
+ P_DATAOUT 0x0,
+ P_DATAIN IOO,
+ P_DATAOUT_DT P_DATAOUT|MSGO,
+ P_DATAIN_DT P_DATAIN|MSGO,
+ P_COMMAND CDO,
+ P_MESGOUT CDO|MSGO,
+ P_STATUS CDO|IOO,
+ P_MESGIN CDO|IOO|MSGO
+ }
+ }
+ /*
+ * Value to "or" into the SCBPTR[1] value to
+ * indicate that an entry in the QINFIFO is valid.
+ */
+ QOUTFIFO_ENTRY_VALID_TAG {
+ size 1
+ }
+ /*
+ * Base address of our shared data with the kernel driver in host
+ * memory. This includes the qoutfifo and target mode
+ * incoming command queue.
+ */
+ SHARED_DATA_ADDR {
+ size 4
+ }
+ /*
+ * Pointer to location in host memory for next
+ * position in the qoutfifo.
+ */
+ QOUTFIFO_NEXT_ADDR {
+ size 4
+ }
+ /*
+ * Kernel and sequencer offsets into the queue of
+ * incoming target mode command descriptors. The
+ * queue is full when the KERNEL_TQINPOS == TQINPOS.
+ */
+ KERNEL_TQINPOS {
+ size 1
+ }
+ TQINPOS {
+ size 1
+ }
+ ARG_1 {
+ size 1
+ 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_WRITE 0x04
+ mask CONT_MSG_LOOP_READ 0x03
+ mask CONT_MSG_LOOP_TARG 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 MANUALCTL 0x40
+ field ENSELI 0x20
+ field ENRSELI 0x10
+ field MANUALP 0x0C
+ field ENAUTOATNP 0x02
+ field ALTSTIM 0x01
+ }
+
+ /*
+ * The initiator specified tag for this target mode transaction.
+ */
+ INITIATOR_TAG {
+ size 1
+ }
+
+ SEQ_FLAGS2 {
+ size 1
+ field TARGET_MSG_PENDING 0x02
+ field SELECTOUT_QFROZEN 0x04
+ }
+
+ ALLOCFIFO_SCBPTR {
+ size 2
+ }
+
+ /*
+ * The maximum amount of time to wait, when interrupt coalescing
+ * is enabled, before issueing a CMDCMPLT interrupt for a completed
+ * command.
+ */
+ INT_COALESCING_TIMER {
+ size 2
+ }
+
+ /*
+ * The maximum number of commands to coalesce into a single interrupt.
+ * Actually the 2's complement of that value to simplify sequencer
+ * code.
+ */
+ INT_COALESCING_MAXCMDS {
+ size 1
+ }
+
+ /*
+ * The minimum number of commands still outstanding required
+ * to continue coalescing (2's complement of value).
+ */
+ INT_COALESCING_MINCMDS {
+ size 1
+ }
+
+ /*
+ * Number of commands "in-flight".
+ */
+ CMDS_PENDING {
+ size 2
+ }
+
+ /*
+ * The count of commands that have been coalesced.
+ */
+ INT_COALESCING_CMDCOUNT {
+ size 1
+ }
+
+ /*
+ * Since the HS_MAIBOX is self clearing, copy its contents to
+ * this position in scratch ram every time it changes.
+ */
+ LOCAL_HS_MAILBOX {
+ size 1
+ }
+ /*
+ * Target-mode CDB type to CDB length table used
+ * in non-packetized operation.
+ */
+ CMDSIZE_TABLE {
+ size 8
+ }
+}
+
+/************************* Hardware SCB Definition ****************************/
+scb {
+ address 0x180
+ size 64
+ modes 0, 1, 2, 3
+ SCB_RESIDUAL_DATACNT {
+ size 4
+ alias SCB_CDB_STORE
+ alias SCB_HOST_CDB_PTR
+ }
+ SCB_RESIDUAL_SGPTR {
+ size 4
+ field SG_ADDR_MASK 0xf8 /* In the last byte */
+ field SG_OVERRUN_RESID 0x02 /* In the first byte */
+ field SG_LIST_NULL 0x01 /* In the first byte */
+ }
+ SCB_SCSI_STATUS {
+ size 1
+ alias SCB_HOST_CDB_LEN
+ }
+ SCB_TARGET_PHASES {
+ size 1
+ }
+ SCB_TARGET_DATA_DIR {
+ size 1
+ }
+ SCB_TARGET_ITAG {
+ size 1
+ }
+ SCB_SENSE_BUSADDR {
+ /*
+ * Only valid if CDB length is less than 13 bytes or
+ * we are using a CDB pointer. Otherwise contains
+ * the last 4 bytes of embedded cdb information.
+ */
+ size 4
+ alias SCB_NEXT_COMPLETE
+ }
+ SCB_TAG {
+ alias SCB_FIFO_USE_COUNT
+ size 2
+ }
+ SCB_CONTROL {
+ size 1
+ field TARGET_SCB 0x80
+ field DISCENB 0x40
+ field TAG_ENB 0x20
+ field MK_MESSAGE 0x10
+ field STATUS_RCVD 0x08
+ field DISCONNECTED 0x04
+ field SCB_TAG_TYPE 0x03
+ }
+ SCB_SCSIID {
+ size 1
+ field TID 0xF0
+ field OID 0x0F
+ }
+ SCB_LUN {
+ size 1
+ field LID 0xff
+ }
+ SCB_TASK_ATTRIBUTE {
+ size 1
+ /*
+ * Overloaded field for non-packetized
+ * ignore wide residue message handling.
+ */
+ field SCB_XFERLEN_ODD 0x01
+ }
+ SCB_CDB_LEN {
+ size 1
+ field SCB_CDB_LEN_PTR 0x80 /* CDB in host memory */
+ }
+ SCB_TASK_MANAGEMENT {
+ size 1
+ }
+ SCB_DATAPTR {
+ size 8
+ }
+ SCB_DATACNT {
+ /*
+ * The last byte is really the high address bits for
+ * the data address.
+ */
+ size 4
+ field SG_LAST_SEG 0x80 /* In the fourth byte */
+ field SG_HIGH_ADDR_BITS 0x7F /* In the fourth byte */
+ }
+ SCB_SGPTR {
+ size 4
+ field SG_STATUS_VALID 0x04 /* In the first byte */
+ field SG_FULL_RESID 0x02 /* In the first byte */
+ field SG_LIST_NULL 0x01 /* In the first byte */
+ }
+ SCB_BUSADDR {
+ size 4
+ }
+ SCB_NEXT {
+ alias SCB_NEXT_SCB_BUSADDR
+ size 2
+ }
+ SCB_NEXT2 {
+ size 2
+ }
+ SCB_SPARE {
+ size 8
+ alias SCB_PKT_LUN
+ }
+ SCB_DISCONNECTED_LISTS {
+ size 8
+ }
+}
+
+/*********************************** Constants ********************************/
+const MK_MESSAGE_BIT_OFFSET 4
+const TID_SHIFT 4
+const TARGET_CMD_CMPLT 0xfe
+const INVALID_ADDR 0x80
+#define SCB_LIST_NULL 0xff
+#define QOUTFIFO_ENTRY_VALID_TOGGLE 0x80
+
+const CCSGADDR_MAX 0x80
+const CCSCBADDR_MAX 0x80
+const CCSGRAM_MAXSEGS 16
+
+/* Selection Timeout Timer Constants */
+const STIMESEL_SHIFT 3
+const STIMESEL_MIN 0x18
+const STIMESEL_BUG_ADJ 0x8
+
+/* WDTR Message values */
+const BUS_8_BIT 0x00
+const BUS_16_BIT 0x01
+const BUS_32_BIT 0x02
+
+/* Offset maximums */
+const MAX_OFFSET 0xfe
+const MAX_OFFSET_PACED 0xfe
+const MAX_OFFSET_PACED_BUG 0x7f
+/*
+ * Some 160 devices incorrectly accept 0xfe as a
+ * sync offset, but will overrun this value. Limit
+ * to 0x7f for speed lower than U320 which will
+ * avoid the persistent sync offset overruns.
+ */
+const MAX_OFFSET_NON_PACED 0x7f
+const HOST_MSG 0xff
+
+/*
+ * The size of our sense buffers.
+ * Sense buffer mapping can be handled in either of two ways.
+ * The first is to allocate a dmamap for each transaction.
+ * Depending on the architecture, dmamaps can be costly. The
+ * alternative is to statically map the buffers in much the same
+ * way we handle our scatter gather lists. The driver implements
+ * the later.
+ */
+const AHD_SENSE_BUFSIZE 256
+
+/* Target mode command processing constants */
+const CMD_GROUP_CODE_SHIFT 0x05
+
+const STATUS_BUSY 0x08
+const STATUS_QUEUE_FULL 0x28
+const STATUS_PKT_SENSE 0xFF
+const TARGET_DATA_IN 1
+
+const SCB_TRANSFER_SIZE_FULL_LUN 56
+const SCB_TRANSFER_SIZE_1BYTE_LUN 48
+/* PKT_OVERRUN_BUFSIZE must be a multiple of 256 less than 64K */
+const PKT_OVERRUN_BUFSIZE 512
+
+/*
+ * Timer parameters.
+ */
+const AHD_TIMER_US_PER_TICK 25
+const AHD_TIMER_MAX_TICKS 0xFFFF
+const AHD_TIMER_MAX_US (AHD_TIMER_MAX_TICKS * AHD_TIMER_US_PER_TICK)
+
+/*
+ * Downloaded (kernel inserted) constants
+ */
+const SG_PREFETCH_CNT download
+const SG_PREFETCH_CNT_LIMIT download
+const SG_PREFETCH_ALIGN_MASK download
+const SG_PREFETCH_ADDR_MASK download
+const SG_SIZEOF download
+const PKT_OVERRUN_BUFOFFSET download
+const SCB_TRANSFER_SIZE download
+
+/*
+ * BIOS SCB offsets
+ */
+const NVRAM_SCB_OFFSET 0x2C
diff --git a/sys/dev/microcode/aic7xxx/aic79xx.seq b/sys/dev/microcode/aic7xxx/aic79xx.seq
new file mode 100644
index 00000000000..456d9b07000
--- /dev/null
+++ b/sys/dev/microcode/aic7xxx/aic79xx.seq
@@ -0,0 +1,2034 @@
+/* $OpenBSD: aic79xx.seq,v 1.1 2003/12/24 22:40:16 krw Exp $ */
+/* $NetBSD: aic79xx.seq,v 1.8 2003/08/29 03:54:06 thorpej Exp $ */
+
+/*
+ * Adaptec U320 device driver firmware for Linux and FreeBSD.
+ *
+ * Copyright (c) 1994-2001 Justin T. Gibbs.
+ * Copyright (c) 2000-2002 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: src/sys/dev/aic7xxx/aic79xx.seq,v 1.13 2003/06/28 04:44:10 gibbs Exp $
+ */
+
+VERSION = "Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#96 $"
+PATCH_ARG_LIST = "struct ahd_softc *ahd"
+PREFIX = "ahd_"
+
+#include <dev/microcode/aic7xxx/aic79xx.reg>
+#include <scsi/scsi_message.h>
+
+restart:
+if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
+ test SEQINTCODE, 0xFF jz idle_loop;
+ SET_SEQINTCODE(NO_SEQINT)
+}
+
+idle_loop:
+
+ if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
+ /*
+ * Convert ERROR status into a sequencer
+ * interrupt to handle the case of an
+ * interrupt collision on the hardware
+ * setting of HWERR.
+ */
+ test ERROR, 0xFF jz no_error_set;
+ SET_SEQINTCODE(SAW_HWERR)
+no_error_set:
+ }
+ SET_MODE(M_SCSI, M_SCSI)
+ test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus;
+ test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus;
+ cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus;
+ /*
+ * ENSELO is cleared by a SELDO, so we must test for SELDO
+ * one last time.
+ */
+BEGIN_CRITICAL;
+ test SSTAT0, SELDO jnz select_out;
+END_CRITICAL;
+ call start_selection;
+idle_loop_checkbus:
+BEGIN_CRITICAL;
+ test SSTAT0, SELDO jnz select_out;
+END_CRITICAL;
+ test SSTAT0, SELDI jnz select_in;
+ test SCSIPHASE, ~DATA_PHASE_MASK jz idle_loop_check_nonpackreq;
+ test SCSISIGO, ATNO jz idle_loop_check_nonpackreq;
+ call unexpected_nonpkt_phase_find_ctxt;
+idle_loop_check_nonpackreq:
+ test SSTAT2, NONPACKREQ jz . + 2;
+ call unexpected_nonpkt_phase_find_ctxt;
+ if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+ and A, FIFO0FREE|FIFO1FREE, DFFSTAT;
+ cmp A, FIFO0FREE|FIFO1FREE jne . + 3;
+ and SBLKCTL, ~DIAGLEDEN|DIAGLEDON;
+ jmp . + 2;
+ or SBLKCTL, DIAGLEDEN|DIAGLEDON;
+ }
+ call idle_loop_gsfifo_in_scsi_mode;
+ call idle_loop_service_fifos;
+ call idle_loop_cchan;
+ jmp idle_loop;
+
+BEGIN_CRITICAL;
+idle_loop_gsfifo:
+ SET_MODE(M_SCSI, M_SCSI)
+idle_loop_gsfifo_in_scsi_mode:
+ test LQISTAT2, LQIGSAVAIL jz return;
+ /*
+ * We have received good status for this transaction. There may
+ * still be data in our FIFOs draining to the host. Complete
+ * the SCB only if all data has transferred to the host.
+ */
+good_status_IU_done:
+ bmov SCBPTR, GSFIFO, 2;
+ clr SCB_SCSI_STATUS;
+ /*
+ * If a command completed before an attempted task management
+ * function completed, notify the host after disabling any
+ * pending select-outs.
+ */
+ test SCB_TASK_MANAGEMENT, 0xFF jz gsfifo_complete_normally;
+ test SSTAT0, SELDO|SELINGO jnz . + 2;
+ and SCSISEQ0, ~ENSELO;
+ SET_SEQINTCODE(TASKMGMT_CMD_CMPLT_OKAY)
+gsfifo_complete_normally:
+ or SCB_CONTROL, STATUS_RCVD;
+
+ /*
+ * Since this status did not consume a FIFO, we have to
+ * be a bit more dilligent in how we check for FIFOs pertaining
+ * to this transaction. There are two states that a FIFO still
+ * transferring data may be in.
+ *
+ * 1) Configured and draining to the host, with a FIFO handler.
+ * 2) Pending cfg4data, fifo not empty.
+ *
+ * Case 1 can be detected by noticing a non-zero FIFO active
+ * count in the SCB. In this case, we allow the routine servicing
+ * the FIFO to complete the SCB.
+ *
+ * Case 2 implies either a pending or yet to occur save data
+ * pointers for this same context in the other FIFO. So, if
+ * we detect case 1, we will properly defer the post of the SCB
+ * and achieve the desired result. The pending cfg4data will
+ * notice that status has been received and complete the SCB.
+ */
+ test SCB_FIFO_USE_COUNT, 0xFF jnz idle_loop_gsfifo_in_scsi_mode;
+ call complete;
+END_CRITICAL;
+ jmp idle_loop_gsfifo_in_scsi_mode;
+
+idle_loop_service_fifos:
+ SET_MODE(M_DFF0, M_DFF0)
+ test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo;
+ call longjmp;
+idle_loop_next_fifo:
+ SET_MODE(M_DFF1, M_DFF1)
+ test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp;
+return:
+ ret;
+
+idle_loop_cchan:
+ SET_MODE(M_CCHAN, M_CCHAN)
+ test QOFF_CTLSTA, HS_MAILBOX_ACT jz hs_mailbox_empty;
+ mov LOCAL_HS_MAILBOX, HS_MAILBOX;
+ or QOFF_CTLSTA, HS_MAILBOX_ACT;
+hs_mailbox_empty:
+BEGIN_CRITICAL;
+ test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle;
+ test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog;
+ test CCSCBCTL, CCSCBDONE jz return;
+END_CRITICAL;
+ /* FALLTHROUGH */
+scbdma_tohost_done:
+ test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone;
+ /*
+ * An SCB has been succesfully uploaded to the host.
+ * If the SCB was uploaded for some reason other than
+ * bad SCSI status (currently only for underruns), we
+ * queue the SCB for normal completion. Otherwise, we
+ * wait until any select-out activity has halted, and
+ * then notify the host so that the transaction can be
+ * dealt with.
+ */
+ test SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host;
+ and CCSCBCTL, ~(CCARREN|CCSCBEN);
+ bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
+ bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
+ bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
+scbdma_notify_host:
+ SET_MODE(M_SCSI, M_SCSI)
+ test SCSISEQ0, ENSELO jnz return;
+ test SSTAT0, (SELDO|SELINGO) jnz return;
+ SET_MODE(M_CCHAN, M_CCHAN)
+ /*
+ * Remove SCB and notify host.
+ */
+ and CCSCBCTL, ~(CCARREN|CCSCBEN);
+ bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
+ SET_SEQINTCODE(BAD_SCB_STATUS)
+ ret;
+fill_qoutfifo_dmadone:
+ and CCSCBCTL, ~(CCARREN|CCSCBEN);
+ call qoutfifo_updated;
+ mvi COMPLETE_SCB_DMAINPROG_HEAD[1], SCB_LIST_NULL;
+ bmov QOUTFIFO_NEXT_ADDR, SCBHADDR, 4;
+ test QOFF_CTLSTA, SDSCB_ROLLOVR jz return;
+ bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4;
+ xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret;
+
+qoutfifo_updated:
+ /*
+ * If there are more commands waiting to be DMA'ed
+ * to the host, always coalesce. Otherwise honor the
+ * host's wishes.
+ */
+ cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne coalesce_by_count;
+ cmp COMPLETE_SCB_HEAD[1], SCB_LIST_NULL jne coalesce_by_count;
+ test LOCAL_HS_MAILBOX, ENINT_COALESCE jz issue_cmdcmplt;
+
+ /*
+ * If we have relatively few commands outstanding, don't
+ * bother waiting for another command to complete.
+ */
+ test CMDS_PENDING[1], 0xFF jnz coalesce_by_count;
+ /* Add -1 so that jnc means <= not just < */
+ add A, -1, INT_COALESCING_MINCMDS;
+ add NONE, A, CMDS_PENDING;
+ jnc issue_cmdcmplt;
+
+ /*
+ * If coalescing, only coalesce up to the limit
+ * provided by the host driver.
+ */
+coalesce_by_count:
+ mov A, INT_COALESCING_MAXCMDS;
+ add NONE, A, INT_COALESCING_CMDCOUNT;
+ jc issue_cmdcmplt;
+ /*
+ * If the timer is not currently active,
+ * fire it up.
+ */
+ test INTCTL, SWTMINTMASK jz return;
+ bmov SWTIMER, INT_COALESCING_TIMER, 2;
+ mvi CLRSEQINTSTAT, CLRSEQ_SWTMRTO;
+ or INTCTL, SWTMINTEN|SWTIMER_START;
+ and INTCTL, ~SWTMINTMASK ret;
+
+issue_cmdcmplt:
+ mvi INTSTAT, CMDCMPLT;
+ clr INT_COALESCING_CMDCOUNT;
+ or INTCTL, SWTMINTMASK ret;
+
+BEGIN_CRITICAL;
+fetch_new_scb_inprog:
+ test CCSCBCTL, ARRDONE jz return;
+fetch_new_scb_done:
+ and CCSCBCTL, ~(CCARREN|CCSCBEN);
+ bmov REG0, SCBPTR, 2;
+ clr A;
+ add CMDS_PENDING, 1;
+ adc CMDS_PENDING[1], A;
+ if ((ahd->bugs & AHD_PKT_LUN_BUG) != 0) {
+ /*
+ * "Short Luns" are not placed into outgoing LQ
+ * packets in the correct byte order. Use a full
+ * sized lun field instead and fill it with the
+ * one byte of lun information we support.
+ */
+ mov SCB_PKT_LUN[6], SCB_LUN;
+ }
+ /*
+ * The FIFO use count field is shared with the
+ * tag set by the host so that our SCB dma engine
+ * knows the correct location to store the SCB.
+ * Set it to zero before processing the SCB.
+ */
+ clr SCB_FIFO_USE_COUNT;
+ /* Update the next SCB address to download. */
+ bmov NEXT_QUEUED_SCB_ADDR, SCB_NEXT_SCB_BUSADDR, 4;
+ mvi SCB_NEXT[1], SCB_LIST_NULL;
+ mvi SCB_NEXT2[1], SCB_LIST_NULL;
+ /* Increment our position in the QINFIFO. */
+ mov NONE, SNSCB_QOFF;
+ /*
+ * SCBs that want to send messages are always
+ * queued independently. This ensures that they
+ * are at the head of the SCB list to select out
+ * to a target and we will see the MK_MESSAGE flag.
+ */
+ test SCB_CONTROL, MK_MESSAGE jnz first_new_target_scb;
+ shr SINDEX, 3, SCB_SCSIID;
+ and SINDEX, ~0x1;
+ mvi SINDEX[1], (WAITING_SCB_TAILS >> 8);
+ bmov DINDEX, SINDEX, 2;
+ bmov SCBPTR, SINDIR, 2;
+ bmov DINDIR, REG0, 2;
+ cmp SCBPTR[1], SCB_LIST_NULL je first_new_target_scb;
+ bmov SCB_NEXT, REG0, 2 ret;
+first_new_target_scb:
+ cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je first_new_scb;
+ bmov SCBPTR, WAITING_TID_TAIL, 2;
+ bmov SCB_NEXT2, REG0, 2;
+ bmov WAITING_TID_TAIL, REG0, 2 ret;
+first_new_scb:
+ bmov WAITING_TID_HEAD, REG0, 2;
+ bmov WAITING_TID_TAIL, REG0, 2 ret;
+END_CRITICAL;
+
+scbdma_idle:
+ /*
+ * Give precedence to downloading new SCBs to execute
+ * unless select-outs are currently frozen.
+ */
+ test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz . + 2;
+BEGIN_CRITICAL;
+ test QOFF_CTLSTA, NEW_SCB_AVAIL jnz fetch_new_scb;
+ cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne dma_complete_scb;
+ cmp COMPLETE_SCB_HEAD[1], SCB_LIST_NULL je return;
+ /* FALLTHROUGH */
+fill_qoutfifo:
+ /*
+ * Keep track of the SCBs we are DMA'ing just
+ * in case the DMA fails or is aborted.
+ */
+ mov A, QOUTFIFO_ENTRY_VALID_TAG;
+ bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2;
+ mvi CCSCBCTL, CCSCBRESET;
+ bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4;
+ bmov SCBPTR, COMPLETE_SCB_HEAD, 2;
+fill_qoutfifo_loop:
+ mov CCSCBRAM, SCBPTR;
+ or CCSCBRAM, A, SCBPTR[1];
+ mov NONE, SDSCB_QOFF;
+ inc INT_COALESCING_CMDCOUNT;
+ add CMDS_PENDING, -1;
+ adc CMDS_PENDING[1], -1;
+ cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done;
+ cmp CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done;
+ test QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done;
+ bmov SCBPTR, SCB_NEXT_COMPLETE, 2;
+ jmp fill_qoutfifo_loop;
+fill_qoutfifo_done:
+ mov SCBHCNT, CCSCBADDR;
+ mvi CCSCBCTL, CCSCBEN|CCSCBRESET;
+ bmov COMPLETE_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
+ mvi SCB_NEXT_COMPLETE[1], SCB_LIST_NULL ret;
+
+fetch_new_scb:
+ bmov SCBHADDR, NEXT_QUEUED_SCB_ADDR, 4;
+ mvi CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET jmp dma_scb;
+dma_complete_scb:
+ bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2;
+ bmov SCBHADDR, SCB_BUSADDR, 4;
+ mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb;
+END_CRITICAL;
+
+/*
+ * Either post or fetch an SCB from host memory. The caller
+ * is responsible for polling for transfer completion.
+ *
+ * Prerequisits: Mode == M_CCHAN
+ * SINDEX contains CCSCBCTL flags
+ * SCBHADDR set to Host SCB address
+ * SCBPTR set to SCB src location on "push" operations
+ */
+SET_SRC_MODE M_CCHAN;
+SET_DST_MODE M_CCHAN;
+dma_scb:
+ mvi SCBHCNT, SCB_TRANSFER_SIZE;
+ mov CCSCBCTL, SINDEX ret;
+
+BEGIN_CRITICAL;
+setjmp:
+ bmov LONGJMP_ADDR, STACK, 2 ret;
+setjmp_inline:
+ bmov LONGJMP_ADDR, STACK, 2;
+longjmp:
+ bmov STACK, LONGJMP_ADDR, 2 ret;
+END_CRITICAL;
+
+/*************************** Chip Bug Work Arounds ****************************/
+/*
+ * Must disable interrupts when setting the mode pointer
+ * register as an interrupt occurring mid update will
+ * fail to store the new mode value for restoration on
+ * an iret.
+ */
+if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) {
+set_mode_work_around:
+ mvi SEQINTCTL, INTVEC1DSL;
+ mov MODE_PTR, SINDEX;
+ clr SEQINTCTL ret;
+
+toggle_dff_mode_work_around:
+ mvi SEQINTCTL, INTVEC1DSL;
+ xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
+ clr SEQINTCTL ret;
+}
+
+
+if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
+set_seqint_work_around:
+ mov SEQINTCODE, SINDEX;
+ mvi SEQINTCODE, NO_SEQINT ret;
+}
+
+/************************ Packetized LongJmp Routines *************************/
+SET_SRC_MODE M_SCSI;
+SET_DST_MODE M_SCSI;
+start_selection:
+BEGIN_CRITICAL;
+ if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) {
+ /*
+ * Razor #494
+ * Rev A hardware fails to update LAST/CURR/NEXTSCB
+ * correctly after a packetized selection in several
+ * situations:
+ *
+ * 1) If only one command existed in the queue, the
+ * LAST/CURR/NEXTSCB are unchanged.
+ *
+ * 2) In a non QAS, protocol allowed phase change,
+ * the queue is shifted 1 too far. LASTSCB is
+ * the last SCB that was correctly processed.
+ *
+ * 3) In the QAS case, if the full list of commands
+ * was successfully sent, NEXTSCB is NULL and neither
+ * CURRSCB nor LASTSCB can be trusted. We must
+ * manually walk the list counting MAXCMDCNT elements
+ * to find the last SCB that was sent correctly.
+ *
+ * To simplify the workaround for this bug in SELDO
+ * handling, we initialize LASTSCB prior to enabling
+ * selection so we can rely on it even for case #1 above.
+ */
+ bmov LASTSCB, WAITING_TID_HEAD, 2;
+ }
+ bmov CURRSCB, WAITING_TID_HEAD, 2;
+ bmov SCBPTR, WAITING_TID_HEAD, 2;
+ shr SELOID, 4, SCB_SCSIID;
+ /*
+ * If we want to send a message to the device, ensure
+ * we are selecting with atn irregardless of our packetized
+ * agreement. Since SPI4 only allows target reset or PPR
+ * messages if this is a packetized connection, the change
+ * to our negotiation table entry for this selection will
+ * be cleared when the message is acted on.
+ */
+ test SCB_CONTROL, MK_MESSAGE jz . + 3;
+ mov NEGOADDR, SELOID;
+ or NEGCONOPTS, ENAUTOATNO;
+ or SCSISEQ0, ENSELO ret;
+END_CRITICAL;
+
+/*
+ * Allocate a FIFO for a non-packetized transaction.
+ * In RevA hardware, both FIFOs must be free before we
+ * can allocate a FIFO for a non-packetized transaction.
+ */
+allocate_fifo_loop:
+ /*
+ * Do whatever work is required to free a FIFO.
+ */
+ call idle_loop_service_fifos;
+ SET_MODE(M_SCSI, M_SCSI)
+allocate_fifo:
+ if ((ahd->bugs & AHD_NONPACKFIFO_BUG) != 0) {
+ and A, FIFO0FREE|FIFO1FREE, DFFSTAT;
+ cmp A, FIFO0FREE|FIFO1FREE jne allocate_fifo_loop;
+ } else {
+ test DFFSTAT, FIFO1FREE jnz allocate_fifo1;
+ test DFFSTAT, FIFO0FREE jz allocate_fifo_loop;
+ mvi DFFSTAT, B_CURRFIFO_0;
+ SET_MODE(M_DFF0, M_DFF0)
+ bmov SCBPTR, ALLOCFIFO_SCBPTR, 2 ret;
+ }
+SET_SRC_MODE M_SCSI;
+SET_DST_MODE M_SCSI;
+allocate_fifo1:
+ mvi DFFSTAT, CURRFIFO_1;
+ SET_MODE(M_DFF1, M_DFF1)
+ bmov SCBPTR, ALLOCFIFO_SCBPTR, 2 ret;
+
+/*
+ * We have been reselected as an initiator
+ * or selected as a target.
+ */
+SET_SRC_MODE M_SCSI;
+SET_DST_MODE M_SCSI;
+select_in:
+ if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
+ /*
+ * This exposes a window whereby a
+ * busfree just after a selection will
+ * be missed, but there is no other safe
+ * way to enable busfree detection if
+ * the busfreerev function is broken.
+ */
+ mvi CLRSINT1,CLRBUSFREE;
+ or SIMODE1, ENBUSFREE;
+ }
+ or SXFRCTL0, SPIOEN;
+ and SAVED_SCSIID, SELID_MASK, SELID;
+ and A, OID, IOWNID;
+ or SAVED_SCSIID, A;
+ mvi CLRSINT0, CLRSELDI;
+ jmp ITloop;
+
+/*
+ * We have successfully selected out.
+ *
+ * Clear SELDO.
+ * Dequeue all SCBs sent from the waiting queue
+ * Requeue all SCBs *not* sent to the tail of the waiting queue
+ * Take Razor #494 into account for above.
+ *
+ * In Packetized Mode:
+ * Return to the idle loop. Our interrupt handler will take
+ * care of any incoming L_Qs.
+ *
+ * In Non-Packetize Mode:
+ * Continue to our normal state machine.
+ */
+SET_SRC_MODE M_SCSI;
+SET_DST_MODE M_SCSI;
+select_out:
+BEGIN_CRITICAL;
+ /* Clear out all SCBs that have been successfully sent. */
+ if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) {
+ /*
+ * For packetized, the LQO manager clears ENSELO on
+ * the assertion of SELDO. If we are non-packetized,
+ * LASTSCB and CURRSCB are accurate.
+ */
+ test SCSISEQ0, ENSELO jnz use_lastscb;
+
+ /*
+ * The update is correct for LQOSTAT1 errors. All
+ * but LQOBUSFREE are handled by kernel interrupts.
+ * If we see LQOBUSFREE, return to the idle loop.
+ * Once we are out of the select_out critical section,
+ * the kernel will cleanup the LQOBUSFREE and we will
+ * eventually restart the selection if appropriate.
+ */
+ test LQOSTAT1, LQOBUSFREE jnz idle_loop;
+
+ /*
+ * On a phase change oustside of packet boundaries,
+ * LASTSCB points to the currently active SCB context
+ * on the bus.
+ */
+ test LQOSTAT2, LQOPHACHGOUTPKT jnz use_lastscb;
+
+ /*
+ * If the hardware has traversed the whole list, NEXTSCB
+ * will be NULL, CURRSCB and LASTSCB cannot be trusted,
+ * but MAXCMDCNT is accurate. If we stop part way through
+ * the list or only had one command to issue, NEXTSCB[1] is
+ * not NULL and LASTSCB is the last command to go out.
+ */
+ cmp NEXTSCB[1], SCB_LIST_NULL jne use_lastscb;
+
+ /*
+ * Brute force walk.
+ */
+ bmov SCBPTR, WAITING_TID_HEAD, 2;
+ mvi SEQINTCTL, INTVEC1DSL;
+ mvi MODE_PTR, MK_MODE(M_CFG, M_CFG);
+ mov A, MAXCMDCNT;
+ mvi MODE_PTR, MK_MODE(M_SCSI, M_SCSI);
+ clr SEQINTCTL;
+find_lastscb_loop:
+ dec A;
+ test A, 0xFF jz found_last_sent_scb;
+ bmov SCBPTR, SCB_NEXT, 2;
+ jmp find_lastscb_loop;
+use_lastscb:
+ bmov SCBPTR, LASTSCB, 2;
+found_last_sent_scb:
+ bmov CURRSCB, SCBPTR, 2;
+curscb_ww_done:
+ } else {
+ bmov SCBPTR, CURRSCB, 2;
+ }
+
+ /*
+ * Requeue any SCBs not sent, to the tail of the waiting Q.
+ */
+ cmp SCB_NEXT[1], SCB_LIST_NULL je select_out_list_done;
+
+ /*
+ * We know that neither the per-TID list nor the list of
+ * TIDs is empty. Use this knowledge to our advantage.
+ */
+ bmov REG0, SCB_NEXT, 2;
+ bmov SCBPTR, WAITING_TID_TAIL, 2;
+ bmov SCB_NEXT2, REG0, 2;
+ bmov WAITING_TID_TAIL, REG0, 2;
+ jmp select_out_inc_tid_q;
+
+select_out_list_done:
+ /*
+ * The whole list made it. Just clear our TID's tail pointer
+ * unless we were queued independently due to our need to
+ * send a message.
+ */
+ test SCB_CONTROL, MK_MESSAGE jnz select_out_inc_tid_q;
+ shr DINDEX, 3, SCB_SCSIID;
+ or DINDEX, 1; /* Want only the second byte */
+ mvi DINDEX[1], ((WAITING_SCB_TAILS) >> 8);
+ mvi DINDIR, SCB_LIST_NULL;
+select_out_inc_tid_q:
+ bmov SCBPTR, WAITING_TID_HEAD, 2;
+ bmov WAITING_TID_HEAD, SCB_NEXT2, 2;
+ cmp WAITING_TID_HEAD[1], SCB_LIST_NULL jne . + 2;
+ mvi WAITING_TID_TAIL[1], SCB_LIST_NULL;
+ bmov SCBPTR, CURRSCB, 2;
+ mvi CLRSINT0, CLRSELDO;
+ test LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_phase;
+ test LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_phase;
+
+ /*
+ * If this is a packetized connection, return to our
+ * idle_loop and let our interrupt handler deal with
+ * any connection setup/teardown issues. The only
+ * exceptions are the case of MK_MESSAGE and task management
+ * SCBs.
+ */
+ if ((ahd->bugs & AHD_LQO_ATNO_BUG) != 0) {
+ /*
+ * In the A, the LQO manager transitions to LQOSTOP0 even if
+ * we have selected out with ATN asserted and the target
+ * REQs in a non-packet phase.
+ */
+ test SCB_CONTROL, MK_MESSAGE jz select_out_no_message;
+ test SCSISIGO, ATNO jnz select_out_non_packetized;
+select_out_no_message:
+ }
+ test LQOSTAT2, LQOSTOP0 jz select_out_non_packetized;
+ test SCB_TASK_MANAGEMENT, 0xFF jz idle_loop;
+ SET_SEQINTCODE(TASKMGMT_FUNC_COMPLETE)
+ jmp idle_loop;
+
+select_out_non_packetized:
+ /* Non packetized request. */
+ and SCSISEQ0, ~ENSELO;
+ if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
+ /*
+ * This exposes a window whereby a
+ * busfree just after a selection will
+ * be missed, but there is no other safe
+ * way to enable busfree detection if
+ * the busfreerev function is broken.
+ */
+ mvi CLRSINT1,CLRBUSFREE;
+ or SIMODE1, ENBUSFREE;
+ }
+ mov SAVED_SCSIID, SCB_SCSIID;
+ mov SAVED_LUN, SCB_LUN;
+ mvi SEQ_FLAGS, NO_CDB_SENT;
+END_CRITICAL;
+ or SXFRCTL0, SPIOEN;
+
+ /*
+ * 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;
+
+ /*
+ * 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.
+ */
+mesgin_phasemis:
+ITloop:
+ call phase_lock;
+
+ mov A, LASTPHASE;
+
+ test A, ~P_DATAIN_DT 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;
+
+ SET_SEQINTCODE(BAD_PHASE)
+ jmp ITloop; /* Try reading the bus again. */
+
+/*
+ * Command phase. Set up the DMA registers and let 'er rip.
+ */
+p_command:
+ test SEQ_FLAGS, NOT_IDENTIFIED jz p_command_okay;
+ SET_SEQINTCODE(PROTO_VIOLATION)
+p_command_okay:
+ test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1))
+ jnz p_command_allocate_fifo;
+ /*
+ * Command retry. Free our current FIFO and
+ * re-allocate a FIFO so transfer state is
+ * reset.
+ */
+SET_SRC_MODE M_DFF1;
+SET_DST_MODE M_DFF1;
+ mvi DFFSXFRCTL, RSTCHN|CLRSHCNT;
+ SET_MODE(M_SCSI, M_SCSI)
+p_command_allocate_fifo:
+ bmov ALLOCFIFO_SCBPTR, SCBPTR, 2;
+ call allocate_fifo;
+SET_SRC_MODE M_DFF1;
+SET_DST_MODE M_DFF1;
+ add NONE, -17, SCB_CDB_LEN;
+ jnc p_command_embedded;
+p_command_from_host:
+ bmov HADDR[0], SCB_HOST_CDB_PTR, 9;
+ mvi SG_CACHE_PRE, LAST_SEG;
+ mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN);
+ jmp p_command_xfer;
+p_command_embedded:
+ bmov SHCNT[0], SCB_CDB_LEN, 1;
+ bmov DFDAT, SCB_CDB_STORE, 16;
+ mvi DFCNTRL, SCSIEN;
+p_command_xfer:
+ and SEQ_FLAGS, ~NO_CDB_SENT;
+ test DFCNTRL, SCSIEN jnz .;
+ /*
+ * DMA Channel automatically disabled.
+ * Don't allow a data phase if the command
+ * was not fully transferred.
+ */
+ test SSTAT2, SDONE jnz ITloop;
+ or SEQ_FLAGS, NO_CDB_SENT;
+ jmp ITloop;
+
+
+/*
+ * Status phase. Wait for the data byte to appear, then read it
+ * and store it into the SCB.
+ */
+SET_SRC_MODE M_SCSI;
+SET_DST_MODE M_SCSI;
+p_status:
+ test SEQ_FLAGS,NOT_IDENTIFIED jnz mesgin_proto_violation;
+p_status_okay:
+ mov SCB_SCSI_STATUS, SCSIDAT;
+ or SCB_CONTROL, STATUS_RCVD;
+ jmp ITloop;
+
+/*
+ * Message out phase. If MSG_OUT is MSG_IDENTIFYFLAG, build a full
+ * indentify message sequence and send it to the target. The host may
+ * override this behavior by setting the MK_MESSAGE bit in the SCB
+ * control byte. This will cause us to interrupt the host and allow
+ * it to handle the message phase completely on its own. If the bit
+ * associated with this target is set, we will also interrupt the host,
+ * thereby allowing it to send a message on the next selection regardless
+ * of the transaction being sent.
+ *
+ * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message.
+ * This is done to allow the host 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:
+ /* Turn on ATN for the retry */
+ mvi SCSISIGO, ATNO;
+p_mesgout:
+ mov SINDEX, MSG_OUT;
+ cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
+ test SCB_CONTROL,MK_MESSAGE jnz host_message_loop;
+p_mesgout_identify:
+ or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SCB_LUN;
+ test SCB_CONTROL, DISCENB jnz . + 2;
+ and SINDEX, ~DISCENB;
+/*
+ * Send a tag message if TAG_ENB is set in the SCB control block.
+ * Use SCB_NONPACKET_TAG as the tag value.
+ */
+p_mesgout_tag:
+ test SCB_CONTROL,TAG_ENB jz p_mesgout_onebyte;
+ mov SCSIDAT, SINDEX; /* Send the identify message */
+ call phase_lock;
+ cmp LASTPHASE, P_MESGOUT jne p_mesgout_done;
+ and SCSIDAT,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL;
+ call phase_lock;
+ cmp LASTPHASE, P_MESGOUT jne p_mesgout_done;
+ mov SCBPTR jmp p_mesgout_onebyte;
+/*
+ * Interrupt the driver, and allow it to handle this message
+ * phase and any required retries.
+ */
+p_mesgout_from_host:
+ cmp SINDEX, HOST_MSG jne p_mesgout_onebyte;
+ jmp host_message_loop;
+
+p_mesgout_onebyte:
+ mvi CLRSINT1, CLRATNO;
+ mov SCSIDAT, SINDEX;
+
+/*
+ * If the next bus phase after ATN drops is 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;
+ mvi MSG_OUT, MSG_NOOP; /* No message left */
+ jmp ITloop;
+
+/*
+ * Message in phase. Bytes are read using Automatic PIO mode.
+ */
+p_mesgin:
+ /* read the 1st message byte */
+ mvi ACCUM call inb_first;
+
+ 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_IGN_WIDE_RESIDUE je mesgin_ign_wide_residue;
+ cmp A,MSG_NOOP je mesgin_done;
+
+/*
+ * Pushed message loop to allow the kernel to
+ * run it's own message state engine. To avoid an
+ * extra nop instruction after signaling the kernel,
+ * we perform the phase_lock before checking to see
+ * if we should exit the loop and skip the phase_lock
+ * in the ITloop. Performing back to back phase_locks
+ * shouldn't hurt, but why do it twice...
+ */
+host_message_loop:
+ call phase_lock; /* Benign the first time through. */
+ SET_SEQINTCODE(HOST_MSG_LOOP)
+ cmp RETURN_1, EXIT_MSG_LOOP je ITloop;
+ cmp RETURN_1, CONT_MSG_LOOP_WRITE jne . + 3;
+ mov SCSIDAT, RETURN_2;
+ jmp host_message_loop;
+ /* Must be CONT_MSG_LOOP_READ */
+ mov NONE, SCSIDAT; /* ACK Byte */
+ jmp host_message_loop;
+
+mesgin_ign_wide_residue:
+ mov SAVED_MODE, MODE_PTR;
+ SET_MODE(M_SCSI, M_SCSI)
+ shr NEGOADDR, 4, SAVED_SCSIID;
+ mov A, NEGCONOPTS;
+ RESTORE_MODE(SAVED_MODE)
+ test A, WIDEXFER jz mesgin_reject;
+ /* Pull the residue byte */
+ mvi REG0 call inb_next;
+ cmp REG0, 0x01 jne mesgin_reject;
+ test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 2;
+ test SCB_TASK_ATTRIBUTE, SCB_XFERLEN_ODD jnz mesgin_done;
+ SET_SEQINTCODE(IGN_WIDE_RES)
+ jmp mesgin_done;
+
+mesgin_proto_violation:
+ SET_SEQINTCODE(PROTO_VIOLATION)
+ jmp mesgin_done;
+mesgin_reject:
+ mvi MSG_MESSAGE_REJECT call mk_mesg;
+mesgin_done:
+ mov NONE,SCSIDAT; /*dummy read from latch to ACK*/
+ jmp ITloop;
+
+#define INDEX_DISC_LIST(scsiid, lun) \
+ and A, 0xC0, scsiid; \
+ or SCBPTR, A, lun; \
+ clr SCBPTR[1]; \
+ and SINDEX, 0x30, scsiid; \
+ shr SINDEX, 3; /* Multiply by 2 */ \
+ add SINDEX, (SCB_DISCONNECTED_LISTS & 0xFF); \
+ mvi SINDEX[1], ((SCB_DISCONNECTED_LISTS >> 8) & 0xFF)
+
+mesgin_identify:
+ /*
+ * Determine whether a target is using tagged or non-tagged
+ * transactions by first looking at the transaction stored in
+ * the per-device, disconnected array. If there is no untagged
+ * transaction for this target, this must be a tagged transaction.
+ */
+ and SAVED_LUN, MSG_IDENTIFY_LUNMASK, A;
+ INDEX_DISC_LIST(SAVED_SCSIID, SAVED_LUN);
+ bmov DINDEX, SINDEX, 2;
+ bmov REG0, SINDIR, 2;
+ cmp REG0[1], SCB_LIST_NULL je snoop_tag;
+ /* Untagged. Clear the busy table entry and setup the SCB. */
+ bmov DINDIR, ALLONES, 2;
+ bmov SCBPTR, REG0, 2;
+ 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. After receiving the tag, look for the SCB at SCB locations tag and
+ * tag + 256.
+ */
+snoop_tag:
+ if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) {
+ or SEQ_FLAGS, 0x80;
+ }
+ mov NONE, SCSIDAT; /* ACK Identify MSG */
+ call phase_lock;
+ if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) {
+ or SEQ_FLAGS, 0x1;
+ }
+ cmp LASTPHASE, P_MESGIN jne not_found_ITloop;
+ if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) {
+ or SEQ_FLAGS, 0x2;
+ }
+ cmp SCSIBUS, MSG_SIMPLE_Q_TAG jne not_found;
+get_tag:
+ clr SCBPTR[1];
+ mvi SCBPTR call inb_next; /* tag value */
+verify_scb:
+ test SCB_CONTROL,DISCONNECTED jz verify_other_scb;
+ mov A, SAVED_SCSIID;
+ cmp SCB_SCSIID, A jne verify_other_scb;
+ mov A, SAVED_LUN;
+ cmp SCB_LUN, A je setup_SCB_disconnected;
+verify_other_scb:
+ xor SCBPTR[1], 1;
+ test SCBPTR[1], 0xFF jnz verify_scb;
+ jmp not_found;
+
+/*
+ * Ensure that the SCB the tag points to is for
+ * an SCB transaction to the reconnecting target.
+ */
+setup_SCB:
+ if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) {
+ or SEQ_FLAGS, 0x10;
+ }
+ test SCB_CONTROL,DISCONNECTED jz not_found;
+setup_SCB_disconnected:
+ and SCB_CONTROL,~DISCONNECTED;
+ clr SEQ_FLAGS; /* make note of IDENTIFY */
+ test SCB_SGPTR, SG_LIST_NULL jnz . + 3;
+ bmov ALLOCFIFO_SCBPTR, SCBPTR, 2;
+ call allocate_fifo;
+ /* See if the host wants to send a message upon reconnection */
+ test SCB_CONTROL, MK_MESSAGE jz mesgin_done;
+ mvi HOST_MSG call mk_mesg;
+ jmp mesgin_done;
+
+not_found:
+ SET_SEQINTCODE(NO_MATCH)
+ jmp mesgin_done;
+
+not_found_ITloop:
+ SET_SEQINTCODE(NO_MATCH)
+ jmp ITloop;
+
+/*
+ * We received a "command complete" message. Put the SCB on the complete
+ * queue and trigger a completion interrupt via the idle loop. Before doing
+ * so, check to see if there
+ * is a residual or the status byte is something other than STATUS_GOOD (0).
+ * In either of these conditions, we upload the SCB back to the host so it can
+ * process this information. In the case of a non zero status byte, we
+ * additionally interrupt the kernel driver synchronously, allowing it to
+ * decide if sense should be retrieved. If the kernel driver wishes to request
+ * sense, it will fill the kernel SCB with a request sense command, requeue
+ * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting
+ * RETURN_1 to SEND_SENSE.
+ */
+mesgin_complete:
+
+ /*
+ * If ATN is raised, we still want to give the target a message.
+ * Perhaps there was a parity error on this last message byte.
+ * Either way, the target should take us to message out phase
+ * and then attempt to complete the command again. We should use a
+ * critical section here to guard against a timeout triggering
+ * for this command and setting ATN while we are still processing
+ * the completion.
+ test SCSISIGI, ATNI jnz mesgin_done;
+ */
+
+ /*
+ * If we are identified and have successfully sent the CDB,
+ * any status will do. Optimize this fast path.
+ */
+ test SCB_CONTROL, STATUS_RCVD jz mesgin_proto_violation;
+ test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT jz complete_accepted;
+
+ /*
+ * If the target never sent an identify message but instead went
+ * to mesgin to give an invalid message, let the host abort us.
+ */
+ test SEQ_FLAGS, NOT_IDENTIFIED jnz mesgin_proto_violation;
+
+ /*
+ * If we recevied good status but never successfully sent the
+ * cdb, abort the command.
+ */
+ test SCB_SCSI_STATUS,0xff jnz complete_accepted;
+ test SEQ_FLAGS, NO_CDB_SENT jnz mesgin_proto_violation;
+complete_accepted:
+
+ /*
+ * See if we attempted to deliver a message but the target ingnored us.
+ */
+ test SCB_CONTROL, MK_MESSAGE jz complete_nomsg;
+ SET_SEQINTCODE(MKMSG_FAILED)
+complete_nomsg:
+ call queue_scb_completion;
+ jmp await_busfree;
+
+freeze_queue:
+ /* Cancel any pending select-out. */
+ test SSTAT0, SELDO|SELINGO jnz . + 2;
+ and SCSISEQ0, ~ENSELO;
+ mov ACCUM_SAVE, A;
+ clr A;
+ add QFREEZE_COUNT, 1;
+ adc QFREEZE_COUNT[1], A;
+ or SEQ_FLAGS2, SELECTOUT_QFROZEN;
+ mov A, ACCUM_SAVE ret;
+
+/*
+ * Complete the current FIFO's SCB if data for this same
+ * SCB is not transferring in the other FIFO.
+ */
+SET_SRC_MODE M_DFF1;
+SET_DST_MODE M_DFF1;
+pkt_complete_scb_if_fifos_idle:
+ bmov ARG_1, SCBPTR, 2;
+ mvi DFFSXFRCTL, CLRCHN;
+ SET_MODE(M_SCSI, M_SCSI)
+ bmov SCBPTR, ARG_1, 2;
+ test SCB_FIFO_USE_COUNT, 0xFF jnz return;
+queue_scb_completion:
+ test SCB_SCSI_STATUS,0xff jnz bad_status;
+ /*
+ * Check for residuals
+ */
+ test SCB_SGPTR, SG_LIST_NULL jnz complete; /* No xfer */
+ test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */
+ test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;
+complete:
+ bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
+ bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
+bad_status:
+ cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb;
+ call freeze_queue;
+upload_scb:
+ /*
+ * Restore SCB TAG since we reuse this field
+ * in the sequencer. We don't want to corrupt
+ * it on the host.
+ */
+ bmov SCB_TAG, SCBPTR, 2;
+ bmov SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2;
+ bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2;
+ or SCB_SGPTR, SG_STATUS_VALID ret;
+
+/*
+ * Is it a disconnect message? Set a flag in the SCB to remind us
+ * and await the bus going free. If this is an untagged transaction
+ * store the SCB id for it in our untagged target table for lookup on
+ * a reselction.
+ */
+mesgin_disconnect:
+ /*
+ * If ATN is raised, we still want to give the target a message.
+ * Perhaps there was a parity error on this last message byte
+ * or we want to abort this command. Either way, the target
+ * should take us to message out phase and then attempt to
+ * disconnect again.
+ * XXX - Wait for more testing.
+ test SCSISIGI, ATNI jnz mesgin_done;
+ */
+ test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT
+ jnz mesgin_proto_violation;
+ or SCB_CONTROL,DISCONNECTED;
+ test SCB_CONTROL, TAG_ENB jnz await_busfree;
+queue_disc_scb:
+ bmov REG0, SCBPTR, 2;
+ INDEX_DISC_LIST(SAVED_SCSIID, SAVED_LUN);
+ bmov DINDEX, SINDEX, 2;
+ bmov DINDIR, REG0, 2;
+ bmov SCBPTR, REG0, 2;
+ /* FALLTHROUGH */
+await_busfree:
+ and SIMODE1, ~ENBUSFREE;
+ if ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0) {
+ /*
+ * In the BUSFREEREV_BUG case, the
+ * busfree status was cleared at the
+ * beginning of the connection.
+ */
+ mvi CLRSINT1,CLRBUSFREE;
+ }
+ mov NONE, SCSIDAT; /* Ack the last byte */
+ test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1))
+ jnz await_busfree_not_m_dff;
+SET_SRC_MODE M_DFF1;
+SET_DST_MODE M_DFF1;
+await_busfree_clrchn:
+ mvi DFFSXFRCTL, CLRCHN;
+await_busfree_not_m_dff:
+ call clear_target_state;
+ test SSTAT1,REQINIT|BUSFREE jz .;
+ test SSTAT1, BUSFREE jnz idle_loop;
+ SET_SEQINTCODE(MISSED_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.
+ * Ack the message as soon as possible.
+ */
+SET_SRC_MODE M_DFF1;
+SET_DST_MODE M_DFF1;
+mesgin_sdptrs:
+ mov NONE,SCSIDAT; /*dummy read from latch to ACK*/
+ test SEQ_FLAGS, DPHASE jz ITloop;
+ call save_pointers;
+ jmp ITloop;
+
+save_pointers:
+ /*
+ * If we are asked to save our position at the end of the
+ * transfer, just mark us at the end rather than perform a
+ * full save.
+ */
+ test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz save_pointers_full;
+ or SCB_SGPTR, SG_LIST_NULL ret;
+
+save_pointers_full:
+ /*
+ * The SCB_DATAPTR becomes the current SHADDR.
+ * All other information comes directly from our residual
+ * state.
+ */
+ bmov SCB_DATAPTR, SHADDR, 8;
+ bmov SCB_DATACNT, SCB_RESIDUAL_DATACNT, 8 ret;
+
+/*
+ * 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. We also reset/reallocate the FIFO to make
+ * sure we have a clean start for the next data or command phase.
+ */
+mesgin_rdptrs:
+ and SEQ_FLAGS, ~DPHASE;
+ test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) jnz msgin_rdptrs_get_fifo;
+ mvi DFFSXFRCTL, RSTCHN|CLRSHCNT;
+ SET_MODE(M_SCSI, M_SCSI)
+msgin_rdptrs_get_fifo:
+ call allocate_fifo;
+ jmp mesgin_done;
+
+clear_target_state:
+ mvi LASTPHASE, P_BUSFREE;
+ /* clear target specific flags */
+ mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret;
+
+phase_lock:
+ if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) {
+ /*
+ * Don't ignore persistent REQ assertions just because
+ * they were asserted within the bus settle delay window.
+ * This allows us to tolerate devices like the GEM318
+ * that violate the SCSI spec. We are careful not to
+ * count REQ while we are waiting for it to fall during
+ * an async phase due to our asserted ACK. Each
+ * sequencer instruction takes ~25ns, so the REQ must
+ * last at least 100ns in order to be counted as a true
+ * REQ.
+ */
+ test SCSIPHASE, 0xFF jnz phase_locked;
+ test SCSISIGI, ACKI jnz phase_lock;
+ test SCSISIGI, REQI jz phase_lock;
+ test SCSIPHASE, 0xFF jnz phase_locked;
+ test SCSISIGI, ACKI jnz phase_lock;
+ test SCSISIGI, REQI jz phase_lock;
+phase_locked:
+ } else {
+ test SCSIPHASE, 0xFF jz .;
+ }
+ test SSTAT1, SCSIPERR jnz phase_lock;
+phase_lock_latch_phase:
+ and LASTPHASE, PHASE_MASK, SCSISIGI ret;
+
+/*
+ * Functions to read data in Automatic PIO mode.
+ *
+ * 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,SCSIDAT; /*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 SCSIPHASE, 0xFF jz .;
+ test SSTAT1, SCSIPERR jnz inb_next_wait;
+inb_next_check_phase:
+ and LASTPHASE, PHASE_MASK, SCSISIGI;
+ cmp LASTPHASE, P_MESGIN jne mesgin_phasemis;
+inb_first:
+ clr DINDEX[1];
+ mov DINDEX,SINDEX;
+ mov DINDIR,SCSIBUS ret; /*read byte directly from bus*/
+inb_last:
+ mov NONE,SCSIDAT ret; /*dummy read from latch to ACK*/
+
+mk_mesg:
+ mvi SCSISIGO, ATNO;
+ mov MSG_OUT,SINDEX ret;
+
+SET_SRC_MODE M_DFF1;
+SET_DST_MODE M_DFF1;
+disable_ccsgen:
+ test SG_STATE, FETCH_INPROG jz disable_ccsgen_fetch_done;
+ clr CCSGCTL;
+disable_ccsgen_fetch_done:
+ clr SG_STATE ret;
+
+service_fifo:
+ /*
+ * Do we have any prefetch left???
+ */
+ test SG_STATE, SEGS_AVAIL jnz idle_sg_avail;
+
+ /*
+ * Can this FIFO have access to the S/G cache yet?
+ */
+ test CCSGCTL, SG_CACHE_AVAIL jz return;
+
+ /* Did we just finish fetching segs? */
+ test CCSGCTL, CCSGDONE jnz idle_sgfetch_complete;
+
+ /* Are we actively fetching segments? */
+ test CCSGCTL, CCSGENACK jnz return;
+
+ /*
+ * We fetch a "cacheline aligned" and sized amount of data
+ * so we don't end up referencing a non-existant page.
+ * Cacheline aligned is in quotes because the kernel will
+ * set the prefetch amount to a reasonable level if the
+ * cacheline size is unknown.
+ */
+ bmov SGHADDR, SCB_RESIDUAL_SGPTR, 4;
+ mvi SGHCNT, SG_PREFETCH_CNT;
+ if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) {
+ /*
+ * Need two instruction between "touches" of SGHADDR.
+ */
+ nop;
+ }
+ and SGHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR;
+ mvi CCSGCTL, CCSGEN|CCSGRESET;
+ or SG_STATE, FETCH_INPROG ret;
+idle_sgfetch_complete:
+ /*
+ * Guard against SG_CACHE_AVAIL activating during sg fetch
+ * request in the other FIFO.
+ */
+ test SG_STATE, FETCH_INPROG jz return;
+ clr CCSGCTL;
+ and CCSGADDR, SG_PREFETCH_ADDR_MASK, SCB_RESIDUAL_SGPTR;
+ mvi SG_STATE, SEGS_AVAIL|LOADING_NEEDED;
+idle_sg_avail:
+ /* Does the hardware have space for another SG entry? */
+ test DFSTATUS, PRELOAD_AVAIL jz return;
+ /*
+ * On the A, preloading a segment before HDMAENACK
+ * comes true can clobber the shaddow address of the
+ * first segment in the S/G FIFO. Wait until it is
+ * safe to proceed.
+ */
+ if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0) {
+ test DFCNTRL, HDMAENACK jz return;
+ }
+ if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
+ bmov HADDR, CCSGRAM, 8;
+ } else {
+ bmov HADDR, CCSGRAM, 4;
+ }
+ bmov HCNT, CCSGRAM, 3;
+ bmov SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1;
+ if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) {
+ and HADDR[4], SG_HIGH_ADDR_BITS, SCB_RESIDUAL_DATACNT[3];
+ }
+ if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
+ /* Skip 4 bytes of pad. */
+ add CCSGADDR, 4;
+ }
+sg_advance:
+ clr A; /* add sizeof(struct scatter) */
+ add SCB_RESIDUAL_SGPTR[0],SG_SIZEOF;
+ adc SCB_RESIDUAL_SGPTR[1],A;
+ adc SCB_RESIDUAL_SGPTR[2],A;
+ adc SCB_RESIDUAL_SGPTR[3],A;
+ mov SINDEX, SCB_RESIDUAL_SGPTR[0];
+ test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 3;
+ or SINDEX, LAST_SEG;
+ clr SG_STATE;
+ mov SG_CACHE_PRE, SINDEX;
+ if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {
+ /*
+ * Use SCSIENWRDIS so that SCSIEN is never
+ * modified by this operation.
+ */
+ or DFCNTRL, PRELOADEN|HDMAEN|SCSIENWRDIS;
+ } else {
+ or DFCNTRL, PRELOADEN|HDMAEN;
+ }
+ /*
+ * Do we have another segment in the cache?
+ */
+ add NONE, SG_PREFETCH_CNT_LIMIT, CCSGADDR;
+ jnc return;
+ and SG_STATE, ~SEGS_AVAIL ret;
+
+/*
+ * Initialize the DMA address and counter from the SCB.
+ */
+load_first_seg:
+ bmov HADDR, SCB_DATAPTR, 11;
+ and REG_ISR, ~SG_FULL_RESID, SCB_SGPTR[0];
+ test SCB_DATACNT[3], SG_LAST_SEG jz . + 2;
+ or REG_ISR, LAST_SEG;
+ mov SG_CACHE_PRE, REG_ISR;
+ mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN);
+ /*
+ * Since we've are entering a data phase, we will
+ * rely on the SCB_RESID* fields. Initialize the
+ * residual and clear the full residual flag.
+ */
+ and SCB_SGPTR[0], ~SG_FULL_RESID;
+ bmov SCB_RESIDUAL_DATACNT[3], SCB_DATACNT[3], 5;
+ /* If we need more S/G elements, tell the idle loop */
+ test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz . + 2;
+ mvi SG_STATE, LOADING_NEEDED ret;
+ clr SG_STATE ret;
+
+p_data_handle_xfer:
+ call setjmp;
+ test SG_STATE, LOADING_NEEDED jnz service_fifo;
+p_data_clear_handler:
+ or LONGJMP_ADDR[1], INVALID_ADDR ret;
+
+p_data:
+ test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT jz p_data_allowed;
+ SET_SEQINTCODE(PROTO_VIOLATION)
+p_data_allowed:
+
+ test SEQ_FLAGS, DPHASE jz data_phase_initialize;
+
+ /*
+ * If we re-enter the data phase after going through another
+ * phase, our transfer location has almost certainly been
+ * corrupted by the interveining, non-data, transfers. Ask
+ * the host driver to fix us up based on the transfer residual
+ * unless we already know that we should be bitbucketing.
+ */
+ test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jnz p_data_bitbucket;
+ SET_SEQINTCODE(PDATA_REINIT)
+ jmp data_phase_inbounds;
+
+p_data_bitbucket:
+ /*
+ * Turn on `Bit Bucket' mode, wait until the target takes
+ * us to another phase, and then notify the host.
+ */
+ mov SAVED_MODE, MODE_PTR;
+ test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1))
+ jnz bitbucket_not_m_dff;
+ /*
+ * Ensure that any FIFO contents are cleared out and the
+ * FIFO free'd prior to starting the BITBUCKET. BITBUCKET
+ * doesn't discard data already in the FIFO.
+ */
+ mvi DFFSXFRCTL, RSTCHN|CLRSHCNT;
+ SET_MODE(M_SCSI, M_SCSI)
+bitbucket_not_m_dff:
+ or SXFRCTL1,BITBUCKET;
+ /* Wait for non-data phase. */
+ test SCSIPHASE, ~DATA_PHASE_MASK jz .;
+ and SXFRCTL1, ~BITBUCKET;
+ RESTORE_MODE(SAVED_MODE)
+SET_SRC_MODE M_DFF1;
+SET_DST_MODE M_DFF1;
+ SET_SEQINTCODE(DATA_OVERRUN)
+ jmp ITloop;
+
+data_phase_initialize:
+ test SCB_SGPTR[0], SG_LIST_NULL jnz p_data_bitbucket;
+ call load_first_seg;
+data_phase_inbounds:
+ /* We have seen a data phase at least once. */
+ or SEQ_FLAGS, DPHASE;
+ mov SAVED_MODE, MODE_PTR;
+ test SG_STATE, LOADING_NEEDED jz data_group_dma_loop;
+ call p_data_handle_xfer;
+data_group_dma_loop:
+ /*
+ * The transfer is complete if either the last segment
+ * completes or the target changes phase. Both conditions
+ * will clear SCSIEN.
+ */
+ call idle_loop_service_fifos;
+ call idle_loop_cchan;
+ call idle_loop_gsfifo;
+ RESTORE_MODE(SAVED_MODE)
+ test DFCNTRL, SCSIEN jnz data_group_dma_loop;
+
+data_group_dmafinish:
+ /*
+ * The transfer has terminated either due to a phase
+ * change, and/or the completion of the last segment.
+ * We have two goals here. Do as much other work
+ * as possible while the data fifo drains on a read
+ * and respond as quickly as possible to the standard
+ * messages (save data pointers/disconnect and command
+ * complete) that usually follow a data phase.
+ */
+ call calc_residual;
+
+ /*
+ * Go ahead and shut down the DMA engine now.
+ */
+ test DFCNTRL, DIRECTION jnz data_phase_finish;
+data_group_fifoflush:
+ if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) {
+ or DFCNTRL, FIFOFLUSH;
+ }
+ /*
+ * We have enabled the auto-ack feature. This means
+ * that the controller may have already transferred
+ * some overrun bytes into the data FIFO and acked them
+ * on the bus. The only way to detect this situation is
+ * to wait for LAST_SEG_DONE to come true on a completed
+ * transfer and then test to see if the data FIFO is
+ * non-empty. We know there is more data yet to transfer
+ * if SG_LIST_NULL is not yet set, thus there cannot be
+ * an overrun.
+ */
+ test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz data_phase_finish;
+ test SG_CACHE_SHADOW, LAST_SEG_DONE jz .;
+ test DFSTATUS, FIFOEMP jnz data_phase_finish;
+ /* Overrun */
+ jmp p_data;
+data_phase_finish:
+ /*
+ * If the target has left us in data phase, loop through
+ * the DMA code again. We will only loop if there is a
+ * data overrun.
+ */
+ if ((ahd->flags & AHD_TARGETROLE) != 0) {
+ test SSTAT0, TARGET jnz data_phase_done;
+ }
+ if ((ahd->flags & AHD_INITIATORROLE) != 0) {
+ test SSTAT1, REQINIT jz .;
+ test SCSIPHASE, DATA_PHASE_MASK jnz p_data;
+ }
+
+data_phase_done:
+ /* Kill off any pending prefetch */
+ call disable_ccsgen;
+ or LONGJMP_ADDR[1], INVALID_ADDR;
+
+ if ((ahd->flags & AHD_TARGETROLE) != 0) {
+ test SEQ_FLAGS, DPHASE_PENDING jz ITloop;
+ /*
+ and SEQ_FLAGS, ~DPHASE_PENDING;
+ * For data-in phases, wait for any pending acks from the
+ * initiator before changing phase. We only need to
+ * send Ignore Wide Residue messages for data-in phases.
+ test DFCNTRL, DIRECTION jz target_ITloop;
+ test SSTAT1, REQINIT jnz .;
+ test SCB_TASK_ATTRIBUTE, SCB_XFERLEN_ODD jz target_ITloop;
+ SET_MODE(M_SCSI, M_SCSI)
+ test NEGCONOPTS, WIDEXFER jz target_ITloop;
+ */
+ /*
+ * Issue an Ignore Wide Residue Message.
+ mvi P_MESGIN|BSYO call change_phase;
+ mvi MSG_IGN_WIDE_RESIDUE call target_outb;
+ mvi 1 call target_outb;
+ jmp target_ITloop;
+ */
+ } else {
+ jmp ITloop;
+ }
+
+/*
+ * We assume that, even though data may still be
+ * transferring to the host, that the SCSI side of
+ * the DMA engine is now in a static state. This
+ * allows us to update our notion of where we are
+ * in this transfer.
+ *
+ * If, by chance, we stopped before being able
+ * to fetch additional segments for this transfer,
+ * yet the last S/G was completely exhausted,
+ * call our idle loop until it is able to load
+ * another segment. This will allow us to immediately
+ * pickup on the next segment on the next data phase.
+ *
+ * If we happened to stop on the last segment, then
+ * our residual information is still correct from
+ * the idle loop and there is no need to perform
+ * any fixups.
+ */
+residual_before_last_seg:
+ test MDFFSTAT, SHVALID jnz sgptr_fixup;
+ /*
+ * Can never happen from an interrupt as the packetized
+ * hardware will only interrupt us once SHVALID or
+ * LAST_SEG_DONE.
+ */
+ call idle_loop_service_fifos;
+ RESTORE_MODE(SAVED_MODE)
+ /* FALLTHROUGH */
+calc_residual:
+ test SG_CACHE_SHADOW, LAST_SEG jz residual_before_last_seg;
+ /* Record if we've consumed all S/G entries */
+ test MDFFSTAT, SHVALID jz . + 2;
+ bmov SCB_RESIDUAL_DATACNT, SHCNT, 3 ret;
+ or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL ret;
+
+sgptr_fixup:
+ /*
+ * Fixup the residual next S/G pointer. The S/G preload
+ * feature of the chip allows us to load two elements
+ * in addition to the currently active element. We
+ * store the bottom byte of the next S/G pointer in
+ * the SG_CACHE_PTR register so we can restore the
+ * correct value when the DMA completes. If the next
+ * sg ptr value has advanced to the point where higher
+ * bytes in the address have been affected, fix them
+ * too.
+ */
+ test SG_CACHE_SHADOW, 0x80 jz sgptr_fixup_done;
+ test SCB_RESIDUAL_SGPTR[0], 0x80 jnz sgptr_fixup_done;
+ add SCB_RESIDUAL_SGPTR[1], -1;
+ adc SCB_RESIDUAL_SGPTR[2], -1;
+ adc SCB_RESIDUAL_SGPTR[3], -1;
+sgptr_fixup_done:
+ and SCB_RESIDUAL_SGPTR[0], SG_ADDR_MASK, SG_CACHE_SHADOW;
+ clr SCB_RESIDUAL_DATACNT[3]; /* We are not the last seg */
+ bmov SCB_RESIDUAL_DATACNT, SHCNT, 3 ret;
+
+export timer_isr:
+ call issue_cmdcmplt;
+ mvi CLRSEQINTSTAT, CLRSEQ_SWTMRTO;
+ if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) {
+ /*
+ * In H2A4, the mode pointer is not saved
+ * for intvec2, but is restored on iret.
+ * This can lead to the restoration of a
+ * bogus mode ptr. Manually clear the
+ * intmask bits and do a normal return
+ * to compensate.
+ */
+ and SEQINTCTL, ~(INTMASK2|INTMASK1) ret;
+ } else {
+ or SEQINTCTL, IRET ret;
+ }
+
+export seq_isr:
+ if ((ahd->features & AHD_RTI) == 0) {
+ /*
+ * On RevA Silicon, if the target returns us to data-out
+ * after we have already trained for data-out, it is
+ * possible for us to transition the free running clock to
+ * data-valid before the required 100ns P1 setup time (8 P1
+ * assertions in fast-160 mode). This will only happen if
+ * this L-Q is a continuation of a data transfer for which
+ * we have already prefetched data into our FIFO (LQ/Data
+ * followed by LQ/Data for the same write transaction).
+ * This can cause some target implementations to miss the
+ * first few data transfers on the bus. We detect this
+ * situation by noticing that this is the first data transfer
+ * after an LQ (LQIWORKONLQ true), that the data transfer is
+ * a continuation of a transfer already setup in our FIFO
+ * (SAVEPTRS interrupt), and that the transaction is a write
+ * (DIRECTION set in DFCNTRL). The delay is performed by
+ * disabling SCSIEN until we see the first REQ from the
+ * target.
+ *
+ * First instruction in an ISR cannot be a branch on
+ * Rev A. Snapshot LQISTAT2 so the status is not missed
+ * and deffer the test by one instruction.
+ */
+ mov REG_ISR, LQISTAT2;
+ test REG_ISR, LQIWORKONLQ jz main_isr;
+ test SEQINTSRC, SAVEPTRS jz main_isr;
+ test LONGJMP_ADDR[1], INVALID_ADDR jz saveptr_active_fifo;
+ /*
+ * Switch to the active FIFO after clearing the snapshot
+ * savepointer in the current FIFO. We do this so that
+ * a pending CTXTDONE or SAVEPTR is visible in the active
+ * FIFO. This status is the only way we can detect if we
+ * have lost the race (e.g. host paused us) and our attepts
+ * to disable the channel occurred after all REQs were
+ * already seen and acked (REQINIT never comes true).
+ */
+ mvi DFFSXFRCTL, CLRCHN;
+ xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
+ test DFCNTRL, DIRECTION jz interrupt_return;
+ and DFCNTRL, ~SCSIEN;
+snapshot_wait_data_valid:
+ test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid;
+ test SSTAT1, REQINIT jz snapshot_wait_data_valid;
+snapshot_data_valid:
+ or DFCNTRL, SCSIEN;
+ or SEQINTCTL, IRET ret;
+snapshot_saveptr:
+ mvi DFFSXFRCTL, CLRCHN;
+ or SEQINTCTL, IRET ret;
+main_isr:
+ }
+ test SEQINTSRC, CFG4DATA jnz cfg4data_intr;
+ test SEQINTSRC, CFG4ISTAT jnz cfg4istat_intr;
+ test SEQINTSRC, SAVEPTRS jnz saveptr_intr;
+ test SEQINTSRC, CFG4ICMD jnz cfg4icmd_intr;
+ SET_SEQINTCODE(INVALID_SEQINT)
+
+/*
+ * There are two types of save pointers interrupts:
+ * The first is a snapshot save pointers where the current FIFO is not
+ * active and contains a snapshot of the current poniter information.
+ * This happens between packets in a stream for a single L_Q. Since we
+ * are not performing a pointer save, we can safely clear the channel
+ * so it can be used for other transactions. On RTI capable controllers,
+ * where snapshots can, and are, disabled, the code to handle this type
+ * of snapshot is not active.
+ *
+ * The second case is a save pointers on an active FIFO which occurs
+ * if the target changes to a new L_Q or busfrees/QASes and the transfer
+ * has a residual. This should occur coincident with a ctxtdone. We
+ * disable the interrupt and allow our active routine to handle the
+ * save.
+ */
+saveptr_intr:
+ if ((ahd->features & AHD_RTI) == 0) {
+ test LONGJMP_ADDR[1], INVALID_ADDR jnz snapshot_saveptr;
+ }
+saveptr_active_fifo:
+ and SEQIMODE, ~ENSAVEPTRS;
+ or SEQINTCTL, IRET ret;
+
+cfg4data_intr:
+ test SCB_SGPTR[0], SG_LIST_NULL jnz pkt_handle_overrun_inc_use_count;
+ call load_first_seg;
+ call pkt_handle_xfer;
+ inc SCB_FIFO_USE_COUNT;
+interrupt_return:
+ or SEQINTCTL, IRET ret;
+
+cfg4istat_intr:
+ call freeze_queue;
+ add NONE, -13, SCB_CDB_LEN;
+ jnc cfg4istat_have_sense_addr;
+ test SCB_CDB_LEN, SCB_CDB_LEN_PTR jnz cfg4istat_have_sense_addr;
+ /*
+ * Host sets up address/count and enables transfer.
+ */
+ SET_SEQINTCODE(CFG4ISTAT_INTR)
+ jmp cfg4istat_setup_handler;
+cfg4istat_have_sense_addr:
+ bmov HADDR, SCB_SENSE_BUSADDR, 4;
+ mvi HCNT[1], (AHD_SENSE_BUFSIZE >> 8);
+ mvi SG_CACHE_PRE, LAST_SEG;
+ mvi DFCNTRL, PRELOADEN|SCSIEN|HDMAEN;
+cfg4istat_setup_handler:
+ /*
+ * Status pkt is transferring to host.
+ * Wait in idle loop for transfer to complete.
+ * If a command completed before an attempted
+ * task management function completed, notify the host.
+ */
+ test SCB_TASK_MANAGEMENT, 0xFF jz cfg4istat_no_taskmgmt_func;
+ SET_SEQINTCODE(TASKMGMT_CMD_CMPLT_OKAY)
+cfg4istat_no_taskmgmt_func:
+ call pkt_handle_status;
+ or SEQINTCTL, IRET ret;
+
+cfg4icmd_intr:
+ /*
+ * In the case of DMAing a CDB from the host, the normal
+ * CDB buffer is formatted with an 8 byte address followed
+ * by a 1 byte count.
+ */
+ bmov HADDR[0], SCB_HOST_CDB_PTR, 9;
+ mvi SG_CACHE_PRE, LAST_SEG;
+ mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN);
+ call pkt_handle_cdb;
+ or SEQINTCTL, IRET ret;
+
+/*
+ * See if the target has gone on in this context creating an
+ * overrun condition. For the write case, the hardware cannot
+ * ack bytes until data are provided. So, if the target begins
+ * another packet without changing contexts, implying we are
+ * not sitting on a packet boundary, we are in an overrun
+ * situation. For the read case, the hardware will continue to
+ * ack bytes into the FIFO, and may even ack the last overrun packet
+ * into the FIFO. If the FIFO should become non-empty, we are in
+ * a read overrun case.
+ */
+#define check_overrun \
+ /* Not on a packet boundary. */ \
+ test MDFFSTAT, DLZERO jz pkt_handle_overrun; \
+ test DFSTATUS, FIFOEMP jz pkt_handle_overrun
+
+pkt_handle_xfer:
+ test SG_STATE, LOADING_NEEDED jz pkt_last_seg;
+ call setjmp;
+ test SEQINTSRC, SAVEPTRS jnz pkt_saveptrs;
+ test SCSIPHASE, ~DATA_PHASE_MASK jz . + 2;
+ test SCSISIGO, ATNO jnz . + 2;
+ test SSTAT2, NONPACKREQ jz pkt_service_fifo;
+ /*
+ * Defer handling of this NONPACKREQ until we
+ * can be sure it pertains to this FIFO. SAVEPTRS
+ * will not be asserted if the NONPACKREQ is for us,
+ * so we must simulate it if shaddow is valid. If
+ * shaddow is not valid, keep running this FIFO until we
+ * have satisfied the transfer by loading segments and
+ * waiting for either shaddow valid or last_seg_done.
+ */
+ test MDFFSTAT, SHVALID jnz pkt_saveptrs;
+pkt_service_fifo:
+ test SG_STATE, LOADING_NEEDED jnz service_fifo;
+pkt_last_seg:
+ call setjmp;
+ test SEQINTSRC, SAVEPTRS jnz pkt_saveptrs;
+ test SG_CACHE_SHADOW, LAST_SEG_DONE jnz pkt_last_seg_done;
+ test SCSIPHASE, ~DATA_PHASE_MASK jz . + 2;
+ test SCSISIGO, ATNO jnz . + 2;
+ test SSTAT2, NONPACKREQ jz return;
+ test MDFFSTAT, SHVALID jz return;
+ /* FALLTHROUGH */
+
+/*
+ * Either a SAVEPTRS interrupt condition is pending for this FIFO
+ * or we have a pending NONPACKREQ for this FIFO. We differentiate
+ * between the two by capturing the state of the SAVEPTRS interrupt
+ * prior to clearing this status and executing the common code for
+ * these two cases.
+ */
+pkt_saveptrs:
+BEGIN_CRITICAL;
+ if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) {
+ or DFCNTRL, FIFOFLUSH;
+ }
+ mov REG0, SEQINTSRC;
+ call calc_residual;
+ call save_pointers;
+ mvi CLRSEQINTSRC, CLRSAVEPTRS;
+ call disable_ccsgen;
+ or SEQIMODE, ENSAVEPTRS;
+ test DFCNTRL, DIRECTION jnz pkt_saveptrs_check_status;
+ test DFSTATUS, FIFOEMP jnz pkt_saveptrs_check_status;
+ /*
+ * Keep a handler around for this FIFO until it drains
+ * to the host to guarantee that we don't complete the
+ * command to the host before the data arrives.
+ */
+pkt_saveptrs_wait_fifoemp:
+ call setjmp;
+ test DFSTATUS, FIFOEMP jz return;
+pkt_saveptrs_check_status:
+ or LONGJMP_ADDR[1], INVALID_ADDR;
+ test REG0, SAVEPTRS jz unexpected_nonpkt_phase;
+ dec SCB_FIFO_USE_COUNT;
+ test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;
+ mvi DFFSXFRCTL, CLRCHN ret;
+END_CRITICAL;
+
+/*
+ * LAST_SEG_DONE status has been seen in the current FIFO.
+ * This indicates that all of the allowed data for this
+ * command has transferred across the SCSI and host buses.
+ * Check for overrun and see if we can complete this command.
+ */
+pkt_last_seg_done:
+BEGIN_CRITICAL;
+ /*
+ * Mark transfer as completed.
+ */
+ or SCB_SGPTR, SG_LIST_NULL;
+
+ /*
+ * Wait for the current context to finish to verify that
+ * no overrun condition has occurred.
+ */
+ test SEQINTSRC, CTXTDONE jnz pkt_ctxt_done;
+ call setjmp;
+pkt_wait_ctxt_done_loop:
+ test SEQINTSRC, CTXTDONE jnz pkt_ctxt_done;
+ /*
+ * A sufficiently large overrun or a NONPACKREQ may
+ * prevent CTXTDONE from ever asserting, so we must
+ * poll for these statuses too.
+ */
+ check_overrun;
+ test SSTAT2, NONPACKREQ jz return;
+ test SEQINTSRC, CTXTDONE jz unexpected_nonpkt_phase;
+ /* FALLTHROUGH */
+
+pkt_ctxt_done:
+ check_overrun;
+ or LONGJMP_ADDR[1], INVALID_ADDR;
+ /*
+ * If status has been received, it is safe to skip
+ * the check to see if another FIFO is active because
+ * LAST_SEG_DONE has been observed. However, we check
+ * the FIFO anyway since it costs us only one extra
+ * instruction to leverage common code to perform the
+ * SCB completion.
+ */
+ dec SCB_FIFO_USE_COUNT;
+ test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;
+ mvi DFFSXFRCTL, CLRCHN ret;
+END_CRITICAL;
+
+/*
+ * Must wait until CDB xfer is over before issuing the
+ * clear channel.
+ */
+pkt_handle_cdb:
+ call setjmp;
+ test SG_CACHE_SHADOW, LAST_SEG_DONE jz return;
+ or LONGJMP_ADDR[1], INVALID_ADDR;
+ mvi DFFSXFRCTL, CLRCHN ret;
+
+/*
+ * Watch over the status transfer. Our host sense buffer is
+ * large enough to take the maximum allowed status packet.
+ * None-the-less, we must still catch and report overruns to
+ * the host. Additionally, properly catch unexpected non-packet
+ * phases that are typically caused by CRC errors in status packet
+ * transmission.
+ */
+pkt_handle_status:
+ call setjmp;
+ test SG_CACHE_SHADOW, LAST_SEG_DONE jnz pkt_status_check_overrun;
+ test SEQINTSRC, CTXTDONE jz pkt_status_check_nonpackreq;
+ test SG_CACHE_SHADOW, LAST_SEG_DONE jnz pkt_status_check_overrun;
+pkt_status_IU_done:
+ if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) {
+ or DFCNTRL, FIFOFLUSH;
+ }
+ test DFSTATUS, FIFOEMP jz return;
+BEGIN_CRITICAL;
+ or LONGJMP_ADDR[1], INVALID_ADDR;
+ mvi SCB_SCSI_STATUS, STATUS_PKT_SENSE;
+ or SCB_CONTROL, STATUS_RCVD;
+ jmp pkt_complete_scb_if_fifos_idle;
+END_CRITICAL;
+pkt_status_check_overrun:
+ /*
+ * Status PKT overruns are uncerimoniously recovered with a
+ * bus reset. If we've overrun, let the host know so that
+ * recovery can be performed.
+ *
+ * LAST_SEG_DONE has been observed. If either CTXTDONE or
+ * a NONPACKREQ phase change have occurred and the FIFO is
+ * empty, there is no overrun.
+ */
+ test DFSTATUS, FIFOEMP jz pkt_status_report_overrun;
+ test SEQINTSRC, CTXTDONE jz . + 2;
+ test DFSTATUS, FIFOEMP jnz pkt_status_IU_done;
+ test SCSIPHASE, ~DATA_PHASE_MASK jz return;
+ test DFSTATUS, FIFOEMP jnz pkt_status_check_nonpackreq;
+pkt_status_report_overrun:
+ SET_SEQINTCODE(STATUS_OVERRUN)
+ /* SEQUENCER RESTARTED */
+pkt_status_check_nonpackreq:
+ /*
+ * CTXTDONE may be held off if a NONPACKREQ is associated with
+ * the current context. If a NONPACKREQ is observed, decide
+ * if it is for the current context. If it is for the current
+ * context, we must defer NONPACKREQ processing until all data
+ * has transferred to the host.
+ */
+ test SCSIPHASE, ~DATA_PHASE_MASK jz return;
+ test SCSISIGO, ATNO jnz . + 2;
+ test SSTAT2, NONPACKREQ jz return;
+ test SEQINTSRC, CTXTDONE jnz pkt_status_IU_done;
+ test DFSTATUS, FIFOEMP jz return;
+ /*
+ * The unexpected nonpkt phase handler assumes that any
+ * data channel use will have a FIFO reference count. It
+ * turns out that the status handler doesn't need a refernce
+ * count since the status received flag, and thus completion
+ * processing, cannot be set until the handler is finished.
+ * We increment the count here to make the nonpkt handler
+ * happy.
+ */
+ inc SCB_FIFO_USE_COUNT;
+ /* FALLTHROUGH */
+
+/*
+ * Nonpackreq is a polled status. It can come true in three situations:
+ * we have received an L_Q, we have sent one or more L_Qs, or there is no
+ * L_Q context associated with this REQ (REQ occurs immediately after a
+ * (re)selection). Routines that know that the context responsible for this
+ * nonpackreq call directly into unexpected_nonpkt_phase. In the case of the
+ * top level idle loop, we exhaust all active contexts prior to determining that
+ * we simply do not have the full I_T_L_Q for this phase.
+ */
+unexpected_nonpkt_phase_find_ctxt:
+ /*
+ * This nonpackreq is most likely associated with one of the tags
+ * in a FIFO or an outgoing LQ. Only treat it as an I_T only
+ * nonpackreq if we've cleared out the FIFOs and handled any
+ * pending SELDO.
+ */
+SET_SRC_MODE M_SCSI;
+SET_DST_MODE M_SCSI;
+ and A, FIFO1FREE|FIFO0FREE, DFFSTAT;
+ cmp A, FIFO1FREE|FIFO0FREE jne return;
+ test SSTAT0, SELDO jnz return;
+ mvi SCBPTR[1], SCB_LIST_NULL;
+unexpected_nonpkt_phase:
+ test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1))
+ jnz unexpected_nonpkt_mode_cleared;
+SET_SRC_MODE M_DFF0;
+SET_DST_MODE M_DFF0;
+ or LONGJMP_ADDR[1], INVALID_ADDR;
+ dec SCB_FIFO_USE_COUNT;
+ mvi DFFSXFRCTL, CLRCHN;
+unexpected_nonpkt_mode_cleared:
+ mvi CLRSINT2, CLRNONPACKREQ;
+ test SCSIPHASE, ~(MSG_IN_PHASE|MSG_OUT_PHASE) jnz illegal_phase;
+ SET_SEQINTCODE(ENTERING_NONPACK)
+ jmp ITloop;
+
+illegal_phase:
+ SET_SEQINTCODE(ILLEGAL_PHASE)
+ jmp ITloop;
+
+/*
+ * We have entered an overrun situation. If we have working
+ * BITBUCKET, flip that on and let the hardware eat any overrun
+ * data. Otherwise use an overrun buffer in the host to simulate
+ * BITBUCKET.
+ */
+pkt_handle_overrun_inc_use_count:
+ inc SCB_FIFO_USE_COUNT;
+pkt_handle_overrun:
+ SET_SEQINTCODE(CFG4OVERRUN)
+ call freeze_queue;
+ if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0) {
+ or DFFSXFRCTL, DFFBITBUCKET;
+SET_SRC_MODE M_DFF1;
+SET_DST_MODE M_DFF1;
+ } else {
+ call load_overrun_buf;
+ mvi DFCNTRL, (HDMAEN|SCSIEN|PRELOADEN);
+ }
+ call setjmp;
+ if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) {
+ test DFSTATUS, PRELOAD_AVAIL jz overrun_load_done;
+ call load_overrun_buf;
+ or DFCNTRL, PRELOADEN;
+overrun_load_done:
+ test SEQINTSRC, CTXTDONE jnz pkt_overrun_end;
+ } else {
+ test DFFSXFRCTL, DFFBITBUCKET jz pkt_overrun_end;
+ }
+ test SSTAT2, NONPACKREQ jz return;
+pkt_overrun_end:
+ or SCB_RESIDUAL_SGPTR, SG_OVERRUN_RESID;
+ test SEQINTSRC, CTXTDONE jz unexpected_nonpkt_phase;
+ dec SCB_FIFO_USE_COUNT;
+ or LONGJMP_ADDR[1], INVALID_ADDR;
+ test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;
+ mvi DFFSXFRCTL, CLRCHN ret;
+
+if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) {
+load_overrun_buf:
+ /*
+ * Load a dummy segment if preload space is available.
+ */
+ mov HADDR[0], SHARED_DATA_ADDR;
+ add HADDR[1], PKT_OVERRUN_BUFOFFSET, SHARED_DATA_ADDR[1];
+ mov ACCUM_SAVE, A;
+ clr A;
+ adc HADDR[2], A, SHARED_DATA_ADDR[2];
+ adc HADDR[3], A, SHARED_DATA_ADDR[3];
+ mov A, ACCUM_SAVE;
+ bmov HADDR[4], ALLZEROS, 4;
+ /* PKT_OVERRUN_BUFSIZE is a multiple of 256 */
+ clr HCNT[0];
+ mvi HCNT[1], ((PKT_OVERRUN_BUFSIZE >> 8) & 0xFF);
+ clr HCNT[2] ret;
+}
diff --git a/sys/dev/microcode/aic7xxx/aic79xx_seq.h b/sys/dev/microcode/aic7xxx/aic79xx_seq.h
new file mode 100644
index 00000000000..a6458651968
--- /dev/null
+++ b/sys/dev/microcode/aic7xxx/aic79xx_seq.h
@@ -0,0 +1,1140 @@
+/* $OpenBSD: aic79xx_seq.h,v 1.1 2003/12/24 22:40:16 krw Exp $ */
+/*
+ * DO NOT EDIT - This file is automatically generated
+ * from the following source files:
+ *
+ * Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#96 $
+ * Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
+ */
+static uint8_t seqprog[] = {
+ 0xff, 0x02, 0x06, 0x78,
+ 0x00, 0xea, 0x50, 0x59,
+ 0x01, 0xea, 0x04, 0x30,
+ 0xff, 0x04, 0x0c, 0x78,
+ 0x19, 0xea, 0x50, 0x59,
+ 0x19, 0xea, 0x04, 0x00,
+ 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x00, 0x00,
+ 0x60, 0x3a, 0x1a, 0x68,
+ 0x04, 0x47, 0x1b, 0x68,
+ 0xff, 0x21, 0x1b, 0x70,
+ 0x40, 0x4b, 0x92, 0x69,
+ 0x00, 0xe2, 0x54, 0x59,
+ 0x40, 0x4b, 0x92, 0x69,
+ 0x20, 0x4b, 0x82, 0x69,
+ 0xfc, 0x42, 0x24, 0x78,
+ 0x10, 0x40, 0x24, 0x78,
+ 0x00, 0xe2, 0xc4, 0x5d,
+ 0x20, 0x4d, 0x28, 0x78,
+ 0x00, 0xe2, 0xc4, 0x5d,
+ 0x30, 0x3f, 0xc0, 0x09,
+ 0x30, 0xe0, 0x30, 0x60,
+ 0x7f, 0x4a, 0x94, 0x08,
+ 0x00, 0xe2, 0x32, 0x40,
+ 0xc0, 0x4a, 0x94, 0x00,
+ 0x00, 0xe2, 0x3e, 0x58,
+ 0x00, 0xe2, 0x56, 0x58,
+ 0x00, 0xe2, 0x66, 0x58,
+ 0x00, 0xe2, 0x06, 0x40,
+ 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x00, 0x00,
+ 0x01, 0x52, 0x64, 0x78,
+ 0x02, 0x58, 0x50, 0x31,
+ 0xff, 0xea, 0x10, 0x0b,
+ 0xff, 0x97, 0x4f, 0x78,
+ 0x50, 0x4b, 0x4a, 0x68,
+ 0xbf, 0x3a, 0x74, 0x08,
+ 0x14, 0xea, 0x50, 0x59,
+ 0x14, 0xea, 0x04, 0x00,
+ 0x08, 0x92, 0x25, 0x03,
+ 0xff, 0x90, 0x3f, 0x68,
+ 0x00, 0xe2, 0x56, 0x5b,
+ 0x00, 0xe2, 0x3e, 0x40,
+ 0x00, 0xea, 0x44, 0x59,
+ 0x01, 0xea, 0x00, 0x30,
+ 0x80, 0xf9, 0x5e, 0x68,
+ 0x00, 0xe2, 0x42, 0x59,
+ 0x11, 0xea, 0x44, 0x59,
+ 0x11, 0xea, 0x00, 0x00,
+ 0x80, 0xf9, 0x42, 0x79,
+ 0xff, 0xea, 0xd4, 0x0d,
+ 0x22, 0xea, 0x44, 0x59,
+ 0x22, 0xea, 0x00, 0x00,
+ 0x10, 0x16, 0x70, 0x78,
+ 0x01, 0x0b, 0xa2, 0x32,
+ 0x10, 0x16, 0x2c, 0x00,
+ 0x18, 0xad, 0x00, 0x79,
+ 0x04, 0xad, 0xca, 0x68,
+ 0x80, 0xad, 0x64, 0x78,
+ 0x10, 0xad, 0x98, 0x78,
+ 0xff, 0x88, 0x83, 0x68,
+ 0xe7, 0xad, 0x5a, 0x09,
+ 0x02, 0x8c, 0x59, 0x32,
+ 0x02, 0x28, 0x19, 0x33,
+ 0x02, 0xa8, 0x50, 0x36,
+ 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x00, 0x00,
+ 0x40, 0x3a, 0x64, 0x68,
+ 0x50, 0x4b, 0x64, 0x68,
+ 0x22, 0xea, 0x44, 0x59,
+ 0x22, 0xea, 0x00, 0x00,
+ 0xe7, 0xad, 0x5a, 0x09,
+ 0x02, 0x8c, 0x59, 0x32,
+ 0x1a, 0xea, 0x50, 0x59,
+ 0x1a, 0xea, 0x04, 0x00,
+ 0xff, 0xea, 0xd4, 0x0d,
+ 0xe7, 0xad, 0x5a, 0x09,
+ 0x00, 0xe2, 0xa6, 0x58,
+ 0xff, 0xea, 0x56, 0x02,
+ 0x04, 0x7c, 0x78, 0x32,
+ 0x20, 0x16, 0x64, 0x78,
+ 0x04, 0x38, 0x79, 0x32,
+ 0x80, 0x37, 0x6f, 0x16,
+ 0xff, 0x2d, 0xb5, 0x60,
+ 0xff, 0x29, 0xb5, 0x60,
+ 0x40, 0x51, 0xc5, 0x78,
+ 0xff, 0x4f, 0xb5, 0x68,
+ 0xff, 0x4d, 0xc1, 0x19,
+ 0x00, 0x4e, 0xd5, 0x19,
+ 0x00, 0xe2, 0xc4, 0x50,
+ 0x01, 0x4c, 0xc1, 0x31,
+ 0x00, 0x50, 0xd5, 0x19,
+ 0x00, 0xe2, 0xc4, 0x48,
+ 0x80, 0x18, 0x64, 0x78,
+ 0x02, 0x4a, 0x1d, 0x30,
+ 0x10, 0xea, 0x18, 0x00,
+ 0x60, 0x18, 0x30, 0x00,
+ 0x7f, 0x18, 0x30, 0x0c,
+ 0x02, 0xea, 0x02, 0x00,
+ 0xff, 0xea, 0xa0, 0x0a,
+ 0x80, 0x18, 0x30, 0x04,
+ 0x40, 0xad, 0x64, 0x78,
+ 0xe7, 0xad, 0x5a, 0x09,
+ 0x02, 0xa8, 0x40, 0x31,
+ 0xff, 0xea, 0xc0, 0x09,
+ 0x01, 0x4e, 0x9d, 0x1a,
+ 0x00, 0x4f, 0x9f, 0x22,
+ 0x01, 0x94, 0x6d, 0x33,
+ 0xff, 0xea, 0x20, 0x0b,
+ 0x04, 0xac, 0x49, 0x32,
+ 0xff, 0xea, 0x5a, 0x03,
+ 0xff, 0xea, 0x5e, 0x03,
+ 0x01, 0x10, 0xd4, 0x31,
+ 0x10, 0x92, 0xf5, 0x68,
+ 0x3d, 0x93, 0xc5, 0x29,
+ 0xfe, 0xe2, 0xc4, 0x09,
+ 0x01, 0xea, 0xc6, 0x01,
+ 0x02, 0xe2, 0xc8, 0x31,
+ 0x02, 0xec, 0x50, 0x31,
+ 0x02, 0xa0, 0xda, 0x31,
+ 0xff, 0xa9, 0xf4, 0x70,
+ 0x02, 0xa0, 0x58, 0x37,
+ 0xff, 0x21, 0xfd, 0x70,
+ 0x02, 0x22, 0x51, 0x31,
+ 0x02, 0xa0, 0x5c, 0x33,
+ 0x02, 0xa0, 0x44, 0x36,
+ 0x02, 0xa0, 0x40, 0x32,
+ 0x02, 0xa0, 0x44, 0x36,
+ 0x04, 0x47, 0x05, 0x69,
+ 0x40, 0x16, 0x30, 0x69,
+ 0xff, 0x2d, 0x35, 0x61,
+ 0xff, 0x29, 0x65, 0x70,
+ 0x01, 0x37, 0xc1, 0x31,
+ 0x02, 0x28, 0x55, 0x32,
+ 0x01, 0xea, 0x5a, 0x01,
+ 0x04, 0x3c, 0xf9, 0x30,
+ 0x02, 0x28, 0x51, 0x31,
+ 0x01, 0xa8, 0x60, 0x31,
+ 0x00, 0xa9, 0x60, 0x01,
+ 0x01, 0x14, 0xd4, 0x31,
+ 0x01, 0x50, 0xa1, 0x1a,
+ 0xff, 0x4e, 0x9d, 0x1a,
+ 0xff, 0x4f, 0x9f, 0x22,
+ 0xff, 0x8d, 0x29, 0x71,
+ 0x80, 0xac, 0x28, 0x71,
+ 0x20, 0x16, 0x28, 0x69,
+ 0x02, 0x8c, 0x51, 0x31,
+ 0x00, 0xe2, 0x12, 0x41,
+ 0x01, 0xac, 0x08, 0x31,
+ 0x09, 0xea, 0x5a, 0x01,
+ 0x02, 0x8c, 0x51, 0x32,
+ 0xff, 0xea, 0x1a, 0x07,
+ 0x04, 0x24, 0xf9, 0x30,
+ 0x1d, 0xea, 0x3a, 0x41,
+ 0x02, 0x2c, 0x51, 0x31,
+ 0x04, 0xa8, 0xf9, 0x30,
+ 0x19, 0xea, 0x3a, 0x41,
+ 0x06, 0xea, 0x08, 0x81,
+ 0x01, 0xe2, 0x5a, 0x35,
+ 0x02, 0xf2, 0xf0, 0x35,
+ 0x02, 0xf2, 0xf0, 0x31,
+ 0x02, 0xf8, 0xe4, 0x35,
+ 0x80, 0xea, 0xb2, 0x01,
+ 0x01, 0xe2, 0x00, 0x30,
+ 0xff, 0xea, 0xb2, 0x0d,
+ 0x80, 0xea, 0xb2, 0x01,
+ 0x11, 0x00, 0x00, 0x10,
+ 0xff, 0xea, 0xb2, 0x0d,
+ 0x01, 0xe2, 0x04, 0x30,
+ 0x01, 0xea, 0x04, 0x34,
+ 0x02, 0x20, 0xbd, 0x30,
+ 0x02, 0x20, 0xb9, 0x30,
+ 0x02, 0x20, 0x51, 0x31,
+ 0x4c, 0x93, 0xd7, 0x28,
+ 0x10, 0x92, 0x63, 0x79,
+ 0x01, 0x6b, 0xc0, 0x30,
+ 0x02, 0x64, 0xc8, 0x00,
+ 0x40, 0x3a, 0x74, 0x04,
+ 0x00, 0xe2, 0x56, 0x58,
+ 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x00, 0x00,
+ 0x30, 0x3f, 0xc0, 0x09,
+ 0x30, 0xe0, 0x64, 0x61,
+ 0x20, 0x3f, 0x7a, 0x69,
+ 0x10, 0x3f, 0x64, 0x79,
+ 0x02, 0xea, 0x7e, 0x00,
+ 0x00, 0xea, 0x44, 0x59,
+ 0x01, 0xea, 0x00, 0x30,
+ 0x02, 0x48, 0x51, 0x35,
+ 0x01, 0xea, 0x7e, 0x00,
+ 0x11, 0xea, 0x44, 0x59,
+ 0x11, 0xea, 0x00, 0x00,
+ 0x02, 0x48, 0x51, 0x35,
+ 0x08, 0xea, 0x98, 0x00,
+ 0x08, 0x57, 0xae, 0x00,
+ 0x08, 0x3c, 0x78, 0x00,
+ 0xf0, 0x49, 0x68, 0x0a,
+ 0x0f, 0x67, 0xc0, 0x09,
+ 0x00, 0x34, 0x69, 0x02,
+ 0x20, 0xea, 0x96, 0x00,
+ 0x00, 0xe2, 0xf8, 0x41,
+ 0x40, 0x3a, 0xae, 0x69,
+ 0x02, 0x55, 0x06, 0x68,
+ 0x02, 0x56, 0xae, 0x69,
+ 0xff, 0x5b, 0xae, 0x61,
+ 0x02, 0x20, 0x51, 0x31,
+ 0x80, 0xea, 0xb2, 0x01,
+ 0x44, 0xea, 0x00, 0x00,
+ 0x01, 0x33, 0xc0, 0x31,
+ 0x33, 0xea, 0x00, 0x00,
+ 0xff, 0xea, 0xb2, 0x09,
+ 0xff, 0xe0, 0xc0, 0x19,
+ 0xff, 0xe0, 0xb0, 0x79,
+ 0x02, 0xac, 0x51, 0x31,
+ 0x00, 0xe2, 0xa6, 0x41,
+ 0x02, 0x5e, 0x50, 0x31,
+ 0x02, 0xa8, 0xb8, 0x30,
+ 0x02, 0x5c, 0x50, 0x31,
+ 0xff, 0xad, 0xc1, 0x71,
+ 0x02, 0xac, 0x41, 0x31,
+ 0x02, 0x22, 0x51, 0x31,
+ 0x02, 0xa0, 0x5c, 0x33,
+ 0x02, 0xa0, 0x44, 0x32,
+ 0x00, 0xe2, 0xca, 0x41,
+ 0x10, 0x92, 0xcb, 0x69,
+ 0x3d, 0x93, 0xc9, 0x29,
+ 0x01, 0xe4, 0xc8, 0x01,
+ 0x01, 0xea, 0xca, 0x01,
+ 0xff, 0xea, 0xda, 0x01,
+ 0x02, 0x20, 0x51, 0x31,
+ 0x02, 0xae, 0x41, 0x32,
+ 0xff, 0x21, 0xd3, 0x61,
+ 0xff, 0xea, 0x46, 0x02,
+ 0x02, 0x5c, 0x50, 0x31,
+ 0x40, 0xea, 0x96, 0x00,
+ 0x02, 0x56, 0xcc, 0x6d,
+ 0x01, 0x55, 0xcc, 0x6d,
+ 0x10, 0x92, 0xdf, 0x79,
+ 0x10, 0x40, 0xe8, 0x69,
+ 0x01, 0x56, 0xe8, 0x79,
+ 0xff, 0x97, 0x07, 0x78,
+ 0x13, 0xea, 0x50, 0x59,
+ 0x13, 0xea, 0x04, 0x00,
+ 0x00, 0xe2, 0x06, 0x40,
+ 0xbf, 0x3a, 0x74, 0x08,
+ 0x08, 0xea, 0x98, 0x00,
+ 0x08, 0x57, 0xae, 0x00,
+ 0x01, 0x93, 0x69, 0x32,
+ 0x01, 0x94, 0x6b, 0x32,
+ 0x40, 0xea, 0x66, 0x02,
+ 0x08, 0x3c, 0x78, 0x00,
+ 0x80, 0xea, 0x62, 0x02,
+ 0x00, 0xe2, 0xb8, 0x5b,
+ 0x01, 0x36, 0xc1, 0x31,
+ 0x9f, 0xe0, 0x4c, 0x7c,
+ 0x80, 0xe0, 0x0c, 0x72,
+ 0xa0, 0xe0, 0x44, 0x72,
+ 0xc0, 0xe0, 0x3a, 0x72,
+ 0xe0, 0xe0, 0x74, 0x72,
+ 0x01, 0xea, 0x50, 0x59,
+ 0x01, 0xea, 0x04, 0x00,
+ 0x00, 0xe2, 0xf8, 0x41,
+ 0x80, 0x33, 0x13, 0x7a,
+ 0x03, 0xea, 0x50, 0x59,
+ 0x03, 0xea, 0x04, 0x00,
+ 0xee, 0x00, 0x1a, 0x6a,
+ 0x05, 0xea, 0xb4, 0x00,
+ 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x00, 0x00,
+ 0x02, 0xa8, 0x90, 0x32,
+ 0x00, 0xe2, 0x6a, 0x59,
+ 0xef, 0x96, 0xd5, 0x19,
+ 0x00, 0xe2, 0x2a, 0x52,
+ 0x09, 0x80, 0xe1, 0x30,
+ 0x02, 0xea, 0x36, 0x00,
+ 0xa8, 0xea, 0x32, 0x00,
+ 0x00, 0xe2, 0x30, 0x42,
+ 0x01, 0x96, 0xd1, 0x30,
+ 0x10, 0x80, 0x89, 0x31,
+ 0x20, 0xea, 0x32, 0x00,
+ 0xbf, 0x33, 0x67, 0x0a,
+ 0x20, 0x19, 0x32, 0x6a,
+ 0x02, 0x4d, 0xf8, 0x69,
+ 0x40, 0x33, 0x67, 0x02,
+ 0x00, 0xe2, 0xf8, 0x41,
+ 0x80, 0x33, 0xb5, 0x6a,
+ 0x01, 0x44, 0x10, 0x33,
+ 0x08, 0x92, 0x25, 0x03,
+ 0x00, 0xe2, 0xf8, 0x41,
+ 0x10, 0xea, 0x80, 0x00,
+ 0x01, 0x31, 0xc5, 0x31,
+ 0x80, 0xe2, 0x60, 0x62,
+ 0x10, 0x92, 0x85, 0x6a,
+ 0xc0, 0x94, 0xc5, 0x01,
+ 0x40, 0x92, 0x51, 0x6a,
+ 0xbf, 0xe2, 0xc4, 0x09,
+ 0x20, 0x92, 0x65, 0x7a,
+ 0x01, 0xe2, 0x88, 0x30,
+ 0x00, 0xe2, 0xb8, 0x5b,
+ 0xa0, 0x36, 0x6d, 0x62,
+ 0x23, 0x92, 0x89, 0x08,
+ 0x00, 0xe2, 0xb8, 0x5b,
+ 0xa0, 0x36, 0x6d, 0x62,
+ 0x00, 0xa8, 0x64, 0x42,
+ 0xff, 0xe2, 0x64, 0x62,
+ 0x00, 0xe2, 0x84, 0x42,
+ 0x40, 0xea, 0x98, 0x00,
+ 0x01, 0xe2, 0x88, 0x30,
+ 0x00, 0xe2, 0xb8, 0x5b,
+ 0xa0, 0x36, 0x43, 0x72,
+ 0x40, 0xea, 0x98, 0x00,
+ 0x01, 0x31, 0x89, 0x32,
+ 0x08, 0xea, 0x62, 0x02,
+ 0x00, 0xe2, 0xf8, 0x41,
+ 0xe0, 0xea, 0xd4, 0x5b,
+ 0x80, 0xe0, 0xc0, 0x6a,
+ 0x04, 0xe0, 0x66, 0x73,
+ 0x02, 0xe0, 0x96, 0x73,
+ 0x00, 0xea, 0x1e, 0x73,
+ 0x03, 0xe0, 0xa6, 0x73,
+ 0x23, 0xe0, 0x96, 0x72,
+ 0x08, 0xe0, 0xbc, 0x72,
+ 0x00, 0xe2, 0xb8, 0x5b,
+ 0x07, 0xea, 0x50, 0x59,
+ 0x07, 0xea, 0x04, 0x00,
+ 0x08, 0x42, 0xf9, 0x71,
+ 0x04, 0x42, 0x93, 0x62,
+ 0x01, 0x43, 0x89, 0x30,
+ 0x00, 0xe2, 0x84, 0x42,
+ 0x01, 0x44, 0xd4, 0x31,
+ 0x00, 0xe2, 0x84, 0x42,
+ 0x01, 0x00, 0x60, 0x32,
+ 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x00, 0x00,
+ 0x4c, 0x34, 0xc1, 0x28,
+ 0x01, 0x64, 0xc0, 0x31,
+ 0x00, 0x30, 0x45, 0x59,
+ 0x01, 0x30, 0x01, 0x30,
+ 0x01, 0xe0, 0xba, 0x7a,
+ 0xa0, 0xea, 0xca, 0x5b,
+ 0x01, 0xa0, 0xba, 0x62,
+ 0x01, 0x84, 0xaf, 0x7a,
+ 0x01, 0x95, 0xbd, 0x6a,
+ 0x05, 0xea, 0x50, 0x59,
+ 0x05, 0xea, 0x04, 0x00,
+ 0x00, 0xe2, 0xbc, 0x42,
+ 0x03, 0xea, 0x50, 0x59,
+ 0x03, 0xea, 0x04, 0x00,
+ 0x00, 0xe2, 0xbc, 0x42,
+ 0x07, 0xea, 0xdc, 0x5b,
+ 0x01, 0x44, 0xd4, 0x31,
+ 0x00, 0xe2, 0xf8, 0x41,
+ 0x3f, 0xe0, 0x6a, 0x0a,
+ 0xc0, 0x34, 0xc1, 0x09,
+ 0x00, 0x35, 0x51, 0x01,
+ 0xff, 0xea, 0x52, 0x09,
+ 0x30, 0x34, 0xc5, 0x09,
+ 0x3d, 0xe2, 0xc4, 0x29,
+ 0xb8, 0xe2, 0xc4, 0x19,
+ 0x01, 0xea, 0xc6, 0x01,
+ 0x02, 0xe2, 0xc8, 0x31,
+ 0x02, 0xec, 0x40, 0x31,
+ 0xff, 0xa1, 0xdc, 0x72,
+ 0x02, 0xe8, 0xda, 0x31,
+ 0x02, 0xa0, 0x50, 0x31,
+ 0x00, 0xe2, 0xfe, 0x42,
+ 0x80, 0x33, 0x67, 0x02,
+ 0x01, 0x44, 0xd4, 0x31,
+ 0x00, 0xe2, 0xb8, 0x5b,
+ 0x01, 0x33, 0x67, 0x02,
+ 0xe0, 0x36, 0x19, 0x63,
+ 0x02, 0x33, 0x67, 0x02,
+ 0x20, 0x46, 0x12, 0x63,
+ 0xff, 0xea, 0x52, 0x09,
+ 0xa8, 0xea, 0xca, 0x5b,
+ 0x04, 0x92, 0xf9, 0x7a,
+ 0x01, 0x34, 0xc1, 0x31,
+ 0x00, 0x93, 0xf9, 0x62,
+ 0x01, 0x35, 0xc1, 0x31,
+ 0x00, 0x94, 0x03, 0x73,
+ 0x01, 0xa9, 0x52, 0x11,
+ 0xff, 0xa9, 0xee, 0x6a,
+ 0x00, 0xe2, 0x12, 0x43,
+ 0x10, 0x33, 0x67, 0x02,
+ 0x04, 0x92, 0x13, 0x7b,
+ 0xfb, 0x92, 0x25, 0x0b,
+ 0xff, 0xea, 0x66, 0x0a,
+ 0x01, 0xa4, 0x0d, 0x6b,
+ 0x02, 0xa8, 0x90, 0x32,
+ 0x00, 0xe2, 0x6a, 0x59,
+ 0x10, 0x92, 0xbd, 0x7a,
+ 0xff, 0xea, 0xdc, 0x5b,
+ 0x00, 0xe2, 0xbc, 0x42,
+ 0x04, 0xea, 0x50, 0x59,
+ 0x04, 0xea, 0x04, 0x00,
+ 0x00, 0xe2, 0xbc, 0x42,
+ 0x04, 0xea, 0x50, 0x59,
+ 0x04, 0xea, 0x04, 0x00,
+ 0x00, 0xe2, 0xf8, 0x41,
+ 0x08, 0x92, 0xb5, 0x7a,
+ 0xc0, 0x33, 0x29, 0x7b,
+ 0x80, 0x33, 0xb5, 0x6a,
+ 0xff, 0x88, 0x29, 0x6b,
+ 0x40, 0x33, 0xb5, 0x6a,
+ 0x10, 0x92, 0x2f, 0x7b,
+ 0x0a, 0xea, 0x50, 0x59,
+ 0x0a, 0xea, 0x04, 0x00,
+ 0x00, 0xe2, 0x4e, 0x5b,
+ 0x00, 0xe2, 0x82, 0x43,
+ 0x50, 0x4b, 0x36, 0x6b,
+ 0xbf, 0x3a, 0x74, 0x08,
+ 0x01, 0xe0, 0xf4, 0x31,
+ 0xff, 0xea, 0xc0, 0x09,
+ 0x01, 0x2e, 0x5d, 0x1a,
+ 0x00, 0x2f, 0x5f, 0x22,
+ 0x04, 0x47, 0x8f, 0x02,
+ 0x01, 0xfa, 0xc0, 0x35,
+ 0x02, 0xa8, 0x84, 0x32,
+ 0x02, 0xea, 0xb4, 0x00,
+ 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x00, 0x00,
+ 0x02, 0x42, 0x51, 0x31,
+ 0xff, 0x90, 0x65, 0x68,
+ 0xff, 0x88, 0x5b, 0x6b,
+ 0x01, 0xa4, 0x57, 0x6b,
+ 0x02, 0xa4, 0x5f, 0x6b,
+ 0x01, 0x84, 0x5f, 0x7b,
+ 0x02, 0x28, 0x19, 0x33,
+ 0x02, 0xa8, 0x50, 0x36,
+ 0xff, 0x88, 0x5f, 0x73,
+ 0x00, 0xe2, 0x32, 0x5b,
+ 0x02, 0xa8, 0x20, 0x33,
+ 0x02, 0x2c, 0x19, 0x33,
+ 0x02, 0xa8, 0x58, 0x32,
+ 0x04, 0xa4, 0x49, 0x07,
+ 0xc0, 0x33, 0xb5, 0x6a,
+ 0x04, 0x92, 0x25, 0x03,
+ 0x20, 0x92, 0x83, 0x6b,
+ 0x02, 0xa8, 0x40, 0x31,
+ 0xc0, 0x34, 0xc1, 0x09,
+ 0x00, 0x35, 0x51, 0x01,
+ 0xff, 0xea, 0x52, 0x09,
+ 0x30, 0x34, 0xc5, 0x09,
+ 0x3d, 0xe2, 0xc4, 0x29,
+ 0xb8, 0xe2, 0xc4, 0x19,
+ 0x01, 0xea, 0xc6, 0x01,
+ 0x02, 0xe2, 0xc8, 0x31,
+ 0x02, 0xa0, 0xda, 0x31,
+ 0x02, 0xa0, 0x50, 0x31,
+ 0xf7, 0x57, 0xae, 0x08,
+ 0x08, 0xea, 0x98, 0x00,
+ 0x01, 0x44, 0xd4, 0x31,
+ 0xee, 0x00, 0x8c, 0x6b,
+ 0x02, 0xea, 0xb4, 0x00,
+ 0x00, 0xe2, 0xb4, 0x5b,
+ 0x09, 0x4c, 0x8e, 0x7b,
+ 0x08, 0x4c, 0x06, 0x68,
+ 0x0b, 0xea, 0x50, 0x59,
+ 0x0b, 0xea, 0x04, 0x00,
+ 0x01, 0x44, 0xd4, 0x31,
+ 0x20, 0x33, 0xf9, 0x79,
+ 0x00, 0xe2, 0x9e, 0x5b,
+ 0x00, 0xe2, 0xf8, 0x41,
+ 0x01, 0x84, 0xa3, 0x7b,
+ 0x01, 0xa4, 0x49, 0x07,
+ 0x08, 0x60, 0x30, 0x33,
+ 0x08, 0x80, 0x41, 0x37,
+ 0xdf, 0x33, 0x67, 0x0a,
+ 0xee, 0x00, 0xb0, 0x6b,
+ 0x05, 0xea, 0xb4, 0x00,
+ 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x00, 0x00,
+ 0x00, 0xe2, 0x6a, 0x59,
+ 0x00, 0xe2, 0xbc, 0x42,
+ 0x01, 0xea, 0x6c, 0x02,
+ 0xc0, 0xea, 0x66, 0x06,
+ 0xff, 0x42, 0xc4, 0x6b,
+ 0x01, 0x41, 0xb8, 0x6b,
+ 0x02, 0x41, 0xb8, 0x7b,
+ 0xff, 0x42, 0xc4, 0x6b,
+ 0x01, 0x41, 0xb8, 0x6b,
+ 0x02, 0x41, 0xb8, 0x7b,
+ 0xff, 0x42, 0xc4, 0x7b,
+ 0x04, 0x4c, 0xb8, 0x6b,
+ 0xe0, 0x41, 0x6c, 0x0e,
+ 0x01, 0x44, 0xd4, 0x31,
+ 0xff, 0x42, 0xcc, 0x7b,
+ 0x04, 0x4c, 0xcc, 0x6b,
+ 0xe0, 0x41, 0x6c, 0x0a,
+ 0xe0, 0x36, 0xf9, 0x61,
+ 0xff, 0xea, 0xca, 0x09,
+ 0x01, 0xe2, 0xc8, 0x31,
+ 0x01, 0x46, 0xda, 0x35,
+ 0x01, 0x44, 0xd4, 0x35,
+ 0x10, 0xea, 0x80, 0x00,
+ 0x01, 0xe2, 0x62, 0x36,
+ 0x04, 0xa6, 0xe4, 0x7b,
+ 0xff, 0xea, 0x5a, 0x09,
+ 0xff, 0xea, 0x4c, 0x0d,
+ 0x01, 0xa6, 0x02, 0x6c,
+ 0x10, 0xad, 0x64, 0x78,
+ 0x80, 0xad, 0xfa, 0x6b,
+ 0x08, 0xad, 0x64, 0x68,
+ 0x04, 0x84, 0xf9, 0x30,
+ 0x00, 0xea, 0x08, 0x81,
+ 0xff, 0xea, 0xd4, 0x09,
+ 0x02, 0x84, 0xf9, 0x88,
+ 0x0d, 0xea, 0x5a, 0x01,
+ 0x04, 0xa6, 0x4c, 0x05,
+ 0x04, 0xa6, 0x64, 0x78,
+ 0xff, 0xea, 0x5a, 0x09,
+ 0x03, 0x84, 0x59, 0x89,
+ 0x03, 0xea, 0x4c, 0x01,
+ 0x80, 0x1a, 0x64, 0x78,
+ 0x08, 0x19, 0x64, 0x78,
+ 0x08, 0xb0, 0xe0, 0x30,
+ 0x04, 0xb0, 0xe0, 0x30,
+ 0x03, 0xb0, 0xf0, 0x30,
+ 0x01, 0xb0, 0x06, 0x33,
+ 0x7f, 0x83, 0xe9, 0x08,
+ 0x04, 0xac, 0x58, 0x19,
+ 0xff, 0xea, 0xc0, 0x09,
+ 0x04, 0x84, 0x09, 0x9b,
+ 0x00, 0x85, 0x0b, 0x23,
+ 0x00, 0x86, 0x0d, 0x23,
+ 0x00, 0x87, 0x0f, 0x23,
+ 0x01, 0x84, 0xc5, 0x31,
+ 0x80, 0x83, 0x25, 0x7c,
+ 0x02, 0xe2, 0xc4, 0x01,
+ 0xff, 0xea, 0x4c, 0x09,
+ 0x01, 0xe2, 0x36, 0x30,
+ 0xc8, 0x19, 0x32, 0x00,
+ 0x88, 0x19, 0x32, 0x00,
+ 0x01, 0xac, 0xd4, 0x99,
+ 0x00, 0xe2, 0x64, 0x50,
+ 0xfe, 0xa6, 0x4c, 0x0d,
+ 0x0b, 0x98, 0xe1, 0x30,
+ 0xfd, 0xa4, 0x49, 0x09,
+ 0x80, 0xa3, 0x39, 0x7c,
+ 0x02, 0xa4, 0x48, 0x01,
+ 0x01, 0xa4, 0x36, 0x30,
+ 0xa8, 0xea, 0x32, 0x00,
+ 0xfd, 0xa4, 0x49, 0x0b,
+ 0x05, 0xa3, 0x07, 0x33,
+ 0x80, 0x83, 0x45, 0x6c,
+ 0x02, 0xea, 0x4c, 0x05,
+ 0xff, 0xea, 0x4c, 0x0d,
+ 0x00, 0xe2, 0x3e, 0x59,
+ 0x02, 0xa6, 0xe6, 0x6b,
+ 0x80, 0xf9, 0xf2, 0x05,
+ 0xc0, 0x33, 0x53, 0x7c,
+ 0x03, 0xea, 0x50, 0x59,
+ 0x03, 0xea, 0x04, 0x00,
+ 0x20, 0x33, 0x77, 0x7c,
+ 0x01, 0x84, 0x5d, 0x6c,
+ 0x06, 0xea, 0x50, 0x59,
+ 0x06, 0xea, 0x04, 0x00,
+ 0x00, 0xe2, 0x7a, 0x44,
+ 0x01, 0x00, 0x60, 0x32,
+ 0xee, 0x00, 0x66, 0x6c,
+ 0x05, 0xea, 0xb4, 0x00,
+ 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x00, 0x00,
+ 0x80, 0x3d, 0x7a, 0x00,
+ 0xfc, 0x42, 0x68, 0x7c,
+ 0x7f, 0x3d, 0x7a, 0x08,
+ 0x00, 0x30, 0x45, 0x59,
+ 0x01, 0x30, 0x01, 0x30,
+ 0x09, 0xea, 0x50, 0x59,
+ 0x09, 0xea, 0x04, 0x00,
+ 0x00, 0xe2, 0xf8, 0x41,
+ 0x01, 0xa4, 0x5d, 0x6c,
+ 0x00, 0xe2, 0x30, 0x5c,
+ 0x20, 0x33, 0x67, 0x02,
+ 0x01, 0x00, 0x60, 0x32,
+ 0x02, 0xa6, 0x82, 0x7c,
+ 0x00, 0xe2, 0x46, 0x5c,
+ 0x00, 0xe2, 0x56, 0x58,
+ 0x00, 0xe2, 0x66, 0x58,
+ 0x00, 0xe2, 0x3a, 0x58,
+ 0x00, 0x30, 0x45, 0x59,
+ 0x01, 0x30, 0x01, 0x30,
+ 0x20, 0x19, 0x82, 0x6c,
+ 0x00, 0xe2, 0xb2, 0x5c,
+ 0x04, 0x19, 0x9c, 0x6c,
+ 0x02, 0x19, 0x32, 0x00,
+ 0x01, 0x84, 0x9d, 0x7c,
+ 0x01, 0x1b, 0x96, 0x7c,
+ 0x01, 0x1a, 0x9c, 0x6c,
+ 0x00, 0xe2, 0x4c, 0x44,
+ 0x80, 0x4b, 0xa2, 0x6c,
+ 0x01, 0x4c, 0x9e, 0x7c,
+ 0x03, 0x42, 0x4c, 0x6c,
+ 0x00, 0xe2, 0xe0, 0x5b,
+ 0x80, 0xf9, 0xf2, 0x01,
+ 0x04, 0x33, 0xf9, 0x79,
+ 0x00, 0xe2, 0xf8, 0x41,
+ 0x08, 0x5d, 0xba, 0x6c,
+ 0x00, 0xe2, 0x56, 0x58,
+ 0x00, 0x30, 0x45, 0x59,
+ 0x01, 0x30, 0x01, 0x30,
+ 0x02, 0x1b, 0xaa, 0x7c,
+ 0x08, 0x5d, 0xb8, 0x7c,
+ 0x03, 0x68, 0x00, 0x37,
+ 0x01, 0x84, 0x09, 0x07,
+ 0x80, 0x1b, 0xc4, 0x7c,
+ 0x80, 0x84, 0xc5, 0x6c,
+ 0xff, 0x85, 0x0b, 0x1b,
+ 0xff, 0x86, 0x0d, 0x23,
+ 0xff, 0x87, 0x0f, 0x23,
+ 0xf8, 0x1b, 0x08, 0x0b,
+ 0xff, 0xea, 0x06, 0x0b,
+ 0x03, 0x68, 0x00, 0x37,
+ 0x00, 0xe2, 0xc4, 0x58,
+ 0x10, 0xea, 0x18, 0x00,
+ 0xf9, 0xd9, 0xb2, 0x0d,
+ 0x01, 0xd9, 0xb2, 0x05,
+ 0x01, 0x52, 0x48, 0x31,
+ 0x20, 0xa4, 0xee, 0x7c,
+ 0x20, 0x5b, 0xee, 0x7c,
+ 0x80, 0xf9, 0xfc, 0x7c,
+ 0x02, 0xea, 0xb4, 0x00,
+ 0x11, 0x00, 0x00, 0x10,
+ 0x04, 0x19, 0x08, 0x7d,
+ 0xdf, 0x19, 0x32, 0x08,
+ 0x60, 0x5b, 0xe6, 0x6c,
+ 0x01, 0x4c, 0xe2, 0x7c,
+ 0x20, 0x19, 0x32, 0x00,
+ 0x01, 0xd9, 0xb2, 0x05,
+ 0x02, 0xea, 0xb4, 0x00,
+ 0x01, 0xd9, 0xb2, 0x05,
+ 0x10, 0x5b, 0x00, 0x6d,
+ 0x08, 0x5b, 0x0a, 0x6d,
+ 0x20, 0x5b, 0xfa, 0x6c,
+ 0x02, 0x5b, 0x2a, 0x6d,
+ 0x0e, 0xea, 0x50, 0x59,
+ 0x0e, 0xea, 0x04, 0x00,
+ 0x80, 0xf9, 0xea, 0x6c,
+ 0xdf, 0x5c, 0xb8, 0x08,
+ 0x01, 0xd9, 0xb2, 0x05,
+ 0x01, 0xa4, 0xe5, 0x6d,
+ 0x00, 0xe2, 0x30, 0x5c,
+ 0x00, 0xe2, 0x34, 0x5d,
+ 0x01, 0x90, 0x21, 0x1b,
+ 0x01, 0xd9, 0xb2, 0x05,
+ 0x00, 0xe2, 0x32, 0x5b,
+ 0xf3, 0x96, 0xd5, 0x19,
+ 0x00, 0xe2, 0x18, 0x55,
+ 0x80, 0x96, 0x19, 0x6d,
+ 0x0f, 0xea, 0x50, 0x59,
+ 0x0f, 0xea, 0x04, 0x00,
+ 0x00, 0xe2, 0x20, 0x45,
+ 0x04, 0x8c, 0xe1, 0x30,
+ 0x01, 0xea, 0xf2, 0x00,
+ 0x02, 0xea, 0x36, 0x00,
+ 0xa8, 0xea, 0x32, 0x00,
+ 0xff, 0x97, 0x27, 0x7d,
+ 0x14, 0xea, 0x50, 0x59,
+ 0x14, 0xea, 0x04, 0x00,
+ 0x00, 0xe2, 0x96, 0x5d,
+ 0x01, 0xd9, 0xb2, 0x05,
+ 0x09, 0x80, 0xe1, 0x30,
+ 0x02, 0xea, 0x36, 0x00,
+ 0xa8, 0xea, 0x32, 0x00,
+ 0x00, 0xe2, 0x8e, 0x5d,
+ 0x01, 0xd9, 0xb2, 0x05,
+ 0x02, 0xa6, 0x44, 0x7d,
+ 0x00, 0xe2, 0x3e, 0x59,
+ 0x20, 0x5b, 0x52, 0x6d,
+ 0xfc, 0x42, 0x3e, 0x7d,
+ 0x10, 0x40, 0x40, 0x6d,
+ 0x20, 0x4d, 0x42, 0x7d,
+ 0x08, 0x5d, 0x52, 0x6d,
+ 0x02, 0xa6, 0xe6, 0x6b,
+ 0x00, 0xe2, 0x3e, 0x59,
+ 0x20, 0x5b, 0x52, 0x6d,
+ 0x01, 0x1b, 0x72, 0x6d,
+ 0xfc, 0x42, 0x4e, 0x7d,
+ 0x10, 0x40, 0x50, 0x6d,
+ 0x20, 0x4d, 0x64, 0x78,
+ 0x08, 0x5d, 0x64, 0x78,
+ 0x02, 0x19, 0x32, 0x00,
+ 0x01, 0x5b, 0x40, 0x31,
+ 0x00, 0xe2, 0xb2, 0x5c,
+ 0x00, 0xe2, 0x9e, 0x5b,
+ 0x20, 0xea, 0xb6, 0x00,
+ 0x00, 0xe2, 0xe0, 0x5b,
+ 0x20, 0x5c, 0xb8, 0x00,
+ 0x04, 0x19, 0x68, 0x6d,
+ 0x01, 0x1a, 0x68, 0x6d,
+ 0x00, 0xe2, 0x3e, 0x59,
+ 0x01, 0x1a, 0x64, 0x78,
+ 0x80, 0xf9, 0xf2, 0x01,
+ 0x20, 0xa0, 0xcc, 0x7d,
+ 0xff, 0x90, 0x21, 0x1b,
+ 0x08, 0x92, 0x43, 0x6b,
+ 0x02, 0xea, 0xb4, 0x04,
+ 0x01, 0xa4, 0x49, 0x03,
+ 0x40, 0x5b, 0x82, 0x6d,
+ 0x00, 0xe2, 0x3e, 0x59,
+ 0x40, 0x5b, 0x82, 0x6d,
+ 0x04, 0x5d, 0xe6, 0x7d,
+ 0x01, 0x1a, 0xe6, 0x7d,
+ 0x20, 0x4d, 0x64, 0x78,
+ 0x40, 0x5b, 0xcc, 0x7d,
+ 0x04, 0x5d, 0xe6, 0x7d,
+ 0x01, 0x1a, 0xe6, 0x7d,
+ 0x80, 0xf9, 0xf2, 0x01,
+ 0xff, 0x90, 0x21, 0x1b,
+ 0x08, 0x92, 0x43, 0x6b,
+ 0x02, 0xea, 0xb4, 0x04,
+ 0x00, 0xe2, 0x3e, 0x59,
+ 0x01, 0x1b, 0x64, 0x78,
+ 0x80, 0xf9, 0xf2, 0x01,
+ 0x02, 0xea, 0xb4, 0x04,
+ 0x00, 0xe2, 0x3e, 0x59,
+ 0x01, 0x1b, 0xaa, 0x6d,
+ 0x40, 0x5b, 0xb8, 0x7d,
+ 0x01, 0x1b, 0xaa, 0x6d,
+ 0x02, 0x19, 0x32, 0x00,
+ 0x01, 0x1a, 0x64, 0x78,
+ 0x80, 0xf9, 0xf2, 0x01,
+ 0xff, 0xea, 0x10, 0x03,
+ 0x08, 0x92, 0x25, 0x03,
+ 0x00, 0xe2, 0x42, 0x43,
+ 0x01, 0x1a, 0xb4, 0x7d,
+ 0x40, 0x5b, 0xb0, 0x7d,
+ 0x01, 0x1a, 0x9e, 0x6d,
+ 0xfc, 0x42, 0x64, 0x78,
+ 0x01, 0x1a, 0xb8, 0x6d,
+ 0x10, 0xea, 0x50, 0x59,
+ 0x10, 0xea, 0x04, 0x00,
+ 0xfc, 0x42, 0x64, 0x78,
+ 0x10, 0x40, 0xbe, 0x6d,
+ 0x20, 0x4d, 0x64, 0x78,
+ 0x40, 0x5b, 0x9e, 0x6d,
+ 0x01, 0x1a, 0x64, 0x78,
+ 0x01, 0x90, 0x21, 0x1b,
+ 0x30, 0x3f, 0xc0, 0x09,
+ 0x30, 0xe0, 0x64, 0x60,
+ 0x40, 0x4b, 0x64, 0x68,
+ 0xff, 0xea, 0x52, 0x01,
+ 0xee, 0x00, 0xd4, 0x6d,
+ 0x80, 0xf9, 0xf2, 0x01,
+ 0xff, 0x90, 0x21, 0x1b,
+ 0x02, 0xea, 0xb4, 0x00,
+ 0x20, 0xea, 0x9a, 0x00,
+ 0xf3, 0x42, 0xde, 0x6d,
+ 0x12, 0xea, 0x50, 0x59,
+ 0x12, 0xea, 0x04, 0x00,
+ 0x00, 0xe2, 0xf8, 0x41,
+ 0x0d, 0xea, 0x50, 0x59,
+ 0x0d, 0xea, 0x04, 0x00,
+ 0x00, 0xe2, 0xf8, 0x41,
+ 0x01, 0x90, 0x21, 0x1b,
+ 0x11, 0xea, 0x50, 0x59,
+ 0x11, 0xea, 0x04, 0x00,
+ 0x00, 0xe2, 0x32, 0x5b,
+ 0x08, 0x5a, 0xb4, 0x00,
+ 0x00, 0xe2, 0x0c, 0x5e,
+ 0xa8, 0xea, 0x32, 0x00,
+ 0x00, 0xe2, 0x3e, 0x59,
+ 0x80, 0x1a, 0xfa, 0x7d,
+ 0x00, 0xe2, 0x0c, 0x5e,
+ 0x80, 0x19, 0x32, 0x00,
+ 0x40, 0x5b, 0x00, 0x6e,
+ 0x08, 0x5a, 0x00, 0x7e,
+ 0x20, 0x4d, 0x64, 0x78,
+ 0x02, 0x84, 0x09, 0x03,
+ 0x40, 0x5b, 0xcc, 0x7d,
+ 0xff, 0x90, 0x21, 0x1b,
+ 0x80, 0xf9, 0xf2, 0x01,
+ 0x08, 0x92, 0x43, 0x6b,
+ 0x02, 0xea, 0xb4, 0x04,
+ 0x01, 0x38, 0xe1, 0x30,
+ 0x05, 0x39, 0xe3, 0x98,
+ 0x01, 0xe0, 0xf4, 0x31,
+ 0xff, 0xea, 0xc0, 0x09,
+ 0x00, 0x3a, 0xe5, 0x20,
+ 0x00, 0x3b, 0xe7, 0x20,
+ 0x01, 0xfa, 0xc0, 0x31,
+ 0x04, 0xea, 0xe8, 0x30,
+ 0xff, 0xea, 0xf0, 0x08,
+ 0x02, 0xea, 0xf2, 0x00,
+ 0xff, 0xea, 0xf4, 0x0c
+};
+
+typedef int ahd_patch_func_t (struct ahd_softc *ahd);
+static ahd_patch_func_t ahd_patch22_func;
+
+static int
+ahd_patch22_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0);
+}
+
+static ahd_patch_func_t ahd_patch21_func;
+
+static int
+ahd_patch21_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0);
+}
+
+static ahd_patch_func_t ahd_patch20_func;
+
+static int
+ahd_patch20_func(struct ahd_softc *ahd)
+{
+ return ((ahd->features & AHD_RTI) == 0);
+}
+
+static ahd_patch_func_t ahd_patch19_func;
+
+static int
+ahd_patch19_func(struct ahd_softc *ahd)
+{
+ return ((ahd->flags & AHD_INITIATORROLE) != 0);
+}
+
+static ahd_patch_func_t ahd_patch18_func;
+
+static int
+ahd_patch18_func(struct ahd_softc *ahd)
+{
+ return ((ahd->flags & AHD_TARGETROLE) != 0);
+}
+
+static ahd_patch_func_t ahd_patch17_func;
+
+static int
+ahd_patch17_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0);
+}
+
+static ahd_patch_func_t ahd_patch16_func;
+
+static int
+ahd_patch16_func(struct ahd_softc *ahd)
+{
+ return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0);
+}
+
+static ahd_patch_func_t ahd_patch15_func;
+
+static int
+ahd_patch15_func(struct ahd_softc *ahd)
+{
+ return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0);
+}
+
+static ahd_patch_func_t ahd_patch14_func;
+
+static int
+ahd_patch14_func(struct ahd_softc *ahd)
+{
+ return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0);
+}
+
+static ahd_patch_func_t ahd_patch13_func;
+
+static int
+ahd_patch13_func(struct ahd_softc *ahd)
+{
+ return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0);
+}
+
+static ahd_patch_func_t ahd_patch12_func;
+
+static int
+ahd_patch12_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0);
+}
+
+static ahd_patch_func_t ahd_patch11_func;
+
+static int
+ahd_patch11_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0);
+}
+
+static ahd_patch_func_t ahd_patch10_func;
+
+static int
+ahd_patch10_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0);
+}
+
+static ahd_patch_func_t ahd_patch9_func;
+
+static int
+ahd_patch9_func(struct ahd_softc *ahd)
+{
+ return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0);
+}
+
+static ahd_patch_func_t ahd_patch8_func;
+
+static int
+ahd_patch8_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_LQO_ATNO_BUG) != 0);
+}
+
+static ahd_patch_func_t ahd_patch7_func;
+
+static int
+ahd_patch7_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0);
+}
+
+static ahd_patch_func_t ahd_patch6_func;
+
+static int
+ahd_patch6_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_NONPACKFIFO_BUG) != 0);
+}
+
+static ahd_patch_func_t ahd_patch5_func;
+
+static int
+ahd_patch5_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0);
+}
+
+static ahd_patch_func_t ahd_patch4_func;
+
+static int
+ahd_patch4_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_PKT_LUN_BUG) != 0);
+}
+
+static ahd_patch_func_t ahd_patch3_func;
+
+static int
+ahd_patch3_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_FAINT_LED_BUG) != 0);
+}
+
+static ahd_patch_func_t ahd_patch2_func;
+
+static int
+ahd_patch2_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_SET_MODE_BUG) != 0);
+}
+
+static ahd_patch_func_t ahd_patch1_func;
+
+static int
+ahd_patch1_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0);
+}
+
+static ahd_patch_func_t ahd_patch0_func;
+
+static int
+ahd_patch0_func(struct ahd_softc *ahd)
+{
+ return (0);
+}
+
+static struct patch {
+ ahd_patch_func_t *patch_func;
+ uint32_t begin :10,
+ skip_instr :10,
+ skip_patch :12;
+} patches[] = {
+ { ahd_patch1_func, 0, 3, 3 },
+ { ahd_patch1_func, 1, 1, 2 },
+ { ahd_patch0_func, 2, 1, 1 },
+ { ahd_patch1_func, 3, 3, 3 },
+ { ahd_patch1_func, 4, 1, 2 },
+ { ahd_patch0_func, 5, 1, 1 },
+ { ahd_patch2_func, 6, 1, 2 },
+ { ahd_patch0_func, 7, 1, 1 },
+ { ahd_patch3_func, 20, 5, 1 },
+ { ahd_patch2_func, 29, 1, 2 },
+ { ahd_patch0_func, 30, 1, 1 },
+ { ahd_patch1_func, 37, 1, 2 },
+ { ahd_patch0_func, 38, 1, 1 },
+ { ahd_patch2_func, 43, 1, 2 },
+ { ahd_patch0_func, 44, 1, 1 },
+ { ahd_patch2_func, 47, 1, 2 },
+ { ahd_patch0_func, 48, 1, 1 },
+ { ahd_patch2_func, 51, 1, 2 },
+ { ahd_patch0_func, 52, 1, 1 },
+ { ahd_patch2_func, 65, 1, 2 },
+ { ahd_patch0_func, 66, 1, 1 },
+ { ahd_patch2_func, 69, 1, 2 },
+ { ahd_patch0_func, 70, 1, 1 },
+ { ahd_patch1_func, 73, 1, 2 },
+ { ahd_patch0_func, 74, 1, 1 },
+ { ahd_patch4_func, 107, 1, 1 },
+ { ahd_patch2_func, 162, 6, 1 },
+ { ahd_patch1_func, 168, 2, 1 },
+ { ahd_patch5_func, 170, 1, 1 },
+ { ahd_patch2_func, 179, 1, 2 },
+ { ahd_patch0_func, 180, 1, 1 },
+ { ahd_patch6_func, 181, 2, 2 },
+ { ahd_patch0_func, 183, 6, 3 },
+ { ahd_patch2_func, 186, 1, 2 },
+ { ahd_patch0_func, 187, 1, 1 },
+ { ahd_patch2_func, 190, 1, 2 },
+ { ahd_patch0_func, 191, 1, 1 },
+ { ahd_patch7_func, 193, 2, 1 },
+ { ahd_patch5_func, 201, 16, 2 },
+ { ahd_patch0_func, 217, 1, 1 },
+ { ahd_patch8_func, 237, 2, 1 },
+ { ahd_patch1_func, 241, 1, 2 },
+ { ahd_patch0_func, 242, 1, 1 },
+ { ahd_patch7_func, 245, 2, 1 },
+ { ahd_patch1_func, 259, 1, 2 },
+ { ahd_patch0_func, 260, 1, 1 },
+ { ahd_patch1_func, 263, 1, 2 },
+ { ahd_patch0_func, 264, 1, 1 },
+ { ahd_patch2_func, 267, 1, 2 },
+ { ahd_patch0_func, 268, 1, 1 },
+ { ahd_patch1_func, 323, 1, 2 },
+ { ahd_patch0_func, 324, 1, 1 },
+ { ahd_patch2_func, 332, 1, 2 },
+ { ahd_patch0_func, 333, 1, 1 },
+ { ahd_patch2_func, 336, 1, 2 },
+ { ahd_patch0_func, 337, 1, 1 },
+ { ahd_patch1_func, 343, 1, 2 },
+ { ahd_patch0_func, 344, 1, 1 },
+ { ahd_patch1_func, 346, 1, 2 },
+ { ahd_patch0_func, 347, 1, 1 },
+ { ahd_patch9_func, 366, 1, 1 },
+ { ahd_patch9_func, 369, 1, 1 },
+ { ahd_patch9_func, 371, 1, 1 },
+ { ahd_patch9_func, 383, 1, 1 },
+ { ahd_patch1_func, 393, 1, 2 },
+ { ahd_patch0_func, 394, 1, 1 },
+ { ahd_patch1_func, 396, 1, 2 },
+ { ahd_patch0_func, 397, 1, 1 },
+ { ahd_patch1_func, 405, 1, 2 },
+ { ahd_patch0_func, 406, 1, 1 },
+ { ahd_patch2_func, 419, 1, 2 },
+ { ahd_patch0_func, 420, 1, 1 },
+ { ahd_patch10_func, 450, 1, 1 },
+ { ahd_patch1_func, 457, 1, 2 },
+ { ahd_patch0_func, 458, 1, 1 },
+ { ahd_patch2_func, 470, 1, 2 },
+ { ahd_patch0_func, 471, 1, 1 },
+ { ahd_patch11_func, 476, 6, 2 },
+ { ahd_patch0_func, 482, 1, 1 },
+ { ahd_patch12_func, 505, 1, 1 },
+ { ahd_patch13_func, 514, 1, 1 },
+ { ahd_patch14_func, 515, 1, 2 },
+ { ahd_patch0_func, 516, 1, 1 },
+ { ahd_patch15_func, 519, 1, 1 },
+ { ahd_patch14_func, 520, 1, 1 },
+ { ahd_patch16_func, 531, 1, 2 },
+ { ahd_patch0_func, 532, 1, 1 },
+ { ahd_patch1_func, 551, 1, 2 },
+ { ahd_patch0_func, 552, 1, 1 },
+ { ahd_patch1_func, 555, 1, 2 },
+ { ahd_patch0_func, 556, 1, 1 },
+ { ahd_patch2_func, 561, 1, 2 },
+ { ahd_patch0_func, 562, 1, 1 },
+ { ahd_patch2_func, 566, 1, 2 },
+ { ahd_patch0_func, 567, 1, 1 },
+ { ahd_patch1_func, 568, 1, 2 },
+ { ahd_patch0_func, 569, 1, 1 },
+ { ahd_patch2_func, 580, 1, 2 },
+ { ahd_patch0_func, 581, 1, 1 },
+ { ahd_patch17_func, 585, 1, 1 },
+ { ahd_patch18_func, 590, 1, 1 },
+ { ahd_patch19_func, 591, 2, 1 },
+ { ahd_patch18_func, 595, 1, 2 },
+ { ahd_patch0_func, 596, 1, 1 },
+ { ahd_patch2_func, 599, 1, 2 },
+ { ahd_patch0_func, 600, 1, 1 },
+ { ahd_patch2_func, 615, 1, 2 },
+ { ahd_patch0_func, 616, 1, 1 },
+ { ahd_patch20_func, 617, 14, 1 },
+ { ahd_patch1_func, 635, 1, 2 },
+ { ahd_patch0_func, 636, 1, 1 },
+ { ahd_patch20_func, 637, 1, 1 },
+ { ahd_patch1_func, 649, 1, 2 },
+ { ahd_patch0_func, 650, 1, 1 },
+ { ahd_patch1_func, 657, 1, 2 },
+ { ahd_patch0_func, 658, 1, 1 },
+ { ahd_patch17_func, 681, 1, 1 },
+ { ahd_patch17_func, 719, 1, 1 },
+ { ahd_patch1_func, 730, 1, 2 },
+ { ahd_patch0_func, 731, 1, 1 },
+ { ahd_patch1_func, 748, 1, 2 },
+ { ahd_patch0_func, 749, 1, 1 },
+ { ahd_patch1_func, 751, 1, 2 },
+ { ahd_patch0_func, 752, 1, 1 },
+ { ahd_patch1_func, 755, 1, 2 },
+ { ahd_patch0_func, 756, 1, 1 },
+ { ahd_patch21_func, 758, 1, 2 },
+ { ahd_patch0_func, 759, 2, 1 },
+ { ahd_patch22_func, 762, 4, 2 },
+ { ahd_patch0_func, 766, 1, 1 },
+ { ahd_patch22_func, 774, 11, 1 }
+};
+
+static struct cs {
+ uint16_t begin;
+ uint16_t end;
+} critical_sections[] = {
+ { 11, 12 },
+ { 13, 14 },
+ { 29, 42 },
+ { 56, 59 },
+ { 101, 128 },
+ { 129, 157 },
+ { 159, 162 },
+ { 170, 178 },
+ { 201, 250 },
+ { 681, 697 },
+ { 697, 711 },
+ { 721, 725 }
+};
+
+static const int num_critical_sections = sizeof(critical_sections)
+ / sizeof(*critical_sections);
diff --git a/sys/dev/microcode/aic7xxx/aic7xxx.reg b/sys/dev/microcode/aic7xxx/aic7xxx.reg
index 481cb99aca0..65007a9ae77 100644
--- a/sys/dev/microcode/aic7xxx/aic7xxx.reg
+++ b/sys/dev/microcode/aic7xxx/aic7xxx.reg
@@ -1,8 +1,9 @@
-/* $OpenBSD: aic7xxx.reg,v 1.6 2002/06/30 18:25:58 smurph Exp $ */
+/* $OpenBSD: aic7xxx.reg,v 1.7 2003/12/24 22:40:16 krw Exp $ */
/*
* Aic7xxx register and scratch ram definitions.
*
- * Copyright (c) 1994-2001 Justin Gibbs.
+ * 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
@@ -11,28 +12,35 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
- * 2. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * 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 Public License ("GPL").
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
*
- * 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
+ * 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 DAMAGE.
+ * 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: src/sys/dev/aic7xxx/aic7xxx.reg,v 1.39 2001/07/18 21:39:47 gibbs Exp $
+ * $FreeBSD: /repoman/r/ncvs/src/sys/dev/aic7xxx/aic7xxx.reg,v 1.43 2003/01/20 20:44:55 gibbs Exp $
*/
-
-VERSION = "$Id: aic7xxx.reg,v 1.6 2002/06/30 18:25:58 smurph Exp $"
+VERSION = "$NetBSD: aic7xxx.reg,v 1.2 2003/04/19 19:26:10 fvdl Exp $"
/*
* This file is processed by the aic7xxx_asm utility for use in assembling
@@ -50,14 +58,14 @@ VERSION = "$Id: aic7xxx.reg,v 1.6 2002/06/30 18:25:58 smurph Exp $"
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
+ field TEMODE 0x80
+ field ENSELO 0x40
+ field ENSELI 0x20
+ field ENRSELI 0x10
+ field ENAUTOATNO 0x08
+ field ENAUTOATNI 0x04
+ field ENAUTOATNP 0x02
+ field SCSIRSTO 0x01
}
/*
@@ -67,13 +75,13 @@ register SCSISEQ {
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
+ field DFON 0x80
+ field DFPEXP 0x40
+ field FAST20 0x20
+ field CLRSTCNT 0x10
+ field SPIOEN 0x08
+ field SCAMEN 0x04
+ field CLRCHN 0x02
}
/*
@@ -83,13 +91,13 @@ register SXFRCTL0 {
register SXFRCTL1 {
address 0x002
access_mode RW
- bit BITBUCKET 0x80
- bit SWRAPEN 0x40
- bit ENSPCHK 0x20
+ field BITBUCKET 0x80
+ field SWRAPEN 0x40
+ field ENSPCHK 0x20
mask STIMESEL 0x18
- bit ENSTIMER 0x04
- bit ACTNEGEN 0x02
- bit STPWEN 0x01 /* Powered Termination */
+ field ENSTIMER 0x04
+ field ACTNEGEN 0x02
+ field STPWEN 0x01 /* Powered Termination */
}
/*
@@ -99,22 +107,22 @@ register SXFRCTL1 {
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
+ 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_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
@@ -130,14 +138,14 @@ register SCSISIGI {
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
+ 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
*/
@@ -160,9 +168,9 @@ register SCSISIGO {
register SCSIRATE {
address 0x004
access_mode RW
- bit WIDEXFER 0x80 /* Wide transfer control */
- bit ENABLE_CRC 0x40 /* CRC for D-Phases */
- bit SINGLE_EDGE 0x10 /* Disable DT Transfers */
+ 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 */
@@ -177,8 +185,8 @@ register SCSIID {
address 0x005
access_mode RW
mask TID 0xf0 /* Target ID mask */
- mask TWIN_TID 0x70
- bit TWIN_CHNLB 0x80
+ mask TWIN_TID 0x70
+ field TWIN_CHNLB 0x80
mask OID 0x0f /* Our ID mask */
/*
* SCSI Maximum Offset (p. 4-61 aic7890/91 Data Book)
@@ -218,18 +226,27 @@ register STCNT {
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
- 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
+ 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
}
@@ -247,12 +264,12 @@ register TARGCRCCNT {
register CLRSINT0 {
address 0x00b
access_mode WO
- bit CLRSELDO 0x40
- bit CLRSELDI 0x20
- bit CLRSELINGO 0x10
- bit CLRSWRAP 0x08
- bit CLRIOERR 0x08 /* Ultra2 Only */
- bit CLRSPIORDY 0x02
+ field CLRSELDO 0x40
+ field CLRSELDI 0x20
+ field CLRSELINGO 0x10
+ field CLRSWRAP 0x08
+ field CLRIOERR 0x08 /* Ultra2 Only */
+ field CLRSPIORDY 0x02
}
/*
@@ -263,15 +280,15 @@ register CLRSINT0 {
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 */
+ 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 Tranceiver mode changed */
+ field SDONE 0x04 /* STCNT = 0x000000 */
+ field SPIORDY 0x02 /* SCSI PIO Ready */
+ field DMADONE 0x01 /* DMA transfer completed */
}
/*
@@ -281,13 +298,13 @@ register SSTAT0 {
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
+ field CLRSELTIMEO 0x80
+ field CLRATNO 0x40
+ field CLRSCSIRSTI 0x20
+ field CLRBUSFREE 0x08
+ field CLRSCSIPERR 0x04
+ field CLRPHASECHG 0x02
+ field CLRREQINIT 0x01
}
/*
@@ -296,14 +313,14 @@ register CLRSINT1 {
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
+ field SELTO 0x80
+ field ATNTARG 0x40
+ field SCSIRSTI 0x20
+ field PHASEMIS 0x10
+ field BUSFREE 0x08
+ field SCSIPERR 0x04
+ field PHASECHG 0x02
+ field REQINIT 0x01
}
/*
@@ -312,13 +329,13 @@ register SSTAT1 {
register SSTAT2 {
address 0x00d
access_mode RO
- bit OVERRUN 0x80
- bit SHVALID 0x40 /* Shaddow Layer non-zero */
- bit EXP_ACTIVE 0x10 /* SCSI Expander Active */
- bit CRCVALERR 0x08 /* CRC doesn't match (U3 only) */
- bit CRCENDERR 0x04 /* No terminal CRC packet (U3 only) */
- bit CRCREQERR 0x02 /* Illegal CRC packet req (U3 only) */
- bit DUAL_EDGE_ERR 0x01 /* Incorrect data phase (U3 only) */
+ field OVERRUN 0x80
+ field SHVALID 0x40 /* Shaddow 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
}
@@ -330,6 +347,7 @@ register SSTAT3 {
access_mode RO
mask SCSICNT 0xf0
mask OFFCNT 0x0f
+ mask U2OFFCNT 0x7f
}
/*
@@ -350,14 +368,14 @@ register SCSIID_ULTRA2 {
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
+ field ENSELDO 0x40
+ field ENSELDI 0x20
+ field ENSELINGO 0x10
+ field ENSWRAP 0x08
+ field ENIOERR 0x08 /* LVD Tranceiver mode changes */
+ field ENSDONE 0x04
+ field ENSPIORDY 0x02
+ field ENDMADONE 0x01
}
/*
@@ -368,14 +386,14 @@ register SIMODE0 {
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
+ field ENSELTIMO 0x80
+ field ENATNTARG 0x40
+ field ENSCSIRST 0x20
+ field ENPHASEMIS 0x10
+ field ENBUSFREE 0x08
+ field ENSCSIPERR 0x04
+ field ENPHASECHG 0x02
+ field ENREQINIT 0x01
}
/*
@@ -384,12 +402,12 @@ register SIMODE1 {
*/
register SCSIBUSL {
address 0x012
- access_mode RW
+ access_mode RW
}
register SCSIBUSH {
address 0x013
- access_mode RW
+ access_mode RW
}
/*
@@ -412,12 +430,12 @@ register SHADDR {
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
+ field STAGE6 0x20
+ field STAGE5 0x10
+ field STAGE4 0x08
+ field STAGE3 0x04
+ field STAGE2 0x02
+ field STAGE1 0x01
alias TARGIDIN
}
@@ -430,16 +448,16 @@ register SELID {
address 0x019
access_mode RW
mask SELID_MASK 0xf0
- bit ONEBIT 0x08
+ field ONEBIT 0x08
}
register SCAMCTL {
address 0x01a
access_mode RW
- bit ENSCAMSELO 0x80
- bit CLRSCAMSELID 0x40
- bit ALTSTIM 0x20
- bit DFLTTID 0x10
+ field ENSCAMSELO 0x80
+ field CLRSCAMSELID 0x40
+ field ALTSTIM 0x20
+ field DFLTTID 0x10
mask SCAMLVL 0x03
}
@@ -463,32 +481,32 @@ register TARGID {
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 */
+ 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
- bit BRDDAT7 0x80
- bit BRDDAT6 0x40
- bit BRDDAT5 0x20
- bit BRDSTB 0x10
- bit BRDCS 0x08
- bit BRDRW 0x04
- bit BRDCTL1 0x02
- bit BRDCTL0 0x01
+ 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 */
- bit BRDDAT4 0x10
- bit BRDDAT3 0x08
- bit BRDDAT2 0x04
- bit BRDRW_ULTRA2 0x02
- bit BRDSTB_ULTRA2 0x01
+ field BRDDAT4 0x10
+ field BRDDAT3 0x08
+ field BRDDAT2 0x04
+ field BRDRW_ULTRA2 0x02
+ field BRDSTB_ULTRA2 0x01
}
/*
@@ -517,14 +535,14 @@ register BRDCTL {
*/
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
+ 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)
@@ -536,14 +554,14 @@ register SEECTL {
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 */
+ 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 */
}
/*
@@ -553,14 +571,14 @@ register SBLKCTL {
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
+ field PERRORDIS 0x80
+ field PAUSEDIS 0x40
+ field FAILDIS 0x20
+ field FASTMODE 0x10
+ field BRKADRINTEN 0x08
+ field STEP 0x04
+ field SEQRESET 0x02
+ field LOADRAM 0x01
}
/*
@@ -632,8 +650,8 @@ register NONE {
register FLAGS {
address 0x06b
access_mode RO
- bit ZERO 0x02
- bit CARRY 0x01
+ field ZERO 0x02
+ field CARRY 0x01
}
register SINDIR {
@@ -656,14 +674,16 @@ register STACK {
access_mode RO
}
+const STACK_SIZE 4
+
/*
* Board Control (p. 3-43)
*/
register BCTL {
address 0x084
access_mode RW
- bit ACE 0x08
- bit ENABLE 0x01
+ field ACE 0x08
+ field ENABLE 0x01
}
/*
@@ -673,23 +693,23 @@ register BCTL {
register DSCOMMAND0 {
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 */
+ 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 */
- bit INTSCBRAMSEL 0x08 /* Internal SCB RAM Select */
- bit RAMPS 0x04 /* External SCB RAM Present */
- bit USCBSIZE32 0x02 /* Use 32byte SCB Page Size */
- bit CIOPARCKEN 0x01 /* Internal bus parity error enable */
+ 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) */
- bit HADDLDSEL1 0x02 /* Host Address Load Select Bits */
- bit HADDLDSEL0 0x01
+ address 0x085
+ access_mode RW
+ mask DSLATT 0xfc /* PCI latency timer (non-ultra2) */
+ field HADDLDSEL1 0x02 /* Host Address Load Select Bits */
+ field HADDLDSEL0 0x01
}
/*
@@ -712,7 +732,7 @@ register BUSSPD {
mask STBOFF 0x38
mask STBON 0x07
mask DFTHRSH_100 0xc0
- mask DFTHRSH_75 0x80
+ mask DFTHRSH_75 0x80
}
/* aic7850/55/60/70/80/95 only */
@@ -726,7 +746,6 @@ register HS_MAILBOX {
address 0x086
mask HOST_MAILBOX 0xF0
mask SEQ_MAILBOX 0x0F
- mask HOST_REQ_INT 0x10
mask HOST_TQINPOS 0x80 /* Boundary at either 0 or 128 */
}
@@ -740,13 +759,13 @@ const SEQ_MAILBOX_SHIFT 0
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
+ field POWRDN 0x40
+ field SWINT 0x10
+ field IRQMS 0x08
+ field PAUSE 0x04
+ field INTEN 0x02
+ field CHIPRST 0x01
+ field CHIPRSTACK 0x01
}
/*
@@ -782,23 +801,23 @@ register SCBPTR {
register INTSTAT {
address 0x091
access_mode RW
- bit BRKADRINT 0x08
- bit SCSIINT 0x04
- bit CMDCMPLT 0x02
- bit SEQINT 0x01
+ 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 NO_IDENT 0x20|SEQINT /* no IDENTIFY after reconnect*/
+ 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 /*
+ 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
@@ -807,37 +826,37 @@ register INTSTAT {
* that require a kernel based
* message state engine.
*/
- mask BAD_STATUS 0x70|SEQINT /* Bad status from target */
- mask PERR_DETECTED 0x80|SEQINT /*
+ 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 /*
+ 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 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)
@@ -851,14 +870,14 @@ register INTSTAT {
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 ILLHADDR 0x01
+ 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
}
/*
@@ -867,39 +886,39 @@ register ERROR {
register CLRINT {
address 0x092
access_mode WO
- bit CLRPARERR 0x10 /* PCI only */
- bit CLRBRKADRINT 0x08
- bit CLRSCSIINT 0x04
- bit CLRCMDINT 0x02
- bit CLRSEQINT 0x01
+ field CLRPARERR 0x10 /* PCI only */
+ field CLRBRKADRINT 0x08
+ field CLRSCSIINT 0x04
+ field CLRCMDINT 0x02
+ field 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
+ 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
- bit PRELOAD_AVAIL 0x80
- bit DFCACHETH 0x40
- bit FIFOQWDEMP 0x20
- bit MREQPEND 0x10
- bit HDONE 0x08
- bit DFTHRESH 0x04
- bit FIFOFULL 0x02
- bit FIFOEMP 0x01
+ 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 {
@@ -925,7 +944,7 @@ register DFDAT {
register SCBCNT {
address 0x09a
access_mode RW
- bit SCBAUTO 0x80
+ field SCBAUTO 0x80
mask SCBCNT_MASK 0x1f
}
@@ -959,12 +978,12 @@ register QOUTFIFO {
register CRCCONTROL1 {
address 0x09d
access_mode RW
- bit CRCONSEEN 0x80
- bit CRCVALCHKEN 0x40
- bit CRCENDCHKEN 0x20
- bit CRCREQCHKEN 0x10
- bit TARGCRCENDEN 0x08
- bit TARGCRCCNTEN 0x04
+ field CRCONSEEN 0x80
+ field CRCVALCHKEN 0x40
+ field CRCENDCHKEN 0x20
+ field CRCREQCHKEN 0x10
+ field TARGCRCENDEN 0x08
+ field TARGCRCCNTEN 0x04
}
@@ -980,13 +999,13 @@ register QOUTCNT {
register SCSIPHASE {
address 0x09e
access_mode RO
- bit STATUS_PHASE 0x20
- bit COMMAND_PHASE 0x10
- bit MSG_IN_PHASE 0x08
- bit MSG_OUT_PHASE 0x04
- bit DATA_IN_PHASE 0x02
- bit DATA_OUT_PHASE 0x01
- mask DATA_PHASE_MASK 0x03
+ 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
}
/*
@@ -995,7 +1014,7 @@ register SCSIPHASE {
register SFUNCT {
address 0x09f
access_mode RW
- bit ALT_MODE 0x80
+ field ALT_MODE 0x80
}
/*
@@ -1004,64 +1023,71 @@ register SFUNCT {
scb {
address 0x0a0
size 64
- SCB_CDB_PTR {
- size 4
- alias SCB_RESIDUAL_DATACNT
- alias SCB_CDB_STORE
- alias SCB_TARGET_INFO
+
+ SCB_CDB_PTR {
+ size 4
+ alias SCB_RESIDUAL_DATACNT
+ alias SCB_CDB_STORE
}
- SCB_RESIDUAL_SGPTR {
+ SCB_RESIDUAL_SGPTR {
size 4
}
- SCB_SCSI_STATUS {
+ SCB_SCSI_STATUS {
size 1
}
- SCB_CDB_STORE_PAD {
- size 3
+ 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.
+ * The last byte is really the high address bits for
+ * the data address.
*/
size 4
- bit SG_LAST_SEG 0x80 /* In the fourth byte */
- mask SG_HIGH_ADDR_BITS 0x7F /* In the fourth byte */
+ field SG_LAST_SEG 0x80 /* In the fourth byte */
+ mask SG_HIGH_ADDR_BITS 0x7F /* In the fourth byte */
}
- SCB_SGPTR {
+ SCB_SGPTR {
size 4
- bit SG_RESID_VALID 0x04 /* In the first byte */
- bit SG_FULL_RESID 0x02 /* In the first byte */
- bit SG_LIST_NULL 0x01 /* In the first byte */
- }
- SCB_CONTROL {
- size 1
- bit TARGET_SCB 0x80
- bit DISCENB 0x40
- bit TAG_ENB 0x20
- bit MK_MESSAGE 0x10
- bit ULTRAENB 0x08
- bit DISCONNECTED 0x04
- mask SCB_TAG_TYPE 0x03
+ 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
- bit TWIN_CHNLB 0x80
- mask TWIN_TID 0x70
- mask TID 0xf0
- mask OID 0x0f
- }
- SCB_LUN {
- mask LID 0xff
+ 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 {
+ SCB_CDB_LEN {
size 1
}
SCB_SCSIRATE {
@@ -1070,20 +1096,20 @@ scb {
SCB_SCSIOFFSET {
size 1
}
- SCB_NEXT {
- size 1
+ SCB_NEXT {
+ size 1
}
- SCB_64_SPARE {
+ SCB_64_SPARE {
size 16
}
- SCB_64_BTT {
- size 16
+ SCB_64_BTT {
+ size 16
}
}
-const SCB_UPLOAD_SIZE 32
-const SCB_DOWNLOAD_SIZE 32
-const SCB_DOWNLOAD_SIZE_64 48
+const SCB_UPLOAD_SIZE 32
+const SCB_DOWNLOAD_SIZE 32
+const SCB_DOWNLOAD_SIZE_64 48
const SG_SIZEOF 0x08 /* sizeof(struct ahc_dma) */
@@ -1092,18 +1118,18 @@ const SG_SIZEOF 0x08 /* sizeof(struct ahc_dma) */
register SEECTL_2840 {
address 0x0c0
access_mode RW
- bit CS_2840 0x04
- bit CK_2840 0x02
- bit DO_2840 0x01
+ field CS_2840 0x04
+ field CK_2840 0x02
+ field DO_2840 0x01
}
register STATUS_2840 {
address 0x0c1
access_mode RW
- bit EEPROM_TF 0x80
+ field EEPROM_TF 0x80
mask BIOS_SEL 0x60
mask ADSEL 0x1e
- bit DI_2840 0x01
+ field DI_2840 0x01
}
/* --------------------- AIC-7870-only definitions -------------------- */
@@ -1127,10 +1153,10 @@ register CCSGADDR {
register CCSGCTL {
address 0x0EB
- bit CCSGDONE 0x80
- bit CCSGEN 0x08
- bit SG_FETCH_NEEDED 0x02 /* Bit used for software state */
- bit CCSGRESET 0x01
+ field CCSGDONE 0x80
+ field CCSGEN 0x08
+ field SG_FETCH_NEEDED 0x02 /* Bit used for software state */
+ field CCSGRESET 0x01
}
register CCSCBCNT {
@@ -1139,12 +1165,12 @@ register CCSCBCNT {
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
+ field CCSCBDONE 0x80
+ field ARRDONE 0x40 /* SCB Array prefetch done */
+ field CCARREN 0x10
+ field CCSCBEN 0x08
+ field CCSCBDIR 0x04
+ field CCSCBRESET 0x01
}
register CCSCBADDR {
@@ -1181,9 +1207,9 @@ register SDSCB_QOFF {
register QOFF_CTLSTA {
address 0x0FA
- bit SCB_AVAIL 0x40
- bit SNSCB_ROLLOVER 0x20
- bit SDSCB_ROLLOVER 0x10
+ field SCB_AVAIL 0x40
+ field SNSCB_ROLLOVER 0x20
+ field SDSCB_ROLLOVER 0x10
mask SCB_QSIZE 0x07
mask SCB_QSIZE_256 0x06
}
@@ -1211,21 +1237,21 @@ register DFF_THRSH {
}
register SG_CACHE_PRE {
- access_mode WO
+ access_mode WO
address 0x0fc
- mask SG_ADDR_MASK 0xf8
- bit ODD_SEG 0x04
- bit LAST_SEG 0x02
- bit LAST_SEG_DONE 0x01
+ 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
- bit ODD_SEG 0x04
- bit LAST_SEG 0x02
- bit LAST_SEG_DONE 0x01
+ 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
@@ -1249,45 +1275,46 @@ scratch_ram {
/*
* 1 byte per target starting at this address for configuration values
*/
- BUSY_TARGETS {
- alias TARG_SCSIRATE
+ 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.
+ * 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
+ 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.
+ * 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
- }
- /*
- * SCBID of the next SCB to be started by the controller.
- */
- NEXT_QUEUED_SCB {
- size 1
+ }
+ 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
@@ -1299,38 +1326,39 @@ scratch_ram {
/* 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 /* Set indicates PCI->SCSI */
- bit FIFOFLUSH 0x02
- bit FIFORESET 0x01
+ 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
- bit IDENTIFY_SEEN 0x80
- bit TARGET_CMD_IS_TAGGED 0x40
- bit DPHASE 0x20
+ field NOT_IDENTIFIED 0x80
+ field NO_CDB_SENT 0x40
+ field TARGET_CMD_IS_TAGGED 0x40
+ field DPHASE 0x20
/* Target flags */
- bit TARG_CMD_PENDING 0x10
- bit CMDPHASE_PENDING 0x08
- bit DPHASE_PENDING 0x04
- bit SPHASE_PENDING 0x02
- bit NO_DISCONNECT 0x01
+ 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 {
+ SAVED_SCSIID {
size 1
}
- SAVED_LUN {
+ SAVED_LUN {
size 1
}
/*
@@ -1338,9 +1366,9 @@ scratch_ram {
*/
LASTPHASE {
size 1
- bit CDI 0x80
- bit IOI 0x40
- bit MSGI 0x20
+ field CDI 0x80
+ field IOI 0x40
+ field MSGI 0x20
mask PHASE_MASK CDI|IOI|MSGI
mask P_DATAOUT 0x00
mask P_DATAIN IOI
@@ -1373,25 +1401,25 @@ scratch_ram {
size 1
}
/*
- * head of list of SCBs that have
- * completed but have not been
- * put into the qoutfifo.
+ * head of list of SCBs that have
+ * completed but have not been
+ * put into the qoutfifo.
*/
- COMPLETE_SCBH {
- size 1
+ COMPLETE_SCBH {
+ size 1
}
/*
- * Address of the hardware scb array in the host.
+ * Address of the hardware scb array in the host.
*/
- HSCB_ADDR {
+ 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.
+ * 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 {
+ SHARED_DATA_ADDR {
size 4
}
KERNEL_QINPOS {
@@ -1444,12 +1472,12 @@ scratch_ram {
*/
SCSISEQ_TEMPLATE {
size 1
- bit ENSELO 0x40
- bit ENSELI 0x20
- bit ENRSELI 0x10
- bit ENAUTOATNO 0x08
- bit ENAUTOATNI 0x04
- bit ENAUTOATNP 0x02
+ field ENSELO 0x40
+ field ENSELI 0x20
+ field ENRSELI 0x10
+ field ENAUTOATNO 0x08
+ field ENAUTOATNI 0x04
+ field ENAUTOATNP 0x02
}
/*
@@ -1459,41 +1487,58 @@ scratch_ram {
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.
*/
- INITIATOR_TAG {
- size 1
+ HA_274_BIOSGLOBAL {
+ size 1
+ field HA_274_EXTENDED_TRANS 0x01
+ alias INITIATOR_TAG
}
- SEQ_FLAGS2 {
- size 1
- bit SCB_DMA 0x01
- }
+ 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. Some of
- * the values are specified in the AHA2742 technical reference manual
- * and are initialized by the BIOS at boot time.
+ * These are reserved registers in the card's scratch ram on the 2742.
+ * The EISA configuraiton 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
- bit TERM_ENB 0x80
- bit RESET_SCSI 0x40
- bit ENSPCHK 0x20
+ 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
- bit EDGE_TRIG 0x80
- mask VECTOR 0x0f
+ }
+ INTDEF {
+ address 0x05c
+ size 1
+ field EDGE_TRIG 0x80
+ mask VECTOR 0x0f
}
HOSTCONF {
address 0x05d
@@ -1504,7 +1549,7 @@ scratch_ram {
size 1
mask BIOSMODE 0x30
mask BIOSDISABLED 0x30
- bit CHANNEL_B_PRIMARY 0x08
+ field CHANNEL_B_PRIMARY 0x08
}
}
@@ -1520,7 +1565,7 @@ scratch_ram {
}
}
-const TID_SHIFT 4
+const TID_SHIFT 4
const SCB_LIST_NULL 0xff
const TARGET_CMD_CMPLT 0xfe
@@ -1536,18 +1581,15 @@ const BUS_32_BIT 0x02
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 SCB_TARGET_PHASES 0
-const SCB_TARGET_DATA_DIR 1
-const SCB_TARGET_STATUS 2
-const SCB_INITIATOR_TAG 3
-const TARGET_DATA_IN 1
+const STATUS_QUEUE_FULL 0x28
+const TARGET_DATA_IN 1
/*
* Downloaded (kernel inserted) constants
diff --git a/sys/dev/microcode/aic7xxx/aic7xxx.seq b/sys/dev/microcode/aic7xxx/aic7xxx.seq
index b8122d7ad5d..b42d25c26d4 100644
--- a/sys/dev/microcode/aic7xxx/aic7xxx.seq
+++ b/sys/dev/microcode/aic7xxx/aic7xxx.seq
@@ -1,8 +1,9 @@
-/* $OpenBSD: aic7xxx.seq,v 1.13 2002/07/05 05:41:03 smurph Exp $ */
+/* $OpenBSD: aic7xxx.seq,v 1.14 2003/12/24 22:40:16 krw Exp $ */
/*
* Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD.
*
- * Copyright (c) 1994-2001 Justin Gibbs.
+ * 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
@@ -11,29 +12,38 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
- * 2. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * 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 Public License ("GPL").
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
*
- * 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
+ * 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 DAMAGE.
+ * 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: src/sys/dev/aic7xxx/aic7xxx.seq,v 1.119 2001/08/05 22:20:12 gibbs Exp $
+ * $FreeBSD: /repoman/r/ncvs/src/sys/dev/aic7xxx/aic7xxx.seq,v 1.123 2003/01/20 20:44:55 gibbs Exp $
*/
-VERSION = "$Id: aic7xxx.seq,v 1.13 2002/07/05 05:41:03 smurph Exp $"
+VERSION = "$NetBSD: aic7xxx.seq,v 1.15 2003/05/03 18:11:31 wiz Exp $"
PATCH_ARG_LIST = "struct ahc_softc *ahc"
+PREFIX = "ahc_"
#include <dev/microcode/aic7xxx/aic7xxx.reg>
#include <scsi/scsi_message.h>
@@ -57,121 +67,121 @@ PATCH_ARG_LIST = "struct ahc_softc *ahc"
*/
bus_free_sel:
- /*
- * Turn off the selection hardware. We need to reset the
- * selection request in order to perform a new selection.
- */
- and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ;
- and SIMODE1, ~ENBUSFREE;
+ /*
+ * Turn off the selection hardware. We need to reset the
+ * selection request in order to perform a new selection.
+ */
+ and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP;
+ and SIMODE1, ~ENBUSFREE;
poll_for_work:
call clear_target_state;
and SXFRCTL0, ~SPIOEN;
- if ((ahc->features & AHC_ULTRA2) != 0) {
- clr SCSIBUSL;
- }
- test SCSISEQ, ENSELO jnz poll_for_selection;
- if ((ahc->features & AHC_TWIN) != 0) {
- xor SBLKCTL,SELBUSB; /* Toggle to the other bus */
- test SCSISEQ, ENSELO jnz poll_for_selection;
- }
- cmp WAITING_SCBH,SCB_LIST_NULL jne start_waiting;
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ clr SCSIBUSL;
+ }
+ test SCSISEQ, ENSELO jnz poll_for_selection;
+ if ((ahc->features & AHC_TWIN) != 0) {
+ xor SBLKCTL,SELBUSB; /* Toggle to the other bus */
+ test SCSISEQ, ENSELO jnz poll_for_selection;
+ }
+ cmp WAITING_SCBH,SCB_LIST_NULL jne start_waiting;
poll_for_work_loop:
if ((ahc->features & AHC_TWIN) != 0) {
xor SBLKCTL,SELBUSB; /* Toggle to the other bus */
- }
- test SSTAT0, SELDO|SELDI jnz selection;
+ }
+ test SSTAT0, SELDO|SELDI jnz selection;
test_queue:
/* Has the driver posted any work for us? */
BEGIN_CRITICAL;
if ((ahc->features & AHC_QUEUE_REGS) != 0) {
test QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop;
} else {
- mov A, QINPOS;
+ mov A, QINPOS;
cmp KERNEL_QINPOS, A je poll_for_work_loop;
}
- mov ARG_1, NEXT_QUEUED_SCB;
+ mov ARG_1, NEXT_QUEUED_SCB;
- /*
- * We have at least one queued SCB now and we don't have any
- * SCBs in the list of SCBs awaiting selection. Allocate a
- * card SCB for the host's SCB and get to work on it.
- */
+ /*
+ * We have at least one queued SCB now and we don't have any
+ * SCBs in the list of SCBs awaiting selection. Allocate a
+ * card SCB for the host's SCB and get to work on it.
+ */
if ((ahc->flags & AHC_PAGESCBS) != 0) {
mov ALLZEROS call get_free_or_disc_scb;
- } else {
+ } else {
/* In the non-paging case, the SCBID == hardware SCB index */
- mov SCBPTR, ARG_1;
+ mov SCBPTR, ARG_1;
}
- or SEQ_FLAGS2, SCB_DMA;
+ or SEQ_FLAGS2, SCB_DMA;
END_CRITICAL;
dma_queued_scb:
- /*
- * DMA the SCB from host ram into the current SCB location.
- */
+ /*
+ * DMA the SCB from host ram into the current SCB location.
+ */
mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
- mov ARG_1 call dma_scb;
- /*
- * Check one last time to see if this SCB was canceled
- * before we completed the DMA operation. If it was,
- * the QINFIFO next pointer will not match our saved
- * value.
- */
- mov A, ARG_1;
+ mov ARG_1 call dma_scb;
+ /*
+ * Check one last time to see if this SCB was canceled
+ * before we completed the DMA operation. If it was,
+ * the QINFIFO next pointer will not match our saved
+ * value.
+ */
+ mov A, ARG_1;
BEGIN_CRITICAL;
- cmp NEXT_QUEUED_SCB, A jne abort_qinscb;
- if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
- cmp SCB_TAG, A je . + 2;
- mvi SCB_MISMATCH call set_seqint;
+ cmp NEXT_QUEUED_SCB, A jne abort_qinscb;
+ if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
+ cmp SCB_TAG, A je . + 2;
+ mvi SCB_MISMATCH call set_seqint;
}
- mov NEXT_QUEUED_SCB, SCB_NEXT;
+ mov NEXT_QUEUED_SCB, SCB_NEXT;
mov SCB_NEXT,WAITING_SCBH;
mov WAITING_SCBH, SCBPTR;
- if ((ahc->features & AHC_QUEUE_REGS) != 0) {
- mov NONE, SNSCB_QOFF;
- } else {
- inc QINPOS;
- }
- and SEQ_FLAGS2, ~SCB_DMA;
+ if ((ahc->features & AHC_QUEUE_REGS) != 0) {
+ mov NONE, SNSCB_QOFF;
+ } else {
+ inc QINPOS;
+ }
+ and SEQ_FLAGS2, ~SCB_DMA;
END_CRITICAL;
start_waiting:
/*
- * Start the first entry on the waiting SCB list.
+ * Start the first entry on the waiting SCB list.
*/
mov SCBPTR, WAITING_SCBH;
call start_selection;
poll_for_selection:
- /*
- * Twin channel devices cannot handle things like SELTO
- * interrupts on the "background" channel. So, while
- * selecting, keep polling the current channel until
- * either a selection or reselection occurs.
- */
- test SSTAT0, SELDO|SELDI jz poll_for_selection;
+ /*
+ * Twin channel devices cannot handle things like SELTO
+ * interrupts on the "background" channel. So, while
+ * selecting, keep polling the current channel until
+ * either a selection or reselection occurs.
+ */
+ test SSTAT0, SELDO|SELDI jz poll_for_selection;
selection:
- /*
- * We aren't expecting a bus free, so interrupt
- * the kernel driver if it happens.
- */
- mvi CLRSINT1,CLRBUSFREE;
- if ((ahc->features & AHC_DT) == 0) {
- or SIMODE1, ENBUSFREE;
- }
-
- /*
- * Guard against a bus free after (re)selection
- * but prior to enabling the busfree interrupt. SELDI
- * and SELDO will be cleared in that case.
- */
- test SSTAT0, SELDI|SELDO jz bus_free_sel;
+ /*
+ * We aren't expecting a bus free, so interrupt
+ * the kernel driver if it happens.
+ */
+ mvi CLRSINT1,CLRBUSFREE;
+ if ((ahc->features & AHC_DT) == 0) {
+ or SIMODE1, ENBUSFREE;
+ }
+
+ /*
+ * Guard against a bus free after (re)selection
+ * but prior to enabling the busfree interrupt. SELDI
+ * and SELDO will be cleared in that case.
+ */
+ test SSTAT0, SELDI|SELDO jz bus_free_sel;
test SSTAT0,SELDO jnz select_out;
select_in:
- if ((ahc->flags & AHC_TARGETROLE) != 0) {
- if ((ahc->flags & AHC_INITIATORROLE) != 0) {
+ if ((ahc->flags & AHC_TARGETROLE) != 0) {
+ if ((ahc->flags & AHC_INITIATORROLE) != 0) {
test SSTAT0, TARGET jz initiator_reselect;
}
- mvi CLRSINT0, CLRSELDI;
+ mvi CLRSINT0, CLRSELDI;
/*
* We've just been selected. Assert BSY and
@@ -184,45 +194,45 @@ select_in:
* Setup the DMA for sending the identify and
* command information.
*/
- or SEQ_FLAGS, CMDPHASE_PENDING;
+ mvi SEQ_FLAGS, CMDPHASE_PENDING;
mov A, TQINPOS;
if ((ahc->features & AHC_CMD_CHAN) != 0) {
mvi DINDEX, CCHADDR;
- mvi SHARED_DATA_ADDR call set_32byte_addr;
+ mvi SHARED_DATA_ADDR call set_32byte_addr;
mvi CCSCBCTL, CCSCBRESET;
} else {
mvi DINDEX, HADDR;
- mvi SHARED_DATA_ADDR call set_32byte_addr;
+ mvi SHARED_DATA_ADDR call set_32byte_addr;
mvi DFCNTRL, FIFORESET;
}
/* Initiator that selected us */
- and SAVED_SCSIID, SELID_MASK, SELID;
+ and SAVED_SCSIID, SELID_MASK, SELID;
/* The Target ID we were selected at */
- if ((ahc->features & AHC_MULTI_TID) != 0) {
- and A, OID, TARGIDIN;
- } else if ((ahc->features & AHC_ULTRA2) != 0) {
- and A, OID, SCSIID_ULTRA2;
- } else {
- and A, OID, SCSIID;
- }
- or SAVED_SCSIID, A;
- if ((ahc->features & AHC_TWIN) != 0) {
- test SBLKCTL, SELBUSB jz . + 2;
- or SAVED_SCSIID, TWIN_CHNLB;
- }
- if ((ahc->features & AHC_CMD_CHAN) != 0) {
- mov CCSCBRAM, SAVED_SCSIID;
+ if ((ahc->features & AHC_MULTI_TID) != 0) {
+ and A, OID, TARGIDIN;
+ } else if ((ahc->features & AHC_ULTRA2) != 0) {
+ and A, OID, SCSIID_ULTRA2;
} else {
- mov DFDAT, SAVED_SCSIID;
- }
+ and A, OID, SCSIID;
+ }
+ or SAVED_SCSIID, A;
+ if ((ahc->features & AHC_TWIN) != 0) {
+ test SBLKCTL, SELBUSB jz . + 2;
+ or SAVED_SCSIID, TWIN_CHNLB;
+ }
+ if ((ahc->features & AHC_CMD_CHAN) != 0) {
+ mov CCSCBRAM, SAVED_SCSIID;
+ } else {
+ mov DFDAT, SAVED_SCSIID;
+ }
/*
* If ATN isn't asserted, the target isn't interested
* in talking to us. Go directly to bus free.
- * XXX SCSI-1 may require us to assume lun 0 if
- * ATN is false.
+ * XXX SCSI-1 may require us to assume lun 0 if
+ * ATN is false.
*/
test SCSISIGI, ATNI jz target_busfree;
@@ -244,6 +254,7 @@ select_in:
} else {
mov DFDAT, DINDEX;
}
+ and SAVED_LUN, MSG_IDENTIFY_LUNMASK, DINDEX;
/* Remember for disconnection decision */
test DINDEX, MSG_IDENTIFY_DISCFLAG jnz . + 2;
@@ -259,9 +270,10 @@ select_in:
* < MSG_IGN_WIDE_RESIDUE.
*/
add A, -MSG_SIMPLE_Q_TAG, DINDEX;
- jnc ident_messages_done;
+ jnc ident_messages_done_msg_pending;
add A, -MSG_IGN_WIDE_RESIDUE, DINDEX;
- jc ident_messages_done;
+ jc ident_messages_done_msg_pending;
+
/* Store for host */
if ((ahc->features & AHC_CMD_CHAN) != 0) {
mov CCSCBRAM, DINDEX;
@@ -286,10 +298,24 @@ select_in:
mov DFDAT, DINDEX;
}
mov INITIATOR_TAG, DINDEX;
- or SEQ_FLAGS, TARGET_CMD_IS_TAGGED;
- test SCSISIGI, ATNI jz . + 2;
- /* Initiator still wants to give us messages */
- call target_inb;
+ or SEQ_FLAGS, TARGET_CMD_IS_TAGGED;
+
+ident_messages_done:
+ /* Terminate the ident list */
+ if ((ahc->features & AHC_CMD_CHAN) != 0) {
+ mvi CCSCBRAM, SCB_LIST_NULL;
+ } else {
+ mvi DFDAT, SCB_LIST_NULL;
+ }
+ or SEQ_FLAGS, TARG_CMD_PENDING;
+ test SEQ_FLAGS2, TARGET_MSG_PENDING
+ jnz target_mesgout_pending;
+ test SCSISIGI, ATNI jnz target_mesgout_continue;
+ jmp target_ITloop;
+
+
+ident_messages_done_msg_pending:
+ or SEQ_FLAGS2, TARGET_MSG_PENDING;
jmp ident_messages_done;
/*
@@ -297,36 +323,11 @@ select_in:
* run it's own target mode message state engine.
*/
host_target_message_loop:
- mvi HOST_MSG_LOOP call set_seqint;
+ mvi HOST_MSG_LOOP call set_seqint;
cmp RETURN_1, EXIT_MSG_LOOP je target_ITloop;
test SSTAT0, SPIORDY jz .;
jmp host_target_message_loop;
-
-ident_messages_done:
- /* If ring buffer is full, return busy or queue full */
- if ((ahc->features & AHC_HS_MAILBOX) != 0) {
- and A, HOST_TQINPOS, HS_MAILBOX;
- } else {
- mov A, KERNEL_TQINPOS;
- }
- cmp TQINPOS, A jne tqinfifo_has_space;
- mvi P_STATUS|BSYO call change_phase;
- test SEQ_FLAGS, TARGET_CMD_IS_TAGGED jz . + 3;
- mvi STATUS_QUEUE_FULL call target_outb;
- jmp target_busfree_wait;
- mvi STATUS_BUSY call target_outb;
- jmp target_busfree_wait;
-tqinfifo_has_space:
- /* Terminate the ident list */
- if ((ahc->features & AHC_CMD_CHAN) != 0) {
- mvi CCSCBRAM, SCB_LIST_NULL;
- } else {
- mvi DFDAT, SCB_LIST_NULL;
- }
- or SEQ_FLAGS, TARG_CMD_PENDING|IDENTIFY_SEEN;
- test SCSISIGI, ATNI jnz target_mesgout_pending;
- jmp target_ITloop;
- }
+ }
if ((ahc->flags & AHC_INITIATORROLE) != 0) {
/*
@@ -334,84 +335,77 @@ if ((ahc->flags & AHC_INITIATORROLE) != 0) {
* reselected, but haven't seen an IDENTIFY message from the target yet.
*/
initiator_reselect:
- /* XXX test for and handle ONE BIT condition */
- test SELID, ONEBIT jnz await_busfree;
-
- or SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN;
- and SAVED_SCSIID, SELID_MASK, SELID;
- if ((ahc->features & AHC_ULTRA2) != 0) {
- and A, OID, SCSIID_ULTRA2;
- } else {
- and A, OID, SCSIID;
- }
- or SAVED_SCSIID, A;
- if ((ahc->features & AHC_TWIN) != 0) {
- test SBLKCTL, SELBUSB jz . + 2;
- or SAVED_SCSIID, TWIN_CHNLB;
- }
- mvi CLRSINT0, CLRSELDI;
- jmp ITloop;
+ /* XXX test for and handle ONE BIT condition */
+ or SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN;
+ and SAVED_SCSIID, SELID_MASK, SELID;
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ and A, OID, SCSIID_ULTRA2;
+ } else {
+ and A, OID, SCSIID;
+ }
+ or SAVED_SCSIID, A;
+ if ((ahc->features & AHC_TWIN) != 0) {
+ test SBLKCTL, SELBUSB jz . + 2;
+ or SAVED_SCSIID, TWIN_CHNLB;
+ }
+ mvi CLRSINT0, CLRSELDI;
+ jmp ITloop;
}
abort_qinscb:
- call add_scb_to_free_list;
- jmp poll_for_work_loop;
+ call add_scb_to_free_list;
+ jmp poll_for_work_loop;
start_selection:
- /*
- * If bus reset interrupts have been disabled (from a previous
- * reset), re-enable them now. Resets are only of interest
- * when we have outstanding transactions, so we can safely
- * defer re-enabling the interrupt until, as an initiator,
- * we start sending out transactions again.
- */
- test SIMODE1, ENSCSIRST jnz . + 3;
- mvi CLRSINT1, CLRSCSIRSTI;
- or SIMODE1, ENSCSIRST;
- if ((ahc->features & AHC_TWIN) != 0) {
- and SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */
- test SCB_SCSIID, TWIN_CHNLB jz . + 2;
- or SINDEX, SELBUSB;
- mov SBLKCTL,SINDEX; /* select channel */
- }
+ /*
+ * If bus reset interrupts have been disabled (from a previous
+ * reset), re-enable them now. Resets are only of interest
+ * when we have outstanding transactions, so we can safely
+ * defer re-enabling the interrupt until, as an initiator,
+ * we start sending out transactions again.
+ */
+ test SIMODE1, ENSCSIRST jnz . + 3;
+ mvi CLRSINT1, CLRSCSIRSTI;
+ or SIMODE1, ENSCSIRST;
+ if ((ahc->features & AHC_TWIN) != 0) {
+ and SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */
+ test SCB_SCSIID, TWIN_CHNLB jz . + 2;
+ or SINDEX, SELBUSB;
+ mov SBLKCTL,SINDEX; /* select channel */
+ }
initialize_scsiid:
- if ((ahc->features & AHC_ULTRA2) != 0) {
- mov SCSIID_ULTRA2, SCB_SCSIID;
- } else if ((ahc->features & AHC_TWIN) != 0) {
- and SCSIID, TWIN_TID|OID, SCB_SCSIID;
- } else {
- mov SCSIID, SCB_SCSIID;
- }
- if ((ahc->flags & AHC_TARGETROLE) != 0) {
- mov SINDEX, SCSISEQ_TEMPLATE;
- test SCB_CONTROL, TARGET_SCB jz . + 2;
- or SINDEX, TEMODE;
- mov SCSISEQ, SINDEX ret;
- } else {
- mov SCSISEQ, SCSISEQ_TEMPLATE ret;
- }
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ mov SCSIID_ULTRA2, SCB_SCSIID;
+ } else if ((ahc->features & AHC_TWIN) != 0) {
+ and SCSIID, TWIN_TID|OID, SCB_SCSIID;
+ } else {
+ mov SCSIID, SCB_SCSIID;
+ }
+ if ((ahc->flags & AHC_TARGETROLE) != 0) {
+ mov SINDEX, SCSISEQ_TEMPLATE;
+ test SCB_CONTROL, TARGET_SCB jz . + 2;
+ or SINDEX, TEMODE;
+ mov SCSISEQ, SINDEX ret;
+ } else {
+ mov SCSISEQ, SCSISEQ_TEMPLATE ret;
+ }
/*
- * Initialize transfer settings and clear the SCSI channel.
- * SINDEX should contain any additional bit's the client wants
- * set in SXFRCTL0. We also assume that the current SCB is
- * a valid SCB for the target we wish to talk to.
+ * Initialize transfer settings with SCB provided settings.
*/
-initialize_channel:
- or SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN;
set_transfer_settings:
- if ((ahc->features & AHC_ULTRA) != 0) {
- test SCB_CONTROL, ULTRAENB jz . + 2;
- or SXFRCTL0, FAST20;
- }
- /*
- * Initialize SCSIRATE with the appropriate value for this target.
- */
- if ((ahc->features & AHC_ULTRA2) != 0) {
- bmov SCSIRATE, SCB_SCSIRATE, 2 ret;
- } else {
- mov SCSIRATE, SCB_SCSIRATE ret;
- }
+ if ((ahc->features & AHC_ULTRA) != 0) {
+ test SCB_CONTROL, ULTRAENB jz . + 2;
+ or SXFRCTL0, FAST20;
+ }
+ /*
+ * Initialize SCSIRATE with the appropriate value for this target.
+ */
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ bmov SCSIRATE, SCB_SCSIRATE, 2 ret;
+ } else {
+ mov SCSIRATE, SCB_SCSIRATE ret;
+ }
if ((ahc->flags & AHC_TARGETROLE) != 0) {
/*
@@ -420,16 +414,16 @@ if ((ahc->flags & AHC_TARGETROLE) != 0) {
* driving REQ on the bus for the next byte.
*/
target_inb:
- /*
- * Drive REQ on the bus by enabling SCSI PIO.
- */
- or SXFRCTL0, SPIOEN;
- /* Wait for the byte */
- test SSTAT0, SPIORDY jz .;
- /* Prevent our read from triggering another REQ */
- and SXFRCTL0, ~SPIOEN;
- /* Save latched contents */
- mov DINDEX, SCSIDATL ret;
+ /*
+ * Drive REQ on the bus by enabling SCSI PIO.
+ */
+ or SXFRCTL0, SPIOEN;
+ /* Wait for the byte */
+ test SSTAT0, SPIORDY jz .;
+ /* Prevent our read from triggering another REQ */
+ and SXFRCTL0, ~SPIOEN;
+ /* Save latched contents */
+ mov DINDEX, SCSIDATL ret;
}
/*
@@ -441,26 +435,34 @@ target_inb:
select_out:
/* Turn off the selection hardware */
and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ;
- mvi CLRSINT0, CLRSELDO;
mov SCBPTR, WAITING_SCBH;
mov WAITING_SCBH,SCB_NEXT;
- mov SAVED_SCSIID, SCB_SCSIID;
- mov SAVED_LUN, SCB_LUN;
- call initialize_channel;
- if ((ahc->flags & AHC_TARGETROLE) != 0) {
+ mov SAVED_SCSIID, SCB_SCSIID;
+ mov SAVED_LUN, SCB_LUN;
+ call set_transfer_settings;
+ if ((ahc->flags & AHC_TARGETROLE) != 0) {
test SSTAT0, TARGET jz initiator_select;
+ or SXFRCTL0, CLRSTCNT|CLRCHN;
+
+ /*
+ * Put tag in connonical location since not
+ * all connections have an SCB.
+ */
+ mov INITIATOR_TAG, SCB_TARGET_ITAG;
+
/*
* We've just re-selected an initiator.
* Assert BSY and setup the phase for
* sending our identify messages.
*/
mvi P_MESGIN|BSYO call change_phase;
+ mvi CLRSINT0, CLRSELDO;
/*
* Start out with a simple identify message.
*/
- or SCB_LUN, MSG_IDENTIFYFLAG call target_outb;
+ or SCB_LUN, MSG_IDENTIFYFLAG call target_outb;
/*
* If we are the result of a tagged command, send
@@ -468,17 +470,17 @@ select_out:
*/
test SCB_CONTROL, TAG_ENB jz . + 3;
mvi MSG_SIMPLE_Q_TAG call target_outb;
- mov SCB_TARGET_INFO[SCB_INITIATOR_TAG] call target_outb;
+ mov SCB_TARGET_ITAG call target_outb;
target_synccmd:
/*
* Now determine what phases the host wants us
* to go through.
*/
- mov SEQ_FLAGS, SCB_TARGET_INFO[SCB_TARGET_PHASES];
+ mov SEQ_FLAGS, SCB_TARGET_PHASES;
- test SCB_CONTROL, MK_MESSAGE jz target_ITloop;
- mvi P_MESGIN|BSYO call change_phase;
- jmp host_target_message_loop;
+ test SCB_CONTROL, MK_MESSAGE jz target_ITloop;
+ mvi P_MESGIN|BSYO call change_phase;
+ jmp host_target_message_loop;
target_ITloop:
/*
* Start honoring ATN signals now that
@@ -494,14 +496,16 @@ target_ITloop:
* on the state of NO_DISCONNECT.
*/
test SEQ_FLAGS, NO_DISCONNECT jz target_disconnect;
- mov RETURN_1, ALLZEROS;
- call complete_target_cmd;
- cmp RETURN_1, CONT_MSG_LOOP jne .;
+ mvi TARG_IMMEDIATE_SCB, SCB_LIST_NULL;
+ call complete_target_cmd;
if ((ahc->flags & AHC_PAGESCBS) != 0) {
mov ALLZEROS call get_free_or_disc_scb;
}
+ cmp TARG_IMMEDIATE_SCB, SCB_LIST_NULL je .;
mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
- mov SCB_TAG call dma_scb;
+ mov TARG_IMMEDIATE_SCB call dma_scb;
+ call set_transfer_settings;
+ or SXFRCTL0, CLRSTCNT|CLRCHN;
jmp target_synccmd;
target_mesgout:
@@ -509,6 +513,7 @@ target_mesgout:
target_mesgout_continue:
call target_inb;
target_mesgout_pending:
+ and SEQ_FLAGS2, ~TARGET_MSG_PENDING;
/* Local Processing goes here... */
jmp host_target_message_loop;
@@ -519,19 +524,37 @@ target_disconnect:
mvi MSG_DISCONNECT call target_outb;
target_busfree_wait:
- /* Wait for preceding I/O session to complete. */
+ /* Wait for preceding I/O session to complete. */
test SCSISIGI, ACKI jnz .;
target_busfree:
- and SIMODE1, ~ENBUSFREE;
- if ((ahc->features & AHC_ULTRA2) != 0) {
- clr SCSIBUSL;
- }
+ and SIMODE1, ~ENBUSFREE;
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ clr SCSIBUSL;
+ }
clr SCSISIGO;
mvi LASTPHASE, P_BUSFREE;
call complete_target_cmd;
jmp poll_for_work;
target_cmdphase:
+ /*
+ * The target has dropped ATN (doesn't want to abort or BDR)
+ * and we believe this selection to be valid. If the ring
+ * buffer for new commands is full, return busy or queue full.
+ */
+ if ((ahc->features & AHC_HS_MAILBOX) != 0) {
+ and A, HOST_TQINPOS, HS_MAILBOX;
+ } else {
+ mov A, KERNEL_TQINPOS;
+ }
+ cmp TQINPOS, A jne tqinfifo_has_space;
+ mvi P_STATUS|BSYO call change_phase;
+ test SEQ_FLAGS, TARGET_CMD_IS_TAGGED jz . + 3;
+ mvi STATUS_QUEUE_FULL call target_outb;
+ jmp target_busfree_wait;
+ mvi STATUS_BUSY call target_outb;
+ jmp target_busfree_wait;
+tqinfifo_has_space:
mvi P_COMMAND|BSYO call change_phase;
call target_inb;
mov A, DINDEX;
@@ -551,11 +574,11 @@ target_cmdphase:
* the first byte.
*/
shr A, CMD_GROUP_CODE_SHIFT;
- add SINDEX, CMDSIZE_TABLE, A;
+ add SINDEX, CMDSIZE_TABLE, A;
mov A, SINDIR;
test A, 0xFF jz command_phase_done;
- or SXFRCTL0, SPIOEN;
+ or SXFRCTL0, SPIOEN;
command_loop:
test SSTAT0, SPIORDY jz .;
cmp A, 1 jne . + 2;
@@ -574,21 +597,20 @@ command_phase_done:
target_dphase:
/*
- * Data phases on the bus are from the
- * perspective of the initiator. The dma
- * code looks at LASTPHASE to determine the
- * data direction of the DMA. Toggle it for
- * target transfers.
+ * Data phases on the bus are from the
+ * perspective of the initiator. The DMA
+ * code looks at LASTPHASE to determine the
+ * data direction of the DMA. Toggle it for
+ * target transfers.
*/
- xor LASTPHASE, IOI, SCB_TARGET_INFO[SCB_TARGET_DATA_DIR];
- or SCB_TARGET_INFO[SCB_TARGET_DATA_DIR], BSYO
- call change_phase;
+ xor LASTPHASE, IOI, SCB_TARGET_DATA_DIR;
+ or SCB_TARGET_DATA_DIR, BSYO call change_phase;
jmp p_data;
target_sphase:
mvi P_STATUS|BSYO call change_phase;
mvi LASTPHASE, P_STATUS;
- mov SCB_TARGET_INFO[SCB_TARGET_STATUS] call target_outb;
+ mov SCB_SCSI_STATUS call target_outb;
/* XXX Watch for ATN or parity errors??? */
mvi SCSISIGO, P_MESGIN|BSYO;
/* MSG_CMDCMPLT is 0, but we can't do an immediate of 0 */
@@ -611,7 +633,7 @@ complete_target_cmd:
or DFCNTRL, FIFORESET;
mvi DFWADDR, 3; /* Third 64bit word or byte 24 */
mov DFDAT, ALLONES;
- mvi 28 call set_hcnt;
+ mvi 28 call set_hcnt;
or DFCNTRL, HDMAEN|FIFOFLUSH;
call dma_finish;
}
@@ -621,13 +643,15 @@ complete_target_cmd:
if ((ahc->flags & AHC_INITIATORROLE) != 0) {
initiator_select:
+ or SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN;
/*
* 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;
+ mvi SEQ_FLAGS, NO_CDB_SENT;
+ mvi CLRSINT0, CLRSELDO;
/*
* Main loop for information transfer phases. Wait for the
@@ -646,19 +670,19 @@ ITloop:
cmp A,P_STATUS je p_status;
cmp A,P_MESGIN je p_mesgin;
- mvi BAD_PHASE call set_seqint;
+ mvi BAD_PHASE call set_seqint;
jmp ITloop; /* Try reading the bus again. */
await_busfree:
and SIMODE1, ~ENBUSFREE;
mov NONE, SCSIDATL; /* Ack the last byte */
- if ((ahc->features & AHC_ULTRA2) != 0) {
- clr SCSIBUSL; /* Prevent bit leakage durint SELTO */
- }
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ clr SCSIBUSL; /* Prevent bit leakage durint SELTO */
+ }
and SXFRCTL0, ~SPIOEN;
test SSTAT1,REQINIT|BUSFREE jz .;
test SSTAT1, BUSFREE jnz poll_for_work;
- mvi MISSED_BUSFREE call set_seqint;
+ mvi MISSED_BUSFREE call set_seqint;
}
clear_target_state:
@@ -668,7 +692,7 @@ clear_target_state:
* clear DFCNTRL too.
*/
clr DFCNTRL;
- or SXFRCTL0, CLRSTCNT|CLRCHN;
+ or SXFRCTL0, CLRSTCNT|CLRCHN;
/*
* We don't know the target we will connect to,
@@ -679,89 +703,89 @@ clear_target_state:
bmov SCSIRATE, ALLZEROS, 2;
} else {
clr SCSIRATE;
- if ((ahc->features & AHC_ULTRA) != 0) {
- and SXFRCTL0, ~(FAST20);
- }
+ if ((ahc->features & AHC_ULTRA) != 0) {
+ and SXFRCTL0, ~(FAST20);
+ }
}
mvi LASTPHASE, P_BUSFREE;
/* clear target specific flags */
- clr SEQ_FLAGS ret;
+ mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret;
sg_advance:
- clr A; /* add sizeof(struct scatter) */
- add SCB_RESIDUAL_SGPTR[0],SG_SIZEOF;
- adc SCB_RESIDUAL_SGPTR[1],A;
- adc SCB_RESIDUAL_SGPTR[2],A;
- adc SCB_RESIDUAL_SGPTR[3],A ret;
+ clr A; /* add sizeof(struct scatter) */
+ add SCB_RESIDUAL_SGPTR[0],SG_SIZEOF;
+ adc SCB_RESIDUAL_SGPTR[1],A;
+ adc SCB_RESIDUAL_SGPTR[2],A;
+ adc SCB_RESIDUAL_SGPTR[3],A ret;
if ((ahc->features & AHC_CMD_CHAN) != 0) {
disable_ccsgen:
- test CCSGCTL, CCSGEN jz return;
- test CCSGCTL, CCSGDONE jz .;
+ test CCSGCTL, CCSGEN jz return;
+ test CCSGCTL, CCSGDONE jz .;
disable_ccsgen_fetch_done:
- clr CCSGCTL;
- test CCSGCTL, CCSGEN jnz .;
- ret;
+ clr CCSGCTL;
+ test CCSGCTL, CCSGEN jnz .;
+ ret;
idle_loop:
- /*
- * Do we need any more segments for this transfer?
- */
- test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return;
-
- /* Did we just finish fetching segs? */
- cmp CCSGCTL, CCSGEN|CCSGDONE je idle_sgfetch_complete;
-
- /* Are we actively fetching segments? */
- test CCSGCTL, CCSGEN jnz return;
-
- /*
- * Do we have any prefetch left???
- */
- cmp CCSGADDR, SG_PREFETCH_CNT jne idle_sg_avail;
-
- /*
- * Need to fetch segments, but we can only do that
- * if the command channel is completely idle. Make
- * sure we don't have an SCB prefetch going on.
- */
- test CCSCBCTL, CCSCBEN jnz return;
-
- /*
- * We fetch a "cacheline aligned" and sized amount of data
- * so we don't end up referencing a non-existant page.
- * Cacheline aligned is in quotes because the kernel will
- * set the prefetch amount to a reasonable level if the
- * cacheline size is unknown.
- */
- mvi CCHCNT, SG_PREFETCH_CNT;
- and CCHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR;
- bmov CCHADDR[1], SCB_RESIDUAL_SGPTR[1], 3;
- mvi CCSGCTL, CCSGEN|CCSGRESET ret;
+ /*
+ * Do we need any more segments for this transfer?
+ */
+ test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return;
+
+ /* Did we just finish fetching segs? */
+ cmp CCSGCTL, CCSGEN|CCSGDONE je idle_sgfetch_complete;
+
+ /* Are we actively fetching segments? */
+ test CCSGCTL, CCSGEN jnz return;
+
+ /*
+ * Do we have any prefetch left???
+ */
+ cmp CCSGADDR, SG_PREFETCH_CNT jne idle_sg_avail;
+
+ /*
+ * Need to fetch segments, but we can only do that
+ * if the command channel is completely idle. Make
+ * sure we don't have an SCB prefetch going on.
+ */
+ test CCSCBCTL, CCSCBEN jnz return;
+
+ /*
+ * We fetch a "cacheline aligned" and sized amount of data
+ * so we don't end up referencing a non-existant page.
+ * Cacheline aligned is in quotes because the kernel will
+ * set the prefetch amount to a reasonable level if the
+ * cacheline size is unknown.
+ */
+ mvi CCHCNT, SG_PREFETCH_CNT;
+ and CCHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR;
+ bmov CCHADDR[1], SCB_RESIDUAL_SGPTR[1], 3;
+ mvi CCSGCTL, CCSGEN|CCSGRESET ret;
idle_sgfetch_complete:
- call disable_ccsgen_fetch_done;
- and CCSGADDR, SG_PREFETCH_ADDR_MASK, SCB_RESIDUAL_SGPTR;
+ call disable_ccsgen_fetch_done;
+ and CCSGADDR, SG_PREFETCH_ADDR_MASK, SCB_RESIDUAL_SGPTR;
idle_sg_avail:
if ((ahc->features & AHC_ULTRA2) != 0) {
- /* Does the hardware have space for another SG entry? */
- test DFSTATUS, PRELOAD_AVAIL jz return;
- bmov HADDR, CCSGRAM, 7;
- test HCNT[0], 0x1 jz . + 2;
- xor DATA_COUNT_ODD, 0x1;
- bmov SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1;
- if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
- mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr;
- }
- call sg_advance;
- mov SINDEX, SCB_RESIDUAL_SGPTR[0];
- test DATA_COUNT_ODD, 0x1 jz . + 2;
- or SINDEX, ODD_SEG;
- test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;
- or SINDEX, LAST_SEG;
- mov SG_CACHE_PRE, SINDEX;
- /* Load the segment */
- or DFCNTRL, PRELOADEN;
- }
- ret;
+ /* Does the hardware have space for another SG entry? */
+ test DFSTATUS, PRELOAD_AVAIL jz return;
+ bmov HADDR, CCSGRAM, 7;
+ test HCNT[0], 0x1 jz . + 2;
+ xor DATA_COUNT_ODD, 0x1;
+ bmov SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1;
+ if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
+ mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr;
+ }
+ call sg_advance;
+ mov SINDEX, SCB_RESIDUAL_SGPTR[0];
+ test DATA_COUNT_ODD, 0x1 jz . + 2;
+ or SINDEX, ODD_SEG;
+ test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;
+ or SINDEX, LAST_SEG;
+ mov SG_CACHE_PRE, SINDEX;
+ /* Load the segment */
+ or DFCNTRL, PRELOADEN;
+ }
+ ret;
}
if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) {
@@ -771,37 +795,37 @@ if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) {
* XXX Can we optimize this for PCI writes only???
*/
calc_mwi_residual:
- /*
- * If the ending address is on a cacheline boundary,
- * there is no need for an extra segment.
- */
- mov A, HCNT[0];
- add A, A, HADDR[0];
- and A, CACHESIZE_MASK;
- test A, 0xFF jz return;
-
- /*
- * If the transfer is less than a cachline,
- * there is no need for an extra segment.
- */
- test HCNT[1], 0xFF jnz calc_mwi_residual_final;
- test HCNT[2], 0xFF jnz calc_mwi_residual_final;
- add NONE, INVERTED_CACHESIZE_MASK, HCNT[0];
- jnc return;
+ /*
+ * If the ending address is on a cacheline boundary,
+ * there is no need for an extra segment.
+ */
+ mov A, HCNT[0];
+ add A, A, HADDR[0];
+ and A, CACHESIZE_MASK;
+ test A, 0xFF jz return;
+
+ /*
+ * If the transfer is less than a cachline,
+ * there is no need for an extra segment.
+ */
+ test HCNT[1], 0xFF jnz calc_mwi_residual_final;
+ test HCNT[2], 0xFF jnz calc_mwi_residual_final;
+ add NONE, INVERTED_CACHESIZE_MASK, HCNT[0];
+ jnc return;
calc_mwi_residual_final:
- mov MWI_RESIDUAL, A;
- not A;
- inc A;
- add HCNT[0], A;
- adc HCNT[1], -1;
- adc HCNT[2], -1 ret;
+ mov MWI_RESIDUAL, A;
+ not A;
+ inc A;
+ add HCNT[0], A;
+ adc HCNT[1], -1;
+ adc HCNT[2], -1 ret;
}
p_data:
- test SEQ_FLAGS,IDENTIFY_SEEN jnz p_data_okay;
- mvi NO_IDENT jmp set_seqint;
-p_data_okay:
+ test SEQ_FLAGS,NOT_IDENTIFIED|NO_CDB_SENT jz p_data_allowed;
+ mvi PROTO_VIOLATION call set_seqint;
+p_data_allowed:
if ((ahc->features & AHC_ULTRA2) != 0) {
mvi DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN;
} else {
@@ -810,412 +834,412 @@ p_data_okay:
test LASTPHASE, IOI jnz . + 2;
or DMAPARAMS, DIRECTION;
if ((ahc->features & AHC_CMD_CHAN) != 0) {
- /* We don't have any valid S/G elements */
- mvi CCSGADDR, SG_PREFETCH_CNT;
+ /* We don't have any valid S/G elements */
+ mvi CCSGADDR, SG_PREFETCH_CNT;
}
- test SEQ_FLAGS, DPHASE jz data_phase_initialize;
+ test SEQ_FLAGS, DPHASE jz data_phase_initialize;
- /*
- * If we re-enter the data phase after going through another
- * phase, our transfer location has almost certainly been
- * corrupted by the interveining, non-data, transfers. Ask
- * the host driver to fix us up based on the transfer residual.
- */
- mvi PDATA_REINIT call set_seqint;
- jmp data_phase_loop;
+ /*
+ * If we re-enter the data phase after going through another
+ * phase, our transfer location has almost certainly been
+ * corrupted by the interveining, non-data, transfers. Ask
+ * the host driver to fix us up based on the transfer residual.
+ */
+ mvi PDATA_REINIT call set_seqint;
+ jmp data_phase_loop;
data_phase_initialize:
- /* We have seen a data phase for the first time */
+ /* We have seen a data phase for the first time */
or SEQ_FLAGS, DPHASE;
/*
* Initialize the DMA address and counter from the SCB.
- * Also set SCB_RESIDUAL_SGPTR, including the LAST_SEG
- * flag in the highest byte of the data count. We cannot
- * modify the saved values in the SCB until we see a save
- * data pointers message.
+ * Also set SCB_RESIDUAL_SGPTR, including the LAST_SEG
+ * flag in the highest byte of the data count. We cannot
+ * modify the saved values in the SCB until we see a save
+ * data pointers message.
*/
- if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
- /* The lowest address byte must be loaded last. */
- mov SCB_DATACNT[3] call set_hhaddr;
- }
+ if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
+ /* The lowest address byte must be loaded last. */
+ mov SCB_DATACNT[3] call set_hhaddr;
+ }
if ((ahc->features & AHC_CMD_CHAN) != 0) {
bmov HADDR, SCB_DATAPTR, 7;
- bmov SCB_RESIDUAL_DATACNT[3], SCB_DATACNT[3], 5;
+ bmov SCB_RESIDUAL_DATACNT[3], SCB_DATACNT[3], 5;
} else {
mvi DINDEX, HADDR;
mvi SCB_DATAPTR call bcopy_7;
- mvi DINDEX, SCB_RESIDUAL_DATACNT + 3;
- mvi SCB_DATACNT + 3 call bcopy_5;
+ mvi DINDEX, SCB_RESIDUAL_DATACNT + 3;
+ mvi SCB_DATACNT + 3 call bcopy_5;
+ }
+ if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) {
+ call calc_mwi_residual;
}
- if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) {
- call calc_mwi_residual;
- }
- and SCB_RESIDUAL_SGPTR[0], ~SG_FULL_RESID;
- and DATA_COUNT_ODD, 0x1, HCNT[0];
+ and SCB_RESIDUAL_SGPTR[0], ~SG_FULL_RESID;
+ and DATA_COUNT_ODD, 0x1, HCNT[0];
if ((ahc->features & AHC_ULTRA2) == 0) {
if ((ahc->features & AHC_CMD_CHAN) != 0) {
bmov STCNT, HCNT, 3;
} else {
call set_stcnt_from_hcnt;
- }
+ }
}
data_phase_loop:
- /* Guard against overruns */
- test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz data_phase_inbounds;
-
- /*
- * Turn on `Bit Bucket' mode, wait until the target takes
- * us to another phase, and then notify the host.
- */
- and DMAPARAMS, DIRECTION;
- mov DFCNTRL, DMAPARAMS;
+ /* Guard against overruns */
+ test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz data_phase_inbounds;
+
+ /*
+ * Turn on `Bit Bucket' mode, wait until the target takes
+ * us to another phase, and then notify the host.
+ */
+ and DMAPARAMS, DIRECTION;
+ mov DFCNTRL, DMAPARAMS;
or SXFRCTL1,BITBUCKET;
- if ((ahc->features & AHC_DT) == 0) {
- test SSTAT1,PHASEMIS jz .;
+ if ((ahc->features & AHC_DT) == 0) {
+ test SSTAT1,PHASEMIS jz .;
} else {
- test SCSIPHASE, DATA_PHASE_MASK jnz .;
+ test SCSIPHASE, DATA_PHASE_MASK jnz .;
}
- and SXFRCTL1, ~BITBUCKET;
- mvi DATA_OVERRUN call set_seqint;
- jmp ITloop;
+ and SXFRCTL1, ~BITBUCKET;
+ mvi DATA_OVERRUN call set_seqint;
+ jmp ITloop;
data_phase_inbounds:
if ((ahc->features & AHC_ULTRA2) != 0) {
- mov SINDEX, SCB_RESIDUAL_SGPTR[0];
- test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;
- or SINDEX, LAST_SEG;
- test DATA_COUNT_ODD, 0x1 jz . + 2;
- or SINDEX, ODD_SEG;
- mov SG_CACHE_PRE, SINDEX;
- mov DFCNTRL, DMAPARAMS;
+ mov SINDEX, SCB_RESIDUAL_SGPTR[0];
+ test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;
+ or SINDEX, LAST_SEG;
+ test DATA_COUNT_ODD, 0x1 jz . + 2;
+ or SINDEX, ODD_SEG;
+ mov SG_CACHE_PRE, SINDEX;
+ mov DFCNTRL, DMAPARAMS;
ultra2_dma_loop:
- call idle_loop;
- /*
- * The transfer is complete if either the last segment
- * completes or the target changes phase.
- */
- test SG_CACHE_SHADOW, LAST_SEG_DONE jnz ultra2_dmafinish;
- if ((ahc->features & AHC_DT) == 0) {
- if ((ahc->flags & AHC_TARGETROLE) != 0) {
- /*
- * As a target, we control the phases,
- * so ignore PHASEMIS.
- */
- test SSTAT0, TARGET jnz ultra2_dma_loop;
- }
- if ((ahc->flags & AHC_INITIATORROLE) != 0) {
- test SSTAT1,PHASEMIS jz ultra2_dma_loop;
- }
- } else {
- test DFCNTRL, SCSIEN jnz ultra2_dma_loop;
- }
+ call idle_loop;
+ /*
+ * The transfer is complete if either the last segment
+ * completes or the target changes phase.
+ */
+ test SG_CACHE_SHADOW, LAST_SEG_DONE jnz ultra2_dmafinish;
+ if ((ahc->features & AHC_DT) == 0) {
+ if ((ahc->flags & AHC_TARGETROLE) != 0) {
+ /*
+ * As a target, we control the phases,
+ * so ignore PHASEMIS.
+ */
+ test SSTAT0, TARGET jnz ultra2_dma_loop;
+ }
+ if ((ahc->flags & AHC_INITIATORROLE) != 0) {
+ test SSTAT1,PHASEMIS jz ultra2_dma_loop;
+ }
+ } else {
+ test DFCNTRL, SCSIEN jnz ultra2_dma_loop;
+ }
ultra2_dmafinish:
- /*
- * The transfer has terminated either due to a phase
- * change, and/or the completion of the last segment.
- * We have two goals here. Do as much other work
- * as possible while the data fifo drains on a read
- * and respond as quickly as possible to the standard
- * messages (save data pointers/disconnect and command
- * complete) that usually follow a data phase.
- */
- if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
- /*
- * On chips with broken auto-flush, start
- * the flushing process now. We'll poke
- * the chip from time to time to keep the
- * flush process going as we complete the
- * data phase.
- */
- or DFCNTRL, FIFOFLUSH;
- }
- /*
- * We assume that, even though data may still be
- * transferring to the host, that the SCSI side of
- * the DMA engine is now in a static state. This
- * allows us to update our notion of where we are
- * in this transfer.
- *
- * If, by chance, we stopped before being able
- * to fetch additional segments for this transfer,
- * yet the last S/G was completely exhausted,
- * call our idle loop until it is able to load
- * another segment. This will allow us to immediately
- * pickup on the next segment on the next data phase.
- *
- * If we happened to stop on the last segment, then
- * our residual information is still correct from
- * the idle loop and there is no need to perform
- * any fixups.
- */
+ /*
+ * The transfer has terminated either due to a phase
+ * change, and/or the completion of the last segment.
+ * We have two goals here. Do as much other work
+ * as possible while the data fifo drains on a read
+ * and respond as quickly as possible to the standard
+ * messages (save data pointers/disconnect and command
+ * complete) that usually follow a data phase.
+ */
+ if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
+ /*
+ * On chips with broken auto-flush, start
+ * the flushing process now. We'll poke
+ * the chip from time to time to keep the
+ * flush process going as we complete the
+ * data phase.
+ */
+ or DFCNTRL, FIFOFLUSH;
+ }
+ /*
+ * We assume that, even though data may still be
+ * transferring to the host, that the SCSI side of
+ * the DMA engine is now in a static state. This
+ * allows us to update our notion of where we are
+ * in this transfer.
+ *
+ * If, by chance, we stopped before being able
+ * to fetch additional segments for this transfer,
+ * yet the last S/G was completely exhausted,
+ * call our idle loop until it is able to load
+ * another segment. This will allow us to immediately
+ * pickup on the next segment on the next data phase.
+ *
+ * If we happened to stop on the last segment, then
+ * our residual information is still correct from
+ * the idle loop and there is no need to perform
+ * any fixups.
+ */
ultra2_ensure_sg:
- test SG_CACHE_SHADOW, LAST_SEG jz ultra2_shvalid;
- /* Record if we've consumed all S/G entries */
- test SSTAT2, SHVALID jnz residuals_correct;
- or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
- jmp residuals_correct;
+ test SG_CACHE_SHADOW, LAST_SEG jz ultra2_shvalid;
+ /* Record if we've consumed all S/G entries */
+ test SSTAT2, SHVALID jnz residuals_correct;
+ or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
+ jmp residuals_correct;
ultra2_shvalid:
- test SSTAT2, SHVALID jnz sgptr_fixup;
- call idle_loop;
- jmp ultra2_ensure_sg;
+ test SSTAT2, SHVALID jnz sgptr_fixup;
+ call idle_loop;
+ jmp ultra2_ensure_sg;
sgptr_fixup:
- /*
- * Fixup the residual next S/G pointer. The S/G preload
- * feature of the chip allows us to load two elements
- * in addition to the currently active element. We
- * store the bottom byte of the next S/G pointer in
- * the SG_CACEPTR register so we can restore the
- * correct value when the DMA completes. If the next
- * sg ptr value has advanced to the point where higher
- * bytes in the address have been affected, fix them
- * too.
- */
- test SG_CACHE_SHADOW, 0x80 jz sgptr_fixup_done;
- test SCB_RESIDUAL_SGPTR[0], 0x80 jnz sgptr_fixup_done;
- add SCB_RESIDUAL_SGPTR[1], -1;
- adc SCB_RESIDUAL_SGPTR[2], -1;
- adc SCB_RESIDUAL_SGPTR[3], -1;
+ /*
+ * Fixup the residual next S/G pointer. The S/G preload
+ * feature of the chip allows us to load two elements
+ * in addition to the currently active element. We
+ * store the bottom byte of the next S/G pointer in
+ * the SG_CACEPTR register so we can restore the
+ * correct value when the DMA completes. If the next
+ * sg ptr value has advanced to the point where higher
+ * bytes in the address have been affected, fix them
+ * too.
+ */
+ test SG_CACHE_SHADOW, 0x80 jz sgptr_fixup_done;
+ test SCB_RESIDUAL_SGPTR[0], 0x80 jnz sgptr_fixup_done;
+ add SCB_RESIDUAL_SGPTR[1], -1;
+ adc SCB_RESIDUAL_SGPTR[2], -1;
+ adc SCB_RESIDUAL_SGPTR[3], -1;
sgptr_fixup_done:
- and SCB_RESIDUAL_SGPTR[0], SG_ADDR_MASK, SG_CACHE_SHADOW;
- clr DATA_COUNT_ODD;
- test SG_CACHE_SHADOW, ODD_SEG jz . + 2;
- or DATA_COUNT_ODD, 0x1;
- clr SCB_RESIDUAL_DATACNT[3]; /* We are not the last seg */
+ and SCB_RESIDUAL_SGPTR[0], SG_ADDR_MASK, SG_CACHE_SHADOW;
+ clr DATA_COUNT_ODD;
+ test SG_CACHE_SHADOW, ODD_SEG jz . + 2;
+ or DATA_COUNT_ODD, 0x1;
+ clr SCB_RESIDUAL_DATACNT[3]; /* We are not the last seg */
residuals_correct:
- /*
- * Go ahead and shut down the DMA engine now.
- * In the future, we'll want to handle end of
- * transfer messages prior to doing this, but this
- * requires similar restructuring for pre-ULTRA2
- * controllers.
- */
- test DMAPARAMS, DIRECTION jnz ultra2_fifoempty;
+ /*
+ * Go ahead and shut down the DMA engine now.
+ * In the future, we'll want to handle end of
+ * transfer messages prior to doing this, but this
+ * requires similar restructuring for pre-ULTRA2
+ * controllers.
+ */
+ test DMAPARAMS, DIRECTION jnz ultra2_fifoempty;
ultra2_fifoflush:
- if ((ahc->features & AHC_DT) == 0) {
- if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
- /*
- * On Rev A of the aic7890, the autoflush
- * feature doesn't function correctly.
- * Perform an explicit manual flush. During
- * a manual flush, the FIFOEMP bit becomes
- * true every time the PCI FIFO empties
- * regardless of the state of the SCSI FIFO.
- * It can take up to 4 clock cycles for the
- * SCSI FIFO to get data into the PCI FIFO
- * and for FIFOEMP to de-assert. Here we
- * guard against this condition by making
- * sure the FIFOEMP bit stays on for 5 full
- * clock cycles.
- */
- or DFCNTRL, FIFOFLUSH;
- test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
- test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
- test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
- test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
- }
- test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
- } else {
- /*
- * We enable the auto-ack feature on DT capable
- * controllers. This means that the controller may
- * have already transferred some overrun bytes into
- * the data FIFO and acked them on the bus. The only
- * way to detect this situation is to wait for
- * LAST_SEG_DONE to come true on a completed transfer
- * and then test to see if the data FIFO is non-empty.
- */
- test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 4;
- test SG_CACHE_SHADOW, LAST_SEG_DONE jz .;
- test DFSTATUS, FIFOEMP jnz ultra2_fifoempty;
- /* Overrun */
- jmp data_phase_loop;
- test DFSTATUS, FIFOEMP jz .;
- }
+ if ((ahc->features & AHC_DT) == 0) {
+ if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
+ /*
+ * On Rev A of the aic7890, the autoflush
+ * feature doesn't function correctly.
+ * Perform an explicit manual flush. During
+ * a manual flush, the FIFOEMP bit becomes
+ * true every time the PCI FIFO empties
+ * regardless of the state of the SCSI FIFO.
+ * It can take up to 4 clock cycles for the
+ * SCSI FIFO to get data into the PCI FIFO
+ * and for FIFOEMP to de-assert. Here we
+ * guard against this condition by making
+ * sure the FIFOEMP bit stays on for 5 full
+ * clock cycles.
+ */
+ or DFCNTRL, FIFOFLUSH;
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ }
+ test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+ } else {
+ /*
+ * We enable the auto-ack feature on DT capable
+ * controllers. This means that the controller may
+ * have already transferred some overrun bytes into
+ * the data FIFO and acked them on the bus. The only
+ * way to detect this situation is to wait for
+ * LAST_SEG_DONE to come true on a completed transfer
+ * and then test to see if the data FIFO is non-empty.
+ */
+ test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 4;
+ test SG_CACHE_SHADOW, LAST_SEG_DONE jz .;
+ test DFSTATUS, FIFOEMP jnz ultra2_fifoempty;
+ /* Overrun */
+ jmp data_phase_loop;
+ test DFSTATUS, FIFOEMP jz .;
+ }
ultra2_fifoempty:
- /* Don't clobber an inprogress host data transfer */
- test DFSTATUS, MREQPEND jnz ultra2_fifoempty;
+ /* Don't clobber an inprogress host data transfer */
+ test DFSTATUS, MREQPEND jnz ultra2_fifoempty;
ultra2_dmahalt:
- and DFCNTRL, ~(SCSIEN|HDMAEN);
- test DFCNTRL, SCSIEN|HDMAEN jnz .;
- if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
- /*
- * Keep HHADDR cleared for future, 32bit addressed
- * only, DMA operations.
- *
- * Due to bayonette style S/G handling, our residual
- * data must be "fixed up" once the transfer is halted.
- * Here we fixup the HSHADDR stored in the high byte
- * of the residual data cnt. By postponing the fixup,
- * we can batch the clearing of HADDR with the fixup.
- * If we halted on the last segment, the residual is
- * already correct. If we are not on the last
- * segment, copy the high address directly from HSHADDR.
- * We don't need to worry about maintaining the
- * SG_LAST_SEG flag as it will always be false in the
- * case where an update is required.
- */
- or DSCOMMAND1, HADDLDSEL0;
- test SG_CACHE_SHADOW, LAST_SEG jnz . + 2;
- mov SCB_RESIDUAL_DATACNT[3], SHADDR;
- clr HADDR;
- and DSCOMMAND1, ~HADDLDSEL0;
- }
+ and DFCNTRL, ~(SCSIEN|HDMAEN);
+ test DFCNTRL, SCSIEN|HDMAEN jnz .;
+ if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
+ /*
+ * Keep HHADDR cleared for future, 32bit addressed
+ * only, DMA operations.
+ *
+ * Due to bayonette style S/G handling, our residual
+ * data must be "fixed up" once the transfer is halted.
+ * Here we fixup the HSHADDR stored in the high byte
+ * of the residual data cnt. By postponing the fixup,
+ * we can batch the clearing of HADDR with the fixup.
+ * If we halted on the last segment, the residual is
+ * already correct. If we are not on the last
+ * segment, copy the high address directly from HSHADDR.
+ * We don't need to worry about maintaining the
+ * SG_LAST_SEG flag as it will always be false in the
+ * case where an update is required.
+ */
+ or DSCOMMAND1, HADDLDSEL0;
+ test SG_CACHE_SHADOW, LAST_SEG jnz . + 2;
+ mov SCB_RESIDUAL_DATACNT[3], SHADDR;
+ clr HADDR;
+ and DSCOMMAND1, ~HADDLDSEL0;
+ }
} else {
- /* If we are the last SG block, tell the hardware. */
- if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
- && ahc->pci_cachesize != 0) {
- test MWI_RESIDUAL, 0xFF jnz dma_mid_sg;
- }
- test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg;
- if ((ahc->flags & AHC_TARGETROLE) != 0) {
- test SSTAT0, TARGET jz dma_last_sg;
- if ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0) {
- test DMAPARAMS, DIRECTION jz dma_mid_sg;
- }
+ /* If we are the last SG block, tell the hardware. */
+ if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
+ && ahc->pci_cachesize != 0) {
+ test MWI_RESIDUAL, 0xFF jnz dma_mid_sg;
+ }
+ test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg;
+ if ((ahc->flags & AHC_TARGETROLE) != 0) {
+ test SSTAT0, TARGET jz dma_last_sg;
+ if ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0) {
+ test DMAPARAMS, DIRECTION jz dma_mid_sg;
+ }
}
dma_last_sg:
and DMAPARAMS, ~WIDEODD;
dma_mid_sg:
- /* Start DMA data transfer. */
+ /* Start DMA data transfer. */
mov DFCNTRL, DMAPARAMS;
dma_loop:
- if ((ahc->features & AHC_CMD_CHAN) != 0) {
- call idle_loop;
- }
- test SSTAT0,DMADONE jnz dma_dmadone;
- test SSTAT1,PHASEMIS jz dma_loop; /* ie. underrun */
+ if ((ahc->features & AHC_CMD_CHAN) != 0) {
+ call idle_loop;
+ }
+ test SSTAT0,DMADONE jnz dma_dmadone;
+ test SSTAT1,PHASEMIS jz dma_loop; /* ie. underrun */
dma_phasemis:
- /*
- * 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.
- */
+ /*
+ * 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;
+ test DFCNTRL,DIRECTION jnz dma_fifoempty;
dma_fifoflush:
- test DFSTATUS,FIFOEMP jz 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 off the DMA and make sure that the DMA
- * hardware has actually stopped. Touching the DMA
- * counters, etc. while a DMA is active will result
- * in an ILLSADDR exception.
- */
+ /* Don't clobber an inprogress host data transfer */
+ test DFSTATUS, MREQPEND jnz dma_fifoempty;
+
+ /*
+ * Now shut off the DMA and make sure that the DMA
+ * hardware has actually stopped. Touching the DMA
+ * counters, etc. while a DMA is active will result
+ * in an ILLSADDR exception.
+ */
dma_dmadone:
- and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
+ and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
dma_halt:
- /*
- * Some revisions of the aic78XX 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 drain
- * the prefetched but unused data from the data fifo until
- * there is space for the input latch to drain.
- */
- if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0) {
- mov NONE, DFDAT;
- }
- test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt;
-
- /* See if we have completed this last segment */
- test STCNT[0], 0xff jnz data_phase_finish;
- test STCNT[1], 0xff jnz data_phase_finish;
- test STCNT[2], 0xff jnz data_phase_finish;
-
- /*
- * Advance the scatter-gather pointers if needed
- */
- if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
- && ahc->pci_cachesize != 0) {
- test MWI_RESIDUAL, 0xFF jz no_mwi_resid;
- /*
- * Reload HADDR from SHADDR and setup the
- * count to be the size of our residual.
- */
- if ((ahc->features & AHC_CMD_CHAN) != 0) {
- bmov HADDR, SHADDR, 4;
- mov HCNT, MWI_RESIDUAL;
- bmov HCNT[1], ALLZEROS, 2;
- } else {
- mvi DINDEX, HADDR;
- mvi SHADDR call bcopy_4;
- mov MWI_RESIDUAL call set_hcnt;
- }
- clr MWI_RESIDUAL;
- jmp sg_load_done;
+ /*
+ * Some revisions of the aic78XX 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 drain
+ * the prefetched but unused data from the data fifo until
+ * there is space for the input latch to drain.
+ */
+ if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0) {
+ mov NONE, DFDAT;
+ }
+ test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt;
+
+ /* See if we have completed this last segment */
+ test STCNT[0], 0xff jnz data_phase_finish;
+ test STCNT[1], 0xff jnz data_phase_finish;
+ test STCNT[2], 0xff jnz data_phase_finish;
+
+ /*
+ * Advance the scatter-gather pointers if needed
+ */
+ if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
+ && ahc->pci_cachesize != 0) {
+ test MWI_RESIDUAL, 0xFF jz no_mwi_resid;
+ /*
+ * Reload HADDR from SHADDR and setup the
+ * count to be the size of our residual.
+ */
+ if ((ahc->features & AHC_CMD_CHAN) != 0) {
+ bmov HADDR, SHADDR, 4;
+ mov HCNT, MWI_RESIDUAL;
+ bmov HCNT[1], ALLZEROS, 2;
+ } else {
+ mvi DINDEX, HADDR;
+ mvi SHADDR call bcopy_4;
+ mov MWI_RESIDUAL call set_hcnt;
+ }
+ clr MWI_RESIDUAL;
+ jmp sg_load_done;
no_mwi_resid:
- }
- test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz sg_load;
- or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
- jmp data_phase_finish;
+ }
+ test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz sg_load;
+ or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
+ jmp data_phase_finish;
sg_load:
/*
- * Load the next SG element's data address and length
- * into the DMA engine. If we don't have hardware
- * to perform a prefetch, we'll have to fetch the
- * segment from host memory first.
+ * Load the next SG element's data address and length
+ * into the DMA engine. If we don't have hardware
+ * to perform a prefetch, we'll have to fetch the
+ * segment from host memory first.
*/
- if ((ahc->features & AHC_CMD_CHAN) != 0) {
- /* Wait for the idle loop to complete */
- test CCSGCTL, CCSGEN jz . + 3;
- call idle_loop;
- test CCSGCTL, CCSGEN jnz . - 1;
- bmov HADDR, CCSGRAM, 7;
- /*
- * Workaround for flaky external SCB RAM
- * on certain aic7895 setups. It seems
- * unable to handle direct transfers from
- * S/G ram to certain SCB locations.
- */
- mov SINDEX, CCSGRAM;
- mov SCB_RESIDUAL_DATACNT[3], SINDEX;
- } else {
- if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
- mov ALLZEROS call set_hhaddr;
- }
- mvi DINDEX, HADDR;
- mvi SCB_RESIDUAL_SGPTR call bcopy_4;
-
- mvi SG_SIZEOF call set_hcnt;
-
- or DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
-
- call dma_finish;
-
- mvi DINDEX, HADDR;
- call dfdat_in_7;
- mov SCB_RESIDUAL_DATACNT[3], DFDAT;
- }
-
- if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
- mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr;
-
- /*
- * The lowest address byte must be loaded
- * last as it triggers the computation of
- * some items in the PCI block. The ULTRA2
- * chips do this on PRELOAD.
- */
- mov HADDR, HADDR;
- }
- if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
- && ahc->pci_cachesize != 0) {
- call calc_mwi_residual;
- }
-
- /* Point to the new next sg in memory */
- call sg_advance;
+ if ((ahc->features & AHC_CMD_CHAN) != 0) {
+ /* Wait for the idle loop to complete */
+ test CCSGCTL, CCSGEN jz . + 3;
+ call idle_loop;
+ test CCSGCTL, CCSGEN jnz . - 1;
+ bmov HADDR, CCSGRAM, 7;
+ /*
+ * Workaround for flaky external SCB RAM
+ * on certain aic7895 setups. It seems
+ * unable to handle direct transfers from
+ * S/G ram to certain SCB locations.
+ */
+ mov SINDEX, CCSGRAM;
+ mov SCB_RESIDUAL_DATACNT[3], SINDEX;
+ } else {
+ if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
+ mov ALLZEROS call set_hhaddr;
+ }
+ mvi DINDEX, HADDR;
+ mvi SCB_RESIDUAL_SGPTR call bcopy_4;
+
+ mvi SG_SIZEOF call set_hcnt;
+
+ or DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
+
+ call dma_finish;
+
+ mvi DINDEX, HADDR;
+ call dfdat_in_7;
+ mov SCB_RESIDUAL_DATACNT[3], DFDAT;
+ }
+
+ if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
+ mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr;
+
+ /*
+ * The lowest address byte must be loaded
+ * last as it triggers the computation of
+ * some items in the PCI block. The ULTRA2
+ * chips do this on PRELOAD.
+ */
+ mov HADDR, HADDR;
+ }
+ if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
+ && ahc->pci_cachesize != 0) {
+ call calc_mwi_residual;
+ }
+
+ /* Point to the new next sg in memory */
+ call sg_advance;
sg_load_done:
if ((ahc->features & AHC_CMD_CHAN) != 0) {
@@ -1223,112 +1247,121 @@ sg_load_done:
} else {
call set_stcnt_from_hcnt;
}
- /* Track odd'ness */
- test HCNT[0], 0x1 jz . + 2;
- xor DATA_COUNT_ODD, 0x1;
+ /* Track odd'ness */
+ test HCNT[0], 0x1 jz . + 2;
+ xor DATA_COUNT_ODD, 0x1;
- if ((ahc->flags & AHC_TARGETROLE) != 0) {
- test SSTAT0, TARGET jnz data_phase_loop;
- }
+ if ((ahc->flags & AHC_TARGETROLE) != 0) {
+ test SSTAT0, TARGET jnz data_phase_loop;
+ }
}
data_phase_finish:
- /*
- * If the target has left us in data phase, loop through
- * the dma code again. In the case of ULTRA2 adapters,
- * we should only loop if there is a data overrun. For
- * all other adapters, we'll loop after each S/G element
- * is loaded as well as if there is an overrun.
- */
- if ((ahc->flags & AHC_TARGETROLE) != 0) {
- test SSTAT0, TARGET jnz data_phase_done;
- }
- if ((ahc->flags & AHC_INITIATORROLE) != 0) {
- test SSTAT1, REQINIT jz .;
- if ((ahc->features & AHC_DT) == 0) {
- test SSTAT1,PHASEMIS jz data_phase_loop;
- } else {
- test SCSIPHASE, DATA_PHASE_MASK jnz data_phase_loop;
- }
- }
+ /*
+ * If the target has left us in data phase, loop through
+ * the DMA code again. In the case of ULTRA2 adapters,
+ * we should only loop if there is a data overrun. For
+ * all other adapters, we'll loop after each S/G element
+ * is loaded as well as if there is an overrun.
+ */
+ if ((ahc->flags & AHC_TARGETROLE) != 0) {
+ test SSTAT0, TARGET jnz data_phase_done;
+ }
+ if ((ahc->flags & AHC_INITIATORROLE) != 0) {
+ test SSTAT1, REQINIT jz .;
+ if ((ahc->features & AHC_DT) == 0) {
+ test SSTAT1,PHASEMIS jz data_phase_loop;
+ } else {
+ test SCSIPHASE, DATA_PHASE_MASK jnz data_phase_loop;
+ }
+ }
data_phase_done:
- /*
- * 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 ((ahc->features & AHC_CMD_CHAN) != 0) {
- /* Kill off any pending prefetch */
- call disable_ccsgen;
- }
-
- if ((ahc->features & AHC_ULTRA2) == 0) {
- /*
- * Clear the high address byte so that all other DMA
- * operations, which use 32bit addressing, can assume
- * HHADDR is 0.
- */
- if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
- mov ALLZEROS call set_hhaddr;
- }
- }
-
- /*
- * Update our residual information before the information is
- * lost by some other type of SCSI I/O (e.g. PIO). If we have
- * transferred all data, no update is needed.
- *
- */
- test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jnz residual_update_done;
- if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
- && ahc->pci_cachesize != 0) {
- if ((ahc->features & AHC_CMD_CHAN) != 0) {
- test MWI_RESIDUAL, 0xFF jz bmov_resid;
- }
- mov A, MWI_RESIDUAL;
- add SCB_RESIDUAL_DATACNT[0], A, STCNT[0];
- clr A;
- adc SCB_RESIDUAL_DATACNT[1], A, STCNT[1];
- adc SCB_RESIDUAL_DATACNT[2], A, STCNT[2];
- clr MWI_RESIDUAL;
- if ((ahc->features & AHC_CMD_CHAN) != 0) {
- jmp . + 2;
+ /*
+ * 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 ((ahc->features & AHC_CMD_CHAN) != 0) {
+ /* Kill off any pending prefetch */
+ call disable_ccsgen;
+ }
+
+ if ((ahc->features & AHC_ULTRA2) == 0) {
+ /*
+ * Clear the high address byte so that all other DMA
+ * operations, which use 32bit addressing, can assume
+ * HHADDR is 0.
+ */
+ if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
+ mov ALLZEROS call set_hhaddr;
+ }
+ }
+
+ /*
+ * Update our residual information before the information is
+ * lost by some other type of SCSI I/O (e.g. PIO). If we have
+ * transferred all data, no update is needed.
+ *
+ */
+ test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jnz residual_update_done;
+ if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
+ && ahc->pci_cachesize != 0) {
+ if ((ahc->features & AHC_CMD_CHAN) != 0) {
+ test MWI_RESIDUAL, 0xFF jz bmov_resid;
+ }
+ mov A, MWI_RESIDUAL;
+ add SCB_RESIDUAL_DATACNT[0], A, STCNT[0];
+ clr A;
+ adc SCB_RESIDUAL_DATACNT[1], A, STCNT[1];
+ adc SCB_RESIDUAL_DATACNT[2], A, STCNT[2];
+ clr MWI_RESIDUAL;
+ if ((ahc->features & AHC_CMD_CHAN) != 0) {
+ jmp . + 2;
bmov_resid:
- bmov SCB_RESIDUAL_DATACNT, STCNT, 3;
- }
- } else if ((ahc->features & AHC_CMD_CHAN) != 0) {
- bmov SCB_RESIDUAL_DATACNT, STCNT, 3;
+ bmov SCB_RESIDUAL_DATACNT, STCNT, 3;
+ }
+ } else if ((ahc->features & AHC_CMD_CHAN) != 0) {
+ bmov SCB_RESIDUAL_DATACNT, STCNT, 3;
} else {
- mov SCB_RESIDUAL_DATACNT[0], STCNT[0];
- mov SCB_RESIDUAL_DATACNT[1], STCNT[1];
- mov SCB_RESIDUAL_DATACNT[2], STCNT[2];
+ mov SCB_RESIDUAL_DATACNT[0], STCNT[0];
+ mov SCB_RESIDUAL_DATACNT[1], STCNT[1];
+ mov SCB_RESIDUAL_DATACNT[2], STCNT[2];
}
residual_update_done:
- /*
- * Since we've been through a data phase, the SCB_RESID* fields
- * are now initialized. Clear the full residual flag.
- */
- and SCB_SGPTR[0], ~SG_FULL_RESID;
+ /*
+ * Since we've been through a data phase, the SCB_RESID* fields
+ * are now initialized. Clear the full residual flag.
+ */
+ and SCB_SGPTR[0], ~SG_FULL_RESID;
if ((ahc->features & AHC_ULTRA2) != 0) {
- /* Clear the channel in case we return to data phase later */
- or SXFRCTL0, CLRSTCNT|CLRCHN;
+ /* Clear the channel in case we return to data phase later */
+ or SXFRCTL0, CLRSTCNT|CLRCHN;
or SXFRCTL0, CLRSTCNT|CLRCHN;
}
- if ((ahc->flags & AHC_TARGETROLE) != 0) {
+ if ((ahc->flags & AHC_TARGETROLE) != 0) {
test SEQ_FLAGS, DPHASE_PENDING jz ITloop;
and SEQ_FLAGS, ~DPHASE_PENDING;
/*
* For data-in phases, wait for any pending acks from the
- * initiator before changing phase.
+ * initiator before changing phase. We only need to
+ * send Ignore Wide Residue messages for data-in phases.
*/
test DFCNTRL, DIRECTION jz target_ITloop;
test SSTAT1, REQINIT jnz .;
+ test DATA_COUNT_ODD, 0x1 jz target_ITloop;
+ test SCSIRATE, WIDEXFER jz target_ITloop;
+ /*
+ * Issue an Ignore Wide Residue Message.
+ */
+ mvi P_MESGIN|BSYO call change_phase;
+ mvi MSG_IGN_WIDE_RESIDUE call target_outb;
+ mvi 1 call target_outb;
jmp target_ITloop;
- } else {
- jmp ITloop;
+ } else {
+ jmp ITloop;
}
if ((ahc->flags & AHC_INITIATORROLE) != 0) {
@@ -1336,95 +1369,99 @@ if ((ahc->flags & AHC_INITIATORROLE) != 0) {
* Command phase. Set up the DMA registers and let 'er rip.
*/
p_command:
- test SEQ_FLAGS,IDENTIFY_SEEN jnz p_command_okay;
- mvi NO_IDENT jmp set_seqint;
+ test SEQ_FLAGS, NOT_IDENTIFIED jz p_command_okay;
+ mvi PROTO_VIOLATION call set_seqint;
p_command_okay:
- if ((ahc->features & AHC_ULTRA2) != 0) {
- bmov HCNT[0], SCB_CDB_LEN, 1;
- bmov HCNT[1], ALLZEROS, 2;
- mvi SG_CACHE_PRE, LAST_SEG;
- } else if ((ahc->features & AHC_CMD_CHAN) != 0) {
- bmov STCNT[0], SCB_CDB_LEN, 1;
- bmov STCNT[1], ALLZEROS, 2;
- } else {
- mov STCNT[0], SCB_CDB_LEN;
- clr STCNT[1];
- clr STCNT[2];
- }
- add NONE, -13, SCB_CDB_LEN;
- mvi SCB_CDB_STORE jnc p_command_embedded;
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ bmov HCNT[0], SCB_CDB_LEN, 1;
+ bmov HCNT[1], ALLZEROS, 2;
+ mvi SG_CACHE_PRE, LAST_SEG;
+ } else if ((ahc->features & AHC_CMD_CHAN) != 0) {
+ bmov STCNT[0], SCB_CDB_LEN, 1;
+ bmov STCNT[1], ALLZEROS, 2;
+ } else {
+ mov STCNT[0], SCB_CDB_LEN;
+ clr STCNT[1];
+ clr STCNT[2];
+ }
+ add NONE, -13, SCB_CDB_LEN;
+ mvi SCB_CDB_STORE jnc p_command_embedded;
p_command_from_host:
- if ((ahc->features & AHC_ULTRA2) != 0) {
- bmov HADDR[0], SCB_CDB_PTR, 4;
- mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION);
- } else {
- if ((ahc->features & AHC_CMD_CHAN) != 0) {
- bmov HADDR[0], SCB_CDB_PTR, 4;
- bmov HCNT, STCNT, 3;
- } else {
- mvi DINDEX, HADDR;
- mvi SCB_CDB_PTR call bcopy_4;
- mov SCB_CDB_LEN call set_hcnt;
- }
- mvi DFCNTRL, (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET);
- }
- jmp p_command_loop;
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ bmov HADDR[0], SCB_CDB_PTR, 4;
+ mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION);
+ } else {
+ if ((ahc->features & AHC_CMD_CHAN) != 0) {
+ bmov HADDR[0], SCB_CDB_PTR, 4;
+ bmov HCNT, STCNT, 3;
+ } else {
+ mvi DINDEX, HADDR;
+ mvi SCB_CDB_PTR call bcopy_4;
+ mov SCB_CDB_LEN call set_hcnt;
+ }
+ mvi DFCNTRL, (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET);
+ }
+ jmp p_command_xfer;
p_command_embedded:
- /*
- * The data fifo seems to require 4 byte aligned
- * transfers from the sequencer. Force this to
- * be the case by clearing HADDR[0] even though
+ /*
+ * The data fifo seems to require 4 byte aligned
+ * transfers from the sequencer. Force this to
+ * be the case by clearing HADDR[0] even though
* we aren't going to touch host memory.
- */
- clr HADDR[0];
- if ((ahc->features & AHC_ULTRA2) != 0) {
- mvi DFCNTRL, (PRELOADEN|SCSIEN|DIRECTION);
- bmov DFDAT, SCB_CDB_STORE, 12;
- } else if ((ahc->features & AHC_CMD_CHAN) != 0) {
- if ((ahc->flags & AHC_SCB_BTT) != 0) {
- /*
- * On the 7895 the data FIFO will
- * get corrupted if you try to dump
- * data from external SCB memory into
- * the FIFO while it is enabled. So,
- * fill the fifo and then enable SCSI
- * transfers.
- */
- mvi DFCNTRL, (DIRECTION|FIFORESET);
+ */
+ clr HADDR[0];
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ mvi DFCNTRL, (PRELOADEN|SCSIEN|DIRECTION);
+ bmov DFDAT, SCB_CDB_STORE, 12;
+ } else if ((ahc->features & AHC_CMD_CHAN) != 0) {
+ if ((ahc->flags & AHC_SCB_BTT) != 0) {
+ /*
+ * On the 7895 the data FIFO will
+ * get corrupted if you try to dump
+ * data from external SCB memory into
+ * the FIFO while it is enabled. So,
+ * fill the fifo and then enable SCSI
+ * transfers.
+ */
+ mvi DFCNTRL, (DIRECTION|FIFORESET);
} else {
mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET);
}
- bmov DFDAT, SCB_CDB_STORE, 12;
- if ((ahc->flags & AHC_SCB_BTT) != 0) {
- mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFOFLUSH);
- } else {
- or DFCNTRL, FIFOFLUSH;
+ bmov DFDAT, SCB_CDB_STORE, 12;
+ if ((ahc->flags & AHC_SCB_BTT) != 0) {
+ mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFOFLUSH);
+ } else {
+ or DFCNTRL, FIFOFLUSH;
}
} else {
- mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET);
- call copy_to_fifo_6;
- call copy_to_fifo_6;
- or DFCNTRL, FIFOFLUSH;
- }
-p_command_loop:
- if ((ahc->features & AHC_DT) == 0) {
- test SSTAT0, SDONE jnz . + 2;
- test SSTAT1, PHASEMIS jz p_command_loop;
- /*
- * Wait for our ACK to go-away on it's own
- * instead of being killed by SCSIEN getting cleared.
- */
- test SCSISIGI, ACKI jnz .;
- } else {
- test DFCNTRL, SCSIEN jnz p_command_loop;
- }
+ mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET);
+ call copy_to_fifo_6;
+ call copy_to_fifo_6;
+ or DFCNTRL, FIFOFLUSH;
+ }
+p_command_xfer:
+ and SEQ_FLAGS, ~NO_CDB_SENT;
+ if ((ahc->features & AHC_DT) == 0) {
+ test SSTAT0, SDONE jnz . + 2;
+ test SSTAT1, PHASEMIS jz . - 1;
+ /*
+ * Wait for our ACK to go-away on it's own
+ * instead of being killed by SCSIEN getting cleared.
+ */
+ test SCSISIGI, ACKI jnz .;
+ } else {
+ test DFCNTRL, SCSIEN jnz .;
+ }
+ test SSTAT0, SDONE jnz p_command_successful;
+ /*
+ * Don't allow a data phase if the command
+ * was not fully transferred.
+ */
+ or SEQ_FLAGS, NO_CDB_SENT;
+p_command_successful:
and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz .;
- if ((ahc->features & AHC_ULTRA2) != 0) {
- /* Drop any residual from the S/G Preload queue */
- or SXFRCTL0, CLRSTCNT;
- }
jmp ITloop;
/*
@@ -1432,10 +1469,10 @@ p_command_loop:
* and store it into the SCB.
*/
p_status:
- test SEQ_FLAGS,IDENTIFY_SEEN jnz p_status_okay;
- mvi NO_IDENT jmp set_seqint;
+ test SEQ_FLAGS, NOT_IDENTIFIED jnz mesgin_proto_violation;
p_status_okay:
- mov SCB_SCSI_STATUS, SCSIDATL;
+ mov SCB_SCSI_STATUS, SCSIDATL;
+ or SCB_CONTROL, STATUS_RCVD;
jmp ITloop;
/*
@@ -1463,20 +1500,20 @@ p_status_okay:
* reason.
*/
p_mesgout_retry:
- /* Turn on ATN for the retry */
- if ((ahc->features & AHC_DT) == 0) {
- or SCSISIGO, ATNO, LASTPHASE;
- } else {
- mvi SCSISIGO, ATNO;
- }
+ /* Turn on ATN for the retry */
+ if ((ahc->features & AHC_DT) == 0) {
+ or SCSISIGO, ATNO, LASTPHASE;
+ } else {
+ mvi SCSISIGO, ATNO;
+ }
p_mesgout:
mov SINDEX, MSG_OUT;
cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
test SCB_CONTROL,MK_MESSAGE jnz host_message_loop;
p_mesgout_identify:
- or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SCB_LUN;
- test SCB_CONTROL, DISCENB jnz . + 2;
- and SINDEX, ~DISCENB;
+ or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SCB_LUN;
+ test SCB_CONTROL, DISCENB jnz . + 2;
+ and SINDEX, ~DISCENB;
/*
* 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.
@@ -1526,7 +1563,7 @@ p_mesgin:
cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs;
cmp ALLZEROS,A je mesgin_complete;
cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs;
- cmp A,MSG_IGN_WIDE_RESIDUE je mesgin_ign_wide_residue;
+ cmp A,MSG_IGN_WIDE_RESIDUE je mesgin_ign_wide_residue;
cmp A,MSG_NOOP je mesgin_done;
/*
@@ -1539,30 +1576,32 @@ p_mesgin:
* shouldn't hurt, but why do it twice...
*/
host_message_loop:
- mvi HOST_MSG_LOOP call set_seqint;
+ mvi HOST_MSG_LOOP call set_seqint;
call phase_lock;
cmp RETURN_1, EXIT_MSG_LOOP je ITloop + 1;
jmp host_message_loop;
mesgin_ign_wide_residue:
if ((ahc->features & AHC_WIDE) != 0) {
- test SCSIRATE, WIDEXFER jz mesgin_reject;
- /* Pull the residue byte */
- mvi ARG_1 call inb_next;
- cmp ARG_1, 0x01 jne mesgin_reject;
- test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 2;
- test DATA_COUNT_ODD, 0x1 jz mesgin_done;
- mvi IGN_WIDE_RES call set_seqint;
- jmp mesgin_done;
+ test SCSIRATE, WIDEXFER jz mesgin_reject;
+ /* Pull the residue byte */
+ mvi ARG_1 call inb_next;
+ cmp ARG_1, 0x01 jne mesgin_reject;
+ test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 2;
+ test DATA_COUNT_ODD, 0x1 jz mesgin_done;
+ mvi IGN_WIDE_RES call set_seqint;
+ jmp mesgin_done;
}
+mesgin_proto_violation:
+ mvi PROTO_VIOLATION call set_seqint;
+ jmp mesgin_done;
mesgin_reject:
- mvi MSG_MESSAGE_REJECT call mk_mesg;
+ mvi MSG_MESSAGE_REJECT call mk_mesg;
mesgin_done:
mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
jmp ITloop;
-mesgin_complete:
/*
* We received a "command complete" message. Put the SCB_TAG into the QOUTFIFO,
* and trigger a completion interrupt. Before doing so, check to see if there
@@ -1575,40 +1614,62 @@ mesgin_complete:
* it to the QINFIFO and tell us not to post to the QOUTFIFO by setting
* RETURN_1 to SEND_SENSE.
*/
+mesgin_complete:
-/*
- * If ATN is raised, we still want to give the target a message.
- * Perhaps there was a parity error on this last message byte.
- * Either way, the target should take us to message out phase
- * and then attempt to complete the command again. We should use a
- * critical section here to guard against a timeout triggering
- * for this command and setting ATN while we are still processing
- * the completion.
- test SCSISIGI, ATNI jnz mesgin_done;
- */
+ /*
+ * If ATN is raised, we still want to give the target a message.
+ * Perhaps there was a parity error on this last message byte.
+ * Either way, the target should take us to message out phase
+ * and then attempt to complete the command again. We should use a
+ * critical section here to guard against a timeout triggering
+ * for this command and setting ATN while we are still processing
+ * the completion.
+ test SCSISIGI, ATNI jnz mesgin_done;
+ */
-/*
- * See if we attempted to deliver a message but the target ingnored us.
- */
- test SCB_CONTROL, MK_MESSAGE jz . + 2;
- mvi MKMSG_FAILED call set_seqint;
+ /*
+ * If we are identified and have successfully sent the CDB,
+ * any status will do. Optimize this fast path.
+ */
+ test SCB_CONTROL, STATUS_RCVD jz mesgin_proto_violation;
+ test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT jz complete_accepted;
-/*
- * Check for residuals
- */
- test SCB_SGPTR, SG_LIST_NULL jnz check_status;/* No xfer */
- test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */
- test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;
+ /*
+ * If the target never sent an identify message but instead went
+ * to mesgin to give an invalid message, let the host abort us.
+ */
+ test SEQ_FLAGS, NOT_IDENTIFIED jnz mesgin_proto_violation;
+
+ /*
+ * If we recevied good status but never successfully sent the
+ * cdb, abort the command.
+ */
+ test SCB_SCSI_STATUS,0xff jnz complete_accepted;
+ test SEQ_FLAGS, NO_CDB_SENT jnz mesgin_proto_violation;
+
+complete_accepted:
+ /*
+ * See if we attempted to deliver a message but the target ingnored us.
+ */
+ test SCB_CONTROL, MK_MESSAGE jz . + 2;
+ mvi MKMSG_FAILED call set_seqint;
+
+ /*
+ * Check for residuals
+ */
+ test SCB_SGPTR, SG_LIST_NULL jnz check_status;/* No xfer */
+ test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */
+ test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;
check_status:
- test SCB_SCSI_STATUS,0xff jz complete; /* Good Status? */
+ test SCB_SCSI_STATUS,0xff jz complete; /* Good Status? */
upload_scb:
- or SCB_SGPTR, SG_RESID_VALID;
+ or SCB_SGPTR, SG_RESID_VALID;
mvi DMAPARAMS, FIFORESET;
mov SCB_TAG call dma_scb;
- test SCB_SCSI_STATUS, 0xff jz complete; /* Just a residual? */
- mvi BAD_STATUS call set_seqint; /* let driver know */
+ test SCB_SCSI_STATUS, 0xff jz complete; /* Just a residual? */
+ mvi BAD_STATUS call set_seqint; /* let driver know */
cmp RETURN_1, SEND_SENSE jne complete;
- call add_scb_to_free_list;
+ call add_scb_to_free_list;
jmp await_busfree;
complete:
mov SCB_TAG call complete_post;
@@ -1639,25 +1700,25 @@ if ((ahc->flags & AHC_INITIATORROLE) != 0) {
* a reselction.
*/
mesgin_disconnect:
- /*
- * If ATN is raised, we still want to give the target a message.
- * Perhaps there was a parity error on this last message byte
- * or we want to abort this command. Either way, the target
- * should take us to message out phase and then attempt to
- * disconnect again.
- * XXX - Wait for more testing.
- test SCSISIGI, ATNI jnz mesgin_done;
- */
-
- test SCSISIGI, ATNI jnz mesgin_done;
+ /*
+ * If ATN is raised, we still want to give the target a message.
+ * Perhaps there was a parity error on this last message byte
+ * or we want to abort this command. Either way, the target
+ * should take us to message out phase and then attempt to
+ * disconnect again.
+ * XXX - Wait for more testing.
+ test SCSISIGI, ATNI jnz mesgin_done;
+ */
+ test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT
+ jnz mesgin_proto_violation;
or SCB_CONTROL,DISCONNECTED;
- if ((ahc->flags & AHC_PAGESCBS) != 0) {
- call add_scb_to_disc_list;
- }
- test SCB_CONTROL, TAG_ENB jnz await_busfree;
- mov ARG_1, SCB_TAG;
- mov SAVED_LUN, SCB_LUN;
- mov SCB_SCSIID call set_busy_target;
+ if ((ahc->flags & AHC_PAGESCBS) != 0) {
+ call add_scb_to_disc_list;
+ }
+ test SCB_CONTROL, TAG_ENB jnz await_busfree;
+ mov ARG_1, SCB_TAG;
+ mov SAVED_LUN, SCB_LUN;
+ mov SCB_SCSIID call set_busy_target;
jmp await_busfree;
/*
@@ -1671,53 +1732,54 @@ mesgin_disconnect:
* chips, SHADDR increments with every bus transaction, even PIO.
*/
mesgin_sdptrs:
- if ((ahc->features & AHC_ULTRA2) != 0) {
- mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
- test SEQ_FLAGS, DPHASE jz ITloop;
- } else {
- test SEQ_FLAGS, DPHASE jz mesgin_done;
- }
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
+ test SEQ_FLAGS, DPHASE jz ITloop;
+ } else {
+ test SEQ_FLAGS, DPHASE jz mesgin_done;
+ }
/*
- * If we are asked to save our position at the end of the
- * transfer, just mark us at the end rather than perform a
- * full save.
- */
- test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz mesgin_sdptrs_full;
- or SCB_SGPTR, SG_LIST_NULL;
- if ((ahc->features & AHC_ULTRA2) != 0) {
- jmp ITloop;
- } else {
- jmp mesgin_done;
- }
+ * If we are asked to save our position at the end of the
+ * transfer, just mark us at the end rather than perform a
+ * full save.
+ */
+ test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz mesgin_sdptrs_full;
+ or SCB_SGPTR, SG_LIST_NULL;
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ jmp ITloop;
+ } else {
+ jmp mesgin_done;
+ }
mesgin_sdptrs_full:
- /*
- * The SCB_SGPTR becomes the next one we'll download,
- * and the SCB_DATAPTR becomes the current SHADDR.
+ /*
+ * 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 ((ahc->features & AHC_CMD_CHAN) != 0) {
bmov SCB_DATAPTR, SHADDR, 4;
- if ((ahc->features & AHC_ULTRA2) == 0) {
- mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
- }
- bmov SCB_DATACNT, SCB_RESIDUAL_DATACNT, 8;
+ if ((ahc->features & AHC_ULTRA2) == 0) {
+ mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
+ }
+ bmov SCB_DATACNT, SCB_RESIDUAL_DATACNT, 8;
} else {
mvi DINDEX, SCB_DATAPTR;
- mvi SHADDR call bcopy_4;
- mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
- mvi SCB_RESIDUAL_DATACNT call bcopy_8;
+ mvi SHADDR call bcopy_4;
+ mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
+ mvi SCB_RESIDUAL_DATACNT call bcopy_8;
}
- jmp ITloop;
+ jmp ITloop;
/*
* 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.
+ * code do the rest. We also reset/reallocate the FIFO to make
+ * sure we have a clean start for the next data or command phase.
*/
mesgin_rdptrs:
and SEQ_FLAGS, ~DPHASE; /*
@@ -1725,6 +1787,7 @@ mesgin_rdptrs:
* the next time through
* the dataphase.
*/
+ or SXFRCTL0, CLRSTCNT|CLRCHN;
jmp mesgin_done;
/*
@@ -1732,14 +1795,14 @@ mesgin_rdptrs:
* upon return. SCBPTR may be modified by this action.
*/
set_busy_target:
- shr DINDEX, 4, SINDEX;
- if ((ahc->flags & AHC_SCB_BTT) != 0) {
- mov SCBPTR, SAVED_LUN;
- add DINDEX, SCB_64_BTT;
- } else {
- add DINDEX, BUSY_TARGETS;
- }
- mov DINDIR, ARG_1 ret;
+ shr DINDEX, 4, SINDEX;
+ if ((ahc->flags & AHC_SCB_BTT) != 0) {
+ mov SCBPTR, SAVED_LUN;
+ add DINDEX, SCB_64_BTT;
+ } else {
+ add DINDEX, BUSY_TARGETS;
+ }
+ mov DINDIR, ARG_1 ret;
/*
* Identify message? For a reconnecting target, this tells us the lun
@@ -1747,68 +1810,68 @@ set_busy_target:
* clearing the "disconnected" bit so we don't "find" it by accident later.
*/
mesgin_identify:
- /*
- * Determine whether a target is using tagged or non-tagged
- * transactions by first looking at the transaction stored in
- * the busy target array. If there is no untagged transaction
- * for this target or the transaction is for a different lun, then
- * this must be an untagged transaction.
- */
- shr SINDEX, 4, SAVED_SCSIID;
- and SAVED_LUN, MSG_IDENTIFY_LUNMASK, A;
- if ((ahc->flags & AHC_SCB_BTT) != 0) {
- add SINDEX, SCB_64_BTT;
- mov SCBPTR, SAVED_LUN;
- if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
- add NONE, -SCB_64_BTT, SINDEX;
- jc . + 2;
- mvi INTSTAT, OUT_OF_RANGE;
- nop;
- add NONE, -(SCB_64_BTT + 16), SINDEX;
- jnc . + 2;
- mvi INTSTAT, OUT_OF_RANGE;
- nop;
- }
+ /*
+ * Determine whether a target is using tagged or non-tagged
+ * transactions by first looking at the transaction stored in
+ * the busy target array. If there is no untagged transaction
+ * for this target or the transaction is for a different lun, then
+ * this must be a tagged transaction.
+ */
+ shr SINDEX, 4, SAVED_SCSIID;
+ and SAVED_LUN, MSG_IDENTIFY_LUNMASK, A;
+ if ((ahc->flags & AHC_SCB_BTT) != 0) {
+ add SINDEX, SCB_64_BTT;
+ mov SCBPTR, SAVED_LUN;
+ if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
+ add NONE, -SCB_64_BTT, SINDEX;
+ jc . + 2;
+ mvi INTSTAT, OUT_OF_RANGE;
+ nop;
+ add NONE, -(SCB_64_BTT + 16), SINDEX;
+ jnc . + 2;
+ mvi INTSTAT, OUT_OF_RANGE;
+ nop;
+ }
} else {
- add SINDEX, BUSY_TARGETS;
- if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
- add NONE, -BUSY_TARGETS, SINDEX;
- jc . + 2;
- mvi INTSTAT, OUT_OF_RANGE;
- nop;
- add NONE, -(BUSY_TARGETS + 16), SINDEX;
- jnc . + 2;
- mvi INTSTAT, OUT_OF_RANGE;
- nop;
- }
- }
- mov ARG_1, SINDIR;
+ add SINDEX, BUSY_TARGETS;
+ if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
+ add NONE, -BUSY_TARGETS, SINDEX;
+ jc . + 2;
+ mvi INTSTAT, OUT_OF_RANGE;
+ nop;
+ add NONE, -(BUSY_TARGETS + 16), SINDEX;
+ jnc . + 2;
+ mvi INTSTAT, OUT_OF_RANGE;
+ nop;
+ }
+ }
+ mov ARG_1, SINDIR;
cmp ARG_1, SCB_LIST_NULL je snoop_tag;
if ((ahc->flags & AHC_PAGESCBS) != 0) {
- mov ARG_1 call findSCB;
- } else {
- mov SCBPTR, ARG_1;
- }
- if ((ahc->flags & AHC_SCB_BTT) != 0) {
- jmp setup_SCB_id_lun_okay;
- } else {
- /*
- * We only allow one untagged command per-target
- * at a time. So, if the lun doesn't match, look
- * for a tag message.
- */
- mov A, SCB_LUN;
- cmp SAVED_LUN, A je setup_SCB_id_lun_okay;
- if ((ahc->flags & AHC_PAGESCBS) != 0) {
- /*
- * findSCB removes the SCB from the
- * disconnected list, so we must replace
- * it there should this SCB be for another
- * lun.
- */
- call cleanup_scb;
- }
- }
+ mov ARG_1 call findSCB;
+ } else {
+ mov SCBPTR, ARG_1;
+ }
+ if ((ahc->flags & AHC_SCB_BTT) != 0) {
+ jmp setup_SCB_id_lun_okay;
+ } else {
+ /*
+ * We only allow one untagged command per-target
+ * at a time. So, if the lun doesn't match, look
+ * for a tag message.
+ */
+ mov A, SCB_LUN;
+ cmp SAVED_LUN, A je setup_SCB_id_lun_okay;
+ if ((ahc->flags & AHC_PAGESCBS) != 0) {
+ /*
+ * findSCB removes the SCB from the
+ * disconnected list, so we must replace
+ * it there should this SCB be for another
+ * lun.
+ */
+ call cleanup_scb;
+ }
+ }
/*
* Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
@@ -1819,61 +1882,61 @@ mesgin_identify:
* SCB.
*/
snoop_tag:
- if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
- or SEQ_FLAGS, 0x80;
- }
+ if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
+ or SEQ_FLAGS, 0x80;
+ }
mov NONE,SCSIDATL; /* ACK Identify MSG */
call phase_lock;
- if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
- or SEQ_FLAGS, 0x1;
- }
+ if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
+ or SEQ_FLAGS, 0x1;
+ }
cmp LASTPHASE, P_MESGIN jne not_found;
- if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
- or SEQ_FLAGS, 0x2;
- }
+ if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
+ or SEQ_FLAGS, 0x2;
+ }
cmp SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found;
get_tag:
- if ((ahc->flags & AHC_PAGESCBS) != 0) {
- mvi ARG_1 call inb_next; /* tag value */
- mov ARG_1 call findSCB;
- } else {
- mvi ARG_1 call inb_next; /* tag value */
- mov SCBPTR, ARG_1;
- }
+ if ((ahc->flags & AHC_PAGESCBS) != 0) {
+ mvi ARG_1 call inb_next; /* tag value */
+ mov ARG_1 call findSCB;
+ } else {
+ mvi ARG_1 call inb_next; /* tag value */
+ mov SCBPTR, ARG_1;
+ }
/*
* Ensure that the SCB the tag points to is for
* an SCB transaction to the reconnecting target.
*/
setup_SCB:
- if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
- or SEQ_FLAGS, 0x4;
- }
- mov A, SCB_SCSIID;
- cmp SAVED_SCSIID, A jne not_found_cleanup_scb;
- if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
- or SEQ_FLAGS, 0x8;
- }
+ if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
+ or SEQ_FLAGS, 0x4;
+ }
+ mov A, SCB_SCSIID;
+ cmp SAVED_SCSIID, A jne not_found_cleanup_scb;
+ if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
+ or SEQ_FLAGS, 0x8;
+ }
setup_SCB_id_okay:
- mov A, SCB_LUN;
- cmp SAVED_LUN, A jne not_found_cleanup_scb;
+ mov A, SCB_LUN;
+ cmp SAVED_LUN, A jne not_found_cleanup_scb;
setup_SCB_id_lun_okay:
- if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
- or SEQ_FLAGS, 0x10;
- }
+ if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
+ or SEQ_FLAGS, 0x10;
+ }
test SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb;
and SCB_CONTROL,~DISCONNECTED;
- test SCB_CONTROL, TAG_ENB jnz setup_SCB_tagged;
- if ((ahc->flags & AHC_SCB_BTT) != 0) {
- mov A, SCBPTR;
- }
- mvi ARG_1, SCB_LIST_NULL;
- mov SAVED_SCSIID call set_busy_target;
- if ((ahc->flags & AHC_SCB_BTT) != 0) {
- mov SCBPTR, A;
- }
+ test SCB_CONTROL, TAG_ENB jnz setup_SCB_tagged;
+ if ((ahc->flags & AHC_SCB_BTT) != 0) {
+ mov A, SCBPTR;
+ }
+ mvi ARG_1, SCB_LIST_NULL;
+ mov SAVED_SCSIID call set_busy_target;
+ if ((ahc->flags & AHC_SCB_BTT) != 0) {
+ mov SCBPTR, A;
+ }
setup_SCB_tagged:
- mvi SEQ_FLAGS,IDENTIFY_SEEN; /* make note of IDENTIFY */
+ clr SEQ_FLAGS; /* make note of IDENTIFY */
call set_transfer_settings;
/* See if the host wants to send a message upon reconnection */
test SCB_CONTROL, MK_MESSAGE jz mesgin_done;
@@ -1881,19 +1944,19 @@ setup_SCB_tagged:
jmp mesgin_done;
not_found_cleanup_scb:
- if ((ahc->flags & AHC_PAGESCBS) != 0) {
- call cleanup_scb;
- }
+ if ((ahc->flags & AHC_PAGESCBS) != 0) {
+ call cleanup_scb;
+ }
not_found:
- mvi NO_MATCH call set_seqint;
+ mvi NO_MATCH call set_seqint;
jmp mesgin_done;
mk_mesg:
- if ((ahc->features & AHC_DT) == 0) {
- or SCSISIGO, ATNO, LASTPHASE;
- } else {
- mvi SCSISIGO, ATNO;
- }
+ if ((ahc->features & AHC_DT) == 0) {
+ or SCSISIGO, ATNO, LASTPHASE;
+ } else {
+ mvi SCSISIGO, ATNO;
+ }
mov MSG_OUT,SINDEX ret;
/*
@@ -1912,7 +1975,7 @@ mk_mesg:
* use the same calling convention as inb.
*/
inb_next_wait_perr:
- mvi PERR_DETECTED call set_seqint;
+ mvi PERR_DETECTED call set_seqint;
jmp inb_next_wait;
inb_next:
mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
@@ -1951,7 +2014,7 @@ change_phase:
/*
* If the data direction has changed, from
* out (initiator driving) to in (target driving),
- * we must wait at least a data release delay plus
+ * we must wait at least a data release delay plus
* the normal bus settle delay. [SCSI III SPI 10.11.0]
*/
cmp DINDEX, A je change_phase_wait;
@@ -1984,21 +2047,21 @@ target_outb:
if ((ahc->flags & AHC_PAGESCBS) != 0) {
BEGIN_CRITICAL;
findSCB:
- mov A, SINDEX; /* Tag passed in SINDEX */
- cmp DISCONNECTED_SCBH, SCB_LIST_NULL je findSCB_notFound;
- mov SCBPTR, DISCONNECTED_SCBH; /* Initialize SCBPTR */
- mvi ARG_2, SCB_LIST_NULL; /* Head of list */
- jmp findSCB_loop;
+ mov A, SINDEX; /* Tag passed in SINDEX */
+ cmp DISCONNECTED_SCBH, SCB_LIST_NULL je findSCB_notFound;
+ mov SCBPTR, DISCONNECTED_SCBH; /* Initialize SCBPTR */
+ mvi ARG_2, SCB_LIST_NULL; /* Head of list */
+ jmp findSCB_loop;
findSCB_next:
- cmp SCB_NEXT, SCB_LIST_NULL je findSCB_notFound;
+ cmp SCB_NEXT, SCB_LIST_NULL je findSCB_notFound;
mov ARG_2, SCBPTR;
mov SCBPTR,SCB_NEXT;
findSCB_loop:
- cmp SCB_TAG, A jne findSCB_next;
+ cmp SCB_TAG, A jne findSCB_next;
rem_scb_from_disc_list:
cmp ARG_2, SCB_LIST_NULL je rHead;
mov DINDEX, SCB_NEXT;
- mov SINDEX, SCBPTR;
+ mov SINDEX, SCBPTR;
mov SCBPTR, ARG_2;
mov SCB_NEXT, DINDEX;
mov SCBPTR, SINDEX ret;
@@ -2006,11 +2069,11 @@ rHead:
mov DISCONNECTED_SCBH,SCB_NEXT ret;
END_CRITICAL;
findSCB_notFound:
- /*
- * We didn't find it. Page in the SCB.
- */
- mov ARG_1, A; /* Save tag */
- mov ALLZEROS call get_free_or_disc_scb;
+ /*
+ * We didn't find it. Page in the SCB.
+ */
+ mov ARG_1, A; /* Save tag */
+ mov ALLZEROS call get_free_or_disc_scb;
mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
mov ARG_1 jmp dma_scb;
}
@@ -2023,13 +2086,13 @@ post_byte_setup:
mov ARG_2, SINDEX;
if ((ahc->features & AHC_CMD_CHAN) != 0) {
mvi DINDEX, CCHADDR;
- mvi SHARED_DATA_ADDR call set_1byte_addr;
+ mvi SHARED_DATA_ADDR call set_1byte_addr;
mvi CCHCNT, 1;
mvi CCSCBCTL, CCSCBRESET ret;
} else {
mvi DINDEX, HADDR;
- mvi SHARED_DATA_ADDR call set_1byte_addr;
- mvi 1 call set_hcnt;
+ mvi SHARED_DATA_ADDR call set_1byte_addr;
+ mvi 1 call set_hcnt;
mvi DFCNTRL, FIFORESET ret;
}
@@ -2046,7 +2109,7 @@ post_byte:
}
phase_lock_perr:
- mvi PERR_DETECTED call set_seqint;
+ mvi PERR_DETECTED call set_seqint;
phase_lock:
/*
* If there is a parity error, wait for the kernel to
@@ -2056,17 +2119,17 @@ phase_lock:
test SSTAT1, REQINIT jz phase_lock;
test SSTAT1, SCSIPERR jnz phase_lock_perr;
phase_lock_latch_phase:
- if ((ahc->features & AHC_DT) == 0) {
- and SCSISIGO, PHASE_MASK, SCSISIGI;
- }
+ if ((ahc->features & AHC_DT) == 0) {
+ and SCSISIGO, PHASE_MASK, SCSISIGI;
+ }
and LASTPHASE, PHASE_MASK, SCSISIGI ret;
if ((ahc->features & AHC_CMD_CHAN) == 0) {
set_hcnt:
- mov HCNT[0], SINDEX;
+ mov HCNT[0], SINDEX;
clear_hcnt:
- clr HCNT[1];
- clr HCNT[2] ret;
+ clr HCNT[1];
+ clr HCNT[2] ret;
set_stcnt_from_hcnt:
mov STCNT[0], HCNT[0];
@@ -2074,7 +2137,7 @@ set_stcnt_from_hcnt:
mov STCNT[2], HCNT[2] ret;
bcopy_8:
- mov DINDIR, SINDIR;
+ mov DINDIR, SINDIR;
bcopy_7:
mov DINDIR, SINDIR;
mov DINDIR, SINDIR;
@@ -2139,27 +2202,27 @@ dma_scb:
mvi HSCB_ADDR call set_64byte_addr;
mov CCSCBPTR, SCBPTR;
test DMAPARAMS, DIRECTION jz dma_scb_tohost;
- if ((ahc->flags & AHC_SCB_BTT) != 0) {
- mvi CCHCNT, SCB_DOWNLOAD_SIZE_64;
- } else {
- mvi CCHCNT, SCB_DOWNLOAD_SIZE;
- }
+ if ((ahc->flags & AHC_SCB_BTT) != 0) {
+ mvi CCHCNT, SCB_DOWNLOAD_SIZE_64;
+ } else {
+ mvi CCHCNT, SCB_DOWNLOAD_SIZE;
+ }
mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET;
cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .;
jmp dma_scb_finish;
dma_scb_tohost:
- mvi CCHCNT, SCB_UPLOAD_SIZE;
- if ((ahc->features & AHC_ULTRA2) == 0) {
+ mvi CCHCNT, SCB_UPLOAD_SIZE;
+ if ((ahc->features & AHC_ULTRA2) == 0) {
mvi CCSCBCTL, CCSCBRESET;
- bmov CCSCBRAM, SCB_BASE, SCB_UPLOAD_SIZE;
+ bmov CCSCBRAM, SCB_BASE, SCB_UPLOAD_SIZE;
or CCSCBCTL, CCSCBEN|CCSCBRESET;
test CCSCBCTL, CCSCBDONE jz .;
- } else if ((ahc->bugs & AHC_SCBCHAN_UPLOAD_BUG) != 0) {
- mvi CCSCBCTL, CCARREN|CCSCBRESET;
- cmp CCSCBCTL, ARRDONE|CCARREN jne .;
- mvi CCHCNT, SCB_UPLOAD_SIZE;
- mvi CCSCBCTL, CCSCBEN|CCSCBRESET;
- cmp CCSCBCTL, CCSCBDONE|CCSCBEN jne .;
+ } else if ((ahc->bugs & AHC_SCBCHAN_UPLOAD_BUG) != 0) {
+ mvi CCSCBCTL, CCARREN|CCSCBRESET;
+ cmp CCSCBCTL, ARRDONE|CCARREN jne .;
+ mvi CCHCNT, SCB_UPLOAD_SIZE;
+ mvi CCSCBCTL, CCSCBEN|CCSCBRESET;
+ cmp CCSCBCTL, CCSCBDONE|CCSCBEN jne .;
} else {
mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET;
cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .;
@@ -2171,74 +2234,73 @@ dma_scb_finish:
} else {
mvi DINDEX, HADDR;
mvi HSCB_ADDR call set_64byte_addr;
- mvi SCB_DOWNLOAD_SIZE call set_hcnt;
+ mvi SCB_DOWNLOAD_SIZE call set_hcnt;
mov DFCNTRL, DMAPARAMS;
test DMAPARAMS, DIRECTION jnz dma_scb_fromhost;
/* Fill it with the SCB data */
copy_scb_tofifo:
- mvi SINDEX, SCB_BASE;
- add A, SCB_DOWNLOAD_SIZE, SINDEX;
+ mvi SINDEX, SCB_BASE;
+ add A, SCB_DOWNLOAD_SIZE, SINDEX;
copy_scb_tofifo_loop:
- call copy_to_fifo_8;
+ call copy_to_fifo_8;
cmp SINDEX, A jne copy_scb_tofifo_loop;
or DFCNTRL, HDMAEN|FIFOFLUSH;
- jmp dma_finish;
+ jmp dma_finish;
dma_scb_fromhost:
- mvi DINDEX, SCB_BASE;
- if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0) {
- /*
- * The PCI module will only issue a PCI
- * retry if the data FIFO is empty. If the
- * host disconnects in the middle of a
- * transfer, we must empty the fifo of all
- * available data to force the chip to
- * continue the transfer. This does not
- * happen for SCSI transfers as the SCSI module
- * will drain the FIFO as data is made available.
- * When the hang occurs, we know that a multiple
- * of 8 bytes are in the FIFO because the PCI
- * module has an 8 byte input latch that only
- * dumps to the FIFO when HCNT == 0 or the
- * latch is full.
- */
- clr A;
- /* Wait for at least 8 bytes of data to arrive. */
+ mvi DINDEX, SCB_BASE;
+ if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0) {
+ /*
+ * The PCI module will only issue a PCI
+ * retry if the data FIFO is empty. If the
+ * host disconnects in the middle of a
+ * transfer, we must empty the fifo of all
+ * available data to force the chip to
+ * continue the transfer. This does not
+ * happen for SCSI transfers as the SCSI module
+ * will drain the FIFO as data are made available.
+ * When the hang occurs, we know that a multiple
+ * of 8 bytes is in the FIFO because the PCI
+ * module has an 8 byte input latch that only
+ * dumps to the FIFO when HCNT == 0 or the
+ * latch is full.
+ */
+ clr A;
+ /* Wait for at least 8 bytes of data to arrive. */
dma_scb_hang_fifo:
- test DFSTATUS, FIFOQWDEMP jnz dma_scb_hang_fifo;
+ test DFSTATUS, FIFOQWDEMP jnz dma_scb_hang_fifo;
dma_scb_hang_wait:
- test DFSTATUS, MREQPEND jnz dma_scb_hang_wait;
- 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;
- /*
- * The PCI module no longer intends to perform
- * a PCI transaction. Drain the fifo.
- */
+ test DFSTATUS, MREQPEND jnz dma_scb_hang_wait;
+ 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;
+ /*
+ * The PCI module no longer intends to perform
+ * a PCI transaction. Drain the fifo.
+ */
dma_scb_hang_dma_drain_fifo:
- not A, HCNT;
- add A, SCB_DOWNLOAD_SIZE+SCB_BASE+1;
- and A, ~0x7;
- mov DINDIR,DFDAT;
- cmp DINDEX, A jne . - 1;
- cmp DINDEX, SCB_DOWNLOAD_SIZE+SCB_BASE
- je dma_finish_nowait;
- /* Restore A as the lines left to transfer. */
- add A, -SCB_BASE, DINDEX;
- shr A, 3;
- jmp dma_scb_hang_fifo;
+ not A, HCNT;
+ add A, SCB_DOWNLOAD_SIZE+SCB_BASE+1;
+ and A, ~0x7;
+ mov DINDIR,DFDAT;
+ cmp DINDEX, A jne . - 1;
+ cmp DINDEX, SCB_DOWNLOAD_SIZE+SCB_BASE
+ je dma_finish_nowait;
+ /* Restore A as the lines left to transfer. */
+ add A, -SCB_BASE, DINDEX;
+ shr A, 3;
+ jmp dma_scb_hang_fifo;
dma_scb_hang_dma_done:
- and DFCNTRL, ~HDMAEN;
- test DFCNTRL, HDMAEN jnz .;
- add SEQADDR0, A;
- } else {
- call dma_finish;
- }
- /* If we were putting the SCB, we are done */
- call dfdat_in_8;
- call dfdat_in_8;
- call dfdat_in_8;
+ and DFCNTRL, ~HDMAEN;
+ test DFCNTRL, HDMAEN jnz .;
+ add SEQADDR0, A;
+ } else {
+ call dma_finish;
+ }
+ call dfdat_in_8;
+ call dfdat_in_8;
+ call dfdat_in_8;
dfdat_in_8:
- mov DINDIR,DFDAT;
+ mov DINDIR,DFDAT;
dfdat_in_7:
mov DINDIR,DFDAT;
mov DINDIR,DFDAT;
@@ -2251,17 +2313,17 @@ dfdat_in_2:
}
copy_to_fifo_8:
- mov DFDAT,SINDIR;
- mov DFDAT,SINDIR;
+ mov DFDAT,SINDIR;
+ mov DFDAT,SINDIR;
copy_to_fifo_6:
- mov DFDAT,SINDIR;
+ mov DFDAT,SINDIR;
copy_to_fifo_5:
- mov DFDAT,SINDIR;
+ mov DFDAT,SINDIR;
copy_to_fifo_4:
- mov DFDAT,SINDIR;
- mov DFDAT,SINDIR;
- mov DFDAT,SINDIR;
- mov DFDAT,SINDIR ret;
+ mov DFDAT,SINDIR;
+ mov DFDAT,SINDIR;
+ mov DFDAT,SINDIR;
+ mov DFDAT,SINDIR ret;
/*
* Wait for DMA from host memory to data FIFO to complete, then disable
@@ -2282,9 +2344,9 @@ dma_finish_nowait:
* If it is not in the disconnected state, it must be free.
*/
cleanup_scb:
- if ((ahc->flags & AHC_PAGESCBS) != 0) {
- test SCB_CONTROL,DISCONNECTED jnz add_scb_to_disc_list;
- }
+ if ((ahc->flags & AHC_PAGESCBS) != 0) {
+ test SCB_CONTROL,DISCONNECTED jnz add_scb_to_disc_list;
+ }
add_scb_to_free_list:
if ((ahc->flags & AHC_PAGESCBS) != 0) {
BEGIN_CRITICAL;
@@ -2298,9 +2360,9 @@ END_CRITICAL;
if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
set_hhaddr:
- or DSCOMMAND1, HADDLDSEL0;
- and HADDR, SG_HIGH_ADDR_BITS, SINDEX;
- and DSCOMMAND1, ~HADDLDSEL0 ret;
+ or DSCOMMAND1, HADDLDSEL0;
+ and HADDR, SG_HIGH_ADDR_BITS, SINDEX;
+ and DSCOMMAND1, ~HADDLDSEL0 ret;
}
if ((ahc->flags & AHC_PAGESCBS) != 0) {
@@ -2309,14 +2371,14 @@ BEGIN_CRITICAL;
cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb;
cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;
return_error:
- mvi NO_FREE_SCB call set_seqint;
+ mvi NO_FREE_SCB call set_seqint;
mvi SINDEX, SCB_LIST_NULL ret;
dequeue_disc_scb:
mov SCBPTR, DISCONNECTED_SCBH;
- mov DISCONNECTED_SCBH, SCB_NEXT;
+ mov DISCONNECTED_SCBH, SCB_NEXT;
END_CRITICAL;
mvi DMAPARAMS, FIFORESET;
- mov SCB_TAG jmp dma_scb;
+ mov SCB_TAG jmp dma_scb;
BEGIN_CRITICAL;
dequeue_free_scb:
mov SCBPTR, FREE_SCBH;
@@ -2335,7 +2397,7 @@ BEGIN_CRITICAL;
END_CRITICAL;
}
set_seqint:
- mov INTSTAT, SINDEX;
- nop;
+ mov INTSTAT, SINDEX;
+ nop;
return:
- ret;
+ ret;