35#include <sys/kernel.h>
40#include <sys/devicestat.h>
43#include <sys/malloc.h>
46#include <sys/selinfo.h>
48#include <sys/sysent.h>
49#include <sys/taskqueue.h>
52#include <vm/vm_extern.h>
54#include <machine/bus.h>
89#define ccb_type ppriv_field0
90#define ccb_ioreq ppriv_ptr1
95#define PASS_MAX_SEGS 16
146 char io_zone_name[12];
147 uma_zone_t pass_zone;
148 uma_zone_t pass_io_zone;
168static void passasync(
void *callback_arg, u_int32_t code,
171 union ccb *done_ccb);
183 u_int32_t sense_flags);
196 .d_version = D_VERSION,
197 .d_flags = D_TRACKCLOSE,
226 printf(
"pass: Failed to attach master async callback "
227 "due to status 0x%x!\n", status);
244 TAILQ_FOREACH_SAFE(io_req, &softc->done_queue, links, io_req2) {
245 TAILQ_REMOVE(&softc->done_queue, io_req, links);
247 uma_zfree(softc->pass_zone, io_req);
255 TAILQ_FOREACH_SAFE(io_req, &softc->incoming_queue, links, io_req2) {
256 TAILQ_REMOVE(&softc->incoming_queue, io_req, links);
258 uma_zfree(softc->pass_zone, io_req);
270 TAILQ_FOREACH_SAFE(io_req, &softc->active_queue, links, io_req2) {
271 TAILQ_REMOVE(&softc->active_queue, io_req, links);
273 TAILQ_INSERT_TAIL(&softc->abandoned_queue, io_req, links);
279 if ((!TAILQ_EMPTY(&softc->abandoned_queue))
299 KASSERT(softc->
open_count >= 0, (
"Negative open count %d",
365 KASSERT(TAILQ_EMPTY(&softc->active_queue),
366 (
"%s called when there are commands on the active queue!\n",
368 KASSERT(TAILQ_EMPTY(&softc->abandoned_queue),
369 (
"%s called when there are commands on the abandoned queue!\n",
371 KASSERT(TAILQ_EMPTY(&softc->incoming_queue),
372 (
"%s called when there are commands on the incoming queue!\n",
374 KASSERT(TAILQ_EMPTY(&softc->done_queue),
375 (
"%s called when there are commands on the done queue!\n",
407 if (softc->pass_zone != NULL)
408 uma_zdestroy(softc->pass_zone);
409 if (softc->pass_io_zone != NULL)
410 uma_zdestroy(softc->pass_io_zone);
414 free(softc, M_DEVBUF);
424 softc = periph->
softc;
448 softc = periph->
softc;
449 physpath = malloc(MAXPATHLEN, M_DEVBUF, M_WAITOK);
457 "GEOM::physpath", periph->
path) == 0
458 && strlen(physpath) != 0) {
460 make_dev_physpath_alias(MAKEDEV_WAITOK, &softc->
alias_dev,
477 while (pending-- > 0)
481 free(physpath, M_DEVBUF);
518 printf(
"passasync: Unable to attach new device "
519 "due to status %#x: %s\n", status, entry ?
529 buftype = (uintptr_t)arg;
543 taskqueue_enqueue(taskqueue_thread,
560 struct make_dev_args args;
565 printf(
"%s: no getdev CCB, can't register device\n", __func__);
569 softc = (
struct pass_softc *)malloc(
sizeof(*softc),
573 printf(
"%s: Unable to probe new device. "
574 "Unable to allocate softc\n", __func__);
578 bzero(softc,
sizeof(*softc));
587 periph->
softc = softc;
588 softc->periph = periph;
589 TAILQ_INIT(&softc->incoming_queue);
590 TAILQ_INIT(&softc->active_queue);
591 TAILQ_INIT(&softc->abandoned_queue);
592 TAILQ_INIT(&softc->done_queue);
593 snprintf(softc->zone_name,
sizeof(softc->zone_name),
"%s%d",
595 snprintf(softc->io_zone_name,
sizeof(softc->io_zone_name),
"%s%dIO",
597 softc->io_zone_size = maxphys;
603 softc->
maxio = DFLTPHYS;
604 else if (cpi.
maxio > maxphys)
605 softc->
maxio = maxphys;
622 | (no_tags ? DEVSTAT_NO_ORDERED_TAGS : 0),
626 DEVSTAT_PRIORITY_PASS);
640 "registration!\n", __func__);
652 "registration!\n", __func__);
658 make_dev_args_init(&args);
661 args.mda_uid = UID_ROOT;
662 args.mda_gid = GID_OPERATOR;
663 args.mda_mode = 0600;
664 args.mda_si_drv1 = periph;
665 args.mda_flags = MAKEDEV_NOWAIT;
666 error = make_dev_s(&args, &softc->
dev,
"%s%d", periph->
periph_name,
680 "registration!\n", __func__);
734 error = securelevel_gt(td->td_ucred, 1);
744 if (((
flags & FWRITE) == 0) || ((
flags & FREAD) == 0)) {
753 if ((
flags & O_NONBLOCK) != 0) {
781 if (
softc->open_count == 0) {
784 TAILQ_FOREACH_SAFE(io_req, &softc->done_queue, links, io_req2) {
785 TAILQ_REMOVE(&softc->done_queue, io_req, links);
787 uma_zfree(softc->pass_zone, io_req);
790 TAILQ_FOREACH_SAFE(io_req, &softc->incoming_queue, links,
792 TAILQ_REMOVE(&softc->incoming_queue, io_req, links);
794 uma_zfree(softc->pass_zone, io_req);
803 io_req = TAILQ_FIRST(&softc->active_queue);
818 TAILQ_FOREACH_SAFE(io_req, &softc->active_queue, links,
820 TAILQ_REMOVE(&softc->active_queue, io_req, links);
822 TAILQ_INSERT_TAIL(&softc->abandoned_queue, io_req,
853 switch (softc->
state) {
861 io_req = TAILQ_FIRST(&softc->incoming_queue);
862 if (io_req == NULL) {
866 TAILQ_REMOVE(&softc->incoming_queue, io_req, links);
867 TAILQ_INSERT_TAIL(&softc->active_queue, io_req, links);
873 start_ccb->
ccb_h.ccb_ioreq = io_req;
885 if (!TAILQ_EMPTY(&softc->incoming_queue))
904 csio = &done_ccb->
csio;
905 switch (csio->
ccb_h.ccb_type) {
909 io_req = done_ccb->
ccb_h.ccb_ioreq;
922 if (error == ERESTART) {
935 bcopy(done_ccb, &io_req->
ccb,
sizeof(*done_ccb));
948 DEVSTAT_WRITE : DEVSTAT_READ, NULL,
958 DEVSTAT_WRITE : DEVSTAT_READ, NULL,
975 DEVSTAT_TAG_SIMPLE, DEVSTAT_READ, NULL,
980 DEVSTAT_TAG_NONE, DEVSTAT_NO_DATA, NULL,
991 TAILQ_REMOVE(&softc->active_queue, io_req, links);
992 TAILQ_INSERT_TAIL(&softc->done_queue, io_req, links);
1001 TAILQ_REMOVE(&softc->abandoned_queue, io_req, links);
1003 uma_zfree(softc->pass_zone, io_req);
1017 if ((TAILQ_EMPTY(&softc->abandoned_queue))
1019 softc->
flags &= ~PASS_FLAG_ABANDONED_REF_SET;
1046 (
"%s called when the pass(4) zone is valid!\n", __func__));
1047 KASSERT((softc->pass_zone == NULL),
1048 (
"%s called when the pass(4) zone is allocated!\n", __func__));
1063 softc->pass_zone = uma_zcreate(softc->zone_name,
1064 sizeof(
struct pass_io_req), NULL, NULL, NULL, NULL,
1067 softc->pass_io_zone = uma_zcreate(softc->io_zone_name,
1068 softc->io_zone_size, NULL, NULL, NULL, NULL,
1073 if ((softc->pass_zone == NULL)
1074 || (softc->pass_io_zone == NULL)) {
1075 if (softc->pass_zone == NULL)
1077 "IO Req UMA zone\n");
1081 softc->
flags &= ~PASS_FLAG_ZONE_INPROG;
1088 softc->
flags &= ~PASS_FLAG_ZONE_INPROG;
1090 wakeup(&softc->pass_zone);
1100 error = msleep(&softc->pass_zone,
1129 numbufs = min(io_req->
num_bufs, 2);
1141 numbufs = min(io_req->
num_bufs, 1);
1145 numbufs = min(io_req->
num_bufs, 1);
1148 numbufs = min(io_req->
num_bufs, 2);
1153 numbufs = min(io_req->
num_bufs, 1);
1159 numbufs = min(io_req->
num_bufs, 1);
1176 for (i = 0; i < io_req->
num_bufs; i++) {
1185 if ((uint8_t *)(uintptr_t)
1189 uma_zfree(softc->pass_io_zone, (uint8_t *)(uintptr_t)
1201 for (i = 0; i < numbufs; i++) {
1217 bus_size_t kern_watermark, user_watermark, len_to_copy;
1218 bus_dma_segment_t *user_sglist, *kern_sglist;
1230 uint8_t *user_ptr, *kern_ptr;
1232 len_to_copy = min(user_sglist[i].ds_len -user_watermark,
1233 kern_sglist[j].ds_len - kern_watermark);
1235 user_ptr = (uint8_t *)(uintptr_t)user_sglist[i].ds_addr;
1236 user_ptr = user_ptr + user_watermark;
1237 kern_ptr = (uint8_t *)(uintptr_t)kern_sglist[j].ds_addr;
1238 kern_ptr = kern_ptr + kern_watermark;
1240 user_watermark += len_to_copy;
1241 kern_watermark += len_to_copy;
1244 error = copyout(kern_ptr, user_ptr, len_to_copy);
1247 "bytes from %p to %p failed with "
1248 "error %d\n", __func__, len_to_copy,
1249 kern_ptr, user_ptr, error);
1253 error = copyin(user_ptr, kern_ptr, len_to_copy);
1256 "bytes from %p to %p failed with "
1257 "error %d\n", __func__, len_to_copy,
1258 user_ptr, kern_ptr, error);
1263 if (user_sglist[i].ds_len == user_watermark) {
1268 if (kern_sglist[j].ds_len == kern_watermark) {
1289 uint16_t *seg_cnt_ptr;
1295 softc = periph->
softc;
1306 printf(
"%s: invalid match buffer length 0\n", __func__);
1344 maxmap = softc->
maxio;
1362 maxmap = softc->
maxio;
1374 maxmap = softc->
maxio;
1400 maxmap = softc->
maxio;
1415 for (i = 0; i < numbufs; i++) {
1417 io_req->
dirs[i] = dirs[i];
1418 io_req->
lengths[i] = lengths[i];
1423 if (lengths[i] <= maxmap)
1426 xpt_print(periph->
path,
"%s: data length %u > max allowed %u "
1427 "bytes\n", __func__, lengths[i], maxmap);
1435 for (i = 0; i < numbufs; i++) {
1445 tmp_buf = malloc(lengths[i], M_SCSIPASS,
1448 *data_ptrs[i] = tmp_buf;
1452 "buffer %p, operation: %s\n", __func__,
1453 tmp_buf, lengths[i], io_req->
user_bufs[i],
1466 "buffer from %p to %p failed with "
1467 "error %d\n", __func__,
1478 size_t sg_length, size_to_go, alloc_size;
1479 uint32_t num_segs_needed;
1490 "more than one S/G list per CCB\n", __func__);
1498 if (num_segs == 0) {
1500 "but sglist_cnt=0!\n", __func__);
1509 if (lengths[0] == 0) {
1511 "but CAM_DATA_SG flag is set!\n", __func__);
1520 if (lengths[0] <= softc->io_zone_size)
1521 num_segs_needed = 1;
1523 num_segs_needed = lengths[0] / softc->io_zone_size;
1524 if ((lengths[0] % softc->io_zone_size) != 0)
1529 sg_length = num_segs *
sizeof(bus_dma_segment_t);
1541 io_req->
user_segptr = malloc(
sizeof(bus_dma_segment_t) *
1542 num_segs, M_SCSIPASS, M_WAITOK | M_ZERO);
1547 error = copyin(*data_ptrs[0], io_req->
user_segptr, sg_length);
1550 "from %p to %p failed with error %d\n",
1557 io_req->
kern_segptr = malloc(
sizeof(bus_dma_segment_t) *
1558 num_segs_needed, M_SCSIPASS, M_WAITOK | M_ZERO);
1567 for (size_to_go = lengths[0], i = 0;
1568 size_to_go > 0 && i < num_segs_needed;
1569 i++, size_to_go -= alloc_size) {
1572 alloc_size = min(size_to_go, softc->io_zone_size);
1573 kern_ptr = uma_zalloc(softc->pass_io_zone, M_WAITOK);
1575 (bus_addr_t)(uintptr_t)kern_ptr;
1578 if (size_to_go > 0) {
1579 printf(
"%s: size_to_go = %zu, software error!\n",
1580 __func__, size_to_go);
1602 printf(
"%s: cannot currently handle more than one "
1603 "S/G list per CCB\n", __func__);
1611 if (num_segs == 0) {
1613 "set, but sglist_cnt=0!\n", __func__);
1622 if (lengths[0] == 0) {
1624 "but CAM_DATA_SG flag is set!\n", __func__);
1630 sg_length = num_segs *
sizeof(bus_dma_segment_t);
1638 io_req->
user_segptr = malloc(
sizeof(bus_dma_segment_t) *
1639 num_segs, M_SCSIPASS, M_WAITOK | M_ZERO);
1646 error = copyin(*data_ptrs[0], io_req->
user_segptr, sg_length);
1649 "from %p to %p failed with error %d\n",
1688 for (i = 0; i < io_req->
num_bufs; i++) {
1696 "bytes from %p to user address %p\n",
1738passioctl(
struct cdev *
dev, u_long cmd, caddr_t addr,
int flag,
struct thread *td)
1769 inccb = (
union ccb *)addr;
1770#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
1772 inccb->
csio.bio = NULL;
1786 "restricted to the XPT device\n",
1834 union ccb **user_ccb, *
ccb;
1837#ifdef COMPAT_FREEBSD32
1838 if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
1855 io_req = uma_zalloc(softc->pass_zone, M_WAITOK | M_ZERO);
1857 user_ccb = (
union ccb **)addr;
1872 "kernel address %p\n", *user_ccb,
ccb);
1874 error = copyin(*user_ccb,
ccb,
sizeof(*
ccb));
1877 "kernel address %p failed with error %d\n",
1878 *user_ccb,
ccb, error);
1879 goto camioqueue_error;
1881#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
1888 goto camioqueue_error;
1894 goto camioqueue_error;
1899 goto camioqueue_error;
1909 "restricted to the XPT device\n",
1912 goto camioqueue_error;
1960 goto camioqueue_error;
1969 TAILQ_INSERT_TAIL(&softc->incoming_queue, io_req, links);
1990 TAILQ_REMOVE(&softc->incoming_queue, io_req, links);
1991 TAILQ_INSERT_TAIL(&softc->active_queue, io_req, links);
2001 TAILQ_REMOVE(&softc->active_queue, io_req, links);
2002 TAILQ_INSERT_TAIL(&softc->done_queue, io_req, links);
2007 uma_zfree(softc->pass_zone, io_req);
2013 union ccb **user_ccb;
2017#ifdef COMPAT_FREEBSD32
2018 if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
2023 user_ccb = (
union ccb **)addr;
2026 io_req = TAILQ_FIRST(&softc->done_queue);
2027 if (io_req == NULL) {
2035 TAILQ_REMOVE(&softc->done_queue, io_req, links);
2056 "kernel address %p\n", *user_ccb, &io_req->
ccb);
2059 error = copyout(&io_req->
ccb, *user_ccb,
sizeof(
union ccb));
2062 "kernel address %p failed with error %d\n",
2063 *user_ccb, &io_req->
ccb, error);
2081 uma_zfree(softc->pass_zone, io_req);
2096passpoll(
struct cdev *dev,
int poll_events,
struct thread *td)
2105 revents = poll_events & (POLLOUT | POLLWRNORM);
2106 if ((poll_events & (POLLIN | POLLRDNORM)) != 0) {
2109 if (!TAILQ_EMPTY(&
softc->done_queue)) {
2110 revents |= poll_events & (POLLIN | POLLRDNORM);
2114 selrecord(td, &
softc->read_select);
2129 kn->kn_hook = (caddr_t)periph;
2131 knlist_add(&
softc->read_select.si_note, kn, 0);
2145 knlist_remove(&
softc->read_select.si_note, kn, 0);
2160 if (TAILQ_EMPTY(&
softc->done_queue))
2206 bzero(&mapinfo,
sizeof(mapinfo));
2243 bcopy(
ccb, inccb,
sizeof(
union ccb));
const struct cam_status_entry * cam_fetch_status_entry(cam_status status)
#define CAM_PRIORITY_NORMAL
#define XPORT_DEVSTAT_TYPE(t)
#define CDAI_TYPE_PHYS_PATH
int cam_compat_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td, d_ioctl_t *cbfnp)
void cam_periph_release_locked(struct cam_periph *periph)
void cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
int cam_periph_acquire(struct cam_periph *periph)
void cam_periph_doacquire(struct cam_periph *periph)
void cam_periph_async(struct cam_periph *periph, u_int32_t code, struct cam_path *path, void *arg)
void cam_periph_release(struct cam_periph *periph)
int cam_periph_runccb(union ccb *ccb, int(*error_routine)(union ccb *ccb, cam_flags camflags, u_int32_t sense_flags), cam_flags camflags, u_int32_t sense_flags, struct devstat *ds)
int cam_periph_error(union ccb *ccb, cam_flags camflags, u_int32_t sense_flags)
int cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo, u_int maxmap)
int cam_periph_ioctl(struct cam_periph *periph, u_long cmd, caddr_t addr, int(*error_routine)(union ccb *ccb, cam_flags camflags, u_int32_t sense_flags))
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_INVALID
void periph_oninv_t(struct cam_periph *periph)
#define cam_periph_assert(periph, what)
#define cam_periph_lock(periph)
#define CAM_PERIPH_MAXMAPS
union ccb * cam_periph_getccb(struct cam_periph *periph, u_int32_t priority)
#define cam_periph_unlock(periph)
static __inline struct mtx * cam_periph_mtx(struct cam_periph *periph)
void periph_dtor_t(struct cam_periph *periph)
void periph_start_t(struct cam_periph *periph, union ccb *start_ccb)
void() periph_init_t(void)
TAILQ_HEAD(ccb_hdr_tailq, ccb_hdr)
void xpt_schedule(struct cam_periph *periph, u_int32_t new_priority)
void xpt_merge_ccb(union ccb *dst_ccb, union ccb *src_ccb)
int xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
void xpt_setup_ccb_flags(struct ccb_hdr *ccb_h, struct cam_path *path, u_int32_t priority, u_int32_t flags)
void xpt_print(struct cam_path *path, const char *fmt,...)
void xpt_announce_periph(struct cam_periph *periph, char *announce_string)
void xpt_setup_ccb(struct ccb_hdr *ccb_h, struct cam_path *path, u_int32_t priority)
void xpt_action(union ccb *start_ccb)
cam_status xpt_register_async(int event, ac_callback_t *cbfunc, void *cbarg, struct cam_path *path)
union ccb * xpt_alloc_ccb_nowait(void)
void xpt_release_ccb(union ccb *free_ccb)
void xpt_free_ccb(union ccb *free_ccb)
static void xpt_path_inq(struct ccb_pathinq *cpi, struct cam_path *path)
#define SID_TYPE(inq_data)
static periph_init_t passinit
static d_ioctl_t passdoioctl
static void passrejectios(struct cam_periph *periph)
static int passmemdone(struct cam_periph *periph, struct pass_io_req *io_req)
static struct cdevsw pass_cdevsw
static void pass_shutdown_kqueue(void *context, int pending)
static int passmemsetup(struct cam_periph *periph, struct pass_io_req *io_req)
static d_close_t passclose
static periph_oninv_t passoninvalidate
static d_ioctl_t passioctl
static periph_dtor_t passcleanup
static int passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
static periph_start_t passstart
static struct filterops passread_filtops
static d_kqfilter_t passkqfilter
static int passreadfilt(struct knote *kn, long hint)
@ PASS_FLAG_ABANDONED_REF_SET
@ PASS_FLAG_INITIAL_PHYSPATH
@ PASS_FLAG_UNMAPPED_CAPABLE
static int passcopysglist(struct cam_periph *periph, struct pass_io_req *io_req, ccb_flags direction)
PERIPHDRIVER_DECLARE(pass, passdriver)
static void passreadfiltdetach(struct knote *kn)
static MALLOC_DEFINE(M_SCSIPASS, "scsi_pass", "scsi passthrough buffers")
static int passcreatezone(struct cam_periph *periph)
static void passdone(struct cam_periph *periph, union ccb *done_ccb)
static void passdevgonecb(void *arg)
static int passerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
static void pass_add_physpath(void *context, int pending)
static periph_ctor_t passregister
@ PASS_IO_USER_SEG_MALLOC
@ PASS_IO_KERN_SEG_MALLOC
static struct periph_driver passdriver
static void passiocleanup(struct pass_softc *softc, struct pass_io_req *io_req)
static void passasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
struct dev_match_result * matches
u_int32_t pattern_buf_len
struct dev_match_pattern * patterns
struct scsi_inquiry_data inq_data
ccb_ppriv_area periph_priv
void(* cbfcnp)(struct cam_periph *, union ccb *)
uint32_t lengths[CAM_PERIPH_MAXMAPS]
ccb_ppriv_area user_periph_priv
struct cam_periph_map_info mapinfo
camq_entry user_periph_links
bus_dma_segment_t * kern_segptr
bus_dma_segment_t * user_segptr
bus_dma_segment_t kern_segs[PASS_MAX_SEGS]
uint8_t * kern_bufs[CAM_PERIPH_MAXMAPS]
uint8_t * user_bufs[CAM_PERIPH_MAXMAPS]
struct bintime start_time
bus_dma_segment_t user_segs[PASS_MAX_SEGS]
uint32_t dirs[CAM_PERIPH_MAXMAPS]
struct devstat * device_stats
struct task shutdown_kqueue_task
struct task add_physpath_task
struct selinfo read_select
struct ccb_dev_advinfo cdai
u_int8_t cdb_bytes[IOCDBLEN]