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