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 $
30 * $DragonFly: src/sys/bus/cam/scsi/scsi_target.c,v 1.19.2.1 2008/07/18 00:08:23 dillon Exp $
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
37 #include <sys/device.h>
38 #include <sys/malloc.h>
40 #include <sys/vnode.h>
41 #include <sys/devicestat.h>
42 #include <sys/thread2.h>
45 #include "../cam_ccb.h"
46 #include "../cam_periph.h"
47 #include "../cam_xpt_periph.h"
48 #include "../cam_sim.h"
49 #include "scsi_targetio.h"
51 /* Transaction information attached to each CCB sent by the user */
52 struct targ_cmd_descr
{
53 struct cam_periph_map_info mapinfo
;
54 TAILQ_ENTRY(targ_cmd_descr
) tqe
;
60 /* Offset into the private CCB area for storing our descriptor */
61 #define targ_descr periph_priv.entries[1].ptr
63 TAILQ_HEAD(descr_queue
, targ_cmd_descr
);
66 TARG_STATE_RESV
= 0x00, /* Invalid state */
67 TARG_STATE_OPENED
= 0x01, /* Device opened, softc initialized */
68 TARG_STATE_LUN_ENABLED
= 0x02 /* Device enabled for a path */
71 /* Per-instance device software context */
73 /* CCBs (CTIOs, ATIOs, INOTs) pending on the controller */
74 struct ccb_queue pending_ccb_queue
;
76 /* Command descriptors awaiting CTIO resources from the XPT */
77 struct descr_queue work_queue
;
79 /* Command descriptors that have been aborted back to the user. */
80 struct descr_queue abort_queue
;
83 * Queue of CCBs that have been copied out to userland, but our
84 * userland daemon has not yet seen.
86 struct ccb_queue user_ccb_queue
;
88 struct cam_periph
*periph
;
89 struct cam_path
*path
;
91 struct selinfo read_select
;
92 struct devstat device_stats
;
95 static d_open_t targopen
;
96 static d_close_t targclose
;
97 static d_read_t targread
;
98 static d_write_t targwrite
;
99 static d_ioctl_t targioctl
;
100 static d_poll_t targpoll
;
101 static d_kqfilter_t targkqfilter
;
102 static void targreadfiltdetach(struct knote
*kn
);
103 static int targreadfilt(struct knote
*kn
, long hint
);
104 static struct filterops targread_filtops
=
105 { 1, NULL
, targreadfiltdetach
, targreadfilt
};
107 #define TARG_CDEV_MAJOR 65
108 static struct dev_ops targ_ops
= {
109 { "targ", TARG_CDEV_MAJOR
, D_KQFILTER
},
111 .d_close
= targclose
,
113 .d_write
= targwrite
,
114 .d_ioctl
= targioctl
,
116 .d_kqfilter
= targkqfilter
119 static cam_status
targendislun(struct cam_path
*path
, int enable
,
120 int grp6_len
, int grp7_len
);
121 static cam_status
targenable(struct targ_softc
*softc
,
122 struct cam_path
*path
,
123 int grp6_len
, int grp7_len
);
124 static cam_status
targdisable(struct targ_softc
*softc
);
125 static periph_ctor_t targctor
;
126 static periph_dtor_t targdtor
;
127 static periph_start_t targstart
;
128 static int targusermerge(struct targ_softc
*softc
,
129 struct targ_cmd_descr
*descr
,
131 static int targsendccb(struct targ_softc
*softc
, union ccb
*ccb
,
132 struct targ_cmd_descr
*descr
);
133 static void targdone(struct cam_periph
*periph
,
134 union ccb
*done_ccb
);
135 static int targreturnccb(struct targ_softc
*softc
,
137 static union ccb
* targgetccb(struct targ_softc
*softc
, xpt_opcode type
,
139 static void targfreeccb(struct targ_softc
*softc
, union ccb
*ccb
);
140 static struct targ_cmd_descr
*
141 targgetdescr(struct targ_softc
*softc
);
142 static periph_init_t targinit
;
143 static void targasync(void *callback_arg
, u_int32_t code
,
144 struct cam_path
*path
, void *arg
);
145 static void abort_all_pending(struct targ_softc
*softc
);
146 static void notify_user(struct targ_softc
*softc
);
147 static int targcamstatus(cam_status status
);
148 static size_t targccblen(xpt_opcode func_code
);
150 static struct periph_driver targdriver
=
153 TAILQ_HEAD_INITIALIZER(targdriver
.units
), /* generation */ 0
155 PERIPHDRIVER_DECLARE(targ
, targdriver
);
157 static MALLOC_DEFINE(M_TARG
, "TARG", "TARG data");
160 * Create softc and initialize it. Only one proc can open each targ device.
161 * There is no locking here because a periph doesn't get created until an
162 * ioctl is issued to do so, and that can't happen until this method returns.
165 targopen(struct dev_open_args
*ap
)
167 cdev_t dev
= ap
->a_head
.a_dev
;
168 struct targ_softc
*softc
;
170 if (dev
->si_drv1
!= 0) {
174 /* Mark device busy before any potentially blocking operations */
175 dev
->si_drv1
= (void *)~0;
176 reference_dev(dev
); /* save ref for later destroy_dev() */
178 /* Create the targ device, allocate its softc, initialize it */
179 make_dev(&targ_ops
, minor(dev
), UID_ROOT
, GID_WHEEL
, 0600,
180 "targ%d", lminor(dev
));
181 MALLOC(softc
, struct targ_softc
*, sizeof(*softc
), M_TARG
,
183 dev
->si_drv1
= softc
;
184 softc
->state
= TARG_STATE_OPENED
;
185 softc
->periph
= NULL
;
188 TAILQ_INIT(&softc
->pending_ccb_queue
);
189 TAILQ_INIT(&softc
->work_queue
);
190 TAILQ_INIT(&softc
->abort_queue
);
191 TAILQ_INIT(&softc
->user_ccb_queue
);
196 /* Disable LUN if enabled and teardown softc */
198 targclose(struct dev_close_args
*ap
)
200 cdev_t dev
= ap
->a_head
.a_dev
;
201 struct targ_softc
*softc
;
202 struct cam_periph
*periph
;
205 softc
= (struct targ_softc
*)dev
->si_drv1
;
206 if ((softc
->periph
== NULL
) ||
207 (softc
->state
& TARG_STATE_LUN_ENABLED
) == 0) {
214 * Acquire a hold on the periph so that it doesn't go away before
215 * we are ready at the end of the function.
217 periph
= softc
->periph
;
218 cam_periph_acquire(periph
);
219 cam_periph_lock(periph
);
220 error
= targdisable(softc
);
221 if (error
== CAM_REQ_CMP
) {
223 if (softc
->periph
!= NULL
) {
224 cam_periph_invalidate(softc
->periph
);
225 softc
->periph
= NULL
;
227 destroy_dev(dev
); /* eats the open ref */
232 cam_periph_unlock(periph
);
233 cam_periph_release(periph
);
238 /* Enable/disable LUNs, set debugging level */
240 targioctl(struct dev_ioctl_args
*ap
)
242 struct targ_softc
*softc
;
245 softc
= (struct targ_softc
*)ap
->a_head
.a_dev
->si_drv1
;
250 struct ioc_enable_lun
*new_lun
;
251 struct cam_path
*path
;
254 new_lun
= (struct ioc_enable_lun
*)ap
->a_data
;
255 status
= xpt_create_path_unlocked(&path
, /*periph*/NULL
,
259 if (status
!= CAM_REQ_CMP
) {
260 kprintf("Couldn't create path, status %#x\n", status
);
263 sim
= xpt_path_sim(path
);
265 status
= targenable(softc
, path
, new_lun
->grp6_len
,
272 if (softc
->periph
== NULL
) {
273 status
= CAM_DEV_NOT_THERE
;
276 cam_periph_lock(softc
->periph
);
277 status
= targdisable(softc
);
278 cam_periph_unlock(softc
->periph
);
283 struct ccb_debug cdbg
;
285 /* If no periph available, disallow debugging changes */
286 if ((softc
->state
& TARG_STATE_LUN_ENABLED
) == 0) {
287 status
= CAM_DEV_NOT_THERE
;
290 bzero(&cdbg
, sizeof cdbg
);
291 if (*((int *)ap
->a_data
) != 0)
292 cdbg
.flags
= CAM_DEBUG_PERIPH
;
294 cdbg
.flags
= CAM_DEBUG_NONE
;
295 cam_periph_lock(softc
->periph
);
296 xpt_setup_ccb(&cdbg
.ccb_h
, softc
->path
, /*priority*/0);
297 cdbg
.ccb_h
.func_code
= XPT_DEBUG
;
298 cdbg
.ccb_h
.cbfcnp
= targdone
;
300 xpt_action((union ccb
*)&cdbg
);
301 cam_periph_unlock(softc
->periph
);
302 status
= cdbg
.ccb_h
.status
& CAM_STATUS_MASK
;
304 status
= CAM_FUNC_NOTAVAIL
;
309 status
= CAM_PROVIDE_FAIL
;
313 return (targcamstatus(status
));
316 /* Writes are always ready, reads wait for user_ccb_queue or abort_queue */
318 targpoll(struct dev_poll_args
*ap
)
320 struct targ_softc
*softc
;
323 softc
= (struct targ_softc
*)ap
->a_head
.a_dev
->si_drv1
;
325 /* Poll for write() is always ok. */
326 revents
= ap
->a_events
& (POLLOUT
| POLLWRNORM
);
327 if ((ap
->a_events
& (POLLIN
| POLLRDNORM
)) != 0) {
328 /* Poll for read() depends on user and abort queues. */
329 cam_periph_lock(softc
->periph
);
330 if (!TAILQ_EMPTY(&softc
->user_ccb_queue
) ||
331 !TAILQ_EMPTY(&softc
->abort_queue
)) {
332 revents
|= ap
->a_events
& (POLLIN
| POLLRDNORM
);
334 cam_periph_unlock(softc
->periph
);
335 /* Only sleep if the user didn't poll for write. */
337 selrecord(curthread
, &softc
->read_select
);
339 ap
->a_events
= revents
;
344 targkqfilter(struct dev_kqfilter_args
*ap
)
346 struct knote
*kn
= ap
->a_kn
;
347 struct targ_softc
*softc
;
349 softc
= (struct targ_softc
*)ap
->a_head
.a_dev
->si_drv1
;
350 kn
->kn_hook
= (caddr_t
)softc
;
351 kn
->kn_fop
= &targread_filtops
;
353 SLIST_INSERT_HEAD(&softc
->read_select
.si_note
, kn
, kn_selnext
);
359 targreadfiltdetach(struct knote
*kn
)
361 struct targ_softc
*softc
;
363 softc
= (struct targ_softc
*)kn
->kn_hook
;
365 SLIST_REMOVE(&softc
->read_select
.si_note
, kn
, knote
, kn_selnext
);
369 /* Notify the user's kqueue when the user queue or abort queue gets a CCB */
371 targreadfilt(struct knote
*kn
, long hint
)
373 struct targ_softc
*softc
;
376 softc
= (struct targ_softc
*)kn
->kn_hook
;
377 cam_periph_lock(softc
->periph
);
378 retval
= !TAILQ_EMPTY(&softc
->user_ccb_queue
) ||
379 !TAILQ_EMPTY(&softc
->abort_queue
);
380 cam_periph_unlock(softc
->periph
);
384 /* Send the HBA the enable/disable message */
386 targendislun(struct cam_path
*path
, int enable
, int grp6_len
, int grp7_len
)
388 struct ccb_en_lun en_ccb
;
391 /* Tell the lun to begin answering selects */
392 xpt_setup_ccb(&en_ccb
.ccb_h
, path
, /*priority*/1);
393 en_ccb
.ccb_h
.func_code
= XPT_EN_LUN
;
394 /* Don't need support for any vendor specific commands */
395 en_ccb
.grp6_len
= grp6_len
;
396 en_ccb
.grp7_len
= grp7_len
;
397 en_ccb
.enable
= enable
? 1 : 0;
398 xpt_action((union ccb
*)&en_ccb
);
399 status
= en_ccb
.ccb_h
.status
& CAM_STATUS_MASK
;
400 if (status
!= CAM_REQ_CMP
) {
401 xpt_print(path
, "%sable lun CCB rejected, status %#x\n",
402 enable
? "en" : "dis", status
);
407 /* Enable target mode on a LUN, given its path */
409 targenable(struct targ_softc
*softc
, struct cam_path
*path
, int grp6_len
,
412 struct cam_periph
*periph
;
413 struct ccb_pathinq cpi
;
416 if ((softc
->state
& TARG_STATE_LUN_ENABLED
) != 0)
417 return (CAM_LUN_ALRDY_ENA
);
419 /* Make sure SIM supports target mode */
420 xpt_setup_ccb(&cpi
.ccb_h
, path
, /*priority*/1);
421 cpi
.ccb_h
.func_code
= XPT_PATH_INQ
;
422 xpt_action((union ccb
*)&cpi
);
423 status
= cpi
.ccb_h
.status
& CAM_STATUS_MASK
;
424 if (status
!= CAM_REQ_CMP
) {
425 kprintf("pathinq failed, status %#x\n", status
);
428 if ((cpi
.target_sprt
& PIT_PROCESSOR
) == 0) {
429 kprintf("controller does not support target mode\n");
430 status
= CAM_FUNC_NOTAVAIL
;
434 /* Destroy any periph on our path if it is disabled */
435 periph
= cam_periph_find(path
, "targ");
436 if (periph
!= NULL
) {
437 struct targ_softc
*del_softc
;
439 del_softc
= (struct targ_softc
*)periph
->softc
;
440 if ((del_softc
->state
& TARG_STATE_LUN_ENABLED
) == 0) {
441 cam_periph_invalidate(del_softc
->periph
);
442 del_softc
->periph
= NULL
;
444 kprintf("Requested path still in use by targ%d\n",
445 periph
->unit_number
);
446 status
= CAM_LUN_ALRDY_ENA
;
451 /* Create a periph instance attached to this path */
452 status
= cam_periph_alloc(targctor
, NULL
, targdtor
, targstart
,
453 "targ", CAM_PERIPH_BIO
, path
, targasync
, 0, softc
);
454 if (status
!= CAM_REQ_CMP
) {
455 kprintf("cam_periph_alloc failed, status %#x\n", status
);
459 /* Ensure that the periph now exists. */
460 if (cam_periph_find(path
, "targ") == NULL
) {
461 panic("targenable: succeeded but no periph?");
465 /* Send the enable lun message */
466 status
= targendislun(path
, /*enable*/1, grp6_len
, grp7_len
);
467 if (status
!= CAM_REQ_CMP
) {
468 kprintf("enable lun failed, status %#x\n", status
);
471 softc
->state
|= TARG_STATE_LUN_ENABLED
;
477 /* Disable this softc's target instance if enabled */
479 targdisable(struct targ_softc
*softc
)
483 if ((softc
->state
& TARG_STATE_LUN_ENABLED
) == 0)
484 return (CAM_REQ_CMP
);
486 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
, ("targdisable\n"));
488 /* Abort any ccbs pending on the controller */
490 abort_all_pending(softc
);
493 /* Disable this lun */
494 status
= targendislun(softc
->path
, /*enable*/0,
495 /*grp6_len*/0, /*grp7_len*/0);
496 if (status
== CAM_REQ_CMP
)
497 softc
->state
&= ~TARG_STATE_LUN_ENABLED
;
499 kprintf("Disable lun failed, status %#x\n", status
);
504 /* Initialize a periph (called from cam_periph_alloc) */
506 targctor(struct cam_periph
*periph
, void *arg
)
508 struct targ_softc
*softc
;
510 /* Store pointer to softc for periph-driven routines */
511 softc
= (struct targ_softc
*)arg
;
512 periph
->softc
= softc
;
513 softc
->periph
= periph
;
514 softc
->path
= periph
->path
;
515 return (CAM_REQ_CMP
);
519 targdtor(struct cam_periph
*periph
)
521 struct targ_softc
*softc
;
522 struct ccb_hdr
*ccb_h
;
523 struct targ_cmd_descr
*descr
;
525 softc
= (struct targ_softc
*)periph
->softc
;
528 * targdisable() aborts CCBs back to the user and leaves them
529 * on user_ccb_queue and abort_queue in case the user is still
530 * interested in them. We free them now.
532 while ((ccb_h
= TAILQ_FIRST(&softc
->user_ccb_queue
)) != NULL
) {
533 TAILQ_REMOVE(&softc
->user_ccb_queue
, ccb_h
, periph_links
.tqe
);
534 targfreeccb(softc
, (union ccb
*)ccb_h
);
536 while ((descr
= TAILQ_FIRST(&softc
->abort_queue
)) != NULL
) {
537 TAILQ_REMOVE(&softc
->abort_queue
, descr
, tqe
);
541 softc
->periph
= NULL
;
543 periph
->softc
= NULL
;
546 /* Receive CCBs from user mode proc and send them to the HBA */
548 targwrite(struct dev_write_args
*ap
)
550 struct uio
*uio
= ap
->a_uio
;
552 struct targ_softc
*softc
;
553 struct targ_cmd_descr
*descr
;
554 int write_len
, error
;
555 int func_code
, priority
;
557 softc
= (struct targ_softc
*)ap
->a_head
.a_dev
->si_drv1
;
558 write_len
= error
= 0;
559 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
560 ("write - uio_resid %d\n", uio
->uio_resid
));
561 while (uio
->uio_resid
>= sizeof(user_ccb
) && error
== 0) {
564 error
= uiomove((caddr_t
)&user_ccb
, sizeof(user_ccb
), uio
);
566 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
567 ("write - uiomove failed (%d)\n", error
));
570 priority
= fuword(&user_ccb
->ccb_h
.pinfo
.priority
);
571 if (priority
== -1) {
575 func_code
= fuword(&user_ccb
->ccb_h
.func_code
);
577 case XPT_ACCEPT_TARGET_IO
:
578 case XPT_IMMED_NOTIFY
:
579 cam_periph_lock(softc
->periph
);
580 ccb
= targgetccb(softc
, func_code
, priority
);
581 descr
= (struct targ_cmd_descr
*)ccb
->ccb_h
.targ_descr
;
582 descr
->user_ccb
= user_ccb
;
583 descr
->func_code
= func_code
;
584 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
585 ("Sent ATIO/INOT (%p)\n", user_ccb
));
587 TAILQ_INSERT_TAIL(&softc
->pending_ccb_queue
,
590 cam_periph_unlock(softc
->periph
);
593 cam_periph_lock(softc
->periph
);
594 if ((func_code
& XPT_FC_QUEUED
) != 0) {
595 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
596 ("Sending queued ccb %#x (%p)\n",
597 func_code
, user_ccb
));
598 descr
= targgetdescr(softc
);
599 descr
->user_ccb
= user_ccb
;
600 descr
->priority
= priority
;
601 descr
->func_code
= func_code
;
603 TAILQ_INSERT_TAIL(&softc
->work_queue
,
606 xpt_schedule(softc
->periph
, priority
);
608 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
609 ("Sending inline ccb %#x (%p)\n",
610 func_code
, user_ccb
));
611 ccb
= targgetccb(softc
, func_code
, priority
);
612 descr
= (struct targ_cmd_descr
*)
613 ccb
->ccb_h
.targ_descr
;
614 descr
->user_ccb
= user_ccb
;
615 descr
->priority
= priority
;
616 descr
->func_code
= func_code
;
617 if (targusermerge(softc
, descr
, ccb
) != EFAULT
)
618 targsendccb(softc
, ccb
, descr
);
619 targreturnccb(softc
, ccb
);
621 cam_periph_unlock(softc
->periph
);
624 write_len
+= sizeof(user_ccb
);
628 * If we've successfully taken in some amount of
629 * data, return success for that data first. If
630 * an error is persistent, it will be reported
633 if (error
!= 0 && write_len
== 0)
635 if (write_len
== 0 && uio
->uio_resid
!= 0)
640 /* Process requests (descrs) via the periph-supplied CCBs */
642 targstart(struct cam_periph
*periph
, union ccb
*start_ccb
)
644 struct targ_softc
*softc
;
645 struct targ_cmd_descr
*descr
, *next_descr
;
648 softc
= (struct targ_softc
*)periph
->softc
;
649 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
, ("targstart %p\n", start_ccb
));
652 descr
= TAILQ_FIRST(&softc
->work_queue
);
655 xpt_release_ccb(start_ccb
);
657 TAILQ_REMOVE(&softc
->work_queue
, descr
, tqe
);
658 next_descr
= TAILQ_FIRST(&softc
->work_queue
);
661 /* Initiate a transaction using the descr and supplied CCB */
662 error
= targusermerge(softc
, descr
, start_ccb
);
664 error
= targsendccb(softc
, start_ccb
, descr
);
666 xpt_print(periph
->path
,
667 "targsendccb failed, err %d\n", error
);
668 xpt_release_ccb(start_ccb
);
669 suword(&descr
->user_ccb
->ccb_h
.status
,
672 TAILQ_INSERT_TAIL(&softc
->abort_queue
, descr
, tqe
);
677 /* If we have more work to do, stay scheduled */
678 if (next_descr
!= NULL
)
679 xpt_schedule(periph
, next_descr
->priority
);
684 targusermerge(struct targ_softc
*softc
, struct targ_cmd_descr
*descr
,
687 struct ccb_hdr
*u_ccbh
, *k_ccbh
;
691 u_ccbh
= &descr
->user_ccb
->ccb_h
;
692 k_ccbh
= &ccb
->ccb_h
;
695 * There are some fields in the CCB header that need to be
696 * preserved, the rest we get from the user ccb. (See xpt_merge_ccb)
698 xpt_setup_ccb(k_ccbh
, softc
->path
, descr
->priority
);
699 k_ccbh
->retry_count
= fuword(&u_ccbh
->retry_count
);
700 k_ccbh
->func_code
= descr
->func_code
;
701 k_ccbh
->flags
= fuword(&u_ccbh
->flags
);
702 k_ccbh
->timeout
= fuword(&u_ccbh
->timeout
);
703 ccb_len
= targccblen(k_ccbh
->func_code
) - sizeof(struct ccb_hdr
);
704 error
= copyin(u_ccbh
+ 1, k_ccbh
+ 1, ccb_len
);
706 k_ccbh
->status
= CAM_REQ_CMP_ERR
;
710 /* Translate usermode abort_ccb pointer to its kernel counterpart */
711 if (k_ccbh
->func_code
== XPT_ABORT
) {
712 struct ccb_abort
*cab
;
713 struct ccb_hdr
*ccb_h
;
715 cab
= (struct ccb_abort
*)ccb
;
717 TAILQ_FOREACH(ccb_h
, &softc
->pending_ccb_queue
,
719 struct targ_cmd_descr
*ab_descr
;
721 ab_descr
= (struct targ_cmd_descr
*)ccb_h
->targ_descr
;
722 if (ab_descr
->user_ccb
== cab
->abort_ccb
) {
723 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
724 ("Changing abort for %p to %p\n",
725 cab
->abort_ccb
, ccb_h
));
726 cab
->abort_ccb
= (union ccb
*)ccb_h
;
731 /* CCB not found, set appropriate status */
733 k_ccbh
->status
= CAM_PATH_INVALID
;
741 /* Build and send a kernel CCB formed from descr->user_ccb */
743 targsendccb(struct targ_softc
*softc
, union ccb
*ccb
,
744 struct targ_cmd_descr
*descr
)
746 struct cam_periph_map_info
*mapinfo
;
747 struct ccb_hdr
*ccb_h
;
751 mapinfo
= &descr
->mapinfo
;
752 mapinfo
->num_bufs_used
= 0;
755 * There's no way for the user to have a completion
756 * function, so we put our own completion function in here.
757 * We also stash in a reference to our descriptor so targreturnccb()
758 * can find our mapping info.
760 ccb_h
->cbfcnp
= targdone
;
761 ccb_h
->targ_descr
= descr
;
764 * We only attempt to map the user memory into kernel space
765 * if they haven't passed in a physical memory pointer,
766 * and if there is actually an I/O operation to perform.
767 * Right now cam_periph_mapmem() only supports SCSI and device
768 * match CCBs. For the SCSI CCBs, we only pass the CCB in if
769 * there's actually data to map. cam_periph_mapmem() will do the
770 * right thing, even if there isn't data to map, but since CCBs
771 * without data are a reasonably common occurance (e.g. test unit
772 * ready), it will save a few cycles if we check for it here.
774 if (((ccb_h
->flags
& CAM_DATA_PHYS
) == 0)
775 && (((ccb_h
->func_code
== XPT_CONT_TARGET_IO
)
776 && ((ccb_h
->flags
& CAM_DIR_MASK
) != CAM_DIR_NONE
))
777 || (ccb_h
->func_code
== XPT_DEV_MATCH
))) {
779 error
= cam_periph_mapmem(ccb
, mapinfo
);
782 * cam_periph_mapmem returned an error, we can't continue.
783 * Return the error to the user.
786 ccb_h
->status
= CAM_REQ_CMP_ERR
;
787 mapinfo
->num_bufs_used
= 0;
793 * Once queued on the pending CCB list, this CCB will be protected
794 * by our error recovery handler.
796 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
, ("sendccb %p\n", ccb
));
797 if (XPT_FC_IS_QUEUED(ccb
)) {
799 TAILQ_INSERT_TAIL(&softc
->pending_ccb_queue
, ccb_h
,
808 /* Completion routine for CCBs (called in a critical section) */
810 targdone(struct cam_periph
*periph
, union ccb
*done_ccb
)
812 struct targ_softc
*softc
;
815 CAM_DEBUG(periph
->path
, CAM_DEBUG_PERIPH
, ("targdone %p\n", done_ccb
));
816 softc
= (struct targ_softc
*)periph
->softc
;
817 TAILQ_REMOVE(&softc
->pending_ccb_queue
, &done_ccb
->ccb_h
,
819 status
= done_ccb
->ccb_h
.status
& CAM_STATUS_MASK
;
821 /* If we're no longer enabled, throw away CCB */
822 if ((softc
->state
& TARG_STATE_LUN_ENABLED
) == 0) {
823 targfreeccb(softc
, done_ccb
);
826 /* abort_all_pending() waits for pending queue to be empty */
827 if (TAILQ_EMPTY(&softc
->pending_ccb_queue
))
828 wakeup(&softc
->pending_ccb_queue
);
830 switch (done_ccb
->ccb_h
.func_code
) {
831 /* All FC_*_QUEUED CCBs go back to userland */
832 case XPT_IMMED_NOTIFY
:
833 case XPT_ACCEPT_TARGET_IO
:
834 case XPT_CONT_TARGET_IO
:
835 TAILQ_INSERT_TAIL(&softc
->user_ccb_queue
, &done_ccb
->ccb_h
,
840 panic("targdone: impossible xpt opcode %#x",
841 done_ccb
->ccb_h
.func_code
);
846 /* Return CCBs to the user from the user queue and abort queue */
848 targread(struct dev_read_args
*ap
)
850 struct uio
*uio
= ap
->a_uio
;
851 struct descr_queue
*abort_queue
;
852 struct targ_cmd_descr
*user_descr
;
853 struct targ_softc
*softc
;
854 struct ccb_queue
*user_queue
;
855 struct ccb_hdr
*ccb_h
;
861 softc
= (struct targ_softc
*)ap
->a_head
.a_dev
->si_drv1
;
862 user_queue
= &softc
->user_ccb_queue
;
863 abort_queue
= &softc
->abort_queue
;
864 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
, ("targread\n"));
866 /* If no data is available, wait or return immediately */
867 cam_periph_lock(softc
->periph
);
868 ccb_h
= TAILQ_FIRST(user_queue
);
869 user_descr
= TAILQ_FIRST(abort_queue
);
870 while (ccb_h
== NULL
&& user_descr
== NULL
) {
871 if ((ap
->a_ioflag
& IO_NDELAY
) == 0) {
872 error
= sim_lock_sleep(user_queue
, PCATCH
, "targrd", 0,
873 softc
->periph
->sim
->lock
);
874 ccb_h
= TAILQ_FIRST(user_queue
);
875 user_descr
= TAILQ_FIRST(abort_queue
);
877 if (error
== ERESTART
) {
884 cam_periph_unlock(softc
->periph
);
889 /* Data is available so fill the user's buffer */
890 while (ccb_h
!= NULL
) {
891 struct targ_cmd_descr
*descr
;
893 if (uio
->uio_resid
< sizeof(user_ccb
))
895 TAILQ_REMOVE(user_queue
, ccb_h
, periph_links
.tqe
);
896 descr
= (struct targ_cmd_descr
*)ccb_h
->targ_descr
;
897 user_ccb
= descr
->user_ccb
;
898 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
899 ("targread ccb %p (%p)\n", ccb_h
, user_ccb
));
900 error
= targreturnccb(softc
, (union ccb
*)ccb_h
);
903 cam_periph_unlock(softc
->periph
);
904 error
= uiomove((caddr_t
)&user_ccb
, sizeof(user_ccb
), uio
);
905 cam_periph_lock(softc
->periph
);
908 read_len
+= sizeof(user_ccb
);
910 ccb_h
= TAILQ_FIRST(user_queue
);
913 /* Flush out any aborted descriptors */
914 while (user_descr
!= NULL
) {
915 if (uio
->uio_resid
< sizeof(user_ccb
))
917 TAILQ_REMOVE(abort_queue
, user_descr
, tqe
);
918 user_ccb
= user_descr
->user_ccb
;
919 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
920 ("targread aborted descr %p (%p)\n",
921 user_descr
, user_ccb
));
922 suword(&user_ccb
->ccb_h
.status
, CAM_REQ_ABORTED
);
923 cam_periph_unlock(softc
->periph
);
924 error
= uiomove((caddr_t
)&user_ccb
, sizeof(user_ccb
), uio
);
925 cam_periph_lock(softc
->periph
);
928 read_len
+= sizeof(user_ccb
);
930 user_descr
= TAILQ_FIRST(abort_queue
);
934 * If we've successfully read some amount of data, don't report an
935 * error. If the error is persistent, it will be reported on the
938 if (read_len
== 0 && uio
->uio_resid
!= 0)
942 cam_periph_unlock(softc
->periph
);
946 /* Copy completed ccb back to the user */
948 targreturnccb(struct targ_softc
*softc
, union ccb
*ccb
)
950 struct targ_cmd_descr
*descr
;
951 struct ccb_hdr
*u_ccbh
;
955 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
, ("targreturnccb %p\n", ccb
));
956 descr
= (struct targ_cmd_descr
*)ccb
->ccb_h
.targ_descr
;
957 u_ccbh
= &descr
->user_ccb
->ccb_h
;
959 /* Copy out the central portion of the ccb_hdr */
960 copyout(&ccb
->ccb_h
.retry_count
, &u_ccbh
->retry_count
,
961 offsetof(struct ccb_hdr
, periph_priv
) -
962 offsetof(struct ccb_hdr
, retry_count
));
964 /* Copy out the rest of the ccb (after the ccb_hdr) */
965 ccb_len
= targccblen(ccb
->ccb_h
.func_code
) - sizeof(struct ccb_hdr
);
966 if (descr
->mapinfo
.num_bufs_used
!= 0)
967 cam_periph_unmapmem(ccb
, &descr
->mapinfo
);
968 error
= copyout(&ccb
->ccb_h
+ 1, u_ccbh
+ 1, ccb_len
);
970 xpt_print(softc
->path
,
971 "targreturnccb - CCB copyout failed (%d)\n", error
);
973 /* Free CCB or send back to devq. */
974 targfreeccb(softc
, ccb
);
980 targgetccb(struct targ_softc
*softc
, xpt_opcode type
, int priority
)
985 ccb_len
= targccblen(type
);
986 MALLOC(ccb
, union ccb
*, ccb_len
, M_TARG
, M_INTWAIT
);
987 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
, ("getccb %p\n", ccb
));
989 xpt_setup_ccb(&ccb
->ccb_h
, softc
->path
, priority
);
990 ccb
->ccb_h
.func_code
= type
;
991 ccb
->ccb_h
.cbfcnp
= targdone
;
992 ccb
->ccb_h
.targ_descr
= targgetdescr(softc
);
997 targfreeccb(struct targ_softc
*softc
, union ccb
*ccb
)
999 CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH
, ("targfreeccb descr %p and\n",
1000 ccb
->ccb_h
.targ_descr
));
1001 FREE(ccb
->ccb_h
.targ_descr
, M_TARG
);
1003 switch (ccb
->ccb_h
.func_code
) {
1004 case XPT_ACCEPT_TARGET_IO
:
1005 case XPT_IMMED_NOTIFY
:
1006 CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH
, ("freeing ccb %p\n", ccb
));
1010 /* Send back CCB if we got it from the periph */
1011 if (XPT_FC_IS_QUEUED(ccb
)) {
1012 CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH
,
1013 ("returning queued ccb %p\n", ccb
));
1014 xpt_release_ccb(ccb
);
1016 CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH
,
1017 ("freeing ccb %p\n", ccb
));
1024 static struct targ_cmd_descr
*
1025 targgetdescr(struct targ_softc
*softc
)
1027 struct targ_cmd_descr
*descr
;
1029 MALLOC(descr
, struct targ_cmd_descr
*, sizeof(*descr
),
1031 descr
->mapinfo
.num_bufs_used
= 0;
1038 dev_ops_add(&targ_ops
, 0, 0);
1042 targasync(void *callback_arg
, u_int32_t code
, struct cam_path
*path
, void *arg
)
1044 /* All events are handled in usermode by INOTs */
1045 panic("targasync() called, should be an INOT instead");
1048 /* Cancel all pending requests and CCBs awaiting work. */
1050 abort_all_pending(struct targ_softc
*softc
)
1052 struct targ_cmd_descr
*descr
;
1053 struct ccb_abort cab
;
1054 struct ccb_hdr
*ccb_h
;
1055 struct cam_sim
*sim
;
1057 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
, ("abort_all_pending\n"));
1059 /* First abort the descriptors awaiting resources */
1060 while ((descr
= TAILQ_FIRST(&softc
->work_queue
)) != NULL
) {
1061 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
1062 ("Aborting descr from workq %p\n", descr
));
1063 TAILQ_REMOVE(&softc
->work_queue
, descr
, tqe
);
1064 TAILQ_INSERT_TAIL(&softc
->abort_queue
, descr
, tqe
);
1068 * Then abort all pending CCBs.
1069 * targdone() will return the aborted CCB via user_ccb_queue
1071 xpt_setup_ccb(&cab
.ccb_h
, softc
->path
, /*priority*/0);
1072 cab
.ccb_h
.func_code
= XPT_ABORT
;
1073 cab
.ccb_h
.status
= CAM_REQ_CMP_ERR
;
1074 TAILQ_FOREACH(ccb_h
, &softc
->pending_ccb_queue
, periph_links
.tqe
) {
1075 CAM_DEBUG(softc
->path
, CAM_DEBUG_PERIPH
,
1076 ("Aborting pending CCB %p\n", ccb_h
));
1077 cab
.abort_ccb
= (union ccb
*)ccb_h
;
1078 xpt_action((union ccb
*)&cab
);
1079 if (cab
.ccb_h
.status
!= CAM_REQ_CMP
) {
1080 xpt_print(cab
.ccb_h
.path
,
1081 "Unable to abort CCB, status %#x\n",
1086 /* If we aborted at least one pending CCB ok, wait for it. */
1087 if (cab
.ccb_h
.status
== CAM_REQ_CMP
) {
1088 sim
= xpt_path_sim(softc
->path
);
1089 sim_lock_sleep(&softc
->pending_ccb_queue
, PCATCH
, "tgabrt", 0,
1093 /* If we aborted anything from the work queue, wakeup user. */
1094 if (!TAILQ_EMPTY(&softc
->user_ccb_queue
)
1095 || !TAILQ_EMPTY(&softc
->abort_queue
))
1099 /* Notify the user that data is ready */
1101 notify_user(struct targ_softc
*softc
)
1104 * Notify users sleeping via poll(), kqueue(), and
1107 selwakeup(&softc
->read_select
);
1108 KNOTE(&softc
->read_select
.si_note
, 0);
1109 wakeup(&softc
->user_ccb_queue
);
1112 /* Convert CAM status to errno values */
1114 targcamstatus(cam_status status
)
1116 switch (status
& CAM_STATUS_MASK
) {
1117 case CAM_REQ_CMP
: /* CCB request completed without error */
1119 case CAM_REQ_INPROG
: /* CCB request is in progress */
1120 return (EINPROGRESS
);
1121 case CAM_REQ_CMP_ERR
: /* CCB request completed with an error */
1123 case CAM_PROVIDE_FAIL
: /* Unable to provide requested capability */
1125 case CAM_FUNC_NOTAVAIL
: /* The requested function is not available */
1127 case CAM_LUN_ALRDY_ENA
: /* LUN is already enabled for target mode */
1128 return (EADDRINUSE
);
1129 case CAM_PATH_INVALID
: /* Supplied Path ID is invalid */
1130 case CAM_DEV_NOT_THERE
: /* SCSI Device Not Installed/there */
1132 case CAM_REQ_ABORTED
: /* CCB request aborted by the host */
1134 case CAM_CMD_TIMEOUT
: /* Command timeout */
1136 case CAM_REQUEUE_REQ
: /* Requeue to preserve transaction ordering */
1138 case CAM_REQ_INVALID
: /* CCB request was invalid */
1140 case CAM_RESRC_UNAVAIL
: /* Resource Unavailable */
1142 case CAM_BUSY
: /* CAM subsytem is busy */
1143 case CAM_UA_ABORT
: /* Unable to abort CCB request */
1151 targccblen(xpt_opcode func_code
)
1155 /* Codes we expect to see as a target */
1156 switch (func_code
) {
1157 case XPT_CONT_TARGET_IO
:
1159 len
= sizeof(struct ccb_scsiio
);
1161 case XPT_ACCEPT_TARGET_IO
:
1162 len
= sizeof(struct ccb_accept_tio
);
1164 case XPT_IMMED_NOTIFY
:
1165 len
= sizeof(struct ccb_immed_notify
);
1168 len
= sizeof(struct ccb_relsim
);
1171 len
= sizeof(struct ccb_pathinq
);
1174 len
= sizeof(struct ccb_debug
);
1177 len
= sizeof(struct ccb_abort
);
1180 len
= sizeof(struct ccb_en_lun
);
1183 len
= sizeof(union ccb
);