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
EHCI_AllocTd(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint)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
EHCI_InitializeQH(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint,IN PEHCI_HCD_QH QH,IN ULONG QhPA)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
EHCI_OpenBulkOrControlEndpoint(IN PEHCI_EXTENSION EhciExtension,IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,IN PEHCI_ENDPOINT EhciEndpoint,IN BOOLEAN IsControl)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
EHCI_OpenInterruptEndpoint(IN PEHCI_EXTENSION EhciExtension,IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,IN PEHCI_ENDPOINT EhciEndpoint)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
EHCI_OpenHsIsoEndpoint(IN PEHCI_EXTENSION EhciExtension,IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,IN PEHCI_ENDPOINT EhciEndpoint)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
EHCI_OpenIsoEndpoint(IN PEHCI_EXTENSION EhciExtension,IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,IN PEHCI_ENDPOINT EhciEndpoint)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
EHCI_OpenEndpoint(IN PVOID ehciExtension,IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,IN PVOID ehciEndpoint)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
EHCI_ReopenEndpoint(IN PVOID ehciExtension,IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,IN PVOID ehciEndpoint)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
EHCI_QueryEndpointRequirements(IN PVOID ehciExtension,IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,IN PUSBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements)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
EHCI_DisablePeriodicList(IN PEHCI_EXTENSION EhciExtension)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
EHCI_CloseEndpoint(IN PVOID ehciExtension,IN PVOID ehciEndpoint,IN BOOLEAN DisablePeriodic)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
EHCI_GetQhForFrame(IN PEHCI_EXTENSION EhciExtension,IN ULONG FrameIdx)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
EHCI_GetDummyQhForFrame(IN PEHCI_EXTENSION EhciExtension,IN ULONG Idx)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
EHCI_AlignHwStructure(IN PEHCI_EXTENSION EhciExtension,IN PULONG PhysicalAddress,IN PULONG_PTR VirtualAddress,IN ULONG Alignment)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
EHCI_AddDummyQHs(IN PEHCI_EXTENSION EhciExtension)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
EHCI_InitializeInterruptSchedule(IN PEHCI_EXTENSION EhciExtension)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
EHCI_InitializeSchedule(IN PEHCI_EXTENSION EhciExtension,IN ULONG_PTR BaseVA,IN ULONG BasePA)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
EHCI_InitializeHardware(IN PEHCI_EXTENSION EhciExtension)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
EHCI_GetOffsetEECP(IN PEHCI_EXTENSION EhciExtension,IN UCHAR CapabilityID)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
EHCI_TakeControlHC(IN PEHCI_EXTENSION EhciExtension)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
EHCI_GetRegistryParameters(IN PEHCI_EXTENSION EhciExtension)1153 EHCI_GetRegistryParameters(IN PEHCI_EXTENSION EhciExtension)
1154 {
1155 DPRINT1("EHCI_GetRegistryParameters: UNIMPLEMENTED. FIXME\n");
1156 }
1157
1158 MPSTATUS
1159 NTAPI
EHCI_StartController(IN PVOID ehciExtension,IN PUSBPORT_RESOURCES Resources)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
EHCI_StopController(IN PVOID ehciExtension,IN BOOLEAN DisableInterrupts)1285 EHCI_StopController(IN PVOID ehciExtension,
1286 IN BOOLEAN DisableInterrupts)
1287 {
1288 DPRINT1("EHCI_StopController: UNIMPLEMENTED. FIXME\n");
1289 }
1290
1291 VOID
1292 NTAPI
EHCI_SuspendController(IN PVOID ehciExtension)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
EHCI_ResumeController(IN PVOID ehciExtension)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
EHCI_HardwarePresent(IN PEHCI_EXTENSION EhciExtension,IN BOOLEAN IsInvalidateController)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
EHCI_InterruptService(IN PVOID ehciExtension)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
EHCI_InterruptDpc(IN PVOID ehciExtension,IN BOOLEAN EnableInterrupts)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
EHCI_MapAsyncTransferToTd(IN PEHCI_EXTENSION EhciExtension,IN ULONG MaxPacketSize,IN ULONG TransferedLen,IN PULONG DataToggle,IN PEHCI_TRANSFER EhciTransfer,IN PEHCI_HCD_TD TD,IN PUSBPORT_SCATTER_GATHER_LIST SgList)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
EHCI_EnableAsyncList(IN PEHCI_EXTENSION EhciExtension)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
EHCI_DisableAsyncList(IN PEHCI_EXTENSION EhciExtension)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
EHCI_EnablePeriodicList(IN PEHCI_EXTENSION EhciExtension)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
EHCI_FlushAsyncCache(IN PEHCI_EXTENSION EhciExtension)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
EHCI_LockQH(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_HCD_QH QH,IN ULONG TransferType)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
EHCI_UnlockQH(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_HCD_QH QH)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
EHCI_LinkTransferToQueue(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint,IN PEHCI_HCD_TD NextTD)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
EHCI_ControlTransfer(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint,IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,IN PEHCI_TRANSFER EhciTransfer,IN PUSBPORT_SCATTER_GATHER_LIST SgList)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
EHCI_BulkTransfer(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint,IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,IN PEHCI_TRANSFER EhciTransfer,IN PUSBPORT_SCATTER_GATHER_LIST SgList)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
EHCI_InterruptTransfer(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint,IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,IN PEHCI_TRANSFER EhciTransfer,IN PUSBPORT_SCATTER_GATHER_LIST SgList)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
EHCI_SubmitTransfer(IN PVOID ehciExtension,IN PVOID ehciEndpoint,IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,IN PVOID ehciTransfer,IN PUSBPORT_SCATTER_GATHER_LIST SgList)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
EHCI_SubmitIsoTransfer(IN PVOID ehciExtension,IN PVOID ehciEndpoint,IN PUSBPORT_TRANSFER_PARAMETERS TransferParameters,IN PVOID ehciTransfer,IN PVOID isoParameters)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
EHCI_AbortIsoTransfer(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint,IN PEHCI_TRANSFER EhciTransfer)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
EHCI_AbortAsyncTransfer(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint,IN PEHCI_TRANSFER EhciTransfer)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
EHCI_AbortTransfer(IN PVOID ehciExtension,IN PVOID ehciEndpoint,IN PVOID ehciTransfer,IN PULONG CompletedLength)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
EHCI_GetEndpointState(IN PVOID ehciExtension,IN PVOID ehciEndpoint)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
EHCI_RemoveQhFromPeriodicList(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint)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
EHCI_RemoveQhFromAsyncList(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_HCD_QH QH)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
EHCI_InsertQhInPeriodicList(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint)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
EHCI_InsertQhInAsyncList(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_HCD_QH QH)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
EHCI_SetIsoEndpointState(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint,IN ULONG EndpointState)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
EHCI_SetAsyncEndpointState(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint,IN ULONG EndpointState)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
EHCI_SetEndpointState(IN PVOID ehciExtension,IN PVOID ehciEndpoint,IN ULONG EndpointState)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
EHCI_InterruptNextSOF(IN PVOID ehciExtension)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
EHCI_GetErrorFromTD(IN PEHCI_HCD_TD TD)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
EHCI_ProcessDoneAsyncTd(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_HCD_TD TD)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
EHCI_PollActiveAsyncEndpoint(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint)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
EHCI_PollHaltedAsyncEndpoint(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint)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
EHCI_PollAsyncEndpoint(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint)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
EHCI_PollIsoEndpoint(IN PEHCI_EXTENSION EhciExtension,IN PEHCI_ENDPOINT EhciEndpoint)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
EHCI_PollEndpoint(IN PVOID ehciExtension,IN PVOID ehciEndpoint)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
EHCI_CheckController(IN PVOID ehciExtension)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
EHCI_Get32BitFrameNumber(IN PVOID ehciExtension)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
EHCI_EnableInterrupts(IN PVOID ehciExtension)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
EHCI_DisableInterrupts(IN PVOID ehciExtension)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
EHCI_PollController(IN PVOID ehciExtension)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
EHCI_SetEndpointDataToggle(IN PVOID ehciExtension,IN PVOID ehciEndpoint,IN ULONG DataToggle)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
EHCI_GetEndpointStatus(IN PVOID ehciExtension,IN PVOID ehciEndpoint)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
EHCI_SetEndpointStatus(IN PVOID ehciExtension,IN PVOID ehciEndpoint,IN ULONG EndpointStatus)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
EHCI_ResetController(IN PVOID ehciExtension)3524 EHCI_ResetController(IN PVOID ehciExtension)
3525 {
3526 DPRINT1("EHCI_ResetController: UNIMPLEMENTED. FIXME\n");
3527 }
3528
3529 MPSTATUS
3530 NTAPI
EHCI_StartSendOnePacket(IN PVOID ehciExtension,IN PVOID PacketParameters,IN PVOID Data,IN PULONG pDataLength,IN PVOID BufferVA,IN PVOID BufferPA,IN ULONG BufferLength,IN USBD_STATUS * pUSBDStatus)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
EHCI_EndSendOnePacket(IN PVOID ehciExtension,IN PVOID PacketParameters,IN PVOID Data,IN PULONG pDataLength,IN PVOID BufferVA,IN PVOID BufferPA,IN ULONG BufferLength,IN USBD_STATUS * pUSBDStatus)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
EHCI_PassThru(IN PVOID ehciExtension,IN PVOID passThruParameters,IN ULONG ParameterLength,IN PVOID pParameters)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
EHCI_RebalanceEndpoint(IN PVOID ohciExtension,IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties,IN PVOID ohciEndpoint)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
EHCI_FlushInterrupts(IN PVOID ehciExtension)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
EHCI_TakePortControl(IN PVOID ohciExtension)3597 EHCI_TakePortControl(IN PVOID ohciExtension)
3598 {
3599 DPRINT1("EHCI_TakePortControl: UNIMPLEMENTED. FIXME\n");
3600 }
3601
3602 VOID
3603 NTAPI
EHCI_Unload(IN PDRIVER_OBJECT DriverObject)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
DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)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