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