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