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

Cache object: fb701b2b3ceffd5769385cdc11e3941b


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