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

📄 aic79xx.seq

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 SEQ
📖 第 1 页 / 共 4 页
字号:
	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 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|NO_CDB_SENT	jz . + 3;	mvi	SEQINTCODE, PROTO_VIOLATION;	jmp	mesgin_done;	/*	 * If the target never gave us status information, have	 * the host abort the command.	 */	test	SCB_CONTROL, STATUS_RCVD jz . - 2;	/*	 * See if we attempted to deliver a message but the target ingnored us.	 */	test	SCB_CONTROL, MK_MESSAGE jz . + 2;	mvi	SEQINTCODE, MKMSG_FAILED;	call	queue_scb_completion;	jmp	await_busfree;freeze_queue:	/* Cancel any pending select-out. */	test	SSTAT0, SELDO 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:	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	jz disconnect_allowed;	mvi	SEQINTCODE, PROTO_VIOLATION;	jmp	mesgin_done;disconnect_allowed:	or	SCB_CONTROL,DISCONNECTED;	test	SCB_CONTROL, TAG_ENB jz queue_disc_scb;	mov	A, SCB_NONPACKET_TAG;	cmp	SCBPTR, A je await_busfree;queue_disc_scb:	bmov	REG0, SCBPTR, 2;	shr	SINDEX, 4, SCB_SCSIID;	INDEX_DISC_LIST(SINDEX, SCB_LUN);	bmov	DINDEX, SINDEX, 2;	bmov	REG1, SINDIR, 2;	bmov	DINDIR, REG0, 2;	bmov	SCBPTR, REG0, 2;	bmov	SCB_NEXT, REG1, 2;	/* FALLTHROUGH */await_busfree:	and	SIMODE1, ~ENBUSFREE;	mov	NONE, SCSIDAT;		/* Ack the last byte */	call	clear_target_state;	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:	test	SSTAT1,REQINIT|BUSFREE	jz .;	test	SSTAT1, BUSFREE jnz idle_loop;	mvi	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.  For chips without S/G pipelining, * we can only ack the message after SHADDR has been saved.  On these * chips, SHADDR increments with every bus transaction, even PIO. */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 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;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 .;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 .;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 return;	clr	SG_STATE;disable_ccsgen_fetch_done:	clr	CCSGCTL ret;toggle_dff_mode:	mvi	SEQINTCTL, INTVEC1DSL;	xor	MODE_PTR, MK_MODE(M_DFF1, M_DFF1);	clr	SEQINTCTL ret;data_group_idle_loop:	mov	SAVED_MODE, MODE_PTR;	test	SG_STATE, LOADING_NEEDED jz . + 2;	call	service_fifo;	call	toggle_dff_mode;	test	SG_STATE, LOADING_NEEDED jz . + 2;	call	service_fifo;	call	idle_loop_cchan;	mov	SAVED_MODE jmp set_mode_work_around;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? */	cmp	CCSGCTL, CCSGEN|SG_CACHE_AVAIL|CCSGDONE		je idle_sgfetch_complete;	/* Are we actively fetching segments? */	test	CCSGCTL, CCSGEN 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.	 */	mvi	SGHCNT, SG_PREFETCH_CNT;	and	SGHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR;	bmov	SGHADDR[1], SCB_RESIDUAL_SGPTR[1], 3;	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;	call	disable_ccsgen_fetch_done;	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.	 */	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	REG0, ~SG_FULL_RESID, SCB_SGPTR[0];	test	SCB_DATACNT[3], SG_LAST_SEG jz . + 2;	or	REG0, LAST_SEG;	test	DATA_COUNT_ODD, 0x1 jz . + 2;	or	REG0, ODD_SEG;	mov	SG_CACHE_PRE, REG0;	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:	test	SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT	jz p_data_allowed;	mvi	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;	mvi	SEQINTCODE, PDATA_REINIT;p_data_bitbucket:	/*	 * Turn on `Bit Bucket' mode, wait until the target takes	 * us to another phase, and then notify the host.	 */	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;	test	SCSIPHASE, DATA_PHASE_MASK jnz .;	and	SXFRCTL1, ~BITBUCKET;	SET_MODE(M_DFF1, M_DFF1);	mvi	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;data_group_dma_loop:	/*	 * The transfer is complete if either the last segment	 * completes or the target changes phase.  Both conditions	 * will clear SCSIEN.  We test SCSIEN twice during our	 * "idle loop" to avoid long delays before we notice the	 * SCSIEN transition.	 */	call	data_group_idle_loop;	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

⌨️ 快捷键说明

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