xref: /freebsd/sys/dev/isp/isp.c (revision cc68614da8232d8baaca0ae0d0dd8f890f06623e)
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, totslen;
3068 #ifdef	ISP_TARGET_MODE
3069 	uint32_t sptr;
3070 #endif
3071 
3072 	/*
3073 	 * We can't be getting this now.
3074 	 */
3075 	if (isp->isp_state != ISP_RUNSTATE) {
3076 		isp_prt(isp, ISP_LOGINFO, "respq interrupt when not ready");
3077 		return;
3078 	}
3079 
3080 	iptr = ISP_READ(isp, BIU2400_RSPINP);
3081 	optr = isp->isp_resodx;
3082 	while (optr != iptr) {
3083 		cptr = optr;
3084 #ifdef	ISP_TARGET_MODE
3085 		sptr = optr;
3086 #endif
3087 		hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, cptr);
3088 		optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp));
3089 
3090 		/*
3091 		 * Synchronize our view of this response queue entry.
3092 		 */
3093 		MEMORYBARRIER(isp, SYNC_RESULT, cptr, QENTRY_LEN, -1);
3094 		if (isp->isp_dblev & ISP_LOGDEBUG1)
3095 			isp_print_qentry(isp, "Response Queue Entry", cptr, hp);
3096 		isp_get_hdr(isp, hp, &sp->req_header);
3097 
3098 		/*
3099 		 * Log IOCBs rejected by the firmware.  We can't really do
3100 		 * much more about them, since it just should not happen.
3101 		 */
3102 		if (sp->req_header.rqs_flags & RQSFLAG_BADTYPE) {
3103 			isp_print_qentry(isp, "invalid entry type", cptr, hp);
3104 			continue;
3105 		}
3106 		if (sp->req_header.rqs_flags & RQSFLAG_BADPARAM) {
3107 			isp_print_qentry(isp, "invalid entry parameter", cptr, hp);
3108 			continue;
3109 		}
3110 		if (sp->req_header.rqs_flags & RQSFLAG_BADCOUNT) {
3111 			isp_print_qentry(isp, "invalid entry count", cptr, hp);
3112 			continue;
3113 		}
3114 		if (sp->req_header.rqs_flags & RQSFLAG_BADORDER) {
3115 			isp_print_qentry(isp, "invalid entry order", cptr, hp);
3116 			continue;
3117 		}
3118 
3119 		etype = sp->req_header.rqs_entry_type;
3120 
3121 		/* We expected Status Continuation, but got different IOCB. */
3122 		if (cont > 0 && etype != RQSTYPE_STATUS_CONT) {
3123 			cont = 0;
3124 			isp_done(cont_xs);
3125 		}
3126 
3127 		if (isp_handle_control(isp, hp)) {
3128 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3129 			continue;
3130 		}
3131 
3132 		switch (etype) {
3133 		case RQSTYPE_RESPONSE:
3134 			isp_get_24xx_response(isp, (isp24xx_statusreq_t *)hp, sp);
3135 			break;
3136 		case RQSTYPE_MARKER:
3137 			isp_prt(isp, ISP_LOG_WARN1, "Marker Response");
3138 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3139 			continue;
3140 		case RQSTYPE_STATUS_CONT:
3141 			isp_get_cont_response(isp, (ispstatus_cont_t *)hp, scp);
3142 			if (cont > 0) {
3143 				slen = min(cont, sizeof(scp->req_sense_data));
3144 				XS_SENSE_APPEND(cont_xs, scp->req_sense_data, slen);
3145 				cont -= slen;
3146 				if (cont == 0) {
3147 					isp_done(cont_xs);
3148 				} else {
3149 					isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
3150 					    "Expecting Status Continuations for %u bytes",
3151 					    cont);
3152 				}
3153 			} else {
3154 				isp_prt(isp, ISP_LOG_WARN1, "Ignored Continuation Response");
3155 			}
3156 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3157 			continue;
3158 #ifdef	ISP_TARGET_MODE
3159 		case RQSTYPE_NOTIFY_ACK:	/* Can be set to ATIO queue. */
3160 		case RQSTYPE_CTIO7:
3161 		case RQSTYPE_ABTS_RCVD:		/* Can be set to ATIO queue. */
3162 		case RQSTYPE_ABTS_RSP:
3163 			isp_target_notify(isp, hp, &cptr, RESULT_QUEUE_LEN(isp));
3164 			/* More then one IOCB could be consumed. */
3165 			while (sptr != cptr) {
3166 				ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3167 				sptr = ISP_NXT_QENTRY(sptr, RESULT_QUEUE_LEN(isp));
3168 				hp = (isphdr_t *)ISP_QUEUE_ENTRY(isp->isp_result, sptr);
3169 			}
3170 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3171 			optr = ISP_NXT_QENTRY(cptr, RESULT_QUEUE_LEN(isp));
3172 			continue;
3173 #endif
3174 		case RQSTYPE_RPT_ID_ACQ:	/* Can be set to ATIO queue.*/
3175 			isp_handle_rpt_id_acq(isp, hp);
3176 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3177 			continue;
3178 		default:
3179 			/* We don't know what was this -- log and skip. */
3180 			isp_prt(isp, ISP_LOGERR, notresp, etype, cptr, optr);
3181 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3182 			continue;
3183 		}
3184 
3185 		xs = isp_find_xs(isp, sp->req_handle);
3186 		if (xs == NULL) {
3187 			/*
3188 			 * Only whine if this isn't the expected fallout of
3189 			 * aborting the command or resetting the target.
3190 			 */
3191 			if (sp->req_completion_status != RQCS_ABORTED &&
3192 			    sp->req_completion_status != RQCS_RESET_OCCURRED)
3193 				isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)",
3194 				    sp->req_handle, sp->req_completion_status);
3195 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3196 			continue;
3197 		}
3198 
3199 		resp = snsp = sp->req_rsp_sense;
3200 		rlen = slen = totslen = 0;
3201 		scsi_status = sp->req_scsi_status;
3202 		if (scsi_status & RQCS_RV) {
3203 			rlen = sp->req_response_len;
3204 			snsp += rlen;
3205 		}
3206 		if (scsi_status & RQCS_SV) {
3207 			totslen = sp->req_sense_len;
3208 			slen = MIN(totslen, sizeof(sp->req_rsp_sense) - rlen);
3209 		}
3210 		*XS_STSP(xs) = scsi_status & 0xff;
3211 		if (scsi_status & RQCS_RESID)
3212 			XS_SET_RESID(xs, sp->req_fcp_residual);
3213 		else
3214 			XS_SET_RESID(xs, 0);
3215 
3216 		if (rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) {
3217 			const char *ptr;
3218 			char lb[64];
3219 			const char *rnames[10] = {
3220 			    "Task Management function complete",
3221 			    "FCP_DATA length different than FCP_BURST_LEN",
3222 			    "FCP_CMND fields invalid",
3223 			    "FCP_DATA parameter mismatch with FCP_DATA_RO",
3224 			    "Task Management function rejected",
3225 			    "Task Management function failed",
3226 			    NULL,
3227 			    NULL,
3228 			    "Task Management function succeeded",
3229 			    "Task Management function incorrect logical unit number",
3230 			};
3231 			uint8_t code = resp[FCP_RSPNS_CODE_OFFSET];
3232 			if (code >= nitems(rnames) || rnames[code] == NULL) {
3233 				ISP_SNPRINTF(lb, sizeof(lb),
3234 				    "Unknown FCP Response Code 0x%x", code);
3235 				ptr = lb;
3236 			} else {
3237 				ptr = rnames[code];
3238 			}
3239 			isp_xs_prt(isp, xs, ISP_LOGWARN,
3240 			    "FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x",
3241 			    rlen, ptr, XS_CDBP(xs)[0] & 0xff);
3242 			if (code != FCP_RSPNS_TMF_DONE &&
3243 			    code != FCP_RSPNS_TMF_SUCCEEDED)
3244 				XS_SETERR(xs, HBA_BOTCH);
3245 		}
3246 		isp_parse_status_24xx(isp, sp, xs);
3247 		if (slen > 0) {
3248 			XS_SAVE_SENSE(xs, snsp, slen);
3249 			if (totslen > slen) {
3250 				cont = totslen - slen;
3251 				cont_xs = xs;
3252 				isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
3253 				    "Expecting Status Continuations for %u bytes",
3254 				    cont);
3255 			}
3256 		}
3257 
3258 		ISP_DMAFREE(isp, xs);
3259 		isp_destroy_handle(isp, sp->req_handle);
3260 		ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
3261 
3262 		/* Complete command if we expect no Status Continuations. */
3263 		if (cont == 0)
3264 			isp_done(xs);
3265 	}
3266 
3267 	/* We haven't received all Status Continuations, but that is it. */
3268 	if (cont > 0)
3269 		isp_done(cont_xs);
3270 
3271 	/* If we processed any IOCBs, let ISP know about it. */
3272 	if (optr != isp->isp_resodx) {
3273 		ISP_WRITE(isp, BIU2400_RSPOUTP, optr);
3274 		isp->isp_resodx = optr;
3275 	}
3276 }
3277 
3278 
3279 void
3280 isp_intr_async(ispsoftc_t *isp, uint16_t mbox)
3281 {
3282 	fcparam *fcp;
3283 	uint16_t chan;
3284 
3285 	isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox);
3286 
3287 	switch (mbox) {
3288 	case ASYNC_SYSTEM_ERROR:
3289 		isp->isp_state = ISP_CRASHED;
3290 		for (chan = 0; chan < isp->isp_nchan; chan++) {
3291 			FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
3292 			isp_change_fw_state(isp, chan, FW_CONFIG_WAIT);
3293 		}
3294 		/*
3295 		 * Were we waiting for a mailbox command to complete?
3296 		 * If so, it's dead, so wake up the waiter.
3297 		 */
3298 		if (isp->isp_mboxbsy) {
3299 			isp->isp_obits = 1;
3300 			isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR;
3301 			isp->isp_mboxbsy = 0;
3302 		}
3303 		/*
3304 		 * It's up to the handler for isp_async to reinit stuff and
3305 		 * restart the firmware
3306 		 */
3307 		isp_async(isp, ISPASYNC_FW_CRASH);
3308 		break;
3309 
3310 	case ASYNC_RQS_XFER_ERR:
3311 		isp_prt(isp, ISP_LOGERR, "Request Queue Transfer Error");
3312 		break;
3313 
3314 	case ASYNC_RSP_XFER_ERR:
3315 		isp_prt(isp, ISP_LOGERR, "Response Queue Transfer Error");
3316 		break;
3317 
3318 	case ASYNC_ATIO_XFER_ERR:
3319 		isp_prt(isp, ISP_LOGERR, "ATIO Queue Transfer Error");
3320 		break;
3321 
3322 	case ASYNC_LIP_OCCURRED:
3323 	case ASYNC_LIP_NOS_OLS_RECV:
3324 	case ASYNC_LIP_ERROR:
3325 	case ASYNC_PTPMODE:
3326 		/*
3327 		 * These are broadcast events that have to be sent across
3328 		 * all active channels.
3329 		 */
3330 		for (chan = 0; chan < isp->isp_nchan; chan++) {
3331 			fcp = FCPARAM(isp, chan);
3332 			int topo = fcp->isp_topo;
3333 
3334 			if (fcp->role == ISP_ROLE_NONE)
3335 				continue;
3336 			if (fcp->isp_loopstate > LOOP_HAVE_LINK)
3337 				fcp->isp_loopstate = LOOP_HAVE_LINK;
3338 			ISP_SET_SENDMARKER(isp, chan, 1);
3339 			isp_async(isp, ISPASYNC_LIP, chan);
3340 #ifdef	ISP_TARGET_MODE
3341 			isp_target_async(isp, chan, mbox);
3342 #endif
3343 			/*
3344 			 * We've had problems with data corruption occurring on
3345 			 * commands that complete (with no apparent error) after
3346 			 * we receive a LIP. This has been observed mostly on
3347 			 * Local Loop topologies. To be safe, let's just mark
3348 			 * all active initiator commands as dead.
3349 			 */
3350 			if (topo == TOPO_NL_PORT || topo == TOPO_FL_PORT) {
3351 				int i, j;
3352 				for (i = j = 0; i < ISP_HANDLE_NUM(isp); i++) {
3353 					XS_T *xs;
3354 					isp_hdl_t *hdp;
3355 
3356 					hdp = &isp->isp_xflist[i];
3357 					if (ISP_H2HT(hdp->handle) != ISP_HANDLE_INITIATOR) {
3358 						continue;
3359 					}
3360 					xs = hdp->cmd;
3361 					if (XS_CHANNEL(xs) != chan) {
3362 						continue;
3363 					}
3364 					j++;
3365 					isp_prt(isp, ISP_LOG_WARN1,
3366 					    "%d.%d.%jx bus reset set at %s:%u",
3367 					    XS_CHANNEL(xs), XS_TGT(xs),
3368 					    (uintmax_t)XS_LUN(xs),
3369 					    __func__, __LINE__);
3370 					XS_SETERR(xs, HBA_BUSRESET);
3371 				}
3372 				if (j) {
3373 					isp_prt(isp, ISP_LOGERR, lipd, chan, j);
3374 				}
3375 			}
3376 		}
3377 		break;
3378 
3379 	case ASYNC_LOOP_UP:
3380 		/*
3381 		 * This is a broadcast event that has to be sent across
3382 		 * all active channels.
3383 		 */
3384 		for (chan = 0; chan < isp->isp_nchan; chan++) {
3385 			fcp = FCPARAM(isp, chan);
3386 			if (fcp->role == ISP_ROLE_NONE)
3387 				continue;
3388 			fcp->isp_linkstate = 1;
3389 			if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3390 				fcp->isp_loopstate = LOOP_HAVE_LINK;
3391 			ISP_SET_SENDMARKER(isp, chan, 1);
3392 			isp_async(isp, ISPASYNC_LOOP_UP, chan);
3393 #ifdef	ISP_TARGET_MODE
3394 			isp_target_async(isp, chan, mbox);
3395 #endif
3396 		}
3397 		break;
3398 
3399 	case ASYNC_LOOP_DOWN:
3400 		/*
3401 		 * This is a broadcast event that has to be sent across
3402 		 * all active channels.
3403 		 */
3404 		for (chan = 0; chan < isp->isp_nchan; chan++) {
3405 			fcp = FCPARAM(isp, chan);
3406 			if (fcp->role == ISP_ROLE_NONE)
3407 				continue;
3408 			ISP_SET_SENDMARKER(isp, chan, 1);
3409 			fcp->isp_linkstate = 0;
3410 			fcp->isp_loopstate = LOOP_NIL;
3411 			isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
3412 #ifdef	ISP_TARGET_MODE
3413 			isp_target_async(isp, chan, mbox);
3414 #endif
3415 		}
3416 		break;
3417 
3418 	case ASYNC_LOOP_RESET:
3419 		/*
3420 		 * This is a broadcast event that has to be sent across
3421 		 * all active channels.
3422 		 */
3423 		for (chan = 0; chan < isp->isp_nchan; chan++) {
3424 			fcp = FCPARAM(isp, chan);
3425 			if (fcp->role == ISP_ROLE_NONE)
3426 				continue;
3427 			ISP_SET_SENDMARKER(isp, chan, 1);
3428 			if (fcp->isp_loopstate > LOOP_HAVE_LINK)
3429 				fcp->isp_loopstate = LOOP_HAVE_LINK;
3430 			isp_async(isp, ISPASYNC_LOOP_RESET, chan);
3431 #ifdef	ISP_TARGET_MODE
3432 			isp_target_async(isp, chan, mbox);
3433 #endif
3434 		}
3435 		break;
3436 
3437 	case ASYNC_PDB_CHANGED:
3438 	{
3439 		int echan, nphdl, nlstate, reason;
3440 
3441 		nphdl = ISP_READ(isp, OUTMAILBOX1);
3442 		nlstate = ISP_READ(isp, OUTMAILBOX2);
3443 		reason = ISP_READ(isp, OUTMAILBOX3) >> 8;
3444 		if (ISP_CAP_MULTI_ID(isp)) {
3445 			chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
3446 			if (chan == 0xff || nphdl == NIL_HANDLE) {
3447 				chan = 0;
3448 				echan = isp->isp_nchan - 1;
3449 			} else if (chan >= isp->isp_nchan) {
3450 				break;
3451 			} else {
3452 				echan = chan;
3453 			}
3454 		} else {
3455 			chan = echan = 0;
3456 		}
3457 		for (; chan <= echan; chan++) {
3458 			fcp = FCPARAM(isp, chan);
3459 			if (fcp->role == ISP_ROLE_NONE)
3460 				continue;
3461 			if (fcp->isp_loopstate > LOOP_LTEST_DONE) {
3462 				if (nphdl != NIL_HANDLE &&
3463 				    nphdl == fcp->isp_login_hdl &&
3464 				    reason == PDB24XX_AE_OPN_2)
3465 					continue;
3466 				fcp->isp_loopstate = LOOP_LTEST_DONE;
3467 			} else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3468 				fcp->isp_loopstate = LOOP_HAVE_LINK;
3469 			isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
3470 			    ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
3471 		}
3472 		break;
3473 	}
3474 	case ASYNC_CHANGE_NOTIFY:
3475 	{
3476 		int portid;
3477 
3478 		portid = ((ISP_READ(isp, OUTMAILBOX1) & 0xff) << 16) |
3479 		    ISP_READ(isp, OUTMAILBOX2);
3480 		if (ISP_CAP_MULTI_ID(isp)) {
3481 			chan = ISP_READ(isp, OUTMAILBOX3) & 0xff;
3482 			if (chan >= isp->isp_nchan)
3483 				break;
3484 		} else {
3485 			chan = 0;
3486 		}
3487 		fcp = FCPARAM(isp, chan);
3488 		if (fcp->role == ISP_ROLE_NONE)
3489 			break;
3490 		if (fcp->isp_loopstate > LOOP_LTEST_DONE)
3491 			fcp->isp_loopstate = LOOP_LTEST_DONE;
3492 		else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
3493 			fcp->isp_loopstate = LOOP_HAVE_LINK;
3494 		isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
3495 		    ISPASYNC_CHANGE_SNS, portid);
3496 		break;
3497 	}
3498 	case ASYNC_ERR_LOGGING_DISABLED:
3499 		isp_prt(isp, ISP_LOGWARN, "Error logging disabled (reason 0x%x)",
3500 		    ISP_READ(isp, OUTMAILBOX1));
3501 		break;
3502 	case ASYNC_P2P_INIT_ERR:
3503 		isp_prt(isp, ISP_LOGWARN, "P2P init error (reason 0x%x)",
3504 		    ISP_READ(isp, OUTMAILBOX1));
3505 		break;
3506 	case ASYNC_RCV_ERR:
3507 		isp_prt(isp, ISP_LOGWARN, "Receive Error");
3508 		break;
3509 	case ASYNC_RJT_SENT:	/* same as ASYNC_QFULL_SENT */
3510 		isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent");
3511 		break;
3512 	case ASYNC_FW_RESTART_COMPLETE:
3513 		isp_prt(isp, ISP_LOGDEBUG0, "FW restart complete");
3514 		break;
3515 	case ASYNC_TEMPERATURE_ALERT:
3516 		isp_prt(isp, ISP_LOGERR, "Temperature alert (subcode 0x%x)",
3517 		    ISP_READ(isp, OUTMAILBOX1));
3518 		break;
3519 	case ASYNC_INTER_DRIVER_COMP:
3520 		isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication complete");
3521 		break;
3522 	case ASYNC_INTER_DRIVER_NOTIFY:
3523 		isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication notification");
3524 		break;
3525 	case ASYNC_INTER_DRIVER_TIME_EXT:
3526 		isp_prt(isp, ISP_LOGDEBUG0, "Inter-driver communication time extended");
3527 		break;
3528 	case ASYNC_TRANSCEIVER_INSERTION:
3529 		isp_prt(isp, ISP_LOGDEBUG0, "Transceiver insertion (0x%x)",
3530 		    ISP_READ(isp, OUTMAILBOX1));
3531 		break;
3532 	case ASYNC_TRANSCEIVER_REMOVAL:
3533 		isp_prt(isp, ISP_LOGDEBUG0, "Transceiver removal");
3534 		break;
3535 	case ASYNC_NIC_FW_STATE_CHANGE:
3536 		isp_prt(isp, ISP_LOGDEBUG0, "NIC Firmware State Change");
3537 		break;
3538 	case ASYNC_AUTOLOAD_FW_COMPLETE:
3539 		isp_prt(isp, ISP_LOGDEBUG0, "Autoload FW init complete");
3540 		break;
3541 	case ASYNC_AUTOLOAD_FW_FAILURE:
3542 		isp_prt(isp, ISP_LOGERR, "Autoload FW init failure");
3543 		break;
3544 	default:
3545 		isp_prt(isp, ISP_LOGWARN, "Unknown Async Code 0x%x", mbox);
3546 		break;
3547 	}
3548 }
3549 
3550 /*
3551  * Handle completions with control handles by waking up waiting threads.
3552  */
3553 static int
3554 isp_handle_control(ispsoftc_t *isp, isphdr_t *hp)
3555 {
3556 	uint32_t hdl;
3557 	void *ptr;
3558 
3559 	switch (hp->rqs_entry_type) {
3560 	case RQSTYPE_RESPONSE:
3561 	case RQSTYPE_MARKER:
3562 	case RQSTYPE_NOTIFY_ACK:
3563 	case RQSTYPE_CTIO7:
3564 	case RQSTYPE_TSK_MGMT:
3565 	case RQSTYPE_CT_PASSTHRU:
3566 	case RQSTYPE_VP_MODIFY:
3567 	case RQSTYPE_VP_CTRL:
3568 	case RQSTYPE_ABORT_IO:
3569 	case RQSTYPE_MBOX:
3570 	case RQSTYPE_LOGIN:
3571 	case RQSTYPE_ELS_PASSTHRU:
3572 		ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl);
3573 		if (ISP_H2HT(hdl) != ISP_HANDLE_CTRL)
3574 			break;
3575 		ptr = isp_find_xs(isp, hdl);
3576 		if (ptr != NULL) {
3577 			isp_destroy_handle(isp, hdl);
3578 			memcpy(ptr, hp, QENTRY_LEN);
3579 			wakeup(ptr);
3580 		}
3581 		return (1);
3582 	}
3583 	return (0);
3584 }
3585 
3586 static void
3587 isp_handle_rpt_id_acq(ispsoftc_t *isp, isphdr_t *hp)
3588 {
3589 	fcparam *fcp;
3590 	isp_ridacq_t rid;
3591 	int chan, c;
3592 	uint32_t portid;
3593 
3594 	isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid);
3595 	portid = (uint32_t)rid.ridacq_vp_port_hi << 16 |
3596 	    rid.ridacq_vp_port_lo;
3597 	if (rid.ridacq_format == 0) {
3598 		for (chan = 0; chan < isp->isp_nchan; chan++) {
3599 			fcp = FCPARAM(isp, chan);
3600 			if (fcp->role == ISP_ROLE_NONE)
3601 				continue;
3602 			c = (chan == 0) ? 127 : (chan - 1);
3603 			if (rid.ridacq_map[c / 16] & (1 << (c % 16)) ||
3604 			    chan == 0) {
3605 				fcp->isp_loopstate = LOOP_HAVE_LINK;
3606 				isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
3607 				    chan, ISPASYNC_CHANGE_OTHER);
3608 			} else {
3609 				fcp->isp_loopstate = LOOP_NIL;
3610 				isp_async(isp, ISPASYNC_LOOP_DOWN,
3611 				    chan);
3612 			}
3613 		}
3614 	} else {
3615 		fcp = FCPARAM(isp, rid.ridacq_vp_index);
3616 		if (rid.ridacq_vp_status == RIDACQ_STS_COMPLETE ||
3617 		    rid.ridacq_vp_status == RIDACQ_STS_CHANGED) {
3618 			fcp->isp_topo = (rid.ridacq_map[0] >> 9) & 0x7;
3619 			fcp->isp_portid = portid;
3620 			fcp->isp_loopstate = LOOP_HAVE_ADDR;
3621 			isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
3622 			    rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER);
3623 		} else {
3624 			fcp->isp_loopstate = LOOP_NIL;
3625 			isp_async(isp, ISPASYNC_LOOP_DOWN,
3626 			    rid.ridacq_vp_index);
3627 		}
3628 	}
3629 }
3630 
3631 static void
3632 isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, XS_T *xs)
3633 {
3634 	int ru_marked, sv_marked;
3635 	int chan = XS_CHANNEL(xs);
3636 
3637 	switch (sp->req_completion_status) {
3638 	case RQCS_COMPLETE:
3639 		return;
3640 
3641 	case RQCS_DMA_ERROR:
3642 		isp_xs_prt(isp, xs, ISP_LOGERR, "DMA error");
3643 		if (XS_NOERR(xs))
3644 			XS_SETERR(xs, HBA_BOTCH);
3645 		break;
3646 
3647 	case RQCS_TRANSPORT_ERROR:
3648 		isp_xs_prt(isp, xs,  ISP_LOGERR, "Transport Error");
3649 		if (XS_NOERR(xs))
3650 			XS_SETERR(xs, HBA_BOTCH);
3651 		break;
3652 
3653 	case RQCS_RESET_OCCURRED:
3654 		isp_xs_prt(isp, xs, ISP_LOGWARN, "reset destroyed command");
3655 		FCPARAM(isp, chan)->sendmarker = 1;
3656 		if (XS_NOERR(xs))
3657 			XS_SETERR(xs, HBA_BUSRESET);
3658 		return;
3659 
3660 	case RQCS_ABORTED:
3661 		isp_xs_prt(isp, xs, ISP_LOGERR, "Command Aborted");
3662 		FCPARAM(isp, chan)->sendmarker = 1;
3663 		if (XS_NOERR(xs))
3664 			XS_SETERR(xs, HBA_ABORTED);
3665 		return;
3666 
3667 	case RQCS_TIMEOUT:
3668 		isp_xs_prt(isp, xs, ISP_LOGWARN, "Command Timed Out");
3669 		if (XS_NOERR(xs))
3670 			XS_SETERR(xs, HBA_CMDTIMEOUT);
3671 		return;
3672 
3673 	case RQCS_DATA_OVERRUN:
3674 		XS_SET_RESID(xs, sp->req_resid);
3675 		isp_xs_prt(isp, xs, ISP_LOGERR, "Data Overrun");
3676 		if (XS_NOERR(xs))
3677 			XS_SETERR(xs, HBA_DATAOVR);
3678 		return;
3679 
3680 	case RQCS_DRE:		/* data reassembly error */
3681 		isp_prt(isp, ISP_LOGERR, "Chan %d data reassembly error for target %d", chan, XS_TGT(xs));
3682 		if (XS_NOERR(xs))
3683 			XS_SETERR(xs, HBA_BOTCH);
3684 		return;
3685 
3686 	case RQCS_TABORT:	/* aborted by target */
3687 		isp_prt(isp, ISP_LOGERR, "Chan %d target %d sent ABTS", chan, XS_TGT(xs));
3688 		if (XS_NOERR(xs))
3689 			XS_SETERR(xs, HBA_ABORTED);
3690 		return;
3691 
3692 	case RQCS_DATA_UNDERRUN:
3693 		ru_marked = (sp->req_scsi_status & RQCS_RU) != 0;
3694 		/*
3695 		 * We can get an underrun w/o things being marked
3696 		 * if we got a non-zero status.
3697 		 */
3698 		sv_marked = (sp->req_scsi_status & (RQCS_SV|RQCS_RV)) != 0;
3699 		if ((ru_marked == 0 && sv_marked == 0) ||
3700 		    (sp->req_resid > XS_XFRLEN(xs))) {
3701 			isp_xs_prt(isp, xs, ISP_LOGWARN, bun, XS_XFRLEN(xs), sp->req_resid, (ru_marked)? "marked" : "not marked");
3702 			if (XS_NOERR(xs))
3703 				XS_SETERR(xs, HBA_BOTCH);
3704 			return;
3705 		}
3706 		XS_SET_RESID(xs, sp->req_resid);
3707 		isp_xs_prt(isp, xs, ISP_LOG_WARN1, "Data Underrun (%d) for command 0x%x", sp->req_resid, XS_CDBP(xs)[0] & 0xff);
3708 		return;
3709 
3710 	case RQCS_PORT_UNAVAILABLE:
3711 		/*
3712 		 * No such port on the loop. Moral equivalent of SELTIMEO
3713 		 */
3714 	case RQCS_PORT_LOGGED_OUT:
3715 	{
3716 		const char *reason;
3717 		uint8_t sts = sp->req_completion_status & 0xff;
3718 		fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs));
3719 		fcportdb_t *lp;
3720 
3721 		/*
3722 		 * It was there (maybe)- treat as a selection timeout.
3723 		 */
3724 		if (sts == RQCS_PORT_UNAVAILABLE) {
3725 			reason = "unavailable";
3726 		} else {
3727 			reason = "logout";
3728 		}
3729 
3730 		isp_prt(isp, ISP_LOGINFO, "Chan %d port %s for target %d",
3731 		    chan, reason, XS_TGT(xs));
3732 
3733 		/* XXX: Should we trigger rescan or FW announce change? */
3734 
3735 		if (XS_NOERR(xs)) {
3736 			lp = &fcp->portdb[XS_TGT(xs)];
3737 			if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
3738 				*XS_STSP(xs) = SCSI_BUSY;
3739 				XS_SETERR(xs, HBA_TGTBSY);
3740 			} else
3741 				XS_SETERR(xs, HBA_SELTIMEOUT);
3742 		}
3743 		return;
3744 	}
3745 	case RQCS_PORT_CHANGED:
3746 		isp_prt(isp, ISP_LOGWARN, "port changed for target %d chan %d", XS_TGT(xs), chan);
3747 		if (XS_NOERR(xs)) {
3748 			*XS_STSP(xs) = SCSI_BUSY;
3749 			XS_SETERR(xs, HBA_TGTBSY);
3750 		}
3751 		return;
3752 
3753 	case RQCS_ENOMEM:	/* f/w resource unavailable */
3754 		isp_prt(isp, ISP_LOGWARN, "f/w resource unavailable for target %d chan %d", XS_TGT(xs), chan);
3755 		if (XS_NOERR(xs)) {
3756 			*XS_STSP(xs) = SCSI_BUSY;
3757 			XS_SETERR(xs, HBA_TGTBSY);
3758 		}
3759 		return;
3760 
3761 	case RQCS_TMO:		/* task management overrun */
3762 		isp_prt(isp, ISP_LOGWARN, "command for target %d overlapped task management for chan %d", XS_TGT(xs), chan);
3763 		if (XS_NOERR(xs)) {
3764 			*XS_STSP(xs) = SCSI_BUSY;
3765 			XS_SETERR(xs, HBA_TGTBSY);
3766 		}
3767 		return;
3768 
3769 	default:
3770 		isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x on chan %d", sp->req_completion_status, chan);
3771 		break;
3772 	}
3773 	if (XS_NOERR(xs))
3774 		XS_SETERR(xs, HBA_BOTCH);
3775 }
3776 
3777 #define	ISP_FC_IBITS(op)	((mbpfc[((op)<<3) + 0] << 24) | (mbpfc[((op)<<3) + 1] << 16) | (mbpfc[((op)<<3) + 2] << 8) | (mbpfc[((op)<<3) + 3]))
3778 #define	ISP_FC_OBITS(op)	((mbpfc[((op)<<3) + 4] << 24) | (mbpfc[((op)<<3) + 5] << 16) | (mbpfc[((op)<<3) + 6] << 8) | (mbpfc[((op)<<3) + 7]))
3779 
3780 #define	ISP_FC_OPMAP(in0, out0)							  0,   0,   0, in0,    0,    0,    0, out0
3781 #define	ISP_FC_OPMAP_HALF(in1, in0, out1, out0)					  0,   0, in1, in0,    0,    0, out1, out0
3782 #define	ISP_FC_OPMAP_FULL(in3, in2, in1, in0, out3, out2, out1, out0)		in3, in2, in1, in0, out3, out2, out1, out0
3783 static const uint32_t mbpfc[] = {
3784 	ISP_FC_OPMAP(0x01, 0x01),	/* 0x00: MBOX_NO_OP */
3785 	ISP_FC_OPMAP(0x1f, 0x01),	/* 0x01: MBOX_LOAD_RAM */
3786 	ISP_FC_OPMAP_HALF(0x07, 0xff, 0x00, 0x1f),	/* 0x02: MBOX_EXEC_FIRMWARE */
3787 	ISP_FC_OPMAP(0xdf, 0x01),	/* 0x03: MBOX_DUMP_RAM */
3788 	ISP_FC_OPMAP(0x07, 0x07),	/* 0x04: MBOX_WRITE_RAM_WORD */
3789 	ISP_FC_OPMAP(0x03, 0x07),	/* 0x05: MBOX_READ_RAM_WORD */
3790 	ISP_FC_OPMAP_FULL(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff),	/* 0x06: MBOX_MAILBOX_REG_TEST */
3791 	ISP_FC_OPMAP(0x07, 0x07),	/* 0x07: MBOX_VERIFY_CHECKSUM	*/
3792 	ISP_FC_OPMAP_FULL(0x0, 0x0, 0x0, 0x01, 0x0, 0x3, 0x80, 0x7f),	/* 0x08: MBOX_ABOUT_FIRMWARE */
3793 	ISP_FC_OPMAP(0xdf, 0x01),	/* 0x09: MBOX_LOAD_RISC_RAM_2100 */
3794 	ISP_FC_OPMAP(0xdf, 0x01),	/* 0x0a: DUMP RAM */
3795 	ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x01),	/* 0x0b: MBOX_LOAD_RISC_RAM */
3796 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x0c: */
3797 	ISP_FC_OPMAP_HALF(0x1, 0x0f, 0x0, 0x01),	/* 0x0d: MBOX_WRITE_RAM_WORD_EXTENDED */
3798 	ISP_FC_OPMAP(0x01, 0x05),	/* 0x0e: MBOX_CHECK_FIRMWARE */
3799 	ISP_FC_OPMAP_HALF(0x1, 0x03, 0x0, 0x0d),	/* 0x0f: MBOX_READ_RAM_WORD_EXTENDED */
3800 	ISP_FC_OPMAP(0x1f, 0x11),	/* 0x10: MBOX_INIT_REQ_QUEUE */
3801 	ISP_FC_OPMAP(0x2f, 0x21),	/* 0x11: MBOX_INIT_RES_QUEUE */
3802 	ISP_FC_OPMAP(0x0f, 0x01),	/* 0x12: MBOX_EXECUTE_IOCB */
3803 	ISP_FC_OPMAP(0x03, 0x03),	/* 0x13: MBOX_WAKE_UP	*/
3804 	ISP_FC_OPMAP_HALF(0x1, 0xff, 0x0, 0x03),	/* 0x14: MBOX_STOP_FIRMWARE */
3805 	ISP_FC_OPMAP(0x4f, 0x01),	/* 0x15: MBOX_ABORT */
3806 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x16: MBOX_ABORT_DEVICE */
3807 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x17: MBOX_ABORT_TARGET */
3808 	ISP_FC_OPMAP(0x03, 0x03),	/* 0x18: MBOX_BUS_RESET */
3809 	ISP_FC_OPMAP(0x07, 0x05),	/* 0x19: MBOX_STOP_QUEUE */
3810 	ISP_FC_OPMAP(0x07, 0x05),	/* 0x1a: MBOX_START_QUEUE */
3811 	ISP_FC_OPMAP(0x07, 0x05),	/* 0x1b: MBOX_SINGLE_STEP_QUEUE */
3812 	ISP_FC_OPMAP(0x07, 0x05),	/* 0x1c: MBOX_ABORT_QUEUE */
3813 	ISP_FC_OPMAP(0x07, 0x03),	/* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */
3814 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x1e: */
3815 	ISP_FC_OPMAP(0x01, 0x07),	/* 0x1f: MBOX_GET_FIRMWARE_STATUS */
3816 	ISP_FC_OPMAP_HALF(0x2, 0x01, 0x7e, 0xcf),	/* 0x20: MBOX_GET_LOOP_ID */
3817 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x21: */
3818 	ISP_FC_OPMAP(0x03, 0x4b),	/* 0x22: MBOX_GET_TIMEOUT_PARAMS */
3819 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x23: */
3820 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x24: */
3821 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x25: */
3822 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x26: */
3823 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x27: */
3824 	ISP_FC_OPMAP(0x01, 0x03),	/* 0x28: MBOX_GET_FIRMWARE_OPTIONS */
3825 	ISP_FC_OPMAP(0x03, 0x07),	/* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */
3826 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x2a: */
3827 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x2b: */
3828 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x2c: */
3829 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x2d: */
3830 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x2e: */
3831 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x2f: */
3832 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x30: */
3833 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x31: */
3834 	ISP_FC_OPMAP(0x4b, 0x4b),	/* 0x32: MBOX_SET_TIMEOUT_PARAMS */
3835 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x33: */
3836 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x34: */
3837 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x35: */
3838 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x36: */
3839 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x37: */
3840 	ISP_FC_OPMAP(0x0f, 0x01),	/* 0x38: MBOX_SET_FIRMWARE_OPTIONS */
3841 	ISP_FC_OPMAP(0x0f, 0x07),	/* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */
3842 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x3a: */
3843 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x3b: */
3844 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x3c: */
3845 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x3d: */
3846 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x3e: */
3847 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x3f: */
3848 	ISP_FC_OPMAP(0x03, 0x01),	/* 0x40: MBOX_LOOP_PORT_BYPASS */
3849 	ISP_FC_OPMAP(0x03, 0x01),	/* 0x41: MBOX_LOOP_PORT_ENABLE */
3850 	ISP_FC_OPMAP_HALF(0x0, 0x01, 0x1f, 0xcf),	/* 0x42: MBOX_GET_RESOURCE_COUNT */
3851 	ISP_FC_OPMAP(0x01, 0x01),	/* 0x43: MBOX_REQUEST_OFFLINE_MODE */
3852 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x44: */
3853 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x45: */
3854 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x46: */
3855 	ISP_FC_OPMAP(0xcf, 0x03),	/* 0x47: GET PORT_DATABASE ENHANCED */
3856 	ISP_FC_OPMAP(0xcf, 0x0f),	/* 0x48: MBOX_INIT_FIRMWARE_MULTI_ID */
3857 	ISP_FC_OPMAP(0xcd, 0x01),	/* 0x49: MBOX_GET_VP_DATABASE */
3858 	ISP_FC_OPMAP_HALF(0x2, 0xcd, 0x0, 0x01),	/* 0x4a: MBOX_GET_VP_DATABASE_ENTRY */
3859 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x4b: */
3860 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x4c: */
3861 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x4d: */
3862 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x4e: */
3863 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x4f: */
3864 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x50: */
3865 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x51: */
3866 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x52: */
3867 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x53: */
3868 	ISP_FC_OPMAP(0xcf, 0x01),	/* 0x54: EXECUTE IOCB A64 */
3869 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x55: */
3870 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x56: */
3871 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x57: */
3872 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x58: */
3873 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x59: */
3874 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x5a: */
3875 	ISP_FC_OPMAP(0x03, 0x01),	/* 0x5b: MBOX_DRIVER_HEARTBEAT */
3876 	ISP_FC_OPMAP(0xcf, 0x01),	/* 0x5c: MBOX_FW_HEARTBEAT */
3877 	ISP_FC_OPMAP(0x07, 0x1f),	/* 0x5d: MBOX_GET_SET_DATA_RATE */
3878 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x5e: */
3879 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x5f: */
3880 	ISP_FC_OPMAP(0xcf, 0x0f),	/* 0x60: MBOX_INIT_FIRMWARE */
3881 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x61: */
3882 	ISP_FC_OPMAP(0x01, 0x01),	/* 0x62: MBOX_INIT_LIP */
3883 	ISP_FC_OPMAP(0xcd, 0x03),	/* 0x63: MBOX_GET_FC_AL_POSITION_MAP */
3884 	ISP_FC_OPMAP(0xcf, 0x01),	/* 0x64: MBOX_GET_PORT_DB */
3885 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x65: MBOX_CLEAR_ACA */
3886 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x66: MBOX_TARGET_RESET */
3887 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x67: MBOX_CLEAR_TASK_SET */
3888 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x68: MBOX_ABORT_TASK_SET */
3889 	ISP_FC_OPMAP_HALF(0x00, 0x01, 0x0f, 0x1f),	/* 0x69: MBOX_GET_FW_STATE */
3890 	ISP_FC_OPMAP_HALF(0x6, 0x03, 0x0, 0xcf),	/* 0x6a: MBOX_GET_PORT_NAME */
3891 	ISP_FC_OPMAP(0xcf, 0x01),	/* 0x6b: MBOX_GET_LINK_STATUS */
3892 	ISP_FC_OPMAP(0x0f, 0x01),	/* 0x6c: MBOX_INIT_LIP_RESET */
3893 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x6d: */
3894 	ISP_FC_OPMAP(0xcf, 0x03),	/* 0x6e: MBOX_SEND_SNS */
3895 	ISP_FC_OPMAP(0x0f, 0x07),	/* 0x6f: MBOX_FABRIC_LOGIN */
3896 	ISP_FC_OPMAP_HALF(0x02, 0x03, 0x00, 0x03),	/* 0x70: MBOX_SEND_CHANGE_REQUEST */
3897 	ISP_FC_OPMAP(0x03, 0x03),	/* 0x71: MBOX_FABRIC_LOGOUT */
3898 	ISP_FC_OPMAP(0x0f, 0x0f),	/* 0x72: MBOX_INIT_LIP_LOGIN */
3899 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x73: */
3900 	ISP_FC_OPMAP(0x07, 0x01),	/* 0x74: LOGIN LOOP PORT */
3901 	ISP_FC_OPMAP_HALF(0x03, 0xcf, 0x00, 0x07),	/* 0x75: GET PORT/NODE NAME LIST */
3902 	ISP_FC_OPMAP(0x4f, 0x01),	/* 0x76: SET VENDOR ID */
3903 	ISP_FC_OPMAP(0xcd, 0x01),	/* 0x77: INITIALIZE IP MAILBOX */
3904 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x78: */
3905 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x79: */
3906 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x7a: */
3907 	ISP_FC_OPMAP(0x00, 0x00),	/* 0x7b: */
3908 	ISP_FC_OPMAP_HALF(0x03, 0x4f, 0x00, 0x07),	/* 0x7c: Get ID List */
3909 	ISP_FC_OPMAP(0xcf, 0x01),	/* 0x7d: SEND LFA */
3910 	ISP_FC_OPMAP(0x0f, 0x01)	/* 0x7e: LUN RESET */
3911 };
3912 #define	MAX_FC_OPCODE	0x7e
3913 /*
3914  * Footnotes
3915  *
3916  * (1): this sets bits 21..16 in mailbox register #8, which we nominally
3917  *	do not access at this time in the core driver. The caller is
3918  *	responsible for setting this register first (Gross!). The assumption
3919  *	is that we won't overflow.
3920  */
3921 
3922 static const char *fc_mbcmd_names[] = {
3923 	"NO-OP",			/* 00h */
3924 	"LOAD RAM",
3925 	"EXEC FIRMWARE",
3926 	"DUMP RAM",
3927 	"WRITE RAM WORD",
3928 	"READ RAM WORD",
3929 	"MAILBOX REG TEST",
3930 	"VERIFY CHECKSUM",
3931 	"ABOUT FIRMWARE",
3932 	"LOAD RAM (2100)",
3933 	"DUMP RAM",
3934 	"LOAD RISC RAM",
3935 	"DUMP RISC RAM",
3936 	"WRITE RAM WORD EXTENDED",
3937 	"CHECK FIRMWARE",
3938 	"READ RAM WORD EXTENDED",
3939 	"INIT REQUEST QUEUE",		/* 10h */
3940 	"INIT RESULT QUEUE",
3941 	"EXECUTE IOCB",
3942 	"WAKE UP",
3943 	"STOP FIRMWARE",
3944 	"ABORT",
3945 	"ABORT DEVICE",
3946 	"ABORT TARGET",
3947 	"BUS RESET",
3948 	"STOP QUEUE",
3949 	"START QUEUE",
3950 	"SINGLE STEP QUEUE",
3951 	"ABORT QUEUE",
3952 	"GET DEV QUEUE STATUS",
3953 	NULL,
3954 	"GET FIRMWARE STATUS",
3955 	"GET LOOP ID",			/* 20h */
3956 	NULL,
3957 	"GET TIMEOUT PARAMS",
3958 	NULL,
3959 	NULL,
3960 	NULL,
3961 	NULL,
3962 	NULL,
3963 	"GET FIRMWARE OPTIONS",
3964 	"GET PORT QUEUE PARAMS",
3965 	"GENERATE SYSTEM ERROR",
3966 	NULL,
3967 	NULL,
3968 	NULL,
3969 	NULL,
3970 	NULL,
3971 	"WRITE SFP",			/* 30h */
3972 	"READ SFP",
3973 	"SET TIMEOUT PARAMS",
3974 	NULL,
3975 	NULL,
3976 	NULL,
3977 	NULL,
3978 	NULL,
3979 	"SET FIRMWARE OPTIONS",
3980 	"SET PORT QUEUE PARAMS",
3981 	NULL,
3982 	"SET FC LED CONF",
3983 	NULL,
3984 	"RESTART NIC FIRMWARE",
3985 	"ACCESS CONTROL",
3986 	NULL,
3987 	"LOOP PORT BYPASS",		/* 40h */
3988 	"LOOP PORT ENABLE",
3989 	"GET RESOURCE COUNT",
3990 	"REQUEST NON PARTICIPATING MODE",
3991 	"DIAGNOSTIC ECHO TEST",
3992 	"DIAGNOSTIC LOOPBACK",
3993 	NULL,
3994 	"GET PORT DATABASE ENHANCED",
3995 	"INIT FIRMWARE MULTI ID",
3996 	"GET VP DATABASE",
3997 	"GET VP DATABASE ENTRY",
3998 	NULL,
3999 	NULL,
4000 	NULL,
4001 	NULL,
4002 	NULL,
4003 	"GET FCF LIST",			/* 50h */
4004 	"GET DCBX PARAMETERS",
4005 	NULL,
4006 	"HOST MEMORY COPY",
4007 	"EXECUTE IOCB A64",
4008 	NULL,
4009 	NULL,
4010 	"SEND RNID",
4011 	NULL,
4012 	"SET PARAMETERS",
4013 	"GET PARAMETERS",
4014 	"DRIVER HEARTBEAT",
4015 	"FIRMWARE HEARTBEAT",
4016 	"GET/SET DATA RATE",
4017 	"SEND RNFT",
4018 	NULL,
4019 	"INIT FIRMWARE",		/* 60h */
4020 	"GET INIT CONTROL BLOCK",
4021 	"INIT LIP",
4022 	"GET FC-AL POSITION MAP",
4023 	"GET PORT DATABASE",
4024 	"CLEAR ACA",
4025 	"TARGET RESET",
4026 	"CLEAR TASK SET",
4027 	"ABORT TASK SET",
4028 	"GET FW STATE",
4029 	"GET PORT NAME",
4030 	"GET LINK STATUS",
4031 	"INIT LIP RESET",
4032 	"GET LINK STATS & PRIVATE DATA CNTS",
4033 	"SEND SNS",
4034 	"FABRIC LOGIN",
4035 	"SEND CHANGE REQUEST",		/* 70h */
4036 	"FABRIC LOGOUT",
4037 	"INIT LIP LOGIN",
4038 	NULL,
4039 	"LOGIN LOOP PORT",
4040 	"GET PORT/NODE NAME LIST",
4041 	"SET VENDOR ID",
4042 	"INITIALIZE IP MAILBOX",
4043 	NULL,
4044 	NULL,
4045 	"GET XGMAC STATS",
4046 	NULL,
4047 	"GET ID LIST",
4048 	"SEND LFA",
4049 	"LUN RESET"
4050 };
4051 
4052 static void
4053 isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
4054 {
4055 	const char *cname, *xname, *sname;
4056 	char tname[16], mname[16];
4057 	unsigned int ibits, obits, box, opcode, t, to;
4058 
4059 	opcode = mbp->param[0];
4060 	if (opcode > MAX_FC_OPCODE) {
4061 		mbp->param[0] = MBOX_INVALID_COMMAND;
4062 		isp_prt(isp, ISP_LOGERR, "Unknown Command 0x%x", opcode);
4063 		return;
4064 	}
4065 	cname = fc_mbcmd_names[opcode];
4066 	ibits = ISP_FC_IBITS(opcode);
4067 	obits = ISP_FC_OBITS(opcode);
4068 	if (cname == NULL) {
4069 		cname = tname;
4070 		ISP_SNPRINTF(tname, sizeof tname, "opcode %x", opcode);
4071 	}
4072 	isp_prt(isp, ISP_LOGDEBUG3, "Mailbox Command '%s'", cname);
4073 
4074 	/*
4075 	 * Pick up any additional bits that the caller might have set.
4076 	 */
4077 	ibits |= mbp->ibits;
4078 	obits |= mbp->obits;
4079 
4080 	/*
4081 	 * Mask any bits that the caller wants us to mask
4082 	 */
4083 	ibits &= mbp->ibitm;
4084 	obits &= mbp->obitm;
4085 
4086 
4087 	if (ibits == 0 && obits == 0) {
4088 		mbp->param[0] = MBOX_COMMAND_PARAM_ERROR;
4089 		isp_prt(isp, ISP_LOGERR, "no parameters for 0x%x", opcode);
4090 		return;
4091 	}
4092 
4093 	for (box = 0; box < ISP_NMBOX(isp); box++) {
4094 		if (ibits & (1 << box)) {
4095 			isp_prt(isp, ISP_LOGDEBUG3, "IN mbox %d = 0x%04x", box,
4096 			    mbp->param[box]);
4097 			ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
4098 		}
4099 		isp->isp_mboxtmp[box] = mbp->param[box] = 0;
4100 	}
4101 
4102 	isp->isp_obits = obits;
4103 	isp->isp_mboxbsy = 1;
4104 
4105 	/*
4106 	 * Set Host Interrupt condition so that RISC will pick up mailbox regs.
4107 	 */
4108 	ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_SET_HOST_INT);
4109 
4110 	/*
4111 	 * While we haven't finished the command, spin our wheels here.
4112 	 */
4113 	to = (mbp->timeout == 0) ? MBCMD_DEFAULT_TIMEOUT : mbp->timeout;
4114 	for (t = 0; t < to; t += 100) {
4115 		if (!isp->isp_mboxbsy)
4116 			break;
4117 		ISP_RUN_ISR(isp);
4118 		if (!isp->isp_mboxbsy)
4119 			break;
4120 		ISP_DELAY(100);
4121 	}
4122 
4123 	/*
4124 	 * Did the command time out?
4125 	 */
4126 	if (isp->isp_mboxbsy) {
4127 		isp->isp_mboxbsy = 0;
4128 		isp_prt(isp, ISP_LOGWARN, "Mailbox Command (0x%x) Timeout (%uus) (%s:%d)",
4129 		    opcode, to, mbp->func, mbp->lineno);
4130 		mbp->param[0] = MBOX_TIMEOUT;
4131 		goto out;
4132 	}
4133 
4134 	/*
4135 	 * Copy back output registers.
4136 	 */
4137 	for (box = 0; box < ISP_NMBOX(isp); box++) {
4138 		if (obits & (1 << box)) {
4139 			mbp->param[box] = isp->isp_mboxtmp[box];
4140 			isp_prt(isp, ISP_LOGDEBUG3, "OUT mbox %d = 0x%04x", box,
4141 			    mbp->param[box]);
4142 		}
4143 	}
4144 
4145 out:
4146 	if (mbp->logval == 0 || mbp->param[0] == MBOX_COMMAND_COMPLETE)
4147 		return;
4148 
4149 	if ((mbp->param[0] & 0xbfe0) == 0 &&
4150 	    (mbp->logval & MBLOGMASK(mbp->param[0])) == 0)
4151 		return;
4152 
4153 	xname = NULL;
4154 	sname = "";
4155 	switch (mbp->param[0]) {
4156 	case MBOX_INVALID_COMMAND:
4157 		xname = "INVALID COMMAND";
4158 		break;
4159 	case MBOX_HOST_INTERFACE_ERROR:
4160 		xname = "HOST INTERFACE ERROR";
4161 		break;
4162 	case MBOX_TEST_FAILED:
4163 		xname = "TEST FAILED";
4164 		break;
4165 	case MBOX_COMMAND_ERROR:
4166 		xname = "COMMAND ERROR";
4167 		ISP_SNPRINTF(mname, sizeof(mname), " subcode 0x%x",
4168 		    mbp->param[1]);
4169 		sname = mname;
4170 		break;
4171 	case MBOX_COMMAND_PARAM_ERROR:
4172 		xname = "COMMAND PARAMETER ERROR";
4173 		break;
4174 	case MBOX_PORT_ID_USED:
4175 		xname = "PORT ID ALREADY IN USE";
4176 		break;
4177 	case MBOX_LOOP_ID_USED:
4178 		xname = "LOOP ID ALREADY IN USE";
4179 		break;
4180 	case MBOX_ALL_IDS_USED:
4181 		xname = "ALL LOOP IDS IN USE";
4182 		break;
4183 	case MBOX_NOT_LOGGED_IN:
4184 		xname = "NOT LOGGED IN";
4185 		break;
4186 	case MBOX_LINK_DOWN_ERROR:
4187 		xname = "LINK DOWN ERROR";
4188 		break;
4189 	case MBOX_LOOPBACK_ERROR:
4190 		xname = "LOOPBACK ERROR";
4191 		break;
4192 	case MBOX_CHECKSUM_ERROR:
4193 		xname = "CHECKSUM ERROR";
4194 		break;
4195 	case MBOX_INVALID_PRODUCT_KEY:
4196 		xname = "INVALID PRODUCT KEY";
4197 		break;
4198 	case MBOX_REGS_BUSY:
4199 		xname = "REGISTERS BUSY";
4200 		break;
4201 	case MBOX_TIMEOUT:
4202 		xname = "TIMEOUT";
4203 		break;
4204 	default:
4205 		ISP_SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]);
4206 		xname = mname;
4207 		break;
4208 	}
4209 	if (xname) {
4210 		isp_prt(isp, ISP_LOGALL, "Mailbox Command '%s' failed (%s%s)",
4211 		    cname, xname, sname);
4212 	}
4213 }
4214 
4215 static int
4216 isp_fw_state(ispsoftc_t *isp, int chan)
4217 {
4218 	mbreg_t mbs;
4219 
4220 	MBSINIT(&mbs, MBOX_GET_FW_STATE, MBLOGALL, 0);
4221 	isp_mboxcmd(isp, &mbs);
4222 	if (mbs.param[0] == MBOX_COMMAND_COMPLETE)
4223 		return (mbs.param[1]);
4224 	return (FW_ERROR);
4225 }
4226 
4227 static void
4228 isp_setdfltfcparm(ispsoftc_t *isp, int chan)
4229 {
4230 	fcparam *fcp = FCPARAM(isp, chan);
4231 
4232 	/*
4233 	 * Establish some default parameters.
4234 	 */
4235 	fcp->role = DEFAULT_ROLE(isp, chan);
4236 	fcp->isp_retry_delay = ICB_DFLT_RDELAY;
4237 	fcp->isp_retry_count = ICB_DFLT_RCOUNT;
4238 	fcp->isp_loopid = DEFAULT_LOOPID(isp, chan);
4239 	fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp, chan);
4240 	fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp, chan);
4241 	fcp->isp_fwoptions = 0;
4242 	fcp->isp_xfwoptions = 0;
4243 	fcp->isp_zfwoptions = 0;
4244 	fcp->isp_lasthdl = NIL_HANDLE;
4245 	fcp->isp_login_hdl = NIL_HANDLE;
4246 
4247 	fcp->isp_fwoptions |= ICB2400_OPT1_FAIRNESS;
4248 	fcp->isp_fwoptions |= ICB2400_OPT1_HARD_ADDRESS;
4249 	if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX)
4250 		fcp->isp_fwoptions |= ICB2400_OPT1_FULL_DUPLEX;
4251 	fcp->isp_fwoptions |= ICB2400_OPT1_BOTH_WWNS;
4252 	fcp->isp_xfwoptions |= ICB2400_OPT2_LOOP_2_PTP;
4253 	fcp->isp_zfwoptions |= ICB2400_OPT3_RATE_AUTO;
4254 
4255 	/*
4256 	 * Now try and read NVRAM unless told to not do so.
4257 	 * This will set fcparam's isp_wwnn_nvram && isp_wwpn_nvram.
4258 	 */
4259 	if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
4260 		int i, j = 0;
4261 		/*
4262 		 * Give a couple of tries at reading NVRAM.
4263 		 */
4264 		for (i = 0; i < 2; i++) {
4265 			j = isp_read_nvram(isp, chan);
4266 			if (j == 0) {
4267 				break;
4268 			}
4269 		}
4270 		if (j) {
4271 			isp->isp_confopts |= ISP_CFG_NONVRAM;
4272 		}
4273 	}
4274 
4275 	fcp->isp_wwnn = ACTIVE_NODEWWN(isp, chan);
4276 	fcp->isp_wwpn = ACTIVE_PORTWWN(isp, chan);
4277 	isp_prt(isp, ISP_LOGCONFIG, "Chan %d 0x%08x%08x/0x%08x%08x Role %s",
4278 	    chan, (uint32_t) (fcp->isp_wwnn >> 32), (uint32_t) (fcp->isp_wwnn),
4279 	    (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) (fcp->isp_wwpn),
4280 	    isp_class3_roles[fcp->role]);
4281 }
4282 
4283 /*
4284  * Re-initialize the ISP and complete all orphaned commands
4285  * with a 'botched' notice. The reset/init routines should
4286  * not disturb an already active list of commands.
4287  */
4288 
4289 int
4290 isp_reinit(ispsoftc_t *isp, int do_load_defaults)
4291 {
4292 	int i, res = 0;
4293 
4294 	if (isp->isp_state > ISP_RESETSTATE)
4295 		isp_stop(isp);
4296 	if (isp->isp_state != ISP_RESETSTATE)
4297 		isp_reset(isp, do_load_defaults);
4298 	if (isp->isp_state != ISP_RESETSTATE) {
4299 		res = EIO;
4300 		isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__);
4301 		goto cleanup;
4302 	}
4303 
4304 	isp_init(isp);
4305 	if (isp->isp_state > ISP_RESETSTATE &&
4306 	    isp->isp_state != ISP_RUNSTATE) {
4307 		res = EIO;
4308 		isp_prt(isp, ISP_LOGERR, "%s: cannot init card", __func__);
4309 		ISP_DISABLE_INTS(isp);
4310 	}
4311 
4312 cleanup:
4313 	isp_clear_commands(isp);
4314 	for (i = 0; i < isp->isp_nchan; i++)
4315 		isp_clear_portdb(isp, i);
4316 	return (res);
4317 }
4318 
4319 /*
4320  * NVRAM Routines
4321  */
4322 static int
4323 isp_read_nvram(ispsoftc_t *isp, int bus)
4324 {
4325 
4326 	return (isp_read_nvram_2400(isp));
4327 }
4328 
4329 static int
4330 isp_read_nvram_2400(ispsoftc_t *isp)
4331 {
4332 	int retval = 0;
4333 	uint32_t addr, csum, lwrds, *dptr;
4334 	uint8_t nvram_data[ISP2400_NVRAM_SIZE];
4335 
4336 	addr = ISP2400_NVRAM_PORT_ADDR(isp->isp_port);
4337 	dptr = (uint32_t *) nvram_data;
4338 	for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
4339 		isp_rd_2400_nvram(isp, addr++, dptr++);
4340 	}
4341 	if (nvram_data[0] != 'I' || nvram_data[1] != 'S' ||
4342 	    nvram_data[2] != 'P') {
4343 		isp_prt(isp, ISP_LOGWARN, "invalid NVRAM header (%x %x %x)",
4344 		    nvram_data[0], nvram_data[1], nvram_data[2]);
4345 		retval = -1;
4346 		goto out;
4347 	}
4348 	dptr = (uint32_t *) nvram_data;
4349 	for (csum = 0, lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
4350 		uint32_t tmp;
4351 		ISP_IOXGET_32(isp, &dptr[lwrds], tmp);
4352 		csum += tmp;
4353 	}
4354 	if (csum != 0) {
4355 		isp_prt(isp, ISP_LOGWARN, "invalid NVRAM checksum");
4356 		retval = -1;
4357 		goto out;
4358 	}
4359 	isp_parse_nvram_2400(isp, nvram_data);
4360 out:
4361 	return (retval);
4362 }
4363 
4364 static void
4365 isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp)
4366 {
4367 	int loops = 0;
4368 	uint32_t base = 0x7ffe0000;
4369 	uint32_t tmp = 0;
4370 
4371 	if (IS_26XX(isp)) {
4372 		base = 0x7fe7c000;	/* XXX: Observation, may be wrong. */
4373 	} else if (IS_25XX(isp)) {
4374 		base = 0x7ff00000 | 0x48000;
4375 	}
4376 	ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr);
4377 	for (loops = 0; loops < 5000; loops++) {
4378 		ISP_DELAY(10);
4379 		tmp = ISP_READ(isp, BIU2400_FLASH_ADDR);
4380 		if ((tmp & (1U << 31)) != 0) {
4381 			break;
4382 		}
4383 	}
4384 	if (tmp & (1U << 31)) {
4385 		*rp = ISP_READ(isp, BIU2400_FLASH_DATA);
4386 		ISP_SWIZZLE_NVRAM_LONG(isp, rp);
4387 	} else {
4388 		*rp = 0xffffffff;
4389 	}
4390 }
4391 
4392 static void
4393 isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
4394 {
4395 	fcparam *fcp = FCPARAM(isp, 0);
4396 	uint64_t wwn;
4397 
4398 	isp_prt(isp, ISP_LOGDEBUG0,
4399 	    "NVRAM 0x%08x%08x 0x%08x%08x maxframelen %d",
4400 	    (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data) >> 32),
4401 	    (uint32_t) (ISP2400_NVRAM_NODE_NAME(nvram_data)),
4402 	    (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data) >> 32),
4403 	    (uint32_t) (ISP2400_NVRAM_PORT_NAME(nvram_data)),
4404 	    ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data));
4405 	isp_prt(isp, ISP_LOGDEBUG0,
4406 	    "NVRAM loopid %d fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x",
4407 	    ISP2400_NVRAM_HARDLOOPID(nvram_data),
4408 	    ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data),
4409 	    ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data),
4410 	    ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data));
4411 
4412 	wwn = ISP2400_NVRAM_PORT_NAME(nvram_data);
4413 	fcp->isp_wwpn_nvram = wwn;
4414 
4415 	wwn = ISP2400_NVRAM_NODE_NAME(nvram_data);
4416 	if (wwn) {
4417 		if ((wwn >> 60) != 2 && (wwn >> 60) != 5) {
4418 			wwn = 0;
4419 		}
4420 	}
4421 	if (wwn == 0 && (fcp->isp_wwpn_nvram >> 60) == 2) {
4422 		wwn = fcp->isp_wwpn_nvram;
4423 		wwn &= ~((uint64_t) 0xfff << 48);
4424 	}
4425 	fcp->isp_wwnn_nvram = wwn;
4426 
4427 	if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) {
4428 		DEFAULT_FRAMESIZE(isp) =
4429 		    ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data);
4430 	}
4431 	if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
4432 		fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data);
4433 	}
4434 	fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data);
4435 	fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data);
4436 	fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data);
4437 }
4438