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

📄 aic7xxx.seq

📁 arm平台上的uclinux系统全部源代码
💻 SEQ
📖 第 1 页 / 共 3 页
字号:
		mvi	STCNT[1], 0xFF;		mvi	STCNT[2], 0xFF;	}data_phase_inbounds:/* If we are the last SG block, tell the hardware. */	cmp	SG_COUNT,0x01 jne data_phase_wideodd;	if ((p->features & AHC_ULTRA2) != 0) {		or	SG_CACHEPTR, LAST_SEG;	} else {		and	DMAPARAMS, ~WIDEODD;	}data_phase_wideodd:	if ((p->features & AHC_ULTRA2) != 0) {		mov	SINDEX, ALLONES;		mov	DFCNTRL, DMAPARAMS;		test	SSTAT0, SDONE jnz .;/* Wait for preload to complete */data_phase_dma_loop:		test	SSTAT0,	SDONE jnz data_phase_dma_done;		test	SSTAT1,PHASEMIS	jz data_phase_dma_loop;	/* ie. underrun */data_phase_dma_phasemis:		test	SSTAT0,SDONE	jnz . + 2;		mov	SINDEX,ALLZEROS;	/* Remeber the phasemiss */	} else {		mov	DMAPARAMS  call dma;	}data_phase_dma_done:/* Go tell the host about any overruns */	test	SXFRCTL1,BITBUCKET jnz data_phase_overrun;/* Exit if we had an underrun.  dma clears SINDEX in this case. */	test	SINDEX,0xff	jz data_phase_finish;/* * Advance the scatter-gather pointers if needed  */sg_advance:	dec	SG_COUNT;	/* one less segment to go */	test	SG_COUNT, 0xff	jz data_phase_finish; /* Are we done? *//* * Load a struct scatter and set up the data address and length. * 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 little-endian host data storage. */sg_load:	if ((p->features & AHC_CMD_CHAN) != 0) {		/*		 * Do we have any prefetch left???		 */		cmp	CCSGADDR, CCSGADDR_MAX jne prefetched_segs_avail;		/*		 * Fetch MIN(CCSGADDR_MAX, (SG_COUNT * 8)) bytes.		 */		add	A, -(CCSGRAM_MAXSEGS + 1), SG_COUNT;		mvi	A, CCSGADDR_MAX;		jc	. + 2;		shl	A, 3, SG_COUNT;		mov	CCHCNT, A;		bmov	CCHADDR, SG_NEXT, 4;		mvi	CCSGCTL, CCSGEN|CCSGRESET;		test	CCSGCTL, CCSGDONE jz .;		and	CCSGCTL, ~CCSGEN;		test	CCSGCTL, CCSGEN jnz .;		mvi	CCSGCTL, CCSGRESET;prefetched_segs_avail:		bmov 	HADDR, CCSGRAM, 8;	} else {		mvi	DINDEX, HADDR;		mvi	SG_NEXT	call bcopy_4;		mvi	HCNT[0],SG_SIZEOF;		clr	HCNT[1];		clr	HCNT[2];		or	DFCNTRL, HDMAEN|DIRECTION|FIFORESET;		call	dma_finish;		/*		 * Copy data from FIFO into SCB data pointer and data count.		 * This assumes that the SG segments are of the form:		 * struct ahc_dma_seg {		 *	u_int32_t	addr;	four bytes, little-endian order		 *	u_int32_t	len;	four bytes, little endian order		 * };		 */		mvi	HADDR	call dfdat_in_7;	}	if ((p->features & AHC_ULTRA2) == 0) {		/* Load STCNT as well.  It is a mirror of HCNT */		call	set_stcnt_from_hcnt;	}/* Advance the SG pointer */	clr	A;			/* add sizeof(struct scatter) */	add	SG_NEXT[0],SG_SIZEOF;	adc	SG_NEXT[1],A;	test	SSTAT1,PHASEMIS	jz data_phase_loop;	/* Ensure the last seg is visable at the shaddow layer */	if ((p->features & AHC_ULTRA2) != 0) {		or	DFCNTRL, PRELOADEN;	}data_phase_finish:	if ((p->features & AHC_ULTRA2) != 0) {		call	ultra2_dmafinish;	}/* * After a DMA finishes, save the SG and STCNT residuals back into the SCB * We use STCNT instead of HCNT, since it's a reflection of how many bytes  * were transferred on the SCSI (as opposed to the host) bus. */	mov	SCB_RESID_DCNT[0],STCNT[0];	mov	SCB_RESID_DCNT[1],STCNT[1];	mov	SCB_RESID_DCNT[2],STCNT[2];	mov	SCB_RESID_SGCNT, SG_COUNT;	if ((p->features & AHC_ULTRA2) != 0) {		or	SXFRCTL0, CLRSTCNT|CLRCHN;	}	jmp	ITloop;data_phase_overrun:	if ((p->features & AHC_ULTRA2) != 0) {		call	ultra2_dmafinish;		or	SXFRCTL0, CLRSTCNT|CLRCHN;	}/* * Turn off BITBUCKET mode and notify the host */	and	SXFRCTL1, ~BITBUCKET;	mvi	INTSTAT,DATA_OVERRUN;	jmp	ITloop;ultra2_dmafinish:	if ((p->features & AHC_ULTRA2) != 0) {		test	DFCNTRL, DIRECTION jnz ultra2_dmahalt;		and	DFCNTRL, ~SCSIEN;		test	DFCNTRL, SCSIEN jnz .;		or	DFCNTRL, FIFOFLUSH;		test	DFSTATUS, FIFOEMP jz . - 1;ultra2_dmahalt:		and     DFCNTRL, ~(SCSIEN|HDMAEN);		test	DFCNTRL, HDMAEN jnz .;		ret;	}/* * Command phase.  Set up the DMA registers and let 'er rip. */p_command:	call	assert;/* * Load HADDR and HCNT. */	if ((p->features & AHC_ULTRA2) != 0) {		or	SG_CACHEPTR, LAST_SEG;	}	if ((p->features & AHC_CMD_CHAN) != 0) {		bmov	HADDR, SCB_CMDPTR, 5;		bmov	HCNT[1], ALLZEROS, 2;	} else {		mvi	DINDEX, HADDR;		mvi	SCB_CMDPTR	call bcopy_5;		clr	HCNT[1];		clr	HCNT[2];	}	if ((p->features & AHC_ULTRA2) == 0) {		call	set_stcnt_from_hcnt;		mvi	(SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET) call dma;	} else {		mvi	(PRELOADEN|SCSIEN|HDMAEN|DIRECTION) call dma;	}	jmp	ITloop;/* * Status phase.  Wait for the data byte to appear, then read it * and store it into the SCB. */p_status:	call	assert;	mov	SCB_TARGET_STATUS, SCSIDATL;	jmp	ITloop;/* * Message out phase.  If MSG_OUT is 0x80, build I full indentify message * sequence and send it to the target.  In addition, if the MK_MESSAGE bit * is set in the SCB_CONTROL byte, interrupt the host and allow it to send * it's own message. *  * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message. * This is done to allow the hsot to send messages outside of an identify * sequence while protecting the seqencer from testing the MK_MESSAGE bit * on an SCB that might not be for the current nexus. (For example, a * BDR message in responce to a bad reselection would leave us pointed to * an SCB that doesn't have anything to do with the current target). * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag, * bus device reset). * * When there are no messages to send, MSG_OUT should be set to MSG_NOOP, * in case the target decides to put us in this phase for some strange * reason. */p_mesgout:	mov	SINDEX, MSG_OUT;	cmp	SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;p_mesgout_identify:	if ((p->features & AHC_WIDE) != 0) {		and	SINDEX,0xf,SCB_TCL;	/* lun */	} else {		and	SINDEX,0x7,SCB_TCL;	/* lun */	}	and	A,DISCENB,SCB_CONTROL;	/* mask off disconnect privledge */	or	SINDEX,A;		/* or in disconnect privledge */	or	SINDEX,MSG_IDENTIFYFLAG;p_mesgout_mk_message:	test	SCB_CONTROL,MK_MESSAGE  jz p_mesgout_tag;	mov	SCSIDATL, SINDEX;	/* Send the last byte */	jmp	p_mesgout_from_host + 1;/* Skip HOST_MSG test *//* * 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. */p_mesgout_tag:	test	SCB_CONTROL,TAG_ENB jz  p_mesgout_onebyte;	mov	SCSIDATL, SINDEX;	/* Send the identify message */	call	phase_lock;	cmp	LASTPHASE, P_MESGOUT	jne p_mesgout_done;	and	SCSIDATL,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL;	call	phase_lock;	cmp	LASTPHASE, P_MESGOUT	jne p_mesgout_done;	mov	SCB_TAG	jmp p_mesgout_onebyte;/* * Interrupt the driver, and allow it to send a message * if it asks. */p_mesgout_from_host:	cmp	SINDEX, HOST_MSG	jne p_mesgout_onebyte;	mvi     INTSTAT,AWAITING_MSG;	nop;	/*	 * Did the host detect a phase change?	 */	cmp	RETURN_1, MSGOUT_PHASEMIS je p_mesgout_done;p_mesgout_onebyte:	mvi	CLRSINT1, CLRATNO;	mov	SCSIDATL, SINDEX;/* * If the next bus phase after ATN drops is a message out, it means * that the target is requesting that the last message(s) be resent. */	call	phase_lock;	cmp	LASTPHASE, P_MESGOUT	jne p_mesgout_done;	or	SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */	jmp	p_mesgout;p_mesgout_done:	mvi	CLRSINT1,CLRATNO;	/* Be sure to turn ATNO off */	mov	LAST_MSG, MSG_OUT;	cmp	MSG_OUT, MSG_IDENTIFYFLAG jne . + 2;	and	SCB_CONTROL, ~MK_MESSAGE;	mvi	MSG_OUT, MSG_NOOP;	/* No message left */	jmp	ITloop;/* * Message in phase.  Bytes are read using Automatic PIO mode. */p_mesgin:	mvi	ACCUM		call inb_first;	/* read the 1st message byte */	test	A,MSG_IDENTIFYFLAG	jnz mesgin_identify;	cmp	A,MSG_DISCONNECT	je mesgin_disconnect;	cmp	A,MSG_SAVEDATAPOINTER	je mesgin_sdptrs;	cmp	ALLZEROS,A		je mesgin_complete;	cmp	A,MSG_RESTOREPOINTERS	je mesgin_rdptrs;	cmp	A,MSG_EXTENDED		je mesgin_extended;	cmp	A,MSG_MESSAGE_REJECT	je mesgin_reject;	cmp	A,MSG_NOOP		je mesgin_done;rej_mesgin:/* * We have no idea what this message in is, so we issue a message reject * and hope for the best.  In any case, rejection should be a rare * occurrence - signal the driver when it happens. */	mvi	INTSTAT,SEND_REJECT;		/* let driver know */	mvi	MSG_MESSAGE_REJECT	call mk_mesg;mesgin_done:	mov	NONE,SCSIDATL;		/*dummy read from latch to ACK*/	jmp	ITloop;mesgin_complete:/* * We got a "command complete" message, so put the SCB_TAG into the QOUTFIFO, * and trigger a completion interrupt.  Before doing so, check to see if there * is a residual or the status byte is something other than STATUS_GOOD (0). * In either of these conditions, we upload the SCB back to the host so it can * process this information.  In the case of a non zero status byte, we  * additionally interrupt the kernel driver synchronously, allowing it to * decide if sense should be retrieved.  If the kernel driver wishes to request * sense, it will fill the kernel SCB with a request sense command and set * RETURN_1 to SEND_SENSE.  If RETURN_1 is set to SEND_SENSE we redownload * the SCB, and process it as the next command by adding it to the waiting list. * If the kernel driver does not wish to request sense, it need only clear * RETURN_1, and the command is allowed to complete normally.  We don't bother * to post to the QOUTFIFO in the error cases 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 */	test	SCB_RESID_SGCNT,0xff	jnz upload_scb;	test	SCB_TARGET_STATUS,0xff	jz complete;	/* Good Status? */upload_scb:	mvi	DMAPARAMS, FIFORESET;	mov	SCB_TAG		call dma_scb;check_status:	test	SCB_TARGET_STATUS,0xff	jz complete;	/* Just a residual? */	mvi	INTSTAT,BAD_STATUS;			/* let driver know */	nop;	cmp	RETURN_1, SEND_SENSE	jne complete;	/* This SCB becomes the next to execute as it will retrieve sense */	mvi	DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;	mov	SCB_TAG		call dma_scb;add_to_waiting_list:	mov	SCB_NEXT,WAITING_SCBH;	mov	WAITING_SCBH, SCBPTR;	/*	 * Prepare our selection hardware before the busfree so we have a	 * high probability of winning arbitration.	 */	call	start_selection;	jmp	await_busfree;complete:	/* If we are untagged, clear our address up in host ram */	test	SCB_CONTROL, TAG_ENB jnz complete_post;	mov	A, SAVED_TCL;	mvi	UNTAGGEDSCB_OFFSET call post_byte_setup;	mvi	SCB_LIST_NULL call post_byte;complete_post:	/* Post the SCB and issue an interrupt */	if ((p->features & AHC_QUEUE_REGS) != 0) {		mov	A, SDSCB_QOFF;	} else {		mov	A, QOUTPOS;	}	mvi	QOUTFIFO_OFFSET call post_byte_setup;	mov	SCB_TAG call post_byte;	if ((p->features & AHC_QUEUE_REGS) == 0) {		inc 	QOUTPOS;	}	mvi	INTSTAT,CMDCMPLT;add_to_free_list:	call	add_scb_to_free_list;	jmp	await_busfree;/* * Is it an extended message?  Copy the message to our message buffer and * notify the host.  The host will tell us whether to reject this message, * respond to it with the message that the host placed in our message buffer, * or simply to do nothing. */mesgin_extended:	mvi	INTSTAT,EXTENDED_MSG;		/* let driver know */	jmp	ITloop;/* * Is it a disconnect message?  Set a flag in the SCB to remind us * and await the bus going free. */mesgin_disconnect:	or	SCB_CONTROL,DISCONNECTED;	call	add_scb_to_disc_list;	jmp	await_busfree;/* * Save data pointers message: * Copying RAM values back to SCB, for Save Data Pointers message, but * only if we've actually been into a data phase to change them.  This * protects against bogus data in scratch ram and the residual counts * since they are only initialized when we go into data_in or data_out. */mesgin_sdptrs:	test	SEQ_FLAGS, DPHASE	jz mesgin_done;	mov	SCB_SGCOUNT,SG_COUNT;	/* The SCB SGPTR becomes the next one we'll download */	mvi	DINDEX, SCB_SGPTR;	mvi	SG_NEXT	call bcopy_4;		/* The SCB DATAPTR0 becomes the current SHADDR */	mvi	DINDEX, SCB_DATAPTR;	mvi	SHADDR		call bcopy_4;/* * Use the residual number since STCNT is corrupted by any message transfer. */	mvi	SCB_RESID_DCNT	call	bcopy_3;	jmp	mesgin_done;/* * Restore pointers message?  Data pointers are recopied from the * SCB anytime we enter a data phase for the first time, so all * we need to do is clear the DPHASE flag and let the data phase * code do the rest. */mesgin_rdptrs:	and	SEQ_FLAGS, ~DPHASE;		/*						 * We'll reload them						 * the next time through						 * the dataphase.						 */	jmp	mesgin_done;/* * Identify message?  For a reconnecting target, this tells us the lun * that the reconnection is for - find the correct SCB and switch to it, * clearing the "disconnected" bit so we don't "find" it by accident later. */mesgin_identify:		if ((p->features & AHC_WIDE) != 0) {		and	A,0x0f;		/* lun in lower four bits */	} else {		and	A,0x07;		/* lun in lower three bits */	}	or      SAVED_TCL,A;		/* SAVED_TCL should be complete now */	call	get_untagged_SCBID;	cmp	ARG_1, SCB_LIST_NULL	je snoop_tag;	if ((p->flags & AHC_PAGESCBS) != 0) {		test	SEQ_FLAGS, SCBPTR_VALID	jz use_retrieveSCB;	}	/*	 * If the SCB was found in the disconnected list (as is	 * always the case in non-paging scenarios), SCBPTR is already	 * set to the correct SCB.  So, simply setup the SCB and get	 * on with things.	 */	mov	SCBPTR	call rem_scb_from_disc_list;	jmp	setup_SCB;/* * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message. * If we get one, we use the tag returned to find the proper * SCB.  With SCB paging, this requires using search 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. */snoop_tag:	mov	NONE,SCSIDATL;		/* ACK Identify MSG */snoop_tag_loop:	call	phase_lock;	cmp	LASTPHASE, P_MESGIN	jne not_found;	cmp	SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found;get_tag:	mvi	ARG_1	call inb_next;	/* tag value */	if ((p->flags & AHC_PAGESCBS) == 0) {index_by_tag:		mov	SCBPTR,ARG_1;		test	SCB_CONTROL,TAG_ENB	jz  not_found;		mov	SCBPTR	call rem_scb_from_disc_list;	} else {

⌨️ 快捷键说明

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