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

📄 aic79xx_core.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
		lastphase = ahd_inb(ahd, LASTPHASE);		printf("%s:%c:%d: Missed busfree. "		       "Lastphase = 0x%x, Curphase = 0x%x\n",		       ahd_name(ahd), 'A',		       SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),		       lastphase, ahd_inb(ahd, SCSISIGI));		ahd_restart(ahd);		return;	}	case DATA_OVERRUN:	{		/*		 * When the sequencer detects an overrun, it		 * places the controller in "BITBUCKET" mode		 * and allows the target to complete its transfer.		 * Unfortunately, none of the counters get updated		 * when the controller is in this mode, so we have		 * no way of knowing how large the overrun was.		 */		struct	scb *scb;		u_int	scbindex = ahd_get_scbptr(ahd);		u_int	lastphase = ahd_inb(ahd, LASTPHASE);		scb = ahd_lookup_scb(ahd, scbindex);		ahd_print_path(ahd, scb);		printf("data overrun detected %s."		       "  Tag == 0x%x.\n",		       ahd_lookup_phase_entry(lastphase)->phasemsg,  		       SCB_GET_TAG(scb));		ahd_print_path(ahd, scb);		printf("%s seen Data Phase.  Length = %ld.  NumSGs = %d.\n",		       ahd_inb(ahd, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't",		       ahd_get_transfer_length(scb), scb->sg_count);		ahd_dump_sglist(scb);		/*		 * Set this and it will take effect when the		 * target does a command complete.		 */		ahd_freeze_devq(ahd, scb);		ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR);		ahd_freeze_scb(scb);		break;	}	case MKMSG_FAILED:	{		struct ahd_devinfo devinfo;		struct scb *scb;		u_int scbid;		ahd_fetch_devinfo(ahd, &devinfo);		printf("%s:%c:%d:%d: Attempt to issue message failed\n",		       ahd_name(ahd), devinfo.channel, devinfo.target,		       devinfo.lun);		scbid = ahd_get_scbptr(ahd);		scb = ahd_lookup_scb(ahd, scbid);		if (scb != NULL		 && (scb->flags & SCB_RECOVERY_SCB) != 0)			/*			 * Ensure that we didn't put a second instance of this			 * SCB into the QINFIFO.			 */			ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),					   SCB_GET_CHANNEL(ahd, scb),					   SCB_GET_LUN(scb), SCB_GET_TAG(scb),					   ROLE_INITIATOR, /*status*/0,					   SEARCH_REMOVE);		ahd_outb(ahd, SCB_CONTROL,			 ahd_inb(ahd, SCB_CONTROL) & ~MK_MESSAGE);		break;	}	}	/*	 *  The sequencer is paused immediately on	 *  a SEQINT, so we should restart it when	 *  we're done.	 */	ahd_unpause(ahd);}voidahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat){	struct scb	*scb;	u_int		 status0;	u_int		 status3;	u_int		 status;	u_int		 lqistat1;	u_int		 lqostat0;	u_int		 scbid;	ahd_update_modes(ahd);	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);	status3 = ahd_inb(ahd, SSTAT3) & (NTRAMPERR|OSRAMPERR);	status0 = ahd_inb(ahd, SSTAT0) & (IOERR|OVERRUN|SELDI|SELDO);	status = ahd_inb(ahd, SSTAT1) & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR);	lqistat1 = ahd_inb(ahd, LQISTAT1);	lqostat0 = ahd_inb(ahd, LQOSTAT0);	if ((status0 & (SELDI|SELDO)) != 0) {		u_int simode0;		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);		simode0 = ahd_inb(ahd, SIMODE0);		status0 &= simode0 & (ENSELDO|ENSELDI|IOERR);		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);	}	scbid = ahd_get_scbptr(ahd);	scb = ahd_lookup_scb(ahd, scbid);	if (scb != NULL	 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)		scb = NULL;	/* Make sure the sequencer is in a safe location. */	ahd_clear_critical_section(ahd);	if ((status0 & IOERR) != 0) {		int now_lvd;		now_lvd = ahd_inb(ahd, SBLKCTL) & ENAB40;		printf("%s: Transceiver State Has Changed to %s mode\n",		       ahd_name(ahd), now_lvd ? "LVD" : "SE");		ahd_outb(ahd, CLRSINT0, CLRIOERR);/* XXX Still True?? */		/*		 * When transitioning to SE mode, the reset line		 * glitches, triggering an arbitration bug in some		 * Ultra2 controllers.  This bug is cleared when we		 * assert the reset line.  Since a reset glitch has		 * already occurred with this transition and a		 * transceiver state change is handled just like		 * a bus reset anyway, asserting the reset line		 * ourselves is safe.		 */		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/now_lvd == 0);		ahd_pause(ahd);		ahd_setup_iocell_workaround(ahd);		ahd_unpause(ahd);	} else if ((status0 & OVERRUN) != 0) {		printf("%s: SCSI offset overrun detected.  Resetting bus.\n",		       ahd_name(ahd));		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);	} else if ((status & SCSIRSTI) != 0) {		printf("%s: Someone reset channel A\n", ahd_name(ahd));		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);	} else if ((status & SCSIPERR) != 0) {		ahd_handle_transmission_error(ahd);	} else if (lqostat0 != 0) {		printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0);		ahd_outb(ahd, CLRLQOINT0, lqostat0);		if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {			ahd_outb(ahd, CLRLQOINT1, 0);		}	} else if ((status & SELTO) != 0) {		u_int scbid;		/* Stop the selection */		ahd_outb(ahd, SCSISEQ0, 0);		/* No more pending messages */		ahd_clear_msg_state(ahd);		/* Clear interrupt state */		ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~ENBUSFREE);		ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR);		/*		 * Although the driver does not care about the		 * 'Selection in Progress' status bit, the busy		 * LED does.  SELINGO is only cleared by a sucessfull		 * selection, so we must manually clear it to insure		 * the LED turns off just incase no future successful		 * selections occur (e.g. no devices on the bus).		 */		ahd_outb(ahd, CLRSINT0, CLRSELINGO);		scbid = ahd_inw(ahd, WAITING_TID_HEAD);#if AHD_DEBUG		if ((ahd_debug & AHD_SHOW_SELTO) != 0)			printf("%s: Saw Selection Timeout for SCB 0x%x\n",			       ahd_name(ahd), scbid);#endif		scb = ahd_lookup_scb(ahd, scbid);		if (scb == NULL) {			printf("%s: ahd_intr - referenced scb not "			       "valid during SELTO scb(0x%x)\n",			       ahd_name(ahd), scbid);			ahd_dump_card_state(ahd);			panic("For diagnostics");		} else {			ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT);			ahd_freeze_devq(ahd, scb);		}		ahd_outb(ahd, CLRINT, CLRSCSIINT);		ahd_iocell_first_selection(ahd);		ahd_restart(ahd);	} else if ((status0 & (SELDI|SELDO)) != 0) {		ahd_iocell_first_selection(ahd);		ahd_unpause(ahd);	} else if (status3 != 0) {		printf("%s: SCSI Cell parity error SSTAT3 == 0x%x\n",		       ahd_name(ahd), status3);		ahd_outb(ahd, CLRSINT3, status3);	} else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {		ahd_handle_lqiphase_error(ahd, lqistat1);	} else if ((status & BUSFREE) != 0) {		u_int busfreetime;		u_int lqostat1;		int   restart;		int   clear_fifo;		int   packetized;		u_int mode;		/*		 * Clear our selection hardware as soon as possible.		 * We may have an entry in the waiting Q for this target,		 * that is affected by this busfree and we don't want to		 * go about selecting the target while we handle the event.		 */		ahd_outb(ahd, SCSISEQ0, 0);		/*		 * Determine what we were up to at the time of		 * the busfree.		 */		mode = AHD_MODE_SCSI;		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);		busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME;		lqostat1 = ahd_inb(ahd, LQOSTAT1);		switch (busfreetime) {		case BUSFREE_DFF0:		case BUSFREE_DFF1:		{			u_int	scbid;			struct	scb *scb;			mode = busfreetime == BUSFREE_DFF0			     ? AHD_MODE_DFF0 : AHD_MODE_DFF1;			ahd_set_modes(ahd, mode, mode);			scbid = ahd_get_scbptr(ahd);			scb = ahd_lookup_scb(ahd, scbid);			if (scb == NULL) {				printf("%s: Invalid SCB in DFF%d "				       "during unexpected busfree\n",				       ahd_name(ahd), mode);				packetized = 0;			} else				packetized = (scb->flags & SCB_PACKETIZED) != 0;			clear_fifo = 1;			break;		}		case BUSFREE_LQO:			clear_fifo = 0;			packetized = 1;			break;		default:			clear_fifo = 0;			packetized =  (lqostat1 & LQOBUSFREE) != 0;			if (!packetized			 && ahd_inb(ahd, LASTPHASE) == P_BUSFREE)				packetized = 1;			break;		}#if AHD_DEBUG		if ((ahd_debug & AHD_SHOW_MISC) != 0)			printf("Saw Busfree.  Busfreetime = 0x%x.\n",			       busfreetime);#endif		/*		 * Busfrees that occur in non-packetized phases are		 * handled by the nonpkt_busfree handler.		 */		if (packetized && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) {			restart = ahd_handle_pkt_busfree(ahd, busfreetime);		} else {			restart = ahd_handle_nonpkt_busfree(ahd);		}		/*		 * Clear the busfree interrupt status.  The setting of		 * the interrupt is a pulse, so we do not need to muck		 * with the ENBUSFREE logic.  This also ensures that if		 * the bus has moved on to another connection, busfree		 * protection is still in force.		 */		ahd_outb(ahd, CLRSINT1, CLRBUSFREE|CLRSCSIPERR);		if (clear_fifo)			ahd_clear_fifo(ahd, mode);		ahd_clear_msg_state(ahd);		ahd_outb(ahd, CLRINT, CLRSCSIINT);		if (restart)			ahd_restart(ahd);		else {			ahd_unpause(ahd);		}	} else {		printf("%s: Missing case in ahd_handle_scsiint. status = %x\n",		       ahd_name(ahd), status);		printf("%s: lqostat1 == 0x%x, SIMODE1 == 0x%x\n",		       ahd_name(ahd), ahd_inb(ahd, LQOSTAT1),		       ahd_inb(ahd, SIMODE1));		ahd_outb(ahd, CLRINT, CLRSCSIINT);		ahd_dump_card_state(ahd);		panic("Missing SCSIINT case");		ahd_unpause(ahd);	}}static voidahd_handle_transmission_error(struct ahd_softc *ahd){	u_int		 lqistat1;	u_int		 lqistat2;	u_int		 msg_out;	u_int		 curphase;	u_int		 lastphase;	u_int		 perrdiag;	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);	lqistat1 = ahd_inb(ahd, LQISTAT1) & ~(LQIPHASE_LQ|LQIPHASE_NLQ);	lqistat2 = ahd_inb(ahd, LQISTAT2);	if ((lqistat1 & (LQICRCI_NLQ|LQICRCI_LQ)) == 0	 && (ahd->bugs & AHD_NLQICRC_DELAYED_BUG) != 0) {		u_int lqistate;		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);		lqistate = ahd_inb(ahd, LQISTATE);		if ((lqistate >= 0x1E && lqistate <= 0x24)		 || (lqistate == 0x29)) {			printf("%s: NLQCRC found via LQISTATE\n",			       ahd_name(ahd));			lqistat1 |= LQICRCI_NLQ;		}		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);	}	ahd_outb(ahd, CLRLQIINT1, lqistat1);	lastphase = ahd_inb(ahd, LASTPHASE);	curphase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;	perrdiag = ahd_inb(ahd, PERRDIAG);	msg_out = MSG_INITIATOR_DET_ERR;	ahd_outb(ahd, CLRSINT1, CLRSCSIPERR);	printf("%s: Transmission error detected\n", ahd_name(ahd));	printf("%s: lqistat1 == 0x%x, LASTPHASE == 0x0%x, "	       "curphase = 0x%x, perrdiag == 0x%x\n",	       ahd_name(ahd), lqistat1, lastphase, curphase, perrdiag);	ahd_dump_card_state(ahd);	if ((lqistat1 & (LQIOVERI_LQ|LQIOVERI_NLQ)) != 0) {		printf("%s: Gross protocol error during incoming "		       "packet.  lqistat1 == 0x%x.  Resetting bus.\n",		       ahd_name(ahd), lqistat1);		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);		return;	} else if ((lqistat1 & LQICRCI_LQ) != 0) {		/*		 * A CRC error has been detected on an incoming LQ.		 * The bus is currently hung on the last ACK.		 * Hit LQIRETRY to release the last ack, and		 * wait for the sequencer to determine that ATNO		 * is asserted while in message out to take us		 * to our host message loop.  No NONPACKREQ or		 * LQIPHASE type errors will occur in this		 * scenario.  After this first LQIRETRY, the LQI		 * manager will be in ISELO where it will		 * happily sit until another packet phase begins.		 * Unexpected bus free detection is enabled		 * through any phases that occur after we release		 * this last ack until the LQI manager sees a		 * packet phase.  This implies we may have to		 * ignore a perfectly valid "unexected busfree"		 * after our "initiator detected error" message is		 * sent.  A busfree is the expected response after		 * we tell the target that it's L_Q was corrupted.		 * (SPI4R09 10.7.3.3.3)		 */		ahd_outb(ahd, LQCTL2, LQIRETRY);		printf("LQIRetry for LQICRCI_LQ to release ACK\n");	} else if ((lqistat1 & LQICRCI_NLQ) != 0) {		u_int scbid;		struct scb *scb;		/*		 * We detected a CRC error in a NON-LQ packet.		 * The hardware has varying behavior in this situation		 * depending on whether this packet was part of a		 * stream or not.		 *		 * PKT by PKT mode:		 * The hardware has already acked the complete packet.		 * If the target honors our outstanding ATN condition,		 * we should be (or soon will be) in MSGOUT phase.		 * This will trigger the LQIPHASE_LQ status bit as the		 * hardware was expecting another LQ.  Unexpected		 * busfree detection is enabled.  Once LQIPHASE_LQ is		 * true (first entry into host message loop is much		 * the same), we must clear LQIPHASE_LQ and hit		 * LQIRETRY so the hardware is ready to handle		 * a future LQ.  NONPACKREQ will not be asserted again		 * once we hit LQIRETRY until another packet is		 * processed.  The target may either go busfree		 * or start another packet in response to our message.		 *		 * Read Streaming P0 asserted:		 * If we raise ATN and the target completes the entire		 * stream (P0 asserted during the last packet), the		 * hardware will ack all data and return to the ISTART		 * state.  When the target reponds to our ATN condition,		 * LQIPHASE_LQ will be asserted.  We should respond to		 * this with an LQIRETRY to prepare for any future		 * packets.  NONPACKREQ will not be asserted again		 * once we hit LQIRETRY until another packet is		 * processed.  The target may either go busfree or		 * start another packet in response to our message.		 * Busfree detection is enabled.		 *		 * Read Streaming P0 not asserted:		 * If we raise ATN and the target transitions to		 * MSGOUT in or after a packet where P0 is not		 * asserted, the hardware will assert LQIPHASE_NLQ.		 * We should respond to the LQIPHASE_NLQ with an		 * LQICONTINUE.  Should the target stay in a non-pkt		 * phase after we send our message, the hardware		 * will assert LQIPHASE_LQ.  Recovery is then just as		 * listed above for the read streaming with P0 asserted.		 * Busfree detection is enabled.		 */		printf("LQICRC_NLQ\n");		ahd_set_active_fifo(ahd);		scbid = ahd_get_scbptr(ahd);		scb = ahd_lookup_scb(ahd, scbid);		if (scb == NULL) {			printf("%s: No SCB valid for LQICRC_NLQ.  "

⌨️ 快捷键说明

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