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