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