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