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

📄 aic79xx.seq

📁 一个2.4.21版本的嵌入式linux内核
💻 SEQ
📖 第 1 页 / 共 4 页
字号:
/* * Adaptec U320 device driver firmware for Linux and FreeBSD. * * Copyright (c) 1994-2001 Justin T. Gibbs. * Copyright (c) 2000-2002 Adaptec Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions, and the following disclaimer, *    without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer *    substantially similar to the "NO WARRANTY" disclaimer below *    ("Disclaimer") and any redistribution must be conditioned upon *    including a substantially similar Disclaimer requirement for further *    binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names *    of any contributors may be used to endorse or promote products derived *    from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#78 $"PATCH_ARG_LIST = "struct ahd_softc *ahd"PREFIX = "ahd_"#include "aic79xx.reg"#include "scsi_message.h"restart:if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {	test	SEQINTCODE, 0xFF jz idle_loop;	SET_SEQINTCODE(NO_SEQINT)}idle_loop:	if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {		/*		 * Convert ERROR status into a sequencer		 * interrupt to handle the case of an		 * interrupt collision on the hardware		 * setting of HWERR.		 */		test	ERROR, 0xFF jz no_error_set;		SET_SEQINTCODE(SAW_HWERR)no_error_set:	}	SET_MODE(M_SCSI, M_SCSI)	test	SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus;	test	SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus;	cmp	WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus;	/*	 * ENSELO is cleared by a SELDO, so we must test for SELDO	 * one last time.	 */BEGIN_CRITICAL;	test	SSTAT0, SELDO jnz select_out;END_CRITICAL;	call	start_selection;idle_loop_checkbus:BEGIN_CRITICAL;	test	SSTAT0, SELDO jnz select_out;END_CRITICAL;	test	SSTAT0, SELDI jnz select_in;	test	SCSIPHASE, ~DATA_PHASE_MASK jz idle_loop_check_nonpackreq;	test	SCSISIGO, ATNO jz idle_loop_check_nonpackreq;	call	unexpected_nonpkt_phase_find_ctxt;idle_loop_check_nonpackreq:	test	SSTAT2, NONPACKREQ jz . + 2;	call	unexpected_nonpkt_phase_find_ctxt;	call	idle_loop_gsfifo_in_scsi_mode;	call	idle_loop_service_fifos;	call	idle_loop_cchan;	jmp	idle_loop;BEGIN_CRITICAL;idle_loop_gsfifo:	SET_MODE(M_SCSI, M_SCSI)idle_loop_gsfifo_in_scsi_mode:	test	LQISTAT2, LQIGSAVAIL jz return;	/*	 * We have received good status for this transaction.  There may	 * still be data in our FIFOs draining to the host.  Setup	 * monitoring of the draining process or complete the SCB.	 */good_status_IU_done:	bmov	SCBPTR, GSFIFO, 2;	clr	SCB_SCSI_STATUS;	/*	 * If a command completed before an attempted task management	 * function completed, notify the host after disabling any	 * pending select-outs.	 */	test	SCB_TASK_MANAGEMENT, 0xFF jz gsfifo_complete_normally;	test	SSTAT0, SELDO|SELINGO jnz . + 2;	and	SCSISEQ0, ~ENSELO;	SET_SEQINTCODE(TASKMGMT_CMD_CMPLT_OKAY)gsfifo_complete_normally:	or	SCB_CONTROL, STATUS_RCVD;	/*	 * Since this status did not consume a FIFO, we have to	 * be a bit more dilligent in how we check for FIFOs pertaining	 * to this transaction.  There are three states that a FIFO still	 * transferring data may be in.	 *	 * 1) Configured and draining to the host, with a pending CLRCHN.	 * 2) Configured and draining to the host, no pending CLRCHN.	 * 3) Pending cfg4data, fifo not empty.	 *	 * Cases 1 and 2 can be detected by noticing that a longjmp is	 * active for the FIFO and LONGJMP_SCB matches our SCB.  In this	 * case, we allow the routine servicing the FIFO to complete the SCB.	 * 	 * Case 3 implies either a pending or yet to occur save data	 * pointers for this same context in the other FIFO.  So, if	 * we detect case 2, we will properly defer the post of the SCB	 * and achieve the desired result.  The pending cfg4data will	 * notice that status has been received and complete the SCB.	 */	test	SCB_SGPTR, SG_LIST_NULL jz good_status_check_fifos;	/*	 * All segments have been loaded (or no data transfer), so	 * it is safe to complete the command.  Since this was a	 * cheap command to check for completion, loop to see if	 * more entries can be removed from the GSFIFO.	 */	call	complete;END_CRITICAL;	jmp	idle_loop_gsfifo_in_scsi_mode;BEGIN_CRITICAL;good_status_check_fifos:	clc;	bmov	ARG_1, SCBPTR, 2;	SET_MODE(M_DFF0, M_DFF0)	call	check_fifo;	jc	return;	SET_MODE(M_DFF1, M_DFF1)	call	check_fifo;	jc	return;	SET_MODE(M_SCSI, M_SCSI)	jmp	queue_scb_completion;END_CRITICAL;idle_loop_service_fifos:	SET_MODE(M_DFF0, M_DFF0)	test	LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo;	call	longjmp;idle_loop_next_fifo:	SET_MODE(M_DFF1, M_DFF1)	test	LONGJMP_ADDR[1], INVALID_ADDR jz longjmp;	ret;idle_loop_cchan:	SET_MODE(M_CCHAN, M_CCHAN)	test	QOFF_CTLSTA, HS_MAILBOX_ACT jz	hs_mailbox_empty;	mov	LOCAL_HS_MAILBOX, HS_MAILBOX;	or	QOFF_CTLSTA, HS_MAILBOX_ACT;hs_mailbox_empty:BEGIN_CRITICAL;	test	CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle;	test	CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog;	test	CCSCBCTL, CCSCBDONE jz return;END_CRITICAL;	/* FALLTHROUGH */scbdma_tohost_done:	test	CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone;	/*	 * A complete SCB upload requires no intervention.	 * The SCB is already on the COMPLETE_SCB list	 * and its completion notification will now be	 * handled just like any other SCB.	 */	and	CCSCBCTL, ~(CCARREN|CCSCBEN) ret;fill_qoutfifo_dmadone:	and	CCSCBCTL, ~(CCARREN|CCSCBEN);	call	qoutfifo_updated;	mvi	COMPLETE_SCB_DMAINPROG_HEAD[1], SCB_LIST_NULL;	bmov	QOUTFIFO_NEXT_ADDR, SCBHADDR, 4;	test	QOFF_CTLSTA, SDSCB_ROLLOVR jz return;	bmov	QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4;	xor	QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret;qoutfifo_updated:	/*	 * If there are more commands waiting to be dma'ed	 * to the host, always coaless.  Otherwise honor the	 * host's wishes.	 */	cmp	COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne coaless_by_count;	cmp	COMPLETE_SCB_HEAD[1], SCB_LIST_NULL jne coaless_by_count;	test	LOCAL_HS_MAILBOX, ENINT_COALESS jz issue_cmdcmplt;	/*	 * If we have relatively few commands outstanding, don't	 * bother waiting for another command to complete.	 */	test	CMDS_PENDING[1], 0xFF jnz coaless_by_count;	/* Add -1 so that jnc means <= not just < */	add	A, -1, INT_COALESSING_MINCMDS;	add	NONE, A, CMDS_PENDING;	jnc	issue_cmdcmplt;		/*	 * If coalessing, only coaless up to the limit	 * provided by the host driver.	 */coaless_by_count:	mov	A, INT_COALESSING_MAXCMDS;	add	NONE, A, INT_COALESSING_CMDCOUNT;	jc	issue_cmdcmplt;	/*	 * If the timer is not currently active,	 * fire it up.	 */	test	INTCTL, SWTMINTMASK jz return;	bmov	SWTIMER, INT_COALESSING_TIMER, 2;	mvi	CLRSEQINTSTAT, CLRSEQ_SWTMRTO;	or	INTCTL, SWTMINTEN|SWTIMER_START;	and	INTCTL, ~SWTMINTMASK ret;issue_cmdcmplt:	mvi	INTSTAT, CMDCMPLT;	clr	INT_COALESSING_CMDCOUNT;	or	INTCTL, SWTMINTMASK ret;BEGIN_CRITICAL;fetch_new_scb_inprog:	test	CCSCBCTL, ARRDONE jz return;fetch_new_scb_done:	and	CCSCBCTL, ~(CCARREN|CCSCBEN);	bmov	REG0, SCBPTR, 2;	clr	A;	add	CMDS_PENDING, 1;	adc	CMDS_PENDING[1], A;	/* Update the next SCB address to download. */	bmov	NEXT_QUEUED_SCB_ADDR, SCB_NEXT_SCB_BUSADDR, 4;	mvi	SCB_NEXT[1], SCB_LIST_NULL;	mvi	SCB_NEXT2[1], SCB_LIST_NULL;	/* Increment our position in the QINFIFO. */	mov	NONE, SNSCB_QOFF;	/*	 * SCBs that want to send messages are always	 * queued independently.  This ensures that they	 * are at the head of the SCB list to select out	 * to a target and we will see the MK_MESSAGE flag.	 */	test	SCB_CONTROL, MK_MESSAGE jnz first_new_target_scb;	shr	SINDEX, 3, SCB_SCSIID;	and	SINDEX, ~0x1;	mvi	SINDEX[1], (WAITING_SCB_TAILS >> 8);	bmov	DINDEX, SINDEX, 2;	bmov	SCBPTR, SINDIR, 2;	bmov	DINDIR, REG0, 2;	cmp	SCBPTR[1], SCB_LIST_NULL je first_new_target_scb;	bmov	SCB_NEXT, REG0, 2 ret;first_new_target_scb:	cmp	WAITING_TID_HEAD[1], SCB_LIST_NULL je first_new_scb;	bmov	SCBPTR, WAITING_TID_TAIL, 2;	bmov	SCB_NEXT2, REG0, 2;	bmov	WAITING_TID_TAIL, REG0, 2 ret;first_new_scb:	bmov	WAITING_TID_HEAD, REG0, 2;	bmov	WAITING_TID_TAIL, REG0, 2 ret;END_CRITICAL;scbdma_idle:	/*	 * Give precedence to downloading new SCBs to execute	 * unless select-outs are currently frozen.	 */	test	SEQ_FLAGS2, SELECTOUT_QFROZEN jnz . + 2;BEGIN_CRITICAL;	test	QOFF_CTLSTA, NEW_SCB_AVAIL jnz fetch_new_scb;	cmp	COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne dma_complete_scb;	cmp	COMPLETE_SCB_HEAD[1], SCB_LIST_NULL je return;	/* FALLTHROUGH */fill_qoutfifo:	/*	 * Keep track of the SCBs we are dmaing just	 * in case the DMA fails or is aborted.	 */	mov	A, QOUTFIFO_ENTRY_VALID_TAG;	bmov	COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2;	mvi	CCSCBCTL, CCSCBRESET;	bmov	SCBHADDR, QOUTFIFO_NEXT_ADDR, 4;	bmov	SCBPTR, COMPLETE_SCB_HEAD, 2;fill_qoutfifo_loop:	mov	CCSCBRAM, SCBPTR;	or	CCSCBRAM, A, SCBPTR[1];	mov	NONE, SDSCB_QOFF;	inc	INT_COALESSING_CMDCOUNT;	add	CMDS_PENDING, -1;	adc	CMDS_PENDING[1], -1;	cmp	SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done;	cmp	CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done;	test	QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done;	bmov	SCBPTR, SCB_NEXT_COMPLETE, 2;	jmp	fill_qoutfifo_loop;fill_qoutfifo_done:	mov	SCBHCNT, CCSCBADDR;	mvi	CCSCBCTL, CCSCBEN|CCSCBRESET;	bmov	COMPLETE_SCB_HEAD, SCB_NEXT_COMPLETE, 2;	mvi	SCB_NEXT_COMPLETE[1], SCB_LIST_NULL ret;fetch_new_scb:	bmov	SCBHADDR, NEXT_QUEUED_SCB_ADDR, 4;	mvi	CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET jmp dma_scb;dma_complete_scb:	bmov	SCBPTR, COMPLETE_DMA_SCB_HEAD, 2;	bmov	SCBHADDR, SCB_BUSADDR, 4;	mvi	CCARREN|CCSCBEN|CCSCBRESET call dma_scb;	/*	 * Now that we've started the DMA, push us onto	 * the normal completion queue to have our SCBID	 * posted to the kernel.	 */	bmov	COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;	bmov	SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;	bmov	COMPLETE_SCB_HEAD, SCBPTR, 2 ret;END_CRITICAL;/* * Either post or fetch an SCB from host memory.  The caller * is responsible for polling for transfer completion. * * Prerequisits: Mode == M_CCHAN *		 SINDEX contains CCSCBCTL flags *		 SCBHADDR set to Host SCB address *		 SCBPTR set to SCB src location on "push" operations */SET_SRC_MODE	M_CCHAN;SET_DST_MODE	M_CCHAN;dma_scb:	mvi	SCBHCNT, SCB_TRANSFER_SIZE;	mov	CCSCBCTL, SINDEX ret;BEGIN_CRITICAL;setjmp_setscb:	bmov	LONGJMP_SCB, SCBPTR, 2;setjmp:	bmov	LONGJMP_ADDR, STACK, 2 ret;setjmp_inline:	bmov	LONGJMP_ADDR, STACK, 2;longjmp:	bmov	STACK, LONGJMP_ADDR, 2 ret;END_CRITICAL;/*************************** Chip Bug Work Arounds ****************************//* * Must disable interrupts when setting the mode pointer * register as an interrupt occurring mid update will * fail to store the new mode value for restoration on * an iret. */if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) {set_mode_work_around:	mvi	SEQINTCTL, INTVEC1DSL;	mov	MODE_PTR, SINDEX;	clr	SEQINTCTL ret;toggle_dff_mode_work_around:	mvi	SEQINTCTL, INTVEC1DSL;	xor	MODE_PTR, MK_MODE(M_DFF1, M_DFF1);	clr	SEQINTCTL ret;}if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {set_seqint_work_around:	mov	SEQINTCODE, SINDEX;	mvi	SEQINTCODE, NO_SEQINT ret;}/************************ Packetized LongJmp Routines *************************/SET_SRC_MODE	M_SCSI;SET_DST_MODE	M_SCSI;start_selection: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;/*

⌨️ 快捷键说明

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