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

📄 aic79xx.seq

📁 linux 内核源代码
💻 SEQ
📖 第 1 页 / 共 5 页
字号:
	 * Ensure that any FIFO contents are cleared out and the	 * FIFO free'd prior to starting the BITBUCKET.  BITBUCKET	 * doesn't discard data already in the FIFO.	 */	mvi	DFFSXFRCTL, RSTCHN|CLRSHCNT;	SET_MODE(M_SCSI, M_SCSI)bitbucket_not_m_dff:	or	SXFRCTL1,BITBUCKET;	/* Wait for non-data phase. */	test	SCSIPHASE, ~DATA_PHASE_MASK jz .;	and	SXFRCTL1, ~BITBUCKET;	RESTORE_MODE(SAVED_MODE)SET_SRC_MODE	M_DFF1;SET_DST_MODE	M_DFF1;	SET_SEQINTCODE(DATA_OVERRUN)	jmp	ITloop;data_phase_initialize:	test	SCB_SGPTR[0], SG_LIST_NULL jnz p_data_bitbucket;	call	load_first_seg;data_phase_inbounds:	/* We have seen a data phase at least once. */	or	SEQ_FLAGS, DPHASE;	mov	SAVED_MODE, MODE_PTR;	test	SG_STATE, LOADING_NEEDED jz data_group_dma_loop;	call	p_data_handle_xfer;data_group_dma_loop:	/*	 * The transfer is complete if either the last segment	 * completes or the target changes phase.  Both conditions	 * will clear SCSIEN.	 */	call	idle_loop_service_fifos;	call	idle_loop_cchan;	call	idle_loop_gsfifo;	RESTORE_MODE(SAVED_MODE)	test	DFCNTRL, SCSIEN jnz data_group_dma_loop;data_group_dmafinish:	/*	 * The transfer has terminated either due to a phase	 * change, and/or the completion of the last segment.	 * We have two goals here.  Do as much other work	 * as possible while the data fifo drains on a read	 * and respond as quickly as possible to the standard	 * messages (save data pointers/disconnect and command	 * complete) that usually follow a data phase.	 */	call	calc_residual;	/*	 * Go ahead and shut down the DMA engine now.	 */	test	DFCNTRL, DIRECTION jnz data_phase_finish;data_group_fifoflush:	if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) {		or	DFCNTRL, FIFOFLUSH;	}	/*	 * We have enabled the auto-ack feature.  This means	 * that the controller may have already transferred	 * some overrun bytes into the data FIFO and acked them	 * on the bus.  The only way to detect this situation is	 * to wait for LAST_SEG_DONE to come true on a completed	 * transfer and then test to see if the data FIFO is	 * non-empty.  We know there is more data yet to transfer	 * if SG_LIST_NULL is not yet set, thus there cannot be	 * an overrun.	 */	test	SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz data_phase_finish;	test	SG_CACHE_SHADOW, LAST_SEG_DONE jz .;	test	DFSTATUS, FIFOEMP jnz data_phase_finish;	/* Overrun */	jmp	p_data;data_phase_finish:	/*	 * If the target has left us in data phase, loop through	 * the dma code again.  We will only loop if there is a	 * data overrun.  	 */	if ((ahd->flags & AHD_TARGETROLE) != 0) {		test	SSTAT0, TARGET jnz data_phase_done;	}	if ((ahd->flags & AHD_INITIATORROLE) != 0) {		test	SSTAT1, REQINIT jz .;		test	SCSIPHASE, DATA_PHASE_MASK jnz p_data;	}data_phase_done:	/* Kill off any pending prefetch */	call	disable_ccsgen;	or 	LONGJMP_ADDR[1], INVALID_ADDR;	if ((ahd->flags & AHD_TARGETROLE) != 0) {		test	SEQ_FLAGS, DPHASE_PENDING jz ITloop;		/*		and	SEQ_FLAGS, ~DPHASE_PENDING;		 * For data-in phases, wait for any pending acks from the		 * initiator before changing phase.  We only need to		 * send Ignore Wide Residue messages for data-in phases.		test	DFCNTRL, DIRECTION jz target_ITloop;		test	SSTAT1, REQINIT	jnz .;		test	SCB_TASK_ATTRIBUTE, SCB_XFERLEN_ODD jz target_ITloop;		SET_MODE(M_SCSI, M_SCSI)		test	NEGCONOPTS, WIDEXFER jz target_ITloop;		 */		/*		 * Issue an Ignore Wide Residue Message.		mvi	P_MESGIN|BSYO call change_phase;		mvi	MSG_IGN_WIDE_RESIDUE call target_outb;		mvi	1 call target_outb;		jmp	target_ITloop;		 */	} else {		jmp	ITloop;	}/* * We assume that, even though data may still be * transferring to the host, that the SCSI side of * the DMA engine is now in a static state.  This * allows us to update our notion of where we are * in this transfer. * * If, by chance, we stopped before being able * to fetch additional segments for this transfer, * yet the last S/G was completely exhausted, * call our idle loop until it is able to load * another segment.  This will allow us to immediately * pickup on the next segment on the next data phase. * * If we happened to stop on the last segment, then * our residual information is still correct from * the idle loop and there is no need to perform * any fixups. */residual_before_last_seg:	test    MDFFSTAT, SHVALID	jnz sgptr_fixup;	/*	 * Can never happen from an interrupt as the packetized	 * hardware will only interrupt us once SHVALID or	 * LAST_SEG_DONE.	 */	call	idle_loop_service_fifos;	RESTORE_MODE(SAVED_MODE)	/* FALLTHROUGH */calc_residual:	test	SG_CACHE_SHADOW, LAST_SEG jz residual_before_last_seg;	/* Record if we've consumed all S/G entries */	test	MDFFSTAT, SHVALID	jz . + 2;	bmov	SCB_RESIDUAL_DATACNT, SHCNT, 3 ret;	or	SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL ret;sgptr_fixup:	/*	 * Fixup the residual next S/G pointer.  The S/G preload	 * feature of the chip allows us to load two elements	 * in addition to the currently active element.  We	 * store the bottom byte of the next S/G pointer in	 * the SG_CACHE_PTR register so we can restore the	 * correct value when the DMA completes.  If the next	 * sg ptr value has advanced to the point where higher	 * bytes in the address have been affected, fix them	 * too.	 */	test	SG_CACHE_SHADOW, 0x80 jz sgptr_fixup_done;	test	SCB_RESIDUAL_SGPTR[0], 0x80 jnz sgptr_fixup_done;	add	SCB_RESIDUAL_SGPTR[1], -1;	adc	SCB_RESIDUAL_SGPTR[2], -1; 	adc	SCB_RESIDUAL_SGPTR[3], -1;sgptr_fixup_done:	and	SCB_RESIDUAL_SGPTR[0], SG_ADDR_MASK, SG_CACHE_SHADOW;	clr	SCB_RESIDUAL_DATACNT[3]; /* We are not the last seg */	bmov	SCB_RESIDUAL_DATACNT, SHCNT, 3 ret;export timer_isr:	call	issue_cmdcmplt;	mvi	CLRSEQINTSTAT, CLRSEQ_SWTMRTO;	if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) {		/*		 * In H2A4, the mode pointer is not saved		 * for intvec2, but is restored on iret.		 * This can lead to the restoration of a		 * bogus mode ptr.  Manually clear the		 * intmask bits and do a normal return		 * to compensate.		 */		and	SEQINTCTL, ~(INTMASK2|INTMASK1) ret;	} else {		or	SEQINTCTL, IRET ret;	}export seq_isr:	if ((ahd->features & AHD_RTI) == 0) {		/*		 * On RevA Silicon, if the target returns us to data-out		 * after we have already trained for data-out, it is		 * possible for us to transition the free running clock to		 * data-valid before the required 100ns P1 setup time (8 P1		 * assertions in fast-160 mode).  This will only happen if		 * this L-Q is a continuation of a data transfer for which		 * we have already prefetched data into our FIFO (LQ/Data		 * followed by LQ/Data for the same write transaction).		 * This can cause some target implementations to miss the		 * first few data transfers on the bus.  We detect this		 * situation by noticing that this is the first data transfer		 * after an LQ (LQIWORKONLQ true), that the data transfer is		 * a continuation of a transfer already setup in our FIFO		 * (SAVEPTRS interrupt), and that the transaction is a write		 * (DIRECTION set in DFCNTRL). The delay is performed by		 * disabling SCSIEN until we see the first REQ from the		 * target.		 * 		 * First instruction in an ISR cannot be a branch on		 * Rev A.  Snapshot LQISTAT2 so the status is not missed		 * and deffer the test by one instruction.		 */		mov	REG_ISR, LQISTAT2;		test	REG_ISR, LQIWORKONLQ jz main_isr;		test	SEQINTSRC, SAVEPTRS  jz main_isr;		test	LONGJMP_ADDR[1], INVALID_ADDR jz saveptr_active_fifo;		/*		 * Switch to the active FIFO after clearing the snapshot		 * savepointer in the current FIFO.  We do this so that		 * a pending CTXTDONE or SAVEPTR is visible in the active		 * FIFO.  This status is the only way we can detect if we		 * have lost the race (e.g. host paused us) and our attempts		 * to disable the channel occurred after all REQs were		 * already seen and acked (REQINIT never comes true).		 */		mvi	DFFSXFRCTL, CLRCHN;		xor	MODE_PTR, MK_MODE(M_DFF1, M_DFF1);		test	DFCNTRL, DIRECTION jz interrupt_return;		and	DFCNTRL, ~SCSIEN;snapshot_wait_data_valid:		test	SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return;		test	SSTAT1, REQINIT	jz snapshot_wait_data_valid;snapshot_data_valid:		or	DFCNTRL, SCSIEN;		or	SEQINTCTL, IRET ret;snapshot_saveptr:		mvi	DFFSXFRCTL, CLRCHN;		or	SEQINTCTL, IRET ret;main_isr:	}	test	SEQINTSRC, CFG4DATA	jnz cfg4data_intr;	test	SEQINTSRC, CFG4ISTAT	jnz cfg4istat_intr;	test	SEQINTSRC, SAVEPTRS	jnz saveptr_intr;	test	SEQINTSRC, CFG4ICMD	jnz cfg4icmd_intr;	SET_SEQINTCODE(INVALID_SEQINT)/* * There are two types of save pointers interrupts: * The first is a snapshot save pointers where the current FIFO is not * active and contains a snapshot of the current poniter information. * This happens between packets in a stream for a single L_Q.  Since we * are not performing a pointer save, we can safely clear the channel * so it can be used for other transactions.  On RTI capable controllers, * where snapshots can, and are, disabled, the code to handle this type * of snapshot is not active. * * The second case is a save pointers on an active FIFO which occurs * if the target changes to a new L_Q or busfrees/QASes and the transfer * has a residual.  This should occur coincident with a ctxtdone.  We * disable the interrupt and allow our active routine to handle the * save. */saveptr_intr:	if ((ahd->features & AHD_RTI) == 0) {		test	LONGJMP_ADDR[1], INVALID_ADDR jnz snapshot_saveptr;	}saveptr_active_fifo:	and	SEQIMODE, ~ENSAVEPTRS;	or	SEQINTCTL, IRET ret;cfg4data_intr:	test	SCB_SGPTR[0], SG_LIST_NULL jnz pkt_handle_overrun_inc_use_count;	call	load_first_seg;	call	pkt_handle_xfer;	inc	SCB_FIFO_USE_COUNT;interrupt_return:	or	SEQINTCTL, IRET ret;cfg4istat_intr:	call	freeze_queue;	add	NONE, -13, SCB_CDB_LEN;	jnc	cfg4istat_have_sense_addr;	test	SCB_CDB_LEN, SCB_CDB_LEN_PTR jnz cfg4istat_have_sense_addr;	/*	 * Host sets up address/count and enables transfer.	 */	SET_SEQINTCODE(CFG4ISTAT_INTR)	jmp	cfg4istat_setup_handler;cfg4istat_have_sense_addr:	bmov	HADDR, SCB_SENSE_BUSADDR, 4;	mvi	HCNT[1], (AHD_SENSE_BUFSIZE >> 8);	mvi	SG_CACHE_PRE, LAST_SEG;	mvi	DFCNTRL, PRELOADEN|SCSIEN|HDMAEN;cfg4istat_setup_handler:	/*	 * Status pkt is transferring to host.	 * Wait in idle loop for transfer to complete.	 * If a command completed before an attempted	 * task management function completed, notify the host.	 */	test	SCB_TASK_MANAGEMENT, 0xFF jz cfg4istat_no_taskmgmt_func;	SET_SEQINTCODE(TASKMGMT_CMD_CMPLT_OKAY)cfg4istat_no_taskmgmt_func:	call	pkt_handle_status;	or	SEQINTCTL, IRET ret;cfg4icmd_intr:	/*	 * In the case of DMAing a CDB from the host, the normal	 * CDB buffer is formatted with an 8 byte address followed	 * by a 1 byte count.	 */	bmov	HADDR[0], SCB_HOST_CDB_PTR, 9;	mvi	SG_CACHE_PRE, LAST_SEG;	mvi	DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN);	call	pkt_handle_cdb;	or	SEQINTCTL, IRET ret;/* * See if the target has gone on in this context creating an * overrun condition.  For the write case, the hardware cannot * ack bytes until data are provided.  So, if the target begins * another  packet without changing contexts, implying we are * not sitting on a packet boundary, we are in an overrun * situation.  For the read case, the hardware will continue to * ack bytes into the FIFO, and may even ack the last overrun packet * into the FIFO.   If the FIFO should become non-empty, we are in * a read overrun case. */#define check_overrun							\	/* Not on a packet boundary. */					\	test 	MDFFSTAT, DLZERO jz pkt_handle_overrun;			\	test	DFSTATUS, FIFOEMP jz pkt_handle_overrunpkt_handle_xfer:	test	SG_STATE, LOADING_NEEDED jz pkt_last_seg;	call	setjmp;	test	SEQINTSRC, SAVEPTRS jnz pkt_saveptrs;	test	SCSIPHASE, ~DATA_PHASE_MASK jz . + 2;	test	SCSISIGO, ATNO jnz . + 2;	test	SSTAT2, NONPACKREQ jz pkt_service_fifo;	/*	 * Defer handling of this NONPACKREQ until we	 * can be sure it pertains to this FIFO.  SAVEPTRS	 * will not be asserted if the NONPACKREQ is for us,	 * so we must simulate it if shaddow is valid.  If	 * shaddow is not valid, keep running this FIFO until we	 * have satisfied the transfer by loading segments and	 * waiting for either shaddow valid or last_seg_done.	 */	test	MDFFSTAT, SHVALID jnz pkt_saveptrs;pkt_service_fifo:	test	SG_STATE, LOADING_NEEDED jnz service_fifo;pkt_last_seg:	call	setjmp;	test	SEQINTSRC, SAVEPTRS jnz pkt_saveptrs;	test	SG_CACHE_SHADOW, LAST_SEG_DONE jnz pkt_last_seg_done;	test	SCSIPHASE, ~DATA_PHASE_MASK jz . + 2;	test	SCSISIGO, ATNO jnz . + 2;	test	SSTAT2, NONPACKREQ jz return;	test	MDFFSTAT, SHVALID jz return;	/* FALLTHROUGH *//* * Either a SAVEPTRS interrupt condition is pending for this FIFO * or we have a pending NONPACKREQ for this FIFO.  We differentiate * between the two by capturing the state of the SAVEPTRS interrupt * prior to clearing this status and executing the common code for * these two cases. */pkt_saveptrs:BEGIN_CRITICAL;	if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) {		or	DFCNTRL, FIFOFLUSH;	}	mov	REG0, SEQINTSRC;	call	calc_residual;	call	save_pointers;	mvi	CLRSEQINTSRC, CLRSAVEPTRS;	call	disable_ccsgen;	or	SEQIMODE, ENSAVEPTRS;	test	DFCNTRL, DIRECTION jnz pkt_saveptrs_check_status;	test	DFSTATUS, FIFOEMP jnz pkt_saveptrs_check_status;	/*	 * Keep a handler around for this FIFO until it drains	 * to the host to guarantee that we don't complete the	 * command to the host before the data arrives.	 */pkt_saveptrs_wait_fifoemp:	call	setjmp;	test	DFSTATUS, FIFOEMP jz return;pkt_saveptrs_check_status:	or	LONGJMP_ADDR[1], INVALID_ADDR;	test	REG0, SAVEPTRS jz unexpected_nonpkt_phase;	dec	SCB_FIFO_USE_COUNT;	test	SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;	mvi	DFFSXFRCTL, CLRCHN ret;/* * LAST_SEG_DONE status has been seen in the current FIFO. * This indicates that all of the allowed data for this * command has transferred across the SCSI and host buses. * Check for overrun and see if we can complete this command. */pkt_last_seg_done:	/*	 * Mark tra

⌨️ 快捷键说明

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