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

📄 aic7xxx.seq

📁 arm平台上的uclinux系统全部源代码
💻 SEQ
📖 第 1 页 / 共 3 页
字号:
/* * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD. * * Copyright (c) 1994-1998 Justin Gibbs. * 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, immediately at the beginning of the file. * 2. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * Where this Software is combined with software released under the terms of  * the GNU Public License (GPL) and the terms of the GPL would require the  * combined work to also be released under the terms of the GPL, the terms * and conditions of this License will apply in addition to those of the * GPL with the exception of any terms or conditions of this License that * conflict with, or are expressly prohibited by, the GPL. * * 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.seq,v 1.1.1.1 1999/11/15 13:42:08 vadim Exp $ */#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. */reset:	clr	SCSISIGO;		/* De-assert BSY */	/* Always allow reselection */	if ((p->flags & AHC_TARGETMODE) != 0) {		mvi	SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP;	} else {		mvi	SCSISEQ, ENRSELI|ENAUTOATNP;	}	if ((p->features & AHC_CMD_CHAN) != 0) {		/* Ensure that no DMA operations are in progress */		clr	CCSGCTL;		clr	CCSCBCTL;	}	call	clear_target_state;	and	SXFRCTL0, ~SPIOEN;poll_for_work:	if ((p->features & AHC_QUEUE_REGS) == 0) {		mov	A, QINPOS;	}poll_for_work_loop:	if ((p->features & AHC_QUEUE_REGS) == 0) {		and	SEQCTL, ~PAUSEDIS;	}	test	SSTAT0, SELDO|SELDI	jnz selection;	test	SCSISEQ, ENSELO	jnz poll_for_work;	if ((p->features & AHC_TWIN) != 0) {		/*		 * Twin channel devices cannot handle things like SELTO		 * interrupts on the "background" channel.  So, if we		 * are selecting, keep polling the current channel util		 * either a selection or reselection occurs.		 */		xor	SBLKCTL,SELBUSB;	/* Toggle to the other bus */		test	SSTAT0, SELDO|SELDI	jnz selection;		test	SCSISEQ, ENSELO	jnz poll_for_work;		xor	SBLKCTL,SELBUSB;	/* Toggle back */	}	cmp	WAITING_SCBH,SCB_LIST_NULL jne start_waiting;test_queue:	/* Has the driver posted any work for us? */	if ((p->features & AHC_QUEUE_REGS) != 0) {		test	QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop;		mov	NONE, SNSCB_QOFF;		inc	QINPOS;	} else {		or	SEQCTL, PAUSEDIS;		cmp	KERNEL_QINPOS, A je poll_for_work_loop;		inc	QINPOS;		and	SEQCTL, ~PAUSEDIS;	}/* * We have at least one queued SCB now and we don't have any  * SCBs in the list of SCBs awaiting selection.  If we have * any SCBs available for use, pull the tag from the QINFIFO * and get to work on it. */	if ((p->flags & AHC_PAGESCBS) != 0) {		mov	ALLZEROS	call	get_free_or_disc_scb;	}dequeue_scb:	add	A, -1, QINPOS;	mvi	QINFIFO_OFFSET call fetch_byte;	if ((p->flags & AHC_PAGESCBS) == 0) {		/* In the non-paging case, the SCBID == hardware SCB index */		mov	SCBPTR, RETURN_2;	}dma_queued_scb:/* * DMA the SCB from host ram into the current SCB location. */	mvi	DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;	mov	RETURN_2	 call dma_scb;start_scb:	/*	 * Place us on the waiting list in case our selection	 * doesn't win during bus arbitration.	 */	mov	SCB_NEXT,WAITING_SCBH;	mov	WAITING_SCBH, SCBPTR;start_waiting:	/*	 * Pull the first entry off of the waiting SCB list.	 */	mov	SCBPTR, WAITING_SCBH;	call	start_selection;	jmp	poll_for_work;start_selection:	if ((p->features & AHC_TWIN) != 0) {		and	SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */		and	A,SELBUSB,SCB_TCL;	/* Get new channel bit */		or	SINDEX,A;		mov	SBLKCTL,SINDEX;		/* select channel */	}initialize_scsiid:	if ((p->features & AHC_ULTRA2) != 0) {		and	A, TID, SCB_TCL;	/* Get target ID */		and	SCSIID_ULTRA2, OID;	/* Clear old target */		or	SCSIID_ULTRA2, A;	} else {		and	A, TID, SCB_TCL;	/* Get target ID */		and	SCSIID, OID;		/* Clear old target */		or	SCSIID, A;	}	mvi	SCSISEQ, ENSELO|ENAUTOATNO|ENRSELI|ENAUTOATNP ret;/* * Initialize Ultra mode setting and clear the SCSI channel. * SINDEX should contain any additional bit's the client wants * set in SXFRCTL0. */initialize_channel:	or	A, CLRSTCNT|CLRCHN, SINDEX;	or	SXFRCTL0, A;	if ((p->features & AHC_ULTRA) != 0) {ultra:		mvi	SINDEX, ULTRA_ENB+1;		test	SAVED_TCL, 0x80		jnz ultra_2; /* Target ID > 7 */		dec	SINDEX;ultra_2:		mov     FUNCTION1,SAVED_TCL;		mov     A,FUNCTION1;		test	SINDIR, A	jz ndx_dtr;		or	SXFRCTL0, FAST20;	} /* * Initialize SCSIRATE with the appropriate value for this target. * The SCSIRATE settings for each target are stored in an array * based at TARG_SCSIRATE. */ndx_dtr:	shr	A,4,SAVED_TCL;	if ((p->features & AHC_TWIN) != 0) {		test	SBLKCTL,SELBUSB	jz ndx_dtr_2;		or	SAVED_TCL, SELBUSB; 		or	A,0x08;			/* Channel B entries add 8 */ndx_dtr_2:	}	if ((p->features & AHC_ULTRA2) != 0) {		add	SINDEX, TARG_OFFSET, A;		mov	SCSIOFFSET, SINDIR;	}	add	SINDEX,TARG_SCSIRATE,A;	mov	SCSIRATE,SINDIR ret;selection:	test	SSTAT0,SELDO	jnz select_out;select_in:	if ((p->flags & AHC_TARGETMODE) != 0) {		test	SSTAT0, TARGET	jz initiator_reselect;		/*		 * We've just been selected.  Assert BSY and		 * setup the phase for receiving the messages		 * from the target.		 */		mvi	SCSISIGO, P_MESGOUT|BSYO;		mvi	CLRSINT0, CLRSELDO;		/*		 * If ATN isn't asserted, go directly to bus free.		 */		test	SCSISIGI, ATNI	jz	target_busfree;		/*		 * Setup the DMA for sending the identify and		 * command information.		 */		mov	A, TMODE_CMDADDR_NEXT;		mvi	DINDEX, HADDR;		mvi	TMODE_CMDADDR call set_32byte_addr;		mvi	DFCNTRL, FIFORESET;		clr	SINDEX;		/* Watch ATN closely now */message_loop:		or	SXFRCTL0, SPIOEN;		test	SSTAT0, SPIORDY jz .;		and	SXFRCTL0, ~SPIOEN;		mov	DINDEX, SCSIDATL;		mov	DFDAT, DINDEX;		inc	SINDEX;		/* Message Testing... */		test	DINDEX, MSG_IDENTIFYFLAG jz . + 2;		mov	ARG_1, DINDEX;		test	SCSISIGI, ATNI	jnz	message_loop;		add	A, -4, SINDEX;		jc	target_cmdphase;		mvi	DFDAT, SCB_LIST_NULL;	/* Terminate the message list */target_cmdphase:		add	HCNT[0], 1, A;		clr	HCNT[1];		clr	HCNT[2];		mvi	SCSISIGO, P_COMMAND|BSYO;		or	SXFRCTL0, SPIOEN;		test	SSTAT0, SPIORDY jz .;		mov	A, SCSIDATL;		mov	DFDAT, A;	/* Store for host */		/*		 * Determine the number of bytes to read		 * based on the command group code.  Count is		 * one less than the total since we've already		 * fetched the first byte.		 */		clr	SINDEX;		shr	A, CMD_GROUP_CODE_SHIFT;		add	SEQADDR0, A;		add	SINDEX, CMD_GROUP0_BYTE_DELTA;		nop;	/* Group 1 and 2 are the same */		add	SINDEX, CMD_GROUP2_BYTE_DELTA;		nop;	/* Group 3 is reserved */		add	SINDEX, CMD_GROUP4_BYTE_DELTA;		add	SINDEX, CMD_GROUP5_BYTE_DELTA;		/* Group 6 and 7 are not handled yet */		mov	A, SINDEX;		add	HCNT[0], A;command_loop:		test	SSTAT0, SPIORDY jz .;		cmp	SINDEX, 1 jne . + 2;		and	SXFRCTL0, ~SPIOEN;	/* Last Byte */		mov	DFDAT, SCSIDATL;		dec	SINDEX;		test	SINDEX, 0xFF jnz command_loop;		or	DFCNTRL, HDMAEN|FIFOFLUSH;			call	dma_finish;		test	ARG_1, MSG_IDENTIFY_DISCFLAG jz selectin_post;		mvi	SCSISIGO, P_MESGIN|BSYO;		or	SXFRCTL0, SPIOEN;		mvi	MSG_DISCONNECT call target_outb;	selectin_post:		inc	TMODE_CMDADDR_NEXT;		cmp	TMODE_CMDADDR_NEXT, TMODE_NUMCMDS jne . + 2;		clr	TMODE_CMDADDR_NEXT;		mvi	QOUTFIFO, SCB_LIST_NULL;		mvi	INTSTAT,CMDCMPLT;		test	ARG_1, MSG_IDENTIFY_DISCFLAG jnz target_busfree;		/* Busy loop on something then go to data or status phase */target_busfree:		clr	SCSISIGO;		jmp	poll_for_work;	}/* * 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:	mvi	CLRSINT0, CLRSELDI;	/* XXX test for and handle ONE BIT condition */	and	SAVED_TCL, SELID_MASK, SELID;	mvi	CLRSINT1,CLRBUSFREE;	or	SIMODE1, ENBUSFREE;		/*						 * We aren't expecting a						 * bus free, so interrupt						 * the kernel driver if it						 * happens.						 */	mvi	SPIOEN call	initialize_channel;	mvi	MSG_OUT, MSG_NOOP;		/* No message to send */	jmp	ITloop;/* * 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 */	mvi	SCSISEQ, ENRSELI|ENAUTOATNP;	/*						 * ATN on parity errors						 * for "in" phases						 */	mvi	CLRSINT0, CLRSELDO;	mov	SCBPTR, WAITING_SCBH;	mov	WAITING_SCBH,SCB_NEXT;	mov	SAVED_TCL, SCB_TCL;	mvi	CLRSINT1,CLRBUSFREE;	or	SIMODE1, ENBUSFREE;		/*						 * We aren't expecting a						 * bus free, so interrupt						 * the kernel driver if it						 * happens.						 */	mvi	SPIOEN call	initialize_channel;/* * As soon as we get a successful selection, the target should go * into the message out phase since we have ATN asserted. */	mvi	MSG_OUT, MSG_IDENTIFYFLAG;	or	SEQ_FLAGS, IDENTIFY_SEEN;/* * Main loop for information transfer phases.  Wait for the target * to assert REQ before checking MSG, C/D and I/O for the bus phase. */ITloop:	call	phase_lock;	mov	A, LASTPHASE;	test	A, ~P_DATAIN	jz p_data;	cmp	A,P_COMMAND	je p_command;	cmp	A,P_MESGOUT	je p_mesgout;	cmp	A,P_STATUS	je p_status;	cmp	A,P_MESGIN	je p_mesgin;	mvi	INTSTAT,BAD_PHASE;	/* unknown phase - signal driver */	jmp	ITloop;			/* Try reading the bus again. */await_busfree:	and	SIMODE1, ~ENBUSFREE;	call	clear_target_state;	mov	NONE, SCSIDATL;		/* Ack the last byte */	and	SXFRCTL0, ~SPIOEN;	test	SSTAT1,REQINIT|BUSFREE	jz .;	test	SSTAT1, BUSFREE jnz poll_for_work;	mvi	INTSTAT, BAD_PHASE;	clear_target_state:	clr	DFCNTRL;		/*					 * We assume that the kernel driver					 * may reset us at any time, even					 * in the middle of a DMA, so clear					 * DFCNTRL too.					 */	clr	SCSIRATE;		/*					 * We don't know the target we will					 * connect to, so default to narrow					 * transfers to avoid parity problems.					 */	and	SXFRCTL0, ~(FAST20);	mvi	LASTPHASE, P_BUSFREE;	/* clear target specific flags */	and	SEQ_FLAGS, (WIDE_BUS|TWIN_BUS) ret;/* * If we re-enter the data phase after going through another phase, the * STCNT may have been cleared, so restore it from the residual field. */data_phase_reinit:	mvi	DINDEX, STCNT;	mvi	SCB_RESID_DCNT	call bcopy_3;	jmp	data_phase_loop;p_data:	if ((p->features & AHC_ULTRA2) != 0) {		mvi	DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN;	} else {		mvi	DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET;	}	test	LASTPHASE, IOI jnz . + 2;	or	DMAPARAMS, DIRECTION;	call	assert;			/*					 * Ensure entering a data					 * phase is okay - seen identify, etc.					 */	if ((p->features & AHC_CMD_CHAN) != 0) {		mvi	CCSGADDR, CCSGADDR_MAX;	}	test	SEQ_FLAGS, DPHASE	jnz data_phase_reinit;	/* We have seen a data phase */	or	SEQ_FLAGS, DPHASE;	/*	 * Initialize the DMA address and counter from the SCB.	 * Also set SG_COUNT and SG_NEXT in memory since we cannot	 * modify the values in the SCB itself until we see a	 * save data pointers message.	 */	if ((p->features & AHC_CMD_CHAN) != 0) {		bmov	HADDR, SCB_DATAPTR, 7;	} else {		mvi	DINDEX, HADDR;		mvi	SCB_DATAPTR	call bcopy_7;	}	if ((p->features & AHC_ULTRA2) == 0) {		call	set_stcnt_from_hcnt;	}	mov	SG_COUNT,SCB_SGCOUNT;	mvi	DINDEX, SG_NEXT;	mvi	SCB_SGPTR	call bcopy_4;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;	and	DMAPARAMS, ~(HDMAEN|SDMAEN);	if ((p->features & AHC_ULTRA2) != 0) {		bmov	HCNT, ALLONES, 3;	} else {		mvi	STCNT[0], 0xFF;

⌨️ 快捷键说明

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