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/mips/cavium/usb/octusb.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 #include <sys/cdefs.h>
    2 __FBSDID("$FreeBSD$");
    3 
    4 /*-
    5  * Copyright (c) 2010 Hans Petter Selasky. 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
   20  * FOR 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 
   29 /*
   30  * This file contains the driver for Octeon Executive Library USB
   31  * Controller driver API.
   32  */
   33 
   34 /* TODO: The root HUB port callback is not yet implemented. */
   35 
   36 #include <sys/stdint.h>
   37 #include <sys/stddef.h>
   38 #include <sys/param.h>
   39 #include <sys/queue.h>
   40 #include <sys/types.h>
   41 #include <sys/systm.h>
   42 #include <sys/kernel.h>
   43 #include <sys/bus.h>
   44 #include <sys/module.h>
   45 #include <sys/lock.h>
   46 #include <sys/mutex.h>
   47 #include <sys/condvar.h>
   48 #include <sys/sysctl.h>
   49 #include <sys/sx.h>
   50 #include <sys/unistd.h>
   51 #include <sys/callout.h>
   52 #include <sys/malloc.h>
   53 #include <sys/priv.h>
   54 
   55 #include <dev/usb/usb.h>
   56 #include <dev/usb/usbdi.h>
   57 
   58 #define USB_DEBUG_VAR octusbdebug
   59 
   60 #include <dev/usb/usb_core.h>
   61 #include <dev/usb/usb_debug.h>
   62 #include <dev/usb/usb_busdma.h>
   63 #include <dev/usb/usb_process.h>
   64 #include <dev/usb/usb_transfer.h>
   65 #include <dev/usb/usb_device.h>
   66 #include <dev/usb/usb_hub.h>
   67 #include <dev/usb/usb_util.h>
   68 
   69 #include <dev/usb/usb_controller.h>
   70 #include <dev/usb/usb_bus.h>
   71 
   72 #include <contrib/octeon-sdk/cvmx.h>
   73 #include <contrib/octeon-sdk/cvmx-usb.h>
   74 
   75 #include <mips/cavium/usb/octusb.h>
   76 
   77 #define OCTUSB_BUS2SC(bus) \
   78    ((struct octusb_softc *)(((uint8_t *)(bus)) - \
   79     ((uint8_t *)&(((struct octusb_softc *)0)->sc_bus))))
   80 
   81 #ifdef USB_DEBUG
   82 static int octusbdebug = 0;
   83 
   84 static SYSCTL_NODE(_hw_usb, OID_AUTO, octusb, CTLFLAG_RW, 0, "OCTUSB");
   85 SYSCTL_INT(_hw_usb_octusb, OID_AUTO, debug, CTLFLAG_RW,
   86     &octusbdebug, 0, "OCTUSB debug level");
   87 
   88 TUNABLE_INT("hw.usb.octusb.debug", &octusbdebug);
   89 
   90 #endif
   91 
   92 struct octusb_std_temp {
   93         octusb_cmd_t *func;
   94         struct octusb_td *td;
   95         struct octusb_td *td_next;
   96         struct usb_page_cache *pc;
   97         uint32_t offset;
   98         uint32_t len;
   99         uint8_t short_pkt;
  100         uint8_t setup_alt_next;
  101 };
  102 
  103 extern struct usb_bus_methods octusb_bus_methods;
  104 extern struct usb_pipe_methods octusb_device_bulk_methods;
  105 extern struct usb_pipe_methods octusb_device_ctrl_methods;
  106 extern struct usb_pipe_methods octusb_device_intr_methods;
  107 extern struct usb_pipe_methods octusb_device_isoc_methods;
  108 
  109 static void octusb_standard_done(struct usb_xfer *);
  110 static void octusb_device_done(struct usb_xfer *, usb_error_t);
  111 static void octusb_timeout(void *);
  112 static void octusb_do_poll(struct usb_bus *);
  113 
  114 static cvmx_usb_speed_t
  115 octusb_convert_speed(enum usb_dev_speed speed)
  116 {
  117         ;                               /* indent fix */
  118         switch (speed) {
  119         case USB_SPEED_HIGH:
  120                 return (CVMX_USB_SPEED_HIGH);
  121         case USB_SPEED_FULL:
  122                 return (CVMX_USB_SPEED_FULL);
  123         default:
  124                 return (CVMX_USB_SPEED_LOW);
  125         }
  126 }
  127 
  128 static cvmx_usb_transfer_t
  129 octusb_convert_ep_type(uint8_t ep_type)
  130 {
  131         ;                               /* indent fix */
  132         switch (ep_type & UE_XFERTYPE) {
  133         case UE_CONTROL:
  134                 return (CVMX_USB_TRANSFER_CONTROL);
  135         case UE_INTERRUPT:
  136                 return (CVMX_USB_TRANSFER_INTERRUPT);
  137         case UE_ISOCHRONOUS:
  138                 return (CVMX_USB_TRANSFER_ISOCHRONOUS);
  139         case UE_BULK:
  140                 return (CVMX_USB_TRANSFER_BULK);
  141         default:
  142                 return (0);             /* should not happen */
  143         }
  144 }
  145 
  146 static uint8_t
  147 octusb_host_alloc_endpoint(struct octusb_td *td)
  148 {
  149         struct octusb_softc *sc;
  150         int ep_handle;
  151 
  152         if (td->qh->fixup_pending)
  153                 return (1);             /* busy */
  154 
  155         if (td->qh->ep_allocated)
  156                 return (0);             /* success */
  157 
  158         /* get softc */
  159         sc = td->qh->sc;
  160 
  161         ep_handle = cvmx_usb_open_pipe(
  162             &sc->sc_port[td->qh->port_index].state,
  163             0,
  164             td->qh->dev_addr,
  165             td->qh->ep_num,
  166             octusb_convert_speed(td->qh->dev_speed),
  167             td->qh->max_packet_size,
  168             octusb_convert_ep_type(td->qh->ep_type),
  169             (td->qh->ep_num & UE_DIR_IN) ? CVMX_USB_DIRECTION_IN :
  170             CVMX_USB_DIRECTION_OUT,
  171             td->qh->ep_interval,
  172             td->qh->ep_mult,
  173             td->qh->hs_hub_addr,
  174             td->qh->hs_hub_port);
  175 
  176         if (ep_handle < 0)
  177                 return (1);             /* busy */
  178 
  179         cvmx_usb_set_toggle(
  180             &sc->sc_port[td->qh->port_index].state,
  181             ep_handle, td->qh->ep_toggle_next);
  182 
  183         td->qh->fixup_handle = -1;
  184         td->qh->fixup_complete = 0;
  185         td->qh->fixup_len = 0;
  186         td->qh->fixup_off = 0;
  187         td->qh->fixup_pending = 0;
  188         td->qh->fixup_actlen = 0;
  189 
  190         td->qh->ep_handle = ep_handle;
  191         td->qh->ep_allocated = 1;
  192 
  193         return (0);                     /* success */
  194 }
  195 
  196 static void
  197 octusb_host_free_endpoint(struct octusb_td *td)
  198 {
  199         struct octusb_softc *sc;
  200 
  201         if (td->qh->ep_allocated == 0)
  202                 return;
  203 
  204         /* get softc */
  205         sc = td->qh->sc;
  206 
  207         if (td->qh->fixup_handle >= 0) {
  208                 /* cancel, if any */
  209                 cvmx_usb_cancel(&sc->sc_port[td->qh->port_index].state,
  210                     td->qh->ep_handle, td->qh->fixup_handle);
  211         }
  212         cvmx_usb_close_pipe(&sc->sc_port[td->qh->port_index].state, td->qh->ep_handle);
  213 
  214         td->qh->ep_allocated = 0;
  215 }
  216 
  217 static void
  218 octusb_complete_cb(cvmx_usb_state_t *state,
  219     cvmx_usb_callback_t reason,
  220     cvmx_usb_complete_t status,
  221     int pipe_handle, int submit_handle,
  222     int bytes_transferred, void *user_data)
  223 {
  224         struct octusb_td *td;
  225 
  226         if (reason != CVMX_USB_CALLBACK_TRANSFER_COMPLETE)
  227                 return;
  228 
  229         td = user_data;
  230 
  231         td->qh->fixup_complete = 1;
  232         td->qh->fixup_pending = 0;
  233         td->qh->fixup_actlen = bytes_transferred;
  234         td->qh->fixup_handle = -1;
  235 
  236         switch (status) {
  237         case CVMX_USB_COMPLETE_SUCCESS:
  238         case CVMX_USB_COMPLETE_SHORT:
  239                 td->error_any = 0;
  240                 td->error_stall = 0;
  241                 break;
  242         case CVMX_USB_COMPLETE_STALL:
  243                 td->error_stall = 1;
  244                 td->error_any = 1;
  245                 break;
  246         default:
  247                 td->error_any = 1;
  248                 break;
  249         }
  250 }
  251 
  252 static uint8_t
  253 octusb_host_control_header_tx(struct octusb_td *td)
  254 {
  255         int status;
  256 
  257         /* allocate endpoint and check pending */
  258         if (octusb_host_alloc_endpoint(td))
  259                 return (1);             /* busy */
  260 
  261         /* check error */
  262         if (td->error_any)
  263                 return (0);             /* done */
  264 
  265         if (td->qh->fixup_complete != 0) {
  266                 /* clear complete flag */
  267                 td->qh->fixup_complete = 0;
  268 
  269                 /* flush data */
  270                 usb_pc_cpu_invalidate(td->qh->fixup_pc);
  271                 return (0);             /* done */
  272         }
  273         /* verify length */
  274         if (td->remainder != 8) {
  275                 td->error_any = 1;
  276                 return (0);             /* done */
  277         }
  278         usbd_copy_out(td->pc, td->offset, td->qh->fixup_buf, 8);
  279 
  280         /* update offset and remainder */
  281         td->offset += 8;
  282         td->remainder -= 8;
  283 
  284         /* setup data length and offset */
  285         td->qh->fixup_len = UGETW(td->qh->fixup_buf + 6);
  286         td->qh->fixup_off = 0;
  287 
  288         if (td->qh->fixup_len > (OCTUSB_MAX_FIXUP - 8)) {
  289                 td->error_any = 1;
  290                 return (0);             /* done */
  291         }
  292         /* do control IN request */
  293         if (td->qh->fixup_buf[0] & UE_DIR_IN) {
  294 
  295                 struct octusb_softc *sc;
  296 
  297                 /* get softc */
  298                 sc = td->qh->sc;
  299 
  300                 /* flush data */
  301                 usb_pc_cpu_flush(td->qh->fixup_pc);
  302 
  303                 status = cvmx_usb_submit_control(
  304                     &sc->sc_port[td->qh->port_index].state,
  305                     td->qh->ep_handle, td->qh->fixup_phys,
  306                     td->qh->fixup_phys + 8, td->qh->fixup_len,
  307                     &octusb_complete_cb, td);
  308                 /* check status */
  309                 if (status < 0) {
  310                         td->error_any = 1;
  311                         return (0);     /* done */
  312                 }
  313                 td->qh->fixup_handle = status;
  314                 td->qh->fixup_pending = 1;
  315                 td->qh->fixup_complete = 0;
  316 
  317                 return (1);             /* busy */
  318         }
  319         return (0);                     /* done */
  320 }
  321 
  322 static uint8_t
  323 octusb_host_control_data_tx(struct octusb_td *td)
  324 {
  325         uint32_t rem;
  326 
  327         /* allocate endpoint and check pending */
  328         if (octusb_host_alloc_endpoint(td))
  329                 return (1);             /* busy */
  330 
  331         /* check error */
  332         if (td->error_any)
  333                 return (0);             /* done */
  334 
  335         rem = td->qh->fixup_len - td->qh->fixup_off;
  336 
  337         if (td->remainder > rem) {
  338                 td->error_any = 1;
  339                 DPRINTFN(1, "Excess setup transmit data\n");
  340                 return (0);             /* done */
  341         }
  342         usbd_copy_out(td->pc, td->offset, td->qh->fixup_buf +
  343             td->qh->fixup_off + 8, td->remainder);
  344 
  345         td->offset += td->remainder;
  346         td->qh->fixup_off += td->remainder;
  347         td->remainder = 0;
  348 
  349         return (0);                     /* done */
  350 }
  351 
  352 static uint8_t
  353 octusb_host_control_data_rx(struct octusb_td *td)
  354 {
  355         uint32_t rem;
  356 
  357         /* allocate endpoint and check pending */
  358         if (octusb_host_alloc_endpoint(td))
  359                 return (1);             /* busy */
  360 
  361         /* check error */
  362         if (td->error_any)
  363                 return (0);             /* done */
  364 
  365         /* copy data from buffer */
  366         rem = td->qh->fixup_actlen - td->qh->fixup_off;
  367 
  368         if (rem > td->remainder)
  369                 rem = td->remainder;
  370 
  371         usbd_copy_in(td->pc, td->offset, td->qh->fixup_buf +
  372             td->qh->fixup_off + 8, rem);
  373 
  374         td->offset += rem;
  375         td->remainder -= rem;
  376         td->qh->fixup_off += rem;
  377 
  378         return (0);                     /* done */
  379 }
  380 
  381 static uint8_t
  382 octusb_host_control_status_tx(struct octusb_td *td)
  383 {
  384         int status;
  385 
  386         /* allocate endpoint and check pending */
  387         if (octusb_host_alloc_endpoint(td))
  388                 return (1);             /* busy */
  389 
  390         /* check error */
  391         if (td->error_any)
  392                 return (0);             /* done */
  393 
  394         if (td->qh->fixup_complete != 0) {
  395                 /* clear complete flag */
  396                 td->qh->fixup_complete = 0;
  397                 /* done */
  398                 return (0);
  399         }
  400         /* do control IN request */
  401         if (!(td->qh->fixup_buf[0] & UE_DIR_IN)) {
  402 
  403                 struct octusb_softc *sc;
  404 
  405                 /* get softc */
  406                 sc = td->qh->sc;
  407 
  408                 /* flush data */
  409                 usb_pc_cpu_flush(td->qh->fixup_pc);
  410 
  411                 /* start USB transfer */
  412                 status = cvmx_usb_submit_control(
  413                     &sc->sc_port[td->qh->port_index].state,
  414                     td->qh->ep_handle, td->qh->fixup_phys,
  415                     td->qh->fixup_phys + 8, td->qh->fixup_len,
  416                     &octusb_complete_cb, td);
  417 
  418                 /* check status */
  419                 if (status < 0) {
  420                         td->error_any = 1;
  421                         return (0);     /* done */
  422                 }
  423                 td->qh->fixup_handle = status;
  424                 td->qh->fixup_pending = 1;
  425                 td->qh->fixup_complete = 0;
  426 
  427                 return (1);             /* busy */
  428         }
  429         return (0);                     /* done */
  430 }
  431 
  432 static uint8_t
  433 octusb_non_control_data_tx(struct octusb_td *td)
  434 {
  435         struct octusb_softc *sc;
  436         uint32_t rem;
  437         int status;
  438 
  439         /* allocate endpoint and check pending */
  440         if (octusb_host_alloc_endpoint(td))
  441                 return (1);             /* busy */
  442 
  443         /* check error */
  444         if (td->error_any)
  445                 return (0);             /* done */
  446 
  447         if ((td->qh->fixup_complete != 0) &&
  448             ((td->qh->ep_type & UE_XFERTYPE) == UE_ISOCHRONOUS)) {
  449                 td->qh->fixup_complete = 0;
  450                 return (0);             /* done */
  451         }
  452         /* check complete */
  453         if (td->remainder == 0) {
  454                 if (td->short_pkt)
  455                         return (0);     /* complete */
  456                 /* else need to send a zero length packet */
  457                 rem = 0;
  458                 td->short_pkt = 1;
  459         } else {
  460                 /* get maximum length */
  461                 rem = OCTUSB_MAX_FIXUP % td->qh->max_frame_size;
  462                 rem = OCTUSB_MAX_FIXUP - rem;
  463 
  464                 if (rem == 0) {
  465                         /* should not happen */
  466                         DPRINTFN(1, "Fixup buffer is too small\n");
  467                         td->error_any = 1;
  468                         return (0);     /* done */
  469                 }
  470                 /* get minimum length */
  471                 if (rem > td->remainder) {
  472                         rem = td->remainder;
  473                         if ((rem == 0) || (rem % td->qh->max_frame_size))
  474                                 td->short_pkt = 1;
  475                 }
  476                 /* copy data into fixup buffer */
  477                 usbd_copy_out(td->pc, td->offset, td->qh->fixup_buf, rem);
  478 
  479                 /* flush data */
  480                 usb_pc_cpu_flush(td->qh->fixup_pc);
  481 
  482                 /* pre-increment TX buffer offset */
  483                 td->offset += rem;
  484                 td->remainder -= rem;
  485         }
  486 
  487         /* get softc */
  488         sc = td->qh->sc;
  489 
  490         switch (td->qh->ep_type & UE_XFERTYPE) {
  491         case UE_ISOCHRONOUS:
  492                 td->qh->iso_pkt.offset = 0;
  493                 td->qh->iso_pkt.length = rem;
  494                 td->qh->iso_pkt.status = 0;
  495                 /* start USB transfer */
  496                 status = cvmx_usb_submit_isochronous(&sc->sc_port[td->qh->port_index].state,
  497                     td->qh->ep_handle, 1, CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT |
  498                     CVMX_USB_ISOCHRONOUS_FLAGS_ASAP, 1, &td->qh->iso_pkt,
  499                     td->qh->fixup_phys, rem, &octusb_complete_cb, td);
  500                 break;
  501         case UE_BULK:
  502                 /* start USB transfer */
  503                 status = cvmx_usb_submit_bulk(&sc->sc_port[td->qh->port_index].state,
  504                     td->qh->ep_handle, td->qh->fixup_phys, rem, &octusb_complete_cb, td);
  505                 break;
  506         case UE_INTERRUPT:
  507                 /* start USB transfer (interrupt or interrupt) */
  508                 status = cvmx_usb_submit_interrupt(&sc->sc_port[td->qh->port_index].state,
  509                     td->qh->ep_handle, td->qh->fixup_phys, rem, &octusb_complete_cb, td);
  510                 break;
  511         default:
  512                 status = -1;
  513                 break;
  514         }
  515 
  516         /* check status */
  517         if (status < 0) {
  518                 td->error_any = 1;
  519                 return (0);             /* done */
  520         }
  521         td->qh->fixup_handle = status;
  522         td->qh->fixup_len = rem;
  523         td->qh->fixup_pending = 1;
  524         td->qh->fixup_complete = 0;
  525 
  526         return (1);                     /* busy */
  527 }
  528 
  529 static uint8_t
  530 octusb_non_control_data_rx(struct octusb_td *td)
  531 {
  532         struct octusb_softc *sc;
  533         uint32_t rem;
  534         int status;
  535         uint8_t got_short;
  536 
  537         /* allocate endpoint and check pending */
  538         if (octusb_host_alloc_endpoint(td))
  539                 return (1);             /* busy */
  540 
  541         /* check error */
  542         if (td->error_any)
  543                 return (0);             /* done */
  544 
  545         got_short = 0;
  546 
  547         if (td->qh->fixup_complete != 0) {
  548 
  549                 /* invalidate data */
  550                 usb_pc_cpu_invalidate(td->qh->fixup_pc);
  551 
  552                 rem = td->qh->fixup_actlen;
  553 
  554                 /* verify transfer length */
  555                 if (rem != td->qh->fixup_len) {
  556                         if (rem < td->qh->fixup_len) {
  557                                 /* we have a short packet */
  558                                 td->short_pkt = 1;
  559                                 got_short = 1;
  560                         } else {
  561                                 /* invalid USB packet */
  562                                 td->error_any = 1;
  563                                 return (0);     /* we are complete */
  564                         }
  565                 }
  566                 /* copy data into fixup buffer */
  567                 usbd_copy_in(td->pc, td->offset, td->qh->fixup_buf, rem);
  568 
  569                 /* post-increment RX buffer offset */
  570                 td->offset += rem;
  571                 td->remainder -= rem;
  572 
  573                 td->qh->fixup_complete = 0;
  574 
  575                 if ((td->qh->ep_type & UE_XFERTYPE) == UE_ISOCHRONOUS)
  576                         return (0);     /* done */
  577         }
  578         /* check if we are complete */
  579         if ((td->remainder == 0) || got_short) {
  580                 if (td->short_pkt) {
  581                         /* we are complete */
  582                         return (0);
  583                 }
  584                 /* else need to receive a zero length packet */
  585                 rem = 0;
  586                 td->short_pkt = 1;
  587         } else {
  588                 /* get maximum length */
  589                 rem = OCTUSB_MAX_FIXUP % td->qh->max_frame_size;
  590                 rem = OCTUSB_MAX_FIXUP - rem;
  591 
  592                 if (rem == 0) {
  593                         /* should not happen */
  594                         DPRINTFN(1, "Fixup buffer is too small\n");
  595                         td->error_any = 1;
  596                         return (0);     /* done */
  597                 }
  598                 /* get minimum length */
  599                 if (rem > td->remainder)
  600                         rem = td->remainder;
  601         }
  602 
  603         /* invalidate data */
  604         usb_pc_cpu_invalidate(td->qh->fixup_pc);
  605 
  606         /* get softc */
  607         sc = td->qh->sc;
  608 
  609         switch (td->qh->ep_type & UE_XFERTYPE) {
  610         case UE_ISOCHRONOUS:
  611                 td->qh->iso_pkt.offset = 0;
  612                 td->qh->iso_pkt.length = rem;
  613                 td->qh->iso_pkt.status = 0;
  614                 /* start USB transfer */
  615                 status = cvmx_usb_submit_isochronous(&sc->sc_port[td->qh->port_index].state,
  616                     td->qh->ep_handle, 1, CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT |
  617                     CVMX_USB_ISOCHRONOUS_FLAGS_ASAP, 1, &td->qh->iso_pkt,
  618                     td->qh->fixup_phys, rem, &octusb_complete_cb, td);
  619                 break;
  620         case UE_BULK:
  621                 /* start USB transfer */
  622                 status = cvmx_usb_submit_bulk(&sc->sc_port[td->qh->port_index].state,
  623                     td->qh->ep_handle, td->qh->fixup_phys, rem, &octusb_complete_cb, td);
  624                 break;
  625         case UE_INTERRUPT:
  626                 /* start USB transfer */
  627                 status = cvmx_usb_submit_interrupt(&sc->sc_port[td->qh->port_index].state,
  628                     td->qh->ep_handle, td->qh->fixup_phys, rem, &octusb_complete_cb, td);
  629                 break;
  630         default:
  631                 status = -1;
  632                 break;
  633         }
  634 
  635         /* check status */
  636         if (status < 0) {
  637                 td->error_any = 1;
  638                 return (0);             /* done */
  639         }
  640         td->qh->fixup_handle = status;
  641         td->qh->fixup_len = rem;
  642         td->qh->fixup_pending = 1;
  643         td->qh->fixup_complete = 0;
  644 
  645         return (1);                     /* busy */
  646 }
  647 
  648 static uint8_t
  649 octusb_xfer_do_fifo(struct usb_xfer *xfer)
  650 {
  651         struct octusb_td *td;
  652 
  653         DPRINTFN(8, "\n");
  654 
  655         td = xfer->td_transfer_cache;
  656 
  657         while (1) {
  658                 if ((td->func) (td)) {
  659                         /* operation in progress */
  660                         break;
  661                 }
  662                 if (((void *)td) == xfer->td_transfer_last) {
  663                         goto done;
  664                 }
  665                 if (td->error_any) {
  666                         goto done;
  667                 } else if (td->remainder > 0) {
  668                         /*
  669                          * We had a short transfer. If there is no
  670                          * alternate next, stop processing !
  671                          */
  672                         if (td->alt_next == 0)
  673                                 goto done;
  674                 }
  675                 /*
  676                  * Fetch the next transfer descriptor and transfer
  677                  * some flags to the next transfer descriptor
  678                  */
  679                 td = td->obj_next;
  680                 xfer->td_transfer_cache = td;
  681         }
  682         return (1);                     /* not complete */
  683 
  684 done:
  685         /* compute all actual lengths */
  686 
  687         octusb_standard_done(xfer);
  688 
  689         return (0);                     /* complete */
  690 }
  691 
  692 static usb_error_t
  693 octusb_standard_done_sub(struct usb_xfer *xfer)
  694 {
  695         struct octusb_td *td;
  696         uint32_t len;
  697         usb_error_t error;
  698 
  699         DPRINTFN(8, "\n");
  700 
  701         td = xfer->td_transfer_cache;
  702 
  703         do {
  704                 len = td->remainder;
  705 
  706                 if (xfer->aframes != xfer->nframes) {
  707                         /*
  708                          * Verify the length and subtract
  709                          * the remainder from "frlengths[]":
  710                          */
  711                         if (len > xfer->frlengths[xfer->aframes]) {
  712                                 td->error_any = 1;
  713                         } else {
  714                                 xfer->frlengths[xfer->aframes] -= len;
  715                         }
  716                 }
  717                 /* Check for transfer error */
  718                 if (td->error_any) {
  719                         /* the transfer is finished */
  720                         error = td->error_stall ? USB_ERR_STALLED : USB_ERR_IOERROR;
  721                         td = NULL;
  722                         break;
  723                 }
  724                 /* Check for short transfer */
  725                 if (len > 0) {
  726                         if (xfer->flags_int.short_frames_ok) {
  727                                 /* follow alt next */
  728                                 if (td->alt_next) {
  729                                         td = td->obj_next;
  730                                 } else {
  731                                         td = NULL;
  732                                 }
  733                         } else {
  734                                 /* the transfer is finished */
  735                                 td = NULL;
  736                         }
  737                         error = 0;
  738                         break;
  739                 }
  740                 td = td->obj_next;
  741 
  742                 /* this USB frame is complete */
  743                 error = 0;
  744                 break;
  745 
  746         } while (0);
  747 
  748         /* update transfer cache */
  749 
  750         xfer->td_transfer_cache = td;
  751 
  752         return (error);
  753 }
  754 
  755 static void
  756 octusb_standard_done(struct usb_xfer *xfer)
  757 {
  758         struct octusb_softc *sc;
  759         struct octusb_qh *qh;
  760         usb_error_t error = 0;
  761 
  762         DPRINTFN(12, "xfer=%p endpoint=%p transfer done\n",
  763             xfer, xfer->endpoint);
  764 
  765         /* reset scanner */
  766 
  767         xfer->td_transfer_cache = xfer->td_transfer_first;
  768 
  769         if (xfer->flags_int.control_xfr) {
  770 
  771                 if (xfer->flags_int.control_hdr)
  772                         error = octusb_standard_done_sub(xfer);
  773 
  774                 xfer->aframes = 1;
  775 
  776                 if (xfer->td_transfer_cache == NULL)
  777                         goto done;
  778         }
  779         while (xfer->aframes != xfer->nframes) {
  780 
  781                 error = octusb_standard_done_sub(xfer);
  782 
  783                 xfer->aframes++;
  784 
  785                 if (xfer->td_transfer_cache == NULL)
  786                         goto done;
  787         }
  788 
  789         if (xfer->flags_int.control_xfr &&
  790             !xfer->flags_int.control_act)
  791                 error = octusb_standard_done_sub(xfer);
  792 
  793 done:
  794         /* update data toggle */
  795 
  796         qh = xfer->qh_start[0];
  797         sc = qh->sc;
  798 
  799         xfer->endpoint->toggle_next =
  800             cvmx_usb_get_toggle(
  801             &sc->sc_port[qh->port_index].state,
  802             qh->ep_handle) ? 1 : 0;
  803 
  804         octusb_device_done(xfer, error);
  805 }
  806 
  807 static void
  808 octusb_interrupt_poll(struct octusb_softc *sc)
  809 {
  810         struct usb_xfer *xfer;
  811         uint8_t x;
  812 
  813         /* poll all ports */
  814         for (x = 0; x != sc->sc_noport; x++)
  815                 cvmx_usb_poll(&sc->sc_port[x].state);
  816 
  817 repeat:
  818         TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
  819                 if (!octusb_xfer_do_fifo(xfer)) {
  820                         /* queue has been modified */
  821                         goto repeat;
  822                 }
  823         }
  824 }
  825 
  826 static void
  827 octusb_start_standard_chain(struct usb_xfer *xfer)
  828 {
  829         DPRINTFN(8, "\n");
  830 
  831         /* poll one time */
  832         if (octusb_xfer_do_fifo(xfer)) {
  833 
  834                 /* put transfer on interrupt queue */
  835                 usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
  836 
  837                 /* start timeout, if any */
  838                 if (xfer->timeout != 0) {
  839                         usbd_transfer_timeout_ms(xfer,
  840                             &octusb_timeout, xfer->timeout);
  841                 }
  842         }
  843 }
  844 
  845 void
  846 octusb_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb)
  847 {
  848 
  849 }
  850 
  851 usb_error_t
  852 octusb_init(struct octusb_softc *sc)
  853 {
  854         cvmx_usb_initialize_flags_t flags;
  855         int status;
  856         uint8_t x;
  857 
  858         /* flush all cache into memory */
  859 
  860         usb_bus_mem_flush_all(&sc->sc_bus, &octusb_iterate_hw_softc);
  861 
  862         /* set up the bus struct */
  863         sc->sc_bus.methods = &octusb_bus_methods;
  864 
  865         /* get number of ports */
  866         sc->sc_noport = cvmx_usb_get_num_ports();
  867 
  868         /* check number of ports */
  869         if (sc->sc_noport > OCTUSB_MAX_PORTS)
  870                 sc->sc_noport = OCTUSB_MAX_PORTS;
  871 
  872         /* set USB revision */
  873         sc->sc_bus.usbrev = USB_REV_2_0;
  874 
  875         /* flags for port initialization */
  876         flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO;
  877 #ifdef USB_DEBUG
  878         if (octusbdebug > 100)
  879                 flags |= CVMX_USB_INITIALIZE_FLAGS_DEBUG_ALL;
  880 #endif
  881 
  882         USB_BUS_LOCK(&sc->sc_bus);
  883 
  884         /* setup all ports */
  885         for (x = 0; x != sc->sc_noport; x++) {
  886                 status = cvmx_usb_initialize(&sc->sc_port[x].state, x, flags);
  887                 if (status < 0)
  888                         sc->sc_port[x].disabled = 1;
  889         }
  890 
  891         USB_BUS_UNLOCK(&sc->sc_bus);
  892 
  893         /* catch lost interrupts */
  894         octusb_do_poll(&sc->sc_bus);
  895 
  896         return (0);
  897 }
  898 
  899 usb_error_t
  900 octusb_uninit(struct octusb_softc *sc)
  901 {
  902         uint8_t x;
  903 
  904         USB_BUS_LOCK(&sc->sc_bus);
  905 
  906         for (x = 0; x != sc->sc_noport; x++) {
  907                 if (sc->sc_port[x].disabled == 0)
  908                         cvmx_usb_shutdown(&sc->sc_port[x].state);
  909         }
  910         USB_BUS_UNLOCK(&sc->sc_bus);
  911 
  912         return (0);
  913 
  914 }
  915 
  916 static void
  917 octusb_suspend(struct octusb_softc *sc)
  918 {
  919         /* TODO */
  920 }
  921 
  922 static void
  923 octusb_resume(struct octusb_softc *sc)
  924 {
  925         /* TODO */
  926 }
  927 
  928 /*------------------------------------------------------------------------*
  929  *      octusb_interrupt - OCTUSB interrupt handler
  930  *------------------------------------------------------------------------*/
  931 void
  932 octusb_interrupt(struct octusb_softc *sc)
  933 {
  934         USB_BUS_LOCK(&sc->sc_bus);
  935 
  936         DPRINTFN(16, "real interrupt\n");
  937 
  938         /* poll all the USB transfers */
  939         octusb_interrupt_poll(sc);
  940 
  941         USB_BUS_UNLOCK(&sc->sc_bus);
  942 }
  943 
  944 /*------------------------------------------------------------------------*
  945  *      octusb_timeout - OCTUSB transfer timeout handler
  946  *------------------------------------------------------------------------*/
  947 static void
  948 octusb_timeout(void *arg)
  949 {
  950         struct usb_xfer *xfer = arg;
  951 
  952         DPRINTF("xfer=%p\n", xfer);
  953 
  954         USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
  955 
  956         /* transfer is transferred */
  957         octusb_device_done(xfer, USB_ERR_TIMEOUT);
  958 }
  959 
  960 /*------------------------------------------------------------------------*
  961  *      octusb_do_poll - OCTUSB poll transfers
  962  *------------------------------------------------------------------------*/
  963 static void
  964 octusb_do_poll(struct usb_bus *bus)
  965 {
  966         struct octusb_softc *sc = OCTUSB_BUS2SC(bus);
  967 
  968         USB_BUS_LOCK(&sc->sc_bus);
  969         octusb_interrupt_poll(sc);
  970         USB_BUS_UNLOCK(&sc->sc_bus);
  971 }
  972 
  973 static void
  974 octusb_setup_standard_chain_sub(struct octusb_std_temp *temp)
  975 {
  976         struct octusb_td *td;
  977 
  978         /* get current Transfer Descriptor */
  979         td = temp->td_next;
  980         temp->td = td;
  981 
  982         /* prepare for next TD */
  983         temp->td_next = td->obj_next;
  984 
  985         /* fill out the Transfer Descriptor */
  986         td->func = temp->func;
  987         td->pc = temp->pc;
  988         td->offset = temp->offset;
  989         td->remainder = temp->len;
  990         td->error_any = 0;
  991         td->error_stall = 0;
  992         td->short_pkt = temp->short_pkt;
  993         td->alt_next = temp->setup_alt_next;
  994 }
  995 
  996 static void
  997 octusb_setup_standard_chain(struct usb_xfer *xfer)
  998 {
  999         struct octusb_std_temp temp;
 1000         struct octusb_td *td;
 1001         uint32_t x;
 1002 
 1003         DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n",
 1004             xfer->address, UE_GET_ADDR(xfer->endpointno),
 1005             xfer->sumlen, usbd_get_speed(xfer->xroot->udev));
 1006 
 1007         /* setup starting point */
 1008         td = xfer->td_start[0];
 1009         xfer->td_transfer_first = td;
 1010         xfer->td_transfer_cache = td;
 1011 
 1012         temp.td = NULL;
 1013         temp.td_next = td;
 1014         temp.setup_alt_next = xfer->flags_int.short_frames_ok;
 1015         temp.offset = 0;
 1016 
 1017         /* check if we should prepend a setup message */
 1018 
 1019         if (xfer->flags_int.control_xfr) {
 1020 
 1021                 if (xfer->flags_int.control_hdr) {
 1022 
 1023                         temp.func = &octusb_host_control_header_tx;
 1024                         temp.len = xfer->frlengths[0];
 1025                         temp.pc = xfer->frbuffers + 0;
 1026                         temp.short_pkt = temp.len ? 1 : 0;
 1027 
 1028                         /* check for last frame */
 1029                         if (xfer->nframes == 1) {
 1030                                 /*
 1031                                  * no STATUS stage yet, SETUP is
 1032                                  * last
 1033                                  */
 1034                                 if (xfer->flags_int.control_act)
 1035                                         temp.setup_alt_next = 0;
 1036                         }
 1037                         octusb_setup_standard_chain_sub(&temp);
 1038                 }
 1039                 x = 1;
 1040         } else {
 1041                 x = 0;
 1042         }
 1043 
 1044         if (x != xfer->nframes) {
 1045                 if (xfer->endpointno & UE_DIR_IN) {
 1046                         if (xfer->flags_int.control_xfr)
 1047                                 temp.func = &octusb_host_control_data_rx;
 1048                         else
 1049                                 temp.func = &octusb_non_control_data_rx;
 1050                 } else {
 1051                         if (xfer->flags_int.control_xfr)
 1052                                 temp.func = &octusb_host_control_data_tx;
 1053                         else
 1054                                 temp.func = &octusb_non_control_data_tx;
 1055                 }
 1056 
 1057                 /* setup "pc" pointer */
 1058                 temp.pc = xfer->frbuffers + x;
 1059         }
 1060         while (x != xfer->nframes) {
 1061 
 1062                 /* DATA0 or DATA1 message */
 1063 
 1064                 temp.len = xfer->frlengths[x];
 1065 
 1066                 x++;
 1067 
 1068                 if (x == xfer->nframes) {
 1069                         if (xfer->flags_int.control_xfr) {
 1070                                 /* no STATUS stage yet, DATA is last */
 1071                                 if (xfer->flags_int.control_act)
 1072                                         temp.setup_alt_next = 0;
 1073                         } else {
 1074                                 temp.setup_alt_next = 0;
 1075                         }
 1076                 }
 1077                 if (temp.len == 0) {
 1078 
 1079                         /* make sure that we send an USB packet */
 1080 
 1081                         temp.short_pkt = 0;
 1082 
 1083                 } else {
 1084 
 1085                         /* regular data transfer */
 1086 
 1087                         temp.short_pkt = (xfer->flags.force_short_xfer) ? 0 : 1;
 1088                 }
 1089 
 1090                 octusb_setup_standard_chain_sub(&temp);
 1091 
 1092                 if (xfer->flags_int.isochronous_xfr) {
 1093                         /* get next data offset */
 1094                         temp.offset += temp.len;
 1095                 } else {
 1096                         /* get next Page Cache pointer */
 1097                         temp.pc = xfer->frbuffers + x;
 1098                 }
 1099         }
 1100 
 1101         /* check if we should append a status stage */
 1102 
 1103         if (xfer->flags_int.control_xfr &&
 1104             !xfer->flags_int.control_act) {
 1105 
 1106                 temp.func = &octusb_host_control_status_tx;
 1107                 temp.len = 0;
 1108                 temp.pc = NULL;
 1109                 temp.short_pkt = 0;
 1110                 temp.setup_alt_next = 0;
 1111 
 1112                 octusb_setup_standard_chain_sub(&temp);
 1113         }
 1114         /* must have at least one frame! */
 1115         td = temp.td;
 1116         xfer->td_transfer_last = td;
 1117 
 1118         /* properly setup QH */
 1119 
 1120         td->qh->ep_allocated = 0;
 1121         td->qh->ep_toggle_next = xfer->endpoint->toggle_next ? 1 : 0;
 1122 }
 1123 
 1124 /*------------------------------------------------------------------------*
 1125  *      octusb_device_done - OCTUSB transfers done code
 1126  *
 1127  * NOTE: This function can be called more than one time in a row.
 1128  *------------------------------------------------------------------------*/
 1129 static void
 1130 octusb_device_done(struct usb_xfer *xfer, usb_error_t error)
 1131 {
 1132         USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
 1133 
 1134         DPRINTFN(2, "xfer=%p, endpoint=%p, error=%d\n",
 1135             xfer, xfer->endpoint, error);
 1136 
 1137         /*
 1138          * 1) Free any endpoints.
 1139          * 2) Control transfers can be split and we should not re-open
 1140          *    the data pipe between transactions unless there is an error.
 1141          */
 1142         if ((xfer->flags_int.control_act == 0) || (error != 0)) {
 1143                 struct octusb_td *td;
 1144 
 1145                 td = xfer->td_start[0];
 1146 
 1147                 octusb_host_free_endpoint(td);
 1148         }
 1149         /* dequeue transfer and start next transfer */
 1150         usbd_transfer_done(xfer, error);
 1151 }
 1152 
 1153 /*------------------------------------------------------------------------*
 1154  * octusb bulk support
 1155  *------------------------------------------------------------------------*/
 1156 static void
 1157 octusb_device_bulk_open(struct usb_xfer *xfer)
 1158 {
 1159         return;
 1160 }
 1161 
 1162 static void
 1163 octusb_device_bulk_close(struct usb_xfer *xfer)
 1164 {
 1165         octusb_device_done(xfer, USB_ERR_CANCELLED);
 1166 }
 1167 
 1168 static void
 1169 octusb_device_bulk_enter(struct usb_xfer *xfer)
 1170 {
 1171         return;
 1172 }
 1173 
 1174 static void
 1175 octusb_device_bulk_start(struct usb_xfer *xfer)
 1176 {
 1177         /* setup TDs */
 1178         octusb_setup_standard_chain(xfer);
 1179         octusb_start_standard_chain(xfer);
 1180 }
 1181 
 1182 struct usb_pipe_methods octusb_device_bulk_methods =
 1183 {
 1184         .open = octusb_device_bulk_open,
 1185         .close = octusb_device_bulk_close,
 1186         .enter = octusb_device_bulk_enter,
 1187         .start = octusb_device_bulk_start,
 1188 };
 1189 
 1190 /*------------------------------------------------------------------------*
 1191  * octusb control support
 1192  *------------------------------------------------------------------------*/
 1193 static void
 1194 octusb_device_ctrl_open(struct usb_xfer *xfer)
 1195 {
 1196         return;
 1197 }
 1198 
 1199 static void
 1200 octusb_device_ctrl_close(struct usb_xfer *xfer)
 1201 {
 1202         octusb_device_done(xfer, USB_ERR_CANCELLED);
 1203 }
 1204 
 1205 static void
 1206 octusb_device_ctrl_enter(struct usb_xfer *xfer)
 1207 {
 1208         return;
 1209 }
 1210 
 1211 static void
 1212 octusb_device_ctrl_start(struct usb_xfer *xfer)
 1213 {
 1214         /* setup TDs */
 1215         octusb_setup_standard_chain(xfer);
 1216         octusb_start_standard_chain(xfer);
 1217 }
 1218 
 1219 struct usb_pipe_methods octusb_device_ctrl_methods =
 1220 {
 1221         .open = octusb_device_ctrl_open,
 1222         .close = octusb_device_ctrl_close,
 1223         .enter = octusb_device_ctrl_enter,
 1224         .start = octusb_device_ctrl_start,
 1225 };
 1226 
 1227 /*------------------------------------------------------------------------*
 1228  * octusb interrupt support
 1229  *------------------------------------------------------------------------*/
 1230 static void
 1231 octusb_device_intr_open(struct usb_xfer *xfer)
 1232 {
 1233         return;
 1234 }
 1235 
 1236 static void
 1237 octusb_device_intr_close(struct usb_xfer *xfer)
 1238 {
 1239         octusb_device_done(xfer, USB_ERR_CANCELLED);
 1240 }
 1241 
 1242 static void
 1243 octusb_device_intr_enter(struct usb_xfer *xfer)
 1244 {
 1245         return;
 1246 }
 1247 
 1248 static void
 1249 octusb_device_intr_start(struct usb_xfer *xfer)
 1250 {
 1251         /* setup TDs */
 1252         octusb_setup_standard_chain(xfer);
 1253         octusb_start_standard_chain(xfer);
 1254 }
 1255 
 1256 struct usb_pipe_methods octusb_device_intr_methods =
 1257 {
 1258         .open = octusb_device_intr_open,
 1259         .close = octusb_device_intr_close,
 1260         .enter = octusb_device_intr_enter,
 1261         .start = octusb_device_intr_start,
 1262 };
 1263 
 1264 /*------------------------------------------------------------------------*
 1265  * octusb isochronous support
 1266  *------------------------------------------------------------------------*/
 1267 static void
 1268 octusb_device_isoc_open(struct usb_xfer *xfer)
 1269 {
 1270         return;
 1271 }
 1272 
 1273 static void
 1274 octusb_device_isoc_close(struct usb_xfer *xfer)
 1275 {
 1276         octusb_device_done(xfer, USB_ERR_CANCELLED);
 1277 }
 1278 
 1279 static void
 1280 octusb_device_isoc_enter(struct usb_xfer *xfer)
 1281 {
 1282         struct octusb_softc *sc = OCTUSB_BUS2SC(xfer->xroot->bus);
 1283         uint32_t temp;
 1284         uint32_t frame_count;
 1285         uint32_t fs_frames;
 1286 
 1287         DPRINTFN(5, "xfer=%p next=%d nframes=%d\n",
 1288             xfer, xfer->endpoint->isoc_next, xfer->nframes);
 1289 
 1290         /* get the current frame index */
 1291 
 1292         frame_count = cvmx_usb_get_frame_number(
 1293             &sc->sc_port[xfer->xroot->udev->port_index].state);
 1294 
 1295         /*
 1296          * check if the frame index is within the window where the frames
 1297          * will be inserted
 1298          */
 1299         temp = (frame_count - xfer->endpoint->isoc_next) & 0x7FF;
 1300 
 1301         if (usbd_get_speed(xfer->xroot->udev) == USB_SPEED_HIGH) {
 1302                 fs_frames = (xfer->nframes + 7) / 8;
 1303         } else {
 1304                 fs_frames = xfer->nframes;
 1305         }
 1306 
 1307         if ((xfer->endpoint->is_synced == 0) || (temp < fs_frames)) {
 1308                 /*
 1309                  * If there is data underflow or the pipe queue is
 1310                  * empty we schedule the transfer a few frames ahead
 1311                  * of the current frame position. Else two isochronous
 1312                  * transfers might overlap.
 1313                  */
 1314                 xfer->endpoint->isoc_next = (frame_count + 3) & 0x7FF;
 1315                 xfer->endpoint->is_synced = 1;
 1316                 DPRINTFN(2, "start next=%d\n", xfer->endpoint->isoc_next);
 1317         }
 1318         /*
 1319          * compute how many milliseconds the insertion is ahead of the
 1320          * current frame position:
 1321          */
 1322         temp = (xfer->endpoint->isoc_next - frame_count) & 0x7FF;
 1323 
 1324         /*
 1325          * pre-compute when the isochronous transfer will be finished:
 1326          */
 1327         xfer->isoc_time_complete =
 1328             usb_isoc_time_expand(&sc->sc_bus, frame_count) + temp +
 1329             fs_frames;
 1330 
 1331         /* compute frame number for next insertion */
 1332         xfer->endpoint->isoc_next += fs_frames;
 1333 }
 1334 
 1335 static void
 1336 octusb_device_isoc_start(struct usb_xfer *xfer)
 1337 {
 1338         /* setup TDs */
 1339         octusb_setup_standard_chain(xfer);
 1340         octusb_start_standard_chain(xfer);
 1341 }
 1342 
 1343 struct usb_pipe_methods octusb_device_isoc_methods =
 1344 {
 1345         .open = octusb_device_isoc_open,
 1346         .close = octusb_device_isoc_close,
 1347         .enter = octusb_device_isoc_enter,
 1348         .start = octusb_device_isoc_start,
 1349 };
 1350 
 1351 /*------------------------------------------------------------------------*
 1352  * OCTUSB root HUB support
 1353  *------------------------------------------------------------------------*
 1354  * Simulate a hardware HUB by handling all the necessary requests.
 1355  *------------------------------------------------------------------------*/
 1356 static const
 1357 struct usb_device_descriptor octusb_devd = {
 1358         .bLength = sizeof(octusb_devd),
 1359         .bDescriptorType = UDESC_DEVICE,
 1360         .bcdUSB = {0x00, 0x02},
 1361         .bDeviceClass = UDCLASS_HUB,
 1362         .bDeviceSubClass = UDSUBCLASS_HUB,
 1363         .bDeviceProtocol = UDPROTO_FSHUB,
 1364         .bMaxPacketSize = 64,
 1365         .idVendor = {0},
 1366         .idProduct = {0},
 1367         .bcdDevice = {0x00, 0x01},
 1368         .iManufacturer = 1,
 1369         .iProduct = 2,
 1370         .iSerialNumber = 0,
 1371         .bNumConfigurations = 1,
 1372 };
 1373 
 1374 static const
 1375 struct usb_device_qualifier octusb_odevd = {
 1376         .bLength = sizeof(octusb_odevd),
 1377         .bDescriptorType = UDESC_DEVICE_QUALIFIER,
 1378         .bcdUSB = {0x00, 0x02},
 1379         .bDeviceClass = UDCLASS_HUB,
 1380         .bDeviceSubClass = UDSUBCLASS_HUB,
 1381         .bDeviceProtocol = UDPROTO_FSHUB,
 1382         .bMaxPacketSize0 = 0,
 1383         .bNumConfigurations = 0,
 1384         .bReserved = 0,
 1385 };
 1386 
 1387 static const
 1388 struct octusb_config_desc octusb_confd = {
 1389         .confd = {
 1390                 .bLength = sizeof(struct usb_config_descriptor),
 1391                 .bDescriptorType = UDESC_CONFIG,
 1392                 .wTotalLength[0] = sizeof(octusb_confd),
 1393                 .bNumInterface = 1,
 1394                 .bConfigurationValue = 1,
 1395                 .iConfiguration = 0,
 1396                 .bmAttributes = UC_SELF_POWERED,
 1397                 .bMaxPower = 0          /* max power */
 1398         },
 1399         .ifcd = {
 1400                 .bLength = sizeof(struct usb_interface_descriptor),
 1401                 .bDescriptorType = UDESC_INTERFACE,
 1402                 .bNumEndpoints = 1,
 1403                 .bInterfaceClass = UICLASS_HUB,
 1404                 .bInterfaceSubClass = UISUBCLASS_HUB,
 1405                 .bInterfaceProtocol = UIPROTO_FSHUB,
 1406         },
 1407         .endpd = {
 1408                 .bLength = sizeof(struct usb_endpoint_descriptor),
 1409                 .bDescriptorType = UDESC_ENDPOINT,
 1410                 .bEndpointAddress = UE_DIR_IN | OCTUSB_INTR_ENDPT,
 1411                 .bmAttributes = UE_INTERRUPT,
 1412                 .wMaxPacketSize[0] = 8, /* max packet (63 ports) */
 1413                 .bInterval = 255,
 1414         },
 1415 };
 1416 
 1417 static const
 1418 struct usb_hub_descriptor_min octusb_hubd =
 1419 {
 1420         .bDescLength = sizeof(octusb_hubd),
 1421         .bDescriptorType = UDESC_HUB,
 1422         .bNbrPorts = 2,
 1423         .wHubCharacteristics = {UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL, 0},
 1424         .bPwrOn2PwrGood = 50,
 1425         .bHubContrCurrent = 0,
 1426         .DeviceRemovable = {0x00},      /* all ports are removable */
 1427 };
 1428 
 1429 static usb_error_t
 1430 octusb_roothub_exec(struct usb_device *udev,
 1431     struct usb_device_request *req, const void **pptr, uint16_t *plength)
 1432 {
 1433         struct octusb_softc *sc = OCTUSB_BUS2SC(udev->bus);
 1434         const void *ptr;
 1435         const char *str_ptr;
 1436         uint16_t value;
 1437         uint16_t index;
 1438         uint16_t status;
 1439         uint16_t change;
 1440         uint16_t len;
 1441         usb_error_t err;
 1442         cvmx_usb_port_status_t usb_port_status;
 1443 
 1444         USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
 1445 
 1446         /* XXX disable power save mode, hence it is not supported */
 1447         udev->power_mode = USB_POWER_MODE_ON;
 1448 
 1449         /* buffer reset */
 1450         ptr = (const void *)&sc->sc_hub_desc.temp;
 1451         len = 0;
 1452         err = 0;
 1453 
 1454         value = UGETW(req->wValue);
 1455         index = UGETW(req->wIndex);
 1456 
 1457         DPRINTFN(3, "type=0x%02x request=0x%02x wLen=0x%04x "
 1458             "wValue=0x%04x wIndex=0x%04x\n",
 1459             req->bmRequestType, req->bRequest,
 1460             UGETW(req->wLength), value, index);
 1461 
 1462 #define C(x,y) ((x) | ((y) << 8))
 1463         switch (C(req->bRequest, req->bmRequestType)) {
 1464         case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
 1465         case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
 1466         case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
 1467                 break;
 1468         case C(UR_GET_CONFIG, UT_READ_DEVICE):
 1469                 len = 1;
 1470                 sc->sc_hub_desc.temp[0] = sc->sc_conf;
 1471                 break;
 1472         case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
 1473                 switch (value >> 8) {
 1474                 case UDESC_DEVICE:
 1475                         if ((value & 0xff) != 0) {
 1476                                 err = USB_ERR_IOERROR;
 1477                                 goto done;
 1478                         }
 1479                         len = sizeof(octusb_devd);
 1480 
 1481                         ptr = (const void *)&octusb_devd;
 1482                         break;
 1483 
 1484                 case UDESC_DEVICE_QUALIFIER:
 1485                         if ((value & 0xff) != 0) {
 1486                                 err = USB_ERR_IOERROR;
 1487                                 goto done;
 1488                         }
 1489                         len = sizeof(octusb_odevd);
 1490                         ptr = (const void *)&octusb_odevd;
 1491                         break;
 1492 
 1493                 case UDESC_CONFIG:
 1494                         if ((value & 0xff) != 0) {
 1495                                 err = USB_ERR_IOERROR;
 1496                                 goto done;
 1497                         }
 1498                         len = sizeof(octusb_confd);
 1499                         ptr = (const void *)&octusb_confd;
 1500                         break;
 1501 
 1502                 case UDESC_STRING:
 1503                         switch (value & 0xff) {
 1504                         case 0: /* Language table */
 1505                                 str_ptr = "\001";
 1506                                 break;
 1507 
 1508                         case 1: /* Vendor */
 1509                                 str_ptr = "Cavium Networks";
 1510                                 break;
 1511 
 1512                         case 2: /* Product */
 1513                                 str_ptr = "OCTUSB Root HUB";
 1514                                 break;
 1515 
 1516                         default:
 1517                                 str_ptr = "";
 1518                                 break;
 1519                         }
 1520 
 1521                         len = usb_make_str_desc(sc->sc_hub_desc.temp,
 1522                             sizeof(sc->sc_hub_desc.temp), str_ptr);
 1523                         break;
 1524 
 1525                 default:
 1526                         err = USB_ERR_IOERROR;
 1527                         goto done;
 1528                 }
 1529                 break;
 1530         case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
 1531                 len = 1;
 1532                 sc->sc_hub_desc.temp[0] = 0;
 1533                 break;
 1534         case C(UR_GET_STATUS, UT_READ_DEVICE):
 1535                 len = 2;
 1536                 USETW(sc->sc_hub_desc.stat.wStatus, UDS_SELF_POWERED);
 1537                 break;
 1538         case C(UR_GET_STATUS, UT_READ_INTERFACE):
 1539         case C(UR_GET_STATUS, UT_READ_ENDPOINT):
 1540                 len = 2;
 1541                 USETW(sc->sc_hub_desc.stat.wStatus, 0);
 1542                 break;
 1543         case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
 1544                 if (value >= OCTUSB_MAX_DEVICES) {
 1545                         err = USB_ERR_IOERROR;
 1546                         goto done;
 1547                 }
 1548                 sc->sc_addr = value;
 1549                 break;
 1550         case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
 1551                 if ((value != 0) && (value != 1)) {
 1552                         err = USB_ERR_IOERROR;
 1553                         goto done;
 1554                 }
 1555                 sc->sc_conf = value;
 1556                 break;
 1557         case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
 1558                 break;
 1559         case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
 1560         case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
 1561         case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
 1562                 err = USB_ERR_IOERROR;
 1563                 goto done;
 1564         case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
 1565                 break;
 1566         case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
 1567                 break;
 1568                 /* Hub requests */
 1569         case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
 1570                 break;
 1571         case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
 1572                 DPRINTFN(4, "UR_CLEAR_PORT_FEATURE "
 1573                     "port=%d feature=%d\n",
 1574                     index, value);
 1575                 if ((index < 1) ||
 1576                     (index > sc->sc_noport) ||
 1577                     sc->sc_port[index - 1].disabled) {
 1578                         err = USB_ERR_IOERROR;
 1579                         goto done;
 1580                 }
 1581                 index--;
 1582 
 1583                 switch (value) {
 1584                 case UHF_PORT_ENABLE:
 1585                         cvmx_usb_disable(&sc->sc_port[index].state);
 1586                         break;
 1587                 case UHF_PORT_SUSPEND:
 1588                 case UHF_PORT_RESET:
 1589                         break;
 1590                 case UHF_C_PORT_CONNECTION:
 1591                         cvmx_usb_set_status(&sc->sc_port[index].state,
 1592                             cvmx_usb_get_status(&sc->sc_port[index].state));
 1593                         break;
 1594                 case UHF_C_PORT_ENABLE:
 1595                         cvmx_usb_set_status(&sc->sc_port[index].state,
 1596                             cvmx_usb_get_status(&sc->sc_port[index].state));
 1597                         break;
 1598                 case UHF_C_PORT_OVER_CURRENT:
 1599                         cvmx_usb_set_status(&sc->sc_port[index].state,
 1600                             cvmx_usb_get_status(&sc->sc_port[index].state));
 1601                         break;
 1602                 case UHF_C_PORT_RESET:
 1603                         sc->sc_isreset = 0;
 1604                         goto done;
 1605                 case UHF_C_PORT_SUSPEND:
 1606                         break;
 1607                 case UHF_PORT_CONNECTION:
 1608                 case UHF_PORT_OVER_CURRENT:
 1609                 case UHF_PORT_POWER:
 1610                 case UHF_PORT_LOW_SPEED:
 1611                 default:
 1612                         err = USB_ERR_IOERROR;
 1613                         goto done;
 1614                 }
 1615                 break;
 1616         case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
 1617                 if ((value & 0xff) != 0) {
 1618                         err = USB_ERR_IOERROR;
 1619                         goto done;
 1620                 }
 1621                 sc->sc_hubd = octusb_hubd;
 1622                 sc->sc_hubd.bNbrPorts = sc->sc_noport;
 1623                 len = sizeof(sc->sc_hubd);
 1624                 ptr = (const void *)&sc->sc_hubd;
 1625                 break;
 1626         case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
 1627                 len = 16;
 1628                 memset(sc->sc_hub_desc.temp, 0, 16);
 1629                 break;
 1630         case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
 1631                 if ((index < 1) ||
 1632                     (index > sc->sc_noport) ||
 1633                     sc->sc_port[index - 1].disabled) {
 1634                         err = USB_ERR_IOERROR;
 1635                         goto done;
 1636                 }
 1637                 index--;
 1638 
 1639                 usb_port_status = cvmx_usb_get_status(&sc->sc_port[index].state);
 1640 
 1641                 status = change = 0;
 1642                 if (usb_port_status.connected)
 1643                         status |= UPS_CURRENT_CONNECT_STATUS;
 1644                 if (usb_port_status.port_enabled)
 1645                         status |= UPS_PORT_ENABLED;
 1646                 if (usb_port_status.port_over_current)
 1647                         status |= UPS_OVERCURRENT_INDICATOR;
 1648                 if (usb_port_status.port_powered)
 1649                         status |= UPS_PORT_POWER;
 1650 
 1651                 switch (usb_port_status.port_speed) {
 1652                 case CVMX_USB_SPEED_HIGH:
 1653                         status |= UPS_HIGH_SPEED;
 1654                         break;
 1655                 case CVMX_USB_SPEED_FULL:
 1656                         break;
 1657                 default:
 1658                         status |= UPS_LOW_SPEED;
 1659                         break;
 1660                 }
 1661 
 1662                 if (usb_port_status.connect_change)
 1663                         change |= UPS_C_CONNECT_STATUS;
 1664                 if (sc->sc_isreset)
 1665                         change |= UPS_C_PORT_RESET;
 1666 
 1667                 USETW(sc->sc_hub_desc.ps.wPortStatus, status);
 1668                 USETW(sc->sc_hub_desc.ps.wPortChange, change);
 1669 
 1670                 len = sizeof(sc->sc_hub_desc.ps);
 1671                 break;
 1672         case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
 1673                 err = USB_ERR_IOERROR;
 1674                 goto done;
 1675         case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
 1676                 break;
 1677         case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
 1678                 if ((index < 1) ||
 1679                     (index > sc->sc_noport) ||
 1680                     sc->sc_port[index - 1].disabled) {
 1681                         err = USB_ERR_IOERROR;
 1682                         goto done;
 1683                 }
 1684                 index--;
 1685 
 1686                 switch (value) {
 1687                 case UHF_PORT_ENABLE:
 1688                         break;
 1689                 case UHF_PORT_RESET:
 1690                         cvmx_usb_disable(&sc->sc_port[index].state);
 1691                         if (cvmx_usb_enable(&sc->sc_port[index].state)) {
 1692                                 err = USB_ERR_IOERROR;
 1693                                 goto done;
 1694                         }
 1695                         sc->sc_isreset = 1;
 1696                         goto done;
 1697                 case UHF_PORT_POWER:
 1698                         /* pretend we turned on power */
 1699                         goto done;
 1700                 case UHF_PORT_SUSPEND:
 1701                 case UHF_C_PORT_CONNECTION:
 1702                 case UHF_C_PORT_ENABLE:
 1703                 case UHF_C_PORT_OVER_CURRENT:
 1704                 case UHF_PORT_CONNECTION:
 1705                 case UHF_PORT_OVER_CURRENT:
 1706                 case UHF_PORT_LOW_SPEED:
 1707                 case UHF_C_PORT_SUSPEND:
 1708                 case UHF_C_PORT_RESET:
 1709                 default:
 1710                         err = USB_ERR_IOERROR;
 1711                         goto done;
 1712                 }
 1713                 break;
 1714         default:
 1715                 err = USB_ERR_IOERROR;
 1716                 goto done;
 1717         }
 1718 done:
 1719         *plength = len;
 1720         *pptr = ptr;
 1721         return (err);
 1722 }
 1723 
 1724 static void
 1725 octusb_xfer_setup(struct usb_setup_params *parm)
 1726 {
 1727         struct usb_page_search page_info;
 1728         struct usb_page_cache *pc;
 1729         struct octusb_softc *sc;
 1730         struct octusb_qh *qh;
 1731         struct usb_xfer *xfer;
 1732         void *last_obj;
 1733         uint32_t n;
 1734         uint32_t ntd;
 1735 
 1736         sc = OCTUSB_BUS2SC(parm->udev->bus);
 1737         xfer = parm->curr_xfer;
 1738         qh = NULL;
 1739 
 1740         /*
 1741          * NOTE: This driver does not use any of the parameters that
 1742          * are computed from the following values. Just set some
 1743          * reasonable dummies:
 1744          */
 1745 
 1746         parm->hc_max_packet_size = 0x400;
 1747         parm->hc_max_packet_count = 3;
 1748         parm->hc_max_frame_size = 0xC00;
 1749 
 1750         usbd_transfer_setup_sub(parm);
 1751 
 1752         if (parm->err)
 1753                 return;
 1754 
 1755         /* Allocate a queue head */
 1756 
 1757         if (usbd_transfer_setup_sub_malloc(
 1758             parm, &pc, sizeof(struct octusb_qh),
 1759             USB_HOST_ALIGN, 1)) {
 1760                 parm->err = USB_ERR_NOMEM;
 1761                 return;
 1762         }
 1763         if (parm->buf) {
 1764                 usbd_get_page(pc, 0, &page_info);
 1765 
 1766                 qh = page_info.buffer;
 1767 
 1768                 /* fill out QH */
 1769 
 1770                 qh->sc = OCTUSB_BUS2SC(xfer->xroot->bus);
 1771                 qh->max_frame_size = xfer->max_frame_size;
 1772                 qh->max_packet_size = xfer->max_packet_size;
 1773                 qh->ep_num = xfer->endpointno;
 1774                 qh->ep_type = xfer->endpoint->edesc->bmAttributes;
 1775                 qh->dev_addr = xfer->address;
 1776                 qh->dev_speed = usbd_get_speed(xfer->xroot->udev);
 1777                 qh->port_index = xfer->xroot->udev->port_index;
 1778 
 1779                 switch (xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
 1780                 case UE_INTERRUPT:
 1781                         if (usbd_get_speed(xfer->xroot->udev) == USB_SPEED_HIGH)
 1782                                 qh->ep_interval = xfer->interval * 8;
 1783                         else
 1784                                 qh->ep_interval = xfer->interval * 1;
 1785                         break;
 1786                 case UE_ISOCHRONOUS:
 1787                         qh->ep_interval = 1 << xfer->fps_shift;
 1788                         break;
 1789                 default:
 1790                         qh->ep_interval = 0;
 1791                         break;
 1792                 }
 1793 
 1794                 qh->ep_mult = xfer->max_packet_count & 3;
 1795                 qh->hs_hub_addr = xfer->xroot->udev->hs_hub_addr;
 1796                 qh->hs_hub_port = xfer->xroot->udev->hs_port_no;
 1797         }
 1798         xfer->qh_start[0] = qh;
 1799 
 1800         /* Allocate a fixup buffer */
 1801 
 1802         if (usbd_transfer_setup_sub_malloc(
 1803             parm, &pc, OCTUSB_MAX_FIXUP,
 1804             OCTUSB_MAX_FIXUP, 1)) {
 1805                 parm->err = USB_ERR_NOMEM;
 1806                 return;
 1807         }
 1808         if (parm->buf) {
 1809                 usbd_get_page(pc, 0, &page_info);
 1810 
 1811                 qh->fixup_phys = page_info.physaddr;
 1812                 qh->fixup_pc = pc;
 1813                 qh->fixup_buf = page_info.buffer;
 1814         }
 1815         /* Allocate transfer descriptors */
 1816 
 1817         last_obj = NULL;
 1818 
 1819         ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC */ ;
 1820 
 1821         if (usbd_transfer_setup_sub_malloc(
 1822             parm, &pc, sizeof(struct octusb_td),
 1823             USB_HOST_ALIGN, ntd)) {
 1824                 parm->err = USB_ERR_NOMEM;
 1825                 return;
 1826         }
 1827         if (parm->buf) {
 1828                 for (n = 0; n != ntd; n++) {
 1829                         struct octusb_td *td;
 1830 
 1831                         usbd_get_page(pc + n, 0, &page_info);
 1832 
 1833                         td = page_info.buffer;
 1834 
 1835                         td->qh = qh;
 1836                         td->obj_next = last_obj;
 1837 
 1838                         last_obj = td;
 1839                 }
 1840         }
 1841         xfer->td_start[0] = last_obj;
 1842 }
 1843 
 1844 static void
 1845 octusb_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc,
 1846     struct usb_endpoint *ep)
 1847 {
 1848         struct octusb_softc *sc = OCTUSB_BUS2SC(udev->bus);
 1849 
 1850         DPRINTFN(2, "endpoint=%p, addr=%d, endpt=%d, mode=%d (%d)\n",
 1851             ep, udev->address, edesc->bEndpointAddress,
 1852             udev->flags.usb_mode, sc->sc_addr);
 1853 
 1854         if (udev->device_index != sc->sc_addr) {
 1855                 switch (edesc->bmAttributes & UE_XFERTYPE) {
 1856                 case UE_CONTROL:
 1857                         ep->methods = &octusb_device_ctrl_methods;
 1858                         break;
 1859                 case UE_INTERRUPT:
 1860                         ep->methods = &octusb_device_intr_methods;
 1861                         break;
 1862                 case UE_ISOCHRONOUS:
 1863                         if (udev->speed != USB_SPEED_LOW)
 1864                                 ep->methods = &octusb_device_isoc_methods;
 1865                         break;
 1866                 case UE_BULK:
 1867                         ep->methods = &octusb_device_bulk_methods;
 1868                         break;
 1869                 default:
 1870                         /* do nothing */
 1871                         break;
 1872                 }
 1873         }
 1874 }
 1875 
 1876 static void
 1877 octusb_xfer_unsetup(struct usb_xfer *xfer)
 1878 {
 1879         DPRINTF("Nothing to do.\n");
 1880 }
 1881 
 1882 static void
 1883 octusb_get_dma_delay(struct usb_device *udev, uint32_t *pus)
 1884 {
 1885         /* DMA delay - wait until any use of memory is finished */
 1886         *pus = (2125);                  /* microseconds */
 1887 }
 1888 
 1889 static void
 1890 octusb_device_resume(struct usb_device *udev)
 1891 {
 1892         DPRINTF("Nothing to do.\n");
 1893 }
 1894 
 1895 static void
 1896 octusb_device_suspend(struct usb_device *udev)
 1897 {
 1898         DPRINTF("Nothing to do.\n");
 1899 }
 1900 
 1901 static void
 1902 octusb_set_hw_power(struct usb_bus *bus)
 1903 {
 1904         DPRINTF("Nothing to do.\n");
 1905 }
 1906 
 1907 static void
 1908 octusb_set_hw_power_sleep(struct usb_bus *bus, uint32_t state)
 1909 {
 1910         struct octusb_softc *sc = OCTUSB_BUS2SC(bus);
 1911 
 1912         switch (state) {
 1913         case USB_HW_POWER_SUSPEND:
 1914                 octusb_suspend(sc);
 1915                 break;
 1916         case USB_HW_POWER_SHUTDOWN:
 1917                 octusb_uninit(sc);
 1918                 break;
 1919         case USB_HW_POWER_RESUME:
 1920                 octusb_resume(sc);
 1921                 break;
 1922         default:
 1923                 break;
 1924         }
 1925 }
 1926 
 1927 struct usb_bus_methods octusb_bus_methods = {
 1928         .endpoint_init = octusb_ep_init,
 1929         .xfer_setup = octusb_xfer_setup,
 1930         .xfer_unsetup = octusb_xfer_unsetup,
 1931         .get_dma_delay = octusb_get_dma_delay,
 1932         .device_resume = octusb_device_resume,
 1933         .device_suspend = octusb_device_suspend,
 1934         .set_hw_power = octusb_set_hw_power,
 1935         .set_hw_power_sleep = octusb_set_hw_power_sleep,
 1936         .roothub_exec = octusb_roothub_exec,
 1937         .xfer_poll = octusb_do_poll,
 1938 };

Cache object: 0bd5e671eb0ad95ad85b7c75003c6ecb


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