summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authordg <dg@FreeBSD.org>1995-05-17 07:06:02 +0000
committerdg <dg@FreeBSD.org>1995-05-17 07:06:02 +0000
commitf879f636052f7f05419f0b359ca1e1d203d7962d (patch)
tree15d8079ad0390253228b99c72a1d1b94b3716938 /sys/dev
parent037b95c21c474703d3d472125943753d6700da3c (diff)
downloadFreeBSD-src-f879f636052f7f05419f0b359ca1e1d203d7962d.zip
FreeBSD-src-f879f636052f7f05419f0b359ca1e1d203d7962d.tar.gz
Fixes to the aic7xxx sequencer code and device driver from Justin Gibbs:
1) If a target initiated a sync negotiation with us and happened to chose a value above 15, the old code inadvertantly truncated it with an "& 0x0f". If the periferal picked something really bad like 0x32, you'd end up with an offset of 2 which would hang the drive since it didn't expect to ever get something so low. We now do a MIN(maxoffset, given_offset). 2) In the case of Wide cards, we were turning on sync transfers after a sucessfull wide negotiation. Now we leave the offset alone in the per target scratch space (which implies asyncronous transfers since we initialize it that way) until a syncronous negotation occurs. 3) We were advertizing a max offset of 15 instead of 8 for wide devices. 4) If the upper level SCSI code sent down a "SCSI_RESET", it would hang the system because we would end up sending a null command to the sequencer. Now we handle SCSI_RESET correctly by having the sequencer interrupt us when it is about to fill the message buffer so that we can fill it in ourselves. The sequencer will also "simulate" a command complete for these "message only" SCBs so that the kernel driver can finish up properly. The cdplay utility will send a "SCSI_REST" to the cdplayer if you use the reset command. 5) The code that handles SCSIINTs was broken in that if more than one type of error was true at once, we'd do outbs without the card being paused. The else clause after the busfree case was also an accident waiting to happen. I've now turned this into an if, else if, else type of thing, since in most cases when we handle one type of error, it should be okay to ignore the rest (ie if we have a SELTO, who cares if there was a parity error on the transaction?), but the section should really be rewritten after 2.0.5. This fix was the least obtrusive way to patch the problem. 6) Only tag either SDTR or WDTR negotiation on an SCB. The real problem is that I don't account for the case when an SCB that is tagged to do a particular type of negotiation completes or SELTOs (selection timeout) without the negotiation taking place, so the accounting of sdtrpending and wdtrpending gets screwed up. In the wide case, if we tag it to do both wdtr and sdtr, it only performs wdtr (since wdtr must occur first and we spread out the negotiation over two commands) so we always have sdtrpending set for that target and we never do a real SDTR. I fill properly fix the accounting after 2.0.5 goes out the door, but this works (as confirmed by Dan) on wide targets. Other stuff that is also included: 1) Don't do a bzero when recycling SCBs. The only thing that must explicitly be set to zero is the scb control byte which is done in ahc_get_scb. We also need to set the SG_list_pointer and SG_list_count to 0 for commands that do not transfer data. 2) Mask the interrupt type printout for the aic7870 case. The bit we were using to determine interrupt type is only valid for the aic7770. Submitted by: Justin Gibbs
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq52
1 files changed, 41 insertions, 11 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index c5a1e9b..e8cc5bb 100644
--- a/sys/dev/aic7xxx/aic7xxx.seq
+++ b/sys/dev/aic7xxx/aic7xxx.seq
@@ -41,7 +41,7 @@
#
##-M#########################################################################
-VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.14 1995/04/15 21:45:56 gibbs Exp $"
+VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.15 1995/04/27 17:44:27 gibbs Exp $"
SCBMASK = 0x1f
@@ -155,6 +155,12 @@ MSG_REJECT = 0x61 # Reject message recieved
BAD_STATUS = 0x71 # Bad status from target
RESIDUAL = 0x81 # Residual byte count != 0
ABORT_TAG = 0x91 # Sent an ABORT_TAG message
+AWAITING_MSG = 0xa1 # Kernel requested to specify
+ # a message to this target
+ # (command was null), so tell
+ # it that it can fill the
+ # message buffer.
+
# 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
@@ -179,8 +185,8 @@ ABORT_TAG = 0x91 # Sent an ABORT_TAG message
# 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_SYNC bit which we set when we want to negotiate for
-# 10MHz irregardless of what the per target scratch space says.
+# 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.
#
# Note that SG_NEXT occupies four bytes.
#
@@ -222,11 +228,14 @@ SCBCOUNT = 0x52 # the actual number of SCBs
FLAGS = 0x53 # Device configuration flags
TWIN_BUS = 0x01
WIDE_BUS = 0x02
-MAX_SYNC = 0x08
+MAX_OFFSET = 0x08
ACTIVE_MSG = 0x20
IDENTIFY_SEEN = 0x40
RESELECTED = 0x80
+MAX_OFFSET_8BIT = 0x0f
+MAX_OFFSET_WIDE = 0x08
+
ACTIVE_A = 0x54
ACTIVE_B = 0x55
SAVED_TCL = 0x56 # Temporary storage for the
@@ -369,6 +378,17 @@ start_selection:
# Messages are stored in scratch RAM starting with a flag byte (high bit
# set means active message), one length byte, and then the message itself.
#
+
+ test SCBARRAY+11,0xff jnz identify # 0 Length Command?
+
+# The kernel has sent us an SCB with no command attached. This implies
+# that the kernel wants to send a message of some sort to this target,
+# so we interrupt the driver, allow it to fill the message buffer, and
+# then go back into the arbitration loop
+ mvi INTSTAT,AWAITING_MSG
+ jmp poll_for_work
+
+identify:
mov SCBARRAY+1 call disconnect # disconnect ok?
and SINDEX,0x7,SCBARRAY+1 # lun
@@ -682,6 +702,7 @@ clear_a:
complete:
mov QOUTFIFO,SCBPTR
mvi INTSTAT,CMDCMPLT
+ test SCBARRAY+11,0xff jz start # Immediate message complete
jmp p_mesgin_done
# If we have a residual count, interrupt and tell the host. Other
@@ -851,6 +872,10 @@ p_mesgin_done:
p_busfree:
mvi CLRSINT1,0x40 # CLRATNO
clr SIGSTATE
+
+# if this is an immediate command, perform a psuedo command complete to
+# notify the driver.
+ test SCBARRAY+11,0xff jz status_ok
jmp start
# Instead of a generic bcopy routine that requires an argument, we unroll
@@ -1202,7 +1227,7 @@ ndx_dtr_2:
mk_dtr:
test SCBARRAY+0,0xc0 jz return # NEEDWDTR|NEEDSDTR
test SCBARRAY+0,NEEDWDTR jnz mk_wdtr_16bit
- or FLAGS, MAX_SYNC # Force an offset of 15
+ or FLAGS, MAX_OFFSET # Force an offset of 15 or 8 if WIDE
mk_sdtr:
mvi DINDIR,1 # extended message
@@ -1210,16 +1235,21 @@ mk_sdtr:
mvi DINDIR,1 # SDTR code
call sdtr_to_rate
mov DINDIR,RETURN_1 # REQ/ACK transfer period
- test FLAGS, MAX_SYNC jnz mk_sdtr_max_sync
- and DINDIR,0xf,SINDIR # Sync Offset
+ test FLAGS, MAX_OFFSET jnz mk_sdtr_max_offset
+ and DINDIR,0x0f,SINDIR # Sync Offset
mk_sdtr_done:
add MSG_LEN,-MSG_START+0,DINDEX ret # update message length
-mk_sdtr_max_sync:
-# We're initiating sync negotiation, so request the max offset we can (15)
- mvi DINDIR, 0x0f
- xor FLAGS, MAX_SYNC
+mk_sdtr_max_offset:
+# We're initiating sync negotiation, so request the max offset we can (15 or 8)
+ xor FLAGS, MAX_OFFSET
+ test SCSIRATE, 0x80 jnz wmax_offset # Talking to a WIDE device?
+ mvi DINDIR, MAX_OFFSET_8BIT
+ jmp mk_sdtr_done
+
+wmax_offset:
+ mvi DINDIR, MAX_OFFSET_WIDE
jmp mk_sdtr_done
mk_wdtr_16bit:
OpenPOWER on IntegriCloud