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