xref: /freebsd/sys/dev/isp/isp.c (revision 22cf89c938886d14f5796fc49f9f020c23ea8eaf)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  *  Copyright (c) 2009-2020 Alexander Motin <mav@FreeBSD.org>
5  *  Copyright (c) 1997-2009 by Matthew Jacob
6  *  All rights reserved.
7  *
8  *  Redistribution and use in source and binary forms, with or without
9  *  modification, are permitted provided that the following conditions
10  *  are met:
11  *
12  *  1. Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *  2. Redistributions in binary form must reproduce the above copyright
15  *     notice, this list of conditions and the following disclaimer in the
16  *     documentation and/or other materials provided with the distribution.
17  *
18  *  THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  *  ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  *  SUCH DAMAGE.
29  *
30  */
31 
32 /*
33  * Machine and OS Independent (well, as best as possible)
34  * code for the Qlogic ISP SCSI and FC-SCSI adapters.
35  */
36 
37 /*
38  * Inspiration and ideas about this driver are from Erik Moe's Linux driver
39  * (qlogicisp.c) and Dave Miller's SBus version of same (qlogicisp.c). Some
40  * ideas dredged from the Solaris driver.
41  */
42 
43 /*
44  * Include header file appropriate for platform we're building on.
45  */
46 #ifdef	__NetBSD__
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD$");
49 #include <dev/ic/isp_netbsd.h>
50 #endif
51 #ifdef	__FreeBSD__
52 #include <sys/cdefs.h>
53 #include <dev/isp/isp_freebsd.h>
54 #endif
55 #ifdef	__OpenBSD__
56 #include <dev/ic/isp_openbsd.h>
57 #endif
58 #ifdef	__linux__
59 #include "isp_linux.h"
60 #endif
61 #ifdef	__svr4__
62 #include "isp_solaris.h"
63 #endif
64 
65 /*
66  * Local static data
67  */
68 static const char notresp[] = "Unknown IOCB in RESPONSE Queue (type 0x%x) @ idx %d (next %d)";
69 static const char bun[] = "bad underrun (count %d, resid %d, status %s)";
70 static const char lipd[] = "Chan %d LIP destroyed %d active commands";
71 static const char sacq[] = "unable to acquire scratch area";
72 
73 static const uint8_t alpa_map[] = {
74 	0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda,
75 	0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce,
76 	0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5,
77 	0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 0xb4, 0xb3,
78 	0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
79 	0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b,
80 	0x98, 0x97, 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81,
81 	0x80, 0x7c, 0x7a, 0x79, 0x76, 0x75, 0x74, 0x73,
82 	0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69,
83 	0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
84 	0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c,
85 	0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c,
86 	0x3a, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
87 	0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x27, 0x26,
88 	0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
89 	0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00
90 };
91 
92 /*
93  * Local function prototypes.
94  */
95 static int isp_handle_control(ispsoftc_t *, isphdr_t *);
96 static void isp_handle_rpt_id_acq(ispsoftc_t *, isphdr_t *);
97 static void isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *);
98 static void isp_clear_portdb(ispsoftc_t *, int);
99 static void isp_mark_portdb(ispsoftc_t *, int);
100 static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int);
101 static int isp_getpdb(ispsoftc_t *, int, uint16_t, isp_pdb_t *);
102 static int isp_gethandles(ispsoftc_t *, int, uint16_t *, int *, int);
103 static void isp_dump_chip_portdb(ispsoftc_t *, int);
104 static uint64_t isp_get_wwn(ispsoftc_t *, int, int, int);
105 static int isp_fclink_test(ispsoftc_t *, int, int);
106 static int isp_pdb_sync(ispsoftc_t *, int);
107 static int isp_scan_loop(ispsoftc_t *, int);
108 static int isp_gid_pt(ispsoftc_t *, int);
109 static int isp_scan_fabric(ispsoftc_t *, int);
110 static int isp_login_device(ispsoftc_t *, int, uint32_t, isp_pdb_t *, uint16_t *);
111 static int isp_register_fc4_type(ispsoftc_t *, int);
112 static int isp_register_fc4_features_24xx(ispsoftc_t *, int);
113 static int isp_register_port_name_24xx(ispsoftc_t *, int);
114 static int isp_register_node_name_24xx(ispsoftc_t *, int);
115 static uint16_t isp_next_handle(ispsoftc_t *, uint16_t *);
116 static int isp_fw_state(ispsoftc_t *, int);
117 static void isp_mboxcmd(ispsoftc_t *, mbreg_t *);
118 
119 static void isp_setdfltfcparm(ispsoftc_t *, int);
120 static int isp_read_nvram(ispsoftc_t *, int);
121 static void isp_rd_2xxx_flash(ispsoftc_t *, uint32_t, uint32_t *);
122 static int isp_read_flthdr_2xxx(ispsoftc_t *);
123 static void isp_parse_flthdr_2xxx(ispsoftc_t *, uint8_t *);
124 static int isp_read_flt_2xxx(ispsoftc_t *);
125 static int isp_parse_flt_2xxx(ispsoftc_t *, uint8_t *);
126 static int isp_read_nvram_2400(ispsoftc_t *);
127 static void isp_parse_nvram_2400(ispsoftc_t *, uint8_t *);
128 
129 static void
130 isp_change_fw_state(ispsoftc_t *isp, int chan, int state)
131 {
132 	fcparam *fcp = FCPARAM(isp, chan);
133 
134 	if (fcp->isp_fwstate == state)
135 		return;
136 	isp_prt(isp, ISP_LOGCONFIG|ISP_LOG_SANCFG,
137 	    "Chan %d Firmware state <%s->%s>", chan,
138 	    isp_fc_fw_statename(fcp->isp_fwstate), isp_fc_fw_statename(state));
139 	fcp->isp_fwstate = state;
140 }
141 
142 /*
143  * Reset Hardware.
144  *
145  * Hit the chip over the head, download new f/w if available and set it running.
146  *
147  * Locking done elsewhere.
148  */
149 
150 void
151 isp_reset(ispsoftc_t *isp, int do_load_defaults)
152 {
153 	mbreg_t mbs;
154 	char *buf;
155 	uint64_t fwt;
156 	uint32_t code_org, val;
157 	int loaded_fw, loops, i, dodnld = 1;
158 	const char *btype = "????";
159 	static const char dcrc[] = "Downloaded RISC Code Checksum Failure";
160 
161 	isp->isp_state = ISP_NILSTATE;
162 	ISP_DISABLE_INTS(isp);
163 
164 	/*
165 	 * Put the board into PAUSE mode (so we can read the SXP registers
166 	 * or write FPM/FBM registers).
167 	 */
168 	ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_HOST_INT);
169 	ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT);
170 	ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
171 
172 	switch (isp->isp_type) {
173 	case ISP_HA_FC_2400:
174 		btype = "2422";
175 		break;
176 	case ISP_HA_FC_2500:
177 		btype = "2532";
178 		break;
179 	case ISP_HA_FC_2600:
180 		btype = "2600";
181 		break;
182 	case ISP_HA_FC_2700:
183 		btype = "2700";
184 		break;
185 	case ISP_HA_FC_2800:
186 		btype = "2800";
187 		break;
188 	default:
189 		break;
190 	}
191 
192 	/*
193 	 * Stop DMA and wait for it to stop.
194 	 */
195 	ISP_WRITE(isp, BIU2400_CSR, BIU2400_DMA_STOP|(3 << 4));
196 	for (loops = 0; loops < 100000; loops++) {
197 		ISP_DELAY(10);
198 		val = ISP_READ(isp, BIU2400_CSR);
199 		if ((val & BIU2400_DMA_ACTIVE) == 0) {
200 			break;
201 		}
202 	}
203 	if (val & BIU2400_DMA_ACTIVE)
204 		isp_prt(isp, ISP_LOGERR, "DMA Failed to Stop on Reset");
205 
206 	/*
207 	 * Hold it in SOFT_RESET and STOP state for 100us.
208 	 */
209 	ISP_WRITE(isp, BIU2400_CSR, BIU2400_SOFT_RESET|BIU2400_DMA_STOP|(3 << 4));
210 	ISP_DELAY(100);
211 	for (loops = 0; loops < 10000; loops++) {
212 		ISP_DELAY(5);
213 		val = ISP_READ(isp, OUTMAILBOX0);
214 		if (val != 0x4)
215 			break;
216 	}
217 	switch (val) {
218 	case 0x0:
219 		break;
220 	case 0x4:
221 		isp_prt(isp, ISP_LOGERR, "The ROM code is busy after 50ms.");
222 		return;
223 	case 0xf:
224 		isp_prt(isp, ISP_LOGERR, "Board configuration error.");
225 		return;
226 	default:
227 		isp_prt(isp, ISP_LOGERR, "Unknown RISC Status Code 0x%x.", val);
228 		return;
229 	}
230 
231 	/*
232 	 * Reset RISC Processor
233 	 */
234 	ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET);
235 	ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RELEASE);
236 	ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RESET);
237 
238 	/*
239 	 * Post-RISC Reset stuff.
240 	 */
241 	for (loops = 0; loops < 10000; loops++) {
242 		ISP_DELAY(5);
243 		val = ISP_READ(isp, OUTMAILBOX0);
244 		if (val != 0x4)
245 			break;
246 	}
247 	switch (val) {
248 	case 0x0:
249 		break;
250 	case 0x4:
251 		isp_prt(isp, ISP_LOGERR, "The ROM code is busy after 50ms.");
252 		return;
253 	case 0xf:
254 		isp_prt(isp, ISP_LOGERR, "Board configuration error.");
255 		return;
256 	default:
257 		isp_prt(isp, ISP_LOGERR, "Unknown RISC Status Code 0x%x.", val);
258 		return;
259 	}
260 
261 	isp->isp_reqidx = isp->isp_reqodx = 0;
262 	isp->isp_resodx = 0;
263 	isp->isp_atioodx = 0;
264 	ISP_WRITE(isp, BIU2400_REQINP, 0);
265 	ISP_WRITE(isp, BIU2400_REQOUTP, 0);
266 	ISP_WRITE(isp, BIU2400_RSPINP, 0);
267 	ISP_WRITE(isp, BIU2400_RSPOUTP, 0);
268 	if (!IS_26XX(isp)) {
269 		ISP_WRITE(isp, BIU2400_PRI_REQINP, 0);
270 		ISP_WRITE(isp, BIU2400_PRI_REQOUTP, 0);
271 	}
272 	ISP_WRITE(isp, BIU2400_ATIO_RSPINP, 0);
273 	ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, 0);
274 
275 	/*
276 	 * Up until this point we've done everything by just reading or
277 	 * setting registers. From this point on we rely on at least *some*
278 	 * kind of firmware running in the card.
279 	 */
280 
281 	/*
282 	 * Do some sanity checking by running a NOP command.
283 	 * If it succeeds, the ROM firmware is now running.
284 	 */
285 	MBSINIT(&mbs, MBOX_NO_OP, MBLOGALL, 0);
286 	isp_mboxcmd(isp, &mbs);
287 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
288 		isp_prt(isp, ISP_LOGERR, "NOP command failed (%x)", mbs.param[0]);
289 		return;
290 	}
291 
292 	/*
293 	 * Do some operational tests
294 	 */
295 	{
296 		static const uint16_t patterns[MAX_MAILBOX] = {
297 			0x0000, 0xdead, 0xbeef, 0xffff,
298 			0xa5a5, 0x5a5a, 0x7f7f, 0x7ff7,
299 			0x3421, 0xabcd, 0xdcba, 0xfeef,
300 			0xbead, 0xdebe, 0x2222, 0x3333,
301 			0x5555, 0x6666, 0x7777, 0xaaaa,
302 			0xffff, 0xdddd, 0x9999, 0x1fbc,
303 			0x6666, 0x6677, 0x1122, 0x33ff,
304 			0x0000, 0x0001, 0x1000, 0x1010,
305 		};
306 		int nmbox = ISP_NMBOX(isp);
307 		MBSINIT(&mbs, MBOX_MAILBOX_REG_TEST, MBLOGALL, 0);
308 		for (i = 1; i < nmbox; i++) {
309 			mbs.param[i] = patterns[i];
310 		}
311 		isp_mboxcmd(isp, &mbs);
312 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
313 			return;
314 		}
315 		for (i = 1; i < nmbox; i++) {
316 			if (mbs.param[i] != patterns[i]) {
317 				isp_prt(isp, ISP_LOGERR, "Register Test Failed at Register %d: should have 0x%04x but got 0x%04x", i, patterns[i], mbs.param[i]);
318 				return;
319 			}
320 		}
321 	}
322 
323 	/*
324 	 * Download new Firmware, unless requested not to do so.
325 	 * This is made slightly trickier in some cases where the
326 	 * firmware of the ROM revision is newer than the revision
327 	 * compiled into the driver. So, where we used to compare
328 	 * versions of our f/w and the ROM f/w, now we just see
329 	 * whether we have f/w at all and whether a config flag
330 	 * has disabled our download.
331 	 */
332 	if ((isp->isp_mdvec->dv_ispfw == NULL) || (isp->isp_confopts & ISP_CFG_NORELOAD)) {
333 		dodnld = 0;
334 	} else {
335 
336 		/*
337 		 * Set up DMA for the request and response queues.
338 		 * We do this now so we can use the request queue
339 		 * for dma to load firmware from.
340 		 */
341 		if (ISP_MBOXDMASETUP(isp) != 0) {
342 			isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
343 			return;
344 		}
345 	}
346 
347 	code_org = ISP_CODE_ORG_2400;
348 	loaded_fw = 0;
349 	if (dodnld) {
350 		const uint32_t *ptr = isp->isp_mdvec->dv_ispfw;
351 		uint32_t la, wi, wl;
352 
353 		/*
354 		 * Keep loading until we run out of f/w.
355 		 */
356 		code_org = ptr[2];	/* 1st load address is our start addr */
357 		for (;;) {
358 			isp_prt(isp, ISP_LOGDEBUG0, "load 0x%x words of code at load address 0x%x", ptr[3], ptr[2]);
359 
360 			wi = 0;
361 			la = ptr[2];
362 			wl = ptr[3];
363 			while (wi < ptr[3]) {
364 				uint32_t *cp;
365 				uint32_t nw;
366 
367 				nw = min(wl, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) / 4);
368 				cp = isp->isp_rquest;
369 				for (i = 0; i < nw; i++)
370 					ISP_IOXPUT_32(isp, ptr[wi + i], &cp[i]);
371 				MEMORYBARRIER(isp, SYNC_REQUEST, 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)), -1);
372 				MBSINIT(&mbs, MBOX_LOAD_RISC_RAM, MBLOGALL, 0);
373 				mbs.param[1] = la;
374 				mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
375 				mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
376 				mbs.param[4] = nw >> 16;
377 				mbs.param[5] = nw;
378 				mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
379 				mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
380 				mbs.param[8] = la >> 16;
381 				isp_prt(isp, ISP_LOGDEBUG0, "LOAD RISC RAM %u words at load address 0x%x", nw, la);
382 				isp_mboxcmd(isp, &mbs);
383 				if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
384 					isp_prt(isp, ISP_LOGERR, "F/W download failed");
385 					return;
386 				}
387 				la += nw;
388 				wi += nw;
389 				wl -= nw;
390 			}
391 
392 			if (ptr[1] == 0) {
393 				break;
394 			}
395 			ptr += ptr[3];
396 		}
397 		loaded_fw = 1;
398 	} else if (IS_26XX(isp)) {
399 		isp_prt(isp, ISP_LOGDEBUG1, "loading firmware from flash");
400 		MBSINIT(&mbs, MBOX_LOAD_FLASH_FIRMWARE, MBLOGALL, 5000000);
401 		mbs.ibitm = 0x01;
402 		mbs.obitm = 0x07;
403 		isp_mboxcmd(isp, &mbs);
404 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
405 			isp_prt(isp, ISP_LOGERR, "Flash F/W load failed");
406 			return;
407 		}
408 	} else {
409 		isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download");
410 	}
411 
412 	/*
413 	 * If we loaded firmware, verify its checksum
414 	 */
415 	if (loaded_fw) {
416 		MBSINIT(&mbs, MBOX_VERIFY_CHECKSUM, MBLOGNONE, 0);
417 		mbs.param[1] = code_org >> 16;
418 		mbs.param[2] = code_org;
419 		isp_mboxcmd(isp, &mbs);
420 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
421 			isp_prt(isp, ISP_LOGERR, dcrc);
422 			return;
423 		}
424 	}
425 
426 	/*
427 	 * Now start it rolling.
428 	 *
429 	 * If we didn't actually download f/w,
430 	 * we still need to (re)start it.
431 	 */
432 	MBSINIT(&mbs, MBOX_EXEC_FIRMWARE, MBLOGALL, 5000000);
433 	mbs.param[1] = code_org >> 16;
434 	mbs.param[2] = code_org;
435 	if (!IS_26XX(isp))
436 		mbs.param[3] = loaded_fw ? 0 : 1;
437 	isp_mboxcmd(isp, &mbs);
438 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
439 		return;
440 
441 	/*
442 	 * Ask the chip for the current firmware version.
443 	 * This should prove that the new firmware is working.
444 	 */
445 	MBSINIT(&mbs, MBOX_ABOUT_FIRMWARE, MBLOGALL, 5000000);
446 	isp_mboxcmd(isp, &mbs);
447 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
448 		return;
449 	}
450 
451 	isp->isp_fwrev[0] = mbs.param[1];
452 	isp->isp_fwrev[1] = mbs.param[2];
453 	isp->isp_fwrev[2] = mbs.param[3];
454 	isp->isp_fwattr = mbs.param[6];
455 	isp->isp_fwattr |= ((uint64_t) mbs.param[15]) << 16;
456 	if (isp->isp_fwattr & ISP2400_FW_ATTR_EXTNDED) {
457 		isp->isp_fwattr |=
458 		    (((uint64_t) mbs.param[16]) << 32) |
459 		    (((uint64_t) mbs.param[17]) << 48);
460 	}
461 
462 	isp_prt(isp, ISP_LOGCONFIG, "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d",
463 	    btype, isp->isp_revision, dodnld? "loaded" : "resident", isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]);
464 
465 	fwt = isp->isp_fwattr;
466 	buf = FCPARAM(isp, 0)->isp_scanscratch;
467 	ISP_SNPRINTF(buf, ISP_FC_SCRLEN, "Attributes:");
468 	if (fwt & ISP2400_FW_ATTR_CLASS2) {
469 		fwt ^=ISP2400_FW_ATTR_CLASS2;
470 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s Class2", buf);
471 	}
472 	if (fwt & ISP2400_FW_ATTR_IP) {
473 		fwt ^=ISP2400_FW_ATTR_IP;
474 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s IP", buf);
475 	}
476 	if (fwt & ISP2400_FW_ATTR_MULTIID) {
477 		fwt ^=ISP2400_FW_ATTR_MULTIID;
478 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MultiID", buf);
479 	}
480 	if (fwt & ISP2400_FW_ATTR_SB2) {
481 		fwt ^=ISP2400_FW_ATTR_SB2;
482 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s SB2", buf);
483 	}
484 	if (fwt & ISP2400_FW_ATTR_T10CRC) {
485 		fwt ^=ISP2400_FW_ATTR_T10CRC;
486 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s T10CRC", buf);
487 	}
488 	if (fwt & ISP2400_FW_ATTR_VI) {
489 		fwt ^=ISP2400_FW_ATTR_VI;
490 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VI", buf);
491 	}
492 	if (fwt & ISP2400_FW_ATTR_MQ) {
493 		fwt ^=ISP2400_FW_ATTR_MQ;
494 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MQ", buf);
495 	}
496 	if (fwt & ISP2400_FW_ATTR_MSIX) {
497 		fwt ^=ISP2400_FW_ATTR_MSIX;
498 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s MSIX", buf);
499 	}
500 	if (fwt & ISP2400_FW_ATTR_FCOE) {
501 		fwt ^=ISP2400_FW_ATTR_FCOE;
502 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s FCOE", buf);
503 	}
504 	if (fwt & ISP2400_FW_ATTR_VP0) {
505 		fwt ^= ISP2400_FW_ATTR_VP0;
506 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VP0_Decoupling", buf);
507 	}
508 	if (fwt & ISP2400_FW_ATTR_EXPFW) {
509 		fwt ^= ISP2400_FW_ATTR_EXPFW;
510 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (Experimental)", buf);
511 	}
512 	if (fwt & ISP2400_FW_ATTR_HOTFW) {
513 		fwt ^= ISP2400_FW_ATTR_HOTFW;
514 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s HotFW", buf);
515 	}
516 	fwt &= ~ISP2400_FW_ATTR_EXTNDED;
517 	if (fwt & ISP2400_FW_ATTR_EXTVP) {
518 		fwt ^= ISP2400_FW_ATTR_EXTVP;
519 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ExtVP", buf);
520 	}
521 	if (fwt & ISP2400_FW_ATTR_VN2VN) {
522 		fwt ^= ISP2400_FW_ATTR_VN2VN;
523 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s VN2VN", buf);
524 	}
525 	if (fwt & ISP2400_FW_ATTR_EXMOFF) {
526 		fwt ^= ISP2400_FW_ATTR_EXMOFF;
527 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s EXMOFF", buf);
528 	}
529 	if (fwt & ISP2400_FW_ATTR_NPMOFF) {
530 		fwt ^= ISP2400_FW_ATTR_NPMOFF;
531 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s NPMOFF", buf);
532 	}
533 	if (fwt & ISP2400_FW_ATTR_DIFCHOP) {
534 		fwt ^= ISP2400_FW_ATTR_DIFCHOP;
535 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s DIFCHOP", buf);
536 	}
537 	if (fwt & ISP2400_FW_ATTR_SRIOV) {
538 		fwt ^= ISP2400_FW_ATTR_SRIOV;
539 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s SRIOV", buf);
540 	}
541 	if (fwt & ISP2400_FW_ATTR_ASICTMP) {
542 		fwt ^= ISP2400_FW_ATTR_ASICTMP;
543 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ASICTMP", buf);
544 	}
545 	if (fwt & ISP2400_FW_ATTR_ATIOMQ) {
546 		fwt ^= ISP2400_FW_ATTR_ATIOMQ;
547 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s ATIOMQ", buf);
548 	}
549 	if (fwt) {
550 		ISP_SNPRINTF(buf, ISP_FC_SCRLEN - strlen(buf), "%s (unknown 0x%08x%08x)", buf,
551 		    (uint32_t) (fwt >> 32), (uint32_t) fwt);
552 	}
553 	isp_prt(isp, ISP_LOGCONFIG, "%s", buf);
554 
555 	/*
556 	 * For the maximum number of commands take free exchange control block
557 	 * buffer count reported by firmware, limiting it to the maximum of our
558 	 * hardcoded handle format (16K now) minus some management reserve.
559 	 */
560 	MBSINIT(&mbs, MBOX_GET_RESOURCE_COUNT, MBLOGALL, 0);
561 	isp_mboxcmd(isp, &mbs);
562 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
563 		return;
564 	isp->isp_maxcmds = MIN(mbs.param[3], ISP_HANDLE_MAX - ISP_HANDLE_RESERVE);
565 	isp_prt(isp, ISP_LOGCONFIG, "%d max I/O command limit set", isp->isp_maxcmds);
566 
567 	/*
568 	 * If we don't have Multi-ID f/w loaded, we need to restrict channels to one.
569 	 * Only make this check for non-SCSI cards (I'm not sure firmware attributes
570 	 * work for them).
571 	 */
572 	if (isp->isp_nchan > 1) {
573 		if (!ISP_CAP_MULTI_ID(isp)) {
574 			isp_prt(isp, ISP_LOGWARN, "non-MULTIID f/w loaded, "
575 			    "only can enable 1 of %d channels", isp->isp_nchan);
576 			isp->isp_nchan = 1;
577 		} else if (!ISP_CAP_VP0(isp)) {
578 			isp_prt(isp, ISP_LOGWARN, "We can not use MULTIID "
579 			    "feature properly without VP0_Decoupling");
580 			isp->isp_nchan = 1;
581 		}
582 	}
583 
584 	/*
585 	 * Final DMA setup after we got isp_maxcmds.
586 	 */
587 	if (ISP_MBOXDMASETUP(isp) != 0) {
588 		isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
589 		return;
590 	}
591 
592 	/*
593 	 * Setup interrupts.
594 	 */
595 	if (ISP_IRQSETUP(isp) != 0) {
596 		isp_prt(isp, ISP_LOGERR, "Cannot setup IRQ");
597 		return;
598 	}
599 	ISP_ENABLE_INTS(isp);
600 
601 	for (i = 0; i < isp->isp_nchan; i++)
602 		isp_change_fw_state(isp, i, FW_CONFIG_WAIT);
603 
604 	isp->isp_state = ISP_RESETSTATE;
605 
606 	/*
607 	 * We get some default values established. As a side
608 	 * effect, NVRAM is read here (unless overridden by
609 	 * a configuration flag).
610 	 */
611 	if (do_load_defaults) {
612 		for (i = 0; i < isp->isp_nchan; i++)
613 			isp_setdfltfcparm(isp, i);
614 	}
615 }
616 
617 /*
618  * Clean firmware shutdown.
619  */
620 static int
621 isp_stop(ispsoftc_t *isp)
622 {
623 	mbreg_t mbs;
624 
625 	isp->isp_state = ISP_NILSTATE;
626 	MBSINIT(&mbs, MBOX_STOP_FIRMWARE, MBLOGALL, 500000);
627 	mbs.param[1] = 0;
628 	mbs.param[2] = 0;
629 	mbs.param[3] = 0;
630 	mbs.param[4] = 0;
631 	mbs.param[5] = 0;
632 	mbs.param[6] = 0;
633 	mbs.param[7] = 0;
634 	mbs.param[8] = 0;
635 	isp_mboxcmd(isp, &mbs);
636 	return (mbs.param[0] == MBOX_COMMAND_COMPLETE ? 0 : mbs.param[0]);
637 }
638 
639 /*
640  * Hardware shutdown.
641  */
642 void
643 isp_shutdown(ispsoftc_t *isp)
644 {
645 
646 	if (isp->isp_state >= ISP_RESETSTATE)
647 		isp_stop(isp);
648 	ISP_DISABLE_INTS(isp);
649 	ISP_WRITE(isp, BIU2400_ICR, 0);
650 	ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE);
651 }
652 
653 /*
654  * Initialize Parameters of Hardware to a known state.
655  *
656  * Locks are held before coming here.
657  */
658 void
659 isp_init(ispsoftc_t *isp)
660 {
661 	fcparam *fcp;
662 	isp_icb_2400_t local, *icbp = &local;
663 	mbreg_t mbs;
664 	int chan;
665 	int ownloopid = 0;
666 
667 	/*
668 	 * Check to see whether all channels have *some* kind of role
669 	 */
670 	for (chan = 0; chan < isp->isp_nchan; chan++) {
671 		fcp = FCPARAM(isp, chan);
672 		if (fcp->role != ISP_ROLE_NONE) {
673 			break;
674 		}
675 	}
676 	if (chan == isp->isp_nchan) {
677 		isp_prt(isp, ISP_LOG_WARN1, "all %d channels with role 'none'", chan);
678 		return;
679 	}
680 
681 	isp->isp_state = ISP_INITSTATE;
682 
683 	/*
684 	 * Start with channel 0.
685 	 */
686 	fcp = FCPARAM(isp, 0);
687 
688 	/*
689 	 * Turn on LIP F8 async event (1)
690 	 */
691 	MBSINIT(&mbs, MBOX_SET_FIRMWARE_OPTIONS, MBLOGALL, 0);
692 	mbs.param[1] = 1;
693 	isp_mboxcmd(isp, &mbs);
694 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
695 		return;
696 	}
697 
698 	ISP_MEMZERO(icbp, sizeof (*icbp));
699 	icbp->icb_fwoptions1 = fcp->isp_fwoptions;
700 	icbp->icb_fwoptions2 = fcp->isp_xfwoptions;
701 	icbp->icb_fwoptions3 = fcp->isp_zfwoptions;
702 	if (isp->isp_nchan > 1 && ISP_CAP_VP0(isp)) {
703 		icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
704 		icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
705 	} else {
706 		if (fcp->role & ISP_ROLE_TARGET)
707 			icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
708 		else
709 			icbp->icb_fwoptions1 &= ~ICB2400_OPT1_TGT_ENABLE;
710 		if (fcp->role & ISP_ROLE_INITIATOR)
711 			icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
712 		else
713 			icbp->icb_fwoptions1 |= ICB2400_OPT1_INI_DISABLE;
714 	}
715 
716 	icbp->icb_version = ICB_VERSION1;
717 	icbp->icb_maxfrmlen = DEFAULT_FRAMESIZE(isp);
718 	if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
719 		icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;
720 		if (IS_28XX(isp))
721 			icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN_28XX;
722 
723 		isp_prt(isp, ISP_LOGERR,
724 		    "bad frame length (%d) from NVRAM - using %d",
725 		    DEFAULT_FRAMESIZE(isp), icbp->icb_maxfrmlen);
726 	}
727 
728 	if (!IS_26XX(isp))
729 		icbp->icb_execthrottle = 0xffff;
730 
731 #ifdef	ISP_TARGET_MODE
732 	/*
733 	 * Set target exchange count. Take half if we are supporting both roles.
734 	 */
735 	if (icbp->icb_fwoptions1 & ICB2400_OPT1_TGT_ENABLE) {
736 		if ((icbp->icb_fwoptions1 & ICB2400_OPT1_INI_DISABLE) == 0)
737 			icbp->icb_xchgcnt = MIN(isp->isp_maxcmds / 2, ATPDPSIZE);
738 		else
739 			icbp->icb_xchgcnt = isp->isp_maxcmds;
740 	}
741 #endif
742 
743 	ownloopid = (isp->isp_confopts & ISP_CFG_OWNLOOPID) != 0;
744 	icbp->icb_hardaddr = fcp->isp_loopid;
745 	if (icbp->icb_hardaddr >= LOCAL_LOOP_LIM) {
746 		icbp->icb_hardaddr = 0;
747 		ownloopid = 0;
748 	}
749 
750 	if (ownloopid)
751 		icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS;
752 
753 	if (isp->isp_confopts & ISP_CFG_NOFCTAPE) {
754 		icbp->icb_fwoptions2 &= ~ICB2400_OPT2_FCTAPE;
755 	}
756 	if (isp->isp_confopts & ISP_CFG_FCTAPE) {
757 		icbp->icb_fwoptions2 |= ICB2400_OPT2_FCTAPE;
758 	}
759 
760 	for (chan = 0; chan < isp->isp_nchan; chan++) {
761 		if (icbp->icb_fwoptions2 & ICB2400_OPT2_FCTAPE)
762 			FCPARAM(isp, chan)->fctape_enabled = 1;
763 		else
764 			FCPARAM(isp, chan)->fctape_enabled = 0;
765 	}
766 
767 	switch (isp->isp_confopts & ISP_CFG_PORT_PREF) {
768 	case ISP_CFG_LPORT_ONLY:
769 		icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
770 		icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_ONLY;
771 		break;
772 	case ISP_CFG_NPORT_ONLY:
773 		icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
774 		icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY;
775 		break;
776 	case ISP_CFG_NPORT:
777 		/* ISP_CFG_PTP_2_LOOP not available in 24XX/25XX */
778 	case ISP_CFG_LPORT:
779 		icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
780 		icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
781 		break;
782 	default:
783 		/* Let NVRAM settings define it if they are sane */
784 		switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TOPO_MASK) {
785 		case ICB2400_OPT2_LOOP_ONLY:
786 		case ICB2400_OPT2_PTP_ONLY:
787 		case ICB2400_OPT2_LOOP_2_PTP:
788 			break;
789 		default:
790 			icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
791 			icbp->icb_fwoptions2 |= ICB2400_OPT2_LOOP_2_PTP;
792 		}
793 		break;
794 	}
795 
796 	switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK) {
797 	case ICB2400_OPT2_ZIO:
798 	case ICB2400_OPT2_ZIO1:
799 		icbp->icb_idelaytimer = 0;
800 		break;
801 	case 0:
802 		break;
803 	default:
804 		isp_prt(isp, ISP_LOGWARN, "bad value %x in fwopt2 timer field", icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK);
805 		icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TIMER_MASK;
806 		break;
807 	}
808 
809 	if (IS_26XX(isp)) {
810 		/* Use handshake to reduce global lock congestion. */
811 		icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHR;
812 		icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHA;
813 	}
814 
815 	if ((icbp->icb_fwoptions3 & ICB2400_OPT3_RSPSZ_MASK) == 0) {
816 		icbp->icb_fwoptions3 |= ICB2400_OPT3_RSPSZ_24;
817 	}
818 	if (isp->isp_confopts & ISP_CFG_1GB) {
819 		icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
820 		icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_1GB;
821 	} else if (isp->isp_confopts & ISP_CFG_2GB) {
822 		icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
823 		icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_2GB;
824 	} else if (isp->isp_confopts & ISP_CFG_4GB) {
825 		icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
826 		icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_4GB;
827 	} else if (isp->isp_confopts & ISP_CFG_8GB) {
828 		icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
829 		icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_8GB;
830 	} else if (isp->isp_confopts & ISP_CFG_16GB) {
831 		icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
832 		icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_16GB;
833 	} else if (isp->isp_confopts & ISP_CFG_32GB) {
834 		icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
835 		icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_32GB;
836 	} else if (isp->isp_confopts & ISP_CFG_64GB) {
837 		icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
838 		icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_64GB;
839 	} else {
840 		switch (icbp->icb_fwoptions3 & ICB2400_OPT3_RATE_MASK) {
841 		case ICB2400_OPT3_RATE_4GB:
842 		case ICB2400_OPT3_RATE_8GB:
843 		case ICB2400_OPT3_RATE_16GB:
844 		case ICB2400_OPT3_RATE_32GB:
845 		case ICB2400_OPT3_RATE_64GB:
846 		case ICB2400_OPT3_RATE_AUTO:
847 			break;
848 		case ICB2400_OPT3_RATE_2GB:
849 			if (isp->isp_type <= ISP_HA_FC_2500)
850 				break;
851 			/*FALLTHROUGH*/
852 		case ICB2400_OPT3_RATE_1GB:
853 			if (isp->isp_type <= ISP_HA_FC_2400)
854 				break;
855 			/*FALLTHROUGH*/
856 		default:
857 			icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
858 			icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO;
859 			break;
860 		}
861 	}
862 	if (ownloopid == 0) {
863 		icbp->icb_fwoptions3 |= ICB2400_OPT3_SOFTID;
864 	}
865 	icbp->icb_logintime = ICB_LOGIN_TOV;
866 
867 	if (fcp->isp_wwnn && fcp->isp_wwpn) {
868 		icbp->icb_fwoptions1 |= ICB2400_OPT1_BOTH_WWNS;
869 		MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
870 		MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwnn);
871 		isp_prt(isp, ISP_LOGDEBUG1, "Setting ICB Node 0x%08x%08x Port 0x%08x%08x", ((uint32_t) (fcp->isp_wwnn >> 32)), ((uint32_t) (fcp->isp_wwnn)),
872 		    ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn)));
873 	} else if (fcp->isp_wwpn) {
874 		icbp->icb_fwoptions1 &= ~ICB2400_OPT1_BOTH_WWNS;
875 		MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
876 		isp_prt(isp, ISP_LOGDEBUG1, "Setting ICB Node to be same as Port 0x%08x%08x", ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn)));
877 	} else {
878 		isp_prt(isp, ISP_LOGERR, "No valid WWNs to use");
879 		return;
880 	}
881 	icbp->icb_rspnsin = isp->isp_resodx;
882 	icbp->icb_rqstout = isp->isp_reqidx;
883 	icbp->icb_retry_count = fcp->isp_retry_count;
884 
885 	icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);
886 	if (icbp->icb_rqstqlen < 8) {
887 		isp_prt(isp, ISP_LOGERR, "bad request queue length %d", icbp->icb_rqstqlen);
888 		return;
889 	}
890 	icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp);
891 	if (icbp->icb_rsltqlen < 8) {
892 		isp_prt(isp, ISP_LOGERR, "bad result queue length %d",
893 		    icbp->icb_rsltqlen);
894 		return;
895 	}
896 	icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma);
897 	icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma);
898 	icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma);
899 	icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma);
900 
901 	icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma);
902 	icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma);
903 	icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma);
904 	icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
905 
906 #ifdef	ISP_TARGET_MODE
907 	/* unconditionally set up the ATIO queue if we support target mode */
908 	icbp->icb_atio_in = isp->isp_atioodx;
909 	icbp->icb_atioqlen = ATIO_QUEUE_LEN(isp);
910 	if (icbp->icb_atioqlen < 8) {
911 		isp_prt(isp, ISP_LOGERR, "bad ATIO queue length %d", icbp->icb_atioqlen);
912 		return;
913 	}
914 	icbp->icb_atioqaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_atioq_dma);
915 	icbp->icb_atioqaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_atioq_dma);
916 	icbp->icb_atioqaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_atioq_dma);
917 	icbp->icb_atioqaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_atioq_dma);
918 	isp_prt(isp, ISP_LOGDEBUG0, "isp_init: atioq %04x%04x%04x%04x", DMA_WD3(isp->isp_atioq_dma), DMA_WD2(isp->isp_atioq_dma),
919 	    DMA_WD1(isp->isp_atioq_dma), DMA_WD0(isp->isp_atioq_dma));
920 #endif
921 
922 	if (ISP_CAP_MSIX(isp) && isp->isp_nirq >= 2) {
923 		icbp->icb_msixresp = 1;
924 		if (IS_26XX(isp) && isp->isp_nirq >= 3)
925 			icbp->icb_msixatio = 2;
926 	}
927 
928 	isp_prt(isp, ISP_LOGDEBUG0, "isp_init: fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x", icbp->icb_fwoptions1, icbp->icb_fwoptions2, icbp->icb_fwoptions3);
929 
930 	isp_prt(isp, ISP_LOGDEBUG0, "isp_init: rqst %04x%04x%04x%04x rsp %04x%04x%04x%04x", DMA_WD3(isp->isp_rquest_dma), DMA_WD2(isp->isp_rquest_dma),
931 	    DMA_WD1(isp->isp_rquest_dma), DMA_WD0(isp->isp_rquest_dma), DMA_WD3(isp->isp_result_dma), DMA_WD2(isp->isp_result_dma),
932 	    DMA_WD1(isp->isp_result_dma), DMA_WD0(isp->isp_result_dma));
933 
934 	if (FC_SCRATCH_ACQUIRE(isp, 0)) {
935 		isp_prt(isp, ISP_LOGERR, sacq);
936 		return;
937 	}
938 	ISP_MEMZERO(fcp->isp_scratch, ISP_FC_SCRLEN);
939 	isp_put_icb_2400(isp, icbp, fcp->isp_scratch);
940 	if (isp->isp_dblev & ISP_LOGDEBUG1) {
941 		isp_print_bytes(isp, "isp_init",
942 		    sizeof (*icbp), fcp->isp_scratch);
943 	}
944 
945 	/*
946 	 * Now fill in information about any additional channels
947 	 */
948 	if (isp->isp_nchan > 1) {
949 		isp_icb_2400_vpinfo_t vpinfo, *vdst;
950 		vp_port_info_t pi, *pdst;
951 		size_t amt = 0;
952 		uint8_t *off;
953 
954 		vpinfo.vp_global_options = ICB2400_VPGOPT_GEN_RIDA;
955 		if (ISP_CAP_VP0(isp)) {
956 			vpinfo.vp_global_options |= ICB2400_VPGOPT_VP0_DECOUPLE;
957 			vpinfo.vp_count = isp->isp_nchan;
958 			chan = 0;
959 		} else {
960 			vpinfo.vp_count = isp->isp_nchan - 1;
961 			chan = 1;
962 		}
963 		off = fcp->isp_scratch;
964 		off += ICB2400_VPINFO_OFF;
965 		vdst = (isp_icb_2400_vpinfo_t *) off;
966 		isp_put_icb_2400_vpinfo(isp, &vpinfo, vdst);
967 		amt = ICB2400_VPINFO_OFF + sizeof (isp_icb_2400_vpinfo_t);
968 		for (; chan < isp->isp_nchan; chan++) {
969 			fcparam *fcp2;
970 
971 			ISP_MEMZERO(&pi, sizeof (pi));
972 			fcp2 = FCPARAM(isp, chan);
973 			if (fcp2->role != ISP_ROLE_NONE) {
974 				pi.vp_port_options = ICB2400_VPOPT_ENABLED |
975 				    ICB2400_VPOPT_ENA_SNSLOGIN;
976 				if (fcp2->role & ISP_ROLE_INITIATOR)
977 					pi.vp_port_options |= ICB2400_VPOPT_INI_ENABLE;
978 				if ((fcp2->role & ISP_ROLE_TARGET) == 0)
979 					pi.vp_port_options |= ICB2400_VPOPT_TGT_DISABLE;
980 				if (fcp2->isp_loopid < LOCAL_LOOP_LIM) {
981 					pi.vp_port_loopid = fcp2->isp_loopid;
982 					if (isp->isp_confopts & ISP_CFG_OWNLOOPID)
983 						pi.vp_port_options |= ICB2400_VPOPT_HARD_ADDRESS;
984 				}
985 
986 			}
987 			MAKE_NODE_NAME_FROM_WWN(pi.vp_port_portname, fcp2->isp_wwpn);
988 			MAKE_NODE_NAME_FROM_WWN(pi.vp_port_nodename, fcp2->isp_wwnn);
989 			off = fcp->isp_scratch;
990 			if (ISP_CAP_VP0(isp))
991 				off += ICB2400_VPINFO_PORT_OFF(chan);
992 			else
993 				off += ICB2400_VPINFO_PORT_OFF(chan - 1);
994 			pdst = (vp_port_info_t *) off;
995 			isp_put_vp_port_info(isp, &pi, pdst);
996 			amt += ICB2400_VPOPT_WRITE_SIZE;
997 		}
998 		if (isp->isp_dblev & ISP_LOGDEBUG1) {
999 			isp_print_bytes(isp, "isp_init",
1000 			    amt - ICB2400_VPINFO_OFF,
1001 			    (char *)fcp->isp_scratch + ICB2400_VPINFO_OFF);
1002 		}
1003 	}
1004 
1005 	/*
1006 	 * Init the firmware
1007 	 */
1008 	MBSINIT(&mbs, 0, MBLOGALL, 30000000);
1009 	if (isp->isp_nchan > 1) {
1010 		mbs.param[0] = MBOX_INIT_FIRMWARE_MULTI_ID;
1011 	} else {
1012 		mbs.param[0] = MBOX_INIT_FIRMWARE;
1013 	}
1014 	mbs.param[1] = 0;
1015 	mbs.param[2] = DMA_WD1(fcp->isp_scdma);
1016 	mbs.param[3] = DMA_WD0(fcp->isp_scdma);
1017 	mbs.param[6] = DMA_WD3(fcp->isp_scdma);
1018 	mbs.param[7] = DMA_WD2(fcp->isp_scdma);
1019 	isp_prt(isp, ISP_LOGDEBUG0, "INIT F/W from %04x%04x%04x%04x", DMA_WD3(fcp->isp_scdma), DMA_WD2(fcp->isp_scdma), DMA_WD1(fcp->isp_scdma), DMA_WD0(fcp->isp_scdma));
1020 	MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp), 0);
1021 	isp_mboxcmd(isp, &mbs);
1022 	FC_SCRATCH_RELEASE(isp, 0);
1023 
1024 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1025 		return;
1026 	}
1027 
1028 	/*
1029 	 * Whatever happens, we're now committed to being here.
1030 	 */
1031 	isp->isp_state = ISP_RUNSTATE;
1032 }
1033 
1034 static int
1035 isp_fc_enable_vp(ispsoftc_t *isp, int chan)
1036 {
1037 	fcparam *fcp = FCPARAM(isp, chan);
1038 	vp_modify_t vp;
1039 	int retval;
1040 
1041 	/* Build a VP MODIFY command in memory */
1042 	ISP_MEMZERO(&vp, sizeof(vp));
1043 	vp.vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY;
1044 	vp.vp_mod_hdr.rqs_entry_count = 1;
1045 	vp.vp_mod_cnt = 1;
1046 	vp.vp_mod_idx0 = chan;
1047 	vp.vp_mod_cmd = VP_MODIFY_ENA;
1048 	vp.vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED |
1049 	    ICB2400_VPOPT_ENA_SNSLOGIN;
1050 	if (fcp->role & ISP_ROLE_INITIATOR)
1051 		vp.vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE;
1052 	if ((fcp->role & ISP_ROLE_TARGET) == 0)
1053 		vp.vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE;
1054 	if (fcp->isp_loopid < LOCAL_LOOP_LIM) {
1055 		vp.vp_mod_ports[0].loopid = fcp->isp_loopid;
1056 		if (isp->isp_confopts & ISP_CFG_OWNLOOPID)
1057 			vp.vp_mod_ports[0].options |= ICB2400_VPOPT_HARD_ADDRESS;
1058 	}
1059 	MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwpn, fcp->isp_wwpn);
1060 	MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwnn, fcp->isp_wwnn);
1061 
1062 	retval = isp_exec_entry_queue(isp, &vp, &vp, 5);
1063 	if (retval != 0) {
1064 		isp_prt(isp, ISP_LOGERR, "%s: VP_MODIFY of chan %d error %d",
1065 		    __func__, chan, retval);
1066 		return (retval);
1067 	}
1068 
1069 	if (vp.vp_mod_hdr.rqs_flags != 0 || vp.vp_mod_status != VP_STS_OK) {
1070 		isp_prt(isp, ISP_LOGERR,
1071 		    "%s: VP_MODIFY of Chan %d failed with flags %x status %d",
1072 		    __func__, chan, vp.vp_mod_hdr.rqs_flags, vp.vp_mod_status);
1073 		return (EIO);
1074 	}
1075 	return (0);
1076 }
1077 
1078 static int
1079 isp_fc_disable_vp(ispsoftc_t *isp, int chan)
1080 {
1081 	vp_ctrl_info_t vp;
1082 	int retval;
1083 
1084 	/* Build a VP CTRL command in memory */
1085 	ISP_MEMZERO(&vp, sizeof(vp));
1086 	vp.vp_ctrl_hdr.rqs_entry_type = RQSTYPE_VP_CTRL;
1087 	vp.vp_ctrl_hdr.rqs_entry_count = 1;
1088 	if (ISP_CAP_VP0(isp)) {
1089 		vp.vp_ctrl_status = 1;
1090 	} else {
1091 		vp.vp_ctrl_status = 0;
1092 		chan--;	/* VP0 can not be controlled in this case. */
1093 	}
1094 	vp.vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL;
1095 	vp.vp_ctrl_vp_count = 1;
1096 	vp.vp_ctrl_idmap[chan / 16] |= (1 << chan % 16);
1097 
1098 	retval = isp_exec_entry_queue(isp, &vp, &vp, 5);
1099 	if (retval != 0) {
1100 		isp_prt(isp, ISP_LOGERR, "%s: VP_CTRL of chan %d error %d",
1101 		    __func__, chan, retval);
1102 		return (retval);
1103 	}
1104 
1105 	if (vp.vp_ctrl_hdr.rqs_flags != 0 || vp.vp_ctrl_status != 0) {
1106 		isp_prt(isp, ISP_LOGERR,
1107 		    "%s: VP_CTRL of Chan %d failed with flags %x status %d %d",
1108 		    __func__, chan, vp.vp_ctrl_hdr.rqs_flags,
1109 		    vp.vp_ctrl_status, vp.vp_ctrl_index_fail);
1110 		return (EIO);
1111 	}
1112 	return (0);
1113 }
1114 
1115 static int
1116 isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role)
1117 {
1118 	fcparam *fcp = FCPARAM(isp, chan);
1119 	int i, was, res = 0;
1120 
1121 	if (chan >= isp->isp_nchan) {
1122 		isp_prt(isp, ISP_LOGWARN, "%s: bad channel %d", __func__, chan);
1123 		return (ENXIO);
1124 	}
1125 	if (fcp->role == new_role)
1126 		return (0);
1127 	for (was = 0, i = 0; i < isp->isp_nchan; i++) {
1128 		if (FCPARAM(isp, i)->role != ISP_ROLE_NONE)
1129 			was++;
1130 	}
1131 	if (was == 0 || (was == 1 && fcp->role != ISP_ROLE_NONE)) {
1132 		fcp->role = new_role;
1133 		return (isp_reinit(isp, 0));
1134 	}
1135 	if (fcp->role != ISP_ROLE_NONE) {
1136 		res = isp_fc_disable_vp(isp, chan);
1137 		isp_clear_portdb(isp, chan);
1138 	}
1139 	fcp->role = new_role;
1140 	if (fcp->role != ISP_ROLE_NONE)
1141 		res = isp_fc_enable_vp(isp, chan);
1142 	return (res);
1143 }
1144 
1145 static void
1146 isp_clear_portdb(ispsoftc_t *isp, int chan)
1147 {
1148 	fcparam *fcp = FCPARAM(isp, chan);
1149 	fcportdb_t *lp;
1150 	int i;
1151 
1152 	for (i = 0; i < MAX_FC_TARG; i++) {
1153 		lp = &fcp->portdb[i];
1154 		switch (lp->state) {
1155 		case FC_PORTDB_STATE_DEAD:
1156 		case FC_PORTDB_STATE_CHANGED:
1157 		case FC_PORTDB_STATE_VALID:
1158 			lp->state = FC_PORTDB_STATE_NIL;
1159 			isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
1160 			break;
1161 		case FC_PORTDB_STATE_NIL:
1162 		case FC_PORTDB_STATE_NEW:
1163 			lp->state = FC_PORTDB_STATE_NIL;
1164 			break;
1165 		case FC_PORTDB_STATE_ZOMBIE:
1166 			break;
1167 		default:
1168 			panic("Don't know how to clear state %d\n", lp->state);
1169 		}
1170 	}
1171 }
1172 
1173 static void
1174 isp_mark_portdb(ispsoftc_t *isp, int chan)
1175 {
1176 	fcparam *fcp = FCPARAM(isp, chan);
1177 	fcportdb_t *lp;
1178 	int i;
1179 
1180 	for (i = 0; i < MAX_FC_TARG; i++) {
1181 		lp = &fcp->portdb[i];
1182 		if (lp->state == FC_PORTDB_STATE_NIL)
1183 			continue;
1184 		if (lp->portid >= DOMAIN_CONTROLLER_BASE &&
1185 		    lp->portid <= DOMAIN_CONTROLLER_END)
1186 			continue;
1187 		fcp->portdb[i].probational = 1;
1188 	}
1189 }
1190 
1191 /*
1192  * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards
1193  * or via FABRIC LOGIN/FABRIC LOGOUT for other cards.
1194  */
1195 static int
1196 isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid, int flags)
1197 {
1198 	isp_plogx_t pl;
1199 	uint32_t sst, parm1;
1200 	int retval, lev;
1201 	const char *msg;
1202 	char buf[64];
1203 
1204 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d PLOGX %s PortID 0x%06x nphdl 0x%x",
1205 	    chan, (flags & PLOGX_FLG_CMD_MASK) == PLOGX_FLG_CMD_PLOGI ?
1206 	    "Login":"Logout", portid, handle);
1207 
1208 	ISP_MEMZERO(&pl, sizeof(pl));
1209 	pl.plogx_header.rqs_entry_count = 1;
1210 	pl.plogx_header.rqs_entry_type = RQSTYPE_LOGIN;
1211 	pl.plogx_nphdl = handle;
1212 	pl.plogx_vphdl = chan;
1213 	pl.plogx_portlo = portid;
1214 	pl.plogx_rspsz_porthi = (portid >> 16) & 0xff;
1215 	pl.plogx_flags = flags;
1216 
1217 	retval = isp_exec_entry_queue(isp, &pl, &pl, 3 * ICB_LOGIN_TOV);
1218 	if (retval != 0) {
1219 		isp_prt(isp, ISP_LOGERR, "%s: PLOGX of chan %d error %d",
1220 		    __func__, chan, retval);
1221 		return (retval);
1222 	}
1223 
1224 	if (pl.plogx_status == PLOGX_STATUS_OK) {
1225 		return (0);
1226 	} else if (pl.plogx_status != PLOGX_STATUS_IOCBERR) {
1227 		isp_prt(isp, ISP_LOGWARN,
1228 		    "status 0x%x on port login IOCB channel %d",
1229 		    pl.plogx_status, chan);
1230 		return (-1);
1231 	}
1232 
1233 	sst = pl.plogx_ioparm[0].lo16 | (pl.plogx_ioparm[0].hi16 << 16);
1234 	parm1 = pl.plogx_ioparm[1].lo16 | (pl.plogx_ioparm[1].hi16 << 16);
1235 
1236 	retval = -1;
1237 	lev = ISP_LOGERR;
1238 	msg = NULL;
1239 
1240 	switch (sst) {
1241 	case PLOGX_IOCBERR_NOLINK:
1242 		msg = "no link";
1243 		break;
1244 	case PLOGX_IOCBERR_NOIOCB:
1245 		msg = "no IOCB buffer";
1246 		break;
1247 	case PLOGX_IOCBERR_NOXGHG:
1248 		msg = "no Exchange Control Block";
1249 		break;
1250 	case PLOGX_IOCBERR_FAILED:
1251 		ISP_SNPRINTF(buf, sizeof (buf), "reason 0x%x (last LOGIN state 0x%x)", parm1 & 0xff, (parm1 >> 8) & 0xff);
1252 		msg = buf;
1253 		break;
1254 	case PLOGX_IOCBERR_NOFABRIC:
1255 		msg = "no fabric";
1256 		break;
1257 	case PLOGX_IOCBERR_NOTREADY:
1258 		msg = "firmware not ready";
1259 		break;
1260 	case PLOGX_IOCBERR_NOLOGIN:
1261 		ISP_SNPRINTF(buf, sizeof (buf), "not logged in (last state 0x%x)", parm1);
1262 		msg = buf;
1263 		retval = MBOX_NOT_LOGGED_IN;
1264 		break;
1265 	case PLOGX_IOCBERR_REJECT:
1266 		ISP_SNPRINTF(buf, sizeof (buf), "LS_RJT = 0x%x", parm1);
1267 		msg = buf;
1268 		break;
1269 	case PLOGX_IOCBERR_NOPCB:
1270 		msg = "no PCB allocated";
1271 		break;
1272 	case PLOGX_IOCBERR_EINVAL:
1273 		ISP_SNPRINTF(buf, sizeof (buf), "invalid parameter at offset 0x%x", parm1);
1274 		msg = buf;
1275 		break;
1276 	case PLOGX_IOCBERR_PORTUSED:
1277 		lev = ISP_LOG_SANCFG|ISP_LOG_WARN1;
1278 		ISP_SNPRINTF(buf, sizeof (buf), "already logged in with N-Port handle 0x%x", parm1);
1279 		msg = buf;
1280 		retval = MBOX_PORT_ID_USED | (parm1 << 16);
1281 		break;
1282 	case PLOGX_IOCBERR_HNDLUSED:
1283 		lev = ISP_LOG_SANCFG|ISP_LOG_WARN1;
1284 		ISP_SNPRINTF(buf, sizeof (buf), "handle already used for PortID 0x%06x", parm1);
1285 		msg = buf;
1286 		retval = MBOX_LOOP_ID_USED;
1287 		break;
1288 	case PLOGX_IOCBERR_NOHANDLE:
1289 		msg = "no handle allocated";
1290 		break;
1291 	case PLOGX_IOCBERR_NOFLOGI:
1292 		msg = "no FLOGI_ACC";
1293 		break;
1294 	default:
1295 		ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x", pl.plogx_status, flags);
1296 		msg = buf;
1297 		break;
1298 	}
1299 	if (msg) {
1300 		isp_prt(isp, lev, "Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s",
1301 		    chan, portid, handle, msg);
1302 	}
1303 	return (retval);
1304 }
1305 
1306 static int
1307 isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb)
1308 {
1309 	mbreg_t mbs;
1310 	union {
1311 		isp_pdb_24xx_t bill;
1312 	} un;
1313 
1314 	MBSINIT(&mbs, MBOX_GET_PORT_DB,
1315 	    MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 250000);
1316 	mbs.ibits = (1 << 9)|(1 << 10);
1317 	mbs.param[1] = id;
1318 	mbs.param[2] = DMA_WD1(isp->isp_iocb_dma);
1319 	mbs.param[3] = DMA_WD0(isp->isp_iocb_dma);
1320 	mbs.param[6] = DMA_WD3(isp->isp_iocb_dma);
1321 	mbs.param[7] = DMA_WD2(isp->isp_iocb_dma);
1322 	mbs.param[9] = chan;
1323 	MEMORYBARRIER(isp, SYNC_IFORDEV, 0, sizeof(un), chan);
1324 
1325 	isp_mboxcmd(isp, &mbs);
1326 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE)
1327 		return (mbs.param[0] | (mbs.param[1] << 16));
1328 
1329 	MEMORYBARRIER(isp, SYNC_IFORCPU, 0, sizeof(un), chan);
1330 	isp_get_pdb_24xx(isp, isp->isp_iocb, &un.bill);
1331 	pdb->handle = un.bill.pdb_handle;
1332 	pdb->prli_word0 = un.bill.pdb_prli_svc0;
1333 	pdb->prli_word3 = un.bill.pdb_prli_svc3;
1334 	pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits);
1335 	ISP_MEMCPY(pdb->portname, un.bill.pdb_portname, 8);
1336 	ISP_MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8);
1337 	isp_prt(isp, ISP_LOGDEBUG0,
1338 	    "Chan %d handle 0x%x Port 0x%06x flags 0x%x curstate %x laststate %x",
1339 	    chan, id, pdb->portid, un.bill.pdb_flags,
1340 	    un.bill.pdb_curstate, un.bill.pdb_laststate);
1341 
1342 	if (un.bill.pdb_curstate < PDB2400_STATE_PLOGI_DONE || un.bill.pdb_curstate > PDB2400_STATE_LOGGED_IN) {
1343 		mbs.param[0] = MBOX_NOT_LOGGED_IN;
1344 		return (mbs.param[0]);
1345 	}
1346 	return (0);
1347 }
1348 
1349 static int
1350 isp_gethandles(ispsoftc_t *isp, int chan, uint16_t *handles, int *num, int loop)
1351 {
1352 	fcparam *fcp = FCPARAM(isp, chan);
1353 	mbreg_t mbs;
1354 	isp_pnhle_24xx_t el4, *elp4;
1355 	int i, j;
1356 	uint32_t p;
1357 
1358 	MBSINIT(&mbs, MBOX_GET_ID_LIST, MBLOGALL, 250000);
1359 	mbs.param[2] = DMA_WD1(fcp->isp_scdma);
1360 	mbs.param[3] = DMA_WD0(fcp->isp_scdma);
1361 	mbs.param[6] = DMA_WD3(fcp->isp_scdma);
1362 	mbs.param[7] = DMA_WD2(fcp->isp_scdma);
1363 	mbs.param[8] = ISP_FC_SCRLEN;
1364 	mbs.param[9] = chan;
1365 	if (FC_SCRATCH_ACQUIRE(isp, chan)) {
1366 		isp_prt(isp, ISP_LOGERR, sacq);
1367 		return (-1);
1368 	}
1369 	MEMORYBARRIER(isp, SYNC_SFORDEV, 0, ISP_FC_SCRLEN, chan);
1370 	isp_mboxcmd(isp, &mbs);
1371 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1372 		FC_SCRATCH_RELEASE(isp, chan);
1373 		return (mbs.param[0] | (mbs.param[1] << 16));
1374 	}
1375 	MEMORYBARRIER(isp, SYNC_SFORCPU, 0, ISP_FC_SCRLEN, chan);
1376 	elp4 = fcp->isp_scratch;
1377 	for (i = 0, j = 0; i < mbs.param[1] && j < *num; i++) {
1378 		isp_get_pnhle_24xx(isp, &elp4[i], &el4);
1379 		p = el4.pnhle_port_id_lo | (el4.pnhle_port_id_hi << 16);
1380 		if (loop && (p >> 8) != (fcp->isp_portid >> 8))
1381 			continue;
1382 		handles[j++] = el4.pnhle_handle;
1383 	}
1384 	*num = j;
1385 	FC_SCRATCH_RELEASE(isp, chan);
1386 	return (0);
1387 }
1388 
1389 static void
1390 isp_dump_chip_portdb(ispsoftc_t *isp, int chan)
1391 {
1392 	isp_pdb_t pdb;
1393 	uint16_t nphdl;
1394 
1395 	isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d chip port dump", chan);
1396 	for (nphdl = 0; nphdl != NPH_MAX_2K; nphdl++) {
1397 		if (isp_getpdb(isp, chan, nphdl, &pdb)) {
1398 			continue;
1399 		}
1400 		isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d Handle 0x%04x "
1401 		    "PortID 0x%06x WWPN 0x%02x%02x%02x%02x%02x%02x%02x%02x",
1402 		    chan, nphdl, pdb.portid, pdb.portname[0], pdb.portname[1],
1403 		    pdb.portname[2], pdb.portname[3], pdb.portname[4],
1404 		    pdb.portname[5], pdb.portname[6], pdb.portname[7]);
1405 	}
1406 }
1407 
1408 static uint64_t
1409 isp_get_wwn(ispsoftc_t *isp, int chan, int nphdl, int nodename)
1410 {
1411 	uint64_t wwn = INI_NONE;
1412 	mbreg_t mbs;
1413 
1414 	MBSINIT(&mbs, MBOX_GET_PORT_NAME,
1415 	    MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 500000);
1416 	mbs.param[1] = nphdl;
1417 	if (nodename)
1418 		mbs.param[10] = 1;
1419 	mbs.param[9] = chan;
1420 	isp_mboxcmd(isp, &mbs);
1421 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1422 		return (wwn);
1423 	}
1424 	wwn = (((uint64_t)(mbs.param[2] >> 8))	<< 56) |
1425 	      (((uint64_t)(mbs.param[2] & 0xff))<< 48) |
1426 	      (((uint64_t)(mbs.param[3] >> 8))	<< 40) |
1427 	      (((uint64_t)(mbs.param[3] & 0xff))<< 32) |
1428 	      (((uint64_t)(mbs.param[6] >> 8))	<< 24) |
1429 	      (((uint64_t)(mbs.param[6] & 0xff))<< 16) |
1430 	      (((uint64_t)(mbs.param[7] >> 8))	<<  8) |
1431 	      (((uint64_t)(mbs.param[7] & 0xff)));
1432 	return (wwn);
1433 }
1434 
1435 /*
1436  * Make sure we have good FC link.
1437  */
1438 
1439 static int
1440 isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
1441 {
1442 	mbreg_t mbs;
1443 	int i, r, topo;
1444 	fcparam *fcp;
1445 	isp_pdb_t pdb;
1446 	NANOTIME_T hra, hrb;
1447 
1448 	fcp = FCPARAM(isp, chan);
1449 
1450 	if (fcp->isp_loopstate < LOOP_HAVE_LINK)
1451 		return (-1);
1452 	if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
1453 		return (0);
1454 
1455 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan);
1456 
1457 	/*
1458 	 * Wait up to N microseconds for F/W to go to a ready state.
1459 	 */
1460 	GET_NANOTIME(&hra);
1461 	while (1) {
1462 		isp_change_fw_state(isp, chan, isp_fw_state(isp, chan));
1463 		if (fcp->isp_fwstate == FW_READY) {
1464 			break;
1465 		}
1466 		if (fcp->isp_loopstate < LOOP_HAVE_LINK)
1467 			goto abort;
1468 		GET_NANOTIME(&hrb);
1469 		if ((NANOTIME_SUB(&hrb, &hra) / 1000 + 1000 >= usdelay))
1470 			break;
1471 		ISP_SLEEP(isp, 1000);
1472 	}
1473 	if (fcp->isp_fwstate != FW_READY) {
1474 		isp_prt(isp, ISP_LOG_SANCFG,
1475 		    "Chan %d Firmware is not ready (%s)",
1476 		    chan, isp_fc_fw_statename(fcp->isp_fwstate));
1477 		return (-1);
1478 	}
1479 
1480 	/*
1481 	 * Get our Loop ID and Port ID.
1482 	 */
1483 	MBSINIT(&mbs, MBOX_GET_LOOP_ID, MBLOGALL, 0);
1484 	mbs.param[9] = chan;
1485 	isp_mboxcmd(isp, &mbs);
1486 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1487 		return (-1);
1488 	}
1489 
1490 	topo = (int) mbs.param[6];
1491 	if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB)
1492 		topo = TOPO_PTP_STUB;
1493 	fcp->isp_topo = topo;
1494 	fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16);
1495 
1496 	if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
1497 		fcp->isp_loopid = mbs.param[1] & 0xff;
1498 	} else if (fcp->isp_topo != TOPO_F_PORT) {
1499 		uint8_t alpa = fcp->isp_portid;
1500 
1501 		for (i = 0; alpa_map[i]; i++) {
1502 			if (alpa_map[i] == alpa)
1503 				break;
1504 		}
1505 		if (alpa_map[i])
1506 			fcp->isp_loopid = i;
1507 	}
1508 
1509 #if 0
1510 	fcp->isp_loopstate = LOOP_HAVE_ADDR;
1511 #endif
1512 	fcp->isp_loopstate = LOOP_TESTING_LINK;
1513 
1514 	if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
1515 		r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb);
1516 		if (r != 0 || pdb.portid == 0) {
1517 			isp_prt(isp, ISP_LOGWARN,
1518 			    "fabric topology, but cannot get info about fabric controller (0x%x)", r);
1519 			fcp->isp_topo = TOPO_PTP_STUB;
1520 			goto not_on_fabric;
1521 		}
1522 
1523 		fcp->isp_fabric_params = mbs.param[7];
1524 		fcp->isp_sns_hdl = NPH_SNS_ID;
1525 		r = isp_register_fc4_type(isp, chan);
1526 		if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1527 			goto abort;
1528 		if (r != 0)
1529 			goto not_on_fabric;
1530 		r = isp_register_fc4_features_24xx(isp, chan);
1531 		if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1532 			goto abort;
1533 		if (r != 0)
1534 			goto not_on_fabric;
1535 		r = isp_register_port_name_24xx(isp, chan);
1536 		if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1537 			goto abort;
1538 		if (r != 0)
1539 			goto not_on_fabric;
1540 		isp_register_node_name_24xx(isp, chan);
1541 		if (fcp->isp_loopstate < LOOP_TESTING_LINK)
1542 			goto abort;
1543 	}
1544 
1545 not_on_fabric:
1546 	/* Get link speed. */
1547 	fcp->isp_gbspeed = 1;
1548 	MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000);
1549 	mbs.param[1] = MBGSD_GET_RATE;
1550 	/* mbs.param[2] undefined if we're just getting rate */
1551 	isp_mboxcmd(isp, &mbs);
1552 	if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
1553 		if (mbs.param[1] == MBGSD_10GB)
1554 			fcp->isp_gbspeed = 10;
1555 		else if (mbs.param[1] == MBGSD_64GB)
1556 			fcp->isp_gbspeed = 64;
1557 		else if (mbs.param[1] == MBGSD_32GB)
1558 			fcp->isp_gbspeed = 32;
1559 		else if (mbs.param[1] == MBGSD_16GB)
1560 			fcp->isp_gbspeed = 16;
1561 		else if (mbs.param[1] == MBGSD_8GB)
1562 			fcp->isp_gbspeed = 8;
1563 		else if (mbs.param[1] == MBGSD_4GB)
1564 			fcp->isp_gbspeed = 4;
1565 		else if (mbs.param[1] == MBGSD_2GB)
1566 			fcp->isp_gbspeed = 2;
1567 		else if (mbs.param[1] == MBGSD_1GB)
1568 			fcp->isp_gbspeed = 1;
1569 	}
1570 
1571 	if (fcp->isp_loopstate < LOOP_TESTING_LINK) {
1572 abort:
1573 		isp_prt(isp, ISP_LOG_SANCFG,
1574 		    "Chan %d FC link test aborted", chan);
1575 		return (1);
1576 	}
1577 	fcp->isp_loopstate = LOOP_LTEST_DONE;
1578 	isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
1579 	    "Chan %d WWPN %016jx WWNN %016jx",
1580 	    chan, (uintmax_t)fcp->isp_wwpn, (uintmax_t)fcp->isp_wwnn);
1581 	isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
1582 	    "Chan %d %dGb %s PortID 0x%06x LoopID 0x%02x",
1583 	    chan, fcp->isp_gbspeed, isp_fc_toponame(fcp), fcp->isp_portid,
1584 	    fcp->isp_loopid);
1585 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan);
1586 	return (0);
1587 }
1588 
1589 /*
1590  * Complete the synchronization of our Port Database.
1591  *
1592  * At this point, we've scanned the local loop (if any) and the fabric
1593  * and performed fabric logins on all new devices.
1594  *
1595  * Our task here is to go through our port database removing any entities
1596  * that are still marked probational (issuing PLOGO for ones which we had
1597  * PLOGI'd into) or are dead, and notifying upper layers about new/changed
1598  * devices.
1599  */
1600 static int
1601 isp_pdb_sync(ispsoftc_t *isp, int chan)
1602 {
1603 	fcparam *fcp = FCPARAM(isp, chan);
1604 	fcportdb_t *lp;
1605 	uint16_t dbidx;
1606 
1607 	if (fcp->isp_loopstate < LOOP_FSCAN_DONE)
1608 		return (-1);
1609 	if (fcp->isp_loopstate >= LOOP_READY)
1610 		return (0);
1611 
1612 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan);
1613 
1614 	fcp->isp_loopstate = LOOP_SYNCING_PDB;
1615 
1616 	for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
1617 		lp = &fcp->portdb[dbidx];
1618 
1619 		if (lp->state == FC_PORTDB_STATE_NIL)
1620 			continue;
1621 		if (lp->probational && lp->state != FC_PORTDB_STATE_ZOMBIE)
1622 			lp->state = FC_PORTDB_STATE_DEAD;
1623 		switch (lp->state) {
1624 		case FC_PORTDB_STATE_DEAD:
1625 			lp->state = FC_PORTDB_STATE_NIL;
1626 			isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
1627 			if ((lp->portid & 0xffff00) != 0) {
1628 				(void) isp_plogx(isp, chan, lp->handle,
1629 				    lp->portid,
1630 				    PLOGX_FLG_CMD_LOGO |
1631 				    PLOGX_FLG_IMPLICIT |
1632 				    PLOGX_FLG_FREE_NPHDL);
1633 			}
1634 			/*
1635 			 * Note that we might come out of this with our state
1636 			 * set to FC_PORTDB_STATE_ZOMBIE.
1637 			 */
1638 			break;
1639 		case FC_PORTDB_STATE_NEW:
1640 			lp->state = FC_PORTDB_STATE_VALID;
1641 			isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp);
1642 			break;
1643 		case FC_PORTDB_STATE_CHANGED:
1644 			lp->state = FC_PORTDB_STATE_VALID;
1645 			isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp);
1646 			lp->portid = lp->new_portid;
1647 			lp->prli_word0 = lp->new_prli_word0;
1648 			lp->prli_word3 = lp->new_prli_word3;
1649 			break;
1650 		case FC_PORTDB_STATE_VALID:
1651 			isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp);
1652 			break;
1653 		case FC_PORTDB_STATE_ZOMBIE:
1654 			break;
1655 		default:
1656 			isp_prt(isp, ISP_LOGWARN,
1657 			    "isp_pdb_sync: state %d for idx %d",
1658 			    lp->state, dbidx);
1659 			isp_dump_portdb(isp, chan);
1660 		}
1661 	}
1662 
1663 	if (fcp->isp_loopstate < LOOP_SYNCING_PDB) {
1664 		isp_prt(isp, ISP_LOG_SANCFG,
1665 		    "Chan %d FC PDB sync aborted", chan);
1666 		return (1);
1667 	}
1668 
1669 	fcp->isp_loopstate = LOOP_READY;
1670 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan);
1671 	return (0);
1672 }
1673 
1674 static void
1675 isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_t *pdb)
1676 {
1677 	fcportdb_t *lp;
1678 	uint64_t wwnn, wwpn;
1679 
1680 	MAKE_WWN_FROM_NODE_NAME(wwnn, pdb->nodename);
1681 	MAKE_WWN_FROM_NODE_NAME(wwpn, pdb->portname);
1682 
1683 	/* Search port database for the same WWPN. */
1684 	if (isp_find_pdb_by_wwpn(isp, chan, wwpn, &lp)) {
1685 		if (!lp->probational) {
1686 			isp_prt(isp, ISP_LOGERR,
1687 			    "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)",
1688 			    chan, lp->portid, lp->handle,
1689 			    FC_PORTDB_TGT(isp, chan, lp), lp->state);
1690 			isp_dump_portdb(isp, chan);
1691 			return;
1692 		}
1693 		lp->probational = 0;
1694 		lp->node_wwn = wwnn;
1695 
1696 		/* Old device, nothing new. */
1697 		if (lp->portid == pdb->portid &&
1698 		    lp->handle == pdb->handle &&
1699 		    lp->prli_word3 == pdb->prli_word3 &&
1700 		    ((pdb->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR) ==
1701 		     (lp->prli_word0 & PRLI_WD0_EST_IMAGE_PAIR))) {
1702 			if (lp->state != FC_PORTDB_STATE_NEW)
1703 				lp->state = FC_PORTDB_STATE_VALID;
1704 			isp_prt(isp, ISP_LOG_SANCFG,
1705 			    "Chan %d Port 0x%06x@0x%04x is valid",
1706 			    chan, pdb->portid, pdb->handle);
1707 			return;
1708 		}
1709 
1710 		/* Something has changed. */
1711 		lp->state = FC_PORTDB_STATE_CHANGED;
1712 		lp->handle = pdb->handle;
1713 		lp->new_portid = pdb->portid;
1714 		lp->new_prli_word0 = pdb->prli_word0;
1715 		lp->new_prli_word3 = pdb->prli_word3;
1716 		isp_prt(isp, ISP_LOG_SANCFG,
1717 		    "Chan %d Port 0x%06x@0x%04x is changed",
1718 		    chan, pdb->portid, pdb->handle);
1719 		return;
1720 	}
1721 
1722 	/* It seems like a new port. Find an empty slot for it. */
1723 	if (!isp_find_pdb_empty(isp, chan, &lp)) {
1724 		isp_prt(isp, ISP_LOGERR, "Chan %d out of portdb entries", chan);
1725 		return;
1726 	}
1727 
1728 	ISP_MEMZERO(lp, sizeof (fcportdb_t));
1729 	lp->probational = 0;
1730 	lp->state = FC_PORTDB_STATE_NEW;
1731 	lp->portid = lp->new_portid = pdb->portid;
1732 	lp->prli_word0 = lp->new_prli_word0 = pdb->prli_word0;
1733 	lp->prli_word3 = lp->new_prli_word3 = pdb->prli_word3;
1734 	lp->handle = pdb->handle;
1735 	lp->port_wwn = wwpn;
1736 	lp->node_wwn = wwnn;
1737 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Port 0x%06x@0x%04x is new",
1738 	    chan, pdb->portid, pdb->handle);
1739 }
1740 
1741 /*
1742  * Scan local loop for devices.
1743  */
1744 static int
1745 isp_scan_loop(ispsoftc_t *isp, int chan)
1746 {
1747 	fcparam *fcp = FCPARAM(isp, chan);
1748 	int idx, lim, r;
1749 	isp_pdb_t pdb;
1750 	uint16_t *handles;
1751 	uint16_t handle;
1752 
1753 	if (fcp->isp_loopstate < LOOP_LTEST_DONE)
1754 		return (-1);
1755 	if (fcp->isp_loopstate >= LOOP_LSCAN_DONE)
1756 		return (0);
1757 
1758 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan);
1759 	fcp->isp_loopstate = LOOP_SCANNING_LOOP;
1760 	if (TOPO_IS_FABRIC(fcp->isp_topo)) {
1761 		isp_prt(isp, ISP_LOG_SANCFG,
1762 		    "Chan %d FC loop scan done (no loop)", chan);
1763 		fcp->isp_loopstate = LOOP_LSCAN_DONE;
1764 		return (0);
1765 	}
1766 
1767 	handles = (uint16_t *)fcp->isp_scanscratch;
1768 	lim = ISP_FC_SCRLEN / 2;
1769 	r = isp_gethandles(isp, chan, handles, &lim, 1);
1770 	if (r != 0) {
1771 		isp_prt(isp, ISP_LOG_SANCFG,
1772 		    "Chan %d Getting list of handles failed with %x", chan, r);
1773 		isp_prt(isp, ISP_LOG_SANCFG,
1774 		    "Chan %d FC loop scan done (bad)", chan);
1775 		return (-1);
1776 	}
1777 
1778 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles",
1779 	    chan, lim);
1780 
1781 	/*
1782 	 * Run through the list and get the port database info for each one.
1783 	 */
1784 	isp_mark_portdb(isp, chan);
1785 	for (idx = 0; idx < lim; idx++) {
1786 		handle = handles[idx];
1787 
1788 		/*
1789 		 * Don't scan "special" ids.
1790 		 */
1791 		if (handle >= NPH_RESERVED)
1792 			continue;
1793 
1794 		/*
1795 		 * Get the port database entity for this index.
1796 		 */
1797 		r = isp_getpdb(isp, chan, handle, &pdb);
1798 		if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
1799 abort:
1800 			isp_prt(isp, ISP_LOG_SANCFG,
1801 			    "Chan %d FC loop scan aborted", chan);
1802 			return (1);
1803 		}
1804 		if (r != 0) {
1805 			isp_prt(isp, ISP_LOGDEBUG1,
1806 			    "Chan %d FC Scan Loop handle %d returned %x",
1807 			    chan, handle, r);
1808 			continue;
1809 		}
1810 
1811 		isp_pdb_add_update(isp, chan, &pdb);
1812 	}
1813 	if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
1814 		goto abort;
1815 	fcp->isp_loopstate = LOOP_LSCAN_DONE;
1816 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan);
1817 	return (0);
1818 }
1819 
1820 static int
1821 isp_ct_passthru(ispsoftc_t *isp, int chan, uint32_t cmd_bcnt, uint32_t rsp_bcnt)
1822 {
1823 	fcparam *fcp = FCPARAM(isp, chan);
1824 	isp_ct_pt_t pt;
1825 	int retval;
1826 
1827 	if (isp->isp_dblev & ISP_LOGDEBUG1)
1828 		isp_print_bytes(isp, "CT request", cmd_bcnt, fcp->isp_scratch);
1829 
1830 	/*
1831 	 * Build a Passthrough IOCB in memory.
1832 	 */
1833 	ISP_MEMZERO(&pt, sizeof(pt));
1834 	pt.ctp_header.rqs_entry_count = 1;
1835 	pt.ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
1836 	pt.ctp_nphdl = fcp->isp_sns_hdl;
1837 	pt.ctp_cmd_cnt = 1;
1838 	pt.ctp_vpidx = ISP_GET_VPIDX(isp, chan);
1839 	pt.ctp_time = 10;
1840 	pt.ctp_rsp_cnt = 1;
1841 	pt.ctp_rsp_bcnt = rsp_bcnt;
1842 	pt.ctp_cmd_bcnt = cmd_bcnt;
1843 	pt.ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma);
1844 	pt.ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma);
1845 	pt.ctp_dataseg[0].ds_count = cmd_bcnt;
1846 	pt.ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma);
1847 	pt.ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma);
1848 	pt.ctp_dataseg[1].ds_count = rsp_bcnt;
1849 
1850 	retval = isp_exec_entry_queue(isp, &pt, &pt, 2 * pt.ctp_time);
1851 	if (retval != 0) {
1852 		isp_prt(isp, ISP_LOGERR, "%s: CTP of chan %d error %d",
1853 		    __func__, chan, retval);
1854 		return (retval);
1855 	}
1856 
1857 	if (pt.ctp_status && pt.ctp_status != RQCS_DATA_UNDERRUN) {
1858 		isp_prt(isp, ISP_LOGWARN,
1859 		    "Chan %d CT pass-through returned 0x%x",
1860 		    chan, pt.ctp_status);
1861 		return (-1);
1862 	}
1863 
1864 	if (isp->isp_dblev & ISP_LOGDEBUG1)
1865 		isp_print_bytes(isp, "CT response", rsp_bcnt, fcp->isp_scratch);
1866 
1867 	return (0);
1868 }
1869 
1870 /*
1871  * Scan the fabric for devices and add them to our port database.
1872  *
1873  * Use the GID_PT command to get list of all Nx_Port IDs SNS knows.
1874  * Use GFF_ID and GFT_ID to check port type (FCP) and features (target).
1875  *
1876  * We use CT Pass-through IOCB.
1877  */
1878 #define	GIDLEN	ISP_FC_SCRLEN
1879 #define	NGENT	((GIDLEN - 16) >> 2)
1880 
1881 static int
1882 isp_gid_pt(ispsoftc_t *isp, int chan)
1883 {
1884 	fcparam *fcp = FCPARAM(isp, chan);
1885 	ct_hdr_t ct;
1886 	uint8_t *scp = fcp->isp_scratch;
1887 
1888 	isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GID_PT", chan);
1889 	if (FC_SCRATCH_ACQUIRE(isp, chan)) {
1890 		isp_prt(isp, ISP_LOGERR, sacq);
1891 		return (-1);
1892 	}
1893 
1894 	/* Build the CT command and execute via pass-through. */
1895 	ISP_MEMZERO(&ct, sizeof (ct));
1896 	ct.ct_revision = CT_REVISION;
1897 	ct.ct_fcs_type = CT_FC_TYPE_FC;
1898 	ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
1899 	ct.ct_cmd_resp = SNS_GID_PT;
1900 	ct.ct_bcnt_resid = (GIDLEN - 16) >> 2;
1901 	isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
1902 	scp[sizeof(ct)] = 0x7f;		/* Port Type = Nx_Port */
1903 	scp[sizeof(ct)+1] = 0;		/* Domain_ID = any */
1904 	scp[sizeof(ct)+2] = 0;		/* Area_ID = any */
1905 	scp[sizeof(ct)+3] = 0;		/* Flags = no Area_ID */
1906 
1907 	if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t), GIDLEN)) {
1908 		FC_SCRATCH_RELEASE(isp, chan);
1909 		return (-1);
1910 	}
1911 
1912 	isp_get_gid_xx_response(isp, (sns_gid_xx_rsp_t *)scp,
1913 	    (sns_gid_xx_rsp_t *)fcp->isp_scanscratch, NGENT);
1914 	FC_SCRATCH_RELEASE(isp, chan);
1915 	return (0);
1916 }
1917 
1918 static int
1919 isp_gff_id(ispsoftc_t *isp, int chan, uint32_t portid)
1920 {
1921 	fcparam *fcp = FCPARAM(isp, chan);
1922 	ct_hdr_t ct;
1923 	uint32_t *rp;
1924 	uint8_t *scp = fcp->isp_scratch;
1925 	sns_gff_id_rsp_t rsp;
1926 	int i, res = -1;
1927 
1928 	if (!fcp->isp_use_gff_id)	/* User may block GFF_ID use. */
1929 		return (res);
1930 
1931 	isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFF_ID", chan);
1932 	if (FC_SCRATCH_ACQUIRE(isp, chan)) {
1933 		isp_prt(isp, ISP_LOGERR, sacq);
1934 		return (res);
1935 	}
1936 
1937 	/* Build the CT command and execute via pass-through. */
1938 	ISP_MEMZERO(&ct, sizeof (ct));
1939 	ct.ct_revision = CT_REVISION;
1940 	ct.ct_fcs_type = CT_FC_TYPE_FC;
1941 	ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
1942 	ct.ct_cmd_resp = SNS_GFF_ID;
1943 	ct.ct_bcnt_resid = (SNS_GFF_ID_RESP_SIZE - sizeof(ct)) / 4;
1944 	isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
1945 	rp = (uint32_t *) &scp[sizeof(ct)];
1946 	ISP_IOZPUT_32(isp, portid, rp);
1947 
1948 	if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
1949 	    SNS_GFF_ID_RESP_SIZE)) {
1950 		FC_SCRATCH_RELEASE(isp, chan);
1951 		return (res);
1952 	}
1953 
1954 	isp_get_gff_id_response(isp, (sns_gff_id_rsp_t *)scp, &rsp);
1955 	if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) {
1956 		for (i = 0; i < 32; i++) {
1957 			if (rsp.snscb_fc4_features[i] != 0) {
1958 				res = 0;
1959 				break;
1960 			}
1961 		}
1962 		if (((rsp.snscb_fc4_features[FC4_SCSI / 8] >>
1963 		    ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
1964 			res = 1;
1965 		/* Workaround for broken Brocade firmware. */
1966 		if (((ISP_SWAP32(isp, rsp.snscb_fc4_features[FC4_SCSI / 8]) >>
1967 		    ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
1968 			res = 1;
1969 	}
1970 	FC_SCRATCH_RELEASE(isp, chan);
1971 	isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFF_ID result is %d", chan, res);
1972 	return (res);
1973 }
1974 
1975 static int
1976 isp_gft_id(ispsoftc_t *isp, int chan, uint32_t portid)
1977 {
1978 	fcparam *fcp = FCPARAM(isp, chan);
1979 	ct_hdr_t ct;
1980 	uint32_t *rp;
1981 	uint8_t *scp = fcp->isp_scratch;
1982 	sns_gft_id_rsp_t rsp;
1983 	int i, res = -1;
1984 
1985 	if (!fcp->isp_use_gft_id)	/* User may block GFT_ID use. */
1986 		return (res);
1987 
1988 	isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFT_ID", chan);
1989 	if (FC_SCRATCH_ACQUIRE(isp, chan)) {
1990 		isp_prt(isp, ISP_LOGERR, sacq);
1991 		return (res);
1992 	}
1993 
1994 	/* Build the CT command and execute via pass-through. */
1995 	ISP_MEMZERO(&ct, sizeof (ct));
1996 	ct.ct_revision = CT_REVISION;
1997 	ct.ct_fcs_type = CT_FC_TYPE_FC;
1998 	ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
1999 	ct.ct_cmd_resp = SNS_GFT_ID;
2000 	ct.ct_bcnt_resid = (SNS_GFT_ID_RESP_SIZE - sizeof(ct)) / 4;
2001 	isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
2002 	rp = (uint32_t *) &scp[sizeof(ct)];
2003 	ISP_IOZPUT_32(isp, portid, rp);
2004 
2005 	if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
2006 	    SNS_GFT_ID_RESP_SIZE)) {
2007 		FC_SCRATCH_RELEASE(isp, chan);
2008 		return (res);
2009 	}
2010 
2011 	isp_get_gft_id_response(isp, (sns_gft_id_rsp_t *)scp, &rsp);
2012 	if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) {
2013 		for (i = 0; i < 8; i++) {
2014 			if (rsp.snscb_fc4_types[i] != 0) {
2015 				res = 0;
2016 				break;
2017 			}
2018 		}
2019 		if (((rsp.snscb_fc4_types[FC4_SCSI / 32] >>
2020 		    (FC4_SCSI % 32)) & 0x01) != 0)
2021 			res = 1;
2022 	}
2023 	FC_SCRATCH_RELEASE(isp, chan);
2024 	isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFT_ID result is %d", chan, res);
2025 	return (res);
2026 }
2027 
2028 static int
2029 isp_scan_fabric(ispsoftc_t *isp, int chan)
2030 {
2031 	fcparam *fcp = FCPARAM(isp, chan);
2032 	fcportdb_t *lp;
2033 	uint32_t portid;
2034 	isp_pdb_t pdb;
2035 	int portidx, portlim, r;
2036 	sns_gid_xx_rsp_t *rs;
2037 
2038 	if (fcp->isp_loopstate < LOOP_LSCAN_DONE)
2039 		return (-1);
2040 	if (fcp->isp_loopstate >= LOOP_FSCAN_DONE)
2041 		return (0);
2042 
2043 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan);
2044 	fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
2045 	if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
2046 		fcp->isp_loopstate = LOOP_FSCAN_DONE;
2047 		isp_prt(isp, ISP_LOG_SANCFG,
2048 		    "Chan %d FC fabric scan done (no fabric)", chan);
2049 		return (0);
2050 	}
2051 
2052 	if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
2053 abort:
2054 		FC_SCRATCH_RELEASE(isp, chan);
2055 		isp_prt(isp, ISP_LOG_SANCFG,
2056 		    "Chan %d FC fabric scan aborted", chan);
2057 		return (1);
2058 	}
2059 
2060 	/*
2061 	 * Make sure we still are logged into the fabric controller.
2062 	 */
2063 	r = isp_getpdb(isp, chan, NPH_FL_ID, &pdb);
2064 	if ((r & 0xffff) == MBOX_NOT_LOGGED_IN) {
2065 		isp_dump_chip_portdb(isp, chan);
2066 	}
2067 	if (r) {
2068 		fcp->isp_loopstate = LOOP_LTEST_DONE;
2069 fail:
2070 		isp_prt(isp, ISP_LOG_SANCFG,
2071 		    "Chan %d FC fabric scan done (bad)", chan);
2072 		return (-1);
2073 	}
2074 
2075 	/* Get list of port IDs from SNS. */
2076 	r = isp_gid_pt(isp, chan);
2077 	if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2078 		goto abort;
2079 	if (r > 0) {
2080 		fcp->isp_loopstate = LOOP_FSCAN_DONE;
2081 		return (-1);
2082 	} else if (r < 0) {
2083 		fcp->isp_loopstate = LOOP_LTEST_DONE;	/* try again */
2084 		return (-1);
2085 	}
2086 
2087 	rs = (sns_gid_xx_rsp_t *) fcp->isp_scanscratch;
2088 	if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2089 		goto abort;
2090 	if (rs->snscb_cthdr.ct_cmd_resp != LS_ACC) {
2091 		int level;
2092 		/* FC-4 Type and Port Type not registered are not errors. */
2093 		if (rs->snscb_cthdr.ct_reason == 9 &&
2094 		    (rs->snscb_cthdr.ct_explanation == 0x07 ||
2095 		     rs->snscb_cthdr.ct_explanation == 0x0a)) {
2096 			level = ISP_LOG_SANCFG;
2097 		} else {
2098 			level = ISP_LOGWARN;
2099 		}
2100 		isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_PT"
2101 		    " (Reason=0x%x Expl=0x%x)", chan,
2102 		    rs->snscb_cthdr.ct_reason,
2103 		    rs->snscb_cthdr.ct_explanation);
2104 		fcp->isp_loopstate = LOOP_FSCAN_DONE;
2105 		return (-1);
2106 	}
2107 
2108 	/* Check our buffer was big enough to get the full list. */
2109 	for (portidx = 0; portidx < NGENT-1; portidx++) {
2110 		if (rs->snscb_ports[portidx].control & 0x80)
2111 			break;
2112 	}
2113 	if ((rs->snscb_ports[portidx].control & 0x80) == 0) {
2114 		isp_prt(isp, ISP_LOGWARN,
2115 		    "fabric too big for scratch area: increase ISP_FC_SCRLEN");
2116 	}
2117 	portlim = portidx + 1;
2118 	isp_prt(isp, ISP_LOG_SANCFG,
2119 	    "Chan %d Got %d ports back from name server", chan, portlim);
2120 
2121 	/* Go through the list and remove duplicate port ids. */
2122 	for (portidx = 0; portidx < portlim; portidx++) {
2123 		int npidx;
2124 
2125 		portid =
2126 		    ((rs->snscb_ports[portidx].portid[0]) << 16) |
2127 		    ((rs->snscb_ports[portidx].portid[1]) << 8) |
2128 		    ((rs->snscb_ports[portidx].portid[2]));
2129 
2130 		for (npidx = portidx + 1; npidx < portlim; npidx++) {
2131 			uint32_t new_portid =
2132 			    ((rs->snscb_ports[npidx].portid[0]) << 16) |
2133 			    ((rs->snscb_ports[npidx].portid[1]) << 8) |
2134 			    ((rs->snscb_ports[npidx].portid[2]));
2135 			if (new_portid == portid) {
2136 				break;
2137 			}
2138 		}
2139 
2140 		if (npidx < portlim) {
2141 			rs->snscb_ports[npidx].portid[0] = 0;
2142 			rs->snscb_ports[npidx].portid[1] = 0;
2143 			rs->snscb_ports[npidx].portid[2] = 0;
2144 			isp_prt(isp, ISP_LOG_SANCFG, "Chan %d removing duplicate PortID 0x%06x entry from list", chan, portid);
2145 		}
2146 	}
2147 
2148 	/*
2149 	 * We now have a list of Port IDs for all FC4 SCSI devices
2150 	 * that the Fabric Name server knows about.
2151 	 *
2152 	 * For each entry on this list go through our port database looking
2153 	 * for probational entries- if we find one, then an old entry is
2154 	 * maybe still this one. We get some information to find out.
2155 	 *
2156 	 * Otherwise, it's a new fabric device, and we log into it
2157 	 * (unconditionally). After searching the entire database
2158 	 * again to make sure that we never ever ever ever have more
2159 	 * than one entry that has the same PortID or the same
2160 	 * WWNN/WWPN duple, we enter the device into our database.
2161 	 */
2162 	isp_mark_portdb(isp, chan);
2163 	for (portidx = 0; portidx < portlim; portidx++) {
2164 		portid = ((rs->snscb_ports[portidx].portid[0]) << 16) |
2165 			 ((rs->snscb_ports[portidx].portid[1]) << 8) |
2166 			 ((rs->snscb_ports[portidx].portid[2]));
2167 		isp_prt(isp, ISP_LOG_SANCFG,
2168 		    "Chan %d Checking fabric port 0x%06x", chan, portid);
2169 		if (portid == 0) {
2170 			isp_prt(isp, ISP_LOG_SANCFG,
2171 			    "Chan %d Port at idx %d is zero",
2172 			    chan, portidx);
2173 			continue;
2174 		}
2175 		if (portid == fcp->isp_portid) {
2176 			isp_prt(isp, ISP_LOG_SANCFG,
2177 			    "Chan %d Port 0x%06x is our", chan, portid);
2178 			continue;
2179 		}
2180 
2181 		/* Now search the entire port database for the same portid. */
2182 		if (isp_find_pdb_by_portid(isp, chan, portid, &lp)) {
2183 			if (!lp->probational) {
2184 				isp_prt(isp, ISP_LOGERR,
2185 				    "Chan %d Port 0x%06x@0x%04x [%d] is not probational (0x%x)",
2186 				    chan, lp->portid, lp->handle,
2187 				    FC_PORTDB_TGT(isp, chan, lp), lp->state);
2188 				isp_dump_portdb(isp, chan);
2189 				goto fail;
2190 			}
2191 
2192 			if (lp->state == FC_PORTDB_STATE_ZOMBIE)
2193 				goto relogin;
2194 
2195 			/*
2196 			 * See if we're still logged into it.
2197 			 *
2198 			 * If we aren't, mark it as a dead device and
2199 			 * leave the new portid in the database entry
2200 			 * for somebody further along to decide what to
2201 			 * do (policy choice).
2202 			 *
2203 			 * If we are, check to see if it's the same
2204 			 * device still (it should be). If for some
2205 			 * reason it isn't, mark it as a changed device
2206 			 * and leave the new portid and role in the
2207 			 * database entry for somebody further along to
2208 			 * decide what to do (policy choice).
2209 			 */
2210 			r = isp_getpdb(isp, chan, lp->handle, &pdb);
2211 			if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2212 				goto abort;
2213 			if (r != 0) {
2214 				lp->state = FC_PORTDB_STATE_DEAD;
2215 				isp_prt(isp, ISP_LOG_SANCFG,
2216 				    "Chan %d Port 0x%06x handle 0x%x is dead (%d)",
2217 				    chan, portid, lp->handle, r);
2218 				goto relogin;
2219 			}
2220 
2221 			isp_pdb_add_update(isp, chan, &pdb);
2222 			continue;
2223 		}
2224 
2225 relogin:
2226 		if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
2227 			isp_prt(isp, ISP_LOG_SANCFG,
2228 			    "Chan %d Port 0x%06x is not logged in", chan, portid);
2229 			continue;
2230 		}
2231 
2232 		r = isp_gff_id(isp, chan, portid);
2233 		if (r == 0) {
2234 			isp_prt(isp, ISP_LOG_SANCFG,
2235 			    "Chan %d Port 0x%06x is not an FCP target", chan, portid);
2236 			continue;
2237 		}
2238 		if (r < 0)
2239 			r = isp_gft_id(isp, chan, portid);
2240 		if (r == 0) {
2241 			isp_prt(isp, ISP_LOG_SANCFG,
2242 			    "Chan %d Port 0x%06x is not FCP", chan, portid);
2243 			continue;
2244 		}
2245 
2246 		if (isp_login_device(isp, chan, portid, &pdb,
2247 		    &FCPARAM(isp, 0)->isp_lasthdl)) {
2248 			if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2249 				goto abort;
2250 			continue;
2251 		}
2252 
2253 		isp_pdb_add_update(isp, chan, &pdb);
2254 	}
2255 
2256 	if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
2257 		goto abort;
2258 	fcp->isp_loopstate = LOOP_FSCAN_DONE;
2259 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan);
2260 	return (0);
2261 }
2262 
2263 /*
2264  * Find an unused handle and try and use to login to a port.
2265  */
2266 static int
2267 isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint16_t *ohp)
2268 {
2269 	int i, r;
2270 	uint16_t handle;
2271 
2272 	handle = isp_next_handle(isp, ohp);
2273 	for (i = 0; i < NPH_MAX_2K; i++) {
2274 		if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2275 			return (-1);
2276 
2277 		/* Check if this handle is free. */
2278 		r = isp_getpdb(isp, chan, handle, p);
2279 		if (r == 0) {
2280 			if (p->portid != portid) {
2281 				/* This handle is busy, try next one. */
2282 				handle = isp_next_handle(isp, ohp);
2283 				continue;
2284 			}
2285 			break;
2286 		}
2287 		if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2288 			return (-1);
2289 
2290 		/*
2291 		 * Now try and log into the device
2292 		 */
2293 		r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
2294 		if (r == 0) {
2295 			break;
2296 		} else if ((r & 0xffff) == MBOX_PORT_ID_USED) {
2297 			/*
2298 			 * If we get here, then the firmwware still thinks we're logged into this device, but with a different
2299 			 * handle. We need to break that association. We used to try and just substitute the handle, but then
2300 			 * failed to get any data via isp_getpdb (below).
2301 			 */
2302 			if (isp_plogx(isp, chan, r >> 16, portid, PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL)) {
2303 				isp_prt(isp, ISP_LOGERR, "baw... logout of %x failed", r >> 16);
2304 			}
2305 			if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
2306 				return (-1);
2307 			r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI);
2308 			if (r != 0)
2309 				i = NPH_MAX_2K;
2310 			break;
2311 		} else if ((r & 0xffff) == MBOX_LOOP_ID_USED) {
2312 			/* Try the next handle. */
2313 			handle = isp_next_handle(isp, ohp);
2314 		} else {
2315 			/* Give up. */
2316 			i = NPH_MAX_2K;
2317 			break;
2318 		}
2319 	}
2320 
2321 	if (i == NPH_MAX_2K) {
2322 		isp_prt(isp, ISP_LOGWARN, "Chan %d PLOGI 0x%06x failed", chan, portid);
2323 		return (-1);
2324 	}
2325 
2326 	/*
2327 	 * If we successfully logged into it, get the PDB for it
2328 	 * so we can crosscheck that it is still what we think it
2329 	 * is and that we also have the role it plays
2330 	 */
2331 	r = isp_getpdb(isp, chan, handle, p);
2332 	if (r != 0) {
2333 		isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x disappeared", chan, portid, handle);
2334 		return (-1);
2335 	}
2336 
2337 	if (p->handle != handle || p->portid != portid) {
2338 		isp_prt(isp, ISP_LOGERR, "Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x)",
2339 		    chan, portid, handle, p->portid, p->handle);
2340 		return (-1);
2341 	}
2342 	return (0);
2343 }
2344 
2345 static int
2346 isp_register_fc4_type(ispsoftc_t *isp, int chan)
2347 {
2348 	fcparam *fcp = FCPARAM(isp, chan);
2349 	rft_id_t rp;
2350 	ct_hdr_t *ct = &rp.rftid_hdr;
2351 	uint8_t *scp = fcp->isp_scratch;
2352 
2353 	if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2354 		isp_prt(isp, ISP_LOGERR, sacq);
2355 		return (-1);
2356 	}
2357 
2358 	/* Build the CT command and execute via pass-through. */
2359 	ISP_MEMZERO(&rp, sizeof(rp));
2360 	ct->ct_revision = CT_REVISION;
2361 	ct->ct_fcs_type = CT_FC_TYPE_FC;
2362 	ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2363 	ct->ct_cmd_resp = SNS_RFT_ID;
2364 	ct->ct_bcnt_resid = (sizeof (rft_id_t) - sizeof (ct_hdr_t)) >> 2;
2365 	rp.rftid_portid[0] = fcp->isp_portid >> 16;
2366 	rp.rftid_portid[1] = fcp->isp_portid >> 8;
2367 	rp.rftid_portid[2] = fcp->isp_portid;
2368 	rp.rftid_fc4types[FC4_SCSI >> 5] = 1 << (FC4_SCSI & 0x1f);
2369 	isp_put_rft_id(isp, &rp, (rft_id_t *)scp);
2370 
2371 	if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) {
2372 		FC_SCRATCH_RELEASE(isp, chan);
2373 		return (-1);
2374 	}
2375 
2376 	isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2377 	FC_SCRATCH_RELEASE(isp, chan);
2378 	if (ct->ct_cmd_resp == LS_RJT) {
2379 		isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1, "Chan %d Register FC4 Type rejected", chan);
2380 		return (-1);
2381 	} else if (ct->ct_cmd_resp == LS_ACC) {
2382 		isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Register FC4 Type accepted", chan);
2383 	} else {
2384 		isp_prt(isp, ISP_LOGWARN, "Chan %d Register FC4 Type: 0x%x", chan, ct->ct_cmd_resp);
2385 		return (-1);
2386 	}
2387 	return (0);
2388 }
2389 
2390 static int
2391 isp_register_fc4_features_24xx(ispsoftc_t *isp, int chan)
2392 {
2393 	fcparam *fcp = FCPARAM(isp, chan);
2394 	ct_hdr_t *ct;
2395 	rff_id_t rp;
2396 	uint8_t *scp = fcp->isp_scratch;
2397 
2398 	if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2399 		isp_prt(isp, ISP_LOGERR, sacq);
2400 		return (-1);
2401 	}
2402 
2403 	/*
2404 	 * Build the CT header and command in memory.
2405 	 */
2406 	ISP_MEMZERO(&rp, sizeof(rp));
2407 	ct = &rp.rffid_hdr;
2408 	ct->ct_revision = CT_REVISION;
2409 	ct->ct_fcs_type = CT_FC_TYPE_FC;
2410 	ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2411 	ct->ct_cmd_resp = SNS_RFF_ID;
2412 	ct->ct_bcnt_resid = (sizeof (rff_id_t) - sizeof (ct_hdr_t)) >> 2;
2413 	rp.rffid_portid[0] = fcp->isp_portid >> 16;
2414 	rp.rffid_portid[1] = fcp->isp_portid >> 8;
2415 	rp.rffid_portid[2] = fcp->isp_portid;
2416 	rp.rffid_fc4features = 0;
2417 	if (fcp->role & ISP_ROLE_TARGET)
2418 		rp.rffid_fc4features |= 1;
2419 	if (fcp->role & ISP_ROLE_INITIATOR)
2420 		rp.rffid_fc4features |= 2;
2421 	rp.rffid_fc4type = FC4_SCSI;
2422 	isp_put_rff_id(isp, &rp, (rff_id_t *)scp);
2423 	if (isp->isp_dblev & ISP_LOGDEBUG1)
2424 		isp_print_bytes(isp, "CT request", sizeof(rft_id_t), scp);
2425 
2426 	if (isp_ct_passthru(isp, chan, sizeof(rft_id_t), sizeof(ct_hdr_t))) {
2427 		FC_SCRATCH_RELEASE(isp, chan);
2428 		return (-1);
2429 	}
2430 
2431 	isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2432 	FC_SCRATCH_RELEASE(isp, chan);
2433 	if (ct->ct_cmd_resp == LS_RJT) {
2434 		isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2435 		    "Chan %d Register FC4 Features rejected", chan);
2436 		return (-1);
2437 	} else if (ct->ct_cmd_resp == LS_ACC) {
2438 		isp_prt(isp, ISP_LOG_SANCFG,
2439 		    "Chan %d Register FC4 Features accepted", chan);
2440 	} else {
2441 		isp_prt(isp, ISP_LOGWARN,
2442 		    "Chan %d Register FC4 Features: 0x%x", chan, ct->ct_cmd_resp);
2443 		return (-1);
2444 	}
2445 	return (0);
2446 }
2447 
2448 static int
2449 isp_register_port_name_24xx(ispsoftc_t *isp, int chan)
2450 {
2451 	fcparam *fcp = FCPARAM(isp, chan);
2452 	ct_hdr_t *ct;
2453 	rspn_id_t rp;
2454 	uint8_t *scp = fcp->isp_scratch;
2455 	int len;
2456 
2457 	if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2458 		isp_prt(isp, ISP_LOGERR, sacq);
2459 		return (-1);
2460 	}
2461 
2462 	/*
2463 	 * Build the CT header and command in memory.
2464 	 */
2465 	ISP_MEMZERO(&rp, sizeof(rp));
2466 	ct = &rp.rspnid_hdr;
2467 	ct->ct_revision = CT_REVISION;
2468 	ct->ct_fcs_type = CT_FC_TYPE_FC;
2469 	ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2470 	ct->ct_cmd_resp = SNS_RSPN_ID;
2471 	rp.rspnid_portid[0] = fcp->isp_portid >> 16;
2472 	rp.rspnid_portid[1] = fcp->isp_portid >> 8;
2473 	rp.rspnid_portid[2] = fcp->isp_portid;
2474 	rp.rspnid_length = 0;
2475 	len = offsetof(rspn_id_t, rspnid_name);
2476 	mtx_lock(&prison0.pr_mtx);
2477 	rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2478 	    "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD");
2479 	mtx_unlock(&prison0.pr_mtx);
2480 	rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2481 	    ":%s", device_get_nameunit(isp->isp_dev));
2482 	if (chan != 0) {
2483 		rp.rspnid_length += sprintf(&scp[len + rp.rspnid_length],
2484 		    "/%d", chan);
2485 	}
2486 	len += rp.rspnid_length;
2487 	ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2;
2488 	isp_put_rspn_id(isp, &rp, (rspn_id_t *)scp);
2489 
2490 	if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) {
2491 		FC_SCRATCH_RELEASE(isp, chan);
2492 		return (-1);
2493 	}
2494 
2495 	isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2496 	FC_SCRATCH_RELEASE(isp, chan);
2497 	if (ct->ct_cmd_resp == LS_RJT) {
2498 		isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2499 		    "Chan %d Register Symbolic Port Name rejected", chan);
2500 		return (-1);
2501 	} else if (ct->ct_cmd_resp == LS_ACC) {
2502 		isp_prt(isp, ISP_LOG_SANCFG,
2503 		    "Chan %d Register Symbolic Port Name accepted", chan);
2504 	} else {
2505 		isp_prt(isp, ISP_LOGWARN,
2506 		    "Chan %d Register Symbolic Port Name: 0x%x", chan, ct->ct_cmd_resp);
2507 		return (-1);
2508 	}
2509 	return (0);
2510 }
2511 
2512 static int
2513 isp_register_node_name_24xx(ispsoftc_t *isp, int chan)
2514 {
2515 	fcparam *fcp = FCPARAM(isp, chan);
2516 	ct_hdr_t *ct;
2517 	rsnn_nn_t rp;
2518 	uint8_t *scp = fcp->isp_scratch;
2519 	int len;
2520 
2521 	if (FC_SCRATCH_ACQUIRE(isp, chan)) {
2522 		isp_prt(isp, ISP_LOGERR, sacq);
2523 		return (-1);
2524 	}
2525 
2526 	/*
2527 	 * Build the CT header and command in memory.
2528 	 */
2529 	ISP_MEMZERO(&rp, sizeof(rp));
2530 	ct = &rp.rsnnnn_hdr;
2531 	ct->ct_revision = CT_REVISION;
2532 	ct->ct_fcs_type = CT_FC_TYPE_FC;
2533 	ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
2534 	ct->ct_cmd_resp = SNS_RSNN_NN;
2535 	MAKE_NODE_NAME_FROM_WWN(rp.rsnnnn_nodename, fcp->isp_wwnn);
2536 	rp.rsnnnn_length = 0;
2537 	len = offsetof(rsnn_nn_t, rsnnnn_name);
2538 	mtx_lock(&prison0.pr_mtx);
2539 	rp.rsnnnn_length += sprintf(&scp[len + rp.rsnnnn_length],
2540 	    "%s", prison0.pr_hostname[0] ? prison0.pr_hostname : "FreeBSD");
2541 	mtx_unlock(&prison0.pr_mtx);
2542 	len += rp.rsnnnn_length;
2543 	ct->ct_bcnt_resid = (len - sizeof(ct_hdr_t)) >> 2;
2544 	isp_put_rsnn_nn(isp, &rp, (rsnn_nn_t *)scp);
2545 
2546 	if (isp_ct_passthru(isp, chan, len, sizeof(ct_hdr_t))) {
2547 		FC_SCRATCH_RELEASE(isp, chan);
2548 		return (-1);
2549 	}
2550 
2551 	isp_get_ct_hdr(isp, (ct_hdr_t *) scp, ct);
2552 	FC_SCRATCH_RELEASE(isp, chan);
2553 	if (ct->ct_cmd_resp == LS_RJT) {
2554 		isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
2555 		    "Chan %d Register Symbolic Node Name rejected", chan);
2556 		return (-1);
2557 	} else if (ct->ct_cmd_resp == LS_ACC) {
2558 		isp_prt(isp, ISP_LOG_SANCFG,
2559 		    "Chan %d Register Symbolic Node Name accepted", chan);
2560 	} else {
2561 		isp_prt(isp, ISP_LOGWARN,
2562 		    "Chan %d Register Symbolic Node Name: 0x%x", chan, ct->ct_cmd_resp);
2563 		return (-1);
2564 	}
2565 	return (0);
2566 }
2567 
2568 static uint16_t
2569 isp_next_handle(ispsoftc_t *isp, uint16_t *ohp)
2570 {
2571 	fcparam *fcp;
2572 	int i, chan, wrap;
2573 	uint16_t handle;
2574 
2575 	handle = *ohp;
2576 	wrap = 0;
2577 
2578 next:
2579 	if (handle == NIL_HANDLE) {
2580 		handle = 0;
2581 	} else {
2582 		handle++;
2583 		if (handle > NPH_RESERVED - 1) {
2584 			if (++wrap >= 2) {
2585 				isp_prt(isp, ISP_LOGERR, "Out of port handles!");
2586 				return (NIL_HANDLE);
2587 			}
2588 			handle = 0;
2589 		}
2590 	}
2591 	for (chan = 0; chan < isp->isp_nchan; chan++) {
2592 		fcp = FCPARAM(isp, chan);
2593 		if (fcp->role == ISP_ROLE_NONE)
2594 			continue;
2595 		for (i = 0; i < MAX_FC_TARG; i++) {
2596 			if (fcp->portdb[i].state != FC_PORTDB_STATE_NIL &&
2597 			    fcp->portdb[i].handle == handle)
2598 				goto next;
2599 		}
2600 	}
2601 	*ohp = handle;
2602 	return (handle);
2603 }
2604 
2605 /*
2606  * Start a command. Locking is assumed done in the caller.
2607  */
2608 
2609 int
2610 isp_start(XS_T *xs)
2611 {
2612 	ispsoftc_t *isp;
2613 	fcparam *fcp;
2614 	uint32_t cdblen;
2615 	ispreqt7_t local, *reqp = &local;
2616 	void *qep;
2617 	fcportdb_t *lp;
2618 	int target, dmaresult;
2619 
2620 	XS_INITERR(xs);
2621 	isp = XS_ISP(xs);
2622 
2623 	/*
2624 	 * Check command CDB length, etc.. We really are limited to 16 bytes
2625 	 * for Fibre Channel, but can do up to 44 bytes in parallel SCSI,
2626 	 * but probably only if we're running fairly new firmware (we'll
2627 	 * let the old f/w choke on an extended command queue entry).
2628 	 */
2629 
2630 	if (XS_CDBLEN(xs) > 16 || XS_CDBLEN(xs) == 0) {
2631 		isp_prt(isp, ISP_LOGERR, "unsupported cdb length (%d, CDB[0]=0x%x)", XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff);
2632 		XS_SETERR(xs, HBA_REQINVAL);
2633 		return (CMD_COMPLETE);
2634 	}
2635 
2636 	/*
2637 	 * Translate the target to device handle as appropriate, checking
2638 	 * for correct device state as well.
2639 	 */
2640 	target = XS_TGT(xs);
2641 	fcp = FCPARAM(isp, XS_CHANNEL(xs));
2642 
2643 	if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
2644 		isp_prt(isp, ISP_LOG_WARN1,
2645 		    "%d.%d.%jx I am not an initiator",
2646 		    XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2647 		XS_SETERR(xs, HBA_SELTIMEOUT);
2648 		return (CMD_COMPLETE);
2649 	}
2650 
2651 	if (isp->isp_state != ISP_RUNSTATE) {
2652 		isp_prt(isp, ISP_LOGERR, "Adapter not at RUNSTATE");
2653 		XS_SETERR(xs, HBA_BOTCH);
2654 		return (CMD_COMPLETE);
2655 	}
2656 
2657 	isp_prt(isp, ISP_LOGDEBUG2, "XS_TGT(xs)=%d", target);
2658 	lp = &fcp->portdb[target];
2659 	if (target < 0 || target >= MAX_FC_TARG ||
2660 	    lp->is_target == 0) {
2661 		XS_SETERR(xs, HBA_SELTIMEOUT);
2662 		return (CMD_COMPLETE);
2663 	}
2664 	if (fcp->isp_loopstate != LOOP_READY) {
2665 		isp_prt(isp, ISP_LOGDEBUG1,
2666 		    "%d.%d.%jx loop is not ready",
2667 		    XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2668 		return (CMD_RQLATER);
2669 	}
2670 	if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
2671 		isp_prt(isp, ISP_LOGDEBUG1,
2672 		    "%d.%d.%jx target zombie",
2673 		    XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2674 		return (CMD_RQLATER);
2675 	}
2676 	if (lp->state != FC_PORTDB_STATE_VALID) {
2677 		isp_prt(isp, ISP_LOGDEBUG1,
2678 		    "%d.%d.%jx bad db port state 0x%x",
2679 		    XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs), lp->state);
2680 		XS_SETERR(xs, HBA_SELTIMEOUT);
2681 		return (CMD_COMPLETE);
2682 	}
2683 
2684  start_again:
2685 
2686 	qep = isp_getrqentry(isp);
2687 	if (qep == NULL) {
2688 		isp_prt(isp, ISP_LOG_WARN1, "Request Queue Overflow");
2689 		XS_SETERR(xs, HBA_BOTCH);
2690 		return (CMD_EAGAIN);
2691 	}
2692 	XS_SETERR(xs, HBA_NOERROR);
2693 
2694 	/*
2695 	 * Now see if we need to synchronize the ISP with respect to anything.
2696 	 * We do dual duty here (cough) for synchronizing for buses other
2697 	 * than which we got here to send a command to.
2698 	 */
2699 	ISP_MEMZERO(reqp, QENTRY_LEN);
2700 	if (ISP_TST_SENDMARKER(isp, XS_CHANNEL(xs))) {
2701 		isp_marker_24xx_t *m = (isp_marker_24xx_t *) reqp;
2702 		m->mrk_header.rqs_entry_count = 1;
2703 		m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
2704 		m->mrk_modifier = SYNC_ALL;
2705 		m->mrk_vphdl = XS_CHANNEL(xs);
2706 		isp_put_marker_24xx(isp, m, qep);
2707 		ISP_SYNC_REQUEST(isp);
2708 		ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 0);
2709 		goto start_again;
2710 	}
2711 
2712 	/*
2713 	 * NB: we do not support long CDBs (yet)
2714 	 */
2715 	cdblen = XS_CDBLEN(xs);
2716 	if (cdblen > sizeof (reqp->req_cdb)) {
2717 		isp_prt(isp, ISP_LOGERR, "Command Length %u too long for this chip", cdblen);
2718 		XS_SETERR(xs, HBA_REQINVAL);
2719 		return (CMD_COMPLETE);
2720 	}
2721 
2722 	reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS;
2723 	reqp->req_header.rqs_entry_count = 1;
2724 	reqp->req_nphdl = lp->handle;
2725 	reqp->req_time = XS_TIME(xs);
2726 	be64enc(reqp->req_lun, CAM_EXTLUN_BYTE_SWIZZLE(XS_LUN(xs)));
2727 	if (XS_XFRIN(xs))
2728 		reqp->req_alen_datadir = FCP_CMND_DATA_READ;
2729 	else if (XS_XFROUT(xs))
2730 		reqp->req_alen_datadir = FCP_CMND_DATA_WRITE;
2731 	if (XS_TAG_P(xs))
2732 		reqp->req_task_attribute = XS_TAG_TYPE(xs);
2733 	else
2734 		reqp->req_task_attribute = FCP_CMND_TASK_ATTR_SIMPLE;
2735 	reqp->req_task_attribute |= (XS_PRIORITY(xs) << FCP_CMND_PRIO_SHIFT) &
2736 	     FCP_CMND_PRIO_MASK;
2737 	if (FCPARAM(isp, XS_CHANNEL(xs))->fctape_enabled && (lp->prli_word3 & PRLI_WD3_RETRY)) {
2738 		if (FCP_NEXT_CRN(isp, &reqp->req_crn, xs)) {
2739 			isp_prt(isp, ISP_LOG_WARN1,
2740 			    "%d.%d.%jx cannot generate next CRN",
2741 			    XS_CHANNEL(xs), target, (uintmax_t)XS_LUN(xs));
2742 			XS_SETERR(xs, HBA_BOTCH);
2743 			return (CMD_EAGAIN);
2744 		}
2745 	}
2746 	ISP_MEMCPY(reqp->req_cdb, XS_CDBP(xs), cdblen);
2747 	reqp->req_dl = XS_XFRLEN(xs);
2748 	reqp->req_tidlo = lp->portid;
2749 	reqp->req_tidhi = lp->portid >> 16;
2750 	reqp->req_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(xs));
2751 
2752 	/* Whew. Thankfully the same for type 7 requests */
2753 	reqp->req_handle = isp_allocate_handle(isp, xs, ISP_HANDLE_INITIATOR);
2754 	if (reqp->req_handle == 0) {
2755 		isp_prt(isp, ISP_LOG_WARN1, "out of xflist pointers");
2756 		XS_SETERR(xs, HBA_BOTCH);
2757 		return (CMD_EAGAIN);
2758 	}
2759 
2760 	/*
2761 	 * Set up DMA and/or do any platform dependent swizzling of the request entry
2762 	 * so that the Qlogic F/W understands what is being asked of it.
2763 	 *
2764 	 * The callee is responsible for adding all requests at this point.
2765 	 */
2766 	dmaresult = ISP_DMASETUP(isp, xs, reqp);
2767 	if (dmaresult != 0) {
2768 		isp_destroy_handle(isp, reqp->req_handle);
2769 		/*
2770 		 * dmasetup sets actual error in packet, and
2771 		 * return what we were given to return.
2772 		 */
2773 		return (dmaresult);
2774 	}
2775 	isp_xs_prt(isp, xs, ISP_LOGDEBUG0, "START cmd cdb[0]=0x%x datalen %ld", XS_CDBP(xs)[0], (long) XS_XFRLEN(xs));
2776 	return (0);
2777 }
2778 
2779 /*
2780  * isp control
2781  * Locks (ints blocked) assumed held.
2782  */
2783 
2784 int
2785 isp_control(ispsoftc_t *isp, ispctl_t ctl, ...)
2786 {
2787 	fcparam *fcp;
2788 	fcportdb_t *lp;
2789 	XS_T *xs;
2790 	mbreg_t *mbr;
2791 	int chan, tgt;
2792 	uint32_t handle;
2793 	va_list ap;
2794 	uint8_t local[QENTRY_LEN];
2795 
2796 	switch (ctl) {
2797 	case ISPCTL_RESET_BUS:
2798 		/*
2799 		 * Issue a bus reset.
2800 		 */
2801 		isp_prt(isp, ISP_LOGERR, "BUS RESET NOT IMPLEMENTED");
2802 		break;
2803 
2804 	case ISPCTL_RESET_DEV:
2805 	{
2806 		isp24xx_tmf_t *tmf;
2807 		isp24xx_statusreq_t *sp;
2808 
2809 		va_start(ap, ctl);
2810 		chan = va_arg(ap, int);
2811 		tgt = va_arg(ap, int);
2812 		va_end(ap);
2813 		fcp = FCPARAM(isp, chan);
2814 
2815 		if (tgt < 0 || tgt >= MAX_FC_TARG) {
2816 			isp_prt(isp, ISP_LOGWARN, "Chan %d trying to reset bad target %d", chan, tgt);
2817 			break;
2818 		}
2819 		lp = &fcp->portdb[tgt];
2820 		if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) {
2821 			isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt);
2822 			break;
2823 		}
2824 
2825 		tmf = (isp24xx_tmf_t *) local;
2826 		ISP_MEMZERO(tmf, QENTRY_LEN);
2827 		tmf->tmf_header.rqs_entry_type = RQSTYPE_TSK_MGMT;
2828 		tmf->tmf_header.rqs_entry_count = 1;
2829 		tmf->tmf_nphdl = lp->handle;
2830 		tmf->tmf_delay = 2;
2831 		tmf->tmf_timeout = 4;
2832 		tmf->tmf_flags = ISP24XX_TMF_TARGET_RESET;
2833 		tmf->tmf_tidlo = lp->portid;
2834 		tmf->tmf_tidhi = lp->portid >> 16;
2835 		tmf->tmf_vpidx = ISP_GET_VPIDX(isp, chan);
2836 		fcp->sendmarker = 1;
2837 		isp_prt(isp, ISP_LOGALL, "Chan %d Reset N-Port Handle 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid);
2838 
2839 		sp = (isp24xx_statusreq_t *) local;
2840 		if (isp_exec_entry_mbox(isp, tmf, sp, 2 * tmf->tmf_timeout))
2841 			break;
2842 
2843 		if (sp->req_completion_status == 0)
2844 			return (0);
2845 		isp_prt(isp, ISP_LOGWARN, "Chan %d reset of target %d returned 0x%x", chan, tgt, sp->req_completion_status);
2846 		break;
2847 	}
2848 	case ISPCTL_ABORT_CMD:
2849 	{
2850 		isp24xx_abrt_t *ab = (isp24xx_abrt_t *)&local;
2851 
2852 		va_start(ap, ctl);
2853 		xs = va_arg(ap, XS_T *);
2854 		va_end(ap);
2855 
2856 		tgt = XS_TGT(xs);
2857 		chan = XS_CHANNEL(xs);
2858 
2859 		handle = isp_find_handle(isp, xs);
2860 		if (handle == 0) {
2861 			isp_prt(isp, ISP_LOGWARN, "cannot find handle for command to abort");
2862 			break;
2863 		}
2864 
2865 		fcp = FCPARAM(isp, chan);
2866 		if (tgt < 0 || tgt >= MAX_FC_TARG) {
2867 			isp_prt(isp, ISP_LOGWARN, "Chan %d trying to abort bad target %d", chan, tgt);
2868 			break;
2869 		}
2870 		lp = &fcp->portdb[tgt];
2871 		if (lp->is_target == 0 || lp->state != FC_PORTDB_STATE_VALID) {
2872 			isp_prt(isp, ISP_LOGWARN, "Chan %d abort of no longer valid target %d", chan, tgt);
2873 			break;
2874 		}
2875 		isp_prt(isp, ISP_LOGALL, "Chan %d Abort Cmd for N-Port 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid);
2876 		ISP_MEMZERO(ab, QENTRY_LEN);
2877 		ab->abrt_header.rqs_entry_type = RQSTYPE_ABORT_IO;
2878 		ab->abrt_header.rqs_entry_count = 1;
2879 		ab->abrt_handle = lp->handle;
2880 		ab->abrt_cmd_handle = handle;
2881 		ab->abrt_tidlo = lp->portid;
2882 		ab->abrt_tidhi = lp->portid >> 16;
2883 		ab->abrt_vpidx = ISP_GET_VPIDX(isp, chan);
2884 
2885 		if (isp_exec_entry_mbox(isp, ab, ab, 5))
2886 			break;
2887 
2888 		if (ab->abrt_nphdl == ISP24XX_ABRT_OKAY)
2889 			return (0);
2890 		isp_prt(isp, ISP_LOGWARN, "Chan %d handle %d abort returned 0x%x", chan, tgt, ab->abrt_nphdl);
2891 	}
2892 	case ISPCTL_FCLINK_TEST:
2893 	{
2894 		int usdelay;
2895 
2896 		va_start(ap, ctl);
2897 		chan = va_arg(ap, int);
2898 		usdelay = va_arg(ap, int);
2899 		va_end(ap);
2900 		if (usdelay == 0)
2901 			usdelay = 250000;
2902 		return (isp_fclink_test(isp, chan, usdelay));
2903 	}
2904 	case ISPCTL_SCAN_FABRIC:
2905 
2906 		va_start(ap, ctl);
2907 		chan = va_arg(ap, int);
2908 		va_end(ap);
2909 		return (isp_scan_fabric(isp, chan));
2910 
2911 	case ISPCTL_SCAN_LOOP:
2912 
2913 		va_start(ap, ctl);
2914 		chan = va_arg(ap, int);
2915 		va_end(ap);
2916 		return (isp_scan_loop(isp, chan));
2917 
2918 	case ISPCTL_PDB_SYNC:
2919 
2920 		va_start(ap, ctl);
2921 		chan = va_arg(ap, int);
2922 		va_end(ap);
2923 		return (isp_pdb_sync(isp, chan));
2924 
2925 	case ISPCTL_SEND_LIP:
2926 		break;
2927 
2928 	case ISPCTL_GET_PDB:
2929 	{
2930 		isp_pdb_t *pdb;
2931 		va_start(ap, ctl);
2932 		chan = va_arg(ap, int);
2933 		tgt = va_arg(ap, int);
2934 		pdb = va_arg(ap, isp_pdb_t *);
2935 		va_end(ap);
2936 		return (isp_getpdb(isp, chan, tgt, pdb));
2937 	}
2938 	case ISPCTL_GET_NAMES:
2939 	{
2940 		uint64_t *wwnn, *wwnp;
2941 		va_start(ap, ctl);
2942 		chan = va_arg(ap, int);
2943 		tgt = va_arg(ap, int);
2944 		wwnn = va_arg(ap, uint64_t *);
2945 		wwnp = va_arg(ap, uint64_t *);
2946 		va_end(ap);
2947 		if (wwnn == NULL && wwnp == NULL) {
2948 			break;
2949 		}
2950 		if (wwnn) {
2951 			*wwnn = isp_get_wwn(isp, chan, tgt, 1);
2952 			if (*wwnn == INI_NONE) {
2953 				break;
2954 			}
2955 		}
2956 		if (wwnp) {
2957 			*wwnp = isp_get_wwn(isp, chan, tgt, 0);
2958 			if (*wwnp == INI_NONE) {
2959 				break;
2960 			}
2961 		}
2962 		return (0);
2963 	}
2964 	case ISPCTL_RUN_MBOXCMD:
2965 	{
2966 		va_start(ap, ctl);
2967 		mbr = va_arg(ap, mbreg_t *);
2968 		va_end(ap);
2969 		isp_mboxcmd(isp, mbr);
2970 		return (0);
2971 	}
2972 	case ISPCTL_PLOGX:
2973 	{
2974 		isp_plcmd_t *p;
2975 		int r;
2976 
2977 		va_start(ap, ctl);
2978 		p = va_arg(ap, isp_plcmd_t *);
2979 		va_end(ap);
2980 
2981 		if ((p->flags & PLOGX_FLG_CMD_MASK) != PLOGX_FLG_CMD_PLOGI || (p->handle != NIL_HANDLE)) {
2982 			return (isp_plogx(isp, p->channel, p->handle, p->portid, p->flags));
2983 		}
2984 		do {
2985 			isp_next_handle(isp, &p->handle);
2986 			r = isp_plogx(isp, p->channel, p->handle, p->portid, p->flags);
2987 			if ((r & 0xffff) == MBOX_PORT_ID_USED) {
2988 				p->handle = r >> 16;
2989 				r = 0;
2990 				break;
2991 			}
2992 		} while ((r & 0xffff) == MBOX_LOOP_ID_USED);
2993 		return (r);
2994 	}
2995 	case ISPCTL_CHANGE_ROLE:
2996 	{
2997 		int role;
2998 
2999 		va_start(ap, ctl);
3000 		chan = va_arg(ap, int);
3001 		role = va_arg(ap, int);
3002 		va_end(ap);
3003 		return (isp_fc_change_role(isp, chan, role));
3004 	}
3005 	default:
3006 		isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl);
3007 		break;
3008 
3009 	}
3010 	return (-1);
3011 }
3012 
3013 /*
3014  * Interrupt Service Routine(s).
3015  *
3016  * External (OS) framework has done the appropriate locking,
3017  * and the locking will be held throughout this function.
3018  */
3019 
3020 #ifdef	ISP_TARGET_MODE
3021 void
3022 isp_intr_atioq(ispsoftc_t *isp)
3023 {
3024 	void *addr;
3025 	uint32_t iptr, optr, oop;
3026 
3027 	iptr = ISP_READ(isp, BIU2400_ATIO_RSPINP);
3028 	optr = isp->isp_atioodx;
3029 	while (optr != iptr) {
3030 		oop = optr;
3031 		MEMORYBARRIER(isp, SYNC_ATIOQ, oop, QENTRY_LEN, -1);
3032 		addr = ISP_QUEUE_ENTRY(isp->isp_atioq, oop);
3033 		switch (((isphdr_t *)addr)->rqs_entry_type) {
3034 		case RQSTYPE_NOTIFY:
3035 		case RQSTYPE_ATIO:
3036 		case RQSTYPE_NOTIFY_ACK:	/* Can be set to ATIO queue.*/
3037 		case RQSTYPE_ABTS_RCVD:		/* Can be set to ATIO queue.*/
3038 			(void) isp_target_notify(isp, addr, &oop,
3039 			    ATIO_QUEUE_LEN(isp));
3040 			break;
3041 		case RQSTYPE_RPT_ID_ACQ:	/* Can be set to ATIO queue.*/
3042 		default:
3043 			isp_print_qentry(isp, "?ATIOQ entry?", oop, addr);
3044 			break;
3045 		}
3046 		optr = ISP_NXT_QENTRY(oop, ATIO_QUEUE_LEN(isp));
3047 	}
3048 	if (isp->isp_atioodx != optr) {
3049 		ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, optr);
3050 		isp->isp_atioodx = optr;
3051 	}
3052 }
3053 #endif
3054 
3055 void
3056 isp_intr_mbox(ispsoftc_t *isp, uint16_t mbox0)
3057 {
3058 	int i, obits;
3059 
3060 	if (!isp->isp_mboxbsy) {
3061 		isp_prt(isp, ISP_LOGWARN, "mailbox 0x%x with no waiters", mbox0);
3062 		return;
3063 	}
3064 	obits = isp->isp_obits;
3065 	isp->isp_mboxtmp[0] = mbox0;
3066 	for (i = 1; i < ISP_NMBOX(isp); i++) {
3067 		if ((obits & (1 << i)) == 0)
3068 			continue;
3069 		isp->isp_mboxtmp[i] = ISP_READ(isp, MBOX_OFF(i));
3070 	}
3071 	isp->isp_mboxbsy = 0;
3072 }
3073 
3074 void
3075 isp_intr_respq(ispsoftc_t *isp)
3076 {
3077 	XS_T *xs, *cont_xs;
3078 	uint8_t qe[QENTRY_LEN];
3079 	isp24xx_statusreq_t *sp = (isp24xx_statusreq_t *)qe;
3080 	ispstatus_cont_t *scp = (ispstatus_cont_t *)qe;
3081 	isphdr_t *hp;
3082 	uint8_t *resp, *snsp, etype;
3083 	uint16_t scsi_status;
3084 	uint32_t iptr, cont = 0, cptr, optr, rlen, slen, totslen;
3085 #ifdef	ISP_TARGET_MODE
3086 	uint32_t sptr;
3087 #endif
3088 
3089 	/*
3090 	 * We can't be getting this now.
3091 	 */
3092 	if (isp->isp_state != ISP_RUNSTATE) {
3093 		isp_prt(isp, ISP_LOGINFO, "respq interrupt when not ready");
3094 		return;
3095 	}
3096 
3097 	iptr = ISP_READ(isp, BIU2400_RSPINP);
3098 	optr = isp->isp_resodx;
3099 	while (optr != iptr) {
3100 		cptr = optr;
3101 #ifdef	ISP_TARGET_MODE
3102 		sptr = optr;
3103 #endif
3104 		hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, cptr);
3105 		optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp));
3106 
3107 		/*
3108 		 * Synchronize our view of this response queue entry.
3109 		 */
3110 		MEMORYBARRIER(isp, SYNC_RESULT, cptr, QENTRY_LEN, -1);
3111 		if (isp->isp_dblev & ISP_LOGDEBUG1)
3112 			isp_print_qentry(isp, "Response Queue Entry", cptr, hp);
3113 		isp_get_hdr(isp, hp, &sp->req_header);
3114 
3115 		/*
3116 		 * Log IOCBs rejected by the firmware.  We can't really do
3117 		 * much more about them, since it just should not happen.
3118 		 */
3119 		if (sp->req_header.rqs_flags & RQSFLAG_BADTYPE) {
3120 			isp_print_qentry(isp, "invalid entry type", cptr, hp);
3121 			continue;
3122 		}
3123 		if (sp->req_header.rqs_flags & RQSFLAG_BADPARAM) {
3124 			isp_print_qentry(isp, "invalid entry parameter", cptr, hp);
3125 			continue;
3126 		}
3127 		if (sp->req_header.rqs_flags & RQSFLAG_BADCOUNT) {
3128 			isp_print_qentry(isp, "invalid entry count", cptr, hp);
3129 			continue;
3130 		}
3131 		if (sp->req_header.rqs_flags & RQSFLAG_BADORDER) {
3132 			isp_print_qentry(isp, "invalid entry order", cptr, hp);
3133 			continue;
3134 		}
3135 
3136 		etype = sp->req_header.rqs_entry_type;
3137 
3138 		/* We expected Status Continuation, but got different IOCB. */
3139 		if (cont > 0 && etype != RQSTYPE_STATUS_CONT) {
3140 			cont = 0;
3141 			isp_done(cont_xs);
3142 		}
3143 
3144 		if (isp_handle_control(isp, hp)) {
3145 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3146 			continue;
3147 		}
3148 
3149 		switch (etype) {
3150 		case RQSTYPE_RESPONSE:
3151 			isp_get_24xx_response(isp, (isp24xx_statusreq_t *)hp, sp);
3152 			break;
3153 		case RQSTYPE_MARKER:
3154 			isp_prt(isp, ISP_LOG_WARN1, "Marker Response");
3155 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3156 			continue;
3157 		case RQSTYPE_STATUS_CONT:
3158 			isp_get_cont_response(isp, (ispstatus_cont_t *)hp, scp);
3159 			if (cont > 0) {
3160 				slen = min(cont, sizeof(scp->req_sense_data));
3161 				XS_SENSE_APPEND(cont_xs, scp->req_sense_data, slen);
3162 				cont -= slen;
3163 				if (cont == 0) {
3164 					isp_done(cont_xs);
3165 				} else {
3166 					isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
3167 					    "Expecting Status Continuations for %u bytes",
3168 					    cont);
3169 				}
3170 			} else {
3171 				isp_prt(isp, ISP_LOG_WARN1, "Ignored Continuation Response");
3172 			}
3173 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3174 			continue;
3175 #ifdef	ISP_TARGET_MODE
3176 		case RQSTYPE_NOTIFY_ACK:	/* Can be set to ATIO queue. */
3177 		case RQSTYPE_CTIO7:
3178 		case RQSTYPE_ABTS_RCVD:		/* Can be set to ATIO queue. */
3179 		case RQSTYPE_ABTS_RSP:
3180 			isp_target_notify(isp, hp, &cptr, RESULT_QUEUE_LEN(isp));
3181 			/* More then one IOCB could be consumed. */
3182 			while (sptr != cptr) {
3183 				ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3184 				sptr = ISP_NXT_QENTRY(sptr, RESULT_QUEUE_LEN(isp));
3185 				hp = (isphdr_t *)ISP_QUEUE_ENTRY(isp->isp_result, sptr);
3186 			}
3187 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3188 			optr = ISP_NXT_QENTRY(cptr, RESULT_QUEUE_LEN(isp));
3189 			continue;
3190 #endif
3191 		case RQSTYPE_RPT_ID_ACQ:	/* Can be set to ATIO queue.*/
3192 			isp_handle_rpt_id_acq(isp, hp);
3193 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3194 			continue;
3195 		default:
3196 			/* We don't know what was this -- log and skip. */
3197 			isp_prt(isp, ISP_LOGERR, notresp, etype, cptr, optr);
3198 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3199 			continue;
3200 		}
3201 
3202 		xs = isp_find_xs(isp, sp->req_handle);
3203 		if (xs == NULL) {
3204 			/*
3205 			 * Only whine if this isn't the expected fallout of
3206 			 * aborting the command or resetting the target.
3207 			 */
3208 			if (sp->req_completion_status != RQCS_ABORTED &&
3209 			    sp->req_completion_status != RQCS_RESET_OCCURRED)
3210 				isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)",
3211 				    sp->req_handle, sp->req_completion_status);
3212 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3213 			continue;
3214 		}
3215 
3216 		resp = snsp = sp->req_rsp_sense;
3217 		rlen = slen = totslen = 0;
3218 		scsi_status = sp->req_scsi_status;
3219 		if (scsi_status & RQCS_RV) {
3220 			rlen = sp->req_response_len;
3221 			snsp += rlen;
3222 		}
3223 		if (scsi_status & RQCS_SV) {
3224 			totslen = sp->req_sense_len;
3225 			slen = MIN(totslen, sizeof(sp->req_rsp_sense) - rlen);
3226 		}
3227 		*XS_STSP(xs) = scsi_status & 0xff;
3228 		if (scsi_status & RQCS_RESID)
3229 			XS_SET_RESID(xs, sp->req_fcp_residual);
3230 		else
3231 			XS_SET_RESID(xs, 0);
3232 
3233 		if (rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) {
3234 			const char *ptr;
3235 			char lb[64];
3236 			const char *rnames[10] = {
3237 			    "Task Management function complete",
3238 			    "FCP_DATA length different than FCP_BURST_LEN",
3239 			    "FCP_CMND fields invalid",
3240 			    "FCP_DATA parameter mismatch with FCP_DATA_RO",
3241 			    "Task Management function rejected",
3242 			    "Task Management function failed",
3243 			    NULL,
3244 			    NULL,
3245 			    "Task Management function succeeded",
3246 			    "Task Management function incorrect logical unit number",
3247 			};
3248 			uint8_t code = resp[FCP_RSPNS_CODE_OFFSET];
3249 			if (code >= nitems(rnames) || rnames[code] == NULL) {
3250 				ISP_SNPRINTF(lb, sizeof(lb),
3251 				    "Unknown FCP Response Code 0x%x", code);
3252 				ptr = lb;
3253 			} else {
3254 				ptr = rnames[code];
3255 			}
3256 			isp_xs_prt(isp, xs, ISP_LOGWARN,
3257 			    "FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x",
3258 			    rlen, ptr, XS_CDBP(xs)[0] & 0xff);
3259 			if (code != FCP_RSPNS_TMF_DONE &&
3260 			    code != FCP_RSPNS_TMF_SUCCEEDED)
3261 				XS_SETERR(xs, HBA_BOTCH);
3262 		}
3263 		isp_parse_status_24xx(isp, sp, xs);
3264 		if (slen > 0) {
3265 			XS_SAVE_SENSE(xs, snsp, slen);
3266 			if (totslen > slen) {
3267 				cont = totslen - slen;
3268 				cont_xs = xs;
3269 				isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
3270 				    "Expecting Status Continuations for %u bytes",
3271 				    cont);
3272 			}
3273 		}
3274 
3275 		ISP_DMAFREE(isp, xs);
3276 		isp_destroy_handle(isp, sp->req_handle);
3277 		ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3278 
3279 		/* Complete command if we expect no Status Continuations. */
3280 		if (cont == 0)
3281 			isp_done(xs);
3282 	}
3283 
3284 	/* We haven't received all Status Continuations, but that is it. */
3285 	if (cont > 0)
3286 		isp_done(cont_xs);
3287 
3288 	/* If we processed any IOCBs, let ISP know about it. */
3289 	if (optr != isp->isp_resodx) {
3290 		ISP_WRITE(isp, BIU2400_RSPOUTP, optr);
3291 		isp->isp_resodx = optr;
3292 	}
3293 }
3294 
3295 
3296 void
3297 isp_intr_async(ispsoftc_t *isp, uint16_t mbox)
3298 {
3299 	fcparam *fcp;
3300 	uint16_t chan;
3301 
3302 	isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox);
3303 
3304 	switch (mbox) {
3305 	case ASYNC_SYSTEM_ERROR:
3306 		isp->isp_state = ISP_CRASHED;
3307 		for (chan = 0; chan < isp->isp_nchan; chan++) {
3308 			FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
3309 			isp_change_fw_state(isp, chan, FW_CONFIG_WAIT);
3310 		}
3311 		/*
3312 		 * Were we waiting for a mailbox command to complete?
3313 		 * If so, it's dead, so wake up the waiter.
3314 		 */
3315 		if (isp->isp_mboxbsy) {
3316 			isp->isp_obits = 1;
3317 			isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR;
3318 			isp->isp_mboxbsy = 0;
3319 		}
3320 		/*
3321 		 * It's up to the handler for isp_async to reinit stuff and
3322 		 * restart the firmware
3323 		 */
3324 		isp_async(isp, ISPASYNC_FW_CRASH);
3325 		break;
3326 
3327 	case ASYNC_RQS_XFER_ERR:
3328 		isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error");
3329 		break;
3330 
3331 	case ASYNC_RSP_XFER_ERR:
3332 		isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error");
3333 		break;
3334 
3335 	case ASYNC_ATIO_XFER_ERR:
3336 		isp_prt(isp, ISP_LOGERR, "ATIO Queue Transfer Error");
3337 		break;
3338 
3339 	case ASYNC_LIP_OCCURRED:
3340 	case ASYNC_LIP_NOS_OLS_RECV:
3341 	case ASYNC_LIP_ERROR:
3342 	case ASYNC_PTPMODE:
3343 		/*
3344 		 * These are broadcast events that have to be sent across
3345 		 * all active channels.
3346 		 */
3347 		for (chan = 0; chan < isp->isp_nchan; chan++) {
3348 			fcp = FCPARAM(isp, chan);
3349 			int topo = fcp->isp_topo;
3350 
3351 			if (fcp->role == ISP_ROLE_NONE)
3352 				continue;
3353 			if (fcp->isp_loopstate > LOOP_HAVE_LINK)
3354 				fcp->isp_loopstate = LOOP_HAVE_LINK;
3355 			ISP_SET_SENDMARKER(isp, chan, 1);
3356 			isp_async(isp, ISPASYNC_LIP, chan);
3357 #ifdef	ISP_TARGET_MODE
3358 			isp_target_async(isp, chan, mbox);
3359 #endif
3360 			/*
3361 			 * We've had problems with data corruption occurring on
3362 			 * commands that complete (with no apparent error) after
3363 			 * we receive a LIP. This has been observed mostly on
3364 			 * Local Loop topologies. To be safe, let's just mark
3365 			 * all active initiator commands as dead.
3366 			 */
3367 			if (topo == TOPO_NL_PORT || topo == TOPO_FL_PORT) {
3368 				int i, j;
3369 				for (i = j = 0; i < ISP_HANDLE_NUM(isp); i++) {
3370 					XS_T *xs;
3371 					isp_hdl_t *hdp;
3372 
3373 					hdp = &isp->isp_xflist[i];
3374 					if (ISP_H2HT(hdp->handle) != ISP_HANDLE_INITIATOR) {
3375 						continue;
3376 					}
3377 					xs = hdp->cmd;
3378 					if (XS_CHANNEL(xs) != chan) {
3379 						continue;
3380 					}
3381 					j++;
3382 					isp_prt(isp, ISP_LOG_WARN1,
3383 					    "%d.%d.%jx bus reset set at %s:%u",
3384 					    XS_CHANNEL(xs), XS_TGT(xs),
3385 					    (uintmax_t)XS_LUN(xs),
3386 					    __func__, __LINE__);
3387 					XS_SETERR(xs, HBA_BUSRESET);
3388 				}
3389 				if (j) {
3390 					isp_prt(isp, ISP_LOGERR, lipd, chan, j);
3391 				}
3392 			}
3393 		}
3394 		break;
3395 
3396 	case ASYNC_LOOP_UP:
3397 		/*
3398 		 * This is a broadcast event that has to be sent across
3399 		 * all active channels.
3400 		 */
3401 		for (chan = 0; chan < isp->isp_nchan; chan++) {
3402 			fcp = FCPARAM(isp, chan);
3403 			if (fcp->role == ISP_ROLE_NONE)
3404 				continue;
3405 			fcp->isp_linkstate = 1;
3406 			if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3407 				fcp->isp_loopstate = LOOP_HAVE_LINK;
3408 			ISP_SET_SENDMARKER(isp, chan, 1);
3409 			isp_async(isp, ISPASYNC_LOOP_UP, chan);
3410 #ifdef	ISP_TARGET_MODE
3411 			isp_target_async(isp, chan, mbox);
3412 #endif
3413 		}
3414 		break;
3415 
3416 	case ASYNC_LOOP_DOWN:
3417 		/*
3418 		 * This is a broadcast event that has to be sent across
3419 		 * all active channels.
3420 		 */
3421 		for (chan = 0; chan < isp->isp_nchan; chan++) {
3422 			fcp = FCPARAM(isp, chan);
3423 			if (fcp->role == ISP_ROLE_NONE)
3424 				continue;
3425 			ISP_SET_SENDMARKER(isp, chan, 1);
3426 			fcp->isp_linkstate = 0;
3427 			fcp->isp_loopstate = LOOP_NIL;
3428 			isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
3429 #ifdef	ISP_TARGET_MODE
3430 			isp_target_async(isp, chan, mbox);
3431 #endif
3432 		}
3433 		break;
3434 
3435 	case ASYNC_LOOP_RESET:
3436 		/*
3437 		 * This is a broadcast event that has to be sent across
3438 		 * all active channels.
3439 		 */
3440 		for (chan = 0; chan < isp->isp_nchan; chan++) {
3441 			fcp = FCPARAM(isp, chan);
3442 			if (fcp->role == ISP_ROLE_NONE)
3443 				continue;
3444 			ISP_SET_SENDMARKER(isp, chan, 1);
3445 			if (fcp->isp_loopstate > LOOP_HAVE_LINK)
3446 				fcp->isp_loopstate = LOOP_HAVE_LINK;
3447 			isp_async(isp, ISPASYNC_LOOP_RESET, chan);
3448 #ifdef	ISP_TARGET_MODE
3449 			isp_target_async(isp, chan, mbox);
3450 #endif
3451 		}
3452 		break;
3453 
3454 	case ASYNC_PDB_CHANGED:
3455 	{
3456 		int echan, nphdl, nlstate, reason;
3457 
3458 		nphdl = ISP_READ(isp, OUTMAILBOX1);
3459 		nlstate = ISP_READ(isp, OUTMAILBOX2);
3460 		reason = ISP_READ(isp, OUTMAILBOX3) >> 8;
3461 		if (ISP_CAP_MULTI_ID(isp)) {
3462 			chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
3463 			if (chan == 0xff || nphdl == NIL_HANDLE) {
3464 				chan = 0;
3465 				echan = isp->isp_nchan - 1;
3466 			} else if (chan >= isp->isp_nchan) {
3467 				break;
3468 			} else {
3469 				echan = chan;
3470 			}
3471 		} else {
3472 			chan = echan = 0;
3473 		}
3474 		for (; chan <= echan; chan++) {
3475 			fcp = FCPARAM(isp, chan);
3476 			if (fcp->role == ISP_ROLE_NONE)
3477 				continue;
3478 			if (fcp->isp_loopstate > LOOP_LTEST_DONE) {
3479 				if (nphdl != NIL_HANDLE &&
3480 				    nphdl == fcp->isp_login_hdl &&
3481 				    reason == PDB24XX_AE_OPN_2)
3482 					continue;
3483 				fcp->isp_loopstate = LOOP_LTEST_DONE;
3484 			} else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3485 				fcp->isp_loopstate = LOOP_HAVE_LINK;
3486 			isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
3487 			    ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
3488 		}
3489 		break;
3490 	}
3491 	case ASYNC_CHANGE_NOTIFY:
3492 	{
3493 		int portid;
3494 
3495 		portid = ((ISP_READ(isp, OUTMAILBOX1) & 0xff) << 16) |
3496 		    ISP_READ(isp, OUTMAILBOX2);
3497 		if (ISP_CAP_MULTI_ID(isp)) {
3498 			chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
3499 			if (chan >= isp->isp_nchan)
3500 				break;
3501 		} else {
3502 			chan = 0;
3503 		}
3504 		fcp = FCPARAM(isp, chan);
3505 		if (fcp->role == ISP_ROLE_NONE)
3506 			break;
3507 		if (fcp->isp_loopstate > LOOP_LTEST_DONE)
3508 			fcp->isp_loopstate = LOOP_LTEST_DONE;
3509 		else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3510 			fcp->isp_loopstate = LOOP_HAVE_LINK;
3511 		isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
3512 		    ISPASYNC_CHANGE_SNS, portid);
3513 		break;
3514 	}
3515 	case ASYNC_ERR_LOGGING_DISABLED:
3516 		isp_prt(isp, ISP_LOGWARN, "Error logging disabled (reason 0x%x)",
3517 		    ISP_READ(isp, OUTMAILBOX1));
3518 		break;
3519 	case ASYNC_P2P_INIT_ERR:
3520 		isp_prt(isp, ISP_LOGWARN, "P2P init error (reason 0x%x)",
3521 		    ISP_READ(isp, OUTMAILBOX1));
3522 		break;
3523 	case ASYNC_RCV_ERR:
3524 		isp_prt(isp, ISP_LOGWARN, "Receive Error");
3525 		break;
3526 	case ASYNC_RJT_SENT:	/* same as ASYNC_QFULL_SENT */
3527 		isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent");
3528 		break;
3529 	case ASYNC_FW_RESTART_COMPLETE:
3530 		isp_prt(isp, ISP_LOGDEBUG0, "FW restart complete");
3531 		break;
3532 	case ASYNC_TEMPERATURE_ALERT:
3533 		isp_prt(isp, ISP_LOGERR, "Temperature alert (subcode 0x%x)",
3534 		    ISP_READ(isp, OUTMAILBOX1));
3535 		break;
3536 	case ASYNC_INTER_DRIVER_COMP:
3537 		isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication complete");
3538 		break;
3539 	case ASYNC_INTER_DRIVER_NOTIFY:
3540 		isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication notification");
3541 		break;
3542 	case ASYNC_INTER_DRIVER_TIME_EXT:
3543 		isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication time extended");
3544 		break;
3545 	case ASYNC_TRANSCEIVER_INSERTION:
3546 		isp_prt(isp, ISP_LOGDEBUG0, "Transceiver insertion (0x%x)",
3547 		    ISP_READ(isp, OUTMAILBOX1));
3548 		break;
3549 	case ASYNC_TRANSCEIVER_REMOVAL:
3550 		isp_prt(isp, ISP_LOGDEBUG0, "Transceiver removal");
3551 		break;
3552 	case ASYNC_NIC_FW_STATE_CHANGE:
3553 		isp_prt(isp, ISP_LOGDEBUG0, "NIC Firmware State Change");
3554 		break;
3555 	case ASYNC_AUTOLOAD_FW_COMPLETE:
3556 		isp_prt(isp, ISP_LOGDEBUG0, "Autoload FW init complete");
3557 		break;
3558 	case ASYNC_AUTOLOAD_FW_FAILURE:
3559 		isp_prt(isp, ISP_LOGERR, "Autoload FW init failure");
3560 		break;
3561 	default:
3562 		isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox);
3563 		break;
3564 	}
3565 }
3566 
3567 /*
3568  * Handle completions with control handles by waking up waiting threads.
3569  */
3570 static int
3571 isp_handle_control(ispsoftc_t *isp, isphdr_t *hp)
3572 {
3573 	uint32_t hdl;
3574 	void *ptr;
3575 
3576 	switch (hp->rqs_entry_type) {
3577 	case RQSTYPE_RESPONSE:
3578 	case RQSTYPE_MARKER:
3579 	case RQSTYPE_NOTIFY_ACK:
3580 	case RQSTYPE_CTIO7:
3581 	case RQSTYPE_TSK_MGMT:
3582 	case RQSTYPE_CT_PASSTHRU:
3583 	case RQSTYPE_VP_MODIFY:
3584 	case RQSTYPE_VP_CTRL:
3585 	case RQSTYPE_ABORT_IO:
3586 	case RQSTYPE_MBOX:
3587 	case RQSTYPE_LOGIN:
3588 	case RQSTYPE_ELS_PASSTHRU:
3589 		ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl);
3590 		if (ISP_H2HT(hdl) != ISP_HANDLE_CTRL)
3591 			break;
3592 		ptr = isp_find_xs(isp, hdl);
3593 		if (ptr != NULL) {
3594 			isp_destroy_handle(isp, hdl);
3595 			memcpy(ptr, hp, QENTRY_LEN);
3596 			wakeup(ptr);
3597 		}
3598 		return (1);
3599 	}
3600 	return (0);
3601 }
3602 
3603 static void
3604 isp_handle_rpt_id_acq(ispsoftc_t *isp, isphdr_t *hp)
3605 {
3606 	fcparam *fcp;
3607 	isp_ridacq_t rid;
3608 	int chan, c;
3609 	uint32_t portid;
3610 
3611 	isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid);
3612 	portid = (uint32_t)rid.ridacq_vp_port_hi << 16 |
3613 	    rid.ridacq_vp_port_lo;
3614 	if (rid.ridacq_format == 0) {
3615 		for (chan = 0; chan < isp->isp_nchan; chan++) {
3616 			fcp = FCPARAM(isp, chan);
3617 			if (fcp->role == ISP_ROLE_NONE)
3618 				continue;
3619 			c = (chan == 0) ? 127 : (chan - 1);
3620 			if (rid.ridacq_map[c / 16] & (1 << (c % 16)) ||
3621 			    chan == 0) {
3622 				fcp->isp_loopstate = LOOP_HAVE_LINK;
3623 				isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
3624 				    chan, ISPASYNC_CHANGE_OTHER);
3625 			} else {
3626 				fcp->isp_loopstate = LOOP_NIL;
3627 				isp_async(isp, ISPASYNC_LOOP_DOWN,
3628 				    chan);
3629 			}
3630 		}
3631 	} else {
3632 		fcp = FCPARAM(isp, rid.ridacq_vp_index);
3633 		if (rid.ridacq_vp_status == RIDACQ_STS_COMPLETE ||
3634 		    rid.ridacq_vp_status == RIDACQ_STS_CHANGED) {
3635 			fcp->isp_topo = (rid.ridacq_map[0] >> 9) & 0x7;
3636 			fcp->isp_portid = portid;
3637 			fcp->isp_loopstate = LOOP_HAVE_ADDR;
3638 			isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
3639 			    rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER);
3640 		} else {
3641 			fcp->isp_loopstate = LOOP_NIL;
3642 			isp_async(isp, ISPASYNC_LOOP_DOWN,
3643 			    rid.ridacq_vp_index);
3644 		}
3645 	}
3646 }
3647 
3648 static void
3649 isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, XS_T *xs)
3650 {
3651 	int ru_marked, sv_marked;
3652 	int chan = XS_CHANNEL(xs);
3653 
3654 	switch (sp->req_completion_status) {
3655 	case RQCS_COMPLETE:
3656 		return;
3657 
3658 	case RQCS_DMA_ERROR:
3659 		isp_xs_prt(isp, xs, ISP_LOGERR, "DMA error");
3660 		if (XS_NOERR(xs))
3661 			XS_SETERR(xs, HBA_BOTCH);
3662 		break;
3663 
3664 	case RQCS_TRANSPORT_ERROR:
3665 		isp_xs_prt(isp, xs,  ISP_LOGERR, "Transport Error");
3666 		if (XS_NOERR(xs))
3667 			XS_SETERR(xs, HBA_BOTCH);
3668 		break;
3669 
3670 	case RQCS_RESET_OCCURRED:
3671 		isp_xs_prt(isp, xs, ISP_LOGWARN, "reset destroyed command");
3672 		FCPARAM(isp, chan)->sendmarker = 1;
3673 		if (XS_NOERR(xs))
3674 			XS_SETERR(xs, HBA_BUSRESET);
3675 		return;
3676 
3677 	case RQCS_ABORTED:
3678 		isp_xs_prt(isp, xs, ISP_LOGERR, "Command Aborted");
3679 		FCPARAM(isp, chan)->sendmarker = 1;
3680 		if (XS_NOERR(xs))
3681 			XS_SETERR(xs, HBA_ABORTED);
3682 		return;
3683 
3684 	case RQCS_TIMEOUT:
3685 		isp_xs_prt(isp, xs, ISP_LOGWARN, "Command Timed Out");
3686 		if (XS_NOERR(xs))
3687 			XS_SETERR(xs, HBA_CMDTIMEOUT);
3688 		return;
3689 
3690 	case RQCS_DATA_OVERRUN:
3691 		XS_SET_RESID(xs, sp->req_resid);
3692 		isp_xs_prt(isp, xs, ISP_LOGERR, "Data Overrun");
3693 		if (XS_NOERR(xs))
3694 			XS_SETERR(xs, HBA_DATAOVR);
3695 		return;
3696 
3697 	case RQCS_DRE:		/* data reassembly error */
3698 		isp_prt(isp, ISP_LOGERR, "Chan %d data reassembly error for target %d", chan, XS_TGT(xs));
3699 		if (XS_NOERR(xs))
3700 			XS_SETERR(xs, HBA_BOTCH);
3701 		return;
3702 
3703 	case RQCS_TABORT:	/* aborted by target */
3704 		isp_prt(isp, ISP_LOGERR, "Chan %d target %d sent ABTS", chan, XS_TGT(xs));
3705 		if (XS_NOERR(xs))
3706 			XS_SETERR(xs, HBA_ABORTED);
3707 		return;
3708 
3709 	case RQCS_DATA_UNDERRUN:
3710 		ru_marked = (sp->req_scsi_status & RQCS_RU) != 0;
3711 		/*
3712 		 * We can get an underrun w/o things being marked
3713 		 * if we got a non-zero status.
3714 		 */
3715 		sv_marked = (sp->req_scsi_status & (RQCS_SV|RQCS_RV)) != 0;
3716 		if ((ru_marked == 0 && sv_marked == 0) ||
3717 		    (sp->req_resid > XS_XFRLEN(xs))) {
3718 			isp_xs_prt(isp, xs, ISP_LOGWARN, bun, XS_XFRLEN(xs), sp->req_resid, (ru_marked)? "marked" : "not marked");
3719 			if (XS_NOERR(xs))
3720 				XS_SETERR(xs, HBA_BOTCH);
3721 			return;
3722 		}
3723 		XS_SET_RESID(xs, sp->req_resid);
3724 		isp_xs_prt(isp, xs, ISP_LOG_WARN1, "Data Underrun (%d) for command 0x%x", sp->req_resid, XS_CDBP(xs)[0] & 0xff);
3725 		return;
3726 
3727 	case RQCS_PORT_UNAVAILABLE:
3728 		/*
3729 		 * No such port on the loop. Moral equivalent of SELTIMEO
3730 		 */
3731 	case RQCS_PORT_LOGGED_OUT:
3732 	{
3733 		const char *reason;
3734 		uint8_t sts = sp->req_completion_status & 0xff;
3735 		fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs));
3736 		fcportdb_t *lp;
3737 
3738 		/*
3739 		 * It was there (maybe)- treat as a selection timeout.
3740 		 */
3741 		if (sts == RQCS_PORT_UNAVAILABLE) {
3742 			reason = "unavailable";
3743 		} else {
3744 			reason = "logout";
3745 		}
3746 
3747 		isp_prt(isp, ISP_LOGINFO, "Chan %d port %s for target %d",
3748 		    chan, reason, XS_TGT(xs));
3749 
3750 		/* XXX: Should we trigger rescan or FW announce change? */
3751 
3752 		if (XS_NOERR(xs)) {
3753 			lp = &fcp->portdb[XS_TGT(xs)];
3754 			if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
3755 				*XS_STSP(xs) = SCSI_BUSY;
3756 				XS_SETERR(xs, HBA_TGTBSY);
3757 			} else
3758 				XS_SETERR(xs, HBA_SELTIMEOUT);
3759 		}
3760 		return;
3761 	}
3762 	case RQCS_PORT_CHANGED:
3763 		isp_prt(isp, ISP_LOGWARN, "port changed for target %d chan %d", XS_TGT(xs), chan);
3764 		if (XS_NOERR(xs)) {
3765 			*XS_STSP(xs) = SCSI_BUSY;
3766 			XS_SETERR(xs, HBA_TGTBSY);
3767 		}
3768 		return;
3769 
3770 	case RQCS_ENOMEM:	/* f/w resource unavailable */
3771 		isp_prt(isp, ISP_LOGWARN, "f/w resource unavailable for target %d chan %d", XS_TGT(xs), chan);
3772 		if (XS_NOERR(xs)) {
3773 			*XS_STSP(xs) = SCSI_BUSY;
3774 			XS_SETERR(xs, HBA_TGTBSY);
3775 		}
3776 		return;
3777 
3778 	case RQCS_TMO:		/* task management overrun */
3779 		isp_prt(isp, ISP_LOGWARN, "command for target %d overlapped task management for chan %d", XS_TGT(xs), chan);
3780 		if (XS_NOERR(xs)) {
3781 			*XS_STSP(xs) = SCSI_BUSY;
3782 			XS_SETERR(xs, HBA_TGTBSY);
3783 		}
3784 		return;
3785 
3786 	default:
3787 		isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x on chan %d", sp->req_completion_status, chan);
3788 		break;
3789 	}
3790 	if (XS_NOERR(xs))
3791 		XS_SETERR(xs, HBA_BOTCH);
3792 }
3793 
3794 #define	ISP_FC_IBITS(op)	((mbpfc[((op)<<3) + 0] << 24) | (mbpfc[((op)<<3) + 1] << 16) | (mbpfc[((op)<<3) + 2] << 8) | (mbpfc[((op)<<3) + 3]))
3795 #define	ISP_FC_OBITS(op)	((mbpfc[((op)<<3) + 4] << 24) | (mbpfc[((op)<<3) + 5] << 16) | (mbpfc[((op)<<3) + 6] << 8) | (mbpfc[((op)<<3) + 7]))
3796 
3797 #define	ISP_FC_OPMAP(in0, out0)							  0,   0,   0, in0,    0,    0,    0, out0
3798 #define	ISP_FC_OPMAP_HALF(in1, in0, out1, out0)					  0,   0, in1, in0,    0,    0, out1, out0
3799 #define	ISP_FC_OPMAP_FULL(in3, in2, in1, in0, out3, out2, out1, out0)		in3, in2, in1, in0, out3, out2, out1, out0
3800 static const uint32_t mbpfc[] = {
3801 	ISP_FC_OPMAP(0x01, 0x01),	/* 0x00: MBOX_NO_OP */
3802 	ISP_FC_OPMAP(0x1f, 0x01),	/* 0x01: MBOX_LOAD_RAM */
3803 	ISP_FC_OPMAP_HALF(0x07, 0xff, 0x00, 0x1f),	/* 0x02: MBOX_EXEC_FIRMWARE */
3804 	ISP_FC_OPMAP(0xdf, 0x01),	/* 0x03: MBOX_DUMP_RAM */
3805 	ISP_FC_OPMAP(0x07, 0x07),	/* 0x04: MBOX_WRITE_RAM_WORD */
3806 	ISP_FC_OPMAP(0x03, 0x07),	/* 0x05: MBOX_READ_RAM_WORD */
3807 	ISP_FC_OPMAP_FULL(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff),	/* 0x06: MBOX_MAILBOX_REG_TEST */
3808 	ISP_FC_OPMAP(0x07, 0x07),	/* 0x07: MBOX_VERIFY_CHECKSUM	*/
3809 	ISP_FC_OPMAP_FULL(0x0, 0x0, 0x0, 0x01, 0x0, 0x3, 0x80, 0x7f),	/* 0x08: MBOX_ABOUT_FIRMWARE */
3810 	ISP_FC_OPMAP(0xdf, 0x01),	/* 0x09: MBOX_LOAD_RISC_RAM_2100 */
3811 	ISP_FC_OPMAP(0xdf, 0x01),	/* 0x0a: DUMP RAM */
3812 	ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x01),	/* 0x0b: MBOX_LOAD_RISC_RAM */
3813 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x0c: */
3814 	ISP_FC_OPMAP_HALF(0x1, 0x0f, 0x0, 0x01),	/* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */
3815 	ISP_FC_OPMAP(0x01, 0x05),	/* 0x0e: MBOX_CHECK_FIRMWARE */
3816 	ISP_FC_OPMAP_HALF(0x1, 0x03, 0x0, 0x0d),	/* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */
3817 	ISP_FC_OPMAP(0x1f, 0x11),	/* 0x10: MBOX_INIT_REQ_QUEUE */
3818 	ISP_FC_OPMAP(0x2f, 0x21),	/* 0x11: MBOX_INIT_RES_QUEUE */
3819 	ISP_FC_OPMAP(0x0f, 0x01),	/* 0x12: MBOX_EXECUTE_IOCB */
3820 	ISP_FC_OPMAP(0x03, 0x03),	/* 0x13: MBOX_WAKE_UP	*/
3821 	ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x03),	/* 0x14: MBOX_STOP_FIRMWARE */
3822 	ISP_FC_OPMAP(0x4f, 0x01),	/* 0x15: MBOX_ABORT */
3823 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x16: MBOX_ABORT_DEVICE */
3824 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x17: MBOX_ABORT_TARGET */
3825 	ISP_FC_OPMAP(0x03, 0x03),	/* 0x18: MBOX_BUS_RESET */
3826 	ISP_FC_OPMAP(0x07, 0x05),	/* 0x19: MBOX_STOP_QUEUE */
3827 	ISP_FC_OPMAP(0x07, 0x05),	/* 0x1a: MBOX_START_QUEUE */
3828 	ISP_FC_OPMAP(0x07, 0x05),	/* 0x1b: MBOX_SINGLE_STEP_QUEUE */
3829 	ISP_FC_OPMAP(0x07, 0x05),	/* 0x1c: MBOX_ABORT_QUEUE */
3830 	ISP_FC_OPMAP(0x07, 0x03),	/* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
3831 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x1e: */
3832 	ISP_FC_OPMAP(0x01, 0x07),	/* 0x1f: MBOX_GET_FIRMWARE_STATUS */
3833 	ISP_FC_OPMAP_HALF(0x2, 0x01, 0x7e, 0xcf),	/* 0x20: MBOX_GET_LOOP_ID */
3834 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x21: */
3835 	ISP_FC_OPMAP(0x03, 0x4b),	/* 0x22: MBOX_GET_TIMEOUT_PARAMS */
3836 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x23: */
3837 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x24: */
3838 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x25: */
3839 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x26: */
3840 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x27: */
3841 	ISP_FC_OPMAP(0x01, 0x03),	/* 0x28: MBOX_GET_FIRMWARE_OPTIONS */
3842 	ISP_FC_OPMAP(0x03, 0x07),	/* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */
3843 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x2a: */
3844 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x2b: */
3845 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x2c: */
3846 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x2d: */
3847 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x2e: */
3848 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x2f: */
3849 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x30: */
3850 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x31: */
3851 	ISP_FC_OPMAP(0x4b, 0x4b),	/* 0x32: MBOX_SET_TIMEOUT_PARAMS */
3852 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x33: */
3853 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x34: */
3854 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x35: */
3855 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x36: */
3856 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x37: */
3857 	ISP_FC_OPMAP(0x0f, 0x01),	/* 0x38: MBOX_SET_FIRMWARE_OPTIONS */
3858 	ISP_FC_OPMAP(0x0f, 0x07),	/* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */
3859 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x3a: */
3860 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x3b: */
3861 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x3c: */
3862 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x3d: */
3863 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x3e: */
3864 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x3f: */
3865 	ISP_FC_OPMAP(0x03, 0x01),	/* 0x40: MBOX_LOOP_PORT_BYPASS */
3866 	ISP_FC_OPMAP(0x03, 0x01),	/* 0x41: MBOX_LOOP_PORT_ENABLE */
3867 	ISP_FC_OPMAP_HALF(0x0, 0x01, 0x1f, 0xcf),	/* 0x42: MBOX_GET_RESOURCE_COUNT */
3868 	ISP_FC_OPMAP(0x01, 0x01),	/* 0x43: MBOX_REQUEST_OFFLINE_MODE */
3869 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x44: */
3870 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x45: */
3871 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x46: */
3872 	ISP_FC_OPMAP(0xcf, 0x03),	/* 0x47: GET PORT_DATABASE ENHANCED */
3873 	ISP_FC_OPMAP(0xcf, 0x0f),	/* 0x48: MBOX_INIT_FIRMWARE_MULTI_ID */
3874 	ISP_FC_OPMAP(0xcd, 0x01),	/* 0x49: MBOX_GET_VP_DATABASE */
3875 	ISP_FC_OPMAP_HALF(0x2, 0xcd, 0x0, 0x01),	/* 0x4a: MBOX_GET_VP_DATABASE_ENTRY */
3876 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x4b: */
3877 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x4c: */
3878 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x4d: */
3879 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x4e: */
3880 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x4f: */
3881 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x50: */
3882 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x51: */
3883 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x52: */
3884 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x53: */
3885 	ISP_FC_OPMAP(0xcf, 0x01),	/* 0x54: EXECUTE IOCB A64 */
3886 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x55: */
3887 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x56: */
3888 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x57: */
3889 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x58: */
3890 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x59: */
3891 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x5a: */
3892 	ISP_FC_OPMAP(0x03, 0x01),	/* 0x5b: MBOX_DRIVER_HEARTBEAT */
3893 	ISP_FC_OPMAP(0xcf, 0x01),	/* 0x5c: MBOX_FW_HEARTBEAT */
3894 	ISP_FC_OPMAP(0x07, 0x1f),	/* 0x5d: MBOX_GET_SET_DATA_RATE */
3895 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x5e: */
3896 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x5f: */
3897 	ISP_FC_OPMAP(0xcf, 0x0f),	/* 0x60: MBOX_INIT_FIRMWARE */
3898 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x61: */
3899 	ISP_FC_OPMAP(0x01, 0x01),	/* 0x62: MBOX_INIT_LIP */
3900 	ISP_FC_OPMAP(0xcd, 0x03),	/* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
3901 	ISP_FC_OPMAP(0xcf, 0x01),	/* 0x64: MBOX_GET_PORT_DB */
3902 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x65: MBOX_CLEAR_ACA */
3903 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x66: MBOX_TARGET_RESET */
3904 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x67: MBOX_CLEAR_TASK_SET */
3905 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x68: MBOX_ABORT_TASK_SET */
3906 	ISP_FC_OPMAP_HALF(0x00, 0x01, 0x0f, 0x1f),	/* 0x69: MBOX_GET_FW_STATE */
3907 	ISP_FC_OPMAP_HALF(0x6, 0x03, 0x0, 0xcf),	/* 0x6a: MBOX_GET_PORT_NAME */
3908 	ISP_FC_OPMAP(0xcf, 0x01),	/* 0x6b: MBOX_GET_LINK_STATUS */
3909 	ISP_FC_OPMAP(0x0f, 0x01),	/* 0x6c: MBOX_INIT_LIP_RESET */
3910 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x6d: */
3911 	ISP_FC_OPMAP(0xcf, 0x03),	/* 0x6e: MBOX_SEND_SNS */
3912 	ISP_FC_OPMAP(0x0f, 0x07),	/* 0x6f: MBOX_FABRIC_LOGIN */
3913 	ISP_FC_OPMAP_HALF(0x02, 0x03, 0x00, 0x03),	/* 0x70: MBOX_SEND_CHANGE_REQUEST */
3914 	ISP_FC_OPMAP(0x03, 0x03),	/* 0x71: MBOX_FABRIC_LOGOUT */
3915 	ISP_FC_OPMAP(0x0f, 0x0f),	/* 0x72: MBOX_INIT_LIP_LOGIN */
3916 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x73: */
3917 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x74: LOGIN LOOP PORT */
3918 	ISP_FC_OPMAP_HALF(0x03, 0xcf, 0x00, 0x07),	/* 0x75: GET PORT/NODE NAME LIST */
3919 	ISP_FC_OPMAP(0x4f, 0x01),	/* 0x76: SET VENDOR ID */
3920 	ISP_FC_OPMAP(0xcd, 0x01),	/* 0x77: INITIALIZE IP MAILBOX */
3921 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x78: */
3922 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x79: */
3923 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x7a: */
3924 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x7b: */
3925 	ISP_FC_OPMAP_HALF(0x03, 0x4f, 0x00, 0x07),	/* 0x7c: Get ID List */
3926 	ISP_FC_OPMAP(0xcf, 0x01),	/* 0x7d: SEND LFA */
3927 	ISP_FC_OPMAP(0x0f, 0x01)	/* 0x7e: LUN RESET */
3928 };
3929 #define	MAX_FC_OPCODE	0x7e
3930 /*
3931  * Footnotes
3932  *
3933  * (1): this sets bits 21..16 in mailbox register #8, which we nominally
3934  *	do not access at this time in the core driver. The caller is
3935  *	responsible for setting this register first (Gross!). The assumption
3936  *	is that we won't overflow.
3937  */
3938 
3939 static const char *fc_mbcmd_names[] = {
3940 	"NO-OP",			/* 00h */
3941 	"LOAD RAM",
3942 	"EXEC FIRMWARE",
3943 	"DUMP RAM",
3944 	"WRITE RAM WORD",
3945 	"READ RAM WORD",
3946 	"MAILBOX REG TEST",
3947 	"VERIFY CHECKSUM",
3948 	"ABOUT FIRMWARE",
3949 	"LOAD RAM (2100)",
3950 	"DUMP RAM",
3951 	"LOAD RISC RAM",
3952 	"DUMP RISC RAM",
3953 	"WRITE RAM WORD EXTENDED",
3954 	"CHECK FIRMWARE",
3955 	"READ RAM WORD EXTENDED",
3956 	"INIT REQUEST QUEUE",		/* 10h */
3957 	"INIT RESULT QUEUE",
3958 	"EXECUTE IOCB",
3959 	"WAKE UP",
3960 	"STOP FIRMWARE",
3961 	"ABORT",
3962 	"ABORT DEVICE",
3963 	"ABORT TARGET",
3964 	"BUS RESET",
3965 	"STOP QUEUE",
3966 	"START QUEUE",
3967 	"SINGLE STEP QUEUE",
3968 	"ABORT QUEUE",
3969 	"GET DEV QUEUE STATUS",
3970 	NULL,
3971 	"GET FIRMWARE STATUS",
3972 	"GET LOOP ID",			/* 20h */
3973 	NULL,
3974 	"GET TIMEOUT PARAMS",
3975 	NULL,
3976 	NULL,
3977 	NULL,
3978 	NULL,
3979 	NULL,
3980 	"GET FIRMWARE OPTIONS",
3981 	"GET PORT QUEUE PARAMS",
3982 	"GENERATE SYSTEM ERROR",
3983 	NULL,
3984 	NULL,
3985 	NULL,
3986 	NULL,
3987 	NULL,
3988 	"WRITE SFP",			/* 30h */
3989 	"READ SFP",
3990 	"SET TIMEOUT PARAMS",
3991 	NULL,
3992 	NULL,
3993 	NULL,
3994 	NULL,
3995 	NULL,
3996 	"SET FIRMWARE OPTIONS",
3997 	"SET PORT QUEUE PARAMS",
3998 	NULL,
3999 	"SET FC LED CONF",
4000 	NULL,
4001 	"RESTART NIC FIRMWARE",
4002 	"ACCESS CONTROL",
4003 	NULL,
4004 	"LOOP PORT BYPASS",		/* 40h */
4005 	"LOOP PORT ENABLE",
4006 	"GET RESOURCE COUNT",
4007 	"REQUEST NON PARTICIPATING MODE",
4008 	"DIAGNOSTIC ECHO TEST",
4009 	"DIAGNOSTIC LOOPBACK",
4010 	NULL,
4011 	"GET PORT DATABASE ENHANCED",
4012 	"INIT FIRMWARE MULTI ID",
4013 	"GET VP DATABASE",
4014 	"GET VP DATABASE ENTRY",
4015 	NULL,
4016 	NULL,
4017 	NULL,
4018 	NULL,
4019 	NULL,
4020 	"GET FCF LIST",			/* 50h */
4021 	"GET DCBX PARAMETERS",
4022 	NULL,
4023 	"HOST MEMORY COPY",
4024 	"EXECUTE IOCB A64",
4025 	NULL,
4026 	NULL,
4027 	"SEND RNID",
4028 	NULL,
4029 	"SET PARAMETERS",
4030 	"GET PARAMETERS",
4031 	"DRIVER HEARTBEAT",
4032 	"FIRMWARE HEARTBEAT",
4033 	"GET/SET DATA RATE",
4034 	"SEND RNFT",
4035 	NULL,
4036 	"INIT FIRMWARE",		/* 60h */
4037 	"GET INIT CONTROL BLOCK",
4038 	"INIT LIP",
4039 	"GET FC-AL POSITION MAP",
4040 	"GET PORT DATABASE",
4041 	"CLEAR ACA",
4042 	"TARGET RESET",
4043 	"CLEAR TASK SET",
4044 	"ABORT TASK SET",
4045 	"GET FW STATE",
4046 	"GET PORT NAME",
4047 	"GET LINK STATUS",
4048 	"INIT LIP RESET",
4049 	"GET LINK STATS & PRIVATE DATA CNTS",
4050 	"SEND SNS",
4051 	"FABRIC LOGIN",
4052 	"SEND CHANGE REQUEST",		/* 70h */
4053 	"FABRIC LOGOUT",
4054 	"INIT LIP LOGIN",
4055 	NULL,
4056 	"LOGIN LOOP PORT",
4057 	"GET PORT/NODE NAME LIST",
4058 	"SET VENDOR ID",
4059 	"INITIALIZE IP MAILBOX",
4060 	NULL,
4061 	NULL,
4062 	"GET XGMAC STATS",
4063 	NULL,
4064 	"GET ID LIST",
4065 	"SEND LFA",
4066 	"LUN RESET"
4067 };
4068 
4069 static void
4070 isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
4071 {
4072 	const char *cname, *xname, *sname;
4073 	char tname[16], mname[16];
4074 	unsigned int ibits, obits, box, opcode, t, to;
4075 
4076 	opcode = mbp->param[0];
4077 	if (opcode > MAX_FC_OPCODE) {
4078 		mbp->param[0] = MBOX_INVALID_COMMAND;
4079 		isp_prt(isp, ISP_LOGERR, "Unknown Command 0x%x", opcode);
4080 		return;
4081 	}
4082 	cname = fc_mbcmd_names[opcode];
4083 	ibits = ISP_FC_IBITS(opcode);
4084 	obits = ISP_FC_OBITS(opcode);
4085 	if (cname == NULL) {
4086 		cname = tname;
4087 		ISP_SNPRINTF(tname, sizeof tname, "opcode %x", opcode);
4088 	}
4089 	isp_prt(isp, ISP_LOGDEBUG3, "Mailbox Command '%s'", cname);
4090 
4091 	/*
4092 	 * Pick up any additional bits that the caller might have set.
4093 	 */
4094 	ibits |= mbp->ibits;
4095 	obits |= mbp->obits;
4096 
4097 	/*
4098 	 * Mask any bits that the caller wants us to mask
4099 	 */
4100 	ibits &= mbp->ibitm;
4101 	obits &= mbp->obitm;
4102 
4103 
4104 	if (ibits == 0 && obits == 0) {
4105 		mbp->param[0] = MBOX_COMMAND_PARAM_ERROR;
4106 		isp_prt(isp, ISP_LOGERR, "no parameters for 0x%x", opcode);
4107 		return;
4108 	}
4109 
4110 	for (box = 0; box < ISP_NMBOX(isp); box++) {
4111 		if (ibits & (1 << box)) {
4112 			isp_prt(isp, ISP_LOGDEBUG3, "IN mbox %d = 0x%04x", box,
4113 			    mbp->param[box]);
4114 			ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
4115 		}
4116 		isp->isp_mboxtmp[box] = mbp->param[box] = 0;
4117 	}
4118 
4119 	isp->isp_obits = obits;
4120 	isp->isp_mboxbsy = 1;
4121 
4122 	/*
4123 	 * Set Host Interrupt condition so that RISC will pick up mailbox regs.
4124 	 */
4125 	ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT);
4126 
4127 	/*
4128 	 * While we haven't finished the command, spin our wheels here.
4129 	 */
4130 	to = (mbp->timeout == 0) ? MBCMD_DEFAULT_TIMEOUT : mbp->timeout;
4131 	for (t = 0; t < to; t += 100) {
4132 		if (!isp->isp_mboxbsy)
4133 			break;
4134 		ISP_RUN_ISR(isp);
4135 		if (!isp->isp_mboxbsy)
4136 			break;
4137 		ISP_DELAY(100);
4138 	}
4139 
4140 	/*
4141 	 * Did the command time out?
4142 	 */
4143 	if (isp->isp_mboxbsy) {
4144 		isp->isp_mboxbsy = 0;
4145 		isp_prt(isp, ISP_LOGWARN, "Mailbox Command (0x%x) Timeout (%uus) (%s:%d)",
4146 		    opcode, to, mbp->func, mbp->lineno);
4147 		mbp->param[0] = MBOX_TIMEOUT;
4148 		goto out;
4149 	}
4150 
4151 	/*
4152 	 * Copy back output registers.
4153 	 */
4154 	for (box = 0; box < ISP_NMBOX(isp); box++) {
4155 		if (obits & (1 << box)) {
4156 			mbp->param[box] = isp->isp_mboxtmp[box];
4157 			isp_prt(isp, ISP_LOGDEBUG3, "OUT mbox %d = 0x%04x", box,
4158 			    mbp->param[box]);
4159 		}
4160 	}
4161 
4162 out:
4163 	if (mbp->logval == 0 || mbp->param[0] == MBOX_COMMAND_COMPLETE)
4164 		return;
4165 
4166 	if ((mbp->param[0] & 0xbfe0) == 0 &&
4167 	    (mbp->logval & MBLOGMASK(mbp->param[0])) == 0)
4168 		return;
4169 
4170 	xname = NULL;
4171 	sname = "";
4172 	switch (mbp->param[0]) {
4173 	case MBOX_INVALID_COMMAND:
4174 		xname = "INVALID COMMAND";
4175 		break;
4176 	case MBOX_HOST_INTERFACE_ERROR:
4177 		xname = "HOST INTERFACE ERROR";
4178 		break;
4179 	case MBOX_TEST_FAILED:
4180 		xname = "TEST FAILED";
4181 		break;
4182 	case MBOX_COMMAND_ERROR:
4183 		xname = "COMMAND ERROR";
4184 		ISP_SNPRINTF(mname, sizeof(mname), " subcode 0x%x",
4185 		    mbp->param[1]);
4186 		sname = mname;
4187 		break;
4188 	case MBOX_COMMAND_PARAM_ERROR:
4189 		xname = "COMMAND PARAMETER ERROR";
4190 		break;
4191 	case MBOX_PORT_ID_USED:
4192 		xname = "PORT ID ALREADY IN USE";
4193 		break;
4194 	case MBOX_LOOP_ID_USED:
4195 		xname = "LOOP ID ALREADY IN USE";
4196 		break;
4197 	case MBOX_ALL_IDS_USED:
4198 		xname = "ALL LOOP IDS IN USE";
4199 		break;
4200 	case MBOX_NOT_LOGGED_IN:
4201 		xname = "NOT LOGGED IN";
4202 		break;
4203 	case MBOX_LINK_DOWN_ERROR:
4204 		xname = "LINK DOWN ERROR";
4205 		break;
4206 	case MBOX_LOOPBACK_ERROR:
4207 		xname = "LOOPBACK ERROR";
4208 		break;
4209 	case MBOX_CHECKSUM_ERROR:
4210 		xname = "CHECKSUM ERROR";
4211 		break;
4212 	case MBOX_INVALID_PRODUCT_KEY:
4213 		xname = "INVALID PRODUCT KEY";
4214 		break;
4215 	case MBOX_REGS_BUSY:
4216 		xname = "REGISTERS BUSY";
4217 		break;
4218 	case MBOX_TIMEOUT:
4219 		xname = "TIMEOUT";
4220 		break;
4221 	default:
4222 		ISP_SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]);
4223 		xname = mname;
4224 		break;
4225 	}
4226 	if (xname) {
4227 		isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s%s)",
4228 		    cname, xname, sname);
4229 	}
4230 }
4231 
4232 static int
4233 isp_fw_state(ispsoftc_t *isp, int chan)
4234 {
4235 	mbreg_t mbs;
4236 
4237 	MBSINIT(&mbs, MBOX_GET_FW_STATE, MBLOGALL, 0);
4238 	isp_mboxcmd(isp, &mbs);
4239 	if (mbs.param[0] == MBOX_COMMAND_COMPLETE)
4240 		return (mbs.param[1]);
4241 	return (FW_ERROR);
4242 }
4243 
4244 static void
4245 isp_setdfltfcparm(ispsoftc_t *isp, int chan)
4246 {
4247 	fcparam *fcp = FCPARAM(isp, chan);
4248 
4249 	/*
4250 	 * Establish some default parameters.
4251 	 */
4252 	fcp->role = DEFAULT_ROLE(isp, chan);
4253 	fcp->isp_retry_delay = ICB_DFLT_RDELAY;
4254 	fcp->isp_retry_count = ICB_DFLT_RCOUNT;
4255 	fcp->isp_loopid = DEFAULT_LOOPID(isp, chan);
4256 	fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp, chan);
4257 	fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp, chan);
4258 	fcp->isp_fwoptions = 0;
4259 	fcp->isp_xfwoptions = 0;
4260 	fcp->isp_zfwoptions = 0;
4261 	fcp->isp_lasthdl = NIL_HANDLE;
4262 	fcp->isp_login_hdl = NIL_HANDLE;
4263 
4264 	fcp->isp_fwoptions |= ICB2400_OPT1_FAIRNESS;
4265 	fcp->isp_fwoptions |= ICB2400_OPT1_HARD_ADDRESS;
4266 	if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX)
4267 		fcp->isp_fwoptions |= ICB2400_OPT1_FULL_DUPLEX;
4268 	fcp->isp_fwoptions |= ICB2400_OPT1_BOTH_WWNS;
4269 	fcp->isp_xfwoptions |= ICB2400_OPT2_LOOP_2_PTP;
4270 	fcp->isp_zfwoptions |= ICB2400_OPT3_RATE_AUTO;
4271 
4272 	/*
4273 	 * Now try and read NVRAM unless told to not do so.
4274 	 * This will set fcparam's isp_wwnn_nvram && isp_wwpn_nvram.
4275 	 */
4276 	if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
4277 		int i, j = 0;
4278 		/*
4279 		 * Give a couple of tries at reading NVRAM.
4280 		 */
4281 		for (i = 0; i < 2; i++) {
4282 			j = isp_read_nvram(isp, chan);
4283 			if (j == 0) {
4284 				break;
4285 			}
4286 		}
4287 		if (j) {
4288 			isp->isp_confopts |= ISP_CFG_NONVRAM;
4289 		}
4290 	}
4291 
4292 	fcp->isp_wwnn = ACTIVE_NODEWWN(isp, chan);
4293 	fcp->isp_wwpn = ACTIVE_PORTWWN(isp, chan);
4294 	isp_prt(isp, ISP_LOGCONFIG, "Chan %d 0x%08x%08x/0x%08x%08x Role %s",
4295 	    chan, (uint32_t) (fcp->isp_wwnn >> 32), (uint32_t) (fcp->isp_wwnn),
4296 	    (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) (fcp->isp_wwpn),
4297 	    isp_class3_roles[fcp->role]);
4298 }
4299 
4300 /*
4301  * Re-initialize the ISP and complete all orphaned commands
4302  * with a 'botched' notice. The reset/init routines should
4303  * not disturb an already active list of commands.
4304  */
4305 
4306 int
4307 isp_reinit(ispsoftc_t *isp, int do_load_defaults)
4308 {
4309 	int i, res = 0;
4310 
4311 	if (isp->isp_state > ISP_RESETSTATE)
4312 		isp_stop(isp);
4313 	if (isp->isp_state != ISP_RESETSTATE)
4314 		isp_reset(isp, do_load_defaults);
4315 	if (isp->isp_state != ISP_RESETSTATE) {
4316 		res = EIO;
4317 		isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__);
4318 		goto cleanup;
4319 	}
4320 
4321 	isp_init(isp);
4322 	if (isp->isp_state > ISP_RESETSTATE &&
4323 	    isp->isp_state != ISP_RUNSTATE) {
4324 		res = EIO;
4325 		isp_prt(isp, ISP_LOGERR, "%s: cannot init card", __func__);
4326 		ISP_DISABLE_INTS(isp);
4327 	}
4328 
4329 cleanup:
4330 	isp_clear_commands(isp);
4331 	for (i = 0; i < isp->isp_nchan; i++)
4332 		isp_clear_portdb(isp, i);
4333 	return (res);
4334 }
4335 
4336 /*
4337  * NVRAM Routines
4338  */
4339 static int
4340 isp_read_nvram(ispsoftc_t *isp, int bus)
4341 {
4342 	fcparam *fcp = FCPARAM(isp, 0);
4343 	int r = 0;
4344 
4345 	if (isp->isp_type != ISP_HA_FC_2600) {
4346 		if (IS_28XX(isp)) {
4347 			fcp->flash_data_addr = ISP28XX_BASE_ADDR;
4348 			fcp->flt_region_flt = ISP28XX_FLT_ADDR;
4349 		} else if (IS_27XX(isp)) {
4350 			fcp->flash_data_addr = ISP27XX_BASE_ADDR;
4351 			fcp->flt_region_flt = ISP27XX_FLT_ADDR;
4352 		} else if (IS_25XX(isp)) {
4353 			fcp->flash_data_addr = ISP25XX_BASE_ADDR;
4354 			fcp->flt_region_flt = ISP25XX_FLT_ADDR;
4355 		} else {
4356 			fcp->flash_data_addr = ISP24XX_BASE_ADDR;
4357 			fcp->flt_region_flt = ISP24XX_FLT_ADDR;
4358 		}
4359 		fcp->flt_length = 0;
4360 		r = isp_read_flthdr_2xxx(isp);
4361 		if (r == 0) {
4362 			isp_read_flt_2xxx(isp);
4363 		} else { /* fallback to hardcoded NVRAM address */
4364 			if (IS_28XX(isp)) {
4365 				fcp->flt_region_nvram = 0x300000;
4366 			} else if (IS_27XX(isp)) {
4367 				fcp->flash_data_addr = 0x7fe7c000;
4368 				fcp->flt_region_nvram = 0;
4369 			} else if (IS_25XX(isp)) {
4370 				fcp->flt_region_nvram = 0x48000;
4371 			} else {
4372 				fcp->flash_data_addr = 0x7ffe0000;
4373 				fcp->flt_region_nvram = 0;
4374 			}
4375 			fcp->flt_region_nvram += ISP2400_NVRAM_PORT_ADDR(isp->isp_port);
4376 		}
4377 	} else {
4378 		fcp->flash_data_addr = 0x7fe7c000;
4379 		fcp->flt_region_nvram = 0;
4380 		fcp->flt_region_nvram += ISP2400_NVRAM_PORT_ADDR(isp->isp_port);
4381 	}
4382 	return (isp_read_nvram_2400(isp));
4383 }
4384 
4385 static void
4386 isp_rd_2xxx_flash(ispsoftc_t *isp, uint32_t addr, uint32_t *rp)
4387 {
4388 	fcparam *fcp = FCPARAM(isp, 0);
4389 	int loops = 0;
4390 	uint32_t base = fcp->flash_data_addr;
4391 	uint32_t tmp = 0;
4392 
4393 	ISP_WRITE(isp, BIU2400_FLASH_ADDR, base + addr);
4394 	for (loops = 0; loops < 5000; loops++) {
4395 		ISP_DELAY(10);
4396 		tmp = ISP_READ(isp, BIU2400_FLASH_ADDR);
4397 		if ((tmp & (1U << 31)) != 0) {
4398 			break;
4399 		}
4400 	}
4401 	if (tmp & (1U << 31)) {
4402 		*rp = ISP_READ(isp, BIU2400_FLASH_DATA);
4403 		ISP_SWIZZLE_NVRAM_LONG(isp, rp);
4404 	} else {
4405 		*rp = 0xffffffff;
4406 	}
4407 }
4408 
4409 static int
4410 isp_read_flthdr_2xxx(ispsoftc_t *isp)
4411 {
4412 	fcparam *fcp = FCPARAM(isp, 0);
4413 	int retval = 0;
4414 	uint32_t addr, lwrds, *dptr;
4415 	uint16_t csum;
4416 	uint8_t flthdr_data[FLT_HEADER_SIZE];
4417 
4418 	addr = fcp->flt_region_flt;
4419 	dptr = (uint32_t *) flthdr_data;
4420 
4421 	isp_prt(isp, ISP_LOGDEBUG0,
4422 	    "FLTL[DEF]: 0x%x", addr);
4423 	for (lwrds = 0; lwrds < FLT_HEADER_SIZE >> 2; lwrds++) {
4424 		isp_rd_2xxx_flash(isp, addr++, dptr++);
4425 	}
4426 	dptr = (uint32_t *) flthdr_data;
4427 	for (csum = 0, lwrds = 0; lwrds < FLT_HEADER_SIZE >> 4; lwrds++) {
4428 		uint16_t tmp;
4429 		ISP_IOXGET_16(isp, &dptr[lwrds], tmp);
4430 		csum += tmp;
4431 	}
4432 	if (csum != 0) {
4433 		retval = -1;
4434 		goto out;
4435 	}
4436 	isp_parse_flthdr_2xxx(isp, flthdr_data);
4437 out:
4438 	return (retval);
4439 }
4440 
4441 static void
4442 isp_parse_flthdr_2xxx(ispsoftc_t *isp, uint8_t *flthdr_data)
4443 {
4444 	fcparam *fcp = FCPARAM(isp, 0);
4445 	uint16_t ver, csum;
4446 
4447 	ver = le16toh((uint16_t) (ISP2XXX_FLT_VERSION(flthdr_data)));
4448 	fcp->flt_length = le16toh((uint16_t) (ISP2XXX_FLT_LENGTH(flthdr_data)));
4449 	csum = le16toh((uint16_t) (ISP2XXX_FLT_CSUM(flthdr_data)));
4450 
4451 	if ((fcp->flt_length == 0) ||
4452 	    (fcp->flt_length > (FLT_HEADER_SIZE + FLT_REGIONS_SIZE))) {
4453 		isp_prt(isp, ISP_LOGERR,
4454 		    "FLT[DEF]: Invalid length=0x%x(%d)",
4455 		    fcp->flt_length, fcp->flt_length);
4456 	}
4457 	isp_prt(isp, ISP_LOGDEBUG0,
4458 	    "FLT[DEF]: version=0x%x length=0x%x(%d) checksum=0x%x",
4459 	    ver, fcp->flt_length, fcp->flt_length, csum);
4460 }
4461 
4462 static int
4463 isp_read_flt_2xxx(ispsoftc_t *isp)
4464 {
4465 	fcparam *fcp = FCPARAM(isp, 0);
4466 	int retval = 0;
4467 	int len = fcp->flt_length - FLT_HEADER_SIZE;
4468 	uint32_t addr, lwrds, *dptr;
4469 	uint8_t flt_data[len];
4470 	fcp->flt_region_entries = len / FLT_REGION_SIZE;
4471 
4472 	addr = fcp->flt_region_flt + (FLT_HEADER_SIZE >> 2);
4473 	dptr = (uint32_t *) flt_data;
4474 	isp_prt(isp, ISP_LOGDEBUG0, "FLT[DEF]: regions=%d",
4475 	    fcp->flt_region_entries);
4476 	for (lwrds = 0; lwrds < len >> 2; lwrds++) {
4477 		isp_rd_2xxx_flash(isp, addr++, dptr++);
4478 	}
4479 	retval = isp_parse_flt_2xxx(isp, flt_data);
4480 	return (retval);
4481 }
4482 
4483 static int
4484 isp_parse_flt_2xxx(ispsoftc_t *isp, uint8_t *flt_data)
4485 {
4486 	fcparam *fcp = FCPARAM(isp, 0);
4487 	int count;
4488 	struct flt_region region[fcp->flt_region_entries];
4489 
4490 	for (count = 0; count < fcp->flt_region_entries; count++) {
4491 		region[count].code =
4492 		    le16toh((uint16_t) (ISP2XXX_FLT_REG_CODE(flt_data, count)));
4493 		region[count].attribute =
4494 		    (uint8_t) (ISP2XXX_FLT_REG_ATTR(flt_data, count));
4495 		region[count].reserved =
4496 		    (uint8_t) (ISP2XXX_FLT_REG_RES(flt_data, count));
4497 		region[count].size =
4498 		    le32toh((uint32_t) (ISP2XXX_FLT_REG_SIZE(flt_data, count)) >> 2);
4499 		region[count].start =
4500 		    le32toh((uint32_t) (ISP2XXX_FLT_REG_START(flt_data, count)) >> 2);
4501 		region[count].end =
4502 		    le32toh((uint32_t) (ISP2XXX_FLT_REG_END(flt_data, count)) >> 2);
4503 
4504 		isp_prt(isp, ISP_LOGDEBUG0,
4505 		    "FLT[0x%x]: start=0x%x end=0x%x size=0x%x attribute=0x%x",
4506 		    region[count].code, region[count].start, region[count].end,
4507 		    region[count].size, region[count].attribute);
4508 
4509 		switch (region[count].code) {
4510 		case FLT_REG_FW:
4511 			fcp->flt_region_fw = region[count].start;
4512 			break;
4513 		case FLT_REG_BOOT_CODE:
4514 			fcp->flt_region_boot = region[count].start;
4515 			break;
4516 		case FLT_REG_VPD_0:
4517 			fcp->flt_region_vpd_nvram = region[count].start;
4518 			if (isp->isp_port == 0)
4519 				fcp->flt_region_vpd = region[count].start;
4520 			break;
4521 		case FLT_REG_VPD_1:
4522 			if (isp->isp_port == 1)
4523 				fcp->flt_region_vpd = region[count].start;
4524 			break;
4525 		case FLT_REG_VPD_2:
4526 			if (!IS_27XX(isp))
4527 				break;
4528 			if (isp->isp_port == 2)
4529 				fcp->flt_region_vpd = region[count].start;
4530 			break;
4531 		case FLT_REG_VPD_3:
4532 			if (!IS_27XX(isp))
4533 				break;
4534 			if (isp->isp_port == 3)
4535 				fcp->flt_region_vpd = region[count].start;
4536 			break;
4537 		case FLT_REG_NVRAM_0:
4538 			if (isp->isp_port == 0)
4539 				fcp->flt_region_nvram = region[count].start;
4540 			break;
4541 		case FLT_REG_NVRAM_1:
4542 			if (isp->isp_port == 1)
4543 				fcp->flt_region_nvram = region[count].start;
4544 			break;
4545 		case FLT_REG_NVRAM_2:
4546 			if (!IS_27XX(isp))
4547 				break;
4548 			if (isp->isp_port == 2)
4549 				fcp->flt_region_nvram = region[count].start;
4550 			break;
4551 		case FLT_REG_NVRAM_3:
4552 			if (!IS_27XX(isp))
4553 				break;
4554 			if (isp->isp_port == 3)
4555 				fcp->flt_region_nvram = region[count].start;
4556 			break;
4557 		case FLT_REG_FDT:
4558 			fcp->flt_region_fdt = region[count].start;
4559 			break;
4560 		case FLT_REG_FLT:
4561 			fcp->flt_region_flt = region[count].start;
4562 			break;
4563 		case FLT_REG_NPIV_CONF_0:
4564 			if (isp->isp_port == 0)
4565 				fcp->flt_region_npiv_conf = region[count].start;
4566 			break;
4567 		case FLT_REG_NPIV_CONF_1:
4568 			if (isp->isp_port == 1)
4569 				fcp->flt_region_npiv_conf = region[count].start;
4570 			break;
4571 		case FLT_REG_GOLD_FW:
4572 			fcp->flt_region_gold_fw = region[count].start;
4573 			break;
4574 		case FLT_REG_FCP_PRIO_0:
4575 			if (isp->isp_port == 0)
4576 				fcp->flt_region_fcp_prio = region[count].start;
4577 			break;
4578 		case FLT_REG_FCP_PRIO_1:
4579 			if (isp->isp_port == 1)
4580 				fcp->flt_region_fcp_prio = region[count].start;
4581 			break;
4582 		case FLT_REG_IMG_PRI_27XX:
4583 			if (IS_27XX(isp))
4584 				fcp->flt_region_img_status_pri = region[count].start;
4585 			break;
4586 		case FLT_REG_IMG_SEC_27XX:
4587 			if (IS_27XX(isp))
4588 				fcp->flt_region_img_status_sec = region[count].start;
4589 			break;
4590 		case FLT_REG_FW_SEC_27XX:
4591 			if (IS_27XX(isp))
4592 				fcp->flt_region_fw_sec = region[count].start;
4593 			break;
4594 		case FLT_REG_BOOTLOAD_SEC_27XX:
4595 			if (IS_27XX(isp))
4596 				fcp->flt_region_boot_sec = region[count].start;
4597 			break;
4598 		case FLT_REG_AUX_IMG_PRI_28XX:
4599 			if (IS_27XX(isp))
4600 				fcp->flt_region_aux_img_status_pri = region[count].start;
4601 			break;
4602 		case FLT_REG_AUX_IMG_SEC_28XX:
4603 			if (IS_27XX(isp))
4604 				fcp->flt_region_aux_img_status_sec = region[count].start;
4605 			break;
4606 		case FLT_REG_NVRAM_SEC_28XX_0:
4607 			if (IS_27XX(isp))
4608 				if (isp->isp_port == 0)
4609 					fcp->flt_region_nvram_sec = region[count].start;
4610 			break;
4611 		case FLT_REG_NVRAM_SEC_28XX_1:
4612 			if (IS_27XX(isp))
4613 				if (isp->isp_port == 1)
4614 					fcp->flt_region_nvram_sec = region[count].start;
4615 			break;
4616 		case FLT_REG_NVRAM_SEC_28XX_2:
4617 			if (IS_27XX(isp))
4618 				if (isp->isp_port == 2)
4619 					fcp->flt_region_nvram_sec = region[count].start;
4620 			break;
4621 		case FLT_REG_NVRAM_SEC_28XX_3:
4622 			if (IS_27XX(isp))
4623 				if (isp->isp_port == 3)
4624 					fcp->flt_region_nvram_sec = region[count].start;
4625 			break;
4626 		case FLT_REG_VPD_SEC_27XX_0:
4627 		case FLT_REG_VPD_SEC_28XX_0:
4628 			if (IS_27XX(isp)) {
4629 				fcp->flt_region_vpd_nvram_sec = region[count].start;
4630 				if (isp->isp_port == 0)
4631 					fcp->flt_region_vpd_sec = region[count].start;
4632 			}
4633 			break;
4634 		case FLT_REG_VPD_SEC_27XX_1:
4635 		case FLT_REG_VPD_SEC_28XX_1:
4636 			if (IS_27XX(isp))
4637 				if (isp->isp_port == 1)
4638 					fcp->flt_region_vpd_sec = region[count].start;
4639 			break;
4640 		case FLT_REG_VPD_SEC_27XX_2:
4641 		case FLT_REG_VPD_SEC_28XX_2:
4642 			if (IS_27XX(isp))
4643 				if (isp->isp_port == 2)
4644 					fcp->flt_region_vpd_sec = region[count].start;
4645 			break;
4646 		case FLT_REG_VPD_SEC_27XX_3:
4647 		case FLT_REG_VPD_SEC_28XX_3:
4648 			if (IS_27XX(isp))
4649 				if (isp->isp_port == 3)
4650 					fcp->flt_region_vpd_sec = region[count].start;
4651 			break;
4652 		}
4653 	}
4654 	isp_prt(isp, ISP_LOGDEBUG0,
4655 	    "FLT[FLT]: boot=0x%x fw=0x%x vpd_nvram=0x%x vpd=0x%x nvram 0x%x "
4656 	    "fdt=0x%x flt=0x%x npiv=0x%x fcp_prif_cfg=0x%x",
4657 	    fcp->flt_region_boot, fcp->flt_region_fw, fcp->flt_region_vpd_nvram,
4658 	    fcp->flt_region_vpd, fcp->flt_region_nvram, fcp->flt_region_fdt,
4659 	    fcp->flt_region_flt, fcp->flt_region_npiv_conf,
4660 	    fcp->flt_region_fcp_prio);
4661 
4662 	return (0);
4663 }
4664 
4665 static int
4666 isp_read_nvram_2400(ispsoftc_t *isp)
4667 {
4668 	fcparam *fcp = FCPARAM(isp, 0);
4669 	int retval = 0;
4670 	uint32_t addr, csum, lwrds, *dptr;
4671 	uint8_t nvram_data[ISP2400_NVRAM_SIZE];
4672 
4673 	addr = fcp->flt_region_nvram;
4674 	dptr = (uint32_t *) nvram_data;
4675 	for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
4676 		isp_rd_2xxx_flash(isp, addr++, dptr++);
4677 	}
4678 	if (nvram_data[0] != 'I' || nvram_data[1] != 'S' ||
4679 	    nvram_data[2] != 'P') {
4680 		isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header (%x %x %x)",
4681 		    nvram_data[0], nvram_data[1], nvram_data[2]);
4682 		retval = -1;
4683 		goto out;
4684 	}
4685 	dptr = (uint32_t *) nvram_data;
4686 	for (csum = 0, lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
4687 		uint32_t tmp;
4688 		ISP_IOXGET_32(isp, &dptr[lwrds], tmp);
4689 		csum += tmp;
4690 	}
4691 	if (csum != 0) {
4692 		isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum");
4693 		retval = -1;
4694 		goto out;
4695 	}
4696 	isp_parse_nvram_2400(isp, nvram_data);
4697 out:
4698 	return (retval);
4699 }
4700 
4701 static void
4702 isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
4703 {
4704 	fcparam *fcp = FCPARAM(isp, 0);
4705 	uint64_t wwn;
4706 
4707 	isp_prt(isp, ISP_LOGDEBUG0,
4708 	    "NVRAM 0x%08x%08x 0x%08x%08x maxframelen %d",
4709 	    (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data) >> 32),
4710 	    (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data)),
4711 	    (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data) >> 32),
4712 	    (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data)),
4713 	    ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data));
4714 	isp_prt(isp, ISP_LOGDEBUG0,
4715 	    "NVRAM loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x",
4716 	    ISP2400_NVRAM_HARDLOOPID(nvram_data),
4717 	    ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data),
4718 	    ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data),
4719 	    ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data));
4720 
4721 	wwn = ISP2400_NVRAM_PORT_NAME(nvram_data);
4722 	fcp->isp_wwpn_nvram = wwn;
4723 
4724 	wwn = ISP2400_NVRAM_NODE_NAME(nvram_data);
4725 	if (wwn) {
4726 		if ((wwn >> 60) != 2 && (wwn >> 60) != 5) {
4727 			wwn = 0;
4728 		}
4729 	}
4730 	if (wwn == 0 && (fcp->isp_wwpn_nvram >> 60) == 2) {
4731 		wwn = fcp->isp_wwpn_nvram;
4732 		wwn &= ~((uint64_t) 0xfff << 48);
4733 	}
4734 	fcp->isp_wwnn_nvram = wwn;
4735 
4736 	if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) {
4737 		DEFAULT_FRAMESIZE(isp) =
4738 		    ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data);
4739 	}
4740 	if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
4741 		fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data);
4742 	}
4743 	fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data);
4744 	fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data);
4745 	fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data);
4746 }
4747