2 * Generic SCSI Target Kernel Mode Driver
4 * Copyright (c) 2002 Nate Lawson.
5 * Copyright (c) 1998, 1999, 2001, 2002 Justin T. Gibbs.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions, and the following disclaimer,
13 * without modification, immediately at the beginning of the file.
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.
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
29 * $FreeBSD: src/sys/cam/scsi/scsi_target.c,v 1.22.2.7 2003/02/18 22:07:10 njl Exp $
32 #include <sys/param.h>
33 #include <sys/systm.h>
35 #include <sys/kernel.h>
38 #include <sys/device.h>
39 #include <sys/malloc.h>
40 #include <sys/vnode.h>
41 #include <sys/devicestat.h>
42 #include <sys/thread2.h>
43 #include <sys/devfs.h>
46 #include "../cam_ccb.h"
47 #include "../cam_periph.h"
48 #include "../cam_xpt_periph.h"
49 #include "../cam_sim.h"
50 #include "scsi_targetio.h"
52 /* Transaction information attached to each CCB sent by the user */
53 struct targ_cmd_descr
{
54 struct cam_periph_map_info mapinfo
;
55 TAILQ_ENTRY(targ_cmd_descr
) tqe
;
61 /* Offset into the private CCB area for storing our descriptor */
62 #define targ_descr periph_priv.entries[1].ptr
64 TAILQ_HEAD(descr_queue
, targ_cmd_descr
);
67 TARG_STATE_RESV
= 0x00, /* Invalid state */
68 TARG_STATE_OPENED
= 0x01, /* Device opened, softc initialized */
69 TARG_STATE_LUN_ENABLED
= 0x02 /* Device enabled for a path */
72 /* Per-instance device software context */
74 /* CCBs (CTIOs, ATIOs, INOTs) pending on the controller */
75 struct ccb_queue pending_ccb_queue
;
77 /* Command descriptors awaiting CTIO resources from the XPT */
78 struct descr_queue work_queue
;
80 /* Command descriptors that have been aborted back to the user. */
81 struct descr_queue abort_queue
;
84 * Queue of CCBs that have been copied out to userland, but our
85 * userland daemon has not yet seen.
87 struct ccb_queue user_ccb_queue
;
89 struct cam_periph
*periph
;
90 struct cam_path
*path
;
92 struct kqinfo read_kq
;
93 struct devstat device_stats
;
96 static d_open_t targopen
;
97 static d_close_t targclose
;
98 static d_read_t targread
;
99 static d_write_t targwrite
;
100 static d_ioctl_t targioctl
;
101 static d_kqfilter_t targkqfilter
;
102 static d_clone_t targclone
;
103 DEVFS_DEFINE_CLONE_BITMAP(targ
);
105 static void targfiltdetach(struct knote
*kn
);
106 static int targreadfilt(struct knote
*kn
, long hint
);
107 static int targwritefilt(struct knote
*kn
, long hint
);
108 static struct filterops targread_filtops
=
109 { FILTEROP_ISFD
, NULL
, targfiltdetach
, targreadfilt
};
110 static struct filterops targwrite_filtops
=
111 { FILTEROP_ISFD
, NULL
, targfiltdetach
, targwritefilt
};
113 static struct dev_ops targ_ops
= {
116 .d_close
= targclose
,
118 .d_write
= targwrite
,
119 .d_ioctl
= targioctl
,
120 .d_kqfilter
= targkqfilter
123 static cam_status
targendislun(struct cam_path
*path
, int enable
,
124 int grp6_len
, int grp7_len
);
125 static cam_status
targenable(struct targ_softc
*softc
,
126 struct cam_path
*path
,
127 int grp6_len
, int grp7_len
);
128 static cam_status
targdisable(struct targ_softc
*softc
);
129 static periph_ctor_t targctor
;
130 static periph_dtor_t targdtor
;
131 static periph_start_t targstart
;
132 static int targusermerge(struct targ_softc
*softc
,
133 struct targ_cmd_descr
*descr
,
135 static int targsendccb(struct targ_softc
*softc
, union ccb
*ccb
,
136 struct targ_cmd_descr
*descr
);
137 static void targdone(struct cam_periph
*periph
,
138 union ccb
*done_ccb
);
139 static int targreturnccb(struct targ_softc
*softc
,
141 static union ccb
* targgetccb(struct targ_softc
*softc
, xpt_opcode type
,
143 static void targfreeccb(struct targ_softc
*softc
, union ccb
*ccb
);
144 static struct targ_cmd_descr
*
145 targgetdescr(struct targ_softc
*softc
);
146 static periph_init_t targinit
;
147 static void targasync(void *callback_arg
, u_int32_t code
,
148 struct cam_path
*path
, void *arg
);
149 static void abort_all_pending(struct targ_softc
*softc
);
150 static void notify_user(struct targ_softc
*softc
);
151 static int targcamstatus(cam_status status
);
152 static size_t targccblen(xpt_opcode func_code
);
154 static struct periph_driver targdriver
=
157 TAILQ_HEAD_INITIALIZER(targdriver
.units
), /* generation */ 0
159 PERIPHDRIVER_DECLARE(targ
, targdriver
);
161 static MALLOC_DEFINE(M_TARG
, "TARG", "TARG data");
164 * Create softc and initialize it. Only one proc can open each targ device.
165 * There is no locking here because a periph doesn't get created until an
166 * ioctl is issued to do so, and that can't happen until this method returns.
169 targopen(struct dev_open_args
*ap
)
171 cdev_t dev
= ap
->a_head
.a_dev
;
172 struct targ_softc
*softc
;
175 * Disallow CAM access if RESTRICTEDROOT
177 if (caps_priv_check_self(SYSCAP_RESTRICTEDROOT
))
180 if (dev
->si_drv1
!= 0)
183 /* Mark device busy before any potentially blocking operations */
184 dev
->si_drv1
= (void *)~0;
185 reference_dev(dev
); /* save ref for later destroy_dev() */
187 /* Create the targ device, allocate its softc, initialize it */
189 make_dev(&targ_ops
, minor(dev
), UID_ROOT
, GID_WHEEL
, 0600,
190 "targ%d", lminor(dev
));
192 softc
= kmalloc(sizeof(*softc
), M_TARG
, M_INTWAIT
| M_ZERO
);
193 dev
->si_drv1
= softc
;
194 softc
->state
= TARG_STATE_OPENED
;
195 softc
->periph
= NULL
;
198 TAILQ_INIT(&softc
->pending_ccb_queue
);
199 TAILQ_INIT(&softc
->work_queue
);
200 TAILQ_INIT(&softc
->abort_queue
);
201 TAILQ_INIT(&softc
->user_ccb_queue
);
206 /* Disable LUN if enabled and teardown softc */
208 targclose(struct dev_close_args
*ap
)
210 cdev_t dev
= ap
->a_head
.a_dev
;
211 struct targ_softc
*softc
;
212 struct cam_periph
*periph
;
215 softc
= (struct targ_softc
*)dev
->si_drv1
;
216 if ((softc
->periph
== NULL
) ||
217 (softc
->state
& TARG_STATE_LUN_ENABLED
) == 0) {
218 devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(targ
), dev
->si_uminor
);
220 kfree(softc
, M_TARG
);
225 * Acquire a hold on the periph so that it doesn't go away before
226 * we are ready at the end of the function.
228 periph
= softc
->periph
;
229 cam_periph_acquire(periph
);
230 cam_periph_lock(periph
);
231 error
= targdisable(softc
);
232 if (error
== CAM_REQ_CMP
) {
234 if (softc
->periph
!= NULL
) {
235 cam_periph_invalidate(softc
->periph
);
236 softc
->periph
= NULL
;
238 destroy_dev(dev
); /* eats the open ref */
239 devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(targ
), dev
->si_uminor
);
240 kfree(softc
, M_TARG
);
244 cam_periph_unlock(periph
);
245 cam_periph_release(periph
);
250 /* Enable/disable LUNs, set debugging level */
252 targioctl(struct dev_ioctl_args
*ap
)
254 struct targ_softc
*softc
;
257 softc
= (struct targ_softc
*)ap
->a_head
.a_dev
->si_drv1
;
262 struct ioc_enable_lun
*new_lun
;
263 struct cam_path
*path
;
266 new_lun
= (struct ioc_enable_lun
*)ap
->a_data
;
267 status
= xpt_create_path_unlocked(&path
, /*periph*/NULL
,
271 if (status
!= CAM_REQ_CMP
) {
272 kprintf("Couldn't create path, status %#x\n", status
);
275 sim
= xpt_path_sim(path
);
277 status
= targenable(softc
, path
, new_lun
->grp6_len
,
284 if (softc
->periph
== NULL
) {
285 status
= CAM_DEV_NOT_THERE
;
288 cam_periph_lock(softc
->periph
);
289 status
= targdisable(softc
);
290 cam_periph_unlock(softc
->periph
);
295 struct ccb_debug
*cdbg
;
297 /* If no periph available, disallow debugging changes */
298 if ((softc
->state
& TARG_STATE_LUN_ENABLED
) == 0) {
299 status
= CAM_DEV_NOT_THERE
;
302 cdbg
= &xpt_alloc_ccb()->cdbg
;
303 if (*((int *)ap
->a_data
) != 0)
304 cdbg
->flags
= CAM_DEBUG_PERIPH
;
306 cdbg
->flags
= CAM_DEBUG_NONE
;
307 cam_periph_lock(softc
->periph
);
308 xpt_setup_ccb(&cdbg
->ccb_h
, softc
->path
, /*priority*/0);
309 cdbg
->ccb_h
.func_code
= XPT_DEBUG
;
310 cdbg
->ccb_h
.cbfcnp
= targdone
;
312 xpt_action((union ccb
*)cdbg
);
313 cam_periph_unlock(softc
->periph
);
314 status
= cdbg
->ccb_h
.status
& CAM_STATUS_MASK
;
315 xpt_free_ccb(&cdbg
->ccb_h
);
317 status
= CAM_FUNC_NOTAVAIL
;
322 status
= CAM_PROVIDE_FAIL
;
326 return (targcamstatus(status
));
330 targkqfilter(struct dev_kqfilter_args
*ap
)
332 struct knote
*kn
= ap
->a_kn
;
333 struct targ_softc
*softc
;
335 softc
= (struct targ_softc
*)ap
->a_head
.a_dev
->si_drv1
;
339 switch (kn
->kn_filter
) {
341 kn
->kn_hook
= (caddr_t
)softc
;
342 kn
->kn_fop
= &targread_filtops
;
345 kn
->kn_hook
= (caddr_t
)softc
;
346 kn
->kn_fop
= &targwrite_filtops
;
348 ap
->a_result
= EOPNOTSUPP
;
352 knote_insert(&softc
->read_kq
.ki_note
, kn
);
357 targfiltdetach(struct knote
*kn
)
359 struct targ_softc
*softc
;
361 softc
= (struct targ_softc
*)kn
->kn_hook
;
362 knote_remove(&softc
->read_kq
.ki_note
, kn
);
365 /* Notify the user's kqueue when the user queue or abort queue gets a CCB */
367 targreadfilt(struct knote
*kn
, long hint
)
369 struct targ_softc
*softc
;
372 softc
= (struct targ_softc
*)kn
->kn_hook
;
373 cam_periph_lock(softc
->periph
);
374 retval
= !TAILQ_EMPTY(&softc
->user_ccb_queue
) ||
375 !TAILQ_EMPTY(&softc
->abort_queue
);
376 cam_periph_unlock(softc
->periph
);
380 /* write() is always ok */
382 targwritefilt(struct knote
*kn
, long hint
)
387 /* Send the HBA the enable/disable message */
389 targendislun(struct cam_path
*path
, int enable
, int grp6_len
, int grp7_len
)
391 struct ccb_en_lun
*en_ccb
;
394 /* Tell the lun to begin answering selects */
395 en_ccb
= &xpt_alloc_ccb()->cel
;
396 xpt_setup_ccb(&en_ccb
->ccb_h
, path
, /*priority*/1);
397 en_ccb
->ccb_h
.func_code
= XPT_EN_LUN
;
398 /* Don't need support for any vendor specific commands */
399 en_ccb
->grp6_len
= grp6_len
;
400 en_ccb
->grp7_len
= grp7_len
;
401 en_ccb
->enable
= enable
? 1 : 0;
402 xpt_action((union ccb
*)en_ccb
);
403 status
= en_ccb
->ccb_h
.status
& CAM_STATUS_MASK
;
404 if (status
!= CAM_REQ_CMP
) {
405 xpt_print(path
, "%sable lun CCB rejected, status %#x\n",
406 enable
? "en" : "dis", status
);
408 xpt_free_ccb(&en_ccb
->ccb_h
);
413 /* Enable target mode on a LUN, given its path */
415 targenable(struct targ_softc
*softc
, struct cam_path
*path
, int grp6_len
,
418 struct cam_periph
*periph
;
419 struct ccb_pathinq
*cpi
;
422 if ((softc
->state
& TARG_STATE_LUN_ENABLED
) != 0)
423 return (CAM_LUN_ALRDY_ENA
);
425 /* Make sure SIM supports target mode */
426 cpi
= &xpt_alloc_ccb()->cpi
;
427 xpt_setup_ccb(&cpi
->ccb_h
, path
, /*priority*/1);
428 cpi
->ccb_h
.func_code
= XPT_PATH_INQ
;
429 xpt_action((union ccb
*)cpi
);
430 status
= cpi
->ccb_h
.status
& CAM_STATUS_MASK
;
431 if (status
!= CAM_REQ_CMP
) {
432 kprintf("pathinq failed, status %#x\n", status
);
435 if ((cpi
->target_sprt
& PIT_PROCESSOR
) == 0) {
436 kprintf("controller does not support target mode\n");
437 status
= CAM_FUNC_NOTAVAIL
;
441 /* Destroy any periph on our path if it is disabled */
442 periph
= cam_periph_find(path
, "targ");
443 if (periph
!= NULL
) {
444 struct targ_softc
*del_softc
;
446 del_softc
= (struct targ_softc
*)periph
->softc
;
447 if ((del_softc
->state
& TARG_STATE_LUN_ENABLED
) == 0) {
448 cam_periph_invalidate(del_softc
->periph
);
449 del_softc
->periph
= NULL
;
451 kprintf("Requested path still in use by targ%d\n",
452 periph
->unit_number
);
453 status
= CAM_LUN_ALRDY_ENA
;
458 /* Create a periph instance attached to this path */
459 status
= cam_periph_alloc(targctor
, NULL
, targdtor
, targstart
,
460 "targ", CAM_PERIPH_BIO
, path
, targasync
, 0, softc
);
461 if (status
!= CAM_REQ_CMP
) {
462 kprintf("cam_periph_alloc failed, status %#x\n", status
);
466 /* Ensure that the periph now exists. */
467 if (cam_periph_find(path
, "targ") == NULL
) {
468 panic("targenable: succeeded but no periph?");
472 /* Send the enable lun message */
473 status
= targendislun(path
, /*enable*/1, grp6_len
, grp7_len
);
474 if (status
!= CAM_REQ_CMP
) {
475 kprintf("enable lun failed, status %#x\n", status
);
478 softc
->state
|= TARG_STATE_LUN_ENABLED
;
481 xpt_free_ccb(&cpi
->ccb_h
);
486 /* Disable this softc's target instance if enabled */
488 targdisable(struct targ_softc
*softc
)
492 if ((softc
->state
& TARG_STATE_LUN_ENABLED
) == 0)
493 return (CAM_REQ_CMP
);
495 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
, ("targdisable\n"));
497 /* Abort any ccbs pending on the controller */
499 abort_all_pending(softc
);
502 /* Disable this lun */
503 status
= targendislun(softc
->path
, /*enable*/0,
504 /*grp6_len*/0, /*grp7_len*/0);
505 if (status
== CAM_REQ_CMP
)
506 softc
->state
&= ~TARG_STATE_LUN_ENABLED
;
508 kprintf("Disable lun failed, status %#x\n", status
);
513 /* Initialize a periph (called from cam_periph_alloc) */
515 targctor(struct cam_periph
*periph
, void *arg
)
517 struct targ_softc
*softc
;
519 /* Store pointer to softc for periph-driven routines */
520 softc
= (struct targ_softc
*)arg
;
521 periph
->softc
= softc
;
522 softc
->periph
= periph
;
523 softc
->path
= periph
->path
;
524 return (CAM_REQ_CMP
);
528 targdtor(struct cam_periph
*periph
)
530 struct targ_softc
*softc
;
531 struct ccb_hdr
*ccb_h
;
532 struct targ_cmd_descr
*descr
;
534 softc
= (struct targ_softc
*)periph
->softc
;
537 * targdisable() aborts CCBs back to the user and leaves them
538 * on user_ccb_queue and abort_queue in case the user is still
539 * interested in them. We free them now.
541 while ((ccb_h
= TAILQ_FIRST(&softc
->user_ccb_queue
)) != NULL
) {
542 TAILQ_REMOVE(&softc
->user_ccb_queue
, ccb_h
, periph_links
.tqe
);
543 targfreeccb(softc
, (union ccb
*)ccb_h
);
545 while ((descr
= TAILQ_FIRST(&softc
->abort_queue
)) != NULL
) {
546 TAILQ_REMOVE(&softc
->abort_queue
, descr
, tqe
);
547 kfree(descr
, M_TARG
);
550 softc
->periph
= NULL
;
552 periph
->softc
= NULL
;
555 /* Receive CCBs from user mode proc and send them to the HBA */
557 targwrite(struct dev_write_args
*ap
)
559 struct uio
*uio
= ap
->a_uio
;
561 struct targ_softc
*softc
;
562 struct targ_cmd_descr
*descr
;
563 int write_len
, error
;
564 int func_code
, priority
;
566 softc
= (struct targ_softc
*)ap
->a_head
.a_dev
->si_drv1
;
567 write_len
= error
= 0;
568 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
569 ("write - uio_resid %zu\n", uio
->uio_resid
));
570 while (uio
->uio_resid
>= sizeof(user_ccb
) && error
== 0) {
573 error
= uiomove((caddr_t
)&user_ccb
, sizeof(user_ccb
), uio
);
575 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
576 ("write - uiomove failed (%d)\n", error
));
579 priority
= fuword32(&user_ccb
->ccb_h
.pinfo
.priority
);
580 if (priority
== -1) {
584 func_code
= fuword32(&user_ccb
->ccb_h
.func_code
);
586 case XPT_ACCEPT_TARGET_IO
:
587 case XPT_IMMED_NOTIFY
:
588 cam_periph_lock(softc
->periph
);
589 ccb
= targgetccb(softc
, func_code
, priority
);
590 descr
= (struct targ_cmd_descr
*)ccb
->ccb_h
.targ_descr
;
591 descr
->user_ccb
= user_ccb
;
592 descr
->func_code
= func_code
;
593 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
594 ("Sent ATIO/INOT (%p)\n", user_ccb
));
596 TAILQ_INSERT_TAIL(&softc
->pending_ccb_queue
,
599 cam_periph_unlock(softc
->periph
);
602 cam_periph_lock(softc
->periph
);
603 if ((func_code
& XPT_FC_QUEUED
) != 0) {
604 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
605 ("Sending queued ccb %#x (%p)\n",
606 func_code
, user_ccb
));
607 descr
= targgetdescr(softc
);
608 descr
->user_ccb
= user_ccb
;
609 descr
->priority
= priority
;
610 descr
->func_code
= func_code
;
612 TAILQ_INSERT_TAIL(&softc
->work_queue
,
615 xpt_schedule(softc
->periph
, priority
);
617 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
618 ("Sending inline ccb %#x (%p)\n",
619 func_code
, user_ccb
));
620 ccb
= targgetccb(softc
, func_code
, priority
);
621 descr
= (struct targ_cmd_descr
*)
622 ccb
->ccb_h
.targ_descr
;
623 descr
->user_ccb
= user_ccb
;
624 descr
->priority
= priority
;
625 descr
->func_code
= func_code
;
626 if (targusermerge(softc
, descr
, ccb
) != EFAULT
)
627 targsendccb(softc
, ccb
, descr
);
628 targreturnccb(softc
, ccb
);
630 cam_periph_unlock(softc
->periph
);
633 write_len
+= sizeof(user_ccb
);
637 * If we've successfully taken in some amount of
638 * data, return success for that data first. If
639 * an error is persistent, it will be reported
642 if (error
!= 0 && write_len
== 0)
644 if (write_len
== 0 && uio
->uio_resid
!= 0)
649 /* Process requests (descrs) via the periph-supplied CCBs */
651 targstart(struct cam_periph
*periph
, union ccb
*start_ccb
)
653 struct targ_softc
*softc
;
654 struct targ_cmd_descr
*descr
, *next_descr
;
657 softc
= (struct targ_softc
*)periph
->softc
;
658 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
, ("targstart %p\n", start_ccb
));
661 descr
= TAILQ_FIRST(&softc
->work_queue
);
664 xpt_release_ccb(start_ccb
);
666 TAILQ_REMOVE(&softc
->work_queue
, descr
, tqe
);
667 next_descr
= TAILQ_FIRST(&softc
->work_queue
);
670 /* Initiate a transaction using the descr and supplied CCB */
671 error
= targusermerge(softc
, descr
, start_ccb
);
673 error
= targsendccb(softc
, start_ccb
, descr
);
675 xpt_print(periph
->path
,
676 "targsendccb failed, err %d\n", error
);
677 xpt_release_ccb(start_ccb
);
678 suword32(&descr
->user_ccb
->ccb_h
.status
,
681 TAILQ_INSERT_TAIL(&softc
->abort_queue
, descr
, tqe
);
686 /* If we have more work to do, stay scheduled */
687 if (next_descr
!= NULL
)
688 xpt_schedule(periph
, next_descr
->priority
);
693 targusermerge(struct targ_softc
*softc
, struct targ_cmd_descr
*descr
,
696 struct ccb_hdr
*u_ccbh
, *k_ccbh
;
700 u_ccbh
= &descr
->user_ccb
->ccb_h
;
701 k_ccbh
= &ccb
->ccb_h
;
704 * There are some fields in the CCB header that need to be
705 * preserved, the rest we get from the user ccb. (See xpt_merge_ccb)
707 xpt_setup_ccb(k_ccbh
, softc
->path
, descr
->priority
);
708 k_ccbh
->retry_count
= fuword32(&u_ccbh
->retry_count
);
709 k_ccbh
->func_code
= descr
->func_code
;
710 k_ccbh
->flags
= fuword32(&u_ccbh
->flags
);
711 k_ccbh
->timeout
= fuword32(&u_ccbh
->timeout
);
712 ccb_len
= targccblen(k_ccbh
->func_code
) - sizeof(struct ccb_hdr
);
713 error
= copyin(u_ccbh
+ 1, k_ccbh
+ 1, ccb_len
);
715 k_ccbh
->status
= CAM_REQ_CMP_ERR
;
719 /* Translate usermode abort_ccb pointer to its kernel counterpart */
720 if (k_ccbh
->func_code
== XPT_ABORT
) {
721 struct ccb_abort
*cab
;
722 struct ccb_hdr
*ccb_h
;
724 cab
= (struct ccb_abort
*)ccb
;
726 TAILQ_FOREACH(ccb_h
, &softc
->pending_ccb_queue
,
728 struct targ_cmd_descr
*ab_descr
;
730 ab_descr
= (struct targ_cmd_descr
*)ccb_h
->targ_descr
;
731 if (ab_descr
->user_ccb
== cab
->abort_ccb
) {
732 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
733 ("Changing abort for %p to %p\n",
734 cab
->abort_ccb
, ccb_h
));
735 cab
->abort_ccb
= (union ccb
*)ccb_h
;
740 /* CCB not found, set appropriate status */
742 k_ccbh
->status
= CAM_PATH_INVALID
;
750 /* Build and send a kernel CCB formed from descr->user_ccb */
752 targsendccb(struct targ_softc
*softc
, union ccb
*ccb
,
753 struct targ_cmd_descr
*descr
)
755 struct cam_periph_map_info
*mapinfo
;
756 struct ccb_hdr
*ccb_h
;
760 mapinfo
= &descr
->mapinfo
;
761 mapinfo
->num_bufs_used
= 0;
764 * There's no way for the user to have a completion
765 * function, so we put our own completion function in here.
766 * We also stash in a reference to our descriptor so targreturnccb()
767 * can find our mapping info.
769 ccb_h
->cbfcnp
= targdone
;
770 ccb_h
->targ_descr
= descr
;
773 * We only attempt to map the user memory into kernel space
774 * if they haven't passed in a physical memory pointer,
775 * and if there is actually an I/O operation to perform.
776 * Right now cam_periph_mapmem() only supports SCSI and device
777 * match CCBs. For the SCSI CCBs, we only pass the CCB in if
778 * there's actually data to map. cam_periph_mapmem() will do the
779 * right thing, even if there isn't data to map, but since CCBs
780 * without data are a reasonably common occurance (e.g. test unit
781 * ready), it will save a few cycles if we check for it here.
783 if (((ccb_h
->flags
& CAM_DATA_PHYS
) == 0)
784 && (((ccb_h
->func_code
== XPT_CONT_TARGET_IO
)
785 && ((ccb_h
->flags
& CAM_DIR_MASK
) != CAM_DIR_NONE
))
786 || (ccb_h
->func_code
== XPT_DEV_MATCH
))) {
788 error
= cam_periph_mapmem(ccb
, mapinfo
);
791 * cam_periph_mapmem returned an error, we can't continue.
792 * Return the error to the user.
795 ccb_h
->status
= CAM_REQ_CMP_ERR
;
796 mapinfo
->num_bufs_used
= 0;
802 * Once queued on the pending CCB list, this CCB will be protected
803 * by our error recovery handler.
805 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
, ("sendccb %p\n", ccb
));
806 if (XPT_FC_IS_QUEUED(ccb
)) {
808 TAILQ_INSERT_TAIL(&softc
->pending_ccb_queue
, ccb_h
,
817 /* Completion routine for CCBs (called in a critical section) */
819 targdone(struct cam_periph
*periph
, union ccb
*done_ccb
)
821 struct targ_softc
*softc
;
823 CAM_DEBUG(periph
->path
, CAM_DEBUG_PERIPH
, ("targdone %p\n", done_ccb
));
824 softc
= (struct targ_softc
*)periph
->softc
;
825 TAILQ_REMOVE(&softc
->pending_ccb_queue
, &done_ccb
->ccb_h
,
828 /* If we're no longer enabled, throw away CCB */
829 if ((softc
->state
& TARG_STATE_LUN_ENABLED
) == 0) {
830 targfreeccb(softc
, done_ccb
);
833 /* abort_all_pending() waits for pending queue to be empty */
834 if (TAILQ_EMPTY(&softc
->pending_ccb_queue
))
835 wakeup(&softc
->pending_ccb_queue
);
837 switch (done_ccb
->ccb_h
.func_code
) {
838 /* All FC_*_QUEUED CCBs go back to userland */
839 case XPT_IMMED_NOTIFY
:
840 case XPT_ACCEPT_TARGET_IO
:
841 case XPT_CONT_TARGET_IO
:
842 TAILQ_INSERT_TAIL(&softc
->user_ccb_queue
, &done_ccb
->ccb_h
,
847 panic("targdone: impossible xpt opcode %#x",
848 done_ccb
->ccb_h
.func_code
);
853 /* Return CCBs to the user from the user queue and abort queue */
855 targread(struct dev_read_args
*ap
)
857 struct uio
*uio
= ap
->a_uio
;
858 struct descr_queue
*abort_queue
;
859 struct targ_cmd_descr
*user_descr
;
860 struct targ_softc
*softc
;
861 struct ccb_queue
*user_queue
;
862 struct ccb_hdr
*ccb_h
;
868 softc
= (struct targ_softc
*)ap
->a_head
.a_dev
->si_drv1
;
869 user_queue
= &softc
->user_ccb_queue
;
870 abort_queue
= &softc
->abort_queue
;
871 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
, ("targread\n"));
873 /* If no data is available, wait or return immediately */
874 cam_periph_lock(softc
->periph
);
875 ccb_h
= TAILQ_FIRST(user_queue
);
876 user_descr
= TAILQ_FIRST(abort_queue
);
877 while (ccb_h
== NULL
&& user_descr
== NULL
) {
878 if ((ap
->a_ioflag
& IO_NDELAY
) == 0) {
879 error
= sim_lock_sleep(user_queue
, PCATCH
, "targrd", 0,
880 softc
->periph
->sim
->lock
);
881 ccb_h
= TAILQ_FIRST(user_queue
);
882 user_descr
= TAILQ_FIRST(abort_queue
);
884 if (error
== ERESTART
) {
891 cam_periph_unlock(softc
->periph
);
896 /* Data is available so fill the user's buffer */
897 while (ccb_h
!= NULL
) {
898 struct targ_cmd_descr
*descr
;
900 if (uio
->uio_resid
< sizeof(user_ccb
))
902 TAILQ_REMOVE(user_queue
, ccb_h
, periph_links
.tqe
);
903 descr
= (struct targ_cmd_descr
*)ccb_h
->targ_descr
;
904 user_ccb
= descr
->user_ccb
;
905 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
906 ("targread ccb %p (%p)\n", ccb_h
, user_ccb
));
907 error
= targreturnccb(softc
, (union ccb
*)ccb_h
);
910 cam_periph_unlock(softc
->periph
);
911 error
= uiomove((caddr_t
)&user_ccb
, sizeof(user_ccb
), uio
);
912 cam_periph_lock(softc
->periph
);
915 read_len
+= sizeof(user_ccb
);
917 ccb_h
= TAILQ_FIRST(user_queue
);
920 /* Flush out any aborted descriptors */
921 while (user_descr
!= NULL
) {
922 if (uio
->uio_resid
< sizeof(user_ccb
))
924 TAILQ_REMOVE(abort_queue
, user_descr
, tqe
);
925 user_ccb
= user_descr
->user_ccb
;
926 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
927 ("targread aborted descr %p (%p)\n",
928 user_descr
, user_ccb
));
929 suword32(&user_ccb
->ccb_h
.status
, CAM_REQ_ABORTED
);
930 cam_periph_unlock(softc
->periph
);
931 error
= uiomove((caddr_t
)&user_ccb
, sizeof(user_ccb
), uio
);
932 cam_periph_lock(softc
->periph
);
935 read_len
+= sizeof(user_ccb
);
937 user_descr
= TAILQ_FIRST(abort_queue
);
941 * If we've successfully read some amount of data, don't report an
942 * error. If the error is persistent, it will be reported on the
945 if (read_len
== 0 && uio
->uio_resid
!= 0)
949 cam_periph_unlock(softc
->periph
);
953 /* Copy completed ccb back to the user */
955 targreturnccb(struct targ_softc
*softc
, union ccb
*ccb
)
957 struct targ_cmd_descr
*descr
;
958 struct ccb_hdr
*u_ccbh
;
962 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
, ("targreturnccb %p\n", ccb
));
963 descr
= (struct targ_cmd_descr
*)ccb
->ccb_h
.targ_descr
;
964 u_ccbh
= &descr
->user_ccb
->ccb_h
;
966 /* Copy out the central portion of the ccb_hdr */
967 copyout(&ccb
->ccb_h
.retry_count
, &u_ccbh
->retry_count
,
968 offsetof(struct ccb_hdr
, periph_priv
) -
969 offsetof(struct ccb_hdr
, retry_count
));
971 /* Copy out the rest of the ccb (after the ccb_hdr) */
972 ccb_len
= targccblen(ccb
->ccb_h
.func_code
) - sizeof(struct ccb_hdr
);
973 if (descr
->mapinfo
.num_bufs_used
!= 0)
974 cam_periph_unmapmem(ccb
, &descr
->mapinfo
);
975 error
= copyout(&ccb
->ccb_h
+ 1, u_ccbh
+ 1, ccb_len
);
977 xpt_print(softc
->path
,
978 "targreturnccb - CCB copyout failed (%d)\n", error
);
980 /* Free CCB or send back to devq. */
981 targfreeccb(softc
, ccb
);
987 targgetccb(struct targ_softc
*softc
, xpt_opcode type
, int priority
)
993 ccb_len
= targccblen(type
);
994 ccb
= kmalloc(ccb_len
, M_TARG
, M_INTWAIT
);
996 ccb
= xpt_alloc_ccb();
997 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
, ("getccb %p\n", ccb
));
999 xpt_setup_ccb(&ccb
->ccb_h
, softc
->path
, priority
);
1000 ccb
->ccb_h
.func_code
= type
;
1001 ccb
->ccb_h
.cbfcnp
= targdone
;
1002 ccb
->ccb_h
.targ_descr
= targgetdescr(softc
);
1008 targfreeccb(struct targ_softc
*softc
, union ccb
*ccb
)
1010 CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH
, ("targfreeccb descr %p and\n",
1011 ccb
->ccb_h
.targ_descr
));
1012 kfree(ccb
->ccb_h
.targ_descr
, M_TARG
);
1013 ccb
->ccb_h
.targ_descr
= NULL
; /* safety */
1015 switch (ccb
->ccb_h
.func_code
) {
1016 case XPT_ACCEPT_TARGET_IO
:
1017 case XPT_IMMED_NOTIFY
:
1018 CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH
, ("freeing ccb %p\n", ccb
));
1019 xpt_free_ccb(&ccb
->ccb_h
);
1022 /* Send back CCB if we got it from the periph */
1023 if (XPT_FC_IS_QUEUED(ccb
)) {
1024 CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH
,
1025 ("returning queued ccb %p\n", ccb
));
1026 xpt_release_ccb(ccb
);
1028 CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH
,
1029 ("freeing ccb %p\n", ccb
));
1030 xpt_free_ccb(&ccb
->ccb_h
);
1036 static struct targ_cmd_descr
*
1037 targgetdescr(struct targ_softc
*softc
)
1039 struct targ_cmd_descr
*descr
;
1041 descr
= kmalloc(sizeof(*descr
), M_TARG
, M_INTWAIT
);
1042 descr
->mapinfo
.num_bufs_used
= 0;
1047 targclone(struct dev_clone_args
*ap
)
1051 unit
= devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(targ
), 0);
1052 ap
->a_dev
= make_only_dev(&targ_ops
, unit
, UID_ROOT
, GID_WHEEL
,
1053 0600, "targ%d", unit
);
1060 make_autoclone_dev(&targ_ops
, &DEVFS_CLONE_BITMAP(targ
),
1061 targclone
, UID_ROOT
, GID_WHEEL
, 0600, "targ");
1062 /* XXX: need uninit or so? */
1066 targasync(void *callback_arg
, u_int32_t code
, struct cam_path
*path
, void *arg
)
1068 /* All events are handled in usermode by INOTs */
1069 panic("targasync() called, should be an INOT instead");
1072 /* Cancel all pending requests and CCBs awaiting work. */
1074 abort_all_pending(struct targ_softc
*softc
)
1076 struct targ_cmd_descr
*descr
;
1077 struct ccb_abort
*cab
;
1078 struct ccb_hdr
*ccb_h
;
1079 struct cam_sim
*sim
;
1081 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
, ("abort_all_pending\n"));
1083 /* First abort the descriptors awaiting resources */
1084 while ((descr
= TAILQ_FIRST(&softc
->work_queue
)) != NULL
) {
1085 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
1086 ("Aborting descr from workq %p\n", descr
));
1087 TAILQ_REMOVE(&softc
->work_queue
, descr
, tqe
);
1088 TAILQ_INSERT_TAIL(&softc
->abort_queue
, descr
, tqe
);
1092 * Then abort all pending CCBs.
1093 * targdone() will return the aborted CCB via user_ccb_queue
1095 cab
= &xpt_alloc_ccb()->cab
;
1096 xpt_setup_ccb(&cab
->ccb_h
, softc
->path
, /*priority*/0);
1097 cab
->ccb_h
.func_code
= XPT_ABORT
;
1098 cab
->ccb_h
.status
= CAM_REQ_CMP_ERR
;
1099 TAILQ_FOREACH(ccb_h
, &softc
->pending_ccb_queue
, periph_links
.tqe
) {
1100 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
1101 ("Aborting pending CCB %p\n", ccb_h
));
1102 cab
->abort_ccb
= (union ccb
*)ccb_h
;
1103 xpt_action((union ccb
*)cab
);
1104 if (cab
->ccb_h
.status
!= CAM_REQ_CMP
) {
1105 xpt_print(cab
->ccb_h
.path
,
1106 "Unable to abort CCB, status %#x\n",
1111 /* If we aborted at least one pending CCB ok, wait for it. */
1112 if (cab
->ccb_h
.status
== CAM_REQ_CMP
) {
1113 sim
= xpt_path_sim(softc
->path
);
1114 sim_lock_sleep(&softc
->pending_ccb_queue
, PCATCH
, "tgabrt", 0,
1118 /* If we aborted anything from the work queue, wakeup user. */
1119 if (!TAILQ_EMPTY(&softc
->user_ccb_queue
) ||
1120 !TAILQ_EMPTY(&softc
->abort_queue
)) {
1124 xpt_free_ccb(&cab
->ccb_h
);
1127 /* Notify the user that data is ready */
1129 notify_user(struct targ_softc
*softc
)
1132 * Notify users sleeping via poll(), kqueue(), and
1135 KNOTE(&softc
->read_kq
.ki_note
, 0);
1136 wakeup(&softc
->user_ccb_queue
);
1139 /* Convert CAM status to errno values */
1141 targcamstatus(cam_status status
)
1143 switch (status
& CAM_STATUS_MASK
) {
1144 case CAM_REQ_CMP
: /* CCB request completed without error */
1146 case CAM_REQ_INPROG
: /* CCB request is in progress */
1147 return (EINPROGRESS
);
1148 case CAM_REQ_CMP_ERR
: /* CCB request completed with an error */
1150 case CAM_PROVIDE_FAIL
: /* Unable to provide requested capability */
1152 case CAM_FUNC_NOTAVAIL
: /* The requested function is not available */
1154 case CAM_LUN_ALRDY_ENA
: /* LUN is already enabled for target mode */
1155 return (EADDRINUSE
);
1156 case CAM_PATH_INVALID
: /* Supplied Path ID is invalid */
1157 case CAM_DEV_NOT_THERE
: /* SCSI Device Not Installed/there */
1159 case CAM_REQ_ABORTED
: /* CCB request aborted by the host */
1161 case CAM_CMD_TIMEOUT
: /* Command timeout */
1163 case CAM_REQUEUE_REQ
: /* Requeue to preserve transaction ordering */
1165 case CAM_REQ_INVALID
: /* CCB request was invalid */
1167 case CAM_RESRC_UNAVAIL
: /* Resource Unavailable */
1169 case CAM_BUSY
: /* CAM subsytem is busy */
1170 case CAM_UA_ABORT
: /* Unable to abort CCB request */
1178 targccblen(xpt_opcode func_code
)
1182 /* Codes we expect to see as a target */
1183 switch (func_code
) {
1184 case XPT_CONT_TARGET_IO
:
1186 len
= sizeof(struct ccb_scsiio
);
1188 case XPT_ACCEPT_TARGET_IO
:
1189 len
= sizeof(struct ccb_accept_tio
);
1191 case XPT_IMMED_NOTIFY
:
1192 len
= sizeof(struct ccb_immed_notify
);
1195 len
= sizeof(struct ccb_relsim
);
1198 len
= sizeof(struct ccb_pathinq
);
1201 len
= sizeof(struct ccb_debug
);
1204 len
= sizeof(struct ccb_abort
);
1207 len
= sizeof(struct ccb_en_lun
);
1210 len
= sizeof(union ccb
);