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

📄 isp.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * Ultra2 F/W always has had fast posting (and LVD transitions)	 *	 * Ultra and older (i.e., SBus) cards may not. It's just safer	 * to assume not for them.	 */	mbs.param[0] = MBOX_SET_FW_FEATURES;	mbs.param[1] = 0;	if (IS_ULTRA2(isp))		mbs.param[1] |= FW_FEATURE_LVD_NOTIFY;#ifndef	ISP_NO_RIO	if (IS_ULTRA2(isp) || IS_1240(isp))		mbs.param[1] |= FW_FEATURE_RIO_16BIT;#else#ifndef	ISP_NO_FASTPOST	if (IS_ULTRA2(isp) || IS_1240(isp))		mbs.param[1] |= FW_FEATURE_FAST_POST;#endif#endif	if (mbs.param[1] != 0) {		u_int16_t sfeat = mbs.param[1];		isp_mboxcmd(isp, &mbs, MBLOGALL);		if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {			isp_prt(isp, ISP_LOGINFO,			    "Enabled FW features (0x%x)", sfeat);		}	}	/*	 * Let the outer layers decide whether to issue a SCSI bus reset.	 */	isp->isp_state = ISP_INITSTATE;}static voidisp_scsi_channel_init(struct ispsoftc *isp, int channel){	sdparam *sdp;	mbreg_t mbs;	int tgt;	sdp = isp->isp_param;	sdp += channel;	/*	 * Set (possibly new) Initiator ID.	 */	mbs.param[0] = MBOX_SET_INIT_SCSI_ID;	mbs.param[1] = (channel << 7) | sdp->isp_initiator_id;	isp_mboxcmd(isp, &mbs, MBLOGALL);	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {		return;	}	isp_prt(isp, ISP_LOGINFO, "Initiator ID is %d on Channel %d",	    sdp->isp_initiator_id, channel);	/*	 * Set current per-target parameters to an initial safe minimum.	 */	for (tgt = 0; tgt < MAX_TARGETS; tgt++) {		int lun;		u_int16_t sdf;		if (sdp->isp_devparam[tgt].dev_enable == 0) {			continue;		}#ifndef	ISP_TARGET_MODE		sdf = sdp->isp_devparam[tgt].goal_flags;		sdf &= DPARM_SAFE_DFLT;		/*		 * It is not quite clear when this changed over so that		 * we could force narrow and async for 1000/1020 cards,		 * but assume that this is only the case for loaded		 * firmware.		 */		if (isp->isp_loaded_fw) {			sdf |= DPARM_NARROW | DPARM_ASYNC;		}#else		/*		 * The !$*!)$!$)* f/w uses the same index into some		 * internal table to decide how to respond to negotiations,		 * so if we've said "let's be safe" for ID X, and ID X		 * selects *us*, the negotiations will back to 'safe'		 * (as in narrow/async). What the f/w *should* do is		 * use the initiator id settings to decide how to respond.		 */		sdp->isp_devparam[tgt].goal_flags = sdf = DPARM_DEFAULT;#endif		mbs.param[0] = MBOX_SET_TARGET_PARAMS;		mbs.param[1] = (channel << 15) | (tgt << 8);		mbs.param[2] = sdf;		if ((sdf & DPARM_SYNC) == 0) {			mbs.param[3] = 0;		} else {			mbs.param[3] =			    (sdp->isp_devparam[tgt].goal_offset << 8) |			    (sdp->isp_devparam[tgt].goal_period);		}		isp_prt(isp, ISP_LOGDEBUG0,		    "Initial Settings bus%d tgt%d flags 0x%x off 0x%x per 0x%x",		    channel, tgt, mbs.param[2], mbs.param[3] >> 8,		    mbs.param[3] & 0xff);		isp_mboxcmd(isp, &mbs, MBLOGNONE);		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {			sdf = DPARM_SAFE_DFLT;			mbs.param[0] = MBOX_SET_TARGET_PARAMS;			mbs.param[1] = (tgt << 8) | (channel << 15);			mbs.param[2] = sdf;			mbs.param[3] = 0;			isp_mboxcmd(isp, &mbs, MBLOGALL);			if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {				continue;			}		}		/*		 * We don't update any information directly from the f/w		 * because we need to run at least one command to cause a		 * new state to be latched up. So, we just assume that we		 * converge to the values we just had set.		 *		 * Ensure that we don't believe tagged queuing is enabled yet.		 * It turns out that sometimes the ISP just ignores our		 * attempts to set parameters for devices that it hasn't		 * seen yet.		 */		sdp->isp_devparam[tgt].actv_flags = sdf & ~DPARM_TQING;		for (lun = 0; lun < (int) isp->isp_maxluns; lun++) {			mbs.param[0] = MBOX_SET_DEV_QUEUE_PARAMS;			mbs.param[1] = (channel << 15) | (tgt << 8) | lun;			mbs.param[2] = sdp->isp_max_queue_depth;			mbs.param[3] = sdp->isp_devparam[tgt].exc_throttle;			isp_mboxcmd(isp, &mbs, MBLOGALL);			if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {				break;			}		}	}	for (tgt = 0; tgt < MAX_TARGETS; tgt++) {		if (sdp->isp_devparam[tgt].dev_refresh) {			isp->isp_sendmarker |= (1 << channel);			isp->isp_update |= (1 << channel);			break;		}	}}/* * Fibre Channel specific initialization. * * Locks are held before coming here. */static voidisp_fibre_init(struct ispsoftc *isp){	fcparam *fcp;	isp_icb_t local, *icbp = &local;	mbreg_t mbs;	int loopid;	u_int64_t nwwn, pwwn;	fcp = isp->isp_param;	/*	 * Do this *before* initializing the firmware.	 */	isp_mark_getpdb_all(isp);	fcp->isp_fwstate = FW_CONFIG_WAIT;	fcp->isp_loopstate = LOOP_NIL;	/*	 * If we have no role (neither target nor initiator), return.	 */	if (isp->isp_role == ISP_ROLE_NONE) {		return;	}	loopid = fcp->isp_loopid;	MEMZERO(icbp, sizeof (*icbp));	icbp->icb_version = ICB_VERSION1;	/*	 * Firmware Options are either retrieved from NVRAM or	 * are patched elsewhere. We check them for sanity here	 * and make changes based on board revision, but otherwise	 * let others decide policy.	 */	/*	 * If this is a 2100 < revision 5, we have to turn off FAIRNESS.	 */	if ((isp->isp_type == ISP_HA_FC_2100) && isp->isp_revision < 5) {		fcp->isp_fwoptions &= ~ICBOPT_FAIRNESS;	}	/*	 * We have to use FULL LOGIN even though it resets the loop too much	 * because otherwise port database entries don't get updated after	 * a LIP- this is a known f/w bug for 2100 f/w less than 1.17.0.	 */	if (ISP_FW_REVX(isp->isp_fwrev) < ISP_FW_REV(1, 17, 0)) {		fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN;	}	/*	 * Insist on Port Database Update Async notifications	 */	fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;	/*	 * Make sure that target role reflects into fwoptions.	 */	if (isp->isp_role & ISP_ROLE_TARGET) {		fcp->isp_fwoptions |= ICBOPT_TGT_ENABLE;	} else {		fcp->isp_fwoptions &= ~ICBOPT_TGT_ENABLE;	}	/*	 * Propagate all of this into the ICB structure.	 */	icbp->icb_fwoptions = fcp->isp_fwoptions;	icbp->icb_maxfrmlen = fcp->isp_maxfrmlen;	if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN ||	    icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {		isp_prt(isp, ISP_LOGERR,		    "bad frame length (%d) from NVRAM- using %d",		    fcp->isp_maxfrmlen, ICB_DFLT_FRMLEN);		icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;	}	icbp->icb_maxalloc = fcp->isp_maxalloc;	if (icbp->icb_maxalloc < 1) {		isp_prt(isp, ISP_LOGERR,		    "bad maximum allocation (%d)- using 16", fcp->isp_maxalloc);		icbp->icb_maxalloc = 16;	}	icbp->icb_execthrottle = fcp->isp_execthrottle;	if (icbp->icb_execthrottle < 1) {		isp_prt(isp, ISP_LOGERR,		    "bad execution throttle of %d- using 16",		    fcp->isp_execthrottle);		icbp->icb_execthrottle = ICB_DFLT_THROTTLE;	}	icbp->icb_retry_delay = fcp->isp_retry_delay;	icbp->icb_retry_count = fcp->isp_retry_count;	icbp->icb_hardaddr = loopid;	/*	 * Right now we just set extended options to prefer point-to-point	 * over loop based upon some soft config options.	 * 	 * NB: for the 2300, ICBOPT_EXTENDED is required.	 */	if (IS_2200(isp) || IS_23XX(isp)) {		icbp->icb_fwoptions |= ICBOPT_EXTENDED;		/*		 * Prefer or force Point-To-Point instead Loop?		 */		switch(isp->isp_confopts & ISP_CFG_PORT_PREF) {		case ISP_CFG_NPORT:			icbp->icb_xfwoptions |= ICBXOPT_PTP_2_LOOP;			break;		case ISP_CFG_NPORT_ONLY:			icbp->icb_xfwoptions |= ICBXOPT_PTP_ONLY;			break;		case ISP_CFG_LPORT_ONLY:			icbp->icb_xfwoptions |= ICBXOPT_LOOP_ONLY;			break;		default:			icbp->icb_xfwoptions |= ICBXOPT_LOOP_2_PTP;			break;		}		if (IS_23XX(isp)) {			if (IS_2300(isp) && isp->isp_revision < 2) {				icbp->icb_fwoptions &= ~ICBOPT_FAST_POST;			}			if (isp->isp_confopts & ISP_CFG_ONEGB) {				icbp->icb_zfwoptions |= ICBZOPT_RATE_ONEGB;			} else if (isp->isp_confopts & ISP_CFG_TWOGB) {				icbp->icb_zfwoptions |= ICBZOPT_RATE_TWOGB;			} else {				icbp->icb_zfwoptions |= ICBZOPT_RATE_AUTO;			}		}	}#ifndef	ISP_NO_RIO_FC	/*	 * RIO seems to be enabled in 2100s for fw >= 1.17.0.	 *	 * I've had some questionable problems with RIO on 2200.	 * More specifically, on a 2204 I had problems with RIO	 * on a Linux system where I was dropping commands right	 * and left. It's not clear to me what the actual problem	 * was, but it seems safer to only support this on the	 * 23XX cards.	 *	 * I have it disabled if we support a target mode role for	 * reasons I can't now remember.	 */	if ((isp->isp_role & ISP_ROLE_TARGET) == 0 && IS_23XX(isp)) {		icbp->icb_xfwoptions |= ICBXOPT_RIO_16BIT;		icbp->icb_racctimer = 4;		icbp->icb_idelaytimer = 8;	}#endif	if ((IS_2200(isp) && ISP_FW_REVX(isp->isp_fwrev) >=	    ISP_FW_REV(2, 1, 26)) || IS_23XX(isp)) {		/*		 * Turn on LIP F8 async event (1)		 * Turn on generate AE 8013 on all LIP Resets (2)		 * Disable LIP F7 switching (8)		 */		mbs.param[0] = MBOX_SET_FIRMWARE_OPTIONS;		mbs.param[1] = 0xb;		mbs.param[2] = 0;		mbs.param[3] = 0;		isp_mboxcmd(isp, &mbs, MBLOGALL);	}	icbp->icb_logintime = 30;	/* 30 second login timeout */	if (IS_23XX(isp)) {		ISP_WRITE(isp, isp->isp_rqstinrp, 0);        	ISP_WRITE(isp, isp->isp_rqstoutrp, 0);        	ISP_WRITE(isp, isp->isp_respinrp, 0);		ISP_WRITE(isp, isp->isp_respoutrp, 0);	}	nwwn = ISP_NODEWWN(isp);	pwwn = ISP_PORTWWN(isp);	if (nwwn && pwwn) {		icbp->icb_fwoptions |= ICBOPT_BOTH_WWNS;		MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, nwwn);		MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn);		isp_prt(isp, ISP_LOGDEBUG1,		    "Setting ICB Node 0x%08x%08x Port 0x%08x%08x",		    ((u_int32_t) (nwwn >> 32)),		    ((u_int32_t) (nwwn & 0xffffffff)),		    ((u_int32_t) (pwwn >> 32)),		    ((u_int32_t) (pwwn & 0xffffffff)));	} else {		isp_prt(isp, ISP_LOGDEBUG1, "Not using any WWNs");		icbp->icb_fwoptions &= ~(ICBOPT_BOTH_WWNS|ICBOPT_FULL_LOGIN);	}	icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);	icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp);	icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma);	icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma);	icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma);	icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma);	icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma);	icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma);	icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma);	icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);	isp_prt(isp, ISP_LOGDEBUG1,	    "isp_fibre_init: fwoptions 0x%x", fcp->isp_fwoptions);	FC_SCRATCH_ACQUIRE(isp);	isp_put_icb(isp, icbp, (isp_icb_t *)fcp->isp_scratch);	/*	 * Init the firmware	 */	mbs.param[0] = MBOX_INIT_FIRMWARE;	mbs.param[1] = 0;	mbs.param[2] = DMA_WD1(fcp->isp_scdma);	mbs.param[3] = DMA_WD0(fcp->isp_scdma);	mbs.param[4] = 0;	mbs.param[5] = 0;	mbs.param[6] = DMA_WD3(fcp->isp_scdma);	mbs.param[7] = DMA_WD2(fcp->isp_scdma);	isp_mboxcmd(isp, &mbs, MBLOGALL);	FC_SCRATCH_RELEASE(isp);	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {		return;	}	isp->isp_reqidx = isp->isp_reqodx = 0;	isp->isp_residx = 0;	isp->isp_sendmarker = 1;	/*	 * Whatever happens, we're now committed to being here.	 */	isp->isp_state = ISP_INITSTATE;}/* * Fibre Channel Support- get the port database for the id. * * Locks are held before coming here. Return 0 if success, * else failure. */static intisp_getmap(struct ispsoftc *isp, fcpos_map_t *map){	fcparam *fcp = (fcparam *) isp->isp_param;	mbreg_t mbs;	mbs.param[0] = MBOX_GET_FC_AL_POSITION_MAP;	mbs.param[1] = 0;	mbs.param[2] = DMA_WD1(fcp->isp_scdma);	mbs.param[3] = DMA_WD0(fcp->isp_scdma);	/*	 * Unneeded. For the 2100, except for initializing f/w, registers	 * 4/5 have to not be written to.	 *	mbs.param[4] = 0;	 *	mbs.param[5] = 0;	 *	 */	mbs.param[6] = 0;	mbs.param[7] = 0;	FC_SCRATCH_ACQUIRE(isp);	isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);	if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {		MEMCPY(map, fcp->isp_scratch, sizeof (fcpos_map_t));		map->fwmap = mbs.param[1] != 0;		FC_SCRATCH_RELEASE(isp);		return (0);	}	FC_SCRATCH_RELEASE(isp);	return (-1);}static voidisp_mark_getpdb_all(struct ispsoftc *isp){	fcparam *fcp = (fcparam *) isp->isp_param;	int i;	for (i = 0; i < MAX_FC_TARG; i++) {		fcp->portdb[i].valid = fcp->portdb[i].fabric_dev = 0;	}}static intisp_getpdb(struct ispsoftc *isp, int id, isp_pdb_t *pdbp){	fcparam *fcp = (fcparam *) isp->isp_param;	mbreg_t mbs;	mbs.param[0] = MBOX_GET_PORT_DB;	mbs.param[1] = id << 8;	mbs.param[2] = DMA_WD1(fcp->isp_scdma);	mbs.param[3] = DMA_WD0(fcp->isp_scdma);	/*	 * Unneeded. For the 2100, except for initializing f/w, registers	 * 4/5 have to not be written to.	 *	mbs.param[4] = 0;	 *	mbs.param[5] = 0;	 *	 */	mbs.param[6] = DMA_WD3(fcp->isp_scdma);	mbs.param[7] = DMA_WD2(fcp->isp_scdma);	FC_SCRATCH_ACQUIRE(isp);	isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);	if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {		isp_get_pdb(isp, (isp_pdb_t *)fcp->isp_scratch, pdbp);		FC_SCRATCH_RELEASE(isp);		return (0);	}	FC_SCRATCH_RELEASE(isp);	return (-1);}static u_int64_tisp_get_portname(struct ispsoftc *isp, int loopid, int nodename){	u_int64_t wwn = 0;	mbreg_t mbs;	mbs.param[0] = MBOX_GET_PORT_NAME;	mbs.param[1] = loopid << 8;	if (nodename)		mbs.param[1] |= 1;	isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);	if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {		wwn =		    (((u_int64_t)(mbs.param[2] & 0xff)) << 56) |		    (((u_int64_t)(mbs.param[2] >> 8))	<< 48) |		    (((u_int64_t)(mbs.param[3] & 0xff))	<< 40) |

⌨️ 快捷键说明

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