37#include <sys/kernel.h>
39#include <sys/malloc.h>
44#include <sys/devicestat.h>
67#define targ_descr periph_priv.entries[1].ptr
117 .d_version = D_VERSION,
128 int grp6_len,
int grp7_len);
131 int grp6_len,
int grp7_len);
142 union ccb *done_ccb);
151static void targasync(
void *callback_arg, u_int32_t code,
175 if (
softc->periph == NULL) {
176 printf(
"%s: destroying non-enabled target\n", __func__);
185 periph =
softc->periph;
189 if (
softc->periph != NULL) {
191 softc->periph = NULL;
209 softc = malloc(
sizeof(*softc), M_TARG,
219 knlist_init_mtx(&softc->
read_select.si_note, NULL);
227targioctl(
struct cdev *dev, u_long cmd, caddr_t addr,
int flag,
struct thread *td)
232 devfs_get_cdevpriv((
void **)&softc);
246 printf(
"Couldn't create path, status %#x\n", status);
257 if (softc->
periph == NULL) {
274 bzero(&cdbg,
sizeof cdbg);
275 if (*((
int *)addr) != 0)
296targpoll(
struct cdev *dev,
int poll_events,
struct thread *td)
301 devfs_get_cdevpriv((
void **)&softc);
304 revents = poll_events & (POLLOUT | POLLWRNORM);
305 if ((poll_events & (POLLIN | POLLRDNORM)) != 0) {
310 revents |= poll_events & (POLLIN | POLLRDNORM);
326 devfs_get_cdevpriv((
void **)&softc);
327 kn->kn_hook = (caddr_t)softc;
365 memset(&en_ccb, 0,
sizeof(en_ccb));
375 xpt_print(path,
"%sable lun CCB rejected, status %#x\n",
376 enable ?
"en" :
"dis", status);
397 printf(
"pathinq failed, status %#x\n", status);
401 printf(
"controller does not support target mode\n");
406 softc->
maxio = DFLTPHYS;
407 else if (cpi.
maxio > maxphys)
408 softc->
maxio = maxphys;
414 if (periph != NULL) {
422 printf(
"Requested path still in use by targ%d\n",
433 printf(
"cam_periph_alloc failed, status %#x\n", status);
439 panic(
"targenable: succeeded but no periph?");
446 printf(
"enable lun failed, status %#x\n", status);
473 softc->
state &= ~TARG_STATE_LUN_ENABLED;
475 printf(
"Disable lun failed, status %#x\n", status);
512 while ((descr = TAILQ_FIRST(&softc->
abort_queue)) != NULL) {
529 int write_len, error;
530 int func_code, priority;
532 devfs_get_cdevpriv((
void **)&softc);
533 write_len = error = 0;
535 (
"write - uio_resid %zd\n", uio->uio_resid));
536 while (uio->uio_resid >=
sizeof(user_ccb) && error == 0) {
539 error = uiomove((caddr_t)&user_ccb,
sizeof(user_ccb), uio);
542 (
"write - uiomove failed (%d)\n", error));
545 priority = fuword32(&user_ccb->ccb_h.pinfo.priority);
550 func_code = fuword32(&user_ccb->ccb_h.func_code);
558 descr->user_ccb = user_ccb;
559 descr->func_code = func_code;
561 (
"Sent ATIO/INOT (%p)\n", user_ccb));
572 (
"Sending queued ccb %#x (%p)\n",
573 func_code, user_ccb));
575 descr->user_ccb = user_ccb;
576 descr->priority = priority;
577 descr->func_code = func_code;
583 (
"Sending inline ccb %#x (%p)\n",
584 func_code, user_ccb));
588 descr->user_ccb = user_ccb;
589 descr->priority = priority;
590 descr->func_code = func_code;
598 write_len +=
sizeof(user_ccb);
607 if (error != 0 && write_len == 0)
609 if (write_len == 0 && uio->uio_resid != 0)
638 "targsendccb failed, err %d\n", error);
640 suword(&descr->user_ccb->ccb_h.status,
642 TAILQ_INSERT_TAIL(&softc->
abort_queue, descr, tqe);
647 if (next_descr != NULL)
656 struct ccb_hdr *u_ccbh, *k_ccbh;
660 u_ccbh = &descr->user_ccb->ccb_h;
673 error = copyin(u_ccbh + 1, k_ccbh + 1, ccb_len);
690 if (ab_descr->user_ccb == cab->
abort_ccb) {
692 (
"Changing abort for %p to %p\n",
728 ccb_h->targ_descr = descr;
792 panic(
"targdone: impossible xpt opcode %#x",
800targread(
struct cdev *dev,
struct uio *uio,
int ioflag)
802 struct descr_queue *abort_queue;
805 struct ccb_queue *user_queue;
812 devfs_get_cdevpriv((
void **)&softc);
819 ccb_h = TAILQ_FIRST(user_queue);
820 user_descr = TAILQ_FIRST(abort_queue);
821 while (
ccb_h == NULL && user_descr == NULL) {
822 if ((ioflag & IO_NDELAY) == 0) {
824 PRIBIO | PCATCH,
"targrd", 0);
825 ccb_h = TAILQ_FIRST(user_queue);
826 user_descr = TAILQ_FIRST(abort_queue);
828 if (error == ERESTART) {
841 while (
ccb_h != NULL) {
844 if (uio->uio_resid <
sizeof(user_ccb))
846 TAILQ_REMOVE(user_queue, ccb_h, periph_links.tqe);
848 user_ccb = descr->user_ccb;
850 (
"targread ccb %p (%p)\n", ccb_h, user_ccb));
855 error = uiomove((caddr_t)&user_ccb,
sizeof(user_ccb), uio);
859 read_len +=
sizeof(user_ccb);
861 ccb_h = TAILQ_FIRST(user_queue);
865 while (user_descr != NULL) {
866 if (uio->uio_resid <
sizeof(user_ccb))
868 TAILQ_REMOVE(abort_queue, user_descr, tqe);
869 user_ccb = user_descr->user_ccb;
871 (
"targread aborted descr %p (%p)\n",
872 user_descr, user_ccb));
875 error = uiomove((caddr_t)&user_ccb,
sizeof(user_ccb), uio);
879 read_len +=
sizeof(user_ccb);
881 user_descr = TAILQ_FIRST(abort_queue);
889 if (read_len == 0 && uio->uio_resid != 0)
908 u_ccbh = &descr->user_ccb->ccb_h;
912 offsetof(
struct ccb_hdr, periph_priv) -
913 offsetof(
struct ccb_hdr, retry_count));
919 error = copyout(&
ccb->
ccb_h + 1, u_ccbh + 1, ccb_len);
922 "targreturnccb - CCB copyout failed (%d)\n", error);
937 ccb = malloc(ccb_len, M_TARG, M_NOWAIT | M_ZERO);
946 if (
ccb->
ccb_h.targ_descr == NULL) {
958 free(
ccb->
ccb_h.targ_descr, M_TARG);
971 (
"returning queued ccb %p\n",
ccb));
975 (
"freeing ccb %p\n",
ccb));
987 descr = malloc(
sizeof(*descr), M_TARG,
1001 dev = make_dev(&
targ_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
"targ");
1002 make_dev_alias(dev,
"targ0");
1009 panic(
"targasync() called, should be an INOT instead");
1023 while ((descr = TAILQ_FIRST(&softc->
work_queue)) != NULL) {
1025 (
"Aborting descr from workq %p\n", descr));
1026 TAILQ_REMOVE(&softc->
work_queue, descr, tqe);
1027 TAILQ_INSERT_TAIL(&softc->
abort_queue, descr, tqe);
1034 memset(&cab, 0,
sizeof(cab));
1040 (
"Aborting pending CCB %p\n", ccb_h));
1045 "Unable to abort CCB, status %#x\n",
1053 PRIBIO | PCATCH,
"tgabrt", 0);
1086 return (EINPROGRESS);
1094 return (EADDRINUSE);
1122 switch (func_code) {
1152 len =
sizeof(
union ccb);
#define CAM_PRIORITY_NORMAL
#define CAM_PRIORITY_NONE
#define XPT_FC_IS_QUEUED(ccb)
#define CAM_DEBUG(path, flag, printfargs)
#define CAM_DEBUG_PRINT(flag, printfargs)
struct cam_periph * cam_periph_find(struct cam_path *path, char *name)
void cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
int cam_periph_acquire(struct cam_periph *periph)
void cam_periph_release(struct cam_periph *periph)
void cam_periph_invalidate(struct cam_periph *periph)
int cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo, u_int maxmap)
cam_status cam_periph_alloc(periph_ctor_t *periph_ctor, periph_oninv_t *periph_oninvalidate, periph_dtor_t *periph_dtor, periph_start_t *periph_start, char *name, cam_periph_type type, struct cam_path *path, ac_callback_t *ac_callback, ac_code code, void *arg)
cam_status periph_ctor_t(struct cam_periph *periph, void *arg)
#define cam_periph_lock(periph)
#define cam_periph_unlock(periph)
void periph_dtor_t(struct cam_periph *periph)
void periph_start_t(struct cam_periph *periph, union ccb *start_ccb)
#define cam_periph_sleep(periph, chan, priority, wmesg, timo)
void() periph_init_t(void)
void xpt_schedule(struct cam_periph *periph, u_int32_t new_priority)
cam_status xpt_create_path(struct cam_path **new_path_ptr, struct cam_periph *perph, path_id_t path_id, target_id_t target_id, lun_id_t lun_id)
void xpt_print(struct cam_path *path, const char *fmt,...)
void xpt_setup_ccb(struct ccb_hdr *ccb_h, struct cam_path *path, u_int32_t priority)
void xpt_action(union ccb *start_ccb)
void xpt_free_path(struct cam_path *path)
void xpt_release_ccb(union ccb *free_ccb)
#define xpt_path_unlock(path)
#define xpt_path_lock(path)
static void xpt_path_inq(struct ccb_pathinq *cpi, struct cam_path *path)
static int targreadfilt(struct knote *kn, long hint)
static void targasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
PERIPHDRIVER_DECLARE(targ, targdriver)
static periph_dtor_t targdtor
static d_kqfilter_t targkqfilter
TAILQ_HEAD(descr_queue, targ_cmd_descr)
static void targdone(struct cam_periph *periph, union ccb *done_ccb)
static void notify_user(struct targ_softc *softc)
static int targusermerge(struct targ_softc *softc, struct targ_cmd_descr *descr, union ccb *ccb)
static union ccb * targgetccb(struct targ_softc *softc, xpt_opcode type, int priority)
static struct periph_driver targdriver
static int targcamstatus(cam_status status)
static periph_init_t targinit
static int targsendccb(struct targ_softc *softc, union ccb *ccb, struct targ_cmd_descr *descr)
static periph_start_t targstart
static struct cdevsw targ_cdevsw
static d_ioctl_t targioctl
static cam_status targenable(struct targ_softc *softc, struct cam_path *path, int grp6_len, int grp7_len)
static void targfreeccb(struct targ_softc *softc, union ccb *ccb)
static size_t targccblen(xpt_opcode func_code)
static void abort_all_pending(struct targ_softc *softc)
static void targcdevdtor(void *data)
static cam_status targdisable(struct targ_softc *softc)
static struct filterops targread_filtops
static MALLOC_DEFINE(M_TARG, "TARG", "TARG data")
static int targreturnccb(struct targ_softc *softc, union ccb *ccb)
static cam_status targendislun(struct cam_path *path, int enable, int grp6_len, int grp7_len)
static d_write_t targwrite
static void targreadfiltdetach(struct knote *kn)
static periph_ctor_t targctor
static struct targ_cmd_descr * targgetdescr(struct targ_softc *softc)
void(* cbfcnp)(struct cam_periph *, union ccb *)
struct cam_periph_map_info mapinfo
struct descr_queue work_queue
struct selinfo read_select
struct ccb_queue user_ccb_queue
struct devstat device_stats
struct descr_queue abort_queue
struct ccb_queue pending_ccb_queue
struct cam_periph * periph