1 // Code for handling UHCI USB controllers. 2 // 3 // Copyright (C) 2009 Kevin O'Connor <kevin@koconnor.net> 4 // 5 // This file may be distributed under the terms of the GNU LGPLv3 license. 6 7 #include "biosvar.h" // GET_LOWFLAT 8 #include "config.h" // CONFIG_* 9 #include "malloc.h" // free 10 #include "output.h" // dprintf 11 #include "pci.h" // pci_config_writew 12 #include "pcidevice.h" // foreachpci 13 #include "pci_ids.h" // PCI_CLASS_SERIAL_USB_UHCI 14 #include "pci_regs.h" // PCI_BASE_ADDRESS_4 15 #include "string.h" // memset 16 #include "usb.h" // struct usb_s 17 #include "usb-ehci.h" // ehci_wait_controllers 18 #include "usb-uhci.h" // USBLEGSUP 19 #include "util.h" // msleep 20 #include "x86.h" // outw 21 22 struct usb_uhci_s { 23 struct usb_s usb; 24 u16 iobase; 25 struct uhci_qh *control_qh; 26 struct uhci_framelist *framelist; 27 }; 28 29 struct uhci_pipe { 30 struct uhci_qh qh; 31 struct uhci_td *next_td; 32 struct usb_pipe pipe; 33 u16 iobase; 34 u8 toggle; 35 }; 36 37 38 /**************************************************************** 39 * Root hub 40 ****************************************************************/ 41 42 // Check if device attached to a given port 43 static int 44 uhci_hub_detect(struct usbhub_s *hub, u32 port) 45 { 46 struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb); 47 u16 ioport = cntl->iobase + USBPORTSC1 + port * 2; 48 u16 status = inw(ioport); 49 if (!(status & USBPORTSC_CCS)) 50 // No device found. 51 return 0; 52 53 // XXX - if just powered up, need to wait for USB_TIME_ATTDB? 54 55 // Begin reset on port 56 outw(USBPORTSC_PR, ioport); 57 msleep(USB_TIME_DRSTR); 58 return 1; 59 } 60 61 // Reset device on port 62 static int 63 uhci_hub_reset(struct usbhub_s *hub, u32 port) 64 { 65 struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb); 66 u16 ioport = cntl->iobase + USBPORTSC1 + port * 2; 67 68 // Finish reset on port 69 outw(0, ioport); 70 udelay(6); // 64 high-speed bit times 71 u16 status = inw(ioport); 72 if (!(status & USBPORTSC_CCS)) 73 // No longer connected 74 return -1; 75 outw(USBPORTSC_PE, ioport); 76 return !!(status & USBPORTSC_LSDA); 77 } 78 79 // Disable port 80 static void 81 uhci_hub_disconnect(struct usbhub_s *hub, u32 port) 82 { 83 struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb); 84 u16 ioport = cntl->iobase + USBPORTSC1 + port * 2; 85 outw(0, ioport); 86 } 87 88 static struct usbhub_op_s uhci_HubOp = { 89 .detect = uhci_hub_detect, 90 .reset = uhci_hub_reset, 91 .disconnect = uhci_hub_disconnect, 92 }; 93 94 // Find any devices connected to the root hub. 95 static int 96 check_uhci_ports(struct usb_uhci_s *cntl) 97 { 98 ASSERT32FLAT(); 99 // Wait for ehci init - in case this is a "companion controller" 100 ehci_wait_controllers(); 101 102 struct usbhub_s hub; 103 memset(&hub, 0, sizeof(hub)); 104 hub.cntl = &cntl->usb; 105 hub.portcount = 2; 106 hub.op = &uhci_HubOp; 107 usb_enumerate(&hub); 108 return hub.devcount; 109 } 110 111 112 /**************************************************************** 113 * Setup 114 ****************************************************************/ 115 116 // Wait for next USB frame to start - for ensuring safe memory release. 117 static void 118 uhci_waittick(u16 iobase) 119 { 120 barrier(); 121 u16 startframe = inw(iobase + USBFRNUM); 122 u32 end = timer_calc(1000 * 5); 123 for (;;) { 124 if (inw(iobase + USBFRNUM) != startframe) 125 break; 126 if (timer_check(end)) { 127 warn_timeout(); 128 return; 129 } 130 yield(); 131 } 132 } 133 134 static void 135 uhci_free_pipes(struct usb_uhci_s *cntl) 136 { 137 dprintf(7, "uhci_free_pipes %p\n", cntl); 138 139 struct uhci_qh *pos = (void*)(cntl->framelist->links[0] & ~UHCI_PTR_BITS); 140 for (;;) { 141 u32 link = pos->link; 142 if (link == UHCI_PTR_TERM) 143 break; 144 struct uhci_qh *next = (void*)(link & ~UHCI_PTR_BITS); 145 struct uhci_pipe *pipe = container_of(next, struct uhci_pipe, qh); 146 if (usb_is_freelist(&cntl->usb, &pipe->pipe)) 147 pos->link = next->link; 148 else 149 pos = next; 150 } 151 uhci_waittick(cntl->iobase); 152 for (;;) { 153 struct usb_pipe *usbpipe = cntl->usb.freelist; 154 if (!usbpipe) 155 break; 156 cntl->usb.freelist = usbpipe->freenext; 157 struct uhci_pipe *pipe = container_of(usbpipe, struct uhci_pipe, pipe); 158 free(pipe); 159 } 160 } 161 162 static void 163 reset_uhci(struct usb_uhci_s *cntl, u16 bdf) 164 { 165 // XXX - don't reset if not needed. 166 167 // Reset PIRQ and SMI 168 pci_config_writew(bdf, USBLEGSUP, USBLEGSUP_RWC); 169 170 // Reset the HC 171 outw(USBCMD_HCRESET, cntl->iobase + USBCMD); 172 udelay(5); 173 174 // Disable interrupts and commands (just to be safe). 175 outw(0, cntl->iobase + USBINTR); 176 outw(0, cntl->iobase + USBCMD); 177 } 178 179 static void 180 configure_uhci(void *data) 181 { 182 struct usb_uhci_s *cntl = data; 183 184 // Allocate ram for schedule storage 185 struct uhci_td *term_td = malloc_high(sizeof(*term_td)); 186 struct uhci_framelist *fl = memalign_high(sizeof(*fl), sizeof(*fl)); 187 struct uhci_pipe *intr_pipe = malloc_high(sizeof(*intr_pipe)); 188 struct uhci_pipe *term_pipe = malloc_high(sizeof(*term_pipe)); 189 if (!term_td || !fl || !intr_pipe || !term_pipe) { 190 warn_noalloc(); 191 goto fail; 192 } 193 194 // Work around for PIIX errata 195 memset(term_td, 0, sizeof(*term_td)); 196 term_td->link = UHCI_PTR_TERM; 197 term_td->token = (uhci_explen(0) | (0x7f << TD_TOKEN_DEVADDR_SHIFT) 198 | USB_PID_IN); 199 memset(term_pipe, 0, sizeof(*term_pipe)); 200 term_pipe->qh.element = (u32)term_td; 201 term_pipe->qh.link = UHCI_PTR_TERM; 202 term_pipe->pipe.cntl = &cntl->usb; 203 204 // Set schedule to point to primary intr queue head 205 memset(intr_pipe, 0, sizeof(*intr_pipe)); 206 intr_pipe->qh.element = UHCI_PTR_TERM; 207 intr_pipe->qh.link = (u32)&term_pipe->qh | UHCI_PTR_QH; 208 intr_pipe->pipe.cntl = &cntl->usb; 209 int i; 210 for (i=0; i<ARRAY_SIZE(fl->links); i++) 211 fl->links[i] = (u32)&intr_pipe->qh | UHCI_PTR_QH; 212 cntl->framelist = fl; 213 cntl->control_qh = &intr_pipe->qh; 214 barrier(); 215 216 // Set the frame length to the default: 1 ms exactly 217 outb(USBSOF_DEFAULT, cntl->iobase + USBSOF); 218 219 // Store the frame list base address 220 outl((u32)fl->links, cntl->iobase + USBFLBASEADD); 221 222 // Set the current frame number 223 outw(0, cntl->iobase + USBFRNUM); 224 225 // Mark as configured and running with a 64-byte max packet. 226 outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, cntl->iobase + USBCMD); 227 228 // Find devices 229 int count = check_uhci_ports(cntl); 230 uhci_free_pipes(cntl); 231 if (count) 232 // Success 233 return; 234 235 // No devices found - shutdown and free controller. 236 outw(0, cntl->iobase + USBCMD); 237 fail: 238 free(term_td); 239 free(fl); 240 free(intr_pipe); 241 free(term_pipe); 242 free(cntl); 243 } 244 245 static void 246 uhci_controller_setup(struct pci_device *pci) 247 { 248 u16 iobase = pci_enable_iobar(pci, PCI_BASE_ADDRESS_4); 249 if (!iobase) 250 return; 251 252 struct usb_uhci_s *cntl = malloc_tmphigh(sizeof(*cntl)); 253 if (!cntl) { 254 warn_noalloc(); 255 return; 256 } 257 memset(cntl, 0, sizeof(*cntl)); 258 cntl->usb.pci = pci; 259 cntl->usb.type = USB_TYPE_UHCI; 260 cntl->iobase = iobase; 261 262 dprintf(1, "UHCI init on dev %pP (io=%x)\n", pci, cntl->iobase); 263 264 pci_enable_busmaster(pci); 265 266 reset_uhci(cntl, pci->bdf); 267 268 run_thread(configure_uhci, cntl); 269 } 270 271 void 272 uhci_setup(void) 273 { 274 if (! CONFIG_USB_UHCI) 275 return; 276 struct pci_device *pci; 277 foreachpci(pci) { 278 if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_UHCI) 279 uhci_controller_setup(pci); 280 } 281 } 282 283 284 /**************************************************************** 285 * End point communication 286 ****************************************************************/ 287 288 static struct usb_pipe * 289 uhci_alloc_intr_pipe(struct usbdevice_s *usbdev 290 , struct usb_endpoint_descriptor *epdesc) 291 { 292 struct usb_uhci_s *cntl = container_of( 293 usbdev->hub->cntl, struct usb_uhci_s, usb); 294 int frameexp = usb_get_period(usbdev, epdesc); 295 dprintf(7, "uhci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp); 296 297 if (frameexp > 10) 298 frameexp = 10; 299 int maxpacket = epdesc->wMaxPacketSize; 300 // Determine number of entries needed for 2 timer ticks. 301 int ms = 1<<frameexp; 302 int count = DIV_ROUND_UP(ticks_to_ms(2), ms); 303 count = ALIGN(count, 2); 304 struct uhci_pipe *pipe = malloc_low(sizeof(*pipe)); 305 struct uhci_td *tds = malloc_low(sizeof(*tds) * count); 306 void *data = malloc_low(maxpacket * count); 307 if (!pipe || !tds || !data) { 308 warn_noalloc(); 309 goto fail; 310 } 311 memset(pipe, 0, sizeof(*pipe)); 312 usb_desc2pipe(&pipe->pipe, usbdev, epdesc); 313 int lowspeed = pipe->pipe.speed; 314 int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7); 315 pipe->qh.element = (u32)tds; 316 pipe->next_td = &tds[0]; 317 pipe->iobase = cntl->iobase; 318 319 int toggle = 0; 320 int i; 321 for (i=0; i<count; i++) { 322 tds[i].link = (i==count-1 ? (u32)&tds[0] : (u32)&tds[i+1]); 323 tds[i].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0) 324 | TD_CTRL_ACTIVE); 325 tds[i].token = (uhci_explen(maxpacket) | toggle 326 | (devaddr << TD_TOKEN_DEVADDR_SHIFT) 327 | USB_PID_IN); 328 tds[i].buffer = data + maxpacket * i; 329 toggle ^= TD_TOKEN_TOGGLE; 330 } 331 332 // Add to interrupt schedule. 333 struct uhci_framelist *fl = cntl->framelist; 334 if (frameexp == 0) { 335 // Add to existing interrupt entry. 336 struct uhci_qh *intr_qh = (void*)(fl->links[0] & ~UHCI_PTR_BITS); 337 pipe->qh.link = intr_qh->link; 338 barrier(); 339 intr_qh->link = (u32)&pipe->qh | UHCI_PTR_QH; 340 if (cntl->control_qh == intr_qh) 341 cntl->control_qh = &pipe->qh; 342 } else { 343 int startpos = 1<<(frameexp-1); 344 pipe->qh.link = fl->links[startpos]; 345 barrier(); 346 for (i=startpos; i<ARRAY_SIZE(fl->links); i+=ms) 347 fl->links[i] = (u32)&pipe->qh | UHCI_PTR_QH; 348 } 349 350 return &pipe->pipe; 351 fail: 352 free(pipe); 353 free(tds); 354 free(data); 355 return NULL; 356 } 357 358 struct usb_pipe * 359 uhci_realloc_pipe(struct usbdevice_s *usbdev, struct usb_pipe *upipe 360 , struct usb_endpoint_descriptor *epdesc) 361 { 362 if (! CONFIG_USB_UHCI) 363 return NULL; 364 usb_add_freelist(upipe); 365 if (!epdesc) 366 return NULL; 367 u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; 368 if (eptype == USB_ENDPOINT_XFER_INT) 369 return uhci_alloc_intr_pipe(usbdev, epdesc); 370 struct usb_uhci_s *cntl = container_of( 371 usbdev->hub->cntl, struct usb_uhci_s, usb); 372 dprintf(7, "uhci_alloc_async_pipe %p %d\n", &cntl->usb, eptype); 373 374 struct usb_pipe *usbpipe = usb_get_freelist(&cntl->usb, eptype); 375 if (usbpipe) { 376 // Use previously allocated pipe. 377 usb_desc2pipe(usbpipe, usbdev, epdesc); 378 return usbpipe; 379 } 380 381 // Allocate a new queue head. 382 struct uhci_pipe *pipe; 383 if (eptype == USB_ENDPOINT_XFER_CONTROL) 384 pipe = malloc_tmphigh(sizeof(*pipe)); 385 else 386 pipe = malloc_low(sizeof(*pipe)); 387 if (!pipe) { 388 warn_noalloc(); 389 return NULL; 390 } 391 memset(pipe, 0, sizeof(*pipe)); 392 usb_desc2pipe(&pipe->pipe, usbdev, epdesc); 393 pipe->qh.element = UHCI_PTR_TERM; 394 pipe->iobase = cntl->iobase; 395 396 // Add queue head to controller list. 397 struct uhci_qh *control_qh = cntl->control_qh; 398 pipe->qh.link = control_qh->link; 399 barrier(); 400 control_qh->link = (u32)&pipe->qh | UHCI_PTR_QH; 401 if (eptype == USB_ENDPOINT_XFER_CONTROL) 402 cntl->control_qh = &pipe->qh; 403 return &pipe->pipe; 404 } 405 406 static int 407 wait_pipe(struct uhci_pipe *pipe, u32 end) 408 { 409 for (;;) { 410 u32 el_link = GET_LOWFLAT(pipe->qh.element); 411 if (el_link & UHCI_PTR_TERM) 412 return 0; 413 if (timer_check(end)) { 414 warn_timeout(); 415 u16 iobase = GET_LOWFLAT(pipe->iobase); 416 struct uhci_td *td = (void*)(el_link & ~UHCI_PTR_BITS); 417 dprintf(1, "Timeout on wait_pipe %p (td=%p s=%x c=%x/%x)\n" 418 , pipe, (void*)el_link, GET_LOWFLAT(td->status) 419 , inw(iobase + USBCMD) 420 , inw(iobase + USBSTS)); 421 SET_LOWFLAT(pipe->qh.element, UHCI_PTR_TERM); 422 uhci_waittick(iobase); 423 return -1; 424 } 425 yield(); 426 } 427 } 428 429 static int 430 wait_td(struct uhci_td *td, u32 end) 431 { 432 u32 status; 433 for (;;) { 434 status = td->status; 435 if (!(status & TD_CTRL_ACTIVE)) 436 break; 437 if (timer_check(end)) { 438 warn_timeout(); 439 return -1; 440 } 441 yield(); 442 } 443 if (status & TD_CTRL_ANY_ERROR) { 444 dprintf(1, "wait_td error - status=%x\n", status); 445 return -2; 446 } 447 return 0; 448 } 449 450 #define STACKTDS 16 451 #define TDALIGN 16 452 453 int 454 uhci_send_pipe(struct usb_pipe *p, int dir, const void *cmd 455 , void *data, int datasize) 456 { 457 if (! CONFIG_USB_UHCI) 458 return -1; 459 struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe); 460 dprintf(7, "uhci_send_pipe qh=%p dir=%d data=%p size=%d\n" 461 , &pipe->qh, dir, data, datasize); 462 int maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket); 463 int lowspeed = GET_LOWFLAT(pipe->pipe.speed); 464 int devaddr = (GET_LOWFLAT(pipe->pipe.devaddr) 465 | (GET_LOWFLAT(pipe->pipe.ep) << 7)); 466 int toggle = GET_LOWFLAT(pipe->toggle) ? TD_TOKEN_TOGGLE : 0; 467 468 // Allocate 16 tds on stack (16byte aligned) 469 u8 tdsbuf[sizeof(struct uhci_td) * STACKTDS + TDALIGN - 1]; 470 struct uhci_td *tds = (void*)ALIGN((u32)tdsbuf, TDALIGN); 471 memset(tds, 0, sizeof(*tds) * STACKTDS); 472 int tdpos = 0; 473 474 // Enable tds 475 u32 end = timer_calc(usb_xfer_time(p, datasize)); 476 barrier(); 477 SET_LOWFLAT(pipe->qh.element, (u32)MAKE_FLATPTR(GET_SEG(SS), tds)); 478 479 // Setup transfer descriptors 480 if (cmd) { 481 // Send setup pid on control transfers 482 struct uhci_td *td = &tds[tdpos++ % STACKTDS]; 483 u32 nexttd = (u32)MAKE_FLATPTR(GET_SEG(SS), &tds[tdpos % STACKTDS]); 484 td->link = nexttd | UHCI_PTR_DEPTH; 485 td->token = (uhci_explen(USB_CONTROL_SETUP_SIZE) 486 | (devaddr << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_SETUP); 487 td->buffer = (void*)cmd; 488 barrier(); 489 td->status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0) 490 | TD_CTRL_ACTIVE); 491 toggle = TD_TOKEN_TOGGLE; 492 } 493 while (datasize) { 494 // Send data pids 495 struct uhci_td *td = &tds[tdpos++ % STACKTDS]; 496 int ret = wait_td(td, end); 497 if (ret) 498 goto fail; 499 500 int transfer = datasize; 501 if (transfer > maxpacket) 502 transfer = maxpacket; 503 u32 nexttd = (u32)MAKE_FLATPTR(GET_SEG(SS), &tds[tdpos % STACKTDS]); 504 td->link = ((transfer==datasize && !cmd) 505 ? UHCI_PTR_TERM : (nexttd | UHCI_PTR_DEPTH)); 506 td->token = (uhci_explen(transfer) | toggle 507 | (devaddr << TD_TOKEN_DEVADDR_SHIFT) 508 | (dir ? USB_PID_IN : USB_PID_OUT)); 509 td->buffer = data; 510 barrier(); 511 td->status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0) 512 | TD_CTRL_ACTIVE); 513 toggle ^= TD_TOKEN_TOGGLE; 514 515 data += transfer; 516 datasize -= transfer; 517 } 518 if (cmd) { 519 // Send status pid on control transfers 520 struct uhci_td *td = &tds[tdpos++ % STACKTDS]; 521 int ret = wait_td(td, end); 522 if (ret) 523 goto fail; 524 td->link = UHCI_PTR_TERM; 525 td->token = (uhci_explen(0) | TD_TOKEN_TOGGLE 526 | (devaddr << TD_TOKEN_DEVADDR_SHIFT) 527 | (dir ? USB_PID_OUT : USB_PID_IN)); 528 td->buffer = 0; 529 barrier(); 530 td->status = (uhci_maxerr(0) | (lowspeed ? TD_CTRL_LS : 0) 531 | TD_CTRL_ACTIVE); 532 } 533 SET_LOWFLAT(pipe->toggle, !!toggle); 534 return wait_pipe(pipe, end); 535 fail: 536 dprintf(1, "uhci_send_bulk failed\n"); 537 SET_LOWFLAT(pipe->qh.element, UHCI_PTR_TERM); 538 uhci_waittick(GET_LOWFLAT(pipe->iobase)); 539 return -1; 540 } 541 542 int 543 uhci_poll_intr(struct usb_pipe *p, void *data) 544 { 545 ASSERT16(); 546 if (! CONFIG_USB_UHCI) 547 return -1; 548 549 struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe); 550 struct uhci_td *td = GET_LOWFLAT(pipe->next_td); 551 u32 status = GET_LOWFLAT(td->status); 552 u32 token = GET_LOWFLAT(td->token); 553 if (status & TD_CTRL_ACTIVE) 554 // No intrs found. 555 return -1; 556 // XXX - check for errors. 557 558 // Copy data. 559 void *tddata = GET_LOWFLAT(td->buffer); 560 memcpy_far(GET_SEG(SS), data, SEG_LOW, LOWFLAT2LOW(tddata) 561 , uhci_expected_length(token)); 562 563 // Reenable this td. 564 struct uhci_td *next = (void*)(GET_LOWFLAT(td->link) & ~UHCI_PTR_BITS); 565 SET_LOWFLAT(pipe->next_td, next); 566 barrier(); 567 SET_LOWFLAT(td->status, (uhci_maxerr(0) | (status & TD_CTRL_LS) 568 | TD_CTRL_ACTIVE)); 569 570 return 0; 571 } 572