1 /* $NetBSD: sl811hs.c,v 1.2 2002/09/08 07:58:14 isaki 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.2 2002/09/08 07:58:14 isaki 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 ? "\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, 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_debud & 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 "\20\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 */ 1627