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