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

📄 aic7xxx.seq

📁 基于组件方式开发操作系统的OSKIT源代码
💻 SEQ
📖 第 1 页 / 共 4 页
字号:
		/*		 * If we are the result of a tagged command, send		 * a simple Q tag and the tag id.		 */		test	SCB_CONTROL, TAG_ENB	jz . + 3;		mvi	MSG_SIMPLE_Q_TAG call target_outb;		mov	SCB_INITIATOR_TAG call target_outb;		mov	INITIATOR_TAG, SCB_INITIATOR_TAG;target_synccmd:		/*		 * Now determine what phases the host wants us		 * to go through.		 */		mov	SEQ_FLAGS, SCB_TARGET_PHASES;		target_ITloop:		/*		 * Start honoring ATN signals now that		 * we properly identified ourselves.		 */		test	SCSISIGI, ATNI			jnz target_mesgout;		test	SEQ_FLAGS, CMDPHASE_PENDING	jnz target_cmdphase;		test	SEQ_FLAGS, DPHASE_PENDING	jnz target_dphase;		test	SEQ_FLAGS, SPHASE_PENDING	jnz target_sphase;		/*		 * No more work to do.  Either disconnect or not depending		 * on the state of NO_DISCONNECT.		 */		test	SEQ_FLAGS, NO_DISCONNECT jz target_disconnect; 		if ((ahc->flags & AHC_PAGESCBS) != 0) {			mov	ALLZEROS	call	get_free_or_disc_scb;		}		mov	RETURN_1, ALLZEROS;		call	complete_target_cmd;		cmp	RETURN_1, CONT_MSG_LOOP jne .;		mvi	DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;		mov	SCB_TAG	 call dma_scb;		jmp	target_synccmd;target_mesgout:		mvi	SCSISIGO, P_MESGOUT|BSYO;		call	target_inb;		/* Local Processing goes here... */target_mesgout_pending_msg:		jmp	host_target_message_loop;		target_disconnect:		mvi	P_MESGIN|BSYO call change_phase;		test	SEQ_FLAGS, DPHASE	jz . + 2;		mvi	MSG_SAVEDATAPOINTER call target_outb;		mvi	MSG_DISCONNECT call target_outb;target_busfree_wait:		/* Wait for preceeding I/O session to complete. */		test	SCSISIGI, ACKI jnz .;target_busfree:		clr	SCSISIGO;		call	complete_target_cmd;		jmp	poll_for_work;target_cmdphase:		mvi	P_COMMAND|BSYO call change_phase;		call	target_inb;		mov	A, DINDEX;		/* Store for host */		if ((ahc->features & AHC_CMD_CHAN) != 0) {			mov	CCSCBRAM, A;		} else {			mov	DFDAT, A;		}		/*		 * Determine the number of bytes to read		 * based on the command group code via table lookup.		 * We reuse the first 8 bytes of the TARG_SCSIRATE		 * BIOS array for this table. Count is one less than		 * the total for the command since we've already fetched		 * the first byte.		 */		shr	A, CMD_GROUP_CODE_SHIFT;		add	SINDEX, TARG_SCSIRATE, A;		mov	A, SINDIR;		test	A, 0xFF jz command_phase_done;command_loop:		or	SXFRCTL0, SPIOEN;		test	SSTAT0, SPIORDY jz .;		cmp	A, 1 jne . + 2;		and	SXFRCTL0, ~SPIOEN;	/* Last Byte */		if ((ahc->features & AHC_CMD_CHAN) != 0) {			mov	CCSCBRAM, SCSIDATL;		} else {			mov	DFDAT, SCSIDATL;		}		dec	A;		test	A, 0xFF jnz command_loop;command_phase_done:		and	SEQ_FLAGS, ~CMDPHASE_PENDING;		jmp	target_ITloop;target_dphase:		/*		 * Data direction flags are from the		 * perspective of the initiator.		 */		test	SCB_TARGET_PHASES[1], TARGET_DATA_IN jz . + 4;		mvi	LASTPHASE, P_DATAOUT;		mvi	P_DATAIN|BSYO call change_phase;		jmp	. + 3;		mvi	LASTPHASE, P_DATAIN;		mvi	P_DATAOUT|BSYO call change_phase;		mov	ALLZEROS call initialize_channel;		jmp	p_data;target_sphase:		mvi	P_STATUS|BSYO call change_phase;		mvi	LASTPHASE, P_STATUS;		mov	SCB_TARGET_STATUS call target_outb;		/* XXX Watch for ATN or parity errors??? */		mvi	SCSISIGO, P_MESGIN|BSYO;		/* MSG_CMDCMPLT is 0, but we can't do an immediate of 0 */		mov	ALLZEROS call target_outb;		jmp	target_busfree_wait;	complete_target_cmd:		test	SEQ_FLAGS, TARG_CMD_PENDING	jnz . + 2;		mov	SCB_TAG jmp complete_post;		if ((ahc->features & AHC_CMD_CHAN) != 0) {			/* Set the valid byte */			mvi	CCSCBADDR, 24;			mov	CCSCBRAM, ALLONES;			mvi	CCHCNT, 28;			or	CCSCBCTL, CCSCBEN|CCSCBRESET;			test	CCSCBCTL, CCSCBDONE jz .;			clr	CCSCBCTL;		} else {			/* Set the valid byte */			or	DFCNTRL, FIFORESET;			mvi	DFWADDR, 3; /* Third 64bit word or byte 24 */			mov	DFDAT, ALLONES;			mvi	HCNT[0], 28;			clr	HCNT[1];			clr	HCNT[2];			or	DFCNTRL, HDMAEN|FIFOFLUSH;			call	dma_finish;		}		inc	TQINPOS;		mvi	INTSTAT,CMDCMPLT ret;	}if ((ahc->flags & AHC_INITIATORMODE) != 0) {initiator_select:	mvi	SPIOEN call	initialize_channel;	/*	 * We aren't expecting a bus free, so interrupt	 * the kernel driver if it happens.	 */	mvi	CLRSINT1,CLRBUSFREE;	or	SIMODE1, ENBUSFREE;	/*	 * 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;	jmp	ITloop;			/* Try reading the bus again. */await_busfree:	and	SIMODE1, ~ENBUSFREE;	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:	/*	 * We assume that the kernel driver may reset us	 * at any time, even in the middle of a DMA, so	 * clear DFCNTRL too.	 */	clr	DFCNTRL;	/*	 * We don't know the target we will connect to,	 * so default to narrow transfers to avoid	 * parity problems.	 */	if ((ahc->features & AHC_ULTRA2) != 0) {		bmov	SCSIRATE, ALLZEROS, 2;	} else {		clr	SCSIRATE;		and	SXFRCTL0, ~(FAST20);	}	mvi	LASTPHASE, P_BUSFREE;	/* clear target specific flags */	clr	SEQ_FLAGS 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:	if ((ahc->features & AHC_CMD_CHAN) != 0) {		bmov	STCNT, SCB_RESID_DCNT, 3;	} else {		mvi	DINDEX, STCNT;		mvi	SCB_RESID_DCNT	call bcopy_3;	}	and	DATA_COUNT_ODD, 0x1, SCB_RESID_DCNT[0];	jmp	data_phase_loop;p_data:	if ((ahc->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 ((ahc->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 ((ahc->features & AHC_CMD_CHAN) != 0) {		bmov	HADDR, SCB_DATAPTR, 7;	} else {		mvi	DINDEX, HADDR;		mvi	SCB_DATAPTR	call bcopy_7;	}	and	DATA_COUNT_ODD, 0x1, SCB_DATACNT[0];	if ((ahc->features & AHC_ULTRA2) == 0) {		if ((ahc->features & AHC_CMD_CHAN) != 0) {			bmov	STCNT, HCNT, 3;		} else {			call	set_stcnt_from_hcnt;		}	}	if ((ahc->features & AHC_CMD_CHAN) != 0) {		bmov	SG_COUNT, SCB_SGCOUNT, 5;	} else {		mvi	DINDEX, SG_COUNT;		mvi	SCB_SGCOUNT	call bcopy_5;	}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 ((ahc->features & AHC_ULTRA2) != 0) {		bmov	HCNT, ALLONES, 3;	} else if ((ahc->features & AHC_CMD_CHAN) != 0) {		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. */	cmp	SG_COUNT,0x01 jne data_phase_wideodd;	if ((ahc->features & AHC_ULTRA2) != 0) {		or	SG_CACHEPTR, LAST_SEG;	} else {		and	DMAPARAMS, ~WIDEODD;	}data_phase_wideodd:	if ((ahc->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 ((ahc->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;	}	/* Track odd'ness */	test	HCNT[0], 0x1 jz . + 2;	xor	DATA_COUNT_ODD, 0x1;	if ((ahc->features & AHC_ULTRA2) == 0) {		/* Load STCNT as well.  It is a mirror of HCNT */		if ((ahc->features & AHC_CMD_CHAN) != 0) {			bmov	STCNT, HCNT, 3;		} else {			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;	if ((ahc->flags & AHC_TARGETMODE) != 0) {		test	SSTAT0, TARGET jnz data_phase_loop;	}	test	SSTAT1, REQINIT jz .;	test	SSTAT1,PHASEMIS	jz data_phase_loop;	/* Ensure the last seg is visable at the shaddow layer */	if ((ahc->features & AHC_ULTRA2) != 0) {		or	DFCNTRL, PRELOADEN;	}data_phase_finish:	if ((ahc->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. */	if ((ahc->features & AHC_CMD_CHAN) != 0) {		bmov	SCB_RESID_DCNT, STCNT, 3;	} 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;	if ((ahc->features & AHC_ULTRA2) != 0) {		or	SXFRCTL0, CLRSTCNT|CLRCHN;	}	if ((ahc->flags & AHC_TARGETMODE) != 0) {		test	SEQ_FLAGS, DPHASE_PENDING jz ITloop;		and	SEQ_FLAGS, ~DPHASE_PENDING;		/*

⌨️ 快捷键说明

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