1 /* 2 * Copyright 2006-2008, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 */ 8 9 #include <module.h> 10 #include <PCI.h> 11 #include <USB3.h> 12 #include <KernelExport.h> 13 14 #include "ehci.h" 15 16 pci_module_info *EHCI::sPCIModule = NULL; 17 18 19 static int32 20 ehci_std_ops(int32 op, ...) 21 { 22 switch (op) { 23 case B_MODULE_INIT: 24 TRACE(("usb_ehci_module: init module\n")); 25 return B_OK; 26 case B_MODULE_UNINIT: 27 TRACE(("usb_ehci_module: uninit module\n")); 28 return B_OK; 29 } 30 31 return EINVAL; 32 } 33 34 35 host_controller_info ehci_module = { 36 { 37 "busses/usb/ehci", 38 0, 39 ehci_std_ops 40 }, 41 NULL, 42 EHCI::AddTo 43 }; 44 45 46 module_info *modules[] = { 47 (module_info *)&ehci_module, 48 NULL 49 }; 50 51 52 // 53 // #pragma mark - 54 // 55 56 57 #ifdef TRACE_USB 58 59 void 60 print_descriptor_chain(ehci_qtd *descriptor) 61 { 62 while (descriptor) { 63 dprintf(" %08lx n%08lx a%08lx t%08lx %08lx %08lx %08lx %08lx %08lx s%ld\n", 64 descriptor->this_phy, descriptor->next_phy, 65 descriptor->alt_next_phy, descriptor->token, 66 descriptor->buffer_phy[0], descriptor->buffer_phy[1], 67 descriptor->buffer_phy[2], descriptor->buffer_phy[3], 68 descriptor->buffer_phy[4], descriptor->buffer_size); 69 70 if (descriptor->next_phy & EHCI_QTD_TERMINATE) 71 break; 72 73 descriptor = (ehci_qtd *)descriptor->next_log; 74 } 75 } 76 77 void 78 print_queue(ehci_qh *queueHead) 79 { 80 dprintf("queue: t%08lx n%08lx ch%08lx ca%08lx cu%08lx\n", 81 queueHead->this_phy, queueHead->next_phy, queueHead->endpoint_chars, 82 queueHead->endpoint_caps, queueHead->current_qtd_phy); 83 dprintf("overlay: n%08lx a%08lx t%08lx %08lx %08lx %08lx %08lx %08lx\n", 84 queueHead->overlay.next_phy, queueHead->overlay.alt_next_phy, 85 queueHead->overlay.token, queueHead->overlay.buffer_phy[0], 86 queueHead->overlay.buffer_phy[1], queueHead->overlay.buffer_phy[2], 87 queueHead->overlay.buffer_phy[3], queueHead->overlay.buffer_phy[4]); 88 print_descriptor_chain((ehci_qtd *)queueHead->element_log); 89 } 90 91 #endif // TRACE_USB 92 93 94 // 95 // #pragma mark - 96 // 97 98 99 EHCI::EHCI(pci_info *info, Stack *stack) 100 : BusManager(stack), 101 fPCIInfo(info), 102 fStack(stack), 103 fPeriodicFrameListArea(-1), 104 fPeriodicFrameList(NULL), 105 fFirstTransfer(NULL), 106 fLastTransfer(NULL), 107 fFinishThread(-1), 108 fCleanupThread(-1), 109 fStopThreads(false), 110 fFreeListHead(NULL), 111 fRootHub(NULL), 112 fRootHubAddress(0), 113 fPortCount(0), 114 fPortResetChange(0), 115 fPortSuspendChange(0) 116 { 117 if (BusManager::InitCheck() < B_OK) { 118 TRACE_ERROR(("usb_ehci: bus manager failed to init\n")); 119 return; 120 } 121 122 TRACE(("usb_ehci: constructing new EHCI Host Controller Driver\n")); 123 fInitOK = false; 124 125 // enable busmaster and memory mapped access 126 uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus, 127 fPCIInfo->device, fPCIInfo->function, PCI_command, 2); 128 command &= ~PCI_command_io; 129 command |= PCI_command_master | PCI_command_memory; 130 131 sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, 132 fPCIInfo->function, PCI_command, 2, command); 133 134 // map the registers 135 uint32 offset = fPCIInfo->u.h0.base_registers[0] & (B_PAGE_SIZE - 1); 136 addr_t physicalAddress = fPCIInfo->u.h0.base_registers[0] - offset; 137 size_t mapSize = (fPCIInfo->u.h0.base_register_sizes[0] + offset 138 + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); 139 140 TRACE(("usb_ehci: map physical memory 0x%08lx (base: 0x%08lx; offset: %lx); size: %ld\n", fPCIInfo->u.h0.base_registers[0], physicalAddress, offset, fPCIInfo->u.h0.base_register_sizes[0])); 141 fRegisterArea = map_physical_memory("EHCI memory mapped registers", 142 (void *)physicalAddress, mapSize, B_ANY_KERNEL_BLOCK_ADDRESS, 143 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_READ_AREA | B_WRITE_AREA, 144 (void **)&fCapabilityRegisters); 145 if (fRegisterArea < B_OK) { 146 TRACE(("usb_ehci: failed to map register memory\n")); 147 return; 148 } 149 150 fCapabilityRegisters += offset; 151 fOperationalRegisters = fCapabilityRegisters + ReadCapReg8(EHCI_CAPLENGTH); 152 TRACE(("usb_ehci: mapped capability registers: 0x%08lx\n", (uint32)fCapabilityRegisters)); 153 TRACE(("usb_ehci: mapped operational registers: 0x%08lx\n", (uint32)fOperationalRegisters)); 154 155 TRACE(("usb_ehci: structural parameters: 0x%08lx\n", ReadCapReg32(EHCI_HCSPARAMS))); 156 TRACE(("usb_ehci: capability parameters: 0x%08lx\n", ReadCapReg32(EHCI_HCCPARAMS))); 157 158 // read port count from capability register 159 fPortCount = ReadCapReg32(EHCI_HCSPARAMS) & 0x0f; 160 161 uint32 extendedCapPointer = ReadCapReg32(EHCI_HCCPARAMS) >> EHCI_ECP_SHIFT; 162 extendedCapPointer &= EHCI_ECP_MASK; 163 if (extendedCapPointer > 0) { 164 TRACE(("usb_ehci: extended capabilities register at %ld\n", extendedCapPointer)); 165 166 uint32 legacySupport = sPCIModule->read_pci_config(fPCIInfo->bus, 167 fPCIInfo->device, fPCIInfo->function, extendedCapPointer, 4); 168 if ((legacySupport & EHCI_LEGSUP_CAPID_MASK) == EHCI_LEGSUP_CAPID) { 169 if (legacySupport & EHCI_LEGSUP_BIOSOWNED) { 170 TRACE(("usb_ehci: the host controller is bios owned\n")); 171 } 172 173 TRACE(("usb_ehci: claiming ownership of the host controller\n")); 174 sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, 175 fPCIInfo->function, extendedCapPointer, 4, EHCI_LEGSUP_OSOWNED); 176 177 for (int32 i = 0; i < 10; i++) { 178 legacySupport = sPCIModule->read_pci_config(fPCIInfo->bus, 179 fPCIInfo->device, fPCIInfo->function, extendedCapPointer, 4); 180 181 if (legacySupport & EHCI_LEGSUP_BIOSOWNED) { 182 TRACE(("usb_ehci: controller is still bios owned, waiting\n")); 183 snooze(50000); 184 } else 185 break; 186 } 187 188 if (legacySupport & EHCI_LEGSUP_BIOSOWNED) { 189 TRACE_ERROR(("usb_ehci: bios won't give up control over the host controller\n")); 190 return; 191 } else if (legacySupport & EHCI_LEGSUP_OSOWNED) { 192 TRACE(("usb_ehci: successfully took ownership of the host controller\n")); 193 } 194 } else { 195 TRACE(("usb_ehci: extended capability is not a legacy support register\n")); 196 } 197 } else { 198 TRACE(("usb_ehci: no extended capabilities register\n")); 199 } 200 201 // disable interrupts 202 WriteOpReg(EHCI_USBINTR, 0); 203 204 // reset the segment register 205 WriteOpReg(EHCI_CTRDSSEGMENT, 0); 206 207 // reset the host controller 208 if (ControllerReset() < B_OK) { 209 TRACE_ERROR(("usb_ehci: host controller failed to reset\n")); 210 return; 211 } 212 213 // create semaphores the finisher thread will wait for 214 fAsyncAdvanceSem = create_sem(0, "EHCI Async Advance"); 215 fFinishTransfersSem = create_sem(0, "EHCI Finish Transfers"); 216 fCleanupSem = create_sem(0, "EHCI Cleanup"); 217 if (fFinishTransfersSem < B_OK || fAsyncAdvanceSem < B_OK 218 || fCleanupSem < B_OK) { 219 TRACE_ERROR(("usb_ehci: failed to create semaphores\n")); 220 return; 221 } 222 223 // create finisher service thread 224 fFinishThread = spawn_kernel_thread(FinishThread, "ehci finish thread", 225 B_NORMAL_PRIORITY, (void *)this); 226 resume_thread(fFinishThread); 227 228 // create cleanup service thread 229 fCleanupThread = spawn_kernel_thread(CleanupThread, "ehci cleanup thread", 230 B_NORMAL_PRIORITY, (void *)this); 231 resume_thread(fCleanupThread); 232 233 // install the interrupt handler and enable interrupts 234 install_io_interrupt_handler(fPCIInfo->u.h0.interrupt_line, 235 InterruptHandler, (void *)this, 0); 236 WriteOpReg(EHCI_USBINTR, EHCI_USBINTR_HOSTSYSERR 237 | EHCI_USBINTR_USBERRINT | EHCI_USBINTR_USBINT | EHCI_USBINTR_INTONAA); 238 239 // allocate the periodic frame list 240 fPeriodicFrameListArea = fStack->AllocateArea((void **)&fPeriodicFrameList, 241 (void **)&physicalAddress, B_PAGE_SIZE * 2, "USB EHCI Periodic Framelist"); 242 if (fPeriodicFrameListArea < B_OK) { 243 TRACE_ERROR(("usb_ehci: unable to allocate periodic framelist\n")); 244 return; 245 } 246 247 // set the periodic frame list base on the controller 248 WriteOpReg(EHCI_PERIODICLISTBASE, (uint32)physicalAddress); 249 250 // create the interrupt entries to support different polling intervals 251 TRACE(("usb_ehci: creating interrupt entries\n")); 252 addr_t physicalBase = physicalAddress + B_PAGE_SIZE; 253 uint8 *logicalBase = (uint8 *)fPeriodicFrameList + B_PAGE_SIZE; 254 memset(logicalBase, 0, B_PAGE_SIZE); 255 256 fInterruptEntries = (interrupt_entry *)logicalBase; 257 for (int32 i = 0; i < 11; i++) { 258 ehci_qh *queueHead = &fInterruptEntries[i].queue_head; 259 queueHead->this_phy = physicalBase; 260 queueHead->current_qtd_phy = EHCI_QTD_TERMINATE; 261 queueHead->overlay.next_phy = EHCI_QTD_TERMINATE; 262 queueHead->overlay.alt_next_phy = EHCI_QTD_TERMINATE; 263 queueHead->overlay.token = EHCI_QTD_STATUS_HALTED; 264 265 // set dummy endpoint information 266 queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH 267 | (3 << EHCI_QH_CHARS_RL_SHIFT) | (64 << EHCI_QH_CHARS_MPL_SHIFT) 268 | EHCI_QH_CHARS_TOGGLE; 269 queueHead->endpoint_caps = (1 << EHCI_QH_CAPS_MULT_SHIFT) 270 | (0xff << EHCI_QH_CAPS_ISM_SHIFT); 271 272 physicalBase += sizeof(interrupt_entry); 273 } 274 275 // build flat interrupt tree 276 TRACE(("usb_ehci: build up interrupt links\n")); 277 uint32 interval = 1024; 278 uint32 intervalIndex = 10; 279 while (interval > 1) { 280 uint32 insertIndex = interval / 2; 281 while (insertIndex < 1024) { 282 uint32 entry = fInterruptEntries[intervalIndex].queue_head.this_phy; 283 fPeriodicFrameList[insertIndex] = entry | EHCI_PFRAMELIST_QH; 284 insertIndex += interval; 285 } 286 287 intervalIndex--; 288 interval /= 2; 289 } 290 291 // setup the empty slot in the list and linking of all -> first 292 ehci_qh *firstLogical = &fInterruptEntries[0].queue_head; 293 uint32 firstPhysical = firstLogical->this_phy | EHCI_QH_TYPE_QH; 294 fPeriodicFrameList[0] = firstPhysical; 295 for (int32 i = 1; i < 11; i++) { 296 fInterruptEntries[i].queue_head.next_phy = firstPhysical; 297 fInterruptEntries[i].queue_head.next_log = firstLogical; 298 fInterruptEntries[i].queue_head.prev_log = NULL; 299 } 300 301 // terminate the first entry 302 firstLogical->next_phy = EHCI_QH_TERMINATE; 303 firstLogical->next_log = NULL; 304 firstLogical->prev_log = NULL; 305 306 // allocate a queue head that will always stay in the async frame list 307 fAsyncQueueHead = CreateQueueHead(); 308 if (!fAsyncQueueHead) { 309 TRACE_ERROR(("usb_ehci: unable to allocate stray async queue head\n")); 310 return; 311 } 312 313 fAsyncQueueHead->next_phy = fAsyncQueueHead->this_phy | EHCI_QH_TYPE_QH; 314 fAsyncQueueHead->next_log = fAsyncQueueHead; 315 fAsyncQueueHead->prev_log = fAsyncQueueHead; 316 fAsyncQueueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH | EHCI_QH_CHARS_RECHEAD; 317 fAsyncQueueHead->endpoint_caps = 1 << EHCI_QH_CAPS_MULT_SHIFT; 318 fAsyncQueueHead->current_qtd_phy = EHCI_QTD_TERMINATE; 319 fAsyncQueueHead->overlay.next_phy = EHCI_QTD_TERMINATE; 320 321 WriteOpReg(EHCI_ASYNCLISTADDR, (uint32)fAsyncQueueHead->this_phy 322 | EHCI_QH_TYPE_QH); 323 TRACE(("usb_ehci: set the async list addr to 0x%08lx\n", ReadOpReg(EHCI_ASYNCLISTADDR))); 324 325 fInitOK = true; 326 TRACE(("usb_ehci: EHCI Host Controller Driver constructed\n")); 327 } 328 329 330 EHCI::~EHCI() 331 { 332 TRACE(("usb_ehci: tear down EHCI Host Controller Driver\n")); 333 334 WriteOpReg(EHCI_USBCMD, 0); 335 WriteOpReg(EHCI_CONFIGFLAG, 0); 336 CancelAllPendingTransfers(); 337 338 int32 result = 0; 339 fStopThreads = true; 340 delete_sem(fAsyncAdvanceSem); 341 delete_sem(fFinishTransfersSem); 342 wait_for_thread(fFinishThread, &result); 343 wait_for_thread(fCleanupThread, &result); 344 345 delete fRootHub; 346 delete_area(fPeriodicFrameListArea); 347 delete_area(fRegisterArea); 348 put_module(B_PCI_MODULE_NAME); 349 } 350 351 352 status_t 353 EHCI::Start() 354 { 355 TRACE(("usb_ehci: starting EHCI Host Controller\n")); 356 TRACE(("usb_ehci: usbcmd: 0x%08lx; usbsts: 0x%08lx\n", ReadOpReg(EHCI_USBCMD), ReadOpReg(EHCI_USBSTS))); 357 358 uint32 frameListSize = (ReadOpReg(EHCI_USBCMD) >> EHCI_USBCMD_FLS_SHIFT) 359 & EHCI_USBCMD_FLS_MASK; 360 WriteOpReg(EHCI_USBCMD, ReadOpReg(EHCI_USBCMD) | EHCI_USBCMD_RUNSTOP 361 | EHCI_USBCMD_ASENABLE | EHCI_USBCMD_PSENABLE 362 | (frameListSize << EHCI_USBCMD_FLS_SHIFT) 363 | (2 << EHCI_USBCMD_ITC_SHIFT)); 364 365 // route all ports to us 366 WriteOpReg(EHCI_CONFIGFLAG, EHCI_CONFIGFLAG_FLAG); 367 368 bool running = false; 369 for (int32 i = 0; i < 10; i++) { 370 uint32 status = ReadOpReg(EHCI_USBSTS); 371 TRACE(("usb_ehci: try %ld: status 0x%08lx\n", i, status)); 372 373 if (status & EHCI_USBSTS_HCHALTED) { 374 snooze(10000); 375 } else { 376 running = true; 377 break; 378 } 379 } 380 381 // set the interrupt threshold 382 WriteOpReg(EHCI_USBCMD, ReadOpReg(EHCI_USBCMD) 383 | (1 << EHCI_USBCMD_ITC_SHIFT)); 384 385 if (!running) { 386 TRACE(("usb_ehci: Host Controller didn't start\n")); 387 return B_ERROR; 388 } 389 390 fRootHubAddress = AllocateAddress(); 391 fRootHub = new(std::nothrow) EHCIRootHub(RootObject(), fRootHubAddress); 392 if (!fRootHub) { 393 TRACE_ERROR(("usb_ehci: no memory to allocate root hub\n")); 394 return B_NO_MEMORY; 395 } 396 397 if (fRootHub->InitCheck() < B_OK) { 398 TRACE_ERROR(("usb_ehci: root hub failed init check\n")); 399 return fRootHub->InitCheck(); 400 } 401 402 SetRootHub(fRootHub); 403 TRACE(("usb_ehci: Host Controller started\n")); 404 return BusManager::Start(); 405 } 406 407 408 status_t 409 EHCI::SubmitTransfer(Transfer *transfer) 410 { 411 // short circuit the root hub 412 if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress) 413 return fRootHub->ProcessTransfer(this, transfer); 414 415 Pipe *pipe = transfer->TransferPipe(); 416 if (pipe->Type() & USB_OBJECT_ISO_PIPE) { 417 // ToDo: implement isochronous transfers... 418 return B_ERROR; 419 } 420 421 ehci_qh *queueHead = CreateQueueHead(); 422 if (!queueHead) { 423 TRACE_ERROR(("usb_ehci: failed to allocate queue head\n")); 424 return B_NO_MEMORY; 425 } 426 427 status_t result = InitQueueHead(queueHead, pipe); 428 if (result < B_OK) { 429 TRACE_ERROR(("usb_ehci: failed to init queue head\n")); 430 FreeQueueHead(queueHead); 431 return result; 432 } 433 434 bool directionIn; 435 ehci_qtd *dataDescriptor; 436 if (pipe->Type() & USB_OBJECT_CONTROL_PIPE) { 437 result = FillQueueWithRequest(transfer, queueHead, &dataDescriptor, 438 &directionIn); 439 } else { 440 result = FillQueueWithData(transfer, queueHead, &dataDescriptor, 441 &directionIn); 442 } 443 444 if (result < B_OK) { 445 TRACE_ERROR(("usb_ehci: failed to fill transfer queue with data\n")); 446 FreeQueueHead(queueHead); 447 return result; 448 } 449 450 result = AddPendingTransfer(transfer, queueHead, dataDescriptor, directionIn); 451 if (result < B_OK) { 452 TRACE_ERROR(("usb_ehci: failed to add pending transfer\n")); 453 FreeQueueHead(queueHead); 454 return result; 455 } 456 457 #ifdef TRACE_USB 458 TRACE(("usb_ehci: linking queue\n")); 459 print_queue(queueHead); 460 #endif 461 462 if (pipe->Type() & USB_OBJECT_INTERRUPT_PIPE) 463 result = LinkInterruptQueueHead(queueHead, pipe); 464 else 465 result = LinkQueueHead(queueHead); 466 467 if (result < B_OK) { 468 TRACE_ERROR(("usb_ehci: failed to link queue head\n")); 469 FreeQueueHead(queueHead); 470 return result; 471 } 472 473 return B_OK; 474 } 475 476 477 status_t 478 EHCI::NotifyPipeChange(Pipe *pipe, usb_change change) 479 { 480 TRACE(("usb_ehci: pipe change %d for pipe 0x%08lx\n", change, (uint32)pipe)); 481 switch (change) { 482 case USB_CHANGE_CREATED: 483 case USB_CHANGE_DESTROYED: { 484 // ToDo: we should create and keep a single queue head 485 // for all transfers to/from this pipe 486 break; 487 } 488 489 case USB_CHANGE_PIPE_POLICY_CHANGED: { 490 // ToDo: for isochronous pipes we might need to adapt to new 491 // pipe policy settings here 492 break; 493 } 494 } 495 496 return B_OK; 497 } 498 499 500 status_t 501 EHCI::AddTo(Stack *stack) 502 { 503 #ifdef TRACE_USB 504 set_dprintf_enabled(true); 505 load_driver_symbols("ehci"); 506 #endif 507 508 if (!sPCIModule) { 509 status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule); 510 if (status < B_OK) { 511 TRACE_ERROR(("usb_ehci: getting pci module failed! 0x%08lx\n", status)); 512 return status; 513 } 514 } 515 516 TRACE(("usb_ehci: searching devices\n")); 517 bool found = false; 518 pci_info *item = new(std::nothrow) pci_info; 519 if (!item) { 520 sPCIModule = NULL; 521 put_module(B_PCI_MODULE_NAME); 522 return B_NO_MEMORY; 523 } 524 525 for (int32 i = 0; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) { 526 if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb 527 && item->class_api == PCI_usb_ehci) { 528 if (item->u.h0.interrupt_line == 0 529 || item->u.h0.interrupt_line == 0xFF) { 530 TRACE_ERROR(("usb_ehci: found device with invalid IRQ - check IRQ assignement\n")); 531 continue; 532 } 533 534 TRACE(("usb_ehci: found device at IRQ %u\n", item->u.h0.interrupt_line)); 535 EHCI *bus = new(std::nothrow) EHCI(item, stack); 536 if (!bus) { 537 delete item; 538 sPCIModule = NULL; 539 put_module(B_PCI_MODULE_NAME); 540 return B_NO_MEMORY; 541 } 542 543 if (bus->InitCheck() < B_OK) { 544 TRACE_ERROR(("usb_ehci: bus failed init check\n")); 545 delete bus; 546 continue; 547 } 548 549 // the bus took it away 550 item = new(std::nothrow) pci_info; 551 552 bus->Start(); 553 stack->AddBusManager(bus); 554 found = true; 555 } 556 } 557 558 if (!found) { 559 TRACE_ERROR(("usb_ehci: no devices found\n")); 560 delete item; 561 sPCIModule = NULL; 562 put_module(B_PCI_MODULE_NAME); 563 return ENODEV; 564 } 565 566 delete item; 567 return B_OK; 568 } 569 570 571 status_t 572 EHCI::GetPortStatus(uint8 index, usb_port_status *status) 573 { 574 if (index >= fPortCount) 575 return B_BAD_INDEX; 576 577 status->status = status->change = 0; 578 uint32 portStatus = ReadOpReg(EHCI_PORTSC + index * sizeof(uint32)); 579 580 // build the status 581 if (portStatus & EHCI_PORTSC_CONNSTATUS) 582 status->status |= PORT_STATUS_CONNECTION; 583 if (portStatus & EHCI_PORTSC_ENABLE) 584 status->status |= PORT_STATUS_ENABLE; 585 if (portStatus & EHCI_PORTSC_ENABLE) 586 status->status |= PORT_STATUS_HIGH_SPEED; 587 if (portStatus & EHCI_PORTSC_OCACTIVE) 588 status->status |= PORT_STATUS_OVER_CURRENT; 589 if (portStatus & EHCI_PORTSC_PORTRESET) 590 status->status |= PORT_STATUS_RESET; 591 if (portStatus & EHCI_PORTSC_PORTPOWER) 592 status->status |= PORT_STATUS_POWER; 593 if (portStatus & EHCI_PORTSC_SUSPEND) 594 status->status |= PORT_STATUS_SUSPEND; 595 if (portStatus & EHCI_PORTSC_DMINUS) 596 status->status |= PORT_STATUS_LOW_SPEED; 597 598 // build the change 599 if (portStatus & EHCI_PORTSC_CONNCHANGE) 600 status->change |= PORT_STATUS_CONNECTION; 601 if (portStatus & EHCI_PORTSC_ENABLECHANGE) 602 status->change |= PORT_STATUS_ENABLE; 603 if (portStatus & EHCI_PORTSC_OCCHANGE) 604 status->change |= PORT_STATUS_OVER_CURRENT; 605 606 // there are no bits to indicate suspend and reset change 607 if (fPortResetChange & (1 << index)) 608 status->change |= PORT_STATUS_RESET; 609 if (fPortSuspendChange & (1 << index)) 610 status->change |= PORT_STATUS_SUSPEND; 611 612 return B_OK; 613 } 614 615 616 status_t 617 EHCI::SetPortFeature(uint8 index, uint16 feature) 618 { 619 if (index >= fPortCount) 620 return B_BAD_INDEX; 621 622 uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32); 623 uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK; 624 625 switch (feature) { 626 case PORT_SUSPEND: 627 return SuspendPort(index); 628 629 case PORT_RESET: 630 return ResetPort(index); 631 632 case PORT_POWER: 633 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTPOWER); 634 return B_OK; 635 } 636 637 return B_BAD_VALUE; 638 } 639 640 641 status_t 642 EHCI::ClearPortFeature(uint8 index, uint16 feature) 643 { 644 if (index >= fPortCount) 645 return B_BAD_INDEX; 646 647 uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32); 648 uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK; 649 650 switch (feature) { 651 case PORT_ENABLE: 652 WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_ENABLE); 653 return B_OK; 654 655 case PORT_POWER: 656 WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_PORTPOWER); 657 return B_OK; 658 659 case C_PORT_CONNECTION: 660 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_CONNCHANGE); 661 return B_OK; 662 663 case C_PORT_ENABLE: 664 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_ENABLECHANGE); 665 return B_OK; 666 667 case C_PORT_OVER_CURRENT: 668 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_OCCHANGE); 669 return B_OK; 670 671 case C_PORT_RESET: 672 fPortResetChange &= ~(1 << index); 673 return B_OK; 674 675 case C_PORT_SUSPEND: 676 fPortSuspendChange &= ~(1 << index); 677 return B_OK; 678 } 679 680 return B_BAD_VALUE; 681 } 682 683 684 status_t 685 EHCI::ResetPort(uint8 index) 686 { 687 TRACE(("usb_ehci: reset port %d\n", index)); 688 uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32); 689 uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK; 690 691 if (portStatus & EHCI_PORTSC_DMINUS) { 692 TRACE(("usb_ehci: lowspeed device connected, giving up port ownership\n")); 693 // there is a lowspeed device connected. 694 // we give the ownership to a companion controller. 695 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTOWNER); 696 fPortResetChange |= (1 << index); 697 return B_OK; 698 } 699 700 // enable reset signaling 701 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTRESET); 702 snooze(250000); 703 704 // disable reset signaling 705 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK; 706 WriteOpReg(portRegister, portStatus & ~EHCI_PORTSC_PORTRESET); 707 snooze(2000); 708 709 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK; 710 if (portStatus & EHCI_PORTSC_PORTRESET) { 711 TRACE(("usb_ehci: port reset won't complete\n")); 712 return B_ERROR; 713 } 714 715 if ((portStatus & EHCI_PORTSC_ENABLE) == 0) { 716 TRACE(("usb_ehci: fullspeed device connected, giving up port ownership\n")); 717 // the port was not enabled, this means that no high speed device is 718 // attached to this port. we give up ownership to a companion controler 719 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_PORTOWNER); 720 } 721 722 fPortResetChange |= (1 << index); 723 return B_OK; 724 } 725 726 727 status_t 728 EHCI::SuspendPort(uint8 index) 729 { 730 uint32 portRegister = EHCI_PORTSC + index * sizeof(uint32); 731 uint32 portStatus = ReadOpReg(portRegister) & EHCI_PORTSC_DATAMASK; 732 WriteOpReg(portRegister, portStatus | EHCI_PORTSC_SUSPEND); 733 fPortSuspendChange |= (1 << index); 734 return B_OK; 735 } 736 737 738 status_t 739 EHCI::ControllerReset() 740 { 741 // halt the controller first 742 WriteOpReg(EHCI_USBCMD, 0); 743 snooze(10000); 744 745 // then reset it 746 WriteOpReg(EHCI_USBCMD, EHCI_USBCMD_HCRESET); 747 748 int32 tries = 5; 749 while (ReadOpReg(EHCI_USBCMD) & EHCI_USBCMD_HCRESET) { 750 snooze(10000); 751 if (tries-- < 0) 752 return B_ERROR; 753 } 754 755 return B_OK; 756 } 757 758 759 status_t 760 EHCI::LightReset() 761 { 762 return B_ERROR; 763 } 764 765 766 int32 767 EHCI::InterruptHandler(void *data) 768 { 769 return ((EHCI *)data)->Interrupt(); 770 } 771 772 773 int32 774 EHCI::Interrupt() 775 { 776 static spinlock lock = 0; 777 acquire_spinlock(&lock); 778 779 // check if any interrupt was generated 780 uint32 status = ReadOpReg(EHCI_USBSTS); 781 if ((status & EHCI_USBSTS_INTMASK) == 0) { 782 release_spinlock(&lock); 783 return B_UNHANDLED_INTERRUPT; 784 } 785 786 uint32 acknowledge = 0; 787 bool asyncAdvance = false; 788 bool finishTransfers = false; 789 int32 result = B_HANDLED_INTERRUPT; 790 791 if (status & EHCI_USBSTS_USBINT) { 792 TRACE(("usb_ehci: transfer finished\n")); 793 acknowledge |= EHCI_USBSTS_USBINT; 794 result = B_INVOKE_SCHEDULER; 795 finishTransfers = true; 796 } 797 798 if (status & EHCI_USBSTS_USBERRINT) { 799 TRACE(("usb_ehci: transfer error\n")); 800 acknowledge |= EHCI_USBSTS_USBERRINT; 801 result = B_INVOKE_SCHEDULER; 802 finishTransfers = true; 803 } 804 805 if (status & EHCI_USBSTS_PORTCHANGE) { 806 TRACE(("usb_ehci: port change detected\n")); 807 acknowledge |= EHCI_USBSTS_PORTCHANGE; 808 } 809 810 if (status & EHCI_USBSTS_FLROLLOVER) { 811 TRACE(("usb_ehci: frame list rolled over\n")); 812 acknowledge |= EHCI_USBSTS_FLROLLOVER; 813 } 814 815 if (status & EHCI_USBSTS_INTONAA) { 816 TRACE(("usb_ehci: interrupt on async advance\n")); 817 acknowledge |= EHCI_USBSTS_INTONAA; 818 asyncAdvance = true; 819 result = B_INVOKE_SCHEDULER; 820 } 821 822 if (status & EHCI_USBSTS_HOSTSYSERR) { 823 TRACE_ERROR(("usb_ehci: host system error!\n")); 824 acknowledge |= EHCI_USBSTS_HOSTSYSERR; 825 } 826 827 if (acknowledge) 828 WriteOpReg(EHCI_USBSTS, acknowledge); 829 830 release_spinlock(&lock); 831 832 if (asyncAdvance) 833 release_sem_etc(fAsyncAdvanceSem, 1, B_DO_NOT_RESCHEDULE); 834 if (finishTransfers) 835 release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE); 836 837 return result; 838 } 839 840 841 status_t 842 EHCI::AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead, 843 ehci_qtd *dataDescriptor, bool directionIn) 844 { 845 transfer_data *data = new(std::nothrow) transfer_data; 846 if (!data) 847 return B_NO_MEMORY; 848 849 status_t result = transfer->InitKernelAccess(); 850 if (result < B_OK) { 851 delete data; 852 return result; 853 } 854 855 data->transfer = transfer; 856 data->queue_head = queueHead; 857 data->data_descriptor = dataDescriptor; 858 data->incoming = directionIn; 859 data->canceled = false; 860 data->link = NULL; 861 862 if (!Lock()) { 863 delete data; 864 return B_ERROR; 865 } 866 867 if (fLastTransfer) 868 fLastTransfer->link = data; 869 else 870 fFirstTransfer = data; 871 872 fLastTransfer = data; 873 Unlock(); 874 875 return B_OK; 876 } 877 878 879 status_t 880 EHCI::CancelQueuedTransfers(Pipe *pipe, bool force) 881 { 882 if (!Lock()) 883 return B_ERROR; 884 885 transfer_data *current = fFirstTransfer; 886 while (current) { 887 if (current->transfer->TransferPipe() == pipe) { 888 // clear the active bit so the descriptors are canceled 889 ehci_qtd *descriptor = (ehci_qtd *)current->queue_head->element_log; 890 while (descriptor) { 891 descriptor->token &= ~EHCI_QTD_STATUS_ACTIVE; 892 descriptor = (ehci_qtd *)descriptor->next_log; 893 } 894 895 if (!force) { 896 // if the transfer is canceled by force, the one causing the 897 // cancel is probably not the one who initiated the transfer 898 // and the callback is likely not safe anymore 899 current->transfer->Finished(B_CANCELED, 0); 900 } 901 902 current->canceled = true; 903 } 904 905 current = current->link; 906 } 907 908 Unlock(); 909 910 // notify the finisher so it can clean up the canceled transfers 911 release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE); 912 return B_OK; 913 } 914 915 916 status_t 917 EHCI::CancelAllPendingTransfers() 918 { 919 if (!Lock()) 920 return B_ERROR; 921 922 transfer_data *transfer = fFirstTransfer; 923 while (transfer) { 924 transfer->transfer->Finished(B_CANCELED, 0); 925 delete transfer->transfer; 926 927 transfer_data *next = transfer->link; 928 delete transfer; 929 transfer = next; 930 } 931 932 fFirstTransfer = NULL; 933 fLastTransfer = NULL; 934 Unlock(); 935 return B_OK; 936 } 937 938 939 int32 940 EHCI::FinishThread(void *data) 941 { 942 ((EHCI *)data)->FinishTransfers(); 943 return B_OK; 944 } 945 946 947 void 948 EHCI::FinishTransfers() 949 { 950 while (!fStopThreads) { 951 if (acquire_sem(fFinishTransfersSem) < B_OK) 952 continue; 953 954 // eat up sems that have been released by multiple interrupts 955 int32 semCount = 0; 956 get_sem_count(fFinishTransfersSem, &semCount); 957 if (semCount > 0) 958 acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0); 959 960 if (!Lock()) 961 continue; 962 963 TRACE(("usb_ehci: finishing transfers\n")); 964 transfer_data *lastTransfer = NULL; 965 transfer_data *transfer = fFirstTransfer; 966 Unlock(); 967 968 while (transfer) { 969 bool transferDone = false; 970 ehci_qtd *descriptor = (ehci_qtd *)transfer->queue_head->element_log; 971 status_t callbackStatus = B_OK; 972 973 while (descriptor) { 974 uint32 status = descriptor->token; 975 if (status & EHCI_QTD_STATUS_ACTIVE) { 976 // still in progress 977 TRACE(("usb_ehci: qtd (0x%08lx) still active\n", descriptor->this_phy)); 978 break; 979 } 980 981 if (status & EHCI_QTD_STATUS_ERRMASK) { 982 // a transfer error occured 983 TRACE_ERROR(("usb_ehci: qtd (0x%08lx) error: 0x%08lx\n", descriptor->this_phy, status)); 984 985 uint8 errorCount = status >> EHCI_QTD_ERRCOUNT_SHIFT; 986 errorCount &= EHCI_QTD_ERRCOUNT_MASK; 987 if (errorCount == 0) { 988 // the error counter counted down to zero, report why 989 int32 reasons = 0; 990 if (status & EHCI_QTD_STATUS_BUFFER) { 991 callbackStatus = transfer->incoming ? B_DEV_DATA_OVERRUN : B_DEV_DATA_UNDERRUN; 992 reasons++; 993 } 994 if (status & EHCI_QTD_STATUS_TERROR) { 995 callbackStatus = B_DEV_CRC_ERROR; 996 reasons++; 997 } 998 999 if (reasons > 1) 1000 callbackStatus = B_DEV_MULTIPLE_ERRORS; 1001 } else if (status & EHCI_QTD_STATUS_BABBLE) { 1002 // there is a babble condition 1003 callbackStatus = transfer->incoming ? B_DEV_FIFO_OVERRUN : B_DEV_FIFO_UNDERRUN; 1004 } else { 1005 // if the error counter didn't count down to zero 1006 // and there was no babble, then this halt was caused 1007 // by a stall handshake 1008 callbackStatus = B_DEV_STALLED; 1009 } 1010 1011 transferDone = true; 1012 break; 1013 } 1014 1015 if (descriptor->next_phy & EHCI_QTD_TERMINATE) { 1016 // we arrived at the last (stray) descriptor, we're done 1017 TRACE(("usb_ehci: qtd (0x%08lx) done\n", descriptor->this_phy)); 1018 callbackStatus = B_OK; 1019 transferDone = true; 1020 break; 1021 } 1022 1023 descriptor = (ehci_qtd *)descriptor->next_log; 1024 } 1025 1026 if (!transferDone) { 1027 lastTransfer = transfer; 1028 transfer = transfer->link; 1029 continue; 1030 } 1031 1032 // remove the transfer from the list first so we are sure 1033 // it doesn't get canceled while we still process it 1034 transfer_data *next = transfer->link; 1035 if (Lock()) { 1036 if (lastTransfer) 1037 lastTransfer->link = transfer->link; 1038 1039 if (transfer == fFirstTransfer) 1040 fFirstTransfer = transfer->link; 1041 if (transfer == fLastTransfer) 1042 fLastTransfer = lastTransfer; 1043 1044 transfer->link = NULL; 1045 Unlock(); 1046 } 1047 1048 // if canceled the callback has already been called 1049 if (!transfer->canceled) { 1050 size_t actualLength = 0; 1051 1052 if (callbackStatus == B_OK) { 1053 bool nextDataToggle = false; 1054 if (transfer->data_descriptor && transfer->incoming) { 1055 // data to read out 1056 iovec *vector = transfer->transfer->Vector(); 1057 size_t vectorCount = transfer->transfer->VectorCount(); 1058 transfer->transfer->PrepareKernelAccess(); 1059 actualLength = ReadDescriptorChain( 1060 transfer->data_descriptor, 1061 vector, vectorCount, 1062 &nextDataToggle); 1063 } else { 1064 // calculate transfered length 1065 actualLength = ReadActualLength( 1066 (ehci_qtd *)transfer->queue_head->element_log, 1067 &nextDataToggle); 1068 } 1069 1070 transfer->transfer->TransferPipe()->SetDataToggle(nextDataToggle); 1071 1072 if (transfer->transfer->IsFragmented()) { 1073 // this transfer may still have data left 1074 transfer->transfer->AdvanceByFragment(actualLength); 1075 if (transfer->transfer->VectorLength() > 0) { 1076 FreeDescriptorChain(transfer->data_descriptor); 1077 transfer->transfer->PrepareKernelAccess(); 1078 status_t result = FillQueueWithData( 1079 transfer->transfer, 1080 transfer->queue_head, 1081 &transfer->data_descriptor, NULL); 1082 1083 if (result == B_OK && Lock()) { 1084 // reappend the transfer 1085 if (fLastTransfer) 1086 fLastTransfer->link = transfer; 1087 if (!fFirstTransfer) 1088 fFirstTransfer = transfer; 1089 1090 fLastTransfer = transfer; 1091 Unlock(); 1092 1093 transfer = next; 1094 continue; 1095 } 1096 } 1097 1098 // the transfer is done, but we already set the 1099 // actualLength with AdvanceByFragment() 1100 actualLength = 0; 1101 } 1102 } 1103 1104 transfer->transfer->Finished(callbackStatus, actualLength); 1105 } 1106 1107 // unlink hardware queue and delete the transfer 1108 UnlinkQueueHead(transfer->queue_head, &fFreeListHead); 1109 delete transfer->transfer; 1110 delete transfer; 1111 transfer = next; 1112 release_sem(fCleanupSem); 1113 } 1114 } 1115 } 1116 1117 1118 int32 1119 EHCI::CleanupThread(void *data) 1120 { 1121 ((EHCI *)data)->Cleanup(); 1122 return B_OK; 1123 } 1124 1125 1126 void 1127 EHCI::Cleanup() 1128 { 1129 ehci_qh *lastFreeListHead = NULL; 1130 1131 while (!fStopThreads) { 1132 if (acquire_sem(fCleanupSem) < B_OK) 1133 continue; 1134 1135 ehci_qh *freeListHead = fFreeListHead; 1136 if (freeListHead == lastFreeListHead) 1137 continue; 1138 1139 // set the doorbell and wait for the host controller to notify us 1140 WriteOpReg(EHCI_USBCMD, ReadOpReg(EHCI_USBCMD) | EHCI_USBCMD_INTONAAD); 1141 if (acquire_sem(fAsyncAdvanceSem) < B_OK) 1142 continue; 1143 1144 ehci_qh *current = freeListHead; 1145 while (current != lastFreeListHead) { 1146 ehci_qh *next = (ehci_qh *)current->next_log; 1147 FreeQueueHead(current); 1148 current = next; 1149 } 1150 1151 lastFreeListHead = freeListHead; 1152 } 1153 } 1154 1155 1156 ehci_qh * 1157 EHCI::CreateQueueHead() 1158 { 1159 ehci_qh *result; 1160 void *physicalAddress; 1161 if (fStack->AllocateChunk((void **)&result, &physicalAddress, 1162 sizeof(ehci_qh)) < B_OK) { 1163 TRACE_ERROR(("usb_ehci: failed to allocate queue head\n")); 1164 return NULL; 1165 } 1166 1167 result->this_phy = (addr_t)physicalAddress; 1168 result->next_phy = EHCI_QH_TERMINATE; 1169 result->next_log = NULL; 1170 result->prev_log = NULL; 1171 1172 ehci_qtd *descriptor = CreateDescriptor(0, 0); 1173 if (!descriptor) { 1174 TRACE_ERROR(("usb_ehci: failed to allocate initial qtd for queue head\n")); 1175 fStack->FreeChunk(result, (void *)result->this_phy, sizeof(ehci_qh)); 1176 return NULL; 1177 } 1178 1179 descriptor->token &= ~EHCI_QTD_STATUS_ACTIVE; 1180 result->stray_log = descriptor; 1181 result->element_log = descriptor; 1182 result->current_qtd_phy = EHCI_QTD_TERMINATE; 1183 result->overlay.next_phy = descriptor->this_phy; 1184 result->overlay.alt_next_phy = EHCI_QTD_TERMINATE; 1185 result->overlay.token = 0; 1186 for (int32 i = 0; i < 5; i++) { 1187 result->overlay.buffer_phy[i] = 0; 1188 result->overlay.ext_buffer_phy[i] = 0; 1189 } 1190 1191 return result; 1192 } 1193 1194 1195 status_t 1196 EHCI::InitQueueHead(ehci_qh *queueHead, Pipe *pipe) 1197 { 1198 switch (pipe->Speed()) { 1199 case USB_SPEED_LOWSPEED: 1200 queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_LOW; 1201 break; 1202 case USB_SPEED_FULLSPEED: 1203 queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_FULL; 1204 break; 1205 case USB_SPEED_HIGHSPEED: 1206 queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH; 1207 break; 1208 default: 1209 TRACE_ERROR(("usb_ehci: unknown pipe speed\n")); 1210 return B_ERROR; 1211 } 1212 1213 queueHead->endpoint_chars |= (3 << EHCI_QH_CHARS_RL_SHIFT) 1214 | (pipe->MaxPacketSize() << EHCI_QH_CHARS_MPL_SHIFT) 1215 | (pipe->EndpointAddress() << EHCI_QH_CHARS_EPT_SHIFT) 1216 | (pipe->DeviceAddress() << EHCI_QH_CHARS_DEV_SHIFT) 1217 | EHCI_QH_CHARS_TOGGLE; 1218 1219 queueHead->endpoint_caps = (1 << EHCI_QH_CAPS_MULT_SHIFT); 1220 if (pipe->Speed() != USB_SPEED_HIGHSPEED) { 1221 if (pipe->Type() & USB_OBJECT_CONTROL_PIPE) 1222 queueHead->endpoint_chars |= EHCI_QH_CHARS_CONTROL; 1223 1224 queueHead->endpoint_caps |= (pipe->HubPort() << EHCI_QH_CAPS_PORT_SHIFT) 1225 | (pipe->HubAddress() << EHCI_QH_CAPS_HUB_SHIFT); 1226 } 1227 1228 return B_OK; 1229 } 1230 1231 1232 void 1233 EHCI::FreeQueueHead(ehci_qh *queueHead) 1234 { 1235 if (!queueHead) 1236 return; 1237 1238 FreeDescriptorChain((ehci_qtd *)queueHead->element_log); 1239 FreeDescriptor((ehci_qtd *)queueHead->stray_log); 1240 fStack->FreeChunk(queueHead, (void *)queueHead->this_phy, sizeof(ehci_qh)); 1241 } 1242 1243 1244 status_t 1245 EHCI::LinkQueueHead(ehci_qh *queueHead) 1246 { 1247 if (!Lock()) 1248 return B_ERROR; 1249 1250 ehci_qh *prevHead = (ehci_qh *)fAsyncQueueHead->prev_log; 1251 queueHead->next_phy = fAsyncQueueHead->this_phy | EHCI_QH_TYPE_QH; 1252 queueHead->next_log = fAsyncQueueHead; 1253 queueHead->prev_log = prevHead; 1254 fAsyncQueueHead->prev_log = queueHead; 1255 prevHead->next_log = queueHead; 1256 prevHead->next_phy = queueHead->this_phy | EHCI_QH_TYPE_QH; 1257 1258 Unlock(); 1259 return B_OK; 1260 } 1261 1262 1263 status_t 1264 EHCI::LinkInterruptQueueHead(ehci_qh *queueHead, Pipe *pipe) 1265 { 1266 if (!Lock()) 1267 return B_ERROR; 1268 1269 uint8 interval = pipe->Interval(); 1270 if (pipe->Speed() == USB_SPEED_HIGHSPEED) { 1271 // Allow interrupts to be scheduled on each possible micro frame. 1272 queueHead->endpoint_caps |= (0xff << EHCI_QH_CAPS_ISM_SHIFT); 1273 } else { 1274 // As we do not yet support FSTNs to correctly reference low/full 1275 // speed interrupt transfers, we simply put them into the 1 interval 1276 // queue. This way we ensure that we reach them on every micro frame 1277 // and can do the corresponding start/complete split transactions. 1278 // ToDo: use FSTNs to correctly link non high speed interrupt transfers 1279 interval = 1; 1280 1281 // For now we also force start splits to be in micro frame 0 and 1282 // complete splits to be in micro frame 2, 3 and 4. 1283 queueHead->endpoint_caps |= (0x01 << EHCI_QH_CAPS_ISM_SHIFT); 1284 queueHead->endpoint_caps |= (0x1c << EHCI_QH_CAPS_SCM_SHIFT); 1285 } 1286 1287 // this should not happen 1288 if (interval < 1) 1289 interval = 1; 1290 1291 // this may happen as intervals can go up to 16; we limit the value to 1292 // 11 as you cannot support intervals above that with a frame list of 1293 // just 1024 entries... 1294 if (interval > 11) 1295 interval = 11; 1296 1297 ehci_qh *interruptQueue = &fInterruptEntries[interval - 1].queue_head; 1298 queueHead->next_phy = interruptQueue->next_phy; 1299 queueHead->next_log = interruptQueue->next_log; 1300 queueHead->prev_log = interruptQueue; 1301 if (interruptQueue->next_log) 1302 ((ehci_qh *)interruptQueue->next_log)->prev_log = queueHead; 1303 interruptQueue->next_log = queueHead; 1304 interruptQueue->next_phy = queueHead->this_phy | EHCI_QH_TYPE_QH; 1305 1306 Unlock(); 1307 return B_OK; 1308 } 1309 1310 1311 status_t 1312 EHCI::UnlinkQueueHead(ehci_qh *queueHead, ehci_qh **freeListHead) 1313 { 1314 if (!Lock()) 1315 return B_ERROR; 1316 1317 ehci_qh *prevHead = (ehci_qh *)queueHead->prev_log; 1318 ehci_qh *nextHead = (ehci_qh *)queueHead->next_log; 1319 if (prevHead) { 1320 prevHead->next_phy = queueHead->next_phy | EHCI_QH_TYPE_QH; 1321 prevHead->next_log = queueHead->next_log; 1322 } 1323 1324 if (nextHead) 1325 nextHead->prev_log = queueHead->prev_log; 1326 1327 queueHead->next_phy = fAsyncQueueHead->this_phy | EHCI_QH_TYPE_QH; 1328 queueHead->prev_log = NULL; 1329 1330 queueHead->next_log = *freeListHead; 1331 *freeListHead = queueHead; 1332 1333 Unlock(); 1334 return B_OK; 1335 } 1336 1337 1338 status_t 1339 EHCI::FillQueueWithRequest(Transfer *transfer, ehci_qh *queueHead, 1340 ehci_qtd **_dataDescriptor, bool *_directionIn) 1341 { 1342 Pipe *pipe = transfer->TransferPipe(); 1343 usb_request_data *requestData = transfer->RequestData(); 1344 bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) > 0; 1345 1346 ehci_qtd *setupDescriptor = CreateDescriptor(sizeof(usb_request_data), 1347 EHCI_QTD_PID_SETUP); 1348 ehci_qtd *statusDescriptor = CreateDescriptor(0, 1349 directionIn ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN); 1350 1351 if (!setupDescriptor || !statusDescriptor) { 1352 TRACE_ERROR(("usb_ehci: failed to allocate descriptors\n")); 1353 FreeDescriptor(setupDescriptor); 1354 FreeDescriptor(statusDescriptor); 1355 return B_NO_MEMORY; 1356 } 1357 1358 iovec vector; 1359 vector.iov_base = requestData; 1360 vector.iov_len = sizeof(usb_request_data); 1361 WriteDescriptorChain(setupDescriptor, &vector, 1); 1362 1363 ehci_qtd *strayDescriptor = (ehci_qtd *)queueHead->stray_log; 1364 statusDescriptor->token |= EHCI_QTD_IOC | EHCI_QTD_DATA_TOGGLE; 1365 1366 ehci_qtd *dataDescriptor = NULL; 1367 if (transfer->VectorCount() > 0) { 1368 ehci_qtd *lastDescriptor = NULL; 1369 status_t result = CreateDescriptorChain(pipe, &dataDescriptor, 1370 &lastDescriptor, strayDescriptor, transfer->VectorLength(), 1371 directionIn ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT); 1372 1373 if (result < B_OK) { 1374 FreeDescriptor(setupDescriptor); 1375 FreeDescriptor(statusDescriptor); 1376 return result; 1377 } 1378 1379 if (!directionIn) { 1380 WriteDescriptorChain(dataDescriptor, transfer->Vector(), 1381 transfer->VectorCount()); 1382 } 1383 1384 LinkDescriptors(setupDescriptor, dataDescriptor, strayDescriptor); 1385 LinkDescriptors(lastDescriptor, statusDescriptor, strayDescriptor); 1386 } else { 1387 // no data: link setup and status descriptors directly 1388 LinkDescriptors(setupDescriptor, statusDescriptor, strayDescriptor); 1389 } 1390 1391 queueHead->element_log = setupDescriptor; 1392 queueHead->overlay.next_phy = setupDescriptor->this_phy; 1393 queueHead->overlay.alt_next_phy = EHCI_QTD_TERMINATE; 1394 1395 *_dataDescriptor = dataDescriptor; 1396 *_directionIn = directionIn; 1397 return B_OK; 1398 } 1399 1400 1401 status_t 1402 EHCI::FillQueueWithData(Transfer *transfer, ehci_qh *queueHead, 1403 ehci_qtd **_dataDescriptor, bool *_directionIn) 1404 { 1405 Pipe *pipe = transfer->TransferPipe(); 1406 bool directionIn = (pipe->Direction() == Pipe::In); 1407 1408 ehci_qtd *firstDescriptor = NULL; 1409 ehci_qtd *lastDescriptor = NULL; 1410 ehci_qtd *strayDescriptor = (ehci_qtd *)queueHead->stray_log; 1411 status_t result = CreateDescriptorChain(pipe, &firstDescriptor, 1412 &lastDescriptor, strayDescriptor, transfer->VectorLength(), 1413 directionIn ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT); 1414 1415 if (result < B_OK) 1416 return result; 1417 1418 lastDescriptor->token |= EHCI_QTD_IOC; 1419 if (!directionIn) { 1420 WriteDescriptorChain(firstDescriptor, transfer->Vector(), 1421 transfer->VectorCount()); 1422 } 1423 1424 queueHead->element_log = firstDescriptor; 1425 queueHead->overlay.next_phy = firstDescriptor->this_phy; 1426 queueHead->overlay.alt_next_phy = EHCI_QTD_TERMINATE; 1427 1428 *_dataDescriptor = firstDescriptor; 1429 if (_directionIn) 1430 *_directionIn = directionIn; 1431 return B_OK; 1432 } 1433 1434 1435 ehci_qtd * 1436 EHCI::CreateDescriptor(size_t bufferSize, uint8 pid) 1437 { 1438 ehci_qtd *result; 1439 void *physicalAddress; 1440 if (fStack->AllocateChunk((void **)&result, &physicalAddress, 1441 sizeof(ehci_qtd)) < B_OK) { 1442 TRACE_ERROR(("usb_ehci: failed to allocate a qtd\n")); 1443 return NULL; 1444 } 1445 1446 result->this_phy = (addr_t)physicalAddress; 1447 result->next_phy = EHCI_QTD_TERMINATE; 1448 result->next_log = NULL; 1449 result->alt_next_phy = EHCI_QTD_TERMINATE; 1450 result->alt_next_log = NULL; 1451 result->buffer_size = bufferSize; 1452 result->token = bufferSize << EHCI_QTD_BYTES_SHIFT; 1453 result->token |= 3 << EHCI_QTD_ERRCOUNT_SHIFT; 1454 result->token |= pid << EHCI_QTD_PID_SHIFT; 1455 result->token |= EHCI_QTD_STATUS_ACTIVE; 1456 if (bufferSize == 0) { 1457 result->buffer_log = NULL; 1458 for (int32 i = 0; i < 5; i++) { 1459 result->buffer_phy[i] = 0; 1460 result->ext_buffer_phy[i] = 0; 1461 } 1462 1463 return result; 1464 } 1465 1466 if (fStack->AllocateChunk(&result->buffer_log, &physicalAddress, 1467 bufferSize) < B_OK) { 1468 TRACE_ERROR(("usb_ehci: unable to allocate qtd buffer\n")); 1469 fStack->FreeChunk(result, (void *)result->this_phy, sizeof(ehci_qtd)); 1470 return NULL; 1471 } 1472 1473 addr_t physicalBase = (addr_t)physicalAddress; 1474 result->buffer_phy[0] = physicalBase; 1475 result->ext_buffer_phy[0] = 0; 1476 for (int32 i = 1; i < 5; i++) { 1477 physicalBase += B_PAGE_SIZE; 1478 result->buffer_phy[i] = physicalBase & EHCI_QTD_PAGE_MASK; 1479 result->ext_buffer_phy[i] = 0; 1480 } 1481 1482 return result; 1483 } 1484 1485 1486 status_t 1487 EHCI::CreateDescriptorChain(Pipe *pipe, ehci_qtd **_firstDescriptor, 1488 ehci_qtd **_lastDescriptor, ehci_qtd *strayDescriptor, size_t bufferSize, 1489 uint8 pid) 1490 { 1491 size_t packetSize = B_PAGE_SIZE * 4; 1492 int32 descriptorCount = (bufferSize + packetSize - 1) / packetSize; 1493 1494 bool dataToggle = pipe->DataToggle(); 1495 ehci_qtd *firstDescriptor = NULL; 1496 ehci_qtd *lastDescriptor = *_firstDescriptor; 1497 for (int32 i = 0; i < descriptorCount; i++) { 1498 ehci_qtd *descriptor = CreateDescriptor(min_c(packetSize, bufferSize), 1499 pid); 1500 1501 if (!descriptor) { 1502 FreeDescriptorChain(firstDescriptor); 1503 return B_NO_MEMORY; 1504 } 1505 1506 if (dataToggle) 1507 descriptor->token |= EHCI_QTD_DATA_TOGGLE; 1508 1509 if (lastDescriptor) 1510 LinkDescriptors(lastDescriptor, descriptor, strayDescriptor); 1511 1512 bufferSize -= packetSize; 1513 lastDescriptor = descriptor; 1514 if (!firstDescriptor) 1515 firstDescriptor = descriptor; 1516 } 1517 1518 *_firstDescriptor = firstDescriptor; 1519 *_lastDescriptor = lastDescriptor; 1520 return B_OK; 1521 } 1522 1523 1524 void 1525 EHCI::FreeDescriptor(ehci_qtd *descriptor) 1526 { 1527 if (!descriptor) 1528 return; 1529 1530 if (descriptor->buffer_log) { 1531 fStack->FreeChunk(descriptor->buffer_log, 1532 (void *)descriptor->buffer_phy[0], descriptor->buffer_size); 1533 } 1534 1535 fStack->FreeChunk(descriptor, (void *)descriptor->this_phy, sizeof(ehci_qtd)); 1536 } 1537 1538 1539 void 1540 EHCI::FreeDescriptorChain(ehci_qtd *topDescriptor) 1541 { 1542 ehci_qtd *current = topDescriptor; 1543 ehci_qtd *next = NULL; 1544 1545 while (current) { 1546 next = (ehci_qtd *)current->next_log; 1547 FreeDescriptor(current); 1548 current = next; 1549 } 1550 } 1551 1552 1553 void 1554 EHCI::LinkDescriptors(ehci_qtd *first, ehci_qtd *last, ehci_qtd *alt) 1555 { 1556 first->next_phy = last->this_phy; 1557 first->next_log = last; 1558 1559 if (alt) { 1560 first->alt_next_phy = alt->this_phy; 1561 first->alt_next_log = alt; 1562 } else { 1563 first->alt_next_phy = EHCI_QTD_TERMINATE; 1564 first->alt_next_log = NULL; 1565 } 1566 } 1567 1568 1569 size_t 1570 EHCI::WriteDescriptorChain(ehci_qtd *topDescriptor, iovec *vector, 1571 size_t vectorCount) 1572 { 1573 ehci_qtd *current = topDescriptor; 1574 size_t actualLength = 0; 1575 size_t vectorIndex = 0; 1576 size_t vectorOffset = 0; 1577 size_t bufferOffset = 0; 1578 1579 while (current) { 1580 if (!current->buffer_log) 1581 break; 1582 1583 while (true) { 1584 size_t length = min_c(current->buffer_size - bufferOffset, 1585 vector[vectorIndex].iov_len - vectorOffset); 1586 1587 memcpy((uint8 *)current->buffer_log + bufferOffset, 1588 (uint8 *)vector[vectorIndex].iov_base + vectorOffset, length); 1589 1590 actualLength += length; 1591 vectorOffset += length; 1592 bufferOffset += length; 1593 1594 if (vectorOffset >= vector[vectorIndex].iov_len) { 1595 if (++vectorIndex >= vectorCount) { 1596 TRACE(("usb_ehci: wrote descriptor chain (%ld bytes, no more vectors)\n", actualLength)); 1597 return actualLength; 1598 } 1599 1600 vectorOffset = 0; 1601 } 1602 1603 if (bufferOffset >= current->buffer_size) { 1604 bufferOffset = 0; 1605 break; 1606 } 1607 } 1608 1609 if (current->next_phy & EHCI_QTD_TERMINATE) 1610 break; 1611 1612 current = (ehci_qtd *)current->next_log; 1613 } 1614 1615 TRACE(("usb_ehci: wrote descriptor chain (%ld bytes)\n", actualLength)); 1616 return actualLength; 1617 } 1618 1619 1620 size_t 1621 EHCI::ReadDescriptorChain(ehci_qtd *topDescriptor, iovec *vector, 1622 size_t vectorCount, bool *nextDataToggle) 1623 { 1624 uint32 dataToggle = 0; 1625 ehci_qtd *current = topDescriptor; 1626 size_t actualLength = 0; 1627 size_t vectorIndex = 0; 1628 size_t vectorOffset = 0; 1629 size_t bufferOffset = 0; 1630 1631 while (current && (current->token & EHCI_QTD_STATUS_ACTIVE) == 0) { 1632 if (!current->buffer_log) 1633 break; 1634 1635 dataToggle = current->token & EHCI_QTD_DATA_TOGGLE; 1636 size_t bufferSize = current->buffer_size; 1637 bufferSize -= (current->token >> EHCI_QTD_BYTES_SHIFT) & EHCI_QTD_BYTES_MASK; 1638 1639 while (true) { 1640 size_t length = min_c(bufferSize - bufferOffset, 1641 vector[vectorIndex].iov_len - vectorOffset); 1642 1643 memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset, 1644 (uint8 *)current->buffer_log + bufferOffset, length); 1645 1646 actualLength += length; 1647 vectorOffset += length; 1648 bufferOffset += length; 1649 1650 if (vectorOffset >= vector[vectorIndex].iov_len) { 1651 if (++vectorIndex >= vectorCount) { 1652 TRACE(("usb_ehci: read descriptor chain (%ld bytes, no more vectors)\n", actualLength)); 1653 *nextDataToggle = dataToggle > 0 ? true : false; 1654 return actualLength; 1655 } 1656 1657 vectorOffset = 0; 1658 } 1659 1660 if (bufferOffset >= bufferSize) { 1661 bufferOffset = 0; 1662 break; 1663 } 1664 } 1665 1666 if (current->next_phy & EHCI_QTD_TERMINATE) 1667 break; 1668 1669 current = (ehci_qtd *)current->next_log; 1670 } 1671 1672 TRACE(("usb_ehci: read descriptor chain (%ld bytes)\n", actualLength)); 1673 *nextDataToggle = dataToggle > 0 ? true : false; 1674 return actualLength; 1675 } 1676 1677 1678 size_t 1679 EHCI::ReadActualLength(ehci_qtd *topDescriptor, bool *nextDataToggle) 1680 { 1681 size_t actualLength = 0; 1682 ehci_qtd *current = topDescriptor; 1683 uint32 dataToggle = 0; 1684 1685 while (current && (current->token & EHCI_QTD_STATUS_ACTIVE) == 0) { 1686 dataToggle = current->token & EHCI_QTD_DATA_TOGGLE; 1687 size_t length = current->buffer_size; 1688 length -= (current->token >> EHCI_QTD_BYTES_SHIFT) & EHCI_QTD_BYTES_MASK; 1689 actualLength += length; 1690 1691 if (current->next_phy & EHCI_QTD_TERMINATE) 1692 break; 1693 1694 current = (ehci_qtd *)current->next_log; 1695 } 1696 1697 TRACE(("usb_ehci: read actual length (%ld bytes)\n", actualLength)); 1698 *nextDataToggle = dataToggle > 0 ? true : false; 1699 return actualLength; 1700 } 1701 1702 1703 inline void 1704 EHCI::WriteOpReg(uint32 reg, uint32 value) 1705 { 1706 *(volatile uint32 *)(fOperationalRegisters + reg) = value; 1707 } 1708 1709 1710 inline uint32 1711 EHCI::ReadOpReg(uint32 reg) 1712 { 1713 return *(volatile uint32 *)(fOperationalRegisters + reg); 1714 } 1715 1716 1717 inline uint8 1718 EHCI::ReadCapReg8(uint32 reg) 1719 { 1720 return *(volatile uint8 *)(fCapabilityRegisters + reg); 1721 } 1722 1723 1724 inline uint16 1725 EHCI::ReadCapReg16(uint32 reg) 1726 { 1727 return *(volatile uint16 *)(fCapabilityRegisters + reg); 1728 } 1729 1730 1731 inline uint32 1732 EHCI::ReadCapReg32(uint32 reg) 1733 { 1734 return *(volatile uint32 *)(fCapabilityRegisters + reg); 1735 } 1736