xref: /reactos/drivers/usb/usbport/usbport.c (revision 0623a6f8)
1 /*
2  * PROJECT:     ReactOS USB Port Driver
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     USBPort main driver functions
5  * COPYRIGHT:   Copyright 2017 Vadim Galyant <vgal@rambler.ru>
6  */
7 
8 #include "usbport.h"
9 
10 #define NDEBUG
11 #include <debug.h>
12 
13 #define NDEBUG_USBPORT_CORE
14 #define NDEBUG_USBPORT_INTERRUPT
15 #define NDEBUG_USBPORT_TIMER
16 #include "usbdebug.h"
17 
18 LIST_ENTRY USBPORT_MiniPortDrivers = {NULL, NULL};
19 LIST_ENTRY USBPORT_USB1FdoList = {NULL, NULL};
20 LIST_ENTRY USBPORT_USB2FdoList = {NULL, NULL};
21 
22 KSPIN_LOCK USBPORT_SpinLock;
23 BOOLEAN USBPORT_Initialized = FALSE;
24 
25 PDEVICE_OBJECT
26 NTAPI
27 USBPORT_FindUSB2Controller(IN PDEVICE_OBJECT FdoDevice)
28 {
29     PUSBPORT_DEVICE_EXTENSION FdoExtension;
30     PUSBPORT_DEVICE_EXTENSION USB2FdoExtension;
31     KIRQL OldIrql;
32     PLIST_ENTRY USB2FdoEntry;
33     PDEVICE_OBJECT USB2FdoDevice = NULL;
34 
35     DPRINT("USBPORT_FindUSB2Controller: FdoDevice - %p\n", FdoDevice);
36 
37     FdoExtension = FdoDevice->DeviceExtension;
38 
39     KeAcquireSpinLock(&USBPORT_SpinLock, &OldIrql);
40 
41     USB2FdoEntry = USBPORT_USB2FdoList.Flink;
42 
43     while (USB2FdoEntry && USB2FdoEntry != &USBPORT_USB2FdoList)
44     {
45         USB2FdoExtension = CONTAINING_RECORD(USB2FdoEntry,
46                                              USBPORT_DEVICE_EXTENSION,
47                                              ControllerLink);
48 
49         if (USB2FdoExtension->BusNumber == FdoExtension->BusNumber &&
50             USB2FdoExtension->PciDeviceNumber == FdoExtension->PciDeviceNumber)
51         {
52             USB2FdoDevice = USB2FdoExtension->CommonExtension.SelfDevice;
53             break;
54         }
55 
56         USB2FdoEntry = USB2FdoEntry->Flink;
57     }
58 
59     KeReleaseSpinLock(&USBPORT_SpinLock, OldIrql);
60 
61     return USB2FdoDevice;
62 }
63 
64 VOID
65 NTAPI
66 USBPORT_AddUSB1Fdo(IN PDEVICE_OBJECT FdoDevice)
67 {
68     PUSBPORT_DEVICE_EXTENSION FdoExtension;
69 
70     DPRINT("USBPORT_AddUSB1Fdo: FdoDevice - %p\n", FdoDevice);
71 
72     FdoExtension = FdoDevice->DeviceExtension;
73     FdoExtension->Flags |= USBPORT_FLAG_REGISTERED_FDO;
74 
75     ExInterlockedInsertTailList(&USBPORT_USB1FdoList,
76                                 &FdoExtension->ControllerLink,
77                                 &USBPORT_SpinLock);
78 }
79 
80 VOID
81 NTAPI
82 USBPORT_AddUSB2Fdo(IN PDEVICE_OBJECT FdoDevice)
83 {
84     PUSBPORT_DEVICE_EXTENSION FdoExtension;
85 
86     DPRINT("USBPORT_AddUSB2Fdo: FdoDevice - %p\n", FdoDevice);
87 
88     FdoExtension = FdoDevice->DeviceExtension;
89     FdoExtension->Flags |= USBPORT_FLAG_REGISTERED_FDO;
90 
91     ExInterlockedInsertTailList(&USBPORT_USB2FdoList,
92                                 &FdoExtension->ControllerLink,
93                                 &USBPORT_SpinLock);
94 }
95 
96 VOID
97 NTAPI
98 USBPORT_RemoveUSBxFdo(IN PDEVICE_OBJECT FdoDevice)
99 {
100     PUSBPORT_DEVICE_EXTENSION FdoExtension;
101     KIRQL OldIrql;
102 
103     DPRINT("USBPORT_RemoveUSBxFdo: FdoDevice - %p\n", FdoDevice);
104 
105     FdoExtension = FdoDevice->DeviceExtension;
106 
107     KeAcquireSpinLock(&USBPORT_SpinLock, &OldIrql);
108     RemoveEntryList(&FdoExtension->ControllerLink);
109     KeReleaseSpinLock(&USBPORT_SpinLock, OldIrql);
110 
111     FdoExtension->Flags &= ~USBPORT_FLAG_REGISTERED_FDO;
112 
113     FdoExtension->ControllerLink.Flink = NULL;
114     FdoExtension->ControllerLink.Blink = NULL;
115 }
116 
117 BOOLEAN
118 NTAPI
119 USBPORT_IsCompanionFdoExtension(IN PDEVICE_OBJECT USB2FdoDevice,
120                                 IN PUSBPORT_DEVICE_EXTENSION USB1FdoExtension)
121 {
122     PUSBPORT_DEVICE_EXTENSION USB2FdoExtension;
123 
124     DPRINT("USBPORT_IsCompanionFdoExtension: USB2Fdo - %p, USB1FdoExtension - %p\n",
125            USB2FdoDevice,
126            USB1FdoExtension);
127 
128     USB2FdoExtension = USB2FdoDevice->DeviceExtension;
129 
130     return USB2FdoExtension->BusNumber == USB1FdoExtension->BusNumber &&
131            USB2FdoExtension->PciDeviceNumber == USB1FdoExtension->PciDeviceNumber;
132 }
133 
134 PDEVICE_RELATIONS
135 NTAPI
136 USBPORT_FindCompanionControllers(IN PDEVICE_OBJECT USB2FdoDevice,
137                                  IN BOOLEAN IsObRefer,
138                                  IN BOOLEAN IsFDOsReturned)
139 {
140     PLIST_ENTRY USB1FdoList;
141     PUSBPORT_DEVICE_EXTENSION USB1FdoExtension;
142     ULONG NumControllers = 0;
143     PDEVICE_OBJECT * Entry;
144     PDEVICE_RELATIONS ControllersList = NULL;
145     KIRQL OldIrql;
146 
147     DPRINT("USBPORT_FindCompanionControllers: USB2Fdo - %p, IsObRefer - %x, IsFDOs - %x\n",
148            USB2FdoDevice,
149            IsObRefer,
150            IsFDOsReturned);
151 
152     KeAcquireSpinLock(&USBPORT_SpinLock, &OldIrql);
153 
154     USB1FdoList = USBPORT_USB1FdoList.Flink;
155 
156     while (USB1FdoList && USB1FdoList != &USBPORT_USB1FdoList)
157     {
158         USB1FdoExtension = CONTAINING_RECORD(USB1FdoList,
159                                              USBPORT_DEVICE_EXTENSION,
160                                              ControllerLink);
161 
162         if (USB1FdoExtension->Flags & USBPORT_FLAG_COMPANION_HC &&
163             USBPORT_IsCompanionFdoExtension(USB2FdoDevice, USB1FdoExtension))
164         {
165             ++NumControllers;
166         }
167 
168         USB1FdoList = USB1FdoExtension->ControllerLink.Flink;
169     }
170 
171     DPRINT("USBPORT_FindCompanionControllers: NumControllers - %x\n",
172            NumControllers);
173 
174     if (!NumControllers)
175     {
176         goto Exit;
177     }
178 
179     ControllersList = ExAllocatePoolWithTag(NonPagedPool,
180                                             NumControllers * sizeof(DEVICE_RELATIONS),
181                                             USB_PORT_TAG);
182 
183     if (!ControllersList)
184     {
185         goto Exit;
186     }
187 
188     RtlZeroMemory(ControllersList, NumControllers * sizeof(DEVICE_RELATIONS));
189 
190     ControllersList->Count = NumControllers;
191 
192     USB1FdoList = USBPORT_USB1FdoList.Flink;
193 
194     Entry = &ControllersList->Objects[0];
195 
196     while (USB1FdoList && USB1FdoList != &USBPORT_USB1FdoList)
197     {
198         USB1FdoExtension = CONTAINING_RECORD(USB1FdoList,
199                                              USBPORT_DEVICE_EXTENSION,
200                                              ControllerLink);
201 
202         if (USB1FdoExtension->Flags & USBPORT_FLAG_COMPANION_HC &&
203             USBPORT_IsCompanionFdoExtension(USB2FdoDevice, USB1FdoExtension))
204         {
205             *Entry = USB1FdoExtension->CommonExtension.LowerPdoDevice;
206 
207             if (IsObRefer)
208             {
209                 ObReferenceObject(USB1FdoExtension->CommonExtension.LowerPdoDevice);
210             }
211 
212             if (IsFDOsReturned)
213             {
214                 *Entry = USB1FdoExtension->CommonExtension.SelfDevice;
215             }
216 
217             ++Entry;
218         }
219 
220         USB1FdoList = USB1FdoExtension->ControllerLink.Flink;
221     }
222 
223 Exit:
224 
225     KeReleaseSpinLock(&USBPORT_SpinLock, OldIrql);
226 
227     return ControllersList;
228 }
229 
230 MPSTATUS
231 NTAPI
232 USBPORT_NtStatusToMpStatus(NTSTATUS NtStatus)
233 {
234     DPRINT("USBPORT_NtStatusToMpStatus: NtStatus - %x\n", NtStatus);
235 
236     if (NtStatus == STATUS_SUCCESS)
237     {
238         return MP_STATUS_SUCCESS;
239     }
240     else
241     {
242         return MP_STATUS_UNSUCCESSFUL;
243     }
244 }
245 
246 NTSTATUS
247 NTAPI
248 USBPORT_SetRegistryKeyValue(IN PDEVICE_OBJECT DeviceObject,
249                             IN BOOL UseDriverKey,
250                             IN ULONG Type,
251                             IN PCWSTR ValueNameString,
252                             IN PVOID Data,
253                             IN ULONG DataSize)
254 {
255     UNICODE_STRING ValueName;
256     HANDLE KeyHandle;
257     NTSTATUS Status;
258 
259     DPRINT("USBPORT_SetRegistryKeyValue: ValueNameString - %S \n",
260            ValueNameString);
261 
262     if (UseDriverKey)
263     {
264         Status = IoOpenDeviceRegistryKey(DeviceObject,
265                                          PLUGPLAY_REGKEY_DRIVER,
266                                          STANDARD_RIGHTS_ALL,
267                                          &KeyHandle);
268     }
269     else
270     {
271         Status = IoOpenDeviceRegistryKey(DeviceObject,
272                                          PLUGPLAY_REGKEY_DEVICE,
273                                          STANDARD_RIGHTS_ALL,
274                                          &KeyHandle);
275     }
276 
277     if (NT_SUCCESS(Status))
278     {
279         RtlInitUnicodeString(&ValueName, ValueNameString);
280 
281         Status = ZwSetValueKey(KeyHandle,
282                                &ValueName,
283                                0,
284                                Type,
285                                Data,
286                                DataSize);
287 
288         ZwClose(KeyHandle);
289     }
290 
291     return Status;
292 }
293 
294 NTSTATUS
295 NTAPI
296 USBPORT_GetRegistryKeyValueFullInfo(IN PDEVICE_OBJECT FdoDevice,
297                                     IN PDEVICE_OBJECT PdoDevice,
298                                     IN BOOL UseDriverKey,
299                                     IN PCWSTR SourceString,
300                                     IN ULONG LengthStr,
301                                     IN PVOID Buffer,
302                                     IN ULONG BufferLength)
303 {
304     NTSTATUS Status;
305     PKEY_VALUE_FULL_INFORMATION KeyValue;
306     UNICODE_STRING ValueName;
307     HANDLE KeyHandle;
308     ULONG LengthKey;
309 
310     DPRINT("USBPORT_GetRegistryKeyValue: UseDriverKey - %x, SourceString - %S, LengthStr - %x, Buffer - %p, BufferLength - %x\n",
311            UseDriverKey,
312            SourceString,
313            LengthStr,
314            Buffer,
315            BufferLength);
316 
317     if (UseDriverKey)
318     {
319         Status = IoOpenDeviceRegistryKey(PdoDevice,
320                                          PLUGPLAY_REGKEY_DRIVER,
321                                          STANDARD_RIGHTS_ALL,
322                                          &KeyHandle);
323     }
324     else
325     {
326         Status = IoOpenDeviceRegistryKey(PdoDevice,
327                                          PLUGPLAY_REGKEY_DEVICE,
328                                          STANDARD_RIGHTS_ALL,
329                                          &KeyHandle);
330     }
331 
332     if (NT_SUCCESS(Status))
333     {
334         RtlInitUnicodeString(&ValueName, SourceString);
335 
336         LengthKey = sizeof(KEY_VALUE_FULL_INFORMATION) +
337                     LengthStr +
338                     BufferLength;
339 
340         KeyValue = ExAllocatePoolWithTag(PagedPool,
341                                          LengthKey,
342                                          USB_PORT_TAG);
343 
344         if (KeyValue)
345         {
346             RtlZeroMemory(KeyValue, LengthKey);
347 
348             Status = ZwQueryValueKey(KeyHandle,
349                                      &ValueName,
350                                      KeyValueFullInformation,
351                                      KeyValue,
352                                      LengthKey,
353                                      &LengthKey);
354 
355             if (NT_SUCCESS(Status))
356             {
357                 RtlCopyMemory(Buffer,
358                               (PUCHAR)KeyValue + KeyValue->DataOffset,
359                               BufferLength);
360             }
361 
362             ExFreePoolWithTag(KeyValue, USB_PORT_TAG);
363         }
364 
365         ZwClose(KeyHandle);
366     }
367 
368     return Status;
369 }
370 
371 MPSTATUS
372 NTAPI
373 USBPORT_GetMiniportRegistryKeyValue(IN PVOID MiniPortExtension,
374                                     IN BOOL UseDriverKey,
375                                     IN PCWSTR SourceString,
376                                     IN SIZE_T LengthStr,
377                                     IN PVOID Buffer,
378                                     IN SIZE_T BufferLength)
379 {
380     PUSBPORT_DEVICE_EXTENSION FdoExtension;
381     PDEVICE_OBJECT FdoDevice;
382     NTSTATUS Status;
383 
384     DPRINT("USBPORT_GetMiniportRegistryKeyValue: MiniPortExtension - %p, UseDriverKey - %x, SourceString - %S, LengthStr - %x, Buffer - %p, BufferLength - %x\n",
385            MiniPortExtension,
386            UseDriverKey,
387            SourceString,
388            LengthStr,
389            Buffer,
390            BufferLength);
391 
392     FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension -
393                                                sizeof(USBPORT_DEVICE_EXTENSION));
394 
395     FdoDevice = FdoExtension->CommonExtension.SelfDevice;
396 
397     Status = USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
398                                                  FdoExtension->CommonExtension.LowerPdoDevice,
399                                                  UseDriverKey,
400                                                  SourceString,
401                                                  LengthStr,
402                                                  Buffer,
403                                                  BufferLength);
404 
405     return USBPORT_NtStatusToMpStatus(Status);
406 }
407 
408 NTSTATUS
409 NTAPI
410 USBPORT_GetSetConfigSpaceData(IN PDEVICE_OBJECT FdoDevice,
411                               IN BOOLEAN IsReadData,
412                               IN PVOID Buffer,
413                               IN ULONG Offset,
414                               IN ULONG Length)
415 {
416     PUSBPORT_DEVICE_EXTENSION FdoExtension;
417     ULONG BytesReadWrite;
418 
419     DPRINT("USBPORT_GetSetConfigSpaceData ... \n");
420 
421     FdoExtension = FdoDevice->DeviceExtension;
422 
423     BytesReadWrite = Length;
424 
425     if (IsReadData)
426     {
427         RtlZeroMemory(Buffer, Length);
428 
429         BytesReadWrite = (*FdoExtension->BusInterface.GetBusData)
430                           (FdoExtension->BusInterface.Context,
431                            PCI_WHICHSPACE_CONFIG,
432                            Buffer,
433                            Offset,
434                            Length);
435     }
436     else
437     {
438         BytesReadWrite = (*FdoExtension->BusInterface.SetBusData)
439                           (FdoExtension->BusInterface.Context,
440                            PCI_WHICHSPACE_CONFIG,
441                            Buffer,
442                            Offset,
443                            Length);
444     }
445 
446     if (BytesReadWrite == Length)
447     {
448         return STATUS_SUCCESS;
449     }
450 
451     return STATUS_UNSUCCESSFUL;
452 }
453 
454 MPSTATUS
455 NTAPI
456 USBPORT_ReadWriteConfigSpace(IN PVOID MiniPortExtension,
457                              IN BOOLEAN IsReadData,
458                              IN PVOID Buffer,
459                              IN ULONG Offset,
460                              IN ULONG Length)
461 {
462     NTSTATUS Status;
463     PUSBPORT_DEVICE_EXTENSION FdoExtension;
464     PDEVICE_OBJECT FdoDevice;
465 
466     DPRINT("USBPORT_ReadWriteConfigSpace: ... \n");
467 
468     //FdoExtension->MiniPortExt = (PVOID)((ULONG_PTR)FdoExtension + sizeof(USBPORT_DEVICE_EXTENSION));
469     FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension -
470                                                sizeof(USBPORT_DEVICE_EXTENSION));
471 
472     FdoDevice = FdoExtension->CommonExtension.SelfDevice;
473 
474     Status = USBPORT_GetSetConfigSpaceData(FdoDevice,
475                                            IsReadData,
476                                            Buffer,
477                                            Offset,
478                                            Length);
479 
480     return USBPORT_NtStatusToMpStatus(Status);
481 }
482 
483 NTSTATUS
484 NTAPI
485 USBPORT_USBDStatusToNtStatus(IN PURB Urb,
486                              IN USBD_STATUS USBDStatus)
487 {
488     NTSTATUS Status;
489 
490     if (USBD_ERROR(USBDStatus))
491     {
492         DPRINT1("USBPORT_USBDStatusToNtStatus: Urb - %p, USBDStatus - %x\n",
493                 Urb,
494                 USBDStatus);
495     }
496 
497     if (Urb)
498         Urb->UrbHeader.Status = USBDStatus;
499 
500     switch (USBDStatus)
501     {
502         case USBD_STATUS_SUCCESS:
503             Status = STATUS_SUCCESS;
504             break;
505 
506         case USBD_STATUS_INSUFFICIENT_RESOURCES:
507             Status = STATUS_INSUFFICIENT_RESOURCES;
508             break;
509 
510         case USBD_STATUS_DEVICE_GONE:
511             Status = STATUS_DEVICE_NOT_CONNECTED;
512             break;
513 
514         case USBD_STATUS_CANCELED:
515             Status = STATUS_CANCELLED;
516             break;
517 
518         case USBD_STATUS_NOT_SUPPORTED:
519             Status = STATUS_NOT_SUPPORTED;
520             break;
521 
522         case USBD_STATUS_INVALID_URB_FUNCTION:
523         case USBD_STATUS_INVALID_PARAMETER:
524         case USBD_STATUS_INVALID_PIPE_HANDLE:
525         case USBD_STATUS_BAD_START_FRAME:
526             Status = STATUS_INVALID_PARAMETER;
527             break;
528 
529         default:
530             if (USBD_ERROR(USBDStatus))
531                 Status = STATUS_UNSUCCESSFUL;
532             else
533                 Status = STATUS_SUCCESS;
534 
535             break;
536     }
537 
538     return Status;
539 }
540 
541 NTSTATUS
542 NTAPI
543 USBPORT_Wait(IN PVOID MiniPortExtension,
544              IN ULONG Milliseconds)
545 {
546     LARGE_INTEGER Interval = {{0, 0}};
547 
548     DPRINT("USBPORT_Wait: Milliseconds - %x\n", Milliseconds);
549     Interval.QuadPart -= 10000 * Milliseconds + (KeQueryTimeIncrement() - 1);
550     return KeDelayExecutionThread(KernelMode, FALSE, &Interval);
551 }
552 
553 VOID
554 NTAPI
555 USBPORT_MiniportInterrupts(IN PDEVICE_OBJECT FdoDevice,
556                            IN BOOLEAN IsEnable)
557 {
558     PUSBPORT_DEVICE_EXTENSION FdoExtension;
559     PUSBPORT_REGISTRATION_PACKET Packet;
560     BOOLEAN IsLock;
561     KIRQL OldIrql;
562 
563     DPRINT_INT("USBPORT_MiniportInterrupts: IsEnable - %p\n", IsEnable);
564 
565     FdoExtension = FdoDevice->DeviceExtension;
566     Packet = &FdoExtension->MiniPortInterface->Packet;
567 
568     IsLock = (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_NOT_LOCK_INT) == 0;
569 
570     if (IsLock)
571         KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
572 
573     if (IsEnable)
574     {
575         FdoExtension->Flags |= USBPORT_FLAG_INTERRUPT_ENABLED;
576         Packet->EnableInterrupts(FdoExtension->MiniPortExt);
577     }
578     else
579     {
580         Packet->DisableInterrupts(FdoExtension->MiniPortExt);
581         FdoExtension->Flags &= ~USBPORT_FLAG_INTERRUPT_ENABLED;
582     }
583 
584     if (IsLock)
585         KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
586 }
587 
588 VOID
589 NTAPI
590 USBPORT_SoftInterruptDpc(IN PRKDPC Dpc,
591                          IN PVOID DeferredContext,
592                          IN PVOID SystemArgument1,
593                          IN PVOID SystemArgument2)
594 {
595     PDEVICE_OBJECT FdoDevice;
596     PUSBPORT_DEVICE_EXTENSION FdoExtension;
597 
598     DPRINT_INT("USBPORT_SoftInterruptDpc: ... \n");
599 
600     FdoDevice = DeferredContext;
601     FdoExtension = FdoDevice->DeviceExtension;
602 
603     if (!KeInsertQueueDpc(&FdoExtension->IsrDpc, NULL, (PVOID)1))
604     {
605         InterlockedDecrement(&FdoExtension->IsrDpcCounter);
606     }
607 }
608 
609 VOID
610 NTAPI
611 USBPORT_SoftInterrupt(IN PDEVICE_OBJECT FdoDevice)
612 {
613     PUSBPORT_DEVICE_EXTENSION FdoExtension;
614     LARGE_INTEGER DueTime = {{0, 0}};
615 
616     DPRINT_INT("USBPORT_SoftInterrupt: ... \n");
617 
618     FdoExtension = FdoDevice->DeviceExtension;
619 
620     KeInitializeTimer(&FdoExtension->TimerSoftInterrupt);
621 
622     KeInitializeDpc(&FdoExtension->SoftInterruptDpc,
623                     USBPORT_SoftInterruptDpc,
624                     FdoDevice);
625 
626     DueTime.QuadPart -= 10000 + (KeQueryTimeIncrement() - 1);
627 
628     KeSetTimer(&FdoExtension->TimerSoftInterrupt,
629                DueTime,
630                &FdoExtension->SoftInterruptDpc);
631 }
632 
633 VOID
634 NTAPI
635 USBPORT_InvalidateControllerHandler(IN PDEVICE_OBJECT FdoDevice,
636                                     IN ULONG Type)
637 {
638     PUSBPORT_DEVICE_EXTENSION FdoExtension;
639 
640     DPRINT_CORE("USBPORT_InvalidateControllerHandler: Invalidate Type - %x\n",
641                 Type);
642 
643     FdoExtension = FdoDevice->DeviceExtension;
644 
645     switch (Type)
646     {
647         case USBPORT_INVALIDATE_CONTROLLER_RESET:
648             DPRINT1("USBPORT_InvalidateControllerHandler: INVALIDATE_CONTROLLER_RESET UNIMPLEMENTED. FIXME. \n");
649             break;
650 
651         case USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE:
652             DPRINT1("USBPORT_InvalidateControllerHandler: INVALIDATE_CONTROLLER_SURPRISE_REMOVE UNIMPLEMENTED. FIXME. \n");
653             break;
654 
655         case USBPORT_INVALIDATE_CONTROLLER_SOFT_INTERRUPT:
656             if (InterlockedIncrement(&FdoExtension->IsrDpcCounter))
657             {
658                 InterlockedDecrement(&FdoExtension->IsrDpcCounter);
659             }
660             else
661             {
662                 USBPORT_SoftInterrupt(FdoDevice);
663             }
664             break;
665     }
666 }
667 
668 ULONG
669 NTAPI
670 USBPORT_InvalidateController(IN PVOID MiniPortExtension,
671                              IN ULONG Type)
672 {
673     PUSBPORT_DEVICE_EXTENSION FdoExtension;
674     PDEVICE_OBJECT FdoDevice;
675 
676     DPRINT("USBPORT_InvalidateController: Invalidate Type - %x\n", Type);
677 
678     //FdoExtension->MiniPortExt = (PVOID)((ULONG_PTR)FdoExtension + sizeof(USBPORT_DEVICE_EXTENSION));
679     FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension -
680                                                sizeof(USBPORT_DEVICE_EXTENSION));
681     FdoDevice = FdoExtension->CommonExtension.SelfDevice;
682 
683     USBPORT_InvalidateControllerHandler(FdoDevice, Type);
684 
685     return 0;
686 }
687 
688 ULONG
689 NTAPI
690 USBPORT_NotifyDoubleBuffer(IN PVOID MiniPortExtension,
691                            IN PVOID MiniPortTransfer,
692                            IN PVOID Buffer,
693                            IN SIZE_T Length)
694 {
695     DPRINT1("USBPORT_NotifyDoubleBuffer: UNIMPLEMENTED. FIXME. \n");
696     return 0;
697 }
698 
699 VOID
700 NTAPI
701 USBPORT_WorkerRequestDpc(IN PRKDPC Dpc,
702                          IN PVOID DeferredContext,
703                          IN PVOID SystemArgument1,
704                          IN PVOID SystemArgument2)
705 {
706     PDEVICE_OBJECT FdoDevice;
707     PUSBPORT_DEVICE_EXTENSION FdoExtension;
708 
709     DPRINT("USBPORT_WorkerRequestDpc: ... \n");
710 
711     FdoDevice = DeferredContext;
712     FdoExtension = FdoDevice->DeviceExtension;
713 
714     if (!InterlockedIncrement(&FdoExtension->IsrDpcHandlerCounter))
715     {
716         USBPORT_DpcHandler(FdoDevice);
717     }
718 
719     InterlockedDecrement(&FdoExtension->IsrDpcHandlerCounter);
720 }
721 
722 VOID
723 NTAPI
724 USBPORT_DoneTransfer(IN PUSBPORT_TRANSFER Transfer)
725 {
726     PUSBPORT_ENDPOINT          Endpoint;
727     PDEVICE_OBJECT             FdoDevice;
728     PUSBPORT_DEVICE_EXTENSION  FdoExtension;
729     PURB                       Urb;
730     PIRP                       Irp;
731     KIRQL                      CancelIrql;
732     KIRQL                      OldIrql;
733 
734     DPRINT_CORE("USBPORT_DoneTransfer: Transfer - %p\n", Transfer);
735 
736     Endpoint = Transfer->Endpoint;
737     FdoDevice = Endpoint->FdoDevice;
738     FdoExtension = FdoDevice->DeviceExtension;
739 
740     Urb = Transfer->Urb;
741     Irp = Transfer->Irp;
742 
743     KeAcquireSpinLock(&FdoExtension->FlushTransferSpinLock, &OldIrql);
744 
745     if (Irp)
746     {
747         IoAcquireCancelSpinLock(&CancelIrql);
748         IoSetCancelRoutine(Irp, NULL);
749         IoReleaseCancelSpinLock(CancelIrql);
750 
751         USBPORT_RemoveActiveTransferIrp(FdoDevice, Irp);
752     }
753 
754     KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
755 
756     USBPORT_USBDStatusToNtStatus(Transfer->Urb, Transfer->USBDStatus);
757     USBPORT_CompleteTransfer(Urb, Urb->UrbHeader.Status);
758 
759     DPRINT_CORE("USBPORT_DoneTransfer: exit\n");
760 }
761 
762 VOID
763 NTAPI
764 USBPORT_FlushDoneTransfers(IN PDEVICE_OBJECT FdoDevice)
765 {
766     PUSBPORT_DEVICE_EXTENSION FdoExtension;
767     PLIST_ENTRY DoneTransferList;
768     PUSBPORT_TRANSFER Transfer;
769     PUSBPORT_ENDPOINT Endpoint;
770     ULONG TransferCount;
771     KIRQL OldIrql;
772     BOOLEAN IsHasTransfers;
773 
774     DPRINT_CORE("USBPORT_FlushDoneTransfers: ... \n");
775 
776     FdoExtension = FdoDevice->DeviceExtension;
777     DoneTransferList = &FdoExtension->DoneTransferList;
778 
779     while (TRUE)
780     {
781         KeAcquireSpinLock(&FdoExtension->DoneTransferSpinLock, &OldIrql);
782 
783         if (IsListEmpty(DoneTransferList))
784             break;
785 
786         Transfer = CONTAINING_RECORD(DoneTransferList->Flink,
787                                      USBPORT_TRANSFER,
788                                      TransferLink);
789 
790         RemoveHeadList(DoneTransferList);
791         KeReleaseSpinLock(&FdoExtension->DoneTransferSpinLock, OldIrql);
792 
793         if (Transfer)
794         {
795             Endpoint = Transfer->Endpoint;
796 
797             if ((Transfer->Flags & TRANSFER_FLAG_SPLITED))
798             {
799                 USBPORT_DoneSplitTransfer(Transfer);
800             }
801             else
802             {
803                 USBPORT_DoneTransfer(Transfer);
804             }
805 
806             IsHasTransfers = USBPORT_EndpointHasQueuedTransfers(FdoDevice,
807                                                                 Endpoint,
808                                                                 &TransferCount);
809 
810             if (IsHasTransfers && !TransferCount)
811             {
812                 USBPORT_InvalidateEndpointHandler(FdoDevice,
813                                                   Endpoint,
814                                                   INVALIDATE_ENDPOINT_WORKER_DPC);
815             }
816         }
817     }
818 
819     KeReleaseSpinLock(&FdoExtension->DoneTransferSpinLock, OldIrql);
820 }
821 
822 
823 VOID
824 NTAPI
825 USBPORT_TransferFlushDpc(IN PRKDPC Dpc,
826                          IN PVOID DeferredContext,
827                          IN PVOID SystemArgument1,
828                          IN PVOID SystemArgument2)
829 {
830     PDEVICE_OBJECT FdoDevice;
831 
832     DPRINT_CORE("USBPORT_TransferFlushDpc: ... \n");
833     FdoDevice = DeferredContext;
834     USBPORT_FlushDoneTransfers(FdoDevice);
835 }
836 
837 BOOLEAN
838 NTAPI
839 USBPORT_QueueDoneTransfer(IN PUSBPORT_TRANSFER Transfer,
840                           IN USBD_STATUS USBDStatus)
841 {
842     PDEVICE_OBJECT FdoDevice;
843     PUSBPORT_DEVICE_EXTENSION  FdoExtension;
844 
845     DPRINT_CORE("USBPORT_QueueDoneTransfer: Transfer - %p, USBDStatus - %p\n",
846                 Transfer,
847                 USBDStatus);
848 
849     FdoDevice = Transfer->Endpoint->FdoDevice;
850     FdoExtension = FdoDevice->DeviceExtension;
851 
852     RemoveEntryList(&Transfer->TransferLink);
853     Transfer->USBDStatus = USBDStatus;
854 
855     ExInterlockedInsertTailList(&FdoExtension->DoneTransferList,
856                                 &Transfer->TransferLink,
857                                 &FdoExtension->DoneTransferSpinLock);
858 
859     return KeInsertQueueDpc(&FdoExtension->TransferFlushDpc, NULL, NULL);
860 }
861 
862 VOID
863 NTAPI
864 USBPORT_DpcHandler(IN PDEVICE_OBJECT FdoDevice)
865 {
866     PUSBPORT_DEVICE_EXTENSION FdoExtension;
867     PUSBPORT_ENDPOINT Endpoint;
868     PLIST_ENTRY Entry;
869     LIST_ENTRY List;
870     LONG LockCounter;
871 
872     DPRINT_CORE("USBPORT_DpcHandler: ... \n");
873 
874     FdoExtension = FdoDevice->DeviceExtension;
875 
876     InitializeListHead(&List);
877 
878     KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock);
879     Entry = FdoExtension->EndpointList.Flink;
880 
881     while (Entry && Entry != &FdoExtension->EndpointList)
882     {
883         Endpoint = CONTAINING_RECORD(Entry,
884                                      USBPORT_ENDPOINT,
885                                      EndpointLink);
886 
887         LockCounter = InterlockedIncrement(&Endpoint->LockCounter);
888 
889         if (USBPORT_GetEndpointState(Endpoint) != USBPORT_ENDPOINT_ACTIVE ||
890             LockCounter ||
891             Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
892         {
893             InterlockedDecrement(&Endpoint->LockCounter);
894         }
895         else
896         {
897             InsertTailList(&List, &Endpoint->DispatchLink);
898 
899             if (Endpoint->WorkerLink.Flink && Endpoint->WorkerLink.Blink)
900             {
901                 RemoveEntryList(&Endpoint->WorkerLink);
902 
903                 Endpoint->WorkerLink.Flink = NULL;
904                 Endpoint->WorkerLink.Blink = NULL;
905             }
906         }
907 
908         Entry = Endpoint->EndpointLink.Flink;
909     }
910 
911     KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
912 
913     while (!IsListEmpty(&List))
914     {
915         Endpoint = CONTAINING_RECORD(List.Flink,
916                                      USBPORT_ENDPOINT,
917                                      DispatchLink);
918 
919         RemoveEntryList(List.Flink);
920         Endpoint->DispatchLink.Flink = NULL;
921         Endpoint->DispatchLink.Blink = NULL;
922 
923         USBPORT_EndpointWorker(Endpoint, TRUE);
924         USBPORT_FlushPendingTransfers(Endpoint);
925     }
926 
927     KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock);
928 
929     if (!IsListEmpty(&FdoExtension->WorkerList))
930     {
931         USBPORT_SignalWorkerThread(FdoDevice);
932     }
933 
934     KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
935 
936     USBPORT_FlushDoneTransfers(FdoDevice);
937 }
938 
939 VOID
940 NTAPI
941 USBPORT_IsrDpcHandler(IN PDEVICE_OBJECT FdoDevice,
942                       IN BOOLEAN IsDpcHandler)
943 {
944     PUSBPORT_DEVICE_EXTENSION FdoExtension;
945     PUSBPORT_REGISTRATION_PACKET Packet;
946     PUSBPORT_ENDPOINT Endpoint;
947     PLIST_ENTRY List;
948     ULONG FrameNumber;
949 
950     ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
951 
952     DPRINT_CORE("USBPORT_IsrDpcHandler: IsDpcHandler - %x\n", IsDpcHandler);
953 
954     FdoExtension = FdoDevice->DeviceExtension;
955     Packet = &FdoExtension->MiniPortInterface->Packet;
956 
957     if (InterlockedIncrement(&FdoExtension->IsrDpcHandlerCounter))
958     {
959         KeInsertQueueDpc(&FdoExtension->IsrDpc, NULL, NULL);
960         InterlockedDecrement(&FdoExtension->IsrDpcHandlerCounter);
961         return;
962     }
963 
964     for (List = ExInterlockedRemoveHeadList(&FdoExtension->EpStateChangeList,
965                                             &FdoExtension->EpStateChangeSpinLock);
966          List != NULL;
967          List = ExInterlockedRemoveHeadList(&FdoExtension->EpStateChangeList,
968                                             &FdoExtension->EpStateChangeSpinLock))
969     {
970         Endpoint = CONTAINING_RECORD(List,
971                                      USBPORT_ENDPOINT,
972                                      StateChangeLink);
973 
974         DPRINT_CORE("USBPORT_IsrDpcHandler: Endpoint - %p\n", Endpoint);
975 
976         KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
977 
978         KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
979         FrameNumber = Packet->Get32BitFrameNumber(FdoExtension->MiniPortExt);
980         KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
981 
982         if (FrameNumber <= Endpoint->FrameNumber &&
983             !(Endpoint->Flags & ENDPOINT_FLAG_NUKE))
984         {
985             KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
986 
987             ExInterlockedInsertHeadList(&FdoExtension->EpStateChangeList,
988                                         &Endpoint->StateChangeLink,
989                                         &FdoExtension->EpStateChangeSpinLock);
990 
991             KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
992             Packet->InterruptNextSOF(FdoExtension->MiniPortExt);
993             KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
994 
995             break;
996         }
997 
998         KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
999 
1000         KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock);
1001         Endpoint->StateLast = Endpoint->StateNext;
1002         KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock);
1003 
1004         DPRINT_CORE("USBPORT_IsrDpcHandler: Endpoint->StateLast - %x\n",
1005                     Endpoint->StateLast);
1006 
1007         if (IsDpcHandler)
1008         {
1009             USBPORT_InvalidateEndpointHandler(FdoDevice,
1010                                               Endpoint,
1011                                               INVALIDATE_ENDPOINT_ONLY);
1012         }
1013         else
1014         {
1015             USBPORT_InvalidateEndpointHandler(FdoDevice,
1016                                               Endpoint,
1017                                               INVALIDATE_ENDPOINT_WORKER_THREAD);
1018         }
1019     }
1020 
1021     if (IsDpcHandler)
1022     {
1023         USBPORT_DpcHandler(FdoDevice);
1024     }
1025 
1026     InterlockedDecrement(&FdoExtension->IsrDpcHandlerCounter);
1027 }
1028 
1029 VOID
1030 NTAPI
1031 USBPORT_IsrDpc(IN PRKDPC Dpc,
1032                IN PVOID DeferredContext,
1033                IN PVOID SystemArgument1,
1034                IN PVOID SystemArgument2)
1035 {
1036     PDEVICE_OBJECT FdoDevice;
1037     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1038     PUSBPORT_REGISTRATION_PACKET Packet;
1039     BOOLEAN InterruptEnable;
1040 
1041     DPRINT_INT("USBPORT_IsrDpc: DeferredContext - %p, SystemArgument2 - %p\n",
1042                DeferredContext,
1043                SystemArgument2);
1044 
1045     FdoDevice = DeferredContext;
1046     FdoExtension = FdoDevice->DeviceExtension;
1047     Packet = &FdoExtension->MiniPortInterface->Packet;
1048 
1049     if (SystemArgument2)
1050     {
1051         InterlockedDecrement(&FdoExtension->IsrDpcCounter);
1052     }
1053 
1054     KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportInterruptsSpinLock);
1055     InterruptEnable = (FdoExtension->Flags & USBPORT_FLAG_INTERRUPT_ENABLED) ==
1056                        USBPORT_FLAG_INTERRUPT_ENABLED;
1057 
1058     Packet->InterruptDpc(FdoExtension->MiniPortExt, InterruptEnable);
1059 
1060     KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportInterruptsSpinLock);
1061 
1062     if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND &&
1063         FdoExtension->TimerFlags & USBPORT_TMFLAG_WAKE)
1064     {
1065         USBPORT_CompletePdoWaitWake(FdoDevice);
1066     }
1067     else
1068     {
1069         USBPORT_IsrDpcHandler(FdoDevice, TRUE);
1070     }
1071 
1072     DPRINT_INT("USBPORT_IsrDpc: exit\n");
1073 }
1074 
1075 BOOLEAN
1076 NTAPI
1077 USBPORT_InterruptService(IN PKINTERRUPT Interrupt,
1078                          IN PVOID ServiceContext)
1079 {
1080     PDEVICE_OBJECT FdoDevice;
1081     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1082     PUSBPORT_REGISTRATION_PACKET Packet;
1083     BOOLEAN Result = FALSE;
1084 
1085     FdoDevice = ServiceContext;
1086     FdoExtension = FdoDevice->DeviceExtension;
1087     Packet = &FdoExtension->MiniPortInterface->Packet;
1088 
1089     DPRINT_INT("USBPORT_InterruptService: FdoExtension[%p]->Flags - %08X\n",
1090            FdoExtension,
1091            FdoExtension->Flags);
1092 
1093     if (FdoExtension->Flags & USBPORT_FLAG_INTERRUPT_ENABLED &&
1094         FdoExtension->MiniPortFlags & USBPORT_MPFLAG_INTERRUPTS_ENABLED)
1095     {
1096         Result = Packet->InterruptService(FdoExtension->MiniPortExt);
1097 
1098         if (Result)
1099         {
1100             KeInsertQueueDpc(&FdoExtension->IsrDpc, NULL, NULL);
1101         }
1102     }
1103 
1104     DPRINT_INT("USBPORT_InterruptService: return - %x\n", Result);
1105 
1106     return Result;
1107 }
1108 
1109 VOID
1110 NTAPI
1111 USBPORT_SignalWorkerThread(IN PDEVICE_OBJECT FdoDevice)
1112 {
1113     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1114     KIRQL OldIrql;
1115 
1116     DPRINT_CORE("USBPORT_SignalWorkerThread ... \n");
1117 
1118     FdoExtension = FdoDevice->DeviceExtension;
1119 
1120     KeAcquireSpinLock(&FdoExtension->WorkerThreadEventSpinLock, &OldIrql);
1121     KeSetEvent(&FdoExtension->WorkerThreadEvent, EVENT_INCREMENT, FALSE);
1122     KeReleaseSpinLock(&FdoExtension->WorkerThreadEventSpinLock, OldIrql);
1123 }
1124 
1125 VOID
1126 NTAPI
1127 USBPORT_WorkerThreadHandler(IN PDEVICE_OBJECT FdoDevice)
1128 {
1129     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1130     PUSBPORT_REGISTRATION_PACKET Packet;
1131     PLIST_ENTRY workerList;
1132     KIRQL OldIrql;
1133     PUSBPORT_ENDPOINT Endpoint;
1134     LIST_ENTRY list;
1135     BOOLEAN Result;
1136 
1137     DPRINT_CORE("USBPORT_WorkerThreadHandler: ... \n");
1138 
1139     FdoExtension = FdoDevice->DeviceExtension;
1140     Packet = &FdoExtension->MiniPortInterface->Packet;
1141 
1142     KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1143 
1144     if (!(FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND))
1145     {
1146         Packet->CheckController(FdoExtension->MiniPortExt);
1147     }
1148 
1149     KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
1150 
1151     InitializeListHead(&list);
1152 
1153     USBPORT_FlushAllEndpoints(FdoDevice);
1154 
1155     while (TRUE)
1156     {
1157         KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1158         KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock);
1159 
1160         workerList = &FdoExtension->WorkerList;
1161 
1162         if (IsListEmpty(workerList))
1163             break;
1164 
1165         Endpoint = CONTAINING_RECORD(workerList->Flink,
1166                                      USBPORT_ENDPOINT,
1167                                      WorkerLink);
1168 
1169         DPRINT_CORE("USBPORT_WorkerThreadHandler: Endpoint - %p\n", Endpoint);
1170 
1171         RemoveHeadList(workerList);
1172         Endpoint->WorkerLink.Blink = NULL;
1173         Endpoint->WorkerLink.Flink = NULL;
1174 
1175         KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
1176 
1177         Result = USBPORT_EndpointWorker(Endpoint, FALSE);
1178         KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock);
1179 
1180         if (Result)
1181         {
1182             if (Endpoint->FlushAbortLink.Flink == NULL ||
1183                 Endpoint->FlushAbortLink.Blink == NULL)
1184             {
1185                 InsertTailList(&list, &Endpoint->FlushAbortLink);
1186             }
1187         }
1188 
1189         while (!IsListEmpty(&list))
1190         {
1191             Endpoint = CONTAINING_RECORD(list.Flink,
1192                                          USBPORT_ENDPOINT,
1193                                          FlushAbortLink);
1194 
1195             RemoveHeadList(&list);
1196 
1197             Endpoint->FlushAbortLink.Flink = NULL;
1198             Endpoint->FlushAbortLink.Blink = NULL;
1199 
1200             if (Endpoint->WorkerLink.Flink == NULL ||
1201                 Endpoint->WorkerLink.Blink == NULL)
1202             {
1203                 InsertTailList(&FdoExtension->WorkerList,
1204                                &Endpoint->WorkerLink);
1205 
1206                 USBPORT_SignalWorkerThread(FdoDevice);
1207             }
1208         }
1209 
1210         KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
1211         KeLowerIrql(OldIrql);
1212     }
1213 
1214     KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
1215     KeLowerIrql(OldIrql);
1216 
1217     USBPORT_FlushClosedEndpointList(FdoDevice);
1218 }
1219 
1220 VOID
1221 NTAPI
1222 USBPORT_DoRootHubCallback(IN PDEVICE_OBJECT FdoDevice)
1223 {
1224     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1225     PDEVICE_OBJECT PdoDevice;
1226     PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
1227     PRH_INIT_CALLBACK RootHubInitCallback;
1228     PVOID RootHubInitContext;
1229 
1230     FdoExtension = FdoDevice->DeviceExtension;
1231 
1232     DPRINT("USBPORT_DoRootHubCallback: FdoDevice - %p\n", FdoDevice);
1233 
1234     PdoDevice = FdoExtension->RootHubPdo;
1235 
1236     if (PdoDevice)
1237     {
1238         PdoExtension = PdoDevice->DeviceExtension;
1239 
1240         RootHubInitContext = PdoExtension->RootHubInitContext;
1241         RootHubInitCallback = PdoExtension->RootHubInitCallback;
1242 
1243         PdoExtension->RootHubInitCallback = NULL;
1244         PdoExtension->RootHubInitContext = NULL;
1245 
1246         if (RootHubInitCallback)
1247         {
1248             RootHubInitCallback(RootHubInitContext);
1249         }
1250     }
1251 
1252     DPRINT("USBPORT_DoRootHubCallback: exit\n");
1253 }
1254 
1255 VOID
1256 NTAPI
1257 USBPORT_SynchronizeRootHubCallback(IN PDEVICE_OBJECT FdoDevice,
1258                                    IN PDEVICE_OBJECT Usb2FdoDevice)
1259 {
1260     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1261     PUSBPORT_REGISTRATION_PACKET Packet;
1262     PUSBPORT_DEVICE_EXTENSION Usb2FdoExtension;
1263     PDEVICE_RELATIONS CompanionControllersList;
1264     PUSBPORT_DEVICE_EXTENSION CompanionFdoExtension;
1265     PDEVICE_OBJECT * Entry;
1266     ULONG ix;
1267 
1268     DPRINT("USBPORT_SynchronizeRootHubCallback: FdoDevice - %p, Usb2FdoDevice - %p\n",
1269            FdoDevice,
1270            Usb2FdoDevice);
1271 
1272     FdoExtension = FdoDevice->DeviceExtension;
1273     Packet = &FdoExtension->MiniPortInterface->Packet;
1274 
1275     if (Usb2FdoDevice == NULL &&
1276         !(Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2))
1277     {
1278         /* Not Companion USB11 Controller */
1279         USBPORT_DoRootHubCallback(FdoDevice);
1280 
1281         FdoExtension->Flags &= ~USBPORT_FLAG_RH_INIT_CALLBACK;
1282         InterlockedCompareExchange(&FdoExtension->RHInitCallBackLock, 0, 1);
1283 
1284         DPRINT("USBPORT_SynchronizeRootHubCallback: exit \n");
1285         return;
1286     }
1287 
1288     /* USB2 or Companion USB11 */
1289 
1290     DPRINT("USBPORT_SynchronizeRootHubCallback: FdoExtension->Flags - %p\n",
1291            FdoExtension->Flags);
1292 
1293     if (!(FdoExtension->Flags & USBPORT_FLAG_COMPANION_HC))
1294     {
1295         KeWaitForSingleObject(&FdoExtension->ControllerSemaphore,
1296                               Executive,
1297                               KernelMode,
1298                               FALSE,
1299                               NULL);
1300 
1301         FdoExtension->Flags |= USBPORT_FLAG_PWR_AND_CHIRP_LOCK;
1302 
1303         if (!(FdoExtension->Flags & (USBPORT_FLAG_HC_SUSPEND |
1304                                      USBPORT_FLAG_POWER_AND_CHIRP_OK)))
1305         {
1306             USBPORT_RootHubPowerAndChirpAllCcPorts(FdoDevice);
1307             FdoExtension->Flags |= USBPORT_FLAG_POWER_AND_CHIRP_OK;
1308         }
1309 
1310         FdoExtension->Flags &= ~USBPORT_FLAG_PWR_AND_CHIRP_LOCK;
1311 
1312         KeReleaseSemaphore(&FdoExtension->ControllerSemaphore,
1313                            LOW_REALTIME_PRIORITY,
1314                            1,
1315                            FALSE);
1316 
1317         CompanionControllersList = USBPORT_FindCompanionControllers(FdoDevice,
1318                                                                     FALSE,
1319                                                                     TRUE);
1320 
1321         if (CompanionControllersList)
1322         {
1323             Entry = &CompanionControllersList->Objects[0];
1324 
1325             for (ix = 0; ix < CompanionControllersList->Count; ++ix)
1326             {
1327                 CompanionFdoExtension = ((*Entry)->DeviceExtension);
1328 
1329                 InterlockedCompareExchange(&CompanionFdoExtension->RHInitCallBackLock,
1330                                            0,
1331                                            1);
1332 
1333                 ++Entry;
1334             }
1335 
1336             ExFreePoolWithTag(CompanionControllersList, USB_PORT_TAG);
1337         }
1338 
1339         USBPORT_DoRootHubCallback(FdoDevice);
1340 
1341         FdoExtension->Flags &= ~USBPORT_FLAG_RH_INIT_CALLBACK;
1342         InterlockedCompareExchange(&FdoExtension->RHInitCallBackLock, 0, 1);
1343     }
1344     else
1345     {
1346         Usb2FdoExtension = Usb2FdoDevice->DeviceExtension;
1347 
1348         USBPORT_Wait(FdoDevice, 50);
1349 
1350         while (FdoExtension->RHInitCallBackLock)
1351         {
1352             USBPORT_Wait(FdoDevice, 10);
1353 
1354             Usb2FdoExtension->Flags |= USBPORT_FLAG_RH_INIT_CALLBACK;
1355             USBPORT_SignalWorkerThread(Usb2FdoDevice);
1356         }
1357 
1358         USBPORT_DoRootHubCallback(FdoDevice);
1359 
1360         FdoExtension->Flags &= ~USBPORT_FLAG_RH_INIT_CALLBACK;
1361     }
1362 
1363     DPRINT("USBPORT_SynchronizeRootHubCallback: exit \n");
1364 }
1365 
1366 VOID
1367 NTAPI
1368 USBPORT_WorkerThread(IN PVOID StartContext)
1369 {
1370     PDEVICE_OBJECT FdoDevice;
1371     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1372     LARGE_INTEGER OldTime;
1373     LARGE_INTEGER NewTime;
1374     KIRQL OldIrql;
1375 
1376     DPRINT_CORE("USBPORT_WorkerThread ... \n");
1377 
1378     FdoDevice = StartContext;
1379     FdoExtension = FdoDevice->DeviceExtension;
1380 
1381     FdoExtension->WorkerThread = KeGetCurrentThread();
1382 
1383     do
1384     {
1385         KeQuerySystemTime(&OldTime);
1386 
1387         KeWaitForSingleObject(&FdoExtension->WorkerThreadEvent,
1388                               Suspended,
1389                               KernelMode,
1390                               FALSE,
1391                               NULL);
1392 
1393         KeQuerySystemTime(&NewTime);
1394 
1395         KeAcquireSpinLock(&FdoExtension->WorkerThreadEventSpinLock, &OldIrql);
1396         KeClearEvent(&FdoExtension->WorkerThreadEvent);
1397         KeReleaseSpinLock(&FdoExtension->WorkerThreadEventSpinLock, OldIrql);
1398         DPRINT_CORE("USBPORT_WorkerThread: run \n");
1399 
1400         if (FdoExtension->MiniPortFlags & USBPORT_MPFLAG_INTERRUPTS_ENABLED)
1401         {
1402             USBPORT_DoSetPowerD0(FdoDevice);
1403 
1404             if (FdoExtension->Flags & USBPORT_FLAG_RH_INIT_CALLBACK)
1405             {
1406                 PDEVICE_OBJECT USB2FdoDevice = NULL;
1407 
1408                 USB2FdoDevice = USBPORT_FindUSB2Controller(FdoDevice);
1409                 USBPORT_SynchronizeRootHubCallback(FdoDevice, USB2FdoDevice);
1410             }
1411         }
1412 
1413         USBPORT_WorkerThreadHandler(FdoDevice);
1414     }
1415     while (!(FdoExtension->Flags & USBPORT_FLAG_WORKER_THREAD_ON));
1416 
1417     PsTerminateSystemThread(0);
1418 }
1419 
1420 NTSTATUS
1421 NTAPI
1422 USBPORT_CreateWorkerThread(IN PDEVICE_OBJECT FdoDevice)
1423 {
1424     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1425     NTSTATUS Status;
1426 
1427     DPRINT("USBPORT_CreateWorkerThread ... \n");
1428 
1429     FdoExtension = FdoDevice->DeviceExtension;
1430 
1431     FdoExtension->Flags &= ~USBPORT_FLAG_WORKER_THREAD_ON;
1432 
1433     KeInitializeEvent(&FdoExtension->WorkerThreadEvent,
1434                       NotificationEvent,
1435                       FALSE);
1436 
1437     Status = PsCreateSystemThread(&FdoExtension->WorkerThreadHandle,
1438                                   THREAD_ALL_ACCESS,
1439                                   NULL,
1440                                   NULL,
1441                                   NULL,
1442                                   USBPORT_WorkerThread,
1443                                   (PVOID)FdoDevice);
1444 
1445     return Status;
1446 }
1447 
1448 VOID
1449 NTAPI
1450 USBPORT_SynchronizeControllersStart(IN PDEVICE_OBJECT FdoDevice)
1451 {
1452     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1453     PDEVICE_OBJECT PdoDevice;
1454     PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
1455     PDEVICE_OBJECT USB2FdoDevice = NULL;
1456     PUSBPORT_DEVICE_EXTENSION USB2FdoExtension;
1457     BOOLEAN IsOn;
1458 
1459     DPRINT_TIMER("USBPORT_SynchronizeControllersStart: FdoDevice - %p\n",
1460                  FdoDevice);
1461 
1462     FdoExtension = FdoDevice->DeviceExtension;
1463 
1464     PdoDevice = FdoExtension->RootHubPdo;
1465 
1466     if (!PdoDevice)
1467     {
1468         return;
1469     }
1470 
1471     PdoExtension = PdoDevice->DeviceExtension;
1472 
1473     if (PdoExtension->RootHubInitCallback == NULL ||
1474         FdoExtension->Flags & USBPORT_FLAG_RH_INIT_CALLBACK)
1475     {
1476         return;
1477     }
1478 
1479     DPRINT_TIMER("USBPORT_SynchronizeControllersStart: Flags - %p\n",
1480                  FdoExtension->Flags);
1481 
1482     if (FdoExtension->Flags & USBPORT_FLAG_COMPANION_HC)
1483     {
1484         IsOn = FALSE;
1485 
1486         USB2FdoDevice = USBPORT_FindUSB2Controller(FdoDevice);
1487 
1488         DPRINT_TIMER("USBPORT_SynchronizeControllersStart: USB2FdoDevice - %p\n",
1489                      USB2FdoDevice);
1490 
1491         if (USB2FdoDevice)
1492         {
1493             USB2FdoExtension = USB2FdoDevice->DeviceExtension;
1494 
1495             if (USB2FdoExtension->CommonExtension.PnpStateFlags &
1496                 USBPORT_PNP_STATE_STARTED)
1497             {
1498                 IsOn = TRUE;
1499             }
1500         }
1501 
1502         if (!(FdoExtension->Flags & USBPORT_FLAG_NO_HACTION))
1503         {
1504             goto Start;
1505         }
1506 
1507         USB2FdoDevice = NULL;
1508     }
1509 
1510     IsOn = TRUE;
1511 
1512   Start:
1513 
1514     if (IsOn &&
1515         !InterlockedCompareExchange(&FdoExtension->RHInitCallBackLock, 1, 0))
1516     {
1517         FdoExtension->Flags |= USBPORT_FLAG_RH_INIT_CALLBACK;
1518         USBPORT_SignalWorkerThread(FdoDevice);
1519 
1520         if (USB2FdoDevice)
1521         {
1522             USB2FdoExtension = USB2FdoDevice->DeviceExtension;
1523 
1524             USB2FdoExtension->Flags |= USBPORT_FLAG_RH_INIT_CALLBACK;
1525             USBPORT_SignalWorkerThread(USB2FdoDevice);
1526         }
1527     }
1528 
1529     DPRINT_TIMER("USBPORT_SynchronizeControllersStart: exit\n");
1530 }
1531 
1532 VOID
1533 NTAPI
1534 USBPORT_TimerDpc(IN PRKDPC Dpc,
1535                  IN PVOID DeferredContext,
1536                  IN PVOID SystemArgument1,
1537                  IN PVOID SystemArgument2)
1538 {
1539     PDEVICE_OBJECT FdoDevice;
1540     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1541     PUSBPORT_REGISTRATION_PACKET Packet;
1542     LARGE_INTEGER DueTime = {{0, 0}};
1543     ULONG TimerFlags;
1544     PTIMER_WORK_QUEUE_ITEM IdleQueueItem;
1545     KIRQL OldIrql;
1546     KIRQL TimerOldIrql;
1547 
1548     DPRINT_TIMER("USBPORT_TimerDpc: Dpc - %p, DeferredContext - %p\n",
1549            Dpc,
1550            DeferredContext);
1551 
1552     FdoDevice = DeferredContext;
1553     FdoExtension = FdoDevice->DeviceExtension;
1554     Packet = &FdoExtension->MiniPortInterface->Packet;
1555 
1556     KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &TimerOldIrql);
1557 
1558     TimerFlags = FdoExtension->TimerFlags;
1559 
1560     DPRINT_TIMER("USBPORT_TimerDpc: Flags - %p, TimerFlags - %p\n",
1561                  FdoExtension->Flags,
1562                  TimerFlags);
1563 
1564     if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND &&
1565         FdoExtension->Flags & USBPORT_FLAG_HC_WAKE_SUPPORT &&
1566         !(TimerFlags & USBPORT_TMFLAG_HC_RESUME))
1567     {
1568         KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1569         Packet->PollController(FdoExtension->MiniPortExt);
1570         KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
1571     }
1572 
1573     USBPORT_SynchronizeControllersStart(FdoDevice);
1574 
1575     if (TimerFlags & USBPORT_TMFLAG_HC_SUSPENDED)
1576     {
1577         USBPORT_BadRequestFlush(FdoDevice);
1578         goto Exit;
1579     }
1580 
1581     KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1582 
1583     if (!(FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND))
1584     {
1585         Packet->CheckController(FdoExtension->MiniPortExt);
1586     }
1587 
1588     KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
1589 
1590     if (FdoExtension->Flags & USBPORT_FLAG_HC_POLLING)
1591     {
1592         KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1593         Packet->PollController(FdoExtension->MiniPortExt);
1594         KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
1595     }
1596 
1597     USBPORT_IsrDpcHandler(FdoDevice, FALSE);
1598 
1599     DPRINT_TIMER("USBPORT_TimerDpc: USBPORT_TimeoutAllEndpoints UNIMPLEMENTED.\n");
1600     //USBPORT_TimeoutAllEndpoints(FdoDevice);
1601     DPRINT_TIMER("USBPORT_TimerDpc: USBPORT_CheckIdleEndpoints UNIMPLEMENTED.\n");
1602     //USBPORT_CheckIdleEndpoints(FdoDevice);
1603 
1604     USBPORT_BadRequestFlush(FdoDevice);
1605 
1606     if (FdoExtension->IdleLockCounter > -1 &&
1607         !(TimerFlags & USBPORT_TMFLAG_IDLE_QUEUEITEM_ON))
1608     {
1609         IdleQueueItem = ExAllocatePoolWithTag(NonPagedPool,
1610                                               sizeof(TIMER_WORK_QUEUE_ITEM),
1611                                               USB_PORT_TAG);
1612 
1613         DPRINT("USBPORT_TimerDpc: IdleLockCounter - %x, IdleQueueItem - %p\n",
1614                FdoExtension->IdleLockCounter,
1615                IdleQueueItem);
1616 
1617         if (IdleQueueItem)
1618         {
1619             RtlZeroMemory(IdleQueueItem, sizeof(TIMER_WORK_QUEUE_ITEM));
1620 
1621             IdleQueueItem->WqItem.List.Flink = NULL;
1622             IdleQueueItem->WqItem.WorkerRoutine = USBPORT_DoIdleNotificationCallback;
1623             IdleQueueItem->WqItem.Parameter = IdleQueueItem;
1624 
1625             IdleQueueItem->FdoDevice = FdoDevice;
1626             IdleQueueItem->Context = 0;
1627 
1628             FdoExtension->TimerFlags |= USBPORT_TMFLAG_IDLE_QUEUEITEM_ON;
1629 
1630             ExQueueWorkItem(&IdleQueueItem->WqItem, CriticalWorkQueue);
1631         }
1632     }
1633 
1634 Exit:
1635 
1636     KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, TimerOldIrql);
1637 
1638     if (TimerFlags & USBPORT_TMFLAG_TIMER_QUEUED)
1639     {
1640         DueTime.QuadPart -= FdoExtension->TimerValue * 10000 +
1641                             (KeQueryTimeIncrement() - 1);
1642 
1643         KeSetTimer(&FdoExtension->TimerObject,
1644                    DueTime,
1645                    &FdoExtension->TimerDpc);
1646     }
1647 
1648     DPRINT_TIMER("USBPORT_TimerDpc: exit\n");
1649 }
1650 
1651 BOOLEAN
1652 NTAPI
1653 USBPORT_StartTimer(IN PDEVICE_OBJECT FdoDevice,
1654                    IN ULONG Time)
1655 {
1656     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1657     LARGE_INTEGER DueTime = {{0, 0}};
1658     ULONG TimeIncrement;
1659     BOOLEAN Result;
1660 
1661     DPRINT_TIMER("USBPORT_StartTimer: FdoDevice - %p, Time - %x\n",
1662            FdoDevice,
1663            Time);
1664 
1665     FdoExtension = FdoDevice->DeviceExtension;
1666 
1667     TimeIncrement = KeQueryTimeIncrement();
1668 
1669     FdoExtension->TimerFlags |= USBPORT_TMFLAG_TIMER_QUEUED;
1670     FdoExtension->TimerValue = Time;
1671 
1672     KeInitializeTimer(&FdoExtension->TimerObject);
1673     KeInitializeDpc(&FdoExtension->TimerDpc, USBPORT_TimerDpc, FdoDevice);
1674 
1675     DueTime.QuadPart -= 10000 * Time + (TimeIncrement - 1);
1676 
1677     Result = KeSetTimer(&FdoExtension->TimerObject,
1678                         DueTime,
1679                         &FdoExtension->TimerDpc);
1680 
1681     return Result;
1682 }
1683 
1684 PUSBPORT_COMMON_BUFFER_HEADER
1685 NTAPI
1686 USBPORT_AllocateCommonBuffer(IN PDEVICE_OBJECT FdoDevice,
1687                              IN SIZE_T BufferLength)
1688 {
1689     PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer = NULL;
1690     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1691     PDMA_ADAPTER DmaAdapter;
1692     PDMA_OPERATIONS DmaOperations;
1693     SIZE_T HeaderSize;
1694     ULONG Length = 0;
1695     ULONG LengthPadded;
1696     PHYSICAL_ADDRESS LogicalAddress;
1697     ULONG_PTR BaseVA;
1698     ULONG_PTR StartBufferVA;
1699     ULONG_PTR StartBufferPA;
1700 
1701     DPRINT("USBPORT_AllocateCommonBuffer: FdoDevice - %p, BufferLength - %p\n",
1702            FdoDevice,
1703            BufferLength);
1704 
1705     if (BufferLength == 0)
1706         goto Exit;
1707 
1708     FdoExtension = FdoDevice->DeviceExtension;
1709 
1710     DmaAdapter = FdoExtension->DmaAdapter;
1711     DmaOperations = DmaAdapter->DmaOperations;
1712 
1713     HeaderSize = sizeof(USBPORT_COMMON_BUFFER_HEADER);
1714     Length = ROUND_TO_PAGES(BufferLength + HeaderSize);
1715     LengthPadded = Length - (BufferLength + HeaderSize);
1716 
1717     BaseVA = (ULONG_PTR)DmaOperations->AllocateCommonBuffer(DmaAdapter,
1718                                                             Length,
1719                                                             &LogicalAddress,
1720                                                             TRUE);
1721 
1722     if (!BaseVA)
1723         goto Exit;
1724 
1725     StartBufferVA = BaseVA & ~(PAGE_SIZE - 1);
1726     StartBufferPA = LogicalAddress.LowPart & ~(PAGE_SIZE - 1);
1727 
1728     HeaderBuffer = (PUSBPORT_COMMON_BUFFER_HEADER)(StartBufferVA +
1729                                                    BufferLength +
1730                                                    LengthPadded);
1731 
1732     HeaderBuffer->Length = Length;
1733     HeaderBuffer->BaseVA = BaseVA;
1734     HeaderBuffer->LogicalAddress = LogicalAddress;
1735 
1736     HeaderBuffer->BufferLength = BufferLength + LengthPadded;
1737     HeaderBuffer->VirtualAddress = StartBufferVA;
1738     HeaderBuffer->PhysicalAddress = StartBufferPA;
1739 
1740     RtlZeroMemory((PVOID)StartBufferVA, BufferLength + LengthPadded);
1741 
1742 Exit:
1743     return HeaderBuffer;
1744 }
1745 
1746 VOID
1747 NTAPI
1748 USBPORT_FreeCommonBuffer(IN PDEVICE_OBJECT FdoDevice,
1749                          IN PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer)
1750 {
1751     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1752     PDMA_ADAPTER DmaAdapter;
1753     PDMA_OPERATIONS DmaOperations;
1754 
1755     DPRINT("USBPORT_FreeCommonBuffer: ... \n");
1756 
1757     FdoExtension = FdoDevice->DeviceExtension;
1758 
1759     DmaAdapter = FdoExtension->DmaAdapter;
1760     DmaOperations = DmaAdapter->DmaOperations;
1761 
1762     DmaOperations->FreeCommonBuffer(FdoExtension->DmaAdapter,
1763                                     HeaderBuffer->Length,
1764                                     HeaderBuffer->LogicalAddress,
1765                                     (PVOID)HeaderBuffer->VirtualAddress,
1766                                     TRUE);
1767 }
1768 
1769 PUSBPORT_MINIPORT_INTERFACE
1770 NTAPI
1771 USBPORT_FindMiniPort(IN PDRIVER_OBJECT DriverObject)
1772 {
1773     KIRQL OldIrql;
1774     PLIST_ENTRY List;
1775     PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
1776     BOOLEAN IsFound = FALSE;
1777 
1778     DPRINT("USBPORT_FindMiniPort: ... \n");
1779 
1780     KeAcquireSpinLock(&USBPORT_SpinLock, &OldIrql);
1781 
1782     for (List = USBPORT_MiniPortDrivers.Flink;
1783          List != &USBPORT_MiniPortDrivers;
1784          List = List->Flink)
1785     {
1786         MiniPortInterface = CONTAINING_RECORD(List,
1787                                               USBPORT_MINIPORT_INTERFACE,
1788                                               DriverLink);
1789 
1790         if (MiniPortInterface->DriverObject == DriverObject)
1791         {
1792             DPRINT("USBPORT_FindMiniPort: find MiniPortInterface - %p\n",
1793                    MiniPortInterface);
1794 
1795             IsFound = TRUE;
1796             break;
1797         }
1798     }
1799 
1800     KeReleaseSpinLock(&USBPORT_SpinLock, OldIrql);
1801 
1802     if (IsFound)
1803         return MiniPortInterface;
1804     else
1805         return NULL;
1806 
1807 }
1808 
1809 NTSTATUS
1810 NTAPI
1811 USBPORT_AddDevice(IN PDRIVER_OBJECT DriverObject,
1812                   IN PDEVICE_OBJECT PhysicalDeviceObject)
1813 {
1814     NTSTATUS Status;
1815     PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
1816     ULONG DeviceNumber = 0;
1817     WCHAR CharDeviceName[64];
1818     UNICODE_STRING DeviceName;
1819     PDEVICE_OBJECT DeviceObject;
1820     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1821     PUSBPORT_COMMON_DEVICE_EXTENSION FdoCommonExtension;
1822     PDEVICE_OBJECT LowerDevice;
1823     ULONG Length;
1824 
1825     DPRINT("USBPORT_AddDevice: DriverObject - %p, PhysicalDeviceObject - %p\n",
1826            DriverObject,
1827            PhysicalDeviceObject);
1828 
1829     MiniPortInterface = USBPORT_FindMiniPort(DriverObject);
1830 
1831     if (!MiniPortInterface)
1832     {
1833         DPRINT("USBPORT_AddDevice: USBPORT_FindMiniPort not found MiniPortInterface\n");
1834         return STATUS_UNSUCCESSFUL;
1835     }
1836 
1837     while (TRUE)
1838     {
1839         /* Construct device name */
1840         RtlStringCbPrintfW(CharDeviceName,
1841                            sizeof(CharDeviceName),
1842                            L"\\Device\\USBFDO-%d",
1843                            DeviceNumber);
1844 
1845         RtlInitUnicodeString(&DeviceName, CharDeviceName);
1846 
1847         Length = sizeof(USBPORT_DEVICE_EXTENSION) +
1848                  MiniPortInterface->Packet.MiniPortExtensionSize +
1849                  sizeof(USB2_HC_EXTENSION);
1850 
1851         /* Create device */
1852         Status = IoCreateDevice(DriverObject,
1853                                 Length,
1854                                 &DeviceName,
1855                                 FILE_DEVICE_CONTROLLER,
1856                                 0,
1857                                 FALSE,
1858                                 &DeviceObject);
1859 
1860         /* Check for success */
1861         if (NT_SUCCESS(Status)) break;
1862 
1863         /* Is there a device object with that same name */
1864         if ((Status == STATUS_OBJECT_NAME_EXISTS) ||
1865             (Status == STATUS_OBJECT_NAME_COLLISION))
1866         {
1867             /* Try the next name */
1868             DeviceNumber++;
1869             continue;
1870         }
1871 
1872         /* Bail out on other errors */
1873         if (!NT_SUCCESS(Status))
1874         {
1875             DPRINT1("USBPORT_AddDevice: failed to create %wZ, Status %x\n",
1876                     &DeviceName,
1877                     Status);
1878 
1879             return Status;
1880         }
1881     }
1882 
1883     DPRINT("USBPORT_AddDevice: created device %p <%wZ>, Status %x\n",
1884            DeviceObject,
1885            &DeviceName,
1886            Status);
1887 
1888     FdoExtension = DeviceObject->DeviceExtension;
1889     FdoCommonExtension = &FdoExtension->CommonExtension;
1890 
1891     RtlZeroMemory(FdoExtension, sizeof(USBPORT_DEVICE_EXTENSION));
1892 
1893     FdoCommonExtension->SelfDevice = DeviceObject;
1894     FdoCommonExtension->LowerPdoDevice = PhysicalDeviceObject;
1895     FdoCommonExtension->IsPDO = FALSE;
1896 
1897     LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject,
1898                                               PhysicalDeviceObject);
1899 
1900     FdoCommonExtension->LowerDevice = LowerDevice;
1901 
1902     FdoCommonExtension->DevicePowerState = PowerDeviceD3;
1903 
1904     FdoExtension->MiniPortExt = (PVOID)((ULONG_PTR)FdoExtension +
1905                                         sizeof(USBPORT_DEVICE_EXTENSION));
1906 
1907     if (MiniPortInterface->Packet.MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1908     {
1909         FdoExtension->Usb2Extension =
1910         (PUSB2_HC_EXTENSION)((ULONG_PTR)FdoExtension->MiniPortExt +
1911                              MiniPortInterface->Packet.MiniPortExtensionSize);
1912 
1913         DPRINT("USBPORT_AddDevice: Usb2Extension - %p\n",
1914                FdoExtension->Usb2Extension);
1915 
1916         USB2_InitController(FdoExtension->Usb2Extension);
1917     }
1918     else
1919     {
1920         FdoExtension->Usb2Extension = NULL;
1921     }
1922 
1923     FdoExtension->MiniPortInterface = MiniPortInterface;
1924     FdoExtension->FdoNameNumber = DeviceNumber;
1925 
1926     KeInitializeSemaphore(&FdoExtension->DeviceSemaphore, 1, 1);
1927     KeInitializeSemaphore(&FdoExtension->ControllerSemaphore, 1, 1);
1928 
1929     InitializeListHead(&FdoExtension->EndpointList);
1930     InitializeListHead(&FdoExtension->DoneTransferList);
1931     InitializeListHead(&FdoExtension->WorkerList);
1932     InitializeListHead(&FdoExtension->EpStateChangeList);
1933     InitializeListHead(&FdoExtension->MapTransferList);
1934     InitializeListHead(&FdoExtension->DeviceHandleList);
1935     InitializeListHead(&FdoExtension->IdleIrpList);
1936     InitializeListHead(&FdoExtension->BadRequestList);
1937     InitializeListHead(&FdoExtension->EndpointClosedList);
1938 
1939     DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1940 
1941     return Status;
1942 }
1943 
1944 VOID
1945 NTAPI
1946 USBPORT_Unload(IN PDRIVER_OBJECT DriverObject)
1947 {
1948     PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
1949 
1950     DPRINT1("USBPORT_Unload: FIXME!\n");
1951 
1952     MiniPortInterface = USBPORT_FindMiniPort(DriverObject);
1953 
1954     if (!MiniPortInterface)
1955     {
1956         DPRINT("USBPORT_Unload: CRITICAL ERROR!!! Not found MiniPortInterface\n");
1957         KeBugCheckEx(BUGCODE_USB_DRIVER, 1, 0, 0, 0);
1958     }
1959 
1960     DPRINT1("USBPORT_Unload: UNIMPLEMENTED. FIXME. \n");
1961     //MiniPortInterface->DriverUnload(DriverObject); // Call MiniPort _HCI_Unload
1962 }
1963 
1964 VOID
1965 NTAPI
1966 USBPORT_MiniportCompleteTransfer(IN PVOID MiniPortExtension,
1967                                  IN PVOID MiniPortEndpoint,
1968                                  IN PVOID TransferParameters,
1969                                  IN USBD_STATUS USBDStatus,
1970                                  IN ULONG TransferLength)
1971 {
1972     PUSBPORT_TRANSFER Transfer;
1973     PUSBPORT_TRANSFER ParentTransfer;
1974     PUSBPORT_TRANSFER SplitTransfer;
1975     PLIST_ENTRY SplitHead;
1976     PLIST_ENTRY Entry;
1977     KIRQL OldIrql;
1978 
1979     DPRINT_CORE("USBPORT_MiniportCompleteTransfer: USBDStatus - %x, TransferLength - %x\n",
1980                 USBDStatus,
1981                 TransferLength);
1982 
1983     Transfer = CONTAINING_RECORD(TransferParameters,
1984                                  USBPORT_TRANSFER,
1985                                  TransferParameters);
1986 
1987     Transfer->Flags |= TRANSFER_FLAG_COMPLETED;
1988     Transfer->CompletedTransferLen = TransferLength;
1989 
1990     if (((Transfer->Flags & TRANSFER_FLAG_SPLITED) == 0) ||
1991         TransferLength >= Transfer->TransferParameters.TransferBufferLength)
1992     {
1993         goto Exit;
1994     }
1995 
1996     ParentTransfer = Transfer->ParentTransfer;
1997 
1998     KeAcquireSpinLock(&ParentTransfer->TransferSpinLock, &OldIrql);
1999 
2000     if (IsListEmpty(&ParentTransfer->SplitTransfersList))
2001     {
2002         goto Exit;
2003     }
2004 
2005     SplitHead = &ParentTransfer->SplitTransfersList;
2006     Entry = SplitHead->Flink;
2007 
2008     while (Entry && !IsListEmpty(SplitHead))
2009     {
2010         SplitTransfer = CONTAINING_RECORD(Entry,
2011                                           USBPORT_TRANSFER,
2012                                           SplitLink);
2013 
2014         if (!(SplitTransfer->Flags & TRANSFER_FLAG_SUBMITED))
2015         {
2016             DPRINT1("USBPORT_MiniportCompleteTransfer: SplitTransfer->Flags - %X\n",
2017                     SplitTransfer->Flags);
2018             //Add TRANSFER_FLAG_xxx
2019         }
2020 
2021         Entry = Entry->Flink;
2022     }
2023 
2024     KeReleaseSpinLock(&ParentTransfer->TransferSpinLock, OldIrql);
2025 
2026 Exit:
2027     USBPORT_QueueDoneTransfer(Transfer, USBDStatus);
2028 }
2029 
2030 VOID
2031 NTAPI
2032 USBPORT_AsyncTimerDpc(IN PRKDPC Dpc,
2033                       IN PVOID DeferredContext,
2034                       IN PVOID SystemArgument1,
2035                       IN PVOID SystemArgument2)
2036 {
2037     PDEVICE_OBJECT FdoDevice;
2038     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2039     PUSBPORT_ASYNC_CALLBACK_DATA AsyncCallbackData;
2040 
2041     DPRINT("USBPORT_AsyncTimerDpc: ... \n");
2042 
2043     AsyncCallbackData = DeferredContext;
2044     FdoDevice = AsyncCallbackData->FdoDevice;
2045     FdoExtension = FdoDevice->DeviceExtension;
2046 
2047     (*AsyncCallbackData->CallbackFunction)(FdoExtension->MiniPortExt,
2048                                            &AsyncCallbackData->CallbackContext);
2049 
2050     ExFreePoolWithTag(AsyncCallbackData, USB_PORT_TAG);
2051 }
2052 
2053 ULONG
2054 NTAPI
2055 USBPORT_RequestAsyncCallback(IN PVOID MiniPortExtension,
2056                              IN ULONG TimerValue,
2057                              IN PVOID Buffer,
2058                              IN SIZE_T Length,
2059                              IN ASYNC_TIMER_CALLBACK * Callback)
2060 {
2061     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2062     PDEVICE_OBJECT FdoDevice;
2063     PUSBPORT_ASYNC_CALLBACK_DATA AsyncCallbackData;
2064     LARGE_INTEGER DueTime = {{0, 0}};
2065 
2066     DPRINT("USBPORT_RequestAsyncCallback: ... \n");
2067 
2068     FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension -
2069                                                sizeof(USBPORT_DEVICE_EXTENSION));
2070 
2071     FdoDevice = FdoExtension->CommonExtension.SelfDevice;
2072 
2073     AsyncCallbackData = ExAllocatePoolWithTag(NonPagedPool,
2074                                               sizeof(USBPORT_ASYNC_CALLBACK_DATA) + Length,
2075                                               USB_PORT_TAG);
2076 
2077     if (!AsyncCallbackData)
2078     {
2079         DPRINT1("USBPORT_RequestAsyncCallback: Not allocated AsyncCallbackData!\n");
2080         return 0;
2081     }
2082 
2083     RtlZeroMemory(AsyncCallbackData,
2084                   sizeof(USBPORT_ASYNC_CALLBACK_DATA) + Length);
2085 
2086     if (Length)
2087     {
2088         RtlCopyMemory(&AsyncCallbackData->CallbackContext, Buffer, Length);
2089     }
2090 
2091     AsyncCallbackData->FdoDevice = FdoDevice;
2092     AsyncCallbackData->CallbackFunction = Callback;
2093 
2094     KeInitializeTimer(&AsyncCallbackData->AsyncTimer);
2095 
2096     KeInitializeDpc(&AsyncCallbackData->AsyncTimerDpc,
2097                     USBPORT_AsyncTimerDpc,
2098                     AsyncCallbackData);
2099 
2100     DueTime.QuadPart -= (KeQueryTimeIncrement() - 1) + 10000 * TimerValue;
2101 
2102     KeSetTimer(&AsyncCallbackData->AsyncTimer,
2103                DueTime,
2104                &AsyncCallbackData->AsyncTimerDpc);
2105 
2106     return 0;
2107 }
2108 
2109 PVOID
2110 NTAPI
2111 USBPORT_GetMappedVirtualAddress(IN PVOID PhysicalAddress,
2112                                 IN PVOID MiniPortExtension,
2113                                 IN PVOID MiniPortEndpoint)
2114 {
2115     PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer;
2116     PUSBPORT_ENDPOINT Endpoint;
2117     ULONG Offset;
2118     ULONG_PTR VirtualAddress;
2119 
2120     DPRINT_CORE("USBPORT_GetMappedVirtualAddress ... \n");
2121 
2122     Endpoint = (PUSBPORT_ENDPOINT)((ULONG_PTR)MiniPortEndpoint -
2123                                    sizeof(USBPORT_ENDPOINT));
2124 
2125     if (!Endpoint)
2126     {
2127         ASSERT(FALSE);
2128     }
2129 
2130     HeaderBuffer = Endpoint->HeaderBuffer;
2131 
2132     Offset = (ULONG_PTR)PhysicalAddress - HeaderBuffer->PhysicalAddress;
2133     VirtualAddress = HeaderBuffer->VirtualAddress + Offset;
2134 
2135     return (PVOID)VirtualAddress;
2136 }
2137 
2138 ULONG
2139 NTAPI
2140 USBPORT_InvalidateEndpoint(IN PVOID MiniPortExtension,
2141                            IN PVOID MiniPortEndpoint)
2142 {
2143     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2144     PDEVICE_OBJECT FdoDevice;
2145     PUSBPORT_ENDPOINT Endpoint;
2146 
2147     DPRINT_CORE("USBPORT_InvalidateEndpoint: ... \n");
2148 
2149     FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension -
2150                                                sizeof(USBPORT_DEVICE_EXTENSION));
2151 
2152     FdoDevice = FdoExtension->CommonExtension.SelfDevice;
2153 
2154     if (!MiniPortEndpoint)
2155     {
2156         USBPORT_InvalidateEndpointHandler(FdoDevice,
2157                                           NULL,
2158                                           INVALIDATE_ENDPOINT_ONLY);
2159         return 0;
2160     }
2161 
2162     Endpoint = (PUSBPORT_ENDPOINT)((ULONG_PTR)MiniPortEndpoint -
2163                                    sizeof(USBPORT_ENDPOINT));
2164 
2165     USBPORT_InvalidateEndpointHandler(FdoDevice,
2166                                       Endpoint,
2167                                       INVALIDATE_ENDPOINT_ONLY);
2168 
2169     return 0;
2170 }
2171 
2172 VOID
2173 NTAPI
2174 USBPORT_CompleteTransfer(IN PURB Urb,
2175                          IN USBD_STATUS TransferStatus)
2176 {
2177     struct _URB_CONTROL_TRANSFER *UrbTransfer;
2178     PUSBPORT_TRANSFER Transfer;
2179     NTSTATUS Status;
2180     PIRP Irp;
2181     KIRQL OldIrql;
2182     PRKEVENT Event;
2183     BOOLEAN WriteToDevice;
2184     BOOLEAN IsFlushSuccess;
2185     PMDL Mdl;
2186     ULONG_PTR CurrentVa;
2187     SIZE_T TransferLength;
2188     PUSBPORT_ENDPOINT Endpoint;
2189     PDEVICE_OBJECT FdoDevice;
2190     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2191     PDMA_OPERATIONS DmaOperations;
2192 
2193     DPRINT("USBPORT_CompleteTransfer: Urb - %p, TransferStatus - %X\n",
2194            Urb,
2195            TransferStatus);
2196 
2197     UrbTransfer = &Urb->UrbControlTransfer;
2198     Transfer = UrbTransfer->hca.Reserved8[0];
2199 
2200     Transfer->USBDStatus = TransferStatus;
2201     Status = USBPORT_USBDStatusToNtStatus(Urb, TransferStatus);
2202 
2203     UrbTransfer->TransferBufferLength = Transfer->CompletedTransferLen;
2204 
2205     if (Transfer->Flags & TRANSFER_FLAG_DMA_MAPPED)
2206     {
2207         Endpoint = Transfer->Endpoint;
2208         FdoDevice = Endpoint->FdoDevice;
2209         FdoExtension = FdoDevice->DeviceExtension;
2210         DmaOperations = FdoExtension->DmaAdapter->DmaOperations;
2211 
2212         WriteToDevice = Transfer->Direction == USBPORT_DMA_DIRECTION_TO_DEVICE;
2213         Mdl = UrbTransfer->TransferBufferMDL;
2214         CurrentVa = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
2215         TransferLength = UrbTransfer->TransferBufferLength;
2216 
2217         IsFlushSuccess = DmaOperations->FlushAdapterBuffers(FdoExtension->DmaAdapter,
2218                                                             Mdl,
2219                                                             Transfer->MapRegisterBase,
2220                                                             (PVOID)CurrentVa,
2221                                                             TransferLength,
2222                                                             WriteToDevice);
2223 
2224         if (!IsFlushSuccess)
2225         {
2226             DPRINT("USBPORT_CompleteTransfer: no FlushAdapterBuffers !!!\n");
2227             ASSERT(FALSE);
2228         }
2229 
2230         KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2231 
2232         DmaOperations->FreeMapRegisters(FdoExtension->DmaAdapter,
2233                                         Transfer->MapRegisterBase,
2234                                         Transfer->NumberOfMapRegisters);
2235 
2236         KeLowerIrql(OldIrql);
2237     }
2238 
2239     if (Urb->UrbHeader.UsbdFlags & USBD_FLAG_ALLOCATED_MDL)
2240     {
2241         IoFreeMdl(Transfer->TransferBufferMDL);
2242         Urb->UrbHeader.UsbdFlags |= ~USBD_FLAG_ALLOCATED_MDL;
2243     }
2244 
2245     Urb->UrbControlTransfer.hca.Reserved8[0] = NULL;
2246     Urb->UrbHeader.UsbdFlags |= ~USBD_FLAG_ALLOCATED_TRANSFER;
2247 
2248     Irp = Transfer->Irp;
2249 
2250     if (Irp)
2251     {
2252         if (!NT_SUCCESS(Status))
2253         {
2254             //DbgBreakPoint();
2255             DPRINT1("USBPORT_CompleteTransfer: Irp - %p complete with Status - %lx\n",
2256                     Irp,
2257                     Status);
2258 
2259             USBPORT_DumpingURB(Urb);
2260         }
2261 
2262         Irp->IoStatus.Status = Status;
2263         Irp->IoStatus.Information = 0;
2264 
2265         KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2266         IoCompleteRequest(Irp, IO_NO_INCREMENT);
2267         KeLowerIrql(OldIrql);
2268     }
2269 
2270     Event = Transfer->Event;
2271 
2272     if (Event)
2273     {
2274         KeSetEvent(Event, EVENT_INCREMENT, FALSE);
2275     }
2276 
2277     ExFreePoolWithTag(Transfer, USB_PORT_TAG);
2278 
2279     DPRINT_CORE("USBPORT_CompleteTransfer: exit\n");
2280 }
2281 
2282 IO_ALLOCATION_ACTION
2283 NTAPI
2284 USBPORT_MapTransfer(IN PDEVICE_OBJECT FdoDevice,
2285                     IN PIRP Irp,
2286                     IN PVOID MapRegisterBase,
2287                     IN PVOID Context)
2288 {
2289     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2290     PDMA_ADAPTER DmaAdapter;
2291     PUSBPORT_TRANSFER Transfer;
2292     PURB Urb;
2293     PUSBPORT_ENDPOINT Endpoint;
2294     PMDL Mdl;
2295     ULONG_PTR CurrentVa;
2296     PUSBPORT_SCATTER_GATHER_LIST sgList;
2297     SIZE_T CurrentLength;
2298     ULONG ix;
2299     BOOLEAN WriteToDevice;
2300     PHYSICAL_ADDRESS PhAddr = {{0, 0}};
2301     PHYSICAL_ADDRESS PhAddress = {{0, 0}};
2302     SIZE_T TransferLength;
2303     SIZE_T SgCurrentLength;
2304     SIZE_T ElementLength;
2305     PUSBPORT_DEVICE_HANDLE DeviceHandle;
2306     PDMA_OPERATIONS DmaOperations;
2307     USBD_STATUS USBDStatus;
2308     LIST_ENTRY List;
2309     PUSBPORT_TRANSFER transfer;
2310 
2311     DPRINT_CORE("USBPORT_MapTransfer: ... \n");
2312 
2313     FdoExtension = FdoDevice->DeviceExtension;
2314     DmaAdapter = FdoExtension->DmaAdapter;
2315     DmaOperations = DmaAdapter->DmaOperations;
2316 
2317     Transfer = Context;
2318 
2319     Urb = Transfer->Urb;
2320     Endpoint = Transfer->Endpoint;
2321     TransferLength = Transfer->TransferParameters.TransferBufferLength;
2322 
2323     Mdl = Urb->UrbControlTransfer.TransferBufferMDL;
2324     CurrentVa = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
2325 
2326     sgList = &Transfer->SgList;
2327 
2328     sgList->Flags = 0;
2329     sgList->CurrentVa = CurrentVa;
2330     sgList->MappedSystemVa = MmGetSystemAddressForMdlSafe(Mdl,
2331                                                           NormalPagePriority);
2332     Transfer->MapRegisterBase = MapRegisterBase;
2333 
2334     ix = 0;
2335     CurrentLength = 0;
2336 
2337     do
2338     {
2339         WriteToDevice = Transfer->Direction == USBPORT_DMA_DIRECTION_TO_DEVICE;
2340         ASSERT(Transfer->Direction != 0);
2341 
2342         PhAddress = DmaOperations->MapTransfer(DmaAdapter,
2343                                                Mdl,
2344                                                MapRegisterBase,
2345                                                (PVOID)CurrentVa,
2346                                                &TransferLength,
2347                                                WriteToDevice);
2348 
2349         DPRINT_CORE("USBPORT_MapTransfer: PhAddress.LowPart - %p, PhAddress.HighPart - %x, TransferLength - %x\n",
2350                PhAddress.LowPart,
2351                PhAddress.HighPart,
2352                TransferLength);
2353 
2354         PhAddress.HighPart = 0;
2355         SgCurrentLength = TransferLength;
2356 
2357         do
2358         {
2359             ElementLength = PAGE_SIZE - (PhAddress.LowPart & (PAGE_SIZE - 1));
2360 
2361             if (ElementLength > SgCurrentLength)
2362                 ElementLength = SgCurrentLength;
2363 
2364             DPRINT_CORE("USBPORT_MapTransfer: PhAddress.LowPart - %p, HighPart - %x, ElementLength - %x\n",
2365                    PhAddress.LowPart,
2366                    PhAddress.HighPart,
2367                    ElementLength);
2368 
2369             sgList->SgElement[ix].SgPhysicalAddress = PhAddress;
2370             sgList->SgElement[ix].SgTransferLength = ElementLength;
2371             sgList->SgElement[ix].SgOffset = CurrentLength +
2372                                              (TransferLength - SgCurrentLength);
2373 
2374             PhAddress.LowPart += ElementLength;
2375             SgCurrentLength -= ElementLength;
2376 
2377             ++ix;
2378         }
2379         while (SgCurrentLength);
2380 
2381         if (PhAddr.QuadPart == PhAddress.QuadPart)
2382         {
2383             DPRINT1("USBPORT_MapTransfer: PhAddr == PhAddress\n");
2384             ASSERT(FALSE);
2385         }
2386 
2387         PhAddr = PhAddress;
2388 
2389         CurrentLength += TransferLength;
2390         CurrentVa += TransferLength;
2391 
2392         TransferLength = Transfer->TransferParameters.TransferBufferLength -
2393                          CurrentLength;
2394     }
2395     while (CurrentLength != Transfer->TransferParameters.TransferBufferLength);
2396 
2397     sgList->SgElementCount = ix;
2398 
2399     if (Endpoint->EndpointProperties.DeviceSpeed == UsbHighSpeed)
2400     {
2401         Transfer->Flags |= TRANSFER_FLAG_HIGH_SPEED;
2402     }
2403 
2404     Transfer->Flags |= TRANSFER_FLAG_DMA_MAPPED;
2405 
2406     if ((Transfer->Flags & TRANSFER_FLAG_ISO) == 0)
2407     {
2408         KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
2409                           &Endpoint->EndpointOldIrql);
2410 
2411         USBPORT_SplitTransfer(FdoDevice, Endpoint, Transfer, &List);
2412 
2413         while (!IsListEmpty(&List))
2414         {
2415             transfer = CONTAINING_RECORD(List.Flink,
2416                                          USBPORT_TRANSFER,
2417                                          TransferLink);
2418 
2419             RemoveHeadList(&List);
2420             InsertTailList(&Endpoint->TransferList, &transfer->TransferLink);
2421         }
2422 
2423         KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
2424                           Endpoint->EndpointOldIrql);
2425     }
2426     else
2427     {
2428         USBDStatus = USBPORT_InitializeIsoTransfer(FdoDevice,
2429                                                    &Urb->UrbIsochronousTransfer,
2430                                                    Transfer);
2431 
2432         if (USBDStatus != USBD_STATUS_SUCCESS)
2433         {
2434             KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
2435                               &Endpoint->EndpointOldIrql);
2436 
2437             USBPORT_QueueDoneTransfer(Transfer, USBDStatus);
2438 
2439             KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
2440                               Endpoint->EndpointOldIrql);
2441         }
2442     }
2443 
2444     DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
2445     InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
2446 
2447     if (USBPORT_EndpointWorker(Endpoint, 0))
2448     {
2449         USBPORT_InvalidateEndpointHandler(FdoDevice,
2450                                           Endpoint,
2451                                           INVALIDATE_ENDPOINT_WORKER_THREAD);
2452     }
2453 
2454     return DeallocateObjectKeepRegisters;
2455 }
2456 
2457 VOID
2458 NTAPI
2459 USBPORT_FlushMapTransfers(IN PDEVICE_OBJECT FdoDevice)
2460 {
2461     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2462     PLIST_ENTRY MapTransferList;
2463     PUSBPORT_TRANSFER Transfer;
2464     ULONG NumMapRegisters;
2465     PMDL Mdl;
2466     SIZE_T TransferBufferLength;
2467     ULONG_PTR VirtualAddr;
2468     KIRQL OldIrql;
2469     NTSTATUS Status;
2470     PDMA_OPERATIONS DmaOperations;
2471 
2472     DPRINT_CORE("USBPORT_FlushMapTransfers: ... \n");
2473 
2474     FdoExtension = FdoDevice->DeviceExtension;
2475     DmaOperations = FdoExtension->DmaAdapter->DmaOperations;
2476 
2477     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2478 
2479     while (TRUE)
2480     {
2481         MapTransferList = &FdoExtension->MapTransferList;
2482 
2483         if (IsListEmpty(&FdoExtension->MapTransferList))
2484         {
2485             KeLowerIrql(OldIrql);
2486             return;
2487         }
2488 
2489         Transfer = CONTAINING_RECORD(MapTransferList->Flink,
2490                                      USBPORT_TRANSFER,
2491                                      TransferLink);
2492 
2493         RemoveHeadList(MapTransferList);
2494 
2495         Mdl = Transfer->Urb->UrbControlTransfer.TransferBufferMDL;
2496         TransferBufferLength = Transfer->TransferParameters.TransferBufferLength;
2497         VirtualAddr = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
2498 
2499         NumMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddr,
2500                                                          TransferBufferLength);
2501 
2502         Transfer->NumberOfMapRegisters = NumMapRegisters;
2503 
2504         Status = DmaOperations->AllocateAdapterChannel(FdoExtension->DmaAdapter,
2505                                                        FdoDevice,
2506                                                        NumMapRegisters,
2507                                                        USBPORT_MapTransfer,
2508                                                        Transfer);
2509 
2510         if (!NT_SUCCESS(Status))
2511             ASSERT(FALSE);
2512     }
2513 
2514     KeLowerIrql(OldIrql);
2515 }
2516 
2517 USBD_STATUS
2518 NTAPI
2519 USBPORT_AllocateTransfer(IN PDEVICE_OBJECT FdoDevice,
2520                          IN PURB Urb,
2521                          IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
2522                          IN PIRP Irp,
2523                          IN PRKEVENT Event)
2524 {
2525     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2526     SIZE_T TransferLength;
2527     PMDL Mdl;
2528     ULONG_PTR VirtualAddr;
2529     ULONG PagesNeed = 0;
2530     SIZE_T PortTransferLength;
2531     SIZE_T FullTransferLength;
2532     PUSBPORT_TRANSFER Transfer;
2533     PUSBPORT_PIPE_HANDLE PipeHandle;
2534     USBD_STATUS USBDStatus;
2535     SIZE_T IsoBlockLen = 0;
2536 
2537     DPRINT_CORE("USBPORT_AllocateTransfer: FdoDevice - %p, Urb - %p, DeviceHandle - %p, Irp - %p, Event - %p\n",
2538            FdoDevice,
2539            Urb,
2540            DeviceHandle,
2541            Irp,
2542            Event);
2543 
2544     FdoExtension = FdoDevice->DeviceExtension;
2545 
2546     TransferLength = Urb->UrbControlTransfer.TransferBufferLength;
2547     PipeHandle = Urb->UrbControlTransfer.PipeHandle;
2548 
2549     if (TransferLength)
2550     {
2551         Mdl = Urb->UrbControlTransfer.TransferBufferMDL;
2552         VirtualAddr = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
2553 
2554         PagesNeed = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddr,
2555                                                    TransferLength);
2556         if (PagesNeed > 0)
2557         {
2558             PagesNeed--;
2559         }
2560     }
2561 
2562     if (Urb->UrbHeader.Function == URB_FUNCTION_ISOCH_TRANSFER)
2563     {
2564         DPRINT1("USBPORT_AllocateTransfer: ISOCH_TRANSFER UNIMPLEMENTED. FIXME\n");
2565 
2566         //IsoBlockLen = sizeof(USBPORT_ISO_BLOCK) +
2567         //              Urb->UrbIsochronousTransfer.NumberOfPackets *
2568         //              sizeof(USBPORT_ISO_BLOCK_PACKET);
2569     }
2570 
2571     PortTransferLength = sizeof(USBPORT_TRANSFER) +
2572                          PagesNeed * sizeof(USBPORT_SCATTER_GATHER_ELEMENT) +
2573                          IsoBlockLen;
2574 
2575     FullTransferLength = PortTransferLength +
2576                          FdoExtension->MiniPortInterface->Packet.MiniPortTransferSize;
2577 
2578     Transfer = ExAllocatePoolWithTag(NonPagedPool,
2579                                      FullTransferLength,
2580                                      USB_PORT_TAG);
2581 
2582     if (!Transfer)
2583     {
2584         DPRINT1("USBPORT_AllocateTransfer: Transfer not allocated!\n");
2585         return USBD_STATUS_INSUFFICIENT_RESOURCES;
2586     }
2587 
2588     RtlZeroMemory(Transfer, FullTransferLength);
2589 
2590     Transfer->Irp = Irp;
2591     Transfer->Urb = Urb;
2592     Transfer->Endpoint = PipeHandle->Endpoint;
2593     Transfer->Event = Event;
2594     Transfer->PortTransferLength = PortTransferLength;
2595     Transfer->FullTransferLength = FullTransferLength;
2596     Transfer->IsoBlockPtr = NULL;
2597     Transfer->Period = 0;
2598     Transfer->ParentTransfer = Transfer;
2599 
2600     if (IsoBlockLen)
2601     {
2602         Transfer->IsoBlockPtr = (PVOID)((ULONG_PTR)Transfer +
2603                                  PortTransferLength - IsoBlockLen);
2604 
2605         Transfer->Period = PipeHandle->Endpoint->EndpointProperties.Period;
2606         Transfer->Flags |= TRANSFER_FLAG_ISO;
2607     }
2608 
2609     Transfer->MiniportTransfer = (PVOID)((ULONG_PTR)Transfer +
2610                                                     PortTransferLength);
2611 
2612     KeInitializeSpinLock(&Transfer->TransferSpinLock);
2613 
2614     Urb->UrbControlTransfer.hca.Reserved8[0] = Transfer;
2615     Urb->UrbHeader.UsbdFlags |= USBD_FLAG_ALLOCATED_TRANSFER;
2616 
2617     USBDStatus = USBD_STATUS_SUCCESS;
2618 
2619     DPRINT_CORE("USBPORT_AllocateTransfer: return USBDStatus - %x\n",
2620                 USBDStatus);
2621 
2622     return USBDStatus;
2623 }
2624 
2625 NTSTATUS
2626 NTAPI
2627 USBPORT_Dispatch(IN PDEVICE_OBJECT DeviceObject,
2628                  IN PIRP Irp)
2629 {
2630     PUSBPORT_COMMON_DEVICE_EXTENSION DeviceExtension;
2631     PIO_STACK_LOCATION IoStack;
2632     NTSTATUS Status = STATUS_SUCCESS;
2633 
2634     DeviceExtension = DeviceObject->DeviceExtension;
2635     IoStack = IoGetCurrentIrpStackLocation(Irp);
2636 
2637     if (DeviceExtension->PnpStateFlags & USBPORT_PNP_STATE_FAILED)
2638     {
2639         DPRINT1("USBPORT_Dispatch: USBPORT_PNP_STATE_FAILED\n");
2640         DbgBreakPoint();
2641     }
2642 
2643     switch (IoStack->MajorFunction)
2644     {
2645         case IRP_MJ_DEVICE_CONTROL:
2646             if (DeviceExtension->IsPDO)
2647             {
2648                 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_DEVICE_CONTROL. Major - %d, Minor - %d\n",
2649                        IoStack->MajorFunction,
2650                        IoStack->MinorFunction);
2651 
2652                 Status = USBPORT_PdoDeviceControl(DeviceObject, Irp);
2653             }
2654             else
2655             {
2656                 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_DEVICE_CONTROL. Major - %d, Minor - %d\n",
2657                        IoStack->MajorFunction,
2658                        IoStack->MinorFunction);
2659 
2660                 Status = USBPORT_FdoDeviceControl(DeviceObject, Irp);
2661             }
2662 
2663             break;
2664 
2665         case IRP_MJ_INTERNAL_DEVICE_CONTROL:
2666             if (DeviceExtension->IsPDO)
2667             {
2668                 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_INTERNAL_DEVICE_CONTROL. Major - %d, Minor - %d\n",
2669                        IoStack->MajorFunction,
2670                        IoStack->MinorFunction);
2671 
2672                 Status = USBPORT_PdoInternalDeviceControl(DeviceObject, Irp);
2673             }
2674             else
2675             {
2676                 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_INTERNAL_DEVICE_CONTROL. Major - %d, Minor - %d\n",
2677                        IoStack->MajorFunction,
2678                        IoStack->MinorFunction);
2679 
2680                 Status = USBPORT_FdoInternalDeviceControl(DeviceObject, Irp);
2681             }
2682 
2683             break;
2684 
2685         case IRP_MJ_POWER:
2686             if (DeviceExtension->IsPDO)
2687             {
2688                 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_POWER. Major - %d, Minor - %d\n",
2689                        IoStack->MajorFunction,
2690                        IoStack->MinorFunction);
2691 
2692                 Status = USBPORT_PdoPower(DeviceObject, Irp);
2693             }
2694             else
2695             {
2696                 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_POWER. Major - %d, Minor - %d\n",
2697                        IoStack->MajorFunction,
2698                        IoStack->MinorFunction);
2699 
2700                 Status = USBPORT_FdoPower(DeviceObject, Irp);
2701             }
2702 
2703             break;
2704 
2705         case IRP_MJ_SYSTEM_CONTROL:
2706             if (DeviceExtension->IsPDO)
2707             {
2708                 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_SYSTEM_CONTROL. Major - %d, Minor - %d\n",
2709                        IoStack->MajorFunction,
2710                        IoStack->MinorFunction);
2711 
2712                 Irp->IoStatus.Status = Status;
2713                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2714             }
2715             else
2716             {
2717                 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_SYSTEM_CONTROL. Major - %d, Minor - %d\n",
2718                        IoStack->MajorFunction,
2719                        IoStack->MinorFunction);
2720 
2721                 IoSkipCurrentIrpStackLocation(Irp);
2722                 Status = IoCallDriver(DeviceExtension->LowerDevice, Irp);
2723             }
2724 
2725             break;
2726 
2727         case IRP_MJ_PNP:
2728             if (DeviceExtension->IsPDO)
2729             {
2730                 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_PNP. Major - %d, Minor - %d\n",
2731                        IoStack->MajorFunction,
2732                        IoStack->MinorFunction);
2733 
2734                 Status = USBPORT_PdoPnP(DeviceObject, Irp);
2735             }
2736             else
2737             {
2738                 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_PNP. Major - %d, Minor - %d\n",
2739                        IoStack->MajorFunction,
2740                        IoStack->MinorFunction);
2741 
2742                 Status = USBPORT_FdoPnP(DeviceObject, Irp);
2743             }
2744 
2745             break;
2746 
2747         case IRP_MJ_CREATE:
2748         case IRP_MJ_CLOSE:
2749             DPRINT("USBPORT_Dispatch: IRP_MJ_CREATE | IRP_MJ_CLOSE\n");
2750             Irp->IoStatus.Status = Status;
2751             IoCompleteRequest(Irp, IO_NO_INCREMENT);
2752             break;
2753 
2754         default:
2755             if (DeviceExtension->IsPDO)
2756             {
2757                 DPRINT("USBPORT_Dispatch: PDO unhandled IRP_MJ_???. Major - %d, Minor - %d\n",
2758                        IoStack->MajorFunction,
2759                        IoStack->MinorFunction);
2760             }
2761             else
2762             {
2763                 DPRINT("USBPORT_Dispatch: FDO unhandled IRP_MJ_???. Major - %d, Minor - %d\n",
2764                        IoStack->MajorFunction,
2765                        IoStack->MinorFunction);
2766             }
2767 
2768             Status = STATUS_INVALID_DEVICE_REQUEST;
2769             Irp->IoStatus.Status = Status;
2770             IoCompleteRequest(Irp, IO_NO_INCREMENT);
2771             break;
2772     }
2773 
2774     DPRINT("USBPORT_Dispatch: Status - %x\n", Status);
2775     return Status;
2776 }
2777 
2778 ULONG
2779 NTAPI
2780 USBPORT_GetHciMn(VOID)
2781 {
2782     return USBPORT_HCI_MN;
2783 }
2784 
2785 NTSTATUS
2786 NTAPI
2787 USBPORT_RegisterUSBPortDriver(IN PDRIVER_OBJECT DriverObject,
2788                               IN ULONG Version,
2789                               IN PUSBPORT_REGISTRATION_PACKET RegPacket)
2790 {
2791     PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
2792 
2793     DPRINT("USBPORT_RegisterUSBPortDriver: DriverObject - %p, Version - %p, RegPacket - %p\n",
2794            DriverObject,
2795            Version,
2796            RegPacket);
2797 
2798     DPRINT("USBPORT_RegisterUSBPortDriver: sizeof(USBPORT_MINIPORT_INTERFACE) - %x\n",
2799            sizeof(USBPORT_MINIPORT_INTERFACE));
2800 
2801     DPRINT("USBPORT_RegisterUSBPortDriver: sizeof(USBPORT_DEVICE_EXTENSION)   - %x\n",
2802            sizeof(USBPORT_DEVICE_EXTENSION));
2803 
2804     if (Version < USB10_MINIPORT_INTERFACE_VERSION)
2805     {
2806         return STATUS_UNSUCCESSFUL;
2807     }
2808 
2809     if (!USBPORT_Initialized)
2810     {
2811         InitializeListHead(&USBPORT_MiniPortDrivers);
2812         InitializeListHead(&USBPORT_USB1FdoList);
2813         InitializeListHead(&USBPORT_USB2FdoList);
2814 
2815         KeInitializeSpinLock(&USBPORT_SpinLock);
2816         USBPORT_Initialized = TRUE;
2817     }
2818 
2819     MiniPortInterface = ExAllocatePoolWithTag(NonPagedPool,
2820                                               sizeof(USBPORT_MINIPORT_INTERFACE),
2821                                               USB_PORT_TAG);
2822     if (!MiniPortInterface)
2823     {
2824         return STATUS_INSUFFICIENT_RESOURCES;
2825     }
2826 
2827     RtlZeroMemory(MiniPortInterface, sizeof(USBPORT_MINIPORT_INTERFACE));
2828 
2829     MiniPortInterface->DriverObject = DriverObject;
2830     MiniPortInterface->DriverUnload = DriverObject->DriverUnload;
2831     MiniPortInterface->Version = Version;
2832 
2833     ExInterlockedInsertTailList(&USBPORT_MiniPortDrivers,
2834                                 &MiniPortInterface->DriverLink,
2835                                 &USBPORT_SpinLock);
2836 
2837     DriverObject->DriverExtension->AddDevice = USBPORT_AddDevice;
2838     DriverObject->DriverUnload = USBPORT_Unload;
2839 
2840     DriverObject->MajorFunction[IRP_MJ_CREATE] = USBPORT_Dispatch;
2841     DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBPORT_Dispatch;
2842     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBPORT_Dispatch;
2843     DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBPORT_Dispatch;
2844     DriverObject->MajorFunction[IRP_MJ_PNP] = USBPORT_Dispatch;
2845     DriverObject->MajorFunction[IRP_MJ_POWER] = USBPORT_Dispatch;
2846     DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USBPORT_Dispatch;
2847 
2848     RegPacket->UsbPortDbgPrint = USBPORT_DbgPrint;
2849     RegPacket->UsbPortTestDebugBreak = USBPORT_TestDebugBreak;
2850     RegPacket->UsbPortAssertFailure = USBPORT_AssertFailure;
2851     RegPacket->UsbPortGetMiniportRegistryKeyValue = USBPORT_GetMiniportRegistryKeyValue;
2852     RegPacket->UsbPortInvalidateRootHub = USBPORT_InvalidateRootHub;
2853     RegPacket->UsbPortInvalidateEndpoint = USBPORT_InvalidateEndpoint;
2854     RegPacket->UsbPortCompleteTransfer = USBPORT_MiniportCompleteTransfer;
2855     RegPacket->UsbPortCompleteIsoTransfer = USBPORT_CompleteIsoTransfer;
2856     RegPacket->UsbPortLogEntry = USBPORT_LogEntry;
2857     RegPacket->UsbPortGetMappedVirtualAddress = USBPORT_GetMappedVirtualAddress;
2858     RegPacket->UsbPortRequestAsyncCallback = USBPORT_RequestAsyncCallback;
2859     RegPacket->UsbPortReadWriteConfigSpace = USBPORT_ReadWriteConfigSpace;
2860     RegPacket->UsbPortWait = USBPORT_Wait;
2861     RegPacket->UsbPortInvalidateController = USBPORT_InvalidateController;
2862     RegPacket->UsbPortBugCheck = USBPORT_BugCheck;
2863     RegPacket->UsbPortNotifyDoubleBuffer = USBPORT_NotifyDoubleBuffer;
2864 
2865     RtlCopyMemory(&MiniPortInterface->Packet,
2866                   RegPacket,
2867                   sizeof(USBPORT_REGISTRATION_PACKET));
2868 
2869     return STATUS_SUCCESS;
2870 }
2871 
2872 NTSTATUS
2873 NTAPI
2874 DriverEntry(IN PDRIVER_OBJECT DriverObject,
2875             IN PUNICODE_STRING RegistryPath)
2876 {
2877     return STATUS_SUCCESS;
2878 }
2879