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