Deleted Added
full compact
isp.c (291014) isp.c (291080)
1/*-
2 * Copyright (c) 1997-2009 by Matthew Jacob
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *

--- 33 unchanged lines hidden (view full) ---

42 */
43#ifdef __NetBSD__
44#include <sys/cdefs.h>
45__KERNEL_RCSID(0, "$NetBSD$");
46#include <dev/ic/isp_netbsd.h>
47#endif
48#ifdef __FreeBSD__
49#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1997-2009 by Matthew Jacob
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *

--- 33 unchanged lines hidden (view full) ---

42 */
43#ifdef __NetBSD__
44#include <sys/cdefs.h>
45__KERNEL_RCSID(0, "$NetBSD$");
46#include <dev/ic/isp_netbsd.h>
47#endif
48#ifdef __FreeBSD__
49#include <sys/cdefs.h>
50__FBSDID("$FreeBSD: head/sys/dev/isp/isp.c 291014 2015-11-18 12:39:20Z mav $");
50__FBSDID("$FreeBSD: head/sys/dev/isp/isp.c 291080 2015-11-19 17:43:47Z mav $");
51#include <dev/isp/isp_freebsd.h>
52#endif
53#ifdef __OpenBSD__
54#include <dev/ic/isp_openbsd.h>
55#endif
56#ifdef __linux__
57#include "isp_linux.h"
58#endif

--- 4 unchanged lines hidden (view full) ---

63/*
64 * General defines
65 */
66#define MBOX_DELAY_COUNT 1000000 / 100
67
68/*
69 * Local static data
70 */
51#include <dev/isp/isp_freebsd.h>
52#endif
53#ifdef __OpenBSD__
54#include <dev/ic/isp_openbsd.h>
55#endif
56#ifdef __linux__
57#include "isp_linux.h"
58#endif

--- 4 unchanged lines hidden (view full) ---

63/*
64 * General defines
65 */
66#define MBOX_DELAY_COUNT 1000000 / 100
67
68/*
69 * Local static data
70 */
71static const char fconf[] = "Chan %d PortDB[%d] changed:\n current =(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)\n database=(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)";
72static const char notresp[] = "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d";
71static const char notresp[] = "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d";
73static const char topology[] = "Chan %d WWPN 0x%08x%08x PortID 0x%06x LoopID 0x%x Connection '%s'";
74static const char bun[] = "bad underrun (count %d, resid %d, status %s)";
75static const char lipd[] = "Chan %d LIP destroyed %d active commands";
76static const char sacq[] = "unable to acquire scratch area";
77
78static const uint8_t alpa_map[] = {
79 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda,
80 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce,
81 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5,

--- 21 unchanged lines hidden (view full) ---

103static void isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *, long *); static void
104isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *, long *);
105static void isp_fastpost_complete(ispsoftc_t *, uint32_t);
106static int isp_mbox_continue(ispsoftc_t *);
107static void isp_scsi_init(ispsoftc_t *);
108static void isp_scsi_channel_init(ispsoftc_t *, int);
109static void isp_fibre_init(ispsoftc_t *);
110static void isp_fibre_init_2400(ispsoftc_t *);
72static const char bun[] = "bad underrun (count %d, resid %d, status %s)";
73static const char lipd[] = "Chan %d LIP destroyed %d active commands";
74static const char sacq[] = "unable to acquire scratch area";
75
76static const uint8_t alpa_map[] = {
77 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda,
78 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce,
79 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5,

--- 21 unchanged lines hidden (view full) ---

101static void isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *, long *); static void
102isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *, long *);
103static void isp_fastpost_complete(ispsoftc_t *, uint32_t);
104static int isp_mbox_continue(ispsoftc_t *);
105static void isp_scsi_init(ispsoftc_t *);
106static void isp_scsi_channel_init(ispsoftc_t *, int);
107static void isp_fibre_init(ispsoftc_t *);
108static void isp_fibre_init_2400(ispsoftc_t *);
111static void isp_mark_portdb(ispsoftc_t *, int, int);
109static void isp_clear_portdb(ispsoftc_t *, int);
110static void isp_mark_portdb(ispsoftc_t *, int);
112static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int, int);
113static int isp_port_login(ispsoftc_t *, uint16_t, uint32_t);
114static int isp_port_logout(ispsoftc_t *, uint16_t, uint32_t);
115static int isp_getpdb(ispsoftc_t *, int, uint16_t, isp_pdb_t *, int);
116static int isp_gethandles(ispsoftc_t *, int, uint16_t *, int *, int, int);
117static void isp_dump_chip_portdb(ispsoftc_t *, int, int);
118static uint64_t isp_get_wwn(ispsoftc_t *, int, int, int);
119static int isp_fclink_test(ispsoftc_t *, int, int);

--- 2158 unchanged lines hidden (view full) ---

2278
2279 /*
2280 * Whatever happens, we're now committed to being here.
2281 */
2282 isp->isp_state = ISP_RUNSTATE;
2283}
2284
2285static void
111static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int, int);
112static int isp_port_login(ispsoftc_t *, uint16_t, uint32_t);
113static int isp_port_logout(ispsoftc_t *, uint16_t, uint32_t);
114static int isp_getpdb(ispsoftc_t *, int, uint16_t, isp_pdb_t *, int);
115static int isp_gethandles(ispsoftc_t *, int, uint16_t *, int *, int, int);
116static void isp_dump_chip_portdb(ispsoftc_t *, int, int);
117static uint64_t isp_get_wwn(ispsoftc_t *, int, int, int);
118static int isp_fclink_test(ispsoftc_t *, int, int);

--- 2158 unchanged lines hidden (view full) ---

