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