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

📄 isp_target.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 3 页
字号:
		}		atun._atio2.at_status = CT_OK;	} else {		at_entry_t *aep = arg;		atun._atio.at_header.rqs_entry_type = RQSTYPE_ATIO;		atun._atio.at_header.rqs_entry_count = 1;		atun._atio.at_handle = aep->at_handle;		atun._atio.at_iid = aep->at_iid;		atun._atio.at_tgt = aep->at_tgt;		atun._atio.at_lun = aep->at_lun;		atun._atio.at_tag_type = aep->at_tag_type;		atun._atio.at_tag_val = aep->at_tag_val;		atun._atio.at_status = (aep->at_flags & AT_TQAE);		atun._atio.at_status |= CT_OK;	}	return (isp_target_put_entry(isp, &atun));}/* * Command completion- both for handling cases of no resources or * no blackhole driver, or other cases where we have to, inline, * finish the command sanely, or for normal command completion. * * The 'completion' code value has the scsi status byte in the low 8 bits. * If status is a CHECK CONDITION and bit 8 is nonzero, then bits 12..15 have * the sense key and  bits 16..23 have the ASCQ and bits 24..31 have the ASC * values. * * NB: the key, asc, ascq, cannot be used for parallel SCSI as it doesn't * NB: inline SCSI sense reporting. As such, we lose this information. XXX. * * For both parallel && fibre channel, we use the feature that does * an automatic resource autoreplenish so we don't have then later do * put of an atio to replenish the f/w's resource count. */intisp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int16_t hdl){	int sts;	union {		ct_entry_t _ctio;		ct2_entry_t _ctio2;	} un;	MEMZERO(&un, sizeof un);	sts = code & 0xff;	if (IS_FC(isp)) {		at2_entry_t *aep = arg;		ct2_entry_t *cto = &un._ctio2;		cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;		cto->ct_header.rqs_entry_count = 1;		cto->ct_iid = aep->at_iid;		if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {			cto->ct_lun = aep->at_lun;		}		cto->ct_rxid = aep->at_rxid;		cto->rsp.m1.ct_scsi_status = sts & 0xff;		cto->ct_flags = CT2_SENDSTATUS | CT2_NO_DATA | CT2_FLAG_MODE1;		if (hdl == 0) {			cto->ct_flags |= CT2_CCINCR;		}		if (aep->at_datalen) {			cto->ct_resid = aep->at_datalen;			cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER;		}		if ((sts & 0xff) == SCSI_CHECK && (sts & ECMD_SVALID)) {			cto->rsp.m1.ct_resp[0] = 0xf0;			cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf;			cto->rsp.m1.ct_resp[7] = 8;			cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff;			cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff;			cto->rsp.m1.ct_senselen = 16;			cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;		}		cto->ct_syshandle = hdl;	} else {		at_entry_t *aep = arg;		ct_entry_t *cto = &un._ctio;		cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;		cto->ct_header.rqs_entry_count = 1;		cto->ct_fwhandle = aep->at_handle;		cto->ct_iid = aep->at_iid;		cto->ct_tgt = aep->at_tgt;		cto->ct_lun = aep->at_lun;		cto->ct_tag_type = aep->at_tag_type;		cto->ct_tag_val = aep->at_tag_val;		if (aep->at_flags & AT_TQAE) {			cto->ct_flags |= CT_TQAE;		}		cto->ct_flags = CT_SENDSTATUS | CT_NO_DATA;		if (hdl == 0) {			cto->ct_flags |= CT_CCINCR;		}		cto->ct_scsi_status = sts;		cto->ct_syshandle = hdl;	}	return (isp_target_put_entry(isp, &un));}voidisp_target_async(struct ispsoftc *isp, int bus, int event){	tmd_event_t evt;	tmd_msg_t msg;	switch (event) {	/*	 * These three we handle here to propagate an effective bus reset	 * upstream, but these do not require any immediate notify actions	 * so we return when done.	 */	case ASYNC_LIP_F8:	case ASYNC_LIP_OCCURRED:	case ASYNC_LOOP_UP:	case ASYNC_LOOP_DOWN:	case ASYNC_LOOP_RESET:	case ASYNC_PTPMODE:		/*		 * These don't require any immediate notify actions. We used		 * treat them like SCSI Bus Resets, but that was just plain		 * wrong. Let the normal CTIO completion report what occurred.		 */                return;	case ASYNC_BUS_RESET:	case ASYNC_TIMEOUT_RESET:		if (IS_FC(isp)) {			return;	/* we'll be getting an inotify instead */		}		evt.ev_bus = bus;		evt.ev_event = event;		(void) isp_async(isp, ISPASYNC_TARGET_EVENT, &evt);		break;	case ASYNC_DEVICE_RESET:		/*		 * Bus Device Reset resets a specific target, so		 * we pass this as a synthesized message.		 */		MEMZERO(&msg, sizeof msg);		if (IS_FC(isp)) {			msg.nt_iid = FCPARAM(isp)->isp_loopid;		} else {			msg.nt_iid = SDPARAM(isp)->isp_initiator_id;		}		msg.nt_bus = bus;		msg.nt_msg[0] = MSG_BUS_DEV_RESET;		(void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg);		break;	default:		isp_prt(isp, ISP_LOGERR,		    "isp_target_async: unknown event 0x%x", event);		break;	}	if (isp->isp_state == ISP_RUNSTATE)		isp_notify_ack(isp, NULL);}/* * Process a received message. * The ISP firmware can handle most messages, there are only * a few that we need to deal with: * - abort: clean up the current command * - abort tag and clear queue */static voidisp_got_msg(struct ispsoftc *isp, int bus, in_entry_t *inp){	u_int8_t status = inp->in_status & ~QLTM_SVALID;	if (status == IN_IDE_RECEIVED || status == IN_MSG_RECEIVED) {		tmd_msg_t msg;		MEMZERO(&msg, sizeof (msg));		msg.nt_bus = bus;		msg.nt_iid = inp->in_iid;		msg.nt_tgt = inp->in_tgt;		msg.nt_lun = inp->in_lun;		msg.nt_tagtype = inp->in_tag_type;		msg.nt_tagval = inp->in_tag_val;		MEMCPY(msg.nt_msg, inp->in_msg, IN_MSGLEN);		(void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg);	} else {		isp_prt(isp, ISP_LOGERR,		    "unknown immediate notify status 0x%x", inp->in_status);	}}/* * Synthesize a message from the task management flags in a FCP_CMND_IU. */static voidisp_got_msg_fc(struct ispsoftc *isp, int bus, in_fcentry_t *inp){	int lun;	static const char f1[] = "%s from iid %d lun %d seq 0x%x";	static const char f2[] = 	    "unknown %s 0x%x lun %d iid %d task flags 0x%x seq 0x%x\n";	if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {		lun = inp->in_scclun;	} else {		lun = inp->in_lun;	}	if (inp->in_status != IN_MSG_RECEIVED) {		isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status",		    inp->in_status, lun, inp->in_iid,		    inp->in_task_flags,  inp->in_seqid);	} else {		tmd_msg_t msg;		MEMZERO(&msg, sizeof (msg));		msg.nt_bus = bus;		msg.nt_iid = inp->in_iid;		msg.nt_tagval = inp->in_seqid;		msg.nt_lun = lun;		if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK) {			isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK",			    inp->in_iid, msg.nt_lun, inp->in_seqid);			msg.nt_msg[0] = MSG_ABORT_TAG;		} else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) {			isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET",			    inp->in_iid, msg.nt_lun, inp->in_seqid);			msg.nt_msg[0] = MSG_CLEAR_QUEUE;		} else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) {			isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET",			    inp->in_iid, msg.nt_lun, inp->in_seqid);			msg.nt_msg[0] = MSG_BUS_DEV_RESET;		} else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) {			isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA",			    inp->in_iid, msg.nt_lun, inp->in_seqid);			/* ???? */			msg.nt_msg[0] = MSG_REL_RECOVERY;		} else if (inp->in_task_flags & TASK_FLAGS_TERMINATE_TASK) {			isp_prt(isp, ISP_LOGINFO, f1, "TERMINATE TASK",			    inp->in_iid, msg.nt_lun, inp->in_seqid);			msg.nt_msg[0] = MSG_TERM_IO_PROC;		} else {			isp_prt(isp, ISP_LOGWARN, f2, "task flag",			    inp->in_status, msg.nt_lun, inp->in_iid,			    inp->in_task_flags,  inp->in_seqid);		}		if (msg.nt_msg[0]) {			(void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg);		}	}}static voidisp_notify_ack(struct ispsoftc *isp, void *arg){	char storage[QENTRY_LEN];	u_int16_t nxti, optr;	void *outp;	if (isp_getrqentry(isp, &nxti, &optr, &outp)) {		isp_prt(isp, ISP_LOGWARN,		    "Request Queue Overflow For isp_notify_ack");		return;	}	MEMZERO(storage, QENTRY_LEN);	if (IS_FC(isp)) {		na_fcentry_t *na = (na_fcentry_t *) storage;		if (arg) {			in_fcentry_t *inp = arg;			MEMCPY(storage, arg, sizeof (isphdr_t));			na->na_iid = inp->in_iid;			if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {				na->na_lun = inp->in_scclun;			} else {				na->na_lun = inp->in_lun;			}			na->na_task_flags = inp->in_task_flags;			na->na_seqid = inp->in_seqid;			na->na_flags = NAFC_RCOUNT;			na->na_status = inp->in_status;			if (inp->in_status == IN_RESET) {				na->na_flags |= NAFC_RST_CLRD;			}		} else {			na->na_flags = NAFC_RST_CLRD;		}		na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;		na->na_header.rqs_entry_count = 1;		isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp);	} else {		na_entry_t *na = (na_entry_t *) storage;		if (arg) {			in_entry_t *inp = arg;			MEMCPY(storage, arg, sizeof (isphdr_t));			na->na_iid = inp->in_iid;			na->na_lun = inp->in_lun;			na->na_tgt = inp->in_tgt;			na->na_seqid = inp->in_seqid;			if (inp->in_status == IN_RESET) {				na->na_event = NA_RST_CLRD;			}		} else {			na->na_event = NA_RST_CLRD;		}		na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;		na->na_header.rqs_entry_count = 1;		isp_put_notify_ack(isp, na, (na_entry_t *)outp);	}	ISP_TDQE(isp, "isp_notify_ack", (int) optr, storage);	ISP_ADD_REQUEST(isp, nxti);}static voidisp_handle_atio(struct ispsoftc *isp, at_entry_t *aep){	int lun;	lun = aep->at_lun;	/*	 * The firmware status (except for the QLTM_SVALID bit) indicates	 * why this ATIO was sent to us.	 *	 * If QLTM_SVALID is set, the firware has recommended Sense Data.	 *	 * If the DISCONNECTS DISABLED bit is set in the flags field,	 * we're still connected on the SCSI bus - i.e. the initiator	 * did not set DiscPriv in the identify message. We don't care	 * about this so it's ignored.	 */	switch(aep->at_status & ~QLTM_SVALID) {	case AT_PATH_INVALID:		/*		 * ATIO rejected by the firmware due to disabled lun.		 */		isp_prt(isp, ISP_LOGERR,		    "rejected ATIO for disabled lun %d", lun);		break;	case AT_NOCAP:		/*		 * Requested Capability not available		 * We sent an ATIO that overflowed the firmware's		 * command resource count.		 */		isp_prt(isp, ISP_LOGERR,		    "rejected ATIO for lun %d because of command count"		    " overflow", lun);		break;	case AT_BDR_MSG:		/*		 * If we send an ATIO to the firmware to increment		 * its command resource count, and the firmware is		 * recovering from a Bus Device Reset, it returns		 * the ATIO with this status. We set the command		 * resource count in the Enable Lun entry and do		 * not increment it. Therefore we should never get		 * this status here.		 */		isp_prt(isp, ISP_LOGERR, atiocope, lun,		    GET_BUS_VAL(aep->at_iid));		break;	case AT_CDB:		/* Got a CDB */	case AT_PHASE_ERROR:	/* Bus Phase Sequence Error */		/*		 * Punt to platform specific layer.		 */		(void) isp_async(isp, ISPASYNC_TARGET_ACTION, aep);		break;	case AT_RESET:		/*		 * A bus reset came along an blew away this command. Why		 * they do this in addition the async event code stuff,		 * I dunno.		 *		 * Ignore it because the async event will clear things		 * up for us.		 */		isp_prt(isp, ISP_LOGWARN, atior, lun,		    GET_IID_VAL(aep->at_iid), GET_BUS_VAL(aep->at_iid));		break;	default:		isp_prt(isp, ISP_LOGERR,		    "Unknown ATIO status 0x%x from initiator %d for lun %d",		    aep->at_status, aep->at_iid, lun);		(void) isp_target_put_atio(isp, aep);		break;	}}static voidisp_handle_atio2(struct ispsoftc *isp, at2_entry_t *aep)

⌨️ 快捷键说明

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