xref: /dragonfly/sys/dev/disk/isp/isp_freebsd.c (revision 944cd60c7b4392d637be82be7baafe9ac12a3061)
1 /*-
2  * Copyright (c) 1997-2009 by Matthew Jacob
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice immediately at the beginning of the file, without modification,
10  *    this list of conditions, and the following disclaimer.
11  * 2. The name of the author may not be used to endorse or promote products
12  *    derived from this software without specific prior written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sys/dev/isp/isp_freebsd.c,v 1.176 2011/11/06 00:44:40 mjacob Exp $
27  */
28 
29 /*
30  * Platform (FreeBSD) dependent common attachment code for Qlogic adapters.
31  */
32 #include <dev/disk/isp/isp_freebsd.h>
33 #include <sys/unistd.h>
34 #include <sys/kthread.h>
35 #include <sys/conf.h>
36 #include <sys/module.h>
37 #include <dev/disk/isp/isp_ioctl.h>
38 #include <bus/cam/cam_periph.h>
39 #include <bus/cam/cam_xpt_periph.h>
40 #include <sys/device.h>
41 
42 #define   THREAD_CREATE       kthread_create
43 
44 MODULE_VERSION(isp, 1);
45 MODULE_DEPEND(isp, cam, 1, 1, 1);
46 int isp_announced = 0;
47 int isp_fabric_hysteresis = 5;
48 int isp_loop_down_limit = 60; /* default loop down limit */
49 int isp_change_is_bad = 0;    /* "changed" devices are bad */
50 int isp_quickboot_time = 7;   /* don't wait more than N secs for loop up */
51 int isp_gone_device_time = 30;          /* grace time before reporting device lost */
52 int isp_autoconfig = 1;                 /* automatically attach/detach devices */
53 static const char *roles[4] = {
54     "(none)", "Target", "Initiator", "Target/Initiator"
55 };
56 static const char prom3[] = "Chan %d PortID 0x%06x Departed from Target %u because of %s";
57 #ifdef ISP_TARGET_MODE
58 static const char rqo[] = "%s: Request Queue Overflow\n";
59 #endif
60 
61 static void isp_freeze_loopdown(ispsoftc_t *, int, char *);
62 static d_ioctl_t ispioctl;
63 static void isp_intr_enable(void *);
64 static void isp_cam_async(void *, uint32_t, struct cam_path *, void *);
65 static void isp_poll(struct cam_sim *);
66 static timeout_t isp_watchdog;
67 static timeout_t isp_gdt;
68 static task_fn_t isp_gdt_task;
69 static timeout_t isp_ldt;
70 static task_fn_t isp_ldt_task;
71 static void isp_kthread(void *);
72 static void isp_action(struct cam_sim *, union ccb *);
73 #ifdef    ISP_INTERNAL_TARGET
74 static void isp_target_thread_pi(void *);
75 static void isp_target_thread_fc(void *);
76 #endif
77 static void isp_timer(void *);
78 
79 static struct dev_ops isp_ops = {
80           { "isp", 0, D_MPSAFE },
81           .d_ioctl =          ispioctl,
82 };
83 
84 static int
isp_attach_chan(ispsoftc_t * isp,struct cam_devq * devq,int chan)85 isp_attach_chan(ispsoftc_t *isp, struct cam_devq *devq, int chan)
86 {
87           struct ccb_setasync *csa;
88           struct cam_sim *sim;
89           struct cam_path *path;
90 
91           /*
92            * Construct our SIM entry.
93            */
94           sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp, device_get_unit(isp->isp_dev), &isp->isp_osinfo.lock, isp->isp_maxcmds, isp->isp_maxcmds, devq);
95           cam_simq_release(devq);
96 
97           if (sim == NULL) {
98                     return (ENOMEM);
99           }
100 
101           ISP_LOCK(isp);
102           if (xpt_bus_register(sim, chan) != CAM_SUCCESS) {
103                     ISP_UNLOCK(isp);
104                     cam_sim_free(sim);
105                     return (EIO);
106           }
107           ISP_UNLOCK(isp);
108           if (xpt_create_path_unlocked(&path, NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
109                     ISP_LOCK(isp);
110                     xpt_bus_deregister(cam_sim_path(sim));
111                     ISP_UNLOCK(isp);
112                     cam_sim_free(sim);
113                     return (ENXIO);
114           }
115           csa = &xpt_alloc_ccb()->csa;
116           xpt_setup_ccb(&csa->ccb_h, path, 5);
117           csa->ccb_h.func_code = XPT_SASYNC_CB;
118           csa->event_enable = AC_LOST_DEVICE;
119           csa->callback = isp_cam_async;
120           csa->callback_arg = sim;
121           xpt_action((union ccb *)csa);
122           xpt_free_ccb(&csa->ccb_h);
123 
124           if (IS_SCSI(isp)) {
125                     struct isp_spi *spi = ISP_SPI_PC(isp, chan);
126                     spi->sim = sim;
127                     spi->path = path;
128 #ifdef    ISP_INTERNAL_TARGET
129                     ISP_SET_PC(isp, chan, proc_active, 1);
130                     if (THREAD_CREATE(isp_target_thread_pi, spi, &spi->target_proc, "%s: isp_test_tgt%d", device_get_nameunit(isp->isp_osinfo.dev), chan)) {
131                               ISP_SET_PC(isp, chan, proc_active, 0);
132                               isp_prt(isp, ISP_LOGERR, "cannot create test target thread");
133                     }
134 #endif
135           } else {
136                     fcparam *fcp = FCPARAM(isp, chan);
137                     struct isp_fc *fc = ISP_FC_PC(isp, chan);
138 
139                     ISP_LOCK(isp);
140                     fc->sim = sim;
141                     fc->path = path;
142                     fc->isp = isp;
143                     fc->ready = 1;
144 
145                     callout_init(&fc->ldt);
146                     callout_init(&fc->gdt);
147                     TASK_INIT(&fc->ltask, 1, isp_ldt_task, fc);
148                     TASK_INIT(&fc->gtask, 1, isp_gdt_task, fc);
149 
150                     /*
151                      * We start by being "loop down" if we have an initiator role
152                      */
153                     if (fcp->role & ISP_ROLE_INITIATOR) {
154                               isp_freeze_loopdown(isp, chan, "isp_attach");
155                               callout_reset(&fc->ldt, isp_quickboot_time * hz, isp_ldt, fc);
156                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Starting Initial Loop Down Timer @ %lu", (unsigned long) time_second);
157                     }
158                     ISP_UNLOCK(isp);
159                     if (THREAD_CREATE(isp_kthread, fc, &fc->kthread, "%s: fc_thrd%d", device_get_nameunit(isp->isp_osinfo.dev), chan)) {
160                               xpt_free_path(fc->path);
161                               ISP_LOCK(isp);
162                               if (callout_active(&fc->ldt)) {
163                                         callout_stop(&fc->ldt);
164                               }
165                               xpt_bus_deregister(cam_sim_path(fc->sim));
166                               ISP_UNLOCK(isp);
167                               cam_sim_free(fc->sim);
168                               return (ENOMEM);
169                     }
170 #ifdef    ISP_INTERNAL_TARGET
171                     ISP_SET_PC(isp, chan, proc_active, 1);
172                     if (THREAD_CREATE(isp_target_thread_fc, fc, &fc->target_proc, "%s: isp_test_tgt%d", device_get_nameunit(isp->isp_osinfo.dev), chan)) {
173                               ISP_SET_PC(isp, chan, proc_active, 0);
174                               isp_prt(isp, ISP_LOGERR, "cannot create test target thread");
175                     }
176 #endif
177                     if (chan == 0) {
178                               struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(isp->isp_osinfo.dev);
179                               struct sysctl_oid *tree = device_get_sysctl_tree(isp->isp_osinfo.dev);
180                               SYSCTL_ADD_QUAD(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "wwnn", CTLFLAG_RD, &FCPARAM(isp, 0)->isp_wwnn, 0, "World Wide Node Name");
181                               SYSCTL_ADD_QUAD(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "wwpn", CTLFLAG_RD, &FCPARAM(isp, 0)->isp_wwpn, 0, "World Wide Port Name");
182                               SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "loop_down_limit", CTLFLAG_RW, &ISP_FC_PC(isp, 0)->loop_down_limit, 0, "Loop Down Limit");
183                               SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "gone_device_time", CTLFLAG_RW, &ISP_FC_PC(isp, 0)->gone_device_time, 0, "Gone Device Time");
184                     }
185           }
186           return (0);
187 }
188 
189 int
isp_attach(ispsoftc_t * isp)190 isp_attach(ispsoftc_t *isp)
191 {
192           const char *nu = device_get_nameunit(isp->isp_osinfo.dev);
193           int du = device_get_unit(isp->isp_dev);
194           int chan;
195 
196           isp->isp_osinfo.ehook.ich_func = isp_intr_enable;
197           isp->isp_osinfo.ehook.ich_arg = isp;
198           isp->isp_osinfo.ehook.ich_desc = "isp";
199           /*
200            * Haha. Set this first, because if we're loaded as a module isp_intr_enable
201            * will be called right awawy, which will clear isp_osinfo.ehook_active,
202            * which would be unwise to then set again later.
203            */
204           isp->isp_osinfo.ehook_active = 1;
205           if (config_intrhook_establish(&isp->isp_osinfo.ehook) != 0) {
206                     isp_prt(isp, ISP_LOGERR, "could not establish interrupt enable hook");
207                     return (-EIO);
208           }
209 
210           /*
211            * Create the device queue for our SIM(s).
212            */
213           isp->isp_osinfo.devq = cam_simq_alloc(isp->isp_maxcmds);
214           if (isp->isp_osinfo.devq == NULL) {
215                     config_intrhook_disestablish(&isp->isp_osinfo.ehook);
216                     return (EIO);
217           }
218 
219           for (chan = 0; chan < isp->isp_nchan; chan++) {
220                     if (isp_attach_chan(isp, isp->isp_osinfo.devq, chan)) {
221                               goto unwind;
222                     }
223           }
224 
225           callout_init(&isp->isp_osinfo.tmo);
226           callout_reset(&isp->isp_osinfo.tmo, hz, isp_timer, isp);
227           isp->isp_osinfo.timer_active = 1;
228 
229           isp->isp_osinfo.cdev = make_dev(&isp_ops, du, UID_ROOT, GID_OPERATOR, 0600, "%s", nu);
230           if (isp->isp_osinfo.cdev) {
231                     isp->isp_osinfo.cdev->si_drv1 = isp;
232           }
233           return (0);
234 
235 unwind:
236           while (--chan >= 0) {
237                     struct cam_sim *sim;
238                     struct cam_path *path;
239                     if (IS_FC(isp)) {
240                               sim = ISP_FC_PC(isp, chan)->sim;
241                               path = ISP_FC_PC(isp, chan)->path;
242                     } else {
243                               sim = ISP_SPI_PC(isp, chan)->sim;
244                               path = ISP_SPI_PC(isp, chan)->path;
245                     }
246                     xpt_free_path(path);
247                     ISP_LOCK(isp);
248                     xpt_bus_deregister(cam_sim_path(sim));
249                     ISP_UNLOCK(isp);
250                     cam_sim_free(sim);
251           }
252           if (isp->isp_osinfo.ehook_active) {
253                     config_intrhook_disestablish(&isp->isp_osinfo.ehook);
254                     isp->isp_osinfo.ehook_active = 0;
255           }
256           if (isp->isp_osinfo.cdev) {
257                     destroy_dev(isp->isp_osinfo.cdev);
258                     isp->isp_osinfo.cdev = NULL;
259           }
260           isp->isp_osinfo.devq = NULL;
261           return (-1);
262 }
263 
264 int
isp_detach(ispsoftc_t * isp)265 isp_detach(ispsoftc_t *isp)
266 {
267           struct cam_sim *sim;
268           struct cam_path *path;
269           struct ccb_setasync *csa;
270           int chan;
271 
272           ISP_LOCK(isp);
273           for (chan = isp->isp_nchan - 1; chan >= 0; chan -= 1) {
274                     if (IS_FC(isp)) {
275                               sim = ISP_FC_PC(isp, chan)->sim;
276                               path = ISP_FC_PC(isp, chan)->path;
277                     } else {
278                               sim = ISP_SPI_PC(isp, chan)->sim;
279                               path = ISP_SPI_PC(isp, chan)->path;
280                     }
281                     if (sim->refcount > 2) {
282                               ISP_UNLOCK(isp);
283                               return (EBUSY);
284                     }
285           }
286           if (isp->isp_osinfo.timer_active) {
287                     callout_stop(&isp->isp_osinfo.tmo);
288                     isp->isp_osinfo.timer_active = 0;
289           }
290           for (chan = isp->isp_nchan - 1; chan >= 0; chan -= 1) {
291                     if (IS_FC(isp)) {
292                               sim = ISP_FC_PC(isp, chan)->sim;
293                               path = ISP_FC_PC(isp, chan)->path;
294                     } else {
295                               sim = ISP_SPI_PC(isp, chan)->sim;
296                               path = ISP_SPI_PC(isp, chan)->path;
297                     }
298                     csa = &xpt_alloc_ccb()->csa;
299                     xpt_setup_ccb(&csa->ccb_h, path, 5);
300                     csa->ccb_h.func_code = XPT_SASYNC_CB;
301                     csa->event_enable = 0;
302                     csa->callback = isp_cam_async;
303                     csa->callback_arg = sim;
304                     xpt_action((union ccb *)csa);
305                     xpt_free_ccb(&csa->ccb_h);
306                     xpt_free_path(path);
307                     xpt_bus_deregister(cam_sim_path(sim));
308                     cam_sim_free(sim);
309           }
310           ISP_UNLOCK(isp);
311           if (isp->isp_osinfo.cdev) {
312                     destroy_dev(isp->isp_osinfo.cdev);
313                     isp->isp_osinfo.cdev = NULL;
314           }
315           if (isp->isp_osinfo.ehook_active) {
316                     config_intrhook_disestablish(&isp->isp_osinfo.ehook);
317                     isp->isp_osinfo.ehook_active = 0;
318           }
319           if (isp->isp_osinfo.devq != NULL) {
320                     isp->isp_osinfo.devq = NULL;
321           }
322           return (0);
323 }
324 
325 static void
isp_freeze_loopdown(ispsoftc_t * isp,int chan,char * msg)326 isp_freeze_loopdown(ispsoftc_t *isp, int chan, char *msg)
327 {
328           if (IS_FC(isp)) {
329                     struct isp_fc *fc = ISP_FC_PC(isp, chan);
330                     if (fc->simqfrozen == 0) {
331                               isp_prt(isp, ISP_LOGDEBUG0, "%s: freeze simq (loopdown) chan %d", msg, chan);
332                               fc->simqfrozen = SIMQFRZ_LOOPDOWN;
333                               xpt_freeze_simq(fc->sim, 1);
334                     } else {
335                               isp_prt(isp, ISP_LOGDEBUG0, "%s: mark frozen (loopdown) chan %d", msg, chan);
336                               fc->simqfrozen |= SIMQFRZ_LOOPDOWN;
337                     }
338           }
339 }
340 
341 static void
isp_unfreeze_loopdown(ispsoftc_t * isp,int chan)342 isp_unfreeze_loopdown(ispsoftc_t *isp, int chan)
343 {
344           if (IS_FC(isp)) {
345                     struct isp_fc *fc = ISP_FC_PC(isp, chan);
346                     int wasfrozen = fc->simqfrozen & SIMQFRZ_LOOPDOWN;
347                     fc->simqfrozen &= ~SIMQFRZ_LOOPDOWN;
348                     if (wasfrozen && fc->simqfrozen == 0) {
349                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d releasing simq", __func__, chan);
350                               xpt_release_simq(fc->sim, 1);
351                     }
352           }
353 }
354 
355 
356 static int
ispioctl(struct dev_ioctl_args * ap)357 ispioctl(struct dev_ioctl_args *ap)
358 {
359           cdev_t dev = ap->a_head.a_dev;
360           caddr_t addr = ap->a_data;
361           u_long c = ap->a_cmd;
362           ispsoftc_t *isp;
363           int nr, chan, retval = ENOTTY;
364 
365           isp = dev->si_drv1;
366 
367           switch (c) {
368           case ISP_SDBLEV:
369           {
370                     int olddblev = isp->isp_dblev;
371                     isp->isp_dblev = *(int *)addr;
372                     *(int *)addr = olddblev;
373                     retval = 0;
374                     break;
375           }
376           case ISP_GETROLE:
377                     chan = *(int *)addr;
378                     if (chan < 0 || chan >= isp->isp_nchan) {
379                               retval = -ENXIO;
380                               break;
381                     }
382                     if (IS_FC(isp)) {
383                               *(int *)addr = FCPARAM(isp, chan)->role;
384                     } else {
385                               *(int *)addr = SDPARAM(isp, chan)->role;
386                     }
387                     retval = 0;
388                     break;
389           case ISP_SETROLE:
390                     nr = *(int *)addr;
391                     chan = nr >> 8;
392                     if (chan < 0 || chan >= isp->isp_nchan) {
393                               retval = -ENXIO;
394                               break;
395                     }
396                     nr &= 0xff;
397                     if (nr & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) {
398                               retval = EINVAL;
399                               break;
400                     }
401                     if (IS_FC(isp)) {
402                               /*
403                                * We don't really support dual role at present on FC cards.
404                                *
405                                * We should, but a bunch of things are currently broken,
406                                * so don't allow it.
407                                */
408                               if (nr == ISP_ROLE_BOTH) {
409                                         isp_prt(isp, ISP_LOGERR, "cannot support dual role at present");
410                                         retval = EINVAL;
411                                         break;
412                               }
413                               *(int *)addr = FCPARAM(isp, chan)->role;
414 #ifdef    ISP_INTERNAL_TARGET
415                               ISP_LOCK(isp);
416                               retval = isp_fc_change_role(isp, chan, nr);
417                               ISP_UNLOCK(isp);
418 #else
419                               FCPARAM(isp, chan)->role = nr;
420 #endif
421                     } else {
422                               *(int *)addr = SDPARAM(isp, chan)->role;
423                               SDPARAM(isp, chan)->role = nr;
424                     }
425                     retval = 0;
426                     break;
427 
428           case ISP_RESETHBA:
429                     ISP_LOCK(isp);
430 #ifdef    ISP_TARGET_MODE
431                     isp_del_all_wwn_entries(isp, ISP_NOCHAN);
432 #endif
433                     isp_reinit(isp, 0);
434                     ISP_UNLOCK(isp);
435                     retval = 0;
436                     break;
437 
438           case ISP_RESCAN:
439                     if (IS_FC(isp)) {
440                               chan = *(int *)addr;
441                               if (chan < 0 || chan >= isp->isp_nchan) {
442                                         retval = -ENXIO;
443                                         break;
444                               }
445                               ISP_LOCK(isp);
446                               if (isp_fc_runstate(isp, chan, 5 * 1000000)) {
447                                         retval = EIO;
448                               } else {
449                                         retval = 0;
450                               }
451                               ISP_UNLOCK(isp);
452                     }
453                     break;
454 
455           case ISP_FC_LIP:
456                     if (IS_FC(isp)) {
457                               chan = *(int *)addr;
458                               if (chan < 0 || chan >= isp->isp_nchan) {
459                                         retval = -ENXIO;
460                                         break;
461                               }
462                               ISP_LOCK(isp);
463                               if (isp_control(isp, ISPCTL_SEND_LIP, chan)) {
464                                         retval = EIO;
465                               } else {
466                                         retval = 0;
467                               }
468                               ISP_UNLOCK(isp);
469                     }
470                     break;
471           case ISP_FC_GETDINFO:
472           {
473                     struct isp_fc_device *ifc = (struct isp_fc_device *) addr;
474                     fcportdb_t *lp;
475 
476                     if (IS_SCSI(isp)) {
477                               break;
478                     }
479                     if (ifc->loopid >= MAX_FC_TARG) {
480                               retval = EINVAL;
481                               break;
482                     }
483                     lp = &FCPARAM(isp, ifc->chan)->portdb[ifc->loopid];
484                     if (lp->state == FC_PORTDB_STATE_VALID || lp->target_mode) {
485                               ifc->role = lp->roles;
486                               ifc->loopid = lp->handle;
487                               ifc->portid = lp->portid;
488                               ifc->node_wwn = lp->node_wwn;
489                               ifc->port_wwn = lp->port_wwn;
490                               retval = 0;
491                     } else {
492                               retval = ENODEV;
493                     }
494                     break;
495           }
496           case ISP_GET_STATS:
497           {
498                     isp_stats_t *sp = (isp_stats_t *) addr;
499 
500                     ISP_MEMZERO(sp, sizeof (*sp));
501                     sp->isp_stat_version = ISP_STATS_VERSION;
502                     sp->isp_type = isp->isp_type;
503                     sp->isp_revision = isp->isp_revision;
504                     ISP_LOCK(isp);
505                     sp->isp_stats[ISP_INTCNT] = isp->isp_intcnt;
506                     sp->isp_stats[ISP_INTBOGUS] = isp->isp_intbogus;
507                     sp->isp_stats[ISP_INTMBOXC] = isp->isp_intmboxc;
508                     sp->isp_stats[ISP_INGOASYNC] = isp->isp_intoasync;
509                     sp->isp_stats[ISP_RSLTCCMPLT] = isp->isp_rsltccmplt;
510                     sp->isp_stats[ISP_FPHCCMCPLT] = isp->isp_fphccmplt;
511                     sp->isp_stats[ISP_RSCCHIWAT] = isp->isp_rscchiwater;
512                     sp->isp_stats[ISP_FPCCHIWAT] = isp->isp_fpcchiwater;
513                     ISP_UNLOCK(isp);
514                     retval = 0;
515                     break;
516           }
517           case ISP_CLR_STATS:
518                     ISP_LOCK(isp);
519                     isp->isp_intcnt = 0;
520                     isp->isp_intbogus = 0;
521                     isp->isp_intmboxc = 0;
522                     isp->isp_intoasync = 0;
523                     isp->isp_rsltccmplt = 0;
524                     isp->isp_fphccmplt = 0;
525                     isp->isp_rscchiwater = 0;
526                     isp->isp_fpcchiwater = 0;
527                     ISP_UNLOCK(isp);
528                     retval = 0;
529                     break;
530           case ISP_FC_GETHINFO:
531           {
532                     struct isp_hba_device *hba = (struct isp_hba_device *) addr;
533                     int chan = hba->fc_channel;
534 
535                     if (chan < 0 || chan >= isp->isp_nchan) {
536                               retval = ENXIO;
537                               break;
538                     }
539                     hba->fc_fw_major = ISP_FW_MAJORX(isp->isp_fwrev);
540                     hba->fc_fw_minor = ISP_FW_MINORX(isp->isp_fwrev);
541                     hba->fc_fw_micro = ISP_FW_MICROX(isp->isp_fwrev);
542                     hba->fc_nchannels = isp->isp_nchan;
543                     if (IS_FC(isp)) {
544                               hba->fc_nports = MAX_FC_TARG;
545                               hba->fc_speed = FCPARAM(isp, hba->fc_channel)->isp_gbspeed;
546                               hba->fc_topology = FCPARAM(isp, chan)->isp_topo + 1;
547                               hba->fc_loopid = FCPARAM(isp, chan)->isp_loopid;
548                               hba->nvram_node_wwn = FCPARAM(isp, chan)->isp_wwnn_nvram;
549                               hba->nvram_port_wwn = FCPARAM(isp, chan)->isp_wwpn_nvram;
550                               hba->active_node_wwn = FCPARAM(isp, chan)->isp_wwnn;
551                               hba->active_port_wwn = FCPARAM(isp, chan)->isp_wwpn;
552                     } else {
553                               hba->fc_nports = MAX_TARGETS;
554                               hba->fc_speed = 0;
555                               hba->fc_topology = 0;
556                               hba->nvram_node_wwn = 0ull;
557                               hba->nvram_port_wwn = 0ull;
558                               hba->active_node_wwn = 0ull;
559                               hba->active_port_wwn = 0ull;
560                     }
561                     retval = 0;
562                     break;
563           }
564           case ISP_TSK_MGMT:
565           {
566                     int needmarker;
567                     struct isp_fc_tsk_mgmt *fct = (struct isp_fc_tsk_mgmt *) addr;
568                     uint16_t loopid;
569                     mbreg_t mbs;
570 
571                     if (IS_SCSI(isp)) {
572                               break;
573                     }
574 
575                     chan = fct->chan;
576                     if (chan < 0 || chan >= isp->isp_nchan) {
577                               retval = -ENXIO;
578                               break;
579                     }
580 
581                     needmarker = retval = 0;
582                     loopid = fct->loopid;
583                     ISP_LOCK(isp);
584                     if (IS_24XX(isp)) {
585                               uint8_t local[QENTRY_LEN];
586                               isp24xx_tmf_t *tmf;
587                               isp24xx_statusreq_t *sp;
588                               fcparam *fcp = FCPARAM(isp, chan);
589                               fcportdb_t *lp;
590                               int i;
591 
592                               for (i = 0; i < MAX_FC_TARG; i++) {
593                                         lp = &fcp->portdb[i];
594                                         if (lp->handle == loopid) {
595                                                   break;
596                                         }
597                               }
598                               if (i == MAX_FC_TARG) {
599                                         retval = ENXIO;
600                                         ISP_UNLOCK(isp);
601                                         break;
602                               }
603                               /* XXX VALIDATE LP XXX */
604                               tmf = (isp24xx_tmf_t *) local;
605                               ISP_MEMZERO(tmf, QENTRY_LEN);
606                               tmf->tmf_header.rqs_entry_type = RQSTYPE_TSK_MGMT;
607                               tmf->tmf_header.rqs_entry_count = 1;
608                               tmf->tmf_nphdl = lp->handle;
609                               tmf->tmf_delay = 2;
610                               tmf->tmf_timeout = 2;
611                               tmf->tmf_tidlo = lp->portid;
612                               tmf->tmf_tidhi = lp->portid >> 16;
613                               tmf->tmf_vpidx = ISP_GET_VPIDX(isp, chan);
614                               tmf->tmf_lun[1] = fct->lun & 0xff;
615                               if (fct->lun >= 256) {
616                                         tmf->tmf_lun[0] = 0x40 | (fct->lun >> 8);
617                               }
618                               switch (fct->action) {
619                               case IPT_CLEAR_ACA:
620                                         tmf->tmf_flags = ISP24XX_TMF_CLEAR_ACA;
621                                         break;
622                               case IPT_TARGET_RESET:
623                                         tmf->tmf_flags = ISP24XX_TMF_TARGET_RESET;
624                                         needmarker = 1;
625                                         break;
626                               case IPT_LUN_RESET:
627                                         tmf->tmf_flags = ISP24XX_TMF_LUN_RESET;
628                                         needmarker = 1;
629                                         break;
630                               case IPT_CLEAR_TASK_SET:
631                                         tmf->tmf_flags = ISP24XX_TMF_CLEAR_TASK_SET;
632                                         needmarker = 1;
633                                         break;
634                               case IPT_ABORT_TASK_SET:
635                                         tmf->tmf_flags = ISP24XX_TMF_ABORT_TASK_SET;
636                                         needmarker = 1;
637                                         break;
638                               default:
639                                         retval = EINVAL;
640                                         break;
641                               }
642                               if (retval) {
643                                         ISP_UNLOCK(isp);
644                                         break;
645                               }
646                               MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 5000000);
647                               mbs.param[1] = QENTRY_LEN;
648                               mbs.param[2] = DMA_WD1(fcp->isp_scdma);
649                               mbs.param[3] = DMA_WD0(fcp->isp_scdma);
650                               mbs.param[6] = DMA_WD3(fcp->isp_scdma);
651                               mbs.param[7] = DMA_WD2(fcp->isp_scdma);
652 
653                               if (FC_SCRATCH_ACQUIRE(isp, chan)) {
654                                         ISP_UNLOCK(isp);
655                                         retval = ENOMEM;
656                                         break;
657                               }
658                               isp_put_24xx_tmf(isp, tmf, fcp->isp_scratch);
659                               MEMORYBARRIER(isp, SYNC_SFORDEV, 0, QENTRY_LEN, chan);
660                               sp = (isp24xx_statusreq_t *) local;
661                               sp->req_completion_status = 1;
662                               retval = isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
663                               MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN, chan);
664                               isp_get_24xx_response(isp, &((isp24xx_statusreq_t *)fcp->isp_scratch)[1], sp);
665                               FC_SCRATCH_RELEASE(isp, chan);
666                               if (retval || sp->req_completion_status != 0) {
667                                         FC_SCRATCH_RELEASE(isp, chan);
668                                         retval = EIO;
669                               }
670                               if (retval == 0) {
671                                         if (needmarker) {
672                                                   fcp->sendmarker = 1;
673                                         }
674                               }
675                     } else {
676                               MBSINIT(&mbs, 0, MBLOGALL, 0);
677                               if (ISP_CAP_2KLOGIN(isp) == 0) {
678                                         loopid <<= 8;
679                               }
680                               switch (fct->action) {
681                               case IPT_CLEAR_ACA:
682                                         mbs.param[0] = MBOX_CLEAR_ACA;
683                                         mbs.param[1] = loopid;
684                                         mbs.param[2] = fct->lun;
685                                         break;
686                               case IPT_TARGET_RESET:
687                                         mbs.param[0] = MBOX_TARGET_RESET;
688                                         mbs.param[1] = loopid;
689                                         needmarker = 1;
690                                         break;
691                               case IPT_LUN_RESET:
692                                         mbs.param[0] = MBOX_LUN_RESET;
693                                         mbs.param[1] = loopid;
694                                         mbs.param[2] = fct->lun;
695                                         needmarker = 1;
696                                         break;
697                               case IPT_CLEAR_TASK_SET:
698                                         mbs.param[0] = MBOX_CLEAR_TASK_SET;
699                                         mbs.param[1] = loopid;
700                                         mbs.param[2] = fct->lun;
701                                         needmarker = 1;
702                                         break;
703                               case IPT_ABORT_TASK_SET:
704                                         mbs.param[0] = MBOX_ABORT_TASK_SET;
705                                         mbs.param[1] = loopid;
706                                         mbs.param[2] = fct->lun;
707                                         needmarker = 1;
708                                         break;
709                               default:
710                                         retval = EINVAL;
711                                         break;
712                               }
713                               if (retval == 0) {
714                                         if (needmarker) {
715                                                   FCPARAM(isp, chan)->sendmarker = 1;
716                                         }
717                                         retval = isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
718                                         if (retval) {
719                                                   retval = EIO;
720                                         }
721                               }
722                     }
723                     ISP_UNLOCK(isp);
724                     break;
725           }
726           default:
727                     break;
728           }
729           return (retval);
730 }
731 
732 static void
isp_intr_enable(void * arg)733 isp_intr_enable(void *arg)
734 {
735           int chan;
736           ispsoftc_t *isp = arg;
737           ISP_LOCK(isp);
738           for (chan = 0; chan < isp->isp_nchan; chan++) {
739                     if (IS_FC(isp)) {
740                               if (FCPARAM(isp, chan)->role != ISP_ROLE_NONE) {
741                                         ISP_ENABLE_INTS(isp);
742                                         break;
743                               }
744                     } else {
745                               if (SDPARAM(isp, chan)->role != ISP_ROLE_NONE) {
746                                         ISP_ENABLE_INTS(isp);
747                                         break;
748                               }
749                     }
750           }
751           isp->isp_osinfo.ehook_active = 0;
752           ISP_UNLOCK(isp);
753           /* Release our hook so that the boot can continue. */
754           config_intrhook_disestablish(&isp->isp_osinfo.ehook);
755 }
756 
757 /*
758  * Local Inlines
759  */
760 
761 static ISP_INLINE int isp_get_pcmd(ispsoftc_t *, union ccb *);
762 static ISP_INLINE void isp_free_pcmd(ispsoftc_t *, union ccb *);
763 
764 static ISP_INLINE int
isp_get_pcmd(ispsoftc_t * isp,union ccb * ccb)765 isp_get_pcmd(ispsoftc_t *isp, union ccb *ccb)
766 {
767           ISP_PCMD(ccb) = isp->isp_osinfo.pcmd_free;
768           if (ISP_PCMD(ccb) == NULL) {
769                     return (-1);
770           }
771           isp->isp_osinfo.pcmd_free = ((struct isp_pcmd *)ISP_PCMD(ccb))->next;
772           return (0);
773 }
774 
775 static ISP_INLINE void
isp_free_pcmd(ispsoftc_t * isp,union ccb * ccb)776 isp_free_pcmd(ispsoftc_t *isp, union ccb *ccb)
777 {
778           ((struct isp_pcmd *)ISP_PCMD(ccb))->next = isp->isp_osinfo.pcmd_free;
779           isp->isp_osinfo.pcmd_free = ISP_PCMD(ccb);
780           ISP_PCMD(ccb) = NULL;
781 }
782 /*
783  * Put the target mode functions here, because some are inlines
784  */
785 
786 #ifdef    ISP_TARGET_MODE
787 static ISP_INLINE int is_lun_enabled(ispsoftc_t *, int, lun_id_t);
788 static ISP_INLINE tstate_t *get_lun_statep(ispsoftc_t *, int, lun_id_t);
789 static ISP_INLINE tstate_t *get_lun_statep_from_tag(ispsoftc_t *, int, uint32_t);
790 static ISP_INLINE void rls_lun_statep(ispsoftc_t *, tstate_t *);
791 static ISP_INLINE inot_private_data_t *get_ntp_from_tagdata(ispsoftc_t *, uint32_t, uint32_t, tstate_t **);
792 static ISP_INLINE atio_private_data_t *isp_get_atpd(ispsoftc_t *, tstate_t *, uint32_t);
793 static ISP_INLINE void isp_put_atpd(ispsoftc_t *, tstate_t *, atio_private_data_t *);
794 static ISP_INLINE inot_private_data_t *isp_get_ntpd(ispsoftc_t *, tstate_t *);
795 static ISP_INLINE inot_private_data_t *isp_find_ntpd(ispsoftc_t *, tstate_t *, uint32_t, uint32_t);
796 static ISP_INLINE void isp_put_ntpd(ispsoftc_t *, tstate_t *, inot_private_data_t *);
797 static cam_status create_lun_state(ispsoftc_t *, int, struct cam_path *, tstate_t **);
798 static void destroy_lun_state(ispsoftc_t *, tstate_t *);
799 static void isp_enable_lun(ispsoftc_t *, union ccb *);
800 static void isp_enable_deferred_luns(ispsoftc_t *, int);
801 static cam_status isp_enable_deferred(ispsoftc_t *, int, lun_id_t);
802 static void isp_disable_lun(ispsoftc_t *, union ccb *);
803 static int isp_enable_target_mode(ispsoftc_t *, int);
804 static void isp_ledone(ispsoftc_t *, lun_entry_t *);
805 static timeout_t isp_refire_putback_atio;
806 static void isp_complete_ctio(union ccb *);
807 static void isp_target_putback_atio(union ccb *);
808 static void isp_target_start_ctio(ispsoftc_t *, union ccb *);
809 static void isp_handle_platform_atio(ispsoftc_t *, at_entry_t *);
810 static void isp_handle_platform_atio2(ispsoftc_t *, at2_entry_t *);
811 static void isp_handle_platform_atio7(ispsoftc_t *, at7_entry_t *);
812 static void isp_handle_platform_ctio(ispsoftc_t *, void *);
813 static void isp_handle_platform_notify_scsi(ispsoftc_t *, in_entry_t *);
814 static void isp_handle_platform_notify_fc(ispsoftc_t *, in_fcentry_t *);
815 static void isp_handle_platform_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *);
816 static int isp_handle_platform_target_notify_ack(ispsoftc_t *, isp_notify_t *);
817 static void isp_handle_platform_target_tmf(ispsoftc_t *, isp_notify_t *);
818 static void isp_target_mark_aborted(ispsoftc_t *, union ccb *);
819 static void isp_target_mark_aborted_early(ispsoftc_t *, tstate_t *, uint32_t);
820 
821 static ISP_INLINE int
is_lun_enabled(ispsoftc_t * isp,int bus,lun_id_t lun)822 is_lun_enabled(ispsoftc_t *isp, int bus, lun_id_t lun)
823 {
824           tstate_t *tptr;
825           struct tslist *lhp;
826 
827           ISP_GET_PC_ADDR(isp, bus, lun_hash[LUN_HASH_FUNC(lun)], lhp);
828           SLIST_FOREACH(tptr, lhp, next) {
829                     if (xpt_path_lun_id(tptr->owner) == lun) {
830                               return (1);
831                     }
832           }
833           return (0);
834 }
835 
836 static void
dump_tstates(ispsoftc_t * isp,int bus)837 dump_tstates(ispsoftc_t *isp, int bus)
838 {
839           int i, j;
840           struct tslist *lhp;
841           tstate_t *tptr = NULL;
842 
843           if (bus >= isp->isp_nchan) {
844                     return;
845           }
846           for (i = 0; i < LUN_HASH_SIZE; i++) {
847                     ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
848                     j = 0;
849                     SLIST_FOREACH(tptr, lhp, next) {
850                               xpt_print(tptr->owner, "[%d, %d] atio_cnt=%d inot_cnt=%d\n", i, j, tptr->atio_count, tptr->inot_count);
851                               j++;
852                     }
853           }
854 }
855 
856 static ISP_INLINE tstate_t *
get_lun_statep(ispsoftc_t * isp,int bus,lun_id_t lun)857 get_lun_statep(ispsoftc_t *isp, int bus, lun_id_t lun)
858 {
859           tstate_t *tptr = NULL;
860           struct tslist *lhp;
861           int i;
862 
863           if (bus < isp->isp_nchan) {
864                     for (i = 0; i < LUN_HASH_SIZE; i++) {
865                               ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
866                               SLIST_FOREACH(tptr, lhp, next) {
867                                         if (xpt_path_lun_id(tptr->owner) == lun) {
868                                                   tptr->hold++;
869                                                   return (tptr);
870                                         }
871                               }
872                     }
873           }
874           return (NULL);
875 }
876 
877 static ISP_INLINE tstate_t *
get_lun_statep_from_tag(ispsoftc_t * isp,int bus,uint32_t tagval)878 get_lun_statep_from_tag(ispsoftc_t *isp, int bus, uint32_t tagval)
879 {
880           tstate_t *tptr = NULL;
881           atio_private_data_t *atp;
882           struct tslist *lhp;
883           int i;
884 
885           if (bus < isp->isp_nchan && tagval != 0) {
886                     for (i = 0; i < LUN_HASH_SIZE; i++) {
887                               ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
888                               SLIST_FOREACH(tptr, lhp, next) {
889                                         atp = isp_get_atpd(isp, tptr, tagval);
890                                         if (atp && atp->tag == tagval) {
891                                                   tptr->hold++;
892                                                   return (tptr);
893                                         }
894                               }
895                     }
896           }
897           return (NULL);
898 }
899 
900 static ISP_INLINE inot_private_data_t *
get_ntp_from_tagdata(ispsoftc_t * isp,uint32_t tag_id,uint32_t seq_id,tstate_t ** rslt)901 get_ntp_from_tagdata(ispsoftc_t *isp, uint32_t tag_id, uint32_t seq_id, tstate_t **rslt)
902 {
903           inot_private_data_t *ntp;
904           tstate_t *tptr;
905           struct tslist *lhp;
906           int bus, i;
907 
908           for (bus = 0; bus < isp->isp_nchan; bus++) {
909                     for (i = 0; i < LUN_HASH_SIZE; i++) {
910                               ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
911                               SLIST_FOREACH(tptr, lhp, next) {
912                                         ntp = isp_find_ntpd(isp, tptr, tag_id, seq_id);
913                                         if (ntp) {
914                                                   *rslt = tptr;
915                                                   tptr->hold++;
916                                                   return (ntp);
917                                         }
918                               }
919                     }
920           }
921           return (NULL);
922 }
923 static ISP_INLINE void
rls_lun_statep(ispsoftc_t * isp,tstate_t * tptr)924 rls_lun_statep(ispsoftc_t *isp, tstate_t *tptr)
925 {
926           KASSERT((tptr->hold), ("tptr not held"));
927           tptr->hold--;
928 }
929 
930 static void
isp_tmcmd_restart(ispsoftc_t * isp)931 isp_tmcmd_restart(ispsoftc_t *isp)
932 {
933           inot_private_data_t *ntp;
934           tstate_t *tptr;
935           struct tslist *lhp;
936           int bus, i;
937 
938           for (bus = 0; bus < isp->isp_nchan; bus++) {
939                     for (i = 0; i < LUN_HASH_SIZE; i++) {
940                               ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
941                               SLIST_FOREACH(tptr, lhp, next) {
942                                         inot_private_data_t *restart_queue = tptr->restart_queue;
943                                         tptr->restart_queue = NULL;
944                                         while (restart_queue) {
945                                                   ntp = restart_queue;
946                                                   restart_queue = ntp->rd.nt.nt_hba;
947                                                   if (IS_24XX(isp)) {
948                                                             isp_prt(isp, ISP_LOGTDEBUG0, "%s: restarting resrc deprived %x", __func__, ((at7_entry_t *)ntp->rd.data)->at_rxid);
949                                                             isp_handle_platform_atio7(isp, (at7_entry_t *) ntp->rd.data);
950                                                   } else {
951                                                             isp_prt(isp, ISP_LOGTDEBUG0, "%s: restarting resrc deprived %x", __func__, ((at2_entry_t *)ntp->rd.data)->at_rxid);
952                                                             isp_handle_platform_atio2(isp, (at2_entry_t *) ntp->rd.data);
953                                                   }
954                                                   isp_put_ntpd(isp, tptr, ntp);
955                                                   if (tptr->restart_queue && restart_queue != NULL) {
956                                                             ntp = tptr->restart_queue;
957                                                             tptr->restart_queue = restart_queue;
958                                                             while (restart_queue->rd.nt.nt_hba) {
959                                                                       restart_queue = restart_queue->rd.nt.nt_hba;
960                                                             }
961                                                             restart_queue->rd.nt.nt_hba = ntp;
962                                                             break;
963                                                   }
964                                         }
965                               }
966                     }
967           }
968 }
969 
970 static ISP_INLINE atio_private_data_t *
isp_get_atpd(ispsoftc_t * isp,tstate_t * tptr,uint32_t tag)971 isp_get_atpd(ispsoftc_t *isp, tstate_t *tptr, uint32_t tag)
972 {
973           atio_private_data_t *atp;
974 
975           if (tag == 0) {
976                     atp = tptr->atfree;
977                     if (atp) {
978                               tptr->atfree = atp->next;
979                     }
980                     return (atp);
981           }
982           for (atp = tptr->atpool; atp < &tptr->atpool[ATPDPSIZE]; atp++) {
983                     if (atp->tag == tag) {
984                               return (atp);
985                     }
986           }
987           return (NULL);
988 }
989 
990 static ISP_INLINE void
isp_put_atpd(ispsoftc_t * isp,tstate_t * tptr,atio_private_data_t * atp)991 isp_put_atpd(ispsoftc_t *isp, tstate_t *tptr, atio_private_data_t *atp)
992 {
993           atp->tag = 0;
994           atp->dead = 0;
995           atp->next = tptr->atfree;
996           tptr->atfree = atp;
997 }
998 
999 static void
isp_dump_atpd(ispsoftc_t * isp,tstate_t * tptr)1000 isp_dump_atpd(ispsoftc_t *isp, tstate_t *tptr)
1001 {
1002           atio_private_data_t *atp;
1003           const char *states[8] = { "Free", "ATIO", "CAM", "CTIO", "LAST_CTIO", "PDON", "?6", "7" };
1004 
1005           for (atp = tptr->atpool; atp < &tptr->atpool[ATPDPSIZE]; atp++) {
1006                     if (atp->tag == 0) {
1007                               continue;
1008                     }
1009                     xpt_print(tptr->owner, "ATP: [0x%x] origdlen %u bytes_xfrd %u last_xfr %u lun %u nphdl 0x%04x s_id 0x%06x d_id 0x%06x oxid 0x%04x state %s\n",
1010                     atp->tag, atp->orig_datalen, atp->bytes_xfered, atp->last_xframt, atp->lun, atp->nphdl, atp->sid, atp->portid, atp->oxid, states[atp->state & 0x7]);
1011           }
1012 }
1013 
1014 
1015 static ISP_INLINE inot_private_data_t *
isp_get_ntpd(ispsoftc_t * isp,tstate_t * tptr)1016 isp_get_ntpd(ispsoftc_t *isp, tstate_t *tptr)
1017 {
1018           inot_private_data_t *ntp;
1019           ntp = tptr->ntfree;
1020           if (ntp) {
1021                     tptr->ntfree = ntp->next;
1022           }
1023           return (ntp);
1024 }
1025 
1026 static ISP_INLINE inot_private_data_t *
isp_find_ntpd(ispsoftc_t * isp,tstate_t * tptr,uint32_t tag_id,uint32_t seq_id)1027 isp_find_ntpd(ispsoftc_t *isp, tstate_t *tptr, uint32_t tag_id, uint32_t seq_id)
1028 {
1029           inot_private_data_t *ntp;
1030           for (ntp = tptr->ntpool; ntp < &tptr->ntpool[ATPDPSIZE]; ntp++) {
1031                     if (ntp->rd.tag_id == tag_id && ntp->rd.seq_id == seq_id) {
1032                               return (ntp);
1033                     }
1034           }
1035           return (NULL);
1036 }
1037 
1038 static ISP_INLINE void
isp_put_ntpd(ispsoftc_t * isp,tstate_t * tptr,inot_private_data_t * ntp)1039 isp_put_ntpd(ispsoftc_t *isp, tstate_t *tptr, inot_private_data_t *ntp)
1040 {
1041           ntp->rd.tag_id = ntp->rd.seq_id = 0;
1042           ntp->next = tptr->ntfree;
1043           tptr->ntfree = ntp;
1044 }
1045 
1046 static cam_status
create_lun_state(ispsoftc_t * isp,int bus,struct cam_path * path,tstate_t ** rslt)1047 create_lun_state(ispsoftc_t *isp, int bus, struct cam_path *path, tstate_t **rslt)
1048 {
1049           cam_status status;
1050           lun_id_t lun;
1051           struct tslist *lhp;
1052           tstate_t *tptr;
1053           int i;
1054 
1055           lun = xpt_path_lun_id(path);
1056           if (lun != CAM_LUN_WILDCARD) {
1057                     if (lun >= ISP_MAX_LUNS(isp)) {
1058                               return (CAM_LUN_INVALID);
1059                     }
1060           }
1061           if (is_lun_enabled(isp, bus, lun)) {
1062                     return (CAM_LUN_ALRDY_ENA);
1063           }
1064           tptr = kmalloc(sizeof (tstate_t), M_DEVBUF, M_WAITOK | M_ZERO);
1065           status = xpt_create_path(&tptr->owner, NULL, xpt_path_path_id(path), xpt_path_target_id(path), lun);
1066           if (status != CAM_REQ_CMP) {
1067                     kfree(tptr, M_DEVBUF);
1068                     return (status);
1069           }
1070           SLIST_INIT(&tptr->atios);
1071           SLIST_INIT(&tptr->inots);
1072           for (i = 0; i < ATPDPSIZE-1; i++) {
1073                     tptr->atpool[i].next = &tptr->atpool[i+1];
1074                     tptr->ntpool[i].next = &tptr->ntpool[i+1];
1075           }
1076           tptr->atfree = tptr->atpool;
1077           tptr->ntfree = tptr->ntpool;
1078           tptr->hold = 1;
1079           ISP_GET_PC_ADDR(isp, bus, lun_hash[LUN_HASH_FUNC(xpt_path_lun_id(tptr->owner))], lhp);
1080           SLIST_INSERT_HEAD(lhp, tptr, next);
1081           *rslt = tptr;
1082           ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, path, "created tstate\n");
1083           return (CAM_REQ_CMP);
1084 }
1085 
1086 static ISP_INLINE void
destroy_lun_state(ispsoftc_t * isp,tstate_t * tptr)1087 destroy_lun_state(ispsoftc_t *isp, tstate_t *tptr)
1088 {
1089           struct tslist *lhp;
1090           KASSERT((tptr->hold == 0), ("tptr still held"));
1091           ISP_GET_PC_ADDR(isp, xpt_path_path_id(tptr->owner), lun_hash[LUN_HASH_FUNC(xpt_path_lun_id(tptr->owner))], lhp);
1092           SLIST_REMOVE(lhp, tptr, tstate, next);
1093           xpt_free_path(tptr->owner);
1094           kfree(tptr, M_DEVBUF);
1095 }
1096 
1097 /*
1098  * Enable a lun.
1099  */
1100 static void
isp_enable_lun(ispsoftc_t * isp,union ccb * ccb)1101 isp_enable_lun(ispsoftc_t *isp, union ccb *ccb)
1102 {
1103           tstate_t *tptr = NULL;
1104           int bus, tm_enabled, target_role;
1105           target_id_t target;
1106           lun_id_t lun;
1107 
1108           /*
1109            * We only support either a wildcard target/lun or a target ID of zero and a non-wildcard lun
1110            */
1111           bus = XS_CHANNEL(ccb);
1112           target = ccb->ccb_h.target_id;
1113           lun = ccb->ccb_h.target_lun;
1114           if (target != CAM_TARGET_WILDCARD && target != 0) {
1115                     ccb->ccb_h.status = CAM_TID_INVALID;
1116                     xpt_done(ccb);
1117                     return;
1118           }
1119           if (target == CAM_TARGET_WILDCARD && lun != CAM_LUN_WILDCARD) {
1120                     ccb->ccb_h.status = CAM_LUN_INVALID;
1121                     xpt_done(ccb);
1122                     return;
1123           }
1124 
1125           if (target != CAM_TARGET_WILDCARD && lun == CAM_LUN_WILDCARD) {
1126                     ccb->ccb_h.status = CAM_LUN_INVALID;
1127                     xpt_done(ccb);
1128                     return;
1129           }
1130           if (isp->isp_dblev & ISP_LOGTDEBUG0) {
1131                     xpt_print(ccb->ccb_h.path, "enabling lun 0x%x on channel %d\n", lun, bus);
1132           }
1133 
1134           /*
1135            * Wait until we're not busy with the lun enables subsystem
1136            */
1137           while (isp->isp_osinfo.tmbusy) {
1138                     isp->isp_osinfo.tmwanted = 1;
1139                     mtx_sleep(isp, &isp->isp_lock, 0, "want_isp_enable_lun", 0);
1140           }
1141           isp->isp_osinfo.tmbusy = 1;
1142 
1143           /*
1144            * This is as a good a place as any to check f/w capabilities.
1145            */
1146 
1147           if (IS_FC(isp)) {
1148                     if (ISP_CAP_TMODE(isp) == 0) {
1149                               xpt_print(ccb->ccb_h.path, "firmware does not support target mode\n");
1150                               ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1151                               goto done;
1152                     }
1153                     /*
1154                      * We *could* handle non-SCCLUN f/w, but we'd have to
1155                      * dork with our already fragile enable/disable code.
1156                      */
1157                     if (ISP_CAP_SCCFW(isp) == 0) {
1158                               xpt_print(ccb->ccb_h.path, "firmware not SCCLUN capable\n");
1159                               ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1160                               goto done;
1161                     }
1162 
1163                     target_role = (FCPARAM(isp, bus)->role & ISP_ROLE_TARGET) != 0;
1164 
1165           } else {
1166                     target_role = (SDPARAM(isp, bus)->role & ISP_ROLE_TARGET) != 0;
1167           }
1168 
1169           /*
1170            * Create the state pointer.
1171            * It should not already exist.
1172            */
1173           tptr = get_lun_statep(isp, bus, lun);
1174           if (tptr) {
1175                     ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
1176                     goto done;
1177           }
1178           ccb->ccb_h.status = create_lun_state(isp, bus, ccb->ccb_h.path, &tptr);
1179           if (ccb->ccb_h.status != CAM_REQ_CMP) {
1180                     goto done;
1181           }
1182 
1183           /*
1184            * We have a tricky maneuver to perform here.
1185            *
1186            * If target mode isn't already enabled here,
1187            * *and* our current role includes target mode,
1188            * we enable target mode here.
1189            *
1190            */
1191           ISP_GET_PC(isp, bus, tm_enabled, tm_enabled);
1192           if (tm_enabled == 0 && target_role != 0) {
1193                     if (isp_enable_target_mode(isp, bus)) {
1194                               ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1195                               destroy_lun_state(isp, tptr);
1196                               tptr = NULL;
1197                               goto done;
1198                     }
1199                     tm_enabled = 1;
1200           }
1201 
1202           /*
1203            * Now check to see whether this bus is in target mode already.
1204            *
1205            * If not, a later role change into target mode will finish the job.
1206            */
1207           if (tm_enabled == 0) {
1208                     ISP_SET_PC(isp, bus, tm_enable_defer, 1);
1209                     ccb->ccb_h.status = CAM_REQ_CMP;
1210                     xpt_print(ccb->ccb_h.path, "Target Mode Not Enabled Yet- Lun Enables Deferred\n");
1211                     goto done;
1212           }
1213 
1214           /*
1215            * Enable the lun.
1216            */
1217           ccb->ccb_h.status = isp_enable_deferred(isp, bus, lun);
1218 
1219 done:
1220           if (ccb->ccb_h.status != CAM_REQ_CMP && tptr) {
1221                     destroy_lun_state(isp, tptr);
1222                     tptr = NULL;
1223           }
1224           if (tptr) {
1225                     rls_lun_statep(isp, tptr);
1226           }
1227           isp->isp_osinfo.tmbusy = 0;
1228           if (isp->isp_osinfo.tmwanted) {
1229                     isp->isp_osinfo.tmwanted = 0;
1230                     wakeup(isp);
1231           }
1232           xpt_done(ccb);
1233 }
1234 
1235 static void
isp_enable_deferred_luns(ispsoftc_t * isp,int bus)1236 isp_enable_deferred_luns(ispsoftc_t *isp, int bus)
1237 {
1238           /*
1239            * XXX: not entirely implemented yet
1240            */
1241           (void) isp_enable_deferred(isp, bus, 0);
1242 }
1243 
1244 static uint32_t
isp_enable_deferred(ispsoftc_t * isp,int bus,lun_id_t lun)1245 isp_enable_deferred(ispsoftc_t *isp, int bus, lun_id_t lun)
1246 {
1247           cam_status status;
1248 
1249           isp_prt(isp, ISP_LOGTINFO, "%s: bus %d lun %u", __func__, bus, lun);
1250           if (IS_24XX(isp) || (IS_FC(isp) && ISP_FC_PC(isp, bus)->tm_luns_enabled)) {
1251                     status = CAM_REQ_CMP;
1252           } else {
1253                     int cmd_cnt, not_cnt;
1254 
1255                     if (IS_23XX(isp)) {
1256                               cmd_cnt = DFLT_CMND_CNT;
1257                               not_cnt = DFLT_INOT_CNT;
1258                     } else {
1259                               cmd_cnt = 64;
1260                               not_cnt = 8;
1261                     }
1262                     status = CAM_REQ_INPROG;
1263                     isp->isp_osinfo.rptr = &status;
1264                     if (isp_lun_cmd(isp, RQSTYPE_ENABLE_LUN, bus, lun, DFLT_CMND_CNT, DFLT_INOT_CNT)) {
1265                               status = CAM_RESRC_UNAVAIL;
1266                     } else {
1267                               mtx_sleep(&status, &isp->isp_lock, PRIBIO, "isp_enable_deferred", 0);
1268                     }
1269                     isp->isp_osinfo.rptr = NULL;
1270           }
1271 
1272           if (status == CAM_REQ_CMP) {
1273                     ISP_SET_PC(isp, bus, tm_luns_enabled, 1);
1274                     isp_prt(isp, ISP_LOGTINFO, "bus %d lun %u now enabled for target mode", bus, lun);
1275           }
1276           return (status);
1277 }
1278 
1279 static void
isp_disable_lun(ispsoftc_t * isp,union ccb * ccb)1280 isp_disable_lun(ispsoftc_t *isp, union ccb *ccb)
1281 {
1282           tstate_t *tptr = NULL;
1283           int bus;
1284           cam_status status;
1285           target_id_t target;
1286           lun_id_t lun;
1287 
1288           bus = XS_CHANNEL(ccb);
1289           target = ccb->ccb_h.target_id;
1290           lun = ccb->ccb_h.target_lun;
1291           if (target != CAM_TARGET_WILDCARD && target != 0) {
1292                     ccb->ccb_h.status = CAM_TID_INVALID;
1293                     xpt_done(ccb);
1294                     return;
1295           }
1296           if (target == CAM_TARGET_WILDCARD && lun != CAM_LUN_WILDCARD) {
1297                     ccb->ccb_h.status = CAM_LUN_INVALID;
1298                     xpt_done(ccb);
1299                     return;
1300           }
1301 
1302           if (target != CAM_TARGET_WILDCARD && lun == CAM_LUN_WILDCARD) {
1303                     ccb->ccb_h.status = CAM_LUN_INVALID;
1304                     xpt_done(ccb);
1305                     return;
1306           }
1307           if (isp->isp_dblev & ISP_LOGTDEBUG0) {
1308                     xpt_print(ccb->ccb_h.path, "enabling lun 0x%x on channel %d\n", lun, bus);
1309           }
1310 
1311           /*
1312            * See if we're busy disabling a lun now.
1313            */
1314           while (isp->isp_osinfo.tmbusy) {
1315                     isp->isp_osinfo.tmwanted = 1;
1316                     mtx_sleep(isp, &isp->isp_lock, PRIBIO, "want_isp_disable_lun", 0);
1317           }
1318           isp->isp_osinfo.tmbusy = 1;
1319 
1320           /*
1321            * Find the state pointer.
1322            */
1323           if ((tptr = get_lun_statep(isp, bus, lun)) == NULL) {
1324                     ccb->ccb_h.status = CAM_PATH_INVALID;
1325                     goto done;
1326           }
1327 
1328           /*
1329            * If we're a 24XX card, we're done.
1330            */
1331           if (IS_24XX(isp)) {
1332                     status = CAM_REQ_CMP;
1333                     goto done;
1334           }
1335 
1336           /*
1337            * For SCC FW, we only deal with lun zero.
1338            */
1339           if (IS_FC(isp)) {
1340                     lun = 0;
1341           }
1342 
1343           isp->isp_osinfo.rptr = &status;
1344           status = CAM_REQ_INPROG;
1345           if (isp_lun_cmd(isp, RQSTYPE_ENABLE_LUN, bus, lun, 0, 0)) {
1346                     status = CAM_RESRC_UNAVAIL;
1347           } else {
1348                     mtx_sleep(ccb, &isp->isp_lock, PRIBIO, "isp_disable_lun", 0);
1349           }
1350 done:
1351           if (status == CAM_REQ_CMP) {
1352                     xpt_print(ccb->ccb_h.path, "now disabled for target mode\n");
1353           }
1354           if (tptr) {
1355                     destroy_lun_state(isp, tptr);
1356           }
1357           isp->isp_osinfo.rptr = NULL;
1358           isp->isp_osinfo.tmbusy = 0;
1359           if (isp->isp_osinfo.tmwanted) {
1360                     isp->isp_osinfo.tmwanted = 0;
1361                     wakeup(isp);
1362           }
1363           xpt_done(ccb);
1364 }
1365 
1366 static int
isp_enable_target_mode(ispsoftc_t * isp,int bus)1367 isp_enable_target_mode(ispsoftc_t *isp, int bus)
1368 {
1369           int ct;
1370 
1371           ISP_GET_PC(isp, bus, tm_enabled, ct);
1372           if (ct != 0) {
1373                     return (0);
1374           }
1375 
1376           if (IS_SCSI(isp)) {
1377                     mbreg_t mbs;
1378 
1379                     MBSINIT(&mbs, MBOX_ENABLE_TARGET_MODE, MBLOGALL, 0);
1380                     mbs.param[0] = MBOX_ENABLE_TARGET_MODE;
1381                     mbs.param[1] = ENABLE_TARGET_FLAG|ENABLE_TQING_FLAG;
1382                     mbs.param[2] = bus << 7;
1383                     if (isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs) < 0 || mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1384                               isp_prt(isp, ISP_LOGERR, "Unable to add Target Role to Bus %d", bus);
1385                               return (EIO);
1386                     }
1387                     SDPARAM(isp, bus)->role |= ISP_ROLE_TARGET;
1388           }
1389           ISP_SET_PC(isp, bus, tm_enabled, 1);
1390           isp_prt(isp, ISP_LOGINFO, "Target Role added to Bus %d", bus);
1391           return (0);
1392 }
1393 
1394 #ifdef    NEEDED
1395 static int
isp_disable_target_mode(ispsoftc_t * isp,int bus)1396 isp_disable_target_mode(ispsoftc_t *isp, int bus)
1397 {
1398           int ct;
1399 
1400           ISP_GET_PC(isp, bus, tm_enabled, ct);
1401           if (ct == 0) {
1402                     return (0);
1403           }
1404 
1405           if (IS_SCSI(isp)) {
1406                     mbreg_t mbs;
1407 
1408                     MBSINIT(&mbs, MBOX_ENABLE_TARGET_MODE, MBLOGALL, 0);
1409                     mbs.param[2] = bus << 7;
1410                     if (isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs) < 0 || mbs.param[0] != MBOX_COMMAND_COMPLETE) {
1411                               isp_prt(isp, ISP_LOGERR, "Unable to subtract Target Role to Bus %d", bus);
1412                               return (EIO);
1413                     }
1414                     SDPARAM(isp, bus)->role &= ~ISP_ROLE_TARGET;
1415           }
1416           ISP_SET_PC(isp, bus, tm_enabled, 0);
1417           isp_prt(isp, ISP_LOGINFO, "Target Role subtracted from Bus %d", bus);
1418           return (0);
1419 }
1420 #endif
1421 
1422 static void
isp_ledone(ispsoftc_t * isp,lun_entry_t * lep)1423 isp_ledone(ispsoftc_t *isp, lun_entry_t *lep)
1424 {
1425           uint32_t *rptr;
1426 
1427           rptr = isp->isp_osinfo.rptr;
1428           if (lep->le_status != LUN_OK) {
1429                     isp_prt(isp, ISP_LOGERR, "ENABLE/MODIFY LUN returned 0x%x", lep->le_status);
1430                     if (rptr) {
1431                               *rptr = CAM_REQ_CMP_ERR;
1432                               wakeup_one(rptr);
1433                     }
1434           } else {
1435                     if (rptr) {
1436                               *rptr = CAM_REQ_CMP;
1437                               wakeup_one(rptr);
1438                     }
1439           }
1440 }
1441 
1442 static void
isp_target_start_ctio(ispsoftc_t * isp,union ccb * ccb)1443 isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
1444 {
1445           void *qe;
1446           tstate_t *tptr;
1447           atio_private_data_t *atp;
1448           struct ccb_scsiio *cso = &ccb->csio;
1449           uint32_t dmaresult, handle;
1450           uint8_t local[QENTRY_LEN];
1451 
1452           /*
1453            * Do some sanity checks.
1454            */
1455           if (cso->dxfer_len == 0) {
1456                     if ((ccb->ccb_h.flags & CAM_SEND_STATUS) == 0) {
1457                               xpt_print(ccb->ccb_h.path, "a data transfer length of zero but no status to send is wrong\n");
1458                               ccb->ccb_h.status = CAM_REQ_INVALID;
1459                               xpt_done(ccb);
1460                               return;
1461                     }
1462           }
1463 
1464           tptr = get_lun_statep(isp, XS_CHANNEL(ccb), XS_LUN(ccb));
1465           if (tptr == NULL) {
1466                     tptr = get_lun_statep(isp, XS_CHANNEL(ccb), CAM_LUN_WILDCARD);
1467                     if (tptr == NULL) {
1468                               xpt_print(ccb->ccb_h.path, "%s: [0x%x] cannot find tstate pointer in %s\n", __func__, cso->tag_id);
1469                               dump_tstates(isp, XS_CHANNEL(ccb));
1470                               ccb->ccb_h.status = CAM_DEV_NOT_THERE;
1471                               xpt_done(ccb);
1472                               return;
1473                     }
1474           }
1475 
1476           atp = isp_get_atpd(isp, tptr, cso->tag_id);
1477           if (atp == NULL) {
1478                     xpt_print(ccb->ccb_h.path, "%s: [0x%x] cannot find private data adjunct\n", __func__, cso->tag_id);
1479                     isp_dump_atpd(isp, tptr);
1480                     ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1481                     xpt_done(ccb);
1482                     return;
1483           }
1484           if (atp->dead) {
1485                     xpt_print(ccb->ccb_h.path, "%s: [0x%x] stopping sending a CTIO for a dead command\n", __func__, cso->tag_id);
1486                     ccb->ccb_h.status = CAM_REQ_ABORTED;
1487                     xpt_done(ccb);
1488                     return;
1489           }
1490 
1491           /*
1492            * Check to make sure we're still in target mode.
1493            */
1494           if ((FCPARAM(isp, XS_CHANNEL(ccb))->role & ISP_ROLE_TARGET) == 0) {
1495                     xpt_print(ccb->ccb_h.path, "%s: [0x%x] stopping sending a CTIO because we're no longer in target mode\n", __func__, cso->tag_id);
1496                     ccb->ccb_h.status = CAM_PROVIDE_FAIL;
1497                     xpt_done(ccb);
1498                     return;
1499           }
1500 
1501           /*
1502            * Get some resources
1503            */
1504           if (isp_get_pcmd(isp, ccb)) {
1505                     rls_lun_statep(isp, tptr);
1506                     xpt_print(ccb->ccb_h.path, "out of PCMDs\n");
1507                     cam_freeze_devq(ccb->ccb_h.path);
1508                     cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
1509                     ccb->ccb_h.status = CAM_REQUEUE_REQ;
1510                     xpt_done(ccb);
1511                     return;
1512           }
1513           qe = isp_getrqentry(isp);
1514           if (qe == NULL) {
1515                     xpt_print(ccb->ccb_h.path, rqo, __func__);
1516                     cam_freeze_devq(ccb->ccb_h.path);
1517                     cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
1518                     ccb->ccb_h.status = CAM_REQUEUE_REQ;
1519                     goto out;
1520           }
1521           memset(local, 0, QENTRY_LEN);
1522 
1523           /*
1524            * We're either moving data or completing a command here.
1525            */
1526           if (IS_24XX(isp)) {
1527                     ct7_entry_t *cto = (ct7_entry_t *) local;
1528 
1529                     cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
1530                     cto->ct_header.rqs_entry_count = 1;
1531                     cto->ct_header.rqs_seqno = 1;
1532                     cto->ct_nphdl = atp->nphdl;
1533                     cto->ct_rxid = atp->tag;
1534                     cto->ct_iid_lo = atp->portid;
1535                     cto->ct_iid_hi = atp->portid >> 16;
1536                     cto->ct_oxid = atp->oxid;
1537                     cto->ct_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(ccb));
1538                     cto->ct_scsi_status = cso->scsi_status;
1539                     cto->ct_timeout = 120;
1540                     cto->ct_flags = atp->tattr << CT7_TASK_ATTR_SHIFT;
1541                     if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
1542                               cto->ct_flags |= CT7_SENDSTATUS;
1543                     }
1544                     if (cso->dxfer_len == 0) {
1545                               cto->ct_flags |= CT7_FLAG_MODE1 | CT7_NO_DATA;
1546                               if ((ccb->ccb_h.flags & CAM_SEND_SENSE) != 0) {
1547                                         int m = min(cso->sense_len, sizeof (struct scsi_sense_data));
1548                                         cto->rsp.m1.ct_resplen = cto->ct_senselen = min(m, MAXRESPLEN_24XX);
1549                                         memcpy(cto->rsp.m1.ct_resp, &cso->sense_data, cto->ct_senselen);
1550                                         cto->ct_scsi_status |= (FCP_SNSLEN_VALID << 8);
1551                               }
1552                     } else {
1553                               cto->ct_flags |= CT7_FLAG_MODE0;
1554                               if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1555                                         cto->ct_flags |= CT7_DATA_IN;
1556                               } else {
1557                                         cto->ct_flags |= CT7_DATA_OUT;
1558                               }
1559                               cto->rsp.m0.reloff = atp->bytes_xfered;
1560                               /*
1561                                * Don't overrun the limits placed on us
1562                                */
1563                               if (atp->bytes_xfered + cso->dxfer_len > atp->orig_datalen) {
1564                                         cso->dxfer_len = atp->orig_datalen - atp->bytes_xfered;
1565                               }
1566                               atp->last_xframt = cso->dxfer_len;
1567                               cto->rsp.m0.ct_xfrlen = cso->dxfer_len;
1568                     }
1569                     if (cto->ct_flags & CT7_SENDSTATUS) {
1570                               int lvl = (cso->scsi_status)? ISP_LOGTINFO : ISP_LOGTDEBUG0;
1571                               cto->ct_resid = atp->orig_datalen - (atp->bytes_xfered + cso->dxfer_len);
1572                               if (cto->ct_resid < 0) {
1573                                         cto->ct_scsi_status |= (FCP_RESID_OVERFLOW << 8);
1574                               } else if (cto->ct_resid > 0) {
1575                                         cto->ct_scsi_status |= (FCP_RESID_UNDERFLOW << 8);
1576                               }
1577                               atp->state = ATPD_STATE_LAST_CTIO;
1578                               ISP_PATH_PRT(isp, lvl, cso->ccb_h.path, "%s: CTIO7[%x] CDB0=%x scsi status %x flags %x resid %d xfrlen %u offset %u\n", __func__, cto->ct_rxid,
1579                                   atp->cdb0, cto->ct_scsi_status, cto->ct_flags, cto->ct_resid, cso->dxfer_len, atp->bytes_xfered);
1580                     } else {
1581                               cto->ct_resid = 0;
1582                               ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, cso->ccb_h.path, "%s: CTIO7[%x] flags %x xfrlen %u offset %u\n", __func__, cto->ct_rxid, cto->ct_flags,
1583                                   cso->dxfer_len, atp->bytes_xfered);
1584                               atp->state = ATPD_STATE_CTIO;
1585                     }
1586           } else if (IS_FC(isp)) {
1587                     ct2_entry_t *cto = (ct2_entry_t *) local;
1588 
1589                     cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
1590                     cto->ct_header.rqs_entry_count = 1;
1591                     cto->ct_header.rqs_seqno = 1;
1592                     if (ISP_CAP_2KLOGIN(isp) == 0) {
1593                               ((ct2e_entry_t *)cto)->ct_iid = cso->init_id;
1594                     } else {
1595                               cto->ct_iid = cso->init_id;
1596                               if (ISP_CAP_SCCFW(isp) == 0) {
1597                                         cto->ct_lun = ccb->ccb_h.target_lun;
1598                               }
1599                     }
1600 
1601 
1602                     cto->ct_rxid = cso->tag_id;
1603                     if (cso->dxfer_len == 0) {
1604                               cto->ct_flags |= CT2_FLAG_MODE1 | CT2_NO_DATA | CT2_SENDSTATUS;
1605                               cto->rsp.m1.ct_scsi_status = cso->scsi_status;
1606                               cto->ct_resid = atp->orig_datalen - atp->bytes_xfered;
1607                               if (cto->ct_resid < 0) {
1608                                         cto->rsp.m1.ct_scsi_status |= CT2_DATA_OVER;
1609                               } else if (cto->ct_resid > 0) {
1610                                         cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER;
1611                               }
1612                               if ((ccb->ccb_h.flags & CAM_SEND_SENSE) != 0) {
1613                                         int m = min(cso->sense_len, MAXRESPLEN);
1614                                         memcpy(cto->rsp.m1.ct_resp, &cso->sense_data, m);
1615                                         cto->rsp.m1.ct_senselen = m;
1616                                         cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
1617                               } else if (cso->scsi_status == SCSI_STATUS_CHECK_COND) {
1618                                         /*
1619                                          * XXX: DEBUG
1620                                          */
1621                                         xpt_print(ccb->ccb_h.path, "CHECK CONDITION being sent without associated SENSE DATA for CDB=0x%x\n", atp->cdb0);
1622                               }
1623                     } else {
1624                               cto->ct_flags |= CT2_FLAG_MODE0;
1625                               if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1626                                         cto->ct_flags |= CT2_DATA_IN;
1627                               } else {
1628                                         cto->ct_flags |= CT2_DATA_OUT;
1629                               }
1630                               cto->ct_reloff = atp->bytes_xfered;
1631                               cto->rsp.m0.ct_xfrlen = cso->dxfer_len;
1632                               /*
1633                                * Don't overrun the limits placed on us
1634                                */
1635                               if (atp->bytes_xfered + cso->dxfer_len > atp->orig_datalen) {
1636                                         cso->dxfer_len = atp->orig_datalen - atp->bytes_xfered;
1637                               }
1638                               if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
1639                                         cto->ct_flags |= CT2_SENDSTATUS;
1640                                         cto->rsp.m0.ct_scsi_status = cso->scsi_status;
1641                                         cto->ct_resid = atp->orig_datalen - (atp->bytes_xfered + cso->dxfer_len);
1642                                         if (cto->ct_resid < 0) {
1643                                                   cto->rsp.m0.ct_scsi_status |= CT2_DATA_OVER;
1644                                         } else if (cto->ct_resid > 0) {
1645                                                   cto->rsp.m0.ct_scsi_status |= CT2_DATA_UNDER;
1646                                         }
1647                               } else {
1648                                         atp->last_xframt = cso->dxfer_len;
1649                               }
1650                               /*
1651                                * If we're sending data and status back together,
1652                                * we can't also send back sense data as well.
1653                                */
1654                               ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
1655                     }
1656 
1657                     if (cto->ct_flags & CT2_SENDSTATUS) {
1658                               int lvl = (cso->scsi_status)? ISP_LOGTINFO : ISP_LOGTDEBUG0;
1659                               cto->ct_flags |= CT2_CCINCR;
1660                               atp->state = ATPD_STATE_LAST_CTIO;
1661                               ISP_PATH_PRT(isp, lvl, cso->ccb_h.path, "%s: CTIO2[%x] CDB0=%x scsi status %x flags %x resid %d xfrlen %u offset %u\n", __func__, cto->ct_rxid,
1662                                   atp->cdb0, cto->rsp.m0.ct_scsi_status, cto->ct_flags, cto->ct_resid, cso->dxfer_len, atp->bytes_xfered);
1663                     } else {
1664                               cto->ct_resid = 0;
1665                               atp->state = ATPD_STATE_CTIO;
1666                               ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "%s: CTIO2[%x] flags %x xfrlen %u offset %u\n", __func__, cto->ct_rxid, cto->ct_flags,
1667                                   cso->dxfer_len, atp->bytes_xfered);
1668                     }
1669                     cto->ct_timeout = 10;
1670           } else {
1671                     ct_entry_t *cto = (ct_entry_t *) local;
1672 
1673                     cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
1674                     cto->ct_header.rqs_entry_count = 1;
1675                     cto->ct_header.rqs_seqno = 1;
1676                     cto->ct_iid = cso->init_id;
1677                     cto->ct_iid |= XS_CHANNEL(ccb) << 7;
1678                     cto->ct_tgt = ccb->ccb_h.target_id;
1679                     cto->ct_lun = ccb->ccb_h.target_lun;
1680                     cto->ct_fwhandle = cso->tag_id >> 16;
1681                     if (AT_HAS_TAG(cso->tag_id)) {
1682                               cto->ct_tag_val = cso->tag_id;
1683                               cto->ct_flags |= CT_TQAE;
1684                     }
1685                     if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) {
1686                               cto->ct_flags |= CT_NODISC;
1687                     }
1688                     if (cso->dxfer_len == 0) {
1689                               cto->ct_flags |= CT_NO_DATA;
1690                     } else if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1691                               cto->ct_flags |= CT_DATA_IN;
1692                     } else {
1693                               cto->ct_flags |= CT_DATA_OUT;
1694                     }
1695                     if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
1696                               cto->ct_flags |= CT_SENDSTATUS|CT_CCINCR;
1697                               cto->ct_scsi_status = cso->scsi_status;
1698                               cto->ct_resid = cso->resid;
1699                               ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "%s: CTIO[%x] scsi status %x resid %d tag_id %x\n", __func__,
1700                                   cto->ct_fwhandle, cso->scsi_status, cso->resid, cso->tag_id);
1701                     }
1702                     ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
1703                     cto->ct_timeout = 10;
1704           }
1705 
1706           if (isp_allocate_xs_tgt(isp, ccb, &handle)) {
1707                     xpt_print(ccb->ccb_h.path, "No XFLIST pointers for %s\n", __func__);
1708                     ccb->ccb_h.status = CAM_REQUEUE_REQ;
1709                     goto out;
1710           }
1711 
1712 
1713           /*
1714            * Call the dma setup routines for this entry (and any subsequent
1715            * CTIOs) if there's data to move, and then tell the f/w it's got
1716            * new things to play with. As with isp_start's usage of DMA setup,
1717            * any swizzling is done in the machine dependent layer. Because
1718            * of this, we put the request onto the queue area first in native
1719            * format.
1720            */
1721 
1722           if (IS_24XX(isp)) {
1723                     ct7_entry_t *cto = (ct7_entry_t *) local;
1724                     cto->ct_syshandle = handle;
1725           } else if (IS_FC(isp)) {
1726                     ct2_entry_t *cto = (ct2_entry_t *) local;
1727                     cto->ct_syshandle = handle;
1728           } else {
1729                     ct_entry_t *cto = (ct_entry_t *) local;
1730                     cto->ct_syshandle = handle;
1731           }
1732 
1733           dmaresult = ISP_DMASETUP(isp, cso, (ispreq_t *) local);
1734           if (dmaresult == CMD_QUEUED) {
1735                     isp->isp_nactive++;
1736                     ccb->ccb_h.status |= CAM_SIM_QUEUED;
1737                     rls_lun_statep(isp, tptr);
1738                     return;
1739           }
1740           if (dmaresult == CMD_EAGAIN) {
1741                     ccb->ccb_h.status = CAM_REQUEUE_REQ;
1742           } else {
1743                     ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1744           }
1745           isp_destroy_tgt_handle(isp, handle);
1746 out:
1747           rls_lun_statep(isp, tptr);
1748           isp_free_pcmd(isp, ccb);
1749           xpt_done(ccb);
1750 }
1751 
1752 static void
isp_refire_putback_atio(void * arg)1753 isp_refire_putback_atio(void *arg)
1754 {
1755           union ccb *ccb = arg;
1756           ispsoftc_t *isp = XS_ISP(ccb);
1757           ISP_LOCK(isp);
1758           isp_target_putback_atio(ccb);
1759           ISP_UNLOCK(isp);
1760 }
1761 
1762 static void
isp_target_putback_atio(union ccb * ccb)1763 isp_target_putback_atio(union ccb *ccb)
1764 {
1765           ispsoftc_t *isp;
1766           struct ccb_scsiio *cso;
1767           void *qe;
1768 
1769           isp = XS_ISP(ccb);
1770 
1771           qe = isp_getrqentry(isp);
1772           if (qe == NULL) {
1773                     xpt_print(ccb->ccb_h.path, rqo, __func__);
1774                     (void) timeout(isp_refire_putback_atio, ccb, 10);
1775                     return;
1776           }
1777           memset(qe, 0, QENTRY_LEN);
1778           cso = &ccb->csio;
1779           if (IS_FC(isp)) {
1780                     at2_entry_t local, *at = &local;
1781                     ISP_MEMZERO(at, sizeof (at2_entry_t));
1782                     at->at_header.rqs_entry_type = RQSTYPE_ATIO2;
1783                     at->at_header.rqs_entry_count = 1;
1784                     if (ISP_CAP_SCCFW(isp)) {
1785                               at->at_scclun = (uint16_t) ccb->ccb_h.target_lun;
1786                     } else {
1787                               at->at_lun = (uint8_t) ccb->ccb_h.target_lun;
1788                     }
1789                     at->at_status = CT_OK;
1790                     at->at_rxid = cso->tag_id;
1791                     at->at_iid = cso->ccb_h.target_id;
1792                     isp_put_atio2(isp, at, qe);
1793           } else {
1794                     at_entry_t local, *at = &local;
1795                     ISP_MEMZERO(at, sizeof (at_entry_t));
1796                     at->at_header.rqs_entry_type = RQSTYPE_ATIO;
1797                     at->at_header.rqs_entry_count = 1;
1798                     at->at_iid = cso->init_id;
1799                     at->at_iid |= XS_CHANNEL(ccb) << 7;
1800                     at->at_tgt = cso->ccb_h.target_id;
1801                     at->at_lun = cso->ccb_h.target_lun;
1802                     at->at_status = CT_OK;
1803                     at->at_tag_val = AT_GET_TAG(cso->tag_id);
1804                     at->at_handle = AT_GET_HANDLE(cso->tag_id);
1805                     isp_put_atio(isp, at, qe);
1806           }
1807           ISP_TDQE(isp, "isp_target_putback_atio", isp->isp_reqidx, qe);
1808           ISP_SYNC_REQUEST(isp);
1809           isp_complete_ctio(ccb);
1810 }
1811 
1812 static void
isp_complete_ctio(union ccb * ccb)1813 isp_complete_ctio(union ccb *ccb)
1814 {
1815           if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
1816                     ccb->ccb_h.status |= CAM_REQ_CMP;
1817           }
1818           ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1819           isp_free_pcmd(XS_ISP(ccb), ccb);
1820           xpt_done(ccb);
1821 }
1822 
1823 /*
1824  * Handle ATIO stuff that the generic code can't.
1825  * This means handling CDBs.
1826  */
1827 
1828 static void
isp_handle_platform_atio(ispsoftc_t * isp,at_entry_t * aep)1829 isp_handle_platform_atio(ispsoftc_t *isp, at_entry_t *aep)
1830 {
1831           tstate_t *tptr;
1832           int status, bus;
1833           struct ccb_accept_tio *atiop;
1834           atio_private_data_t *atp;
1835 
1836           /*
1837            * The firmware status (except for the QLTM_SVALID bit)
1838            * indicates why this ATIO was sent to us.
1839            *
1840            * If QLTM_SVALID is set, the firmware has recommended Sense Data.
1841            *
1842            * If the DISCONNECTS DISABLED bit is set in the flags field,
1843            * we're still connected on the SCSI bus.
1844            */
1845           status = aep->at_status;
1846           if ((status & ~QLTM_SVALID) == AT_PHASE_ERROR) {
1847                     /*
1848                      * Bus Phase Sequence error. We should have sense data
1849                      * suggested by the f/w. I'm not sure quite yet what
1850                      * to do about this for CAM.
1851                      */
1852                     isp_prt(isp, ISP_LOGWARN, "PHASE ERROR");
1853                     isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1854                     return;
1855           }
1856           if ((status & ~QLTM_SVALID) != AT_CDB) {
1857                     isp_prt(isp, ISP_LOGWARN, "bad atio (0x%x) leaked to platform", status);
1858                     isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1859                     return;
1860           }
1861 
1862           bus = GET_BUS_VAL(aep->at_iid);
1863           tptr = get_lun_statep(isp, bus, aep->at_lun);
1864           if (tptr == NULL) {
1865                     tptr = get_lun_statep(isp, bus, CAM_LUN_WILDCARD);
1866                     if (tptr == NULL) {
1867                               /*
1868                                * Because we can't autofeed sense data back with
1869                                * a command for parallel SCSI, we can't give back
1870                                * a CHECK CONDITION. We'll give back a BUSY status
1871                                * instead. This works out okay because the only
1872                                * time we should, in fact, get this, is in the
1873                                * case that somebody configured us without the
1874                                * blackhole driver, so they get what they deserve.
1875                                */
1876                               isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1877                               return;
1878                     }
1879           }
1880 
1881           atp = isp_get_atpd(isp, tptr, 0);
1882           atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
1883           if (atiop == NULL || atp == NULL) {
1884                     /*
1885                      * Because we can't autofeed sense data back with
1886                      * a command for parallel SCSI, we can't give back
1887                      * a CHECK CONDITION. We'll give back a QUEUE FULL status
1888                      * instead. This works out okay because the only time we
1889                      * should, in fact, get this, is in the case that we've
1890                      * run out of ATIOS.
1891                      */
1892                     xpt_print(tptr->owner, "no %s for lun %d from initiator %d\n", (atp == NULL && atiop == NULL)? "ATIOs *or* ATPS" :
1893                         ((atp == NULL)? "ATPs" : "ATIOs"), aep->at_lun, aep->at_iid);
1894                     isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1895                     if (atp) {
1896                               isp_put_atpd(isp, tptr, atp);
1897                     }
1898                     rls_lun_statep(isp, tptr);
1899                     return;
1900           }
1901           atp->tag = aep->at_tag_val;
1902           if (atp->tag == 0) {
1903                     atp->tag = ~0;
1904           }
1905           atp->state = ATPD_STATE_ATIO;
1906           SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
1907           tptr->atio_count--;
1908           ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, atiop->ccb_h.path, "Take FREE ATIO count now %d\n", tptr->atio_count);
1909           atiop->ccb_h.target_id = aep->at_tgt;
1910           atiop->ccb_h.target_lun = aep->at_lun;
1911           if (aep->at_flags & AT_NODISC) {
1912                     atiop->ccb_h.flags = CAM_DIS_DISCONNECT;
1913           } else {
1914                     atiop->ccb_h.flags = 0;
1915           }
1916 
1917           if (status & QLTM_SVALID) {
1918                     size_t amt = ISP_MIN(QLTM_SENSELEN, sizeof (atiop->sense_data));
1919                     atiop->sense_len = amt;
1920                     ISP_MEMCPY(&atiop->sense_data, aep->at_sense, amt);
1921           } else {
1922                     atiop->sense_len = 0;
1923           }
1924 
1925           atiop->init_id = GET_IID_VAL(aep->at_iid);
1926           atiop->cdb_len = aep->at_cdblen;
1927           ISP_MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen);
1928           atiop->ccb_h.status = CAM_CDB_RECVD;
1929           /*
1930            * Construct a tag 'id' based upon tag value (which may be 0..255)
1931            * and the handle (which we have to preserve).
1932            */
1933           atiop->tag_id = atp->tag;
1934           if (aep->at_flags & AT_TQAE) {
1935                     atiop->tag_action = aep->at_tag_type;
1936                     atiop->ccb_h.status |= CAM_TAG_ACTION_VALID;
1937           }
1938           atp->orig_datalen = 0;
1939           atp->bytes_xfered = 0;
1940           atp->last_xframt = 0;
1941           atp->lun = aep->at_lun;
1942           atp->nphdl = aep->at_iid;
1943           atp->portid = PORT_NONE;
1944           atp->oxid = 0;
1945           atp->cdb0 = atiop->cdb_io.cdb_bytes[0];
1946           atp->tattr = aep->at_tag_type;
1947           atp->state = ATPD_STATE_CAM;
1948           ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, tptr->owner, "ATIO[%x] CDB=0x%x lun %d\n", aep->at_tag_val, atp->cdb0, atp->lun);
1949           rls_lun_statep(isp, tptr);
1950 }
1951 
1952 static void
isp_handle_platform_atio2(ispsoftc_t * isp,at2_entry_t * aep)1953 isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep)
1954 {
1955           lun_id_t lun;
1956           fcportdb_t *lp;
1957           tstate_t *tptr;
1958           struct ccb_accept_tio *atiop;
1959           uint16_t nphdl;
1960           atio_private_data_t *atp;
1961           inot_private_data_t *ntp;
1962 
1963           /*
1964            * The firmware status (except for the QLTM_SVALID bit)
1965            * indicates why this ATIO was sent to us.
1966            *
1967            * If QLTM_SVALID is set, the firmware has recommended Sense Data.
1968            */
1969           if ((aep->at_status & ~QLTM_SVALID) != AT_CDB) {
1970                     isp_prt(isp, ISP_LOGWARN, "bogus atio (0x%x) leaked to platform", aep->at_status);
1971                     isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1972                     return;
1973           }
1974 
1975           if (ISP_CAP_SCCFW(isp)) {
1976                     lun = aep->at_scclun;
1977           } else {
1978                     lun = aep->at_lun;
1979           }
1980           if (ISP_CAP_2KLOGIN(isp)) {
1981                     nphdl = ((at2e_entry_t *)aep)->at_iid;
1982           } else {
1983                     nphdl = aep->at_iid;
1984           }
1985           tptr = get_lun_statep(isp, 0, lun);
1986           if (tptr == NULL) {
1987                     tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD);
1988                     if (tptr == NULL) {
1989                               isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] no state pointer for lun %d", aep->at_rxid, lun);
1990                               isp_endcmd(isp, aep, SCSI_STATUS_CHECK_COND | ECMD_SVALID | (0x5 << 12) | (0x25 << 16), 0);
1991                               return;
1992                     }
1993           }
1994 
1995           /*
1996            * Start any commands pending resources first.
1997            */
1998           if (tptr->restart_queue) {
1999                     inot_private_data_t *restart_queue = tptr->restart_queue;
2000                     tptr->restart_queue = NULL;
2001                     while (restart_queue) {
2002                               ntp = restart_queue;
2003                               restart_queue = ntp->rd.nt.nt_hba;
2004                               isp_prt(isp, ISP_LOGTDEBUG0, "%s: restarting resrc deprived %x", __func__, ((at2_entry_t *)ntp->rd.data)->at_rxid);
2005                               isp_handle_platform_atio2(isp, (at2_entry_t *) ntp->rd.data);
2006                               isp_put_ntpd(isp, tptr, ntp);
2007                               /*
2008                                * If a recursion caused the restart queue to start to fill again,
2009                                * stop and splice the new list on top of the old list and restore
2010                                * it and go to noresrc.
2011                                */
2012                               if (tptr->restart_queue) {
2013                                         ntp = tptr->restart_queue;
2014                                         tptr->restart_queue = restart_queue;
2015                                         while (restart_queue->rd.nt.nt_hba) {
2016                                                   restart_queue = restart_queue->rd.nt.nt_hba;
2017                                         }
2018                                         restart_queue->rd.nt.nt_hba = ntp;
2019                                         goto noresrc;
2020                               }
2021                     }
2022           }
2023 
2024           atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
2025           if (atiop == NULL) {
2026                     goto noresrc;
2027           }
2028 
2029           atp = isp_get_atpd(isp, tptr, 0);
2030           if (atp == NULL) {
2031                     goto noresrc;
2032           }
2033 
2034           atp->tag = aep->at_rxid;
2035           atp->state = ATPD_STATE_ATIO;
2036           SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
2037           tptr->atio_count--;
2038           ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, atiop->ccb_h.path, "Take FREE ATIO count now %d\n", tptr->atio_count);
2039           atiop->ccb_h.target_id = FCPARAM(isp, 0)->isp_loopid;
2040           atiop->ccb_h.target_lun = lun;
2041 
2042           /*
2043            * We don't get 'suggested' sense data as we do with SCSI cards.
2044            */
2045           atiop->sense_len = 0;
2046           if (ISP_CAP_2KLOGIN(isp)) {
2047                     /*
2048                      * NB: We could not possibly have 2K logins if we
2049                      * NB: also did not have SCC FW.
2050                      */
2051                     atiop->init_id = ((at2e_entry_t *)aep)->at_iid;
2052           } else {
2053                     atiop->init_id = aep->at_iid;
2054           }
2055 
2056           /*
2057            * If we're not in the port database, add ourselves.
2058            */
2059           if (!IS_2100(isp) && isp_find_pdb_by_loopid(isp, 0, atiop->init_id, &lp) == 0) {
2060                     uint64_t iid =
2061                               (((uint64_t) aep->at_wwpn[0]) << 48) |
2062                               (((uint64_t) aep->at_wwpn[1]) << 32) |
2063                               (((uint64_t) aep->at_wwpn[2]) << 16) |
2064                               (((uint64_t) aep->at_wwpn[3]) <<  0);
2065                     /*
2066                      * However, make sure we delete ourselves if otherwise
2067                      * we were there but at a different loop id.
2068                      */
2069                     if (isp_find_pdb_by_wwn(isp, 0, iid, &lp)) {
2070                               isp_del_wwn_entry(isp, 0, iid, lp->handle, lp->portid);
2071                     }
2072                     isp_add_wwn_entry(isp, 0, iid, atiop->init_id, PORT_ANY);
2073           }
2074           atiop->cdb_len = ATIO2_CDBLEN;
2075           ISP_MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, ATIO2_CDBLEN);
2076           atiop->ccb_h.status = CAM_CDB_RECVD;
2077           atiop->tag_id = atp->tag;
2078           switch (aep->at_taskflags & ATIO2_TC_ATTR_MASK) {
2079           case ATIO2_TC_ATTR_SIMPLEQ:
2080                     atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
2081                     atiop->tag_action = MSG_SIMPLE_Q_TAG;
2082                     break;
2083           case ATIO2_TC_ATTR_HEADOFQ:
2084                     atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
2085                     atiop->tag_action = MSG_HEAD_OF_Q_TAG;
2086                     break;
2087           case ATIO2_TC_ATTR_ORDERED:
2088                     atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
2089                     atiop->tag_action = MSG_ORDERED_Q_TAG;
2090                     break;
2091           case ATIO2_TC_ATTR_ACAQ:                /* ?? */
2092           case ATIO2_TC_ATTR_UNTAGGED:
2093           default:
2094                     atiop->tag_action = 0;
2095                     break;
2096           }
2097 
2098           atp->orig_datalen = aep->at_datalen;
2099           atp->bytes_xfered = 0;
2100           atp->last_xframt = 0;
2101           atp->lun = lun;
2102           atp->nphdl = atiop->init_id;
2103           atp->sid = PORT_ANY;
2104           atp->oxid = aep->at_oxid;
2105           atp->cdb0 = aep->at_cdb[0];
2106           atp->tattr = aep->at_taskflags & ATIO2_TC_ATTR_MASK;
2107           atp->state = ATPD_STATE_CAM;
2108           xpt_done((union ccb *)atiop);
2109           ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, tptr->owner, "ATIO2[%x] CDB=0x%x lun %d datalen %u\n", aep->at_rxid, atp->cdb0, lun, atp->orig_datalen);
2110           rls_lun_statep(isp, tptr);
2111           return;
2112 noresrc:
2113           ntp = isp_get_ntpd(isp, tptr);
2114           if (ntp == NULL) {
2115                     rls_lun_statep(isp, tptr);
2116                     isp_endcmd(isp, aep, nphdl, 0, SCSI_STATUS_BUSY, 0);
2117                     return;
2118           }
2119           memcpy(ntp->rd.data, aep, QENTRY_LEN);
2120           ntp->rd.nt.nt_hba = tptr->restart_queue;
2121           tptr->restart_queue = ntp;
2122           rls_lun_statep(isp, tptr);
2123 }
2124 
2125 static void
isp_handle_platform_atio7(ispsoftc_t * isp,at7_entry_t * aep)2126 isp_handle_platform_atio7(ispsoftc_t *isp, at7_entry_t *aep)
2127 {
2128           int cdbxlen;
2129           uint16_t lun, chan, nphdl = NIL_HANDLE;
2130           uint32_t did, sid;
2131           uint64_t wwn = INI_NONE;
2132           fcportdb_t *lp;
2133           tstate_t *tptr;
2134           struct ccb_accept_tio *atiop;
2135           atio_private_data_t *atp = NULL;
2136           inot_private_data_t *ntp;
2137 
2138           did = (aep->at_hdr.d_id[0] << 16) | (aep->at_hdr.d_id[1] << 8) | aep->at_hdr.d_id[2];
2139           sid = (aep->at_hdr.s_id[0] << 16) | (aep->at_hdr.s_id[1] << 8) | aep->at_hdr.s_id[2];
2140           lun = (aep->at_cmnd.fcp_cmnd_lun[0] << 8) | aep->at_cmnd.fcp_cmnd_lun[1];
2141 
2142           /*
2143            * Find the N-port handle, and Virtual Port Index for this command.
2144            *
2145            * If we can't, we're somewhat in trouble because we can't actually respond w/o that information.
2146            * We also, as a matter of course, need to know the WWN of the initiator too.
2147            */
2148           if (ISP_CAP_MULTI_ID(isp)) {
2149                     /*
2150                      * Find the right channel based upon D_ID
2151                      */
2152                     isp_find_chan_by_did(isp, did, &chan);
2153 
2154                     if (chan == ISP_NOCHAN) {
2155                               NANOTIME_T now;
2156 
2157                               /*
2158                                * If we don't recognizer our own D_DID, terminate the exchange, unless we're within 2 seconds of startup
2159                                * It's a bit tricky here as we need to stash this command *somewhere*.
2160                                */
2161                               GET_NANOTIME(&now);
2162                               if (NANOTIME_SUB(&isp->isp_init_time, &now) > 2000000000ULL) {
2163                                         isp_prt(isp, ISP_LOGWARN, "%s: [RX_ID 0x%x] D_ID %x not found on any channel- dropping", __func__, aep->at_rxid, did);
2164                                         isp_endcmd(isp, aep, NIL_HANDLE, ISP_NOCHAN, ECMD_TERMINATE, 0);
2165                                         return;
2166                               }
2167                               tptr = get_lun_statep(isp, 0, 0);
2168                               if (tptr == NULL) {
2169                                         tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD);
2170                                         if (tptr == NULL) {
2171                                                   isp_prt(isp, ISP_LOGWARN, "%s: [RX_ID 0x%x] D_ID %x not found on any channel and no tptr- dropping", __func__, aep->at_rxid, did);
2172                                                   isp_endcmd(isp, aep, NIL_HANDLE, ISP_NOCHAN, ECMD_TERMINATE, 0);
2173                                                   return;
2174                                         }
2175                               }
2176                               isp_prt(isp, ISP_LOGWARN, "%s: [RX_ID 0x%x] D_ID %x not found on any channel- deferring", __func__, aep->at_rxid, did);
2177                               goto noresrc;
2178                     }
2179                     isp_prt(isp, ISP_LOGTDEBUG0, "%s: [RX_ID 0x%x] D_ID 0x%06x found on Chan %d for S_ID 0x%06x", __func__, aep->at_rxid, did, chan, sid);
2180           } else {
2181                     chan = 0;
2182           }
2183 
2184           /*
2185            * Find the PDB entry for this initiator
2186            */
2187           if (isp_find_pdb_by_sid(isp, chan, sid, &lp) == 0) {
2188                     /*
2189                      * If we're not in the port database terminate the exchange.
2190                      */
2191                     isp_prt(isp, ISP_LOGTINFO, "%s: [RX_ID 0x%x] D_ID 0x%06x found on Chan %d for S_ID 0x%06x wasn't in PDB already",
2192                         __func__, aep->at_rxid, did, chan, sid);
2193                     isp_endcmd(isp, aep, NIL_HANDLE, chan, ECMD_TERMINATE, 0);
2194                     return;
2195           }
2196           nphdl = lp->handle;
2197           wwn = lp->port_wwn;
2198 
2199           /*
2200            * Get the tstate pointer
2201            */
2202           tptr = get_lun_statep(isp, chan, lun);
2203           if (tptr == NULL) {
2204                     tptr = get_lun_statep(isp, chan, CAM_LUN_WILDCARD);
2205                     if (tptr == NULL) {
2206                               isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] no state pointer for lun %d or wildcard", aep->at_rxid, lun);
2207                               isp_endcmd(isp, aep, nphdl, chan, SCSI_STATUS_CHECK_COND | ECMD_SVALID | (0x5 << 12) | (0x25 << 16), 0);
2208                               return;
2209                     }
2210           }
2211 
2212           /*
2213            * Start any commands pending resources first.
2214            */
2215           if (tptr->restart_queue) {
2216                     inot_private_data_t *restart_queue = tptr->restart_queue;
2217                     tptr->restart_queue = NULL;
2218                     while (restart_queue) {
2219                               ntp = restart_queue;
2220                               restart_queue = ntp->rd.nt.nt_hba;
2221                               isp_prt(isp, ISP_LOGTDEBUG0, "%s: restarting resrc deprived %x", __func__, ((at7_entry_t *)ntp->rd.data)->at_rxid);
2222                               isp_handle_platform_atio7(isp, (at7_entry_t *) ntp->rd.data);
2223                               isp_put_ntpd(isp, tptr, ntp);
2224                               /*
2225                                * If a recursion caused the restart queue to start to fill again,
2226                                * stop and splice the new list on top of the old list and restore
2227                                * it and go to noresrc.
2228                                */
2229                               if (tptr->restart_queue) {
2230                                         if (restart_queue) {
2231                                                   ntp = tptr->restart_queue;
2232                                                   tptr->restart_queue = restart_queue;
2233                                                   while (restart_queue->rd.nt.nt_hba) {
2234                                                             restart_queue = restart_queue->rd.nt.nt_hba;
2235                                                   }
2236                                                   restart_queue->rd.nt.nt_hba = ntp;
2237                                         }
2238                                         goto noresrc;
2239                               }
2240                     }
2241           }
2242 
2243           /*
2244            * If the f/w is out of resources, just send a BUSY status back.
2245            */
2246           if (aep->at_rxid == AT7_NORESRC_RXID) {
2247                     rls_lun_statep(isp, tptr);
2248                     isp_endcmd(isp, aep, nphdl, chan, SCSI_BUSY, 0);
2249                     return;
2250           }
2251 
2252           /*
2253            * If we're out of resources, just send a BUSY status back.
2254            */
2255           atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
2256           if (atiop == NULL) {
2257                     isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] out of atios", aep->at_rxid);
2258                     goto noresrc;
2259           }
2260 
2261           atp = isp_get_atpd(isp, tptr, 0);
2262           if (atp == NULL) {
2263                     isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] out of atps", aep->at_rxid);
2264                     goto noresrc;
2265           }
2266           if (isp_get_atpd(isp, tptr, aep->at_rxid)) {
2267                     isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] tag wraparound in isp_handle_platforms_atio7 (N-Port Handle 0x%04x S_ID 0x%04x OX_ID 0x%04x)\n",
2268                         aep->at_rxid, nphdl, sid, aep->at_hdr.ox_id);
2269                     /*
2270                      * It's not a "no resource" condition- but we can treat it like one
2271                      */
2272                     goto noresrc;
2273           }
2274 
2275           atp->tag = aep->at_rxid;
2276           atp->state = ATPD_STATE_ATIO;
2277           SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
2278           tptr->atio_count--;
2279           ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, atiop->ccb_h.path, "Take FREE ATIO count now %d\n", tptr->atio_count);
2280           atiop->init_id = nphdl;
2281           atiop->ccb_h.target_id = FCPARAM(isp, chan)->isp_loopid;
2282           atiop->ccb_h.target_lun = lun;
2283           atiop->sense_len = 0;
2284           cdbxlen = aep->at_cmnd.fcp_cmnd_alen_datadir >> FCP_CMND_ADDTL_CDBLEN_SHIFT;
2285           if (cdbxlen) {
2286                     isp_prt(isp, ISP_LOGWARN, "additional CDBLEN ignored");
2287           }
2288           cdbxlen = sizeof (aep->at_cmnd.cdb_dl.sf.fcp_cmnd_cdb);
2289           ISP_MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cmnd.cdb_dl.sf.fcp_cmnd_cdb, cdbxlen);
2290           atiop->cdb_len = cdbxlen;
2291           atiop->ccb_h.status = CAM_CDB_RECVD;
2292           atiop->tag_id = atp->tag;
2293           switch (aep->at_cmnd.fcp_cmnd_task_attribute & FCP_CMND_TASK_ATTR_MASK) {
2294           case FCP_CMND_TASK_ATTR_SIMPLE:
2295                     atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
2296                     atiop->tag_action = MSG_SIMPLE_Q_TAG;
2297                     break;
2298           case FCP_CMND_TASK_ATTR_HEAD:
2299                     atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
2300                     atiop->tag_action = MSG_HEAD_OF_Q_TAG;
2301                     break;
2302           case FCP_CMND_TASK_ATTR_ORDERED:
2303                     atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
2304                     atiop->tag_action = MSG_ORDERED_Q_TAG;
2305                     break;
2306           default:
2307                     /* FALLTHROUGH */
2308           case FCP_CMND_TASK_ATTR_ACA:
2309           case FCP_CMND_TASK_ATTR_UNTAGGED:
2310                     atiop->tag_action = 0;
2311                     break;
2312           }
2313           atp->orig_datalen = aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl;
2314           atp->bytes_xfered = 0;
2315           atp->last_xframt = 0;
2316           atp->lun = lun;
2317           atp->nphdl = nphdl;
2318           atp->portid = sid;
2319           atp->oxid = aep->at_hdr.ox_id;
2320           atp->cdb0 = atiop->cdb_io.cdb_bytes[0];
2321           atp->tattr = aep->at_cmnd.fcp_cmnd_task_attribute & FCP_CMND_TASK_ATTR_MASK;
2322           atp->state = ATPD_STATE_CAM;
2323           ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, tptr->owner, "ATIO7[%x] CDB=0x%x lun %d datalen %u\n", aep->at_rxid, atp->cdb0, lun, atp->orig_datalen);
2324           xpt_done((union ccb *)atiop);
2325           rls_lun_statep(isp, tptr);
2326           return;
2327 noresrc:
2328           if (atp) {
2329                     isp_put_atpd(isp, tptr, atp);
2330           }
2331           ntp = isp_get_ntpd(isp, tptr);
2332           if (ntp == NULL) {
2333                     rls_lun_statep(isp, tptr);
2334                     isp_endcmd(isp, aep, nphdl, chan, SCSI_STATUS_BUSY, 0);
2335                     return;
2336           }
2337           memcpy(ntp->rd.data, aep, QENTRY_LEN);
2338           ntp->rd.nt.nt_hba = tptr->restart_queue;
2339           tptr->restart_queue = ntp;
2340           rls_lun_statep(isp, tptr);
2341 }
2342 
2343 static void
isp_handle_platform_ctio(ispsoftc_t * isp,void * arg)2344 isp_handle_platform_ctio(ispsoftc_t *isp, void *arg)
2345 {
2346           union ccb *ccb;
2347           int sentstatus, ok, notify_cam, resid = 0;
2348           tstate_t *tptr = NULL;
2349           atio_private_data_t *atp = NULL;
2350           int bus;
2351           uint32_t tval, handle;
2352 
2353           /*
2354            * CTIO handles are 16 bits.
2355            * CTIO2 and CTIO7 are 32 bits.
2356            */
2357 
2358           if (IS_SCSI(isp)) {
2359                     handle = ((ct_entry_t *)arg)->ct_syshandle;
2360           } else {
2361                     handle = ((ct2_entry_t *)arg)->ct_syshandle;
2362           }
2363           ccb = isp_find_xs_tgt(isp, handle);
2364           if (ccb == NULL) {
2365                     isp_print_bytes(isp, "null ccb in isp_handle_platform_ctio", QENTRY_LEN, arg);
2366                     return;
2367           }
2368           isp_destroy_tgt_handle(isp, handle);
2369           bus = XS_CHANNEL(ccb);
2370           tptr = get_lun_statep(isp, bus, XS_LUN(ccb));
2371           if (tptr == NULL) {
2372                     tptr = get_lun_statep(isp, bus, CAM_LUN_WILDCARD);
2373           }
2374           KASSERT((tptr != NULL), ("cannot get state pointer"));
2375           if (isp->isp_nactive) {
2376                     isp->isp_nactive++;
2377           }
2378           if (IS_24XX(isp)) {
2379                     ct7_entry_t *ct = arg;
2380 
2381                     atp = isp_get_atpd(isp, tptr, ct->ct_rxid);
2382                     if (atp == NULL) {
2383                               rls_lun_statep(isp, tptr);
2384                               isp_prt(isp, ISP_LOGERR, "%s: cannot find adjunct for %x after I/O", __func__, ct->ct_rxid);
2385                               return;
2386                     }
2387 
2388                     sentstatus = ct->ct_flags & CT7_SENDSTATUS;
2389                     ok = (ct->ct_nphdl == CT7_OK);
2390                     if (ok && sentstatus && (ccb->ccb_h.flags & CAM_SEND_SENSE)) {
2391                               ccb->ccb_h.status |= CAM_SENT_SENSE;
2392                     }
2393                     notify_cam = ct->ct_header.rqs_seqno & 0x1;
2394                     if ((ct->ct_flags & CT7_DATAMASK) != CT7_NO_DATA) {
2395                               resid = ct->ct_resid;
2396                               atp->bytes_xfered += (atp->last_xframt - resid);
2397                               atp->last_xframt = 0;
2398                     }
2399                     if (ct->ct_nphdl == CT_HBA_RESET) {
2400                               ok = 0;
2401                               notify_cam = 1;
2402                               sentstatus = 1;
2403                               ccb->ccb_h.status |= CAM_UNREC_HBA_ERROR;
2404                     } else if (!ok) {
2405                               ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
2406                     }
2407                     tval = atp->tag;
2408                     isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN, "%s: CTIO7[%x] sts 0x%x flg 0x%x sns %d resid %d %s", __func__,
2409                         ct->ct_rxid, ct->ct_nphdl, ct->ct_flags, (ccb->ccb_h.status & CAM_SENT_SENSE) != 0, resid, sentstatus? "FIN" : "MID");
2410                     atp->state = ATPD_STATE_PDON; /* XXX: should really come after isp_complete_ctio */
2411           } else if (IS_FC(isp)) {
2412                     ct2_entry_t *ct = arg;
2413 
2414                     atp = isp_get_atpd(isp, tptr, ct->ct_rxid);
2415                     if (atp == NULL) {
2416                               rls_lun_statep(isp, tptr);
2417                               isp_prt(isp, ISP_LOGERR, "%s: cannot find adjunct for %x after I/O", __func__, ct->ct_rxid);
2418                               return;
2419                     }
2420                     sentstatus = ct->ct_flags & CT2_SENDSTATUS;
2421                     ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;
2422                     if (ok && sentstatus && (ccb->ccb_h.flags & CAM_SEND_SENSE)) {
2423                               ccb->ccb_h.status |= CAM_SENT_SENSE;
2424                     }
2425                     notify_cam = ct->ct_header.rqs_seqno & 0x1;
2426                     if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
2427                               resid = ct->ct_resid;
2428                               atp->bytes_xfered += (atp->last_xframt - resid);
2429                               atp->last_xframt = 0;
2430                     }
2431                     if (ct->ct_status == CT_HBA_RESET) {
2432                               ok = 0;
2433                               notify_cam = 1;
2434                               sentstatus = 1;
2435                               ccb->ccb_h.status |= CAM_UNREC_HBA_ERROR;
2436                     } else if (!ok) {
2437                               ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
2438                     }
2439                     isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN, "%s: CTIO2[%x] sts 0x%x flg 0x%x sns %d resid %d %s", __func__,
2440                         ct->ct_rxid, ct->ct_status, ct->ct_flags, (ccb->ccb_h.status & CAM_SENT_SENSE) != 0, resid, sentstatus? "FIN" : "MID");
2441                     tval = atp->tag;
2442                     atp->state = ATPD_STATE_PDON; /* XXX: should really come after isp_complete_ctio */
2443           } else {
2444                     ct_entry_t *ct = arg;
2445                     sentstatus = ct->ct_flags & CT_SENDSTATUS;
2446                     ok = (ct->ct_status  & ~QLTM_SVALID) == CT_OK;
2447                     /*
2448                      * We *ought* to be able to get back to the original ATIO
2449                      * here, but for some reason this gets lost. It's just as
2450                      * well because it's squirrelled away as part of periph
2451                      * private data.
2452                      *
2453                      * We can live without it as long as we continue to use
2454                      * the auto-replenish feature for CTIOs.
2455                      */
2456                     notify_cam = ct->ct_header.rqs_seqno & 0x1;
2457                     if (ct->ct_status == (CT_HBA_RESET & 0xff)) {
2458                               ok = 0;
2459                               notify_cam = 1;
2460                               sentstatus = 1;
2461                               ccb->ccb_h.status |= CAM_UNREC_HBA_ERROR;
2462                     } else if (!ok) {
2463                               ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
2464                     } else if (ct->ct_status & QLTM_SVALID) {
2465                               char *sp = (char *)ct;
2466                               sp += CTIO_SENSE_OFFSET;
2467                               ccb->csio.sense_len = min(sizeof (ccb->csio.sense_data), QLTM_SENSELEN);
2468                               ISP_MEMCPY(&ccb->csio.sense_data, sp, ccb->csio.sense_len);
2469                               ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
2470                     }
2471                     if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) {
2472                               resid = ct->ct_resid;
2473                     }
2474                     isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO[%x] tag %x S_ID 0x%x lun %d sts %x flg %x resid %d %s", __func__,
2475                         ct->ct_fwhandle, ct->ct_tag_val, ct->ct_iid, ct->ct_lun, ct->ct_status, ct->ct_flags, resid, sentstatus? "FIN" : "MID");
2476                     tval = ct->ct_fwhandle;
2477           }
2478           ccb->csio.resid += resid;
2479 
2480           /*
2481            * We're here either because intermediate data transfers are done
2482            * and/or the final status CTIO (which may have joined with a
2483            * Data Transfer) is done.
2484            *
2485            * In any case, for this platform, the upper layers figure out
2486            * what to do next, so all we do here is collect status and
2487            * pass information along. Any DMA handles have already been
2488            * freed.
2489            */
2490           if (notify_cam == 0) {
2491                     isp_prt(isp, ISP_LOGTDEBUG0, "  INTER CTIO[0x%x] done", tval);
2492                     return;
2493           }
2494           if (tptr) {
2495                     rls_lun_statep(isp, tptr);
2496           }
2497           isp_prt(isp, ISP_LOGTDEBUG0, "%s CTIO[0x%x] done", (sentstatus)? "  FINAL " : "MIDTERM ", tval);
2498 
2499           if (!ok && !IS_24XX(isp)) {
2500                     isp_target_putback_atio(ccb);
2501           } else {
2502                     isp_complete_ctio(ccb);
2503           }
2504 }
2505 
2506 static void
isp_handle_platform_notify_scsi(ispsoftc_t * isp,in_entry_t * inot)2507 isp_handle_platform_notify_scsi(ispsoftc_t *isp, in_entry_t *inot)
2508 {
2509           (void) isp_notify_ack(isp, inot);
2510 }
2511 
2512 static void
isp_handle_platform_notify_fc(ispsoftc_t * isp,in_fcentry_t * inp)2513 isp_handle_platform_notify_fc(ispsoftc_t *isp, in_fcentry_t *inp)
2514 {
2515           int needack = 1;
2516           switch (inp->in_status) {
2517           case IN_PORT_LOGOUT:
2518                     /*
2519                      * XXX: Need to delete this initiator's WWN from the database
2520                      * XXX: Need to send this LOGOUT upstream
2521                      */
2522                     isp_prt(isp, ISP_LOGWARN, "port logout of S_ID 0x%x", inp->in_iid);
2523                     break;
2524           case IN_PORT_CHANGED:
2525                     isp_prt(isp, ISP_LOGWARN, "port changed for S_ID 0x%x", inp->in_iid);
2526                     break;
2527           case IN_GLOBAL_LOGO:
2528                     isp_del_all_wwn_entries(isp, 0);
2529                     isp_prt(isp, ISP_LOGINFO, "all ports logged out");
2530                     break;
2531           case IN_ABORT_TASK:
2532           {
2533                     tstate_t *tptr;
2534                     uint16_t lun;
2535                     uint32_t loopid;
2536                     uint64_t wwn;
2537                     atio_private_data_t *atp;
2538                     fcportdb_t *lp;
2539                     struct ccb_immediate_notify *inot = NULL;
2540 
2541                     if (ISP_CAP_SCCFW(isp)) {
2542                               lun = inp->in_scclun;
2543                     } else {
2544                               lun = inp->in_lun;
2545                     }
2546                     if (ISP_CAP_2KLOGIN(isp)) {
2547                               loopid = ((in_fcentry_e_t *)inp)->in_iid;
2548                     } else {
2549                               loopid = inp->in_iid;
2550                     }
2551                     if (isp_find_pdb_by_loopid(isp, 0, loopid, &lp)) {
2552                               wwn = lp->port_wwn;
2553                     } else {
2554                               wwn = INI_ANY;
2555                     }
2556                     tptr = get_lun_statep(isp, 0, lun);
2557                     if (tptr == NULL) {
2558                               tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD);
2559                               if (tptr == NULL) {
2560                                         isp_prt(isp, ISP_LOGWARN, "ABORT TASK for lun %u- but no tstate", lun);
2561                                         return;
2562                               }
2563                     }
2564                     atp = isp_get_atpd(isp, tptr, inp->in_seqid);
2565 
2566                     if (atp) {
2567                               inot = (struct ccb_immediate_notify *) SLIST_FIRST(&tptr->inots);
2568                               isp_prt(isp, ISP_LOGTDEBUG0, "ABORT TASK RX_ID %x WWN 0x%016llx state %d", inp->in_seqid, (unsigned long long) wwn, atp->state);
2569                               if (inot) {
2570                                         tptr->inot_count--;
2571                                         SLIST_REMOVE_HEAD(&tptr->inots, sim_links.sle);
2572                                         ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, inot->ccb_h.path, "%s: Take FREE INOT count now %d\n", __func__, tptr->inot_count);
2573                               } else {
2574                                         ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, tptr->owner, "out of INOT structures\n");
2575                               }
2576                     } else {
2577                               ISP_PATH_PRT(isp, ISP_LOGWARN, tptr->owner, "abort task RX_ID %x from wwn 0x%016llx, state unknown\n", inp->in_seqid, wwn);
2578                     }
2579                     if (inot) {
2580                               isp_notify_t tmp, *nt = &tmp;
2581                               ISP_MEMZERO(nt, sizeof (isp_notify_t));
2582                               nt->nt_hba = isp;
2583                               nt->nt_tgt = FCPARAM(isp, 0)->isp_wwpn;
2584                               nt->nt_wwn = wwn;
2585                               nt->nt_nphdl = loopid;
2586                               nt->nt_sid = PORT_ANY;
2587                               nt->nt_did = PORT_ANY;
2588                               nt->nt_lun = lun;
2589                               nt->nt_need_ack = 1;
2590                               nt->nt_channel = 0;
2591                               nt->nt_ncode = NT_ABORT_TASK;
2592                               nt->nt_lreserved = inot;
2593                               isp_handle_platform_target_tmf(isp, nt);
2594                               needack = 0;
2595                     }
2596                     rls_lun_statep(isp, tptr);
2597                     break;
2598           }
2599           default:
2600                     break;
2601           }
2602           if (needack) {
2603                     (void) isp_notify_ack(isp, inp);
2604           }
2605 }
2606 
2607 static void
isp_handle_platform_notify_24xx(ispsoftc_t * isp,in_fcentry_24xx_t * inot)2608 isp_handle_platform_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *inot)
2609 {
2610           uint16_t nphdl;
2611           uint32_t portid;
2612           fcportdb_t *lp;
2613           uint8_t *ptr = NULL;
2614           uint64_t wwn;
2615 
2616           nphdl = inot->in_nphdl;
2617           if (nphdl != NIL_HANDLE) {
2618                     portid = inot->in_portid_hi << 16 | inot->in_portid_lo;
2619           } else {
2620                     portid = PORT_ANY;
2621           }
2622 
2623           switch (inot->in_status) {
2624           case IN24XX_ELS_RCVD:
2625           {
2626                     char buf[16], *msg;
2627                     int chan = ISP_GET_VPIDX(isp, inot->in_vpidx);
2628 
2629                     /*
2630                      * Note that we're just getting notification that an ELS was received
2631                      * (possibly with some associated information sent upstream). This is
2632                      * *not* the same as being given the ELS frame to accept or reject.
2633                      */
2634                     switch (inot->in_status_subcode) {
2635                     case LOGO:
2636                               msg = "LOGO";
2637                               if (ISP_FW_NEWER_THAN(isp, 4, 0, 25)) {
2638                                         ptr = (uint8_t *)inot;  /* point to unswizzled entry! */
2639                                         wwn =     (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF])   << 56) |
2640                                                   (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF+1]) << 48) |
2641                                                   (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF+2]) << 40) |
2642                                                   (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF+3]) << 32) |
2643                                                   (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF+4]) << 24) |
2644                                                   (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF+5]) << 16) |
2645                                                   (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF+6]) <<  8) |
2646                                                   (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF+7]));
2647                               } else {
2648                                         wwn = INI_ANY;
2649                               }
2650                               isp_del_wwn_entry(isp, chan, wwn, nphdl, portid);
2651                               break;
2652                     case PRLO:
2653                               msg = "PRLO";
2654                               break;
2655                     case PLOGI:
2656                     case PRLI:
2657                               /*
2658                                * Treat PRLI the same as PLOGI and make a database entry for it.
2659                                */
2660                               if (inot->in_status_subcode == PLOGI)
2661                                         msg = "PLOGI";
2662                               else
2663                                         msg = "PRLI";
2664                               if (ISP_FW_NEWER_THAN(isp, 4, 0, 25)) {
2665                                         ptr = (uint8_t *)inot;  /* point to unswizzled entry! */
2666                                         wwn =     (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF])   << 56) |
2667                                                   (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF+1]) << 48) |
2668                                                   (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF+2]) << 40) |
2669                                                   (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF+3]) << 32) |
2670                                                   (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF+4]) << 24) |
2671                                                   (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF+5]) << 16) |
2672                                                   (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF+6]) <<  8) |
2673                                                   (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF+7]));
2674                               } else {
2675                                         wwn = INI_NONE;
2676                               }
2677                               isp_add_wwn_entry(isp, chan, wwn, nphdl, portid);
2678                               break;
2679                     case PDISC:
2680                               msg = "PDISC";
2681                               break;
2682                     case ADISC:
2683                               msg = "ADISC";
2684                               break;
2685                     default:
2686                               ISP_SNPRINTF(buf, sizeof (buf), "ELS 0x%x", inot->in_status_subcode);
2687                               msg = buf;
2688                               break;
2689                     }
2690                     if (inot->in_flags & IN24XX_FLAG_PUREX_IOCB) {
2691                               isp_prt(isp, ISP_LOGERR, "%s Chan %d ELS N-port handle %x PortID 0x%06x marked as needing a PUREX response", msg, chan, nphdl, portid);
2692                               break;
2693                     }
2694                     isp_prt(isp, ISP_LOGTDEBUG0, "%s Chan %d ELS N-port handle %x PortID 0x%06x RX_ID 0x%x OX_ID 0x%x", msg, chan, nphdl, portid,
2695                         inot->in_rxid, inot->in_oxid);
2696                     (void) isp_notify_ack(isp, inot);
2697                     break;
2698           }
2699 
2700           case IN24XX_PORT_LOGOUT:
2701                     ptr = "PORT LOGOUT";
2702                     if (isp_find_pdb_by_loopid(isp, ISP_GET_VPIDX(isp, inot->in_vpidx), nphdl, &lp)) {
2703                               isp_del_wwn_entry(isp, ISP_GET_VPIDX(isp, inot->in_vpidx), lp->port_wwn, nphdl, lp->portid);
2704                     }
2705                     /* FALLTHROUGH */
2706           case IN24XX_PORT_CHANGED:
2707                     if (ptr == NULL) {
2708                               ptr = "PORT CHANGED";
2709                     }
2710                     /* FALLTHROUGH */
2711           case IN24XX_LIP_RESET:
2712                     if (ptr == NULL) {
2713                               ptr = "LIP RESET";
2714                     }
2715                     isp_prt(isp, ISP_LOGINFO, "Chan %d %s (sub-status 0x%x) for N-port handle 0x%x", ISP_GET_VPIDX(isp, inot->in_vpidx), ptr, inot->in_status_subcode, nphdl);
2716 
2717                     /*
2718                      * All subcodes here are irrelevant. What is relevant
2719                      * is that we need to terminate all active commands from
2720                      * this initiator (known by N-port handle).
2721                      */
2722                     /* XXX IMPLEMENT XXX */
2723                     (void) isp_notify_ack(isp, inot);
2724                     break;
2725 
2726           case IN24XX_LINK_RESET:
2727           case IN24XX_LINK_FAILED:
2728           case IN24XX_SRR_RCVD:
2729           default:
2730                     (void) isp_notify_ack(isp, inot);
2731                     break;
2732           }
2733 }
2734 
2735 static int
isp_handle_platform_target_notify_ack(ispsoftc_t * isp,isp_notify_t * mp)2736 isp_handle_platform_target_notify_ack(ispsoftc_t *isp, isp_notify_t *mp)
2737 {
2738 
2739           if (isp->isp_state != ISP_RUNSTATE) {
2740                     isp_prt(isp, ISP_LOGTINFO, "Notify Code 0x%x (qevalid=%d) acked- h/w not ready (dropping)", mp->nt_ncode, mp->nt_lreserved != NULL);
2741                     return (0);
2742           }
2743 
2744           /*
2745            * This case is for a Task Management Function, which shows up as an ATIO7 entry.
2746            */
2747           if (IS_24XX(isp) && mp->nt_lreserved && ((isphdr_t *)mp->nt_lreserved)->rqs_entry_type == RQSTYPE_ATIO) {
2748                     ct7_entry_t local, *cto = &local;
2749                     at7_entry_t *aep = (at7_entry_t *)mp->nt_lreserved;
2750                     fcportdb_t *lp;
2751                     uint32_t sid;
2752                     uint16_t nphdl;
2753 
2754                     sid = (aep->at_hdr.s_id[0] << 16) | (aep->at_hdr.s_id[1] << 8) | aep->at_hdr.s_id[2];
2755                     if (isp_find_pdb_by_sid(isp, mp->nt_channel, sid, &lp)) {
2756                               nphdl = lp->handle;
2757                     } else {
2758                               nphdl = NIL_HANDLE;
2759                     }
2760                     ISP_MEMZERO(&local, sizeof (local));
2761                     cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
2762                     cto->ct_header.rqs_entry_count = 1;
2763                     cto->ct_nphdl = nphdl;
2764                     cto->ct_rxid = aep->at_rxid;
2765                     cto->ct_vpidx = mp->nt_channel;
2766                     cto->ct_iid_lo = sid;
2767                     cto->ct_iid_hi = sid >> 16;
2768                     cto->ct_oxid = aep->at_hdr.ox_id;
2769                     cto->ct_flags = CT7_SENDSTATUS|CT7_NOACK|CT7_NO_DATA|CT7_FLAG_MODE1;
2770                     cto->ct_flags |= (aep->at_ta_len >> 12) << CT7_TASK_ATTR_SHIFT;
2771                     return (isp_target_put_entry(isp, &local));
2772           }
2773 
2774           /*
2775            * This case is for a responding to an ABTS frame
2776            */
2777           if (IS_24XX(isp) && mp->nt_lreserved && ((isphdr_t *)mp->nt_lreserved)->rqs_entry_type == RQSTYPE_ABTS_RCVD) {
2778 
2779                     /*
2780                      * Overload nt_need_ack here to mark whether we've terminated the associated command.
2781                      */
2782                     if (mp->nt_need_ack) {
2783                               uint8_t storage[QENTRY_LEN];
2784                               ct7_entry_t *cto = (ct7_entry_t *) storage;
2785                               abts_t *abts = (abts_t *)mp->nt_lreserved;
2786 
2787                               ISP_MEMZERO(cto, sizeof (ct7_entry_t));
2788                               isp_prt(isp, ISP_LOGTDEBUG0, "%s: [%x] terminating after ABTS received", __func__, abts->abts_rxid_task);
2789                               cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
2790                               cto->ct_header.rqs_entry_count = 1;
2791                               cto->ct_nphdl = mp->nt_nphdl;
2792                               cto->ct_rxid = abts->abts_rxid_task;
2793                               cto->ct_iid_lo = mp->nt_sid;
2794                               cto->ct_iid_hi = mp->nt_sid >> 16;
2795                               cto->ct_oxid = abts->abts_ox_id;
2796                               cto->ct_vpidx = mp->nt_channel;
2797                               cto->ct_flags = CT7_NOACK|CT7_TERMINATE;
2798                               if (isp_target_put_entry(isp, cto)) {
2799                                         return (ENOMEM);
2800                               }
2801                               mp->nt_need_ack = 0;
2802                     }
2803                     if (isp_acknak_abts(isp, mp->nt_lreserved, 0) == ENOMEM) {
2804                               return (ENOMEM);
2805                     } else {
2806                               return (0);
2807                     }
2808           }
2809 
2810           /*
2811            * Handle logout cases here
2812            */
2813           if (mp->nt_ncode == NT_GLOBAL_LOGOUT) {
2814                     isp_del_all_wwn_entries(isp, mp->nt_channel);
2815           }
2816 
2817           if (mp->nt_ncode == NT_LOGOUT) {
2818                     if (!IS_2100(isp) && IS_FC(isp)) {
2819                               isp_del_wwn_entries(isp, mp);
2820                     }
2821           }
2822 
2823           /*
2824            * General purpose acknowledgement
2825            */
2826           if (mp->nt_need_ack) {
2827                     isp_prt(isp, ISP_LOGTINFO, "Notify Code 0x%x (qevalid=%d) being acked", mp->nt_ncode, mp->nt_lreserved != NULL);
2828                     return (isp_notify_ack(isp, mp->nt_lreserved));
2829           }
2830           return (0);
2831 }
2832 
2833 /*
2834  * Handle task management functions.
2835  *
2836  * We show up here with a notify structure filled out.
2837  *
2838  * The nt_lreserved tag points to the original queue entry
2839  */
2840 static void
isp_handle_platform_target_tmf(ispsoftc_t * isp,isp_notify_t * notify)2841 isp_handle_platform_target_tmf(ispsoftc_t *isp, isp_notify_t *notify)
2842 {
2843           tstate_t *tptr;
2844           fcportdb_t *lp;
2845           struct ccb_immediate_notify *inot;
2846           inot_private_data_t *ntp = NULL;
2847           lun_id_t lun;
2848 
2849           isp_prt(isp, ISP_LOGTDEBUG0, "%s: code 0x%x sid  0x%x tagval 0x%016llx chan %d lun 0x%x", __func__, notify->nt_ncode,
2850               notify->nt_sid, (unsigned long long) notify->nt_tagval, notify->nt_channel, notify->nt_lun);
2851           /*
2852            * NB: This assignment is necessary because of tricky type conversion.
2853            * XXX: This is tricky and I need to check this. If the lun isn't known
2854            * XXX: for the task management function, it does not of necessity follow
2855            * XXX: that it should go up stream to the wildcard listener.
2856            */
2857           if (notify->nt_lun == LUN_ANY) {
2858                     lun = CAM_LUN_WILDCARD;
2859           } else {
2860                     lun = notify->nt_lun;
2861           }
2862           tptr = get_lun_statep(isp, notify->nt_channel, lun);
2863           if (tptr == NULL) {
2864                     tptr = get_lun_statep(isp, notify->nt_channel, CAM_LUN_WILDCARD);
2865                     if (tptr == NULL) {
2866                               isp_prt(isp, ISP_LOGWARN, "%s: no state pointer found for chan %d lun 0x%x", __func__, notify->nt_channel, lun);
2867                               goto bad;
2868                     }
2869           }
2870           inot = (struct ccb_immediate_notify *) SLIST_FIRST(&tptr->inots);
2871           if (inot == NULL) {
2872                     isp_prt(isp, ISP_LOGWARN, "%s: out of immediate notify structures for chan %d lun 0x%x", __func__, notify->nt_channel, lun);
2873                     goto bad;
2874           }
2875 
2876           if (isp_find_pdb_by_sid(isp, notify->nt_channel, notify->nt_sid, &lp) == 0) {
2877                     inot->initiator_id = CAM_TARGET_WILDCARD;
2878           } else {
2879                     inot->initiator_id = lp->handle;
2880           }
2881           inot->seq_id = notify->nt_tagval;
2882           inot->tag_id = notify->nt_tagval >> 32;
2883 
2884           switch (notify->nt_ncode) {
2885           case NT_ABORT_TASK:
2886                     isp_target_mark_aborted_early(isp, tptr, inot->tag_id);
2887                     inot->arg = MSG_ABORT_TASK;
2888                     break;
2889           case NT_ABORT_TASK_SET:
2890                     isp_target_mark_aborted_early(isp, tptr, TAG_ANY);
2891                     inot->arg = MSG_ABORT_TASK_SET;
2892                     break;
2893           case NT_CLEAR_ACA:
2894                     inot->arg = MSG_CLEAR_ACA;
2895                     break;
2896           case NT_CLEAR_TASK_SET:
2897                     inot->arg = MSG_CLEAR_TASK_SET;
2898                     break;
2899           case NT_LUN_RESET:
2900                     inot->arg = MSG_LOGICAL_UNIT_RESET;
2901                     break;
2902           case NT_TARGET_RESET:
2903                     inot->arg = MSG_TARGET_RESET;
2904                     break;
2905           default:
2906                     isp_prt(isp, ISP_LOGWARN, "%s: unknown TMF code 0x%x for chan %d lun 0x%x", __func__, notify->nt_ncode, notify->nt_channel, lun);
2907                     goto bad;
2908           }
2909 
2910           ntp = isp_get_ntpd(isp, tptr);
2911           if (ntp == NULL) {
2912                     isp_prt(isp, ISP_LOGWARN, "%s: out of inotify private structures", __func__);
2913                     goto bad;
2914           }
2915           ISP_MEMCPY(&ntp->rd.nt, notify, sizeof (isp_notify_t));
2916           if (notify->nt_lreserved) {
2917                     ISP_MEMCPY(&ntp->rd.data, notify->nt_lreserved, QENTRY_LEN);
2918                     ntp->rd.nt.nt_lreserved = &ntp->rd.data;
2919           }
2920           ntp->rd.seq_id = notify->nt_tagval;
2921           ntp->rd.tag_id = notify->nt_tagval >> 32;
2922 
2923           tptr->inot_count--;
2924           SLIST_REMOVE_HEAD(&tptr->inots, sim_links.sle);
2925           rls_lun_statep(isp, tptr);
2926           ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, inot->ccb_h.path, "%s: Take FREE INOT count now %d\n", __func__, tptr->inot_count);
2927           inot->ccb_h.status = CAM_MESSAGE_RECV;
2928           xpt_done((union ccb *)inot);
2929           return;
2930 bad:
2931           if (tptr) {
2932                     rls_lun_statep(isp, tptr);
2933           }
2934           if (notify->nt_need_ack && notify->nt_lreserved) {
2935                     if (((isphdr_t *)notify->nt_lreserved)->rqs_entry_type == RQSTYPE_ABTS_RCVD) {
2936                               (void) isp_acknak_abts(isp, notify->nt_lreserved, ENOMEM);
2937                     } else {
2938                               (void) isp_notify_ack(isp, notify->nt_lreserved);
2939                     }
2940           }
2941 }
2942 
2943 /*
2944  * Find the associated private data and mark it as dead so
2945  * we don't try to work on it any further.
2946  */
2947 static void
isp_target_mark_aborted(ispsoftc_t * isp,union ccb * ccb)2948 isp_target_mark_aborted(ispsoftc_t *isp, union ccb *ccb)
2949 {
2950           tstate_t *tptr;
2951           atio_private_data_t *atp;
2952 
2953           tptr = get_lun_statep(isp, XS_CHANNEL(ccb), XS_LUN(ccb));
2954           if (tptr == NULL) {
2955                     tptr = get_lun_statep(isp, XS_CHANNEL(ccb), CAM_LUN_WILDCARD);
2956                     if (tptr == NULL) {
2957                               ccb->ccb_h.status = CAM_REQ_INVALID;
2958                               return;
2959                     }
2960           }
2961 
2962           atp = isp_get_atpd(isp, tptr, ccb->atio.tag_id);
2963           if (atp == NULL) {
2964                     ccb->ccb_h.status = CAM_REQ_INVALID;
2965                     return;
2966           }
2967           atp->dead = 1;
2968           ccb->ccb_h.status = CAM_REQ_CMP;
2969 }
2970 
2971 static void
isp_target_mark_aborted_early(ispsoftc_t * isp,tstate_t * tptr,uint32_t tag_id)2972 isp_target_mark_aborted_early(ispsoftc_t *isp, tstate_t *tptr, uint32_t tag_id)
2973 {
2974           atio_private_data_t *atp;
2975           inot_private_data_t *restart_queue = tptr->restart_queue;
2976 
2977           /*
2978            * First, clean any commands pending restart
2979            */
2980           tptr->restart_queue = NULL;
2981           while (restart_queue) {
2982                     uint32_t this_tag_id;
2983                     inot_private_data_t *ntp = restart_queue;
2984 
2985                     restart_queue = ntp->rd.nt.nt_hba;
2986 
2987                     if (IS_24XX(isp)) {
2988                               this_tag_id = ((at7_entry_t *)ntp->rd.data)->at_rxid;
2989                     } else {
2990                               this_tag_id = ((at2_entry_t *)ntp->rd.data)->at_rxid;
2991                     }
2992                     if ((uint64_t)tag_id == TAG_ANY || tag_id == this_tag_id) {
2993                               isp_put_ntpd(isp, tptr, ntp);
2994                     } else {
2995                               ntp->rd.nt.nt_hba = tptr->restart_queue;
2996                               tptr->restart_queue = ntp;
2997                     }
2998           }
2999 
3000           /*
3001            * Now mark other ones dead as well.
3002            */
3003           for (atp = tptr->atpool; atp < &tptr->atpool[ATPDPSIZE]; atp++) {
3004                     if ((uint64_t)tag_id == TAG_ANY || atp->tag == tag_id) {
3005                               atp->dead = 1;
3006                     }
3007           }
3008 }
3009 
3010 
3011 #ifdef    ISP_INTERNAL_TARGET
3012 // #define          ISP_FORCE_TIMEOUT             1
3013 // #define          ISP_TEST_WWNS                           1
3014 // #define          ISP_TEST_SEPARATE_STATUS      1
3015 
3016 #define   ccb_data_offset               ppriv_field0
3017 #define   ccb_atio            ppriv_ptr1
3018 #define   ccb_inot            ppriv_ptr1
3019 
3020 #define   MAX_ISP_TARG_TRANSFER         (2 << 20)
3021 #define   NISP_TARG_CMDS                1024
3022 #define   NISP_TARG_NOTIFIES  1024
3023 #define   DISK_SHIFT                    9
3024 #define   JUNK_SIZE           256
3025 
3026 #ifndef   VERIFY_10
3027 #define   VERIFY_10 0x2f
3028 #endif
3029 
3030 TAILQ_HEAD(ccb_queue, ccb_hdr);
3031 extern u_int vm_kmem_size;
3032 static int ca;
3033 static uint32_t disk_size;
3034 static uint8_t *disk_data = NULL;
3035 static uint8_t *junk_data;
3036 static MALLOC_DEFINE(M_ISPTARG, "ISPTARG", "ISP TARGET data");
3037 struct isptarg_softc {
3038           /* CCBs (CTIOs, ATIOs, INOTs) pending on the controller */
3039           struct ccb_queue    work_queue;
3040           struct ccb_queue    rework_queue;
3041           struct ccb_queue    running_queue;
3042           struct ccb_queue    inot_queue;
3043           struct cam_periph       *periph;
3044           struct cam_path               *path;
3045           ispsoftc_t                    *isp;
3046 };
3047 static periph_ctor_t          isptargctor;
3048 static periph_dtor_t          isptargdtor;
3049 static periph_start_t         isptargstart;
3050 static periph_init_t          isptarginit;
3051 static void                   isptarg_done(struct cam_periph *, union ccb *);
3052 static void                   isptargasync(void *, u_int32_t, struct cam_path *, void *);
3053 
3054 
3055 static int isptarg_rwparm(uint8_t *, uint8_t *, uint64_t, uint32_t, uint8_t **, uint32_t *, int *);
3056 
3057 static struct periph_driver isptargdriver =
3058 {
3059           isptarginit, "isptarg", TAILQ_HEAD_INITIALIZER(isptargdriver.units), /* generation */ 0
3060 };
3061 
3062 static void
isptarginit(void)3063 isptarginit(void)
3064 {
3065 }
3066 
3067 static void
isptargnotify(ispsoftc_t * isp,union ccb * iccb,struct ccb_immediate_notify * inot)3068 isptargnotify(ispsoftc_t *isp, union ccb *iccb, struct ccb_immediate_notify *inot)
3069 {
3070           struct ccb_notify_acknowledge *ack = &iccb->cna2;
3071 
3072           ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, inot->ccb_h.path, "%s: [0x%x] immediate notify for 0x%x from 0x%x status 0x%x arg 0x%x\n", __func__,
3073               inot->tag_id, inot->initiator_id, inot->seq_id, inot->ccb_h.status, inot->arg);
3074           ack->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE;
3075           ack->ccb_h.flags = 0;
3076           ack->ccb_h.retry_count = 0;
3077           ack->ccb_h.cbfcnp = isptarg_done;
3078           ack->ccb_h.timeout = 0;
3079           ack->ccb_h.ccb_inot = inot;
3080           ack->tag_id = inot->tag_id;
3081           ack->seq_id = inot->seq_id;
3082           ack->initiator_id = inot->initiator_id;
3083           xpt_action(iccb);
3084 }
3085 
3086 static void
isptargstart(struct cam_periph * periph,union ccb * iccb)3087 isptargstart(struct cam_periph *periph, union ccb *iccb)
3088 {
3089           const uint8_t niliqd[SHORT_INQUIRY_LENGTH] = {
3090                     0x7f, 0x0, 0x5, 0x2, 32, 0, 0, 0x32,
3091                     'F', 'R', 'E', 'E', 'B', 'S', 'D', ' ',
3092                     'S', 'C', 'S', 'I', ' ', 'N', 'U', 'L',
3093                     'L', ' ', 'D', 'E', 'V', 'I', 'C', 'E',
3094                     '0', '0', '0', '1'
3095           };
3096           const uint8_t iqd[SHORT_INQUIRY_LENGTH] = {
3097                     0, 0x0, 0x5, 0x2, 32, 0, 0, 0x32,
3098                     'F', 'R', 'E', 'E', 'B', 'S', 'D', ' ',
3099                     'S', 'C', 'S', 'I', ' ', 'M', 'E', 'M',
3100                     'O', 'R', 'Y', ' ', 'D', 'I', 'S', 'K',
3101                     '0', '0', '0', '1'
3102           };
3103           int i, more = 0, last;
3104           struct isptarg_softc *softc = periph->softc;
3105           struct ccb_scsiio *csio;
3106           lun_id_t return_lun;
3107           struct ccb_accept_tio *atio;
3108           uint8_t *cdb, *ptr, status;
3109           uint8_t *data_ptr;
3110           uint32_t data_len, flags;
3111           struct ccb_hdr *ccbh;
3112 
3113           KKASSERT(lockstatus(periph->sim->mtx, curthread) != 0);
3114           ISP_PATH_PRT(softc->isp, ISP_LOGTDEBUG0, iccb->ccb_h.path, "%s: function code 0x%x INOTQ=%c WORKQ=%c REWORKQ=%c\n", __func__, iccb->ccb_h.func_code,
3115               TAILQ_FIRST(&softc->inot_queue)? 'y' : 'n', TAILQ_FIRST(&softc->work_queue)? 'y' : 'n', TAILQ_FIRST(&softc->rework_queue)? 'y' : 'n');
3116           /*
3117            * Check for immediate notifies first
3118            */
3119           ccbh = TAILQ_FIRST(&softc->inot_queue);
3120           if (ccbh) {
3121                     TAILQ_REMOVE(&softc->inot_queue, ccbh, periph_links.tqe);
3122                     if (TAILQ_FIRST(&softc->inot_queue) || TAILQ_FIRST(&softc->work_queue) || TAILQ_FIRST(&softc->rework_queue)) {
3123                               xpt_schedule(periph, 1);
3124                     }
3125                     isptargnotify(softc->isp, iccb, (struct ccb_immediate_notify *)ccbh);
3126                     return;
3127           }
3128 
3129           /*
3130            * Check the rework (continuation) work queue first.
3131            */
3132           ccbh = TAILQ_FIRST(&softc->rework_queue);
3133           if (ccbh) {
3134                     atio = (struct ccb_accept_tio *)ccbh;
3135                     TAILQ_REMOVE(&softc->rework_queue, ccbh, periph_links.tqe);
3136                     more = TAILQ_FIRST(&softc->work_queue) || TAILQ_FIRST(&softc->rework_queue);
3137           } else {
3138                     ccbh = TAILQ_FIRST(&softc->work_queue);
3139                     if (ccbh == NULL) {
3140                               ISP_PATH_PRT(softc->isp, ISP_LOGTDEBUG0, iccb->ccb_h.path, "%s: woken up but no work?\n", __func__);
3141                               xpt_release_ccb(iccb);
3142                               return;
3143                     }
3144                     atio = (struct ccb_accept_tio *)ccbh;
3145                     TAILQ_REMOVE(&softc->work_queue, ccbh, periph_links.tqe);
3146                     more = TAILQ_FIRST(&softc->work_queue) != NULL;
3147                     atio->ccb_h.ccb_data_offset = 0;
3148           }
3149 
3150           if (atio->tag_id == 0xffffffff || atio->ccb_h.func_code != XPT_ACCEPT_TARGET_IO) {
3151                     panic("BAD ATIO");
3152           }
3153 
3154           data_ptr = NULL;
3155           data_len = 0;
3156           csio = &iccb->csio;
3157           status = SCSI_STATUS_OK;
3158           flags = CAM_SEND_STATUS;
3159           memset(&atio->sense_data, 0, sizeof (atio->sense_data));
3160           cdb = atio->cdb_io.cdb_bytes;
3161           ISP_PATH_PRT(softc->isp, ISP_LOGTDEBUG0, ccbh->path, "%s: [0x%x] processing ATIO from 0x%x CDB=0x%x data_offset=%u\n", __func__, atio->tag_id, atio->init_id,
3162               cdb[0], atio->ccb_h.ccb_data_offset);
3163 
3164           return_lun = XS_LUN(atio);
3165           if (return_lun != 0) {
3166                     xpt_print(atio->ccb_h.path, "[0x%x] Non-Zero Lun %d: cdb0=0x%x\n", atio->tag_id, return_lun, cdb[0]);
3167                     if (cdb[0] != INQUIRY && cdb[0] != REPORT_LUNS && cdb[0] != REQUEST_SENSE) {
3168                               status = SCSI_STATUS_CHECK_COND;
3169                               atio->sense_data.error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_ILLEGAL_REQUEST;
3170                               atio->sense_data.add_sense_code = 0x25;
3171                               atio->sense_data.add_sense_code_qual = 0x0;
3172                               atio->sense_len = sizeof (atio->sense_data);
3173                     }
3174                     return_lun = CAM_LUN_WILDCARD;
3175           }
3176 
3177           switch (cdb[0]) {
3178           case REQUEST_SENSE:
3179                     flags |= CAM_DIR_IN;
3180                     data_len = sizeof (atio->sense_data);
3181                     junk_data[0] = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_NO_SENSE;
3182                     memset(junk_data+1, 0, data_len-1);
3183                     if (data_len > cdb[4]) {
3184                               data_len = cdb[4];
3185                     }
3186                     if (data_len) {
3187                               data_ptr = junk_data;
3188                     }
3189                     break;
3190           case READ_6:
3191           case READ_10:
3192           case READ_12:
3193           case READ_16:
3194                     if (isptarg_rwparm(cdb, disk_data, disk_size, atio->ccb_h.ccb_data_offset, &data_ptr, &data_len, &last)) {
3195                               status = SCSI_STATUS_CHECK_COND;
3196                               atio->sense_data.error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_UNIT_ATTENTION;
3197                               atio->sense_data.add_sense_code = 0x5;
3198                               atio->sense_data.add_sense_code_qual = 0x24;
3199                               atio->sense_len = sizeof (atio->sense_data);
3200                     } else {
3201 #ifdef    ISP_FORCE_TIMEOUT
3202                               {
3203                                         static int foo;
3204                                         if (foo++ == 500) {
3205                                                   if (more) {
3206                                                             xpt_schedule(periph, 1);
3207                                                   }
3208                                                   foo = 0;
3209                                                   return;
3210                                         }
3211                               }
3212 #endif
3213 #ifdef    ISP_TEST_SEPARATE_STATUS
3214                               if (last && data_len) {
3215                                         last = 0;
3216                               }
3217 #endif
3218                               if (last == 0) {
3219                                         flags &= ~CAM_SEND_STATUS;
3220                               }
3221                               if (data_len) {
3222                                         atio->ccb_h.ccb_data_offset += data_len;
3223                                         flags |= CAM_DIR_IN;
3224                               } else {
3225                                         flags |= CAM_DIR_NONE;
3226                               }
3227                     }
3228                     break;
3229           case WRITE_6:
3230           case WRITE_10:
3231           case WRITE_12:
3232           case WRITE_16:
3233                     if (isptarg_rwparm(cdb, disk_data, disk_size, atio->ccb_h.ccb_data_offset, &data_ptr, &data_len, &last)) {
3234                               status = SCSI_STATUS_CHECK_COND;
3235                               atio->sense_data.error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_UNIT_ATTENTION;
3236                               atio->sense_data.add_sense_code = 0x5;
3237                               atio->sense_data.add_sense_code_qual = 0x24;
3238                               atio->sense_len = sizeof (atio->sense_data);
3239                     } else {
3240 #ifdef    ISP_FORCE_TIMEOUT
3241                               {
3242                                         static int foo;
3243                                         if (foo++ == 500) {
3244                                                   if (more) {
3245                                                             xpt_schedule(periph, 1);
3246                                                   }
3247                                                   foo = 0;
3248                                                   return;
3249                                         }
3250                               }
3251 #endif
3252 #ifdef    ISP_TEST_SEPARATE_STATUS
3253                               if (last && data_len) {
3254                                         last = 0;
3255                               }
3256 #endif
3257                               if (last == 0) {
3258                                         flags &= ~CAM_SEND_STATUS;
3259                               }
3260                               if (data_len) {
3261                                         atio->ccb_h.ccb_data_offset += data_len;
3262                                         flags |= CAM_DIR_OUT;
3263                               } else {
3264                                         flags |= CAM_DIR_NONE;
3265                               }
3266                     }
3267                     break;
3268           case INQUIRY:
3269                     flags |= CAM_DIR_IN;
3270                     if (cdb[1] || cdb[2] || cdb[3]) {
3271                               status = SCSI_STATUS_CHECK_COND;
3272                               atio->sense_data.error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_UNIT_ATTENTION;
3273                               atio->sense_data.add_sense_code = 0x5;
3274                               atio->sense_data.add_sense_code_qual = 0x20;
3275                               atio->sense_len = sizeof (atio->sense_data);
3276                               break;
3277                     }
3278                     data_len = sizeof (iqd);
3279                     if (data_len > cdb[4]) {
3280                               data_len = cdb[4];
3281                     }
3282                     if (data_len) {
3283                               if (XS_LUN(iccb) != 0) {
3284                                         memcpy(junk_data, niliqd, sizeof (iqd));
3285                               } else {
3286                                         memcpy(junk_data, iqd, sizeof (iqd));
3287                               }
3288                               data_ptr = junk_data;
3289                     }
3290                     break;
3291           case TEST_UNIT_READY:
3292                     flags |= CAM_DIR_NONE;
3293                     if (ca) {
3294                               ca = 0;
3295                               status = SCSI_STATUS_CHECK_COND;
3296                               atio->sense_data.error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_UNIT_ATTENTION;
3297                               atio->sense_data.add_sense_code = 0x28;
3298                               atio->sense_data.add_sense_code_qual = 0x0;
3299                               atio->sense_len = sizeof (atio->sense_data);
3300                     }
3301                     break;
3302           case SYNCHRONIZE_CACHE:
3303           case START_STOP:
3304           case RESERVE:
3305           case RELEASE:
3306           case VERIFY_10:
3307                     flags |= CAM_DIR_NONE;
3308                     break;
3309 
3310           case READ_CAPACITY:
3311                     flags |= CAM_DIR_IN;
3312                     if (cdb[2] || cdb[3] || cdb[4] || cdb[5]) {
3313                               status = SCSI_STATUS_CHECK_COND;
3314                               atio->sense_data.error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_UNIT_ATTENTION;
3315                               atio->sense_data.add_sense_code = 0x5;
3316                               atio->sense_data.add_sense_code_qual = 0x24;
3317                               atio->sense_len = sizeof (atio->sense_data);
3318                               break;
3319                     }
3320                     if (cdb[8] & 0x1) { /* PMI */
3321                               junk_data[0] = 0xff;
3322                               junk_data[1] = 0xff;
3323                               junk_data[2] = 0xff;
3324                               junk_data[3] = 0xff;
3325                     } else {
3326                               uint64_t last_blk = (disk_size >> DISK_SHIFT) - 1;
3327                               if (last_blk < 0xffffffffULL) {
3328                                   junk_data[0] = (last_blk >> 24) & 0xff;
3329                                   junk_data[1] = (last_blk >> 16) & 0xff;
3330                                   junk_data[2] = (last_blk >>  8) & 0xff;
3331                                   junk_data[3] = (last_blk) & 0xff;
3332                               } else {
3333                                   junk_data[0] = 0xff;
3334                                   junk_data[1] = 0xff;
3335                                   junk_data[2] = 0xff;
3336                                   junk_data[3] = 0xff;
3337                               }
3338                     }
3339                     junk_data[4] = ((1 << DISK_SHIFT) >> 24) & 0xff;
3340                     junk_data[5] = ((1 << DISK_SHIFT) >> 16) & 0xff;
3341                     junk_data[6] = ((1 << DISK_SHIFT) >>  8) & 0xff;
3342                     junk_data[7] = ((1 << DISK_SHIFT)) & 0xff;
3343                     data_ptr = junk_data;
3344                     data_len = 8;
3345                     break;
3346           case REPORT_LUNS:
3347                     flags |= CAM_DIR_IN;
3348                     memset(junk_data, 0, JUNK_SIZE);
3349                     junk_data[0] = (1 << 3) >> 24;
3350                     junk_data[1] = (1 << 3) >> 16;
3351                     junk_data[2] = (1 << 3) >> 8;
3352                     junk_data[3] = (1 << 3);
3353                     ptr = NULL;
3354                     for (i = 0; i < 1; i++) {
3355                               ptr = &junk_data[8 + (1 << 3)];
3356                               if (i >= 256) {
3357                                         ptr[0] = 0x40 | ((i >> 8) & 0x3f);
3358                               }
3359                               ptr[1] = i;
3360                     }
3361                     data_ptr = junk_data;
3362                     data_len = (ptr + 8) - junk_data;
3363                     break;
3364 
3365           default:
3366                     flags |= CAM_DIR_NONE;
3367                     status = SCSI_STATUS_CHECK_COND;
3368                     atio->sense_data.error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_UNIT_ATTENTION;
3369                     atio->sense_data.add_sense_code = 0x5;
3370                     atio->sense_data.add_sense_code_qual = 0x20;
3371                     atio->sense_len = sizeof (atio->sense_data);
3372                     break;
3373           }
3374 
3375           /*
3376            * If we are done with the transaction, tell the
3377            * controller to send status and perform a CMD_CMPLT.
3378            * If we have associated sense data, see if we can
3379            * send that too.
3380            */
3381           if (status == SCSI_STATUS_CHECK_COND) {
3382                     flags |= CAM_SEND_SENSE;
3383                     csio->sense_len = atio->sense_len;
3384                     csio->sense_data = atio->sense_data;
3385                     flags &= ~CAM_DIR_MASK;
3386                     data_len = 0;
3387                     data_ptr = NULL;
3388           }
3389           cam_fill_ctio(csio, 0, isptarg_done, flags, MSG_SIMPLE_Q_TAG, atio->tag_id, atio->init_id, status, data_ptr, data_len, 0);
3390           iccb->ccb_h.target_id = atio->ccb_h.target_id;
3391           iccb->ccb_h.target_lun = return_lun;
3392           iccb->ccb_h.ccb_atio = atio;
3393           xpt_action(iccb);
3394 
3395           if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) {
3396                     cam_release_devq(periph->path, 0, 0, 0, 0);
3397                     atio->ccb_h.status &= ~CAM_DEV_QFRZN;
3398           }
3399           if (more) {
3400                     xpt_schedule(periph, 1);
3401           }
3402 }
3403 
3404 static cam_status
isptargctor(struct cam_periph * periph,void * arg)3405 isptargctor(struct cam_periph *periph, void *arg)
3406 {
3407           struct isptarg_softc *softc;
3408 
3409           softc = (struct isptarg_softc *)arg;
3410           periph->softc = softc;
3411           softc->periph = periph;
3412           softc->path = periph->path;
3413           ISP_PATH_PRT(softc->isp, ISP_LOGTDEBUG0, periph->path, "%s called\n", __func__);
3414           return (CAM_REQ_CMP);
3415 }
3416 
3417 static void
isptargdtor(struct cam_periph * periph)3418 isptargdtor(struct cam_periph *periph)
3419 {
3420           struct isptarg_softc *softc;
3421           softc = (struct isptarg_softc *)periph->softc;
3422           ISP_PATH_PRT(softc->isp, ISP_LOGTDEBUG0, periph->path, "%s called\n", __func__);
3423           softc->periph = NULL;
3424           softc->path = NULL;
3425           periph->softc = NULL;
3426 }
3427 
3428 static void
isptarg_done(struct cam_periph * periph,union ccb * ccb)3429 isptarg_done(struct cam_periph *periph, union ccb *ccb)
3430 {
3431           struct isptarg_softc *softc;
3432           ispsoftc_t *isp;
3433           struct ccb_accept_tio *atio;
3434           struct ccb_immediate_notify *inot;
3435           cam_status status;
3436 
3437           softc = (struct isptarg_softc *)periph->softc;
3438           isp = softc->isp;
3439           status = ccb->ccb_h.status & CAM_STATUS_MASK;
3440 
3441           switch (ccb->ccb_h.func_code) {
3442           case XPT_ACCEPT_TARGET_IO:
3443                     atio = (struct ccb_accept_tio *) ccb;
3444                     ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "[0x%x] ATIO seen in %s\n", atio->tag_id, __func__);
3445                     TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h, periph_links.tqe);
3446                     xpt_schedule(periph, 1);
3447                     break;
3448           case XPT_IMMEDIATE_NOTIFY:
3449                     inot = (struct ccb_immediate_notify *) ccb;
3450                     ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "[0x%x] INOT for 0x%x seen in %s\n", inot->tag_id, inot->seq_id, __func__);
3451                     TAILQ_INSERT_TAIL(&softc->inot_queue, &ccb->ccb_h, periph_links.tqe);
3452                     xpt_schedule(periph, 1);
3453                     break;
3454           case XPT_CONT_TARGET_IO:
3455                     if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
3456                               cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0);
3457                               ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
3458                     }
3459                     atio = ccb->ccb_h.ccb_atio;
3460                     if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3461                               cam_error_print(ccb, CAM_ESF_ALL, CAM_EPF_ALL);
3462                               xpt_action((union ccb *)atio);
3463                     } else if ((ccb->ccb_h.flags & CAM_SEND_STATUS) == 0) {
3464                               ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "[0x%x] MID CTIO seen in %s\n", atio->tag_id, __func__);
3465                               TAILQ_INSERT_TAIL(&softc->rework_queue, &atio->ccb_h, periph_links.tqe);
3466                               xpt_schedule(periph, 1);
3467                     } else {
3468                               ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "[0x%x] FINAL CTIO seen in %s\n", atio->tag_id, __func__);
3469                               xpt_action((union ccb *)atio);
3470                     }
3471                     xpt_release_ccb(ccb);
3472                     break;
3473           case XPT_NOTIFY_ACKNOWLEDGE:
3474                     if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
3475                               cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0);
3476                               ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
3477                     }
3478                     inot = ccb->ccb_h.ccb_inot;
3479                     ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, inot->ccb_h.path, "[0x%x] recycle notify for tag 0x%x\n", inot->tag_id, inot->seq_id);
3480                     xpt_release_ccb(ccb);
3481                     xpt_action((union ccb *)inot);
3482                     break;
3483           default:
3484                     xpt_print(ccb->ccb_h.path, "unexpected code 0x%x\n", ccb->ccb_h.func_code);
3485                     break;
3486           }
3487 }
3488 
3489 static void
isptargasync(void * callback_arg,u_int32_t code,struct cam_path * path,void * arg)3490 isptargasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
3491 {
3492           struct ac_contract *acp = arg;
3493           struct ac_device_changed *fc = (struct ac_device_changed *) acp->contract_data;
3494 
3495           if (code != AC_CONTRACT) {
3496                     return;
3497           }
3498           xpt_print(path, "0x%016llx Port ID 0x%06x %s\n", (unsigned long long) fc->wwpn, fc->port, fc->arrived? "arrived" : "departed");
3499 }
3500 
3501 static void
isp_target_thread(ispsoftc_t * isp,int chan)3502 isp_target_thread(ispsoftc_t *isp, int chan)
3503 {
3504           union ccb *ccb = NULL;
3505           int i;
3506           void *wchan;
3507           cam_status status;
3508           struct isptarg_softc *softc = NULL;
3509           struct cam_periph *periph = NULL, *wperiph = NULL;
3510           struct cam_path *path, *wpath;
3511           struct cam_sim *sim;
3512 
3513           if (disk_data == NULL) {
3514                     disk_size = roundup2(vm_kmem_size >> 1, (1ULL << 20));
3515                     if (disk_size < (50 << 20)) {
3516                               disk_size = 50 << 20;
3517                     }
3518                     disk_data = kmalloc(disk_size, M_ISPTARG, M_WAITOK | M_ZERO);
3519                     isp_prt(isp, ISP_LOGINFO, "allocated a %ju MiB disk", (uintmax_t) (disk_size >> 20));
3520           }
3521           junk_data = kmalloc(JUNK_SIZE, M_ISPTARG, M_WAITOK | M_ZERO);
3522 
3523 
3524           softc = kmalloc(sizeof (*softc), M_ISPTARG, M_WAITOK | M_ZERO);
3525           TAILQ_INIT(&softc->work_queue);
3526           TAILQ_INIT(&softc->rework_queue);
3527           TAILQ_INIT(&softc->running_queue);
3528           TAILQ_INIT(&softc->inot_queue);
3529           softc->isp = isp;
3530 
3531           periphdriver_register(&isptargdriver);
3532           ISP_GET_PC(isp, chan, sim, sim);
3533           ISP_GET_PC(isp, chan, path,  path);
3534           status = xpt_create_path_unlocked(&wpath, NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
3535           if (status != CAM_REQ_CMP) {
3536                     isp_prt(isp, ISP_LOGERR, "%s: could not allocate wildcard path", __func__);
3537                     return;
3538           }
3539           status = xpt_create_path_unlocked(&path, NULL, cam_sim_path(sim), 0, 0);
3540           if (status != CAM_REQ_CMP) {
3541                     xpt_free_path(wpath);
3542                     isp_prt(isp, ISP_LOGERR, "%s: could not allocate path", __func__);
3543                     return;
3544           }
3545 
3546           ISP_LOCK(isp);
3547           status = cam_periph_alloc(isptargctor, NULL, isptargdtor, isptargstart, "isptarg", CAM_PERIPH_BIO, wpath, NULL, 0, softc);
3548           if (status != CAM_REQ_CMP) {
3549                     ISP_UNLOCK(isp);
3550                     isp_prt(isp, ISP_LOGERR, "%s: cam_periph_alloc for wildcard failed", __func__);
3551                     goto out;
3552           }
3553           wperiph = cam_periph_find(wpath, "isptarg");
3554           if (wperiph == NULL) {
3555                     ISP_UNLOCK(isp);
3556                     isp_prt(isp, ISP_LOGERR, "%s: wildcard periph already allocated but doesn't exist", __func__);
3557                     goto out;
3558           }
3559 
3560           status = cam_periph_alloc(isptargctor, NULL, isptargdtor, isptargstart, "isptarg", CAM_PERIPH_BIO, path, NULL, 0, softc);
3561           if (status != CAM_REQ_CMP) {
3562                     ISP_UNLOCK(isp);
3563                     isp_prt(isp, ISP_LOGERR, "%s: cam_periph_alloc failed", __func__);
3564                     goto out;
3565           }
3566 
3567           periph = cam_periph_find(path, "isptarg");
3568           if (periph == NULL) {
3569                     ISP_UNLOCK(isp);
3570                     isp_prt(isp, ISP_LOGERR, "%s: periph already allocated but doesn't exist", __func__);
3571                     goto out;
3572           }
3573 
3574           status = xpt_register_async(AC_CONTRACT, isptargasync, isp, wpath);
3575           if (status != CAM_REQ_CMP) {
3576                     ISP_UNLOCK(isp);
3577                     isp_prt(isp, ISP_LOGERR, "%s: xpt_register_async failed", __func__);
3578                     goto out;
3579           }
3580 
3581           ISP_UNLOCK(isp);
3582 
3583           ccb = xpt_alloc_ccb();
3584 
3585           /*
3586            * Make sure role is none.
3587            */
3588           xpt_setup_ccb(&ccb->ccb_h, periph->path, 10);
3589           ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
3590           ccb->knob.xport_specific.fc.role = KNOB_ROLE_NONE;
3591 #ifdef    ISP_TEST_WWNS
3592           ccb->knob.xport_specific.fc.valid = KNOB_VALID_ROLE | KNOB_VALID_ADDRESS;
3593           ccb->knob.xport_specific.fc.wwnn = 0x508004d000000000ULL | (device_get_unit(isp->isp_osinfo.dev) << 8) | (chan << 16);
3594           ccb->knob.xport_specific.fc.wwpn = 0x508004d000000001ULL | (device_get_unit(isp->isp_osinfo.dev) << 8) | (chan << 16);
3595 #else
3596           ccb->knob.xport_specific.fc.valid = KNOB_VALID_ROLE;
3597 #endif
3598 
3599           ISP_LOCK(isp);
3600           xpt_action(ccb);
3601           ISP_UNLOCK(isp);
3602 
3603           /*
3604            * Now enable luns
3605            */
3606           xpt_setup_ccb(&ccb->ccb_h, periph->path, 10);
3607           ccb->ccb_h.func_code = XPT_EN_LUN;
3608           ccb->cel.enable = 1;
3609           ISP_LOCK(isp);
3610           xpt_action(ccb);
3611           ISP_UNLOCK(isp);
3612           if (ccb->ccb_h.status != CAM_REQ_CMP) {
3613                     xpt_free_ccb(&ccb->ccb_h);
3614                     xpt_print(periph->path, "failed to enable lun (0x%x)\n", ccb->ccb_h.status);
3615                     goto out;
3616           }
3617 
3618           xpt_setup_ccb(&ccb->ccb_h, wperiph->path, 10);
3619           ccb->ccb_h.func_code = XPT_EN_LUN;
3620           ccb->cel.enable = 1;
3621           ISP_LOCK(isp);
3622           xpt_action(ccb);
3623           ISP_UNLOCK(isp);
3624           if (ccb->ccb_h.status != CAM_REQ_CMP) {
3625                     xpt_free_ccb(&ccb->ccb_h);
3626                     xpt_print(wperiph->path, "failed to enable lun (0x%x)\n", ccb->ccb_h.status);
3627                     goto out;
3628           }
3629           xpt_free_ccb(&ccb->ccb_h);
3630           ccb = NULL; /* safety */
3631 
3632           /*
3633            * Add resources
3634            */
3635           ISP_GET_PC_ADDR(isp, chan, target_proc, wchan);
3636           for (i = 0; i < 4; i++) {
3637                     ccb = xpt_alloc_ccb();
3638                     xpt_setup_ccb(&ccb->ccb_h, wperiph->path, 1);
3639                     ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO;
3640                     ccb->ccb_h.cbfcnp = isptarg_done;
3641                     ISP_LOCK(isp);
3642                     xpt_action(ccb);
3643                     ISP_UNLOCK(isp);
3644           }
3645           for (i = 0; i < NISP_TARG_CMDS; i++) {
3646                     ccb = xpt_alloc_ccb();
3647                     xpt_setup_ccb(&ccb->ccb_h, periph->path, 1);
3648                     ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO;
3649                     ccb->ccb_h.cbfcnp = isptarg_done;
3650                     ISP_LOCK(isp);
3651                     xpt_action(ccb);
3652                     ISP_UNLOCK(isp);
3653           }
3654           for (i = 0; i < 4; i++) {
3655                     ccb = xpt_alloc_ccb();
3656                     xpt_setup_ccb(&ccb->ccb_h, wperiph->path, 1);
3657                     ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
3658                     ccb->ccb_h.cbfcnp = isptarg_done;
3659                     ISP_LOCK(isp);
3660                     xpt_action(ccb);
3661                     ISP_UNLOCK(isp);
3662           }
3663           for (i = 0; i < NISP_TARG_NOTIFIES; i++) {
3664                     ccb = xpt_alloc_ccb();
3665                     xpt_setup_ccb(&ccb->ccb_h, periph->path, 1);
3666                     ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
3667                     ccb->ccb_h.cbfcnp = isptarg_done;
3668                     ISP_LOCK(isp);
3669                     xpt_action(ccb);
3670                     ISP_UNLOCK(isp);
3671           }
3672 
3673           /*
3674            * Now turn it all back on
3675            */
3676           ccb = xpt_alloc_ccb();
3677           xpt_setup_ccb(&ccb->ccb_h, periph->path, 10);
3678           ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
3679           ccb->knob.xport_specific.fc.valid = KNOB_VALID_ROLE;
3680           ccb->knob.xport_specific.fc.role = KNOB_ROLE_TARGET;
3681           ISP_LOCK(isp);
3682           xpt_action(ccb);
3683           xpt_free_ccb(&ccb->ccb_h);
3684           ISP_UNLOCK(isp);
3685 
3686           /*
3687            * Okay, while things are still active, sleep...
3688            */
3689           ISP_LOCK(isp);
3690           for (;;) {
3691                     ISP_GET_PC(isp, chan, proc_active, i);
3692                     if (i == 0) {
3693                               break;
3694                     }
3695                     lksleep(wchan, &isp->isp_lock, PUSER, "tsnooze", 0);
3696           }
3697           ISP_UNLOCK(isp);
3698 
3699 out:
3700           if (wperiph) {
3701                     cam_periph_invalidate(wperiph);
3702           }
3703           if (periph) {
3704                     cam_periph_invalidate(periph);
3705           }
3706           if (junk_data) {
3707                     kfree(junk_data, M_ISPTARG);
3708           }
3709           if (disk_data) {
3710                     kfree(disk_data, M_ISPTARG);
3711           }
3712           if (softc) {
3713                     kfree(softc, M_ISPTARG);
3714           }
3715           xpt_free_path(path);
3716           xpt_free_path(wpath);
3717 }
3718 
3719 static void
isp_target_thread_pi(void * arg)3720 isp_target_thread_pi(void *arg)
3721 {
3722           struct isp_spi *pi = arg;
3723           isp_target_thread(cam_sim_softc(pi->sim), cam_sim_bus(pi->sim));
3724 }
3725 
3726 static void
isp_target_thread_fc(void * arg)3727 isp_target_thread_fc(void *arg)
3728 {
3729           struct isp_fc *fc = arg;
3730           isp_target_thread(cam_sim_softc(fc->sim), cam_sim_bus(fc->sim));
3731 }
3732 
3733 static int
isptarg_rwparm(uint8_t * cdb,uint8_t * dp,uint64_t dl,uint32_t offset,uint8_t ** kp,uint32_t * tl,int * lp)3734 isptarg_rwparm(uint8_t *cdb, uint8_t *dp, uint64_t dl, uint32_t offset, uint8_t **kp, uint32_t *tl, int *lp)
3735 {
3736           uint32_t cnt, curcnt;
3737           uint64_t lba;
3738 
3739           switch (cdb[0]) {
3740           case WRITE_16:
3741           case READ_16:
3742                     cnt =     (((uint32_t)cdb[10]) <<  24) |
3743                               (((uint32_t)cdb[11]) <<  16) |
3744                               (((uint32_t)cdb[12]) <<   8) |
3745                               ((uint32_t)cdb[13]);
3746 
3747                     lba =     (((uint64_t)cdb[2]) << 56) |
3748                               (((uint64_t)cdb[3]) << 48) |
3749                               (((uint64_t)cdb[4]) << 40) |
3750                               (((uint64_t)cdb[5]) << 32) |
3751                               (((uint64_t)cdb[6]) << 24) |
3752                               (((uint64_t)cdb[7]) << 16) |
3753                               (((uint64_t)cdb[8]) <<  8) |
3754                               ((uint64_t)cdb[9]);
3755                     break;
3756           case WRITE_12:
3757           case READ_12:
3758                     cnt =     (((uint32_t)cdb[6]) <<  16) |
3759                               (((uint32_t)cdb[7]) <<   8) |
3760                               ((u_int32_t)cdb[8]);
3761 
3762                     lba =     (((uint32_t)cdb[2]) << 24) |
3763                               (((uint32_t)cdb[3]) << 16) |
3764                               (((uint32_t)cdb[4]) <<  8) |
3765                               ((uint32_t)cdb[5]);
3766                     break;
3767           case WRITE_10:
3768           case READ_10:
3769                     cnt =     (((uint32_t)cdb[7]) <<  8) |
3770                               ((u_int32_t)cdb[8]);
3771 
3772                     lba =     (((uint32_t)cdb[2]) << 24) |
3773                               (((uint32_t)cdb[3]) << 16) |
3774                               (((uint32_t)cdb[4]) <<  8) |
3775                               ((uint32_t)cdb[5]);
3776                     break;
3777           case WRITE_6:
3778           case READ_6:
3779                     cnt = cdb[4];
3780                     if (cnt == 0) {
3781                               cnt = 256;
3782                     }
3783                     lba =     (((uint32_t)cdb[1] & 0x1f) << 16) |
3784                               (((uint32_t)cdb[2]) << 8) |
3785                               ((uint32_t)cdb[3]);
3786                     break;
3787           default:
3788                     return (-1);
3789           }
3790 
3791           cnt <<= DISK_SHIFT;
3792           lba <<= DISK_SHIFT;
3793 
3794           if (offset == cnt) {
3795                     *lp = 1;
3796                     return (0);
3797           }
3798 
3799           if (lba + cnt > dl) {
3800                     return (-1);
3801           }
3802 
3803 
3804           curcnt = MAX_ISP_TARG_TRANSFER;
3805           if (offset + curcnt >= cnt) {
3806                     curcnt = cnt - offset;
3807                     *lp = 1;
3808           } else {
3809                     *lp = 0;
3810           }
3811           *tl = curcnt;
3812           *kp = &dp[lba + offset];
3813           return (0);
3814 }
3815 
3816 #endif
3817 #endif
3818 
3819 static void
isp_cam_async(void * cbarg,uint32_t code,struct cam_path * path,void * arg)3820 isp_cam_async(void *cbarg, uint32_t code, struct cam_path *path, void *arg)
3821 {
3822           struct cam_sim *sim;
3823           int bus, tgt;
3824           ispsoftc_t *isp;
3825 
3826           sim = (struct cam_sim *)cbarg;
3827           isp = (ispsoftc_t *) cam_sim_softc(sim);
3828           bus = cam_sim_bus(sim);
3829           tgt = xpt_path_target_id(path);
3830 
3831           switch (code) {
3832           case AC_LOST_DEVICE:
3833                     if (IS_SCSI(isp)) {
3834                               uint16_t oflags, nflags;
3835                               sdparam *sdp = SDPARAM(isp, bus);
3836 
3837                               if (tgt >= 0) {
3838                                         nflags = sdp->isp_devparam[tgt].nvrm_flags;
3839 #ifndef   ISP_TARGET_MODE
3840                                         nflags &= DPARM_SAFE_DFLT;
3841                                         if (isp->isp_loaded_fw) {
3842                                                   nflags |= DPARM_NARROW | DPARM_ASYNC;
3843                                         }
3844 #else
3845                                         nflags = DPARM_DEFAULT;
3846 #endif
3847                                         oflags = sdp->isp_devparam[tgt].goal_flags;
3848                                         sdp->isp_devparam[tgt].goal_flags = nflags;
3849                                         sdp->isp_devparam[tgt].dev_update = 1;
3850                                         sdp->update = 1;
3851                                         (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, bus);
3852                                         sdp->isp_devparam[tgt].goal_flags = oflags;
3853                               }
3854                     }
3855                     break;
3856           default:
3857                     isp_prt(isp, ISP_LOGWARN, "isp_cam_async: Code 0x%x", code);
3858                     break;
3859           }
3860 }
3861 
3862 static void
isp_poll(struct cam_sim * sim)3863 isp_poll(struct cam_sim *sim)
3864 {
3865           ispsoftc_t *isp = cam_sim_softc(sim);
3866           uint32_t isr;
3867           uint16_t sema, mbox;
3868 
3869           if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
3870                     isp_intr(isp, isr, sema, mbox);
3871           }
3872 }
3873 
3874 
3875 static void
isp_watchdog(void * arg)3876 isp_watchdog(void *arg)
3877 {
3878           struct ccb_scsiio *xs = arg;
3879           ispsoftc_t *isp;
3880           uint32_t ohandle = ISP_HANDLE_FREE, handle;
3881 
3882           isp = XS_ISP(xs);
3883           ISP_LOCK(isp);
3884 
3885           handle = isp_find_handle(isp, xs);
3886 
3887           if (handle != ISP_HANDLE_FREE && !XS_CMD_WPEND_P(xs)) {
3888                     isp_xs_prt(isp, xs, ISP_LOGWARN, "first watchdog (handle 0x%x) timed out- deferring for grace period", handle);
3889                     callout_reset(&PISP_PCMD(xs)->wdog, 2 * hz, isp_watchdog, xs);
3890                     XS_CMD_S_WPEND(xs);
3891                     ISP_UNLOCK(isp);
3892                     return;
3893           }
3894           XS_C_TACTIVE(xs);
3895 
3896           /*
3897            * Hand crank the interrupt code just to be sure the command isn't stuck somewhere.
3898            */
3899           if (handle != ISP_HANDLE_FREE) {
3900                     uint32_t isr;
3901                     uint16_t sema, mbox;
3902                     if (ISP_READ_ISR(isp, &isr, &sema, &mbox) != 0) {
3903                               isp_intr(isp, isr, sema, mbox);
3904                     }
3905                     ohandle = handle;
3906                     handle = isp_find_handle(isp, xs);
3907           }
3908           if (handle != ISP_HANDLE_FREE) {
3909                     /*
3910                      * Try and make sure the command is really dead before
3911                      * we release the handle (and DMA resources) for reuse.
3912                      *
3913                      * If we are successful in aborting the command then
3914                      * we're done here because we'll get the command returned
3915                      * back separately.
3916                      */
3917                     if (isp_control(isp, ISPCTL_ABORT_CMD, xs) == 0) {
3918                               ISP_UNLOCK(isp);
3919                               return;
3920                     }
3921 
3922                     /*
3923                      * Note that after calling the above, the command may in
3924                      * fact have been completed.
3925                      */
3926                     xs = isp_find_xs(isp, handle);
3927 
3928                     /*
3929                      * If the command no longer exists, then we won't
3930                      * be able to find the xs again with this handle.
3931                      */
3932                     if (xs == NULL) {
3933                               ISP_UNLOCK(isp);
3934                               return;
3935                     }
3936 
3937                     /*
3938                      * After this point, the command is really dead.
3939                      */
3940                     if (XS_XFRLEN(xs)) {
3941                               ISP_DMAFREE(isp, xs, handle);
3942                     }
3943                     isp_destroy_handle(isp, handle);
3944                     isp_prt(isp, ISP_LOGERR, "%s: timeout for handle 0x%x", __func__, handle);
3945                     XS_SETERR(xs, CAM_CMD_TIMEOUT);
3946                     isp_prt_endcmd(isp, xs);
3947                     isp_done(xs);
3948           } else {
3949                     if (ohandle != ISP_HANDLE_FREE) {
3950                               isp_prt(isp, ISP_LOGWARN, "%s: timeout for handle 0x%x, recovered during interrupt", __func__, ohandle);
3951                     } else {
3952                               isp_prt(isp, ISP_LOGWARN, "%s: timeout for handle already free", __func__);
3953                     }
3954           }
3955           ISP_UNLOCK(isp);
3956 }
3957 
3958 static void
isp_bus_scan_cb(struct cam_periph * periph,union ccb * ccb)3959 isp_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
3960 {
3961           if (ccb->ccb_h.status != CAM_REQ_CMP)
3962                     kprintf("cam_scan_callback: failure status = %x\n",
3963                               ccb->ccb_h.status);
3964 
3965           xpt_free_path(ccb->ccb_h.path);
3966           xpt_free_ccb(&ccb->ccb_h);
3967 }
3968 
3969 static void
isp_make_here(ispsoftc_t * isp,int chan,int tgt)3970 isp_make_here(ispsoftc_t *isp, int chan, int tgt)
3971 {
3972           union ccb *ccb;
3973           struct isp_fc *fc = ISP_FC_PC(isp, chan);
3974 
3975           if (isp_autoconfig == 0) {
3976                     return;
3977           }
3978 
3979           /*
3980            * Allocate a CCB, create a wildcard path for this target and schedule a rescan.
3981            */
3982           ccb = xpt_alloc_ccb();
3983           if (ccb == NULL) {
3984                     isp_prt(isp, ISP_LOGWARN, "Chan %d unable to alloc CCB for rescan", chan);
3985                     return;
3986           }
3987           if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(fc->sim), tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
3988                     isp_prt(isp, ISP_LOGWARN, "unable to create path for rescan");
3989                     xpt_free_ccb(&ccb->ccb_h);
3990                     return;
3991           }
3992           xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, 5/*priority (low)*/);
3993           ccb->ccb_h.func_code = XPT_SCAN_BUS;
3994           ccb->ccb_h.cbfcnp = isp_bus_scan_cb;
3995           ccb->crcn.flags = CAM_FLAG_NONE;
3996           xpt_action(ccb);
3997 }
3998 
3999 static void
isp_make_gone(ispsoftc_t * isp,int chan,int tgt)4000 isp_make_gone(ispsoftc_t *isp, int chan, int tgt)
4001 {
4002           struct cam_path *tp;
4003           struct isp_fc *fc = ISP_FC_PC(isp, chan);
4004 
4005           if (isp_autoconfig == 0) {
4006                     return;
4007           }
4008           if (xpt_create_path(&tp, NULL, cam_sim_path(fc->sim), tgt, CAM_LUN_WILDCARD) == CAM_REQ_CMP) {
4009                     xpt_async(AC_LOST_DEVICE, tp, NULL);
4010                     xpt_free_path(tp);
4011           }
4012 }
4013 
4014 /*
4015  * Gone Device Timer Function- when we have decided that a device has gone
4016  * away, we wait a specific period of time prior to telling the OS it has
4017  * gone away.
4018  *
4019  * This timer function fires once a second and then scans the port database
4020  * for devices that are marked dead but still have a virtual target assigned.
4021  * We decrement a counter for that port database entry, and when it hits zero,
4022  * we tell the OS the device has gone away.
4023  */
4024 static void
isp_gdt(void * arg)4025 isp_gdt(void *arg)
4026 {
4027           struct isp_fc *fc = arg;
4028 
4029           ISP_LOCK(fc->isp);
4030           taskqueue_enqueue(taskqueue_swi, &fc->gtask);
4031           ISP_UNLOCK(fc->isp);
4032 }
4033 
4034 static void
isp_gdt_task(void * arg,int pending)4035 isp_gdt_task(void *arg, int pending)
4036 {
4037           struct isp_fc *fc = arg;
4038           ispsoftc_t *isp = fc->isp;
4039           int chan = fc - isp->isp_osinfo.pc.fc;
4040           fcportdb_t *lp;
4041           int dbidx, tgt, more_to_do = 0;
4042 
4043           ISP_LOCK(isp);
4044           isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GDT timer expired", chan);
4045           for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
4046                     lp = &FCPARAM(isp, chan)->portdb[dbidx];
4047 
4048                     if (lp->state != FC_PORTDB_STATE_ZOMBIE) {
4049                               continue;
4050                     }
4051                     if (lp->dev_map_idx == 0 || lp->target_mode) {
4052                               continue;
4053                     }
4054                     if (lp->gone_timer != 0) {
4055                               isp_prt(isp, ISP_LOGSANCFG, "%s: Chan %d more to do for target %u (timer=%u)", __func__, chan, lp->dev_map_idx - 1, lp->gone_timer);
4056                               lp->gone_timer -= 1;
4057                               more_to_do++;
4058                               continue;
4059                     }
4060                     tgt = lp->dev_map_idx - 1;
4061                     FCPARAM(isp, chan)->isp_dev_map[tgt] = 0;
4062                     lp->dev_map_idx = 0;
4063                     lp->state = FC_PORTDB_STATE_NIL;
4064                     isp_prt(isp, ISP_LOGCONFIG, prom3, chan, lp->portid, tgt, "Gone Device Timeout");
4065                     isp_make_gone(isp, chan, tgt);
4066           }
4067           if (fc->ready) {
4068                     if (more_to_do) {
4069                               callout_reset(&fc->gdt, hz, isp_gdt, fc);
4070                     } else {
4071                               callout_deactivate(&fc->gdt);
4072                               isp_prt(isp, ISP_LOGSANCFG, "Chan %d Stopping Gone Device Timer @ %lu", chan, (unsigned long) time_second);
4073                     }
4074           }
4075           ISP_UNLOCK(isp);
4076 }
4077 
4078 /*
4079  * Loop Down Timer Function- when loop goes down, a timer is started and
4080  * and after it expires we come here and take all probational devices that
4081  * the OS knows about and the tell the OS that they've gone away.
4082  *
4083  * We don't clear the devices out of our port database because, when loop
4084  * come back up, we have to do some actual cleanup with the chip at that
4085  * point (implicit PLOGO, e.g., to get the chip's port database state right).
4086  */
4087 static void
isp_ldt(void * arg)4088 isp_ldt(void *arg)
4089 {
4090           struct isp_fc *fc = arg;
4091 
4092           ISP_LOCK(fc->isp);
4093           taskqueue_enqueue(taskqueue_swi, &fc->ltask);
4094           ISP_UNLOCK(fc->isp);
4095 }
4096 
4097 static void
isp_ldt_task(void * arg,int pending)4098 isp_ldt_task(void *arg, int pending)
4099 {
4100           struct isp_fc *fc = arg;
4101           ispsoftc_t *isp = fc->isp;
4102           int chan = fc - isp->isp_osinfo.pc.fc;
4103           fcportdb_t *lp;
4104           int dbidx, tgt, i;
4105 
4106           ISP_LOCK(isp);
4107           isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d Loop Down Timer expired @ %lu", chan, (unsigned long) time_second);
4108           callout_deactivate(&fc->ldt);
4109 
4110           /*
4111            * Notify to the OS all targets who we now consider have departed.
4112            */
4113           for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
4114                     lp = &FCPARAM(isp, chan)->portdb[dbidx];
4115 
4116                     if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
4117                               continue;
4118                     }
4119                     if (lp->dev_map_idx == 0 || lp->target_mode) {
4120                               continue;
4121                     }
4122 
4123                     /*
4124                      * XXX: CLEAN UP AND COMPLETE ANY PENDING COMMANDS FIRST!
4125                      */
4126 
4127 
4128                     for (i = 0; i < isp->isp_maxcmds; i++) {
4129                               struct ccb_scsiio *xs;
4130 
4131                               if (!ISP_VALID_HANDLE(isp, isp->isp_xflist[i].handle)) {
4132                                         continue;
4133                               }
4134                               if ((xs = isp->isp_xflist[i].cmd) == NULL) {
4135                                         continue;
4136                         }
4137                               if (dbidx != (FCPARAM(isp, chan)->isp_dev_map[XS_TGT(xs)] - 1)) {
4138                                         continue;
4139                               }
4140                               isp_prt(isp, ISP_LOGWARN, "command handle 0x%08x for %d.%d.%d orphaned by loop down timeout",
4141                                   isp->isp_xflist[i].handle, chan, XS_TGT(xs), XS_LUN(xs));
4142                     }
4143 
4144                     /*
4145                      * Mark that we've announced that this device is gone....
4146                      */
4147                     lp->reserved = 1;
4148 
4149                     /*
4150                      * but *don't* change the state of the entry. Just clear
4151                      * any target id stuff and announce to CAM that the
4152                      * device is gone. This way any necessary PLOGO stuff
4153                      * will happen when loop comes back up.
4154                      */
4155 
4156                     tgt = lp->dev_map_idx - 1;
4157                     FCPARAM(isp, chan)->isp_dev_map[tgt] = 0;
4158                     lp->dev_map_idx = 0;
4159                     lp->state = FC_PORTDB_STATE_NIL;
4160                     isp_prt(isp, ISP_LOGCONFIG, prom3, chan, lp->portid, tgt, "Loop Down Timeout");
4161                     isp_make_gone(isp, chan, tgt);
4162           }
4163 
4164           if (FCPARAM(isp, chan)->role & ISP_ROLE_INITIATOR) {
4165                     isp_unfreeze_loopdown(isp, chan);
4166           }
4167           /*
4168            * The loop down timer has expired. Wake up the kthread
4169            * to notice that fact (or make it false).
4170            */
4171           fc->loop_dead = 1;
4172           fc->loop_down_time = fc->loop_down_limit+1;
4173           wakeup(fc);
4174           ISP_UNLOCK(isp);
4175 }
4176 
4177 static void
isp_kthread(void * arg)4178 isp_kthread(void *arg)
4179 {
4180           struct isp_fc *fc = arg;
4181           ispsoftc_t *isp = fc->isp;
4182           int chan = fc - isp->isp_osinfo.pc.fc;
4183           int slp = 0;
4184 
4185           lockmgr(&isp->isp_osinfo.lock, LK_EXCLUSIVE);
4186 
4187           for (;;) {
4188                     int lb, lim;
4189 
4190                     isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d checking FC state", __func__, chan);
4191                     lb = isp_fc_runstate(isp, chan, 250000);
4192 
4193                     /*
4194                      * Our action is different based upon whether we're supporting
4195                      * Initiator mode or not. If we are, we might freeze the simq
4196                      * when loop is down and set all sorts of different delays to
4197                      * check again.
4198                      *
4199                      * If not, we simply just wait for loop to come up.
4200                      */
4201                     if (lb && (FCPARAM(isp, chan)->role & ISP_ROLE_INITIATOR)) {
4202                               /*
4203                                * Increment loop down time by the last sleep interval
4204                                */
4205                               fc->loop_down_time += slp;
4206 
4207                               if (lb < 0) {
4208                                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC loop not up (down count %d)", __func__, chan, fc->loop_down_time);
4209                               } else {
4210                                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC got to %d (down count %d)", __func__, chan, lb, fc->loop_down_time);
4211                               }
4212 
4213                               /*
4214                                * If we've never seen loop up and we've waited longer
4215                                * than quickboot time, or we've seen loop up but we've
4216                                * waited longer than loop_down_limit, give up and go
4217                                * to sleep until loop comes up.
4218                                */
4219                               if (FCPARAM(isp, chan)->loop_seen_once == 0) {
4220                                         lim = isp_quickboot_time;
4221                               } else {
4222                                         lim = fc->loop_down_limit;
4223                               }
4224                               if (fc->loop_down_time >= lim) {
4225                                         isp_freeze_loopdown(isp, chan, "loop limit hit");
4226                                         slp = 0;
4227                               } else if (fc->loop_down_time < 10) {
4228                                         slp = 1;
4229                               } else if (fc->loop_down_time < 30) {
4230                                         slp = 5;
4231                               } else if (fc->loop_down_time < 60) {
4232                                         slp = 10;
4233                               } else if (fc->loop_down_time < 120) {
4234                                         slp = 20;
4235                               } else {
4236                                         slp = 30;
4237                               }
4238 
4239                     } else if (lb) {
4240                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC Loop Down", __func__, chan);
4241                               fc->loop_down_time += slp;
4242                               slp = 60;
4243                     } else {
4244                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC state OK", __func__, chan);
4245                               fc->loop_down_time = 0;
4246                               slp = 0;
4247                     }
4248 
4249 
4250                     /*
4251                      * If this is past the first loop up or the loop is dead and if we'd frozen the simq, unfreeze it
4252                      * now so that CAM can start sending us commands.
4253                      *
4254                      * If the FC state isn't okay yet, they'll hit that in isp_start which will freeze the queue again
4255                      * or kill the commands, as appropriate.
4256                      */
4257 
4258                     if (FCPARAM(isp, chan)->loop_seen_once || fc->loop_dead) {
4259                               isp_unfreeze_loopdown(isp, chan);
4260                     }
4261 
4262                     isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d sleep time %d", __func__, chan, slp);
4263 
4264                     lksleep(fc, &isp->isp_osinfo.lock, 0, "ispf", slp * hz);
4265 
4266                     /*
4267                      * If slp is zero, we're waking up for the first time after
4268                      * things have been okay. In this case, we set a deferral state
4269                      * for all commands and delay hysteresis seconds before starting
4270                      * the FC state evaluation. This gives the loop/fabric a chance
4271                      * to settle.
4272                      */
4273                     if (slp == 0 && fc->hysteresis) {
4274                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d sleep hysteresis ticks %d", __func__, chan, fc->hysteresis * hz);
4275                               lockmgr(&isp->isp_osinfo.lock, LK_RELEASE);
4276                               tsleep(isp_kthread, 0, "ispt", fc->hysteresis * hz);
4277                               lockmgr(&isp->isp_osinfo.lock, LK_EXCLUSIVE);
4278                     }
4279           }
4280           lockmgr(&isp->isp_osinfo.lock, LK_RELEASE);
4281 }
4282 
4283 static void
isp_action(struct cam_sim * sim,union ccb * ccb)4284 isp_action(struct cam_sim *sim, union ccb *ccb)
4285 {
4286           int bus, tgt, ts, error, lim;
4287           ispsoftc_t *isp;
4288           struct ccb_trans_settings *cts;
4289 
4290           CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
4291 
4292           isp = (ispsoftc_t *)cam_sim_softc(sim);
4293           KKASSERT(lockstatus(&isp->isp_lock, curthread) != 0);
4294 
4295           if (isp->isp_state != ISP_RUNSTATE && ccb->ccb_h.func_code == XPT_SCSI_IO) {
4296                     isp_init(isp);
4297                     if (isp->isp_state != ISP_INITSTATE) {
4298                               /*
4299                                * Lie. Say it was a selection timeout.
4300                                */
4301                               ccb->ccb_h.status = CAM_SEL_TIMEOUT | CAM_DEV_QFRZN;
4302                               xpt_freeze_devq(ccb->ccb_h.path, 1);
4303                               xpt_done(ccb);
4304                               return;
4305                     }
4306                     isp->isp_state = ISP_RUNSTATE;
4307           }
4308           isp_prt(isp, ISP_LOGDEBUG2, "isp_action code %x", ccb->ccb_h.func_code);
4309           ISP_PCMD(ccb) = NULL;
4310 
4311           switch (ccb->ccb_h.func_code) {
4312           case XPT_SCSI_IO:   /* Execute the requested I/O operation */
4313                     bus = XS_CHANNEL(ccb);
4314                     /*
4315                      * Do a couple of preliminary checks...
4316                      */
4317                     if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
4318                               if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
4319                                         ccb->ccb_h.status = CAM_REQ_INVALID;
4320                                         xpt_done(ccb);
4321                                         break;
4322                               }
4323                     }
4324 #ifdef    DIAGNOSTIC
4325                     if (ccb->ccb_h.target_id > (ISP_MAX_TARGETS(isp) - 1)) {
4326                               xpt_print(ccb->ccb_h.path, "invalid target\n");
4327                               ccb->ccb_h.status = CAM_PATH_INVALID;
4328                     } else if (ccb->ccb_h.target_lun > (ISP_MAX_LUNS(isp) - 1)) {
4329                               xpt_print(ccb->ccb_h.path, "invalid lun\n");
4330                               ccb->ccb_h.status = CAM_PATH_INVALID;
4331                     }
4332                     if (ccb->ccb_h.status == CAM_PATH_INVALID) {
4333                               xpt_done(ccb);
4334                               break;
4335                     }
4336 #endif
4337                     ccb->csio.scsi_status = SCSI_STATUS_OK;
4338                     if (isp_get_pcmd(isp, ccb)) {
4339                               isp_prt(isp, ISP_LOGWARN, "out of PCMDs");
4340                               cam_freeze_devq(ccb->ccb_h.path);
4341                               cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
4342                               xpt_done(ccb);
4343                               break;
4344                     }
4345                     error = isp_start((XS_T *) ccb);
4346                     switch (error) {
4347                     case CMD_QUEUED:
4348                               XS_CMD_S_CLEAR(ccb);
4349                               ccb->ccb_h.status |= CAM_SIM_QUEUED;
4350                               if (ccb->ccb_h.timeout == CAM_TIME_INFINITY) {
4351                                         break;
4352                               }
4353                               ts = ccb->ccb_h.timeout;
4354                               if (ts == CAM_TIME_DEFAULT) {
4355                                         ts = 60*1000;
4356                               }
4357                               ts = isp_mstohz(ts);
4358                               XS_S_TACTIVE(ccb);
4359                               callout_reset(&PISP_PCMD(ccb)->wdog, ts, isp_watchdog, ccb);
4360                               break;
4361                     case CMD_RQLATER:
4362                               /*
4363                                * We get this result for FC devices if the loop state isn't ready yet
4364                                * or if the device in question has gone zombie on us.
4365                                *
4366                                * If we've never seen Loop UP at all, we requeue this request and wait
4367                                * for the initial loop up delay to expire.
4368                                */
4369                               lim = ISP_FC_PC(isp, bus)->loop_down_limit;
4370                               if (FCPARAM(isp, bus)->loop_seen_once == 0 || ISP_FC_PC(isp, bus)->loop_down_time >= lim) {
4371                                         if (FCPARAM(isp, bus)->loop_seen_once == 0) {
4372                                                   isp_prt(isp, ISP_LOGDEBUG0, "%d.%d loop not seen yet @ %lu", XS_TGT(ccb), XS_LUN(ccb), (unsigned long) time_second);
4373                                         } else {
4374                                                   isp_prt(isp, ISP_LOGDEBUG0, "%d.%d downtime (%d) > lim (%d)", XS_TGT(ccb), XS_LUN(ccb), ISP_FC_PC(isp, bus)->loop_down_time, lim);
4375                                         }
4376                                         ccb->ccb_h.status = CAM_SEL_TIMEOUT|CAM_DEV_QFRZN;
4377                                         xpt_freeze_devq(ccb->ccb_h.path, 1);
4378                                         isp_free_pcmd(isp, ccb);
4379                                         xpt_done(ccb);
4380                                         break;
4381                               }
4382                               isp_prt(isp, ISP_LOGDEBUG0, "%d.%d retry later", XS_TGT(ccb), XS_LUN(ccb));
4383                               cam_freeze_devq(ccb->ccb_h.path);
4384                               cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 1000, 0);
4385                               XS_SETERR(ccb, CAM_REQUEUE_REQ);
4386                               isp_free_pcmd(isp, ccb);
4387                               xpt_done(ccb);
4388                               break;
4389                     case CMD_EAGAIN:
4390                               isp_free_pcmd(isp, ccb);
4391                               cam_freeze_devq(ccb->ccb_h.path);
4392                               cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 100, 0);
4393                               XS_SETERR(ccb, CAM_REQUEUE_REQ);
4394                               xpt_done(ccb);
4395                               break;
4396                     case CMD_COMPLETE:
4397                               isp_done((struct ccb_scsiio *) ccb);
4398                               break;
4399                     default:
4400                               isp_prt(isp, ISP_LOGERR, "What's this? 0x%x at %d in file %s", error, __LINE__, __FILE__);
4401                               XS_SETERR(ccb, CAM_REQ_CMP_ERR);
4402                               isp_free_pcmd(isp, ccb);
4403                               xpt_done(ccb);
4404                     }
4405                     break;
4406 
4407 #ifdef    ISP_TARGET_MODE
4408           case XPT_EN_LUN:              /* Enable/Disable LUN as a target */
4409                     if (ccb->cel.enable) {
4410                               isp_enable_lun(isp, ccb);
4411                     } else {
4412                               isp_disable_lun(isp, ccb);
4413                     }
4414                     break;
4415           case XPT_IMMED_NOTIFY:
4416           case XPT_IMMEDIATE_NOTIFY:    /* Add Immediate Notify Resource */
4417           case XPT_ACCEPT_TARGET_IO:    /* Add Accept Target IO Resource */
4418           {
4419                     tstate_t *tptr = get_lun_statep(isp, XS_CHANNEL(ccb), ccb->ccb_h.target_lun);
4420                     if (tptr == NULL) {
4421                               tptr = get_lun_statep(isp, XS_CHANNEL(ccb), CAM_LUN_WILDCARD);
4422                     }
4423                     if (tptr == NULL) {
4424                               const char *str;
4425                               uint32_t tag;
4426 
4427                               if (ccb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY) {
4428                                         str = "XPT_IMMEDIATE_NOTIFY";
4429                                         tag = ccb->cin1.seq_id;
4430                               } else {
4431                                         tag = ccb->atio.tag_id;
4432                                         str = "XPT_ACCEPT_TARGET_IO";
4433                               }
4434                               ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "%s: [0x%x] no state pointer found for %s\n", __func__, tag, str);
4435                               dump_tstates(isp, XS_CHANNEL(ccb));
4436                               ccb->ccb_h.status = CAM_DEV_NOT_THERE;
4437                               break;
4438                     }
4439                     ccb->ccb_h.sim_priv.entries[0].field = 0;
4440                     ccb->ccb_h.sim_priv.entries[1].ptr = isp;
4441                     ccb->ccb_h.flags = 0;
4442 
4443                     if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
4444                               if (ccb->atio.tag_id) {
4445                                         atio_private_data_t *atp = isp_get_atpd(isp, tptr, ccb->atio.tag_id);
4446                                         if (atp) {
4447                                                   isp_put_atpd(isp, tptr, atp);
4448                                         }
4449                               }
4450                               tptr->atio_count++;
4451                               SLIST_INSERT_HEAD(&tptr->atios, &ccb->ccb_h, sim_links.sle);
4452                               ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "Put FREE ATIO (tag id 0x%x), count now %d\n",
4453                                   ((struct ccb_accept_tio *)ccb)->tag_id, tptr->atio_count);
4454                     } else if (ccb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY) {
4455                               if (ccb->cin1.tag_id) {
4456                                         inot_private_data_t *ntp = isp_find_ntpd(isp, tptr, ccb->cin1.tag_id, ccb->cin1.seq_id);
4457                                         if (ntp) {
4458                                                   isp_put_ntpd(isp, tptr, ntp);
4459                                         }
4460                               }
4461                               tptr->inot_count++;
4462                               SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h, sim_links.sle);
4463                               ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "Put FREE INOT, (seq id 0x%x) count now %d\n",
4464                                   ((struct ccb_immediate_notify *)ccb)->seq_id, tptr->inot_count);
4465                     } else if (ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
4466                               tptr->inot_count++;
4467                               SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h, sim_links.sle);
4468                               ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "Put FREE INOT, (seq id 0x%x) count now %d\n",
4469                                   ((struct ccb_immediate_notify *)ccb)->seq_id, tptr->inot_count);
4470                     }
4471                     rls_lun_statep(isp, tptr);
4472                     ccb->ccb_h.status = CAM_REQ_INPROG;
4473                     break;
4474           }
4475           case XPT_NOTIFY_ACK:
4476                     ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4477                     break;
4478           case XPT_NOTIFY_ACKNOWLEDGE:            /* notify ack */
4479           {
4480                     tstate_t *tptr;
4481                     inot_private_data_t *ntp;
4482 
4483                     /*
4484                      * XXX: Because we cannot guarantee that the path information in the notify acknowledge ccb
4485                      * XXX: matches that for the immediate notify, we have to *search* for the notify structure
4486                      */
4487                     /*
4488                      * All the relevant path information is in the associated immediate notify
4489                      */
4490                     ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "%s: [0x%x] NOTIFY ACKNOWLEDGE for 0x%x seen\n", __func__, ccb->cna2.tag_id, ccb->cna2.seq_id);
4491                     ntp = get_ntp_from_tagdata(isp, ccb->cna2.tag_id, ccb->cna2.seq_id, &tptr);
4492                     if (ntp == NULL) {
4493                               ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "%s: [0x%x] XPT_NOTIFY_ACKNOWLEDGE of 0x%x cannot find ntp private data\n", __func__,
4494                                    ccb->cna2.tag_id, ccb->cna2.seq_id);
4495                               ccb->ccb_h.status = CAM_DEV_NOT_THERE;
4496                               xpt_done(ccb);
4497                               break;
4498                     }
4499                     if (isp_handle_platform_target_notify_ack(isp, &ntp->rd.nt)) {
4500                               rls_lun_statep(isp, tptr);
4501                               cam_freeze_devq(ccb->ccb_h.path);
4502                               cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 1000, 0);
4503                               XS_SETERR(ccb, CAM_REQUEUE_REQ);
4504                               break;
4505                     }
4506                     isp_put_ntpd(isp, tptr, ntp);
4507                     rls_lun_statep(isp, tptr);
4508                     ccb->ccb_h.status = CAM_REQ_CMP;
4509                     ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "%s: [0x%x] calling xpt_done for tag 0x%x\n", __func__, ccb->cna2.tag_id, ccb->cna2.seq_id);
4510                     xpt_done(ccb);
4511                     break;
4512           }
4513           case XPT_CONT_TARGET_IO:
4514                     isp_target_start_ctio(isp, ccb);
4515                     break;
4516 #endif
4517           case XPT_RESET_DEV:           /* BDR the specified SCSI device */
4518 
4519                     bus = cam_sim_bus(xpt_path_sim(ccb->ccb_h.path));
4520                     tgt = ccb->ccb_h.target_id;
4521                     tgt |= (bus << 16);
4522 
4523                     error = isp_control(isp, ISPCTL_RESET_DEV, bus, tgt);
4524                     if (error) {
4525                               ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4526                     } else {
4527                               ccb->ccb_h.status = CAM_REQ_CMP;
4528                     }
4529                     xpt_done(ccb);
4530                     break;
4531           case XPT_ABORT:                         /* Abort the specified CCB */
4532           {
4533                     union ccb *accb = ccb->cab.abort_ccb;
4534                     switch (accb->ccb_h.func_code) {
4535 #ifdef    ISP_TARGET_MODE
4536                     case XPT_ACCEPT_TARGET_IO:
4537                               isp_target_mark_aborted(isp, accb);
4538                               break;
4539 #endif
4540                     case XPT_SCSI_IO:
4541                               error = isp_control(isp, ISPCTL_ABORT_CMD, ccb);
4542                               if (error) {
4543                                         ccb->ccb_h.status = CAM_UA_ABORT;
4544                               } else {
4545                                         ccb->ccb_h.status = CAM_REQ_CMP;
4546                               }
4547                               break;
4548                     default:
4549                               ccb->ccb_h.status = CAM_REQ_INVALID;
4550                               break;
4551                     }
4552                     /*
4553                      * This is not a queued CCB, so the caller expects it to be
4554                      * complete when control is returned.
4555                      */
4556                     break;
4557           }
4558 #define   IS_CURRENT_SETTINGS(c)        (c->type == CTS_TYPE_CURRENT_SETTINGS)
4559           case XPT_SET_TRAN_SETTINGS:   /* Nexus Settings */
4560                     cts = &ccb->cts;
4561                     if (!IS_CURRENT_SETTINGS(cts)) {
4562                               ccb->ccb_h.status = CAM_REQ_INVALID;
4563                               xpt_done(ccb);
4564                               break;
4565                     }
4566                     tgt = cts->ccb_h.target_id;
4567                     bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
4568                     if (IS_SCSI(isp)) {
4569                               struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi;
4570                               struct ccb_trans_settings_spi *spi = &cts->xport_specific.spi;
4571                               sdparam *sdp = SDPARAM(isp, bus);
4572                               uint16_t *dptr;
4573 
4574                               if (spi->valid == 0 && scsi->valid == 0) {
4575                                         ccb->ccb_h.status = CAM_REQ_CMP;
4576                                         xpt_done(ccb);
4577                                         break;
4578                               }
4579 
4580                               /*
4581                                * We always update (internally) from goal_flags
4582                                * so any request to change settings just gets
4583                                * vectored to that location.
4584                                */
4585                               dptr = &sdp->isp_devparam[tgt].goal_flags;
4586 
4587                               if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
4588                                         if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
4589                                                   *dptr |= DPARM_DISC;
4590                                         else
4591                                                   *dptr &= ~DPARM_DISC;
4592                               }
4593 
4594                               if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
4595                                         if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
4596                                                   *dptr |= DPARM_TQING;
4597                                         else
4598                                                   *dptr &= ~DPARM_TQING;
4599                               }
4600 
4601                               if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
4602                                         if (spi->bus_width == MSG_EXT_WDTR_BUS_16_BIT)
4603                                                   *dptr |= DPARM_WIDE;
4604                                         else
4605                                                   *dptr &= ~DPARM_WIDE;
4606                               }
4607 
4608                               /*
4609                                * XXX: FIX ME
4610                                */
4611                               if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) && (spi->valid & CTS_SPI_VALID_SYNC_RATE) && (spi->sync_period && spi->sync_offset)) {
4612                                         *dptr |= DPARM_SYNC;
4613                                         /*
4614                                          * XXX: CHECK FOR LEGALITY
4615                                          */
4616                                         sdp->isp_devparam[tgt].goal_period = spi->sync_period;
4617                                         sdp->isp_devparam[tgt].goal_offset = spi->sync_offset;
4618                               } else {
4619                                         *dptr &= ~DPARM_SYNC;
4620                               }
4621                               isp_prt(isp, ISP_LOGDEBUG0, "SET (%d.%d.%d) to flags %x off %x per %x", bus, tgt, cts->ccb_h.target_lun, sdp->isp_devparam[tgt].goal_flags,
4622                                   sdp->isp_devparam[tgt].goal_offset, sdp->isp_devparam[tgt].goal_period);
4623                               sdp->isp_devparam[tgt].dev_update = 1;
4624                               sdp->update = 1;
4625                     }
4626                     ccb->ccb_h.status = CAM_REQ_CMP;
4627                     xpt_done(ccb);
4628                     break;
4629           case XPT_GET_TRAN_SETTINGS:
4630                     cts = &ccb->cts;
4631                     tgt = cts->ccb_h.target_id;
4632                     bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
4633                     if (IS_FC(isp)) {
4634                               fcparam *fcp = FCPARAM(isp, bus);
4635                               struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi;
4636                               struct ccb_trans_settings_fc *fc = &cts->xport_specific.fc;
4637                               unsigned int hdlidx;
4638 
4639                               cts->protocol = PROTO_SCSI;
4640                               cts->protocol_version = SCSI_REV_2;
4641                               cts->transport = XPORT_FC;
4642                               cts->transport_version = 0;
4643 
4644                               scsi->valid = CTS_SCSI_VALID_TQ;
4645                               scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
4646                               fc->valid = CTS_FC_VALID_SPEED;
4647                               fc->bitrate = 100000;
4648                               fc->bitrate *= fcp->isp_gbspeed;
4649                               hdlidx = fcp->isp_dev_map[tgt] - 1;
4650                               if (hdlidx < MAX_FC_TARG) {
4651                                         fcportdb_t *lp = &fcp->portdb[hdlidx];
4652                                         fc->wwnn = lp->node_wwn;
4653                                         fc->wwpn = lp->port_wwn;
4654                                         fc->port = lp->portid;
4655                                         fc->valid |= CTS_FC_VALID_WWNN | CTS_FC_VALID_WWPN | CTS_FC_VALID_PORT;
4656                               }
4657                     } else {
4658                               struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi;
4659                               struct ccb_trans_settings_spi *spi = &cts->xport_specific.spi;
4660                               sdparam *sdp = SDPARAM(isp, bus);
4661                               uint16_t dval, pval, oval;
4662 
4663                               if (IS_CURRENT_SETTINGS(cts)) {
4664                                         sdp->isp_devparam[tgt].dev_refresh = 1;
4665                                         sdp->update = 1;
4666                                         (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, bus);
4667                                         dval = sdp->isp_devparam[tgt].actv_flags;
4668                                         oval = sdp->isp_devparam[tgt].actv_offset;
4669                                         pval = sdp->isp_devparam[tgt].actv_period;
4670                               } else {
4671                                         dval = sdp->isp_devparam[tgt].nvrm_flags;
4672                                         oval = sdp->isp_devparam[tgt].nvrm_offset;
4673                                         pval = sdp->isp_devparam[tgt].nvrm_period;
4674                               }
4675 
4676                               cts->protocol = PROTO_SCSI;
4677                               cts->protocol_version = SCSI_REV_2;
4678                               cts->transport = XPORT_SPI;
4679                               cts->transport_version = 2;
4680 
4681                               spi->valid = 0;
4682                               scsi->valid = 0;
4683                               spi->flags = 0;
4684                               scsi->flags = 0;
4685                               if (dval & DPARM_DISC) {
4686                                         spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
4687                               }
4688                               if ((dval & DPARM_SYNC) && oval && pval) {
4689                                         spi->sync_offset = oval;
4690                                         spi->sync_period = pval;
4691                               } else {
4692                                         spi->sync_offset = 0;
4693                                         spi->sync_period = 0;
4694                               }
4695                               spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
4696                               spi->valid |= CTS_SPI_VALID_SYNC_RATE;
4697                               spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
4698                               if (dval & DPARM_WIDE) {
4699                                         spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
4700                               } else {
4701                                         spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
4702                               }
4703                               if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
4704                                         scsi->valid = CTS_SCSI_VALID_TQ;
4705                                         if (dval & DPARM_TQING) {
4706                                                   scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
4707                                         }
4708                                         spi->valid |= CTS_SPI_VALID_DISC;
4709                               }
4710                               isp_prt(isp, ISP_LOGDEBUG0, "GET %s (%d.%d.%d) to flags %x off %x per %x", IS_CURRENT_SETTINGS(cts)? "ACTIVE" : "NVRAM",
4711                                   bus, tgt, cts->ccb_h.target_lun, dval, oval, pval);
4712                     }
4713                     ccb->ccb_h.status = CAM_REQ_CMP;
4714                     xpt_done(ccb);
4715                     break;
4716 
4717           case XPT_CALC_GEOMETRY:
4718                     cam_calc_geometry(&ccb->ccg, 1);
4719                     xpt_done(ccb);
4720                     break;
4721 
4722           case XPT_RESET_BUS:           /* Reset the specified bus */
4723                     bus = cam_sim_bus(sim);
4724                     error = isp_control(isp, ISPCTL_RESET_BUS, bus);
4725                     if (error) {
4726                               ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4727                               xpt_done(ccb);
4728                               break;
4729                     }
4730                     if (bootverbose) {
4731                               xpt_print(ccb->ccb_h.path, "reset bus on channel %d\n", bus);
4732                     }
4733                     if (IS_FC(isp)) {
4734                               xpt_async(AC_BUS_RESET, ISP_FC_PC(isp, bus)->path, 0);
4735                     } else {
4736                               xpt_async(AC_BUS_RESET, ISP_SPI_PC(isp, bus)->path, 0);
4737                     }
4738                     ccb->ccb_h.status = CAM_REQ_CMP;
4739                     xpt_done(ccb);
4740                     break;
4741 
4742           case XPT_TERM_IO:             /* Terminate the I/O process */
4743                     ccb->ccb_h.status = CAM_REQ_INVALID;
4744                     xpt_done(ccb);
4745                     break;
4746 
4747 #if 0
4748           case XPT_SET_SIM_KNOB:                  /* Set SIM knobs */
4749           {
4750                     struct ccb_sim_knob *kp = &ccb->knob;
4751                     fcparam *fcp;
4752 
4753 
4754                     if (!IS_FC(isp)) {
4755                               ccb->ccb_h.status = CAM_REQ_INVALID;
4756                               xpt_done(ccb);
4757                               break;
4758                     }
4759 
4760                     bus = cam_sim_bus(xpt_path_sim(kp->ccb_h.path));
4761                     fcp = FCPARAM(isp, bus);
4762 
4763                     if (kp->xport_specific.fc.valid & KNOB_VALID_ADDRESS) {
4764                               fcp->isp_wwnn = ISP_FC_PC(isp, bus)->def_wwnn = kp->xport_specific.fc.wwnn;
4765                               fcp->isp_wwpn = ISP_FC_PC(isp, bus)->def_wwpn = kp->xport_specific.fc.wwpn;
4766                               isp_prt(isp, ISP_LOGALL, "Setting Channel %d wwns to 0x%jx 0x%jx", bus, fcp->isp_wwnn, fcp->isp_wwpn);
4767                     }
4768                     ccb->ccb_h.status = CAM_REQ_CMP;
4769                     if (kp->xport_specific.fc.valid & KNOB_VALID_ROLE) {
4770                               int rchange = 0;
4771                               int newrole = 0;
4772 
4773                               switch (kp->xport_specific.fc.role) {
4774                               case KNOB_ROLE_NONE:
4775                                         if (fcp->role != ISP_ROLE_NONE) {
4776                                                   rchange = 1;
4777                                                   newrole = ISP_ROLE_NONE;
4778                                         }
4779                                         break;
4780                               case KNOB_ROLE_TARGET:
4781                                         if (fcp->role != ISP_ROLE_TARGET) {
4782                                                   rchange = 1;
4783                                                   newrole = ISP_ROLE_TARGET;
4784                                         }
4785                                         break;
4786                               case KNOB_ROLE_INITIATOR:
4787                                         if (fcp->role != ISP_ROLE_INITIATOR) {
4788                                                   rchange = 1;
4789                                                   newrole = ISP_ROLE_INITIATOR;
4790                                         }
4791                                         break;
4792                               case KNOB_ROLE_BOTH:
4793 #if 0
4794                                         if (fcp->role != ISP_ROLE_BOTH) {
4795                                                   rchange = 1;
4796                                                   newrole = ISP_ROLE_BOTH;
4797                                         }
4798 #else
4799                                         /*
4800                                          * We don't really support dual role at present on FC cards.
4801                                          *
4802                                          * We should, but a bunch of things are currently broken,
4803                                          * so don't allow it.
4804                                          */
4805                                         isp_prt(isp, ISP_LOGERR, "cannot support dual role at present");
4806                                         ccb->ccb_h.status = CAM_REQ_INVALID;
4807 #endif
4808                                         break;
4809                               }
4810                               if (rchange) {
4811                                         if (isp_fc_change_role(isp, bus, newrole) != 0) {
4812                                                   ccb->ccb_h.status = CAM_REQ_CMP_ERR;
4813 #ifdef    ISP_TARGET_MODE
4814                                         } else if (newrole == ISP_ROLE_TARGET || newrole == ISP_ROLE_BOTH) {
4815                                                   isp_enable_deferred_luns(isp, bus);
4816 #endif
4817                                         }
4818                               }
4819                     }
4820                     xpt_done(ccb);
4821                     break;
4822           }
4823           case XPT_GET_SIM_KNOB:                  /* Set SIM knobs */
4824           {
4825                     struct ccb_sim_knob *kp = &ccb->knob;
4826 
4827                     if (IS_FC(isp)) {
4828                               fcparam *fcp;
4829 
4830                               bus = cam_sim_bus(xpt_path_sim(kp->ccb_h.path));
4831                               fcp = FCPARAM(isp, bus);
4832 
4833                               kp->xport_specific.fc.wwnn = fcp->isp_wwnn;
4834                               kp->xport_specific.fc.wwpn = fcp->isp_wwpn;
4835                               switch (fcp->role) {
4836                               case ISP_ROLE_NONE:
4837                                         kp->xport_specific.fc.role = KNOB_ROLE_NONE;
4838                                         break;
4839                               case ISP_ROLE_TARGET:
4840                                         kp->xport_specific.fc.role = KNOB_ROLE_TARGET;
4841                                         break;
4842                               case ISP_ROLE_INITIATOR:
4843                                         kp->xport_specific.fc.role = KNOB_ROLE_INITIATOR;
4844                                         break;
4845                               case ISP_ROLE_BOTH:
4846                                         kp->xport_specific.fc.role = KNOB_ROLE_BOTH;
4847                                         break;
4848                               }
4849                               kp->xport_specific.fc.valid = KNOB_VALID_ADDRESS | KNOB_VALID_ROLE;
4850                               ccb->ccb_h.status = CAM_REQ_CMP;
4851                     } else {
4852                               ccb->ccb_h.status = CAM_REQ_INVALID;
4853                     }
4854                     xpt_done(ccb);
4855                     break;
4856           }
4857 #endif
4858           case XPT_PATH_INQ:            /* Path routing inquiry */
4859           {
4860                     struct ccb_pathinq *cpi = &ccb->cpi;
4861 
4862                     cpi->version_num = 1;
4863 #ifdef    ISP_TARGET_MODE
4864                     cpi->target_sprt = PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO;
4865 #else
4866                     cpi->target_sprt = 0;
4867 #endif
4868                     cpi->hba_eng_cnt = 0;
4869                     cpi->max_target = ISP_MAX_TARGETS(isp) - 1;
4870                     cpi->max_lun = ISP_MAX_LUNS(isp) - 1;
4871                     cpi->bus_id = cam_sim_bus(sim);
4872                     bus = cam_sim_bus(xpt_path_sim(cpi->ccb_h.path));
4873                     if (IS_FC(isp)) {
4874                               fcparam *fcp = FCPARAM(isp, bus);
4875 
4876                               cpi->hba_misc = PIM_NOBUSRESET;
4877 
4878                               /*
4879                                * Because our loop ID can shift from time to time,
4880                                * make our initiator ID out of range of our bus.
4881                                */
4882                               cpi->initiator_id = cpi->max_target + 1;
4883 
4884                               /*
4885                                * Set base transfer capabilities for Fibre Channel, for this HBA.
4886                                */
4887                               if (IS_25XX(isp)) {
4888                                         cpi->base_transfer_speed = 8000000;
4889                               } else if (IS_24XX(isp)) {
4890                                         cpi->base_transfer_speed = 4000000;
4891                               } else if (IS_23XX(isp)) {
4892                                         cpi->base_transfer_speed = 2000000;
4893                               } else {
4894                                         cpi->base_transfer_speed = 1000000;
4895                               }
4896                               cpi->hba_inquiry = PI_TAG_ABLE;
4897                               cpi->transport = XPORT_FC;
4898                               cpi->transport_version = 0;
4899                               cpi->xport_specific.fc.wwnn = fcp->isp_wwnn;
4900                               cpi->xport_specific.fc.wwpn = fcp->isp_wwpn;
4901                               cpi->xport_specific.fc.port = fcp->isp_portid;
4902                               cpi->xport_specific.fc.bitrate = fcp->isp_gbspeed * 1000;
4903                     } else {
4904                               sdparam *sdp = SDPARAM(isp, bus);
4905                               cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
4906                               cpi->hba_misc = 0;
4907                               cpi->initiator_id = sdp->isp_initiator_id;
4908                               cpi->base_transfer_speed = 3300;
4909                               cpi->transport = XPORT_SPI;
4910                               cpi->transport_version = 2;
4911                     }
4912                     cpi->protocol = PROTO_SCSI;
4913                     cpi->protocol_version = SCSI_REV_2;
4914                     strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
4915                     strncpy(cpi->hba_vid, "Qlogic", HBA_IDLEN);
4916                     strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
4917                     cpi->unit_number = cam_sim_unit(sim);
4918                     cpi->ccb_h.status = CAM_REQ_CMP;
4919                     xpt_done(ccb);
4920                     break;
4921           }
4922           default:
4923                     ccb->ccb_h.status = CAM_REQ_INVALID;
4924                     xpt_done(ccb);
4925                     break;
4926           }
4927 }
4928 
4929 #define   ISPDDB    (CAM_DEBUG_INFO|CAM_DEBUG_TRACE|CAM_DEBUG_CDB)
4930 
4931 void
isp_done(XS_T * sccb)4932 isp_done(XS_T *sccb)
4933 {
4934           ispsoftc_t *isp = XS_ISP(sccb);
4935           uint32_t status;
4936 
4937           if (XS_NOERR(sccb))
4938                     XS_SETERR(sccb, CAM_REQ_CMP);
4939 
4940           if ((sccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP && (sccb->scsi_status != SCSI_STATUS_OK)) {
4941                     sccb->ccb_h.status &= ~CAM_STATUS_MASK;
4942                     if ((sccb->scsi_status == SCSI_STATUS_CHECK_COND) && (sccb->ccb_h.status & CAM_AUTOSNS_VALID) == 0) {
4943                               sccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
4944                     } else {
4945                               sccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
4946                     }
4947           }
4948 
4949           sccb->ccb_h.status &= ~CAM_SIM_QUEUED;
4950           status = sccb->ccb_h.status & CAM_STATUS_MASK;
4951           if (status != CAM_REQ_CMP) {
4952                     if (status != CAM_SEL_TIMEOUT)
4953                               isp_prt(isp, ISP_LOGDEBUG0, "target %d lun %d CAM status 0x%x SCSI status 0x%x", XS_TGT(sccb), XS_LUN(sccb), sccb->ccb_h.status, sccb->scsi_status);
4954                     if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
4955                               sccb->ccb_h.status |= CAM_DEV_QFRZN;
4956                               xpt_freeze_devq(sccb->ccb_h.path, 1);
4957                     }
4958           }
4959 
4960           if ((CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB)) && (sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4961                     xpt_print(sccb->ccb_h.path, "cam completion status 0x%x\n", sccb->ccb_h.status);
4962           }
4963 
4964           XS_CMD_S_DONE(sccb);
4965           if (XS_TACTIVE_P(sccb))
4966                     callout_stop(&PISP_PCMD(sccb)->wdog);
4967           XS_CMD_S_CLEAR(sccb);
4968           isp_free_pcmd(isp, (union ccb *) sccb);
4969           xpt_done((union ccb *) sccb);
4970 }
4971 
4972 void
isp_async(ispsoftc_t * isp,ispasync_t cmd,...)4973 isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
4974 {
4975           int bus;
4976           static const char prom[] = "Chan %d PortID 0x%06x handle 0x%x role %s %s WWPN 0x%08x%08x";
4977           static const char prom2[] = "Chan %d PortID 0x%06x handle 0x%x role %s %s tgt %u WWPN 0x%08x%08x";
4978           char *msg = NULL;
4979           target_id_t tgt;
4980           fcportdb_t *lp;
4981           struct isp_fc *fc;
4982           struct cam_path *tmppath;
4983           __va_list ap;
4984 
4985           switch (cmd) {
4986           case ISPASYNC_NEW_TGT_PARAMS:
4987           {
4988                     struct ccb_trans_settings_scsi *scsi;
4989                     struct ccb_trans_settings_spi *spi;
4990                     int flags, tgt;
4991                     sdparam *sdp;
4992                     struct ccb_trans_settings cts;
4993 
4994                     memset(&cts, 0, sizeof (struct ccb_trans_settings));
4995 
4996                     __va_start(ap, cmd);
4997                     bus = __va_arg(ap, int);
4998                     tgt = __va_arg(ap, int);
4999                     __va_end(ap);
5000                     sdp = SDPARAM(isp, bus);
5001 
5002                     if (xpt_create_path(&tmppath, NULL, cam_sim_path(ISP_SPI_PC(isp, bus)->sim), tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
5003                               isp_prt(isp, ISP_LOGWARN, "isp_async cannot make temp path for %d.%d", tgt, bus);
5004                               break;
5005                     }
5006                     flags = sdp->isp_devparam[tgt].actv_flags;
5007                     cts.type = CTS_TYPE_CURRENT_SETTINGS;
5008                     cts.protocol = PROTO_SCSI;
5009                     cts.transport = XPORT_SPI;
5010 
5011                     scsi = &cts.proto_specific.scsi;
5012                     spi = &cts.xport_specific.spi;
5013 
5014                     if (flags & DPARM_TQING) {
5015                               scsi->valid |= CTS_SCSI_VALID_TQ;
5016                               scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
5017                     }
5018 
5019                     if (flags & DPARM_DISC) {
5020                               spi->valid |= CTS_SPI_VALID_DISC;
5021                               spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
5022                     }
5023                     spi->flags |= CTS_SPI_VALID_BUS_WIDTH;
5024                     if (flags & DPARM_WIDE) {
5025                               spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
5026                     } else {
5027                               spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
5028                     }
5029                     if (flags & DPARM_SYNC) {
5030                               spi->valid |= CTS_SPI_VALID_SYNC_RATE;
5031                               spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
5032                               spi->sync_period = sdp->isp_devparam[tgt].actv_period;
5033                               spi->sync_offset = sdp->isp_devparam[tgt].actv_offset;
5034                     }
5035                     isp_prt(isp, ISP_LOGDEBUG2, "NEW_TGT_PARAMS bus %d tgt %d period %x offset %x flags %x", bus, tgt, sdp->isp_devparam[tgt].actv_period, sdp->isp_devparam[tgt].actv_offset, flags);
5036                     xpt_setup_ccb(&cts.ccb_h, tmppath, 1);
5037                     xpt_async(AC_TRANSFER_NEG, tmppath, &cts);
5038                     xpt_free_path(tmppath);
5039                     break;
5040           }
5041           case ISPASYNC_BUS_RESET:
5042           {
5043                     __va_start(ap, cmd);
5044                     bus = __va_arg(ap, int);
5045                     __va_end(ap);
5046                     isp_prt(isp, ISP_LOGINFO, "SCSI bus reset on bus %d detected", bus);
5047                     if (IS_FC(isp)) {
5048                               xpt_async(AC_BUS_RESET, ISP_FC_PC(isp, bus)->path, NULL);
5049                     } else {
5050                               xpt_async(AC_BUS_RESET, ISP_SPI_PC(isp, bus)->path, NULL);
5051                     }
5052                     break;
5053           }
5054           case ISPASYNC_LIP:
5055                     if (msg == NULL) {
5056                               msg = "LIP Received";
5057                     }
5058                     /* FALLTHROUGH */
5059           case ISPASYNC_LOOP_RESET:
5060                     if (msg == NULL) {
5061                               msg = "LOOP Reset";
5062                     }
5063                     /* FALLTHROUGH */
5064           case ISPASYNC_LOOP_DOWN:
5065           {
5066                     if (msg == NULL) {
5067                               msg = "LOOP Down";
5068                     }
5069                     __va_start(ap, cmd);
5070                     bus = __va_arg(ap, int);
5071                     __va_end(ap);
5072 
5073                     FCPARAM(isp, bus)->link_active = 0;
5074 
5075                     fc = ISP_FC_PC(isp, bus);
5076                     if (cmd == ISPASYNC_LOOP_DOWN && fc->ready) {
5077                               /*
5078                                * We don't do any simq freezing if we are only in target mode
5079                                */
5080                               if (FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) {
5081                                         if (fc->path) {
5082                                                   isp_freeze_loopdown(isp, bus, msg);
5083                                         }
5084                                         if (!callout_active(&fc->ldt)) {
5085                                                   callout_reset(&fc->ldt, fc->loop_down_limit * hz, isp_ldt, fc);
5086                                                   isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Starting Loop Down Timer @ %lu", (unsigned long) time_second);
5087                                         }
5088                               }
5089                     }
5090                     isp_prt(isp, ISP_LOGINFO, "Chan %d: %s", bus, msg);
5091                     break;
5092           }
5093           case ISPASYNC_LOOP_UP:
5094                     __va_start(ap, cmd);
5095                     bus = __va_arg(ap, int);
5096                     __va_end(ap);
5097                     fc = ISP_FC_PC(isp, bus);
5098                     /*
5099                      * Now we just note that Loop has come up. We don't
5100                      * actually do anything because we're waiting for a
5101                      * Change Notify before activating the FC cleanup
5102                      * thread to look at the state of the loop again.
5103                      */
5104                     FCPARAM(isp, bus)->link_active = 1;
5105                     fc->loop_dead = 0;
5106                     fc->loop_down_time = 0;
5107                     isp_prt(isp, ISP_LOGINFO, "Chan %d Loop UP", bus);
5108                     break;
5109           case ISPASYNC_DEV_ARRIVED:
5110                     __va_start(ap, cmd);
5111                     bus = __va_arg(ap, int);
5112                     lp = __va_arg(ap, fcportdb_t *);
5113                     __va_end(ap);
5114                     fc = ISP_FC_PC(isp, bus);
5115                     lp->reserved = 0;
5116                     lp->gone_timer = 0;
5117                     if ((FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) && (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) {
5118                               int dbidx = lp - FCPARAM(isp, bus)->portdb;
5119                               int i;
5120 
5121                               for (i = 0; i < MAX_FC_TARG; i++) {
5122                                         if (i >= FL_ID && i <= SNS_ID) {
5123                                                   continue;
5124                                         }
5125                                         if (FCPARAM(isp, bus)->isp_dev_map[i] == 0) {
5126                                                   break;
5127                                         }
5128                               }
5129                               if (i < MAX_FC_TARG) {
5130                                         FCPARAM(isp, bus)->isp_dev_map[i] = dbidx + 1;
5131                                         lp->dev_map_idx = i + 1;
5132                               } else {
5133                                         isp_prt(isp, ISP_LOGWARN, "out of target ids");
5134                                         isp_dump_portdb(isp, bus);
5135                               }
5136                     }
5137                     if (lp->dev_map_idx) {
5138                               tgt = lp->dev_map_idx - 1;
5139                               isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, roles[lp->roles], "arrived at", tgt, (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
5140                               isp_make_here(isp, bus, tgt);
5141                     } else {
5142                               isp_prt(isp, ISP_LOGCONFIG, prom, bus, lp->portid, lp->handle, roles[lp->roles], "arrived", (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
5143                     }
5144                     break;
5145           case ISPASYNC_DEV_CHANGED:
5146                     __va_start(ap, cmd);
5147                     bus = __va_arg(ap, int);
5148                     lp = __va_arg(ap, fcportdb_t *);
5149                     __va_end(ap);
5150                     fc = ISP_FC_PC(isp, bus);
5151                     lp->reserved = 0;
5152                     lp->gone_timer = 0;
5153                     if (isp_change_is_bad) {
5154                               lp->state = FC_PORTDB_STATE_NIL;
5155                               if (lp->dev_map_idx) {
5156                                         tgt = lp->dev_map_idx - 1;
5157                                         FCPARAM(isp, bus)->isp_dev_map[tgt] = 0;
5158                                         lp->dev_map_idx = 0;
5159                                         isp_prt(isp, ISP_LOGCONFIG, prom3, bus, lp->portid, tgt, "change is bad");
5160                                         isp_make_gone(isp, bus, tgt);
5161                               } else {
5162                                         isp_prt(isp, ISP_LOGCONFIG, prom, bus, lp->portid, lp->handle, roles[lp->roles], "changed and departed",
5163                                             (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
5164                               }
5165                     } else {
5166                               lp->portid = lp->new_portid;
5167                               lp->roles = lp->new_roles;
5168                               if (lp->dev_map_idx) {
5169                                         int t = lp->dev_map_idx - 1;
5170                                         FCPARAM(isp, bus)->isp_dev_map[t] = (lp - FCPARAM(isp, bus)->portdb) + 1;
5171                                         tgt = lp->dev_map_idx - 1;
5172                                         isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, roles[lp->roles], "changed at", tgt,
5173                                             (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
5174                               } else {
5175                                         isp_prt(isp, ISP_LOGCONFIG, prom, bus, lp->portid, lp->handle, roles[lp->roles], "changed", (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
5176                               }
5177                     }
5178                     break;
5179           case ISPASYNC_DEV_STAYED:
5180                     __va_start(ap, cmd);
5181                     bus = __va_arg(ap, int);
5182                     lp = __va_arg(ap, fcportdb_t *);
5183                     __va_end(ap);
5184                     if (lp->dev_map_idx) {
5185                               tgt = lp->dev_map_idx - 1;
5186                               isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, roles[lp->roles], "stayed at", tgt,
5187                                   (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
5188                     } else {
5189                               isp_prt(isp, ISP_LOGCONFIG, prom, bus, lp->portid, lp->handle, roles[lp->roles], "stayed",
5190                                   (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
5191                     }
5192                     break;
5193           case ISPASYNC_DEV_GONE:
5194                     __va_start(ap, cmd);
5195                     bus = __va_arg(ap, int);
5196                     lp = __va_arg(ap, fcportdb_t *);
5197                     __va_end(ap);
5198                     fc = ISP_FC_PC(isp, bus);
5199                     /*
5200                      * If this has a virtual target and we haven't marked it
5201                      * that we're going to have isp_gdt tell the OS it's gone,
5202                      * set the isp_gdt timer running on it.
5203                      *
5204                      * If it isn't marked that isp_gdt is going to get rid of it,
5205                      * announce that it's gone.
5206                      *
5207                      */
5208                     if (lp->dev_map_idx && lp->reserved == 0) {
5209                               lp->reserved = 1;
5210                               lp->state = FC_PORTDB_STATE_ZOMBIE;
5211                               lp->gone_timer = ISP_FC_PC(isp, bus)->gone_device_time;
5212                               if (fc->ready && !callout_active(&fc->gdt)) {
5213                                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d Starting Gone Device Timer with %u seconds time now %lu", bus, lp->gone_timer, (unsigned long)time_second);
5214                                         callout_reset(&fc->gdt, hz, isp_gdt, fc);
5215                               }
5216                               tgt = lp->dev_map_idx - 1;
5217                               isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, roles[lp->roles], "gone zombie at", tgt, (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
5218                     } else if (lp->reserved == 0) {
5219                               isp_prt(isp, ISP_LOGCONFIG, prom, bus, lp->portid, lp->handle, roles[lp->roles], "departed", (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
5220                     }
5221                     break;
5222           case ISPASYNC_CHANGE_NOTIFY:
5223           {
5224                     char *msg;
5225                     int evt, nphdl, nlstate, reason;
5226 
5227                     __va_start(ap, cmd);
5228                     bus = __va_arg(ap, int);
5229                     evt = __va_arg(ap, int);
5230                     if (IS_24XX(isp) && evt == ISPASYNC_CHANGE_PDB) {
5231                               nphdl = __va_arg(ap, int);
5232                               nlstate = __va_arg(ap, int);
5233                               reason = __va_arg(ap, int);
5234                     } else {
5235                               nphdl = NIL_HANDLE;
5236                               nlstate = reason = 0;
5237                     }
5238                     __va_end(ap);
5239                     fc = ISP_FC_PC(isp, bus);
5240 
5241                     if (evt == ISPASYNC_CHANGE_PDB) {
5242                               msg = "Chan %d Port Database Changed";
5243                     } else if (evt == ISPASYNC_CHANGE_SNS) {
5244                               msg = "Chan %d Name Server Database Changed";
5245                     } else {
5246                               msg = "Chan %d Other Change Notify";
5247                     }
5248 
5249                     /*
5250                      * If the loop down timer is running, cancel it.
5251                      */
5252                     if (fc->ready && callout_active(&fc->ldt)) {
5253                               isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Stopping Loop Down Timer @ %lu", (unsigned long) time_second);
5254                               callout_stop(&fc->ldt);
5255                     }
5256                     isp_prt(isp, ISP_LOGINFO, msg, bus);
5257                     if (FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) {
5258                               isp_freeze_loopdown(isp, bus, msg);
5259                     }
5260                     wakeup(fc);
5261                     break;
5262           }
5263 #ifdef    ISP_TARGET_MODE
5264           case ISPASYNC_TARGET_NOTIFY:
5265           {
5266                     isp_notify_t *notify;
5267                     __va_start(ap, cmd);
5268                     notify = __va_arg(ap, isp_notify_t *);
5269                     __va_end(ap);
5270                     switch (notify->nt_ncode) {
5271                     case NT_ABORT_TASK:
5272                     case NT_ABORT_TASK_SET:
5273                     case NT_CLEAR_ACA:
5274                     case NT_CLEAR_TASK_SET:
5275                     case NT_LUN_RESET:
5276                     case NT_TARGET_RESET:
5277                               /*
5278                                * These are task management functions.
5279                                */
5280                               isp_handle_platform_target_tmf(isp, notify);
5281                               break;
5282                     case NT_BUS_RESET:
5283                     case NT_LIP_RESET:
5284                     case NT_LINK_UP:
5285                     case NT_LINK_DOWN:
5286                               /*
5287                                * No action need be taken here.
5288                                */
5289                               break;
5290                     case NT_HBA_RESET:
5291                               isp_del_all_wwn_entries(isp, ISP_NOCHAN);
5292                               break;
5293                     case NT_LOGOUT:
5294                               /*
5295                                * This is device arrival/departure notification
5296                                */
5297                               isp_handle_platform_target_notify_ack(isp, notify);
5298                               break;
5299                     case NT_ARRIVED:
5300                     {
5301                               struct ac_contract ac;
5302                               struct ac_device_changed *fc;
5303 
5304                               ac.contract_number = AC_CONTRACT_DEV_CHG;
5305                               fc = (struct ac_device_changed *) ac.contract_data;
5306                               fc->wwpn = notify->nt_wwn;
5307                               fc->port = notify->nt_sid;
5308                               fc->target = notify->nt_nphdl;
5309                               fc->arrived = 1;
5310                               xpt_async(AC_CONTRACT, ISP_FC_PC(isp, notify->nt_channel)->path, &ac);
5311                               break;
5312                     }
5313                     case NT_DEPARTED:
5314                     {
5315                               struct ac_contract ac;
5316                               struct ac_device_changed *fc;
5317 
5318                               ac.contract_number = AC_CONTRACT_DEV_CHG;
5319                               fc = (struct ac_device_changed *) ac.contract_data;
5320                               fc->wwpn = notify->nt_wwn;
5321                               fc->port = notify->nt_sid;
5322                               fc->target = notify->nt_nphdl;
5323                               fc->arrived = 0;
5324                               xpt_async(AC_CONTRACT, ISP_FC_PC(isp, notify->nt_channel)->path, &ac);
5325                               break;
5326                     }
5327                     default:
5328                               isp_prt(isp, ISP_LOGALL, "target notify code 0x%x", notify->nt_ncode);
5329                               isp_handle_platform_target_notify_ack(isp, notify);
5330                               break;
5331                     }
5332                     break;
5333           }
5334           case ISPASYNC_TARGET_ACTION:
5335           {
5336                     isphdr_t *hp;
5337 
5338                     __va_start(ap, cmd);
5339                     hp = __va_arg(ap, isphdr_t *);
5340                     __va_end(ap);
5341                     switch (hp->rqs_entry_type) {
5342                     default:
5343                               isp_prt(isp, ISP_LOGWARN, "%s: unhandled target action 0x%x", __func__, hp->rqs_entry_type);
5344                               break;
5345                     case RQSTYPE_NOTIFY:
5346                               if (IS_SCSI(isp)) {
5347                                         isp_handle_platform_notify_scsi(isp, (in_entry_t *) hp);
5348                               } else if (IS_24XX(isp)) {
5349                                         isp_handle_platform_notify_24xx(isp, (in_fcentry_24xx_t *) hp);
5350                               } else {
5351                                         isp_handle_platform_notify_fc(isp, (in_fcentry_t *) hp);
5352                               }
5353                               break;
5354                     case RQSTYPE_ATIO:
5355                               if (IS_24XX(isp)) {
5356                                         isp_handle_platform_atio7(isp, (at7_entry_t *) hp);
5357                               } else {
5358                                         isp_handle_platform_atio(isp, (at_entry_t *) hp);
5359                               }
5360                               break;
5361                     case RQSTYPE_ATIO2:
5362                               isp_handle_platform_atio2(isp, (at2_entry_t *) hp);
5363                               break;
5364                     case RQSTYPE_CTIO7:
5365                     case RQSTYPE_CTIO3:
5366                     case RQSTYPE_CTIO2:
5367                     case RQSTYPE_CTIO:
5368                               isp_handle_platform_ctio(isp, hp);
5369                               break;
5370                     case RQSTYPE_ABTS_RCVD:
5371                     {
5372                               abts_t *abts = (abts_t *)hp;
5373                               isp_notify_t notify, *nt = &notify;
5374                               tstate_t *tptr;
5375                               fcportdb_t *lp;
5376                               uint16_t chan;
5377                               uint32_t sid, did;
5378 
5379                               did = (abts->abts_did_hi << 16) | abts->abts_did_lo;
5380                               sid = (abts->abts_sid_hi << 16) | abts->abts_sid_lo;
5381                               ISP_MEMZERO(nt, sizeof (isp_notify_t));
5382 
5383                               nt->nt_hba = isp;
5384                               nt->nt_did = did;
5385                               nt->nt_nphdl = abts->abts_nphdl;
5386                               nt->nt_sid = sid;
5387                               isp_find_chan_by_did(isp, did, &chan);
5388                               if (chan == ISP_NOCHAN) {
5389                                         nt->nt_tgt = TGT_ANY;
5390                               } else {
5391                                         nt->nt_tgt = FCPARAM(isp, chan)->isp_wwpn;
5392                                         if (isp_find_pdb_by_loopid(isp, chan, abts->abts_nphdl, &lp)) {
5393                                                   nt->nt_wwn = lp->port_wwn;
5394                                         } else {
5395                                                   nt->nt_wwn = INI_ANY;
5396                                         }
5397                               }
5398                               /*
5399                                * Try hard to find the lun for this command.
5400                                */
5401                               tptr = get_lun_statep_from_tag(isp, chan, abts->abts_rxid_task);
5402                               if (tptr) {
5403                                         nt->nt_lun = xpt_path_lun_id(tptr->owner);
5404                                         rls_lun_statep(isp, tptr);
5405                               } else {
5406                                         nt->nt_lun = LUN_ANY;
5407                               }
5408                               nt->nt_need_ack = 1;
5409                               nt->nt_tagval = abts->abts_rxid_task;
5410                               nt->nt_tagval |= (((uint64_t) abts->abts_rxid_abts) << 32);
5411                               if (abts->abts_rxid_task == ISP24XX_NO_TASK) {
5412                                         isp_prt(isp, ISP_LOGTINFO, "[0x%x] ABTS from N-Port handle 0x%x Port 0x%06x has no task id (rx_id 0x%04x ox_id 0x%04x)",
5413                                             abts->abts_rxid_abts, abts->abts_nphdl, sid, abts->abts_rx_id, abts->abts_ox_id);
5414                               } else {
5415                                         isp_prt(isp, ISP_LOGTINFO, "[0x%x] ABTS from N-Port handle 0x%x Port 0x%06x for task 0x%x (rx_id 0x%04x ox_id 0x%04x)",
5416                                             abts->abts_rxid_abts, abts->abts_nphdl, sid, abts->abts_rxid_task, abts->abts_rx_id, abts->abts_ox_id);
5417                               }
5418                               nt->nt_channel = chan;
5419                               nt->nt_ncode = NT_ABORT_TASK;
5420                               nt->nt_lreserved = hp;
5421                               isp_handle_platform_target_tmf(isp, nt);
5422                               break;
5423                     }
5424                     case RQSTYPE_ENABLE_LUN:
5425                     case RQSTYPE_MODIFY_LUN:
5426                               isp_ledone(isp, (lun_entry_t *) hp);
5427                               break;
5428                     }
5429                     break;
5430           }
5431 #endif
5432           case ISPASYNC_FW_CRASH:
5433           {
5434                     uint16_t mbox1, mbox6;
5435                     mbox1 = ISP_READ(isp, OUTMAILBOX1);
5436                     if (IS_DUALBUS(isp)) {
5437                               mbox6 = ISP_READ(isp, OUTMAILBOX6);
5438                     } else {
5439                               mbox6 = 0;
5440                     }
5441                     isp_prt(isp, ISP_LOGERR, "Internal Firmware Error on bus %d @ RISC Address 0x%x", mbox6, mbox1);
5442                     mbox1 = isp->isp_osinfo.mbox_sleep_ok;
5443                     isp->isp_osinfo.mbox_sleep_ok = 0;
5444                     isp_reinit(isp, 1);
5445                     isp->isp_osinfo.mbox_sleep_ok = mbox1;
5446                     isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
5447                     break;
5448           }
5449           default:
5450                     isp_prt(isp, ISP_LOGERR, "unknown isp_async event %d", cmd);
5451                     break;
5452           }
5453 }
5454 
5455 
5456 /*
5457  * Locks are held before coming here.
5458  */
5459 void
isp_uninit(ispsoftc_t * isp)5460 isp_uninit(ispsoftc_t *isp)
5461 {
5462           if (IS_24XX(isp)) {
5463                     ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET);
5464           } else {
5465                     ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
5466           }
5467           ISP_DISABLE_INTS(isp);
5468 }
5469 
5470 /*
5471  * When we want to get the 'default' WWNs (when lacking NVRAM), we pick them
5472  * up from our platform default (defww{p|n}n) and morph them based upon
5473  * channel.
5474  *
5475  * When we want to get the 'active' WWNs, we get NVRAM WWNs and then morph them
5476  * based upon channel.
5477  */
5478 
5479 uint64_t
isp_default_wwn(ispsoftc_t * isp,int chan,int isactive,int iswwnn)5480 isp_default_wwn(ispsoftc_t * isp, int chan, int isactive, int iswwnn)
5481 {
5482           uint64_t seed;
5483           struct isp_fc *fc = ISP_FC_PC(isp, chan);
5484 
5485           /*
5486            * If we're asking for a active WWN, the default overrides get
5487            * returned, otherwise the NVRAM value is picked.
5488            *
5489            * If we're asking for a default WWN, we just pick the default override.
5490            */
5491           if (isactive) {
5492                     seed = iswwnn ? fc->def_wwnn : fc->def_wwpn;
5493                     if (seed) {
5494                               return (seed);
5495                     }
5496                     seed = iswwnn ? FCPARAM(isp, chan)->isp_wwnn_nvram : FCPARAM(isp, chan)->isp_wwpn_nvram;
5497                     if (seed) {
5498                               return (seed);
5499                     }
5500                     return (0x400000007F000009ull);
5501           } else {
5502                     seed = iswwnn ? fc->def_wwnn : fc->def_wwpn;
5503           }
5504 
5505 
5506           /*
5507            * For channel zero just return what we have. For either ACTIVE or
5508            * DEFAULT cases, we depend on default override of NVRAM values for
5509            * channel zero.
5510            */
5511           if (chan == 0) {
5512                     return (seed);
5513           }
5514 
5515           /*
5516            * For other channels, we are doing one of three things:
5517            *
5518            * 1. If what we have now is non-zero, return it. Otherwise we morph
5519            * values from channel 0. 2. If we're here for a WWPN we synthesize
5520            * it if Channel 0's wwpn has a type 2 NAA. 3. If we're here for a
5521            * WWNN we synthesize it if Channel 0's wwnn has a type 2 NAA.
5522            */
5523 
5524           if (seed) {
5525                     return (seed);
5526           }
5527           if (isactive) {
5528                     seed = iswwnn ? FCPARAM(isp, 0)->isp_wwnn_nvram : FCPARAM(isp, 0)->isp_wwpn_nvram;
5529           } else {
5530                     seed = iswwnn ? ISP_FC_PC(isp, 0)->def_wwnn : ISP_FC_PC(isp, 0)->def_wwpn;
5531           }
5532 
5533           if (((seed >> 60) & 0xf) == 2) {
5534                     /*
5535                      * The type 2 NAA fields for QLogic cards appear be laid out
5536                      * thusly:
5537                      *
5538                      * bits 63..60 NAA == 2 bits 59..57 unused/zero bit 56
5539                      * port (1) or node (0) WWN distinguishor bit 48
5540                      * physical port on dual-port chips (23XX/24XX)
5541                      *
5542                      * This is somewhat nutty, particularly since bit 48 is
5543                      * irrelevant as they assign separate serial numbers to
5544                      * different physical ports anyway.
5545                      *
5546                      * We'll stick our channel number plus one first into bits
5547                      * 57..59 and thence into bits 52..55 which allows for 8 bits
5548                      * of channel which is comfortably more than our maximum
5549                      * (126) now.
5550                      */
5551                     seed &= ~0x0FF0000000000000ULL;
5552                     if (iswwnn == 0) {
5553                               seed |= ((uint64_t) (chan + 1) & 0xf) << 56;
5554                               seed |= ((uint64_t) ((chan + 1) >> 4) & 0xf) << 52;
5555                     }
5556           } else {
5557                     seed = 0;
5558           }
5559           return (seed);
5560 }
5561 
5562 void
isp_prt(ispsoftc_t * isp,int level,const char * fmt,...)5563 isp_prt(ispsoftc_t *isp, int level, const char *fmt, ...)
5564 {
5565           int loc;
5566           char lbuf[128];
5567           __va_list ap;
5568 
5569           if (level != ISP_LOGALL && (level & isp->isp_dblev) == 0) {
5570                     return;
5571           }
5572           ksprintf(lbuf, "%s: ", device_get_nameunit(isp->isp_dev));
5573           loc = strlen(lbuf);
5574           __va_start(ap, fmt);
5575           kvsnprintf(&lbuf[loc], sizeof (lbuf) - loc - 1, fmt, ap);
5576           __va_end(ap);
5577           kprintf("%s\n", lbuf);
5578 }
5579 
5580 void
isp_xs_prt(ispsoftc_t * isp,XS_T * xs,int level,const char * fmt,...)5581 isp_xs_prt(ispsoftc_t *isp, XS_T *xs, int level, const char *fmt, ...)
5582 {
5583           __va_list ap;
5584           if (level != ISP_LOGALL && (level & isp->isp_dblev) == 0) {
5585                     return;
5586           }
5587           xpt_print_path(xs->ccb_h.path);
5588           __va_start(ap, fmt);
5589           kvprintf(fmt, ap);
5590           __va_end(ap);
5591           kprintf("\n");
5592 }
5593 
5594 uint64_t
isp_nanotime_sub(struct timespec * b,struct timespec * a)5595 isp_nanotime_sub(struct timespec *b, struct timespec *a)
5596 {
5597           uint64_t elapsed;
5598           struct timespec x;
5599 
5600           timespecsub(b, a, &x);
5601           elapsed = GET_NANOSEC(&x);
5602           if (elapsed == 0)
5603                     elapsed++;
5604           return (elapsed);
5605 }
5606 
5607 int
isp_mbox_acquire(ispsoftc_t * isp)5608 isp_mbox_acquire(ispsoftc_t *isp)
5609 {
5610           if (isp->isp_osinfo.mboxbsy) {
5611                     return (1);
5612           } else {
5613                     isp->isp_osinfo.mboxcmd_done = 0;
5614                     isp->isp_osinfo.mboxbsy = 1;
5615                     return (0);
5616           }
5617 }
5618 
5619 void
isp_mbox_wait_complete(ispsoftc_t * isp,mbreg_t * mbp)5620 isp_mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
5621 {
5622           unsigned int usecs = mbp->timeout;
5623           unsigned int max, olim, ilim;
5624 
5625           if (usecs == 0) {
5626                     usecs = MBCMD_DEFAULT_TIMEOUT;
5627           }
5628           max = isp->isp_mbxwrk0 + 1;
5629 
5630           if (isp->isp_osinfo.mbox_sleep_ok) {
5631                     unsigned int ms = (usecs + 999) / 1000;
5632 
5633                     isp->isp_osinfo.mbox_sleep_ok = 0;
5634                     isp->isp_osinfo.mbox_sleeping = 1;
5635                     for (olim = 0; olim < max; olim++) {
5636                               lksleep(&isp->isp_mbxworkp, &isp->isp_osinfo.lock, 0, "ispmbx_sleep", isp_mstohz(ms));
5637                               if (isp->isp_osinfo.mboxcmd_done) {
5638                                         break;
5639                               }
5640                     }
5641                     isp->isp_osinfo.mbox_sleep_ok = 1;
5642                     isp->isp_osinfo.mbox_sleeping = 0;
5643           } else {
5644                     for (olim = 0; olim < max; olim++) {
5645                               for (ilim = 0; ilim < usecs; ilim += 100) {
5646                                         uint32_t isr;
5647                                         uint16_t sema, mbox;
5648                                         if (isp->isp_osinfo.mboxcmd_done) {
5649                                                   break;
5650                                         }
5651                                         if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
5652                                                   isp_intr(isp, isr, sema, mbox);
5653                                                   if (isp->isp_osinfo.mboxcmd_done) {
5654                                                             break;
5655                                                   }
5656                                         }
5657                                         ISP_DELAY(100);
5658                               }
5659                               if (isp->isp_osinfo.mboxcmd_done) {
5660                                         break;
5661                               }
5662                     }
5663           }
5664           if (isp->isp_osinfo.mboxcmd_done == 0) {
5665                     isp_prt(isp, ISP_LOGWARN, "%s Mailbox Command (0x%x) Timeout (%uus) (started @ %s:%d)",
5666                         isp->isp_osinfo.mbox_sleep_ok? "Interrupting" : "Polled", isp->isp_lastmbxcmd, usecs, mbp->func, mbp->lineno);
5667                     mbp->param[0] = MBOX_TIMEOUT;
5668                     isp->isp_osinfo.mboxcmd_done = 1;
5669           }
5670 }
5671 
5672 void
isp_mbox_notify_done(ispsoftc_t * isp)5673 isp_mbox_notify_done(ispsoftc_t *isp)
5674 {
5675           if (isp->isp_osinfo.mbox_sleeping) {
5676                     wakeup(&isp->isp_mbxworkp);
5677           }
5678           isp->isp_osinfo.mboxcmd_done = 1;
5679 }
5680 
5681 void
isp_mbox_release(ispsoftc_t * isp)5682 isp_mbox_release(ispsoftc_t *isp)
5683 {
5684           isp->isp_osinfo.mboxbsy = 0;
5685 }
5686 
5687 int
isp_fc_scratch_acquire(ispsoftc_t * isp,int chan)5688 isp_fc_scratch_acquire(ispsoftc_t *isp, int chan)
5689 {
5690           int ret = 0;
5691           if (isp->isp_osinfo.pc.fc[chan].fcbsy) {
5692                     ret = -1;
5693           } else {
5694                     isp->isp_osinfo.pc.fc[chan].fcbsy = 1;
5695           }
5696           return (ret);
5697 }
5698 
5699 int
isp_mstohz(int ms)5700 isp_mstohz(int ms)
5701 {
5702           int hz;
5703           struct timeval t;
5704           t.tv_sec = ms / 1000;
5705           t.tv_usec = (ms % 1000) * 1000;
5706           hz = tvtohz_high(&t);
5707           if (hz < 0) {
5708                     hz = 0x7fffffff;
5709           }
5710           if (hz == 0) {
5711                     hz = 1;
5712           }
5713           return (hz);
5714 }
5715 
5716 void
isp_platform_intr(void * arg)5717 isp_platform_intr(void *arg)
5718 {
5719           ispsoftc_t *isp = arg;
5720           uint32_t isr;
5721           uint16_t sema, mbox;
5722 
5723           ISP_LOCK(isp);
5724           isp->isp_intcnt++;
5725           if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
5726                     isp->isp_intbogus++;
5727           } else {
5728                     isp_intr(isp, isr, sema, mbox);
5729           }
5730           ISP_UNLOCK(isp);
5731 }
5732 
5733 void
isp_common_dmateardown(ispsoftc_t * isp,struct ccb_scsiio * csio,uint32_t hdl)5734 isp_common_dmateardown(ispsoftc_t *isp, struct ccb_scsiio *csio, uint32_t hdl)
5735 {
5736           if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
5737                     bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_POSTREAD);
5738           } else {
5739                     bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_POSTWRITE);
5740           }
5741           bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap);
5742 }
5743 
5744 static void
isp_timer(void * arg)5745 isp_timer(void *arg)
5746 {
5747           ispsoftc_t *isp = arg;
5748 
5749           ISP_LOCK(isp);
5750 #ifdef    ISP_TARGET_MODE
5751           isp_tmcmd_restart(isp);
5752 #endif
5753           ISP_UNLOCK(isp);
5754           callout_reset(&isp->isp_osinfo.tmo, hz, isp_timer, isp);
5755 }
5756