Update the sequencer code to handle both channels of Twin channel devices.

You can now sling 14 devices off of a 274xT.  In the process of adding
twin channel support, I removed all evident restrictions on supporting
Wide channeled devices, but I do not have a Wide controller to test them
on.

aic7770_seq.h, the pre-compiled header, is no longer needed since config
handles this dependancy.
This commit is contained in:
Justin T. Gibbs 1994-12-31 19:26:54 +00:00
parent 528486881b
commit 8ff1d93efb
3 changed files with 435 additions and 165 deletions

View File

@ -64,7 +64,8 @@ QINFIFO = 0x9b
QINCNT = 0x9c
QOUTFIFO = 0x9d
SCSICONF = 0x5a
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
@ -98,16 +99,17 @@ SIGNAL_4 = 0x41 # SDTR -> SCSIRATE conversion
STATUS_ERROR = 0x51
# The host adapter card (at least the BIOS) uses 20-2f for SCSI
# device information, 32-33 and 5a-5f as well. Since we don't support
# wide or twin-bus SCSI, 28-2f can be reclaimed. As it turns out, the
# BIOS trashes 20-27 anyway, writing the synchronous negotiation results
# device information, 32-33 and 5a-5f as well. As it turns out, the
# BIOS trashes 20-2f, writing the synchronous negotiation results
# on top of the BIOS values, so we re-use those for our per-target
# scratchspace (actually a value that can be copied directly into
# SCSIRATE). This implies, since we can't get the BIOS config values,
# that all targets will be negotiated with for synchronous transfer.
# NEEDSDTR has one bit per target indicating if an SDTR message is
# needed for that device - this will be set initially, as well as
# after a bus reset condition.
# 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.
#
# 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
@ -124,10 +126,11 @@ STATUS_ERROR = 0x51
# Note that SG_NEXT occupies four bytes.
#
SYNCNEG = 0x20
DISC_DSB_A = 0x32
DROPATN = 0x30
REJBYTE = 0x31
DISC_DSB_A = 0x32
DISC_DSB_B = 0x33
RESELECT = 0x34
MSG_FLAGS = 0x35
@ -141,11 +144,11 @@ MSG_START+5 = 0x3c
-MSG_START+0 = 0xc9 # 2's complement of MSG_START+0
ARG_1 = 0x4c # sdtr conversion args & return
ARG_2 = 0x4d
RETURN_1 = 0x4c
SIGSTATE = 0x4e # value written to SCSISIGO
NEEDSDTR = 0x4f # send SDTR message, 1 bit/trgt
SIGSTATE = 0x4d # value written to SCSISIGO
NEEDSDTR_A = 0x4e # send SDTR message, 1 bit/trgt
NEEDSDTR_B = 0x4f
SG_SIZEOF = 0x8 # sizeof(struct scatterlist)
SG_NOLOAD = 0x50 # load SG pointer/length?
@ -157,12 +160,24 @@ SG_NEXT+2 = 0x54
SG_NEXT+3 = 0x55
SCBCOUNT = 0x56 # the actual number of SCBs
ACTIVE_A = 0x57
FLAGS = 0x57 # Device configuration flags
TWIN_BUS = 0x01
WIDE_BUS = 0x02
ACTIVE_A = 0x58
ACTIVE_B = 0x59
# Poll QINCNT for work - the lower bits contain
# the number of entries in the Queue In FIFO.
#
start:
test FLAGS,TWIN_BUS jz start2 # Are we a twin channel device?
# For fairness, we check the other bus first, since we just finished a
# transaction on the current channel.
xor SBLKCTL,0x08 # Toggle to the other bus
test SCSISIGI,0x4 jnz reselect # BSYI
xor SBLKCTL,0x08 # Toggle to the original bus
start2:
test SCSISIGI,0x4 jnz reselect # BSYI
test QINCNT,SCBMASK jz start
@ -174,18 +189,34 @@ start:
mov SCBPTR,QINFIFO
# See if there is not already an active SCB for this target. This code
# will have to be modified when we add support for dual and wide busses.
# 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
# time, it is faster than looping through all SCB's looking for active
# commands. It may be benificial to make findscb a more general procedure
# to see if the added cost of the search is negligible. This code also
# assumes that the kernel driver will clear the active flags on board
# initialization, board reset, and a target's SELTO.
and FUNCTION1,0x70,SCBARRAY+1
mov A,FUNCTION1
test ACTIVE_A,A jz active
test SCBARRAY+1,0x88 jz test_a # Id < 8 && A channel
test ACTIVE_B,A jnz requeue
or ACTIVE_B,A # Mark the current target as busy
jmp start_scb
# Place the currently active back on the queue for later processing
requeue:
mov QINFIFO, SCBPTR
jmp start
# Mark the current target as busy and get working on the SCB
active:
or ACTIVE_A,A
test_a:
test ACTIVE_A,A jnz requeue
or ACTIVE_A,A # Mark the current target as busy
start_scb:
and A,0x08,SCBARRAY+1
mov SBLKCTL,A # select channel, !wide
mov SCBARRAY+1 call initialize
clr SG_NOLOAD
clr RESELECT
@ -485,24 +516,37 @@ p_mesgin:
# We got a "command complete" message, so put the SCB pointer
# into the Queue Out, and trigger a completion interrupt.
# Check status for non zero return and interrupt driver if needed
# This allows the driver to do a sense command to find out the
# source of error. We don't bother to post to the QOUTFIFO in
# the error case since it would require extra work in the kernel
# driver to ensure that the entry was removed before the command
# complete code tried processing it.
# First, mark this target as free.
and FUNCTION1,0x70,SCBARRAY+1
mov A,FUNCTION1
xor ACTIVE_A,A
# This allows the driver to interpret errors only when they occur
# instead of always uploading the scb. If the status is SCSI_CHECK,
# the driver will download a new scb requesting sense, to replace
# the old one and the sequencer code will imediately jump to start
# working on it. If the kernel driver does not wish to request sense,
# the sequencer program counter is incremented by 1, preventing another run
# on the current SCB and the command is allowed to complete. We don't
# bother to post to the QOUTFIFO in the error case since it would require
# 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?
call inb_last # ack & turn auto PIO back on
mvi INTSTAT,STATUS_ERROR # let driver know
jmp ITloop
jmp start_scb
status_ok:
# First, mark this target as free.
and FUNCTION1,0x70,SCBARRAY+1
mov A,FUNCTION1
test SCBARRAY+1,0x88 jz clear_a
xor ACTIVE_B,A
jmp complete
clear_a:
xor ACTIVE_A,A
complete:
mov QOUTFIFO,SCBPTR
mvi INTSTAT,0x2 # CMDCMPLT
mvi INTSTAT,0x02 # CMDCMPLT
jmp p_mesgin_done
# Is it an extended message? We only support the synchronous data
@ -523,15 +567,24 @@ p_mesgin1:
cmp A,1 jne p_mesginN # SDTR code
mvi ARG_1 call inb_next # xfer period
mvi ARG_2 call inb_next # REQ/ACK offset
mvi A call inb_next # REQ/ACK offset
mvi INTSTAT,SIGNAL_4 # call driver to convert
call ndx_sdtr # index sync config for target
mov DINDEX,SINDEX
mov DINDIR,RETURN_1 # save returned value
not A # turn off "need sdtr" flag
and NEEDSDTR,A
test SBLKCTL,0x08 jnz p_mesgin1_b
test SCSIID,0x80 jnz p_mesgin1_b
and NEEDSDTR_A,A
jmp p_mesgin1_save
p_mesgin1_b:
and NEEDSDTR_B,A
p_mesgin1_save:
and A,0x80,SINDIR # get the WIDEXFER flag
or RETURN_1,A # Set WIDEXFER if necessary
mov DINDIR,RETURN_1 # save returned value
# Even though the SCSI-2 specification says that a device responding
# to our SDTR message should honor our parameters for transmitting
@ -587,7 +640,7 @@ p_mesgin5:
#
test MSG_FLAGS,0x80 jnz p_mesgin_done
xor SCBARRAY+0,0x4 # clear disconnect bit in SCB
and SCBARRAY+0,0xfb # clear disconnect bit in SCB
mvi RESELECT,0xc0 # make note of IDENTIFY
call sg_scb2ram # implied restore pointers
@ -606,14 +659,28 @@ p_mesgin6:
and FUNCTION1,0x70,SCSIID # outstanding SDTR message?
mov A,FUNCTION1
test NEEDSDTR,A jz p_mesgin_done # no - ignore rejection
test SBLKCTL,0x08 jnz p_mesgin6_b
test SCSIID,0x80 jnz p_mesgin6_b
test NEEDSDTR_A,A jz p_mesgin_done # no - ignore rejection
call ndx_sdtr # note use of asynch xfer
mov DINDEX,SINDEX
clr DINDIR
not A # turn off "active sdtr" flag
and NEEDSDTR,A
not A
and NEEDSDTR_A,A
jmp p_mesgin6_done
p_mesgin6_b:
test NEEDSDTR_B,A jz p_mesgin_done # no - ignore rejection
call ndx_sdtr # note use of asynch xfer
mov DINDEX,SINDEX
clr DINDIR
not A
and NEEDSDTR_B,A
p_mesgin6_done:
clr SCSIRATE # select asynch xfer
jmp p_mesgin_done
@ -772,7 +839,7 @@ dma2:
dma3:
test SINDEX,0x4 jnz dma5 # DIRECTION
dma4:
test DFSTATUS,0x1 jz dma4 # FIFOFLUSHACK
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
@ -795,9 +862,20 @@ dma6:
# contents are stomped on return.
#
initialize:
clr SBLKCTL # channel A, !wide
and SCSIID,0xf0,SINDEX # target ID
and A,0x7,SCSICONF # SCSI_ID_A[210]
test SBLKCTL,0x08 jnz initialize_b
mvi SINDEX,SCSICONF_A
test FLAGS,WIDE_BUS jnz initialize_wide
and A,0x7,SCSICONF_A # SCSI_ID_A[210]
jmp initialize_2
initialize_b:
and A,0x7,SCSICONF_B # SCSI_ID_B[210]
mvi SCSICONF_B jmp initialize_2
initialize_wide:
and A, 0xf,SCSICONF_B
initialize_2:
or SCSIID,A
# Esundry initialization.
@ -821,8 +899,8 @@ initialize:
#
# STPWEN is 7870-specific, enabling an external termination power source.
#
and A,0x38,SCSICONF # PARITY_ENB_A|SEL_TIM_A[10]
or SXFRCTL1,0x5,A # ENSTIMER|STPWEN
and A,0x38,SINDIR # PARITY_ENB|SEL_TIM[10]
or SXFRCTL1,0x7,A # ENSTIMER|ACTNEGEN|STPWEN
mvi SIMODE1,0x84 # ENSELTIMO|ENSCSIPERR
# Initialize scatter-gather pointers by setting up the working copy
@ -849,19 +927,25 @@ assert1:
ret
# Find out if disconnection is ok from the information the BIOS has left
# us. The target ID should be in the upper four bits of SINDEX; A will
# us. The tcl from SCBARRAY+1 should be in SINDEX; A will
# contain either 0x40 (disconnection ok) or 0x00 (disconnection not ok)
# on exit.
#
# This is the only place the target ID is limited to three bits, so we
# can use the FUNCTION1 register.
# 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 DISC_DSB_A,A jz disconnect1 # bit nonzero if DISabled
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
@ -874,9 +958,10 @@ disconnect1:
#
findSCB:
and A,0x7,SINDEX # lun in lower three bits
or DINDEX,A,SELID # can I do this?
and DINDEX,0xf7 # only channel A implemented
or DINDEX,A,SELID
and DINDEX,0xf7
and A,0x08,SBLKCTL # B Channel??
or DINDEX,A
clr SINDEX
findSCB1:
@ -884,7 +969,6 @@ findSCB1:
mov SCBPTR,SINDEX # switch to new SCB
cmp SCBARRAY+1,A jne findSCB2 # target ID/channel/lun match?
test SCBARRAY+0,0x4 jz findSCB2 # should be disconnected
ret
findSCB2:
@ -1029,7 +1113,9 @@ sg_advance2:
#
ndx_sdtr:
shr A,SCSIID,4
and A,0x7
test SBLKCTL,0x08 jz ndx_sdtr_2
or A,0x08 # Channel B entries add 8
ndx_sdtr_2:
add SINDEX,SYNCNEG,A
and FUNCTION1,0x70,SCSIID # 3-bit target address decode
@ -1042,7 +1128,11 @@ mk_sdtr:
mov DINDEX,SINDEX # save SINDEX
call ndx_sdtr
test NEEDSDTR,A jnz mk_sdtr1 # do we need negotiation?
test SCBARRAY+1,0x88 jz mk_sdtr1_a
test NEEDSDTR_B,A jnz mk_sdtr1 # do we need negotiation?
ret
mk_sdtr1_a:
test NEEDSDTR_A,A jnz mk_sdtr1 # do we need negotiation?
ret
mk_sdtr1:

