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