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