1 /* 2 * Copyright 2004-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 * Niels S. Reedijk 8 * Salvatore Benedetto <salvatore.benedetto@gmail.com> 9 */ 10 11 #include <module.h> 12 #include <PCI.h> 13 #include <PCI_x86.h> 14 #include <USB3.h> 15 #include <KernelExport.h> 16 17 #include "uhci.h" 18 19 #define USB_MODULE_NAME "uhci" 20 21 pci_module_info *UHCI::sPCIModule = NULL; 22 pci_x86_module_info *UHCI::sPCIx86Module = NULL; 23 24 static int32 sDebuggerCommandAdded = 0; 25 26 27 #ifdef HAIKU_TARGET_PLATFORM_HAIKU 28 29 30 class DebugTransfer : public Transfer { 31 public: 32 DebugTransfer(Pipe *pipe) 33 : 34 Transfer(pipe) 35 { 36 } 37 38 uhci_td *firstDescriptor; 39 uhci_qh *transferQueue; 40 }; 41 42 43 /*! The function is an evil hack to allow <tt> <kdebug>usb_keyboard </tt> to 44 execute transfers. 45 When invoked the first time, a new transfer is started, each time the 46 function is called afterwards, it is checked whether the transfer is already 47 completed. If called with argv[1] == "cancel" the function cancels a 48 possibly pending transfer. 49 */ 50 static int 51 debug_process_transfer(int argc, char **argv) 52 { 53 Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0); 54 if (pipe == NULL) 55 return 2; 56 57 // check if we have a UHCI bus at all 58 if (pipe->GetBusManager()->TypeName()[0] != 'u') 59 return 3; 60 61 uint8 *data = (uint8 *)get_debug_variable("_usbTransferData", 0); 62 if (data == NULL) 63 return 4; 64 65 size_t length = (size_t)get_debug_variable("_usbTransferLength", 0); 66 if (length == 0) 67 return 5; 68 69 static uint8 transferBuffer[sizeof(DebugTransfer)] 70 __attribute__((aligned(16))); 71 static DebugTransfer* transfer; 72 73 UHCI *bus = (UHCI *)pipe->GetBusManager(); 74 75 if (argc > 1 && strcmp(argv[1], "cancel") == 0) { 76 if (transfer != NULL) { 77 bus->CancelDebugTransfer(transfer); 78 transfer = NULL; 79 } 80 return 0; 81 } 82 83 if (transfer != NULL) { 84 bool stillPending; 85 status_t error = bus->CheckDebugTransfer(transfer, stillPending); 86 if (!stillPending) 87 transfer = NULL; 88 89 return error == B_OK ? 0 : 6; 90 } 91 92 transfer = new(transferBuffer) DebugTransfer(pipe); 93 transfer->SetData(data, length); 94 95 if (bus->StartDebugTransfer(transfer) != B_OK) { 96 transfer = NULL; 97 return 7; 98 } 99 100 return 0; 101 } 102 #endif 103 104 105 static int32 106 uhci_std_ops(int32 op, ...) 107 { 108 switch (op) { 109 case B_MODULE_INIT: 110 TRACE_MODULE("init module\n"); 111 return B_OK; 112 case B_MODULE_UNINIT: 113 TRACE_MODULE("uninit module\n"); 114 break; 115 default: 116 return EINVAL; 117 } 118 119 return B_OK; 120 } 121 122 123 usb_host_controller_info uhci_module = { 124 { 125 "busses/usb/uhci", 126 0, 127 uhci_std_ops 128 }, 129 NULL, 130 UHCI::AddTo 131 }; 132 133 134 module_info *modules[] = { 135 (module_info *)&uhci_module, 136 NULL 137 }; 138 139 140 // 141 // #pragma mark - 142 // 143 144 145 #ifdef TRACE_USB 146 147 void 148 print_descriptor_chain(uhci_td *descriptor) 149 { 150 while (descriptor) { 151 dprintf("ph: 0x%08" B_PRIx32 "; lp: 0x%08" B_PRIx32 "; vf: %s; q: %s; " 152 "t: %s; st: 0x%08" B_PRIx32 "; to: 0x%08" B_PRIx32 "\n", 153 descriptor->this_phy & 0xffffffff, descriptor->link_phy & 0xfffffff0, 154 descriptor->link_phy & 0x4 ? "y" : "n", 155 descriptor->link_phy & 0x2 ? "qh" : "td", 156 descriptor->link_phy & 0x1 ? "y" : "n", 157 descriptor->status, descriptor->token); 158 159 if (descriptor->link_phy & TD_TERMINATE) 160 break; 161 162 descriptor = (uhci_td *)descriptor->link_log; 163 } 164 } 165 166 #endif // TRACE_USB 167 168 169 // 170 // #pragma mark - 171 // 172 173 174 Queue::Queue(Stack *stack) 175 { 176 fStack = stack; 177 178 mutex_init(&fLock, "uhci queue lock"); 179 180 phys_addr_t physicalAddress; 181 fStatus = fStack->AllocateChunk((void **)&fQueueHead, &physicalAddress, 182 sizeof(uhci_qh)); 183 if (fStatus < B_OK) 184 return; 185 186 fQueueHead->this_phy = (uint32)physicalAddress; 187 fQueueHead->element_phy = QH_TERMINATE; 188 189 fStrayDescriptor = NULL; 190 fQueueTop = NULL; 191 } 192 193 194 Queue::~Queue() 195 { 196 Lock(); 197 mutex_destroy(&fLock); 198 199 fStack->FreeChunk(fQueueHead, fQueueHead->this_phy, sizeof(uhci_qh)); 200 201 if (fStrayDescriptor) 202 fStack->FreeChunk(fStrayDescriptor, fStrayDescriptor->this_phy, 203 sizeof(uhci_td)); 204 } 205 206 207 status_t 208 Queue::InitCheck() 209 { 210 return fStatus; 211 } 212 213 214 bool 215 Queue::Lock() 216 { 217 return (mutex_lock(&fLock) == B_OK); 218 } 219 220 221 void 222 Queue::Unlock() 223 { 224 mutex_unlock(&fLock); 225 } 226 227 228 status_t 229 Queue::LinkTo(Queue *other) 230 { 231 if (!other) 232 return B_BAD_VALUE; 233 234 if (!Lock()) 235 return B_ERROR; 236 237 fQueueHead->link_phy = other->fQueueHead->this_phy | QH_NEXT_IS_QH; 238 fQueueHead->link_log = other->fQueueHead; 239 Unlock(); 240 241 return B_OK; 242 } 243 244 245 status_t 246 Queue::TerminateByStrayDescriptor() 247 { 248 // According to the *BSD USB sources, there needs to be a stray transfer 249 // descriptor in order to get some chipset to work nicely (like the PIIX). 250 phys_addr_t physicalAddress; 251 status_t result = fStack->AllocateChunk((void **)&fStrayDescriptor, 252 &physicalAddress, sizeof(uhci_td)); 253 if (result < B_OK) { 254 TRACE_ERROR("failed to allocate a stray transfer descriptor\n"); 255 return result; 256 } 257 258 fStrayDescriptor->status = 0; 259 fStrayDescriptor->this_phy = (uint32)physicalAddress; 260 fStrayDescriptor->link_phy = TD_TERMINATE; 261 fStrayDescriptor->link_log = NULL; 262 fStrayDescriptor->buffer_phy = 0; 263 fStrayDescriptor->buffer_log = NULL; 264 fStrayDescriptor->buffer_size = 0; 265 fStrayDescriptor->token = TD_TOKEN_NULL_DATA 266 | (0x7f << TD_TOKEN_DEVADDR_SHIFT) | TD_TOKEN_IN; 267 268 if (!Lock()) { 269 fStack->FreeChunk(fStrayDescriptor, fStrayDescriptor->this_phy, 270 sizeof(uhci_td)); 271 return B_ERROR; 272 } 273 274 fQueueHead->link_phy = fStrayDescriptor->this_phy; 275 fQueueHead->link_log = fStrayDescriptor; 276 Unlock(); 277 278 return B_OK; 279 } 280 281 282 status_t 283 Queue::AppendTransfer(uhci_qh *transfer, bool lock) 284 { 285 if (lock && !Lock()) 286 return B_ERROR; 287 288 transfer->link_log = NULL; 289 transfer->link_phy = fQueueHead->link_phy; 290 291 if (!fQueueTop) { 292 // the list is empty, make this the first element 293 fQueueTop = transfer; 294 fQueueHead->element_phy = transfer->this_phy | QH_NEXT_IS_QH; 295 } else { 296 // append the transfer queue to the list 297 uhci_qh *element = fQueueTop; 298 while (element && element->link_log) 299 element = (uhci_qh *)element->link_log; 300 301 element->link_log = transfer; 302 element->link_phy = transfer->this_phy | QH_NEXT_IS_QH; 303 } 304 305 if (lock) 306 Unlock(); 307 return B_OK; 308 } 309 310 311 status_t 312 Queue::RemoveTransfer(uhci_qh *transfer, bool lock) 313 { 314 if (lock && !Lock()) 315 return B_ERROR; 316 317 if (fQueueTop == transfer) { 318 // this was the top element 319 fQueueTop = (uhci_qh *)transfer->link_log; 320 if (!fQueueTop) { 321 // this was the only element, terminate this queue 322 fQueueHead->element_phy = QH_TERMINATE; 323 } else { 324 // there are elements left, adjust the element pointer 325 fQueueHead->element_phy = transfer->link_phy; 326 } 327 328 if (lock) 329 Unlock(); 330 return B_OK; 331 } else { 332 uhci_qh *element = fQueueTop; 333 while (element) { 334 if (element->link_log == transfer) { 335 element->link_log = transfer->link_log; 336 element->link_phy = transfer->link_phy; 337 if (lock) 338 Unlock(); 339 return B_OK; 340 } 341 342 element = (uhci_qh *)element->link_log; 343 } 344 } 345 346 if (lock) 347 Unlock(); 348 return B_BAD_VALUE; 349 } 350 351 352 uint32 353 Queue::PhysicalAddress() 354 { 355 return fQueueHead->this_phy; 356 } 357 358 359 void 360 Queue::PrintToStream() 361 { 362 #ifdef TRACE_USB 363 TRACE("queue:\n"); 364 dprintf("link phy: 0x%08" B_PRIx32 "; link type: %s; terminate: %s\n", 365 fQueueHead->link_phy & 0xfff0, 366 fQueueHead->link_phy & 0x0002 ? "QH" : "TD", 367 fQueueHead->link_phy & 0x0001 ? "yes" : "no"); 368 dprintf("elem phy: 0x%08" B_PRIx32 "; elem type: %s; terminate: %s\n", 369 fQueueHead->element_phy & 0xfff0, 370 fQueueHead->element_phy & 0x0002 ? "QH" : "TD", 371 fQueueHead->element_phy & 0x0001 ? "yes" : "no"); 372 #endif 373 } 374 375 376 // 377 // #pragma mark - 378 // 379 380 381 UHCI::UHCI(pci_info *info, Stack *stack) 382 : BusManager(stack), 383 fPCIInfo(info), 384 fStack(stack), 385 fEnabledInterrupts(0), 386 fFrameArea(-1), 387 fFrameList(NULL), 388 fFrameBandwidth(NULL), 389 fFirstIsochronousDescriptor(NULL), 390 fLastIsochronousDescriptor(NULL), 391 fQueueCount(0), 392 fQueues(NULL), 393 fFirstTransfer(NULL), 394 fLastTransfer(NULL), 395 fFinishTransfersSem(-1), 396 fFinishThread(-1), 397 fStopThreads(false), 398 fProcessingPipe(NULL), 399 fFreeList(NULL), 400 fCleanupThread(-1), 401 fCleanupSem(-1), 402 fCleanupCount(0), 403 fFirstIsochronousTransfer(NULL), 404 fLastIsochronousTransfer(NULL), 405 fFinishIsochronousTransfersSem(-1), 406 fFinishIsochronousThread(-1), 407 fRootHub(NULL), 408 fRootHubAddress(0), 409 fPortResetChange(0), 410 fIRQ(0), 411 fUseMSI(false) 412 { 413 // Create a lock for the isochronous transfer list 414 mutex_init(&fIsochronousLock, "UHCI isochronous lock"); 415 416 if (!fInitOK) { 417 TRACE_ERROR("bus manager failed to init\n"); 418 return; 419 } 420 421 TRACE("constructing new UHCI host controller driver\n"); 422 fInitOK = false; 423 424 fRegisterBase = sPCIModule->read_pci_config(fPCIInfo->bus, 425 fPCIInfo->device, fPCIInfo->function, PCI_memory_base, 4); 426 fRegisterBase &= PCI_address_io_mask; 427 TRACE("iospace offset: 0x%08" B_PRIx32 "\n", fRegisterBase); 428 429 if (fRegisterBase == 0) { 430 fRegisterBase = fPCIInfo->u.h0.base_registers[0]; 431 TRACE_ALWAYS("register base: 0x%08" B_PRIx32 "\n", fRegisterBase); 432 } 433 434 // enable pci address access 435 uint16 command = PCI_command_io | PCI_command_master | PCI_command_memory; 436 command |= sPCIModule->read_pci_config(fPCIInfo->bus, fPCIInfo->device, 437 fPCIInfo->function, PCI_command, 2); 438 439 sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, 440 fPCIInfo->function, PCI_command, 2, command); 441 442 // disable interrupts 443 WriteReg16(UHCI_USBINTR, 0); 444 445 // make sure we gain control of the UHCI controller instead of the BIOS 446 sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, 447 fPCIInfo->function, PCI_LEGSUP, 2, PCI_LEGSUP_USBPIRQDEN 448 | PCI_LEGSUP_CLEAR_SMI); 449 450 // do a global and host reset 451 GlobalReset(); 452 if (ControllerReset() < B_OK) { 453 TRACE_ERROR("host failed to reset\n"); 454 return; 455 } 456 457 // Setup the frame list 458 phys_addr_t physicalAddress; 459 fFrameArea = fStack->AllocateArea((void **)&fFrameList, &physicalAddress, 460 4096, "USB UHCI framelist"); 461 462 if (fFrameArea < B_OK) { 463 TRACE_ERROR("unable to create an area for the frame pointer list\n"); 464 return; 465 } 466 467 // Set base pointer and reset frame number 468 WriteReg32(UHCI_FRBASEADD, (uint32)physicalAddress); 469 WriteReg16(UHCI_FRNUM, 0); 470 471 // Set the max packet size for bandwidth reclamation to 64 bytes 472 WriteReg16(UHCI_USBCMD, ReadReg16(UHCI_USBCMD) | UHCI_USBCMD_MAXP); 473 474 // we will create four queues: 475 // 0: interrupt transfers 476 // 1: low speed control transfers 477 // 2: full speed control transfers 478 // 3: bulk transfers 479 // 4: debug queue 480 // TODO: 4: bandwidth reclamation queue 481 fQueueCount = 5; 482 fQueues = new(std::nothrow) Queue *[fQueueCount]; 483 if (!fQueues) { 484 delete_area(fFrameArea); 485 return; 486 } 487 488 for (int32 i = 0; i < fQueueCount; i++) { 489 fQueues[i] = new(std::nothrow) Queue(fStack); 490 if (!fQueues[i] || fQueues[i]->InitCheck() < B_OK) { 491 TRACE_ERROR("cannot create queues\n"); 492 delete_area(fFrameArea); 493 return; 494 } 495 496 if (i > 0) 497 fQueues[i - 1]->LinkTo(fQueues[i]); 498 } 499 500 // Make sure the last queue terminates 501 fQueues[fQueueCount - 1]->TerminateByStrayDescriptor(); 502 503 // Create the array that will keep bandwidth information 504 fFrameBandwidth = new(std::nothrow) uint16[NUMBER_OF_FRAMES]; 505 506 // Create lists for managing isochronous transfer descriptors 507 fFirstIsochronousDescriptor = new(std::nothrow) uhci_td *[NUMBER_OF_FRAMES]; 508 if (!fFirstIsochronousDescriptor) { 509 TRACE_ERROR("faild to allocate memory for first isochronous descriptor\n"); 510 return; 511 } 512 513 fLastIsochronousDescriptor = new(std::nothrow) uhci_td *[NUMBER_OF_FRAMES]; 514 if (!fLastIsochronousDescriptor) { 515 TRACE_ERROR("failed to allocate memory for last isochronous descriptor\n"); 516 delete [] fFirstIsochronousDescriptor; 517 return; 518 } 519 520 for (int32 i = 0; i < NUMBER_OF_FRAMES; i++) { 521 fFrameList[i] = fQueues[UHCI_INTERRUPT_QUEUE]->PhysicalAddress() 522 | FRAMELIST_NEXT_IS_QH; 523 fFrameBandwidth[i] = MAX_AVAILABLE_BANDWIDTH; 524 fFirstIsochronousDescriptor[i] = NULL; 525 fLastIsochronousDescriptor[i] = NULL; 526 } 527 528 // Create semaphore the finisher and cleanup threads will wait for 529 fFinishTransfersSem = create_sem(0, "UHCI Finish Transfers"); 530 if (fFinishTransfersSem < B_OK) { 531 TRACE_ERROR("failed to create finisher semaphore\n"); 532 return; 533 } 534 535 fCleanupSem = create_sem(0, "UHCI Cleanup"); 536 if (fCleanupSem < B_OK) { 537 TRACE_ERROR("failed to create cleanup semaphore\n"); 538 return; 539 } 540 541 // Create the finisher service and cleanup threads 542 fFinishThread = spawn_kernel_thread(FinishThread, 543 "uhci finish thread", B_URGENT_DISPLAY_PRIORITY, (void *)this); 544 resume_thread(fFinishThread); 545 546 fCleanupThread = spawn_kernel_thread(CleanupThread, 547 "uhci cleanup thread", B_NORMAL_PRIORITY, (void *)this); 548 resume_thread(fCleanupThread); 549 550 // Create semaphore the isochronous finisher thread will wait for 551 fFinishIsochronousTransfersSem = create_sem(0, 552 "UHCI Isochronous Finish Transfers"); 553 if (fFinishIsochronousTransfersSem < B_OK) { 554 TRACE_ERROR("failed to create isochronous finisher semaphore\n"); 555 return; 556 } 557 558 // Create the isochronous finisher service thread 559 fFinishIsochronousThread = spawn_kernel_thread(FinishIsochronousThread, 560 "uhci isochronous finish thread", B_URGENT_DISPLAY_PRIORITY, 561 (void *)this); 562 resume_thread(fFinishIsochronousThread); 563 564 // Find the right interrupt vector, using MSIs if available. 565 fIRQ = fPCIInfo->u.h0.interrupt_line; 566 if (sPCIx86Module != NULL && sPCIx86Module->get_msi_count(fPCIInfo->bus, 567 fPCIInfo->device, fPCIInfo->function) >= 1) { 568 uint8 msiVector = 0; 569 if (sPCIx86Module->configure_msi(fPCIInfo->bus, fPCIInfo->device, 570 fPCIInfo->function, 1, &msiVector) == B_OK 571 && sPCIx86Module->enable_msi(fPCIInfo->bus, fPCIInfo->device, 572 fPCIInfo->function) == B_OK) { 573 TRACE_ALWAYS("using message signaled interrupts\n"); 574 fIRQ = msiVector; 575 fUseMSI = true; 576 } 577 } 578 579 // Install the interrupt handler 580 TRACE("installing interrupt handler\n"); 581 install_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this, 0); 582 583 // Enable interrupts 584 fEnabledInterrupts = UHCI_USBSTS_USBINT | UHCI_USBSTS_ERRINT 585 | UHCI_USBSTS_HOSTERR | UHCI_USBSTS_HCPRERR | UHCI_USBSTS_HCHALT; 586 WriteReg16(UHCI_USBINTR, UHCI_USBINTR_CRC | UHCI_USBINTR_IOC 587 | UHCI_USBINTR_SHORT); 588 589 #ifdef HAIKU_TARGET_PLATFORM_HAIKU 590 if (atomic_add(&sDebuggerCommandAdded, 1) == 0) { 591 add_debugger_command("uhci_process_transfer", 592 &debug_process_transfer, 593 "Processes a USB transfer with the given variables"); 594 } 595 #endif 596 597 TRACE("UHCI host controller driver constructed\n"); 598 fInitOK = true; 599 } 600 601 602 UHCI::~UHCI() 603 { 604 #ifdef HAIKU_TARGET_PLATFORM_HAIKU 605 if (atomic_add(&sDebuggerCommandAdded, -1) == 1) { 606 remove_debugger_command("uhci_process_transfer", 607 &debug_process_transfer); 608 } 609 #endif 610 611 int32 result = 0; 612 fStopThreads = true; 613 delete_sem(fFinishTransfersSem); 614 delete_sem(fCleanupSem); 615 delete_sem(fFinishIsochronousTransfersSem); 616 wait_for_thread(fFinishThread, &result); 617 wait_for_thread(fCleanupThread, &result); 618 wait_for_thread(fFinishIsochronousThread, &result); 619 620 remove_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this); 621 622 LockIsochronous(); 623 isochronous_transfer_data *isoTransfer = fFirstIsochronousTransfer; 624 while (isoTransfer) { 625 isochronous_transfer_data *next = isoTransfer->link; 626 delete isoTransfer; 627 isoTransfer = next; 628 } 629 mutex_destroy(&fIsochronousLock); 630 631 Lock(); 632 transfer_data *transfer = fFirstTransfer; 633 while (transfer) { 634 transfer->transfer->Finished(B_CANCELED, 0); 635 delete transfer->transfer; 636 637 transfer_data *next = transfer->link; 638 delete transfer; 639 transfer = next; 640 } 641 642 for (int32 i = 0; i < fQueueCount; i++) 643 delete fQueues[i]; 644 645 delete [] fQueues; 646 delete [] fFrameBandwidth; 647 delete [] fFirstIsochronousDescriptor; 648 delete [] fLastIsochronousDescriptor; 649 delete fRootHub; 650 delete_area(fFrameArea); 651 652 if (fUseMSI && sPCIx86Module != NULL) { 653 sPCIx86Module->disable_msi(fPCIInfo->bus, 654 fPCIInfo->device, fPCIInfo->function); 655 sPCIx86Module->unconfigure_msi(fPCIInfo->bus, 656 fPCIInfo->device, fPCIInfo->function); 657 } 658 put_module(B_PCI_MODULE_NAME); 659 if (sPCIx86Module != NULL) { 660 sPCIx86Module = NULL; 661 put_module(B_PCI_X86_MODULE_NAME); 662 } 663 Unlock(); 664 } 665 666 667 status_t 668 UHCI::Start() 669 { 670 // Start the host controller, then start the Busmanager 671 TRACE("starting UHCI BusManager\n"); 672 TRACE("usbcmd reg 0x%04x, usbsts reg 0x%04x\n", 673 ReadReg16(UHCI_USBCMD), ReadReg16(UHCI_USBSTS)); 674 675 // Set the run bit in the command register 676 WriteReg16(UHCI_USBCMD, ReadReg16(UHCI_USBCMD) | UHCI_USBCMD_RS); 677 678 bool running = false; 679 for (int32 i = 0; i < 10; i++) { 680 uint16 status = ReadReg16(UHCI_USBSTS); 681 TRACE("current loop %" B_PRId32 ", status 0x%04x\n", i, status); 682 683 if (status & UHCI_USBSTS_HCHALT) 684 snooze(10000); 685 else { 686 running = true; 687 break; 688 } 689 } 690 691 if (!running) { 692 TRACE_ERROR("controller won't start running\n"); 693 return B_ERROR; 694 } 695 696 fRootHubAddress = AllocateAddress(); 697 fRootHub = new(std::nothrow) UHCIRootHub(RootObject(), fRootHubAddress); 698 if (!fRootHub) { 699 TRACE_ERROR("no memory to allocate root hub\n"); 700 return B_NO_MEMORY; 701 } 702 703 if (fRootHub->InitCheck() < B_OK) { 704 TRACE_ERROR("root hub failed init check\n"); 705 delete fRootHub; 706 return B_ERROR; 707 } 708 709 SetRootHub(fRootHub); 710 711 TRACE("controller is started. status: %u curframe: %u\n", 712 ReadReg16(UHCI_USBSTS), ReadReg16(UHCI_FRNUM)); 713 TRACE_ALWAYS("successfully started the controller\n"); 714 return BusManager::Start(); 715 } 716 717 718 status_t 719 UHCI::SubmitTransfer(Transfer *transfer) 720 { 721 // Short circuit the root hub 722 Pipe *pipe = transfer->TransferPipe(); 723 if (pipe->DeviceAddress() == fRootHubAddress) 724 return fRootHub->ProcessTransfer(this, transfer); 725 726 TRACE("submit transfer called for device %d\n", pipe->DeviceAddress()); 727 if (pipe->Type() & USB_OBJECT_CONTROL_PIPE) 728 return SubmitRequest(transfer); 729 730 // Process isochronous transfers 731 if (pipe->Type() & USB_OBJECT_ISO_PIPE) 732 return SubmitIsochronous(transfer); 733 734 uhci_td *firstDescriptor = NULL; 735 uhci_qh *transferQueue = NULL; 736 status_t result = CreateFilledTransfer(transfer, &firstDescriptor, 737 &transferQueue); 738 if (result < B_OK) 739 return result; 740 741 Queue *queue = NULL; 742 if (pipe->Type() & USB_OBJECT_INTERRUPT_PIPE) 743 queue = fQueues[UHCI_INTERRUPT_QUEUE]; 744 else 745 queue = fQueues[UHCI_BULK_QUEUE]; 746 747 bool directionIn = (pipe->Direction() == Pipe::In); 748 result = AddPendingTransfer(transfer, queue, transferQueue, 749 firstDescriptor, firstDescriptor, directionIn); 750 if (result < B_OK) { 751 TRACE_ERROR("failed to add pending transfer\n"); 752 FreeDescriptorChain(firstDescriptor); 753 FreeTransferQueue(transferQueue); 754 return result; 755 } 756 757 queue->AppendTransfer(transferQueue); 758 return B_OK; 759 } 760 761 762 status_t 763 UHCI::StartDebugTransfer(DebugTransfer *transfer) 764 { 765 transfer->firstDescriptor = NULL; 766 transfer->transferQueue = NULL; 767 status_t result = CreateFilledTransfer(transfer, &transfer->firstDescriptor, 768 &transfer->transferQueue); 769 if (result < B_OK) 770 return result; 771 772 fQueues[UHCI_DEBUG_QUEUE]->AppendTransfer(transfer->transferQueue, false); 773 774 return B_OK; 775 } 776 777 778 status_t 779 UHCI::CheckDebugTransfer(DebugTransfer *transfer, bool &_stillPending) 780 { 781 bool transferOK = false; 782 bool transferError = false; 783 uhci_td *descriptor = transfer->firstDescriptor; 784 785 while (descriptor) { 786 uint32 status = descriptor->status; 787 if (status & TD_STATUS_ACTIVE) 788 break; 789 790 if (status & TD_ERROR_MASK) { 791 transferError = true; 792 break; 793 } 794 795 if ((descriptor->link_phy & TD_TERMINATE) 796 || uhci_td_actual_length(descriptor) 797 < uhci_td_maximum_length(descriptor)) { 798 transferOK = true; 799 break; 800 } 801 802 descriptor = (uhci_td *)descriptor->link_log; 803 } 804 805 if (!transferOK && !transferError) { 806 spin(200); 807 _stillPending = true; 808 return B_OK; 809 } 810 811 if (transferOK) { 812 uint8 lastDataToggle = 0; 813 if (transfer->TransferPipe()->Direction() == Pipe::In) { 814 // data to read out 815 iovec *vector = transfer->Vector(); 816 size_t vectorCount = transfer->VectorCount(); 817 818 ReadDescriptorChain(transfer->firstDescriptor, 819 vector, vectorCount, &lastDataToggle); 820 } else { 821 // read the actual length that was sent 822 ReadActualLength(transfer->firstDescriptor, &lastDataToggle); 823 } 824 825 transfer->TransferPipe()->SetDataToggle(lastDataToggle == 0); 826 } 827 828 fQueues[UHCI_DEBUG_QUEUE]->RemoveTransfer(transfer->transferQueue, false); 829 FreeDescriptorChain(transfer->firstDescriptor); 830 FreeTransferQueue(transfer->transferQueue); 831 _stillPending = false; 832 return transferOK ? B_OK : B_IO_ERROR; 833 } 834 835 836 void 837 UHCI::CancelDebugTransfer(DebugTransfer *transfer) 838 { 839 // clear the active bit so the descriptors are canceled 840 uhci_td *descriptor = transfer->firstDescriptor; 841 while (descriptor) { 842 descriptor->status &= ~TD_STATUS_ACTIVE; 843 descriptor = (uhci_td *)descriptor->link_log; 844 } 845 846 transfer->Finished(B_CANCELED, 0); 847 848 // dequeue and free resources 849 fQueues[UHCI_DEBUG_QUEUE]->RemoveTransfer(transfer->transferQueue, false); 850 FreeDescriptorChain(transfer->firstDescriptor); 851 FreeTransferQueue(transfer->transferQueue); 852 // TODO: [bonefish] The Free*() calls cause "PMA: provided address resulted 853 // in invalid index" to be printed, so apparently something is not right. 854 // Though I have not clue what. This is the same cleanup code as in 855 // CheckDebugTransfer() that should undo the CreateFilledTransfer() from 856 // StartDebugTransfer(). 857 } 858 859 860 status_t 861 UHCI::CancelQueuedTransfers(Pipe *pipe, bool force) 862 { 863 if (pipe->Type() & USB_OBJECT_ISO_PIPE) 864 return CancelQueuedIsochronousTransfers(pipe, force); 865 866 if (!Lock()) 867 return B_ERROR; 868 869 struct transfer_entry { 870 Transfer * transfer; 871 transfer_entry * next; 872 }; 873 874 transfer_entry *list = NULL; 875 transfer_data *current = fFirstTransfer; 876 while (current) { 877 if (current->transfer && current->transfer->TransferPipe() == pipe) { 878 // clear the active bit so the descriptors are canceled 879 uhci_td *descriptor = current->first_descriptor; 880 while (descriptor) { 881 descriptor->status &= ~TD_STATUS_ACTIVE; 882 descriptor = (uhci_td *)descriptor->link_log; 883 } 884 885 if (!force) { 886 // if the transfer is canceled by force, the one causing the 887 // cancel is probably not the one who initiated the transfer 888 // and the callback is likely not safe anymore 889 transfer_entry *entry 890 = (transfer_entry *)malloc(sizeof(transfer_entry)); 891 if (entry != NULL) { 892 entry->transfer = current->transfer; 893 current->transfer = NULL; 894 entry->next = list; 895 list = entry; 896 } 897 } 898 899 current->canceled = true; 900 } 901 current = current->link; 902 } 903 904 Unlock(); 905 906 while (list != NULL) { 907 transfer_entry *next = list->next; 908 list->transfer->Finished(B_CANCELED, 0); 909 delete list->transfer; 910 free(list); 911 list = next; 912 } 913 914 // wait for any transfers that might have made it before canceling 915 while (fProcessingPipe == pipe) 916 snooze(1000); 917 918 // notify the finisher so it can clean up the canceled transfers 919 release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE); 920 return B_OK; 921 } 922 923 924 status_t 925 UHCI::CancelQueuedIsochronousTransfers(Pipe *pipe, bool force) 926 { 927 isochronous_transfer_data *current = fFirstIsochronousTransfer; 928 929 while (current) { 930 if (current->transfer->TransferPipe() == pipe) { 931 int32 packetCount 932 = current->transfer->IsochronousData()->packet_count; 933 // Set the active bit off on every descriptor in order to prevent 934 // the controller from processing them. Then set off the is_active 935 // field of the transfer in order to make the finisher thread skip 936 // the transfer. The FinishIsochronousThread will do the rest. 937 for (int32 i = 0; i < packetCount; i++) 938 current->descriptors[i]->status &= ~TD_STATUS_ACTIVE; 939 940 // TODO: Use the force paramater in order to avoid calling 941 // invalid callbacks 942 current->is_active = false; 943 } 944 945 current = current->link; 946 } 947 948 TRACE_ERROR("no isochronous transfer found!\n"); 949 return B_ERROR; 950 } 951 952 953 status_t 954 UHCI::SubmitRequest(Transfer *transfer) 955 { 956 Pipe *pipe = transfer->TransferPipe(); 957 usb_request_data *requestData = transfer->RequestData(); 958 bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) > 0; 959 960 uhci_td *setupDescriptor = CreateDescriptor(pipe, TD_TOKEN_SETUP, 961 sizeof(usb_request_data)); 962 963 uhci_td *statusDescriptor = CreateDescriptor(pipe, 964 directionIn ? TD_TOKEN_OUT : TD_TOKEN_IN, 0); 965 966 if (!setupDescriptor || !statusDescriptor) { 967 TRACE_ERROR("failed to allocate descriptors\n"); 968 FreeDescriptor(setupDescriptor); 969 FreeDescriptor(statusDescriptor); 970 return B_NO_MEMORY; 971 } 972 973 iovec vector; 974 vector.iov_base = requestData; 975 vector.iov_len = sizeof(usb_request_data); 976 WriteDescriptorChain(setupDescriptor, &vector, 1); 977 978 statusDescriptor->status |= TD_CONTROL_IOC; 979 statusDescriptor->token |= TD_TOKEN_DATA1; 980 statusDescriptor->link_phy = TD_TERMINATE; 981 statusDescriptor->link_log = NULL; 982 983 uhci_td *dataDescriptor = NULL; 984 if (transfer->VectorCount() > 0) { 985 uhci_td *lastDescriptor = NULL; 986 status_t result = CreateDescriptorChain(pipe, &dataDescriptor, 987 &lastDescriptor, directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT, 988 transfer->VectorLength()); 989 990 if (result < B_OK) { 991 FreeDescriptor(setupDescriptor); 992 FreeDescriptor(statusDescriptor); 993 return result; 994 } 995 996 if (!directionIn) { 997 WriteDescriptorChain(dataDescriptor, transfer->Vector(), 998 transfer->VectorCount()); 999 } 1000 1001 LinkDescriptors(setupDescriptor, dataDescriptor); 1002 LinkDescriptors(lastDescriptor, statusDescriptor); 1003 } else { 1004 // Link transfer and status descriptors directly 1005 LinkDescriptors(setupDescriptor, statusDescriptor); 1006 } 1007 1008 Queue *queue = NULL; 1009 if (pipe->Speed() == USB_SPEED_LOWSPEED) 1010 queue = fQueues[UHCI_LOW_SPEED_CONTROL_QUEUE]; 1011 else 1012 queue = fQueues[UHCI_FULL_SPEED_CONTROL_QUEUE]; 1013 1014 uhci_qh *transferQueue = CreateTransferQueue(setupDescriptor); 1015 status_t result = AddPendingTransfer(transfer, queue, transferQueue, 1016 setupDescriptor, dataDescriptor, directionIn); 1017 if (result < B_OK) { 1018 TRACE_ERROR("failed to add pending transfer\n"); 1019 FreeDescriptorChain(setupDescriptor); 1020 FreeTransferQueue(transferQueue); 1021 return result; 1022 } 1023 1024 queue->AppendTransfer(transferQueue); 1025 return B_OK; 1026 } 1027 1028 1029 status_t 1030 UHCI::AddPendingTransfer(Transfer *transfer, Queue *queue, 1031 uhci_qh *transferQueue, uhci_td *firstDescriptor, uhci_td *dataDescriptor, 1032 bool directionIn) 1033 { 1034 if (!transfer || !queue || !transferQueue || !firstDescriptor) 1035 return B_BAD_VALUE; 1036 1037 transfer_data *data = new(std::nothrow) transfer_data; 1038 if (!data) 1039 return B_NO_MEMORY; 1040 1041 status_t result = transfer->InitKernelAccess(); 1042 if (result < B_OK) { 1043 delete data; 1044 return result; 1045 } 1046 1047 data->transfer = transfer; 1048 data->queue = queue; 1049 data->transfer_queue = transferQueue; 1050 data->first_descriptor = firstDescriptor; 1051 data->data_descriptor = dataDescriptor; 1052 data->incoming = directionIn; 1053 data->canceled = false; 1054 data->link = NULL; 1055 1056 if (!Lock()) { 1057 delete data; 1058 return B_ERROR; 1059 } 1060 1061 if (fLastTransfer) 1062 fLastTransfer->link = data; 1063 if (!fFirstTransfer) 1064 fFirstTransfer = data; 1065 1066 fLastTransfer = data; 1067 Unlock(); 1068 return B_OK; 1069 } 1070 1071 1072 status_t 1073 UHCI::AddPendingIsochronousTransfer(Transfer *transfer, uhci_td **isoRequest, 1074 bool directionIn) 1075 { 1076 if (!transfer || !isoRequest) 1077 return B_BAD_VALUE; 1078 1079 isochronous_transfer_data *data 1080 = new(std::nothrow) isochronous_transfer_data; 1081 if (!data) 1082 return B_NO_MEMORY; 1083 1084 status_t result = transfer->InitKernelAccess(); 1085 if (result < B_OK) { 1086 delete data; 1087 return result; 1088 } 1089 1090 data->transfer = transfer; 1091 data->descriptors = isoRequest; 1092 data->last_to_process = transfer->IsochronousData()->packet_count - 1; 1093 data->incoming = directionIn; 1094 data->is_active = true; 1095 data->link = NULL; 1096 1097 // Put in the isochronous transfer list 1098 if (!LockIsochronous()) { 1099 delete data; 1100 return B_ERROR; 1101 } 1102 1103 if (fLastIsochronousTransfer) 1104 fLastIsochronousTransfer->link = data; 1105 if (!fFirstIsochronousTransfer) 1106 fFirstIsochronousTransfer = data; 1107 1108 fLastIsochronousTransfer = data; 1109 UnlockIsochronous(); 1110 return B_OK; 1111 } 1112 1113 1114 status_t 1115 UHCI::SubmitIsochronous(Transfer *transfer) 1116 { 1117 Pipe *pipe = transfer->TransferPipe(); 1118 bool directionIn = (pipe->Direction() == Pipe::In); 1119 usb_isochronous_data *isochronousData = transfer->IsochronousData(); 1120 size_t packetSize = transfer->DataLength(); 1121 size_t restSize = packetSize % isochronousData->packet_count; 1122 packetSize /= isochronousData->packet_count; 1123 uint16 currentFrame; 1124 1125 if (packetSize > pipe->MaxPacketSize()) { 1126 TRACE_ERROR("isochronous packetSize is bigger than pipe MaxPacketSize\n"); 1127 return B_BAD_VALUE; 1128 } 1129 1130 // Ignore the fact that the last descriptor might need less bandwidth. 1131 // The overhead is not worthy. 1132 uint16 bandwidth = transfer->Bandwidth() / isochronousData->packet_count; 1133 1134 TRACE("isochronous transfer descriptor bandwidth %d\n", bandwidth); 1135 1136 // The following holds the list of transfer descriptor of the 1137 // isochronous request. It is used to quickly remove all the isochronous 1138 // descriptors from the frame list, as descriptors are not link to each 1139 // other in a queue like for every other transfer. 1140 uhci_td **isoRequest 1141 = new(std::nothrow) uhci_td *[isochronousData->packet_count]; 1142 if (isoRequest == NULL) { 1143 TRACE("failed to create isoRequest array!\n"); 1144 return B_NO_MEMORY; 1145 } 1146 1147 // Create the list of transfer descriptors 1148 for (uint32 i = 0; i < (isochronousData->packet_count - 1); i++) { 1149 isoRequest[i] = CreateDescriptor(pipe, 1150 directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT, packetSize); 1151 // If we ran out of memory, clean up and return 1152 if (isoRequest[i] == NULL) { 1153 for (uint32 j = 0; j < i; j++) 1154 FreeDescriptor(isoRequest[j]); 1155 delete [] isoRequest; 1156 return B_NO_MEMORY; 1157 } 1158 // Make sure data toggle is set to zero 1159 isoRequest[i]->token &= ~TD_TOKEN_DATA1; 1160 } 1161 1162 // Create the last transfer descriptor which should be of smaller size 1163 // and set the IOC bit 1164 isoRequest[isochronousData->packet_count - 1] = CreateDescriptor(pipe, 1165 directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT, 1166 (restSize) ? restSize : packetSize); 1167 // If we are that unlucky... 1168 if (!isoRequest[isochronousData->packet_count - 1]) { 1169 for (uint32 i = 0; i < (isochronousData->packet_count - 2); i++) 1170 FreeDescriptor(isoRequest[i]); 1171 delete [] isoRequest; 1172 return B_NO_MEMORY; 1173 } 1174 isoRequest[isochronousData->packet_count - 1]->token &= ~TD_TOKEN_DATA1; 1175 1176 // If direction is out set every descriptor data 1177 if (!directionIn) { 1178 iovec *vector = transfer->Vector(); 1179 WriteIsochronousDescriptorChain(isoRequest, 1180 isochronousData->packet_count, vector); 1181 } else { 1182 // Initialize the packet descriptors 1183 for (uint32 i = 0; i < isochronousData->packet_count; i++) { 1184 isochronousData->packet_descriptors[i].actual_length = 0; 1185 isochronousData->packet_descriptors[i].status = B_NO_INIT; 1186 } 1187 } 1188 1189 TRACE("isochronous submitted size=%ld bytes, TDs=%" B_PRId32 ", " 1190 "packetSize=%ld, restSize=%ld\n", transfer->DataLength(), 1191 isochronousData->packet_count, packetSize, restSize); 1192 1193 // Find the entry where to start inserting the first Isochronous descriptor 1194 if (isochronousData->flags & USB_ISO_ASAP || 1195 isochronousData->starting_frame_number == NULL) { 1196 // find the first available frame with enough bandwidth. 1197 // This should always be the case, as defining the starting frame 1198 // number in the driver makes no sense for many reason, one of which 1199 // is that frame numbers value are host controller specific, and the 1200 // driver does not know which host controller is running. 1201 currentFrame = ReadReg16(UHCI_FRNUM); 1202 1203 // Make sure that: 1204 // 1. We are at least 5ms ahead the controller 1205 // 2. We stay in the range 0-1023 1206 // 3. There is enough bandwidth in the first entry 1207 currentFrame = (currentFrame + 5) % NUMBER_OF_FRAMES; 1208 } else { 1209 // Find out if the frame number specified has enough bandwidth, 1210 // otherwise find the first next available frame with enough bandwidth 1211 currentFrame = *isochronousData->starting_frame_number; 1212 } 1213 1214 // Find the first entry with enough bandwidth 1215 // TODO: should we also check the bandwidth of the following packet_count frames? 1216 uint16 startSeekingFromFrame = currentFrame; 1217 while (fFrameBandwidth[currentFrame] < bandwidth) { 1218 currentFrame = (currentFrame + 1) % NUMBER_OF_FRAMES; 1219 if (currentFrame == startSeekingFromFrame) { 1220 TRACE_ERROR("not enough bandwidth to queue the isochronous request"); 1221 for (uint32 i = 0; i < isochronousData->packet_count; i++) 1222 FreeDescriptor(isoRequest[i]); 1223 delete [] isoRequest; 1224 return B_ERROR; 1225 } 1226 } 1227 1228 if (isochronousData->starting_frame_number) 1229 *isochronousData->starting_frame_number = currentFrame; 1230 1231 // Add transfer to the list 1232 status_t result = AddPendingIsochronousTransfer(transfer, isoRequest, 1233 directionIn); 1234 if (result < B_OK) { 1235 TRACE_ERROR("failed to add pending isochronous transfer\n"); 1236 for (uint32 i = 0; i < isochronousData->packet_count; i++) 1237 FreeDescriptor(isoRequest[i]); 1238 delete [] isoRequest; 1239 return result; 1240 } 1241 1242 TRACE("appended isochronous transfer by starting at frame number %d\n", 1243 currentFrame); 1244 1245 // Insert the Transfer Descriptor by starting at 1246 // the starting_frame_number entry 1247 // TODO: We don't consider bInterval, and assume it's 1! 1248 for (uint32 i = 0; i < isochronousData->packet_count; i++) { 1249 result = LinkIsochronousDescriptor(isoRequest[i], currentFrame); 1250 if (result < B_OK) { 1251 TRACE_ERROR("failed to add pending isochronous transfer\n"); 1252 for (uint32 i = 0; i < isochronousData->packet_count; i++) 1253 FreeDescriptor(isoRequest[i]); 1254 delete [] isoRequest; 1255 return result; 1256 } 1257 1258 fFrameBandwidth[currentFrame] -= bandwidth; 1259 currentFrame = (currentFrame + 1) % NUMBER_OF_FRAMES; 1260 } 1261 1262 // Wake up the isochronous finisher thread 1263 release_sem_etc(fFinishIsochronousTransfersSem, 1, B_DO_NOT_RESCHEDULE); 1264 1265 return B_OK; 1266 } 1267 1268 1269 isochronous_transfer_data * 1270 UHCI::FindIsochronousTransfer(uhci_td *descriptor) 1271 { 1272 // Simply check every last descriptor of the isochronous transfer list 1273 if (LockIsochronous()) { 1274 isochronous_transfer_data *transfer = fFirstIsochronousTransfer; 1275 if (transfer) { 1276 while (transfer->descriptors[transfer->last_to_process] 1277 != descriptor) { 1278 transfer = transfer->link; 1279 if (!transfer) 1280 break; 1281 } 1282 } 1283 UnlockIsochronous(); 1284 return transfer; 1285 } 1286 return NULL; 1287 } 1288 1289 1290 status_t 1291 UHCI::LinkIsochronousDescriptor(uhci_td *descriptor, uint16 frame) 1292 { 1293 // The transfer descriptor is appended to the last 1294 // existing isochronous transfer descriptor (if any) 1295 // in that frame. 1296 if (LockIsochronous()) { 1297 if (!fFirstIsochronousDescriptor[frame]) { 1298 // Insert the transfer descriptor in the first position 1299 fFrameList[frame] = descriptor->this_phy & ~FRAMELIST_NEXT_IS_QH; 1300 fFirstIsochronousDescriptor[frame] = descriptor; 1301 fLastIsochronousDescriptor[frame] = descriptor; 1302 } else { 1303 // Append to the last transfer descriptor 1304 fLastIsochronousDescriptor[frame]->link_log = descriptor; 1305 fLastIsochronousDescriptor[frame]->link_phy 1306 = descriptor->this_phy & ~TD_NEXT_IS_QH; 1307 fLastIsochronousDescriptor[frame] = descriptor; 1308 } 1309 1310 descriptor->link_phy 1311 = fQueues[UHCI_INTERRUPT_QUEUE]->PhysicalAddress() | TD_NEXT_IS_QH; 1312 UnlockIsochronous(); 1313 return B_OK; 1314 } 1315 return B_ERROR; 1316 } 1317 1318 1319 uhci_td * 1320 UHCI::UnlinkIsochronousDescriptor(uint16 frame) 1321 { 1322 // We always unlink from the top 1323 if (LockIsochronous()) { 1324 uhci_td *descriptor = fFirstIsochronousDescriptor[frame]; 1325 if (descriptor) { 1326 // The descriptor will be freed later. 1327 fFrameList[frame] = descriptor->link_phy; 1328 if (descriptor->link_log) { 1329 fFirstIsochronousDescriptor[frame] 1330 = (uhci_td *)descriptor->link_log; 1331 } else { 1332 fFirstIsochronousDescriptor[frame] = NULL; 1333 fLastIsochronousDescriptor[frame] = NULL; 1334 } 1335 } 1336 UnlockIsochronous(); 1337 return descriptor; 1338 } 1339 return NULL; 1340 } 1341 1342 1343 int32 1344 UHCI::FinishThread(void *data) 1345 { 1346 ((UHCI *)data)->FinishTransfers(); 1347 return B_OK; 1348 } 1349 1350 1351 void 1352 UHCI::FinishTransfers() 1353 { 1354 while (!fStopThreads) { 1355 if (acquire_sem(fFinishTransfersSem) < B_OK) 1356 continue; 1357 1358 // eat up sems that have been released by multiple interrupts 1359 int32 semCount = 0; 1360 get_sem_count(fFinishTransfersSem, &semCount); 1361 if (semCount > 0) 1362 acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0); 1363 1364 if (!Lock()) 1365 continue; 1366 1367 TRACE("finishing transfers (first transfer: 0x%08lx; last" 1368 " transfer: 0x%08lx)\n", (addr_t)fFirstTransfer, 1369 (addr_t)fLastTransfer); 1370 transfer_data *lastTransfer = NULL; 1371 transfer_data *transfer = fFirstTransfer; 1372 Unlock(); 1373 1374 while (transfer) { 1375 bool transferDone = false; 1376 uhci_td *descriptor = transfer->first_descriptor; 1377 status_t callbackStatus = B_OK; 1378 1379 while (descriptor) { 1380 uint32 status = descriptor->status; 1381 if (status & TD_STATUS_ACTIVE) { 1382 // still in progress 1383 TRACE("td (0x%08" B_PRIx32 ") still active\n", 1384 descriptor->this_phy); 1385 break; 1386 } 1387 1388 if (status & TD_ERROR_MASK) { 1389 // an error occured 1390 TRACE_ERROR("td (0x%08" B_PRIx32 ") error: status: 0x%08" 1391 B_PRIx32 "; token: 0x%08" B_PRIx32 ";\n", 1392 descriptor->this_phy, status, descriptor->token); 1393 1394 uint8 errorCount = status >> TD_ERROR_COUNT_SHIFT; 1395 errorCount &= TD_ERROR_COUNT_MASK; 1396 if (errorCount == 0) { 1397 // the error counter counted down to zero, report why 1398 int32 reasons = 0; 1399 if (status & TD_STATUS_ERROR_BUFFER) { 1400 callbackStatus = transfer->incoming ? B_DEV_DATA_OVERRUN : B_DEV_DATA_UNDERRUN; 1401 reasons++; 1402 } 1403 if (status & TD_STATUS_ERROR_TIMEOUT) { 1404 callbackStatus = transfer->incoming ? B_DEV_CRC_ERROR : B_TIMED_OUT; 1405 reasons++; 1406 } 1407 if (status & TD_STATUS_ERROR_NAK) { 1408 callbackStatus = B_DEV_UNEXPECTED_PID; 1409 reasons++; 1410 } 1411 if (status & TD_STATUS_ERROR_BITSTUFF) { 1412 callbackStatus = B_DEV_CRC_ERROR; 1413 reasons++; 1414 } 1415 1416 if (reasons > 1) 1417 callbackStatus = B_DEV_MULTIPLE_ERRORS; 1418 } else if (status & TD_STATUS_ERROR_BABBLE) { 1419 // there is a babble condition 1420 callbackStatus = transfer->incoming ? B_DEV_FIFO_OVERRUN : B_DEV_FIFO_UNDERRUN; 1421 } else { 1422 // if the error counter didn't count down to zero 1423 // and there was no babble, then this halt was caused 1424 // by a stall handshake 1425 callbackStatus = B_DEV_STALLED; 1426 } 1427 1428 transferDone = true; 1429 break; 1430 } 1431 1432 if ((descriptor->link_phy & TD_TERMINATE) 1433 || ((descriptor->status & TD_CONTROL_SPD) != 0 1434 && uhci_td_actual_length(descriptor) 1435 < uhci_td_maximum_length(descriptor))) { 1436 // all descriptors are done, or we have a short packet 1437 TRACE("td (0x%08" B_PRIx32 ") ok\n", descriptor->this_phy); 1438 callbackStatus = B_OK; 1439 transferDone = true; 1440 break; 1441 } 1442 1443 descriptor = (uhci_td *)descriptor->link_log; 1444 } 1445 1446 if (!transferDone) { 1447 lastTransfer = transfer; 1448 transfer = transfer->link; 1449 continue; 1450 } 1451 1452 // remove the transfer from the list first so we are sure 1453 // it doesn't get canceled while we still process it 1454 transfer_data *next = transfer->link; 1455 if (Lock()) { 1456 if (lastTransfer) 1457 lastTransfer->link = transfer->link; 1458 1459 if (transfer == fFirstTransfer) 1460 fFirstTransfer = transfer->link; 1461 if (transfer == fLastTransfer) 1462 fLastTransfer = lastTransfer; 1463 1464 // store the currently processing pipe here so we can wait 1465 // in cancel if we are processing something on the target pipe 1466 if (!transfer->canceled) 1467 fProcessingPipe = transfer->transfer->TransferPipe(); 1468 1469 transfer->link = NULL; 1470 Unlock(); 1471 } 1472 1473 // if canceled the callback has already been called 1474 if (!transfer->canceled) { 1475 size_t actualLength = 0; 1476 if (callbackStatus == B_OK) { 1477 uint8 lastDataToggle = 0; 1478 if (transfer->data_descriptor && transfer->incoming) { 1479 // data to read out 1480 iovec *vector = transfer->transfer->Vector(); 1481 size_t vectorCount = transfer->transfer->VectorCount(); 1482 1483 transfer->transfer->PrepareKernelAccess(); 1484 actualLength = ReadDescriptorChain( 1485 transfer->data_descriptor, 1486 vector, vectorCount, 1487 &lastDataToggle); 1488 } else if (transfer->data_descriptor) { 1489 // read the actual length that was sent 1490 actualLength = ReadActualLength( 1491 transfer->data_descriptor, &lastDataToggle); 1492 } 1493 1494 transfer->transfer->TransferPipe()->SetDataToggle(lastDataToggle == 0); 1495 1496 if (transfer->transfer->IsFragmented()) { 1497 // this transfer may still have data left 1498 TRACE("advancing fragmented transfer\n"); 1499 transfer->transfer->AdvanceByFragment(actualLength); 1500 if (transfer->transfer->VectorLength() > 0) { 1501 TRACE("still %ld bytes left on transfer\n", 1502 transfer->transfer->VectorLength()); 1503 1504 Transfer *resubmit = transfer->transfer; 1505 1506 // free the used descriptors 1507 transfer->queue->RemoveTransfer( 1508 transfer->transfer_queue); 1509 AddToFreeList(transfer); 1510 1511 // resubmit the advanced transfer so the rest 1512 // of the buffers are transmitted over the bus 1513 resubmit->PrepareKernelAccess(); 1514 if (SubmitTransfer(resubmit) != B_OK) 1515 resubmit->Finished(B_ERROR, 0); 1516 1517 transfer = next; 1518 continue; 1519 } 1520 1521 // the transfer is done, but we already set the 1522 // actualLength with AdvanceByFragment() 1523 actualLength = 0; 1524 } 1525 } 1526 1527 transfer->transfer->Finished(callbackStatus, actualLength); 1528 fProcessingPipe = NULL; 1529 } 1530 1531 // remove and free the hardware queue and its descriptors 1532 transfer->queue->RemoveTransfer(transfer->transfer_queue); 1533 delete transfer->transfer; 1534 AddToFreeList(transfer); 1535 transfer = next; 1536 } 1537 } 1538 } 1539 1540 1541 void 1542 UHCI::AddToFreeList(transfer_data *transfer) 1543 { 1544 transfer->free_after_frame = ReadReg16(UHCI_FRNUM); 1545 if (!Lock()) 1546 return; 1547 1548 transfer->link = fFreeList; 1549 fFreeList = transfer; 1550 Unlock(); 1551 1552 if (atomic_add(&fCleanupCount, 1) == 0) 1553 release_sem(fCleanupSem); 1554 } 1555 1556 1557 int32 1558 UHCI::CleanupThread(void *data) 1559 { 1560 ((UHCI *)data)->Cleanup(); 1561 return B_OK; 1562 } 1563 1564 1565 void 1566 UHCI::Cleanup() 1567 { 1568 while (!fStopThreads) { 1569 if (acquire_sem(fCleanupSem) != B_OK) 1570 continue; 1571 1572 bigtime_t nextTime = system_time() + 1000; 1573 while (atomic_get(&fCleanupCount) != 0) { 1574 // wait for the frame to pass 1575 snooze_until(nextTime, B_SYSTEM_TIMEBASE); 1576 nextTime += 1000; 1577 1578 if (!Lock()) 1579 continue; 1580 1581 // find the first entry we may free 1582 transfer_data **link = &fFreeList; 1583 transfer_data *transfer = fFreeList; 1584 uint16 frameNumber = ReadReg16(UHCI_FRNUM); 1585 while (transfer) { 1586 if (transfer->free_after_frame != frameNumber) { 1587 *link = NULL; 1588 break; 1589 } 1590 1591 link = &transfer->link; 1592 transfer = transfer->link; 1593 } 1594 1595 Unlock(); 1596 1597 // the transfers below this one are all freeable 1598 while (transfer) { 1599 transfer_data *next = transfer->link; 1600 FreeDescriptorChain(transfer->first_descriptor); 1601 FreeTransferQueue(transfer->transfer_queue); 1602 delete transfer; 1603 atomic_add(&fCleanupCount, -1); 1604 transfer = next; 1605 } 1606 } 1607 } 1608 } 1609 1610 1611 int32 1612 UHCI::FinishIsochronousThread(void *data) 1613 { 1614 ((UHCI *)data)->FinishIsochronousTransfers(); 1615 return B_OK; 1616 } 1617 1618 1619 void 1620 UHCI::FinishIsochronousTransfers() 1621 { 1622 /* This thread stays one position behind the controller and processes every 1623 * isochronous descriptor. Once it finds the last isochronous descriptor 1624 * of a transfer, it processes the entire transfer. 1625 */ 1626 1627 while (!fStopThreads) { 1628 // Go to sleep if there are not isochronous transfer to process 1629 if (acquire_sem(fFinishIsochronousTransfersSem) < B_OK) 1630 return; 1631 1632 bool transferDone = false; 1633 uint16 currentFrame = ReadReg16(UHCI_FRNUM); 1634 1635 // Process the frame list until one transfer is processed 1636 while (!transferDone) { 1637 // wait 1ms in order to be sure to be one position behind 1638 // the controller 1639 if (currentFrame == ReadReg16(UHCI_FRNUM)) 1640 snooze(1000); 1641 1642 // Process the frame till it has isochronous descriptors in it. 1643 while (!(fFrameList[currentFrame] & FRAMELIST_NEXT_IS_QH)) { 1644 uhci_td *current = UnlinkIsochronousDescriptor(currentFrame); 1645 1646 // Process the transfer if we found the last descriptor 1647 isochronous_transfer_data *transfer 1648 = FindIsochronousTransfer(current); 1649 // Process the descriptors only if it is still active and 1650 // belongs to an inbound transfer. If the transfer is not 1651 // active, it means the request has been removed, so simply 1652 // remove the descriptors. 1653 if (transfer && transfer->is_active) { 1654 if (current->token & TD_TOKEN_IN) { 1655 iovec *vector = transfer->transfer->Vector(); 1656 transfer->transfer->PrepareKernelAccess(); 1657 ReadIsochronousDescriptorChain(transfer, vector); 1658 } 1659 1660 // Remove the transfer 1661 if (LockIsochronous()) { 1662 if (transfer == fFirstIsochronousTransfer) { 1663 fFirstIsochronousTransfer = transfer->link; 1664 if (transfer == fLastIsochronousTransfer) 1665 fLastIsochronousTransfer = NULL; 1666 } else { 1667 isochronous_transfer_data *temp 1668 = fFirstIsochronousTransfer; 1669 while (transfer != temp->link) 1670 temp = temp->link; 1671 1672 if (transfer == fLastIsochronousTransfer) 1673 fLastIsochronousTransfer = temp; 1674 temp->link = temp->link->link; 1675 } 1676 UnlockIsochronous(); 1677 } 1678 1679 transfer->transfer->Finished(B_OK, 0); 1680 1681 uint32 packetCount = 1682 transfer->transfer->IsochronousData()->packet_count; 1683 for (uint32 i = 0; i < packetCount; i++) 1684 FreeDescriptor(transfer->descriptors[i]); 1685 1686 delete [] transfer->descriptors; 1687 delete transfer->transfer; 1688 delete transfer; 1689 transferDone = true; 1690 } 1691 } 1692 1693 // Make sure to reset the frame bandwidth 1694 fFrameBandwidth[currentFrame] = MAX_AVAILABLE_BANDWIDTH; 1695 currentFrame = (currentFrame + 1) % NUMBER_OF_FRAMES; 1696 } 1697 } 1698 } 1699 1700 1701 void 1702 UHCI::GlobalReset() 1703 { 1704 uint8 sofValue = ReadReg8(UHCI_SOFMOD); 1705 1706 WriteReg16(UHCI_USBCMD, UHCI_USBCMD_GRESET); 1707 snooze(100000); 1708 WriteReg16(UHCI_USBCMD, 0); 1709 snooze(10000); 1710 1711 WriteReg8(UHCI_SOFMOD, sofValue); 1712 } 1713 1714 1715 status_t 1716 UHCI::ControllerReset() 1717 { 1718 WriteReg16(UHCI_USBCMD, UHCI_USBCMD_HCRESET); 1719 1720 int32 tries = 5; 1721 while (ReadReg16(UHCI_USBCMD) & UHCI_USBCMD_HCRESET) { 1722 snooze(10000); 1723 if (tries-- < 0) 1724 return B_ERROR; 1725 } 1726 1727 return B_OK; 1728 } 1729 1730 1731 status_t 1732 UHCI::GetPortStatus(uint8 index, usb_port_status *status) 1733 { 1734 if (index > 1) 1735 return B_BAD_INDEX; 1736 1737 status->status = status->change = 0; 1738 uint16 portStatus = ReadReg16(UHCI_PORTSC1 + index * 2); 1739 1740 // build the status 1741 if (portStatus & UHCI_PORTSC_CURSTAT) 1742 status->status |= PORT_STATUS_CONNECTION; 1743 if (portStatus & UHCI_PORTSC_ENABLED) 1744 status->status |= PORT_STATUS_ENABLE; 1745 if (portStatus & UHCI_PORTSC_RESET) 1746 status->status |= PORT_STATUS_RESET; 1747 if (portStatus & UHCI_PORTSC_LOWSPEED) 1748 status->status |= PORT_STATUS_LOW_SPEED; 1749 1750 // build the change 1751 if (portStatus & UHCI_PORTSC_STATCHA) 1752 status->change |= PORT_STATUS_CONNECTION; 1753 if (portStatus & UHCI_PORTSC_ENABCHA) 1754 status->change |= PORT_STATUS_ENABLE; 1755 1756 // ToDo: work out suspended/resume 1757 1758 // there are no bits to indicate reset change 1759 if (fPortResetChange & (1 << index)) 1760 status->change |= PORT_STATUS_RESET; 1761 1762 // the port is automagically powered on 1763 status->status |= PORT_STATUS_POWER; 1764 return B_OK; 1765 } 1766 1767 1768 status_t 1769 UHCI::SetPortFeature(uint8 index, uint16 feature) 1770 { 1771 if (index > 1) 1772 return B_BAD_INDEX; 1773 1774 switch (feature) { 1775 case PORT_RESET: 1776 return ResetPort(index); 1777 1778 case PORT_POWER: 1779 // the ports are automatically powered 1780 return B_OK; 1781 } 1782 1783 return B_BAD_VALUE; 1784 } 1785 1786 1787 status_t 1788 UHCI::ClearPortFeature(uint8 index, uint16 feature) 1789 { 1790 if (index > 1) 1791 return B_BAD_INDEX; 1792 1793 uint32 portRegister = UHCI_PORTSC1 + index * 2; 1794 uint16 portStatus = ReadReg16(portRegister) & UHCI_PORTSC_DATAMASK; 1795 1796 switch (feature) { 1797 case C_PORT_RESET: 1798 fPortResetChange &= ~(1 << index); 1799 return B_OK; 1800 1801 case C_PORT_CONNECTION: 1802 WriteReg16(portRegister, portStatus | UHCI_PORTSC_STATCHA); 1803 return B_OK; 1804 1805 case C_PORT_ENABLE: 1806 WriteReg16(portRegister, portStatus | UHCI_PORTSC_ENABCHA); 1807 return B_OK; 1808 } 1809 1810 return B_BAD_VALUE; 1811 } 1812 1813 1814 status_t 1815 UHCI::ResetPort(uint8 index) 1816 { 1817 if (index > 1) 1818 return B_BAD_INDEX; 1819 1820 TRACE("reset port %d\n", index); 1821 1822 uint32 port = UHCI_PORTSC1 + index * 2; 1823 uint16 status = ReadReg16(port); 1824 status &= UHCI_PORTSC_DATAMASK; 1825 WriteReg16(port, status | UHCI_PORTSC_RESET); 1826 snooze(250000); 1827 1828 status = ReadReg16(port); 1829 status &= UHCI_PORTSC_DATAMASK; 1830 WriteReg16(port, status & ~UHCI_PORTSC_RESET); 1831 snooze(1000); 1832 1833 for (int32 i = 10; i > 0; i--) { 1834 // try to enable the port 1835 status = ReadReg16(port); 1836 status &= UHCI_PORTSC_DATAMASK; 1837 WriteReg16(port, status | UHCI_PORTSC_ENABLED); 1838 snooze(50000); 1839 1840 status = ReadReg16(port); 1841 1842 if ((status & UHCI_PORTSC_CURSTAT) == 0) { 1843 // no device connected. since we waited long enough we can assume 1844 // that the port was reset and no device is connected. 1845 break; 1846 } 1847 1848 if (status & (UHCI_PORTSC_STATCHA | UHCI_PORTSC_ENABCHA)) { 1849 // port enabled changed or connection status were set. 1850 // acknowledge either / both and wait again. 1851 status &= UHCI_PORTSC_DATAMASK; 1852 WriteReg16(port, status | UHCI_PORTSC_STATCHA | UHCI_PORTSC_ENABCHA); 1853 continue; 1854 } 1855 1856 if (status & UHCI_PORTSC_ENABLED) { 1857 // the port is enabled 1858 break; 1859 } 1860 } 1861 1862 fPortResetChange |= (1 << index); 1863 TRACE("port was reset: 0x%04x\n", ReadReg16(port)); 1864 return B_OK; 1865 } 1866 1867 1868 int32 1869 UHCI::InterruptHandler(void *data) 1870 { 1871 return ((UHCI *)data)->Interrupt(); 1872 } 1873 1874 1875 int32 1876 UHCI::Interrupt() 1877 { 1878 static spinlock lock = B_SPINLOCK_INITIALIZER; 1879 acquire_spinlock(&lock); 1880 1881 // Check if we really had an interrupt 1882 uint16 status = ReadReg16(UHCI_USBSTS); 1883 if ((status & fEnabledInterrupts) == 0) { 1884 if (status != 0) { 1885 TRACE("discarding not enabled interrupts 0x%08x\n", status); 1886 WriteReg16(UHCI_USBSTS, status); 1887 } 1888 1889 release_spinlock(&lock); 1890 return B_UNHANDLED_INTERRUPT; 1891 } 1892 1893 uint16 acknowledge = 0; 1894 bool finishTransfers = false; 1895 int32 result = B_HANDLED_INTERRUPT; 1896 1897 if (status & UHCI_USBSTS_USBINT) { 1898 TRACE_MODULE("transfer finished\n"); 1899 acknowledge |= UHCI_USBSTS_USBINT; 1900 result = B_INVOKE_SCHEDULER; 1901 finishTransfers = true; 1902 } 1903 1904 if (status & UHCI_USBSTS_ERRINT) { 1905 TRACE_MODULE("transfer error\n"); 1906 acknowledge |= UHCI_USBSTS_ERRINT; 1907 result = B_INVOKE_SCHEDULER; 1908 finishTransfers = true; 1909 } 1910 1911 if (status & UHCI_USBSTS_RESDET) { 1912 TRACE_MODULE("resume detected\n"); 1913 acknowledge |= UHCI_USBSTS_RESDET; 1914 } 1915 1916 if (status & UHCI_USBSTS_HOSTERR) { 1917 TRACE_MODULE_ERROR("host system error\n"); 1918 acknowledge |= UHCI_USBSTS_HOSTERR; 1919 } 1920 1921 if (status & UHCI_USBSTS_HCPRERR) { 1922 TRACE_MODULE_ERROR("process error\n"); 1923 acknowledge |= UHCI_USBSTS_HCPRERR; 1924 } 1925 1926 if (status & UHCI_USBSTS_HCHALT) { 1927 TRACE_MODULE_ERROR("host controller halted\n"); 1928 // at least disable interrupts so we do not flood the system 1929 WriteReg16(UHCI_USBINTR, 0); 1930 fEnabledInterrupts = 0; 1931 // ToDo: cancel all transfers and reset the host controller 1932 // acknowledge not needed 1933 } 1934 1935 if (acknowledge) 1936 WriteReg16(UHCI_USBSTS, acknowledge); 1937 1938 release_spinlock(&lock); 1939 1940 if (finishTransfers) 1941 release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE); 1942 1943 return result; 1944 } 1945 1946 1947 status_t 1948 UHCI::AddTo(Stack *stack) 1949 { 1950 #ifdef TRACE_USB 1951 set_dprintf_enabled(true); 1952 #ifndef HAIKU_TARGET_PLATFORM_HAIKU 1953 load_driver_symbols("uhci"); 1954 #endif 1955 #endif 1956 1957 if (!sPCIModule) { 1958 status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule); 1959 if (status < B_OK) { 1960 TRACE_MODULE_ERROR("AddTo(): getting pci module failed! 0x%08" 1961 B_PRIx32 "\n", status); 1962 return status; 1963 } 1964 } 1965 1966 TRACE_MODULE("AddTo(): setting up hardware\n"); 1967 1968 bool found = false; 1969 pci_info *item = new(std::nothrow) pci_info; 1970 if (!item) { 1971 sPCIModule = NULL; 1972 put_module(B_PCI_MODULE_NAME); 1973 return B_NO_MEMORY; 1974 } 1975 1976 // Try to get the PCI x86 module as well so we can enable possible MSIs. 1977 if (sPCIx86Module == NULL && get_module(B_PCI_X86_MODULE_NAME, 1978 (module_info **)&sPCIx86Module) != B_OK) { 1979 // If it isn't there, that's not critical though. 1980 TRACE_MODULE_ERROR("failed to get pci x86 module\n"); 1981 sPCIx86Module = NULL; 1982 } 1983 1984 for (int32 i = 0; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) { 1985 1986 if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb 1987 && item->class_api == PCI_usb_uhci) { 1988 if (item->u.h0.interrupt_line == 0 1989 || item->u.h0.interrupt_line == 0xFF) { 1990 TRACE_MODULE_ERROR("AddTo(): found with invalid IRQ - check IRQ assignement\n"); 1991 continue; 1992 } 1993 1994 TRACE_MODULE("AddTo(): found at IRQ %u\n", 1995 item->u.h0.interrupt_line); 1996 UHCI *bus = new(std::nothrow) UHCI(item, stack); 1997 if (!bus) { 1998 delete item; 1999 sPCIModule = NULL; 2000 put_module(B_PCI_MODULE_NAME); 2001 return B_NO_MEMORY; 2002 } 2003 2004 if (bus->InitCheck() < B_OK) { 2005 TRACE_MODULE_ERROR("AddTo(): InitCheck() failed 0x%08" B_PRIx32 2006 "\n", bus->InitCheck()); 2007 delete bus; 2008 continue; 2009 } 2010 2011 // the bus took it away 2012 item = new(std::nothrow) pci_info; 2013 2014 bus->Start(); 2015 stack->AddBusManager(bus); 2016 found = true; 2017 } 2018 } 2019 2020 if (!found) { 2021 TRACE_MODULE_ERROR("no devices found\n"); 2022 delete item; 2023 sPCIModule = NULL; 2024 put_module(B_PCI_MODULE_NAME); 2025 return ENODEV; 2026 } 2027 2028 delete item; 2029 return B_OK; 2030 } 2031 2032 2033 status_t 2034 UHCI::CreateFilledTransfer(Transfer *transfer, uhci_td **_firstDescriptor, 2035 uhci_qh **_transferQueue) 2036 { 2037 Pipe *pipe = transfer->TransferPipe(); 2038 bool directionIn = (pipe->Direction() == Pipe::In); 2039 2040 uhci_td *firstDescriptor = NULL; 2041 uhci_td *lastDescriptor = NULL; 2042 status_t result = CreateDescriptorChain(pipe, &firstDescriptor, 2043 &lastDescriptor, directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT, 2044 transfer->VectorLength()); 2045 2046 if (result < B_OK) 2047 return result; 2048 if (!firstDescriptor || !lastDescriptor) 2049 return B_NO_MEMORY; 2050 2051 lastDescriptor->status |= TD_CONTROL_IOC; 2052 lastDescriptor->link_phy = TD_TERMINATE; 2053 lastDescriptor->link_log = NULL; 2054 2055 if (!directionIn) { 2056 WriteDescriptorChain(firstDescriptor, transfer->Vector(), 2057 transfer->VectorCount()); 2058 } 2059 2060 uhci_qh *transferQueue = CreateTransferQueue(firstDescriptor); 2061 if (!transferQueue) { 2062 FreeDescriptorChain(firstDescriptor); 2063 return B_NO_MEMORY; 2064 } 2065 2066 *_firstDescriptor = firstDescriptor; 2067 *_transferQueue = transferQueue; 2068 return B_OK; 2069 } 2070 2071 2072 uhci_qh * 2073 UHCI::CreateTransferQueue(uhci_td *descriptor) 2074 { 2075 uhci_qh *queueHead; 2076 phys_addr_t physicalAddress; 2077 if (fStack->AllocateChunk((void **)&queueHead, &physicalAddress, 2078 sizeof(uhci_qh)) < B_OK) 2079 return NULL; 2080 2081 queueHead->this_phy = (uint32)physicalAddress; 2082 queueHead->element_phy = descriptor->this_phy; 2083 return queueHead; 2084 } 2085 2086 2087 void 2088 UHCI::FreeTransferQueue(uhci_qh *queueHead) 2089 { 2090 if (!queueHead) 2091 return; 2092 2093 fStack->FreeChunk(queueHead, queueHead->this_phy, sizeof(uhci_qh)); 2094 } 2095 2096 2097 uhci_td * 2098 UHCI::CreateDescriptor(Pipe *pipe, uint8 direction, size_t bufferSize) 2099 { 2100 uhci_td *result; 2101 phys_addr_t physicalAddress; 2102 2103 if (fStack->AllocateChunk((void **)&result, &physicalAddress, 2104 sizeof(uhci_td)) < B_OK) { 2105 TRACE_ERROR("failed to allocate a transfer descriptor\n"); 2106 return NULL; 2107 } 2108 2109 result->this_phy = (uint32)physicalAddress; 2110 result->status = TD_STATUS_ACTIVE; 2111 if (pipe->Type() & USB_OBJECT_ISO_PIPE) 2112 result->status |= TD_CONTROL_ISOCHRONOUS; 2113 else { 2114 result->status |= TD_CONTROL_3_ERRORS; 2115 if (direction == TD_TOKEN_IN 2116 && (pipe->Type() & USB_OBJECT_CONTROL_PIPE) != 0) 2117 result->status |= TD_CONTROL_SPD; 2118 } 2119 if (pipe->Speed() == USB_SPEED_LOWSPEED) 2120 result->status |= TD_CONTROL_LOWSPEED; 2121 2122 result->buffer_size = bufferSize; 2123 if (bufferSize == 0) 2124 result->token = TD_TOKEN_NULL_DATA; 2125 else 2126 result->token = (bufferSize - 1) << TD_TOKEN_MAXLEN_SHIFT; 2127 2128 result->token |= (pipe->EndpointAddress() << TD_TOKEN_ENDPTADDR_SHIFT) 2129 | (pipe->DeviceAddress() << 8) | direction; 2130 2131 result->link_phy = 0; 2132 result->link_log = NULL; 2133 if (bufferSize <= 0) { 2134 result->buffer_log = NULL; 2135 result->buffer_phy = 0; 2136 return result; 2137 } 2138 2139 if (fStack->AllocateChunk(&result->buffer_log, &physicalAddress, 2140 bufferSize) < B_OK) { 2141 TRACE_ERROR("unable to allocate space for the buffer\n"); 2142 fStack->FreeChunk(result, result->this_phy, sizeof(uhci_td)); 2143 return NULL; 2144 } 2145 result->buffer_phy = physicalAddress; 2146 2147 return result; 2148 } 2149 2150 2151 status_t 2152 UHCI::CreateDescriptorChain(Pipe *pipe, uhci_td **_firstDescriptor, 2153 uhci_td **_lastDescriptor, uint8 direction, size_t bufferSize) 2154 { 2155 size_t packetSize = pipe->MaxPacketSize(); 2156 int32 descriptorCount = (bufferSize + packetSize - 1) / packetSize; 2157 if (descriptorCount == 0) 2158 descriptorCount = 1; 2159 2160 bool dataToggle = pipe->DataToggle(); 2161 uhci_td *firstDescriptor = NULL; 2162 uhci_td *lastDescriptor = *_firstDescriptor; 2163 for (int32 i = 0; i < descriptorCount; i++) { 2164 uhci_td *descriptor = CreateDescriptor(pipe, direction, 2165 min_c(packetSize, bufferSize)); 2166 2167 if (!descriptor) { 2168 FreeDescriptorChain(firstDescriptor); 2169 return B_NO_MEMORY; 2170 } 2171 2172 if (dataToggle) 2173 descriptor->token |= TD_TOKEN_DATA1; 2174 2175 // link to previous 2176 if (lastDescriptor) 2177 LinkDescriptors(lastDescriptor, descriptor); 2178 2179 dataToggle = !dataToggle; 2180 bufferSize -= packetSize; 2181 lastDescriptor = descriptor; 2182 if (!firstDescriptor) 2183 firstDescriptor = descriptor; 2184 } 2185 2186 *_firstDescriptor = firstDescriptor; 2187 *_lastDescriptor = lastDescriptor; 2188 return B_OK; 2189 } 2190 2191 2192 void 2193 UHCI::FreeDescriptor(uhci_td *descriptor) 2194 { 2195 if (!descriptor) 2196 return; 2197 2198 if (descriptor->buffer_log) { 2199 fStack->FreeChunk(descriptor->buffer_log, 2200 descriptor->buffer_phy, descriptor->buffer_size); 2201 } 2202 2203 fStack->FreeChunk(descriptor, descriptor->this_phy, sizeof(uhci_td)); 2204 } 2205 2206 2207 void 2208 UHCI::FreeDescriptorChain(uhci_td *topDescriptor) 2209 { 2210 uhci_td *current = topDescriptor; 2211 uhci_td *next = NULL; 2212 2213 while (current) { 2214 next = (uhci_td *)current->link_log; 2215 FreeDescriptor(current); 2216 current = next; 2217 } 2218 } 2219 2220 2221 void 2222 UHCI::LinkDescriptors(uhci_td *first, uhci_td *second) 2223 { 2224 first->link_phy = second->this_phy | TD_DEPTH_FIRST; 2225 first->link_log = second; 2226 } 2227 2228 2229 size_t 2230 UHCI::WriteDescriptorChain(uhci_td *topDescriptor, iovec *vector, 2231 size_t vectorCount) 2232 { 2233 uhci_td *current = topDescriptor; 2234 size_t actualLength = 0; 2235 size_t vectorIndex = 0; 2236 size_t vectorOffset = 0; 2237 size_t bufferOffset = 0; 2238 2239 while (current) { 2240 if (!current->buffer_log) 2241 break; 2242 2243 while (true) { 2244 size_t length = min_c(current->buffer_size - bufferOffset, 2245 vector[vectorIndex].iov_len - vectorOffset); 2246 2247 TRACE("copying %ld bytes to bufferOffset %ld from" 2248 " vectorOffset %ld at index %ld of %ld\n", length, bufferOffset, 2249 vectorOffset, vectorIndex, vectorCount); 2250 memcpy((uint8 *)current->buffer_log + bufferOffset, 2251 (uint8 *)vector[vectorIndex].iov_base + vectorOffset, length); 2252 2253 actualLength += length; 2254 vectorOffset += length; 2255 bufferOffset += length; 2256 2257 if (vectorOffset >= vector[vectorIndex].iov_len) { 2258 if (++vectorIndex >= vectorCount) { 2259 TRACE("wrote descriptor chain (%ld bytes, no more vectors)\n", 2260 actualLength); 2261 return actualLength; 2262 } 2263 2264 vectorOffset = 0; 2265 } 2266 2267 if (bufferOffset >= current->buffer_size) { 2268 bufferOffset = 0; 2269 break; 2270 } 2271 } 2272 2273 if (current->link_phy & TD_TERMINATE) 2274 break; 2275 2276 current = (uhci_td *)current->link_log; 2277 } 2278 2279 TRACE("wrote descriptor chain (%ld bytes)\n", actualLength); 2280 return actualLength; 2281 } 2282 2283 2284 size_t 2285 UHCI::ReadDescriptorChain(uhci_td *topDescriptor, iovec *vector, 2286 size_t vectorCount, uint8 *lastDataToggle) 2287 { 2288 uint8 dataToggle = 0; 2289 uhci_td *current = topDescriptor; 2290 size_t actualLength = 0; 2291 size_t vectorIndex = 0; 2292 size_t vectorOffset = 0; 2293 size_t bufferOffset = 0; 2294 2295 while (current && (current->status & TD_STATUS_ACTIVE) == 0) { 2296 if (!current->buffer_log) 2297 break; 2298 2299 dataToggle = (current->token >> TD_TOKEN_DATA_TOGGLE_SHIFT) & 0x01; 2300 size_t bufferSize = uhci_td_actual_length(current); 2301 2302 while (true) { 2303 size_t length = min_c(bufferSize - bufferOffset, 2304 vector[vectorIndex].iov_len - vectorOffset); 2305 2306 TRACE("copying %ld bytes to vectorOffset %ld from" 2307 " bufferOffset %ld at index %ld of %ld\n", length, vectorOffset, 2308 bufferOffset, vectorIndex, vectorCount); 2309 memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset, 2310 (uint8 *)current->buffer_log + bufferOffset, length); 2311 2312 actualLength += length; 2313 vectorOffset += length; 2314 bufferOffset += length; 2315 2316 if (vectorOffset >= vector[vectorIndex].iov_len) { 2317 if (++vectorIndex >= vectorCount) { 2318 TRACE("read descriptor chain (%ld bytes, no more vectors)\n", 2319 actualLength); 2320 if (lastDataToggle) 2321 *lastDataToggle = dataToggle; 2322 return actualLength; 2323 } 2324 2325 vectorOffset = 0; 2326 } 2327 2328 if (bufferOffset >= bufferSize) { 2329 bufferOffset = 0; 2330 break; 2331 } 2332 } 2333 2334 if (current->link_phy & TD_TERMINATE) 2335 break; 2336 2337 current = (uhci_td *)current->link_log; 2338 } 2339 2340 if (lastDataToggle) 2341 *lastDataToggle = dataToggle; 2342 2343 TRACE("read descriptor chain (%ld bytes)\n", actualLength); 2344 return actualLength; 2345 } 2346 2347 2348 size_t 2349 UHCI::ReadActualLength(uhci_td *topDescriptor, uint8 *lastDataToggle) 2350 { 2351 size_t actualLength = 0; 2352 uhci_td *current = topDescriptor; 2353 uint8 dataToggle = 0; 2354 2355 while (current && (current->status & TD_STATUS_ACTIVE) == 0) { 2356 actualLength += uhci_td_actual_length(current); 2357 dataToggle = (current->token >> TD_TOKEN_DATA_TOGGLE_SHIFT) & 0x01; 2358 2359 if (current->link_phy & TD_TERMINATE) 2360 break; 2361 2362 current = (uhci_td *)current->link_log; 2363 } 2364 2365 if (lastDataToggle) 2366 *lastDataToggle = dataToggle; 2367 2368 TRACE("read actual length (%ld bytes)\n", actualLength); 2369 return actualLength; 2370 } 2371 2372 2373 void 2374 UHCI::WriteIsochronousDescriptorChain(uhci_td **isoRequest, uint32 packetCount, 2375 iovec *vector) 2376 { 2377 size_t vectorOffset = 0; 2378 for (uint32 i = 0; i < packetCount; i++) { 2379 size_t bufferSize = isoRequest[i]->buffer_size; 2380 memcpy((uint8 *)isoRequest[i]->buffer_log, 2381 (uint8 *)vector->iov_base + vectorOffset, bufferSize); 2382 vectorOffset += bufferSize; 2383 } 2384 } 2385 2386 2387 void 2388 UHCI::ReadIsochronousDescriptorChain(isochronous_transfer_data *transfer, 2389 iovec *vector) 2390 { 2391 size_t vectorOffset = 0; 2392 usb_isochronous_data *isochronousData 2393 = transfer->transfer->IsochronousData(); 2394 2395 for (uint32 i = 0; i < isochronousData->packet_count; i++) { 2396 uhci_td *current = transfer->descriptors[i]; 2397 2398 size_t bufferSize = current->buffer_size; 2399 size_t actualLength = uhci_td_actual_length(current); 2400 2401 isochronousData->packet_descriptors[i].actual_length = actualLength; 2402 2403 if (actualLength > 0) 2404 isochronousData->packet_descriptors[i].status = B_OK; 2405 else { 2406 isochronousData->packet_descriptors[i].status = B_ERROR; 2407 vectorOffset += bufferSize; 2408 continue; 2409 } 2410 memcpy((uint8 *)vector->iov_base + vectorOffset, 2411 (uint8 *)current->buffer_log, bufferSize); 2412 2413 vectorOffset += bufferSize; 2414 } 2415 } 2416 2417 2418 bool 2419 UHCI::LockIsochronous() 2420 { 2421 return (mutex_lock(&fIsochronousLock) == B_OK); 2422 } 2423 2424 2425 void 2426 UHCI::UnlockIsochronous() 2427 { 2428 mutex_unlock(&fIsochronousLock); 2429 } 2430 2431 2432 inline void 2433 UHCI::WriteReg8(uint32 reg, uint8 value) 2434 { 2435 sPCIModule->write_io_8(fRegisterBase + reg, value); 2436 } 2437 2438 2439 inline void 2440 UHCI::WriteReg16(uint32 reg, uint16 value) 2441 { 2442 sPCIModule->write_io_16(fRegisterBase + reg, value); 2443 } 2444 2445 2446 inline void 2447 UHCI::WriteReg32(uint32 reg, uint32 value) 2448 { 2449 sPCIModule->write_io_32(fRegisterBase + reg, value); 2450 } 2451 2452 2453 inline uint8 2454 UHCI::ReadReg8(uint32 reg) 2455 { 2456 return sPCIModule->read_io_8(fRegisterBase + reg); 2457 } 2458 2459 2460 inline uint16 2461 UHCI::ReadReg16(uint32 reg) 2462 { 2463 return sPCIModule->read_io_16(fRegisterBase + reg); 2464 } 2465 2466 2467 inline uint32 2468 UHCI::ReadReg32(uint32 reg) 2469 { 2470 return sPCIModule->read_io_32(fRegisterBase + reg); 2471 } 2472