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