View File

@ -64,7 +64,8 @@ QINFIFO = 0x9b
QINCNT = 0x9c
QOUTFIFO = 0x9d
SCSICONF = 0x5a
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
@ -98,16 +99,17 @@ SIGNAL_4 = 0x41 # SDTR -> SCSIRATE conversion
STATUS_ERROR = 0x51
# The host adapter card (at least the BIOS) uses 20-2f for SCSI
# device information, 32-33 and 5a-5f as well. Since we don't support
# wide or twin-bus SCSI, 28-2f can be reclaimed. As it turns out, the
# BIOS trashes 20-27 anyway, writing the synchronous negotiation results
# device information, 32-33 and 5a-5f as well. As it turns out, the
# BIOS trashes 20-2f, writing the synchronous negotiation results
# on top of the BIOS values, so we re-use those for our per-target
# scratchspace (actually a value that can be copied directly into
# SCSIRATE). This implies, since we can't get the BIOS config values,
# that all targets will be negotiated with for synchronous transfer.
# NEEDSDTR has one bit per target indicating if an SDTR message is
# needed for that device - this will be set initially, as well as
# after a bus reset condition.
# 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.
#
# 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
@ -124,10 +126,11 @@ STATUS_ERROR = 0x51
# Note that SG_NEXT occupies four bytes.
#
SYNCNEG = 0x20
DISC_DSB_A = 0x32
DROPATN = 0x30
REJBYTE = 0x31
DISC_DSB_A = 0x32
DISC_DSB_B = 0x33
RESELECT = 0x34
MSG_FLAGS = 0x35
@ -141,11 +144,11 @@ MSG_START+5 = 0x3c
-MSG_START+0 = 0xc9 # 2's complement of MSG_START+0
ARG_1 = 0x4c # sdtr conversion args & return
ARG_2 = 0x4d
RETURN_1 = 0x4c
SIGSTATE = 0x4e # value written to SCSISIGO
NEEDSDTR = 0x4f # send SDTR message, 1 bit/trgt
SIGSTATE = 0x4d # value written to SCSISIGO
NEEDSDTR_A = 0x4e # send SDTR message, 1 bit/trgt
NEEDSDTR_B = 0x4f
SG_SIZEOF = 0x8 # sizeof(struct scatterlist)
SG_NOLOAD = 0x50 # load SG pointer/length?
@ -157,12 +160,24 @@ SG_NEXT+2 = 0x54
SG_NEXT+3 = 0x55
SCBCOUNT = 0x56 # the actual number of SCBs
ACTIVE_A = 0x57
FLAGS = 0x57 # Device configuration flags
TWIN_BUS = 0x01
WIDE_BUS = 0x02
ACTIVE_A = 0x58
ACTIVE_B = 0x59
# Poll QINCNT for work - the lower bits contain
# the number of entries in the Queue In FIFO.
#
start:
test FLAGS,TWIN_BUS jz start2 # Are we a twin channel device?
# For fairness, we check the other bus first, since we just finished a
# transaction on the current channel.
xor SBLKCTL,0x08 # Toggle to the other bus
test SCSISIGI,0x4 jnz reselect # BSYI
xor SBLKCTL,0x08 # Toggle to the original bus
start2:
test SCSISIGI,0x4 jnz reselect # BSYI
test QINCNT,SCBMASK jz start
@ -174,18 +189,34 @@ start:
mov SCBPTR,QINFIFO
# See if there is not already an active SCB for this target. This code
# will have to be modified when we add support for dual and wide busses.
# 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
# time, it is faster than looping through all SCB's looking for active
# commands. It may be benificial to make findscb a more general procedure
# to see if the added cost of the search is negligible. This code also
# assumes that the kernel driver will clear the active flags on board
# initialization, board reset, and a target's SELTO.
and FUNCTION1,0x70,SCBARRAY+1
mov A,FUNCTION1
test ACTIVE_A,A jz active
test SCBARRAY+1,0x88 jz test_a # Id < 8 && A channel
test ACTIVE_B,A jnz requeue
or ACTIVE_B,A # Mark the current target as busy
jmp start_scb
# Place the currently active back on the queue for later processing
requeue:
mov QINFIFO, SCBPTR
jmp start
# Mark the current target as busy and get working on the SCB
active:
or ACTIVE_A,A
test_a:
test ACTIVE_A,A jnz requeue
or ACTIVE_A,A # Mark the current target as busy
start_scb:
and A,0x08,SCBARRAY+1
mov SBLKCTL,A # select channel, !wide
mov SCBARRAY+1 call initialize
clr SG_NOLOAD
clr RESELECT
@ -485,24 +516,37 @@ p_mesgin:
# We got a "command complete" message, so put the SCB pointer
# into the Queue Out, and trigger a completion interrupt.
# Check status for non zero return and interrupt driver if needed
# This allows the driver to do a sense command to find out the
# source of error. We don't bother to post to the QOUTFIFO in
# the error case since it would require extra work in the kernel
# driver to ensure that the entry was removed before the command
# complete code tried processing it.
# First, mark this target as free.
and FUNCTION1,0x70,SCBARRAY+1
mov A,FUNCTION1
xor ACTIVE_A,A
# This allows the driver to interpret errors only when they occur
# instead of always uploading the scb. If the status is SCSI_CHECK,
# the driver will download a new scb requesting sense, to replace
# the old one and the sequencer code will imediately jump to start
# working on it. If the kernel driver does not wish to request sense,
# the sequencer program counter is incremented by 1, preventing another run
# on the current SCB and the command is allowed to complete. We don't
# bother to post to the QOUTFIFO in the error case since it would require
# 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?
call inb_last # ack & turn auto PIO back on
mvi INTSTAT,STATUS_ERROR # let driver know
jmp ITloop
jmp start_scb
status_ok:
# First, mark this target as free.
and FUNCTION1,0x70,SCBARRAY+1
mov A,FUNCTION1
test SCBARRAY+1,0x88 jz clear_a
xor ACTIVE_B,A
jmp complete
clear_a:
xor ACTIVE_A,A
complete:
mov QOUTFIFO,SCBPTR
mvi INTSTAT,0x2 # CMDCMPLT
mvi INTSTAT,0x02 # CMDCMPLT
jmp p_mesgin_done
# Is it an extended message? We only support the synchronous data
@ -523,15 +567,24 @@ p_mesgin1:
cmp A,1 jne p_mesginN # SDTR code
mvi ARG_1 call inb_next # xfer period
mvi ARG_2 call inb_next # REQ/ACK offset
mvi A call inb_next # REQ/ACK offset
mvi INTSTAT,SIGNAL_4 # call driver to convert
call ndx_sdtr # index sync config for target
mov DINDEX,SINDEX
mov DINDIR,RETURN_1 # save returned value
not A # turn off "need sdtr" flag
and NEEDSDTR,A
test SBLKCTL,0x08 jnz p_mesgin1_b
test SCSIID,0x80 jnz p_mesgin1_b
and NEEDSDTR_A,A
jmp p_mesgin1_save
p_mesgin1_b:
and NEEDSDTR_B,A
p_mesgin1_save:
and A,0x80,SINDIR # get the WIDEXFER flag
or RETURN_1,A # Set WIDEXFER if necessary
mov DINDIR,RETURN_1 # save returned value
# Even though the SCSI-2 specification says that a device responding
# to our SDTR message should honor our parameters for transmitting
@ -587,7 +640,7 @@ p_mesgin5:
#
test MSG_FLAGS,0x80 jnz p_mesgin_done
xor SCBARRAY+0,0x4 # clear disconnect bit in SCB
and SCBARRAY+0,0xfb # clear disconnect bit in SCB
mvi RESELECT,0xc0 # make note of IDENTIFY
call sg_scb2ram # implied restore pointers
@ -606,14 +659,28 @@ p_mesgin6:
and FUNCTION1,0x70,SCSIID # outstanding SDTR message?
mov A,FUNCTION1
test NEEDSDTR,A jz p_mesgin_done # no - ignore rejection
test SBLKCTL,0x08 jnz p_mesgin6_b
test SCSIID,0x80 jnz p_mesgin6_b
test NEEDSDTR_A,A jz p_mesgin_done # no - ignore rejection
call ndx_sdtr # note use of asynch xfer
mov DINDEX,SINDEX
clr DINDIR
not A # turn off "active sdtr" flag
and NEEDSDTR,A
not A
and NEEDSDTR_A,A
jmp p_mesgin6_done
p_mesgin6_b:
test NEEDSDTR_B,A jz p_mesgin_done # no - ignore rejection
call ndx_sdtr # note use of asynch xfer
mov DINDEX,SINDEX
clr DINDIR
not A
and NEEDSDTR_B,A
p_mesgin6_done:
clr SCSIRATE # select asynch xfer
jmp p_mesgin_done
@ -772,7 +839,7 @@ dma2:
dma3:
test SINDEX,0x4 jnz dma5 # DIRECTION
dma4:
test DFSTATUS,0x1 jz dma4 # FIFOFLUSHACK
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
@ -795,9 +862,20 @@ dma6:
# contents are stomped on return.
#
initialize:
clr SBLKCTL # channel A, !wide
and SCSIID,0xf0,SINDEX # target ID
and A,0x7,SCSICONF # SCSI_ID_A[210]
test SBLKCTL,0x08 jnz initialize_b
mvi SINDEX,SCSICONF_A
test FLAGS,WIDE_BUS jnz initialize_wide
and A,0x7,SCSICONF_A # SCSI_ID_A[210]
jmp initialize_2
initialize_b:
and A,0x7,SCSICONF_B # SCSI_ID_B[210]
mvi SCSICONF_B jmp initialize_2
initialize_wide:
and A, 0xf,SCSICONF_B
initialize_2:
or SCSIID,A
# Esundry initialization.
@ -821,8 +899,8 @@ initialize:
#
# STPWEN is 7870-specific, enabling an external termination power source.
#
and A,0x38,SCSICONF # PARITY_ENB_A|SEL_TIM_A[10]
or SXFRCTL1,0x5,A # ENSTIMER|STPWEN
and A,0x38,SINDIR # PARITY_ENB|SEL_TIM[10]
or SXFRCTL1,0x7,A # ENSTIMER|ACTNEGEN|STPWEN
mvi SIMODE1,0x84 # ENSELTIMO|ENSCSIPERR
# Initialize scatter-gather pointers by setting up the working copy
@ -849,19 +927,25 @@ assert1:
ret
# Find out if disconnection is ok from the information the BIOS has left
# us. The target ID should be in the upper four bits of SINDEX; A will
# us. The tcl from SCBARRAY+1 should be in SINDEX; A will
# contain either 0x40 (disconnection ok) or 0x00 (disconnection not ok)
# on exit.
#
# This is the only place the target ID is limited to three bits, so we
# can use the FUNCTION1 register.
# 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 DISC_DSB_A,A jz disconnect1 # bit nonzero if DISabled
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
@ -874,9 +958,10 @@ disconnect1:
#
findSCB:
and A,0x7,SINDEX # lun in lower three bits
or DINDEX,A,SELID # can I do this?
and DINDEX,0xf7 # only channel A implemented
or DINDEX,A,SELID
and DINDEX,0xf7
and A,0x08,SBLKCTL # B Channel??
or DINDEX,A
clr SINDEX
findSCB1:
@ -884,7 +969,6 @@ findSCB1:
mov SCBPTR,SINDEX # switch to new SCB
cmp SCBARRAY+1,A jne findSCB2 # target ID/channel/lun match?
test SCBARRAY+0,0x4 jz findSCB2 # should be disconnected
ret
findSCB2:
@ -1029,7 +1113,9 @@ sg_advance2:
#
ndx_sdtr:
shr A,SCSIID,4
and A,0x7
test SBLKCTL,0x08 jz ndx_sdtr_2
or A,0x08 # Channel B entries add 8
ndx_sdtr_2:
add SINDEX,SYNCNEG,A
and FUNCTION1,0x70,SCSIID # 3-bit target address decode
@ -1042,7 +1128,11 @@ mk_sdtr:
mov DINDEX,SINDEX # save SINDEX
call ndx_sdtr
test NEEDSDTR,A jnz mk_sdtr1 # do we need negotiation?
test SCBARRAY+1,0x88 jz mk_sdtr1_a
test NEEDSDTR_B,A jnz mk_sdtr1 # do we need negotiation?
ret
mk_sdtr1_a:
test NEEDSDTR_A,A jnz mk_sdtr1 # do we need negotiation?
ret
mk_sdtr1:

