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