The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/cam/scsi/scsi_pass.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
    5  * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   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.
   16  *
   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
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/kernel.h>
   36 #include <sys/conf.h>
   37 #include <sys/types.h>
   38 #include <sys/bio.h>
   39 #include <sys/bus.h>
   40 #include <sys/devicestat.h>
   41 #include <sys/errno.h>
   42 #include <sys/fcntl.h>
   43 #include <sys/malloc.h>
   44 #include <sys/proc.h>
   45 #include <sys/poll.h>
   46 #include <sys/selinfo.h>
   47 #include <sys/sdt.h>
   48 #include <sys/sysent.h>
   49 #include <sys/taskqueue.h>
   50 #include <vm/uma.h>
   51 #include <vm/vm.h>
   52 #include <vm/vm_extern.h>
   53 
   54 #include <machine/bus.h>
   55 
   56 #include <cam/cam.h>
   57 #include <cam/cam_ccb.h>
   58 #include <cam/cam_periph.h>
   59 #include <cam/cam_queue.h>
   60 #include <cam/cam_xpt.h>
   61 #include <cam/cam_xpt_periph.h>
   62 #include <cam/cam_debug.h>
   63 #include <cam/cam_compat.h>
   64 #include <cam/cam_xpt_periph.h>
   65 
   66 #include <cam/scsi/scsi_all.h>
   67 #include <cam/scsi/scsi_pass.h>
   68 
   69 typedef enum {
   70         PASS_FLAG_OPEN                  = 0x01,
   71         PASS_FLAG_LOCKED                = 0x02,
   72         PASS_FLAG_INVALID               = 0x04,
   73         PASS_FLAG_INITIAL_PHYSPATH      = 0x08,
   74         PASS_FLAG_ZONE_INPROG           = 0x10,
   75         PASS_FLAG_ZONE_VALID            = 0x20,
   76         PASS_FLAG_UNMAPPED_CAPABLE      = 0x40,
   77         PASS_FLAG_ABANDONED_REF_SET     = 0x80
   78 } pass_flags;
   79 
   80 typedef enum {
   81         PASS_STATE_NORMAL
   82 } pass_state;
   83 
   84 typedef enum {
   85         PASS_CCB_BUFFER_IO,
   86         PASS_CCB_QUEUED_IO
   87 } pass_ccb_types;
   88 
   89 #define ccb_type        ppriv_field0
   90 #define ccb_ioreq       ppriv_ptr1
   91 
   92 /*
   93  * The maximum number of memory segments we preallocate.
   94  */
   95 #define PASS_MAX_SEGS   16
   96 
   97 typedef enum {
   98         PASS_IO_NONE            = 0x00,
   99         PASS_IO_USER_SEG_MALLOC = 0x01,
  100         PASS_IO_KERN_SEG_MALLOC = 0x02,
  101         PASS_IO_ABANDONED       = 0x04
  102 } pass_io_flags; 
  103 
  104 struct pass_io_req {
  105         union ccb                        ccb;
  106         union ccb                       *alloced_ccb;
  107         union ccb                       *user_ccb_ptr;
  108         camq_entry                       user_periph_links;
  109         ccb_ppriv_area                   user_periph_priv;
  110         struct cam_periph_map_info       mapinfo;
  111         pass_io_flags                    flags;
  112         ccb_flags                        data_flags;
  113         int                              num_user_segs;
  114         bus_dma_segment_t                user_segs[PASS_MAX_SEGS];
  115         int                              num_kern_segs;
  116         bus_dma_segment_t                kern_segs[PASS_MAX_SEGS];
  117         bus_dma_segment_t               *user_segptr;
  118         bus_dma_segment_t               *kern_segptr;
  119         int                              num_bufs;
  120         uint32_t                         dirs[CAM_PERIPH_MAXMAPS];
  121         uint32_t                         lengths[CAM_PERIPH_MAXMAPS];
  122         uint8_t                         *user_bufs[CAM_PERIPH_MAXMAPS];
  123         uint8_t                         *kern_bufs[CAM_PERIPH_MAXMAPS];
  124         struct bintime                   start_time;
  125         TAILQ_ENTRY(pass_io_req)         links;
  126 };
  127 
  128 struct pass_softc {
  129         pass_state                state;
  130         pass_flags                flags;
  131         u_int8_t                  pd_type;
  132         union ccb                 saved_ccb;
  133         int                       open_count;
  134         u_int                     maxio;
  135         struct devstat           *device_stats;
  136         struct cdev              *dev;
  137         struct cdev              *alias_dev;
  138         struct task               add_physpath_task;
  139         struct task               shutdown_kqueue_task;
  140         struct selinfo            read_select;
  141         TAILQ_HEAD(, pass_io_req) incoming_queue;
  142         TAILQ_HEAD(, pass_io_req) active_queue;
  143         TAILQ_HEAD(, pass_io_req) abandoned_queue;
  144         TAILQ_HEAD(, pass_io_req) done_queue;
  145         struct cam_periph        *periph;
  146         char                      zone_name[12];
  147         char                      io_zone_name[12];
  148         uma_zone_t                pass_zone;
  149         uma_zone_t                pass_io_zone;
  150         size_t                    io_zone_size;
  151 };
  152 
  153 static  d_open_t        passopen;
  154 static  d_close_t       passclose;
  155 static  d_ioctl_t       passioctl;
  156 static  d_ioctl_t       passdoioctl;
  157 static  d_poll_t        passpoll;
  158 static  d_kqfilter_t    passkqfilter;
  159 static  void            passreadfiltdetach(struct knote *kn);
  160 static  int             passreadfilt(struct knote *kn, long hint);
  161 
  162 static  periph_init_t   passinit;
  163 static  periph_ctor_t   passregister;
  164 static  periph_oninv_t  passoninvalidate;
  165 static  periph_dtor_t   passcleanup;
  166 static  periph_start_t  passstart;
  167 static  void            pass_shutdown_kqueue(void *context, int pending);
  168 static  void            pass_add_physpath(void *context, int pending);
  169 static  void            passasync(void *callback_arg, u_int32_t code,
  170                                   struct cam_path *path, void *arg);
  171 static  void            passdone(struct cam_periph *periph, 
  172                                  union ccb *done_ccb);
  173 static  int             passcreatezone(struct cam_periph *periph);
  174 static  void            passiocleanup(struct pass_softc *softc, 
  175                                       struct pass_io_req *io_req);
  176 static  int             passcopysglist(struct cam_periph *periph,
  177                                        struct pass_io_req *io_req,
  178                                        ccb_flags direction);
  179 static  int             passmemsetup(struct cam_periph *periph,
  180                                      struct pass_io_req *io_req);
  181 static  int             passmemdone(struct cam_periph *periph,
  182                                     struct pass_io_req *io_req);
  183 static  int             passerror(union ccb *ccb, u_int32_t cam_flags, 
  184                                   u_int32_t sense_flags);
  185 static  int             passsendccb(struct cam_periph *periph, union ccb *ccb,
  186                                     union ccb *inccb);
  187 
  188 static struct periph_driver passdriver =
  189 {
  190         passinit, "pass",
  191         TAILQ_HEAD_INITIALIZER(passdriver.units), /* generation */ 0
  192 };
  193 
  194 PERIPHDRIVER_DECLARE(pass, passdriver);
  195 
  196 static struct cdevsw pass_cdevsw = {
  197         .d_version =    D_VERSION,
  198         .d_flags =      D_TRACKCLOSE,
  199         .d_open =       passopen,
  200         .d_close =      passclose,
  201         .d_ioctl =      passioctl,
  202         .d_poll =       passpoll,
  203         .d_kqfilter =   passkqfilter,
  204         .d_name =       "pass",
  205 };
  206 
  207 static struct filterops passread_filtops = {
  208         .f_isfd =       1,
  209         .f_detach =     passreadfiltdetach,
  210         .f_event =      passreadfilt
  211 };
  212 
  213 static MALLOC_DEFINE(M_SCSIPASS, "scsi_pass", "scsi passthrough buffers");
  214 
  215 static void
  216 passinit(void)
  217 {
  218         cam_status status;
  219 
  220         /*
  221          * Install a global async callback.  This callback will
  222          * receive async callbacks like "new device found".
  223          */
  224         status = xpt_register_async(AC_FOUND_DEVICE, passasync, NULL, NULL);
  225 
  226         if (status != CAM_REQ_CMP) {
  227                 printf("pass: Failed to attach master async callback "
  228                        "due to status 0x%x!\n", status);
  229         }
  230 
  231 }
  232 
  233 static void
  234 passrejectios(struct cam_periph *periph)
  235 {
  236         struct pass_io_req *io_req, *io_req2;
  237         struct pass_softc *softc;
  238 
  239         softc = (struct pass_softc *)periph->softc;
  240 
  241         /*
  242          * The user can no longer get status for I/O on the done queue, so
  243          * clean up all outstanding I/O on the done queue.
  244          */
  245         TAILQ_FOREACH_SAFE(io_req, &softc->done_queue, links, io_req2) {
  246                 TAILQ_REMOVE(&softc->done_queue, io_req, links);
  247                 passiocleanup(softc, io_req);
  248                 uma_zfree(softc->pass_zone, io_req);
  249         }
  250 
  251         /*
  252          * The underlying device is gone, so we can't issue these I/Os.
  253          * The devfs node has been shut down, so we can't return status to
  254          * the user.  Free any I/O left on the incoming queue.
  255          */
  256         TAILQ_FOREACH_SAFE(io_req, &softc->incoming_queue, links, io_req2) {
  257                 TAILQ_REMOVE(&softc->incoming_queue, io_req, links);
  258                 passiocleanup(softc, io_req);
  259                 uma_zfree(softc->pass_zone, io_req);
  260         }
  261 
  262         /*
  263          * Normally we would put I/Os on the abandoned queue and acquire a
  264          * reference when we saw the final close.  But, the device went
  265          * away and devfs may have moved everything off to deadfs by the
  266          * time the I/O done callback is called; as a result, we won't see
  267          * any more closes.  So, if we have any active I/Os, we need to put
  268          * them on the abandoned queue.  When the abandoned queue is empty,
  269          * we'll release the remaining reference (see below) to the peripheral.
  270          */
  271         TAILQ_FOREACH_SAFE(io_req, &softc->active_queue, links, io_req2) {
  272                 TAILQ_REMOVE(&softc->active_queue, io_req, links);
  273                 io_req->flags |= PASS_IO_ABANDONED;
  274                 TAILQ_INSERT_TAIL(&softc->abandoned_queue, io_req, links);
  275         }
  276 
  277         /*
  278          * If we put any I/O on the abandoned queue, acquire a reference.
  279          */
  280         if ((!TAILQ_EMPTY(&softc->abandoned_queue))
  281          && ((softc->flags & PASS_FLAG_ABANDONED_REF_SET) == 0)) {
  282                 cam_periph_doacquire(periph);
  283                 softc->flags |= PASS_FLAG_ABANDONED_REF_SET;
  284         }
  285 }
  286 
  287 static void
  288 passdevgonecb(void *arg)
  289 {
  290         struct cam_periph *periph;
  291         struct mtx *mtx;
  292         struct pass_softc *softc;
  293         int i;
  294 
  295         periph = (struct cam_periph *)arg;
  296         mtx = cam_periph_mtx(periph);
  297         mtx_lock(mtx);
  298 
  299         softc = (struct pass_softc *)periph->softc;
  300         KASSERT(softc->open_count >= 0, ("Negative open count %d",
  301                 softc->open_count));
  302 
  303         /*
  304          * When we get this callback, we will get no more close calls from
  305          * devfs.  So if we have any dangling opens, we need to release the
  306          * reference held for that particular context.
  307          */
  308         for (i = 0; i < softc->open_count; i++)
  309                 cam_periph_release_locked(periph);
  310 
  311         softc->open_count = 0;
  312 
  313         /*
  314          * Release the reference held for the device node, it is gone now.
  315          * Accordingly, inform all queued I/Os of their fate.
  316          */
  317         cam_periph_release_locked(periph);
  318         passrejectios(periph);
  319 
  320         /*
  321          * We reference the SIM lock directly here, instead of using
  322          * cam_periph_unlock().  The reason is that the final call to
  323          * cam_periph_release_locked() above could result in the periph
  324          * getting freed.  If that is the case, dereferencing the periph
  325          * with a cam_periph_unlock() call would cause a page fault.
  326          */
  327         mtx_unlock(mtx);
  328 
  329         /*
  330          * We have to remove our kqueue context from a thread because it
  331          * may sleep.  It would be nice if we could get a callback from
  332          * kqueue when it is done cleaning up resources.
  333          */
  334         taskqueue_enqueue(taskqueue_thread, &softc->shutdown_kqueue_task);
  335 }
  336 
  337 static void
  338 passoninvalidate(struct cam_periph *periph)
  339 {
  340         struct pass_softc *softc;
  341 
  342         softc = (struct pass_softc *)periph->softc;
  343 
  344         /*
  345          * De-register any async callbacks.
  346          */
  347         xpt_register_async(0, passasync, periph, periph->path);
  348 
  349         softc->flags |= PASS_FLAG_INVALID;
  350 
  351         /*
  352          * Tell devfs this device has gone away, and ask for a callback
  353          * when it has cleaned up its state.
  354          */
  355         destroy_dev_sched_cb(softc->dev, passdevgonecb, periph);
  356 }
  357 
  358 static void
  359 passcleanup(struct cam_periph *periph)
  360 {
  361         struct pass_softc *softc;
  362 
  363         softc = (struct pass_softc *)periph->softc;
  364 
  365         cam_periph_assert(periph, MA_OWNED);
  366         KASSERT(TAILQ_EMPTY(&softc->active_queue),
  367                 ("%s called when there are commands on the active queue!\n",
  368                 __func__));
  369         KASSERT(TAILQ_EMPTY(&softc->abandoned_queue),
  370                 ("%s called when there are commands on the abandoned queue!\n",
  371                 __func__));
  372         KASSERT(TAILQ_EMPTY(&softc->incoming_queue),
  373                 ("%s called when there are commands on the incoming queue!\n",
  374                 __func__));
  375         KASSERT(TAILQ_EMPTY(&softc->done_queue),
  376                 ("%s called when there are commands on the done queue!\n",
  377                 __func__));
  378 
  379         devstat_remove_entry(softc->device_stats);
  380 
  381         cam_periph_unlock(periph);
  382 
  383         /*
  384          * We call taskqueue_drain() for the physpath task to make sure it
  385          * is complete.  We drop the lock because this can potentially
  386          * sleep.  XXX KDM that is bad.  Need a way to get a callback when
  387          * a taskqueue is drained.
  388          *
  389          * Note that we don't drain the kqueue shutdown task queue.  This
  390          * is because we hold a reference on the periph for kqueue, and
  391          * release that reference from the kqueue shutdown task queue.  So
  392          * we cannot come into this routine unless we've released that
  393          * reference.  Also, because that could be the last reference, we
  394          * could be called from the cam_periph_release() call in
  395          * pass_shutdown_kqueue().  In that case, the taskqueue_drain()
  396          * would deadlock.  It would be preferable if we had a way to
  397          * get a callback when a taskqueue is done.
  398          */
  399         taskqueue_drain(taskqueue_thread, &softc->add_physpath_task);
  400 
  401         /*
  402          * It should be safe to destroy the zones from here, because all
  403          * of the references to this peripheral have been freed, and all
  404          * I/O has been terminated and freed.  We check the zones for NULL
  405          * because they may not have been allocated yet if the device went
  406          * away before any asynchronous I/O has been issued.
  407          */
  408         if (softc->pass_zone != NULL)
  409                 uma_zdestroy(softc->pass_zone);
  410         if (softc->pass_io_zone != NULL)
  411                 uma_zdestroy(softc->pass_io_zone);
  412 
  413         cam_periph_lock(periph);
  414 
  415         free(softc, M_DEVBUF);
  416 }
  417 
  418 static void
  419 pass_shutdown_kqueue(void *context, int pending)
  420 {
  421         struct cam_periph *periph;
  422         struct pass_softc *softc;
  423 
  424         periph = context;
  425         softc = periph->softc;
  426 
  427         knlist_clear(&softc->read_select.si_note, /*is_locked*/ 0);
  428         knlist_destroy(&softc->read_select.si_note);
  429 
  430         /*
  431          * Release the reference we held for kqueue.
  432          */
  433         cam_periph_release(periph);
  434 }
  435 
  436 static void
  437 pass_add_physpath(void *context, int pending)
  438 {
  439         struct cam_periph *periph;
  440         struct pass_softc *softc;
  441         struct mtx *mtx;
  442         char *physpath;
  443 
  444         /*
  445          * If we have one, create a devfs alias for our
  446          * physical path.
  447          */
  448         periph = context;
  449         softc = periph->softc;
  450         physpath = malloc(MAXPATHLEN, M_DEVBUF, M_WAITOK);
  451         mtx = cam_periph_mtx(periph);
  452         mtx_lock(mtx);
  453 
  454         if (periph->flags & CAM_PERIPH_INVALID)
  455                 goto out;
  456 
  457         if (xpt_getattr(physpath, MAXPATHLEN,
  458                         "GEOM::physpath", periph->path) == 0
  459          && strlen(physpath) != 0) {
  460 
  461                 mtx_unlock(mtx);
  462                 make_dev_physpath_alias(MAKEDEV_WAITOK | MAKEDEV_CHECKNAME,
  463                                 &softc->alias_dev, softc->dev,
  464                                 softc->alias_dev, physpath);
  465                 mtx_lock(mtx);
  466         }
  467 
  468 out:
  469         /*
  470          * Now that we've made our alias, we no longer have to have a
  471          * reference to the device.
  472          */
  473         if ((softc->flags & PASS_FLAG_INITIAL_PHYSPATH) == 0)
  474                 softc->flags |= PASS_FLAG_INITIAL_PHYSPATH;
  475 
  476         /*
  477          * We always acquire a reference to the periph before queueing this
  478          * task queue function, so it won't go away before we run.
  479          */
  480         while (pending-- > 0)
  481                 cam_periph_release_locked(periph);
  482         mtx_unlock(mtx);
  483 
  484         free(physpath, M_DEVBUF);
  485 }
  486 
  487 static void
  488 passasync(void *callback_arg, u_int32_t code,
  489           struct cam_path *path, void *arg)
  490 {
  491         struct cam_periph *periph;
  492 
  493         periph = (struct cam_periph *)callback_arg;
  494 
  495         switch (code) {
  496         case AC_FOUND_DEVICE:
  497         {
  498                 struct ccb_getdev *cgd;
  499                 cam_status status;
  500  
  501                 cgd = (struct ccb_getdev *)arg;
  502                 if (cgd == NULL)
  503                         break;
  504 
  505                 /*
  506                  * Allocate a peripheral instance for
  507                  * this device and start the probe
  508                  * process.
  509                  */
  510                 status = cam_periph_alloc(passregister, passoninvalidate,
  511                                           passcleanup, passstart, "pass",
  512                                           CAM_PERIPH_BIO, path,
  513                                           passasync, AC_FOUND_DEVICE, cgd);
  514 
  515                 if (status != CAM_REQ_CMP
  516                  && status != CAM_REQ_INPROG) {
  517                         const struct cam_status_entry *entry;
  518 
  519                         entry = cam_fetch_status_entry(status);
  520 
  521                         printf("passasync: Unable to attach new device "
  522                                "due to status %#x: %s\n", status, entry ?
  523                                entry->status_text : "Unknown");
  524                 }
  525 
  526                 break;
  527         }
  528         case AC_ADVINFO_CHANGED:
  529         {
  530                 uintptr_t buftype;
  531 
  532                 buftype = (uintptr_t)arg;
  533                 if (buftype == CDAI_TYPE_PHYS_PATH) {
  534                         struct pass_softc *softc;
  535 
  536                         softc = (struct pass_softc *)periph->softc;
  537                         /*
  538                          * Acquire a reference to the periph before we
  539                          * start the taskqueue, so that we don't run into
  540                          * a situation where the periph goes away before
  541                          * the task queue has a chance to run.
  542                          */
  543                         if (cam_periph_acquire(periph) != 0)
  544                                 break;
  545 
  546                         taskqueue_enqueue(taskqueue_thread,
  547                                           &softc->add_physpath_task);
  548                 }
  549                 break;
  550         }
  551         default:
  552                 cam_periph_async(periph, code, path, arg);
  553                 break;
  554         }
  555 }
  556 
  557 static cam_status
  558 passregister(struct cam_periph *periph, void *arg)
  559 {
  560         struct pass_softc *softc;
  561         struct ccb_getdev *cgd;
  562         struct ccb_pathinq cpi;
  563         struct make_dev_args args;
  564         int error, no_tags;
  565 
  566         cgd = (struct ccb_getdev *)arg;
  567         if (cgd == NULL) {
  568                 printf("%s: no getdev CCB, can't register device\n", __func__);
  569                 return(CAM_REQ_CMP_ERR);
  570         }
  571 
  572         softc = (struct pass_softc *)malloc(sizeof(*softc),
  573                                             M_DEVBUF, M_NOWAIT);
  574 
  575         if (softc == NULL) {
  576                 printf("%s: Unable to probe new device. "
  577                        "Unable to allocate softc\n", __func__);
  578                 return(CAM_REQ_CMP_ERR);
  579         }
  580 
  581         bzero(softc, sizeof(*softc));
  582         softc->state = PASS_STATE_NORMAL;
  583         if (cgd->protocol == PROTO_SCSI || cgd->protocol == PROTO_ATAPI)
  584                 softc->pd_type = SID_TYPE(&cgd->inq_data);
  585         else if (cgd->protocol == PROTO_SATAPM)
  586                 softc->pd_type = T_ENCLOSURE;
  587         else
  588                 softc->pd_type = T_DIRECT;
  589 
  590         periph->softc = softc;
  591         softc->periph = periph;
  592         TAILQ_INIT(&softc->incoming_queue);
  593         TAILQ_INIT(&softc->active_queue);
  594         TAILQ_INIT(&softc->abandoned_queue);
  595         TAILQ_INIT(&softc->done_queue);
  596         snprintf(softc->zone_name, sizeof(softc->zone_name), "%s%d",
  597                  periph->periph_name, periph->unit_number);
  598         snprintf(softc->io_zone_name, sizeof(softc->io_zone_name), "%s%dIO",
  599                  periph->periph_name, periph->unit_number);
  600         softc->io_zone_size = MAXPHYS;
  601         knlist_init_mtx(&softc->read_select.si_note, cam_periph_mtx(periph));
  602 
  603         xpt_path_inq(&cpi, periph->path);
  604 
  605         if (cpi.maxio == 0)
  606                 softc->maxio = DFLTPHYS;        /* traditional default */
  607         else if (cpi.maxio > MAXPHYS)
  608                 softc->maxio = MAXPHYS;         /* for safety */
  609         else
  610                 softc->maxio = cpi.maxio;       /* real value */
  611 
  612         if (cpi.hba_misc & PIM_UNMAPPED)
  613                 softc->flags |= PASS_FLAG_UNMAPPED_CAPABLE;
  614 
  615         /*
  616          * We pass in 0 for a blocksize, since we don't 
  617          * know what the blocksize of this device is, if 
  618          * it even has a blocksize.
  619          */
  620         cam_periph_unlock(periph);
  621         no_tags = (cgd->inq_data.flags & SID_CmdQue) == 0;
  622         softc->device_stats = devstat_new_entry("pass",
  623                           periph->unit_number, 0,
  624                           DEVSTAT_NO_BLOCKSIZE
  625                           | (no_tags ? DEVSTAT_NO_ORDERED_TAGS : 0),
  626                           softc->pd_type |
  627                           XPORT_DEVSTAT_TYPE(cpi.transport) |
  628                           DEVSTAT_TYPE_PASS,
  629                           DEVSTAT_PRIORITY_PASS);
  630 
  631         /*
  632          * Initialize the taskqueue handler for shutting down kqueue.
  633          */
  634         TASK_INIT(&softc->shutdown_kqueue_task, /*priority*/ 0,
  635                   pass_shutdown_kqueue, periph);
  636 
  637         /*
  638          * Acquire a reference to the periph that we can release once we've
  639          * cleaned up the kqueue.
  640          */
  641         if (cam_periph_acquire(periph) != 0) {
  642                 xpt_print(periph->path, "%s: lost periph during "
  643                           "registration!\n", __func__);
  644                 cam_periph_lock(periph);
  645                 return (CAM_REQ_CMP_ERR);
  646         }
  647 
  648         /*
  649          * Acquire a reference to the periph before we create the devfs
  650          * instance for it.  We'll release this reference once the devfs
  651          * instance has been freed.
  652          */
  653         if (cam_periph_acquire(periph) != 0) {
  654                 xpt_print(periph->path, "%s: lost periph during "
  655                           "registration!\n", __func__);
  656                 cam_periph_lock(periph);
  657                 return (CAM_REQ_CMP_ERR);
  658         }
  659 
  660         /* Register the device */
  661         make_dev_args_init(&args);
  662         args.mda_devsw = &pass_cdevsw;
  663         args.mda_unit = periph->unit_number;
  664         args.mda_uid = UID_ROOT;
  665         args.mda_gid = GID_OPERATOR;
  666         args.mda_mode = 0600;
  667         args.mda_si_drv1 = periph;
  668         error = make_dev_s(&args, &softc->dev, "%s%d", periph->periph_name,
  669             periph->unit_number);
  670         if (error != 0) {
  671                 cam_periph_lock(periph);
  672                 cam_periph_release_locked(periph);
  673                 return (CAM_REQ_CMP_ERR);
  674         }
  675 
  676         /*
  677          * Hold a reference to the periph before we create the physical
  678          * path alias so it can't go away.
  679          */
  680         if (cam_periph_acquire(periph) != 0) {
  681                 xpt_print(periph->path, "%s: lost periph during "
  682                           "registration!\n", __func__);
  683                 cam_periph_lock(periph);
  684                 return (CAM_REQ_CMP_ERR);
  685         }
  686 
  687         cam_periph_lock(periph);
  688 
  689         TASK_INIT(&softc->add_physpath_task, /*priority*/0,
  690                   pass_add_physpath, periph);
  691 
  692         /*
  693          * See if physical path information is already available.
  694          */
  695         taskqueue_enqueue(taskqueue_thread, &softc->add_physpath_task);
  696 
  697         /*
  698          * Add an async callback so that we get notified if
  699          * this device goes away or its physical path
  700          * (stored in the advanced info data of the EDT) has
  701          * changed.
  702          */
  703         xpt_register_async(AC_LOST_DEVICE | AC_ADVINFO_CHANGED,
  704                            passasync, periph, periph->path);
  705 
  706         if (bootverbose)
  707                 xpt_announce_periph(periph, NULL);
  708 
  709         return(CAM_REQ_CMP);
  710 }
  711 
  712 static int
  713 passopen(struct cdev *dev, int flags, int fmt, struct thread *td)
  714 {
  715         struct cam_periph *periph;
  716         struct pass_softc *softc;
  717         int error;
  718 
  719         periph = (struct cam_periph *)dev->si_drv1;
  720         if (cam_periph_acquire(periph) != 0)
  721                 return (ENXIO);
  722 
  723         cam_periph_lock(periph);
  724 
  725         softc = (struct pass_softc *)periph->softc;
  726 
  727         if (softc->flags & PASS_FLAG_INVALID) {
  728                 cam_periph_release_locked(periph);
  729                 cam_periph_unlock(periph);
  730                 return(ENXIO);
  731         }
  732 
  733         /*
  734          * Don't allow access when we're running at a high securelevel.
  735          */
  736         error = securelevel_gt(td->td_ucred, 1);
  737         if (error) {
  738                 cam_periph_release_locked(periph);
  739                 cam_periph_unlock(periph);
  740                 return(error);
  741         }
  742 
  743         /*
  744          * Only allow read-write access.
  745          */
  746         if (((flags & FWRITE) == 0) || ((flags & FREAD) == 0)) {
  747                 cam_periph_release_locked(periph);
  748                 cam_periph_unlock(periph);
  749                 return(EPERM);
  750         }
  751 
  752         /*
  753          * We don't allow nonblocking access.
  754          */
  755         if ((flags & O_NONBLOCK) != 0) {
  756                 xpt_print(periph->path, "can't do nonblocking access\n");
  757                 cam_periph_release_locked(periph);
  758                 cam_periph_unlock(periph);
  759                 return(EINVAL);
  760         }
  761 
  762         softc->open_count++;
  763 
  764         cam_periph_unlock(periph);
  765 
  766         return (error);
  767 }
  768 
  769 static int
  770 passclose(struct cdev *dev, int flag, int fmt, struct thread *td)
  771 {
  772         struct  cam_periph *periph;
  773         struct  pass_softc *softc;
  774         struct mtx *mtx;
  775 
  776         periph = (struct cam_periph *)dev->si_drv1;
  777         mtx = cam_periph_mtx(periph);
  778         mtx_lock(mtx);
  779 
  780         softc = periph->softc;
  781         softc->open_count--;
  782 
  783         if (softc->open_count == 0) {
  784                 struct pass_io_req *io_req, *io_req2;
  785 
  786                 TAILQ_FOREACH_SAFE(io_req, &softc->done_queue, links, io_req2) {
  787                         TAILQ_REMOVE(&softc->done_queue, io_req, links);
  788                         passiocleanup(softc, io_req);
  789                         uma_zfree(softc->pass_zone, io_req);
  790                 }
  791 
  792                 TAILQ_FOREACH_SAFE(io_req, &softc->incoming_queue, links,
  793                                    io_req2) {
  794                         TAILQ_REMOVE(&softc->incoming_queue, io_req, links);
  795                         passiocleanup(softc, io_req);
  796                         uma_zfree(softc->pass_zone, io_req);
  797                 }
  798 
  799                 /*
  800                  * If there are any active I/Os, we need to forcibly acquire a
  801                  * reference to the peripheral so that we don't go away
  802                  * before they complete.  We'll release the reference when
  803                  * the abandoned queue is empty.
  804                  */
  805                 io_req = TAILQ_FIRST(&softc->active_queue);
  806                 if ((io_req != NULL)
  807                  && (softc->flags & PASS_FLAG_ABANDONED_REF_SET) == 0) {
  808                         cam_periph_doacquire(periph);
  809                         softc->flags |= PASS_FLAG_ABANDONED_REF_SET;
  810                 }
  811 
  812                 /*
  813                  * Since the I/O in the active queue is not under our
  814                  * control, just set a flag so that we can clean it up when
  815                  * it completes and put it on the abandoned queue.  This
  816                  * will prevent our sending spurious completions in the
  817                  * event that the device is opened again before these I/Os
  818                  * complete.
  819                  */
  820                 TAILQ_FOREACH_SAFE(io_req, &softc->active_queue, links,
  821                                    io_req2) {
  822                         TAILQ_REMOVE(&softc->active_queue, io_req, links);
  823                         io_req->flags |= PASS_IO_ABANDONED;
  824                         TAILQ_INSERT_TAIL(&softc->abandoned_queue, io_req,
  825                                           links);
  826                 }
  827         }
  828 
  829         cam_periph_release_locked(periph);
  830 
  831         /*
  832          * We reference the lock directly here, instead of using
  833          * cam_periph_unlock().  The reason is that the call to
  834          * cam_periph_release_locked() above could result in the periph
  835          * getting freed.  If that is the case, dereferencing the periph
  836          * with a cam_periph_unlock() call would cause a page fault.
  837          *
  838          * cam_periph_release() avoids this problem using the same method,
  839          * but we're manually acquiring and dropping the lock here to
  840          * protect the open count and avoid another lock acquisition and
  841          * release.
  842          */
  843         mtx_unlock(mtx);
  844 
  845         return (0);
  846 }
  847 
  848 
  849 static void
  850 passstart(struct cam_periph *periph, union ccb *start_ccb)
  851 {
  852         struct pass_softc *softc;
  853 
  854         softc = (struct pass_softc *)periph->softc;
  855 
  856         switch (softc->state) {
  857         case PASS_STATE_NORMAL: {
  858                 struct pass_io_req *io_req;
  859 
  860                 /*
  861                  * Check for any queued I/O requests that require an
  862                  * allocated slot.
  863                  */
  864                 io_req = TAILQ_FIRST(&softc->incoming_queue);
  865                 if (io_req == NULL) {
  866                         xpt_release_ccb(start_ccb);
  867                         break;
  868                 }
  869                 TAILQ_REMOVE(&softc->incoming_queue, io_req, links);
  870                 TAILQ_INSERT_TAIL(&softc->active_queue, io_req, links);
  871                 /*
  872                  * Merge the user's CCB into the allocated CCB.
  873                  */
  874                 xpt_merge_ccb(start_ccb, &io_req->ccb);
  875                 start_ccb->ccb_h.ccb_type = PASS_CCB_QUEUED_IO;
  876                 start_ccb->ccb_h.ccb_ioreq = io_req;
  877                 start_ccb->ccb_h.cbfcnp = passdone;
  878                 io_req->alloced_ccb = start_ccb;
  879                 binuptime(&io_req->start_time);
  880                 devstat_start_transaction(softc->device_stats,
  881                                           &io_req->start_time);
  882 
  883                 xpt_action(start_ccb);
  884 
  885                 /*
  886                  * If we have any more I/O waiting, schedule ourselves again.
  887                  */
  888                 if (!TAILQ_EMPTY(&softc->incoming_queue))
  889                         xpt_schedule(periph, CAM_PRIORITY_NORMAL);
  890                 break;
  891         }
  892         default:
  893                 break;
  894         }
  895 }
  896 
  897 static void
  898 passdone(struct cam_periph *periph, union ccb *done_ccb)
  899 { 
  900         struct pass_softc *softc;
  901         struct ccb_scsiio *csio;
  902 
  903         softc = (struct pass_softc *)periph->softc;
  904 
  905         cam_periph_assert(periph, MA_OWNED);
  906 
  907         csio = &done_ccb->csio;
  908         switch (csio->ccb_h.ccb_type) {
  909         case PASS_CCB_QUEUED_IO: {
  910                 struct pass_io_req *io_req;
  911 
  912                 io_req = done_ccb->ccb_h.ccb_ioreq;
  913 #if 0
  914                 xpt_print(periph->path, "%s: called for user CCB %p\n",
  915                           __func__, io_req->user_ccb_ptr);
  916 #endif
  917                 if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
  918                  && (done_ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER)
  919                  && ((io_req->flags & PASS_IO_ABANDONED) == 0)) {
  920                         int error;
  921 
  922                         error = passerror(done_ccb, CAM_RETRY_SELTO,
  923                                           SF_RETRY_UA | SF_NO_PRINT);
  924 
  925                         if (error == ERESTART) {
  926                                 /*
  927                                  * A retry was scheduled, so
  928                                  * just return.
  929                                  */
  930                                 return;
  931                         }
  932                 }
  933 
  934                 /*
  935                  * Copy the allocated CCB contents back to the malloced CCB
  936                  * so we can give status back to the user when he requests it.
  937                  */
  938                 bcopy(done_ccb, &io_req->ccb, sizeof(*done_ccb));
  939 
  940                 /*
  941                  * Log data/transaction completion with devstat(9).
  942                  */
  943                 switch (done_ccb->ccb_h.func_code) {
  944                 case XPT_SCSI_IO:
  945                         devstat_end_transaction(softc->device_stats,
  946                             done_ccb->csio.dxfer_len - done_ccb->csio.resid,
  947                             done_ccb->csio.tag_action & 0x3,
  948                             ((done_ccb->ccb_h.flags & CAM_DIR_MASK) ==
  949                             CAM_DIR_NONE) ? DEVSTAT_NO_DATA :
  950                             (done_ccb->ccb_h.flags & CAM_DIR_OUT) ?
  951                             DEVSTAT_WRITE : DEVSTAT_READ, NULL,
  952                             &io_req->start_time);
  953                         break;
  954                 case XPT_ATA_IO:
  955                         devstat_end_transaction(softc->device_stats,
  956                             done_ccb->ataio.dxfer_len - done_ccb->ataio.resid,
  957                             0, /* Not used in ATA */
  958                             ((done_ccb->ccb_h.flags & CAM_DIR_MASK) ==
  959                             CAM_DIR_NONE) ? DEVSTAT_NO_DATA : 
  960                             (done_ccb->ccb_h.flags & CAM_DIR_OUT) ?
  961                             DEVSTAT_WRITE : DEVSTAT_READ, NULL,
  962                             &io_req->start_time);
  963                         break;
  964                 case XPT_SMP_IO:
  965                         /*
  966                          * XXX KDM this isn't quite right, but there isn't
  967                          * currently an easy way to represent a bidirectional 
  968                          * transfer in devstat.  The only way to do it
  969                          * and have the byte counts come out right would
  970                          * mean that we would have to record two
  971                          * transactions, one for the request and one for the
  972                          * response.  For now, so that we report something,
  973                          * just treat the entire thing as a read.
  974                          */
  975                         devstat_end_transaction(softc->device_stats,
  976                             done_ccb->smpio.smp_request_len +
  977                             done_ccb->smpio.smp_response_len,
  978                             DEVSTAT_TAG_SIMPLE, DEVSTAT_READ, NULL,
  979                             &io_req->start_time);
  980                         break;
  981                 default:
  982                         devstat_end_transaction(softc->device_stats, 0,
  983                             DEVSTAT_TAG_NONE, DEVSTAT_NO_DATA, NULL,
  984                             &io_req->start_time);
  985                         break;
  986                 }
  987 
  988                 /*
  989                  * In the normal case, take the completed I/O off of the
  990                  * active queue and put it on the done queue.  Notitfy the
  991                  * user that we have a completed I/O.
  992                  */
  993                 if ((io_req->flags & PASS_IO_ABANDONED) == 0) {
  994                         TAILQ_REMOVE(&softc->active_queue, io_req, links);
  995                         TAILQ_INSERT_TAIL(&softc->done_queue, io_req, links);
  996                         selwakeuppri(&softc->read_select, PRIBIO);
  997                         KNOTE_LOCKED(&softc->read_select.si_note, 0);
  998                 } else {
  999                         /*
 1000                          * In the case of an abandoned I/O (final close
 1001                          * without fetching the I/O), take it off of the
 1002                          * abandoned queue and free it.
 1003                          */
 1004                         TAILQ_REMOVE(&softc->abandoned_queue, io_req, links);
 1005                         passiocleanup(softc, io_req);
 1006                         uma_zfree(softc->pass_zone, io_req);
 1007 
 1008                         /*
 1009                          * Release the done_ccb here, since we may wind up
 1010                          * freeing the peripheral when we decrement the
 1011                          * reference count below.
 1012                          */
 1013                         xpt_release_ccb(done_ccb);
 1014 
 1015                         /*
 1016                          * If the abandoned queue is empty, we can release
 1017                          * our reference to the periph since we won't have
 1018                          * any more completions coming.
 1019                          */
 1020                         if ((TAILQ_EMPTY(&softc->abandoned_queue))
 1021                          && (softc->flags & PASS_FLAG_ABANDONED_REF_SET)) {
 1022                                 softc->flags &= ~PASS_FLAG_ABANDONED_REF_SET;
 1023                                 cam_periph_release_locked(periph);
 1024                         }
 1025 
 1026                         /*
 1027                          * We have already released the CCB, so we can
 1028                          * return.
 1029                          */
 1030                         return;
 1031                 }
 1032                 break;
 1033         }
 1034         }
 1035         xpt_release_ccb(done_ccb);
 1036 }
 1037 
 1038 static int
 1039 passcreatezone(struct cam_periph *periph)
 1040 {
 1041         struct pass_softc *softc;
 1042         int error;
 1043 
 1044         error = 0;
 1045         softc = (struct pass_softc *)periph->softc;
 1046 
 1047         cam_periph_assert(periph, MA_OWNED);
 1048         KASSERT(((softc->flags & PASS_FLAG_ZONE_VALID) == 0), 
 1049                 ("%s called when the pass(4) zone is valid!\n", __func__));
 1050         KASSERT((softc->pass_zone == NULL), 
 1051                 ("%s called when the pass(4) zone is allocated!\n", __func__));
 1052 
 1053         if ((softc->flags & PASS_FLAG_ZONE_INPROG) == 0) {
 1054 
 1055                 /*
 1056                  * We're the first context through, so we need to create
 1057                  * the pass(4) UMA zone for I/O requests.
 1058                  */
 1059                 softc->flags |= PASS_FLAG_ZONE_INPROG;
 1060 
 1061                 /*
 1062                  * uma_zcreate() does a blocking (M_WAITOK) allocation,
 1063                  * so we cannot hold a mutex while we call it.
 1064                  */
 1065                 cam_periph_unlock(periph);
 1066 
 1067                 softc->pass_zone = uma_zcreate(softc->zone_name,
 1068                     sizeof(struct pass_io_req), NULL, NULL, NULL, NULL,
 1069                     /*align*/ 0, /*flags*/ 0);
 1070 
 1071                 softc->pass_io_zone = uma_zcreate(softc->io_zone_name,
 1072                     softc->io_zone_size, NULL, NULL, NULL, NULL,
 1073                     /*align*/ 0, /*flags*/ 0);
 1074 
 1075                 cam_periph_lock(periph);
 1076 
 1077                 if ((softc->pass_zone == NULL)
 1078                  || (softc->pass_io_zone == NULL)) {
 1079                         if (softc->pass_zone == NULL)
 1080                                 xpt_print(periph->path, "unable to allocate "
 1081                                     "IO Req UMA zone\n");
 1082                         else
 1083                                 xpt_print(periph->path, "unable to allocate "
 1084                                     "IO UMA zone\n");
 1085                         softc->flags &= ~PASS_FLAG_ZONE_INPROG;
 1086                         goto bailout;
 1087                 }
 1088 
 1089                 /*
 1090                  * Set the flags appropriately and notify any other waiters.
 1091                  */
 1092                 softc->flags &= ~PASS_FLAG_ZONE_INPROG;
 1093                 softc->flags |= PASS_FLAG_ZONE_VALID;
 1094                 wakeup(&softc->pass_zone);
 1095         } else {
 1096                 /*
 1097                  * In this case, the UMA zone has not yet been created, but
 1098                  * another context is in the process of creating it.  We
 1099                  * need to sleep until the creation is either done or has
 1100                  * failed.
 1101                  */
 1102                 while ((softc->flags & PASS_FLAG_ZONE_INPROG)
 1103                     && ((softc->flags & PASS_FLAG_ZONE_VALID) == 0)) {
 1104                         error = msleep(&softc->pass_zone,
 1105                                        cam_periph_mtx(periph), PRIBIO,
 1106                                        "paszon", 0);
 1107                         if (error != 0)
 1108                                 goto bailout;
 1109                 }
 1110                 /*
 1111                  * If the zone creation failed, no luck for the user.
 1112                  */
 1113                 if ((softc->flags & PASS_FLAG_ZONE_VALID) == 0){
 1114                         error = ENOMEM;
 1115                         goto bailout;
 1116                 }
 1117         }
 1118 bailout:
 1119         return (error);
 1120 }
 1121 
 1122 static void
 1123 passiocleanup(struct pass_softc *softc, struct pass_io_req *io_req)
 1124 {
 1125         union ccb *ccb;
 1126         u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
 1127         int i, numbufs;
 1128 
 1129         ccb = &io_req->ccb;
 1130 
 1131         switch (ccb->ccb_h.func_code) {
 1132         case XPT_DEV_MATCH:
 1133                 numbufs = min(io_req->num_bufs, 2);
 1134 
 1135                 if (numbufs == 1) {
 1136                         data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches;
 1137                 } else {
 1138                         data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns;
 1139                         data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches;
 1140                 }
 1141                 break;
 1142         case XPT_SCSI_IO:
 1143         case XPT_CONT_TARGET_IO:
 1144                 data_ptrs[0] = &ccb->csio.data_ptr;
 1145                 numbufs = min(io_req->num_bufs, 1);
 1146                 break;
 1147         case XPT_ATA_IO:
 1148                 data_ptrs[0] = &ccb->ataio.data_ptr;
 1149                 numbufs = min(io_req->num_bufs, 1);
 1150                 break;
 1151         case XPT_SMP_IO:
 1152                 numbufs = min(io_req->num_bufs, 2);
 1153                 data_ptrs[0] = &ccb->smpio.smp_request;
 1154                 data_ptrs[1] = &ccb->smpio.smp_response;
 1155                 break;
 1156         case XPT_DEV_ADVINFO:
 1157                 numbufs = min(io_req->num_bufs, 1);
 1158                 data_ptrs[0] = (uint8_t **)&ccb->cdai.buf;
 1159                 break;
 1160         case XPT_NVME_IO:
 1161         case XPT_NVME_ADMIN:
 1162                 data_ptrs[0] = &ccb->nvmeio.data_ptr;
 1163                 numbufs = min(io_req->num_bufs, 1);
 1164                 break;
 1165         default:
 1166                 /* allow ourselves to be swapped once again */
 1167                 return;
 1168                 break; /* NOTREACHED */ 
 1169         }
 1170 
 1171         if (io_req->flags & PASS_IO_USER_SEG_MALLOC) {
 1172                 free(io_req->user_segptr, M_SCSIPASS);
 1173                 io_req->user_segptr = NULL;
 1174         }
 1175 
 1176         /*
 1177          * We only want to free memory we malloced.
 1178          */
 1179         if (io_req->data_flags == CAM_DATA_VADDR) {
 1180                 for (i = 0; i < io_req->num_bufs; i++) {
 1181                         if (io_req->kern_bufs[i] == NULL)
 1182                                 continue;
 1183 
 1184                         free(io_req->kern_bufs[i], M_SCSIPASS);
 1185                         io_req->kern_bufs[i] = NULL;
 1186                 }
 1187         } else if (io_req->data_flags == CAM_DATA_SG) {
 1188                 for (i = 0; i < io_req->num_kern_segs; i++) {
 1189                         if ((uint8_t *)(uintptr_t)
 1190                             io_req->kern_segptr[i].ds_addr == NULL)
 1191                                 continue;
 1192 
 1193                         uma_zfree(softc->pass_io_zone, (uint8_t *)(uintptr_t)
 1194                             io_req->kern_segptr[i].ds_addr);
 1195                         io_req->kern_segptr[i].ds_addr = 0;
 1196                 }
 1197         }
 1198 
 1199         if (io_req->flags & PASS_IO_KERN_SEG_MALLOC) {
 1200                 free(io_req->kern_segptr, M_SCSIPASS);
 1201                 io_req->kern_segptr = NULL;
 1202         }
 1203 
 1204         if (io_req->data_flags != CAM_DATA_PADDR) {
 1205                 for (i = 0; i < numbufs; i++) {
 1206                         /*
 1207                          * Restore the user's buffer pointers to their
 1208                          * previous values.
 1209                          */
 1210                         if (io_req->user_bufs[i] != NULL)
 1211                                 *data_ptrs[i] = io_req->user_bufs[i];
 1212                 }
 1213         }
 1214 
 1215 }
 1216 
 1217 static int
 1218 passcopysglist(struct cam_periph *periph, struct pass_io_req *io_req,
 1219                ccb_flags direction)
 1220 {
 1221         bus_size_t kern_watermark, user_watermark, len_copied, len_to_copy;
 1222         bus_dma_segment_t *user_sglist, *kern_sglist;
 1223         int i, j, error;
 1224 
 1225         error = 0;
 1226         kern_watermark = 0;
 1227         user_watermark = 0;
 1228         len_to_copy = 0;
 1229         len_copied = 0;
 1230         user_sglist = io_req->user_segptr;
 1231         kern_sglist = io_req->kern_segptr;
 1232 
 1233         for (i = 0, j = 0; i < io_req->num_user_segs &&
 1234              j < io_req->num_kern_segs;) {
 1235                 uint8_t *user_ptr, *kern_ptr;
 1236 
 1237                 len_to_copy = min(user_sglist[i].ds_len -user_watermark,
 1238                     kern_sglist[j].ds_len - kern_watermark);
 1239 
 1240                 user_ptr = (uint8_t *)(uintptr_t)user_sglist[i].ds_addr;
 1241                 user_ptr = user_ptr + user_watermark;
 1242                 kern_ptr = (uint8_t *)(uintptr_t)kern_sglist[j].ds_addr;
 1243                 kern_ptr = kern_ptr + kern_watermark;
 1244 
 1245                 user_watermark += len_to_copy;
 1246                 kern_watermark += len_to_copy;
 1247 
 1248                 if (!useracc(user_ptr, len_to_copy,
 1249                     (direction == CAM_DIR_IN) ? VM_PROT_WRITE : VM_PROT_READ)) {
 1250                         xpt_print(periph->path, "%s: unable to access user "
 1251                                   "S/G list element %p len %zu\n", __func__,
 1252                                   user_ptr, len_to_copy);
 1253                         error = EFAULT;
 1254                         goto bailout;
 1255                 }
 1256 
 1257                 if (direction == CAM_DIR_IN) {
 1258                         error = copyout(kern_ptr, user_ptr, len_to_copy);
 1259                         if (error != 0) {
 1260                                 xpt_print(periph->path, "%s: copyout of %u "
 1261                                           "bytes from %p to %p failed with "
 1262                                           "error %d\n", __func__, len_to_copy,
 1263                                           kern_ptr, user_ptr, error);
 1264                                 goto bailout;
 1265                         }
 1266                 } else {
 1267                         error = copyin(user_ptr, kern_ptr, len_to_copy);
 1268                         if (error != 0) {
 1269                                 xpt_print(periph->path, "%s: copyin of %u "
 1270                                           "bytes from %p to %p failed with "
 1271                                           "error %d\n", __func__, len_to_copy,
 1272                                           user_ptr, kern_ptr, error);
 1273                                 goto bailout;
 1274                         }
 1275                 }
 1276 
 1277                 len_copied += len_to_copy;
 1278 
 1279                 if (user_sglist[i].ds_len == user_watermark) {
 1280                         i++;
 1281                         user_watermark = 0;
 1282                 }
 1283 
 1284                 if (kern_sglist[j].ds_len == kern_watermark) {
 1285                         j++;
 1286                         kern_watermark = 0;
 1287                 }
 1288         }
 1289 
 1290 bailout:
 1291 
 1292         return (error);
 1293 }
 1294 
 1295 static int
 1296 passmemsetup(struct cam_periph *periph, struct pass_io_req *io_req)
 1297 {
 1298         union ccb *ccb;
 1299         struct pass_softc *softc;
 1300         int numbufs, i;
 1301         uint8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
 1302         uint32_t lengths[CAM_PERIPH_MAXMAPS];
 1303         uint32_t dirs[CAM_PERIPH_MAXMAPS];
 1304         uint32_t num_segs;
 1305         uint16_t *seg_cnt_ptr;
 1306         size_t maxmap;
 1307         int error;
 1308 
 1309         cam_periph_assert(periph, MA_NOTOWNED);
 1310 
 1311         softc = periph->softc;
 1312 
 1313         error = 0;
 1314         ccb = &io_req->ccb;
 1315         maxmap = 0;
 1316         num_segs = 0;
 1317         seg_cnt_ptr = NULL;
 1318 
 1319         switch(ccb->ccb_h.func_code) {
 1320         case XPT_DEV_MATCH:
 1321                 if (ccb->cdm.match_buf_len == 0) {
 1322                         printf("%s: invalid match buffer length 0\n", __func__);
 1323                         return(EINVAL);
 1324                 }
 1325                 if (ccb->cdm.pattern_buf_len > 0) {
 1326                         data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns;
 1327                         lengths[0] = ccb->cdm.pattern_buf_len;
 1328                         dirs[0] = CAM_DIR_OUT;
 1329                         data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches;
 1330                         lengths[1] = ccb->cdm.match_buf_len;
 1331                         dirs[1] = CAM_DIR_IN;
 1332                         numbufs = 2;
 1333                 } else {
 1334                         data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches;
 1335                         lengths[0] = ccb->cdm.match_buf_len;
 1336                         dirs[0] = CAM_DIR_IN;
 1337                         numbufs = 1;
 1338                 }
 1339                 io_req->data_flags = CAM_DATA_VADDR;
 1340                 break;
 1341         case XPT_SCSI_IO:
 1342         case XPT_CONT_TARGET_IO:
 1343                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
 1344                         return(0);
 1345 
 1346                 /*
 1347                  * The user shouldn't be able to supply a bio.
 1348                  */
 1349                 if ((ccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_BIO)
 1350                         return (EINVAL);
 1351 
 1352                 io_req->data_flags = ccb->ccb_h.flags & CAM_DATA_MASK;
 1353 
 1354                 data_ptrs[0] = &ccb->csio.data_ptr;
 1355                 lengths[0] = ccb->csio.dxfer_len;
 1356                 dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
 1357                 num_segs = ccb->csio.sglist_cnt;
 1358                 seg_cnt_ptr = &ccb->csio.sglist_cnt;
 1359                 numbufs = 1;
 1360                 maxmap = softc->maxio;
 1361                 break;
 1362         case XPT_ATA_IO:
 1363                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
 1364                         return(0);
 1365 
 1366                 /*
 1367                  * We only support a single virtual address for ATA I/O.
 1368                  */
 1369                 if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR)
 1370                         return (EINVAL);
 1371 
 1372                 io_req->data_flags = CAM_DATA_VADDR;
 1373 
 1374                 data_ptrs[0] = &ccb->ataio.data_ptr;
 1375                 lengths[0] = ccb->ataio.dxfer_len;
 1376                 dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
 1377                 numbufs = 1;
 1378                 maxmap = softc->maxio;
 1379                 break;
 1380         case XPT_SMP_IO:
 1381                 io_req->data_flags = CAM_DATA_VADDR;
 1382 
 1383                 data_ptrs[0] = &ccb->smpio.smp_request;
 1384                 lengths[0] = ccb->smpio.smp_request_len;
 1385                 dirs[0] = CAM_DIR_OUT;
 1386                 data_ptrs[1] = &ccb->smpio.smp_response;
 1387                 lengths[1] = ccb->smpio.smp_response_len;
 1388                 dirs[1] = CAM_DIR_IN;
 1389                 numbufs = 2;
 1390                 maxmap = softc->maxio;
 1391                 break;
 1392         case XPT_DEV_ADVINFO:
 1393                 if (ccb->cdai.bufsiz == 0)
 1394                         return (0);
 1395 
 1396                 io_req->data_flags = CAM_DATA_VADDR;
 1397 
 1398                 data_ptrs[0] = (uint8_t **)&ccb->cdai.buf;
 1399                 lengths[0] = ccb->cdai.bufsiz;
 1400                 dirs[0] = CAM_DIR_IN;
 1401                 numbufs = 1;
 1402                 break;
 1403         case XPT_NVME_ADMIN:
 1404         case XPT_NVME_IO:
 1405                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
 1406                         return (0);
 1407 
 1408                 io_req->data_flags = ccb->ccb_h.flags & CAM_DATA_MASK;
 1409 
 1410                 data_ptrs[0] = &ccb->nvmeio.data_ptr;
 1411                 lengths[0] = ccb->nvmeio.dxfer_len;
 1412                 dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
 1413                 num_segs = ccb->nvmeio.sglist_cnt;
 1414                 seg_cnt_ptr = &ccb->nvmeio.sglist_cnt;
 1415                 numbufs = 1;
 1416                 maxmap = softc->maxio;
 1417                 break;
 1418         default:
 1419                 return(EINVAL);
 1420                 break; /* NOTREACHED */
 1421         }
 1422 
 1423         io_req->num_bufs = numbufs;
 1424 
 1425         /*
 1426          * If there is a maximum, check to make sure that the user's
 1427          * request fits within the limit.  In general, we should only have
 1428          * a maximum length for requests that go to hardware.  Otherwise it
 1429          * is whatever we're able to malloc.
 1430          */
 1431         for (i = 0; i < numbufs; i++) {
 1432                 io_req->user_bufs[i] = *data_ptrs[i];
 1433                 io_req->dirs[i] = dirs[i];
 1434                 io_req->lengths[i] = lengths[i];
 1435 
 1436                 if (maxmap == 0)
 1437                         continue;
 1438 
 1439                 if (lengths[i] <= maxmap)
 1440                         continue;
 1441 
 1442                 xpt_print(periph->path, "%s: data length %u > max allowed %u "
 1443                           "bytes\n", __func__, lengths[i], maxmap);
 1444                 error = EINVAL;
 1445                 goto bailout;
 1446         }
 1447 
 1448         switch (io_req->data_flags) {
 1449         case CAM_DATA_VADDR:
 1450                 /* Map or copy the buffer into kernel address space */
 1451                 for (i = 0; i < numbufs; i++) {
 1452                         uint8_t *tmp_buf;
 1453 
 1454                         /*
 1455                          * If for some reason no length is specified, we
 1456                          * don't need to allocate anything.
 1457                          */
 1458                         if (io_req->lengths[i] == 0)
 1459                                 continue;
 1460 
 1461                         /*
 1462                          * Make sure that the user's buffer is accessible
 1463                          * to that process.
 1464                          */
 1465                         if (!useracc(io_req->user_bufs[i], io_req->lengths[i],
 1466                             (io_req->dirs[i] == CAM_DIR_IN) ? VM_PROT_WRITE :
 1467                              VM_PROT_READ)) {
 1468                                 xpt_print(periph->path, "%s: user address %p "
 1469                                     "length %u is not accessible\n", __func__,
 1470                                     io_req->user_bufs[i], io_req->lengths[i]);
 1471                                 error = EFAULT;
 1472                                 goto bailout;
 1473                         }
 1474 
 1475                         tmp_buf = malloc(lengths[i], M_SCSIPASS,
 1476                                          M_WAITOK | M_ZERO);
 1477                         io_req->kern_bufs[i] = tmp_buf;
 1478                         *data_ptrs[i] = tmp_buf;
 1479 
 1480 #if 0
 1481                         xpt_print(periph->path, "%s: malloced %p len %u, user "
 1482                                   "buffer %p, operation: %s\n", __func__,
 1483                                   tmp_buf, lengths[i], io_req->user_bufs[i],
 1484                                   (dirs[i] == CAM_DIR_IN) ? "read" : "write");
 1485 #endif
 1486                         /*
 1487                          * We only need to copy in if the user is writing.
 1488                          */
 1489                         if (dirs[i] != CAM_DIR_OUT)
 1490                                 continue;
 1491 
 1492                         error = copyin(io_req->user_bufs[i],
 1493                                        io_req->kern_bufs[i], lengths[i]);
 1494                         if (error != 0) {
 1495                                 xpt_print(periph->path, "%s: copy of user "
 1496                                           "buffer from %p to %p failed with "
 1497                                           "error %d\n", __func__,
 1498                                           io_req->user_bufs[i],
 1499                                           io_req->kern_bufs[i], error);
 1500                                 goto bailout;
 1501                         }
 1502                 }
 1503                 break;
 1504         case CAM_DATA_PADDR:
 1505                 /* Pass down the pointer as-is */
 1506                 break;
 1507         case CAM_DATA_SG: {
 1508                 size_t sg_length, size_to_go, alloc_size;
 1509                 uint32_t num_segs_needed;
 1510 
 1511                 /*
 1512                  * Copy the user S/G list in, and then copy in the
 1513                  * individual segments.
 1514                  */
 1515                 /*
 1516                  * We shouldn't see this, but check just in case.
 1517                  */
 1518                 if (numbufs != 1) {
 1519                         xpt_print(periph->path, "%s: cannot currently handle "
 1520                                   "more than one S/G list per CCB\n", __func__);
 1521                         error = EINVAL;
 1522                         goto bailout;
 1523                 }
 1524 
 1525                 /*
 1526                  * We have to have at least one segment.
 1527                  */
 1528                 if (num_segs == 0) {
 1529                         xpt_print(periph->path, "%s: CAM_DATA_SG flag set, "
 1530                                   "but sglist_cnt=0!\n", __func__);
 1531                         error = EINVAL;
 1532                         goto bailout;
 1533                 }
 1534 
 1535                 /*
 1536                  * Make sure the user specified the total length and didn't
 1537                  * just leave it to us to decode the S/G list.
 1538                  */
 1539                 if (lengths[0] == 0) {
 1540                         xpt_print(periph->path, "%s: no dxfer_len specified, "
 1541                                   "but CAM_DATA_SG flag is set!\n", __func__);
 1542                         error = EINVAL;
 1543                         goto bailout;
 1544                 }
 1545 
 1546                 /*
 1547                  * We allocate buffers in io_zone_size increments for an
 1548                  * S/G list.  This will generally be MAXPHYS.
 1549                  */
 1550                 if (lengths[0] <= softc->io_zone_size)
 1551                         num_segs_needed = 1;
 1552                 else {
 1553                         num_segs_needed = lengths[0] / softc->io_zone_size;
 1554                         if ((lengths[0] % softc->io_zone_size) != 0)
 1555                                 num_segs_needed++;
 1556                 }
 1557 
 1558                 /* Figure out the size of the S/G list */
 1559                 sg_length = num_segs * sizeof(bus_dma_segment_t);
 1560                 io_req->num_user_segs = num_segs;
 1561                 io_req->num_kern_segs = num_segs_needed;
 1562 
 1563                 /* Save the user's S/G list pointer for later restoration */
 1564                 io_req->user_bufs[0] = *data_ptrs[0];
 1565 
 1566                 /*
 1567                  * If we have enough segments allocated by default to handle
 1568                  * the length of the user's S/G list,
 1569                  */
 1570                 if (num_segs > PASS_MAX_SEGS) {
 1571                         io_req->user_segptr = malloc(sizeof(bus_dma_segment_t) *
 1572                             num_segs, M_SCSIPASS, M_WAITOK | M_ZERO);
 1573                         io_req->flags |= PASS_IO_USER_SEG_MALLOC;
 1574                 } else
 1575                         io_req->user_segptr = io_req->user_segs;
 1576 
 1577                 if (!useracc(*data_ptrs[0], sg_length, VM_PROT_READ)) {
 1578                         xpt_print(periph->path, "%s: unable to access user "
 1579                                   "S/G list at %p\n", __func__, *data_ptrs[0]);
 1580                         error = EFAULT;
 1581                         goto bailout;
 1582                 }
 1583 
 1584                 error = copyin(*data_ptrs[0], io_req->user_segptr, sg_length);
 1585                 if (error != 0) {
 1586                         xpt_print(periph->path, "%s: copy of user S/G list "
 1587                                   "from %p to %p failed with error %d\n",
 1588                                   __func__, *data_ptrs[0], io_req->user_segptr,
 1589                                   error);
 1590                         goto bailout;
 1591                 }
 1592 
 1593                 if (num_segs_needed > PASS_MAX_SEGS) {
 1594                         io_req->kern_segptr = malloc(sizeof(bus_dma_segment_t) *
 1595                             num_segs_needed, M_SCSIPASS, M_WAITOK | M_ZERO);
 1596                         io_req->flags |= PASS_IO_KERN_SEG_MALLOC;
 1597                 } else {
 1598                         io_req->kern_segptr = io_req->kern_segs;
 1599                 }
 1600 
 1601                 /*
 1602                  * Allocate the kernel S/G list.
 1603                  */
 1604                 for (size_to_go = lengths[0], i = 0;
 1605                      size_to_go > 0 && i < num_segs_needed;
 1606                      i++, size_to_go -= alloc_size) {
 1607                         uint8_t *kern_ptr;
 1608 
 1609                         alloc_size = min(size_to_go, softc->io_zone_size);
 1610                         kern_ptr = uma_zalloc(softc->pass_io_zone, M_WAITOK);
 1611                         io_req->kern_segptr[i].ds_addr =
 1612                             (bus_addr_t)(uintptr_t)kern_ptr;
 1613                         io_req->kern_segptr[i].ds_len = alloc_size;
 1614                 }
 1615                 if (size_to_go > 0) {
 1616                         printf("%s: size_to_go = %zu, software error!\n",
 1617                                __func__, size_to_go);
 1618                         error = EINVAL;
 1619                         goto bailout;
 1620                 }
 1621 
 1622                 *data_ptrs[0] = (uint8_t *)io_req->kern_segptr;
 1623                 *seg_cnt_ptr = io_req->num_kern_segs;
 1624 
 1625                 /*
 1626                  * We only need to copy data here if the user is writing.
 1627                  */
 1628                 if (dirs[0] == CAM_DIR_OUT)
 1629                         error = passcopysglist(periph, io_req, dirs[0]);
 1630                 break;
 1631         }
 1632         case CAM_DATA_SG_PADDR: {
 1633                 size_t sg_length;
 1634 
 1635                 /*
 1636                  * We shouldn't see this, but check just in case.
 1637                  */
 1638                 if (numbufs != 1) {
 1639                         printf("%s: cannot currently handle more than one "
 1640                                "S/G list per CCB\n", __func__);
 1641                         error = EINVAL;
 1642                         goto bailout;
 1643                 }
 1644 
 1645                 /*
 1646                  * We have to have at least one segment.
 1647                  */
 1648                 if (num_segs == 0) {
 1649                         xpt_print(periph->path, "%s: CAM_DATA_SG_PADDR flag "
 1650                                   "set, but sglist_cnt=0!\n", __func__);
 1651                         error = EINVAL;
 1652                         goto bailout;
 1653                 }
 1654 
 1655                 /*
 1656                  * Make sure the user specified the total length and didn't
 1657                  * just leave it to us to decode the S/G list.
 1658                  */
 1659                 if (lengths[0] == 0) {
 1660                         xpt_print(periph->path, "%s: no dxfer_len specified, "
 1661                                   "but CAM_DATA_SG flag is set!\n", __func__);
 1662                         error = EINVAL;
 1663                         goto bailout;
 1664                 }
 1665 
 1666                 /* Figure out the size of the S/G list */
 1667                 sg_length = num_segs * sizeof(bus_dma_segment_t);
 1668                 io_req->num_user_segs = num_segs;
 1669                 io_req->num_kern_segs = io_req->num_user_segs;
 1670 
 1671                 /* Save the user's S/G list pointer for later restoration */
 1672                 io_req->user_bufs[0] = *data_ptrs[0];
 1673 
 1674                 if (num_segs > PASS_MAX_SEGS) {
 1675                         io_req->user_segptr = malloc(sizeof(bus_dma_segment_t) *
 1676                             num_segs, M_SCSIPASS, M_WAITOK | M_ZERO);
 1677                         io_req->flags |= PASS_IO_USER_SEG_MALLOC;
 1678                 } else
 1679                         io_req->user_segptr = io_req->user_segs;
 1680 
 1681                 io_req->kern_segptr = io_req->user_segptr;
 1682 
 1683                 error = copyin(*data_ptrs[0], io_req->user_segptr, sg_length);
 1684                 if (error != 0) {
 1685                         xpt_print(periph->path, "%s: copy of user S/G list "
 1686                                   "from %p to %p failed with error %d\n",
 1687                                   __func__, *data_ptrs[0], io_req->user_segptr,
 1688                                   error);
 1689                         goto bailout;
 1690                 }
 1691                 break;
 1692         }
 1693         default:
 1694         case CAM_DATA_BIO:
 1695                 /*
 1696                  * A user shouldn't be attaching a bio to the CCB.  It
 1697                  * isn't a user-accessible structure.
 1698                  */
 1699                 error = EINVAL;
 1700                 break;
 1701         }
 1702 
 1703 bailout:
 1704         if (error != 0)
 1705                 passiocleanup(softc, io_req);
 1706 
 1707         return (error);
 1708 }
 1709 
 1710 static int
 1711 passmemdone(struct cam_periph *periph, struct pass_io_req *io_req)
 1712 {
 1713         struct pass_softc *softc;
 1714         int error;
 1715         int i;
 1716 
 1717         error = 0;
 1718         softc = (struct pass_softc *)periph->softc;
 1719 
 1720         switch (io_req->data_flags) {
 1721         case CAM_DATA_VADDR:
 1722                 /*
 1723                  * Copy back to the user buffer if this was a read.
 1724                  */
 1725                 for (i = 0; i < io_req->num_bufs; i++) {
 1726                         if (io_req->dirs[i] != CAM_DIR_IN)
 1727                                 continue;
 1728 
 1729                         error = copyout(io_req->kern_bufs[i],
 1730                             io_req->user_bufs[i], io_req->lengths[i]);
 1731                         if (error != 0) {
 1732                                 xpt_print(periph->path, "Unable to copy %u "
 1733                                           "bytes from %p to user address %p\n",
 1734                                           io_req->lengths[i],
 1735                                           io_req->kern_bufs[i],
 1736                                           io_req->user_bufs[i]);
 1737                                 goto bailout;
 1738                         }
 1739 
 1740                 }
 1741                 break;
 1742         case CAM_DATA_PADDR:
 1743                 /* Do nothing.  The pointer is a physical address already */
 1744                 break;
 1745         case CAM_DATA_SG:
 1746                 /*
 1747                  * Copy back to the user buffer if this was a read.
 1748                  * Restore the user's S/G list buffer pointer.
 1749                  */
 1750                 if (io_req->dirs[0] == CAM_DIR_IN)
 1751                         error = passcopysglist(periph, io_req, io_req->dirs[0]);
 1752                 break;
 1753         case CAM_DATA_SG_PADDR:
 1754                 /*
 1755                  * Restore the user's S/G list buffer pointer.  No need to
 1756                  * copy.
 1757                  */
 1758                 break;
 1759         default:
 1760         case CAM_DATA_BIO:
 1761                 error = EINVAL;
 1762                 break;
 1763         }
 1764 
 1765 bailout:
 1766         /*
 1767          * Reset the user's pointers to their original values and free
 1768          * allocated memory.
 1769          */
 1770         passiocleanup(softc, io_req);
 1771 
 1772         return (error);
 1773 }
 1774 
 1775 static int
 1776 passioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
 1777 {
 1778         int error;
 1779 
 1780         if ((error = passdoioctl(dev, cmd, addr, flag, td)) == ENOTTY) {
 1781                 error = cam_compat_ioctl(dev, cmd, addr, flag, td, passdoioctl);
 1782         }
 1783         return (error);
 1784 }
 1785 
 1786 static int
 1787 passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
 1788 {
 1789         struct  cam_periph *periph;
 1790         struct  pass_softc *softc;
 1791         int     error;
 1792         uint32_t priority;
 1793 
 1794         periph = (struct cam_periph *)dev->si_drv1;
 1795         cam_periph_lock(periph);
 1796         softc = (struct pass_softc *)periph->softc;
 1797 
 1798         error = 0;
 1799 
 1800         switch (cmd) {
 1801 
 1802         case CAMIOCOMMAND:
 1803         {
 1804                 union ccb *inccb;
 1805                 union ccb *ccb;
 1806                 int ccb_malloced;
 1807 
 1808                 inccb = (union ccb *)addr;
 1809 #if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
 1810                 if (inccb->ccb_h.func_code == XPT_SCSI_IO)
 1811                         inccb->csio.bio = NULL;
 1812 #endif
 1813 
 1814                 if (inccb->ccb_h.flags & CAM_UNLOCKED) {
 1815                         error = EINVAL;
 1816                         break;
 1817                 }
 1818 
 1819                 /*
 1820                  * Some CCB types, like scan bus and scan lun can only go
 1821                  * through the transport layer device.
 1822                  */
 1823                 if (inccb->ccb_h.func_code & XPT_FC_XPT_ONLY) {
 1824                         xpt_print(periph->path, "CCB function code %#x is "
 1825                             "restricted to the XPT device\n",
 1826                             inccb->ccb_h.func_code);
 1827                         error = ENODEV;
 1828                         break;
 1829                 }
 1830 
 1831                 /* Compatibility for RL/priority-unaware code. */
 1832                 priority = inccb->ccb_h.pinfo.priority;
 1833                 if (priority <= CAM_PRIORITY_OOB)
 1834                     priority += CAM_PRIORITY_OOB + 1;
 1835 
 1836                 /*
 1837                  * Non-immediate CCBs need a CCB from the per-device pool
 1838                  * of CCBs, which is scheduled by the transport layer.
 1839                  * Immediate CCBs and user-supplied CCBs should just be
 1840                  * malloced.
 1841                  */
 1842                 if ((inccb->ccb_h.func_code & XPT_FC_QUEUED)
 1843                  && ((inccb->ccb_h.func_code & XPT_FC_USER_CCB) == 0)) {
 1844                         ccb = cam_periph_getccb(periph, priority);
 1845                         ccb_malloced = 0;
 1846                 } else {
 1847                         ccb = xpt_alloc_ccb_nowait();
 1848 
 1849                         if (ccb != NULL)
 1850                                 xpt_setup_ccb(&ccb->ccb_h, periph->path,
 1851                                               priority);
 1852                         ccb_malloced = 1;
 1853                 }
 1854 
 1855                 if (ccb == NULL) {
 1856                         xpt_print(periph->path, "unable to allocate CCB\n");
 1857                         error = ENOMEM;
 1858                         break;
 1859                 }
 1860 
 1861                 error = passsendccb(periph, ccb, inccb);
 1862 
 1863                 if (ccb_malloced)
 1864                         xpt_free_ccb(ccb);
 1865                 else
 1866                         xpt_release_ccb(ccb);
 1867 
 1868                 break;
 1869         }
 1870         case CAMIOQUEUE:
 1871         {
 1872                 struct pass_io_req *io_req;
 1873                 union ccb **user_ccb, *ccb;
 1874                 xpt_opcode fc;
 1875 
 1876 #ifdef COMPAT_FREEBSD32
 1877                 if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
 1878                         error = ENOTTY;
 1879                         goto bailout;
 1880                 }
 1881 #endif
 1882                 if ((softc->flags & PASS_FLAG_ZONE_VALID) == 0) {
 1883                         error = passcreatezone(periph);
 1884                         if (error != 0)
 1885                                 goto bailout;
 1886                 }
 1887 
 1888                 /*
 1889                  * We're going to do a blocking allocation for this I/O
 1890                  * request, so we have to drop the lock.
 1891                  */
 1892                 cam_periph_unlock(periph);
 1893 
 1894                 io_req = uma_zalloc(softc->pass_zone, M_WAITOK | M_ZERO);
 1895                 ccb = &io_req->ccb;
 1896                 user_ccb = (union ccb **)addr;
 1897 
 1898                 /*
 1899                  * Unlike the CAMIOCOMMAND ioctl above, we only have a
 1900                  * pointer to the user's CCB, so we have to copy the whole
 1901                  * thing in to a buffer we have allocated (above) instead
 1902                  * of allowing the ioctl code to malloc a buffer and copy
 1903                  * it in.
 1904                  *
 1905                  * This is an advantage for this asynchronous interface,
 1906                  * since we don't want the memory to get freed while the
 1907                  * CCB is outstanding.
 1908                  */
 1909 #if 0
 1910                 xpt_print(periph->path, "Copying user CCB %p to "
 1911                           "kernel address %p\n", *user_ccb, ccb);
 1912 #endif
 1913                 error = copyin(*user_ccb, ccb, sizeof(*ccb));
 1914                 if (error != 0) {
 1915                         xpt_print(periph->path, "Copy of user CCB %p to "
 1916                                   "kernel address %p failed with error %d\n",
 1917                                   *user_ccb, ccb, error);
 1918                         goto camioqueue_error;
 1919                 }
 1920 #if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
 1921                 if (ccb->ccb_h.func_code == XPT_SCSI_IO)
 1922                         ccb->csio.bio = NULL;
 1923 #endif
 1924 
 1925                 if (ccb->ccb_h.flags & CAM_UNLOCKED) {
 1926                         error = EINVAL;
 1927                         goto camioqueue_error;
 1928                 }
 1929 
 1930                 if (ccb->ccb_h.flags & CAM_CDB_POINTER) {
 1931                         if (ccb->csio.cdb_len > IOCDBLEN) {
 1932                                 error = EINVAL;
 1933                                 goto camioqueue_error;
 1934                         }
 1935                         error = copyin(ccb->csio.cdb_io.cdb_ptr,
 1936                             ccb->csio.cdb_io.cdb_bytes, ccb->csio.cdb_len);
 1937                         if (error != 0)
 1938                                 goto camioqueue_error;
 1939                         ccb->ccb_h.flags &= ~CAM_CDB_POINTER;
 1940                 }
 1941 
 1942                 /*
 1943                  * Some CCB types, like scan bus and scan lun can only go
 1944                  * through the transport layer device.
 1945                  */
 1946                 if (ccb->ccb_h.func_code & XPT_FC_XPT_ONLY) {
 1947                         xpt_print(periph->path, "CCB function code %#x is "
 1948                             "restricted to the XPT device\n",
 1949                             ccb->ccb_h.func_code);
 1950                         error = ENODEV;
 1951                         goto camioqueue_error;
 1952                 }
 1953 
 1954                 /*
 1955                  * Save the user's CCB pointer as well as his linked list
 1956                  * pointers and peripheral private area so that we can
 1957                  * restore these later.
 1958                  */
 1959                 io_req->user_ccb_ptr = *user_ccb;
 1960                 io_req->user_periph_links = ccb->ccb_h.periph_links;
 1961                 io_req->user_periph_priv = ccb->ccb_h.periph_priv;
 1962 
 1963                 /*
 1964                  * Now that we've saved the user's values, we can set our
 1965                  * own peripheral private entry.
 1966                  */
 1967                 ccb->ccb_h.ccb_ioreq = io_req;
 1968 
 1969                 /* Compatibility for RL/priority-unaware code. */
 1970                 priority = ccb->ccb_h.pinfo.priority;
 1971                 if (priority <= CAM_PRIORITY_OOB)
 1972                     priority += CAM_PRIORITY_OOB + 1;
 1973 
 1974                 /*
 1975                  * Setup fields in the CCB like the path and the priority.
 1976                  * The path in particular cannot be done in userland, since
 1977                  * it is a pointer to a kernel data structure.
 1978                  */
 1979                 xpt_setup_ccb_flags(&ccb->ccb_h, periph->path, priority,
 1980                                     ccb->ccb_h.flags);
 1981 
 1982                 /*
 1983                  * Setup our done routine.  There is no way for the user to
 1984                  * have a valid pointer here.
 1985                  */
 1986                 ccb->ccb_h.cbfcnp = passdone;
 1987 
 1988                 fc = ccb->ccb_h.func_code;
 1989                 /*
 1990                  * If this function code has memory that can be mapped in
 1991                  * or out, we need to call passmemsetup().
 1992                  */
 1993                 if ((fc == XPT_SCSI_IO) || (fc == XPT_ATA_IO)
 1994                  || (fc == XPT_SMP_IO) || (fc == XPT_DEV_MATCH)
 1995                  || (fc == XPT_DEV_ADVINFO)
 1996                  || (fc == XPT_NVME_ADMIN) || (fc == XPT_NVME_IO)) {
 1997                         error = passmemsetup(periph, io_req);
 1998                         if (error != 0)
 1999                                 goto camioqueue_error;
 2000                 } else
 2001                         io_req->mapinfo.num_bufs_used = 0;
 2002 
 2003                 cam_periph_lock(periph);
 2004 
 2005                 /*
 2006                  * Everything goes on the incoming queue initially.
 2007                  */
 2008                 TAILQ_INSERT_TAIL(&softc->incoming_queue, io_req, links);
 2009 
 2010                 /*
 2011                  * If the CCB is queued, and is not a user CCB, then
 2012                  * we need to allocate a slot for it.  Call xpt_schedule()
 2013                  * so that our start routine will get called when a CCB is
 2014                  * available.
 2015                  */
 2016                 if ((fc & XPT_FC_QUEUED)
 2017                  && ((fc & XPT_FC_USER_CCB) == 0)) {
 2018                         xpt_schedule(periph, priority);
 2019                         break;
 2020                 } 
 2021 
 2022                 /*
 2023                  * At this point, the CCB in question is either an
 2024                  * immediate CCB (like XPT_DEV_ADVINFO) or it is a user CCB
 2025                  * and therefore should be malloced, not allocated via a slot.
 2026                  * Remove the CCB from the incoming queue and add it to the
 2027                  * active queue.
 2028                  */
 2029                 TAILQ_REMOVE(&softc->incoming_queue, io_req, links);
 2030                 TAILQ_INSERT_TAIL(&softc->active_queue, io_req, links);
 2031 
 2032                 xpt_action(ccb);
 2033 
 2034                 /*
 2035                  * If this is not a queued CCB (i.e. it is an immediate CCB),
 2036                  * then it is already done.  We need to put it on the done
 2037                  * queue for the user to fetch.
 2038                  */
 2039                 if ((fc & XPT_FC_QUEUED) == 0) {
 2040                         TAILQ_REMOVE(&softc->active_queue, io_req, links);
 2041                         TAILQ_INSERT_TAIL(&softc->done_queue, io_req, links);
 2042                 }
 2043                 break;
 2044 
 2045 camioqueue_error:
 2046                 uma_zfree(softc->pass_zone, io_req);
 2047                 cam_periph_lock(periph);
 2048                 break;
 2049         }
 2050         case CAMIOGET:
 2051         {
 2052                 union ccb **user_ccb;
 2053                 struct pass_io_req *io_req;
 2054                 int old_error;
 2055 
 2056 #ifdef COMPAT_FREEBSD32
 2057                 if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
 2058                         error = ENOTTY;
 2059                         goto bailout;
 2060                 }
 2061 #endif
 2062                 user_ccb = (union ccb **)addr;
 2063                 old_error = 0;
 2064 
 2065                 io_req = TAILQ_FIRST(&softc->done_queue);
 2066                 if (io_req == NULL) {
 2067                         error = ENOENT;
 2068                         break;
 2069                 }
 2070 
 2071                 /*
 2072                  * Remove the I/O from the done queue.
 2073                  */
 2074                 TAILQ_REMOVE(&softc->done_queue, io_req, links);
 2075 
 2076                 /*
 2077                  * We have to drop the lock during the copyout because the
 2078                  * copyout can result in VM faults that require sleeping.
 2079                  */
 2080                 cam_periph_unlock(periph);
 2081 
 2082                 /*
 2083                  * Do any needed copies (e.g. for reads) and revert the
 2084                  * pointers in the CCB back to the user's pointers.
 2085                  */
 2086                 error = passmemdone(periph, io_req);
 2087 
 2088                 old_error = error;
 2089 
 2090                 io_req->ccb.ccb_h.periph_links = io_req->user_periph_links;
 2091                 io_req->ccb.ccb_h.periph_priv = io_req->user_periph_priv;
 2092 
 2093 #if 0
 2094                 xpt_print(periph->path, "Copying to user CCB %p from "
 2095                           "kernel address %p\n", *user_ccb, &io_req->ccb);
 2096 #endif
 2097 
 2098                 error = copyout(&io_req->ccb, *user_ccb, sizeof(union ccb));
 2099                 if (error != 0) {
 2100                         xpt_print(periph->path, "Copy to user CCB %p from "
 2101                                   "kernel address %p failed with error %d\n",
 2102                                   *user_ccb, &io_req->ccb, error);
 2103                 }
 2104 
 2105                 /*
 2106                  * Prefer the first error we got back, and make sure we
 2107                  * don't overwrite bad status with good.
 2108                  */
 2109                 if (old_error != 0)
 2110                         error = old_error;
 2111 
 2112                 cam_periph_lock(periph);
 2113 
 2114                 /*
 2115                  * At this point, if there was an error, we could potentially
 2116                  * re-queue the I/O and try again.  But why?  The error
 2117                  * would almost certainly happen again.  We might as well
 2118                  * not leak memory.
 2119                  */
 2120                 uma_zfree(softc->pass_zone, io_req);
 2121                 break;
 2122         }
 2123         default:
 2124                 error = cam_periph_ioctl(periph, cmd, addr, passerror);
 2125                 break;
 2126         }
 2127 
 2128 bailout:
 2129         cam_periph_unlock(periph);
 2130 
 2131         return(error);
 2132 }
 2133 
 2134 static int
 2135 passpoll(struct cdev *dev, int poll_events, struct thread *td)
 2136 {
 2137         struct cam_periph *periph;
 2138         struct pass_softc *softc;
 2139         int revents;
 2140 
 2141         periph = (struct cam_periph *)dev->si_drv1;
 2142         softc = (struct pass_softc *)periph->softc;
 2143 
 2144         revents = poll_events & (POLLOUT | POLLWRNORM);
 2145         if ((poll_events & (POLLIN | POLLRDNORM)) != 0) {
 2146                 cam_periph_lock(periph);
 2147 
 2148                 if (!TAILQ_EMPTY(&softc->done_queue)) {
 2149                         revents |= poll_events & (POLLIN | POLLRDNORM);
 2150                 }
 2151                 cam_periph_unlock(periph);
 2152                 if (revents == 0)
 2153                         selrecord(td, &softc->read_select);
 2154         }
 2155 
 2156         return (revents);
 2157 }
 2158 
 2159 static int
 2160 passkqfilter(struct cdev *dev, struct knote *kn)
 2161 {
 2162         struct cam_periph *periph;
 2163         struct pass_softc *softc;
 2164 
 2165         periph = (struct cam_periph *)dev->si_drv1;
 2166         softc = (struct pass_softc *)periph->softc;
 2167 
 2168         kn->kn_hook = (caddr_t)periph;
 2169         kn->kn_fop = &passread_filtops;
 2170         knlist_add(&softc->read_select.si_note, kn, 0);
 2171 
 2172         return (0);
 2173 }
 2174 
 2175 static void
 2176 passreadfiltdetach(struct knote *kn)
 2177 {
 2178         struct cam_periph *periph;
 2179         struct pass_softc *softc;
 2180 
 2181         periph = (struct cam_periph *)kn->kn_hook;
 2182         softc = (struct pass_softc *)periph->softc;
 2183 
 2184         knlist_remove(&softc->read_select.si_note, kn, 0);
 2185 }
 2186 
 2187 static int
 2188 passreadfilt(struct knote *kn, long hint)
 2189 {
 2190         struct cam_periph *periph;
 2191         struct pass_softc *softc;
 2192         int retval;
 2193 
 2194         periph = (struct cam_periph *)kn->kn_hook;
 2195         softc = (struct pass_softc *)periph->softc;
 2196 
 2197         cam_periph_assert(periph, MA_OWNED);
 2198 
 2199         if (TAILQ_EMPTY(&softc->done_queue))
 2200                 retval = 0;
 2201         else
 2202                 retval = 1;
 2203 
 2204         return (retval);
 2205 }
 2206 
 2207 /*
 2208  * Generally, "ccb" should be the CCB supplied by the kernel.  "inccb"
 2209  * should be the CCB that is copied in from the user.
 2210  */
 2211 static int
 2212 passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
 2213 {
 2214         struct pass_softc *softc;
 2215         struct cam_periph_map_info mapinfo;
 2216         uint8_t *cmd;
 2217         xpt_opcode fc;
 2218         int error;
 2219 
 2220         softc = (struct pass_softc *)periph->softc;
 2221 
 2222         /*
 2223          * There are some fields in the CCB header that need to be
 2224          * preserved, the rest we get from the user.
 2225          */
 2226         xpt_merge_ccb(ccb, inccb);
 2227 
 2228         if (ccb->ccb_h.flags & CAM_CDB_POINTER) {
 2229                 cmd = __builtin_alloca(ccb->csio.cdb_len);
 2230                 error = copyin(ccb->csio.cdb_io.cdb_ptr, cmd, ccb->csio.cdb_len);
 2231                 if (error)
 2232                         return (error);
 2233                 ccb->csio.cdb_io.cdb_ptr = cmd;
 2234         }
 2235 
 2236         /*
 2237          * Let cam_periph_mapmem do a sanity check on the data pointer format.
 2238          * Even if no data transfer is needed, it's a cheap check and it
 2239          * simplifies the code.
 2240          */
 2241         fc = ccb->ccb_h.func_code;
 2242         if ((fc == XPT_SCSI_IO) || (fc == XPT_ATA_IO) || (fc == XPT_SMP_IO)
 2243             || (fc == XPT_DEV_MATCH) || (fc == XPT_DEV_ADVINFO) || (fc == XPT_MMC_IO)
 2244             || (fc == XPT_NVME_ADMIN) || (fc == XPT_NVME_IO)) {
 2245 
 2246                 bzero(&mapinfo, sizeof(mapinfo));
 2247 
 2248                 /*
 2249                  * cam_periph_mapmem calls into proc and vm functions that can
 2250                  * sleep as well as trigger I/O, so we can't hold the lock.
 2251                  * Dropping it here is reasonably safe.
 2252                  */
 2253                 cam_periph_unlock(periph);
 2254                 error = cam_periph_mapmem(ccb, &mapinfo, softc->maxio);
 2255                 cam_periph_lock(periph);
 2256 
 2257                 /*
 2258                  * cam_periph_mapmem returned an error, we can't continue.
 2259                  * Return the error to the user.
 2260                  */
 2261                 if (error)
 2262                         return(error);
 2263         } else
 2264                 /* Ensure that the unmap call later on is a no-op. */
 2265                 mapinfo.num_bufs_used = 0;
 2266 
 2267         /*
 2268          * If the user wants us to perform any error recovery, then honor
 2269          * that request.  Otherwise, it's up to the user to perform any
 2270          * error recovery.
 2271          */
 2272         cam_periph_runccb(ccb, (ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ? 
 2273             passerror : NULL, /* cam_flags */ CAM_RETRY_SELTO,
 2274             /* sense_flags */ SF_RETRY_UA | SF_NO_PRINT,
 2275             softc->device_stats);
 2276 
 2277         cam_periph_unlock(periph);
 2278         cam_periph_unmapmem(ccb, &mapinfo);
 2279         cam_periph_lock(periph);
 2280 
 2281         ccb->ccb_h.cbfcnp = NULL;
 2282         ccb->ccb_h.periph_priv = inccb->ccb_h.periph_priv;
 2283         bcopy(ccb, inccb, sizeof(union ccb));
 2284 
 2285         return(0);
 2286 }
 2287 
 2288 static int
 2289 passerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
 2290 {
 2291         struct cam_periph *periph;
 2292         struct pass_softc *softc;
 2293 
 2294         periph = xpt_path_periph(ccb->ccb_h.path);
 2295         softc = (struct pass_softc *)periph->softc;
 2296         
 2297         return(cam_periph_error(ccb, cam_flags, sense_flags));
 2298 }

Cache object: 628085463caed6ed87c94f2449309b11


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.