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