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