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

📄 aic79xx.seq

📁 一个2.4.21版本的嵌入式linux内核
💻 SEQ
📖 第 1 页 / 共 4 页
字号:
	bmov	ALLOCFIFO_SCBPTR, SCBPTR, 2;	call	allocate_fifo;	/* See if the host wants to send a message upon reconnection */	test	SCB_CONTROL, MK_MESSAGE jz mesgin_done;	mvi	HOST_MSG	call mk_mesg;	jmp	mesgin_done;not_found:	SET_SEQINTCODE(NO_MATCH)	jmp	mesgin_done;not_found_ITloop:	SET_SEQINTCODE(NO_MATCH)	jmp	ITloop;/* * We received a "command complete" message.  Put the SCB on the complete * queue and trigger a completion interrupt via the idle loop.  Before doing * so, check to see if there * is a residual or the status byte is something other than STATUS_GOOD (0). * In either of these conditions, we upload the SCB back to the host so it can * process this information.  In the case of a non zero status byte, we  * additionally interrupt the kernel driver synchronously, allowing it to * decide if sense should be retrieved.  If the kernel driver wishes to request * sense, it will fill the kernel SCB with a request sense command, requeue * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting  * RETURN_1 to SEND_SENSE. */mesgin_complete:	/*	 * If ATN is raised, we still want to give the target a message.	 * Perhaps there was a parity error on this last message byte.	 * Either way, the target should take us to message out phase	 * and then attempt to complete the command again.  We should use a	 * critical section here to guard against a timeout triggering	 * for this command and setting ATN while we are still processing	 * the completion.	test	SCSISIGI, ATNI jnz mesgin_done;	 */	/*	 * If we are identified and have successfully sent the CDB,	 * any status will do.  Optimize this fast path.	 */	test	SCB_CONTROL, STATUS_RCVD jz mesgin_proto_violation;	test	SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT jz complete_accepted;	/*	 * If the target never sent an identify message but instead went	 * to mesgin to give an invalid message, let the host abort us.	 */	test	SEQ_FLAGS, NOT_IDENTIFIED jnz mesgin_proto_violation;	/*	 * If we recevied good status but never successfully sent the	 * cdb, abort the command.	 */	test	SCB_SCSI_STATUS,0xff	jnz complete_accepted;	test	SEQ_FLAGS, NO_CDB_SENT jnz mesgin_proto_violation;complete_accepted:	/*	 * See if we attempted to deliver a message but the target ingnored us.	 */	test	SCB_CONTROL, MK_MESSAGE jz complete_nomsg;	SET_SEQINTCODE(MKMSG_FAILED)complete_nomsg:	call	queue_scb_completion;	jmp	await_busfree;freeze_queue:	/* Cancel any pending select-out. */	test	SSTAT0, SELDO|SELINGO jnz . + 2;	and	SCSISEQ0, ~ENSELO;	mov	ACCUM_SAVE, A;	clr	A;	add	QFREEZE_COUNT, 1;	adc	QFREEZE_COUNT[1], A;	or	SEQ_FLAGS2, SELECTOUT_QFROZEN;	mov	A, ACCUM_SAVE ret;queue_arg1_scb_completion:	SET_MODE(M_SCSI, M_SCSI)	bmov	SCBPTR, ARG_1, 2;queue_scb_completion:	if ((ahd->bugs & AHD_ABORT_LQI_BUG) == 0) {		/*		 * Set MK_MESSAGE to trigger an abort should this SCB		 * be referenced by a target even though it is not currently		 * active.		 */		or	SCB_CONTROL, MK_MESSAGE;	}	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:	bmov	SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;	bmov	COMPLETE_SCB_HEAD, SCBPTR, 2 ret;bad_status:	cmp	SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb;	call	freeze_queue;upload_scb:	bmov	SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2;	bmov	COMPLETE_DMA_SCB_HEAD, SCBPTR, 2;	or	SCB_SGPTR, SG_STATUS_VALID ret;/* * 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:	call	clear_target_state;	test	SSTAT1,REQINIT|BUSFREE	jz .;	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;clear_target_state:	mvi	LASTPHASE, P_BUSFREE;	/* clear target specific flags */	mvi	SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret;phase_lock:     	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;	/*	 * 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 instruction between "touches" of SGHADDR.		 */		nop;	}	and	SGHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR;	mvi	CCSGCTL, CCSGEN|SG_CACHE_AVAIL|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;	if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {		bmov	HADDR, CCSGRAM, 8;	} else {		bmov 	HADDR, CCSGRAM, 4;	}	bmov	HCNT, CCSGRAM, 3;	test	HCNT[0], 0x1 jz . + 2;	xor	DATA_COUNT_ODD, 0x1;	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	DATA_COUNT_ODD, 0x1 jz . + 2;	or	SINDEX, ODD_SEG;	test	SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 3;	or	SINDEX, LAST_SEG;	clr	SG_STATE;	mov	SG_CACHE_PRE, SINDEX;	/*	 * Load the segment.  Or in HDMAEN here too	 * just in case HDMAENACK has not come true	 * by the time this segment is loaded.  If	 * HDMAENACK is not true, this or will disable	 * HDMAEN mid-transfer.  We do not want to simply	 * mvi our original settings as SCSIEN automatically	 * de-asserts and we don't want to accidentally	 * re-enable it.	 */	if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {		/*		 * Use SCSIENWRDIS so that SCSIEN is never		 * modified by this operation.		 */		or	DFCNTRL, PRELOADEN|SCSIENWRDIS|HDMAEN;	} 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	DATA_COUNT_ODD, 0x1, SCB_DATACNT[0];	and	REG_ISR, ~SG_FULL_RESID, SCB_SGPTR[0];	test	SCB_DATACNT[3], SG_LAST_SEG jz . + 2;	or	REG_ISR, LAST_SEG;	test	DATA_COUNT_ODD, 0x1 jz . + 2;	or	REG_ISR, ODD_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_setscb;	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;	/*	 * 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

⌨️ 快捷键说明

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