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