1 /* 2 * PROJECT: ReactOS USB OHCI Miniport Driver 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: USBOHCI main driver functions 5 * COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru> 6 */ 7 8 #include "usbohci.h" 9 10 #define NDEBUG 11 #include <debug.h> 12 13 #define NDEBUG_OHCI_TRACE 14 #include "dbg_ohci.h" 15 16 USBPORT_REGISTRATION_PACKET RegPacket; 17 18 static const UCHAR Index[8] = 19 { 20 ENDPOINT_INTERRUPT_1ms - 1, 21 ENDPOINT_INTERRUPT_2ms - 1, 22 ENDPOINT_INTERRUPT_4ms - 1, 23 ENDPOINT_INTERRUPT_8ms - 1, 24 ENDPOINT_INTERRUPT_16ms - 1, 25 ENDPOINT_INTERRUPT_32ms - 1, 26 ENDPOINT_INTERRUPT_32ms - 1, 27 ENDPOINT_INTERRUPT_32ms - 1 28 }; 29 30 static const UCHAR Balance[OHCI_NUMBER_OF_INTERRUPTS] = 31 { 32 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30, 33 1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31 34 }; 35 36 VOID 37 NTAPI 38 OHCI_DumpHcdED(POHCI_HCD_ED ED) 39 { 40 DPRINT("ED - %p\n", ED); 41 DPRINT("EndpointControl - %X\n", ED->HwED.EndpointControl.AsULONG); 42 DPRINT("TailPointer - %08X\n", ED->HwED.TailPointer); 43 DPRINT("HeadPointer - %08X\n", ED->HwED.HeadPointer); 44 DPRINT("NextED - %08X\n", ED->HwED.NextED); 45 } 46 47 VOID 48 NTAPI 49 OHCI_DumpHcdTD(POHCI_HCD_TD TD) 50 { 51 DPRINT("TD - %p\n", TD); 52 DPRINT("gTD.Control - %08X\n", TD->HwTD.gTD.Control.AsULONG); 53 if (TD->HwTD.gTD.CurrentBuffer) 54 DPRINT("gTD.CurrentBuffer - %08X\n", TD->HwTD.gTD.CurrentBuffer); 55 if (TD->HwTD.gTD.NextTD) 56 DPRINT("gTD.NextTD - %08X\n", TD->HwTD.gTD.NextTD); 57 if (TD->HwTD.gTD.BufferEnd) 58 DPRINT("gTD.BufferEnd - %08X\n", TD->HwTD.gTD.BufferEnd); 59 60 if (TD->HwTD.SetupPacket.bmRequestType.B) 61 DPRINT("bmRequestType - %02X\n", TD->HwTD.SetupPacket.bmRequestType.B); 62 if (TD->HwTD.SetupPacket.bRequest) 63 DPRINT("bRequest - %02X\n", TD->HwTD.SetupPacket.bRequest); 64 if (TD->HwTD.SetupPacket.wValue.W) 65 DPRINT("wValue - %04X\n", TD->HwTD.SetupPacket.wValue.W); 66 if (TD->HwTD.SetupPacket.wIndex.W) 67 DPRINT("wIndex - %04X\n", TD->HwTD.SetupPacket.wIndex.W); 68 if (TD->HwTD.SetupPacket.wLength) 69 DPRINT("wLength - %04X\n", TD->HwTD.SetupPacket.wLength); 70 71 DPRINT("PhysicalAddress - %p\n", TD->PhysicalAddress); 72 DPRINT("Flags - %X\n", TD->Flags); 73 DPRINT("OhciTransfer - %08X\n", TD->OhciTransfer); 74 DPRINT("NextTDVa - %08X\n", TD->NextTDVa); 75 if (TD->TransferLen) 76 DPRINT("TransferLen - %X\n", TD->TransferLen); 77 } 78 79 VOID 80 NTAPI 81 OHCI_EnableList(IN POHCI_EXTENSION OhciExtension, 82 IN POHCI_ENDPOINT OhciEndpoint) 83 { 84 POHCI_OPERATIONAL_REGISTERS OperationalRegs; 85 PULONG CommandStatusReg; 86 ULONG TransferType; 87 OHCI_REG_COMMAND_STATUS CommandStatus; 88 89 DPRINT_OHCI("OHCI_EnableList: ... \n"); 90 91 OperationalRegs = OhciExtension->OperationalRegs; 92 CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus; 93 94 CommandStatus.AsULONG = 0; 95 96 if (READ_REGISTER_ULONG((PULONG)&OperationalRegs->HcControlHeadED)) 97 CommandStatus.ControlListFilled = 1; 98 99 if (READ_REGISTER_ULONG((PULONG)&OperationalRegs->HcBulkHeadED)) 100 CommandStatus.BulkListFilled = 1; 101 102 TransferType = OhciEndpoint->EndpointProperties.TransferType; 103 104 if (TransferType == USBPORT_TRANSFER_TYPE_BULK) 105 CommandStatus.BulkListFilled = 1; 106 else if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL) 107 CommandStatus.ControlListFilled = 1; 108 109 WRITE_REGISTER_ULONG(CommandStatusReg, CommandStatus.AsULONG); 110 } 111 112 VOID 113 NTAPI 114 OHCI_InsertEndpointInSchedule(IN POHCI_ENDPOINT OhciEndpoint) 115 { 116 POHCI_STATIC_ED HeadED; 117 POHCI_HCD_ED ED; 118 POHCI_HCD_ED PrevED; 119 PLIST_ENTRY HeadLink; 120 121 DPRINT_OHCI("OHCI_InsertEndpointInSchedule: OhciEndpoint - %p\n", 122 OhciEndpoint); 123 124 ED = OhciEndpoint->HcdED; 125 126 HeadED = OhciEndpoint->HeadED; 127 HeadLink = &HeadED->Link; 128 129 if (IsListEmpty(HeadLink)) 130 { 131 InsertHeadList(HeadLink, &ED->HcdEDLink); 132 133 if (HeadED->Type == OHCI_STATIC_ED_TYPE_CONTROL || 134 HeadED->Type == OHCI_STATIC_ED_TYPE_BULK) 135 { 136 ED->HwED.NextED = READ_REGISTER_ULONG(HeadED->pNextED); 137 WRITE_REGISTER_ULONG(HeadED->pNextED, ED->PhysicalAddress); 138 } 139 else if (HeadED->Type == OHCI_STATIC_ED_TYPE_INTERRUPT) 140 { 141 ED->HwED.NextED = *HeadED->pNextED; 142 *HeadED->pNextED = ED->PhysicalAddress; 143 } 144 else 145 { 146 DPRINT1("OHCI_InsertEndpointInSchedule: Unknown HeadED->Type - %x\n", 147 HeadED->Type); 148 DbgBreakPoint(); 149 } 150 } 151 else 152 { 153 PrevED = CONTAINING_RECORD(HeadLink->Blink, 154 OHCI_HCD_ED, 155 HcdEDLink); 156 157 InsertTailList(HeadLink, &ED->HcdEDLink); 158 159 ED->HwED.NextED = 0; 160 PrevED->HwED.NextED = ED->PhysicalAddress; 161 } 162 } 163 164 POHCI_HCD_ED 165 NTAPI 166 OHCI_InitializeED(IN POHCI_ENDPOINT OhciEndpoint, 167 IN POHCI_HCD_ED ED, 168 IN POHCI_HCD_TD FirstTD, 169 IN ULONG_PTR EdPA) 170 { 171 OHCI_ENDPOINT_CONTROL EndpointControl; 172 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties; 173 174 DPRINT_OHCI("OHCI_InitializeED: OhciEndpoint - %p, ED - %p, FirstTD - %p, EdPA - %p\n", 175 OhciEndpoint, 176 ED, 177 FirstTD, 178 EdPA); 179 180 RtlZeroMemory(ED, sizeof(OHCI_HCD_ED)); 181 182 ED->PhysicalAddress = EdPA; 183 184 EndpointProperties = &OhciEndpoint->EndpointProperties; 185 186 EndpointControl = ED->HwED.EndpointControl; 187 188 EndpointControl.FunctionAddress = EndpointProperties->DeviceAddress; 189 EndpointControl.EndpointNumber = EndpointProperties->EndpointAddress; 190 EndpointControl.MaximumPacketSize = EndpointProperties->TotalMaxPacketSize; 191 192 if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_CONTROL) 193 { 194 EndpointControl.Direction = OHCI_ED_DATA_FLOW_DIRECTION_FROM_TD; 195 } 196 else if (EndpointProperties->Direction) 197 { 198 EndpointControl.Direction = OHCI_ED_DATA_FLOW_DIRECTION_OUT; 199 } 200 else 201 { 202 EndpointControl.Direction = OHCI_ED_DATA_FLOW_DIRECTION_IN; 203 } 204 205 if (EndpointProperties->DeviceSpeed == UsbLowSpeed) 206 EndpointControl.Speed = OHCI_ENDPOINT_LOW_SPEED; 207 208 if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 209 EndpointControl.Format = OHCI_ENDPOINT_ISOCHRONOUS_FORMAT; 210 else 211 EndpointControl.sKip = 1; 212 213 ED->HwED.EndpointControl = EndpointControl; 214 215 ED->HwED.TailPointer = FirstTD->PhysicalAddress; 216 ED->HwED.HeadPointer = FirstTD->PhysicalAddress; 217 218 FirstTD->Flags |= OHCI_HCD_TD_FLAG_ALLOCATED; 219 220 OhciEndpoint->HcdTailP = FirstTD; 221 OhciEndpoint->HcdHeadP = FirstTD; 222 223 return ED; 224 } 225 226 VOID 227 NTAPI 228 OHCI_InitializeTDs(IN POHCI_ENDPOINT OhciEndpoint, 229 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties) 230 { 231 POHCI_HCD_TD TdVA; 232 ULONG TdPA; 233 ULONG TdCount; 234 ULONG ix; 235 236 ASSERT(EndpointProperties->BufferLength > sizeof(OHCI_HCD_ED)); 237 238 TdCount = (EndpointProperties->BufferLength - sizeof(OHCI_HCD_ED)) / 239 sizeof(OHCI_HCD_TD); 240 241 OhciEndpoint->MaxTransferDescriptors = TdCount; 242 243 DPRINT_OHCI("OHCI_InitializeTDs: TdCount - %x\n", TdCount); 244 245 ASSERT(TdCount > 0); 246 247 TdVA = OhciEndpoint->FirstTD; 248 249 TdPA = EndpointProperties->BufferPA + sizeof(OHCI_HCD_ED); 250 251 for (ix = 0; ix < TdCount; ix++) 252 { 253 DPRINT_OHCI("OHCI_InitializeTDs: TdVA - %p, TdPA - %08X\n", TdVA, TdPA); 254 255 RtlZeroMemory(TdVA, sizeof(OHCI_HCD_TD)); 256 257 TdVA->PhysicalAddress = TdPA; 258 TdVA->Flags = 0; 259 TdVA->OhciTransfer = 0; 260 261 TdVA++; 262 TdPA += sizeof(OHCI_HCD_TD); 263 } 264 } 265 266 MPSTATUS 267 NTAPI 268 OHCI_OpenControlEndpoint(IN POHCI_EXTENSION OhciExtension, 269 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 270 IN POHCI_ENDPOINT OhciEndpoint) 271 { 272 POHCI_HCD_ED ED; 273 274 DPRINT_OHCI("OHCI_OpenControlEndpoint: ... \n"); 275 276 ED = (POHCI_HCD_ED)EndpointProperties->BufferVA; 277 278 OhciEndpoint->FirstTD = (POHCI_HCD_TD)((ULONG_PTR)ED + sizeof(OHCI_HCD_ED)); 279 OhciEndpoint->HeadED = &OhciExtension->ControlStaticED; 280 281 OHCI_InitializeTDs(OhciEndpoint, EndpointProperties); 282 283 OhciEndpoint->HcdED = OHCI_InitializeED(OhciEndpoint, 284 ED, 285 OhciEndpoint->FirstTD, 286 EndpointProperties->BufferPA); 287 288 OhciEndpoint->HcdED->Flags = OHCI_HCD_ED_FLAG_CONTROL | 289 OHCI_HCD_ED_FLAG_RESET_ON_HALT; 290 291 OHCI_InsertEndpointInSchedule(OhciEndpoint); 292 293 return MP_STATUS_SUCCESS; 294 } 295 296 MPSTATUS 297 NTAPI 298 OHCI_OpenBulkEndpoint(IN POHCI_EXTENSION OhciExtension, 299 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 300 IN POHCI_ENDPOINT OhciEndpoint) 301 { 302 POHCI_HCD_ED ED; 303 304 DPRINT_OHCI("OHCI_OpenBulkEndpoint: ... \n"); 305 306 ED = (POHCI_HCD_ED)EndpointProperties->BufferVA; 307 308 OhciEndpoint->FirstTD = (POHCI_HCD_TD)((ULONG_PTR)ED + sizeof(OHCI_HCD_ED)); 309 OhciEndpoint->HeadED = &OhciExtension->BulkStaticED; 310 311 OHCI_InitializeTDs(OhciEndpoint, EndpointProperties); 312 313 OhciEndpoint->HcdED = OHCI_InitializeED(OhciEndpoint, 314 ED, 315 OhciEndpoint->FirstTD, 316 EndpointProperties->BufferPA); 317 318 OHCI_InsertEndpointInSchedule(OhciEndpoint); 319 320 return MP_STATUS_SUCCESS; 321 } 322 323 MPSTATUS 324 NTAPI 325 OHCI_OpenInterruptEndpoint(IN POHCI_EXTENSION OhciExtension, 326 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 327 IN POHCI_ENDPOINT OhciEndpoint) 328 { 329 UCHAR Period; 330 ULONG PeriodIdx = 0; 331 POHCI_HCD_ED ED; 332 ULONG ScheduleOffset; 333 334 DPRINT_OHCI("OHCI_OpenInterruptEndpoint: ... \n"); 335 336 ED = (POHCI_HCD_ED)EndpointProperties->BufferVA; 337 338 OhciEndpoint->FirstTD = (POHCI_HCD_TD)((ULONG_PTR)ED + sizeof(OHCI_HCD_ED)); 339 340 Period = EndpointProperties->Period; 341 342 ASSERT(Period != 0); 343 344 while (!(Period & 1)) 345 { 346 PeriodIdx++; 347 Period >>= 1; 348 } 349 350 ASSERT(PeriodIdx < ARRAYSIZE(Index)); 351 352 ScheduleOffset = EndpointProperties->ScheduleOffset; 353 DPRINT_OHCI("OHCI_OpenInterruptEndpoint: InitTD. Index[PeriodIdx] - %x, ScheduleOffset - %x\n", 354 Index[PeriodIdx], 355 ScheduleOffset); 356 357 OhciEndpoint->HeadED = &OhciExtension->IntStaticED[Index[PeriodIdx] + 358 ScheduleOffset]; 359 360 //OhciEndpoint->HeadED->UsbBandwidth += EndpointProperties->UsbBandwidth; 361 362 OHCI_InitializeTDs(OhciEndpoint, EndpointProperties); 363 364 OhciEndpoint->HcdED = OHCI_InitializeED(OhciEndpoint, 365 ED, 366 OhciEndpoint->FirstTD, 367 EndpointProperties->BufferPA); 368 369 OHCI_InsertEndpointInSchedule(OhciEndpoint); 370 371 return MP_STATUS_SUCCESS; 372 } 373 374 MPSTATUS 375 NTAPI 376 OHCI_OpenIsoEndpoint(IN POHCI_EXTENSION OhciExtension, 377 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 378 IN POHCI_ENDPOINT OhciEndpoint) 379 { 380 DPRINT1("OHCI_OpenIsoEndpoint: UNIMPLEMENTED. FIXME\n"); 381 return MP_STATUS_NOT_SUPPORTED; 382 } 383 384 MPSTATUS 385 NTAPI 386 OHCI_OpenEndpoint(IN PVOID ohciExtension, 387 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 388 IN PVOID ohciEndpoint) 389 { 390 POHCI_EXTENSION OhciExtension = ohciExtension; 391 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint; 392 ULONG TransferType; 393 MPSTATUS MPStatus; 394 395 DPRINT_OHCI("OHCI_OpenEndpoint: ... \n"); 396 397 RtlCopyMemory(&OhciEndpoint->EndpointProperties, 398 EndpointProperties, 399 sizeof(OhciEndpoint->EndpointProperties)); 400 401 InitializeListHead(&OhciEndpoint->TDList); 402 403 TransferType = EndpointProperties->TransferType; 404 405 switch (TransferType) 406 { 407 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS: 408 MPStatus = OHCI_OpenIsoEndpoint(OhciExtension, 409 EndpointProperties, 410 OhciEndpoint); 411 break; 412 413 case USBPORT_TRANSFER_TYPE_CONTROL: 414 MPStatus = OHCI_OpenControlEndpoint(OhciExtension, 415 EndpointProperties, 416 OhciEndpoint); 417 break; 418 419 case USBPORT_TRANSFER_TYPE_BULK: 420 MPStatus = OHCI_OpenBulkEndpoint(OhciExtension, 421 EndpointProperties, 422 OhciEndpoint); 423 break; 424 425 case USBPORT_TRANSFER_TYPE_INTERRUPT: 426 MPStatus = OHCI_OpenInterruptEndpoint(OhciExtension, 427 EndpointProperties, 428 OhciEndpoint); 429 break; 430 431 default: 432 MPStatus = MP_STATUS_NOT_SUPPORTED; 433 break; 434 } 435 436 return MPStatus; 437 } 438 439 MPSTATUS 440 NTAPI 441 OHCI_ReopenEndpoint(IN PVOID ohciExtension, 442 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 443 IN PVOID ohciEndpoint) 444 { 445 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint; 446 POHCI_HCD_ED ED; 447 448 DPRINT_OHCI("OHCI_ReopenEndpoint: ... \n"); 449 450 ED = OhciEndpoint->HcdED; 451 452 RtlCopyMemory(&OhciEndpoint->EndpointProperties, 453 EndpointProperties, 454 sizeof(OhciEndpoint->EndpointProperties)); 455 456 ED->HwED.EndpointControl.FunctionAddress = 457 OhciEndpoint->EndpointProperties.DeviceAddress; 458 459 ED->HwED.EndpointControl.MaximumPacketSize = 460 OhciEndpoint->EndpointProperties.TotalMaxPacketSize; 461 462 return MP_STATUS_SUCCESS; 463 } 464 465 VOID 466 NTAPI 467 OHCI_QueryEndpointRequirements(IN PVOID ohciExtension, 468 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 469 IN PUSBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements) 470 { 471 ULONG TransferType; 472 473 DPRINT_OHCI("OHCI_QueryEndpointRequirements: ... \n"); 474 475 TransferType = EndpointProperties->TransferType; 476 477 switch (TransferType) 478 { 479 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS: 480 DPRINT_OHCI("OHCI_QueryEndpointRequirements: IsoTransfer\n"); 481 EndpointRequirements->MaxTransferSize = OHCI_MAX_ISO_TRANSFER_SIZE; 482 EndpointRequirements->HeaderBufferSize = 483 sizeof(OHCI_HCD_ED) + OHCI_MAX_ISO_TD_COUNT * sizeof(OHCI_HCD_TD); 484 break; 485 486 case USBPORT_TRANSFER_TYPE_CONTROL: 487 DPRINT_OHCI("OHCI_QueryEndpointRequirements: ControlTransfer\n"); 488 EndpointRequirements->MaxTransferSize = OHCI_MAX_CONTROL_TRANSFER_SIZE; 489 EndpointRequirements->HeaderBufferSize = 490 sizeof(OHCI_HCD_ED) + OHCI_MAX_CONTROL_TD_COUNT * sizeof(OHCI_HCD_TD); 491 break; 492 493 case USBPORT_TRANSFER_TYPE_BULK: 494 DPRINT_OHCI("OHCI_QueryEndpointRequirements: BulkTransfer\n"); 495 EndpointRequirements->MaxTransferSize = OHCI_MAX_BULK_TRANSFER_SIZE; 496 EndpointRequirements->HeaderBufferSize = 497 sizeof(OHCI_HCD_ED) + OHCI_MAX_BULK_TD_COUNT * sizeof(OHCI_HCD_TD); 498 break; 499 500 case USBPORT_TRANSFER_TYPE_INTERRUPT: 501 DPRINT_OHCI("OHCI_QueryEndpointRequirements: InterruptTransfer\n"); 502 EndpointRequirements->MaxTransferSize = OHCI_MAX_INTERRUPT_TRANSFER_SIZE; 503 EndpointRequirements->HeaderBufferSize = 504 sizeof(OHCI_HCD_ED) + OHCI_MAX_INTERRUPT_TD_COUNT * sizeof(OHCI_HCD_TD); 505 break; 506 507 default: 508 DPRINT1("OHCI_QueryEndpointRequirements: Unknown TransferType - %x\n", 509 TransferType); 510 DbgBreakPoint(); 511 break; 512 } 513 } 514 515 VOID 516 NTAPI 517 OHCI_CloseEndpoint(IN PVOID ohciExtension, 518 IN PVOID ohciEndpoint, 519 IN BOOLEAN IsDoDisablePeriodic) 520 { 521 #if DBG 522 DPRINT1("OHCI_CloseEndpoint: Not supported\n"); 523 #endif 524 return; 525 } 526 527 MPSTATUS 528 NTAPI 529 OHCI_TakeControlHC(IN POHCI_EXTENSION OhciExtension, 530 IN PUSBPORT_RESOURCES Resources) 531 { 532 POHCI_OPERATIONAL_REGISTERS OperationalRegs; 533 PULONG ControlReg; 534 PULONG InterruptEnableReg; 535 PULONG InterruptDisableReg; 536 PULONG CommandStatusReg; 537 PULONG InterruptStatusReg; 538 OHCI_REG_CONTROL Control; 539 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable; 540 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable; 541 OHCI_REG_COMMAND_STATUS CommandStatus; 542 OHCI_REG_INTERRUPT_STATUS IntStatus; 543 LARGE_INTEGER StartTicks, CurrentTicks; 544 UINT32 TicksDiff; 545 546 DPRINT("OHCI_TakeControlHC: ...\n"); 547 548 OperationalRegs = OhciExtension->OperationalRegs; 549 550 ControlReg = (PULONG)&OperationalRegs->HcControl; 551 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable; 552 InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable; 553 CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus; 554 InterruptStatusReg = (PULONG)&OperationalRegs->HcInterruptStatus; 555 556 /* 5.1.1.3 Take Control of Host Controller */ 557 Control.AsULONG = READ_REGISTER_ULONG(ControlReg); 558 559 if (Control.InterruptRouting == 0) 560 return MP_STATUS_SUCCESS; 561 562 DPRINT1("OHCI_TakeControlHC: detected Legacy BIOS\n"); 563 564 IntEnable.AsULONG = READ_REGISTER_ULONG(InterruptEnableReg); 565 566 DPRINT("OHCI_TakeControlHC: Control - %lX, IntEnable - %lX\n", 567 Control.AsULONG, 568 IntEnable.AsULONG); 569 570 if (Control.HostControllerFunctionalState == OHCI_HC_STATE_RESET && 571 IntEnable.AsULONG == 0) 572 { 573 Control.AsULONG = 0; 574 WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG); 575 return MP_STATUS_SUCCESS; 576 } 577 578 /* Enable interrupt generations */ 579 IntEnable.AsULONG = 0; 580 IntEnable.MasterInterruptEnable = 1; 581 582 WRITE_REGISTER_ULONG(InterruptEnableReg, IntEnable.AsULONG); 583 584 /* Request a change of control of the HC */ 585 CommandStatus.AsULONG = 0; 586 CommandStatus.OwnershipChangeRequest = 1; 587 588 WRITE_REGISTER_ULONG(CommandStatusReg, CommandStatus.AsULONG); 589 590 /* Disable interrupt generation due to Root Hub Status Change */ 591 IntDisable.AsULONG = 0; 592 IntDisable.RootHubStatusChange = 1; 593 594 WRITE_REGISTER_ULONG(InterruptDisableReg, IntDisable.AsULONG); 595 596 /* Monitoring the InterruptRouting bit 597 to determine when the ownership change has taken effect. */ 598 599 TicksDiff = (500 * 10000) / KeQueryTimeIncrement(); // 500 ms 600 KeQueryTickCount(&StartTicks); 601 602 do 603 { 604 Control.AsULONG = READ_REGISTER_ULONG(ControlReg); 605 606 if (Control.InterruptRouting == 0) 607 { 608 /* Clear all bits in register */ 609 IntStatus.AsULONG = 0xFFFFFFFF; 610 WRITE_REGISTER_ULONG(InterruptStatusReg, IntStatus.AsULONG); 611 612 /* Disable interrupt generations */ 613 IntDisable.AsULONG = 0; 614 IntDisable.MasterInterruptEnable = 1; 615 616 WRITE_REGISTER_ULONG(InterruptDisableReg, IntDisable.AsULONG); 617 618 return MP_STATUS_SUCCESS; 619 } 620 621 KeQueryTickCount(&CurrentTicks); 622 } 623 while (CurrentTicks.QuadPart - StartTicks.QuadPart < TicksDiff); 624 625 return MP_STATUS_HW_ERROR; 626 } 627 628 MPSTATUS 629 NTAPI 630 OHCI_StartController(IN PVOID ohciExtension, 631 IN PUSBPORT_RESOURCES Resources) 632 { 633 POHCI_EXTENSION OhciExtension = ohciExtension; 634 POHCI_OPERATIONAL_REGISTERS OperationalRegs; 635 PULONG CommandStatusReg; 636 PULONG FmIntervalReg; 637 PULONG ControlReg; 638 PULONG InterruptEnableReg; 639 PULONG RhStatusReg; 640 OHCI_REG_COMMAND_STATUS CommandStatus; 641 OHCI_REG_INTERRUPT_ENABLE_DISABLE Interrupts; 642 OHCI_REG_RH_STATUS RhStatus; 643 OHCI_REG_FRAME_INTERVAL FrameInterval; 644 ULONG MaxFrameIntervalAdjusting; 645 OHCI_REG_CONTROL Control; 646 UCHAR HeadIndex; 647 POHCI_ENDPOINT_DESCRIPTOR IntED; 648 ULONG_PTR IntEdPA; 649 POHCI_HCCA OhciHCCA; 650 LARGE_INTEGER StartTicks, CurrentTicks; 651 UINT32 TicksDiff; 652 ULONG ix; 653 ULONG jx; 654 MPSTATUS MPStatus = MP_STATUS_SUCCESS; 655 656 DPRINT_OHCI("OHCI_StartController: ohciExtension - %p, Resources - %p\n", 657 ohciExtension, 658 Resources); 659 660 /* HC on-chip operational registers */ 661 OperationalRegs = (POHCI_OPERATIONAL_REGISTERS)Resources->ResourceBase; 662 OhciExtension->OperationalRegs = OperationalRegs; 663 664 CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus; 665 FmIntervalReg = (PULONG)&OperationalRegs->HcFmInterval; 666 ControlReg = (PULONG)&OperationalRegs->HcControl; 667 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable; 668 RhStatusReg = (PULONG)&OperationalRegs->HcRhStatus; 669 670 /* 5.1.1 Initialization */ 671 672 MPStatus = OHCI_TakeControlHC(OhciExtension, Resources); 673 674 if (MPStatus != MP_STATUS_SUCCESS) 675 { 676 DPRINT1("OHCI_StartController: OHCI_TakeControlHC return MPStatus - %x\n", 677 MPStatus); 678 679 return MPStatus; 680 } 681 682 OhciExtension->HcResourcesVA = (POHCI_HC_RESOURCES)Resources->StartVA; 683 OhciExtension->HcResourcesPA = Resources->StartPA; 684 685 DPRINT_OHCI("OHCI_StartController: HcResourcesVA - %p, HcResourcesPA - %lx\n", 686 OhciExtension->HcResourcesVA, 687 OhciExtension->HcResourcesPA); 688 689 /* 5.2.7.2 Interrupt */ 690 691 /* Build structure of interrupt static EDs */ 692 for (ix = 0; ix < INTERRUPT_ENDPOINTs; ix++) 693 { 694 IntED = &OhciExtension->HcResourcesVA->InterrruptHeadED[ix]; 695 IntEdPA = OhciExtension->HcResourcesPA + FIELD_OFFSET(OHCI_HC_RESOURCES, InterrruptHeadED[ix]); 696 697 if (ix == (ENDPOINT_INTERRUPT_1ms - 1)) 698 { 699 HeadIndex = ED_EOF; 700 IntED->NextED = 0; 701 } 702 else 703 { 704 HeadIndex = ((ix - 1) / 2); 705 706 ASSERT(HeadIndex >= (ENDPOINT_INTERRUPT_1ms - 1) && 707 HeadIndex < (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms)); 708 709 IntED->NextED = OhciExtension->IntStaticED[HeadIndex].PhysicalAddress; 710 } 711 712 IntED->EndpointControl.sKip = 1; 713 714 IntED->TailPointer = 0; 715 IntED->HeadPointer = 0; 716 717 OhciExtension->IntStaticED[ix].HwED = IntED; 718 OhciExtension->IntStaticED[ix].PhysicalAddress = IntEdPA; 719 OhciExtension->IntStaticED[ix].HeadIndex = HeadIndex; 720 OhciExtension->IntStaticED[ix].pNextED = &IntED->NextED; 721 OhciExtension->IntStaticED[ix].Type = OHCI_STATIC_ED_TYPE_INTERRUPT; 722 723 InitializeListHead(&OhciExtension->IntStaticED[ix].Link); 724 } 725 726 OhciHCCA = &OhciExtension->HcResourcesVA->HcHCCA; 727 DPRINT_OHCI("OHCI_InitializeSchedule: OhciHCCA - %p\n", OhciHCCA); 728 729 /* Set head pointers which start from HCCA */ 730 for (ix = 0, jx = (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms); 731 ix < OHCI_NUMBER_OF_INTERRUPTS; 732 ix++, jx++) 733 { 734 OhciHCCA->InterrruptTable[Balance[ix]] = 735 OhciExtension->IntStaticED[jx].PhysicalAddress; 736 737 OhciExtension->IntStaticED[jx].pNextED = 738 (PULONG)&OhciHCCA->InterrruptTable[Balance[ix]]; 739 740 OhciExtension->IntStaticED[jx].HccaIndex = Balance[ix]; 741 } 742 743 DPRINT_OHCI("OHCI_InitializeSchedule: ix - %x\n", ix); 744 745 /* Init static Control and Bulk EDs head pointers which start from HCCA */ 746 InitializeListHead(&OhciExtension->ControlStaticED.Link); 747 748 OhciExtension->ControlStaticED.HeadIndex = ED_EOF; 749 OhciExtension->ControlStaticED.Type = OHCI_STATIC_ED_TYPE_CONTROL; 750 OhciExtension->ControlStaticED.pNextED = &OperationalRegs->HcControlHeadED; 751 752 InitializeListHead(&OhciExtension->BulkStaticED.Link); 753 754 OhciExtension->BulkStaticED.HeadIndex = ED_EOF; 755 OhciExtension->BulkStaticED.Type = OHCI_STATIC_ED_TYPE_BULK; 756 OhciExtension->BulkStaticED.pNextED = &OperationalRegs->HcBulkHeadED; 757 758 /* 6.3.1 Frame Timing */ 759 FrameInterval.AsULONG = READ_REGISTER_ULONG(FmIntervalReg); 760 761 MaxFrameIntervalAdjusting = OHCI_DEFAULT_FRAME_INTERVAL / 10; // 10% 762 763 if ((FrameInterval.FrameInterval) < (OHCI_DEFAULT_FRAME_INTERVAL - MaxFrameIntervalAdjusting) || 764 (FrameInterval.FrameInterval) > (OHCI_DEFAULT_FRAME_INTERVAL + MaxFrameIntervalAdjusting)) 765 { 766 FrameInterval.FrameInterval = OHCI_DEFAULT_FRAME_INTERVAL; 767 } 768 769 /* 5.4 FrameInterval Counter */ 770 FrameInterval.FrameIntervalToggle = 1; 771 772 /* OHCI_MAXIMUM_OVERHEAD is the maximum overhead per frame */ 773 FrameInterval.FSLargestDataPacket = 774 ((FrameInterval.FrameInterval - OHCI_MAXIMUM_OVERHEAD) * 6) / 7; 775 776 OhciExtension->FrameInterval = FrameInterval; 777 778 DPRINT_OHCI("OHCI_StartController: FrameInterval - %lX\n", 779 FrameInterval.AsULONG); 780 781 /* Reset HostController */ 782 CommandStatus.AsULONG = 0; 783 CommandStatus.HostControllerReset = 1; 784 785 WRITE_REGISTER_ULONG(CommandStatusReg, CommandStatus.AsULONG); 786 787 KeStallExecutionProcessor(25); 788 789 Control.AsULONG = READ_REGISTER_ULONG(ControlReg); 790 Control.HostControllerFunctionalState = OHCI_HC_STATE_RESET; 791 792 WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG); 793 794 TicksDiff = (500 * 10000) / KeQueryTimeIncrement(); // 500 ms 795 KeQueryTickCount(&StartTicks); 796 797 while (TRUE) 798 { 799 WRITE_REGISTER_ULONG(FmIntervalReg, OhciExtension->FrameInterval.AsULONG); 800 FrameInterval.AsULONG = READ_REGISTER_ULONG(FmIntervalReg); 801 802 KeQueryTickCount(&CurrentTicks); 803 804 if (CurrentTicks.QuadPart - StartTicks.QuadPart >= TicksDiff) 805 { 806 MPStatus = MP_STATUS_HW_ERROR; 807 break; 808 } 809 810 if (FrameInterval.AsULONG == OhciExtension->FrameInterval.AsULONG) 811 { 812 MPStatus = MP_STATUS_SUCCESS; 813 break; 814 } 815 } 816 817 if (MPStatus != MP_STATUS_SUCCESS) 818 { 819 DPRINT_OHCI("OHCI_StartController: frame interval not set\n"); 820 return MPStatus; 821 } 822 823 /* Setup HcPeriodicStart register */ 824 WRITE_REGISTER_ULONG(&OperationalRegs->HcPeriodicStart, 825 (OhciExtension->FrameInterval.FrameInterval * 9) / 10); //90% 826 827 /* Setup HcHCCA register */ 828 WRITE_REGISTER_ULONG(&OperationalRegs->HcHCCA, 829 OhciExtension->HcResourcesPA + FIELD_OFFSET(OHCI_HC_RESOURCES, HcHCCA)); 830 831 /* Setup HcInterruptEnable register */ 832 Interrupts.AsULONG = 0; 833 834 Interrupts.SchedulingOverrun = 1; 835 Interrupts.WritebackDoneHead = 1; 836 Interrupts.UnrecoverableError = 1; 837 Interrupts.FrameNumberOverflow = 1; 838 Interrupts.OwnershipChange = 1; 839 840 WRITE_REGISTER_ULONG(InterruptEnableReg, Interrupts.AsULONG); 841 842 /* Setup HcControl register */ 843 Control.AsULONG = READ_REGISTER_ULONG(ControlReg); 844 845 Control.ControlBulkServiceRatio = 0; // FIXME (1 : 1) 846 Control.PeriodicListEnable = 1; 847 Control.IsochronousEnable = 1; 848 Control.ControlListEnable = 1; 849 Control.BulkListEnable = 1; 850 Control.HostControllerFunctionalState = OHCI_HC_STATE_OPERATIONAL; 851 852 WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG); 853 854 /* Setup HcRhStatus register */ 855 RhStatus.AsULONG = 0; 856 RhStatus.SetGlobalPower = 1; 857 858 WRITE_REGISTER_ULONG(RhStatusReg, RhStatus.AsULONG); 859 860 return MP_STATUS_SUCCESS; 861 } 862 863 VOID 864 NTAPI 865 OHCI_StopController(IN PVOID ohciExtension, 866 IN BOOLEAN IsDoDisableInterrupts) 867 { 868 POHCI_EXTENSION OhciExtension = ohciExtension; 869 POHCI_OPERATIONAL_REGISTERS OperationalRegs; 870 PULONG ControlReg; 871 PULONG InterruptDisableReg; 872 PULONG InterruptStatusReg; 873 OHCI_REG_CONTROL Control; 874 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable; 875 OHCI_REG_INTERRUPT_STATUS IntStatus; 876 877 DPRINT("OHCI_StopController: ... \n"); 878 879 OperationalRegs = OhciExtension->OperationalRegs; 880 881 ControlReg = (PULONG)&OperationalRegs->HcControl; 882 InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable; 883 InterruptStatusReg = (PULONG)&OperationalRegs->HcInterruptStatus; 884 885 /* Setup HcControl register */ 886 Control.AsULONG = READ_REGISTER_ULONG(ControlReg); 887 888 Control.PeriodicListEnable = 0; 889 Control.IsochronousEnable = 0; 890 Control.ControlListEnable = 0; 891 Control.BulkListEnable = 0; 892 Control.HostControllerFunctionalState = OHCI_HC_STATE_SUSPEND; 893 Control.RemoteWakeupEnable = 0; 894 895 WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG); 896 897 /* Disable interrupt generations */ 898 IntDisable.AsULONG = 0xFFFFFFFF; 899 WRITE_REGISTER_ULONG(InterruptDisableReg, IntDisable.AsULONG); 900 901 /* Clear all bits in HcInterruptStatus register */ 902 IntStatus.AsULONG = 0xFFFFFFFF; 903 WRITE_REGISTER_ULONG(InterruptStatusReg, IntStatus.AsULONG); 904 } 905 906 VOID 907 NTAPI 908 OHCI_SuspendController(IN PVOID ohciExtension) 909 { 910 POHCI_EXTENSION OhciExtension = ohciExtension; 911 POHCI_OPERATIONAL_REGISTERS OperationalRegs; 912 PULONG ControlReg; 913 PULONG InterruptEnableReg; 914 OHCI_REG_CONTROL Control; 915 OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptReg; 916 917 DPRINT("OHCI_SuspendController: ... \n"); 918 919 OperationalRegs = OhciExtension->OperationalRegs; 920 ControlReg = (PULONG)&OperationalRegs->HcControl; 921 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable; 922 923 /* Disable all interrupt generations */ 924 WRITE_REGISTER_ULONG(&OperationalRegs->HcInterruptDisable.AsULONG, 925 0xFFFFFFFF); 926 927 /* Clear all bits in HcInterruptStatus register */ 928 WRITE_REGISTER_ULONG(&OperationalRegs->HcInterruptStatus.AsULONG, 929 0xFFFFFFFF); 930 931 /* Setup HcControl register */ 932 Control.AsULONG = READ_REGISTER_ULONG(ControlReg); 933 Control.HostControllerFunctionalState = OHCI_HC_STATE_SUSPEND; 934 Control.RemoteWakeupEnable = 1; 935 936 WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG); 937 938 /* Setup HcInterruptEnable register */ 939 InterruptReg.AsULONG = 0; 940 InterruptReg.ResumeDetected = 1; 941 InterruptReg.UnrecoverableError = 1; 942 InterruptReg.RootHubStatusChange = 1; 943 InterruptReg.MasterInterruptEnable = 1; 944 945 WRITE_REGISTER_ULONG(InterruptEnableReg, InterruptReg.AsULONG); 946 } 947 948 MPSTATUS 949 NTAPI 950 OHCI_ResumeController(IN PVOID ohciExtension) 951 { 952 POHCI_EXTENSION OhciExtension = ohciExtension; 953 POHCI_OPERATIONAL_REGISTERS OperationalRegs; 954 PULONG ControlReg; 955 PULONG InterruptEnableReg; 956 POHCI_HCCA HcHCCA; 957 OHCI_REG_CONTROL control; 958 OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptReg; 959 960 DPRINT("OHCI_ResumeController \n"); 961 962 OperationalRegs = OhciExtension->OperationalRegs; 963 ControlReg = (PULONG)&OperationalRegs->HcControl; 964 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable; 965 966 control.AsULONG = READ_REGISTER_ULONG(ControlReg); 967 968 if (control.HostControllerFunctionalState != OHCI_HC_STATE_SUSPEND) 969 return MP_STATUS_HW_ERROR; 970 971 HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA; 972 HcHCCA->Pad1 = 0; 973 974 /* Setup HcControl register */ 975 control.HostControllerFunctionalState = OHCI_HC_STATE_OPERATIONAL; 976 WRITE_REGISTER_ULONG(ControlReg, control.AsULONG); 977 978 /* Setup HcInterruptEnable register */ 979 InterruptReg.AsULONG = 0; 980 InterruptReg.SchedulingOverrun = 1; 981 InterruptReg.WritebackDoneHead = 1; 982 InterruptReg.UnrecoverableError = 1; 983 InterruptReg.FrameNumberOverflow = 1; 984 InterruptReg.OwnershipChange = 1; 985 986 WRITE_REGISTER_ULONG(InterruptEnableReg, InterruptReg.AsULONG); 987 WRITE_REGISTER_ULONG(ControlReg, control.AsULONG); 988 989 return MP_STATUS_SUCCESS; 990 } 991 992 BOOLEAN 993 NTAPI 994 OHCI_HardwarePresent(IN POHCI_EXTENSION OhciExtension, 995 IN BOOLEAN IsInvalidateController) 996 { 997 POHCI_OPERATIONAL_REGISTERS OperationalRegs; 998 PULONG CommandStatusReg; 999 1000 OperationalRegs = OhciExtension->OperationalRegs; 1001 CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus; 1002 1003 if (READ_REGISTER_ULONG(CommandStatusReg) != 0xFFFFFFFF) 1004 return TRUE; 1005 1006 DPRINT1("OHCI_HardwarePresent: IsInvalidateController - %x\n", 1007 IsInvalidateController); 1008 1009 if (IsInvalidateController) 1010 { 1011 RegPacket.UsbPortInvalidateController(OhciExtension, 1012 USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE); 1013 } 1014 1015 return FALSE; 1016 } 1017 1018 BOOLEAN 1019 NTAPI 1020 OHCI_InterruptService(IN PVOID ohciExtension) 1021 { 1022 POHCI_EXTENSION OhciExtension = ohciExtension; 1023 POHCI_OPERATIONAL_REGISTERS OperationalRegs; 1024 OHCI_REG_INTERRUPT_STATUS IntStatus; 1025 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable; 1026 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable; 1027 BOOLEAN HardwarePresent = FALSE; 1028 1029 DPRINT_OHCI("OHCI_Interrupt: Ext %p\n", OhciExtension); 1030 1031 OperationalRegs = OhciExtension->OperationalRegs; 1032 1033 HardwarePresent = OHCI_HardwarePresent(OhciExtension, FALSE); 1034 1035 if (!HardwarePresent) 1036 return FALSE; 1037 1038 IntEnable.AsULONG = READ_REGISTER_ULONG((PULONG)&OperationalRegs->HcInterruptEnable); 1039 IntStatus.AsULONG = READ_REGISTER_ULONG((PULONG)&OperationalRegs->HcInterruptStatus) & IntEnable.AsULONG; 1040 1041 if ((IntStatus.AsULONG == 0) || (IntEnable.MasterInterruptEnable == 0)) 1042 return FALSE; 1043 1044 if (IntStatus.UnrecoverableError) 1045 DPRINT1("OHCI_InterruptService: IntStatus.UnrecoverableError\n"); 1046 1047 if (IntStatus.FrameNumberOverflow) 1048 { 1049 POHCI_HCCA HcHCCA; 1050 ULONG fm; 1051 ULONG hp; 1052 1053 HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA; 1054 1055 DPRINT("FrameNumberOverflow %lX\n", HcHCCA->FrameNumber); 1056 1057 hp = OhciExtension->FrameHighPart; 1058 fm = HcHCCA->FrameNumber; 1059 1060 /* Increment value of FrameHighPart */ 1061 OhciExtension->FrameHighPart += 1 * (1 << 16) - ((hp ^ fm) & 0x8000); 1062 } 1063 1064 /* Disable interrupt generation */ 1065 IntDisable.AsULONG = 0; 1066 IntDisable.MasterInterruptEnable = 1; 1067 WRITE_REGISTER_ULONG((PULONG)&OperationalRegs->HcInterruptDisable, 1068 IntDisable.AsULONG); 1069 1070 return TRUE; 1071 } 1072 1073 VOID 1074 NTAPI 1075 OHCI_InterruptDpc(IN PVOID ohciExtension, 1076 IN BOOLEAN IsDoEnableInterrupts) 1077 { 1078 POHCI_EXTENSION OhciExtension = ohciExtension; 1079 POHCI_OPERATIONAL_REGISTERS OperationalRegs; 1080 PULONG InterruptDisableReg; 1081 PULONG InterruptEnableReg; 1082 PULONG InterruptStatusReg; 1083 OHCI_REG_INTERRUPT_STATUS IntStatus; 1084 OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptBits; 1085 POHCI_HCCA HcHCCA; 1086 1087 OperationalRegs = OhciExtension->OperationalRegs; 1088 1089 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable; 1090 InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable; 1091 InterruptStatusReg = (PULONG)&OperationalRegs->HcInterruptStatus; 1092 1093 DPRINT_OHCI("OHCI_InterruptDpc: OhciExtension - %p, IsDoEnableInterrupts - %x\n", 1094 OhciExtension, 1095 IsDoEnableInterrupts); 1096 1097 IntStatus.AsULONG = READ_REGISTER_ULONG(InterruptStatusReg); 1098 1099 if (IntStatus.RootHubStatusChange) 1100 { 1101 DPRINT_OHCI("OHCI_InterruptDpc: RootHubStatusChange\n"); 1102 RegPacket.UsbPortInvalidateRootHub(OhciExtension); 1103 } 1104 1105 if (IntStatus.WritebackDoneHead) 1106 { 1107 DPRINT_OHCI("OHCI_InterruptDpc: WritebackDoneHead\n"); 1108 1109 HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA; 1110 HcHCCA->DoneHead = 0; 1111 1112 RegPacket.UsbPortInvalidateEndpoint(OhciExtension, NULL); 1113 } 1114 1115 if (IntStatus.StartofFrame) 1116 { 1117 /* Disable interrupt generation due to Start of Frame */ 1118 InterruptBits.AsULONG = 0; 1119 InterruptBits.StartofFrame = 1; 1120 1121 WRITE_REGISTER_ULONG(InterruptDisableReg, InterruptBits.AsULONG); 1122 } 1123 1124 if (IntStatus.ResumeDetected) 1125 DPRINT1("OHCI_IntDpc: ResumeDetected\n"); 1126 1127 if (IntStatus.UnrecoverableError) 1128 { 1129 DPRINT1("OHCI_IntDpc: UnrecoverableError\n"); 1130 } 1131 1132 WRITE_REGISTER_ULONG(InterruptStatusReg, IntStatus.AsULONG); 1133 1134 if (IsDoEnableInterrupts) 1135 { 1136 /* Enable interrupt generation */ 1137 InterruptBits.AsULONG = 0; 1138 InterruptBits.MasterInterruptEnable = 1; 1139 1140 WRITE_REGISTER_ULONG(InterruptEnableReg, InterruptBits.AsULONG); 1141 } 1142 } 1143 1144 /** 1145 * @brief Forms the next General Transfer Descriptor for the current transfer 1146 * 1147 * @param[in] OhciExtension The ohci extension 1148 * @param[in] TransferedLen The consolidated length of all previous descriptors' buffers 1149 * @param[in] OhciTransfer The ohci transfer 1150 * @param[out] TD The transfer descriptor we are forming 1151 * @param[in] SGList The scatter/gather list 1152 * 1153 * @return The length of all previous buffers summed with the length of the current buffer 1154 */ 1155 static 1156 ULONG 1157 OHCI_MapTransferToTD(IN POHCI_EXTENSION OhciExtension, 1158 IN ULONG TransferedLen, 1159 IN POHCI_TRANSFER OhciTransfer, 1160 OUT POHCI_HCD_TD TD, 1161 IN PUSBPORT_SCATTER_GATHER_LIST SGList) 1162 { 1163 PUSBPORT_SCATTER_GATHER_ELEMENT SgElement; 1164 ULONG SgIdx, CurrentTransferLen, BufferEnd, CurrentBuffer; 1165 ULONG TransferDataLeft = OhciTransfer->TransferParameters->TransferBufferLength - TransferedLen; 1166 1167 DPRINT_OHCI("OHCI_MapTransferToTD: TransferedLen - %x\n", TransferedLen); 1168 1169 for (SgIdx = 0; SgIdx < SGList->SgElementCount; SgIdx++) 1170 { 1171 SgElement = &SGList->SgElement[SgIdx]; 1172 1173 if (TransferedLen >= SgElement->SgOffset && 1174 TransferedLen < SgElement->SgOffset + SgElement->SgTransferLength) 1175 { 1176 break; 1177 } 1178 } 1179 1180 DPRINT_OHCI("OHCI_MapTransferToTD: SgIdx - %x, SgCount - %x\n", 1181 SgIdx, 1182 SGList->SgElementCount); 1183 1184 ASSERT(SgIdx < SGList->SgElementCount); 1185 ASSERT(TransferedLen == SgElement->SgOffset); 1186 1187 /* The buffer for a TD can be 0 to 8192 bytes long, 1188 * and can span within mo more than two 4k pages (see OpenHCI spec 3.3.2) 1189 * CurrentBuffer - the (physical) address of the first byte in the buffer 1190 * BufferEnd - the address of the last byte in the buffer. It can be on a different physical 4k page 1191 * when a controller will reach the end of a page from CurrentBuffer, it will take the first 20 bits 1192 * of the BufferEnd as a next address (OpenHCI spec, 4.3.1.3.1) 1193 */ 1194 1195 CurrentBuffer = SgElement->SgPhysicalAddress.LowPart; 1196 1197 if (TransferDataLeft <= SgElement->SgTransferLength) 1198 { 1199 CurrentTransferLen = TransferDataLeft; 1200 BufferEnd = SgElement->SgPhysicalAddress.LowPart + CurrentTransferLen - 1; 1201 } 1202 else 1203 { 1204 PUSBPORT_SCATTER_GATHER_ELEMENT SgNextElement; 1205 ASSERT(SGList->SgElementCount - SgIdx > 1); 1206 1207 SgNextElement = &SGList->SgElement[SgIdx + 1]; 1208 1209 TransferDataLeft -= SgElement->SgTransferLength; 1210 CurrentTransferLen = SgElement->SgTransferLength; 1211 1212 if (TransferDataLeft <= SgNextElement->SgTransferLength) 1213 { 1214 CurrentTransferLen += TransferDataLeft; 1215 BufferEnd = SgNextElement->SgPhysicalAddress.LowPart + TransferDataLeft - 1; 1216 } 1217 else 1218 { 1219 CurrentTransferLen += SgNextElement->SgTransferLength; 1220 BufferEnd = SgNextElement->SgPhysicalAddress.LowPart + SgNextElement->SgTransferLength - 1; 1221 } 1222 } 1223 1224 TD->HwTD.gTD.CurrentBuffer = CurrentBuffer; 1225 TD->HwTD.gTD.BufferEnd = BufferEnd; 1226 TD->TransferLen = CurrentTransferLen; 1227 1228 return TransferedLen + CurrentTransferLen; 1229 } 1230 1231 POHCI_HCD_TD 1232 NTAPI 1233 OHCI_AllocateTD(IN POHCI_EXTENSION OhciExtension, 1234 IN POHCI_ENDPOINT OhciEndpoint) 1235 { 1236 POHCI_HCD_TD TD; 1237 1238 DPRINT_OHCI("OHCI_AllocateTD: ... \n"); 1239 1240 TD = OhciEndpoint->FirstTD; 1241 1242 while (TD->Flags & OHCI_HCD_TD_FLAG_ALLOCATED) 1243 { 1244 TD += 1; 1245 } 1246 1247 TD->Flags |= OHCI_HCD_TD_FLAG_ALLOCATED; 1248 1249 RtlSecureZeroMemory(&TD->HwTD, sizeof(TD->HwTD)); 1250 1251 return TD; 1252 } 1253 1254 ULONG 1255 NTAPI 1256 OHCI_RemainTDs(IN POHCI_EXTENSION OhciExtension, 1257 IN POHCI_ENDPOINT OhciEndpoint) 1258 { 1259 POHCI_HCD_TD TD; 1260 ULONG MaxTDs; 1261 ULONG RemainTDs; 1262 ULONG ix; 1263 1264 DPRINT_OHCI("OHCI_RemainTDs: ... \n"); 1265 1266 MaxTDs = OhciEndpoint->MaxTransferDescriptors; 1267 TD = OhciEndpoint->FirstTD; 1268 1269 RemainTDs = 0; 1270 1271 for (ix = 0; ix < MaxTDs; ix++) 1272 { 1273 if (!(TD->Flags & OHCI_HCD_TD_FLAG_ALLOCATED)) 1274 RemainTDs++; 1275 1276 TD += 1; 1277 } 1278 1279 return RemainTDs; 1280 } 1281 1282 static 1283 MPSTATUS 1284 OHCI_ControlTransfer(IN POHCI_EXTENSION OhciExtension, 1285 IN POHCI_ENDPOINT OhciEndpoint, 1286 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, 1287 IN POHCI_TRANSFER OhciTransfer, 1288 IN PUSBPORT_SCATTER_GATHER_LIST SGList) 1289 { 1290 POHCI_HCD_TD SetupTD; 1291 POHCI_HCD_TD TD; 1292 POHCI_HCD_TD PrevTD; 1293 ULONG MaxTDs; 1294 ULONG TransferedLen; 1295 UCHAR DataToggle; 1296 1297 DPRINT_OHCI("OHCI_ControlTransfer: Ext %p, Endpoint %p\n", 1298 OhciExtension, 1299 OhciEndpoint); 1300 1301 MaxTDs = OHCI_RemainTDs(OhciExtension, OhciEndpoint); 1302 1303 if ((SGList->SgElementCount + OHCI_NON_DATA_CONTROL_TDS) > MaxTDs) 1304 return MP_STATUS_FAILURE; 1305 1306 /* Form a setup packet first */ 1307 SetupTD = OhciEndpoint->HcdTailP; 1308 RtlSecureZeroMemory(&SetupTD->HwTD, sizeof(SetupTD->HwTD)); 1309 1310 SetupTD->Flags |= OHCI_HCD_TD_FLAG_PROCESSED; 1311 SetupTD->OhciTransfer = OhciTransfer; 1312 1313 OhciTransfer->PendingTDs++; 1314 1315 RtlCopyMemory(&SetupTD->HwTD.SetupPacket, 1316 &TransferParameters->SetupPacket, 1317 sizeof(SetupTD->HwTD.SetupPacket)); 1318 1319 SetupTD->HwTD.gTD.CurrentBuffer = SetupTD->PhysicalAddress + FIELD_OFFSET(OHCI_HCD_TD, HwTD.SetupPacket); 1320 SetupTD->HwTD.gTD.BufferEnd = SetupTD->PhysicalAddress + FIELD_OFFSET(OHCI_HCD_TD, HwTD.SetupPacket) + 1321 sizeof(USB_DEFAULT_PIPE_SETUP_PACKET) - 1; 1322 SetupTD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE; 1323 SetupTD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NOT_ACCESSED; 1324 SetupTD->HwTD.gTD.Control.DataToggle = OHCI_TD_DATA_TOGGLE_DATA0; 1325 1326 PrevTD = SetupTD; 1327 1328 /* Data packets follow a setup packet (if any) */ 1329 TD = OHCI_AllocateTD(OhciExtension, OhciEndpoint); 1330 TD->Flags |= OHCI_HCD_TD_FLAG_PROCESSED; 1331 TD->OhciTransfer = OhciTransfer; 1332 1333 PrevTD->HwTD.gTD.NextTD = TD->PhysicalAddress; 1334 PrevTD->NextTDVa = TD; 1335 1336 /* The first data packet should use DATA1, subsequent ones use DATA0 (OpenHCI spec, 4.3.1.3.4) */ 1337 DataToggle = OHCI_TD_DATA_TOGGLE_DATA1; 1338 TransferedLen = 0; 1339 1340 while (TransferedLen < TransferParameters->TransferBufferLength) 1341 { 1342 OhciTransfer->PendingTDs++; 1343 1344 if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) 1345 TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_IN; 1346 else 1347 TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_OUT; 1348 1349 TD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE; 1350 TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NOT_ACCESSED; 1351 TD->HwTD.gTD.Control.DataToggle = DataToggle; 1352 1353 TransferedLen = OHCI_MapTransferToTD(OhciExtension, 1354 TransferedLen, 1355 OhciTransfer, 1356 TD, 1357 SGList); 1358 1359 PrevTD = TD; 1360 1361 TD = OHCI_AllocateTD(OhciExtension, OhciEndpoint); 1362 TD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE; 1363 TD->Flags |= OHCI_HCD_TD_FLAG_PROCESSED; 1364 TD->OhciTransfer = OhciTransfer; 1365 1366 PrevTD->HwTD.gTD.NextTD = TD->PhysicalAddress; 1367 PrevTD->NextTDVa = TD; 1368 1369 DataToggle = OHCI_TD_DATA_TOGGLE_DATA0; 1370 } 1371 1372 if (TransferParameters->TransferFlags & USBD_SHORT_TRANSFER_OK) 1373 { 1374 PrevTD->HwTD.gTD.Control.BufferRounding = TRUE; 1375 OhciTransfer->Flags |= OHCI_TRANSFER_FLAGS_SHORT_TRANSFER_OK; 1376 } 1377 1378 /* After data packets, goes a status packet */ 1379 1380 TD->Flags |= OHCI_HCD_TD_FLAG_CONTROL_STATUS; 1381 TD->TransferLen = 0; 1382 1383 if ((TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) != 0) 1384 { 1385 TD->HwTD.gTD.Control.BufferRounding = FALSE; 1386 TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_OUT; 1387 } 1388 else 1389 { 1390 TD->HwTD.gTD.Control.BufferRounding = TRUE; 1391 TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_IN; 1392 } 1393 1394 /* OpenHCI spec, 4.3.1.3.4 */ 1395 TD->HwTD.gTD.Control.DataToggle = OHCI_TD_DATA_TOGGLE_DATA1; 1396 TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NOT_ACCESSED; 1397 TD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_IMMEDIATE; 1398 1399 OhciTransfer->PendingTDs++; 1400 OhciTransfer->ControlStatusTD = TD; 1401 1402 PrevTD = TD; 1403 1404 /* And the last descriptor, which is not used in the current transfer (OpenHCI spec, 4.6) */ 1405 TD = OHCI_AllocateTD(OhciExtension, OhciEndpoint); 1406 1407 PrevTD->HwTD.gTD.NextTD = TD->PhysicalAddress; 1408 PrevTD->NextTDVa = TD; 1409 1410 TD->NextTDVa = NULL; 1411 /* TD->HwTD.gTD.NextTD = 0; */ 1412 1413 OhciTransfer->NextTD = TD; 1414 OhciEndpoint->HcdTailP = TD; 1415 1416 OhciEndpoint->HcdED->HwED.TailPointer = TD->PhysicalAddress; 1417 1418 OHCI_EnableList(OhciExtension, OhciEndpoint); 1419 1420 return MP_STATUS_SUCCESS; 1421 } 1422 1423 static 1424 MPSTATUS 1425 OHCI_BulkOrInterruptTransfer(IN POHCI_EXTENSION OhciExtension, 1426 IN POHCI_ENDPOINT OhciEndpoint, 1427 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, 1428 IN POHCI_TRANSFER OhciTransfer, 1429 IN PUSBPORT_SCATTER_GATHER_LIST SGList) 1430 { 1431 POHCI_HCD_TD TD; 1432 POHCI_HCD_TD PrevTD; 1433 ULONG TransferedLen; 1434 ULONG MaxTDs; 1435 1436 DPRINT_OHCI("OHCI_BulkOrInterruptTransfer: ... \n"); 1437 1438 MaxTDs = OHCI_RemainTDs(OhciExtension, OhciEndpoint); 1439 1440 if (SGList->SgElementCount > MaxTDs) 1441 return MP_STATUS_FAILURE; 1442 1443 TD = OhciEndpoint->HcdTailP; 1444 1445 TransferedLen = 0; 1446 1447 do 1448 { 1449 TD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_NONE; 1450 TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NOT_ACCESSED; 1451 1452 if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) 1453 { 1454 TD->HwTD.gTD.Control.BufferRounding = FALSE; 1455 TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_IN; 1456 } 1457 else 1458 { 1459 TD->HwTD.gTD.Control.BufferRounding = TRUE; 1460 TD->HwTD.gTD.Control.DirectionPID = OHCI_TD_DIRECTION_PID_OUT; 1461 } 1462 1463 TD->Flags |= OHCI_HCD_TD_FLAG_PROCESSED; 1464 TD->OhciTransfer = OhciTransfer; 1465 1466 if (TransferParameters->TransferBufferLength) 1467 { 1468 TransferedLen = OHCI_MapTransferToTD(OhciExtension, 1469 TransferedLen, 1470 OhciTransfer, 1471 TD, 1472 SGList); 1473 } 1474 else 1475 { 1476 ASSERT(SGList->SgElementCount == 0); 1477 TD->TransferLen = 0; 1478 } 1479 1480 PrevTD = TD; 1481 1482 TD = OHCI_AllocateTD(OhciExtension, OhciEndpoint); 1483 OhciTransfer->PendingTDs++; 1484 1485 PrevTD->HwTD.gTD.NextTD = TD->PhysicalAddress; 1486 PrevTD->NextTDVa = TD; 1487 } 1488 while (TransferedLen < TransferParameters->TransferBufferLength); 1489 1490 if (TransferParameters->TransferFlags & USBD_SHORT_TRANSFER_OK) 1491 { 1492 PrevTD->HwTD.gTD.Control.BufferRounding = TRUE; 1493 OhciTransfer->Flags |= OHCI_TRANSFER_FLAGS_SHORT_TRANSFER_OK; 1494 } 1495 1496 PrevTD->HwTD.gTD.Control.DelayInterrupt = OHCI_TD_INTERRUPT_IMMEDIATE; 1497 1498 /* The last TD in a chain is not used in a transfer. The controller does not access it 1499 * so it will be used for chaining a next transfer to it (OpenHCI spec, 4.6) 1500 */ 1501 /* TD->HwTD.gTD.NextTD = 0; */ 1502 TD->NextTDVa = NULL; 1503 1504 OhciTransfer->NextTD = TD; 1505 OhciEndpoint->HcdTailP = TD; 1506 1507 OhciEndpoint->HcdED->HwED.TailPointer = TD->PhysicalAddress; 1508 1509 OHCI_EnableList(OhciExtension, OhciEndpoint); 1510 1511 return MP_STATUS_SUCCESS; 1512 } 1513 1514 /** 1515 * @brief Creates the transfer descriptor chain for the given transfer's buffer 1516 * and attaches it to a given endpoint (for control, bulk or interrupt transfers) 1517 * 1518 * @param[in] OhciExtension The ohci extension 1519 * @param[in] OhciEndpoint The ohci endpoint 1520 * @param[in] TransferParameters The transfer parameters 1521 * @param[in] OhciTransfer The ohci transfer 1522 * @param[in] SGList The scatter/gather list 1523 * 1524 * @return MP_STATUS_SUCCESS or MP_STATUS_FAILURE if there are not enough TDs left 1525 * or wrong transfer type given 1526 */ 1527 MPSTATUS 1528 NTAPI 1529 OHCI_SubmitTransfer(IN PVOID ohciExtension, 1530 IN PVOID ohciEndpoint, 1531 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, 1532 IN PVOID ohciTransfer, 1533 IN PUSBPORT_SCATTER_GATHER_LIST SGList) 1534 { 1535 POHCI_EXTENSION OhciExtension = ohciExtension; 1536 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint; 1537 POHCI_TRANSFER OhciTransfer = ohciTransfer; 1538 ULONG TransferType; 1539 1540 DPRINT_OHCI("OHCI_SubmitTransfer: ... \n"); 1541 1542 RtlZeroMemory(OhciTransfer, sizeof(OHCI_TRANSFER)); 1543 1544 OhciTransfer->TransferParameters = TransferParameters; 1545 OhciTransfer->OhciEndpoint = OhciEndpoint; 1546 1547 TransferType = OhciEndpoint->EndpointProperties.TransferType; 1548 1549 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL) 1550 { 1551 return OHCI_ControlTransfer(OhciExtension, 1552 OhciEndpoint, 1553 TransferParameters, 1554 OhciTransfer, 1555 SGList); 1556 } 1557 1558 if (TransferType == USBPORT_TRANSFER_TYPE_BULK || 1559 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 1560 { 1561 return OHCI_BulkOrInterruptTransfer(OhciExtension, 1562 OhciEndpoint, 1563 TransferParameters, 1564 OhciTransfer, 1565 SGList); 1566 } 1567 1568 return MP_STATUS_FAILURE; 1569 } 1570 1571 MPSTATUS 1572 NTAPI 1573 OHCI_SubmitIsoTransfer(IN PVOID ohciExtension, 1574 IN PVOID ohciEndpoint, 1575 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, 1576 IN PVOID ohciTransfer, 1577 IN PVOID isoParameters) 1578 { 1579 DPRINT1("OHCI_SubmitIsoTransfer: UNIMPLEMENTED. FIXME\n"); 1580 return MP_STATUS_SUCCESS; 1581 } 1582 1583 VOID 1584 NTAPI 1585 OHCI_ProcessDoneTD(IN POHCI_EXTENSION OhciExtension, 1586 IN POHCI_HCD_TD TD, 1587 IN BOOLEAN IsPortComplete) 1588 { 1589 POHCI_TRANSFER OhciTransfer; 1590 POHCI_ENDPOINT OhciEndpoint; 1591 ULONG Buffer; 1592 ULONG BufferEnd; 1593 ULONG Length; 1594 1595 DPRINT_OHCI("OHCI_ProcessDoneTD: ... \n"); 1596 1597 OhciTransfer = TD->OhciTransfer; 1598 OhciEndpoint = OhciTransfer->OhciEndpoint; 1599 1600 OhciTransfer->PendingTDs--; 1601 1602 Buffer = TD->HwTD.gTD.CurrentBuffer; 1603 BufferEnd = TD->HwTD.gTD.BufferEnd; 1604 1605 if (TD->Flags & OHCI_HCD_TD_FLAG_NOT_ACCESSED) 1606 { 1607 TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NO_ERROR; 1608 } 1609 else 1610 { 1611 if (TD->HwTD.gTD.CurrentBuffer) 1612 { 1613 if (TD->TransferLen) 1614 { 1615 Length = (BufferEnd & (PAGE_SIZE - 1)) - 1616 (Buffer & (PAGE_SIZE - 1)); 1617 1618 Length++; 1619 1620 if (Buffer >> PAGE_SHIFT != BufferEnd >> PAGE_SHIFT) 1621 Length += PAGE_SIZE; 1622 1623 TD->TransferLen -= Length; 1624 } 1625 } 1626 1627 if (TD->HwTD.gTD.Control.DirectionPID != OHCI_TD_DIRECTION_PID_SETUP) 1628 OhciTransfer->TransferLen += TD->TransferLen; 1629 1630 if (TD->HwTD.gTD.Control.ConditionCode) 1631 { 1632 OhciTransfer->USBDStatus = USBD_STATUS_HALTED | 1633 TD->HwTD.gTD.Control.ConditionCode; 1634 } 1635 } 1636 1637 TD->Flags = 0; 1638 TD->HwTD.gTD.NextTD = 0; 1639 TD->OhciTransfer = 0; 1640 1641 TD->DoneLink.Flink = NULL; 1642 TD->DoneLink.Blink = NULL; 1643 1644 if (IsPortComplete && (OhciTransfer->PendingTDs == 0)) 1645 { 1646 RegPacket.UsbPortCompleteTransfer(OhciExtension, 1647 OhciEndpoint, 1648 OhciTransfer->TransferParameters, 1649 OhciTransfer->USBDStatus, 1650 OhciTransfer->TransferLen); 1651 } 1652 } 1653 1654 VOID 1655 NTAPI 1656 OHCI_ProcessDoneIsoTD(IN POHCI_EXTENSION OhciExtension, 1657 IN POHCI_HCD_TD TD, 1658 IN BOOLEAN IsPortComplete) 1659 { 1660 DPRINT1("OHCI_ProcessDoneIsoTD: UNIMPLEMENTED. FIXME\n"); 1661 } 1662 1663 /** 1664 * @brief Aborts the transfer descriptor chain in a given endpoint 1665 * 1666 * @param[in] ohciExtension The ohci extension 1667 * @param[in] ohciEndpoint The ohci endpoint 1668 * @param[in] ohciTransfer The ohci transfer 1669 * @param[out] CompletedLength 1670 */ 1671 VOID 1672 NTAPI 1673 OHCI_AbortTransfer(IN PVOID ohciExtension, 1674 IN PVOID ohciEndpoint, 1675 IN PVOID ohciTransfer, 1676 IN OUT PULONG CompletedLength) 1677 { 1678 POHCI_EXTENSION OhciExtension = ohciExtension; 1679 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint; 1680 POHCI_TRANSFER OhciTransfer = ohciTransfer; 1681 POHCI_HCD_ED ED = OhciEndpoint->HcdED; 1682 POHCI_HCD_TD TD, NextTD, LastTD; 1683 ULONG ix; 1684 BOOLEAN IsIsoEndpoint; 1685 BOOLEAN IsProcessed = FALSE; 1686 1687 DPRINT("OHCI_AbortTransfer: ohciEndpoint - %p, ohciTransfer - %p\n", 1688 OhciEndpoint, 1689 OhciTransfer); 1690 1691 IsIsoEndpoint = (OhciEndpoint->EndpointProperties.TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS); 1692 NextTD = RegPacket.UsbPortGetMappedVirtualAddress(ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_MASK, 1693 OhciExtension, 1694 OhciEndpoint); 1695 1696 if (NextTD->OhciTransfer == OhciTransfer) 1697 { 1698 LastTD = OhciTransfer->NextTD; 1699 1700 /* Keeping the carry bit from previous pointer value */ 1701 ED->HwED.HeadPointer = LastTD->PhysicalAddress | 1702 (ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_CARRY); 1703 1704 OhciEndpoint->HcdHeadP = LastTD; 1705 1706 for (ix = 0; ix < OhciEndpoint->MaxTransferDescriptors; ix++) 1707 { 1708 TD = &OhciEndpoint->FirstTD[ix]; 1709 1710 if (TD->OhciTransfer != OhciTransfer) 1711 continue; 1712 1713 if (IsIsoEndpoint) 1714 OHCI_ProcessDoneIsoTD(OhciExtension, TD, FALSE); 1715 else 1716 OHCI_ProcessDoneTD(OhciExtension, TD, FALSE); 1717 } 1718 1719 *CompletedLength = OhciTransfer->TransferLen; 1720 return; 1721 } 1722 1723 if (NextTD == OhciEndpoint->HcdHeadP) 1724 IsProcessed = TRUE; 1725 1726 for (TD = OhciEndpoint->HcdHeadP; TD != NextTD; TD = TD->NextTDVa) 1727 { 1728 if (TD->OhciTransfer != OhciTransfer) 1729 continue; 1730 1731 if (OhciEndpoint->HcdHeadP == TD) 1732 OhciEndpoint->HcdHeadP = TD->NextTDVa; 1733 1734 if (IsIsoEndpoint) 1735 OHCI_ProcessDoneIsoTD(OhciExtension, TD, FALSE); 1736 else 1737 OHCI_ProcessDoneTD(OhciExtension, TD, FALSE); 1738 1739 IsProcessed = TRUE; 1740 } 1741 1742 if (!IsProcessed) 1743 { 1744 for (TD = OhciEndpoint->HcdHeadP; TD->OhciTransfer != OhciTransfer; TD = TD->NextTDVa) 1745 { 1746 if (TD == OhciEndpoint->HcdTailP) 1747 { 1748 TD = NULL; 1749 break; 1750 } 1751 LastTD = TD; 1752 } 1753 1754 for (; TD->OhciTransfer == OhciTransfer; TD = TD->NextTDVa) 1755 { 1756 if (TD == OhciEndpoint->HcdTailP) 1757 break; 1758 1759 if (IsIsoEndpoint) 1760 OHCI_ProcessDoneIsoTD(OhciExtension, TD, FALSE); 1761 else 1762 OHCI_ProcessDoneTD(OhciExtension, TD, FALSE); 1763 } 1764 1765 LastTD->OhciTransfer->NextTD = TD; 1766 1767 LastTD->NextTDVa = TD; 1768 LastTD->HwTD.gTD.NextTD = TD->PhysicalAddress; 1769 } 1770 1771 *CompletedLength = OhciTransfer->TransferLen; 1772 1773 if (OhciTransfer->TransferLen) 1774 { 1775 DPRINT("OHCI_AbortTransfer: *CompletedLength - %x\n", *CompletedLength); 1776 } 1777 } 1778 1779 ULONG 1780 NTAPI 1781 OHCI_GetEndpointState(IN PVOID ohciExtension, 1782 IN PVOID ohciEndpoint) 1783 { 1784 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint; 1785 POHCI_HCD_ED ED; 1786 1787 DPRINT_OHCI("OHCI_GetEndpointState: ... \n"); 1788 1789 ED = OhciEndpoint->HcdED; 1790 1791 if (ED->Flags & OHCI_HCD_TD_FLAG_NOT_ACCESSED) 1792 return USBPORT_ENDPOINT_REMOVE; 1793 1794 if (ED->HwED.EndpointControl.sKip) 1795 return USBPORT_ENDPOINT_PAUSED; 1796 1797 return USBPORT_ENDPOINT_ACTIVE; 1798 } 1799 1800 VOID 1801 NTAPI 1802 OHCI_RemoveEndpointFromSchedule(IN POHCI_ENDPOINT OhciEndpoint) 1803 { 1804 POHCI_HCD_ED ED; 1805 POHCI_HCD_ED PreviousED; 1806 POHCI_STATIC_ED HeadED; 1807 1808 DPRINT_OHCI("OHCI_RemoveEndpointFromSchedule \n"); 1809 1810 ED = OhciEndpoint->HcdED; 1811 HeadED = OhciEndpoint->HeadED; 1812 1813 if (&HeadED->Link == ED->HcdEDLink.Blink) 1814 { 1815 if (HeadED->Type == OHCI_STATIC_ED_TYPE_CONTROL || 1816 HeadED->Type == OHCI_STATIC_ED_TYPE_BULK) 1817 { 1818 WRITE_REGISTER_ULONG(HeadED->pNextED, ED->HwED.NextED); 1819 } 1820 else if (HeadED->Type == OHCI_STATIC_ED_TYPE_INTERRUPT) 1821 { 1822 *HeadED->pNextED = ED->HwED.NextED; 1823 } 1824 else 1825 { 1826 DPRINT1("OHCI_RemoveEndpointFromSchedule: Unknown HeadED->Type - %x\n", 1827 HeadED->Type); 1828 DbgBreakPoint(); 1829 } 1830 } 1831 else 1832 { 1833 PreviousED = CONTAINING_RECORD(ED->HcdEDLink.Blink, 1834 OHCI_HCD_ED, 1835 HcdEDLink); 1836 1837 PreviousED->HwED.NextED = ED->HwED.NextED; 1838 } 1839 1840 RemoveEntryList(&ED->HcdEDLink); 1841 1842 OhciEndpoint->HeadED = NULL; 1843 } 1844 1845 VOID 1846 NTAPI 1847 OHCI_SetEndpointState(IN PVOID ohciExtension, 1848 IN PVOID ohciEndpoint, 1849 IN ULONG EndpointState) 1850 { 1851 POHCI_EXTENSION OhciExtension = ohciExtension; 1852 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint; 1853 POHCI_HCD_ED ED; 1854 1855 DPRINT_OHCI("OHCI_SetEndpointState: EndpointState - %x\n", 1856 EndpointState); 1857 1858 ED = OhciEndpoint->HcdED; 1859 1860 switch (EndpointState) 1861 { 1862 case USBPORT_ENDPOINT_PAUSED: 1863 ED->HwED.EndpointControl.sKip = 1; 1864 break; 1865 1866 case USBPORT_ENDPOINT_ACTIVE: 1867 ED->HwED.EndpointControl.sKip = 0; 1868 OHCI_EnableList(OhciExtension, OhciEndpoint); 1869 break; 1870 1871 case USBPORT_ENDPOINT_REMOVE: 1872 ED->HwED.EndpointControl.sKip = 1; 1873 ED->Flags |= OHCI_HCD_ED_FLAG_NOT_ACCESSED; 1874 OHCI_RemoveEndpointFromSchedule(OhciEndpoint); 1875 break; 1876 1877 default: 1878 ASSERT(FALSE); 1879 break; 1880 } 1881 } 1882 1883 VOID 1884 NTAPI 1885 OHCI_PollAsyncEndpoint(IN POHCI_EXTENSION OhciExtension, 1886 IN POHCI_ENDPOINT OhciEndpoint) 1887 { 1888 PUSBPORT_TRANSFER_PARAMETERS TransferParameters; 1889 POHCI_HCD_ED ED; 1890 ULONG_PTR NextTdPA; 1891 POHCI_HCD_TD NextTD; 1892 POHCI_HCD_TD TD; 1893 PLIST_ENTRY DoneList; 1894 POHCI_TRANSFER OhciTransfer; 1895 POHCI_HCD_TD ControlStatusTD; 1896 ULONG_PTR PhysicalAddress; 1897 ULONG TransferNumber; 1898 POHCI_TRANSFER transfer; 1899 UCHAR ConditionCode; 1900 BOOLEAN IsResetOnHalt = FALSE; 1901 1902 //DPRINT_OHCI("OHCI_PollAsyncEndpoint: Endpoint - %p\n", OhciEndpoint); 1903 1904 ED = OhciEndpoint->HcdED; 1905 NextTdPA = ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_MASK; 1906 1907 if (!NextTdPA) 1908 { 1909 OHCI_DumpHcdED(ED); 1910 DbgBreakPoint(); 1911 } 1912 1913 NextTD = RegPacket.UsbPortGetMappedVirtualAddress(NextTdPA, 1914 OhciExtension, 1915 OhciEndpoint); 1916 DPRINT_OHCI("NextTD - %p\n", NextTD); 1917 1918 if ((ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_HALT) == 0) 1919 goto ProcessListTDs; 1920 1921 OHCI_DumpHcdED(ED); 1922 1923 IsResetOnHalt = (ED->Flags & OHCI_HCD_ED_FLAG_RESET_ON_HALT) != 0; 1924 DPRINT1("PollAsyncEndpoint: IsResetOnHalt %x\n", IsResetOnHalt); 1925 1926 for (TD = OhciEndpoint->HcdHeadP; ; TD = TD->NextTDVa) 1927 { 1928 if (!TD) 1929 { 1930 OHCI_DumpHcdED(ED); 1931 DbgBreakPoint(); 1932 } 1933 1934 if (TD == NextTD) 1935 { 1936 DPRINT("TD == NextTD - %p\n", TD); 1937 goto HandleDoneList; 1938 } 1939 1940 OhciTransfer = TD->OhciTransfer; 1941 ConditionCode = TD->HwTD.gTD.Control.ConditionCode; 1942 1943 DPRINT("TD - %p, ConditionCode - %X\n", TD, ConditionCode); 1944 OHCI_DumpHcdTD(TD); 1945 1946 switch (ConditionCode) 1947 { 1948 case OHCI_TD_CONDITION_NO_ERROR: 1949 TD->Flags |= OHCI_HCD_TD_FLAG_DONE; 1950 InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink); 1951 continue; 1952 1953 case OHCI_TD_CONDITION_NOT_ACCESSED: 1954 TD->Flags |= (OHCI_HCD_TD_FLAG_DONE | OHCI_HCD_TD_FLAG_NOT_ACCESSED); 1955 InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink); 1956 continue; 1957 1958 case OHCI_TD_CONDITION_DATA_UNDERRUN: 1959 DPRINT1("DATA_UNDERRUN. Transfer->Flags - %X\n", OhciTransfer->Flags); 1960 1961 if (OhciTransfer->Flags & OHCI_TRANSFER_FLAGS_SHORT_TRANSFER_OK) 1962 { 1963 IsResetOnHalt = TRUE; 1964 TD->HwTD.gTD.Control.ConditionCode = OHCI_TD_CONDITION_NO_ERROR; 1965 1966 ControlStatusTD = OhciTransfer->ControlStatusTD; 1967 1968 if ((TD->Flags & OHCI_HCD_TD_FLAG_CONTROL_STATUS) == 0 && 1969 ControlStatusTD) 1970 { 1971 PhysicalAddress = ControlStatusTD->PhysicalAddress; 1972 PhysicalAddress |= (ED->HwED.HeadPointer & 1973 OHCI_ED_HEAD_POINTER_FLAGS_MASK); 1974 1975 ED->HwED.HeadPointer = PhysicalAddress; 1976 1977 NextTD = OhciTransfer->ControlStatusTD; 1978 DPRINT("PhysicalAddress - %p, NextTD - %p\n", PhysicalAddress, NextTD); 1979 } 1980 else 1981 { 1982 TransferParameters = OhciTransfer->TransferParameters; 1983 1984 if (TransferParameters->IsTransferSplited) 1985 { 1986 TransferNumber = TransferParameters->TransferCounter; 1987 transfer = OhciTransfer; 1988 1989 do 1990 { 1991 transfer = transfer->NextTD->OhciTransfer; 1992 NextTD = transfer->NextTD; 1993 } 1994 while (transfer && TransferNumber == 1995 transfer->TransferParameters->TransferCounter); 1996 1997 PhysicalAddress = NextTD->PhysicalAddress; 1998 PhysicalAddress |= (ED->HwED.HeadPointer & 1999 OHCI_ED_HEAD_POINTER_FLAGS_MASK); 2000 2001 ED->HwED.HeadPointer = PhysicalAddress; 2002 DPRINT("PhysicalAddress - %p, NextTD - %p\n", PhysicalAddress, NextTD); 2003 } 2004 else 2005 { 2006 PhysicalAddress = OhciTransfer->NextTD->PhysicalAddress; 2007 PhysicalAddress |= (ED->HwED.HeadPointer & 2008 OHCI_ED_HEAD_POINTER_FLAGS_MASK); 2009 2010 ED->HwED.HeadPointer = PhysicalAddress; 2011 2012 NextTD = OhciTransfer->NextTD; 2013 DPRINT("PhysicalAddress - %p, NextTD - %p\n", PhysicalAddress, NextTD); 2014 } 2015 } 2016 2017 TD->Flags |= OHCI_HCD_TD_FLAG_DONE; 2018 InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink); 2019 continue; 2020 } 2021 2022 /* fall through */ 2023 2024 default: 2025 TD->Flags |= OHCI_HCD_TD_FLAG_DONE; 2026 InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink); 2027 2028 ED->HwED.HeadPointer = OhciTransfer->NextTD->PhysicalAddress | 2029 (ED->HwED.HeadPointer & 2030 OHCI_ED_HEAD_POINTER_FLAGS_MASK); 2031 2032 NextTD = OhciTransfer->NextTD; 2033 break; 2034 } 2035 } 2036 2037 ProcessListTDs: 2038 2039 TD = OhciEndpoint->HcdHeadP; 2040 2041 while (TD != NextTD) 2042 { 2043 OHCI_DumpHcdTD(TD); 2044 TD->Flags |= OHCI_HCD_TD_FLAG_DONE; 2045 InsertTailList(&OhciEndpoint->TDList, &TD->DoneLink); 2046 TD = TD->NextTDVa; 2047 } 2048 2049 HandleDoneList: 2050 2051 TD = NextTD; 2052 OhciEndpoint->HcdHeadP = NextTD; 2053 2054 DoneList = &OhciEndpoint->TDList; 2055 2056 while (!IsListEmpty(DoneList)) 2057 { 2058 TD = CONTAINING_RECORD(DoneList->Flink, 2059 OHCI_HCD_TD, 2060 DoneLink); 2061 2062 RemoveHeadList(DoneList); 2063 2064 if (TD->Flags & OHCI_HCD_TD_FLAG_DONE && 2065 TD->Flags & OHCI_HCD_TD_FLAG_PROCESSED) 2066 { 2067 OHCI_ProcessDoneTD(OhciExtension, TD, TRUE); 2068 } 2069 } 2070 2071 if (IsResetOnHalt) 2072 { 2073 ED->HwED.HeadPointer &= ~OHCI_ED_HEAD_POINTER_HALT; 2074 DPRINT("ED->HwED.HeadPointer - %p\n", ED->HwED.HeadPointer); 2075 } 2076 } 2077 2078 VOID 2079 NTAPI 2080 OHCI_PollIsoEndpoint(IN POHCI_EXTENSION OhciExtension, 2081 IN POHCI_ENDPOINT OhciEndpoint) 2082 { 2083 DPRINT1("OHCI_PollAsyncEndpoint: UNIMPLEMENTED. FIXME \n"); 2084 ASSERT(FALSE); 2085 } 2086 2087 VOID 2088 NTAPI 2089 OHCI_PollEndpoint(IN PVOID ohciExtension, 2090 IN PVOID ohciEndpoint) 2091 { 2092 POHCI_EXTENSION OhciExtension = ohciExtension; 2093 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint; 2094 ULONG TransferType; 2095 2096 DPRINT_OHCI("OHCI_PollEndpoint: OhciExtension - %p, Endpoint - %p\n", 2097 OhciExtension, 2098 OhciEndpoint); 2099 2100 TransferType = OhciEndpoint->EndpointProperties.TransferType; 2101 2102 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 2103 { 2104 OHCI_PollIsoEndpoint(OhciExtension, OhciEndpoint); 2105 return; 2106 } 2107 2108 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL || 2109 TransferType == USBPORT_TRANSFER_TYPE_BULK || 2110 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 2111 { 2112 OHCI_PollAsyncEndpoint(OhciExtension, OhciEndpoint); 2113 } 2114 } 2115 2116 VOID 2117 NTAPI 2118 OHCI_CheckController(IN PVOID ohciExtension) 2119 { 2120 POHCI_EXTENSION OhciExtension = ohciExtension; 2121 POHCI_OPERATIONAL_REGISTERS OperationalRegs; 2122 PULONG HcControlReg; 2123 OHCI_REG_CONTROL HcControl; 2124 ULONG FmNumber; 2125 USHORT FmDiff; 2126 POHCI_HCCA HcHCCA; 2127 2128 //DPRINT_OHCI("OHCI_CheckController: ...\n"); 2129 2130 OperationalRegs = OhciExtension->OperationalRegs; 2131 2132 if (!OHCI_HardwarePresent(OhciExtension, TRUE)) 2133 return; 2134 2135 HcControlReg = (PULONG)&OperationalRegs->HcControl; 2136 HcControl.AsULONG = READ_REGISTER_ULONG(HcControlReg); 2137 2138 if (HcControl.HostControllerFunctionalState != OHCI_HC_STATE_OPERATIONAL) 2139 return; 2140 2141 FmNumber = READ_REGISTER_ULONG(&OperationalRegs->HcFmNumber); 2142 FmDiff = (USHORT)(FmNumber - OhciExtension->HcdFmNumber); 2143 2144 if (FmNumber == 0 || FmDiff < 5) 2145 return; 2146 2147 HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA; 2148 OhciExtension->HcdFmNumber = FmNumber; 2149 2150 if (HcHCCA->Pad1 == 0) 2151 { 2152 HcHCCA->Pad1 = 0xBAD1; 2153 return; 2154 } 2155 2156 DPRINT1("OHCI_CheckController: HcHCCA->Pad1 - %x\n", HcHCCA->Pad1); 2157 2158 if (HcHCCA->Pad1 == 0xBAD1) 2159 { 2160 HcHCCA->Pad1 = 0xBAD2; 2161 } 2162 else if (HcHCCA->Pad1 == 0xBAD2) 2163 { 2164 HcHCCA->Pad1 = 0xBAD3; 2165 2166 RegPacket.UsbPortInvalidateController(OhciExtension, 2167 USBPORT_INVALIDATE_CONTROLLER_RESET); 2168 } 2169 } 2170 2171 ULONG 2172 NTAPI 2173 OHCI_Get32BitFrameNumber(IN PVOID ohciExtension) 2174 { 2175 POHCI_EXTENSION OhciExtension = ohciExtension; 2176 POHCI_HCCA HcHCCA; 2177 ULONG fm; 2178 ULONG hp; 2179 2180 HcHCCA = &OhciExtension->HcResourcesVA->HcHCCA; 2181 2182 /* 5.4 FrameInterval Counter: Get32BitFrameNumber() */ 2183 2184 hp = OhciExtension->FrameHighPart; 2185 fm = HcHCCA->FrameNumber; 2186 2187 DPRINT_OHCI("OHCI_Get32BitFrameNumber: hp - %lX, fm - %lX\n", hp, fm); 2188 2189 return ((fm & 0x7FFF) | hp) + ((fm ^ hp) & 0x8000); 2190 } 2191 2192 VOID 2193 NTAPI 2194 OHCI_InterruptNextSOF(IN PVOID ohciExtension) 2195 { 2196 POHCI_EXTENSION OhciExtension = ohciExtension; 2197 POHCI_OPERATIONAL_REGISTERS OperationalRegs; 2198 PULONG InterruptEnableReg; 2199 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable; 2200 2201 DPRINT_OHCI("OHCI_InterruptNextSOF: OhciExtension - %p\n", 2202 OhciExtension); 2203 2204 OperationalRegs = OhciExtension->OperationalRegs; 2205 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable; 2206 2207 /* Enable interrupt generation due to Start of Frame */ 2208 IntEnable.AsULONG = 0; 2209 IntEnable.StartofFrame = 1; 2210 2211 WRITE_REGISTER_ULONG(InterruptEnableReg, IntEnable.AsULONG); 2212 } 2213 2214 VOID 2215 NTAPI 2216 OHCI_EnableInterrupts(IN PVOID ohciExtension) 2217 { 2218 POHCI_EXTENSION OhciExtension = ohciExtension; 2219 POHCI_OPERATIONAL_REGISTERS OperationalRegs; 2220 PULONG InterruptEnableReg; 2221 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable; 2222 2223 DPRINT_OHCI("OHCI_EnableInterrupts: OhciExtension - %p\n", 2224 OhciExtension); 2225 2226 OperationalRegs = OhciExtension->OperationalRegs; 2227 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable; 2228 2229 /* Enable interrupt generation */ 2230 IntEnable.AsULONG = 0; 2231 IntEnable.MasterInterruptEnable = 1; 2232 2233 WRITE_REGISTER_ULONG(InterruptEnableReg, IntEnable.AsULONG); 2234 } 2235 2236 VOID 2237 NTAPI 2238 OHCI_DisableInterrupts(IN PVOID ohciExtension) 2239 { 2240 POHCI_EXTENSION OhciExtension = ohciExtension; 2241 POHCI_OPERATIONAL_REGISTERS OperationalRegs; 2242 PULONG InterruptDisableReg; 2243 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntDisable; 2244 2245 DPRINT_OHCI("OHCI_DisableInterrupts\n"); 2246 2247 OperationalRegs = OhciExtension->OperationalRegs; 2248 InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable; 2249 2250 /* Disable interrupt generation */ 2251 IntDisable.AsULONG = 0; 2252 IntDisable.MasterInterruptEnable = 1; 2253 2254 WRITE_REGISTER_ULONG(InterruptDisableReg, IntDisable.AsULONG); 2255 } 2256 2257 VOID 2258 NTAPI 2259 OHCI_PollController(IN PVOID ohciExtension) 2260 { 2261 DPRINT1("OHCI_PollController: UNIMPLEMENTED. FIXME\n"); 2262 } 2263 2264 VOID 2265 NTAPI 2266 OHCI_SetEndpointDataToggle(IN PVOID ohciExtension, 2267 IN PVOID ohciEndpoint, 2268 IN ULONG DataToggle) 2269 { 2270 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint; 2271 POHCI_HCD_ED ED; 2272 2273 DPRINT_OHCI("OHCI_SetEndpointDataToggle: Endpoint - %p, DataToggle - %x\n", 2274 OhciEndpoint, 2275 DataToggle); 2276 2277 ED = OhciEndpoint->HcdED; 2278 2279 if (DataToggle) 2280 ED->HwED.HeadPointer |= OHCI_ED_HEAD_POINTER_CARRY; 2281 else 2282 ED->HwED.HeadPointer &= ~OHCI_ED_HEAD_POINTER_CARRY; 2283 } 2284 2285 ULONG 2286 NTAPI 2287 OHCI_GetEndpointStatus(IN PVOID ohciExtension, 2288 IN PVOID ohciEndpoint) 2289 { 2290 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint; 2291 POHCI_HCD_ED ED; 2292 ULONG EndpointStatus = USBPORT_ENDPOINT_RUN; 2293 2294 DPRINT_OHCI("OHCI_GetEndpointStatus: ... \n"); 2295 2296 ED = OhciEndpoint->HcdED; 2297 2298 if ((ED->HwED.HeadPointer & OHCI_ED_HEAD_POINTER_HALT) && 2299 !(ED->Flags & OHCI_HCD_ED_FLAG_RESET_ON_HALT)) 2300 { 2301 EndpointStatus = USBPORT_ENDPOINT_HALT; 2302 } 2303 2304 return EndpointStatus; 2305 } 2306 2307 VOID 2308 NTAPI 2309 OHCI_SetEndpointStatus(IN PVOID ohciExtension, 2310 IN PVOID ohciEndpoint, 2311 IN ULONG EndpointStatus) 2312 { 2313 POHCI_EXTENSION OhciExtension = ohciExtension; 2314 POHCI_ENDPOINT OhciEndpoint = ohciEndpoint; 2315 POHCI_HCD_ED ED; 2316 2317 DPRINT_OHCI("OHCI_SetEndpointStatus: Endpoint - %p, EndpointStatus - %lX\n", 2318 OhciEndpoint, 2319 EndpointStatus); 2320 2321 if (EndpointStatus == USBPORT_ENDPOINT_RUN) 2322 { 2323 ED = OhciEndpoint->HcdED; 2324 ED->HwED.HeadPointer &= ~OHCI_ED_HEAD_POINTER_HALT; 2325 2326 OHCI_EnableList(OhciExtension, OhciEndpoint); 2327 } 2328 else if (EndpointStatus == USBPORT_ENDPOINT_HALT) 2329 { 2330 ASSERT(FALSE); 2331 } 2332 } 2333 2334 VOID 2335 NTAPI 2336 OHCI_ResetController(IN PVOID ohciExtension) 2337 { 2338 POHCI_EXTENSION OhciExtension = ohciExtension; 2339 POHCI_OPERATIONAL_REGISTERS OperationalRegs; 2340 ULONG FrameNumber; 2341 PULONG ControlReg; 2342 PULONG CommandStatusReg; 2343 PULONG InterruptEnableReg; 2344 PULONG FmIntervalReg; 2345 PULONG RhStatusReg; 2346 PULONG PortStatusReg; 2347 OHCI_REG_CONTROL ControlBak; 2348 OHCI_REG_CONTROL Control; 2349 OHCI_REG_COMMAND_STATUS CommandStatus; 2350 OHCI_REG_INTERRUPT_ENABLE_DISABLE IntEnable; 2351 ULONG_PTR HCCA; 2352 ULONG_PTR ControlHeadED; 2353 ULONG_PTR BulkHeadED; 2354 OHCI_REG_FRAME_INTERVAL FrameInterval; 2355 ULONG_PTR PeriodicStart; 2356 ULONG_PTR LSThreshold; 2357 OHCI_REG_RH_STATUS RhStatus; 2358 OHCI_REG_RH_DESCRIPTORA RhDescriptorA; 2359 OHCI_REG_RH_PORT_STATUS PortStatus; 2360 ULONG NumPorts; 2361 ULONG ix; 2362 2363 DPRINT("OHCI_ResetController: ... \n"); 2364 2365 OperationalRegs = OhciExtension->OperationalRegs; 2366 2367 ControlReg = (PULONG)&OperationalRegs->HcControl; 2368 CommandStatusReg = (PULONG)&OperationalRegs->HcCommandStatus; 2369 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable; 2370 FmIntervalReg = (PULONG)&OperationalRegs->HcFmInterval; 2371 RhStatusReg = (PULONG)&OperationalRegs->HcRhStatus; 2372 2373 /* Backup FrameNumber from HcHCCA */ 2374 FrameNumber = OhciExtension->HcResourcesVA->HcHCCA.FrameNumber; 2375 2376 /* Backup registers */ 2377 ControlBak.AsULONG = READ_REGISTER_ULONG(ControlReg); 2378 HCCA = READ_REGISTER_ULONG(&OperationalRegs->HcHCCA); 2379 ControlHeadED = READ_REGISTER_ULONG(&OperationalRegs->HcControlHeadED); 2380 BulkHeadED = READ_REGISTER_ULONG(&OperationalRegs->HcBulkHeadED); 2381 FrameInterval.AsULONG = READ_REGISTER_ULONG(FmIntervalReg); 2382 PeriodicStart = READ_REGISTER_ULONG(&OperationalRegs->HcPeriodicStart); 2383 LSThreshold = READ_REGISTER_ULONG(&OperationalRegs->HcLSThreshold); 2384 2385 /* Reset HostController */ 2386 CommandStatus.AsULONG = 0; 2387 CommandStatus.HostControllerReset = 1; 2388 WRITE_REGISTER_ULONG(CommandStatusReg, CommandStatus.AsULONG); 2389 2390 KeStallExecutionProcessor(10); 2391 2392 /* Restore registers */ 2393 WRITE_REGISTER_ULONG(&OperationalRegs->HcHCCA, HCCA); 2394 WRITE_REGISTER_ULONG(&OperationalRegs->HcControlHeadED, ControlHeadED); 2395 WRITE_REGISTER_ULONG(&OperationalRegs->HcBulkHeadED, BulkHeadED); 2396 2397 /* Set OPERATIONAL state for HC */ 2398 Control.AsULONG = 0; 2399 Control.HostControllerFunctionalState = OHCI_HC_STATE_OPERATIONAL; 2400 WRITE_REGISTER_ULONG(ControlReg, Control.AsULONG); 2401 2402 /* Set Toggle bit for FmInterval register */ 2403 FrameInterval.FrameIntervalToggle = 1; 2404 WRITE_REGISTER_ULONG(FmIntervalReg, FrameInterval.AsULONG); 2405 2406 /* Restore registers */ 2407 WRITE_REGISTER_ULONG(&OperationalRegs->HcFmNumber, FrameNumber); 2408 WRITE_REGISTER_ULONG(&OperationalRegs->HcPeriodicStart, PeriodicStart); 2409 WRITE_REGISTER_ULONG(&OperationalRegs->HcLSThreshold, LSThreshold); 2410 2411 /* Setup RhStatus register */ 2412 RhStatus.AsULONG = 0; 2413 RhStatus.SetRemoteWakeupEnable = 1; 2414 RhStatus.SetGlobalPower = 1; 2415 WRITE_REGISTER_ULONG(RhStatusReg, RhStatus.AsULONG); 2416 2417 /* Setup RH PortStatus registers */ 2418 RhDescriptorA = OHCI_ReadRhDescriptorA(OhciExtension); 2419 NumPorts = RhDescriptorA.NumberDownstreamPorts; 2420 2421 PortStatus.AsULONG = 0; 2422 PortStatus.SetPortPower = 1; 2423 2424 for (ix = 0; ix < NumPorts; ix++) 2425 { 2426 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[ix]; 2427 WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG); 2428 } 2429 2430 /* Restore HcControl register */ 2431 ControlBak.HostControllerFunctionalState = OHCI_HC_STATE_OPERATIONAL; 2432 WRITE_REGISTER_ULONG(ControlReg, ControlBak.AsULONG); 2433 2434 /* Setup HcInterruptEnable register */ 2435 IntEnable.AsULONG = 0xFFFFFFFF; 2436 IntEnable.Reserved1 = 0; 2437 WRITE_REGISTER_ULONG(InterruptEnableReg, IntEnable.AsULONG); 2438 } 2439 2440 MPSTATUS 2441 NTAPI 2442 OHCI_StartSendOnePacket(IN PVOID ohciExtension, 2443 IN PVOID PacketParameters, 2444 IN PVOID Data, 2445 IN PULONG pDataLength, 2446 IN PVOID BufferVA, 2447 IN PVOID BufferPA, 2448 IN ULONG BufferLength, 2449 IN USBD_STATUS * pUSBDStatus) 2450 { 2451 DPRINT1("OHCI_StartSendOnePacket: UNIMPLEMENTED. FIXME\n"); 2452 return MP_STATUS_SUCCESS; 2453 } 2454 2455 MPSTATUS 2456 NTAPI 2457 OHCI_EndSendOnePacket(IN PVOID ohciExtension, 2458 IN PVOID PacketParameters, 2459 IN PVOID Data, 2460 IN PULONG pDataLength, 2461 IN PVOID BufferVA, 2462 IN PVOID BufferPA, 2463 IN ULONG BufferLength, 2464 IN USBD_STATUS * pUSBDStatus) 2465 { 2466 DPRINT1("OHCI_EndSendOnePacket: UNIMPLEMENTED. FIXME\n"); 2467 return MP_STATUS_SUCCESS; 2468 } 2469 2470 MPSTATUS 2471 NTAPI 2472 OHCI_PassThru(IN PVOID ohciExtension, 2473 IN PVOID passThruParameters, 2474 IN ULONG ParameterLength, 2475 IN PVOID pParameters) 2476 { 2477 DPRINT1("OHCI_PassThru: UNIMPLEMENTED. FIXME\n"); 2478 return MP_STATUS_SUCCESS; 2479 } 2480 2481 VOID 2482 NTAPI 2483 OHCI_Unload(IN PDRIVER_OBJECT DriverObject) 2484 { 2485 #if DBG 2486 DPRINT1("OHCI_Unload: Not supported\n"); 2487 #endif 2488 return; 2489 } 2490 2491 VOID 2492 NTAPI 2493 OHCI_FlushInterrupts(IN PVOID uhciExtension) 2494 { 2495 #if DBG 2496 DPRINT1("OHCI_FlushInterrupts: Not supported\n"); 2497 #endif 2498 return; 2499 } 2500 2501 NTSTATUS 2502 NTAPI 2503 DriverEntry(IN PDRIVER_OBJECT DriverObject, 2504 IN PUNICODE_STRING RegistryPath) 2505 { 2506 NTSTATUS Status; 2507 2508 DPRINT_OHCI("DriverEntry: DriverObject - %p, RegistryPath - %wZ\n", 2509 DriverObject, 2510 RegistryPath); 2511 2512 RtlZeroMemory(&RegPacket, sizeof(USBPORT_REGISTRATION_PACKET)); 2513 2514 RegPacket.MiniPortVersion = USB_MINIPORT_VERSION_OHCI; 2515 2516 RegPacket.MiniPortFlags = USB_MINIPORT_FLAGS_INTERRUPT | 2517 USB_MINIPORT_FLAGS_MEMORY_IO; 2518 2519 RegPacket.MiniPortBusBandwidth = TOTAL_USB11_BUS_BANDWIDTH; 2520 2521 RegPacket.MiniPortExtensionSize = sizeof(OHCI_EXTENSION); 2522 RegPacket.MiniPortEndpointSize = sizeof(OHCI_ENDPOINT); 2523 RegPacket.MiniPortTransferSize = sizeof(OHCI_TRANSFER); 2524 RegPacket.MiniPortResourcesSize = sizeof(OHCI_HC_RESOURCES); 2525 2526 RegPacket.OpenEndpoint = OHCI_OpenEndpoint; 2527 RegPacket.ReopenEndpoint = OHCI_ReopenEndpoint; 2528 RegPacket.QueryEndpointRequirements = OHCI_QueryEndpointRequirements; 2529 RegPacket.CloseEndpoint = OHCI_CloseEndpoint; 2530 RegPacket.StartController = OHCI_StartController; 2531 RegPacket.StopController = OHCI_StopController; 2532 RegPacket.SuspendController = OHCI_SuspendController; 2533 RegPacket.ResumeController = OHCI_ResumeController; 2534 RegPacket.InterruptService = OHCI_InterruptService; 2535 RegPacket.InterruptDpc = OHCI_InterruptDpc; 2536 RegPacket.SubmitTransfer = OHCI_SubmitTransfer; 2537 RegPacket.SubmitIsoTransfer = OHCI_SubmitIsoTransfer; 2538 RegPacket.AbortTransfer = OHCI_AbortTransfer; 2539 RegPacket.GetEndpointState = OHCI_GetEndpointState; 2540 RegPacket.SetEndpointState = OHCI_SetEndpointState; 2541 RegPacket.PollEndpoint = OHCI_PollEndpoint; 2542 RegPacket.CheckController = OHCI_CheckController; 2543 RegPacket.Get32BitFrameNumber = OHCI_Get32BitFrameNumber; 2544 RegPacket.InterruptNextSOF = OHCI_InterruptNextSOF; 2545 RegPacket.EnableInterrupts = OHCI_EnableInterrupts; 2546 RegPacket.DisableInterrupts = OHCI_DisableInterrupts; 2547 RegPacket.PollController = OHCI_PollController; 2548 RegPacket.SetEndpointDataToggle = OHCI_SetEndpointDataToggle; 2549 RegPacket.GetEndpointStatus = OHCI_GetEndpointStatus; 2550 RegPacket.SetEndpointStatus = OHCI_SetEndpointStatus; 2551 RegPacket.ResetController = OHCI_ResetController; 2552 RegPacket.RH_GetRootHubData = OHCI_RH_GetRootHubData; 2553 RegPacket.RH_GetStatus = OHCI_RH_GetStatus; 2554 RegPacket.RH_GetPortStatus = OHCI_RH_GetPortStatus; 2555 RegPacket.RH_GetHubStatus = OHCI_RH_GetHubStatus; 2556 RegPacket.RH_SetFeaturePortReset = OHCI_RH_SetFeaturePortReset; 2557 RegPacket.RH_SetFeaturePortPower = OHCI_RH_SetFeaturePortPower; 2558 RegPacket.RH_SetFeaturePortEnable = OHCI_RH_SetFeaturePortEnable; 2559 RegPacket.RH_SetFeaturePortSuspend = OHCI_RH_SetFeaturePortSuspend; 2560 RegPacket.RH_ClearFeaturePortEnable = OHCI_RH_ClearFeaturePortEnable; 2561 RegPacket.RH_ClearFeaturePortPower = OHCI_RH_ClearFeaturePortPower; 2562 RegPacket.RH_ClearFeaturePortSuspend = OHCI_RH_ClearFeaturePortSuspend; 2563 RegPacket.RH_ClearFeaturePortEnableChange = OHCI_RH_ClearFeaturePortEnableChange; 2564 RegPacket.RH_ClearFeaturePortConnectChange = OHCI_RH_ClearFeaturePortConnectChange; 2565 RegPacket.RH_ClearFeaturePortResetChange = OHCI_RH_ClearFeaturePortResetChange; 2566 RegPacket.RH_ClearFeaturePortSuspendChange = OHCI_RH_ClearFeaturePortSuspendChange; 2567 RegPacket.RH_ClearFeaturePortOvercurrentChange = OHCI_RH_ClearFeaturePortOvercurrentChange; 2568 RegPacket.RH_DisableIrq = OHCI_RH_DisableIrq; 2569 RegPacket.RH_EnableIrq = OHCI_RH_EnableIrq; 2570 RegPacket.StartSendOnePacket = OHCI_StartSendOnePacket; 2571 RegPacket.EndSendOnePacket = OHCI_EndSendOnePacket; 2572 RegPacket.PassThru = OHCI_PassThru; 2573 RegPacket.FlushInterrupts = OHCI_FlushInterrupts; 2574 2575 DriverObject->DriverUnload = OHCI_Unload; 2576 2577 Status = USBPORT_RegisterUSBPortDriver(DriverObject, 2578 USB10_MINIPORT_INTERFACE_VERSION, 2579 &RegPacket); 2580 2581 DPRINT_OHCI("DriverEntry: USBPORT_RegisterUSBPortDriver return Status - %x\n", 2582 Status); 2583 2584 return Status; 2585 } 2586