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