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