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