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