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

📄 aic79xx.seq

📁 linux-2.6.15.6
💻 SEQ
📖 第 1 页 / 共 5 页
字号:
BEGIN_CRITICAL;	if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) {		/*		 * Razor #494		 * Rev A hardware fails to update LAST/CURR/NEXTSCB		 * correctly after a packetized selection in several		 * situations:		 *		 * 1) If only one command existed in the queue, the		 *    LAST/CURR/NEXTSCB are unchanged.		 *		 * 2) In a non QAS, protocol allowed phase change,		 *    the queue is shifted 1 too far.  LASTSCB is		 *    the last SCB that was correctly processed.		 * 		 * 3) In the QAS case, if the full list of commands		 *    was successfully sent, NEXTSCB is NULL and neither		 *    CURRSCB nor LASTSCB can be trusted.  We must		 *    manually walk the list counting MAXCMDCNT elements		 *    to find the last SCB that was sent correctly.		 *		 * To simplify the workaround for this bug in SELDO		 * handling, we initialize LASTSCB prior to enabling		 * selection so we can rely on it even for case #1 above.		 */		bmov	LASTSCB, WAITING_TID_HEAD, 2;	}	bmov	CURRSCB, WAITING_TID_HEAD, 2;	bmov	SCBPTR, WAITING_TID_HEAD, 2;	shr	SELOID, 4, SCB_SCSIID;	/*	 * If we want to send a message to the device, ensure	 * we are selecting with atn irregardless of our packetized	 * agreement.  Since SPI4 only allows target reset or PPR	 * messages if this is a packetized connection, the change	 * to our negotiation table entry for this selection will	 * be cleared when the message is acted on.	 */	test	SCB_CONTROL, MK_MESSAGE jz . + 3;	mov	NEGOADDR, SELOID;	or	NEGCONOPTS, ENAUTOATNO;	or	SCSISEQ0, ENSELO ret;END_CRITICAL;/* * Allocate a FIFO for a non-packetized transaction. * In RevA hardware, both FIFOs must be free before we * can allocate a FIFO for a non-packetized transaction. */allocate_fifo_loop:	/*	 * Do whatever work is required to free a FIFO.	 */	call	idle_loop_service_fifos;	SET_MODE(M_SCSI, M_SCSI)allocate_fifo:	if ((ahd->bugs & AHD_NONPACKFIFO_BUG) != 0) {		and	A, FIFO0FREE|FIFO1FREE, DFFSTAT;		cmp	A, FIFO0FREE|FIFO1FREE jne allocate_fifo_loop;	} else {		test	DFFSTAT, FIFO1FREE jnz allocate_fifo1;		test	DFFSTAT, FIFO0FREE jz allocate_fifo_loop;		mvi	DFFSTAT, B_CURRFIFO_0;		SET_MODE(M_DFF0, M_DFF0)		bmov	SCBPTR, ALLOCFIFO_SCBPTR, 2 ret;	}SET_SRC_MODE	M_SCSI;SET_DST_MODE	M_SCSI;allocate_fifo1:	mvi	DFFSTAT, CURRFIFO_1;	SET_MODE(M_DFF1, M_DFF1)	bmov	SCBPTR, ALLOCFIFO_SCBPTR, 2 ret;/* * We have been reselected as an initiator * or selected as a target. */SET_SRC_MODE	M_SCSI;SET_DST_MODE	M_SCSI;select_in:	if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {		/*		 * Test to ensure that the bus has not		 * already gone free prior to clearing		 * any stale busfree status.  This avoids		 * a window whereby a busfree just after		 * a selection could be missed.		 */		test	SCSISIGI, BSYI jz . + 2;		mvi	CLRSINT1,CLRBUSFREE;		or	SIMODE1, ENBUSFREE;	}	or	SXFRCTL0, SPIOEN;	and	SAVED_SCSIID, SELID_MASK, SELID;	and	A, OID, IOWNID;	or	SAVED_SCSIID, A;	mvi	CLRSINT0, CLRSELDI;	jmp	ITloop;/* * We have successfully selected out. * * Clear SELDO. * Dequeue all SCBs sent from the waiting queue * Requeue all SCBs *not* sent to the tail of the waiting queue * Take Razor #494 into account for above. * * In Packetized Mode: *	Return to the idle loop.  Our interrupt handler will take *	care of any incoming L_Qs. * * In Non-Packetize Mode: *	Continue to our normal state machine. */SET_SRC_MODE	M_SCSI;SET_DST_MODE	M_SCSI;select_out:BEGIN_CRITICAL;	/* Clear out all SCBs that have been successfully sent. */	if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) {		/*		 * For packetized, the LQO manager clears ENSELO on		 * the assertion of SELDO.  If we are non-packetized,		 * LASTSCB and CURRSCB are accurate.		 */		test	SCSISEQ0, ENSELO jnz use_lastscb;		/*		 * The update is correct for LQOSTAT1 errors.  All		 * but LQOBUSFREE are handled by kernel interrupts.		 * If we see LQOBUSFREE, return to the idle loop.		 * Once we are out of the select_out critical section,		 * the kernel will cleanup the LQOBUSFREE and we will		 * eventually restart the selection if appropriate.		 */		test	LQOSTAT1, LQOBUSFREE jnz idle_loop;		/*		 * On a phase change oustside of packet boundaries,		 * LASTSCB points to the currently active SCB context		 * on the bus.		 */		test	LQOSTAT2, LQOPHACHGOUTPKT jnz use_lastscb;		/*		 * If the hardware has traversed the whole list, NEXTSCB		 * will be NULL, CURRSCB and LASTSCB cannot be trusted,		 * but MAXCMDCNT is accurate.  If we stop part way through		 * the list or only had one command to issue, NEXTSCB[1] is		 * not NULL and LASTSCB is the last command to go out.		 */		cmp	NEXTSCB[1], SCB_LIST_NULL jne use_lastscb;		/*		 * Brute force walk.		 */		bmov	SCBPTR, WAITING_TID_HEAD, 2;		mvi	SEQINTCTL, INTVEC1DSL;		mvi	MODE_PTR, MK_MODE(M_CFG, M_CFG);		mov	A, MAXCMDCNT;		mvi	MODE_PTR, MK_MODE(M_SCSI, M_SCSI);		clr	SEQINTCTL;find_lastscb_loop:		dec	A;		test	A, 0xFF jz found_last_sent_scb;		bmov	SCBPTR, SCB_NEXT, 2;		jmp	find_lastscb_loop;use_lastscb:		bmov	SCBPTR, LASTSCB, 2;found_last_sent_scb:		bmov	CURRSCB, SCBPTR, 2;curscb_ww_done:	} else {		bmov	SCBPTR, CURRSCB, 2;	}	/*	 * Requeue any SCBs not sent, to the tail of the waiting Q.	 */	cmp	SCB_NEXT[1], SCB_LIST_NULL je select_out_list_done;	/*	 * We know that neither the per-TID list nor the list of	 * TIDs is empty.  Use this knowledge to our advantage.	 */	bmov	REG0, SCB_NEXT, 2;	bmov	SCBPTR, WAITING_TID_TAIL, 2;	bmov	SCB_NEXT2, REG0, 2;	bmov	WAITING_TID_TAIL, REG0, 2;	jmp	select_out_inc_tid_q;select_out_list_done:	/*	 * The whole list made it.  Just clear our TID's tail pointer	 * unless we were queued independently due to our need to	 * send a message.	 */	test	SCB_CONTROL, MK_MESSAGE jnz select_out_inc_tid_q;	shr	DINDEX, 3, SCB_SCSIID;	or	DINDEX, 1;	/* Want only the second byte */	mvi	DINDEX[1], ((WAITING_SCB_TAILS) >> 8);	mvi	DINDIR, SCB_LIST_NULL;select_out_inc_tid_q:	bmov	SCBPTR, WAITING_TID_HEAD, 2;	bmov	WAITING_TID_HEAD, SCB_NEXT2, 2;	cmp	WAITING_TID_HEAD[1], SCB_LIST_NULL jne . + 2;	mvi	WAITING_TID_TAIL[1], SCB_LIST_NULL;	bmov	SCBPTR, CURRSCB, 2;	mvi	CLRSINT0, CLRSELDO;	test	LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_phase;	test	LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_phase;	/*	 * If this is a packetized connection, return to our	 * idle_loop and let our interrupt handler deal with	 * any connection setup/teardown issues.  The only	 * exceptions are the case of MK_MESSAGE and task management	 * SCBs.	 */	if ((ahd->bugs & AHD_LQO_ATNO_BUG) != 0) {		/*		 * In the A, the LQO manager transitions to LQOSTOP0 even if		 * we have selected out with ATN asserted and the target		 * REQs in a non-packet phase.		 */		test 	SCB_CONTROL, MK_MESSAGE jz select_out_no_message;		test	SCSISIGO, ATNO jnz select_out_non_packetized;select_out_no_message:	}	test	LQOSTAT2, LQOSTOP0 jz select_out_non_packetized;	test	SCB_TASK_MANAGEMENT, 0xFF jz idle_loop;	SET_SEQINTCODE(TASKMGMT_FUNC_COMPLETE)	jmp	idle_loop;select_out_non_packetized:	/* Non packetized request. */	and     SCSISEQ0, ~ENSELO;	if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {		/*		 * Test to ensure that the bus has not		 * already gone free prior to clearing		 * any stale busfree status.  This avoids		 * a window whereby a busfree just after		 * a selection could be missed.		 */		test	SCSISIGI, BSYI jz . + 2;		mvi	CLRSINT1,CLRBUSFREE;		or	SIMODE1, ENBUSFREE;	}	mov	SAVED_SCSIID, SCB_SCSIID;	mov	SAVED_LUN, SCB_LUN;	mvi	SEQ_FLAGS, NO_CDB_SENT;END_CRITICAL;	or	SXFRCTL0, SPIOEN;	/*	 * 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;	/*	 * 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.	 */mesgin_phasemis:ITloop:	call	phase_lock;	mov	A, LASTPHASE;	test	A, ~P_DATAIN_DT	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;	SET_SEQINTCODE(BAD_PHASE)	jmp	ITloop;			/* Try reading the bus again. *//* * Command phase.  Set up the DMA registers and let 'er rip. */p_command:	test	SEQ_FLAGS, NOT_IDENTIFIED jz p_command_okay;	SET_SEQINTCODE(PROTO_VIOLATION)p_command_okay:	test	MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1))		jnz p_command_allocate_fifo;	/*	 * Command retry.  Free our current FIFO and	 * re-allocate a FIFO so transfer state is	 * reset.	 */SET_SRC_MODE	M_DFF1;SET_DST_MODE	M_DFF1;	mvi	DFFSXFRCTL, RSTCHN|CLRSHCNT;	SET_MODE(M_SCSI, M_SCSI)p_command_allocate_fifo:	bmov	ALLOCFIFO_SCBPTR, SCBPTR, 2;	call	allocate_fifo;SET_SRC_MODE	M_DFF1;SET_DST_MODE	M_DFF1;	add	NONE, -17, SCB_CDB_LEN;	jnc	p_command_embedded;p_command_from_host:	bmov	HADDR[0], SCB_HOST_CDB_PTR, 9;	mvi	SG_CACHE_PRE, LAST_SEG;	mvi	DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN);	jmp	p_command_xfer;p_command_embedded:	bmov	SHCNT[0], SCB_CDB_LEN,  1;	bmov	DFDAT, SCB_CDB_STORE, 16; 	mvi	DFCNTRL, SCSIEN;p_command_xfer:	and	SEQ_FLAGS, ~NO_CDB_SENT;	if ((ahd->features & AHD_FAST_CDB_DELIVERY) != 0) {		/*		 * To speed up CDB delivery in Rev B, all CDB acks		 * are "released" to the output sync as soon as the		 * command phase starts.  There is only one problem		 * with this approach.  If the target changes phase		 * before all data are sent, we have left over acks		 * that can go out on the bus in a data phase.  Due		 * to other chip contraints, this only happens if		 * the target goes to data-in, but if the acks go		 * out before we can test SDONE, we'll think that		 * the transfer has completed successfully.  Work		 * around this by taking advantage of the 400ns or		 * 800ns dead time between command phase and the REQ		 * of the new phase.  If the transfer has completed		 * successfully, SCSIEN should fall *long* before we		 * see a phase change.  We thus treat any phasemiss		 * that occurs before SCSIEN falls as an incomplete		 * transfer.		 */		test	SSTAT1, PHASEMIS jnz p_command_xfer_failed;		test	DFCNTRL, SCSIEN jnz . - 1;	} else {		test	DFCNTRL, SCSIEN jnz .;	}	/*	 * DMA Channel automatically disabled.	 * Don't allow a data phase if the command	 * was not fully transferred.	 */	test	SSTAT2, SDONE jnz ITloop;p_command_xfer_failed:	or	SEQ_FLAGS, NO_CDB_SENT;	jmp	ITloop;/* * Status phase.  Wait for the data byte to appear, then read it * and store it into the SCB. */SET_SRC_MODE	M_SCSI;SET_DST_MODE	M_SCSI;p_status:	test	SEQ_FLAGS,NOT_IDENTIFIED jnz mesgin_proto_violation;p_status_okay:	mov	SCB_SCSI_STATUS, SCSIDAT;	or	SCB_CONTROL, STATUS_RCVD;	jmp	ITloop;/* * Message out phase.  If MSG_OUT is MSG_IDENTIFYFLAG, build a full * indentify message sequence and send it to the target.  The host may * override this behavior by setting the MK_MESSAGE bit in the SCB * control byte.  This will cause us to interrupt the host and allow * it to handle the message phase completely on its own.  If the bit * associated with this target is set, we will also interrupt the host, * thereby allowing it to send a message on the next selection regardless * of the transaction being sent. *  * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message. * This is done to allow the host 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:	/* Turn on ATN for the retry */	mvi	SCSISIGO, ATNO;p_mesgout:	mov	SINDEX, MSG_OUT;	cmp	SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;	test	SCB_CONTROL,MK_MESSAGE	jnz host_message_loop;p_mesgout_identify:	or	SINDEX, MSG_IDENTIFYFLAG|DISCENB, SCB_LUN;	test	SCB_CONTROL, DISCENB jnz . + 2;	and	SINDEX, ~DISCENB;/* * Send a tag message if TAG_ENB is set in the SCB control block. * Use SCB_NONPACKET_TAG as the tag value. */p_mesgout_tag:	test	SCB_CONTROL,TAG_ENB jz  p_mesgout_onebyte;	mov	SCSIDAT, SINDEX;	/* Send the identify message */	call	phase_lock;	cmp	LASTPHASE, P_MESGOUT	jne p_mesgout_done;	and	SCSIDAT,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL;

⌨️ 快捷键说明

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