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/mmc/mmc_sim.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  * Copyright (c) 2020-2021 Emmanuel Vadot <manu@FreeBSD.org>
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
   10  *    notice, this list of conditions and the following disclaimer in the
   11  *    documentation and/or other materials provided with the distribution.
   12  *
   13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   18  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   20  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   21  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   23  * SUCH DAMAGE.
   24  *
   25  * $FreeBSD$
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include <sys/param.h>
   32 #include <sys/kernel.h>
   33 #include <sys/systm.h>
   34 #include <sys/malloc.h>
   35 #include <sys/mutex.h>
   36 
   37 #include <cam/cam.h>
   38 #include <cam/cam_ccb.h>
   39 #include <cam/cam_debug.h>
   40 #include <cam/cam_sim.h>
   41 #include <cam/cam_xpt_sim.h>
   42 #include <cam/mmc/mmc_sim.h>
   43 
   44 #include "mmc_sim_if.h"
   45 
   46 static void
   47 mmc_cam_default_poll(struct cam_sim *sim)
   48 {
   49         struct mmc_sim *mmc_sim;
   50 
   51         mmc_sim = cam_sim_softc(sim);
   52         MMC_SIM_CAM_POLL(mmc_sim->dev);
   53 }
   54 
   55 static void
   56 mmc_sim_task(void *arg, int pending)
   57 {
   58         struct mmc_sim *mmc_sim;
   59         struct ccb_trans_settings *cts;
   60         int rv;
   61 
   62         mmc_sim = arg;
   63 
   64         if (mmc_sim->ccb == NULL)
   65                 return;
   66 
   67         cts = &mmc_sim->ccb->cts;
   68         switch (mmc_sim->ccb->ccb_h.func_code) {
   69         case XPT_MMC_GET_TRAN_SETTINGS:
   70                 rv = MMC_SIM_GET_TRAN_SETTINGS(mmc_sim->dev, &cts->proto_specific.mmc);
   71                 if (rv != 0)
   72                         mmc_sim->ccb->ccb_h.status = CAM_REQ_INVALID;
   73                 else
   74                         mmc_sim->ccb->ccb_h.status = CAM_REQ_CMP;
   75                 break;
   76         case XPT_MMC_SET_TRAN_SETTINGS:
   77                 rv = MMC_SIM_SET_TRAN_SETTINGS(mmc_sim->dev, &cts->proto_specific.mmc);
   78                 if (rv != 0)
   79                         mmc_sim->ccb->ccb_h.status = CAM_REQ_INVALID;
   80                 else
   81                         mmc_sim->ccb->ccb_h.status = CAM_REQ_CMP;
   82                 break;
   83         default:
   84                 panic("Unsupported ccb func %x\n", mmc_sim->ccb->ccb_h.func_code);
   85                 break;
   86         }
   87 
   88         xpt_done(mmc_sim->ccb);
   89         mmc_sim->ccb = NULL;
   90 }
   91 
   92 
   93 static void
   94 mmc_cam_sim_default_action(struct cam_sim *sim, union ccb *ccb)
   95 {
   96         struct mmc_sim *mmc_sim;
   97         struct ccb_trans_settings_mmc mmc;
   98         int rv;
   99 
  100         mmc_sim = cam_sim_softc(sim);
  101 
  102         mtx_assert(&mmc_sim->mtx, MA_OWNED);
  103 
  104         if (mmc_sim->ccb != NULL) {
  105                 ccb->ccb_h.status = CAM_BUSY;
  106                 xpt_done(ccb);
  107                 return;
  108         }
  109 
  110         switch (ccb->ccb_h.func_code) {
  111         case XPT_PATH_INQ:
  112                 rv = MMC_SIM_GET_TRAN_SETTINGS(mmc_sim->dev, &mmc);
  113                 if (rv != 0) {
  114                         ccb->ccb_h.status = CAM_REQ_INVALID;
  115                 } else {
  116                         mmc_path_inq(&ccb->cpi, "Deglitch Networks",
  117                             sim, mmc.host_max_data);
  118                 }
  119                 break;
  120         case XPT_GET_TRAN_SETTINGS:
  121         {
  122                 struct ccb_trans_settings *cts = &ccb->cts;
  123 
  124                 rv = MMC_SIM_GET_TRAN_SETTINGS(mmc_sim->dev, &cts->proto_specific.mmc);
  125                 if (rv != 0)
  126                         ccb->ccb_h.status = CAM_REQ_INVALID;
  127                 else {
  128                         cts->protocol = PROTO_MMCSD;
  129                         cts->protocol_version = 1;
  130                         cts->transport = XPORT_MMCSD;
  131                         cts->transport_version = 1;
  132                         cts->xport_specific.valid = 0;
  133                         ccb->ccb_h.status = CAM_REQ_CMP;
  134                 }
  135                 break;
  136         }
  137         case XPT_MMC_GET_TRAN_SETTINGS:
  138         {
  139                 ccb->ccb_h.status = CAM_SIM_QUEUED;
  140                 mmc_sim->ccb = ccb;
  141                 taskqueue_enqueue(taskqueue_thread, &mmc_sim->sim_task);
  142                 return;
  143                 /* NOTREACHED */
  144                 break;
  145         }
  146         case XPT_SET_TRAN_SETTINGS:
  147         {
  148                 struct ccb_trans_settings *cts = &ccb->cts;
  149 
  150                 rv = MMC_SIM_SET_TRAN_SETTINGS(mmc_sim->dev, &cts->proto_specific.mmc);
  151                 if (rv != 0)
  152                         ccb->ccb_h.status = CAM_REQ_INVALID;
  153                 else
  154                         ccb->ccb_h.status = CAM_REQ_CMP;
  155                 break;
  156         }
  157         case XPT_MMC_SET_TRAN_SETTINGS:
  158         {
  159                 ccb->ccb_h.status = CAM_SIM_QUEUED;
  160                 mmc_sim->ccb = ccb;
  161                 taskqueue_enqueue(taskqueue_thread, &mmc_sim->sim_task);
  162                 return;
  163                 /* NOTREACHED */
  164                 break;
  165         }
  166         case XPT_RESET_BUS:
  167                 ccb->ccb_h.status = CAM_REQ_CMP;
  168                 break;
  169         case XPT_MMC_IO:
  170         {
  171                 rv = MMC_SIM_CAM_REQUEST(mmc_sim->dev, ccb);
  172                 if (rv != 0)
  173                         ccb->ccb_h.status = CAM_SIM_QUEUED;
  174                 return;
  175                 /* NOTREACHED */
  176                 break;
  177         }
  178         default:
  179                 ccb->ccb_h.status = CAM_REQ_INVALID;
  180                 break;
  181         }
  182         xpt_done(ccb);
  183         return;
  184 }
  185 
  186 int
  187 mmc_cam_sim_alloc(device_t dev, const char *name, struct mmc_sim *mmc_sim)
  188 {
  189         kobjop_desc_t kobj_desc;
  190         kobj_method_t *kobj_method;
  191 
  192         mmc_sim->dev = dev;
  193 
  194         if ((mmc_sim->devq = cam_simq_alloc(1)) == NULL) {
  195                 goto fail;
  196         }
  197 
  198         snprintf(mmc_sim->name, sizeof(mmc_sim->name), "%s_sim", name);
  199         mtx_init(&mmc_sim->mtx, mmc_sim->name, NULL, MTX_DEF);
  200 
  201         /* Provide sim_poll hook only if the device has the poll method. */
  202         kobj_desc = &mmc_sim_cam_poll_desc;
  203         kobj_method = kobj_lookup_method(((kobj_t)dev)->ops->cls, NULL,
  204             kobj_desc);
  205         mmc_sim->sim = cam_sim_alloc(mmc_cam_sim_default_action,
  206             kobj_method == &kobj_desc->deflt ? NULL : mmc_cam_default_poll,
  207             mmc_sim->name, mmc_sim, device_get_unit(dev),
  208             &mmc_sim->mtx, 1, 1, mmc_sim->devq);
  209 
  210         if (mmc_sim->sim == NULL) {
  211                 cam_simq_free(mmc_sim->devq);
  212                 device_printf(dev, "cannot allocate CAM SIM\n");
  213                 goto fail;
  214         }
  215 
  216         mtx_lock(&mmc_sim->mtx);
  217         if (xpt_bus_register(mmc_sim->sim, dev, 0) != 0) {
  218                 device_printf(dev, "cannot register SCSI pass-through bus\n");
  219                 cam_sim_free(mmc_sim->sim, FALSE);
  220                 cam_simq_free(mmc_sim->devq);
  221                 mtx_unlock(&mmc_sim->mtx);
  222                 goto fail;
  223         }
  224 
  225         mtx_unlock(&mmc_sim->mtx);
  226         TASK_INIT(&mmc_sim->sim_task, 0, mmc_sim_task, mmc_sim);
  227 
  228         return (0);
  229 
  230 fail:
  231         mmc_cam_sim_free(mmc_sim);
  232         return (1);
  233 }
  234 
  235 void
  236 mmc_cam_sim_free(struct mmc_sim *mmc_sim)
  237 {
  238 
  239         if (mmc_sim->sim != NULL) {
  240                 mtx_lock(&mmc_sim->mtx);
  241                 xpt_bus_deregister(cam_sim_path(mmc_sim->sim));
  242                 cam_sim_free(mmc_sim->sim, FALSE);
  243                 mtx_unlock(&mmc_sim->mtx);
  244         }
  245 
  246         if (mmc_sim->devq != NULL)
  247                 cam_simq_free(mmc_sim->devq);
  248 }
  249 
  250 void
  251 mmc_cam_sim_discover(struct mmc_sim *mmc_sim)
  252 {
  253 
  254         mmccam_start_discovery(mmc_sim->sim);
  255 }

Cache object: 2bdc912ab4d21c51cbd904695fcd822c


[ 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.