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

📄 aic7xxx_core.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		ahc_dump_card_state(ahc);		panic("for saftey");		break;	}	case OUT_OF_RANGE:	{		printf("%s: BTT calculation out of range\n", ahc_name(ahc));		printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, "		       "ARG_1 == 0x%x ACCUM = 0x%x\n",		       ahc_inb(ahc, SAVED_SCSIID), ahc_inb(ahc, SAVED_LUN),		       ahc_inb(ahc, ARG_1), ahc_inb(ahc, ACCUM));		printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, "		       "SINDEX == 0x%x\n, A == 0x%x\n",		       ahc_inb(ahc, SEQ_FLAGS), ahc_inb(ahc, SCBPTR),		       ahc_index_busy_tcl(ahc,			    BUILD_TCL(ahc_inb(ahc, SAVED_SCSIID),				      ahc_inb(ahc, SAVED_LUN))),		       ahc_inb(ahc, SINDEX),		       ahc_inb(ahc, ACCUM));		printf("SCSIID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, "		       "SCB_TAG == 0x%x, SCB_CONTROL == 0x%x\n",		       ahc_inb(ahc, SCSIID), ahc_inb(ahc, SCB_SCSIID),		       ahc_inb(ahc, SCB_LUN), ahc_inb(ahc, SCB_TAG),		       ahc_inb(ahc, SCB_CONTROL));		printf("SCSIBUSL == 0x%x, SCSISIGI == 0x%x\n",		       ahc_inb(ahc, SCSIBUSL), ahc_inb(ahc, SCSISIGI));		ahc_dump_card_state(ahc);		panic("for safety");		break;	}	default:		printf("ahc_intr: seqint, "		       "intstat == 0x%x, scsisigi = 0x%x\n",		       intstat, ahc_inb(ahc, SCSISIGI));		break;	}unpause:	/*	 *  The sequencer is paused immediately on	 *  a SEQINT, so we should restart it when	 *  we're done.	 */	ahc_unpause(ahc);}voidahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat){	u_int	scb_index;	u_int	status0;	u_int	status;	struct	scb *scb;	char	cur_channel;	char	intr_channel;	if ((ahc->features & AHC_TWIN) != 0	 && ((ahc_inb(ahc, SBLKCTL) & SELBUSB) != 0))		cur_channel = 'B';	else		cur_channel = 'A';	intr_channel = cur_channel;	if ((ahc->features & AHC_ULTRA2) != 0)		status0 = ahc_inb(ahc, SSTAT0) & IOERR;	else		status0 = 0;	status = ahc_inb(ahc, SSTAT1) & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR);	if (status == 0 && status0 == 0) {		if ((ahc->features & AHC_TWIN) != 0) {			/* Try the other channel */		 	ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB);			status = ahc_inb(ahc, SSTAT1)			       & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR);			intr_channel = (cur_channel == 'A') ? 'B' : 'A';		}		if (status == 0) {			printf("%s: Spurious SCSI interrupt\n", ahc_name(ahc));			ahc_outb(ahc, CLRINT, CLRSCSIINT);			ahc_unpause(ahc);			return;		}	}	/* Make sure the sequencer is in a safe location. */	ahc_clear_critical_section(ahc);	scb_index = ahc_inb(ahc, SCB_TAG);	scb = ahc_lookup_scb(ahc, scb_index);	if (scb != NULL	 && (ahc_inb(ahc, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)		scb = NULL;	if ((ahc->features & AHC_ULTRA2) != 0	 && (status0 & IOERR) != 0) {		int now_lvd;		now_lvd = ahc_inb(ahc, SBLKCTL) & ENAB40;		printf("%s: Transceiver State Has Changed to %s mode\n",		       ahc_name(ahc), now_lvd ? "LVD" : "SE");		ahc_outb(ahc, CLRSINT0, CLRIOERR);		/*		 * 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.		 */		ahc_reset_channel(ahc, intr_channel,				 /*Initiate Reset*/now_lvd == 0);	} else if ((status & SCSIRSTI) != 0) {		printf("%s: Someone reset channel %c\n",			ahc_name(ahc), intr_channel);		if (intr_channel != cur_channel)		 	ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB);		ahc_reset_channel(ahc, intr_channel, /*Initiate Reset*/FALSE);	} else if ((status & SCSIPERR) != 0) {		/*		 * Determine the bus phase and queue an appropriate message.		 * SCSIPERR is latched true as soon as a parity error		 * occurs.  If the sequencer acked the transfer that		 * caused the parity error and the currently presented		 * transfer on the bus has correct parity, SCSIPERR will		 * be cleared by CLRSCSIPERR.  Use this to determine if		 * we should look at the last phase the sequencer recorded,		 * or the current phase presented on the bus.		 */		struct	ahc_devinfo devinfo;		u_int	mesg_out;		u_int	curphase;		u_int	errorphase;		u_int	lastphase;		u_int	scsirate;		u_int	i;		u_int	sstat2;		int	silent;		lastphase = ahc_inb(ahc, LASTPHASE);		curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;		sstat2 = ahc_inb(ahc, SSTAT2);		ahc_outb(ahc, CLRSINT1, CLRSCSIPERR);		/*		 * For all phases save DATA, the sequencer won't		 * automatically ack a byte that has a parity error		 * in it.  So the only way that the current phase		 * could be 'data-in' is if the parity error is for		 * an already acked byte in the data phase.  During		 * synchronous data-in transfers, we may actually		 * ack bytes before latching the current phase in		 * LASTPHASE, leading to the discrepancy between		 * curphase and lastphase.		 */		if ((ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0		 || curphase == P_DATAIN || curphase == P_DATAIN_DT)			errorphase = curphase;		else			errorphase = lastphase;		for (i = 0; i < num_phases; i++) {			if (errorphase == ahc_phase_table[i].phase)				break;		}		mesg_out = ahc_phase_table[i].mesg_out;		silent = FALSE;		if (scb != NULL) {			if (SCB_IS_SILENT(scb))				silent = TRUE;			else				ahc_print_path(ahc, scb);			scb->flags |= SCB_TRANSMISSION_ERROR;		} else			printf("%s:%c:%d: ", ahc_name(ahc), intr_channel,			       SCSIID_TARGET(ahc, ahc_inb(ahc, SAVED_SCSIID)));		scsirate = ahc_inb(ahc, SCSIRATE);		if (silent == FALSE) {			printf("parity error detected %s. "			       "SEQADDR(0x%x) SCSIRATE(0x%x)\n",			       ahc_phase_table[i].phasemsg,			       ahc_inw(ahc, SEQADDR0),			       scsirate);			if ((ahc->features & AHC_DT) != 0) {				if ((sstat2 & CRCVALERR) != 0)					printf("\tCRC Value Mismatch\n");				if ((sstat2 & CRCENDERR) != 0)					printf("\tNo terminal CRC packet "					       "recevied\n");				if ((sstat2 & CRCREQERR) != 0)					printf("\tIllegal CRC packet "					       "request\n");				if ((sstat2 & DUAL_EDGE_ERR) != 0)					printf("\tUnexpected %sDT Data Phase\n",					       (scsirate & SINGLE_EDGE)					     ? "" : "non-");			}		}		if ((ahc->features & AHC_DT) != 0		 && (sstat2 & DUAL_EDGE_ERR) != 0) {			/*			 * This error applies regardless of			 * data direction, so ignore the value			 * in the phase table.			 */			mesg_out = MSG_INITIATOR_DET_ERR;		}		/*		 * We've set the hardware to assert ATN if we   		 * get a parity error on "in" phases, so all we  		 * need to do is stuff the message buffer with		 * the appropriate message.  "In" phases have set		 * mesg_out to something other than MSG_NOP.		 */		if (mesg_out != MSG_NOOP) {			if (ahc->msg_type != MSG_TYPE_NONE)				ahc->send_msg_perror = TRUE;			else				ahc_outb(ahc, MSG_OUT, mesg_out);		}		/*		 * Force a renegotiation with this target just in		 * case we are out of sync for some external reason		 * unknown (or unreported) by the target.		 */		ahc_fetch_devinfo(ahc, &devinfo);		ahc_force_renegotiation(ahc, &devinfo);		ahc_outb(ahc, CLRINT, CLRSCSIINT);		ahc_unpause(ahc);	} else if ((status & SELTO) != 0) {		u_int	scbptr;		/* Stop the selection */		ahc_outb(ahc, SCSISEQ, 0);		/* No more pending messages */		ahc_clear_msg_state(ahc);		/* Clear interrupt state */		ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);		ahc_outb(ahc, 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).		 */		ahc_outb(ahc, CLRSINT0, CLRSELINGO);		scbptr = ahc_inb(ahc, WAITING_SCBH);		ahc_outb(ahc, SCBPTR, scbptr);		scb_index = ahc_inb(ahc, SCB_TAG);		scb = ahc_lookup_scb(ahc, scb_index);		if (scb == NULL) {			printf("%s: ahc_intr - referenced scb not "			       "valid during SELTO scb(%d, %d)\n",			       ahc_name(ahc), scbptr, scb_index);			ahc_dump_card_state(ahc);		} else {			struct ahc_devinfo devinfo;#ifdef AHC_DEBUG			if ((ahc_debug & AHC_SHOW_SELTO) != 0) {				ahc_print_path(ahc, scb);				printf("Saw Selection Timeout for SCB 0x%x\n",				       scb_index);			}#endif			/*			 * Force a renegotiation with this target just in			 * case the cable was pulled and will later be			 * re-attached.  The target may forget its negotiation			 * settings with us should it attempt to reselect			 * during the interruption.  The target will not issue			 * a unit attention in this case, so we must always			 * renegotiate.			 */			ahc_scb_devinfo(ahc, &devinfo, scb);			ahc_force_renegotiation(ahc, &devinfo);			ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);			ahc_freeze_devq(ahc, scb);		}		ahc_outb(ahc, CLRINT, CLRSCSIINT);		ahc_restart(ahc);	} else if ((status & BUSFREE) != 0		&& (ahc_inb(ahc, SIMODE1) & ENBUSFREE) != 0) {		struct	ahc_devinfo devinfo;		u_int	lastphase;		u_int	saved_scsiid;		u_int	saved_lun;		u_int	target;		u_int	initiator_role_id;		char	channel;		int	printerror;		/*		 * 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.		 */		ahc_outb(ahc, SCSISEQ,			 ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP));		/*		 * Disable busfree interrupts and clear the busfree		 * interrupt status.  We do this here so that several		 * bus transactions occur prior to clearing the SCSIINT		 * latch.  It can take a bit for the clearing to take effect.		 */		ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);		ahc_outb(ahc, CLRSINT1, CLRBUSFREE|CLRSCSIPERR);		/*		 * Look at what phase we were last in.		 * If its message out, chances are pretty good		 * that the busfree was in response to one of		 * our abort requests.		 */		lastphase = ahc_inb(ahc, LASTPHASE);		saved_scsiid = ahc_inb(ahc, SAVED_SCSIID);		saved_lun = ahc_inb(ahc, SAVED_LUN);		target = SCSIID_TARGET(ahc, saved_scsiid);		initiator_role_id = SCSIID_OUR_ID(saved_scsiid);		channel = SCSIID_CHANNEL(ahc, saved_scsiid);		ahc_compile_devinfo(&devinfo, initiator_role_id,				    target, saved_lun, channel, ROLE_INITIATOR);		printerror = 1;		if (lastphase == P_MESGOUT) {			u_int tag;			tag = SCB_LIST_NULL;			if (ahc_sent_msg(ahc, AHCMSG_1B, MSG_ABORT_TAG, TRUE)			 || ahc_sent_msg(ahc, AHCMSG_1B, MSG_ABORT, TRUE)) {				if (ahc->msgout_buf[ahc->msgout_index - 1]				 == MSG_ABORT_TAG)					tag = scb->hscb->tag;				ahc_print_path(ahc, scb);				printf("SCB %d - Abort%s Completed.\n",				       scb->hscb->tag, tag == SCB_LIST_NULL ?				       "" : " Tag");				ahc_abort_scbs(ahc, target, channel,					       saved_lun, tag,					       ROLE_INITIATOR,					       CAM_REQ_ABORTED);				printerror = 0;			} else if (ahc_sent_msg(ahc, AHCMSG_1B,						MSG_BUS_DEV_RESET, TRUE)) {#ifdef __FreeBSD__				/*				 * Don't mark the user's request for this BDR				 * as completing with CAM_BDR_SENT.  CAM3				 * specifies CAM_REQ_CMP.				 */				if (scb != NULL				 && scb->io_ctx->ccb_h.func_code== XPT_RESET_DEV				 && ahc_match_scb(ahc, scb, target, channel,						  CAM_LUN_WILDCARD,						  SCB_LIST_NULL,						  ROLE_INITIATOR)) {					ahc_set_transaction_status(scb, CAM_REQ_CMP);				}#endif				ahc_compile_devinfo(&devinfo,						    initiator_role_id,						    target,						    CAM_LUN_WILDCARD,						    channel,						    ROLE_INITIATOR);				ahc_handle_devreset(ahc, &devinfo,						    CAM_BDR_SENT,						    "Bus Device Reset",						    /*verbose_level*/0);				printerror = 0;			} else if (ahc_sent_msg(ahc, AHCMSG_EXT,						MSG_EXT_PPR, FALSE)) {				struct ahc_initiator_tinfo *tinfo;				struct ahc_tmode_tstate *tstate;				/*				 * PPR Rejected.  Try non-ppr negotiation				 * and retry command.				 */				tinfo = ahc_fetch_transinfo(ahc,							    devinfo.channel,							    devinfo.our_scsiid,							    devinfo.target,							    &tstate);				tinfo->curr.transport_version = 2;				tinfo->goal.transport_version = 2;				tinfo->goal.ppr_options = 0;				ahc_qinfifo_requeue_tail(ahc, scb);				printerror = 0;			} else if (ahc_sent_msg(ahc, AHCMSG_EXT,						MSG_EXT_WDTR, FALSE)) {				/*				 * Negotiation Rejected.  Go-narrow and				 * retry command.				 */				ahc_set_width(ahc, &devinfo,					      MSG_EXT_WDTR_BUS_8_BIT,					      AHC_TRANS_CUR|AHC_TRANS_GOAL,					      /*paused*/TRUE);				ahc_qinfifo_requeue_tail(ahc, scb);				printerror = 0;			} else if (ahc_sent_msg(ahc, AHCMSG_EXT,						MSG_EXT_SDTR, FALSE)) {				/*				 * Negotiation Rejected.  Go-async and				 * retry command.				 */				ahc_set_syncrate(ahc, &devinfo,						/*syncrate*/NULL,						/*period*/0, /*offset*/0,						/*ppr_options*/0,						AHC_TRANS_CUR|AHC_TRANS_GOAL,						/*paused*/TRUE);				ahc_qinfifo_requeue_tail(ahc, scb);				printerror = 0;			}		}		if (printerror != 0) {			u_int i;			if (scb != NULL) {				u_int tag;				if ((scb->hscb->control & TAG_ENB) != 0)					tag = scb->hscb->tag;				else					tag = SCB_LIST_NULL;				ahc_print_path(ahc, scb);				ahc_abort_scbs(ahc, target, channel,					       SCB_GET_LUN(scb), tag,					       ROLE_INITIATOR,					       CAM_UNEXP_BUSFREE);			} else {				/*				 * We had not fully identified this connection,				 * so we cannot abort anything.				 */				printf("%s: ", ahc_name(ahc));			}			for (i = 0; i < num_phases; i++) {				if (lastphase == ahc_phase_table[i].phase)					break;			}

⌨️ 快捷键说明

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