xref: /reactos/drivers/usb/usbport/pnp.c (revision 40462c92)
1 /*
2  * PROJECT:     ReactOS USB Port Driver
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     USBPort plug and play 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 #include "usbdebug.h"
15 
16 IO_COMPLETION_ROUTINE USBPORT_FdoStartCompletion;
17 
18 NTSTATUS
19 NTAPI
20 USBPORT_FdoStartCompletion(IN PDEVICE_OBJECT DeviceObject,
21                            IN PIRP Irp,
22                            IN PVOID Context)
23 {
24     KeSetEvent((PKEVENT)Context, EVENT_INCREMENT, FALSE);
25     return STATUS_MORE_PROCESSING_REQUIRED;
26 }
27 
28 NTSTATUS
29 NTAPI
30 USBPORT_RegisterDeviceInterface(IN PDEVICE_OBJECT PdoDevice,
31                                 IN PDEVICE_OBJECT DeviceObject,
32                                 IN CONST GUID *InterfaceClassGuid,
33                                 IN BOOLEAN Enable)
34 {
35     PUSBPORT_RHDEVICE_EXTENSION DeviceExtension;
36     PUNICODE_STRING SymbolicLinkName;
37     NTSTATUS Status;
38 
39     DPRINT("USBPORT_RegisterDeviceInterface: Enable - %x\n", Enable);
40 
41     DeviceExtension = DeviceObject->DeviceExtension;
42     SymbolicLinkName = &DeviceExtension->CommonExtension.SymbolicLinkName;
43 
44     if (Enable)
45     {
46         Status = IoRegisterDeviceInterface(PdoDevice,
47                                            InterfaceClassGuid,
48                                            NULL,
49                                            SymbolicLinkName);
50 
51         if (NT_SUCCESS(Status))
52         {
53             DeviceExtension->CommonExtension.IsInterfaceEnabled = 1;
54 
55             Status = USBPORT_SetRegistryKeyValue(PdoDevice,
56                                                  FALSE,
57                                                  REG_SZ,
58                                                  L"SymbolicName",
59                                                  SymbolicLinkName->Buffer,
60                                                  SymbolicLinkName->Length);
61 
62             if (NT_SUCCESS(Status))
63             {
64                 DPRINT("USBPORT_RegisterDeviceInterface: LinkName  - %wZ\n",
65                        &DeviceExtension->CommonExtension.SymbolicLinkName);
66 
67                 Status = IoSetDeviceInterfaceState(SymbolicLinkName, TRUE);
68             }
69         }
70     }
71     else
72     {
73         /* Disable device interface */
74         Status = IoSetDeviceInterfaceState(SymbolicLinkName, FALSE);
75 
76         if (NT_SUCCESS(Status))
77         {
78             RtlFreeUnicodeString(SymbolicLinkName);
79             DeviceExtension->CommonExtension.IsInterfaceEnabled = 0; // Disabled interface
80         }
81     }
82 
83     return Status;
84 }
85 
86 BOOLEAN
87 NTAPI
88 USBPORT_IsSelectiveSuspendEnabled(IN PDEVICE_OBJECT FdoDevice)
89 {
90     PUSBPORT_DEVICE_EXTENSION FdoExtension;
91     ULONG Disabled = 0;
92 
93     DPRINT("USBPORT_IsSelectiveSuspendEnabled: ... \n");
94 
95     FdoExtension = FdoDevice->DeviceExtension;
96 
97     USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
98                                         FdoExtension->CommonExtension.LowerPdoDevice,
99                                         TRUE,
100                                         L"HcDisableSelectiveSuspend",
101                                         sizeof(L"HcDisableSelectiveSuspend"),
102                                         &Disabled,
103                                         sizeof(Disabled));
104 
105     return (Disabled == 0);
106 }
107 
108 NTSTATUS
109 NTAPI
110 USBPORT_GetConfigValue(IN PWSTR ValueName,
111                        IN ULONG ValueType,
112                        IN PVOID ValueData,
113                        IN ULONG ValueLength,
114                        IN PVOID Context,
115                        IN PVOID EntryContext)
116 {
117     NTSTATUS Status = STATUS_SUCCESS;
118 
119     DPRINT("USBPORT_GetConfigValue \n");
120 
121     if (ValueType == REG_DWORD)
122     {
123         *(PULONG)EntryContext = *(PULONG)ValueData;
124     }
125     else
126     {
127         Status = STATUS_INVALID_PARAMETER;
128     }
129 
130     return Status;
131 }
132 
133 NTSTATUS
134 NTAPI
135 USBPORT_GetDefaultBIOSx(IN PDEVICE_OBJECT FdoDevice,
136                          IN PULONG UsbBIOSx,
137                          IN PULONG DisableSelectiveSuspend,
138                          IN PULONG DisableCcDetect,
139                          IN PULONG IdleEpSupport,
140                          IN PULONG IdleEpSupportEx,
141                          IN PULONG SoftRetry)
142 {
143     RTL_QUERY_REGISTRY_TABLE QueryTable[7];
144 
145     DPRINT("USBPORT_GetDefaultBIOS_X: ... \n");
146 
147     RtlZeroMemory(QueryTable, sizeof(QueryTable));
148 
149     *UsbBIOSx = 2;
150 
151     QueryTable[0].QueryRoutine = USBPORT_GetConfigValue;
152     QueryTable[0].Flags = 0;
153     QueryTable[0].Name = L"UsbBIOSx";
154     QueryTable[0].EntryContext = UsbBIOSx;
155     QueryTable[0].DefaultType = REG_DWORD;
156     QueryTable[0].DefaultData = UsbBIOSx;
157     QueryTable[0].DefaultLength = sizeof(ULONG);
158 
159     QueryTable[1].QueryRoutine = USBPORT_GetConfigValue;
160     QueryTable[1].Flags = 0;
161     QueryTable[1].Name = L"DisableSelectiveSuspend";
162     QueryTable[1].EntryContext = DisableSelectiveSuspend;
163     QueryTable[1].DefaultType = REG_DWORD;
164     QueryTable[1].DefaultData = DisableSelectiveSuspend;
165     QueryTable[1].DefaultLength = sizeof(ULONG);
166 
167     QueryTable[2].QueryRoutine = USBPORT_GetConfigValue;
168     QueryTable[2].Flags = 0;
169     QueryTable[2].Name = L"DisableCcDetect";
170     QueryTable[2].EntryContext = DisableCcDetect;
171     QueryTable[2].DefaultType = REG_DWORD;
172     QueryTable[2].DefaultData = DisableCcDetect;
173     QueryTable[2].DefaultLength = sizeof(ULONG);
174 
175     QueryTable[3].QueryRoutine = USBPORT_GetConfigValue;
176     QueryTable[3].Flags = 0;
177     QueryTable[3].Name = L"EnIdleEndpointSupport";
178     QueryTable[3].EntryContext = IdleEpSupport;
179     QueryTable[3].DefaultType = REG_DWORD;
180     QueryTable[3].DefaultData = IdleEpSupport;
181     QueryTable[3].DefaultLength = sizeof(ULONG);
182 
183     QueryTable[4].QueryRoutine = USBPORT_GetConfigValue;
184     QueryTable[4].Flags = 0;
185     QueryTable[4].Name = L"EnIdleEndpointSupportEx";
186     QueryTable[4].EntryContext = IdleEpSupportEx;
187     QueryTable[4].DefaultType = REG_DWORD;
188     QueryTable[4].DefaultData = IdleEpSupportEx;
189     QueryTable[4].DefaultLength = sizeof(ULONG);
190 
191     QueryTable[5].QueryRoutine = USBPORT_GetConfigValue;
192     QueryTable[5].Flags = 0;
193     QueryTable[5].Name = L"EnSoftRetry";
194     QueryTable[5].EntryContext = SoftRetry;
195     QueryTable[5].DefaultType = REG_DWORD;
196     QueryTable[5].DefaultData = SoftRetry;
197     QueryTable[5].DefaultLength = sizeof(ULONG);
198 
199     return RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
200                                   L"usb",
201                                   QueryTable,
202                                   NULL,
203                                   NULL);
204 }
205 
206 NTSTATUS
207 NTAPI
208 USBPORT_IsCompanionController(IN PDEVICE_OBJECT DeviceObject,
209                               IN BOOLEAN *IsCompanion)
210 {
211     PDEVICE_OBJECT HighestDevice;
212     PIRP Irp;
213     KEVENT Event;
214     PIO_STACK_LOCATION IoStack;
215     PCI_DEVICE_PRESENT_INTERFACE PciInterface = {0};
216     PCI_DEVICE_PRESENCE_PARAMETERS Parameters   = {0};
217     IO_STATUS_BLOCK IoStatusBlock;
218     NTSTATUS Status;
219     BOOLEAN IsPresent;
220 
221     DPRINT("USBPORT_IsCompanionController: ... \n");
222 
223     *IsCompanion = FALSE;
224 
225     KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
226 
227     HighestDevice = IoGetAttachedDeviceReference(DeviceObject);
228 
229     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
230                                        HighestDevice,
231                                        NULL,
232                                        0,
233                                        NULL,
234                                        &Event,
235                                        &IoStatusBlock);
236 
237     if (!Irp)
238     {
239         Status = STATUS_INSUFFICIENT_RESOURCES;
240         ObDereferenceObject(HighestDevice);
241         return Status;
242     }
243 
244     IoStack = IoGetNextIrpStackLocation(Irp);
245 
246     Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
247     Irp->IoStatus.Information = 0;
248 
249     IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
250 
251     IoStack->Parameters.QueryInterface.InterfaceType = &GUID_PCI_DEVICE_PRESENT_INTERFACE;
252     IoStack->Parameters.QueryInterface.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
253     IoStack->Parameters.QueryInterface.Version = 1;
254     IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)&PciInterface;
255     IoStack->Parameters.QueryInterface.InterfaceSpecificData = 0;
256 
257     Status = IoCallDriver(HighestDevice, Irp);
258 
259     if (Status == STATUS_PENDING)
260     {
261         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
262         Status = IoStatusBlock.Status;
263     }
264 
265     if (!NT_SUCCESS(Status))
266     {
267         DPRINT1("USBPORT_IsCompanionController: query interface failed\\n");
268         ObDereferenceObject(HighestDevice);
269         return Status;
270     }
271 
272     DPRINT("USBPORT_IsCompanionController: query interface succeeded\n");
273 
274     if (PciInterface.Size < sizeof(PCI_DEVICE_PRESENT_INTERFACE))
275     {
276         DPRINT1("USBPORT_IsCompanionController: old version\n");
277         ObDereferenceObject(HighestDevice);
278         return Status;
279     }
280 
281     Parameters.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
282 
283     Parameters.BaseClass = PCI_CLASS_SERIAL_BUS_CTLR;
284     Parameters.SubClass = PCI_SUBCLASS_SB_USB;
285     Parameters.ProgIf = PCI_INTERFACE_USB_ID_EHCI;
286 
287     Parameters.Flags = PCI_USE_LOCAL_BUS |
288                        PCI_USE_LOCAL_DEVICE |
289                        PCI_USE_CLASS_SUBCLASS |
290                        PCI_USE_PROGIF;
291 
292     IsPresent = (PciInterface.IsDevicePresentEx)(PciInterface.Context,
293                                                  &Parameters);
294 
295     if (IsPresent)
296     {
297         DPRINT("USBPORT_IsCompanionController: Present EHCI controller for FDO - %p\n",
298                DeviceObject);
299     }
300     else
301     {
302         DPRINT("USBPORT_IsCompanionController: No EHCI controller for FDO - %p\n",
303                DeviceObject);
304     }
305 
306     *IsCompanion = IsPresent;
307 
308     (PciInterface.InterfaceDereference)(PciInterface.Context);
309 
310     ObDereferenceObject(HighestDevice);
311 
312     return Status;
313 }
314 
315 NTSTATUS
316 NTAPI
317 USBPORT_QueryPciBusInterface(IN PDEVICE_OBJECT FdoDevice)
318 {
319     PUSBPORT_DEVICE_EXTENSION FdoExtension;
320     PBUS_INTERFACE_STANDARD BusInterface;
321     PIO_STACK_LOCATION IoStack;
322     IO_STATUS_BLOCK IoStatusBlock;
323     PDEVICE_OBJECT HighestDevice;
324     KEVENT Event;
325     PIRP Irp;
326     NTSTATUS Status;
327 
328     DPRINT("USBPORT_QueryPciBusInterface: ...  \n");
329 
330     FdoExtension = FdoDevice->DeviceExtension;
331     BusInterface = &FdoExtension->BusInterface;
332 
333     RtlZeroMemory(BusInterface, sizeof(BUS_INTERFACE_STANDARD));
334     KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
335     HighestDevice = IoGetAttachedDeviceReference(FdoDevice);
336 
337     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
338                                        HighestDevice,
339                                        NULL,
340                                        0,
341                                        NULL,
342                                        &Event,
343                                        &IoStatusBlock);
344 
345     if (Irp)
346     {
347         IoStack = IoGetNextIrpStackLocation(Irp);
348 
349         Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
350         Irp->IoStatus.Information = 0;
351 
352         IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
353 
354         IoStack->Parameters.QueryInterface.InterfaceType = &GUID_BUS_INTERFACE_STANDARD;
355         IoStack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
356         IoStack->Parameters.QueryInterface.Version = 1;
357         IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface;
358         IoStack->Parameters.QueryInterface.InterfaceSpecificData = 0;
359 
360         Status = IoCallDriver(HighestDevice, Irp);
361 
362         if (Status == STATUS_PENDING)
363         {
364             KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
365             Status = IoStatusBlock.Status;
366         }
367     }
368     else
369     {
370         Status = STATUS_INSUFFICIENT_RESOURCES;
371     }
372 
373     ObDereferenceObject(HighestDevice);
374 
375     DPRINT("USBPORT_QueryPciBusInterface: return Status - %x\n", Status);
376 
377     return Status;
378 }
379 
380 NTSTATUS
381 NTAPI
382 USBPORT_QueryCapabilities(IN PDEVICE_OBJECT FdoDevice,
383                           IN PDEVICE_CAPABILITIES Capabilities)
384 {
385     PUSBPORT_DEVICE_EXTENSION FdoExtention;
386     PIRP Irp;
387     NTSTATUS Status;
388     PIO_STACK_LOCATION IoStack;
389     KEVENT Event;
390 
391     DPRINT("USBPORT_QueryCapabilities: ... \n");
392 
393     FdoExtention = FdoDevice->DeviceExtension;
394 
395     RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES));
396 
397     Capabilities->Size     = sizeof(DEVICE_CAPABILITIES);
398     Capabilities->Version  = 1;
399     Capabilities->Address  = MAXULONG;
400     Capabilities->UINumber = MAXULONG;
401 
402     Irp = IoAllocateIrp(FdoExtention->CommonExtension.LowerDevice->StackSize,
403                         FALSE);
404 
405     if (!Irp)
406     {
407         DPRINT1("USBPORT_QueryCapabilities: No resources - IoAllocateIrp!\n");
408         return STATUS_INSUFFICIENT_RESOURCES;
409     }
410 
411     IoStack = IoGetCurrentIrpStackLocation(Irp);
412     Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
413 
414     IoStack = IoGetNextIrpStackLocation(Irp);
415     IoStack->MajorFunction = IRP_MJ_PNP;
416     IoStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
417 
418     KeInitializeEvent(&Event, NotificationEvent, FALSE);
419 
420     IoSetCompletionRoutine(Irp,
421                           USBPORT_FdoStartCompletion,
422                           &Event,
423                           TRUE,
424                           TRUE,
425                           TRUE);
426 
427     IoStack->Parameters.DeviceCapabilities.Capabilities = Capabilities;
428 
429     Status = IoCallDriver(FdoExtention->CommonExtension.LowerDevice, Irp);
430 
431     if (Status == STATUS_PENDING)
432     {
433         KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
434         Status = Irp->IoStatus.Status;
435     }
436 
437     if (NT_SUCCESS(Status) && Capabilities)
438     {
439         USBPORT_DumpingCapabilities(Capabilities);
440     }
441 
442     IoFreeIrp(Irp);
443 
444     return Status;
445 }
446 
447 NTSTATUS
448 NTAPI
449 USBPORT_CreateLegacySymbolicLink(IN PDEVICE_OBJECT FdoDevice)
450 {
451     PUSBPORT_DEVICE_EXTENSION FdoExtension;
452     WCHAR CharName[255] = {0};
453     WCHAR CharDosName[255] = {0};
454     UNICODE_STRING DeviceName;
455     NTSTATUS Status;
456 
457     FdoExtension = FdoDevice->DeviceExtension;
458 
459     RtlStringCbPrintfW(CharName,
460                        sizeof(CharName),
461                        L"\\Device\\USBFDO-%d",
462                        FdoExtension->FdoNameNumber);
463 
464     RtlInitUnicodeString(&DeviceName, CharName);
465 
466     RtlStringCbPrintfW(CharDosName,
467                        sizeof(CharDosName),
468                        L"\\DosDevices\\HCD%d",
469                        FdoExtension->FdoNameNumber);
470 
471     RtlInitUnicodeString(&FdoExtension->DosDeviceSymbolicName, CharDosName);
472 
473     DPRINT("USBPORT_CreateLegacySymbolicLink: DeviceName - %wZ, DosSymbolicName - %wZ\n",
474            &DeviceName,
475            &FdoExtension->DosDeviceSymbolicName);
476 
477     Status = IoCreateSymbolicLink(&FdoExtension->DosDeviceSymbolicName,
478                                   &DeviceName);
479 
480     if (NT_SUCCESS(Status))
481     {
482         FdoExtension->Flags |= USBPORT_FLAG_DOS_SYMBOLIC_NAME;
483     }
484 
485     return Status;
486 }
487 
488 NTSTATUS
489 NTAPI
490 USBPORT_StopDevice(IN PDEVICE_OBJECT FdoDevice)
491 {
492     DPRINT1("USBPORT_StopDevice: UNIMPLEMENTED. FIXME\n");
493     DbgBreakPoint();
494     return STATUS_SUCCESS;
495 }
496 
497 NTSTATUS
498 NTAPI
499 USBPORT_StartDevice(IN PDEVICE_OBJECT FdoDevice,
500                     IN PUSBPORT_RESOURCES UsbPortResources)
501 {
502     PUSBPORT_DEVICE_EXTENSION FdoExtension;
503     PUSBPORT_REGISTRATION_PACKET Packet;
504     NTSTATUS Status;
505     PCI_COMMON_CONFIG PciConfig;
506     ULONG BytesRead;
507     DEVICE_DESCRIPTION DeviceDescription;
508     PDMA_ADAPTER DmaAdapter = NULL;
509     ULONG MiniPortStatus;
510     PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer;
511     ULONG ResultLength;
512     ULONG DisableSelectiveSuspend = 0;
513     ULONG DisableCcDetect = 0;
514     ULONG IdleEpSupport = 0;
515     ULONG IdleEpSupportEx = 0;
516     ULONG SoftRetry = 0;
517     ULONG Limit2GB = 0;
518     ULONG TotalBusBandwidth = 0;
519     BOOLEAN IsCompanion = FALSE;
520     ULONG LegacyBIOS;
521     ULONG MiniportFlags;
522     ULONG ix;
523 
524     DPRINT("USBPORT_StartDevice: FdoDevice - %p, UsbPortResources - %p\n",
525            FdoDevice,
526            UsbPortResources);
527 
528     FdoExtension = FdoDevice->DeviceExtension;
529     Packet = &FdoExtension->MiniPortInterface->Packet;
530 
531     Status = USBPORT_QueryPciBusInterface(FdoDevice);
532     if (!NT_SUCCESS(Status))
533         goto ExitWithError;
534 
535     BytesRead = (*FdoExtension->BusInterface.GetBusData)(FdoExtension->BusInterface.Context,
536                                                          PCI_WHICHSPACE_CONFIG,
537                                                          &PciConfig,
538                                                          0,
539                                                          PCI_COMMON_HDR_LENGTH);
540 
541     if (BytesRead != PCI_COMMON_HDR_LENGTH)
542     {
543         DPRINT1("USBPORT_StartDevice: Failed to get pci config information!\n");
544         goto ExitWithError;
545     }
546 
547     FdoExtension->VendorID = PciConfig.VendorID;
548     FdoExtension->DeviceID = PciConfig.DeviceID;
549     FdoExtension->RevisionID = PciConfig.RevisionID;
550     FdoExtension->ProgIf = PciConfig.ProgIf;
551     FdoExtension->SubClass = PciConfig.SubClass;
552     FdoExtension->BaseClass = PciConfig.BaseClass;
553 
554     RtlZeroMemory(&DeviceDescription, sizeof(DeviceDescription));
555 
556     DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
557     DeviceDescription.Master = TRUE;
558     DeviceDescription.ScatterGather = TRUE;
559     DeviceDescription.Dma32BitAddresses = TRUE;
560     DeviceDescription.InterfaceType = PCIBus;
561     DeviceDescription.DmaWidth = Width32Bits;
562     DeviceDescription.DmaSpeed = Compatible;
563     DeviceDescription.MaximumLength = MAXULONG;
564 
565     DmaAdapter = IoGetDmaAdapter(FdoExtension->CommonExtension.LowerPdoDevice,
566                                  &DeviceDescription,
567                                  &FdoExtension->NumberMapRegs);
568 
569     FdoExtension->DmaAdapter = DmaAdapter;
570 
571     if (!DmaAdapter)
572     {
573         DPRINT1("USBPORT_StartDevice: Failed to get DmaAdapter!\n");
574         Status = STATUS_INSUFFICIENT_RESOURCES;
575         goto ExitWithError;
576     }
577 
578     Status = USBPORT_CreateWorkerThread(FdoDevice);
579     if (!NT_SUCCESS(Status))
580         goto ExitWithError;
581 
582     Status = USBPORT_QueryCapabilities(FdoDevice, &FdoExtension->Capabilities);
583     if (!NT_SUCCESS(Status))
584         goto ExitWithError;
585 
586     FdoExtension->PciDeviceNumber = FdoExtension->Capabilities.Address >> 16;
587     FdoExtension->PciFunctionNumber = FdoExtension->Capabilities.Address & 0xFFFF;
588 
589     Status = IoGetDeviceProperty(FdoExtension->CommonExtension.LowerPdoDevice,
590                                  DevicePropertyBusNumber,
591                                  sizeof(ULONG),
592                                  &FdoExtension->BusNumber,
593                                  &ResultLength);
594 
595     if (!NT_SUCCESS(Status))
596         goto ExitWithError;
597 
598     KeInitializeSpinLock(&FdoExtension->EndpointListSpinLock);
599     KeInitializeSpinLock(&FdoExtension->EpStateChangeSpinLock);
600     KeInitializeSpinLock(&FdoExtension->EndpointClosedSpinLock);
601     KeInitializeSpinLock(&FdoExtension->DeviceHandleSpinLock);
602     KeInitializeSpinLock(&FdoExtension->IdleIoCsqSpinLock);
603     KeInitializeSpinLock(&FdoExtension->BadRequestIoCsqSpinLock);
604     KeInitializeSpinLock(&FdoExtension->MapTransferSpinLock);
605     KeInitializeSpinLock(&FdoExtension->FlushTransferSpinLock);
606     KeInitializeSpinLock(&FdoExtension->FlushPendingTransferSpinLock);
607     KeInitializeSpinLock(&FdoExtension->DoneTransferSpinLock);
608     KeInitializeSpinLock(&FdoExtension->WorkerThreadEventSpinLock);
609     KeInitializeSpinLock(&FdoExtension->MiniportSpinLock);
610     KeInitializeSpinLock(&FdoExtension->TimerFlagsSpinLock);
611     KeInitializeSpinLock(&FdoExtension->PowerWakeSpinLock);
612     KeInitializeSpinLock(&FdoExtension->SetPowerD0SpinLock);
613     KeInitializeSpinLock(&FdoExtension->RootHubCallbackSpinLock);
614     KeInitializeSpinLock(&FdoExtension->TtSpinLock);
615 
616     KeInitializeDpc(&FdoExtension->IsrDpc, USBPORT_IsrDpc, FdoDevice);
617 
618     KeInitializeDpc(&FdoExtension->TransferFlushDpc,
619                     USBPORT_TransferFlushDpc,
620                     FdoDevice);
621 
622     KeInitializeDpc(&FdoExtension->WorkerRequestDpc,
623                     USBPORT_WorkerRequestDpc,
624                     FdoDevice);
625 
626     KeInitializeDpc(&FdoExtension->HcWakeDpc,
627                     USBPORT_HcWakeDpc,
628                     FdoDevice);
629 
630     IoCsqInitialize(&FdoExtension->IdleIoCsq,
631                     USBPORT_InsertIdleIrp,
632                     USBPORT_RemoveIdleIrp,
633                     USBPORT_PeekNextIdleIrp,
634                     USBPORT_AcquireIdleLock,
635                     USBPORT_ReleaseIdleLock,
636                     USBPORT_CompleteCanceledIdleIrp);
637 
638     IoCsqInitialize(&FdoExtension->BadRequestIoCsq,
639                     USBPORT_InsertBadRequest,
640                     USBPORT_RemoveBadRequest,
641                     USBPORT_PeekNextBadRequest,
642                     USBPORT_AcquireBadRequestLock,
643                     USBPORT_ReleaseBadRequestLock,
644                     USBPORT_CompleteCanceledBadRequest);
645 
646     FdoExtension->IsrDpcCounter = -1;
647     FdoExtension->IsrDpcHandlerCounter = -1;
648     FdoExtension->IdleLockCounter = -1;
649     FdoExtension->BadRequestLockCounter = -1;
650     FdoExtension->ChirpRootPortLock = -1;
651 
652     FdoExtension->RHInitCallBackLock = 0;
653 
654     FdoExtension->UsbAddressBitMap[0] = 1;
655     FdoExtension->UsbAddressBitMap[1] = 0;
656     FdoExtension->UsbAddressBitMap[2] = 0;
657     FdoExtension->UsbAddressBitMap[3] = 0;
658 
659     USBPORT_GetDefaultBIOSx(FdoDevice,
660                             &FdoExtension->UsbBIOSx,
661                             &DisableSelectiveSuspend,
662                             &DisableCcDetect,
663                             &IdleEpSupport,
664                             &IdleEpSupportEx,
665                             &SoftRetry);
666 
667     if (DisableSelectiveSuspend)
668         FdoExtension->Flags |= USBPORT_FLAG_BIOS_DISABLE_SS;
669 
670     if (!DisableSelectiveSuspend &&
671         USBPORT_IsSelectiveSuspendEnabled(FdoDevice))
672     {
673         FdoExtension->Flags |= USBPORT_FLAG_SELECTIVE_SUSPEND;
674     }
675 
676     MiniportFlags = Packet->MiniPortFlags;
677 
678     if (MiniportFlags & USB_MINIPORT_FLAGS_POLLING)
679         FdoExtension->Flags |= USBPORT_FLAG_HC_POLLING;
680 
681     if (MiniportFlags & USB_MINIPORT_FLAGS_WAKE_SUPPORT)
682         FdoExtension->Flags |= USBPORT_FLAG_HC_WAKE_SUPPORT;
683 
684     if (MiniportFlags & USB_MINIPORT_FLAGS_DISABLE_SS)
685         FdoExtension->Flags = (FdoExtension->Flags & ~USBPORT_FLAG_SELECTIVE_SUSPEND) |
686                               USBPORT_FLAG_BIOS_DISABLE_SS;
687 
688     USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
689                                 TRUE,
690                                 REG_DWORD,
691                                 L"EnIdleEndpointSupport",
692                                 &IdleEpSupport,
693                                 sizeof(IdleEpSupport));
694 
695     USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
696                                 TRUE,
697                                 REG_DWORD,
698                                 L"EnIdleEndpointSupportEx",
699                                 &IdleEpSupportEx,
700                                 sizeof(IdleEpSupportEx));
701 
702     USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
703                                 TRUE,
704                                 REG_DWORD,
705                                 L"EnSoftRetry",
706                                 &SoftRetry,
707                                 sizeof(SoftRetry));
708 
709     USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
710                                         FdoExtension->CommonExtension.LowerPdoDevice,
711                                         TRUE,
712                                         L"CommonBuffer2GBLimit",
713                                         sizeof(L"CommonBuffer2GBLimit"),
714                                         &Limit2GB,
715                                         sizeof(Limit2GB));
716 
717     FdoExtension->CommonBufferLimit = (Limit2GB != 0);
718 
719     if (FdoExtension->BaseClass == PCI_CLASS_SERIAL_BUS_CTLR &&
720         FdoExtension->SubClass == PCI_SUBCLASS_SB_USB  &&
721         FdoExtension->ProgIf < PCI_INTERFACE_USB_ID_EHCI)
722     {
723         Status = USBPORT_IsCompanionController(FdoDevice, &IsCompanion);
724 
725         if (!NT_SUCCESS(Status))
726         {
727             if (IsCompanion)
728             {
729                 FdoExtension->Flags |= USBPORT_FLAG_COMPANION_HC;
730             }
731             else
732             {
733                 FdoExtension->Flags &= ~USBPORT_FLAG_COMPANION_HC;
734             }
735         }
736     }
737 
738     if (DisableCcDetect)
739     {
740         FdoExtension->Flags &= ~USBPORT_FLAG_COMPANION_HC;
741     }
742 
743     TotalBusBandwidth = Packet->MiniPortBusBandwidth;
744     FdoExtension->TotalBusBandwidth = TotalBusBandwidth;
745 
746     USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
747                                         FdoExtension->CommonExtension.LowerPdoDevice,
748                                         TRUE,
749                                         L"TotalBusBandwidth",
750                                         sizeof(L"TotalBusBandwidth"),
751                                         &TotalBusBandwidth,
752                                         sizeof(TotalBusBandwidth));
753 
754     if (TotalBusBandwidth != FdoExtension->TotalBusBandwidth)
755     {
756         FdoExtension->TotalBusBandwidth = TotalBusBandwidth;
757     }
758 
759     for (ix = 0; ix < USB2_FRAMES; ix++)
760     {
761         FdoExtension->Bandwidth[ix] = FdoExtension->TotalBusBandwidth -
762                                       FdoExtension->TotalBusBandwidth / 10;
763     }
764 
765     FdoExtension->ActiveIrpTable = ExAllocatePoolWithTag(NonPagedPool,
766                                                          sizeof(USBPORT_IRP_TABLE),
767                                                          USB_PORT_TAG);
768 
769     if (!FdoExtension->ActiveIrpTable)
770     {
771         DPRINT1("USBPORT_StartDevice: Allocate ActiveIrpTable failed!\n");
772         goto ExitWithError;
773     }
774 
775     RtlZeroMemory(FdoExtension->ActiveIrpTable, sizeof(USBPORT_IRP_TABLE));
776 
777     FdoExtension->PendingIrpTable = ExAllocatePoolWithTag(NonPagedPool,
778                                                           sizeof(USBPORT_IRP_TABLE),
779                                                           USB_PORT_TAG);
780 
781     if (!FdoExtension->PendingIrpTable)
782     {
783         DPRINT1("USBPORT_StartDevice: Allocate PendingIrpTable failed!\n");
784         goto ExitWithError;
785     }
786 
787     RtlZeroMemory(FdoExtension->PendingIrpTable, sizeof(USBPORT_IRP_TABLE));
788 
789     Status = IoConnectInterrupt(&FdoExtension->InterruptObject,
790                                 USBPORT_InterruptService,
791                                 (PVOID)FdoDevice,
792                                 0,
793                                 UsbPortResources->InterruptVector,
794                                 UsbPortResources->InterruptLevel,
795                                 UsbPortResources->InterruptLevel,
796                                 UsbPortResources->InterruptMode,
797                                 UsbPortResources->ShareVector,
798                                 UsbPortResources->InterruptAffinity,
799                                 0);
800 
801 
802     if (!NT_SUCCESS(Status))
803     {
804         DPRINT1("USBPORT_StartDevice: IoConnectInterrupt failed!\n");
805         goto ExitWithError;
806     }
807 
808     FdoExtension->Flags &= ~USBPORT_FLAG_INT_CONNECTED;
809 
810     if (Packet->MiniPortExtensionSize)
811     {
812         RtlZeroMemory(FdoExtension->MiniPortExt, Packet->MiniPortExtensionSize);
813     }
814 
815     if (Packet->MiniPortResourcesSize)
816     {
817         HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice,
818                                                     Packet->MiniPortResourcesSize);
819 
820         if (!HeaderBuffer)
821         {
822             DPRINT1("USBPORT_StartDevice: Failed to AllocateCommonBuffer!\n");
823             Status = STATUS_INSUFFICIENT_RESOURCES;
824             goto ExitWithError;
825         }
826 
827         UsbPortResources->StartVA = HeaderBuffer->VirtualAddress;
828         UsbPortResources->StartPA = HeaderBuffer->PhysicalAddress;
829 
830         FdoExtension->MiniPortCommonBuffer = HeaderBuffer;
831     }
832     else
833     {
834         FdoExtension->MiniPortCommonBuffer = NULL;
835     }
836 
837     MiniPortStatus = Packet->StartController(FdoExtension->MiniPortExt,
838                                              UsbPortResources);
839 
840     if (UsbPortResources->LegacySupport)
841     {
842         FdoExtension->Flags |= USBPORT_FLAG_LEGACY_SUPPORT;
843         LegacyBIOS = 1;
844     }
845     else
846     {
847         LegacyBIOS = 0;
848     }
849 
850     USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
851                                 FALSE,
852                                 REG_DWORD,
853                                 L"DetectedLegacyBIOS",
854                                 &LegacyBIOS,
855                                 sizeof(LegacyBIOS));
856 
857     if (MiniPortStatus)
858     {
859         DPRINT1("USBPORT_StartDevice: Failed to Start MiniPort. MiniPortStatus - %x\n",
860                 MiniPortStatus);
861 
862         if (FdoExtension->Flags & USBPORT_FLAG_INT_CONNECTED)
863         {
864             IoDisconnectInterrupt(FdoExtension->InterruptObject);
865             FdoExtension->Flags &= ~USBPORT_FLAG_INT_CONNECTED;
866         }
867 
868         if (FdoExtension->MiniPortCommonBuffer)
869         {
870             USBPORT_FreeCommonBuffer(FdoDevice, FdoExtension->MiniPortCommonBuffer);
871             FdoExtension->MiniPortCommonBuffer = NULL;
872         }
873 
874         goto ExitWithError;
875     }
876     else
877     {
878         FdoExtension->MiniPortFlags |= USBPORT_MPFLAG_INTERRUPTS_ENABLED;
879         USBPORT_MiniportInterrupts(FdoDevice, TRUE);
880     }
881 
882     FdoExtension->TimerValue = 500;
883     USBPORT_StartTimer((PVOID)FdoDevice, 500);
884 
885     Status = USBPORT_RegisterDeviceInterface(FdoExtension->CommonExtension.LowerPdoDevice,
886                                              FdoDevice,
887                                              &GUID_DEVINTERFACE_USB_HOST_CONTROLLER,
888                                              TRUE);
889 
890     if (!NT_SUCCESS(Status))
891     {
892         DPRINT1("USBPORT_StartDevice: RegisterDeviceInterface failed!\n");
893         goto ExitWithError;
894     }
895 
896     USBPORT_CreateLegacySymbolicLink(FdoDevice);
897 
898     FdoExtension->Flags |= USBPORT_FLAG_HC_STARTED;
899 
900     DPRINT("USBPORT_StartDevice: Exit Status - %p\n", Status);
901     return Status;
902 
903 ExitWithError:
904     USBPORT_StopDevice(FdoDevice);
905 
906     DPRINT1("USBPORT_StartDevice: ExitWithError Status - %lx\n", Status);
907     return Status;
908 }
909 
910 NTSTATUS
911 NTAPI
912 USBPORT_ParseResources(IN PDEVICE_OBJECT FdoDevice,
913                        IN PIRP Irp,
914                        IN PUSBPORT_RESOURCES UsbPortResources)
915 {
916     PCM_RESOURCE_LIST AllocatedResourcesTranslated;
917     PCM_PARTIAL_RESOURCE_LIST ResourceList;
918     PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
919     PCM_PARTIAL_RESOURCE_DESCRIPTOR PortDescriptor = NULL;
920     PCM_PARTIAL_RESOURCE_DESCRIPTOR MemoryDescriptor = NULL;
921     PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDescriptor = NULL;
922     PIO_STACK_LOCATION IoStack;
923     ULONG ix;
924     NTSTATUS Status = STATUS_SUCCESS;
925 
926     DPRINT("USBPORT_ParseResources: ... \n");
927 
928     IoStack = IoGetCurrentIrpStackLocation(Irp);
929     AllocatedResourcesTranslated = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
930 
931     if (AllocatedResourcesTranslated)
932     {
933         RtlZeroMemory(UsbPortResources, sizeof(USBPORT_RESOURCES));
934 
935         ResourceList = &AllocatedResourcesTranslated->List[0].PartialResourceList;
936 
937         PartialDescriptor = &ResourceList->PartialDescriptors[0];
938 
939         for (ix = 0; ix < ResourceList->Count; ++ix)
940         {
941             if (PartialDescriptor->Type == CmResourceTypePort)
942             {
943                 if (!PortDescriptor)
944                     PortDescriptor = PartialDescriptor;
945             }
946             else if (PartialDescriptor->Type == CmResourceTypeInterrupt)
947             {
948                 if (!InterruptDescriptor)
949                     InterruptDescriptor = PartialDescriptor;
950             }
951             else if (PartialDescriptor->Type == CmResourceTypeMemory)
952             {
953                 if (!MemoryDescriptor)
954                     MemoryDescriptor = PartialDescriptor;
955             }
956 
957             PartialDescriptor += 1;
958         }
959 
960         if (PortDescriptor)
961         {
962             if (PortDescriptor->Flags & CM_RESOURCE_PORT_IO)
963             {
964                 UsbPortResources->ResourceBase = (PVOID)(ULONG_PTR)PortDescriptor->u.Port.Start.QuadPart;
965             }
966             else
967             {
968                 UsbPortResources->ResourceBase = MmMapIoSpace(PortDescriptor->u.Port.Start,
969                                                               PortDescriptor->u.Port.Length,
970                                                               0);
971             }
972 
973             UsbPortResources->IoSpaceLength = PortDescriptor->u.Port.Length;
974 
975             if (UsbPortResources->ResourceBase)
976             {
977                 UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_PORT;
978             }
979             else
980             {
981                 Status = STATUS_NONE_MAPPED;
982             }
983         }
984 
985         if (MemoryDescriptor && NT_SUCCESS(Status))
986         {
987             UsbPortResources->IoSpaceLength = MemoryDescriptor->u.Memory.Length;
988 
989             UsbPortResources->ResourceBase = MmMapIoSpace(MemoryDescriptor->u.Memory.Start,
990                                                           MemoryDescriptor->u.Memory.Length,
991                                                           0);
992 
993             if (UsbPortResources->ResourceBase)
994             {
995                 UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_MEMORY;
996             }
997             else
998             {
999                 Status = STATUS_NONE_MAPPED;
1000             }
1001         }
1002 
1003         if (InterruptDescriptor && NT_SUCCESS(Status))
1004         {
1005             UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_INTERRUPT;
1006 
1007             UsbPortResources->InterruptVector = InterruptDescriptor->u.Interrupt.Vector;
1008             UsbPortResources->InterruptLevel = InterruptDescriptor->u.Interrupt.Level;
1009             UsbPortResources->InterruptAffinity = InterruptDescriptor->u.Interrupt.Affinity;
1010 
1011             UsbPortResources->ShareVector = InterruptDescriptor->ShareDisposition ==
1012                                             CmResourceShareShared;
1013 
1014             UsbPortResources->InterruptMode = InterruptDescriptor->Flags ==
1015                                               CM_RESOURCE_INTERRUPT_LATCHED;
1016         }
1017     }
1018     else
1019     {
1020         Status = STATUS_NONE_MAPPED;
1021     }
1022 
1023     return Status;
1024 }
1025 
1026 NTSTATUS
1027 NTAPI
1028 USBPORT_CreatePdo(IN PDEVICE_OBJECT FdoDevice,
1029                   OUT PDEVICE_OBJECT *RootHubPdo)
1030 {
1031     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1032     PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
1033     UNICODE_STRING DeviceName;
1034     ULONG DeviceNumber = 0;
1035     PDEVICE_OBJECT DeviceObject = NULL;
1036     WCHAR CharDeviceName[64];
1037     NTSTATUS Status = STATUS_SUCCESS;
1038 
1039     DPRINT("USBPORT_CreatePdo: FdoDevice - %p, RootHubPdo - %p\n",
1040            FdoDevice,
1041            RootHubPdo);
1042 
1043     FdoExtension = FdoDevice->DeviceExtension;
1044 
1045     do
1046     {
1047         RtlStringCbPrintfW(CharDeviceName,
1048                            sizeof(CharDeviceName),
1049                            L"\\Device\\USBPDO-%d",
1050                            DeviceNumber);
1051 
1052         RtlInitUnicodeString(&DeviceName, CharDeviceName);
1053 
1054         DPRINT("USBPORT_CreatePdo: DeviceName - %wZ\n", &DeviceName);
1055 
1056         Status = IoCreateDevice(FdoExtension->MiniPortInterface->DriverObject,
1057                                 sizeof(USBPORT_RHDEVICE_EXTENSION),
1058                                 &DeviceName,
1059                                 FILE_DEVICE_BUS_EXTENDER,
1060                                 0,
1061                                 FALSE,
1062                                 &DeviceObject);
1063 
1064         ++DeviceNumber;
1065     }
1066     while (Status == STATUS_OBJECT_NAME_COLLISION);
1067 
1068     if (!NT_SUCCESS(Status))
1069     {
1070         *RootHubPdo = NULL;
1071         DPRINT1("USBPORT_CreatePdo: Filed create HubPdo!\n");
1072         return Status;
1073     }
1074 
1075     if (DeviceObject)
1076     {
1077         PdoExtension = DeviceObject->DeviceExtension;
1078 
1079         RtlZeroMemory(PdoExtension, sizeof(USBPORT_RHDEVICE_EXTENSION));
1080 
1081         PdoExtension->CommonExtension.SelfDevice = DeviceObject;
1082         PdoExtension->CommonExtension.IsPDO = TRUE;
1083 
1084         PdoExtension->FdoDevice = FdoDevice;
1085         PdoExtension->PdoNameNumber = DeviceNumber;
1086 
1087         USBPORT_AdjustDeviceCapabilities(FdoDevice, DeviceObject);
1088 
1089         DeviceObject->StackSize = FdoDevice->StackSize;
1090 
1091         DeviceObject->Flags |= DO_POWER_PAGABLE;
1092         DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1093     }
1094     else
1095     {
1096         Status = STATUS_UNSUCCESSFUL;
1097     }
1098 
1099     if (!NT_SUCCESS(Status))
1100         *RootHubPdo = NULL;
1101     else
1102         *RootHubPdo = DeviceObject;
1103 
1104     DPRINT("USBPORT_CreatePdo: HubPdo - %p\n", DeviceObject);
1105     return Status;
1106 }
1107 
1108 NTSTATUS
1109 NTAPI
1110 USBPORT_FdoPnP(IN PDEVICE_OBJECT FdoDevice,
1111                IN PIRP Irp)
1112 {
1113     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1114     PUSBPORT_COMMON_DEVICE_EXTENSION FdoCommonExtension;
1115     PUSBPORT_REGISTRATION_PACKET Packet;
1116     PUSBPORT_RESOURCES UsbPortResources;
1117     PIO_STACK_LOCATION IoStack;
1118     UCHAR Minor;
1119     KEVENT Event;
1120     NTSTATUS Status;
1121     DEVICE_RELATION_TYPE RelationType;
1122     PDEVICE_RELATIONS DeviceRelations;
1123     PDEVICE_OBJECT RootHubPdo;
1124 
1125     FdoExtension = FdoDevice->DeviceExtension;
1126     FdoCommonExtension = &FdoExtension->CommonExtension;
1127     UsbPortResources = &FdoExtension->UsbPortResources;
1128     Packet = &FdoExtension->MiniPortInterface->Packet;
1129 
1130     IoStack = IoGetCurrentIrpStackLocation(Irp);
1131     Minor = IoStack->MinorFunction;
1132 
1133     DPRINT("USBPORT_FdoPnP: FdoDevice - %p, Minor - %x\n", FdoDevice, Minor);
1134 
1135     RelationType = IoStack->Parameters.QueryDeviceRelations.Type;
1136 
1137     switch (Minor)
1138     {
1139         case IRP_MN_START_DEVICE:
1140             DPRINT("IRP_MN_START_DEVICE\n");
1141 
1142             KeInitializeEvent(&Event, NotificationEvent, FALSE);
1143 
1144             IoCopyCurrentIrpStackLocationToNext(Irp);
1145 
1146             IoSetCompletionRoutine(Irp,
1147                                    USBPORT_FdoStartCompletion,
1148                                    &Event,
1149                                    TRUE,
1150                                    TRUE,
1151                                    TRUE);
1152 
1153             Status = IoCallDriver(FdoCommonExtension->LowerDevice,
1154                                   Irp);
1155 
1156             if (Status == STATUS_PENDING)
1157             {
1158                 KeWaitForSingleObject(&Event,
1159                                       Suspended,
1160                                       KernelMode,
1161                                       FALSE,
1162                                       NULL);
1163 
1164                 Status = Irp->IoStatus.Status;
1165             }
1166 
1167             if (!NT_SUCCESS(Status))
1168             {
1169                 goto Exit;
1170             }
1171 
1172             Status = USBPORT_ParseResources(FdoDevice,
1173                                             Irp,
1174                                             UsbPortResources);
1175 
1176             if (!NT_SUCCESS(Status))
1177             {
1178                 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STOPPED;
1179                 goto Exit;
1180             }
1181 
1182             Status = USBPORT_StartDevice(FdoDevice, UsbPortResources);
1183 
1184             if (!NT_SUCCESS(Status))
1185             {
1186                 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STOPPED;
1187                 goto Exit;
1188             }
1189 
1190             FdoCommonExtension->PnpStateFlags &= ~USBPORT_PNP_STATE_NOT_INIT;
1191             FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STARTED;
1192 
1193             FdoCommonExtension->DevicePowerState = PowerDeviceD0;
1194 
1195             if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1196             {
1197                 USBPORT_AddUSB2Fdo(FdoDevice);
1198             }
1199             else
1200             {
1201                 USBPORT_AddUSB1Fdo(FdoDevice);
1202             }
1203 
1204 Exit:
1205             Irp->IoStatus.Status = Status;
1206             IoCompleteRequest(Irp, IO_NO_INCREMENT);
1207             return Status;
1208 
1209         case IRP_MN_QUERY_REMOVE_DEVICE:
1210             DPRINT("IRP_MN_QUERY_REMOVE_DEVICE\n");
1211             if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1212             {
1213                 DPRINT1("USBPORT_FdoPnP: Haction registry write FIXME\n");
1214             }
1215 
1216             Irp->IoStatus.Status = STATUS_SUCCESS;
1217             goto ForwardIrp;
1218 
1219         case IRP_MN_REMOVE_DEVICE:
1220             DPRINT("USBPORT_FdoPnP: IRP_MN_REMOVE_DEVICE\n");
1221             FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_FAILED;
1222 
1223             if (FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_STARTED &&
1224                !(FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_NOT_INIT))
1225             {
1226                 DPRINT1("USBPORT_FdoPnP: stop fdo FIXME\n");
1227                 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_NOT_INIT;
1228             }
1229 
1230             Irp->IoStatus.Status = STATUS_SUCCESS;
1231             IoSkipCurrentIrpStackLocation(Irp);
1232             Status = IoCallDriver(FdoCommonExtension->LowerDevice, Irp);
1233 
1234             IoDetachDevice(FdoCommonExtension->LowerDevice);
1235 
1236             RootHubPdo = FdoExtension->RootHubPdo;
1237 
1238             IoDeleteDevice(FdoDevice);
1239 
1240             if (RootHubPdo)
1241             {
1242                 IoDeleteDevice(RootHubPdo);
1243             }
1244 
1245             return Status;
1246 
1247         case IRP_MN_CANCEL_REMOVE_DEVICE:
1248             DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n");
1249             Irp->IoStatus.Status = STATUS_SUCCESS;
1250             goto ForwardIrp;
1251 
1252         case IRP_MN_STOP_DEVICE:
1253             DPRINT("IRP_MN_STOP_DEVICE\n");
1254             if (FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_STARTED)
1255             {
1256                 DPRINT1("USBPORT_FdoPnP: stop fdo FIXME\n");
1257 
1258                 FdoCommonExtension->PnpStateFlags &= ~USBPORT_PNP_STATE_STARTED;
1259                 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_NOT_INIT;
1260             }
1261 
1262             Irp->IoStatus.Status = STATUS_SUCCESS;
1263             goto ForwardIrp;
1264 
1265         case IRP_MN_QUERY_STOP_DEVICE:
1266             DPRINT("IRP_MN_QUERY_STOP_DEVICE\n");
1267             Irp->IoStatus.Status = STATUS_SUCCESS;
1268             goto ForwardIrp;
1269 
1270         case IRP_MN_CANCEL_STOP_DEVICE:
1271             DPRINT("IRP_MN_CANCEL_STOP_DEVICE\n");
1272             Irp->IoStatus.Status = STATUS_SUCCESS;
1273             goto ForwardIrp;
1274 
1275         case IRP_MN_QUERY_DEVICE_RELATIONS:
1276             DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
1277             if (RelationType == BusRelations)
1278             {
1279                 DeviceRelations = ExAllocatePoolWithTag(PagedPool,
1280                                                         sizeof(DEVICE_RELATIONS),
1281                                                         USB_PORT_TAG);
1282 
1283                 if (!DeviceRelations)
1284                 {
1285                     Status = STATUS_INSUFFICIENT_RESOURCES;
1286                     Irp->IoStatus.Status = Status;
1287                     IoCompleteRequest(Irp, IO_NO_INCREMENT);
1288                     return Status;
1289                 }
1290 
1291                 DeviceRelations->Count = 0;
1292                 DeviceRelations->Objects[0] = NULL;
1293 
1294                 if (!FdoExtension->RootHubPdo)
1295                 {
1296                     Status = USBPORT_CreatePdo(FdoDevice,
1297                                                &FdoExtension->RootHubPdo);
1298 
1299                     if (!NT_SUCCESS(Status))
1300                     {
1301                         ExFreePoolWithTag(DeviceRelations, USB_PORT_TAG);
1302                         goto ForwardIrp;
1303                     }
1304                 }
1305                 else
1306                 {
1307                     Status = STATUS_SUCCESS;
1308                 }
1309 
1310                 DeviceRelations->Count = 1;
1311                 DeviceRelations->Objects[0] = FdoExtension->RootHubPdo;
1312 
1313                 ObReferenceObject(FdoExtension->RootHubPdo);
1314                 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
1315             }
1316             else
1317             {
1318                 if (RelationType == RemovalRelations)
1319                 {
1320                     DPRINT1("USBPORT_FdoPnP: FIXME IRP_MN_QUERY_DEVICE_RELATIONS/RemovalRelations\n");
1321                 }
1322 
1323                 goto ForwardIrp;
1324             }
1325 
1326             Irp->IoStatus.Status = Status;
1327             goto ForwardIrp;
1328 
1329         case IRP_MN_QUERY_INTERFACE:
1330             DPRINT("IRP_MN_QUERY_INTERFACE\n");
1331             goto ForwardIrp;
1332 
1333         case IRP_MN_QUERY_CAPABILITIES:
1334             DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
1335             goto ForwardIrp;
1336 
1337         case IRP_MN_QUERY_RESOURCES:
1338             DPRINT("IRP_MN_QUERY_RESOURCES\n");
1339             goto ForwardIrp;
1340 
1341         case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1342             DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1343             goto ForwardIrp;
1344 
1345         case IRP_MN_QUERY_DEVICE_TEXT:
1346             DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n");
1347             goto ForwardIrp;
1348 
1349         case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1350             DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1351             goto ForwardIrp;
1352 
1353         case IRP_MN_READ_CONFIG:
1354             DPRINT("IRP_MN_READ_CONFIG\n");
1355             goto ForwardIrp;
1356 
1357         case IRP_MN_WRITE_CONFIG:
1358             DPRINT("IRP_MN_WRITE_CONFIG\n");
1359             goto ForwardIrp;
1360 
1361         case IRP_MN_EJECT:
1362             DPRINT("IRP_MN_EJECT\n");
1363             goto ForwardIrp;
1364 
1365         case IRP_MN_SET_LOCK:
1366             DPRINT("IRP_MN_SET_LOCK\n");
1367             goto ForwardIrp;
1368 
1369         case IRP_MN_QUERY_ID:
1370             DPRINT("IRP_MN_QUERY_ID\n");
1371             goto ForwardIrp;
1372 
1373         case IRP_MN_QUERY_PNP_DEVICE_STATE:
1374             DPRINT("IRP_MN_QUERY_PNP_DEVICE_STATE\n");
1375             goto ForwardIrp;
1376 
1377         case IRP_MN_QUERY_BUS_INFORMATION:
1378             DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
1379             goto ForwardIrp;
1380 
1381         case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1382             DPRINT("IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
1383             goto ForwardIrp;
1384 
1385         case IRP_MN_SURPRISE_REMOVAL:
1386             DPRINT1("IRP_MN_SURPRISE_REMOVAL\n");
1387             if (!(FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_FAILED))
1388             {
1389                 USBPORT_InvalidateControllerHandler(FdoDevice,
1390                                                     USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE);
1391             }
1392             goto ForwardIrp;
1393 
1394         default:
1395             DPRINT("unknown IRP_MN_???\n");
1396 ForwardIrp:
1397             /* forward irp to next device object */
1398             IoSkipCurrentIrpStackLocation(Irp);
1399             break;
1400     }
1401 
1402     return IoCallDriver(FdoCommonExtension->LowerDevice, Irp);
1403 }
1404 
1405 PVOID
1406 NTAPI
1407 USBPORT_GetDeviceHwIds(IN PDEVICE_OBJECT FdoDevice,
1408                        IN USHORT VendorID,
1409                        IN USHORT DeviceID,
1410                        IN USHORT RevisionID)
1411 {
1412     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1413     PUSBPORT_REGISTRATION_PACKET Packet;
1414     PVOID Id;
1415     WCHAR Buffer[300] = {0};
1416     SIZE_T Length = 0;
1417     size_t Remaining = sizeof(Buffer);
1418     PWCHAR EndBuffer;
1419 
1420     FdoExtension = FdoDevice->DeviceExtension;
1421     Packet = &FdoExtension->MiniPortInterface->Packet;
1422 
1423     DPRINT("USBPORT_GetDeviceHwIds: FdoDevice - %p, Packet->MiniPortFlags - %p\n",
1424            FdoDevice,
1425            Packet->MiniPortFlags);
1426 
1427     if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1428     {
1429         RtlStringCbPrintfExW(Buffer,
1430                              Remaining,
1431                              &EndBuffer,
1432                              &Remaining,
1433                              0,
1434                              L"USB\\ROOT_HUB20&VID%04x&PID%04x&REV%04x",
1435                              VendorID,
1436                              DeviceID,
1437                              RevisionID);
1438 
1439         EndBuffer++;
1440         Remaining -= sizeof(UNICODE_NULL);
1441 
1442         RtlStringCbPrintfExW(EndBuffer,
1443                              Remaining,
1444                              &EndBuffer,
1445                              &Remaining,
1446                              0,
1447                              L"USB\\ROOT_HUB20&VID%04x&PID%04x",
1448                              VendorID,
1449                              DeviceID);
1450 
1451         EndBuffer++;
1452         Remaining -= sizeof(UNICODE_NULL);
1453 
1454         RtlStringCbPrintfExW(EndBuffer,
1455                              Remaining,
1456                              NULL,
1457                              &Remaining,
1458                              0,
1459                              L"USB\\ROOT_HUB20");
1460     }
1461     else
1462     {
1463         RtlStringCbPrintfExW(Buffer,
1464                              Remaining,
1465                              &EndBuffer,
1466                              &Remaining,
1467                              0,
1468                              L"USB\\ROOT_HUB&VID%04x&PID%04x&REV%04x",
1469                              VendorID,
1470                              DeviceID,
1471                              RevisionID);
1472 
1473         EndBuffer++;
1474         Remaining -= sizeof(UNICODE_NULL);
1475 
1476         RtlStringCbPrintfExW(EndBuffer,
1477                              Remaining,
1478                              &EndBuffer,
1479                              &Remaining,
1480                              0,
1481                              L"USB\\ROOT_HUB&VID%04x&PID%04x",
1482                              VendorID,
1483                              DeviceID);
1484 
1485         EndBuffer++;
1486         Remaining -= sizeof(UNICODE_NULL);
1487 
1488         RtlStringCbPrintfExW(EndBuffer,
1489                              Remaining,
1490                              NULL,
1491                              &Remaining,
1492                              0,
1493                              L"USB\\ROOT_HUB");
1494     }
1495 
1496     Length = (sizeof(Buffer) - Remaining + 2 * sizeof(UNICODE_NULL));
1497 
1498      /* for debug only */
1499     if (FALSE)
1500     {
1501         DPRINT("Hardware IDs:\n");
1502         USBPORT_DumpingIDs(Buffer);
1503     }
1504 
1505     Id = ExAllocatePoolWithTag(PagedPool, Length, USB_PORT_TAG);
1506 
1507     if (!Id)
1508         return NULL;
1509 
1510     RtlMoveMemory(Id, Buffer, Length);
1511 
1512     return Id;
1513 }
1514 
1515 NTSTATUS
1516 NTAPI
1517 USBPORT_PdoPnP(IN PDEVICE_OBJECT PdoDevice,
1518                IN PIRP Irp)
1519 {
1520     PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
1521     PUSBPORT_COMMON_DEVICE_EXTENSION PdoCommonExtension;
1522     PDEVICE_OBJECT FdoDevice;
1523     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1524     PIO_STACK_LOCATION IoStack;
1525     UCHAR Minor;
1526     NTSTATUS Status;
1527     PPNP_BUS_INFORMATION BusInformation;
1528     PDEVICE_CAPABILITIES DeviceCapabilities;
1529 
1530     PdoExtension = PdoDevice->DeviceExtension;
1531     PdoCommonExtension = &PdoExtension->CommonExtension;
1532 
1533     FdoDevice = PdoExtension->FdoDevice;
1534     FdoExtension = FdoDevice->DeviceExtension;
1535 
1536     IoStack = IoGetCurrentIrpStackLocation(Irp);
1537     Minor = IoStack->MinorFunction;
1538 
1539     Status = Irp->IoStatus.Status;
1540 
1541     DPRINT("USBPORT_PdoPnP: PdoDevice - %p, Minor - %x\n", PdoDevice, Minor);
1542 
1543     switch (Minor)
1544     {
1545         case IRP_MN_START_DEVICE:
1546             DPRINT("IRP_MN_START_DEVICE\n");
1547 
1548             Status = USBPORT_RootHubCreateDevice(FdoDevice, PdoDevice);
1549 
1550             if (NT_SUCCESS(Status))
1551             {
1552                 Status = USBPORT_RegisterDeviceInterface(PdoDevice,
1553                                                          PdoDevice,
1554                                                          &GUID_DEVINTERFACE_USB_HUB,
1555                                                          TRUE);
1556 
1557                 if (NT_SUCCESS(Status))
1558                 {
1559                     PdoCommonExtension->DevicePowerState = PowerDeviceD0;
1560                     PdoCommonExtension->PnpStateFlags = USBPORT_PNP_STATE_STARTED;
1561                 }
1562             }
1563 
1564             break;
1565 
1566         case IRP_MN_QUERY_REMOVE_DEVICE:
1567             DPRINT("USBPORT_PdoPnP: IRP_MN_QUERY_REMOVE_DEVICE\n");
1568             Status = STATUS_SUCCESS;
1569             break;
1570 
1571         case IRP_MN_REMOVE_DEVICE:
1572             DPRINT1("USBPORT_PdoPnP: IRP_MN_REMOVE_DEVICE UNIMPLEMENTED. FIXME. \n");
1573             //USBPORT_StopRootHub();
1574             Status = STATUS_SUCCESS;
1575             break;
1576 
1577         case IRP_MN_CANCEL_REMOVE_DEVICE:
1578             DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n");
1579             Status = STATUS_SUCCESS;
1580             break;
1581 
1582         case IRP_MN_STOP_DEVICE:
1583             DPRINT1("USBPORT_PdoPnP: IRP_MN_STOP_DEVICE UNIMPLEMENTED. FIXME. \n");
1584             //USBPORT_StopRootHub();
1585             Status = STATUS_SUCCESS;
1586             break;
1587 
1588         case IRP_MN_QUERY_STOP_DEVICE:
1589             DPRINT("IRP_MN_QUERY_STOP_DEVICE\n");
1590             Status = STATUS_SUCCESS;
1591             break;
1592 
1593         case IRP_MN_CANCEL_STOP_DEVICE:
1594             DPRINT("IRP_MN_CANCEL_STOP_DEVICE\n");
1595             Status = STATUS_SUCCESS;
1596             break;
1597 
1598         case IRP_MN_QUERY_DEVICE_RELATIONS:
1599         {
1600             PDEVICE_RELATIONS DeviceRelations;
1601 
1602             DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
1603             if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
1604             {
1605                 break;
1606             }
1607 
1608             DeviceRelations = ExAllocatePoolWithTag(PagedPool,
1609                                                     sizeof(DEVICE_RELATIONS),
1610                                                     USB_PORT_TAG);
1611 
1612             if (!DeviceRelations)
1613             {
1614                 Status = STATUS_INSUFFICIENT_RESOURCES;
1615                 Irp->IoStatus.Information = 0;
1616                 break;
1617             }
1618 
1619             DeviceRelations->Count = 1;
1620             DeviceRelations->Objects[0] = PdoDevice;
1621 
1622             ObReferenceObject(PdoDevice);
1623 
1624             Status = STATUS_SUCCESS;
1625             Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
1626             break;
1627         }
1628 
1629         case IRP_MN_QUERY_INTERFACE:
1630             DPRINT("IRP_MN_QUERY_INTERFACE\n");
1631             Status = USBPORT_PdoQueryInterface(FdoDevice, PdoDevice, Irp);
1632             break;
1633 
1634         case IRP_MN_QUERY_CAPABILITIES:
1635             DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
1636 
1637             DeviceCapabilities = IoStack->Parameters.DeviceCapabilities.Capabilities;
1638 
1639             RtlCopyMemory(DeviceCapabilities,
1640                           &PdoExtension->Capabilities,
1641                           sizeof(DEVICE_CAPABILITIES));
1642 
1643             Status = STATUS_SUCCESS;
1644             break;
1645 
1646         case IRP_MN_QUERY_RESOURCES:
1647             DPRINT("USBPORT_PdoPnP: IRP_MN_QUERY_RESOURCES\n");
1648             break;
1649 
1650         case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1651             DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1652             break;
1653 
1654         case IRP_MN_QUERY_DEVICE_TEXT:
1655             DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n");
1656             break;
1657 
1658         case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1659             DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1660             break;
1661 
1662         case IRP_MN_READ_CONFIG:
1663             DPRINT("IRP_MN_READ_CONFIG\n");
1664             ASSERT(FALSE);
1665             break;
1666 
1667         case IRP_MN_WRITE_CONFIG:
1668             DPRINT("IRP_MN_WRITE_CONFIG\n");
1669             ASSERT(FALSE);
1670             break;
1671 
1672         case IRP_MN_EJECT:
1673             DPRINT("IRP_MN_EJECT\n");
1674             ASSERT(FALSE);
1675             break;
1676 
1677         case IRP_MN_SET_LOCK:
1678             DPRINT("IRP_MN_SET_LOCK\n");
1679             ASSERT(FALSE);
1680             break;
1681 
1682         case IRP_MN_QUERY_ID:
1683         {
1684             ULONG IdType;
1685             LONG Length;
1686             WCHAR Buffer[64] = {0};
1687             PVOID Id;
1688 
1689             Status = STATUS_SUCCESS;
1690             IdType = IoStack->Parameters.QueryId.IdType;
1691 
1692             DPRINT("IRP_MN_QUERY_ID/Type %x\n", IdType);
1693 
1694             if (IdType == BusQueryDeviceID)
1695             {
1696                 PUSBPORT_REGISTRATION_PACKET Packet;
1697                 Packet = &FdoExtension->MiniPortInterface->Packet;
1698 
1699                 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1700                 {
1701                     RtlStringCbPrintfW(Buffer,
1702                                        sizeof(Buffer),
1703                                        L"USB\\ROOT_HUB20");
1704                 }
1705                 else
1706                 {
1707                     RtlStringCbPrintfW(Buffer,
1708                                        sizeof(Buffer),
1709                                        L"USB\\ROOT_HUB");
1710                 }
1711 
1712                 Length = (LONG)(wcslen(Buffer) + 1);
1713 
1714                 Id = ExAllocatePoolWithTag(PagedPool,
1715                                            Length * sizeof(WCHAR),
1716                                            USB_PORT_TAG);
1717 
1718                 if (Id)
1719                 {
1720                     RtlZeroMemory(Id, Length * sizeof(WCHAR));
1721                     RtlStringCbCopyW(Id, Length * sizeof(WCHAR), Buffer);
1722 
1723                     DPRINT("BusQueryDeviceID - %S, TotalLength - %hu\n",
1724                            Id,
1725                            Length);
1726                 }
1727 
1728                 Irp->IoStatus.Information = (ULONG_PTR)Id;
1729                 break;
1730             }
1731 
1732             if (IdType == BusQueryHardwareIDs)
1733             {
1734                 Id = USBPORT_GetDeviceHwIds(FdoDevice,
1735                                             FdoExtension->VendorID,
1736                                             FdoExtension->DeviceID,
1737                                             FdoExtension->RevisionID);
1738 
1739                 Irp->IoStatus.Information = (ULONG_PTR)Id;
1740                 break;
1741             }
1742 
1743             if (IdType == BusQueryCompatibleIDs ||
1744                 IdType == BusQueryInstanceID)
1745             {
1746                 Irp->IoStatus.Information = 0;
1747                 break;
1748             }
1749 
1750             /* IdType == BusQueryDeviceSerialNumber */
1751             Status = Irp->IoStatus.Status;
1752             break;
1753         }
1754 
1755         case IRP_MN_QUERY_PNP_DEVICE_STATE:
1756             DPRINT("IRP_MN_QUERY_PNP_DEVICE_STATE\n");
1757             Status = STATUS_SUCCESS;
1758             break;
1759 
1760         case IRP_MN_QUERY_BUS_INFORMATION:
1761             DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
1762 
1763             /* Allocate buffer for bus information */
1764             BusInformation = ExAllocatePoolWithTag(PagedPool,
1765                                                    sizeof(PNP_BUS_INFORMATION),
1766                                                    USB_PORT_TAG);
1767 
1768             if (!BusInformation)
1769             {
1770                 /* No memory */
1771                 Status = STATUS_INSUFFICIENT_RESOURCES;
1772                 break;
1773             }
1774 
1775             RtlZeroMemory(BusInformation, sizeof(PNP_BUS_INFORMATION));
1776 
1777             /* Copy BUS GUID */
1778             RtlMoveMemory(&BusInformation->BusTypeGuid,
1779                           &GUID_BUS_TYPE_USB,
1780                           sizeof(GUID));
1781 
1782             /* Set bus type */
1783             BusInformation->LegacyBusType = PNPBus;
1784             BusInformation->BusNumber = 0;
1785 
1786             Status = STATUS_SUCCESS;
1787             Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
1788             break;
1789 
1790         case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1791             DPRINT("IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
1792             break;
1793 
1794         case IRP_MN_SURPRISE_REMOVAL:
1795             DPRINT("USBPORT_PdoPnP: IRP_MN_SURPRISE_REMOVAL\n");
1796             Status = STATUS_SUCCESS;
1797             break;
1798 
1799         default:
1800             DPRINT("unknown IRP_MN_???\n");
1801             break;
1802     }
1803 
1804     Irp->IoStatus.Status = Status;
1805     IoCompleteRequest(Irp, IO_NO_INCREMENT);
1806     return Status;
1807 }
1808