2277
2278 /*
2279 * Whatever happens, we're now committed to being here.
2280 */
2281 isp->isp_state = ISP_RUNSTATE;
2282}
2283
2284static void
2286isp_mark_portdb(ispsoftc_t *isp, int chan, int disposition)
2285isp_clear_portdb(ispsoftc_t *isp, int chan)
2287{
2288 fcparam *fcp = FCPARAM(isp, chan);
2289 fcportdb_t *lp;
2290 int i;
2291
2292 for (i = 0; i < MAX_FC_TARG; i++) {
2293 lp = &fcp->portdb[i];
2294 switch (lp->state) {
2286{
2287 fcparam *fcp = FCPARAM(isp, chan);
2288 fcportdb_t *lp;
2289 int i;
2290
2291 for (i = 0; i < MAX_FC_TARG; i++) {
2292 lp = &fcp->portdb[i];
2293 switch (lp->state) {
2295 case FC_PORTDB_STATE_PROBATIONAL:
2296 case FC_PORTDB_STATE_DEAD:
2297 case FC_PORTDB_STATE_CHANGED:
2294 case FC_PORTDB_STATE_DEAD:
2295 case FC_PORTDB_STATE_CHANGED:
2298 case FC_PORTDB_STATE_PENDING_VALID:
2299 case FC_PORTDB_STATE_VALID:
2296 case FC_PORTDB_STATE_VALID:
2300 if (disposition > 0)
2301 lp->state = FC_PORTDB_STATE_PROBATIONAL;
2302 else {
2303 lp->state = FC_PORTDB_STATE_NIL;
2304 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
2305 }
2297 lp->state = FC_PORTDB_STATE_NIL;
2298 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
2306 break;
2299 break;
2307 case FC_PORTDB_STATE_ZOMBIE:
2308 break;
2309 case FC_PORTDB_STATE_NIL:
2310 case FC_PORTDB_STATE_NEW:
2300 case FC_PORTDB_STATE_NIL:
2301 case FC_PORTDB_STATE_NEW:
2311 default:
2312 ISP_MEMZERO(lp, sizeof(*lp));
2313 lp->state = FC_PORTDB_STATE_NIL;
2314 break;
2302 lp->state = FC_PORTDB_STATE_NIL;
2303 break;
2304 case FC_PORTDB_STATE_ZOMBIE:
2305 break;
2306 default:
2307 panic("Don't know how to clear state %d\n", lp->state);
2315 }
2316 }
2317}
2318
2308 }
2309 }
2310}
2311
2312static void
2313isp_mark_portdb(ispsoftc_t *isp, int chan)
2314{
2315 fcparam *fcp = FCPARAM(isp, chan);
2316 fcportdb_t *lp;
2317 int i;
2318
2319 for (i = 0; i < MAX_FC_TARG; i++) {
2320 lp = &fcp->portdb[i];
2321 if (lp->state == FC_PORTDB_STATE_NIL)
2322 continue;
2323 if ((lp->portid & 0xfffc00) == 0xfffc00)
2324 continue;
2325 fcp->portdb[i].probational = 1;
2326 }
2327}
2328
2319/*
2320 * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards
2321 * or via FABRIC LOGIN/FABRIC LOGOUT for other cards.
2322 */
2323static int
2324isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags, int gs)
2325{
2326 mbreg_t mbs;
2327 uint8_t q[QENTRY_LEN];
2328 isp_plogx_t *plp;
2329 fcparam *fcp;
2330 uint8_t *scp;
2331 uint32_t sst, parm1;
2332 int rval, lev;
2333 const char *msg;
2334 char buf[64];
2335
2329/*
2330 * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards
2331 * or via FABRIC LOGIN/FABRIC LOGOUT for other cards.
2332 */
2333static int
2334isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags, int gs)
2335{
2336 mbreg_t mbs;
2337 uint8_t q[QENTRY_LEN];
2338 isp_plogx_t *plp;
2339 fcparam *fcp;
2340 uint8_t *scp;
2341 uint32_t sst, parm1;
2342 int rval, lev;
2343 const char *msg;
2344 char buf[64];
2345
2346 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d PLOGX %s PortID 0x%06x nphdl 0x%x",
2347 chan, (flags & PLOGX_FLG_CMD_MASK) == PLOGX_FLG_CMD_PLOGI ?
2348 "Login":"Logout", portid, handle);
2336 if (!IS_24XX(isp)) {
2337 int action = flags & PLOGX_FLG_CMD_MASK;
2338 if (action == PLOGX_FLG_CMD_PLOGI) {
2339 return (isp_port_login(isp, handle, portid));
2340 } else if (action == PLOGX_FLG_CMD_LOGO) {
2341 return (isp_port_logout(isp, handle, portid));
2342 } else {
2343 return (MBOX_INVALID_COMMAND);

--- 417 unchanged lines hidden (view full) ---

2761/*
2762 * Make sure we have good FC link.
2763 */
2764
2765static int
2766isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
2767{
2768 mbreg_t mbs;
2349 if (!IS_24XX(isp)) {
2350 int action = flags & PLOGX_FLG_CMD_MASK;
2351 if (action == PLOGX_FLG_CMD_PLOGI) {
2352 return (isp_port_login(isp, handle, portid));
2353 } else if (action == PLOGX_FLG_CMD_LOGO) {
2354 return (isp_port_logout(isp, handle, portid));
2355 } else {
2356 return (MBOX_INVALID_COMMAND);

--- 417 unchanged lines hidden (view full) ---

2774/*
2775 * Make sure we have good FC link.
2776 */
2777
2778static int
2779isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
2780{
2781 mbreg_t mbs;
2769 int r;
2782 int i, r;
2770 uint16_t nphdl;
2771 fcparam *fcp;
2772 isp_pdb_t pdb;
2773 NANOTIME_T hra, hrb;
2774
2775 fcp = FCPARAM(isp, chan);
2776
2783 uint16_t nphdl;
2784 fcparam *fcp;
2785 isp_pdb_t pdb;
2786 NANOTIME_T hra, hrb;
2787
2788 fcp = FCPARAM(isp, chan);
2789
2777 /* Mark port database entries for following scan. */
2778 isp_mark_portdb(isp, chan, 1);
2790 /* Mark port database entries probational for following scan. */
2791 isp_mark_portdb(isp, chan);
2779
2780 if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
2781 return (0);
2782
2783 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan);
2784 fcp->isp_loopstate = LOOP_TESTING_LINK;
2785
2786 /*

--- 26 unchanged lines hidden (view full) ---

2813 */
2814 MBSINIT(&mbs, MBOX_GET_LOOP_ID, MBLOGALL, 0);
2815 mbs.param[9] = chan;
2816 isp_mboxcmd(isp, &mbs);
2817 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
2818 return (-1);
2819 }
2820
2792
2793 if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
2794 return (0);
2795
2796 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan);
2797 fcp->isp_loopstate = LOOP_TESTING_LINK;
2798
2799 /*

--- 26 unchanged lines hidden (view full) ---

2826 */
2827 MBSINIT(&mbs, MBOX_GET_LOOP_ID, MBLOGALL, 0);
2828 mbs.param[9] = chan;
2829 isp_mboxcmd(isp, &mbs);
2830 if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
2831 return (-1);
2832 }
2833
2821 if (ISP_CAP_2KLOGIN(isp)) {
2822 fcp->isp_loopid = mbs.param[1];
2823 } else {
2824 fcp->isp_loopid = mbs.param[1] & 0xff;
2825 }
2826
2827 if (IS_2100(isp)) {
2828 /*
2829 * Don't bother with fabric if we are using really old
2830 * 2100 firmware. It's just not worth it.
2831 */
2832 if (ISP_FW_NEWER_THAN(isp, 1, 15, 37))
2833 fcp->isp_topo = TOPO_FL_PORT;
2834 else
2835 fcp->isp_topo = TOPO_NL_PORT;
2836 } else {
2837 int topo = (int) mbs.param[6];
2838 if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) {
2839 topo = TOPO_PTP_STUB;
2840 }
2841 fcp->isp_topo = topo;
2842 }
2843 fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16);
2844
2834 if (IS_2100(isp)) {
2835 /*
2836 * Don't bother with fabric if we are using really old
2837 * 2100 firmware. It's just not worth it.
2838 */
2839 if (ISP_FW_NEWER_THAN(isp, 1, 15, 37))
2840 fcp->isp_topo = TOPO_FL_PORT;
2841 else
2842 fcp->isp_topo = TOPO_NL_PORT;
2843 } else {
2844 int topo = (int) mbs.param[6];
2845 if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) {
2846 topo = TOPO_PTP_STUB;
2847 }
2848 fcp->isp_topo = topo;
2849 }
2850 fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16);
2851
2845 /*
2846 * Check to make sure we got a valid loopid
2847 * The 24XX seems to mess this up for multiple channels.
2848 */
2849 if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_NL_PORT) {
2852 if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
2853 fcp->isp_loopid = mbs.param[1] & 0xff;
2854 } else if (fcp->isp_topo != TOPO_F_PORT) {
2850 uint8_t alpa = fcp->isp_portid;
2851
2855 uint8_t alpa = fcp->isp_portid;
2856
2852 if (alpa == 0) {
2853 /* "Cannot Happen" */
2854 isp_prt(isp, ISP_LOGWARN, "Zero AL_PA for Loop Topology?");
2855 } else {
2856 int i;
2857 for (i = 0; alpa_map[i]; i++) {
2858 if (alpa_map[i] == alpa) {
2859 break;
2860 }
2861 }
2862 if (alpa_map[i] && fcp->isp_loopid != i) {
2863 isp_prt(isp, ISP_LOG_SANCFG,
2864 "Chan %d Deriving loopid %d from AL_PA map (AL_PA 0x%x) and ignoring returned value %d (AL_PA 0x%x)",
2865 chan, i, alpa_map[i], fcp->isp_loopid, alpa);
2866 fcp->isp_loopid = i;
2867 }
2857 for (i = 0; alpa_map[i]; i++) {
2858 if (alpa_map[i] == alpa)
2859 break;
2868 }
2860 }
2861 if (alpa_map[i])
2862 fcp->isp_loopid = i;
2869 }
2870
2871 if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
2872 nphdl = IS_24XX(isp) ? NPH_FL_ID : FL_ID;
2873 r = isp_getpdb(isp, chan, nphdl, &pdb, 1);
2874 if (r != 0 || pdb.portid == 0) {
2875 if (IS_2100(isp)) {
2876 fcp->isp_topo = TOPO_NL_PORT;

--- 17 unchanged lines hidden (view full) ---

2894 }
2895 if (r) {
2896 isp_prt(isp, ISP_LOGWARN|ISP_LOG_SANCFG, "%s: register fc4 type failed", __func__);
2897 return (-1);
2898 }
2899 }
2900
2901not_on_fabric:
2863 }
2864
2865 if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
2866 nphdl = IS_24XX(isp) ? NPH_FL_ID : FL_ID;
2867 r = isp_getpdb(isp, chan, nphdl, &pdb, 1);
2868 if (r != 0 || pdb.portid == 0) {
2869 if (IS_2100(isp)) {
2870 fcp->isp_topo = TOPO_NL_PORT;

--- 17 unchanged lines hidden (view full) ---

2888 }
2889 if (r) {
2890 isp_prt(isp, ISP_LOGWARN|ISP_LOG_SANCFG, "%s: register fc4 type failed", __func__);
2891 return (-1);
2892 }
2893 }
2894
2895not_on_fabric:
2896 /* Get link speed. */
2902 fcp->isp_gbspeed = 1;
2903 if (IS_23XX(isp) || IS_24XX(isp)) {
2904 MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000);
2905 mbs.param[1] = MBGSD_GET_RATE;
2906 /* mbs.param[2] undefined if we're just getting rate */
2907 isp_mboxcmd(isp, &mbs);
2908 if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
2897 fcp->isp_gbspeed = 1;
2898 if (IS_23XX(isp) || IS_24XX(isp)) {
2899 MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000);
2900 mbs.param[1] = MBGSD_GET_RATE;
2901 /* mbs.param[2] undefined if we're just getting rate */
2902 isp_mboxcmd(isp, &mbs);
2903 if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
2909 if (mbs.param[1] == MBGSD_EIGHTGB) {
2910 isp_prt(isp, ISP_LOGINFO, "Chan %d 8Gb link speed", chan);
2904 if (mbs.param[1] == MBGSD_10GB)
2905 fcp->isp_gbspeed = 10;
2906 else if (mbs.param[1] == MBGSD_16GB)
2907 fcp->isp_gbspeed = 16;
2908 else if (mbs.param[1] == MBGSD_8GB)
2911 fcp->isp_gbspeed = 8;
2909 fcp->isp_gbspeed = 8;
2912 } else if (mbs.param[1] == MBGSD_FOURGB) {
2913 isp_prt(isp, ISP_LOGINFO, "Chan %d 4Gb link speed", chan);
2910 else if (mbs.param[1] == MBGSD_4GB)
2914 fcp->isp_gbspeed = 4;
2911 fcp->isp_gbspeed = 4;
2915 } else if (mbs.param[1] == MBGSD_TWOGB) {
2916 isp_prt(isp, ISP_LOGINFO, "Chan %d 2Gb link speed", chan);
2912 else if (mbs.param[1] == MBGSD_2GB)
2917 fcp->isp_gbspeed = 2;
2913 fcp->isp_gbspeed = 2;
2918 } else if (mbs.param[1] == MBGSD_ONEGB) {
2919 isp_prt(isp, ISP_LOGINFO, "Chan %d 1Gb link speed", chan);
2914 else if (mbs.param[1] == MBGSD_1GB)
2920 fcp->isp_gbspeed = 1;
2915 fcp->isp_gbspeed = 1;
2921 }
2922 }
2923 }
2924
2925 fcp->isp_loopstate = LOOP_LTEST_DONE;
2916 }
2917 }
2918
2919 fcp->isp_loopstate = LOOP_LTEST_DONE;
2926 /*
2927 * Announce ourselves, too.
2928 */
2929 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG, topology, chan, (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) fcp->isp_wwpn, fcp->isp_portid, fcp->isp_loopid, isp_fc_toponame(fcp));
2920 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
2921 "Chan %d WWPN %016jx WWNN %016jx",
2922 chan, (uintmax_t)fcp->isp_wwpn, (uintmax_t)fcp->isp_wwnn);
2923 isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
2924 "Chan %d %dGb %s PortID 0x%06x LoopID 0x%02x",
2925 chan, fcp->isp_gbspeed, isp_fc_toponame(fcp), fcp->isp_portid,
2926 fcp->isp_loopid);
2930 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan);
2931 return (0);
2932}
2933
2934/*
2935 * Complete the synchronization of our Port Database.
2936 *
2937 * At this point, we've scanned the local loop (if any) and the fabric

--- 20 unchanged lines hidden (view full) ---

2958
2959 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan);
2960
2961 fcp->isp_loopstate = LOOP_SYNCING_PDB;
2962
2963 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
2964 lp = &fcp->portdb[dbidx];
2965
2927 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan);
2928 return (0);
2929}
2930
2931/*
2932 * Complete the synchronization of our Port Database.
2933 *
2934 * At this point, we've scanned the local loop (if any) and the fabric

--- 20 unchanged lines hidden (view full) ---

2955
2956 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan);
2957
2958 fcp->isp_loopstate = LOOP_SYNCING_PDB;
2959
2960 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
2961 lp = &fcp->portdb[dbidx];
2962
2966 if (lp->state == FC_PORTDB_STATE_NIL ||
2967 lp->state == FC_PORTDB_STATE_VALID) {
2963 if (lp->state == FC_PORTDB_STATE_NIL)
2968 continue;
2964 continue;
2969 }
2970
2965 if (lp->probational && lp->state != FC_PORTDB_STATE_ZOMBIE)
2966 lp->state = FC_PORTDB_STATE_DEAD;
2971 switch (lp->state) {
2967 switch (lp->state) {
2972 case FC_PORTDB_STATE_PROBATIONAL:
2973 case FC_PORTDB_STATE_DEAD:
2974 lp->state = FC_PORTDB_STATE_NIL;
2975 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
2976 if (lp->autologin == 0) {
2977 (void) isp_plogx(isp, chan, lp->handle,
2978 lp->portid,
2979 PLOGX_FLG_CMD_LOGO |
2980 PLOGX_FLG_IMPLICIT |
2981 PLOGX_FLG_FREE_NPHDL, 0);
2968 case FC_PORTDB_STATE_DEAD:
2969 lp->state = FC_PORTDB_STATE_NIL;
2970 isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
2971 if (lp->autologin == 0) {
2972 (void) isp_plogx(isp, chan, lp->handle,
2973 lp->portid,
2974 PLOGX_FLG_CMD_LOGO |
2975 PLOGX_FLG_IMPLICIT |
2976 PLOGX_FLG_FREE_NPHDL, 0);
2982 } else {
2983 lp->autologin = 0;
2984 }
2977 }
2985 lp->new_prli_word3 = 0;
2986 lp->new_portid = 0;
2987 /*
2988 * Note that we might come out of this with our state
2989 * set to FC_PORTDB_STATE_ZOMBIE.
2990 */
2991 break;
2992 case FC_PORTDB_STATE_NEW:
2978 /*
2979 * Note that we might come out of this with our state
2980 * set to FC_PORTDB_STATE_ZOMBIE.
2981 */
2982 break;
2983 case FC_PORTDB_STATE_NEW:
2993 lp->portid = lp->new_portid;
2994 lp->prli_word3 = lp->new_prli_word3;
2995 lp->state = FC_PORTDB_STATE_VALID;
2996 isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp);
2984 lp->state = FC_PORTDB_STATE_VALID;
2985 isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp);
2997 lp->new_prli_word3 = 0;
2998 lp->new_portid = 0;
2999 break;
3000 case FC_PORTDB_STATE_CHANGED:
3001 lp->state = FC_PORTDB_STATE_VALID;
3002 isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp);
3003 lp->portid = lp->new_portid;
3004 lp->prli_word3 = lp->new_prli_word3;
2986 break;
2987 case FC_PORTDB_STATE_CHANGED:
2988 lp->state = FC_PORTDB_STATE_VALID;
2989 isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp);
2990 lp->portid = lp->new_portid;
2991 lp->prli_word3 = lp->new_prli_word3;
3005 lp->new_prli_word3 = 0;
3006 lp->new_portid = 0;
3007 break;
2992 break;
3008 case FC_PORTDB_STATE_PENDING_VALID:
3009 lp->portid = lp->new_portid;
3010 lp->prli_word3 = lp->new_prli_word3;
3011 lp->state = FC_PORTDB_STATE_VALID;
2993 case FC_PORTDB_STATE_VALID:
3012 isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp);
3013 break;
3014 case FC_PORTDB_STATE_ZOMBIE:
3015 break;
3016 default:
3017 isp_prt(isp, ISP_LOGWARN,
3018 "isp_pdb_sync: state %d for idx %d",
3019 lp->state, dbidx);

