]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/isp/isp_freebsd.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / dev / isp / isp_freebsd.c
1 /*-
2  * Copyright (c) 1997-2006 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 <machine/stdarg.h>     /* for use by isp_prt below */
36 #include <sys/conf.h>
37 #include <sys/module.h>
38 #include <sys/ioccom.h>
39 #include <dev/isp/isp_ioctl.h>
40 #if     __FreeBSD_version >= 500000
41 #include <sys/sysctl.h>
42 #else
43 #include <sys/devicestat.h>
44 #endif
45 #include <cam/cam_periph.h>
46 #include <cam/cam_xpt_periph.h>
47
48 #if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025
49 #define CAM_NEW_TRAN_CODE       1
50 #endif
51
52
53 MODULE_VERSION(isp, 1);
54 MODULE_DEPEND(isp, cam, 1, 1, 1);
55 int isp_announced = 0;
56 int isp_fabric_hysteresis = 5;
57 int isp_loop_down_limit = 300;  /* default loop down limit */
58 int isp_change_is_bad = 0;      /* "changed" devices are bad */
59 int isp_quickboot_time = 15;    /* don't wait more than N secs for loop up */
60 int isp_gone_device_time = 30;  /* grace time before reporting device lost */
61 static const char *roles[4] = {
62     "(none)", "Target", "Initiator", "Target/Initiator"
63 };
64 static const char prom3[] =
65     "PortID 0x%06x Departed from Target %u because of %s";
66
67 static void isp_freeze_loopdown(ispsoftc_t *, char *);
68 static d_ioctl_t ispioctl;
69 static void isp_intr_enable(void *);
70 static void isp_cam_async(void *, uint32_t, struct cam_path *, void *);
71 static void isp_poll(struct cam_sim *);
72 static timeout_t isp_watchdog;
73 static timeout_t isp_ldt;
74 static void isp_kthread(void *);
75 static void isp_action(struct cam_sim *, union ccb *);
76
77 #if __FreeBSD_version < 700000
78 ispfwfunc *isp_get_firmware_p = NULL;
79 #endif
80
81 #if __FreeBSD_version < 500000  
82 #define ISP_CDEV_MAJOR  248
83 static struct cdevsw isp_cdevsw = {
84         /* open */      nullopen,
85         /* close */     nullclose,
86         /* read */      noread,
87         /* write */     nowrite,
88         /* ioctl */     ispioctl,
89         /* poll */      nopoll,
90         /* mmap */      nommap,
91         /* strategy */  nostrategy,
92         /* name */      "isp",
93         /* maj */       ISP_CDEV_MAJOR,
94         /* dump */      nodump,
95         /* psize */     nopsize,
96         /* flags */     D_TAPE,
97 };
98 #define isp_sysctl_update(x)    do { ; } while (0)
99 #else
100 static struct cdevsw isp_cdevsw = {
101         .d_version =    D_VERSION,
102 #if     __FreeBSD_version < 700037
103         .d_flags =      D_NEEDGIANT,
104 #endif
105         .d_ioctl =      ispioctl,
106         .d_name =       "isp",
107 };
108 static void isp_sysctl_update(ispsoftc_t *);
109 #endif
110
111 static ispsoftc_t *isplist = NULL;
112
113 void
114 isp_attach(ispsoftc_t *isp)
115 {
116         int primary, secondary;
117         struct ccb_setasync csa;
118         struct cam_devq *devq;
119         struct cam_sim *sim;
120         struct cam_path *path;
121
122         /*
123          * Establish (in case of 12X0) which bus is the primary.
124          */
125
126         primary = 0;
127         secondary = 1;
128
129         /*
130          * Create the device queue for our SIM(s).
131          */
132         devq = cam_simq_alloc(isp->isp_maxcmds);
133         if (devq == NULL) {
134                 return;
135         }
136
137         /*
138          * Construct our SIM entry.
139          */
140         sim = isp_sim_alloc(isp_action, isp_poll, "isp", isp,
141             device_get_unit(isp->isp_dev), 1, isp->isp_maxcmds, devq);
142         if (sim == NULL) {
143                 cam_simq_free(devq);
144                 return;
145         }
146
147         isp->isp_osinfo.ehook.ich_func = isp_intr_enable;
148         isp->isp_osinfo.ehook.ich_arg = isp;
149         ISP_UNLOCK(isp);
150         if (config_intrhook_establish(&isp->isp_osinfo.ehook) != 0) {
151                 ISP_LOCK(isp);
152                 cam_sim_free(sim, TRUE);
153                 isp_prt(isp, ISP_LOGERR,
154                     "could not establish interrupt enable hook");
155                 return;
156         }
157         ISP_LOCK(isp);
158
159         if (xpt_bus_register(sim, isp->isp_dev, primary) != CAM_SUCCESS) {
160                 cam_sim_free(sim, TRUE);
161                 return;
162         }
163
164         if (xpt_create_path(&path, NULL, cam_sim_path(sim),
165             CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
166                 xpt_bus_deregister(cam_sim_path(sim));
167                 cam_sim_free(sim, TRUE);
168                 config_intrhook_disestablish(&isp->isp_osinfo.ehook);
169                 return;
170         }
171
172         xpt_setup_ccb(&csa.ccb_h, path, 5);
173         csa.ccb_h.func_code = XPT_SASYNC_CB;
174         csa.event_enable = AC_LOST_DEVICE;
175         csa.callback = isp_cam_async;
176         csa.callback_arg = sim;
177         xpt_action((union ccb *)&csa);
178         isp->isp_sim = sim;
179         isp->isp_path = path;
180
181         /*
182          * If we have a second channel, construct SIM entry for that.
183          */
184         if (IS_DUALBUS(isp)) {
185                 sim = isp_sim_alloc(isp_action, isp_poll, "isp", isp,
186                     device_get_unit(isp->isp_dev), 1, isp->isp_maxcmds, devq);
187                 if (sim == NULL) {
188                         xpt_bus_deregister(cam_sim_path(isp->isp_sim));
189                         xpt_free_path(isp->isp_path);
190                         cam_simq_free(devq);
191                         config_intrhook_disestablish(&isp->isp_osinfo.ehook);
192                         return;
193                 }
194                 if (xpt_bus_register(sim, isp->isp_dev, secondary) !=
195                     CAM_SUCCESS) {
196                         xpt_bus_deregister(cam_sim_path(isp->isp_sim));
197                         xpt_free_path(isp->isp_path);
198                         cam_sim_free(sim, TRUE);
199                         config_intrhook_disestablish(&isp->isp_osinfo.ehook);
200                         return;
201                 }
202
203                 if (xpt_create_path(&path, NULL, cam_sim_path(sim),
204                     CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
205                         xpt_bus_deregister(cam_sim_path(isp->isp_sim));
206                         xpt_free_path(isp->isp_path);
207                         xpt_bus_deregister(cam_sim_path(sim));
208                         cam_sim_free(sim, TRUE);
209                         config_intrhook_disestablish(&isp->isp_osinfo.ehook);
210                         return;
211                 }
212
213                 xpt_setup_ccb(&csa.ccb_h, path, 5);
214                 csa.ccb_h.func_code = XPT_SASYNC_CB;
215                 csa.event_enable = AC_LOST_DEVICE;
216                 csa.callback = isp_cam_async;
217                 csa.callback_arg = sim;
218                 xpt_action((union ccb *)&csa);
219                 isp->isp_sim2 = sim;
220                 isp->isp_path2 = path;
221         }
222
223         /*
224          * Create device nodes
225          */
226         ISP_UNLOCK(isp);
227         (void) make_dev(&isp_cdevsw, device_get_unit(isp->isp_dev), UID_ROOT,
228             GID_OPERATOR, 0600, "%s", device_get_nameunit(isp->isp_dev));
229         isp_sysctl_update(isp);
230         ISP_LOCK(isp);
231
232         if (isp->isp_role != ISP_ROLE_NONE) {
233                 isp->isp_state = ISP_RUNSTATE;
234                 ISP_ENABLE_INTS(isp);
235         }
236         if (isplist == NULL) {
237                 isplist = isp;
238         } else {
239                 ispsoftc_t *tmp = isplist;
240                 while (tmp->isp_osinfo.next) {
241                         tmp = tmp->isp_osinfo.next;
242                 }
243                 tmp->isp_osinfo.next = isp;
244         }
245
246         /*
247          * Create a kernel thread for fibre channel instances.
248          */
249         if (IS_FC(isp)) {
250                 isp_callout_init(&isp->isp_osinfo.ldt);
251                 isp_callout_init(&isp->isp_osinfo.gdt);
252                 ISP_UNLOCK(isp);
253 #if __FreeBSD_version >= 500000  
254                 if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
255                     RFHIGHPID, 0, "%s: fc_thrd",
256                     device_get_nameunit(isp->isp_dev)))
257 #else
258                 if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
259                     "%s: fc_thrd", device_get_nameunit(isp->isp_dev)))
260 #endif
261                 {
262                         ISP_LOCK(isp);
263                         xpt_bus_deregister(cam_sim_path(sim));
264                         cam_sim_free(sim, TRUE);
265                         config_intrhook_disestablish(&isp->isp_osinfo.ehook);
266                         isp_prt(isp, ISP_LOGERR, "could not create kthread");
267                         return;
268                 }
269                 ISP_LOCK(isp);
270                 /*
271                  * We start by being "loop down" if we have an initiator role
272                  */
273                 if (isp->isp_role & ISP_ROLE_INITIATOR) {
274                         isp_freeze_loopdown(isp, "isp_attach");
275                         isp->isp_osinfo.ldt_running = 1;
276                         callout_reset(&isp->isp_osinfo.ldt,
277                             isp_quickboot_time * hz, isp_ldt, isp);
278                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
279                            "Starting Initial Loop Down Timer");
280                 }
281         }
282 }
283
284 static void
285 isp_freeze_loopdown(ispsoftc_t *isp, char *msg)
286 {
287         if (isp->isp_osinfo.simqfrozen == 0) {
288                 isp_prt(isp, ISP_LOGDEBUG0, "%s: freeze simq (loopdown)", msg);
289                 isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
290                 xpt_freeze_simq(isp->isp_sim, 1);
291         } else {
292                 isp_prt(isp, ISP_LOGDEBUG0, "%s: mark frozen (loopdown)", msg);
293                 isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
294         }
295 }
296
297
298 #if __FreeBSD_version < 500000  
299 #define _DEV    dev_t
300 #define _IOP    struct proc
301 #else
302 #define _IOP    struct thread
303 #define _DEV    struct cdev *
304 #endif
305
306 static int
307 ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
308 {
309         ispsoftc_t *isp;
310         int nr, retval = ENOTTY;
311
312         isp = isplist;
313         while (isp) {
314                 if (minor(dev) == device_get_unit(isp->isp_dev)) {
315                         break;
316                 }
317                 isp = isp->isp_osinfo.next;
318         }
319         if (isp == NULL) {
320                 return (ENXIO);
321         }
322         
323         switch (c) {
324 #ifdef  ISP_FW_CRASH_DUMP
325         case ISP_GET_FW_CRASH_DUMP:
326                 if (IS_FC(isp)) {
327                         uint16_t *ptr = FCPARAM(isp)->isp_dump_data;
328                         size_t sz;
329
330                         retval = 0;
331                         if (IS_2200(isp)) {
332                                 sz = QLA2200_RISC_IMAGE_DUMP_SIZE;
333                         } else {
334                                 sz = QLA2300_RISC_IMAGE_DUMP_SIZE;
335                         }
336                         if (ptr && *ptr) {
337                                 void *uaddr = *((void **) addr);
338                                 if (copyout(ptr, uaddr, sz)) {
339                                         retval = EFAULT;
340                                 } else {
341                                         *ptr = 0;
342                                 }
343                         } else {
344                                 retval = ENXIO;
345                         }
346                 }
347                 break;
348         case ISP_FORCE_CRASH_DUMP:
349                 if (IS_FC(isp)) {
350                         ISP_LOCK(isp);
351                         isp_freeze_loopdown(isp,
352                             "ispioctl(ISP_FORCE_CRASH_DUMP)");
353                         isp_fw_dump(isp);
354                         isp_reinit(isp);
355                         ISP_UNLOCK(isp);
356                         retval = 0;
357                 }
358                 break;
359 #endif
360         case ISP_SDBLEV:
361         {
362                 int olddblev = isp->isp_dblev;
363                 isp->isp_dblev = *(int *)addr;
364                 *(int *)addr = olddblev;
365                 retval = 0;
366                 break;
367         }
368         case ISP_GETROLE:
369                 *(int *)addr = isp->isp_role;
370                 retval = 0;
371                 break;
372         case ISP_SETROLE:
373                 nr = *(int *)addr;
374                 if (nr & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) {
375                         retval = EINVAL;
376                         break;
377                 }
378                 *(int *)addr = isp->isp_role;
379                 isp->isp_role = nr;
380                 /* FALLTHROUGH */
381         case ISP_RESETHBA:
382                 ISP_LOCK(isp);
383                 isp_reinit(isp);
384                 ISP_UNLOCK(isp);
385                 retval = 0;
386                 break;
387         case ISP_RESCAN:
388                 if (IS_FC(isp)) {
389                         ISP_LOCK(isp);
390                         if (isp_fc_runstate(isp, 5 * 1000000)) {
391                                 retval = EIO;
392                         } else {
393                                 retval = 0;
394                         }
395                         ISP_UNLOCK(isp);
396                 }
397                 break;
398         case ISP_FC_LIP:
399                 if (IS_FC(isp)) {
400                         ISP_LOCK(isp);
401                         if (isp_control(isp, ISPCTL_SEND_LIP, 0)) {
402                                 retval = EIO;
403                         } else {
404                                 retval = 0;
405                         }
406                         ISP_UNLOCK(isp);
407                 }
408                 break;
409         case ISP_FC_GETDINFO:
410         {
411                 struct isp_fc_device *ifc = (struct isp_fc_device *) addr;
412                 fcportdb_t *lp;
413
414                 if (IS_SCSI(isp)) {
415                         break;
416                 }
417                 if (ifc->loopid >= MAX_FC_TARG) {
418                         retval = EINVAL;
419                         break;
420                 }
421                 lp = &FCPARAM(isp)->portdb[ifc->loopid];
422                 if (lp->state == FC_PORTDB_STATE_VALID) {
423                         ifc->role = lp->roles;
424                         ifc->loopid = lp->handle;
425                         ifc->portid = lp->portid;
426                         ifc->node_wwn = lp->node_wwn;
427                         ifc->port_wwn = lp->port_wwn;
428                         retval = 0;
429                 } else {
430                         retval = ENODEV;
431                 }
432                 break;
433         }
434         case ISP_GET_STATS:
435         {
436                 isp_stats_t *sp = (isp_stats_t *) addr;
437
438                 MEMZERO(sp, sizeof (*sp));
439                 sp->isp_stat_version = ISP_STATS_VERSION;
440                 sp->isp_type = isp->isp_type;
441                 sp->isp_revision = isp->isp_revision;
442                 ISP_LOCK(isp);
443                 sp->isp_stats[ISP_INTCNT] = isp->isp_intcnt;
444                 sp->isp_stats[ISP_INTBOGUS] = isp->isp_intbogus;
445                 sp->isp_stats[ISP_INTMBOXC] = isp->isp_intmboxc;
446                 sp->isp_stats[ISP_INGOASYNC] = isp->isp_intoasync;
447                 sp->isp_stats[ISP_RSLTCCMPLT] = isp->isp_rsltccmplt;
448                 sp->isp_stats[ISP_FPHCCMCPLT] = isp->isp_fphccmplt;
449                 sp->isp_stats[ISP_RSCCHIWAT] = isp->isp_rscchiwater;
450                 sp->isp_stats[ISP_FPCCHIWAT] = isp->isp_fpcchiwater;
451                 ISP_UNLOCK(isp);
452                 retval = 0;
453                 break;
454         }
455         case ISP_CLR_STATS:
456                 ISP_LOCK(isp);
457                 isp->isp_intcnt = 0;
458                 isp->isp_intbogus = 0;
459                 isp->isp_intmboxc = 0;
460                 isp->isp_intoasync = 0;
461                 isp->isp_rsltccmplt = 0;
462                 isp->isp_fphccmplt = 0;
463                 isp->isp_rscchiwater = 0;
464                 isp->isp_fpcchiwater = 0;
465                 ISP_UNLOCK(isp);
466                 retval = 0;
467                 break;
468         case ISP_FC_GETHINFO:
469         {
470                 struct isp_hba_device *hba = (struct isp_hba_device *) addr;
471                 MEMZERO(hba, sizeof (*hba));
472
473                 hba->fc_fw_major = ISP_FW_MAJORX(isp->isp_fwrev);
474                 hba->fc_fw_minor = ISP_FW_MINORX(isp->isp_fwrev);
475                 hba->fc_fw_micro = ISP_FW_MICROX(isp->isp_fwrev);
476                 if (IS_FC(isp)) {
477                         hba->fc_speed = FCPARAM(isp)->isp_gbspeed;
478                         hba->fc_scsi_supported = 1;
479                         hba->fc_topology = FCPARAM(isp)->isp_topo + 1;
480                         hba->fc_loopid = FCPARAM(isp)->isp_loopid;
481                         hba->nvram_node_wwn = FCPARAM(isp)->isp_wwnn_nvram;
482                         hba->nvram_port_wwn = FCPARAM(isp)->isp_wwpn_nvram;
483                         hba->active_node_wwn = ISP_NODEWWN(isp);
484                         hba->active_port_wwn = ISP_PORTWWN(isp);
485                 }
486                 retval = 0;
487                 break;
488         }
489         case ISP_TSK_MGMT:
490         {
491                 int needmarker;
492                 struct isp_fc_tsk_mgmt *fct = (struct isp_fc_tsk_mgmt *) addr;
493                 uint16_t loopid;
494                 mbreg_t mbs;
495
496                 if (IS_SCSI(isp)) {
497                         break;
498                 }
499
500                 memset(&mbs, 0, sizeof (mbs));
501                 needmarker = retval = 0;
502                 loopid = fct->loopid;
503                 if (FCPARAM(isp)->isp_2klogin == 0) {
504                         loopid <<= 8;
505                 }
506                 switch (fct->action) {
507                 case IPT_CLEAR_ACA:
508                         mbs.param[0] = MBOX_CLEAR_ACA;
509                         mbs.param[1] = loopid;
510                         mbs.param[2] = fct->lun;
511                         break;
512                 case IPT_TARGET_RESET:
513                         mbs.param[0] = MBOX_TARGET_RESET;
514                         mbs.param[1] = loopid;
515                         needmarker = 1;
516                         break;
517                 case IPT_LUN_RESET:
518                         mbs.param[0] = MBOX_LUN_RESET;
519                         mbs.param[1] = loopid;
520                         mbs.param[2] = fct->lun;
521                         needmarker = 1;
522                         break;
523                 case IPT_CLEAR_TASK_SET:
524                         mbs.param[0] = MBOX_CLEAR_TASK_SET;
525                         mbs.param[1] = loopid;
526                         mbs.param[2] = fct->lun;
527                         needmarker = 1;
528                         break;
529                 case IPT_ABORT_TASK_SET:
530                         mbs.param[0] = MBOX_ABORT_TASK_SET;
531                         mbs.param[1] = loopid;
532                         mbs.param[2] = fct->lun;
533                         needmarker = 1;
534                         break;
535                 default:
536                         retval = EINVAL;
537                         break;
538                 }
539                 if (retval == 0) {
540                         if (needmarker) {
541                                 isp->isp_sendmarker |= 1;
542                         }
543                         ISP_LOCK(isp);
544                         retval = isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
545                         ISP_UNLOCK(isp);
546                         if (retval)
547                                 retval = EIO;
548                 }
549                 break;
550         }
551         default:
552                 break;
553         }
554         return (retval);
555 }
556
557 #if __FreeBSD_version >= 500000
558 static void
559 isp_sysctl_update(ispsoftc_t *isp)
560 {
561         struct sysctl_ctx_list *ctx =
562             device_get_sysctl_ctx(isp->isp_osinfo.dev);
563         struct sysctl_oid *tree = device_get_sysctl_tree(isp->isp_osinfo.dev);
564
565         if (IS_SCSI(isp)) {
566                 return;
567         }
568
569         snprintf(isp->isp_osinfo.sysctl_info.fc.wwnn,
570             sizeof (isp->isp_osinfo.sysctl_info.fc.wwnn), "0x%08x%08x",
571             (uint32_t) (ISP_NODEWWN(isp) >> 32), (uint32_t) ISP_NODEWWN(isp));
572
573         snprintf(isp->isp_osinfo.sysctl_info.fc.wwpn,
574             sizeof (isp->isp_osinfo.sysctl_info.fc.wwpn), "0x%08x%08x",
575             (uint32_t) (ISP_PORTWWN(isp) >> 32), (uint32_t) ISP_PORTWWN(isp));
576
577         SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
578                "wwnn", CTLFLAG_RD, isp->isp_osinfo.sysctl_info.fc.wwnn, 0,
579                "World Wide Node Name");
580
581         SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
582                "wwpn", CTLFLAG_RD, isp->isp_osinfo.sysctl_info.fc.wwpn, 0,
583                "World Wide Port Name");
584
585         SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
586             "loop_down_limit",
587             CTLFLAG_RW, &isp->isp_osinfo.loop_down_limit, 0,
588             "How long to wait for loop to come back up");
589
590         SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
591             "gone_device_time",
592             CTLFLAG_RW, &isp->isp_osinfo.gone_device_time, 0,
593             "How long to wait for a device to reappear");
594 }
595 #endif
596
597 static void
598 isp_intr_enable(void *arg)
599 {
600         ispsoftc_t *isp = arg;
601         ISP_LOCK(isp);
602         if (isp->isp_role != ISP_ROLE_NONE) {
603                 ISP_ENABLE_INTS(isp);
604         }
605         ISP_UNLOCK(isp);
606         /* Release our hook so that the boot can continue. */
607         config_intrhook_disestablish(&isp->isp_osinfo.ehook);
608 }
609
610 /*
611  * Put the target mode functions here, because some are inlines
612  */
613
614 #ifdef  ISP_TARGET_MODE
615
616 static __inline int is_lun_enabled(ispsoftc_t *, int, lun_id_t);
617 static __inline int are_any_luns_enabled(ispsoftc_t *, int);
618 static __inline tstate_t *get_lun_statep(ispsoftc_t *, int, lun_id_t);
619 static __inline void rls_lun_statep(ispsoftc_t *, tstate_t *);
620 static __inline atio_private_data_t *isp_get_atpd(ispsoftc_t *, int);
621 static cam_status
622 create_lun_state(ispsoftc_t *, int, struct cam_path *, tstate_t **);
623 static void destroy_lun_state(ispsoftc_t *, tstate_t *);
624 static int isp_en_lun(ispsoftc_t *, union ccb *);
625 static void isp_ledone(ispsoftc_t *, lun_entry_t *);
626 static cam_status isp_abort_tgt_ccb(ispsoftc_t *, union ccb *);
627 static timeout_t isp_refire_putback_atio;
628 static void isp_complete_ctio(union ccb *);
629 static void isp_target_putback_atio(union ccb *);
630 static void isp_target_start_ctio(ispsoftc_t *, union ccb *);
631 static int isp_handle_platform_atio(ispsoftc_t *, at_entry_t *);
632 static int isp_handle_platform_atio2(ispsoftc_t *, at2_entry_t *);
633 static int isp_handle_platform_ctio(ispsoftc_t *, void *);
634 static int isp_handle_platform_notify_scsi(ispsoftc_t *, in_entry_t *);
635 static int isp_handle_platform_notify_fc(ispsoftc_t *, in_fcentry_t *);
636
637 static __inline int
638 is_lun_enabled(ispsoftc_t *isp, int bus, lun_id_t lun)
639 {
640         tstate_t *tptr;
641         tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(isp, bus, lun)];
642         if (tptr == NULL) {
643                 return (0);
644         }
645         do {
646                 if (tptr->lun == (lun_id_t) lun && tptr->bus == bus) {
647                         return (1);
648                 }
649         } while ((tptr = tptr->next) != NULL);
650         return (0);
651 }
652
653 static __inline int
654 are_any_luns_enabled(ispsoftc_t *isp, int port)
655 {
656         int lo, hi;
657         if (IS_DUALBUS(isp)) {
658                 lo = (port * (LUN_HASH_SIZE >> 1));
659                 hi = lo + (LUN_HASH_SIZE >> 1);
660         } else {
661                 lo = 0;
662                 hi = LUN_HASH_SIZE;
663         }
664         for (lo = 0; lo < hi; lo++) {
665                 if (isp->isp_osinfo.lun_hash[lo]) {
666                         return (1);
667                 }
668         }
669         return (0);
670 }
671
672 static __inline tstate_t *
673 get_lun_statep(ispsoftc_t *isp, int bus, lun_id_t lun)
674 {
675         tstate_t *tptr = NULL;
676
677         if (lun == CAM_LUN_WILDCARD) {
678                 if (isp->isp_osinfo.tmflags[bus] & TM_WILDCARD_ENABLED) {
679                         tptr = &isp->isp_osinfo.tsdflt[bus];
680                         tptr->hold++;
681                         return (tptr);
682                 }
683                 return (NULL);
684         } else {
685                 tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(isp, bus, lun)];
686                 if (tptr == NULL) {
687                         return (NULL);
688                 }
689         }
690
691         do {
692                 if (tptr->lun == lun && tptr->bus == bus) {
693                         tptr->hold++;
694                         return (tptr);
695                 }
696         } while ((tptr = tptr->next) != NULL);
697         return (tptr);
698 }
699
700 static __inline void
701 rls_lun_statep(ispsoftc_t *isp, tstate_t *tptr)
702 {
703         if (tptr->hold)
704                 tptr->hold--;
705 }
706
707 static __inline atio_private_data_t *
708 isp_get_atpd(ispsoftc_t *isp, int tag)
709 {
710         atio_private_data_t *atp;
711         for (atp = isp->isp_osinfo.atpdp;
712             atp < &isp->isp_osinfo.atpdp[ATPDPSIZE]; atp++) {
713                 if (atp->tag == tag)
714                         return (atp);
715         }
716         return (NULL);
717 }
718
719 static cam_status
720 create_lun_state(ispsoftc_t *isp, int bus,
721     struct cam_path *path, tstate_t **rslt)
722 {
723         cam_status status;
724         lun_id_t lun;
725         int hfx;
726         tstate_t *tptr, *new;
727
728         lun = xpt_path_lun_id(path);
729         if (lun >= ISP_MAX_LUNS(isp)) {
730                 return (CAM_LUN_INVALID);
731         }
732         if (is_lun_enabled(isp, bus, lun)) {
733                 return (CAM_LUN_ALRDY_ENA);
734         }
735         new = (tstate_t *) malloc(sizeof (tstate_t), M_DEVBUF, M_NOWAIT|M_ZERO);
736         if (new == NULL) {
737                 return (CAM_RESRC_UNAVAIL);
738         }
739
740         status = xpt_create_path(&new->owner, NULL, xpt_path_path_id(path),
741             xpt_path_target_id(path), xpt_path_lun_id(path));
742         if (status != CAM_REQ_CMP) {
743                 free(new, M_DEVBUF);
744                 return (status);
745         }
746         new->bus = bus;
747         new->lun = lun;
748         SLIST_INIT(&new->atios);
749         SLIST_INIT(&new->inots);
750         new->hold = 1;
751
752         hfx = LUN_HASH_FUNC(isp, new->bus, new->lun);
753         tptr = isp->isp_osinfo.lun_hash[hfx];
754         if (tptr == NULL) {
755                 isp->isp_osinfo.lun_hash[hfx] = new;
756         } else {
757                 while (tptr->next)
758                         tptr = tptr->next;
759                 tptr->next = new;
760         }
761         *rslt = new;
762         return (CAM_REQ_CMP);
763 }
764
765 static __inline void
766 destroy_lun_state(ispsoftc_t *isp, tstate_t *tptr)
767 {
768         int hfx;
769         tstate_t *lw, *pw;
770
771         if (tptr->hold) {
772                 return;
773         }
774         hfx = LUN_HASH_FUNC(isp, tptr->bus, tptr->lun);
775         pw = isp->isp_osinfo.lun_hash[hfx];
776         if (pw == NULL) {
777                 return;
778         } else if (pw->lun == tptr->lun && pw->bus == tptr->bus) {
779                 isp->isp_osinfo.lun_hash[hfx] = pw->next;
780         } else {
781                 lw = pw;
782                 pw = lw->next;
783                 while (pw) {
784                         if (pw->lun == tptr->lun && pw->bus == tptr->bus) {
785                                 lw->next = pw->next;
786                                 break;
787                         }
788                         lw = pw;
789                         pw = pw->next;
790                 }
791                 if (pw == NULL) {
792                         return;
793                 }
794         }
795         free(tptr, M_DEVBUF);
796 }
797
798 /*
799  * Enable luns.
800  */
801 static int
802 isp_en_lun(ispsoftc_t *isp, union ccb *ccb)
803 {
804         struct ccb_en_lun *cel = &ccb->cel;
805         tstate_t *tptr = NULL;
806         uint32_t seq;
807         int bus, cmd, av, wildcard, tm_on;
808         lun_id_t lun;
809         target_id_t tgt;
810
811         bus = XS_CHANNEL(ccb);
812         if (bus > 1) {
813                 xpt_print(ccb->ccb_h.path, "illegal bus %d\n", bus);
814                 ccb->ccb_h.status = CAM_PATH_INVALID;
815                 return (-1);
816         }
817         tgt = ccb->ccb_h.target_id;
818         lun = ccb->ccb_h.target_lun;
819
820         if (isp->isp_dblev & ISP_LOGTDEBUG0) {
821                 xpt_print(ccb->ccb_h.path, "%sabling lun 0x%x on channel %d\n",
822                     cel->enable? "en" : "dis", lun, bus);
823         }
824
825         if ((lun != CAM_LUN_WILDCARD) &&
826             (lun >= (lun_id_t) isp->isp_maxluns)) {
827                 ccb->ccb_h.status = CAM_LUN_INVALID;
828                 return (-1);
829         }
830
831         if (IS_SCSI(isp)) {
832                 sdparam *sdp = isp->isp_param;
833                 sdp += bus;
834                 if (tgt != CAM_TARGET_WILDCARD &&
835                     tgt != sdp->isp_initiator_id) {
836                         ccb->ccb_h.status = CAM_TID_INVALID;
837                         return (-1);
838                 }
839         } else {
840                 /*
841                  * There's really no point in doing this yet w/o multi-tid
842                  * capability. Even then, it's problematic.
843                  */
844 #if     0
845                 if (tgt != CAM_TARGET_WILDCARD &&
846                     tgt != FCPARAM(isp)->isp_iid) {
847                         ccb->ccb_h.status = CAM_TID_INVALID;
848                         return (-1);
849                 }
850 #endif
851                 /*
852                  * This is as a good a place as any to check f/w capabilities.
853                  */
854                 if (FCPARAM(isp)->isp_tmode == 0) {
855                         xpt_print(ccb->ccb_h.path,
856                             "firmware does not support target mode\n");
857                         ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
858                         return (-1);
859                 }
860                 /*
861                  * XXX: We *could* handle non-SCCLUN f/w, but we'd have to
862                  * XXX: dork with our already fragile enable/disable code.
863                  */
864                 if (FCPARAM(isp)->isp_sccfw == 0) {
865                         xpt_print(ccb->ccb_h.path,
866                             "firmware not SCCLUN capable\n");
867                         ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
868                         return (-1);
869                 }
870         }
871
872         if (tgt == CAM_TARGET_WILDCARD) {
873                 if (lun == CAM_LUN_WILDCARD) {
874                         wildcard = 1;
875                 } else {
876                         ccb->ccb_h.status = CAM_LUN_INVALID;
877                         return (-1);
878                 }
879         } else {
880                 wildcard = 0;
881         }
882
883         tm_on = (isp->isp_osinfo.tmflags[bus] & TM_TMODE_ENABLED) != 0;
884
885         /*
886          * Next check to see whether this is a target/lun wildcard action.
887          *
888          * If so, we know that we can accept commands for luns that haven't
889          * been enabled yet and send them upstream. Otherwise, we have to
890          * handle them locally (if we see them at all).
891          */
892
893         if (wildcard) {
894                 tptr = &isp->isp_osinfo.tsdflt[bus];
895                 if (cel->enable) {
896                         if (tm_on) {
897                                 ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
898                                 return (-1);
899                         }
900                         ccb->ccb_h.status =
901                             xpt_create_path(&tptr->owner, NULL,
902                             xpt_path_path_id(ccb->ccb_h.path),
903                             xpt_path_target_id(ccb->ccb_h.path),
904                             xpt_path_lun_id(ccb->ccb_h.path));
905                         if (ccb->ccb_h.status != CAM_REQ_CMP) {
906                                 return (-1);
907                         }
908                         SLIST_INIT(&tptr->atios);
909                         SLIST_INIT(&tptr->inots);
910                         isp->isp_osinfo.tmflags[bus] |= TM_WILDCARD_ENABLED;
911                 } else {
912                         if (tm_on == 0) {
913                                 ccb->ccb_h.status = CAM_REQ_CMP;
914                                 return (-1);
915                         }
916                         if (tptr->hold) {
917                                 ccb->ccb_h.status = CAM_SCSI_BUSY;
918                                 return (-1);
919                         }
920                         xpt_free_path(tptr->owner);
921                         isp->isp_osinfo.tmflags[bus] &= ~TM_WILDCARD_ENABLED;
922                 }
923         }
924
925         /*
926          * Now check to see whether this bus needs to be
927          * enabled/disabled with respect to target mode.
928          */
929         av = bus << 31;
930         if (cel->enable && tm_on == 0) {
931                 av |= ENABLE_TARGET_FLAG;
932                 av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
933                 if (av) {
934                         ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
935                         if (wildcard) {
936                                 isp->isp_osinfo.tmflags[bus] &=
937                                     ~TM_WILDCARD_ENABLED;
938                                 xpt_free_path(tptr->owner);
939                         }
940                         return (-1);
941                 }
942                 isp->isp_osinfo.tmflags[bus] |= TM_TMODE_ENABLED;
943                 xpt_print(ccb->ccb_h.path, "Target Mode Enabled\n");
944         } else if (cel->enable == 0 && tm_on && wildcard) {
945                 if (are_any_luns_enabled(isp, bus)) {
946                         ccb->ccb_h.status = CAM_SCSI_BUSY;
947                         return (-1);
948                 }
949                 av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
950                 if (av) {
951                         ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
952                         return (-1);
953                 }
954                 isp->isp_osinfo.tmflags[bus] &= ~TM_TMODE_ENABLED;
955                 xpt_print(ccb->ccb_h.path, "Target Mode Disabled\n");
956         }
957
958         if (wildcard) {
959                 ccb->ccb_h.status = CAM_REQ_CMP;
960                 return (-1);
961         }
962
963         /*
964          * Find an empty slot
965          */
966         for (seq = 0; seq < NLEACT; seq++) {
967                 if (isp->isp_osinfo.leact[seq] == 0) {
968                         break;
969                 }
970         }
971         if (seq >= NLEACT) {
972                 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
973                 return (-1);
974                 
975         }
976         isp->isp_osinfo.leact[seq] = ccb;
977
978         if (cel->enable) {
979                 ccb->ccb_h.status =
980                     create_lun_state(isp, bus, ccb->ccb_h.path, &tptr);
981                 if (ccb->ccb_h.status != CAM_REQ_CMP) {
982                         isp->isp_osinfo.leact[seq] = 0;
983                         return (-1);
984                 }
985         } else {
986                 tptr = get_lun_statep(isp, bus, lun);
987                 if (tptr == NULL) {
988                         ccb->ccb_h.status = CAM_LUN_INVALID;
989                         return (-1);
990                 }
991         }
992
993         if (cel->enable) {
994                 int c, n, ulun = lun;
995
996                 cmd = RQSTYPE_ENABLE_LUN;
997                 c = DFLT_CMND_CNT;
998                 n = DFLT_INOT_CNT;
999                 if (IS_FC(isp) && lun != 0) {
1000                         cmd = RQSTYPE_MODIFY_LUN;
1001                         n = 0;
1002                         /*
1003                          * For SCC firmware, we only deal with setting
1004                          * (enabling or modifying) lun 0.
1005                          */
1006                         ulun = 0;
1007                 }
1008                 if (isp_lun_cmd(isp, cmd, bus, tgt, ulun, c, n, seq+1) == 0) {
1009                         rls_lun_statep(isp, tptr);
1010                         ccb->ccb_h.status = CAM_REQ_INPROG;
1011                         return (seq);
1012                 }
1013         } else {
1014                 int c, n, ulun = lun;
1015
1016                 cmd = -RQSTYPE_MODIFY_LUN;
1017                 c = DFLT_CMND_CNT;
1018                 n = DFLT_INOT_CNT;
1019                 if (IS_FC(isp) && lun != 0) {
1020                         n = 0;
1021                         /*
1022                          * For SCC firmware, we only deal with setting
1023                          * (enabling or modifying) lun 0.
1024                          */
1025                         ulun = 0;
1026                 }
1027                 if (isp_lun_cmd(isp, cmd, bus, tgt, ulun, c, n, seq+1) == 0) {
1028                         rls_lun_statep(isp, tptr);
1029                         ccb->ccb_h.status = CAM_REQ_INPROG;
1030                         return (seq);
1031                 }
1032         }
1033         rls_lun_statep(isp, tptr);
1034         xpt_print(ccb->ccb_h.path, "isp_lun_cmd failed\n");
1035         isp->isp_osinfo.leact[seq] = 0;
1036         ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1037         return (-1);
1038 }
1039
1040 static void
1041 isp_ledone(ispsoftc_t *isp, lun_entry_t *lep)
1042 {
1043         const char lfmt[] = "now %sabled for target mode\n";
1044         union ccb *ccb;
1045         uint32_t seq;
1046         tstate_t *tptr;
1047         int av;
1048         struct ccb_en_lun *cel;
1049
1050         seq = lep->le_reserved - 1;
1051         if (seq >= NLEACT) {
1052                 isp_prt(isp, ISP_LOGERR,
1053                     "seq out of range (%u) in isp_ledone", seq);
1054                 return;
1055         }
1056         ccb = isp->isp_osinfo.leact[seq];
1057         if (ccb == 0) {
1058                 isp_prt(isp, ISP_LOGERR,
1059                     "no ccb for seq %u in isp_ledone", seq);
1060                 return;
1061         }
1062         cel = &ccb->cel;
1063         tptr = get_lun_statep(isp, XS_CHANNEL(ccb), XS_LUN(ccb));
1064         if (tptr == NULL) {
1065                 xpt_print(ccb->ccb_h.path, "null tptr in isp_ledone\n");
1066                 isp->isp_osinfo.leact[seq] = 0;
1067                 return;
1068         }
1069
1070         if (lep->le_status != LUN_OK) {
1071                 xpt_print(ccb->ccb_h.path,
1072                     "ENABLE/MODIFY LUN returned 0x%x\n", lep->le_status);
1073 err:
1074                 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1075                 rls_lun_statep(isp, tptr);
1076                 isp->isp_osinfo.leact[seq] = 0;
1077                 xpt_done(ccb);
1078                 return;
1079         } else {
1080                 isp_prt(isp, ISP_LOGTDEBUG0,
1081                     "isp_ledone: ENABLE/MODIFY done okay");
1082         }
1083
1084
1085         if (cel->enable) {
1086                 ccb->ccb_h.status = CAM_REQ_CMP;
1087                 xpt_print(ccb->ccb_h.path, lfmt, "en");
1088                 rls_lun_statep(isp, tptr);
1089                 isp->isp_osinfo.leact[seq] = 0;
1090                 xpt_done(ccb);
1091                 return;
1092         }
1093
1094         if (lep->le_header.rqs_entry_type == RQSTYPE_MODIFY_LUN) {
1095                 if (isp_lun_cmd(isp, -RQSTYPE_ENABLE_LUN, XS_CHANNEL(ccb),
1096                     XS_TGT(ccb), XS_LUN(ccb), 0, 0, seq+1)) {
1097                         xpt_print(ccb->ccb_h.path,
1098                             "isp_ledone: isp_lun_cmd failed\n");
1099                         goto err;
1100                 }
1101                 rls_lun_statep(isp, tptr);
1102                 return;
1103         }
1104
1105         xpt_print(ccb->ccb_h.path, lfmt, "dis");
1106         rls_lun_statep(isp, tptr);
1107         destroy_lun_state(isp, tptr);
1108         ccb->ccb_h.status = CAM_REQ_CMP;
1109         isp->isp_osinfo.leact[seq] = 0;
1110         xpt_done(ccb);
1111         if (are_any_luns_enabled(isp, XS_CHANNEL(ccb)) == 0) {
1112                 int bus = XS_CHANNEL(ccb);
1113                 av = bus << 31;
1114                 av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
1115                 if (av) {
1116                         isp_prt(isp, ISP_LOGWARN,
1117                             "disable target mode on channel %d failed", bus);
1118                 }
1119                 isp->isp_osinfo.tmflags[bus] &= ~TM_TMODE_ENABLED;
1120         }
1121 }
1122
1123
1124 static cam_status
1125 isp_abort_tgt_ccb(ispsoftc_t *isp, union ccb *ccb)
1126 {
1127         tstate_t *tptr;
1128         struct ccb_hdr_slist *lp;
1129         struct ccb_hdr *curelm;
1130         int found, *ctr;
1131         union ccb *accb = ccb->cab.abort_ccb;
1132
1133         xpt_print(ccb->ccb_h.path, "aborting ccb %p\n", accb);
1134         if (accb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
1135                 int badpath = 0;
1136                 if (IS_FC(isp) && (accb->ccb_h.target_id != 
1137                     ((fcparam *) isp->isp_param)->isp_loopid)) {
1138                         badpath = 1;
1139                 } else if (IS_SCSI(isp) && (accb->ccb_h.target_id != 
1140                     ((sdparam *) isp->isp_param)->isp_initiator_id)) {
1141                         badpath = 1;
1142                 }
1143                 if (badpath) {
1144                         /*
1145                          * Being restrictive about target ids is really about
1146                          * making sure we're aborting for the right multi-tid
1147                          * path. This doesn't really make much sense at present.
1148                          */
1149 #if     0
1150                         return (CAM_PATH_INVALID);
1151 #endif
1152                 }
1153         }
1154         tptr = get_lun_statep(isp, XS_CHANNEL(ccb), accb->ccb_h.target_lun);
1155         if (tptr == NULL) {
1156                 xpt_print(ccb->ccb_h.path, "can't get statep\n");
1157                 return (CAM_PATH_INVALID);
1158         }
1159         if (accb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
1160                 lp = &tptr->atios;
1161                 ctr = &tptr->atio_count;
1162         } else if (accb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
1163                 lp = &tptr->inots;
1164                 ctr = &tptr->inot_count;
1165         } else {
1166                 rls_lun_statep(isp, tptr);
1167                 xpt_print(ccb->ccb_h.path, "bad function code %d\n",
1168                     accb->ccb_h.func_code);
1169                 return (CAM_UA_ABORT);
1170         }
1171         curelm = SLIST_FIRST(lp);
1172         found = 0;
1173         if (curelm == &accb->ccb_h) {
1174                 found = 1;
1175                 SLIST_REMOVE_HEAD(lp, sim_links.sle);
1176         } else {
1177                 while(curelm != NULL) {
1178                         struct ccb_hdr *nextelm;
1179
1180                         nextelm = SLIST_NEXT(curelm, sim_links.sle);
1181                         if (nextelm == &accb->ccb_h) {
1182                                 found = 1;
1183                                 SLIST_NEXT(curelm, sim_links.sle) =
1184                                     SLIST_NEXT(nextelm, sim_links.sle);
1185                                 break;
1186                         }
1187                         curelm = nextelm;
1188                 }
1189         }
1190         rls_lun_statep(isp, tptr);
1191         if (found) {
1192                 (*ctr)--;
1193                 accb->ccb_h.status = CAM_REQ_ABORTED;
1194                 xpt_done(accb);
1195                 return (CAM_REQ_CMP);
1196         }
1197         xpt_print(ccb->ccb_h.path, "ccb %p not found\n", accb);
1198         return (CAM_PATH_INVALID);
1199 }
1200
1201 static void
1202 isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
1203 {
1204         void *qe;
1205         struct ccb_scsiio *cso = &ccb->csio;
1206         uint32_t nxti, optr, handle;
1207         uint8_t local[QENTRY_LEN];
1208
1209
1210         if (isp_getrqentry(isp, &nxti, &optr, &qe)) {
1211                 xpt_print(ccb->ccb_h.path,
1212                     "Request Queue Overflow in isp_target_start_ctio\n");
1213                 XS_SETERR(ccb, CAM_REQUEUE_REQ);
1214                 goto out;
1215         }
1216         memset(local, 0, QENTRY_LEN);
1217
1218         /*
1219          * We're either moving data or completing a command here.
1220          */
1221
1222         if (IS_FC(isp)) {
1223                 atio_private_data_t *atp;
1224                 ct2_entry_t *cto = (ct2_entry_t *) local;
1225
1226                 cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
1227                 cto->ct_header.rqs_entry_count = 1;
1228                 if (FCPARAM(isp)->isp_2klogin) {
1229                         ((ct2e_entry_t *)cto)->ct_iid = cso->init_id;
1230                 } else {
1231                         cto->ct_iid = cso->init_id;
1232                         if (FCPARAM(isp)->isp_sccfw == 0) {
1233                                 cto->ct_lun = ccb->ccb_h.target_lun;
1234                         }
1235                 }
1236
1237                 atp = isp_get_atpd(isp, cso->tag_id);
1238                 if (atp == NULL) {
1239                         xpt_print(ccb->ccb_h.path,
1240                             "cannot find private data adjunct for tag %x\n",
1241                             cso->tag_id);
1242                         XS_SETERR(ccb, CAM_REQ_CMP_ERR);
1243                         goto out;
1244                 }
1245
1246                 cto->ct_rxid = cso->tag_id;
1247                 if (cso->dxfer_len == 0) {
1248                         cto->ct_flags |= CT2_FLAG_MODE1 | CT2_NO_DATA;
1249                         if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
1250                                 cto->ct_flags |= CT2_SENDSTATUS;
1251                                 cto->rsp.m1.ct_scsi_status = cso->scsi_status;
1252                                 cto->ct_resid =
1253                                     atp->orig_datalen - atp->bytes_xfered;
1254                                 if (cto->ct_resid < 0) {
1255                                         cto->rsp.m1.ct_scsi_status |=
1256                                             CT2_DATA_OVER;
1257                                 } else if (cto->ct_resid > 0) {
1258                                         cto->rsp.m1.ct_scsi_status |=
1259                                             CT2_DATA_UNDER;
1260                                 }
1261                         }
1262                         if ((ccb->ccb_h.flags & CAM_SEND_SENSE) != 0) {
1263                                 int m = min(cso->sense_len, MAXRESPLEN);
1264                                 memcpy(cto->rsp.m1.ct_resp,
1265                                     &cso->sense_data, m);
1266                                 cto->rsp.m1.ct_senselen = m;
1267                                 cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
1268                         }
1269                 } else {
1270                         cto->ct_flags |= CT2_FLAG_MODE0;
1271                         if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1272                                 cto->ct_flags |= CT2_DATA_IN;
1273                         } else {
1274                                 cto->ct_flags |= CT2_DATA_OUT;
1275                         }
1276                         cto->ct_reloff = atp->bytes_xfered;
1277                         if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
1278                                 cto->ct_flags |= CT2_SENDSTATUS;
1279                                 cto->rsp.m0.ct_scsi_status = cso->scsi_status;
1280                                 cto->ct_resid =
1281                                     atp->orig_datalen -
1282                                     (atp->bytes_xfered + cso->dxfer_len);
1283                                 if (cto->ct_resid < 0) {
1284                                         cto->rsp.m0.ct_scsi_status |=
1285                                             CT2_DATA_OVER;
1286                                 } else if (cto->ct_resid > 0) {
1287                                         cto->rsp.m0.ct_scsi_status |=
1288                                             CT2_DATA_UNDER;
1289                                 }
1290                         } else {
1291                                 atp->last_xframt = cso->dxfer_len;
1292                         }
1293                         /*
1294                          * If we're sending data and status back together,
1295                          * we can't also send back sense data as well.
1296                          */
1297                         ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
1298                 }
1299
1300                 if (cto->ct_flags & CT2_SENDSTATUS) {
1301                         isp_prt(isp, ISP_LOGTDEBUG0,
1302                             "CTIO2[%x] STATUS %x origd %u curd %u resid %u",
1303                             cto->ct_rxid, cso->scsi_status, atp->orig_datalen,
1304                             cso->dxfer_len, cto->ct_resid);
1305                         cto->ct_flags |= CT2_CCINCR;
1306                         atp->state = ATPD_STATE_LAST_CTIO;
1307                 } else {
1308                         atp->state = ATPD_STATE_CTIO;
1309                 }
1310                 cto->ct_timeout = 10;
1311         } else {
1312                 ct_entry_t *cto = (ct_entry_t *) local;
1313
1314                 cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
1315                 cto->ct_header.rqs_entry_count = 1;
1316                 cto->ct_iid = cso->init_id;
1317                 cto->ct_iid |= XS_CHANNEL(ccb) << 7;
1318                 cto->ct_tgt = ccb->ccb_h.target_id;
1319                 cto->ct_lun = ccb->ccb_h.target_lun;
1320                 cto->ct_fwhandle = AT_GET_HANDLE(cso->tag_id);
1321                 if (AT_HAS_TAG(cso->tag_id)) {
1322                         cto->ct_tag_val = (uint8_t) AT_GET_TAG(cso->tag_id);
1323                         cto->ct_flags |= CT_TQAE;
1324                 }
1325                 if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) {
1326                         cto->ct_flags |= CT_NODISC;
1327                 }
1328                 if (cso->dxfer_len == 0) {
1329                         cto->ct_flags |= CT_NO_DATA;
1330                 } else if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1331                         cto->ct_flags |= CT_DATA_IN;
1332                 } else {
1333                         cto->ct_flags |= CT_DATA_OUT;
1334                 }
1335                 if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
1336                         cto->ct_flags |= CT_SENDSTATUS|CT_CCINCR;
1337                         cto->ct_scsi_status = cso->scsi_status;
1338                         cto->ct_resid = cso->resid;
1339                         isp_prt(isp, ISP_LOGTDEBUG0,
1340                             "CTIO[%x] SCSI STATUS 0x%x resid %d tag_id %x",
1341                             cto->ct_fwhandle, cso->scsi_status, cso->resid,
1342                             cso->tag_id);
1343                 }
1344                 ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
1345                 cto->ct_timeout = 10;
1346         }
1347
1348         if (isp_save_xs_tgt(isp, ccb, &handle)) {
1349                 xpt_print(ccb->ccb_h.path,
1350                     "No XFLIST pointers for isp_target_start_ctio\n");
1351                 XS_SETERR(ccb, CAM_REQUEUE_REQ);
1352                 goto out;
1353         }
1354
1355
1356         /*
1357          * Call the dma setup routines for this entry (and any subsequent
1358          * CTIOs) if there's data to move, and then tell the f/w it's got
1359          * new things to play with. As with isp_start's usage of DMA setup,
1360          * any swizzling is done in the machine dependent layer. Because
1361          * of this, we put the request onto the queue area first in native
1362          * format.
1363          */
1364
1365         if (IS_FC(isp)) {
1366                 ct2_entry_t *cto = (ct2_entry_t *) local;
1367                 cto->ct_syshandle = handle;
1368         } else {
1369                 ct_entry_t *cto = (ct_entry_t *) local;
1370                 cto->ct_syshandle = handle;
1371         }
1372
1373         switch (ISP_DMASETUP(isp, cso, (ispreq_t *) local, &nxti, optr)) {
1374         case CMD_QUEUED:
1375                 ISP_ADD_REQUEST(isp, nxti);
1376                 ccb->ccb_h.status |= CAM_SIM_QUEUED;
1377                 return;
1378
1379         case CMD_EAGAIN:
1380                 XS_SETERR(ccb, CAM_REQUEUE_REQ);
1381                 break;
1382
1383         default:
1384                 break;
1385         }
1386         isp_destroy_tgt_handle(isp, handle);
1387
1388 out:
1389         xpt_done(ccb);
1390 }
1391
1392 static void
1393 isp_refire_putback_atio(void *arg)
1394 {
1395         int s = splcam();
1396         isp_target_putback_atio(arg);
1397         splx(s);
1398 }
1399
1400 static void
1401 isp_target_putback_atio(union ccb *ccb)
1402 {
1403         ispsoftc_t *isp;
1404         struct ccb_scsiio *cso;
1405         uint32_t nxti, optr;
1406         void *qe;
1407
1408         isp = XS_ISP(ccb);
1409
1410         if (isp_getrqentry(isp, &nxti, &optr, &qe)) {
1411                 xpt_print(ccb->ccb_h.path,
1412                     "isp_target_putback_atio: Request Queue Overflow\n"); 
1413                 (void) timeout(isp_refire_putback_atio, ccb, 10);
1414                 return;
1415         }
1416         memset(qe, 0, QENTRY_LEN);
1417         cso = &ccb->csio;
1418         if (IS_FC(isp)) {
1419                 at2_entry_t local, *at = &local;
1420                 MEMZERO(at, sizeof (at2_entry_t));
1421                 at->at_header.rqs_entry_type = RQSTYPE_ATIO2;
1422                 at->at_header.rqs_entry_count = 1;
1423                 if (FCPARAM(isp)->isp_sccfw) {
1424                         at->at_scclun = (uint16_t) ccb->ccb_h.target_lun;
1425                 } else {
1426                         at->at_lun = (uint8_t) ccb->ccb_h.target_lun;
1427                 }
1428                 at->at_status = CT_OK;
1429                 at->at_rxid = cso->tag_id;
1430                 at->at_iid = cso->ccb_h.target_id;
1431                 isp_put_atio2(isp, at, qe);
1432         } else {
1433                 at_entry_t local, *at = &local;
1434                 MEMZERO(at, sizeof (at_entry_t));
1435                 at->at_header.rqs_entry_type = RQSTYPE_ATIO;
1436                 at->at_header.rqs_entry_count = 1;
1437                 at->at_iid = cso->init_id;
1438                 at->at_iid |= XS_CHANNEL(ccb) << 7;
1439                 at->at_tgt = cso->ccb_h.target_id;
1440                 at->at_lun = cso->ccb_h.target_lun;
1441                 at->at_status = CT_OK;
1442                 at->at_tag_val = AT_GET_TAG(cso->tag_id);
1443                 at->at_handle = AT_GET_HANDLE(cso->tag_id);
1444                 isp_put_atio(isp, at, qe);
1445         }
1446         ISP_TDQE(isp, "isp_target_putback_atio", (int) optr, qe);
1447         ISP_ADD_REQUEST(isp, nxti);
1448         isp_complete_ctio(ccb);
1449 }
1450
1451 static void
1452 isp_complete_ctio(union ccb *ccb)
1453 {
1454         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
1455                 ccb->ccb_h.status |= CAM_REQ_CMP;
1456         }
1457         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1458         xpt_done(ccb);
1459 }
1460
1461 /*
1462  * Handle ATIO stuff that the generic code can't.
1463  * This means handling CDBs.
1464  */
1465
1466 static int
1467 isp_handle_platform_atio(ispsoftc_t *isp, at_entry_t *aep)
1468 {
1469         tstate_t *tptr;
1470         int status, bus, iswildcard;
1471         struct ccb_accept_tio *atiop;
1472
1473         /*
1474          * The firmware status (except for the QLTM_SVALID bit)
1475          * indicates why this ATIO was sent to us.
1476          *
1477          * If QLTM_SVALID is set, the firware has recommended Sense Data.
1478          *
1479          * If the DISCONNECTS DISABLED bit is set in the flags field,
1480          * we're still connected on the SCSI bus.
1481          */
1482         status = aep->at_status;
1483         if ((status & ~QLTM_SVALID) == AT_PHASE_ERROR) {
1484                 /*
1485                  * Bus Phase Sequence error. We should have sense data
1486                  * suggested by the f/w. I'm not sure quite yet what
1487                  * to do about this for CAM.
1488                  */
1489                 isp_prt(isp, ISP_LOGWARN, "PHASE ERROR");
1490                 isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1491                 return (0);
1492         }
1493         if ((status & ~QLTM_SVALID) != AT_CDB) {
1494                 isp_prt(isp, ISP_LOGWARN, "bad atio (0x%x) leaked to platform",
1495                     status);
1496                 isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1497                 return (0);
1498         }
1499
1500         bus = GET_BUS_VAL(aep->at_iid);
1501         tptr = get_lun_statep(isp, bus, aep->at_lun);
1502         if (tptr == NULL) {
1503                 tptr = get_lun_statep(isp, bus, CAM_LUN_WILDCARD);
1504                 if (tptr == NULL) {
1505                         /*
1506                          * Because we can't autofeed sense data back with
1507                          * a command for parallel SCSI, we can't give back
1508                          * a CHECK CONDITION. We'll give back a BUSY status
1509                          * instead. This works out okay because the only
1510                          * time we should, in fact, get this, is in the
1511                          * case that somebody configured us without the
1512                          * blackhole driver, so they get what they deserve.
1513                          */
1514                         isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1515                         return (0);
1516                 }
1517                 iswildcard = 1;
1518         } else {
1519                 iswildcard = 0;
1520         }
1521
1522         atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
1523         if (atiop == NULL) {
1524                 /*
1525                  * Because we can't autofeed sense data back with
1526                  * a command for parallel SCSI, we can't give back
1527                  * a CHECK CONDITION. We'll give back a QUEUE FULL status
1528                  * instead. This works out okay because the only time we
1529                  * should, in fact, get this, is in the case that we've
1530                  * run out of ATIOS.
1531                  */
1532                 xpt_print(tptr->owner,
1533                     "no ATIOS for lun %d from initiator %d on channel %d\n",
1534                     aep->at_lun, GET_IID_VAL(aep->at_iid), bus);
1535                 if (aep->at_flags & AT_TQAE)
1536                         isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0);
1537                 else
1538                         isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1539                 rls_lun_statep(isp, tptr);
1540                 return (0);
1541         }
1542         SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
1543         tptr->atio_count--;
1544         isp_prt(isp, ISP_LOGTDEBUG0, "Take FREE ATIO lun %d, count now %d",
1545             aep->at_lun, tptr->atio_count);
1546         if (iswildcard) {
1547                 atiop->ccb_h.target_id = aep->at_tgt;
1548                 atiop->ccb_h.target_lun = aep->at_lun;
1549         }
1550         if (aep->at_flags & AT_NODISC) {
1551                 atiop->ccb_h.flags = CAM_DIS_DISCONNECT;
1552         } else {
1553                 atiop->ccb_h.flags = 0;
1554         }
1555
1556         if (status & QLTM_SVALID) {
1557                 size_t amt = imin(QLTM_SENSELEN, sizeof (atiop->sense_data));
1558                 atiop->sense_len = amt;
1559                 MEMCPY(&atiop->sense_data, aep->at_sense, amt);
1560         } else {
1561                 atiop->sense_len = 0;
1562         }
1563
1564         atiop->init_id = GET_IID_VAL(aep->at_iid);
1565         atiop->cdb_len = aep->at_cdblen;
1566         MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen);
1567         atiop->ccb_h.status = CAM_CDB_RECVD;
1568         /*
1569          * Construct a tag 'id' based upon tag value (which may be 0..255)
1570          * and the handle (which we have to preserve).
1571          */
1572         AT_MAKE_TAGID(atiop->tag_id, bus, device_get_unit(isp->isp_dev), aep);
1573         if (aep->at_flags & AT_TQAE) {
1574                 atiop->tag_action = aep->at_tag_type;
1575                 atiop->ccb_h.status |= CAM_TAG_ACTION_VALID;
1576         }
1577         xpt_done((union ccb*)atiop);
1578         isp_prt(isp, ISP_LOGTDEBUG0,
1579             "ATIO[%x] CDB=0x%x bus %d iid%d->lun%d tag 0x%x ttype 0x%x %s",
1580             aep->at_handle, aep->at_cdb[0] & 0xff, GET_BUS_VAL(aep->at_iid),
1581             GET_IID_VAL(aep->at_iid), aep->at_lun, aep->at_tag_val & 0xff,
1582             aep->at_tag_type, (aep->at_flags & AT_NODISC)?
1583             "nondisc" : "disconnecting");
1584         rls_lun_statep(isp, tptr);
1585         return (0);
1586 }
1587
1588 static int
1589 isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep)
1590 {
1591         lun_id_t lun;
1592         tstate_t *tptr;
1593         struct ccb_accept_tio *atiop;
1594         atio_private_data_t *atp;
1595
1596         /*
1597          * The firmware status (except for the QLTM_SVALID bit)
1598          * indicates why this ATIO was sent to us.
1599          *
1600          * If QLTM_SVALID is set, the firware has recommended Sense Data.
1601          */
1602         if ((aep->at_status & ~QLTM_SVALID) != AT_CDB) {
1603                 isp_prt(isp, ISP_LOGWARN,
1604                     "bogus atio (0x%x) leaked to platform", aep->at_status);
1605                 isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1606                 return (0);
1607         }
1608
1609         if (FCPARAM(isp)->isp_sccfw) {
1610                 lun = aep->at_scclun;
1611         } else {
1612                 lun = aep->at_lun;
1613         }
1614         tptr = get_lun_statep(isp, 0, lun);
1615         if (tptr == NULL) {
1616                 isp_prt(isp, ISP_LOGTDEBUG0,
1617                     "[0x%x] no state pointer for lun %d", aep->at_rxid, lun);
1618                 tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD);
1619                 if (tptr == NULL) {
1620                         isp_endcmd(isp, aep,
1621                             SCSI_STATUS_CHECK_COND | ECMD_SVALID |
1622                             (0x5 << 12) | (0x25 << 16), 0);
1623                         return (0);
1624                 }
1625         }
1626
1627         atp = isp_get_atpd(isp, 0);
1628         atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
1629         if (atiop == NULL || atp == NULL) {
1630
1631                 /*
1632                  * Because we can't autofeed sense data back with
1633                  * a command for parallel SCSI, we can't give back
1634                  * a CHECK CONDITION. We'll give back a QUEUE FULL status
1635                  * instead. This works out okay because the only time we
1636                  * should, in fact, get this, is in the case that we've
1637                  * run out of ATIOS.
1638                  */
1639                 xpt_print(tptr->owner,
1640                     "no %s for lun %d from initiator %d\n",
1641                     (atp == NULL && atiop == NULL)? "ATIO2s *or* ATPS" :
1642                     ((atp == NULL)? "ATPs" : "ATIO2s"), lun, aep->at_iid);
1643                 rls_lun_statep(isp, tptr);
1644                 isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0);
1645                 return (0);
1646         }
1647         atp->state = ATPD_STATE_ATIO;
1648         SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
1649         tptr->atio_count--;
1650         isp_prt(isp, ISP_LOGTDEBUG0, "Take FREE ATIO lun %d, count now %d",
1651             lun, tptr->atio_count);
1652
1653         if (tptr == &isp->isp_osinfo.tsdflt[0]) {
1654                 atiop->ccb_h.target_id = FCPARAM(isp)->isp_loopid;
1655                 atiop->ccb_h.target_lun = lun;
1656         }
1657         /*
1658          * We don't get 'suggested' sense data as we do with SCSI cards.
1659          */
1660         atiop->sense_len = 0;
1661
1662         atiop->init_id = aep->at_iid;
1663         atiop->cdb_len = ATIO2_CDBLEN;
1664         MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, ATIO2_CDBLEN);
1665         atiop->ccb_h.status = CAM_CDB_RECVD;
1666         atiop->tag_id = aep->at_rxid;
1667         switch (aep->at_taskflags & ATIO2_TC_ATTR_MASK) {
1668         case ATIO2_TC_ATTR_SIMPLEQ:
1669                 atiop->tag_action = MSG_SIMPLE_Q_TAG;
1670                 break;
1671         case ATIO2_TC_ATTR_HEADOFQ:
1672                 atiop->tag_action = MSG_HEAD_OF_Q_TAG;
1673                 break;
1674         case ATIO2_TC_ATTR_ORDERED:
1675                 atiop->tag_action = MSG_ORDERED_Q_TAG;
1676                 break;
1677         case ATIO2_TC_ATTR_ACAQ:                /* ?? */
1678         case ATIO2_TC_ATTR_UNTAGGED:
1679         default:
1680                 atiop->tag_action = 0;
1681                 break;
1682         }
1683         atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
1684
1685         atp->tag = atiop->tag_id;
1686         atp->lun = lun;
1687         atp->orig_datalen = aep->at_datalen;
1688         atp->last_xframt = 0;
1689         atp->bytes_xfered = 0;
1690         atp->state = ATPD_STATE_CAM;
1691         xpt_done((union ccb*)atiop);
1692
1693         isp_prt(isp, ISP_LOGTDEBUG0,
1694             "ATIO2[%x] CDB=0x%x iid%d->lun%d tattr 0x%x datalen %u",
1695             aep->at_rxid, aep->at_cdb[0] & 0xff, aep->at_iid,
1696             lun, aep->at_taskflags, aep->at_datalen);
1697         rls_lun_statep(isp, tptr);
1698         return (0);
1699 }
1700
1701 static int
1702 isp_handle_platform_ctio(ispsoftc_t *isp, void *arg)
1703 {
1704         union ccb *ccb;
1705         int sentstatus, ok, notify_cam, resid = 0;
1706         uint16_t tval;
1707
1708         /*
1709          * CTIO and CTIO2 are close enough....
1710          */
1711
1712         ccb = isp_find_xs_tgt(isp, ((ct_entry_t *)arg)->ct_syshandle);
1713         KASSERT((ccb != NULL), ("null ccb in isp_handle_platform_ctio"));
1714         isp_destroy_tgt_handle(isp, ((ct_entry_t *)arg)->ct_syshandle);
1715
1716         if (IS_FC(isp)) {
1717                 ct2_entry_t *ct = arg;
1718                 atio_private_data_t *atp = isp_get_atpd(isp, ct->ct_rxid);
1719                 if (atp == NULL) {
1720                         isp_prt(isp, ISP_LOGERR,
1721                             "cannot find adjunct for %x after I/O",
1722                             ct->ct_rxid);
1723                         return (0);
1724                 }
1725                 sentstatus = ct->ct_flags & CT2_SENDSTATUS;
1726                 ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;
1727                 if (ok && sentstatus && (ccb->ccb_h.flags & CAM_SEND_SENSE)) {
1728                         ccb->ccb_h.status |= CAM_SENT_SENSE;
1729                 }
1730                 notify_cam = ct->ct_header.rqs_seqno & 0x1;
1731                 if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
1732                         resid = ct->ct_resid;
1733                         atp->bytes_xfered += (atp->last_xframt - resid);
1734                         atp->last_xframt = 0;
1735                 }
1736                 if (sentstatus || !ok) {
1737                         atp->tag = 0;
1738                 }
1739                 isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN,
1740                     "CTIO2[%x] sts 0x%x flg 0x%x sns %d resid %d %s",
1741                     ct->ct_rxid, ct->ct_status, ct->ct_flags,
1742                     (ccb->ccb_h.status & CAM_SENT_SENSE) != 0,
1743                     resid, sentstatus? "FIN" : "MID");
1744                 tval = ct->ct_rxid;
1745
1746                 /* XXX: should really come after isp_complete_ctio */
1747                 atp->state = ATPD_STATE_PDON;
1748         } else {
1749                 ct_entry_t *ct = arg;
1750                 sentstatus = ct->ct_flags & CT_SENDSTATUS;
1751                 ok = (ct->ct_status  & ~QLTM_SVALID) == CT_OK;
1752                 /*
1753                  * We *ought* to be able to get back to the original ATIO
1754                  * here, but for some reason this gets lost. It's just as
1755                  * well because it's squirrelled away as part of periph
1756                  * private data.
1757                  *
1758                  * We can live without it as long as we continue to use
1759                  * the auto-replenish feature for CTIOs.
1760                  */
1761                 notify_cam = ct->ct_header.rqs_seqno & 0x1;
1762                 if (ct->ct_status & QLTM_SVALID) {
1763                         char *sp = (char *)ct;
1764                         sp += CTIO_SENSE_OFFSET;
1765                         ccb->csio.sense_len =
1766                             min(sizeof (ccb->csio.sense_data), QLTM_SENSELEN);
1767                         MEMCPY(&ccb->csio.sense_data, sp, ccb->csio.sense_len);
1768                         ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
1769                 }
1770                 if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) {
1771                         resid = ct->ct_resid;
1772                 }
1773                 isp_prt(isp, ISP_LOGTDEBUG0,
1774                     "CTIO[%x] tag %x iid %d lun %d sts %x flg %x resid %d %s",
1775                     ct->ct_fwhandle, ct->ct_tag_val, ct->ct_iid, ct->ct_lun,
1776                     ct->ct_status, ct->ct_flags, resid,
1777                     sentstatus? "FIN" : "MID");
1778                 tval = ct->ct_fwhandle;
1779         }
1780         ccb->csio.resid += resid;
1781
1782         /*
1783          * We're here either because intermediate data transfers are done
1784          * and/or the final status CTIO (which may have joined with a
1785          * Data Transfer) is done.
1786          *
1787          * In any case, for this platform, the upper layers figure out
1788          * what to do next, so all we do here is collect status and
1789          * pass information along. Any DMA handles have already been
1790          * freed.
1791          */
1792         if (notify_cam == 0) {
1793                 isp_prt(isp, ISP_LOGTDEBUG0, "  INTER CTIO[0x%x] done", tval);
1794                 return (0);
1795         }
1796
1797         isp_prt(isp, ISP_LOGTDEBUG0, "%s CTIO[0x%x] done",
1798             (sentstatus)? "  FINAL " : "MIDTERM ", tval);
1799
1800         if (!ok) {
1801                 isp_target_putback_atio(ccb);
1802         } else {
1803                 isp_complete_ctio(ccb);
1804
1805         }
1806         return (0);
1807 }
1808
1809 static int
1810 isp_handle_platform_notify_scsi(ispsoftc_t *isp, in_entry_t *inp)
1811 {
1812         return (0);     /* XXXX */
1813 }
1814
1815 static int
1816 isp_handle_platform_notify_fc(ispsoftc_t *isp, in_fcentry_t *inp)
1817 {
1818
1819         switch (inp->in_status) {
1820         case IN_PORT_LOGOUT:
1821                 isp_prt(isp, ISP_LOGWARN, "port logout of iid %d",
1822                    inp->in_iid);
1823                 break;
1824         case IN_PORT_CHANGED:
1825                 isp_prt(isp, ISP_LOGWARN, "port changed for iid %d",
1826                    inp->in_iid);
1827                 break;
1828         case IN_GLOBAL_LOGO:
1829                 isp_prt(isp, ISP_LOGINFO, "all ports logged out");
1830                 break;
1831         case IN_ABORT_TASK:
1832         {
1833                 atio_private_data_t *atp = isp_get_atpd(isp, inp->in_seqid);
1834                 struct ccb_immed_notify *inot = NULL;
1835
1836                 if (atp) {
1837                         tstate_t *tptr = get_lun_statep(isp, 0, atp->lun);
1838                         if (tptr) {
1839                                 inot = (struct ccb_immed_notify *)
1840                                     SLIST_FIRST(&tptr->inots);
1841                                 if (inot) {
1842                                         tptr->inot_count--;
1843                                         SLIST_REMOVE_HEAD(&tptr->inots,
1844                                             sim_links.sle);
1845                                         isp_prt(isp, ISP_LOGTDEBUG0,
1846                                             "Take FREE INOT count now %d",
1847                                             tptr->inot_count);
1848                                 }
1849                         }
1850                         isp_prt(isp, ISP_LOGWARN,
1851                            "abort task RX_ID %x IID %d state %d",
1852                            inp->in_seqid, inp->in_iid, atp->state);
1853                 } else {
1854                         isp_prt(isp, ISP_LOGWARN,
1855                            "abort task RX_ID %x from iid %d, state unknown",
1856                            inp->in_seqid, inp->in_iid);
1857                 }
1858                 if (inot) {
1859                         inot->initiator_id = inp->in_iid;
1860                         inot->sense_len = 0;
1861                         inot->message_args[0] = MSG_ABORT_TAG;
1862                         inot->message_args[1] = inp->in_seqid & 0xff;
1863                         inot->message_args[2] = (inp->in_seqid >> 8) & 0xff;
1864                         inot->ccb_h.status = CAM_MESSAGE_RECV;
1865                         xpt_done((union ccb *)inot);
1866                 }
1867                 break;
1868         }
1869         default:
1870                 break;
1871         }
1872         return (0);
1873 }
1874 #endif
1875
1876 static void
1877 isp_cam_async(void *cbarg, uint32_t code, struct cam_path *path, void *arg)
1878 {
1879         struct cam_sim *sim;
1880         ispsoftc_t *isp;
1881
1882         sim = (struct cam_sim *)cbarg;
1883         isp = (ispsoftc_t *) cam_sim_softc(sim);
1884         switch (code) {
1885         case AC_LOST_DEVICE:
1886                 if (IS_SCSI(isp)) {
1887                         uint16_t oflags, nflags;
1888                         sdparam *sdp = isp->isp_param;
1889                         int tgt;
1890
1891                         tgt = xpt_path_target_id(path);
1892                         if (tgt >= 0) {
1893                                 sdp += cam_sim_bus(sim);
1894                                 nflags = sdp->isp_devparam[tgt].nvrm_flags;
1895 #ifndef ISP_TARGET_MODE
1896                                 nflags &= DPARM_SAFE_DFLT;
1897                                 if (isp->isp_loaded_fw) {
1898                                         nflags |= DPARM_NARROW | DPARM_ASYNC;
1899                                 }
1900 #else
1901                                 nflags = DPARM_DEFAULT;
1902 #endif
1903                                 oflags = sdp->isp_devparam[tgt].goal_flags;
1904                                 sdp->isp_devparam[tgt].goal_flags = nflags;
1905                                 sdp->isp_devparam[tgt].dev_update = 1;
1906                                 isp->isp_update |= (1 << cam_sim_bus(sim));
1907                                 (void) isp_control(isp,
1908                                     ISPCTL_UPDATE_PARAMS, NULL);
1909                                 sdp->isp_devparam[tgt].goal_flags = oflags;
1910                         }
1911                 }
1912                 break;
1913         default:
1914                 isp_prt(isp, ISP_LOGWARN, "isp_cam_async: Code 0x%x", code);
1915                 break;
1916         }
1917 }
1918
1919 static void
1920 isp_poll(struct cam_sim *sim)
1921 {
1922         ispsoftc_t *isp = cam_sim_softc(sim);
1923         uint32_t isr;
1924         uint16_t sema, mbox;
1925
1926         if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
1927                 isp_intr(isp, isr, sema, mbox);
1928         }
1929 }
1930
1931
1932 static int isp_watchdog_work(ispsoftc_t *, XS_T *);
1933
1934 static int
1935 isp_watchdog_work(ispsoftc_t *isp, XS_T *xs)
1936 {
1937         uint32_t handle;
1938
1939         /*
1940          * We've decided this command is dead. Make sure we're not trying
1941          * to kill a command that's already dead by getting it's handle and
1942          * and seeing whether it's still alive.
1943          */
1944         handle = isp_find_handle(isp, xs);
1945         if (handle) {
1946                 uint32_t isr;
1947                 uint16_t sema, mbox;
1948
1949                 if (XS_CMD_DONE_P(xs)) {
1950                         isp_prt(isp, ISP_LOGDEBUG1,
1951                             "watchdog found done cmd (handle 0x%x)", handle);
1952                         return (1);;
1953                 }
1954
1955                 if (XS_CMD_WDOG_P(xs)) {
1956                         isp_prt(isp, ISP_LOGDEBUG2,
1957                             "recursive watchdog (handle 0x%x)", handle);
1958                         return (1);
1959                 }
1960
1961                 XS_CMD_S_WDOG(xs);
1962                 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
1963                         isp_intr(isp, isr, sema, mbox);
1964                 }
1965                 if (XS_CMD_DONE_P(xs)) {
1966                         isp_prt(isp, ISP_LOGDEBUG2,
1967                             "watchdog cleanup for handle 0x%x", handle);
1968                         isp_free_pcmd(isp, (union ccb *)xs);
1969                         xpt_done((union ccb *) xs);
1970                 } else if (XS_CMD_GRACE_P(xs)) {
1971                         /*
1972                          * Make sure the command is *really* dead before we
1973                          * release the handle (and DMA resources) for reuse.
1974                          */
1975                         (void) isp_control(isp, ISPCTL_ABORT_CMD, xs);
1976
1977                         /*
1978                          * After this point, the comamnd is really dead.
1979                          */
1980                         if (XS_XFRLEN(xs)) {
1981                                 ISP_DMAFREE(isp, xs, handle);
1982                         } 
1983                         isp_destroy_handle(isp, handle);
1984                         xpt_print(xs->ccb_h.path,
1985                             "watchdog timeout for handle 0x%x\n", handle);
1986                         XS_SETERR(xs, CAM_CMD_TIMEOUT);
1987                         XS_CMD_C_WDOG(xs);
1988                         isp_done(xs);
1989                 } else {
1990                         XS_CMD_C_WDOG(xs);
1991                         xs->ccb_h.timeout_ch = timeout(isp_watchdog, xs, hz);
1992                         XS_CMD_S_GRACE(xs);
1993                         isp->isp_sendmarker |= 1 << XS_CHANNEL(xs);
1994                 }
1995                 return (1);
1996         }
1997         return (0);
1998 }
1999
2000 static void
2001 isp_watchdog(void *arg)
2002 {
2003         ispsoftc_t *isp;
2004         XS_T *xs = arg;
2005         int r;
2006
2007         for (r = 0, isp = isplist; r && isp; isp = isp->isp_osinfo.next) {
2008                 ISP_LOCK(isp);
2009                 r = isp_watchdog_work(isp, xs);
2010                 ISP_UNLOCK(isp);
2011         }
2012         if (isp == NULL) {
2013                 printf("isp_watchdog: nobody had %p active\n", arg);
2014         }
2015 }
2016
2017
2018 #if __FreeBSD_version >= 600000  
2019 static void
2020 isp_make_here(ispsoftc_t *isp, int tgt)
2021 {
2022         union ccb *ccb;
2023         /*
2024          * Allocate a CCB, create a wildcard path for this bus,
2025          * and schedule a rescan.
2026          */
2027         ccb = xpt_alloc_ccb_nowait();
2028         if (ccb == NULL) {
2029                 isp_prt(isp, ISP_LOGWARN, "unable to alloc CCB for rescan");
2030                 return;
2031         }
2032         if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
2033             cam_sim_path(isp->isp_sim), tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
2034                 isp_prt(isp, ISP_LOGWARN, "unable to create path for rescan");
2035                 xpt_free_ccb(ccb);
2036                 return;
2037         }
2038         xpt_rescan(ccb);
2039 }
2040
2041 static void
2042 isp_make_gone(ispsoftc_t *isp, int tgt)
2043 {
2044         struct cam_path *tp;
2045         if (xpt_create_path(&tp, NULL, cam_sim_path(isp->isp_sim), tgt,
2046             CAM_LUN_WILDCARD) == CAM_REQ_CMP) {
2047                 xpt_async(AC_LOST_DEVICE, tp, NULL);
2048                 xpt_free_path(tp);
2049         }
2050 }
2051 #else
2052 #define isp_make_here(isp, tgt) do { ; } while (0)
2053 #define isp_make_gone(isp, tgt) do { ; } while (0)
2054 #endif
2055
2056
2057 /*
2058  * Gone Device Timer Function- when we have decided that a device has gone
2059  * away, we wait a specific period of time prior to telling the OS it has
2060  * gone away.
2061  *
2062  * This timer function fires once a second and then scans the port database
2063  * for devices that are marked dead but still have a virtual target assigned.
2064  * We decrement a counter for that port database entry, and when it hits zero,
2065  * we tell the OS the device has gone away.
2066  */
2067 static void
2068 isp_gdt(void *arg)
2069 {
2070         ispsoftc_t *isp = arg;
2071         fcportdb_t *lp;
2072         int dbidx, tgt, more_to_do = 0;
2073
2074         ISP_LOCK(isp);
2075         isp_prt(isp, ISP_LOGDEBUG0, "GDT timer expired");
2076         for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
2077                 lp = &FCPARAM(isp)->portdb[dbidx];
2078
2079                 if (lp->state != FC_PORTDB_STATE_ZOMBIE) {
2080                         continue;
2081                 }
2082                 if (lp->ini_map_idx == 0) {
2083                         continue;
2084                 }
2085                 if (lp->new_reserved == 0) {
2086                         continue;
2087                 }
2088                 lp->new_reserved -= 1;
2089                 if (lp->new_reserved != 0) {
2090                         more_to_do++;
2091                         continue;
2092                 }
2093                 tgt = lp->ini_map_idx - 1;
2094                 FCPARAM(isp)->isp_ini_map[tgt] = 0;
2095                 lp->ini_map_idx = 0;
2096                 lp->state = FC_PORTDB_STATE_NIL;
2097                 isp_prt(isp, ISP_LOGCONFIG, prom3, lp->portid, tgt,
2098                     "Gone Device Timeout");
2099                 isp_make_gone(isp, tgt);
2100         }
2101         if (more_to_do) {
2102                 isp->isp_osinfo.gdt_running = 1;
2103                 callout_reset(&isp->isp_osinfo.gdt, hz, isp_gdt, isp);
2104         } else {
2105                 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2106                     "stopping Gone Device Timer");
2107                 isp->isp_osinfo.gdt_running = 0;
2108         }
2109         ISP_UNLOCK(isp);
2110 }
2111
2112 /*
2113  * Loop Down Timer Function- when loop goes down, a timer is started and
2114  * and after it expires we come here and take all probational devices that
2115  * the OS knows about and the tell the OS that they've gone away.
2116  * 
2117  * We don't clear the devices out of our port database because, when loop
2118  * come back up, we have to do some actual cleanup with the chip at that
2119  * point (implicit PLOGO, e.g., to get the chip's port database state right).
2120  */
2121 static void
2122 isp_ldt(void *arg)
2123 {
2124         ispsoftc_t *isp = arg;
2125         fcportdb_t *lp;
2126         int dbidx, tgt;
2127
2128         ISP_LOCK(isp);
2129
2130         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Loop Down Timer expired");
2131
2132         /*
2133          * Notify to the OS all targets who we now consider have departed.
2134          */
2135         for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
2136                 lp = &FCPARAM(isp)->portdb[dbidx];
2137
2138                 if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
2139                         continue;
2140                 }
2141                 if (lp->ini_map_idx == 0) {
2142                         continue;
2143                 }
2144
2145                 /*
2146                  * XXX: CLEAN UP AND COMPLETE ANY PENDING COMMANDS FIRST!
2147                  */
2148
2149                 /*
2150                  * Mark that we've announced that this device is gone....
2151                  */
2152                 lp->reserved = 1;
2153
2154                 /*
2155                  * but *don't* change the state of the entry. Just clear
2156                  * any target id stuff and announce to CAM that the
2157                  * device is gone. This way any necessary PLOGO stuff
2158                  * will happen when loop comes back up.
2159                  */
2160
2161                 tgt = lp->ini_map_idx - 1;
2162                 FCPARAM(isp)->isp_ini_map[tgt] = 0;
2163                 lp->ini_map_idx = 0;
2164                 isp_prt(isp, ISP_LOGCONFIG, prom3, lp->portid, tgt,
2165                     "Loop Down Timeout");
2166                 isp_make_gone(isp, tgt);
2167         }
2168
2169         /*
2170          * The loop down timer has expired. Wake up the kthread
2171          * to notice that fact (or make it false).
2172          */
2173         isp->isp_osinfo.loop_down_time = isp->isp_osinfo.loop_down_limit+1;
2174         wakeup(ISP_KT_WCHAN(isp));
2175         ISP_UNLOCK(isp);
2176 }
2177
2178 static void
2179 isp_kthread(void *arg)
2180 {
2181         ispsoftc_t *isp = arg;
2182         int slp = 0;
2183 #if __FreeBSD_version < 500000  
2184         int s = splcam();
2185 #elif __FreeBSD_version < 700037
2186         mtx_lock(&Giant);
2187 #else
2188         mtx_lock(&isp->isp_osinfo.lock);
2189 #endif
2190         /*
2191          * The first loop is for our usage where we have yet to have
2192          * gotten good fibre channel state.
2193          */
2194         for (;;) {
2195                 int wasfrozen, lb, lim;
2196
2197                 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2198                     "isp_kthread: checking FC state");
2199                 isp->isp_osinfo.mbox_sleep_ok = 1;
2200                 lb = isp_fc_runstate(isp, 250000);
2201                 isp->isp_osinfo.mbox_sleep_ok = 0;
2202                 if (lb) {
2203                         /*
2204                          * Increment loop down time by the last sleep interval
2205                          */
2206                         isp->isp_osinfo.loop_down_time += slp;
2207
2208                         if (lb < 0) {
2209                                 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2210                                     "kthread: FC loop not up (down count %d)",
2211                                     isp->isp_osinfo.loop_down_time);
2212                         } else {
2213                                 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2214                                     "kthread: FC got to %d (down count %d)",
2215                                     lb, isp->isp_osinfo.loop_down_time);
2216                         }
2217
2218
2219                         /*
2220                          * If we've never seen loop up and we've waited longer
2221                          * than quickboot time, or we've seen loop up but we've
2222                          * waited longer than loop_down_limit, give up and go
2223                          * to sleep until loop comes up.
2224                          */
2225                         if (FCPARAM(isp)->loop_seen_once == 0) {
2226                                 lim = isp_quickboot_time;
2227                         } else {
2228                                 lim = isp->isp_osinfo.loop_down_limit;
2229                         }
2230                         if (isp->isp_osinfo.loop_down_time >= lim) {
2231                                 isp_freeze_loopdown(isp, "loop limit hit");
2232                                 slp = 0;
2233                         } else if (isp->isp_osinfo.loop_down_time < 10) {
2234                                 slp = 1;
2235                         } else if (isp->isp_osinfo.loop_down_time < 30) {
2236                                 slp = 5;
2237                         } else if (isp->isp_osinfo.loop_down_time < 60) {
2238                                 slp = 10;
2239                         } else if (isp->isp_osinfo.loop_down_time < 120) {
2240                                 slp = 20;
2241                         } else {
2242                                 slp = 30;
2243                         }
2244
2245                 } else {
2246                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2247                             "isp_kthread: FC state OK");
2248                         isp->isp_osinfo.loop_down_time = 0;
2249                         slp = 0;
2250                 }
2251
2252                 /*
2253                  * If we'd frozen the simq, unfreeze it now so that CAM
2254                  * can start sending us commands. If the FC state isn't
2255                  * okay yet, they'll hit that in isp_start which will
2256                  * freeze the queue again.
2257                  */
2258                 wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN;
2259                 isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN;
2260                 if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
2261                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2262                             "isp_kthread: releasing simq");
2263                         xpt_release_simq(isp->isp_sim, 1);
2264                 }
2265                 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2266                     "isp_kthread: sleep time %d", slp);
2267 #if __FreeBSD_version < 700037
2268                 tsleep(ISP_KT_WCHAN(isp), PRIBIO, "ispf", slp * hz);
2269 #else
2270                 msleep(ISP_KT_WCHAN(isp), &isp->isp_osinfo.lock,
2271                     PRIBIO, "ispf", slp * hz);
2272 #endif
2273                 /*
2274                  * If slp is zero, we're waking up for the first time after
2275                  * things have been okay. In this case, we set a deferral state
2276                  * for all commands and delay hysteresis seconds before starting
2277                  * the FC state evaluation. This gives the loop/fabric a chance
2278                  * to settle.
2279                  */
2280                 if (slp == 0 && isp->isp_osinfo.hysteresis) {
2281                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
2282                             "isp_kthread: sleep hysteresis tick time %d",
2283                             isp->isp_osinfo.hysteresis * hz);
2284 #if __FreeBSD_version < 700037
2285                         (void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT",
2286                             (isp->isp_osinfo.hysteresis * hz));
2287 #else
2288                         (void) msleep(&isp_fabric_hysteresis,
2289                             &isp->isp_osinfo.lock, PRIBIO, "ispT",
2290                             (isp->isp_osinfo.hysteresis * hz));
2291 #endif
2292                 }
2293         }
2294 #if __FreeBSD_version < 500000  
2295         splx(s);
2296 #elif __FreeBSD_version < 700037
2297         mtx_unlock(&Giant);
2298 #else
2299         mtx_unlock(&isp->isp_osinfo.lock);
2300 #endif
2301 }
2302
2303 #if __FreeBSD_version < 500000  
2304 static void isp_action_wrk(struct cam_sim *, union ccb *);
2305 static void
2306 isp_action(struct cam_sim *sim, union ccb *ccb)
2307 {
2308         ispsoftc_t *isp = (ispsoftc_t *)cam_sim_softc(sim);
2309         ISP_LOCK(isp);
2310         isp_action_wrk(sim, ccb);
2311         ISP_UNLOCK(isp);
2312 }
2313 #define isp_action isp_action_wrk
2314 #endif
2315
2316 static void
2317 isp_action(struct cam_sim *sim, union ccb *ccb)
2318 {
2319         int bus, tgt, ts, error, lim;
2320         ispsoftc_t *isp;
2321         struct ccb_trans_settings *cts;
2322
2323         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
2324         
2325         isp = (ispsoftc_t *)cam_sim_softc(sim);
2326         if (isp->isp_state != ISP_RUNSTATE &&
2327             ccb->ccb_h.func_code == XPT_SCSI_IO) {
2328                 isp_init(isp);
2329                 if (isp->isp_state != ISP_INITSTATE) {
2330                         /*
2331                          * Lie. Say it was a selection timeout.
2332                          */
2333                         ccb->ccb_h.status = CAM_SEL_TIMEOUT | CAM_DEV_QFRZN;
2334                         xpt_freeze_devq(ccb->ccb_h.path, 1);
2335                         xpt_done(ccb);
2336                         return;
2337                 }
2338                 isp->isp_state = ISP_RUNSTATE;
2339         }
2340         isp_prt(isp, ISP_LOGDEBUG2, "isp_action code %x", ccb->ccb_h.func_code);
2341         ISP_PCMD(ccb) = NULL;
2342
2343         switch (ccb->ccb_h.func_code) {
2344         case XPT_SCSI_IO:       /* Execute the requested I/O operation */
2345                 /*
2346                  * Do a couple of preliminary checks...
2347                  */
2348                 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
2349                         if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
2350                                 ccb->ccb_h.status = CAM_REQ_INVALID;
2351                                 xpt_done(ccb);
2352                                 break;
2353                         }
2354                 }
2355 #ifdef  DIAGNOSTIC
2356                 if (ccb->ccb_h.target_id > (ISP_MAX_TARGETS(isp) - 1)) {
2357                         xpt_print(ccb->ccb_h.path, "invalid target\n");
2358                         ccb->ccb_h.status = CAM_PATH_INVALID;
2359                 } else if (ccb->ccb_h.target_lun > (ISP_MAX_LUNS(isp) - 1)) {
2360                         xpt_print(ccb->ccb_h.path, "invalid lun\n");
2361                         ccb->ccb_h.status = CAM_PATH_INVALID;
2362                 }
2363                 if (ccb->ccb_h.status == CAM_PATH_INVALID) {
2364                         xpt_done(ccb);
2365                         break;
2366                 }
2367 #endif
2368                 ccb->csio.scsi_status = SCSI_STATUS_OK;
2369                 if (isp_get_pcmd(isp, ccb)) {
2370                         isp_prt(isp, ISP_LOGWARN, "out of PCMDs");
2371                         cam_freeze_devq(ccb->ccb_h.path);
2372                         cam_release_devq(ccb->ccb_h.path,
2373                             RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
2374                         xpt_done(ccb);
2375                         break;
2376                 }
2377                 error = isp_start((XS_T *) ccb);
2378                 switch (error) {
2379                 case CMD_QUEUED:
2380                         XS_CMD_S_CLEAR(ccb);
2381                         ccb->ccb_h.status |= CAM_SIM_QUEUED;
2382                         if (ccb->ccb_h.timeout == CAM_TIME_INFINITY) {
2383                                 break;
2384                         }
2385                         ts = ccb->ccb_h.timeout;
2386                         if (ts == CAM_TIME_DEFAULT) {
2387                                 ts = 60*1000;
2388                         }
2389                         ts = isp_mstohz(ts);
2390                         callout_reset(&PISP_PCMD(ccb)->wdog, ts,
2391                             isp_watchdog, ccb);
2392                         break;
2393                 case CMD_RQLATER:
2394                         /*
2395                          * Handle initial and subsequent loop down cases
2396                          */
2397                         if (FCPARAM(isp)->loop_seen_once == 0) {
2398                                 lim = isp_quickboot_time;
2399                         } else {
2400                                 lim = isp->isp_osinfo.loop_down_limit;
2401                         }
2402                         if (isp->isp_osinfo.loop_down_time >= lim) {
2403                                 isp_prt(isp, ISP_LOGDEBUG0,
2404                                     "%d.%d downtime (%d) > lim (%d)",
2405                                     XS_TGT(ccb), XS_LUN(ccb),
2406                                     isp->isp_osinfo.loop_down_time, lim);
2407                                 ccb->ccb_h.status =
2408                                     CAM_SEL_TIMEOUT|CAM_DEV_QFRZN;
2409                                 xpt_freeze_devq(ccb->ccb_h.path, 1);
2410                                 isp_free_pcmd(isp, ccb);
2411                                 xpt_done(ccb);
2412                                 break;
2413                         }
2414                         isp_prt(isp, ISP_LOGDEBUG0,
2415                             "%d.%d retry later", XS_TGT(ccb), XS_LUN(ccb));
2416                         /*
2417                          * Otherwise, retry in a while.
2418                          */
2419                         cam_freeze_devq(ccb->ccb_h.path);
2420                         cam_release_devq(ccb->ccb_h.path,
2421                             RELSIM_RELEASE_AFTER_TIMEOUT, 0, 1000, 0);
2422                         XS_SETERR(ccb, CAM_REQUEUE_REQ);
2423                         isp_free_pcmd(isp, ccb);
2424                         xpt_done(ccb);
2425                         break;
2426                 case CMD_EAGAIN:
2427                         XS_SETERR(ccb, CAM_REQUEUE_REQ);
2428                         isp_free_pcmd(isp, ccb);
2429                         xpt_done(ccb);
2430                         break;
2431                 case CMD_COMPLETE:
2432                         isp_done((struct ccb_scsiio *) ccb);
2433                         break;
2434                 default:
2435                         isp_prt(isp, ISP_LOGERR,
2436                             "What's this? 0x%x at %d in file %s",
2437                             error, __LINE__, __FILE__);
2438                         XS_SETERR(ccb, CAM_REQ_CMP_ERR);
2439                         isp_free_pcmd(isp, ccb);
2440                         xpt_done(ccb);
2441                 }
2442                 break;
2443
2444 #ifdef  ISP_TARGET_MODE
2445         case XPT_EN_LUN:                /* Enable LUN as a target */
2446         {
2447                 int seq, i;
2448                 seq = isp_en_lun(isp, ccb);
2449                 if (seq < 0) {
2450                         xpt_done(ccb);
2451                         break;
2452                 }
2453                 for (i = 0; isp->isp_osinfo.leact[seq] && i < 30 * 1000; i++) {
2454                         uint32_t isr;
2455                         uint16_t sema, mbox;
2456                         if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
2457                                 isp_intr(isp, isr, sema, mbox);
2458                         }
2459                         DELAY(1000);
2460                 }
2461                 break;
2462         }
2463         case XPT_NOTIFY_ACK:            /* recycle notify ack */
2464         case XPT_IMMED_NOTIFY:          /* Add Immediate Notify Resource */
2465         case XPT_ACCEPT_TARGET_IO:      /* Add Accept Target IO Resource */
2466         {
2467                 tstate_t *tptr =
2468                     get_lun_statep(isp, XS_CHANNEL(ccb), ccb->ccb_h.target_lun);
2469                 if (tptr == NULL) {
2470                         ccb->ccb_h.status = CAM_LUN_INVALID;
2471                         xpt_done(ccb);
2472                         break;
2473                 }
2474                 ccb->ccb_h.sim_priv.entries[0].field = 0;
2475                 ccb->ccb_h.sim_priv.entries[1].ptr = isp;
2476                 ccb->ccb_h.flags = 0;
2477
2478                 if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
2479                         /*
2480                          * Note that the command itself may not be done-
2481                          * it may not even have had the first CTIO sent.
2482                          */
2483                         tptr->atio_count++;
2484                         isp_prt(isp, ISP_LOGTDEBUG0,
2485                             "Put FREE ATIO, lun %d, count now %d",
2486                             ccb->ccb_h.target_lun, tptr->atio_count);
2487                         SLIST_INSERT_HEAD(&tptr->atios, &ccb->ccb_h,
2488                             sim_links.sle);
2489                 } else if (ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
2490                         tptr->inot_count++;
2491                         isp_prt(isp, ISP_LOGTDEBUG0,
2492                             "Put FREE INOT, lun %d, count now %d",
2493                             ccb->ccb_h.target_lun, tptr->inot_count);
2494                         SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h,
2495                             sim_links.sle);
2496                 } else {
2497                         isp_prt(isp, ISP_LOGWARN, "Got Notify ACK");;
2498                 }
2499                 rls_lun_statep(isp, tptr);
2500                 ccb->ccb_h.status = CAM_REQ_INPROG;
2501                 break;
2502         }
2503         case XPT_CONT_TARGET_IO:
2504         {
2505                 isp_target_start_ctio(isp, ccb);
2506                 break;
2507         }
2508 #endif
2509         case XPT_RESET_DEV:             /* BDR the specified SCSI device */
2510
2511                 bus = cam_sim_bus(xpt_path_sim(ccb->ccb_h.path));
2512                 tgt = ccb->ccb_h.target_id;
2513                 tgt |= (bus << 16);
2514
2515                 error = isp_control(isp, ISPCTL_RESET_DEV, &tgt);
2516                 if (error) {
2517                         ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2518                 } else {
2519                         ccb->ccb_h.status = CAM_REQ_CMP;
2520                 }
2521                 xpt_done(ccb);
2522                 break;
2523         case XPT_ABORT:                 /* Abort the specified CCB */
2524         {
2525                 union ccb *accb = ccb->cab.abort_ccb;
2526                 switch (accb->ccb_h.func_code) {
2527 #ifdef  ISP_TARGET_MODE
2528                 case XPT_ACCEPT_TARGET_IO:
2529                 case XPT_IMMED_NOTIFY:
2530                         ccb->ccb_h.status = isp_abort_tgt_ccb(isp, ccb);
2531                         break;
2532                 case XPT_CONT_TARGET_IO:
2533                         isp_prt(isp, ISP_LOGERR, "cannot abort CTIOs yet");
2534                         ccb->ccb_h.status = CAM_UA_ABORT;
2535                         break;
2536 #endif
2537                 case XPT_SCSI_IO:
2538                         error = isp_control(isp, ISPCTL_ABORT_CMD, ccb);
2539                         if (error) {
2540                                 ccb->ccb_h.status = CAM_UA_ABORT;
2541                         } else {
2542                                 ccb->ccb_h.status = CAM_REQ_CMP;
2543                         }
2544                         break;
2545                 default:
2546                         ccb->ccb_h.status = CAM_REQ_INVALID;
2547                         break;
2548                 }
2549                 xpt_done(ccb);
2550                 break;
2551         }
2552 #ifdef  CAM_NEW_TRAN_CODE
2553 #define IS_CURRENT_SETTINGS(c)  (c->type == CTS_TYPE_CURRENT_SETTINGS)
2554 #else
2555 #define IS_CURRENT_SETTINGS(c)  (c->flags & CCB_TRANS_CURRENT_SETTINGS)
2556 #endif
2557         case XPT_SET_TRAN_SETTINGS:     /* Nexus Settings */
2558                 cts = &ccb->cts;
2559                 if (!IS_CURRENT_SETTINGS(cts)) {
2560                         ccb->ccb_h.status = CAM_REQ_INVALID;
2561                         xpt_done(ccb);
2562                         break;
2563                 }
2564                 tgt = cts->ccb_h.target_id;
2565                 if (IS_SCSI(isp)) {
2566 #ifndef CAM_NEW_TRAN_CODE
2567                         sdparam *sdp = isp->isp_param;
2568                         uint16_t *dptr;
2569
2570                         bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
2571
2572                         sdp += bus;
2573                         /*
2574                          * We always update (internally) from goal_flags
2575                          * so any request to change settings just gets
2576                          * vectored to that location.
2577                          */
2578                         dptr = &sdp->isp_devparam[tgt].goal_flags;
2579
2580                         /*
2581                          * Note that these operations affect the
2582                          * the goal flags (goal_flags)- not
2583                          * the current state flags. Then we mark
2584                          * things so that the next operation to
2585                          * this HBA will cause the update to occur.
2586                          */
2587                         if (cts->valid & CCB_TRANS_DISC_VALID) {
2588                                 if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) {
2589                                         *dptr |= DPARM_DISC;
2590                                 } else {
2591                                         *dptr &= ~DPARM_DISC;
2592                                 }
2593                         }
2594                         if (cts->valid & CCB_TRANS_TQ_VALID) {
2595                                 if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) {
2596                                         *dptr |= DPARM_TQING;
2597                                 } else {
2598                                         *dptr &= ~DPARM_TQING;
2599                                 }
2600                         }
2601                         if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) {
2602                                 switch (cts->bus_width) {
2603                                 case MSG_EXT_WDTR_BUS_16_BIT:
2604                                         *dptr |= DPARM_WIDE;
2605                                         break;
2606                                 default:
2607                                         *dptr &= ~DPARM_WIDE;
2608                                 }
2609                         }
2610                         /*
2611                          * Any SYNC RATE of nonzero and SYNC_OFFSET
2612                          * of nonzero will cause us to go to the
2613                          * selected (from NVRAM) maximum value for
2614                          * this device. At a later point, we'll
2615                          * allow finer control.
2616                          */
2617                         if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) &&
2618                             (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) &&
2619                             (cts->sync_offset > 0)) {
2620                                 *dptr |= DPARM_SYNC;
2621                         } else {
2622                                 *dptr &= ~DPARM_SYNC;
2623                         }
2624                         *dptr |= DPARM_SAFE_DFLT;
2625 #else
2626                         struct ccb_trans_settings_scsi *scsi =
2627                             &cts->proto_specific.scsi;
2628                         struct ccb_trans_settings_spi *spi =
2629                             &cts->xport_specific.spi;
2630                         sdparam *sdp = isp->isp_param;
2631                         uint16_t *dptr;
2632
2633                         if (spi->valid == 0 && scsi->valid == 0) {
2634                                 ccb->ccb_h.status = CAM_REQ_CMP;
2635                                 xpt_done(ccb);
2636                                 break;
2637                         }
2638                                 
2639                         bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
2640                         sdp += bus;
2641                         /*
2642                          * We always update (internally) from goal_flags
2643                          * so any request to change settings just gets
2644                          * vectored to that location.
2645                          */
2646                         dptr = &sdp->isp_devparam[tgt].goal_flags;
2647
2648                         if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
2649                                 if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
2650                                         *dptr |= DPARM_DISC;
2651                                 else
2652                                         *dptr &= ~DPARM_DISC;
2653                         }
2654
2655                         if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
2656                                 if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
2657                                         *dptr |= DPARM_TQING;
2658                                 else
2659                                         *dptr &= ~DPARM_TQING;
2660                         }
2661
2662                         if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
2663                                 if (spi->bus_width == MSG_EXT_WDTR_BUS_16_BIT)
2664                                         *dptr |= DPARM_WIDE;
2665                                 else
2666                                         *dptr &= ~DPARM_WIDE;
2667                         }
2668
2669                         /*
2670                          * XXX: FIX ME
2671                          */
2672                         if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) &&
2673                             (spi->valid & CTS_SPI_VALID_SYNC_RATE) &&
2674                             (spi->sync_period && spi->sync_offset)) {
2675                                 *dptr |= DPARM_SYNC;
2676                                 /*
2677                                  * XXX: CHECK FOR LEGALITY
2678                                  */
2679                                 sdp->isp_devparam[tgt].goal_period =
2680                                     spi->sync_period;
2681                                 sdp->isp_devparam[tgt].goal_offset =
2682                                     spi->sync_offset;
2683                         } else {
2684                                 *dptr &= ~DPARM_SYNC;
2685                         }
2686 #endif
2687                         isp_prt(isp, ISP_LOGDEBUG0,
2688                             "SET (%d.%d.%d) to flags %x off %x per %x",
2689                             bus, tgt, cts->ccb_h.target_lun,
2690                             sdp->isp_devparam[tgt].goal_flags,
2691                             sdp->isp_devparam[tgt].goal_offset,
2692                             sdp->isp_devparam[tgt].goal_period);
2693                         sdp->isp_devparam[tgt].dev_update = 1;
2694                         isp->isp_update |= (1 << bus);
2695                 }
2696                 ccb->ccb_h.status = CAM_REQ_CMP;
2697                 xpt_done(ccb);
2698                 break;
2699         case XPT_GET_TRAN_SETTINGS:
2700                 cts = &ccb->cts;
2701                 tgt = cts->ccb_h.target_id;
2702                 if (IS_FC(isp)) {
2703 #ifndef CAM_NEW_TRAN_CODE
2704                         /*
2705                          * a lot of normal SCSI things don't make sense.
2706                          */
2707                         cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
2708                         cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
2709                         /*
2710                          * How do you measure the width of a high
2711                          * speed serial bus? Well, in bytes.
2712                          *
2713                          * Offset and period make no sense, though, so we set
2714                          * (above) a 'base' transfer speed to be gigabit.
2715                          */
2716                         cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
2717 #else
2718                         fcparam *fcp = isp->isp_param;
2719                         struct ccb_trans_settings_scsi *scsi =
2720                             &cts->proto_specific.scsi;
2721                         struct ccb_trans_settings_fc *fc =
2722                             &cts->xport_specific.fc;
2723
2724                         cts->protocol = PROTO_SCSI;
2725                         cts->protocol_version = SCSI_REV_2;
2726                         cts->transport = XPORT_FC;
2727                         cts->transport_version = 0;
2728
2729                         scsi->valid = CTS_SCSI_VALID_TQ;
2730                         scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
2731                         fc->valid = CTS_FC_VALID_SPEED;
2732                         fc->bitrate = 100000;
2733                         if (fcp->isp_gbspeed == 4 || fcp->isp_gbspeed == 2)
2734                                 fc->bitrate *= fcp->isp_gbspeed;
2735                         if (tgt > 0 && tgt < MAX_FC_TARG) {
2736                                 fcportdb_t *lp = &fcp->portdb[tgt];
2737                                 fc->wwnn = lp->node_wwn;
2738                                 fc->wwpn = lp->port_wwn;
2739                                 fc->port = lp->portid;
2740                                 fc->valid |= CTS_FC_VALID_WWNN |
2741                                     CTS_FC_VALID_WWPN | CTS_FC_VALID_PORT;
2742                         }
2743 #endif
2744                 } else {
2745 #ifdef  CAM_NEW_TRAN_CODE
2746                         struct ccb_trans_settings_scsi *scsi =
2747                             &cts->proto_specific.scsi;
2748                         struct ccb_trans_settings_spi *spi =
2749                             &cts->xport_specific.spi;
2750 #endif
2751                         sdparam *sdp = isp->isp_param;
2752                         int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
2753                         uint16_t dval, pval, oval;
2754
2755                         sdp += bus;
2756
2757                         if (IS_CURRENT_SETTINGS(cts)) {
2758                                 sdp->isp_devparam[tgt].dev_refresh = 1;
2759                                 isp->isp_update |= (1 << bus);
2760                                 (void) isp_control(isp, ISPCTL_UPDATE_PARAMS,
2761                                     NULL);
2762                                 dval = sdp->isp_devparam[tgt].actv_flags;
2763                                 oval = sdp->isp_devparam[tgt].actv_offset;
2764                                 pval = sdp->isp_devparam[tgt].actv_period;
2765                         } else {
2766                                 dval = sdp->isp_devparam[tgt].nvrm_flags;
2767                                 oval = sdp->isp_devparam[tgt].nvrm_offset;
2768                                 pval = sdp->isp_devparam[tgt].nvrm_period;
2769                         }
2770
2771 #ifndef CAM_NEW_TRAN_CODE
2772                         cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
2773
2774                         if (dval & DPARM_DISC) {
2775                                 cts->flags |= CCB_TRANS_DISC_ENB;
2776                         }
2777                         if (dval & DPARM_TQING) {
2778                                 cts->flags |= CCB_TRANS_TAG_ENB;
2779                         }
2780                         if (dval & DPARM_WIDE) {
2781                                 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
2782                         } else {
2783                                 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
2784                         }
2785                         cts->valid = CCB_TRANS_BUS_WIDTH_VALID |
2786                             CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
2787
2788                         if ((dval & DPARM_SYNC) && oval != 0) {
2789                                 cts->sync_period = pval;
2790                                 cts->sync_offset = oval;
2791                                 cts->valid |=
2792                                     CCB_TRANS_SYNC_RATE_VALID |
2793                                     CCB_TRANS_SYNC_OFFSET_VALID;
2794                         }
2795 #else
2796                         cts->protocol = PROTO_SCSI;
2797                         cts->protocol_version = SCSI_REV_2;
2798                         cts->transport = XPORT_SPI;
2799                         cts->transport_version = 2;
2800
2801                         spi->valid = 0;
2802                         scsi->valid = 0;
2803                         spi->flags = 0;
2804                         scsi->flags = 0;
2805                         if (dval & DPARM_DISC) {
2806                                 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
2807                         }
2808                         if ((dval & DPARM_SYNC) && oval && pval) {
2809                                 spi->sync_offset = oval;
2810                                 spi->sync_period = pval;
2811                         } else {
2812                                 spi->sync_offset = 0;
2813                                 spi->sync_period = 0;
2814                         }
2815                         spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
2816                         spi->valid |= CTS_SPI_VALID_SYNC_RATE;
2817                         spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
2818                         if (dval & DPARM_WIDE) {
2819                                 spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
2820                         } else {
2821                                 spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
2822                         }
2823                         if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
2824                                 scsi->valid = CTS_SCSI_VALID_TQ;
2825                                 if (dval & DPARM_TQING) {
2826                                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
2827                                 }
2828                                 spi->valid |= CTS_SPI_VALID_DISC;
2829                         }
2830 #endif
2831                         isp_prt(isp, ISP_LOGDEBUG0,
2832                             "GET %s (%d.%d.%d) to flags %x off %x per %x",
2833                             IS_CURRENT_SETTINGS(cts)? "ACTIVE" : "NVRAM",
2834                             bus, tgt, cts->ccb_h.target_lun, dval, oval, pval);
2835                 }
2836                 ccb->ccb_h.status = CAM_REQ_CMP;
2837                 xpt_done(ccb);
2838                 break;
2839
2840         case XPT_CALC_GEOMETRY:
2841 #if __FreeBSD_version < 500000  
2842         {
2843                 struct ccb_calc_geometry *ccg;
2844                 u_int32_t secs_per_cylinder;
2845                 u_int32_t size_mb;
2846
2847                 ccg = &ccb->ccg;
2848                 if (ccg->block_size == 0) {
2849                         ccb->ccb_h.status = CAM_REQ_INVALID;
2850                         xpt_done(ccb);
2851                         break;
2852                 }
2853                 size_mb = ccg->volume_size /((1024L * 1024L) / ccg->block_size);
2854                 if (size_mb > 1024) {
2855                         ccg->heads = 255;
2856                         ccg->secs_per_track = 63;
2857                 } else {
2858                         ccg->heads = 64;
2859                         ccg->secs_per_track = 32;
2860                 }
2861                 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
2862                 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
2863                 ccb->ccb_h.status = CAM_REQ_CMP;
2864                 xpt_done(ccb);
2865                 break;
2866         }
2867 #else
2868         {
2869                 cam_calc_geometry(&ccb->ccg, /*extended*/1);
2870                 xpt_done(ccb);
2871                 break;
2872         }
2873 #endif
2874         case XPT_RESET_BUS:             /* Reset the specified bus */
2875                 bus = cam_sim_bus(sim);
2876                 error = isp_control(isp, ISPCTL_RESET_BUS, &bus);
2877                 if (error)
2878                         ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2879                 else {
2880                         if (bootverbose) {
2881                                 xpt_print(ccb->ccb_h.path, "reset bus\n");
2882                         }
2883                         if (cam_sim_bus(sim) && isp->isp_path2 != NULL)
2884                                 xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
2885                         else if (isp->isp_path != NULL)
2886                                 xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
2887                         ccb->ccb_h.status = CAM_REQ_CMP;
2888                 }
2889                 xpt_done(ccb);
2890                 break;
2891
2892         case XPT_TERM_IO:               /* Terminate the I/O process */
2893                 ccb->ccb_h.status = CAM_REQ_INVALID;
2894                 xpt_done(ccb);
2895                 break;
2896
2897         case XPT_PATH_INQ:              /* Path routing inquiry */
2898         {
2899                 struct ccb_pathinq *cpi = &ccb->cpi;
2900
2901                 cpi->version_num = 1;
2902 #ifdef  ISP_TARGET_MODE
2903                 cpi->target_sprt = PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO;
2904 #else
2905                 cpi->target_sprt = 0;
2906 #endif
2907                 cpi->hba_eng_cnt = 0;
2908                 cpi->max_target = ISP_MAX_TARGETS(isp) - 1;
2909                 cpi->max_lun = ISP_MAX_LUNS(isp) - 1;
2910                 cpi->bus_id = cam_sim_bus(sim);
2911                 if (IS_FC(isp)) {
2912                         cpi->hba_misc = PIM_NOBUSRESET;
2913                         /*
2914                          * Because our loop ID can shift from time to time,
2915                          * make our initiator ID out of range of our bus.
2916                          */
2917                         cpi->initiator_id = cpi->max_target + 1;
2918
2919                         /*
2920                          * Set base transfer capabilities for Fibre Channel.
2921                          * Technically not correct because we don't know
2922                          * what media we're running on top of- but we'll
2923                          * look good if we always say 100MB/s.
2924                          */
2925                         cpi->base_transfer_speed = 100000;
2926                         if (FCPARAM(isp)->isp_gbspeed == 4 ||
2927                             FCPARAM(isp)->isp_gbspeed == 2)
2928                                 cpi->base_transfer_speed *=
2929                                     FCPARAM(isp)->isp_gbspeed;
2930                         cpi->hba_inquiry = PI_TAG_ABLE;
2931 #ifdef  CAM_NEW_TRAN_CODE
2932                         cpi->transport = XPORT_FC;
2933                         cpi->transport_version = 0;
2934 #endif
2935                 } else {
2936                         sdparam *sdp = isp->isp_param;
2937                         sdp += cam_sim_bus(xpt_path_sim(cpi->ccb_h.path));
2938                         cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
2939                         cpi->hba_misc = 0;
2940                         cpi->initiator_id = sdp->isp_initiator_id;
2941                         cpi->base_transfer_speed = 3300;
2942 #ifdef  CAM_NEW_TRAN_CODE
2943                         cpi->transport = XPORT_SPI;
2944                         cpi->transport_version = 2;
2945 #endif
2946                 }
2947 #ifdef  CAM_NEW_TRAN_CODE
2948                 cpi->protocol = PROTO_SCSI;
2949                 cpi->protocol_version = SCSI_REV_2;
2950 #endif
2951                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2952                 strncpy(cpi->hba_vid, "Qlogic", HBA_IDLEN);
2953                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2954                 cpi->unit_number = cam_sim_unit(sim);
2955                 cpi->ccb_h.status = CAM_REQ_CMP;
2956                 xpt_done(ccb);
2957                 break;
2958         }
2959         default:
2960                 ccb->ccb_h.status = CAM_REQ_INVALID;
2961                 xpt_done(ccb);
2962                 break;
2963         }
2964 }
2965
2966 #define ISPDDB  (CAM_DEBUG_INFO|CAM_DEBUG_TRACE|CAM_DEBUG_CDB)
2967
2968 void
2969 isp_done(struct ccb_scsiio *sccb)
2970 {
2971         ispsoftc_t *isp = XS_ISP(sccb);
2972
2973         if (XS_NOERR(sccb))
2974                 XS_SETERR(sccb, CAM_REQ_CMP);
2975
2976         if ((sccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP &&
2977             (sccb->scsi_status != SCSI_STATUS_OK)) {
2978                 sccb->ccb_h.status &= ~CAM_STATUS_MASK;
2979                 if ((sccb->scsi_status == SCSI_STATUS_CHECK_COND) && 
2980                     (sccb->ccb_h.status & CAM_AUTOSNS_VALID) == 0) {
2981                         sccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
2982                 } else {
2983                         sccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
2984                 }
2985         }
2986
2987         sccb->ccb_h.status &= ~CAM_SIM_QUEUED;
2988         if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2989                 isp_prt(isp, ISP_LOGDEBUG0,
2990                     "target %d lun %d CAM status 0x%x SCSI status 0x%x",
2991                     XS_TGT(sccb), XS_LUN(sccb), sccb->ccb_h.status,
2992                     sccb->scsi_status);
2993                 if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2994                         sccb->ccb_h.status |= CAM_DEV_QFRZN;
2995                         xpt_freeze_devq(sccb->ccb_h.path, 1);
2996                 }
2997         }
2998
2999         if ((CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB)) &&
3000             (sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3001                 xpt_print(sccb->ccb_h.path,
3002                     "cam completion status 0x%x\n", sccb->ccb_h.status);
3003         }
3004
3005         XS_CMD_S_DONE(sccb);
3006         if (XS_CMD_WDOG_P(sccb) == 0) {
3007                 untimeout(isp_watchdog, sccb, sccb->ccb_h.timeout_ch);
3008                 if (XS_CMD_GRACE_P(sccb)) {
3009                         isp_prt(isp, ISP_LOGDEBUG2,
3010                             "finished command on borrowed time");
3011                 }
3012                 XS_CMD_S_CLEAR(sccb);
3013                 isp_free_pcmd(isp, (union ccb *) sccb);
3014                 xpt_done((union ccb *) sccb);
3015         }
3016 }
3017
3018 int
3019 isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
3020 {
3021         int bus, rv = 0;
3022         static const char prom[] =
3023             "PortID 0x%06x handle 0x%x role %s %s\n"
3024             "      WWNN 0x%08x%08x WWPN 0x%08x%08x";
3025         static const char prom2[] =
3026             "PortID 0x%06x handle 0x%x role %s %s tgt %u\n"
3027             "      WWNN 0x%08x%08x WWPN 0x%08x%08x";
3028         char *msg = NULL;
3029         target_id_t tgt;
3030         fcportdb_t *lp;
3031         struct cam_path *tmppath;
3032
3033         switch (cmd) {
3034         case ISPASYNC_NEW_TGT_PARAMS:
3035         {
3036 #ifdef  CAM_NEW_TRAN_CODE
3037                 struct ccb_trans_settings_scsi *scsi;
3038                 struct ccb_trans_settings_spi *spi;
3039 #endif
3040                 int flags, tgt;
3041                 sdparam *sdp = isp->isp_param;
3042                 struct ccb_trans_settings cts;
3043
3044                 memset(&cts, 0, sizeof (struct ccb_trans_settings));
3045
3046                 tgt = *((int *)arg);
3047                 bus = (tgt >> 16) & 0xffff;
3048                 tgt &= 0xffff;
3049                 sdp += bus;
3050                 if (xpt_create_path(&tmppath, NULL,
3051                     cam_sim_path(bus? isp->isp_sim2 : isp->isp_sim),
3052                     tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
3053                         isp_prt(isp, ISP_LOGWARN,
3054                             "isp_async cannot make temp path for %d.%d",
3055                             tgt, bus);
3056                         rv = -1;
3057                         break;
3058                 }
3059                 flags = sdp->isp_devparam[tgt].actv_flags;
3060 #ifdef  CAM_NEW_TRAN_CODE
3061                 cts.type = CTS_TYPE_CURRENT_SETTINGS;
3062                 cts.protocol = PROTO_SCSI;
3063                 cts.transport = XPORT_SPI;
3064
3065                 scsi = &cts.proto_specific.scsi;
3066                 spi = &cts.xport_specific.spi;
3067
3068                 if (flags & DPARM_TQING) {
3069                         scsi->valid |= CTS_SCSI_VALID_TQ;
3070                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
3071                 }
3072
3073                 if (flags & DPARM_DISC) {
3074                         spi->valid |= CTS_SPI_VALID_DISC;
3075                         spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
3076                 }
3077                 spi->flags |= CTS_SPI_VALID_BUS_WIDTH;
3078                 if (flags & DPARM_WIDE) {
3079                         spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
3080                 } else {
3081                         spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
3082                 }
3083                 if (flags & DPARM_SYNC) {
3084                         spi->valid |= CTS_SPI_VALID_SYNC_RATE;
3085                         spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
3086                         spi->sync_period = sdp->isp_devparam[tgt].actv_period;
3087                         spi->sync_offset = sdp->isp_devparam[tgt].actv_offset;
3088                 }
3089 #else
3090                 cts.flags = CCB_TRANS_CURRENT_SETTINGS;
3091                 cts.valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
3092                 if (flags & DPARM_DISC) {
3093                         cts.flags |= CCB_TRANS_DISC_ENB;
3094                 }
3095                 if (flags & DPARM_TQING) {
3096                         cts.flags |= CCB_TRANS_TAG_ENB;
3097                 }
3098                 cts.valid |= CCB_TRANS_BUS_WIDTH_VALID;
3099                 cts.bus_width = (flags & DPARM_WIDE)?
3100                     MSG_EXT_WDTR_BUS_8_BIT : MSG_EXT_WDTR_BUS_16_BIT;
3101                 cts.sync_period = sdp->isp_devparam[tgt].actv_period;
3102                 cts.sync_offset = sdp->isp_devparam[tgt].actv_offset;
3103                 if (flags & DPARM_SYNC) {
3104                         cts.valid |=
3105                             CCB_TRANS_SYNC_RATE_VALID |
3106                             CCB_TRANS_SYNC_OFFSET_VALID;
3107                 }
3108 #endif
3109                 isp_prt(isp, ISP_LOGDEBUG2,
3110                     "NEW_TGT_PARAMS bus %d tgt %d period %x offset %x flags %x",
3111                     bus, tgt, sdp->isp_devparam[tgt].actv_period,
3112                     sdp->isp_devparam[tgt].actv_offset, flags);
3113                 xpt_setup_ccb(&cts.ccb_h, tmppath, 1);
3114                 xpt_async(AC_TRANSFER_NEG, tmppath, &cts);
3115                 xpt_free_path(tmppath);
3116                 break;
3117         }
3118         case ISPASYNC_BUS_RESET:
3119                 bus = *((int *)arg);
3120                 isp_prt(isp, ISP_LOGINFO, "SCSI bus reset on bus %d detected",
3121                     bus);
3122                 if (bus > 0 && isp->isp_path2) {
3123                         xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
3124                 } else if (isp->isp_path) {
3125                         xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
3126                 }
3127                 break;
3128         case ISPASYNC_LIP:
3129                 if (msg == NULL) {
3130                         msg = "LIP Received";
3131                 }
3132                 /* FALLTHROUGH */
3133         case ISPASYNC_LOOP_RESET:
3134                 if (msg == NULL) {
3135                         msg = "LOOP Reset";
3136                 }
3137                 /* FALLTHROUGH */
3138         case ISPASYNC_LOOP_DOWN:
3139                 if (msg == NULL) {
3140                         msg = "LOOP Down";
3141                 }
3142                 if (isp->isp_path) {
3143                         isp_freeze_loopdown(isp, msg);
3144                 }
3145                 if (isp->isp_osinfo.ldt_running == 0) {
3146                         isp->isp_osinfo.ldt_running = 1;
3147                         callout_reset(&isp->isp_osinfo.ldt,
3148                             isp->isp_osinfo.loop_down_limit * hz, isp_ldt, isp);
3149                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3150                            "starting Loop Down Timer");
3151                 }
3152                 isp_prt(isp, ISP_LOGINFO, msg);
3153                 break;
3154         case ISPASYNC_LOOP_UP:
3155                 /*
3156                  * Now we just note that Loop has come up. We don't
3157                  * actually do anything because we're waiting for a
3158                  * Change Notify before activating the FC cleanup
3159                  * thread to look at the state of the loop again.
3160                  */
3161                 isp_prt(isp, ISP_LOGINFO, "Loop UP");
3162                 break;
3163         case ISPASYNC_DEV_ARRIVED:
3164                 lp = arg;
3165                 lp->reserved = 0;
3166                 if ((isp->isp_role & ISP_ROLE_INITIATOR) &&
3167                     (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) {
3168                         int dbidx = lp - FCPARAM(isp)->portdb;
3169                         int i;
3170
3171                         for (i = 0; i < MAX_FC_TARG; i++) {
3172                                 if (i >= FL_ID && i <= SNS_ID) {
3173                                         continue;
3174                                 }
3175                                 if (FCPARAM(isp)->isp_ini_map[i] == 0) {
3176                                         break;
3177                                 }
3178                         }
3179                         if (i < MAX_FC_TARG) {
3180                                 FCPARAM(isp)->isp_ini_map[i] = dbidx + 1;
3181                                 lp->ini_map_idx = i + 1;
3182                         } else {
3183                                 isp_prt(isp, ISP_LOGWARN, "out of target ids");
3184                                 isp_dump_portdb(isp);
3185                         }
3186                 }
3187                 if (lp->ini_map_idx) {
3188                         tgt = lp->ini_map_idx - 1;
3189                         isp_prt(isp, ISP_LOGCONFIG, prom2,
3190                             lp->portid, lp->handle,
3191                             roles[lp->roles], "arrived at", tgt,
3192                             (uint32_t) (lp->node_wwn >> 32),
3193                             (uint32_t) lp->node_wwn,
3194                             (uint32_t) (lp->port_wwn >> 32),
3195                             (uint32_t) lp->port_wwn);
3196                         isp_make_here(isp, tgt);
3197                 } else {
3198                         isp_prt(isp, ISP_LOGCONFIG, prom,
3199                             lp->portid, lp->handle,
3200                             roles[lp->roles], "arrived",
3201                             (uint32_t) (lp->node_wwn >> 32),
3202                             (uint32_t) lp->node_wwn,
3203                             (uint32_t) (lp->port_wwn >> 32),
3204                             (uint32_t) lp->port_wwn);
3205                 }
3206                 break;
3207         case ISPASYNC_DEV_CHANGED:
3208                 lp = arg;
3209                 if (isp_change_is_bad) {
3210                         lp->state = FC_PORTDB_STATE_NIL;
3211                         if (lp->ini_map_idx) {
3212                                 tgt = lp->ini_map_idx - 1;
3213                                 FCPARAM(isp)->isp_ini_map[tgt] = 0;
3214                                 lp->ini_map_idx = 0;
3215                                 isp_prt(isp, ISP_LOGCONFIG, prom3,
3216                                     lp->portid, tgt, "change is bad");
3217                                 isp_make_gone(isp, tgt);
3218                         } else {
3219                                 isp_prt(isp, ISP_LOGCONFIG, prom,
3220                                     lp->portid, lp->handle,
3221                                     roles[lp->roles],
3222                                     "changed and departed",
3223                                     (uint32_t) (lp->node_wwn >> 32),
3224                                     (uint32_t) lp->node_wwn,
3225                                     (uint32_t) (lp->port_wwn >> 32),
3226                                     (uint32_t) lp->port_wwn);
3227                         }
3228                 } else {
3229                         lp->portid = lp->new_portid;
3230                         lp->roles = lp->new_roles;
3231                         if (lp->ini_map_idx) {
3232                                 int t = lp->ini_map_idx - 1;
3233                                 FCPARAM(isp)->isp_ini_map[t] =
3234                                     (lp - FCPARAM(isp)->portdb) + 1;
3235                                 tgt = lp->ini_map_idx - 1;
3236                                 isp_prt(isp, ISP_LOGCONFIG, prom2,
3237                                     lp->portid, lp->handle,
3238                                     roles[lp->roles], "changed at", tgt,
3239                                     (uint32_t) (lp->node_wwn >> 32),
3240                                     (uint32_t) lp->node_wwn,
3241                                     (uint32_t) (lp->port_wwn >> 32),
3242                                     (uint32_t) lp->port_wwn);
3243                         } else {
3244                                 isp_prt(isp, ISP_LOGCONFIG, prom,
3245                                     lp->portid, lp->handle,
3246                                     roles[lp->roles], "changed",
3247                                     (uint32_t) (lp->node_wwn >> 32),
3248                                     (uint32_t) lp->node_wwn,
3249                                     (uint32_t) (lp->port_wwn >> 32),
3250                                     (uint32_t) lp->port_wwn);
3251                         }
3252                 }
3253                 break;
3254         case ISPASYNC_DEV_STAYED:
3255                 lp = arg;
3256                 if (lp->ini_map_idx) {
3257                         tgt = lp->ini_map_idx - 1;
3258                         isp_prt(isp, ISP_LOGCONFIG, prom2,
3259                             lp->portid, lp->handle,
3260                             roles[lp->roles], "stayed at", tgt,
3261                             (uint32_t) (lp->node_wwn >> 32),
3262                             (uint32_t) lp->node_wwn,
3263                             (uint32_t) (lp->port_wwn >> 32),
3264                             (uint32_t) lp->port_wwn);
3265                 } else {
3266                         isp_prt(isp, ISP_LOGCONFIG, prom,
3267                             lp->portid, lp->handle,
3268                             roles[lp->roles], "stayed",
3269                             (uint32_t) (lp->node_wwn >> 32),
3270                             (uint32_t) lp->node_wwn,
3271                             (uint32_t) (lp->port_wwn >> 32),
3272                             (uint32_t) lp->port_wwn);
3273                 }
3274                 break;
3275         case ISPASYNC_DEV_GONE:
3276                 lp = arg;
3277                 /*
3278                  * If this has a virtual target and we haven't marked it
3279                  * that we're going to have isp_gdt tell the OS it's gone,
3280                  * set the isp_gdt timer running on it.
3281                  *
3282                  * If it isn't marked that isp_gdt is going to get rid of it,
3283                  * announce that it's gone.
3284                  */
3285                 if (lp->ini_map_idx && lp->reserved == 0) {
3286                         lp->reserved = 1;
3287                         lp->new_reserved = isp->isp_osinfo.gone_device_time;
3288                         lp->state = FC_PORTDB_STATE_ZOMBIE;
3289                         if (isp->isp_osinfo.gdt_running == 0) {
3290                                 isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3291                                     "starting Gone Device Timer");
3292                                 isp->isp_osinfo.gdt_running = 1;
3293                                 callout_reset(&isp->isp_osinfo.gdt, hz,
3294                                     isp_gdt, isp);
3295                         }
3296                         tgt = lp->ini_map_idx - 1;
3297                         isp_prt(isp, ISP_LOGCONFIG, prom2,
3298                             lp->portid, lp->handle,
3299                             roles[lp->roles], "gone zombie at", tgt,
3300                             (uint32_t) (lp->node_wwn >> 32),
3301                             (uint32_t) lp->node_wwn,
3302                             (uint32_t) (lp->port_wwn >> 32),
3303                             (uint32_t) lp->port_wwn);
3304                 } else if (lp->reserved == 0) {
3305                         isp_prt(isp, ISP_LOGCONFIG, prom,
3306                             lp->portid, lp->handle,
3307                             roles[lp->roles], "departed",
3308                             (uint32_t) (lp->node_wwn >> 32),
3309                             (uint32_t) lp->node_wwn,
3310                             (uint32_t) (lp->port_wwn >> 32),
3311                             (uint32_t) lp->port_wwn);
3312                 }
3313                 break;
3314         case ISPASYNC_CHANGE_NOTIFY:
3315         {
3316                 char *msg;
3317                 if (arg == ISPASYNC_CHANGE_PDB) {
3318                         msg = "Port Database Changed";
3319                 } else if (arg == ISPASYNC_CHANGE_SNS) {
3320                         msg = "Name Server Database Changed";
3321                 } else {
3322                         msg = "Other Change Notify";
3323                 }
3324                 /*
3325                  * If the loop down timer is running, cancel it.
3326                  */
3327                 if (isp->isp_osinfo.ldt_running) {
3328                         isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
3329                            "Stopping Loop Down Timer");
3330                         isp->isp_osinfo.ldt_running = 0;
3331                         callout_stop(&isp->isp_osinfo.ldt);
3332                 }
3333                 isp_prt(isp, ISP_LOGINFO, msg);
3334                 isp_freeze_loopdown(isp, msg);
3335                 wakeup(ISP_KT_WCHAN(isp));
3336                 break;
3337         }
3338 #ifdef  ISP_TARGET_MODE
3339         case ISPASYNC_TARGET_NOTIFY:
3340         {
3341                 tmd_notify_t *nt = arg;
3342                 isp_prt(isp, ISP_LOGALL,
3343                     "target notify code 0x%x", nt->nt_ncode);
3344                 break;
3345         }
3346         case ISPASYNC_TARGET_ACTION:
3347                 switch (((isphdr_t *)arg)->rqs_entry_type) {
3348                 default:
3349                         isp_prt(isp, ISP_LOGWARN,
3350                            "event 0x%x for unhandled target action",
3351                             ((isphdr_t *)arg)->rqs_entry_type);
3352                         break;
3353                 case RQSTYPE_NOTIFY:
3354                         if (IS_SCSI(isp)) {
3355                                 rv = isp_handle_platform_notify_scsi(isp,
3356                                     (in_entry_t *) arg);
3357                         } else {
3358                                 rv = isp_handle_platform_notify_fc(isp,
3359                                     (in_fcentry_t *) arg);
3360                         }
3361                         break;
3362                 case RQSTYPE_ATIO:
3363                         rv = isp_handle_platform_atio(isp, (at_entry_t *) arg);
3364                         break;
3365                 case RQSTYPE_ATIO2:
3366                         rv = isp_handle_platform_atio2(isp, (at2_entry_t *)arg);
3367                         break;
3368                 case RQSTYPE_CTIO3:
3369                 case RQSTYPE_CTIO2:
3370                 case RQSTYPE_CTIO:
3371                         rv = isp_handle_platform_ctio(isp, arg);
3372                         break;
3373                 case RQSTYPE_ENABLE_LUN:
3374                 case RQSTYPE_MODIFY_LUN:
3375                         isp_ledone(isp, (lun_entry_t *) arg);
3376                         break;
3377                 }
3378                 break;
3379 #endif
3380         case ISPASYNC_FW_CRASH:
3381         {
3382                 uint16_t mbox1, mbox6;
3383                 mbox1 = ISP_READ(isp, OUTMAILBOX1);
3384                 if (IS_DUALBUS(isp)) { 
3385                         mbox6 = ISP_READ(isp, OUTMAILBOX6);
3386                 } else {
3387                         mbox6 = 0;
3388                 }
3389                 isp_prt(isp, ISP_LOGERR,
3390                     "Internal Firmware Error on bus %d @ RISC Address 0x%x",
3391                     mbox6, mbox1);
3392 #ifdef  ISP_FW_CRASH_DUMP
3393                 mbox1 = isp->isp_osinfo.mbox_sleep_ok;
3394                 isp->isp_osinfo.mbox_sleep_ok = 0;
3395                 if (IS_FC(isp)) {
3396                         FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
3397                         FCPARAM(isp)->isp_loopstate = LOOP_NIL;
3398                         isp_freeze_loopdown(isp, "f/w crash");
3399                         isp_fw_dump(isp);
3400                 }
3401                 isp_reinit(isp);
3402                 isp->isp_osinfo.mbox_sleep_ok = mbox1;
3403 #else
3404                 mbox1 = isp->isp_osinfo.mbox_sleep_ok;
3405                 isp->isp_osinfo.mbox_sleep_ok = 0;
3406                 isp_reinit(isp);
3407                 isp->isp_osinfo.mbox_sleep_ok = mbox1;
3408 #endif
3409                 isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
3410                 break;
3411         }
3412         case ISPASYNC_UNHANDLED_RESPONSE:
3413                 break;
3414         default:
3415                 isp_prt(isp, ISP_LOGERR, "unknown isp_async event %d", cmd);
3416                 break;
3417         }
3418         return (rv);
3419 }
3420
3421
3422 /*
3423  * Locks are held before coming here.
3424  */
3425 void
3426 isp_uninit(ispsoftc_t *isp)
3427 {
3428         if (IS_24XX(isp)) {
3429                 ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET);
3430         } else {
3431                 ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
3432         }
3433         ISP_DISABLE_INTS(isp);
3434 }
3435
3436 void
3437 isp_prt(ispsoftc_t *isp, int level, const char *fmt, ...)
3438 {
3439         va_list ap;
3440         if (level != ISP_LOGALL && (level & isp->isp_dblev) == 0) {
3441                 return;
3442         }
3443         printf("%s: ", device_get_nameunit(isp->isp_dev));
3444         va_start(ap, fmt);
3445         vprintf(fmt, ap);
3446         va_end(ap);
3447         printf("\n");
3448 }
3449
3450 uint64_t
3451 isp_nanotime_sub(struct timespec *b, struct timespec *a)
3452 {
3453         uint64_t elapsed;
3454         struct timespec x = *b;
3455         timespecsub(&x, a);
3456         elapsed = GET_NANOSEC(&x);
3457         if (elapsed == 0)
3458                 elapsed++;
3459         return (elapsed);
3460 }
3461
3462 int
3463 isp_mbox_acquire(ispsoftc_t *isp)
3464 {
3465         if (isp->isp_osinfo.mboxbsy) {
3466                 return (1);
3467         } else {
3468                 isp->isp_osinfo.mboxcmd_done = 0;
3469                 isp->isp_osinfo.mboxbsy = 1;
3470                 return (0);
3471         }
3472 }
3473
3474 void
3475 isp_mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
3476 {
3477         unsigned int usecs = mbp->timeout;
3478         unsigned int max, olim, ilim;
3479
3480         if (usecs == 0) {
3481                 usecs = MBCMD_DEFAULT_TIMEOUT;
3482         }
3483         max = isp->isp_mbxwrk0 + 1;
3484
3485         if (isp->isp_osinfo.mbox_sleep_ok) {
3486                 unsigned int ms = (usecs + 999) / 1000;
3487
3488                 isp->isp_osinfo.mbox_sleep_ok = 0;
3489                 isp->isp_osinfo.mbox_sleeping = 1;
3490                 for (olim = 0; olim < max; olim++) {
3491 #if __FreeBSD_version < 700037
3492                         tsleep(&isp->isp_mbxworkp, PRIBIO, "ispmbx_sleep",
3493                             isp_mstohz(ms));
3494 #else
3495                         msleep(&isp->isp_mbxworkp, &isp->isp_osinfo.lock,
3496                             PRIBIO, "ispmbx_sleep", isp_mstohz(ms));
3497 #endif
3498                         if (isp->isp_osinfo.mboxcmd_done) {
3499                                 break;
3500                         }
3501                 }
3502                 isp->isp_osinfo.mbox_sleep_ok = 1;
3503                 isp->isp_osinfo.mbox_sleeping = 0;
3504         } else {
3505                 for (olim = 0; olim < max; olim++) {
3506                         for (ilim = 0; ilim < usecs; ilim += 100) {
3507                                 uint32_t isr;
3508                                 uint16_t sema, mbox;
3509                                 if (isp->isp_osinfo.mboxcmd_done) {
3510                                         break;
3511                                 }
3512                                 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
3513                                         isp_intr(isp, isr, sema, mbox);
3514                                         if (isp->isp_osinfo.mboxcmd_done) {
3515                                                 break;
3516                                         }
3517                                 }
3518                                 USEC_DELAY(100);
3519                         }
3520                         if (isp->isp_osinfo.mboxcmd_done) {
3521                                 break;
3522                         }
3523                 }
3524         }
3525         if (isp->isp_osinfo.mboxcmd_done == 0) {
3526                 isp_prt(isp, ISP_LOGWARN,
3527                     "%s Mailbox Command (0x%x) Timeout (%uus)",
3528                     isp->isp_osinfo.mbox_sleep_ok? "Interrupting" : "Polled",
3529                     isp->isp_lastmbxcmd, usecs);
3530                 mbp->param[0] = MBOX_TIMEOUT;
3531                 isp->isp_osinfo.mboxcmd_done = 1;
3532         }
3533 }
3534
3535 void
3536 isp_mbox_notify_done(ispsoftc_t *isp)
3537 {
3538         if (isp->isp_osinfo.mbox_sleeping) {
3539                 wakeup(&isp->isp_mbxworkp);
3540         }
3541         isp->isp_osinfo.mboxcmd_done = 1;
3542 }
3543
3544 void
3545 isp_mbox_release(ispsoftc_t *isp)
3546 {
3547         isp->isp_osinfo.mboxbsy = 0;
3548 }
3549
3550 int
3551 isp_mstohz(int ms)
3552 {
3553         int hz;
3554         struct timeval t;
3555         t.tv_sec = ms / 1000;
3556         t.tv_usec = (ms % 1000) * 1000;
3557         hz = tvtohz(&t);
3558         if (hz < 0) {
3559                 hz = 0x7fffffff;
3560         }
3561         if (hz == 0) {
3562                 hz = 1;
3563         }
3564         return (hz);
3565 }
3566
3567 void
3568 isp_platform_intr(void *arg)
3569 {
3570         ispsoftc_t *isp = arg;
3571         uint32_t isr;
3572         uint16_t sema, mbox;
3573
3574         ISP_LOCK(isp);
3575         isp->isp_intcnt++;
3576         if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
3577                 isp->isp_intbogus++;
3578         } else {
3579                 isp_intr(isp, isr, sema, mbox);
3580         }
3581         ISP_UNLOCK(isp);
3582 }
3583
3584 void
3585 isp_common_dmateardown(ispsoftc_t *isp, struct ccb_scsiio *csio, uint32_t hdl)
3586 {
3587         if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
3588                 bus_dmamap_sync(isp->isp_osinfo.dmat,
3589                     PISP_PCMD(csio)->dmap, BUS_DMASYNC_POSTREAD);
3590         } else {
3591                 bus_dmamap_sync(isp->isp_osinfo.dmat,
3592                     PISP_PCMD(csio)->dmap, BUS_DMASYNC_POSTWRITE);
3593         }
3594         bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap);
3595 }