1 /* 2 * Copyright 2006-2011, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 * Jérôme Duval <korli@users.berlios.de> 8 */ 9 10 11 #include <stdio.h> 12 13 #include <driver_settings.h> 14 #include <PCI_x86.h> 15 #include <bus/PCI.h> 16 #include <USB3.h> 17 #include <KernelExport.h> 18 19 #include "ehci.h" 20 21 22 #define CALLED(x...) TRACE_MODULE("CALLED %s\n", __PRETTY_FUNCTION__) 23 24 #define USB_MODULE_NAME "ehci" 25 26 27 static pci_x86_module_info* sPCIx86Module = NULL; 28 device_manager_info* gDeviceManager; 29 static usb_for_controller_interface* gUSB; 30 31 32 #define EHCI_PCI_DEVICE_MODULE_NAME "busses/usb/ehci/pci/driver_v1" 33 #define EHCI_PCI_USB_BUS_MODULE_NAME "busses/usb/ehci/device_v1" 34 35 36 typedef struct { 37 EHCI* ehci; 38 pci_device_module_info* pci; 39 pci_device* device; 40 41 pci_info pciinfo; 42 43 device_node* node; 44 device_node* driver_node; 45 } ehci_pci_sim_info; 46 47 48 // #pragma mark - 49 50 51 static status_t 52 init_bus(device_node* node, void** bus_cookie) 53 { 54 CALLED(); 55 56 driver_module_info* driver; 57 ehci_pci_sim_info* bus; 58 device_node* parent = gDeviceManager->get_parent_node(node); 59 gDeviceManager->get_driver(parent, &driver, (void**)&bus); 60 gDeviceManager->put_node(parent); 61 62 Stack *stack; 63 if (gUSB->get_stack((void**)&stack) != B_OK) 64 return B_ERROR; 65 66 EHCI *ehci = new(std::nothrow) EHCI(&bus->pciinfo, bus->pci, bus->device, stack, node); 67 if (ehci == NULL) { 68 return B_NO_MEMORY; 69 } 70 71 if (ehci->InitCheck() < B_OK) { 72 TRACE_MODULE_ERROR("bus failed init check\n"); 73 delete ehci; 74 return B_ERROR; 75 } 76 77 if (ehci->Start() != B_OK) { 78 delete ehci; 79 return B_ERROR; 80 } 81 82 *bus_cookie = ehci; 83 84 return B_OK; 85 } 86 87 88 static void 89 uninit_bus(void* bus_cookie) 90 { 91 CALLED(); 92 EHCI* ehci = (EHCI*)bus_cookie; 93 delete ehci; 94 } 95 96 97 static status_t 98 register_child_devices(void* cookie) 99 { 100 CALLED(); 101 ehci_pci_sim_info* bus = (ehci_pci_sim_info*)cookie; 102 device_node* node = bus->driver_node; 103 104 char prettyName[25]; 105 sprintf(prettyName, "EHCI Controller %" B_PRIu16, 0); 106 107 device_attr attrs[] = { 108 // properties of this controller for the usb bus manager 109 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, 110 { .string = prettyName }}, 111 { B_DEVICE_FIXED_CHILD, B_STRING_TYPE, 112 { .string = USB_FOR_CONTROLLER_MODULE_NAME }}, 113 114 // private data to identify the device 115 { NULL } 116 }; 117 118 return gDeviceManager->register_node(node, EHCI_PCI_USB_BUS_MODULE_NAME, 119 attrs, NULL, NULL); 120 } 121 122 123 static status_t 124 init_device(device_node* node, void** device_cookie) 125 { 126 CALLED(); 127 ehci_pci_sim_info* bus = (ehci_pci_sim_info*)calloc(1, 128 sizeof(ehci_pci_sim_info)); 129 if (bus == NULL) 130 return B_NO_MEMORY; 131 132 pci_device_module_info* pci; 133 pci_device* device; 134 { 135 device_node* pciParent = gDeviceManager->get_parent_node(node); 136 gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci, 137 (void**)&device); 138 gDeviceManager->put_node(pciParent); 139 } 140 141 bus->pci = pci; 142 bus->device = device; 143 bus->driver_node = node; 144 145 pci_info *pciInfo = &bus->pciinfo; 146 pci->get_pci_info(device, pciInfo); 147 148 *device_cookie = bus; 149 return B_OK; 150 } 151 152 153 static void 154 uninit_device(void* device_cookie) 155 { 156 CALLED(); 157 ehci_pci_sim_info* bus = (ehci_pci_sim_info*)device_cookie; 158 free(bus); 159 160 } 161 162 163 static status_t 164 register_device(device_node* parent) 165 { 166 CALLED(); 167 device_attr attrs[] = { 168 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "EHCI PCI"}}, 169 {} 170 }; 171 172 return gDeviceManager->register_node(parent, 173 EHCI_PCI_DEVICE_MODULE_NAME, attrs, NULL, NULL); 174 } 175 176 177 static float 178 supports_device(device_node* parent) 179 { 180 CALLED(); 181 const char* bus; 182 uint16 type, subType, api; 183 184 // make sure parent is a EHCI PCI device node 185 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false) 186 < B_OK) { 187 return -1; 188 } 189 190 if (strcmp(bus, "pci") != 0) 191 return 0.0f; 192 193 if (gDeviceManager->get_attr_uint16(parent, B_DEVICE_SUB_TYPE, &subType, 194 false) < B_OK 195 || gDeviceManager->get_attr_uint16(parent, B_DEVICE_TYPE, &type, 196 false) < B_OK 197 || gDeviceManager->get_attr_uint16(parent, B_DEVICE_INTERFACE, &api, 198 false) < B_OK) { 199 TRACE_MODULE("Could not find type/subtype/interface attributes\n"); 200 return -1; 201 } 202 203 if (type == PCI_serial_bus && subType == PCI_usb && api == PCI_usb_ehci) { 204 pci_device_module_info* pci; 205 pci_device* device; 206 gDeviceManager->get_driver(parent, (driver_module_info**)&pci, 207 (void**)&device); 208 TRACE_MODULE("EHCI Device found!\n"); 209 210 return 0.8f; 211 } 212 213 return 0.0f; 214 } 215 216 217 module_dependency module_dependencies[] = { 218 { USB_FOR_CONTROLLER_MODULE_NAME, (module_info**)&gUSB }, 219 { B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager }, 220 {} 221 }; 222 223 224 static status_t 225 device_std_ops(int32 op, ...) 226 { 227 switch (op) { 228 case B_MODULE_INIT: 229 if (get_module(B_PCI_X86_MODULE_NAME, (module_info**)&sPCIx86Module) != B_OK) 230 sPCIx86Module = NULL; 231 return B_OK; 232 case B_MODULE_UNINIT: 233 if (sPCIx86Module != NULL) 234 put_module(B_PCI_X86_MODULE_NAME); 235 return B_OK; 236 default: 237 return B_ERROR; 238 } 239 } 240 241 242 static usb_bus_interface gEHCIPCIDeviceModule = { 243 { 244 { 245 EHCI_PCI_USB_BUS_MODULE_NAME, 246 0, 247 device_std_ops 248 }, 249 NULL, // supports device 250 NULL, // register device 251 init_bus, 252 uninit_bus, 253 NULL, // register child devices 254 NULL, // rescan 255 NULL, // device removed 256 }, 257 }; 258 259 // Root device that binds to the PCI bus. It will register an usb_bus_interface 260 // node for each device. 261 static driver_module_info sEHCIDevice = { 262 { 263 EHCI_PCI_DEVICE_MODULE_NAME, 264 0, 265 NULL 266 }, 267 supports_device, 268 register_device, 269 init_device, 270 uninit_device, 271 register_child_devices, 272 NULL, // rescan 273 NULL, // device removed 274 }; 275 276 module_info* modules[] = { 277 (module_info* )&sEHCIDevice, 278 (module_info* )&gEHCIPCIDeviceModule, 279 NULL 280 }; 281 282 283 // 284 // #pragma mark - 285 // 286 287 288 #ifdef TRACE_USB 289 290 void 291 print_descriptor_chain(ehci_qtd *descriptor) 292 { 293 while (descriptor) { 294 dprintf(" %08" B_PRIx32 " n%08" B_PRIx32 " a%08" B_PRIx32 " t%08" 295 B_PRIx32 " %08" B_PRIx32 " %08" B_PRIx32 " %08" B_PRIx32 " %08" 296 B_PRIx32 " %08" B_PRIx32 " s%" B_PRIuSIZE "\n", 297 descriptor->this_phy, descriptor->next_phy, 298 descriptor->alt_next_phy, descriptor->token, 299 descriptor->buffer_phy[0], descriptor->buffer_phy[1], 300 descriptor->buffer_phy[2], descriptor->buffer_phy[3], 301 descriptor->buffer_phy[4], descriptor->buffer_size); 302 303 if (descriptor->next_phy & EHCI_ITEM_TERMINATE) 304 break; 305 306 descriptor = descriptor->next_log; 307 } 308 } 309 310 311 void 312 print_queue(ehci_qh *queueHead) 313 { 314 dprintf("queue: t%08" B_PRIx32 " n%08" B_PRIx32 " ch%08" B_PRIx32 315 " ca%08" B_PRIx32 " cu%08" B_PRIx32 "\n", 316 queueHead->this_phy, queueHead->next_phy, queueHead->endpoint_chars, 317 queueHead->endpoint_caps, queueHead->current_qtd_phy); 318 dprintf("overlay: n%08" B_PRIx32 " a%08" B_PRIx32 " t%08" B_PRIx32 319 " %08" B_PRIx32 " %08" B_PRIx32 " %08" B_PRIx32 " %08" B_PRIx32 320 " %08" B_PRIx32 "\n", queueHead->overlay.next_phy, 321 queueHead->overlay.alt_next_phy, queueHead->overlay.token, 322 queueHead->overlay.buffer_phy[0], queueHead->overlay.buffer_phy[1], 323 queueHead->overlay.buffer_phy[2], queueHead->overlay.buffer_phy[3], 324 queueHead->overlay.buffer_phy[4]); 325 print_descriptor_chain(queueHead->element_log); 326 } 327 328 329 #endif // TRACE_USB 330 331 332 // 333 // #pragma mark - 334 // 335 336 337 EHCI::EHCI(pci_info *info, pci_device_module_info* pci, pci_device* device, Stack *stack, 338 device_node* node) 339 : BusManager(stack, node), 340 fCapabilityRegisters(NULL), 341 fOperationalRegisters(NULL), 342 fRegisterArea(-1), 343 fPCIInfo(info), 344 fPci(pci), 345 fDevice(device), 346 fStack(stack), 347 fEnabledInterrupts(0), 348 fThreshold(0), 349 fPeriodicFrameListArea(-1), 350 fPeriodicFrameList(NULL), 351 fInterruptEntries(NULL), 352 fItdEntries(NULL), 353 fSitdEntries(NULL), 354 fAsyncQueueHead(NULL), 355 fAsyncAdvanceSem(-1), 356 fFirstTransfer(NULL), 357 fLastTransfer(NULL), 358 fFinishTransfersSem(-1), 359 fFinishThread(-1), 360 fProcessingPipe(NULL), 361 fFreeListHead(NULL), 362 fCleanupSem(-1), 363 fCleanupThread(-1), 364 fStopThreads(false), 365 fNextStartingFrame(-1), 366 fFrameBandwidth(NULL), 367 fFirstIsochronousTransfer(NULL), 368 fLastIsochronousTransfer(NULL), 369 fFinishIsochronousTransfersSem(-1), 370 fFinishIsochronousThread(-1), 371 fRootHub(NULL), 372 fRootHubAddress(0), 373 fPortCount(0), 374 fPortResetChange(0), 375 fPortSuspendChange(0), 376 fInterruptPollThread(-1), 377 fIRQ(0), 378 fUseMSI(false) 379 { 380 // Create a lock for the isochronous transfer list 381 mutex_init(&fIsochronousLock, "EHCI isochronous lock"); 382 383 if (BusManager::InitCheck() != B_OK) { 384 TRACE_ERROR("bus manager failed to init\n"); 385 return; 386 } 387 388 TRACE("constructing new EHCI host controller driver\n"); 389 fInitOK = false; 390 391 // ATI/AMD SB600/SB700 periodic list cache workaround 392 // Logic kindly borrowed from NetBSD PR 40056 393 if (fPCIInfo->vendor_id == AMD_SBX00_VENDOR) { 394 bool applyWorkaround = false; 395 396 if (fPCIInfo->device_id == AMD_SB600_EHCI_CONTROLLER) { 397 // always apply on SB600 398 applyWorkaround = true; 399 } else if (fPCIInfo->device_id == AMD_SB700_SB800_EHCI_CONTROLLER) { 400 // only apply on certain chipsets, determined by SMBus revision 401 device_node *pciNode = NULL; 402 device_node* deviceRoot = gDeviceManager->get_root_node(); 403 device_attr acpiAttrs[] = { 404 { B_DEVICE_BUS, B_STRING_TYPE, { .string = "pci" }}, 405 { B_DEVICE_VENDOR_ID, B_UINT16_TYPE, { .ui16 = AMD_SBX00_VENDOR }}, 406 { B_DEVICE_ID, B_UINT16_TYPE, { .ui16 = AMD_SBX00_SMBUS_CONTROLLER }}, 407 { NULL } 408 }; 409 if (gDeviceManager->find_child_node(deviceRoot, acpiAttrs, 410 &pciNode) == B_OK) { 411 pci_device_module_info *pci; 412 pci_device *pciDevice; 413 if (gDeviceManager->get_driver(pciNode, (driver_module_info **)&pci, 414 (void **)&pciDevice) == B_OK) { 415 416 pci_info smbus; 417 pci->get_pci_info(pciDevice, &smbus); 418 // Only applies to chipsets < SB710 (rev A14) 419 if (smbus.revision == 0x3a || smbus.revision == 0x3b) 420 applyWorkaround = true; 421 } 422 } 423 } 424 425 if (applyWorkaround) { 426 // According to AMD errata of SB700 and SB600 register documentation 427 // this disables the Periodic List Cache on SB600 and the Advanced 428 // Periodic List Cache on early SB700. Both the BSDs and Linux use 429 // this workaround. 430 431 TRACE_ALWAYS("disabling SB600/SB700 periodic list cache\n"); 432 uint32 workaround = fPci->read_pci_config(fDevice, 433 AMD_SBX00_EHCI_MISC_REGISTER, 4); 434 435 fPci->write_pci_config(fDevice, AMD_SBX00_EHCI_MISC_REGISTER, 4, 436 workaround | AMD_SBX00_EHCI_MISC_DISABLE_PERIODIC_LIST_CACHE); 437 } 438 } 439 440 // enable busmaster and memory mapped access 441 uint16 command = fPci->read_pci_config(fDevice, PCI_command, 2); 442 command &= ~PCI_command_io; 443 command |= PCI_command_master | PCI_command_memory; 444 445 fPci->write_pci_config(fDevice, PCI_command, 2, command); 446 447 // map the registers 448 uint32 offset = fPCIInfo->u.h0.base_registers[0] & (B_PAGE_SIZE - 1); 449 phys_addr_t physicalAddress = fPCIInfo->u.h0.base_registers[0] - offset; 450 size_t mapSize = (fPCIInfo->u.h0.base_register_sizes[0] + offset 451 + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); 452 453 TRACE("map physical memory 0x%08" B_PRIx32 " (base: 0x%08" B_PRIxPHYSADDR 454 "; offset: %" B_PRIx32 "); size: %" B_PRIu32 "\n", 455 fPCIInfo->u.h0.base_registers[0], physicalAddress, offset, 456 fPCIInfo->u.h0.base_register_sizes[0]); 457 458 fRegisterArea = map_physical_memory("EHCI memory mapped registers", 459 physicalAddress, mapSize, B_ANY_KERNEL_BLOCK_ADDRESS, 460 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 461 (void **)&fCapabilityRegisters); 462 if (fRegisterArea < 0) { 463 TRACE_ERROR("failed to map register memory\n"); 464 return; 465 } 466 467 fCapabilityRegisters += offset; 468 fOperationalRegisters = fCapabilityRegisters + ReadCapReg8(EHCI_CAPLENGTH); 469 TRACE("mapped capability registers: 0x%p\n", fCapabilityRegisters); 470 TRACE("mapped operational registers: 0x%p\n", fOperationalRegisters); 471 472 TRACE("structural parameters: 0x%08" B_PRIx32 "\n", 473 ReadCapReg32(EHCI_HCSPARAMS)); 474 TRACE("capability parameters: 0x%08" B_PRIx32 "\n", 475 ReadCapReg32(EHCI_HCCPARAMS)); 476 477 if (EHCI_HCCPARAMS_FRAME_CACHE(ReadCapReg32(EHCI_HCCPARAMS))) 478 fThreshold = 2 + 8; 479 else 480 fThreshold = 2 + EHCI_HCCPARAMS_IPT(ReadCapReg32(EHCI_HCCPARAMS)); 481 482 // read port count from capability register 483 fPortCount = ReadCapReg32(EHCI_HCSPARAMS) & 0x0f; 484 485 uint32 extendedCapPointer = ReadCapReg32(EHCI_HCCPARAMS) >> EHCI_ECP_SHIFT; 486 extendedCapPointer &= EHCI_ECP_MASK; 487 if (extendedCapPointer > 0) { 488 TRACE("extended capabilities register at %" B_PRIu32 "\n", 489 extendedCapPointer); 490 491 uint32 legacySupport = fPci->read_pci_config(fDevice, extendedCapPointer, 4); 492 if ((legacySupport & EHCI_LEGSUP_CAPID_MASK) == EHCI_LEGSUP_CAPID) { 493 if ((legacySupport & EHCI_LEGSUP_BIOSOWNED) != 0) { 494 TRACE_ALWAYS("the host controller is bios owned, claiming" 495 " ownership\n"); 496 497 fPci->write_pci_config(fDevice, extendedCapPointer + 3, 1, 1); 498 499 for (int32 i = 0; i < 20; i++) { 500 legacySupport = fPci->read_pci_config(fDevice, 501 extendedCapPointer, 4); 502 503 if ((legacySupport & EHCI_LEGSUP_BIOSOWNED) == 0) 504 break; 505 506 TRACE_ALWAYS("controller is still bios owned, waiting\n"); 507 snooze(50000); 508 } 509 } 510 511 if (legacySupport & EHCI_LEGSUP_BIOSOWNED) { 512 TRACE_ERROR("bios won't give up control over the host " 513 "controller (ignoring)\n"); 514 } else if (legacySupport & EHCI_LEGSUP_OSOWNED) { 515 TRACE_ALWAYS( 516 "successfully took ownership of the host controller\n"); 517 } 518 519 // Force off the BIOS owned flag, and clear all SMIs. Some BIOSes 520 // do indicate a successful handover but do not remove their SMIs 521 // and then freeze the system when interrupts are generated. 522 fPci->write_pci_config(fDevice, extendedCapPointer + 2, 1, 0); 523 fPci->write_pci_config(fDevice, extendedCapPointer + 4, 4, 0); 524 } else { 525 TRACE_ALWAYS( 526 "extended capability is not a legacy support register\n"); 527 } 528 } else { 529 TRACE_ALWAYS("no extended capabilities register\n"); 530 } 531 532 // disable interrupts 533 WriteOpReg(EHCI_USBINTR, 0); 534 535 // reset the host controller 536 if (ControllerReset() != B_OK) { 537 TRACE_ERROR("host controller failed to reset\n"); 538 return; 539 } 540 541 // reset the segment register 542 WriteOpReg(EHCI_CTRDSSEGMENT, 0); 543 544 // create semaphores the finisher thread will wait for 545 fAsyncAdvanceSem = create_sem(0, "EHCI Async Advance"); 546 fFinishTransfersSem = create_sem(0, "EHCI Finish Transfers"); 547 fCleanupSem = create_sem(0, "EHCI Cleanup"); 548 if (fFinishTransfersSem < 0 || fAsyncAdvanceSem < 0 || fCleanupSem < 0) { 549 TRACE_ERROR("failed to create semaphores\n"); 550 return; 551 } 552 553 // create finisher service thread 554 fFinishThread = spawn_kernel_thread(FinishThread, "ehci finish thread", 555 B_NORMAL_PRIORITY, (void *)this); 556 resume_thread(fFinishThread); 557 558 // Create semaphore the isochronous finisher thread will wait for 559 fFinishIsochronousTransfersSem = create_sem(0, 560 "EHCI Isochronous Finish Transfers"); 561 if (fFinishIsochronousTransfersSem < 0) { 562 TRACE_ERROR("failed to create isochronous finisher semaphore\n"); 563 return; 564 } 565 566 // Create the isochronous finisher service thread 567 fFinishIsochronousThread = spawn_kernel_thread(FinishIsochronousThread, 568 "ehci isochronous finish thread", B_URGENT_DISPLAY_PRIORITY, 569 (void *)this); 570 resume_thread(fFinishIsochronousThread); 571 572 // create cleanup service thread 573 fCleanupThread = spawn_kernel_thread(CleanupThread, "ehci cleanup thread", 574 B_NORMAL_PRIORITY, (void *)this); 575 resume_thread(fCleanupThread); 576 577 // set up interrupts or interrupt polling now that the controller is ready 578 bool polling = false; 579 void *settings = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS); 580 if (settings != NULL) { 581 polling = get_driver_boolean_parameter(settings, "ehci_polling", false, 582 false); 583 unload_driver_settings(settings); 584 } 585 586 if (polling) { 587 // create and run the polling thread 588 TRACE_ALWAYS("enabling ehci polling\n"); 589 fInterruptPollThread = spawn_kernel_thread(InterruptPollThread, 590 "ehci interrupt poll thread", B_NORMAL_PRIORITY, (void *)this); 591 resume_thread(fInterruptPollThread); 592 } else { 593 // Find the right interrupt vector, using MSIs if available. 594 fIRQ = fPCIInfo->u.h0.interrupt_line; 595 if (sPCIx86Module != NULL && sPCIx86Module->get_msi_count( 596 fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function) >= 1) { 597 uint8 msiVector = 0; 598 if (sPCIx86Module->configure_msi(fPCIInfo->bus, fPCIInfo->device, 599 fPCIInfo->function, 1, &msiVector) == B_OK 600 && sPCIx86Module->enable_msi(fPCIInfo->bus, fPCIInfo->device, 601 fPCIInfo->function) == B_OK) { 602 TRACE_ALWAYS("using message signaled interrupts\n"); 603 fIRQ = msiVector; 604 fUseMSI = true; 605 } 606 } 607 608 if (fIRQ == 0 || fIRQ == 0xFF) { 609 TRACE_MODULE_ERROR("device PCI:%d:%d:%d was assigned an invalid IRQ\n", 610 fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function); 611 return; 612 } 613 614 // install the interrupt handler and enable interrupts 615 install_io_interrupt_handler(fIRQ, InterruptHandler, 616 (void *)this, 0); 617 } 618 619 // ensure that interrupts are en-/disabled on the PCI device 620 command = fPci->read_pci_config(fDevice, PCI_command, 2); 621 if ((polling || fUseMSI) == ((command & PCI_command_int_disable) == 0)) { 622 if (polling || fUseMSI) 623 command &= ~PCI_command_int_disable; 624 else 625 command |= PCI_command_int_disable; 626 627 fPci->write_pci_config(fDevice, PCI_command, 2, command); 628 } 629 630 fEnabledInterrupts = EHCI_USBINTR_HOSTSYSERR | EHCI_USBINTR_USBERRINT 631 | EHCI_USBINTR_USBINT | EHCI_USBINTR_INTONAA; 632 WriteOpReg(EHCI_USBINTR, fEnabledInterrupts); 633 634 // structures don't span page boundaries 635 size_t itdListSize = EHCI_VFRAMELIST_ENTRIES_COUNT 636 / (B_PAGE_SIZE / sizeof(itd_entry)) * B_PAGE_SIZE; 637 size_t sitdListSize = EHCI_VFRAMELIST_ENTRIES_COUNT 638 / (B_PAGE_SIZE / sizeof(sitd_entry)) * B_PAGE_SIZE; 639 size_t frameListSize = B_PAGE_SIZE + B_PAGE_SIZE + itdListSize 640 + sitdListSize; 641 642 // allocate the periodic frame list 643 fPeriodicFrameListArea = fStack->AllocateArea((void **)&fPeriodicFrameList, 644 &physicalAddress, frameListSize, "USB EHCI Periodic Framelist"); 645 if (fPeriodicFrameListArea < 0) { 646 TRACE_ERROR("unable to allocate periodic framelist\n"); 647 return; 648 } 649 650 if ((physicalAddress & 0xfff) != 0) { 651 panic("EHCI_PERIODICLISTBASE not aligned on 4k: 0x%" B_PRIxPHYSADDR 652 "\n", physicalAddress); 653 } 654 655 // set the periodic frame list base on the controller 656 WriteOpReg(EHCI_PERIODICLISTBASE, (uint32)physicalAddress); 657 658 // create the interrupt entries to support different polling intervals 659 TRACE("creating interrupt entries\n"); 660 uint32_t physicalBase = physicalAddress + B_PAGE_SIZE; 661 uint8 *logicalBase = (uint8 *)fPeriodicFrameList + B_PAGE_SIZE; 662 memset(logicalBase, 0, B_PAGE_SIZE); 663 664 fInterruptEntries = (interrupt_entry *)logicalBase; 665 for (int32 i = 0; i < EHCI_INTERRUPT_ENTRIES_COUNT; i++) { 666 ehci_qh *queueHead = &fInterruptEntries[i].queue_head; 667 queueHead->this_phy = physicalBase | EHCI_ITEM_TYPE_QH; 668 queueHead->current_qtd_phy = 0; 669 queueHead->overlay.next_phy = EHCI_ITEM_TERMINATE; 670 queueHead->overlay.alt_next_phy = EHCI_ITEM_TERMINATE; 671 queueHead->overlay.token = EHCI_QTD_STATUS_HALTED; 672 673 // set dummy endpoint information 674 queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH 675 | (3 << EHCI_QH_CHARS_RL_SHIFT) | (64 << EHCI_QH_CHARS_MPL_SHIFT) 676 | EHCI_QH_CHARS_TOGGLE; 677 queueHead->endpoint_caps = (1 << EHCI_QH_CAPS_MULT_SHIFT) 678 | (0xff << EHCI_QH_CAPS_ISM_SHIFT); 679 680 physicalBase += sizeof(interrupt_entry); 681 if ((physicalBase & 0x1f) != 0) { 682 panic("physical base for interrupt entry %" B_PRId32 683 " not aligned on 32, interrupt entry structure size %lu\n", 684 i, sizeof(interrupt_entry)); 685 } 686 } 687 688 // create the itd and sitd entries 689 TRACE("build up iso entries\n"); 690 uint32_t itdPhysicalBase = physicalAddress + B_PAGE_SIZE + B_PAGE_SIZE; 691 itd_entry* itds = (itd_entry *)((uint8 *)fPeriodicFrameList + B_PAGE_SIZE 692 + B_PAGE_SIZE); 693 memset(itds, 0, itdListSize); 694 695 uint32_t sitdPhysicalBase = itdPhysicalBase + itdListSize; 696 sitd_entry* sitds = (sitd_entry *)((uint8 *)fPeriodicFrameList + B_PAGE_SIZE 697 + B_PAGE_SIZE + itdListSize); 698 memset(sitds, 0, sitdListSize); 699 700 fItdEntries = new(std::nothrow) ehci_itd *[EHCI_VFRAMELIST_ENTRIES_COUNT]; 701 fSitdEntries = new(std::nothrow) ehci_sitd *[EHCI_VFRAMELIST_ENTRIES_COUNT]; 702 703 dprintf("sitd entry size %lu, itd entry size %lu\n", sizeof(sitd_entry), 704 sizeof(itd_entry)); 705 for (int32 i = 0; i < EHCI_VFRAMELIST_ENTRIES_COUNT; i++) { 706 ehci_sitd *sitd = &sitds[i].sitd; 707 sitd->this_phy = sitdPhysicalBase | EHCI_ITEM_TYPE_SITD; 708 sitd->back_phy = EHCI_ITEM_TERMINATE; 709 fSitdEntries[i] = sitd; 710 TRACE("sitd entry %" B_PRId32 " %p 0x%" B_PRIx32 "\n", i, sitd, 711 sitd->this_phy); 712 713 ehci_itd *itd = &itds[i].itd; 714 itd->this_phy = itdPhysicalBase | EHCI_ITEM_TYPE_ITD; 715 itd->next_phy = sitd->this_phy; 716 fItdEntries[i] = itd; 717 TRACE("itd entry %" B_PRId32 " %p 0x%" B_PRIx32 "\n", i, itd, 718 itd->this_phy); 719 720 sitdPhysicalBase += sizeof(sitd_entry); 721 itdPhysicalBase += sizeof(itd_entry); 722 if ((sitdPhysicalBase & 0x10) != 0 || (itdPhysicalBase & 0x10) != 0) 723 panic("physical base for entry %" B_PRId32 " not aligned on 32\n", 724 i); 725 } 726 727 // build flat interrupt tree 728 TRACE("build up interrupt links\n"); 729 uint32 interval = EHCI_VFRAMELIST_ENTRIES_COUNT; 730 uint32 intervalIndex = EHCI_INTERRUPT_ENTRIES_COUNT - 1; 731 while (interval > 1) { 732 for (uint32 insertIndex = interval / 2; 733 insertIndex < EHCI_VFRAMELIST_ENTRIES_COUNT; 734 insertIndex += interval) { 735 fSitdEntries[insertIndex]->next_phy 736 = fInterruptEntries[intervalIndex].queue_head.this_phy; 737 } 738 739 intervalIndex--; 740 interval /= 2; 741 } 742 743 // setup the empty slot in the list and linking of all -> first 744 ehci_qh *firstLogical = &fInterruptEntries[0].queue_head; 745 fSitdEntries[0]->next_phy = firstLogical->this_phy; 746 for (int32 i = 1; i < EHCI_INTERRUPT_ENTRIES_COUNT; i++) { 747 fInterruptEntries[i].queue_head.next_phy = firstLogical->this_phy; 748 fInterruptEntries[i].queue_head.next_log = firstLogical; 749 fInterruptEntries[i].queue_head.prev_log = NULL; 750 } 751 752 // terminate the first entry 753 firstLogical->next_phy = EHCI_ITEM_TERMINATE; 754 firstLogical->next_log = NULL; 755 firstLogical->prev_log = NULL; 756 757 for (int32 i = 0; i < EHCI_FRAMELIST_ENTRIES_COUNT; i++) { 758 fPeriodicFrameList[i] 759 = fItdEntries[i & (EHCI_VFRAMELIST_ENTRIES_COUNT - 1)]->this_phy; 760 TRACE("periodic entry %" B_PRId32 " linked to 0x%" B_PRIx32 "\n", i, 761 fPeriodicFrameList[i]); 762 } 763 764 // Create the array that will keep bandwidth information 765 fFrameBandwidth = new(std::nothrow) uint16[EHCI_VFRAMELIST_ENTRIES_COUNT]; 766 for (int32 i = 0; i < EHCI_VFRAMELIST_ENTRIES_COUNT; i++) { 767 fFrameBandwidth[i] = MAX_AVAILABLE_BANDWIDTH; 768 } 769 770 // allocate a queue head that will always stay in the async frame list 771 fAsyncQueueHead = CreateQueueHead(); 772 if (!fAsyncQueueHead) { 773 TRACE_ERROR("unable to allocate stray async queue head\n"); 774 return; 775 } 776 777 fAsyncQueueHead->next_phy = fAsyncQueueHead->this_phy; 778 fAsyncQueueHead->next_log = fAsyncQueueHead; 779 fAsyncQueueHead->prev_log = fAsyncQueueHead; 780 fAsyncQueueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH 781 | EHCI_QH_CHARS_RECHEAD; 782 fAsyncQueueHead->endpoint_caps = 1 << EHCI_QH_CAPS_MULT_SHIFT; 783 fAsyncQueueHead->overlay.next_phy = EHCI_ITEM_TERMINATE; 784 785 WriteOpReg(EHCI_ASYNCLISTADDR, (uint32)fAsyncQueueHead->this_phy); 786 TRACE("set the async list addr to 0x%08" B_PRIx32 "\n", 787 ReadOpReg(EHCI_ASYNCLISTADDR)); 788 789 fInitOK = true; 790 TRACE("EHCI host controller driver constructed\n"); 791 } 792 793 794 EHCI::~EHCI() 795 { 796 TRACE("tear down EHCI host controller driver\n"); 797 798 WriteOpReg(EHCI_USBCMD, 0); 799 WriteOpReg(EHCI_CONFIGFLAG, 0); 800 CancelAllPendingTransfers(); 801 802 int32 result = 0; 803 fStopThreads = true; 804 delete_sem(fAsyncAdvanceSem); 805 delete_sem(fFinishTransfersSem); 806 delete_sem(fFinishIsochronousTransfersSem); 807 delete_sem(fCleanupSem); 808 wait_for_thread(fFinishThread, &result); 809 wait_for_thread(fCleanupThread, &result); 810 wait_for_thread(fFinishIsochronousThread, &result); 811 812 if (fInterruptPollThread >= 0) 813 wait_for_thread(fInterruptPollThread, &result); 814 else 815 remove_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this); 816 817 LockIsochronous(); 818 isochronous_transfer_data *isoTransfer = fFirstIsochronousTransfer; 819 while (isoTransfer) { 820 isochronous_transfer_data *next = isoTransfer->link; 821 delete isoTransfer; 822 isoTransfer = next; 823 } 824 mutex_destroy(&fIsochronousLock); 825 826 delete fRootHub; 827 delete [] fFrameBandwidth; 828 delete [] fItdEntries; 829 delete [] fSitdEntries; 830 delete_area(fPeriodicFrameListArea); 831 delete_area(fRegisterArea); 832 833 if (fUseMSI && sPCIx86Module != NULL) { 834 sPCIx86Module->disable_msi(fPCIInfo->bus, 835 fPCIInfo->device, fPCIInfo->function); 836 sPCIx86Module->unconfigure_msi(fPCIInfo->bus, 837 fPCIInfo->device, fPCIInfo->function); 838 } 839 840 } 841 842 843 status_t 844 EHCI::Start() 845 { 846 TRACE("starting EHCI host controller\n"); 847 TRACE("usbcmd: 0x%08" B_PRIx32 "; usbsts: 0x%08" B_PRIx32 "\n", 848 ReadOpReg(EHCI_USBCMD), ReadOpReg(EHCI_USBSTS)); 849 850 bool hasPerPortChangeEvent = (ReadCapReg32(EHCI_HCCPARAMS) 851 & EHCI_HCCPARAMS_PPCEC) != 0; 852 853 uint32 config = ReadOpReg(EHCI_USBCMD); 854 config &= ~((EHCI_USBCMD_ITC_MASK << EHCI_USBCMD_ITC_SHIFT) 855 | EHCI_USBCMD_PPCEE); 856 uint32 frameListSize = (config >> EHCI_USBCMD_FLS_SHIFT) 857 & EHCI_USBCMD_FLS_MASK; 858 859 WriteOpReg(EHCI_USBCMD, config | EHCI_USBCMD_RUNSTOP 860 | (hasPerPortChangeEvent ? EHCI_USBCMD_PPCEE : 0) 861 | EHCI_USBCMD_ASENABLE | EHCI_USBCMD_PSENABLE 862 | (frameListSize << EHCI_USBCMD_FLS_SHIFT) 863 | (1 << EHCI_USBCMD_ITC_SHIFT)); 864 865 switch (frameListSize) { 866 case 0: 867 TRACE("frame list size 1024\n"); 868 break; 869 case 1: 870 TRACE("frame list size 512\n"); 871 break; 872 case 2: 873 TRACE("frame list size 256\n"); 874 break; 875 default: 876 TRACE_ALWAYS("unknown frame list size\n"); 877 } 878 879 bool running = false; 880 for (int32 i = 0; i < 10; i++) { 881 uint32 status = ReadOpReg(EHCI_USBSTS); 882 TRACE("try %" B_PRId32 ": status 0x%08" B_PRIx32 "\n", i, status); 883 884 if (status & EHCI_USBSTS_HCHALTED) { 885 snooze(10000); 886 } else { 887 running = true; 888 break; 889 } 890 } 891 892 if (!running) { 893 TRACE_ERROR("host controller didn't start\n"); 894 return B_ERROR; 895 } 896 897 // route all ports to us 898 WriteOpReg(EHCI_CONFIGFLAG, EHCI_CONFIGFLAG_FLAG); 899 snooze(10000); 900 901 fRootHubAddress = AllocateAddress(); 902 fRootHub = new(std::nothrow) EHCIRootHub(RootObject(), fRootHubAddress); 903 if (!fRootHub) { 904 TRACE_ERROR("no memory to allocate root hub\n"); 905 return B_NO_MEMORY; 906 } 907 908 if (fRootHub->InitCheck() != B_OK) { 909 TRACE_ERROR("root hub failed init check\n"); 910 return fRootHub->InitCheck(); 911 } 912 913 SetRootHub(fRootHub); 914 915 fRootHub->RegisterNode(Node()); 916 917 TRACE_ALWAYS("successfully started the controller\n"); 918 return BusManager::Start(); 919 } 920 921 922 status_t 923 EHCI::StartDebugTransfer(Transfer *transfer) 924 { 925 static transfer_data transferData; 926 927 transferData.queue_head = CreateQueueHead(); 928 if (transferData.queue_head == NULL) 929 return B_NO_MEMORY; 930 931 Pipe *pipe = transfer->TransferPipe(); 932 status_t result = InitQueueHead(transferData.queue_head, pipe); 933 if (result != B_OK) { 934 FreeQueueHead(transferData.queue_head); 935 return result; 936 } 937 938 if ((pipe->Type() & USB_OBJECT_CONTROL_PIPE) != 0) { 939 result = FillQueueWithRequest(transfer, transferData.queue_head, 940 &transferData.data_descriptor, &transferData.incoming, false); 941 } else { 942 result = FillQueueWithData(transfer, transferData.queue_head, 943 &transferData.data_descriptor, &transferData.incoming, false); 944 } 945 946 if (result != B_OK) { 947 FreeQueueHead(transferData.queue_head); 948 return result; 949 } 950 951 if ((pipe->Type() & USB_OBJECT_INTERRUPT_PIPE) != 0) 952 LinkPeriodicDebugQueueHead(transferData.queue_head, pipe); 953 else 954 LinkAsyncDebugQueueHead(transferData.queue_head); 955 956 // we abuse the callback cookie to hold our transfer data 957 transfer->SetCallback(NULL, &transferData); 958 return B_OK; 959 } 960 961 962 void 963 EHCI::LinkAsyncDebugQueueHead(ehci_qh *queueHead) 964 { 965 ehci_qh *prevHead = fAsyncQueueHead->prev_log; 966 queueHead->next_phy = fAsyncQueueHead->this_phy; 967 queueHead->next_log = fAsyncQueueHead; 968 queueHead->prev_log = prevHead; 969 fAsyncQueueHead->prev_log = queueHead; 970 prevHead->next_log = queueHead; 971 prevHead->next_phy = queueHead->this_phy; 972 } 973 974 975 void 976 EHCI::LinkPeriodicDebugQueueHead(ehci_qh *queueHead, Pipe *pipe) 977 { 978 if (pipe->Speed() == USB_SPEED_HIGHSPEED) 979 queueHead->endpoint_caps |= (0xff << EHCI_QH_CAPS_ISM_SHIFT); 980 else { 981 queueHead->endpoint_caps |= (0x01 << EHCI_QH_CAPS_ISM_SHIFT); 982 queueHead->endpoint_caps |= (0x1c << EHCI_QH_CAPS_SCM_SHIFT); 983 } 984 985 ehci_qh *interruptQueue = &fInterruptEntries[0].queue_head; 986 queueHead->next_phy = interruptQueue->next_phy; 987 queueHead->next_log = interruptQueue->next_log; 988 queueHead->prev_log = interruptQueue; 989 if (interruptQueue->next_log) 990 interruptQueue->next_log->prev_log = queueHead; 991 interruptQueue->next_log = queueHead; 992 interruptQueue->next_phy = queueHead->this_phy; 993 } 994 995 996 status_t 997 EHCI::CheckDebugTransfer(Transfer *transfer) 998 { 999 bool transferOK = false; 1000 bool transferError = false; 1001 transfer_data *transferData = (transfer_data *)transfer->CallbackCookie(); 1002 ehci_qtd *descriptor = transferData->queue_head->element_log; 1003 1004 while (descriptor) { 1005 uint32 status = descriptor->token; 1006 if ((status & EHCI_QTD_STATUS_ACTIVE) != 0) { 1007 // still in progress 1008 break; 1009 } 1010 1011 if ((status & EHCI_QTD_STATUS_ERRMASK) != 0) { 1012 transferError = true; 1013 break; 1014 } 1015 1016 if ((descriptor->next_phy & EHCI_ITEM_TERMINATE) != 0) { 1017 // we arrived at the last (stray) descriptor, we're done 1018 transferOK = true; 1019 break; 1020 } 1021 1022 if (((status >> EHCI_QTD_PID_SHIFT) & EHCI_QTD_PID_MASK) 1023 == EHCI_QTD_PID_IN 1024 && ((status >> EHCI_QTD_BYTES_SHIFT) & EHCI_QTD_BYTES_MASK) != 0) { 1025 // a short packet condition existed on this descriptor 1026 if (descriptor->alt_next_log != NULL) { 1027 descriptor = descriptor->alt_next_log; 1028 continue; 1029 } 1030 1031 transferOK = true; 1032 break; 1033 } 1034 1035 descriptor = descriptor->next_log; 1036 } 1037 1038 if (!transferOK && !transferError) { 1039 spin(75); 1040 return B_DEV_PENDING; 1041 } 1042 1043 if (transferOK) { 1044 bool nextDataToggle = false; 1045 if (transferData->data_descriptor != NULL && transferData->incoming) { 1046 // data to read out 1047 iovec *vector = transfer->Vector(); 1048 size_t vectorCount = transfer->VectorCount(); 1049 1050 ReadDescriptorChain(transferData->data_descriptor, 1051 vector, vectorCount, &nextDataToggle); 1052 } else if (transferData->data_descriptor != NULL) 1053 ReadActualLength(transferData->data_descriptor, &nextDataToggle); 1054 1055 transfer->TransferPipe()->SetDataToggle(nextDataToggle); 1056 } 1057 1058 CleanupDebugTransfer(transfer); 1059 return transferOK ? B_OK : B_IO_ERROR; 1060 } 1061 1062 1063 void 1064 EHCI::CancelDebugTransfer(Transfer *transfer) 1065 { 1066 transfer_data *transferData = (transfer_data *)transfer->CallbackCookie(); 1067 1068 // clear the active bit so the descriptors are canceled 1069 ehci_qtd *descriptor = transferData->queue_head->element_log; 1070 while (descriptor != NULL) { 1071 descriptor->token &= ~EHCI_QTD_STATUS_ACTIVE; 1072 descriptor = descriptor->next_log; 1073 } 1074 1075 transfer->Finished(B_CANCELED, 0); 1076 CleanupDebugTransfer(transfer); 1077 } 1078 1079 1080 void 1081 EHCI::CleanupDebugTransfer(Transfer *transfer) 1082 { 1083 transfer_data *transferData = (transfer_data *)transfer->CallbackCookie(); 1084 ehci_qh *queueHead = transferData->queue_head; 1085 ehci_qh *prevHead = queueHead->prev_log; 1086 if (prevHead != NULL) { 1087 prevHead->next_phy = queueHead->next_phy; 1088 prevHead->next_log = queueHead->next_log; 1089 } 1090 1091 ehci_qh *nextHead = queueHead->next_log; 1092 if (nextHead != NULL) 1093 nextHead->prev_log = queueHead->prev_log; 1094 1095 queueHead->next_phy = fAsyncQueueHead->this_phy; 1096 queueHead->prev_log = NULL; 1097 queueHead->next_log = NULL; 1098 1099 // wait for async advance to ensure the controller does not access this 1100 // queue head anymore. 1101 spin(125); 1102 1103 FreeQueueHead(queueHead); 1104 } 1105 1106 1107 status_t 1108 EHCI::SubmitTransfer(Transfer *transfer) 1109 { 1110 // short circuit the root hub 1111 if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress) 1112 return fRootHub->ProcessTransfer(this, transfer); 1113 1114 Pipe *pipe = transfer->TransferPipe(); 1115 if ((pipe->Type() & USB_OBJECT_ISO_PIPE) != 0) 1116 return SubmitIsochronous(transfer); 1117 1118 status_t result = transfer->InitKernelAccess(); 1119 if (result != B_OK) 1120 return result; 1121 1122 ehci_qh *queueHead = CreateQueueHead(); 1123 if (!queueHead) { 1124 TRACE_ERROR("failed to allocate queue head\n"); 1125 return B_NO_MEMORY; 1126 } 1127 1128 result = InitQueueHead(queueHead, pipe); 1129 if (result != B_OK) { 1130 TRACE_ERROR("failed to init queue head\n"); 1131 FreeQueueHead(queueHead); 1132 return result; 1133 } 1134 1135 bool directionIn; 1136 ehci_qtd *dataDescriptor; 1137 if ((pipe->Type() & USB_OBJECT_CONTROL_PIPE) != 0) { 1138 result = FillQueueWithRequest(transfer, queueHead, &dataDescriptor, 1139 &directionIn, true); 1140 } else { 1141 result = FillQueueWithData(transfer, queueHead, &dataDescriptor, 1142 &directionIn, true); 1143 } 1144 1145 if (result != B_OK) { 1146 TRACE_ERROR("failed to fill transfer queue with data\n"); 1147 FreeQueueHead(queueHead); 1148 return result; 1149 } 1150 1151 result = AddPendingTransfer(transfer, queueHead, dataDescriptor, 1152 directionIn); 1153 if (result != B_OK) { 1154 TRACE_ERROR("failed to add pending transfer\n"); 1155 FreeQueueHead(queueHead); 1156 return result; 1157 } 1158 1159 #ifdef TRACE_USB 1160 TRACE("linking queue\n"); 1161 print_queue(queueHead); 1162 #endif 1163 1164 if ((pipe->Type() & USB_OBJECT_INTERRUPT_PIPE) != 0) 1165 result = LinkInterruptQueueHead(queueHead, pipe); 1166 else 1167 result = LinkQueueHead(queueHead); 1168 1169 if (result != B_OK) { 1170 TRACE_ERROR("failed to link queue head\n"); 1171 FreeQueueHead(queueHead); 1172 return result; 1173 } 1174 1175 return B_OK; 1176 } 1177 1178 1179 status_t 1180 EHCI::SubmitIsochronous(Transfer *transfer) 1181 { 1182 Pipe *pipe = transfer->TransferPipe(); 1183 bool directionIn = (pipe->Direction() == Pipe::In); 1184 usb_isochronous_data *isochronousData = transfer->IsochronousData(); 1185 size_t packetSize = transfer->DataLength(); 1186 #ifdef TRACE_USB 1187 size_t restSize = packetSize % isochronousData->packet_count; 1188 #endif 1189 packetSize /= isochronousData->packet_count; 1190 uint16 currentFrame; 1191 1192 if (packetSize > pipe->MaxPacketSize()) { 1193 TRACE_ERROR( 1194 "isochronous packetSize is bigger than pipe MaxPacketSize\n"); 1195 return B_BAD_VALUE; 1196 } 1197 1198 status_t result = transfer->InitKernelAccess(); 1199 if (result != B_OK) 1200 return result; 1201 1202 // Ignore the fact that the last descriptor might need less bandwidth. 1203 // The overhead is not worthy. 1204 uint16 bandwidth = transfer->Bandwidth() / isochronousData->packet_count; 1205 1206 TRACE("isochronous transfer descriptor bandwidth %d\n", bandwidth); 1207 1208 // The following holds the list of transfer descriptor of the 1209 // isochronous request. It is used to quickly remove all the isochronous 1210 // descriptors from the frame list, as descriptors are not link to each 1211 // other in a queue like for every other transfer. 1212 ehci_itd **isoRequest 1213 = new(std::nothrow) ehci_itd *[isochronousData->packet_count]; 1214 if (isoRequest == NULL) { 1215 TRACE("failed to create isoRequest array!\n"); 1216 return B_NO_MEMORY; 1217 } 1218 1219 TRACE("isochronous submitted size=%" B_PRIuSIZE " bytes, TDs=%" B_PRIu32 1220 ", maxPacketSize=%" B_PRIuSIZE ", packetSize=%" B_PRIuSIZE 1221 ", restSize=%" B_PRIuSIZE "\n", transfer->DataLength(), 1222 isochronousData->packet_count, pipe->MaxPacketSize(), packetSize, 1223 restSize); 1224 1225 // Find the entry where to start inserting the first Isochronous descriptor 1226 if ((isochronousData->flags & USB_ISO_ASAP) != 0 || 1227 isochronousData->starting_frame_number == NULL) { 1228 1229 if (fFirstIsochronousTransfer != NULL && fNextStartingFrame != -1) 1230 currentFrame = fNextStartingFrame; 1231 else { 1232 uint32 threshold = fThreshold; 1233 TRACE("threshold: %" B_PRIu32 "\n", threshold); 1234 1235 // find the first available frame with enough bandwidth. 1236 // This should always be the case, as defining the starting frame 1237 // number in the driver makes no sense for many reason, one of which 1238 // is that frame numbers value are host controller specific, and the 1239 // driver does not know which host controller is running. 1240 currentFrame = ((ReadOpReg(EHCI_FRINDEX) + threshold) / 8) 1241 & (EHCI_FRAMELIST_ENTRIES_COUNT - 1); 1242 } 1243 1244 // Make sure that: 1245 // 1. We are at least 5ms ahead the controller 1246 // 2. We stay in the range 0-127 1247 // 3. There is enough bandwidth in the first entry 1248 currentFrame &= EHCI_VFRAMELIST_ENTRIES_COUNT - 1; 1249 } else { 1250 // Find out if the frame number specified has enough bandwidth, 1251 // otherwise find the first next available frame with enough bandwidth 1252 currentFrame = *isochronousData->starting_frame_number; 1253 } 1254 1255 TRACE("isochronous starting frame=%d\n", currentFrame); 1256 1257 uint16 itdIndex = 0; 1258 size_t dataLength = transfer->DataLength(); 1259 void* bufferLog; 1260 phys_addr_t bufferPhy; 1261 if (fStack->AllocateChunk(&bufferLog, &bufferPhy, dataLength) != B_OK) { 1262 TRACE_ERROR("unable to allocate itd buffer\n"); 1263 delete[] isoRequest; 1264 return B_NO_MEMORY; 1265 } 1266 1267 memset(bufferLog, 0, dataLength); 1268 1269 phys_addr_t currentPhy = bufferPhy; 1270 uint32 frameCount = 0; 1271 while (dataLength > 0) { 1272 ehci_itd* itd = CreateItdDescriptor(); 1273 isoRequest[itdIndex++] = itd; 1274 uint16 pg = 0; 1275 itd->buffer_phy[pg] = currentPhy & 0xfffff000; 1276 uint32 offset = currentPhy & 0xfff; 1277 TRACE("isochronous created itd, filling it with phy %" B_PRIxPHYSADDR 1278 "\n", currentPhy); 1279 for (int32 i = 0; i < 8 && dataLength > 0; i++) { 1280 size_t length = min_c(dataLength, packetSize); 1281 itd->token[i] = (EHCI_ITD_STATUS_ACTIVE << EHCI_ITD_STATUS_SHIFT) 1282 | (length << EHCI_ITD_TLENGTH_SHIFT) | (pg << EHCI_ITD_PG_SHIFT) 1283 | (offset << EHCI_ITD_TOFFSET_SHIFT); 1284 itd->last_token = i; 1285 TRACE("isochronous filled slot %" B_PRId32 " 0x%" B_PRIx32 "\n", i, 1286 itd->token[i]); 1287 dataLength -= length; 1288 offset += length; 1289 if (dataLength > 0 && offset > 0xfff) { 1290 offset -= B_PAGE_SIZE; 1291 currentPhy += B_PAGE_SIZE; 1292 itd->buffer_phy[pg + 1] = currentPhy & 0xfffff000; 1293 pg++; 1294 } 1295 if (dataLength <= 0) 1296 itd->token[i] |= EHCI_ITD_IOC; 1297 } 1298 1299 currentPhy += (offset & 0xfff) - (currentPhy & 0xfff); 1300 1301 itd->buffer_phy[0] 1302 |= (pipe->EndpointAddress() << EHCI_ITD_ENDPOINT_SHIFT) 1303 | (pipe->DeviceAddress() << EHCI_ITD_ADDRESS_SHIFT); 1304 itd->buffer_phy[1] 1305 |= (pipe->MaxPacketSize() & EHCI_ITD_MAXPACKETSIZE_MASK) 1306 | (directionIn << EHCI_ITD_DIR_SHIFT); 1307 itd->buffer_phy[2] 1308 |= ((((pipe->MaxPacketSize() >> EHCI_ITD_MAXPACKETSIZE_LENGTH) + 1) 1309 & EHCI_ITD_MUL_MASK) << EHCI_ITD_MUL_SHIFT); 1310 1311 TRACE("isochronous filled itd buffer_phy[0,1,2] 0x%" B_PRIx32 ", 0x%" 1312 B_PRIx32 " 0x%" B_PRIx32 "\n", 1313 itd->buffer_phy[0], itd->buffer_phy[1], itd->buffer_phy[2]); 1314 1315 if (!LockIsochronous()) 1316 continue; 1317 LinkITDescriptors(itd, &fItdEntries[currentFrame]); 1318 UnlockIsochronous(); 1319 fFrameBandwidth[currentFrame] -= bandwidth; 1320 currentFrame = (currentFrame + 1) & (EHCI_VFRAMELIST_ENTRIES_COUNT - 1); 1321 frameCount++; 1322 } 1323 1324 TRACE("isochronous filled itds count %d\n", itdIndex); 1325 1326 // Add transfer to the list 1327 result = AddPendingIsochronousTransfer(transfer, isoRequest, 1328 itdIndex - 1, directionIn, bufferPhy, bufferLog, 1329 transfer->DataLength()); 1330 if (result != B_OK) { 1331 TRACE_ERROR("failed to add pending isochronous transfer\n"); 1332 for (uint32 i = 0; i < itdIndex; i++) 1333 FreeDescriptor(isoRequest[i]); 1334 delete[] isoRequest; 1335 return result; 1336 } 1337 1338 TRACE("appended isochronous transfer by starting at frame number %d\n", 1339 currentFrame); 1340 fNextStartingFrame = currentFrame + 1; 1341 1342 // Wake up the isochronous finisher thread 1343 release_sem_etc(fFinishIsochronousTransfersSem, 1 /*frameCount*/, 1344 B_DO_NOT_RESCHEDULE); 1345 1346 return B_OK; 1347 } 1348 1349 1350 isochronous_transfer_data * 1351 EHCI::FindIsochronousTransfer(ehci_itd *itd) 1352 { 1353 // Simply check every last descriptor of the isochronous transfer list 1354 isochronous_transfer_data *transfer = fFirstIsochronousTransfer; 1355 if (transfer) { 1356 while (transfer->descriptors[transfer->last_to_process] 1357 != itd) { 1358 transfer = transfer->link; 1359 if (!transfer) 1360 break; 1361 } 1362 } 1363 return transfer; 1364 } 1365 1366 1367 status_t 1368 EHCI::NotifyPipeChange(Pipe *pipe, usb_change change) 1369 { 1370 TRACE("pipe change %d for pipe %p\n", change, pipe); 1371 switch (change) { 1372 case USB_CHANGE_CREATED: 1373 case USB_CHANGE_DESTROYED: { 1374 // ToDo: we should create and keep a single queue head 1375 // for all transfers to/from this pipe 1376 break; 1377 } 1378 1379 case USB_CHANGE_PIPE_POLICY_CHANGED: { 1380 // ToDo: for isochronous pipes we might need to adapt to new 1381 // pipe policy settings here 1382 break; 1383 } 1384 } 1385 1386 return B_OK; 1387 } 1388 1389 1390 status_t 1391 EHCI::GetPortStatus(uint8 index, usb_port_status *status) 1392 { 1393 if (index >= fPortCount) 1394 return B_BAD_INDEX; 1395 1396 status->status = status->change = 0; 1397 uint32 portStatus = ReadOpReg(EHCI_PORTSC + index * sizeof(uint32)); 1398 1399 // build the status 1400 if (portStatus & EHCI_PORTSC_CONNSTATUS) 1401 status->status |= PORT_STATUS_CONNECTION; 1402 if (portStatus & EHCI_PORTSC_ENABLE) 1403 status->status |= PORT_STATUS_ENABLE; 1404 if (portStatus & EHCI_PORTSC_ENABLE) 1405 status->status |= PORT_STATUS_HIGH_SPEED; 1406 if (portStatus & EHCI_PORTSC_OCACTIVE) 1407 status->status |= PORT_STATUS_OVER_CURRENT; 1408 if (portStatus & EHCI_PORTSC_PORTRESET) 1409 status->status |= PORT_STATUS_RESET; 1410 if (portStatus & EHCI_PORTSC_PORTPOWER) 1411 status->status |= PORT_STATUS_POWER; 1412 if (portStatus & EHCI_PORTSC_SUSPEND) 1413 status->status |= PORT_STATUS_SUSPEND; 1414 if (portStatus & EHCI_PORTSC_DMINUS) 1415 status->status |= PORT_STATUS_LOW_SPEED; 1416 1417 // build the change 1418 if (portStatus & EHCI_PORTSC_CONNCHANGE) 1419 status->change |= PORT_STATUS_CONNECTION; 1420 if (portStatus & EHCI_PORTSC_ENABLECHANGE) 1421 status->change |= PORT_STATUS_ENABLE; 1422 if (portStatus & EHCI_PORTSC_OCCHANGE) 1423 status->change |= PORT_STATUS_OVER_CURRENT; 1424 1425 // there are no bits to indicate suspend and reset change 1426 if (fPortResetChange & (1 << index)) 1427 status->change |= PORT_STATUS_RESET; 1428 if (fPortSuspendChange & (1 << index)) 1429 status->change |= PORT_STATUS_SUSPEND; 1430 1431 return B_OK; 1432 } 1433 1434 1435 status_t 1436 EHCI::SetPortFeature(uint8 index, uint16 feature) 1437 { 1438 if (index >= fPortCount) 1439 return B_BAD_INDEX; 1440 1441 uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32); 1442 uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK; 1443 1444 switch (feature) { 1445 case PORT_SUSPEND: 1446 return SuspendPort(index); 1447 1448 case PORT_RESET: 1449 return ResetPort(index); 1450 1451 case PORT_POWER: 1452 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTPOWER); 1453 return B_OK; 1454 } 1455 1456 return B_BAD_VALUE; 1457 } 1458 1459 1460 status_t 1461 EHCI::ClearPortFeature(uint8 index, uint16 feature) 1462 { 1463 if (index >= fPortCount) 1464 return B_BAD_INDEX; 1465 1466 uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32); 1467 uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK; 1468 1469 switch (feature) { 1470 case PORT_ENABLE: 1471 WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_ENABLE); 1472 return B_OK; 1473 1474 case PORT_POWER: 1475 WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_PORTPOWER); 1476 return B_OK; 1477 1478 case C_PORT_CONNECTION: 1479 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_CONNCHANGE); 1480 return B_OK; 1481 1482 case C_PORT_ENABLE: 1483 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_ENABLECHANGE); 1484 return B_OK; 1485 1486 case C_PORT_OVER_CURRENT: 1487 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_OCCHANGE); 1488 return B_OK; 1489 1490 case C_PORT_RESET: 1491 fPortResetChange &= ~(1 << index); 1492 return B_OK; 1493 1494 case C_PORT_SUSPEND: 1495 fPortSuspendChange &= ~(1 << index); 1496 return B_OK; 1497 } 1498 1499 return B_BAD_VALUE; 1500 } 1501 1502 1503 status_t 1504 EHCI::ResetPort(uint8 index) 1505 { 1506 TRACE("reset port %d\n", index); 1507 uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32); 1508 uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK; 1509 1510 if (portStatus & EHCI_PORTSC_DMINUS) { 1511 TRACE_ALWAYS("lowspeed device connected, giving up port ownership\n"); 1512 // there is a lowspeed device connected. 1513 // we give the ownership to a companion controller. 1514 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTOWNER); 1515 fPortResetChange |= (1 << index); 1516 return B_OK; 1517 } 1518 1519 // enable reset signaling 1520 WriteOpReg(portRegister, (portStatus & ~EHCI_PORTSC_ENABLE) 1521 | EHCI_PORTSC_PORTRESET); 1522 snooze(50000); 1523 1524 // disable reset signaling 1525 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK; 1526 WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_PORTRESET); 1527 snooze(2000); 1528 1529 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK; 1530 if (portStatus & EHCI_PORTSC_PORTRESET) { 1531 TRACE_ERROR("port reset won't complete\n"); 1532 return B_ERROR; 1533 } 1534 1535 if ((portStatus & EHCI_PORTSC_ENABLE) == 0) { 1536 TRACE_ALWAYS("fullspeed device connected, giving up port ownership\n"); 1537 // the port was not enabled, this means that no high speed device is 1538 // attached to this port. we give up ownership to a companion controler 1539 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTOWNER); 1540 } 1541 1542 fPortResetChange |= (1 << index); 1543 return B_OK; 1544 } 1545 1546 1547 status_t 1548 EHCI::SuspendPort(uint8 index) 1549 { 1550 uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32); 1551 uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK; 1552 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_SUSPEND); 1553 fPortSuspendChange |= (1 << index); 1554 return B_OK; 1555 } 1556 1557 1558 status_t 1559 EHCI::ControllerReset() 1560 { 1561 // halt the controller first 1562 WriteOpReg(EHCI_USBCMD, 0); 1563 snooze(10000); 1564 1565 // then reset it 1566 WriteOpReg(EHCI_USBCMD, EHCI_USBCMD_HCRESET); 1567 1568 int32 tries = 5; 1569 while (ReadOpReg(EHCI_USBCMD) & EHCI_USBCMD_HCRESET) { 1570 snooze(10000); 1571 if (tries-- < 0) 1572 return B_ERROR; 1573 } 1574 1575 return B_OK; 1576 } 1577 1578 1579 status_t 1580 EHCI::LightReset() 1581 { 1582 return B_ERROR; 1583 } 1584 1585 1586 int32 1587 EHCI::InterruptHandler(void *data) 1588 { 1589 return ((EHCI *)data)->Interrupt(); 1590 } 1591 1592 1593 int32 1594 EHCI::Interrupt() 1595 { 1596 static spinlock lock = B_SPINLOCK_INITIALIZER; 1597 acquire_spinlock(&lock); 1598 1599 // check if any interrupt was generated 1600 uint32 status = ReadOpReg(EHCI_USBSTS) & EHCI_USBSTS_INTMASK; 1601 if ((status & fEnabledInterrupts) == 0) { 1602 if (status != 0) { 1603 TRACE("discarding not enabled interrupts 0x%08" B_PRIx32 "\n", 1604 status); 1605 WriteOpReg(EHCI_USBSTS, status); 1606 } 1607 1608 release_spinlock(&lock); 1609 return B_UNHANDLED_INTERRUPT; 1610 } 1611 1612 bool asyncAdvance = false; 1613 bool finishTransfers = false; 1614 int32 result = B_HANDLED_INTERRUPT; 1615 1616 if (status & EHCI_USBSTS_USBINT) { 1617 TRACE("transfer finished\n"); 1618 result = B_INVOKE_SCHEDULER; 1619 finishTransfers = true; 1620 } 1621 1622 if (status & EHCI_USBSTS_USBERRINT) { 1623 TRACE("transfer error\n"); 1624 result = B_INVOKE_SCHEDULER; 1625 finishTransfers = true; 1626 } 1627 1628 if (status & EHCI_USBSTS_FLROLLOVER) 1629 TRACE("frame list rollover\n"); 1630 1631 if (status & EHCI_USBSTS_PORTCHANGE) 1632 TRACE("port change detected\n"); 1633 1634 if (status & EHCI_USBSTS_INTONAA) { 1635 TRACE("interrupt on async advance\n"); 1636 asyncAdvance = true; 1637 result = B_INVOKE_SCHEDULER; 1638 } 1639 1640 if (status & EHCI_USBSTS_HOSTSYSERR) 1641 TRACE_ERROR("host system error!\n"); 1642 1643 WriteOpReg(EHCI_USBSTS, status); 1644 release_spinlock(&lock); 1645 1646 if (asyncAdvance) 1647 release_sem_etc(fAsyncAdvanceSem, 1, B_DO_NOT_RESCHEDULE); 1648 if (finishTransfers) 1649 release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE); 1650 1651 return result; 1652 } 1653 1654 1655 int32 1656 EHCI::InterruptPollThread(void *data) 1657 { 1658 EHCI *ehci = (EHCI *)data; 1659 1660 while (!ehci->fStopThreads) { 1661 // TODO: this could be handled much better by only polling when there 1662 // are actual transfers going on... 1663 snooze(1000); 1664 1665 cpu_status status = disable_interrupts(); 1666 ehci->Interrupt(); 1667 restore_interrupts(status); 1668 } 1669 1670 return 0; 1671 } 1672 1673 1674 status_t 1675 EHCI::AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead, 1676 ehci_qtd *dataDescriptor, bool directionIn) 1677 { 1678 transfer_data *data = new(std::nothrow) transfer_data; 1679 if (!data) 1680 return B_NO_MEMORY; 1681 1682 data->transfer = transfer; 1683 data->queue_head = queueHead; 1684 data->data_descriptor = dataDescriptor; 1685 data->incoming = directionIn; 1686 data->canceled = false; 1687 data->link = NULL; 1688 1689 if (!Lock()) { 1690 delete data; 1691 return B_ERROR; 1692 } 1693 1694 // We do not support queuing other transfers in tandem with a fragmented one. 1695 transfer_data *it = fFirstTransfer; 1696 while (it) { 1697 if (it->transfer && it->transfer->TransferPipe() == transfer->TransferPipe() 1698 && it->transfer->IsFragmented()) { 1699 TRACE_ERROR("cannot submit transfer: a fragmented transfer is queued\n"); 1700 1701 Unlock(); 1702 delete data; 1703 return B_DEV_RESOURCE_CONFLICT; 1704 } 1705 1706 it = it->link; 1707 } 1708 1709 if (fLastTransfer) 1710 fLastTransfer->link = data; 1711 else 1712 fFirstTransfer = data; 1713 1714 fLastTransfer = data; 1715 Unlock(); 1716 1717 return B_OK; 1718 } 1719 1720 1721 status_t 1722 EHCI::AddPendingIsochronousTransfer(Transfer *transfer, ehci_itd **isoRequest, 1723 uint32 lastIndex, bool directionIn, addr_t bufferPhy, void* bufferLog, 1724 size_t bufferSize) 1725 { 1726 if (!transfer || !isoRequest) 1727 return B_BAD_VALUE; 1728 1729 isochronous_transfer_data *data 1730 = new(std::nothrow) isochronous_transfer_data; 1731 if (!data) 1732 return B_NO_MEMORY; 1733 1734 data->transfer = transfer; 1735 data->descriptors = isoRequest; 1736 data->last_to_process = lastIndex; 1737 data->incoming = directionIn; 1738 data->is_active = true; 1739 data->link = NULL; 1740 data->buffer_phy = bufferPhy; 1741 data->buffer_log = bufferLog; 1742 data->buffer_size = bufferSize; 1743 1744 // Put in the isochronous transfer list 1745 if (!LockIsochronous()) { 1746 delete data; 1747 return B_ERROR; 1748 } 1749 1750 if (fLastIsochronousTransfer) 1751 fLastIsochronousTransfer->link = data; 1752 else if (!fFirstIsochronousTransfer) 1753 fFirstIsochronousTransfer = data; 1754 1755 fLastIsochronousTransfer = data; 1756 UnlockIsochronous(); 1757 return B_OK; 1758 } 1759 1760 1761 status_t 1762 EHCI::CancelQueuedTransfers(Pipe *pipe, bool force) 1763 { 1764 if ((pipe->Type() & USB_OBJECT_ISO_PIPE) != 0) 1765 return CancelQueuedIsochronousTransfers(pipe, force); 1766 1767 if (!Lock()) 1768 return B_ERROR; 1769 1770 struct transfer_entry { 1771 Transfer * transfer; 1772 transfer_entry * next; 1773 }; 1774 1775 transfer_entry *list = NULL; 1776 transfer_data *current = fFirstTransfer; 1777 while (current) { 1778 if (current->transfer && current->transfer->TransferPipe() == pipe) { 1779 // clear the active bit so the descriptors are canceled 1780 ehci_qtd *descriptor = current->queue_head->element_log; 1781 while (descriptor) { 1782 descriptor->token &= ~EHCI_QTD_STATUS_ACTIVE; 1783 descriptor = descriptor->next_log; 1784 } 1785 1786 if (!force) { 1787 // if the transfer is canceled by force, the one causing the 1788 // cancel is probably not the one who initiated the transfer 1789 // and the callback is likely not safe anymore 1790 transfer_entry *entry 1791 = (transfer_entry *)malloc(sizeof(transfer_entry)); 1792 if (entry != NULL) { 1793 entry->transfer = current->transfer; 1794 current->transfer = NULL; 1795 entry->next = list; 1796 list = entry; 1797 } 1798 } 1799 1800 current->canceled = true; 1801 } 1802 1803 current = current->link; 1804 } 1805 1806 Unlock(); 1807 1808 while (list != NULL) { 1809 transfer_entry *next = list->next; 1810 list->transfer->Finished(B_CANCELED, 0); 1811 delete list->transfer; 1812 free(list); 1813 list = next; 1814 } 1815 1816 // wait for any transfers that might have made it before canceling 1817 while (fProcessingPipe == pipe) 1818 snooze(1000); 1819 1820 // notify the finisher so it can clean up the canceled transfers 1821 release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE); 1822 return B_OK; 1823 } 1824 1825 1826 status_t 1827 EHCI::CancelQueuedIsochronousTransfers(Pipe *pipe, bool force) 1828 { 1829 isochronous_transfer_data *current = fFirstIsochronousTransfer; 1830 1831 while (current) { 1832 if (current->transfer->TransferPipe() == pipe) { 1833 // TODO implement 1834 1835 // TODO: Use the force paramater in order to avoid calling 1836 // invalid callbacks 1837 current->is_active = false; 1838 } 1839 1840 current = current->link; 1841 } 1842 1843 TRACE_ERROR("no isochronous transfer found!\n"); 1844 return B_ERROR; 1845 } 1846 1847 1848 status_t 1849 EHCI::CancelAllPendingTransfers() 1850 { 1851 if (!Lock()) 1852 return B_ERROR; 1853 1854 transfer_data *transfer = fFirstTransfer; 1855 while (transfer) { 1856 transfer->transfer->Finished(B_CANCELED, 0); 1857 delete transfer->transfer; 1858 1859 transfer_data *next = transfer->link; 1860 delete transfer; 1861 transfer = next; 1862 } 1863 1864 fFirstTransfer = NULL; 1865 fLastTransfer = NULL; 1866 Unlock(); 1867 return B_OK; 1868 } 1869 1870 1871 int32 1872 EHCI::FinishThread(void *data) 1873 { 1874 ((EHCI *)data)->FinishTransfers(); 1875 return B_OK; 1876 } 1877 1878 1879 void 1880 EHCI::FinishTransfers() 1881 { 1882 while (!fStopThreads) { 1883 if (acquire_sem(fFinishTransfersSem) != B_OK) 1884 continue; 1885 1886 // eat up sems that have been released by multiple interrupts 1887 int32 semCount = 0; 1888 get_sem_count(fFinishTransfersSem, &semCount); 1889 if (semCount > 0) { 1890 acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 1891 0); 1892 } 1893 1894 if (!Lock()) 1895 continue; 1896 1897 TRACE("finishing transfers\n"); 1898 transfer_data *lastTransfer = NULL; 1899 transfer_data *transfer = fFirstTransfer; 1900 Unlock(); 1901 1902 while (transfer) { 1903 bool transferDone = false; 1904 ehci_qtd *descriptor = transfer->queue_head->element_log; 1905 status_t callbackStatus = B_OK; 1906 1907 while (descriptor) { 1908 uint32 status = descriptor->token; 1909 if (status & EHCI_QTD_STATUS_ACTIVE) { 1910 // still in progress 1911 TRACE("qtd (0x%08" B_PRIx32 ") still active\n", 1912 descriptor->this_phy); 1913 break; 1914 } 1915 1916 if (status & EHCI_QTD_STATUS_ERRMASK) { 1917 // a transfer error occured 1918 TRACE_ERROR("qtd (0x%" B_PRIx32 ") error: 0x%08" B_PRIx32 1919 "\n", descriptor->this_phy, status); 1920 1921 uint8 errorCount = status >> EHCI_QTD_ERRCOUNT_SHIFT; 1922 errorCount &= EHCI_QTD_ERRCOUNT_MASK; 1923 if (errorCount == 0) { 1924 // the error counter counted down to zero, report why 1925 int32 reasons = 0; 1926 if (status & EHCI_QTD_STATUS_BUFFER) { 1927 callbackStatus = transfer->incoming 1928 ? B_DEV_DATA_OVERRUN : B_DEV_DATA_UNDERRUN; 1929 reasons++; 1930 } 1931 if (status & EHCI_QTD_STATUS_TERROR) { 1932 callbackStatus = B_DEV_CRC_ERROR; 1933 reasons++; 1934 } 1935 if ((transfer->queue_head->endpoint_chars 1936 & EHCI_QH_CHARS_EPS_HIGH) == 0) { 1937 // For full-/lowspeed endpoints the unused ping 1938 // state bit is used as another error bit, it is 1939 // unspecific however. 1940 if ((status & EHCI_QTD_STATUS_LS_ERR) != 0) { 1941 callbackStatus = B_DEV_STALLED; 1942 reasons++; 1943 } 1944 } 1945 1946 if (reasons > 1) 1947 callbackStatus = B_DEV_MULTIPLE_ERRORS; 1948 else if (reasons == 0) { 1949 TRACE_ERROR("error counter counted down to zero " 1950 "but none of the error bits are set\n"); 1951 callbackStatus = B_DEV_STALLED; 1952 } 1953 } else if (status & EHCI_QTD_STATUS_BABBLE) { 1954 // there is a babble condition 1955 callbackStatus = transfer->incoming 1956 ? B_DEV_FIFO_OVERRUN : B_DEV_FIFO_UNDERRUN; 1957 } else { 1958 // if the error counter didn't count down to zero 1959 // and there was no babble, then this halt was caused 1960 // by a stall handshake 1961 callbackStatus = B_DEV_STALLED; 1962 } 1963 1964 transferDone = true; 1965 break; 1966 } 1967 1968 if (descriptor->next_phy & EHCI_ITEM_TERMINATE) { 1969 // we arrived at the last (stray) descriptor, we're done 1970 TRACE("qtd (0x%08" B_PRIx32 ") done\n", 1971 descriptor->this_phy); 1972 callbackStatus = B_OK; 1973 transferDone = true; 1974 break; 1975 } 1976 1977 if (((status >> EHCI_QTD_PID_SHIFT) & EHCI_QTD_PID_MASK) 1978 == EHCI_QTD_PID_IN 1979 && ((status >> EHCI_QTD_BYTES_SHIFT) & EHCI_QTD_BYTES_MASK) 1980 != 0) { 1981 // a short packet condition existed on this descriptor, 1982 // follow the alternate next pointer if set 1983 if (descriptor->alt_next_log != NULL) { 1984 descriptor = descriptor->alt_next_log; 1985 continue; 1986 } 1987 1988 // no alternate next, transfer is done 1989 callbackStatus = B_OK; 1990 transferDone = true; 1991 break; 1992 } 1993 1994 descriptor = descriptor->next_log; 1995 } 1996 1997 if (!transferDone) { 1998 lastTransfer = transfer; 1999 transfer = transfer->link; 2000 continue; 2001 } 2002 2003 // remove the transfer from the list first so we are sure 2004 // it doesn't get canceled while we still process it 2005 transfer_data *next = transfer->link; 2006 if (Lock()) { 2007 if (lastTransfer) 2008 lastTransfer->link = transfer->link; 2009 2010 if (transfer == fFirstTransfer) 2011 fFirstTransfer = transfer->link; 2012 if (transfer == fLastTransfer) 2013 fLastTransfer = lastTransfer; 2014 2015 // store the currently processing pipe here so we can wait 2016 // in cancel if we are processing something on the target pipe 2017 if (!transfer->canceled) 2018 fProcessingPipe = transfer->transfer->TransferPipe(); 2019 2020 transfer->link = NULL; 2021 Unlock(); 2022 } 2023 2024 // if canceled the callback has already been called 2025 if (!transfer->canceled) { 2026 size_t actualLength = 0; 2027 2028 if (callbackStatus == B_OK) { 2029 bool nextDataToggle = false; 2030 if (transfer->data_descriptor && transfer->incoming) { 2031 // data to read out 2032 iovec *vector = transfer->transfer->Vector(); 2033 size_t vectorCount = transfer->transfer->VectorCount(); 2034 callbackStatus = transfer->transfer->PrepareKernelAccess(); 2035 if (callbackStatus == B_OK) { 2036 actualLength = ReadDescriptorChain( 2037 transfer->data_descriptor, 2038 vector, vectorCount, 2039 &nextDataToggle); 2040 } 2041 } else if (transfer->data_descriptor) { 2042 // calculate transfered length 2043 actualLength = ReadActualLength( 2044 transfer->data_descriptor, &nextDataToggle); 2045 } 2046 2047 transfer->transfer->TransferPipe()->SetDataToggle( 2048 nextDataToggle); 2049 } 2050 2051 if (callbackStatus == B_OK && transfer->transfer->IsFragmented()) { 2052 // this transfer may still have data left 2053 transfer->transfer->AdvanceByFragment(actualLength); 2054 if (transfer->transfer->FragmentLength() > 0) { 2055 FreeDescriptorChain(transfer->data_descriptor); 2056 status_t result = FillQueueWithData( 2057 transfer->transfer, 2058 transfer->queue_head, 2059 &transfer->data_descriptor, NULL, true); 2060 2061 if (result == B_OK && Lock()) { 2062 // reappend the transfer 2063 if (fLastTransfer) 2064 fLastTransfer->link = transfer; 2065 if (!fFirstTransfer) 2066 fFirstTransfer = transfer; 2067 2068 fLastTransfer = transfer; 2069 Unlock(); 2070 2071 transfer = next; 2072 continue; 2073 } 2074 } 2075 2076 // the transfer is done, but we already set the 2077 // actualLength with AdvanceByFragment() 2078 actualLength = 0; 2079 } 2080 2081 transfer->transfer->Finished(callbackStatus, actualLength); 2082 fProcessingPipe = NULL; 2083 } 2084 2085 // unlink hardware queue and delete the transfer 2086 UnlinkQueueHead(transfer->queue_head, &fFreeListHead); 2087 delete transfer->transfer; 2088 delete transfer; 2089 transfer = next; 2090 release_sem(fCleanupSem); 2091 } 2092 } 2093 } 2094 2095 2096 int32 2097 EHCI::CleanupThread(void *data) 2098 { 2099 ((EHCI *)data)->Cleanup(); 2100 return B_OK; 2101 } 2102 2103 2104 void 2105 EHCI::Cleanup() 2106 { 2107 ehci_qh *lastFreeListHead = NULL; 2108 2109 while (!fStopThreads) { 2110 if (acquire_sem(fCleanupSem) != B_OK) 2111 continue; 2112 2113 ehci_qh *freeListHead = fFreeListHead; 2114 if (freeListHead == lastFreeListHead) 2115 continue; 2116 2117 // set the doorbell and wait for the host controller to notify us 2118 WriteOpReg(EHCI_USBCMD, ReadOpReg(EHCI_USBCMD) | EHCI_USBCMD_INTONAAD); 2119 if (acquire_sem(fAsyncAdvanceSem) != B_OK) 2120 continue; 2121 2122 ehci_qh *current = freeListHead; 2123 while (current != lastFreeListHead) { 2124 ehci_qh *next = current->next_log; 2125 FreeQueueHead(current); 2126 current = next; 2127 } 2128 2129 lastFreeListHead = freeListHead; 2130 } 2131 } 2132 2133 2134 int32 2135 EHCI::FinishIsochronousThread(void *data) 2136 { 2137 ((EHCI *)data)->FinishIsochronousTransfers(); 2138 return B_OK; 2139 } 2140 2141 2142 void 2143 EHCI::FinishIsochronousTransfers() 2144 { 2145 /* This thread stays one position behind the controller and processes every 2146 * isochronous descriptor. Once it finds the last isochronous descriptor 2147 * of a transfer, it processes the entire transfer. 2148 */ 2149 while (!fStopThreads) { 2150 // Go to sleep if there are no isochronous transfers to process 2151 if (acquire_sem(fFinishIsochronousTransfersSem) != B_OK) 2152 return; 2153 2154 bool transferDone = false; 2155 2156 uint32 frame = (ReadOpReg(EHCI_FRINDEX) / 8 ) 2157 & (EHCI_FRAMELIST_ENTRIES_COUNT - 1); 2158 uint32 currentFrame = (frame + EHCI_VFRAMELIST_ENTRIES_COUNT - 5) 2159 & (EHCI_VFRAMELIST_ENTRIES_COUNT - 1); 2160 uint32 loop = 0; 2161 2162 // Process the frame list until one transfer is processed 2163 while (!transferDone && loop++ < EHCI_VFRAMELIST_ENTRIES_COUNT) { 2164 // wait 1ms in order to be sure to be one position behind 2165 // the controller 2166 while (currentFrame == (((ReadOpReg(EHCI_FRINDEX) / 8) 2167 & (EHCI_VFRAMELIST_ENTRIES_COUNT - 1)))) { 2168 snooze(1000); 2169 } 2170 2171 ehci_itd *itd = fItdEntries[currentFrame]; 2172 2173 TRACE("FinishIsochronousTransfers itd %p phy 0x%" B_PRIx32 2174 " prev (%p/0x%" B_PRIx32 ") at frame %" B_PRId32 "\n", itd, 2175 itd->this_phy, itd->prev, itd->prev != NULL 2176 ? itd->prev->this_phy : 0, currentFrame); 2177 2178 if (!LockIsochronous()) 2179 continue; 2180 2181 // Process the frame till it has isochronous descriptors in it. 2182 while (!(itd->next_phy & EHCI_ITEM_TERMINATE) && itd->prev != NULL) { 2183 TRACE("FinishIsochronousTransfers checking itd %p last_token" 2184 " %" B_PRId32 "\n", itd, itd->last_token); 2185 TRACE("FinishIsochronousTransfers tokens 0x%" B_PRIx32 " 0x%" 2186 B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx32 2187 " 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx32 "\n", 2188 itd->token[0], itd->token[1], itd->token[2], itd->token[3], 2189 itd->token[4], itd->token[5], itd->token[6], itd->token[7]); 2190 if (((itd->token[itd->last_token] >> EHCI_ITD_STATUS_SHIFT) 2191 & EHCI_ITD_STATUS_ACTIVE) == EHCI_ITD_STATUS_ACTIVE) { 2192 TRACE("FinishIsochronousTransfers unprocessed active itd\n"); 2193 } 2194 UnlinkITDescriptors(itd, &fItdEntries[currentFrame]); 2195 2196 // Process the transfer if we found the last descriptor 2197 isochronous_transfer_data *transfer 2198 = FindIsochronousTransfer(itd); 2199 // Process the descriptors only if it is still active and 2200 // belongs to an inbound transfer. If the transfer is not 2201 // active, it means the request has been removed, so simply 2202 // remove the descriptors. 2203 if (transfer && transfer->is_active) { 2204 TRACE("FinishIsochronousTransfers active transfer\n"); 2205 size_t actualLength = 0; 2206 status_t status = B_OK; 2207 if (((itd->buffer_phy[1] >> EHCI_ITD_DIR_SHIFT) & 1) != 0) { 2208 status = transfer->transfer->PrepareKernelAccess(); 2209 if (status == B_OK) 2210 actualLength = ReadIsochronousDescriptorChain(transfer); 2211 } 2212 2213 // Remove the transfer 2214 if (transfer == fFirstIsochronousTransfer) { 2215 fFirstIsochronousTransfer = transfer->link; 2216 if (transfer == fLastIsochronousTransfer) 2217 fLastIsochronousTransfer = NULL; 2218 } else { 2219 isochronous_transfer_data *temp 2220 = fFirstIsochronousTransfer; 2221 while (temp != NULL && transfer != temp->link) 2222 temp = temp->link; 2223 2224 if (transfer == fLastIsochronousTransfer) 2225 fLastIsochronousTransfer = temp; 2226 if (temp != NULL && temp->link != NULL) 2227 temp->link = temp->link->link; 2228 } 2229 transfer->link = NULL; 2230 2231 transfer->transfer->Finished(status, actualLength); 2232 2233 itd = itd->prev; 2234 2235 for (uint32 i = 0; i <= transfer->last_to_process; i++) 2236 FreeDescriptor(transfer->descriptors[i]); 2237 2238 TRACE("FinishIsochronousTransfers descriptors freed\n"); 2239 2240 delete [] transfer->descriptors; 2241 delete transfer->transfer; 2242 fStack->FreeChunk(transfer->buffer_log, 2243 (phys_addr_t)transfer->buffer_phy, 2244 transfer->buffer_size); 2245 delete transfer; 2246 transferDone = true; 2247 } else { 2248 TRACE("FinishIsochronousTransfers not end of transfer\n"); 2249 itd = itd->prev; 2250 } 2251 } 2252 2253 UnlockIsochronous(); 2254 2255 TRACE("FinishIsochronousTransfers next frame\n"); 2256 2257 // Make sure to reset the frame bandwidth 2258 fFrameBandwidth[currentFrame] = MAX_AVAILABLE_BANDWIDTH; 2259 currentFrame = (currentFrame + 1) % EHCI_VFRAMELIST_ENTRIES_COUNT; 2260 } 2261 } 2262 } 2263 2264 2265 ehci_qh * 2266 EHCI::CreateQueueHead() 2267 { 2268 ehci_qh *result; 2269 phys_addr_t physicalAddress; 2270 if (fStack->AllocateChunk((void **)&result, &physicalAddress, 2271 sizeof(ehci_qh)) != B_OK) { 2272 TRACE_ERROR("failed to allocate queue head\n"); 2273 return NULL; 2274 } 2275 2276 result->this_phy = (addr_t)physicalAddress | EHCI_ITEM_TYPE_QH; 2277 result->next_phy = EHCI_ITEM_TERMINATE; 2278 result->next_log = NULL; 2279 result->prev_log = NULL; 2280 2281 ehci_qtd *descriptor = CreateDescriptor(0, 0); 2282 if (!descriptor) { 2283 TRACE_ERROR("failed to allocate initial qtd for queue head\n"); 2284 fStack->FreeChunk(result, physicalAddress, sizeof(ehci_qh)); 2285 return NULL; 2286 } 2287 2288 descriptor->token &= ~EHCI_QTD_STATUS_ACTIVE; 2289 result->stray_log = descriptor; 2290 result->element_log = descriptor; 2291 result->current_qtd_phy = 0; 2292 result->overlay.next_phy = descriptor->this_phy; 2293 result->overlay.alt_next_phy = EHCI_ITEM_TERMINATE; 2294 result->overlay.token = 0; 2295 for (int32 i = 0; i < 5; i++) { 2296 result->overlay.buffer_phy[i] = 0; 2297 result->overlay.ext_buffer_phy[i] = 0; 2298 } 2299 2300 return result; 2301 } 2302 2303 2304 status_t 2305 EHCI::InitQueueHead(ehci_qh *queueHead, Pipe *pipe) 2306 { 2307 switch (pipe->Speed()) { 2308 case USB_SPEED_LOWSPEED: 2309 queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_LOW; 2310 break; 2311 case USB_SPEED_FULLSPEED: 2312 queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_FULL; 2313 break; 2314 case USB_SPEED_HIGHSPEED: 2315 queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH; 2316 break; 2317 default: 2318 TRACE_ERROR("unknown pipe speed\n"); 2319 return B_ERROR; 2320 } 2321 2322 queueHead->endpoint_chars |= (3 << EHCI_QH_CHARS_RL_SHIFT) 2323 | (pipe->MaxPacketSize() << EHCI_QH_CHARS_MPL_SHIFT) 2324 | (pipe->EndpointAddress() << EHCI_QH_CHARS_EPT_SHIFT) 2325 | (pipe->DeviceAddress() << EHCI_QH_CHARS_DEV_SHIFT) 2326 | EHCI_QH_CHARS_TOGGLE; 2327 2328 queueHead->endpoint_caps = (1 << EHCI_QH_CAPS_MULT_SHIFT); 2329 if (pipe->Speed() != USB_SPEED_HIGHSPEED) { 2330 if ((pipe->Type() & USB_OBJECT_CONTROL_PIPE) != 0) 2331 queueHead->endpoint_chars |= EHCI_QH_CHARS_CONTROL; 2332 2333 queueHead->endpoint_caps |= (pipe->HubPort() << EHCI_QH_CAPS_PORT_SHIFT) 2334 | (pipe->HubAddress() << EHCI_QH_CAPS_HUB_SHIFT); 2335 } 2336 2337 return B_OK; 2338 } 2339 2340 2341 void 2342 EHCI::FreeQueueHead(ehci_qh *queueHead) 2343 { 2344 if (!queueHead) 2345 return; 2346 2347 FreeDescriptorChain(queueHead->element_log); 2348 FreeDescriptor(queueHead->stray_log); 2349 fStack->FreeChunk(queueHead, (phys_addr_t)queueHead->this_phy, 2350 sizeof(ehci_qh)); 2351 } 2352 2353 2354 status_t 2355 EHCI::LinkQueueHead(ehci_qh *queueHead) 2356 { 2357 if (!Lock()) 2358 return B_ERROR; 2359 2360 ehci_qh *prevHead = fAsyncQueueHead->prev_log; 2361 queueHead->next_phy = fAsyncQueueHead->this_phy; 2362 queueHead->next_log = fAsyncQueueHead; 2363 queueHead->prev_log = prevHead; 2364 fAsyncQueueHead->prev_log = queueHead; 2365 prevHead->next_log = queueHead; 2366 prevHead->next_phy = queueHead->this_phy; 2367 2368 Unlock(); 2369 return B_OK; 2370 } 2371 2372 2373 status_t 2374 EHCI::LinkInterruptQueueHead(ehci_qh *queueHead, Pipe *pipe) 2375 { 2376 uint8 interval = pipe->Interval(); 2377 if (pipe->Speed() == USB_SPEED_HIGHSPEED) { 2378 // Allow interrupts to be scheduled on each possible micro frame. 2379 queueHead->endpoint_caps |= (0xff << EHCI_QH_CAPS_ISM_SHIFT); 2380 } else { 2381 // As we do not yet support FSTNs to correctly reference low/full 2382 // speed interrupt transfers, we simply put them into the 1 or 8 interval 2383 // queue. This way we ensure that we reach them on every micro frame 2384 // and can do the corresponding start/complete split transactions. 2385 // ToDo: use FSTNs to correctly link non high speed interrupt transfers 2386 if (pipe->Speed() == USB_SPEED_LOWSPEED) { 2387 // Low speed devices can't be polled faster than 8ms, so just use 2388 // that. 2389 interval = 4; 2390 } else 2391 interval = 1; 2392 2393 // For now we also force start splits to be in micro frame 0 and 2394 // complete splits to be in micro frame 2, 3 and 4. 2395 queueHead->endpoint_caps |= (0x01 << EHCI_QH_CAPS_ISM_SHIFT); 2396 queueHead->endpoint_caps |= (0x1c << EHCI_QH_CAPS_SCM_SHIFT); 2397 } 2398 2399 // this should not happen 2400 if (interval < 1) 2401 interval = 1; 2402 2403 // this may happen as intervals can go up to 16; we limit the value to 2404 // EHCI_INTERRUPT_ENTRIES_COUNT as you cannot support intervals above 2405 // that with a frame list of just EHCI_VFRAMELIST_ENTRIES_COUNT entries... 2406 if (interval > EHCI_INTERRUPT_ENTRIES_COUNT) 2407 interval = EHCI_INTERRUPT_ENTRIES_COUNT; 2408 2409 if (!Lock()) 2410 return B_ERROR; 2411 2412 ehci_qh *interruptQueue = &fInterruptEntries[interval - 1].queue_head; 2413 queueHead->next_phy = interruptQueue->next_phy; 2414 queueHead->next_log = interruptQueue->next_log; 2415 queueHead->prev_log = interruptQueue; 2416 if (interruptQueue->next_log) 2417 interruptQueue->next_log->prev_log = queueHead; 2418 interruptQueue->next_log = queueHead; 2419 interruptQueue->next_phy = queueHead->this_phy; 2420 2421 Unlock(); 2422 return B_OK; 2423 } 2424 2425 2426 status_t 2427 EHCI::UnlinkQueueHead(ehci_qh *queueHead, ehci_qh **freeListHead) 2428 { 2429 if (!Lock()) 2430 return B_ERROR; 2431 2432 ehci_qh *prevHead = queueHead->prev_log; 2433 ehci_qh *nextHead = queueHead->next_log; 2434 if (prevHead) { 2435 prevHead->next_phy = queueHead->next_phy; 2436 prevHead->next_log = queueHead->next_log; 2437 } 2438 2439 if (nextHead) 2440 nextHead->prev_log = queueHead->prev_log; 2441 2442 queueHead->next_phy = fAsyncQueueHead->this_phy; 2443 queueHead->prev_log = NULL; 2444 2445 queueHead->next_log = *freeListHead; 2446 *freeListHead = queueHead; 2447 2448 Unlock(); 2449 return B_OK; 2450 } 2451 2452 2453 status_t 2454 EHCI::FillQueueWithRequest(Transfer *transfer, ehci_qh *queueHead, 2455 ehci_qtd **_dataDescriptor, bool *_directionIn, bool prepareKernelAccess) 2456 { 2457 Pipe *pipe = transfer->TransferPipe(); 2458 usb_request_data *requestData = transfer->RequestData(); 2459 bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) > 0; 2460 2461 ehci_qtd *setupDescriptor = CreateDescriptor(sizeof(usb_request_data), 2462 EHCI_QTD_PID_SETUP); 2463 ehci_qtd *statusDescriptor = CreateDescriptor(0, 2464 directionIn ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN); 2465 2466 if (!setupDescriptor || !statusDescriptor) { 2467 TRACE_ERROR("failed to allocate descriptors\n"); 2468 FreeDescriptor(setupDescriptor); 2469 FreeDescriptor(statusDescriptor); 2470 return B_NO_MEMORY; 2471 } 2472 2473 iovec vector; 2474 vector.iov_base = requestData; 2475 vector.iov_len = sizeof(usb_request_data); 2476 WriteDescriptorChain(setupDescriptor, &vector, 1); 2477 2478 ehci_qtd *strayDescriptor = queueHead->stray_log; 2479 statusDescriptor->token |= EHCI_QTD_IOC | EHCI_QTD_DATA_TOGGLE; 2480 2481 ehci_qtd *dataDescriptor = NULL; 2482 if (transfer->VectorCount() > 0) { 2483 ehci_qtd *lastDescriptor = NULL; 2484 status_t result = CreateDescriptorChain(pipe, &dataDescriptor, 2485 &lastDescriptor, statusDescriptor, transfer->FragmentLength(), 2486 directionIn ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT); 2487 2488 if (result != B_OK) { 2489 FreeDescriptor(setupDescriptor); 2490 FreeDescriptor(statusDescriptor); 2491 return result; 2492 } 2493 2494 if (!directionIn) { 2495 if (prepareKernelAccess) { 2496 result = transfer->PrepareKernelAccess(); 2497 if (result != B_OK) { 2498 FreeDescriptor(setupDescriptor); 2499 FreeDescriptor(statusDescriptor); 2500 return result; 2501 } 2502 } 2503 WriteDescriptorChain(dataDescriptor, transfer->Vector(), 2504 transfer->VectorCount()); 2505 } 2506 2507 LinkDescriptors(setupDescriptor, dataDescriptor, strayDescriptor); 2508 LinkDescriptors(lastDescriptor, statusDescriptor, statusDescriptor); 2509 } else { 2510 // no data: link setup and status descriptors directly 2511 LinkDescriptors(setupDescriptor, statusDescriptor, strayDescriptor); 2512 } 2513 2514 queueHead->element_log = setupDescriptor; 2515 queueHead->overlay.next_phy = setupDescriptor->this_phy; 2516 queueHead->overlay.alt_next_phy = EHCI_ITEM_TERMINATE; 2517 2518 *_dataDescriptor = dataDescriptor; 2519 *_directionIn = directionIn; 2520 return B_OK; 2521 } 2522 2523 2524 status_t 2525 EHCI::FillQueueWithData(Transfer *transfer, ehci_qh *queueHead, 2526 ehci_qtd **_dataDescriptor, bool *_directionIn, bool prepareKernelAccess) 2527 { 2528 Pipe *pipe = transfer->TransferPipe(); 2529 bool directionIn = (pipe->Direction() == Pipe::In); 2530 2531 ehci_qtd *firstDescriptor = NULL; 2532 ehci_qtd *lastDescriptor = NULL; 2533 ehci_qtd *strayDescriptor = queueHead->stray_log; 2534 status_t result = CreateDescriptorChain(pipe, &firstDescriptor, 2535 &lastDescriptor, strayDescriptor, transfer->FragmentLength(), 2536 directionIn ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT); 2537 2538 if (result != B_OK) 2539 return result; 2540 2541 lastDescriptor->token |= EHCI_QTD_IOC; 2542 if (!directionIn) { 2543 if (prepareKernelAccess) { 2544 result = transfer->PrepareKernelAccess(); 2545 if (result != B_OK) { 2546 FreeDescriptorChain(firstDescriptor); 2547 return result; 2548 } 2549 } 2550 WriteDescriptorChain(firstDescriptor, transfer->Vector(), 2551 transfer->VectorCount()); 2552 } 2553 2554 queueHead->element_log = firstDescriptor; 2555 queueHead->overlay.next_phy = firstDescriptor->this_phy; 2556 queueHead->overlay.alt_next_phy = EHCI_ITEM_TERMINATE; 2557 2558 *_dataDescriptor = firstDescriptor; 2559 if (_directionIn) 2560 *_directionIn = directionIn; 2561 return B_OK; 2562 } 2563 2564 2565 ehci_qtd * 2566 EHCI::CreateDescriptor(size_t bufferSize, uint8 pid) 2567 { 2568 ehci_qtd *result; 2569 phys_addr_t physicalAddress; 2570 if (fStack->AllocateChunk((void **)&result, &physicalAddress, 2571 sizeof(ehci_qtd)) != B_OK) { 2572 TRACE_ERROR("failed to allocate a qtd\n"); 2573 return NULL; 2574 } 2575 2576 result->this_phy = (addr_t)physicalAddress; 2577 result->next_phy = EHCI_ITEM_TERMINATE; 2578 result->next_log = NULL; 2579 result->alt_next_phy = EHCI_ITEM_TERMINATE; 2580 result->alt_next_log = NULL; 2581 result->buffer_size = bufferSize; 2582 result->token = bufferSize << EHCI_QTD_BYTES_SHIFT; 2583 result->token |= 3 << EHCI_QTD_ERRCOUNT_SHIFT; 2584 result->token |= pid << EHCI_QTD_PID_SHIFT; 2585 result->token |= EHCI_QTD_STATUS_ACTIVE; 2586 if (bufferSize == 0) { 2587 result->buffer_log = NULL; 2588 for (int32 i = 0; i < 5; i++) { 2589 result->buffer_phy[i] = 0; 2590 result->ext_buffer_phy[i] = 0; 2591 } 2592 2593 return result; 2594 } 2595 2596 if (fStack->AllocateChunk(&result->buffer_log, &physicalAddress, 2597 bufferSize) != B_OK) { 2598 TRACE_ERROR("unable to allocate qtd buffer\n"); 2599 fStack->FreeChunk(result, (phys_addr_t)result->this_phy, 2600 sizeof(ehci_qtd)); 2601 return NULL; 2602 } 2603 2604 addr_t physicalBase = (addr_t)physicalAddress; 2605 result->buffer_phy[0] = physicalBase; 2606 result->ext_buffer_phy[0] = 0; 2607 for (int32 i = 1; i < 5; i++) { 2608 physicalBase += B_PAGE_SIZE; 2609 result->buffer_phy[i] = physicalBase & EHCI_QTD_PAGE_MASK; 2610 result->ext_buffer_phy[i] = 0; 2611 } 2612 2613 return result; 2614 } 2615 2616 2617 status_t 2618 EHCI::CreateDescriptorChain(Pipe *pipe, ehci_qtd **_firstDescriptor, 2619 ehci_qtd **_lastDescriptor, ehci_qtd *strayDescriptor, size_t bufferSize, 2620 uint8 pid) 2621 { 2622 size_t packetSize = B_PAGE_SIZE * 4; 2623 int32 descriptorCount = (bufferSize + packetSize - 1) / packetSize; 2624 2625 bool dataToggle = pipe->DataToggle(); 2626 ehci_qtd *firstDescriptor = NULL; 2627 ehci_qtd *lastDescriptor = *_firstDescriptor; 2628 for (int32 i = 0; i < descriptorCount; i++) { 2629 ehci_qtd *descriptor = CreateDescriptor(min_c(packetSize, bufferSize), 2630 pid); 2631 2632 if (!descriptor) { 2633 FreeDescriptorChain(firstDescriptor); 2634 return B_NO_MEMORY; 2635 } 2636 2637 if (dataToggle) 2638 descriptor->token |= EHCI_QTD_DATA_TOGGLE; 2639 2640 if (lastDescriptor) 2641 LinkDescriptors(lastDescriptor, descriptor, strayDescriptor); 2642 2643 bufferSize -= packetSize; 2644 lastDescriptor = descriptor; 2645 if (!firstDescriptor) 2646 firstDescriptor = descriptor; 2647 } 2648 2649 *_firstDescriptor = firstDescriptor; 2650 *_lastDescriptor = lastDescriptor; 2651 return B_OK; 2652 } 2653 2654 2655 void 2656 EHCI::FreeDescriptor(ehci_qtd *descriptor) 2657 { 2658 if (!descriptor) 2659 return; 2660 2661 if (descriptor->buffer_log) { 2662 fStack->FreeChunk(descriptor->buffer_log, 2663 (phys_addr_t)descriptor->buffer_phy[0], descriptor->buffer_size); 2664 } 2665 2666 fStack->FreeChunk(descriptor, (phys_addr_t)descriptor->this_phy, 2667 sizeof(ehci_qtd)); 2668 } 2669 2670 2671 void 2672 EHCI::FreeDescriptorChain(ehci_qtd *topDescriptor) 2673 { 2674 ehci_qtd *current = topDescriptor; 2675 ehci_qtd *next = NULL; 2676 2677 while (current) { 2678 next = current->next_log; 2679 FreeDescriptor(current); 2680 current = next; 2681 } 2682 } 2683 2684 2685 ehci_itd * 2686 EHCI::CreateItdDescriptor() 2687 { 2688 ehci_itd *result; 2689 phys_addr_t physicalAddress; 2690 if (fStack->AllocateChunk((void **)&result, &physicalAddress, 2691 sizeof(ehci_itd)) != B_OK) { 2692 TRACE_ERROR("failed to allocate a itd\n"); 2693 return NULL; 2694 } 2695 2696 memset(result, 0, sizeof(ehci_itd)); 2697 result->this_phy = (addr_t)physicalAddress; 2698 result->next_phy = EHCI_ITEM_TERMINATE; 2699 2700 return result; 2701 } 2702 2703 2704 ehci_sitd * 2705 EHCI::CreateSitdDescriptor() 2706 { 2707 ehci_sitd *result; 2708 phys_addr_t physicalAddress; 2709 if (fStack->AllocateChunk((void **)&result, &physicalAddress, 2710 sizeof(ehci_sitd)) != B_OK) { 2711 TRACE_ERROR("failed to allocate a sitd\n"); 2712 return NULL; 2713 } 2714 2715 memset(result, 0, sizeof(ehci_sitd)); 2716 result->this_phy = (addr_t)physicalAddress | EHCI_ITEM_TYPE_SITD; 2717 result->next_phy = EHCI_ITEM_TERMINATE; 2718 2719 return result; 2720 } 2721 2722 2723 void 2724 EHCI::FreeDescriptor(ehci_itd *descriptor) 2725 { 2726 if (!descriptor) 2727 return; 2728 2729 fStack->FreeChunk(descriptor, (phys_addr_t)descriptor->this_phy, 2730 sizeof(ehci_itd)); 2731 } 2732 2733 2734 void 2735 EHCI::FreeDescriptor(ehci_sitd *descriptor) 2736 { 2737 if (!descriptor) 2738 return; 2739 2740 fStack->FreeChunk(descriptor, (phys_addr_t)descriptor->this_phy, 2741 sizeof(ehci_sitd)); 2742 } 2743 2744 2745 void 2746 EHCI::LinkDescriptors(ehci_qtd *first, ehci_qtd *last, ehci_qtd *alt) 2747 { 2748 first->next_phy = last->this_phy; 2749 first->next_log = last; 2750 2751 if (alt) { 2752 first->alt_next_phy = alt->this_phy; 2753 first->alt_next_log = alt; 2754 } else { 2755 first->alt_next_phy = EHCI_ITEM_TERMINATE; 2756 first->alt_next_log = NULL; 2757 } 2758 } 2759 2760 2761 void 2762 EHCI::LinkITDescriptors(ehci_itd *itd, ehci_itd **_last) 2763 { 2764 ehci_itd *last = *_last; 2765 itd->next_phy = last->next_phy; 2766 itd->next = NULL; 2767 itd->prev = last; 2768 last->next = itd; 2769 last->next_phy = itd->this_phy; 2770 *_last = itd; 2771 } 2772 2773 2774 void 2775 EHCI::LinkSITDescriptors(ehci_sitd *sitd, ehci_sitd **_last) 2776 { 2777 ehci_sitd *last = *_last; 2778 sitd->next_phy = last->next_phy; 2779 sitd->next = NULL; 2780 sitd->prev = last; 2781 last->next = sitd; 2782 last->next_phy = sitd->this_phy; 2783 *_last = sitd; 2784 } 2785 2786 2787 void 2788 EHCI::UnlinkITDescriptors(ehci_itd *itd, ehci_itd **last) 2789 { 2790 itd->prev->next_phy = itd->next_phy; 2791 itd->prev->next = itd->next; 2792 if (itd->next != NULL) 2793 itd->next->prev = itd->prev; 2794 if (itd == *last) 2795 *last = itd->prev; 2796 } 2797 2798 2799 void 2800 EHCI::UnlinkSITDescriptors(ehci_sitd *sitd, ehci_sitd **last) 2801 { 2802 sitd->prev->next_phy = sitd->next_phy; 2803 sitd->prev->next = sitd->next; 2804 if (sitd->next != NULL) 2805 sitd->next->prev = sitd->prev; 2806 if (sitd == *last) 2807 *last = sitd->prev; 2808 } 2809 2810 2811 size_t 2812 EHCI::WriteDescriptorChain(ehci_qtd *topDescriptor, iovec *vector, 2813 size_t vectorCount) 2814 { 2815 ehci_qtd *current = topDescriptor; 2816 size_t actualLength = 0; 2817 size_t vectorIndex = 0; 2818 size_t vectorOffset = 0; 2819 size_t bufferOffset = 0; 2820 2821 while (current) { 2822 if (!current->buffer_log) 2823 break; 2824 2825 while (true) { 2826 size_t length = min_c(current->buffer_size - bufferOffset, 2827 vector[vectorIndex].iov_len - vectorOffset); 2828 2829 memcpy((uint8 *)current->buffer_log + bufferOffset, 2830 (uint8 *)vector[vectorIndex].iov_base + vectorOffset, length); 2831 2832 actualLength += length; 2833 vectorOffset += length; 2834 bufferOffset += length; 2835 2836 if (vectorOffset >= vector[vectorIndex].iov_len) { 2837 if (++vectorIndex >= vectorCount) { 2838 TRACE("wrote descriptor chain (%ld bytes, no more vectors)" 2839 "\n", actualLength); 2840 return actualLength; 2841 } 2842 2843 vectorOffset = 0; 2844 } 2845 2846 if (bufferOffset >= current->buffer_size) { 2847 bufferOffset = 0; 2848 break; 2849 } 2850 } 2851 2852 if (current->next_phy & EHCI_ITEM_TERMINATE) 2853 break; 2854 2855 current = current->next_log; 2856 } 2857 2858 TRACE("wrote descriptor chain (%ld bytes)\n", actualLength); 2859 return actualLength; 2860 } 2861 2862 2863 size_t 2864 EHCI::ReadDescriptorChain(ehci_qtd *topDescriptor, iovec *vector, 2865 size_t vectorCount, bool *nextDataToggle) 2866 { 2867 uint32 dataToggle = 0; 2868 ehci_qtd *current = topDescriptor; 2869 size_t actualLength = 0; 2870 size_t vectorIndex = 0; 2871 size_t vectorOffset = 0; 2872 size_t bufferOffset = 0; 2873 2874 while (current && (current->token & EHCI_QTD_STATUS_ACTIVE) == 0) { 2875 if (!current->buffer_log) 2876 break; 2877 2878 dataToggle = current->token & EHCI_QTD_DATA_TOGGLE; 2879 size_t bufferSize = current->buffer_size; 2880 bufferSize -= (current->token >> EHCI_QTD_BYTES_SHIFT) 2881 & EHCI_QTD_BYTES_MASK; 2882 2883 while (true) { 2884 size_t length = min_c(bufferSize - bufferOffset, 2885 vector[vectorIndex].iov_len - vectorOffset); 2886 2887 memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset, 2888 (uint8 *)current->buffer_log + bufferOffset, length); 2889 2890 actualLength += length; 2891 vectorOffset += length; 2892 bufferOffset += length; 2893 2894 if (vectorOffset >= vector[vectorIndex].iov_len) { 2895 if (++vectorIndex >= vectorCount) { 2896 TRACE("read descriptor chain (%ld bytes, no more vectors)" 2897 "\n", actualLength); 2898 *nextDataToggle = dataToggle > 0 ? true : false; 2899 return actualLength; 2900 } 2901 2902 vectorOffset = 0; 2903 } 2904 2905 if (bufferOffset >= bufferSize) { 2906 bufferOffset = 0; 2907 break; 2908 } 2909 } 2910 2911 if (current->next_phy & EHCI_ITEM_TERMINATE) 2912 break; 2913 2914 current = current->next_log; 2915 } 2916 2917 TRACE("read descriptor chain (%ld bytes)\n", actualLength); 2918 *nextDataToggle = dataToggle > 0 ? true : false; 2919 return actualLength; 2920 } 2921 2922 2923 size_t 2924 EHCI::ReadActualLength(ehci_qtd *topDescriptor, bool *nextDataToggle) 2925 { 2926 size_t actualLength = 0; 2927 ehci_qtd *current = topDescriptor; 2928 uint32 dataToggle = 0; 2929 2930 while (current && (current->token & EHCI_QTD_STATUS_ACTIVE) == 0) { 2931 dataToggle = current->token & EHCI_QTD_DATA_TOGGLE; 2932 size_t length = current->buffer_size; 2933 length -= (current->token >> EHCI_QTD_BYTES_SHIFT) 2934 & EHCI_QTD_BYTES_MASK; 2935 actualLength += length; 2936 2937 if (current->next_phy & EHCI_ITEM_TERMINATE) 2938 break; 2939 2940 current = current->next_log; 2941 } 2942 2943 TRACE("read actual length (%ld bytes)\n", actualLength); 2944 *nextDataToggle = dataToggle > 0 ? true : false; 2945 return actualLength; 2946 } 2947 2948 2949 size_t 2950 EHCI::WriteIsochronousDescriptorChain(isochronous_transfer_data *transfer, 2951 uint32 packetCount, iovec *vector) 2952 { 2953 // TODO implement 2954 return 0; 2955 } 2956 2957 2958 size_t 2959 EHCI::ReadIsochronousDescriptorChain(isochronous_transfer_data *transfer) 2960 { 2961 iovec *vector = transfer->transfer->Vector(); 2962 size_t vectorCount = transfer->transfer->VectorCount(); 2963 size_t vectorOffset = 0; 2964 size_t vectorIndex = 0; 2965 usb_isochronous_data *isochronousData 2966 = transfer->transfer->IsochronousData(); 2967 uint32 packet = 0; 2968 size_t totalLength = 0; 2969 size_t bufferOffset = 0; 2970 2971 size_t packetSize = transfer->transfer->DataLength(); 2972 packetSize /= isochronousData->packet_count; 2973 2974 for (uint32 i = 0; i <= transfer->last_to_process; i++) { 2975 ehci_itd *itd = transfer->descriptors[i]; 2976 for (uint32 j = 0; j <= itd->last_token 2977 && packet < isochronousData->packet_count; j++) { 2978 2979 size_t bufferSize = (itd->token[j] >> EHCI_ITD_TLENGTH_SHIFT) 2980 & EHCI_ITD_TLENGTH_MASK; 2981 if (((itd->token[j] >> EHCI_ITD_STATUS_SHIFT) 2982 & EHCI_ITD_STATUS_MASK) != 0) { 2983 bufferSize = 0; 2984 } 2985 isochronousData->packet_descriptors[packet].actual_length 2986 = bufferSize; 2987 2988 if (bufferSize > 0) 2989 isochronousData->packet_descriptors[packet].status = B_OK; 2990 else 2991 isochronousData->packet_descriptors[packet].status = B_ERROR; 2992 2993 totalLength += bufferSize; 2994 2995 size_t offset = bufferOffset; 2996 size_t skipSize = packetSize - bufferSize; 2997 while (bufferSize > 0) { 2998 size_t length = min_c(bufferSize, 2999 vector[vectorIndex].iov_len - vectorOffset); 3000 memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset, 3001 (uint8 *)transfer->buffer_log + bufferOffset, length); 3002 offset += length; 3003 vectorOffset += length; 3004 bufferSize -= length; 3005 3006 if (vectorOffset >= vector[vectorIndex].iov_len) { 3007 if (++vectorIndex >= vectorCount) { 3008 TRACE("read isodescriptor chain (%ld bytes, no more " 3009 "vectors)\n", totalLength); 3010 return totalLength; 3011 } 3012 3013 vectorOffset = 0; 3014 } 3015 } 3016 3017 // skip to next packet offset 3018 while (skipSize > 0) { 3019 size_t length = min_c(skipSize, 3020 vector[vectorIndex].iov_len - vectorOffset); 3021 vectorOffset += length; 3022 skipSize -= length; 3023 if (vectorOffset >= vector[vectorIndex].iov_len) { 3024 if (++vectorIndex >= vectorCount) { 3025 TRACE("read isodescriptor chain (%ld bytes, no more " 3026 "vectors)\n", totalLength); 3027 return totalLength; 3028 } 3029 3030 vectorOffset = 0; 3031 } 3032 } 3033 3034 bufferOffset += packetSize; 3035 if (bufferOffset >= transfer->buffer_size) 3036 return totalLength; 3037 3038 packet++; 3039 } 3040 } 3041 3042 TRACE("ReadIsochronousDescriptorChain packet count %" B_PRId32 "\n", 3043 packet); 3044 3045 return totalLength; 3046 } 3047 3048 3049 bool 3050 EHCI::LockIsochronous() 3051 { 3052 return (mutex_lock(&fIsochronousLock) == B_OK); 3053 } 3054 3055 3056 void 3057 EHCI::UnlockIsochronous() 3058 { 3059 mutex_unlock(&fIsochronousLock); 3060 } 3061 3062 3063 inline void 3064 EHCI::WriteOpReg(uint32 reg, uint32 value) 3065 { 3066 *(volatile uint32 *)(fOperationalRegisters + reg) = value; 3067 } 3068 3069 3070 inline uint32 3071 EHCI::ReadOpReg(uint32 reg) 3072 { 3073 return *(volatile uint32 *)(fOperationalRegisters + reg); 3074 } 3075 3076 3077 inline uint8 3078 EHCI::ReadCapReg8(uint32 reg) 3079 { 3080 return *(volatile uint8 *)(fCapabilityRegisters + reg); 3081 } 3082 3083 3084 inline uint16 3085 EHCI::ReadCapReg16(uint32 reg) 3086 { 3087 return *(volatile uint16 *)(fCapabilityRegisters + reg); 3088 } 3089 3090 3091 inline uint32 3092 EHCI::ReadCapReg32(uint32 reg) 3093 { 3094 return *(volatile uint32 *)(fCapabilityRegisters + reg); 3095 } 3096