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