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