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