--- 7 unchanged lines hidden (view full) ---

3027 * in isp_start.
3028 */
3029 fcp->loop_seen_once = 1;
3030 fcp->isp_loopstate = LOOP_READY;
3031 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan);
3032 return (0);
3033}
3034
2994 isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp);
2995 break;
2996 case FC_PORTDB_STATE_ZOMBIE:
2997 break;
2998 default:
2999 isp_prt(isp, ISP_LOGWARN,
3000 "isp_pdb_sync: state %d for idx %d",
3001 lp->state, dbidx);

--- 7 unchanged lines hidden (view full) ---

3009 * in isp_start.
3010 */
3011 fcp->loop_seen_once = 1;
3012 fcp->isp_loopstate = LOOP_READY;
3013 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan);
3014 return (0);
3015}
3016
3017static void
3018isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_t *pdb)
3019{
3020 fcportdb_t *lp;
3021 uint64_t wwnn, wwpn;
3022
3023 MAKE_WWN_FROM_NODE_NAME(wwnn, pdb->nodename);
3024 MAKE_WWN_FROM_NODE_NAME(wwpn, pdb->portname);
3025
3026 /* Search port database for the same WWPN. */
3027 if (isp_find_pdb_by_wwpn(isp, chan, wwpn, &lp)) {
3028 if (!lp->probational) {
3029 isp_prt(isp, ISP_LOGERR,
3030 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)",
3031 chan, lp->portid, lp->handle,
3032 FC_PORTDB_TGT(isp, chan, lp), lp->state);
3033 isp_dump_portdb(isp, chan);
3034 return;
3035 }
3036 lp->probational = 0;
3037 lp->node_wwn = wwnn;
3038
3039 /* Old device, nothing new. */
3040 if (lp->portid == pdb->portid &&
3041 lp->handle == pdb->handle &&
3042 lp->prli_word3 == pdb->prli_word3) {
3043 if (lp->state != FC_PORTDB_STATE_NEW)
3044 lp->state = FC_PORTDB_STATE_VALID;
3045 isp_prt(isp, ISP_LOG_SANCFG,
3046 "Chan %d Port 0x%06x@0x%04x is valid",
3047 chan, pdb->portid, pdb->handle);
3048 return;
3049 }
3050
3051 /* Something has changed. */
3052 lp->state = FC_PORTDB_STATE_CHANGED;
3053 lp->handle = pdb->handle;
3054 lp->new_portid = pdb->portid;
3055 lp->new_prli_word3 = pdb->prli_word3;
3056 isp_prt(isp, ISP_LOG_SANCFG,
3057 "Chan %d Port 0x%06x@0x%04x is changed",
3058 chan, pdb->portid, pdb->handle);
3059 return;
3060 }
3061
3062 /* It seems like a new port. Find an empty slot for it. */
3063 if (!isp_find_pdb_empty(isp, chan, &lp)) {
3064 isp_prt(isp, ISP_LOGERR, "Chan %d out of portdb entries", chan);
3065 return;
3066 }
3067
3068 ISP_MEMZERO(lp, sizeof (fcportdb_t));
3069 lp->autologin = 1;
3070 lp->probational = 0;
3071 lp->state = FC_PORTDB_STATE_NEW;
3072 lp->portid = lp->new_portid = pdb->portid;
3073 lp->prli_word3 = lp->new_prli_word3 = pdb->prli_word3;
3074 lp->handle = pdb->handle;
3075 lp->port_wwn = wwpn;
3076 lp->node_wwn = wwnn;
3077 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Port 0x%06x@0x%04x is new",
3078 chan, pdb->portid, pdb->handle);
3079}
3080
3035/*
3036 * Scan local loop for devices.
3037 */
3038static int
3039isp_scan_loop(ispsoftc_t *isp, int chan)
3040{
3081/*
3082 * Scan local loop for devices.
3083 */
3084static int
3085isp_scan_loop(ispsoftc_t *isp, int chan)
3086{
3041 fcportdb_t *lp, tmp;
3042 fcparam *fcp = FCPARAM(isp, chan);
3087 fcparam *fcp = FCPARAM(isp, chan);
3043 int i, idx, lim, r;
3088 int idx, lim, r;
3044 isp_pdb_t pdb;
3045 uint16_t handles[LOCAL_LOOP_LIM];
3046 uint16_t handle;
3047
3048 if (fcp->isp_loopstate < LOOP_LTEST_DONE) {
3049 return (-1);
3050 }
3051 if (fcp->isp_loopstate > LOOP_SCANNING_LOOP) {
3052 return (0);
3053 }
3054 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan);
3089 isp_pdb_t pdb;
3090 uint16_t handles[LOCAL_LOOP_LIM];
3091 uint16_t handle;
3092
3093 if (fcp->isp_loopstate < LOOP_LTEST_DONE) {
3094 return (-1);
3095 }
3096 if (fcp->isp_loopstate > LOOP_SCANNING_LOOP) {
3097 return (0);
3098 }
3099 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan);
3055 if (fcp->isp_topo != TOPO_NL_PORT && fcp->isp_topo != TOPO_FL_PORT &&
3056 fcp->isp_topo != TOPO_N_PORT) {
3100 if (TOPO_IS_FABRIC(fcp->isp_topo)) {
3057 isp_prt(isp, ISP_LOG_SANCFG,
3058 "Chan %d FC loop scan done (no loop)", chan);
3059 fcp->isp_loopstate = LOOP_LSCAN_DONE;
3060 return (0);
3061 }
3062 fcp->isp_loopstate = LOOP_SCANNING_LOOP;
3063
3064 lim = LOCAL_LOOP_LIM;
3065 r = isp_gethandles(isp, chan, handles, &lim, 1, 1);
3066 if (r != 0) {
3067 isp_prt(isp, ISP_LOG_SANCFG,
3068 "Chan %d Getting list of handles failed with %x", chan, r);
3101 isp_prt(isp, ISP_LOG_SANCFG,
3102 "Chan %d FC loop scan done (no loop)", chan);
3103 fcp->isp_loopstate = LOOP_LSCAN_DONE;
3104 return (0);
3105 }
3106 fcp->isp_loopstate = LOOP_SCANNING_LOOP;
3107
3108 lim = LOCAL_LOOP_LIM;
3109 r = isp_gethandles(isp, chan, handles, &lim, 1, 1);
3110 if (r != 0) {
3111 isp_prt(isp, ISP_LOG_SANCFG,
3112 "Chan %d Getting list of handles failed with %x", chan, r);
3069fail:
3070 isp_prt(isp, ISP_LOG_SANCFG,
3071 "Chan %d FC loop scan done (bad)", chan);
3072 return (-1);
3073 }
3074
3075 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles",
3076 chan, lim);
3077

--- 30 unchanged lines hidden (view full) ---

3108 continue;
3109 }
3110 }
3111
3112 /*
3113 * Get the port database entity for this index.
3114 */
3115 r = isp_getpdb(isp, chan, handle, &pdb, 1);
3113 isp_prt(isp, ISP_LOG_SANCFG,
3114 "Chan %d FC loop scan done (bad)", chan);
3115 return (-1);
3116 }
3117
3118 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles",
3119 chan, lim);
3120

