diff options
author | gibbs <gibbs@FreeBSD.org> | 1995-01-16 16:31:21 +0000 |
---|---|---|
committer | gibbs <gibbs@FreeBSD.org> | 1995-01-16 16:31:21 +0000 |
commit | 1ce8bad19c84cf0872d7f24495ed37d035f0a0e2 (patch) | |
tree | 6bd668f1ae746bc724b74ab832f474eb39584dcc /sys/gnu | |
parent | d07546f6ba693863e0aab8d5ec7bdb9b6ec5b02a (diff) | |
download | FreeBSD-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.c | 2 | ||||
-rw-r--r-- | sys/gnu/misc/aic7xxx/aic7xxx.seq | 235 |
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 |