xref: /reactos/drivers/storage/port/storport/fdo.c (revision 139a3d66)
1 /*
2  * PROJECT:     ReactOS Storport Driver
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Storport FDO code
5  * COPYRIGHT:   Copyright 2017 Eric Kohl (eric.kohl@reactos.org)
6  */
7 
8 /* INCLUDES *******************************************************************/
9 
10 #include "precomp.h"
11 
12 #define NDEBUG
13 #include <debug.h>
14 
15 
16 /* FUNCTIONS ******************************************************************/
17 
18 static
19 BOOLEAN
20 NTAPI
21 PortFdoInterruptRoutine(
22     _In_ PKINTERRUPT Interrupt,
23     _In_ PVOID ServiceContext)
24 {
25     PFDO_DEVICE_EXTENSION DeviceExtension;
26 
27     DPRINT1("PortFdoInterruptRoutine(%p %p)\n",
28             Interrupt, ServiceContext);
29 
30     DeviceExtension = (PFDO_DEVICE_EXTENSION)ServiceContext;
31 
32     return MiniportHwInterrupt(&DeviceExtension->Miniport);
33 }
34 
35 
36 static
37 NTSTATUS
38 PortFdoConnectInterrupt(
39     _In_ PFDO_DEVICE_EXTENSION DeviceExtension)
40 {
41     ULONG Vector;
42     KIRQL Irql;
43     KINTERRUPT_MODE InterruptMode;
44     BOOLEAN ShareVector;
45     KAFFINITY Affinity;
46     NTSTATUS Status;
47 
48     DPRINT1("PortFdoConnectInterrupt(%p)\n",
49             DeviceExtension);
50 
51     /* No resources, no interrupt. Done! */
52     if (DeviceExtension->AllocatedResources == NULL ||
53         DeviceExtension->TranslatedResources == NULL)
54     {
55         DPRINT1("Checkpoint\n");
56         return STATUS_SUCCESS;
57     }
58 
59     /* Get the interrupt data from the resource list */
60     Status = GetResourceListInterrupt(DeviceExtension,
61                                       &Vector,
62                                       &Irql,
63                                       &InterruptMode,
64                                       &ShareVector,
65                                       &Affinity);
66     if (!NT_SUCCESS(Status))
67     {
68         DPRINT1("GetResourceListInterrupt() failed (Status 0x%08lx)\n", Status);
69         return Status;
70     }
71 
72     DPRINT1("Vector: %lu\n", Vector);
73     DPRINT1("Irql: %lu\n", Irql);
74 
75     DPRINT1("Affinity: 0x%08lx\n", Affinity);
76 
77     /* Connect the interrupt */
78     Status = IoConnectInterrupt(&DeviceExtension->Interrupt,
79                                 PortFdoInterruptRoutine,
80                                 DeviceExtension,
81                                 NULL,
82                                 Vector,
83                                 Irql,
84                                 Irql,
85                                 InterruptMode,
86                                 ShareVector,
87                                 Affinity,
88                                 FALSE);
89     if (NT_SUCCESS(Status))
90     {
91         DeviceExtension->InterruptIrql = Irql;
92     }
93     else
94     {
95         DPRINT1("IoConnectInterrupt() failed (Status 0x%08lx)\n", Status);
96     }
97 
98     return Status;
99 }
100 
101 
102 static
103 NTSTATUS
104 PortFdoStartMiniport(
105     _In_ PFDO_DEVICE_EXTENSION DeviceExtension)
106 {
107     PHW_INITIALIZATION_DATA InitData;
108     INTERFACE_TYPE InterfaceType;
109     NTSTATUS Status;
110 
111     DPRINT1("PortFdoStartDevice(%p)\n", DeviceExtension);
112 
113     /* Get the interface type of the lower device */
114     InterfaceType = GetBusInterface(DeviceExtension->LowerDevice);
115     if (InterfaceType == InterfaceTypeUndefined)
116         return STATUS_NO_SUCH_DEVICE;
117 
118     /* Get the driver init data for the given interface type */
119     InitData = PortGetDriverInitData(DeviceExtension->DriverExtension,
120                                      InterfaceType);
121     if (InitData == NULL)
122         return STATUS_NO_SUCH_DEVICE;
123 
124     /* Initialize the miniport */
125     Status = MiniportInitialize(&DeviceExtension->Miniport,
126                                 DeviceExtension,
127                                 InitData);
128     if (!NT_SUCCESS(Status))
129     {
130         DPRINT1("MiniportInitialize() failed (Status 0x%08lx)\n", Status);
131         return Status;
132     }
133 
134     /* Call the miniports FindAdapter function */
135     Status = MiniportFindAdapter(&DeviceExtension->Miniport);
136     if (!NT_SUCCESS(Status))
137     {
138         DPRINT1("MiniportFindAdapter() failed (Status 0x%08lx)\n", Status);
139         return Status;
140     }
141 
142     /* Connect the configured interrupt */
143     Status = PortFdoConnectInterrupt(DeviceExtension);
144     if (!NT_SUCCESS(Status))
145     {
146         DPRINT1("PortFdoConnectInterrupt() failed (Status 0x%08lx)\n", Status);
147         return Status;
148     }
149 
150     /* Call the miniports HwInitialize function */
151     Status = MiniportHwInitialize(&DeviceExtension->Miniport);
152     if (!NT_SUCCESS(Status))
153     {
154         DPRINT1("MiniportHwInitialize() failed (Status 0x%08lx)\n", Status);
155         return Status;
156     }
157 
158     /* Call the HwPassiveInitRoutine function, if available */
159     if (DeviceExtension->HwPassiveInitRoutine != NULL)
160     {
161         DPRINT1("Calling HwPassiveInitRoutine()\n");
162         if (!DeviceExtension->HwPassiveInitRoutine(&DeviceExtension->Miniport.MiniportExtension->HwDeviceExtension))
163         {
164             DPRINT1("HwPassiveInitRoutine() failed\n");
165             return STATUS_UNSUCCESSFUL;
166         }
167     }
168 
169     return STATUS_SUCCESS;
170 }
171 
172 
173 static
174 NTSTATUS
175 NTAPI
176 PortFdoStartDevice(
177     _In_ PFDO_DEVICE_EXTENSION DeviceExtension,
178     _In_ PIRP Irp)
179 {
180     PIO_STACK_LOCATION Stack;
181     NTSTATUS Status;
182 
183     DPRINT1("PortFdoStartDevice(%p %p)\n",
184             DeviceExtension, Irp);
185 
186     ASSERT(DeviceExtension->ExtensionType == FdoExtension);
187 
188     /* Get the current stack location */
189     Stack = IoGetCurrentIrpStackLocation(Irp);
190 
191     /* Start the lower device if the FDO is in 'stopped' state */
192     if (DeviceExtension->PnpState == dsStopped)
193     {
194         Status = ForwardIrpAndWait(DeviceExtension->LowerDevice, Irp);
195         if (!NT_SUCCESS(Status))
196         {
197             DPRINT1("ForwardIrpAndWait() failed (Status 0x%08lx)\n", Status);
198             return Status;
199         }
200     }
201 
202     /* Change to the 'started' state */
203     DeviceExtension->PnpState = dsStarted;
204 
205     /* Copy the raw and translated resource lists into the device extension */
206     if (Stack->Parameters.StartDevice.AllocatedResources != NULL &&
207         Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
208     {
209         DeviceExtension->AllocatedResources = CopyResourceList(NonPagedPool,
210                                                                Stack->Parameters.StartDevice.AllocatedResources);
211         if (DeviceExtension->AllocatedResources == NULL)
212             return STATUS_NO_MEMORY;
213 
214         DeviceExtension->TranslatedResources = CopyResourceList(NonPagedPool,
215                                                                 Stack->Parameters.StartDevice.AllocatedResourcesTranslated);
216         if (DeviceExtension->TranslatedResources == NULL)
217             return STATUS_NO_MEMORY;
218     }
219 
220     /* Get the bus interface of the lower (bus) device */
221     Status = QueryBusInterface(DeviceExtension->LowerDevice,
222                                (PGUID)&GUID_BUS_INTERFACE_STANDARD,
223                                sizeof(BUS_INTERFACE_STANDARD),
224                                1,
225                                &DeviceExtension->BusInterface,
226                                NULL);
227     DPRINT1("Status: 0x%08lx\n", Status);
228     if (NT_SUCCESS(Status))
229     {
230         DPRINT1("Context: %p\n", DeviceExtension->BusInterface.Context);
231         DeviceExtension->BusInitialized = TRUE;
232     }
233 
234     /* Start the miniport (FindAdapter & Initialize) */
235     Status = PortFdoStartMiniport(DeviceExtension);
236     if (!NT_SUCCESS(Status))
237     {
238         DPRINT1("FdoStartMiniport() failed (Status 0x%08lx)\n", Status);
239         DeviceExtension->PnpState = dsStopped;
240     }
241 
242     return Status;
243 }
244 
245 
246 static
247 NTSTATUS
248 PortSendInquiry(
249     _In_ PPDO_DEVICE_EXTENSION PdoExtension)
250 {
251     IO_STATUS_BLOCK IoStatusBlock;
252     PIO_STACK_LOCATION IrpStack;
253     KEVENT Event;
254 //    KIRQL Irql;
255     PIRP Irp;
256     NTSTATUS Status;
257     PSENSE_DATA SenseBuffer;
258     BOOLEAN KeepTrying = TRUE;
259     ULONG RetryCount = 0;
260     SCSI_REQUEST_BLOCK Srb;
261     PCDB Cdb;
262 //    PSCSI_PORT_LUN_EXTENSION LunExtension;
263 //    PFDO_DEVICE_EXTENSION DeviceExtension;
264 
265     DPRINT("PortSendInquiry(%p)\n", PdoExtension);
266 
267     if (PdoExtension->InquiryBuffer == NULL)
268     {
269         PdoExtension->InquiryBuffer = ExAllocatePoolWithTag(NonPagedPool, INQUIRYDATABUFFERSIZE, TAG_INQUIRY_DATA);
270         if (PdoExtension->InquiryBuffer == NULL)
271             return STATUS_INSUFFICIENT_RESOURCES;
272     }
273 
274     SenseBuffer = ExAllocatePoolWithTag(NonPagedPool, SENSE_BUFFER_SIZE, TAG_SENSE_DATA);
275     if (SenseBuffer == NULL)
276     {
277         return STATUS_INSUFFICIENT_RESOURCES;
278     }
279 
280     while (KeepTrying)
281     {
282         /* Initialize event for waiting */
283         KeInitializeEvent(&Event,
284                           NotificationEvent,
285                           FALSE);
286 
287         /* Create an IRP */
288         Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_IN,
289                                             PdoExtension->Device,
290                                             NULL,
291                                             0,
292                                             PdoExtension->InquiryBuffer,
293                                             INQUIRYDATABUFFERSIZE,
294                                             TRUE,
295                                             &Event,
296                                             &IoStatusBlock);
297         if (Irp == NULL)
298         {
299             DPRINT("IoBuildDeviceIoControlRequest() failed\n");
300 
301             /* Quit the loop */
302             Status = STATUS_INSUFFICIENT_RESOURCES;
303             KeepTrying = FALSE;
304             continue;
305         }
306 
307         /* Prepare SRB */
308         RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
309 
310         Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
311         Srb.OriginalRequest = Irp;
312         Srb.PathId = PdoExtension->Bus;
313         Srb.TargetId = PdoExtension->Target;
314         Srb.Lun = PdoExtension->Lun;
315         Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
316         Srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
317         Srb.TimeOutValue = 4;
318         Srb.CdbLength = 6;
319 
320         Srb.SenseInfoBuffer = SenseBuffer;
321         Srb.SenseInfoBufferLength = SENSE_BUFFER_SIZE;
322 
323         Srb.DataBuffer = PdoExtension->InquiryBuffer;
324         Srb.DataTransferLength = INQUIRYDATABUFFERSIZE;
325 
326         /* Attach Srb to the Irp */
327         IrpStack = IoGetNextIrpStackLocation(Irp);
328         IrpStack->Parameters.Scsi.Srb = &Srb;
329 
330         /* Fill in CDB */
331         Cdb = (PCDB)Srb.Cdb;
332         Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
333         Cdb->CDB6INQUIRY.LogicalUnitNumber = PdoExtension->Lun;
334         Cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
335 
336         /* Call the driver */
337         Status = IoCallDriver(PdoExtension->Device, Irp);
338 
339         /* Wait for it to complete */
340         if (Status == STATUS_PENDING)
341         {
342             DPRINT1("PortSendInquiry(): Waiting for the driver to process request...\n");
343             KeWaitForSingleObject(&Event,
344                                   Executive,
345                                   KernelMode,
346                                   FALSE,
347                                   NULL);
348             Status = IoStatusBlock.Status;
349         }
350 
351         DPRINT("PortSendInquiry(): Request processed by driver, status = 0x%08X\n", Status);
352 
353         if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_SUCCESS)
354         {
355             DPRINT("Found a device!\n");
356 
357             /* Quit the loop */
358             Status = STATUS_SUCCESS;
359             KeepTrying = FALSE;
360             continue;
361         }
362 
363         DPRINT("Inquiry SRB failed with SrbStatus 0x%08X\n", Srb.SrbStatus);
364 
365         /* Check if the queue is frozen */
366         if (Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN)
367         {
368             /* Something weird happened, deal with it (unfreeze the queue) */
369             KeepTrying = FALSE;
370 
371             DPRINT("SpiSendInquiry(): the queue is frozen at TargetId %d\n", Srb.TargetId);
372 
373 //            LunExtension = SpiGetLunExtension(DeviceExtension,
374 //                                              LunInfo->PathId,
375 //                                              LunInfo->TargetId,
376 //                                              LunInfo->Lun);
377 
378             /* Clear frozen flag */
379 //            LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE;
380 
381             /* Acquire the spinlock */
382 //            KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
383 
384             /* Process the request */
385 //            SpiGetNextRequestFromLun(DeviceObject->DeviceExtension, LunExtension);
386 
387             /* SpiGetNextRequestFromLun() releases the spinlock,
388                 so we just lower irql back to what it was before */
389 //            KeLowerIrql(Irql);
390         }
391 
392         /* Check if data overrun happened */
393         if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN)
394         {
395             DPRINT("Data overrun at TargetId %d\n", PdoExtension->Target);
396 
397             /* Quit the loop */
398             Status = STATUS_SUCCESS;
399             KeepTrying = FALSE;
400         }
401         else if ((Srb.SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
402                  SenseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST)
403         {
404             /* LUN is not valid, but some device responds there.
405                 Mark it as invalid anyway */
406 
407             /* Quit the loop */
408             Status = STATUS_INVALID_DEVICE_REQUEST;
409             KeepTrying = FALSE;
410         }
411         else
412         {
413             /* Retry a couple of times if no timeout happened */
414             if ((RetryCount < 2) &&
415                 (SRB_STATUS(Srb.SrbStatus) != SRB_STATUS_NO_DEVICE) &&
416                 (SRB_STATUS(Srb.SrbStatus) != SRB_STATUS_SELECTION_TIMEOUT))
417             {
418                 RetryCount++;
419                 KeepTrying = TRUE;
420             }
421             else
422             {
423                 /* That's all, quit the loop */
424                 KeepTrying = FALSE;
425 
426                 /* Set status according to SRB status */
427                 if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_BAD_FUNCTION ||
428                     SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_BAD_SRB_BLOCK_LENGTH)
429                 {
430                     Status = STATUS_INVALID_DEVICE_REQUEST;
431                 }
432                 else
433                 {
434                     Status = STATUS_IO_DEVICE_ERROR;
435                 }
436             }
437         }
438     }
439 
440     /* Free the sense buffer */
441     ExFreePoolWithTag(SenseBuffer, TAG_SENSE_DATA);
442 
443     DPRINT("PortSendInquiry() done with Status 0x%08X\n", Status);
444 
445     return Status;
446 }
447 
448 
449 
450 static
451 NTSTATUS
452 PortFdoScanBus(
453     _In_ PFDO_DEVICE_EXTENSION DeviceExtension)
454 {
455     PPDO_DEVICE_EXTENSION PdoExtension;
456     ULONG Bus, Target; //, Lun;
457     NTSTATUS Status;
458 
459     DPRINT("PortFdoScanBus(%p)\n", DeviceExtension);
460 
461     DPRINT("NumberOfBuses: %lu\n", DeviceExtension->Miniport.PortConfig.NumberOfBuses);
462     DPRINT("MaximumNumberOfTargets: %lu\n", DeviceExtension->Miniport.PortConfig.MaximumNumberOfTargets);
463     DPRINT("MaximumNumberOfLogicalUnits: %lu\n", DeviceExtension->Miniport.PortConfig.MaximumNumberOfLogicalUnits);
464 
465     /* Scan all buses */
466     for (Bus = 0; Bus < DeviceExtension->Miniport.PortConfig.NumberOfBuses; Bus++)
467     {
468         DPRINT("Scanning bus %ld\n", Bus);
469 
470         /* Scan all targets */
471         for (Target = 0; Target < DeviceExtension->Miniport.PortConfig.MaximumNumberOfTargets; Target++)
472         {
473             DPRINT("  Scanning target %ld:%ld\n", Bus, Target);
474 
475             DPRINT("    Scanning logical unit %ld:%ld:%ld\n", Bus, Target, 0);
476             Status = PortCreatePdo(DeviceExtension, Bus, Target, 0, &PdoExtension);
477             if (NT_SUCCESS(Status))
478             {
479                 /* Scan LUN 0 */
480                 Status = PortSendInquiry(PdoExtension);
481                 DPRINT("PortSendInquiry returned 0x%08lx\n", Status);
482                 if (!NT_SUCCESS(Status))
483                 {
484                     PortDeletePdo(PdoExtension);
485                 }
486                 else
487                 {
488                     DPRINT("VendorId: %.8s\n", PdoExtension->InquiryBuffer->VendorId);
489                     DPRINT("ProductId: %.16s\n", PdoExtension->InquiryBuffer->ProductId);
490                     DPRINT("ProductRevisionLevel: %.4s\n", PdoExtension->InquiryBuffer->ProductRevisionLevel);
491                     DPRINT("VendorSpecific: %.20s\n", PdoExtension->InquiryBuffer->VendorSpecific);
492                 }
493             }
494 
495 #if 0
496             /* Scan all logical units */
497             for (Lun = 1; Lun < DeviceExtension->Miniport.PortConfig.MaximumNumberOfLogicalUnits; Lun++)
498             {
499                 DPRINT("    Scanning logical unit %ld:%ld:%ld\n", Bus, Target, Lun);
500                 Status = PortSendInquiry(DeviceExtension->Device, Bus, Target, Lun);
501                 DPRINT("PortSendInquiry returned 0x%08lx\n", Status);
502                 if (!NT_SUCCESS(Status))
503                     break;
504             }
505 #endif
506         }
507     }
508 
509     DPRINT("PortFdoScanBus() done!\n");
510 
511     return STATUS_SUCCESS;
512 }
513 
514 
515 static
516 NTSTATUS
517 PortFdoQueryBusRelations(
518     _In_ PFDO_DEVICE_EXTENSION DeviceExtension,
519     _Out_ PULONG_PTR Information)
520 {
521     NTSTATUS Status = STATUS_SUCCESS;;
522 
523     DPRINT1("PortFdoQueryBusRelations(%p %p)\n",
524             DeviceExtension, Information);
525 
526     Status = PortFdoScanBus(DeviceExtension);
527 
528     DPRINT1("Units found: %lu\n", DeviceExtension->PdoCount);
529 
530     *Information = 0;
531 
532     return Status;
533 }
534 
535 
536 static
537 NTSTATUS
538 PortFdoFilterRequirements(
539     PFDO_DEVICE_EXTENSION DeviceExtension,
540     PIRP Irp)
541 {
542     PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
543 
544     DPRINT1("PortFdoFilterRequirements(%p %p)\n", DeviceExtension, Irp);
545 
546     /* Get the bus number and the slot number */
547     RequirementsList =(PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
548     if (RequirementsList != NULL)
549     {
550         DeviceExtension->BusNumber = RequirementsList->BusNumber;
551         DeviceExtension->SlotNumber = RequirementsList->SlotNumber;
552     }
553 
554     return STATUS_SUCCESS;
555 }
556 
557 
558 NTSTATUS
559 NTAPI
560 PortFdoScsi(
561     _In_ PDEVICE_OBJECT DeviceObject,
562     _In_ PIRP Irp)
563 {
564     PFDO_DEVICE_EXTENSION DeviceExtension;
565 //    PIO_STACK_LOCATION Stack;
566     ULONG_PTR Information = 0;
567     NTSTATUS Status = STATUS_NOT_SUPPORTED;
568 
569     DPRINT("PortFdoScsi(%p %p)\n", DeviceObject, Irp);
570 
571     DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
572     ASSERT(DeviceExtension);
573     ASSERT(DeviceExtension->ExtensionType == FdoExtension);
574 
575 //    Stack = IoGetCurrentIrpStackLocation(Irp);
576 
577 
578     Irp->IoStatus.Information = Information;
579     Irp->IoStatus.Status = Status;
580     IoCompleteRequest(Irp, IO_NO_INCREMENT);
581 
582     return Status;
583 }
584 
585 
586 NTSTATUS
587 NTAPI
588 PortFdoPnp(
589     _In_ PDEVICE_OBJECT DeviceObject,
590     _In_ PIRP Irp)
591 {
592     PFDO_DEVICE_EXTENSION DeviceExtension;
593     PIO_STACK_LOCATION Stack;
594     ULONG_PTR Information = 0;
595     NTSTATUS Status = STATUS_NOT_SUPPORTED;
596 
597     DPRINT1("PortFdoPnp(%p %p)\n",
598             DeviceObject, Irp);
599 
600     DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
601     ASSERT(DeviceExtension);
602     ASSERT(DeviceExtension->ExtensionType == FdoExtension);
603 
604     Stack = IoGetCurrentIrpStackLocation(Irp);
605 
606     switch (Stack->MinorFunction)
607     {
608         case IRP_MN_START_DEVICE: /* 0x00 */
609             DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
610             Status = PortFdoStartDevice(DeviceExtension, Irp);
611             break;
612 
613         case IRP_MN_QUERY_REMOVE_DEVICE: /* 0x01 */
614             DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n");
615             break;
616 
617         case IRP_MN_REMOVE_DEVICE: /* 0x02 */
618             DPRINT1("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
619             break;
620 
621         case IRP_MN_CANCEL_REMOVE_DEVICE: /* 0x03 */
622             DPRINT1("IRP_MJ_PNP / IRP_MN_CANCEL_REMOVE_DEVICE\n");
623             break;
624 
625         case IRP_MN_STOP_DEVICE: /* 0x04 */
626             DPRINT1("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
627             break;
628 
629         case IRP_MN_QUERY_STOP_DEVICE: /* 0x05 */
630             DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_STOP_DEVICE\n");
631             break;
632 
633         case IRP_MN_CANCEL_STOP_DEVICE: /* 0x06 */
634             DPRINT1("IRP_MJ_PNP / IRP_MN_CANCEL_STOP_DEVICE\n");
635             break;
636 
637         case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */
638             DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n");
639             switch (Stack->Parameters.QueryDeviceRelations.Type)
640             {
641                 case BusRelations:
642                     DPRINT1("    IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
643                     Status = PortFdoQueryBusRelations(DeviceExtension, &Information);
644                     break;
645 
646                 case RemovalRelations:
647                     DPRINT1("    IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
648                     return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp);
649 
650                 default:
651                     DPRINT1("    IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
652                             Stack->Parameters.QueryDeviceRelations.Type);
653                     return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp);
654             }
655             break;
656 
657         case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0x0d */
658             DPRINT1("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
659             PortFdoFilterRequirements(DeviceExtension, Irp);
660             return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp);
661 
662         case IRP_MN_QUERY_PNP_DEVICE_STATE: /* 0x14 */
663             DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
664             break;
665 
666         case IRP_MN_DEVICE_USAGE_NOTIFICATION: /* 0x16 */
667             DPRINT1("IRP_MJ_PNP / IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
668             break;
669 
670         case IRP_MN_SURPRISE_REMOVAL: /* 0x17 */
671             DPRINT1("IRP_MJ_PNP / IRP_MN_SURPRISE_REMOVAL\n");
672             break;
673 
674         default:
675             DPRINT1("IRP_MJ_PNP / Unknown IOCTL 0x%lx\n", Stack->MinorFunction);
676             return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp);
677     }
678 
679     Irp->IoStatus.Information = Information;
680     Irp->IoStatus.Status = Status;
681     IoCompleteRequest(Irp, IO_NO_INCREMENT);
682 
683     return Status;
684 }
685 
686 /* EOF */
687