--- 30 unchanged lines hidden (view full) ---

3151 continue;
3152 }
3153 }
3154
3155 /*
3156 * Get the port database entity for this index.
3157 */
3158 r = isp_getpdb(isp, chan, handle, &pdb, 1);
3159 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
3160 goto abort;
3116 if (r != 0) {
3117 isp_prt(isp, ISP_LOGDEBUG1,
3118 "Chan %d FC Scan Loop handle %d returned %x",
3119 chan, handle, r);
3120 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
3121 goto abort;
3122 continue;
3123 }
3124
3161 if (r != 0) {
3162 isp_prt(isp, ISP_LOGDEBUG1,
3163 "Chan %d FC Scan Loop handle %d returned %x",
3164 chan, handle, r);
3165 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
3166 goto abort;
3167 continue;
3168 }
3169
3125 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
3126 goto abort;
3127
3128 /*
3129 * On *very* old 2100 firmware we would end up sometimes
3130 * with the firmware returning the port database entry
3131 * for something else. We used to restart this, but
3132 * now we just punt.
3133 */
3134 if (IS_2100(isp) && pdb.handle != handle) {
3135 isp_prt(isp, ISP_LOGWARN,
3136 "Chan %d getpdb() returned wrong handle %x != %x",
3137 chan, pdb.handle, handle);
3138 goto fail;
3139 }
3140
3141 /*
3142 * Save the pertinent info locally.
3143 */
3144 MAKE_WWN_FROM_NODE_NAME(tmp.node_wwn, pdb.nodename);
3145 MAKE_WWN_FROM_NODE_NAME(tmp.port_wwn, pdb.portname);
3146 tmp.prli_word3 = pdb.prli_word3;
3147 tmp.portid = pdb.portid;
3148 tmp.handle = pdb.handle;
3149
3150 /*
3151 * Check to make sure it's still a valid entry. The 24XX seems
3152 * to return a portid but not a WWPN/WWNN or role for devices
3153 * which shift on a loop.
3154 */
3155 if (tmp.node_wwn == 0 || tmp.port_wwn == 0 || tmp.portid == 0) {
3156 int a, b, c;
3157 isp_prt(isp, ISP_LOGWARN,
3158 "Chan %d bad pdb (WWNN %016jx, WWPN %016jx, PortID %06x, W3 0x%x, H 0x%x) @ handle 0x%x",
3159 chan, tmp.node_wwn, tmp.port_wwn, tmp.portid, tmp.prli_word3, tmp.handle, handle);
3160 a = (tmp.node_wwn == 0);
3161 b = (tmp.port_wwn == 0);
3162 c = (tmp.portid == 0);
3163 if (a == 0 && b == 0) {
3164 tmp.node_wwn =
3165 isp_get_wwn(isp, chan, handle, 1);
3166 tmp.port_wwn =
3167 isp_get_wwn(isp, chan, handle, 0);
3168 if (tmp.node_wwn && tmp.port_wwn) {
3169 isp_prt(isp, ISP_LOGWARN, "DODGED!");
3170 goto cont;
3171 }
3172 }
3173 isp_dump_portdb(isp, chan);
3174 continue;
3175 }
3176 cont:
3177
3178 /*
3179 * Now search the entire port database
3180 * for the same Port WWN.
3181 */
3182 if (isp_find_pdb_by_wwn(isp, chan, tmp.port_wwn, &lp)) {
3183 /*
3184 * Okay- we've found a non-nil entry that matches.
3185 * Check to make sure it's probational or a zombie.
3186 */
3187 if (lp->state != FC_PORTDB_STATE_PROBATIONAL &&
3188 lp->state != FC_PORTDB_STATE_ZOMBIE &&
3189 lp->state != FC_PORTDB_STATE_VALID) {
3190 isp_prt(isp, ISP_LOGERR,
3191 "Chan %d [%d] not probational/zombie (0x%x)",
3192 chan, FC_PORTDB_TGT(isp, chan, lp), lp->state);
3193 isp_dump_portdb(isp, chan);
3194 goto fail;
3195 }
3196
3197 /*
3198 * Mark the device as something the f/w logs into
3199 * automatically.
3200 */
3201 lp->autologin = 1;
3202 lp->node_wwn = tmp.node_wwn;
3203
3204 /*
3205 * Check to make see if really still the same
3206 * device. If it is, we mark it pending valid.
3207 */
3208 if (lp->portid == tmp.portid && lp->handle == tmp.handle && lp->prli_word3 == tmp.prli_word3) {
3209 lp->new_portid = tmp.portid;
3210 lp->new_prli_word3 = tmp.prli_word3;
3211 lp->state = FC_PORTDB_STATE_PENDING_VALID;
3212 isp_prt(isp, ISP_LOG_SANCFG,
3213 "Chan %d Loop port 0x%06x@0x%04x now pending valid",
3214 chan, tmp.portid, tmp.handle);
3215 continue;
3216 }
3217
3218 /*
3219 * We can wipe out the old handle value
3220 * here because it's no longer valid.
3221 */
3222 lp->handle = tmp.handle;
3223
3224 /*
3225 * Claim that this has changed and let somebody else
3226 * decide what to do.
3227 */
3228 isp_prt(isp, ISP_LOG_SANCFG,
3229 "Chan %d Loop port 0x%06x@0x%04x changed",
3230 chan, tmp.portid, tmp.handle);
3231 lp->state = FC_PORTDB_STATE_CHANGED;
3232 lp->new_portid = tmp.portid;
3233 lp->new_prli_word3 = tmp.prli_word3;
3234 continue;
3235 }
3236
3237 /*
3238 * Ah. A new device entry. Find an empty slot
3239 * for it and save info for later disposition.
3240 */
3241 for (i = 0; i < MAX_FC_TARG; i++) {
3242 if (fcp->portdb[i].state == FC_PORTDB_STATE_NIL) {
3243 break;
3244 }
3245 }
3246 if (i == MAX_FC_TARG) {
3247 isp_prt(isp, ISP_LOGERR,
3248 "Chan %d out of portdb entries", chan);
3249 continue;
3250 }
3251 lp = &fcp->portdb[i];
3252
3253 ISP_MEMZERO(lp, sizeof (fcportdb_t));
3254 lp->autologin = 1;
3255 lp->state = FC_PORTDB_STATE_NEW;
3256 lp->new_portid = tmp.portid;
3257 lp->new_prli_word3 = tmp.prli_word3;
3258 lp->handle = tmp.handle;
3259 lp->port_wwn = tmp.port_wwn;
3260 lp->node_wwn = tmp.node_wwn;
3261 isp_prt(isp, ISP_LOG_SANCFG,
3262 "Chan %d Loop port 0x%06x@0x%04x is a new entry",
3263 chan, tmp.portid, tmp.handle);
3170 isp_pdb_add_update(isp, chan, &pdb);
3264 }
3265 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
3266 goto abort;
3267 fcp->isp_loopstate = LOOP_LSCAN_DONE;
3268 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan);
3269 return (0);
3270}
3271

--- 82 unchanged lines hidden (view full) ---

3354 } un;
3355 isp_ct_pt_t *pt;
3356 ct_hdr_t *ct;
3357 uint32_t *rp;
3358 uint8_t *scp = fcp->isp_scratch;
3359
3360 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d scanning fabric (GID_FT) via CT", chan);
3361
3171 }
3172 if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
3173 goto abort;
3174 fcp->isp_loopstate = LOOP_LSCAN_DONE;
3175 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan);
3176 return (0);
3177}
3178

--- 82 unchanged lines hidden (view full) ---

3261 } un;
3262 isp_ct_pt_t *pt;
3263 ct_hdr_t *ct;
3264 uint32_t *rp;
3265 uint8_t *scp = fcp->isp_scratch;
3266
3267 isp_prt(isp, ISP_LOGDEBUG0, "Chan %d scanning fabric (GID_FT) via CT", chan);
3268
3362 if (!IS_24XX(isp)) {
3363 return (1);
3364 }
3365
3366 /*
3367 * Build a Passthrough IOCB in memory.
3368 */
3369 pt = &un.plocal;
3370 ISP_MEMZERO(un.q, QENTRY_LEN);
3371 pt->ctp_header.rqs_entry_count = 1;
3372 pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
3373 pt->ctp_handle = 0xffffffff;

--- 66 unchanged lines hidden (view full) ---

