1 /* 2 * PROJECT: ReactOS USB UHCI Miniport Driver 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: USBUHCI main driver functions 5 * COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru> 6 */ 7 8 #include "usbuhci.h" 9 10 #define NDEBUG 11 #include <debug.h> 12 13 #define NDEBUG_UHCI_TRACE 14 #define NDEBUG_UHCI_IMPLEMENT 15 #include "dbg_uhci.h" 16 17 USBPORT_REGISTRATION_PACKET RegPacket; 18 19 VOID 20 NTAPI 21 UhciDumpHcdQH(PUHCI_HCD_QH QH) 22 { 23 DPRINT("QH - %p\n", QH); 24 DPRINT("NextQH - %p\n", QH->HwQH.NextQH); 25 DPRINT("NextElement - %p\n", QH->HwQH.NextElement); 26 27 DPRINT("PhysicalAddress - %p\n", QH->PhysicalAddress); 28 DPRINT("QhFlags - %X\n", QH->QhFlags); 29 DPRINT("NextHcdQH - %X\n", QH->NextHcdQH); 30 DPRINT("PrevHcdQH - %X\n", QH->PrevHcdQH); 31 DPRINT("UhciEndpoint - %X\n", QH->UhciEndpoint); 32 } 33 34 VOID 35 NTAPI 36 UhciDumpHcdTD(PUHCI_HCD_TD TD) 37 { 38 DPRINT("TD - %p\n", TD); 39 DPRINT("NextElement - %p\n", TD->HwTD.NextElement); 40 DPRINT("ControlStatus - %08X\n", TD->HwTD.ControlStatus.AsULONG); 41 DPRINT("Token - %p\n", TD->HwTD.Token.AsULONG); 42 if (TD->HwTD.Buffer) 43 DPRINT("Buffer - %p\n", TD->HwTD.Buffer); 44 45 if (TD->SetupPacket.bmRequestType.B) 46 DPRINT("bmRequestType - %02X\n", TD->SetupPacket.bmRequestType.B); 47 if (TD->SetupPacket.bRequest) 48 DPRINT("bRequest - %02X\n", TD->SetupPacket.bRequest); 49 if (TD->SetupPacket.wValue.W) 50 DPRINT("wValue - %04X\n", TD->SetupPacket.wValue.W); 51 if (TD->SetupPacket.wIndex.W) 52 DPRINT("wIndex - %04X\n", TD->SetupPacket.wIndex.W); 53 if (TD->SetupPacket.wLength) 54 DPRINT("wLength - %04X\n", TD->SetupPacket.wLength); 55 56 DPRINT("PhysicalAddress - %p\n", TD->PhysicalAddress); 57 DPRINT("Flags - %X\n", TD->Flags); 58 DPRINT("NextHcdTD - %p\n", TD->NextHcdTD); 59 DPRINT("UhciTransfer - %p\n", TD->UhciTransfer); 60 } 61 62 VOID 63 NTAPI 64 UhciFixDataToggle(IN PUHCI_EXTENSION UhciExtension, 65 IN PUHCI_ENDPOINT UhciEndpoint, 66 IN PUHCI_HCD_TD TD, 67 IN BOOL DataToggle) 68 { 69 DPRINT_UHCI("UhciFixDataToggle: UhciExtension - %p, UhciEndpoint - %p, DataToggle - %X\n", 70 UhciExtension, 71 UhciEndpoint, 72 DataToggle); 73 74 while (TD) 75 { 76 TD->HwTD.Token.DataToggle = !TD->HwTD.Token.DataToggle; 77 DataToggle = !DataToggle; 78 79 TD = TD->NextHcdTD; 80 } 81 82 UhciEndpoint->DataToggle = DataToggle; 83 } 84 85 VOID 86 NTAPI 87 UhciCleanupFrameListEntry(IN PUHCI_EXTENSION UhciExtension, 88 IN ULONG Index) 89 { 90 PUHCI_HC_RESOURCES UhciResources; 91 ULONG PhysicalAddress; 92 ULONG HeadIdx; 93 94 UhciResources = UhciExtension->HcResourcesVA; 95 96 if (Index == 0) 97 { 98 PhysicalAddress = UhciExtension->StaticTD->PhysicalAddress; 99 100 UhciResources->FrameList[0] = PhysicalAddress | 101 UHCI_FRAME_LIST_POINTER_TD; 102 } 103 else 104 { 105 HeadIdx = (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms) + 106 (Index & (ENDPOINT_INTERRUPT_32ms - 1)); 107 108 PhysicalAddress = UhciExtension->IntQH[HeadIdx]->PhysicalAddress; 109 110 UhciResources->FrameList[Index] = PhysicalAddress | 111 UHCI_FRAME_LIST_POINTER_QH; 112 } 113 } 114 115 VOID 116 NTAPI 117 UhciCleanupFrameList(IN PUHCI_EXTENSION UhciExtension, 118 IN BOOLEAN IsAllEntries) 119 { 120 ULONG NewFrameNumber; 121 ULONG OldFrameNumber; 122 ULONG ix; 123 124 DPRINT_UHCI("UhciCleanupFrameList: [%p] All - %x\n", 125 UhciExtension, IsAllEntries); 126 127 // FIXME: using UhciExtension->LockFrameList after supporting ISOs. 128 129 NewFrameNumber = UhciGet32BitFrameNumber(UhciExtension); 130 OldFrameNumber = UhciExtension->FrameNumber; 131 132 if ((NewFrameNumber - OldFrameNumber) < UHCI_FRAME_LIST_MAX_ENTRIES && 133 IsAllEntries == FALSE) 134 { 135 for (ix = OldFrameNumber & UHCI_FRAME_LIST_INDEX_MASK; 136 ix != (NewFrameNumber & UHCI_FRAME_LIST_INDEX_MASK); 137 ix = (ix + 1) & UHCI_FRAME_LIST_INDEX_MASK) 138 { 139 UhciCleanupFrameListEntry(UhciExtension, ix); 140 } 141 } 142 else 143 { 144 for (ix = 0; ix < UHCI_FRAME_LIST_MAX_ENTRIES; ++ix) 145 { 146 UhciCleanupFrameListEntry(UhciExtension, ix); 147 } 148 } 149 150 UhciExtension->FrameNumber = NewFrameNumber; 151 } 152 153 VOID 154 NTAPI 155 UhciUpdateCounter(IN PUHCI_EXTENSION UhciExtension) 156 { 157 ULONG FrameNumber; 158 159 FrameNumber = READ_PORT_USHORT(&UhciExtension->BaseRegister->FrameNumber); 160 FrameNumber &= UHCI_FRNUM_FRAME_MASK; 161 162 if ((FrameNumber ^ UhciExtension->FrameHighPart) & UHCI_FRNUM_OVERFLOW_LIST) 163 { 164 UhciExtension->FrameHighPart += UHCI_FRAME_LIST_MAX_ENTRIES; 165 166 DPRINT_UHCI("UhciUpdateCounter: UhciExtension->FrameHighPart - %lX\n", 167 UhciExtension->FrameHighPart); 168 } 169 } 170 171 VOID 172 NTAPI 173 UhciSetNextQH(IN PUHCI_HCD_QH QH, 174 IN PUHCI_HCD_QH NextQH) 175 { 176 DPRINT_UHCI("UhciSetNextQH: QH - %p, NextQH - %p\n", QH, NextQH); 177 178 QH->HwQH.NextQH = NextQH->PhysicalAddress | UHCI_QH_HEAD_LINK_PTR_QH; 179 QH->NextHcdQH = NextQH; 180 181 NextQH->PrevHcdQH = QH; 182 NextQH->QhFlags |= UHCI_HCD_QH_FLAG_ACTIVE; 183 } 184 185 MPSTATUS 186 NTAPI 187 UhciOpenEndpoint(IN PVOID uhciExtension, 188 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 189 IN PVOID uhciEndpoint) 190 { 191 PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint; 192 ULONG TransferType; 193 ULONG_PTR BufferVA; 194 ULONG BufferPA; 195 ULONG ix; 196 ULONG TdCount; 197 PUHCI_HCD_TD TD; 198 SIZE_T BufferLength; 199 PUHCI_HCD_QH QH; 200 201 RtlCopyMemory(&UhciEndpoint->EndpointProperties, 202 EndpointProperties, 203 sizeof(UhciEndpoint->EndpointProperties)); 204 205 InitializeListHead(&UhciEndpoint->ListTDs); 206 207 UhciEndpoint->EndpointLock = 0; 208 UhciEndpoint->DataToggle = UHCI_TD_PID_DATA0; 209 UhciEndpoint->Flags = 0; 210 211 TransferType = EndpointProperties->TransferType; 212 213 DPRINT("UhciOpenEndpoint: UhciEndpoint - %p, TransferType - %x\n", 214 UhciEndpoint, 215 TransferType); 216 217 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL || 218 TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 219 { 220 UhciEndpoint->Flags |= UHCI_ENDPOINT_FLAG_CONTROL_OR_ISO; 221 } 222 223 BufferVA = EndpointProperties->BufferVA; 224 BufferPA = EndpointProperties->BufferPA; 225 226 BufferLength = EndpointProperties->BufferLength; 227 228 /* For Isochronous transfers not used QHs (only TDs) */ 229 if (EndpointProperties->TransferType != USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 230 { 231 /* Initialize HCD Queue Head */ 232 UhciEndpoint->QH = (PUHCI_HCD_QH)BufferVA; 233 234 QH = UhciEndpoint->QH; 235 236 QH->HwQH.NextElement |= UHCI_QH_ELEMENT_LINK_PTR_TERMINATE; 237 QH->PhysicalAddress = BufferPA; 238 239 QH->NextHcdQH = QH; 240 QH->PrevHcdQH = QH; 241 QH->UhciEndpoint = UhciEndpoint; 242 243 BufferVA += sizeof(UHCI_HCD_QH); 244 BufferPA += sizeof(UHCI_HCD_QH); 245 246 BufferLength -= sizeof(UHCI_HCD_QH); 247 } 248 249 /* Initialize HCD Transfer Descriptors */ 250 TdCount = BufferLength / sizeof(UHCI_HCD_TD); 251 UhciEndpoint->MaxTDs = TdCount; 252 253 UhciEndpoint->FirstTD = (PUHCI_HCD_TD)BufferVA; 254 UhciEndpoint->AllocatedTDs = 0; 255 256 RtlZeroMemory(UhciEndpoint->FirstTD, TdCount * sizeof(UHCI_HCD_TD)); 257 258 for (ix = 0; ix < UhciEndpoint->MaxTDs; ix++) 259 { 260 TD = &UhciEndpoint->FirstTD[ix]; 261 TD->PhysicalAddress = BufferPA; 262 BufferPA += sizeof(UHCI_HCD_TD); 263 } 264 265 UhciEndpoint->TailTD = NULL; 266 UhciEndpoint->HeadTD = NULL; 267 268 return MP_STATUS_SUCCESS; 269 } 270 271 MPSTATUS 272 NTAPI 273 UhciReopenEndpoint(IN PVOID uhciExtension, 274 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 275 IN PVOID uhciEndpoint) 276 { 277 DPRINT_IMPL("Uhci: UNIMPLEMENTED. FIXME\n"); 278 return MP_STATUS_SUCCESS; 279 } 280 281 VOID 282 NTAPI 283 UhciQueryEndpointRequirements(IN PVOID uhciExtension, 284 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 285 IN PUSBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements) 286 { 287 ULONG TransferType; 288 ULONG TdCount; 289 290 DPRINT("UhciQueryEndpointRequirements: ... \n"); 291 292 TransferType = EndpointProperties->TransferType; 293 294 switch (TransferType) 295 { 296 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS: 297 DPRINT("UhciQueryEndpointRequirements: IsoTransfer\n"); 298 TdCount = 2 * UHCI_MAX_ISO_TD_COUNT; 299 300 EndpointRequirements->HeaderBufferSize = 0 + // Iso queue is have not Queue Heads 301 TdCount * sizeof(UHCI_HCD_TD); 302 303 EndpointRequirements->MaxTransferSize = UHCI_MAX_ISO_TRANSFER_SIZE; 304 break; 305 306 case USBPORT_TRANSFER_TYPE_CONTROL: 307 DPRINT("UhciQueryEndpointRequirements: ControlTransfer\n"); 308 TdCount = EndpointProperties->MaxTransferSize / 309 EndpointProperties->TotalMaxPacketSize; 310 311 TdCount += 2; // First + Last TDs 312 313 EndpointRequirements->HeaderBufferSize = sizeof(UHCI_HCD_QH) + 314 TdCount * sizeof(UHCI_HCD_TD); 315 316 EndpointRequirements->MaxTransferSize = EndpointProperties->MaxTransferSize; 317 break; 318 319 case USBPORT_TRANSFER_TYPE_BULK: 320 DPRINT("UhciQueryEndpointRequirements: BulkTransfer\n"); 321 TdCount = 2 * UHCI_MAX_BULK_TRANSFER_SIZE / 322 EndpointProperties->TotalMaxPacketSize; 323 324 EndpointRequirements->HeaderBufferSize = sizeof(UHCI_HCD_QH) + 325 TdCount * sizeof(UHCI_HCD_TD); 326 327 EndpointRequirements->MaxTransferSize = UHCI_MAX_BULK_TRANSFER_SIZE; 328 break; 329 330 case USBPORT_TRANSFER_TYPE_INTERRUPT: 331 DPRINT("UhciQueryEndpointRequirements: InterruptTransfer\n"); 332 TdCount = 2 * UHCI_MAX_INTERRUPT_TD_COUNT; 333 334 EndpointRequirements->HeaderBufferSize = sizeof(UHCI_HCD_QH) + 335 TdCount * sizeof(UHCI_HCD_TD); 336 337 EndpointRequirements->MaxTransferSize = UHCI_MAX_INTERRUPT_TD_COUNT * 338 EndpointProperties->TotalMaxPacketSize; 339 break; 340 341 default: 342 DPRINT1("UhciQueryEndpointRequirements: Unknown TransferType - %x\n", 343 TransferType); 344 DbgBreakPoint(); 345 break; 346 } 347 } 348 349 VOID 350 NTAPI 351 UhciCloseEndpoint(IN PVOID uhciExtension, 352 IN PVOID uhciEndpoint, 353 IN BOOLEAN IsDoDisablePeriodic) 354 { 355 DPRINT_IMPL("UhciCloseEndpoint: UNIMPLEMENTED. FIXME\n"); 356 } 357 358 MPSTATUS 359 NTAPI 360 UhciTakeControlHC(IN PUHCI_EXTENSION UhciExtension, 361 IN PUSBPORT_RESOURCES Resources) 362 { 363 LARGE_INTEGER EndTime; 364 LARGE_INTEGER CurrentTime; 365 ULONG ResourcesTypes; 366 PUHCI_HW_REGISTERS BaseRegister; 367 PUSHORT StatusRegister; 368 UHCI_PCI_LEGSUP LegacySupport; 369 UHCI_PCI_LEGSUP LegacyMask; 370 UHCI_USB_COMMAND Command; 371 UHCI_USB_STATUS HcStatus; 372 MPSTATUS MpStatus = MP_STATUS_SUCCESS; 373 374 DPRINT("UhciTakeControlHC: Resources->ResourcesTypes - %x\n", 375 Resources->ResourcesTypes); 376 377 ResourcesTypes = Resources->ResourcesTypes; 378 379 if ((ResourcesTypes & (USBPORT_RESOURCES_PORT | USBPORT_RESOURCES_INTERRUPT)) != 380 (USBPORT_RESOURCES_PORT | USBPORT_RESOURCES_INTERRUPT)) 381 { 382 DPRINT1("UhciTakeControlHC: MP_STATUS_ERROR\n"); 383 MpStatus = MP_STATUS_ERROR; 384 } 385 386 BaseRegister = UhciExtension->BaseRegister; 387 StatusRegister = &BaseRegister->HcStatus.AsUSHORT; 388 389 RegPacket.UsbPortReadWriteConfigSpace(UhciExtension, 390 TRUE, 391 &LegacySupport.AsUSHORT, 392 PCI_LEGSUP, 393 sizeof(USHORT)); 394 395 UhciDisableInterrupts(UhciExtension); 396 397 Command.AsUSHORT = READ_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT); 398 399 Command.Run = 0; 400 Command.GlobalReset = 0; 401 Command.ConfigureFlag = 0; 402 403 WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT); 404 405 KeQuerySystemTime(&EndTime); 406 EndTime.QuadPart += 100 * 10000; // 100 ms 407 408 HcStatus.AsUSHORT = READ_PORT_USHORT(StatusRegister); 409 DPRINT("UhciTakeControlHC: HcStatus.AsUSHORT - %04X\n", HcStatus.AsUSHORT); 410 411 while (HcStatus.HcHalted == 0) 412 { 413 HcStatus.AsUSHORT = READ_PORT_USHORT(StatusRegister); 414 KeQuerySystemTime(&CurrentTime); 415 416 if (CurrentTime.QuadPart >= EndTime.QuadPart) 417 break; 418 } 419 420 WRITE_PORT_USHORT(StatusRegister, UHCI_USB_STATUS_MASK); 421 422 LegacyMask.AsUSHORT = 0; 423 LegacyMask.Smi60Read = 1; 424 LegacyMask.Smi60Write = 1; 425 LegacyMask.Smi64Read = 1; 426 LegacyMask.Smi64Write = 1; 427 LegacyMask.SmiIrq = 1; 428 LegacyMask.A20Gate = 1; 429 LegacyMask.SmiEndPassThrough = 1; 430 431 if (LegacySupport.AsUSHORT & LegacyMask.AsUSHORT) 432 { 433 DPRINT("UhciTakeControlHC: LegacySupport.AsUSHORT - %04X\n", 434 LegacySupport.AsUSHORT); 435 436 Resources->LegacySupport = 1; 437 438 RegPacket.UsbPortReadWriteConfigSpace(UhciExtension, 439 TRUE, 440 &LegacySupport.AsUSHORT, 441 PCI_LEGSUP, 442 sizeof(USHORT)); 443 LegacySupport.AsUSHORT = 0; 444 445 RegPacket.UsbPortReadWriteConfigSpace(UhciExtension, 446 FALSE, 447 &LegacySupport.AsUSHORT, 448 PCI_LEGSUP, 449 sizeof(USHORT)); 450 } 451 452 return MpStatus; 453 } 454 455 MPSTATUS 456 NTAPI 457 UhciInitializeHardware(IN PUHCI_EXTENSION UhciExtension) 458 { 459 PUHCI_HW_REGISTERS BaseRegister; 460 UHCI_USB_COMMAND Command; 461 UHCI_USB_STATUS StatusMask; 462 463 DPRINT("UhciInitializeHardware: UhciExtension - %p\n", UhciExtension); 464 DPRINT("UhciInitializeHardware: VIA HW FIXME\n"); // after supporting HcFlavor in usbport 465 466 BaseRegister = UhciExtension->BaseRegister; 467 468 /* Save SOF Timing Value */ 469 UhciExtension->SOF_Modify = READ_PORT_UCHAR(&BaseRegister->SOF_Modify); 470 471 RegPacket.UsbPortWait(UhciExtension, 20); 472 473 Command.AsUSHORT = READ_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT); 474 475 /* Global Reset */ 476 Command.AsUSHORT = 0; 477 Command.GlobalReset = 1; 478 WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT); 479 480 RegPacket.UsbPortWait(UhciExtension, 20); 481 482 Command.AsUSHORT = 0; 483 WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT); 484 485 /* Set MaxPacket for full speed bandwidth reclamation */ 486 Command.AsUSHORT = 0; 487 Command.MaxPacket = 1; // 64 bytes 488 WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT); 489 490 /* Restore SOF Timing Value */ 491 WRITE_PORT_UCHAR(&BaseRegister->SOF_Modify, UhciExtension->SOF_Modify); 492 493 StatusMask = UhciExtension->StatusMask; 494 495 StatusMask.Interrupt = 1; 496 StatusMask.ErrorInterrupt = 1; 497 StatusMask.ResumeDetect = 1; 498 StatusMask.HostSystemError = 1; 499 500 UhciExtension->StatusMask = StatusMask; 501 502 return MP_STATUS_SUCCESS; 503 } 504 505 MPSTATUS 506 NTAPI 507 UhciInitializeSchedule(IN PUHCI_EXTENSION UhciExtension, 508 IN PUHCI_HC_RESOURCES HcResourcesVA, 509 IN ULONG hcResourcesPA) 510 { 511 PUHCI_HCD_QH IntQH; 512 ULONG IntQhPA; 513 PUHCI_HCD_QH StaticControlHead; 514 ULONG StaticControlHeadPA; 515 PUHCI_HCD_QH StaticBulkHead; 516 ULONG StaticBulkHeadPA; 517 PUHCI_HCD_TD StaticBulkTD; 518 ULONG StaticBulkTdPA; 519 PUHCI_HCD_TD StaticTD; 520 ULONG StaticTdPA; 521 PUHCI_HCD_TD StaticSofTD; 522 ULONG StaticSofTdPA; 523 ULONG PhysicalAddress; 524 ULONG Idx; 525 ULONG HeadIdx; 526 UCHAR FrameIdx; 527 528 DPRINT("UhciInitializeSchedule: Ext[%p], VA - %p, PA - %lx\n", 529 UhciExtension, 530 HcResourcesVA, 531 hcResourcesPA); 532 533 /* Build structure (tree) of static QHs 534 for interrupt and isochronous transfers */ 535 for (FrameIdx = 0; FrameIdx < INTERRUPT_ENDPOINTs; FrameIdx++) 536 { 537 IntQH = &HcResourcesVA->StaticIntHead[FrameIdx]; 538 IntQhPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticIntHead[FrameIdx]); 539 540 RtlZeroMemory(IntQH, sizeof(UHCI_HCD_QH)); 541 542 IntQH->HwQH.NextElement |= UHCI_QH_ELEMENT_LINK_PTR_TERMINATE; 543 IntQH->PhysicalAddress = IntQhPA; 544 545 UhciExtension->IntQH[FrameIdx] = IntQH; 546 547 if (FrameIdx == 0) 548 UhciSetNextQH(IntQH, UhciExtension->IntQH[0]); 549 else 550 UhciSetNextQH(IntQH, UhciExtension->IntQH[(FrameIdx - 1) / 2]); 551 } 552 553 /* Initialize static QH for control transfers */ 554 StaticControlHead = &HcResourcesVA->StaticControlHead; 555 StaticControlHeadPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticControlHead); 556 557 RtlZeroMemory(StaticControlHead, sizeof(UHCI_HCD_QH)); 558 559 StaticControlHead->HwQH.NextElement |= UHCI_QH_ELEMENT_LINK_PTR_TERMINATE; 560 StaticControlHead->PhysicalAddress = StaticControlHeadPA; 561 562 UhciSetNextQH(UhciExtension->IntQH[0],StaticControlHead); 563 564 UhciExtension->ControlQH = StaticControlHead; 565 566 /* Initialize static QH for bulk transfers */ 567 StaticBulkHead = &HcResourcesVA->StaticBulkHead; 568 StaticBulkHeadPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticBulkHead); 569 570 RtlZeroMemory(StaticBulkHead, sizeof(UHCI_HCD_QH)); 571 572 StaticBulkHead->PhysicalAddress = StaticBulkHeadPA; 573 PhysicalAddress = StaticBulkHeadPA | UHCI_QH_ELEMENT_LINK_PTR_QH; 574 PhysicalAddress |= UHCI_QH_ELEMENT_LINK_PTR_TERMINATE; 575 StaticBulkHead->HwQH.NextQH = PhysicalAddress; 576 577 UhciSetNextQH(StaticControlHead, StaticBulkHead); 578 579 UhciExtension->BulkQH = StaticBulkHead; 580 UhciExtension->BulkTailQH = StaticBulkHead; 581 582 /* Initialize static TD for bulk transfers */ 583 StaticBulkTD = &HcResourcesVA->StaticBulkTD; 584 StaticBulkTdPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticBulkTD); 585 586 StaticBulkTD->HwTD.NextElement = StaticBulkTdPA | UHCI_TD_LINK_PTR_TD; 587 588 StaticBulkTD->HwTD.ControlStatus.AsULONG = 0; 589 StaticBulkTD->HwTD.ControlStatus.IsochronousType = 1; 590 591 StaticBulkTD->HwTD.Token.AsULONG = 0; 592 StaticBulkTD->HwTD.Token.Endpoint = 1; 593 StaticBulkTD->HwTD.Token.MaximumLength = UHCI_TD_LENGTH_NULL; 594 StaticBulkTD->HwTD.Token.PIDCode = UHCI_TD_PID_OUT; 595 596 StaticBulkTD->HwTD.Buffer = 0; 597 598 StaticBulkTD->PhysicalAddress = StaticBulkTdPA; 599 StaticBulkTD->NextHcdTD = NULL; 600 StaticBulkTD->Flags = UHCI_HCD_TD_FLAG_PROCESSED; 601 602 PhysicalAddress = StaticBulkTdPA | UHCI_QH_ELEMENT_LINK_PTR_TD; 603 UhciExtension->BulkQH->HwQH.NextElement = PhysicalAddress; 604 605 /* Set Frame List pointers */ 606 for (Idx = 0; Idx < UHCI_FRAME_LIST_MAX_ENTRIES; Idx++) 607 { 608 HeadIdx = (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms) + 609 (Idx & (ENDPOINT_INTERRUPT_32ms - 1)); 610 611 PhysicalAddress = UhciExtension->IntQH[HeadIdx]->PhysicalAddress; 612 PhysicalAddress |= UHCI_FRAME_LIST_POINTER_QH; 613 HcResourcesVA->FrameList[Idx] = PhysicalAddress; 614 } 615 616 /* Initialize static TD for first frame */ 617 StaticTD = &HcResourcesVA->StaticTD; 618 StaticTdPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticTD); 619 620 RtlZeroMemory(StaticTD, sizeof(UHCI_HCD_TD)); 621 622 StaticTD->PhysicalAddress = StaticTdPA; 623 624 HeadIdx = (INTERRUPT_ENDPOINTs - ENDPOINT_INTERRUPT_32ms); 625 PhysicalAddress = UhciExtension->IntQH[HeadIdx]->PhysicalAddress; 626 StaticTD->HwTD.NextElement = PhysicalAddress | UHCI_TD_LINK_PTR_QH; 627 628 StaticTD->HwTD.ControlStatus.InterruptOnComplete = 1; 629 StaticTD->HwTD.Token.PIDCode = UHCI_TD_PID_IN; 630 631 UhciExtension->StaticTD = StaticTD; 632 633 /* Initialize StaticSofTDs for UhciInterruptNextSOF() */ 634 UhciExtension->SOF_HcdTDs = &HcResourcesVA->StaticSofTD[0]; 635 StaticSofTdPA = hcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, StaticSofTD[0]); 636 637 for (Idx = 0; Idx < UHCI_MAX_STATIC_SOF_TDS; Idx++) 638 { 639 StaticSofTD = UhciExtension->SOF_HcdTDs + Idx; 640 641 RtlZeroMemory(StaticSofTD, sizeof(UHCI_HCD_TD)); 642 643 PhysicalAddress = UhciExtension->IntQH[HeadIdx]->PhysicalAddress; 644 StaticSofTD->HwTD.NextElement = PhysicalAddress | UHCI_TD_LINK_PTR_QH; 645 646 StaticSofTD->HwTD.ControlStatus.InterruptOnComplete = 1; 647 StaticSofTD->PhysicalAddress = StaticSofTdPA; 648 649 StaticSofTdPA += sizeof(UHCI_HCD_TD); 650 } 651 652 return MP_STATUS_SUCCESS; 653 } 654 655 MPSTATUS 656 NTAPI 657 UhciStartController(IN PVOID uhciExtension, 658 IN PUSBPORT_RESOURCES Resources) 659 { 660 PUHCI_EXTENSION UhciExtension = uhciExtension; 661 PUHCI_HW_REGISTERS BaseRegister; 662 MPSTATUS MpStatus; 663 PUSHORT PortControlRegister; 664 UHCI_PORT_STATUS_CONTROL PortControl; 665 UHCI_USB_COMMAND Command; 666 USHORT Port; 667 668 UhciExtension->Flags &= ~UHCI_EXTENSION_FLAG_SUSPENDED; 669 UhciExtension->BaseRegister = Resources->ResourceBase; 670 BaseRegister = UhciExtension->BaseRegister; 671 DPRINT("UhciStartController: UhciExtension - %p, BaseRegister - %p\n", UhciExtension, BaseRegister); 672 673 UhciExtension->HcFlavor = Resources->HcFlavor; 674 675 MpStatus = UhciTakeControlHC(UhciExtension, Resources); 676 677 if (MpStatus == MP_STATUS_SUCCESS) 678 { 679 MpStatus = UhciInitializeHardware(UhciExtension); 680 681 if (MpStatus == MP_STATUS_SUCCESS) 682 { 683 UhciExtension->HcResourcesVA = (PUHCI_HC_RESOURCES)Resources->StartVA; 684 UhciExtension->HcResourcesPA = Resources->StartPA; 685 686 MpStatus = UhciInitializeSchedule(UhciExtension, 687 UhciExtension->HcResourcesVA, 688 UhciExtension->HcResourcesPA); 689 690 UhciExtension->LockFrameList = 0; 691 } 692 } 693 694 WRITE_PORT_ULONG(&BaseRegister->FrameAddress, 695 UhciExtension->HcResourcesPA + FIELD_OFFSET(UHCI_HC_RESOURCES, FrameList)); 696 697 if (MpStatus == MP_STATUS_SUCCESS) 698 { 699 Command.AsUSHORT = READ_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT); 700 Command.Run = 1; 701 WRITE_PORT_USHORT(&BaseRegister->HcCommand.AsUSHORT, Command.AsUSHORT); 702 703 for (Port = 0; Port < UHCI_NUM_ROOT_HUB_PORTS; Port++) 704 { 705 PortControlRegister = &BaseRegister->PortControl[Port].AsUSHORT; 706 PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister); 707 708 PortControl.ConnectStatusChange = 0; 709 PortControl.Suspend = 0; 710 711 WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT); 712 } 713 714 UhciExtension->HcResourcesVA->FrameList[0] = 715 UhciExtension->StaticTD->PhysicalAddress; 716 } 717 718 return MP_STATUS_SUCCESS; 719 } 720 721 VOID 722 NTAPI 723 UhciStopController(IN PVOID uhciExtension, 724 IN BOOLEAN IsDoDisableInterrupts) 725 { 726 PUHCI_EXTENSION UhciExtension = uhciExtension; 727 PUHCI_HW_REGISTERS BaseRegister; 728 PUSHORT CommandReg; 729 UHCI_USB_COMMAND Command; 730 LARGE_INTEGER EndTime; 731 LARGE_INTEGER CurrentTime; 732 733 DPRINT("UhciStopController: UhciExtension - %p\n", UhciExtension); 734 735 BaseRegister = UhciExtension->BaseRegister; 736 CommandReg = &BaseRegister->HcCommand.AsUSHORT; 737 738 Command.AsUSHORT = READ_PORT_USHORT(CommandReg); 739 740 if (Command.AsUSHORT == 0xFFFF) 741 { 742 DPRINT("UhciStopController: Command == -1\n"); 743 return; 744 } 745 746 DPRINT("UhciStopController: Command.AsUSHORT - %p\n", Command.AsUSHORT); 747 748 if (Command.GlobalReset) 749 { 750 Command.GlobalReset = 0; 751 WRITE_PORT_USHORT(CommandReg, Command.AsUSHORT); 752 } 753 754 Command.HcReset = 1; 755 756 WRITE_PORT_USHORT(CommandReg, Command.AsUSHORT); 757 758 KeQuerySystemTime(&EndTime); 759 EndTime.QuadPart += 100 * 1000; 760 761 while (Command.AsUSHORT = READ_PORT_USHORT(CommandReg), 762 Command.HcReset == 1) 763 { 764 KeQuerySystemTime(&CurrentTime); 765 766 if (CurrentTime.QuadPart >= EndTime.QuadPart) 767 { 768 DPRINT1("UhciStopController: Failed to reset\n"); 769 DbgBreakPoint(); 770 break; 771 } 772 } 773 } 774 775 VOID 776 NTAPI 777 UhciSuspendController(IN PVOID uhciExtension) 778 { 779 DPRINT_IMPL("UhciSuspendController: UNIMPLEMENTED. FIXME\n"); 780 } 781 782 MPSTATUS 783 NTAPI 784 UhciResumeController(IN PVOID uhciExtension) 785 { 786 DPRINT_IMPL("UhciResumeController: UNIMPLEMENTED. FIXME\n"); 787 return MP_STATUS_SUCCESS; 788 } 789 790 BOOLEAN 791 NTAPI 792 UhciHardwarePresent(IN PUHCI_EXTENSION UhciExtension) 793 { 794 UHCI_USB_STATUS UhciStatus; 795 PUSHORT StatusReg; 796 797 StatusReg = &UhciExtension->BaseRegister->HcStatus.AsUSHORT; 798 UhciStatus.AsUSHORT = READ_PORT_USHORT(StatusReg); 799 800 if (UhciStatus.AsUSHORT == MAXUSHORT) 801 DPRINT_UHCI("UhciHardwarePresent: HW not present\n"); 802 803 return UhciStatus.AsUSHORT != MAXUSHORT; 804 } 805 806 BOOLEAN 807 NTAPI 808 UhciInterruptService(IN PVOID uhciExtension) 809 { 810 PUHCI_EXTENSION UhciExtension = uhciExtension; 811 PUHCI_HW_REGISTERS BaseRegister; 812 PUSHORT CommandReg; 813 UHCI_USB_COMMAND Command; 814 PUSHORT StatusReg; 815 UHCI_USB_STATUS HcStatus; 816 PUSHORT InterruptEnableReg; 817 PUHCI_HCD_QH QH; 818 PUHCI_HCD_QH BulkTailQH; 819 ULONG ScheduleError; 820 BOOLEAN Result = FALSE; 821 822 BaseRegister = UhciExtension->BaseRegister; 823 StatusReg = &BaseRegister->HcStatus.AsUSHORT; 824 InterruptEnableReg = &BaseRegister->HcInterruptEnable.AsUSHORT; 825 CommandReg = &BaseRegister->HcCommand.AsUSHORT; 826 827 if (!UhciHardwarePresent(UhciExtension)) 828 { 829 DPRINT1("UhciInterruptService: return FALSE\n"); 830 return FALSE; 831 } 832 833 HcStatus.AsUSHORT = READ_PORT_USHORT(StatusReg) & UHCI_USB_STATUS_MASK; 834 835 if (HcStatus.HostSystemError || HcStatus.HcProcessError) 836 { 837 DPRINT1("UhciInterruptService: Error [%p] HcStatus %X\n", 838 UhciExtension, 839 HcStatus.AsUSHORT); 840 } 841 else if (HcStatus.AsUSHORT) 842 { 843 UhciExtension->HcScheduleError = 0; 844 } 845 846 if (HcStatus.HcProcessError) 847 { 848 USHORT fn = READ_PORT_USHORT(&BaseRegister->FrameNumber); 849 USHORT intr = READ_PORT_USHORT(InterruptEnableReg); 850 USHORT cmd = READ_PORT_USHORT(CommandReg); 851 852 DPRINT1("UhciInterruptService: HC ProcessError!\n"); 853 DPRINT1("UhciExtension %p, frame %X\n", UhciExtension, fn); 854 DPRINT1("HcCommand %X\n", cmd); 855 DPRINT1("HcStatus %X\n", HcStatus.AsUSHORT); 856 DPRINT1("HcInterruptEnable %X\n", intr); 857 858 DbgBreakPoint(); 859 } 860 861 if (HcStatus.HcHalted) 862 { 863 DPRINT_UHCI("UhciInterruptService: Hc Halted [%p] HcStatus %X\n", 864 UhciExtension, 865 HcStatus.AsUSHORT); 866 } 867 else if (HcStatus.AsUSHORT) 868 { 869 UhciExtension->HcStatus.AsUSHORT = HcStatus.AsUSHORT; 870 871 WRITE_PORT_USHORT(StatusReg, HcStatus.AsUSHORT); 872 WRITE_PORT_USHORT(InterruptEnableReg, 0); 873 874 if (HcStatus.HostSystemError) 875 { 876 DPRINT1("UhciInterruptService: HostSystemError! HcStatus - %X\n", 877 HcStatus.AsUSHORT); 878 879 DbgBreakPoint(); 880 } 881 882 Result = TRUE; 883 } 884 885 if (!HcStatus.Interrupt) 886 goto NextProcess; 887 888 UhciUpdateCounter(UhciExtension); 889 890 BulkTailQH = UhciExtension->BulkTailQH; 891 892 if (BulkTailQH->HwQH.NextQH & UHCI_QH_HEAD_LINK_PTR_TERMINATE) 893 goto NextProcess; 894 895 QH = UhciExtension->BulkQH; 896 897 do 898 { 899 QH = QH->NextHcdQH; 900 901 if (!QH) 902 { 903 BulkTailQH->HwQH.NextQH |= UHCI_QH_HEAD_LINK_PTR_TERMINATE; 904 goto NextProcess; 905 } 906 } 907 while (QH->HwQH.NextElement & UHCI_QH_ELEMENT_LINK_PTR_TERMINATE); 908 909 NextProcess: 910 911 if (HcStatus.HcProcessError) 912 { 913 UhciCleanupFrameList(UhciExtension, TRUE); 914 915 ScheduleError = UhciExtension->HcScheduleError; 916 UhciExtension->HcScheduleError = ScheduleError + 1; 917 918 DPRINT1("UhciInterruptService: [%p] ScheduleError %X\n", 919 UhciExtension, 920 ScheduleError); 921 922 if (ScheduleError < UHCI_MAX_HC_SCHEDULE_ERRORS) 923 { 924 Command.AsUSHORT = READ_PORT_USHORT(CommandReg); 925 Command.Run = 1; 926 WRITE_PORT_USHORT(CommandReg, Command.AsUSHORT); 927 } 928 } 929 else if (HcStatus.Interrupt && UhciExtension->ExtensionLock) 930 { 931 DPRINT1("UhciInterruptService: [%p] HcStatus %X\n", 932 UhciExtension, 933 HcStatus.AsUSHORT); 934 935 UhciCleanupFrameList(UhciExtension, FALSE); 936 } 937 938 return Result; 939 } 940 941 VOID 942 NTAPI 943 UhciInterruptDpc(IN PVOID uhciExtension, 944 IN BOOLEAN IsDoEnableInterrupts) 945 { 946 PUHCI_EXTENSION UhciExtension = uhciExtension; 947 PUHCI_HW_REGISTERS BaseRegister; 948 UHCI_USB_STATUS HcStatus; 949 950 DPRINT_UHCI("UhciInterruptDpc: [%p] EnableInt %x, HcStatus %X\n", 951 uhciExtension, IsDoEnableInterrupts, UhciExtension->HcStatus); 952 953 BaseRegister = UhciExtension->BaseRegister; 954 955 HcStatus = UhciExtension->HcStatus; 956 UhciExtension->HcStatus.AsUSHORT = 0; 957 958 if ((HcStatus.Interrupt | HcStatus.ErrorInterrupt) != 0) 959 RegPacket.UsbPortInvalidateEndpoint(UhciExtension, 0); 960 961 if (IsDoEnableInterrupts) 962 { 963 WRITE_PORT_USHORT(&BaseRegister->HcInterruptEnable.AsUSHORT, 964 UhciExtension->StatusMask.AsUSHORT); 965 } 966 } 967 968 VOID 969 NTAPI 970 UhciQueueTransfer(IN PUHCI_EXTENSION UhciExtension, 971 IN PUHCI_ENDPOINT UhciEndpoint, 972 IN PUHCI_HCD_TD FirstTD, 973 IN PUHCI_HCD_TD LastTD) 974 { 975 PUHCI_HCD_QH QH; 976 PUHCI_HCD_QH BulkTailQH; 977 PUHCI_HCD_TD TailTD; 978 ULONG PhysicalAddress; 979 980 DPRINT("UhciQueueTransfer: FirstTD - %p, LastTD - %p\n", FirstTD, LastTD); 981 982 TailTD = UhciEndpoint->TailTD; 983 QH = UhciEndpoint->QH; 984 985 if (UhciEndpoint->HeadTD) 986 { 987 TailTD->NextHcdTD = FirstTD; 988 989 TailTD->HwTD.NextElement = FirstTD->PhysicalAddress; 990 TailTD->HwTD.NextElement |= UHCI_TD_LINK_PTR_TD; 991 992 PhysicalAddress = QH->HwQH.NextElement; 993 994 PhysicalAddress &= ~(UHCI_TD_LINK_PTR_TERMINATE | 995 UHCI_TD_LINK_PTR_QH | 996 UHCI_TD_LINK_PTR_DEPTH_FIRST); 997 998 if (FirstTD->HwTD.ControlStatus.Status & UHCI_TD_STS_ACTIVE) 999 { 1000 if (PhysicalAddress == TailTD->PhysicalAddress && 1001 !(TailTD->HwTD.ControlStatus.Status & UHCI_TD_STS_ACTIVE)) 1002 { 1003 QH->HwQH.NextElement = FirstTD->PhysicalAddress; 1004 1005 QH->HwQH.NextElement &= ~(UHCI_QH_ELEMENT_LINK_PTR_TERMINATE | 1006 UHCI_QH_ELEMENT_LINK_PTR_QH); 1007 } 1008 } 1009 } 1010 else 1011 { 1012 if (FirstTD) 1013 { 1014 UhciEndpoint->HeadTD = FirstTD; 1015 } 1016 else 1017 { 1018 UhciEndpoint->TailTD = NULL; 1019 UhciEndpoint->HeadTD = NULL; 1020 } 1021 1022 if (FirstTD == NULL || UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED) 1023 { 1024 PhysicalAddress = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE; 1025 } 1026 else 1027 { 1028 PhysicalAddress = FirstTD->PhysicalAddress; 1029 PhysicalAddress &= ~UHCI_QH_ELEMENT_LINK_PTR_TERMINATE; 1030 } 1031 1032 QH->HwQH.NextElement = PhysicalAddress & ~UHCI_QH_ELEMENT_LINK_PTR_QH; 1033 } 1034 1035 if (UhciEndpoint->EndpointProperties.TransferType == USBPORT_TRANSFER_TYPE_BULK) 1036 { 1037 BulkTailQH = UhciExtension->BulkTailQH; 1038 BulkTailQH->HwQH.NextQH &= ~UHCI_QH_HEAD_LINK_PTR_TERMINATE; 1039 } 1040 1041 UhciEndpoint->TailTD = LastTD; 1042 } 1043 1044 PUHCI_HCD_TD 1045 NTAPI 1046 UhciAllocateTD(IN PUHCI_EXTENSION UhciExtension, 1047 IN PUHCI_ENDPOINT UhciEndpoint) 1048 { 1049 PUHCI_HCD_TD TD; 1050 ULONG AllocTdCounter; 1051 ULONG ix; 1052 1053 DPRINT_UHCI("UhciAllocateTD: ...\n"); 1054 1055 AllocTdCounter = UhciEndpoint->AllocTdCounter; 1056 1057 for (ix = 0; ix < UhciEndpoint->MaxTDs; ++ix) 1058 { 1059 TD = &UhciEndpoint->FirstTD[AllocTdCounter]; 1060 1061 if (!(TD->Flags & UHCI_HCD_TD_FLAG_ALLOCATED)) 1062 { 1063 TD->Flags |= UHCI_HCD_TD_FLAG_ALLOCATED; 1064 1065 UhciEndpoint->AllocatedTDs++; 1066 UhciEndpoint->AllocTdCounter = AllocTdCounter; 1067 1068 return TD; 1069 } 1070 1071 if (AllocTdCounter < UhciEndpoint->MaxTDs - 1) 1072 AllocTdCounter++; 1073 else 1074 AllocTdCounter = 0; 1075 } 1076 1077 return NULL; 1078 } 1079 1080 VOID 1081 NTAPI 1082 UhciMapAsyncTransferToTDs(IN PUHCI_EXTENSION UhciExtension, 1083 IN PUHCI_ENDPOINT UhciEndpoint, 1084 IN PUHCI_TRANSFER UhciTransfer, 1085 OUT PUHCI_HCD_TD * OutFirstTD, 1086 OUT PUHCI_HCD_TD * OutLastTD, 1087 IN PUSBPORT_SCATTER_GATHER_LIST SgList) 1088 { 1089 PUHCI_HCD_TD TD; 1090 PUHCI_HCD_TD LastTD = NULL; 1091 ULONG PhysicalAddress; 1092 USHORT TotalMaxPacketSize; 1093 USHORT DeviceSpeed; 1094 USHORT EndpointAddress; 1095 USHORT DeviceAddress; 1096 ULONG TransferType; 1097 SIZE_T TransferLength = 0; 1098 SIZE_T LengthMapped = 0; 1099 SIZE_T BytesRemaining; 1100 SIZE_T LengthThisTD; 1101 ULONG ix; 1102 BOOL DataToggle; 1103 UCHAR PIDCode; 1104 BOOLEAN IsLastTd = TRUE; 1105 BOOLEAN ZeroLengthTransfer = TRUE; 1106 1107 DPRINT_UHCI("UhciMapAsyncTransferToTDs: ...\n"); 1108 1109 TotalMaxPacketSize = UhciEndpoint->EndpointProperties.TotalMaxPacketSize; 1110 DeviceSpeed = UhciEndpoint->EndpointProperties.DeviceSpeed; 1111 EndpointAddress = UhciEndpoint->EndpointProperties.EndpointAddress; 1112 DeviceAddress = UhciEndpoint->EndpointProperties.DeviceAddress; 1113 TransferType = UhciEndpoint->EndpointProperties.TransferType; 1114 1115 if (SgList->SgElementCount || TransferType == USBPORT_TRANSFER_TYPE_CONTROL) 1116 ZeroLengthTransfer = FALSE; 1117 1118 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL) 1119 { 1120 if (UhciTransfer->TransferParameters->TransferFlags & 1121 USBD_TRANSFER_DIRECTION_IN) 1122 { 1123 PIDCode = UHCI_TD_PID_IN; 1124 } 1125 else 1126 { 1127 PIDCode = UHCI_TD_PID_OUT; 1128 } 1129 1130 DataToggle = UHCI_TD_PID_DATA1; 1131 } 1132 else 1133 { 1134 if (USB_ENDPOINT_DIRECTION_OUT(EndpointAddress)) 1135 PIDCode = UHCI_TD_PID_OUT; 1136 else 1137 PIDCode = UHCI_TD_PID_IN; 1138 1139 DataToggle = UhciEndpoint->DataToggle; 1140 } 1141 1142 for (ix = 0; ix < SgList->SgElementCount || ZeroLengthTransfer; ix++) 1143 { 1144 BytesRemaining = SgList->SgElement[ix].SgTransferLength; 1145 PhysicalAddress = SgList->SgElement[ix].SgPhysicalAddress.LowPart; 1146 1147 if (!IsLastTd) 1148 { 1149 PhysicalAddress += TransferLength; 1150 BytesRemaining -= TransferLength; 1151 } 1152 1153 IsLastTd = TRUE; 1154 TransferLength = 0; 1155 1156 while (BytesRemaining || ZeroLengthTransfer) 1157 { 1158 ZeroLengthTransfer = FALSE; 1159 1160 if (BytesRemaining >= TotalMaxPacketSize) 1161 { 1162 LengthThisTD = TotalMaxPacketSize; 1163 BytesRemaining -= TotalMaxPacketSize; 1164 } 1165 else 1166 { 1167 if (ix >= SgList->SgElementCount - 1) 1168 { 1169 LengthThisTD = BytesRemaining; 1170 } 1171 else 1172 { 1173 IsLastTd = FALSE; 1174 1175 DPRINT1("UhciMapAsyncTransferToTds: IsLastTd = FALSE. FIXME\n"); 1176 ASSERT(FALSE); 1177 } 1178 1179 BytesRemaining = 0; 1180 } 1181 1182 UhciTransfer->PendingTds++; 1183 TD = UhciAllocateTD(UhciExtension, UhciEndpoint); 1184 TD->Flags |= UHCI_HCD_TD_FLAG_PROCESSED; 1185 1186 TD->HwTD.NextElement = 0; 1187 TD->HwTD.Buffer = PhysicalAddress; 1188 1189 TD->HwTD.ControlStatus.AsULONG = 0; 1190 TD->HwTD.ControlStatus.LowSpeedDevice = (DeviceSpeed == UsbLowSpeed); 1191 TD->HwTD.ControlStatus.Status = UHCI_TD_STS_ACTIVE; 1192 TD->HwTD.ControlStatus.ErrorCounter = 3; 1193 TD->HwTD.ControlStatus.ActualLength = UHCI_TD_LENGTH_NULL; 1194 TD->HwTD.ControlStatus.ShortPacketDetect = 1; 1195 1196 TD->HwTD.Token.AsULONG = 0; 1197 TD->HwTD.Token.Endpoint = EndpointAddress; 1198 TD->HwTD.Token.DeviceAddress = DeviceAddress; 1199 TD->HwTD.Token.PIDCode = PIDCode; 1200 1201 if (LengthThisTD == 0) 1202 TD->HwTD.Token.MaximumLength = UHCI_TD_LENGTH_NULL; 1203 else 1204 TD->HwTD.Token.MaximumLength = LengthThisTD - 1; 1205 1206 TD->HwTD.Token.DataToggle = (DataToggle == UHCI_TD_PID_DATA1); 1207 1208 TD->NextHcdTD = 0; 1209 TD->UhciTransfer = UhciTransfer; 1210 1211 if (!IsLastTd) 1212 ASSERT(FALSE); 1213 1214 PhysicalAddress += LengthThisTD; 1215 LengthMapped += LengthThisTD; 1216 1217 if (LastTD) 1218 { 1219 LastTD->HwTD.NextElement = TD->PhysicalAddress & 1220 UHCI_TD_LINK_POINTER_MASK; 1221 LastTD->NextHcdTD = TD; 1222 } 1223 else 1224 { 1225 *OutFirstTD = TD; 1226 } 1227 1228 LastTD = TD; 1229 DataToggle = DataToggle == UHCI_TD_PID_DATA0; 1230 } 1231 } 1232 1233 UhciEndpoint->DataToggle = DataToggle; 1234 1235 *OutLastTD = LastTD; 1236 } 1237 1238 MPSTATUS 1239 NTAPI 1240 UhciControlTransfer(IN PUHCI_EXTENSION UhciExtension, 1241 IN PUHCI_ENDPOINT UhciEndpoint, 1242 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, 1243 IN PUHCI_TRANSFER UhciTransfer, 1244 IN PUSBPORT_SCATTER_GATHER_LIST SgList) 1245 { 1246 PUHCI_HCD_TD FirstTD; 1247 PUHCI_HCD_TD LastTD; 1248 PUHCI_HCD_TD DataFirstTD; 1249 PUHCI_HCD_TD DataLastTD; 1250 UHCI_CONTROL_STATUS ControlStatus; 1251 USB_DEVICE_SPEED DeviceSpeed; 1252 USHORT EndpointAddress; 1253 USHORT DeviceAddress; 1254 ULONG PhysicalAddress; 1255 1256 DPRINT_UHCI("UhciControlTransfer: UhciTransfer - %p\n", UhciTransfer); 1257 1258 if (UhciEndpoint->EndpointLock > 1) 1259 { 1260 InterlockedDecrement(&UhciEndpoint->EndpointLock); 1261 1262 if (UhciEndpoint->EndpointProperties.TransferType == 1263 USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 1264 { 1265 InterlockedDecrement(&UhciExtension->ExtensionLock); 1266 } 1267 1268 DPRINT("UhciControlTransfer: end MP_STATUS_FAILURE\n"); 1269 return MP_STATUS_FAILURE; 1270 } 1271 1272 DeviceSpeed = UhciEndpoint->EndpointProperties.DeviceSpeed; 1273 EndpointAddress = UhciEndpoint->EndpointProperties.EndpointAddress; 1274 DeviceAddress = UhciEndpoint->EndpointProperties.DeviceAddress; 1275 1276 /* Allocate and setup first TD */ 1277 UhciTransfer->PendingTds++; 1278 FirstTD = UhciAllocateTD(UhciExtension, UhciEndpoint); 1279 FirstTD->Flags |= UHCI_HCD_TD_FLAG_PROCESSED; 1280 DPRINT_UHCI("UhciControlTransfer: FirstTD - %p\n", FirstTD); 1281 1282 FirstTD->HwTD.NextElement = 0; 1283 1284 ControlStatus.AsULONG = 0; 1285 ControlStatus.LowSpeedDevice = (DeviceSpeed == UsbLowSpeed); 1286 ControlStatus.Status |= UHCI_TD_STS_ACTIVE; 1287 ControlStatus.ErrorCounter = 3; 1288 FirstTD->HwTD.ControlStatus = ControlStatus; 1289 1290 FirstTD->HwTD.Token.AsULONG = 0; 1291 FirstTD->HwTD.Token.Endpoint = EndpointAddress; 1292 FirstTD->HwTD.Token.DeviceAddress = DeviceAddress; 1293 1294 FirstTD->HwTD.Token.MaximumLength = sizeof(USB_DEFAULT_PIPE_SETUP_PACKET); 1295 FirstTD->HwTD.Token.MaximumLength--; 1296 FirstTD->HwTD.Token.PIDCode = UHCI_TD_PID_SETUP; 1297 FirstTD->HwTD.Token.DataToggle = UHCI_TD_PID_DATA0; 1298 1299 RtlCopyMemory(&FirstTD->SetupPacket, 1300 &TransferParameters->SetupPacket, 1301 sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); 1302 1303 FirstTD->HwTD.Buffer = FirstTD->PhysicalAddress + FIELD_OFFSET(UHCI_HCD_TD, SetupPacket); 1304 1305 FirstTD->NextHcdTD = NULL; 1306 FirstTD->UhciTransfer = UhciTransfer; 1307 1308 /* Allocate and setup last TD */ 1309 UhciTransfer->PendingTds++; 1310 LastTD = UhciAllocateTD(UhciExtension, UhciEndpoint); 1311 LastTD->Flags |= UHCI_HCD_TD_FLAG_PROCESSED; 1312 DPRINT_UHCI("UhciControlTransfer: LastTD - %p\n", LastTD); 1313 1314 LastTD->HwTD.NextElement = 0; 1315 1316 LastTD->HwTD.ControlStatus.AsULONG = 0; 1317 LastTD->HwTD.ControlStatus.LowSpeedDevice = (DeviceSpeed == UsbLowSpeed); 1318 LastTD->HwTD.ControlStatus.Status |= UHCI_TD_STS_ACTIVE; 1319 LastTD->HwTD.ControlStatus.ErrorCounter = 3; 1320 1321 LastTD->HwTD.Token.AsULONG = 0; 1322 LastTD->HwTD.Token.Endpoint = EndpointAddress; 1323 LastTD->HwTD.Token.DeviceAddress = DeviceAddress; 1324 1325 LastTD->UhciTransfer = UhciTransfer; 1326 LastTD->NextHcdTD = NULL; 1327 1328 /* Allocate and setup TDs for data */ 1329 DataFirstTD = NULL; 1330 DataLastTD = NULL; 1331 1332 UhciMapAsyncTransferToTDs(UhciExtension, 1333 UhciEndpoint, 1334 UhciTransfer, 1335 &DataFirstTD, 1336 &DataLastTD, 1337 SgList); 1338 1339 if (DataFirstTD) 1340 { 1341 PhysicalAddress = DataFirstTD->PhysicalAddress; 1342 PhysicalAddress &= UHCI_TD_LINK_POINTER_MASK; 1343 FirstTD->HwTD.NextElement = PhysicalAddress; 1344 FirstTD->NextHcdTD = DataFirstTD; 1345 1346 PhysicalAddress = LastTD->PhysicalAddress; 1347 PhysicalAddress &= UHCI_TD_LINK_POINTER_MASK; 1348 DataLastTD->HwTD.NextElement = PhysicalAddress; 1349 DataLastTD->NextHcdTD = LastTD; 1350 } 1351 else 1352 { 1353 PhysicalAddress = LastTD->PhysicalAddress; 1354 PhysicalAddress &= UHCI_TD_LINK_POINTER_MASK; 1355 FirstTD->HwTD.NextElement = PhysicalAddress; 1356 FirstTD->NextHcdTD = LastTD; 1357 } 1358 1359 LastTD->HwTD.Buffer = 0; 1360 LastTD->HwTD.ControlStatus.InterruptOnComplete = 1; 1361 1362 LastTD->HwTD.Token.DataToggle = UHCI_TD_PID_DATA1; 1363 LastTD->HwTD.Token.MaximumLength = UHCI_TD_LENGTH_NULL; 1364 1365 if (UhciTransfer->TransferParameters->TransferFlags & 1366 USBD_TRANSFER_DIRECTION_IN) 1367 { 1368 LastTD->HwTD.Token.PIDCode = UHCI_TD_PID_OUT; 1369 } 1370 else 1371 { 1372 LastTD->HwTD.Token.PIDCode = UHCI_TD_PID_IN; 1373 } 1374 1375 LastTD->HwTD.NextElement = UHCI_TD_LINK_PTR_TERMINATE; 1376 1377 LastTD->Flags |= UHCI_HCD_TD_FLAG_CONTROLL; 1378 LastTD->NextHcdTD = NULL; 1379 1380 /* Link this transfer to queue */ 1381 UhciQueueTransfer(UhciExtension, UhciEndpoint, FirstTD, LastTD); 1382 1383 DPRINT_UHCI("UhciControlTransfer: end MP_STATUS_SUCCESS\n"); 1384 return MP_STATUS_SUCCESS; 1385 } 1386 1387 MPSTATUS 1388 NTAPI 1389 UhciBulkOrInterruptTransfer(IN PUHCI_EXTENSION UhciExtension, 1390 IN PUHCI_ENDPOINT UhciEndpoint, 1391 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, 1392 IN PUHCI_TRANSFER UhciTransfer, 1393 IN PUSBPORT_SCATTER_GATHER_LIST SgList) 1394 { 1395 PUHCI_HCD_TD DataFirstTD; 1396 PUHCI_HCD_TD DataLastTD; 1397 ULONG TotalMaxPacketSize; 1398 ULONG SgCount; 1399 ULONG TransferLength; 1400 ULONG TDs; 1401 ULONG ix; 1402 1403 DPRINT_UHCI("UhciBulkOrInterruptTransfer: ...\n"); 1404 1405 TotalMaxPacketSize = UhciEndpoint->EndpointProperties.TotalMaxPacketSize; 1406 1407 SgCount = SgList->SgElementCount; 1408 1409 if (SgCount == 0) 1410 { 1411 DPRINT("UhciBulkOrInterruptTransfer: SgCount == 0 \n"); 1412 TDs = 1; 1413 } 1414 else 1415 { 1416 TransferLength = 0; 1417 1418 for (ix = 0; ix < SgCount; ++ix) 1419 { 1420 TransferLength += SgList->SgElement[ix].SgTransferLength; 1421 } 1422 1423 DPRINT("UhciBulkOrInterruptTransfer: SgCount - %X, TransferLength - %X\n", 1424 SgList->SgElementCount, 1425 TransferLength); 1426 1427 if (TransferLength) 1428 { 1429 TDs = TransferLength + (TotalMaxPacketSize - 1); 1430 TDs /= TotalMaxPacketSize; 1431 } 1432 else 1433 { 1434 TDs = 1; 1435 } 1436 } 1437 1438 if ((UhciEndpoint->MaxTDs - UhciEndpoint->AllocatedTDs) < TDs) 1439 { 1440 DPRINT1("UhciBulkOrInterruptTransfer: Not enough TDs \n"); 1441 return MP_STATUS_FAILURE; 1442 } 1443 1444 DataFirstTD = NULL; 1445 DataLastTD = NULL; 1446 1447 UhciMapAsyncTransferToTDs(UhciExtension, 1448 UhciEndpoint, 1449 UhciTransfer, 1450 &DataFirstTD, 1451 &DataLastTD, 1452 SgList); 1453 1454 if (DataLastTD == NULL || DataFirstTD == NULL) 1455 { 1456 DPRINT1("UhciBulkOrInterruptTransfer: !DataLastTD || !DataFirstTD\n"); 1457 return MP_STATUS_FAILURE; 1458 } 1459 1460 DataLastTD->HwTD.NextElement = UHCI_TD_LINK_PTR_TERMINATE; 1461 DataLastTD->HwTD.ControlStatus.InterruptOnComplete = 1; 1462 DataLastTD->NextHcdTD = NULL; 1463 1464 UhciQueueTransfer(UhciExtension, 1465 UhciEndpoint, 1466 DataFirstTD, 1467 DataLastTD); 1468 1469 return MP_STATUS_SUCCESS; 1470 } 1471 1472 MPSTATUS 1473 NTAPI 1474 UhciSubmitTransfer(IN PVOID uhciExtension, 1475 IN PVOID uhciEndpoint, 1476 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, 1477 IN PVOID uhciTransfer, 1478 IN PUSBPORT_SCATTER_GATHER_LIST SgList) 1479 { 1480 PUHCI_EXTENSION UhciExtension = uhciExtension; 1481 PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint; 1482 PUHCI_TRANSFER UhciTransfer = uhciTransfer; 1483 ULONG TransferType; 1484 1485 DPRINT_UHCI("UhciSubmitTransfer: ...\n"); 1486 1487 InterlockedIncrement(&UhciEndpoint->EndpointLock); 1488 1489 TransferType = UhciEndpoint->EndpointProperties.TransferType; 1490 1491 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS && 1492 InterlockedIncrement(&UhciExtension->ExtensionLock) == 1) 1493 { 1494 UhciExtension->FrameNumber = UhciGet32BitFrameNumber(UhciExtension); 1495 } 1496 1497 RtlZeroMemory(UhciTransfer, sizeof(UHCI_TRANSFER)); 1498 1499 UhciTransfer->TransferParameters = TransferParameters; 1500 UhciTransfer->UhciEndpoint = UhciEndpoint; 1501 UhciTransfer->USBDStatus = USBD_STATUS_SUCCESS; 1502 1503 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL) 1504 { 1505 return UhciControlTransfer(UhciExtension, 1506 UhciEndpoint, 1507 TransferParameters, 1508 UhciTransfer, 1509 SgList); 1510 } 1511 1512 if (TransferType == USBPORT_TRANSFER_TYPE_BULK || 1513 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 1514 { 1515 return UhciBulkOrInterruptTransfer(UhciExtension, 1516 UhciEndpoint, 1517 TransferParameters, 1518 UhciTransfer, 1519 SgList); 1520 } 1521 1522 DPRINT1("UhciSubmitTransfer: Error TransferType - %x\n", TransferType); 1523 1524 return MP_STATUS_SUCCESS; 1525 } 1526 1527 USBD_STATUS 1528 NTAPI 1529 UhciGetErrorFromTD(IN PUHCI_EXTENSION UhciExtension, 1530 IN PUHCI_HCD_TD TD) 1531 { 1532 USBD_STATUS USBDStatus; 1533 UCHAR TdStatus; 1534 1535 //DPRINT("UhciGetErrorFromTD: ...\n"); 1536 1537 TdStatus = TD->HwTD.ControlStatus.Status; 1538 1539 if (TdStatus == UHCI_TD_STS_ACTIVE) 1540 { 1541 if (TD->HwTD.Token.MaximumLength == UHCI_TD_LENGTH_NULL) 1542 return USBD_STATUS_SUCCESS; 1543 1544 if (TD->HwTD.ControlStatus.ActualLength + 1 >= 1545 TD->HwTD.Token.MaximumLength + 1) 1546 { 1547 return USBD_STATUS_SUCCESS; 1548 } 1549 1550 if (TD->HwTD.ControlStatus.InterruptOnComplete == 1) 1551 return USBD_STATUS_SUCCESS; 1552 1553 return USBD_STATUS_ERROR_SHORT_TRANSFER; 1554 } 1555 1556 if (TdStatus & UHCI_TD_STS_BABBLE_DETECTED && 1557 TdStatus & UHCI_TD_STS_STALLED) 1558 { 1559 DPRINT1("UhciGetErrorFromTD: USBD_STATUS_BUFFER_OVERRUN, TD - %p\n", TD); 1560 return USBD_STATUS_BUFFER_OVERRUN; 1561 } 1562 1563 if (TdStatus & UHCI_TD_STS_TIMEOUT_CRC_ERROR && 1564 TdStatus & UHCI_TD_STS_STALLED) 1565 { 1566 DPRINT1("UhciGetErrorFromTD: USBD_STATUS_DEV_NOT_RESPONDING, TD - %p\n", TD); 1567 return USBD_STATUS_DEV_NOT_RESPONDING; 1568 } 1569 1570 if (TdStatus & UHCI_TD_STS_TIMEOUT_CRC_ERROR) 1571 { 1572 if (TD->HwTD.ControlStatus.ActualLength == UHCI_TD_LENGTH_NULL) 1573 { 1574 DPRINT1("UhciGetErrorFromTD: USBD_STATUS_DEV_NOT_RESPONDING, TD - %p\n", TD); 1575 return USBD_STATUS_DEV_NOT_RESPONDING; 1576 } 1577 else 1578 { 1579 DPRINT1("UhciGetErrorFromTD: USBD_STATUS_CRC, TD - %p\n", TD); 1580 return USBD_STATUS_CRC; 1581 } 1582 } 1583 else if (TdStatus & UHCI_TD_STS_DATA_BUFFER_ERROR) 1584 { 1585 DPRINT1("UhciGetErrorFromTD: USBD_STATUS_DATA_OVERRUN, TD - %p\n", TD); 1586 USBDStatus = USBD_STATUS_DATA_OVERRUN; 1587 } 1588 else if (TdStatus & UHCI_TD_STS_STALLED) 1589 { 1590 DPRINT1("UhciGetErrorFromTD: USBD_STATUS_STALL_PID, TD - %p\n", TD); 1591 USBDStatus = USBD_STATUS_STALL_PID; 1592 } 1593 else 1594 { 1595 DPRINT1("UhciGetErrorFromTD: USBD_STATUS_INTERNAL_HC_ERROR, TD - %p\n", TD); 1596 USBDStatus = USBD_STATUS_INTERNAL_HC_ERROR; 1597 } 1598 1599 return USBDStatus; 1600 } 1601 1602 VOID 1603 NTAPI 1604 UhciProcessDoneNonIsoTD(IN PUHCI_EXTENSION UhciExtension, 1605 IN PUHCI_HCD_TD TD) 1606 { 1607 PUSBPORT_TRANSFER_PARAMETERS TransferParameters; 1608 PUHCI_ENDPOINT UhciEndpoint; 1609 PUHCI_TRANSFER UhciTransfer; 1610 USBD_STATUS USBDStatus = USBD_STATUS_SUCCESS; 1611 SIZE_T TransferedLen; 1612 1613 DPRINT_UHCI("UhciProcessDoneNonIsoTD: TD - %p\n", TD); 1614 1615 UhciTransfer = TD->UhciTransfer; 1616 UhciTransfer->PendingTds--; 1617 1618 TransferParameters = UhciTransfer->TransferParameters; 1619 UhciEndpoint = UhciTransfer->UhciEndpoint; 1620 1621 if (!(TD->Flags & UHCI_HCD_TD_FLAG_NOT_ACCESSED)) 1622 { 1623 if (UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED) 1624 USBDStatus = UhciGetErrorFromTD(UhciExtension, TD); 1625 1626 if (USBDStatus != USBD_STATUS_SUCCESS || 1627 (TD->HwTD.ControlStatus.ActualLength == UHCI_TD_LENGTH_NULL)) 1628 { 1629 TransferedLen = 0; 1630 } 1631 else 1632 { 1633 TransferedLen = TD->HwTD.ControlStatus.ActualLength + 1; 1634 } 1635 1636 if (TD->HwTD.Token.PIDCode != UHCI_TD_PID_SETUP) 1637 UhciTransfer->TransferLen += TransferedLen; 1638 1639 if (TD->HwTD.Token.PIDCode == UHCI_TD_PID_IN && 1640 TD->Flags & UHCI_HCD_TD_FLAG_DATA_BUFFER) 1641 { 1642 DPRINT_IMPL("UhciProcessDoneNonIsoTD: UNIMPLEMENTED. FIXME\n"); 1643 } 1644 1645 if (USBDStatus != USBD_STATUS_SUCCESS) 1646 UhciTransfer->USBDStatus = USBDStatus; 1647 } 1648 1649 if (TD->Flags & UHCI_HCD_TD_FLAG_DATA_BUFFER) 1650 DPRINT_IMPL("UhciProcessDoneNonIsoTD: UNIMPLEMENTED. FIXME\n"); 1651 1652 UhciEndpoint->AllocatedTDs--; 1653 1654 TD->HwTD.NextElement = 0; 1655 TD->UhciTransfer = NULL; 1656 TD->Flags = 0; 1657 1658 if (UhciTransfer->PendingTds == 0) 1659 { 1660 InterlockedDecrement(&UhciEndpoint->EndpointLock); 1661 1662 if (UhciEndpoint->EndpointProperties.TransferType == 1663 USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 1664 { 1665 InterlockedDecrement(&UhciExtension->ExtensionLock); 1666 } 1667 1668 RegPacket.UsbPortCompleteTransfer(UhciExtension, 1669 UhciEndpoint, 1670 TransferParameters, 1671 UhciTransfer->USBDStatus, 1672 UhciTransfer->TransferLen); 1673 } 1674 } 1675 1676 MPSTATUS 1677 NTAPI 1678 UhciIsochTransfer(IN PVOID ehciExtension, 1679 IN PVOID ehciEndpoint, 1680 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, 1681 IN PVOID ehciTransfer, 1682 IN PVOID isoParameters) 1683 { 1684 DPRINT_IMPL("UhciIsochTransfer: UNIMPLEMENTED. FIXME\n"); 1685 return MP_STATUS_SUCCESS; 1686 } 1687 1688 VOID 1689 NTAPI 1690 UhciAbortIsoTransfer(IN PUHCI_EXTENSION UhciExtension, 1691 IN PUHCI_ENDPOINT UhciEndpoint, 1692 IN PUHCI_TRANSFER UhciTransfer) 1693 { 1694 DPRINT_IMPL("UhciAbortIsoTransfer: UNIMPLEMENTED. FIXME\n"); 1695 } 1696 1697 VOID 1698 NTAPI 1699 UhciAbortNonIsoTransfer(IN PUHCI_EXTENSION UhciExtension, 1700 IN PUHCI_ENDPOINT UhciEndpoint, 1701 IN PUHCI_TRANSFER UhciTransfer, 1702 IN PULONG CompletedLength) 1703 { 1704 PUHCI_HCD_TD TD; 1705 PUHCI_HCD_TD PrevTD = NULL; 1706 ULONG PhysicalAddress; 1707 BOOL DataToggle; 1708 BOOLEAN IsHeadTD = FALSE; 1709 1710 DPRINT("UhciAbortNonIsoTransfer: UhciExtension - %p, QH - %p, UhciTransfer - %p\n", 1711 UhciExtension, 1712 UhciEndpoint->QH, 1713 UhciTransfer); 1714 1715 for (TD = UhciEndpoint->HeadTD; 1716 TD && TD->UhciTransfer != UhciTransfer; 1717 TD = TD->NextHcdTD) 1718 { 1719 PrevTD = TD; 1720 } 1721 1722 DataToggle = TD->HwTD.Token.DataToggle; 1723 1724 if (TD == UhciEndpoint->HeadTD) 1725 IsHeadTD = TRUE; 1726 1727 while (TD && TD->UhciTransfer == UhciTransfer) 1728 { 1729 DPRINT_UHCI("UhciAbortNonIsoTransfer: TD - %p\n", TD); 1730 1731 if (TD->HwTD.ControlStatus.Status & UHCI_TD_STS_ACTIVE) 1732 { 1733 if (TD->Flags & UHCI_HCD_TD_FLAG_DATA_BUFFER) 1734 DPRINT_IMPL("UhciAbortNonIsoTransfer: UNIMPLEMENTED. FIXME\n"); 1735 1736 UhciEndpoint->AllocatedTDs--; 1737 1738 DPRINT_UHCI("UhciAbortNonIsoTransfer: Active TD - %p\n", TD); 1739 1740 TD->HwTD.NextElement = 0; 1741 TD->Flags = 0; 1742 TD->UhciTransfer = NULL; 1743 } 1744 else 1745 { 1746 UhciProcessDoneNonIsoTD(UhciExtension, TD); 1747 } 1748 1749 TD = TD->NextHcdTD; 1750 } 1751 1752 UhciFixDataToggle(UhciExtension, 1753 UhciEndpoint, 1754 TD, 1755 DataToggle); 1756 1757 if (IsHeadTD) 1758 { 1759 if (TD) 1760 { 1761 UhciEndpoint->HeadTD = TD; 1762 } 1763 else 1764 { 1765 UhciEndpoint->HeadTD = NULL; 1766 UhciEndpoint->TailTD = NULL; 1767 } 1768 1769 if (TD == NULL || UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED) 1770 { 1771 PhysicalAddress = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE; 1772 } 1773 else 1774 { 1775 PhysicalAddress = TD->PhysicalAddress; 1776 PhysicalAddress &= ~UHCI_QH_ELEMENT_LINK_PTR_TERMINATE; 1777 } 1778 1779 DPRINT_UHCI("UhciAbortNonIsoTransfer: TD - %p\n", TD); 1780 1781 UhciEndpoint->QH->HwQH.NextElement = PhysicalAddress; 1782 UhciEndpoint->QH->HwQH.NextElement &= ~UHCI_QH_ELEMENT_LINK_PTR_QH; 1783 } 1784 else if (TD) 1785 { 1786 PrevTD->HwTD.NextElement = TD->PhysicalAddress & UHCI_TD_LINK_POINTER_MASK; 1787 PrevTD->NextHcdTD = TD; 1788 } 1789 else 1790 { 1791 PrevTD->NextHcdTD = NULL; 1792 PrevTD->HwTD.NextElement = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE; 1793 1794 UhciEndpoint->TailTD = PrevTD; 1795 } 1796 1797 *CompletedLength = UhciTransfer->TransferLen; 1798 } 1799 1800 VOID 1801 NTAPI 1802 UhciAbortTransfer(IN PVOID uhciExtension, 1803 IN PVOID uhciEndpoint, 1804 IN PVOID uhciTransfer, 1805 IN PULONG CompletedLength) 1806 { 1807 PUHCI_EXTENSION UhciExtension = uhciExtension; 1808 PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint; 1809 PUHCI_TRANSFER UhciTransfer = uhciTransfer; 1810 ULONG TransferType; 1811 1812 DPRINT("UhciAbortTransfer: ...\n"); 1813 1814 InterlockedDecrement(&UhciEndpoint->EndpointLock); 1815 1816 TransferType = UhciEndpoint->EndpointProperties.TransferType; 1817 1818 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 1819 { 1820 InterlockedDecrement(&UhciExtension->ExtensionLock); 1821 1822 UhciAbortIsoTransfer(UhciExtension, 1823 UhciEndpoint, 1824 UhciTransfer); 1825 } 1826 1827 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL || 1828 TransferType == USBPORT_TRANSFER_TYPE_BULK || 1829 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 1830 { 1831 UhciAbortNonIsoTransfer(UhciExtension, 1832 UhciEndpoint, 1833 UhciTransfer, 1834 CompletedLength); 1835 } 1836 } 1837 1838 ULONG 1839 NTAPI 1840 UhciGetEndpointState(IN PVOID uhciExtension, 1841 IN PVOID uhciEndpoint) 1842 { 1843 DPRINT_IMPL("UhciGetEndpointState: UNIMPLEMENTED. FIXME\n"); 1844 return 0; 1845 } 1846 1847 VOID 1848 NTAPI 1849 UhciInsertQH(IN PUHCI_EXTENSION UhciExtension, 1850 IN PUHCI_HCD_QH StaticQH, 1851 IN PUHCI_HCD_QH QH) 1852 { 1853 PUHCI_HCD_QH NextHcdQH; 1854 1855 DPRINT("UhciInsertQH: UhciExtension - %p, StaticQH - %p, QH - %p\n", UhciExtension, StaticQH, QH); 1856 1857 QH->HwQH.NextQH = StaticQH->HwQH.NextQH; 1858 NextHcdQH = StaticQH->NextHcdQH; 1859 1860 QH->PrevHcdQH = StaticQH; 1861 QH->NextHcdQH = NextHcdQH; 1862 1863 if (NextHcdQH) 1864 NextHcdQH->PrevHcdQH = QH; 1865 else 1866 UhciExtension->BulkTailQH = QH; 1867 1868 StaticQH->HwQH.NextQH = QH->PhysicalAddress | UHCI_QH_HEAD_LINK_PTR_QH; 1869 StaticQH->NextHcdQH = QH; 1870 1871 QH->QhFlags |= UHCI_HCD_QH_FLAG_ACTIVE; 1872 } 1873 1874 VOID 1875 NTAPI 1876 UhciUnlinkQH(IN PUHCI_EXTENSION UhciExtension, 1877 IN PUHCI_HCD_QH QH) 1878 { 1879 PUHCI_HCD_QH NextHcdQH; 1880 PUHCI_HCD_QH PrevHcdQH; 1881 PUHCI_HCD_QH BulkQH; 1882 1883 DPRINT("UhciUnlinkQH: ... \n"); 1884 1885 NextHcdQH = QH->NextHcdQH; 1886 PrevHcdQH = QH->PrevHcdQH; 1887 1888 if (UhciExtension->BulkTailQH == QH) 1889 UhciExtension->BulkTailQH = PrevHcdQH; 1890 1891 PrevHcdQH->HwQH.NextQH = QH->HwQH.NextQH; 1892 PrevHcdQH->NextHcdQH = NextHcdQH; 1893 1894 if (NextHcdQH) 1895 NextHcdQH->PrevHcdQH = PrevHcdQH; 1896 1897 QH->PrevHcdQH = QH; 1898 QH->NextHcdQH = QH; 1899 1900 if (!(QH->UhciEndpoint->EndpointProperties.TransferType == 1901 USBPORT_TRANSFER_TYPE_BULK)) 1902 { 1903 QH->QhFlags &= ~UHCI_HCD_QH_FLAG_ACTIVE; 1904 return; 1905 } 1906 1907 if ((UhciExtension->BulkTailQH->HwQH.NextQH & UHCI_QH_HEAD_LINK_PTR_TERMINATE) 1908 == UHCI_QH_HEAD_LINK_PTR_TERMINATE) 1909 { 1910 QH->QhFlags &= ~UHCI_HCD_QH_FLAG_ACTIVE; 1911 return; 1912 } 1913 1914 BulkQH = UhciExtension->BulkQH; 1915 1916 while (TRUE) 1917 { 1918 BulkQH = BulkQH->NextHcdQH; 1919 1920 if (!BulkQH) 1921 break; 1922 1923 if (!(BulkQH->HwQH.NextElement & UHCI_QH_ELEMENT_LINK_PTR_TERMINATE)) 1924 { 1925 QH->QhFlags &= ~UHCI_HCD_QH_FLAG_ACTIVE; 1926 return; 1927 } 1928 } 1929 1930 UhciExtension->BulkTailQH->HwQH.NextQH |= UHCI_QH_HEAD_LINK_PTR_TERMINATE; 1931 1932 QH->QhFlags &= ~UHCI_HCD_QH_FLAG_ACTIVE; 1933 } 1934 1935 VOID 1936 NTAPI 1937 UhciSetEndpointState(IN PVOID uhciExtension, 1938 IN PVOID uhciEndpoint, 1939 IN ULONG EndpointState) 1940 { 1941 PUHCI_EXTENSION UhciExtension = uhciExtension; 1942 PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint; 1943 ULONG TransferType; 1944 PUHCI_HCD_QH QH; 1945 ULONG Idx; 1946 1947 TransferType = UhciEndpoint->EndpointProperties.TransferType; 1948 QH = UhciEndpoint->QH; 1949 1950 DPRINT("UhciSetEndpointState: EndpointState - %x, TransferType - %x\n", 1951 EndpointState, 1952 TransferType); 1953 1954 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 1955 return; 1956 1957 if (TransferType != USBPORT_TRANSFER_TYPE_CONTROL && 1958 TransferType != USBPORT_TRANSFER_TYPE_BULK && 1959 TransferType != USBPORT_TRANSFER_TYPE_INTERRUPT) 1960 { 1961 DPRINT("UhciSetEndpointState: Unknown TransferType - %x\n", 1962 TransferType); 1963 } 1964 1965 switch (EndpointState) 1966 { 1967 case USBPORT_ENDPOINT_PAUSED: 1968 UhciUnlinkQH(UhciExtension, QH); 1969 return; 1970 1971 case USBPORT_ENDPOINT_ACTIVE: 1972 switch (TransferType) 1973 { 1974 case USBPORT_TRANSFER_TYPE_CONTROL: 1975 UhciInsertQH(UhciExtension, 1976 UhciExtension->ControlQH, 1977 UhciEndpoint->QH); 1978 break; 1979 1980 case USBPORT_TRANSFER_TYPE_BULK: 1981 UhciInsertQH(UhciExtension, 1982 UhciExtension->BulkQH, 1983 UhciEndpoint->QH); 1984 break; 1985 1986 case USBPORT_TRANSFER_TYPE_INTERRUPT: 1987 Idx = UhciEndpoint->EndpointProperties.Period + 1988 UhciEndpoint->EndpointProperties.ScheduleOffset; 1989 1990 UhciInsertQH(UhciExtension, 1991 UhciExtension->IntQH[Idx - 1], 1992 UhciEndpoint->QH); 1993 break; 1994 default: 1995 ASSERT(FALSE); 1996 break; 1997 } 1998 1999 break; 2000 2001 case USBPORT_ENDPOINT_REMOVE: 2002 QH->QhFlags |= UHCI_HCD_QH_FLAG_REMOVE; 2003 UhciUnlinkQH(UhciExtension, QH); 2004 break; 2005 2006 default: 2007 ASSERT(FALSE); 2008 break; 2009 } 2010 } 2011 2012 ULONG 2013 NTAPI 2014 UhciGetEndpointStatus(IN PVOID uhciExtension, 2015 IN PVOID uhciEndpoint) 2016 { 2017 PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint; 2018 ULONG EndpointStatus; 2019 2020 DPRINT_UHCI("UhciGetEndpointStatus: ...\n"); 2021 2022 if (UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED) 2023 EndpointStatus = USBPORT_ENDPOINT_HALT; 2024 else 2025 EndpointStatus = USBPORT_ENDPOINT_RUN; 2026 2027 return EndpointStatus; 2028 } 2029 2030 VOID 2031 NTAPI 2032 UhciSetEndpointStatus(IN PVOID uhciExtension, 2033 IN PVOID uhciEndpoint, 2034 IN ULONG EndpointStatus) 2035 { 2036 PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint; 2037 ULONG PhysicalAddress; 2038 2039 DPRINT("UhciSetEndpointStatus: uhciEndpoint - %p, EndpointStatus - %X\n", 2040 uhciEndpoint, 2041 EndpointStatus); 2042 2043 if (EndpointStatus != USBPORT_ENDPOINT_RUN) 2044 return; 2045 2046 if (!(UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED)) 2047 return; 2048 2049 UhciEndpoint->Flags &= ~UHCI_ENDPOINT_FLAG_HALTED; 2050 2051 if (UhciEndpoint->HeadTD == NULL) 2052 UhciEndpoint->TailTD = NULL; 2053 2054 if (UhciEndpoint->HeadTD) 2055 { 2056 PhysicalAddress = UhciEndpoint->HeadTD->PhysicalAddress; 2057 PhysicalAddress &= ~UHCI_TD_LINK_PTR_TERMINATE; 2058 UhciEndpoint->QH->HwQH.NextElement = PhysicalAddress; 2059 UhciEndpoint->QH->HwQH.NextElement &= ~UHCI_QH_ELEMENT_LINK_PTR_QH; 2060 } 2061 else 2062 { 2063 UhciEndpoint->QH->HwQH.NextElement = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE; 2064 } 2065 } 2066 2067 VOID 2068 NTAPI 2069 UhciPollIsoEndpoint(IN PUHCI_EXTENSION UhciExtension, 2070 IN PUHCI_ENDPOINT UhciEndpoint) 2071 { 2072 DPRINT_IMPL("UhciPollIsoEndpoint: UNIMPLEMENTED. FIXME\n"); 2073 } 2074 2075 VOID 2076 NTAPI 2077 UhciPollNonIsoEndpoint(IN PUHCI_EXTENSION UhciExtension, 2078 IN PUHCI_ENDPOINT UhciEndpoint) 2079 { 2080 PUHCI_HCD_QH QH; 2081 PUHCI_HCD_TD NextTD; 2082 PUHCI_HCD_TD TD; 2083 ULONG NextTdPA; 2084 ULONG PhysicalAddress; 2085 SIZE_T TransferedLen; 2086 PLIST_ENTRY ListTDs; 2087 UCHAR TdStatus; 2088 2089 DPRINT_UHCI("UhciPollNonIsoEndpoint: UhciExtension - %p, UhciEndpoint - %p\n", 2090 UhciExtension, 2091 UhciEndpoint); 2092 2093 if (UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED) 2094 { 2095 DPRINT("UhciPollNonIsoEndpoint: Ep->Flags & UHCI_ENDPOINT_FLAG_HALTED \n"); 2096 return; 2097 } 2098 2099 QH = UhciEndpoint->QH; 2100 2101 NextTdPA = QH->HwQH.NextElement & UHCI_QH_ELEMENT_LINK_POINTER_MASK; 2102 2103 if (NextTdPA) 2104 { 2105 NextTD = RegPacket.UsbPortGetMappedVirtualAddress(NextTdPA, 2106 UhciExtension, 2107 UhciEndpoint); 2108 } 2109 else 2110 { 2111 NextTD = NULL; 2112 } 2113 2114 DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD - %p, NextTdPA - %p\n", 2115 NextTD, 2116 NextTdPA); 2117 2118 for (TD = UhciEndpoint->HeadTD; TD != NextTD && TD != NULL; TD = TD->NextHcdTD) 2119 { 2120 DPRINT_UHCI("UhciPollNonIsoEndpoint: TD - %p, TD->NextHcdTD - %p\n", 2121 TD, 2122 TD->NextHcdTD); 2123 2124 TD->Flags |= UHCI_HCD_TD_FLAG_DONE; 2125 InsertTailList(&UhciEndpoint->ListTDs, &TD->TdLink); 2126 2127 if (TD->NextHcdTD && 2128 TD->NextHcdTD->HwTD.ControlStatus.Status & UHCI_TD_STS_ACTIVE) 2129 { 2130 if (NextTdPA == 0) 2131 { 2132 TD = TD->NextHcdTD; 2133 goto EnqueueTD; 2134 } 2135 2136 if (NextTdPA != TD->NextHcdTD->PhysicalAddress) 2137 { 2138 DPRINT("UhciPollNonIsoEndpoint: TD->NextHcdTD->PhysicalAddress - %p\n", 2139 TD->NextHcdTD->PhysicalAddress); 2140 ASSERT(FALSE); 2141 } 2142 } 2143 else 2144 { 2145 if (TD->NextHcdTD == NULL) 2146 { 2147 DPRINT_UHCI("UhciPollNonIsoEndpoint: TD->NextHcdTD == NULL\n"); 2148 } 2149 else 2150 { 2151 DPRINT_UHCI("UhciPollNonIsoEndpoint: ControlStatus - %X\n", 2152 TD->NextHcdTD->HwTD.ControlStatus.AsULONG); 2153 } 2154 } 2155 } 2156 2157 UhciEndpoint->HeadTD = NextTD; 2158 2159 if (NextTD == NULL) 2160 { 2161 DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD == NULL\n"); 2162 2163 UhciEndpoint->HeadTD = NULL; 2164 UhciEndpoint->TailTD = NULL; 2165 2166 QH->HwQH.NextElement = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE; 2167 2168 goto ProcessListTDs; 2169 } 2170 2171 DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD - %p, NextTdPA - %p\n", 2172 NextTD, 2173 NextTdPA); 2174 2175 TdStatus = NextTD->HwTD.ControlStatus.Status; 2176 2177 if (TdStatus & UHCI_TD_STS_ACTIVE) 2178 { 2179 DPRINT_UHCI("UhciPollNonIsoEndpoint: UHCI_TD_STS_ACTIVE \n"); 2180 goto ProcessListTDs; 2181 } 2182 2183 if (NextTD->HwTD.Token.PIDCode == UHCI_TD_PID_IN && 2184 TdStatus & UHCI_TD_STS_STALLED && 2185 TdStatus & UHCI_TD_STS_TIMEOUT_CRC_ERROR && 2186 !(TdStatus & UHCI_TD_STS_NAK_RECEIVED) && 2187 !(TdStatus & UHCI_TD_STS_BABBLE_DETECTED) && 2188 !(TdStatus & UHCI_TD_STS_BITSTUFF_ERROR)) 2189 { 2190 DPRINT("UhciPollNonIsoEndpoint: USBD_STATUS_DEV_NOT_RESPONDING\n"); 2191 2192 UhciDumpHcdTD(NextTD); 2193 2194 if (!(NextTD->Flags & UHCI_HCD_TD_FLAG_STALLED_SETUP)) 2195 { 2196 NextTD->HwTD.ControlStatus.ErrorCounter = 3; 2197 2198 NextTD->HwTD.ControlStatus.Status &= ~(UHCI_TD_STS_STALLED | 2199 UHCI_TD_STS_TIMEOUT_CRC_ERROR); 2200 2201 NextTD->HwTD.ControlStatus.Status |= UHCI_TD_STS_ACTIVE; 2202 2203 NextTD->Flags = NextTD->Flags | UHCI_HCD_TD_FLAG_STALLED_SETUP; 2204 2205 goto ProcessListTDs; 2206 } 2207 } 2208 2209 if (TdStatus & (UHCI_TD_STS_STALLED | 2210 UHCI_TD_STS_DATA_BUFFER_ERROR | 2211 UHCI_TD_STS_BABBLE_DETECTED | 2212 UHCI_TD_STS_TIMEOUT_CRC_ERROR | 2213 UHCI_TD_STS_BITSTUFF_ERROR)) 2214 { 2215 DPRINT("UhciPollNonIsoEndpoint: NextTD UHCI_TD_STS_ - %02X, PIDCode - %02X\n", 2216 NextTD->HwTD.ControlStatus.Status, 2217 NextTD->HwTD.Token.PIDCode); 2218 2219 UhciDumpHcdTD(NextTD); 2220 2221 UhciEndpoint->Flags |= UHCI_ENDPOINT_FLAG_HALTED; 2222 NextTD->Flags |= UHCI_HCD_TD_FLAG_DONE; 2223 2224 InsertTailList(&UhciEndpoint->ListTDs, &NextTD->TdLink); 2225 2226 if (TD->UhciTransfer != NextTD->UhciTransfer) 2227 ASSERT(TD->UhciTransfer == NextTD->UhciTransfer); 2228 2229 while (TD && 2230 TD->UhciTransfer->TransferParameters->TransferCounter == 2231 NextTD->UhciTransfer->TransferParameters->TransferCounter) 2232 { 2233 DPRINT("UhciPollNonIsoEndpoint: Bad TD - %p\n", TD); 2234 2235 if (!(TD->Flags & UHCI_HCD_TD_FLAG_DONE)) 2236 { 2237 TD->Flags |= UHCI_HCD_TD_FLAG_DONE; 2238 TD->Flags |= UHCI_HCD_TD_FLAG_NOT_ACCESSED; 2239 2240 InsertTailList(&UhciEndpoint->ListTDs, &TD->TdLink); 2241 } 2242 2243 TD = TD->NextHcdTD; 2244 } 2245 2246 if (UhciEndpoint->EndpointProperties.TransferType != 2247 USBPORT_TRANSFER_TYPE_CONTROL) 2248 { 2249 UhciFixDataToggle(UhciExtension, 2250 UhciEndpoint, 2251 TD, 2252 NextTD->HwTD.Token.DataToggle); 2253 } 2254 } 2255 else 2256 { 2257 TransferedLen = NextTD->HwTD.ControlStatus.ActualLength; 2258 2259 if (TransferedLen == UHCI_TD_LENGTH_NULL) 2260 TransferedLen = 0; 2261 else 2262 TransferedLen += 1; 2263 2264 if (NextTD->HwTD.Token.MaximumLength == UHCI_TD_LENGTH_NULL || 2265 TransferedLen >= (NextTD->HwTD.Token.MaximumLength + 1)) 2266 { 2267 DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD - %p, TransferedLen - %X\n", 2268 NextTD, 2269 TransferedLen); 2270 2271 if (NextTdPA == 2272 (QH->HwQH.NextElement & UHCI_QH_ELEMENT_LINK_POINTER_MASK)) 2273 { 2274 NextTD->Flags |= UHCI_HCD_TD_FLAG_DONE; 2275 InsertTailList(&UhciEndpoint->ListTDs, &NextTD->TdLink); 2276 2277 UhciEndpoint->HeadTD = NextTD->NextHcdTD; 2278 2279 QH->HwQH.NextElement = NextTD->HwTD.NextElement; 2280 QH->HwQH.NextElement |= UHCI_QH_ELEMENT_LINK_PTR_TD; 2281 2282 DPRINT_UHCI("UhciPollNonIsoEndpoint: NextTD - %p, TD - %p\n", 2283 NextTD, 2284 TD); 2285 } 2286 2287 goto ProcessListTDs; 2288 } 2289 2290 DPRINT_UHCI("UhciPollNonIsoEndpoint: ShortPacket. ControlStatus - %X\n", 2291 NextTD->HwTD.ControlStatus.AsULONG); 2292 2293 NextTD->Flags |= UHCI_HCD_TD_FLAG_DONE; 2294 InsertTailList(&UhciEndpoint->ListTDs, &NextTD->TdLink); 2295 2296 while (TD && 2297 TD->UhciTransfer->TransferParameters->TransferCounter == 2298 NextTD->UhciTransfer->TransferParameters->TransferCounter) 2299 { 2300 if (TD->Flags & UHCI_HCD_TD_FLAG_CONTROLL && 2301 NextTD->UhciTransfer->TransferParameters->TransferFlags & 2302 USBD_SHORT_TRANSFER_OK) 2303 { 2304 break; 2305 } 2306 2307 if (!(TD->Flags & UHCI_HCD_TD_FLAG_DONE)) 2308 { 2309 DPRINT_UHCI("UhciPollNonIsoEndpoint: TD - %p\n", TD); 2310 2311 TD->Flags |= (UHCI_HCD_TD_FLAG_DONE | 2312 UHCI_HCD_TD_FLAG_NOT_ACCESSED); 2313 2314 InsertTailList(&UhciEndpoint->ListTDs, &TD->TdLink); 2315 } 2316 2317 TD = TD->NextHcdTD; 2318 } 2319 2320 if (NextTD->NextHcdTD && 2321 (UhciEndpoint->EndpointProperties.TransferType != 2322 USBPORT_TRANSFER_TYPE_CONTROL)) 2323 { 2324 UhciFixDataToggle(UhciExtension, 2325 UhciEndpoint, 2326 TD, 2327 NextTD->NextHcdTD->HwTD.Token.DataToggle); 2328 } 2329 2330 if (!(NextTD->UhciTransfer->TransferParameters->TransferFlags & 2331 USBD_SHORT_TRANSFER_OK)) 2332 { 2333 UhciEndpoint->Flags |= UHCI_ENDPOINT_FLAG_HALTED; 2334 } 2335 } 2336 2337 EnqueueTD: 2338 2339 if (TD) 2340 { 2341 UhciEndpoint->HeadTD = TD; 2342 } 2343 else 2344 { 2345 UhciEndpoint->HeadTD = NULL; 2346 UhciEndpoint->TailTD = NULL; 2347 } 2348 2349 if (TD == NULL || UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED) 2350 { 2351 PhysicalAddress = UHCI_QH_ELEMENT_LINK_PTR_TERMINATE; 2352 } 2353 else 2354 { 2355 PhysicalAddress = TD->PhysicalAddress; 2356 PhysicalAddress &= ~UHCI_QH_ELEMENT_LINK_PTR_TERMINATE; 2357 } 2358 2359 DPRINT_UHCI("UhciPollNonIsoEndpoint: TD - %p\n", TD); 2360 2361 QH->HwQH.NextElement = PhysicalAddress; 2362 QH->HwQH.NextElement &= ~UHCI_QH_ELEMENT_LINK_PTR_QH; 2363 2364 ProcessListTDs: 2365 2366 ListTDs = &UhciEndpoint->ListTDs; 2367 2368 while (!IsListEmpty(ListTDs)) 2369 { 2370 TD = CONTAINING_RECORD(ListTDs->Flink, 2371 UHCI_HCD_TD, 2372 TdLink.Flink); 2373 2374 RemoveHeadList(ListTDs); 2375 2376 if ((TD->Flags & (UHCI_HCD_TD_FLAG_PROCESSED | UHCI_HCD_TD_FLAG_DONE)) == 2377 (UHCI_HCD_TD_FLAG_PROCESSED | UHCI_HCD_TD_FLAG_DONE)) 2378 { 2379 UhciProcessDoneNonIsoTD(UhciExtension, TD); 2380 } 2381 } 2382 2383 if (UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_CONTROL_OR_ISO && 2384 UhciEndpoint->Flags & UHCI_ENDPOINT_FLAG_HALTED) 2385 { 2386 DPRINT_UHCI("UhciPollNonIsoEndpoint: Halted periodic EP - %p\n", 2387 UhciEndpoint); 2388 2389 UhciSetEndpointStatus(UhciExtension, 2390 UhciEndpoint, 2391 USBPORT_ENDPOINT_RUN); 2392 } 2393 } 2394 2395 VOID 2396 NTAPI 2397 UhciPollEndpoint(IN PVOID uhciExtension, 2398 IN PVOID uhciEndpoint) 2399 { 2400 PUHCI_EXTENSION UhciExtension = uhciExtension; 2401 PUHCI_ENDPOINT UhciEndpoint = uhciEndpoint; 2402 ULONG TransferType; 2403 2404 DPRINT_UHCI("UhciPollEndpoint: ...\n"); 2405 2406 TransferType = UhciEndpoint->EndpointProperties.TransferType; 2407 2408 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 2409 { 2410 UhciPollIsoEndpoint(UhciExtension, UhciEndpoint); 2411 return; 2412 } 2413 2414 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL || 2415 TransferType == USBPORT_TRANSFER_TYPE_BULK || 2416 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 2417 { 2418 UhciPollNonIsoEndpoint(UhciExtension, UhciEndpoint); 2419 } 2420 } 2421 2422 VOID 2423 NTAPI 2424 UhciCheckController(IN PVOID uhciExtension) 2425 { 2426 PUHCI_EXTENSION UhciExtension = uhciExtension; 2427 2428 if (!UhciHardwarePresent(UhciExtension) || 2429 UhciExtension->HcScheduleError >= UHCI_MAX_HC_SCHEDULE_ERRORS) 2430 { 2431 DPRINT1("UhciCheckController: INVALIDATE_CONTROLLER_SURPRISE_REMOVE !!!\n"); 2432 2433 RegPacket.UsbPortInvalidateController(UhciExtension, 2434 USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE); 2435 } 2436 } 2437 2438 ULONG 2439 NTAPI 2440 UhciGet32BitFrameNumber(IN PVOID uhciExtension) 2441 { 2442 PUHCI_EXTENSION UhciExtension = uhciExtension; 2443 ULONG Uhci32BitFrame; 2444 USHORT Fn; // FrameNumber 2445 ULONG Hp; // FrameHighPart 2446 2447 Fn = READ_PORT_USHORT(&UhciExtension->BaseRegister->FrameNumber); 2448 Fn &= UHCI_FRNUM_FRAME_MASK; 2449 Hp = UhciExtension->FrameHighPart; 2450 2451 Uhci32BitFrame = Hp; 2452 Uhci32BitFrame += ((USHORT)Hp ^ Fn) & UHCI_FRNUM_OVERFLOW_LIST; 2453 Uhci32BitFrame |= Fn; 2454 2455 DPRINT_UHCI("UhciGet32BitFrameNumber: Uhci32BitFrame - %lX\n", 2456 Uhci32BitFrame); 2457 2458 return Uhci32BitFrame; 2459 } 2460 2461 VOID 2462 NTAPI 2463 UhciInterruptNextSOF(IN PVOID uhciExtension) 2464 { 2465 PUHCI_EXTENSION UhciExtension = uhciExtension; 2466 PUHCI_HC_RESOURCES UhciResources; 2467 ULONG CurrentFrame; 2468 PUHCI_HCD_TD SOF_HcdTDs; 2469 ULONG ix; 2470 ULONG NextFrame; 2471 ULONG SofFrame; 2472 ULONG Idx; 2473 2474 DPRINT_UHCI("UhciInterruptNextSOF: ...\n"); 2475 2476 CurrentFrame = UhciGet32BitFrameNumber(UhciExtension); 2477 2478 SOF_HcdTDs = UhciExtension->SOF_HcdTDs; 2479 NextFrame = CurrentFrame + 2; 2480 2481 for (ix = 0; ix < UHCI_MAX_STATIC_SOF_TDS; ++ix) 2482 { 2483 SofFrame = SOF_HcdTDs->Frame; 2484 2485 if (SofFrame == NextFrame) 2486 break; 2487 2488 if (SofFrame < CurrentFrame) 2489 { 2490 SOF_HcdTDs->Frame = NextFrame; 2491 SOF_HcdTDs->Flags |= UHCI_HCD_TD_FLAG_GOOD_FRAME; 2492 2493 /* Insert SOF_HcdTD (InterruptOnComplete = TRUE) in Frame List */ 2494 UhciResources = UhciExtension->HcResourcesVA; 2495 Idx = SOF_HcdTDs->Frame & UHCI_FRAME_LIST_INDEX_MASK; 2496 2497 InterlockedExchange((PLONG)&SOF_HcdTDs->HwTD.NextElement, 2498 UhciResources->FrameList[Idx]); 2499 2500 UhciResources->FrameList[Idx] = SOF_HcdTDs->PhysicalAddress; 2501 break; 2502 } 2503 2504 /* Go to next SOF_HcdTD */ 2505 SOF_HcdTDs += 1; 2506 } 2507 2508 for (ix = 0; ix < UHCI_MAX_STATIC_SOF_TDS; ++ix) 2509 { 2510 SOF_HcdTDs = &UhciExtension->SOF_HcdTDs[ix]; 2511 2512 if (SOF_HcdTDs->Frame && 2513 (SOF_HcdTDs->Frame < CurrentFrame || 2514 (SOF_HcdTDs->Frame - CurrentFrame) > UHCI_FRAME_LIST_MAX_ENTRIES)) 2515 { 2516 SOF_HcdTDs->Frame = 0; 2517 } 2518 } 2519 } 2520 2521 VOID 2522 NTAPI 2523 UhciEnableInterrupts(IN PVOID uhciExtension) 2524 { 2525 PUHCI_EXTENSION UhciExtension = uhciExtension; 2526 PUHCI_HW_REGISTERS BaseRegister; 2527 UHCI_PCI_LEGSUP LegacySupport; 2528 2529 DPRINT("UhciEnableInterrupts: UhciExtension - %p\n", UhciExtension); 2530 2531 BaseRegister = UhciExtension->BaseRegister; 2532 2533 RegPacket.UsbPortReadWriteConfigSpace(UhciExtension, 2534 TRUE, 2535 &LegacySupport.AsUSHORT, 2536 PCI_LEGSUP, 2537 sizeof(USHORT)); 2538 2539 LegacySupport.UsbPIRQ = 1; 2540 2541 RegPacket.UsbPortReadWriteConfigSpace(UhciExtension, 2542 FALSE, 2543 &LegacySupport.AsUSHORT, 2544 PCI_LEGSUP, 2545 sizeof(USHORT)); 2546 2547 WRITE_PORT_USHORT(&BaseRegister->HcInterruptEnable.AsUSHORT, 2548 UhciExtension->StatusMask.AsUSHORT); 2549 } 2550 2551 VOID 2552 NTAPI 2553 UhciDisableInterrupts(IN PVOID uhciExtension) 2554 { 2555 PUHCI_EXTENSION UhciExtension = uhciExtension; 2556 PUHCI_HW_REGISTERS BaseRegister; 2557 USB_CONTROLLER_FLAVOR HcFlavor; 2558 UHCI_PCI_LEGSUP LegacySupport; 2559 2560 DPRINT("UhciDisableInterrupts: UhciExtension - %p\n", UhciExtension); 2561 2562 BaseRegister = UhciExtension->BaseRegister; 2563 WRITE_PORT_USHORT(&BaseRegister->HcInterruptEnable.AsUSHORT, 0); 2564 2565 HcFlavor = UhciExtension->HcFlavor; 2566 DPRINT("UhciDisableInterrupts: FIXME HcFlavor - %lx\n", HcFlavor); 2567 2568 RegPacket.UsbPortReadWriteConfigSpace(UhciExtension, 2569 TRUE, 2570 &LegacySupport.AsUSHORT, 2571 PCI_LEGSUP, 2572 sizeof(USHORT)); 2573 2574 LegacySupport.UsbPIRQ = 0; 2575 2576 RegPacket.UsbPortReadWriteConfigSpace(UhciExtension, 2577 FALSE, 2578 &LegacySupport.AsUSHORT, 2579 PCI_LEGSUP, 2580 sizeof(USHORT)); 2581 } 2582 2583 VOID 2584 NTAPI 2585 UhciPollController(IN PVOID uhciExtension) 2586 { 2587 PUHCI_EXTENSION UhciExtension = uhciExtension; 2588 PUHCI_HW_REGISTERS BaseRegister; 2589 PUSHORT PortRegister; 2590 UHCI_PORT_STATUS_CONTROL PortControl; 2591 USHORT Port; 2592 2593 DPRINT_UHCI("UhciPollController: UhciExtension - %p\n", UhciExtension); 2594 2595 BaseRegister = UhciExtension->BaseRegister; 2596 2597 if (!(UhciExtension->Flags & UHCI_EXTENSION_FLAG_SUSPENDED)) 2598 { 2599 UhciCleanupFrameList(UhciExtension, FALSE); 2600 UhciUpdateCounter(UhciExtension); 2601 RegPacket.UsbPortInvalidateRootHub(UhciExtension); 2602 return; 2603 } 2604 2605 for (Port = 0; Port < UHCI_NUM_ROOT_HUB_PORTS; Port++) 2606 { 2607 PortRegister = (PUSHORT)&BaseRegister->PortControl[Port]; 2608 PortControl.AsUSHORT = READ_PORT_USHORT(PortRegister); 2609 2610 if (PortControl.ConnectStatusChange == 1) 2611 RegPacket.UsbPortInvalidateRootHub(UhciExtension); 2612 } 2613 } 2614 2615 VOID 2616 NTAPI 2617 UhciSetEndpointDataToggle(IN PVOID uhciExtension, 2618 IN PVOID uhciEndpoint, 2619 IN ULONG DataToggle) 2620 { 2621 DPRINT_IMPL("UhciSetEndpointDataToggle: UNIMPLEMENTED. FIXME\n"); 2622 } 2623 2624 VOID 2625 NTAPI 2626 UhciResetController(IN PVOID uhciExtension) 2627 { 2628 DPRINT_IMPL("UhciResetController: UNIMPLEMENTED. FIXME\n"); 2629 } 2630 2631 MPSTATUS 2632 NTAPI 2633 UhciStartSendOnePacket(IN PVOID uhciExtension, 2634 IN PVOID PacketParameters, 2635 IN PVOID Data, 2636 IN PULONG pDataLength, 2637 IN PVOID BufferVA, 2638 IN PVOID BufferPA, 2639 IN ULONG BufferLength, 2640 IN USBD_STATUS * pUSBDStatus) 2641 { 2642 DPRINT_IMPL("UhciStartSendOnePacket: UNIMPLEMENTED. FIXME\n"); 2643 return MP_STATUS_SUCCESS; 2644 } 2645 2646 MPSTATUS 2647 NTAPI 2648 UhciEndSendOnePacket(IN PVOID uhciExtension, 2649 IN PVOID PacketParameters, 2650 IN PVOID Data, 2651 IN PULONG pDataLength, 2652 IN PVOID BufferVA, 2653 IN PVOID BufferPA, 2654 IN ULONG BufferLength, 2655 IN USBD_STATUS * pUSBDStatus) 2656 { 2657 DPRINT_IMPL("UhciEndSendOnePacket: UNIMPLEMENTED. FIXME\n"); 2658 return MP_STATUS_SUCCESS; 2659 } 2660 2661 MPSTATUS 2662 NTAPI 2663 UhciPassThru(IN PVOID uhciExtension, 2664 IN PVOID passThruParameters, 2665 IN ULONG ParameterLength, 2666 IN PVOID pParameters) 2667 { 2668 DPRINT_IMPL("UhciPassThru: UNIMPLEMENTED. FIXME\n"); 2669 return MP_STATUS_SUCCESS; 2670 } 2671 2672 VOID 2673 NTAPI 2674 UhciFlushInterrupts(IN PVOID uhciExtension) 2675 { 2676 DPRINT_IMPL("UhciFlushInterrupts: UNIMPLEMENTED. FIXME\n"); 2677 } 2678 2679 MPSTATUS 2680 NTAPI 2681 UhciUnload(IN PVOID uhciExtension) 2682 { 2683 DPRINT_IMPL("UhciUnload: UNIMPLEMENTED. FIXME\n"); 2684 return MP_STATUS_SUCCESS; 2685 } 2686 2687 NTSTATUS 2688 NTAPI 2689 DriverEntry(IN PDRIVER_OBJECT DriverObject, 2690 IN PUNICODE_STRING RegistryPath) 2691 { 2692 DPRINT("DriverEntry: DriverObject - %p, RegistryPath - %p\n", DriverObject, RegistryPath); 2693 2694 RtlZeroMemory(&RegPacket, sizeof(USBPORT_REGISTRATION_PACKET)); 2695 2696 RegPacket.MiniPortVersion = USB_MINIPORT_VERSION_UHCI; 2697 2698 RegPacket.MiniPortFlags = USB_MINIPORT_FLAGS_INTERRUPT | 2699 USB_MINIPORT_FLAGS_PORT_IO | 2700 USB_MINIPORT_FLAGS_NOT_LOCK_INT | 2701 USB_MINIPORT_FLAGS_POLLING | 2702 USB_MINIPORT_FLAGS_WAKE_SUPPORT; 2703 2704 RegPacket.MiniPortBusBandwidth = TOTAL_USB11_BUS_BANDWIDTH; 2705 2706 RegPacket.MiniPortExtensionSize = sizeof(UHCI_EXTENSION); 2707 RegPacket.MiniPortEndpointSize = sizeof(UHCI_ENDPOINT); 2708 RegPacket.MiniPortTransferSize = sizeof(UHCI_TRANSFER); 2709 RegPacket.MiniPortResourcesSize = sizeof(UHCI_HC_RESOURCES); 2710 2711 RegPacket.OpenEndpoint = UhciOpenEndpoint; 2712 RegPacket.ReopenEndpoint = UhciReopenEndpoint; 2713 RegPacket.QueryEndpointRequirements = UhciQueryEndpointRequirements; 2714 RegPacket.CloseEndpoint = UhciCloseEndpoint; 2715 RegPacket.StartController = UhciStartController; 2716 RegPacket.StopController = UhciStopController; 2717 RegPacket.SuspendController = UhciSuspendController; 2718 RegPacket.ResumeController = UhciResumeController; 2719 RegPacket.InterruptService = UhciInterruptService; 2720 RegPacket.InterruptDpc = UhciInterruptDpc; 2721 RegPacket.SubmitTransfer = UhciSubmitTransfer; 2722 RegPacket.SubmitIsoTransfer = UhciIsochTransfer; 2723 RegPacket.AbortTransfer = UhciAbortTransfer; 2724 RegPacket.GetEndpointState = UhciGetEndpointState; 2725 RegPacket.SetEndpointState = UhciSetEndpointState; 2726 RegPacket.PollEndpoint = UhciPollEndpoint; 2727 RegPacket.CheckController = UhciCheckController; 2728 RegPacket.Get32BitFrameNumber = UhciGet32BitFrameNumber; 2729 RegPacket.InterruptNextSOF = UhciInterruptNextSOF; 2730 RegPacket.EnableInterrupts = UhciEnableInterrupts; 2731 RegPacket.DisableInterrupts = UhciDisableInterrupts; 2732 RegPacket.PollController = UhciPollController; 2733 RegPacket.SetEndpointDataToggle = UhciSetEndpointDataToggle; 2734 RegPacket.GetEndpointStatus = UhciGetEndpointStatus; 2735 RegPacket.SetEndpointStatus = UhciSetEndpointStatus; 2736 RegPacket.RH_GetRootHubData = UhciRHGetRootHubData; 2737 RegPacket.RH_GetStatus = UhciRHGetStatus; 2738 RegPacket.RH_GetPortStatus = UhciRHGetPortStatus; 2739 RegPacket.RH_GetHubStatus = UhciRHGetHubStatus; 2740 RegPacket.RH_SetFeaturePortReset = UhciRHSetFeaturePortReset; 2741 RegPacket.RH_SetFeaturePortPower = UhciRHSetFeaturePortPower; 2742 RegPacket.RH_SetFeaturePortEnable = UhciRHSetFeaturePortEnable; 2743 RegPacket.RH_SetFeaturePortSuspend = UhciRHSetFeaturePortSuspend; 2744 RegPacket.RH_ClearFeaturePortEnable = UhciRHClearFeaturePortEnable; 2745 RegPacket.RH_ClearFeaturePortPower = UhciRHClearFeaturePortPower; 2746 RegPacket.RH_ClearFeaturePortSuspend = UhciRHClearFeaturePortSuspend; 2747 RegPacket.RH_ClearFeaturePortEnableChange = UhciRHClearFeaturePortEnableChange; 2748 RegPacket.RH_ClearFeaturePortConnectChange = UhciRHClearFeaturePortConnectChange; 2749 RegPacket.RH_ClearFeaturePortResetChange = UhciRHClearFeaturePortResetChange; 2750 RegPacket.RH_ClearFeaturePortSuspendChange = UhciRHClearFeaturePortSuspendChange; 2751 RegPacket.RH_ClearFeaturePortOvercurrentChange = UhciRHClearFeaturePortOvercurrentChange; 2752 RegPacket.RH_DisableIrq = UhciRHDisableIrq; 2753 RegPacket.RH_EnableIrq = UhciRHEnableIrq; 2754 RegPacket.StartSendOnePacket = UhciStartSendOnePacket; 2755 RegPacket.EndSendOnePacket = UhciEndSendOnePacket; 2756 RegPacket.PassThru = UhciPassThru; 2757 RegPacket.FlushInterrupts = UhciFlushInterrupts; 2758 2759 DriverObject->DriverUnload = NULL; 2760 2761 return USBPORT_RegisterUSBPortDriver(DriverObject, 2762 USB10_MINIPORT_INTERFACE_VERSION, 2763 &RegPacket); 2764 } 2765