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->FragmentLength()); 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 // We do not support queuing other transfers in tandem with a fragmented one. 1069 transfer_data *it = fFirstTransfer; 1070 while (it) { 1071 if (it->transfer && it->transfer->TransferPipe() == transfer->TransferPipe() 1072 && it->transfer->IsFragmented()) { 1073 TRACE_ERROR("cannot submit transfer: a fragmented transfer is queued\n"); 1074 1075 Unlock(); 1076 delete data; 1077 return B_DEV_RESOURCE_CONFLICT; 1078 } 1079 1080 it = it->link; 1081 } 1082 1083 if (fLastTransfer) 1084 fLastTransfer->link = data; 1085 if (!fFirstTransfer) 1086 fFirstTransfer = data; 1087 1088 fLastTransfer = data; 1089 Unlock(); 1090 return B_OK; 1091 } 1092 1093 1094 status_t 1095 UHCI::AddPendingIsochronousTransfer(Transfer *transfer, uhci_td **isoRequest, 1096 bool directionIn) 1097 { 1098 if (!transfer || !isoRequest) 1099 return B_BAD_VALUE; 1100 1101 isochronous_transfer_data *data 1102 = new(std::nothrow) isochronous_transfer_data; 1103 if (!data) 1104 return B_NO_MEMORY; 1105 1106 status_t result = transfer->InitKernelAccess(); 1107 if (result < B_OK) { 1108 delete data; 1109 return result; 1110 } 1111 1112 data->transfer = transfer; 1113 data->descriptors = isoRequest; 1114 data->last_to_process = transfer->IsochronousData()->packet_count - 1; 1115 data->incoming = directionIn; 1116 data->is_active = true; 1117 data->link = NULL; 1118 1119 // Put in the isochronous transfer list 1120 if (!LockIsochronous()) { 1121 delete data; 1122 return B_ERROR; 1123 } 1124 1125 if (fLastIsochronousTransfer) 1126 fLastIsochronousTransfer->link = data; 1127 if (!fFirstIsochronousTransfer) 1128 fFirstIsochronousTransfer = data; 1129 1130 fLastIsochronousTransfer = data; 1131 UnlockIsochronous(); 1132 return B_OK; 1133 } 1134 1135 1136 status_t 1137 UHCI::SubmitIsochronous(Transfer *transfer) 1138 { 1139 Pipe *pipe = transfer->TransferPipe(); 1140 bool directionIn = (pipe->Direction() == Pipe::In); 1141 usb_isochronous_data *isochronousData = transfer->IsochronousData(); 1142 size_t packetSize = transfer->DataLength(); 1143 size_t restSize = packetSize % isochronousData->packet_count; 1144 packetSize /= isochronousData->packet_count; 1145 uint16 currentFrame; 1146 1147 if (packetSize > pipe->MaxPacketSize()) { 1148 TRACE_ERROR("isochronous packetSize is bigger than pipe MaxPacketSize\n"); 1149 return B_BAD_VALUE; 1150 } 1151 1152 // Ignore the fact that the last descriptor might need less bandwidth. 1153 // The overhead is not worthy. 1154 uint16 bandwidth = transfer->Bandwidth() / isochronousData->packet_count; 1155 1156 TRACE("isochronous transfer descriptor bandwidth %d\n", bandwidth); 1157 1158 // The following holds the list of transfer descriptor of the 1159 // isochronous request. It is used to quickly remove all the isochronous 1160 // descriptors from the frame list, as descriptors are not link to each 1161 // other in a queue like for every other transfer. 1162 uhci_td **isoRequest 1163 = new(std::nothrow) uhci_td *[isochronousData->packet_count]; 1164 if (isoRequest == NULL) { 1165 TRACE("failed to create isoRequest array!\n"); 1166 return B_NO_MEMORY; 1167 } 1168 1169 // Create the list of transfer descriptors 1170 for (uint32 i = 0; i < (isochronousData->packet_count - 1); i++) { 1171 isoRequest[i] = CreateDescriptor(pipe, 1172 directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT, packetSize); 1173 // If we ran out of memory, clean up and return 1174 if (isoRequest[i] == NULL) { 1175 for (uint32 j = 0; j < i; j++) 1176 FreeDescriptor(isoRequest[j]); 1177 delete [] isoRequest; 1178 return B_NO_MEMORY; 1179 } 1180 // Make sure data toggle is set to zero 1181 isoRequest[i]->token &= ~TD_TOKEN_DATA1; 1182 } 1183 1184 // Create the last transfer descriptor which should be of smaller size 1185 // and set the IOC bit 1186 isoRequest[isochronousData->packet_count - 1] = CreateDescriptor(pipe, 1187 directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT, 1188 (restSize) ? restSize : packetSize); 1189 // If we are that unlucky... 1190 if (!isoRequest[isochronousData->packet_count - 1]) { 1191 for (uint32 i = 0; i < (isochronousData->packet_count - 2); i++) 1192 FreeDescriptor(isoRequest[i]); 1193 delete [] isoRequest; 1194 return B_NO_MEMORY; 1195 } 1196 isoRequest[isochronousData->packet_count - 1]->token &= ~TD_TOKEN_DATA1; 1197 1198 // If direction is out set every descriptor data 1199 if (!directionIn) { 1200 iovec *vector = transfer->Vector(); 1201 WriteIsochronousDescriptorChain(isoRequest, 1202 isochronousData->packet_count, vector); 1203 } else { 1204 // Initialize the packet descriptors 1205 for (uint32 i = 0; i < isochronousData->packet_count; i++) { 1206 isochronousData->packet_descriptors[i].actual_length = 0; 1207 isochronousData->packet_descriptors[i].status = B_NO_INIT; 1208 } 1209 } 1210 1211 TRACE("isochronous submitted size=%ld bytes, TDs=%" B_PRId32 ", " 1212 "packetSize=%ld, restSize=%ld\n", transfer->DataLength(), 1213 isochronousData->packet_count, packetSize, restSize); 1214 1215 // Find the entry where to start inserting the first Isochronous descriptor 1216 if (isochronousData->flags & USB_ISO_ASAP || 1217 isochronousData->starting_frame_number == NULL) { 1218 // find the first available frame with enough bandwidth. 1219 // This should always be the case, as defining the starting frame 1220 // number in the driver makes no sense for many reason, one of which 1221 // is that frame numbers value are host controller specific, and the 1222 // driver does not know which host controller is running. 1223 currentFrame = ReadReg16(UHCI_FRNUM); 1224 1225 // Make sure that: 1226 // 1. We are at least 5ms ahead the controller 1227 // 2. We stay in the range 0-1023 1228 // 3. There is enough bandwidth in the first entry 1229 currentFrame = (currentFrame + 5) % NUMBER_OF_FRAMES; 1230 } else { 1231 // Find out if the frame number specified has enough bandwidth, 1232 // otherwise find the first next available frame with enough bandwidth 1233 currentFrame = *isochronousData->starting_frame_number; 1234 } 1235 1236 // Find the first entry with enough bandwidth 1237 // TODO: should we also check the bandwidth of the following packet_count frames? 1238 uint16 startSeekingFromFrame = currentFrame; 1239 while (fFrameBandwidth[currentFrame] < bandwidth) { 1240 currentFrame = (currentFrame + 1) % NUMBER_OF_FRAMES; 1241 if (currentFrame == startSeekingFromFrame) { 1242 TRACE_ERROR("not enough bandwidth to queue the isochronous request"); 1243 for (uint32 i = 0; i < isochronousData->packet_count; i++) 1244 FreeDescriptor(isoRequest[i]); 1245 delete [] isoRequest; 1246 return B_ERROR; 1247 } 1248 } 1249 1250 if (isochronousData->starting_frame_number) 1251 *isochronousData->starting_frame_number = currentFrame; 1252 1253 // Add transfer to the list 1254 status_t result = AddPendingIsochronousTransfer(transfer, isoRequest, 1255 directionIn); 1256 if (result < B_OK) { 1257 TRACE_ERROR("failed to add pending isochronous transfer\n"); 1258 for (uint32 i = 0; i < isochronousData->packet_count; i++) 1259 FreeDescriptor(isoRequest[i]); 1260 delete [] isoRequest; 1261 return result; 1262 } 1263 1264 TRACE("appended isochronous transfer by starting at frame number %d\n", 1265 currentFrame); 1266 1267 // Insert the Transfer Descriptor by starting at 1268 // the starting_frame_number entry 1269 // TODO: We don't consider bInterval, and assume it's 1! 1270 for (uint32 i = 0; i < isochronousData->packet_count; i++) { 1271 result = LinkIsochronousDescriptor(isoRequest[i], currentFrame); 1272 if (result < B_OK) { 1273 TRACE_ERROR("failed to add pending isochronous transfer\n"); 1274 for (uint32 i = 0; i < isochronousData->packet_count; i++) 1275 FreeDescriptor(isoRequest[i]); 1276 delete [] isoRequest; 1277 return result; 1278 } 1279 1280 fFrameBandwidth[currentFrame] -= bandwidth; 1281 currentFrame = (currentFrame + 1) % NUMBER_OF_FRAMES; 1282 } 1283 1284 // Wake up the isochronous finisher thread 1285 release_sem_etc(fFinishIsochronousTransfersSem, 1, B_DO_NOT_RESCHEDULE); 1286 1287 return B_OK; 1288 } 1289 1290 1291 isochronous_transfer_data * 1292 UHCI::FindIsochronousTransfer(uhci_td *descriptor) 1293 { 1294 // Simply check every last descriptor of the isochronous transfer list 1295 if (LockIsochronous()) { 1296 isochronous_transfer_data *transfer = fFirstIsochronousTransfer; 1297 if (transfer) { 1298 while (transfer->descriptors[transfer->last_to_process] 1299 != descriptor) { 1300 transfer = transfer->link; 1301 if (!transfer) 1302 break; 1303 } 1304 } 1305 UnlockIsochronous(); 1306 return transfer; 1307 } 1308 return NULL; 1309 } 1310 1311 1312 status_t 1313 UHCI::LinkIsochronousDescriptor(uhci_td *descriptor, uint16 frame) 1314 { 1315 // The transfer descriptor is appended to the last 1316 // existing isochronous transfer descriptor (if any) 1317 // in that frame. 1318 if (LockIsochronous()) { 1319 if (!fFirstIsochronousDescriptor[frame]) { 1320 // Insert the transfer descriptor in the first position 1321 fFrameList[frame] = descriptor->this_phy & ~FRAMELIST_NEXT_IS_QH; 1322 fFirstIsochronousDescriptor[frame] = descriptor; 1323 fLastIsochronousDescriptor[frame] = descriptor; 1324 } else { 1325 // Append to the last transfer descriptor 1326 fLastIsochronousDescriptor[frame]->link_log = descriptor; 1327 fLastIsochronousDescriptor[frame]->link_phy 1328 = descriptor->this_phy & ~TD_NEXT_IS_QH; 1329 fLastIsochronousDescriptor[frame] = descriptor; 1330 } 1331 1332 descriptor->link_phy 1333 = fQueues[UHCI_INTERRUPT_QUEUE]->PhysicalAddress() | TD_NEXT_IS_QH; 1334 UnlockIsochronous(); 1335 return B_OK; 1336 } 1337 return B_ERROR; 1338 } 1339 1340 1341 uhci_td * 1342 UHCI::UnlinkIsochronousDescriptor(uint16 frame) 1343 { 1344 // We always unlink from the top 1345 if (LockIsochronous()) { 1346 uhci_td *descriptor = fFirstIsochronousDescriptor[frame]; 1347 if (descriptor) { 1348 // The descriptor will be freed later. 1349 fFrameList[frame] = descriptor->link_phy; 1350 if (descriptor->link_log) { 1351 fFirstIsochronousDescriptor[frame] 1352 = (uhci_td *)descriptor->link_log; 1353 } else { 1354 fFirstIsochronousDescriptor[frame] = NULL; 1355 fLastIsochronousDescriptor[frame] = NULL; 1356 } 1357 } 1358 UnlockIsochronous(); 1359 return descriptor; 1360 } 1361 return NULL; 1362 } 1363 1364 1365 int32 1366 UHCI::FinishThread(void *data) 1367 { 1368 ((UHCI *)data)->FinishTransfers(); 1369 return B_OK; 1370 } 1371 1372 1373 void 1374 UHCI::FinishTransfers() 1375 { 1376 while (!fStopThreads) { 1377 if (acquire_sem(fFinishTransfersSem) < B_OK) 1378 continue; 1379 1380 // eat up sems that have been released by multiple interrupts 1381 int32 semCount = 0; 1382 get_sem_count(fFinishTransfersSem, &semCount); 1383 if (semCount > 0) 1384 acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0); 1385 1386 if (!Lock()) 1387 continue; 1388 1389 TRACE("finishing transfers (first transfer: 0x%08lx; last" 1390 " transfer: 0x%08lx)\n", (addr_t)fFirstTransfer, 1391 (addr_t)fLastTransfer); 1392 transfer_data *lastTransfer = NULL; 1393 transfer_data *transfer = fFirstTransfer; 1394 Unlock(); 1395 1396 while (transfer) { 1397 bool transferDone = false; 1398 uhci_td *descriptor = transfer->first_descriptor; 1399 status_t callbackStatus = B_OK; 1400 1401 while (descriptor) { 1402 uint32 status = descriptor->status; 1403 if (status & TD_STATUS_ACTIVE) { 1404 // still in progress 1405 TRACE("td (0x%08" B_PRIx32 ") still active\n", 1406 descriptor->this_phy); 1407 break; 1408 } 1409 1410 if (status & TD_ERROR_MASK) { 1411 // an error occured 1412 TRACE_ERROR("td (0x%08" B_PRIx32 ") error: status: 0x%08" 1413 B_PRIx32 "; token: 0x%08" B_PRIx32 ";\n", 1414 descriptor->this_phy, status, descriptor->token); 1415 1416 uint8 errorCount = status >> TD_ERROR_COUNT_SHIFT; 1417 errorCount &= TD_ERROR_COUNT_MASK; 1418 if (errorCount == 0) { 1419 // the error counter counted down to zero, report why 1420 int32 reasons = 0; 1421 if (status & TD_STATUS_ERROR_BUFFER) { 1422 callbackStatus = transfer->incoming ? B_DEV_DATA_OVERRUN : B_DEV_DATA_UNDERRUN; 1423 reasons++; 1424 } 1425 if (status & TD_STATUS_ERROR_TIMEOUT) { 1426 callbackStatus = transfer->incoming ? B_DEV_CRC_ERROR : B_TIMED_OUT; 1427 reasons++; 1428 } 1429 if (status & TD_STATUS_ERROR_NAK) { 1430 callbackStatus = B_DEV_UNEXPECTED_PID; 1431 reasons++; 1432 } 1433 if (status & TD_STATUS_ERROR_BITSTUFF) { 1434 callbackStatus = B_DEV_CRC_ERROR; 1435 reasons++; 1436 } 1437 1438 if (reasons > 1) 1439 callbackStatus = B_DEV_MULTIPLE_ERRORS; 1440 } else if (status & TD_STATUS_ERROR_BABBLE) { 1441 // there is a babble condition 1442 callbackStatus = transfer->incoming ? B_DEV_FIFO_OVERRUN : B_DEV_FIFO_UNDERRUN; 1443 } else { 1444 // if the error counter didn't count down to zero 1445 // and there was no babble, then this halt was caused 1446 // by a stall handshake 1447 callbackStatus = B_DEV_STALLED; 1448 } 1449 1450 transferDone = true; 1451 break; 1452 } 1453 1454 if ((descriptor->link_phy & TD_TERMINATE) 1455 || ((descriptor->status & TD_CONTROL_SPD) != 0 1456 && uhci_td_actual_length(descriptor) 1457 < uhci_td_maximum_length(descriptor))) { 1458 // all descriptors are done, or we have a short packet 1459 TRACE("td (0x%08" B_PRIx32 ") ok\n", descriptor->this_phy); 1460 callbackStatus = B_OK; 1461 transferDone = true; 1462 break; 1463 } 1464 1465 descriptor = (uhci_td *)descriptor->link_log; 1466 } 1467 1468 if (!transferDone) { 1469 lastTransfer = transfer; 1470 transfer = transfer->link; 1471 continue; 1472 } 1473 1474 // remove the transfer from the list first so we are sure 1475 // it doesn't get canceled while we still process it 1476 transfer_data *next = transfer->link; 1477 if (Lock()) { 1478 if (lastTransfer) 1479 lastTransfer->link = transfer->link; 1480 1481 if (transfer == fFirstTransfer) 1482 fFirstTransfer = transfer->link; 1483 if (transfer == fLastTransfer) 1484 fLastTransfer = lastTransfer; 1485 1486 // store the currently processing pipe here so we can wait 1487 // in cancel if we are processing something on the target pipe 1488 if (!transfer->canceled) 1489 fProcessingPipe = transfer->transfer->TransferPipe(); 1490 1491 transfer->link = NULL; 1492 Unlock(); 1493 } 1494 1495 // if canceled the callback has already been called 1496 if (!transfer->canceled) { 1497 size_t actualLength = 0; 1498 if (callbackStatus == B_OK) { 1499 uint8 lastDataToggle = 0; 1500 if (transfer->data_descriptor && transfer->incoming) { 1501 // data to read out 1502 iovec *vector = transfer->transfer->Vector(); 1503 size_t vectorCount = transfer->transfer->VectorCount(); 1504 1505 transfer->transfer->PrepareKernelAccess(); 1506 actualLength = ReadDescriptorChain( 1507 transfer->data_descriptor, 1508 vector, vectorCount, 1509 &lastDataToggle); 1510 } else if (transfer->data_descriptor) { 1511 // read the actual length that was sent 1512 actualLength = ReadActualLength( 1513 transfer->data_descriptor, &lastDataToggle); 1514 } 1515 1516 transfer->transfer->TransferPipe()->SetDataToggle(lastDataToggle == 0); 1517 1518 if (transfer->transfer->IsFragmented()) { 1519 // this transfer may still have data left 1520 TRACE("advancing fragmented transfer\n"); 1521 transfer->transfer->AdvanceByFragment(actualLength); 1522 if (transfer->transfer->FragmentLength() > 0) { 1523 TRACE("still %ld bytes left on transfer\n", 1524 transfer->transfer->FragmentLength()); 1525 1526 Transfer *resubmit = transfer->transfer; 1527 1528 // free the used descriptors 1529 transfer->queue->RemoveTransfer( 1530 transfer->transfer_queue); 1531 AddToFreeList(transfer); 1532 1533 // resubmit the advanced transfer so the rest 1534 // of the buffers are transmitted over the bus 1535 resubmit->PrepareKernelAccess(); 1536 if (SubmitTransfer(resubmit) != B_OK) 1537 resubmit->Finished(B_ERROR, 0); 1538 1539 transfer = next; 1540 continue; 1541 } 1542 1543 // the transfer is done, but we already set the 1544 // actualLength with AdvanceByFragment() 1545 actualLength = 0; 1546 } 1547 } 1548 1549 transfer->transfer->Finished(callbackStatus, actualLength); 1550 fProcessingPipe = NULL; 1551 } 1552 1553 // remove and free the hardware queue and its descriptors 1554 transfer->queue->RemoveTransfer(transfer->transfer_queue); 1555 delete transfer->transfer; 1556 AddToFreeList(transfer); 1557 transfer = next; 1558 } 1559 } 1560 } 1561 1562 1563 void 1564 UHCI::AddToFreeList(transfer_data *transfer) 1565 { 1566 transfer->free_after_frame = ReadReg16(UHCI_FRNUM); 1567 if (!Lock()) 1568 return; 1569 1570 transfer->link = fFreeList; 1571 fFreeList = transfer; 1572 Unlock(); 1573 1574 if (atomic_add(&fCleanupCount, 1) == 0) 1575 release_sem(fCleanupSem); 1576 } 1577 1578 1579 int32 1580 UHCI::CleanupThread(void *data) 1581 { 1582 ((UHCI *)data)->Cleanup(); 1583 return B_OK; 1584 } 1585 1586 1587 void 1588 UHCI::Cleanup() 1589 { 1590 while (!fStopThreads) { 1591 if (acquire_sem(fCleanupSem) != B_OK) 1592 continue; 1593 1594 bigtime_t nextTime = system_time() + 1000; 1595 while (atomic_get(&fCleanupCount) != 0) { 1596 // wait for the frame to pass 1597 snooze_until(nextTime, B_SYSTEM_TIMEBASE); 1598 nextTime += 1000; 1599 1600 if (!Lock()) 1601 continue; 1602 1603 // find the first entry we may free 1604 transfer_data **link = &fFreeList; 1605 transfer_data *transfer = fFreeList; 1606 uint16 frameNumber = ReadReg16(UHCI_FRNUM); 1607 while (transfer) { 1608 if (transfer->free_after_frame != frameNumber) { 1609 *link = NULL; 1610 break; 1611 } 1612 1613 link = &transfer->link; 1614 transfer = transfer->link; 1615 } 1616 1617 Unlock(); 1618 1619 // the transfers below this one are all freeable 1620 while (transfer) { 1621 transfer_data *next = transfer->link; 1622 FreeDescriptorChain(transfer->first_descriptor); 1623 FreeTransferQueue(transfer->transfer_queue); 1624 delete transfer; 1625 atomic_add(&fCleanupCount, -1); 1626 transfer = next; 1627 } 1628 } 1629 } 1630 } 1631 1632 1633 int32 1634 UHCI::FinishIsochronousThread(void *data) 1635 { 1636 ((UHCI *)data)->FinishIsochronousTransfers(); 1637 return B_OK; 1638 } 1639 1640 1641 void 1642 UHCI::FinishIsochronousTransfers() 1643 { 1644 /* This thread stays one position behind the controller and processes every 1645 * isochronous descriptor. Once it finds the last isochronous descriptor 1646 * of a transfer, it processes the entire transfer. 1647 */ 1648 1649 while (!fStopThreads) { 1650 // Go to sleep if there are not isochronous transfer to process 1651 if (acquire_sem(fFinishIsochronousTransfersSem) < B_OK) 1652 return; 1653 1654 bool transferDone = false; 1655 uint16 currentFrame = ReadReg16(UHCI_FRNUM); 1656 1657 // Process the frame list until one transfer is processed 1658 while (!transferDone) { 1659 // wait 1ms in order to be sure to be one position behind 1660 // the controller 1661 if (currentFrame == ReadReg16(UHCI_FRNUM)) 1662 snooze(1000); 1663 1664 // Process the frame till it has isochronous descriptors in it. 1665 while (!(fFrameList[currentFrame] & FRAMELIST_NEXT_IS_QH)) { 1666 uhci_td *current = UnlinkIsochronousDescriptor(currentFrame); 1667 1668 // Process the transfer if we found the last descriptor 1669 isochronous_transfer_data *transfer 1670 = FindIsochronousTransfer(current); 1671 // Process the descriptors only if it is still active and 1672 // belongs to an inbound transfer. If the transfer is not 1673 // active, it means the request has been removed, so simply 1674 // remove the descriptors. 1675 if (transfer && transfer->is_active) { 1676 if (current->token & TD_TOKEN_IN) { 1677 iovec *vector = transfer->transfer->Vector(); 1678 transfer->transfer->PrepareKernelAccess(); 1679 ReadIsochronousDescriptorChain(transfer, vector); 1680 } 1681 1682 // Remove the transfer 1683 if (LockIsochronous()) { 1684 if (transfer == fFirstIsochronousTransfer) { 1685 fFirstIsochronousTransfer = transfer->link; 1686 if (transfer == fLastIsochronousTransfer) 1687 fLastIsochronousTransfer = NULL; 1688 } else { 1689 isochronous_transfer_data *temp 1690 = fFirstIsochronousTransfer; 1691 while (transfer != temp->link) 1692 temp = temp->link; 1693 1694 if (transfer == fLastIsochronousTransfer) 1695 fLastIsochronousTransfer = temp; 1696 temp->link = temp->link->link; 1697 } 1698 UnlockIsochronous(); 1699 } 1700 1701 transfer->transfer->Finished(B_OK, 0); 1702 1703 uint32 packetCount = 1704 transfer->transfer->IsochronousData()->packet_count; 1705 for (uint32 i = 0; i < packetCount; i++) 1706 FreeDescriptor(transfer->descriptors[i]); 1707 1708 delete [] transfer->descriptors; 1709 delete transfer->transfer; 1710 delete transfer; 1711 transferDone = true; 1712 } 1713 } 1714 1715 // Make sure to reset the frame bandwidth 1716 fFrameBandwidth[currentFrame] = MAX_AVAILABLE_BANDWIDTH; 1717 currentFrame = (currentFrame + 1) % NUMBER_OF_FRAMES; 1718 } 1719 } 1720 } 1721 1722 1723 void 1724 UHCI::GlobalReset() 1725 { 1726 uint8 sofValue = ReadReg8(UHCI_SOFMOD); 1727 1728 WriteReg16(UHCI_USBCMD, UHCI_USBCMD_GRESET); 1729 snooze(100000); 1730 WriteReg16(UHCI_USBCMD, 0); 1731 snooze(10000); 1732 1733 WriteReg8(UHCI_SOFMOD, sofValue); 1734 } 1735 1736 1737 status_t 1738 UHCI::ControllerReset() 1739 { 1740 WriteReg16(UHCI_USBCMD, UHCI_USBCMD_HCRESET); 1741 1742 int32 tries = 5; 1743 while (ReadReg16(UHCI_USBCMD) & UHCI_USBCMD_HCRESET) { 1744 snooze(10000); 1745 if (tries-- < 0) 1746 return B_ERROR; 1747 } 1748 1749 return B_OK; 1750 } 1751 1752 1753 status_t 1754 UHCI::GetPortStatus(uint8 index, usb_port_status *status) 1755 { 1756 if (index > 1) 1757 return B_BAD_INDEX; 1758 1759 status->status = status->change = 0; 1760 uint16 portStatus = ReadReg16(UHCI_PORTSC1 + index * 2); 1761 1762 // build the status 1763 if (portStatus & UHCI_PORTSC_CURSTAT) 1764 status->status |= PORT_STATUS_CONNECTION; 1765 if (portStatus & UHCI_PORTSC_ENABLED) 1766 status->status |= PORT_STATUS_ENABLE; 1767 if (portStatus & UHCI_PORTSC_RESET) 1768 status->status |= PORT_STATUS_RESET; 1769 if (portStatus & UHCI_PORTSC_LOWSPEED) 1770 status->status |= PORT_STATUS_LOW_SPEED; 1771 1772 // build the change 1773 if (portStatus & UHCI_PORTSC_STATCHA) 1774 status->change |= PORT_STATUS_CONNECTION; 1775 if (portStatus & UHCI_PORTSC_ENABCHA) 1776 status->change |= PORT_STATUS_ENABLE; 1777 1778 // ToDo: work out suspended/resume 1779 1780 // there are no bits to indicate reset change 1781 if (fPortResetChange & (1 << index)) 1782 status->change |= PORT_STATUS_RESET; 1783 1784 // the port is automagically powered on 1785 status->status |= PORT_STATUS_POWER; 1786 return B_OK; 1787 } 1788 1789 1790 status_t 1791 UHCI::SetPortFeature(uint8 index, uint16 feature) 1792 { 1793 if (index > 1) 1794 return B_BAD_INDEX; 1795 1796 switch (feature) { 1797 case PORT_RESET: 1798 return ResetPort(index); 1799 1800 case PORT_POWER: 1801 // the ports are automatically powered 1802 return B_OK; 1803 } 1804 1805 return B_BAD_VALUE; 1806 } 1807 1808 1809 status_t 1810 UHCI::ClearPortFeature(uint8 index, uint16 feature) 1811 { 1812 if (index > 1) 1813 return B_BAD_INDEX; 1814 1815 uint32 portRegister = UHCI_PORTSC1 + index * 2; 1816 uint16 portStatus = ReadReg16(portRegister) & UHCI_PORTSC_DATAMASK; 1817 1818 switch (feature) { 1819 case C_PORT_RESET: 1820 fPortResetChange &= ~(1 << index); 1821 return B_OK; 1822 1823 case C_PORT_CONNECTION: 1824 WriteReg16(portRegister, portStatus | UHCI_PORTSC_STATCHA); 1825 return B_OK; 1826 1827 case C_PORT_ENABLE: 1828 WriteReg16(portRegister, portStatus | UHCI_PORTSC_ENABCHA); 1829 return B_OK; 1830 } 1831 1832 return B_BAD_VALUE; 1833 } 1834 1835 1836 status_t 1837 UHCI::ResetPort(uint8 index) 1838 { 1839 if (index > 1) 1840 return B_BAD_INDEX; 1841 1842 TRACE("reset port %d\n", index); 1843 1844 uint32 port = UHCI_PORTSC1 + index * 2; 1845 uint16 status = ReadReg16(port); 1846 status &= UHCI_PORTSC_DATAMASK; 1847 WriteReg16(port, status | UHCI_PORTSC_RESET); 1848 snooze(250000); 1849 1850 status = ReadReg16(port); 1851 status &= UHCI_PORTSC_DATAMASK; 1852 WriteReg16(port, status & ~UHCI_PORTSC_RESET); 1853 snooze(1000); 1854 1855 for (int32 i = 10; i > 0; i--) { 1856 // try to enable the port 1857 status = ReadReg16(port); 1858 status &= UHCI_PORTSC_DATAMASK; 1859 WriteReg16(port, status | UHCI_PORTSC_ENABLED); 1860 snooze(50000); 1861 1862 status = ReadReg16(port); 1863 1864 if ((status & UHCI_PORTSC_CURSTAT) == 0) { 1865 // no device connected. since we waited long enough we can assume 1866 // that the port was reset and no device is connected. 1867 break; 1868 } 1869 1870 if (status & (UHCI_PORTSC_STATCHA | UHCI_PORTSC_ENABCHA)) { 1871 // port enabled changed or connection status were set. 1872 // acknowledge either / both and wait again. 1873 status &= UHCI_PORTSC_DATAMASK; 1874 WriteReg16(port, status | UHCI_PORTSC_STATCHA | UHCI_PORTSC_ENABCHA); 1875 continue; 1876 } 1877 1878 if (status & UHCI_PORTSC_ENABLED) { 1879 // the port is enabled 1880 break; 1881 } 1882 } 1883 1884 fPortResetChange |= (1 << index); 1885 TRACE("port was reset: 0x%04x\n", ReadReg16(port)); 1886 return B_OK; 1887 } 1888 1889 1890 int32 1891 UHCI::InterruptHandler(void *data) 1892 { 1893 return ((UHCI *)data)->Interrupt(); 1894 } 1895 1896 1897 int32 1898 UHCI::Interrupt() 1899 { 1900 static spinlock lock = B_SPINLOCK_INITIALIZER; 1901 acquire_spinlock(&lock); 1902 1903 // Check if we really had an interrupt 1904 uint16 status = ReadReg16(UHCI_USBSTS); 1905 if ((status & fEnabledInterrupts) == 0) { 1906 if (status != 0) { 1907 TRACE("discarding not enabled interrupts 0x%08x\n", status); 1908 WriteReg16(UHCI_USBSTS, status); 1909 } 1910 1911 release_spinlock(&lock); 1912 return B_UNHANDLED_INTERRUPT; 1913 } 1914 1915 uint16 acknowledge = 0; 1916 bool finishTransfers = false; 1917 int32 result = B_HANDLED_INTERRUPT; 1918 1919 if (status & UHCI_USBSTS_USBINT) { 1920 TRACE_MODULE("transfer finished\n"); 1921 acknowledge |= UHCI_USBSTS_USBINT; 1922 result = B_INVOKE_SCHEDULER; 1923 finishTransfers = true; 1924 } 1925 1926 if (status & UHCI_USBSTS_ERRINT) { 1927 TRACE_MODULE("transfer error\n"); 1928 acknowledge |= UHCI_USBSTS_ERRINT; 1929 result = B_INVOKE_SCHEDULER; 1930 finishTransfers = true; 1931 } 1932 1933 if (status & UHCI_USBSTS_RESDET) { 1934 TRACE_MODULE("resume detected\n"); 1935 acknowledge |= UHCI_USBSTS_RESDET; 1936 } 1937 1938 if (status & UHCI_USBSTS_HOSTERR) { 1939 TRACE_MODULE_ERROR("host system error\n"); 1940 acknowledge |= UHCI_USBSTS_HOSTERR; 1941 } 1942 1943 if (status & UHCI_USBSTS_HCPRERR) { 1944 TRACE_MODULE_ERROR("process error\n"); 1945 acknowledge |= UHCI_USBSTS_HCPRERR; 1946 } 1947 1948 if (status & UHCI_USBSTS_HCHALT) { 1949 TRACE_MODULE_ERROR("host controller halted\n"); 1950 // at least disable interrupts so we do not flood the system 1951 WriteReg16(UHCI_USBINTR, 0); 1952 fEnabledInterrupts = 0; 1953 // ToDo: cancel all transfers and reset the host controller 1954 // acknowledge not needed 1955 } 1956 1957 if (acknowledge) 1958 WriteReg16(UHCI_USBSTS, acknowledge); 1959 1960 release_spinlock(&lock); 1961 1962 if (finishTransfers) 1963 release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE); 1964 1965 return result; 1966 } 1967 1968 1969 status_t 1970 UHCI::CreateFilledTransfer(Transfer *transfer, uhci_td **_firstDescriptor, 1971 uhci_qh **_transferQueue) 1972 { 1973 Pipe *pipe = transfer->TransferPipe(); 1974 bool directionIn = (pipe->Direction() == Pipe::In); 1975 1976 uhci_td *firstDescriptor = NULL; 1977 uhci_td *lastDescriptor = NULL; 1978 status_t result = CreateDescriptorChain(pipe, &firstDescriptor, 1979 &lastDescriptor, directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT, 1980 transfer->FragmentLength()); 1981 1982 if (result < B_OK) 1983 return result; 1984 if (!firstDescriptor || !lastDescriptor) 1985 return B_NO_MEMORY; 1986 1987 lastDescriptor->status |= TD_CONTROL_IOC; 1988 lastDescriptor->link_phy = TD_TERMINATE; 1989 lastDescriptor->link_log = NULL; 1990 1991 if (!directionIn) { 1992 WriteDescriptorChain(firstDescriptor, transfer->Vector(), 1993 transfer->VectorCount()); 1994 } 1995 1996 uhci_qh *transferQueue = CreateTransferQueue(firstDescriptor); 1997 if (!transferQueue) { 1998 FreeDescriptorChain(firstDescriptor); 1999 return B_NO_MEMORY; 2000 } 2001 2002 *_firstDescriptor = firstDescriptor; 2003 *_transferQueue = transferQueue; 2004 return B_OK; 2005 } 2006 2007 2008 uhci_qh * 2009 UHCI::CreateTransferQueue(uhci_td *descriptor) 2010 { 2011 uhci_qh *queueHead; 2012 phys_addr_t physicalAddress; 2013 if (fStack->AllocateChunk((void **)&queueHead, &physicalAddress, 2014 sizeof(uhci_qh)) < B_OK) 2015 return NULL; 2016 2017 queueHead->this_phy = (uint32)physicalAddress; 2018 queueHead->element_phy = descriptor->this_phy; 2019 return queueHead; 2020 } 2021 2022 2023 void 2024 UHCI::FreeTransferQueue(uhci_qh *queueHead) 2025 { 2026 if (!queueHead) 2027 return; 2028 2029 fStack->FreeChunk(queueHead, queueHead->this_phy, sizeof(uhci_qh)); 2030 } 2031 2032 2033 uhci_td * 2034 UHCI::CreateDescriptor(Pipe *pipe, uint8 direction, size_t bufferSize) 2035 { 2036 uhci_td *result; 2037 phys_addr_t physicalAddress; 2038 2039 if (fStack->AllocateChunk((void **)&result, &physicalAddress, 2040 sizeof(uhci_td)) < B_OK) { 2041 TRACE_ERROR("failed to allocate a transfer descriptor\n"); 2042 return NULL; 2043 } 2044 2045 result->this_phy = (uint32)physicalAddress; 2046 result->status = TD_STATUS_ACTIVE; 2047 if (pipe->Type() & USB_OBJECT_ISO_PIPE) 2048 result->status |= TD_CONTROL_ISOCHRONOUS; 2049 else { 2050 result->status |= TD_CONTROL_3_ERRORS; 2051 if (direction == TD_TOKEN_IN) 2052 result->status |= TD_CONTROL_SPD; 2053 } 2054 if (pipe->Speed() == USB_SPEED_LOWSPEED) 2055 result->status |= TD_CONTROL_LOWSPEED; 2056 2057 result->buffer_size = bufferSize; 2058 if (bufferSize == 0) 2059 result->token = TD_TOKEN_NULL_DATA; 2060 else 2061 result->token = (bufferSize - 1) << TD_TOKEN_MAXLEN_SHIFT; 2062 2063 result->token |= (pipe->EndpointAddress() << TD_TOKEN_ENDPTADDR_SHIFT) 2064 | (pipe->DeviceAddress() << 8) | direction; 2065 2066 result->link_phy = 0; 2067 result->link_log = NULL; 2068 if (bufferSize <= 0) { 2069 result->buffer_log = NULL; 2070 result->buffer_phy = 0; 2071 return result; 2072 } 2073 2074 if (fStack->AllocateChunk(&result->buffer_log, &physicalAddress, 2075 bufferSize) < B_OK) { 2076 TRACE_ERROR("unable to allocate space for the buffer\n"); 2077 fStack->FreeChunk(result, result->this_phy, sizeof(uhci_td)); 2078 return NULL; 2079 } 2080 result->buffer_phy = physicalAddress; 2081 2082 return result; 2083 } 2084 2085 2086 status_t 2087 UHCI::CreateDescriptorChain(Pipe *pipe, uhci_td **_firstDescriptor, 2088 uhci_td **_lastDescriptor, uint8 direction, size_t bufferSize) 2089 { 2090 size_t packetSize = pipe->MaxPacketSize(); 2091 int32 descriptorCount = (bufferSize + packetSize - 1) / packetSize; 2092 if (descriptorCount == 0) 2093 descriptorCount = 1; 2094 2095 bool dataToggle = pipe->DataToggle(); 2096 uhci_td *firstDescriptor = NULL; 2097 uhci_td *lastDescriptor = *_firstDescriptor; 2098 for (int32 i = 0; i < descriptorCount; i++) { 2099 uhci_td *descriptor = CreateDescriptor(pipe, direction, 2100 min_c(packetSize, bufferSize)); 2101 2102 if (!descriptor) { 2103 FreeDescriptorChain(firstDescriptor); 2104 return B_NO_MEMORY; 2105 } 2106 2107 if (dataToggle) 2108 descriptor->token |= TD_TOKEN_DATA1; 2109 2110 // link to previous 2111 if (lastDescriptor) 2112 LinkDescriptors(lastDescriptor, descriptor); 2113 2114 dataToggle = !dataToggle; 2115 bufferSize -= packetSize; 2116 lastDescriptor = descriptor; 2117 if (!firstDescriptor) 2118 firstDescriptor = descriptor; 2119 } 2120 2121 *_firstDescriptor = firstDescriptor; 2122 *_lastDescriptor = lastDescriptor; 2123 return B_OK; 2124 } 2125 2126 2127 void 2128 UHCI::FreeDescriptor(uhci_td *descriptor) 2129 { 2130 if (!descriptor) 2131 return; 2132 2133 if (descriptor->buffer_log) { 2134 fStack->FreeChunk(descriptor->buffer_log, 2135 descriptor->buffer_phy, descriptor->buffer_size); 2136 } 2137 2138 fStack->FreeChunk(descriptor, descriptor->this_phy, sizeof(uhci_td)); 2139 } 2140 2141 2142 void 2143 UHCI::FreeDescriptorChain(uhci_td *topDescriptor) 2144 { 2145 uhci_td *current = topDescriptor; 2146 uhci_td *next = NULL; 2147 2148 while (current) { 2149 next = (uhci_td *)current->link_log; 2150 FreeDescriptor(current); 2151 current = next; 2152 } 2153 } 2154 2155 2156 void 2157 UHCI::LinkDescriptors(uhci_td *first, uhci_td *second) 2158 { 2159 first->link_phy = second->this_phy | TD_DEPTH_FIRST; 2160 first->link_log = second; 2161 } 2162 2163 2164 size_t 2165 UHCI::WriteDescriptorChain(uhci_td *topDescriptor, iovec *vector, 2166 size_t vectorCount) 2167 { 2168 uhci_td *current = topDescriptor; 2169 size_t actualLength = 0; 2170 size_t vectorIndex = 0; 2171 size_t vectorOffset = 0; 2172 size_t bufferOffset = 0; 2173 2174 while (current) { 2175 if (!current->buffer_log) 2176 break; 2177 2178 while (true) { 2179 size_t length = min_c(current->buffer_size - bufferOffset, 2180 vector[vectorIndex].iov_len - vectorOffset); 2181 2182 TRACE("copying %ld bytes to bufferOffset %ld from" 2183 " vectorOffset %ld at index %ld of %ld\n", length, bufferOffset, 2184 vectorOffset, vectorIndex, vectorCount); 2185 memcpy((uint8 *)current->buffer_log + bufferOffset, 2186 (uint8 *)vector[vectorIndex].iov_base + vectorOffset, length); 2187 2188 actualLength += length; 2189 vectorOffset += length; 2190 bufferOffset += length; 2191 2192 if (vectorOffset >= vector[vectorIndex].iov_len) { 2193 if (++vectorIndex >= vectorCount) { 2194 TRACE("wrote descriptor chain (%ld bytes, no more vectors)\n", 2195 actualLength); 2196 return actualLength; 2197 } 2198 2199 vectorOffset = 0; 2200 } 2201 2202 if (bufferOffset >= current->buffer_size) { 2203 bufferOffset = 0; 2204 break; 2205 } 2206 } 2207 2208 if (current->link_phy & TD_TERMINATE) 2209 break; 2210 2211 current = (uhci_td *)current->link_log; 2212 } 2213 2214 TRACE("wrote descriptor chain (%ld bytes)\n", actualLength); 2215 return actualLength; 2216 } 2217 2218 2219 size_t 2220 UHCI::ReadDescriptorChain(uhci_td *topDescriptor, iovec *vector, 2221 size_t vectorCount, uint8 *lastDataToggle) 2222 { 2223 uint8 dataToggle = 0; 2224 uhci_td *current = topDescriptor; 2225 size_t actualLength = 0; 2226 size_t vectorIndex = 0; 2227 size_t vectorOffset = 0; 2228 size_t bufferOffset = 0; 2229 2230 while (current && (current->status & TD_STATUS_ACTIVE) == 0) { 2231 if (!current->buffer_log) 2232 break; 2233 2234 dataToggle = (current->token >> TD_TOKEN_DATA_TOGGLE_SHIFT) & 0x01; 2235 size_t bufferSize = uhci_td_actual_length(current); 2236 2237 while (true) { 2238 size_t length = min_c(bufferSize - bufferOffset, 2239 vector[vectorIndex].iov_len - vectorOffset); 2240 2241 TRACE("copying %ld bytes to vectorOffset %ld from" 2242 " bufferOffset %ld at index %ld of %ld\n", length, vectorOffset, 2243 bufferOffset, vectorIndex, vectorCount); 2244 memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset, 2245 (uint8 *)current->buffer_log + bufferOffset, length); 2246 2247 actualLength += length; 2248 vectorOffset += length; 2249 bufferOffset += length; 2250 2251 if (vectorOffset >= vector[vectorIndex].iov_len) { 2252 if (++vectorIndex >= vectorCount) { 2253 TRACE("read descriptor chain (%ld bytes, no more vectors)\n", 2254 actualLength); 2255 if (lastDataToggle) 2256 *lastDataToggle = dataToggle; 2257 return actualLength; 2258 } 2259 2260 vectorOffset = 0; 2261 } 2262 2263 if (bufferOffset >= bufferSize) { 2264 bufferOffset = 0; 2265 break; 2266 } 2267 } 2268 2269 if (current->link_phy & TD_TERMINATE) 2270 break; 2271 2272 current = (uhci_td *)current->link_log; 2273 } 2274 2275 if (lastDataToggle) 2276 *lastDataToggle = dataToggle; 2277 2278 TRACE("read descriptor chain (%ld bytes)\n", actualLength); 2279 return actualLength; 2280 } 2281 2282 2283 size_t 2284 UHCI::ReadActualLength(uhci_td *topDescriptor, uint8 *lastDataToggle) 2285 { 2286 size_t actualLength = 0; 2287 uhci_td *current = topDescriptor; 2288 uint8 dataToggle = 0; 2289 2290 while (current && (current->status & TD_STATUS_ACTIVE) == 0) { 2291 actualLength += uhci_td_actual_length(current); 2292 dataToggle = (current->token >> TD_TOKEN_DATA_TOGGLE_SHIFT) & 0x01; 2293 2294 if (current->link_phy & TD_TERMINATE) 2295 break; 2296 2297 current = (uhci_td *)current->link_log; 2298 } 2299 2300 if (lastDataToggle) 2301 *lastDataToggle = dataToggle; 2302 2303 TRACE("read actual length (%ld bytes)\n", actualLength); 2304 return actualLength; 2305 } 2306 2307 2308 void 2309 UHCI::WriteIsochronousDescriptorChain(uhci_td **isoRequest, uint32 packetCount, 2310 iovec *vector) 2311 { 2312 size_t vectorOffset = 0; 2313 for (uint32 i = 0; i < packetCount; i++) { 2314 size_t bufferSize = isoRequest[i]->buffer_size; 2315 memcpy((uint8 *)isoRequest[i]->buffer_log, 2316 (uint8 *)vector->iov_base + vectorOffset, bufferSize); 2317 vectorOffset += bufferSize; 2318 } 2319 } 2320 2321 2322 void 2323 UHCI::ReadIsochronousDescriptorChain(isochronous_transfer_data *transfer, 2324 iovec *vector) 2325 { 2326 size_t vectorOffset = 0; 2327 usb_isochronous_data *isochronousData 2328 = transfer->transfer->IsochronousData(); 2329 2330 for (uint32 i = 0; i < isochronousData->packet_count; i++) { 2331 uhci_td *current = transfer->descriptors[i]; 2332 2333 size_t bufferSize = current->buffer_size; 2334 size_t actualLength = uhci_td_actual_length(current); 2335 2336 isochronousData->packet_descriptors[i].actual_length = actualLength; 2337 2338 if (actualLength > 0) 2339 isochronousData->packet_descriptors[i].status = B_OK; 2340 else { 2341 isochronousData->packet_descriptors[i].status = B_ERROR; 2342 vectorOffset += bufferSize; 2343 continue; 2344 } 2345 memcpy((uint8 *)vector->iov_base + vectorOffset, 2346 (uint8 *)current->buffer_log, bufferSize); 2347 2348 vectorOffset += bufferSize; 2349 } 2350 } 2351 2352 2353 bool 2354 UHCI::LockIsochronous() 2355 { 2356 return (mutex_lock(&fIsochronousLock) == B_OK); 2357 } 2358 2359 2360 void 2361 UHCI::UnlockIsochronous() 2362 { 2363 mutex_unlock(&fIsochronousLock); 2364 } 2365 2366 2367 inline void 2368 UHCI::WriteReg8(uint32 reg, uint8 value) 2369 { 2370 sPCIModule->write_io_8(fRegisterBase + reg, value); 2371 } 2372 2373 2374 inline void 2375 UHCI::WriteReg16(uint32 reg, uint16 value) 2376 { 2377 sPCIModule->write_io_16(fRegisterBase + reg, value); 2378 } 2379 2380 2381 inline void 2382 UHCI::WriteReg32(uint32 reg, uint32 value) 2383 { 2384 sPCIModule->write_io_32(fRegisterBase + reg, value); 2385 } 2386 2387 2388 inline uint8 2389 UHCI::ReadReg8(uint32 reg) 2390 { 2391 return sPCIModule->read_io_8(fRegisterBase + reg); 2392 } 2393 2394 2395 inline uint16 2396 UHCI::ReadReg16(uint32 reg) 2397 { 2398 return sPCIModule->read_io_16(fRegisterBase + reg); 2399 } 2400 2401 2402 inline uint32 2403 UHCI::ReadReg32(uint32 reg) 2404 { 2405 return sPCIModule->read_io_32(fRegisterBase + reg); 2406 } 2407