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/dev/usb/storage/urio.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) 2000 Iwasa Kazmi
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions, and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson.
   29  * This code includes software developed by the NetBSD Foundation, Inc. and
   30  * its contributors.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 /*
   37  * 2000/3/24  added NetBSD/OpenBSD support (from Alex Nemirovsky)
   38  * 2000/3/07  use two bulk-pipe handles for read and write (Dirk)
   39  * 2000/3/06  change major number(143), and copyright header
   40  *            some fix for 4.0 (Dirk)
   41  * 2000/3/05  codes for FreeBSD 4.x - CURRENT (Thanks to Dirk-Willem van Gulik)
   42  * 2000/3/01  remove retry code from urioioctl()
   43  *            change method of bulk transfer (no interrupt)
   44  * 2000/2/28  small fixes for new rio_usb.h
   45  * 2000/2/24  first version.
   46  */
   47 
   48 #include <sys/stdint.h>
   49 #include <sys/stddef.h>
   50 #include <sys/param.h>
   51 #include <sys/queue.h>
   52 #include <sys/types.h>
   53 #include <sys/systm.h>
   54 #include <sys/kernel.h>
   55 #include <sys/bus.h>
   56 #include <sys/module.h>
   57 #include <sys/lock.h>
   58 #include <sys/mutex.h>
   59 #include <sys/condvar.h>
   60 #include <sys/sysctl.h>
   61 #include <sys/sx.h>
   62 #include <sys/unistd.h>
   63 #include <sys/callout.h>
   64 #include <sys/malloc.h>
   65 #include <sys/priv.h>
   66 #include <sys/conf.h>
   67 #include <sys/fcntl.h>
   68 
   69 #include <dev/usb/usb.h>
   70 #include <dev/usb/usbdi.h>
   71 #include "usbdevs.h"
   72 
   73 #include <dev/usb/usb_ioctl.h>
   74 #include <dev/usb/usb_generic.h>
   75 
   76 #define USB_DEBUG_VAR urio_debug
   77 #include <dev/usb/usb_debug.h>
   78 
   79 #include <dev/usb/storage/rio500_usb.h>
   80 
   81 #ifdef USB_DEBUG
   82 static int urio_debug = 0;
   83 
   84 static SYSCTL_NODE(_hw_usb, OID_AUTO, urio, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
   85     "USB urio");
   86 SYSCTL_INT(_hw_usb_urio, OID_AUTO, debug, CTLFLAG_RWTUN,
   87     &urio_debug, 0, "urio debug level");
   88 #endif
   89 
   90 #define URIO_T_WR     0
   91 #define URIO_T_RD     1
   92 #define URIO_T_WR_CS  2
   93 #define URIO_T_RD_CS  3
   94 #define URIO_T_MAX    4
   95 
   96 #define URIO_BSIZE      (1<<12)         /* bytes */
   97 #define URIO_IFQ_MAXLEN      2          /* units */
   98 
   99 struct urio_softc {
  100         struct usb_fifo_sc sc_fifo;
  101         struct mtx sc_mtx;
  102 
  103         struct usb_device *sc_udev;
  104         struct usb_xfer *sc_xfer[URIO_T_MAX];
  105 
  106         uint8_t sc_flags;
  107 #define URIO_FLAG_READ_STALL    0x01    /* read transfer stalled */
  108 #define URIO_FLAG_WRITE_STALL   0x02    /* write transfer stalled */
  109 
  110         uint8_t sc_name[16];
  111 };
  112 
  113 /* prototypes */
  114 
  115 static device_probe_t urio_probe;
  116 static device_attach_t urio_attach;
  117 static device_detach_t urio_detach;
  118 
  119 static usb_callback_t urio_write_callback;
  120 static usb_callback_t urio_write_clear_stall_callback;
  121 static usb_callback_t urio_read_callback;
  122 static usb_callback_t urio_read_clear_stall_callback;
  123 
  124 static usb_fifo_close_t urio_close;
  125 static usb_fifo_cmd_t urio_start_read;
  126 static usb_fifo_cmd_t urio_start_write;
  127 static usb_fifo_cmd_t urio_stop_read;
  128 static usb_fifo_cmd_t urio_stop_write;
  129 static usb_fifo_ioctl_t urio_ioctl;
  130 static usb_fifo_open_t urio_open;
  131 
  132 static struct usb_fifo_methods urio_fifo_methods = {
  133         .f_close = &urio_close,
  134         .f_ioctl = &urio_ioctl,
  135         .f_open = &urio_open,
  136         .f_start_read = &urio_start_read,
  137         .f_start_write = &urio_start_write,
  138         .f_stop_read = &urio_stop_read,
  139         .f_stop_write = &urio_stop_write,
  140         .basename[0] = "urio",
  141 };
  142 
  143 static const struct usb_config urio_config[URIO_T_MAX] = {
  144         [URIO_T_WR] = {
  145                 .type = UE_BULK,
  146                 .endpoint = UE_ADDR_ANY,
  147                 .direction = UE_DIR_OUT,
  148                 .bufsize = URIO_BSIZE,
  149                 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1,},
  150                 .callback = &urio_write_callback,
  151         },
  152 
  153         [URIO_T_RD] = {
  154                 .type = UE_BULK,
  155                 .endpoint = UE_ADDR_ANY,
  156                 .direction = UE_DIR_IN,
  157                 .bufsize = URIO_BSIZE,
  158                 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,},
  159                 .callback = &urio_read_callback,
  160         },
  161 
  162         [URIO_T_WR_CS] = {
  163                 .type = UE_CONTROL,
  164                 .endpoint = 0x00,       /* Control pipe */
  165                 .direction = UE_DIR_ANY,
  166                 .bufsize = sizeof(struct usb_device_request),
  167                 .callback = &urio_write_clear_stall_callback,
  168                 .timeout = 1000,        /* 1 second */
  169                 .interval = 50, /* 50ms */
  170         },
  171 
  172         [URIO_T_RD_CS] = {
  173                 .type = UE_CONTROL,
  174                 .endpoint = 0x00,       /* Control pipe */
  175                 .direction = UE_DIR_ANY,
  176                 .bufsize = sizeof(struct usb_device_request),
  177                 .callback = &urio_read_clear_stall_callback,
  178                 .timeout = 1000,        /* 1 second */
  179                 .interval = 50, /* 50ms */
  180         },
  181 };
  182 
  183 static device_method_t urio_methods[] = {
  184         /* Device interface */
  185         DEVMETHOD(device_probe, urio_probe),
  186         DEVMETHOD(device_attach, urio_attach),
  187         DEVMETHOD(device_detach, urio_detach),
  188 
  189         DEVMETHOD_END
  190 };
  191 
  192 static driver_t urio_driver = {
  193         .name = "urio",
  194         .methods = urio_methods,
  195         .size = sizeof(struct urio_softc),
  196 };
  197 
  198 static const STRUCT_USB_HOST_ID urio_devs[] = {
  199         {USB_VPI(USB_VENDOR_DIAMOND, USB_PRODUCT_DIAMOND_RIO500USB, 0)},
  200         {USB_VPI(USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_RIO600USB, 0)},
  201         {USB_VPI(USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_RIO800USB, 0)},
  202 };
  203 
  204 DRIVER_MODULE(urio, uhub, urio_driver, NULL, NULL);
  205 MODULE_DEPEND(urio, usb, 1, 1, 1);
  206 MODULE_VERSION(urio, 1);
  207 USB_PNP_HOST_INFO(urio_devs);
  208 
  209 static int
  210 urio_probe(device_t dev)
  211 {
  212         struct usb_attach_arg *uaa = device_get_ivars(dev);
  213 
  214         if (uaa->usb_mode != USB_MODE_HOST)
  215                 return (ENXIO);
  216         if (uaa->info.bConfigIndex != 0)
  217                 return (ENXIO);
  218         if (uaa->info.bIfaceIndex != 0)
  219                 return (ENXIO);
  220 
  221         return (usbd_lookup_id_by_uaa(urio_devs, sizeof(urio_devs), uaa));
  222 }
  223 
  224 static int
  225 urio_attach(device_t dev)
  226 {
  227         struct usb_attach_arg *uaa = device_get_ivars(dev);
  228         struct urio_softc *sc = device_get_softc(dev);
  229         int error;
  230 
  231         device_set_usb_desc(dev);
  232 
  233         sc->sc_udev = uaa->device;
  234 
  235         mtx_init(&sc->sc_mtx, "urio lock", NULL, MTX_DEF | MTX_RECURSE);
  236 
  237         snprintf(sc->sc_name, sizeof(sc->sc_name),
  238             "%s", device_get_nameunit(dev));
  239 
  240         error = usbd_transfer_setup(uaa->device,
  241             &uaa->info.bIfaceIndex, sc->sc_xfer,
  242             urio_config, URIO_T_MAX, sc, &sc->sc_mtx);
  243 
  244         if (error) {
  245                 DPRINTF("error=%s\n", usbd_errstr(error));
  246                 goto detach;
  247         }
  248 
  249         error = usb_fifo_attach(uaa->device, sc, &sc->sc_mtx,
  250             &urio_fifo_methods, &sc->sc_fifo,
  251             device_get_unit(dev), -1, uaa->info.bIfaceIndex,
  252             UID_ROOT, GID_OPERATOR, 0644);
  253         if (error) {
  254                 goto detach;
  255         }
  256         return (0);                     /* success */
  257 
  258 detach:
  259         urio_detach(dev);
  260         return (ENOMEM);                /* failure */
  261 }
  262 
  263 static void
  264 urio_write_callback(struct usb_xfer *xfer, usb_error_t error)
  265 {
  266         struct urio_softc *sc = usbd_xfer_softc(xfer);
  267         struct usb_fifo *f = sc->sc_fifo.fp[USB_FIFO_TX];
  268         struct usb_page_cache *pc;
  269         uint32_t actlen;
  270 
  271         switch (USB_GET_STATE(xfer)) {
  272         case USB_ST_TRANSFERRED:
  273         case USB_ST_SETUP:
  274                 if (sc->sc_flags & URIO_FLAG_WRITE_STALL) {
  275                         usbd_transfer_start(sc->sc_xfer[URIO_T_WR_CS]);
  276                         return;
  277                 }
  278                 pc = usbd_xfer_get_frame(xfer, 0);
  279                 if (usb_fifo_get_data(f, pc, 0,
  280                     usbd_xfer_max_len(xfer), &actlen, 0)) {
  281                         usbd_xfer_set_frame_len(xfer, 0, actlen);
  282                         usbd_transfer_submit(xfer);
  283                 }
  284                 return;
  285 
  286         default:                        /* Error */
  287                 if (error != USB_ERR_CANCELLED) {
  288                         /* try to clear stall first */
  289                         sc->sc_flags |= URIO_FLAG_WRITE_STALL;
  290                         usbd_transfer_start(sc->sc_xfer[URIO_T_WR_CS]);
  291                 }
  292                 return;
  293         }
  294 }
  295 
  296 static void
  297 urio_write_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error)
  298 {
  299         struct urio_softc *sc = usbd_xfer_softc(xfer);
  300         struct usb_xfer *xfer_other = sc->sc_xfer[URIO_T_WR];
  301 
  302         if (usbd_clear_stall_callback(xfer, xfer_other)) {
  303                 DPRINTF("stall cleared\n");
  304                 sc->sc_flags &= ~URIO_FLAG_WRITE_STALL;
  305                 usbd_transfer_start(xfer_other);
  306         }
  307 }
  308 
  309 static void
  310 urio_read_callback(struct usb_xfer *xfer, usb_error_t error)
  311 {
  312         struct urio_softc *sc = usbd_xfer_softc(xfer);
  313         struct usb_fifo *f = sc->sc_fifo.fp[USB_FIFO_RX];
  314         struct usb_page_cache *pc;
  315         int actlen;
  316 
  317         usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
  318 
  319         switch (USB_GET_STATE(xfer)) {
  320         case USB_ST_TRANSFERRED:
  321                 pc = usbd_xfer_get_frame(xfer, 0);
  322                 usb_fifo_put_data(f, pc, 0, actlen, 1);
  323 
  324         case USB_ST_SETUP:
  325                 if (sc->sc_flags & URIO_FLAG_READ_STALL) {
  326                         usbd_transfer_start(sc->sc_xfer[URIO_T_RD_CS]);
  327                         return;
  328                 }
  329                 if (usb_fifo_put_bytes_max(f) != 0) {
  330                         usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
  331                         usbd_transfer_submit(xfer);
  332                 }
  333                 return;
  334 
  335         default:                        /* Error */
  336                 if (error != USB_ERR_CANCELLED) {
  337                         /* try to clear stall first */
  338                         sc->sc_flags |= URIO_FLAG_READ_STALL;
  339                         usbd_transfer_start(sc->sc_xfer[URIO_T_RD_CS]);
  340                 }
  341                 return;
  342         }
  343 }
  344 
  345 static void
  346 urio_read_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error)
  347 {
  348         struct urio_softc *sc = usbd_xfer_softc(xfer);
  349         struct usb_xfer *xfer_other = sc->sc_xfer[URIO_T_RD];
  350 
  351         if (usbd_clear_stall_callback(xfer, xfer_other)) {
  352                 DPRINTF("stall cleared\n");
  353                 sc->sc_flags &= ~URIO_FLAG_READ_STALL;
  354                 usbd_transfer_start(xfer_other);
  355         }
  356 }
  357 
  358 static void
  359 urio_start_read(struct usb_fifo *fifo)
  360 {
  361         struct urio_softc *sc = usb_fifo_softc(fifo);
  362 
  363         usbd_transfer_start(sc->sc_xfer[URIO_T_RD]);
  364 }
  365 
  366 static void
  367 urio_stop_read(struct usb_fifo *fifo)
  368 {
  369         struct urio_softc *sc = usb_fifo_softc(fifo);
  370 
  371         usbd_transfer_stop(sc->sc_xfer[URIO_T_RD_CS]);
  372         usbd_transfer_stop(sc->sc_xfer[URIO_T_RD]);
  373 }
  374 
  375 static void
  376 urio_start_write(struct usb_fifo *fifo)
  377 {
  378         struct urio_softc *sc = usb_fifo_softc(fifo);
  379 
  380         usbd_transfer_start(sc->sc_xfer[URIO_T_WR]);
  381 }
  382 
  383 static void
  384 urio_stop_write(struct usb_fifo *fifo)
  385 {
  386         struct urio_softc *sc = usb_fifo_softc(fifo);
  387 
  388         usbd_transfer_stop(sc->sc_xfer[URIO_T_WR_CS]);
  389         usbd_transfer_stop(sc->sc_xfer[URIO_T_WR]);
  390 }
  391 
  392 static int
  393 urio_open(struct usb_fifo *fifo, int fflags)
  394 {
  395         struct urio_softc *sc = usb_fifo_softc(fifo);
  396 
  397         if (fflags & FREAD) {
  398                 /* clear stall first */
  399                 mtx_lock(&sc->sc_mtx);
  400                 sc->sc_flags |= URIO_FLAG_READ_STALL;
  401                 mtx_unlock(&sc->sc_mtx);
  402 
  403                 if (usb_fifo_alloc_buffer(fifo,
  404                     usbd_xfer_max_len(sc->sc_xfer[URIO_T_RD]),
  405                     URIO_IFQ_MAXLEN)) {
  406                         return (ENOMEM);
  407                 }
  408         }
  409         if (fflags & FWRITE) {
  410                 /* clear stall first */
  411                 sc->sc_flags |= URIO_FLAG_WRITE_STALL;
  412 
  413                 if (usb_fifo_alloc_buffer(fifo,
  414                     usbd_xfer_max_len(sc->sc_xfer[URIO_T_WR]),
  415                     URIO_IFQ_MAXLEN)) {
  416                         return (ENOMEM);
  417                 }
  418         }
  419         return (0);                     /* success */
  420 }
  421 
  422 static void
  423 urio_close(struct usb_fifo *fifo, int fflags)
  424 {
  425         if (fflags & (FREAD | FWRITE)) {
  426                 usb_fifo_free_buffer(fifo);
  427         }
  428 }
  429 
  430 static int
  431 urio_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr,
  432     int fflags)
  433 {
  434         struct usb_ctl_request ur;
  435         struct RioCommand *rio_cmd;
  436         int error;
  437 
  438         switch (cmd) {
  439         case RIO_RECV_COMMAND:
  440                 if (!(fflags & FWRITE)) {
  441                         error = EPERM;
  442                         goto done;
  443                 }
  444                 memset(&ur, 0, sizeof(ur));
  445                 rio_cmd = addr;
  446                 ur.ucr_request.bmRequestType =
  447                     rio_cmd->requesttype | UT_READ_VENDOR_DEVICE;
  448                 break;
  449 
  450         case RIO_SEND_COMMAND:
  451                 if (!(fflags & FWRITE)) {
  452                         error = EPERM;
  453                         goto done;
  454                 }
  455                 memset(&ur, 0, sizeof(ur));
  456                 rio_cmd = addr;
  457                 ur.ucr_request.bmRequestType =
  458                     rio_cmd->requesttype | UT_WRITE_VENDOR_DEVICE;
  459                 break;
  460 
  461         default:
  462                 error = EINVAL;
  463                 goto done;
  464         }
  465 
  466         DPRINTFN(2, "Sending command\n");
  467 
  468         /* Send rio control message */
  469         ur.ucr_request.bRequest = rio_cmd->request;
  470         USETW(ur.ucr_request.wValue, rio_cmd->value);
  471         USETW(ur.ucr_request.wIndex, rio_cmd->index);
  472         USETW(ur.ucr_request.wLength, rio_cmd->length);
  473         ur.ucr_data = rio_cmd->buffer;
  474 
  475         /* reuse generic USB code */
  476         error = ugen_do_request(fifo, &ur);
  477 
  478 done:
  479         return (error);
  480 }
  481 
  482 static int
  483 urio_detach(device_t dev)
  484 {
  485         struct urio_softc *sc = device_get_softc(dev);
  486 
  487         DPRINTF("\n");
  488 
  489         usb_fifo_detach(&sc->sc_fifo);
  490 
  491         usbd_transfer_unsetup(sc->sc_xfer, URIO_T_MAX);
  492 
  493         mtx_destroy(&sc->sc_mtx);
  494 
  495         return (0);
  496 }

Cache object: b9d885a04d465e912565cf2531f45a8e


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