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