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

Cache object: a0da1d44a5d15745f14bb685b45af344


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