1 /* 2 * Copyright 2005-2013, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jan-Rixt Van Hoye 7 * Salvatore Benedetto <salvatore.benedetto@gmail.com> 8 * Michael Lotz <mmlr@mlotz.ch> 9 * Siarzhuk Zharski <imker@gmx.li> 10 */ 11 12 #include <module.h> 13 #include <PCI.h> 14 #include <PCI_x86.h> 15 #include <USB3.h> 16 #include <KernelExport.h> 17 #include <util/AutoLock.h> 18 19 #include "ohci.h" 20 21 #define USB_MODULE_NAME "ohci" 22 23 pci_module_info *OHCI::sPCIModule = NULL; 24 pci_x86_module_info *OHCI::sPCIx86Module = NULL; 25 26 27 static int32 28 ohci_std_ops(int32 op, ...) 29 { 30 switch (op) { 31 case B_MODULE_INIT: 32 TRACE_MODULE("init module\n"); 33 return B_OK; 34 case B_MODULE_UNINIT: 35 TRACE_MODULE("uninit module\n"); 36 return B_OK; 37 } 38 39 return EINVAL; 40 } 41 42 43 usb_host_controller_info ohci_module = { 44 { 45 "busses/usb/ohci", 46 0, 47 ohci_std_ops 48 }, 49 NULL, 50 OHCI::AddTo 51 }; 52 53 54 module_info *modules[] = { 55 (module_info *)&ohci_module, 56 NULL 57 }; 58 59 60 // 61 // #pragma mark - 62 // 63 64 65 status_t 66 OHCI::AddTo(Stack *stack) 67 { 68 if (!sPCIModule) { 69 status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule); 70 if (status < B_OK) { 71 TRACE_MODULE_ERROR("getting pci module failed! 0x%08" B_PRIx32 "\n", 72 status); 73 return status; 74 } 75 } 76 77 TRACE_MODULE("searching devices\n"); 78 bool found = false; 79 pci_info *item = new(std::nothrow) pci_info; 80 if (!item) { 81 sPCIModule = NULL; 82 put_module(B_PCI_MODULE_NAME); 83 return B_NO_MEMORY; 84 } 85 86 // Try to get the PCI x86 module as well so we can enable possible MSIs. 87 if (sPCIx86Module == NULL && get_module(B_PCI_X86_MODULE_NAME, 88 (module_info **)&sPCIx86Module) != B_OK) { 89 // If it isn't there, that's not critical though. 90 TRACE_MODULE_ERROR("failed to get pci x86 module\n"); 91 sPCIx86Module = NULL; 92 } 93 94 for (uint32 i = 0 ; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) { 95 if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb 96 && item->class_api == PCI_usb_ohci) { 97 TRACE_MODULE("found device at PCI:%d:%d:%d\n", 98 item->bus, item->device, item->function); 99 OHCI *bus = new(std::nothrow) OHCI(item, stack); 100 if (bus == NULL) { 101 delete item; 102 put_module(B_PCI_MODULE_NAME); 103 if (sPCIx86Module != NULL) 104 put_module(B_PCI_X86_MODULE_NAME); 105 return B_NO_MEMORY; 106 } 107 108 // The bus will put the PCI modules when it is destroyed, so get 109 // them again to increase their reference count. 110 get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule); 111 if (sPCIx86Module != NULL) 112 get_module(B_PCI_X86_MODULE_NAME, (module_info **)&sPCIx86Module); 113 114 if (bus->InitCheck() < B_OK) { 115 TRACE_MODULE_ERROR("bus failed init check\n"); 116 delete bus; 117 continue; 118 } 119 120 // the bus took it away 121 item = new(std::nothrow) pci_info; 122 123 if (bus->Start() != B_OK) { 124 delete bus; 125 continue; 126 } 127 found = true; 128 } 129 } 130 131 // The modules will have been gotten again if we successfully 132 // initialized a bus, so we should put them here. 133 put_module(B_PCI_MODULE_NAME); 134 if (sPCIx86Module != NULL) 135 put_module(B_PCI_X86_MODULE_NAME); 136 137 if (!found) 138 TRACE_MODULE_ERROR("no devices found\n"); 139 delete item; 140 return found ? B_OK : ENODEV; 141 } 142 143 144 OHCI::OHCI(pci_info *info, Stack *stack) 145 : BusManager(stack), 146 fPCIInfo(info), 147 fStack(stack), 148 fOperationalRegisters(NULL), 149 fRegisterArea(-1), 150 fHccaArea(-1), 151 fHcca(NULL), 152 fInterruptEndpoints(NULL), 153 fDummyControl(NULL), 154 fDummyBulk(NULL), 155 fDummyIsochronous(NULL), 156 fFirstTransfer(NULL), 157 fLastTransfer(NULL), 158 fFinishTransfersSem(-1), 159 fFinishThread(-1), 160 fStopFinishThread(false), 161 fProcessingPipe(NULL), 162 fFrameBandwidth(NULL), 163 fRootHub(NULL), 164 fRootHubAddress(0), 165 fPortCount(0), 166 fIRQ(0), 167 fUseMSI(false) 168 { 169 if (!fInitOK) { 170 TRACE_ERROR("bus manager failed to init\n"); 171 return; 172 } 173 174 TRACE("constructing new OHCI host controller driver\n"); 175 fInitOK = false; 176 177 mutex_init(&fEndpointLock, "ohci endpoint lock"); 178 179 // enable busmaster and memory mapped access 180 uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus, 181 fPCIInfo->device, fPCIInfo->function, PCI_command, 2); 182 command &= ~PCI_command_io; 183 command |= PCI_command_master | PCI_command_memory; 184 185 sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, 186 fPCIInfo->function, PCI_command, 2, command); 187 188 // map the registers 189 uint32 offset = sPCIModule->read_pci_config(fPCIInfo->bus, 190 fPCIInfo->device, fPCIInfo->function, PCI_base_registers, 4); 191 offset &= PCI_address_memory_32_mask; 192 TRACE_ALWAYS("iospace offset: 0x%" B_PRIx32 "\n", offset); 193 fRegisterArea = map_physical_memory("OHCI memory mapped registers", 194 offset, B_PAGE_SIZE, B_ANY_KERNEL_BLOCK_ADDRESS, 195 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 196 (void **)&fOperationalRegisters); 197 if (fRegisterArea < B_OK) { 198 TRACE_ERROR("failed to map register memory\n"); 199 return; 200 } 201 202 TRACE("mapped operational registers: %p\n", fOperationalRegisters); 203 204 // Check the revision of the controller, which should be 10h 205 uint32 revision = _ReadReg(OHCI_REVISION) & 0xff; 206 TRACE("version %" B_PRId32 ".%" B_PRId32 "%s\n", 207 OHCI_REVISION_HIGH(revision), OHCI_REVISION_LOW(revision), 208 OHCI_REVISION_LEGACY(revision) ? ", legacy support" : ""); 209 210 if (OHCI_REVISION_HIGH(revision) != 1 || OHCI_REVISION_LOW(revision) != 0) { 211 TRACE_ERROR("unsupported OHCI revision\n"); 212 return; 213 } 214 215 phys_addr_t hccaPhysicalAddress; 216 fHccaArea = fStack->AllocateArea((void **)&fHcca, &hccaPhysicalAddress, 217 sizeof(ohci_hcca), "USB OHCI Host Controller Communication Area"); 218 219 if (fHccaArea < B_OK) { 220 TRACE_ERROR("unable to create the HCCA block area\n"); 221 return; 222 } 223 224 memset(fHcca, 0, sizeof(ohci_hcca)); 225 226 // Set Up Host controller 227 // Dummy endpoints 228 fDummyControl = _AllocateEndpoint(); 229 if (!fDummyControl) 230 return; 231 232 fDummyBulk = _AllocateEndpoint(); 233 if (!fDummyBulk) { 234 _FreeEndpoint(fDummyControl); 235 return; 236 } 237 238 fDummyIsochronous = _AllocateEndpoint(); 239 if (!fDummyIsochronous) { 240 _FreeEndpoint(fDummyControl); 241 _FreeEndpoint(fDummyBulk); 242 return; 243 } 244 245 // Static endpoints that get linked in the HCCA 246 fInterruptEndpoints = new(std::nothrow) 247 ohci_endpoint_descriptor *[OHCI_STATIC_ENDPOINT_COUNT]; 248 if (!fInterruptEndpoints) { 249 TRACE_ERROR("failed to allocate memory for interrupt endpoints\n"); 250 _FreeEndpoint(fDummyControl); 251 _FreeEndpoint(fDummyBulk); 252 _FreeEndpoint(fDummyIsochronous); 253 return; 254 } 255 256 for (int32 i = 0; i < OHCI_STATIC_ENDPOINT_COUNT; i++) { 257 fInterruptEndpoints[i] = _AllocateEndpoint(); 258 if (!fInterruptEndpoints[i]) { 259 TRACE_ERROR("failed to allocate interrupt endpoint %" B_PRId32 "\n", 260 i); 261 while (--i >= 0) 262 _FreeEndpoint(fInterruptEndpoints[i]); 263 _FreeEndpoint(fDummyBulk); 264 _FreeEndpoint(fDummyControl); 265 _FreeEndpoint(fDummyIsochronous); 266 return; 267 } 268 } 269 270 // build flat tree so that at each of the static interrupt endpoints 271 // fInterruptEndpoints[i] == interrupt endpoint for interval 2^i 272 uint32 interval = OHCI_BIGGEST_INTERVAL; 273 uint32 intervalIndex = OHCI_STATIC_ENDPOINT_COUNT - 1; 274 while (interval > 1) { 275 uint32 insertIndex = interval / 2; 276 while (insertIndex < OHCI_BIGGEST_INTERVAL) { 277 fHcca->interrupt_table[insertIndex] 278 = fInterruptEndpoints[intervalIndex]->physical_address; 279 insertIndex += interval; 280 } 281 282 intervalIndex--; 283 interval /= 2; 284 } 285 286 // setup the empty slot in the list and linking of all -> first 287 fHcca->interrupt_table[0] = fInterruptEndpoints[0]->physical_address; 288 for (int32 i = 1; i < OHCI_STATIC_ENDPOINT_COUNT; i++) { 289 fInterruptEndpoints[i]->next_physical_endpoint 290 = fInterruptEndpoints[0]->physical_address; 291 fInterruptEndpoints[i]->next_logical_endpoint 292 = fInterruptEndpoints[0]; 293 } 294 295 // Now link the first endpoint to the isochronous endpoint 296 fInterruptEndpoints[0]->next_physical_endpoint 297 = fDummyIsochronous->physical_address; 298 299 // When the handover from SMM takes place, all interrupts are routed to the 300 // OS. As we don't yet have an interrupt handler installed at this point, 301 // this may cause interrupt storms if the firmware does not disable the 302 // interrupts during handover. Therefore we disable interrupts before 303 // requesting ownership. We have to keep the ownership change interrupt 304 // enabled though, as otherwise the SMM will not be notified of the 305 // ownership change request we trigger below. 306 _WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTERRUPTS & 307 ~OHCI_OWNERSHIP_CHANGE) ; 308 309 // Determine in what context we are running (Kindly copied from FreeBSD) 310 uint32 control = _ReadReg(OHCI_CONTROL); 311 if (control & OHCI_INTERRUPT_ROUTING) { 312 TRACE_ALWAYS("smm is in control of the host controller\n"); 313 uint32 status = _ReadReg(OHCI_COMMAND_STATUS); 314 _WriteReg(OHCI_COMMAND_STATUS, status | OHCI_OWNERSHIP_CHANGE_REQUEST); 315 for (uint32 i = 0; i < 100 && (control & OHCI_INTERRUPT_ROUTING); i++) { 316 snooze(1000); 317 control = _ReadReg(OHCI_CONTROL); 318 } 319 320 if ((control & OHCI_INTERRUPT_ROUTING) != 0) { 321 TRACE_ERROR("smm does not respond.\n"); 322 323 // TODO: Enable this reset as soon as the non-specified 324 // reset a few lines later is replaced by a better solution. 325 //_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET); 326 //snooze(USB_DELAY_BUS_RESET); 327 } else 328 TRACE_ALWAYS("ownership change successful\n"); 329 } else { 330 TRACE("cold started\n"); 331 snooze(USB_DELAY_BUS_RESET); 332 } 333 334 // TODO: This reset delays system boot time. It should not be necessary 335 // according to the OHCI spec, but without it some controllers don't start. 336 _WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET); 337 snooze(USB_DELAY_BUS_RESET); 338 339 // We now own the host controller and the bus has been reset 340 uint32 frameInterval = _ReadReg(OHCI_FRAME_INTERVAL); 341 uint32 intervalValue = OHCI_GET_INTERVAL_VALUE(frameInterval); 342 343 _WriteReg(OHCI_COMMAND_STATUS, OHCI_HOST_CONTROLLER_RESET); 344 // Nominal time for a reset is 10 us 345 uint32 reset = 0; 346 for (uint32 i = 0; i < 10; i++) { 347 spin(10); 348 reset = _ReadReg(OHCI_COMMAND_STATUS) & OHCI_HOST_CONTROLLER_RESET; 349 if (reset == 0) 350 break; 351 } 352 353 if (reset) { 354 TRACE_ERROR("error resetting the host controller (timeout)\n"); 355 return; 356 } 357 358 // The controller is now in SUSPEND state, we have 2ms to go OPERATIONAL. 359 360 // Set up host controller register 361 _WriteReg(OHCI_HCCA, (uint32)hccaPhysicalAddress); 362 _WriteReg(OHCI_CONTROL_HEAD_ED, (uint32)fDummyControl->physical_address); 363 _WriteReg(OHCI_BULK_HEAD_ED, (uint32)fDummyBulk->physical_address); 364 // Switch on desired functional features 365 control = _ReadReg(OHCI_CONTROL); 366 control &= ~(OHCI_CONTROL_BULK_SERVICE_RATIO_MASK | OHCI_ENABLE_LIST 367 | OHCI_HC_FUNCTIONAL_STATE_MASK | OHCI_INTERRUPT_ROUTING); 368 control |= OHCI_ENABLE_LIST | OHCI_CONTROL_BULK_RATIO_1_4 369 | OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL; 370 // And finally start the controller 371 _WriteReg(OHCI_CONTROL, control); 372 373 // The controller is now OPERATIONAL. 374 frameInterval = (_ReadReg(OHCI_FRAME_INTERVAL) & OHCI_FRAME_INTERVAL_TOGGLE) 375 ^ OHCI_FRAME_INTERVAL_TOGGLE; 376 frameInterval |= OHCI_FSMPS(intervalValue) | intervalValue; 377 _WriteReg(OHCI_FRAME_INTERVAL, frameInterval); 378 // 90% periodic 379 uint32 periodic = OHCI_PERIODIC(intervalValue); 380 _WriteReg(OHCI_PERIODIC_START, periodic); 381 382 // Fiddle the No Over Current Protection bit to avoid chip bug 383 uint32 desca = _ReadReg(OHCI_RH_DESCRIPTOR_A); 384 _WriteReg(OHCI_RH_DESCRIPTOR_A, desca | OHCI_RH_NO_OVER_CURRENT_PROTECTION); 385 _WriteReg(OHCI_RH_STATUS, OHCI_RH_LOCAL_POWER_STATUS_CHANGE); 386 snooze(OHCI_ENABLE_POWER_DELAY); 387 _WriteReg(OHCI_RH_DESCRIPTOR_A, desca); 388 389 // The AMD756 requires a delay before re-reading the register, 390 // otherwise it will occasionally report 0 ports. 391 uint32 numberOfPorts = 0; 392 for (uint32 i = 0; i < 10 && numberOfPorts == 0; i++) { 393 snooze(OHCI_READ_DESC_DELAY); 394 uint32 descriptor = _ReadReg(OHCI_RH_DESCRIPTOR_A); 395 numberOfPorts = OHCI_RH_GET_PORT_COUNT(descriptor); 396 } 397 if (numberOfPorts > OHCI_MAX_PORT_COUNT) 398 numberOfPorts = OHCI_MAX_PORT_COUNT; 399 fPortCount = numberOfPorts; 400 TRACE("port count is %d\n", fPortCount); 401 402 // Create the array that will keep bandwidth information 403 fFrameBandwidth = new(std::nothrow) uint16[NUMBER_OF_FRAMES]; 404 405 for (int32 i = 0; i < NUMBER_OF_FRAMES; i++) 406 fFrameBandwidth[i] = MAX_AVAILABLE_BANDWIDTH; 407 408 // Create semaphore the finisher thread will wait for 409 fFinishTransfersSem = create_sem(0, "OHCI Finish Transfers"); 410 if (fFinishTransfersSem < B_OK) { 411 TRACE_ERROR("failed to create semaphore\n"); 412 return; 413 } 414 415 // Create the finisher service thread 416 fFinishThread = spawn_kernel_thread(_FinishThread, "ohci finish thread", 417 B_URGENT_DISPLAY_PRIORITY, (void *)this); 418 resume_thread(fFinishThread); 419 420 // Find the right interrupt vector, using MSIs if available. 421 fIRQ = fPCIInfo->u.h0.interrupt_line; 422 if (sPCIx86Module != NULL && sPCIx86Module->get_msi_count(fPCIInfo->bus, 423 fPCIInfo->device, fPCIInfo->function) >= 1) { 424 uint8 msiVector = 0; 425 if (sPCIx86Module->configure_msi(fPCIInfo->bus, fPCIInfo->device, 426 fPCIInfo->function, 1, &msiVector) == B_OK 427 && sPCIx86Module->enable_msi(fPCIInfo->bus, fPCIInfo->device, 428 fPCIInfo->function) == B_OK) { 429 TRACE_ALWAYS("using message signaled interrupts\n"); 430 fIRQ = msiVector; 431 fUseMSI = true; 432 } 433 } 434 435 if (fIRQ == 0 || fIRQ == 0xFF) { 436 TRACE_MODULE_ERROR("device PCI:%d:%d:%d was assigned an invalid IRQ\n", 437 fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function); 438 return; 439 } 440 441 // Install the interrupt handler 442 TRACE("installing interrupt handler\n"); 443 install_io_interrupt_handler(fIRQ, _InterruptHandler, (void *)this, 0); 444 445 // Enable interesting interrupts now that the handler is in place 446 _WriteReg(OHCI_INTERRUPT_ENABLE, OHCI_NORMAL_INTERRUPTS 447 | OHCI_MASTER_INTERRUPT_ENABLE); 448 449 TRACE("OHCI host controller driver constructed\n"); 450 fInitOK = true; 451 } 452 453 454 OHCI::~OHCI() 455 { 456 int32 result = 0; 457 fStopFinishThread = true; 458 delete_sem(fFinishTransfersSem); 459 wait_for_thread(fFinishThread, &result); 460 461 remove_io_interrupt_handler(fIRQ, _InterruptHandler, (void *)this); 462 463 _LockEndpoints(); 464 mutex_destroy(&fEndpointLock); 465 466 if (fHccaArea >= B_OK) 467 delete_area(fHccaArea); 468 if (fRegisterArea >= B_OK) 469 delete_area(fRegisterArea); 470 471 _FreeEndpoint(fDummyControl); 472 _FreeEndpoint(fDummyBulk); 473 _FreeEndpoint(fDummyIsochronous); 474 475 if (fInterruptEndpoints != NULL) { 476 for (int i = 0; i < OHCI_STATIC_ENDPOINT_COUNT; i++) 477 _FreeEndpoint(fInterruptEndpoints[i]); 478 } 479 480 delete [] fFrameBandwidth; 481 delete [] fInterruptEndpoints; 482 delete fRootHub; 483 484 if (fUseMSI && sPCIx86Module != NULL) { 485 sPCIx86Module->disable_msi(fPCIInfo->bus, 486 fPCIInfo->device, fPCIInfo->function); 487 sPCIx86Module->unconfigure_msi(fPCIInfo->bus, 488 fPCIInfo->device, fPCIInfo->function); 489 } 490 491 put_module(B_PCI_MODULE_NAME); 492 if (sPCIx86Module != NULL) 493 put_module(B_PCI_X86_MODULE_NAME); 494 } 495 496 497 status_t 498 OHCI::Start() 499 { 500 TRACE("starting OHCI host controller\n"); 501 502 uint32 control = _ReadReg(OHCI_CONTROL); 503 if ((control & OHCI_HC_FUNCTIONAL_STATE_MASK) 504 != OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL) { 505 TRACE_ERROR("controller not started (0x%08" B_PRIx32 ")!\n", control); 506 return B_ERROR; 507 } else 508 TRACE("controller is operational!\n"); 509 510 fRootHubAddress = AllocateAddress(); 511 fRootHub = new(std::nothrow) OHCIRootHub(RootObject(), fRootHubAddress); 512 if (!fRootHub) { 513 TRACE_ERROR("no memory to allocate root hub\n"); 514 return B_NO_MEMORY; 515 } 516 517 if (fRootHub->InitCheck() < B_OK) { 518 TRACE_ERROR("root hub failed init check\n"); 519 return B_ERROR; 520 } 521 522 SetRootHub(fRootHub); 523 TRACE_ALWAYS("successfully started the controller\n"); 524 return BusManager::Start(); 525 } 526 527 528 status_t 529 OHCI::SubmitTransfer(Transfer *transfer) 530 { 531 // short circuit the root hub 532 if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress) 533 return fRootHub->ProcessTransfer(this, transfer); 534 535 uint32 type = transfer->TransferPipe()->Type(); 536 if (type & USB_OBJECT_CONTROL_PIPE) { 537 TRACE("submitting request\n"); 538 return _SubmitRequest(transfer); 539 } 540 541 if ((type & USB_OBJECT_BULK_PIPE) || (type & USB_OBJECT_INTERRUPT_PIPE)) { 542 TRACE("submitting %s transfer\n", 543 (type & USB_OBJECT_BULK_PIPE) ? "bulk" : "interrupt"); 544 return _SubmitTransfer(transfer); 545 } 546 547 if (type & USB_OBJECT_ISO_PIPE) { 548 TRACE("submitting isochronous transfer\n"); 549 return _SubmitIsochronousTransfer(transfer); 550 } 551 552 TRACE_ERROR("tried to submit transfer for unknown pipe type %" B_PRIu32 "\n", 553 type); 554 return B_ERROR; 555 } 556 557 558 status_t 559 OHCI::CancelQueuedTransfers(Pipe *pipe, bool force) 560 { 561 if (!Lock()) 562 return B_ERROR; 563 564 struct transfer_entry { 565 Transfer * transfer; 566 transfer_entry * next; 567 }; 568 569 transfer_entry *list = NULL; 570 transfer_data *current = fFirstTransfer; 571 while (current) { 572 if (current->transfer && current->transfer->TransferPipe() == pipe) { 573 // Check if the skip bit is already set 574 if (!(current->endpoint->flags & OHCI_ENDPOINT_SKIP)) { 575 current->endpoint->flags |= OHCI_ENDPOINT_SKIP; 576 // In case the controller is processing 577 // this endpoint, wait for it to finish 578 snooze(1000); 579 } 580 581 // Clear the endpoint 582 current->endpoint->head_physical_descriptor 583 = current->endpoint->tail_physical_descriptor; 584 585 if (!force) { 586 if (pipe->Type() & USB_OBJECT_ISO_PIPE) { 587 ohci_isochronous_td *descriptor 588 = (ohci_isochronous_td *)current->first_descriptor; 589 while (descriptor) { 590 uint16 frame = OHCI_ITD_GET_STARTING_FRAME( 591 descriptor->flags); 592 _ReleaseIsochronousBandwidth(frame, 593 OHCI_ITD_GET_FRAME_COUNT(descriptor->flags)); 594 if (descriptor 595 == (ohci_isochronous_td*)current->last_descriptor) 596 // this is the last ITD of the transfer 597 break; 598 599 descriptor 600 = (ohci_isochronous_td *) 601 descriptor->next_done_descriptor; 602 } 603 } 604 605 // If the transfer is canceled by force, the one causing the 606 // cancel is probably not the one who initiated the transfer 607 // and the callback is likely not safe anymore 608 transfer_entry *entry 609 = (transfer_entry *)malloc(sizeof(transfer_entry)); 610 if (entry != NULL) { 611 entry->transfer = current->transfer; 612 current->transfer = NULL; 613 entry->next = list; 614 list = entry; 615 } 616 } 617 current->canceled = true; 618 } 619 current = current->link; 620 } 621 622 Unlock(); 623 624 while (list != NULL) { 625 transfer_entry *next = list->next; 626 list->transfer->Finished(B_CANCELED, 0); 627 delete list->transfer; 628 free(list); 629 list = next; 630 } 631 632 // wait for any transfers that might have made it before canceling 633 while (fProcessingPipe == pipe) 634 snooze(1000); 635 636 // notify the finisher so it can clean up the canceled transfers 637 release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE); 638 return B_OK; 639 } 640 641 642 status_t 643 OHCI::NotifyPipeChange(Pipe *pipe, usb_change change) 644 { 645 TRACE("pipe change %d for pipe %p\n", change, pipe); 646 if (pipe->DeviceAddress() == fRootHubAddress) { 647 // no need to insert/remove endpoint descriptors for the root hub 648 return B_OK; 649 } 650 651 switch (change) { 652 case USB_CHANGE_CREATED: 653 return _InsertEndpointForPipe(pipe); 654 655 case USB_CHANGE_DESTROYED: 656 return _RemoveEndpointForPipe(pipe); 657 658 case USB_CHANGE_PIPE_POLICY_CHANGED: 659 TRACE("pipe policy changing unhandled!\n"); 660 break; 661 662 default: 663 TRACE_ERROR("unknown pipe change!\n"); 664 return B_ERROR; 665 } 666 667 return B_OK; 668 } 669 670 671 status_t 672 OHCI::GetPortStatus(uint8 index, usb_port_status *status) 673 { 674 if (index >= fPortCount) { 675 TRACE_ERROR("get port status for invalid port %u\n", index); 676 return B_BAD_INDEX; 677 } 678 679 status->status = status->change = 0; 680 uint32 portStatus = _ReadReg(OHCI_RH_PORT_STATUS(index)); 681 682 // status 683 if (portStatus & OHCI_RH_PORTSTATUS_CCS) 684 status->status |= PORT_STATUS_CONNECTION; 685 if (portStatus & OHCI_RH_PORTSTATUS_PES) 686 status->status |= PORT_STATUS_ENABLE; 687 if (portStatus & OHCI_RH_PORTSTATUS_PSS) 688 status->status |= PORT_STATUS_SUSPEND; 689 if (portStatus & OHCI_RH_PORTSTATUS_POCI) 690 status->status |= PORT_STATUS_OVER_CURRENT; 691 if (portStatus & OHCI_RH_PORTSTATUS_PRS) 692 status->status |= PORT_STATUS_RESET; 693 if (portStatus & OHCI_RH_PORTSTATUS_PPS) 694 status->status |= PORT_STATUS_POWER; 695 if (portStatus & OHCI_RH_PORTSTATUS_LSDA) 696 status->status |= PORT_STATUS_LOW_SPEED; 697 698 // change 699 if (portStatus & OHCI_RH_PORTSTATUS_CSC) 700 status->change |= PORT_STATUS_CONNECTION; 701 if (portStatus & OHCI_RH_PORTSTATUS_PESC) 702 status->change |= PORT_STATUS_ENABLE; 703 if (portStatus & OHCI_RH_PORTSTATUS_PSSC) 704 status->change |= PORT_STATUS_SUSPEND; 705 if (portStatus & OHCI_RH_PORTSTATUS_OCIC) 706 status->change |= PORT_STATUS_OVER_CURRENT; 707 if (portStatus & OHCI_RH_PORTSTATUS_PRSC) 708 status->change |= PORT_STATUS_RESET; 709 710 TRACE("port %u status 0x%04x change 0x%04x\n", index, 711 status->status, status->change); 712 return B_OK; 713 } 714 715 716 status_t 717 OHCI::SetPortFeature(uint8 index, uint16 feature) 718 { 719 TRACE("set port feature index %u feature %u\n", index, feature); 720 if (index > fPortCount) 721 return B_BAD_INDEX; 722 723 switch (feature) { 724 case PORT_ENABLE: 725 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PES); 726 return B_OK; 727 728 case PORT_SUSPEND: 729 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PSS); 730 return B_OK; 731 732 case PORT_RESET: 733 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PRS); 734 return B_OK; 735 736 case PORT_POWER: 737 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PPS); 738 return B_OK; 739 } 740 741 return B_BAD_VALUE; 742 } 743 744 745 status_t 746 OHCI::ClearPortFeature(uint8 index, uint16 feature) 747 { 748 TRACE("clear port feature index %u feature %u\n", index, feature); 749 if (index > fPortCount) 750 return B_BAD_INDEX; 751 752 switch (feature) { 753 case PORT_ENABLE: 754 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_CCS); 755 return B_OK; 756 757 case PORT_SUSPEND: 758 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_POCI); 759 return B_OK; 760 761 case PORT_POWER: 762 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_LSDA); 763 return B_OK; 764 765 case C_PORT_CONNECTION: 766 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_CSC); 767 return B_OK; 768 769 case C_PORT_ENABLE: 770 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PESC); 771 return B_OK; 772 773 case C_PORT_SUSPEND: 774 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PSSC); 775 return B_OK; 776 777 case C_PORT_OVER_CURRENT: 778 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_OCIC); 779 return B_OK; 780 781 case C_PORT_RESET: 782 _WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_RH_PORTSTATUS_PRSC); 783 return B_OK; 784 } 785 786 return B_BAD_VALUE; 787 } 788 789 790 int32 791 OHCI::_InterruptHandler(void *data) 792 { 793 return ((OHCI *)data)->_Interrupt(); 794 } 795 796 797 int32 798 OHCI::_Interrupt() 799 { 800 static spinlock lock = B_SPINLOCK_INITIALIZER; 801 acquire_spinlock(&lock); 802 803 uint32 status = 0; 804 uint32 acknowledge = 0; 805 bool finishTransfers = false; 806 int32 result = B_HANDLED_INTERRUPT; 807 808 // The LSb of done_head is used to inform the HCD that an interrupt 809 // condition exists for both the done list and for another event recorded in 810 // the HcInterruptStatus register. If done_head is 0, then the interrupt 811 // was caused by other than the HccaDoneHead update and the 812 // HcInterruptStatus register needs to be accessed to determine that exact 813 // interrupt cause. If HccDoneHead is nonzero, then a done list update 814 // interrupt is indicated and if the LSb of the Dword is nonzero, then an 815 // additional interrupt event is indicated and HcInterruptStatus should be 816 // checked to determine its cause. 817 uint32 doneHead = fHcca->done_head; 818 if (doneHead != 0) { 819 status = OHCI_WRITEBACK_DONE_HEAD; 820 if (doneHead & OHCI_DONE_INTERRUPTS) 821 status |= _ReadReg(OHCI_INTERRUPT_STATUS) 822 & _ReadReg(OHCI_INTERRUPT_ENABLE); 823 } else { 824 status = _ReadReg(OHCI_INTERRUPT_STATUS) & _ReadReg(OHCI_INTERRUPT_ENABLE) 825 & ~OHCI_WRITEBACK_DONE_HEAD; 826 if (status == 0) { 827 // Nothing to be done (PCI shared interrupt) 828 release_spinlock(&lock); 829 return B_UNHANDLED_INTERRUPT; 830 } 831 } 832 833 if (status & OHCI_SCHEDULING_OVERRUN) { 834 TRACE_MODULE("scheduling overrun occured\n"); 835 acknowledge |= OHCI_SCHEDULING_OVERRUN; 836 } 837 838 if (status & OHCI_WRITEBACK_DONE_HEAD) { 839 TRACE_MODULE("transfer descriptors processed\n"); 840 fHcca->done_head = 0; 841 acknowledge |= OHCI_WRITEBACK_DONE_HEAD; 842 result = B_INVOKE_SCHEDULER; 843 finishTransfers = true; 844 } 845 846 if (status & OHCI_RESUME_DETECTED) { 847 TRACE_MODULE("resume detected\n"); 848 acknowledge |= OHCI_RESUME_DETECTED; 849 } 850 851 if (status & OHCI_UNRECOVERABLE_ERROR) { 852 TRACE_MODULE_ERROR("unrecoverable error - controller halted\n"); 853 _WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET); 854 // TODO: clear all pending transfers, reset and resetup the controller 855 } 856 857 if (status & OHCI_ROOT_HUB_STATUS_CHANGE) { 858 TRACE_MODULE("root hub status change\n"); 859 // Disable the interrupt as it will otherwise be retriggered until the 860 // port has been reset and the change is cleared explicitly. 861 // TODO: renable it once we use status changes instead of polling 862 _WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ROOT_HUB_STATUS_CHANGE); 863 acknowledge |= OHCI_ROOT_HUB_STATUS_CHANGE; 864 } 865 866 if (acknowledge != 0) 867 _WriteReg(OHCI_INTERRUPT_STATUS, acknowledge); 868 869 release_spinlock(&lock); 870 871 if (finishTransfers) 872 release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE); 873 874 return result; 875 } 876 877 878 status_t 879 OHCI::_AddPendingTransfer(Transfer *transfer, 880 ohci_endpoint_descriptor *endpoint, ohci_general_td *firstDescriptor, 881 ohci_general_td *dataDescriptor, ohci_general_td *lastDescriptor, 882 bool directionIn) 883 { 884 if (!transfer || !endpoint || !lastDescriptor) 885 return B_BAD_VALUE; 886 887 transfer_data *data = new(std::nothrow) transfer_data; 888 if (!data) 889 return B_NO_MEMORY; 890 891 status_t result = transfer->InitKernelAccess(); 892 if (result < B_OK) { 893 delete data; 894 return result; 895 } 896 897 data->transfer = transfer; 898 data->endpoint = endpoint; 899 data->incoming = directionIn; 900 data->canceled = false; 901 data->link = NULL; 902 903 // the current tail will become the first descriptor 904 data->first_descriptor = (ohci_general_td *)endpoint->tail_logical_descriptor; 905 906 // the data and first descriptors might be the same 907 if (dataDescriptor == firstDescriptor) 908 data->data_descriptor = data->first_descriptor; 909 else 910 data->data_descriptor = dataDescriptor; 911 912 // even the last and the first descriptor might be the same 913 if (lastDescriptor == firstDescriptor) 914 data->last_descriptor = data->first_descriptor; 915 else 916 data->last_descriptor = lastDescriptor; 917 918 if (!Lock()) { 919 delete data; 920 return B_ERROR; 921 } 922 923 if (fLastTransfer) 924 fLastTransfer->link = data; 925 else 926 fFirstTransfer = data; 927 928 fLastTransfer = data; 929 Unlock(); 930 931 return B_OK; 932 } 933 934 935 status_t 936 OHCI::_AddPendingIsochronousTransfer(Transfer *transfer, 937 ohci_endpoint_descriptor *endpoint, ohci_isochronous_td *firstDescriptor, 938 ohci_isochronous_td *lastDescriptor, bool directionIn) 939 { 940 if (!transfer || !endpoint || !lastDescriptor) 941 return B_BAD_VALUE; 942 943 transfer_data *data = new(std::nothrow) transfer_data; 944 if (!data) 945 return B_NO_MEMORY; 946 947 status_t result = transfer->InitKernelAccess(); 948 if (result < B_OK) { 949 delete data; 950 return result; 951 } 952 953 data->transfer = transfer; 954 data->endpoint = endpoint; 955 data->incoming = directionIn; 956 data->canceled = false; 957 data->link = NULL; 958 959 // the current tail will become the first descriptor 960 data->first_descriptor = (ohci_general_td*)endpoint->tail_logical_descriptor; 961 962 // the data and first descriptors are the same 963 data->data_descriptor = data->first_descriptor; 964 965 // the last and the first descriptor might be the same 966 if (lastDescriptor == firstDescriptor) 967 data->last_descriptor = data->first_descriptor; 968 else 969 data->last_descriptor = (ohci_general_td*)lastDescriptor; 970 971 if (!Lock()) { 972 delete data; 973 return B_ERROR; 974 } 975 976 if (fLastTransfer) 977 fLastTransfer->link = data; 978 else 979 fFirstTransfer = data; 980 981 fLastTransfer = data; 982 Unlock(); 983 984 return B_OK; 985 } 986 987 988 int32 989 OHCI::_FinishThread(void *data) 990 { 991 ((OHCI *)data)->_FinishTransfers(); 992 return B_OK; 993 } 994 995 996 void 997 OHCI::_FinishTransfers() 998 { 999 while (!fStopFinishThread) { 1000 if (acquire_sem(fFinishTransfersSem) < B_OK) 1001 continue; 1002 1003 // eat up sems that have been released by multiple interrupts 1004 int32 semCount = 0; 1005 get_sem_count(fFinishTransfersSem, &semCount); 1006 if (semCount > 0) 1007 acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0); 1008 1009 if (!Lock()) 1010 continue; 1011 1012 TRACE("finishing transfers (first transfer: %p; last" 1013 " transfer: %p)\n", fFirstTransfer, fLastTransfer); 1014 transfer_data *lastTransfer = NULL; 1015 transfer_data *transfer = fFirstTransfer; 1016 Unlock(); 1017 1018 while (transfer) { 1019 bool transferDone = false; 1020 ohci_general_td *descriptor = transfer->first_descriptor; 1021 ohci_endpoint_descriptor *endpoint = transfer->endpoint; 1022 status_t callbackStatus = B_OK; 1023 1024 if (endpoint->flags & OHCI_ENDPOINT_ISOCHRONOUS_FORMAT) { 1025 transfer_data *next = transfer->link; 1026 if (_FinishIsochronousTransfer(transfer, &lastTransfer)) { 1027 delete transfer->transfer; 1028 delete transfer; 1029 } 1030 transfer = next; 1031 continue; 1032 } 1033 1034 MutexLocker endpointLocker(endpoint->lock); 1035 1036 if ((endpoint->head_physical_descriptor & OHCI_ENDPOINT_HEAD_MASK) 1037 != endpoint->tail_physical_descriptor 1038 && (endpoint->head_physical_descriptor 1039 & OHCI_ENDPOINT_HALTED) == 0) { 1040 // there are still active transfers on this endpoint, we need 1041 // to wait for all of them to complete, otherwise we'd read 1042 // a potentially bogus data toggle value below 1043 TRACE("endpoint %p still has active tds\n", endpoint); 1044 lastTransfer = transfer; 1045 transfer = transfer->link; 1046 continue; 1047 } 1048 1049 endpointLocker.Unlock(); 1050 1051 while (descriptor && !transfer->canceled) { 1052 uint32 status = OHCI_TD_GET_CONDITION_CODE(descriptor->flags); 1053 if (status == OHCI_TD_CONDITION_NOT_ACCESSED) { 1054 // td is still active 1055 TRACE("td %p still active\n", descriptor); 1056 break; 1057 } 1058 1059 if (status != OHCI_TD_CONDITION_NO_ERROR) { 1060 // an error occured, but we must ensure that the td 1061 // was actually done 1062 if (endpoint->head_physical_descriptor & OHCI_ENDPOINT_HALTED) { 1063 // the endpoint is halted, this guaratees us that this 1064 // descriptor has passed (we don't know if the endpoint 1065 // was halted because of this td, but we do not need 1066 // to know, as when it was halted by another td this 1067 // still ensures that this td was handled before). 1068 TRACE_ERROR("td error: 0x%08" B_PRIx32 "\n", status); 1069 1070 callbackStatus = _GetStatusOfConditionCode(status); 1071 1072 transferDone = true; 1073 break; 1074 } else { 1075 // an error occured but the endpoint is not halted so 1076 // the td is in fact still active 1077 TRACE("td %p active with error\n", descriptor); 1078 break; 1079 } 1080 } 1081 1082 // the td has completed without an error 1083 TRACE("td %p done\n", descriptor); 1084 1085 if (descriptor == transfer->last_descriptor 1086 || descriptor->buffer_physical != 0) { 1087 // this is the last td of the transfer or a short packet 1088 callbackStatus = B_OK; 1089 transferDone = true; 1090 break; 1091 } 1092 1093 descriptor 1094 = (ohci_general_td *)descriptor->next_logical_descriptor; 1095 } 1096 1097 if (transfer->canceled) { 1098 // when a transfer is canceled, all transfers to that endpoint 1099 // are canceled by setting the head pointer to the tail pointer 1100 // which causes all of the tds to become "free" (as they are 1101 // inaccessible and not accessed anymore (as setting the head 1102 // pointer required disabling the endpoint)) 1103 callbackStatus = B_OK; 1104 transferDone = true; 1105 } 1106 1107 if (!transferDone) { 1108 lastTransfer = transfer; 1109 transfer = transfer->link; 1110 continue; 1111 } 1112 1113 // remove the transfer from the list first so we are sure 1114 // it doesn't get canceled while we still process it 1115 transfer_data *next = transfer->link; 1116 if (Lock()) { 1117 if (lastTransfer) 1118 lastTransfer->link = transfer->link; 1119 1120 if (transfer == fFirstTransfer) 1121 fFirstTransfer = transfer->link; 1122 if (transfer == fLastTransfer) 1123 fLastTransfer = lastTransfer; 1124 1125 // store the currently processing pipe here so we can wait 1126 // in cancel if we are processing something on the target pipe 1127 if (!transfer->canceled) 1128 fProcessingPipe = transfer->transfer->TransferPipe(); 1129 1130 transfer->link = NULL; 1131 Unlock(); 1132 } 1133 1134 // break the descriptor chain on the last descriptor 1135 transfer->last_descriptor->next_logical_descriptor = NULL; 1136 TRACE("transfer %p done with status 0x%08" B_PRIx32 "\n", 1137 transfer, callbackStatus); 1138 1139 // if canceled the callback has already been called 1140 if (!transfer->canceled) { 1141 size_t actualLength = 0; 1142 if (callbackStatus == B_OK) { 1143 if (transfer->data_descriptor && transfer->incoming) { 1144 // data to read out 1145 iovec *vector = transfer->transfer->Vector(); 1146 size_t vectorCount = transfer->transfer->VectorCount(); 1147 1148 transfer->transfer->PrepareKernelAccess(); 1149 actualLength = _ReadDescriptorChain( 1150 transfer->data_descriptor, 1151 vector, vectorCount); 1152 } else if (transfer->data_descriptor) { 1153 // read the actual length that was sent 1154 actualLength = _ReadActualLength( 1155 transfer->data_descriptor); 1156 } 1157 1158 // get the last data toggle and store it for next time 1159 transfer->transfer->TransferPipe()->SetDataToggle( 1160 (endpoint->head_physical_descriptor 1161 & OHCI_ENDPOINT_TOGGLE_CARRY) != 0); 1162 1163 if (transfer->transfer->IsFragmented()) { 1164 // this transfer may still have data left 1165 TRACE("advancing fragmented transfer\n"); 1166 transfer->transfer->AdvanceByFragment(actualLength); 1167 if (transfer->transfer->VectorLength() > 0) { 1168 TRACE("still %ld bytes left on transfer\n", 1169 transfer->transfer->VectorLength()); 1170 // TODO actually resubmit the transfer 1171 } 1172 1173 // the transfer is done, but we already set the 1174 // actualLength with AdvanceByFragment() 1175 actualLength = 0; 1176 } 1177 } 1178 1179 transfer->transfer->Finished(callbackStatus, actualLength); 1180 fProcessingPipe = NULL; 1181 } 1182 1183 if (callbackStatus != B_OK) { 1184 // remove the transfer and make the head pointer valid again 1185 // (including clearing the halt state) 1186 _RemoveTransferFromEndpoint(transfer); 1187 } 1188 1189 // free the descriptors 1190 _FreeDescriptorChain(transfer->first_descriptor); 1191 1192 delete transfer->transfer; 1193 delete transfer; 1194 transfer = next; 1195 } 1196 } 1197 } 1198 1199 1200 bool 1201 OHCI::_FinishIsochronousTransfer(transfer_data *transfer, 1202 transfer_data **_lastTransfer) 1203 { 1204 status_t callbackStatus = B_OK; 1205 size_t actualLength = 0; 1206 uint32 packet = 0; 1207 1208 if (transfer->canceled) 1209 callbackStatus = B_CANCELED; 1210 else { 1211 // at first check if ALL ITDs are retired by HC 1212 ohci_isochronous_td *descriptor 1213 = (ohci_isochronous_td *)transfer->first_descriptor; 1214 while (descriptor) { 1215 if (OHCI_TD_GET_CONDITION_CODE(descriptor->flags) 1216 == OHCI_TD_CONDITION_NOT_ACCESSED) { 1217 TRACE("ITD %p still active\n", descriptor); 1218 *_lastTransfer = transfer; 1219 return false; 1220 } 1221 1222 if (descriptor == (ohci_isochronous_td*)transfer->last_descriptor) { 1223 // this is the last ITD of the transfer 1224 descriptor = (ohci_isochronous_td *)transfer->first_descriptor; 1225 break; 1226 } 1227 1228 descriptor 1229 = (ohci_isochronous_td *)descriptor->next_done_descriptor; 1230 } 1231 1232 while (descriptor) { 1233 uint32 status = OHCI_TD_GET_CONDITION_CODE(descriptor->flags); 1234 if (status != OHCI_TD_CONDITION_NO_ERROR) { 1235 TRACE_ERROR("ITD error: 0x%08" B_PRIx32 "\n", status); 1236 // spec says that in most cases condition code 1237 // of retired ITDs is set to NoError, but for the 1238 // time overrun it can be DataOverrun. We assume 1239 // the _first_ occurience of such error as status 1240 // reported to the callback 1241 if (callbackStatus == B_OK) 1242 callbackStatus = _GetStatusOfConditionCode(status); 1243 } 1244 1245 usb_isochronous_data *isochronousData 1246 = transfer->transfer->IsochronousData(); 1247 1248 uint32 frameCount = OHCI_ITD_GET_FRAME_COUNT(descriptor->flags); 1249 for (size_t i = 0; i < frameCount; i++, packet++) { 1250 usb_iso_packet_descriptor* packet_descriptor 1251 = &isochronousData->packet_descriptors[packet]; 1252 1253 uint16 offset = descriptor->offset[OHCI_ITD_OFFSET_IDX(i)]; 1254 uint8 code = OHCI_ITD_GET_BUFFER_CONDITION_CODE(offset); 1255 packet_descriptor->status = _GetStatusOfConditionCode(code); 1256 1257 // not touched by HC - sheduled too late to be processed 1258 // in the requested frame - so we ignore it too 1259 if (packet_descriptor->status == B_DEV_TOO_LATE) 1260 continue; 1261 1262 size_t len = OHCI_ITD_GET_BUFFER_LENGTH(offset); 1263 if (!transfer->incoming) 1264 len = packet_descriptor->request_length - len; 1265 1266 packet_descriptor->actual_length = len; 1267 actualLength += len; 1268 } 1269 1270 uint16 frame = OHCI_ITD_GET_STARTING_FRAME(descriptor->flags); 1271 _ReleaseIsochronousBandwidth(frame, 1272 OHCI_ITD_GET_FRAME_COUNT(descriptor->flags)); 1273 1274 TRACE("ITD %p done\n", descriptor); 1275 1276 if (descriptor == (ohci_isochronous_td*)transfer->last_descriptor) 1277 break; 1278 1279 descriptor 1280 = (ohci_isochronous_td *)descriptor->next_done_descriptor; 1281 } 1282 } 1283 1284 // remove the transfer from the list first so we are sure 1285 // it doesn't get canceled while we still process it 1286 if (Lock()) { 1287 if (*_lastTransfer) 1288 (*_lastTransfer)->link = transfer->link; 1289 1290 if (transfer == fFirstTransfer) 1291 fFirstTransfer = transfer->link; 1292 if (transfer == fLastTransfer) 1293 fLastTransfer = *_lastTransfer; 1294 1295 // store the currently processing pipe here so we can wait 1296 // in cancel if we are processing something on the target pipe 1297 if (!transfer->canceled) 1298 fProcessingPipe = transfer->transfer->TransferPipe(); 1299 1300 transfer->link = NULL; 1301 Unlock(); 1302 } 1303 1304 // break the descriptor chain on the last descriptor 1305 transfer->last_descriptor->next_logical_descriptor = NULL; 1306 TRACE("iso.transfer %p done with status 0x%08" B_PRIx32 " len:%ld\n", 1307 transfer, callbackStatus, actualLength); 1308 1309 // if canceled the callback has already been called 1310 if (!transfer->canceled) { 1311 if (callbackStatus == B_OK && actualLength > 0) { 1312 if (transfer->data_descriptor && transfer->incoming) { 1313 // data to read out 1314 iovec *vector = transfer->transfer->Vector(); 1315 size_t vectorCount = transfer->transfer->VectorCount(); 1316 1317 transfer->transfer->PrepareKernelAccess(); 1318 _ReadIsochronousDescriptorChain( 1319 (ohci_isochronous_td*)transfer->data_descriptor, 1320 vector, vectorCount); 1321 } 1322 } 1323 1324 transfer->transfer->Finished(callbackStatus, actualLength); 1325 fProcessingPipe = NULL; 1326 } 1327 1328 _FreeIsochronousDescriptorChain( 1329 (ohci_isochronous_td*)transfer->first_descriptor); 1330 1331 return true; 1332 } 1333 1334 1335 status_t 1336 OHCI::_SubmitRequest(Transfer *transfer) 1337 { 1338 usb_request_data *requestData = transfer->RequestData(); 1339 bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) != 0; 1340 1341 ohci_general_td *setupDescriptor 1342 = _CreateGeneralDescriptor(sizeof(usb_request_data)); 1343 if (!setupDescriptor) { 1344 TRACE_ERROR("failed to allocate setup descriptor\n"); 1345 return B_NO_MEMORY; 1346 } 1347 1348 setupDescriptor->flags = OHCI_TD_DIRECTION_PID_SETUP 1349 | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) 1350 | OHCI_TD_TOGGLE_0 1351 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE); 1352 1353 ohci_general_td *statusDescriptor = _CreateGeneralDescriptor(0); 1354 if (!statusDescriptor) { 1355 TRACE_ERROR("failed to allocate status descriptor\n"); 1356 _FreeGeneralDescriptor(setupDescriptor); 1357 return B_NO_MEMORY; 1358 } 1359 1360 statusDescriptor->flags 1361 = (directionIn ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN) 1362 | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) 1363 | OHCI_TD_TOGGLE_1 1364 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE); 1365 1366 iovec vector; 1367 vector.iov_base = requestData; 1368 vector.iov_len = sizeof(usb_request_data); 1369 _WriteDescriptorChain(setupDescriptor, &vector, 1); 1370 1371 status_t result; 1372 ohci_general_td *dataDescriptor = NULL; 1373 if (transfer->VectorCount() > 0) { 1374 ohci_general_td *lastDescriptor = NULL; 1375 result = _CreateDescriptorChain(&dataDescriptor, &lastDescriptor, 1376 directionIn ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT, 1377 transfer->VectorLength()); 1378 if (result < B_OK) { 1379 _FreeGeneralDescriptor(setupDescriptor); 1380 _FreeGeneralDescriptor(statusDescriptor); 1381 return result; 1382 } 1383 1384 if (!directionIn) { 1385 _WriteDescriptorChain(dataDescriptor, transfer->Vector(), 1386 transfer->VectorCount()); 1387 } 1388 1389 _LinkDescriptors(setupDescriptor, dataDescriptor); 1390 _LinkDescriptors(lastDescriptor, statusDescriptor); 1391 } else { 1392 _LinkDescriptors(setupDescriptor, statusDescriptor); 1393 } 1394 1395 // Add to the transfer list 1396 ohci_endpoint_descriptor *endpoint 1397 = (ohci_endpoint_descriptor *)transfer->TransferPipe()->ControllerCookie(); 1398 1399 MutexLocker endpointLocker(endpoint->lock); 1400 result = _AddPendingTransfer(transfer, endpoint, setupDescriptor, 1401 dataDescriptor, statusDescriptor, directionIn); 1402 if (result < B_OK) { 1403 TRACE_ERROR("failed to add pending transfer\n"); 1404 _FreeDescriptorChain(setupDescriptor); 1405 return result; 1406 } 1407 1408 // Add the descriptor chain to the endpoint 1409 _SwitchEndpointTail(endpoint, setupDescriptor, statusDescriptor); 1410 endpointLocker.Unlock(); 1411 1412 // Tell the controller to process the control list 1413 endpoint->flags &= ~OHCI_ENDPOINT_SKIP; 1414 _WriteReg(OHCI_COMMAND_STATUS, OHCI_CONTROL_LIST_FILLED); 1415 return B_OK; 1416 } 1417 1418 1419 status_t 1420 OHCI::_SubmitTransfer(Transfer *transfer) 1421 { 1422 Pipe *pipe = transfer->TransferPipe(); 1423 bool directionIn = (pipe->Direction() == Pipe::In); 1424 1425 ohci_general_td *firstDescriptor = NULL; 1426 ohci_general_td *lastDescriptor = NULL; 1427 status_t result = _CreateDescriptorChain(&firstDescriptor, &lastDescriptor, 1428 directionIn ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT, 1429 transfer->VectorLength()); 1430 1431 if (result < B_OK) 1432 return result; 1433 1434 // Apply data toggle to the first descriptor (the others will use the carry) 1435 firstDescriptor->flags &= ~OHCI_TD_TOGGLE_CARRY; 1436 firstDescriptor->flags |= pipe->DataToggle() ? OHCI_TD_TOGGLE_1 1437 : OHCI_TD_TOGGLE_0; 1438 1439 // Set the last descriptor to generate an interrupt 1440 lastDescriptor->flags &= ~OHCI_TD_INTERRUPT_MASK; 1441 lastDescriptor->flags |= 1442 OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE); 1443 1444 if (!directionIn) { 1445 _WriteDescriptorChain(firstDescriptor, transfer->Vector(), 1446 transfer->VectorCount()); 1447 } 1448 1449 // Add to the transfer list 1450 ohci_endpoint_descriptor *endpoint 1451 = (ohci_endpoint_descriptor *)pipe->ControllerCookie(); 1452 1453 MutexLocker endpointLocker(endpoint->lock); 1454 result = _AddPendingTransfer(transfer, endpoint, firstDescriptor, 1455 firstDescriptor, lastDescriptor, directionIn); 1456 if (result < B_OK) { 1457 TRACE_ERROR("failed to add pending transfer\n"); 1458 _FreeDescriptorChain(firstDescriptor); 1459 return result; 1460 } 1461 1462 // Add the descriptor chain to the endpoint 1463 _SwitchEndpointTail(endpoint, firstDescriptor, lastDescriptor); 1464 endpointLocker.Unlock(); 1465 1466 endpoint->flags &= ~OHCI_ENDPOINT_SKIP; 1467 if (pipe->Type() & USB_OBJECT_BULK_PIPE) { 1468 // Tell the controller to process the bulk list 1469 _WriteReg(OHCI_COMMAND_STATUS, OHCI_BULK_LIST_FILLED); 1470 } 1471 1472 return B_OK; 1473 } 1474 1475 1476 status_t 1477 OHCI::_SubmitIsochronousTransfer(Transfer *transfer) 1478 { 1479 Pipe *pipe = transfer->TransferPipe(); 1480 bool directionIn = (pipe->Direction() == Pipe::In); 1481 usb_isochronous_data *isochronousData = transfer->IsochronousData(); 1482 1483 ohci_isochronous_td *firstDescriptor = NULL; 1484 ohci_isochronous_td *lastDescriptor = NULL; 1485 status_t result = _CreateIsochronousDescriptorChain(&firstDescriptor, 1486 &lastDescriptor, transfer); 1487 1488 if (firstDescriptor == 0 || lastDescriptor == 0) 1489 return B_ERROR; 1490 1491 if (result < B_OK) 1492 return result; 1493 1494 // Set the last descriptor to generate an interrupt 1495 lastDescriptor->flags &= ~OHCI_ITD_INTERRUPT_MASK; 1496 // let the controller retire last ITD 1497 lastDescriptor->flags |= OHCI_ITD_SET_DELAY_INTERRUPT(1); 1498 1499 // If direction is out set every descriptor data 1500 if (pipe->Direction() == Pipe::Out) 1501 _WriteIsochronousDescriptorChain(firstDescriptor, 1502 transfer->Vector(), transfer->VectorCount()); 1503 else 1504 // Initialize the packet descriptors 1505 for (uint32 i = 0; i < isochronousData->packet_count; i++) { 1506 isochronousData->packet_descriptors[i].actual_length = 0; 1507 isochronousData->packet_descriptors[i].status = B_NO_INIT; 1508 } 1509 1510 // Add to the transfer list 1511 ohci_endpoint_descriptor *endpoint 1512 = (ohci_endpoint_descriptor *)pipe->ControllerCookie(); 1513 1514 MutexLocker endpointLocker(endpoint->lock); 1515 result = _AddPendingIsochronousTransfer(transfer, endpoint, 1516 firstDescriptor, lastDescriptor, directionIn); 1517 if (result < B_OK) { 1518 TRACE_ERROR("failed to add pending iso.transfer:" 1519 "0x%08" B_PRIx32 "\n", result); 1520 _FreeIsochronousDescriptorChain(firstDescriptor); 1521 return result; 1522 } 1523 1524 // Add the descriptor chain to the endpoint 1525 _SwitchIsochronousEndpointTail(endpoint, firstDescriptor, lastDescriptor); 1526 endpointLocker.Unlock(); 1527 1528 endpoint->flags &= ~OHCI_ENDPOINT_SKIP; 1529 1530 return B_OK; 1531 } 1532 1533 1534 void 1535 OHCI::_SwitchEndpointTail(ohci_endpoint_descriptor *endpoint, 1536 ohci_general_td *first, ohci_general_td *last) 1537 { 1538 // fill in the information of the first descriptor into the current tail 1539 ohci_general_td *tail = (ohci_general_td *)endpoint->tail_logical_descriptor; 1540 tail->flags = first->flags; 1541 tail->buffer_physical = first->buffer_physical; 1542 tail->next_physical_descriptor = first->next_physical_descriptor; 1543 tail->last_physical_byte_address = first->last_physical_byte_address; 1544 tail->buffer_size = first->buffer_size; 1545 tail->buffer_logical = first->buffer_logical; 1546 tail->next_logical_descriptor = first->next_logical_descriptor; 1547 1548 // the first descriptor becomes the new tail 1549 first->flags = 0; 1550 first->buffer_physical = 0; 1551 first->next_physical_descriptor = 0; 1552 first->last_physical_byte_address = 0; 1553 first->buffer_size = 0; 1554 first->buffer_logical = NULL; 1555 first->next_logical_descriptor = NULL; 1556 1557 if (first == last) 1558 _LinkDescriptors(tail, first); 1559 else 1560 _LinkDescriptors(last, first); 1561 1562 // update the endpoint tail pointer to reflect the change 1563 endpoint->tail_logical_descriptor = first; 1564 endpoint->tail_physical_descriptor = (uint32)first->physical_address; 1565 TRACE("switched tail from %p to %p\n", tail, first); 1566 1567 #if 0 1568 _PrintEndpoint(endpoint); 1569 _PrintDescriptorChain(tail); 1570 #endif 1571 } 1572 1573 1574 void 1575 OHCI::_SwitchIsochronousEndpointTail(ohci_endpoint_descriptor *endpoint, 1576 ohci_isochronous_td *first, ohci_isochronous_td *last) 1577 { 1578 // fill in the information of the first descriptor into the current tail 1579 ohci_isochronous_td *tail 1580 = (ohci_isochronous_td*)endpoint->tail_logical_descriptor; 1581 tail->flags = first->flags; 1582 tail->buffer_page_byte_0 = first->buffer_page_byte_0; 1583 tail->next_physical_descriptor = first->next_physical_descriptor; 1584 tail->last_byte_address = first->last_byte_address; 1585 tail->buffer_size = first->buffer_size; 1586 tail->buffer_logical = first->buffer_logical; 1587 tail->next_logical_descriptor = first->next_logical_descriptor; 1588 tail->next_done_descriptor = first->next_done_descriptor; 1589 1590 // the first descriptor becomes the new tail 1591 first->flags = 0; 1592 first->buffer_page_byte_0 = 0; 1593 first->next_physical_descriptor = 0; 1594 first->last_byte_address = 0; 1595 first->buffer_size = 0; 1596 first->buffer_logical = NULL; 1597 first->next_logical_descriptor = NULL; 1598 first->next_done_descriptor = NULL; 1599 1600 for (int i = 0; i < OHCI_ITD_NOFFSET; i++) { 1601 tail->offset[i] = first->offset[i]; 1602 first->offset[i] = 0; 1603 } 1604 1605 if (first == last) 1606 _LinkIsochronousDescriptors(tail, first, NULL); 1607 else 1608 _LinkIsochronousDescriptors(last, first, NULL); 1609 1610 // update the endpoint tail pointer to reflect the change 1611 endpoint->tail_logical_descriptor = first; 1612 endpoint->tail_physical_descriptor = (uint32)first->physical_address; 1613 TRACE("switched tail from %p to %p\n", tail, first); 1614 1615 #if 0 1616 _PrintEndpoint(endpoint); 1617 _PrintDescriptorChain(tail); 1618 #endif 1619 } 1620 1621 1622 void 1623 OHCI::_RemoveTransferFromEndpoint(transfer_data *transfer) 1624 { 1625 // The transfer failed and the endpoint was halted. This means that the 1626 // endpoint head pointer might point somewhere into the descriptor chain 1627 // of this transfer. As we do not know if this transfer actually caused 1628 // the halt on the endpoint we have to make sure this is the case. If we 1629 // find the head to point to somewhere into the descriptor chain then 1630 // simply advancing the head pointer to the link of the last transfer 1631 // will bring the endpoint into a valid state again. This operation is 1632 // safe as the endpoint is currently halted and we therefore can change 1633 // the head pointer. 1634 ohci_endpoint_descriptor *endpoint = transfer->endpoint; 1635 ohci_general_td *descriptor = transfer->first_descriptor; 1636 while (descriptor) { 1637 if ((endpoint->head_physical_descriptor & OHCI_ENDPOINT_HEAD_MASK) 1638 == descriptor->physical_address) { 1639 // This descriptor caused the halt. Advance the head pointer. This 1640 // will either move the head to the next valid transfer that can 1641 // then be restarted, or it will move the head to the tail when 1642 // there are no more transfer descriptors. Setting the head will 1643 // also clear the halt state as it is stored in the first bit of 1644 // the head pointer. 1645 endpoint->head_physical_descriptor 1646 = transfer->last_descriptor->next_physical_descriptor; 1647 return; 1648 } 1649 1650 descriptor = (ohci_general_td *)descriptor->next_logical_descriptor; 1651 } 1652 } 1653 1654 1655 ohci_endpoint_descriptor * 1656 OHCI::_AllocateEndpoint() 1657 { 1658 ohci_endpoint_descriptor *endpoint; 1659 phys_addr_t physicalAddress; 1660 1661 mutex *lock = (mutex *)malloc(sizeof(mutex)); 1662 if (lock == NULL) { 1663 TRACE_ERROR("no memory to allocate endpoint lock\n"); 1664 return NULL; 1665 } 1666 1667 // Allocate memory chunk 1668 if (fStack->AllocateChunk((void **)&endpoint, &physicalAddress, 1669 sizeof(ohci_endpoint_descriptor)) < B_OK) { 1670 TRACE_ERROR("failed to allocate endpoint descriptor\n"); 1671 free(lock); 1672 return NULL; 1673 } 1674 1675 mutex_init(lock, "ohci endpoint lock"); 1676 1677 endpoint->flags = OHCI_ENDPOINT_SKIP; 1678 endpoint->physical_address = (uint32)physicalAddress; 1679 endpoint->head_physical_descriptor = 0; 1680 endpoint->tail_logical_descriptor = NULL; 1681 endpoint->tail_physical_descriptor = 0; 1682 endpoint->next_logical_endpoint = NULL; 1683 endpoint->next_physical_endpoint = 0; 1684 endpoint->lock = lock; 1685 return endpoint; 1686 } 1687 1688 1689 void 1690 OHCI::_FreeEndpoint(ohci_endpoint_descriptor *endpoint) 1691 { 1692 if (!endpoint) 1693 return; 1694 1695 mutex_destroy(endpoint->lock); 1696 free(endpoint->lock); 1697 1698 fStack->FreeChunk((void *)endpoint, endpoint->physical_address, 1699 sizeof(ohci_endpoint_descriptor)); 1700 } 1701 1702 1703 status_t 1704 OHCI::_InsertEndpointForPipe(Pipe *pipe) 1705 { 1706 TRACE("inserting endpoint for device %u endpoint %u\n", 1707 pipe->DeviceAddress(), pipe->EndpointAddress()); 1708 1709 ohci_endpoint_descriptor *endpoint = _AllocateEndpoint(); 1710 if (!endpoint) { 1711 TRACE_ERROR("cannot allocate memory for endpoint\n"); 1712 return B_NO_MEMORY; 1713 } 1714 1715 uint32 flags = OHCI_ENDPOINT_SKIP; 1716 1717 // Set up device and endpoint address 1718 flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(pipe->DeviceAddress()) 1719 | OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(pipe->EndpointAddress()); 1720 1721 // Set the direction 1722 switch (pipe->Direction()) { 1723 case Pipe::In: 1724 flags |= OHCI_ENDPOINT_DIRECTION_IN; 1725 break; 1726 1727 case Pipe::Out: 1728 flags |= OHCI_ENDPOINT_DIRECTION_OUT; 1729 break; 1730 1731 case Pipe::Default: 1732 flags |= OHCI_ENDPOINT_DIRECTION_DESCRIPTOR; 1733 break; 1734 1735 default: 1736 TRACE_ERROR("direction unknown\n"); 1737 _FreeEndpoint(endpoint); 1738 return B_ERROR; 1739 } 1740 1741 // Set up the speed 1742 switch (pipe->Speed()) { 1743 case USB_SPEED_LOWSPEED: 1744 flags |= OHCI_ENDPOINT_LOW_SPEED; 1745 break; 1746 1747 case USB_SPEED_FULLSPEED: 1748 flags |= OHCI_ENDPOINT_FULL_SPEED; 1749 break; 1750 1751 default: 1752 TRACE_ERROR("unacceptable speed\n"); 1753 _FreeEndpoint(endpoint); 1754 return B_ERROR; 1755 } 1756 1757 // Set the maximum packet size 1758 flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(pipe->MaxPacketSize()); 1759 endpoint->flags = flags; 1760 1761 // Add the endpoint to the appropriate list 1762 uint32 type = pipe->Type(); 1763 ohci_endpoint_descriptor *head = NULL; 1764 if (type & USB_OBJECT_CONTROL_PIPE) 1765 head = fDummyControl; 1766 else if (type & USB_OBJECT_BULK_PIPE) 1767 head = fDummyBulk; 1768 else if (type & USB_OBJECT_INTERRUPT_PIPE) 1769 head = _FindInterruptEndpoint(pipe->Interval()); 1770 else if (type & USB_OBJECT_ISO_PIPE) 1771 head = fDummyIsochronous; 1772 else 1773 TRACE_ERROR("unknown pipe type\n"); 1774 1775 if (head == NULL) { 1776 TRACE_ERROR("no list found for endpoint\n"); 1777 _FreeEndpoint(endpoint); 1778 return B_ERROR; 1779 } 1780 1781 // Create (necessary) tail descriptor 1782 if (pipe->Type() & USB_OBJECT_ISO_PIPE) { 1783 // Set the isochronous bit format 1784 endpoint->flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT; 1785 ohci_isochronous_td *tail = _CreateIsochronousDescriptor(0); 1786 tail->flags = 0; 1787 endpoint->tail_logical_descriptor = tail; 1788 endpoint->head_physical_descriptor = tail->physical_address; 1789 endpoint->tail_physical_descriptor = tail->physical_address; 1790 } else { 1791 ohci_general_td *tail = _CreateGeneralDescriptor(0); 1792 tail->flags = 0; 1793 endpoint->tail_logical_descriptor = tail; 1794 endpoint->head_physical_descriptor = tail->physical_address; 1795 endpoint->tail_physical_descriptor = tail->physical_address; 1796 } 1797 1798 if (!_LockEndpoints()) { 1799 if (endpoint->tail_logical_descriptor) { 1800 _FreeGeneralDescriptor( 1801 (ohci_general_td *)endpoint->tail_logical_descriptor); 1802 } 1803 1804 _FreeEndpoint(endpoint); 1805 return B_ERROR; 1806 } 1807 1808 pipe->SetControllerCookie((void *)endpoint); 1809 endpoint->next_logical_endpoint = head->next_logical_endpoint; 1810 endpoint->next_physical_endpoint = head->next_physical_endpoint; 1811 head->next_logical_endpoint = (void *)endpoint; 1812 head->next_physical_endpoint = (uint32)endpoint->physical_address; 1813 1814 _UnlockEndpoints(); 1815 return B_OK; 1816 } 1817 1818 1819 status_t 1820 OHCI::_RemoveEndpointForPipe(Pipe *pipe) 1821 { 1822 TRACE("removing endpoint for device %u endpoint %u\n", 1823 pipe->DeviceAddress(), pipe->EndpointAddress()); 1824 1825 ohci_endpoint_descriptor *endpoint 1826 = (ohci_endpoint_descriptor *)pipe->ControllerCookie(); 1827 if (endpoint == NULL) 1828 return B_OK; 1829 1830 // TODO implement properly, but at least disable it for now 1831 endpoint->flags |= OHCI_ENDPOINT_SKIP; 1832 return B_OK; 1833 } 1834 1835 1836 ohci_endpoint_descriptor * 1837 OHCI::_FindInterruptEndpoint(uint8 interval) 1838 { 1839 uint32 index = 0; 1840 uint32 power = 1; 1841 while (power <= OHCI_BIGGEST_INTERVAL / 2) { 1842 if (power * 2 > interval) 1843 break; 1844 1845 power *= 2; 1846 index++; 1847 } 1848 1849 return fInterruptEndpoints[index]; 1850 } 1851 1852 1853 ohci_general_td * 1854 OHCI::_CreateGeneralDescriptor(size_t bufferSize) 1855 { 1856 ohci_general_td *descriptor; 1857 phys_addr_t physicalAddress; 1858 1859 if (fStack->AllocateChunk((void **)&descriptor, &physicalAddress, 1860 sizeof(ohci_general_td)) != B_OK) { 1861 TRACE_ERROR("failed to allocate general descriptor\n"); 1862 return NULL; 1863 } 1864 1865 descriptor->physical_address = (uint32)physicalAddress; 1866 descriptor->next_physical_descriptor = 0; 1867 descriptor->next_logical_descriptor = NULL; 1868 descriptor->buffer_size = bufferSize; 1869 if (bufferSize == 0) { 1870 descriptor->buffer_physical = 0; 1871 descriptor->buffer_logical = NULL; 1872 descriptor->last_physical_byte_address = 0; 1873 return descriptor; 1874 } 1875 1876 if (fStack->AllocateChunk(&descriptor->buffer_logical, 1877 &physicalAddress, bufferSize) != B_OK) { 1878 TRACE_ERROR("failed to allocate space for buffer\n"); 1879 fStack->FreeChunk(descriptor, descriptor->physical_address, 1880 sizeof(ohci_general_td)); 1881 return NULL; 1882 } 1883 descriptor->buffer_physical = physicalAddress; 1884 1885 descriptor->last_physical_byte_address 1886 = descriptor->buffer_physical + bufferSize - 1; 1887 return descriptor; 1888 } 1889 1890 1891 void 1892 OHCI::_FreeGeneralDescriptor(ohci_general_td *descriptor) 1893 { 1894 if (!descriptor) 1895 return; 1896 1897 if (descriptor->buffer_logical) { 1898 fStack->FreeChunk(descriptor->buffer_logical, 1899 descriptor->buffer_physical, descriptor->buffer_size); 1900 } 1901 1902 fStack->FreeChunk((void *)descriptor, descriptor->physical_address, 1903 sizeof(ohci_general_td)); 1904 } 1905 1906 1907 status_t 1908 OHCI::_CreateDescriptorChain(ohci_general_td **_firstDescriptor, 1909 ohci_general_td **_lastDescriptor, uint32 direction, size_t bufferSize) 1910 { 1911 size_t blockSize = 8192; 1912 int32 descriptorCount = (bufferSize + blockSize - 1) / blockSize; 1913 if (descriptorCount == 0) 1914 descriptorCount = 1; 1915 1916 ohci_general_td *firstDescriptor = NULL; 1917 ohci_general_td *lastDescriptor = *_firstDescriptor; 1918 for (int32 i = 0; i < descriptorCount; i++) { 1919 ohci_general_td *descriptor = _CreateGeneralDescriptor( 1920 min_c(blockSize, bufferSize)); 1921 1922 if (!descriptor) { 1923 _FreeDescriptorChain(firstDescriptor); 1924 return B_NO_MEMORY; 1925 } 1926 1927 descriptor->flags = direction 1928 | OHCI_TD_BUFFER_ROUNDING 1929 | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) 1930 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) 1931 | OHCI_TD_TOGGLE_CARRY; 1932 1933 // link to previous 1934 if (lastDescriptor) 1935 _LinkDescriptors(lastDescriptor, descriptor); 1936 1937 bufferSize -= blockSize; 1938 lastDescriptor = descriptor; 1939 if (!firstDescriptor) 1940 firstDescriptor = descriptor; 1941 } 1942 1943 *_firstDescriptor = firstDescriptor; 1944 *_lastDescriptor = lastDescriptor; 1945 return B_OK; 1946 } 1947 1948 1949 void 1950 OHCI::_FreeDescriptorChain(ohci_general_td *topDescriptor) 1951 { 1952 ohci_general_td *current = topDescriptor; 1953 ohci_general_td *next = NULL; 1954 1955 while (current) { 1956 next = (ohci_general_td *)current->next_logical_descriptor; 1957 _FreeGeneralDescriptor(current); 1958 current = next; 1959 } 1960 } 1961 1962 1963 ohci_isochronous_td * 1964 OHCI::_CreateIsochronousDescriptor(size_t bufferSize) 1965 { 1966 ohci_isochronous_td *descriptor = NULL; 1967 phys_addr_t physicalAddress; 1968 1969 if (fStack->AllocateChunk((void **)&descriptor, &physicalAddress, 1970 sizeof(ohci_isochronous_td)) != B_OK) { 1971 TRACE_ERROR("failed to allocate isochronous descriptor\n"); 1972 return NULL; 1973 } 1974 1975 descriptor->physical_address = (uint32)physicalAddress; 1976 descriptor->next_physical_descriptor = 0; 1977 descriptor->next_logical_descriptor = NULL; 1978 descriptor->next_done_descriptor = NULL; 1979 descriptor->buffer_size = bufferSize; 1980 if (bufferSize == 0) { 1981 descriptor->buffer_page_byte_0 = 0; 1982 descriptor->buffer_logical = NULL; 1983 descriptor->last_byte_address = 0; 1984 return descriptor; 1985 } 1986 1987 if (fStack->AllocateChunk(&descriptor->buffer_logical, 1988 &physicalAddress, bufferSize) != B_OK) { 1989 TRACE_ERROR("failed to allocate space for iso.buffer\n"); 1990 fStack->FreeChunk(descriptor, descriptor->physical_address, 1991 sizeof(ohci_isochronous_td)); 1992 return NULL; 1993 } 1994 descriptor->buffer_page_byte_0 = (uint32)physicalAddress; 1995 descriptor->last_byte_address 1996 = descriptor->buffer_page_byte_0 + bufferSize - 1; 1997 1998 return descriptor; 1999 } 2000 2001 2002 void 2003 OHCI::_FreeIsochronousDescriptor(ohci_isochronous_td *descriptor) 2004 { 2005 if (!descriptor) 2006 return; 2007 2008 if (descriptor->buffer_logical) { 2009 fStack->FreeChunk(descriptor->buffer_logical, 2010 descriptor->buffer_page_byte_0, descriptor->buffer_size); 2011 } 2012 2013 fStack->FreeChunk((void *)descriptor, descriptor->physical_address, 2014 sizeof(ohci_general_td)); 2015 } 2016 2017 2018 status_t 2019 OHCI::_CreateIsochronousDescriptorChain(ohci_isochronous_td **_firstDescriptor, 2020 ohci_isochronous_td **_lastDescriptor, Transfer *transfer) 2021 { 2022 Pipe *pipe = transfer->TransferPipe(); 2023 usb_isochronous_data *isochronousData = transfer->IsochronousData(); 2024 2025 size_t dataLength = transfer->VectorLength(); 2026 size_t packet_count = isochronousData->packet_count; 2027 2028 if (packet_count == 0) { 2029 TRACE_ERROR("isochronous packet_count should not be equal to zero."); 2030 return B_BAD_VALUE; 2031 } 2032 2033 size_t packetSize = dataLength / packet_count; 2034 if (dataLength % packet_count != 0) 2035 packetSize++; 2036 2037 if (packetSize > pipe->MaxPacketSize()) { 2038 TRACE_ERROR("isochronous packetSize %ld is bigger" 2039 " than pipe MaxPacketSize %ld.", packetSize, pipe->MaxPacketSize()); 2040 return B_BAD_VALUE; 2041 } 2042 2043 uint16 bandwidth = transfer->Bandwidth() / packet_count; 2044 if (transfer->Bandwidth() % packet_count != 0) 2045 bandwidth++; 2046 2047 ohci_isochronous_td *firstDescriptor = NULL; 2048 ohci_isochronous_td *lastDescriptor = *_firstDescriptor; 2049 2050 // the frame number currently processed by the host controller 2051 uint16 currentFrame = fHcca->current_frame_number & 0xFFFF; 2052 uint16 safeFrames = 5; 2053 2054 // The entry where to start inserting the first Isochronous descriptor 2055 // real frame number may differ in case provided one has not bandwidth 2056 if (isochronousData->flags & USB_ISO_ASAP || 2057 isochronousData->starting_frame_number == NULL) 2058 // We should stay about 5-10 ms ahead of the controller 2059 // USB1 frame is equal to 1 ms 2060 currentFrame += safeFrames; 2061 else 2062 currentFrame = *isochronousData->starting_frame_number; 2063 2064 uint16 packets = packet_count; 2065 uint16 frameOffset = 0; 2066 while (packets > 0) { 2067 // look for up to 8 continous frames with available bandwidth 2068 uint16 frameCount = 0; 2069 while (frameCount < min_c(OHCI_ITD_NOFFSET, packets) 2070 && _AllocateIsochronousBandwidth(frameOffset + currentFrame 2071 + frameCount, bandwidth)) 2072 frameCount++; 2073 2074 if (frameCount == 0) { 2075 // starting frame has no bandwidth for our transaction - try next 2076 if (++frameOffset >= 0xFFFF) { 2077 TRACE_ERROR("failed to allocate bandwidth\n"); 2078 _FreeIsochronousDescriptorChain(firstDescriptor); 2079 return B_NO_MEMORY; 2080 } 2081 continue; 2082 } 2083 2084 ohci_isochronous_td *descriptor = _CreateIsochronousDescriptor( 2085 packetSize * frameCount); 2086 2087 if (!descriptor) { 2088 TRACE_ERROR("failed to allocate ITD\n"); 2089 _ReleaseIsochronousBandwidth(currentFrame + frameOffset, frameCount); 2090 _FreeIsochronousDescriptorChain(firstDescriptor); 2091 return B_NO_MEMORY; 2092 } 2093 2094 uint16 pageOffset = descriptor->buffer_page_byte_0 & 0xfff; 2095 descriptor->buffer_page_byte_0 &= ~0xfff; 2096 for (uint16 i = 0; i < frameCount; i++) { 2097 descriptor->offset[OHCI_ITD_OFFSET_IDX(i)] 2098 = OHCI_ITD_MK_OFFS(pageOffset + packetSize * i); 2099 } 2100 2101 descriptor->flags = OHCI_ITD_SET_FRAME_COUNT(frameCount) 2102 | OHCI_ITD_SET_CONDITION_CODE(OHCI_ITD_CONDITION_NOT_ACCESSED) 2103 | OHCI_ITD_SET_DELAY_INTERRUPT(OHCI_ITD_INTERRUPT_NONE) 2104 | OHCI_ITD_SET_STARTING_FRAME(currentFrame + frameOffset); 2105 2106 // the last packet may be shorter than other ones in this transfer 2107 if (packets <= OHCI_ITD_NOFFSET) 2108 descriptor->last_byte_address 2109 += dataLength - packetSize * (packet_count); 2110 2111 // link to previous 2112 if (lastDescriptor) 2113 _LinkIsochronousDescriptors(lastDescriptor, descriptor, descriptor); 2114 2115 lastDescriptor = descriptor; 2116 if (!firstDescriptor) 2117 firstDescriptor = descriptor; 2118 2119 packets -= frameCount; 2120 2121 frameOffset += frameCount; 2122 2123 if (packets == 0 && isochronousData->starting_frame_number) 2124 *isochronousData->starting_frame_number = currentFrame + frameOffset; 2125 } 2126 2127 *_firstDescriptor = firstDescriptor; 2128 *_lastDescriptor = lastDescriptor; 2129 2130 return B_OK; 2131 } 2132 2133 2134 void 2135 OHCI::_FreeIsochronousDescriptorChain(ohci_isochronous_td *topDescriptor) 2136 { 2137 ohci_isochronous_td *current = topDescriptor; 2138 ohci_isochronous_td *next = NULL; 2139 2140 while (current) { 2141 next = (ohci_isochronous_td *)current->next_done_descriptor; 2142 _FreeIsochronousDescriptor(current); 2143 current = next; 2144 } 2145 } 2146 2147 2148 size_t 2149 OHCI::_WriteDescriptorChain(ohci_general_td *topDescriptor, iovec *vector, 2150 size_t vectorCount) 2151 { 2152 ohci_general_td *current = topDescriptor; 2153 size_t actualLength = 0; 2154 size_t vectorIndex = 0; 2155 size_t vectorOffset = 0; 2156 size_t bufferOffset = 0; 2157 2158 while (current) { 2159 if (!current->buffer_logical) 2160 break; 2161 2162 while (true) { 2163 size_t length = min_c(current->buffer_size - bufferOffset, 2164 vector[vectorIndex].iov_len - vectorOffset); 2165 2166 TRACE("copying %ld bytes to bufferOffset %ld from" 2167 " vectorOffset %ld at index %ld of %ld\n", length, bufferOffset, 2168 vectorOffset, vectorIndex, vectorCount); 2169 memcpy((uint8 *)current->buffer_logical + bufferOffset, 2170 (uint8 *)vector[vectorIndex].iov_base + vectorOffset, length); 2171 2172 actualLength += length; 2173 vectorOffset += length; 2174 bufferOffset += length; 2175 2176 if (vectorOffset >= vector[vectorIndex].iov_len) { 2177 if (++vectorIndex >= vectorCount) { 2178 TRACE("wrote descriptor chain (%ld bytes, no" 2179 " more vectors)\n", actualLength); 2180 return actualLength; 2181 } 2182 2183 vectorOffset = 0; 2184 } 2185 2186 if (bufferOffset >= current->buffer_size) { 2187 bufferOffset = 0; 2188 break; 2189 } 2190 } 2191 2192 if (!current->next_logical_descriptor) 2193 break; 2194 2195 current = (ohci_general_td *)current->next_logical_descriptor; 2196 } 2197 2198 TRACE("wrote descriptor chain (%ld bytes)\n", actualLength); 2199 return actualLength; 2200 } 2201 2202 2203 size_t 2204 OHCI::_WriteIsochronousDescriptorChain(ohci_isochronous_td *topDescriptor, 2205 iovec *vector, size_t vectorCount) 2206 { 2207 ohci_isochronous_td *current = topDescriptor; 2208 size_t actualLength = 0; 2209 size_t vectorIndex = 0; 2210 size_t vectorOffset = 0; 2211 size_t bufferOffset = 0; 2212 2213 while (current) { 2214 if (!current->buffer_logical) 2215 break; 2216 2217 while (true) { 2218 size_t length = min_c(current->buffer_size - bufferOffset, 2219 vector[vectorIndex].iov_len - vectorOffset); 2220 2221 TRACE("copying %ld bytes to bufferOffset %ld from" 2222 " vectorOffset %ld at index %ld of %ld\n", length, bufferOffset, 2223 vectorOffset, vectorIndex, vectorCount); 2224 memcpy((uint8 *)current->buffer_logical + bufferOffset, 2225 (uint8 *)vector[vectorIndex].iov_base + vectorOffset, length); 2226 2227 actualLength += length; 2228 vectorOffset += length; 2229 bufferOffset += length; 2230 2231 if (vectorOffset >= vector[vectorIndex].iov_len) { 2232 if (++vectorIndex >= vectorCount) { 2233 TRACE("wrote descriptor chain (%ld bytes, no" 2234 " more vectors)\n", actualLength); 2235 return actualLength; 2236 } 2237 2238 vectorOffset = 0; 2239 } 2240 2241 if (bufferOffset >= current->buffer_size) { 2242 bufferOffset = 0; 2243 break; 2244 } 2245 } 2246 2247 if (!current->next_logical_descriptor) 2248 break; 2249 2250 current = (ohci_isochronous_td *)current->next_logical_descriptor; 2251 } 2252 2253 TRACE("wrote descriptor chain (%ld bytes)\n", actualLength); 2254 return actualLength; 2255 } 2256 2257 2258 size_t 2259 OHCI::_ReadDescriptorChain(ohci_general_td *topDescriptor, iovec *vector, 2260 size_t vectorCount) 2261 { 2262 ohci_general_td *current = topDescriptor; 2263 size_t actualLength = 0; 2264 size_t vectorIndex = 0; 2265 size_t vectorOffset = 0; 2266 size_t bufferOffset = 0; 2267 2268 while (current && OHCI_TD_GET_CONDITION_CODE(current->flags) 2269 != OHCI_TD_CONDITION_NOT_ACCESSED) { 2270 if (!current->buffer_logical) 2271 break; 2272 2273 size_t bufferSize = current->buffer_size; 2274 if (current->buffer_physical != 0) { 2275 bufferSize -= current->last_physical_byte_address 2276 - current->buffer_physical + 1; 2277 } 2278 2279 while (true) { 2280 size_t length = min_c(bufferSize - bufferOffset, 2281 vector[vectorIndex].iov_len - vectorOffset); 2282 2283 TRACE("copying %ld bytes to vectorOffset %ld from" 2284 " bufferOffset %ld at index %ld of %ld\n", length, vectorOffset, 2285 bufferOffset, vectorIndex, vectorCount); 2286 memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset, 2287 (uint8 *)current->buffer_logical + bufferOffset, length); 2288 2289 actualLength += length; 2290 vectorOffset += length; 2291 bufferOffset += length; 2292 2293 if (vectorOffset >= vector[vectorIndex].iov_len) { 2294 if (++vectorIndex >= vectorCount) { 2295 TRACE("read descriptor chain (%ld bytes, no more vectors)\n", 2296 actualLength); 2297 return actualLength; 2298 } 2299 2300 vectorOffset = 0; 2301 } 2302 2303 if (bufferOffset >= bufferSize) { 2304 bufferOffset = 0; 2305 break; 2306 } 2307 } 2308 2309 current = (ohci_general_td *)current->next_logical_descriptor; 2310 } 2311 2312 TRACE("read descriptor chain (%ld bytes)\n", actualLength); 2313 return actualLength; 2314 } 2315 2316 2317 void 2318 OHCI::_ReadIsochronousDescriptorChain(ohci_isochronous_td *topDescriptor, 2319 iovec *vector, size_t vectorCount) 2320 { 2321 ohci_isochronous_td *current = topDescriptor; 2322 size_t actualLength = 0; 2323 size_t vectorIndex = 0; 2324 size_t vectorOffset = 0; 2325 size_t bufferOffset = 0; 2326 2327 while (current && OHCI_ITD_GET_CONDITION_CODE(current->flags) 2328 != OHCI_ITD_CONDITION_NOT_ACCESSED) { 2329 size_t bufferSize = current->buffer_size; 2330 if (current->buffer_logical != NULL && bufferSize > 0) { 2331 while (true) { 2332 size_t length = min_c(bufferSize - bufferOffset, 2333 vector[vectorIndex].iov_len - vectorOffset); 2334 2335 TRACE("copying %ld bytes to vectorOffset %ld from bufferOffset" 2336 " %ld at index %ld of %ld\n", length, vectorOffset, 2337 bufferOffset, vectorIndex, vectorCount); 2338 memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset, 2339 (uint8 *)current->buffer_logical + bufferOffset, length); 2340 2341 actualLength += length; 2342 vectorOffset += length; 2343 bufferOffset += length; 2344 2345 if (vectorOffset >= vector[vectorIndex].iov_len) { 2346 if (++vectorIndex >= vectorCount) { 2347 TRACE("read descriptor chain (%ld bytes, " 2348 "no more vectors)\n", actualLength); 2349 return; 2350 } 2351 2352 vectorOffset = 0; 2353 } 2354 2355 if (bufferOffset >= bufferSize) { 2356 bufferOffset = 0; 2357 break; 2358 } 2359 } 2360 } 2361 2362 current = (ohci_isochronous_td *)current->next_done_descriptor; 2363 } 2364 2365 TRACE("read descriptor chain (%ld bytes)\n", actualLength); 2366 return; 2367 } 2368 2369 2370 size_t 2371 OHCI::_ReadActualLength(ohci_general_td *topDescriptor) 2372 { 2373 ohci_general_td *current = topDescriptor; 2374 size_t actualLength = 0; 2375 2376 while (current && OHCI_TD_GET_CONDITION_CODE(current->flags) 2377 != OHCI_TD_CONDITION_NOT_ACCESSED) { 2378 size_t length = current->buffer_size; 2379 if (current->buffer_physical != 0) { 2380 length -= current->last_physical_byte_address 2381 - current->buffer_physical + 1; 2382 } 2383 2384 actualLength += length; 2385 current = (ohci_general_td *)current->next_logical_descriptor; 2386 } 2387 2388 TRACE("read actual length (%ld bytes)\n", actualLength); 2389 return actualLength; 2390 } 2391 2392 2393 void 2394 OHCI::_LinkDescriptors(ohci_general_td *first, ohci_general_td *second) 2395 { 2396 first->next_physical_descriptor = second->physical_address; 2397 first->next_logical_descriptor = second; 2398 } 2399 2400 2401 void 2402 OHCI::_LinkIsochronousDescriptors(ohci_isochronous_td *first, 2403 ohci_isochronous_td *second, ohci_isochronous_td *nextDone) 2404 { 2405 first->next_physical_descriptor = second->physical_address; 2406 first->next_logical_descriptor = second; 2407 first->next_done_descriptor = nextDone; 2408 } 2409 2410 2411 bool 2412 OHCI::_AllocateIsochronousBandwidth(uint16 frame, uint16 size) 2413 { 2414 frame %= NUMBER_OF_FRAMES; 2415 if (size > fFrameBandwidth[frame]) 2416 return false; 2417 2418 fFrameBandwidth[frame]-= size; 2419 return true; 2420 } 2421 2422 2423 void 2424 OHCI::_ReleaseIsochronousBandwidth(uint16 startFrame, uint16 frameCount) 2425 { 2426 for (size_t index = 0; index < frameCount; index++) { 2427 uint16 frame = (startFrame + index) % NUMBER_OF_FRAMES; 2428 fFrameBandwidth[frame] = MAX_AVAILABLE_BANDWIDTH; 2429 } 2430 } 2431 2432 2433 status_t 2434 OHCI::_GetStatusOfConditionCode(uint8 conditionCode) 2435 { 2436 switch (conditionCode) { 2437 case OHCI_TD_CONDITION_NO_ERROR: 2438 return B_OK; 2439 2440 case OHCI_TD_CONDITION_CRC_ERROR: 2441 case OHCI_TD_CONDITION_BIT_STUFFING: 2442 case OHCI_TD_CONDITION_TOGGLE_MISMATCH: 2443 return B_DEV_CRC_ERROR; 2444 2445 case OHCI_TD_CONDITION_STALL: 2446 return B_DEV_STALLED; 2447 2448 case OHCI_TD_CONDITION_NO_RESPONSE: 2449 return B_TIMED_OUT; 2450 2451 case OHCI_TD_CONDITION_PID_CHECK_FAILURE: 2452 return B_DEV_BAD_PID; 2453 2454 case OHCI_TD_CONDITION_UNEXPECTED_PID: 2455 return B_DEV_UNEXPECTED_PID; 2456 2457 case OHCI_TD_CONDITION_DATA_OVERRUN: 2458 return B_DEV_DATA_OVERRUN; 2459 2460 case OHCI_TD_CONDITION_DATA_UNDERRUN: 2461 return B_DEV_DATA_UNDERRUN; 2462 2463 case OHCI_TD_CONDITION_BUFFER_OVERRUN: 2464 return B_DEV_FIFO_OVERRUN; 2465 2466 case OHCI_TD_CONDITION_BUFFER_UNDERRUN: 2467 return B_DEV_FIFO_UNDERRUN; 2468 2469 case OHCI_TD_CONDITION_NOT_ACCESSED: 2470 return B_DEV_PENDING; 2471 2472 case 0x0E: 2473 return B_DEV_TOO_LATE; // PSW: _NOT_ACCESSED 2474 2475 default: 2476 break; 2477 } 2478 2479 return B_ERROR; 2480 } 2481 2482 2483 bool 2484 OHCI::_LockEndpoints() 2485 { 2486 return (mutex_lock(&fEndpointLock) == B_OK); 2487 } 2488 2489 2490 void 2491 OHCI::_UnlockEndpoints() 2492 { 2493 mutex_unlock(&fEndpointLock); 2494 } 2495 2496 2497 inline void 2498 OHCI::_WriteReg(uint32 reg, uint32 value) 2499 { 2500 *(volatile uint32 *)(fOperationalRegisters + reg) = value; 2501 } 2502 2503 2504 inline uint32 2505 OHCI::_ReadReg(uint32 reg) 2506 { 2507 return *(volatile uint32 *)(fOperationalRegisters + reg); 2508 } 2509 2510 2511 void 2512 OHCI::_PrintEndpoint(ohci_endpoint_descriptor *endpoint) 2513 { 2514 dprintf("endpoint %p\n", endpoint); 2515 dprintf("\tflags........... 0x%08" B_PRIx32 "\n", endpoint->flags); 2516 dprintf("\ttail_physical... 0x%08" B_PRIx32 "\n", endpoint->tail_physical_descriptor); 2517 dprintf("\thead_physical... 0x%08" B_PRIx32 "\n", endpoint->head_physical_descriptor); 2518 dprintf("\tnext_physical... 0x%08" B_PRIx32 "\n", endpoint->next_physical_endpoint); 2519 dprintf("\tphysical........ 0x%08" B_PRIx32 "\n", endpoint->physical_address); 2520 dprintf("\ttail_logical.... %p\n", endpoint->tail_logical_descriptor); 2521 dprintf("\tnext_logical.... %p\n", endpoint->next_logical_endpoint); 2522 } 2523 2524 2525 void 2526 OHCI::_PrintDescriptorChain(ohci_general_td *topDescriptor) 2527 { 2528 while (topDescriptor) { 2529 dprintf("descriptor %p\n", topDescriptor); 2530 dprintf("\tflags........... 0x%08" B_PRIx32 "\n", topDescriptor->flags); 2531 dprintf("\tbuffer_physical. 0x%08" B_PRIx32 "\n", topDescriptor->buffer_physical); 2532 dprintf("\tnext_physical... 0x%08" B_PRIx32 "\n", topDescriptor->next_physical_descriptor); 2533 dprintf("\tlast_byte....... 0x%08" B_PRIx32 "\n", topDescriptor->last_physical_byte_address); 2534 dprintf("\tphysical........ 0x%08" B_PRIx32 "\n", topDescriptor->physical_address); 2535 dprintf("\tbuffer_size..... %lu\n", topDescriptor->buffer_size); 2536 dprintf("\tbuffer_logical.. %p\n", topDescriptor->buffer_logical); 2537 dprintf("\tnext_logical.... %p\n", topDescriptor->next_logical_descriptor); 2538 2539 topDescriptor = (ohci_general_td *)topDescriptor->next_logical_descriptor; 2540 } 2541 } 2542 2543 2544 void 2545 OHCI::_PrintDescriptorChain(ohci_isochronous_td *topDescriptor) 2546 { 2547 while (topDescriptor) { 2548 dprintf("iso.descriptor %p\n", topDescriptor); 2549 dprintf("\tflags........... 0x%08" B_PRIx32 "\n", topDescriptor->flags); 2550 dprintf("\tbuffer_pagebyte0 0x%08" B_PRIx32 "\n", topDescriptor->buffer_page_byte_0); 2551 dprintf("\tnext_physical... 0x%08" B_PRIx32 "\n", topDescriptor->next_physical_descriptor); 2552 dprintf("\tlast_byte....... 0x%08" B_PRIx32 "\n", topDescriptor->last_byte_address); 2553 dprintf("\toffset:\n\t0x%04x 0x%04x 0x%04x 0x%04x\n" 2554 "\t0x%04x 0x%04x 0x%04x 0x%04x\n", 2555 topDescriptor->offset[0], topDescriptor->offset[1], 2556 topDescriptor->offset[2], topDescriptor->offset[3], 2557 topDescriptor->offset[4], topDescriptor->offset[5], 2558 topDescriptor->offset[6], topDescriptor->offset[7]); 2559 dprintf("\tphysical........ 0x%08" B_PRIx32 "\n", topDescriptor->physical_address); 2560 dprintf("\tbuffer_size..... %lu\n", topDescriptor->buffer_size); 2561 dprintf("\tbuffer_logical.. %p\n", topDescriptor->buffer_logical); 2562 dprintf("\tnext_logical.... %p\n", topDescriptor->next_logical_descriptor); 2563 dprintf("\tnext_done....... %p\n", topDescriptor->next_done_descriptor); 2564 2565 topDescriptor = (ohci_isochronous_td *)topDescriptor->next_done_descriptor; 2566 } 2567 } 2568 2569