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

📄 aic7xxx.seq

📁 基于组件方式开发操作系统的OSKIT源代码
💻 SEQ
📖 第 1 页 / 共 3 页
字号:
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_CMD_CHAN) != 0) {		if ((p->features & AHC_ULTRA2) != 0) {			bmov	HCNT, ALLONES, 3;		}		bmov	STCNT, ALLONES, 3;	} else {		mvi	STCNT[0], 0xFF;		mvi	STCNT[1], 0xFF;		mvi	STCNT[2], 0xFF;	}data_phase_inbounds:/* If we are the last SG block, tell the hardware. */if ((p->features & AHC_ULTRA2) == 0) {	cmp	SG_COUNT,0x01 jne data_phase_wideodd;	and	DMAPARAMS, ~WIDEODD;}data_phase_wideodd:	if ((p->features & AHC_ULTRA2) != 0) {		mov	SINDEX, ALLONES;		mov	DFCNTRL, DMAPARAMS;		test	SSTAT0, SDONE jnz .;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;		clr	SINDEX;			/* Remember 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;		if ((p->features & AHC_ULTRA2) == 0) {			bmov    STCNT, HCNT, 3;		}	} 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;		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, REQINIT jz .;	test	SSTAT1,PHASEMIS	jz data_phase_loop;	if ((p->features & AHC_ULTRA2) != 0) {		mov	DFCNTRL, DMAPARAMS;		test	SSTAT0, SDONE jnz .;	}data_phase_finish:/* * 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. */	if ((p->features & AHC_ULTRA2) != 0) {		call	ultra2_dmafinish;	}	if ((p->features & AHC_ULTRA2) == 0) {		if ((p->features & AHC_CMD_CHAN) != 0) {			bmov    SCB_RESID_DCNT, STCNT, 3;			mov	SCB_RESID_SGCNT, SG_COUNT;		} else {			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;		}	}	jmp	ITloop;data_phase_overrun:	if ((p->features & AHC_ULTRA2) != 0) {		call	ultra2_dmafinish;	}/* * 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 .;		bmov	SCB_RESID_DCNT, STCNT, 3;		mov	SCB_RESID_SGCNT, SG_COUNT;		or	SXFRCTL0, CLRSTCNT|CLRCHN;		ret;	}/* * Command phase.  Set up the DMA registers and let 'er rip. */p_command:	call	assert;/* * Load HADDR and HCNT. */	if ((p->features & AHC_CMD_CHAN) != 0) {		bmov	HADDR, SCB_CMDPTR, 5;		bmov	HCNT[1], ALLZEROS, 2;		if ((p->features & AHC_ULTRA2) == 0) {			bmov	STCNT, HCNT, 3;		}	} else {		mvi	DINDEX, HADDR;		mvi	SCB_CMDPTR	call bcopy_5;		clr	HCNT[1];		clr	HCNT[2];		call	set_stcnt_from_hcnt;	}	if ((p->features & AHC_ULTRA2) == 0) {		mvi	(SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET) call dma;	} else {		mvi	DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION);		test	SSTAT0, SDONE jnz .;p_command_dma_loop:		test	SSTAT0, DMADONE jnz p_command_ultra2_dma_done;		test	SSTAT1,PHASEMIS	jz p_command_dma_loop;	/* ie. underrun */p_command_ultra2_dma_done:		and     DFCNTRL, ~(SCSIEN|HDMAEN);		test	DFCNTRL, HDMAEN jnz .;		or	SXFRCTL0, CLRSTCNT|CLRCHN;	}	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_retry:	or      SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */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    je p_mesgout_retry;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;	/*	 * The SCB SGPTR becomes the next one we'll download,	 * and the SCB DATAPTR becomes the current SHADDR.	 * Use the residual number since STCNT is corrupted by	 * any message transfer.	 */	if ((p->features & AHC_CMD_CHAN) != 0) {		bmov    SCB_SGCOUNT, SG_COUNT, 5;		bmov    SCB_DATAPTR, SHADDR, 4;		bmov    SCB_DATACNT, SCB_RESID_DCNT, 3;	} else {		mvi	DINDEX, SCB_SGCOUNT;		mvi	SG_COUNT	call bcopy_5;		mvi	DINDEX, SCB_DATAPTR;		mvi	SHADDR		call bcopy_4;		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 */	mvi     ARG_2, SCB_LIST_NULL;   /* SCBID of prev SCB in disc List */	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.	 */

⌨️ 快捷键说明

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