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