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