3440 }
3441 return (0);
3442}
3443
3444static int
3445isp_scan_fabric(ispsoftc_t *isp, int chan)
3446{
3447 fcparam *fcp = FCPARAM(isp, chan);
3269 /*
3270 * Build a Passthrough IOCB in memory.
3271 */
3272 pt = &un.plocal;
3273 ISP_MEMZERO(un.q, QENTRY_LEN);
3274 pt->ctp_header.rqs_entry_count = 1;
3275 pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
3276 pt->ctp_handle = 0xffffffff;

--- 66 unchanged lines hidden (view full) ---

3343 }
3344 return (0);
3345}
3346
3347static int
3348isp_scan_fabric(ispsoftc_t *isp, int chan)
3349{
3350 fcparam *fcp = FCPARAM(isp, chan);
3351 fcportdb_t *lp;
3448 uint32_t portid;
3449 uint16_t nphdl;
3450 isp_pdb_t pdb;
3451 int portidx, portlim, r;
3452 sns_gid_ft_rsp_t *rs0, *rs1;
3453
3454 if (fcp->isp_loopstate < LOOP_LSCAN_DONE) {
3455 return (-1);
3456 }
3457 if (fcp->isp_loopstate > LOOP_SCANNING_FABRIC) {
3458 return (0);
3459 }
3460 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan);
3352 uint32_t portid;
3353 uint16_t nphdl;
3354 isp_pdb_t pdb;
3355 int portidx, portlim, r;
3356 sns_gid_ft_rsp_t *rs0, *rs1;
3357
3358 if (fcp->isp_loopstate < LOOP_LSCAN_DONE) {
3359 return (-1);
3360 }
3361 if (fcp->isp_loopstate > LOOP_SCANNING_FABRIC) {
3362 return (0);
3363 }
3364 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan);
3461 if (fcp->isp_topo != TOPO_FL_PORT && fcp->isp_topo != TOPO_F_PORT) {
3365 if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
3462 fcp->isp_loopstate = LOOP_FSCAN_DONE;
3463 isp_prt(isp, ISP_LOG_SANCFG,
3464 "Chan %d FC fabric scan done (no fabric)", chan);
3465 return (0);
3466 }
3467 fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
3468
3469 if (FC_SCRATCH_ACQUIRE(isp, chan)) {

--- 20 unchanged lines hidden (view full) ---

3490 isp_dump_chip_portdb(isp, chan, 0);
3491 }
3492 if (r) {
3493 fcp->isp_loopstate = LOOP_LTEST_DONE;
3494 FC_SCRATCH_RELEASE(isp, chan);
3495 goto fail;
3496 }
3497
3366 fcp->isp_loopstate = LOOP_FSCAN_DONE;
3367 isp_prt(isp, ISP_LOG_SANCFG,
3368 "Chan %d FC fabric scan done (no fabric)", chan);
3369 return (0);
3370 }
3371 fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
3372
3373 if (FC_SCRATCH_ACQUIRE(isp, chan)) {

--- 20 unchanged lines hidden (view full) ---

3394 isp_dump_chip_portdb(isp, chan, 0);
3395 }
3396 if (r) {
3397 fcp->isp_loopstate = LOOP_LTEST_DONE;
3398 FC_SCRATCH_RELEASE(isp, chan);
3399 goto fail;
3400 }
3401
3498 if (IS_24XX(isp)) {
3402 /* Get list of port IDs from SNS. */
3403 if (IS_24XX(isp))
3499 r = isp_gid_ft_ct_passthru(isp, chan);
3404 r = isp_gid_ft_ct_passthru(isp, chan);
3500 } else {
3405 else
3501 r = isp_gid_ft_sns(isp, chan);
3406 r = isp_gid_ft_sns(isp, chan);
3502 }
3503
3504 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
3407 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
3505 goto abort;
3408 goto abort;
3506 }
3507
3508 if (r > 0) {
3509 fcp->isp_loopstate = LOOP_FSCAN_DONE;
3510 FC_SCRATCH_RELEASE(isp, chan);
3511 return (0);
3512 } else if (r < 0) {
3513 fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */
3514 FC_SCRATCH_RELEASE(isp, chan);
3515 return (0);
3516 }
3517
3518 MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN, chan);
3519 rs0 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+IGPOFF);
3520 rs1 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+OGPOFF);
3521 isp_get_gid_ft_response(isp, rs0, rs1, NGENT);
3409 if (r > 0) {
3410 fcp->isp_loopstate = LOOP_FSCAN_DONE;
3411 FC_SCRATCH_RELEASE(isp, chan);
3412 return (0);
3413 } else if (r < 0) {
3414 fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */
3415 FC_SCRATCH_RELEASE(isp, chan);
3416 return (0);
3417 }
3418
3419 MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN, chan);
3420 rs0 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+IGPOFF);
3421 rs1 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+OGPOFF);
3422 isp_get_gid_ft_response(isp, rs0, rs1, NGENT);
3522 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
3423 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
3523 goto abort;
3424 goto abort;
3524 }
3525 if (rs1->snscb_cthdr.ct_cmd_resp != LS_ACC) {
3526 int level;
3527 if (rs1->snscb_cthdr.ct_reason == 9 && rs1->snscb_cthdr.ct_explanation == 7) {
3528 level = ISP_LOG_SANCFG;
3529 } else {
3530 level = ISP_LOGWARN;
3531 }
3532 isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_FT"
3533 " (Reason=0x%x Expl=0x%x)", chan,
3534 rs1->snscb_cthdr.ct_reason,
3535 rs1->snscb_cthdr.ct_explanation);
3536 FC_SCRATCH_RELEASE(isp, chan);
3537 fcp->isp_loopstate = LOOP_FSCAN_DONE;
3538 return (0);
3539 }
3540
3425 if (rs1->snscb_cthdr.ct_cmd_resp != LS_ACC) {
3426 int level;
3427 if (rs1->snscb_cthdr.ct_reason == 9 && rs1->snscb_cthdr.ct_explanation == 7) {
3428 level = ISP_LOG_SANCFG;
3429 } else {
3430 level = ISP_LOGWARN;
3431 }
3432 isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_FT"
3433 " (Reason=0x%x Expl=0x%x)", chan,
3434 rs1->snscb_cthdr.ct_reason,
3435 rs1->snscb_cthdr.ct_explanation);
3436 FC_SCRATCH_RELEASE(isp, chan);
3437 fcp->isp_loopstate = LOOP_FSCAN_DONE;
3438 return (0);
3439 }
3440
3541 /*
3542 * Go through the list and remove duplicate port ids.
3543 */
3544
3545 portlim = 0;
3546 portidx = 0;
3441 /* Check our buffer was big enough to get the full list. */
3547 for (portidx = 0; portidx < NGENT-1; portidx++) {
3442 for (portidx = 0; portidx < NGENT-1; portidx++) {
3548 if (rs1->snscb_ports[portidx].control & 0x80) {
3443 if (rs1->snscb_ports[portidx].control & 0x80)
3549 break;
3444 break;
3550 }
3551 }
3445 }
3552
3553 /*
3554 * If we're not at the last entry, our list wasn't big enough.
3555 */
3556 if ((rs1->snscb_ports[portidx].control & 0x80) == 0) {
3557 isp_prt(isp, ISP_LOGWARN,
3558 "fabric too big for scratch area: increase ISP_FC_SCRLEN");
3559 }
3560 portlim = portidx + 1;
3561 isp_prt(isp, ISP_LOG_SANCFG,
3562 "Chan %d Got %d ports back from name server", chan, portlim);
3563
3446 if ((rs1->snscb_ports[portidx].control & 0x80) == 0) {
3447 isp_prt(isp, ISP_LOGWARN,
3448 "fabric too big for scratch area: increase ISP_FC_SCRLEN");
3449 }
3450 portlim = portidx + 1;
3451 isp_prt(isp, ISP_LOG_SANCFG,
3452 "Chan %d Got %d ports back from name server", chan, portlim);
3453
3454 /* Go through the list and remove duplicate port ids. */
3564 for (portidx = 0; portidx < portlim; portidx++) {
3565 int npidx;
3566
3567 portid =
3568 ((rs1->snscb_ports[portidx].portid[0]) << 16) |
3569 ((rs1->snscb_ports[portidx].portid[1]) << 8) |
3570 ((rs1->snscb_ports[portidx].portid[2]));
3571

--- 26 unchanged lines hidden (view full) ---

3598 * Otherwise, it's a new fabric device, and we log into it
3599 * (unconditionally). After searching the entire database
3600 * again to make sure that we never ever ever ever have more
3601 * than one entry that has the same PortID or the same
3602 * WWNN/WWPN duple, we enter the device into our database.
3603 */
3604
3605 for (portidx = 0; portidx < portlim; portidx++) {
3455 for (portidx = 0; portidx < portlim; portidx++) {
3456 int npidx;
3457
3458 portid =
3459 ((rs1->snscb_ports[portidx].portid[0]) << 16) |
3460 ((rs1->snscb_ports[portidx].portid[1]) << 8) |
3461 ((rs1->snscb_ports[portidx].portid[2]));
3462

--- 26 unchanged lines hidden (view full) ---

3489 * Otherwise, it's a new fabric device, and we log into it
3490 * (unconditionally). After searching the entire database
3491 * again to make sure that we never ever ever ever have more
3492 * than one entry that has the same PortID or the same
3493 * WWNN/WWPN duple, we enter the device into our database.
3494 */
3495
3496 for (portidx = 0; portidx < portlim; portidx++) {
3606 fcportdb_t *lp;
3607 uint64_t wwnn, wwpn;
3608 int dbidx, nr;
3609
3610 portid =
3611 ((rs1->snscb_ports[portidx].portid[0]) << 16) |
3612 ((rs1->snscb_ports[portidx].portid[1]) << 8) |
3613 ((rs1->snscb_ports[portidx].portid[2]));
3614
3497 portid = ((rs1->snscb_ports[portidx].portid[0]) << 16) |
3498 ((rs1->snscb_ports[portidx].portid[1]) << 8) |
3499 ((rs1->snscb_ports[portidx].portid[2]));
3500 isp_prt(isp, ISP_LOG_SANCFG,
3501 "Chan %d Checking fabric port 0x%06x", chan, portid);
3615 if (portid == 0) {
3616 isp_prt(isp, ISP_LOG_SANCFG,
3617 "Chan %d Skipping null PortID at idx %d",
3618 chan, portidx);
3619 continue;
3620 }
3502 if (portid == 0) {
3503 isp_prt(isp, ISP_LOG_SANCFG,
3504 "Chan %d Skipping null PortID at idx %d",
3505 chan, portidx);
3506 continue;
3507 }
3621
3622 if (portid == fcp->isp_portid) {
3623 isp_prt(isp, ISP_LOG_SANCFG,
3624 "Chan %d Skipping our PortID 0x%06x", chan, portid);
3625 continue;
3626 }
3627
3508 if (portid == fcp->isp_portid) {
3509 isp_prt(isp, ISP_LOG_SANCFG,
3510 "Chan %d Skipping our PortID 0x%06x", chan, portid);
3511 continue;
3512 }
3513
3628 isp_prt(isp, ISP_LOG_SANCFG,
3629 "Chan %d Checking fabric port 0x%06x", chan, portid);
3630
3631 /*
3632 * We now search our Port Database for any
3633 * probational entries with this PortID. We don't
3634 * look for zombies here- only probational
3635 * entries (we've already logged out of zombies).
3636 */
3637 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
3638 lp = &fcp->portdb[dbidx];
3639
3640 if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
3641 continue;
3514 /* Now search the entire port database for the same portid. */
3515 if (isp_find_pdb_by_portid(isp, chan, portid, &lp)) {
3516 if (!lp->probational) {
3517 isp_prt(isp, ISP_LOGERR,
3518 "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)",
3519 chan, lp->portid, lp->handle,
3520 FC_PORTDB_TGT(isp, chan, lp), lp->state);
3521 FC_SCRATCH_RELEASE(isp, chan);
3522 isp_dump_portdb(isp, chan);
3523 goto fail;
3642 }
3524 }
3643 if (lp->portid == portid) {
3644 break;
3645 }
3646 }
3647
3525
3648 /*
3649 * We found a probational entry with this Port ID.
3650 */
3651 if (dbidx < MAX_FC_TARG) {
3652 int handle_changed = 0;
3653
3654 lp = &fcp->portdb[dbidx];
3655
3656 /*
3657 * See if we're still logged into it.
3658 *
3659 * If we aren't, mark it as a dead device and
3660 * leave the new portid in the database entry
3661 * for somebody further along to decide what to
3662 * do (policy choice).
3663 *
3664 * If we are, check to see if it's the same
3665 * device still (it should be). If for some
3666 * reason it isn't, mark it as a changed device
3667 * and leave the new portid and role in the
3668 * database entry for somebody further along to
3669 * decide what to do (policy choice).
3526 /*
3527 * See if we're still logged into it.
3528 *
3529 * If we aren't, mark it as a dead device and
3530 * leave the new portid in the database entry
3531 * for somebody further along to decide what to
3532 * do (policy choice).
3533 *
3534 * If we are, check to see if it's the same
3535 * device still (it should be). If for some
3536 * reason it isn't, mark it as a changed device
3537 * and leave the new portid and role in the
3538 * database entry for somebody further along to
3539 * decide what to do (policy choice).
3670 *
3671 */
3540 */
3672
3673 r = isp_getpdb(isp, chan, lp->handle, &pdb, 0);
3541 r = isp_getpdb(isp, chan, lp->handle, &pdb, 0);
3674 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
3542 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
3675 goto abort;
3543 goto abort;
3676 }
3677 if (r != 0) {
3544 if (r != 0) {
3678 lp->new_portid = portid;
3679 lp->state = FC_PORTDB_STATE_DEAD;
3545 lp->state = FC_PORTDB_STATE_DEAD;
3680 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric PortID 0x%06x handle 0x%x is dead (%d)", chan, portid, lp->handle, r);
3681 continue;
3682 }
3683
3684
3685 /*
3686 * Check to make sure that handle, portid, WWPN and
3687 * WWNN agree. If they don't, then the association
3688 * between this PortID and the stated handle has been
3689 * broken by the firmware.
3690 */
3691 MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
3692 MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
3693 if (pdb.handle != lp->handle ||
3694 pdb.portid != portid ||
3695 wwpn != lp->port_wwn ||
3696 (lp->node_wwn != 0 && wwnn != lp->node_wwn)) {
3697 isp_prt(isp, ISP_LOG_SANCFG,
3546 isp_prt(isp, ISP_LOG_SANCFG,
3698 fconf, chan, dbidx, pdb.handle, pdb.portid,
3699 (uint32_t) (wwnn >> 32), (uint32_t) wwnn,
3700 (uint32_t) (wwpn >> 32), (uint32_t) wwpn,
3701 lp->handle, portid,
3702 (uint32_t) (lp->node_wwn >> 32),
3703 (uint32_t) lp->node_wwn,
3704 (uint32_t) (lp->port_wwn >> 32),
3705 (uint32_t) lp->port_wwn);
3706 /*
3707 * Try to re-login to this device using a
3708 * new handle. If that fails, mark it dead.
3709 *
3710 * isp_login_device will check for handle and
3711 * portid consistency after re-login.
3712 *
3713 */
3714 if ((fcp->role & ISP_ROLE_INITIATOR) == 0 ||
3715 isp_login_device(isp, chan, portid, &pdb,
3716 &FCPARAM(isp, 0)->isp_lasthdl)) {
3717 lp->new_portid = portid;
3718 lp->state = FC_PORTDB_STATE_DEAD;
3719 if (fcp->isp_loopstate <
3720 LOOP_SCANNING_FABRIC) {
3721 goto abort;
3722 }
3723 continue;
3724 }
3725 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
3726 goto abort;
3727 }
3728 MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
3729 MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
3730 if (wwpn != lp->port_wwn ||
3731 (lp->node_wwn != 0 && wwnn != lp->node_wwn)) {
3732 isp_prt(isp, ISP_LOGWARN, "changed WWN"
3733 " after relogin");
3734 lp->new_portid = portid;
3735 lp->state = FC_PORTDB_STATE_DEAD;
3736 continue;
3737 }
3738
3739 lp->handle = pdb.handle;
3740 handle_changed++;
3547 "Chan %d Port 0x%06x handle 0x%x is dead (%d)",
3548 chan, portid, lp->handle, r);
3549 goto relogin;
3741 }
3742
3550 }
3551
3743 nr = pdb.prli_word3;
3744
3745 /*
3746 * Check to see whether the portid and roles have
3747 * stayed the same. If they have stayed the same,
3748 * we believe that this is the same device and it
3749 * hasn't become disconnected and reconnected, so
3750 * mark it as pending valid.
3751 *
3752 * If they aren't the same, mark the device as a
3753 * changed device and save the new port id and role
3754 * and let somebody else decide.
3755 */
3756
3757 lp->new_portid = portid;
3758 lp->new_prli_word3 = nr;
3759 if (pdb.portid != lp->portid || nr != lp->prli_word3 || handle_changed) {
3760 isp_prt(isp, ISP_LOG_SANCFG,
3761 "Chan %d Fabric port 0x%06x changed",
3762 chan, portid);
3763 lp->state = FC_PORTDB_STATE_CHANGED;
3764 } else {
3765 isp_prt(isp, ISP_LOG_SANCFG,
3766 "Chan %d Fabric port 0x%06x now pending valid",
3767 chan, portid);
3768 lp->state = FC_PORTDB_STATE_PENDING_VALID;
3769 }
3552 isp_pdb_add_update(isp, chan, &pdb);
3770 continue;
3771 }
3772
3553 continue;
3554 }
3555
3556relogin:
3773 if ((fcp->role & ISP_ROLE_INITIATOR) == 0)
3774 continue;
3775
3557 if ((fcp->role & ISP_ROLE_INITIATOR) == 0)
3558 continue;
3559
3776 /*
3777 * Ah- a new entry. Search the database again for all non-NIL
3778 * entries to make sure we never ever make a new database entry
3779 * with the same port id. While we're at it, mark where the
3780 * last free entry was.
3781 */
3782
3783 dbidx = MAX_FC_TARG;
3784 for (lp = fcp->portdb; lp < &fcp->portdb[MAX_FC_TARG]; lp++) {
3785 if (lp->state == FC_PORTDB_STATE_NIL) {
3786 if (dbidx == MAX_FC_TARG) {
3787 dbidx = lp - fcp->portdb;
3788 }
3789 continue;
3790 }
3791 if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
3792 continue;
3793 }
3794 if (lp->portid == portid) {
3795 break;
3796 }
3797 }
3798
3799 if (lp < &fcp->portdb[MAX_FC_TARG]) {
3800 isp_prt(isp, ISP_LOGWARN, "Chan %d PortID 0x%06x "
3801 "already at %d handle %d state %d",
3802 chan, portid, dbidx, lp->handle, lp->state);
3803 continue;
3804 }
3805
3806 /*
3807 * We should have the index of the first free entry seen.
3808 */
3809 if (dbidx == MAX_FC_TARG) {
3810 isp_prt(isp, ISP_LOGERR,
3811 "port database too small to login PortID 0x%06x"
3812 "- increase MAX_FC_TARG", portid);
3813 continue;
3814 }
3815
3816 /*
3817 * Otherwise, point to our new home.
3818 */
3819 lp = &fcp->portdb[dbidx];
3820
3821 /*
3822 * Try to see if we are logged into this device,
3823 * and maybe log into it.
3824 *
3825 * isp_login_device will check for handle and
3826 * portid consistency after login.
3827 */
3828 if (isp_login_device(isp, chan, portid, &pdb,
3829 &FCPARAM(isp, 0)->isp_lasthdl)) {
3560 if (isp_login_device(isp, chan, portid, &pdb,
3561 &FCPARAM(isp, 0)->isp_lasthdl)) {
3830 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
3562 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
3831 goto abort;
3563 goto abort;
3832 }
3833 continue;
3834 }
3564 continue;
3565 }
3835 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
3836 goto abort;
3837 }
3838
3566
3839 nphdl = pdb.handle;
3840 MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
3841 MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
3842 nr = pdb.prli_word3;
3843
3844 /*
3845 * And go through the database *one* more time to make sure
3846 * that we do not make more than one entry that has the same
3847 * WWNN/WWPN duple
3848 */
3849 for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
3850 if ((fcp->portdb[dbidx].node_wwn == wwnn ||
3851 fcp->portdb[dbidx].node_wwn == 0) &&
3852 fcp->portdb[dbidx].port_wwn == wwpn) {
3853 break;
3854 }
3855 }
3856
3857 if (dbidx == MAX_FC_TARG) {
3858 ISP_MEMZERO(lp, sizeof (fcportdb_t));
3859 lp->handle = nphdl;
3860 lp->node_wwn = wwnn;
3861 lp->port_wwn = wwpn;
3862 lp->new_portid = portid;
3863 lp->new_prli_word3 = nr;
3864 lp->state = FC_PORTDB_STATE_NEW;
3865 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric port 0x%06x is a new entry", chan, portid);
3866 continue;
3867 }
3868
3869 if (fcp->portdb[dbidx].state != FC_PORTDB_STATE_ZOMBIE) {
3870 isp_prt(isp, ISP_LOGWARN,
3871 "Chan %d PortID 0x%x 0x%08x%08x/0x%08x%08x %ld "
3872 "already at idx %d, state 0x%x", chan, portid,
3873 (uint32_t) (wwnn >> 32), (uint32_t) wwnn,
3874 (uint32_t) (wwpn >> 32), (uint32_t) wwpn,
3875 (long) (lp - fcp->portdb), dbidx,
3876 fcp->portdb[dbidx].state);
3877 continue;
3878 }
3879
3880 /*
3881 * We found a zombie entry that matches us.
3882 * Revive it. We know that WWN and WWPN
3883 * are the same. For fabric devices, we
3884 * don't care that handle is different
3885 * as we assign that. If role or portid
3886 * are different, it maybe a changed device.
3887 */
3888 lp = &fcp->portdb[dbidx];
3889 lp->handle = nphdl;
3890 lp->node_wwn = wwnn;
3891 lp->new_portid = portid;
3892 lp->new_prli_word3 = nr;
3893 if (lp->portid != portid || lp->prli_word3 != nr) {
3894 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Zombie fabric port 0x%06x now changed", chan, portid);
3895 lp->state = FC_PORTDB_STATE_CHANGED;
3896 } else {
3897 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Zombie fabric port 0x%06x now pending valid", chan, portid);
3898 lp->state = FC_PORTDB_STATE_PENDING_VALID;
3899 }
3567 isp_pdb_add_update(isp, chan, &pdb);
3900 }
3901
3568 }
3569
3902 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
3570 if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
3903 goto abort;
3571 goto abort;
3904 }
3905 FC_SCRATCH_RELEASE(isp, chan);
3906 fcp->isp_loopstate = LOOP_FSCAN_DONE;
3907 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan);
3908 return (0);
3909}
3910
3911/*
3912 * Find an unused handle and try and use to login to a port.

--- 7 unchanged lines hidden (view full) ---

3920 if (ISP_CAP_2KLOGIN(isp)) {
3921 lim = NPH_MAX_2K;
3922 } else {
3923 lim = NPH_MAX;
3924 }
3925
3926 handle = isp_next_handle(isp, ohp);
3927 for (i = 0; i < lim; i++) {
3572 FC_SCRATCH_RELEASE(isp, chan);
3573 fcp->isp_loopstate = LOOP_FSCAN_DONE;
3574 isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan);
3575 return (0);
3576}
3577
3578/*
3579 * Find an unused handle and try and use to login to a port.

--- 7 unchanged lines hidden (view full) ---

3587 if (ISP_CAP_2KLOGIN(isp)) {
3588 lim = NPH_MAX_2K;
3589 } else {
3590 lim = NPH_MAX;
3591 }
3592
3593 handle = isp_next_handle(isp, ohp);
3594 for (i = 0; i < lim; i++) {
3928 /*
3929 * See if we're still logged into something with
3930 * this handle and that something agrees with this
3931 * port id.
3932 */
3595 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
3596 return (-1);
3597
3598 /* Check if this handle is free. */
3933 r = isp_getpdb(isp, chan, handle, p, 0);
3599 r = isp_getpdb(isp, chan, handle, p, 0);
3934 if (r == 0 && p->portid != portid) {
3935 (void) isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL, 1);
3936 } else if (r == 0) {
3600 if (r == 0) {
3601 if (p->portid != portid) {
3602 /* This handle is busy, try next one. */
3603 handle = isp_next_handle(isp, ohp);
3604 continue;
3605 }
3937 break;
3938 }
3606 break;
3607 }
3939 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
3608 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
3940 return (-1);
3609 return (-1);
3941 }
3610
3942 /*
3943 * Now try and log into the device
3944 */
3945 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI, 1);
3611 /*
3612 * Now try and log into the device
3613 */
3614 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI, 1);
3946 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
3947 return (-1);
3948 }
3949 if (r == 0) {
3950 break;
3951 } else if ((r & 0xffff) == MBOX_PORT_ID_USED) {
3952 /*
3953 * If we get here, then the firmwware still thinks we're logged into this device, but with a different
3954 * handle. We need to break that association. We used to try and just substitute the handle, but then
3955 * failed to get any data via isp_getpdb (below).
3956 */
3957 if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL, 1)) {
3958 isp_prt(isp, ISP_LOGERR, "baw... logout of %x failed", r >> 16);
3959 }
3615 if (r == 0) {
3616 break;
3617 } else if ((r & 0xffff) == MBOX_PORT_ID_USED) {
3618 /*
3619 * If we get here, then the firmwware still thinks we're logged into this device, but with a different
3620 * handle. We need to break that association. We used to try and just substitute the handle, but then
3621 * failed to get any data via isp_getpdb (below).
3622 */
3623 if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL, 1)) {
3624 isp_prt(isp, ISP_LOGERR, "baw... logout of %x failed", r >> 16);
3625 }
3960 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
3626 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
3961 return (-1);
3627 return (-1);
3962 }
3963 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI, 1);
3628 r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI, 1);
3964 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
3965 return (-1);
3966 }
3967 if (r != 0)
3968 i = lim;
3969 break;
3970 } else if ((r & 0xffff) == MBOX_LOOP_ID_USED) {
3971 /* Try the next handle. */
3972 handle = isp_next_handle(isp, ohp);
3973 } else {
3974 /* Give up. */

--- 8 unchanged lines hidden (view full) ---

3983 }
3984
3985 /*
3986 * If we successfully logged into it, get the PDB for it
3987 * so we can crosscheck that it is still what we think it
3988 * is and that we also have the role it plays
3989 */
3990 r = isp_getpdb(isp, chan, handle, p, 0);
3629 if (r != 0)
3630 i = lim;
3631 break;
3632 } else if ((r & 0xffff) == MBOX_LOOP_ID_USED) {
3633 /* Try the next handle. */
3634 handle = isp_next_handle(isp, ohp);
3635 } else {
3636 /* Give up. */

--- 8 unchanged lines hidden (view full) ---

3645 }
3646
3647 /*
3648 * If we successfully logged into it, get the PDB for it
3649 * so we can crosscheck that it is still what we think it
3650 * is and that we also have the role it plays
3651 */
3652 r = isp_getpdb(isp, chan, handle, p, 0);
3991 if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
3992 return (-1);
3993 }
3994 if (r != 0) {
3995 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x disappeared", chan, portid, handle);
3996 return (-1);
3997 }
3998
3999 if (p->handle != handle || p->portid != portid) {
4000 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x)",
4001 chan, portid, handle, p->portid, p->handle);

