summaryrefslogtreecommitdiffstats
path: root/sys/gnu
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>1995-01-16 16:31:21 +0000
committergibbs <gibbs@FreeBSD.org>1995-01-16 16:31:21 +0000
commit1ce8bad19c84cf0872d7f24495ed37d035f0a0e2 (patch)
tree6bd668f1ae746bc724b74ab832f474eb39584dcc /sys/gnu
parentd07546f6ba693863e0aab8d5ec7bdb9b6ec5b02a (diff)
downloadFreeBSD-src-1ce8bad19c84cf0872d7f24495ed37d035f0a0e2.zip
FreeBSD-src-1ce8bad19c84cf0872d7f24495ed37d035f0a0e2.tar.gz
At $Ids to all files. Have the sequencer use DMA to tranfer its SCB
(SCSI control block) instead of having the host PIO it down. Also reimplement WDTR and SDTR optimization to remove code in the sequencer and place the responsibility of knowing when to initiate SDTR or WDTR on the kernel driver. This vastly shortens the sequencer program yet yeilds the same performance.
Diffstat (limited to 'sys/gnu')
-rw-r--r--sys/gnu/misc/aic7xxx/aic7xxx.c2
-rw-r--r--sys/gnu/misc/aic7xxx/aic7xxx.seq235
2 files changed, 128 insertions, 109 deletions
diff --git a/sys/gnu/misc/aic7xxx/aic7xxx.c b/sys/gnu/misc/aic7xxx/aic7xxx.c
index 417a352..8077ac8 100644
--- a/sys/gnu/misc/aic7xxx/aic7xxx.c
+++ b/sys/gnu/misc/aic7xxx/aic7xxx.c
@@ -25,6 +25,8 @@
*
* A <label> is an <undef-sym> ending in a colon. Spaces, tabs, and commas
* are token separators.
+ *
+ * $Id$
*/
/* #define _POSIX_SOURCE 1 */
diff --git a/sys/gnu/misc/aic7xxx/aic7xxx.seq b/sys/gnu/misc/aic7xxx/aic7xxx.seq
index d1ed1e1..b02c778 100644
--- a/sys/gnu/misc/aic7xxx/aic7xxx.seq
+++ b/sys/gnu/misc/aic7xxx/aic7xxx.seq
@@ -1,6 +1,6 @@
# @(#)aic7xxx.seq 1.32 94/11/29 jda
#
-# Adaptec 274x/284x/294x device driver for Linux.
+# Adaptec 274x/284x/294x device driver for Linux and FreeBSD.
# Copyright (c) 1994 The University of Calgary Department of Computer Science.
#
# This program is free software; you can redistribute it and/or modify
@@ -16,8 +16,14 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+# FreeBSD, Twin, Wide, 2 command per target support, and other optimizations
+# provided by Justin T. Gibbs (gibbs@FreeBSD.org)
+#
+# $Id$
-VERSION AIC7XXX_SEQ_VERSION 1.32
+VERSION AIC7XXX_SEQ_VERSION 1.5
SCBMASK = 0x1f
@@ -70,14 +76,30 @@ SCSICONF_B = 0x5b
# The two reserved bytes at SCBARRAY+1[23] are expected to be set to
# zero, and the reserved bit in SCBARRAY+0 is used as an internal flag
# to indicate whether or not to reload scatter-gather parameters after
-# a disconnect.
+# a disconnect. We also use bits 6 & 7 to indicate whether or not to
+# initiate SDTR or WDTR repectively when starting this command.
#
SCBARRAY+0 = 0xa0
+
+DISCONNECTED = 0x04
+NEEDDMA = 0x08
+SG_LOAD = 0x10
+NEEDSDTR = 0x40
+NEEDWDTR = 0x80
+
SCBARRAY+1 = 0xa1
SCBARRAY+2 = 0xa2
SCBARRAY+3 = 0xa3
+SCBARRAY+4 = 0xa4
+SCBARRAY+5 = 0xa5
+SCBARRAY+6 = 0xa6
SCBARRAY+7 = 0xa7
+SCBARRAY+8 = 0xa8
+SCBARRAY+9 = 0xa9
+SCBARRAY+10 = 0xaa
SCBARRAY+11 = 0xab
+SCBARRAY+12 = 0xac
+SCBARRAY+13 = 0xad
SCBARRAY+14 = 0xae
SCBARRAY+15 = 0xaf
SCBARRAY+16 = 0xb0
@@ -90,14 +112,16 @@ SCBARRAY+22 = 0xb6
SCBARRAY+23 = 0xb7
SCBARRAY+24 = 0xb8
SCBARRAY+25 = 0xb9
+SCBARRAY+26 = 0xba
-SIGNAL_0 = 0x01 # unknown scsi bus phase
-SIGNAL_1 = 0x11 # message reject
-SIGNAL_2 = 0x21 # no IDENTIFY after reconnect
-SIGNAL_3 = 0x31 # no cmd match for reconnect
-SIGNAL_4 = 0x41 # SDTR -> SCSIRATE conversion
-STATUS_ERROR = 0x51
-SIGNAL_WDTR = 0x61
+BAD_PHASE = 0x01 # unknown scsi bus phase
+SEND_REJECT = 0x11 # sending a message reject
+NO_IDENT = 0x21 # no IDENTIFY after reconnect
+NO_MATCH = 0x31 # no cmd match for reconnect
+MSG_SDTR = 0x41 # SDTR message recieved
+MSG_WDTR = 0x51 # WDTR message recieved
+MSG_REJECT = 0x61 # Reject message recieved
+BAD_STATUS = 0x71 # Bad status from target
# The host adapter card (at least the BIOS) uses 20-2f for SCSI
# device information, 32-33 and 5a-5f as well. As it turns out, the
@@ -107,10 +131,10 @@ SIGNAL_WDTR = 0x61
# SCSIRATE). The kernel driver will enable synchronous negotiation
# for all targets that have a value other than 0 in the lower four
# bits of the target scratch space. This should work irregardless of
-# whether the bios has been installed. NEEDSDTR has one bit per target
-# indicating if an SDTR message is needed for that device - this will
-# be set initially (based on a search through the target scratch space),
-# as well as after a bus reset condition.
+# whether the bios has been installed. NEEDWDTR and NEEDSDTR are the top
+# two bits of the SCB control byte. The kernel driver will set these
+# when a WDTR or SDTR message should be sent to the target the SCB's
+# command references.
#
# The high bit of DROPATN is set if ATN should be dropped before the ACK
# when outb is called. REJBYTE contains the first byte of a MESSAGE IN
@@ -133,9 +157,6 @@ REJBYTE = 0x31
DISC_DSB_A = 0x32
DISC_DSB_B = 0x33
-NEEDWDTR_A = 0x34
-NEEDWDTR_B = 0x35
-
MSG_LEN = 0x36
MSG_START+0 = 0x37
MSG_START+1 = 0x38
@@ -146,13 +167,16 @@ MSG_START+5 = 0x3c
-MSG_START+0 = 0xc9 # 2's complement of MSG_START+0
ARG_1 = 0x4c # sdtr conversion args & return
+BUS_16_BIT = 0x01
RETURN_1 = 0x4c
SIGSTATE = 0x4d # value written to SCSISIGO
-NEEDSDTR_A = 0x4e # send SDTR message, 1 bit/trgt
-NEEDSDTR_B = 0x4f
-SG_SIZEOF = 0x8 # sizeof(struct scatterlist)
+# Linux users should use 0xc (12) for SG_SIZEOF
+SG_SIZEOF = 0x8 # sizeof(struct ahc_dma)
+#SG_SIZEOF = 0xc # sizeof(struct scatterlist)
+SCB_SIZEOF = 0x13 # sizeof SCB to DMA (19 bytes)
+
SG_NOLOAD = 0x50 # load SG pointer/length?
SG_COUNT = 0x51 # working value of SG count
SG_NEXT = 0x52 # working value of SG pointer
@@ -165,7 +189,6 @@ SCBCOUNT = 0x56 # the actual number of SCBs
FLAGS = 0x57 # Device configuration flags
TWIN_BUS = 0x01
WIDE_BUS = 0x02
-CHECK_DTR = 0x08
SENSE = 0x10
ACTIVE_MSG = 0x20
IDENTIFY_SEEN = 0x40
@@ -189,13 +212,60 @@ start2:
test SCSISIGI,0x4 jnz reselect # BSYI
test QINCNT,SCBMASK jz start
-# We have at least one queued SCB now. Set the SCB pointer
-# from the FIFO so we see the right bank of SCB registers,
-# then set SCSI options and set the initiator and target
-# SCSI IDs.
+# We have at least one queued SCB now. Set the SCB pointer
+# from the FIFO so we see the right bank of SCB registers,
+# then set SCSI options and set the initiator and target
+# SCSI IDs.
#
mov SCBPTR,QINFIFO
+# If the control byte of this SCB has the NEEDDMA flag set, we have
+# yet to DMA it from host memory
+
+test SCBARRAY+0,NEEDDMA jz test_busy
+ clr HCNT+2
+ clr HCNT+1
+ mvi HCNT+0,SCB_SIZEOF
+
+ mvi A,4
+ mvi DINDEX,HADDR
+ mvi SCBARRAY+26 call bcopy
+
+ mvi DFCNTRL,0xd # HDMAEN|DIRECTION|FIFORESET
+
+# Wait for DMA from host memory to data FIFO to complete, then disable
+# DMA and wait for it to acknowledge that it's off.
+#
+scb_load1:
+ test DFSTATUS,0x8 jz scb_load1 # HDONE
+
+ clr DFCNTRL # disable DMA
+scb_load2:
+ test DFCNTRL,0x8 jnz scb_load2 # HDMAENACK
+
+# Copy the SCB from the FIFO to the SCBARRAY
+
+ mov SCBARRAY+0, DFDAT
+ mov SCBARRAY+1, DFDAT
+ mov SCBARRAY+2, DFDAT
+ mov SCBARRAY+3, DFDAT
+ mov SCBARRAY+4, DFDAT
+ mov SCBARRAY+5, DFDAT
+ mov SCBARRAY+6, DFDAT
+ mov SCBARRAY+7, DFDAT
+ mov SCBARRAY+8, DFDAT
+ mov SCBARRAY+9, DFDAT
+ mov SCBARRAY+10, DFDAT
+ mov SCBARRAY+11, DFDAT
+ mov SCBARRAY+12, DFDAT
+ mov SCBARRAY+13, DFDAT
+ mov SCBARRAY+14, DFDAT
+ mov SCBARRAY+15, DFDAT
+ mov SCBARRAY+16, DFDAT
+ mov SCBARRAY+17, DFDAT
+ mov SCBARRAY+18, DFDAT
+ and SCBARRAY+0, 0xf7
+
# See if there is not already an active SCB for this target. This code
# locks out on a per target basis instead of target/lun. Although this
# is not ideal for devices that have multiple luns active at the same
@@ -205,6 +275,7 @@ start2:
# assumes that the kernel driver will clear the active flags on board
# initialization, board reset, and a target's SELTO.
+test_busy:
and FUNCTION1,0x70,SCBARRAY+1
mov A,FUNCTION1
test SCBARRAY+1,0x88 jz test_a # Id < 8 && A channel
@@ -228,6 +299,7 @@ test_a:
or ACTIVE_A,A # Mark the current target as busy
start_scb:
+ or SCBARRAY+0,NEEDDMA
and SINDEX,0x08,SCBARRAY+1
and A,WIDE_BUS,FLAGS # Wide bus?
or SINDEX,A
@@ -252,8 +324,8 @@ start_scb:
or SINDEX,0x80 call mk_mesg # IDENTIFY message
mov A,SINDEX
+ test SCBARRAY+0,0xc0 jz !message # WDTR or SDTR??
cmp MSG_START+0,A jne !message # did driver beat us?
- test FLAGS,CHECK_DTR jz !message # Don't even bother with DTR?
mvi MSG_START+1 call mk_dtr # build DTR message if needed
!message:
@@ -337,7 +409,7 @@ ITloop:
cmp A,0xa0 je p_mesgout
cmp A,0xe0 je p_mesgin
- mvi INTSTAT,SIGNAL_0 # unknown - signal driver
+ mvi INTSTAT,BAD_PHASE # unknown - signal driver
p_dataout:
mvi 0 call scsisig # !CDO|!IOO|!MSGO
@@ -544,8 +616,8 @@ p_mesgin:
# extra work in the kernel driver to ensure that the entry was removed
# before the command complete code tried processing it.
- test SCBARRAY+14,0xff jz status_ok # 0 Status?
- mvi INTSTAT,STATUS_ERROR # let driver know
+ test SCBARRAY+14,0xff jz status_ok # 0 Status?
+ mvi INTSTAT,BAD_STATUS # let driver know
test FLAGS,SENSE jz status_ok
jmp p_mesgin_done
@@ -585,12 +657,13 @@ p_mesgin1:
p_mesginWDTR:
cmp ARG_1,2 jne p_mesginN # extended mesg length = 2
mvi A call inb_next # Width of bus
- mvi INTSTAT,SIGNAL_WDTR # let driver know
+ mvi INTSTAT,MSG_WDTR # let driver know
test RETURN_1,0x80 jz p_mesgin_done# Do we need to send WDTR?
# We didn't initiate the wide negotiation, so we must respond to the request
and RETURN_1,0x7f # Clear the SEND_WDTR Flag
or FLAGS,ACTIVE_MSG
+ mvi DINDEX,MSG_START+0
mvi MSG_START+0 call mk_wdtr # build WDTR message
or SINDEX,0x10,SIGSTATE # turn on ATNO
call scsisig
@@ -600,11 +673,12 @@ p_mesginSDTR:
cmp ARG_1,3 jne p_mesginN # extended mesg length = 3
mvi ARG_1 call inb_next # xfer period
mvi A call inb_next # REQ/ACK offset
- mvi INTSTAT,SIGNAL_4 # call driver to convert
+ mvi INTSTAT,MSG_SDTR # call driver to convert
test RETURN_1,0x80 jz p_mesgin_done# Do we need to mk_sdtr?
or FLAGS,ACTIVE_MSG
+ mvi DINDEX, MSG_START+0
mvi MSG_START+0 call mk_sdtr
or SINDEX,0x10,SIGSTATE # turn on ATNO
call scsisig
@@ -662,70 +736,15 @@ p_mesgin5:
# required on reselect
jmp p_mesgin_done
-# Message reject? If we have an outstanding WDTR or SDTR negotiation, assume
-# that it's a response from the target selecting 8bit or asynchronous transfer,
-# otherwise just ignore it since we have no clue what it pertains to.
-#
-# XXX - I don't have a device that responds this way. Does this code
-# actually work?
+# Message reject? Let the kernel driver handle this. If we have an
+# outstanding WDTR or SDTR negotiation, assume that it's a response from
+# the target selecting 8bit or asynchronous transfer, otherwise just ignore
+# it since we have no clue what it pertains to.
#
p_mesgin6:
cmp A,7 jne p_mesgin7 # message reject code?
- and FUNCTION1,0x70,SCSIID # outstanding SDTR message?
- mov A,FUNCTION1
-
- test SBLKCTL,0x08 jnz p_mesgin6_b
- test SCSIID,0x80 jnz p_mesgin6_b
- test NEEDWDTR_A,A jnz clear_wdtr_a
- test NEEDSDTR_A,A jnz clear_sdtr_a
- jmp p_mesgin_done # no - ignore rejection
-
-clear_sdtr_a:
- call ndx_dtr # note use of asynch xfer
- mov DINDEX,SINDEX
- and DINDIR,0x80,SINDIR
-
- not A
- and NEEDSDTR_A,A
- jmp clear_sdtr_done
-
-clear_wdtr_a:
- call ndx_dtr # note use of 8bit xfer
- mov DINDEX,SINDEX
- and DINDIR,0x7f,SINDIR
-
- not A
- and NEEDWDTR_A,A
- jmp clear_wdtr_done
-
-p_mesgin6_b:
- test NEEDWDTR_B,A jnz clear_wdtr_b
- test NEEDSDTR_B,A jnz clear_sdtr_b
- jmp p_mesgin_done # no - ignore rejection
-
-clear_wdtr_b:
- call ndx_dtr # note use of 8bit xfer
- mov DINDEX,SINDEX
- and DINDIR,0x7f,SINDIR
-
- not A
- and NEEDWDTR_B,A
-
-clear_wdtr_done:
- and SCSIRATE,0x7f # select 8bit xfer
- jmp p_mesgin_done
-
-clear_sdtr_b:
- call ndx_dtr # note use of asynch xfer
- mov DINDEX,SINDEX
- and DINDIR,0x80,SINDIR
-
- not A
- and NEEDSDTR_B,A
-
-clear_sdtr_done:
- and SCSIRATE,0xf0 # select asynch xfer
+ mvi INTSTAT, MSG_REJECT
jmp p_mesgin_done
# [ ADD MORE MESSAGE HANDLING HERE ]
@@ -742,7 +761,7 @@ p_mesgin7:
p_mesginN:
or SINDEX,0x10,SIGSTATE # turn on ATNO
call scsisig
- mvi INTSTAT,SIGNAL_1 # let driver know
+ mvi INTSTAT,SEND_REJECT # let driver know
mvi 0x7 call mk_mesg # MESSAGE REJECT message
@@ -964,7 +983,7 @@ assert:
test FLAGS,RESELECTED jz assert1 # reselected?
test FLAGS,IDENTIFY_SEEN jnz assert1 # seen IDENTIFY?
- mvi INTSTAT,SIGNAL_2 # no - cause a kernel panic
+ mvi INTSTAT,NO_IDENT # no - cause a kernel panic
assert1:
ret
@@ -1019,7 +1038,7 @@ findSCB2:
mov A,SCBCOUNT
cmp SINDEX,A jne findSCB1
- mvi INTSTAT,SIGNAL_3 # not found - signal kernel
+ mvi INTSTAT,NO_MATCH # not found - signal kernel
mvi 0x6 call mk_mesg # ABORT message
or SINDEX,0x10,SIGSTATE # assert ATNO
@@ -1053,7 +1072,7 @@ sg_ram2scb:
and SCBARRAY+0,0xef,SCBARRAY+0
test SG_NOLOAD,0x80 jz sg_ram2scb1 # reload s/g?
- or SCBARRAY+0,0x10
+ or SCBARRAY+0,SG_LOAD
sg_ram2scb1:
ret
@@ -1112,10 +1131,16 @@ sg_load2:
mov SCBARRAY+21,DFDAT
mov SCBARRAY+22,DFDAT
+# For Linux, we must throw away four bytes since there is a 32bit gap
+# in the middle of a struct scatterlist
+# mov NONE,DFDAT
+# mov NONE,DFDAT
+# mov NONE,DFDAT
+# mov NONE,DFDAT
+
mov SCBARRAY+23,DFDAT
mov SCBARRAY+24,DFDAT
- mov SCBARRAY+25,DFDAT
- mov NONE,DFDAT #Only support 24 bit length.
+ mov SCBARRAY+25,DFDAT #Only support 24 bit length.
sg_load3:
ret
@@ -1173,19 +1198,11 @@ ndx_dtr_2:
mk_dtr:
mov DINDEX,SINDEX # save SINDEX
- call ndx_dtr
- test SCBARRAY+1,0x88 jz mk_dtr_a
- test NEEDWDTR_B,A jnz mk_wdtr_16 # do we need negotiation?
- test NEEDSDTR_B,A jnz mk_sdtr
- ret
-mk_dtr_a:
- test NEEDWDTR_A,A jnz mk_wdtr_16 # do we need negotiation?
- test NEEDSDTR_A,A jnz mk_sdtr
- ret
-
-mk_wdtr_16:
- mvi ARG_1,1 # 16bit wide bus
+ test SCBARRAY+0,NEEDWDTR jnz mk_wdtr_16bit
+ jmp mk_sdtr
+mk_wdtr_16bit:
+ mvi ARG_1,BUS_16_BIT
mk_wdtr:
mvi DINDIR,1 # extended message
mvi DINDIR,2 # extended message length = 2
OpenPOWER on IntegriCloud