1 /* $NetBSD: sl811hs.c,v 1.7 2005/12/11 12:21:28 christos 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.7 2005/12/11 12:21:28 christos 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, const 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 const 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 ? "\20\x8""D+\7RESUME\6INSERT\5SOF\4res\3""BABBLE\2USBB\1USBA" 444 : "\20\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, const 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 snprintf(slbuf, sizeof(slbuf), "%s root hub", 811 sltypestr[sc->sc_sltype]); 812 totlen = slhci_str(buf, len, slbuf); 813 break; 814 default: 815 printf("strerr%d ", value & 0xff); 816 break; 817 } 818 break; 819 default: 820 printf("unknownGetDescriptor=%x", value); 821 error = USBD_IOERROR; 822 break; 823 } 824 break; 825 case C(UR_GET_INTERFACE, UT_READ_INTERFACE): 826 /* Get Interface, 9.4.4 */ 827 if (len > 0) { 828 *(u_int8_t *)buf = 0; 829 totlen = 1; 830 } 831 break; 832 case C(UR_GET_STATUS, UT_READ_DEVICE): 833 /* Get Status from device, 9.4.5 */ 834 if (len > 1) { 835 USETW(((usb_status_t *)buf)->wStatus, UDS_SELF_POWERED); 836 totlen = 2; 837 } 838 break; 839 case C(UR_GET_STATUS, UT_READ_INTERFACE): 840 case C(UR_GET_STATUS, UT_READ_ENDPOINT): 841 /* Get Status from interface, endpoint, 9.4.5 */ 842 if (len > 1) { 843 USETW(((usb_status_t *)buf)->wStatus, 0); 844 totlen = 2; 845 } 846 break; 847 case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): 848 /* Set Address, 9.4.6 */ 849 DPRINTF(D_MSG, ("UR_SET_ADDRESS ")); 850 if (value >= USB_MAX_DEVICES) { 851 error = USBD_IOERROR; 852 goto ret; 853 } 854 sc->sc_addr = value; 855 break; 856 case C(UR_SET_CONFIG, UT_WRITE_DEVICE): 857 /* Set Configuration, 9.4.7 */ 858 DPRINTF(D_MSG, ("UR_SET_CONFIG ")); 859 if (value != 0 && value != 1) { 860 error = USBD_IOERROR; 861 goto ret; 862 } 863 sc->sc_conf = value; 864 break; 865 case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE): 866 /* Set Descriptor, 9.4.8, not supported */ 867 DPRINTF(D_MSG, ("UR_SET_DESCRIPTOR,WRITE_DEVICE not supported\n")); 868 break; 869 case C(UR_SET_FEATURE, UT_WRITE_DEVICE): 870 case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): 871 case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): 872 /* Set Feature, 9.4.9, not supported */ 873 DPRINTF(D_MSG, ("UR_SET_FEATURE not supported\n")); 874 error = USBD_IOERROR; 875 break; 876 case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): 877 /* Set Interface, 9.4.10, not supported */ 878 break; 879 case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT): 880 /* Synch Frame, 9.4.11, not supported */ 881 break; 882 883 /* 884 * Hub specific requests 885 */ 886 case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE): 887 /* Clear Hub Feature, 11.16.2.1, not supported */ 888 DPRINTF(D_MSG, ("ClearHubFeature not supported\n")); 889 break; 890 case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER): 891 /* Clear Port Feature, 11.16.2.2 */ 892 if (index != 1) { 893 error = USBD_IOERROR; 894 goto ret; 895 } 896 switch (value) { 897 case UHF_PORT_POWER: 898 DPRINTF(D_MSG, ("POWER_OFF ")); 899 sc->sc_powerstat = POWER_OFF; 900 /* x68k Nereid USB controller needs it */ 901 if (sc->sc_enable_power) 902 sc->sc_enable_power(sc, sc->sc_powerstat); 903 break; 904 case UHF_PORT_SUSPEND: 905 DPRINTF(D_MSG, ("SUSPEND ")); 906 sl11write(sc, SL11_CTRL, 907 sl11read(sc, SL11_CTRL) & ~SL11_CTRL_SUSPEND); 908 break; 909 case UHF_C_PORT_CONNECTION: 910 sc->sc_change &= ~UPS_C_CONNECT_STATUS; 911 break; 912 case UHF_C_PORT_RESET: 913 sc->sc_change &= ~UPS_C_PORT_RESET; 914 break; 915 case UHF_PORT_ENABLE: 916 break; 917 case UHF_C_PORT_SUSPEND: 918 case UHF_C_PORT_ENABLE: 919 case UHF_C_PORT_OVER_CURRENT: 920 default: 921 printf("ClrPortFeatERR:value=0x%x ", value); 922 error = USBD_IOERROR; 923 break; 924 } 925 //DPRINTF(D_XFER, ("CH=%04x ", sc->sc_change)); 926 break; 927 case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER): 928 /* Get Bus State, 11.16.2.3, not supported */ 929 /* shall return a STALL... */ 930 break; 931 case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): 932 /* Get Hub Descriptor, 11.16.2.4 */ 933 if (value != 0) { 934 error = USBD_IOERROR; 935 goto ret; 936 } 937 l = min(len, USB_HUB_DESCRIPTOR_SIZE); 938 totlen = l; 939 memcpy(buf, &slhci_hubd, l); 940 break; 941 case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): 942 /* Get Hub Status, 11.16.2.5 */ 943 DPRINTF(D_MSG, ("UR_GET_STATUS RCD")); 944 if (len != 4) { 945 error = USBD_IOERROR; 946 goto ret; 947 } 948 memset(buf, 0, len); 949 totlen = len; 950 break; 951 case C(UR_GET_STATUS, UT_READ_CLASS_OTHER): 952 /* Get Port Status, 11.16.2.6 */ 953 if (index != 1 || len != 4) { 954 printf("index=%d,len=%d ", index, len); 955 error = USBD_IOERROR; 956 goto ret; 957 } 958 /* 959 * change 960 * o port is always enabled. 961 * o cannot detect over current. 962 */ 963 s = splusb(); 964 sc->sc_change &= ~(UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET); 965 if ((sc->sc_flags & SLF_INSERT)) { 966 sc->sc_flags &= ~SLF_INSERT; 967 sc->sc_change |= UPS_C_CONNECT_STATUS; 968 } 969 if ((sc->sc_flags & SLF_RESET)) { 970 sc->sc_flags &= ~SLF_RESET; 971 sc->sc_change |= UPS_C_PORT_RESET; 972 } 973 splx(s); 974 /* 975 * XXX It can recognize that device is detached, 976 * while there is sl11_speed() here. 977 */ 978 if (sc->sc_change) 979 sl11_speed(sc); 980 /* 981 * status 982 * o port is always enabled. 983 * o cannot detect over current. 984 */ 985 status = 0; 986 if (sc->sc_connect) 987 status |= UPS_CURRENT_CONNECT_STATUS | UPS_PORT_ENABLED; 988 r = sl11read(sc, SL11_CTRL); 989 if (r & SL11_CTRL_SUSPEND) 990 status |= UPS_SUSPEND; 991 if (sc->sc_powerstat) 992 status |= UPS_PORT_POWER; 993 if (!sc->sc_fullspeed) 994 status |= UPS_LOW_SPEED; 995 996 //DPRINTF(D_XFER, ("ST=%04x,CH=%04x ", status, sc->sc_change)); 997 USETW(ps.wPortStatus, status); 998 USETW(ps.wPortChange, sc->sc_change); 999 l = min(len, sizeof(ps)); 1000 memcpy(buf, &ps, l); 1001 totlen = l; 1002 break; 1003 case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE): 1004 /* Set Hub Descriptor, 11.16.2.7, not supported */ 1005 /* STALL ? */ 1006 error = USBD_IOERROR; 1007 break; 1008 case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE): 1009 /* Set Hub Feature, 11.16.2.8, not supported */ 1010 break; 1011 case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): 1012 /* Set Port Feature, 11.16.2.9 */ 1013 if (index != 1) { 1014 printf("index=%d ", index); 1015 error = USBD_IOERROR; 1016 goto ret; 1017 } 1018 switch (value) { 1019 case UHF_PORT_RESET: 1020 DPRINTF(D_MSG, ("PORT_RESET ")); 1021 sl11_reset(sc); 1022 sl11_speed(sc); 1023 sc->sc_change = 0; 1024 break; 1025 case UHF_PORT_POWER: 1026 DPRINTF(D_MSG, ("PORT_POWER ")); 1027 sc->sc_powerstat = POWER_ON; 1028 /* x68k Nereid USB controller needs it */ 1029 if (sc->sc_enable_power) 1030 sc->sc_enable_power(sc, sc->sc_powerstat); 1031 delay_ms(25); 1032 break; 1033 default: 1034 printf("SetPortFeatERR=0x%x ", value); 1035 error = USBD_IOERROR; 1036 break; 1037 } 1038 break; 1039 default: 1040 DPRINTF(D_MSG, ("ioerr(UR=%02x,UT=%02x) ", 1041 req->bRequest, req->bmRequestType)); 1042 error = USBD_IOERROR; 1043 goto ret; 1044 } 1045 xfer->actlen = totlen; 1046 error = USBD_NORMAL_COMPLETION; 1047 ret: 1048 xfer->status = error; 1049 s = splusb(); 1050 usb_transfer_complete(xfer); 1051 splx(s); 1052 return USBD_IN_PROGRESS; 1053 } 1054 1055 void 1056 slhci_root_ctrl_abort(usbd_xfer_handle xfer) 1057 { 1058 DPRINTF(D_TRACE, ("SLRCabort ")); 1059 } 1060 1061 void 1062 slhci_root_ctrl_close(usbd_pipe_handle pipe) 1063 { 1064 DPRINTF(D_TRACE, ("SLRCclose ")); 1065 } 1066 1067 void 1068 slhci_root_ctrl_done(usbd_xfer_handle xfer) 1069 { 1070 DPRINTF(D_TRACE, ("SLRCdone\n")); 1071 } 1072 1073 static usbd_status 1074 slhci_root_intr_transfer(usbd_xfer_handle xfer) 1075 { 1076 usbd_status error; 1077 1078 DPRINTF(D_TRACE, ("SLRItransfer ")); 1079 1080 /* Insert last in queue */ 1081 error = usb_insert_transfer(xfer); 1082 if (error) 1083 return error; 1084 1085 /* 1086 * Pipe isn't running (otherwise error would be USBD_INPROG), 1087 * start first. 1088 */ 1089 return slhci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); 1090 } 1091 1092 static usbd_status 1093 slhci_root_intr_start(usbd_xfer_handle xfer) 1094 { 1095 usbd_pipe_handle pipe = xfer->pipe; 1096 struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus; 1097 1098 DPRINTF(D_TRACE, ("SLRIstart ")); 1099 1100 sc->sc_interval = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval); 1101 usb_callout(sc->sc_poll_handle, sc->sc_interval, slhci_poll_hub, xfer); 1102 sc->sc_intr_xfer = xfer; 1103 return USBD_IN_PROGRESS; 1104 } 1105 1106 static void 1107 slhci_root_intr_abort(usbd_xfer_handle xfer) 1108 { 1109 DPRINTF(D_TRACE, ("SLRIabort ")); 1110 } 1111 1112 static void 1113 slhci_root_intr_close(usbd_pipe_handle pipe) 1114 { 1115 struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus; 1116 1117 DPRINTF(D_TRACE, ("SLRIclose ")); 1118 1119 usb_uncallout(sc->sc_poll_handle, slhci_poll_hub, sc->sc_intr_xfer); 1120 sc->sc_intr_xfer = NULL; 1121 } 1122 1123 static void 1124 slhci_root_intr_done(usbd_xfer_handle xfer) 1125 { 1126 //DPRINTF(D_XFER, ("RIdn ")); 1127 } 1128 1129 static usbd_status 1130 slhci_device_ctrl_transfer(usbd_xfer_handle xfer) 1131 { 1132 usbd_status error; 1133 1134 DPRINTF(D_TRACE, ("C")); 1135 1136 error = usb_insert_transfer(xfer); 1137 if (error) 1138 return error; 1139 1140 return slhci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); 1141 } 1142 1143 static usbd_status 1144 slhci_device_ctrl_start(usbd_xfer_handle xfer) 1145 { 1146 usb_device_request_t *req = &xfer->request; 1147 usbd_pipe_handle pipe = xfer->pipe; 1148 struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus; 1149 usbd_status status = USBD_NORMAL_COMPLETION; 1150 void *buf; 1151 int pid = SL11_PID_OUT; 1152 int len, actlen, size; 1153 int s; 1154 u_int8_t toggle = 0; 1155 1156 DPRINTF(D_TRACE, ("st ")); 1157 #ifdef SLHCI_DEBUG 1158 if ((slhci_debug & D_TRACE)) 1159 print_req_hub(req); 1160 #endif 1161 1162 /* SETUP transaction */ 1163 if (slhci_transaction(sc, pipe, SL11_PID_SETUP, 1164 sizeof(*req), (u_char*)req, toggle) == -1) { 1165 status = USBD_IOERROR; 1166 goto ret; 1167 } 1168 toggle ^= SL11_EPCTRL_DATATOGGLE; 1169 1170 /* DATA transaction */ 1171 actlen = 0; 1172 len = UGETW(req->wLength); 1173 if (len) { 1174 buf = KERNADDR(&xfer->dmabuf, 0); 1175 if (req->bmRequestType & UT_READ) 1176 pid = SL11_PID_IN; 1177 for (; actlen < len; ) { 1178 size = min(len - actlen, 8/* Minimum size */); 1179 if (slhci_transaction(sc, pipe, pid, size, buf, toggle) == -1) 1180 break; 1181 toggle ^= SL11_EPCTRL_DATATOGGLE; 1182 (u_char*)buf += size; 1183 actlen += size; 1184 } 1185 } 1186 xfer->actlen = actlen; 1187 1188 /* ACK (status) */ 1189 if (pid == SL11_PID_IN) 1190 pid = SL11_PID_OUT; 1191 else 1192 pid = SL11_PID_IN; 1193 if (slhci_transaction(sc, pipe, pid, 0, NULL, toggle) == -1) 1194 status = USBD_IOERROR; 1195 1196 ret: 1197 xfer->status = status; 1198 1199 #ifdef SLHCI_DEBUG 1200 if((slhci_debug & D_TRACE) && UGETW(req->wLength) > 0){ 1201 int i; 1202 for(i=0; i < UGETW(req->wLength); i++) 1203 printf("%02x", *(unsigned char*)(KERNADDR(&xfer->dmabuf, i))); 1204 printf(" "); 1205 } 1206 #endif 1207 s = splusb(); 1208 usb_transfer_complete(xfer); 1209 splx(s); 1210 return USBD_IN_PROGRESS; 1211 } 1212 1213 static void 1214 slhci_device_ctrl_abort(usbd_xfer_handle xfer) 1215 { 1216 DPRINTF(D_TRACE, ("Cab ")); 1217 slhci_abort_xfer(xfer, USBD_CANCELLED); 1218 } 1219 1220 static void 1221 slhci_device_ctrl_close(usbd_pipe_handle pipe) 1222 { 1223 DPRINTF(D_TRACE, ("Ccl ")); 1224 } 1225 1226 static void 1227 slhci_device_ctrl_done(usbd_xfer_handle xfer) 1228 { 1229 DPRINTF(D_TRACE, ("Cdn ")); 1230 } 1231 1232 static usbd_status 1233 slhci_device_intr_transfer(usbd_xfer_handle xfer) 1234 { 1235 usbd_status error; 1236 1237 DPRINTF(D_TRACE, ("INTRtrans ")); 1238 1239 error = usb_insert_transfer(xfer); 1240 if (error) 1241 return error; 1242 1243 return slhci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); 1244 } 1245 1246 static usbd_status 1247 slhci_device_intr_start(usbd_xfer_handle xfer) 1248 { 1249 usbd_pipe_handle pipe = xfer->pipe; 1250 struct slhci_xfer *sx; 1251 1252 DPRINTF(D_TRACE, ("INTRstart ")); 1253 1254 sx = malloc(sizeof(*sx), M_USB, M_NOWAIT); 1255 if (sx == NULL) 1256 goto reterr; 1257 memset(sx, 0, sizeof(*sx)); 1258 sx->sx_xfer = xfer; 1259 xfer->hcpriv = sx; 1260 1261 /* initialize callout */ 1262 usb_callout_init(sx->sx_callout_t); 1263 usb_callout(sx->sx_callout_t, 1264 MS_TO_TICKS(pipe->endpoint->edesc->bInterval), 1265 slhci_poll_device, sx); 1266 1267 /* ACK */ 1268 return USBD_IN_PROGRESS; 1269 1270 reterr: 1271 return USBD_IOERROR; 1272 } 1273 1274 static void 1275 slhci_poll_device(void *arg) 1276 { 1277 struct slhci_xfer *sx = (struct slhci_xfer *)arg; 1278 usbd_xfer_handle xfer = sx->sx_xfer; 1279 usbd_pipe_handle pipe = xfer->pipe; 1280 struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus; 1281 void *buf; 1282 int pid; 1283 int r; 1284 int s; 1285 1286 DPRINTF(D_TRACE, ("pldev")); 1287 1288 usb_callout(sx->sx_callout_t, 1289 MS_TO_TICKS(pipe->endpoint->edesc->bInterval), 1290 slhci_poll_device, sx); 1291 1292 /* interrupt transfer */ 1293 pid = (UE_GET_DIR(pipe->endpoint->edesc->bEndpointAddress) == UE_DIR_IN) 1294 ? SL11_PID_IN : SL11_PID_OUT; 1295 buf = KERNADDR(&xfer->dmabuf, 0); 1296 1297 r = slhci_transaction(sc, pipe, pid, xfer->length, buf, 0/*toggle*/); 1298 if (r < 0) { 1299 DPRINTF(D_MSG, ("%s error", __FUNCTION__)); 1300 return; 1301 } 1302 /* no change, return NAK */ 1303 if (r == 0) 1304 return; 1305 1306 xfer->status = USBD_NORMAL_COMPLETION; 1307 s = splusb(); 1308 xfer->device->bus->intr_context++; 1309 usb_transfer_complete(xfer); 1310 xfer->device->bus->intr_context--; 1311 splx(s); 1312 } 1313 1314 static void 1315 slhci_device_intr_abort(usbd_xfer_handle xfer) 1316 { 1317 struct slhci_xfer *sx; 1318 1319 DPRINTF(D_TRACE, ("INTRabort ")); 1320 1321 sx = xfer->hcpriv; 1322 if (sx) { 1323 usb_uncallout(sx->sx_callout_t, slhci_poll_device, sx); 1324 free(sx, M_USB); 1325 xfer->hcpriv = NULL; 1326 } else { 1327 printf("%s: sx == NULL!\n", __FUNCTION__); 1328 } 1329 slhci_abort_xfer(xfer, USBD_CANCELLED); 1330 } 1331 1332 static void 1333 slhci_device_intr_close(usbd_pipe_handle pipe) 1334 { 1335 DPRINTF(D_TRACE, ("INTRclose ")); 1336 } 1337 1338 static void 1339 slhci_device_intr_done(usbd_xfer_handle xfer) 1340 { 1341 DPRINTF(D_TRACE, ("INTRdone ")); 1342 } 1343 1344 static usbd_status 1345 slhci_device_isoc_transfer(usbd_xfer_handle xfer) 1346 { 1347 DPRINTF(D_TRACE, ("S")); 1348 return USBD_NORMAL_COMPLETION; 1349 } 1350 1351 static usbd_status 1352 slhci_device_isoc_start(usbd_xfer_handle xfer) 1353 { 1354 DPRINTF(D_TRACE, ("st ")); 1355 return USBD_NORMAL_COMPLETION; 1356 } 1357 1358 static void 1359 slhci_device_isoc_abort(usbd_xfer_handle xfer) 1360 { 1361 DPRINTF(D_TRACE, ("Sab ")); 1362 } 1363 1364 static void 1365 slhci_device_isoc_close(usbd_pipe_handle pipe) 1366 { 1367 DPRINTF(D_TRACE, ("Scl ")); 1368 } 1369 1370 static void 1371 slhci_device_isoc_done(usbd_xfer_handle xfer) 1372 { 1373 DPRINTF(D_TRACE, ("Sdn ")); 1374 } 1375 1376 static usbd_status 1377 slhci_device_bulk_transfer(usbd_xfer_handle xfer) 1378 { 1379 DPRINTF(D_TRACE, ("B")); 1380 return USBD_NORMAL_COMPLETION; 1381 } 1382 1383 static usbd_status 1384 slhci_device_bulk_start(usbd_xfer_handle xfer) 1385 { 1386 DPRINTF(D_TRACE, ("st ")); 1387 return USBD_NORMAL_COMPLETION; 1388 } 1389 1390 static void 1391 slhci_device_bulk_abort(usbd_xfer_handle xfer) 1392 { 1393 DPRINTF(D_TRACE, ("Bab ")); 1394 } 1395 1396 static void 1397 slhci_device_bulk_close(usbd_pipe_handle pipe) 1398 { 1399 DPRINTF(D_TRACE, ("Bcl ")); 1400 } 1401 1402 static void 1403 slhci_device_bulk_done(usbd_xfer_handle xfer) 1404 { 1405 DPRINTF(D_TRACE, ("Bdn ")); 1406 } 1407 1408 #define DATA0_RD (0x03) 1409 #define DATA0_WR (0x07) 1410 #define SLHCI_TIMEOUT (5000) 1411 1412 /* 1413 * Do a transaction. 1414 * return 1 if ACK, 0 if NAK, -1 if error. 1415 */ 1416 static int 1417 slhci_transaction(struct slhci_softc *sc, usbd_pipe_handle pipe, 1418 u_int8_t pid, int len, u_char *buf, u_int8_t toggle) 1419 { 1420 #ifdef SLHCI_DEBUG 1421 char str[64]; 1422 int i; 1423 #endif 1424 int timeout; 1425 int ls_via_hub = 0; 1426 int pl; 1427 u_int8_t isr; 1428 u_int8_t result = 0; 1429 u_int8_t devaddr = pipe->device->address; 1430 u_int8_t endpointaddr = pipe->endpoint->edesc->bEndpointAddress; 1431 u_int8_t endpoint; 1432 u_int8_t cmd = DATA0_RD; 1433 1434 endpoint = UE_GET_ADDR(endpointaddr); 1435 DPRINTF(D_XFER, ("\n(%x,%d%s%d,%d) ", 1436 pid, len, (pid == SL11_PID_IN) ? "<-" : "->", devaddr, endpoint)); 1437 1438 /* Set registers */ 1439 sl11write(sc, SL11_E0ADDR, 0x40); 1440 sl11write(sc, SL11_E0LEN, len); 1441 sl11write(sc, SL11_E0PID, (pid << 4) + endpoint); 1442 sl11write(sc, SL11_E0DEV, devaddr); 1443 1444 /* Set buffer unless PID_IN */ 1445 if (pid != SL11_PID_IN) { 1446 if (len > 0) 1447 sl11write_region(sc, 0x40, buf, len); 1448 cmd = DATA0_WR; 1449 } 1450 1451 /* timing ? */ 1452 pl = (len >> 3) + 3; 1453 1454 /* Low speed device via HUB */ 1455 /* XXX does not work... */ 1456 if ((sc->sc_fullspeed) && pipe->device->speed == USB_SPEED_LOW) { 1457 pl = len + 16; 1458 cmd |= SL11_EPCTRL_PREAMBLE; 1459 1460 /* 1461 * SL811HS/T rev 1.2 has a bug, when it got PID_IN 1462 * from LowSpeed device via HUB. 1463 */ 1464 if (sc->sc_sltype == SLTYPE_SL811HS_R12 && pid == SL11_PID_IN) { 1465 ls_via_hub = 1; 1466 DPRINTF(D_MSG, ("LSvH ")); 1467 } 1468 } 1469 1470 /* timing ? */ 1471 if (sl11read(sc, SL811_CSOF) <= (u_int8_t)pl) 1472 cmd |= SL11_EPCTRL_SOF; 1473 1474 /* Transfer */ 1475 sl11write(sc, SL11_ISR, 0xff); 1476 sl11write(sc, SL11_E0CTRL, cmd | toggle); 1477 1478 /* Polling */ 1479 for (timeout = SLHCI_TIMEOUT; timeout; timeout--) { 1480 isr = sl11read(sc, SL11_ISR); 1481 if ((isr & SL11_ISR_USBA)) 1482 break; 1483 } 1484 1485 /* Check result status */ 1486 result = sl11read(sc, SL11_E0STAT); 1487 if (!(result & SL11_EPSTAT_NAK) && ls_via_hub) { 1488 /* Resend PID_IN within 20usec */ 1489 sl11write(sc, SL11_ISR, 0xff); 1490 sl11write(sc, SL11_E0CTRL, SL11_EPCTRL_ARM); 1491 } 1492 1493 sl11write(sc, SL11_ISR, 0xff); 1494 1495 DPRINTF(D_XFER, ("t=%d i=%x ", SLHCI_TIMEOUT - timeout, isr)); 1496 #if SLHCI_DEBUG 1497 bitmask_snprintf(result, 1498 "\20\x8STALL\7NAK\6OV\5SETUP\4DATA1\3TIMEOUT\2ERR\1ACK", 1499 str, sizeof(str)); 1500 DPRINTF(D_XFER, ("STAT=%s ", str)); 1501 #endif 1502 1503 if ((result & SL11_EPSTAT_ERROR)) 1504 return -1; 1505 1506 if ((result & SL11_EPSTAT_NAK)) 1507 return 0; 1508 1509 /* Read buffer if PID_IN */ 1510 if (pid == SL11_PID_IN && len > 0) { 1511 sl11read_region(sc, buf, 0x40, len); 1512 #if SLHCI_DEBUG 1513 for (i = 0; i < len; i++) 1514 DPRINTF(D_XFER, ("%02X ", buf[i])); 1515 #endif 1516 } 1517 1518 return 1; 1519 } 1520 1521 void 1522 slhci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) 1523 { 1524 xfer->status = status; 1525 usb_transfer_complete(xfer); 1526 } 1527 1528 void 1529 slhci_device_clear_toggle(usbd_pipe_handle pipe) 1530 { 1531 DPRINTF(D_TRACE, ("SLdevice_clear_toggle ")); 1532 } 1533 1534 #ifdef SLHCI_DEBUG 1535 void 1536 print_req(usb_device_request_t *r) 1537 { 1538 char *xmes[]={ 1539 "GETSTAT", 1540 "CLRFEAT", 1541 "res", 1542 "SETFEAT", 1543 "res", 1544 "SETADDR", 1545 "GETDESC", 1546 "SETDESC", 1547 "GETCONF", 1548 "SETCONF", 1549 "GETIN/F", 1550 "SETIN/F", 1551 "SYNC_FR" 1552 }; 1553 int req, type, value, index, len; 1554 1555 req = r->bRequest; 1556 type = r->bmRequestType; 1557 value = UGETW(r->wValue); 1558 index = UGETW(r->wIndex); 1559 len = UGETW(r->wLength); 1560 1561 printf("%x,%s,v=%d,i=%d,l=%d ", 1562 type, xmes[req], value, index, len); 1563 } 1564 1565 void 1566 print_req_hub(usb_device_request_t *r) 1567 { 1568 struct { 1569 int req; 1570 int type; 1571 char *str; 1572 } conf[] = { 1573 { 1, 0x20, "ClrHubFeat" }, 1574 { 1, 0x23, "ClrPortFeat" }, 1575 { 2, 0xa3, "GetBusState" }, 1576 { 6, 0xa0, "GetHubDesc" }, 1577 { 0, 0xa0, "GetHubStat" }, 1578 { 0, 0xa3, "GetPortStat" }, 1579 { 7, 0x20, "SetHubDesc" }, 1580 { 3, 0x20, "SetHubFeat" }, 1581 { 3, 0x23, "SetPortFeat" }, 1582 {-1, 0, NULL}, 1583 }; 1584 int i; 1585 int value, index, len; 1586 1587 value = UGETW(r->wValue); 1588 index = UGETW(r->wIndex); 1589 len = UGETW(r->wLength); 1590 for (i = 0; ; i++) { 1591 if (conf[i].req == -1 ) 1592 return print_req(r); 1593 if (r->bmRequestType == conf[i].type && r->bRequest == conf[i].req) { 1594 printf("%s", conf[i].str); 1595 break; 1596 } 1597 } 1598 printf(",v=%d,i=%d,l=%d ", value, index, len); 1599 } 1600 1601 void 1602 print_dumpreg(struct slhci_softc *sc) 1603 { 1604 printf("00=%02x,01=%02x,02=%02x,03=%02x,04=%02x," 1605 "08=%02x,09=%02x,0A=%02x,0B=%02x,0C=%02x,", 1606 sl11read(sc, 0), sl11read(sc, 1), 1607 sl11read(sc, 2), sl11read(sc, 3), 1608 sl11read(sc, 4), sl11read(sc, 8), 1609 sl11read(sc, 9), sl11read(sc, 10), 1610 sl11read(sc, 11), sl11read(sc, 12) 1611 ); 1612 printf("CR1=%02x,IER=%02x,0D=%02x,0E=%02x,0F=%02x ", 1613 sl11read(sc, 5), sl11read(sc, 6), 1614 sl11read(sc, 13), sl11read(sc, 14), sl11read(sc, 15) 1615 ); 1616 } 1617 1618 void 1619 print_xfer(usbd_xfer_handle xfer) 1620 { 1621 printf("xfer: length=%d, actlen=%d, flags=%x, timeout=%d,", 1622 xfer->length, xfer->actlen, xfer->flags, xfer->timeout); 1623 printf("request{ "); 1624 print_req_hub(&xfer->request); 1625 printf("} "); 1626 } 1627 #endif /* SLHCI_DEBUG */ 1628