--- 1831 unchanged lines hidden (view full) ---

5833 }
5834 }
5835 } else {
5836 isp->isp_intoasync++;
5837 }
5838 return (acked);
5839}
5840
3653 if (r != 0) {
3654 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x disappeared", chan, portid, handle);
3655 return (-1);
3656 }
3657
3658 if (p->handle != handle || p->portid != portid) {
3659 isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x)",
3660 chan, portid, handle, p->portid, p->handle);

--- 1831 unchanged lines hidden (view full) ---

5492 }
5493 }
5494 } else {
5495 isp->isp_intoasync++;
5496 }
5497 return (acked);
5498}
5499
5841#define GET_24XX_BUS(isp, chan, msg) \
5842 if (IS_24XX(isp)) { \
5843 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff; \
5844 if (chan >= isp->isp_nchan) { \
5845 isp_prt(isp, ISP_LOGERR, "bogus channel %u for %s at line %d", chan, msg, __LINE__); \
5846 break; \
5847 } \
5848 }
5849
5850
5851static int
5852isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
5853{
5500static int
5501isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
5502{
5503 fcparam *fcp;
5854 int acked = 0;
5855 uint16_t chan;
5856
5857 if (IS_DUALBUS(isp)) {
5858 chan = ISP_READ(isp, OUTMAILBOX6);
5859 } else {
5860 chan = 0;
5861 }

--- 65 unchanged lines hidden (view full) ---

5927 case ASYNC_LIP_F8:
5928 case ASYNC_LIP_OCCURRED:
5929 case ASYNC_PTPMODE:
5930 /*
5931 * These are broadcast events that have to be sent across
5932 * all active channels.
5933 */
5934 for (chan = 0; chan < isp->isp_nchan; chan++) {
5504 int acked = 0;
5505 uint16_t chan;
5506
5507 if (IS_DUALBUS(isp)) {
5508 chan = ISP_READ(isp, OUTMAILBOX6);
5509 } else {
5510 chan = 0;
5511 }

--- 65 unchanged lines hidden (view full) ---

5577 case ASYNC_LIP_F8:
5578 case ASYNC_LIP_OCCURRED:
5579 case ASYNC_PTPMODE:
5580 /*
5581 * These are broadcast events that have to be sent across
5582 * all active channels.
5583 */
5584 for (chan = 0; chan < isp->isp_nchan; chan++) {
5935 fcparam *fcp = FCPARAM(isp, chan);
5585 fcp = FCPARAM(isp, chan);
5936 int topo = fcp->isp_topo;
5937
5938 if (fcp->role == ISP_ROLE_NONE) {
5939 continue;
5940 }
5941
5942 fcp->isp_loopstate = LOOP_NIL;
5943 ISP_SET_SENDMARKER(isp, chan, 1);

--- 40 unchanged lines hidden (view full) ---

5984 break;
5985
5986 case ASYNC_LOOP_UP:
5987 /*
5988 * This is a broadcast event that has to be sent across
5989 * all active channels.
5990 */
5991 for (chan = 0; chan < isp->isp_nchan; chan++) {
5586 int topo = fcp->isp_topo;
5587
5588 if (fcp->role == ISP_ROLE_NONE) {
5589 continue;
5590 }
5591
5592 fcp->isp_loopstate = LOOP_NIL;
5593 ISP_SET_SENDMARKER(isp, chan, 1);

--- 40 unchanged lines hidden (view full) ---

5634 break;
5635
5636 case ASYNC_LOOP_UP:
5637 /*
5638 * This is a broadcast event that has to be sent across
5639 * all active channels.
5640 */
5641 for (chan = 0; chan < isp->isp_nchan; chan++) {
5992 fcparam *fcp = FCPARAM(isp, chan);
5993
5994 if (fcp->role == ISP_ROLE_NONE) {
5642 fcp = FCPARAM(isp, chan);
5643 if (fcp->role == ISP_ROLE_NONE)
5995 continue;
5644 continue;
5996 }
5997
5998 ISP_SET_SENDMARKER(isp, chan, 1);
5999 isp_async(isp, ISPASYNC_LOOP_UP, chan);
6000#ifdef ISP_TARGET_MODE
6001 if (isp_target_async(isp, chan, mbox)) {
6002 acked = 1;
6003 }
6004#endif
6005 }
6006 break;
6007
6008 case ASYNC_LOOP_DOWN:
6009 /*
6010 * This is a broadcast event that has to be sent across
6011 * all active channels.
6012 */
6013 for (chan = 0; chan < isp->isp_nchan; chan++) {
5645 ISP_SET_SENDMARKER(isp, chan, 1);
5646 isp_async(isp, ISPASYNC_LOOP_UP, chan);
5647#ifdef ISP_TARGET_MODE
5648 if (isp_target_async(isp, chan, mbox)) {
5649 acked = 1;
5650 }
5651#endif
5652 }
5653 break;
5654
5655 case ASYNC_LOOP_DOWN:
5656 /*
5657 * This is a broadcast event that has to be sent across
5658 * all active channels.
5659 */
5660 for (chan = 0; chan < isp->isp_nchan; chan++) {
6014 fcparam *fcp = FCPARAM(isp, chan);
6015
6016 if (fcp->role == ISP_ROLE_NONE) {
5661 fcp = FCPARAM(isp, chan);
5662 if (fcp->role == ISP_ROLE_NONE)
6017 continue;
5663 continue;
6018 }
6019
6020 ISP_SET_SENDMARKER(isp, chan, 1);
6021 fcp->isp_loopstate = LOOP_NIL;
6022 isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
5664 ISP_SET_SENDMARKER(isp, chan, 1);
5665 fcp->isp_loopstate = LOOP_NIL;
5666 isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
6023
6024#ifdef ISP_TARGET_MODE
6025 if (isp_target_async(isp, chan, mbox)) {
6026 acked = 1;
6027 }
6028#endif
6029 }
6030 break;
6031
6032 case ASYNC_LOOP_RESET:
6033 /*
6034 * This is a broadcast event that has to be sent across
6035 * all active channels.
6036 */
6037 for (chan = 0; chan < isp->isp_nchan; chan++) {
5667#ifdef ISP_TARGET_MODE
5668 if (isp_target_async(isp, chan, mbox)) {
5669 acked = 1;
5670 }
5671#endif
5672 }
5673 break;
5674
5675 case ASYNC_LOOP_RESET:
5676 /*
5677 * This is a broadcast event that has to be sent across
5678 * all active channels.
5679 */
5680 for (chan = 0; chan < isp->isp_nchan; chan++) {
6038 fcparam *fcp = FCPARAM(isp, chan);
6039
6040 if (fcp->role == ISP_ROLE_NONE) {
5681 fcp = FCPARAM(isp, chan);
5682 if (fcp->role == ISP_ROLE_NONE)
6041 continue;
5683 continue;
6042 }
6043
6044 ISP_SET_SENDMARKER(isp, chan, 1);
6045 fcp->isp_loopstate = LOOP_NIL;
6046 isp_async(isp, ISPASYNC_LOOP_RESET, chan);
6047#ifdef ISP_TARGET_MODE
6048 if (isp_target_async(isp, chan, mbox)) {
6049 acked = 1;
6050 }
6051#endif
6052 }
6053 break;
6054
6055 case ASYNC_PDB_CHANGED:
6056 {
6057 int echan, nphdl, nlstate, reason;
6058
5684 ISP_SET_SENDMARKER(isp, chan, 1);
5685 fcp->isp_loopstate = LOOP_NIL;
5686 isp_async(isp, ISPASYNC_LOOP_RESET, chan);
5687#ifdef ISP_TARGET_MODE
5688 if (isp_target_async(isp, chan, mbox)) {
5689 acked = 1;
5690 }
5691#endif
5692 }
5693 break;
5694
5695 case ASYNC_PDB_CHANGED:
5696 {
5697 int echan, nphdl, nlstate, reason;
5698
6059 if (IS_24XX(isp)) {
6060 nphdl = ISP_READ(isp, OUTMAILBOX1);
6061 nlstate = ISP_READ(isp, OUTMAILBOX2);
5699 nphdl = ISP_READ(isp, OUTMAILBOX1);
5700 nlstate = ISP_READ(isp, OUTMAILBOX2);
5701 if (IS_24XX(isp))
6062 reason = ISP_READ(isp, OUTMAILBOX3) >> 8;
5702 reason = ISP_READ(isp, OUTMAILBOX3) >> 8;
6063 GET_24XX_BUS(isp, chan, "ASYNC_CHANGE_NOTIFY");
6064 echan = (nphdl == NIL_HANDLE) ?
6065 isp->isp_nchan - 1 : chan;
5703 else
5704 reason = 0xff;
5705 if (ISP_CAP_MULTI_ID(isp)) {
5706 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
5707 if (chan == 0xff || nphdl == NIL_HANDLE) {
5708 chan = 0;
5709 echan = isp->isp_nchan - 1;
5710 } else if (chan >= isp->isp_nchan) {
5711 break;
5712 } else {
5713 echan = chan;
5714 }
6066 } else {
5715 } else {
6067 nphdl = NIL_HANDLE;
6068 nlstate = reason = 0;
6069 chan = echan = 0;
6070 }
6071 for (; chan <= echan; chan++) {
5716 chan = echan = 0;
5717 }
5718 for (; chan <= echan; chan++) {
6072 fcparam *fcp = FCPARAM(isp, chan);
6073
6074 if (fcp->role == ISP_ROLE_NONE) {
5719 fcp = FCPARAM(isp, chan);
5720 if (fcp->role == ISP_ROLE_NONE)
6075 continue;
5721 continue;
6076 }
6077 if (fcp->isp_loopstate > LOOP_LTEST_DONE)
6078 fcp->isp_loopstate = LOOP_LTEST_DONE;
5722 if (fcp->isp_loopstate > LOOP_LTEST_DONE)
5723 fcp->isp_loopstate = LOOP_LTEST_DONE;
6079 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
5724 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
5725 ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
6080 }
6081 break;
6082 }
6083 case ASYNC_CHANGE_NOTIFY:
6084 {
5726 }
5727 break;
5728 }
5729 case ASYNC_CHANGE_NOTIFY:
5730 {
6085 int lochan, hichan;
5731 int portid;
6086
5732
6087 if (ISP_FW_NEWER_THAN(isp, 4, 0, 25) && ISP_CAP_MULTI_ID(isp)) {
6088 GET_24XX_BUS(isp, chan, "ASYNC_CHANGE_NOTIFY");
6089 lochan = chan;
6090 hichan = chan + 1;
5733 portid = ((ISP_READ(isp, OUTMAILBOX1) & 0xff) << 16) |
5734 ISP_READ(isp, OUTMAILBOX2);
5735 if (ISP_CAP_MULTI_ID(isp)) {
5736 chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
5737 if (chan >= isp->isp_nchan)
5738 break;
6091 } else {
5739 } else {
6092 lochan = 0;
6093 hichan = isp->isp_nchan;
5740 chan = 0;
6094 }
5741 }
6095 for (chan = lochan; chan < hichan; chan++) {
6096 fcparam *fcp = FCPARAM(isp, chan);
6097
6098 if (fcp->role == ISP_ROLE_NONE) {
6099 continue;
6100 }
6101
6102 if (fcp->isp_loopstate > LOOP_LSCAN_DONE)
6103 fcp->isp_loopstate = LOOP_LSCAN_DONE;
6104 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, ISPASYNC_CHANGE_SNS);
6105 }
5742 fcp = FCPARAM(isp, chan);
5743 if (fcp->role == ISP_ROLE_NONE)
5744 break;
5745 if (fcp->isp_loopstate > LOOP_LSCAN_DONE)
5746 fcp->isp_loopstate = LOOP_LSCAN_DONE;
5747 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
5748 ISPASYNC_CHANGE_SNS, portid);
6106 break;
6107 }
6108
6109 case ASYNC_CONNMODE:
6110 /*
6111 * This only applies to 2100 amd 2200 cards
6112 */
6113 if (!IS_2200(isp) && !IS_2100(isp)) {

--- 1037 unchanged lines hidden (view full) ---

7151 ISP_FC_OPMAP(0x00, 0x00), /* 0x55: */
7152 ISP_FC_OPMAP(0x00, 0x00), /* 0x56: */
7153 ISP_FC_OPMAP(0x00, 0x00), /* 0x57: */
7154 ISP_FC_OPMAP(0x00, 0x00), /* 0x58: */
7155 ISP_FC_OPMAP(0x00, 0x00), /* 0x59: */
7156 ISP_FC_OPMAP(0x00, 0x00), /* 0x5a: */
7157 ISP_FC_OPMAP(0x03, 0x01), /* 0x5b: MBOX_DRIVER_HEARTBEAT */
7158 ISP_FC_OPMAP(0xcf, 0x01), /* 0x5c: MBOX_FW_HEARTBEAT */
5749 break;
5750 }
5751
5752 case ASYNC_CONNMODE:
5753 /*
5754 * This only applies to 2100 amd 2200 cards
5755 */
5756 if (!IS_2200(isp) && !IS_2100(isp)) {

--- 1037 unchanged lines hidden (view full) ---

6794 ISP_FC_OPMAP(0x00, 0x00), /* 0x55: */
6795 ISP_FC_OPMAP(0x00, 0x00), /* 0x56: */
6796 ISP_FC_OPMAP(0x00, 0x00), /* 0x57: */
6797 ISP_FC_OPMAP(0x00, 0x00), /* 0x58: */
6798 ISP_FC_OPMAP(0x00, 0x00), /* 0x59: */
6799 ISP_FC_OPMAP(0x00, 0x00), /* 0x5a: */
6800 ISP_FC_OPMAP(0x03, 0x01), /* 0x5b: MBOX_DRIVER_HEARTBEAT */
6801 ISP_FC_OPMAP(0xcf, 0x01), /* 0x5c: MBOX_FW_HEARTBEAT */
7159 ISP_FC_OPMAP(0x07, 0x03), /* 0x5d: MBOX_GET_SET_DATA_RATE */
6802 ISP_FC_OPMAP(0x07, 0x1f), /* 0x5d: MBOX_GET_SET_DATA_RATE */
7160 ISP_FC_OPMAP(0x00, 0x00), /* 0x5e: */
7161 ISP_FC_OPMAP(0x00, 0x00), /* 0x5f: */
7162 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x60: MBOX_INIT_FIRMWARE */
7163 ISP_FC_OPMAP(0x00, 0x00), /* 0x61: */
7164 ISP_FC_OPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */
7165 ISP_FC_OPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
7166 ISP_FC_OPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */
7167 ISP_FC_OPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */

--- 761 unchanged lines hidden (view full) ---

7929 ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET);
7930 ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS);
7931 ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL);
7932 ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);
7933 }
7934 }
7935 }
7936
6803 ISP_FC_OPMAP(0x00, 0x00), /* 0x5e: */
6804 ISP_FC_OPMAP(0x00, 0x00), /* 0x5f: */
6805 ISP_FC_OPMAP(0xcf, 0x0f), /* 0x60: MBOX_INIT_FIRMWARE */
6806 ISP_FC_OPMAP(0x00, 0x00), /* 0x61: */
6807 ISP_FC_OPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */
6808 ISP_FC_OPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
6809 ISP_FC_OPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */
6810 ISP_FC_OPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */

--- 761 unchanged lines hidden (view full) ---

7572 ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET);
7573 ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS);
7574 ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL);
7575 ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);
7576 }
7577 }
7578 }
7579
7937 cleanup:
7580cleanup:
7938 isp->isp_nactive = 0;
7939 isp_clear_commands(isp);
7940 if (IS_FC(isp)) {
7941 for (i = 0; i < isp->isp_nchan; i++)
7581 isp->isp_nactive = 0;
7582 isp_clear_commands(isp);
7583 if (IS_FC(isp)) {
7584 for (i = 0; i < isp->isp_nchan; i++)
7942 isp_mark_portdb(isp, i, -1);
7585 isp_clear_portdb(isp, i);
7943 }
7944 return (res);
7945}
7946
7947/*
7948 * NVRAM Routines
7949 */
7950static int

--- 603 unchanged lines hidden ---
7586 }
7587 return (res);
7588}
7589
7590/*
7591 * NVRAM Routines
7592 */
7593static int

--- 603 unchanged lines hidden ---