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