View File

@ -64,7 +64,8 @@ QINFIFO = 0x9b
QINCNT = 0x9c
QOUTFIFO = 0x9d
SCSICONF = 0x5a
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
@ -98,16 +99,17 @@ SIGNAL_4 = 0x41 # SDTR -> SCSIRATE conversion
STATUS_ERROR = 0x51
# The host adapter card (at least the BIOS) uses 20-2f for SCSI
# device information, 32-33 and 5a-5f as well. Since we don't support
# wide or twin-bus SCSI, 28-2f can be reclaimed. As it turns out, the
# BIOS trashes 20-27 anyway, writing the synchronous negotiation results
# device information, 32-33 and 5a-5f as well. As it turns out, the
# BIOS trashes 20-2f, writing the synchronous negotiation results
# on top of the BIOS values, so we re-use those for our per-target
# scratchspace (actually a value that can be copied directly into
# SCSIRATE). This implies, since we can't get the BIOS config values,
# that all targets will be negotiated with for synchronous transfer.
# NEEDSDTR has one bit per target indicating if an SDTR message is
# needed for that device - this will be set initially, as well as
# after a bus reset condition.
# 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.
#
# 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
@ -124,10 +126,11 @@ STATUS_ERROR = 0x51
# Note that SG_NEXT occupies four bytes.
#
SYNCNEG = 0x20
DISC_DSB_A = 0x32
DROPATN = 0x30
REJBYTE = 0x31
DISC_DSB_A = 0x32
DISC_DSB_B = 0x33
RESELECT = 0x34
MSG_FLAGS = 0x35
@ -141,11 +144,11 @@ MSG_START+5 = 0x3c
-MSG_START+0 = 0xc9 # 2's complement of MSG_START+0
ARG_1 = 0x4c # sdtr conversion args & return
ARG_2 = 0x4d
RETURN_1 = 0x4c
SIGSTATE = 0x4e # value written to SCSISIGO
NEEDSDTR = 0x4f # send SDTR message, 1 bit/trgt
SIGSTATE = 0x4d # value written to SCSISIGO
NEEDSDTR_A = 0x4e # send SDTR message, 1 bit/trgt
NEEDSDTR_B = 0x4f
SG_SIZEOF = 0x8 # sizeof(struct scatterlist)
SG_NOLOAD = 0x50 # load SG pointer/length?
@ -157,12 +160,24 @@ SG_NEXT+2 = 0x54
SG_NEXT+3 = 0x55
SCBCOUNT = 0x56 # the actual number of SCBs
ACTIVE_A = 0x57
FLAGS = 0x57 # Device configuration flags
TWIN_BUS = 0x01
WIDE_BUS = 0x02
ACTIVE_A = 0x58
ACTIVE_B = 0x59
# Poll QINCNT for work - the lower bits contain
# the number of entries in the Queue In FIFO.
#
start:
test FLAGS,TWIN_BUS jz start2 # Are we a twin channel device?
# For fairness, we check the other bus first, since we just finished a
# transaction on the current channel.
xor SBLKCTL,0x08 # Toggle to the other bus
test SCSISIGI,0x4 jnz reselect # BSYI
xor SBLKCTL,0x08 # Toggle to the original bus
start2:
test SCSISIGI,0x4 jnz reselect # BSYI
test QINCNT,SCBMASK jz start
@ -174,18 +189,34 @@ start:
mov SCBPTR,QINFIFO
# See if there is not already an active SCB for this target. This code
# will have to be modified when we add support for dual and wide busses.
# 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
# time, it is faster than looping through all SCB's looking for active
# commands. It may be benificial to make findscb a more general procedure
# to see if the added cost of the search is negligible. This code also
# assumes that the kernel driver will clear the active flags on board
# initialization, board reset, and a target's SELTO.
and FUNCTION1,0x70,SCBARRAY+1
mov A,FUNCTION1
test ACTIVE_A,A jz active
test SCBARRAY+1,0x88 jz test_a # Id < 8 && A channel
test ACTIVE_B,A jnz requeue
or ACTIVE_B,A # Mark the current target as busy
jmp start_scb
# Place the currently active back on the queue for later processing
requeue:
mov QINFIFO, SCBPTR
jmp start
# Mark the current target as busy and get working on the SCB
active:
or ACTIVE_A,A
test_a:
test ACTIVE_A,A jnz requeue
or ACTIVE_A,A # Mark the current target as busy
start_scb:
and A,0x08,SCBARRAY+1
mov SBLKCTL,A # select channel, !wide
mov SCBARRAY+1 call initialize
clr SG_NOLOAD
clr RESELECT
@ -485,24 +516,37 @@ p_mesgin:
# We got a "command complete" message, so put the SCB pointer
# into the Queue Out, and trigger a completion interrupt.
# Check status for non zero return and interrupt driver if needed
# This allows the driver to do a sense command to find out the
# source of error. We don't bother to post to the QOUTFIFO in
# the error case since it would require extra work in the kernel
# driver to ensure that the entry was removed before the command
# complete code tried processing it.
# First, mark this target as free.
and FUNCTION1,0x70,SCBARRAY+1
mov A,FUNCTION1
xor ACTIVE_A,A
# This allows the driver to interpret errors only when they occur
# instead of always uploading the scb. If the status is SCSI_CHECK,
# the driver will download a new scb requesting sense, to replace
# the old one and the sequencer code will imediately jump to start
# working on it. If the kernel driver does not wish to request sense,
# the sequencer program counter is incremented by 1, preventing another run
# on the current SCB and the command is allowed to complete. We don't
# bother to post to the QOUTFIFO in the error case since it would require
# 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?
call inb_last # ack & turn auto PIO back on
mvi INTSTAT,STATUS_ERROR # let driver know
jmp ITloop
jmp start_scb
status_ok:
# First, mark this target as free.
and FUNCTION1,0x70,SCBARRAY+1
mov A,FUNCTION1
test SCBARRAY+1,0x88 jz clear_a
xor ACTIVE_B,A
jmp complete
clear_a:
xor ACTIVE_A,A
complete:
mov QOUTFIFO,SCBPTR
mvi INTSTAT,0x2 # CMDCMPLT
mvi INTSTAT,0x02 # CMDCMPLT
jmp p_mesgin_done
# Is it an extended message? We only support the synchronous data
@ -523,15 +567,24 @@ p_mesgin1:
cmp A,1 jne p_mesginN # SDTR code
mvi ARG_1 call inb_next # xfer period
mvi ARG_2 call inb_next # REQ/ACK offset
mvi A call inb_next # REQ/ACK offset
mvi INTSTAT,SIGNAL_4 # call driver to convert
call ndx_sdtr # index sync config for target
mov DINDEX,SINDEX
mov DINDIR,RETURN_1 # save returned value
not A # turn off "need sdtr" flag
and NEEDSDTR,A
test SBLKCTL,0x08 jnz p_mesgin1_b
test SCSIID,0x80 jnz p_mesgin1_b
and NEEDSDTR_A,A
jmp p_mesgin1_save
p_mesgin1_b:
and NEEDSDTR_B,A
p_mesgin1_save:
and A,0x80,SINDIR # get the WIDEXFER flag
or RETURN_1,A # Set WIDEXFER if necessary
mov DINDIR,RETURN_1 # save returned value
# Even though the SCSI-2 specification says that a device responding
# to our SDTR message should honor our parameters for transmitting
@ -587,7 +640,7 @@ p_mesgin5:
#
test MSG_FLAGS,0x80 jnz p_mesgin_done
xor SCBARRAY+0,0x4 # clear disconnect bit in SCB
and SCBARRAY+0,0xfb # clear disconnect bit in SCB
mvi RESELECT,0xc0 # make note of IDENTIFY
call sg_scb2ram # implied restore pointers
@ -606,14 +659,28 @@ p_mesgin6:
and FUNCTION1,0x70,SCSIID # outstanding SDTR message?
mov A,FUNCTION1
test NEEDSDTR,A jz p_mesgin_done # no - ignore rejection
test SBLKCTL,0x08 jnz p_mesgin6_b
test SCSIID,0x80 jnz p_mesgin6_b
test NEEDSDTR_A,A jz p_mesgin_done # no - ignore rejection
call ndx_sdtr # note use of asynch xfer
mov DINDEX,SINDEX
clr DINDIR
not A # turn off "active sdtr" flag
and NEEDSDTR,A
not A
and NEEDSDTR_A,A
jmp p_mesgin6_done
p_mesgin6_b:
test NEEDSDTR_B,A jz p_mesgin_done # no - ignore rejection
call ndx_sdtr # note use of asynch xfer
mov DINDEX,SINDEX
clr DINDIR
not A
and NEEDSDTR_B,A
p_mesgin6_done:
clr SCSIRATE # select asynch xfer
jmp p_mesgin_done
@ -772,7 +839,7 @@ dma2:
dma3:
test SINDEX,0x4 jnz dma5 # DIRECTION
dma4:
test DFSTATUS,0x1 jz dma4 # FIFOFLUSHACK
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
@ -795,9 +862,20 @@ dma6:
# contents are stomped on return.
#
initialize:
clr SBLKCTL # channel A, !wide
and SCSIID,0xf0,SINDEX # target ID
and A,0x7,SCSICONF # SCSI_ID_A[210]
test SBLKCTL,0x08 jnz initialize_b
mvi SINDEX,SCSICONF_A
test FLAGS,WIDE_BUS jnz initialize_wide
and A,0x7,SCSICONF_A # SCSI_ID_A[210]
jmp initialize_2
initialize_b:
and A,0x7,SCSICONF_B # SCSI_ID_B[210]
mvi SCSICONF_B jmp initialize_2
initialize_wide:
and A, 0xf,SCSICONF_B
initialize_2:
or SCSIID,A
# Esundry initialization.
@ -821,8 +899,8 @@ initialize:
#
# STPWEN is 7870-specific, enabling an external termination power source.
#
and A,0x38,SCSICONF # PARITY_ENB_A|SEL_TIM_A[10]
or SXFRCTL1,0x5,A # ENSTIMER|STPWEN
and A,0x38,SINDIR # PARITY_ENB|SEL_TIM[10]
or SXFRCTL1,0x7,A # ENSTIMER|ACTNEGEN|STPWEN
mvi SIMODE1,0x84 # ENSELTIMO|ENSCSIPERR
# Initialize scatter-gather pointers by setting up the working copy
@ -849,19 +927,25 @@ assert1:
ret
# Find out if disconnection is ok from the information the BIOS has left
# us. The target ID should be in the upper four bits of SINDEX; A will
# us. The tcl from SCBARRAY+1 should be in SINDEX; A will
# contain either 0x40 (disconnection ok) or 0x00 (disconnection not ok)
# on exit.
#
# This is the only place the target ID is limited to three bits, so we
# can use the FUNCTION1 register.
# 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 DISC_DSB_A,A jz disconnect1 # bit nonzero if DISabled
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
@ -874,9 +958,10 @@ disconnect1:
#
findSCB:
and A,0x7,SINDEX # lun in lower three bits
or DINDEX,A,SELID # can I do this?
and DINDEX,0xf7 # only channel A implemented
or DINDEX,A,SELID
and DINDEX,0xf7
and A,0x08,SBLKCTL # B Channel??
or DINDEX,A
clr SINDEX
findSCB1:
@ -884,7 +969,6 @@ findSCB1:
mov SCBPTR,SINDEX # switch to new SCB
cmp SCBARRAY+1,A jne findSCB2 # target ID/channel/lun match?
test SCBARRAY+0,0x4 jz findSCB2 # should be disconnected
ret
findSCB2:
@ -1029,7 +1113,9 @@ sg_advance2:
#
ndx_sdtr:
shr A,SCSIID,4
and A,0x7
test SBLKCTL,0x08 jz ndx_sdtr_2
or A,0x08 # Channel B entries add 8
ndx_sdtr_2:
add SINDEX,SYNCNEG,A
and FUNCTION1,0x70,SCSIID # 3-bit target address decode
@ -1042,7 +1128,11 @@ mk_sdtr:
mov DINDEX,SINDEX # save SINDEX
call ndx_sdtr
test NEEDSDTR,A jnz mk_sdtr1 # do we need negotiation?
test SCBARRAY+1,0x88 jz mk_sdtr1_a
test NEEDSDTR_B,A jnz mk_sdtr1 # do we need negotiation?
ret
mk_sdtr1_a:
test NEEDSDTR_A,A jnz mk_sdtr1 # do we need negotiation?
ret
mk_sdtr1: