?? isp.c
字號:
* 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 + -