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

📄 isp_linux.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
     */    if ((tmd = isp->isp_osinfo.tfreelist) == NULL) {	isp_endcmd(isp, aep, SCSI_QFULL, 0);	return (0);    }    tmd->cd_lflags = CDFL_BUSY;    tmd->cd_iid = aep->at_iid;    tmd->cd_tgt = ((fcparam *)isp->isp_param)->isp_loopid;    tmd->cd_lun = lun;    tmd->cd_bus = 0;    MEMCPY(tmd->cd_cdb, aep->at_cdb, ATIO_CDBLEN);    switch (aep->at_taskflags & ATIO2_TC_ATTR_MASK) {    case ATIO2_TC_ATTR_SIMPLEQ:	tmd->cd_tagtype = MSG_SIMPLE_Q_TAG;	break;    case ATIO2_TC_ATTR_HEADOFQ:	tmd->cd_tagtype = MSG_HEAD_OF_Q_TAG;	break;    case ATIO2_TC_ATTR_ORDERED:	tmd->cd_tagtype = MSG_ORDERED_Q_TAG;	break;    case ATIO2_TC_ATTR_ACAQ:		/* ?? */    case ATIO2_TC_ATTR_UNTAGGED:    default:	tmd->cd_tagtype = 0;	break;    }    tmd->cd_tagval = aep->at_rxid;    tmd->cd_hba = isp;    tmd->cd_data = NULL;    tmd->cd_hflags = 0;    tmd->cd_totlen = aep->at_datalen;    tmd->cd_resid = tmd->cd_xfrlen = tmd->cd_error = 0;    tmd->cd_scsi_status = 0;    if ((isp->isp_dblev & ISP_LOGTDEBUG0) || isp->isp_osinfo.hcb == NULL) {	isp_prt(isp, ISP_LOGALL,	    "ATIO2[%x] CDB=0x%x iid %d for lun %d tcode 0x%x dlen %d",	    aep->at_rxid, aep->at_cdb[0] & 0xff, aep->at_iid,	    lun, aep->at_taskcodes, aep->at_datalen);    }    if (isp->isp_osinfo.hcb == NULL) {	if (aep->at_cdb[0] == INQUIRY && lun == 0) {	    if (aep->at_cdb[1] == 0 && aep->at_cdb[2] == 0) {		static u_int8_t inqdata[] = {		    DEFAULT_DEVICE_TYPE, 0x0, 0x2, 0x2, 32, 0, 0, 0x40,		    'L', 'I', 'N', 'U', 'X', ' ', ' ', ' ',		    'T', 'A', 'R', 'G', 'E', 'T', ' ', 'D',		    'D', 'E', 'V', 'I', 'C', 'E', ' ', ' ',		    '0', '0', '0', '1'		};		struct scatterlist single, *dp = &single;		dp->address = inqdata;		dp->alt_address = NULL;		dp->length = sizeof (inqdata);		tmd->cd_data = dp;		tmd->cd_resid = tmd->cd_xfrlen = sizeof (inqdata);		tmd->cd_hflags |= CDFH_DATA_IN|CDFH_STSVALID;		ISP_DROP_LK_SOFTC(isp);		isp_target_start_ctio(isp, tmd);		ISP_IGET_LK_SOFTC(isp);	    } else {		/*		 * Illegal field in CDB		 *  0x24 << 24 | 0x5 << 12 | ECMD_SVALID | SCSI_CHECK		 */		isp_endcmd(isp, aep, 0x24005102, 0);	    }	} else if (lun == 0) {		/*		 * Not Ready, Cause Not Reportable		 *		 *  0x4 << 24 | 0x2 << 12 | ECMD_SVALID | SCSI_CHECK		 */		isp_endcmd(isp, aep, 0x04002102, 0);	} else {	    /*	     * Logical Unit Not Supported:	     * 	0x25 << 24 | 0x5 << 12 | ECMD_SVALID | SCSI_CHECK	     */	    isp_endcmd(isp, aep, 0x25005102, 0);	}	MEMZERO(tmd, sizeof (tmd_cmd_t));	return (0);    }    tmd->cd_reserved[0] = QOUT_TMD_START;    isp->isp_osinfo.tfreelist = tmd->cd_private;    tmd->cd_private = isp->isp_osinfo.pending_t;    isp->isp_osinfo.pending_t = tmd;    return (0);}static intisp_handle_platform_ctio(struct ispsoftc *isp, void *arg){    tmd_cmd_t *tmd;    int sentstatus, ok, resid = 0, sts;    /*     * CTIO and CTIO2 are close enough....     */    tmd = (tmd_cmd_t *) isp_find_xs(isp, ((ct_entry_t *)arg)->ct_syshandle);    if (tmd == NULL) {	isp_prt(isp, ISP_LOGERR, "isp_handle_platform_ctio: null tmd");	return (0);    }    isp_destroy_handle(isp, ((ct_entry_t *)arg)->ct_syshandle);    if (IS_FC(isp)) {	ct2_entry_t *ct = arg;	sentstatus = ct->ct_flags & CT2_SENDSTATUS;	if (sentstatus) {	    tmd->cd_lflags |= CDFL_SENTSTATUS;	}	sts = ct->ct_status & ~QLTM_SVALID;	ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;	if (ok && sentstatus && (tmd->cd_hflags & CDFH_SNSVALID)) {	    tmd->cd_lflags |= CDFL_SENTSENSE;	}	isp_prt(isp, ISP_LOGTDEBUG1,	    "CTIO2[%x] sts 0x%x flg 0x%x sns %d %s",	    ct->ct_rxid, ct->ct_status, ct->ct_flags,	    (tmd->cd_lflags & CDFL_SENTSENSE) != 0,	    sentstatus? "FIN" : "MID");	if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {	    resid = ct->ct_resid;	}    } else {	ct_entry_t *ct = arg;	sts = ct->ct_status & ~QLTM_SVALID;	sentstatus = ct->ct_flags & CT_SENDSTATUS;	if (sentstatus) {	    tmd->cd_lflags |= CDFL_SENTSTATUS;	}	ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;	if (ok && sentstatus && (tmd->cd_hflags & CDFH_SNSVALID)) {	    tmd->cd_lflags |= CDFL_SENTSENSE;	}	isp_prt(isp, ISP_LOGTDEBUG1,	    "CTIO[%x] tag %x iid %x tgt %d lun %d sts 0x%x flg %x %s",	    ct->ct_fwhandle, ct->ct_tag_val, ct->ct_iid, ct->ct_tgt,	    ct->ct_lun, ct->ct_status, ct->ct_flags,	    sentstatus? "FIN" : "MID");	if (ct->ct_status & QLTM_SVALID) {	    char *sp = (char *)ct;	    sp += CTIO_SENSE_OFFSET;	    MEMCPY(tmd->cd_sense, sp, QLTM_SENSELEN);	    tmd->cd_lflags |= CDFL_SNSVALID;	}	if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) {	    resid = ct->ct_resid;	}    }    tmd->cd_resid += resid;    /*     * We're here either because intermediate data transfers are done     * and/or the final status CTIO (which may have joined with a     * Data Transfer) is done.     *     * In any case, for this platform, the upper layers figure out     * what to do next, so all we do here is collect status and     * pass information along.     */    isp_prt(isp, ISP_LOGTDEBUG0, "%s CTIO done (resid %d)",	(sentstatus)? "  FINAL " : "MIDTERM ", tmd->cd_resid);    if (!ok) {	isp_prt(isp, ISP_LOGERR, "CTIO ended with badstate (0x%x)", sts);	tmd->cd_lflags |= CDFL_ERROR;	tmd->cd_error = -EIO;	isp_target_putback_atio(isp, tmd);    } else {	isp_complete_ctio(isp, tmd);    }    return (0);}static voidisp_target_putback_atio(struct ispsoftc *isp, tmd_cmd_t *tmd){    u_int16_t nxti;    u_int8_t local[QENTRY_LEN];    void *qe;    if (isp_getrqentry(isp, &nxti, NULL, &qe)) {	isp_prt(isp, ISP_LOGWARN,	    "isp_target_putback_atio: Request Queue Overflow");	/* XXXX */	isp_complete_ctio(isp, tmd);	return;    }    MEMZERO(local, sizeof (local));    if (IS_FC(isp)) {	at2_entry_t *at = (at2_entry_t *) local;	at->at_header.rqs_entry_type = RQSTYPE_ATIO2;	at->at_header.rqs_entry_count = 1;	if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN)	    at->at_scclun = (uint16_t) tmd->cd_lun;	else	    at->at_lun = (uint8_t) tmd->cd_lun;	at->at_status = CT_OK;	at->at_rxid = tmd->cd_tagval;	isp_put_atio2(isp, at, qe);    } else {	at_entry_t *at = (at_entry_t *)local;	at->at_header.rqs_entry_type = RQSTYPE_ATIO;	at->at_header.rqs_entry_count = 1;	at->at_iid = tmd->cd_iid;	at->at_iid |= tmd->cd_bus << 7;	at->at_tgt = tmd->cd_tgt;	at->at_lun = tmd->cd_lun;	at->at_status = CT_OK;	at->at_tag_val = AT_GET_TAG(tmd->cd_tagval);	at->at_handle = AT_GET_HANDLE(tmd->cd_tagval);	isp_put_atio(isp, at, qe);    }    ISP_TDQE(isp, "isp_target_putback_atio", isp->isp_reqidx, qe);    ISP_ADD_REQUEST(isp, nxti);    isp_complete_ctio(isp, tmd);}static voidisp_complete_ctio(struct ispsoftc *isp, tmd_cmd_t *tmd){    if (isp->isp_osinfo.hcb == NULL) {	isp_prt(isp, ISP_LOGWARN, "nobody to tell about completing command");	MEMZERO(tmd, sizeof (tmd_cmd_t));	tmd->cd_private = isp->isp_osinfo.tfreelist;	isp->isp_osinfo.tfreelist = tmd;    } else {	tmd->cd_reserved[0] = QOUT_TMD_DONE;	tmd->cd_private = isp->isp_osinfo.pending_t;	isp->isp_osinfo.pending_t = tmd;    }}static intisp_en_dis_lun(struct ispsoftc *isp, int enable, int bus, int tgt, int lun){    DECLARE_MUTEX_LOCKED(rsem);    u_int16_t rstat;    int rv, enabled, cmd;    /*     * First, we can't do anything unless we have an upper     * level target driver to route commands to.     */    if (isp->isp_osinfo.hcb == NULL) {	return (-EINVAL);    }    /*     * Second, check for sanity of enable argument.     */    enabled = ((isp->isp_osinfo.tmflags & (1 << bus)) != 0);    if (enable == 0 && enabled == 0) {	return (-EINVAL);    }    /*     * Third, check to see if we're enabling on fibre channel     * and don't yet have a notion of who the heck we are (no     * loop yet).     */    if (IS_FC(isp) && !enabled) {	ISP_LOCK_SOFTC(isp);	if ((isp->isp_role & ISP_ROLE_TARGET) == 0) {	    isp->isp_role |= ISP_ROLE_TARGET;	    if (isp_drain_reset(isp, "lun enables")) {		return (-EIO);	    }	}	ISP_UNLK_SOFTC(isp);	SEND_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, 1);    }    /*     * If this is a wildcard target, select our initiator     * id/loop id for use as what we enable as.     */    if (tgt == -1) {	if (IS_FC(isp)) {	    tgt = ((fcparam *)isp->isp_param)->isp_loopid;	} else {	    tgt = ((sdparam *)isp->isp_param)->isp_initiator_id;	}    }    /*     * Do some sanity checking on lun arguments.     */    if (lun < 0 || lun >= (IS_FC(isp)? TM_MAX_LUN_FC : TM_MAX_LUN_SCSI)) {	return (-EINVAL);    }    /*     * Snag the semaphore on the return state value on enables/disables.     */    if (down_interruptible(&isp->isp_osinfo.tgt_inisem)) {	return (-EINTR);    }    if (enable && LUN_BTST(isp, bus, lun)) {	up(&isp->isp_osinfo.tgt_inisem);	return (-EEXIST);    }    if (!enable && !LUN_BTST(isp, bus, lun)) {	up(&isp->isp_osinfo.tgt_inisem);	return (-NODEV);    }    if (enable && nolunsenabled(isp, bus)) {	int av = (bus << 31) | ENABLE_TARGET_FLAG;	ISP_LOCK_SOFTC(isp);	rv = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);	ISP_UNLK_SOFTC(isp);	if (rv) {	    up(&isp->isp_osinfo.tgt_inisem);	    return (-EIO);	}    }    ISP_LOCK_SOFTC(isp);    isp->isp_osinfo.rsemap = &rsem;    if (enable) {	u_int32_t seq = isp->isp_osinfo.rollinfo++;	int n, ulun = lun;	cmd = RQSTYPE_ENABLE_LUN;	n = DFLT_INOT_CNT;	if (IS_FC(isp) && lun != 0) {	    cmd = RQSTYPE_MODIFY_LUN;	    n = 0;	    /*	     * For SCC firmware, we only deal with setting	     * (enabling or modifying) lun 0.	     */	    ulun = 0;	}	rstat = LUN_ERR;	if (isp_lun_cmd(isp, cmd, bus, tgt, ulun, DFLT_CMND_CNT, n, seq)) {	    isp_prt(isp, ISP_LOGERR, "isp_lun_cmd failed");	    goto out;	}	ISP_UNLK_SOFTC(isp);	down(isp->isp_osinfo.rsemap);	ISP_LOCK_SOFTC(isp);	isp->isp_osinfo.rsemap = NULL;	rstat = isp->isp_osinfo.rstatus;	if (rstat != LUN_OK) {	    isp_prt(isp, ISP_LOGERR, "MODIFY/ENABLE LUN returned 0x%x", rstat);	    goto out;	}    } else {	int n, ulun = lun;	u_int32_t seq;	rstat = LUN_ERR;	seq = isp->isp_osinfo.rollinfo++;	cmd = -RQSTYPE_MODIFY_LUN;	n = DFLT_INOT_CNT;	if (IS_FC(isp) && lun != 0) {	    n = 0;	    /*	     * For SCC firmware, we only deal with setting	     * (enabling or modifying) lun 0.	     */	    ulun = 0;	}	if (isp_lun_cmd(isp, cmd, bus, tgt, ulun, DFLT_CMND_CNT, n, seq)) {	    isp_prt(isp, ISP_LOGERR, "isp_lun_cmd failed");	    goto out;	}	ISP_UNLK_SOFTC(isp);	down(isp->isp_osinfo.rsemap);	ISP_LOCK_SOFTC(isp);	isp->isp_osinfo.rsemap = NULL;	rstat = isp->isp_osinfo.rstatus;	if (rstat != LUN_OK) {	    isp_prt(isp, ISP_LOGERR, "MODIFY LUN returned 0x%x", rstat);	    goto out;	}	if (IS_FC(isp) && lun) {	    goto out;	}	seq = isp->isp_osinfo.rollinfo++;	isp->isp_osinfo.rsemap = &rsem;	rstat = LUN_ERR;	cmd = -RQSTYPE_ENABLE_LUN;	if (isp_lun_cmd(isp, cmd, bus, tgt, lun, 0, 0, seq)) {	    isp_prt(isp, ISP_LOGERR, "isp_lun_cmd failed");	    goto out;	}	ISP_UNLK_SOFTC(isp);	down(isp->isp_osinfo.rsemap);	ISP_LOCK_SOFTC(isp);	isp->isp_osinfo.rsemap = NULL;	rstat = isp->isp_osinfo.rstatus;	if (rstat != LUN_OK) {	    isp_prt(isp, ISP_LOGERR, "DISABLE LUN returned 0x%x", rstat);	    goto out;	}    }out:    if (rstat != LUN_OK) {	isp_prt(isp, ISP_LOGERR, "lun %d %sable failed", lun,	    (enable) ? "en" : "dis");	ISP_UNLK_SOFTC(isp);	up(&isp->isp_osinfo.tgt_inisem);	return (-EIO);    } else {	isp_prt(isp, ISP_LOGINFO,	    "lun %d now %sabled for target mode on channel %d", lun,	    (enable)? "en" : "dis", bus);	if (enable == 0) {	    LUN_BCLR(isp, bus, lun);	    if (nolunsenabled(isp, bus)) {		int av = bus << 31;		rv = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);		if (rv) {		    isp_prt(isp, ISP_LOGERR,			"failed to disable target mode on channel %d", bus);		    /* but proceed */		    ISP_UNLK_SOFTC(isp);		    return (-EIO);		}		isp->isp_osinfo.tmflags &= ~(1 << bus);		isp->isp_role &= ~ISP_ROLE_TARGET;		if (IS_FC(isp)) {		    if (isplinux_drain_reset(isp, "lun disables")) {			return (-EIO);		    }		    if ((isp->isp_role & ISP_ROLE_INITIATOR) != 0) {			ISP_UNLK_SOFTC(isp);			SEND_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, 1);			ISP_LOCK_SOFTC(isp);		    }		}	    }	} else {	    isp->isp_osinfo.tmflags |= (1 << bus);	    LUN_BSET(isp, bus, lun);	}	ISP_UNLK_SOFTC(isp);	up(&isp->isp_osinfo.tgt_inisem);	return (0);    }}#endifintisp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg){    switch (cmd) {    case ISPASYNC_NEW_TGT_PARAMS:	if (IS_SCSI(isp)) {	    sdparam *sdp = isp->isp_param;	    char *wt;	    int mhz, flags, bus, tgt, period;	    tgt = *((int *) arg);	    bus = (tgt >> 16) & 0xffff;	    tgt &= 0xffff;	    sdp += bus;	    flags = sdp->isp_devparam[tgt].actv_flags;	    period = sdp->isp_devparam[tgt].actv_period;	    if ((flags & DPARM_SYNC) && period &&		(sdp->isp_devparam[tgt].actv_offset) != 0) {		if (sdp->isp_lvdmode || period < 0xc) {		    switch (period) {		    case 0x9:			mhz = 80;			break;		    case 0xa:			mhz = 40;			break;		    case 0xb:			mhz = 33;			break;		    case 0xc:			mhz = 25;			break;		    default:			mhz = 1000 / (period * 4);			break;		    }		} else {		    mhz = 1000 / (period * 4);		}

⌨️ 快捷键说明

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