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