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