1 /* $NetBSD: isp_netbsd.c,v 1.99 2024/02/09 22:08:34 andvar Exp $ */
2 /*
3  * Platform (NetBSD) dependent common attachment code for Qlogic adapters.
4  */
5 /*
6  * Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration
7  * All rights reserved.
8  *
9  * Additional Copyright (C) 2000-2007 by Matthew Jacob
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: isp_netbsd.c,v 1.99 2024/02/09 22:08:34 andvar Exp $");
37 
38 #include <dev/ic/isp_netbsd.h>
39 #include <dev/ic/isp_ioctl.h>
40 #include <sys/scsiio.h>
41 
42 /*
43  * Set a timeout for the watchdogging of a command.
44  *
45  * The dimensional analysis is
46  *
47  *        milliseconds * (seconds/millisecond) * (ticks/second) = ticks
48  *
49  *                            =
50  *
51  *        (milliseconds / 1000) * hz = ticks
52  *
53  *
54  * For timeouts less than 1 second, we'll get zero. Because of this, and
55  * because we want to establish *our* timeout to be longer than what the
56  * firmware might do, we just add 3 seconds at the back end.
57  */
58 #define   _XT(xs)   ((((xs)->timeout/1000) * hz) + (3 * hz))
59 
60 static void isp_config_interrupts(device_t);
61 static void ispminphys_1020(struct buf *);
62 static void ispminphys(struct buf *);
63 static void ispcmd(struct ispsoftc *, XS_T *);
64 static void isprequest(struct scsipi_channel *, scsipi_adapter_req_t, void *);
65 static int
66 ispioctl(struct scsipi_channel *, u_long, void *, int, struct proc *);
67 
68 static void isp_polled_cmd_wait(struct ispsoftc *, XS_T *);
69 static void isp_dog(void *);
70 static void isp_gdt(void *);
71 static void isp_ldt(void *);
72 static void isp_make_here(ispsoftc_t *, int);
73 static void isp_make_gone(ispsoftc_t *, int);
74 static void isp_fc_worker(void *);
75 
76 static const char *roles[4] = {
77     "(none)", "Target", "Initiator", "Target/Initiator"
78 };
79 static const char prom3[] =
80     "PortID %#06x Departed from Target %u because of %s";
81 int isp_change_is_bad = 0;    /* "changed" devices are bad */
82 int isp_quickboot_time = 15;  /* don't wait more than N secs for loop up */
83 static int isp_fabric_hysteresis = 5;
84 #define   isp_change_is_bad   0
85 
86 /*
87  * Complete attachment of hardware, include subdevices.
88  */
89 
90 void
isp_attach(struct ispsoftc * isp)91 isp_attach(struct ispsoftc *isp)
92 {
93           device_t self = isp->isp_osinfo.dev;
94           int i;
95 
96           isp->isp_state = ISP_RUNSTATE;
97 
98           isp->isp_osinfo.adapter.adapt_dev = self;
99           isp->isp_osinfo.adapter.adapt_openings = isp->isp_maxcmds;
100           isp->isp_osinfo.loop_down_limit = 300;
101 
102           /*
103            * It's not stated whether max_periph is limited by SPI
104            * tag uage, but let's assume that it is.
105            */
106           isp->isp_osinfo.adapter.adapt_max_periph = uimin(isp->isp_maxcmds, 255);
107           isp->isp_osinfo.adapter.adapt_ioctl = ispioctl;
108           isp->isp_osinfo.adapter.adapt_request = isprequest;
109           if (isp->isp_type <= ISP_HA_SCSI_1020A) {
110                     isp->isp_osinfo.adapter.adapt_minphys = ispminphys_1020;
111           } else {
112                     isp->isp_osinfo.adapter.adapt_minphys = ispminphys;
113           }
114 
115           callout_init(&isp->isp_osinfo.gdt, 0);
116           callout_setfunc(&isp->isp_osinfo.gdt, isp_gdt, isp);
117           callout_init(&isp->isp_osinfo.ldt, 0);
118           callout_setfunc(&isp->isp_osinfo.ldt, isp_ldt, isp);
119           if (IS_FC(isp)) {
120                     if (kthread_create(PRI_NONE, 0, NULL, isp_fc_worker, isp,
121                         &isp->isp_osinfo.thread, "%s:fc_thrd",
122                         device_xname(self))) {
123                               isp_prt(isp, ISP_LOGERR,
124                                   "unable to create FC worker thread");
125                               return;
126                     }
127           }
128 
129           for (i = 0; i != isp->isp_osinfo.adapter.adapt_nchannels; i++) {
130                     isp->isp_osinfo.chan[i].chan_adapter =
131                         &isp->isp_osinfo.adapter;
132                     isp->isp_osinfo.chan[i].chan_bustype = &scsi_bustype;
133                     isp->isp_osinfo.chan[i].chan_channel = i;
134                     /*
135                      * Until the midlayer is fixed to use REPORT LUNS,
136                      * limit to 8 luns.
137                      */
138                     isp->isp_osinfo.chan[i].chan_nluns = uimin(isp->isp_maxluns, 8);
139                     if (IS_FC(isp)) {
140                               isp->isp_osinfo.chan[i].chan_ntargets = MAX_FC_TARG;
141                               if (ISP_CAP_2KLOGIN(isp) == 0 && MAX_FC_TARG > 256) {
142                                         isp->isp_osinfo.chan[i].chan_ntargets = 256;
143                               }
144                               isp->isp_osinfo.chan[i].chan_id = MAX_FC_TARG;
145                     } else {
146                               isp->isp_osinfo.chan[i].chan_ntargets = MAX_TARGETS;
147                               isp->isp_osinfo.chan[i].chan_id =
148                                   SDPARAM(isp, i)->isp_initiator_id;
149                               ISP_LOCK(isp);
150                               (void) isp_control(isp, ISPCTL_RESET_BUS, i);
151                               ISP_UNLOCK(isp);
152                     }
153           }
154 
155           /*
156          * Defer enabling mailbox interrupts until later.
157          */
158         config_interrupts(self, isp_config_interrupts);
159 }
160 
161 static void
isp_config_interrupts(device_t self)162 isp_config_interrupts(device_t self)
163 {
164           int i;
165         struct ispsoftc *isp = device_private(self);
166 
167         isp->isp_osinfo.mbox_sleep_ok = 1;
168 
169           if (IS_FC(isp) && (FCPARAM(isp, 0)->isp_fwstate != FW_READY ||
170               FCPARAM(isp, 0)->isp_loopstate != LOOP_READY)) {
171                     isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
172                        "Starting Initial Loop Down Timer");
173                     callout_schedule(&isp->isp_osinfo.ldt, isp_quickboot_time * hz);
174           }
175 
176           /*
177            * And attach children (if any).
178            */
179           for (i = 0; i < isp->isp_osinfo.adapter.adapt_nchannels; i++) {
180                     config_found(self, &isp->isp_osinfo.chan[i], scsiprint,
181                         CFARGS_NONE);
182           }
183 }
184 
185 /*
186  * minphys our xfers
187  */
188 static void
ispminphys_1020(struct buf * bp)189 ispminphys_1020(struct buf *bp)
190 {
191           if (bp->b_bcount >= (1 << 24)) {
192                     bp->b_bcount = (1 << 24);
193           }
194           minphys(bp);
195 }
196 
197 static void
ispminphys(struct buf * bp)198 ispminphys(struct buf *bp)
199 {
200           if (bp->b_bcount >= (1 << 30)) {
201                     bp->b_bcount = (1 << 30);
202           }
203           minphys(bp);
204 }
205 
206 static int
ispioctl(struct scsipi_channel * chan,u_long cmd,void * addr,int flag,struct proc * p)207 ispioctl(struct scsipi_channel *chan, u_long cmd, void *addr, int flag,
208           struct proc *p)
209 {
210           struct ispsoftc *isp = device_private(chan->chan_adapter->adapt_dev);
211           int nr, bus, retval = ENOTTY;
212 
213           switch (cmd) {
214           case ISP_SDBLEV:
215           {
216                     int olddblev = isp->isp_dblev;
217                     isp->isp_dblev = *(int *)addr;
218                     *(int *)addr = olddblev;
219                     retval = 0;
220                     break;
221           }
222           case ISP_GETROLE:
223                     bus = *(int *)addr;
224                     if (bus < 0 || bus >= isp->isp_nchan) {
225                               retval = -ENXIO;
226                               break;
227                     }
228                     if (IS_FC(isp)) {
229                               *(int *)addr = FCPARAM(isp, bus)->role;
230                     } else {
231                               *(int *)addr = SDPARAM(isp, bus)->role;
232                     }
233                     retval = 0;
234                     break;
235           case ISP_SETROLE:
236 
237                     nr = *(int *)addr;
238                     bus = nr >> 8;
239                     if (bus < 0 || bus >= isp->isp_nchan) {
240                               retval = -ENXIO;
241                               break;
242                     }
243                     nr &= 0xff;
244                     if (nr & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) {
245                               retval = EINVAL;
246                               break;
247                     }
248                     if (IS_FC(isp)) {
249                               *(int *)addr = FCPARAM(isp, bus)->role;
250                               FCPARAM(isp, bus)->role = nr;
251                     } else {
252                               *(int *)addr = SDPARAM(isp, bus)->role;
253                               SDPARAM(isp, bus)->role = nr;
254                     }
255                     retval = 0;
256                     break;
257 
258           case ISP_RESETHBA:
259                     ISP_LOCK(isp);
260                     isp_reinit(isp, 0);
261                     ISP_UNLOCK(isp);
262                     retval = 0;
263                     break;
264 
265           case ISP_RESCAN:
266                     if (IS_FC(isp)) {
267                               bus = *(int *)addr;
268                               if (bus < 0 || bus >= isp->isp_nchan) {
269                                         retval = -ENXIO;
270                                         break;
271                               }
272                               ISP_LOCK(isp);
273                               if (isp_fc_runstate(isp, bus, 5 * 1000000)) {
274                                         retval = EIO;
275                               } else {
276                                         retval = 0;
277                               }
278                               ISP_UNLOCK(isp);
279                     }
280                     break;
281 
282           case ISP_FC_LIP:
283                     if (IS_FC(isp)) {
284                               bus = *(int *)addr;
285                               if (bus < 0 || bus >= isp->isp_nchan) {
286                                         retval = -ENXIO;
287                                         break;
288                               }
289                               ISP_LOCK(isp);
290                               if (isp_control(isp, ISPCTL_SEND_LIP, bus)) {
291                                         retval = EIO;
292                               } else {
293                                         retval = 0;
294                               }
295                               ISP_UNLOCK(isp);
296                     }
297                     break;
298           case ISP_FC_GETDINFO:
299           {
300                     struct isp_fc_device *ifc = (struct isp_fc_device *) addr;
301                     fcportdb_t *lp;
302 
303                     if (IS_SCSI(isp)) {
304                               break;
305                     }
306                     if (ifc->loopid >= MAX_FC_TARG) {
307                               retval = EINVAL;
308                               break;
309                     }
310                     lp = &FCPARAM(isp, ifc->chan)->portdb[ifc->loopid];
311                     if (lp->state == FC_PORTDB_STATE_VALID) {
312                               ifc->role = lp->roles;
313                               ifc->loopid = lp->handle;
314                               ifc->portid = lp->portid;
315                               ifc->node_wwn = lp->node_wwn;
316                               ifc->port_wwn = lp->port_wwn;
317                               retval = 0;
318                     } else {
319                               retval = ENODEV;
320                     }
321                     break;
322           }
323           case ISP_GET_STATS:
324           {
325                     isp_stats_t *sp = (isp_stats_t *) addr;
326 
327                     ISP_MEMZERO(sp, sizeof (*sp));
328                     sp->isp_stat_version = ISP_STATS_VERSION;
329                     sp->isp_type = isp->isp_type;
330                     sp->isp_revision = isp->isp_revision;
331                     ISP_LOCK(isp);
332                     sp->isp_stats[ISP_INTCNT] = isp->isp_intcnt;
333                     sp->isp_stats[ISP_INTBOGUS] = isp->isp_intbogus;
334                     sp->isp_stats[ISP_INTMBOXC] = isp->isp_intmboxc;
335                     sp->isp_stats[ISP_INGOASYNC] = isp->isp_intoasync;
336                     sp->isp_stats[ISP_RSLTCCMPLT] = isp->isp_rsltccmplt;
337                     sp->isp_stats[ISP_FPHCCMCPLT] = isp->isp_fphccmplt;
338                     sp->isp_stats[ISP_RSCCHIWAT] = isp->isp_rscchiwater;
339                     sp->isp_stats[ISP_FPCCHIWAT] = isp->isp_fpcchiwater;
340                     ISP_UNLOCK(isp);
341                     retval = 0;
342                     break;
343           }
344           case ISP_CLR_STATS:
345                     ISP_LOCK(isp);
346                     isp->isp_intcnt = 0;
347                     isp->isp_intbogus = 0;
348                     isp->isp_intmboxc = 0;
349                     isp->isp_intoasync = 0;
350                     isp->isp_rsltccmplt = 0;
351                     isp->isp_fphccmplt = 0;
352                     isp->isp_rscchiwater = 0;
353                     isp->isp_fpcchiwater = 0;
354                     ISP_UNLOCK(isp);
355                     retval = 0;
356                     break;
357           case ISP_FC_GETHINFO:
358           {
359                     struct isp_hba_device *hba = (struct isp_hba_device *) addr;
360                     bus = hba->fc_channel;
361 
362                     if (bus < 0 || bus >= isp->isp_nchan) {
363                               retval = ENXIO;
364                               break;
365                     }
366                     hba->fc_fw_major = ISP_FW_MAJORX(isp->isp_fwrev);
367                     hba->fc_fw_minor = ISP_FW_MINORX(isp->isp_fwrev);
368                     hba->fc_fw_micro = ISP_FW_MICROX(isp->isp_fwrev);
369                     hba->fc_nchannels = isp->isp_nchan;
370                     hba->fc_nports = isp->isp_nchan;/* XXXX 24XX STUFF? XXX */
371                     if (IS_FC(isp)) {
372                               hba->fc_speed = FCPARAM(isp, bus)->isp_gbspeed;
373                               hba->fc_topology = FCPARAM(isp, bus)->isp_topo + 1;
374                               hba->fc_loopid = FCPARAM(isp, bus)->isp_loopid;
375                               hba->nvram_node_wwn = FCPARAM(isp, bus)->isp_wwnn_nvram;
376                               hba->nvram_port_wwn = FCPARAM(isp, bus)->isp_wwpn_nvram;
377                               hba->active_node_wwn = FCPARAM(isp, bus)->isp_wwnn;
378                               hba->active_port_wwn = FCPARAM(isp, bus)->isp_wwpn;
379                     } else {
380                               hba->fc_speed = 0;
381                               hba->fc_topology = 0;
382                               hba->nvram_node_wwn = 0ull;
383                               hba->nvram_port_wwn = 0ull;
384                               hba->active_node_wwn = 0ull;
385                               hba->active_port_wwn = 0ull;
386                     }
387                     retval = 0;
388                     break;
389           }
390           case ISP_TSK_MGMT:
391           {
392                     int needmarker;
393                     struct isp_fc_tsk_mgmt *fct = (struct isp_fc_tsk_mgmt *) addr;
394                     uint16_t loopid;
395                     mbreg_t mbs;
396 
397                     if (IS_SCSI(isp)) {
398                               break;
399                     }
400 
401                     bus = fct->chan;
402                     if (bus < 0 || bus >= isp->isp_nchan) {
403                               retval = -ENXIO;
404                               break;
405                     }
406 
407                     memset(&mbs, 0, sizeof (mbs));
408                     needmarker = retval = 0;
409                     loopid = fct->loopid;
410                     if (ISP_CAP_2KLOGIN(isp) == 0) {
411                               loopid <<= 8;
412                     }
413                     switch (fct->action) {
414                     case IPT_CLEAR_ACA:
415                               mbs.param[0] = MBOX_CLEAR_ACA;
416                               mbs.param[1] = loopid;
417                               mbs.param[2] = fct->lun;
418                               break;
419                     case IPT_TARGET_RESET:
420                               mbs.param[0] = MBOX_TARGET_RESET;
421                               mbs.param[1] = loopid;
422                               needmarker = 1;
423                               break;
424                     case IPT_LUN_RESET:
425                               mbs.param[0] = MBOX_LUN_RESET;
426                               mbs.param[1] = loopid;
427                               mbs.param[2] = fct->lun;
428                               needmarker = 1;
429                               break;
430                     case IPT_CLEAR_TASK_SET:
431                               mbs.param[0] = MBOX_CLEAR_TASK_SET;
432                               mbs.param[1] = loopid;
433                               mbs.param[2] = fct->lun;
434                               needmarker = 1;
435                               break;
436                     case IPT_ABORT_TASK_SET:
437                               mbs.param[0] = MBOX_ABORT_TASK_SET;
438                               mbs.param[1] = loopid;
439                               mbs.param[2] = fct->lun;
440                               needmarker = 1;
441                               break;
442                     default:
443                               retval = EINVAL;
444                               break;
445                     }
446                     if (retval == 0) {
447                               if (needmarker) {
448                                         FCPARAM(isp, bus)->sendmarker = 1;
449                               }
450                               ISP_LOCK(isp);
451                               retval = isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
452                               ISP_UNLOCK(isp);
453                               if (retval) {
454                                         retval = EIO;
455                               }
456                     }
457                     break;
458           }
459           case ISP_FC_GETDLIST:
460           {
461                     isp_dlist_t local, *ua;
462                     uint16_t nph, nphe, count, channel, lim;
463                     struct wwnpair pair, *uptr;
464 
465                     if (IS_SCSI(isp)) {
466                               retval = EINVAL;
467                               break;
468                     }
469 
470                     ua = *(isp_dlist_t **)addr;
471                     if (copyin(ua, &local, sizeof (isp_dlist_t))) {
472                               retval = EFAULT;
473                               break;
474                     }
475                     lim = local.count;
476                     channel = local.channel;
477                     if (channel >= isp->isp_nchan) {
478                               retval = EINVAL;
479                               break;
480                     }
481 
482                     ua = *(isp_dlist_t **)addr;
483                     uptr = &ua->wwns[0];
484 
485                     if (ISP_CAP_2KLOGIN(isp)) {
486                               nphe = NPH_MAX_2K;
487                     } else {
488                               nphe = NPH_MAX;
489                     }
490                     for (count = 0, nph = 0; count < lim && nph != nphe; nph++) {
491                               ISP_LOCK(isp);
492                               retval = isp_control(isp, ISPCTL_GET_NAMES, channel,
493                                   nph, &pair.wwnn, &pair.wwpn);
494                               ISP_UNLOCK(isp);
495                               if (retval || (pair.wwpn == INI_NONE &&
496                                   pair.wwnn == INI_NONE)) {
497                                         retval = 0;
498                                         continue;
499                               }
500                               if (copyout(&pair, (void *)uptr++, sizeof (pair))) {
501                                         retval = EFAULT;
502                                         break;
503                               }
504                               count++;
505                     }
506                     if (retval == 0) {
507                               if (copyout(&count, (void *)&ua->count,
508                                   sizeof (count))) {
509                                         retval = EFAULT;
510                               }
511                     }
512                     break;
513           }
514           case SCBUSIORESET:
515                     ISP_LOCK(isp);
516                     if (isp_control(isp, ISPCTL_RESET_BUS, &chan->chan_channel)) {
517                               retval = EIO;
518                     } else {
519                               retval = 0;
520                     }
521                     ISP_UNLOCK(isp);
522                     break;
523           default:
524                     break;
525           }
526           return (retval);
527 }
528 
529 static void
ispcmd(struct ispsoftc * isp,XS_T * xs)530 ispcmd(struct ispsoftc *isp, XS_T *xs)
531 {
532           volatile uint8_t ombi;
533           int lim, chan;
534 
535           ISP_LOCK(isp);
536           if (isp->isp_state < ISP_RUNSTATE) {
537                     ISP_DISABLE_INTS(isp);
538                     isp_init(isp);
539                     if (isp->isp_state != ISP_INITSTATE) {
540                               ISP_ENABLE_INTS(isp);
541                               ISP_UNLOCK(isp);
542                               isp_prt(isp, ISP_LOGERR, "isp not at init state");
543                               XS_SETERR(xs, HBA_BOTCH);
544                               scsipi_done(xs);
545                               return;
546                     }
547                     isp->isp_state = ISP_RUNSTATE;
548                     ISP_ENABLE_INTS(isp);
549           }
550           chan = XS_CHANNEL(xs);
551 
552           /*
553            * Handle the case of a FC card where the FC thread hasn't
554            * fired up yet and we don't yet have a known loop state.
555            */
556           if (IS_FC(isp) && (FCPARAM(isp, chan)->isp_fwstate != FW_READY ||
557               FCPARAM(isp, chan)->isp_loopstate != LOOP_READY) &&
558               isp->isp_osinfo.thread == NULL) {
559                     ombi = isp->isp_osinfo.mbox_sleep_ok != 0;
560                     int delay_time;
561 
562                     if (xs->xs_control & XS_CTL_POLL) {
563                               isp->isp_osinfo.mbox_sleep_ok = 0;
564                     }
565 
566                     if (isp->isp_osinfo.loop_checked == 0) {
567                               delay_time = 10 * 1000000;
568                               isp->isp_osinfo.loop_checked = 1;
569                     } else {
570                               delay_time = 250000;
571                     }
572 
573                     if (isp_fc_runstate(isp,  XS_CHANNEL(xs), delay_time) != 0) {
574                               if (xs->xs_control & XS_CTL_POLL) {
575                                         isp->isp_osinfo.mbox_sleep_ok = ombi;
576                               }
577                               if (FCPARAM(isp, XS_CHANNEL(xs))->loop_seen_once == 0) {
578                                         XS_SETERR(xs, HBA_SELTIMEOUT);
579                                         scsipi_done(xs);
580                                         ISP_UNLOCK(isp);
581                                         return;
582                               }
583                               /*
584                                * Otherwise, fall thru to be queued up for later.
585                                */
586                     } else {
587                               int wasblocked =
588                                   (isp->isp_osinfo.blocked || isp->isp_osinfo.paused);
589                               isp->isp_osinfo.blocked = isp->isp_osinfo.paused = 0;
590                               if (wasblocked) {
591                                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
592                                             "THAW QUEUES @ LINE %d", __LINE__);
593                                         scsipi_channel_thaw(&isp->isp_osinfo.chan[chan],
594                                             1);
595                               }
596                     }
597                     if (xs->xs_control & XS_CTL_POLL) {
598                               isp->isp_osinfo.mbox_sleep_ok = ombi;
599                     }
600           }
601 
602           if (isp->isp_osinfo.paused) {
603                     isp_prt(isp, ISP_LOGWARN, "I/O while paused");
604                     xs->error = XS_RESOURCE_SHORTAGE;
605                     scsipi_done(xs);
606                     ISP_UNLOCK(isp);
607                     return;
608           }
609           if (isp->isp_osinfo.blocked) {
610                     isp_prt(isp, ISP_LOGWARN,
611                         "I/O while blocked with retries %d", xs->xs_retries);
612                     if (xs->xs_retries) {
613                               xs->error = XS_REQUEUE;
614                               xs->xs_retries--;
615                     } else {
616                               XS_SETERR(xs, HBA_SELTIMEOUT);
617                     }
618                     scsipi_done(xs);
619                     ISP_UNLOCK(isp);
620                     return;
621           }
622 
623           if (xs->xs_control & XS_CTL_POLL) {
624                     ombi = isp->isp_osinfo.mbox_sleep_ok;
625                     isp->isp_osinfo.mbox_sleep_ok = 0;
626           }
627 
628           switch (isp_start(xs)) {
629           case CMD_QUEUED:
630                     if (IS_FC(isp) && isp->isp_osinfo.wwns[XS_TGT(xs)] == 0) {
631                               fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs));
632                               int dbidx = fcp->isp_dev_map[XS_TGT(xs)] - 1;
633                               device_t dev = xs->xs_periph->periph_dev;
634 
635                               if (dbidx >= 0 && dev &&
636                                   prop_dictionary_set_uint64(device_properties(dev),
637                                   "port-wwn", fcp->portdb[dbidx].port_wwn) == TRUE) {
638                                         isp->isp_osinfo.wwns[XS_TGT(xs)] =
639                                             fcp->portdb[dbidx].port_wwn;
640                               }
641                 }
642                     if (xs->xs_control & XS_CTL_POLL) {
643                               isp_polled_cmd_wait(isp, xs);
644                               isp->isp_osinfo.mbox_sleep_ok = ombi;
645                     } else if (xs->timeout) {
646                               callout_reset(&xs->xs_callout, _XT(xs), isp_dog, xs);
647                     }
648                     break;
649           case CMD_EAGAIN:
650                     isp->isp_osinfo.paused = 1;
651                     xs->error = XS_RESOURCE_SHORTAGE;
652                     isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
653                         "FREEZE QUEUES @ LINE %d", __LINE__);
654                     for (chan = 0; chan < isp->isp_nchan; chan++) {
655                               scsipi_channel_freeze(&isp->isp_osinfo.chan[chan], 1);
656                     }
657                     scsipi_done(xs);
658                     break;
659           case CMD_RQLATER:
660                     /*
661                      * We can only get RQLATER from FC devices (1 channel only)
662                      *
663                      * If we've never seen loop up see if if we've been down
664                      * quickboot time, otherwise wait loop down limit time.
665                      * If so, then we start giving up on commands.
666                      */
667                     if (FCPARAM(isp, XS_CHANNEL(xs))->loop_seen_once == 0) {
668                               lim = isp_quickboot_time;
669                     } else {
670                               lim = isp->isp_osinfo.loop_down_limit;
671                     }
672                     if (isp->isp_osinfo.loop_down_time >= lim) {
673                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
674                                   "RQLATER->SELTIMEOUT for %d (%d >= %d)", XS_TGT(xs),
675                                   isp->isp_osinfo.loop_down_time, lim);
676                               XS_SETERR(xs, HBA_SELTIMEOUT);
677                               scsipi_done(xs);
678                               break;
679                     }
680                     if (isp->isp_osinfo.blocked == 0) {
681                               isp->isp_osinfo.blocked = 1;
682                               scsipi_channel_freeze(&isp->isp_osinfo.chan[chan], 1);
683                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
684                                   "FREEZE QUEUES @ LINE %d", __LINE__);
685                     } else {
686                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
687                                   "RQLATER WITH FROZEN QUEUES @ LINE %d", __LINE__);
688                     }
689                     xs->error = XS_REQUEUE;
690                     scsipi_done(xs);
691                     break;
692           case CMD_COMPLETE:
693                     scsipi_done(xs);
694                     break;
695           }
696           ISP_UNLOCK(isp);
697 }
698 
699 static void
isprequest(struct scsipi_channel * chan,scsipi_adapter_req_t req,void * arg)700 isprequest(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg)
701 {
702           struct ispsoftc *isp = device_private(chan->chan_adapter->adapt_dev);
703 
704           switch (req) {
705           case ADAPTER_REQ_RUN_XFER:
706                     ispcmd(isp, (XS_T *) arg);
707                     break;
708 
709           case ADAPTER_REQ_GROW_RESOURCES:
710                     /* Not supported. */
711                     break;
712 
713           case ADAPTER_REQ_SET_XFER_MODE:
714           if (IS_SCSI(isp)) {
715                     struct scsipi_xfer_mode *xm = arg;
716                     int dflags = 0;
717                     sdparam *sdp = SDPARAM(isp, chan->chan_channel);
718 
719                     if (xm->xm_mode & PERIPH_CAP_TQING)
720                               dflags |= DPARM_TQING;
721                     if (xm->xm_mode & PERIPH_CAP_WIDE16)
722                               dflags |= DPARM_WIDE;
723                     if (xm->xm_mode & PERIPH_CAP_SYNC)
724                               dflags |= DPARM_SYNC;
725                     ISP_LOCK(isp);
726                     sdp->isp_devparam[xm->xm_target].goal_flags |= dflags;
727                     dflags = sdp->isp_devparam[xm->xm_target].goal_flags;
728                     sdp->isp_devparam[xm->xm_target].dev_update = 1;
729                     sdp->update = 1;
730                     ISP_UNLOCK(isp);
731                     isp_prt(isp, ISP_LOGDEBUG1,
732                         "isprequest: device flags %#x for %d.%d.X",
733                         dflags, chan->chan_channel, xm->xm_target);
734                     break;
735           }
736           default:
737                     break;
738           }
739 }
740 
741 static void
isp_polled_cmd_wait(struct ispsoftc * isp,XS_T * xs)742 isp_polled_cmd_wait(struct ispsoftc *isp, XS_T *xs)
743 {
744           int infinite = 0, mswait;
745 
746           /*
747            * If we can't use interrupts, poll on completion.
748            */
749           if ((mswait = XS_TIME(xs)) == 0) {
750                     infinite = 1;
751           }
752 
753           while (mswait || infinite) {
754                     uint32_t isr;
755                     uint16_t sema, mbox;
756                     if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
757                               isp_intr(isp, isr, sema, mbox);
758                               if (XS_CMD_DONE_P(xs)) {
759                                         break;
760                               }
761                     }
762                     ISP_DELAY(1000);
763                     mswait -= 1;
764           }
765 
766           /*
767            * If no other error occurred but we didn't finish
768            * something bad happened, so abort the command.
769            */
770           if (XS_CMD_DONE_P(xs) == 0) {
771                     if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
772                               isp_reinit(isp, 0);
773                     }
774                     if (XS_NOERR(xs)) {
775                               isp_prt(isp, ISP_LOGERR, "polled command timed out");
776                               XS_SETERR(xs, HBA_BOTCH);
777                     }
778           }
779           scsipi_done(xs);
780 }
781 
782 void
isp_done(XS_T * xs)783 isp_done(XS_T *xs)
784 {
785           if (XS_CMD_WDOG_P(xs) == 0) {
786                     struct ispsoftc *isp = XS_ISP(xs);
787                     callout_stop(&xs->xs_callout);
788                     if (XS_CMD_GRACE_P(xs)) {
789                               isp_prt(isp, ISP_LOGDEBUG1,
790                                   "finished command on borrowed time");
791                     }
792                     XS_CMD_S_CLEAR(xs);
793                     /*
794                      * Fixup- if we get a QFULL, we need
795                      * to set XS_BUSY as the error.
796                      */
797                     if (xs->status == SCSI_QUEUE_FULL) {
798                               xs->error = XS_BUSY;
799                     }
800                     if (isp->isp_osinfo.paused) {
801                               int i;
802                               isp->isp_osinfo.paused = 0;
803                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
804                                   "THAW QUEUES @ LINE %d", __LINE__);
805                               for (i = 0; i < isp->isp_nchan; i++) {
806                                         scsipi_channel_timed_thaw(&isp->isp_osinfo.chan[i]);
807                               }
808                     }
809                     if (xs->error == XS_DRIVER_STUFFUP) {
810                               isp_prt(isp, ISP_LOGERR,
811                                   "BOTCHED cmd for %d.%d.%d cmd %#x datalen %ld",
812                                   XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs),
813                                   XS_CDBP(xs)[0], (long) XS_XFRLEN(xs));
814                     }
815                     scsipi_done(xs);
816           }
817 }
818 
819 static void
isp_dog(void * arg)820 isp_dog(void *arg)
821 {
822           XS_T *xs = arg;
823           struct ispsoftc *isp = XS_ISP(xs);
824           uint32_t handle;
825           int sok;
826 
827 
828           ISP_ILOCK(isp);
829           sok = isp->isp_osinfo.mbox_sleep_ok;
830           isp->isp_osinfo.mbox_sleep_ok = 0;
831           /*
832            * We've decided this command is dead. Make sure we're not trying
833            * to kill a command that's already dead by getting its handle and
834            * and seeing whether it's still alive.
835            */
836           handle = isp_find_handle(isp, xs);
837           if (handle) {
838                     uint32_t isr;
839                     uint16_t mbox, sema;
840 
841                     if (XS_CMD_DONE_P(xs)) {
842                               isp_prt(isp, ISP_LOGDEBUG1,
843                                   "watchdog found done cmd (handle %#x)", handle);
844                               goto out;
845                     }
846 
847                     if (XS_CMD_WDOG_P(xs)) {
848                               isp_prt(isp, ISP_LOGDEBUG1,
849                                   "recursive watchdog (handle %#x)", handle);
850                               goto out;
851                     }
852 
853                     XS_CMD_S_WDOG(xs);
854 
855                     if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
856                               isp_intr(isp, isr, sema, mbox);
857 
858                     }
859                     if (XS_CMD_DONE_P(xs)) {
860                               isp_prt(isp, ISP_LOGDEBUG1,
861                                   "watchdog cleanup for handle %#x", handle);
862                               XS_CMD_C_WDOG(xs);
863                               isp_done(xs);
864                     } else if (XS_CMD_GRACE_P(xs)) {
865                               isp_prt(isp, ISP_LOGDEBUG1,
866                                   "watchdog timeout for handle %#x", handle);
867                               /*
868                                * Make sure the command is *really* dead before we
869                                * release the handle (and DMA resources) for reuse.
870                                */
871                               (void) isp_control(isp, ISPCTL_ABORT_CMD, arg);
872 
873                               /*
874                                * After this point, the command is really dead.
875                                */
876                               if (XS_XFRLEN(xs)) {
877                                         ISP_DMAFREE(isp, xs, handle);
878                               }
879                               isp_destroy_handle(isp, handle);
880                               XS_SETERR(xs, XS_TIMEOUT);
881                               XS_CMD_S_CLEAR(xs);
882                               isp_done(xs);
883                     } else {
884                               void *qe;
885                               isp_marker_t local, *mp = &local;
886                               isp_prt(isp, ISP_LOGDEBUG2,
887                                   "possible command timeout on handle %x", handle);
888                               XS_CMD_C_WDOG(xs);
889                               callout_reset(&xs->xs_callout, hz, isp_dog, xs);
890                               qe = isp_getrqentry(isp);
891                               if (qe == NULL)
892                                         goto out;
893                               XS_CMD_S_GRACE(xs);
894                               ISP_MEMZERO((void *) mp, sizeof (*mp));
895                               mp->mrk_header.rqs_entry_count = 1;
896                               mp->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
897                               mp->mrk_modifier = SYNC_ALL;
898                               mp->mrk_target = XS_CHANNEL(xs) << 7;
899                               isp_put_marker(isp, mp, qe);
900                               ISP_SYNC_REQUEST(isp);
901                     }
902           } else {
903                     isp_prt(isp, ISP_LOGDEBUG0, "watchdog with no command");
904           }
905 out:
906           isp->isp_osinfo.mbox_sleep_ok = sok;
907           ISP_IUNLOCK(isp);
908 }
909 
910 /*
911  * Gone Device Timer Function- when we have decided that a device has gone
912  * away, we wait a specific period of time prior to telling the OS it has
913  * gone away.
914  *
915  * This timer function fires once a second and then scans the port database
916  * for devices that are marked dead but still have a virtual target assigned.
917  * We decrement a counter for that port database entry, and when it hits zero,
918  * we tell the OS the device has gone away.
919  */
920 static void
isp_gdt(void * arg)921 isp_gdt(void *arg)
922 {
923           ispsoftc_t *isp = arg;
924           fcportdb_t *lp;
925           int dbidx, tgt, more_to_do = 0;
926 
927           isp_prt(isp, ISP_LOGDEBUG0, "GDT timer expired");
928           ISP_LOCK(isp);
929           for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
930                     lp = &FCPARAM(isp, 0)->portdb[dbidx];
931 
932                     if (lp->state != FC_PORTDB_STATE_ZOMBIE) {
933                               continue;
934                     }
935                     if (lp->dev_map_idx == 0) {
936                               continue;
937                     }
938                     if (lp->new_reserved == 0) {
939                               continue;
940                     }
941                     lp->new_reserved -= 1;
942                     if (lp->new_reserved != 0) {
943                               more_to_do++;
944                               continue;
945                     }
946                     tgt = lp->dev_map_idx - 1;
947                     FCPARAM(isp, 0)->isp_dev_map[tgt] = 0;
948                     lp->dev_map_idx = 0;
949                     lp->state = FC_PORTDB_STATE_NIL;
950                     isp_prt(isp, ISP_LOGCONFIG, prom3, lp->portid, tgt,
951                         "Gone Device Timeout");
952                     isp_make_gone(isp, tgt);
953           }
954           if (more_to_do) {
955                     callout_schedule(&isp->isp_osinfo.gdt, hz);
956           } else {
957                     isp->isp_osinfo.gdt_running = 0;
958                     isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
959                         "stopping Gone Device Timer");
960           }
961           ISP_UNLOCK(isp);
962 }
963 
964 /*
965  * Loop Down Timer Function- when loop goes down, a timer is started and
966  * and after it expires we come here and take all probational devices that
967  * the OS knows about and the tell the OS that they've gone away.
968  *
969  * We don't clear the devices out of our port database because, when loop
970  * come back up, we have to do some actual cleanup with the chip at that
971  * point (implicit PLOGO, e.g., to get the chip's port database state right).
972  */
973 static void
isp_ldt(void * arg)974 isp_ldt(void *arg)
975 {
976           ispsoftc_t *isp = arg;
977           fcportdb_t *lp;
978           int dbidx, tgt;
979 
980           isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Loop Down Timer expired");
981           ISP_LOCK(isp);
982 
983           /*
984            * Notify to the OS all targets who we now consider have departed.
985            */
986           for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
987                     lp = &FCPARAM(isp, 0)->portdb[dbidx];
988 
989                     if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
990                               continue;
991                     }
992                     if (lp->dev_map_idx == 0) {
993                               continue;
994                     }
995 
996                     /*
997                      * XXX: CLEAN UP AND COMPLETE ANY PENDING COMMANDS FIRST!
998                      */
999 
1000                     /*
1001                      * Mark that we've announced that this device is gone....
1002                      */
1003                     lp->reserved = 1;
1004 
1005                     /*
1006                      * but *don't* change the state of the entry. Just clear
1007                      * any target id stuff and announce to CAM that the
1008                      * device is gone. This way any necessary PLOGO stuff
1009                      * will happen when loop comes back up.
1010                      */
1011 
1012                     tgt = lp->dev_map_idx - 1;
1013                     FCPARAM(isp, 0)->isp_dev_map[tgt] = 0;
1014                     lp->dev_map_idx = 0;
1015                     isp_prt(isp, ISP_LOGCONFIG, prom3, lp->portid, tgt,
1016                         "Loop Down Timeout");
1017                     isp_make_gone(isp, tgt);
1018           }
1019 
1020           /*
1021            * The loop down timer has expired. Wake up the kthread
1022            * to notice that fact (or make it false).
1023            */
1024           isp->isp_osinfo.loop_down_time = isp->isp_osinfo.loop_down_limit+1;
1025           wakeup(&isp->isp_osinfo.thread);
1026           ISP_UNLOCK(isp);
1027 }
1028 
1029 static void
isp_make_here(ispsoftc_t * isp,int tgt)1030 isp_make_here(ispsoftc_t *isp, int tgt)
1031 {
1032           isp_prt(isp, ISP_LOGINFO, "target %d has arrived", tgt);
1033 }
1034 
1035 static void
isp_make_gone(ispsoftc_t * isp,int tgt)1036 isp_make_gone(ispsoftc_t *isp, int tgt)
1037 {
1038           isp_prt(isp, ISP_LOGINFO, "target %d has departed", tgt);
1039 }
1040 
1041 static void
isp_fc_worker(void * arg)1042 isp_fc_worker(void *arg)
1043 {
1044           ispsoftc_t *isp = arg;
1045           int slp = 0;
1046           int chan = 0;
1047 
1048           int s = splbio();
1049           /*
1050            * The first loop is for our usage where we have yet to have
1051            * gotten good fibre channel state.
1052            */
1053           while (isp->isp_osinfo.thread != NULL) {
1054                     int sok, lb, lim;
1055 
1056                     isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "checking FC state");
1057                     sok = isp->isp_osinfo.mbox_sleep_ok;
1058                     isp->isp_osinfo.mbox_sleep_ok = 1;
1059                     lb = isp_fc_runstate(isp, chan, 250000);
1060                     isp->isp_osinfo.mbox_sleep_ok = sok;
1061                     if (lb) {
1062                               /*
1063                                * Increment loop down time by the last sleep interval
1064                                */
1065                               isp->isp_osinfo.loop_down_time += slp;
1066 
1067                               if (lb < 0) {
1068                                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1069                                             "FC loop not up (down count %d)",
1070                                             isp->isp_osinfo.loop_down_time);
1071                               } else {
1072                                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1073                                             "FC got to %d (down count %d)",
1074                                             lb, isp->isp_osinfo.loop_down_time);
1075                               }
1076 
1077 
1078                               /*
1079                                * If we've never seen loop up and we've waited longer
1080                                * than quickboot time, or we've seen loop up but we've
1081                                * waited longer than loop_down_limit, give up and go
1082                                * to sleep until loop comes up.
1083                                */
1084                               if (FCPARAM(isp, 0)->loop_seen_once == 0) {
1085                                         lim = isp_quickboot_time;
1086                               } else {
1087                                         lim = isp->isp_osinfo.loop_down_limit;
1088                               }
1089                               if (isp->isp_osinfo.loop_down_time >= lim) {
1090                                         /*
1091                                          * If we're now past our limit, release
1092                                          * the queues and let them come in and
1093                                          * either get HBA_SELTIMEOUT or cause
1094                                          * another freeze.
1095                                          */
1096                                         isp->isp_osinfo.blocked = 1;
1097                                         slp = 0;
1098                               } else if (isp->isp_osinfo.loop_down_time < 10) {
1099                                         slp = 1;
1100                               } else if (isp->isp_osinfo.loop_down_time < 30) {
1101                                         slp = 5;
1102                               } else if (isp->isp_osinfo.loop_down_time < 60) {
1103                                         slp = 10;
1104                               } else if (isp->isp_osinfo.loop_down_time < 120) {
1105                                         slp = 20;
1106                               } else {
1107                                         slp = 30;
1108                               }
1109 
1110                     } else {
1111                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1112                                   "FC state OK");
1113                               isp->isp_osinfo.loop_down_time = 0;
1114                               slp = 0;
1115                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1116                                   "THAW QUEUES @ LINE %d", __LINE__);
1117                               scsipi_channel_thaw(&isp->isp_osinfo.chan[chan], 1);
1118                     }
1119 
1120                     /*
1121                      * If we'd frozen the queues, unfreeze them now so that
1122                      * we can start getting commands. If the FC state isn't
1123                      * okay yet, they'll hit that in isp_start which will
1124                      * freeze the queues again.
1125                      */
1126                     if (isp->isp_osinfo.blocked) {
1127                               isp->isp_osinfo.blocked = 0;
1128                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1129                                   "THAW QUEUES @ LINE %d", __LINE__);
1130                               scsipi_channel_thaw(&isp->isp_osinfo.chan[chan], 1);
1131                     }
1132                     isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "sleep time %d", slp);
1133                     tsleep(&isp->isp_osinfo.thread, PRIBIO, "ispf", slp * hz);
1134 
1135                     /*
1136                      * If slp is zero, we're waking up for the first time after
1137                      * things have been okay. In this case, we set a deferral state
1138                      * for all commands and delay hysteresis seconds before starting
1139                      * the FC state evaluation. This gives the loop/fabric a chance
1140                      * to settle.
1141                      */
1142                     if (slp == 0 && isp_fabric_hysteresis) {
1143                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1144                                   "sleep hysteresis tick time %d",
1145                                   isp_fabric_hysteresis * hz);
1146                               (void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT",
1147                                   (isp_fabric_hysteresis * hz));
1148                     }
1149           }
1150           splx(s);
1151 
1152           /* In case parent is waiting for us to exit. */
1153           wakeup(&isp->isp_osinfo.thread);
1154           kthread_exit(0);
1155 }
1156 
1157 /*
1158  * Free any associated resources prior to decommissioning and
1159  * set the card to a known state (so it doesn't wake up and kick
1160  * us when we aren't expecting it to).
1161  *
1162  * Locks are held before coming here.
1163  */
1164 void
isp_uninit(struct ispsoftc * isp)1165 isp_uninit(struct ispsoftc *isp)
1166 {
1167           isp_lock(isp);
1168           /*
1169            * Leave with interrupts disabled.
1170            */
1171           ISP_DISABLE_INTS(isp);
1172           isp_unlock(isp);
1173 }
1174 
1175 void
isp_async(struct ispsoftc * isp,ispasync_t cmd,...)1176 isp_async(struct ispsoftc *isp, ispasync_t cmd, ...)
1177 {
1178           int bus, tgt;
1179           const char *msg = NULL;
1180           static const char prom[] =
1181               "PortID %#06x handle %#x role %s %s\n"
1182               "      WWNN %#08x%08x WWPN %#08x%08x";
1183           static const char prom2[] =
1184               "PortID %#06x handle %#x role %s %s tgt %u\n"
1185               "      WWNN %#08x%08x WWPN %#08x%08x";
1186           fcportdb_t *lp;
1187           va_list ap;
1188 
1189           switch (cmd) {
1190           case ISPASYNC_NEW_TGT_PARAMS:
1191           if (IS_SCSI(isp)) {
1192                     sdparam *sdp;
1193                     int flags;
1194                     struct scsipi_xfer_mode xm;
1195 
1196                     va_start(ap, cmd);
1197                     bus = va_arg(ap, int);
1198                     tgt = va_arg(ap, int);
1199                     va_end(ap);
1200                     sdp = SDPARAM(isp, bus);
1201                     flags = sdp->isp_devparam[tgt].actv_flags;
1202 
1203                     xm.xm_mode = 0;
1204                     xm.xm_period = sdp->isp_devparam[tgt].actv_period;
1205                     xm.xm_offset = sdp->isp_devparam[tgt].actv_offset;
1206                     xm.xm_target = tgt;
1207 
1208                     if ((flags & DPARM_SYNC) && xm.xm_period && xm.xm_offset)
1209                               xm.xm_mode |= PERIPH_CAP_SYNC;
1210                     if (flags & DPARM_WIDE)
1211                               xm.xm_mode |= PERIPH_CAP_WIDE16;
1212                     if (flags & DPARM_TQING)
1213                               xm.xm_mode |= PERIPH_CAP_TQING;
1214                     scsipi_async_event(&isp->isp_osinfo.chan[bus],
1215                         ASYNC_EVENT_XFER_MODE, &xm);
1216                     break;
1217           }
1218           /* FALLTHROUGH */
1219           case ISPASYNC_BUS_RESET:
1220                     va_start(ap, cmd);
1221                     bus = va_arg(ap, int);
1222                     va_end(ap);
1223                     isp_prt(isp, ISP_LOGINFO, "SCSI bus %d reset detected", bus);
1224                     scsipi_async_event(&isp->isp_osinfo.chan[bus],
1225                         ASYNC_EVENT_RESET, NULL);
1226                     break;
1227           case ISPASYNC_LIP:
1228                     if (msg == NULL) {
1229                               msg = "LIP Received";
1230                     }
1231                     /* FALLTHROUGH */
1232           case ISPASYNC_LOOP_RESET:
1233                     if (msg == NULL) {
1234                               msg = "LOOP Reset Received";
1235                     }
1236                     /* FALLTHROUGH */
1237           case ISPASYNC_LOOP_DOWN:
1238                     if (msg == NULL) {
1239                               msg = "Loop DOWN";
1240                     }
1241                     va_start(ap, cmd);
1242                     bus = va_arg(ap, int);
1243                     va_end(ap);
1244 
1245                     /*
1246                      * Don't do queue freezes or blockage until we have the
1247                      * thread running and interrupts that can unfreeze/unblock us.
1248                      */
1249                     if (isp->isp_osinfo.mbox_sleep_ok &&
1250                         isp->isp_osinfo.blocked == 0 &&
1251                         isp->isp_osinfo.thread) {
1252                               isp->isp_osinfo.blocked = 1;
1253                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1254                                   "FREEZE QUEUES @ LINE %d", __LINE__);
1255                               scsipi_channel_freeze(&isp->isp_osinfo.chan[bus], 1);
1256                               if (callout_pending(&isp->isp_osinfo.ldt) == 0) {
1257                                         callout_schedule(&isp->isp_osinfo.ldt,
1258                                             isp->isp_osinfo.loop_down_limit * hz);
1259                                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1260                                            "Starting Loop Down Timer");
1261                               }
1262                     }
1263                     isp_prt(isp, ISP_LOGINFO, "%s", msg);
1264                     break;
1265         case ISPASYNC_LOOP_UP:
1266                     /*
1267                      * Let the subsequent ISPASYNC_CHANGE_NOTIFY invoke
1268                      * the FC worker thread. When the FC worker thread
1269                      * is done, let *it* call scsipi_channel_thaw...
1270                      */
1271                     isp_prt(isp, ISP_LOGINFO, "Loop UP");
1272                     break;
1273           case ISPASYNC_DEV_ARRIVED:
1274                     va_start(ap, cmd);
1275                     bus = va_arg(ap, int);
1276                     lp = va_arg(ap, fcportdb_t *);
1277                     va_end(ap);
1278                     lp->reserved = 0;
1279                     if ((FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) &&
1280                         (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) {
1281                               int dbidx = lp - FCPARAM(isp, bus)->portdb;
1282                               int i;
1283 
1284                               for (i = 0; i < MAX_FC_TARG; i++) {
1285                                         if (i >= FL_ID && i <= SNS_ID) {
1286                                                   continue;
1287                                         }
1288                                         if (FCPARAM(isp, bus)->isp_dev_map[i] == 0) {
1289                                                   break;
1290                                         }
1291                               }
1292                               if (i < MAX_FC_TARG) {
1293                                         FCPARAM(isp, bus)->isp_dev_map[i] = dbidx + 1;
1294                                         lp->dev_map_idx = i + 1;
1295                               } else {
1296                                         isp_prt(isp, ISP_LOGWARN, "out of target ids");
1297                                         isp_dump_portdb(isp, bus);
1298                               }
1299                     }
1300                     if (lp->dev_map_idx) {
1301                               tgt = lp->dev_map_idx - 1;
1302                               isp_prt(isp, ISP_LOGCONFIG, prom2,
1303                                   lp->portid, lp->handle,
1304                                 roles[lp->roles], "arrived at", tgt,
1305                                   (uint32_t) (lp->node_wwn >> 32),
1306                                   (uint32_t) lp->node_wwn,
1307                                   (uint32_t) (lp->port_wwn >> 32),
1308                                   (uint32_t) lp->port_wwn);
1309                               isp_make_here(isp, tgt);
1310                     } else {
1311                               isp_prt(isp, ISP_LOGCONFIG, prom,
1312                                   lp->portid, lp->handle,
1313                                 roles[lp->roles], "arrived",
1314                                   (uint32_t) (lp->node_wwn >> 32),
1315                                   (uint32_t) lp->node_wwn,
1316                                   (uint32_t) (lp->port_wwn >> 32),
1317                                   (uint32_t) lp->port_wwn);
1318                     }
1319                     break;
1320           case ISPASYNC_DEV_CHANGED:
1321                     va_start(ap, cmd);
1322                     bus = va_arg(ap, int);
1323                     lp = va_arg(ap, fcportdb_t *);
1324                     va_end(ap);
1325                     if (isp_change_is_bad) {
1326                               lp->state = FC_PORTDB_STATE_NIL;
1327                               if (lp->dev_map_idx) {
1328                                         tgt = lp->dev_map_idx - 1;
1329                                         FCPARAM(isp, bus)->isp_dev_map[tgt] = 0;
1330                                         lp->dev_map_idx = 0;
1331                                         isp_prt(isp, ISP_LOGCONFIG, prom3,
1332                                             lp->portid, tgt, "change is bad");
1333                                         isp_make_gone(isp, tgt);
1334                               } else {
1335                                         isp_prt(isp, ISP_LOGCONFIG, prom,
1336                                             lp->portid, lp->handle,
1337                                             roles[lp->roles],
1338                                             "changed and departed",
1339                                             (uint32_t) (lp->node_wwn >> 32),
1340                                             (uint32_t) lp->node_wwn,
1341                                             (uint32_t) (lp->port_wwn >> 32),
1342                                             (uint32_t) lp->port_wwn);
1343                               }
1344                     } else {
1345                               lp->portid = lp->new_portid;
1346                               lp->roles = lp->new_roles;
1347                               if (lp->dev_map_idx) {
1348                                         int t = lp->dev_map_idx - 1;
1349                                         FCPARAM(isp, bus)->isp_dev_map[t] =
1350                                             (lp - FCPARAM(isp, bus)->portdb) + 1;
1351                                         tgt = lp->dev_map_idx - 1;
1352                                         isp_prt(isp, ISP_LOGCONFIG, prom2,
1353                                             lp->portid, lp->handle,
1354                                             roles[lp->roles], "changed at", tgt,
1355                                             (uint32_t) (lp->node_wwn >> 32),
1356                                             (uint32_t) lp->node_wwn,
1357                                             (uint32_t) (lp->port_wwn >> 32),
1358                                             (uint32_t) lp->port_wwn);
1359                               } else {
1360                                         isp_prt(isp, ISP_LOGCONFIG, prom,
1361                                             lp->portid, lp->handle,
1362                                             roles[lp->roles], "changed",
1363                                             (uint32_t) (lp->node_wwn >> 32),
1364                                             (uint32_t) lp->node_wwn,
1365                                             (uint32_t) (lp->port_wwn >> 32),
1366                                             (uint32_t) lp->port_wwn);
1367                               }
1368                     }
1369                     break;
1370           case ISPASYNC_DEV_STAYED:
1371                     va_start(ap, cmd);
1372                     bus = va_arg(ap, int);
1373                     lp = va_arg(ap, fcportdb_t *);
1374                     va_end(ap);
1375                     if (lp->dev_map_idx) {
1376                               tgt = lp->dev_map_idx - 1;
1377                               isp_prt(isp, ISP_LOGCONFIG, prom2,
1378                                   lp->portid, lp->handle,
1379                                   roles[lp->roles], "stayed at", tgt,
1380                                   (uint32_t) (lp->node_wwn >> 32),
1381                                   (uint32_t) lp->node_wwn,
1382                                   (uint32_t) (lp->port_wwn >> 32),
1383                                   (uint32_t) lp->port_wwn);
1384                     } else {
1385                               isp_prt(isp, ISP_LOGCONFIG, prom,
1386                                   lp->portid, lp->handle,
1387                                   roles[lp->roles], "stayed",
1388                                   (uint32_t) (lp->node_wwn >> 32),
1389                                   (uint32_t) lp->node_wwn,
1390                                   (uint32_t) (lp->port_wwn >> 32),
1391                                   (uint32_t) lp->port_wwn);
1392                     }
1393                     break;
1394           case ISPASYNC_DEV_GONE:
1395                     va_start(ap, cmd);
1396                     bus = va_arg(ap, int);
1397                     lp = va_arg(ap, fcportdb_t *);
1398                     va_end(ap);
1399                     /*
1400                      * If this has a virtual target and we haven't marked it
1401                      * that we're going to have isp_gdt tell the OS it's gone,
1402                      * set the isp_gdt timer running on it.
1403                      *
1404                      * If it isn't marked that isp_gdt is going to get rid of it,
1405                      * announce that it's gone.
1406                      */
1407                     if (lp->dev_map_idx && lp->reserved == 0) {
1408                               lp->reserved = 1;
1409                               lp->new_reserved = isp->isp_osinfo.gone_device_time;
1410                               lp->state = FC_PORTDB_STATE_ZOMBIE;
1411                               if (isp->isp_osinfo.gdt_running == 0) {
1412                                         isp->isp_osinfo.gdt_running = 1;
1413                                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1414                                             "starting Gone Device Timer");
1415                                         callout_schedule(&isp->isp_osinfo.gdt, hz);
1416                               }
1417                               tgt = lp->dev_map_idx - 1;
1418                               isp_prt(isp, ISP_LOGCONFIG, prom2,
1419                                   lp->portid, lp->handle,
1420                                 roles[lp->roles], "gone zombie at", tgt,
1421                                   (uint32_t) (lp->node_wwn >> 32),
1422                                   (uint32_t) lp->node_wwn,
1423                                   (uint32_t) (lp->port_wwn >> 32),
1424                                   (uint32_t) lp->port_wwn);
1425                     } else if (lp->reserved == 0) {
1426                               isp_prt(isp, ISP_LOGCONFIG, prom,
1427                                   lp->portid, lp->handle,
1428                                   roles[lp->roles], "departed",
1429                                   (uint32_t) (lp->node_wwn >> 32),
1430                                   (uint32_t) lp->node_wwn,
1431                                   (uint32_t) (lp->port_wwn >> 32),
1432                                   (uint32_t) lp->port_wwn);
1433                     }
1434                     break;
1435           case ISPASYNC_CHANGE_NOTIFY:
1436           {
1437                     int opt;
1438 
1439                     va_start(ap, cmd);
1440                     bus = va_arg(ap, int);
1441                     opt = va_arg(ap, int);
1442                     va_end(ap);
1443 
1444                     if (opt == ISPASYNC_CHANGE_PDB) {
1445                               msg = "Port Database Changed";
1446                     } else if (opt == ISPASYNC_CHANGE_SNS) {
1447                               msg = "Name Server Database Changed";
1448                     } else {
1449                               msg = "Other Change Notify";
1450                     }
1451                     /*
1452                      * If the loop down timer is running, cancel it.
1453                      */
1454                     if (callout_pending(&isp->isp_osinfo.ldt)) {
1455                               callout_stop(&isp->isp_osinfo.ldt);
1456                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1457                                  "Stopping Loop Down Timer");
1458                     }
1459                     isp_prt(isp, ISP_LOGINFO, "%s", msg);
1460                     /*
1461                      * We can set blocked here because we know it's now okay
1462                      * to try and run isp_fc_runstate (in order to build loop
1463                      * state). But we don't try and freeze the midlayer's queue
1464                      * if we have no thread that we can wake to later unfreeze
1465                      * it.
1466                      */
1467                     if (isp->isp_osinfo.blocked == 0) {
1468                               isp->isp_osinfo.blocked = 1;
1469                               if (isp->isp_osinfo.thread) {
1470                                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1471                                             "FREEZE QUEUES @ LINE %d", __LINE__);
1472                                         scsipi_channel_freeze(&isp->isp_osinfo.chan[bus], 1);
1473                               }
1474                     }
1475                     /*
1476                      * Note that we have work for the thread to do, and
1477                      * if the thread is here already, wake it up.
1478                      */
1479                     if (isp->isp_osinfo.thread) {
1480                               wakeup(&isp->isp_osinfo.thread);
1481                     } else {
1482                               isp_prt(isp, ISP_LOGDEBUG1, "no FC thread yet");
1483                     }
1484                     break;
1485           }
1486           case ISPASYNC_FW_CRASH:
1487           {
1488                     uint16_t mbox1;
1489                     mbox1 = ISP_READ(isp, OUTMAILBOX1);
1490                     if (IS_DUALBUS(isp)) {
1491                               bus = ISP_READ(isp, OUTMAILBOX6);
1492                     } else {
1493                               bus = 0;
1494                     }
1495                 isp_prt(isp, ISP_LOGERR,
1496                     "Internal Firmware Error on bus %d @ RISC Address %#x",
1497                     bus, mbox1);
1498                     if (IS_FC(isp)) {
1499                               if (isp->isp_osinfo.blocked == 0) {
1500                                         isp->isp_osinfo.blocked = 1;
1501                                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
1502                                             "FREEZE QUEUES @ LINE %d", __LINE__);
1503                                         scsipi_channel_freeze(&isp->isp_osinfo.chan[bus], 1);
1504                               }
1505                     }
1506                     mbox1 = isp->isp_osinfo.mbox_sleep_ok;
1507                     isp->isp_osinfo.mbox_sleep_ok = 0;
1508                     isp_reinit(isp, 0);
1509                     isp->isp_osinfo.mbox_sleep_ok = mbox1;
1510                     isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
1511                     break;
1512           }
1513           default:
1514                     break;
1515           }
1516 }
1517 
1518 void
isp_prt(struct ispsoftc * isp,int level,const char * fmt,...)1519 isp_prt(struct ispsoftc *isp, int level, const char *fmt, ...)
1520 {
1521           va_list ap;
1522           if (level != ISP_LOGALL && (level & isp->isp_dblev) == 0) {
1523                     return;
1524           }
1525           printf("%s: ", device_xname(isp->isp_osinfo.dev));
1526           va_start(ap, fmt);
1527           vprintf(fmt, ap);
1528           va_end(ap);
1529           printf("\n");
1530 }
1531 
1532 void
isp_xs_prt(struct ispsoftc * isp,XS_T * xs,int level,const char * fmt,...)1533 isp_xs_prt(struct ispsoftc *isp, XS_T *xs, int level, const char *fmt, ...)
1534 {
1535           va_list ap;
1536           if (level != ISP_LOGALL && (level & isp->isp_dblev) == 0) {
1537                     return;
1538           }
1539           scsipi_printaddr(xs->xs_periph);
1540           va_start(ap, fmt);
1541           vprintf(fmt, ap);
1542           va_end(ap);
1543           printf("\n");
1544 }
1545 
1546 void
isp_lock(struct ispsoftc * isp)1547 isp_lock(struct ispsoftc *isp)
1548 {
1549           int s = splbio();
1550           if (isp->isp_osinfo.islocked++ == 0) {
1551                     isp->isp_osinfo.splsaved = s;
1552           } else {
1553                     splx(s);
1554           }
1555 }
1556 
1557 void
isp_unlock(struct ispsoftc * isp)1558 isp_unlock(struct ispsoftc *isp)
1559 {
1560           if (isp->isp_osinfo.islocked-- <= 1) {
1561                     isp->isp_osinfo.islocked = 0;
1562                     splx(isp->isp_osinfo.splsaved);
1563           }
1564 }
1565 
1566 uint64_t
isp_microtime_sub(struct timeval * b,struct timeval * a)1567 isp_microtime_sub(struct timeval *b, struct timeval *a)
1568 {
1569           struct timeval x;
1570           uint64_t elapsed;
1571           timersub(b, a, &x);
1572           elapsed = GET_NANOSEC(&x);
1573           if (elapsed == 0)
1574                     elapsed++;
1575           return (elapsed);
1576 }
1577 
1578 int
isp_mbox_acquire(ispsoftc_t * isp)1579 isp_mbox_acquire(ispsoftc_t *isp)
1580 {
1581           if (isp->isp_osinfo.mboxbsy) {
1582                     return (1);
1583           } else {
1584                     isp->isp_osinfo.mboxcmd_done = 0;
1585                     isp->isp_osinfo.mboxbsy = 1;
1586                     return (0);
1587           }
1588 }
1589 
1590 void
isp_mbox_wait_complete(struct ispsoftc * isp,mbreg_t * mbp)1591 isp_mbox_wait_complete(struct ispsoftc *isp, mbreg_t *mbp)
1592 {
1593           unsigned int usecs = mbp->timeout;
1594           unsigned int maxc, olim, ilim;
1595           struct timeval start;
1596 
1597           if (usecs == 0) {
1598                     usecs = MBCMD_DEFAULT_TIMEOUT;
1599           }
1600           maxc = isp->isp_mbxwrk0 + 1;
1601 
1602           microtime(&start);
1603           if (isp->isp_osinfo.mbox_sleep_ok) {
1604                     int to;
1605                     struct timeval tv, utv;
1606 
1607                     tv.tv_sec = 0;
1608                     tv.tv_usec = 0;
1609                     for (olim = 0; olim < maxc; olim++) {
1610                               utv.tv_sec = usecs / 1000000;
1611                               utv.tv_usec = usecs % 1000000;
1612                               timeradd(&tv, &utv, &tv);
1613                     }
1614                     to = tvtohz(&tv);
1615                     if (to == 0)
1616                               to = 1;
1617                     timeradd(&tv, &start, &tv);
1618 
1619                     isp->isp_osinfo.mbox_sleep_ok = 0;
1620                     isp->isp_osinfo.mbox_sleeping = 1;
1621                     tsleep(&isp->isp_mbxworkp, PRIBIO, "ispmbx_sleep", to);
1622                     isp->isp_osinfo.mbox_sleeping = 0;
1623                     isp->isp_osinfo.mbox_sleep_ok = 1;
1624           } else {
1625                     for (olim = 0; olim < maxc; olim++) {
1626                               for (ilim = 0; ilim < usecs; ilim += 100) {
1627                                         uint32_t isr;
1628                                         uint16_t sema, mbox;
1629                                         if (isp->isp_osinfo.mboxcmd_done) {
1630                                                   break;
1631                                         }
1632                                         if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
1633                                                   isp_intr(isp, isr, sema, mbox);
1634                                                   if (isp->isp_osinfo.mboxcmd_done) {
1635                                                             break;
1636                                                   }
1637                                         }
1638                                         ISP_DELAY(100);
1639                               }
1640                               if (isp->isp_osinfo.mboxcmd_done) {
1641                                         break;
1642                               }
1643                     }
1644           }
1645           if (isp->isp_osinfo.mboxcmd_done == 0) {
1646                     struct timeval finish, elapsed;
1647 
1648                     microtime(&finish);
1649                     timersub(&finish, &start, &elapsed);
1650                     isp_prt(isp, ISP_LOGWARN,
1651                         "%s Mailbox Command (%#x) Timeout (%juus actual)",
1652                         isp->isp_osinfo.mbox_sleep_ok? "Interrupting" : "Polled",
1653                         isp->isp_lastmbxcmd, (intmax_t)(elapsed.tv_sec * 1000000) +
1654                         elapsed.tv_usec);
1655                     mbp->param[0] = MBOX_TIMEOUT;
1656                     isp->isp_osinfo.mboxcmd_done = 1;
1657           }
1658 }
1659 
1660 void
isp_mbox_notify_done(ispsoftc_t * isp)1661 isp_mbox_notify_done(ispsoftc_t *isp)
1662 {
1663           if (isp->isp_osinfo.mbox_sleeping) {
1664                     wakeup(&isp->isp_mbxworkp);
1665           }
1666           isp->isp_osinfo.mboxcmd_done = 1;
1667 }
1668 
1669 void
isp_mbox_release(ispsoftc_t * isp)1670 isp_mbox_release(ispsoftc_t *isp)
1671 {
1672           isp->isp_osinfo.mboxbsy = 0;
1673 }
1674