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