📄 isp_linux.c
字号:
} else { mhz = 0; } switch (flags & (DPARM_WIDE|DPARM_TQING)) { case DPARM_WIDE: wt = ", 16 bit wide"; break; case DPARM_TQING: wt = ", Tagged Queueing Enabled"; break; case DPARM_WIDE|DPARM_TQING: wt = ", 16 bit wide, Tagged Queueing Enabled"; break; default: wt = " "; break; } if (mhz) { isp_prt(isp, ISP_LOGINFO, "Channel %d Target %d at %dMHz Max Offset %d%s", bus, tgt, mhz, sdp->isp_devparam[tgt].actv_offset, wt); } else { isp_prt(isp, ISP_LOGINFO, "Channel %d Target %d Async Mode%s", bus, tgt, wt); } } break; case ISPASYNC_LIP: isp_prt(isp, ISP_LOGINFO, "LIP Received"); break; case ISPASYNC_LOOP_RESET: isp_prt(isp, ISP_LOGINFO, "Loop Reset Received"); break; case ISPASYNC_BUS_RESET: isp_prt(isp, ISP_LOGINFO, "SCSI bus %d reset detected", *((int *) arg)); break; case ISPASYNC_LOOP_DOWN: isp_prt(isp, ISP_LOGINFO, "Loop DOWN"); break; case ISPASYNC_LOOP_UP: isp_prt(isp, ISP_LOGINFO, "Loop UP"); break; case ISPASYNC_PROMENADE: { fcparam *fcp = isp->isp_param; struct lportdb *lp; int tgt; tgt = *((int *) arg); lp = &fcp->portdb[tgt]; if (lp->valid) { isp_prt(isp, ISP_LOGINFO, "ID %d (Loop 0x%x) Port WWN 0x%08x%08x arrived, role %s", tgt, lp->loopid, (unsigned int) (lp->port_wwn >> 32), (unsigned int) (lp->port_wwn & 0xffffffff), class3_roles[fcp->portdb[tgt].roles]); } else { isp_prt(isp, ISP_LOGINFO, "ID %d (Loop 0x%x) Port WWN 0x%08x%08x departed", tgt, lp->loopid, (unsigned int) (lp->port_wwn >> 32), (unsigned int) (lp->port_wwn & 0xffffffff)); } break; } case ISPASYNC_CHANGE_NOTIFY: if (arg == ISPASYNC_CHANGE_PDB) { isp_prt(isp, ISP_LOGINFO, "Port Database Changed"); } else if (arg == ISPASYNC_CHANGE_SNS) { isp_prt(isp, ISP_LOGINFO, "Name Server Database Changed"); } SEND_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, 0); break; case ISPASYNC_FABRIC_DEV: { int target, base, lim; fcparam *fcp = isp->isp_param; struct lportdb *lp = NULL; struct lportdb *clp = (struct lportdb *) arg; char *pt; switch (clp->port_type) { case 1: pt = " N_Port"; break; case 2: pt = " NL_Port"; break; case 3: pt = "F/NL_Port"; break; case 0x7f: pt = " Nx_Port"; break; case 0x81: pt = " F_port"; break; case 0x82: pt = " FL_Port"; break; case 0x84: pt = " E_port"; break; default: pt = " "; break; } isp_prt(isp, ISP_LOGINFO, "%s Fabric Device @ PortID 0x%x", pt, clp->portid); /* * If we don't have an initiator role we bail. * * We just use ISPASYNC_FABRIC_DEV for announcement purposes. */ if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) { break; } /* * Is this entry for us? If so, we bail. */ if (fcp->isp_portid == clp->portid) { break; } /* * Else, the default policy is to find room for it in * our local port database. Later, when we execute * the call to isp_pdb_sync either this newly arrived * or already logged in device will be (re)announced. */ if (fcp->isp_topo == TOPO_FL_PORT) base = FC_SNS_ID+1; else base = 0; if (fcp->isp_topo == TOPO_N_PORT) lim = 1; else lim = MAX_FC_TARG; /* * Is it already in our list? */ for (target = base; target < lim; target++) { if (target >= FL_PORT_ID && target <= FC_SNS_ID) { continue; } lp = &fcp->portdb[target]; if (lp->port_wwn == clp->port_wwn && lp->node_wwn == clp->node_wwn) { lp->fabric_dev = 1; break; } } if (target < lim) { break; } for (target = base; target < lim; target++) { if (target >= FL_PORT_ID && target <= FC_SNS_ID) { continue; } lp = &fcp->portdb[target]; if (lp->port_wwn == 0) { break; } } if (target == lim) { isp_prt(isp, ISP_LOGWARN, "out of space for fabric devices"); break; } lp->port_type = clp->port_type; lp->fc4_type = clp->fc4_type; lp->node_wwn = clp->node_wwn; lp->port_wwn = clp->port_wwn; lp->portid = clp->portid; lp->fabric_dev = 1; break; }#ifdef LINUX_ISP_TARGET_MODE case ISPASYNC_TARGET_MESSAGE: { tmd_msg_t *mp = arg; isp_prt(isp, ISP_LOGTDEBUG2, "bus %d iid %d tgt %d lun %d ttype %x tval %x msg[0]=%x", mp->nt_bus, (int) mp->nt_iid, (int) mp->nt_tgt, (int) mp->nt_lun, mp->nt_tagtype, mp->nt_tagval, mp->nt_msg[0]); break; } case ISPASYNC_TARGET_EVENT: { tmd_event_t *ep = arg; isp_prt(isp, ISP_LOGTDEBUG2, "bus %d event code 0x%x", ep->ev_bus, ep->ev_event); break; } case ISPASYNC_TARGET_ACTION: switch (((isphdr_t *)arg)->rqs_entry_type) { default: isp_prt(isp, ISP_LOGWARN, "event 0x%x for unhandled target action", ((isphdr_t *)arg)->rqs_entry_type); break; case RQSTYPE_ATIO: (void) isp_handle_platform_atio(isp, (at_entry_t *) arg); break; case RQSTYPE_ATIO2: (void) isp_handle_platform_atio2(isp, (at2_entry_t *)arg); break; case RQSTYPE_CTIO2: case RQSTYPE_CTIO: (void) isp_handle_platform_ctio(isp, arg); break; case RQSTYPE_ENABLE_LUN: case RQSTYPE_MODIFY_LUN: isp->isp_osinfo.rstatus = ((lun_entry_t *)arg)->le_status; if (isp->isp_osinfo.rsemap) { up(isp->isp_osinfo.rsemap); } break; } break;#endif case ISPASYNC_FW_CRASH: { u_int16_t mbox1, mbox6; mbox1 = ISP_READ(isp, OUTMAILBOX1); if (IS_DUALBUS(isp)) { mbox6 = ISP_READ(isp, OUTMAILBOX6); } else { mbox6 = 0; } isp_prt(isp, ISP_LOGERR, "Internal F/W Error on bus %d @ RISC Address 0x%x", mbox6, mbox1); if (IS_FC(isp)) { /* XXX isp->isp_blocked = 1; */ SEND_THREAD_EVENT(isp, ISP_THREAD_FW_CRASH_DUMP, 0); } break; } case ISPASYNC_UNHANDLED_RESPONSE: break; default: return (-1); } return (0);}intisplinux_biosparam(Disk *disk, kdev_t n, int ip[]){ int size = disk->capacity; ip[0] = 64; ip[1] = 32; ip[2] = size >> 11; if (ip[2] > 1024) { ip[0] = 255; ip[1] = 63; ip[2] = size / (ip[0] * ip[1]); } return (0);}/* * Set the queue depth for this device. */voidisplinux_sqd(struct Scsi_Host *host, Scsi_Device *devs){ while (devs) { if (devs->host == host && devs->tagged_supported == 0) { /* * If this device doesn't support tagged operations, don't waste * queue space for it, even if it has multiple luns. */ devs->queue_depth = 2; } else if (devs->host == host) { int depth = 2; struct ispsoftc *isp = (struct ispsoftc *) host->hostdata; if (IS_SCSI(isp)) { sdparam *sdp = isp->isp_param; sdp += devs->channel; depth = sdp->isp_devparam[devs->id].exc_throttle; } else { depth = FCPARAM(isp)->isp_execthrottle; } if (isp_throttle) { /* * This limit is due to the size of devs->queue_depth */ depth = (unsigned char) min(isp_throttle, 255);; } if (depth < 4) { depth = 4; } devs->queue_depth = depth; } devs = devs->next; }}/* * Periodic watchdog timer.. the main purpose here is to restart * commands that were pegged on resources, etc... */voidisplinux_timer(unsigned long arg){ Scsi_Cmnd *Cmnd; struct ispsoftc *isp = (struct ispsoftc *) arg; ISP_ILOCK_SOFTC(isp); if (IS_FC(isp)) { int rql; if (isp->isp_role & ISP_ROLE_INITIATOR) rql = LOOP_READY; else rql = LOOP_LSCAN_DONE; if (isp->isp_fcrswdog || FCPARAM(isp)->isp_fwstate != FW_READY || FCPARAM(isp)->isp_loopstate < rql) { isp->isp_fcrswdog = 0; if (isp->isp_deadloop == 0 && isp->isp_role != ISP_ROLE_NONE) { SEND_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, 0); } } } isplinux_runwaitq(isp); if ((Cmnd = isp->isp_osinfo.dqnext) != NULL) { isp->isp_osinfo.dqnext = isp->isp_osinfo.dqtail = NULL; } if (isp->dogactive) { isp->isp_osinfo.timer.expires = jiffies + ISP_WATCH_TIME; add_timer(&isp->isp_osinfo.timer); } ISP_IUNLK_SOFTC(isp); if (Cmnd) { ISP_LOCK_SCSI_DONE(isp); while (Cmnd) { Scsi_Cmnd *f = (Scsi_Cmnd *) Cmnd->host_scribble; Cmnd->host_scribble = NULL; /* * Get around silliness in midlayer. */ if (host_byte(Cmnd->result) == DID_RESET) { Cmnd->flags |= IS_RESETTING; } (*Cmnd->scsi_done)(Cmnd); Cmnd = f; } ISP_UNLK_SCSI_DONE(isp); }}voidisplinux_mbtimer(unsigned long arg){ struct ispsoftc *isp = (struct ispsoftc *) arg; ISP_ILOCK_SOFTC(isp); if (isp->mbox_waiting) { isp->mbox_waiting = 0; up(&isp->mbox_c_sem); } ISP_IUNLK_SOFTC(isp);}voidisplinux_intr(int irq, void *arg, struct pt_regs *pt){ struct ispsoftc *isp = arg; u_int16_t isr, sema, mbox; Scsi_Cmnd *Cmnd; ISP_ILOCK_SOFTC(isp); isp->isp_intcnt++; if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) { isp->isp_intbogus++; ISP_IUNLK_SOFTC(isp); return; } isp_intr(isp, isr, sema, mbox); isplinux_runwaitq(isp); if ((Cmnd = isp->isp_osinfo.dqnext) != NULL) { isp->isp_osinfo.dqnext = isp->isp_osinfo.dqtail = NULL; }#ifdef LINUX_ISP_TARGET_MODE if (isp->isp_osinfo.pending_t) { struct tmd_cmd *tmd = isp->isp_osinfo.pending_t; isp->isp_osinfo.pending_t = NULL; ISP_IUNLK_SOFTC(isp); do { struct tmd_cmd *next = tmd->cd_private; tmd->cd_private = isp->isp_osinfo.hcb_token; (*isp->isp_osinfo.hcb)(tmd->cd_reserved[0], tmd); tmd = next; } while (tmd != NULL); } else { ISP_IUNLK_SOFTC(isp); }#else ISP_IUNLK_SOFTC(isp);#endif if (Cmnd) { ISP_LOCK_SCSI_DONE(isp); while (Cmnd) { Scsi_Cmnd *f = (Scsi_Cmnd *) Cmnd->host_scribble; Cmnd->host_scribble = NULL; /* * Get around silliness in midlayer. */ if (host_byte(Cmnd->result) == DID_RESET) { Cmnd->flags |= IS_RESETTING; } (*Cmnd->scsi_done)(Cmnd); Cmnd = f; } ISP_UNLK_SCSI_DONE(isp); }}static INLINE intisp_parse_rolearg(struct ispsoftc *isp, char *roles){ char *role = roles; while (role && *role) { unsigned int id; char *eqtok, *commatok, *p, *q; eqtok = role; eqtok = strchr(role, '='); if (eqtok == NULL) break; *eqtok = 0; commatok = strchr(eqtok+1, ','); if (commatok) *commatok = 0; if (strncmp(role, "0x", 2) == 0) q = role + 2; else q = role; id = simple_strtoul(q, &p, 16); *eqtok = '='; if (p != q && id == isp->isp_osinfo.device_id) { p = eqtok + 1; if (strcmp(p, "none") == 0) { if (commatok) { *commatok = ','; } return (ISP_ROLE_NONE); } if (strcmp(p, "target") == 0) { if (commatok) { *commatok = ','; } return (ISP_ROLE_TARGET); } if (strcmp(p, "initiator") == 0) { if (commatok) { *commatok = ','; } return (ISP_ROLE_INITIATOR); } if (strcmp(p, "both") == 0) { if (commatok) { *commatok = ','; } return (ISP_ROLE_BOTH); } break; } if (commatok) { role = commatok+1; *commatok = ','; } else { break; } } return (ISP_DEFAULT_ROLES);}static INLINE u_int64_tisp_parse_wwnarg(struct ispsoftc *isp, char *wwns){ char *wwnt = wwns;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -