xref: /reactos/drivers/usb/usbport/usbport.c (revision e5813c46)
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 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         ASSERT(MiniPortInterface->Packet.MiniPortExtensionSize <=
1848                MAXULONG - sizeof(USBPORT_DEVICE_EXTENSION) - sizeof(USB2_HC_EXTENSION));
1849         Length = (ULONG)(sizeof(USBPORT_DEVICE_EXTENSION) +
1850                          MiniPortInterface->Packet.MiniPortExtensionSize +
1851                          sizeof(USB2_HC_EXTENSION));
1852 
1853         /* Create device */
1854         Status = IoCreateDevice(DriverObject,
1855                                 Length,
1856                                 &DeviceName,
1857                                 FILE_DEVICE_CONTROLLER,
1858                                 0,
1859                                 FALSE,
1860                                 &DeviceObject);
1861 
1862         /* Check for success */
1863         if (NT_SUCCESS(Status)) break;
1864 
1865         /* Is there a device object with that same name */
1866         if ((Status == STATUS_OBJECT_NAME_EXISTS) ||
1867             (Status == STATUS_OBJECT_NAME_COLLISION))
1868         {
1869             /* Try the next name */
1870             DeviceNumber++;
1871             continue;
1872         }
1873 
1874         /* Bail out on other errors */
1875         if (!NT_SUCCESS(Status))
1876         {
1877             DPRINT1("USBPORT_AddDevice: failed to create %wZ, Status %x\n",
1878                     &DeviceName,
1879                     Status);
1880 
1881             return Status;
1882         }
1883     }
1884 
1885     DPRINT("USBPORT_AddDevice: created device %p <%wZ>, Status %x\n",
1886            DeviceObject,
1887            &DeviceName,
1888            Status);
1889 
1890     FdoExtension = DeviceObject->DeviceExtension;
1891     FdoCommonExtension = &FdoExtension->CommonExtension;
1892 
1893     RtlZeroMemory(FdoExtension, sizeof(USBPORT_DEVICE_EXTENSION));
1894 
1895     FdoCommonExtension->SelfDevice = DeviceObject;
1896     FdoCommonExtension->LowerPdoDevice = PhysicalDeviceObject;
1897     FdoCommonExtension->IsPDO = FALSE;
1898 
1899     LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject,
1900                                               PhysicalDeviceObject);
1901 
1902     FdoCommonExtension->LowerDevice = LowerDevice;
1903 
1904     FdoCommonExtension->DevicePowerState = PowerDeviceD3;
1905 
1906     FdoExtension->MiniPortExt = (PVOID)((ULONG_PTR)FdoExtension +
1907                                         sizeof(USBPORT_DEVICE_EXTENSION));
1908 
1909     if (MiniPortInterface->Packet.MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1910     {
1911         FdoExtension->Usb2Extension =
1912         (PUSB2_HC_EXTENSION)((ULONG_PTR)FdoExtension->MiniPortExt +
1913                              MiniPortInterface->Packet.MiniPortExtensionSize);
1914 
1915         DPRINT("USBPORT_AddDevice: Usb2Extension - %p\n",
1916                FdoExtension->Usb2Extension);
1917 
1918         USB2_InitController(FdoExtension->Usb2Extension);
1919     }
1920     else
1921     {
1922         FdoExtension->Usb2Extension = NULL;
1923     }
1924 
1925     FdoExtension->MiniPortInterface = MiniPortInterface;
1926     FdoExtension->FdoNameNumber = DeviceNumber;
1927 
1928     KeInitializeSemaphore(&FdoExtension->DeviceSemaphore, 1, 1);
1929     KeInitializeSemaphore(&FdoExtension->ControllerSemaphore, 1, 1);
1930 
1931     InitializeListHead(&FdoExtension->EndpointList);
1932     InitializeListHead(&FdoExtension->DoneTransferList);
1933     InitializeListHead(&FdoExtension->WorkerList);
1934     InitializeListHead(&FdoExtension->EpStateChangeList);
1935     InitializeListHead(&FdoExtension->MapTransferList);
1936     InitializeListHead(&FdoExtension->DeviceHandleList);
1937     InitializeListHead(&FdoExtension->IdleIrpList);
1938     InitializeListHead(&FdoExtension->BadRequestList);
1939     InitializeListHead(&FdoExtension->EndpointClosedList);
1940 
1941     DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1942 
1943     return Status;
1944 }
1945 
1946 VOID
1947 NTAPI
1948 USBPORT_Unload(IN PDRIVER_OBJECT DriverObject)
1949 {
1950     PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
1951 
1952     DPRINT1("USBPORT_Unload: FIXME!\n");
1953 
1954     MiniPortInterface = USBPORT_FindMiniPort(DriverObject);
1955 
1956     if (!MiniPortInterface)
1957     {
1958         DPRINT("USBPORT_Unload: CRITICAL ERROR!!! Not found MiniPortInterface\n");
1959         KeBugCheckEx(BUGCODE_USB_DRIVER, 1, 0, 0, 0);
1960     }
1961 
1962     DPRINT1("USBPORT_Unload: UNIMPLEMENTED. FIXME. \n");
1963     //MiniPortInterface->DriverUnload(DriverObject); // Call MiniPort _HCI_Unload
1964 }
1965 
1966 VOID
1967 NTAPI
1968 USBPORT_MiniportCompleteTransfer(IN PVOID MiniPortExtension,
1969                                  IN PVOID MiniPortEndpoint,
1970                                  IN PVOID TransferParameters,
1971                                  IN USBD_STATUS USBDStatus,
1972                                  IN ULONG TransferLength)
1973 {
1974     PUSBPORT_TRANSFER Transfer;
1975     PUSBPORT_TRANSFER ParentTransfer;
1976     PUSBPORT_TRANSFER SplitTransfer;
1977     PLIST_ENTRY SplitHead;
1978     PLIST_ENTRY Entry;
1979     KIRQL OldIrql;
1980 
1981     DPRINT_CORE("USBPORT_MiniportCompleteTransfer: USBDStatus - %x, TransferLength - %x\n",
1982                 USBDStatus,
1983                 TransferLength);
1984 
1985     Transfer = CONTAINING_RECORD(TransferParameters,
1986                                  USBPORT_TRANSFER,
1987                                  TransferParameters);
1988 
1989     Transfer->Flags |= TRANSFER_FLAG_COMPLETED;
1990     Transfer->CompletedTransferLen = TransferLength;
1991 
1992     if (((Transfer->Flags & TRANSFER_FLAG_SPLITED) == 0) ||
1993         TransferLength >= Transfer->TransferParameters.TransferBufferLength)
1994     {
1995         goto Exit;
1996     }
1997 
1998     ParentTransfer = Transfer->ParentTransfer;
1999 
2000     KeAcquireSpinLock(&ParentTransfer->TransferSpinLock, &OldIrql);
2001 
2002     if (IsListEmpty(&ParentTransfer->SplitTransfersList))
2003     {
2004         goto Exit;
2005     }
2006 
2007     SplitHead = &ParentTransfer->SplitTransfersList;
2008     Entry = SplitHead->Flink;
2009 
2010     while (Entry && !IsListEmpty(SplitHead))
2011     {
2012         SplitTransfer = CONTAINING_RECORD(Entry,
2013                                           USBPORT_TRANSFER,
2014                                           SplitLink);
2015 
2016         if (!(SplitTransfer->Flags & TRANSFER_FLAG_SUBMITED))
2017         {
2018             DPRINT1("USBPORT_MiniportCompleteTransfer: SplitTransfer->Flags - %X\n",
2019                     SplitTransfer->Flags);
2020             //Add TRANSFER_FLAG_xxx
2021         }
2022 
2023         Entry = Entry->Flink;
2024     }
2025 
2026     KeReleaseSpinLock(&ParentTransfer->TransferSpinLock, OldIrql);
2027 
2028 Exit:
2029     USBPORT_QueueDoneTransfer(Transfer, USBDStatus);
2030 }
2031 
2032 VOID
2033 NTAPI
2034 USBPORT_AsyncTimerDpc(IN PRKDPC Dpc,
2035                       IN PVOID DeferredContext,
2036                       IN PVOID SystemArgument1,
2037                       IN PVOID SystemArgument2)
2038 {
2039     PDEVICE_OBJECT FdoDevice;
2040     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2041     PUSBPORT_ASYNC_CALLBACK_DATA AsyncCallbackData;
2042 
2043     DPRINT("USBPORT_AsyncTimerDpc: ... \n");
2044 
2045     AsyncCallbackData = DeferredContext;
2046     FdoDevice = AsyncCallbackData->FdoDevice;
2047     FdoExtension = FdoDevice->DeviceExtension;
2048 
2049     (*AsyncCallbackData->CallbackFunction)(FdoExtension->MiniPortExt,
2050                                            &AsyncCallbackData->CallbackContext);
2051 
2052     ExFreePoolWithTag(AsyncCallbackData, USB_PORT_TAG);
2053 }
2054 
2055 ULONG
2056 NTAPI
2057 USBPORT_RequestAsyncCallback(IN PVOID MiniPortExtension,
2058                              IN ULONG TimerValue,
2059                              IN PVOID Buffer,
2060                              IN SIZE_T Length,
2061                              IN ASYNC_TIMER_CALLBACK * Callback)
2062 {
2063     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2064     PDEVICE_OBJECT FdoDevice;
2065     PUSBPORT_ASYNC_CALLBACK_DATA AsyncCallbackData;
2066     LARGE_INTEGER DueTime = {{0, 0}};
2067 
2068     DPRINT("USBPORT_RequestAsyncCallback: ... \n");
2069 
2070     FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension -
2071                                                sizeof(USBPORT_DEVICE_EXTENSION));
2072 
2073     FdoDevice = FdoExtension->CommonExtension.SelfDevice;
2074 
2075     AsyncCallbackData = ExAllocatePoolWithTag(NonPagedPool,
2076                                               sizeof(USBPORT_ASYNC_CALLBACK_DATA) + Length,
2077                                               USB_PORT_TAG);
2078 
2079     if (!AsyncCallbackData)
2080     {
2081         DPRINT1("USBPORT_RequestAsyncCallback: Not allocated AsyncCallbackData!\n");
2082         return 0;
2083     }
2084 
2085     RtlZeroMemory(AsyncCallbackData,
2086                   sizeof(USBPORT_ASYNC_CALLBACK_DATA) + Length);
2087 
2088     if (Length)
2089     {
2090         RtlCopyMemory(&AsyncCallbackData->CallbackContext, Buffer, Length);
2091     }
2092 
2093     AsyncCallbackData->FdoDevice = FdoDevice;
2094     AsyncCallbackData->CallbackFunction = Callback;
2095 
2096     KeInitializeTimer(&AsyncCallbackData->AsyncTimer);
2097 
2098     KeInitializeDpc(&AsyncCallbackData->AsyncTimerDpc,
2099                     USBPORT_AsyncTimerDpc,
2100                     AsyncCallbackData);
2101 
2102     DueTime.QuadPart -= (KeQueryTimeIncrement() - 1) + 10000 * TimerValue;
2103 
2104     KeSetTimer(&AsyncCallbackData->AsyncTimer,
2105                DueTime,
2106                &AsyncCallbackData->AsyncTimerDpc);
2107 
2108     return 0;
2109 }
2110 
2111 PVOID
2112 NTAPI
2113 USBPORT_GetMappedVirtualAddress(IN ULONG PhysicalAddress,
2114                                 IN PVOID MiniPortExtension,
2115                                 IN PVOID MiniPortEndpoint)
2116 {
2117     PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer;
2118     PUSBPORT_ENDPOINT Endpoint;
2119     ULONG Offset;
2120     ULONG_PTR VirtualAddress;
2121 
2122     DPRINT_CORE("USBPORT_GetMappedVirtualAddress ... \n");
2123 
2124     Endpoint = (PUSBPORT_ENDPOINT)((ULONG_PTR)MiniPortEndpoint -
2125                                    sizeof(USBPORT_ENDPOINT));
2126 
2127     if (!Endpoint)
2128     {
2129         ASSERT(FALSE);
2130     }
2131 
2132     HeaderBuffer = Endpoint->HeaderBuffer;
2133 
2134     Offset = PhysicalAddress - HeaderBuffer->PhysicalAddress;
2135     VirtualAddress = HeaderBuffer->VirtualAddress + Offset;
2136 
2137     return (PVOID)VirtualAddress;
2138 }
2139 
2140 ULONG
2141 NTAPI
2142 USBPORT_InvalidateEndpoint(IN PVOID MiniPortExtension,
2143                            IN PVOID MiniPortEndpoint)
2144 {
2145     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2146     PDEVICE_OBJECT FdoDevice;
2147     PUSBPORT_ENDPOINT Endpoint;
2148 
2149     DPRINT_CORE("USBPORT_InvalidateEndpoint: ... \n");
2150 
2151     FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension -
2152                                                sizeof(USBPORT_DEVICE_EXTENSION));
2153 
2154     FdoDevice = FdoExtension->CommonExtension.SelfDevice;
2155 
2156     if (!MiniPortEndpoint)
2157     {
2158         USBPORT_InvalidateEndpointHandler(FdoDevice,
2159                                           NULL,
2160                                           INVALIDATE_ENDPOINT_ONLY);
2161         return 0;
2162     }
2163 
2164     Endpoint = (PUSBPORT_ENDPOINT)((ULONG_PTR)MiniPortEndpoint -
2165                                    sizeof(USBPORT_ENDPOINT));
2166 
2167     USBPORT_InvalidateEndpointHandler(FdoDevice,
2168                                       Endpoint,
2169                                       INVALIDATE_ENDPOINT_ONLY);
2170 
2171     return 0;
2172 }
2173 
2174 VOID
2175 NTAPI
2176 USBPORT_CompleteTransfer(IN PURB Urb,
2177                          IN USBD_STATUS TransferStatus)
2178 {
2179     struct _URB_CONTROL_TRANSFER *UrbTransfer;
2180     PUSBPORT_TRANSFER Transfer;
2181     NTSTATUS Status;
2182     PIRP Irp;
2183     KIRQL OldIrql;
2184     PRKEVENT Event;
2185     BOOLEAN WriteToDevice;
2186     BOOLEAN IsFlushSuccess;
2187     PMDL Mdl;
2188     ULONG_PTR CurrentVa;
2189     SIZE_T TransferLength;
2190     PUSBPORT_ENDPOINT Endpoint;
2191     PDEVICE_OBJECT FdoDevice;
2192     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2193     PDMA_OPERATIONS DmaOperations;
2194 
2195     DPRINT("USBPORT_CompleteTransfer: Urb - %p, TransferStatus - %X\n",
2196            Urb,
2197            TransferStatus);
2198 
2199     UrbTransfer = &Urb->UrbControlTransfer;
2200     Transfer = UrbTransfer->hca.Reserved8[0];
2201 
2202     Transfer->USBDStatus = TransferStatus;
2203     Status = USBPORT_USBDStatusToNtStatus(Urb, TransferStatus);
2204 
2205     UrbTransfer->TransferBufferLength = Transfer->CompletedTransferLen;
2206 
2207     if (Transfer->Flags & TRANSFER_FLAG_DMA_MAPPED)
2208     {
2209         Endpoint = Transfer->Endpoint;
2210         FdoDevice = Endpoint->FdoDevice;
2211         FdoExtension = FdoDevice->DeviceExtension;
2212         DmaOperations = FdoExtension->DmaAdapter->DmaOperations;
2213 
2214         WriteToDevice = Transfer->Direction == USBPORT_DMA_DIRECTION_TO_DEVICE;
2215         Mdl = UrbTransfer->TransferBufferMDL;
2216         CurrentVa = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
2217         TransferLength = UrbTransfer->TransferBufferLength;
2218 
2219         IsFlushSuccess = DmaOperations->FlushAdapterBuffers(FdoExtension->DmaAdapter,
2220                                                             Mdl,
2221                                                             Transfer->MapRegisterBase,
2222                                                             (PVOID)CurrentVa,
2223                                                             TransferLength,
2224                                                             WriteToDevice);
2225 
2226         if (!IsFlushSuccess)
2227         {
2228             DPRINT("USBPORT_CompleteTransfer: no FlushAdapterBuffers !!!\n");
2229             ASSERT(FALSE);
2230         }
2231 
2232         KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2233 
2234         DmaOperations->FreeMapRegisters(FdoExtension->DmaAdapter,
2235                                         Transfer->MapRegisterBase,
2236                                         Transfer->NumberOfMapRegisters);
2237 
2238         KeLowerIrql(OldIrql);
2239     }
2240 
2241     if (Urb->UrbHeader.UsbdFlags & USBD_FLAG_ALLOCATED_MDL)
2242     {
2243         IoFreeMdl(Transfer->TransferBufferMDL);
2244         Urb->UrbHeader.UsbdFlags |= ~USBD_FLAG_ALLOCATED_MDL;
2245     }
2246 
2247     Urb->UrbControlTransfer.hca.Reserved8[0] = NULL;
2248     Urb->UrbHeader.UsbdFlags |= ~USBD_FLAG_ALLOCATED_TRANSFER;
2249 
2250     Irp = Transfer->Irp;
2251 
2252     if (Irp)
2253     {
2254         if (!NT_SUCCESS(Status))
2255         {
2256             //DbgBreakPoint();
2257             DPRINT1("USBPORT_CompleteTransfer: Irp - %p complete with Status - %lx\n",
2258                     Irp,
2259                     Status);
2260 
2261             USBPORT_DumpingURB(Urb);
2262         }
2263 
2264         Irp->IoStatus.Status = Status;
2265         Irp->IoStatus.Information = 0;
2266 
2267         KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2268         IoCompleteRequest(Irp, IO_NO_INCREMENT);
2269         KeLowerIrql(OldIrql);
2270     }
2271 
2272     Event = Transfer->Event;
2273 
2274     if (Event)
2275     {
2276         KeSetEvent(Event, EVENT_INCREMENT, FALSE);
2277     }
2278 
2279     ExFreePoolWithTag(Transfer, USB_PORT_TAG);
2280 
2281     DPRINT_CORE("USBPORT_CompleteTransfer: exit\n");
2282 }
2283 
2284 IO_ALLOCATION_ACTION
2285 NTAPI
2286 USBPORT_MapTransfer(IN PDEVICE_OBJECT FdoDevice,
2287                     IN PIRP Irp,
2288                     IN PVOID MapRegisterBase,
2289                     IN PVOID Context)
2290 {
2291     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2292     PDMA_ADAPTER DmaAdapter;
2293     PUSBPORT_TRANSFER Transfer;
2294     PURB Urb;
2295     PUSBPORT_ENDPOINT Endpoint;
2296     PMDL Mdl;
2297     ULONG_PTR CurrentVa;
2298     PUSBPORT_SCATTER_GATHER_LIST sgList;
2299     SIZE_T CurrentLength;
2300     ULONG ix;
2301     BOOLEAN WriteToDevice;
2302     PHYSICAL_ADDRESS PhAddr = {{0, 0}};
2303     PHYSICAL_ADDRESS PhAddress = {{0, 0}};
2304     ULONG TransferLength;
2305     SIZE_T SgCurrentLength;
2306     SIZE_T ElementLength;
2307     PUSBPORT_DEVICE_HANDLE DeviceHandle;
2308     PDMA_OPERATIONS DmaOperations;
2309     USBD_STATUS USBDStatus;
2310     LIST_ENTRY List;
2311     PUSBPORT_TRANSFER transfer;
2312 
2313     DPRINT_CORE("USBPORT_MapTransfer: ... \n");
2314 
2315     FdoExtension = FdoDevice->DeviceExtension;
2316     DmaAdapter = FdoExtension->DmaAdapter;
2317     DmaOperations = DmaAdapter->DmaOperations;
2318 
2319     Transfer = Context;
2320 
2321     Urb = Transfer->Urb;
2322     Endpoint = Transfer->Endpoint;
2323     TransferLength = Transfer->TransferParameters.TransferBufferLength;
2324 
2325     Mdl = Urb->UrbControlTransfer.TransferBufferMDL;
2326     CurrentVa = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
2327 
2328     sgList = &Transfer->SgList;
2329 
2330     sgList->Flags = 0;
2331     sgList->CurrentVa = CurrentVa;
2332     sgList->MappedSystemVa = MmGetSystemAddressForMdlSafe(Mdl,
2333                                                           NormalPagePriority);
2334     Transfer->MapRegisterBase = MapRegisterBase;
2335 
2336     ix = 0;
2337     CurrentLength = 0;
2338 
2339     do
2340     {
2341         WriteToDevice = Transfer->Direction == USBPORT_DMA_DIRECTION_TO_DEVICE;
2342         ASSERT(Transfer->Direction != 0);
2343 
2344         PhAddress = DmaOperations->MapTransfer(DmaAdapter,
2345                                                Mdl,
2346                                                MapRegisterBase,
2347                                                (PVOID)CurrentVa,
2348                                                &TransferLength,
2349                                                WriteToDevice);
2350 
2351         DPRINT_CORE("USBPORT_MapTransfer: PhAddress.LowPart - %p, PhAddress.HighPart - %x, TransferLength - %x\n",
2352                PhAddress.LowPart,
2353                PhAddress.HighPart,
2354                TransferLength);
2355 
2356         PhAddress.HighPart = 0;
2357         SgCurrentLength = TransferLength;
2358 
2359         do
2360         {
2361             ElementLength = PAGE_SIZE - (PhAddress.LowPart & (PAGE_SIZE - 1));
2362 
2363             if (ElementLength > SgCurrentLength)
2364                 ElementLength = SgCurrentLength;
2365 
2366             DPRINT_CORE("USBPORT_MapTransfer: PhAddress.LowPart - %p, HighPart - %x, ElementLength - %x\n",
2367                    PhAddress.LowPart,
2368                    PhAddress.HighPart,
2369                    ElementLength);
2370 
2371             sgList->SgElement[ix].SgPhysicalAddress = PhAddress;
2372             sgList->SgElement[ix].SgTransferLength = ElementLength;
2373             sgList->SgElement[ix].SgOffset = CurrentLength +
2374                                              (TransferLength - SgCurrentLength);
2375 
2376             PhAddress.LowPart += ElementLength;
2377             SgCurrentLength -= ElementLength;
2378 
2379             ++ix;
2380         }
2381         while (SgCurrentLength);
2382 
2383         if (PhAddr.QuadPart == PhAddress.QuadPart)
2384         {
2385             DPRINT1("USBPORT_MapTransfer: PhAddr == PhAddress\n");
2386             ASSERT(FALSE);
2387         }
2388 
2389         PhAddr = PhAddress;
2390 
2391         CurrentLength += TransferLength;
2392         CurrentVa += TransferLength;
2393 
2394         TransferLength = Transfer->TransferParameters.TransferBufferLength -
2395                          CurrentLength;
2396     }
2397     while (CurrentLength != Transfer->TransferParameters.TransferBufferLength);
2398 
2399     sgList->SgElementCount = ix;
2400 
2401     if (Endpoint->EndpointProperties.DeviceSpeed == UsbHighSpeed)
2402     {
2403         Transfer->Flags |= TRANSFER_FLAG_HIGH_SPEED;
2404     }
2405 
2406     Transfer->Flags |= TRANSFER_FLAG_DMA_MAPPED;
2407 
2408     if ((Transfer->Flags & TRANSFER_FLAG_ISO) == 0)
2409     {
2410         KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
2411                           &Endpoint->EndpointOldIrql);
2412 
2413         USBPORT_SplitTransfer(FdoDevice, Endpoint, Transfer, &List);
2414 
2415         while (!IsListEmpty(&List))
2416         {
2417             transfer = CONTAINING_RECORD(List.Flink,
2418                                          USBPORT_TRANSFER,
2419                                          TransferLink);
2420 
2421             RemoveHeadList(&List);
2422             InsertTailList(&Endpoint->TransferList, &transfer->TransferLink);
2423         }
2424 
2425         KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
2426                           Endpoint->EndpointOldIrql);
2427     }
2428     else
2429     {
2430         USBDStatus = USBPORT_InitializeIsoTransfer(FdoDevice,
2431                                                    &Urb->UrbIsochronousTransfer,
2432                                                    Transfer);
2433 
2434         if (USBDStatus != USBD_STATUS_SUCCESS)
2435         {
2436             KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
2437                               &Endpoint->EndpointOldIrql);
2438 
2439             USBPORT_QueueDoneTransfer(Transfer, USBDStatus);
2440 
2441             KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
2442                               Endpoint->EndpointOldIrql);
2443         }
2444     }
2445 
2446     DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
2447     InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
2448 
2449     if (USBPORT_EndpointWorker(Endpoint, 0))
2450     {
2451         USBPORT_InvalidateEndpointHandler(FdoDevice,
2452                                           Endpoint,
2453                                           INVALIDATE_ENDPOINT_WORKER_THREAD);
2454     }
2455 
2456     return DeallocateObjectKeepRegisters;
2457 }
2458 
2459 VOID
2460 NTAPI
2461 USBPORT_FlushMapTransfers(IN PDEVICE_OBJECT FdoDevice)
2462 {
2463     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2464     PLIST_ENTRY MapTransferList;
2465     PUSBPORT_TRANSFER Transfer;
2466     ULONG NumMapRegisters;
2467     PMDL Mdl;
2468     SIZE_T TransferBufferLength;
2469     ULONG_PTR VirtualAddr;
2470     KIRQL OldIrql;
2471     NTSTATUS Status;
2472     PDMA_OPERATIONS DmaOperations;
2473 
2474     DPRINT_CORE("USBPORT_FlushMapTransfers: ... \n");
2475 
2476     FdoExtension = FdoDevice->DeviceExtension;
2477     DmaOperations = FdoExtension->DmaAdapter->DmaOperations;
2478 
2479     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2480 
2481     while (TRUE)
2482     {
2483         MapTransferList = &FdoExtension->MapTransferList;
2484 
2485         if (IsListEmpty(&FdoExtension->MapTransferList))
2486         {
2487             KeLowerIrql(OldIrql);
2488             return;
2489         }
2490 
2491         Transfer = CONTAINING_RECORD(MapTransferList->Flink,
2492                                      USBPORT_TRANSFER,
2493                                      TransferLink);
2494 
2495         RemoveHeadList(MapTransferList);
2496 
2497         Mdl = Transfer->Urb->UrbControlTransfer.TransferBufferMDL;
2498         TransferBufferLength = Transfer->TransferParameters.TransferBufferLength;
2499         VirtualAddr = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
2500 
2501         NumMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddr,
2502                                                          TransferBufferLength);
2503 
2504         Transfer->NumberOfMapRegisters = NumMapRegisters;
2505 
2506         Status = DmaOperations->AllocateAdapterChannel(FdoExtension->DmaAdapter,
2507                                                        FdoDevice,
2508                                                        NumMapRegisters,
2509                                                        USBPORT_MapTransfer,
2510                                                        Transfer);
2511 
2512         if (!NT_SUCCESS(Status))
2513             ASSERT(FALSE);
2514     }
2515 
2516     KeLowerIrql(OldIrql);
2517 }
2518 
2519 USBD_STATUS
2520 NTAPI
2521 USBPORT_AllocateTransfer(IN PDEVICE_OBJECT FdoDevice,
2522                          IN PURB Urb,
2523                          IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
2524                          IN PIRP Irp,
2525                          IN PRKEVENT Event)
2526 {
2527     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2528     SIZE_T TransferLength;
2529     PMDL Mdl;
2530     ULONG_PTR VirtualAddr;
2531     ULONG PagesNeed = 0;
2532     SIZE_T PortTransferLength;
2533     SIZE_T FullTransferLength;
2534     PUSBPORT_TRANSFER Transfer;
2535     PUSBPORT_PIPE_HANDLE PipeHandle;
2536     USBD_STATUS USBDStatus;
2537     SIZE_T IsoBlockLen = 0;
2538 
2539     DPRINT_CORE("USBPORT_AllocateTransfer: FdoDevice - %p, Urb - %p, DeviceHandle - %p, Irp - %p, Event - %p\n",
2540            FdoDevice,
2541            Urb,
2542            DeviceHandle,
2543            Irp,
2544            Event);
2545 
2546     FdoExtension = FdoDevice->DeviceExtension;
2547 
2548     TransferLength = Urb->UrbControlTransfer.TransferBufferLength;
2549     PipeHandle = Urb->UrbControlTransfer.PipeHandle;
2550 
2551     if (TransferLength)
2552     {
2553         Mdl = Urb->UrbControlTransfer.TransferBufferMDL;
2554         VirtualAddr = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
2555 
2556         PagesNeed = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddr,
2557                                                    TransferLength);
2558         if (PagesNeed > 0)
2559         {
2560             PagesNeed--;
2561         }
2562     }
2563 
2564     if (Urb->UrbHeader.Function == URB_FUNCTION_ISOCH_TRANSFER)
2565     {
2566         DPRINT1("USBPORT_AllocateTransfer: ISOCH_TRANSFER UNIMPLEMENTED. FIXME\n");
2567 
2568         //IsoBlockLen = sizeof(USBPORT_ISO_BLOCK) +
2569         //              Urb->UrbIsochronousTransfer.NumberOfPackets *
2570         //              sizeof(USBPORT_ISO_BLOCK_PACKET);
2571     }
2572 
2573     PortTransferLength = sizeof(USBPORT_TRANSFER) +
2574                          PagesNeed * sizeof(USBPORT_SCATTER_GATHER_ELEMENT) +
2575                          IsoBlockLen;
2576 
2577     FullTransferLength = PortTransferLength +
2578                          FdoExtension->MiniPortInterface->Packet.MiniPortTransferSize;
2579 
2580     Transfer = ExAllocatePoolWithTag(NonPagedPool,
2581                                      FullTransferLength,
2582                                      USB_PORT_TAG);
2583 
2584     if (!Transfer)
2585     {
2586         DPRINT1("USBPORT_AllocateTransfer: Transfer not allocated!\n");
2587         return USBD_STATUS_INSUFFICIENT_RESOURCES;
2588     }
2589 
2590     RtlZeroMemory(Transfer, FullTransferLength);
2591 
2592     Transfer->Irp = Irp;
2593     Transfer->Urb = Urb;
2594     Transfer->Endpoint = PipeHandle->Endpoint;
2595     Transfer->Event = Event;
2596     Transfer->PortTransferLength = PortTransferLength;
2597     Transfer->FullTransferLength = FullTransferLength;
2598     Transfer->IsoBlockPtr = NULL;
2599     Transfer->Period = 0;
2600     Transfer->ParentTransfer = Transfer;
2601 
2602     if (IsoBlockLen)
2603     {
2604         Transfer->IsoBlockPtr = (PVOID)((ULONG_PTR)Transfer +
2605                                  PortTransferLength - IsoBlockLen);
2606 
2607         Transfer->Period = PipeHandle->Endpoint->EndpointProperties.Period;
2608         Transfer->Flags |= TRANSFER_FLAG_ISO;
2609     }
2610 
2611     Transfer->MiniportTransfer = (PVOID)((ULONG_PTR)Transfer +
2612                                                     PortTransferLength);
2613 
2614     KeInitializeSpinLock(&Transfer->TransferSpinLock);
2615 
2616     Urb->UrbControlTransfer.hca.Reserved8[0] = Transfer;
2617     Urb->UrbHeader.UsbdFlags |= USBD_FLAG_ALLOCATED_TRANSFER;
2618 
2619     USBDStatus = USBD_STATUS_SUCCESS;
2620 
2621     DPRINT_CORE("USBPORT_AllocateTransfer: return USBDStatus - %x\n",
2622                 USBDStatus);
2623 
2624     return USBDStatus;
2625 }
2626 
2627 NTSTATUS
2628 NTAPI
2629 USBPORT_Dispatch(IN PDEVICE_OBJECT DeviceObject,
2630                  IN PIRP Irp)
2631 {
2632     PUSBPORT_COMMON_DEVICE_EXTENSION DeviceExtension;
2633     PIO_STACK_LOCATION IoStack;
2634     NTSTATUS Status = STATUS_SUCCESS;
2635 
2636     DeviceExtension = DeviceObject->DeviceExtension;
2637     IoStack = IoGetCurrentIrpStackLocation(Irp);
2638 
2639     if (DeviceExtension->PnpStateFlags & USBPORT_PNP_STATE_FAILED)
2640     {
2641         DPRINT1("USBPORT_Dispatch: USBPORT_PNP_STATE_FAILED\n");
2642         DbgBreakPoint();
2643     }
2644 
2645     switch (IoStack->MajorFunction)
2646     {
2647         case IRP_MJ_DEVICE_CONTROL:
2648             if (DeviceExtension->IsPDO)
2649             {
2650                 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_DEVICE_CONTROL. Major - %d, Minor - %d\n",
2651                        IoStack->MajorFunction,
2652                        IoStack->MinorFunction);
2653 
2654                 Status = USBPORT_PdoDeviceControl(DeviceObject, Irp);
2655             }
2656             else
2657             {
2658                 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_DEVICE_CONTROL. Major - %d, Minor - %d\n",
2659                        IoStack->MajorFunction,
2660                        IoStack->MinorFunction);
2661 
2662                 Status = USBPORT_FdoDeviceControl(DeviceObject, Irp);
2663             }
2664 
2665             break;
2666 
2667         case IRP_MJ_INTERNAL_DEVICE_CONTROL:
2668             if (DeviceExtension->IsPDO)
2669             {
2670                 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_INTERNAL_DEVICE_CONTROL. Major - %d, Minor - %d\n",
2671                        IoStack->MajorFunction,
2672                        IoStack->MinorFunction);
2673 
2674                 Status = USBPORT_PdoInternalDeviceControl(DeviceObject, Irp);
2675             }
2676             else
2677             {
2678                 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_INTERNAL_DEVICE_CONTROL. Major - %d, Minor - %d\n",
2679                        IoStack->MajorFunction,
2680                        IoStack->MinorFunction);
2681 
2682                 Status = USBPORT_FdoInternalDeviceControl(DeviceObject, Irp);
2683             }
2684 
2685             break;
2686 
2687         case IRP_MJ_POWER:
2688             if (DeviceExtension->IsPDO)
2689             {
2690                 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_POWER. Major - %d, Minor - %d\n",
2691                        IoStack->MajorFunction,
2692                        IoStack->MinorFunction);
2693 
2694                 Status = USBPORT_PdoPower(DeviceObject, Irp);
2695             }
2696             else
2697             {
2698                 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_POWER. Major - %d, Minor - %d\n",
2699                        IoStack->MajorFunction,
2700                        IoStack->MinorFunction);
2701 
2702                 Status = USBPORT_FdoPower(DeviceObject, Irp);
2703             }
2704 
2705             break;
2706 
2707         case IRP_MJ_SYSTEM_CONTROL:
2708             if (DeviceExtension->IsPDO)
2709             {
2710                 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_SYSTEM_CONTROL. Major - %d, Minor - %d\n",
2711                        IoStack->MajorFunction,
2712                        IoStack->MinorFunction);
2713 
2714                 Status = Irp->IoStatus.Status;
2715                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2716             }
2717             else
2718             {
2719                 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_SYSTEM_CONTROL. Major - %d, Minor - %d\n",
2720                        IoStack->MajorFunction,
2721                        IoStack->MinorFunction);
2722 
2723                 IoSkipCurrentIrpStackLocation(Irp);
2724                 Status = IoCallDriver(DeviceExtension->LowerDevice, Irp);
2725             }
2726 
2727             break;
2728 
2729         case IRP_MJ_PNP:
2730             if (DeviceExtension->IsPDO)
2731             {
2732                 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_PNP. Major - %d, Minor - %d\n",
2733                        IoStack->MajorFunction,
2734                        IoStack->MinorFunction);
2735 
2736                 Status = USBPORT_PdoPnP(DeviceObject, Irp);
2737             }
2738             else
2739             {
2740                 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_PNP. Major - %d, Minor - %d\n",
2741                        IoStack->MajorFunction,
2742                        IoStack->MinorFunction);
2743 
2744                 Status = USBPORT_FdoPnP(DeviceObject, Irp);
2745             }
2746 
2747             break;
2748 
2749         case IRP_MJ_CREATE:
2750         case IRP_MJ_CLOSE:
2751             DPRINT("USBPORT_Dispatch: IRP_MJ_CREATE | IRP_MJ_CLOSE\n");
2752             Irp->IoStatus.Status = Status;
2753             IoCompleteRequest(Irp, IO_NO_INCREMENT);
2754             break;
2755 
2756         default:
2757             if (DeviceExtension->IsPDO)
2758             {
2759                 DPRINT("USBPORT_Dispatch: PDO unhandled IRP_MJ_???. Major - %d, Minor - %d\n",
2760                        IoStack->MajorFunction,
2761                        IoStack->MinorFunction);
2762             }
2763             else
2764             {
2765                 DPRINT("USBPORT_Dispatch: FDO unhandled IRP_MJ_???. Major - %d, Minor - %d\n",
2766                        IoStack->MajorFunction,
2767                        IoStack->MinorFunction);
2768             }
2769 
2770             Status = STATUS_INVALID_DEVICE_REQUEST;
2771             Irp->IoStatus.Status = Status;
2772             IoCompleteRequest(Irp, IO_NO_INCREMENT);
2773             break;
2774     }
2775 
2776     DPRINT("USBPORT_Dispatch: Status - %x\n", Status);
2777     return Status;
2778 }
2779 
2780 ULONG
2781 NTAPI
2782 USBPORT_GetHciMn(VOID)
2783 {
2784     return USBPORT_HCI_MN;
2785 }
2786 
2787 NTSTATUS
2788 NTAPI
2789 USBPORT_RegisterUSBPortDriver(IN PDRIVER_OBJECT DriverObject,
2790                               IN ULONG Version,
2791                               IN PUSBPORT_REGISTRATION_PACKET RegPacket)
2792 {
2793     PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
2794 
2795     DPRINT("USBPORT_RegisterUSBPortDriver: DriverObject - %p, Version - %p, RegPacket - %p\n",
2796            DriverObject,
2797            Version,
2798            RegPacket);
2799 
2800     DPRINT("USBPORT_RegisterUSBPortDriver: sizeof(USBPORT_MINIPORT_INTERFACE) - %x\n",
2801            sizeof(USBPORT_MINIPORT_INTERFACE));
2802 
2803     DPRINT("USBPORT_RegisterUSBPortDriver: sizeof(USBPORT_DEVICE_EXTENSION)   - %x\n",
2804            sizeof(USBPORT_DEVICE_EXTENSION));
2805 
2806     if (Version < USB10_MINIPORT_INTERFACE_VERSION)
2807     {
2808         return STATUS_UNSUCCESSFUL;
2809     }
2810 
2811     if (!USBPORT_Initialized)
2812     {
2813         InitializeListHead(&USBPORT_MiniPortDrivers);
2814         InitializeListHead(&USBPORT_USB1FdoList);
2815         InitializeListHead(&USBPORT_USB2FdoList);
2816 
2817         KeInitializeSpinLock(&USBPORT_SpinLock);
2818         USBPORT_Initialized = TRUE;
2819     }
2820 
2821     MiniPortInterface = ExAllocatePoolWithTag(NonPagedPool,
2822                                               sizeof(USBPORT_MINIPORT_INTERFACE),
2823                                               USB_PORT_TAG);
2824     if (!MiniPortInterface)
2825     {
2826         return STATUS_INSUFFICIENT_RESOURCES;
2827     }
2828 
2829     RtlZeroMemory(MiniPortInterface, sizeof(USBPORT_MINIPORT_INTERFACE));
2830 
2831     MiniPortInterface->DriverObject = DriverObject;
2832     MiniPortInterface->DriverUnload = DriverObject->DriverUnload;
2833     MiniPortInterface->Version = Version;
2834 
2835     ExInterlockedInsertTailList(&USBPORT_MiniPortDrivers,
2836                                 &MiniPortInterface->DriverLink,
2837                                 &USBPORT_SpinLock);
2838 
2839     DriverObject->DriverExtension->AddDevice = USBPORT_AddDevice;
2840     DriverObject->DriverUnload = USBPORT_Unload;
2841 
2842     DriverObject->MajorFunction[IRP_MJ_CREATE] = USBPORT_Dispatch;
2843     DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBPORT_Dispatch;
2844     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBPORT_Dispatch;
2845     DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBPORT_Dispatch;
2846     DriverObject->MajorFunction[IRP_MJ_PNP] = USBPORT_Dispatch;
2847     DriverObject->MajorFunction[IRP_MJ_POWER] = USBPORT_Dispatch;
2848     DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USBPORT_Dispatch;
2849 
2850     RegPacket->UsbPortDbgPrint = USBPORT_DbgPrint;
2851     RegPacket->UsbPortTestDebugBreak = USBPORT_TestDebugBreak;
2852     RegPacket->UsbPortAssertFailure = USBPORT_AssertFailure;
2853     RegPacket->UsbPortGetMiniportRegistryKeyValue = USBPORT_GetMiniportRegistryKeyValue;
2854     RegPacket->UsbPortInvalidateRootHub = USBPORT_InvalidateRootHub;
2855     RegPacket->UsbPortInvalidateEndpoint = USBPORT_InvalidateEndpoint;
2856     RegPacket->UsbPortCompleteTransfer = USBPORT_MiniportCompleteTransfer;
2857     RegPacket->UsbPortCompleteIsoTransfer = USBPORT_CompleteIsoTransfer;
2858     RegPacket->UsbPortLogEntry = USBPORT_LogEntry;
2859     RegPacket->UsbPortGetMappedVirtualAddress = USBPORT_GetMappedVirtualAddress;
2860     RegPacket->UsbPortRequestAsyncCallback = USBPORT_RequestAsyncCallback;
2861     RegPacket->UsbPortReadWriteConfigSpace = USBPORT_ReadWriteConfigSpace;
2862     RegPacket->UsbPortWait = USBPORT_Wait;
2863     RegPacket->UsbPortInvalidateController = USBPORT_InvalidateController;
2864     RegPacket->UsbPortBugCheck = USBPORT_BugCheck;
2865     RegPacket->UsbPortNotifyDoubleBuffer = USBPORT_NotifyDoubleBuffer;
2866 
2867     RtlCopyMemory(&MiniPortInterface->Packet,
2868                   RegPacket,
2869                   sizeof(USBPORT_REGISTRATION_PACKET));
2870 
2871     return STATUS_SUCCESS;
2872 }
2873 
2874 NTSTATUS
2875 NTAPI
2876 DriverEntry(IN PDRIVER_OBJECT DriverObject,
2877             IN PUNICODE_STRING RegistryPath)
2878 {
2879     return STATUS_SUCCESS;
2880 }
2881