diff options
author | mjacob <mjacob@FreeBSD.org> | 2006-11-18 03:53:16 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 2006-11-18 03:53:16 +0000 |
commit | 5af654c5862709158954dcd905ab90b7b4543c24 (patch) | |
tree | 786890bd8855d5539d11081e2bf6044e5553adbf | |
parent | edc10a6695602b387851a4829c5b186ed1053cd2 (diff) | |
download | FreeBSD-src-5af654c5862709158954dcd905ab90b7b4543c24.zip FreeBSD-src-5af654c5862709158954dcd905ab90b7b4543c24.tar.gz |
Make the SAN login/logout stuff more common between different chipsets
and provied an isp_control entry point so that the outer layers can
do PLOGI/LOGO explicitly. Add MS IOCB support. This completes the cycle
for base support for SMI-S.
-rw-r--r-- | sys/dev/isp/isp.c | 142 | ||||
-rw-r--r-- | sys/dev/isp/isp_library.c | 60 | ||||
-rw-r--r-- | sys/dev/isp/isp_library.h | 4 | ||||
-rw-r--r-- | sys/dev/isp/isp_pci.c | 6 | ||||
-rw-r--r-- | sys/dev/isp/ispmbox.h | 35 | ||||
-rw-r--r-- | sys/dev/isp/ispvar.h | 3 |
6 files changed, 175 insertions, 75 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index fb19d93..52a4052 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -114,9 +114,9 @@ static void isp_scsi_channel_init(ispsoftc_t *, int); static void isp_fibre_init(ispsoftc_t *); static void isp_fibre_init_2400(ispsoftc_t *); static void isp_mark_portdb(ispsoftc_t *, int); -static void isp_plogx_24xx(ispsoftc_t *, uint16_t, uint32_t, int *); +static int isp_plogx(ispsoftc_t *, uint16_t, uint32_t, int, int); static int isp_port_login(ispsoftc_t *, uint16_t, uint32_t); -static void isp_port_logout(ispsoftc_t *, uint16_t, uint32_t); +static int isp_port_logout(ispsoftc_t *, uint16_t, uint32_t); static int isp_getpdb(ispsoftc_t *, uint16_t, isp_pdb_t *, int); static uint64_t isp_get_portname(ispsoftc_t *, int, int); static int isp_fclink_test(ispsoftc_t *, int); @@ -2083,36 +2083,47 @@ isp_mark_portdb(ispsoftc_t *isp, int onprobation) /* * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards + * or via FABRIC LOGIN/FABRIC LOGOUT for other cards. */ -static void -isp_plogx_24xx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int *log_ret) +static int +isp_plogx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int flags, int gs) { mbreg_t mbs; uint8_t q[QENTRY_LEN]; - isp_plogx_t *plp = (isp_plogx_t *) q; - uint8_t *scp = FCPARAM(isp)->isp_scratch; + isp_plogx_t *plp; + uint8_t *scp; uint32_t sst, parm1; - int junk; + int rval; + + if (!IS_24XX(isp)) { + int action = flags & PLOGX_FLG_CMD_MASK; + if (action == PLOGX_FLG_CMD_PLOGI) { + return (isp_port_login(isp, handle, portid)); + } else if (action == PLOGX_FLG_CMD_LOGO) { + return (isp_port_logout(isp, handle, portid)); + } else { + return (MBOX_INVALID_COMMAND); + } + } MEMZERO(q, QENTRY_LEN); + plp = (isp_plogx_t *) q; plp->plogx_header.rqs_entry_count = 1; plp->plogx_header.rqs_entry_type = RQSTYPE_LOGIN; plp->plogx_handle = 0xffffffff; plp->plogx_nphdl = handle; plp->plogx_portlo = portid; plp->plogx_rspsz_porthi = (portid >> 16) & 0xff; - if (log_ret) { - plp->plogx_flags = *log_ret; - } else { - log_ret = &junk; - } + plp->plogx_flags = flags; if (isp->isp_dblev & ISP_LOGDEBUG1) { isp_print_bytes(isp, "IOCB LOGX", QENTRY_LEN, plp); } - /* - * XXX: We're going to assume somebody has acquired SCRATCH for us - */ + + if (gs == 0) { + FC_SCRATCH_ACQUIRE(isp); + } + scp = FCPARAM(isp)->isp_scratch; isp_put_plogx(isp, plp, (isp_plogx_t *) scp); @@ -2128,7 +2139,8 @@ isp_plogx_24xx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int *log_ret) MEMORYBARRIER(isp, SYNC_SFORDEV, 0, QENTRY_LEN); isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - *log_ret = mbs.param[0]; + rval = mbs.param[0]; + goto out; } MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN); scp += QENTRY_LEN; @@ -2138,19 +2150,19 @@ isp_plogx_24xx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int *log_ret) } if (plp->plogx_status == PLOGX_STATUS_OK) { - *log_ret = 0; - return; + rval = 0; + goto out; } else if (plp->plogx_status != PLOGX_STATUS_IOCBERR) { isp_prt(isp, ISP_LOGWARN, "status 0x%x on port login IOCB", plp->plogx_status); - *log_ret = -1; - return; + rval = -1; + goto out; } sst = plp->plogx_ioparm[0].lo16 | (plp->plogx_ioparm[0].hi16 << 16); parm1 = plp->plogx_ioparm[1].lo16 | (plp->plogx_ioparm[1].hi16 << 16); - *log_ret = -1; + rval = -1; switch (sst) { case PLOGX_IOCBERR_NOLINK: @@ -2166,8 +2178,8 @@ isp_plogx_24xx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int *log_ret) case PLOGX_IOCBERR_FAILED: isp_prt(isp, ISP_LOGERR, "PLOGX(0x%x) of Port 0x%06x failed: reason 0x%x (last LOGIN" - " state 0x%x)", *log_ret, portid, - parm1 & 0xff, (parm1 >> 8) & 0xff); + " state 0x%x)", flags, portid, parm1 & 0xff, + (parm1 >> 8) & 0xff); break; case PLOGX_IOCBERR_NOFABRIC: isp_prt(isp, ISP_LOGERR, "PLOGX failed- no fabric"); @@ -2179,7 +2191,7 @@ isp_plogx_24xx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int *log_ret) isp_prt(isp, ISP_LOGERR, "PLOGX failed- not logged in (last LOGIN state 0x%x)", parm1); - *log_ret = MBOX_NOT_LOGGED_IN; + rval = MBOX_NOT_LOGGED_IN; break; case PLOGX_IOCBERR_REJECT: isp_prt(isp, ISP_LOGERR, "PLOGX failed: LS_RJT = 0x%x", parm1); @@ -2195,13 +2207,13 @@ isp_plogx_24xx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int *log_ret) isp_prt(isp, ISP_LOGDEBUG0, "portid 0x%x already logged in with N-port handle 0x%x", portid, parm1); - *log_ret = MBOX_PORT_ID_USED | (handle << 16); + rval = MBOX_PORT_ID_USED | (handle << 16); break; case PLOGX_IOCBERR_HNDLUSED: isp_prt(isp, ISP_LOGDEBUG0, "N-port handle 0x%x already used for portid 0x%x", handle, parm1); - *log_ret = MBOX_LOOP_ID_USED; + rval = MBOX_LOOP_ID_USED; break; case PLOGX_IOCBERR_NOHANDLE: isp_prt(isp, ISP_LOGERR, "PLOGX failed- no handle allocated"); @@ -2210,11 +2222,16 @@ isp_plogx_24xx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int *log_ret) isp_prt(isp, ISP_LOGERR, "PLOGX failed- no FLOGI_ACC"); break; default: - isp_prt(isp, ISP_LOGERR, "status %x from %s", plp->plogx_status, - (*log_ret)? "PLOGI" : "LOGO"); - *log_ret = -1; + isp_prt(isp, ISP_LOGERR, "status %x from %x", plp->plogx_status, + flags); + rval = -1; break; } +out: + if (gs == 0) { + FC_SCRATCH_RELEASE(isp); + } + return (rval); } static int @@ -2239,14 +2256,14 @@ isp_port_login(ispsoftc_t *isp, uint16_t handle, uint32_t portid) switch (mbs.param[0]) { case MBOX_PORT_ID_USED: isp_prt(isp, ISP_LOGDEBUG0, - "isp_port_login: portid 0x%06x already logged in as %u", + "isp_plogi_old: portid 0x%06x already logged in as %u", portid, mbs.param[1]); return (MBOX_PORT_ID_USED | (mbs.param[1] << 16)); break; case MBOX_LOOP_ID_USED: isp_prt(isp, ISP_LOGDEBUG0, - "isp_port_login: handle %u in use for port id 0x%02xXXXX", + "isp_plogi_old: handle %u in use for port id 0x%02xXXXX", handle, mbs.param[1] & 0xff); return (MBOX_LOOP_ID_USED); @@ -2255,24 +2272,24 @@ isp_port_login(ispsoftc_t *isp, uint16_t handle, uint32_t portid) case MBOX_COMMAND_ERROR: isp_prt(isp, ISP_LOGINFO, - "isp_port_login: error 0x%x in PLOGI to port 0x%06x", + "isp_plogi_old: error 0x%x in PLOGI to port 0x%06x", mbs.param[1], portid); return (MBOX_COMMAND_ERROR); case MBOX_ALL_IDS_USED: isp_prt(isp, ISP_LOGINFO, - "isp_port_login: all IDs used for fabric login"); + "isp_plogi_old: all IDs used for fabric login"); return (MBOX_ALL_IDS_USED); default: isp_prt(isp, ISP_LOGINFO, - "isp_port_login: error 0x%x on port login of 0x%06x@0x%0x", + "isp_plogi_old: error 0x%x on port login of 0x%06x@0x%0x", mbs.param[0], portid, handle); return (mbs.param[0]); } } -static void +static int isp_port_logout(ispsoftc_t *isp, uint16_t handle, uint32_t portid) { mbreg_t mbs; @@ -2288,6 +2305,7 @@ isp_port_logout(ispsoftc_t *isp, uint16_t handle, uint32_t portid) mbs.logval = MBLOGNONE; mbs.timeout = 100000; isp_mboxcmd(isp, &mbs); + return (mbs.param[0] == MBOX_COMMAND_COMPLETE? 0 : mbs.param[0]); } static int @@ -2725,19 +2743,10 @@ isp_pdb_sync(ispsoftc_t *isp) lp->state = FC_PORTDB_STATE_NIL; isp_async(isp, ISPASYNC_DEV_GONE, lp); if (lp->autologin == 0) { - if (IS_24XX(isp)) { - int action = - PLOGX_FLG_CMD_LOGO | - PLOGX_FLG_IMPLICIT | - PLOGX_FLG_FREE_NPHDL; - FC_SCRATCH_ACQUIRE(isp); - isp_plogx_24xx(isp, lp->handle, - lp->portid, &action); - FC_SCRATCH_RELEASE(isp); - } else { - isp_port_logout(isp, lp->handle, - lp->portid); - } + (void) isp_plogx(isp, lp->handle, lp->portid, + PLOGX_FLG_CMD_LOGO | + PLOGX_FLG_IMPLICIT | + PLOGX_FLG_FREE_NPHDL, 0); } else { lp->autologin = 0; } @@ -2987,7 +2996,7 @@ isp_scan_loop(ispsoftc_t *isp) lp->new_roles = tmp.roles; lp->state = FC_PORTDB_STATE_PENDING_VALID; isp_prt(isp, ISP_LOGSANCFG, - "Loop Port 0x%06x@0x%x Pending Valid", + "Loop Port 0x%02x@0x%x Pending Valid", tmp.portid, tmp.handle); break; } @@ -3686,7 +3695,7 @@ isp_scan_fabric(ispsoftc_t *isp) static int isp_login_device(ispsoftc_t *isp, uint32_t portid, isp_pdb_t *p, uint16_t *ohp) { - int lim, i, r, logval; + int lim, i, r; uint16_t handle; if (IS_24XX(isp)) { @@ -3704,14 +3713,8 @@ isp_login_device(ispsoftc_t *isp, uint32_t portid, isp_pdb_t *p, uint16_t *ohp) */ r = isp_getpdb(isp, handle, p, 0); if (r == 0 && p->portid != portid) { - if (IS_24XX(isp)) { - logval = - PLOGX_FLG_CMD_LOGO | - PLOGX_FLG_IMPLICIT; - isp_plogx_24xx(isp, handle, portid, &logval); - } else { - isp_port_logout(isp, handle, portid); - } + (void) isp_plogx(isp, handle,portid, + PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT, 1); } else if (r == 0) { break; } @@ -3721,22 +3724,17 @@ isp_login_device(ispsoftc_t *isp, uint32_t portid, isp_pdb_t *p, uint16_t *ohp) /* * Now try and log into the device */ - if (IS_24XX(isp)) { - logval = PLOGX_FLG_CMD_PLOGI; - isp_plogx_24xx(isp, handle, portid, &logval); - } else { - logval = isp_port_login(isp, handle, portid); - } + r = isp_plogx(isp, handle, portid, PLOGX_FLG_CMD_PLOGI, 1); if (FCPARAM(isp)->isp_loopstate != LOOP_SCANNING_FABRIC) { return (-1); } - if (logval == 0) { + if (r == 0) { *ohp = handle; break; - } else if ((logval & 0xffff) == MBOX_PORT_ID_USED) { - handle = logval >> 16; + } else if ((r & 0xffff) == MBOX_PORT_ID_USED) { + handle = r >> 16; break; - } else if (logval != MBOX_LOOP_ID_USED) { + } else if (r != MBOX_LOOP_ID_USED) { i = lim; break; } else { @@ -3929,6 +3927,9 @@ isp_nxt_handle(ispsoftc_t *isp, uint16_t handle) } } else { handle += 1; + if (handle == NPH_MGT_ID) { + handle++; + } if (handle >= FL_ID && handle <= SNS_ID) { handle = SNS_ID+1; } else if (IS_24XX(isp)) { @@ -4423,6 +4424,11 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg) isp_mboxcmd(isp, arg); return(0); + case ISPCTL_PLOGX: + { + isp_plcmd_t *p = arg; + return (isp_plogx(isp, p->handle, p->portid, p->flags, 0)); + } #ifdef ISP_TARGET_MODE case ISPCTL_TOGGLE_TMODE: { diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c index 0bba226..e99eadf 100644 --- a/sys/dev/isp/isp_library.c +++ b/sys/dev/isp/isp_library.c @@ -1038,6 +1038,36 @@ isp_get_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *src, isp_ct_pt_t *dst) } void +isp_get_ms(ispsoftc_t *isp, isp_ms_t *src, isp_ms_t *dst) +{ + int i; + + isp_get_hdr(isp, &src->ms_header, &dst->ms_header); + ISP_IOXGET_32(isp, &src->ms_handle, dst->ms_handle); + ISP_IOXGET_16(isp, &src->ms_nphdl, dst->ms_nphdl); + ISP_IOXGET_16(isp, &src->ms_status, dst->ms_status); + ISP_IOXGET_16(isp, &src->ms_flags, dst->ms_flags); + ISP_IOXGET_16(isp, &src->ms_reserved1, dst->ms_reserved1); + ISP_IOXGET_16(isp, &src->ms_time, dst->ms_time); + ISP_IOXGET_16(isp, &src->ms_cmd_cnt, dst->ms_cmd_cnt); + ISP_IOXGET_16(isp, &src->ms_tot_cnt, dst->ms_tot_cnt); + ISP_IOXGET_8(isp, &src->ms_type, dst->ms_type); + ISP_IOXGET_8(isp, &src->ms_r_ctl, dst->ms_r_ctl); + ISP_IOXGET_16(isp, &src->ms_rxid, dst->ms_rxid); + ISP_IOXGET_16(isp, &src->ms_reserved2, dst->ms_reserved2); + ISP_IOXGET_32(isp, &src->ms_rsp_bcnt, dst->ms_rsp_bcnt); + ISP_IOXGET_32(isp, &src->ms_cmd_bcnt, dst->ms_cmd_bcnt); + for (i = 0; i < 2; i++) { + ISP_IOXGET_32(isp, &src->ms_dataseg[i].ds_base, + dst->ms_dataseg[i].ds_base); + ISP_IOXGET_32(isp, &src->ms_dataseg[i].ds_basehi, + dst->ms_dataseg[i].ds_basehi); + ISP_IOXGET_32(isp, &src->ms_dataseg[i].ds_count, + dst->ms_dataseg[i].ds_count); + } +} + +void isp_put_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *src, isp_ct_pt_t *dst) { int i; @@ -1067,6 +1097,36 @@ isp_put_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *src, isp_ct_pt_t *dst) } } +void +isp_put_ms(ispsoftc_t *isp, isp_ms_t *src, isp_ms_t *dst) +{ + int i; + + isp_put_hdr(isp, &src->ms_header, &dst->ms_header); + ISP_IOXPUT_32(isp, src->ms_handle, &dst->ms_handle); + ISP_IOXPUT_16(isp, src->ms_nphdl, &dst->ms_nphdl); + ISP_IOXPUT_16(isp, src->ms_status, &dst->ms_status); + ISP_IOXPUT_16(isp, src->ms_flags, &dst->ms_flags); + ISP_IOXPUT_16(isp, src->ms_reserved1, &dst->ms_reserved1); + ISP_IOXPUT_16(isp, src->ms_time, &dst->ms_time); + ISP_IOXPUT_16(isp, src->ms_cmd_cnt, &dst->ms_cmd_cnt); + ISP_IOXPUT_16(isp, src->ms_tot_cnt, &dst->ms_tot_cnt); + ISP_IOXPUT_8(isp, src->ms_type, &dst->ms_type); + ISP_IOXPUT_8(isp, src->ms_r_ctl, &dst->ms_r_ctl); + ISP_IOXPUT_16(isp, src->ms_rxid, &dst->ms_rxid); + ISP_IOXPUT_16(isp, src->ms_reserved2, &dst->ms_reserved2); + ISP_IOXPUT_32(isp, src->ms_rsp_bcnt, &dst->ms_rsp_bcnt); + ISP_IOXPUT_32(isp, src->ms_cmd_bcnt, &dst->ms_cmd_bcnt); + for (i = 0; i < 2; i++) { + ISP_IOXPUT_32(isp, src->ms_dataseg[i].ds_base, + &dst->ms_dataseg[i].ds_base); + ISP_IOXPUT_32(isp, src->ms_dataseg[i].ds_basehi, + &dst->ms_dataseg[i].ds_basehi); + ISP_IOXPUT_32(isp, src->ms_dataseg[i].ds_count, + &dst->ms_dataseg[i].ds_count); + } +} + /* * Generic SNS request - not particularly useful since the per-command data * isn't always 16 bit words. diff --git a/sys/dev/isp/isp_library.h b/sys/dev/isp/isp_library.h index 2c4b013..18ec1ce 100644 --- a/sys/dev/isp/isp_library.h +++ b/sys/dev/isp/isp_library.h @@ -91,8 +91,12 @@ isp_put_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *); extern void isp_get_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *); extern void +isp_get_ms(ispsoftc_t *isp, isp_ms_t *, isp_ms_t *); +extern void isp_put_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *); extern void +isp_put_ms(ispsoftc_t *isp, isp_ms_t *, isp_ms_t *); +extern void isp_put_sns_request(ispsoftc_t *, sns_screq_t *, sns_screq_t *); extern void isp_put_gid_ft_request(ispsoftc_t *, sns_gid_ft_req_t *, diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c index ee62276..2f9c9a5 100644 --- a/sys/dev/isp/isp_pci.c +++ b/sys/dev/isp/isp_pci.c @@ -1057,7 +1057,6 @@ isp_pci_attach(device_t dev) cmd &= ~PCIM_CMD_INTX_DISABLE; } -#ifdef WE_KNEW_WHAT_WE_WERE_DOING if (IS_24XX(isp)) { int reg; @@ -1089,11 +1088,6 @@ isp_pci_attach(device_t dev) pci_write_config(dev, reg, 2, pectl); } } -#else - if (IS_24XX(isp)) { - cmd &= ~PCIM_CMD_INTX_DISABLE; - } -#endif pci_write_config(dev, PCIR_COMMAND, cmd, 2); diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h index 6ee4fa3..f72ac07 100644 --- a/sys/dev/isp/ispmbox.h +++ b/sys/dev/isp/ispmbox.h @@ -329,6 +329,7 @@ typedef struct { #define RQSTYPE_IP_RECV 0x23 #define RQSTYPE_IP_RECV_CONT 0x24 #define RQSTYPE_CT_PASSTHRU 0x29 +#define RQSTYPE_MS_PASSTHRU 0x29 #define RQSTYPE_ABORT_IO 0x33 #define RQSTYPE_T6RQS 0x48 #define RQSTYPE_LOGIN 0x52 @@ -631,6 +632,29 @@ typedef struct { ispds64_t ctp_dataseg[2]; } isp_ct_pt_t; +/* + * MS Passthru IOCB + */ +typedef struct { + isphdr_t ms_header; + uint32_t ms_handle; + uint16_t ms_nphdl; /* XXX: Note, this is for 2K Logins only */ + uint16_t ms_status; + uint16_t ms_flags; + uint16_t ms_reserved1; /* low 8 bits */ + uint16_t ms_time; + uint16_t ms_cmd_cnt; /* Command DSD count */; + uint16_t ms_tot_cnt; /* Total DSD Count */ + uint8_t ms_type; /* MS type */ + uint8_t ms_r_ctl; /* R_CTL */ + uint16_t ms_rxid; /* RX_ID */ + uint16_t ms_reserved2; + uint32_t ms_handle2; + uint32_t ms_rsp_bcnt; /* Response byte count */ + uint32_t ms_cmd_bcnt; /* Command byte count */ + ispds64_t ms_dataseg[2]; +} isp_ms_t; + /* * Completion Status Codes. */ @@ -1108,6 +1132,17 @@ typedef struct { } isp_pdb_t; /* + * Genericized Port Login/Logout software structure + */ +typedef struct { + uint16_t handle; + uint32_t + flags : 8, + portid : 24; +} isp_plcmd_t; +/* the flags to use are those for PLOGX_FLG_* below */ + +/* * ISP24XX- Login/Logout Port IOCB */ typedef struct { diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index 72d3da3..e79c525 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -791,7 +791,8 @@ typedef enum { ISPCTL_GET_PORTNAME, /* get portname from an N-port handle */ ISPCTL_RUN_MBOXCMD, /* run a mailbox command */ ISPCTL_TOGGLE_TMODE, /* toggle target mode */ - ISPCTL_GET_PDB /* get a single port database entry */ + ISPCTL_GET_PDB, /* get a single port database entry */ + ISPCTL_PLOGX /* do a port login/logout */ } ispctl_t; int isp_control(ispsoftc_t *, ispctl_t, void *); |