1 /* $NetBSD: ahci.c,v 1.8 2012/03/11 00:34:46 mrg 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.8 2012/03/11 00:34:46 mrg 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 <sys/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 callout_init(&sc->sc_poll_handle, 0); 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 snprintb(bitbuf, sizeof(bitbuf), 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 r); 357 358 DPRINTF(D_XFER, ("I=%s ", bitbuf)); 359 #endif /* AHCI_DEBUG */ 360 #endif 361 362 return 0; 363 } 364 365 usbd_status 366 ahci_open(usbd_pipe_handle pipe) 367 { 368 usbd_device_handle dev = pipe->device; 369 struct ahci_softc *sc = (struct ahci_softc *)dev->bus; 370 struct ahci_pipe *apipe = (struct ahci_pipe *)pipe; 371 usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; 372 373 DPRINTF(D_TRACE, ("ahci_open(addr=%d,ep=%d,scaddr=%d)", 374 dev->address, ed->bEndpointAddress, sc->sc_addr)); 375 376 apipe->toggle=0; 377 378 if (dev->address == sc->sc_addr) { 379 switch (ed->bEndpointAddress) { 380 case USB_CONTROL_ENDPOINT: 381 pipe->methods = &ahci_root_ctrl_methods; 382 break; 383 case UE_DIR_IN | AHCI_INTR_ENDPT: 384 pipe->methods = &ahci_root_intr_methods; 385 break; 386 default: 387 printf("open:endpointErr!\n"); 388 return USBD_INVAL; 389 } 390 } else { 391 switch (ed->bmAttributes & UE_XFERTYPE) { 392 case UE_CONTROL: 393 DPRINTF(D_MSG, ("control ")); 394 pipe->methods = &ahci_device_ctrl_methods; 395 break; 396 case UE_INTERRUPT: 397 DPRINTF(D_MSG, ("interrupt ")); 398 pipe->methods = &ahci_device_intr_methods; 399 break; 400 case UE_ISOCHRONOUS: 401 DPRINTF(D_MSG, ("isochronous ")); 402 pipe->methods = &ahci_device_isoc_methods; 403 break; 404 case UE_BULK: 405 DPRINTF(D_MSG, ("bluk ")); 406 pipe->methods = &ahci_device_bulk_methods; 407 break; 408 } 409 } 410 return USBD_NORMAL_COMPLETION; 411 } 412 413 void 414 ahci_softintr(void *arg) 415 { 416 DPRINTF(D_TRACE, ("%s()", __func__)); 417 } 418 419 void 420 ahci_poll(struct usbd_bus *bus) 421 { 422 DPRINTF(D_TRACE, ("%s()", __func__)); 423 } 424 425 /* 426 * Emulation of interrupt transfer for status change endpoint 427 * of root hub. 428 */ 429 void 430 ahci_poll_hub(void *arg) 431 { 432 usbd_xfer_handle xfer = arg; 433 usbd_pipe_handle pipe = xfer->pipe; 434 struct ahci_softc *sc = (struct ahci_softc *)pipe->device->bus; 435 int s; 436 u_char *p; 437 static int p0_state=0; 438 static int p1_state=0; 439 440 callout_reset(&sc->sc_poll_handle, sc->sc_interval, ahci_poll_hub, xfer); 441 442 /* USB spec 11.13.3 (p.260) */ 443 p = KERNADDR(&xfer->dmabuf, 0); 444 p[0] = 0; 445 if ((REG_READ(ADMHCD_REG_PORTSTATUS0) & ADMHCD_CCS) != p0_state) { 446 p[0] = 2; 447 DPRINTF(D_TRACE, ("!")); 448 p0_state=(REG_READ(ADMHCD_REG_PORTSTATUS0) & ADMHCD_CCS); 449 }; 450 if ((REG_READ(ADMHCD_REG_PORTSTATUS1) & ADMHCD_CCS) != p1_state) { 451 p[0] = 2; 452 DPRINTF(D_TRACE, ("@")); 453 p1_state=(REG_READ(ADMHCD_REG_PORTSTATUS1) & ADMHCD_CCS); 454 }; 455 456 /* no change, return NAK */ 457 if (p[0] == 0) 458 return; 459 460 xfer->actlen = 1; 461 xfer->status = USBD_NORMAL_COMPLETION; 462 s = splusb(); 463 usb_transfer_complete(xfer); 464 splx(s); 465 } 466 467 usbd_status 468 ahci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size) 469 { 470 struct ahci_softc *sc = (struct ahci_softc *)bus; 471 472 DPRINTF(D_MEM, ("SLallocm")); 473 return usb_allocmem(&sc->sc_bus, size, 0, dma); 474 } 475 476 void 477 ahci_freem(struct usbd_bus *bus, usb_dma_t *dma) 478 { 479 struct ahci_softc *sc = (struct ahci_softc *)bus; 480 481 DPRINTF(D_MEM, ("SLfreem")); 482 usb_freemem(&sc->sc_bus, dma); 483 } 484 485 usbd_xfer_handle 486 ahci_allocx(struct usbd_bus *bus) 487 { 488 struct ahci_softc *sc = (struct ahci_softc *)bus; 489 usbd_xfer_handle xfer; 490 491 DPRINTF(D_MEM, ("SLallocx")); 492 493 xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); 494 if (xfer) { 495 SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next); 496 #ifdef DIAGNOSTIC 497 if (xfer->busy_free != XFER_FREE) { 498 printf("ahci_allocx: xfer=%p not free, 0x%08x\n", 499 xfer, xfer->busy_free); 500 } 501 #endif 502 } else { 503 xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT); 504 } 505 506 if (xfer) { 507 memset(xfer, 0, sizeof(*xfer)); 508 #ifdef DIAGNOSTIC 509 xfer->busy_free = XFER_BUSY; 510 #endif 511 } 512 513 return xfer; 514 } 515 516 void 517 ahci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) 518 { 519 struct ahci_softc *sc = (struct ahci_softc *)bus; 520 521 DPRINTF(D_MEM, ("SLfreex")); 522 523 #ifdef DIAGNOSTIC 524 if (xfer->busy_free != XFER_BUSY) { 525 printf("ahci_freex: xfer=%p not busy, 0x%08x\n", 526 xfer, xfer->busy_free); 527 return; 528 } 529 xfer->busy_free = XFER_FREE; 530 #endif 531 SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); 532 } 533 534 void 535 ahci_noop(usbd_pipe_handle pipe) 536 { 537 DPRINTF(D_TRACE, ("%s()", __func__)); 538 } 539 540 /* 541 * Data structures and routines to emulate the root hub. 542 */ 543 usb_device_descriptor_t ahci_devd = { 544 USB_DEVICE_DESCRIPTOR_SIZE, 545 UDESC_DEVICE, /* type */ 546 {0x01, 0x01}, /* USB version */ 547 UDCLASS_HUB, /* class */ 548 UDSUBCLASS_HUB, /* subclass */ 549 0, /* protocol */ 550 64, /* max packet */ 551 {USB_VENDOR_SCANLOGIC & 0xff, /* vendor ID (low) */ 552 USB_VENDOR_SCANLOGIC >> 8 }, /* vendor ID (high) */ 553 {0} /* ? */, /* product ID */ 554 {0}, /* device */ 555 1, /* index to manufacturer */ 556 2, /* index to product */ 557 0, /* index to serial number */ 558 1 /* number of configurations */ 559 }; 560 561 usb_config_descriptor_t ahci_confd = { 562 USB_CONFIG_DESCRIPTOR_SIZE, 563 UDESC_CONFIG, 564 {USB_CONFIG_DESCRIPTOR_SIZE + 565 USB_INTERFACE_DESCRIPTOR_SIZE + 566 USB_ENDPOINT_DESCRIPTOR_SIZE}, 567 1, /* number of interfaces */ 568 1, /* configuration value */ 569 0, /* index to configuration */ 570 UC_SELF_POWERED, /* attributes */ 571 250 /* max current is 500mA... */ 572 }; 573 574 usb_interface_descriptor_t ahci_ifcd = { 575 USB_INTERFACE_DESCRIPTOR_SIZE, 576 UDESC_INTERFACE, 577 0, /* interface number */ 578 0, /* alternate setting */ 579 1, /* number of endpoint */ 580 UICLASS_HUB, /* class */ 581 UISUBCLASS_HUB, /* subclass */ 582 0, /* protocol */ 583 0 /* index to interface */ 584 }; 585 586 usb_endpoint_descriptor_t ahci_endpd = { 587 USB_ENDPOINT_DESCRIPTOR_SIZE, 588 UDESC_ENDPOINT, 589 UE_DIR_IN | AHCI_INTR_ENDPT, /* endpoint address */ 590 UE_INTERRUPT, /* attributes */ 591 {8}, /* max packet size */ 592 255 /* interval */ 593 }; 594 595 usb_hub_descriptor_t ahci_hubd = { 596 USB_HUB_DESCRIPTOR_SIZE, 597 UDESC_HUB, 598 2, /* number of ports */ 599 { 0, 0}, /* hub characteristics */ 600 0, /* 5:power on to power good */ 601 0, /* 6:maximum current */ 602 { 0x00 }, /* both ports are removable */ 603 { 0x00 } /* port power control mask */ 604 }; 605 606 static int 607 ahci_str(usb_string_descriptor_t *p, int l, const char *s) 608 { 609 int i; 610 611 if (l == 0) 612 return 0; 613 p->bLength = 2 * strlen(s) + 2; 614 if (l == 1) 615 return 1; 616 p->bDescriptorType = UDESC_STRING; 617 l -= 2; 618 for (i = 0; s[i] && l > 1; i++, l -= 2) 619 USETW2(p->bString[i], 0, s[i]); 620 return 2 * i + 2; 621 } 622 623 usbd_status 624 ahci_root_ctrl_transfer(usbd_xfer_handle xfer) 625 { 626 usbd_status error; 627 628 DPRINTF(D_TRACE, ("SLRCtrans ")); 629 630 /* Insert last in queue */ 631 error = usb_insert_transfer(xfer); 632 if (error) { 633 DPRINTF(D_MSG, ("usb_insert_transfer returns err! ")); 634 return error; 635 } 636 637 /* 638 * Pipe isn't running (otherwise error would be USBD_INPROG), 639 * so start it first. 640 */ 641 return ahci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); 642 } 643 644 usbd_status 645 ahci_root_ctrl_start(usbd_xfer_handle xfer) 646 { 647 struct ahci_softc *sc = (struct ahci_softc *)xfer->pipe->device->bus; 648 usb_device_request_t *req; 649 int len, value, index, l, s, status; 650 int totlen = 0; 651 void *buf = NULL; 652 usb_port_status_t ps; 653 usbd_status error; 654 655 656 DPRINTF(D_TRACE, ("SLRCstart ")); 657 658 req = &xfer->request; 659 660 len = UGETW(req->wLength); 661 value = UGETW(req->wValue); 662 index = UGETW(req->wIndex); 663 664 if (len) 665 buf = KERNADDR(&xfer->dmabuf, 0); 666 667 #ifdef AHCI_DEBUG 668 if ((ahci_debug & D_TRACE)) 669 print_req_hub(req); 670 #endif 671 672 #define C(x,y) ((x) | ((y) << 8)) 673 switch (C(req->bRequest, req->bmRequestType)) { 674 case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE): 675 DPRINTF(D_MSG, ("UR_CLEAR_FEATURE(DEVICE)XXX ")); 676 break; 677 case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE): 678 DPRINTF(D_MSG, ("UR_CLEAR_FEATURE(INTERFACE)XXX ")); 679 break; 680 case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT): 681 DPRINTF(D_MSG, ("UR_CLEAR_FEATURE(ENDPOINT)XXX ")); 682 break; 683 case C(UR_GET_CONFIG, UT_READ_DEVICE): 684 DPRINTF(D_MSG, ("UR_GET_CONFIG ")); 685 if (len > 0) { 686 *(u_int8_t *)buf = sc->sc_conf; 687 totlen = 1; 688 } 689 break; 690 case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): 691 switch (value >> 8) { 692 case UDESC_DEVICE: 693 DPRINTF(D_MSG, ("UDESC_DEVICE ")); 694 if ((value & 0xff) != 0) { 695 error = USBD_IOERROR; 696 goto ret; 697 } 698 totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); 699 memcpy(buf, &ahci_devd, l); 700 break; 701 case UDESC_CONFIG: 702 DPRINTF(D_MSG, ("UDESC_CONFIG ")); 703 if ((value & 0xff) != 0) { 704 error = USBD_IOERROR; 705 goto ret; 706 } 707 totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE); 708 memcpy(buf, &ahci_confd, l); 709 buf = (char *)buf + l; 710 len -= l; 711 712 l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE); 713 totlen += l; 714 memcpy(buf, &ahci_ifcd, l); 715 buf = (char *)buf + l; 716 len -= l; 717 718 l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE); 719 totlen += l; 720 memcpy(buf, &ahci_endpd, l); 721 break; 722 case UDESC_STRING: 723 DPRINTF(D_MSG, ("UDESC_STR ")); 724 if (len == 0) 725 break; 726 *(u_int8_t *)buf = 0; 727 totlen = 1; 728 switch (value & 0xff) { 729 case 0: 730 break; 731 case 1: /* Vendor */ 732 totlen = ahci_str(buf, len, "ADMTek"); 733 break; 734 case 2: /* Product */ 735 totlen = ahci_str(buf, len, "ADM5120 root hub"); 736 break; 737 default: 738 printf("strerr%d ", value & 0xff); 739 break; 740 } 741 break; 742 default: 743 printf("unknownGetDescriptor=%x", value); 744 error = USBD_IOERROR; 745 break; 746 } 747 break; 748 case C(UR_GET_INTERFACE, UT_READ_INTERFACE): 749 /* Get Interface, 9.4.4 */ 750 if (len > 0) { 751 *(u_int8_t *)buf = 0; 752 totlen = 1; 753 } 754 break; 755 case C(UR_GET_STATUS, UT_READ_DEVICE): 756 /* Get Status from device, 9.4.5 */ 757 if (len > 1) { 758 USETW(((usb_status_t *)buf)->wStatus, UDS_SELF_POWERED); 759 totlen = 2; 760 } 761 break; 762 case C(UR_GET_STATUS, UT_READ_INTERFACE): 763 case C(UR_GET_STATUS, UT_READ_ENDPOINT): 764 /* Get Status from interface, endpoint, 9.4.5 */ 765 if (len > 1) { 766 USETW(((usb_status_t *)buf)->wStatus, 0); 767 totlen = 2; 768 } 769 break; 770 case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): 771 /* Set Address, 9.4.6 */ 772 DPRINTF(D_MSG, ("UR_SET_ADDRESS ")); 773 if (value >= USB_MAX_DEVICES) { 774 error = USBD_IOERROR; 775 goto ret; 776 } 777 sc->sc_addr = value; 778 break; 779 case C(UR_SET_CONFIG, UT_WRITE_DEVICE): 780 /* Set Configuration, 9.4.7 */ 781 DPRINTF(D_MSG, ("UR_SET_CONFIG ")); 782 if (value != 0 && value != 1) { 783 error = USBD_IOERROR; 784 goto ret; 785 } 786 sc->sc_conf = value; 787 break; 788 case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE): 789 /* Set Descriptor, 9.4.8, not supported */ 790 DPRINTF(D_MSG, ("UR_SET_DESCRIPTOR,WRITE_DEVICE not supported\n")); 791 break; 792 case C(UR_SET_FEATURE, UT_WRITE_DEVICE): 793 case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): 794 case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): 795 /* Set Feature, 9.4.9, not supported */ 796 DPRINTF(D_MSG, ("UR_SET_FEATURE not supported\n")); 797 error = USBD_IOERROR; 798 break; 799 case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): 800 /* Set Interface, 9.4.10, not supported */ 801 break; 802 case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT): 803 /* Synch Frame, 9.4.11, not supported */ 804 break; 805 806 /* 807 * Hub specific requests 808 */ 809 case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE): 810 /* Clear Hub Feature, 11.16.2.1, not supported */ 811 DPRINTF(D_MSG, ("ClearHubFeature not supported\n")); 812 break; 813 case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER): 814 815 #define WPS(x) REG_WRITE(ADMHCD_REG_PORTSTATUS0+(index-1)*4, (x)) 816 /* Clear Port Feature, 11.16.2.2 */ 817 if (index != 1 && index != 2 ) { 818 error = USBD_IOERROR; 819 goto ret; 820 } 821 switch (value) { 822 case UHF_PORT_POWER: 823 DPRINTF(D_MSG, ("POWER_OFF ")); 824 WPS(ADMHCD_LSDA); 825 break; 826 case UHF_PORT_SUSPEND: 827 DPRINTF(D_MSG, ("SUSPEND ")); 828 WPS(ADMHCD_POCI); 829 break; 830 case UHF_PORT_ENABLE: 831 DPRINTF(D_MSG, ("ENABLE ")); 832 WPS(ADMHCD_CCS); 833 break; 834 case UHF_C_PORT_CONNECTION: 835 WPS(ADMHCD_CSC); 836 break; 837 case UHF_C_PORT_RESET: 838 WPS(ADMHCD_PRSC); 839 break; 840 case UHF_C_PORT_SUSPEND: 841 WPS(ADMHCD_PSSC); 842 break; 843 case UHF_C_PORT_ENABLE: 844 WPS(ADMHCD_PESC); 845 break; 846 case UHF_C_PORT_OVER_CURRENT: 847 WPS(ADMHCD_OCIC); 848 break; 849 default: 850 printf("ClrPortFeatERR:value=0x%x ", value); 851 error = USBD_IOERROR; 852 break; 853 } 854 //DPRINTF(D_XFER, ("CH=%04x ", sc->sc_change)); 855 #undef WPS 856 break; 857 case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER): 858 /* Get Bus State, 11.16.2.3, not supported */ 859 /* shall return a STALL... */ 860 break; 861 case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): 862 /* Get Hub Descriptor, 11.16.2.4 */ 863 DPRINTF(D_MSG, ("UR_GET_DESCRIPTOR RCD")); 864 if ((value&0xff) != 0) { 865 error = USBD_IOERROR; 866 goto ret; 867 } 868 l = min(len, USB_HUB_DESCRIPTOR_SIZE); 869 totlen = l; 870 memcpy(buf, &ahci_hubd, l); 871 break; 872 case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): 873 /* Get Hub Status, 11.16.2.5 */ 874 DPRINTF(D_MSG, ("UR_GET_STATUS RCD")); 875 if (len != 4) { 876 error = USBD_IOERROR; 877 goto ret; 878 } 879 memset(buf, 0, len); 880 totlen = len; 881 break; 882 case C(UR_GET_STATUS, UT_READ_CLASS_OTHER): 883 /* Get Port Status, 11.16.2.6 */ 884 if ((index != 1 && index != 2) || len != 4) { 885 printf("index=%d,len=%d ", index, len); 886 error = USBD_IOERROR; 887 goto ret; 888 } 889 status = REG_READ(ADMHCD_REG_PORTSTATUS0+(index-1)*4); 890 DPRINTF(D_MSG, ("UR_GET_STATUS RCO=%x ", status)); 891 892 //DPRINTF(D_XFER, ("ST=%04x,CH=%04x ", status, sc->sc_change)); 893 USETW(ps.wPortStatus, status & (UPS_CURRENT_CONNECT_STATUS|UPS_PORT_ENABLED|UPS_SUSPEND|UPS_OVERCURRENT_INDICATOR|UPS_RESET|UPS_PORT_POWER|UPS_LOW_SPEED)); 894 USETW(ps.wPortChange, (status>>16) & (UPS_C_CONNECT_STATUS|UPS_C_PORT_ENABLED|UPS_C_SUSPEND|UPS_C_OVERCURRENT_INDICATOR|UPS_C_PORT_RESET)); 895 l = min(len, sizeof(ps)); 896 memcpy(buf, &ps, l); 897 totlen = l; 898 break; 899 case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE): 900 /* Set Hub Descriptor, 11.16.2.7, not supported */ 901 /* STALL ? */ 902 error = USBD_IOERROR; 903 break; 904 case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE): 905 /* Set Hub Feature, 11.16.2.8, not supported */ 906 break; 907 case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): 908 #define WPS(x) REG_WRITE(ADMHCD_REG_PORTSTATUS0+(index-1)*4, (x)) 909 /* Set Port Feature, 11.16.2.9 */ 910 if ((index != 1) && (index !=2)) { 911 printf("index=%d ", index); 912 error = USBD_IOERROR; 913 goto ret; 914 } 915 switch (value) { 916 case UHF_PORT_RESET: 917 DPRINTF(D_MSG, ("PORT_RESET ")); 918 WPS(ADMHCD_PRS); 919 break; 920 case UHF_PORT_POWER: 921 DPRINTF(D_MSG, ("PORT_POWER ")); 922 WPS(ADMHCD_PPS); 923 break; 924 case UHF_PORT_ENABLE: 925 DPRINTF(D_MSG, ("PORT_ENABLE ")); 926 WPS(ADMHCD_PES); 927 break; 928 default: 929 printf("SetPortFeatERR=0x%x ", value); 930 error = USBD_IOERROR; 931 break; 932 } 933 #undef WPS 934 break; 935 default: 936 DPRINTF(D_MSG, ("ioerr(UR=%02x,UT=%02x) ", 937 req->bRequest, req->bmRequestType)); 938 error = USBD_IOERROR; 939 goto ret; 940 } 941 xfer->actlen = totlen; 942 error = USBD_NORMAL_COMPLETION; 943 ret: 944 xfer->status = error; 945 s = splusb(); 946 usb_transfer_complete(xfer); 947 splx(s); 948 return USBD_IN_PROGRESS; 949 } 950 951 void 952 ahci_root_ctrl_abort(usbd_xfer_handle xfer) 953 { 954 DPRINTF(D_TRACE, ("SLRCabort ")); 955 } 956 957 void 958 ahci_root_ctrl_close(usbd_pipe_handle pipe) 959 { 960 DPRINTF(D_TRACE, ("SLRCclose ")); 961 } 962 963 void 964 ahci_root_ctrl_done(usbd_xfer_handle xfer) 965 { 966 DPRINTF(D_TRACE, ("SLRCdone\n")); 967 } 968 969 static usbd_status 970 ahci_root_intr_transfer(usbd_xfer_handle xfer) 971 { 972 usbd_status error; 973 974 DPRINTF(D_TRACE, ("SLRItransfer ")); 975 976 /* Insert last in queue */ 977 error = usb_insert_transfer(xfer); 978 if (error) 979 return error; 980 981 /* 982 * Pipe isn't running (otherwise error would be USBD_INPROG), 983 * start first. 984 */ 985 return ahci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); 986 } 987 988 static usbd_status 989 ahci_root_intr_start(usbd_xfer_handle xfer) 990 { 991 usbd_pipe_handle pipe = xfer->pipe; 992 struct ahci_softc *sc = (struct ahci_softc *)pipe->device->bus; 993 994 DPRINTF(D_TRACE, ("SLRIstart ")); 995 996 sc->sc_interval = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval); 997 callout_reset(&sc->sc_poll_handle, sc->sc_interval, ahci_poll_hub, xfer); 998 sc->sc_intr_xfer = xfer; 999 return USBD_IN_PROGRESS; 1000 } 1001 1002 static void 1003 ahci_root_intr_abort(usbd_xfer_handle xfer) 1004 { 1005 DPRINTF(D_TRACE, ("SLRIabort ")); 1006 } 1007 1008 static void 1009 ahci_root_intr_close(usbd_pipe_handle pipe) 1010 { 1011 struct ahci_softc *sc = (struct ahci_softc *)pipe->device->bus; 1012 1013 DPRINTF(D_TRACE, ("SLRIclose ")); 1014 1015 callout_stop(&sc->sc_poll_handle); 1016 sc->sc_intr_xfer = NULL; 1017 } 1018 1019 static void 1020 ahci_root_intr_done(usbd_xfer_handle xfer) 1021 { 1022 //DPRINTF(D_XFER, ("RIdn ")); 1023 } 1024 1025 static usbd_status 1026 ahci_device_ctrl_transfer(usbd_xfer_handle xfer) 1027 { 1028 usbd_status error; 1029 1030 DPRINTF(D_TRACE, ("C")); 1031 1032 error = usb_insert_transfer(xfer); 1033 if (error) 1034 return error; 1035 1036 return ahci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); 1037 } 1038 1039 static usbd_status 1040 ahci_device_ctrl_start(usbd_xfer_handle xfer) 1041 { 1042 usbd_status status = USBD_NORMAL_COMPLETION; 1043 int s, err; 1044 static struct admhcd_ed ep_v __attribute__((aligned(16))), *ep; 1045 static struct admhcd_td td_v[4] __attribute__((aligned(16))), *td, *td1, *td2, *td3; 1046 static usb_dma_t reqdma; 1047 usbd_pipe_handle pipe = xfer->pipe; 1048 usb_device_request_t *req = &xfer->request; 1049 struct ahci_softc *sc = (struct ahci_softc *)pipe->device->bus; 1050 int len, isread; 1051 1052 1053 #if 0 1054 struct ahci_pipe *apipe = (struct ahci_pipe *)xfer->pipe; 1055 #endif 1056 while (sc->busy) { 1057 delay_ms(10); 1058 }; 1059 sc->busy++; 1060 /* printf("ctrl_start>>>\n"); */ 1061 1062 #ifdef DIAGNOSTIC 1063 if (!(xfer->rqflags & URQ_REQUEST)) { 1064 /* XXX panic */ 1065 printf("ahci_device_ctrl_transfer: not a request\n"); 1066 return (USBD_INVAL); 1067 } 1068 #endif 1069 1070 #define KSEG1ADDR(x) (0xa0000000 | (((u_int32_t)x) & 0x1fffffff)) 1071 DPRINTF(D_TRACE, ("st ")); 1072 if (!ep) { 1073 ep = (struct admhcd_ed *)KSEG1ADDR(&ep_v); 1074 td = (struct admhcd_td *)KSEG1ADDR(&td_v[0]); 1075 td1 = (struct admhcd_td *)KSEG1ADDR(&td_v[1]); 1076 td2 = (struct admhcd_td *)KSEG1ADDR(&td_v[2]); 1077 td3 = (struct admhcd_td *)KSEG1ADDR(&td_v[3]); 1078 err = usb_allocmem(&sc->sc_bus, 1079 sizeof(usb_device_request_t), 1080 0, &reqdma); 1081 if (err) 1082 return (USBD_NOMEM); 1083 1084 /* printf("ep: %p\n",ep); */ 1085 }; 1086 1087 ep->control = pipe->device->address | \ 1088 ((pipe->device->speed==USB_SPEED_FULL)?ADMHCD_ED_SPEED:0) | \ 1089 ((UGETW(pipe->endpoint->edesc->wMaxPacketSize))<<ADMHCD_ED_MAXSHIFT); 1090 memcpy(KERNADDR(&reqdma, 0), req, sizeof *req); 1091 /* printf("status: %x\n",REG_READ(ADMHCD_REG_PORTSTATUS0)); 1092 printf("ep_control: %x\n",ep->control); 1093 printf("speed: %x\n",pipe->device->speed); 1094 printf("req: %p\n",req); 1095 printf("dmabuf: %p\n",xfer->dmabuf.block); */ 1096 1097 isread = req->bmRequestType & UT_READ; 1098 len = UGETW(req->wLength); 1099 1100 ep->next = ep; 1101 1102 td->buffer = DMAADDR(&reqdma,0) | 0xa0000000; 1103 td->buflen=sizeof(*req); 1104 td->control=ADMHCD_TD_SETUP | ADMHCD_TD_DATA0 | ADMHCD_TD_OWN; 1105 1106 if (len) { 1107 td->next = td1; 1108 1109 td1->buffer = DMAADDR(&xfer->dmabuf,0) | 0xa0000000; 1110 td1->buflen = len; 1111 td1->next = td2; 1112 td1->control= (isread?ADMHCD_TD_IN:ADMHCD_TD_OUT) | ADMHCD_TD_DATA1 | ADMHCD_TD_R | ADMHCD_TD_OWN; 1113 } else { 1114 td1->control = 0; 1115 td->next = td2; 1116 }; 1117 1118 td2->buffer = 0; 1119 td2->buflen= 0; 1120 td2->next = td3; 1121 td2->control = (isread?ADMHCD_TD_OUT:ADMHCD_TD_IN) | ADMHCD_TD_DATA1 | ADMHCD_TD_OWN; 1122 1123 td3->buffer = 0; 1124 td3->buflen= 0; 1125 td3->next = 0; 1126 td3->control = 0; 1127 1128 ep->head = td; 1129 ep->tail = td3; 1130 /* 1131 printf("ep: %p\n",ep); 1132 printf("ep->next: %p\n",ep->next); 1133 printf("ep->head: %p\n",ep->head); 1134 printf("ep->tail: %p\n",ep->tail); 1135 printf("td: %p\n",td); 1136 printf("td->next: %p\n",td->next); 1137 printf("td->buffer: %x\n",td->buffer); 1138 printf("td->buflen: %x\n",td->buflen); 1139 printf("td1: %p\n",td1); 1140 printf("td1->next: %p\n",td1->next); 1141 printf("td2: %p\n",td2); 1142 printf("td2->next: %p\n",td2->next); 1143 printf("td3: %p\n",td3); 1144 printf("td3->next: %p\n",td3->next); 1145 */ 1146 1147 REG_WRITE(ADMHCD_REG_HOSTHEAD, (u_int32_t)ep); 1148 REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP | ADMHCD_DMA_EN); 1149 /* printf("1: %x %x %x %x\n", ep->control, td->control, td1->control, td2->control); */ 1150 s=100; 1151 while (s--) { 1152 delay_ms(10); 1153 /* printf("%x %x %x %x\n", ep->control, td->control, td1->control, td2->control);*/ 1154 status = USBD_TIMEOUT; 1155 if (td->control & ADMHCD_TD_OWN) continue; 1156 1157 err = (td->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT; 1158 if (err) { 1159 status = USBD_IOERROR; 1160 break; 1161 }; 1162 1163 status = USBD_TIMEOUT; 1164 if (td1->control & ADMHCD_TD_OWN) continue; 1165 err = (td1->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT; 1166 if (err) { 1167 status = USBD_IOERROR; 1168 break; 1169 }; 1170 1171 status = USBD_TIMEOUT; 1172 if (td2->control & ADMHCD_TD_OWN) continue; 1173 err = (td2->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT; 1174 if (err) { 1175 status = USBD_IOERROR; 1176 }; 1177 status = USBD_NORMAL_COMPLETION; 1178 break; 1179 1180 }; 1181 REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP); 1182 1183 xfer->actlen = len; 1184 xfer->status = status; 1185 1186 sc->busy--; 1187 /* printf("ctrl_start<<<\n"); */ 1188 1189 s = splusb(); 1190 usb_transfer_complete(xfer); 1191 splx(s); 1192 return USBD_IN_PROGRESS; 1193 } 1194 1195 static void 1196 ahci_device_ctrl_abort(usbd_xfer_handle xfer) 1197 { 1198 DPRINTF(D_TRACE, ("Cab ")); 1199 ahci_abort_xfer(xfer, USBD_CANCELLED); 1200 } 1201 1202 static void 1203 ahci_device_ctrl_close(usbd_pipe_handle pipe) 1204 { 1205 DPRINTF(D_TRACE, ("Ccl ")); 1206 } 1207 1208 static void 1209 ahci_device_ctrl_done(usbd_xfer_handle xfer) 1210 { 1211 DPRINTF(D_TRACE, ("Cdn ")); 1212 } 1213 1214 static usbd_status 1215 ahci_device_intr_transfer(usbd_xfer_handle xfer) 1216 { 1217 usbd_status error; 1218 1219 DPRINTF(D_TRACE, ("INTRtrans ")); 1220 1221 error = usb_insert_transfer(xfer); 1222 if (error) 1223 return error; 1224 1225 return ahci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); 1226 } 1227 1228 static usbd_status 1229 ahci_device_intr_start(usbd_xfer_handle xfer) 1230 { 1231 usbd_pipe_handle pipe = xfer->pipe; 1232 struct ahci_xfer *sx; 1233 1234 DPRINTF(D_TRACE, ("INTRstart ")); 1235 1236 sx = malloc(sizeof(*sx), M_USB, M_NOWAIT); 1237 if (sx == NULL) 1238 goto reterr; 1239 memset(sx, 0, sizeof(*sx)); 1240 sx->sx_xfer = xfer; 1241 xfer->hcpriv = sx; 1242 1243 /* initialize callout */ 1244 callout_init(&sx->sx_callout_t, 0); 1245 callout_reset(&sx->sx_callout_t, 1246 MS_TO_TICKS(pipe->endpoint->edesc->bInterval), 1247 ahci_poll_device, sx); 1248 1249 /* ACK */ 1250 return USBD_IN_PROGRESS; 1251 1252 reterr: 1253 return USBD_IOERROR; 1254 } 1255 1256 static void 1257 ahci_poll_device(void *arg) 1258 { 1259 struct ahci_xfer *sx = (struct ahci_xfer *)arg; 1260 usbd_xfer_handle xfer = sx->sx_xfer; 1261 usbd_pipe_handle pipe = xfer->pipe; 1262 struct ahci_softc *sc = (struct ahci_softc *)pipe->device->bus; 1263 void *buf; 1264 int pid; 1265 int r; 1266 int s; 1267 1268 DPRINTF(D_TRACE, ("pldev")); 1269 1270 callout_reset(&sx->sx_callout_t, 1271 MS_TO_TICKS(pipe->endpoint->edesc->bInterval), 1272 ahci_poll_device, sx); 1273 1274 /* interrupt transfer */ 1275 pid = (UE_GET_DIR(pipe->endpoint->edesc->bEndpointAddress) == UE_DIR_IN) 1276 ? ADMHCD_TD_IN : ADMHCD_TD_OUT; 1277 buf = KERNADDR(&xfer->dmabuf, 0); 1278 1279 r = ahci_transaction(sc, pipe, pid, xfer->length, buf, 0/*toggle*/); 1280 if (r < 0) { 1281 DPRINTF(D_MSG, ("%s error", __func__)); 1282 return; 1283 } 1284 /* no change, return NAK */ 1285 if (r == 0) 1286 return; 1287 1288 xfer->status = USBD_NORMAL_COMPLETION; 1289 s = splusb(); 1290 usb_transfer_complete(xfer); 1291 splx(s); 1292 } 1293 1294 static void 1295 ahci_device_intr_abort(usbd_xfer_handle xfer) 1296 { 1297 struct ahci_xfer *sx; 1298 1299 DPRINTF(D_TRACE, ("INTRabort ")); 1300 1301 sx = xfer->hcpriv; 1302 if (sx) { 1303 callout_stop(&sx->sx_callout_t); 1304 free(sx, M_USB); 1305 xfer->hcpriv = NULL; 1306 } else { 1307 printf("%s: sx == NULL!\n", __func__); 1308 } 1309 ahci_abort_xfer(xfer, USBD_CANCELLED); 1310 } 1311 1312 static void 1313 ahci_device_intr_close(usbd_pipe_handle pipe) 1314 { 1315 DPRINTF(D_TRACE, ("INTRclose ")); 1316 } 1317 1318 static void 1319 ahci_device_intr_done(usbd_xfer_handle xfer) 1320 { 1321 DPRINTF(D_TRACE, ("INTRdone ")); 1322 } 1323 1324 static usbd_status 1325 ahci_device_isoc_transfer(usbd_xfer_handle xfer) 1326 { 1327 DPRINTF(D_TRACE, ("S")); 1328 return USBD_NORMAL_COMPLETION; 1329 } 1330 1331 static usbd_status 1332 ahci_device_isoc_start(usbd_xfer_handle xfer) 1333 { 1334 DPRINTF(D_TRACE, ("st ")); 1335 return USBD_NORMAL_COMPLETION; 1336 } 1337 1338 static void 1339 ahci_device_isoc_abort(usbd_xfer_handle xfer) 1340 { 1341 DPRINTF(D_TRACE, ("Sab ")); 1342 } 1343 1344 static void 1345 ahci_device_isoc_close(usbd_pipe_handle pipe) 1346 { 1347 DPRINTF(D_TRACE, ("Scl ")); 1348 } 1349 1350 static void 1351 ahci_device_isoc_done(usbd_xfer_handle xfer) 1352 { 1353 DPRINTF(D_TRACE, ("Sdn ")); 1354 } 1355 1356 static usbd_status 1357 ahci_device_bulk_transfer(usbd_xfer_handle xfer) 1358 { 1359 usbd_status error; 1360 1361 DPRINTF(D_TRACE, ("B")); 1362 1363 error = usb_insert_transfer(xfer); 1364 if (error) 1365 return error; 1366 1367 return ahci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); 1368 } 1369 1370 static usbd_status 1371 ahci_device_bulk_start(usbd_xfer_handle xfer) 1372 { 1373 #define NBULK_TDS 32 1374 static volatile int level = 0; 1375 usbd_status status = USBD_NORMAL_COMPLETION; 1376 int s, err; 1377 static struct admhcd_ed ep_v __attribute__((aligned(16))), *ep; 1378 static struct admhcd_td td_v[NBULK_TDS] __attribute__((aligned(16))), *td[NBULK_TDS]; 1379 usbd_pipe_handle pipe = xfer->pipe; 1380 struct ahci_softc *sc = (struct ahci_softc *)pipe->device->bus; 1381 int endpt, i, len, tlen, segs, offset, isread, toggle, short_ok; 1382 struct ahci_pipe *apipe = (struct ahci_pipe *)xfer->pipe; 1383 1384 #define KSEG1ADDR(x) (0xa0000000 | (((u_int32_t)x) & 0x1fffffff)) 1385 DPRINTF(D_TRACE, ("st ")); 1386 1387 #ifdef DIAGNOSTIC 1388 if (xfer->rqflags & URQ_REQUEST) { 1389 /* XXX panic */ 1390 printf("ohci_device_bulk_start: a request\n"); 1391 return (USBD_INVAL); 1392 } 1393 #endif 1394 1395 while (sc->busy) { 1396 delay_ms(10); 1397 }; 1398 sc->busy++; 1399 level++; 1400 /* printf("bulk_start>>>\n"); */ 1401 1402 if (!ep) { 1403 ep = (struct admhcd_ed *)KSEG1ADDR(&ep_v); 1404 for (i=0; i<NBULK_TDS; i++) { 1405 td[i] = (struct admhcd_td *)KSEG1ADDR(&td_v[i]); 1406 }; 1407 /* printf("ep: %p\n",ep);*/ 1408 }; 1409 if (apipe->toggle == 0) { 1410 toggle = ADMHCD_TD_DATA0; 1411 } else { 1412 toggle = apipe->toggle; 1413 }; 1414 1415 endpt = pipe->endpoint->edesc->bEndpointAddress; 1416 ep->control = pipe->device->address | ((endpt & 0xf) << ADMHCD_ED_EPSHIFT)|\ 1417 ((pipe->device->speed==USB_SPEED_FULL)?ADMHCD_ED_SPEED:0) | \ 1418 ((UGETW(pipe->endpoint->edesc->wMaxPacketSize))<<ADMHCD_ED_MAXSHIFT); 1419 1420 short_ok = xfer->flags & USBD_SHORT_XFER_OK?ADMHCD_TD_R:0; 1421 /* printf("level: %d\n",level); 1422 printf("short_xfer: %x\n",short_ok); 1423 printf("ep_control: %x\n",ep->control); 1424 printf("speed: %x\n",pipe->device->speed); 1425 printf("dmabuf: %p\n",xfer->dmabuf.block); */ 1426 1427 isread = UE_GET_DIR(endpt) == UE_DIR_IN; 1428 len = xfer->length; 1429 1430 ep->next = ep; 1431 1432 i = 0; 1433 offset = 0; 1434 while ((len>0) || (i==0)) { 1435 tlen = min(len,4096); 1436 td[i]->buffer = DMAADDR(&xfer->dmabuf,offset) | 0xa0000000; 1437 td[i]->buflen=tlen; 1438 td[i]->control=(isread?ADMHCD_TD_IN:ADMHCD_TD_OUT) | toggle | ADMHCD_TD_OWN | short_ok; 1439 td[i]->len=tlen; 1440 toggle = ADMHCD_TD_TOGGLE; 1441 len -= tlen; 1442 offset += tlen; 1443 td[i]->next = td[i+1]; 1444 i++; 1445 }; 1446 1447 td[i]->buffer = 0; 1448 td[i]->buflen = 0; 1449 td[i]->control = 0; 1450 td[i]->next = 0; 1451 1452 ep->head = td[0]; 1453 ep->tail = td[i]; 1454 segs = i; 1455 len = 0; 1456 1457 /* printf("segs: %d\n",segs); 1458 printf("ep: %p\n",ep); 1459 printf("ep->control: %x\n",ep->control); 1460 printf("ep->next: %p\n",ep->next); 1461 printf("ep->head: %p\n",ep->head); 1462 printf("ep->tail: %p\n",ep->tail); 1463 for (i=0; i<segs; i++) { 1464 printf("td[%d]: %p\n",i,td[i]); 1465 printf("td[%d]->control: %x\n",i,td[i]->control); 1466 printf("td[%d]->next: %p\n",i,td[i]->next); 1467 printf("td[%d]->buffer: %x\n",i,td[i]->buffer); 1468 printf("td[%d]->buflen: %x\n",i,td[i]->buflen); 1469 }; */ 1470 1471 REG_WRITE(ADMHCD_REG_HOSTHEAD, (u_int32_t)ep); 1472 REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP | ADMHCD_DMA_EN); 1473 i = 0; 1474 /* printf("1: %x %d %x %x\n", ep->control, i, td[i]->control, td[i]->buflen); */ 1475 s=100; 1476 err = 0; 1477 while (s--) { 1478 /* printf("%x %d %x %x\n", ep->control, i, td[i]->control, td[i]->buflen); */ 1479 status = USBD_TIMEOUT; 1480 if (td[i]->control & ADMHCD_TD_OWN) { 1481 delay_ms(3); 1482 continue; 1483 }; 1484 1485 len += td[i]->len - td[i]->buflen; 1486 1487 err = (td[i]->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT; 1488 if (err) { 1489 status = USBD_IOERROR; 1490 break; 1491 }; 1492 1493 i++; 1494 if (i==segs) { 1495 status = USBD_NORMAL_COMPLETION; 1496 break; 1497 }; 1498 1499 }; 1500 REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP); 1501 1502 apipe->toggle = ((u_int32_t)ep->head & 2)?ADMHCD_TD_DATA1:ADMHCD_TD_DATA0; 1503 /* printf("bulk_transfer_done: status: %x, err: %x, len: %x, toggle: %x\n", status,err,len,apipe->toggle); */ 1504 1505 if (short_ok && (err == 0x9 || err == 0xd)) { 1506 /* printf("bulk_transfer_done: short_transfer fix\n"); */ 1507 status = USBD_NORMAL_COMPLETION; 1508 }; 1509 xfer->actlen = len; 1510 xfer->status = status; 1511 1512 level--; 1513 sc->busy--; 1514 /* printf("bulk_start<<<\n"); */ 1515 1516 s = splusb(); 1517 usb_transfer_complete(xfer); 1518 splx(s); 1519 return USBD_IN_PROGRESS; 1520 } 1521 1522 static void 1523 ahci_device_bulk_abort(usbd_xfer_handle xfer) 1524 { 1525 DPRINTF(D_TRACE, ("Bab ")); 1526 ahci_abort_xfer(xfer, USBD_CANCELLED); 1527 } 1528 1529 static void 1530 ahci_device_bulk_close(usbd_pipe_handle pipe) 1531 { 1532 DPRINTF(D_TRACE, ("Bcl ")); 1533 } 1534 1535 static void 1536 ahci_device_bulk_done(usbd_xfer_handle xfer) 1537 { 1538 DPRINTF(D_TRACE, ("Bdn ")); 1539 } 1540 1541 #define DATA0_RD (0x03) 1542 #define DATA0_WR (0x07) 1543 #define AHCI_TIMEOUT (5000) 1544 1545 /* 1546 * Do a transaction. 1547 * return 1 if ACK, 0 if NAK, -1 if error. 1548 */ 1549 static int 1550 ahci_transaction(struct ahci_softc *sc, usbd_pipe_handle pipe, 1551 u_int8_t pid, int len, u_char *buf, u_int8_t toggle) 1552 { 1553 return -1; 1554 #if 0 1555 #ifdef AHCI_DEBUG 1556 char str[64]; 1557 int i; 1558 #endif 1559 int timeout; 1560 int ls_via_hub = 0; 1561 int pl; 1562 u_int8_t isr; 1563 u_int8_t result = 0; 1564 u_int8_t devaddr = pipe->device->address; 1565 u_int8_t endpointaddr = pipe->endpoint->edesc->bEndpointAddress; 1566 u_int8_t endpoint; 1567 u_int8_t cmd = DATA0_RD; 1568 1569 endpoint = UE_GET_ADDR(endpointaddr); 1570 DPRINTF(D_XFER, ("\n(%x,%d%s%d,%d) ", 1571 pid, len, (pid == SL11_PID_IN) ? "<-" : "->", devaddr, endpoint)); 1572 1573 /* Set registers */ 1574 sl11write(sc, SL11_E0ADDR, 0x40); 1575 sl11write(sc, SL11_E0LEN, len); 1576 sl11write(sc, SL11_E0PID, (pid << 4) + endpoint); 1577 sl11write(sc, SL11_E0DEV, devaddr); 1578 1579 /* Set buffer unless PID_IN */ 1580 if (pid != SL11_PID_IN) { 1581 if (len > 0) 1582 sl11write_region(sc, 0x40, buf, len); 1583 cmd = DATA0_WR; 1584 } 1585 1586 /* timing ? */ 1587 pl = (len >> 3) + 3; 1588 1589 /* Low speed device via HUB */ 1590 /* XXX does not work... */ 1591 if ((sc->sc_fullspeed) && pipe->device->speed == USB_SPEED_LOW) { 1592 pl = len + 16; 1593 cmd |= SL11_EPCTRL_PREAMBLE; 1594 1595 /* 1596 * SL811HS/T rev 1.2 has a bug, when it got PID_IN 1597 * from LowSpeed device via HUB. 1598 */ 1599 if (sc->sc_sltype == SLTYPE_SL811HS_R12 && pid == SL11_PID_IN) { 1600 ls_via_hub = 1; 1601 DPRINTF(D_MSG, ("LSvH ")); 1602 } 1603 } 1604 1605 /* timing ? */ 1606 if (sl11read(sc, SL811_CSOF) <= (u_int8_t)pl) 1607 cmd |= SL11_EPCTRL_SOF; 1608 1609 /* Transfer */ 1610 sl11write(sc, SL11_ISR, 0xff); 1611 sl11write(sc, SL11_E0CTRL, cmd | toggle); 1612 1613 /* Polling */ 1614 for (timeout = AHCI_TIMEOUT; timeout; timeout--) { 1615 isr = sl11read(sc, SL11_ISR); 1616 if ((isr & SL11_ISR_USBA)) 1617 break; 1618 } 1619 1620 /* Check result status */ 1621 result = sl11read(sc, SL11_E0STAT); 1622 if (!(result & SL11_EPSTAT_NAK) && ls_via_hub) { 1623 /* Resend PID_IN within 20usec */ 1624 sl11write(sc, SL11_ISR, 0xff); 1625 sl11write(sc, SL11_E0CTRL, SL11_EPCTRL_ARM); 1626 } 1627 1628 sl11write(sc, SL11_ISR, 0xff); 1629 1630 DPRINTF(D_XFER, ("t=%d i=%x ", AHCI_TIMEOUT - timeout, isr)); 1631 #if AHCI_DEBUG 1632 snprintb(str, sizeof(str), 1633 "\20\x8STALL\7NAK\6OV\5SETUP\4DATA1\3TIMEOUT\2ERR\1ACK", result); 1634 DPRINTF(D_XFER, ("STAT=%s ", str)); 1635 #endif 1636 1637 if ((result & SL11_EPSTAT_ERROR)) 1638 return -1; 1639 1640 if ((result & SL11_EPSTAT_NAK)) 1641 return 0; 1642 1643 /* Read buffer if PID_IN */ 1644 if (pid == SL11_PID_IN && len > 0) { 1645 sl11read_region(sc, buf, 0x40, len); 1646 #if AHCI_DEBUG 1647 for (i = 0; i < len; i++) 1648 DPRINTF(D_XFER, ("%02X ", buf[i])); 1649 #endif 1650 } 1651 1652 return 1; 1653 #endif 1654 } 1655 1656 void 1657 ahci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) 1658 { 1659 xfer->status = status; 1660 usb_transfer_complete(xfer); 1661 } 1662 1663 void 1664 ahci_device_clear_toggle(usbd_pipe_handle pipe) 1665 { 1666 struct ahci_pipe *apipe = (struct ahci_pipe *)pipe; 1667 apipe->toggle = 0; 1668 } 1669 1670 #ifdef AHCI_DEBUG 1671 void 1672 print_req(usb_device_request_t *r) 1673 { 1674 const char *xmes[]={ 1675 "GETSTAT", 1676 "CLRFEAT", 1677 "res", 1678 "SETFEAT", 1679 "res", 1680 "SETADDR", 1681 "GETDESC", 1682 "SETDESC", 1683 "GETCONF", 1684 "SETCONF", 1685 "GETIN/F", 1686 "SETIN/F", 1687 "SYNC_FR" 1688 }; 1689 int req, type, value, index, len; 1690 1691 req = r->bRequest; 1692 type = r->bmRequestType; 1693 value = UGETW(r->wValue); 1694 index = UGETW(r->wIndex); 1695 len = UGETW(r->wLength); 1696 1697 printf("%x,%s,v=%d,i=%d,l=%d ", 1698 type, xmes[req], value, index, len); 1699 } 1700 1701 void 1702 print_req_hub(usb_device_request_t *r) 1703 { 1704 struct { 1705 int req; 1706 int type; 1707 const char *str; 1708 } conf[] = { 1709 { 1, 0x20, "ClrHubFeat" }, 1710 { 1, 0x23, "ClrPortFeat" }, 1711 { 2, 0xa3, "GetBusState" }, 1712 { 6, 0xa0, "GetHubDesc" }, 1713 { 0, 0xa0, "GetHubStat" }, 1714 { 0, 0xa3, "GetPortStat" }, 1715 { 7, 0x20, "SetHubDesc" }, 1716 { 3, 0x20, "SetHubFeat" }, 1717 { 3, 0x23, "SetPortFeat" }, 1718 {-1, 0, NULL}, 1719 }; 1720 int i; 1721 int value, index, len; 1722 1723 value = UGETW(r->wValue); 1724 index = UGETW(r->wIndex); 1725 len = UGETW(r->wLength); 1726 for (i = 0; ; i++) { 1727 if (conf[i].req == -1 ) 1728 return print_req(r); 1729 if (r->bmRequestType == conf[i].type && r->bRequest == conf[i].req) { 1730 printf("%s", conf[i].str); 1731 break; 1732 } 1733 } 1734 printf(",v=%d,i=%d,l=%d ", value, index, len); 1735 } 1736 1737 void 1738 print_dumpreg(struct ahci_softc *sc) 1739 { 1740 #if 0 1741 printf("00=%02x,01=%02x,02=%02x,03=%02x,04=%02x," 1742 "08=%02x,09=%02x,0A=%02x,0B=%02x,0C=%02x,", 1743 sl11read(sc, 0), sl11read(sc, 1), 1744 sl11read(sc, 2), sl11read(sc, 3), 1745 sl11read(sc, 4), sl11read(sc, 8), 1746 sl11read(sc, 9), sl11read(sc, 10), 1747 sl11read(sc, 11), sl11read(sc, 12) 1748 ); 1749 printf("CR1=%02x,IER=%02x,0D=%02x,0E=%02x,0F=%02x ", 1750 sl11read(sc, 5), sl11read(sc, 6), 1751 sl11read(sc, 13), sl11read(sc, 14), sl11read(sc, 15) 1752 ); 1753 #endif 1754 } 1755 1756 void 1757 print_xfer(usbd_xfer_handle xfer) 1758 { 1759 printf("xfer: length=%d, actlen=%d, flags=%x, timeout=%d,", 1760 xfer->length, xfer->actlen, xfer->flags, xfer->timeout); 1761 printf("request{ "); 1762 print_req_hub(&xfer->request); 1763 printf("} "); 1764 } 1765 #endif /* AHCI_DEBUG */ 1766