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