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