diff options
author | gibbs <gibbs@FreeBSD.org> | 1996-04-20 21:20:31 +0000 |
---|---|---|
committer | gibbs <gibbs@FreeBSD.org> | 1996-04-20 21:20:31 +0000 |
commit | cafb54d853000338e3d0590d348b8d668e1c0259 (patch) | |
tree | c825509647c8d7ed608323c310baab7f89d3981f /sys | |
parent | e6bdc02ac0ba01a8cb4503d73a5f42f3954d46c8 (diff) | |
download | FreeBSD-src-cafb54d853000338e3d0590d348b8d668e1c0259.zip FreeBSD-src-cafb54d853000338e3d0590d348b8d668e1c0259.tar.gz |
Implement SCB paging. This allows up to 255 active commands on
aic7770 >= Rev E, aic7850, aic7860, aic7870, and ai7880 based controllers.
Make findSCB safer for non-tagged commands when tagged commands are
active on the controller. The symptoms of this problem were
"Overlapped commands attempted" messages during error recovery
attempts.
Compact scratch ram usage. This leaves 8 bytes free for future use.
Clean up some comments.
aic7xxx_reg.h:
Update my copyright.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.seq | 178 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_reg.h | 103 |
2 files changed, 181 insertions, 100 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq index 7f5d8b4..10e97af 100644 --- a/sys/dev/aic7xxx/aic7xxx.seq +++ b/sys/dev/aic7xxx/aic7xxx.seq @@ -5,8 +5,9 @@ * The University of Calgary Department of Computer Science. * All rights reserved. * - *Modifications/enhancements: - * Copyright (c) 1994, 1995, 1996 Justin Gibbs. All rights reserved. + *FreeBSD, Twin, Wide, 2 command per target support, tagged queuing, + *SCB paging and other optimizations: + *Copyright (c) 1994, 1995, 1996 Justin Gibbs. All rights reserved. * *Redistribution and use in source and binary forms, with or without *modification, are permitted provided that the following conditions @@ -36,12 +37,9 @@ *OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *SUCH DAMAGE. * - *FreeBSD, Twin, Wide, 2 command per target support, tagged queuing and other - *optimizations provided by Justin T. Gibbs (gibbs@FreeBSD.org) - * *-M************************************************************************/ -VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.31 1996/03/10 07:02:31 gibbs Exp $" +VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.32 1996/03/31 03:02:33 gibbs Exp $" #include "../../dev/aic7xxx/aic7xxx_reg.h" @@ -79,6 +77,7 @@ reset: * We jump to start after every bus free. */ start: + and FLAGS,0x0f /* clear target specific flags */ mvi SCSISEQ,ENRSELI /* Always allow reselection */ poll_for_work: /* @@ -152,7 +151,7 @@ test_a: 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 */ @@ -199,16 +198,15 @@ mk_identify: 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 */ @@ -230,7 +228,6 @@ wait_for_selection: 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 @@ -241,8 +238,8 @@ reselect: * 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 - @@ -343,7 +340,7 @@ sg_advance: * 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. + * This, like all DMA's, assumes little-endian host data storage. */ sg_load: clr HCNT2 @@ -425,15 +422,13 @@ data_phase_finish: 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 @@ -460,7 +455,7 @@ p_status: 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: @@ -510,7 +505,7 @@ p_mesgout_snoop: 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 @@ -551,20 +546,20 @@ mesgin_done: 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 imediately - * 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 */ @@ -612,7 +607,7 @@ test_immediate: mvi INTSTAT,IMMEDDONE jmp start complete: - mov QOUTFIFO,SCBPTR + mov QOUTFIFO,SCB_TAG mvi INTSTAT,CMDCMPLT jmp mesgin_done @@ -626,10 +621,10 @@ complete: */ 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: @@ -660,6 +655,7 @@ p_mesginSDTR: * 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 */ @@ -671,6 +667,22 @@ p_mesginSDTR: */ 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 /* @@ -688,7 +700,7 @@ mesgin_sdptrs: * code do the rest. */ mesgin_rdptrs: - and FLAGS,0xfb /* + and FLAGS,0xef /* * !DPHASE we'll reload them * the next time through */ @@ -711,21 +723,19 @@ mesgin_identify: /* * 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 */ /* @@ -738,19 +748,29 @@ get_tag: jc abort_tag /* - * Ensure that the SCB the tag points to is for a SCB transaction + * Ensure that the SCB the tag points to is for an 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 /* @@ -899,27 +919,59 @@ assert: 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. @@ -992,7 +1044,7 @@ ndx_dtr_2: */ 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 */ @@ -1000,7 +1052,7 @@ mk_sdtr: 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: @@ -1010,8 +1062,6 @@ mk_sdtr_max_offset: /* * 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 diff --git a/sys/dev/aic7xxx/aic7xxx_reg.h b/sys/dev/aic7xxx/aic7xxx_reg.h index f45e409..a0155da 100644 --- a/sys/dev/aic7xxx/aic7xxx_reg.h +++ b/sys/dev/aic7xxx/aic7xxx_reg.h @@ -13,12 +13,22 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Absolutely no warranty of function or purpose is made by the author - * Justin T. Gibbs. - * 4. Modifications may be freely made to this file if the above conditions - * are met. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * $Id: aic7xxx_reg.h,v 1.6 1996/03/10 07:02:32 gibbs Exp $ + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: aic7xxx_reg.h,v 1.7 1996/03/31 03:02:37 gibbs Exp $ */ /* @@ -547,7 +557,9 @@ #define SCB_CMDPTR2 0x0b6 #define SCB_CMDPTR3 0x0b7 #define SCB_CMDLEN 0x0b8 -#define SCB_NEXT_WAITING 0x0b9 +#define SCB_TAG 0x0b9 +#define SCB_NEXT 0x0ba +#define SCB_PREV 0x0bb #ifdef linux #define SG_SIZEOF 0x0c /* sizeof(struct scatterlist) */ @@ -629,9 +641,11 @@ /* * The sequencer will stick the frist byte of any rejected message here so - * we can see what is getting thrown away. + * we can see what is getting thrown away. Extended messages put the + * extended message type in REJBYTE_EXT. */ -#define REJBYTE 0x031 +#define REJBYTE 0x030 +#define REJBYTE_EXT 0x031 /* * Bit vector of targets that have disconnection disabled. @@ -645,6 +659,7 @@ */ #define MSG_LEN 0x034 +/* We reserve 8bytes to store outgoing messages */ #define MSG0 0x035 #define COMP_MSG0 0xcb /* 2's complement of MSG0 */ #define MSG1 0x036 @@ -652,64 +667,79 @@ #define MSG3 0x038 #define MSG4 0x039 #define MSG5 0x03a +#define MSG6 0x03b +#define MSG7 0x03c /* * These are offsets into the card's scratch ram. Some of the values are * specified in the AHA2742 technical reference manual and are initialized * by the BIOS at boot time. */ -#define LASTPHASE 0x049 -#define ARG_1 0x04a -#define RETURN_1 0x04a -#define SEND_SENSE 0x80 +#define LASTPHASE 0x03d +#define ARG_1 0x03e +#define MAXOFFSET 0x01 +#define RETURN_1 0x03f #define SEND_WDTR 0x80 -#define SEND_SDTR 0x80 -#define SEND_REJ 0x40 +#define SEND_SDTR 0x60 +#define SEND_SENSE 0x40 +#define SEND_REJ 0x20 +#define SCB_PAGEDIN 0x10 -#define SIGSTATE 0x04b +#define SIGSTATE 0x040 -#define DMAPARAMS 0x04c /* Parameters for DMA Logic */ +#define DMAPARAMS 0x041 /* Parameters for DMA Logic */ -#define SG_COUNT 0x04d -#define SG_NEXT 0x04e /* working value of SG pointer */ -#define SG_NEXT0 0x04e -#define SG_NEXT1 0x04f -#define SG_NEXT2 0x050 -#define SG_NEXT3 0x051 +#define SG_COUNT 0x042 +#define SG_NEXT 0x043 /* working value of SG pointer */ +#define SG_NEXT0 0x043 +#define SG_NEXT1 0x044 +#define SG_NEXT2 0x045 +#define SG_NEXT3 0x046 -#define SCBCOUNT 0x052 /* +#define SCBCOUNT 0x047 /* * Number of SCBs supported by * this card. */ -#define FLAGS 0x053 +#define COMP_SCBCOUNT 0x048 /* + * Two's compliment of SCBCOUNT + */ +#define QCNTMASK 0x049 /* + * Mask of bits to test against + * when looking at the Queue Count + * registers. Works around a bug + * on aic7850 chips. + */ +#define FLAGS 0x04a #define SINGLE_BUS 0x00 #define TWIN_BUS 0x01 #define WIDE_BUS 0x02 -#define DPHASE 0x04 -#define MAXOFFSET 0x08 +#define PAGESCBS 0x04 +#define DPHASE 0x10 +#define SELECTED 0x20 #define IDENTIFY_SEEN 0x40 #define RESELECTED 0x80 -#define ACTIVE_A 0x054 -#define ACTIVE_B 0x055 -#define SAVED_TCL 0x056 /* +#define SAVED_TCL 0x04b /* * Temporary storage for the * target/channel/lun of a * reconnecting target */ -#define WAITING_SCBH 0x057 /* +#define ACTIVE_A 0x04c +#define ACTIVE_B 0x04d +#define WAITING_SCBH 0x04e /* * head of list of SCBs awaiting * selection */ -#define QCNTMASK 0x058 /* - * Mask of bits to test against - * when looking at the Queue Count - * registers. Works around a bug - * on aic7850 chips. +#define DISCONNECTED_SCBH 0x04f /* + * head of list of SCBs that are + * disconnected. Used for SCB + * paging. */ -#define COMP_SCBCOUNT 0x059 #define SCB_LIST_NULL 0xff +#define SAVED_LINKPTR 0x050 +#define SAVED_SCBPTR 0x051 + #define SCSICONF 0x05a #define HOSTCONF 0x05d @@ -730,6 +760,7 @@ #define MSG_NOP 0x08 #define MSG_MSG_PARITY_ERROR 0x09 #define MSG_BUS_DEVICE_RESET 0x0c +#define MSG_ABORT_TAG 0x0d #define MSG_SIMPLE_TAG 0x20 #define MSG_IDENTIFY 0x80 |