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>
13 #define NDEBUG_EHCI_TRACE
16 USBPORT_REGISTRATION_PACKET RegPacket
;
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
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 },
95 C_ASSERT(RTL_NUMBER_OF(pTable
) == INTERRUPT_ENDPOINTs
+ 1);
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
101 C_ASSERT(RTL_NUMBER_OF(Balance
) == EHCI_FRAMES
);
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,
109 C_ASSERT(RTL_NUMBER_OF(LinkTable
) == INTERRUPT_ENDPOINTs
+ 1);
113 EHCI_AllocTd(IN PEHCI_EXTENSION EhciExtension
,
114 IN PEHCI_ENDPOINT EhciEndpoint
)
119 DPRINT_EHCI("EHCI_AllocTd: ... \n");
121 if (EhciEndpoint
->MaxTDs
== 0)
123 RegPacket
.UsbPortBugCheck(EhciExtension
);
127 TD
= EhciEndpoint
->FirstTD
;
129 for (ix
= 1; TD
->TdFlags
& EHCI_HCD_TD_FLAG_ALLOCATED
; ix
++)
133 if (ix
>= EhciEndpoint
->MaxTDs
)
135 RegPacket
.UsbPortBugCheck(EhciExtension
);
140 TD
->TdFlags
|= EHCI_HCD_TD_FLAG_ALLOCATED
;
142 EhciEndpoint
->RemainTDs
--;
149 EHCI_InitializeQH(IN PEHCI_EXTENSION EhciExtension
,
150 IN PEHCI_ENDPOINT EhciEndpoint
,
154 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
;
157 DPRINT_EHCI("EHCI_InitializeQH: EhciEndpoint - %p, QH - %p, QhPA - %p\n",
162 EndpointProperties
= &EhciEndpoint
->EndpointProperties
;
164 RtlZeroMemory(QH
, sizeof(EHCI_HCD_QH
));
166 ASSERT((QhPA
& ~LINK_POINTER_MASK
) == 0);
168 QH
->sqh
.PhysicalAddress
= QhPA
;
170 QH
->sqh
.HwQH
.EndpointParams
.DeviceAddress
= EndpointProperties
->DeviceAddress
;
171 QH
->sqh
.HwQH
.EndpointParams
.EndpointNumber
= EndpointProperties
->EndpointAddress
;
173 DeviceSpeed
= EndpointProperties
->DeviceSpeed
;
178 QH
->sqh
.HwQH
.EndpointParams
.EndpointSpeed
= EHCI_QH_EP_LOW_SPEED
;
182 QH
->sqh
.HwQH
.EndpointParams
.EndpointSpeed
= EHCI_QH_EP_FULL_SPEED
;
186 QH
->sqh
.HwQH
.EndpointParams
.EndpointSpeed
= EHCI_QH_EP_HIGH_SPEED
;
190 DPRINT1("EHCI_InitializeQH: Unknown DeviceSpeed - %x\n", DeviceSpeed
);
195 QH
->sqh
.HwQH
.EndpointParams
.MaximumPacketLength
= EndpointProperties
->MaxPacketSize
;
196 QH
->sqh
.HwQH
.EndpointCaps
.PipeMultiplier
= 1;
198 if (DeviceSpeed
== UsbHighSpeed
)
200 QH
->sqh
.HwQH
.EndpointCaps
.HubAddr
= 0;
201 QH
->sqh
.HwQH
.EndpointCaps
.PortNumber
= 0;
205 QH
->sqh
.HwQH
.EndpointCaps
.HubAddr
= EndpointProperties
->HubAddr
;
206 QH
->sqh
.HwQH
.EndpointCaps
.PortNumber
= EndpointProperties
->PortNumber
;
208 if (EndpointProperties
->TransferType
== USBPORT_TRANSFER_TYPE_CONTROL
)
209 QH
->sqh
.HwQH
.EndpointParams
.ControlEndpointFlag
= 1;
212 QH
->sqh
.HwQH
.NextTD
= TERMINATE_POINTER
;
213 QH
->sqh
.HwQH
.AlternateNextTD
= TERMINATE_POINTER
;
215 QH
->sqh
.HwQH
.Token
.Status
&= (UCHAR
)~(EHCI_TOKEN_STATUS_ACTIVE
|
216 EHCI_TOKEN_STATUS_HALTED
);
223 EHCI_OpenBulkOrControlEndpoint(IN PEHCI_EXTENSION EhciExtension
,
224 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
225 IN PEHCI_ENDPOINT EhciEndpoint
,
226 IN BOOLEAN IsControl
)
236 DPRINT("EHCI_OpenBulkOrControlEndpoint: EhciEndpoint - %p, IsControl - %x\n",
240 InitializeListHead(&EhciEndpoint
->ListTDs
);
242 EhciEndpoint
->DmaBufferVA
= (PVOID
)EndpointProperties
->BufferVA
;
243 EhciEndpoint
->DmaBufferPA
= EndpointProperties
->BufferPA
;
245 RtlZeroMemory(EhciEndpoint
->DmaBufferVA
, sizeof(EHCI_HCD_TD
));
247 QH
= (PEHCI_HCD_QH
)EhciEndpoint
->DmaBufferVA
+ 1;
248 QhPA
= EhciEndpoint
->DmaBufferPA
+ sizeof(EHCI_HCD_TD
);
250 EhciEndpoint
->FirstTD
= (PEHCI_HCD_TD
)(QH
+ 1);
252 TdCount
= (EndpointProperties
->BufferLength
-
253 (sizeof(EHCI_HCD_TD
) + sizeof(EHCI_HCD_QH
))) /
256 if (EndpointProperties
->TransferType
== USBPORT_TRANSFER_TYPE_CONTROL
)
257 EhciEndpoint
->EndpointStatus
|= USBPORT_ENDPOINT_CONTROL
;
259 EhciEndpoint
->MaxTDs
= TdCount
;
260 EhciEndpoint
->RemainTDs
= TdCount
;
262 TdVA
= EhciEndpoint
->FirstTD
;
263 TdPA
= QhPA
+ sizeof(EHCI_HCD_QH
);
265 for (ix
= 0; ix
< TdCount
; ix
++)
267 DPRINT_EHCI("EHCI_OpenBulkOrControlEndpoint: TdVA - %p, TdPA - %p\n",
271 RtlZeroMemory(TdVA
, sizeof(EHCI_HCD_TD
));
273 ASSERT((TdPA
& ~LINK_POINTER_MASK
) == 0);
275 TdVA
->PhysicalAddress
= TdPA
;
276 TdVA
->EhciEndpoint
= EhciEndpoint
;
277 TdVA
->EhciTransfer
= NULL
;
279 TdPA
+= sizeof(EHCI_HCD_TD
);
283 EhciEndpoint
->QH
= EHCI_InitializeQH(EhciExtension
,
290 QH
->sqh
.HwQH
.EndpointParams
.DataToggleControl
= 1;
291 EhciEndpoint
->HcdHeadP
= NULL
;
295 QH
->sqh
.HwQH
.EndpointParams
.DataToggleControl
= 0;
298 TD
= EHCI_AllocTd(EhciExtension
, EhciEndpoint
);
301 return MP_STATUS_NO_RESOURCES
;
303 TD
->TdFlags
|= EHCI_HCD_TD_FLAG_DUMMY
;
304 TD
->HwTD
.Token
.Status
&= (UCHAR
)~EHCI_TOKEN_STATUS_ACTIVE
;
306 TD
->HwTD
.NextTD
= TERMINATE_POINTER
;
307 TD
->HwTD
.AlternateNextTD
= TERMINATE_POINTER
;
309 TD
->NextHcdTD
= NULL
;
310 TD
->AltNextHcdTD
= NULL
;
312 EhciEndpoint
->HcdTailP
= TD
;
313 EhciEndpoint
->HcdHeadP
= TD
;
315 QH
->sqh
.HwQH
.CurrentTD
= TD
->PhysicalAddress
;
316 QH
->sqh
.HwQH
.NextTD
= TERMINATE_POINTER
;
317 QH
->sqh
.HwQH
.AlternateNextTD
= TERMINATE_POINTER
;
319 QH
->sqh
.HwQH
.Token
.Status
&= (UCHAR
)~EHCI_TOKEN_STATUS_ACTIVE
;
320 QH
->sqh
.HwQH
.Token
.TransferBytes
= 0;
322 return MP_STATUS_SUCCESS
;
327 EHCI_OpenInterruptEndpoint(IN PEHCI_EXTENSION EhciExtension
,
328 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
329 IN PEHCI_ENDPOINT EhciEndpoint
)
333 PEHCI_HCD_TD FirstTD
;
336 PEHCI_HCD_TD DummyTD
;
339 const EHCI_PERIOD
* PeriodTable
= NULL
;
340 ULONG ScheduleOffset
;
344 DPRINT("EHCI_OpenInterruptEndpoint: EhciExtension - %p, EndpointProperties - %p, EhciEndpoint - %p\n",
349 Period
= EndpointProperties
->Period
;
350 ScheduleOffset
= EndpointProperties
->ScheduleOffset
;
352 ASSERT(Period
< (INTERRUPT_ENDPOINTs
+ 1));
354 while (!(Period
& 1))
362 InitializeListHead(&EhciEndpoint
->ListTDs
);
364 if (EhciEndpoint
->EndpointProperties
.DeviceSpeed
== UsbHighSpeed
)
366 PeriodTable
= &pTable
[ClassicPeriod
[Idx
] + ScheduleOffset
];
367 EhciEndpoint
->PeriodTable
= PeriodTable
;
369 DPRINT("EHCI_OpenInterruptEndpoint: EhciEndpoint - %p, ScheduleMask - %X, Index - %X\n",
371 PeriodTable
->ScheduleMask
,
374 EhciEndpoint
->StaticQH
= EhciExtension
->PeriodicHead
[PeriodTable
->PeriodIdx
];
378 EhciEndpoint
->PeriodTable
= NULL
;
380 DPRINT("EHCI_OpenInterruptEndpoint: EhciEndpoint - %p, Index - %X\n",
384 EhciEndpoint
->StaticQH
= EhciExtension
->PeriodicHead
[ClassicPeriod
[Idx
] +
388 EhciEndpoint
->DmaBufferVA
= (PVOID
)EndpointProperties
->BufferVA
;
389 EhciEndpoint
->DmaBufferPA
= EndpointProperties
->BufferPA
;
391 RtlZeroMemory((PVOID
)EndpointProperties
->BufferVA
, sizeof(EHCI_HCD_TD
));
393 QH
= (PEHCI_HCD_QH
)(EndpointProperties
->BufferVA
+ sizeof(EHCI_HCD_TD
));
394 QhPA
= EndpointProperties
->BufferPA
+ sizeof(EHCI_HCD_TD
);
396 FirstTD
= (PEHCI_HCD_TD
)(EndpointProperties
->BufferVA
+
397 sizeof(EHCI_HCD_TD
) +
398 sizeof(EHCI_HCD_QH
));
400 FirstTdPA
= EndpointProperties
->BufferPA
+
401 sizeof(EHCI_HCD_TD
) +
404 TdCount
= (EndpointProperties
->BufferLength
-
405 (sizeof(EHCI_HCD_TD
) + sizeof(EHCI_HCD_QH
))) /
408 ASSERT(TdCount
>= EHCI_MAX_INTERRUPT_TD_COUNT
+ 1);
410 EhciEndpoint
->FirstTD
= FirstTD
;
411 EhciEndpoint
->MaxTDs
= TdCount
;
413 for (ix
= 0; ix
< TdCount
; ix
++)
415 TD
= EhciEndpoint
->FirstTD
+ ix
;
417 RtlZeroMemory(TD
, sizeof(EHCI_HCD_TD
));
419 ASSERT((FirstTdPA
& ~LINK_POINTER_MASK
) == 0);
421 TD
->PhysicalAddress
= FirstTdPA
;
422 TD
->EhciEndpoint
= EhciEndpoint
;
423 TD
->EhciTransfer
= NULL
;
425 FirstTdPA
+= sizeof(EHCI_HCD_TD
);
428 EhciEndpoint
->RemainTDs
= TdCount
;
430 EhciEndpoint
->QH
= EHCI_InitializeQH(EhciExtension
,
435 if (EhciEndpoint
->EndpointProperties
.DeviceSpeed
== UsbHighSpeed
)
437 QH
->sqh
.HwQH
.EndpointCaps
.InterruptMask
= PeriodTable
->ScheduleMask
;
441 QH
->sqh
.HwQH
.EndpointCaps
.InterruptMask
=
442 EndpointProperties
->InterruptScheduleMask
;
444 QH
->sqh
.HwQH
.EndpointCaps
.SplitCompletionMask
=
445 EndpointProperties
->SplitCompletionMask
;
448 DummyTD
= EHCI_AllocTd(EhciExtension
, EhciEndpoint
);
450 DummyTD
->TdFlags
|= EHCI_HCD_TD_FLAG_DUMMY
;
451 DummyTD
->NextHcdTD
= NULL
;
452 DummyTD
->AltNextHcdTD
= NULL
;
454 DummyTD
->HwTD
.Token
.Status
&= ~EHCI_TOKEN_STATUS_ACTIVE
;
456 DummyTD
->HwTD
.NextTD
= TERMINATE_POINTER
;
457 DummyTD
->HwTD
.AlternateNextTD
= TERMINATE_POINTER
;
459 EhciEndpoint
->HcdTailP
= DummyTD
;
460 EhciEndpoint
->HcdHeadP
= DummyTD
;
462 QH
->sqh
.HwQH
.CurrentTD
= DummyTD
->PhysicalAddress
;
463 QH
->sqh
.HwQH
.NextTD
= TERMINATE_POINTER
;
464 QH
->sqh
.HwQH
.AlternateNextTD
= TERMINATE_POINTER
;
466 QH
->sqh
.HwQH
.Token
.Status
&= ~EHCI_TOKEN_STATUS_ACTIVE
;
467 QH
->sqh
.HwQH
.Token
.TransferBytes
= 0;
469 return MP_STATUS_SUCCESS
;
474 EHCI_OpenHsIsoEndpoint(IN PEHCI_EXTENSION EhciExtension
,
475 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
476 IN PEHCI_ENDPOINT EhciEndpoint
)
478 DPRINT1("EHCI_OpenHsIsoEndpoint: UNIMPLEMENTED. FIXME\n");
479 return MP_STATUS_NOT_SUPPORTED
;
484 EHCI_OpenIsoEndpoint(IN PEHCI_EXTENSION EhciExtension
,
485 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
486 IN PEHCI_ENDPOINT EhciEndpoint
)
488 DPRINT1("EHCI_OpenIsoEndpoint: UNIMPLEMENTED. FIXME\n");
489 return MP_STATUS_NOT_SUPPORTED
;
494 EHCI_OpenEndpoint(IN PVOID ehciExtension
,
495 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
496 IN PVOID ehciEndpoint
)
498 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
499 PEHCI_ENDPOINT EhciEndpoint
= ehciEndpoint
;
503 DPRINT("EHCI_OpenEndpoint: ... \n");
505 RtlCopyMemory(&EhciEndpoint
->EndpointProperties
,
507 sizeof(EhciEndpoint
->EndpointProperties
));
509 TransferType
= EndpointProperties
->TransferType
;
511 switch (TransferType
)
513 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS
:
514 if (EndpointProperties
->DeviceSpeed
== UsbHighSpeed
)
516 MPStatus
= EHCI_OpenHsIsoEndpoint(EhciExtension
,
522 MPStatus
= EHCI_OpenIsoEndpoint(EhciExtension
,
529 case USBPORT_TRANSFER_TYPE_CONTROL
:
530 MPStatus
= EHCI_OpenBulkOrControlEndpoint(EhciExtension
,
536 case USBPORT_TRANSFER_TYPE_BULK
:
537 MPStatus
= EHCI_OpenBulkOrControlEndpoint(EhciExtension
,
543 case USBPORT_TRANSFER_TYPE_INTERRUPT
:
544 MPStatus
= EHCI_OpenInterruptEndpoint(EhciExtension
,
550 MPStatus
= MP_STATUS_NOT_SUPPORTED
;
559 EHCI_ReopenEndpoint(IN PVOID ehciExtension
,
560 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
561 IN PVOID ehciEndpoint
)
563 PEHCI_ENDPOINT EhciEndpoint
;
568 EhciEndpoint
= ehciEndpoint
;
570 TransferType
= EndpointProperties
->TransferType
;
572 DPRINT("EHCI_ReopenEndpoint: EhciEndpoint - %p, TransferType - %x\n",
576 switch (TransferType
)
578 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS
:
579 if (EndpointProperties
->DeviceSpeed
== UsbHighSpeed
)
581 DPRINT1("EHCI_ReopenEndpoint: HS Iso. UNIMPLEMENTED. FIXME\n");
582 MPStatus
= MP_STATUS_NOT_SUPPORTED
;
586 DPRINT1("EHCI_ReopenEndpoint: Iso. UNIMPLEMENTED. FIXME\n");
587 MPStatus
= MP_STATUS_NOT_SUPPORTED
;
592 case USBPORT_TRANSFER_TYPE_CONTROL
:
593 case USBPORT_TRANSFER_TYPE_BULK
:
594 case USBPORT_TRANSFER_TYPE_INTERRUPT
:
595 RtlCopyMemory(&EhciEndpoint
->EndpointProperties
,
597 sizeof(EhciEndpoint
->EndpointProperties
));
599 QH
= EhciEndpoint
->QH
;
601 QH
->sqh
.HwQH
.EndpointParams
.DeviceAddress
= EndpointProperties
->DeviceAddress
;
602 QH
->sqh
.HwQH
.EndpointParams
.MaximumPacketLength
= EndpointProperties
->MaxPacketSize
;
604 QH
->sqh
.HwQH
.EndpointCaps
.HubAddr
= EndpointProperties
->HubAddr
;
609 DPRINT1("EHCI_ReopenEndpoint: Unknown TransferType\n");
610 MPStatus
= MP_STATUS_SUCCESS
;
619 EHCI_QueryEndpointRequirements(IN PVOID ehciExtension
,
620 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
621 IN PUSBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements
)
625 DPRINT("EHCI_QueryEndpointRequirements: ... \n");
627 TransferType
= EndpointProperties
->TransferType
;
629 switch (TransferType
)
631 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS
:
632 DPRINT("EHCI_QueryEndpointRequirements: IsoTransfer\n");
634 if (EndpointProperties
->DeviceSpeed
== UsbHighSpeed
)
636 EndpointRequirements
->HeaderBufferSize
= EHCI_MAX_HS_ISO_HEADER_BUFFER_SIZE
;
637 EndpointRequirements
->MaxTransferSize
= EHCI_MAX_HS_ISO_TRANSFER_SIZE
;
641 EndpointRequirements
->HeaderBufferSize
= EHCI_MAX_FS_ISO_HEADER_BUFFER_SIZE
;
642 EndpointRequirements
->MaxTransferSize
= EHCI_MAX_FS_ISO_TRANSFER_SIZE
;
646 case USBPORT_TRANSFER_TYPE_CONTROL
:
647 DPRINT("EHCI_QueryEndpointRequirements: ControlTransfer\n");
648 EndpointRequirements
->HeaderBufferSize
= sizeof(EHCI_HCD_TD
) +
649 sizeof(EHCI_HCD_QH
) +
650 EHCI_MAX_CONTROL_TD_COUNT
* sizeof(EHCI_HCD_TD
);
652 EndpointRequirements
->MaxTransferSize
= EHCI_MAX_CONTROL_TRANSFER_SIZE
;
655 case USBPORT_TRANSFER_TYPE_BULK
:
656 DPRINT("EHCI_QueryEndpointRequirements: BulkTransfer\n");
657 EndpointRequirements
->HeaderBufferSize
= sizeof(EHCI_HCD_TD
) +
658 sizeof(EHCI_HCD_QH
) +
659 EHCI_MAX_BULK_TD_COUNT
* sizeof(EHCI_HCD_TD
);
661 EndpointRequirements
->MaxTransferSize
= EHCI_MAX_BULK_TRANSFER_SIZE
;
664 case USBPORT_TRANSFER_TYPE_INTERRUPT
:
665 DPRINT("EHCI_QueryEndpointRequirements: InterruptTransfer\n");
666 EndpointRequirements
->HeaderBufferSize
= sizeof(EHCI_HCD_TD
) +
667 sizeof(EHCI_HCD_QH
) +
668 EHCI_MAX_INTERRUPT_TD_COUNT
* sizeof(EHCI_HCD_TD
);
670 EndpointRequirements
->MaxTransferSize
= EHCI_MAX_INTERRUPT_TRANSFER_SIZE
;
674 DPRINT1("EHCI_QueryEndpointRequirements: Unknown TransferType - %x\n",
683 EHCI_DisablePeriodicList(IN PEHCI_EXTENSION EhciExtension
)
685 PEHCI_HW_REGISTERS OperationalRegs
;
686 EHCI_USB_COMMAND Command
;
688 DPRINT("EHCI_DisablePeriodicList: ... \n");
690 if (EhciExtension
->Flags
& EHCI_FLAGS_IDLE_SUPPORT
)
692 OperationalRegs
= EhciExtension
->OperationalRegs
;
694 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
695 Command
.PeriodicEnable
= 0;
696 WRITE_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
, Command
.AsULONG
);
702 EHCI_CloseEndpoint(IN PVOID ehciExtension
,
703 IN PVOID ehciEndpoint
,
704 IN BOOLEAN DisablePeriodic
)
706 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
707 PEHCI_ENDPOINT EhciEndpoint
= ehciEndpoint
;
710 DPRINT1("EHCI_CloseEndpoint: EhciEndpoint - %p, DisablePeriodic - %X\n",
716 TransferType
= EhciEndpoint
->EndpointProperties
.TransferType
;
718 if (TransferType
== USBPORT_TRANSFER_TYPE_ISOCHRONOUS
||
719 TransferType
== USBPORT_TRANSFER_TYPE_INTERRUPT
)
721 EHCI_DisablePeriodicList(EhciExtension
);
728 EHCI_GetQhForFrame(IN PEHCI_EXTENSION EhciExtension
,
731 //DPRINT_EHCI("EHCI_GetQhForFrame: FrameIdx - %x, Balance[FrameIdx] - %x\n",
733 // Balance[FrameIdx & 0x1F]);
735 return EhciExtension
->PeriodicHead
[Balance
[FrameIdx
& (EHCI_FRAMES
- 1)]];
740 EHCI_GetDummyQhForFrame(IN PEHCI_EXTENSION EhciExtension
,
743 return (PEHCI_HCD_QH
)((ULONG_PTR
)EhciExtension
->IsoDummyQHListVA
+
744 Idx
* sizeof(EHCI_HCD_QH
));
749 EHCI_AlignHwStructure(IN PEHCI_EXTENSION EhciExtension
,
750 IN PULONG PhysicalAddress
,
751 IN PULONG_PTR VirtualAddress
,
758 //DPRINT_EHCI("EHCI_AlignHwStructure: *PhysicalAddress - %X, *VirtualAddress - %X, Alignment - %x\n",
763 PAddress
= *PhysicalAddress
;
764 VAddress
= *VirtualAddress
;
766 NewPAddress
= (ULONG
)(ULONG_PTR
)PAGE_ALIGN(*PhysicalAddress
+ Alignment
- 1);
768 if (NewPAddress
!= (ULONG
)(ULONG_PTR
)PAGE_ALIGN(*PhysicalAddress
))
770 VAddress
+= NewPAddress
- PAddress
;
771 PAddress
= NewPAddress
;
773 DPRINT("EHCI_AlignHwStructure: VAddress - %X, PAddress - %X\n",
778 *VirtualAddress
= VAddress
;
779 *PhysicalAddress
= PAddress
;
784 EHCI_AddDummyQHs(IN PEHCI_EXTENSION EhciExtension
)
786 PEHCI_HC_RESOURCES HcResourcesVA
;
787 PEHCI_HCD_QH DummyQH
;
789 EHCI_QH_EP_PARAMS EndpointParams
;
790 EHCI_LINK_POINTER PAddress
;
793 DPRINT("EHCI_AddDummyQueueHeads: EhciExtension - %p\n", EhciExtension
);
795 HcResourcesVA
= EhciExtension
->HcResourcesVA
;
797 DummyQH
= EhciExtension
->IsoDummyQHListVA
;
798 DummyQhPA
= EhciExtension
->IsoDummyQHListPA
;
800 for (Frame
= 0; Frame
< EHCI_FRAME_LIST_MAX_ENTRIES
; Frame
++)
802 RtlZeroMemory(DummyQH
, sizeof(EHCI_HCD_QH
));
804 PAddress
.AsULONG
= HcResourcesVA
->PeriodicFrameList
[Frame
];
806 DummyQH
->sqh
.HwQH
.HorizontalLink
.AsULONG
= PAddress
.AsULONG
;
807 DummyQH
->sqh
.HwQH
.CurrentTD
= 0;
808 DummyQH
->sqh
.HwQH
.NextTD
= TERMINATE_POINTER
;
809 DummyQH
->sqh
.HwQH
.AlternateNextTD
= TERMINATE_POINTER
;
811 EndpointParams
= DummyQH
->sqh
.HwQH
.EndpointParams
;
812 EndpointParams
.DeviceAddress
= 0;
813 EndpointParams
.EndpointSpeed
= 0;
814 EndpointParams
.MaximumPacketLength
= EHCI_DUMMYQH_MAX_PACKET_LENGTH
;
815 DummyQH
->sqh
.HwQH
.EndpointParams
= EndpointParams
;
817 DummyQH
->sqh
.HwQH
.EndpointCaps
.AsULONG
= 0;
818 DummyQH
->sqh
.HwQH
.EndpointCaps
.InterruptMask
= 0;
819 DummyQH
->sqh
.HwQH
.EndpointCaps
.SplitCompletionMask
= 0;
820 DummyQH
->sqh
.HwQH
.EndpointCaps
.PipeMultiplier
= 1;
822 DummyQH
->sqh
.HwQH
.Token
.Status
&= (UCHAR
)~EHCI_TOKEN_STATUS_ACTIVE
;
824 DummyQH
->sqh
.PhysicalAddress
= DummyQhPA
;
825 DummyQH
->sqh
.StaticQH
= EHCI_GetQhForFrame(EhciExtension
, Frame
);
827 PAddress
.AsULONG
= DummyQhPA
;
828 PAddress
.Reserved
= 0;
829 PAddress
.Type
= EHCI_LINK_TYPE_QH
;
831 HcResourcesVA
->PeriodicFrameList
[Frame
] = PAddress
.AsULONG
;
834 DummyQhPA
+= sizeof(EHCI_HCD_QH
);
840 EHCI_InitializeInterruptSchedule(IN PEHCI_EXTENSION EhciExtension
)
842 PEHCI_STATIC_QH StaticQH
;
845 DPRINT("EHCI_InitializeInterruptSchedule: ... \n");
847 for (ix
= 0; ix
< INTERRUPT_ENDPOINTs
; ix
++)
849 StaticQH
= EhciExtension
->PeriodicHead
[ix
];
851 StaticQH
->HwQH
.EndpointParams
.HeadReclamationListFlag
= 0;
852 StaticQH
->HwQH
.NextTD
|= TERMINATE_POINTER
;
853 StaticQH
->HwQH
.Token
.Status
|= (UCHAR
)EHCI_TOKEN_STATUS_HALTED
;
856 for (ix
= 1; ix
< INTERRUPT_ENDPOINTs
; ix
++)
858 StaticQH
= EhciExtension
->PeriodicHead
[ix
];
860 StaticQH
->PrevHead
= NULL
;
861 StaticQH
->NextHead
= (PEHCI_HCD_QH
)EhciExtension
->PeriodicHead
[LinkTable
[ix
]];
863 StaticQH
->HwQH
.HorizontalLink
.AsULONG
=
864 EhciExtension
->PeriodicHead
[LinkTable
[ix
]]->PhysicalAddress
;
866 StaticQH
->HwQH
.HorizontalLink
.Type
= EHCI_LINK_TYPE_QH
;
867 StaticQH
->HwQH
.EndpointCaps
.InterruptMask
= 0xFF;
869 StaticQH
->QhFlags
|= EHCI_QH_FLAG_STATIC
;
871 if (ix
< (ENDPOINT_INTERRUPT_8ms
- 1))
872 StaticQH
->QhFlags
|= EHCI_QH_FLAG_STATIC_FAST
;
875 EhciExtension
->PeriodicHead
[0]->HwQH
.HorizontalLink
.Terminate
= 1;
877 EhciExtension
->PeriodicHead
[0]->QhFlags
|= (EHCI_QH_FLAG_STATIC
|
878 EHCI_QH_FLAG_STATIC_FAST
);
883 EHCI_InitializeSchedule(IN PEHCI_EXTENSION EhciExtension
,
887 PEHCI_HW_REGISTERS OperationalRegs
;
888 PEHCI_HC_RESOURCES HcResourcesVA
;
890 PEHCI_STATIC_QH AsyncHead
;
892 PEHCI_STATIC_QH PeriodicHead
;
893 ULONG PeriodicHeadPA
;
894 PEHCI_STATIC_QH StaticQH
;
895 EHCI_LINK_POINTER NextLink
;
896 EHCI_LINK_POINTER StaticHeadPA
;
900 DPRINT("EHCI_InitializeSchedule: BaseVA - %p, BasePA - %p\n",
904 OperationalRegs
= EhciExtension
->OperationalRegs
;
906 HcResourcesVA
= (PEHCI_HC_RESOURCES
)BaseVA
;
907 HcResourcesPA
= BasePA
;
909 EhciExtension
->HcResourcesVA
= HcResourcesVA
;
910 EhciExtension
->HcResourcesPA
= BasePA
;
912 /* Asynchronous Schedule */
914 AsyncHead
= &HcResourcesVA
->AsyncHead
;
915 AsyncHeadPA
= HcResourcesPA
+ FIELD_OFFSET(EHCI_HC_RESOURCES
, AsyncHead
);
917 RtlZeroMemory(AsyncHead
, sizeof(EHCI_STATIC_QH
));
919 NextLink
.AsULONG
= AsyncHeadPA
;
920 NextLink
.Type
= EHCI_LINK_TYPE_QH
;
922 AsyncHead
->HwQH
.HorizontalLink
= NextLink
;
923 AsyncHead
->HwQH
.EndpointParams
.HeadReclamationListFlag
= 1;
924 AsyncHead
->HwQH
.EndpointCaps
.PipeMultiplier
= 1;
925 AsyncHead
->HwQH
.NextTD
|= TERMINATE_POINTER
;
926 AsyncHead
->HwQH
.Token
.Status
= (UCHAR
)EHCI_TOKEN_STATUS_HALTED
;
928 AsyncHead
->PhysicalAddress
= AsyncHeadPA
;
929 AsyncHead
->PrevHead
= AsyncHead
->NextHead
= (PEHCI_HCD_QH
)AsyncHead
;
931 EhciExtension
->AsyncHead
= AsyncHead
;
933 /* Periodic Schedule */
935 PeriodicHead
= &HcResourcesVA
->PeriodicHead
[0];
936 PeriodicHeadPA
= HcResourcesPA
+ FIELD_OFFSET(EHCI_HC_RESOURCES
, PeriodicHead
[0]);
938 for (ix
= 0; ix
< (INTERRUPT_ENDPOINTs
+ 1); ix
++)
940 EHCI_AlignHwStructure(EhciExtension
,
942 (PULONG_PTR
)&PeriodicHead
,
945 EhciExtension
->PeriodicHead
[ix
] = PeriodicHead
;
946 EhciExtension
->PeriodicHead
[ix
]->PhysicalAddress
= PeriodicHeadPA
;
949 PeriodicHeadPA
+= sizeof(EHCI_STATIC_QH
);
952 EHCI_InitializeInterruptSchedule(EhciExtension
);
954 for (Frame
= 0; Frame
< EHCI_FRAME_LIST_MAX_ENTRIES
; Frame
++)
956 StaticQH
= EHCI_GetQhForFrame(EhciExtension
, Frame
);
958 StaticHeadPA
.AsULONG
= StaticQH
->PhysicalAddress
;
959 StaticHeadPA
.Type
= EHCI_LINK_TYPE_QH
;
961 //DPRINT_EHCI("EHCI_InitializeSchedule: StaticHeadPA[%x] - %X\n",
965 HcResourcesVA
->PeriodicFrameList
[Frame
] = StaticHeadPA
.AsULONG
;
968 EhciExtension
->IsoDummyQHListVA
= &HcResourcesVA
->IsoDummyQH
[0];
969 EhciExtension
->IsoDummyQHListPA
= HcResourcesPA
+ FIELD_OFFSET(EHCI_HC_RESOURCES
, IsoDummyQH
[0]);
971 EHCI_AddDummyQHs(EhciExtension
);
973 WRITE_REGISTER_ULONG(&OperationalRegs
->PeriodicListBase
,
974 EhciExtension
->HcResourcesPA
+ FIELD_OFFSET(EHCI_HC_RESOURCES
, PeriodicFrameList
));
976 WRITE_REGISTER_ULONG(&OperationalRegs
->AsyncListBase
,
979 return MP_STATUS_SUCCESS
;
984 EHCI_InitializeHardware(IN PEHCI_EXTENSION EhciExtension
)
986 PEHCI_HC_CAPABILITY_REGISTERS CapabilityRegisters
;
987 PEHCI_HW_REGISTERS OperationalRegs
;
988 EHCI_USB_COMMAND Command
;
989 LARGE_INTEGER EndTime
;
990 LARGE_INTEGER CurrentTime
;
991 EHCI_HC_STRUCTURAL_PARAMS StructuralParams
;
993 DPRINT("EHCI_InitializeHardware: ... \n");
995 OperationalRegs
= EhciExtension
->OperationalRegs
;
996 CapabilityRegisters
= EhciExtension
->CapabilityRegisters
;
998 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1000 WRITE_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
, Command
.AsULONG
);
1002 KeQuerySystemTime(&EndTime
);
1003 EndTime
.QuadPart
+= 100 * 10000; // 100 msec
1005 DPRINT("EHCI_InitializeHardware: Start reset ... \n");
1009 KeQuerySystemTime(&CurrentTime
);
1010 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1012 if (Command
.Reset
!= 1)
1015 if (CurrentTime
.QuadPart
>= EndTime
.QuadPart
)
1017 if (Command
.Reset
== 1)
1019 DPRINT1("EHCI_InitializeHardware: Reset failed!\n");
1020 return MP_STATUS_HW_ERROR
;
1027 DPRINT("EHCI_InitializeHardware: Reset - OK\n");
1029 StructuralParams
.AsULONG
= READ_REGISTER_ULONG(&CapabilityRegisters
->StructParameters
.AsULONG
);
1031 EhciExtension
->NumberOfPorts
= StructuralParams
.PortCount
;
1032 EhciExtension
->PortPowerControl
= StructuralParams
.PortPowerControl
;
1034 DPRINT("EHCI_InitializeHardware: StructuralParams - %X\n", StructuralParams
.AsULONG
);
1035 DPRINT("EHCI_InitializeHardware: PortPowerControl - %x\n", EhciExtension
->PortPowerControl
);
1036 DPRINT("EHCI_InitializeHardware: N_PORTS - %x\n", EhciExtension
->NumberOfPorts
);
1038 WRITE_REGISTER_ULONG(&OperationalRegs
->PeriodicListBase
, 0);
1039 WRITE_REGISTER_ULONG(&OperationalRegs
->AsyncListBase
, 0);
1041 EhciExtension
->InterruptMask
.AsULONG
= 0;
1042 EhciExtension
->InterruptMask
.Interrupt
= 1;
1043 EhciExtension
->InterruptMask
.ErrorInterrupt
= 1;
1044 EhciExtension
->InterruptMask
.PortChangeInterrupt
= 0;
1045 EhciExtension
->InterruptMask
.FrameListRollover
= 1;
1046 EhciExtension
->InterruptMask
.HostSystemError
= 1;
1047 EhciExtension
->InterruptMask
.InterruptOnAsyncAdvance
= 1;
1049 return MP_STATUS_SUCCESS
;
1054 EHCI_GetOffsetEECP(IN PEHCI_EXTENSION EhciExtension
,
1055 IN UCHAR CapabilityID
)
1057 EHCI_LEGACY_EXTENDED_CAPABILITY LegacyCapability
;
1058 EHCI_HC_CAPABILITY_PARAMS CapParameters
;
1061 DPRINT("EHCI_GetOffsetEECP: CapabilityID - %x\n", CapabilityID
);
1063 CapParameters
= EhciExtension
->CapabilityRegisters
->CapParameters
;
1065 OffsetEECP
= CapParameters
.ExtCapabilitiesPointer
;
1072 RegPacket
.UsbPortReadWriteConfigSpace(EhciExtension
,
1074 &LegacyCapability
.AsULONG
,
1076 sizeof(LegacyCapability
));
1078 DPRINT("EHCI_GetOffsetEECP: OffsetEECP - %x\n", OffsetEECP
);
1080 if (LegacyCapability
.CapabilityID
== CapabilityID
)
1083 OffsetEECP
= LegacyCapability
.NextCapabilityPointer
;
1094 EHCI_TakeControlHC(IN PEHCI_EXTENSION EhciExtension
)
1096 LARGE_INTEGER EndTime
;
1097 LARGE_INTEGER CurrentTime
;
1098 EHCI_LEGACY_EXTENDED_CAPABILITY LegacyCapability
;
1101 DPRINT("EHCI_TakeControlHC: EhciExtension - %p\n", EhciExtension
);
1103 OffsetEECP
= EHCI_GetOffsetEECP(EhciExtension
, 1);
1105 if (OffsetEECP
== 0)
1106 return MP_STATUS_SUCCESS
;
1108 DPRINT("EHCI_TakeControlHC: OffsetEECP - %X\n", OffsetEECP
);
1110 RegPacket
.UsbPortReadWriteConfigSpace(EhciExtension
,
1112 &LegacyCapability
.AsULONG
,
1114 sizeof(LegacyCapability
));
1116 if (LegacyCapability
.BiosOwnedSemaphore
== 0)
1117 return MP_STATUS_SUCCESS
;
1119 LegacyCapability
.OsOwnedSemaphore
= 1;
1121 RegPacket
.UsbPortReadWriteConfigSpace(EhciExtension
,
1123 &LegacyCapability
.AsULONG
,
1125 sizeof(LegacyCapability
));
1127 KeQuerySystemTime(&EndTime
);
1128 EndTime
.QuadPart
+= 100 * 10000;
1132 RegPacket
.UsbPortReadWriteConfigSpace(EhciExtension
,
1134 &LegacyCapability
.AsULONG
,
1136 sizeof(LegacyCapability
));
1137 KeQuerySystemTime(&CurrentTime
);
1139 if (LegacyCapability
.BiosOwnedSemaphore
)
1141 DPRINT("EHCI_TakeControlHC: Ownership is ok\n");
1145 while (CurrentTime
.QuadPart
<= EndTime
.QuadPart
);
1147 return MP_STATUS_SUCCESS
;
1152 EHCI_GetRegistryParameters(IN PEHCI_EXTENSION EhciExtension
)
1154 DPRINT1("EHCI_GetRegistryParameters: UNIMPLEMENTED. FIXME\n");
1159 EHCI_StartController(IN PVOID ehciExtension
,
1160 IN PUSBPORT_RESOURCES Resources
)
1162 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
1163 PEHCI_HC_CAPABILITY_REGISTERS CapabilityRegisters
;
1164 PEHCI_HW_REGISTERS OperationalRegs
;
1166 EHCI_USB_COMMAND Command
;
1167 UCHAR CapabilityRegLength
;
1170 DPRINT("EHCI_StartController: ... \n");
1172 if ((Resources
->ResourcesTypes
& (USBPORT_RESOURCES_MEMORY
| USBPORT_RESOURCES_INTERRUPT
)) !=
1173 (USBPORT_RESOURCES_MEMORY
| USBPORT_RESOURCES_INTERRUPT
))
1175 DPRINT1("EHCI_StartController: Resources->ResourcesTypes - %x\n",
1176 Resources
->ResourcesTypes
);
1178 return MP_STATUS_ERROR
;
1181 CapabilityRegisters
= (PEHCI_HC_CAPABILITY_REGISTERS
)Resources
->ResourceBase
;
1182 EhciExtension
->CapabilityRegisters
= CapabilityRegisters
;
1184 CapabilityRegLength
= READ_REGISTER_UCHAR(&CapabilityRegisters
->RegistersLength
);
1186 OperationalRegs
= (PEHCI_HW_REGISTERS
)((ULONG_PTR
)CapabilityRegisters
+
1187 CapabilityRegLength
);
1189 EhciExtension
->OperationalRegs
= OperationalRegs
;
1191 DPRINT("EHCI_StartController: CapabilityRegisters - %p\n", CapabilityRegisters
);
1192 DPRINT("EHCI_StartController: OperationalRegs - %p\n", OperationalRegs
);
1194 RegPacket
.UsbPortReadWriteConfigSpace(EhciExtension
,
1197 EHCI_FLADJ_PCI_CONFIG_OFFSET
,
1200 EhciExtension
->FrameLengthAdjustment
= Fladj
;
1202 EHCI_GetRegistryParameters(EhciExtension
);
1204 MPStatus
= EHCI_TakeControlHC(EhciExtension
);
1208 DPRINT1("EHCI_StartController: Unsuccessful TakeControlHC()\n");
1212 MPStatus
= EHCI_InitializeHardware(EhciExtension
);
1216 DPRINT1("EHCI_StartController: Unsuccessful InitializeHardware()\n");
1220 MPStatus
= EHCI_InitializeSchedule(EhciExtension
,
1222 Resources
->StartPA
);
1226 DPRINT1("EHCI_StartController: Unsuccessful InitializeSchedule()\n");
1230 RegPacket
.UsbPortReadWriteConfigSpace(EhciExtension
,
1233 EHCI_FLADJ_PCI_CONFIG_OFFSET
,
1236 if (Fladj
!= EhciExtension
->FrameLengthAdjustment
)
1238 Fladj
= EhciExtension
->FrameLengthAdjustment
;
1240 RegPacket
.UsbPortReadWriteConfigSpace(EhciExtension
,
1243 EHCI_FLADJ_PCI_CONFIG_OFFSET
,
1247 /* Port routing control logic default-routes all ports to this HC */
1248 EhciExtension
->PortRoutingControl
= EHCI_CONFIG_FLAG_CONFIGURED
;
1249 WRITE_REGISTER_ULONG(&OperationalRegs
->ConfigFlag
,
1250 EhciExtension
->PortRoutingControl
);
1252 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1253 Command
.InterruptThreshold
= 1; // one micro-frame
1254 WRITE_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
, Command
.AsULONG
);
1256 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1257 Command
.Run
= 1; // execution of the schedule
1258 WRITE_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
, Command
.AsULONG
);
1260 EhciExtension
->IsStarted
= TRUE
;
1262 if (Resources
->IsChirpHandled
)
1266 for (Port
= 1; Port
<= EhciExtension
->NumberOfPorts
; Port
++)
1268 EHCI_RH_SetFeaturePortPower(EhciExtension
, Port
);
1271 RegPacket
.UsbPortWait(EhciExtension
, 200);
1273 for (Port
= 1; Port
<= EhciExtension
->NumberOfPorts
; Port
++)
1275 EHCI_RH_ChirpRootPort(EhciExtension
, Port
++);
1284 EHCI_StopController(IN PVOID ehciExtension
,
1285 IN BOOLEAN DisableInterrupts
)
1287 DPRINT1("EHCI_StopController: UNIMPLEMENTED. FIXME\n");
1292 EHCI_SuspendController(IN PVOID ehciExtension
)
1294 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
1295 PEHCI_HW_REGISTERS OperationalRegs
;
1296 EHCI_USB_COMMAND Command
;
1297 EHCI_USB_STATUS Status
;
1298 EHCI_INTERRUPT_ENABLE IntrEn
;
1301 DPRINT("EHCI_SuspendController: ... \n");
1303 OperationalRegs
= EhciExtension
->OperationalRegs
;
1305 EhciExtension
->BackupPeriodiclistbase
= READ_REGISTER_ULONG(&OperationalRegs
->PeriodicListBase
);
1306 EhciExtension
->BackupAsynclistaddr
= READ_REGISTER_ULONG(&OperationalRegs
->AsyncListBase
);
1307 EhciExtension
->BackupCtrlDSSegment
= READ_REGISTER_ULONG(&OperationalRegs
->SegmentSelector
);
1308 EhciExtension
->BackupUSBCmd
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1310 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1311 Command
.InterruptAdvanceDoorbell
= 0;
1312 WRITE_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
, Command
.AsULONG
);
1314 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1316 WRITE_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
, Command
.AsULONG
);
1318 KeStallExecutionProcessor(125);
1320 Status
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcStatus
.AsULONG
);
1322 Status
.HCHalted
= 0;
1323 Status
.Reclamation
= 0;
1324 Status
.PeriodicStatus
= 0;
1325 Status
.AsynchronousStatus
= 0;
1328 WRITE_REGISTER_ULONG(&OperationalRegs
->HcStatus
.AsULONG
, Status
.AsULONG
);
1330 WRITE_REGISTER_ULONG(&OperationalRegs
->HcInterruptEnable
.AsULONG
, 0);
1332 for (ix
= 0; ix
< 10; ix
++)
1334 Status
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcStatus
.AsULONG
);
1336 if (Status
.HCHalted
)
1339 RegPacket
.UsbPortWait(EhciExtension
, 1);
1342 if (!Status
.HCHalted
)
1345 IntrEn
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcInterruptEnable
.AsULONG
);
1346 IntrEn
.PortChangeInterrupt
= 1;
1347 WRITE_REGISTER_ULONG(&OperationalRegs
->HcInterruptEnable
.AsULONG
, IntrEn
.AsULONG
);
1349 EhciExtension
->Flags
|= EHCI_FLAGS_CONTROLLER_SUSPEND
;
1354 EHCI_ResumeController(IN PVOID ehciExtension
)
1356 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
1357 PEHCI_HW_REGISTERS OperationalRegs
;
1358 ULONG RoutingControl
;
1359 EHCI_USB_COMMAND Command
;
1361 DPRINT("EHCI_ResumeController: ... \n");
1363 OperationalRegs
= EhciExtension
->OperationalRegs
;
1365 RoutingControl
= EhciExtension
->PortRoutingControl
;
1367 if (!(RoutingControl
& EHCI_CONFIG_FLAG_CONFIGURED
))
1369 EhciExtension
->PortRoutingControl
= RoutingControl
| EHCI_CONFIG_FLAG_CONFIGURED
;
1370 WRITE_REGISTER_ULONG(&OperationalRegs
->ConfigFlag
,
1371 EhciExtension
->PortRoutingControl
);
1373 return MP_STATUS_HW_ERROR
;
1376 WRITE_REGISTER_ULONG(&OperationalRegs
->SegmentSelector
,
1377 EhciExtension
->BackupCtrlDSSegment
);
1379 WRITE_REGISTER_ULONG(&OperationalRegs
->PeriodicListBase
,
1380 EhciExtension
->BackupPeriodiclistbase
);
1382 WRITE_REGISTER_ULONG(&OperationalRegs
->AsyncListBase
,
1383 EhciExtension
->BackupAsynclistaddr
);
1385 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1387 Command
.AsULONG
= Command
.AsULONG
^ EhciExtension
->BackupUSBCmd
;
1390 Command
.FrameListSize
= 0;
1391 Command
.InterruptAdvanceDoorbell
= 0;
1392 Command
.LightResetHC
= 0;
1393 Command
.AsynchronousParkModeCount
= 0;
1394 Command
.AsynchronousParkModeEnable
= 0;
1398 WRITE_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
,
1401 WRITE_REGISTER_ULONG(&OperationalRegs
->HcInterruptEnable
.AsULONG
,
1402 EhciExtension
->InterruptMask
.AsULONG
);
1404 EhciExtension
->Flags
&= ~EHCI_FLAGS_CONTROLLER_SUSPEND
;
1406 return MP_STATUS_SUCCESS
;
1411 EHCI_HardwarePresent(IN PEHCI_EXTENSION EhciExtension
,
1412 IN BOOLEAN IsInvalidateController
)
1414 PEHCI_HW_REGISTERS OperationalRegs
= EhciExtension
->OperationalRegs
;
1416 if (READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
) != -1)
1419 DPRINT1("EHCI_HardwarePresent: IsInvalidateController - %x\n",
1420 IsInvalidateController
);
1422 if (!IsInvalidateController
)
1425 RegPacket
.UsbPortInvalidateController(EhciExtension
,
1426 USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE
);
1432 EHCI_InterruptService(IN PVOID ehciExtension
)
1434 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
1435 PEHCI_HW_REGISTERS OperationalRegs
;
1436 BOOLEAN Result
= FALSE
;
1437 EHCI_USB_STATUS IntrSts
;
1438 EHCI_INTERRUPT_ENABLE IntrEn
;
1439 EHCI_INTERRUPT_ENABLE iStatus
;
1440 EHCI_USB_COMMAND Command
;
1443 OperationalRegs
= EhciExtension
->OperationalRegs
;
1445 DPRINT_EHCI("EHCI_InterruptService: ... \n");
1447 Result
= EHCI_HardwarePresent(EhciExtension
, FALSE
);
1452 IntrEn
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcInterruptEnable
.AsULONG
);
1453 IntrSts
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcStatus
.AsULONG
);
1455 iStatus
.AsULONG
= (IntrEn
.AsULONG
& IntrSts
.AsULONG
) & EHCI_INTERRUPT_MASK
;
1457 if (!iStatus
.AsULONG
)
1460 EhciExtension
->InterruptStatus
= iStatus
;
1462 WRITE_REGISTER_ULONG(&OperationalRegs
->HcStatus
.AsULONG
, iStatus
.AsULONG
);
1464 if (iStatus
.HostSystemError
)
1466 EhciExtension
->HcSystemErrors
++;
1468 if (EhciExtension
->HcSystemErrors
< EHCI_MAX_HC_SYSTEM_ERRORS
)
1470 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1472 WRITE_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
, Command
.AsULONG
);
1476 FrameIndex
= READ_REGISTER_ULONG(&OperationalRegs
->FrameIndex
) / EHCI_MICROFRAMES
;
1477 FrameIndex
&= EHCI_FRINDEX_FRAME_MASK
;
1479 if ((FrameIndex
^ EhciExtension
->FrameIndex
) & EHCI_FRAME_LIST_MAX_ENTRIES
)
1481 EhciExtension
->FrameHighPart
+= 2 * EHCI_FRAME_LIST_MAX_ENTRIES
;
1483 EhciExtension
->FrameHighPart
-= (FrameIndex
^ EhciExtension
->FrameHighPart
) &
1484 EHCI_FRAME_LIST_MAX_ENTRIES
;
1487 EhciExtension
->FrameIndex
= FrameIndex
;
1494 EHCI_InterruptDpc(IN PVOID ehciExtension
,
1495 IN BOOLEAN EnableInterrupts
)
1497 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
1498 PEHCI_HW_REGISTERS OperationalRegs
;
1499 EHCI_INTERRUPT_ENABLE iStatus
;
1501 OperationalRegs
= EhciExtension
->OperationalRegs
;
1503 DPRINT_EHCI("EHCI_InterruptDpc: [%p] EnableInterrupts - %x\n",
1504 EhciExtension
, EnableInterrupts
);
1506 iStatus
= EhciExtension
->InterruptStatus
;
1507 EhciExtension
->InterruptStatus
.AsULONG
= 0;
1509 if (iStatus
.Interrupt
== 1 ||
1510 iStatus
.ErrorInterrupt
== 1 ||
1511 iStatus
.InterruptOnAsyncAdvance
== 1)
1513 DPRINT_EHCI("EHCI_InterruptDpc: [%p] InterruptStatus - %X\n", EhciExtension
, iStatus
.AsULONG
);
1514 RegPacket
.UsbPortInvalidateEndpoint(EhciExtension
, NULL
);
1517 if (iStatus
.PortChangeInterrupt
== 1)
1519 DPRINT_EHCI("EHCI_InterruptDpc: [%p] PortChangeInterrupt\n", EhciExtension
);
1520 RegPacket
.UsbPortInvalidateRootHub(EhciExtension
);
1523 if (EnableInterrupts
)
1525 WRITE_REGISTER_ULONG(&OperationalRegs
->HcInterruptEnable
.AsULONG
,
1526 EhciExtension
->InterruptMask
.AsULONG
);
1532 EHCI_MapAsyncTransferToTd(IN PEHCI_EXTENSION EhciExtension
,
1533 IN ULONG MaxPacketSize
,
1534 IN ULONG TransferedLen
,
1535 IN PULONG DataToggle
,
1536 IN PEHCI_TRANSFER EhciTransfer
,
1538 IN PUSBPORT_SCATTER_GATHER_LIST SgList
)
1540 PUSBPORT_TRANSFER_PARAMETERS TransferParameters
;
1541 PUSBPORT_SCATTER_GATHER_ELEMENT SgElement
;
1549 DPRINT_EHCI("EHCI_MapAsyncTransferToTd: EhciTransfer - %p, TD - %p, TransferedLen - %x, MaxPacketSize - %x, DataToggle - %x\n",
1556 TransferParameters
= EhciTransfer
->TransferParameters
;
1558 SgElement
= &SgList
->SgElement
[0];
1560 for (SgIdx
= 0; SgIdx
< SgList
->SgElementCount
; SgIdx
++)
1562 if (TransferedLen
>= SgElement
->SgOffset
&&
1563 TransferedLen
< SgElement
->SgOffset
+ SgElement
->SgTransferLength
)
1571 SgRemain
= SgList
->SgElementCount
- SgIdx
;
1573 if (SgRemain
> EHCI_MAX_QTD_BUFFER_PAGES
)
1575 TD
->HwTD
.Buffer
[0] = SgList
->SgElement
[SgIdx
].SgPhysicalAddress
.LowPart
-
1576 SgList
->SgElement
[SgIdx
].SgOffset
+
1579 LengthThisTD
= EHCI_MAX_QTD_BUFFER_PAGES
* PAGE_SIZE
-
1580 (TD
->HwTD
.Buffer
[0] & (PAGE_SIZE
- 1));
1582 for (ix
= 1; ix
< EHCI_MAX_QTD_BUFFER_PAGES
; ix
++)
1584 TD
->HwTD
.Buffer
[ix
] = SgList
->SgElement
[SgIdx
+ ix
].SgPhysicalAddress
.LowPart
;
1587 NumPackets
= LengthThisTD
/ MaxPacketSize
;
1588 DiffLength
= LengthThisTD
- MaxPacketSize
* (LengthThisTD
/ MaxPacketSize
);
1590 if (LengthThisTD
!= MaxPacketSize
* (LengthThisTD
/ MaxPacketSize
))
1591 LengthThisTD
-= DiffLength
;
1593 if (DataToggle
&& (NumPackets
& 1))
1594 *DataToggle
= !(*DataToggle
);
1598 LengthThisTD
= TransferParameters
->TransferBufferLength
- TransferedLen
;
1600 TD
->HwTD
.Buffer
[0] = TransferedLen
+
1601 SgList
->SgElement
[SgIdx
].SgPhysicalAddress
.LowPart
-
1602 SgList
->SgElement
[SgIdx
].SgOffset
;
1604 for (ix
= 1; ix
< EHCI_MAX_QTD_BUFFER_PAGES
; ix
++)
1606 if ((SgIdx
+ ix
) >= SgList
->SgElementCount
)
1609 TD
->HwTD
.Buffer
[ix
] = SgList
->SgElement
[SgIdx
+ ix
].SgPhysicalAddress
.LowPart
;
1613 TD
->HwTD
.Token
.TransferBytes
= LengthThisTD
;
1614 TD
->LengthThisTD
= LengthThisTD
;
1616 return LengthThisTD
+ TransferedLen
;
1621 EHCI_EnableAsyncList(IN PEHCI_EXTENSION EhciExtension
)
1623 PEHCI_HW_REGISTERS OperationalRegs
;
1624 EHCI_USB_COMMAND UsbCmd
;
1626 DPRINT_EHCI("EHCI_EnableAsyncList: ... \n");
1628 OperationalRegs
= EhciExtension
->OperationalRegs
;
1630 UsbCmd
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1631 UsbCmd
.AsynchronousEnable
= 1;
1632 WRITE_REGISTER_ULONG((&OperationalRegs
->HcCommand
.AsULONG
), UsbCmd
.AsULONG
);
1637 EHCI_DisableAsyncList(IN PEHCI_EXTENSION EhciExtension
)
1639 PEHCI_HW_REGISTERS OperationalRegs
;
1640 EHCI_USB_COMMAND UsbCmd
;
1642 DPRINT("EHCI_DisableAsyncList: ... \n");
1644 OperationalRegs
= EhciExtension
->OperationalRegs
;
1646 UsbCmd
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1647 UsbCmd
.AsynchronousEnable
= 0;
1648 WRITE_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
, UsbCmd
.AsULONG
);
1653 EHCI_EnablePeriodicList(IN PEHCI_EXTENSION EhciExtension
)
1655 PEHCI_HW_REGISTERS OperationalRegs
;
1656 EHCI_USB_COMMAND Command
;
1658 DPRINT("EHCI_EnablePeriodicList: ... \n");
1660 OperationalRegs
= EhciExtension
->OperationalRegs
;
1662 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1663 Command
.PeriodicEnable
= 1;
1664 WRITE_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
, Command
.AsULONG
);
1669 EHCI_FlushAsyncCache(IN PEHCI_EXTENSION EhciExtension
)
1671 PEHCI_HW_REGISTERS OperationalRegs
;
1672 EHCI_USB_COMMAND Command
;
1673 EHCI_USB_STATUS Status
;
1674 LARGE_INTEGER CurrentTime
;
1675 LARGE_INTEGER EndTime
;
1676 EHCI_USB_COMMAND Cmd
;
1678 DPRINT_EHCI("EHCI_FlushAsyncCache: EhciExtension - %p\n", EhciExtension
);
1680 OperationalRegs
= EhciExtension
->OperationalRegs
;
1681 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1682 Status
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcStatus
.AsULONG
);
1684 if (!Status
.AsynchronousStatus
&& !Command
.AsynchronousEnable
)
1687 if (Status
.AsynchronousStatus
&& !Command
.AsynchronousEnable
)
1689 KeQuerySystemTime(&EndTime
);
1690 EndTime
.QuadPart
+= 100 * 10000; //100 ms
1694 Status
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcStatus
.AsULONG
);
1695 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1696 KeQuerySystemTime(&CurrentTime
);
1698 if (CurrentTime
.QuadPart
> EndTime
.QuadPart
)
1699 RegPacket
.UsbPortBugCheck(EhciExtension
);
1701 while (Status
.AsynchronousStatus
&& Command
.AsULONG
!= -1 && Command
.Run
);
1706 if (!Status
.AsynchronousStatus
&& Command
.AsynchronousEnable
)
1708 KeQuerySystemTime(&EndTime
);
1709 EndTime
.QuadPart
+= 100 * 10000; //100 ms
1713 Status
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcStatus
.AsULONG
);
1714 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1715 KeQuerySystemTime(&CurrentTime
);
1717 while (!Status
.AsynchronousStatus
&& Command
.AsULONG
!= -1 && Command
.Run
);
1720 Command
.InterruptAdvanceDoorbell
= 1;
1721 WRITE_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
, Command
.AsULONG
);
1723 KeQuerySystemTime(&EndTime
);
1724 EndTime
.QuadPart
+= 100 * 10000; //100 ms
1726 Cmd
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1728 if (Cmd
.InterruptAdvanceDoorbell
)
1732 if (Cmd
.AsULONG
== -1)
1735 KeStallExecutionProcessor(1);
1736 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1737 KeQuerySystemTime(&CurrentTime
);
1739 if (!Command
.InterruptAdvanceDoorbell
)
1746 /* InterruptOnAsyncAdvance */
1747 WRITE_REGISTER_ULONG(&OperationalRegs
->HcStatus
.AsULONG
, 0x20);
1752 EHCI_LockQH(IN PEHCI_EXTENSION EhciExtension
,
1754 IN ULONG TransferType
)
1756 PEHCI_HCD_QH PrevQH
;
1757 PEHCI_HCD_QH NextQH
;
1759 ULONG FrameIndexReg
;
1760 PEHCI_HW_REGISTERS OperationalRegs
;
1761 EHCI_USB_COMMAND Command
;
1763 DPRINT_EHCI("EHCI_LockQH: QH - %p, TransferType - %x\n",
1767 OperationalRegs
= EhciExtension
->OperationalRegs
;
1769 ASSERT((QH
->sqh
.QhFlags
& EHCI_QH_FLAG_UPDATING
) == 0);
1770 ASSERT(EhciExtension
->LockQH
== NULL
);
1772 PrevQH
= QH
->sqh
.PrevHead
;
1773 QH
->sqh
.QhFlags
|= EHCI_QH_FLAG_UPDATING
;
1777 NextQH
= QH
->sqh
.NextHead
;
1779 EhciExtension
->PrevQH
= PrevQH
;
1780 EhciExtension
->NextQH
= NextQH
;
1781 EhciExtension
->LockQH
= QH
;
1785 QhPA
= NextQH
->sqh
.PhysicalAddress
;
1786 QhPA
&= LINK_POINTER_MASK
+ TERMINATE_POINTER
;
1787 QhPA
|= (EHCI_LINK_TYPE_QH
<< 1);
1791 QhPA
= TERMINATE_POINTER
;
1794 PrevQH
->sqh
.HwQH
.HorizontalLink
.AsULONG
= QhPA
;
1796 FrameIndexReg
= READ_REGISTER_ULONG(&OperationalRegs
->FrameIndex
);
1798 if (TransferType
== USBPORT_TRANSFER_TYPE_INTERRUPT
)
1802 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
1804 while (READ_REGISTER_ULONG(&OperationalRegs
->FrameIndex
) ==
1805 FrameIndexReg
&& (Command
.AsULONG
!= -1) && Command
.Run
);
1809 EHCI_FlushAsyncCache(EhciExtension
);
1815 EHCI_UnlockQH(IN PEHCI_EXTENSION EhciExtension
,
1820 DPRINT_EHCI("EHCI_UnlockQH: QH - %p\n", QH
);
1822 ASSERT(QH
->sqh
.QhFlags
& EHCI_QH_FLAG_UPDATING
);
1823 ASSERT(EhciExtension
->LockQH
);
1824 ASSERT(EhciExtension
->LockQH
== QH
);
1826 QH
->sqh
.QhFlags
&= ~EHCI_QH_FLAG_UPDATING
;
1828 EhciExtension
->LockQH
= NULL
;
1830 QhPA
= QH
->sqh
.PhysicalAddress
;
1831 QhPA
&= LINK_POINTER_MASK
+ TERMINATE_POINTER
;
1832 QhPA
|= (EHCI_LINK_TYPE_QH
<< 1);
1834 EhciExtension
->PrevQH
->sqh
.HwQH
.HorizontalLink
.AsULONG
= QhPA
;
1839 EHCI_LinkTransferToQueue(IN PEHCI_EXTENSION EhciExtension
,
1840 IN PEHCI_ENDPOINT EhciEndpoint
,
1841 IN PEHCI_HCD_TD NextTD
)
1845 PEHCI_TRANSFER Transfer
;
1846 PEHCI_HCD_TD LinkTD
;
1850 DPRINT_EHCI("EHCI_LinkTransferToQueue: EhciEndpoint - %p, NextTD - %p\n",
1854 ASSERT(EhciEndpoint
->HcdHeadP
!= NULL
);
1855 IsPresent
= EHCI_HardwarePresent(EhciExtension
, 0);
1857 QH
= EhciEndpoint
->QH
;
1858 TD
= EhciEndpoint
->HcdHeadP
;
1860 if (TD
== EhciEndpoint
->HcdTailP
)
1864 EHCI_LockQH(EhciExtension
,
1866 EhciEndpoint
->EndpointProperties
.TransferType
);
1869 QH
->sqh
.HwQH
.CurrentTD
= EhciEndpoint
->DmaBufferPA
;
1870 QH
->sqh
.HwQH
.NextTD
= NextTD
->PhysicalAddress
;
1871 QH
->sqh
.HwQH
.AlternateNextTD
= NextTD
->HwTD
.AlternateNextTD
;
1873 QH
->sqh
.HwQH
.Token
.Status
= (UCHAR
)~(EHCI_TOKEN_STATUS_ACTIVE
|
1874 EHCI_TOKEN_STATUS_HALTED
);
1876 QH
->sqh
.HwQH
.Token
.TransferBytes
= 0;
1879 EHCI_UnlockQH(EhciExtension
, QH
);
1881 EhciEndpoint
->HcdHeadP
= NextTD
;
1885 DPRINT_EHCI("EHCI_LinkTransferToQueue: TD - %p, HcdTailP - %p\n",
1886 EhciEndpoint
->HcdHeadP
,
1887 EhciEndpoint
->HcdTailP
);
1889 LinkTD
= EhciEndpoint
->HcdHeadP
;
1891 while (TD
!= EhciEndpoint
->HcdTailP
)
1897 ASSERT(LinkTD
!= EhciEndpoint
->HcdTailP
);
1899 Transfer
= LinkTD
->EhciTransfer
;
1901 TD
= EhciEndpoint
->FirstTD
;
1903 for (ix
= 0; ix
< EhciEndpoint
->MaxTDs
; ix
++)
1905 if (TD
->EhciTransfer
== Transfer
)
1907 TD
->AltNextHcdTD
= NextTD
;
1908 TD
->HwTD
.AlternateNextTD
= NextTD
->PhysicalAddress
;
1914 LinkTD
->HwTD
.NextTD
= NextTD
->PhysicalAddress
;
1915 LinkTD
->NextHcdTD
= NextTD
;
1917 if (QH
->sqh
.HwQH
.CurrentTD
== LinkTD
->PhysicalAddress
)
1919 QH
->sqh
.HwQH
.NextTD
= NextTD
->PhysicalAddress
;
1920 QH
->sqh
.HwQH
.AlternateNextTD
= TERMINATE_POINTER
;
1927 EHCI_ControlTransfer(IN PEHCI_EXTENSION EhciExtension
,
1928 IN PEHCI_ENDPOINT EhciEndpoint
,
1929 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters
,
1930 IN PEHCI_TRANSFER EhciTransfer
,
1931 IN PUSBPORT_SCATTER_GATHER_LIST SgList
)
1933 PEHCI_HCD_TD FirstTD
;
1934 PEHCI_HCD_TD LastTD
;
1936 PEHCI_HCD_TD PrevTD
;
1937 PEHCI_HCD_TD LinkTD
;
1938 ULONG TransferedLen
= 0;
1939 EHCI_TD_TOKEN Token
;
1940 ULONG DataToggle
= 1;
1942 DPRINT_EHCI("EHCI_ControlTransfer: EhciEndpoint - %p, EhciTransfer - %p\n",
1946 if (EhciEndpoint
->RemainTDs
< EHCI_MAX_CONTROL_TD_COUNT
)
1947 return MP_STATUS_FAILURE
;
1949 EhciExtension
->PendingTransfers
++;
1950 EhciEndpoint
->PendingTDs
++;
1952 EhciTransfer
->TransferOnAsyncList
= 1;
1954 FirstTD
= EHCI_AllocTd(EhciExtension
, EhciEndpoint
);
1958 RegPacket
.UsbPortBugCheck(EhciExtension
);
1959 return MP_STATUS_FAILURE
;
1962 EhciTransfer
->PendingTDs
++;
1964 FirstTD
->TdFlags
|= EHCI_HCD_TD_FLAG_PROCESSED
;
1965 FirstTD
->EhciTransfer
= EhciTransfer
;
1967 FirstTD
->HwTD
.Buffer
[0] = FirstTD
->PhysicalAddress
+ FIELD_OFFSET(EHCI_HCD_TD
, SetupPacket
);
1968 FirstTD
->HwTD
.Buffer
[1] = 0;
1969 FirstTD
->HwTD
.Buffer
[2] = 0;
1970 FirstTD
->HwTD
.Buffer
[3] = 0;
1971 FirstTD
->HwTD
.Buffer
[4] = 0;
1973 FirstTD
->NextHcdTD
= NULL
;
1975 FirstTD
->HwTD
.NextTD
= TERMINATE_POINTER
;
1976 FirstTD
->HwTD
.AlternateNextTD
= TERMINATE_POINTER
;
1978 FirstTD
->HwTD
.Token
.AsULONG
= 0;
1979 FirstTD
->HwTD
.Token
.ErrorCounter
= 3;
1980 FirstTD
->HwTD
.Token
.PIDCode
= EHCI_TD_TOKEN_PID_SETUP
;
1981 FirstTD
->HwTD
.Token
.Status
= (UCHAR
)EHCI_TOKEN_STATUS_ACTIVE
;
1982 FirstTD
->HwTD
.Token
.TransferBytes
= sizeof(FirstTD
->SetupPacket
);
1984 RtlCopyMemory(&FirstTD
->SetupPacket
,
1985 &TransferParameters
->SetupPacket
,
1986 sizeof(FirstTD
->SetupPacket
));
1988 LastTD
= EHCI_AllocTd(EhciExtension
, EhciEndpoint
);
1992 RegPacket
.UsbPortBugCheck(EhciExtension
);
1993 return MP_STATUS_FAILURE
;
1996 EhciTransfer
->PendingTDs
++;
1998 LastTD
->TdFlags
|= EHCI_HCD_TD_FLAG_PROCESSED
;
1999 LastTD
->EhciTransfer
= EhciTransfer
;
2001 LastTD
->HwTD
.Buffer
[0] = 0;
2002 LastTD
->HwTD
.Buffer
[1] = 0;
2003 LastTD
->HwTD
.Buffer
[2] = 0;
2004 LastTD
->HwTD
.Buffer
[3] = 0;
2005 LastTD
->HwTD
.Buffer
[4] = 0;
2007 LastTD
->NextHcdTD
= NULL
;
2008 LastTD
->HwTD
.NextTD
= TERMINATE_POINTER
;
2009 LastTD
->HwTD
.AlternateNextTD
= TERMINATE_POINTER
;
2011 LastTD
->HwTD
.Token
.AsULONG
= 0;
2012 LastTD
->HwTD
.Token
.ErrorCounter
= 3;
2014 FirstTD
->AltNextHcdTD
= LastTD
;
2015 FirstTD
->HwTD
.AlternateNextTD
= LastTD
->PhysicalAddress
;
2020 while (TransferedLen
< TransferParameters
->TransferBufferLength
)
2022 TD
= EHCI_AllocTd(EhciExtension
, EhciEndpoint
);
2026 RegPacket
.UsbPortBugCheck(EhciExtension
);
2027 return MP_STATUS_FAILURE
;
2032 EhciTransfer
->PendingTDs
++;
2034 TD
->TdFlags
|= EHCI_HCD_TD_FLAG_PROCESSED
;
2035 TD
->EhciTransfer
= EhciTransfer
;
2037 TD
->HwTD
.Buffer
[0] = 0;
2038 TD
->HwTD
.Buffer
[1] = 0;
2039 TD
->HwTD
.Buffer
[2] = 0;
2040 TD
->HwTD
.Buffer
[3] = 0;
2041 TD
->HwTD
.Buffer
[4] = 0;
2043 TD
->NextHcdTD
= NULL
;
2045 TD
->HwTD
.NextTD
= TERMINATE_POINTER
;
2046 TD
->HwTD
.AlternateNextTD
= TERMINATE_POINTER
;
2048 TD
->HwTD
.Token
.AsULONG
= 0;
2049 TD
->HwTD
.Token
.ErrorCounter
= 3;
2051 PrevTD
->NextHcdTD
= TD
;
2052 PrevTD
->HwTD
.NextTD
= TD
->PhysicalAddress
;
2054 if (TransferParameters
->TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
2055 TD
->HwTD
.Token
.PIDCode
= EHCI_TD_TOKEN_PID_IN
;
2057 TD
->HwTD
.Token
.PIDCode
= EHCI_TD_TOKEN_PID_OUT
;
2059 TD
->HwTD
.Token
.DataToggle
= DataToggle
;
2060 TD
->HwTD
.Token
.Status
= (UCHAR
)EHCI_TOKEN_STATUS_ACTIVE
;
2063 TD
->HwTD
.Token
.DataToggle
= 1;
2065 TD
->HwTD
.Token
.DataToggle
= 0;
2067 TD
->AltNextHcdTD
= LastTD
;
2068 TD
->HwTD
.AlternateNextTD
= LastTD
->PhysicalAddress
;
2070 TransferedLen
= EHCI_MapAsyncTransferToTd(EhciExtension
,
2071 EhciEndpoint
->EndpointProperties
.MaxPacketSize
,
2081 LinkTD
->NextHcdTD
= LastTD
;
2082 LinkTD
->HwTD
.NextTD
= LastTD
->PhysicalAddress
;
2084 LastTD
->HwTD
.Buffer
[0] = 0;
2085 LastTD
->LengthThisTD
= 0;
2088 Token
.Status
= (UCHAR
)EHCI_TOKEN_STATUS_ACTIVE
;
2089 Token
.InterruptOnComplete
= 1;
2090 Token
.DataToggle
= 1;
2092 if (TransferParameters
->TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
2093 Token
.PIDCode
= EHCI_TD_TOKEN_PID_OUT
;
2095 Token
.PIDCode
= EHCI_TD_TOKEN_PID_IN
;
2097 LastTD
->HwTD
.Token
= Token
;
2099 LastTD
->NextHcdTD
= EhciEndpoint
->HcdTailP
;
2100 LastTD
->HwTD
.NextTD
= EhciEndpoint
->HcdTailP
->PhysicalAddress
;
2102 EHCI_EnableAsyncList(EhciExtension
);
2103 EHCI_LinkTransferToQueue(EhciExtension
, EhciEndpoint
, FirstTD
);
2105 ASSERT(EhciEndpoint
->HcdTailP
->NextHcdTD
== NULL
);
2106 ASSERT(EhciEndpoint
->HcdTailP
->AltNextHcdTD
== NULL
);
2108 return MP_STATUS_SUCCESS
;
2113 EHCI_BulkTransfer(IN PEHCI_EXTENSION EhciExtension
,
2114 IN PEHCI_ENDPOINT EhciEndpoint
,
2115 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters
,
2116 IN PEHCI_TRANSFER EhciTransfer
,
2117 IN PUSBPORT_SCATTER_GATHER_LIST SgList
)
2119 PEHCI_HCD_TD PrevTD
;
2120 PEHCI_HCD_TD FirstTD
;
2122 ULONG TransferedLen
;
2124 DPRINT_EHCI("EHCI_BulkTransfer: EhciEndpoint - %p, EhciTransfer - %p\n",
2128 if (((TransferParameters
->TransferBufferLength
/
2129 ((EHCI_MAX_QTD_BUFFER_PAGES
- 1) * PAGE_SIZE
)) + 1) > EhciEndpoint
->RemainTDs
)
2131 DPRINT1("EHCI_BulkTransfer: return MP_STATUS_FAILURE\n");
2132 return MP_STATUS_FAILURE
;
2135 EhciExtension
->PendingTransfers
++;
2136 EhciEndpoint
->PendingTDs
++;
2138 EhciTransfer
->TransferOnAsyncList
= 1;
2143 if (TransferParameters
->TransferBufferLength
)
2145 while (TransferedLen
< TransferParameters
->TransferBufferLength
)
2147 TD
= EHCI_AllocTd(EhciExtension
, EhciEndpoint
);
2151 RegPacket
.UsbPortBugCheck(EhciExtension
);
2152 return MP_STATUS_FAILURE
;
2155 EhciTransfer
->PendingTDs
++;
2157 TD
->TdFlags
|= EHCI_HCD_TD_FLAG_PROCESSED
;
2158 TD
->EhciTransfer
= EhciTransfer
;
2160 TD
->HwTD
.Buffer
[0] = 0;
2161 TD
->HwTD
.Buffer
[1] = 0;
2162 TD
->HwTD
.Buffer
[2] = 0;
2163 TD
->HwTD
.Buffer
[3] = 0;
2164 TD
->HwTD
.Buffer
[4] = 0;
2166 TD
->NextHcdTD
= NULL
;
2167 TD
->HwTD
.NextTD
= TERMINATE_POINTER
;
2168 TD
->HwTD
.AlternateNextTD
= TERMINATE_POINTER
;
2170 TD
->HwTD
.Token
.AsULONG
= 0;
2171 TD
->HwTD
.Token
.ErrorCounter
= 3;
2173 if (EhciTransfer
->PendingTDs
== 1)
2179 PrevTD
->HwTD
.NextTD
= TD
->PhysicalAddress
;
2180 PrevTD
->NextHcdTD
= TD
;
2183 TD
->HwTD
.AlternateNextTD
= EhciEndpoint
->HcdTailP
->PhysicalAddress
;
2184 TD
->AltNextHcdTD
= EhciEndpoint
->HcdTailP
;
2186 TD
->HwTD
.Token
.InterruptOnComplete
= 1;
2188 if (TransferParameters
->TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
2189 TD
->HwTD
.Token
.PIDCode
= EHCI_TD_TOKEN_PID_IN
;
2191 TD
->HwTD
.Token
.PIDCode
= EHCI_TD_TOKEN_PID_OUT
;
2193 TD
->HwTD
.Token
.Status
= (UCHAR
)EHCI_TOKEN_STATUS_ACTIVE
;
2194 TD
->HwTD
.Token
.DataToggle
= 1;
2196 TransferedLen
= EHCI_MapAsyncTransferToTd(EhciExtension
,
2197 EhciEndpoint
->EndpointProperties
.MaxPacketSize
,
2209 TD
= EHCI_AllocTd(EhciExtension
, EhciEndpoint
);
2213 RegPacket
.UsbPortBugCheck(EhciExtension
);
2214 return MP_STATUS_FAILURE
;
2217 EhciTransfer
->PendingTDs
++;
2219 TD
->TdFlags
|= EHCI_HCD_TD_FLAG_PROCESSED
;
2220 TD
->EhciTransfer
= EhciTransfer
;
2222 TD
->HwTD
.Buffer
[0] = 0;
2223 TD
->HwTD
.Buffer
[1] = 0;
2224 TD
->HwTD
.Buffer
[2] = 0;
2225 TD
->HwTD
.Buffer
[3] = 0;
2226 TD
->HwTD
.Buffer
[4] = 0;
2228 TD
->HwTD
.NextTD
= TERMINATE_POINTER
;
2229 TD
->HwTD
.AlternateNextTD
= TERMINATE_POINTER
;
2231 TD
->HwTD
.Token
.AsULONG
= 0;
2232 TD
->HwTD
.Token
.ErrorCounter
= 3;
2234 TD
->NextHcdTD
= NULL
;
2236 ASSERT(EhciTransfer
->PendingTDs
== 1);
2240 TD
->HwTD
.AlternateNextTD
= EhciEndpoint
->HcdTailP
->PhysicalAddress
;
2241 TD
->AltNextHcdTD
= EhciEndpoint
->HcdTailP
;
2243 TD
->HwTD
.Token
.InterruptOnComplete
= 1;
2245 if (TransferParameters
->TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
2246 TD
->HwTD
.Token
.PIDCode
= EHCI_TD_TOKEN_PID_IN
;
2248 TD
->HwTD
.Token
.PIDCode
= EHCI_TD_TOKEN_PID_OUT
;
2250 TD
->HwTD
.Buffer
[0] = TD
->PhysicalAddress
;
2252 TD
->HwTD
.Token
.Status
= (UCHAR
)EHCI_TOKEN_STATUS_ACTIVE
;
2253 TD
->HwTD
.Token
.DataToggle
= 1;
2255 TD
->LengthThisTD
= 0;
2258 TD
->HwTD
.NextTD
= EhciEndpoint
->HcdTailP
->PhysicalAddress
;
2259 TD
->NextHcdTD
= EhciEndpoint
->HcdTailP
;
2261 EHCI_EnableAsyncList(EhciExtension
);
2262 EHCI_LinkTransferToQueue(EhciExtension
, EhciEndpoint
, FirstTD
);
2264 ASSERT(EhciEndpoint
->HcdTailP
->NextHcdTD
== 0);
2265 ASSERT(EhciEndpoint
->HcdTailP
->AltNextHcdTD
== 0);
2267 return MP_STATUS_SUCCESS
;
2272 EHCI_InterruptTransfer(IN PEHCI_EXTENSION EhciExtension
,
2273 IN PEHCI_ENDPOINT EhciEndpoint
,
2274 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters
,
2275 IN PEHCI_TRANSFER EhciTransfer
,
2276 IN PUSBPORT_SCATTER_GATHER_LIST SgList
)
2279 PEHCI_HCD_TD FirstTD
;
2280 PEHCI_HCD_TD PrevTD
= NULL
;
2281 ULONG TransferedLen
= 0;
2283 DPRINT_EHCI("EHCI_InterruptTransfer: EhciEndpoint - %p, EhciTransfer - %p\n",
2287 if (!EhciEndpoint
->RemainTDs
)
2289 DPRINT1("EHCI_InterruptTransfer: EhciEndpoint - %p\n", EhciEndpoint
);
2291 return MP_STATUS_FAILURE
;
2294 EhciEndpoint
->PendingTDs
++;
2296 if (!TransferParameters
->TransferBufferLength
)
2298 DPRINT1("EHCI_InterruptTransfer: EhciEndpoint - %p\n", EhciEndpoint
);
2300 return MP_STATUS_FAILURE
;
2303 while (TransferedLen
< TransferParameters
->TransferBufferLength
)
2305 TD
= EHCI_AllocTd(EhciExtension
, EhciEndpoint
);
2309 DPRINT1("EHCI_InterruptTransfer: EhciEndpoint - %p\n", EhciEndpoint
);
2310 RegPacket
.UsbPortBugCheck(EhciExtension
);
2311 return MP_STATUS_FAILURE
;
2314 EhciTransfer
->PendingTDs
++;
2316 TD
->TdFlags
|= EHCI_HCD_TD_FLAG_PROCESSED
;
2317 TD
->EhciTransfer
= EhciTransfer
;
2319 TD
->HwTD
.Buffer
[0] = 0;
2320 TD
->HwTD
.Buffer
[1] = 0;
2321 TD
->HwTD
.Buffer
[2] = 0;
2322 TD
->HwTD
.Buffer
[3] = 0;
2323 TD
->HwTD
.Buffer
[4] = 0;
2325 TD
->HwTD
.NextTD
= TERMINATE_POINTER
;
2326 TD
->HwTD
.AlternateNextTD
= TERMINATE_POINTER
;
2328 TD
->HwTD
.Token
.AsULONG
= 0;
2329 TD
->HwTD
.Token
.ErrorCounter
= 3;
2331 TD
->NextHcdTD
= NULL
;
2333 if (EhciTransfer
->PendingTDs
== 1)
2339 PrevTD
->HwTD
.NextTD
= TD
->PhysicalAddress
;
2340 PrevTD
->NextHcdTD
= TD
;
2343 if (TransferParameters
->TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
2344 TD
->HwTD
.Token
.PIDCode
= EHCI_TD_TOKEN_PID_IN
;
2346 TD
->HwTD
.Token
.PIDCode
= EHCI_TD_TOKEN_PID_OUT
;
2348 TD
->HwTD
.Token
.Status
= (UCHAR
)EHCI_TOKEN_STATUS_ACTIVE
;
2349 TD
->HwTD
.Token
.DataToggle
= 1;
2351 TransferedLen
= EHCI_MapAsyncTransferToTd(EhciExtension
,
2352 EhciEndpoint
->EndpointProperties
.TotalMaxPacketSize
,
2362 TD
->HwTD
.Token
.InterruptOnComplete
= 1;
2364 DPRINT_EHCI("EHCI_InterruptTransfer: PendingTDs - %x, TD->PhysicalAddress - %p, FirstTD - %p\n",
2365 EhciTransfer
->PendingTDs
,
2366 TD
->PhysicalAddress
,
2369 TD
->HwTD
.NextTD
= EhciEndpoint
->HcdTailP
->PhysicalAddress
;
2370 TD
->NextHcdTD
= EhciEndpoint
->HcdTailP
;
2372 EHCI_LinkTransferToQueue(EhciExtension
, EhciEndpoint
, FirstTD
);
2374 ASSERT(EhciEndpoint
->HcdTailP
->NextHcdTD
== NULL
);
2375 ASSERT(EhciEndpoint
->HcdTailP
->AltNextHcdTD
== NULL
);
2377 EHCI_EnablePeriodicList(EhciExtension
);
2379 return MP_STATUS_SUCCESS
;
2384 EHCI_SubmitTransfer(IN PVOID ehciExtension
,
2385 IN PVOID ehciEndpoint
,
2386 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters
,
2387 IN PVOID ehciTransfer
,
2388 IN PUSBPORT_SCATTER_GATHER_LIST SgList
)
2390 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
2391 PEHCI_ENDPOINT EhciEndpoint
= ehciEndpoint
;
2392 PEHCI_TRANSFER EhciTransfer
= ehciTransfer
;
2395 DPRINT_EHCI("EHCI_SubmitTransfer: EhciEndpoint - %p, EhciTransfer - %p\n",
2399 RtlZeroMemory(EhciTransfer
, sizeof(EHCI_TRANSFER
));
2401 EhciTransfer
->TransferParameters
= TransferParameters
;
2402 EhciTransfer
->USBDStatus
= USBD_STATUS_SUCCESS
;
2403 EhciTransfer
->EhciEndpoint
= EhciEndpoint
;
2405 switch (EhciEndpoint
->EndpointProperties
.TransferType
)
2407 case USBPORT_TRANSFER_TYPE_CONTROL
:
2408 MPStatus
= EHCI_ControlTransfer(EhciExtension
,
2415 case USBPORT_TRANSFER_TYPE_BULK
:
2416 MPStatus
= EHCI_BulkTransfer(EhciExtension
,
2423 case USBPORT_TRANSFER_TYPE_INTERRUPT
:
2424 MPStatus
= EHCI_InterruptTransfer(EhciExtension
,
2433 MPStatus
= MP_STATUS_NOT_SUPPORTED
;
2442 EHCI_SubmitIsoTransfer(IN PVOID ehciExtension
,
2443 IN PVOID ehciEndpoint
,
2444 IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters
,
2445 IN PVOID ehciTransfer
,
2446 IN PVOID isoParameters
)
2448 DPRINT1("EHCI_SubmitIsoTransfer: UNIMPLEMENTED. FIXME\n");
2449 return MP_STATUS_SUCCESS
;
2454 EHCI_AbortIsoTransfer(IN PEHCI_EXTENSION EhciExtension
,
2455 IN PEHCI_ENDPOINT EhciEndpoint
,
2456 IN PEHCI_TRANSFER EhciTransfer
)
2458 DPRINT1("EHCI_AbortIsoTransfer: UNIMPLEMENTED. FIXME\n");
2463 EHCI_AbortAsyncTransfer(IN PEHCI_EXTENSION EhciExtension
,
2464 IN PEHCI_ENDPOINT EhciEndpoint
,
2465 IN PEHCI_TRANSFER EhciTransfer
)
2469 ULONG TransferLength
;
2470 PEHCI_HCD_TD CurrentTD
;
2471 PEHCI_TRANSFER CurrentTransfer
;
2473 PEHCI_HCD_TD LastTD
;
2474 PEHCI_HCD_TD PrevTD
;
2477 DPRINT("EHCI_AbortAsyncTransfer: EhciEndpoint - %p, EhciTransfer - %p\n",
2481 QH
= EhciEndpoint
->QH
;
2482 TD
= EhciEndpoint
->HcdHeadP
;
2484 ASSERT(EhciEndpoint
->PendingTDs
);
2485 EhciEndpoint
->PendingTDs
--;
2487 if (TD
->EhciTransfer
== EhciTransfer
)
2491 while (TD
!= EhciEndpoint
->HcdTailP
&&
2492 TD
->EhciTransfer
== EhciTransfer
)
2494 TransferLength
+= TD
->LengthThisTD
- TD
->HwTD
.Token
.TransferBytes
;
2496 TD
->HwTD
.NextTD
= 0;
2497 TD
->HwTD
.AlternateNextTD
= 0;
2500 TD
->EhciTransfer
= NULL
;
2502 EhciEndpoint
->RemainTDs
++;
2508 EhciTransfer
->TransferLen
+= TransferLength
;
2510 QH
->sqh
.HwQH
.CurrentTD
= EhciEndpoint
->DmaBufferPA
;
2511 QH
->sqh
.HwQH
.NextTD
= TD
->PhysicalAddress
;
2512 QH
->sqh
.HwQH
.AlternateNextTD
= TD
->HwTD
.AlternateNextTD
;
2514 QH
->sqh
.HwQH
.Token
.TransferBytes
= 0;
2515 QH
->sqh
.HwQH
.Token
.Status
= (UCHAR
)~(EHCI_TOKEN_STATUS_ACTIVE
|
2516 EHCI_TOKEN_STATUS_HALTED
);
2518 EhciEndpoint
->HcdHeadP
= TD
;
2522 DPRINT("EHCI_AbortAsyncTransfer: TD->EhciTransfer - %p\n", TD
->EhciTransfer
);
2524 CurrentTD
= RegPacket
.UsbPortGetMappedVirtualAddress(QH
->sqh
.HwQH
.CurrentTD
,
2528 CurrentTransfer
= CurrentTD
->EhciTransfer
;
2529 TD
= EhciEndpoint
->HcdHeadP
;
2531 while (TD
&& TD
->EhciTransfer
!= EhciTransfer
)
2537 FirstTdPA
= TD
->PhysicalAddress
;
2539 while (TD
&& TD
->EhciTransfer
== EhciTransfer
)
2541 TD
->HwTD
.NextTD
= 0;
2542 TD
->HwTD
.AlternateNextTD
= 0;
2545 TD
->EhciTransfer
= NULL
;
2547 EhciEndpoint
->RemainTDs
++;
2553 NextTD
= LastTD
->PhysicalAddress
+ FIELD_OFFSET(EHCI_HCD_TD
, HwTD
.NextTD
);
2555 PrevTD
->HwTD
.NextTD
= LastTD
->PhysicalAddress
;
2556 PrevTD
->HwTD
.AlternateNextTD
= LastTD
->PhysicalAddress
;
2558 PrevTD
->NextHcdTD
= LastTD
;
2559 PrevTD
->AltNextHcdTD
= LastTD
;
2561 if (CurrentTransfer
== EhciTransfer
)
2563 QH
->sqh
.HwQH
.CurrentTD
= EhciEndpoint
->DmaBufferPA
;
2565 QH
->sqh
.HwQH
.Token
.Status
= (UCHAR
)~EHCI_TOKEN_STATUS_ACTIVE
;
2566 QH
->sqh
.HwQH
.Token
.TransferBytes
= 0;
2568 QH
->sqh
.HwQH
.NextTD
= NextTD
;
2569 QH
->sqh
.HwQH
.AlternateNextTD
= TERMINATE_POINTER
;
2574 if (PrevTD
->EhciTransfer
== CurrentTransfer
)
2576 if (QH
->sqh
.HwQH
.NextTD
== FirstTdPA
)
2577 QH
->sqh
.HwQH
.NextTD
= NextTD
;
2579 if (QH
->sqh
.HwQH
.AlternateNextTD
== FirstTdPA
)
2580 QH
->sqh
.HwQH
.AlternateNextTD
= NextTD
;
2582 for (TD
= EhciEndpoint
->HcdHeadP
;
2586 if (TD
->EhciTransfer
== CurrentTransfer
)
2588 TD
->HwTD
.AlternateNextTD
= NextTD
;
2589 TD
->AltNextHcdTD
= LastTD
;
2598 EHCI_AbortTransfer(IN PVOID ehciExtension
,
2599 IN PVOID ehciEndpoint
,
2600 IN PVOID ehciTransfer
,
2601 IN PULONG CompletedLength
)
2603 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
2604 PEHCI_ENDPOINT EhciEndpoint
= ehciEndpoint
;
2605 PEHCI_TRANSFER EhciTransfer
= ehciTransfer
;
2608 DPRINT("EHCI_AbortTransfer: EhciTransfer - %p, CompletedLength - %x\n",
2612 TransferType
= EhciEndpoint
->EndpointProperties
.TransferType
;
2614 if (TransferType
== USBPORT_TRANSFER_TYPE_ISOCHRONOUS
)
2615 EHCI_AbortIsoTransfer(EhciExtension
, EhciEndpoint
, EhciTransfer
);
2617 EHCI_AbortAsyncTransfer(EhciExtension
, EhciEndpoint
, EhciTransfer
);
2622 EHCI_GetEndpointState(IN PVOID ehciExtension
,
2623 IN PVOID ehciEndpoint
)
2625 DPRINT1("EHCI_GetEndpointState: UNIMPLEMENTED. FIXME\n");
2631 EHCI_RemoveQhFromPeriodicList(IN PEHCI_EXTENSION EhciExtension
,
2632 IN PEHCI_ENDPOINT EhciEndpoint
)
2635 PEHCI_HCD_QH NextHead
;
2637 PEHCI_HCD_QH PrevHead
;
2639 QH
= EhciEndpoint
->QH
;
2641 if (!(QH
->sqh
.QhFlags
& EHCI_QH_FLAG_IN_SCHEDULE
))
2644 DPRINT("EHCI_RemoveQhFromPeriodicList: EhciEndpoint - %p, QH - %X, EhciEndpoint->StaticQH - %p\n",
2647 EhciEndpoint
->StaticQH
);
2649 NextHead
= QH
->sqh
.NextHead
;
2650 PrevHead
= QH
->sqh
.PrevHead
;
2652 PrevHead
->sqh
.NextHead
= NextHead
;
2656 if (!(NextHead
->sqh
.QhFlags
& EHCI_QH_FLAG_STATIC
))
2657 NextHead
->sqh
.PrevHead
= PrevHead
;
2659 NextQhPA
= NextHead
->sqh
.PhysicalAddress
;
2660 NextQhPA
&= LINK_POINTER_MASK
+ TERMINATE_POINTER
;
2661 NextQhPA
|= (EHCI_LINK_TYPE_QH
<< 1);
2663 PrevHead
->sqh
.HwQH
.HorizontalLink
.AsULONG
= NextQhPA
;
2667 PrevHead
->sqh
.HwQH
.HorizontalLink
.Terminate
= 1;
2670 QH
->sqh
.QhFlags
&= ~EHCI_QH_FLAG_IN_SCHEDULE
;
2672 QH
->sqh
.NextHead
= NULL
;
2673 QH
->sqh
.PrevHead
= NULL
;
2678 EHCI_RemoveQhFromAsyncList(IN PEHCI_EXTENSION EhciExtension
,
2681 PEHCI_HCD_QH NextHead
;
2683 PEHCI_HCD_QH PrevHead
;
2684 PEHCI_STATIC_QH AsyncHead
;
2687 DPRINT("EHCI_RemoveQhFromAsyncList: QH - %p\n", QH
);
2689 if (QH
->sqh
.QhFlags
& EHCI_QH_FLAG_IN_SCHEDULE
)
2691 NextHead
= QH
->sqh
.NextHead
;
2692 PrevHead
= QH
->sqh
.PrevHead
;
2694 AsyncHead
= EhciExtension
->AsyncHead
;
2696 AsyncHeadPA
= AsyncHead
->PhysicalAddress
;
2697 AsyncHeadPA
&= LINK_POINTER_MASK
+ TERMINATE_POINTER
;
2698 AsyncHeadPA
|= (EHCI_LINK_TYPE_QH
<< 1);
2700 NextHeadPA
= NextHead
->sqh
.PhysicalAddress
;
2701 NextHeadPA
&= LINK_POINTER_MASK
+ TERMINATE_POINTER
;
2702 NextHeadPA
|= (EHCI_LINK_TYPE_QH
<< 1);
2704 PrevHead
->sqh
.HwQH
.HorizontalLink
.AsULONG
= NextHeadPA
;
2706 PrevHead
->sqh
.NextHead
= NextHead
;
2707 NextHead
->sqh
.PrevHead
= PrevHead
;
2709 EHCI_FlushAsyncCache(EhciExtension
);
2711 if (READ_REGISTER_ULONG(&EhciExtension
->OperationalRegs
->AsyncListBase
) ==
2712 QH
->sqh
.PhysicalAddress
)
2714 WRITE_REGISTER_ULONG(&EhciExtension
->OperationalRegs
->AsyncListBase
,
2718 QH
->sqh
.QhFlags
&= ~EHCI_QH_FLAG_IN_SCHEDULE
;
2724 EHCI_InsertQhInPeriodicList(IN PEHCI_EXTENSION EhciExtension
,
2725 IN PEHCI_ENDPOINT EhciEndpoint
)
2727 PEHCI_STATIC_QH StaticQH
;
2730 PEHCI_HCD_QH NextHead
;
2731 PEHCI_HCD_QH PrevHead
;
2733 QH
= EhciEndpoint
->QH
;
2734 StaticQH
= EhciEndpoint
->StaticQH
;
2736 ASSERT((QH
->sqh
.QhFlags
& EHCI_QH_FLAG_IN_SCHEDULE
) == 0);
2737 ASSERT(StaticQH
->QhFlags
& EHCI_QH_FLAG_STATIC
);
2739 NextHead
= StaticQH
->NextHead
;
2741 QH
->sqh
.Period
= EhciEndpoint
->EndpointProperties
.Period
;
2742 QH
->sqh
.Ordinal
= EhciEndpoint
->EndpointProperties
.Reserved6
;
2744 DPRINT("EHCI_InsertQhInPeriodicList: EhciEndpoint - %p, QH - %X, EhciEndpoint->StaticQH - %p\n",
2747 EhciEndpoint
->StaticQH
);
2749 PrevHead
= (PEHCI_HCD_QH
)StaticQH
;
2751 if ((StaticQH
->QhFlags
& EHCI_QH_FLAG_STATIC
) &&
2752 (!NextHead
|| (NextHead
->sqh
.QhFlags
& EHCI_QH_FLAG_STATIC
)))
2754 DPRINT("EHCI_InsertQhInPeriodicList: StaticQH - %p, StaticQH->NextHead - %p\n",
2756 StaticQH
->NextHead
);
2761 !(NextHead
->sqh
.QhFlags
& EHCI_QH_FLAG_STATIC
) &&
2762 QH
->sqh
.Ordinal
> NextHead
->sqh
.Ordinal
)
2764 PrevHead
= NextHead
;
2765 NextHead
= NextHead
->sqh
.NextHead
;
2769 QH
->sqh
.NextHead
= NextHead
;
2770 QH
->sqh
.PrevHead
= PrevHead
;
2772 if (NextHead
&& !(NextHead
->sqh
.QhFlags
& EHCI_QH_FLAG_STATIC
))
2773 NextHead
->sqh
.PrevHead
= QH
;
2775 QH
->sqh
.QhFlags
|= EHCI_QH_FLAG_IN_SCHEDULE
;
2776 QH
->sqh
.HwQH
.HorizontalLink
= PrevHead
->sqh
.HwQH
.HorizontalLink
;
2778 PrevHead
->sqh
.NextHead
= QH
;
2780 QhPA
= QH
->sqh
.PhysicalAddress
;
2781 QhPA
&= LINK_POINTER_MASK
+ TERMINATE_POINTER
;
2782 QhPA
|= (EHCI_LINK_TYPE_QH
<< 1);
2784 PrevHead
->sqh
.HwQH
.HorizontalLink
.AsULONG
= QhPA
;
2789 EHCI_InsertQhInAsyncList(IN PEHCI_EXTENSION EhciExtension
,
2792 PEHCI_STATIC_QH AsyncHead
;
2794 PEHCI_HCD_QH NextHead
;
2796 DPRINT("EHCI_InsertQhInAsyncList: QH - %p\n", QH
);
2798 ASSERT((QH
->sqh
.QhFlags
& EHCI_QH_FLAG_IN_SCHEDULE
) == 0);
2799 ASSERT((QH
->sqh
.QhFlags
& EHCI_QH_FLAG_NUKED
) == 0);
2801 AsyncHead
= EhciExtension
->AsyncHead
;
2802 NextHead
= AsyncHead
->NextHead
;
2804 QH
->sqh
.HwQH
.HorizontalLink
= AsyncHead
->HwQH
.HorizontalLink
;
2805 QH
->sqh
.QhFlags
|= EHCI_QH_FLAG_IN_SCHEDULE
;
2806 QH
->sqh
.NextHead
= NextHead
;
2807 QH
->sqh
.PrevHead
= (PEHCI_HCD_QH
)AsyncHead
;
2809 NextHead
->sqh
.PrevHead
= QH
;
2811 QhPA
= QH
->sqh
.PhysicalAddress
;
2812 QhPA
&= LINK_POINTER_MASK
+ TERMINATE_POINTER
;
2813 QhPA
|= (EHCI_LINK_TYPE_QH
<< 1);
2815 AsyncHead
->HwQH
.HorizontalLink
.AsULONG
= QhPA
;
2817 AsyncHead
->NextHead
= QH
;
2822 EHCI_SetIsoEndpointState(IN PEHCI_EXTENSION EhciExtension
,
2823 IN PEHCI_ENDPOINT EhciEndpoint
,
2824 IN ULONG EndpointState
)
2826 DPRINT1("EHCI_SetIsoEndpointState: UNIMPLEMENTED. FIXME\n");
2831 EHCI_SetAsyncEndpointState(IN PEHCI_EXTENSION EhciExtension
,
2832 IN PEHCI_ENDPOINT EhciEndpoint
,
2833 IN ULONG EndpointState
)
2838 DPRINT("EHCI_SetAsyncEndpointState: EhciEndpoint - %p, EndpointState - %x\n",
2842 QH
= EhciEndpoint
->QH
;
2844 TransferType
= EhciEndpoint
->EndpointProperties
.TransferType
;
2846 switch (EndpointState
)
2848 case USBPORT_ENDPOINT_PAUSED
:
2849 if (TransferType
== USBPORT_TRANSFER_TYPE_INTERRUPT
)
2850 EHCI_RemoveQhFromPeriodicList(EhciExtension
, EhciEndpoint
);
2852 EHCI_RemoveQhFromAsyncList(EhciExtension
, EhciEndpoint
->QH
);
2856 case USBPORT_ENDPOINT_ACTIVE
:
2857 if (TransferType
== USBPORT_TRANSFER_TYPE_INTERRUPT
)
2858 EHCI_InsertQhInPeriodicList(EhciExtension
, EhciEndpoint
);
2860 EHCI_InsertQhInAsyncList(EhciExtension
, EhciEndpoint
->QH
);
2864 case USBPORT_ENDPOINT_REMOVE
:
2865 QH
->sqh
.QhFlags
|= EHCI_QH_FLAG_CLOSED
;
2867 if (TransferType
== USBPORT_TRANSFER_TYPE_INTERRUPT
)
2868 EHCI_RemoveQhFromPeriodicList(EhciExtension
, EhciEndpoint
);
2870 EHCI_RemoveQhFromAsyncList(EhciExtension
, EhciEndpoint
->QH
);
2879 EhciEndpoint
->EndpointState
= EndpointState
;
2884 EHCI_SetEndpointState(IN PVOID ehciExtension
,
2885 IN PVOID ehciEndpoint
,
2886 IN ULONG EndpointState
)
2888 PEHCI_ENDPOINT EhciEndpoint
;
2891 DPRINT("EHCI_SetEndpointState: ... \n");
2893 EhciEndpoint
= ehciEndpoint
;
2894 TransferType
= EhciEndpoint
->EndpointProperties
.TransferType
;
2896 if (TransferType
== USBPORT_TRANSFER_TYPE_CONTROL
||
2897 TransferType
== USBPORT_TRANSFER_TYPE_BULK
||
2898 TransferType
== USBPORT_TRANSFER_TYPE_INTERRUPT
)
2900 EHCI_SetAsyncEndpointState((PEHCI_EXTENSION
)ehciExtension
,
2904 else if (TransferType
== USBPORT_TRANSFER_TYPE_ISOCHRONOUS
)
2906 EHCI_SetIsoEndpointState((PEHCI_EXTENSION
)ehciExtension
,
2912 RegPacket
.UsbPortBugCheck(ehciExtension
);
2918 EHCI_InterruptNextSOF(IN PVOID ehciExtension
)
2920 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
2922 DPRINT_EHCI("EHCI_InterruptNextSOF: ... \n");
2924 RegPacket
.UsbPortInvalidateController(EhciExtension
,
2925 USBPORT_INVALIDATE_CONTROLLER_SOFT_INTERRUPT
);
2930 EHCI_GetErrorFromTD(IN PEHCI_HCD_TD TD
)
2932 EHCI_TD_TOKEN Token
;
2934 DPRINT_EHCI("EHCI_GetErrorFromTD: ... \n");
2936 ASSERT(TD
->HwTD
.Token
.Status
& EHCI_TOKEN_STATUS_HALTED
);
2938 Token
= TD
->HwTD
.Token
;
2940 if (Token
.Status
& EHCI_TOKEN_STATUS_TRANSACTION_ERROR
)
2942 DPRINT("EHCI_GetErrorFromTD: TD - %p, TRANSACTION_ERROR\n", TD
);
2943 return USBD_STATUS_XACT_ERROR
;
2946 if (Token
.Status
& EHCI_TOKEN_STATUS_BABBLE_DETECTED
)
2948 DPRINT("EHCI_GetErrorFromTD: TD - %p, BABBLE_DETECTED\n", TD
);
2949 return USBD_STATUS_BABBLE_DETECTED
;
2952 if (Token
.Status
& EHCI_TOKEN_STATUS_DATA_BUFFER_ERROR
)
2954 DPRINT("EHCI_GetErrorFromTD: TD - %p, DATA_BUFFER_ERROR\n", TD
);
2955 return USBD_STATUS_DATA_BUFFER_ERROR
;
2958 if (Token
.Status
& EHCI_TOKEN_STATUS_MISSED_MICROFRAME
)
2960 DPRINT("EHCI_GetErrorFromTD: TD - %p, MISSED_MICROFRAME\n", TD
);
2961 return USBD_STATUS_XACT_ERROR
;
2964 DPRINT("EHCI_GetErrorFromTD: TD - %p, STALL_PID\n", TD
);
2965 return USBD_STATUS_STALL_PID
;
2970 EHCI_ProcessDoneAsyncTd(IN PEHCI_EXTENSION EhciExtension
,
2973 PEHCI_TRANSFER EhciTransfer
;
2974 PUSBPORT_TRANSFER_PARAMETERS TransferParameters
;
2976 PEHCI_ENDPOINT EhciEndpoint
;
2977 ULONG LengthTransfered
;
2978 USBD_STATUS USBDStatus
;
2979 PEHCI_HW_REGISTERS OperationalRegs
;
2980 EHCI_USB_COMMAND Command
;
2982 DPRINT_EHCI("EHCI_ProcessDoneAsyncTd: TD - %p\n", TD
);
2984 EhciTransfer
= TD
->EhciTransfer
;
2986 TransferParameters
= EhciTransfer
->TransferParameters
;
2987 EhciTransfer
->PendingTDs
--;
2989 EhciEndpoint
= EhciTransfer
->EhciEndpoint
;
2991 if (!(TD
->TdFlags
& EHCI_HCD_TD_FLAG_ACTIVE
))
2994 if (TD
->HwTD
.Token
.Status
& EHCI_TOKEN_STATUS_HALTED
)
2995 USBDStatus
= EHCI_GetErrorFromTD(TD
);
2997 USBDStatus
= USBD_STATUS_SUCCESS
;
2999 LengthTransfered
= TD
->LengthThisTD
- TD
->HwTD
.Token
.TransferBytes
;
3001 if (TD
->HwTD
.Token
.PIDCode
!= EHCI_TD_TOKEN_PID_SETUP
)
3002 EhciTransfer
->TransferLen
+= LengthTransfered
;
3004 if (USBDStatus
!= USBD_STATUS_SUCCESS
)
3005 EhciTransfer
->USBDStatus
= USBDStatus
;
3008 TD
->HwTD
.NextTD
= 0;
3009 TD
->HwTD
.AlternateNextTD
= 0;
3012 TD
->EhciTransfer
= NULL
;
3014 EhciEndpoint
->RemainTDs
++;
3016 if (EhciTransfer
->PendingTDs
== 0)
3018 EhciEndpoint
->PendingTDs
--;
3020 TransferType
= EhciEndpoint
->EndpointProperties
.TransferType
;
3022 if (TransferType
== USBPORT_TRANSFER_TYPE_CONTROL
||
3023 TransferType
== USBPORT_TRANSFER_TYPE_BULK
)
3025 EhciExtension
->PendingTransfers
--;
3027 if (EhciExtension
->PendingTransfers
== 0)
3029 OperationalRegs
= EhciExtension
->OperationalRegs
;
3030 Command
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcCommand
.AsULONG
);
3032 if (!Command
.InterruptAdvanceDoorbell
&&
3033 (EhciExtension
->Flags
& EHCI_FLAGS_IDLE_SUPPORT
))
3035 EHCI_DisableAsyncList(EhciExtension
);
3040 RegPacket
.UsbPortCompleteTransfer(EhciExtension
,
3043 EhciTransfer
->USBDStatus
,
3044 EhciTransfer
->TransferLen
);
3050 EHCI_PollActiveAsyncEndpoint(IN PEHCI_EXTENSION EhciExtension
,
3051 IN PEHCI_ENDPOINT EhciEndpoint
)
3055 PEHCI_HCD_TD CurrentTD
;
3056 ULONG CurrentTDPhys
;
3057 BOOLEAN IsScheduled
;
3059 DPRINT_EHCI("EHCI_PollActiveAsyncEndpoint: ... \n");
3061 QH
= EhciEndpoint
->QH
;
3063 CurrentTDPhys
= QH
->sqh
.HwQH
.CurrentTD
& LINK_POINTER_MASK
;
3064 ASSERT(CurrentTDPhys
);
3066 CurrentTD
= RegPacket
.UsbPortGetMappedVirtualAddress(CurrentTDPhys
,
3070 if (CurrentTD
== EhciEndpoint
->DmaBufferVA
)
3073 IsScheduled
= QH
->sqh
.QhFlags
& EHCI_QH_FLAG_IN_SCHEDULE
;
3075 if (!EHCI_HardwarePresent(EhciExtension
, 0))
3078 TD
= EhciEndpoint
->HcdHeadP
;
3080 if (TD
== CurrentTD
)
3082 if (TD
!= EhciEndpoint
->HcdTailP
&&
3083 !(TD
->HwTD
.Token
.Status
& EHCI_TOKEN_STATUS_ACTIVE
))
3085 if (TD
->NextHcdTD
&& TD
->HwTD
.NextTD
!= TD
->NextHcdTD
->PhysicalAddress
)
3086 TD
->HwTD
.NextTD
= TD
->NextHcdTD
->PhysicalAddress
;
3088 if (TD
->AltNextHcdTD
&&
3089 TD
->HwTD
.AlternateNextTD
!= TD
->AltNextHcdTD
->PhysicalAddress
)
3091 TD
->HwTD
.AlternateNextTD
= TD
->AltNextHcdTD
->PhysicalAddress
;
3094 if (QH
->sqh
.HwQH
.CurrentTD
== TD
->PhysicalAddress
&&
3095 !(TD
->HwTD
.Token
.Status
& EHCI_TOKEN_STATUS_ACTIVE
) &&
3096 (QH
->sqh
.HwQH
.NextTD
!= TD
->HwTD
.NextTD
||
3097 QH
->sqh
.HwQH
.AlternateNextTD
!= TD
->HwTD
.AlternateNextTD
))
3099 QH
->sqh
.HwQH
.NextTD
= TD
->HwTD
.NextTD
;
3100 QH
->sqh
.HwQH
.AlternateNextTD
= TD
->HwTD
.AlternateNextTD
;
3103 EHCI_InterruptNextSOF(EhciExtension
);
3108 while (TD
!= CurrentTD
)
3110 ASSERT((TD
->TdFlags
& EHCI_HCD_TD_FLAG_DUMMY
) == 0);
3112 TD
->TdFlags
|= EHCI_HCD_TD_FLAG_DONE
;
3114 if (TD
->HwTD
.Token
.Status
& EHCI_TOKEN_STATUS_ACTIVE
)
3115 TD
->TdFlags
|= EHCI_HCD_TD_FLAG_ACTIVE
;
3117 InsertTailList(&EhciEndpoint
->ListTDs
, &TD
->DoneLink
);
3122 if (CurrentTD
->HwTD
.Token
.Status
& EHCI_TOKEN_STATUS_ACTIVE
)
3125 EhciEndpoint
->HcdHeadP
= TD
;
3129 if ((CurrentTD
->NextHcdTD
!= EhciEndpoint
->HcdTailP
) &&
3130 (CurrentTD
->AltNextHcdTD
!= EhciEndpoint
->HcdTailP
||
3131 CurrentTD
->HwTD
.Token
.TransferBytes
== 0))
3134 EhciEndpoint
->HcdHeadP
= TD
;
3140 EHCI_LockQH(EhciExtension
,
3142 EhciEndpoint
->EndpointProperties
.TransferType
);
3145 QH
->sqh
.HwQH
.CurrentTD
= EhciEndpoint
->DmaBufferPA
;
3147 CurrentTD
->TdFlags
|= EHCI_HCD_TD_FLAG_DONE
;
3148 InsertTailList(&EhciEndpoint
->ListTDs
, &CurrentTD
->DoneLink
);
3150 if (CurrentTD
->HwTD
.Token
.TransferBytes
&&
3151 CurrentTD
->AltNextHcdTD
== EhciEndpoint
->HcdTailP
)
3153 TD
= CurrentTD
->NextHcdTD
;
3155 while (TD
!= EhciEndpoint
->HcdTailP
)
3157 TD
->TdFlags
|= EHCI_HCD_TD_FLAG_ACTIVE
;
3158 InsertTailList(&EhciEndpoint
->ListTDs
, &TD
->DoneLink
);
3163 QH
->sqh
.HwQH
.CurrentTD
= EhciEndpoint
->HcdTailP
->PhysicalAddress
;
3164 QH
->sqh
.HwQH
.NextTD
= TERMINATE_POINTER
;
3165 QH
->sqh
.HwQH
.AlternateNextTD
= TERMINATE_POINTER
;
3166 QH
->sqh
.HwQH
.Token
.TransferBytes
= 0;
3168 EhciEndpoint
->HcdHeadP
= EhciEndpoint
->HcdTailP
;
3171 EHCI_UnlockQH(EhciExtension
, QH
);
3176 EHCI_PollHaltedAsyncEndpoint(IN PEHCI_EXTENSION EhciExtension
,
3177 IN PEHCI_ENDPOINT EhciEndpoint
)
3180 PEHCI_HCD_TD CurrentTD
;
3183 PEHCI_TRANSFER Transfer
;
3184 BOOLEAN IsScheduled
;
3186 DPRINT("EHCI_PollHaltedAsyncEndpoint: EhciEndpoint - %p\n", EhciEndpoint
);
3188 QH
= EhciEndpoint
->QH
;
3191 CurrentTdPA
= QH
->sqh
.HwQH
.CurrentTD
& LINK_POINTER_MASK
;
3192 ASSERT(CurrentTdPA
);
3194 IsScheduled
= QH
->sqh
.QhFlags
& EHCI_QH_FLAG_IN_SCHEDULE
;
3196 if (!EHCI_HardwarePresent(EhciExtension
, 0))
3199 CurrentTD
= RegPacket
.UsbPortGetMappedVirtualAddress(CurrentTdPA
,
3203 DPRINT("EHCI_PollHaltedAsyncEndpoint: CurrentTD - %p\n", CurrentTD
);
3205 if (CurrentTD
== EhciEndpoint
->DmaBufferVA
)
3208 ASSERT(EhciEndpoint
->HcdTailP
!= CurrentTD
);
3212 EHCI_LockQH(EhciExtension
,
3214 EhciEndpoint
->EndpointProperties
.TransferType
);
3217 TD
= EhciEndpoint
->HcdHeadP
;
3219 while (TD
!= CurrentTD
)
3221 DPRINT("EHCI_PollHaltedAsyncEndpoint: TD - %p\n", TD
);
3223 ASSERT((TD
->TdFlags
& EHCI_HCD_TD_FLAG_DUMMY
) == 0);
3225 if (TD
->HwTD
.Token
.Status
& EHCI_TOKEN_STATUS_ACTIVE
)
3226 TD
->TdFlags
|= EHCI_HCD_TD_FLAG_ACTIVE
;
3228 TD
->TdFlags
|= EHCI_HCD_TD_FLAG_DONE
;
3230 InsertTailList(&EhciEndpoint
->ListTDs
, &TD
->DoneLink
);
3237 Transfer
= CurrentTD
->EhciTransfer
;
3241 DPRINT("EHCI_PollHaltedAsyncEndpoint: TD - %p\n", TD
);
3243 if (TD
->HwTD
.Token
.Status
& EHCI_TOKEN_STATUS_ACTIVE
)
3244 TD
->TdFlags
|= EHCI_HCD_TD_FLAG_ACTIVE
;
3246 TD
->TdFlags
|= EHCI_HCD_TD_FLAG_DONE
;
3248 InsertTailList(&EhciEndpoint
->ListTDs
, &TD
->DoneLink
);
3252 while (TD
->EhciTransfer
== Transfer
);
3254 EhciEndpoint
->HcdHeadP
= TD
;
3256 QH
->sqh
.HwQH
.CurrentTD
= EhciEndpoint
->DmaBufferPA
;
3257 QH
->sqh
.HwQH
.NextTD
= TD
->PhysicalAddress
;
3258 QH
->sqh
.HwQH
.AlternateNextTD
= TERMINATE_POINTER
;
3259 QH
->sqh
.HwQH
.Token
.TransferBytes
= 0;
3262 EHCI_UnlockQH(EhciExtension
, QH
);
3264 if (EhciEndpoint
->EndpointStatus
& USBPORT_ENDPOINT_CONTROL
)
3266 EhciEndpoint
->EndpointStatus
&= ~USBPORT_ENDPOINT_HALT
;
3267 QH
->sqh
.HwQH
.Token
.ErrorCounter
= 0;
3268 QH
->sqh
.HwQH
.Token
.Status
&= (UCHAR
)~(EHCI_TOKEN_STATUS_ACTIVE
|
3269 EHCI_TOKEN_STATUS_HALTED
);
3276 EHCI_PollAsyncEndpoint(IN PEHCI_EXTENSION EhciExtension
,
3277 IN PEHCI_ENDPOINT EhciEndpoint
)
3280 PLIST_ENTRY DoneList
;
3283 //DPRINT_EHCI("EHCI_PollAsyncEndpoint: EhciEndpoint - %p\n", EhciEndpoint);
3285 if (!EhciEndpoint
->PendingTDs
)
3288 QH
= EhciEndpoint
->QH
;
3290 if (QH
->sqh
.QhFlags
& EHCI_QH_FLAG_CLOSED
)
3293 if (QH
->sqh
.HwQH
.Token
.Status
& EHCI_TOKEN_STATUS_ACTIVE
||
3294 !(QH
->sqh
.HwQH
.Token
.Status
& EHCI_TOKEN_STATUS_HALTED
))
3296 EHCI_PollActiveAsyncEndpoint(EhciExtension
, EhciEndpoint
);
3300 EhciEndpoint
->EndpointStatus
|= USBPORT_ENDPOINT_HALT
;
3301 EHCI_PollHaltedAsyncEndpoint(EhciExtension
, EhciEndpoint
);
3304 DoneList
= &EhciEndpoint
->ListTDs
;
3306 while (!IsListEmpty(DoneList
))
3308 TD
= CONTAINING_RECORD(DoneList
->Flink
,
3312 RemoveHeadList(DoneList
);
3314 ASSERT((TD
->TdFlags
& (EHCI_HCD_TD_FLAG_PROCESSED
|
3315 EHCI_HCD_TD_FLAG_DONE
)));
3317 EHCI_ProcessDoneAsyncTd(EhciExtension
, TD
);
3323 EHCI_PollIsoEndpoint(IN PEHCI_EXTENSION EhciExtension
,
3324 IN PEHCI_ENDPOINT EhciEndpoint
)
3326 DPRINT1("EHCI_PollIsoEndpoint: UNIMPLEMENTED. FIXME\n");
3331 EHCI_PollEndpoint(IN PVOID ehciExtension
,
3332 IN PVOID ehciEndpoint
)
3334 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
3335 PEHCI_ENDPOINT EhciEndpoint
= ehciEndpoint
;
3338 //DPRINT_EHCI("EHCI_PollEndpoint: EhciEndpoint - %p\n", EhciEndpoint);
3340 TransferType
= EhciEndpoint
->EndpointProperties
.TransferType
;
3342 if (TransferType
== USBPORT_TRANSFER_TYPE_ISOCHRONOUS
)
3343 EHCI_PollIsoEndpoint(EhciExtension
, EhciEndpoint
);
3345 EHCI_PollAsyncEndpoint(EhciExtension
, EhciEndpoint
);
3350 EHCI_CheckController(IN PVOID ehciExtension
)
3352 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
3354 //DPRINT_EHCI("EHCI_CheckController: ... \n");
3356 if (EhciExtension
->IsStarted
)
3357 EHCI_HardwarePresent(EhciExtension
, TRUE
);
3362 EHCI_Get32BitFrameNumber(IN PVOID ehciExtension
)
3364 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
3369 //DPRINT_EHCI("EHCI_Get32BitFrameNumber: EhciExtension - %p\n", EhciExtension);
3371 FrameIdx
= EhciExtension
->FrameIndex
;
3372 FrameIndex
= READ_REGISTER_ULONG(&EhciExtension
->OperationalRegs
->FrameIndex
);
3374 FrameNumber
= (USHORT
)FrameIdx
^ ((FrameIndex
/ EHCI_MICROFRAMES
) & EHCI_FRINDEX_FRAME_MASK
);
3375 FrameNumber
&= EHCI_FRAME_LIST_MAX_ENTRIES
;
3376 FrameNumber
+= FrameIndex
| ((FrameIndex
/ EHCI_MICROFRAMES
) & EHCI_FRINDEX_INDEX_MASK
);
3383 EHCI_EnableInterrupts(IN PVOID ehciExtension
)
3385 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
3387 DPRINT("EHCI_EnableInterrupts: EhciExtension->InterruptMask - %x\n",
3388 EhciExtension
->InterruptMask
.AsULONG
);
3390 WRITE_REGISTER_ULONG(&EhciExtension
->OperationalRegs
->HcInterruptEnable
.AsULONG
,
3391 EhciExtension
->InterruptMask
.AsULONG
);
3396 EHCI_DisableInterrupts(IN PVOID ehciExtension
)
3398 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
3400 DPRINT("EHCI_DisableInterrupts: ... \n");
3402 WRITE_REGISTER_ULONG(&EhciExtension
->OperationalRegs
->HcInterruptEnable
.AsULONG
,
3408 EHCI_PollController(IN PVOID ehciExtension
)
3410 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
3411 PEHCI_HW_REGISTERS OperationalRegs
;
3413 EHCI_PORT_STATUS_CONTROL PortSC
;
3415 DPRINT_EHCI("EHCI_PollController: ... \n");
3417 OperationalRegs
= EhciExtension
->OperationalRegs
;
3419 if (!(EhciExtension
->Flags
& EHCI_FLAGS_CONTROLLER_SUSPEND
))
3421 RegPacket
.UsbPortInvalidateRootHub(EhciExtension
);
3425 if (EhciExtension
->NumberOfPorts
)
3427 for (Port
= 0; Port
< EhciExtension
->NumberOfPorts
; Port
++)
3429 PortSC
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->PortControl
[Port
].AsULONG
);
3431 if (PortSC
.ConnectStatusChange
)
3432 RegPacket
.UsbPortInvalidateRootHub(EhciExtension
);
3439 EHCI_SetEndpointDataToggle(IN PVOID ehciExtension
,
3440 IN PVOID ehciEndpoint
,
3441 IN ULONG DataToggle
)
3443 PEHCI_ENDPOINT EhciEndpoint
;
3446 EhciEndpoint
= ehciEndpoint
;
3448 DPRINT("EHCI_SetEndpointDataToggle: EhciEndpoint - %p, DataToggle - %x\n",
3452 TransferType
= EhciEndpoint
->EndpointProperties
.TransferType
;
3454 if (TransferType
== USBPORT_TRANSFER_TYPE_BULK
||
3455 TransferType
== USBPORT_TRANSFER_TYPE_INTERRUPT
)
3457 EhciEndpoint
->QH
->sqh
.HwQH
.Token
.DataToggle
= DataToggle
;
3463 EHCI_GetEndpointStatus(IN PVOID ehciExtension
,
3464 IN PVOID ehciEndpoint
)
3466 PEHCI_ENDPOINT EhciEndpoint
;
3468 ULONG EndpointStatus
= USBPORT_ENDPOINT_RUN
;
3470 EhciEndpoint
= ehciEndpoint
;
3472 DPRINT("EHCI_GetEndpointStatus: EhciEndpoint - %p\n", EhciEndpoint
);
3474 TransferType
= EhciEndpoint
->EndpointProperties
.TransferType
;
3476 if (TransferType
== USBPORT_TRANSFER_TYPE_ISOCHRONOUS
)
3477 return EndpointStatus
;
3479 if (EhciEndpoint
->EndpointStatus
& USBPORT_ENDPOINT_HALT
)
3480 EndpointStatus
= USBPORT_ENDPOINT_HALT
;
3482 return EndpointStatus
;
3487 EHCI_SetEndpointStatus(IN PVOID ehciExtension
,
3488 IN PVOID ehciEndpoint
,
3489 IN ULONG EndpointStatus
)
3491 PEHCI_ENDPOINT EhciEndpoint
;
3495 EhciEndpoint
= ehciEndpoint
;
3497 DPRINT("EHCI_SetEndpointStatus: EhciEndpoint - %p, EndpointStatus - %x\n",
3501 TransferType
= EhciEndpoint
->EndpointProperties
.TransferType
;
3503 if (TransferType
!= USBPORT_TRANSFER_TYPE_ISOCHRONOUS
)
3506 if (EndpointStatus
== USBPORT_ENDPOINT_RUN
)
3508 EhciEndpoint
->EndpointStatus
&= ~USBPORT_ENDPOINT_HALT
;
3510 QH
= EhciEndpoint
->QH
;
3511 QH
->sqh
.HwQH
.Token
.Status
&= (UCHAR
)~EHCI_TOKEN_STATUS_HALTED
;
3516 if (EndpointStatus
== USBPORT_ENDPOINT_HALT
)
3523 EHCI_ResetController(IN PVOID ehciExtension
)
3525 DPRINT1("EHCI_ResetController: UNIMPLEMENTED. FIXME\n");
3530 EHCI_StartSendOnePacket(IN PVOID ehciExtension
,
3531 IN PVOID PacketParameters
,
3533 IN PULONG pDataLength
,
3536 IN ULONG BufferLength
,
3537 IN USBD_STATUS
* pUSBDStatus
)
3539 DPRINT1("EHCI_StartSendOnePacket: UNIMPLEMENTED. FIXME\n");
3540 return MP_STATUS_SUCCESS
;
3545 EHCI_EndSendOnePacket(IN PVOID ehciExtension
,
3546 IN PVOID PacketParameters
,
3548 IN PULONG pDataLength
,
3551 IN ULONG BufferLength
,
3552 IN USBD_STATUS
* pUSBDStatus
)
3554 DPRINT1("EHCI_EndSendOnePacket: UNIMPLEMENTED. FIXME\n");
3555 return MP_STATUS_SUCCESS
;
3560 EHCI_PassThru(IN PVOID ehciExtension
,
3561 IN PVOID passThruParameters
,
3562 IN ULONG ParameterLength
,
3563 IN PVOID pParameters
)
3565 DPRINT1("EHCI_PassThru: UNIMPLEMENTED. FIXME\n");
3566 return MP_STATUS_SUCCESS
;
3571 EHCI_RebalanceEndpoint(IN PVOID ohciExtension
,
3572 IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties
,
3573 IN PVOID ohciEndpoint
)
3575 DPRINT1("EHCI_RebalanceEndpoint: UNIMPLEMENTED. FIXME\n");
3580 EHCI_FlushInterrupts(IN PVOID ehciExtension
)
3582 PEHCI_EXTENSION EhciExtension
= ehciExtension
;
3583 PEHCI_HW_REGISTERS OperationalRegs
;
3584 EHCI_USB_STATUS Status
;
3586 DPRINT("EHCI_FlushInterrupts: ... \n");
3588 OperationalRegs
= EhciExtension
->OperationalRegs
;
3590 Status
.AsULONG
= READ_REGISTER_ULONG(&OperationalRegs
->HcStatus
.AsULONG
);
3591 WRITE_REGISTER_ULONG(&OperationalRegs
->HcStatus
.AsULONG
, Status
.AsULONG
);
3596 EHCI_TakePortControl(IN PVOID ohciExtension
)
3598 DPRINT1("EHCI_TakePortControl: UNIMPLEMENTED. FIXME\n");
3603 EHCI_Unload(IN PDRIVER_OBJECT DriverObject
)
3606 DPRINT1("EHCI_Unload: Not supported\n");
3613 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
3614 IN PUNICODE_STRING RegistryPath
)
3616 DPRINT("DriverEntry: DriverObject - %p, RegistryPath - %wZ\n",
3620 if (USBPORT_GetHciMn() != USBPORT_HCI_MN
)
3621 return STATUS_INSUFFICIENT_RESOURCES
;
3623 RtlZeroMemory(&RegPacket
, sizeof(USBPORT_REGISTRATION_PACKET
));
3625 RegPacket
.MiniPortVersion
= USB_MINIPORT_VERSION_EHCI
;
3627 RegPacket
.MiniPortFlags
= USB_MINIPORT_FLAGS_INTERRUPT
|
3628 USB_MINIPORT_FLAGS_MEMORY_IO
|
3629 USB_MINIPORT_FLAGS_USB2
|
3630 USB_MINIPORT_FLAGS_POLLING
|
3631 USB_MINIPORT_FLAGS_WAKE_SUPPORT
;
3633 RegPacket
.MiniPortBusBandwidth
= TOTAL_USB20_BUS_BANDWIDTH
;
3635 RegPacket
.MiniPortExtensionSize
= sizeof(EHCI_EXTENSION
);
3636 RegPacket
.MiniPortEndpointSize
= sizeof(EHCI_ENDPOINT
);
3637 RegPacket
.MiniPortTransferSize
= sizeof(EHCI_TRANSFER
);
3638 RegPacket
.MiniPortResourcesSize
= sizeof(EHCI_HC_RESOURCES
);
3640 RegPacket
.OpenEndpoint
= EHCI_OpenEndpoint
;
3641 RegPacket
.ReopenEndpoint
= EHCI_ReopenEndpoint
;
3642 RegPacket
.QueryEndpointRequirements
= EHCI_QueryEndpointRequirements
;
3643 RegPacket
.CloseEndpoint
= EHCI_CloseEndpoint
;
3644 RegPacket
.StartController
= EHCI_StartController
;
3645 RegPacket
.StopController
= EHCI_StopController
;
3646 RegPacket
.SuspendController
= EHCI_SuspendController
;
3647 RegPacket
.ResumeController
= EHCI_ResumeController
;
3648 RegPacket
.InterruptService
= EHCI_InterruptService
;
3649 RegPacket
.InterruptDpc
= EHCI_InterruptDpc
;
3650 RegPacket
.SubmitTransfer
= EHCI_SubmitTransfer
;
3651 RegPacket
.SubmitIsoTransfer
= EHCI_SubmitIsoTransfer
;
3652 RegPacket
.AbortTransfer
= EHCI_AbortTransfer
;
3653 RegPacket
.GetEndpointState
= EHCI_GetEndpointState
;
3654 RegPacket
.SetEndpointState
= EHCI_SetEndpointState
;
3655 RegPacket
.PollEndpoint
= EHCI_PollEndpoint
;
3656 RegPacket
.CheckController
= EHCI_CheckController
;
3657 RegPacket
.Get32BitFrameNumber
= EHCI_Get32BitFrameNumber
;
3658 RegPacket
.InterruptNextSOF
= EHCI_InterruptNextSOF
;
3659 RegPacket
.EnableInterrupts
= EHCI_EnableInterrupts
;
3660 RegPacket
.DisableInterrupts
= EHCI_DisableInterrupts
;
3661 RegPacket
.PollController
= EHCI_PollController
;
3662 RegPacket
.SetEndpointDataToggle
= EHCI_SetEndpointDataToggle
;
3663 RegPacket
.GetEndpointStatus
= EHCI_GetEndpointStatus
;
3664 RegPacket
.SetEndpointStatus
= EHCI_SetEndpointStatus
;
3665 RegPacket
.RH_GetRootHubData
= EHCI_RH_GetRootHubData
;
3666 RegPacket
.RH_GetStatus
= EHCI_RH_GetStatus
;
3667 RegPacket
.RH_GetPortStatus
= EHCI_RH_GetPortStatus
;
3668 RegPacket
.RH_GetHubStatus
= EHCI_RH_GetHubStatus
;
3669 RegPacket
.RH_SetFeaturePortReset
= EHCI_RH_SetFeaturePortReset
;
3670 RegPacket
.RH_SetFeaturePortPower
= EHCI_RH_SetFeaturePortPower
;
3671 RegPacket
.RH_SetFeaturePortEnable
= EHCI_RH_SetFeaturePortEnable
;
3672 RegPacket
.RH_SetFeaturePortSuspend
= EHCI_RH_SetFeaturePortSuspend
;
3673 RegPacket
.RH_ClearFeaturePortEnable
= EHCI_RH_ClearFeaturePortEnable
;
3674 RegPacket
.RH_ClearFeaturePortPower
= EHCI_RH_ClearFeaturePortPower
;
3675 RegPacket
.RH_ClearFeaturePortSuspend
= EHCI_RH_ClearFeaturePortSuspend
;
3676 RegPacket
.RH_ClearFeaturePortEnableChange
= EHCI_RH_ClearFeaturePortEnableChange
;
3677 RegPacket
.RH_ClearFeaturePortConnectChange
= EHCI_RH_ClearFeaturePortConnectChange
;
3678 RegPacket
.RH_ClearFeaturePortResetChange
= EHCI_RH_ClearFeaturePortResetChange
;
3679 RegPacket
.RH_ClearFeaturePortSuspendChange
= EHCI_RH_ClearFeaturePortSuspendChange
;
3680 RegPacket
.RH_ClearFeaturePortOvercurrentChange
= EHCI_RH_ClearFeaturePortOvercurrentChange
;
3681 RegPacket
.RH_DisableIrq
= EHCI_RH_DisableIrq
;
3682 RegPacket
.RH_EnableIrq
= EHCI_RH_EnableIrq
;
3683 RegPacket
.StartSendOnePacket
= EHCI_StartSendOnePacket
;
3684 RegPacket
.EndSendOnePacket
= EHCI_EndSendOnePacket
;
3685 RegPacket
.PassThru
= EHCI_PassThru
;
3686 RegPacket
.RebalanceEndpoint
= EHCI_RebalanceEndpoint
;
3687 RegPacket
.FlushInterrupts
= EHCI_FlushInterrupts
;
3688 RegPacket
.RH_ChirpRootPort
= EHCI_RH_ChirpRootPort
;
3689 RegPacket
.TakePortControl
= EHCI_TakePortControl
;
3691 DriverObject
->DriverUnload
= EHCI_Unload
;
3693 return USBPORT_RegisterUSBPortDriver(DriverObject
,
3694 USB20_MINIPORT_INTERFACE_VERSION
,