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

📄 aic79xx.seq

📁 linux2.6.16版本
💻 SEQ
📖 第 1 页 / 共 5 页
字号:
	test	SCB_FIFO_USE_COUNT, 0xFF jnz return;queue_scb_completion:	test	SCB_SCSI_STATUS,0xff	jnz bad_status;	/*	 * Check for residuals	 */	test	SCB_SGPTR, SG_LIST_NULL jnz complete;	/* No xfer */	test	SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */	test	SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;complete:BEGIN_CRITICAL;	bmov	SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;	bmov	COMPLETE_SCB_HEAD, SCBPTR, 2 ret;END_CRITICAL;bad_status:	cmp	SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb;	call	freeze_queue;upload_scb:	/*	 * Restore SCB TAG since we reuse this field	 * in the sequencer.  We don't want to corrupt	 * it on the host.	 */	bmov	SCB_TAG, SCBPTR, 2;BEGIN_CRITICAL;	or	SCB_SGPTR, SG_STATUS_VALID;	mvi	SCB_NEXT_COMPLETE[1], SCB_LIST_NULL;	cmp	COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne add_dma_scb_tail;	bmov	COMPLETE_DMA_SCB_HEAD, SCBPTR, 2;	bmov	COMPLETE_DMA_SCB_TAIL, SCBPTR, 2 ret;add_dma_scb_tail:	bmov	REG0, SCBPTR, 2;	bmov	SCBPTR, COMPLETE_DMA_SCB_TAIL, 2;	bmov	SCB_NEXT_COMPLETE, REG0, 2;	bmov	COMPLETE_DMA_SCB_TAIL, REG0, 2 ret;END_CRITICAL;/* * Is it a disconnect message?  Set a flag in the SCB to remind us * and await the bus going free.  If this is an untagged transaction * store the SCB id for it in our untagged target table for lookup on * a reselction. */mesgin_disconnect:	/*	 * If ATN is raised, we still want to give the target a message.	 * Perhaps there was a parity error on this last message byte	 * or we want to abort this command.  Either way, the target	 * should take us to message out phase and then attempt to	 * disconnect again.	 * XXX - Wait for more testing.	test	SCSISIGI, ATNI jnz mesgin_done;	 */	test	SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT		jnz mesgin_proto_violation;	or	SCB_CONTROL,DISCONNECTED;	test	SCB_CONTROL, TAG_ENB jnz await_busfree;queue_disc_scb:	bmov	REG0, SCBPTR, 2;	INDEX_DISC_LIST(SAVED_SCSIID, SAVED_LUN);	bmov	DINDEX, SINDEX, 2;	bmov	DINDIR, REG0, 2;	bmov	SCBPTR, REG0, 2;	/* FALLTHROUGH */await_busfree:	and	SIMODE1, ~ENBUSFREE;	if ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0) {		/*		 * In the BUSFREEREV_BUG case, the		 * busfree status was cleared at the		 * beginning of the connection.		 */		mvi	CLRSINT1,CLRBUSFREE;	}	mov	NONE, SCSIDAT;		/* Ack the last byte */	test	MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1))		jnz await_busfree_not_m_dff;SET_SRC_MODE	M_DFF1;SET_DST_MODE	M_DFF1;await_busfree_clrchn:	mvi	DFFSXFRCTL, CLRCHN;await_busfree_not_m_dff:	/* clear target specific flags */	mvi	SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;	test	SSTAT1,REQINIT|BUSFREE	jz .;	/*	 * We only set BUSFREE status once either a new	 * phase has been detected or we are really	 * BUSFREE.  This allows the driver to know	 * that we are active on the bus even though	 * no identified transaction exists should a	 * timeout occur while awaiting busfree.	 */	mvi	LASTPHASE, P_BUSFREE;	test	SSTAT1, BUSFREE jnz idle_loop;	SET_SEQINTCODE(MISSED_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. * Ack the message as soon as possible. */SET_SRC_MODE	M_DFF1;SET_DST_MODE	M_DFF1;mesgin_sdptrs:	mov	NONE,SCSIDAT;		/*dummy read from latch to ACK*/	test	SEQ_FLAGS, DPHASE	jz ITloop;	call	save_pointers;	jmp	ITloop;save_pointers:	/*	 * If we are asked to save our position at the end of the	 * transfer, just mark us at the end rather than perform a	 * full save.	 */	test	SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz save_pointers_full;	or	SCB_SGPTR, SG_LIST_NULL ret;save_pointers_full:	/*	 * The SCB_DATAPTR becomes the current SHADDR.	 * All other information comes directly from our residual	 * state.	 */	bmov	SCB_DATAPTR, SHADDR, 8;	bmov	SCB_DATACNT, SCB_RESIDUAL_DATACNT, 8 ret;/* * 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.  We also reset/reallocate the FIFO to make * sure we have a clean start for the next data or command phase. */mesgin_rdptrs:	and	SEQ_FLAGS, ~DPHASE;	test	MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) jnz msgin_rdptrs_get_fifo;	mvi	DFFSXFRCTL, RSTCHN|CLRSHCNT;	SET_MODE(M_SCSI, M_SCSI)msgin_rdptrs_get_fifo:	call	allocate_fifo;	jmp	mesgin_done;phase_lock:     	if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) {		/*		 * Don't ignore persistent REQ assertions just because		 * they were asserted within the bus settle delay window.		 * This allows us to tolerate devices like the GEM318		 * that violate the SCSI spec.  We are careful not to		 * count REQ while we are waiting for it to fall during		 * an async phase due to our asserted ACK.  Each		 * sequencer instruction takes ~25ns, so the REQ must		 * last at least 100ns in order to be counted as a true		 * REQ.		 */		test	SCSIPHASE, 0xFF jnz phase_locked;		test	SCSISIGI, ACKI jnz phase_lock;		test	SCSISIGI, REQI jz phase_lock;		test	SCSIPHASE, 0xFF jnz phase_locked;		test	SCSISIGI, ACKI jnz phase_lock;		test	SCSISIGI, REQI jz phase_lock;phase_locked:	} else {		test	SCSIPHASE, 0xFF jz .;	}	test	SSTAT1, SCSIPERR jnz phase_lock;phase_lock_latch_phase:	and	LASTPHASE, PHASE_MASK, SCSISIGI ret;/* * Functions to read data in Automatic PIO mode. * * 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,SCSIDAT;		/*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	SCSIPHASE, 0xFF jz .;	test	SSTAT1, SCSIPERR jnz inb_next_wait;inb_next_check_phase:	and	LASTPHASE, PHASE_MASK, SCSISIGI;	cmp	LASTPHASE, P_MESGIN jne mesgin_phasemis;inb_first:	clr	DINDEX[1];	mov	DINDEX,SINDEX;	mov	DINDIR,SCSIBUS	ret;		/*read byte directly from bus*/inb_last:	mov	NONE,SCSIDAT ret;		/*dummy read from latch to ACK*/mk_mesg:	mvi	SCSISIGO, ATNO;	mov	MSG_OUT,SINDEX ret;SET_SRC_MODE	M_DFF1;SET_DST_MODE	M_DFF1;disable_ccsgen:	test	SG_STATE, FETCH_INPROG jz disable_ccsgen_fetch_done;	clr	CCSGCTL;disable_ccsgen_fetch_done:	clr	SG_STATE ret;service_fifo:	/*	 * Do we have any prefetch left???	 */	test	SG_STATE, SEGS_AVAIL jnz idle_sg_avail;	/*	 * Can this FIFO have access to the S/G cache yet?	 */	test	CCSGCTL, SG_CACHE_AVAIL jz return;	/* Did we just finish fetching segs? */	test	CCSGCTL, CCSGDONE jnz idle_sgfetch_complete;	/* Are we actively fetching segments? */	test	CCSGCTL, CCSGENACK jnz return;	/*	 * Should the other FIFO get the S/G cache first?  If	 * both FIFOs have been allocated since we last checked	 * any FIFO, it is important that we service a FIFO	 * that is not actively on the bus first.  This guarantees	 * that a FIFO will be freed to handle snapshot requests for	 * any FIFO that is still on the bus.  Chips with RTI do not	 * perform snapshots, so don't bother with this test there.	 */	if ((ahd->features & AHD_RTI) == 0) {		/*		 * If we're not still receiving SCSI data,		 * it is safe to allocate the S/G cache to		 * this FIFO.		 */		test	DFCNTRL, SCSIEN jz idle_sgfetch_start;		/*		 * Switch to the other FIFO.  Non-RTI chips		 * also have the "set mode" bug, so we must		 * disable interrupts during the switch.		 */		mvi	SEQINTCTL, INTVEC1DSL;		xor	MODE_PTR, MK_MODE(M_DFF1, M_DFF1);		/*		 * If the other FIFO needs loading, then it		 * must not have claimed the S/G cache yet		 * (SG_CACHE_AVAIL would have been cleared in		 * the orginal FIFO mode and we test this above).		 * Return to the idle loop so we can process the		 * FIFO not currently on the bus first.		 */		test	SG_STATE, LOADING_NEEDED jz idle_sgfetch_okay;		clr	SEQINTCTL ret;idle_sgfetch_okay:		xor	MODE_PTR, MK_MODE(M_DFF1, M_DFF1);		clr	SEQINTCTL;	}idle_sgfetch_start:	/*	 * We fetch a "cacheline aligned" and sized amount of data	 * so we don't end up referencing a non-existant page.	 * Cacheline aligned is in quotes because the kernel will	 * set the prefetch amount to a reasonable level if the	 * cacheline size is unknown.	 */	bmov	SGHADDR, SCB_RESIDUAL_SGPTR, 4;	mvi	SGHCNT, SG_PREFETCH_CNT;	if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) {		/*		 * Need two instructions between "touches" of SGHADDR.		 */		nop;	}	and	SGHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR;	mvi	CCSGCTL, CCSGEN|CCSGRESET;	or	SG_STATE, FETCH_INPROG ret;idle_sgfetch_complete:	/*	 * Guard against SG_CACHE_AVAIL activating during sg fetch	 * request in the other FIFO.	 */	test	SG_STATE, FETCH_INPROG jz return;	clr	CCSGCTL;	and	CCSGADDR, SG_PREFETCH_ADDR_MASK, SCB_RESIDUAL_SGPTR;	mvi	SG_STATE, SEGS_AVAIL|LOADING_NEEDED;idle_sg_avail:	/* Does the hardware have space for another SG entry? */	test	DFSTATUS, PRELOAD_AVAIL jz return;	/*	 * On the A, preloading a segment before HDMAENACK	 * comes true can clobber the shaddow address of the	 * first segment in the S/G FIFO.  Wait until it is	 * safe to proceed.	 */	if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0) {		test	DFCNTRL, HDMAENACK jz return;	}	if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {		bmov	HADDR, CCSGRAM, 8;	} else {		bmov 	HADDR, CCSGRAM, 4;	}	bmov	HCNT, CCSGRAM, 3;	bmov	SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1;	if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) {		and	HADDR[4], SG_HIGH_ADDR_BITS, SCB_RESIDUAL_DATACNT[3];	}	if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {		/* Skip 4 bytes of pad. */		add	CCSGADDR, 4;	}sg_advance:	clr	A;			/* add sizeof(struct scatter) */	add	SCB_RESIDUAL_SGPTR[0],SG_SIZEOF;	adc	SCB_RESIDUAL_SGPTR[1],A;	adc	SCB_RESIDUAL_SGPTR[2],A;	adc	SCB_RESIDUAL_SGPTR[3],A;	mov	SINDEX, SCB_RESIDUAL_SGPTR[0];	test	SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 3;	or	SINDEX, LAST_SEG;	clr	SG_STATE;	mov	SG_CACHE_PRE, SINDEX;	if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {		/*		 * Use SCSIENWRDIS so that SCSIEN is never		 * modified by this operation.		 */		or	DFCNTRL, PRELOADEN|HDMAEN|SCSIENWRDIS;	} else {		or	DFCNTRL, PRELOADEN|HDMAEN;	}	/*	 * Do we have another segment in the cache?	 */	add	NONE, SG_PREFETCH_CNT_LIMIT, CCSGADDR;	jnc	return;	and	SG_STATE, ~SEGS_AVAIL ret;/* * Initialize the DMA address and counter from the SCB. */load_first_seg:	bmov	HADDR, SCB_DATAPTR, 11;	and	REG_ISR, ~SG_FULL_RESID, SCB_SGPTR[0];	test	SCB_DATACNT[3], SG_LAST_SEG jz . + 2;	or	REG_ISR, LAST_SEG;	mov	SG_CACHE_PRE, REG_ISR;	mvi	DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN);	/*	 * Since we've are entering a data phase, we will	 * rely on the SCB_RESID* fields.  Initialize the	 * residual and clear the full residual flag.	 */	and	SCB_SGPTR[0], ~SG_FULL_RESID;	bmov	SCB_RESIDUAL_DATACNT[3], SCB_DATACNT[3], 5;	/* If we need more S/G elements, tell the idle loop */	test	SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz . + 2;	mvi	SG_STATE, LOADING_NEEDED ret;	clr	SG_STATE ret;p_data_handle_xfer:	call	setjmp;	test	SG_STATE, LOADING_NEEDED jnz service_fifo;p_data_clear_handler:	or	LONGJMP_ADDR[1], INVALID_ADDR ret;p_data:	test	SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT	jz p_data_allowed;	SET_SEQINTCODE(PROTO_VIOLATION)p_data_allowed: 	test	SEQ_FLAGS, DPHASE	jz data_phase_initialize;	/*	 * If we re-enter the data phase after going through another	 * phase, our transfer location has almost certainly been	 * corrupted by the interveining, non-data, transfers.  Ask	 * the host driver to fix us up based on the transfer residual	 * unless we already know that we should be bitbucketing.	 */	test	SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jnz p_data_bitbucket;	SET_SEQINTCODE(PDATA_REINIT)	jmp	data_phase_inbounds;p_data_bitbucket:	/*	 * Turn on `Bit Bucket' mode, wait until the target takes	 * us to another phase, and then notify the host.	 */	mov	SAVED_MODE, MODE_PTR;	test	MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1))		jnz bitbucket_not_m_dff;	/*

⌨️ 快捷键说明

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