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/dev/ic/sl811hs.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 /*      $NetBSD: sl811hs.c,v 1.3 2003/03/13 06:50:23 bsh Exp $  */
    2 
    3 /*
    4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Tetsuya Isaki.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * ScanLogic SL811HS/T USB Host Controller
   41  */
   42 /*
   43  * !! HIGHLY EXPERIMENTAL CODE !!
   44  */
   45 
   46 #include <sys/cdefs.h>
   47 __KERNEL_RCSID(0, "$NetBSD: sl811hs.c,v 1.3 2003/03/13 06:50:23 bsh Exp $");
   48 
   49 #include "opt_slhci.h"
   50 
   51 #include <sys/param.h>
   52 #include <sys/systm.h>
   53 #include <sys/kernel.h>
   54 #include <sys/proc.h>
   55 #include <sys/device.h>
   56 #include <sys/malloc.h>
   57 
   58 #include <machine/bus.h>
   59 #include <machine/cpu.h>
   60 
   61 #include <dev/usb/usb.h>
   62 #include <dev/usb/usbdi.h>
   63 #include <dev/usb/usbdivar.h>
   64 #include <dev/usb/usb_mem.h>
   65 #include <dev/usb/usbdevs.h>
   66 
   67 #include <dev/ic/sl811hsreg.h>
   68 #include <dev/ic/sl811hsvar.h>
   69 
   70 static inline u_int8_t sl11read(struct slhci_softc *, int);
   71 static inline void     sl11write(struct slhci_softc *, int, u_int8_t);
   72 static inline void sl11read_region(struct slhci_softc *, u_char *, int, int);
   73 static inline void sl11write_region(struct slhci_softc *, int, u_char *, int);
   74 
   75 static void             sl11_reset(struct slhci_softc *);
   76 static void             sl11_speed(struct slhci_softc *);
   77 
   78 static usbd_status      slhci_open(usbd_pipe_handle);
   79 static void             slhci_softintr(void *);
   80 static void             slhci_poll(struct usbd_bus *);
   81 static void             slhci_poll_hub(void *);
   82 static void             slhci_poll_device(void *arg);
   83 static usbd_status      slhci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t);
   84 static void             slhci_freem(struct usbd_bus *, usb_dma_t *);
   85 static usbd_xfer_handle slhci_allocx(struct usbd_bus *);
   86 static void             slhci_freex(struct usbd_bus *, usbd_xfer_handle);
   87 
   88 static int              slhci_str(usb_string_descriptor_t *, int, char *);
   89 
   90 static usbd_status      slhci_root_ctrl_transfer(usbd_xfer_handle);
   91 static usbd_status      slhci_root_ctrl_start(usbd_xfer_handle);
   92 static void             slhci_root_ctrl_abort(usbd_xfer_handle);
   93 static void             slhci_root_ctrl_close(usbd_pipe_handle);
   94 static void             slhci_root_ctrl_done(usbd_xfer_handle);
   95 
   96 static usbd_status      slhci_root_intr_transfer(usbd_xfer_handle);
   97 static usbd_status      slhci_root_intr_start(usbd_xfer_handle);
   98 static void             slhci_root_intr_abort(usbd_xfer_handle);
   99 static void             slhci_root_intr_close(usbd_pipe_handle);
  100 static void             slhci_root_intr_done(usbd_xfer_handle);
  101 
  102 static usbd_status      slhci_device_ctrl_transfer(usbd_xfer_handle);
  103 static usbd_status      slhci_device_ctrl_start(usbd_xfer_handle);
  104 static void             slhci_device_ctrl_abort(usbd_xfer_handle);
  105 static void             slhci_device_ctrl_close(usbd_pipe_handle);
  106 static void             slhci_device_ctrl_done(usbd_xfer_handle);
  107 
  108 static usbd_status      slhci_device_intr_transfer(usbd_xfer_handle);
  109 static usbd_status      slhci_device_intr_start(usbd_xfer_handle);
  110 static void             slhci_device_intr_abort(usbd_xfer_handle);
  111 static void             slhci_device_intr_close(usbd_pipe_handle);
  112 static void             slhci_device_intr_done(usbd_xfer_handle);
  113 
  114 static usbd_status      slhci_device_isoc_transfer(usbd_xfer_handle);
  115 static usbd_status      slhci_device_isoc_start(usbd_xfer_handle);
  116 static void             slhci_device_isoc_abort(usbd_xfer_handle);
  117 static void             slhci_device_isoc_close(usbd_pipe_handle);
  118 static void             slhci_device_isoc_done(usbd_xfer_handle);
  119 
  120 static usbd_status      slhci_device_bulk_transfer(usbd_xfer_handle);
  121 static usbd_status      slhci_device_bulk_start(usbd_xfer_handle);
  122 static void             slhci_device_bulk_abort(usbd_xfer_handle);
  123 static void             slhci_device_bulk_close(usbd_pipe_handle);
  124 static void             slhci_device_bulk_done(usbd_xfer_handle);
  125 
  126 static int              slhci_transaction(struct slhci_softc *,
  127         usbd_pipe_handle, u_int8_t, int, u_char *, u_int8_t);
  128 static void             slhci_noop(usbd_pipe_handle);
  129 static void             slhci_abort_xfer(usbd_xfer_handle, usbd_status);
  130 static void             slhci_device_clear_toggle(usbd_pipe_handle);
  131 
  132 extern int usbdebug;
  133 int slhci_dummy;
  134 
  135 /* For root hub */
  136 #define SLHCI_INTR_ENDPT        (1)
  137 
  138 #ifdef SLHCI_DEBUG
  139 #define D_TRACE (0x0001)        /* function trace */
  140 #define D_MSG   (0x0002)        /* debug messages */
  141 #define D_XFER  (0x0004)        /* transfer messages (noisy!) */
  142 #define D_MEM   (0x0008)        /* memory allocation */
  143 
  144 int slhci_debug = D_MSG | D_XFER;
  145 #define DPRINTF(z,x)    if((slhci_debug&(z))!=0)printf x
  146 void            print_req(usb_device_request_t *);
  147 void            print_req_hub(usb_device_request_t *);
  148 void            print_dumpreg(struct slhci_softc *);
  149 void            print_xfer(usbd_xfer_handle);
  150 #else
  151 #define DPRINTF(z,x)
  152 #endif
  153 
  154 
  155 /* XXX: sync with argument */
  156 static char *sltypestr [] = {
  157         "SL11H/T",
  158         "SL811HS/T",
  159 };
  160 
  161 
  162 struct usbd_bus_methods slhci_bus_methods = {
  163         slhci_open,
  164         slhci_softintr,
  165         slhci_poll,
  166         slhci_allocm,
  167         slhci_freem,
  168         slhci_allocx,
  169         slhci_freex,
  170 };
  171 
  172 struct usbd_pipe_methods slhci_root_ctrl_methods = {
  173         slhci_root_ctrl_transfer,
  174         slhci_root_ctrl_start,
  175         slhci_root_ctrl_abort,
  176         slhci_root_ctrl_close,
  177         slhci_noop,
  178         slhci_root_ctrl_done,
  179 };
  180 
  181 struct usbd_pipe_methods slhci_root_intr_methods = {
  182         slhci_root_intr_transfer,
  183         slhci_root_intr_start,
  184         slhci_root_intr_abort,
  185         slhci_root_intr_close,
  186         slhci_noop,
  187         slhci_root_intr_done,
  188 };
  189 
  190 struct usbd_pipe_methods slhci_device_ctrl_methods = {
  191         slhci_device_ctrl_transfer,
  192         slhci_device_ctrl_start,
  193         slhci_device_ctrl_abort,
  194         slhci_device_ctrl_close,
  195         slhci_noop,
  196         slhci_device_ctrl_done,
  197 };
  198 
  199 struct usbd_pipe_methods slhci_device_intr_methods = {
  200         slhci_device_intr_transfer,
  201         slhci_device_intr_start,
  202         slhci_device_intr_abort,
  203         slhci_device_intr_close,
  204         slhci_device_clear_toggle,
  205         slhci_device_intr_done,
  206 };
  207 
  208 struct usbd_pipe_methods slhci_device_isoc_methods = {
  209         slhci_device_isoc_transfer,
  210         slhci_device_isoc_start,
  211         slhci_device_isoc_abort,
  212         slhci_device_isoc_close,
  213         slhci_noop,
  214         slhci_device_isoc_done,
  215 };
  216 
  217 struct usbd_pipe_methods slhci_device_bulk_methods = {
  218         slhci_device_bulk_transfer,
  219         slhci_device_bulk_start,
  220         slhci_device_bulk_abort,
  221         slhci_device_bulk_close,
  222         slhci_noop,
  223         slhci_device_bulk_done,
  224 };
  225 
  226 struct slhci_pipe {
  227         struct usbd_pipe pipe;
  228 };
  229 
  230 
  231 /*
  232  * SL811HS Register read/write routine
  233  */
  234 static inline u_int8_t
  235 sl11read(struct slhci_softc *sc, int reg)
  236 {
  237         bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_ADDR, reg);
  238         return bus_space_read_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_DATA);
  239 }
  240 
  241 static inline void
  242 sl11write(struct slhci_softc *sc, int reg, u_int8_t data)
  243 {
  244         bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_ADDR, reg);
  245         bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_DATA, data);
  246 }
  247 
  248 static inline void
  249 sl11read_region(struct slhci_softc *sc, u_char *buf, int reg, int len)
  250 {
  251         int i;
  252         bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_ADDR, reg);
  253         for (i = 0; i < len; i++)
  254                 buf[i] = bus_space_read_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_DATA);
  255 }
  256 
  257 static inline void
  258 sl11write_region(struct slhci_softc *sc, int reg, u_char *buf, int len)
  259 {
  260         int i;
  261         bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_ADDR, reg);
  262         for (i = 0; i < len; i++)
  263                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_DATA, buf[i]);
  264 }
  265 
  266 /*
  267  * USB bus reset. From sl811hs_appnote.pdf, p22
  268  */
  269 static void
  270 sl11_reset(struct slhci_softc *sc)
  271 {
  272         u_int8_t r;
  273 
  274         DPRINTF(D_TRACE, ("%s() ", __FUNCTION__));
  275         r = sl11read(sc, SL11_CTRL);
  276         sl11write(sc, SL11_CTRL, r | SL11_CTRL_RESETENGINE);
  277         delay_ms(250);
  278         sl11write(sc, SL11_CTRL, r | SL11_CTRL_RESETENGINE | SL11_CTRL_SUSPEND);
  279         delay_ms(150);
  280         sl11write(sc, SL11_CTRL, r | SL11_CTRL_RESETENGINE);
  281         delay_ms(10);
  282         sl11write(sc, SL11_CTRL, r);
  283 }
  284 
  285 /*
  286  * Detect the speed of attached device.
  287  */
  288 static void
  289 sl11_speed(struct slhci_softc *sc)
  290 {
  291         u_int8_t r;
  292 
  293         sl11write(sc, SL11_ISR, 0xff);
  294         r = sl11read(sc, SL11_ISR);
  295         if ((r & SL11_ISR_RESET)) {
  296                 DPRINTF(D_MSG, ("NC "));
  297                 sl11write(sc, SL11_ISR, SL11_ISR_RESET);
  298                 sc->sc_connect = 0;
  299         }
  300 
  301         if ((sl11read(sc, SL11_ISR) & SL11_ISR_RESET)) {
  302                 sl11write(sc, SL11_ISR, 0xff);
  303         } else {
  304                 u_int8_t pol = 0, ctrl = 0;
  305 
  306                 sc->sc_connect = 1;
  307                 if (r & SL11_ISR_DATA) {
  308                         DPRINTF(D_MSG, ("FS "));
  309                         pol  = 0;
  310                         ctrl = SL11_CTRL_EOF2;
  311                         sc->sc_fullspeed = 1;
  312                 } else {
  313                         DPRINTF(D_MSG, ("LS "));
  314                         pol  = SL811_CSOF_POLARITY;
  315                         ctrl = SL11_CTRL_LOWSPEED;
  316                         sc->sc_fullspeed = 0;
  317                 }
  318                 sl11write(sc, SL811_CSOF, pol | SL811_CSOF_MASTER | 0x2e);
  319                 sl11write(sc, SL11_DATA, 0xe0);
  320                 sl11write(sc, SL11_CTRL, ctrl | SL11_CTRL_ENABLESOF);
  321         }
  322 
  323         sl11write(sc, SL11_E0PID,  (SL11_PID_SOF << 4) + 0);
  324         sl11write(sc, SL11_E0DEV,  0);
  325         sl11write(sc, SL11_E0CTRL, SL11_EPCTRL_ARM);
  326         delay_ms(30);
  327 }
  328 
  329 /*
  330  * If detect some known controller, return the type.
  331  * If does not, return -1.
  332  */
  333 int
  334 sl811hs_find(struct slhci_softc *sc)
  335 {
  336         int rev;
  337 
  338         sc->sc_sltype = -1;
  339         rev = sl11read(sc, SL11_REV) >> 4;
  340         if (rev >= SLTYPE_SL11H && rev <= SLTYPE_SL811HS_R14)
  341                 sc->sc_sltype = rev;
  342         return sc->sc_sltype;
  343 }
  344 
  345 /*
  346  * Attach SL11H/SL811HS. Return 0 if success.
  347  */
  348 int
  349 slhci_attach(struct slhci_softc *sc, struct device *self)
  350 {
  351         int rev;
  352 
  353         /* Detect and check the controller type */
  354         rev = sl811hs_find(sc);
  355         if (rev == -1)
  356                 return -1;
  357 
  358         printf("%s: ScanLogic %s USB Host Controller",
  359                 sc->sc_bus.bdev.dv_xname, sltypestr[(rev > 0)]);
  360         switch (rev) {
  361         case SLTYPE_SL11H:
  362                 break;
  363         case SLTYPE_SL811HS_R12:
  364                 printf(" (rev 1.2)");
  365                 break;
  366         case SLTYPE_SL811HS_R14:
  367                 printf(" (rev 1.4)");
  368                 break;
  369         default:
  370                 printf(" (unknown revision)");
  371                 break;
  372         }
  373         printf("\n");
  374 
  375         /* Initialize sc */
  376         sc->sc_bus.usbrev = USBREV_1_1;
  377         sc->sc_bus.methods = &slhci_bus_methods;
  378         sc->sc_bus.pipe_size = sizeof(struct slhci_pipe);
  379         sc->sc_bus.dmatag = sc->sc_dmat;
  380 
  381         SIMPLEQ_INIT(&sc->sc_free_xfers);
  382 
  383         usb_callout_init(sc->sc_poll_handle);
  384 
  385         /* Initialize controller */
  386         sl11write(sc, SL811_CSOF, SL811_CSOF_MASTER | 0x2e);
  387         sl11write(sc, SL11_ISR, 0xff);
  388 
  389         /* Disable interrupt, then wait 40msec */
  390         sl11write(sc, SL11_IER, 0x00);
  391         delay_ms(40);
  392 
  393         /* Reset USB engine */
  394         sl11write(sc, SL11_CTRL, SL11_CTRL_RESETENGINE | SL11_CTRL_SUSPEND);
  395         delay_ms(40);
  396         sl11write(sc, SL11_CTRL, 0x00);
  397         delay_ms(10);
  398 
  399         /* USB Bus reset for GET_PORT_STATUS */
  400         sl11_reset(sc);
  401 
  402         /* Enable interrupt */
  403         sl11write(sc, SL11_IER, SL11_IER_INSERT);
  404         /* x68k Nereid USB controller needs it */
  405         if (sc->sc_enable_intr)
  406                 sc->sc_enable_intr(sc->sc_arg, INTR_ON);
  407 
  408 #ifdef USB_DEBUG
  409         usbdebug = 0;
  410 #endif
  411 
  412         /* Attach USB devices */
  413         sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint);
  414 
  415         return 0;
  416 }
  417 
  418 int
  419 slhci_intr(void *arg)
  420 {
  421         struct slhci_softc *sc = arg;
  422         u_int8_t r;
  423 #ifdef SLHCI_DEBUG
  424         char bitbuf[256];
  425 #endif
  426 
  427         r = sl11read(sc, SL11_ISR);
  428 
  429         sl11write(sc, SL11_ISR, SL11_ISR_DATA | SL11_ISR_SOFTIMER);
  430 
  431         if ((r & SL11_ISR_RESET)) {
  432                 sc->sc_flags |= SLF_RESET;
  433                 sl11write(sc, SL11_ISR, SL11_ISR_RESET);
  434         }
  435         if ((r & SL11_ISR_INSERT)) {
  436                 sc->sc_flags |= SLF_INSERT;
  437                 sl11write(sc, SL11_ISR, SL11_ISR_INSERT);
  438         }
  439 
  440 #ifdef SLHCI_DEBUG
  441         bitmask_snprintf(r,
  442                 (sl11read(sc, SL11_CTRL) & SL11_CTRL_SUSPEND)
  443                 ? "\2\x8""D+\7RESUME\6INSERT\5SOF\4res\3""BABBLE\2USBB\1USBA"
  444                 : "\2\x8""D+\7RESET\6INSERT\5SOF\4res\3""BABBLE\2USBB\1USBA",
  445                 bitbuf, sizeof(bitbuf));
  446         DPRINTF(D_XFER, ("I=%s ", bitbuf));
  447 #endif /* SLHCI_DEBUG */
  448 
  449         return 0;
  450 }
  451 
  452 usbd_status
  453 slhci_open(usbd_pipe_handle pipe)
  454 {
  455         usbd_device_handle dev = pipe->device;
  456         struct slhci_softc *sc = (struct slhci_softc *)dev->bus;
  457         usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
  458 
  459         DPRINTF(D_TRACE, ("slhci_open(addr=%d,ep=%d,scaddr=%d)",
  460                 dev->address, ed->bEndpointAddress, sc->sc_addr));
  461 
  462         if (dev->address == sc->sc_addr) {
  463                 switch (ed->bEndpointAddress) {
  464                 case USB_CONTROL_ENDPOINT:
  465                         pipe->methods = &slhci_root_ctrl_methods;
  466                         break;
  467                 case UE_DIR_IN | SLHCI_INTR_ENDPT:
  468                         pipe->methods = &slhci_root_intr_methods;
  469                         break;
  470                 default:
  471                         printf("open:endpointErr!\n");
  472                         return USBD_INVAL;
  473                 }
  474         } else {
  475                 switch (ed->bmAttributes & UE_XFERTYPE) {
  476                 case UE_CONTROL:
  477                         DPRINTF(D_MSG, ("control "));
  478                         pipe->methods = &slhci_device_ctrl_methods;
  479                         break;
  480                 case UE_INTERRUPT:
  481                         DPRINTF(D_MSG, ("interrupt "));
  482                         pipe->methods = &slhci_device_intr_methods;
  483                         break;
  484                 case UE_ISOCHRONOUS:
  485                         DPRINTF(D_MSG, ("isochronous "));
  486                         pipe->methods = &slhci_device_isoc_methods;
  487                         break;
  488                 case UE_BULK:
  489                         DPRINTF(D_MSG, ("bluk "));
  490                         pipe->methods = &slhci_device_bulk_methods;
  491                         break;
  492                 }
  493         }
  494         return USBD_NORMAL_COMPLETION;
  495 }
  496 
  497 void
  498 slhci_softintr(void *arg)
  499 {
  500         DPRINTF(D_TRACE, ("%s()", __FUNCTION__));
  501 }
  502 
  503 void
  504 slhci_poll(struct usbd_bus *bus)
  505 {
  506         DPRINTF(D_TRACE, ("%s()", __FUNCTION__));
  507 }
  508 
  509 /*
  510  * Emulation of interrupt transfer for status change endpoint
  511  * of root hub.
  512  */
  513 void
  514 slhci_poll_hub(void *arg)
  515 {
  516         usbd_xfer_handle xfer = arg;
  517         usbd_pipe_handle pipe = xfer->pipe;
  518         struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
  519         int s;
  520         u_char *p;
  521 
  522         usb_callout(sc->sc_poll_handle, sc->sc_interval, slhci_poll_hub, xfer);
  523 
  524         /* USB spec 11.13.3 (p.260) */
  525         p = KERNADDR(&xfer->dmabuf, 0);
  526         p[0] = 0;
  527         if ((sc->sc_flags & (SLF_INSERT | SLF_RESET))) {
  528                 p[0] = 2;
  529                 DPRINTF(D_TRACE, ("!"));
  530         }
  531 
  532         /* no change, return NAK */
  533         if (p[0] == 0)
  534                 return;
  535 
  536         xfer->actlen = 1;
  537         xfer->status = USBD_NORMAL_COMPLETION;
  538         s = splusb();
  539         xfer->device->bus->intr_context++;
  540         usb_transfer_complete(xfer);
  541         xfer->device->bus->intr_context--;
  542         splx(s);
  543 }
  544 
  545 usbd_status
  546 slhci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size)
  547 {
  548         struct slhci_softc *sc = (struct slhci_softc *)bus;
  549 
  550         DPRINTF(D_MEM, ("SLallocm"));
  551         return usb_allocmem(&sc->sc_bus, size, 0, dma);
  552 }
  553 
  554 void
  555 slhci_freem(struct usbd_bus *bus, usb_dma_t *dma)
  556 {
  557         struct slhci_softc *sc = (struct slhci_softc *)bus;
  558 
  559         DPRINTF(D_MEM, ("SLfreem"));
  560         usb_freemem(&sc->sc_bus, dma);
  561 }
  562 
  563 usbd_xfer_handle
  564 slhci_allocx(struct usbd_bus *bus)
  565 {
  566         struct slhci_softc *sc = (struct slhci_softc *)bus;
  567         usbd_xfer_handle xfer;
  568 
  569         DPRINTF(D_MEM, ("SLallocx"));
  570 
  571         xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
  572         if (xfer) {
  573                 SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
  574 #ifdef DIAGNOSTIC
  575                 if (xfer->busy_free != XFER_FREE) {
  576                         printf("slhci_allocx: xfer=%p not free, 0x%08x\n",
  577                                 xfer, xfer->busy_free);
  578                 }
  579 #endif
  580         } else {
  581                 xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT);
  582         }
  583 
  584         if (xfer) {
  585                 memset(xfer, 0, sizeof(*xfer));
  586 #ifdef DIAGNOSTIC
  587                 xfer->busy_free = XFER_BUSY;
  588 #endif
  589         }
  590 
  591         return xfer;
  592 }
  593 
  594 void
  595 slhci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer)
  596 {
  597         struct slhci_softc *sc = (struct slhci_softc *)bus;
  598 
  599         DPRINTF(D_MEM, ("SLfreex"));
  600 
  601 #ifdef DIAGNOSTIC
  602         if (xfer->busy_free != XFER_BUSY) {
  603                 printf("slhci_freex: xfer=%p not busy, 0x%08x\n",
  604                         xfer, xfer->busy_free);
  605                 return;
  606         }
  607         xfer->busy_free = XFER_FREE;
  608 #endif
  609         SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
  610 }
  611 
  612 void
  613 slhci_noop(usbd_pipe_handle pipe)
  614 {
  615         DPRINTF(D_TRACE, ("%s()", __FUNCTION__));
  616 }
  617 
  618 /*
  619  * Data structures and routines to emulate the root hub.
  620  */
  621 usb_device_descriptor_t slhci_devd = {
  622         USB_DEVICE_DESCRIPTOR_SIZE,
  623         UDESC_DEVICE,           /* type */
  624         {0x01, 0x01},                   /* USB version */
  625         UDCLASS_HUB,            /* class */
  626         UDSUBCLASS_HUB,         /* subclass */
  627         0,                      /* protocol */
  628         64,                     /* max packet */
  629         {USB_VENDOR_SCANLOGIC & 0xff,   /* vendor ID (low)  */
  630          USB_VENDOR_SCANLOGIC >> 8  },  /* vendor ID (high) */
  631         {0} /* ? */,            /* product ID */
  632         {0},                    /* device */
  633         1,                      /* index to manufacturer */
  634         2,                      /* index to product */
  635         0,                      /* index to serial number */
  636         1                       /* number of configurations */
  637 };
  638 
  639 usb_config_descriptor_t slhci_confd = {
  640         USB_CONFIG_DESCRIPTOR_SIZE,
  641         UDESC_CONFIG,
  642         {USB_CONFIG_DESCRIPTOR_SIZE +
  643          USB_INTERFACE_DESCRIPTOR_SIZE +
  644          USB_ENDPOINT_DESCRIPTOR_SIZE},
  645         1,                      /* number of interfaces */
  646         1,                      /* configuration value */
  647         0,                      /* index to configuration */
  648         UC_SELF_POWERED,        /* attributes */
  649         15                      /* max current is 30mA... */
  650 };
  651 
  652 usb_interface_descriptor_t slhci_ifcd = {
  653         USB_INTERFACE_DESCRIPTOR_SIZE,
  654         UDESC_INTERFACE,
  655         0,                      /* interface number */
  656         0,                      /* alternate setting */
  657         1,                      /* number of endpoint */
  658         UICLASS_HUB,            /* class */
  659         UISUBCLASS_HUB,         /* subclass */
  660         0,                      /* protocol */
  661         0                       /* index to interface */
  662 };
  663 
  664 usb_endpoint_descriptor_t slhci_endpd = {
  665         USB_ENDPOINT_DESCRIPTOR_SIZE,
  666         UDESC_ENDPOINT,
  667         UE_DIR_IN | SLHCI_INTR_ENDPT,   /* endpoint address */
  668         UE_INTERRUPT,           /* attributes */
  669         {8},                    /* max packet size */
  670         255                     /* interval */
  671 };
  672 
  673 usb_hub_descriptor_t slhci_hubd = {
  674         USB_HUB_DESCRIPTOR_SIZE,
  675         UDESC_HUB,
  676         1,                      /* number of ports */
  677         {UHD_PWR_INDIVIDUAL | UHD_OC_NONE, 0},  /* hub characteristics */
  678         20 /* ? */,             /* 5:power on to power good */
  679         50,                     /* 6:maximum current */
  680         { 0x00 },               /* both ports are removable */
  681         { 0x00 }                /* port power control mask */
  682 };
  683 
  684 static int
  685 slhci_str(usb_string_descriptor_t *p, int l, char *s)
  686 {
  687         int i;
  688 
  689         if (l == 0)
  690                 return 0;
  691         p->bLength = 2 * strlen(s) + 2;
  692         if (l == 1)
  693                 return 1;
  694         p->bDescriptorType = UDESC_STRING;
  695         l -= 2;
  696         for (i = 0; s[i] && l > 1; i++, l -= 2)
  697                 USETW2(p->bString[i], 0, s[i]);
  698         return 2 * i + 2;
  699 }
  700 
  701 usbd_status
  702 slhci_root_ctrl_transfer(usbd_xfer_handle xfer)
  703 {
  704         usbd_status error;
  705 
  706         DPRINTF(D_TRACE, ("SLRCtrans "));
  707 
  708         /* Insert last in queue */
  709         error = usb_insert_transfer(xfer);
  710         if (error) {
  711                 DPRINTF(D_MSG, ("usb_insert_transfer returns err! "));
  712                 return error;
  713         }
  714 
  715         /*
  716          * Pipe isn't running (otherwise error would be USBD_INPROG),
  717          * so start it first.
  718          */
  719         return slhci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
  720 }
  721 
  722 usbd_status
  723 slhci_root_ctrl_start(usbd_xfer_handle xfer)
  724 {
  725         struct slhci_softc *sc = (struct slhci_softc *)xfer->pipe->device->bus;
  726         usb_device_request_t *req;
  727         int len, value, index, l, s, status;
  728         int totlen = 0;
  729         void *buf = NULL;
  730         usb_port_status_t ps;
  731         usbd_status error;
  732         char slbuf[50];
  733         u_int8_t r;
  734 
  735         DPRINTF(D_TRACE, ("SLRCstart "));
  736 
  737         req = &xfer->request;
  738 
  739         len = UGETW(req->wLength);
  740         value = UGETW(req->wValue);
  741         index = UGETW(req->wIndex);
  742 
  743         if (len)
  744                 buf = KERNADDR(&xfer->dmabuf, 0);
  745 
  746 #ifdef SLHCI_DEBUG
  747         if ((slhci_debug & D_TRACE))
  748                 print_req_hub(req);
  749 #endif
  750 
  751 #define C(x,y) ((x) | ((y) << 8))
  752         switch (C(req->bRequest, req->bmRequestType)) {
  753         case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
  754         case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
  755         case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
  756                 DPRINTF(D_MSG, ("UR_CLEAR_FEATURE "));
  757                 break;
  758         case C(UR_GET_CONFIG, UT_READ_DEVICE):
  759                 DPRINTF(D_MSG, ("UR_GET_CONFIG "));
  760                 if (len > 0) {
  761                         *(u_int8_t *)buf = sc->sc_conf;
  762                         totlen = 1;
  763                 }
  764                 break;
  765         case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
  766                 switch (value >> 8) {
  767                 case UDESC_DEVICE:
  768                         DPRINTF(D_MSG, ("UDESC_DEVICE "));
  769                         if ((value & 0xff) != 0) {
  770                                 error = USBD_IOERROR;
  771                                 goto ret;
  772                         }
  773                         totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
  774                         memcpy(buf, &slhci_devd, l);
  775                         break;
  776                 case UDESC_CONFIG:
  777                         DPRINTF(D_MSG, ("UDESC_CONFIG "));
  778                         if ((value & 0xff) != 0) {
  779                                 error = USBD_IOERROR;
  780                                 goto ret;
  781                         }
  782                         totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
  783                         memcpy(buf, &slhci_confd, l);
  784                         buf = (char *)buf + l;
  785                         len -= l;
  786 
  787                         l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE);
  788                         totlen += l;
  789                         memcpy(buf, &slhci_ifcd, l);
  790                         buf = (char *)buf + l;
  791                         len -= l;
  792 
  793                         l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE);
  794                         totlen += l;
  795                         memcpy(buf, &slhci_endpd, l);
  796                         break;
  797                 case UDESC_STRING:
  798                         DPRINTF(D_MSG, ("UDESC_STR "));
  799                         if (len == 0)
  800                                 break;
  801                         *(u_int8_t *)buf = 0;
  802                         totlen = 1;
  803                         switch (value & 0xff) {
  804                         case 0:
  805                                 break;
  806                         case 1: /* Vendor */
  807                                 totlen = slhci_str(buf, len, "ScanLogic");
  808                                 break;
  809                         case 2: /* Product */
  810                                 sprintf(slbuf, "%s root hub", sltypestr[sc->sc_sltype]);
  811                                 totlen = slhci_str(buf, len, slbuf);
  812                                 break;
  813                         default:
  814                                 printf("strerr%d ", value & 0xff);
  815                                 break;
  816                         }
  817                         break;
  818                 default:
  819                         printf("unknownGetDescriptor=%x", value);
  820                         error = USBD_IOERROR;
  821                         break;
  822                 }
  823                 break;
  824         case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
  825                 /* Get Interface, 9.4.4 */
  826                 if (len > 0) {
  827                         *(u_int8_t *)buf = 0;
  828                         totlen = 1;
  829                 }
  830                 break;
  831         case C(UR_GET_STATUS, UT_READ_DEVICE):
  832                 /* Get Status from device, 9.4.5 */
  833                 if (len > 1) {
  834                         USETW(((usb_status_t *)buf)->wStatus, UDS_SELF_POWERED);
  835                         totlen = 2;
  836                 }
  837                 break;
  838         case C(UR_GET_STATUS, UT_READ_INTERFACE):
  839         case C(UR_GET_STATUS, UT_READ_ENDPOINT):
  840                 /* Get Status from interface, endpoint, 9.4.5 */
  841                 if (len > 1) {
  842                         USETW(((usb_status_t *)buf)->wStatus, 0);
  843                         totlen = 2;
  844                 }
  845                 break;
  846         case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
  847                 /* Set Address, 9.4.6 */
  848                 DPRINTF(D_MSG, ("UR_SET_ADDRESS "));
  849                 if (value >= USB_MAX_DEVICES) {
  850                         error = USBD_IOERROR;
  851                         goto ret;
  852                 }
  853                 sc->sc_addr = value;
  854                 break;
  855         case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
  856                 /* Set Configuration, 9.4.7 */
  857                 DPRINTF(D_MSG, ("UR_SET_CONFIG "));
  858                 if (value != 0 && value != 1) {
  859                         error = USBD_IOERROR;
  860                         goto ret;
  861                 }
  862                 sc->sc_conf = value;
  863                 break;
  864         case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
  865                 /* Set Descriptor, 9.4.8, not supported */
  866                 DPRINTF(D_MSG, ("UR_SET_DESCRIPTOR,WRITE_DEVICE not supported\n"));
  867                 break;
  868         case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
  869         case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
  870         case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
  871                 /* Set Feature, 9.4.9, not supported */
  872                 DPRINTF(D_MSG, ("UR_SET_FEATURE not supported\n"));
  873                 error = USBD_IOERROR;
  874                 break;
  875         case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
  876                 /* Set Interface, 9.4.10, not supported */
  877                 break;
  878         case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
  879                 /* Synch Frame, 9.4.11, not supported */
  880                 break;
  881 
  882         /*
  883          * Hub specific requests
  884          */
  885         case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
  886                 /* Clear Hub Feature, 11.16.2.1, not supported */
  887                 DPRINTF(D_MSG, ("ClearHubFeature not supported\n"));
  888                 break;
  889         case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
  890                 /* Clear Port Feature, 11.16.2.2 */
  891                 if (index != 1) {
  892                         error = USBD_IOERROR;
  893                         goto ret;
  894                 }
  895                 switch (value) {
  896                 case UHF_PORT_POWER:
  897                         DPRINTF(D_MSG, ("POWER_OFF "));
  898                         sc->sc_powerstat = POWER_OFF;
  899                         /* x68k Nereid USB controller needs it */
  900                         if (sc->sc_enable_power)
  901                                 sc->sc_enable_power(sc, sc->sc_powerstat);
  902                         break;
  903                 case UHF_PORT_SUSPEND:
  904                         DPRINTF(D_MSG, ("SUSPEND "));
  905                         sl11write(sc, SL11_CTRL,
  906                                 sl11read(sc, SL11_CTRL) & ~SL11_CTRL_SUSPEND);
  907                         break;
  908                 case UHF_C_PORT_CONNECTION:
  909                         sc->sc_change &= ~UPS_C_CONNECT_STATUS;
  910                         break;
  911                 case UHF_C_PORT_RESET:
  912                         sc->sc_change &= ~UPS_C_PORT_RESET;
  913                         break;
  914                 case UHF_PORT_ENABLE:
  915                         break;
  916                 case UHF_C_PORT_SUSPEND:
  917                 case UHF_C_PORT_ENABLE:
  918                 case UHF_C_PORT_OVER_CURRENT:
  919                 default:
  920                         printf("ClrPortFeatERR:value=0x%x ", value);
  921                         error = USBD_IOERROR;
  922                         break;
  923                 }
  924                 //DPRINTF(D_XFER, ("CH=%04x ", sc->sc_change));
  925                 break;
  926         case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER):
  927                 /* Get Bus State, 11.16.2.3, not supported */
  928                 /* shall return a STALL... */
  929                 break;
  930         case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
  931                 /* Get Hub Descriptor, 11.16.2.4 */
  932                 if (value != 0) {
  933                         error = USBD_IOERROR;
  934                         goto ret;
  935                 }
  936                 l = min(len, USB_HUB_DESCRIPTOR_SIZE);
  937                 totlen = l;
  938                 memcpy(buf, &slhci_hubd, l);
  939                 break;
  940         case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
  941                 /* Get Hub Status, 11.16.2.5 */
  942                 DPRINTF(D_MSG, ("UR_GET_STATUS RCD"));
  943                 if (len != 4) {
  944                         error = USBD_IOERROR;
  945                         goto ret;
  946                 }
  947                 memset(buf, 0, len);
  948                 totlen = len;
  949                 break;
  950         case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
  951                 /* Get Port Status, 11.16.2.6 */
  952                 if (index != 1 || len != 4) {
  953                         printf("index=%d,len=%d ", index, len);
  954                         error = USBD_IOERROR;
  955                         goto ret;
  956                 }
  957                 /*
  958                  * change
  959                  * o port is always enabled.
  960                  * o cannot detect over current.
  961                  */
  962                 s = splusb();
  963                 sc->sc_change &= ~(UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET);
  964                 if ((sc->sc_flags & SLF_INSERT)) {
  965                         sc->sc_flags &= ~SLF_INSERT;
  966                         sc->sc_change |= UPS_C_CONNECT_STATUS;
  967                 }
  968                 if ((sc->sc_flags & SLF_RESET)) {
  969                         sc->sc_flags &= ~SLF_RESET;
  970                         sc->sc_change |= UPS_C_PORT_RESET;
  971                 }
  972                 splx(s);
  973                 /*
  974                  * XXX It can recognize that device is detached,
  975                  * while there is sl11_speed() here.
  976                  */
  977                 if (sc->sc_change)
  978                         sl11_speed(sc);
  979                 /*
  980                  * status
  981                  * o port is always enabled.
  982                  * o cannot detect over current.
  983                  */
  984                 status = 0;
  985                 if (sc->sc_connect)
  986                         status |= UPS_CURRENT_CONNECT_STATUS | UPS_PORT_ENABLED;
  987                 r = sl11read(sc, SL11_CTRL);
  988                 if (r & SL11_CTRL_SUSPEND)
  989                         status |= UPS_SUSPEND;
  990                 if (sc->sc_powerstat)
  991                         status |= UPS_PORT_POWER;
  992                 if (!sc->sc_fullspeed)
  993                         status |= UPS_LOW_SPEED;
  994 
  995                 //DPRINTF(D_XFER, ("ST=%04x,CH=%04x ", status, sc->sc_change));
  996                 USETW(ps.wPortStatus, status);
  997                 USETW(ps.wPortChange, sc->sc_change);
  998                 l = min(len, sizeof(ps));
  999                 memcpy(buf, &ps, l);
 1000                 totlen = l;
 1001                 break;
 1002         case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
 1003                 /* Set Hub Descriptor, 11.16.2.7, not supported */
 1004                 /* STALL ? */
 1005                 error = USBD_IOERROR;
 1006                 break;
 1007         case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
 1008                 /* Set Hub Feature, 11.16.2.8, not supported */
 1009                 break;
 1010         case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
 1011                 /* Set Port Feature, 11.16.2.9 */
 1012                 if (index != 1) {
 1013                         printf("index=%d ", index);
 1014                         error = USBD_IOERROR;
 1015                         goto ret;
 1016                 }
 1017                 switch (value) {
 1018                 case UHF_PORT_RESET:
 1019                         DPRINTF(D_MSG, ("PORT_RESET "));
 1020                         sl11_reset(sc);
 1021                         sl11_speed(sc);
 1022                         sc->sc_change = 0;
 1023                         break;
 1024                 case UHF_PORT_POWER:
 1025                         DPRINTF(D_MSG, ("PORT_POWER "));
 1026                         sc->sc_powerstat = POWER_ON;
 1027                         /* x68k Nereid USB controller needs it */
 1028                         if (sc->sc_enable_power)
 1029                                 sc->sc_enable_power(sc, sc->sc_powerstat);
 1030                         delay_ms(25);
 1031                         break;
 1032                 default:
 1033                         printf("SetPortFeatERR=0x%x ", value);
 1034                         error = USBD_IOERROR;
 1035                         break;
 1036                 }
 1037                 break;
 1038         default:
 1039                 DPRINTF(D_MSG, ("ioerr(UR=%02x,UT=%02x) ",
 1040                         req->bRequest, req->bmRequestType));
 1041                 error = USBD_IOERROR;
 1042                 goto ret;
 1043         }
 1044         xfer->actlen = totlen;
 1045         error = USBD_NORMAL_COMPLETION;
 1046  ret:
 1047         xfer->status = error;
 1048         s = splusb();
 1049         usb_transfer_complete(xfer);
 1050         splx(s);
 1051         return USBD_IN_PROGRESS;
 1052 }
 1053 
 1054 void
 1055 slhci_root_ctrl_abort(usbd_xfer_handle xfer)
 1056 {
 1057         DPRINTF(D_TRACE, ("SLRCabort "));
 1058 }
 1059 
 1060 void
 1061 slhci_root_ctrl_close(usbd_pipe_handle pipe)
 1062 {
 1063         DPRINTF(D_TRACE, ("SLRCclose "));
 1064 }
 1065 
 1066 void
 1067 slhci_root_ctrl_done(usbd_xfer_handle xfer)
 1068 {
 1069         DPRINTF(D_TRACE, ("SLRCdone\n"));
 1070 }
 1071 
 1072 static usbd_status
 1073 slhci_root_intr_transfer(usbd_xfer_handle xfer)
 1074 {
 1075         usbd_status error;
 1076 
 1077         DPRINTF(D_TRACE, ("SLRItransfer "));
 1078 
 1079         /* Insert last in queue */
 1080         error = usb_insert_transfer(xfer);
 1081         if (error)
 1082                 return error;
 1083 
 1084         /*
 1085          * Pipe isn't running (otherwise error would be USBD_INPROG),
 1086          * start first.
 1087          */
 1088         return slhci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
 1089 }
 1090 
 1091 static usbd_status
 1092 slhci_root_intr_start(usbd_xfer_handle xfer)
 1093 {
 1094         usbd_pipe_handle pipe = xfer->pipe;
 1095         struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
 1096 
 1097         DPRINTF(D_TRACE, ("SLRIstart "));
 1098 
 1099         sc->sc_interval = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval);
 1100         usb_callout(sc->sc_poll_handle, sc->sc_interval, slhci_poll_hub, xfer);
 1101         sc->sc_intr_xfer = xfer;
 1102         return USBD_IN_PROGRESS;
 1103 }
 1104 
 1105 static void
 1106 slhci_root_intr_abort(usbd_xfer_handle xfer)
 1107 {
 1108         DPRINTF(D_TRACE, ("SLRIabort "));
 1109 }
 1110 
 1111 static void
 1112 slhci_root_intr_close(usbd_pipe_handle pipe)
 1113 {
 1114         struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
 1115 
 1116         DPRINTF(D_TRACE, ("SLRIclose "));
 1117 
 1118         usb_uncallout(sc->sc_poll_handle, slhci_poll_hub, sc->sc_intr_xfer);
 1119         sc->sc_intr_xfer = NULL;
 1120 }
 1121 
 1122 static void
 1123 slhci_root_intr_done(usbd_xfer_handle xfer)
 1124 {
 1125         //DPRINTF(D_XFER, ("RIdn "));
 1126 }
 1127 
 1128 static usbd_status
 1129 slhci_device_ctrl_transfer(usbd_xfer_handle xfer)
 1130 {
 1131         usbd_status error;
 1132 
 1133         DPRINTF(D_TRACE, ("C"));
 1134 
 1135         error = usb_insert_transfer(xfer);
 1136         if (error)
 1137                 return error;
 1138 
 1139         return slhci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
 1140 }
 1141 
 1142 static usbd_status
 1143 slhci_device_ctrl_start(usbd_xfer_handle xfer)
 1144 {
 1145         usb_device_request_t *req = &xfer->request;
 1146         usbd_pipe_handle pipe = xfer->pipe;
 1147         struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
 1148         usbd_status status =  USBD_NORMAL_COMPLETION;
 1149         void *buf;
 1150         int pid = SL11_PID_OUT;
 1151         int len, actlen, size;
 1152         int s;
 1153         u_int8_t toggle = 0;
 1154 
 1155         DPRINTF(D_TRACE, ("st "));
 1156 #ifdef SLHCI_DEBUG
 1157         if ((slhci_debug & D_TRACE))
 1158                 print_req_hub(req);
 1159 #endif
 1160 
 1161         /* SETUP transaction */
 1162         if (slhci_transaction(sc, pipe, SL11_PID_SETUP,
 1163                         sizeof(*req), (u_char*)req, toggle) == -1) {
 1164                 status = USBD_IOERROR;
 1165                 goto ret;
 1166         }
 1167         toggle ^= SL11_EPCTRL_DATATOGGLE;
 1168 
 1169         /* DATA transaction */
 1170         actlen = 0;
 1171         len = UGETW(req->wLength);
 1172         if (len) {
 1173                 buf = KERNADDR(&xfer->dmabuf, 0);
 1174                 if (req->bmRequestType & UT_READ)
 1175                         pid = SL11_PID_IN;
 1176                 for (; actlen < len; ) {
 1177                         size = min(len - actlen, 8/* Minimum size */);
 1178                         if (slhci_transaction(sc, pipe, pid, size, buf, toggle) == -1)
 1179                                 break;
 1180                         toggle ^= SL11_EPCTRL_DATATOGGLE;
 1181                         (u_char*)buf += size;
 1182                         actlen += size;
 1183                 }
 1184         }
 1185         xfer->actlen = actlen;
 1186 
 1187         /* ACK (status) */
 1188         if (pid == SL11_PID_IN)
 1189                 pid = SL11_PID_OUT;
 1190         else
 1191                 pid = SL11_PID_IN;
 1192         if (slhci_transaction(sc, pipe, pid, 0, NULL, toggle) == -1)
 1193                 status = USBD_IOERROR;
 1194 
 1195  ret:
 1196         xfer->status = status;
 1197 
 1198 #ifdef SLHCI_DEBUG
 1199         if((slhci_debug & D_TRACE) && UGETW(req->wLength) > 0){
 1200                 int i;
 1201                 for(i=0; i < UGETW(req->wLength); i++)
 1202                         printf("%02x", *(unsigned char*)(KERNADDR(&xfer->dmabuf, i)));
 1203                 printf(" ");
 1204         }
 1205 #endif
 1206         s = splusb();
 1207         usb_transfer_complete(xfer);
 1208         splx(s);
 1209         return USBD_IN_PROGRESS;
 1210 }
 1211 
 1212 static void
 1213 slhci_device_ctrl_abort(usbd_xfer_handle xfer)
 1214 {
 1215         DPRINTF(D_TRACE, ("Cab "));
 1216         slhci_abort_xfer(xfer, USBD_CANCELLED);
 1217 }
 1218 
 1219 static void
 1220 slhci_device_ctrl_close(usbd_pipe_handle pipe)
 1221 {
 1222         DPRINTF(D_TRACE, ("Ccl "));
 1223 }
 1224 
 1225 static void
 1226 slhci_device_ctrl_done(usbd_xfer_handle xfer)
 1227 {
 1228         DPRINTF(D_TRACE, ("Cdn "));
 1229 }
 1230 
 1231 static usbd_status
 1232 slhci_device_intr_transfer(usbd_xfer_handle xfer)
 1233 {
 1234         usbd_status error;
 1235 
 1236         DPRINTF(D_TRACE, ("INTRtrans "));
 1237 
 1238         error = usb_insert_transfer(xfer);
 1239         if (error)
 1240                 return error;
 1241 
 1242         return slhci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
 1243 }
 1244 
 1245 static usbd_status
 1246 slhci_device_intr_start(usbd_xfer_handle xfer)
 1247 {
 1248         usbd_pipe_handle pipe = xfer->pipe;
 1249         struct slhci_xfer *sx;
 1250 
 1251         DPRINTF(D_TRACE, ("INTRstart "));
 1252 
 1253         sx = malloc(sizeof(*sx), M_USB, M_NOWAIT);
 1254         if (sx == NULL)
 1255                 goto reterr;
 1256         memset(sx, 0, sizeof(*sx));
 1257         sx->sx_xfer  = xfer;
 1258         xfer->hcpriv = sx;
 1259 
 1260         /* initialize callout */
 1261         usb_callout_init(sx->sx_callout_t);
 1262         usb_callout(sx->sx_callout_t, 
 1263                 MS_TO_TICKS(pipe->endpoint->edesc->bInterval),
 1264                 slhci_poll_device, sx);
 1265 
 1266         /* ACK */
 1267         return USBD_IN_PROGRESS;
 1268 
 1269  reterr:
 1270         return USBD_IOERROR;
 1271 }
 1272 
 1273 static void
 1274 slhci_poll_device(void *arg)
 1275 {
 1276         struct slhci_xfer *sx = (struct slhci_xfer *)arg;
 1277         usbd_xfer_handle xfer = sx->sx_xfer;
 1278         usbd_pipe_handle pipe = xfer->pipe;
 1279         struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus;
 1280         void *buf;
 1281         int pid;
 1282         int r;
 1283         int s;
 1284 
 1285         DPRINTF(D_TRACE, ("pldev"));
 1286 
 1287         usb_callout(sx->sx_callout_t,
 1288                 MS_TO_TICKS(pipe->endpoint->edesc->bInterval),
 1289                 slhci_poll_device, sx);
 1290 
 1291         /* interrupt transfer */
 1292         pid = (UE_GET_DIR(pipe->endpoint->edesc->bEndpointAddress) == UE_DIR_IN)
 1293             ? SL11_PID_IN : SL11_PID_OUT;
 1294         buf = KERNADDR(&xfer->dmabuf, 0);
 1295 
 1296         r = slhci_transaction(sc, pipe, pid, xfer->length, buf, 0/*toggle*/);
 1297         if (r < 0) {
 1298                 DPRINTF(D_MSG, ("%s error", __FUNCTION__));
 1299                 return;
 1300         }
 1301         /* no change, return NAK */
 1302         if (r == 0)
 1303                 return;
 1304 
 1305         xfer->status = USBD_NORMAL_COMPLETION;
 1306         s = splusb();
 1307         xfer->device->bus->intr_context++;
 1308         usb_transfer_complete(xfer);
 1309         xfer->device->bus->intr_context--;
 1310         splx(s);
 1311 }
 1312 
 1313 static void
 1314 slhci_device_intr_abort(usbd_xfer_handle xfer)
 1315 {
 1316         struct slhci_xfer *sx;
 1317 
 1318         DPRINTF(D_TRACE, ("INTRabort "));
 1319 
 1320         sx = xfer->hcpriv;
 1321         if (sx) {
 1322                 usb_uncallout(sx->sx_callout_t, slhci_poll_device, sx);
 1323                 free(sx, M_USB);
 1324                 xfer->hcpriv = NULL;
 1325         } else {
 1326                 printf("%s: sx == NULL!\n", __FUNCTION__);
 1327         }
 1328         slhci_abort_xfer(xfer, USBD_CANCELLED);
 1329 }
 1330 
 1331 static void
 1332 slhci_device_intr_close(usbd_pipe_handle pipe)
 1333 {
 1334         DPRINTF(D_TRACE, ("INTRclose "));
 1335 }
 1336 
 1337 static void
 1338 slhci_device_intr_done(usbd_xfer_handle xfer)
 1339 {
 1340         DPRINTF(D_TRACE, ("INTRdone "));
 1341 }
 1342 
 1343 static usbd_status
 1344 slhci_device_isoc_transfer(usbd_xfer_handle xfer)
 1345 {
 1346         DPRINTF(D_TRACE, ("S"));
 1347         return USBD_NORMAL_COMPLETION;
 1348 }
 1349 
 1350 static usbd_status
 1351 slhci_device_isoc_start(usbd_xfer_handle xfer)
 1352 {
 1353         DPRINTF(D_TRACE, ("st "));
 1354         return USBD_NORMAL_COMPLETION;
 1355 }
 1356 
 1357 static void
 1358 slhci_device_isoc_abort(usbd_xfer_handle xfer)
 1359 {
 1360         DPRINTF(D_TRACE, ("Sab "));
 1361 }
 1362 
 1363 static void
 1364 slhci_device_isoc_close(usbd_pipe_handle pipe)
 1365 {
 1366         DPRINTF(D_TRACE, ("Scl "));
 1367 }
 1368 
 1369 static void
 1370 slhci_device_isoc_done(usbd_xfer_handle xfer)
 1371 {
 1372         DPRINTF(D_TRACE, ("Sdn "));
 1373 }
 1374 
 1375 static usbd_status
 1376 slhci_device_bulk_transfer(usbd_xfer_handle xfer)
 1377 {
 1378         DPRINTF(D_TRACE, ("B"));
 1379         return USBD_NORMAL_COMPLETION;
 1380 }
 1381 
 1382 static usbd_status
 1383 slhci_device_bulk_start(usbd_xfer_handle xfer)
 1384 {
 1385         DPRINTF(D_TRACE, ("st "));
 1386         return USBD_NORMAL_COMPLETION;
 1387 }
 1388 
 1389 static void
 1390 slhci_device_bulk_abort(usbd_xfer_handle xfer)
 1391 {
 1392         DPRINTF(D_TRACE, ("Bab "));
 1393 }
 1394 
 1395 static void
 1396 slhci_device_bulk_close(usbd_pipe_handle pipe)
 1397 {
 1398         DPRINTF(D_TRACE, ("Bcl "));
 1399 }
 1400 
 1401 static void
 1402 slhci_device_bulk_done(usbd_xfer_handle xfer)
 1403 {
 1404         DPRINTF(D_TRACE, ("Bdn "));
 1405 }
 1406 
 1407 #define DATA0_RD        (0x03)
 1408 #define DATA0_WR        (0x07)
 1409 #define SLHCI_TIMEOUT   (5000)
 1410 
 1411 /*
 1412  * Do a transaction.
 1413  * return 1 if ACK, 0 if NAK, -1 if error.
 1414  */
 1415 static int
 1416 slhci_transaction(struct slhci_softc *sc, usbd_pipe_handle pipe,
 1417         u_int8_t pid, int len, u_char *buf, u_int8_t toggle)
 1418 {
 1419 #ifdef SLHCI_DEBUG
 1420         char str[64];
 1421         int i;
 1422 #endif
 1423         int timeout;
 1424         int ls_via_hub = 0;
 1425         int pl;
 1426         u_int8_t isr;
 1427         u_int8_t result = 0;
 1428         u_int8_t devaddr = pipe->device->address;
 1429         u_int8_t endpointaddr = pipe->endpoint->edesc->bEndpointAddress;
 1430         u_int8_t endpoint;
 1431         u_int8_t cmd = DATA0_RD;
 1432 
 1433         endpoint = UE_GET_ADDR(endpointaddr);
 1434         DPRINTF(D_XFER, ("\n(%x,%d%s%d,%d) ",
 1435                 pid, len, (pid == SL11_PID_IN) ? "<-" : "->", devaddr, endpoint));
 1436 
 1437         /* Set registers */
 1438         sl11write(sc, SL11_E0ADDR, 0x40);
 1439         sl11write(sc, SL11_E0LEN,  len);
 1440         sl11write(sc, SL11_E0PID,  (pid << 4) + endpoint);
 1441         sl11write(sc, SL11_E0DEV,  devaddr);
 1442 
 1443         /* Set buffer unless PID_IN */
 1444         if (pid != SL11_PID_IN) {
 1445                 if (len > 0)
 1446                         sl11write_region(sc, 0x40, buf, len);
 1447                 cmd = DATA0_WR;
 1448         }
 1449 
 1450         /* timing ? */
 1451         pl = (len >> 3) + 3;
 1452 
 1453         /* Low speed device via HUB */
 1454         /* XXX does not work... */
 1455         if ((sc->sc_fullspeed) && pipe->device->speed == USB_SPEED_LOW) {
 1456                 pl = len + 16;
 1457                 cmd |= SL11_EPCTRL_PREAMBLE;
 1458 
 1459                 /*
 1460                  * SL811HS/T rev 1.2 has a bug, when it got PID_IN
 1461                  * from LowSpeed device via HUB.
 1462                  */
 1463                 if (sc->sc_sltype == SLTYPE_SL811HS_R12 && pid == SL11_PID_IN) {
 1464                         ls_via_hub = 1;
 1465                         DPRINTF(D_MSG, ("LSvH "));
 1466                 }
 1467         }
 1468 
 1469         /* timing ? */
 1470         if (sl11read(sc, SL811_CSOF) <= (u_int8_t)pl)
 1471                 cmd |= SL11_EPCTRL_SOF;
 1472 
 1473         /* Transfer */
 1474         sl11write(sc, SL11_ISR, 0xff);
 1475         sl11write(sc, SL11_E0CTRL, cmd | toggle);
 1476 
 1477         /* Polling */
 1478         for (timeout = SLHCI_TIMEOUT; timeout; timeout--) {
 1479                 isr = sl11read(sc, SL11_ISR);
 1480                 if ((isr & SL11_ISR_USBA))
 1481                         break;
 1482         }
 1483 
 1484         /* Check result status */
 1485         result = sl11read(sc, SL11_E0STAT);
 1486         if (!(result & SL11_EPSTAT_NAK) && ls_via_hub) {
 1487                 /* Resend PID_IN within 20usec */
 1488                 sl11write(sc, SL11_ISR, 0xff);
 1489                 sl11write(sc, SL11_E0CTRL, SL11_EPCTRL_ARM);
 1490         }
 1491 
 1492         sl11write(sc, SL11_ISR, 0xff);
 1493 
 1494         DPRINTF(D_XFER, ("t=%d i=%x ", SLHCI_TIMEOUT - timeout, isr));
 1495 #if SLHCI_DEBUG
 1496         bitmask_snprintf(result,
 1497                 "\2\x8STALL\7NAK\6OV\5SETUP\4DATA1\3TIMEOUT\2ERR\1ACK",
 1498                 str, sizeof(str));
 1499         DPRINTF(D_XFER, ("STAT=%s ", str));
 1500 #endif
 1501 
 1502         if ((result & SL11_EPSTAT_ERROR))
 1503                 return -1;
 1504 
 1505         if ((result & SL11_EPSTAT_NAK))
 1506                 return 0;
 1507 
 1508         /* Read buffer if PID_IN */
 1509         if (pid == SL11_PID_IN && len > 0) {
 1510                 sl11read_region(sc, buf, 0x40, len);
 1511 #if SLHCI_DEBUG
 1512                 for (i = 0; i < len; i++)
 1513                         DPRINTF(D_XFER, ("%02X ", buf[i]));
 1514 #endif
 1515         }
 1516 
 1517         return 1;
 1518 }
 1519 
 1520 void
 1521 slhci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
 1522 {
 1523         xfer->status = status;
 1524         usb_transfer_complete(xfer);
 1525 }
 1526 
 1527 void
 1528 slhci_device_clear_toggle(usbd_pipe_handle pipe)
 1529 {
 1530         DPRINTF(D_TRACE, ("SLdevice_clear_toggle "));
 1531 }
 1532 
 1533 #ifdef SLHCI_DEBUG
 1534 void
 1535 print_req(usb_device_request_t *r)
 1536 {
 1537         char *xmes[]={
 1538                 "GETSTAT",
 1539                 "CLRFEAT",
 1540                 "res",
 1541                 "SETFEAT",
 1542                 "res",
 1543                 "SETADDR",
 1544                 "GETDESC",
 1545                 "SETDESC",
 1546                 "GETCONF",
 1547                 "SETCONF",
 1548                 "GETIN/F",
 1549                 "SETIN/F",
 1550                 "SYNC_FR"
 1551         };
 1552         int req, type, value, index, len;
 1553 
 1554         req   = r->bRequest;
 1555         type  = r->bmRequestType;
 1556         value = UGETW(r->wValue);
 1557         index = UGETW(r->wIndex);
 1558         len   = UGETW(r->wLength);
 1559 
 1560         printf("%x,%s,v=%d,i=%d,l=%d ",
 1561                 type, xmes[req], value, index, len);
 1562 }
 1563 
 1564 void
 1565 print_req_hub(usb_device_request_t *r)
 1566 {
 1567         struct {
 1568                 int req;
 1569                 int type;
 1570                 char *str;
 1571         } conf[] = {
 1572                 { 1, 0x20, "ClrHubFeat"  },
 1573                 { 1, 0x23, "ClrPortFeat" },
 1574                 { 2, 0xa3, "GetBusState" },
 1575                 { 6, 0xa0, "GetHubDesc"  },
 1576                 { 0, 0xa0, "GetHubStat"  },
 1577                 { 0, 0xa3, "GetPortStat" },
 1578                 { 7, 0x20, "SetHubDesc"  },
 1579                 { 3, 0x20, "SetHubFeat"  },
 1580                 { 3, 0x23, "SetPortFeat" },
 1581                 {-1, 0, NULL},
 1582         };
 1583         int i;
 1584         int value, index, len;
 1585 
 1586         value = UGETW(r->wValue);
 1587         index = UGETW(r->wIndex);
 1588         len   = UGETW(r->wLength);
 1589         for (i = 0; ; i++) {
 1590                 if (conf[i].req == -1 )
 1591                         return print_req(r);
 1592                 if (r->bmRequestType == conf[i].type && r->bRequest == conf[i].req) {
 1593                         printf("%s", conf[i].str);
 1594                         break;
 1595                 }
 1596         }
 1597         printf(",v=%d,i=%d,l=%d ", value, index, len);
 1598 }
 1599 
 1600 void
 1601 print_dumpreg(struct slhci_softc *sc)
 1602 {
 1603         printf("00=%02x,01=%02x,02=%02x,03=%02x,04=%02x,"
 1604                "08=%02x,09=%02x,0A=%02x,0B=%02x,0C=%02x,",
 1605                 sl11read(sc, 0),  sl11read(sc, 1),
 1606                 sl11read(sc, 2),  sl11read(sc, 3),
 1607                 sl11read(sc, 4),  sl11read(sc, 8),
 1608                 sl11read(sc, 9),  sl11read(sc, 10),
 1609                 sl11read(sc, 11), sl11read(sc, 12)
 1610         );
 1611         printf("CR1=%02x,IER=%02x,0D=%02x,0E=%02x,0F=%02x ",
 1612                 sl11read(sc, 5), sl11read(sc, 6),
 1613                 sl11read(sc, 13), sl11read(sc, 14), sl11read(sc, 15)
 1614         );
 1615 }
 1616 
 1617 void
 1618 print_xfer(usbd_xfer_handle xfer)
 1619 {
 1620         printf("xfer: length=%d, actlen=%d, flags=%x, timeout=%d,",
 1621                 xfer->length, xfer->actlen, xfer->flags, xfer->timeout);
 1622         printf("request{ ");
 1623         print_req_hub(&xfer->request);
 1624         printf("} ");
 1625 }
 1626 #endif /* SLHCI_DEBUG */

Cache object: 52e5dfbb667fdb8af020b6c564cddc5e


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