b2eb0540298d565473fadd79f4323c9d2c2bfea1
[dragonfly.git] / sys / dev / disk / isp / isp_freebsd.c
1 /* $FreeBSD: src/sys/dev/isp/isp_freebsd.c,v 1.32.2.20 2002/10/11 18:49:25 mjacob Exp $ */
2 /* $DragonFly: src/sys/dev/disk/isp/isp_freebsd.c,v 1.21 2008/05/18 20:30:22 pavalos Exp $ */
3 /*
4  * Platform (FreeBSD) dependent common attachment code for Qlogic adapters.
5  *
6  * Copyright (c) 1997, 1998, 1999, 2000, 2001 by Matthew Jacob
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice immediately at the beginning of the file, without modification,
13  *    this list of conditions, and the following disclaimer.
14  * 2. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 #include <sys/unistd.h>
30 #include <sys/kthread.h>
31 #include <sys/conf.h>
32 #include <sys/device.h>
33 #include <machine/stdarg.h>     /* for use by isp_prt below */
34
35 #include "isp_ioctl.h"
36 #include "isp_freebsd.h"
37
38 static d_ioctl_t ispioctl;
39 static void isp_intr_enable(void *);
40 static void isp_cam_async(void *, u_int32_t, struct cam_path *, void *);
41 static void isp_poll(struct cam_sim *);
42 static timeout_t isp_watchdog;
43 static void isp_kthread(void *);
44 static void isp_action(struct cam_sim *, union ccb *);
45
46
47 #define ISP_CDEV_MAJOR  248
48 static struct dev_ops isp_ops = {
49         { "isp", ISP_CDEV_MAJOR, D_TAPE },
50         .d_open =       nullopen,
51         .d_close =      nullclose,
52         .d_ioctl =      ispioctl,
53 };
54
55 static struct ispsoftc *isplist = NULL;
56
57 void
58 isp_attach(struct ispsoftc *isp)
59 {
60         int primary, secondary;
61         struct ccb_setasync csa;
62         struct cam_devq *devq;
63         struct cam_sim *sim;
64         struct cam_path *path;
65
66         /*
67          * Establish (in case of 12X0) which bus is the primary.
68          */
69
70         primary = 0;
71         secondary = 1;
72
73         /*
74          * Create the device queue for our SIM(s).
75          */
76         devq = cam_simq_alloc(isp->isp_maxcmds);
77         if (devq == NULL) {
78                 return;
79         }
80
81         /*
82          * Construct our SIM entry.
83          */
84         ISPLOCK_2_CAMLOCK(isp);
85         sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
86             device_get_unit(isp->isp_dev), &sim_mplock, 1, isp->isp_maxcmds, devq);
87         cam_simq_release(devq);         /* leaves 1 ref due to cam_sim_alloc */
88         if (sim == NULL) {
89                 CAMLOCK_2_ISPLOCK(isp);
90                 return;
91         }
92         CAMLOCK_2_ISPLOCK(isp);
93
94         isp->isp_osinfo.ehook.ich_func = isp_intr_enable;
95         isp->isp_osinfo.ehook.ich_arg = isp;
96         isp->isp_osinfo.ehook.ich_desc = "isp";
97         ISPLOCK_2_CAMLOCK(isp);
98         if (config_intrhook_establish(&isp->isp_osinfo.ehook) != 0) {
99                 cam_sim_free(sim);
100                 CAMLOCK_2_ISPLOCK(isp);
101                 isp_prt(isp, ISP_LOGERR,
102                     "could not establish interrupt enable hook");
103                 return;
104         }
105
106         if (xpt_bus_register(sim, primary) != CAM_SUCCESS) {
107                 cam_sim_free(sim);
108                 CAMLOCK_2_ISPLOCK(isp);
109                 return;
110         }
111
112         if (xpt_create_path(&path, NULL, cam_sim_path(sim),
113             CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
114                 xpt_bus_deregister(cam_sim_path(sim));
115                 cam_sim_free(sim);
116                 config_intrhook_disestablish(&isp->isp_osinfo.ehook);
117                 CAMLOCK_2_ISPLOCK(isp);
118                 return;
119         }
120
121         xpt_setup_ccb(&csa.ccb_h, path, 5);
122         csa.ccb_h.func_code = XPT_SASYNC_CB;
123         csa.event_enable = AC_LOST_DEVICE;
124         csa.callback = isp_cam_async;
125         csa.callback_arg = sim;
126         xpt_action((union ccb *)&csa);
127         CAMLOCK_2_ISPLOCK(isp);
128         isp->isp_sim = sim;
129         isp->isp_path = path;
130         /*
131          * Create a kernel thread for fibre channel instances. We
132          * don't have dual channel FC cards.
133          */
134         if (IS_FC(isp)) {
135                 ISPLOCK_2_CAMLOCK(isp);
136                 if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kthread,
137                     "%s: fc_thrd", device_get_nameunit(isp->isp_dev))) {
138                         xpt_bus_deregister(cam_sim_path(sim));
139                         cam_sim_free(sim);
140                         config_intrhook_disestablish(&isp->isp_osinfo.ehook);
141                         CAMLOCK_2_ISPLOCK(isp);
142                         isp_prt(isp, ISP_LOGERR, "could not create kthread");
143                         return;
144                 }
145                 CAMLOCK_2_ISPLOCK(isp);
146         }
147
148
149         /*
150          * If we have a second channel, construct SIM entry for that.
151          */
152         if (IS_DUALBUS(isp)) {
153                 ISPLOCK_2_CAMLOCK(isp);
154                 sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
155                     device_get_unit(isp->isp_dev), &sim_mplock, 1, isp->isp_maxcmds, devq);
156                 if (sim == NULL) {
157                         xpt_bus_deregister(cam_sim_path(isp->isp_sim));
158                         xpt_free_path(isp->isp_path);
159                         config_intrhook_disestablish(&isp->isp_osinfo.ehook);
160                         return;
161                 }
162                 if (xpt_bus_register(sim, secondary) != CAM_SUCCESS) {
163                         xpt_bus_deregister(cam_sim_path(isp->isp_sim));
164                         xpt_free_path(isp->isp_path);
165                         cam_sim_free(sim);
166                         config_intrhook_disestablish(&isp->isp_osinfo.ehook);
167                         CAMLOCK_2_ISPLOCK(isp);
168                         return;
169                 }
170
171                 if (xpt_create_path(&path, NULL, cam_sim_path(sim),
172                     CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
173                         xpt_bus_deregister(cam_sim_path(isp->isp_sim));
174                         xpt_free_path(isp->isp_path);
175                         xpt_bus_deregister(cam_sim_path(sim));
176                         cam_sim_free(sim);
177                         config_intrhook_disestablish(&isp->isp_osinfo.ehook);
178                         CAMLOCK_2_ISPLOCK(isp);
179                         return;
180                 }
181
182                 xpt_setup_ccb(&csa.ccb_h, path, 5);
183                 csa.ccb_h.func_code = XPT_SASYNC_CB;
184                 csa.event_enable = AC_LOST_DEVICE;
185                 csa.callback = isp_cam_async;
186                 csa.callback_arg = sim;
187                 xpt_action((union ccb *)&csa);
188                 CAMLOCK_2_ISPLOCK(isp);
189                 isp->isp_sim2 = sim;
190                 isp->isp_path2 = path;
191         }
192         /*
193          * Create device nodes
194          */
195         dev_ops_add(&isp_ops, -1, device_get_unit(isp->isp_dev));
196         make_dev(&isp_ops, device_get_unit(isp->isp_dev), UID_ROOT,
197             GID_OPERATOR, 0600, "%s", device_get_nameunit(isp->isp_dev));
198
199         if (isp->isp_role != ISP_ROLE_NONE) {
200                 isp->isp_state = ISP_RUNSTATE;
201         }
202         if (isplist == NULL) {
203                 isplist = isp;
204         } else {
205                 struct ispsoftc *tmp = isplist;
206                 while (tmp->isp_osinfo.next) {
207                         tmp = tmp->isp_osinfo.next;
208                 }
209                 tmp->isp_osinfo.next = isp;
210         }
211
212 }
213
214 static INLINE void
215 isp_freeze_loopdown(struct ispsoftc *isp, char *msg)
216 {
217         if (isp->isp_osinfo.simqfrozen == 0) {
218                 isp_prt(isp, ISP_LOGDEBUG0, "%s: freeze simq (loopdown)", msg);
219                 isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
220                 ISPLOCK_2_CAMLOCK(isp);
221                 xpt_freeze_simq(isp->isp_sim, 1);
222                 CAMLOCK_2_ISPLOCK(isp);
223         } else {
224                 isp_prt(isp, ISP_LOGDEBUG0, "%s: mark frozen (loopdown)", msg);
225                 isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
226         }
227 }
228
229 static int
230 ispioctl(struct dev_ioctl_args *ap)
231 {
232         cdev_t dev = ap->a_head.a_dev;
233         struct ispsoftc *isp;
234         int retval = ENOTTY;
235
236         isp = isplist;
237         while (isp) {
238                 if (minor(dev) == device_get_unit(isp->isp_dev)) {
239                         break;
240                 }
241                 isp = isp->isp_osinfo.next;
242         }
243         if (isp == NULL)
244                 return (ENXIO);
245         
246         switch (ap->a_cmd) {
247 #ifdef  ISP_FW_CRASH_DUMP
248         case ISP_GET_FW_CRASH_DUMP:
249         {
250                 u_int16_t *ptr = FCPARAM(isp)->isp_dump_data;
251                 size_t sz;
252
253                 retval = 0;
254                 if (IS_2200(isp))
255                         sz = QLA2200_RISC_IMAGE_DUMP_SIZE;
256                 else
257                         sz = QLA2300_RISC_IMAGE_DUMP_SIZE;
258                 ISP_LOCK(isp);
259                 if (ptr && *ptr) {
260                         void *uaddr = *((void **) addr);
261                         if (copyout(ptr, uaddr, sz)) {
262                                 retval = EFAULT;
263                         } else {
264                                 *ptr = 0;
265                         }
266                 } else {
267                         retval = ENXIO;
268                 }
269                 ISP_UNLOCK(isp);
270                 break;
271         }
272
273         case ISP_FORCE_CRASH_DUMP:
274                 ISP_LOCK(isp);
275                 isp_freeze_loopdown(isp, "ispioctl(ISP_FORCE_CRASH_DUMP)");
276                 isp_fw_dump(isp);
277                 isp_reinit(isp);
278                 ISP_UNLOCK(isp);
279                 retval = 0;
280                 break;
281 #endif
282         case ISP_SDBLEV:
283         {
284                 int olddblev = isp->isp_dblev;
285                 isp->isp_dblev = *(int *)ap->a_data;
286                 *(int *)ap->a_data = olddblev;
287                 retval = 0;
288                 break;
289         }
290         case ISP_RESETHBA:
291                 ISP_LOCK(isp);
292                 isp_reinit(isp);
293                 ISP_UNLOCK(isp);
294                 retval = 0;
295                 break;
296         case ISP_RESCAN:
297                 if (IS_FC(isp)) {
298                         ISP_LOCK(isp);
299                         if (isp_fc_runstate(isp, 5 * 1000000)) {
300                                 retval = EIO;
301                         } else {
302                                 retval = 0;
303                         }
304                         ISP_UNLOCK(isp);
305                 }
306                 break;
307         case ISP_FC_LIP:
308                 if (IS_FC(isp)) {
309                         ISP_LOCK(isp);
310                         if (isp_control(isp, ISPCTL_SEND_LIP, 0)) {
311                                 retval = EIO;
312                         } else {
313                                 retval = 0;
314                         }
315                         ISP_UNLOCK(isp);
316                 }
317                 break;
318         case ISP_FC_GETDINFO:
319         {
320                 struct isp_fc_device *ifc = (struct isp_fc_device *) ap->a_data;
321                 struct lportdb *lp;
322
323                 if (ifc->loopid < 0 || ifc->loopid >= MAX_FC_TARG) {
324                         retval = EINVAL;
325                         break;
326                 }
327                 ISP_LOCK(isp);
328                 lp = &FCPARAM(isp)->portdb[ifc->loopid];
329                 if (lp->valid) {
330                         ifc->loopid = lp->loopid;
331                         ifc->portid = lp->portid;
332                         ifc->node_wwn = lp->node_wwn;
333                         ifc->port_wwn = lp->port_wwn;
334                         retval = 0;
335                 } else {
336                         retval = ENODEV;
337                 }
338                 ISP_UNLOCK(isp);
339                 break;
340         }
341         case ISP_GET_STATS:
342         {
343                 isp_stats_t *sp = (isp_stats_t *) ap->a_data;
344
345                 MEMZERO(sp, sizeof (*sp));
346                 sp->isp_stat_version = ISP_STATS_VERSION;
347                 sp->isp_type = isp->isp_type;
348                 sp->isp_revision = isp->isp_revision;
349                 ISP_LOCK(isp);
350                 sp->isp_stats[ISP_INTCNT] = isp->isp_intcnt;
351                 sp->isp_stats[ISP_INTBOGUS] = isp->isp_intbogus;
352                 sp->isp_stats[ISP_INTMBOXC] = isp->isp_intmboxc;
353                 sp->isp_stats[ISP_INGOASYNC] = isp->isp_intoasync;
354                 sp->isp_stats[ISP_RSLTCCMPLT] = isp->isp_rsltccmplt;
355                 sp->isp_stats[ISP_FPHCCMCPLT] = isp->isp_fphccmplt;
356                 sp->isp_stats[ISP_RSCCHIWAT] = isp->isp_rscchiwater;
357                 sp->isp_stats[ISP_FPCCHIWAT] = isp->isp_fpcchiwater;
358                 ISP_UNLOCK(isp);
359                 retval = 0;
360                 break;
361         }
362         case ISP_CLR_STATS:
363                 ISP_LOCK(isp);
364                 isp->isp_intcnt = 0;
365                 isp->isp_intbogus = 0;
366                 isp->isp_intmboxc = 0;
367                 isp->isp_intoasync = 0;
368                 isp->isp_rsltccmplt = 0;
369                 isp->isp_fphccmplt = 0;
370                 isp->isp_rscchiwater = 0;
371                 isp->isp_fpcchiwater = 0;
372                 ISP_UNLOCK(isp);
373                 retval = 0;
374                 break;
375         case ISP_FC_GETHINFO:
376         {
377                 struct isp_hba_device *hba = (struct isp_hba_device *) ap->a_data;
378                 MEMZERO(hba, sizeof (*hba));
379                 ISP_LOCK(isp);
380                 hba->fc_speed = FCPARAM(isp)->isp_gbspeed;
381                 hba->fc_scsi_supported = 1;
382                 hba->fc_topology = FCPARAM(isp)->isp_topo + 1;
383                 hba->fc_loopid = FCPARAM(isp)->isp_loopid;
384                 hba->active_node_wwn = FCPARAM(isp)->isp_nodewwn;
385                 hba->active_port_wwn = FCPARAM(isp)->isp_portwwn;
386                 ISP_UNLOCK(isp);
387                 retval = 0;
388                 break;
389         }
390         case ISP_GET_FC_PARAM:
391         {
392                 struct isp_fc_param *f = (struct isp_fc_param *) ap->a_data;
393
394                 if (!IS_FC(isp)) {
395                         retval = EINVAL;
396                         break;
397                 }
398                 f->parameter = 0;
399                 if (strcmp(f->param_name, "framelength") == 0) {
400                         f->parameter = FCPARAM(isp)->isp_maxfrmlen;
401                         retval = 0;
402                         break;
403                 }
404                 if (strcmp(f->param_name, "exec_throttle") == 0) {
405                         f->parameter = FCPARAM(isp)->isp_execthrottle;
406                         retval = 0;
407                         break;
408                 }
409                 if (strcmp(f->param_name, "fullduplex") == 0) {
410                         if (FCPARAM(isp)->isp_fwoptions & ICBOPT_FULL_DUPLEX)
411                                 f->parameter = 1;
412                         retval = 0;
413                         break;
414                 }
415                 if (strcmp(f->param_name, "loopid") == 0) {
416                         f->parameter = FCPARAM(isp)->isp_loopid;
417                         retval = 0;
418                         break;
419                 }
420                 retval = EINVAL;
421                 break;
422         }
423         case ISP_SET_FC_PARAM:
424         {
425                 struct isp_fc_param *f = (struct isp_fc_param *) ap->a_data;
426                 u_int32_t param = f->parameter;
427
428                 if (!IS_FC(isp)) {
429                         retval = EINVAL;
430                         break;
431                 }
432                 f->parameter = 0;
433                 if (strcmp(f->param_name, "framelength") == 0) {
434                         if (param != 512 && param != 1024 && param != 1024) {
435                                 retval = EINVAL;
436                                 break;
437                         }
438                         FCPARAM(isp)->isp_maxfrmlen = param;
439                         retval = 0;
440                         break;
441                 }
442                 if (strcmp(f->param_name, "exec_throttle") == 0) {
443                         if (param < 16 || param > 255) {
444                                 retval = EINVAL;
445                                 break;
446                         }
447                         FCPARAM(isp)->isp_execthrottle = param;
448                         retval = 0;
449                         break;
450                 }
451                 if (strcmp(f->param_name, "fullduplex") == 0) {
452                         if (param != 0 && param != 1) {
453                                 retval = EINVAL;
454                                 break;
455                         }
456                         if (param) {
457                                 FCPARAM(isp)->isp_fwoptions |=
458                                     ICBOPT_FULL_DUPLEX;
459                         } else {
460                                 FCPARAM(isp)->isp_fwoptions &=
461                                     ~ICBOPT_FULL_DUPLEX;
462                         }
463                         retval = 0;
464                         break;
465                 }
466                 if (strcmp(f->param_name, "loopid") == 0) {
467                         if (param < 0 || param > 125) {
468                                 retval = EINVAL;
469                                 break;
470                         }
471                         FCPARAM(isp)->isp_loopid = param;
472                         retval = 0;
473                         break;
474                 }
475                 retval = EINVAL;
476                 break;
477         }
478         default:
479                 break;
480         }
481         return (retval);
482 }
483
484 static void
485 isp_intr_enable(void *arg)
486 {
487         struct ispsoftc *isp = arg;
488         if (isp->isp_role != ISP_ROLE_NONE) {
489                 ENABLE_INTS(isp);
490         }
491         /* Release our hook so that the boot can continue. */
492         config_intrhook_disestablish(&isp->isp_osinfo.ehook);
493 }
494
495 /*
496  * Put the target mode functions here, because some are inlines
497  */
498
499 #ifdef  ISP_TARGET_MODE
500
501 static INLINE int is_lun_enabled(struct ispsoftc *, int, lun_id_t);
502 static INLINE int are_any_luns_enabled(struct ispsoftc *, int);
503 static INLINE tstate_t *get_lun_statep(struct ispsoftc *, int, lun_id_t);
504 static INLINE void rls_lun_statep(struct ispsoftc *, tstate_t *);
505 static INLINE int isp_psema_sig_rqe(struct ispsoftc *, int);
506 static INLINE int isp_cv_wait_timed_rqe(struct ispsoftc *, int, int);
507 static INLINE void isp_cv_signal_rqe(struct ispsoftc *, int, int);
508 static INLINE void isp_vsema_rqe(struct ispsoftc *, int);
509 static INLINE atio_private_data_t *isp_get_atpd(struct ispsoftc *, int);
510 static cam_status
511 create_lun_state(struct ispsoftc *, int, struct cam_path *, tstate_t **);
512 static void destroy_lun_state(struct ispsoftc *, tstate_t *);
513 static void isp_en_lun(struct ispsoftc *, union ccb *);
514 static cam_status isp_abort_tgt_ccb(struct ispsoftc *, union ccb *);
515 static timeout_t isp_refire_putback_atio;
516 static void isp_complete_ctio(union ccb *);
517 static void isp_target_putback_atio(union ccb *);
518 static cam_status isp_target_start_ctio(struct ispsoftc *, union ccb *);
519 static int isp_handle_platform_atio(struct ispsoftc *, at_entry_t *);
520 static int isp_handle_platform_atio2(struct ispsoftc *, at2_entry_t *);
521 static int isp_handle_platform_ctio(struct ispsoftc *, void *);
522 static int isp_handle_platform_notify_scsi(struct ispsoftc *, in_entry_t *);
523 static int isp_handle_platform_notify_fc(struct ispsoftc *, in_fcentry_t *);
524
525 static INLINE int
526 is_lun_enabled(struct ispsoftc *isp, int bus, lun_id_t lun)
527 {
528         tstate_t *tptr;
529         tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(isp, bus, lun)];
530         if (tptr == NULL) {
531                 return (0);
532         }
533         do {
534                 if (tptr->lun == (lun_id_t) lun && tptr->bus == bus) {
535                         return (1);
536                 }
537         } while ((tptr = tptr->next) != NULL);
538         return (0);
539 }
540
541 static INLINE int
542 are_any_luns_enabled(struct ispsoftc *isp, int port)
543 {
544         int lo, hi;
545         if (IS_DUALBUS(isp)) {
546                 lo = (port * (LUN_HASH_SIZE >> 1));
547                 hi = lo + (LUN_HASH_SIZE >> 1);
548         } else {
549                 lo = 0;
550                 hi = LUN_HASH_SIZE;
551         }
552         for (lo = 0; lo < hi; lo++) {
553                 if (isp->isp_osinfo.lun_hash[lo]) {
554                         return (1);
555                 }
556         }
557         return (0);
558 }
559
560 static INLINE tstate_t *
561 get_lun_statep(struct ispsoftc *isp, int bus, lun_id_t lun)
562 {
563         tstate_t *tptr = NULL;
564
565         if (lun == CAM_LUN_WILDCARD) {
566                 if (isp->isp_osinfo.tmflags[bus] & TM_WILDCARD_ENABLED) {
567                         tptr = &isp->isp_osinfo.tsdflt[bus];
568                         tptr->hold++;
569                         return (tptr);
570                 }
571         } else {
572                 tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(isp, bus, lun)];
573                 if (tptr == NULL) {
574                         return (NULL);
575                 }
576         }
577
578         do {
579                 if (tptr->lun == lun && tptr->bus == bus) {
580                         tptr->hold++;
581                         return (tptr);
582                 }
583         } while ((tptr = tptr->next) != NULL);
584         return (tptr);
585 }
586
587 static __inline void
588 rls_lun_statep(struct ispsoftc *isp, tstate_t *tptr)
589 {
590         if (tptr->hold)
591                 tptr->hold--;
592 }
593
594 static __inline int
595 isp_psema_sig_rqe(struct ispsoftc *isp, int bus)
596 {
597         while (isp->isp_osinfo.tmflags[bus] & TM_BUSY) {
598                 isp->isp_osinfo.tmflags[bus] |= TM_WANTED;
599                 if (tsleep(&isp->isp_osinfo.tmflags[bus], PCATCH, "i0", 0)) {
600                         return (-1);
601                 }
602                 isp->isp_osinfo.tmflags[bus] |= TM_BUSY;
603         }
604         return (0);
605 }
606
607 static __inline int
608 isp_cv_wait_timed_rqe(struct ispsoftc *isp, int bus, int timo)
609 {
610         if (tsleep(&isp->isp_osinfo.rstatus[bus], 0, "qt1", timo)) {
611                 return (-1);
612         }
613         return (0);
614 }
615
616 static __inline void
617 isp_cv_signal_rqe(struct ispsoftc *isp, int bus, int status)
618 {
619         isp->isp_osinfo.rstatus[bus] = status;
620         wakeup(&isp->isp_osinfo.rstatus[bus]);
621 }
622
623 static __inline void
624 isp_vsema_rqe(struct ispsoftc *isp, int bus)
625 {
626         if (isp->isp_osinfo.tmflags[bus] & TM_WANTED) {
627                 isp->isp_osinfo.tmflags[bus] &= ~TM_WANTED;
628                 wakeup(&isp->isp_osinfo.tmflags[bus]);
629         }
630         isp->isp_osinfo.tmflags[bus] &= ~TM_BUSY;
631 }
632
633 static __inline atio_private_data_t *
634 isp_get_atpd(struct ispsoftc *isp, int tag)
635 {
636         atio_private_data_t *atp;
637         for (atp = isp->isp_osinfo.atpdp;
638             atp < &isp->isp_osinfo.atpdp[ATPDPSIZE]; atp++) {
639                 if (atp->tag == tag)
640                         return (atp);
641         }
642         return (NULL);
643 }
644
645 static cam_status
646 create_lun_state(struct ispsoftc *isp, int bus,
647     struct cam_path *path, tstate_t **rslt)
648 {
649         cam_status status;
650         lun_id_t lun;
651         int hfx;
652         tstate_t *tptr, *new;
653
654         lun = xpt_path_lun_id(path);
655         if (lun < 0) {
656                 return (CAM_LUN_INVALID);
657         }
658         if (is_lun_enabled(isp, bus, lun)) {
659                 return (CAM_LUN_ALRDY_ENA);
660         }
661         new = kmalloc(sizeof (tstate_t), M_DEVBUF, M_WAITOK | M_ZERO);
662         status = xpt_create_path(&new->owner, NULL, xpt_path_path_id(path),
663             xpt_path_target_id(path), xpt_path_lun_id(path));
664         if (status != CAM_REQ_CMP) {
665                 kfree(new, M_DEVBUF);
666                 return (status);
667         }
668         new->bus = bus;
669         new->lun = lun;
670         SLIST_INIT(&new->atios);
671         SLIST_INIT(&new->inots);
672         new->hold = 1;
673
674         hfx = LUN_HASH_FUNC(isp, new->bus, new->lun);
675         tptr = isp->isp_osinfo.lun_hash[hfx];
676         if (tptr == NULL) {
677                 isp->isp_osinfo.lun_hash[hfx] = new;
678         } else {
679                 while (tptr->next)
680                         tptr = tptr->next;
681                 tptr->next = new;
682         }
683         *rslt = new;
684         return (CAM_REQ_CMP);
685 }
686
687 static INLINE void
688 destroy_lun_state(struct ispsoftc *isp, tstate_t *tptr)
689 {
690         int hfx;
691         tstate_t *lw, *pw;
692
693         hfx = LUN_HASH_FUNC(isp, tptr->bus, tptr->lun);
694         if (tptr->hold) {
695                 return;
696         }
697         pw = isp->isp_osinfo.lun_hash[hfx];
698         if (pw == NULL) {
699                 return;
700         } else if (pw->lun == tptr->lun && pw->bus == tptr->bus) {
701                 isp->isp_osinfo.lun_hash[hfx] = pw->next;
702         } else {
703                 lw = pw;
704                 pw = lw->next;
705                 while (pw) {
706                         if (pw->lun == tptr->lun && pw->bus == tptr->bus) {
707                                 lw->next = pw->next;
708                                 break;
709                         }
710                         lw = pw;
711                         pw = pw->next;
712                 }
713                 if (pw == NULL) {
714                         return;
715                 }
716         }
717         kfree(tptr, M_DEVBUF);
718 }
719
720 /*
721  * we enter with our locks held.
722  */
723 static void
724 isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
725 {
726         const char lfmt[] = "Lun now %sabled for target mode on channel %d";
727         struct ccb_en_lun *cel = &ccb->cel;
728         tstate_t *tptr;
729         u_int16_t rstat;
730         int bus, cmd, av, wildcard;
731         lun_id_t lun;
732         target_id_t tgt;
733
734
735         bus = XS_CHANNEL(ccb) & 0x1;
736         tgt = ccb->ccb_h.target_id;
737         lun = ccb->ccb_h.target_lun;
738
739         /*
740          * Do some sanity checking first.
741          */
742
743         if ((lun != CAM_LUN_WILDCARD) &&
744             (lun < 0 || lun >= (lun_id_t) isp->isp_maxluns)) {
745                 ccb->ccb_h.status = CAM_LUN_INVALID;
746                 return;
747         }
748
749         if (IS_SCSI(isp)) {
750                 sdparam *sdp = isp->isp_param;
751                 sdp += bus;
752                 if (tgt != CAM_TARGET_WILDCARD &&
753                     tgt != sdp->isp_initiator_id) {
754                         ccb->ccb_h.status = CAM_TID_INVALID;
755                         return;
756                 }
757         } else {
758                 if (tgt != CAM_TARGET_WILDCARD &&
759                     tgt != FCPARAM(isp)->isp_iid) {
760                         ccb->ccb_h.status = CAM_TID_INVALID;
761                         return;
762                 }
763                 /*
764                  * This is as a good a place as any to check f/w capabilities.
765                  */
766                 if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_TMODE) == 0) {
767                         isp_prt(isp, ISP_LOGERR,
768                             "firmware does not support target mode");
769                         ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
770                         return;
771                 }
772                 /*
773                  * XXX: We *could* handle non-SCCLUN f/w, but we'd have to
774                  * XXX: dorks with our already fragile enable/disable code.
775                  */
776                 if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {
777                         isp_prt(isp, ISP_LOGERR,
778                             "firmware not SCCLUN capable");
779                 }
780         }
781
782         if (tgt == CAM_TARGET_WILDCARD) {
783                 if (lun == CAM_LUN_WILDCARD) {
784                         wildcard = 1;
785                 } else {
786                         ccb->ccb_h.status = CAM_LUN_INVALID;
787                         return;
788                 }
789         } else {
790                 wildcard = 0;
791         }
792
793         /*
794          * Next check to see whether this is a target/lun wildcard action.
795          *
796          * If so, we know that we can accept commands for luns that haven't
797          * been enabled yet and send them upstream. Otherwise, we have to
798          * handle them locally (if we see them at all).
799          */
800
801         if (wildcard) {
802                 tptr = &isp->isp_osinfo.tsdflt[bus];
803                 if (cel->enable) {
804                         if (isp->isp_osinfo.tmflags[bus] &
805                             TM_WILDCARD_ENABLED) {
806                                 ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
807                                 return;
808                         }
809                         ccb->ccb_h.status =
810                             xpt_create_path(&tptr->owner, NULL,
811                             xpt_path_path_id(ccb->ccb_h.path),
812                             xpt_path_target_id(ccb->ccb_h.path),
813                             xpt_path_lun_id(ccb->ccb_h.path));
814                         if (ccb->ccb_h.status != CAM_REQ_CMP) {
815                                 return;
816                         }
817                         SLIST_INIT(&tptr->atios);
818                         SLIST_INIT(&tptr->inots);
819                         isp->isp_osinfo.tmflags[bus] |= TM_WILDCARD_ENABLED;
820                 } else {
821                         if ((isp->isp_osinfo.tmflags[bus] &
822                             TM_WILDCARD_ENABLED) == 0) {
823                                 ccb->ccb_h.status = CAM_REQ_CMP;
824                                 return;
825                         }
826                         if (tptr->hold) {
827                                 ccb->ccb_h.status = CAM_SCSI_BUSY;
828                                 return;
829                         }
830                         xpt_free_path(tptr->owner);
831                         isp->isp_osinfo.tmflags[bus] &= ~TM_WILDCARD_ENABLED;
832                 }
833         }
834
835         /*
836          * Now check to see whether this bus needs to be
837          * enabled/disabled with respect to target mode.
838          */
839         av = bus << 31;
840         if (cel->enable && !(isp->isp_osinfo.tmflags[bus] & TM_TMODE_ENABLED)) {
841                 av |= ENABLE_TARGET_FLAG;
842                 av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
843                 if (av) {
844                         ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
845                         if (wildcard) {
846                                 isp->isp_osinfo.tmflags[bus] &=
847                                     ~TM_WILDCARD_ENABLED;
848                                 xpt_free_path(tptr->owner);
849                         }
850                         return;
851                 }
852                 isp->isp_osinfo.tmflags[bus] |= TM_TMODE_ENABLED;
853                 isp_prt(isp, ISP_LOGINFO,
854                     "Target Mode enabled on channel %d", bus);
855         } else if (cel->enable == 0 &&
856             (isp->isp_osinfo.tmflags[bus] & TM_TMODE_ENABLED) && wildcard) {
857                 if (are_any_luns_enabled(isp, bus)) {
858                         ccb->ccb_h.status = CAM_SCSI_BUSY;
859                         return;
860                 }
861                 av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
862                 if (av) {
863                         ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
864                         return;
865                 }
866                 isp->isp_osinfo.tmflags[bus] &= ~TM_TMODE_ENABLED;
867                 isp_prt(isp, ISP_LOGINFO,
868                     "Target Mode disabled on channel %d", bus);
869         }
870
871         if (wildcard) {
872                 ccb->ccb_h.status = CAM_REQ_CMP;
873                 return;
874         }
875
876         if (cel->enable) {
877                 ccb->ccb_h.status =
878                     create_lun_state(isp, bus, ccb->ccb_h.path, &tptr);
879                 if (ccb->ccb_h.status != CAM_REQ_CMP) {
880                         return;
881                 }
882         } else {
883                 tptr = get_lun_statep(isp, bus, lun);
884                 if (tptr == NULL) {
885                         ccb->ccb_h.status = CAM_LUN_INVALID;
886                         return;
887                 }
888         }
889
890         if (isp_psema_sig_rqe(isp, bus)) {
891                 rls_lun_statep(isp, tptr);
892                 if (cel->enable)
893                         destroy_lun_state(isp, tptr);
894                 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
895                 return;
896         }
897
898         if (cel->enable) {
899                 u_int32_t seq = isp->isp_osinfo.rollinfo++;
900                 int c, n, ulun = lun;
901
902                 cmd = RQSTYPE_ENABLE_LUN;
903                 c = DFLT_CMND_CNT;
904                 n = DFLT_INOT_CNT;
905                 if (IS_FC(isp) && lun != 0) {
906                         cmd = RQSTYPE_MODIFY_LUN;
907                         n = 0;
908                         /*
909                          * For SCC firmware, we only deal with setting
910                          * (enabling or modifying) lun 0.
911                          */
912                         ulun = 0;
913                 }
914                 rstat = LUN_ERR;
915                 if (isp_lun_cmd(isp, cmd, bus, tgt, ulun, c, n, seq)) {
916                         xpt_print_path(ccb->ccb_h.path);
917                         isp_prt(isp, ISP_LOGWARN, "isp_lun_cmd failed");
918                         goto out;
919                 }
920                 if (isp_cv_wait_timed_rqe(isp, bus, 30 * hz)) {
921                         xpt_print_path(ccb->ccb_h.path);
922                         isp_prt(isp, ISP_LOGERR,
923                             "wait for ENABLE/MODIFY LUN timed out");
924                         goto out;
925                 }
926                 rstat = isp->isp_osinfo.rstatus[bus];
927                 if (rstat != LUN_OK) {
928                         xpt_print_path(ccb->ccb_h.path);
929                         isp_prt(isp, ISP_LOGERR,
930                             "ENABLE/MODIFY LUN returned 0x%x", rstat);
931                         goto out;
932                 }
933         } else {
934                 int c, n, ulun = lun;
935                 u_int32_t seq;
936
937                 rstat = LUN_ERR;
938                 seq = isp->isp_osinfo.rollinfo++;
939                 cmd = -RQSTYPE_MODIFY_LUN;
940
941                 c = DFLT_CMND_CNT;
942                 n = DFLT_INOT_CNT;
943                 if (IS_FC(isp) && lun != 0) {
944                         n = 0;
945                         /*
946                          * For SCC firmware, we only deal with setting
947                          * (enabling or modifying) lun 0.
948                          */
949                         ulun = 0;
950                 }
951                 if (isp_lun_cmd(isp, cmd, bus, tgt, ulun, c, n, seq)) {
952                         xpt_print_path(ccb->ccb_h.path);
953                         isp_prt(isp, ISP_LOGERR, "isp_lun_cmd failed");
954                         goto out;
955                 }
956                 if (isp_cv_wait_timed_rqe(isp, bus, 30 * hz)) {
957                         xpt_print_path(ccb->ccb_h.path);
958                         isp_prt(isp, ISP_LOGERR,
959                             "wait for MODIFY LUN timed out");
960                         goto out;
961                 }
962                 rstat = isp->isp_osinfo.rstatus[bus];
963                 if (rstat != LUN_OK) {
964                         xpt_print_path(ccb->ccb_h.path);
965                         isp_prt(isp, ISP_LOGERR,
966                             "MODIFY LUN returned 0x%x", rstat);
967                         goto out;
968                 }
969                 if (IS_FC(isp) && lun) {
970                         goto out;
971                 }
972
973                 seq = isp->isp_osinfo.rollinfo++;
974
975                 rstat = LUN_ERR;
976                 cmd = -RQSTYPE_ENABLE_LUN;
977                 if (isp_lun_cmd(isp, cmd, bus, tgt, lun, 0, 0, seq)) {
978                         xpt_print_path(ccb->ccb_h.path);
979                         isp_prt(isp, ISP_LOGERR, "isp_lun_cmd failed");
980                         goto out;
981                 }
982                 if (isp_cv_wait_timed_rqe(isp, bus, 30 * hz)) {
983                         xpt_print_path(ccb->ccb_h.path);
984                         isp_prt(isp, ISP_LOGERR,
985                              "wait for DISABLE LUN timed out");
986                         goto out;
987                 }
988                 rstat = isp->isp_osinfo.rstatus[bus];
989                 if (rstat != LUN_OK) {
990                         xpt_print_path(ccb->ccb_h.path);
991                         isp_prt(isp, ISP_LOGWARN,
992                             "DISABLE LUN returned 0x%x", rstat);
993                         goto out;
994                 }
995                 if (are_any_luns_enabled(isp, bus) == 0) {
996                         av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
997                         if (av) {
998                                 isp_prt(isp, ISP_LOGWARN,
999                                     "disable target mode on channel %d failed",
1000                                     bus);
1001                                 goto out;
1002                         }
1003                         isp->isp_osinfo.tmflags[bus] &= ~TM_TMODE_ENABLED;
1004                         xpt_print_path(ccb->ccb_h.path);
1005                         isp_prt(isp, ISP_LOGINFO,
1006                             "Target Mode disabled on channel %d", bus);
1007                 }
1008         }
1009
1010 out:
1011         isp_vsema_rqe(isp, bus);
1012
1013         if (rstat != LUN_OK) {
1014                 xpt_print_path(ccb->ccb_h.path);
1015                 isp_prt(isp, ISP_LOGWARN,
1016                     "lun %sable failed", (cel->enable) ? "en" : "dis");
1017                 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1018                 rls_lun_statep(isp, tptr);
1019                 if (cel->enable)
1020                         destroy_lun_state(isp, tptr);
1021         } else {
1022                 xpt_print_path(ccb->ccb_h.path);
1023                 isp_prt(isp, ISP_LOGINFO, lfmt,
1024                     (cel->enable) ? "en" : "dis", bus);
1025                 rls_lun_statep(isp, tptr);
1026                 if (cel->enable == 0) {
1027                         destroy_lun_state(isp, tptr);
1028                 }
1029                 ccb->ccb_h.status = CAM_REQ_CMP;
1030         }
1031 }
1032
1033 static cam_status
1034 isp_abort_tgt_ccb(struct ispsoftc *isp, union ccb *ccb)
1035 {
1036         tstate_t *tptr;
1037         struct ccb_hdr_slist *lp;
1038         struct ccb_hdr *curelm;
1039         int found;
1040         union ccb *accb = ccb->cab.abort_ccb;
1041
1042         if (accb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
1043                 if (IS_FC(isp) && (accb->ccb_h.target_id != 
1044                     ((fcparam *) isp->isp_param)->isp_loopid)) {
1045                         return (CAM_PATH_INVALID);
1046                 } else if (IS_SCSI(isp) && (accb->ccb_h.target_id != 
1047                     ((sdparam *) isp->isp_param)->isp_initiator_id)) {
1048                         return (CAM_PATH_INVALID);
1049                 }
1050         }
1051         tptr = get_lun_statep(isp, XS_CHANNEL(ccb), accb->ccb_h.target_lun);
1052         if (tptr == NULL) {
1053                 return (CAM_PATH_INVALID);
1054         }
1055         if (accb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
1056                 lp = &tptr->atios;
1057         } else if (accb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
1058                 lp = &tptr->inots;
1059         } else {
1060                 rls_lun_statep(isp, tptr);
1061                 return (CAM_UA_ABORT);
1062         }
1063         curelm = SLIST_FIRST(lp);
1064         found = 0;
1065         if (curelm == &accb->ccb_h) {
1066                 found = 1;
1067                 SLIST_REMOVE_HEAD(lp, sim_links.sle);
1068         } else {
1069                 while(curelm != NULL) {
1070                         struct ccb_hdr *nextelm;
1071
1072                         nextelm = SLIST_NEXT(curelm, sim_links.sle);
1073                         if (nextelm == &accb->ccb_h) {
1074                                 found = 1;
1075                                 SLIST_NEXT(curelm, sim_links.sle) =
1076                                     SLIST_NEXT(nextelm, sim_links.sle);
1077                                 break;
1078                         }
1079                         curelm = nextelm;
1080                 }
1081         }
1082         rls_lun_statep(isp, tptr);
1083         if (found) {
1084                 accb->ccb_h.status = CAM_REQ_ABORTED;
1085                 return (CAM_REQ_CMP);
1086         }
1087         return(CAM_PATH_INVALID);
1088 }
1089
1090 static cam_status
1091 isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb)
1092 {
1093         void *qe;
1094         struct ccb_scsiio *cso = &ccb->csio;
1095         u_int16_t *hp, save_handle;
1096         u_int16_t nxti, optr;
1097         u_int8_t local[QENTRY_LEN];
1098
1099
1100         if (isp_getrqentry(isp, &nxti, &optr, &qe)) {
1101                 xpt_print_path(ccb->ccb_h.path);
1102                 kprintf("Request Queue Overflow in isp_target_start_ctio\n");
1103                 return (CAM_RESRC_UNAVAIL);
1104         }
1105         bzero(local, QENTRY_LEN);
1106
1107         /*
1108          * We're either moving data or completing a command here.
1109          */
1110
1111         if (IS_FC(isp)) {
1112                 atio_private_data_t *atp;
1113                 ct2_entry_t *cto = (ct2_entry_t *) local;
1114
1115                 cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
1116                 cto->ct_header.rqs_entry_count = 1;
1117                 cto->ct_iid = cso->init_id;
1118                 if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {
1119                         cto->ct_lun = ccb->ccb_h.target_lun;
1120                 }
1121
1122                 atp = isp_get_atpd(isp, cso->tag_id);
1123                 if (atp == NULL) {
1124                         isp_prt(isp, ISP_LOGERR,
1125                             "cannot find private data adjunct for tag %x",
1126                             cso->tag_id);
1127                         return (-1);
1128                 }
1129
1130                 cto->ct_rxid = cso->tag_id;
1131                 if (cso->dxfer_len == 0) {
1132                         cto->ct_flags |= CT2_FLAG_MODE1 | CT2_NO_DATA;
1133                         if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
1134                                 cto->ct_flags |= CT2_SENDSTATUS;
1135                                 cto->rsp.m1.ct_scsi_status = cso->scsi_status;
1136                                 cto->ct_resid =
1137                                     atp->orig_datalen - atp->bytes_xfered;
1138                                 if (cto->ct_resid < 0) {
1139                                         cto->rsp.m1.ct_scsi_status |=
1140                                             CT2_DATA_OVER;
1141                                 } else if (cto->ct_resid > 0) {
1142                                         cto->rsp.m1.ct_scsi_status |=
1143                                             CT2_DATA_UNDER;
1144                                 }
1145                         }
1146                         if ((ccb->ccb_h.flags & CAM_SEND_SENSE) != 0) {
1147                                 int m = min(cso->sense_len, MAXRESPLEN);
1148                                 bcopy(&cso->sense_data, cto->rsp.m1.ct_resp, m);
1149                                 cto->rsp.m1.ct_senselen = m;
1150                                 cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
1151                         }
1152                 } else {
1153                         cto->ct_flags |= CT2_FLAG_MODE0;
1154                         if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1155                                 cto->ct_flags |= CT2_DATA_IN;
1156                         } else {
1157                                 cto->ct_flags |= CT2_DATA_OUT;
1158                         }
1159                         cto->ct_reloff = atp->bytes_xfered;
1160                         if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
1161                                 cto->ct_flags |= CT2_SENDSTATUS;
1162                                 cto->rsp.m0.ct_scsi_status = cso->scsi_status;
1163                                 cto->ct_resid =
1164                                     atp->orig_datalen -
1165                                     (atp->bytes_xfered + cso->dxfer_len);
1166                                 if (cto->ct_resid < 0) {
1167                                         cto->rsp.m0.ct_scsi_status |=
1168                                             CT2_DATA_OVER;
1169                                 } else if (cto->ct_resid > 0) {
1170                                         cto->rsp.m0.ct_scsi_status |=
1171                                             CT2_DATA_UNDER;
1172                                 }
1173                         } else {
1174                                 atp->last_xframt = cso->dxfer_len;
1175                         }
1176                         /*
1177                          * If we're sending data and status back together,
1178                          * we can't also send back sense data as well.
1179                          */
1180                         ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
1181                 }
1182
1183                 if (cto->ct_flags & CT2_SENDSTATUS) {
1184                         isp_prt(isp, ISP_LOGTDEBUG0,
1185                             "CTIO2[%x] STATUS %x origd %u curd %u resid %u",
1186                             cto->ct_rxid, cso->scsi_status, atp->orig_datalen,
1187                             cso->dxfer_len, cto->ct_resid);
1188                         cto->ct_flags |= CT2_CCINCR;
1189                         atp->state = ATPD_STATE_LAST_CTIO;
1190                 } else
1191                         atp->state = ATPD_STATE_CTIO;
1192                 cto->ct_timeout = 10;
1193                 hp = &cto->ct_syshandle;
1194         } else {
1195                 ct_entry_t *cto = (ct_entry_t *) local;
1196
1197                 cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
1198                 cto->ct_header.rqs_entry_count = 1;
1199                 cto->ct_iid = cso->init_id;
1200                 cto->ct_iid |= XS_CHANNEL(ccb) << 7;
1201                 cto->ct_tgt = ccb->ccb_h.target_id;
1202                 cto->ct_lun = ccb->ccb_h.target_lun;
1203                 cto->ct_fwhandle = AT_GET_HANDLE(cso->tag_id);
1204                 if (AT_HAS_TAG(cso->tag_id)) {
1205                         cto->ct_tag_val = (u_int8_t) AT_GET_TAG(cso->tag_id);
1206                         cto->ct_flags |= CT_TQAE;
1207                 }
1208                 if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) {
1209                         cto->ct_flags |= CT_NODISC;
1210                 }
1211                 if (cso->dxfer_len == 0) {
1212                         cto->ct_flags |= CT_NO_DATA;
1213                 } else if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1214                         cto->ct_flags |= CT_DATA_IN;
1215                 } else {
1216                         cto->ct_flags |= CT_DATA_OUT;
1217                 }
1218                 if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
1219                         cto->ct_flags |= CT_SENDSTATUS|CT_CCINCR;
1220                         cto->ct_scsi_status = cso->scsi_status;
1221                         cto->ct_resid = cso->resid;
1222                         isp_prt(isp, ISP_LOGTDEBUG0,
1223                             "CTIO[%x] SCSI STATUS 0x%x resid %d tag_id %x",
1224                             cto->ct_fwhandle, cso->scsi_status, cso->resid,
1225                             cso->tag_id);
1226                 }
1227                 ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
1228                 cto->ct_timeout = 10;
1229                 hp = &cto->ct_syshandle;
1230         }
1231
1232         if (isp_save_xs(isp, (XS_T *)ccb, hp)) {
1233                 xpt_print_path(ccb->ccb_h.path);
1234                 kprintf("No XFLIST pointers for isp_target_start_ctio\n");
1235                 return (CAM_RESRC_UNAVAIL);
1236         }
1237
1238
1239         /*
1240          * Call the dma setup routines for this entry (and any subsequent
1241          * CTIOs) if there's data to move, and then tell the f/w it's got
1242          * new things to play with. As with isp_start's usage of DMA setup,
1243          * any swizzling is done in the machine dependent layer. Because
1244          * of this, we put the request onto the queue area first in native
1245          * format.
1246          */
1247
1248         save_handle = *hp;
1249
1250         switch (ISP_DMASETUP(isp, cso, (ispreq_t *) local, &nxti, optr)) {
1251         case CMD_QUEUED:
1252                 ISP_ADD_REQUEST(isp, nxti);
1253                 return (CAM_REQ_INPROG);
1254
1255         case CMD_EAGAIN:
1256                 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1257                 isp_destroy_handle(isp, save_handle);
1258                 return (CAM_RESRC_UNAVAIL);
1259
1260         default:
1261                 isp_destroy_handle(isp, save_handle);
1262                 return (XS_ERR(ccb));
1263         }
1264 }
1265
1266 static void
1267 isp_refire_putback_atio(void *arg)
1268 {
1269         crit_enter();
1270         isp_target_putback_atio(arg);
1271         crit_exit();
1272 }
1273
1274 static void
1275 isp_target_putback_atio(union ccb *ccb)
1276 {
1277         struct ispsoftc *isp;
1278         struct ccb_scsiio *cso;
1279         u_int16_t nxti, optr;
1280         void *qe;
1281
1282         isp = XS_ISP(ccb);
1283
1284         if (isp_getrqentry(isp, &nxti, &optr, &qe)) {
1285                 (void) timeout(isp_refire_putback_atio, ccb, 10);
1286                 isp_prt(isp, ISP_LOGWARN,
1287                     "isp_target_putback_atio: Request Queue Overflow"); 
1288                 return;
1289         }
1290         bzero(qe, QENTRY_LEN);
1291         cso = &ccb->csio;
1292         if (IS_FC(isp)) {
1293                 at2_entry_t local, *at = &local;
1294                 MEMZERO(at, sizeof (at2_entry_t));
1295                 at->at_header.rqs_entry_type = RQSTYPE_ATIO2;
1296                 at->at_header.rqs_entry_count = 1;
1297                 if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) != 0) {
1298                         at->at_scclun = (uint16_t) ccb->ccb_h.target_lun;
1299                 } else {
1300                         at->at_lun = (uint8_t) ccb->ccb_h.target_lun;
1301                 }
1302                 at->at_status = CT_OK;
1303                 at->at_rxid = cso->tag_id;
1304                 at->at_iid = cso->ccb_h.target_id;
1305                 isp_put_atio2(isp, at, qe);
1306         } else {
1307                 at_entry_t local, *at = &local;
1308                 MEMZERO(at, sizeof (at_entry_t));
1309                 at->at_header.rqs_entry_type = RQSTYPE_ATIO;
1310                 at->at_header.rqs_entry_count = 1;
1311                 at->at_iid = cso->init_id;
1312                 at->at_iid |= XS_CHANNEL(ccb) << 7;
1313                 at->at_tgt = cso->ccb_h.target_id;
1314                 at->at_lun = cso->ccb_h.target_lun;
1315                 at->at_status = CT_OK;
1316                 at->at_tag_val = AT_GET_TAG(cso->tag_id);
1317                 at->at_handle = AT_GET_HANDLE(cso->tag_id);
1318                 isp_put_atio(isp, at, qe);
1319         }
1320         ISP_TDQE(isp, "isp_target_putback_atio", (int) optr, qe);
1321         ISP_ADD_REQUEST(isp, nxti);
1322         isp_complete_ctio(ccb);
1323 }
1324
1325 static void
1326 isp_complete_ctio(union ccb *ccb)
1327 {
1328         if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
1329                 ccb->ccb_h.status |= CAM_REQ_CMP;
1330         }
1331         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1332         xpt_done(ccb);
1333 }
1334
1335 /*
1336  * Handle ATIO stuff that the generic code can't.
1337  * This means handling CDBs.
1338  */
1339
1340 static int
1341 isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep)
1342 {
1343         tstate_t *tptr;
1344         int status, bus, iswildcard;
1345         struct ccb_accept_tio *atiop;
1346
1347         /*
1348          * The firmware status (except for the QLTM_SVALID bit)
1349          * indicates why this ATIO was sent to us.
1350          *
1351          * If QLTM_SVALID is set, the firware has recommended Sense Data.
1352          *
1353          * If the DISCONNECTS DISABLED bit is set in the flags field,
1354          * we're still connected on the SCSI bus.
1355          */
1356         status = aep->at_status;
1357         if ((status & ~QLTM_SVALID) == AT_PHASE_ERROR) {
1358                 /*
1359                  * Bus Phase Sequence error. We should have sense data
1360                  * suggested by the f/w. I'm not sure quite yet what
1361                  * to do about this for CAM.
1362                  */
1363                 isp_prt(isp, ISP_LOGWARN, "PHASE ERROR");
1364                 isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1365                 return (0);
1366         }
1367         if ((status & ~QLTM_SVALID) != AT_CDB) {
1368                 isp_prt(isp, ISP_LOGWARN, "bad atio (0x%x) leaked to platform",
1369                     status);
1370                 isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1371                 return (0);
1372         }
1373
1374         bus = GET_BUS_VAL(aep->at_iid);
1375         tptr = get_lun_statep(isp, bus, aep->at_lun);
1376         if (tptr == NULL) {
1377                 tptr = get_lun_statep(isp, bus, CAM_LUN_WILDCARD);
1378                 iswildcard = 1;
1379         } else {
1380                 iswildcard = 0;
1381         }
1382
1383         if (tptr == NULL) {
1384                 /*
1385                  * Because we can't autofeed sense data back with
1386                  * a command for parallel SCSI, we can't give back
1387                  * a CHECK CONDITION. We'll give back a BUSY status
1388                  * instead. This works out okay because the only
1389                  * time we should, in fact, get this, is in the
1390                  * case that somebody configured us without the
1391                  * blackhole driver, so they get what they deserve.
1392                  */
1393                 isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1394                 return (0);
1395         }
1396
1397         atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
1398         if (atiop == NULL) {
1399                 /*
1400                  * Because we can't autofeed sense data back with
1401                  * a command for parallel SCSI, we can't give back
1402                  * a CHECK CONDITION. We'll give back a QUEUE FULL status
1403                  * instead. This works out okay because the only time we
1404                  * should, in fact, get this, is in the case that we've
1405                  * run out of ATIOS.
1406                  */
1407                 xpt_print_path(tptr->owner);
1408                 isp_prt(isp, ISP_LOGWARN,
1409                     "no ATIOS for lun %d from initiator %d on channel %d",
1410                     aep->at_lun, GET_IID_VAL(aep->at_iid), bus);
1411                 if (aep->at_flags & AT_TQAE)
1412                         isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0);
1413                 else
1414                         isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1415                 rls_lun_statep(isp, tptr);
1416                 return (0);
1417         }
1418         SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
1419         if (iswildcard) {
1420                 atiop->ccb_h.target_id = aep->at_tgt;
1421                 atiop->ccb_h.target_lun = aep->at_lun;
1422         }
1423         if (aep->at_flags & AT_NODISC) {
1424                 atiop->ccb_h.flags = CAM_DIS_DISCONNECT;
1425         } else {
1426                 atiop->ccb_h.flags = 0;
1427         }
1428
1429         if (status & QLTM_SVALID) {
1430                 size_t amt = imin(QLTM_SENSELEN, sizeof (atiop->sense_data));
1431                 atiop->sense_len = amt;
1432                 MEMCPY(&atiop->sense_data, aep->at_sense, amt);
1433         } else {
1434                 atiop->sense_len = 0;
1435         }
1436
1437         atiop->init_id = GET_IID_VAL(aep->at_iid);
1438         atiop->cdb_len = aep->at_cdblen;
1439         MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen);
1440         atiop->ccb_h.status = CAM_CDB_RECVD;
1441         /*
1442          * Construct a tag 'id' based upon tag value (which may be 0..255)
1443          * and the handle (which we have to preserve).
1444          */
1445         AT_MAKE_TAGID(atiop->tag_id, aep);
1446         if (aep->at_flags & AT_TQAE) {
1447                 atiop->tag_action = aep->at_tag_type;
1448                 atiop->ccb_h.status |= CAM_TAG_ACTION_VALID;
1449         }
1450         xpt_done((union ccb*)atiop);
1451         isp_prt(isp, ISP_LOGTDEBUG0,
1452             "ATIO[%x] CDB=0x%x bus %d iid%d->lun%d tag 0x%x ttype 0x%x %s",
1453             aep->at_handle, aep->at_cdb[0] & 0xff, GET_BUS_VAL(aep->at_iid),
1454             GET_IID_VAL(aep->at_iid), aep->at_lun, aep->at_tag_val & 0xff,
1455             aep->at_tag_type, (aep->at_flags & AT_NODISC)?
1456             "nondisc" : "disconnecting");
1457         rls_lun_statep(isp, tptr);
1458         return (0);
1459 }
1460
1461 static int
1462 isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep)
1463 {
1464         lun_id_t lun;
1465         tstate_t *tptr;
1466         struct ccb_accept_tio *atiop;
1467         atio_private_data_t *atp;
1468
1469         /*
1470          * The firmware status (except for the QLTM_SVALID bit)
1471          * indicates why this ATIO was sent to us.
1472          *
1473          * If QLTM_SVALID is set, the firware has recommended Sense Data.
1474          */
1475         if ((aep->at_status & ~QLTM_SVALID) != AT_CDB) {
1476                 isp_prt(isp, ISP_LOGWARN,
1477                     "bogus atio (0x%x) leaked to platform", aep->at_status);
1478                 isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1479                 return (0);
1480         }
1481
1482         if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) != 0) {
1483                 lun = aep->at_scclun;
1484         } else {
1485                 lun = aep->at_lun;
1486         }
1487         tptr = get_lun_statep(isp, 0, lun);
1488         if (tptr == NULL) {
1489                 isp_prt(isp, ISP_LOGWARN, "no state pointer for lun %d", lun);
1490                 tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD);
1491         }
1492
1493         if (tptr == NULL) {
1494                 /*
1495                  * What we'd like to know is whether or not we have a listener
1496                  * upstream that really hasn't configured yet. If we do, then
1497                  * we can give a more sensible reply here. If not, then we can
1498                  * reject this out of hand.
1499                  *
1500                  * Choices for what to send were
1501                  *
1502                  *      Not Ready, Unit Not Self-Configured Yet
1503                  *      (0x2,0x3e,0x00)
1504                  *
1505                  * for the former and
1506                  *
1507                  *      Illegal Request, Logical Unit Not Supported
1508                  *      (0x5,0x25,0x00)
1509                  *
1510                  * for the latter.
1511                  *
1512                  * We used to decide whether there was at least one listener
1513                  * based upon whether the black hole driver was configured.
1514                  * However, recent config(8) changes have made this hard to do
1515                  * at this time.
1516                  *
1517                  */
1518                 isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
1519                 return (0);
1520         }
1521
1522         atp = isp_get_atpd(isp, 0);
1523         atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
1524         if (atiop == NULL || atp == NULL) {
1525                 /*
1526                  * Because we can't autofeed sense data back with
1527                  * a command for parallel SCSI, we can't give back
1528                  * a CHECK CONDITION. We'll give back a QUEUE FULL status
1529                  * instead. This works out okay because the only time we
1530                  * should, in fact, get this, is in the case that we've
1531                  * run out of ATIOS.
1532                  */
1533                 xpt_print_path(tptr->owner);
1534                 isp_prt(isp, ISP_LOGWARN,
1535                     "no %s for lun %d from initiator %d",
1536                     (atp == NULL && atiop == NULL)? "ATIO2s *or* ATPS" :
1537                     ((atp == NULL)? "ATPs" : "ATIO2s"), lun, aep->at_iid);
1538                 rls_lun_statep(isp, tptr);
1539                 isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0);
1540                 return (0);
1541         }
1542         atp->state = ATPD_STATE_ATIO;
1543         SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
1544         tptr->atio_count--;
1545         isp_prt(isp, ISP_LOGTDEBUG0, "Take FREE ATIO2 lun %d, count now %d",
1546             lun, tptr->atio_count);
1547
1548         if (tptr == &isp->isp_osinfo.tsdflt[0]) {
1549                 atiop->ccb_h.target_id =
1550                     ((fcparam *)isp->isp_param)->isp_loopid;
1551                 atiop->ccb_h.target_lun = lun;
1552         }
1553         /*
1554          * We don't get 'suggested' sense data as we do with SCSI cards.
1555          */
1556         atiop->sense_len = 0;
1557
1558         atiop->init_id = aep->at_iid;
1559         atiop->cdb_len = ATIO2_CDBLEN;
1560         MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, ATIO2_CDBLEN);
1561         atiop->ccb_h.status = CAM_CDB_RECVD;
1562         atiop->tag_id = aep->at_rxid;
1563         switch (aep->at_taskflags & ATIO2_TC_ATTR_MASK) {
1564         case ATIO2_TC_ATTR_SIMPLEQ:
1565                 atiop->tag_action = MSG_SIMPLE_Q_TAG;
1566                 break;
1567         case ATIO2_TC_ATTR_HEADOFQ:
1568                 atiop->tag_action = MSG_HEAD_OF_Q_TAG;
1569                 break;
1570         case ATIO2_TC_ATTR_ORDERED:
1571                 atiop->tag_action = MSG_ORDERED_Q_TAG;
1572                 break;
1573         case ATIO2_TC_ATTR_ACAQ:                /* ?? */
1574         case ATIO2_TC_ATTR_UNTAGGED:
1575         default:
1576                 atiop->tag_action = 0;
1577                 break;
1578         }
1579         atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
1580
1581         atp->tag = atiop->tag_id;
1582         atp->lun = lun;
1583         atp->orig_datalen = aep->at_datalen;
1584         atp->last_xframt = 0;
1585         atp->bytes_xfered = 0;
1586         atp->state = ATPD_STATE_CAM;
1587         xpt_done((union ccb*)atiop);
1588
1589         isp_prt(isp, ISP_LOGTDEBUG0,
1590             "ATIO2[%x] CDB=0x%x iid%d->lun%d tattr 0x%x datalen %u",
1591             aep->at_rxid, aep->at_cdb[0] & 0xff, aep->at_iid,
1592             lun, aep->at_taskflags, aep->at_datalen);
1593         rls_lun_statep(isp, tptr);
1594         return (0);
1595 }
1596
1597 static int
1598 isp_handle_platform_ctio(struct ispsoftc *isp, void *arg)
1599 {
1600         union ccb *ccb;
1601         int sentstatus, ok, notify_cam, resid = 0;
1602         u_int16_t tval;
1603
1604         /*
1605          * CTIO and CTIO2 are close enough....
1606          */
1607
1608         ccb = (union ccb *) isp_find_xs(isp, ((ct_entry_t *)arg)->ct_syshandle);
1609         KASSERT((ccb != NULL), ("null ccb in isp_handle_platform_ctio"));
1610         isp_destroy_handle(isp, ((ct_entry_t *)arg)->ct_syshandle);
1611
1612         if (IS_FC(isp)) {
1613                 ct2_entry_t *ct = arg;
1614                 atio_private_data_t *atp = isp_get_atpd(isp, ct->ct_rxid);
1615                 if (atp == NULL) {
1616                         isp_prt(isp, ISP_LOGERR,
1617                             "cannot find adjunct for %x after I/O",
1618                             ct->ct_rxid);
1619                         return (0);
1620                 }
1621                 sentstatus = ct->ct_flags & CT2_SENDSTATUS;
1622                 ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;
1623                 if (ok && sentstatus && (ccb->ccb_h.flags & CAM_SEND_SENSE)) {
1624                         ccb->ccb_h.status |= CAM_SENT_SENSE;
1625                 }
1626                 notify_cam = ct->ct_header.rqs_seqno & 0x1;
1627                 if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
1628                         resid = ct->ct_resid;
1629                         atp->bytes_xfered += (atp->last_xframt - resid);
1630                         atp->last_xframt = 0;
1631                 }
1632                 if (sentstatus || !ok) {
1633                         atp->tag = 0;
1634                 }
1635                 isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN,
1636                     "CTIO2[%x] sts 0x%x flg 0x%x sns %d resid %d %s",
1637                     ct->ct_rxid, ct->ct_status, ct->ct_flags,
1638                     (ccb->ccb_h.status & CAM_SENT_SENSE) != 0,
1639                     resid, sentstatus? "FIN" : "MID");
1640                 tval = ct->ct_rxid;
1641
1642                 /* XXX: should really come after isp_complete_ctio */
1643                 atp->state = ATPD_STATE_PDON;
1644         } else {
1645                 ct_entry_t *ct = arg;
1646                 sentstatus = ct->ct_flags & CT_SENDSTATUS;
1647                 ok = (ct->ct_status  & ~QLTM_SVALID) == CT_OK;
1648                 /*
1649                  * We *ought* to be able to get back to the original ATIO
1650                  * here, but for some reason this gets lost. It's just as
1651                  * well because it's squirrelled away as part of periph
1652                  * private data.
1653                  *
1654                  * We can live without it as long as we continue to use
1655                  * the auto-replenish feature for CTIOs.
1656                  */
1657                 notify_cam = ct->ct_header.rqs_seqno & 0x1;
1658                 if (ct->ct_status & QLTM_SVALID) {
1659                         char *sp = (char *)ct;
1660                         sp += CTIO_SENSE_OFFSET;
1661                         ccb->csio.sense_len =
1662                             min(sizeof (ccb->csio.sense_data), QLTM_SENSELEN);
1663                         MEMCPY(&ccb->csio.sense_data, sp, ccb->csio.sense_len);
1664                         ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
1665                 }
1666                 if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) {
1667                         resid = ct->ct_resid;
1668                 }
1669                 isp_prt(isp, ISP_LOGTDEBUG0,
1670                     "CTIO[%x] tag %x iid %d lun %d sts %x flg %x resid %d %s",
1671                     ct->ct_fwhandle, ct->ct_tag_val, ct->ct_iid, ct->ct_lun,
1672                     ct->ct_status, ct->ct_flags, resid,
1673                     sentstatus? "FIN" : "MID");
1674                 tval = ct->ct_fwhandle;
1675         }
1676         ccb->csio.resid += resid;
1677
1678         /*
1679          * We're here either because intermediate data transfers are done
1680          * and/or the final status CTIO (which may have joined with a
1681          * Data Transfer) is done.
1682          *
1683          * In any case, for this platform, the upper layers figure out
1684          * what to do next, so all we do here is collect status and
1685          * pass information along. Any DMA handles have already been
1686          * freed.
1687          */
1688         if (notify_cam == 0) {
1689                 isp_prt(isp, ISP_LOGTDEBUG0, "  INTER CTIO[0x%x] done", tval);
1690                 return (0);
1691         }
1692
1693         isp_prt(isp, ISP_LOGTDEBUG0, "%s CTIO[0x%x] done",
1694             (sentstatus)? "  FINAL " : "MIDTERM ", tval);
1695
1696         if (!ok) {
1697                 isp_target_putback_atio(ccb);
1698         } else {
1699                 isp_complete_ctio(ccb);
1700
1701         }
1702         return (0);
1703 }
1704
1705 static int
1706 isp_handle_platform_notify_scsi(struct ispsoftc *isp, in_entry_t *inp)
1707 {
1708         return (0);     /* XXXX */
1709 }
1710
1711 static int
1712 isp_handle_platform_notify_fc(struct ispsoftc *isp, in_fcentry_t *inp)
1713 {
1714
1715         switch (inp->in_status) {
1716         case IN_PORT_LOGOUT:
1717                 isp_prt(isp, ISP_LOGWARN, "port logout of iid %d",
1718                    inp->in_iid);
1719                 break;
1720         case IN_PORT_CHANGED:
1721                 isp_prt(isp, ISP_LOGWARN, "port changed for iid %d",
1722                    inp->in_iid);
1723                 break;
1724         case IN_GLOBAL_LOGO:
1725                 isp_prt(isp, ISP_LOGINFO, "all ports logged out");
1726                 break;
1727         case IN_ABORT_TASK:
1728         {
1729                 atio_private_data_t *atp = isp_get_atpd(isp, inp->in_seqid);
1730                 struct ccb_immed_notify *inot = NULL;
1731
1732                 if (atp) {
1733                         tstate_t *tptr = get_lun_statep(isp, 0, atp->lun);
1734                         if (tptr) {
1735                                 inot = (struct ccb_immed_notify *)
1736                                     SLIST_FIRST(&tptr->inots);
1737                                 if (inot) {
1738                                         SLIST_REMOVE_HEAD(&tptr->inots,
1739                                             sim_links.sle);
1740                                 }
1741                         }
1742                         isp_prt(isp, ISP_LOGWARN,
1743                            "abort task RX_ID %x IID %d state %d",
1744                            inp->in_seqid, inp->in_iid, atp->state);
1745                 } else {
1746                         isp_prt(isp, ISP_LOGWARN,
1747                            "abort task RX_ID %x from iid %d, state unknown",
1748                            inp->in_seqid, inp->in_iid);
1749                 }
1750                 if (inot) {
1751                         inot->initiator_id = inp->in_iid;
1752                         inot->sense_len = 0;
1753                         inot->message_args[0] = MSG_ABORT_TAG;
1754                         inot->message_args[1] = inp->in_seqid & 0xff;
1755                         inot->message_args[2] = (inp->in_seqid >> 8) & 0xff;
1756                         inot->ccb_h.status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN;
1757                         xpt_done((union ccb *)inot);
1758                 }
1759                 break;
1760         }
1761         default:
1762                 break;
1763         }
1764         return (0);
1765 }
1766 #endif
1767
1768 static void
1769 isp_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg)
1770 {
1771         struct cam_sim *sim;
1772         struct ispsoftc *isp;
1773
1774         sim = (struct cam_sim *)cbarg;
1775         isp = (struct ispsoftc *) cam_sim_softc(sim);
1776         switch (code) {
1777         case AC_LOST_DEVICE:
1778                 if (IS_SCSI(isp)) {
1779                         u_int16_t oflags, nflags;
1780                         sdparam *sdp = isp->isp_param;
1781                         int tgt;
1782
1783                         tgt = xpt_path_target_id(path);
1784                         if (tgt >= 0) {
1785                                 sdp += cam_sim_bus(sim);
1786                                 ISP_LOCK(isp);
1787                                 nflags = sdp->isp_devparam[tgt].nvrm_flags;
1788 #ifndef ISP_TARGET_MODE
1789                                 nflags &= DPARM_SAFE_DFLT;
1790                                 if (isp->isp_loaded_fw) {
1791                                         nflags |= DPARM_NARROW | DPARM_ASYNC;
1792                                 }
1793 #else
1794                                 nflags = DPARM_DEFAULT;
1795 #endif
1796                                 oflags = sdp->isp_devparam[tgt].goal_flags;
1797                                 sdp->isp_devparam[tgt].goal_flags = nflags;
1798                                 sdp->isp_devparam[tgt].dev_update = 1;
1799                                 isp->isp_update |= (1 << cam_sim_bus(sim));
1800                                 (void) isp_control(isp,
1801                                     ISPCTL_UPDATE_PARAMS, NULL);
1802                                 sdp->isp_devparam[tgt].goal_flags = oflags;
1803                                 ISP_UNLOCK(isp);
1804                         }
1805                 }
1806                 break;
1807         default:
1808                 isp_prt(isp, ISP_LOGWARN, "isp_cam_async: Code 0x%x", code);
1809                 break;
1810         }
1811 }
1812
1813 static void
1814 isp_poll(struct cam_sim *sim)
1815 {
1816         struct ispsoftc *isp = cam_sim_softc(sim);
1817         u_int16_t isr, sema, mbox;
1818
1819         ISP_LOCK(isp);
1820         if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
1821                 isp_intr(isp, isr, sema, mbox);
1822         }
1823         ISP_UNLOCK(isp);
1824 }
1825
1826
1827 static void
1828 isp_watchdog(void *arg)
1829 {
1830         XS_T *xs = arg;
1831         struct ispsoftc *isp = XS_ISP(xs);
1832         u_int32_t handle;
1833         int iok;
1834
1835         /*
1836          * We've decided this command is dead. Make sure we're not trying
1837          * to kill a command that's already dead by getting it's handle and
1838          * and seeing whether it's still alive.
1839          */
1840         ISP_LOCK(isp);
1841         iok = isp->isp_osinfo.intsok;
1842         isp->isp_osinfo.intsok = 0;
1843         handle = isp_find_handle(isp, xs);
1844         if (handle) {
1845                 u_int16_t isr, sema, mbox;
1846
1847                 if (XS_CMD_DONE_P(xs)) {
1848                         isp_prt(isp, ISP_LOGDEBUG1,
1849                             "watchdog found done cmd (handle 0x%x)", handle);
1850                         ISP_UNLOCK(isp);
1851                         return;
1852                 }
1853
1854                 if (XS_CMD_WDOG_P(xs)) {
1855                         isp_prt(isp, ISP_LOGDEBUG2,
1856                             "recursive watchdog (handle 0x%x)", handle);
1857                         ISP_UNLOCK(isp);
1858                         return;
1859                 }
1860
1861                 XS_CMD_S_WDOG(xs);
1862                 if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
1863                         isp_intr(isp, isr, sema, mbox);
1864                 }
1865                 if (XS_CMD_DONE_P(xs)) {
1866                         isp_prt(isp, ISP_LOGDEBUG2,
1867                             "watchdog cleanup for handle 0x%x", handle);
1868                         xpt_done((union ccb *) xs);
1869                 } else if (XS_CMD_GRACE_P(xs)) {
1870                         /*
1871                          * Make sure the command is *really* dead before we
1872                          * release the handle (and DMA resources) for reuse.
1873                          */
1874                         (void) isp_control(isp, ISPCTL_ABORT_CMD, arg);
1875
1876                         /*
1877                          * After this point, the comamnd is really dead.
1878                          */
1879                         if (XS_XFRLEN(xs)) {
1880                                 ISP_DMAFREE(isp, xs, handle);
1881                         } 
1882                         isp_destroy_handle(isp, handle);
1883                         xpt_print_path(xs->ccb_h.path);
1884                         isp_prt(isp, ISP_LOGWARN,
1885                             "watchdog timeout for handle 0x%x", handle);
1886                         XS_SETERR(xs, CAM_CMD_TIMEOUT);
1887                         XS_CMD_C_WDOG(xs);
1888                         isp_done(xs);
1889                 } else {
1890                         u_int16_t nxti, optr;
1891                         ispreq_t local, *mp= &local, *qe;
1892
1893                         XS_CMD_C_WDOG(xs);
1894                         callout_reset(&xs->ccb_h.timeout_ch, hz,
1895                                       isp_watchdog, xs);
1896                         if (isp_getrqentry(isp, &nxti, &optr, (void **) &qe)) {
1897                                 ISP_UNLOCK(isp);
1898                                 return;
1899                         }
1900                         XS_CMD_S_GRACE(xs);
1901                         MEMZERO((void *) mp, sizeof (*mp));
1902                         mp->req_header.rqs_entry_count = 1;
1903                         mp->req_header.rqs_entry_type = RQSTYPE_MARKER;
1904                         mp->req_modifier = SYNC_ALL;
1905                         mp->req_target = XS_CHANNEL(xs) << 7;
1906                         isp_put_request(isp, mp, qe);
1907                         ISP_ADD_REQUEST(isp, nxti);
1908                 }
1909         } else {
1910                 isp_prt(isp, ISP_LOGDEBUG2, "watchdog with no command");
1911         }
1912         isp->isp_osinfo.intsok = iok;
1913         ISP_UNLOCK(isp);
1914 }
1915
1916 static void
1917 isp_kthread(void *arg)
1918 {
1919         struct ispsoftc *isp = arg;
1920
1921         crit_enter();
1922         isp->isp_osinfo.intsok = 1;
1923
1924         /*
1925          * The first loop is for our usage where we have yet to have
1926          * gotten good fibre channel state.
1927          */
1928         for (;;) {
1929                 int wasfrozen;
1930
1931                 isp_prt(isp, ISP_LOGDEBUG0, "kthread: checking FC state");
1932                 while (isp_fc_runstate(isp, 2 * 1000000) != 0) {
1933                         isp_prt(isp, ISP_LOGDEBUG0, "kthread: FC state ungood");
1934                         if (FCPARAM(isp)->isp_fwstate != FW_READY ||
1935                             FCPARAM(isp)->isp_loopstate < LOOP_PDB_RCVD) {
1936                                 if (FCPARAM(isp)->loop_seen_once == 0 ||
1937                                     isp->isp_osinfo.ktmature == 0) {
1938                                         break;
1939                                 }
1940                         }
1941                         tsleep(isp_kthread, 0, "isp_fcthrd", hz);
1942
1943                 }
1944
1945                 /*
1946                  * Even if we didn't get good loop state we may be
1947                  * unfreezing the SIMQ so that we can kill off
1948                  * commands (if we've never seen loop before, for example).
1949                  */
1950                 isp->isp_osinfo.ktmature = 1;
1951                 wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN;
1952                 isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN;
1953                 if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
1954                         isp_prt(isp, ISP_LOGDEBUG0, "kthread: releasing simq");
1955                         ISPLOCK_2_CAMLOCK(isp);
1956                         xpt_release_simq(isp->isp_sim, 1);
1957                         CAMLOCK_2_ISPLOCK(isp);
1958                 }
1959                 tsleep(&isp->isp_osinfo.kthread, 0, "isp_fc_worker", 0);
1960                 isp_prt(isp, ISP_LOGDEBUG0, "kthread: waiting until called");
1961         }
1962 }
1963
1964 static void
1965 isp_action(struct cam_sim *sim, union ccb *ccb)
1966 {
1967         int bus, tgt, error;
1968         struct ispsoftc *isp;
1969         struct ccb_trans_settings *cts;
1970
1971         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
1972         
1973         isp = (struct ispsoftc *)cam_sim_softc(sim);
1974         ccb->ccb_h.sim_priv.entries[0].field = 0;
1975         ccb->ccb_h.sim_priv.entries[1].ptr = isp;
1976         if (isp->isp_state != ISP_RUNSTATE &&
1977             ccb->ccb_h.func_code == XPT_SCSI_IO) {
1978                 CAMLOCK_2_ISPLOCK(isp);
1979                 isp_init(isp);
1980                 if (isp->isp_state != ISP_INITSTATE) {
1981                         ISP_UNLOCK(isp);
1982                         /*
1983                          * Lie. Say it was a selection timeout.
1984                          */
1985                         ccb->ccb_h.status = CAM_SEL_TIMEOUT | CAM_DEV_QFRZN;
1986                         xpt_freeze_devq(ccb->ccb_h.path, 1);
1987                         xpt_done(ccb);
1988                         return;
1989                 }
1990                 isp->isp_state = ISP_RUNSTATE;
1991                 ISPLOCK_2_CAMLOCK(isp);
1992         }
1993         isp_prt(isp, ISP_LOGDEBUG2, "isp_action code %x", ccb->ccb_h.func_code);
1994
1995
1996         switch (ccb->ccb_h.func_code) {
1997         case XPT_SCSI_IO:       /* Execute the requested I/O operation */
1998                 /*
1999                  * Do a couple of preliminary checks...
2000                  */
2001                 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
2002                         if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
2003                                 ccb->ccb_h.status = CAM_REQ_INVALID;
2004                                 xpt_done(ccb);
2005                                 break;
2006                         }
2007                 }
2008 #ifdef  DIAGNOSTIC
2009                 if (ccb->ccb_h.target_id > (ISP_MAX_TARGETS(isp) - 1)) {
2010                         ccb->ccb_h.status = CAM_PATH_INVALID;
2011                 } else if (ccb->ccb_h.target_lun > (ISP_MAX_LUNS(isp) - 1)) {
2012                         ccb->ccb_h.status = CAM_PATH_INVALID;
2013                 }
2014                 if (ccb->ccb_h.status == CAM_PATH_INVALID) {
2015                         isp_prt(isp, ISP_LOGERR,
2016                             "invalid tgt/lun (%d.%d) in XPT_SCSI_IO",
2017                             ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
2018                         xpt_done(ccb);
2019                         break;
2020                 }
2021 #endif
2022                 ((struct ccb_scsiio *) ccb)->scsi_status = SCSI_STATUS_OK;
2023                 CAMLOCK_2_ISPLOCK(isp);
2024                 error = isp_start((XS_T *) ccb);
2025                 switch (error) {
2026                 case CMD_QUEUED:
2027                         ccb->ccb_h.status |= CAM_SIM_QUEUED;
2028                         if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
2029                                 u_int64_t ticks = (u_int64_t) hz;
2030                                 if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT)
2031                                         ticks = 60 * 1000 * ticks;
2032                                 else
2033                                         ticks = ccb->ccb_h.timeout * hz;
2034                                 ticks = ((ticks + 999) / 1000) + hz + hz;
2035                                 if (ticks >= 0x80000000) {
2036                                         isp_prt(isp, ISP_LOGERR,
2037                                             "timeout overflow");
2038                                         ticks = 0x7fffffff;
2039                                 }
2040                                 callout_reset(&ccb->ccb_h.timeout_ch, ticks,
2041                                     isp_watchdog, ccb);
2042                         }
2043                         ISPLOCK_2_CAMLOCK(isp);
2044                         break;
2045                 case CMD_RQLATER:
2046                         /*
2047                          * This can only happen for Fibre Channel
2048                          */
2049                         KASSERT((IS_FC(isp)), ("CMD_RQLATER for FC only"));
2050                         if (FCPARAM(isp)->loop_seen_once == 0 &&
2051                             isp->isp_osinfo.ktmature) {
2052                                 ISPLOCK_2_CAMLOCK(isp);
2053                                 XS_SETERR(ccb, CAM_SEL_TIMEOUT);
2054                                 xpt_done(ccb);
2055                                 break;
2056                         }
2057                         wakeup(&isp->isp_osinfo.kthread);
2058                         isp_freeze_loopdown(isp, "isp_action(RQLATER)");
2059                         isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
2060                         XS_SETERR(ccb, CAM_REQUEUE_REQ);
2061                         ISPLOCK_2_CAMLOCK(isp);
2062                         xpt_done(ccb);
2063                         break;
2064                 case CMD_EAGAIN:
2065                         XS_SETERR(ccb, CAM_REQUEUE_REQ);
2066                         ISPLOCK_2_CAMLOCK(isp);
2067                         xpt_done(ccb);
2068                         break;
2069                 case CMD_COMPLETE:
2070                         isp_done((struct ccb_scsiio *) ccb);
2071                         ISPLOCK_2_CAMLOCK(isp);
2072                         break;
2073                 default:
2074                         isp_prt(isp, ISP_LOGERR,
2075                             "What's this? 0x%x at %d in file %s",
2076                             error, __LINE__, __FILE__);
2077                         XS_SETERR(ccb, CAM_REQ_CMP_ERR);
2078                         xpt_done(ccb);
2079                         ISPLOCK_2_CAMLOCK(isp);
2080                 }
2081                 break;
2082
2083 #ifdef  ISP_TARGET_MODE
2084         case XPT_EN_LUN:                /* Enable LUN as a target */
2085         {
2086                 int iok;
2087                 CAMLOCK_2_ISPLOCK(isp);
2088                 iok = isp->isp_osinfo.intsok;
2089                 isp->isp_osinfo.intsok = 0;
2090                 isp_en_lun(isp, ccb);
2091                 isp->isp_osinfo.intsok = iok;
2092                 ISPLOCK_2_CAMLOCK(isp);
2093                 xpt_done(ccb);
2094                 break;
2095         }
2096         case XPT_NOTIFY_ACK:            /* recycle notify ack */
2097         case XPT_IMMED_NOTIFY:          /* Add Immediate Notify Resource */
2098         case XPT_ACCEPT_TARGET_IO:      /* Add Accept Target IO Resource */
2099         {
2100                 tstate_t *tptr =
2101                     get_lun_statep(isp, XS_CHANNEL(ccb), ccb->ccb_h.target_lun);
2102                 if (tptr == NULL) {
2103                         ccb->ccb_h.status = CAM_LUN_INVALID;
2104                         xpt_done(ccb);
2105                         break;
2106                 }
2107                 ccb->ccb_h.sim_priv.entries[0].field = 0;
2108                 ccb->ccb_h.sim_priv.entries[1].ptr = isp;
2109                 ccb->ccb_h.flags = 0;
2110
2111                 CAMLOCK_2_ISPLOCK(isp);
2112                 if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
2113                         /*
2114                          * Note that the command itself may not be done-
2115                          * it may not even have had the first CTIO sent.
2116                          */
2117                         tptr->atio_count++;
2118                         isp_prt(isp, ISP_LOGTDEBUG0,
2119                             "Put FREE ATIO2, lun %d, count now %d",
2120                             ccb->ccb_h.target_lun, tptr->atio_count);
2121                         SLIST_INSERT_HEAD(&tptr->atios, &ccb->ccb_h,
2122                             sim_links.sle);
2123                 } else if (ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
2124                         SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h,
2125                             sim_links.sle);
2126                 } else {
2127                         ;
2128                 }
2129                 rls_lun_statep(isp, tptr);
2130                 ccb->ccb_h.status = CAM_REQ_INPROG;
2131                 ISPLOCK_2_CAMLOCK(isp);
2132                 break;
2133         }
2134         case XPT_CONT_TARGET_IO:
2135         {
2136                 CAMLOCK_2_ISPLOCK(isp);
2137                 ccb->ccb_h.status = isp_target_start_ctio(isp, ccb);
2138                 if (ccb->ccb_h.status != CAM_REQ_INPROG) {
2139                         isp_prt(isp, ISP_LOGWARN,
2140                             "XPT_CONT_TARGET_IO: status 0x%x",
2141                             ccb->ccb_h.status);
2142                         XS_SETERR(ccb, CAM_REQUEUE_REQ);
2143                         ISPLOCK_2_CAMLOCK(isp);
2144                         xpt_done(ccb);
2145                 } else {
2146                         ISPLOCK_2_CAMLOCK(isp);
2147                         ccb->ccb_h.status |= CAM_SIM_QUEUED;
2148                 }
2149                 break;
2150         }
2151 #endif
2152         case XPT_RESET_DEV:             /* BDR the specified SCSI device */
2153
2154                 bus = cam_sim_bus(xpt_path_sim(ccb->ccb_h.path));
2155                 tgt = ccb->ccb_h.target_id;
2156                 tgt |= (bus << 16);
2157
2158                 CAMLOCK_2_ISPLOCK(isp);
2159                 error = isp_control(isp, ISPCTL_RESET_DEV, &tgt);
2160                 ISPLOCK_2_CAMLOCK(isp);
2161                 if (error) {
2162                         ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2163                 } else {
2164                         ccb->ccb_h.status = CAM_REQ_CMP;
2165                 }
2166                 xpt_done(ccb);
2167                 break;
2168         case XPT_ABORT:                 /* Abort the specified CCB */
2169         {
2170                 union ccb *accb = ccb->cab.abort_ccb;
2171                 CAMLOCK_2_ISPLOCK(isp);
2172                 switch (accb->ccb_h.func_code) {
2173 #ifdef  ISP_TARGET_MODE
2174                 case XPT_ACCEPT_TARGET_IO:
2175                 case XPT_IMMED_NOTIFY:
2176                         ccb->ccb_h.status = isp_abort_tgt_ccb(isp, ccb);
2177                         break;
2178                 case XPT_CONT_TARGET_IO:
2179                         isp_prt(isp, ISP_LOGERR, "cannot abort CTIOs yet");
2180                         ccb->ccb_h.status = CAM_UA_ABORT;
2181                         break;
2182 #endif
2183                 case XPT_SCSI_IO:
2184                         error = isp_control(isp, ISPCTL_ABORT_CMD, ccb);
2185                         if (error) {
2186                                 ccb->ccb_h.status = CAM_UA_ABORT;
2187                         } else {
2188                                 ccb->ccb_h.status = CAM_REQ_CMP;
2189                         }
2190                         break;
2191                 default:
2192                         ccb->ccb_h.status = CAM_REQ_INVALID;
2193                         break;
2194                 }
2195                 ISPLOCK_2_CAMLOCK(isp);
2196                 xpt_done(ccb);
2197                 break;
2198         }
2199 #define IS_CURRENT_SETTINGS(c)  (c->type == CTS_TYPE_CURRENT_SETTINGS)
2200         case XPT_SET_TRAN_SETTINGS:     /* Nexus Settings */
2201                 cts = &ccb->cts;
2202                 if (!IS_CURRENT_SETTINGS(cts)) {
2203                         ccb->ccb_h.status = CAM_REQ_INVALID;
2204                         xpt_done(ccb);
2205                         break;
2206                 }
2207                 tgt = cts->ccb_h.target_id;
2208                 CAMLOCK_2_ISPLOCK(isp);
2209                 if (IS_SCSI(isp)) {
2210                         struct ccb_trans_settings_scsi *scsi =
2211                             &cts->proto_specific.scsi;
2212                         struct ccb_trans_settings_spi *spi =
2213                             &cts->xport_specific.spi;
2214                         sdparam *sdp = isp->isp_param;
2215                         u_int16_t *dptr;
2216
2217                         bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
2218                         sdp += bus;
2219                         /*
2220                          * We always update (internally) from dev_flags
2221                          * so any request to change settings just gets
2222                          * vectored to that location.
2223                          */
2224                         dptr = &sdp->isp_devparam[tgt].goal_flags;
2225
2226                         if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
2227                                 if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
2228                                         *dptr |= DPARM_DISC;
2229                                 else
2230                                         *dptr &= ~DPARM_DISC;
2231                         }
2232
2233                         if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
2234                                 if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
2235                                         *dptr |= DPARM_TQING;
2236                                 else
2237                                         *dptr &= ~DPARM_TQING;
2238                         }
2239
2240                         if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
2241                                 if (spi->bus_width == MSG_EXT_WDTR_BUS_16_BIT)
2242                                         *dptr |= DPARM_WIDE;
2243                                 else
2244                                         *dptr &= ~DPARM_WIDE;
2245                         }
2246
2247                         /*
2248                          * XXX: FIX ME
2249                          */
2250                         if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) &&
2251                             (spi->valid & CTS_SPI_VALID_SYNC_RATE)) {
2252                                 *dptr |= DPARM_SYNC;
2253                                 isp_prt(isp, ISP_LOGDEBUG0,
2254                                    "enabling synchronous mode, but ignoring "
2255                                    "setting to period 0x%x offset 0x%x",
2256                                    spi->sync_period, spi->sync_offset);
2257                         } else if (spi->sync_period && spi->sync_offset) {
2258                                 *dptr |= DPARM_SYNC;
2259                                 isp_prt(isp, ISP_LOGDEBUG0,
2260                                    "enabling synchronous mode (1), but ignoring"
2261                                    " setting to period 0x%x offset 0x%x",
2262                                    spi->sync_period, spi->sync_offset);
2263                         } else {
2264                                 *dptr &= ~DPARM_SYNC;
2265                         }
2266                         isp_prt(isp, ISP_LOGDEBUG0,
2267                             "SET bus %d targ %d to flags %x off %x per %x",
2268                             bus, tgt, sdp->isp_devparam[tgt].goal_flags,
2269                             sdp->isp_devparam[tgt].goal_offset,
2270                             sdp->isp_devparam[tgt].goal_period);
2271                         sdp->isp_devparam[tgt].dev_update = 1;
2272                         isp->isp_update |= (1 << bus);
2273                 }
2274                 ISPLOCK_2_CAMLOCK(isp);
2275                 ccb->ccb_h.status = CAM_REQ_CMP;
2276                 xpt_done(ccb);
2277                 break;
2278         case XPT_GET_TRAN_SETTINGS:
2279                 cts = &ccb->cts;
2280                 tgt = cts->ccb_h.target_id;
2281                 CAMLOCK_2_ISPLOCK(isp);
2282                 if (IS_FC(isp)) {
2283                         fcparam *fcp = isp->isp_param;
2284                         struct ccb_trans_settings_fc *fc =
2285                             &cts->xport_specific.fc;
2286
2287                         cts->protocol = PROTO_SCSI;
2288                         cts->protocol_version = SCSI_REV_2;
2289                         cts->transport = XPORT_FC;
2290                         cts->transport_version = 0;
2291
2292                         fc->valid = CTS_FC_VALID_SPEED;
2293                         fc->bitrate = 100000;
2294                         if (tgt > 0 && tgt < MAX_FC_TARG) {
2295                                 struct lportdb *lp = &fcp->portdb[tgt];
2296                                 fc->wwnn = lp->node_wwn;
2297                                 fc->wwpn = lp->port_wwn;
2298                                 fc->port = lp->portid;
2299                                 fc->valid |= CTS_FC_VALID_WWNN |
2300                                     CTS_FC_VALID_WWPN | CTS_FC_VALID_PORT;
2301                         }
2302                 } else {
2303                         struct ccb_trans_settings_scsi *scsi =
2304                             &cts->proto_specific.scsi;
2305                         struct ccb_trans_settings_spi *spi =
2306                             &cts->xport_specific.spi;
2307                         sdparam *sdp = isp->isp_param;
2308                         int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
2309                         u_int16_t dval, pval, oval;
2310
2311                         sdp += bus;
2312
2313                         if (IS_CURRENT_SETTINGS(cts)) {
2314                                 sdp->isp_devparam[tgt].dev_refresh = 1;
2315                                 isp->isp_update |= (1 << bus);
2316                                 (void) isp_control(isp, ISPCTL_UPDATE_PARAMS,
2317                                     NULL);
2318                                 dval = sdp->isp_devparam[tgt].actv_flags;
2319                                 oval = sdp->isp_devparam[tgt].actv_offset;
2320                                 pval = sdp->isp_devparam[tgt].actv_period;
2321                         } else {
2322                                 dval = sdp->isp_devparam[tgt].nvrm_flags;
2323                                 oval = sdp->isp_devparam[tgt].nvrm_offset;
2324                                 pval = sdp->isp_devparam[tgt].nvrm_period;
2325                         }
2326
2327                         cts->protocol = PROTO_SCSI;
2328                         cts->protocol_version = SCSI_REV_2;
2329                         cts->transport = XPORT_SPI;
2330                         cts->transport_version = 2;
2331
2332                         scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
2333                         spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
2334                         if (dval & DPARM_DISC) {
2335                                 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
2336                         }
2337                         if (dval & DPARM_TQING) {
2338                                 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
2339                         }
2340                         if ((dval & DPARM_SYNC) && oval != 0) {
2341                                 spi->sync_offset = oval;
2342                                 spi->sync_period = pval;
2343                                 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
2344                                 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
2345                         }
2346                         spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
2347                         if (dval & DPARM_WIDE) {
2348                                 spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
2349                         } else {
2350                                 spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
2351                         }
2352                         if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
2353                                 scsi->valid = CTS_SCSI_VALID_TQ;
2354                                 spi->valid |= CTS_SPI_VALID_DISC;
2355                         } else {
2356                                 scsi->valid = 0;
2357                         }
2358                         isp_prt(isp, ISP_LOGDEBUG0,
2359                             "GET %s bus %d targ %d to flags %x off %x per %x",
2360                             IS_CURRENT_SETTINGS(cts)? "ACTIVE" : "NVRAM",
2361                             bus, tgt, dval, oval, pval);
2362                 }
2363                 ISPLOCK_2_CAMLOCK(isp);
2364                 ccb->ccb_h.status = CAM_REQ_CMP;
2365                 xpt_done(ccb);
2366                 break;
2367
2368         case XPT_CALC_GEOMETRY:
2369         {
2370                 struct ccb_calc_geometry *ccg;
2371                 u_int32_t secs_per_cylinder;
2372                 u_int32_t size_mb;
2373
2374                 ccg = &ccb->ccg;
2375                 if (ccg->block_size == 0) {
2376                         isp_prt(isp, ISP_LOGERR,
2377                             "%d.%d XPT_CALC_GEOMETRY block size 0?",
2378                             ccg->ccb_h.target_id, ccg->ccb_h.target_lun);
2379                         ccb->ccb_h.status = CAM_REQ_INVALID;
2380                         xpt_done(ccb);
2381                         break;
2382                 }
2383                 size_mb = ccg->volume_size /((1024L * 1024L) / ccg->block_size);
2384                 if (size_mb > 1024) {
2385                         ccg->heads = 255;
2386                         ccg->secs_per_track = 63;
2387                 } else {
2388                         ccg->heads = 64;
2389                         ccg->secs_per_track = 32;
2390                 }
2391                 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
2392                 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
2393                 ccb->ccb_h.status = CAM_REQ_CMP;
2394                 xpt_done(ccb);
2395                 break;
2396         }
2397         case XPT_RESET_BUS:             /* Reset the specified bus */
2398                 bus = cam_sim_bus(sim);
2399                 CAMLOCK_2_ISPLOCK(isp);
2400                 error = isp_control(isp, ISPCTL_RESET_BUS, &bus);
2401                 ISPLOCK_2_CAMLOCK(isp);
2402                 if (error)
2403                         ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2404                 else {
2405                         if (cam_sim_bus(sim) && isp->isp_path2 != NULL)
2406                                 xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
2407                         else if (isp->isp_path != NULL)
2408                                 xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
2409                         ccb->ccb_h.status = CAM_REQ_CMP;
2410                 }
2411                 xpt_done(ccb);
2412                 break;
2413
2414         case XPT_TERM_IO:               /* Terminate the I/O process */
2415                 ccb->ccb_h.status = CAM_REQ_INVALID;
2416                 xpt_done(ccb);
2417                 break;
2418
2419         case XPT_PATH_INQ:              /* Path routing inquiry */
2420         {
2421                 struct ccb_pathinq *cpi = &ccb->cpi;
2422
2423                 cpi->version_num = 1;
2424 #ifdef  ISP_TARGET_MODE
2425                 cpi->target_sprt = PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO;
2426 #else
2427                 cpi->target_sprt = 0;
2428 #endif
2429                 cpi->hba_eng_cnt = 0;
2430                 cpi->max_target = ISP_MAX_TARGETS(isp) - 1;
2431                 cpi->max_lun = ISP_MAX_LUNS(isp) - 1;
2432                 cpi->bus_id = cam_sim_bus(sim);
2433                 if (IS_FC(isp)) {
2434                         cpi->hba_misc = PIM_NOBUSRESET;
2435                         /*
2436                          * Because our loop ID can shift from time to time,
2437                          * make our initiator ID out of range of our bus.
2438                          */
2439                         cpi->initiator_id = cpi->max_target + 1;
2440
2441                         /*
2442                          * Set base transfer capabilities for Fibre Channel.
2443                          * Technically not correct because we don't know
2444                          * what media we're running on top of- but we'll
2445                          * look good if we always say 100MB/s.
2446                          */
2447                         if (FCPARAM(isp)->isp_gbspeed == 2)
2448                                 cpi->base_transfer_speed = 200000;
2449                         else
2450                                 cpi->base_transfer_speed = 100000;
2451                         cpi->hba_inquiry = PI_TAG_ABLE;
2452                         cpi->transport = XPORT_FC;
2453                         cpi->transport_version = 0;     /* WHAT'S THIS FOR? */
2454                 } else {
2455                         sdparam *sdp = isp->isp_param;
2456                         sdp += cam_sim_bus(xpt_path_sim(cpi->ccb_h.path));
2457                         cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
2458                         cpi->hba_misc = 0;
2459                         cpi->initiator_id = sdp->isp_initiator_id;
2460                         cpi->base_transfer_speed = 3300;
2461                         cpi->transport = XPORT_SPI;
2462                         cpi->transport_version = 2;     /* WHAT'S THIS FOR? */
2463                 }
2464                 cpi->protocol = PROTO_SCSI;
2465                 cpi->protocol_version = SCSI_REV_2;
2466                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2467                 strncpy(cpi->hba_vid, "Qlogic", HBA_IDLEN);
2468                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2469                 cpi->unit_number = cam_sim_unit(sim);
2470                 cpi->ccb_h.status = CAM_REQ_CMP;
2471                 xpt_done(ccb);
2472                 break;
2473         }
2474         default:
2475                 ccb->ccb_h.status = CAM_REQ_INVALID;
2476                 xpt_done(ccb);
2477                 break;
2478         }
2479 }
2480
2481 #define ISPDDB  (CAM_DEBUG_INFO|CAM_DEBUG_TRACE|CAM_DEBUG_CDB)
2482 void
2483 isp_done(struct ccb_scsiio *sccb)
2484 {
2485         struct ispsoftc *isp = XS_ISP(sccb);
2486
2487         if (XS_NOERR(sccb))
2488                 XS_SETERR(sccb, CAM_REQ_CMP);
2489
2490         if ((sccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP &&
2491             (sccb->scsi_status != SCSI_STATUS_OK)) {
2492                 sccb->ccb_h.status &= ~CAM_STATUS_MASK;
2493                 if ((sccb->scsi_status == SCSI_STATUS_CHECK_COND) && 
2494                     (sccb->ccb_h.status & CAM_AUTOSNS_VALID) == 0) {
2495                         sccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
2496                 } else {
2497                         sccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
2498                 }
2499         }
2500
2501         sccb->ccb_h.status &= ~CAM_SIM_QUEUED;
2502         if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2503                 if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2504                         sccb->ccb_h.status |= CAM_DEV_QFRZN;
2505                         xpt_freeze_devq(sccb->ccb_h.path, 1);
2506                         isp_prt(isp, ISP_LOGDEBUG0,
2507                             "freeze devq %d.%d cam sts %x scsi sts %x",
2508                             sccb->ccb_h.target_id, sccb->ccb_h.target_lun,
2509                             sccb->ccb_h.status, sccb->scsi_status);
2510                 }
2511         }
2512
2513         if ((CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB)) &&
2514             (sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
2515                 xpt_print_path(sccb->ccb_h.path);
2516                 isp_prt(isp, ISP_LOGINFO, 
2517                     "cam completion status 0x%x", sccb->ccb_h.status);
2518         }
2519
2520         XS_CMD_S_DONE(sccb);
2521         if (XS_CMD_WDOG_P(sccb) == 0) {
2522                 callout_stop(&sccb->ccb_h.timeout_ch);
2523                 if (XS_CMD_GRACE_P(sccb)) {
2524                         isp_prt(isp, ISP_LOGDEBUG2,
2525                             "finished command on borrowed time");
2526                 }
2527                 XS_CMD_S_CLEAR(sccb);
2528                 ISPLOCK_2_CAMLOCK(isp);
2529                 xpt_done((union ccb *) sccb);
2530                 CAMLOCK_2_ISPLOCK(isp);
2531         }
2532 }
2533
2534 int
2535 isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
2536 {
2537         int bus, rv = 0;
2538         switch (cmd) {
2539         case ISPASYNC_NEW_TGT_PARAMS:
2540         {
2541                 struct ccb_trans_settings_scsi *scsi;
2542                 struct ccb_trans_settings_spi *spi;
2543                 int flags, tgt;
2544                 sdparam *sdp = isp->isp_param;
2545                 struct ccb_trans_settings cts;
2546                 struct cam_path *tmppath;
2547
2548                 bzero(&cts, sizeof (struct ccb_trans_settings));
2549
2550                 tgt = *((int *)arg);
2551                 bus = (tgt >> 16) & 0xffff;
2552                 tgt &= 0xffff;
2553                 sdp += bus;
2554                 ISPLOCK_2_CAMLOCK(isp);
2555                 if (xpt_create_path(&tmppath, NULL,
2556                     cam_sim_path(bus? isp->isp_sim2 : isp->isp_sim),
2557                     tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
2558                         CAMLOCK_2_ISPLOCK(isp);
2559                         isp_prt(isp, ISP_LOGWARN,
2560                             "isp_async cannot make temp path for %d.%d",
2561                             tgt, bus);
2562                         rv = -1;
2563                         break;
2564                 }
2565                 CAMLOCK_2_ISPLOCK(isp);
2566                 flags = sdp->isp_devparam[tgt].actv_flags;
2567                 cts.type = CTS_TYPE_CURRENT_SETTINGS;
2568                 cts.protocol = PROTO_SCSI;
2569                 cts.transport = XPORT_SPI;
2570
2571                 scsi = &cts.proto_specific.scsi;
2572                 spi = &cts.xport_specific.spi;
2573
2574                 if (flags & DPARM_TQING) {
2575                         scsi->valid |= CTS_SCSI_VALID_TQ;
2576                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
2577                 }
2578
2579                 if (flags & DPARM_DISC) {
2580                         spi->valid |= CTS_SPI_VALID_DISC;
2581                         spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
2582                 }
2583                 spi->flags |= CTS_SPI_VALID_BUS_WIDTH;
2584                 if (flags & DPARM_WIDE) {
2585                         spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
2586                 } else {
2587                         spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
2588                 }
2589                 if (flags & DPARM_SYNC) {
2590                         spi->valid |= CTS_SPI_VALID_SYNC_RATE;
2591                         spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
2592                         spi->sync_period = sdp->isp_devparam[tgt].actv_period;
2593                         spi->sync_offset = sdp->isp_devparam[tgt].actv_offset;
2594                 }
2595                 isp_prt(isp, ISP_LOGDEBUG2,
2596                     "NEW_TGT_PARAMS bus %d tgt %d period %x offset %x flags %x",
2597                     bus, tgt, sdp->isp_devparam[tgt].actv_period,
2598                     sdp->isp_devparam[tgt].actv_offset, flags);
2599                 xpt_setup_ccb(&cts.ccb_h, tmppath, 1);
2600                 ISPLOCK_2_CAMLOCK(isp);
2601                 xpt_async(AC_TRANSFER_NEG, tmppath, &cts);
2602                 xpt_free_path(tmppath);
2603                 CAMLOCK_2_ISPLOCK(isp);
2604                 break;
2605         }
2606         case ISPASYNC_BUS_RESET:
2607                 bus = *((int *)arg);
2608                 isp_prt(isp, ISP_LOGINFO, "SCSI bus reset on bus %d detected",
2609                     bus);
2610                 if (bus > 0 && isp->isp_path2) {
2611                         ISPLOCK_2_CAMLOCK(isp);
2612                         xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
2613                         CAMLOCK_2_ISPLOCK(isp);
2614                 } else if (isp->isp_path) {
2615                         ISPLOCK_2_CAMLOCK(isp);
2616                         xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
2617                         CAMLOCK_2_ISPLOCK(isp);
2618                 }
2619                 break;
2620         case ISPASYNC_LIP:
2621                 if (isp->isp_path) {
2622                         isp_freeze_loopdown(isp, "ISPASYNC_LIP");
2623                 }
2624                 isp_prt(isp, ISP_LOGINFO, "LIP Received");
2625                 break;
2626         case ISPASYNC_LOOP_RESET:
2627                 if (isp->isp_path) {
2628                         isp_freeze_loopdown(isp, "ISPASYNC_LOOP_RESET");
2629                 }
2630                 isp_prt(isp, ISP_LOGINFO, "Loop Reset Received");
2631                 break;
2632         case ISPASYNC_LOOP_DOWN:
2633                 if (isp->isp_path) {
2634                         isp_freeze_loopdown(isp, "ISPASYNC_LOOP_DOWN");
2635                 }
2636                 isp_prt(isp, ISP_LOGINFO, "Loop DOWN");
2637                 break;
2638         case ISPASYNC_LOOP_UP:
2639                 /*
2640                  * Now we just note that Loop has come up. We don't
2641                  * actually do anything because we're waiting for a
2642                  * Change Notify before activating the FC cleanup
2643                  * thread to look at the state of the loop again.
2644                  */
2645                 isp_prt(isp, ISP_LOGINFO, "Loop UP");
2646                 break;
2647         case ISPASYNC_PROMENADE:
2648         {
2649                 struct cam_path *tmppath;
2650                 const char *fmt = "Target %d (Loop 0x%x) Port ID 0x%x "
2651                     "(role %s) %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x";
2652                 static const char *roles[4] = {
2653                     "(none)", "Target", "Initiator", "Target/Initiator"
2654                 };
2655                 fcparam *fcp = isp->isp_param;
2656                 int tgt = *((int *) arg);
2657                 struct lportdb *lp = &fcp->portdb[tgt]; 
2658
2659                 isp_prt(isp, ISP_LOGINFO, fmt, tgt, lp->loopid, lp->portid,
2660                     roles[lp->roles & 0x3],
2661                     (lp->valid)? "Arrived" : "Departed",
2662                     (u_int32_t) (lp->port_wwn >> 32),
2663                     (u_int32_t) (lp->port_wwn & 0xffffffffLL),
2664                     (u_int32_t) (lp->node_wwn >> 32),
2665                     (u_int32_t) (lp->node_wwn & 0xffffffffLL));
2666
2667                 if (xpt_create_path(&tmppath, NULL, cam_sim_path(isp->isp_sim),
2668                     (target_id_t)tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
2669                         break;
2670                 }
2671                 if (lp->valid && (lp->roles &
2672                     (SVC3_INI_ROLE >> SVC3_ROLE_SHIFT))) {
2673                         ISPLOCK_2_CAMLOCK(isp);
2674                         xpt_async(AC_FOUND_DEVICE, tmppath, NULL);
2675                 } else {
2676                         ISPLOCK_2_CAMLOCK(isp);
2677                         xpt_async(AC_LOST_DEVICE, tmppath, NULL);
2678                 }
2679                 CAMLOCK_2_ISPLOCK(isp);
2680                 xpt_free_path(tmppath);
2681                 break;
2682         }
2683         case ISPASYNC_CHANGE_NOTIFY:
2684                 if (arg == ISPASYNC_CHANGE_PDB) {
2685                         isp_prt(isp, ISP_LOGINFO,
2686                             "Port Database Changed");
2687                 } else if (arg == ISPASYNC_CHANGE_SNS) {
2688                         isp_prt(isp, ISP_LOGINFO,
2689                             "Name Server Database Changed");
2690                 }
2691                 wakeup(&isp->isp_osinfo.kthread);
2692                 break;
2693         case ISPASYNC_FABRIC_DEV:
2694         {
2695                 int target, base, lim;
2696                 fcparam *fcp = isp->isp_param;
2697                 struct lportdb *lp = NULL;
2698                 struct lportdb *clp = (struct lportdb *) arg;
2699                 char *pt;
2700
2701                 switch (clp->port_type) {
2702                 case 1:
2703                         pt = "   N_Port";
2704                         break;
2705                 case 2:
2706                         pt = "  NL_Port";
2707                         break;
2708                 case 3:
2709                         pt = "F/NL_Port";
2710                         break;
2711                 case 0x7f:
2712                         pt = "  Nx_Port";
2713                         break;
2714                 case 0x81:
2715                         pt = "  F_port";
2716                         break;
2717                 case 0x82:
2718                         pt = "  FL_Port";
2719                         break;
2720                 case 0x84:
2721                         pt = "   E_port";
2722                         break;
2723                 default:
2724                         pt = " ";
2725                         break;
2726                 }
2727
2728                 isp_prt(isp, ISP_LOGINFO,
2729                     "%s Fabric Device @ PortID 0x%x", pt, clp->portid);
2730
2731                 /*
2732                  * If we don't have an initiator role we bail.
2733                  *
2734                  * We just use ISPASYNC_FABRIC_DEV for announcement purposes.
2735                  */
2736
2737                 if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) {
2738                         break;
2739                 }
2740
2741                 /*
2742                  * Is this entry for us? If so, we bail.
2743                  */
2744
2745                 if (fcp->isp_portid == clp->portid) {
2746                         break;
2747                 }
2748
2749                 /*
2750                  * Else, the default policy is to find room for it in
2751                  * our local port database. Later, when we execute
2752                  * the call to isp_pdb_sync either this newly arrived
2753                  * or already logged in device will be (re)announced.
2754                  */
2755
2756                 if (fcp->isp_topo == TOPO_FL_PORT)
2757                         base = FC_SNS_ID+1;
2758                 else
2759                         base = 0;
2760
2761                 if (fcp->isp_topo == TOPO_N_PORT)
2762                         lim = 1;
2763                 else
2764                         lim = MAX_FC_TARG;
2765
2766                 /*
2767                  * Is it already in our list?
2768                  */
2769                 for (target = base; target < lim; target++) {
2770                         if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
2771                                 continue;
2772                         }
2773                         lp = &fcp->portdb[target];
2774                         if (lp->port_wwn == clp->port_wwn &&
2775                             lp->node_wwn == clp->node_wwn) {
2776                                 lp->fabric_dev = 1;
2777                                 break;
2778                         }
2779                 }
2780                 if (target < lim) {
2781                         break;
2782                 }
2783                 for (target = base; target < lim; target++) {
2784                         if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
2785                                 continue;
2786                         }
2787                         lp = &fcp->portdb[target];
2788                         if (lp->port_wwn == 0) {
2789                                 break;
2790                         }
2791                 }
2792                 if (target == lim) {
2793                         isp_prt(isp, ISP_LOGWARN,
2794                             "out of space for fabric devices");
2795                         break;
2796                 }
2797                 lp->port_type = clp->port_type;
2798                 lp->fc4_type = clp->fc4_type;
2799                 lp->node_wwn = clp->node_wwn;
2800                 lp->port_wwn = clp->port_wwn;
2801                 lp->portid = clp->portid;
2802                 lp->fabric_dev = 1;
2803                 break;
2804         }
2805 #ifdef  ISP_TARGET_MODE
2806         case ISPASYNC_TARGET_MESSAGE:
2807         {
2808                 tmd_msg_t *mp = arg;
2809                 isp_prt(isp, ISP_LOGALL,
2810                     "bus %d iid %d tgt %d lun %d ttype %x tval %x msg[0]=%x",
2811                     mp->nt_bus, (int) mp->nt_iid, (int) mp->nt_tgt,
2812                     (int) mp->nt_lun, mp->nt_tagtype, mp->nt_tagval,
2813                     mp->nt_msg[0]);
2814                 break;
2815         }
2816         case ISPASYNC_TARGET_EVENT:
2817         {
2818                 tmd_event_t *ep = arg;
2819                 isp_prt(isp, ISP_LOGALL,
2820                     "bus %d event code 0x%x", ep->ev_bus, ep->ev_event);
2821                 break;
2822         }
2823         case ISPASYNC_TARGET_ACTION:
2824                 switch (((isphdr_t *)arg)->rqs_entry_type) {
2825                 default:
2826                         isp_prt(isp, ISP_LOGWARN,
2827                            "event 0x%x for unhandled target action",
2828                             ((isphdr_t *)arg)->rqs_entry_type);
2829                         break;
2830                 case RQSTYPE_NOTIFY:
2831                         if (IS_SCSI(isp)) {
2832                                 rv = isp_handle_platform_notify_scsi(isp,
2833                                     (in_entry_t *) arg);
2834                         } else {
2835                                 rv = isp_handle_platform_notify_fc(isp,
2836                                     (in_fcentry_t *) arg);
2837                         }
2838                         break;
2839                 case RQSTYPE_ATIO:
2840                         rv = isp_handle_platform_atio(isp, (at_entry_t *) arg);
2841                         break;
2842                 case RQSTYPE_ATIO2:
2843                         rv = isp_handle_platform_atio2(isp, (at2_entry_t *)arg);
2844                         break;
2845                 case RQSTYPE_CTIO2:
2846                 case RQSTYPE_CTIO:
2847                         rv = isp_handle_platform_ctio(isp, arg);
2848                         break;
2849                 case RQSTYPE_ENABLE_LUN:
2850                 case RQSTYPE_MODIFY_LUN:
2851                         if (IS_DUALBUS(isp)) {
2852                                 bus =
2853                                     GET_BUS_VAL(((lun_entry_t *)arg)->le_rsvd);
2854                         } else {
2855                                 bus = 0;
2856                         }
2857                         isp_cv_signal_rqe(isp, bus,
2858                             ((lun_entry_t *)arg)->le_status);
2859                         break;
2860                 }
2861                 break;
2862 #endif
2863         case ISPASYNC_FW_CRASH:
2864         {
2865                 u_int16_t mbox1, mbox6;
2866                 mbox1 = ISP_READ(isp, OUTMAILBOX1);
2867                 if (IS_DUALBUS(isp)) { 
2868                         mbox6 = ISP_READ(isp, OUTMAILBOX6);
2869                 } else {
2870                         mbox6 = 0;
2871                 }
2872                 isp_prt(isp, ISP_LOGERR,
2873                     "Internal Firmware Error on bus %d @ RISC Address 0x%x",
2874                     mbox6, mbox1);
2875 #ifdef  ISP_FW_CRASH_DUMP
2876                 /*
2877                  * XXX: really need a thread to do this right.
2878                  */
2879                 if (IS_FC(isp)) {
2880                         FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
2881                         FCPARAM(isp)->isp_loopstate = LOOP_NIL;
2882                         isp_freeze_loopdown(isp, "f/w crash");
2883                         isp_fw_dump(isp);
2884                 }
2885                 isp_reinit(isp);
2886                 isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
2887 #endif
2888                 break;
2889         }
2890         case ISPASYNC_UNHANDLED_RESPONSE:
2891                 break;
2892         default:
2893                 isp_prt(isp, ISP_LOGERR, "unknown isp_async event %d", cmd);
2894                 break;
2895         }
2896         return (rv);
2897 }
2898
2899
2900 /*
2901  * Locks are held before coming here.
2902  */
2903 void
2904 isp_uninit(struct ispsoftc *isp)
2905 {
2906         ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
2907         DISABLE_INTS(isp);
2908 }
2909
2910 void
2911 isp_prt(struct ispsoftc *isp, int level, const char *fmt, ...)
2912 {
2913         __va_list ap;
2914         if (level != ISP_LOGALL && (level & isp->isp_dblev) == 0) {
2915                 return;
2916         }
2917         kprintf("%s: ", device_get_nameunit(isp->isp_dev));
2918         __va_start(ap, fmt);
2919         kvprintf(fmt, ap);
2920         __va_end(ap);
2921         kprintf("\n");
2922 }