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

Cache object: 3a2f0e6729897c96c8f020ec5120814f


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