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