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

📄 aic7xxx.seq

📁 arm平台上的uclinux系统全部源代码
💻 SEQ
📖 第 1 页 / 共 3 页
字号:
		/*		 * Ensure that the SCB the tag points to is for		 * an SCB transaction to the reconnecting target.		 */use_retrieveSCB:		call	retrieveSCB;	}setup_SCB:	mov	A, SAVED_TCL;	cmp	SCB_TCL, A	jne not_found_cleanup_scb;	test	SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb;	and	SCB_CONTROL,~DISCONNECTED;	or	SEQ_FLAGS,IDENTIFY_SEEN;	  /* make note of IDENTIFY */	/* See if the host wants to send a message upon reconnection */	test	SCB_CONTROL, MK_MESSAGE jz mesgin_done;	and	SCB_CONTROL, ~MK_MESSAGE;	mvi	HOST_MSG	call mk_mesg;	jmp	mesgin_done;not_found_cleanup_scb:	test	SCB_CONTROL, DISCONNECTED jz . + 3;	call	add_scb_to_disc_list;	jmp	not_found;	call	add_scb_to_free_list;not_found:	mvi	INTSTAT, NO_MATCH;	mvi	MSG_BUS_DEV_RESET	call mk_mesg;	jmp	mesgin_done;/* * Message reject?  Let the kernel driver handle this.  If we have an  * outstanding WDTR or SDTR negotiation, assume that it's a response from  * the target selecting 8bit or asynchronous transfer, otherwise just ignore  * it since we have no clue what it pertains to. */mesgin_reject:	mvi	INTSTAT, REJECT_MSG;	jmp	mesgin_done;/* * [ ADD MORE MESSAGE HANDLING HERE ] *//* * Locking the driver out, build a one-byte message passed in SINDEX * if there is no active message already.  SINDEX is returned intact. */mk_mesg:	or	SCSISIGO,ATNO,LASTPHASE;/* turn on ATNO */	mov	MSG_OUT,SINDEX ret;/* * Functions to read data in Automatic PIO mode. * * According to Adaptec's documentation, an ACK is not sent on input from * the target until SCSIDATL is read from.  So we wait until SCSIDATL is * latched (the usual way), then read the data byte directly off the bus * using SCSIBUSL.  When we have pulled the ATN line, or we just want to * acknowledge the byte, then we do a dummy read from SCISDATL.  The SCSI * spec guarantees that the target will hold the data byte on the bus until * we send our ACK. * * The assumption here is that these are called in a particular sequence, * and that REQ is already set when inb_first is called.  inb_{first,next} * use the same calling convention as inb. */inb_next:	mov	NONE,SCSIDATL;		/*dummy read from latch to ACK*/inb_next_wait:	/*	 * If there is a parity error, wait for the kernel to	 * see the interrupt and prepare our message response	 * before continuing.	 */	test	SSTAT1, REQINIT	jz inb_next_wait;	test	SSTAT1, SCSIPERR jnz inb_next_wait;	and	LASTPHASE, PHASE_MASK, SCSISIGI;	cmp	LASTPHASE, P_MESGIN jne mesgin_phasemis;inb_first:	mov	DINDEX,SINDEX;	mov	DINDIR,SCSIBUSL	ret;		/*read byte directly from bus*/inb_last:	mov	NONE,SCSIDATL ret;		/*dummy read from latch to ACK*/if ((p->flags & AHC_TARGETMODE) != 0) {	/*	 * Send a byte to an initiator in Automatic PIO mode.	 * SPIOEN must be on prior to calling this routine.	 */target_outb:	mov	SCSIDATL, SINDEX;	test	SSTAT0, SPIORDY	jz .;	ret;}	mesgin_phasemis:/* * We expected to receive another byte, but the target changed phase */	mvi	INTSTAT, MSGIN_PHASEMIS;	jmp	ITloop;/* * DMA data transfer.  HADDR and HCNT must be loaded first, and * SINDEX should contain the value to load DFCNTRL with - 0x3d for * host->scsi, or 0x39 for scsi->host.  The SCSI channel is cleared * during initialization. */dma:	mov	DFCNTRL,SINDEX;dma_loop:	test	SSTAT0,DMADONE	jnz dma_dmadone;	test	SSTAT1,PHASEMIS	jz dma_loop;	/* ie. underrun */dma_phasemis:	test	SSTAT0,SDONE	jnz dma_checkfifo;	mov	SINDEX,ALLZEROS;		/* Notify caller of phasemiss *//* * We will be "done" DMAing when the transfer count goes to zero, or * the target changes the phase (in light of this, it makes sense that * the DMA circuitry doesn't ACK when PHASEMIS is active).  If we are * doing a SCSI->Host transfer, the data FIFO should be flushed auto- * magically on STCNT=0 or a phase change, so just wait for FIFO empty * status. */dma_checkfifo:	test	DFCNTRL,DIRECTION	jnz dma_fifoempty;dma_fifoflush:	test	DFSTATUS,FIFOEMP	jz dma_fifoflush;dma_fifoempty:	/* Don't clobber an inprogress host data transfer */	test	DFSTATUS, MREQPEND	jnz dma_fifoempty;/* * Now shut the DMA enables off and make sure that the DMA enables are  * actually off first lest we get an ILLSADDR. */dma_dmadone:	and	DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);dma_halt:	/*	 * Some revisions of the aic7880 have a problem where, if the	 * data fifo is full, but the PCI input latch is not empty, 	 * HDMAEN cannot be cleared.  The fix used here is to attempt	 * to drain the data fifo until there is space for the input	 * latch to drain and HDMAEN de-asserts.	 */	if ((p->features & AHC_ULTRA2) == 0) {		mov	NONE, DFDAT;	}	test	DFCNTRL, HDMAEN jnz dma_halt;return:	ret;/* * Assert that if we've been reselected, then we've seen an IDENTIFY * message. */assert:	test	SEQ_FLAGS,IDENTIFY_SEEN	jnz return;	/* seen IDENTIFY? */	mvi	INTSTAT,NO_IDENT 	ret;	/* no - tell the kernel *//* * Locate a disconnected SCB either by SAVED_TCL (ARG_1 is SCB_LIST_NULL) * or by the SCBID ARG_1.  The search begins at the SCB index passed in * via SINDEX which is an SCB that must be on the disconnected list.  If * the SCB cannot be found, SINDEX will be SCB_LIST_NULL, otherwise, SCBPTR * is set to the proper SCB. */findSCB:	mov	SCBPTR,SINDEX;			/* Initialize SCBPTR */	cmp	ARG_1, SCB_LIST_NULL	jne findSCB_by_SCBID;	mov	A, SAVED_TCL;	mvi	SCB_TCL	jmp findSCB_loop;	/* &SCB_TCL -> SINDEX */findSCB_by_SCBID:	mov	A, ARG_1;			/* Tag passed in ARG_1 */	mvi	SCB_TAG	jmp findSCB_loop;	/* &SCB_TAG -> SINDEX */findSCB_next:	cmp	SCB_NEXT, SCB_LIST_NULL je notFound;	mov	SCBPTR,SCB_NEXT;	dec	SINDEX;		/* Last comparison moved us too far */findSCB_loop:	cmp	SINDIR, A	jne findSCB_next;	mov	SINDEX, SCBPTR 	ret;notFound:	mvi	SINDEX, SCB_LIST_NULL	ret;/* * Retrieve an SCB by SCBID first searching the disconnected list falling * back to DMA'ing the SCB down from the host.  This routine assumes that * ARG_1 is the SCBID of interrest and that SINDEX is the position in the * disconnected list to start the search from.  If SINDEX is SCB_LIST_NULL, * we go directly to the host for the SCB. */retrieveSCB:	test	SEQ_FLAGS, SCBPTR_VALID	jz retrieve_from_host;	mov	SCBPTR	call findSCB;	/* Continue the search */	cmp	SINDEX, SCB_LIST_NULL	je retrieve_from_host;/* * This routine expects SINDEX to contain the index of the SCB to be * removed and SCBPTR to be pointing to that SCB. */rem_scb_from_disc_list:/* Remove this SCB from the disconnection list */	cmp	SCB_NEXT,SCB_LIST_NULL je unlink_prev;	mov	DINDEX, SCB_PREV;	mov	SCBPTR, SCB_NEXT;	mov	SCB_PREV, DINDEX;	mov	SCBPTR, SINDEX;unlink_prev:	cmp	SCB_PREV,SCB_LIST_NULL	je rHead;/* At the head of the list */	mov	DINDEX, SCB_NEXT;	mov	SCBPTR, SCB_PREV;	mov	SCB_NEXT, DINDEX;	mov	SCBPTR, SINDEX ret;rHead:	mov	DISCONNECTED_SCBH,SCB_NEXT ret;retrieve_from_host:/* * We didn't find it.  Pull an SCB and DMA down the one we want. * We should never get here in the non-paging case. */	mov	ALLZEROS	call	get_free_or_disc_scb;	mvi	DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;	/* Jump instead of call as we want to return anyway */	mov	ARG_1	jmp dma_scb;/* * Determine whether a target is using tagged or non-tagged transactions * by first looking for a matching transaction based on the TCL and if * that fails, looking up this device in the host's untagged SCB array. * The TCL to search for is assumed to be in SAVED_TCL.  The value is * returned in ARG_1 (SCB_LIST_NULL for tagged, SCBID for non-tagged). * The SCBPTR_VALID bit is set in SEQ_FLAGS if we found the information * in an SCB instead of having to go to the host. */get_untagged_SCBID:	cmp	DISCONNECTED_SCBH, SCB_LIST_NULL je get_SCBID_from_host;	mvi	ARG_1, SCB_LIST_NULL;	mov	DISCONNECTED_SCBH call findSCB;	cmp	SINDEX, SCB_LIST_NULL	je get_SCBID_from_host;	or	SEQ_FLAGS, SCBPTR_VALID;/* Was in disconnected list */	test	SCB_CONTROL, TAG_ENB	jnz . + 2;	mov	ARG_1, SCB_TAG	ret;	mvi	ARG_1, SCB_LIST_NULL ret;/* * Fetch a byte from host memory given an index of (A + (256 * SINDEX)) * and a base address of SCBID_ADDR.  The byte is returned in RETURN_2. */fetch_byte:	mov	ARG_2, SINDEX;	if ((p->features & AHC_CMD_CHAN) != 0) {		mvi	DINDEX, CCHADDR;		mvi	SCBID_ADDR call set_1byte_addr;		mvi	CCHCNT, 1;		mvi	CCSGCTL, CCSGEN|CCSGRESET;		test	CCSGCTL, CCSGDONE jz .;		mvi	CCSGCTL, CCSGRESET;		bmov	RETURN_2, CCSGRAM, 1 ret;	} else {		mvi	DINDEX, HADDR;		mvi	SCBID_ADDR call set_1byte_addr;		mvi	HCNT[0], 1;		clr	HCNT[1];		clr	HCNT[2];		mvi	DFCNTRL, HDMAEN|DIRECTION|FIFORESET;		call	dma_finish;		mov	RETURN_2, DFDAT ret;	}/* * Prepare the hardware to post a byte to host memory given an * index of (A + (256 * SINDEX)) and a base address of SCBID_ADDR. */post_byte_setup:	mov	ARG_2, SINDEX;	if ((p->features & AHC_CMD_CHAN) != 0) {		mvi	DINDEX, CCHADDR;		mvi	SCBID_ADDR call	set_1byte_addr;		mvi	CCHCNT, 1;		mvi	CCSCBCTL, CCSCBRESET ret;	} else {		mvi	DINDEX, HADDR;		mvi	SCBID_ADDR call	set_1byte_addr;		mvi	HCNT[0], 1;		clr	HCNT[1];		clr	HCNT[2];		mvi	DFCNTRL, FIFORESET ret;	}post_byte:	if ((p->features & AHC_CMD_CHAN) != 0) {		bmov	CCSCBRAM, SINDEX, 1;		or	CCSCBCTL, CCSCBEN|CCSCBRESET;		test	CCSCBCTL, CCSCBDONE jz .;		clr	CCSCBCTL ret;	} else {		mov	DFDAT, SINDEX;		or	DFCNTRL, HDMAEN|FIFOFLUSH;		jmp	dma_finish;	}get_SCBID_from_host:	mov	A, SAVED_TCL;	mvi	UNTAGGEDSCB_OFFSET call fetch_byte;	mov	RETURN_1,  RETURN_2 ret;phase_lock:     	test	SSTAT1, REQINIT jz phase_lock;	test	SSTAT1, SCSIPERR jnz phase_lock;	and	LASTPHASE, PHASE_MASK, SCSISIGI;	mov	SCSISIGO, LASTPHASE ret;set_stcnt_from_hcnt:	mov	STCNT[0], HCNT[0];	mov	STCNT[1], HCNT[1];	mov	STCNT[2], HCNT[2] ret;bcopy_7:	mov	DINDIR, SINDIR;	mov	DINDIR, SINDIR;bcopy_5:	mov	DINDIR, SINDIR;bcopy_4:	mov	DINDIR, SINDIR;bcopy_3:	mov	DINDIR, SINDIR;	mov	DINDIR, SINDIR;	mov	DINDIR, SINDIR ret;/* * Setup addr assuming that A is an index into * an array of 32byte objects, SINDEX contains * the base address of that array, and DINDEX * contains the base address of the location * to store the indexed address. */set_32byte_addr:	shr	ARG_2, 3, A;	shl	A, 5;/* * Setup addr assuming that A + (ARG_1 * 256) is an * index into an array of 1byte objects, SINDEX contains * the base address of that array, and DINDEX contains * the base address of the location to store the computed * address. */set_1byte_addr:	add	DINDIR, A, SINDIR;	mov	A, ARG_2;	adc	DINDIR, A, SINDIR;	clr	A;	adc	DINDIR, A, SINDIR;	adc	DINDIR, A, SINDIR ret;/* * Either post or fetch and SCB from host memory based on the * DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX. */dma_scb:	mov	A, SINDEX;	if ((p->features & AHC_CMD_CHAN) != 0) {		mvi	DINDEX, CCHADDR;		mvi	HSCB_ADDR call set_32byte_addr;		mov	CCSCBPTR, SCBPTR;		mvi	CCHCNT, 32;		test	DMAPARAMS, DIRECTION jz dma_scb_tohost;		mvi	CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET;		cmp	CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .;		jmp	dma_scb_finish;dma_scb_tohost:		if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {			mvi	CCSCBCTL, CCSCBRESET;			bmov	CCSCBRAM, SCB_CONTROL, 32;			or	CCSCBCTL, CCSCBEN|CCSCBRESET;			test	CCSCBCTL, CCSCBDONE jz .;		} else {			mvi	CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET;			cmp	CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .;		}dma_scb_finish:		clr	CCSCBCTL;		test	CCSCBCTL, CCARREN|CCSCBEN jnz .;		ret;	} else {		mvi	DINDEX, HADDR;		mvi	HSCB_ADDR call set_32byte_addr;		mvi	HCNT[0], 32;		clr	HCNT[1];		clr	HCNT[2];		mov	DFCNTRL, DMAPARAMS;		test	DMAPARAMS, DIRECTION	jnz dma_scb_fromhost;		/* Fill it with the SCB data */copy_scb_tofifo:		mvi	SINDEX, SCB_CONTROL;		add	A, 32, SINDEX;copy_scb_tofifo_loop:		mov	DFDAT,SINDIR;		mov	DFDAT,SINDIR;		mov	DFDAT,SINDIR;		mov	DFDAT,SINDIR;		mov	DFDAT,SINDIR;		mov	DFDAT,SINDIR;		mov	DFDAT,SINDIR;		mov	DFDAT,SINDIR;		cmp	SINDEX, A jne copy_scb_tofifo_loop;		or	DFCNTRL, HDMAEN|FIFOFLUSH;dma_scb_fromhost:		call	dma_finish;		/* If we were putting the SCB, we are done */		test	DMAPARAMS, DIRECTION	jz	return;		mvi	SCB_CONTROL  call dfdat_in_7;		call	dfdat_in_7_continued;		call	dfdat_in_7_continued;		jmp	dfdat_in_7_continued;dfdat_in_7:		mov     DINDEX,SINDEX;dfdat_in_7_continued:		mov	DINDIR,DFDAT;		mov	DINDIR,DFDAT;		mov	DINDIR,DFDAT;		mov	DINDIR,DFDAT;		mov	DINDIR,DFDAT;		mov	DINDIR,DFDAT;		mov	DINDIR,DFDAT ret;	}/* * Wait for DMA from host memory to data FIFO to complete, then disable * DMA and wait for it to acknowledge that it's off. */dma_finish:	test	DFSTATUS,HDONE	jz dma_finish;	/* Turn off DMA */	and	DFCNTRL, ~HDMAEN;	test	DFCNTRL, HDMAEN jnz .;	ret;add_scb_to_free_list:	if ((p->flags & AHC_PAGESCBS) != 0) {		mov	SCB_NEXT, FREE_SCBH;		mov	FREE_SCBH, SCBPTR;	}	mvi	SCB_TAG, SCB_LIST_NULL ret;if ((p->flags & AHC_PAGESCBS) != 0) {get_free_or_disc_scb:	cmp	FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb;	cmp	DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;return_error:	mvi	SINDEX, SCB_LIST_NULL	ret;dequeue_disc_scb:	mov	SCBPTR, DISCONNECTED_SCBH;dma_up_scb:	mvi	DMAPARAMS, FIFORESET;	mov	SCB_TAG		call dma_scb;unlink_disc_scb:	/* jmp instead of call since we want to return anyway */	mov	SCBPTR	jmp rem_scb_from_disc_list;dequeue_free_scb:	mov	SCBPTR, FREE_SCBH;	mov	FREE_SCBH, SCB_NEXT ret;}add_scb_to_disc_list:/* * Link this SCB into the DISCONNECTED list.  This list holds the * candidates for paging out an SCB if one is needed for a new command. * Modifying the disconnected list is a critical(pause dissabled) section. */	mvi	SCB_PREV, SCB_LIST_NULL;	mov	SCB_NEXT, DISCONNECTED_SCBH;	mov	DISCONNECTED_SCBH, SCBPTR;	cmp	SCB_NEXT,SCB_LIST_NULL je return;	mov	SCBPTR,SCB_NEXT;	mov	SCB_PREV,DISCONNECTED_SCBH;	mov	SCBPTR,DISCONNECTED_SCBH ret;

⌨️ 快捷键说明

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