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/usbmisc/ugensa/ugensa.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 /* $OpenBSD: umsm.c,v 1.15 2007/06/14 10:11:16 mbalmer Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 /*
   20  * Generic USB serial driver used for devices where hardware specific
   21  * don't apply or doesn't make sense (for example Qualcomm MSM EVDO, UMTS
   22  * and other similar communication devices).
   23  */
   24 
   25 #include <sys/param.h>
   26 #include <sys/systm.h>
   27 #include <sys/kernel.h>
   28 #include <sys/device.h>
   29 #include <sys/conf.h>
   30 #include <sys/tty.h>
   31 #include <sys/types.h>
   32 #include <sys/bus.h>
   33 #include <sys/module.h>
   34 
   35 #include <bus/usb/usb.h>
   36 #include <bus/usb/usbdi.h>
   37 #include <bus/usb/usbdi_util.h>
   38 #include <bus/usb/usbcdc.h>
   39 #include <dev/usbmisc/ucom/ucomvar.h>
   40 
   41 #ifdef UGENSA_DEBUG
   42 static int      ugensadebug = 1;
   43 #define DPRINTFN(n, x)  do { if (ugensadebug > (n)) kprintf x; } while (0)
   44 #else
   45 #define DPRINTFN(n, x)
   46 #endif
   47 #define DPRINTF(x) DPRINTFN(0, x)
   48 
   49 #define UGENSABUFSZ             4096
   50 #define UGENSA_INTR_INTERVAL    100     /* ms */
   51 
   52 struct ugensa_softc {
   53         struct ucom_softc        sc_ucom;
   54         int                      sc_iface_no;
   55 
   56         /* interrupt ep */
   57         int                      sc_intr_number;
   58         usbd_pipe_handle         sc_intr_pipe;
   59         u_char                  *sc_intr_buf;
   60         int                      sc_isize;
   61 
   62         u_char                   sc_lsr;        /* Local status register */
   63         u_char                   sc_msr;        /* Status register */
   64         u_char                   sc_dtr;        /* Current DTR state */
   65         u_char                   sc_rts;        /* Current RTS state */
   66 };
   67 
   68 static device_probe_t ugensa_match;
   69 static device_attach_t ugensa_attach;
   70 static device_detach_t ugensa_detach;
   71 
   72 static int  ugensa_open(void *, int);
   73 static void ugensa_close(void *, int);
   74 static void ugensa_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
   75 static void ugensa_get_status(void *, int, u_char *, u_char *);
   76 static void ugensa_set(void *, int, int, int);
   77 
   78 static void ugensa_e220_changemode(usbd_device_handle);
   79 
   80 static device_method_t ugensa_methods[] = {
   81         /* Device interface */
   82         DEVMETHOD(device_probe, ugensa_match),
   83         DEVMETHOD(device_attach, ugensa_attach),
   84         DEVMETHOD(device_detach, ugensa_detach),
   85         DEVMETHOD_END
   86 };
   87 
   88 static driver_t ugensa_driver = {
   89         "ucom",
   90         ugensa_methods,
   91         sizeof (struct ugensa_softc)
   92 };
   93 
   94 struct ucom_callback ugensa_callback = {
   95         ugensa_get_status,
   96         ugensa_set,
   97         NULL,
   98         NULL,
   99         ugensa_open,
  100         ugensa_close,
  101         NULL,
  102         NULL
  103 };
  104 
  105 static const struct usb_devno ugensa_devs[] = {
  106         { USB_DEVICE(0x05c6, 0x6000) }, /* Qualcomm HSDPA MSM */
  107         { USB_DEVICE(0x05c6, 0x6613) }, /* Qualcomm HSDPA MSM */
  108         { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera KPC650 */
  109         { USB_DEVICE(0x0f3d, 0x0112) }, /* AirPrime PC5220 */
  110         { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
  111         { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
  112         { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
  113         { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
  114         { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
  115         { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
  116         { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless AirCard 595U */
  117         { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
  118         { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */
  119         { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
  120         { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
  121         { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
  122         { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */
  123         { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8755 */
  124         { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
  125         { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780 */
  126         { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */
  127         { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */
  128         { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */
  129         { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880E */
  130         { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881E */
  131         { USB_DEVICE(0x1199, 0x6855) }, /* Sierra Wireless AirCard 880U */
  132         { USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881U */
  133         { USB_DEVICE(0x12d1, 0x1001) }, /* Huawei Mobile Connect */
  134         { USB_DEVICE(0x12d1, 0x1003) }, /* Huawei Mobile E220 */
  135         { USB_DEVICE(0x12d1, 0x1004) }, /* Huawei Mobile E220 */
  136         { USB_DEVICE(0x1410, 0x1100) }, /* Novatel Wireless Merlin XS620/S640 */
  137         { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin S620/V620 */
  138         { USB_DEVICE(0x1410, 0x1120) }, /* Novatel Wireless Merlin EX720 */
  139         { USB_DEVICE(0x1410, 0x1130) }, /* Novatel Wireless Merlin S720 */
  140         { USB_DEVICE(0x1410, 0x1400) }, /* Novatel Wireless Merlin U730 */
  141         { USB_DEVICE(0x1410, 0x1410) }, /* Novatel Wireless Merlin U740 */
  142         { USB_DEVICE(0x1410, 0x1420) }, /* Novatel Wireless Expedite EU870D */
  143         { USB_DEVICE(0x1410, 0x1430) }, /* Novatel Wireless Merlin XU870 */
  144         { USB_DEVICE(0x1410, 0x2100) }, /* Novatel Wireless Expedite EV620 */
  145         { USB_DEVICE(0x1410, 0x2110) }, /* Novatel Wireless Merlin ES620,
  146                                            Merlin ES720, Ovation U720 */
  147         { USB_DEVICE(0x1410, 0x2130) }, /* Novatel Wireless Merlin ES620 */
  148         { USB_DEVICE(0x1410, 0x2410) }, /* Novatel Wireless Expedite EU740 */
  149         { USB_DEVICE(0x1410, 0x4100) }, /* Novatel Wireless Ovation MC727 */
  150         { USB_DEVICE(0x1410, 0x4400) }, /* Novatel Wireless Ovation MC950D */
  151         { USB_DEVICE(0x16d5, 0x6501) }, /* AnyDATA ADU-E100A/D/H */
  152         { USB_DEVICE(0x413c, 0x8114) }, /* Dell Wireless 5700 */
  153         { USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless 5500 */
  154         { USB_DEVICE(0x413c, 0x8116) }, /* Dell Wireless 5505 */
  155         { USB_DEVICE(0x413c, 0x8117) }, /* Dell Wireless 5700 */
  156         { USB_DEVICE(0x413c, 0x8118) }, /* Dell Wireless 5510 */
  157         { USB_DEVICE(0x413c, 0x8128) }, /* Dell Wireless 5700 */
  158         { USB_DEVICE(0x413c, 0x8136) }, /* Dell Wireless 5520 */
  159         { USB_DEVICE(0x413c, 0x8137) }, /* Dell Wireless 5520 */
  160 };
  161 
  162 DRIVER_MODULE(ugensa, uhub, ugensa_driver, ucom_devclass, usbd_driver_load, NULL);
  163 MODULE_DEPEND(ugensa, usb, 1, 1, 1);
  164 MODULE_DEPEND(ugensa, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER);
  165 MODULE_VERSION(ugensa, 1);
  166 
  167 static int
  168 ugensa_match(device_t self)
  169 {
  170         struct usb_attach_arg *uaa = device_get_ivars(self);
  171 
  172         if (uaa->iface == NULL)
  173                 return UMATCH_NONE;
  174 
  175         /*
  176          * Some devices have mass storage interfaces. What we do with these
  177          * is telling them that we don't need the mass storage and then
  178          * just treat them the way we should.
  179          *
  180          * These devices, most notably Huawei (vendor id 0x12d1) have only
  181          * one interface in mass storage, and after sending them magic,
  182          * they have more than one and are in the correct operating mode.
  183          */
  184 
  185         if (uaa->vendor == 0x12d1) {
  186                 if (uaa->nifaces > 1) {
  187                         /*
  188                          * XXX: we might want to let the normal lookup handle
  189                          * these cases. Right now we just claim we know the
  190                          * device if it isn't in mass storage mode anymore.
  191                          */
  192                         return UMATCH_VENDOR_IFACESUBCLASS;
  193                 } else {
  194                         ugensa_e220_changemode(uaa->device);
  195                         return -1; // avoid umass to reattach (UMATCH_HIGHEST)
  196                 }
  197         }
  198 
  199         return (usb_lookup(ugensa_devs, uaa->vendor, uaa->product) != NULL) ?
  200             UMATCH_VENDOR_IFACESUBCLASS : UMATCH_NONE;
  201 }
  202 
  203 static int
  204 ugensa_attach(device_t self)
  205 {
  206         struct ugensa_softc *sc = device_get_softc(self);
  207         struct usb_attach_arg *uaa = device_get_ivars(self);
  208         struct ucom_softc *ucom;
  209         usb_interface_descriptor_t *id;
  210         usb_endpoint_descriptor_t *ed;
  211         int i;
  212 
  213         ucom = &sc->sc_ucom;
  214         bzero(sc, sizeof (struct ugensa_softc));
  215 
  216         ucom->sc_dev = self;
  217         ucom->sc_udev = uaa->device;
  218         ucom->sc_iface = uaa->iface;
  219 
  220         id = usbd_get_interface_descriptor(ucom->sc_iface);
  221 
  222         sc->sc_iface_no = id->bInterfaceNumber;
  223         ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1;
  224         for (i = 0; i < id->bNumEndpoints; i++) {
  225                 ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i);
  226                 if (ed == NULL) {
  227                         device_printf(ucom->sc_dev, "no endpoint descriptor "
  228                                       "found for %d\n", i);
  229                         goto error;
  230                 }
  231 
  232                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  233                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
  234                         sc->sc_intr_number = ed->bEndpointAddress;
  235                         sc->sc_isize = UGETW(ed->wMaxPacketSize);
  236                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  237                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
  238                         ucom->sc_bulkin_no = ed->bEndpointAddress;
  239                 else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  240                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
  241                         ucom->sc_bulkout_no = ed->bEndpointAddress;
  242         }
  243         if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) {
  244                 device_printf(ucom->sc_dev, "missing endpoint\n");
  245                 goto error;
  246         }
  247 
  248         sc->sc_dtr = sc->sc_rts = -1;
  249 
  250         ucom->sc_parent = sc;
  251         ucom->sc_portno = UCOM_UNK_PORTNO;
  252         ucom->sc_ibufsize = UGENSABUFSZ;
  253         ucom->sc_obufsize = UGENSABUFSZ;
  254         ucom->sc_ibufsizepad = UGENSABUFSZ;
  255         ucom->sc_opkthdrlen = 0;
  256         ucom->sc_callback = &ugensa_callback;
  257 
  258         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, ucom->sc_udev,
  259                            ucom->sc_dev);
  260 
  261         DPRINTF(("%s: in = 0x%x, out = 0x%x\n",
  262                  device_get_nameunit(ucom->sc_dev), ucom->sc_bulkin_no,
  263                  ucom->sc_bulkout_no));
  264 
  265         ucom_attach(&sc->sc_ucom);
  266 
  267         return 0;
  268 
  269 error:
  270         ucom->sc_dying = 1;
  271         return ENXIO;
  272 }
  273 
  274 static int
  275 ugensa_detach(device_t self)
  276 {
  277         struct ugensa_softc *sc = device_get_softc(self);
  278         int rv = 0;
  279 
  280         /* close the interrupt endpoint if that is opened */
  281         if (sc->sc_intr_pipe != NULL) {
  282                 usbd_abort_pipe(sc->sc_intr_pipe);
  283                 usbd_close_pipe(sc->sc_intr_pipe);
  284                 kfree(sc->sc_intr_buf, M_USBDEV);
  285                 sc->sc_intr_pipe = NULL;
  286         }
  287 
  288         DPRINTF(("ugensa_detach: sc=%p\n", sc));
  289         sc->sc_ucom.sc_dying = 1;
  290         rv = ucom_detach(&sc->sc_ucom);
  291         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_ucom.sc_udev,
  292                            sc->sc_ucom.sc_dev);
  293 
  294         return (rv);
  295 }
  296 
  297 #if 0 /* not yet */
  298 int
  299 ugensa_activate(struct device *self, enum devact act)
  300 {
  301         struct ugensa_softc *sc = (struct ugensa_softc *)self;
  302         int rv = 0;
  303 
  304         switch (act) {
  305         case DVACT_ACTIVATE:
  306                 break;
  307 
  308         case DVACT_DEACTIVATE:
  309                 if (sc->sc_subdev != NULL)
  310                         rv = config_deactivate(sc->sc_subdev);
  311                 sc->sc_dying = 1;
  312                 break;
  313         }
  314         return (rv);
  315 }
  316 #endif
  317 
  318 static int
  319 ugensa_open(void *addr, int portno)
  320 {
  321         struct ugensa_softc *sc = addr;
  322         int err;
  323 
  324         if (sc->sc_ucom.sc_dying)
  325                 return (ENXIO);
  326 
  327         if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
  328                 sc->sc_intr_buf = kmalloc(sc->sc_isize, M_USBDEV, M_WAITOK);
  329                 err = usbd_open_pipe_intr(sc->sc_ucom.sc_iface,
  330                     sc->sc_intr_number, USBD_SHORT_XFER_OK, &sc->sc_intr_pipe,
  331                     sc, sc->sc_intr_buf, sc->sc_isize, ugensa_intr,
  332                     UGENSA_INTR_INTERVAL);
  333                 if (err) {
  334                         device_printf(sc->sc_ucom.sc_dev,
  335                             "cannot open interrupt pipe (addr %d)\n",
  336                             sc->sc_intr_number);
  337                         return (EIO);
  338                 }
  339         }
  340 
  341         return (0);
  342 }
  343 
  344 static void
  345 ugensa_close(void *addr, int portno)
  346 {
  347         struct ugensa_softc *sc = addr;
  348         int err;
  349 
  350         if (sc->sc_ucom.sc_dying)
  351                 return;
  352 
  353         if (sc->sc_intr_pipe != NULL) {
  354                 err = usbd_abort_pipe(sc->sc_intr_pipe);
  355                 if (err)
  356                         device_printf(sc->sc_ucom.sc_dev,
  357                             "abort interrupt pipe failed: %s\n",
  358                             usbd_errstr(err));
  359                 err = usbd_close_pipe(sc->sc_intr_pipe);
  360                 if (err)
  361                         device_printf(sc->sc_ucom.sc_dev,
  362                             "close interrupt pipe failed: %s\n",
  363                             usbd_errstr(err));
  364                 kfree(sc->sc_intr_buf, M_USBDEV);
  365                 sc->sc_intr_pipe = NULL;
  366         }
  367 
  368 }
  369 
  370 static void
  371 ugensa_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
  372 {
  373         struct ugensa_softc *sc = priv;
  374         usb_cdc_notification_t *buf;
  375         u_char mstatus;
  376 
  377         buf = (usb_cdc_notification_t *)sc->sc_intr_buf;
  378         if (sc->sc_ucom.sc_dying)
  379                 return;
  380 
  381         if (status != USBD_NORMAL_COMPLETION) {
  382                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
  383                         return;
  384 
  385                 device_printf(sc->sc_ucom.sc_dev,
  386                     "ugensa_intr: abnormal status: %s\n", usbd_errstr(status));
  387                 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
  388                 return;
  389         }
  390 
  391         if (buf->bmRequestType != UCDC_NOTIFICATION) {
  392                 DPRINTF(("%s: umsm_intr: unknown message type(0x%02x)\n",
  393                     sc->sc_dev.dv_xname, buf->bmRequestType));
  394                 return;
  395         }
  396 
  397         if (buf->bNotification == UCDC_N_SERIAL_STATE) {
  398                 /* invalid message length, discard it */
  399                 if (UGETW(buf->wLength) != 2)
  400                         return;
  401                 /* XXX: sc_lsr is always 0 */
  402                 sc->sc_lsr = sc->sc_msr = 0;
  403                 mstatus = buf->data[0];
  404                 if (ISSET(mstatus, UCDC_N_SERIAL_RI))
  405                         sc->sc_msr |= UMSR_RI;
  406                 if (ISSET(mstatus, UCDC_N_SERIAL_DSR))
  407                         sc->sc_msr |= UMSR_DSR;
  408                 if (ISSET(mstatus, UCDC_N_SERIAL_DCD))
  409                         sc->sc_msr |= UMSR_DCD;
  410         } else if (buf->bNotification != UCDC_N_CONNECTION_SPEED_CHANGE) {
  411                 DPRINTF(("%s: umsm_intr: unknown notify message (0x%02x)\n",
  412                     sc->sc_dev.dv_xname, buf->bNotification));
  413                 return;
  414         }
  415 
  416         ucom_status_change(&sc->sc_ucom);
  417 }
  418 
  419 static void
  420 ugensa_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
  421 {
  422         struct ugensa_softc *sc = addr;
  423 
  424         if (lsr != NULL)
  425                 *lsr = sc->sc_lsr;
  426         if (msr != NULL)
  427                 *msr = sc->sc_msr;
  428 }
  429 
  430 static void
  431 ugensa_set(void *addr, int portno, int reg, int onoff)
  432 {
  433         struct ugensa_softc *sc = addr;
  434         usb_device_request_t req;
  435         int ls;
  436 
  437         switch (reg) {
  438         case UCOM_SET_DTR:
  439                 if (sc->sc_dtr == onoff)
  440                         return;
  441                 sc->sc_dtr = onoff;
  442                 break;
  443         case UCOM_SET_RTS:
  444                 if (sc->sc_rts == onoff)
  445                         return;
  446                 sc->sc_rts = onoff;
  447                 break;
  448         default:
  449                 return;
  450         }
  451 
  452         /* build an usb request */
  453         ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) |
  454             (sc->sc_rts ? UCDC_LINE_RTS : 0);
  455         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  456         req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
  457         USETW(req.wValue, ls);
  458         USETW(req.wIndex, sc->sc_iface_no);
  459         USETW(req.wLength, 0);
  460 
  461         (void)usbd_do_request(sc->sc_ucom.sc_udev, &req, 0);
  462 }
  463 
  464 static void
  465 ugensa_e220_changemode(usbd_device_handle dev)
  466 {
  467         usb_device_request_t req;
  468 
  469         req.bmRequestType = UT_WRITE_DEVICE;
  470         req.bRequest = UR_SET_FEATURE;
  471         USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
  472         USETW(req.wIndex, 0x2);
  473         USETW(req.wLength, 0);
  474 
  475         usbd_do_request(dev, &req, 0);
  476 }
  477 

Cache object: 51c745f8ef0ad4885ccfa3ae183b469b


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