1 /* 2 * PROJECT: ReactOS USB EHCI Miniport Driver 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: USBEHCI main driver functions 5 * COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru> 6 */ 7 8 #include "usbehci.h" 9 10 #define NDEBUG 11 #include <debug.h> 12 13 #define NDEBUG_EHCI_TRACE 14 #include "dbg_ehci.h" 15 16 USBPORT_REGISTRATION_PACKET RegPacket; 17 18 static const UCHAR ClassicPeriod[8] = { 19 ENDPOINT_INTERRUPT_1ms - 1, 20 ENDPOINT_INTERRUPT_2ms - 1, 21 ENDPOINT_INTERRUPT_4ms - 1, 22 ENDPOINT_INTERRUPT_8ms - 1, 23 ENDPOINT_INTERRUPT_16ms - 1, 24 ENDPOINT_INTERRUPT_32ms - 1, 25 ENDPOINT_INTERRUPT_32ms - 1, 26 ENDPOINT_INTERRUPT_32ms - 1 27 }; 28 29 static const EHCI_PERIOD pTable[] = { 30 { ENDPOINT_INTERRUPT_1ms, 0x00, 0xFF }, 31 { ENDPOINT_INTERRUPT_2ms, 0x00, 0x55 }, 32 { ENDPOINT_INTERRUPT_2ms, 0x00, 0xAA }, 33 { ENDPOINT_INTERRUPT_4ms, 0x00, 0x11 }, 34 { ENDPOINT_INTERRUPT_4ms, 0x00, 0x44 }, 35 { ENDPOINT_INTERRUPT_4ms, 0x00, 0x22 }, 36 { ENDPOINT_INTERRUPT_4ms, 0x00, 0x88 }, 37 { ENDPOINT_INTERRUPT_8ms, 0x00, 0x01 }, 38 { ENDPOINT_INTERRUPT_8ms, 0x00, 0x10 }, 39 { ENDPOINT_INTERRUPT_8ms, 0x00, 0x04 }, 40 { ENDPOINT_INTERRUPT_8ms, 0x00, 0x40 }, 41 { ENDPOINT_INTERRUPT_8ms, 0x00, 0x02 }, 42 { ENDPOINT_INTERRUPT_8ms, 0x00, 0x20 }, 43 { ENDPOINT_INTERRUPT_8ms, 0x00, 0x08 }, 44 { ENDPOINT_INTERRUPT_8ms, 0x00, 0x80 }, 45 { ENDPOINT_INTERRUPT_16ms, 0x01, 0x01 }, 46 { ENDPOINT_INTERRUPT_16ms, 0x02, 0x01 }, 47 { ENDPOINT_INTERRUPT_16ms, 0x01, 0x10 }, 48 { ENDPOINT_INTERRUPT_16ms, 0x02, 0x10 }, 49 { ENDPOINT_INTERRUPT_16ms, 0x01, 0x04 }, 50 { ENDPOINT_INTERRUPT_16ms, 0x02, 0x04 }, 51 { ENDPOINT_INTERRUPT_16ms, 0x01, 0x40 }, 52 { ENDPOINT_INTERRUPT_16ms, 0x02, 0x40 }, 53 { ENDPOINT_INTERRUPT_16ms, 0x01, 0x02 }, 54 { ENDPOINT_INTERRUPT_16ms, 0x02, 0x02 }, 55 { ENDPOINT_INTERRUPT_16ms, 0x01, 0x20 }, 56 { ENDPOINT_INTERRUPT_16ms, 0x02, 0x20 }, 57 { ENDPOINT_INTERRUPT_16ms, 0x01, 0x08 }, 58 { ENDPOINT_INTERRUPT_16ms, 0x02, 0x08 }, 59 { ENDPOINT_INTERRUPT_16ms, 0x01, 0x80 }, 60 { ENDPOINT_INTERRUPT_16ms, 0x02, 0x80 }, 61 { ENDPOINT_INTERRUPT_32ms, 0x03, 0x01 }, 62 { ENDPOINT_INTERRUPT_32ms, 0x05, 0x01 }, 63 { ENDPOINT_INTERRUPT_32ms, 0x04, 0x01 }, 64 { ENDPOINT_INTERRUPT_32ms, 0x06, 0x01 }, 65 { ENDPOINT_INTERRUPT_32ms, 0x03, 0x10 }, 66 { ENDPOINT_INTERRUPT_32ms, 0x05, 0x10 }, 67 { ENDPOINT_INTERRUPT_32ms, 0x04, 0x10 }, 68 { ENDPOINT_INTERRUPT_32ms, 0x06, 0x10 }, 69 { ENDPOINT_INTERRUPT_32ms, 0x03, 0x04 }, 70 { ENDPOINT_INTERRUPT_32ms, 0x05, 0x04 }, 71 { ENDPOINT_INTERRUPT_32ms, 0x04, 0x04 }, 72 { ENDPOINT_INTERRUPT_32ms, 0x06, 0x04 }, 73 { ENDPOINT_INTERRUPT_32ms, 0x03, 0x40 }, 74 { ENDPOINT_INTERRUPT_32ms, 0x05, 0x40 }, 75 { ENDPOINT_INTERRUPT_32ms, 0x04, 0x40 }, 76 { ENDPOINT_INTERRUPT_32ms, 0x06, 0x40 }, 77 { ENDPOINT_INTERRUPT_32ms, 0x03, 0x02 }, 78 { ENDPOINT_INTERRUPT_32ms, 0x05, 0x02 }, 79 { ENDPOINT_INTERRUPT_32ms, 0x04, 0x02 }, 80 { ENDPOINT_INTERRUPT_32ms, 0x06, 0x02 }, 81 { ENDPOINT_INTERRUPT_32ms, 0x03, 0x20 }, 82 { ENDPOINT_INTERRUPT_32ms, 0x05, 0x20 }, 83 { ENDPOINT_INTERRUPT_32ms, 0x04, 0x20 }, 84 { ENDPOINT_INTERRUPT_32ms, 0x06, 0x20 }, 85 { ENDPOINT_INTERRUPT_32ms, 0x03, 0x08 }, 86 { ENDPOINT_INTERRUPT_32ms, 0x05, 0x08 }, 87 { ENDPOINT_INTERRUPT_32ms, 0x04, 0x08 }, 88 { ENDPOINT_INTERRUPT_32ms, 0x06, 0x08 }, 89 { ENDPOINT_INTERRUPT_32ms, 0x03, 0x80 }, 90 { ENDPOINT_INTERRUPT_32ms, 0x05, 0x80 }, 91 { ENDPOINT_INTERRUPT_32ms, 0x04, 0x80 }, 92 { ENDPOINT_INTERRUPT_32ms, 0x06, 0x80 }, 93 { 0x00, 0x00, 0x00 } 94 }; 95 C_ASSERT(RTL_NUMBER_OF(pTable) == INTERRUPT_ENDPOINTs + 1); 96 97 static const UCHAR Balance[] = { 98 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30, 99 1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31 100 }; 101 C_ASSERT(RTL_NUMBER_OF(Balance) == EHCI_FRAMES); 102 103 static const UCHAR LinkTable[] = { 104 255, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 105 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 106 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 107 30, 30, 0 108 }; 109 C_ASSERT(RTL_NUMBER_OF(LinkTable) == INTERRUPT_ENDPOINTs + 1); 110 111 PEHCI_HCD_TD 112 NTAPI 113 EHCI_AllocTd(IN PEHCI_EXTENSION EhciExtension, 114 IN PEHCI_ENDPOINT EhciEndpoint) 115 { 116 PEHCI_HCD_TD TD; 117 ULONG ix; 118 119 DPRINT_EHCI("EHCI_AllocTd: ... \n"); 120 121 if (EhciEndpoint->MaxTDs == 0) 122 { 123 RegPacket.UsbPortBugCheck(EhciExtension); 124 return NULL; 125 } 126 127 TD = EhciEndpoint->FirstTD; 128 129 for (ix = 1; TD->TdFlags & EHCI_HCD_TD_FLAG_ALLOCATED; ix++) 130 { 131 TD += 1; 132 133 if (ix >= EhciEndpoint->MaxTDs) 134 { 135 RegPacket.UsbPortBugCheck(EhciExtension); 136 return NULL; 137 } 138 } 139 140 TD->TdFlags |= EHCI_HCD_TD_FLAG_ALLOCATED; 141 142 EhciEndpoint->RemainTDs--; 143 144 return TD; 145 } 146 147 PEHCI_HCD_QH 148 NTAPI 149 EHCI_InitializeQH(IN PEHCI_EXTENSION EhciExtension, 150 IN PEHCI_ENDPOINT EhciEndpoint, 151 IN PEHCI_HCD_QH QH, 152 IN ULONG QhPA) 153 { 154 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties; 155 ULONG DeviceSpeed; 156 157 DPRINT_EHCI("EHCI_InitializeQH: EhciEndpoint - %p, QH - %p, QhPA - %p\n", 158 EhciEndpoint, 159 QH, 160 QhPA); 161 162 EndpointProperties = &EhciEndpoint->EndpointProperties; 163 164 RtlZeroMemory(QH, sizeof(EHCI_HCD_QH)); 165 166 ASSERT((QhPA & ~LINK_POINTER_MASK) == 0); 167 168 QH->sqh.PhysicalAddress = QhPA; 169 170 QH->sqh.HwQH.EndpointParams.DeviceAddress = EndpointProperties->DeviceAddress; 171 QH->sqh.HwQH.EndpointParams.EndpointNumber = EndpointProperties->EndpointAddress; 172 173 DeviceSpeed = EndpointProperties->DeviceSpeed; 174 175 switch (DeviceSpeed) 176 { 177 case UsbLowSpeed: 178 QH->sqh.HwQH.EndpointParams.EndpointSpeed = EHCI_QH_EP_LOW_SPEED; 179 break; 180 181 case UsbFullSpeed: 182 QH->sqh.HwQH.EndpointParams.EndpointSpeed = EHCI_QH_EP_FULL_SPEED; 183 break; 184 185 case UsbHighSpeed: 186 QH->sqh.HwQH.EndpointParams.EndpointSpeed = EHCI_QH_EP_HIGH_SPEED; 187 break; 188 189 default: 190 DPRINT1("EHCI_InitializeQH: Unknown DeviceSpeed - %x\n", DeviceSpeed); 191 ASSERT(FALSE); 192 break; 193 } 194 195 QH->sqh.HwQH.EndpointParams.MaximumPacketLength = EndpointProperties->MaxPacketSize; 196 QH->sqh.HwQH.EndpointCaps.PipeMultiplier = 1; 197 198 if (DeviceSpeed == UsbHighSpeed) 199 { 200 QH->sqh.HwQH.EndpointCaps.HubAddr = 0; 201 QH->sqh.HwQH.EndpointCaps.PortNumber = 0; 202 } 203 else 204 { 205 QH->sqh.HwQH.EndpointCaps.HubAddr = EndpointProperties->HubAddr; 206 QH->sqh.HwQH.EndpointCaps.PortNumber = EndpointProperties->PortNumber; 207 208 if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_CONTROL) 209 QH->sqh.HwQH.EndpointParams.ControlEndpointFlag = 1; 210 } 211 212 QH->sqh.HwQH.NextTD = TERMINATE_POINTER; 213 QH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; 214 215 QH->sqh.HwQH.Token.Status &= (UCHAR)~(EHCI_TOKEN_STATUS_ACTIVE | 216 EHCI_TOKEN_STATUS_HALTED); 217 218 return QH; 219 } 220 221 MPSTATUS 222 NTAPI 223 EHCI_OpenBulkOrControlEndpoint(IN PEHCI_EXTENSION EhciExtension, 224 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 225 IN PEHCI_ENDPOINT EhciEndpoint, 226 IN BOOLEAN IsControl) 227 { 228 PEHCI_HCD_QH QH; 229 ULONG QhPA; 230 PEHCI_HCD_TD TdVA; 231 ULONG TdPA; 232 PEHCI_HCD_TD TD; 233 ULONG TdCount; 234 ULONG ix; 235 236 DPRINT("EHCI_OpenBulkOrControlEndpoint: EhciEndpoint - %p, IsControl - %x\n", 237 EhciEndpoint, 238 IsControl); 239 240 InitializeListHead(&EhciEndpoint->ListTDs); 241 242 EhciEndpoint->DmaBufferVA = (PVOID)EndpointProperties->BufferVA; 243 EhciEndpoint->DmaBufferPA = EndpointProperties->BufferPA; 244 245 RtlZeroMemory(EhciEndpoint->DmaBufferVA, sizeof(EHCI_HCD_TD)); 246 247 QH = (PEHCI_HCD_QH)EhciEndpoint->DmaBufferVA + 1; 248 QhPA = EhciEndpoint->DmaBufferPA + sizeof(EHCI_HCD_TD); 249 250 EhciEndpoint->FirstTD = (PEHCI_HCD_TD)(QH + 1); 251 252 TdCount = (EndpointProperties->BufferLength - 253 (sizeof(EHCI_HCD_TD) + sizeof(EHCI_HCD_QH))) / 254 sizeof(EHCI_HCD_TD); 255 256 if (EndpointProperties->TransferType == USBPORT_TRANSFER_TYPE_CONTROL) 257 EhciEndpoint->EndpointStatus |= USBPORT_ENDPOINT_CONTROL; 258 259 EhciEndpoint->MaxTDs = TdCount; 260 EhciEndpoint->RemainTDs = TdCount; 261 262 TdVA = EhciEndpoint->FirstTD; 263 TdPA = QhPA + sizeof(EHCI_HCD_QH); 264 265 for (ix = 0; ix < TdCount; ix++) 266 { 267 DPRINT_EHCI("EHCI_OpenBulkOrControlEndpoint: TdVA - %p, TdPA - %p\n", 268 TdVA, 269 TdPA); 270 271 RtlZeroMemory(TdVA, sizeof(EHCI_HCD_TD)); 272 273 ASSERT((TdPA & ~LINK_POINTER_MASK) == 0); 274 275 TdVA->PhysicalAddress = TdPA; 276 TdVA->EhciEndpoint = EhciEndpoint; 277 TdVA->EhciTransfer = NULL; 278 279 TdPA += sizeof(EHCI_HCD_TD); 280 TdVA += 1; 281 } 282 283 EhciEndpoint->QH = EHCI_InitializeQH(EhciExtension, 284 EhciEndpoint, 285 QH, 286 QhPA); 287 288 if (IsControl) 289 { 290 QH->sqh.HwQH.EndpointParams.DataToggleControl = 1; 291 EhciEndpoint->HcdHeadP = NULL; 292 } 293 else 294 { 295 QH->sqh.HwQH.EndpointParams.DataToggleControl = 0; 296 } 297 298 TD = EHCI_AllocTd(EhciExtension, EhciEndpoint); 299 300 if (!TD) 301 return MP_STATUS_NO_RESOURCES; 302 303 TD->TdFlags |= EHCI_HCD_TD_FLAG_DUMMY; 304 TD->HwTD.Token.Status &= (UCHAR)~EHCI_TOKEN_STATUS_ACTIVE; 305 306 TD->HwTD.NextTD = TERMINATE_POINTER; 307 TD->HwTD.AlternateNextTD = TERMINATE_POINTER; 308 309 TD->NextHcdTD = NULL; 310 TD->AltNextHcdTD = NULL; 311 312 EhciEndpoint->HcdTailP = TD; 313 EhciEndpoint->HcdHeadP = TD; 314 315 QH->sqh.HwQH.CurrentTD = TD->PhysicalAddress; 316 QH->sqh.HwQH.NextTD = TERMINATE_POINTER; 317 QH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; 318 319 QH->sqh.HwQH.Token.Status &= (UCHAR)~EHCI_TOKEN_STATUS_ACTIVE; 320 QH->sqh.HwQH.Token.TransferBytes = 0; 321 322 return MP_STATUS_SUCCESS; 323 } 324 325 MPSTATUS 326 NTAPI 327 EHCI_OpenInterruptEndpoint(IN PEHCI_EXTENSION EhciExtension, 328 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 329 IN PEHCI_ENDPOINT EhciEndpoint) 330 { 331 PEHCI_HCD_QH QH; 332 ULONG QhPA; 333 PEHCI_HCD_TD FirstTD; 334 ULONG FirstTdPA; 335 PEHCI_HCD_TD TD; 336 PEHCI_HCD_TD DummyTD; 337 ULONG TdCount; 338 ULONG ix; 339 const EHCI_PERIOD * PeriodTable = NULL; 340 ULONG ScheduleOffset; 341 ULONG Idx = 0; 342 UCHAR Period; 343 344 DPRINT("EHCI_OpenInterruptEndpoint: EhciExtension - %p, EndpointProperties - %p, EhciEndpoint - %p\n", 345 EhciExtension, 346 EndpointProperties, 347 EhciEndpoint); 348 349 Period = EndpointProperties->Period; 350 ScheduleOffset = EndpointProperties->ScheduleOffset; 351 352 ASSERT(Period < (INTERRUPT_ENDPOINTs + 1)); 353 354 while (!(Period & 1)) 355 { 356 Idx++; 357 Period >>= 1; 358 } 359 360 ASSERT(Idx < 8); 361 362 InitializeListHead(&EhciEndpoint->ListTDs); 363 364 if (EhciEndpoint->EndpointProperties.DeviceSpeed == UsbHighSpeed) 365 { 366 PeriodTable = &pTable[ClassicPeriod[Idx] + ScheduleOffset]; 367 EhciEndpoint->PeriodTable = PeriodTable; 368 369 DPRINT("EHCI_OpenInterruptEndpoint: EhciEndpoint - %p, ScheduleMask - %X, Index - %X\n", 370 EhciEndpoint, 371 PeriodTable->ScheduleMask, 372 ClassicPeriod[Idx]); 373 374 EhciEndpoint->StaticQH = EhciExtension->PeriodicHead[PeriodTable->PeriodIdx]; 375 } 376 else 377 { 378 EhciEndpoint->PeriodTable = NULL; 379 380 DPRINT("EHCI_OpenInterruptEndpoint: EhciEndpoint - %p, Index - %X\n", 381 EhciEndpoint, 382 ClassicPeriod[Idx]); 383 384 EhciEndpoint->StaticQH = EhciExtension->PeriodicHead[ClassicPeriod[Idx] + 385 ScheduleOffset]; 386 } 387 388 EhciEndpoint->DmaBufferVA = (PVOID)EndpointProperties->BufferVA; 389 EhciEndpoint->DmaBufferPA = EndpointProperties->BufferPA; 390 391 RtlZeroMemory((PVOID)EndpointProperties->BufferVA, sizeof(EHCI_HCD_TD)); 392 393 QH = (PEHCI_HCD_QH)(EndpointProperties->BufferVA + sizeof(EHCI_HCD_TD)); 394 QhPA = EndpointProperties->BufferPA + sizeof(EHCI_HCD_TD); 395 396 FirstTD = (PEHCI_HCD_TD)(EndpointProperties->BufferVA + 397 sizeof(EHCI_HCD_TD) + 398 sizeof(EHCI_HCD_QH)); 399 400 FirstTdPA = EndpointProperties->BufferPA + 401 sizeof(EHCI_HCD_TD) + 402 sizeof(EHCI_HCD_QH); 403 404 TdCount = (EndpointProperties->BufferLength - 405 (sizeof(EHCI_HCD_TD) + sizeof(EHCI_HCD_QH))) / 406 sizeof(EHCI_HCD_TD); 407 408 ASSERT(TdCount >= EHCI_MAX_INTERRUPT_TD_COUNT + 1); 409 410 EhciEndpoint->FirstTD = FirstTD; 411 EhciEndpoint->MaxTDs = TdCount; 412 413 for (ix = 0; ix < TdCount; ix++) 414 { 415 TD = EhciEndpoint->FirstTD + ix; 416 417 RtlZeroMemory(TD, sizeof(EHCI_HCD_TD)); 418 419 ASSERT((FirstTdPA & ~LINK_POINTER_MASK) == 0); 420 421 TD->PhysicalAddress = FirstTdPA; 422 TD->EhciEndpoint = EhciEndpoint; 423 TD->EhciTransfer = NULL; 424 425 FirstTdPA += sizeof(EHCI_HCD_TD); 426 } 427 428 EhciEndpoint->RemainTDs = TdCount; 429 430 EhciEndpoint->QH = EHCI_InitializeQH(EhciExtension, 431 EhciEndpoint, 432 QH, 433 QhPA); 434 435 if (EhciEndpoint->EndpointProperties.DeviceSpeed == UsbHighSpeed) 436 { 437 QH->sqh.HwQH.EndpointCaps.InterruptMask = PeriodTable->ScheduleMask; 438 } 439 else 440 { 441 QH->sqh.HwQH.EndpointCaps.InterruptMask = 442 EndpointProperties->InterruptScheduleMask; 443 444 QH->sqh.HwQH.EndpointCaps.SplitCompletionMask = 445 EndpointProperties->SplitCompletionMask; 446 } 447 448 DummyTD = EHCI_AllocTd(EhciExtension, EhciEndpoint); 449 450 DummyTD->TdFlags |= EHCI_HCD_TD_FLAG_DUMMY; 451 DummyTD->NextHcdTD = NULL; 452 DummyTD->AltNextHcdTD = NULL; 453 454 DummyTD->HwTD.Token.Status &= ~EHCI_TOKEN_STATUS_ACTIVE; 455 456 DummyTD->HwTD.NextTD = TERMINATE_POINTER; 457 DummyTD->HwTD.AlternateNextTD = TERMINATE_POINTER; 458 459 EhciEndpoint->HcdTailP = DummyTD; 460 EhciEndpoint->HcdHeadP = DummyTD; 461 462 QH->sqh.HwQH.CurrentTD = DummyTD->PhysicalAddress; 463 QH->sqh.HwQH.NextTD = TERMINATE_POINTER; 464 QH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; 465 466 QH->sqh.HwQH.Token.Status &= ~EHCI_TOKEN_STATUS_ACTIVE; 467 QH->sqh.HwQH.Token.TransferBytes = 0; 468 469 return MP_STATUS_SUCCESS; 470 } 471 472 MPSTATUS 473 NTAPI 474 EHCI_OpenHsIsoEndpoint(IN PEHCI_EXTENSION EhciExtension, 475 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 476 IN PEHCI_ENDPOINT EhciEndpoint) 477 { 478 DPRINT1("EHCI_OpenHsIsoEndpoint: UNIMPLEMENTED. FIXME\n"); 479 return MP_STATUS_NOT_SUPPORTED; 480 } 481 482 MPSTATUS 483 NTAPI 484 EHCI_OpenIsoEndpoint(IN PEHCI_EXTENSION EhciExtension, 485 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 486 IN PEHCI_ENDPOINT EhciEndpoint) 487 { 488 DPRINT1("EHCI_OpenIsoEndpoint: UNIMPLEMENTED. FIXME\n"); 489 return MP_STATUS_NOT_SUPPORTED; 490 } 491 492 MPSTATUS 493 NTAPI 494 EHCI_OpenEndpoint(IN PVOID ehciExtension, 495 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 496 IN PVOID ehciEndpoint) 497 { 498 PEHCI_EXTENSION EhciExtension = ehciExtension; 499 PEHCI_ENDPOINT EhciEndpoint = ehciEndpoint; 500 ULONG TransferType; 501 MPSTATUS MPStatus; 502 503 DPRINT("EHCI_OpenEndpoint: ... \n"); 504 505 RtlCopyMemory(&EhciEndpoint->EndpointProperties, 506 EndpointProperties, 507 sizeof(EhciEndpoint->EndpointProperties)); 508 509 TransferType = EndpointProperties->TransferType; 510 511 switch (TransferType) 512 { 513 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS: 514 if (EndpointProperties->DeviceSpeed == UsbHighSpeed) 515 { 516 MPStatus = EHCI_OpenHsIsoEndpoint(EhciExtension, 517 EndpointProperties, 518 EhciEndpoint); 519 } 520 else 521 { 522 MPStatus = EHCI_OpenIsoEndpoint(EhciExtension, 523 EndpointProperties, 524 EhciEndpoint); 525 } 526 527 break; 528 529 case USBPORT_TRANSFER_TYPE_CONTROL: 530 MPStatus = EHCI_OpenBulkOrControlEndpoint(EhciExtension, 531 EndpointProperties, 532 EhciEndpoint, 533 TRUE); 534 break; 535 536 case USBPORT_TRANSFER_TYPE_BULK: 537 MPStatus = EHCI_OpenBulkOrControlEndpoint(EhciExtension, 538 EndpointProperties, 539 EhciEndpoint, 540 FALSE); 541 break; 542 543 case USBPORT_TRANSFER_TYPE_INTERRUPT: 544 MPStatus = EHCI_OpenInterruptEndpoint(EhciExtension, 545 EndpointProperties, 546 EhciEndpoint); 547 break; 548 549 default: 550 MPStatus = MP_STATUS_NOT_SUPPORTED; 551 break; 552 } 553 554 return MPStatus; 555 } 556 557 MPSTATUS 558 NTAPI 559 EHCI_ReopenEndpoint(IN PVOID ehciExtension, 560 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 561 IN PVOID ehciEndpoint) 562 { 563 PEHCI_ENDPOINT EhciEndpoint; 564 ULONG TransferType; 565 PEHCI_HCD_QH QH; 566 MPSTATUS MPStatus; 567 568 EhciEndpoint = ehciEndpoint; 569 570 TransferType = EndpointProperties->TransferType; 571 572 DPRINT("EHCI_ReopenEndpoint: EhciEndpoint - %p, TransferType - %x\n", 573 EhciEndpoint, 574 TransferType); 575 576 switch (TransferType) 577 { 578 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS: 579 if (EndpointProperties->DeviceSpeed == UsbHighSpeed) 580 { 581 DPRINT1("EHCI_ReopenEndpoint: HS Iso. UNIMPLEMENTED. FIXME\n"); 582 MPStatus = MP_STATUS_NOT_SUPPORTED; 583 } 584 else 585 { 586 DPRINT1("EHCI_ReopenEndpoint: Iso. UNIMPLEMENTED. FIXME\n"); 587 MPStatus = MP_STATUS_NOT_SUPPORTED; 588 } 589 590 break; 591 592 case USBPORT_TRANSFER_TYPE_CONTROL: 593 case USBPORT_TRANSFER_TYPE_BULK: 594 case USBPORT_TRANSFER_TYPE_INTERRUPT: 595 RtlCopyMemory(&EhciEndpoint->EndpointProperties, 596 EndpointProperties, 597 sizeof(EhciEndpoint->EndpointProperties)); 598 599 QH = EhciEndpoint->QH; 600 601 QH->sqh.HwQH.EndpointParams.DeviceAddress = EndpointProperties->DeviceAddress; 602 QH->sqh.HwQH.EndpointParams.MaximumPacketLength = EndpointProperties->MaxPacketSize; 603 604 QH->sqh.HwQH.EndpointCaps.HubAddr = EndpointProperties->HubAddr; 605 606 break; 607 608 default: 609 DPRINT1("EHCI_ReopenEndpoint: Unknown TransferType\n"); 610 MPStatus = MP_STATUS_SUCCESS; 611 break; 612 } 613 614 return MPStatus; 615 } 616 617 VOID 618 NTAPI 619 EHCI_QueryEndpointRequirements(IN PVOID ehciExtension, 620 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 621 IN PUSBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements) 622 { 623 ULONG TransferType; 624 625 DPRINT("EHCI_QueryEndpointRequirements: ... \n"); 626 627 TransferType = EndpointProperties->TransferType; 628 629 switch (TransferType) 630 { 631 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS: 632 DPRINT("EHCI_QueryEndpointRequirements: IsoTransfer\n"); 633 634 if (EndpointProperties->DeviceSpeed == UsbHighSpeed) 635 { 636 EndpointRequirements->HeaderBufferSize = EHCI_MAX_HS_ISO_HEADER_BUFFER_SIZE; 637 EndpointRequirements->MaxTransferSize = EHCI_MAX_HS_ISO_TRANSFER_SIZE; 638 } 639 else 640 { 641 EndpointRequirements->HeaderBufferSize = EHCI_MAX_FS_ISO_HEADER_BUFFER_SIZE; 642 EndpointRequirements->MaxTransferSize = EHCI_MAX_FS_ISO_TRANSFER_SIZE; 643 } 644 break; 645 646 case USBPORT_TRANSFER_TYPE_CONTROL: 647 DPRINT("EHCI_QueryEndpointRequirements: ControlTransfer\n"); 648 EndpointRequirements->HeaderBufferSize = sizeof(EHCI_HCD_TD) + 649 sizeof(EHCI_HCD_QH) + 650 EHCI_MAX_CONTROL_TD_COUNT * sizeof(EHCI_HCD_TD); 651 652 EndpointRequirements->MaxTransferSize = EHCI_MAX_CONTROL_TRANSFER_SIZE; 653 break; 654 655 case USBPORT_TRANSFER_TYPE_BULK: 656 DPRINT("EHCI_QueryEndpointRequirements: BulkTransfer\n"); 657 EndpointRequirements->HeaderBufferSize = sizeof(EHCI_HCD_TD) + 658 sizeof(EHCI_HCD_QH) + 659 EHCI_MAX_BULK_TD_COUNT * sizeof(EHCI_HCD_TD); 660 661 EndpointRequirements->MaxTransferSize = EHCI_MAX_BULK_TRANSFER_SIZE; 662 break; 663 664 case USBPORT_TRANSFER_TYPE_INTERRUPT: 665 DPRINT("EHCI_QueryEndpointRequirements: InterruptTransfer\n"); 666 EndpointRequirements->HeaderBufferSize = sizeof(EHCI_HCD_TD) + 667 sizeof(EHCI_HCD_QH) + 668 EHCI_MAX_INTERRUPT_TD_COUNT * sizeof(EHCI_HCD_TD); 669 670 EndpointRequirements->MaxTransferSize = EHCI_MAX_INTERRUPT_TRANSFER_SIZE; 671 break; 672 673 default: 674 DPRINT1("EHCI_QueryEndpointRequirements: Unknown TransferType - %x\n", 675 TransferType); 676 DbgBreakPoint(); 677 break; 678 } 679 } 680 681 VOID 682 NTAPI 683 EHCI_DisablePeriodicList(IN PEHCI_EXTENSION EhciExtension) 684 { 685 PEHCI_HW_REGISTERS OperationalRegs; 686 EHCI_USB_COMMAND Command; 687 688 DPRINT("EHCI_DisablePeriodicList: ... \n"); 689 690 if (EhciExtension->Flags & EHCI_FLAGS_IDLE_SUPPORT) 691 { 692 OperationalRegs = EhciExtension->OperationalRegs; 693 694 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 695 Command.PeriodicEnable = 0; 696 WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); 697 } 698 } 699 700 VOID 701 NTAPI 702 EHCI_CloseEndpoint(IN PVOID ehciExtension, 703 IN PVOID ehciEndpoint, 704 IN BOOLEAN DisablePeriodic) 705 { 706 PEHCI_EXTENSION EhciExtension = ehciExtension; 707 PEHCI_ENDPOINT EhciEndpoint = ehciEndpoint; 708 ULONG TransferType; 709 710 DPRINT1("EHCI_CloseEndpoint: EhciEndpoint - %p, DisablePeriodic - %X\n", 711 EhciEndpoint, 712 DisablePeriodic); 713 714 if (DisablePeriodic) 715 { 716 TransferType = EhciEndpoint->EndpointProperties.TransferType; 717 718 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS || 719 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 720 { 721 EHCI_DisablePeriodicList(EhciExtension); 722 } 723 } 724 } 725 726 PEHCI_STATIC_QH 727 NTAPI 728 EHCI_GetQhForFrame(IN PEHCI_EXTENSION EhciExtension, 729 IN ULONG FrameIdx) 730 { 731 //DPRINT_EHCI("EHCI_GetQhForFrame: FrameIdx - %x, Balance[FrameIdx] - %x\n", 732 // FrameIdx, 733 // Balance[FrameIdx & 0x1F]); 734 735 return EhciExtension->PeriodicHead[Balance[FrameIdx & (EHCI_FRAMES - 1)]]; 736 } 737 738 PEHCI_HCD_QH 739 NTAPI 740 EHCI_GetDummyQhForFrame(IN PEHCI_EXTENSION EhciExtension, 741 IN ULONG Idx) 742 { 743 return (PEHCI_HCD_QH)((ULONG_PTR)EhciExtension->IsoDummyQHListVA + 744 Idx * sizeof(EHCI_HCD_QH)); 745 } 746 747 VOID 748 NTAPI 749 EHCI_AlignHwStructure(IN PEHCI_EXTENSION EhciExtension, 750 IN PULONG PhysicalAddress, 751 IN PULONG_PTR VirtualAddress, 752 IN ULONG Alignment) 753 { 754 ULONG PAddress; 755 ULONG NewPAddress; 756 ULONG_PTR VAddress; 757 758 //DPRINT_EHCI("EHCI_AlignHwStructure: *PhysicalAddress - %X, *VirtualAddress - %X, Alignment - %x\n", 759 // *PhysicalAddress, 760 // *VirtualAddress, 761 // Alignment); 762 763 PAddress = *PhysicalAddress; 764 VAddress = *VirtualAddress; 765 766 NewPAddress = (ULONG)(ULONG_PTR)PAGE_ALIGN(*PhysicalAddress + Alignment - 1); 767 768 if (NewPAddress != (ULONG)(ULONG_PTR)PAGE_ALIGN(*PhysicalAddress)) 769 { 770 VAddress += NewPAddress - PAddress; 771 PAddress = NewPAddress; 772 773 DPRINT("EHCI_AlignHwStructure: VAddress - %X, PAddress - %X\n", 774 VAddress, 775 PAddress); 776 } 777 778 *VirtualAddress = VAddress; 779 *PhysicalAddress = PAddress; 780 } 781 782 VOID 783 NTAPI 784 EHCI_AddDummyQHs(IN PEHCI_EXTENSION EhciExtension) 785 { 786 PEHCI_HC_RESOURCES HcResourcesVA; 787 PEHCI_HCD_QH DummyQH; 788 ULONG DummyQhPA; 789 EHCI_QH_EP_PARAMS EndpointParams; 790 EHCI_LINK_POINTER PAddress; 791 ULONG Frame; 792 793 DPRINT("EHCI_AddDummyQueueHeads: EhciExtension - %p\n", EhciExtension); 794 795 HcResourcesVA = EhciExtension->HcResourcesVA; 796 797 DummyQH = EhciExtension->IsoDummyQHListVA; 798 DummyQhPA = EhciExtension->IsoDummyQHListPA; 799 800 for (Frame = 0; Frame < EHCI_FRAME_LIST_MAX_ENTRIES; Frame++) 801 { 802 RtlZeroMemory(DummyQH, sizeof(EHCI_HCD_QH)); 803 804 PAddress.AsULONG = HcResourcesVA->PeriodicFrameList[Frame]; 805 806 DummyQH->sqh.HwQH.HorizontalLink.AsULONG = PAddress.AsULONG; 807 DummyQH->sqh.HwQH.CurrentTD = 0; 808 DummyQH->sqh.HwQH.NextTD = TERMINATE_POINTER; 809 DummyQH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; 810 811 EndpointParams = DummyQH->sqh.HwQH.EndpointParams; 812 EndpointParams.DeviceAddress = 0; 813 EndpointParams.EndpointSpeed = 0; 814 EndpointParams.MaximumPacketLength = EHCI_DUMMYQH_MAX_PACKET_LENGTH; 815 DummyQH->sqh.HwQH.EndpointParams = EndpointParams; 816 817 DummyQH->sqh.HwQH.EndpointCaps.AsULONG = 0; 818 DummyQH->sqh.HwQH.EndpointCaps.InterruptMask = 0; 819 DummyQH->sqh.HwQH.EndpointCaps.SplitCompletionMask = 0; 820 DummyQH->sqh.HwQH.EndpointCaps.PipeMultiplier = 1; 821 822 DummyQH->sqh.HwQH.Token.Status &= (UCHAR)~EHCI_TOKEN_STATUS_ACTIVE; 823 824 DummyQH->sqh.PhysicalAddress = DummyQhPA; 825 DummyQH->sqh.StaticQH = EHCI_GetQhForFrame(EhciExtension, Frame); 826 827 PAddress.AsULONG = DummyQhPA; 828 PAddress.Reserved = 0; 829 PAddress.Type = EHCI_LINK_TYPE_QH; 830 831 HcResourcesVA->PeriodicFrameList[Frame] = PAddress.AsULONG; 832 833 DummyQH++; 834 DummyQhPA += sizeof(EHCI_HCD_QH); 835 } 836 } 837 838 VOID 839 NTAPI 840 EHCI_InitializeInterruptSchedule(IN PEHCI_EXTENSION EhciExtension) 841 { 842 PEHCI_STATIC_QH StaticQH; 843 ULONG ix; 844 845 DPRINT("EHCI_InitializeInterruptSchedule: ... \n"); 846 847 for (ix = 0; ix < INTERRUPT_ENDPOINTs; ix++) 848 { 849 StaticQH = EhciExtension->PeriodicHead[ix]; 850 851 StaticQH->HwQH.EndpointParams.HeadReclamationListFlag = 0; 852 StaticQH->HwQH.NextTD |= TERMINATE_POINTER; 853 StaticQH->HwQH.Token.Status |= (UCHAR)EHCI_TOKEN_STATUS_HALTED; 854 } 855 856 for (ix = 1; ix < INTERRUPT_ENDPOINTs; ix++) 857 { 858 StaticQH = EhciExtension->PeriodicHead[ix]; 859 860 StaticQH->PrevHead = NULL; 861 StaticQH->NextHead = (PEHCI_HCD_QH)EhciExtension->PeriodicHead[LinkTable[ix]]; 862 863 StaticQH->HwQH.HorizontalLink.AsULONG = 864 EhciExtension->PeriodicHead[LinkTable[ix]]->PhysicalAddress; 865 866 StaticQH->HwQH.HorizontalLink.Type = EHCI_LINK_TYPE_QH; 867 StaticQH->HwQH.EndpointCaps.InterruptMask = 0xFF; 868 869 StaticQH->QhFlags |= EHCI_QH_FLAG_STATIC; 870 871 if (ix < (ENDPOINT_INTERRUPT_8ms - 1)) 872 StaticQH->QhFlags |= EHCI_QH_FLAG_STATIC_FAST; 873 } 874 875 EhciExtension->PeriodicHead[0]->HwQH.HorizontalLink.Terminate = 1; 876 877 EhciExtension->PeriodicHead[0]->QhFlags |= (EHCI_QH_FLAG_STATIC | 878 EHCI_QH_FLAG_STATIC_FAST); 879 } 880 881 MPSTATUS 882 NTAPI 883 EHCI_InitializeSchedule(IN PEHCI_EXTENSION EhciExtension, 884 IN ULONG_PTR BaseVA, 885 IN ULONG BasePA) 886 { 887 PEHCI_HW_REGISTERS OperationalRegs; 888 PEHCI_HC_RESOURCES HcResourcesVA; 889 ULONG HcResourcesPA; 890 PEHCI_STATIC_QH AsyncHead; 891 ULONG AsyncHeadPA; 892 PEHCI_STATIC_QH PeriodicHead; 893 ULONG PeriodicHeadPA; 894 PEHCI_STATIC_QH StaticQH; 895 EHCI_LINK_POINTER NextLink; 896 EHCI_LINK_POINTER StaticHeadPA; 897 ULONG Frame; 898 ULONG ix; 899 900 DPRINT("EHCI_InitializeSchedule: BaseVA - %p, BasePA - %p\n", 901 BaseVA, 902 BasePA); 903 904 OperationalRegs = EhciExtension->OperationalRegs; 905 906 HcResourcesVA = (PEHCI_HC_RESOURCES)BaseVA; 907 HcResourcesPA = BasePA; 908 909 EhciExtension->HcResourcesVA = HcResourcesVA; 910 EhciExtension->HcResourcesPA = BasePA; 911 912 /* Asynchronous Schedule */ 913 914 AsyncHead = &HcResourcesVA->AsyncHead; 915 AsyncHeadPA = HcResourcesPA + FIELD_OFFSET(EHCI_HC_RESOURCES, AsyncHead); 916 917 RtlZeroMemory(AsyncHead, sizeof(EHCI_STATIC_QH)); 918 919 NextLink.AsULONG = AsyncHeadPA; 920 NextLink.Type = EHCI_LINK_TYPE_QH; 921 922 AsyncHead->HwQH.HorizontalLink = NextLink; 923 AsyncHead->HwQH.EndpointParams.HeadReclamationListFlag = 1; 924 AsyncHead->HwQH.EndpointCaps.PipeMultiplier = 1; 925 AsyncHead->HwQH.NextTD |= TERMINATE_POINTER; 926 AsyncHead->HwQH.Token.Status = (UCHAR)EHCI_TOKEN_STATUS_HALTED; 927 928 AsyncHead->PhysicalAddress = AsyncHeadPA; 929 AsyncHead->PrevHead = AsyncHead->NextHead = (PEHCI_HCD_QH)AsyncHead; 930 931 EhciExtension->AsyncHead = AsyncHead; 932 933 /* Periodic Schedule */ 934 935 PeriodicHead = &HcResourcesVA->PeriodicHead[0]; 936 PeriodicHeadPA = HcResourcesPA + FIELD_OFFSET(EHCI_HC_RESOURCES, PeriodicHead[0]); 937 938 for (ix = 0; ix < (INTERRUPT_ENDPOINTs + 1); ix++) 939 { 940 EHCI_AlignHwStructure(EhciExtension, 941 &PeriodicHeadPA, 942 (PULONG_PTR)&PeriodicHead, 943 80); 944 945 EhciExtension->PeriodicHead[ix] = PeriodicHead; 946 EhciExtension->PeriodicHead[ix]->PhysicalAddress = PeriodicHeadPA; 947 948 PeriodicHead += 1; 949 PeriodicHeadPA += sizeof(EHCI_STATIC_QH); 950 } 951 952 EHCI_InitializeInterruptSchedule(EhciExtension); 953 954 for (Frame = 0; Frame < EHCI_FRAME_LIST_MAX_ENTRIES; Frame++) 955 { 956 StaticQH = EHCI_GetQhForFrame(EhciExtension, Frame); 957 958 StaticHeadPA.AsULONG = StaticQH->PhysicalAddress; 959 StaticHeadPA.Type = EHCI_LINK_TYPE_QH; 960 961 //DPRINT_EHCI("EHCI_InitializeSchedule: StaticHeadPA[%x] - %X\n", 962 // Frame, 963 // StaticHeadPA); 964 965 HcResourcesVA->PeriodicFrameList[Frame] = StaticHeadPA.AsULONG; 966 } 967 968 EhciExtension->IsoDummyQHListVA = &HcResourcesVA->IsoDummyQH[0]; 969 EhciExtension->IsoDummyQHListPA = HcResourcesPA + FIELD_OFFSET(EHCI_HC_RESOURCES, IsoDummyQH[0]); 970 971 EHCI_AddDummyQHs(EhciExtension); 972 973 WRITE_REGISTER_ULONG(&OperationalRegs->PeriodicListBase, 974 EhciExtension->HcResourcesPA + FIELD_OFFSET(EHCI_HC_RESOURCES, PeriodicFrameList)); 975 976 WRITE_REGISTER_ULONG(&OperationalRegs->AsyncListBase, 977 NextLink.AsULONG); 978 979 return MP_STATUS_SUCCESS; 980 } 981 982 MPSTATUS 983 NTAPI 984 EHCI_InitializeHardware(IN PEHCI_EXTENSION EhciExtension) 985 { 986 PEHCI_HC_CAPABILITY_REGISTERS CapabilityRegisters; 987 PEHCI_HW_REGISTERS OperationalRegs; 988 EHCI_USB_COMMAND Command; 989 LARGE_INTEGER EndTime; 990 LARGE_INTEGER CurrentTime; 991 EHCI_HC_STRUCTURAL_PARAMS StructuralParams; 992 993 DPRINT("EHCI_InitializeHardware: ... \n"); 994 995 OperationalRegs = EhciExtension->OperationalRegs; 996 CapabilityRegisters = EhciExtension->CapabilityRegisters; 997 998 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 999 Command.Reset = 1; 1000 WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); 1001 1002 KeQuerySystemTime(&EndTime); 1003 EndTime.QuadPart += 100 * 10000; // 100 msec 1004 1005 DPRINT("EHCI_InitializeHardware: Start reset ... \n"); 1006 1007 while (TRUE) 1008 { 1009 KeQuerySystemTime(&CurrentTime); 1010 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1011 1012 if (Command.Reset != 1) 1013 break; 1014 1015 if (CurrentTime.QuadPart >= EndTime.QuadPart) 1016 { 1017 if (Command.Reset == 1) 1018 { 1019 DPRINT1("EHCI_InitializeHardware: Reset failed!\n"); 1020 return MP_STATUS_HW_ERROR; 1021 } 1022 1023 break; 1024 } 1025 } 1026 1027 DPRINT("EHCI_InitializeHardware: Reset - OK\n"); 1028 1029 StructuralParams.AsULONG = READ_REGISTER_ULONG(&CapabilityRegisters->StructParameters.AsULONG); 1030 1031 EhciExtension->NumberOfPorts = StructuralParams.PortCount; 1032 EhciExtension->PortPowerControl = StructuralParams.PortPowerControl; 1033 1034 DPRINT("EHCI_InitializeHardware: StructuralParams - %X\n", StructuralParams.AsULONG); 1035 DPRINT("EHCI_InitializeHardware: PortPowerControl - %x\n", EhciExtension->PortPowerControl); 1036 DPRINT("EHCI_InitializeHardware: N_PORTS - %x\n", EhciExtension->NumberOfPorts); 1037 1038 WRITE_REGISTER_ULONG(&OperationalRegs->PeriodicListBase, 0); 1039 WRITE_REGISTER_ULONG(&OperationalRegs->AsyncListBase, 0); 1040 1041 EhciExtension->InterruptMask.AsULONG = 0; 1042 EhciExtension->InterruptMask.Interrupt = 1; 1043 EhciExtension->InterruptMask.ErrorInterrupt = 1; 1044 EhciExtension->InterruptMask.PortChangeInterrupt = 0; 1045 EhciExtension->InterruptMask.FrameListRollover = 1; 1046 EhciExtension->InterruptMask.HostSystemError = 1; 1047 EhciExtension->InterruptMask.InterruptOnAsyncAdvance = 1; 1048 1049 return MP_STATUS_SUCCESS; 1050 } 1051 1052 UCHAR 1053 NTAPI 1054 EHCI_GetOffsetEECP(IN PEHCI_EXTENSION EhciExtension, 1055 IN UCHAR CapabilityID) 1056 { 1057 EHCI_LEGACY_EXTENDED_CAPABILITY LegacyCapability; 1058 EHCI_HC_CAPABILITY_PARAMS CapParameters; 1059 UCHAR OffsetEECP; 1060 1061 DPRINT("EHCI_GetOffsetEECP: CapabilityID - %x\n", CapabilityID); 1062 1063 CapParameters = EhciExtension->CapabilityRegisters->CapParameters; 1064 1065 OffsetEECP = CapParameters.ExtCapabilitiesPointer; 1066 1067 if (!OffsetEECP) 1068 return 0; 1069 1070 while (TRUE) 1071 { 1072 RegPacket.UsbPortReadWriteConfigSpace(EhciExtension, 1073 TRUE, 1074 &LegacyCapability.AsULONG, 1075 OffsetEECP, 1076 sizeof(LegacyCapability)); 1077 1078 DPRINT("EHCI_GetOffsetEECP: OffsetEECP - %x\n", OffsetEECP); 1079 1080 if (LegacyCapability.CapabilityID == CapabilityID) 1081 break; 1082 1083 OffsetEECP = LegacyCapability.NextCapabilityPointer; 1084 1085 if (!OffsetEECP) 1086 return 0; 1087 } 1088 1089 return OffsetEECP; 1090 } 1091 1092 MPSTATUS 1093 NTAPI 1094 EHCI_TakeControlHC(IN PEHCI_EXTENSION EhciExtension) 1095 { 1096 LARGE_INTEGER EndTime; 1097 LARGE_INTEGER CurrentTime; 1098 EHCI_LEGACY_EXTENDED_CAPABILITY LegacyCapability; 1099 UCHAR OffsetEECP; 1100 1101 DPRINT("EHCI_TakeControlHC: EhciExtension - %p\n", EhciExtension); 1102 1103 OffsetEECP = EHCI_GetOffsetEECP(EhciExtension, 1); 1104 1105 if (OffsetEECP == 0) 1106 return MP_STATUS_SUCCESS; 1107 1108 DPRINT("EHCI_TakeControlHC: OffsetEECP - %X\n", OffsetEECP); 1109 1110 RegPacket.UsbPortReadWriteConfigSpace(EhciExtension, 1111 TRUE, 1112 &LegacyCapability.AsULONG, 1113 OffsetEECP, 1114 sizeof(LegacyCapability)); 1115 1116 if (LegacyCapability.BiosOwnedSemaphore == 0) 1117 return MP_STATUS_SUCCESS; 1118 1119 LegacyCapability.OsOwnedSemaphore = 1; 1120 1121 RegPacket.UsbPortReadWriteConfigSpace(EhciExtension, 1122 FALSE, 1123 &LegacyCapability.AsULONG, 1124 OffsetEECP, 1125 sizeof(LegacyCapability)); 1126 1127 KeQuerySystemTime(&EndTime); 1128 EndTime.QuadPart += 100 * 10000; 1129 1130 do 1131 { 1132 RegPacket.UsbPortReadWriteConfigSpace(EhciExtension, 1133 TRUE, 1134 &LegacyCapability.AsULONG, 1135 OffsetEECP, 1136 sizeof(LegacyCapability)); 1137 KeQuerySystemTime(&CurrentTime); 1138 1139 if (LegacyCapability.BiosOwnedSemaphore) 1140 { 1141 DPRINT("EHCI_TakeControlHC: Ownership is ok\n"); 1142 break; 1143 } 1144 } 1145 while (CurrentTime.QuadPart <= EndTime.QuadPart); 1146 1147 return MP_STATUS_SUCCESS; 1148 } 1149 1150 VOID 1151 NTAPI 1152 EHCI_GetRegistryParameters(IN PEHCI_EXTENSION EhciExtension) 1153 { 1154 DPRINT1("EHCI_GetRegistryParameters: UNIMPLEMENTED. FIXME\n"); 1155 } 1156 1157 MPSTATUS 1158 NTAPI 1159 EHCI_StartController(IN PVOID ehciExtension, 1160 IN PUSBPORT_RESOURCES Resources) 1161 { 1162 PEHCI_EXTENSION EhciExtension = ehciExtension; 1163 PEHCI_HC_CAPABILITY_REGISTERS CapabilityRegisters; 1164 PEHCI_HW_REGISTERS OperationalRegs; 1165 MPSTATUS MPStatus; 1166 EHCI_USB_COMMAND Command; 1167 UCHAR CapabilityRegLength; 1168 UCHAR Fladj; 1169 1170 DPRINT("EHCI_StartController: ... \n"); 1171 1172 if ((Resources->ResourcesTypes & (USBPORT_RESOURCES_MEMORY | USBPORT_RESOURCES_INTERRUPT)) != 1173 (USBPORT_RESOURCES_MEMORY | USBPORT_RESOURCES_INTERRUPT)) 1174 { 1175 DPRINT1("EHCI_StartController: Resources->ResourcesTypes - %x\n", 1176 Resources->ResourcesTypes); 1177 1178 return MP_STATUS_ERROR; 1179 } 1180 1181 CapabilityRegisters = (PEHCI_HC_CAPABILITY_REGISTERS)Resources->ResourceBase; 1182 EhciExtension->CapabilityRegisters = CapabilityRegisters; 1183 1184 CapabilityRegLength = READ_REGISTER_UCHAR(&CapabilityRegisters->RegistersLength); 1185 1186 OperationalRegs = (PEHCI_HW_REGISTERS)((ULONG_PTR)CapabilityRegisters + 1187 CapabilityRegLength); 1188 1189 EhciExtension->OperationalRegs = OperationalRegs; 1190 1191 DPRINT("EHCI_StartController: CapabilityRegisters - %p\n", CapabilityRegisters); 1192 DPRINT("EHCI_StartController: OperationalRegs - %p\n", OperationalRegs); 1193 1194 RegPacket.UsbPortReadWriteConfigSpace(EhciExtension, 1195 TRUE, 1196 &Fladj, 1197 EHCI_FLADJ_PCI_CONFIG_OFFSET, 1198 sizeof(Fladj)); 1199 1200 EhciExtension->FrameLengthAdjustment = Fladj; 1201 1202 EHCI_GetRegistryParameters(EhciExtension); 1203 1204 MPStatus = EHCI_TakeControlHC(EhciExtension); 1205 1206 if (MPStatus) 1207 { 1208 DPRINT1("EHCI_StartController: Unsuccessful TakeControlHC()\n"); 1209 return MPStatus; 1210 } 1211 1212 MPStatus = EHCI_InitializeHardware(EhciExtension); 1213 1214 if (MPStatus) 1215 { 1216 DPRINT1("EHCI_StartController: Unsuccessful InitializeHardware()\n"); 1217 return MPStatus; 1218 } 1219 1220 MPStatus = EHCI_InitializeSchedule(EhciExtension, 1221 Resources->StartVA, 1222 Resources->StartPA); 1223 1224 if (MPStatus) 1225 { 1226 DPRINT1("EHCI_StartController: Unsuccessful InitializeSchedule()\n"); 1227 return MPStatus; 1228 } 1229 1230 RegPacket.UsbPortReadWriteConfigSpace(EhciExtension, 1231 TRUE, 1232 &Fladj, 1233 EHCI_FLADJ_PCI_CONFIG_OFFSET, 1234 sizeof(Fladj)); 1235 1236 if (Fladj != EhciExtension->FrameLengthAdjustment) 1237 { 1238 Fladj = EhciExtension->FrameLengthAdjustment; 1239 1240 RegPacket.UsbPortReadWriteConfigSpace(EhciExtension, 1241 FALSE, // write 1242 &Fladj, 1243 EHCI_FLADJ_PCI_CONFIG_OFFSET, 1244 sizeof(Fladj)); 1245 } 1246 1247 /* Port routing control logic default-routes all ports to this HC */ 1248 EhciExtension->PortRoutingControl = EHCI_CONFIG_FLAG_CONFIGURED; 1249 WRITE_REGISTER_ULONG(&OperationalRegs->ConfigFlag, 1250 EhciExtension->PortRoutingControl); 1251 1252 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1253 Command.InterruptThreshold = 1; // one micro-frame 1254 WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); 1255 1256 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1257 Command.Run = 1; // execution of the schedule 1258 WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); 1259 1260 EhciExtension->IsStarted = TRUE; 1261 1262 if (Resources->IsChirpHandled) 1263 { 1264 ULONG Port; 1265 1266 for (Port = 1; Port <= EhciExtension->NumberOfPorts; Port++) 1267 { 1268 EHCI_RH_SetFeaturePortPower(EhciExtension, Port); 1269 } 1270 1271 RegPacket.UsbPortWait(EhciExtension, 200); 1272 1273 for (Port = 1; Port <= EhciExtension->NumberOfPorts; Port++) 1274 { 1275 EHCI_RH_ChirpRootPort(EhciExtension, Port++); 1276 } 1277 } 1278 1279 return MPStatus; 1280 } 1281 1282 VOID 1283 NTAPI 1284 EHCI_StopController(IN PVOID ehciExtension, 1285 IN BOOLEAN DisableInterrupts) 1286 { 1287 DPRINT1("EHCI_StopController: UNIMPLEMENTED. FIXME\n"); 1288 } 1289 1290 VOID 1291 NTAPI 1292 EHCI_SuspendController(IN PVOID ehciExtension) 1293 { 1294 PEHCI_EXTENSION EhciExtension = ehciExtension; 1295 PEHCI_HW_REGISTERS OperationalRegs; 1296 EHCI_USB_COMMAND Command; 1297 EHCI_USB_STATUS Status; 1298 EHCI_INTERRUPT_ENABLE IntrEn; 1299 ULONG ix; 1300 1301 DPRINT("EHCI_SuspendController: ... \n"); 1302 1303 OperationalRegs = EhciExtension->OperationalRegs; 1304 1305 EhciExtension->BackupPeriodiclistbase = READ_REGISTER_ULONG(&OperationalRegs->PeriodicListBase); 1306 EhciExtension->BackupAsynclistaddr = READ_REGISTER_ULONG(&OperationalRegs->AsyncListBase); 1307 EhciExtension->BackupCtrlDSSegment = READ_REGISTER_ULONG(&OperationalRegs->SegmentSelector); 1308 EhciExtension->BackupUSBCmd = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1309 1310 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1311 Command.InterruptAdvanceDoorbell = 0; 1312 WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); 1313 1314 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1315 Command.Run = 0; 1316 WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); 1317 1318 KeStallExecutionProcessor(125); 1319 1320 Status.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG); 1321 1322 Status.HCHalted = 0; 1323 Status.Reclamation = 0; 1324 Status.PeriodicStatus = 0; 1325 Status.AsynchronousStatus = 0; 1326 1327 if (Status.AsULONG) 1328 WRITE_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG, Status.AsULONG); 1329 1330 WRITE_REGISTER_ULONG(&OperationalRegs->HcInterruptEnable.AsULONG, 0); 1331 1332 for (ix = 0; ix < 10; ix++) 1333 { 1334 Status.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG); 1335 1336 if (Status.HCHalted) 1337 break; 1338 1339 RegPacket.UsbPortWait(EhciExtension, 1); 1340 } 1341 1342 if (!Status.HCHalted) 1343 DbgBreakPoint(); 1344 1345 IntrEn.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcInterruptEnable.AsULONG); 1346 IntrEn.PortChangeInterrupt = 1; 1347 WRITE_REGISTER_ULONG(&OperationalRegs->HcInterruptEnable.AsULONG, IntrEn.AsULONG); 1348 1349 EhciExtension->Flags |= EHCI_FLAGS_CONTROLLER_SUSPEND; 1350 } 1351 1352 MPSTATUS 1353 NTAPI 1354 EHCI_ResumeController(IN PVOID ehciExtension) 1355 { 1356 PEHCI_EXTENSION EhciExtension = ehciExtension; 1357 PEHCI_HW_REGISTERS OperationalRegs; 1358 ULONG RoutingControl; 1359 EHCI_USB_COMMAND Command; 1360 1361 DPRINT("EHCI_ResumeController: ... \n"); 1362 1363 OperationalRegs = EhciExtension->OperationalRegs; 1364 1365 RoutingControl = EhciExtension->PortRoutingControl; 1366 1367 if (!(RoutingControl & EHCI_CONFIG_FLAG_CONFIGURED)) 1368 { 1369 EhciExtension->PortRoutingControl = RoutingControl | EHCI_CONFIG_FLAG_CONFIGURED; 1370 WRITE_REGISTER_ULONG(&OperationalRegs->ConfigFlag, 1371 EhciExtension->PortRoutingControl); 1372 1373 return MP_STATUS_HW_ERROR; 1374 } 1375 1376 WRITE_REGISTER_ULONG(&OperationalRegs->SegmentSelector, 1377 EhciExtension->BackupCtrlDSSegment); 1378 1379 WRITE_REGISTER_ULONG(&OperationalRegs->PeriodicListBase, 1380 EhciExtension->BackupPeriodiclistbase); 1381 1382 WRITE_REGISTER_ULONG(&OperationalRegs->AsyncListBase, 1383 EhciExtension->BackupAsynclistaddr); 1384 1385 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1386 1387 Command.AsULONG = Command.AsULONG ^ EhciExtension->BackupUSBCmd; 1388 1389 Command.Reset = 0; 1390 Command.FrameListSize = 0; 1391 Command.InterruptAdvanceDoorbell = 0; 1392 Command.LightResetHC = 0; 1393 Command.AsynchronousParkModeCount = 0; 1394 Command.AsynchronousParkModeEnable = 0; 1395 1396 Command.Run = 1; 1397 1398 WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, 1399 Command.AsULONG); 1400 1401 WRITE_REGISTER_ULONG(&OperationalRegs->HcInterruptEnable.AsULONG, 1402 EhciExtension->InterruptMask.AsULONG); 1403 1404 EhciExtension->Flags &= ~EHCI_FLAGS_CONTROLLER_SUSPEND; 1405 1406 return MP_STATUS_SUCCESS; 1407 } 1408 1409 BOOLEAN 1410 NTAPI 1411 EHCI_HardwarePresent(IN PEHCI_EXTENSION EhciExtension, 1412 IN BOOLEAN IsInvalidateController) 1413 { 1414 PEHCI_HW_REGISTERS OperationalRegs = EhciExtension->OperationalRegs; 1415 1416 if (READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG) != -1) 1417 return TRUE; 1418 1419 DPRINT1("EHCI_HardwarePresent: IsInvalidateController - %x\n", 1420 IsInvalidateController); 1421 1422 if (!IsInvalidateController) 1423 return FALSE; 1424 1425 RegPacket.UsbPortInvalidateController(EhciExtension, 1426 USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE); 1427 return FALSE; 1428 } 1429 1430 BOOLEAN 1431 NTAPI 1432 EHCI_InterruptService(IN PVOID ehciExtension) 1433 { 1434 PEHCI_EXTENSION EhciExtension = ehciExtension; 1435 PEHCI_HW_REGISTERS OperationalRegs; 1436 BOOLEAN Result = FALSE; 1437 EHCI_USB_STATUS IntrSts; 1438 EHCI_INTERRUPT_ENABLE IntrEn; 1439 EHCI_INTERRUPT_ENABLE iStatus; 1440 EHCI_USB_COMMAND Command; 1441 ULONG FrameIndex; 1442 1443 OperationalRegs = EhciExtension->OperationalRegs; 1444 1445 DPRINT_EHCI("EHCI_InterruptService: ... \n"); 1446 1447 Result = EHCI_HardwarePresent(EhciExtension, FALSE); 1448 1449 if (!Result) 1450 return FALSE; 1451 1452 IntrEn.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcInterruptEnable.AsULONG); 1453 IntrSts.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG); 1454 1455 iStatus.AsULONG = (IntrEn.AsULONG & IntrSts.AsULONG) & EHCI_INTERRUPT_MASK; 1456 1457 if (!iStatus.AsULONG) 1458 return FALSE; 1459 1460 EhciExtension->InterruptStatus = iStatus; 1461 1462 WRITE_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG, iStatus.AsULONG); 1463 1464 if (iStatus.HostSystemError) 1465 { 1466 EhciExtension->HcSystemErrors++; 1467 1468 if (EhciExtension->HcSystemErrors < EHCI_MAX_HC_SYSTEM_ERRORS) 1469 { 1470 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1471 Command.Run = 1; 1472 WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); 1473 } 1474 } 1475 1476 FrameIndex = READ_REGISTER_ULONG(&OperationalRegs->FrameIndex) / EHCI_MICROFRAMES; 1477 FrameIndex &= EHCI_FRINDEX_FRAME_MASK; 1478 1479 if ((FrameIndex ^ EhciExtension->FrameIndex) & EHCI_FRAME_LIST_MAX_ENTRIES) 1480 { 1481 EhciExtension->FrameHighPart += 2 * EHCI_FRAME_LIST_MAX_ENTRIES; 1482 1483 EhciExtension->FrameHighPart -= (FrameIndex ^ EhciExtension->FrameHighPart) & 1484 EHCI_FRAME_LIST_MAX_ENTRIES; 1485 } 1486 1487 EhciExtension->FrameIndex = FrameIndex; 1488 1489 return TRUE; 1490 } 1491 1492 VOID 1493 NTAPI 1494 EHCI_InterruptDpc(IN PVOID ehciExtension, 1495 IN BOOLEAN EnableInterrupts) 1496 { 1497 PEHCI_EXTENSION EhciExtension = ehciExtension; 1498 PEHCI_HW_REGISTERS OperationalRegs; 1499 EHCI_INTERRUPT_ENABLE iStatus; 1500 1501 OperationalRegs = EhciExtension->OperationalRegs; 1502 1503 DPRINT_EHCI("EHCI_InterruptDpc: [%p] EnableInterrupts - %x\n", 1504 EhciExtension, EnableInterrupts); 1505 1506 iStatus = EhciExtension->InterruptStatus; 1507 EhciExtension->InterruptStatus.AsULONG = 0; 1508 1509 if (iStatus.Interrupt == 1 || 1510 iStatus.ErrorInterrupt == 1 || 1511 iStatus.InterruptOnAsyncAdvance == 1) 1512 { 1513 DPRINT_EHCI("EHCI_InterruptDpc: [%p] InterruptStatus - %X\n", EhciExtension, iStatus.AsULONG); 1514 RegPacket.UsbPortInvalidateEndpoint(EhciExtension, NULL); 1515 } 1516 1517 if (iStatus.PortChangeInterrupt == 1) 1518 { 1519 DPRINT_EHCI("EHCI_InterruptDpc: [%p] PortChangeInterrupt\n", EhciExtension); 1520 RegPacket.UsbPortInvalidateRootHub(EhciExtension); 1521 } 1522 1523 if (EnableInterrupts) 1524 { 1525 WRITE_REGISTER_ULONG(&OperationalRegs->HcInterruptEnable.AsULONG, 1526 EhciExtension->InterruptMask.AsULONG); 1527 } 1528 } 1529 1530 ULONG 1531 NTAPI 1532 EHCI_MapAsyncTransferToTd(IN PEHCI_EXTENSION EhciExtension, 1533 IN ULONG MaxPacketSize, 1534 IN ULONG TransferedLen, 1535 IN PULONG DataToggle, 1536 IN PEHCI_TRANSFER EhciTransfer, 1537 IN PEHCI_HCD_TD TD, 1538 IN PUSBPORT_SCATTER_GATHER_LIST SgList) 1539 { 1540 PUSBPORT_TRANSFER_PARAMETERS TransferParameters; 1541 PUSBPORT_SCATTER_GATHER_ELEMENT SgElement; 1542 ULONG SgIdx; 1543 ULONG LengthThisTD; 1544 ULONG ix; 1545 ULONG SgRemain; 1546 ULONG DiffLength; 1547 ULONG NumPackets; 1548 1549 DPRINT_EHCI("EHCI_MapAsyncTransferToTd: EhciTransfer - %p, TD - %p, TransferedLen - %x, MaxPacketSize - %x, DataToggle - %x\n", 1550 EhciTransfer, 1551 TD, 1552 TransferedLen, 1553 MaxPacketSize, 1554 DataToggle); 1555 1556 TransferParameters = EhciTransfer->TransferParameters; 1557 1558 SgElement = &SgList->SgElement[0]; 1559 1560 for (SgIdx = 0; SgIdx < SgList->SgElementCount; SgIdx++) 1561 { 1562 if (TransferedLen >= SgElement->SgOffset && 1563 TransferedLen < SgElement->SgOffset + SgElement->SgTransferLength) 1564 { 1565 break; 1566 } 1567 1568 SgElement += 1; 1569 } 1570 1571 SgRemain = SgList->SgElementCount - SgIdx; 1572 1573 if (SgRemain > EHCI_MAX_QTD_BUFFER_PAGES) 1574 { 1575 TD->HwTD.Buffer[0] = SgList->SgElement[SgIdx].SgPhysicalAddress.LowPart - 1576 SgList->SgElement[SgIdx].SgOffset + 1577 TransferedLen; 1578 1579 LengthThisTD = EHCI_MAX_QTD_BUFFER_PAGES * PAGE_SIZE - 1580 (TD->HwTD.Buffer[0] & (PAGE_SIZE - 1)); 1581 1582 for (ix = 1; ix < EHCI_MAX_QTD_BUFFER_PAGES; ix++) 1583 { 1584 TD->HwTD.Buffer[ix] = SgList->SgElement[SgIdx + ix].SgPhysicalAddress.LowPart; 1585 } 1586 1587 NumPackets = LengthThisTD / MaxPacketSize; 1588 DiffLength = LengthThisTD - MaxPacketSize * (LengthThisTD / MaxPacketSize); 1589 1590 if (LengthThisTD != MaxPacketSize * (LengthThisTD / MaxPacketSize)) 1591 LengthThisTD -= DiffLength; 1592 1593 if (DataToggle && (NumPackets & 1)) 1594 *DataToggle = !(*DataToggle); 1595 } 1596 else 1597 { 1598 LengthThisTD = TransferParameters->TransferBufferLength - TransferedLen; 1599 1600 TD->HwTD.Buffer[0] = TransferedLen + 1601 SgList->SgElement[SgIdx].SgPhysicalAddress.LowPart - 1602 SgList->SgElement[SgIdx].SgOffset; 1603 1604 for (ix = 1; ix < EHCI_MAX_QTD_BUFFER_PAGES; ix++) 1605 { 1606 if ((SgIdx + ix) >= SgList->SgElementCount) 1607 break; 1608 1609 TD->HwTD.Buffer[ix] = SgList->SgElement[SgIdx + ix].SgPhysicalAddress.LowPart; 1610 } 1611 } 1612 1613 TD->HwTD.Token.TransferBytes = LengthThisTD; 1614 TD->LengthThisTD = LengthThisTD; 1615 1616 return LengthThisTD + TransferedLen; 1617 } 1618 1619 VOID 1620 NTAPI 1621 EHCI_EnableAsyncList(IN PEHCI_EXTENSION EhciExtension) 1622 { 1623 PEHCI_HW_REGISTERS OperationalRegs; 1624 EHCI_USB_COMMAND UsbCmd; 1625 1626 DPRINT_EHCI("EHCI_EnableAsyncList: ... \n"); 1627 1628 OperationalRegs = EhciExtension->OperationalRegs; 1629 1630 UsbCmd.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1631 UsbCmd.AsynchronousEnable = 1; 1632 WRITE_REGISTER_ULONG((&OperationalRegs->HcCommand.AsULONG), UsbCmd.AsULONG); 1633 } 1634 1635 VOID 1636 NTAPI 1637 EHCI_DisableAsyncList(IN PEHCI_EXTENSION EhciExtension) 1638 { 1639 PEHCI_HW_REGISTERS OperationalRegs; 1640 EHCI_USB_COMMAND UsbCmd; 1641 1642 DPRINT("EHCI_DisableAsyncList: ... \n"); 1643 1644 OperationalRegs = EhciExtension->OperationalRegs; 1645 1646 UsbCmd.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1647 UsbCmd.AsynchronousEnable = 0; 1648 WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, UsbCmd.AsULONG); 1649 } 1650 1651 VOID 1652 NTAPI 1653 EHCI_EnablePeriodicList(IN PEHCI_EXTENSION EhciExtension) 1654 { 1655 PEHCI_HW_REGISTERS OperationalRegs; 1656 EHCI_USB_COMMAND Command; 1657 1658 DPRINT("EHCI_EnablePeriodicList: ... \n"); 1659 1660 OperationalRegs = EhciExtension->OperationalRegs; 1661 1662 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1663 Command.PeriodicEnable = 1; 1664 WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); 1665 } 1666 1667 VOID 1668 NTAPI 1669 EHCI_FlushAsyncCache(IN PEHCI_EXTENSION EhciExtension) 1670 { 1671 PEHCI_HW_REGISTERS OperationalRegs; 1672 EHCI_USB_COMMAND Command; 1673 EHCI_USB_STATUS Status; 1674 LARGE_INTEGER CurrentTime; 1675 LARGE_INTEGER EndTime; 1676 EHCI_USB_COMMAND Cmd; 1677 1678 DPRINT_EHCI("EHCI_FlushAsyncCache: EhciExtension - %p\n", EhciExtension); 1679 1680 OperationalRegs = EhciExtension->OperationalRegs; 1681 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1682 Status.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG); 1683 1684 if (!Status.AsynchronousStatus && !Command.AsynchronousEnable) 1685 return; 1686 1687 if (Status.AsynchronousStatus && !Command.AsynchronousEnable) 1688 { 1689 KeQuerySystemTime(&EndTime); 1690 EndTime.QuadPart += 100 * 10000; //100 ms 1691 1692 do 1693 { 1694 Status.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG); 1695 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1696 KeQuerySystemTime(&CurrentTime); 1697 1698 if (CurrentTime.QuadPart > EndTime.QuadPart) 1699 RegPacket.UsbPortBugCheck(EhciExtension); 1700 } 1701 while (Status.AsynchronousStatus && Command.AsULONG != -1 && Command.Run); 1702 1703 return; 1704 } 1705 1706 if (!Status.AsynchronousStatus && Command.AsynchronousEnable) 1707 { 1708 KeQuerySystemTime(&EndTime); 1709 EndTime.QuadPart += 100 * 10000; //100 ms 1710 1711 do 1712 { 1713 Status.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG); 1714 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1715 KeQuerySystemTime(&CurrentTime); 1716 } 1717 while (!Status.AsynchronousStatus && Command.AsULONG != -1 && Command.Run); 1718 } 1719 1720 Command.InterruptAdvanceDoorbell = 1; 1721 WRITE_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG, Command.AsULONG); 1722 1723 KeQuerySystemTime(&EndTime); 1724 EndTime.QuadPart += 100 * 10000; //100 ms 1725 1726 Cmd.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1727 1728 if (Cmd.InterruptAdvanceDoorbell) 1729 { 1730 while (Cmd.Run) 1731 { 1732 if (Cmd.AsULONG == -1) 1733 break; 1734 1735 KeStallExecutionProcessor(1); 1736 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1737 KeQuerySystemTime(&CurrentTime); 1738 1739 if (!Command.InterruptAdvanceDoorbell) 1740 break; 1741 1742 Cmd = Command; 1743 } 1744 } 1745 1746 /* InterruptOnAsyncAdvance */ 1747 WRITE_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG, 0x20); 1748 } 1749 1750 VOID 1751 NTAPI 1752 EHCI_LockQH(IN PEHCI_EXTENSION EhciExtension, 1753 IN PEHCI_HCD_QH QH, 1754 IN ULONG TransferType) 1755 { 1756 PEHCI_HCD_QH PrevQH; 1757 PEHCI_HCD_QH NextQH; 1758 ULONG QhPA; 1759 ULONG FrameIndexReg; 1760 PEHCI_HW_REGISTERS OperationalRegs; 1761 EHCI_USB_COMMAND Command; 1762 1763 DPRINT_EHCI("EHCI_LockQH: QH - %p, TransferType - %x\n", 1764 QH, 1765 TransferType); 1766 1767 OperationalRegs = EhciExtension->OperationalRegs; 1768 1769 ASSERT((QH->sqh.QhFlags & EHCI_QH_FLAG_UPDATING) == 0); 1770 ASSERT(EhciExtension->LockQH == NULL); 1771 1772 PrevQH = QH->sqh.PrevHead; 1773 QH->sqh.QhFlags |= EHCI_QH_FLAG_UPDATING; 1774 1775 ASSERT(PrevQH); 1776 1777 NextQH = QH->sqh.NextHead; 1778 1779 EhciExtension->PrevQH = PrevQH; 1780 EhciExtension->NextQH = NextQH; 1781 EhciExtension->LockQH = QH; 1782 1783 if (NextQH) 1784 { 1785 QhPA = NextQH->sqh.PhysicalAddress; 1786 QhPA &= LINK_POINTER_MASK + TERMINATE_POINTER; 1787 QhPA |= (EHCI_LINK_TYPE_QH << 1); 1788 } 1789 else 1790 { 1791 QhPA = TERMINATE_POINTER; 1792 } 1793 1794 PrevQH->sqh.HwQH.HorizontalLink.AsULONG = QhPA; 1795 1796 FrameIndexReg = READ_REGISTER_ULONG(&OperationalRegs->FrameIndex); 1797 1798 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 1799 { 1800 do 1801 { 1802 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 1803 } 1804 while (READ_REGISTER_ULONG(&OperationalRegs->FrameIndex) == 1805 FrameIndexReg && (Command.AsULONG != -1) && Command.Run); 1806 } 1807 else 1808 { 1809 EHCI_FlushAsyncCache(EhciExtension); 1810 } 1811 } 1812 1813 VOID 1814 NTAPI 1815 EHCI_UnlockQH(IN PEHCI_EXTENSION EhciExtension, 1816 IN PEHCI_HCD_QH QH) 1817 { 1818 ULONG QhPA; 1819 1820 DPRINT_EHCI("EHCI_UnlockQH: QH - %p\n", QH); 1821 1822 ASSERT(QH->sqh.QhFlags & EHCI_QH_FLAG_UPDATING); 1823 ASSERT(EhciExtension->LockQH); 1824 ASSERT(EhciExtension->LockQH == QH); 1825 1826 QH->sqh.QhFlags &= ~EHCI_QH_FLAG_UPDATING; 1827 1828 EhciExtension->LockQH = NULL; 1829 1830 QhPA = QH->sqh.PhysicalAddress; 1831 QhPA &= LINK_POINTER_MASK + TERMINATE_POINTER; 1832 QhPA |= (EHCI_LINK_TYPE_QH << 1); 1833 1834 EhciExtension->PrevQH->sqh.HwQH.HorizontalLink.AsULONG = QhPA; 1835 } 1836 1837 VOID 1838 NTAPI 1839 EHCI_LinkTransferToQueue(IN PEHCI_EXTENSION EhciExtension, 1840 IN PEHCI_ENDPOINT EhciEndpoint, 1841 IN PEHCI_HCD_TD NextTD) 1842 { 1843 PEHCI_HCD_QH QH; 1844 PEHCI_HCD_TD TD; 1845 PEHCI_TRANSFER Transfer; 1846 PEHCI_HCD_TD LinkTD; 1847 BOOLEAN IsPresent; 1848 ULONG ix; 1849 1850 DPRINT_EHCI("EHCI_LinkTransferToQueue: EhciEndpoint - %p, NextTD - %p\n", 1851 EhciEndpoint, 1852 NextTD); 1853 1854 ASSERT(EhciEndpoint->HcdHeadP != NULL); 1855 IsPresent = EHCI_HardwarePresent(EhciExtension, 0); 1856 1857 QH = EhciEndpoint->QH; 1858 TD = EhciEndpoint->HcdHeadP; 1859 1860 if (TD == EhciEndpoint->HcdTailP) 1861 { 1862 if (IsPresent) 1863 { 1864 EHCI_LockQH(EhciExtension, 1865 QH, 1866 EhciEndpoint->EndpointProperties.TransferType); 1867 } 1868 1869 QH->sqh.HwQH.CurrentTD = EhciEndpoint->DmaBufferPA; 1870 QH->sqh.HwQH.NextTD = NextTD->PhysicalAddress; 1871 QH->sqh.HwQH.AlternateNextTD = NextTD->HwTD.AlternateNextTD; 1872 1873 QH->sqh.HwQH.Token.Status = (UCHAR)~(EHCI_TOKEN_STATUS_ACTIVE | 1874 EHCI_TOKEN_STATUS_HALTED); 1875 1876 QH->sqh.HwQH.Token.TransferBytes = 0; 1877 1878 if (IsPresent) 1879 EHCI_UnlockQH(EhciExtension, QH); 1880 1881 EhciEndpoint->HcdHeadP = NextTD; 1882 } 1883 else 1884 { 1885 DPRINT_EHCI("EHCI_LinkTransferToQueue: TD - %p, HcdTailP - %p\n", 1886 EhciEndpoint->HcdHeadP, 1887 EhciEndpoint->HcdTailP); 1888 1889 LinkTD = EhciEndpoint->HcdHeadP; 1890 1891 while (TD != EhciEndpoint->HcdTailP) 1892 { 1893 LinkTD = TD; 1894 TD = TD->NextHcdTD; 1895 } 1896 1897 ASSERT(LinkTD != EhciEndpoint->HcdTailP); 1898 1899 Transfer = LinkTD->EhciTransfer; 1900 1901 TD = EhciEndpoint->FirstTD; 1902 1903 for (ix = 0; ix < EhciEndpoint->MaxTDs; ix++) 1904 { 1905 if (TD->EhciTransfer == Transfer) 1906 { 1907 TD->AltNextHcdTD = NextTD; 1908 TD->HwTD.AlternateNextTD = NextTD->PhysicalAddress; 1909 } 1910 1911 TD += 1; 1912 } 1913 1914 LinkTD->HwTD.NextTD = NextTD->PhysicalAddress; 1915 LinkTD->NextHcdTD = NextTD; 1916 1917 if (QH->sqh.HwQH.CurrentTD == LinkTD->PhysicalAddress) 1918 { 1919 QH->sqh.HwQH.NextTD = NextTD->PhysicalAddress; 1920 QH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; 1921 } 1922 } 1923 } 1924 1925 MPSTATUS 1926 NTAPI 1927 EHCI_ControlTransfer(IN PEHCI_EXTENSION EhciExtension, 1928 IN PEHCI_ENDPOINT EhciEndpoint, 1929 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, 1930 IN PEHCI_TRANSFER EhciTransfer, 1931 IN PUSBPORT_SCATTER_GATHER_LIST SgList) 1932 { 1933 PEHCI_HCD_TD FirstTD; 1934 PEHCI_HCD_TD LastTD; 1935 PEHCI_HCD_TD TD; 1936 PEHCI_HCD_TD PrevTD; 1937 PEHCI_HCD_TD LinkTD; 1938 ULONG TransferedLen = 0; 1939 EHCI_TD_TOKEN Token; 1940 ULONG DataToggle = 1; 1941 1942 DPRINT_EHCI("EHCI_ControlTransfer: EhciEndpoint - %p, EhciTransfer - %p\n", 1943 EhciEndpoint, 1944 EhciTransfer); 1945 1946 if (EhciEndpoint->RemainTDs < EHCI_MAX_CONTROL_TD_COUNT) 1947 return MP_STATUS_FAILURE; 1948 1949 EhciExtension->PendingTransfers++; 1950 EhciEndpoint->PendingTDs++; 1951 1952 EhciTransfer->TransferOnAsyncList = 1; 1953 1954 FirstTD = EHCI_AllocTd(EhciExtension, EhciEndpoint); 1955 1956 if (!FirstTD) 1957 { 1958 RegPacket.UsbPortBugCheck(EhciExtension); 1959 return MP_STATUS_FAILURE; 1960 } 1961 1962 EhciTransfer->PendingTDs++; 1963 1964 FirstTD->TdFlags |= EHCI_HCD_TD_FLAG_PROCESSED; 1965 FirstTD->EhciTransfer = EhciTransfer; 1966 1967 FirstTD->HwTD.Buffer[0] = FirstTD->PhysicalAddress + FIELD_OFFSET(EHCI_HCD_TD, SetupPacket); 1968 FirstTD->HwTD.Buffer[1] = 0; 1969 FirstTD->HwTD.Buffer[2] = 0; 1970 FirstTD->HwTD.Buffer[3] = 0; 1971 FirstTD->HwTD.Buffer[4] = 0; 1972 1973 FirstTD->NextHcdTD = NULL; 1974 1975 FirstTD->HwTD.NextTD = TERMINATE_POINTER; 1976 FirstTD->HwTD.AlternateNextTD = TERMINATE_POINTER; 1977 1978 FirstTD->HwTD.Token.AsULONG = 0; 1979 FirstTD->HwTD.Token.ErrorCounter = 3; 1980 FirstTD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_SETUP; 1981 FirstTD->HwTD.Token.Status = (UCHAR)EHCI_TOKEN_STATUS_ACTIVE; 1982 FirstTD->HwTD.Token.TransferBytes = sizeof(FirstTD->SetupPacket); 1983 1984 RtlCopyMemory(&FirstTD->SetupPacket, 1985 &TransferParameters->SetupPacket, 1986 sizeof(FirstTD->SetupPacket)); 1987 1988 LastTD = EHCI_AllocTd(EhciExtension, EhciEndpoint); 1989 1990 if (!LastTD) 1991 { 1992 RegPacket.UsbPortBugCheck(EhciExtension); 1993 return MP_STATUS_FAILURE; 1994 } 1995 1996 EhciTransfer->PendingTDs++; 1997 1998 LastTD->TdFlags |= EHCI_HCD_TD_FLAG_PROCESSED; 1999 LastTD->EhciTransfer = EhciTransfer; 2000 2001 LastTD->HwTD.Buffer[0] = 0; 2002 LastTD->HwTD.Buffer[1] = 0; 2003 LastTD->HwTD.Buffer[2] = 0; 2004 LastTD->HwTD.Buffer[3] = 0; 2005 LastTD->HwTD.Buffer[4] = 0; 2006 2007 LastTD->NextHcdTD = NULL; 2008 LastTD->HwTD.NextTD = TERMINATE_POINTER; 2009 LastTD->HwTD.AlternateNextTD = TERMINATE_POINTER; 2010 2011 LastTD->HwTD.Token.AsULONG = 0; 2012 LastTD->HwTD.Token.ErrorCounter = 3; 2013 2014 FirstTD->AltNextHcdTD = LastTD; 2015 FirstTD->HwTD.AlternateNextTD = LastTD->PhysicalAddress; 2016 2017 PrevTD = FirstTD; 2018 LinkTD = FirstTD; 2019 2020 while (TransferedLen < TransferParameters->TransferBufferLength) 2021 { 2022 TD = EHCI_AllocTd(EhciExtension, EhciEndpoint); 2023 2024 if (!TD) 2025 { 2026 RegPacket.UsbPortBugCheck(EhciExtension); 2027 return MP_STATUS_FAILURE; 2028 } 2029 2030 LinkTD = TD; 2031 2032 EhciTransfer->PendingTDs++; 2033 2034 TD->TdFlags |= EHCI_HCD_TD_FLAG_PROCESSED; 2035 TD->EhciTransfer = EhciTransfer; 2036 2037 TD->HwTD.Buffer[0] = 0; 2038 TD->HwTD.Buffer[1] = 0; 2039 TD->HwTD.Buffer[2] = 0; 2040 TD->HwTD.Buffer[3] = 0; 2041 TD->HwTD.Buffer[4] = 0; 2042 2043 TD->NextHcdTD = NULL; 2044 2045 TD->HwTD.NextTD = TERMINATE_POINTER; 2046 TD->HwTD.AlternateNextTD = TERMINATE_POINTER; 2047 2048 TD->HwTD.Token.AsULONG = 0; 2049 TD->HwTD.Token.ErrorCounter = 3; 2050 2051 PrevTD->NextHcdTD = TD; 2052 PrevTD->HwTD.NextTD = TD->PhysicalAddress; 2053 2054 if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) 2055 TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_IN; 2056 else 2057 TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_OUT; 2058 2059 TD->HwTD.Token.DataToggle = DataToggle; 2060 TD->HwTD.Token.Status = (UCHAR)EHCI_TOKEN_STATUS_ACTIVE; 2061 2062 if (DataToggle) 2063 TD->HwTD.Token.DataToggle = 1; 2064 else 2065 TD->HwTD.Token.DataToggle = 0; 2066 2067 TD->AltNextHcdTD = LastTD; 2068 TD->HwTD.AlternateNextTD = LastTD->PhysicalAddress; 2069 2070 TransferedLen = EHCI_MapAsyncTransferToTd(EhciExtension, 2071 EhciEndpoint->EndpointProperties.MaxPacketSize, 2072 TransferedLen, 2073 &DataToggle, 2074 EhciTransfer, 2075 TD, 2076 SgList); 2077 2078 PrevTD = TD; 2079 } 2080 2081 LinkTD->NextHcdTD = LastTD; 2082 LinkTD->HwTD.NextTD = LastTD->PhysicalAddress; 2083 2084 LastTD->HwTD.Buffer[0] = 0; 2085 LastTD->LengthThisTD = 0; 2086 2087 Token.AsULONG = 0; 2088 Token.Status = (UCHAR)EHCI_TOKEN_STATUS_ACTIVE; 2089 Token.InterruptOnComplete = 1; 2090 Token.DataToggle = 1; 2091 2092 if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) 2093 Token.PIDCode = EHCI_TD_TOKEN_PID_OUT; 2094 else 2095 Token.PIDCode = EHCI_TD_TOKEN_PID_IN; 2096 2097 LastTD->HwTD.Token = Token; 2098 2099 LastTD->NextHcdTD = EhciEndpoint->HcdTailP; 2100 LastTD->HwTD.NextTD = EhciEndpoint->HcdTailP->PhysicalAddress; 2101 2102 EHCI_EnableAsyncList(EhciExtension); 2103 EHCI_LinkTransferToQueue(EhciExtension, EhciEndpoint, FirstTD); 2104 2105 ASSERT(EhciEndpoint->HcdTailP->NextHcdTD == NULL); 2106 ASSERT(EhciEndpoint->HcdTailP->AltNextHcdTD == NULL); 2107 2108 return MP_STATUS_SUCCESS; 2109 } 2110 2111 MPSTATUS 2112 NTAPI 2113 EHCI_BulkTransfer(IN PEHCI_EXTENSION EhciExtension, 2114 IN PEHCI_ENDPOINT EhciEndpoint, 2115 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, 2116 IN PEHCI_TRANSFER EhciTransfer, 2117 IN PUSBPORT_SCATTER_GATHER_LIST SgList) 2118 { 2119 PEHCI_HCD_TD PrevTD; 2120 PEHCI_HCD_TD FirstTD; 2121 PEHCI_HCD_TD TD; 2122 ULONG TransferedLen; 2123 2124 DPRINT_EHCI("EHCI_BulkTransfer: EhciEndpoint - %p, EhciTransfer - %p\n", 2125 EhciEndpoint, 2126 EhciTransfer); 2127 2128 if (((TransferParameters->TransferBufferLength / 2129 ((EHCI_MAX_QTD_BUFFER_PAGES - 1) * PAGE_SIZE)) + 1) > EhciEndpoint->RemainTDs) 2130 { 2131 DPRINT1("EHCI_BulkTransfer: return MP_STATUS_FAILURE\n"); 2132 return MP_STATUS_FAILURE; 2133 } 2134 2135 EhciExtension->PendingTransfers++; 2136 EhciEndpoint->PendingTDs++; 2137 2138 EhciTransfer->TransferOnAsyncList = 1; 2139 2140 TransferedLen = 0; 2141 PrevTD = NULL; 2142 2143 if (TransferParameters->TransferBufferLength) 2144 { 2145 while (TransferedLen < TransferParameters->TransferBufferLength) 2146 { 2147 TD = EHCI_AllocTd(EhciExtension, EhciEndpoint); 2148 2149 if (!TD) 2150 { 2151 RegPacket.UsbPortBugCheck(EhciExtension); 2152 return MP_STATUS_FAILURE; 2153 } 2154 2155 EhciTransfer->PendingTDs++; 2156 2157 TD->TdFlags |= EHCI_HCD_TD_FLAG_PROCESSED; 2158 TD->EhciTransfer = EhciTransfer; 2159 2160 TD->HwTD.Buffer[0] = 0; 2161 TD->HwTD.Buffer[1] = 0; 2162 TD->HwTD.Buffer[2] = 0; 2163 TD->HwTD.Buffer[3] = 0; 2164 TD->HwTD.Buffer[4] = 0; 2165 2166 TD->NextHcdTD = NULL; 2167 TD->HwTD.NextTD = TERMINATE_POINTER; 2168 TD->HwTD.AlternateNextTD = TERMINATE_POINTER; 2169 2170 TD->HwTD.Token.AsULONG = 0; 2171 TD->HwTD.Token.ErrorCounter = 3; 2172 2173 if (EhciTransfer->PendingTDs == 1) 2174 { 2175 FirstTD = TD; 2176 } 2177 else 2178 { 2179 PrevTD->HwTD.NextTD = TD->PhysicalAddress; 2180 PrevTD->NextHcdTD = TD; 2181 } 2182 2183 TD->HwTD.AlternateNextTD = EhciEndpoint->HcdTailP->PhysicalAddress; 2184 TD->AltNextHcdTD = EhciEndpoint->HcdTailP; 2185 2186 TD->HwTD.Token.InterruptOnComplete = 1; 2187 2188 if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) 2189 TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_IN; 2190 else 2191 TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_OUT; 2192 2193 TD->HwTD.Token.Status = (UCHAR)EHCI_TOKEN_STATUS_ACTIVE; 2194 TD->HwTD.Token.DataToggle = 1; 2195 2196 TransferedLen = EHCI_MapAsyncTransferToTd(EhciExtension, 2197 EhciEndpoint->EndpointProperties.MaxPacketSize, 2198 TransferedLen, 2199 0, 2200 EhciTransfer, 2201 TD, 2202 SgList); 2203 2204 PrevTD = TD; 2205 } 2206 } 2207 else 2208 { 2209 TD = EHCI_AllocTd(EhciExtension, EhciEndpoint); 2210 2211 if (!TD) 2212 { 2213 RegPacket.UsbPortBugCheck(EhciExtension); 2214 return MP_STATUS_FAILURE; 2215 } 2216 2217 EhciTransfer->PendingTDs++; 2218 2219 TD->TdFlags |= EHCI_HCD_TD_FLAG_PROCESSED; 2220 TD->EhciTransfer = EhciTransfer; 2221 2222 TD->HwTD.Buffer[0] = 0; 2223 TD->HwTD.Buffer[1] = 0; 2224 TD->HwTD.Buffer[2] = 0; 2225 TD->HwTD.Buffer[3] = 0; 2226 TD->HwTD.Buffer[4] = 0; 2227 2228 TD->HwTD.NextTD = TERMINATE_POINTER; 2229 TD->HwTD.AlternateNextTD = TERMINATE_POINTER; 2230 2231 TD->HwTD.Token.AsULONG = 0; 2232 TD->HwTD.Token.ErrorCounter = 3; 2233 2234 TD->NextHcdTD = NULL; 2235 2236 ASSERT(EhciTransfer->PendingTDs == 1); 2237 2238 FirstTD = TD; 2239 2240 TD->HwTD.AlternateNextTD = EhciEndpoint->HcdTailP->PhysicalAddress; 2241 TD->AltNextHcdTD = EhciEndpoint->HcdTailP; 2242 2243 TD->HwTD.Token.InterruptOnComplete = 1; 2244 2245 if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) 2246 TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_IN; 2247 else 2248 TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_OUT; 2249 2250 TD->HwTD.Buffer[0] = TD->PhysicalAddress; 2251 2252 TD->HwTD.Token.Status = (UCHAR)EHCI_TOKEN_STATUS_ACTIVE; 2253 TD->HwTD.Token.DataToggle = 1; 2254 2255 TD->LengthThisTD = 0; 2256 } 2257 2258 TD->HwTD.NextTD = EhciEndpoint->HcdTailP->PhysicalAddress; 2259 TD->NextHcdTD = EhciEndpoint->HcdTailP; 2260 2261 EHCI_EnableAsyncList(EhciExtension); 2262 EHCI_LinkTransferToQueue(EhciExtension, EhciEndpoint, FirstTD); 2263 2264 ASSERT(EhciEndpoint->HcdTailP->NextHcdTD == 0); 2265 ASSERT(EhciEndpoint->HcdTailP->AltNextHcdTD == 0); 2266 2267 return MP_STATUS_SUCCESS; 2268 } 2269 2270 MPSTATUS 2271 NTAPI 2272 EHCI_InterruptTransfer(IN PEHCI_EXTENSION EhciExtension, 2273 IN PEHCI_ENDPOINT EhciEndpoint, 2274 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, 2275 IN PEHCI_TRANSFER EhciTransfer, 2276 IN PUSBPORT_SCATTER_GATHER_LIST SgList) 2277 { 2278 PEHCI_HCD_TD TD; 2279 PEHCI_HCD_TD FirstTD; 2280 PEHCI_HCD_TD PrevTD = NULL; 2281 ULONG TransferedLen = 0; 2282 2283 DPRINT_EHCI("EHCI_InterruptTransfer: EhciEndpoint - %p, EhciTransfer - %p\n", 2284 EhciEndpoint, 2285 EhciTransfer); 2286 2287 if (!EhciEndpoint->RemainTDs) 2288 { 2289 DPRINT1("EHCI_InterruptTransfer: EhciEndpoint - %p\n", EhciEndpoint); 2290 DbgBreakPoint(); 2291 return MP_STATUS_FAILURE; 2292 } 2293 2294 EhciEndpoint->PendingTDs++; 2295 2296 if (!TransferParameters->TransferBufferLength) 2297 { 2298 DPRINT1("EHCI_InterruptTransfer: EhciEndpoint - %p\n", EhciEndpoint); 2299 DbgBreakPoint(); 2300 return MP_STATUS_FAILURE; 2301 } 2302 2303 while (TransferedLen < TransferParameters->TransferBufferLength) 2304 { 2305 TD = EHCI_AllocTd(EhciExtension, EhciEndpoint); 2306 2307 if (!TD) 2308 { 2309 DPRINT1("EHCI_InterruptTransfer: EhciEndpoint - %p\n", EhciEndpoint); 2310 RegPacket.UsbPortBugCheck(EhciExtension); 2311 return MP_STATUS_FAILURE; 2312 } 2313 2314 EhciTransfer->PendingTDs++; 2315 2316 TD->TdFlags |= EHCI_HCD_TD_FLAG_PROCESSED; 2317 TD->EhciTransfer = EhciTransfer; 2318 2319 TD->HwTD.Buffer[0] = 0; 2320 TD->HwTD.Buffer[1] = 0; 2321 TD->HwTD.Buffer[2] = 0; 2322 TD->HwTD.Buffer[3] = 0; 2323 TD->HwTD.Buffer[4] = 0; 2324 2325 TD->HwTD.NextTD = TERMINATE_POINTER; 2326 TD->HwTD.AlternateNextTD = TERMINATE_POINTER; 2327 2328 TD->HwTD.Token.AsULONG = 0; 2329 TD->HwTD.Token.ErrorCounter = 3; 2330 2331 TD->NextHcdTD = NULL; 2332 2333 if (EhciTransfer->PendingTDs == 1) 2334 { 2335 FirstTD = TD; 2336 } 2337 else if (PrevTD) 2338 { 2339 PrevTD->HwTD.NextTD = TD->PhysicalAddress; 2340 PrevTD->NextHcdTD = TD; 2341 } 2342 2343 if (TransferParameters->TransferFlags & USBD_TRANSFER_DIRECTION_IN) 2344 TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_IN; 2345 else 2346 TD->HwTD.Token.PIDCode = EHCI_TD_TOKEN_PID_OUT; 2347 2348 TD->HwTD.Token.Status = (UCHAR)EHCI_TOKEN_STATUS_ACTIVE; 2349 TD->HwTD.Token.DataToggle = 1; 2350 2351 TransferedLen = EHCI_MapAsyncTransferToTd(EhciExtension, 2352 EhciEndpoint->EndpointProperties.TotalMaxPacketSize, 2353 TransferedLen, 2354 NULL, 2355 EhciTransfer, 2356 TD, 2357 SgList); 2358 2359 PrevTD = TD; 2360 } 2361 2362 TD->HwTD.Token.InterruptOnComplete = 1; 2363 2364 DPRINT_EHCI("EHCI_InterruptTransfer: PendingTDs - %x, TD->PhysicalAddress - %p, FirstTD - %p\n", 2365 EhciTransfer->PendingTDs, 2366 TD->PhysicalAddress, 2367 FirstTD); 2368 2369 TD->HwTD.NextTD = EhciEndpoint->HcdTailP->PhysicalAddress; 2370 TD->NextHcdTD = EhciEndpoint->HcdTailP; 2371 2372 EHCI_LinkTransferToQueue(EhciExtension, EhciEndpoint, FirstTD); 2373 2374 ASSERT(EhciEndpoint->HcdTailP->NextHcdTD == NULL); 2375 ASSERT(EhciEndpoint->HcdTailP->AltNextHcdTD == NULL); 2376 2377 EHCI_EnablePeriodicList(EhciExtension); 2378 2379 return MP_STATUS_SUCCESS; 2380 } 2381 2382 MPSTATUS 2383 NTAPI 2384 EHCI_SubmitTransfer(IN PVOID ehciExtension, 2385 IN PVOID ehciEndpoint, 2386 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, 2387 IN PVOID ehciTransfer, 2388 IN PUSBPORT_SCATTER_GATHER_LIST SgList) 2389 { 2390 PEHCI_EXTENSION EhciExtension = ehciExtension; 2391 PEHCI_ENDPOINT EhciEndpoint = ehciEndpoint; 2392 PEHCI_TRANSFER EhciTransfer = ehciTransfer; 2393 MPSTATUS MPStatus; 2394 2395 DPRINT_EHCI("EHCI_SubmitTransfer: EhciEndpoint - %p, EhciTransfer - %p\n", 2396 EhciEndpoint, 2397 EhciTransfer); 2398 2399 RtlZeroMemory(EhciTransfer, sizeof(EHCI_TRANSFER)); 2400 2401 EhciTransfer->TransferParameters = TransferParameters; 2402 EhciTransfer->USBDStatus = USBD_STATUS_SUCCESS; 2403 EhciTransfer->EhciEndpoint = EhciEndpoint; 2404 2405 switch (EhciEndpoint->EndpointProperties.TransferType) 2406 { 2407 case USBPORT_TRANSFER_TYPE_CONTROL: 2408 MPStatus = EHCI_ControlTransfer(EhciExtension, 2409 EhciEndpoint, 2410 TransferParameters, 2411 EhciTransfer, 2412 SgList); 2413 break; 2414 2415 case USBPORT_TRANSFER_TYPE_BULK: 2416 MPStatus = EHCI_BulkTransfer(EhciExtension, 2417 EhciEndpoint, 2418 TransferParameters, 2419 EhciTransfer, 2420 SgList); 2421 break; 2422 2423 case USBPORT_TRANSFER_TYPE_INTERRUPT: 2424 MPStatus = EHCI_InterruptTransfer(EhciExtension, 2425 EhciEndpoint, 2426 TransferParameters, 2427 EhciTransfer, 2428 SgList); 2429 break; 2430 2431 default: 2432 DbgBreakPoint(); 2433 MPStatus = MP_STATUS_NOT_SUPPORTED; 2434 break; 2435 } 2436 2437 return MPStatus; 2438 } 2439 2440 MPSTATUS 2441 NTAPI 2442 EHCI_SubmitIsoTransfer(IN PVOID ehciExtension, 2443 IN PVOID ehciEndpoint, 2444 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters, 2445 IN PVOID ehciTransfer, 2446 IN PVOID isoParameters) 2447 { 2448 DPRINT1("EHCI_SubmitIsoTransfer: UNIMPLEMENTED. FIXME\n"); 2449 return MP_STATUS_SUCCESS; 2450 } 2451 2452 VOID 2453 NTAPI 2454 EHCI_AbortIsoTransfer(IN PEHCI_EXTENSION EhciExtension, 2455 IN PEHCI_ENDPOINT EhciEndpoint, 2456 IN PEHCI_TRANSFER EhciTransfer) 2457 { 2458 DPRINT1("EHCI_AbortIsoTransfer: UNIMPLEMENTED. FIXME\n"); 2459 } 2460 2461 VOID 2462 NTAPI 2463 EHCI_AbortAsyncTransfer(IN PEHCI_EXTENSION EhciExtension, 2464 IN PEHCI_ENDPOINT EhciEndpoint, 2465 IN PEHCI_TRANSFER EhciTransfer) 2466 { 2467 PEHCI_HCD_QH QH; 2468 PEHCI_HCD_TD TD; 2469 ULONG TransferLength; 2470 PEHCI_HCD_TD CurrentTD; 2471 PEHCI_TRANSFER CurrentTransfer; 2472 ULONG FirstTdPA; 2473 PEHCI_HCD_TD LastTD; 2474 PEHCI_HCD_TD PrevTD; 2475 ULONG NextTD; 2476 2477 DPRINT("EHCI_AbortAsyncTransfer: EhciEndpoint - %p, EhciTransfer - %p\n", 2478 EhciEndpoint, 2479 EhciTransfer); 2480 2481 QH = EhciEndpoint->QH; 2482 TD = EhciEndpoint->HcdHeadP; 2483 2484 ASSERT(EhciEndpoint->PendingTDs); 2485 EhciEndpoint->PendingTDs--; 2486 2487 if (TD->EhciTransfer == EhciTransfer) 2488 { 2489 TransferLength = 0; 2490 2491 while (TD != EhciEndpoint->HcdTailP && 2492 TD->EhciTransfer == EhciTransfer) 2493 { 2494 TransferLength += TD->LengthThisTD - TD->HwTD.Token.TransferBytes; 2495 2496 TD->HwTD.NextTD = 0; 2497 TD->HwTD.AlternateNextTD = 0; 2498 2499 TD->TdFlags = 0; 2500 TD->EhciTransfer = NULL; 2501 2502 EhciEndpoint->RemainTDs++; 2503 2504 TD = TD->NextHcdTD; 2505 } 2506 2507 if (TransferLength) 2508 EhciTransfer->TransferLen += TransferLength; 2509 2510 QH->sqh.HwQH.CurrentTD = EhciEndpoint->DmaBufferPA; 2511 QH->sqh.HwQH.NextTD = TD->PhysicalAddress; 2512 QH->sqh.HwQH.AlternateNextTD = TD->HwTD.AlternateNextTD; 2513 2514 QH->sqh.HwQH.Token.TransferBytes = 0; 2515 QH->sqh.HwQH.Token.Status = (UCHAR)~(EHCI_TOKEN_STATUS_ACTIVE | 2516 EHCI_TOKEN_STATUS_HALTED); 2517 2518 EhciEndpoint->HcdHeadP = TD; 2519 } 2520 else 2521 { 2522 DPRINT("EHCI_AbortAsyncTransfer: TD->EhciTransfer - %p\n", TD->EhciTransfer); 2523 2524 CurrentTD = RegPacket.UsbPortGetMappedVirtualAddress(QH->sqh.HwQH.CurrentTD, 2525 EhciExtension, 2526 EhciEndpoint); 2527 2528 CurrentTransfer = CurrentTD->EhciTransfer; 2529 TD = EhciEndpoint->HcdHeadP; 2530 2531 while (TD && TD->EhciTransfer != EhciTransfer) 2532 { 2533 PrevTD = TD; 2534 TD = TD->NextHcdTD; 2535 } 2536 2537 FirstTdPA = TD->PhysicalAddress; 2538 2539 while (TD && TD->EhciTransfer == EhciTransfer) 2540 { 2541 TD->HwTD.NextTD = 0; 2542 TD->HwTD.AlternateNextTD = 0; 2543 2544 TD->TdFlags = 0; 2545 TD->EhciTransfer = NULL; 2546 2547 EhciEndpoint->RemainTDs++; 2548 2549 TD = TD->NextHcdTD; 2550 } 2551 2552 LastTD = TD; 2553 NextTD = LastTD->PhysicalAddress + FIELD_OFFSET(EHCI_HCD_TD, HwTD.NextTD); 2554 2555 PrevTD->HwTD.NextTD = LastTD->PhysicalAddress; 2556 PrevTD->HwTD.AlternateNextTD = LastTD->PhysicalAddress; 2557 2558 PrevTD->NextHcdTD = LastTD; 2559 PrevTD->AltNextHcdTD = LastTD; 2560 2561 if (CurrentTransfer == EhciTransfer) 2562 { 2563 QH->sqh.HwQH.CurrentTD = EhciEndpoint->DmaBufferPA; 2564 2565 QH->sqh.HwQH.Token.Status = (UCHAR)~EHCI_TOKEN_STATUS_ACTIVE; 2566 QH->sqh.HwQH.Token.TransferBytes = 0; 2567 2568 QH->sqh.HwQH.NextTD = NextTD; 2569 QH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; 2570 2571 return; 2572 } 2573 2574 if (PrevTD->EhciTransfer == CurrentTransfer) 2575 { 2576 if (QH->sqh.HwQH.NextTD == FirstTdPA) 2577 QH->sqh.HwQH.NextTD = NextTD; 2578 2579 if (QH->sqh.HwQH.AlternateNextTD == FirstTdPA) 2580 QH->sqh.HwQH.AlternateNextTD = NextTD; 2581 2582 for (TD = EhciEndpoint->HcdHeadP; 2583 TD; 2584 TD = TD->NextHcdTD) 2585 { 2586 if (TD->EhciTransfer == CurrentTransfer) 2587 { 2588 TD->HwTD.AlternateNextTD = NextTD; 2589 TD->AltNextHcdTD = LastTD; 2590 } 2591 } 2592 } 2593 } 2594 } 2595 2596 VOID 2597 NTAPI 2598 EHCI_AbortTransfer(IN PVOID ehciExtension, 2599 IN PVOID ehciEndpoint, 2600 IN PVOID ehciTransfer, 2601 IN PULONG CompletedLength) 2602 { 2603 PEHCI_EXTENSION EhciExtension = ehciExtension; 2604 PEHCI_ENDPOINT EhciEndpoint = ehciEndpoint; 2605 PEHCI_TRANSFER EhciTransfer = ehciTransfer; 2606 ULONG TransferType; 2607 2608 DPRINT("EHCI_AbortTransfer: EhciTransfer - %p, CompletedLength - %x\n", 2609 EhciTransfer, 2610 CompletedLength); 2611 2612 TransferType = EhciEndpoint->EndpointProperties.TransferType; 2613 2614 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 2615 EHCI_AbortIsoTransfer(EhciExtension, EhciEndpoint, EhciTransfer); 2616 else 2617 EHCI_AbortAsyncTransfer(EhciExtension, EhciEndpoint, EhciTransfer); 2618 } 2619 2620 ULONG 2621 NTAPI 2622 EHCI_GetEndpointState(IN PVOID ehciExtension, 2623 IN PVOID ehciEndpoint) 2624 { 2625 DPRINT1("EHCI_GetEndpointState: UNIMPLEMENTED. FIXME\n"); 2626 return 0; 2627 } 2628 2629 VOID 2630 NTAPI 2631 EHCI_RemoveQhFromPeriodicList(IN PEHCI_EXTENSION EhciExtension, 2632 IN PEHCI_ENDPOINT EhciEndpoint) 2633 { 2634 PEHCI_HCD_QH QH; 2635 PEHCI_HCD_QH NextHead; 2636 ULONG NextQhPA; 2637 PEHCI_HCD_QH PrevHead; 2638 2639 QH = EhciEndpoint->QH; 2640 2641 if (!(QH->sqh.QhFlags & EHCI_QH_FLAG_IN_SCHEDULE)) 2642 return; 2643 2644 DPRINT("EHCI_RemoveQhFromPeriodicList: EhciEndpoint - %p, QH - %X, EhciEndpoint->StaticQH - %p\n", 2645 EhciEndpoint, 2646 QH, 2647 EhciEndpoint->StaticQH); 2648 2649 NextHead = QH->sqh.NextHead; 2650 PrevHead = QH->sqh.PrevHead; 2651 2652 PrevHead->sqh.NextHead = NextHead; 2653 2654 if (NextHead) 2655 { 2656 if (!(NextHead->sqh.QhFlags & EHCI_QH_FLAG_STATIC)) 2657 NextHead->sqh.PrevHead = PrevHead; 2658 2659 NextQhPA = NextHead->sqh.PhysicalAddress; 2660 NextQhPA &= LINK_POINTER_MASK + TERMINATE_POINTER; 2661 NextQhPA |= (EHCI_LINK_TYPE_QH << 1); 2662 2663 PrevHead->sqh.HwQH.HorizontalLink.AsULONG = NextQhPA; 2664 } 2665 else 2666 { 2667 PrevHead->sqh.HwQH.HorizontalLink.Terminate = 1; 2668 } 2669 2670 QH->sqh.QhFlags &= ~EHCI_QH_FLAG_IN_SCHEDULE; 2671 2672 QH->sqh.NextHead = NULL; 2673 QH->sqh.PrevHead = NULL; 2674 } 2675 2676 VOID 2677 NTAPI 2678 EHCI_RemoveQhFromAsyncList(IN PEHCI_EXTENSION EhciExtension, 2679 IN PEHCI_HCD_QH QH) 2680 { 2681 PEHCI_HCD_QH NextHead; 2682 ULONG NextHeadPA; 2683 PEHCI_HCD_QH PrevHead; 2684 PEHCI_STATIC_QH AsyncHead; 2685 ULONG AsyncHeadPA; 2686 2687 DPRINT("EHCI_RemoveQhFromAsyncList: QH - %p\n", QH); 2688 2689 if (QH->sqh.QhFlags & EHCI_QH_FLAG_IN_SCHEDULE) 2690 { 2691 NextHead = QH->sqh.NextHead; 2692 PrevHead = QH->sqh.PrevHead; 2693 2694 AsyncHead = EhciExtension->AsyncHead; 2695 2696 AsyncHeadPA = AsyncHead->PhysicalAddress; 2697 AsyncHeadPA &= LINK_POINTER_MASK + TERMINATE_POINTER; 2698 AsyncHeadPA |= (EHCI_LINK_TYPE_QH << 1); 2699 2700 NextHeadPA = NextHead->sqh.PhysicalAddress; 2701 NextHeadPA &= LINK_POINTER_MASK + TERMINATE_POINTER; 2702 NextHeadPA |= (EHCI_LINK_TYPE_QH << 1); 2703 2704 PrevHead->sqh.HwQH.HorizontalLink.AsULONG = NextHeadPA; 2705 2706 PrevHead->sqh.NextHead = NextHead; 2707 NextHead->sqh.PrevHead = PrevHead; 2708 2709 EHCI_FlushAsyncCache(EhciExtension); 2710 2711 if (READ_REGISTER_ULONG(&EhciExtension->OperationalRegs->AsyncListBase) == 2712 QH->sqh.PhysicalAddress) 2713 { 2714 WRITE_REGISTER_ULONG(&EhciExtension->OperationalRegs->AsyncListBase, 2715 AsyncHeadPA); 2716 } 2717 2718 QH->sqh.QhFlags &= ~EHCI_QH_FLAG_IN_SCHEDULE; 2719 } 2720 } 2721 2722 VOID 2723 NTAPI 2724 EHCI_InsertQhInPeriodicList(IN PEHCI_EXTENSION EhciExtension, 2725 IN PEHCI_ENDPOINT EhciEndpoint) 2726 { 2727 PEHCI_STATIC_QH StaticQH; 2728 PEHCI_HCD_QH QH; 2729 ULONG QhPA; 2730 PEHCI_HCD_QH NextHead; 2731 PEHCI_HCD_QH PrevHead; 2732 2733 QH = EhciEndpoint->QH; 2734 StaticQH = EhciEndpoint->StaticQH; 2735 2736 ASSERT((QH->sqh.QhFlags & EHCI_QH_FLAG_IN_SCHEDULE) == 0); 2737 ASSERT(StaticQH->QhFlags & EHCI_QH_FLAG_STATIC); 2738 2739 NextHead = StaticQH->NextHead; 2740 2741 QH->sqh.Period = EhciEndpoint->EndpointProperties.Period; 2742 QH->sqh.Ordinal = EhciEndpoint->EndpointProperties.Reserved6; 2743 2744 DPRINT("EHCI_InsertQhInPeriodicList: EhciEndpoint - %p, QH - %X, EhciEndpoint->StaticQH - %p\n", 2745 EhciEndpoint, 2746 QH, 2747 EhciEndpoint->StaticQH); 2748 2749 PrevHead = (PEHCI_HCD_QH)StaticQH; 2750 2751 if ((StaticQH->QhFlags & EHCI_QH_FLAG_STATIC) && 2752 (!NextHead || (NextHead->sqh.QhFlags & EHCI_QH_FLAG_STATIC))) 2753 { 2754 DPRINT("EHCI_InsertQhInPeriodicList: StaticQH - %p, StaticQH->NextHead - %p\n", 2755 StaticQH, 2756 StaticQH->NextHead); 2757 } 2758 else 2759 { 2760 while (NextHead && 2761 !(NextHead->sqh.QhFlags & EHCI_QH_FLAG_STATIC) && 2762 QH->sqh.Ordinal > NextHead->sqh.Ordinal) 2763 { 2764 PrevHead = NextHead; 2765 NextHead = NextHead->sqh.NextHead; 2766 } 2767 } 2768 2769 QH->sqh.NextHead = NextHead; 2770 QH->sqh.PrevHead = PrevHead; 2771 2772 if (NextHead && !(NextHead->sqh.QhFlags & EHCI_QH_FLAG_STATIC)) 2773 NextHead->sqh.PrevHead = QH; 2774 2775 QH->sqh.QhFlags |= EHCI_QH_FLAG_IN_SCHEDULE; 2776 QH->sqh.HwQH.HorizontalLink = PrevHead->sqh.HwQH.HorizontalLink; 2777 2778 PrevHead->sqh.NextHead = QH; 2779 2780 QhPA = QH->sqh.PhysicalAddress; 2781 QhPA &= LINK_POINTER_MASK + TERMINATE_POINTER; 2782 QhPA |= (EHCI_LINK_TYPE_QH << 1); 2783 2784 PrevHead->sqh.HwQH.HorizontalLink.AsULONG = QhPA; 2785 } 2786 2787 VOID 2788 NTAPI 2789 EHCI_InsertQhInAsyncList(IN PEHCI_EXTENSION EhciExtension, 2790 IN PEHCI_HCD_QH QH) 2791 { 2792 PEHCI_STATIC_QH AsyncHead; 2793 ULONG QhPA; 2794 PEHCI_HCD_QH NextHead; 2795 2796 DPRINT("EHCI_InsertQhInAsyncList: QH - %p\n", QH); 2797 2798 ASSERT((QH->sqh.QhFlags & EHCI_QH_FLAG_IN_SCHEDULE) == 0); 2799 ASSERT((QH->sqh.QhFlags & EHCI_QH_FLAG_NUKED) == 0); 2800 2801 AsyncHead = EhciExtension->AsyncHead; 2802 NextHead = AsyncHead->NextHead; 2803 2804 QH->sqh.HwQH.HorizontalLink = AsyncHead->HwQH.HorizontalLink; 2805 QH->sqh.QhFlags |= EHCI_QH_FLAG_IN_SCHEDULE; 2806 QH->sqh.NextHead = NextHead; 2807 QH->sqh.PrevHead = (PEHCI_HCD_QH)AsyncHead; 2808 2809 NextHead->sqh.PrevHead = QH; 2810 2811 QhPA = QH->sqh.PhysicalAddress; 2812 QhPA &= LINK_POINTER_MASK + TERMINATE_POINTER; 2813 QhPA |= (EHCI_LINK_TYPE_QH << 1); 2814 2815 AsyncHead->HwQH.HorizontalLink.AsULONG = QhPA; 2816 2817 AsyncHead->NextHead = QH; 2818 } 2819 2820 VOID 2821 NTAPI 2822 EHCI_SetIsoEndpointState(IN PEHCI_EXTENSION EhciExtension, 2823 IN PEHCI_ENDPOINT EhciEndpoint, 2824 IN ULONG EndpointState) 2825 { 2826 DPRINT1("EHCI_SetIsoEndpointState: UNIMPLEMENTED. FIXME\n"); 2827 } 2828 2829 VOID 2830 NTAPI 2831 EHCI_SetAsyncEndpointState(IN PEHCI_EXTENSION EhciExtension, 2832 IN PEHCI_ENDPOINT EhciEndpoint, 2833 IN ULONG EndpointState) 2834 { 2835 PEHCI_HCD_QH QH; 2836 ULONG TransferType; 2837 2838 DPRINT("EHCI_SetAsyncEndpointState: EhciEndpoint - %p, EndpointState - %x\n", 2839 EhciEndpoint, 2840 EndpointState); 2841 2842 QH = EhciEndpoint->QH; 2843 2844 TransferType = EhciEndpoint->EndpointProperties.TransferType; 2845 2846 switch (EndpointState) 2847 { 2848 case USBPORT_ENDPOINT_PAUSED: 2849 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 2850 EHCI_RemoveQhFromPeriodicList(EhciExtension, EhciEndpoint); 2851 else 2852 EHCI_RemoveQhFromAsyncList(EhciExtension, EhciEndpoint->QH); 2853 2854 break; 2855 2856 case USBPORT_ENDPOINT_ACTIVE: 2857 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 2858 EHCI_InsertQhInPeriodicList(EhciExtension, EhciEndpoint); 2859 else 2860 EHCI_InsertQhInAsyncList(EhciExtension, EhciEndpoint->QH); 2861 2862 break; 2863 2864 case USBPORT_ENDPOINT_REMOVE: 2865 QH->sqh.QhFlags |= EHCI_QH_FLAG_CLOSED; 2866 2867 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 2868 EHCI_RemoveQhFromPeriodicList(EhciExtension, EhciEndpoint); 2869 else 2870 EHCI_RemoveQhFromAsyncList(EhciExtension, EhciEndpoint->QH); 2871 2872 break; 2873 2874 default: 2875 DbgBreakPoint(); 2876 break; 2877 } 2878 2879 EhciEndpoint->EndpointState = EndpointState; 2880 } 2881 2882 VOID 2883 NTAPI 2884 EHCI_SetEndpointState(IN PVOID ehciExtension, 2885 IN PVOID ehciEndpoint, 2886 IN ULONG EndpointState) 2887 { 2888 PEHCI_ENDPOINT EhciEndpoint; 2889 ULONG TransferType; 2890 2891 DPRINT("EHCI_SetEndpointState: ... \n"); 2892 2893 EhciEndpoint = ehciEndpoint; 2894 TransferType = EhciEndpoint->EndpointProperties.TransferType; 2895 2896 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL || 2897 TransferType == USBPORT_TRANSFER_TYPE_BULK || 2898 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 2899 { 2900 EHCI_SetAsyncEndpointState((PEHCI_EXTENSION)ehciExtension, 2901 EhciEndpoint, 2902 EndpointState); 2903 } 2904 else if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 2905 { 2906 EHCI_SetIsoEndpointState((PEHCI_EXTENSION)ehciExtension, 2907 EhciEndpoint, 2908 EndpointState); 2909 } 2910 else 2911 { 2912 RegPacket.UsbPortBugCheck(ehciExtension); 2913 } 2914 } 2915 2916 VOID 2917 NTAPI 2918 EHCI_InterruptNextSOF(IN PVOID ehciExtension) 2919 { 2920 PEHCI_EXTENSION EhciExtension = ehciExtension; 2921 2922 DPRINT_EHCI("EHCI_InterruptNextSOF: ... \n"); 2923 2924 RegPacket.UsbPortInvalidateController(EhciExtension, 2925 USBPORT_INVALIDATE_CONTROLLER_SOFT_INTERRUPT); 2926 } 2927 2928 USBD_STATUS 2929 NTAPI 2930 EHCI_GetErrorFromTD(IN PEHCI_HCD_TD TD) 2931 { 2932 EHCI_TD_TOKEN Token; 2933 2934 DPRINT_EHCI("EHCI_GetErrorFromTD: ... \n"); 2935 2936 ASSERT(TD->HwTD.Token.Status & EHCI_TOKEN_STATUS_HALTED); 2937 2938 Token = TD->HwTD.Token; 2939 2940 if (Token.Status & EHCI_TOKEN_STATUS_TRANSACTION_ERROR) 2941 { 2942 DPRINT("EHCI_GetErrorFromTD: TD - %p, TRANSACTION_ERROR\n", TD); 2943 return USBD_STATUS_XACT_ERROR; 2944 } 2945 2946 if (Token.Status & EHCI_TOKEN_STATUS_BABBLE_DETECTED) 2947 { 2948 DPRINT("EHCI_GetErrorFromTD: TD - %p, BABBLE_DETECTED\n", TD); 2949 return USBD_STATUS_BABBLE_DETECTED; 2950 } 2951 2952 if (Token.Status & EHCI_TOKEN_STATUS_DATA_BUFFER_ERROR) 2953 { 2954 DPRINT("EHCI_GetErrorFromTD: TD - %p, DATA_BUFFER_ERROR\n", TD); 2955 return USBD_STATUS_DATA_BUFFER_ERROR; 2956 } 2957 2958 if (Token.Status & EHCI_TOKEN_STATUS_MISSED_MICROFRAME) 2959 { 2960 DPRINT("EHCI_GetErrorFromTD: TD - %p, MISSED_MICROFRAME\n", TD); 2961 return USBD_STATUS_XACT_ERROR; 2962 } 2963 2964 DPRINT("EHCI_GetErrorFromTD: TD - %p, STALL_PID\n", TD); 2965 return USBD_STATUS_STALL_PID; 2966 } 2967 2968 VOID 2969 NTAPI 2970 EHCI_ProcessDoneAsyncTd(IN PEHCI_EXTENSION EhciExtension, 2971 IN PEHCI_HCD_TD TD) 2972 { 2973 PEHCI_TRANSFER EhciTransfer; 2974 PUSBPORT_TRANSFER_PARAMETERS TransferParameters; 2975 ULONG TransferType; 2976 PEHCI_ENDPOINT EhciEndpoint; 2977 ULONG LengthTransfered; 2978 USBD_STATUS USBDStatus; 2979 PEHCI_HW_REGISTERS OperationalRegs; 2980 EHCI_USB_COMMAND Command; 2981 2982 DPRINT_EHCI("EHCI_ProcessDoneAsyncTd: TD - %p\n", TD); 2983 2984 EhciTransfer = TD->EhciTransfer; 2985 2986 TransferParameters = EhciTransfer->TransferParameters; 2987 EhciTransfer->PendingTDs--; 2988 2989 EhciEndpoint = EhciTransfer->EhciEndpoint; 2990 2991 if (!(TD->TdFlags & EHCI_HCD_TD_FLAG_ACTIVE)) 2992 { 2993 2994 if (TD->HwTD.Token.Status & EHCI_TOKEN_STATUS_HALTED) 2995 USBDStatus = EHCI_GetErrorFromTD(TD); 2996 else 2997 USBDStatus = USBD_STATUS_SUCCESS; 2998 2999 LengthTransfered = TD->LengthThisTD - TD->HwTD.Token.TransferBytes; 3000 3001 if (TD->HwTD.Token.PIDCode != EHCI_TD_TOKEN_PID_SETUP) 3002 EhciTransfer->TransferLen += LengthTransfered; 3003 3004 if (USBDStatus != USBD_STATUS_SUCCESS) 3005 EhciTransfer->USBDStatus = USBDStatus; 3006 } 3007 3008 TD->HwTD.NextTD = 0; 3009 TD->HwTD.AlternateNextTD = 0; 3010 3011 TD->TdFlags = 0; 3012 TD->EhciTransfer = NULL; 3013 3014 EhciEndpoint->RemainTDs++; 3015 3016 if (EhciTransfer->PendingTDs == 0) 3017 { 3018 EhciEndpoint->PendingTDs--; 3019 3020 TransferType = EhciEndpoint->EndpointProperties.TransferType; 3021 3022 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL || 3023 TransferType == USBPORT_TRANSFER_TYPE_BULK) 3024 { 3025 EhciExtension->PendingTransfers--; 3026 3027 if (EhciExtension->PendingTransfers == 0) 3028 { 3029 OperationalRegs = EhciExtension->OperationalRegs; 3030 Command.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcCommand.AsULONG); 3031 3032 if (!Command.InterruptAdvanceDoorbell && 3033 (EhciExtension->Flags & EHCI_FLAGS_IDLE_SUPPORT)) 3034 { 3035 EHCI_DisableAsyncList(EhciExtension); 3036 } 3037 } 3038 } 3039 3040 RegPacket.UsbPortCompleteTransfer(EhciExtension, 3041 EhciEndpoint, 3042 TransferParameters, 3043 EhciTransfer->USBDStatus, 3044 EhciTransfer->TransferLen); 3045 } 3046 } 3047 3048 VOID 3049 NTAPI 3050 EHCI_PollActiveAsyncEndpoint(IN PEHCI_EXTENSION EhciExtension, 3051 IN PEHCI_ENDPOINT EhciEndpoint) 3052 { 3053 PEHCI_HCD_QH QH; 3054 PEHCI_HCD_TD TD; 3055 PEHCI_HCD_TD CurrentTD; 3056 ULONG CurrentTDPhys; 3057 BOOLEAN IsScheduled; 3058 3059 DPRINT_EHCI("EHCI_PollActiveAsyncEndpoint: ... \n"); 3060 3061 QH = EhciEndpoint->QH; 3062 3063 CurrentTDPhys = QH->sqh.HwQH.CurrentTD & LINK_POINTER_MASK; 3064 ASSERT(CurrentTDPhys); 3065 3066 CurrentTD = RegPacket.UsbPortGetMappedVirtualAddress(CurrentTDPhys, 3067 EhciExtension, 3068 EhciEndpoint); 3069 3070 if (CurrentTD == EhciEndpoint->DmaBufferVA) 3071 return; 3072 3073 IsScheduled = QH->sqh.QhFlags & EHCI_QH_FLAG_IN_SCHEDULE; 3074 3075 if (!EHCI_HardwarePresent(EhciExtension, 0)) 3076 IsScheduled = 0; 3077 3078 TD = EhciEndpoint->HcdHeadP; 3079 3080 if (TD == CurrentTD) 3081 { 3082 if (TD != EhciEndpoint->HcdTailP && 3083 !(TD->HwTD.Token.Status & EHCI_TOKEN_STATUS_ACTIVE)) 3084 { 3085 if (TD->NextHcdTD && TD->HwTD.NextTD != TD->NextHcdTD->PhysicalAddress) 3086 TD->HwTD.NextTD = TD->NextHcdTD->PhysicalAddress; 3087 3088 if (TD->AltNextHcdTD && 3089 TD->HwTD.AlternateNextTD != TD->AltNextHcdTD->PhysicalAddress) 3090 { 3091 TD->HwTD.AlternateNextTD = TD->AltNextHcdTD->PhysicalAddress; 3092 } 3093 3094 if (QH->sqh.HwQH.CurrentTD == TD->PhysicalAddress && 3095 !(TD->HwTD.Token.Status & EHCI_TOKEN_STATUS_ACTIVE) && 3096 (QH->sqh.HwQH.NextTD != TD->HwTD.NextTD || 3097 QH->sqh.HwQH.AlternateNextTD != TD->HwTD.AlternateNextTD)) 3098 { 3099 QH->sqh.HwQH.NextTD = TD->HwTD.NextTD; 3100 QH->sqh.HwQH.AlternateNextTD = TD->HwTD.AlternateNextTD; 3101 } 3102 3103 EHCI_InterruptNextSOF(EhciExtension); 3104 } 3105 } 3106 else 3107 { 3108 while (TD != CurrentTD) 3109 { 3110 ASSERT((TD->TdFlags & EHCI_HCD_TD_FLAG_DUMMY) == 0); 3111 3112 TD->TdFlags |= EHCI_HCD_TD_FLAG_DONE; 3113 3114 if (TD->HwTD.Token.Status & EHCI_TOKEN_STATUS_ACTIVE) 3115 TD->TdFlags |= EHCI_HCD_TD_FLAG_ACTIVE; 3116 3117 InsertTailList(&EhciEndpoint->ListTDs, &TD->DoneLink); 3118 TD = TD->NextHcdTD; 3119 } 3120 } 3121 3122 if (CurrentTD->HwTD.Token.Status & EHCI_TOKEN_STATUS_ACTIVE) 3123 { 3124 ASSERT(TD != NULL); 3125 EhciEndpoint->HcdHeadP = TD; 3126 return; 3127 } 3128 3129 if ((CurrentTD->NextHcdTD != EhciEndpoint->HcdTailP) && 3130 (CurrentTD->AltNextHcdTD != EhciEndpoint->HcdTailP || 3131 CurrentTD->HwTD.Token.TransferBytes == 0)) 3132 { 3133 ASSERT(TD != NULL); 3134 EhciEndpoint->HcdHeadP = TD; 3135 return; 3136 } 3137 3138 if (IsScheduled) 3139 { 3140 EHCI_LockQH(EhciExtension, 3141 QH, 3142 EhciEndpoint->EndpointProperties.TransferType); 3143 } 3144 3145 QH->sqh.HwQH.CurrentTD = EhciEndpoint->DmaBufferPA; 3146 3147 CurrentTD->TdFlags |= EHCI_HCD_TD_FLAG_DONE; 3148 InsertTailList(&EhciEndpoint->ListTDs, &CurrentTD->DoneLink); 3149 3150 if (CurrentTD->HwTD.Token.TransferBytes && 3151 CurrentTD->AltNextHcdTD == EhciEndpoint->HcdTailP) 3152 { 3153 TD = CurrentTD->NextHcdTD; 3154 3155 while (TD != EhciEndpoint->HcdTailP) 3156 { 3157 TD->TdFlags |= EHCI_HCD_TD_FLAG_ACTIVE; 3158 InsertTailList(&EhciEndpoint->ListTDs, &TD->DoneLink); 3159 TD = TD->NextHcdTD; 3160 } 3161 } 3162 3163 QH->sqh.HwQH.CurrentTD = EhciEndpoint->HcdTailP->PhysicalAddress; 3164 QH->sqh.HwQH.NextTD = TERMINATE_POINTER; 3165 QH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; 3166 QH->sqh.HwQH.Token.TransferBytes = 0; 3167 3168 EhciEndpoint->HcdHeadP = EhciEndpoint->HcdTailP; 3169 3170 if (IsScheduled) 3171 EHCI_UnlockQH(EhciExtension, QH); 3172 } 3173 3174 VOID 3175 NTAPI 3176 EHCI_PollHaltedAsyncEndpoint(IN PEHCI_EXTENSION EhciExtension, 3177 IN PEHCI_ENDPOINT EhciEndpoint) 3178 { 3179 PEHCI_HCD_QH QH; 3180 PEHCI_HCD_TD CurrentTD; 3181 ULONG CurrentTdPA; 3182 PEHCI_HCD_TD TD; 3183 PEHCI_TRANSFER Transfer; 3184 BOOLEAN IsScheduled; 3185 3186 DPRINT("EHCI_PollHaltedAsyncEndpoint: EhciEndpoint - %p\n", EhciEndpoint); 3187 3188 QH = EhciEndpoint->QH; 3189 EHCI_DumpHwQH(QH); 3190 3191 CurrentTdPA = QH->sqh.HwQH.CurrentTD & LINK_POINTER_MASK; 3192 ASSERT(CurrentTdPA); 3193 3194 IsScheduled = QH->sqh.QhFlags & EHCI_QH_FLAG_IN_SCHEDULE; 3195 3196 if (!EHCI_HardwarePresent(EhciExtension, 0)) 3197 IsScheduled = 0; 3198 3199 CurrentTD = RegPacket.UsbPortGetMappedVirtualAddress(CurrentTdPA, 3200 EhciExtension, 3201 EhciEndpoint); 3202 3203 DPRINT("EHCI_PollHaltedAsyncEndpoint: CurrentTD - %p\n", CurrentTD); 3204 3205 if (CurrentTD == EhciEndpoint->DmaBufferVA) 3206 return; 3207 3208 ASSERT(EhciEndpoint->HcdTailP != CurrentTD); 3209 3210 if (IsScheduled) 3211 { 3212 EHCI_LockQH(EhciExtension, 3213 QH, 3214 EhciEndpoint->EndpointProperties.TransferType); 3215 } 3216 3217 TD = EhciEndpoint->HcdHeadP; 3218 3219 while (TD != CurrentTD) 3220 { 3221 DPRINT("EHCI_PollHaltedAsyncEndpoint: TD - %p\n", TD); 3222 3223 ASSERT((TD->TdFlags & EHCI_HCD_TD_FLAG_DUMMY) == 0); 3224 3225 if (TD->HwTD.Token.Status & EHCI_TOKEN_STATUS_ACTIVE) 3226 TD->TdFlags |= EHCI_HCD_TD_FLAG_ACTIVE; 3227 3228 TD->TdFlags |= EHCI_HCD_TD_FLAG_DONE; 3229 3230 InsertTailList(&EhciEndpoint->ListTDs, &TD->DoneLink); 3231 3232 TD = TD->NextHcdTD; 3233 } 3234 3235 TD = CurrentTD; 3236 3237 Transfer = CurrentTD->EhciTransfer; 3238 3239 do 3240 { 3241 DPRINT("EHCI_PollHaltedAsyncEndpoint: TD - %p\n", TD); 3242 3243 if (TD->HwTD.Token.Status & EHCI_TOKEN_STATUS_ACTIVE) 3244 TD->TdFlags |= EHCI_HCD_TD_FLAG_ACTIVE; 3245 3246 TD->TdFlags |= EHCI_HCD_TD_FLAG_DONE; 3247 3248 InsertTailList(&EhciEndpoint->ListTDs, &TD->DoneLink); 3249 3250 TD = TD->NextHcdTD; 3251 } 3252 while (TD->EhciTransfer == Transfer); 3253 3254 EhciEndpoint->HcdHeadP = TD; 3255 3256 QH->sqh.HwQH.CurrentTD = EhciEndpoint->DmaBufferPA; 3257 QH->sqh.HwQH.NextTD = TD->PhysicalAddress; 3258 QH->sqh.HwQH.AlternateNextTD = TERMINATE_POINTER; 3259 QH->sqh.HwQH.Token.TransferBytes = 0; 3260 3261 if (IsScheduled) 3262 EHCI_UnlockQH(EhciExtension, QH); 3263 3264 if (EhciEndpoint->EndpointStatus & USBPORT_ENDPOINT_CONTROL) 3265 { 3266 EhciEndpoint->EndpointStatus &= ~USBPORT_ENDPOINT_HALT; 3267 QH->sqh.HwQH.Token.ErrorCounter = 0; 3268 QH->sqh.HwQH.Token.Status &= (UCHAR)~(EHCI_TOKEN_STATUS_ACTIVE | 3269 EHCI_TOKEN_STATUS_HALTED); 3270 3271 } 3272 } 3273 3274 VOID 3275 NTAPI 3276 EHCI_PollAsyncEndpoint(IN PEHCI_EXTENSION EhciExtension, 3277 IN PEHCI_ENDPOINT EhciEndpoint) 3278 { 3279 PEHCI_HCD_QH QH; 3280 PLIST_ENTRY DoneList; 3281 PEHCI_HCD_TD TD; 3282 3283 //DPRINT_EHCI("EHCI_PollAsyncEndpoint: EhciEndpoint - %p\n", EhciEndpoint); 3284 3285 if (!EhciEndpoint->PendingTDs) 3286 return; 3287 3288 QH = EhciEndpoint->QH; 3289 3290 if (QH->sqh.QhFlags & EHCI_QH_FLAG_CLOSED) 3291 return; 3292 3293 if (QH->sqh.HwQH.Token.Status & EHCI_TOKEN_STATUS_ACTIVE || 3294 !(QH->sqh.HwQH.Token.Status & EHCI_TOKEN_STATUS_HALTED)) 3295 { 3296 EHCI_PollActiveAsyncEndpoint(EhciExtension, EhciEndpoint); 3297 } 3298 else 3299 { 3300 EhciEndpoint->EndpointStatus |= USBPORT_ENDPOINT_HALT; 3301 EHCI_PollHaltedAsyncEndpoint(EhciExtension, EhciEndpoint); 3302 } 3303 3304 DoneList = &EhciEndpoint->ListTDs; 3305 3306 while (!IsListEmpty(DoneList)) 3307 { 3308 TD = CONTAINING_RECORD(DoneList->Flink, 3309 EHCI_HCD_TD, 3310 DoneLink); 3311 3312 RemoveHeadList(DoneList); 3313 3314 ASSERT((TD->TdFlags & (EHCI_HCD_TD_FLAG_PROCESSED | 3315 EHCI_HCD_TD_FLAG_DONE))); 3316 3317 EHCI_ProcessDoneAsyncTd(EhciExtension, TD); 3318 } 3319 } 3320 3321 VOID 3322 NTAPI 3323 EHCI_PollIsoEndpoint(IN PEHCI_EXTENSION EhciExtension, 3324 IN PEHCI_ENDPOINT EhciEndpoint) 3325 { 3326 DPRINT1("EHCI_PollIsoEndpoint: UNIMPLEMENTED. FIXME\n"); 3327 } 3328 3329 VOID 3330 NTAPI 3331 EHCI_PollEndpoint(IN PVOID ehciExtension, 3332 IN PVOID ehciEndpoint) 3333 { 3334 PEHCI_EXTENSION EhciExtension = ehciExtension; 3335 PEHCI_ENDPOINT EhciEndpoint = ehciEndpoint; 3336 ULONG TransferType; 3337 3338 //DPRINT_EHCI("EHCI_PollEndpoint: EhciEndpoint - %p\n", EhciEndpoint); 3339 3340 TransferType = EhciEndpoint->EndpointProperties.TransferType; 3341 3342 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 3343 EHCI_PollIsoEndpoint(EhciExtension, EhciEndpoint); 3344 else 3345 EHCI_PollAsyncEndpoint(EhciExtension, EhciEndpoint); 3346 } 3347 3348 VOID 3349 NTAPI 3350 EHCI_CheckController(IN PVOID ehciExtension) 3351 { 3352 PEHCI_EXTENSION EhciExtension = ehciExtension; 3353 3354 //DPRINT_EHCI("EHCI_CheckController: ... \n"); 3355 3356 if (EhciExtension->IsStarted) 3357 EHCI_HardwarePresent(EhciExtension, TRUE); 3358 } 3359 3360 ULONG 3361 NTAPI 3362 EHCI_Get32BitFrameNumber(IN PVOID ehciExtension) 3363 { 3364 PEHCI_EXTENSION EhciExtension = ehciExtension; 3365 ULONG FrameIdx; 3366 ULONG FrameIndex; 3367 ULONG FrameNumber; 3368 3369 //DPRINT_EHCI("EHCI_Get32BitFrameNumber: EhciExtension - %p\n", EhciExtension); 3370 3371 FrameIdx = EhciExtension->FrameIndex; 3372 FrameIndex = READ_REGISTER_ULONG(&EhciExtension->OperationalRegs->FrameIndex); 3373 3374 FrameNumber = (USHORT)FrameIdx ^ ((FrameIndex / EHCI_MICROFRAMES) & EHCI_FRINDEX_FRAME_MASK); 3375 FrameNumber &= EHCI_FRAME_LIST_MAX_ENTRIES; 3376 FrameNumber += FrameIndex | ((FrameIndex / EHCI_MICROFRAMES) & EHCI_FRINDEX_INDEX_MASK); 3377 3378 return FrameNumber; 3379 } 3380 3381 VOID 3382 NTAPI 3383 EHCI_EnableInterrupts(IN PVOID ehciExtension) 3384 { 3385 PEHCI_EXTENSION EhciExtension = ehciExtension; 3386 3387 DPRINT("EHCI_EnableInterrupts: EhciExtension->InterruptMask - %x\n", 3388 EhciExtension->InterruptMask.AsULONG); 3389 3390 WRITE_REGISTER_ULONG(&EhciExtension->OperationalRegs->HcInterruptEnable.AsULONG, 3391 EhciExtension->InterruptMask.AsULONG); 3392 } 3393 3394 VOID 3395 NTAPI 3396 EHCI_DisableInterrupts(IN PVOID ehciExtension) 3397 { 3398 PEHCI_EXTENSION EhciExtension = ehciExtension; 3399 3400 DPRINT("EHCI_DisableInterrupts: ... \n"); 3401 3402 WRITE_REGISTER_ULONG(&EhciExtension->OperationalRegs->HcInterruptEnable.AsULONG, 3403 0); 3404 } 3405 3406 VOID 3407 NTAPI 3408 EHCI_PollController(IN PVOID ehciExtension) 3409 { 3410 PEHCI_EXTENSION EhciExtension = ehciExtension; 3411 PEHCI_HW_REGISTERS OperationalRegs; 3412 ULONG Port; 3413 EHCI_PORT_STATUS_CONTROL PortSC; 3414 3415 DPRINT_EHCI("EHCI_PollController: ... \n"); 3416 3417 OperationalRegs = EhciExtension->OperationalRegs; 3418 3419 if (!(EhciExtension->Flags & EHCI_FLAGS_CONTROLLER_SUSPEND)) 3420 { 3421 RegPacket.UsbPortInvalidateRootHub(EhciExtension); 3422 return; 3423 } 3424 3425 if (EhciExtension->NumberOfPorts) 3426 { 3427 for (Port = 0; Port < EhciExtension->NumberOfPorts; Port++) 3428 { 3429 PortSC.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->PortControl[Port].AsULONG); 3430 3431 if (PortSC.ConnectStatusChange) 3432 RegPacket.UsbPortInvalidateRootHub(EhciExtension); 3433 } 3434 } 3435 } 3436 3437 VOID 3438 NTAPI 3439 EHCI_SetEndpointDataToggle(IN PVOID ehciExtension, 3440 IN PVOID ehciEndpoint, 3441 IN ULONG DataToggle) 3442 { 3443 PEHCI_ENDPOINT EhciEndpoint; 3444 ULONG TransferType; 3445 3446 EhciEndpoint = ehciEndpoint; 3447 3448 DPRINT("EHCI_SetEndpointDataToggle: EhciEndpoint - %p, DataToggle - %x\n", 3449 EhciEndpoint, 3450 DataToggle); 3451 3452 TransferType = EhciEndpoint->EndpointProperties.TransferType; 3453 3454 if (TransferType == USBPORT_TRANSFER_TYPE_BULK || 3455 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 3456 { 3457 EhciEndpoint->QH->sqh.HwQH.Token.DataToggle = DataToggle; 3458 } 3459 } 3460 3461 ULONG 3462 NTAPI 3463 EHCI_GetEndpointStatus(IN PVOID ehciExtension, 3464 IN PVOID ehciEndpoint) 3465 { 3466 PEHCI_ENDPOINT EhciEndpoint; 3467 ULONG TransferType; 3468 ULONG EndpointStatus = USBPORT_ENDPOINT_RUN; 3469 3470 EhciEndpoint = ehciEndpoint; 3471 3472 DPRINT("EHCI_GetEndpointStatus: EhciEndpoint - %p\n", EhciEndpoint); 3473 3474 TransferType = EhciEndpoint->EndpointProperties.TransferType; 3475 3476 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 3477 return EndpointStatus; 3478 3479 if (EhciEndpoint->EndpointStatus & USBPORT_ENDPOINT_HALT) 3480 EndpointStatus = USBPORT_ENDPOINT_HALT; 3481 3482 return EndpointStatus; 3483 } 3484 3485 VOID 3486 NTAPI 3487 EHCI_SetEndpointStatus(IN PVOID ehciExtension, 3488 IN PVOID ehciEndpoint, 3489 IN ULONG EndpointStatus) 3490 { 3491 PEHCI_ENDPOINT EhciEndpoint; 3492 ULONG TransferType; 3493 PEHCI_HCD_QH QH; 3494 3495 EhciEndpoint = ehciEndpoint; 3496 3497 DPRINT("EHCI_SetEndpointStatus: EhciEndpoint - %p, EndpointStatus - %x\n", 3498 EhciEndpoint, 3499 EndpointStatus); 3500 3501 TransferType = EhciEndpoint->EndpointProperties.TransferType; 3502 3503 if (TransferType != USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 3504 { 3505 3506 if (EndpointStatus == USBPORT_ENDPOINT_RUN) 3507 { 3508 EhciEndpoint->EndpointStatus &= ~USBPORT_ENDPOINT_HALT; 3509 3510 QH = EhciEndpoint->QH; 3511 QH->sqh.HwQH.Token.Status &= (UCHAR)~EHCI_TOKEN_STATUS_HALTED; 3512 3513 return; 3514 } 3515 3516 if (EndpointStatus == USBPORT_ENDPOINT_HALT) 3517 DbgBreakPoint(); 3518 } 3519 } 3520 3521 VOID 3522 NTAPI 3523 EHCI_ResetController(IN PVOID ehciExtension) 3524 { 3525 DPRINT1("EHCI_ResetController: UNIMPLEMENTED. FIXME\n"); 3526 } 3527 3528 MPSTATUS 3529 NTAPI 3530 EHCI_StartSendOnePacket(IN PVOID ehciExtension, 3531 IN PVOID PacketParameters, 3532 IN PVOID Data, 3533 IN PULONG pDataLength, 3534 IN PVOID BufferVA, 3535 IN PVOID BufferPA, 3536 IN ULONG BufferLength, 3537 IN USBD_STATUS * pUSBDStatus) 3538 { 3539 DPRINT1("EHCI_StartSendOnePacket: UNIMPLEMENTED. FIXME\n"); 3540 return MP_STATUS_SUCCESS; 3541 } 3542 3543 MPSTATUS 3544 NTAPI 3545 EHCI_EndSendOnePacket(IN PVOID ehciExtension, 3546 IN PVOID PacketParameters, 3547 IN PVOID Data, 3548 IN PULONG pDataLength, 3549 IN PVOID BufferVA, 3550 IN PVOID BufferPA, 3551 IN ULONG BufferLength, 3552 IN USBD_STATUS * pUSBDStatus) 3553 { 3554 DPRINT1("EHCI_EndSendOnePacket: UNIMPLEMENTED. FIXME\n"); 3555 return MP_STATUS_SUCCESS; 3556 } 3557 3558 MPSTATUS 3559 NTAPI 3560 EHCI_PassThru(IN PVOID ehciExtension, 3561 IN PVOID passThruParameters, 3562 IN ULONG ParameterLength, 3563 IN PVOID pParameters) 3564 { 3565 DPRINT1("EHCI_PassThru: UNIMPLEMENTED. FIXME\n"); 3566 return MP_STATUS_SUCCESS; 3567 } 3568 3569 VOID 3570 NTAPI 3571 EHCI_RebalanceEndpoint(IN PVOID ohciExtension, 3572 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties, 3573 IN PVOID ohciEndpoint) 3574 { 3575 DPRINT1("EHCI_RebalanceEndpoint: UNIMPLEMENTED. FIXME\n"); 3576 } 3577 3578 VOID 3579 NTAPI 3580 EHCI_FlushInterrupts(IN PVOID ehciExtension) 3581 { 3582 PEHCI_EXTENSION EhciExtension = ehciExtension; 3583 PEHCI_HW_REGISTERS OperationalRegs; 3584 EHCI_USB_STATUS Status; 3585 3586 DPRINT("EHCI_FlushInterrupts: ... \n"); 3587 3588 OperationalRegs = EhciExtension->OperationalRegs; 3589 3590 Status.AsULONG = READ_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG); 3591 WRITE_REGISTER_ULONG(&OperationalRegs->HcStatus.AsULONG, Status.AsULONG); 3592 } 3593 3594 VOID 3595 NTAPI 3596 EHCI_TakePortControl(IN PVOID ohciExtension) 3597 { 3598 DPRINT1("EHCI_TakePortControl: UNIMPLEMENTED. FIXME\n"); 3599 } 3600 3601 VOID 3602 NTAPI 3603 EHCI_Unload(IN PDRIVER_OBJECT DriverObject) 3604 { 3605 #if DBG 3606 DPRINT1("EHCI_Unload: Not supported\n"); 3607 #endif 3608 return; 3609 } 3610 3611 NTSTATUS 3612 NTAPI 3613 DriverEntry(IN PDRIVER_OBJECT DriverObject, 3614 IN PUNICODE_STRING RegistryPath) 3615 { 3616 DPRINT("DriverEntry: DriverObject - %p, RegistryPath - %wZ\n", 3617 DriverObject, 3618 RegistryPath); 3619 3620 if (USBPORT_GetHciMn() != USBPORT_HCI_MN) 3621 return STATUS_INSUFFICIENT_RESOURCES; 3622 3623 RtlZeroMemory(&RegPacket, sizeof(USBPORT_REGISTRATION_PACKET)); 3624 3625 RegPacket.MiniPortVersion = USB_MINIPORT_VERSION_EHCI; 3626 3627 RegPacket.MiniPortFlags = USB_MINIPORT_FLAGS_INTERRUPT | 3628 USB_MINIPORT_FLAGS_MEMORY_IO | 3629 USB_MINIPORT_FLAGS_USB2 | 3630 USB_MINIPORT_FLAGS_POLLING | 3631 USB_MINIPORT_FLAGS_WAKE_SUPPORT; 3632 3633 RegPacket.MiniPortBusBandwidth = TOTAL_USB20_BUS_BANDWIDTH; 3634 3635 RegPacket.MiniPortExtensionSize = sizeof(EHCI_EXTENSION); 3636 RegPacket.MiniPortEndpointSize = sizeof(EHCI_ENDPOINT); 3637 RegPacket.MiniPortTransferSize = sizeof(EHCI_TRANSFER); 3638 RegPacket.MiniPortResourcesSize = sizeof(EHCI_HC_RESOURCES); 3639 3640 RegPacket.OpenEndpoint = EHCI_OpenEndpoint; 3641 RegPacket.ReopenEndpoint = EHCI_ReopenEndpoint; 3642 RegPacket.QueryEndpointRequirements = EHCI_QueryEndpointRequirements; 3643 RegPacket.CloseEndpoint = EHCI_CloseEndpoint; 3644 RegPacket.StartController = EHCI_StartController; 3645 RegPacket.StopController = EHCI_StopController; 3646 RegPacket.SuspendController = EHCI_SuspendController; 3647 RegPacket.ResumeController = EHCI_ResumeController; 3648 RegPacket.InterruptService = EHCI_InterruptService; 3649 RegPacket.InterruptDpc = EHCI_InterruptDpc; 3650 RegPacket.SubmitTransfer = EHCI_SubmitTransfer; 3651 RegPacket.SubmitIsoTransfer = EHCI_SubmitIsoTransfer; 3652 RegPacket.AbortTransfer = EHCI_AbortTransfer; 3653 RegPacket.GetEndpointState = EHCI_GetEndpointState; 3654 RegPacket.SetEndpointState = EHCI_SetEndpointState; 3655 RegPacket.PollEndpoint = EHCI_PollEndpoint; 3656 RegPacket.CheckController = EHCI_CheckController; 3657 RegPacket.Get32BitFrameNumber = EHCI_Get32BitFrameNumber; 3658 RegPacket.InterruptNextSOF = EHCI_InterruptNextSOF; 3659 RegPacket.EnableInterrupts = EHCI_EnableInterrupts; 3660 RegPacket.DisableInterrupts = EHCI_DisableInterrupts; 3661 RegPacket.PollController = EHCI_PollController; 3662 RegPacket.SetEndpointDataToggle = EHCI_SetEndpointDataToggle; 3663 RegPacket.GetEndpointStatus = EHCI_GetEndpointStatus; 3664 RegPacket.SetEndpointStatus = EHCI_SetEndpointStatus; 3665 RegPacket.RH_GetRootHubData = EHCI_RH_GetRootHubData; 3666 RegPacket.RH_GetStatus = EHCI_RH_GetStatus; 3667 RegPacket.RH_GetPortStatus = EHCI_RH_GetPortStatus; 3668 RegPacket.RH_GetHubStatus = EHCI_RH_GetHubStatus; 3669 RegPacket.RH_SetFeaturePortReset = EHCI_RH_SetFeaturePortReset; 3670 RegPacket.RH_SetFeaturePortPower = EHCI_RH_SetFeaturePortPower; 3671 RegPacket.RH_SetFeaturePortEnable = EHCI_RH_SetFeaturePortEnable; 3672 RegPacket.RH_SetFeaturePortSuspend = EHCI_RH_SetFeaturePortSuspend; 3673 RegPacket.RH_ClearFeaturePortEnable = EHCI_RH_ClearFeaturePortEnable; 3674 RegPacket.RH_ClearFeaturePortPower = EHCI_RH_ClearFeaturePortPower; 3675 RegPacket.RH_ClearFeaturePortSuspend = EHCI_RH_ClearFeaturePortSuspend; 3676 RegPacket.RH_ClearFeaturePortEnableChange = EHCI_RH_ClearFeaturePortEnableChange; 3677 RegPacket.RH_ClearFeaturePortConnectChange = EHCI_RH_ClearFeaturePortConnectChange; 3678 RegPacket.RH_ClearFeaturePortResetChange = EHCI_RH_ClearFeaturePortResetChange; 3679 RegPacket.RH_ClearFeaturePortSuspendChange = EHCI_RH_ClearFeaturePortSuspendChange; 3680 RegPacket.RH_ClearFeaturePortOvercurrentChange = EHCI_RH_ClearFeaturePortOvercurrentChange; 3681 RegPacket.RH_DisableIrq = EHCI_RH_DisableIrq; 3682 RegPacket.RH_EnableIrq = EHCI_RH_EnableIrq; 3683 RegPacket.StartSendOnePacket = EHCI_StartSendOnePacket; 3684 RegPacket.EndSendOnePacket = EHCI_EndSendOnePacket; 3685 RegPacket.PassThru = EHCI_PassThru; 3686 RegPacket.RebalanceEndpoint = EHCI_RebalanceEndpoint; 3687 RegPacket.FlushInterrupts = EHCI_FlushInterrupts; 3688 RegPacket.RH_ChirpRootPort = EHCI_RH_ChirpRootPort; 3689 RegPacket.TakePortControl = EHCI_TakePortControl; 3690 3691 DriverObject->DriverUnload = EHCI_Unload; 3692 3693 return USBPORT_RegisterUSBPortDriver(DriverObject, 3694 USB20_MINIPORT_INTERFACE_VERSION, 3695 &RegPacket); 3696 } 3697