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