⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aic7xxx.seq

📁 linux-2.6.15.6
💻 SEQ
📖 第 1 页 / 共 5 页
字号:
/* * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD. * * Copyright (c) 1994-2001 Justin T. Gibbs. * Copyright (c) 2000-2001 Adaptec Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions, and the following disclaimer, *    without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer *    substantially similar to the "NO WARRANTY" disclaimer below *    ("Disclaimer") and any redistribution must be conditioned upon *    including a substantially similar Disclaimer requirement for further *    binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names *    of any contributors may be used to endorse or promote products derived *    from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. * * $FreeBSD$ */VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $"PATCH_ARG_LIST = "struct ahc_softc *ahc"PREFIX = "ahc_"#include "aic7xxx.reg"#include "scsi_message.h"/* * A few words on the waiting SCB list: * After starting the selection hardware, we check for reconnecting targets * as well as for our selection to complete just in case the reselection wins * bus arbitration.  The problem with this is that we must keep track of the * SCB that we've already pulled from the QINFIFO and started the selection * on just in case the reselection wins so that we can retry the selection at * a later time.  This problem cannot be resolved by holding a single entry * in scratch ram since a reconnecting target can request sense and this will * create yet another SCB waiting for selection.  The solution used here is to  * use byte 27 of the SCB as a psuedo-next pointer and to thread a list * of SCBs that are awaiting selection.  Since 0-0xfe are valid SCB indexes,  * SCB_LIST_NULL is 0xff which is out of range.  An entry is also added to * this list everytime a request sense occurs or after completing a non-tagged * command for which a second SCB has been queued.  The sequencer will * automatically consume the entries. */bus_free_sel:	/*	 * Turn off the selection hardware.  We need to reset the	 * selection request in order to perform a new selection.	 */	and	SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP;	and	SIMODE1, ~ENBUSFREE;poll_for_work:	call	clear_target_state;	and	SXFRCTL0, ~SPIOEN;	if ((ahc->features & AHC_ULTRA2) != 0) {		clr	SCSIBUSL;	}	test	SCSISEQ, ENSELO	jnz poll_for_selection;	if ((ahc->features & AHC_TWIN) != 0) {		xor	SBLKCTL,SELBUSB;	/* Toggle to the other bus */		test	SCSISEQ, ENSELO		jnz poll_for_selection;	}	cmp	WAITING_SCBH,SCB_LIST_NULL jne start_waiting;poll_for_work_loop:	if ((ahc->features & AHC_TWIN) != 0) {		xor	SBLKCTL,SELBUSB;	/* Toggle to the other bus */	}	test	SSTAT0, SELDO|SELDI	jnz selection;test_queue:	/* Has the driver posted any work for us? */BEGIN_CRITICAL;	if ((ahc->features & AHC_QUEUE_REGS) != 0) {		test	QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop;	} else {		mov	A, QINPOS;		cmp	KERNEL_QINPOS, A je poll_for_work_loop;	}	mov	ARG_1, NEXT_QUEUED_SCB;	/*	 * We have at least one queued SCB now and we don't have any 	 * SCBs in the list of SCBs awaiting selection.  Allocate a	 * card SCB for the host's SCB and get to work on it.	 */	if ((ahc->flags & AHC_PAGESCBS) != 0) {		mov	ALLZEROS	call	get_free_or_disc_scb;	} else {		/* In the non-paging case, the SCBID == hardware SCB index */		mov	SCBPTR, ARG_1;	}	or	SEQ_FLAGS2, SCB_DMA;END_CRITICAL;dma_queued_scb:	/*	 * DMA the SCB from host ram into the current SCB location.	 */	mvi	DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;	mov	ARG_1	call dma_scb;	/*	 * Check one last time to see if this SCB was canceled	 * before we completed the DMA operation.  If it was,	 * the QINFIFO next pointer will not match our saved	 * value.	 */	mov	A, ARG_1;BEGIN_CRITICAL;	cmp	NEXT_QUEUED_SCB, A jne abort_qinscb;	if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {		cmp	SCB_TAG, A je . + 2;		mvi	SCB_MISMATCH call set_seqint;	}	mov	NEXT_QUEUED_SCB, SCB_NEXT;	mov	SCB_NEXT,WAITING_SCBH;	mov	WAITING_SCBH, SCBPTR;	if ((ahc->features & AHC_QUEUE_REGS) != 0) {		mov	NONE, SNSCB_QOFF;	} else {		inc	QINPOS;	}	and	SEQ_FLAGS2, ~SCB_DMA;END_CRITICAL;start_waiting:	/*	 * Start the first entry on the waiting SCB list.	 */	mov	SCBPTR, WAITING_SCBH;	call	start_selection;poll_for_selection:	/*	 * Twin channel devices cannot handle things like SELTO	 * interrupts on the "background" channel.  So, while	 * selecting, keep polling the current channel until	 * either a selection or reselection occurs.	 */	test	SSTAT0, SELDO|SELDI	jz poll_for_selection;selection:	/*	 * We aren't expecting a bus free, so interrupt	 * the kernel driver if it happens.	 */	mvi	CLRSINT1,CLRBUSFREE;	if ((ahc->features & AHC_DT) == 0) {		or	SIMODE1, ENBUSFREE;	}	/*	 * Guard against a bus free after (re)selection	 * but prior to enabling the busfree interrupt.  SELDI	 * and SELDO will be cleared in that case.	 */	test	SSTAT0, SELDI|SELDO	jz bus_free_sel;	test	SSTAT0,SELDO	jnz select_out;select_in:	if ((ahc->flags & AHC_TARGETROLE) != 0) {		if ((ahc->flags & AHC_INITIATORROLE) != 0) {			test	SSTAT0, TARGET	jz initiator_reselect;		}		mvi	CLRSINT0, CLRSELDI;		/*		 * We've just been selected.  Assert BSY and		 * setup the phase for receiving messages		 * from the target.		 */		mvi	SCSISIGO, P_MESGOUT|BSYO;		/*		 * Setup the DMA for sending the identify and		 * command information.		 */		mvi	SEQ_FLAGS, CMDPHASE_PENDING;		mov     A, TQINPOS;		if ((ahc->features & AHC_CMD_CHAN) != 0) {			mvi	DINDEX, CCHADDR;			mvi	SHARED_DATA_ADDR call set_32byte_addr;			mvi	CCSCBCTL, CCSCBRESET;		} else {			mvi	DINDEX, HADDR;			mvi	SHARED_DATA_ADDR call set_32byte_addr;			mvi	DFCNTRL, FIFORESET;		}		/* Initiator that selected us */		and	SAVED_SCSIID, SELID_MASK, SELID;		/* The Target ID we were selected at */		if ((ahc->features & AHC_MULTI_TID) != 0) {			and	A, OID, TARGIDIN;		} else if ((ahc->features & AHC_ULTRA2) != 0) {			and	A, OID, SCSIID_ULTRA2;		} else {			and	A, OID, SCSIID;		}		or	SAVED_SCSIID, A;		if ((ahc->features & AHC_TWIN) != 0) {			test 	SBLKCTL, SELBUSB jz . + 2;			or	SAVED_SCSIID, TWIN_CHNLB;		}		if ((ahc->features & AHC_CMD_CHAN) != 0) {			mov	CCSCBRAM, SAVED_SCSIID;		} else {			mov	DFDAT, SAVED_SCSIID;		}		/*		 * If ATN isn't asserted, the target isn't interested		 * in talking to us.  Go directly to bus free.		 * XXX SCSI-1 may require us to assume lun 0 if		 * ATN is false.		 */		test	SCSISIGI, ATNI	jz	target_busfree;		/*		 * Watch ATN closely now as we pull in messages from the		 * initiator.  We follow the guidlines from section 6.5		 * of the SCSI-2 spec for what messages are allowed when.		 */		call	target_inb;		/*		 * Our first message must be one of IDENTIFY, ABORT, or		 * BUS_DEVICE_RESET.		 */		test	DINDEX, MSG_IDENTIFYFLAG jz host_target_message_loop;		/* Store for host */		if ((ahc->features & AHC_CMD_CHAN) != 0) {			mov	CCSCBRAM, DINDEX;		} else {			mov	DFDAT, DINDEX;		}		and	SAVED_LUN, MSG_IDENTIFY_LUNMASK, DINDEX;		/* Remember for disconnection decision */		test	DINDEX, MSG_IDENTIFY_DISCFLAG jnz . + 2;		/* XXX Honor per target settings too */		or	SEQ_FLAGS, NO_DISCONNECT;		test	SCSISIGI, ATNI	jz	ident_messages_done;		call	target_inb;		/*		 * If this is a tagged request, the tagged message must		 * immediately follow the identify.  We test for a valid		 * tag message by seeing if it is >= MSG_SIMPLE_Q_TAG and		 * < MSG_IGN_WIDE_RESIDUE.		 */		add	A, -MSG_SIMPLE_Q_TAG, DINDEX;		jnc	ident_messages_done_msg_pending;		add	A, -MSG_IGN_WIDE_RESIDUE, DINDEX;		jc	ident_messages_done_msg_pending;		/* Store for host */		if ((ahc->features & AHC_CMD_CHAN) != 0) {			mov	CCSCBRAM, DINDEX;		} else {			mov	DFDAT, DINDEX;		}				/*		 * If the initiator doesn't feel like providing a tag number,		 * we've got a failed selection and must transition to bus		 * free.		 */		test	SCSISIGI, ATNI	jz	target_busfree;		/*		 * Store the tag for the host.		 */		call	target_inb;		if ((ahc->features & AHC_CMD_CHAN) != 0) {			mov	CCSCBRAM, DINDEX;		} else {			mov	DFDAT, DINDEX;		}		mov	INITIATOR_TAG, DINDEX;		or	SEQ_FLAGS, TARGET_CMD_IS_TAGGED;ident_messages_done:		/* Terminate the ident list */		if ((ahc->features & AHC_CMD_CHAN) != 0) {			mvi	CCSCBRAM, SCB_LIST_NULL;		} else {			mvi	DFDAT, SCB_LIST_NULL;		}		or	SEQ_FLAGS, TARG_CMD_PENDING;		test	SEQ_FLAGS2, TARGET_MSG_PENDING			jnz target_mesgout_pending;		test	SCSISIGI, ATNI jnz target_mesgout_continue;		jmp	target_ITloop;ident_messages_done_msg_pending:		or	SEQ_FLAGS2, TARGET_MSG_PENDING;		jmp	ident_messages_done;		/*		 * Pushed message loop to allow the kernel to		 * run it's own target mode message state engine.		 */host_target_message_loop:		mvi	HOST_MSG_LOOP call set_seqint;		cmp	RETURN_1, EXIT_MSG_LOOP	je target_ITloop;		test	SSTAT0, SPIORDY jz .;		jmp	host_target_message_loop;	}if ((ahc->flags & AHC_INITIATORROLE) != 0) {/* * Reselection has been initiated by a target. Make a note that we've been * reselected, but haven't seen an IDENTIFY message from the target yet. */initiator_reselect:	/* XXX test for and handle ONE BIT condition */	or	SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN;	and	SAVED_SCSIID, SELID_MASK, SELID;	if ((ahc->features & AHC_ULTRA2) != 0) {		and	A, OID, SCSIID_ULTRA2;	} else {		and	A, OID, SCSIID;	}	or	SAVED_SCSIID, A;	if ((ahc->features & AHC_TWIN) != 0) {		test	SBLKCTL, SELBUSB	jz . + 2;		or	SAVED_SCSIID, TWIN_CHNLB;	}	mvi	CLRSINT0, CLRSELDI;	jmp	ITloop;}abort_qinscb:	call	add_scb_to_free_list;	jmp	poll_for_work_loop;start_selection:	/*	 * If bus reset interrupts have been disabled (from a previous	 * reset), re-enable them now.  Resets are only of interest	 * when we have outstanding transactions, so we can safely	 * defer re-enabling the interrupt until, as an initiator,	 * we start sending out transactions again.	 */	test	SIMODE1, ENSCSIRST	jnz . + 3;	mvi	CLRSINT1, CLRSCSIRSTI;	or	SIMODE1, ENSCSIRST;	if ((ahc->features & AHC_TWIN) != 0) {		and	SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */		test	SCB_SCSIID, TWIN_CHNLB jz . + 2;		or	SINDEX, SELBUSB;		mov	SBLKCTL,SINDEX;		/* select channel */	}initialize_scsiid:	if ((ahc->features & AHC_ULTRA2) != 0) {		mov	SCSIID_ULTRA2, SCB_SCSIID;	} else if ((ahc->features & AHC_TWIN) != 0) {		and	SCSIID, TWIN_TID|OID, SCB_SCSIID;	} else {		mov	SCSIID, SCB_SCSIID;	}	if ((ahc->flags & AHC_TARGETROLE) != 0) {		mov	SINDEX, SCSISEQ_TEMPLATE;		test	SCB_CONTROL, TARGET_SCB jz . + 2;		or	SINDEX, TEMODE;		mov	SCSISEQ, SINDEX ret;	} else {		mov	SCSISEQ, SCSISEQ_TEMPLATE ret;	}/* * Initialize transfer settings with SCB provided settings. */set_transfer_settings:	if ((ahc->features & AHC_ULTRA) != 0) {		test	SCB_CONTROL, ULTRAENB jz . + 2;		or	SXFRCTL0, FAST20;	} 	/*	 * Initialize SCSIRATE with the appropriate value for this target.	 */	if ((ahc->features & AHC_ULTRA2) != 0) {		bmov	SCSIRATE, SCB_SCSIRATE, 2 ret;	} else {		mov	SCSIRATE, SCB_SCSIRATE ret;	}if ((ahc->flags & AHC_TARGETROLE) != 0) {/* * We carefully toggle SPIOEN to allow us to return the  * message byte we receive so it can be checked prior to * driving REQ on the bus for the next byte. */target_inb:	/*	 * Drive REQ on the bus by enabling SCSI PIO.	 */	or	SXFRCTL0, SPIOEN;	/* Wait for the byte */	test	SSTAT0, SPIORDY jz .;	/* Prevent our read from triggering another REQ */	and	SXFRCTL0, ~SPIOEN;	/* Save latched contents */	mov	DINDEX, SCSIDATL ret;}/* * After the selection, remove this SCB from the "waiting SCB" * list.  This is achieved by simply moving our "next" pointer into * WAITING_SCBH.  Our next pointer will be set to null the next time this * SCB is used, so don't bother with it now. */select_out:	/* Turn off the selection hardware */	and	SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ;	mov	SCBPTR, WAITING_SCBH;	mov	WAITING_SCBH,SCB_NEXT;	mov	SAVED_SCSIID, SCB_SCSIID;	and	SAVED_LUN, LID, SCB_LUN;	call	set_transfer_settings;	if ((ahc->flags & AHC_TARGETROLE) != 0) {		test	SSTAT0, TARGET	jz initiator_select;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -