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