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