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