patch-2.0.13 linux/drivers/scsi/aic7xxx.seq
Next file: linux/drivers/scsi/aic7xxx_proc.c
Previous file: linux/drivers/scsi/aic7xxx.h
Back to the patch index
Back to the overall index
- Lines: 487
- Date:
Sat Aug 10 10:44:18 1996
- Orig file:
v2.0.12/linux/drivers/scsi/aic7xxx.seq
- Orig date:
Sat Apr 20 20:59:10 1996
diff -u --recursive --new-file v2.0.12/linux/drivers/scsi/aic7xxx.seq linux/drivers/scsi/aic7xxx.seq
@@ -23,15 +23,22 @@
*
* FreeBSD, Twin, Wide, 2 command per target support, tagged queuing and other
* optimizations provided by Justin T. Gibbs (gibbs@FreeBSD.org)
+ *
+ * This version corresponds to version 1.42 of FreeBSDs aic7xxx.seq.
+ *
*-M*************************************************************************/
-VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 3.0 1996/04/16 08:52:23 deang Exp $"
+VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 3.1 1996/07/23 03:37:26 deang Exp $"
#ifdef linux
#include "aic7xxx_reg.h"
#else
+#if defined(__NetBSD__)
+#include "../../../../dev/ic/aic7xxxreg.h"
+#elif defined(__FreeBSD__)
#include "../../dev/aic7xxx/aic7xxx_reg.h"
#endif
+#endif
/*
* We can't just use ACCUM in the sequencer code because it
@@ -67,7 +74,13 @@
* We jump to start after every bus free.
*/
start:
+ and FLAGS,0x0f /* clear target specific flags */
mvi SCSISEQ,ENRSELI /* Always allow reselection */
+ clr SCSIRATE /*
+ * We don't know the target we will
+ * connect to, so default to narrow
+ * transfers to avoid parity problems.
+ */
poll_for_work:
/*
* Are we a twin channel device?
@@ -140,7 +153,7 @@
or ACTIVE_A,A
start_scb:
- mov SCB_NEXT_WAITING,WAITING_SCBH
+ mov SCB_NEXT,WAITING_SCBH
mov WAITING_SCBH, SCBPTR
start_scb2:
and SINDEX,0xf7,SBLKCTL /* Clear the channel select bit */
@@ -178,25 +191,24 @@
jmp wait_for_selection
mk_identify:
- and A,DISCENB,SCB_CONTROL /* mask off disconnect privilege */
+ and A,DISCENB,SCB_CONTROL /* mask off disconnect privledge */
and MSG0,0x7,SCB_TCL /* lun */
- or MSG0,A /* or in disconnect privilege */
+ or MSG0,A /* or in disconnect privledge */
or MSG0,MSG_IDENTIFY
mvi MSG_LEN, 1
test SCB_CONTROL,0xb0 jz !message /* WDTR, SDTR or TAG?? */
/*
- * Tag Message if Tag enabled in SCB control block. Use SCBPTR as the tag
- * value
+ * Send a tag message if TAG_ENB is set in the SCB control block.
+ * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
*/
mk_tag:
mvi DINDEX, MSG1
test SCB_CONTROL,TAG_ENB jz mk_tag_done
- and A,0x23,SCB_CONTROL
- mov DINDIR,A
- mov DINDIR,SCBPTR
+ and DINDIR,0x23,SCB_CONTROL
+ mov DINDIR,SCB_TAG
add MSG_LEN,COMP_MSG0,DINDEX /* update message length */
@@ -218,7 +230,6 @@
reselect:
clr MSG_LEN /* Don't have anything in the mesg buffer */
mov SELID call initialize_scsiid
- and FLAGS,0x03 /* clear target specific flags */
or FLAGS,RESELECTED
jmp select2
@@ -229,8 +240,8 @@
* SCB is used, so don't bother with it now.
*/
select:
- and FLAGS,0x03 /* Clear target flags */
- mov WAITING_SCBH,SCB_NEXT_WAITING
+ mov WAITING_SCBH,SCB_NEXT
+ or FLAGS,SELECTED
select2:
/*
* Set CLRCHN here before the target has entered a data transfer mode -
@@ -244,13 +255,29 @@
call ndx_dtr
mov SCSIRATE,SINDIR
+/*
+ * Initialize Ultra mode setting.
+ */
+ mov FUNCTION1,SCSIID
+ mov A,FUNCTION1
+ and SINDEX,0xdf,SXFRCTL0 /* default to Ultra disabled */
+ test SCSIID, 0x80 jnz ultra_b /* Target ID > 7 */
+ test SBLKCTL, SELBUSB jnz ultra_b /* Second channel device */
+ test ULTRA_ENB,A jz set_sxfrctl0
+ or SINDEX, ULTRAEN jmp set_sxfrctl0
+ultra_b:
+ test ULTRA_ENB_B,A jz set_sxfrctl0
+ or SINDEX, ULTRAEN
+
+set_sxfrctl0:
+ mov SXFRCTL0,SINDEX
+
mvi SCSISEQ,ENAUTOATNP /*
* ATN on parity errors
* for "in" phases
*/
mvi CLRSINT1,CLRBUSFREE
mvi CLRSINT0,0x60 /* CLRSELDI|CLRSELDO */
-
/*
* Main loop for information transfer phases. If BSY is false, then
* we have a bus free condition, expected or not. Otherwise, wait
@@ -274,6 +301,7 @@
cmp A,P_MESGIN je p_mesgin
mvi INTSTAT,BAD_PHASE /* unknown phase - signal driver */
+ jmp ITloop /* Try reading the bus again. */
p_dataout:
mvi DMAPARAMS,0x7d /*
@@ -305,12 +333,29 @@
or FLAGS, DPHASE /* We have seen a data phase */
data_phase_loop:
+/* Guard against overruns */
+ test SG_COUNT, 0xff jnz data_phase_inbounds
+/*
+ * Turn on 'Bit Bucket' mode, set the transfer count to
+ * 16meg and let the target run until it changes phase.
+ * When the transfer completes, notify the host that we
+ * had an overrun.
+ */
+ or SXFRCTL1,BITBUCKET
+ mvi STCNT0,0xff
+ mvi STCNT1,0xff
+ mvi STCNT2,0xff
+
+data_phase_inbounds:
/* If we are the last SG block, don't set wideodd. */
cmp SG_COUNT,0x01 jne data_phase_wideodd
and DMAPARAMS, 0xbf /* Turn off WIDEODD */
data_phase_wideodd:
mov DMAPARAMS call dma
+/* Go tell the host about any overruns */
+ test SXFRCTL1,BITBUCKET jnz data_phase_overrun
+
/* Exit if we had an underrun */
test SSTAT0,SDONE jz data_phase_finish /* underrun STCNT != 0 */
@@ -412,16 +457,22 @@
mov SCB_RESID_SGCNT, SG_COUNT
jmp ITloop
+data_phase_overrun:
+/*
+ * Turn off BITBUCKET mode and notify the host
+ */
+ and SXFRCTL1,0x7f /* ~BITBUCKET */
+ mvi INTSTAT,DATA_OVERRUN
+ jmp ITloop
+
/*
- * Command phase. Set up the DMA registers and let 'er rip - the
- * two bytes after the SCB SCSI_cmd_length are zeroed by the driver,
- * so we can copy those three bytes directly into HCNT.
+ * Command phase. Set up the DMA registers and let 'er rip.
*/
p_command:
call assert
/*
- * Load HADDR and HCNT. We can do this in one bcopy since they are neighbors
+ * Load HADDR and HCNT.
*/
mov HADDR0, SCB_CMDPTR0
mov HADDR1, SCB_CMDPTR1
@@ -448,7 +499,7 @@
jmp mesgin_done
/*
- * Message out phase. If there is no active message, but the target
+ * Message out phase. If there is not an active message, but the target
* took us into this phase anyway, build a no-op message and send it.
*/
p_mesgout:
@@ -473,6 +524,7 @@
p_mesgout_loop:
test SSTAT1,PHASEMIS jnz p_mesgout_phasemis
test SSTAT0,SPIORDY jz p_mesgout_loop
+ test SSTAT1,PHASEMIS jnz p_mesgout_phasemis
cmp DINDEX,1 jne p_mesgout_outb /* last byte? */
mvi CLRSINT1,CLRATNO /* drop ATN */
p_mesgout_outb:
@@ -498,7 +550,7 @@
jmp ITloop
p_mesgout_phasemis:
- mvi CLRSINT1,CLRATNO /* Be sure turn ATNO off */
+ mvi CLRSINT1,CLRATNO /* Be sure to turn ATNO off */
p_mesgout_done:
clr MSG_LEN /* no active msg */
jmp ITloop
@@ -539,20 +591,20 @@
mesgin_complete:
/*
- * We got a "command complete" message, so put the SCB pointer
- * into QUEUEOUT, and trigger a completion interrupt.
- * Check status for non zero return and interrupt driver if needed
- * 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, modify the "waiting for selection" SCB list and set
- * RETURN_1 to 0x80. If RETURN_1 is set to 0x80 the sequencer immediately
- * jumps to main loop where it will run down the waiting SCB list.
- * If the kernel driver does not wish to request sense, it need
- * only clear RETURN_1, 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.
+ * We got a "command complete" message, so put the SCB_TAG into QUEUEOUT,
+ * and trigger a completion interrupt. Check status for non zero return
+ * and interrupt driver if needed. 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, modify the "waiting for selection" SCB list
+ * and set RETURN_1 to SEND_SENSE. If RETURN_1 is set to SEND_SENSE the
+ * sequencer imediately jumps to main loop where it will run down the waiting
+ * SCB list and process the sense request. If the kernel driver does not
+ * wish to request sense, it need only clear RETURN_1, 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.
*
* First check for residuals
*/
@@ -600,7 +652,7 @@
mvi INTSTAT,IMMEDDONE
jmp start
complete:
- mov QOUTFIFO,SCBPTR
+ mov QOUTFIFO,SCB_TAG
mvi INTSTAT,CMDCMPLT
jmp mesgin_done
@@ -614,10 +666,10 @@
*/
mesgin_extended:
mvi ARG_1 call inb_next /* extended message length */
- mvi A call inb_next /* extended message code */
+ mvi REJBYTE_EXT call inb_next /* extended message code */
- cmp A,MSG_SDTR je p_mesginSDTR
- cmp A,MSG_WDTR je p_mesginWDTR
+ cmp REJBYTE_EXT,MSG_SDTR je p_mesginSDTR
+ cmp REJBYTE_EXT,MSG_WDTR je p_mesginWDTR
jmp rej_mesgin
p_mesginWDTR:
@@ -648,6 +700,7 @@
* Requested SDTR too small
* Reject it.
*/
+ clr ARG_1 /* Use the scratch ram rate */
mvi DINDEX, MSG0
mvi MSG0 call mk_sdtr
or SCSISIGO,ATNO /* turn on ATNO */
@@ -659,6 +712,22 @@
*/
mesgin_disconnect:
or SCB_CONTROL,DISCONNECTED
+ test FLAGS, PAGESCBS jz mesgin_done
+/*
+ * Link this SCB into the DISCONNECTED list. This list holds the
+ * candidates for paging out an SCB if one is needed for a new command.
+ * Modifying the disconnected list is a critical(pause dissabled) section.
+ */
+ mvi SCB_PREV, SCB_LIST_NULL
+ mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */
+ mov SCB_NEXT, DISCONNECTED_SCBH
+ mov DISCONNECTED_SCBH, SCBPTR
+ cmp SCB_NEXT,SCB_LIST_NULL je linkdone
+ mov SCBPTR,SCB_NEXT
+ mov SCB_PREV,DISCONNECTED_SCBH
+ mov SCBPTR,DISCONNECTED_SCBH
+linkdone:
+ mvi SEQCTL,0x10 /* !PAUSEDIS|FASTMODE */
jmp mesgin_done
/*
@@ -676,7 +745,7 @@
* code do the rest.
*/
mesgin_rdptrs:
- and FLAGS,0xfb /*
+ and FLAGS,0xef /*
* !DPHASE we'll reload them
* the next time through
*/
@@ -699,21 +768,19 @@
/*
* Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
- * If we get one, we use the tag returned to switch to the proper
- * SCB. Otherwise, we just use the findSCB method.
+ * If we get one, we use the tag returned to switch to find the proper
+ * SCB. With SCB paging, this requires using findSCB for both tagged
+ * and non-tagged transactions since the SCB may exist in any slot.
+ * If we're not using SCB paging, we can use the tag as the direct
+ * index to the SCB.
*/
+ mvi ARG_1,SCB_LIST_NULL /* Default to no-tag */
snoop_tag_loop:
test SSTAT1,BUSFREE jnz use_findSCB
test SSTAT1,REQINIT jz snoop_tag_loop
test SSTAT1,PHASEMIS jnz use_findSCB
mvi A call inb_first
- cmp A,MSG_SIMPLE_TAG je get_tag
-use_findSCB:
- mov ALLZEROS call findSCB /* Have to search */
-setup_SCB:
- and SCB_CONTROL,0xfb /* clear disconnect bit in SCB */
- or FLAGS,IDENTIFY_SEEN /* make note of IDENTIFY */
- jmp ITloop
+ cmp A,MSG_SIMPLE_TAG jne use_findSCB
get_tag:
mvi ARG_1 call inb_next /* tag value */
/*
@@ -729,16 +796,26 @@
* Ensure that the SCB the tag points to is for a SCB transaction
* to the reconnecting target.
*/
+ test FLAGS, PAGESCBS jz index_by_tag
+ call inb_last /* Ack Tag */
+use_findSCB:
+ mov ALLZEROS call findSCB /* Have to search */
+setup_SCB:
+ and SCB_CONTROL,0xfb /* clear disconnect bit in SCB */
+ or FLAGS,IDENTIFY_SEEN /* make note of IDENTIFY */
+ jmp ITloop
+index_by_tag:
mov SCBPTR,ARG_1
mov A,SAVED_TCL
cmp SCB_TCL,A jne abort_tag
test SCB_CONTROL,TAG_ENB jz abort_tag
call inb_last /* Ack Successful tag */
jmp setup_SCB
+
abort_tag:
or SCSISIGO,ATNO /* turn on ATNO */
mvi INTSTAT,ABORT_TAG /* let driver know */
- mvi 0xd call mk_mesg /* ABORT TAG message */
+ mvi MSG_ABORT_TAG call mk_mesg /* ABORT TAG message */
jmp mesgin_done
/*
@@ -778,7 +855,7 @@
mk_mesg:
mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */
test MSG_LEN,0xff jz mk_mesg1 /* Should always succeed */
-
+
/*
* Hmmm. For some reason the mesg buffer is in use.
* Tell the driver. It should look at SINDEX to find
@@ -817,6 +894,7 @@
test SSTAT0,SPIORDY jz inb_next_wait /* wait for next byte */
inb_first:
mov DINDEX,SINDEX
+ test SSTAT1,PHASEMIS jnz mesgin_phasemis
mov DINDIR,SCSIBUSL ret /*read byte directly from bus*/
inb_last:
mov NONE,SCSIDATL ret /*dummy read from latch to ACK*/
@@ -887,27 +965,59 @@
mvi INTSTAT,NO_IDENT ret /* no - cause a kernel panic */
/*
- * 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
+ * Locate the SCB matching the target ID/channel/lun in SAVED_TCL, and the tag
+ * value in ARG_1. If ARG_1 == SCB_LIST_NULL, we're looking for a non-tagged
+ * SCB. Have the kernel print a warning message if it can't be found, and
+ * generate an ABORT/ABORT_TAG message to the target. SINDEX should be
* cleared on call.
*/
findSCB:
mov A,SAVED_TCL
- mov SCBPTR,SINDEX /* switch to new SCB */
+ mov SCBPTR,SINDEX /* switch to next SCB */
+ mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */
cmp SCB_TCL,A jne findSCB1 /* target ID/channel/lun match? */
test SCB_CONTROL,DISCONNECTED jz findSCB1 /*should be disconnected*/
- ret
+ test SCB_CONTROL,TAG_ENB jnz findTaggedSCB
+ cmp ARG_1,SCB_LIST_NULL je foundSCB
+ jmp findSCB1
+findTaggedSCB:
+ mov A, ARG_1 /* Tag passed in ARG_1 */
+ cmp SCB_TAG,A jne findSCB1 /* Found it? */
+foundSCB:
+ test FLAGS,PAGESCBS jz foundSCB_ret
+/* Remove this SCB from the disconnection list */
+ cmp SCB_NEXT,SCB_LIST_NULL je unlink_prev
+ mov SAVED_LINKPTR, SCB_PREV
+ mov SCBPTR, SCB_NEXT
+ mov SCB_PREV, SAVED_LINKPTR
+ mov SCBPTR, SINDEX
+unlink_prev:
+ cmp SCB_PREV,SCB_LIST_NULL je rHead/* At the head of the list */
+ mov SAVED_LINKPTR, SCB_NEXT
+ mov SCBPTR, SCB_PREV
+ mov SCB_NEXT, SAVED_LINKPTR
+ mov SCBPTR, SINDEX
+ mvi SEQCTL,0x10 ret /* !PAUSEDIS|FASTMODE */
+rHead:
+ mov DISCONNECTED_SCBH,SCB_NEXT
+foundSCB_ret:
+ mvi SEQCTL,0x10 ret /* !PAUSEDIS|FASTMODE */
findSCB1:
+ mvi SEQCTL,0x10 /* !PAUSEDIS|FASTMODE */
inc SINDEX
mov A,SCBCOUNT
cmp SINDEX,A jne findSCB
mvi INTSTAT,NO_MATCH /* not found - signal kernel */
- mvi MSG_ABORT call mk_mesg /* ABORT message */
-
- or SCSISIGO,ATNO ret /* assert ATNO */
+ cmp RETURN_1,SCB_PAGEDIN je return
+ or SCSISIGO,ATNO /* assert ATNO */
+ cmp ARG_1,SCB_LIST_NULL jne find_abort_tag
+ mvi MSG_ABORT call mk_mesg
+ jmp ITloop
+find_abort_tag:
+ mvi MSG_ABORT_TAG call mk_mesg
+ jmp ITloop
/*
* Make a working copy of the scatter-gather parameters from the SCB.
@@ -980,7 +1090,7 @@
*/
mk_dtr:
test SCB_CONTROL,NEEDWDTR jnz mk_wdtr_16bit
- or FLAGS, MAXOFFSET /* Force an offset of 15 or 8 if WIDE */
+ mvi ARG_1, MAXOFFSET /* Force an offset of 15 or 8 if WIDE */
mk_sdtr:
mvi DINDIR,1 /* extended message */
@@ -988,7 +1098,7 @@
mvi DINDIR,1 /* SDTR code */
call sdtr_to_rate
mov DINDIR,RETURN_1 /* REQ/ACK transfer period */
- test FLAGS, MAXOFFSET jnz mk_sdtr_max_offset
+ cmp ARG_1, MAXOFFSET je mk_sdtr_max_offset
and DINDIR,0x0f,SINDIR /* Sync Offset */
mk_sdtr_done:
@@ -998,8 +1108,6 @@
/*
* We're initiating sync negotiation, so request the max offset we can (15 or 8)
*/
- xor FLAGS, MAXOFFSET
-
/* Talking to a WIDE device? */
test SCSIRATE, WIDEXFER jnz wmax_offset
mvi DINDIR, MAX_OFFSET_8BIT
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov