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

📄 aic7xxx.seq

📁 linux-2.6.15.6
💻 SEQ
📖 第 1 页 / 共 4 页
字号:
		mvi	DINDEX, HADDR;		mvi	SCB_DATAPTR	call bcopy_7;		call	set_stcnt_from_hcnt;		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 ((p->features & AHC_ULTRA2) != 0) {		bmov	HCNT, ALLONES, 3;	}	if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {		bmov	STCNT, ALLONES, 3;	}	if ((p->features & AHC_CMD_CHAN) == 0) {		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) {		shl	A, 2, SG_COUNT;		cmp	SG_COUNT,0x01 jne data_phase_wideodd;		or	A, LAST_SEG;	} else {		cmp	SG_COUNT,0x01 jne data_phase_wideodd;		and	DMAPARAMS, ~WIDEODD;	}data_phase_wideodd:	if ((p->features & AHC_ULTRA2) != 0) {			mov	SG_CACHEPTR, A;		mov	DFCNTRL, DMAPARAMS; /* start the operation */		test	SXFRCTL1, BITBUCKET jnz data_phase_overrun;u2_preload_wait:		test	SSTAT1, PHASEMIS jnz u2_phasemis;		test	DFSTATUS, PRELOAD_AVAIL jz u2_preload_wait;	} 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  */sg_advance:	if ((p->features & AHC_ULTRA2) != 0) {		cmp	SG_COUNT, 0x01	je u2_data_phase_finish;	} else {		dec	SG_COUNT;		test	SG_COUNT, 0xff	jz data_phase_finish;	}	if ((p->features & AHC_CMD_CHAN) != 0) {		/*		 * Do we have any prefetch left???		 */		cmp	CCSGADDR, CCSGADDR_MAX jne prefetch_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;prefetch_avail:		bmov 	HADDR, CCSGRAM, 8;		if ((p->features & AHC_ULTRA2) == 0) {			bmov    STCNT, HCNT, 3;		} else {			dec	SG_COUNT;		}	} 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	DINDEX, 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;	if ((p->features & AHC_ULTRA2) != 0) {		jmp	data_phase_loop;	} else {		test    SSTAT1, REQINIT jz .;		test	SSTAT1,PHASEMIS	jz data_phase_loop;	}/* * We've loaded all of our segments into the preload layer.  Now, we simply * have to wait for it to finish or for us to get a phasemis.  And, since * we'll get a phasemis if we do finish, all we really need to do is wait * for a phasemis then check if we did actually complete all the segments. */	if ((p->features & AHC_ULTRA2) != 0) {u2_data_phase_finish:		test	SSTAT1, PHASEMIS jnz u2_phasemis;		test	SG_CACHEPTR, LAST_SEG_DONE jz u2_data_phase_finish;		clr	SG_COUNT;		test	SSTAT1, REQINIT	jz .;		test	SSTAT1, PHASEMIS jz data_phase_loop;u2_phasemis:		call	ultra2_dmafinish;		test	SG_CACHEPTR, LAST_SEG_DONE jnz data_phase_finish;		test	SSTAT2, SHVALID jnz u2_fixup_residual;		mvi	INTSTAT, SEQ_SG_FIXUP;		jmp	data_phase_finish;u2_fixup_residual:		shr	ARG_1, 2, SG_CACHEPTR;u2_phasemis_loop:		and	A, 0x3f, SG_COUNT;		cmp	ARG_1, A je data_phase_finish;/* * Subtract SG_SIZEOF from the SG_NEXT pointer and add 1 to the SG_COUNT */ 		clr	A;		add	SG_NEXT[0], -SG_SIZEOF;		adc	SG_NEXT[1], 0xff;		inc	SG_COUNT;		jmp	u2_phasemis_loop;	}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_CMD_CHAN) != 0) {		bmov    SCB_RESID_DCNT, STCNT, 3;		mov	SCB_RESID_SGCNT, SG_COUNT;		if ((p->features & AHC_ULTRA2) != 0) {			or	SXFRCTL0, CLRSTCNT|CLRCHN;		}	} 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:/* * Turn off BITBUCKET mode and notify the host */	if ((p->features & AHC_ULTRA2) != 0) {/* * Wait for the target to quit transferring data on the SCSI bus */ 		test	SSTAT1, PHASEMIS jz .;		call	ultra2_dmafinish;	}	and	SXFRCTL1, ~BITBUCKET;	mvi	INTSTAT,DATA_OVERRUN;	jmp	ITloop;/* * Actually turn off the DMA hardware, save our current position into the * proper residual variables, wait for the next REQ signal, then jump to * the ITloop.  Jumping to the ITloop ensures that if we happen to get * brought into the data phase again (or are still in it after our last * segment) that we will properly signal an overrun to the kernel. */	if ((p->features & AHC_ULTRA2) != 0) {ultra2_dmafinish:		test	DFCNTRL, DIRECTION jnz ultra2_dmahalt;		and	DFCNTRL, ~SCSIEN;		test	DFCNTRL, SCSIEN jnz .;		if ((p->bugs & AHC_BUG_AUTOFLUSH) != 0) {			or	DFCNTRL, FIFOFLUSH;		}ultra2_dmafifoflush:		if ((p->bugs & AHC_BUG_AUTOFLUSH) != 0) {			/*			 * hardware bug alert!  This needless set of jumps			 * works around a glitch in the silicon.  When the			 * PCI DMA fifo goes empty, but there is still SCSI			 * data to be flushed into the PCI DMA fifo (and from			 * there on into main memory), the FIFOEMP bit will			 * come on between the time when the PCI DMA buffer			 * went empty and the next bit of data is copied from			 * the SCSI fifo into the PCI fifo.  It should only			 * come on when both FIFOs (meaning the entire FIFO			 * chain) are emtpy.  Since it can take up to 4 cycles			 * for new data to be copied from the SCSI fifo into			 * the PCI fifo, testing for FIFOEMP status for 4			 * extra times gives the needed time for any			 * remaining SCSI fifo data to be put in the PCI fifo			 * before we declare it *truly* empty.			 */			test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;			test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;			test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;			test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;		}		test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;		test	DFSTATUS, MREQPEND	jnz .;ultra2_dmahalt:		and     DFCNTRL, ~(HDMAEN|SCSIEN);		test	DFCNTRL, (HDMAEN|SCSIEN) 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_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, SDONE jnz p_command_ultra2_dma_done;		test	SSTAT1,PHASEMIS	jz p_command_dma_loop;	/* ie. underrun */p_command_ultra2_dma_done:		test	SCSISIGI, REQI	jz p_command_ultra2_shutdown;		test	SSTAT1, (PHASEMIS|REQINIT)	jz p_command_ultra2_dma_done;p_command_ultra2_shutdown:		and     DFCNTRL, ~(HDMAEN|SCSIEN);		test	DFCNTRL, (HDMAEN|SCSIEN) 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;

⌨️ 快捷键说明

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