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