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

📄 isp.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		}		PRINTF("%s: Target %d on Bus %d Reset Succeeded\n",		    isp->isp_name, tgt, bus);		isp->isp_sendmarker = 1 << bus;		return (0);	case ISPCTL_ABORT_CMD:		xs = (ISP_SCSI_XFER_T *) arg;		for (i = 0; i < RQUEST_QUEUE_LEN; i++) {			if (xs == isp->isp_xflist[i]) {				break;			}		}		if (i == RQUEST_QUEUE_LEN) {			PRINTF("%s: isp_control- cannot find command to abort "			    "in active list\n", isp->isp_name);			break;		}		mbs.param[0] = MBOX_ABORT;#ifdef	ISP2100_SCCLUN		if (isp->isp_type & ISP_HA_FC) {			mbs.param[1] = XS_TGT(xs) << 8;			mbs.param[4] = 0;			mbs.param[5] = 0;			mbs.param[6] = XS_LUN(xs);		} else {			mbs.param[1] = XS_TGT(xs) << 8 | XS_LUN(xs);		}#else		mbs.param[1] = XS_TGT(xs) << 8 | XS_LUN(xs);#endif		/*		 * XXX: WHICH BUS?		 */		mbs.param[2] = (i+1) >> 16;		mbs.param[3] = (i+1) & 0xffff;		isp_mboxcmd(isp, &mbs);		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {			PRINTF("%s: isp_control MBOX_ABORT failure (code %x)\n",			    isp->isp_name, mbs.param[0]);			break;		}		PRINTF("%s: command for target %d lun %d was aborted\n",		    isp->isp_name, XS_TGT(xs), XS_LUN(xs));		return (0);	case ISPCTL_UPDATE_PARAMS:		isp_update(isp);		return (0);	case ISPCTL_FCLINK_TEST:		return (isp_fclink_test(isp, FC_FW_READY_DELAY));	}	return (-1);}/* * Interrupt Service Routine(s). * * External (OS) framework has done the appropriate locking, * and the locking will be held throughout this function. */intisp_intr(arg)	void *arg;{	ISP_SCSI_XFER_T *complist[RESULT_QUEUE_LEN], *xs;	struct ispsoftc *isp = arg;	u_int8_t iptr, optr;	u_int16_t isr, sema;	int i, nlooked = 0, ndone = 0;	/*	 * Well, if we've disabled interrupts, we may get a case where	 * isr isn't set, but sema is.	 */	isr = ISP_READ(isp, BIU_ISR);	sema = ISP_READ(isp, BIU_SEMA) & 0x1;	IDPRINTF(5, ("%s: isp_intr isr %x sem %x\n", isp->isp_name, isr, sema));	if (IS_FC(isp)) {		if (isr == 0 || (isr & BIU2100_ISR_RISC_INT) == 0) {			if (isr) {				IDPRINTF(4, ("%s: isp_intr isr=%x\n",				    isp->isp_name, isr));			}			return (0);		}	} else {		if (isr == 0 || (isr & BIU_ISR_RISC_INT) == 0) {			if (isr) {				IDPRINTF(4, ("%s: isp_intr isr=%x\n",				    isp->isp_name, isr));			}			return (0);		}	}	if (isp->isp_state != ISP_RUNSTATE) {		IDPRINTF(3, ("%s: interrupt (isr=%x,sema=%x) when not ready\n",		    isp->isp_name, isr, sema));		ISP_WRITE(isp, INMAILBOX5, ISP_READ(isp, OUTMAILBOX5));		ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);		ISP_WRITE(isp, BIU_SEMA, 0);		ENABLE_INTS(isp);		return (1);	}	if (sema) {		u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0);		if (mbox & 0x4000) {			IDPRINTF(3, ("%s: Command Mbox 0x%x\n",			    isp->isp_name, mbox));		} else {			u_int32_t fhandle = isp_parse_async(isp, (int) mbox);			IDPRINTF(3, ("%s: Async Mbox 0x%x\n",			    isp->isp_name, mbox));			if (fhandle > 0) {				xs = (void *)isp->isp_xflist[fhandle - 1];				isp->isp_xflist[fhandle - 1] = NULL;				/*				 * Since we don't have a result queue entry				 * item, we must believe that SCSI status is				 * zero and that all data transferred.				 */				XS_RESID(xs) = 0;				XS_STS(xs) = 0;				if (XS_XFRLEN(xs)) {					ISP_DMAFREE(isp, xs, fhandle - 1);				}				if (isp->isp_nactive > 0)				    isp->isp_nactive--;				XS_CMD_DONE(xs);			}		}		ISP_WRITE(isp, BIU_SEMA, 0);		ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);		ENABLE_INTS(isp);		return (1);	}	/*	 * You *must* read OUTMAILBOX5 prior to clearing the RISC interrupt.	 */	optr = isp->isp_residx;	iptr = ISP_READ(isp, OUTMAILBOX5);	ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);	if (optr == iptr) {		IDPRINTF(4, ("why intr? isr %x iptr %x optr %x\n",		    isr, optr, iptr));	}	while (optr != iptr) {		ispstatusreq_t *sp;		u_int8_t oop;		int buddaboom = 0;		sp = (ispstatusreq_t *) ISP_QUEUE_ENTRY(isp->isp_result, optr);		oop = optr;		optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN);		nlooked++;		MemoryBarrier();		ISP_SBUSIFY_ISPHDR(isp, &sp->req_header);		if (sp->req_header.rqs_entry_type != RQSTYPE_RESPONSE) {			if (isp_handle_other_response(isp, sp, &optr) == 0) {				ISP_WRITE(isp, INMAILBOX5, optr);				continue;			}			/*			 * It really has to be a bounced request just copied			 * from the request queue to the response queue. If			 * not, something bad has happened.			 */			if (sp->req_header.rqs_entry_type != RQSTYPE_REQUEST) {				ISP_WRITE(isp, INMAILBOX5, optr);				PRINTF("%s: not RESPONSE in RESPONSE Queue "				    "(type 0x%x) @ idx %d (next %d)\n",				    isp->isp_name,				    sp->req_header.rqs_entry_type, oop, optr);				continue;			}			buddaboom = 1;		}		if (sp->req_header.rqs_flags & 0xf) {#define	_RQS_OFLAGS	\	~(RQSFLAG_CONTINUATION|RQSFLAG_FULL|RQSFLAG_BADHEADER|RQSFLAG_BADPACKET)			if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) {				IDPRINTF(3, ("%s: continuation segment\n",				    isp->isp_name));				ISP_WRITE(isp, INMAILBOX5, optr);				continue;			}			if (sp->req_header.rqs_flags & RQSFLAG_FULL) {				IDPRINTF(2, ("%s: internal queues full\n",				    isp->isp_name));				/*				 * We'll synthesize a QUEUE FULL message below.				 */			}			if (sp->req_header.rqs_flags & RQSFLAG_BADHEADER) {				PRINTF("%s: bad header\n", isp->isp_name);				buddaboom++;			}			if (sp->req_header.rqs_flags & RQSFLAG_BADPACKET) {				PRINTF("%s: bad request packet\n",				    isp->isp_name);				buddaboom++;			}			if (sp->req_header.rqs_flags & _RQS_OFLAGS) {				PRINTF("%s: unknown flags in response (0x%x)\n",				    isp->isp_name, sp->req_header.rqs_flags);				buddaboom++;			}#undef	_RQS_OFLAGS		}		if (sp->req_handle > RQUEST_QUEUE_LEN || sp->req_handle < 1) {			PRINTF("%s: bad request handle %d\n", isp->isp_name,				sp->req_handle);			ISP_WRITE(isp, INMAILBOX5, optr);			continue;		}		xs = (void *) isp->isp_xflist[sp->req_handle - 1];		if (xs == NULL) {			PRINTF("%s: NULL xs in xflist (handle %x)\n",			    isp->isp_name, sp->req_handle);			isp_dumpxflist(isp);			ISP_WRITE(isp, INMAILBOX5, optr);			continue;		}		isp->isp_xflist[sp->req_handle - 1] = NULL;		if (sp->req_status_flags & RQSTF_BUS_RESET) {			isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));		}		if (buddaboom) {			XS_SETERR(xs, HBA_BOTCH);		}		XS_STS(xs) = sp->req_scsi_status & 0xff;		if (IS_SCSI(isp)) {			if (sp->req_state_flags & RQSF_GOT_SENSE) {				MEMCPY(XS_SNSP(xs), sp->req_sense_data,					XS_SNSLEN(xs));				XS_SNS_IS_VALID(xs);			}			/*			 * A new synchronous rate was negotiated for this			 * target. Mark state such that we'll go look up			 * that which has changed later.			 */			if (sp->req_status_flags & RQSTF_NEGOTIATION) {				sdparam *sdp = isp->isp_param;				sdp += XS_CHANNEL(xs);				sdp->isp_devparam[XS_TGT(xs)].dev_refresh = 1;				isp->isp_update |= (1 << XS_CHANNEL(xs));			}		} else {			if (XS_STS(xs) == SCSI_CHECK) {				XS_SNS_IS_VALID(xs);				MEMCPY(XS_SNSP(xs), sp->req_sense_data,					XS_SNSLEN(xs));				sp->req_state_flags |= RQSF_GOT_SENSE;			}		}		if (XS_NOERR(xs) && XS_STS(xs) == SCSI_BUSY) {			XS_SETERR(xs, HBA_TGTBSY);		}		if (sp->req_header.rqs_entry_type == RQSTYPE_RESPONSE) {			if (XS_NOERR(xs)) {			    if (sp->req_completion_status != RQCS_COMPLETE) {				isp_parse_status(isp, sp, xs);			    } else {				XS_SETERR(xs, HBA_NOERROR);			    }			}		} else if (sp->req_header.rqs_entry_type == RQSTYPE_REQUEST) {			if (sp->req_header.rqs_flags & RQSFLAG_FULL) {				/*				 * Force Queue Full status.				 */				XS_STS(xs) = SCSI_QFULL;				XS_SETERR(xs, HBA_NOERROR);			} else if (XS_NOERR(xs)) {				XS_SETERR(xs, HBA_BOTCH);			}		} else {			PRINTF("%s: unhandled respose queue type 0x%x\n",			    isp->isp_name, sp->req_header.rqs_entry_type);			if (XS_NOERR(xs)) {				XS_SETERR(xs, HBA_BOTCH);			}		}		if (isp->isp_type & ISP_HA_SCSI) {			XS_RESID(xs) = sp->req_resid;		} else if (sp->req_scsi_status & RQCS_RU) {			XS_RESID(xs) = sp->req_resid;			IDPRINTF(4, ("%s: cnt %d rsd %d\n", isp->isp_name,				XS_XFRLEN(xs), sp->req_resid));		}		if (XS_XFRLEN(xs)) {			ISP_DMAFREE(isp, xs, sp->req_handle - 1);		}		/*		 * XXX: If we have a check condition, but no Sense Data,		 * XXX: mark it as an error (ARQ failed). We need to		 * XXX: to do a more distinct job because there may		 * XXX: cases where ARQ is disabled.		 */		if (XS_STS(xs) == SCSI_CHECK && !(XS_IS_SNS_VALID(xs))) {			if (XS_NOERR(xs)) {				PRINTF("%s: ARQ failure for target %d lun %d\n",				    isp->isp_name, XS_TGT(xs), XS_LUN(xs));				XS_SETERR(xs, HBA_ARQFAIL);			}		}		if ((isp->isp_dblev >= 5) ||		    (isp->isp_dblev > 2 && !XS_NOERR(xs))) {			PRINTF("%s(%d.%d): FIN%d dl%d resid%d STS %x",			    isp->isp_name, XS_TGT(xs), XS_LUN(xs),			    sp->req_header.rqs_seqno, XS_XFRLEN(xs),			    XS_RESID(xs), XS_STS(xs));			if (sp->req_state_flags & RQSF_GOT_SENSE) {				PRINTF(" Skey: %x", XS_SNSKEY(xs));				if (!(XS_IS_SNS_VALID(xs))) {					PRINTF(" BUT NOT SET");				}			}			PRINTF(" XS_ERR=0x%x\n", (unsigned int) XS_ERR(xs));		}		if (isp->isp_nactive > 0)		    isp->isp_nactive--;		complist[ndone++] = xs;	/* defer completion call until later */	}	/*	 * If we looked at any commands, then it's valid to find out	 * what the outpointer is. It also is a trigger to update the	 * ISP's notion of what we've seen so far.	 */	if (nlooked) {		ISP_WRITE(isp, INMAILBOX5, optr);		isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4);	}	isp->isp_residx = optr;	for (i = 0; i < ndone; i++) {		xs = complist[i];		if (xs) {			XS_CMD_DONE(xs);		}	}	ENABLE_INTS(isp);	return (1);}/* * Support routines. */static intisp_parse_async(isp, mbox)	struct ispsoftc *isp;	int mbox;{	u_int32_t fast_post_handle = 0;	switch (mbox) {	case MBOX_COMMAND_COMPLETE:	/* sometimes these show up */		break;	case ASYNC_BUS_RESET:	{		int bus;		if (IS_1080(isp) || IS_12X0(isp)) {			bus = ISP_READ(isp, OUTMAILBOX6);		} else {			bus = 0;		}		isp->isp_sendmarker = (1 << bus);		isp_async(isp, ISPASYNC_BUS_RESET, &bus);#ifdef	ISP_TARGET_MODE		isp_notify_ack(isp, NULL);#endif		break;	}	case ASYNC_SYSTEM_ERROR:		mbox = ISP_READ(isp, OUTMAILBOX1);		PRINTF("%s: Internal FW Error @ RISC Addr 0x%x\n",		    isp->isp_name, mbox);		isp_restart(isp);		/* no point continuing after this */		return (-1);	case ASYNC_RQS_XFER_ERR:		PRINTF("%s: Request Queue Transfer Error\n", isp->isp_name);		break;	case ASYNC_RSP_XFER_ERR:		PRINTF("%s: Response Queue Transfer Error\n", isp->isp_name);		break;	case ASYNC_QWAKEUP:		/* don't need to be chatty */		mbox = ISP_READ(isp, OUTMAILBOX4);		break;	case ASYNC_TIMEOUT_RESET:		PRINTF("%s: timeout initiated SCSI bus reset\n", isp->isp_name);		isp->isp_sendmarker = 1;#ifdef	ISP_TARGET_MODE		isp_notify_ack(isp, NULL);#endif		break;	case ASYNC_DEVICE_RESET:		/*		 * XXX: WHICH BUS?		 */		isp->isp_sendmarker = 1;		PRINTF("%s: device reset\n", isp->isp_name);#ifdef	ISP_TARGET_MODE		isp_notify_ack(isp, NULL);#endif		break;	case ASYNC_EXTMSG_UNDERRUN:		PRINTF("%s: extended message underrun\n", isp->isp_name);		break;	case ASYNC_SCAM_INT:		PRINTF("%s: SCAM interrupt\n", isp->isp_name);		break;	case ASYNC_HUNG_SCSI:		PRINTF("%s: stalled SCSI Bus after DATA Overrun\n",		    isp->isp_name);		/* XXX: Need to issue SCSI reset at this point */		break;	case ASYNC_KILLED_BUS:		PRINTF("%s: SCSI Bus reset after DATA Overrun\n",		    isp->isp_name);		break;	case ASYNC_BUS_TRANSIT:		/*		 * XXX: WHICH BUS?		 */		mbox = ISP_READ(isp, OUTMAILBOX2);		switch (mbox & 0x1c00) {		case SXP_PINS_LVD_MODE:			PRINTF("%s: Transition to LVD mode\n", isp->isp_name);			((sdparam *)isp->isp_param)->isp_diffmode = 0;			((sdparam *)isp->isp_param)->isp_ultramode = 0;			((sdparam *)isp->isp_param)->isp_lvdmode = 1;			break;		case SXP_PINS_HVD_MODE:			PRINTF("%s: Transition to Differential mode\n",			    isp->isp_name);			((sdparam *)isp->isp_param)->isp_diffmode = 1;			((sdparam *)isp->isp_param)->isp_ultramode = 0;			((sdparam *)isp->isp_param)->isp_lvdmode = 0;			break;		case SXP_PINS_SE_MODE:			PRINTF("%s: Transition to Single Ended mode\n",			    isp->isp_name);			((sdparam *)isp->isp_param)->isp_diffmode = 0;			((sdparam *)isp->isp_param)->isp_ultramode = 1;			((sdparam *)isp->isp_param)->isp_lvdmode = 0;			break;		default:			PRINTF("%s: Transition to unknown mode 0x%x\n",			    isp->isp_name, mbox);			break;		}		/*		 * XXX: Set up to renegotiate again!		 */		/* Can only be for a 1080... */		isp->isp_sendmarker = (1 << ISP_READ(isp, OUTMAILBOX6));		break;	case ASYNC_CMD_CMPLT:		fast_post_handle = (ISP_READ(isp, OUTMAILBOX2) << 16) |		    ISP_READ(isp, OUTMAILBOX1);		IDPRINTF(3, ("%s: fast post completion of %u\n", isp->isp_name,		    fast_post_handle));		break;	case ASYNC_CTIO_DONE:		/* Should only occur when Fast Posting Set for 2100s */		PRINTF("%s: CTIO done\n", isp->isp_name);		break;	case ASYNC_LIP_OCCURRED:		((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT;		isp->isp_sendmarker = 1;		isp_mark_getpdb_all(isp);		PRINTF("%s: LIP occurred\n", isp->isp_name);		break;	case ASYNC_LOOP_UP:		((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT;		isp->isp_sendmarker = 1;		isp_mark_getpdb_all(isp);		isp_async(isp, ISPASYNC_LOOP_UP, NULL);		break;	case ASYNC_LOOP_DOWN:

⌨️ 快捷键说明

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