summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq408
1 files changed, 171 insertions, 237 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index 38c2663..be980dd 100644
--- a/sys/dev/aic7xxx/aic7xxx.seq
+++ b/sys/dev/aic7xxx/aic7xxx.seq
@@ -43,7 +43,7 @@
VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.18 1995/07/31 08:21:59 gibbs Exp $"
-SCBMASK = 0x1f
+SCBMASK = 0xff
SCSISEQ = 0x00
ENRSELI = 0x10
@@ -64,6 +64,7 @@ SELDO = 0x40
SELDI = 0x20
CLRSINT1 = 0x0c
SSTAT1 = 0x0c
+PHASEMIS = 0x10
SIMODE1 = 0x11
SCSIBUSL = 0x12
SHADDR = 0x14
@@ -99,18 +100,19 @@ SCSICONF_A = 0x5a
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. We also use bits 6 & 7 to indicate whether or not to
-# initiate SDTR or WDTR repectively when starting this command.
+# zero. Bit 3 in SCBARRAY+0 is used as an internal flag to indicate
+# whether or not to DMA an SCB from host ram. This flag prevents the
+# "re-fetching" of transactions that are requed because the target is
+# busy with another command. 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 = 0x10
TAG_ENB = 0x20
-NEEDSDTR = 0x40
+DISCENB = 0x40
NEEDWDTR = 0x80
SCBARRAY+1 = 0xa1
@@ -170,11 +172,11 @@ IMMEDDONE = 0xb1
# scratchspace (actually a value that can be copied directly into
# SCSIRATE). The kernel driver will enable synchronous negotiation
# for all targets that have a value other than 0 in the lower four
-# bits of the target scratch space. This should work irregardless of
-# 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.
+# bits of the target scratch space. This should work regardless of
+# whether the bios has been installed. NEEDSDTR and NEEDWDTR are the
+# fouth and sevent 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.
#
# REJBYTE contains the first byte of a MESSAGE IN message, so the driver
# can report an intelligible error if a message is rejected.
@@ -185,9 +187,9 @@ IMMEDDONE = 0xb1
# no idea what the lun is, and we can't select the right SCB register
# bank, so force a kernel panic if the target attempts a data in/out or
# command phase instead of corrupting something. FLAGS also contains
-# configuration bits so that we can optimize for TWIN and WIDE controllers
-# as well as the MAX_OFFSET bit which we set when we want to negotiate for
-# maximum sync offset irregardless of what the per target scratch space says.
+# configuration bits so that we can optimize for TWIN and WIDE controllers,
+# the MAX_OFFSET bit which we set when we want to negotiate for maximum sync
+# offset irregardless of what the per target scratch space says.
#
# Note that SG_NEXT occupies four bytes.
#
@@ -215,9 +217,9 @@ SIGSTATE = 0x4b # value written to SCSISIGO
# 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)
+SCB_SIZEOF = 0x1a # sizeof SCB to DMA (26 bytes)
-SG_NOLOAD = 0x4c # load SG pointer/length?
+DMAPARAMS = 0x4c # Parameters for DMA
SG_COUNT = 0x4d # working value of SG count
SG_NEXT = 0x4e # working value of SG pointer
SG_NEXT+0 = 0x4e
@@ -229,6 +231,7 @@ SCBCOUNT = 0x52 # the actual number of SCBs
FLAGS = 0x53 # Device configuration flags
TWIN_BUS = 0x01
WIDE_BUS = 0x02
+DPHASE = 0x04
MAX_OFFSET = 0x08
ACTIVE_MSG = 0x20
IDENTIFY_SEEN = 0x40
@@ -242,7 +245,6 @@ ACTIVE_B = 0x55
SAVED_TCL = 0x56 # Temporary storage for the
# target/channel/lun of a
# reconnecting target
-
# After starting the selection hardware, we return to the "poll_for_work"
# loop so that we can check for reconnecting targets as well as for our
# selection to complete just in case the reselection wins bus arbitration.
@@ -309,11 +311,10 @@ test SCBARRAY+0,NEEDDMA jz test_busy
# Copy the SCB from the FIFO to the SCBARRAY
mvi DINDEX, SCBARRAY+0
- call bcopy_3_dfdat
- call bcopy_4_dfdat
- call bcopy_4_dfdat
- call bcopy_4_dfdat
- call bcopy_4_dfdat
+ call bcopy_5_dfdat
+ call bcopy_7_dfdat
+ call bcopy_7_dfdat
+ call bcopy_7_dfdat
# 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
@@ -330,7 +331,7 @@ test_busy:
test SCBARRAY+1,0x88 jz test_a # Id < 8 && A channel
test ACTIVE_B,A jnz requeue
- test SCBARRAY+0,0x20 jnz start_scb
+ test SCBARRAY+0,TAG_ENB jnz start_scb
or ACTIVE_B,A # Mark the current target as busy
jmp start_scb
@@ -346,7 +347,7 @@ start_waiting:
test_a:
test ACTIVE_A,A jnz requeue
- test SCBARRAY+0,0x20 jnz start_scb
+ test SCBARRAY+0,TAG_ENB jnz start_scb
or ACTIVE_A,A # Mark the current target as busy
start_scb:
@@ -364,8 +365,7 @@ start_scb:
start_selection:
or SCSISEQ,0x48 # ENSELO|ENAUTOATNO
mov WAITING_SCBH, SCBPTR
- clr SG_NOLOAD
- and FLAGS,0x3f # !RESELECTING
+ and FLAGS,0x3f # !RESELECTING
# As soon as we get a successful selection, the target should go
# into the message out phase since we have ATN asserted. Prepare
@@ -387,14 +387,14 @@ start_selection:
jmp wait_for_selection
identify:
- mov SCBARRAY+1 call disconnect # disconnect ok?
+ and A,DISCENB,SCBARRAY+0 # mask off disconnect privledge
and SINDEX,0x7,SCBARRAY+1 # lun
- or SINDEX,A # return value from disconnect
+ or SINDEX,A # or in disconnect privledge
or SINDEX,0x80 call mk_mesg # IDENTIFY message
mov A,SINDEX
- test SCBARRAY+0,0xe0 jz !message # WDTR, SDTR or TAG??
+ test SCBARRAY+0,0xb0 jz !message # WDTR, SDTR or TAG??
cmp MSG_START+0,A jne !message # did driver beat us?
# Tag Message if Tag enabled in SCB control block. Use SCBPTR as the tag
@@ -470,78 +470,118 @@ ITloop:
p_dataout:
mvi 0 call scsisig # !CDO|!IOO|!MSGO
- call assert
- call sg_load
+ mvi DMAPARAMS,0x7d # WIDEODD|SCSIEN|SDMAEN|HDMAEN|
+ # DIRECTION|FIFORESET
+ jmp data_phase_init
- mvi DINDEX,HADDR
- mvi SCBARRAY+19 call bcopy_4
+# If we re-enter the data phase after going through another phase, the
+# STCNT may have been cleared, so restore it from the residual field.
+data_phase_reinit:
+ mvi DINDEX, STCNT
+ mvi SCBARRAY+15 call bcopy_3
+ jmp data_phase_loop
-# mvi DINDEX,HCNT # implicit since HCNT is next to HADDR
- mvi SCBARRAY+23 call bcopy_3
+# Reads should not use WIDEODD since it may make the last byte for a SG segment
+# go to the next segment.
+p_datain:
+ mvi 0x40 call scsisig # !CDO|IOO|!MSGO
+ mvi DMAPARAMS,0x39 # SCSIEN|SDMAEN|HDMAEN|
+ # !DIRECTION|FIFORESET
+data_phase_init:
+ call assert
- mvi DINDEX,STCNT
- mvi SCBARRAY+23 call bcopy_3
+ test FLAGS, DPHASE jnz data_phase_reinit
+ call sg_scb2ram
+ or FLAGS, DPHASE # We have seen a data phase
+data_phase_loop:
# If we are the last SG block, don't set wideodd.
- test SCBARRAY+18,0xff jnz p_dataout_wideodd
- mvi 0x3d call dma # SCSIEN|SDMAEN|HDMAEN|
- # DIRECTION|FIFORESET
- jmp p_dataout_rest
+ cmp SG_COUNT,0x01 jne data_phase_wideodd
+ and DMAPARAMS, 0xbf # Turn off WIDEODD
+data_phase_wideodd:
+ mov DMAPARAMS call dma
-p_dataout_wideodd:
- mvi 0xbd call dma # WIDEODD|SCSIEN|SDMAEN|HDMAEN|
- # DIRECTION|FIFORESET
+# Exit if we had an underrun
+ test SSTAT0,0x04 jz data_phase_finish # underrun STCNT != 0
-p_dataout_rest:
-# After a DMA finishes, save the final transfer pointer and count
-# back into the SCB, in case a device disconnects in the middle of
-# a transfer. Use SHADDR and STCNT instead of HADDR and HCNT, since
-# it's a reflection of how many bytes were transferred on the SCSI
-# (as opposed to the host) bus.
+# Advance the scatter-gather pointers if needed
#
- mvi DINDEX,SCBARRAY+23
- mvi STCNT call bcopy_3
-
- mvi DINDEX,SCBARRAY+19
- mvi SHADDR call bcopy_4
+sg_advance:
+ dec SG_COUNT # one less segment to go
- call sg_advance
- mov SCBARRAY+18,SG_COUNT # residual S/G count
+ test SG_COUNT, 0xff jz data_phase_finish #Are we done?
- jmp ITloop
+ clr A # add sizeof(struct scatter)
+ add SG_NEXT+0,SG_SIZEOF,SG_NEXT+0
+ adc SG_NEXT+1,A,SG_NEXT+1
+ adc SG_NEXT+2,A,SG_NEXT+2
+ adc SG_NEXT+3,A,SG_NEXT+3
-p_datain:
- mvi 0x40 call scsisig # !CDO|IOO|!MSGO
- call assert
- call sg_load
+# Load a struct scatter and set up the data address and length.
+# If the working value of the SG count is nonzero, then
+# we need to load a new set of values.
+#
+# This, like all DMA's, assumes a little-endian host data storage.
+#
+sg_load:
+ clr HCNT+2
+ clr HCNT+1
+ mvi HCNT+0,SG_SIZEOF
mvi DINDEX,HADDR
- mvi SCBARRAY+19 call bcopy_4
+ mvi SG_NEXT call bcopy_4
-# mvi DINDEX,HCNT # implicit since HCNT is next to HADDR
- mvi SCBARRAY+23 call bcopy_3
+ mvi DFCNTRL,0xd # HDMAEN|DIRECTION|FIFORESET
- mvi DINDEX,STCNT
- mvi SCBARRAY+23 call bcopy_3
+# Wait for DMA from host memory to data FIFO to complete, then disable
+# DMA and wait for it to acknowledge that it's off.
+#
+ call dma_finish
-# If we are the last SG block, don't set wideodd.
- test SCBARRAY+18,0xff jnz p_datain_wideodd
- mvi 0x39 call dma # SCSIEN|SDMAEN|HDMAEN|
- # !DIRECTION|FIFORESET
- jmp p_datain_rest
-p_datain_wideodd:
- mvi 0xb9 call dma # WIDEODD|SCSIEN|SDMAEN|HDMAEN|
- # !DIRECTION|FIFORESET
-p_datain_rest:
- mvi DINDEX,SCBARRAY+23
- mvi STCNT call bcopy_3
+# Copy data from FIFO into SCB data pointer and data count. This assumes
+# that the struct scatterlist has this structure (this and sizeof(struct
+# scatterlist) == 12 are asserted in aic7xxx.c):
+#
+# struct scatterlist {
+# char *address; /* four bytes, little-endian order */
+# ... /* four bytes, ignored */
+# unsigned short length; /* two bytes, little-endian order */
+# }
+#
- mvi DINDEX,SCBARRAY+19
- mvi SHADDR call bcopy_4
+# Not in FreeBSD. the scatter list entry is only 8 bytes.
+#
+# struct ahc_dma_seg {
+# physaddr addr; /* four bytes, little-endian order */
+# long len; /* four bytes, little endian order */
+# };
+#
- call sg_advance
- mov SCBARRAY+18,SG_COUNT # residual S/G count
+ mvi DINDEX,HADDR
+ call bcopy_7_dfdat
+# For Linux, we must throw away four bytes since there is a 32bit gap
+# in the middle of a struct scatterlist
+# call bcopy_4_dfdat
+# mov NONE,DFDAT
+# mov NONE,DFDAT
+# mov NONE,DFDAT
+# mov NONE,DFDAT
+# call bcopy_3_dfdat #Only support 24 bit length.
+
+# Load STCNT as well. It is a mirror of HCNT
+ mvi DINDEX,STCNT
+ mvi HCNT call bcopy_3
+ test SSTAT1,PHASEMIS jz data_phase_loop
+
+data_phase_finish:
+# After a DMA finishes, save the SG and STCNT residuals back into the SCB
+# We use STCNT instead of HCNT, since it's a reflection of how many bytes
+# were transferred on the SCSI (as opposed to the host) bus.
+#
+ mvi DINDEX,SCBARRAY+15
+ mvi STCNT call bcopy_3
+ mov SCBARRAY+18, SG_COUNT
jmp ITloop
# Command phase. Set up the DMA registers and let 'er rip - the
@@ -552,11 +592,9 @@ p_command:
mvi 0x80 call scsisig # CDO|!IOO|!MSGO
call assert
+# Load HADDR and HCNT. We can do this in one bcopy since they are neighbors
mvi DINDEX,HADDR
- mvi SCBARRAY+7 call bcopy_4
-
-# mvi DINDEX,HCNT # implicit since HCNT is next to HADDR
- mvi SCBARRAY+11 call bcopy_3
+ mvi SCBARRAY+7 call bcopy_7
mvi DINDEX,STCNT
mvi SCBARRAY+11 call bcopy_3
@@ -678,9 +716,7 @@ p_mesgin:
# before the command complete code tried processing it.
# First check for residuals
- test SCBARRAY+15,0xff jnz resid
- test SCBARRAY+16,0xff jnz resid
- test SCBARRAY+17,0xff jnz resid
+ test SCBARRAY+18,0xff jnz resid
check_status:
test SCBARRAY+14,0xff jz status_ok # 0 Status?
@@ -690,7 +726,7 @@ check_status:
status_ok:
# First, mark this target as free.
- test SCBARRAY+0,0x20 jnz complete # Tagged command
+ test SCBARRAY+0,TAG_ENB jnz complete # Tagged command
and FUNCTION1,0x70,SCBARRAY+1
mov A,FUNCTION1
test SCBARRAY+1,0x88 jz clear_a
@@ -774,7 +810,7 @@ p_mesginSDTR:
p_mesgin2:
cmp A,4 jne p_mesgin3 # disconnect code?
- or SCBARRAY+0,0x4 # set "disconnected" bit
+ or SCBARRAY+0,DISCONNECTED
jmp p_mesgin_done
# Save data pointers message? Copy working values into the SCB,
@@ -787,13 +823,15 @@ p_mesgin3:
jmp p_mesgin_done
# Restore pointers message? Data pointers are recopied from the
-# SCB anyway at the start of any DMA operation, so the only thing
-# to copy is the scatter-gather values.
+# 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.
#
p_mesgin4:
cmp A,3 jne p_mesgin5 # restore pointers code?
- call sg_scb2ram
+ and FLAGS,0xfb # !DPHASE we'll reload them
+ # the next time through
jmp p_mesgin_done
# Identify message? For a reconnecting target, this tells us the lun
@@ -816,8 +854,6 @@ setup_SCB:
and SCBARRAY+0,0xfb # clear disconnect bit in SCB
or FLAGS,IDENTIFY_SEEN # make note of IDENTIFY
- call sg_scb2ram # implied restore pointers
- # required on reselect
jmp ITloop
get_tag:
mvi A call inb_first
@@ -885,30 +921,31 @@ p_busfree:
jmp poll_for_work
# Instead of a generic bcopy routine that requires an argument, we unroll
-# the two cases that are actually used, and call them explicitly. This
-# not only reduces the overhead of doing a bcopy by 2/3rds, but ends up
-# saving space in the program since you don't have to put the argument
-# into the accumulator before the call. Both functions expect DINDEX to
-# contain the destination address and SINDEX to contain the source
-# address.
-bcopy_3:
+# the cases that are actually used, and call them explicitly. This
+# not only reduces the overhead of doing a bcopy, but ends up saving space
+# in the program since you don't have to put the argument into the accumulator
+# before the call. Both functions expect DINDEX to contain the destination
+# address and SINDEX to contain the source address.
+bcopy_7:
mov DINDIR,SINDIR
mov DINDIR,SINDIR
- mov DINDIR,SINDIR ret
-
+bcopy_5:
+ mov DINDIR,SINDIR
bcopy_4:
mov DINDIR,SINDIR
+bcopy_3:
mov DINDIR,SINDIR
mov DINDIR,SINDIR
mov DINDIR,SINDIR ret
-bcopy_3_dfdat:
+bcopy_7_dfdat:
mov DINDIR,DFDAT
mov DINDIR,DFDAT
- mov DINDIR,DFDAT ret
-
+bcopy_5_dfdat:
+ mov DINDIR,DFDAT
bcopy_4_dfdat:
mov DINDIR,DFDAT
+bcopy_3_dfdat:
mov DINDIR,DFDAT
mov DINDIR,DFDAT
mov DINDIR,DFDAT ret
@@ -976,7 +1013,6 @@ inb_last1:
dma:
mov DFCNTRL,SINDEX
dma1:
-dma2:
test SSTAT0,0x1 jnz dma3 # DMADONE
test SSTAT1,0x10 jz dma1 # PHASEMIS, ie. underrun
@@ -992,19 +1028,14 @@ dma3:
dma4:
test DFSTATUS,0x1 jz dma4 # !FIFOEMP
-# Now shut the DMA enables off, and copy STCNT (ie. the underrun
-# amount, if any) to the SCB registers; SG_COUNT will get copied to
-# the SCB's residual S/G count field after sg_advance is called. Make
-# sure that the DMA enables are actually off first lest we get an ILLSADDR.
+# Now shut the DMA enables off and make sure that the DMA enables are
+# actually off first lest we get an ILLSADDR.
#
dma5:
clr DFCNTRL # disable DMA
dma6:
test DFCNTRL,0x38 jnz dma6 # SCSIENACK|SDMAENACK|HDMAENACK
- mvi DINDEX,SCBARRAY+15
- mvi STCNT call bcopy_3
-
ret
dma_finish:
@@ -1036,10 +1067,9 @@ initialize_for_target:
mvi SXFRCTL0,0x8a # DFON|SPIOEN|CLRCHN
-# Initialize scatter-gather pointers by setting up the working copy
-# in scratch RAM.
-#
- call sg_scb2ram
+# Make sure that the system knows we have not been through a DATA
+# phase.
+ and FLAGS, 0xfb # !DPHASE
# Initialize SCSIRATE with the appropriate value for this target.
#
@@ -1055,29 +1085,6 @@ assert:
mvi INTSTAT,NO_IDENT ret # no - cause a kernel panic
-# Find out if disconnection is ok from the information the BIOS has left
-# us. The tcl from SCBARRAY+1 should be in SINDEX; A will
-# contain either 0x40 (disconnection ok) or 0x00 (disconnection not ok)
-# on exit.
-#
-# To allow for wide or twin busses, we check the upper bit of the target ID
-# and the channel ID and look at the appropriate disconnect register.
-#
-disconnect:
- and FUNCTION1,0x70,SINDEX # strip off extra just in case
- mov A,FUNCTION1
- test SINDEX, 0x88 jz disconnect_a
-
- test DISC_DSB_B,A jz disconnect1 # bit nonzero if DISabled
- clr A ret
-
-disconnect_a:
- test DISC_DSB_A,A jz disconnect1 # bit nonzero if DISabled
- clr A ret
-
-disconnect1:
- mvi A,0x40 ret
-
# Locate the SCB matching the target ID/channel/lun in SAVED_TCL and switch
# the SCB to it. Have the kernel print a warning message if it can't be
# found, and generate an ABORT message to the target. SINDEX should be
@@ -1087,7 +1094,7 @@ findSCB:
mov A,SAVED_TCL
mov SCBPTR,SINDEX # switch to new SCB
cmp SCBARRAY+1,A jne findSCB1 # target ID/channel/lun match?
- test SCBARRAY+0,0x4 jz findSCB1 # should be disconnected
+ test SCBARRAY+0,DISCONNECTED jz findSCB1 # should be disconnected
test SCBARRAY+0,TAG_ENB jnz get_tag
ret
@@ -1103,113 +1110,40 @@ findSCB1:
call scsisig
ret
-# Make a working copy of the scatter-gather parameters in the SCB.
+# Make a working copy of the scatter-gather parameters from the SCB.
#
sg_scb2ram:
+ mvi DINDEX,HADDR
+ mvi SCBARRAY+19 call bcopy_7
+
+ mvi DINDEX,STCNT
+ mvi SCBARRAY+23 call bcopy_3
+
mov SG_COUNT,SCBARRAY+2
mvi DINDEX,SG_NEXT
mvi SCBARRAY+3 call bcopy_4
+ ret
- mvi SG_NOLOAD,0x80
- test SCBARRAY+0,0x10 jnz return # don't reload s/g?
- clr SG_NOLOAD ret
-
-# Copying RAM values back to SCB, for 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.
#
sg_ram2scb:
+ test FLAGS, DPHASE jz return
mov SCBARRAY+2,SG_COUNT
mvi DINDEX,SCBARRAY+3
mvi SG_NEXT call bcopy_4
+
+ mvi DINDEX,SCBARRAY+19
+ mvi SHADDR call bcopy_4
- and SCBARRAY+0,0xef,SCBARRAY+0
- test SG_NOLOAD,0x80 jz return # reload s/g?
- or SCBARRAY+0,SG_LOAD ret
-
-# Load a struct scatter if needed and set up the data address and
-# length. If the working value of the SG count is nonzero, then
-# we need to load a new set of values.
-#
-# This, like the above DMA, assumes a little-endian host data storage.
-#
-sg_load:
- test SG_COUNT,0xff jz return # SG being used?
- test SG_NOLOAD,0x80 jnz return # don't reload s/g?
-
- clr HCNT+2
- clr HCNT+1
- mvi HCNT+0,SG_SIZEOF
-
- mvi DINDEX,HADDR
- mvi SG_NEXT call bcopy_4
-
- 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.
-#
-
- call dma_finish
-
-# Copy data from FIFO into SCB data pointer and data count. This assumes
-# that the struct scatterlist has this structure (this and sizeof(struct
-# scatterlist) == 12 are asserted in aic7xxx.c):
-#
-# struct scatterlist {
-# char *address; /* four bytes, little-endian order */
-# ... /* four bytes, ignored */
-# unsigned short length; /* two bytes, little-endian order */
-# }
-#
-
-# Not in FreeBSD. the scatter list entry is only 8 bytes.
-#
-# struct ahc_dma_seg {
-# physaddr addr; /* four bytes, little-endian order */
-# long len; /* four bytes, little endian order */
-# };
-#
-
- mvi DINDEX, SCBARRAY+19
- call bcopy_4_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
-
- call bcopy_3_dfdat #Only support 24 bit length.
+# Use the residual number since STCNT is corrupted by any message transfer
+ mvi SCBARRAY+15 call bcopy_3
ret
-# Advance the scatter-gather pointers only IF NEEDED. If SG is enabled,
-# and the SCSI transfer count is zero (note that this should be called
-# right after a DMA finishes), then move the working copies of the SG
-# pointer/length along. If the SCSI transfer count is not zero, then
-# presumably the target is disconnecting - do not reload the SG values
-# next time.
-#
-sg_advance:
- test SG_COUNT,0xff jz return # s/g enabled?
-
- test STCNT+0,0xff jnz sg_advance1 # SCSI transfer count nonzero?
- test STCNT+1,0xff jnz sg_advance1
- test STCNT+2,0xff jnz sg_advance1
-
- clr SG_NOLOAD # reload s/g next time
- dec SG_COUNT # one less segment to go
-
- clr A # add sizeof(struct scatter)
- add SG_NEXT+0,SG_SIZEOF,SG_NEXT+0
- adc SG_NEXT+1,A,SG_NEXT+1
- adc SG_NEXT+2,A,SG_NEXT+2
- adc SG_NEXT+3,A,SG_NEXT+3 ret
-
-sg_advance1:
- mvi SG_NOLOAD,0x80 ret # don't reload s/g next time
-
# Add the array base SYNCNEG to the target offset (the target address
# is in SCSIID), and return the result in SINDEX. The accumulator
# contains the 3->8 decoding of the target ID on return.
@@ -1231,7 +1165,7 @@ ndx_dtr_2:
# reject, you wouldn't be able to tell which message was the culpret.
#
mk_dtr:
- test SCBARRAY+0,0xc0 jz return # NEEDWDTR|NEEDSDTR
+ test SCBARRAY+0,0x90 jz return # NEEDWDTR|NEEDSDTR
test SCBARRAY+0,NEEDWDTR jnz mk_wdtr_16bit
or FLAGS, MAX_OFFSET # Force an offset of 15 or 8 if WIDE
OpenPOWER on IntegriCloud