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