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

Cache object: d6f9df93eba94dfe45ce459fa672e961


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