xref: /reactos/drivers/storage/port/storport/fdo.c (revision a6726659)
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 NTSTATUS
247 SpiSendInquiry(IN PDEVICE_OBJECT DeviceObject,
248                ULONG Bus, ULONG Target, ULONG Lun)
249 {
250 //    IO_STATUS_BLOCK IoStatusBlock;
251 //    PIO_STACK_LOCATION IrpStack;
252 //    KEVENT Event;
253 //    KIRQL Irql;
254 //    PIRP Irp;
255     NTSTATUS Status;
256     PINQUIRYDATA InquiryBuffer;
257     PUCHAR /*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 //    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
264 
265 PFDO_DEVICE_EXTENSION DeviceExtension;
266     PVOID SrbExtension = NULL;
267     BOOLEAN ret;
268 
269     DPRINT1("SpiSendInquiry() called\n");
270 
271     DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
272 
273     InquiryBuffer = ExAllocatePoolWithTag(NonPagedPool, INQUIRYDATABUFFERSIZE, TAG_INQUIRY_DATA);
274     if (InquiryBuffer == NULL)
275         return STATUS_INSUFFICIENT_RESOURCES;
276 
277     SenseBuffer = ExAllocatePoolWithTag(NonPagedPool, SENSE_BUFFER_SIZE, TAG_SENSE_DATA);
278     if (SenseBuffer == NULL)
279     {
280         ExFreePoolWithTag(InquiryBuffer, TAG_INQUIRY_DATA);
281         return STATUS_INSUFFICIENT_RESOURCES;
282     }
283 
284     if (DeviceExtension->Miniport.PortConfig.SrbExtensionSize != 0)
285     {
286         SrbExtension = ExAllocatePoolWithTag(NonPagedPool, DeviceExtension->Miniport.PortConfig.SrbExtensionSize, TAG_SENSE_DATA);
287         if (SrbExtension == NULL)
288         {
289             ExFreePoolWithTag(SenseBuffer, TAG_SENSE_DATA);
290             ExFreePoolWithTag(InquiryBuffer, TAG_INQUIRY_DATA);
291             return STATUS_INSUFFICIENT_RESOURCES;
292         }
293     }
294 
295 //    while (KeepTrying)
296     {
297         /* Initialize event for waiting */
298 //        KeInitializeEvent(&Event,
299 //                          NotificationEvent,
300 //                          FALSE);
301 
302         /* Create an IRP */
303 //        Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_IN,
304 //                                            DeviceObject,
305 //                                            NULL,
306 //                                            0,
307 //                                            InquiryBuffer,
308 //                                            INQUIRYDATABUFFERSIZE,
309 //                                            TRUE,
310 //                                            &Event,
311 //                                            &IoStatusBlock);
312 //        if (Irp == NULL)
313 //        {
314 //            DPRINT1("IoBuildDeviceIoControlRequest() failed\n");
315 
316             /* Quit the loop */
317 //            Status = STATUS_INSUFFICIENT_RESOURCES;
318 //            KeepTrying = FALSE;
319 //            continue;
320 //        }
321 
322         /* Prepare SRB */
323         RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
324 
325         Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
326 //        Srb.OriginalRequest = Irp;
327         Srb.PathId = Bus;
328         Srb.TargetId = Target;
329         Srb.Lun = Lun;
330         Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
331         Srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
332         Srb.TimeOutValue = 4;
333         Srb.CdbLength = 6;
334 
335         Srb.SenseInfoBuffer = SenseBuffer;
336         Srb.SenseInfoBufferLength = SENSE_BUFFER_SIZE;
337 
338         Srb.DataBuffer = InquiryBuffer;
339         Srb.DataTransferLength = INQUIRYDATABUFFERSIZE;
340 
341         Srb.SrbExtension = SrbExtension;
342 
343         /* Attach Srb to the Irp */
344 //        IrpStack = IoGetNextIrpStackLocation(Irp);
345 //        IrpStack->Parameters.Scsi.Srb = &Srb;
346 
347         /* Fill in CDB */
348         Cdb = (PCDB)Srb.Cdb;
349         Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
350         Cdb->CDB6INQUIRY.LogicalUnitNumber = Lun;
351         Cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
352 
353         /* Call the driver */
354 
355 
356         ret = MiniportStartIo(&DeviceExtension->Miniport,
357                               &Srb);
358 DPRINT1("MiniportStartIo returned %u\n", ret);
359 
360 //        Status = IoCallDriver(DeviceObject, Irp);
361 
362         /* Wait for it to complete */
363 //        if (Status == STATUS_PENDING)
364 //        {
365 //            DPRINT1("SpiSendInquiry(): Waiting for the driver to process request...\n");
366 //            KeWaitForSingleObject(&Event,
367 //                                  Executive,
368 //                                  KernelMode,
369 //                                  FALSE,
370 //                                  NULL);
371 //            Status = IoStatusBlock.Status;
372 //        }
373 
374 //        DPRINT1("SpiSendInquiry(): Request processed by driver, status = 0x%08X\n", Status);
375 
376         if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_SUCCESS)
377         {
378             /* All fine, copy data over */
379 //            RtlCopyMemory(LunInfo->InquiryData,
380 //                          InquiryBuffer,
381 //                          INQUIRYDATABUFFERSIZE);
382 
383             /* Quit the loop */
384             Status = STATUS_SUCCESS;
385 //            KeepTrying = FALSE;
386 //            continue;
387         }
388 
389         DPRINT("Inquiry SRB failed with SrbStatus 0x%08X\n", Srb.SrbStatus);
390 #if 0
391         /* Check if the queue is frozen */
392         if (Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN)
393         {
394             /* Something weird happened, deal with it (unfreeze the queue) */
395             KeepTrying = FALSE;
396 
397             DPRINT("SpiSendInquiry(): the queue is frozen at TargetId %d\n", Srb.TargetId);
398 
399             LunExtension = SpiGetLunExtension(DeviceExtension,
400                                               LunInfo->PathId,
401                                               LunInfo->TargetId,
402                                               LunInfo->Lun);
403 
404             /* Clear frozen flag */
405             LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE;
406 
407             /* Acquire the spinlock */
408             KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
409 
410             /* Process the request */
411             SpiGetNextRequestFromLun(DeviceObject->DeviceExtension, LunExtension);
412 
413             /* SpiGetNextRequestFromLun() releases the spinlock,
414                 so we just lower irql back to what it was before */
415             KeLowerIrql(Irql);
416         }
417 
418         /* Check if data overrun happened */
419         if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN)
420         {
421             DPRINT("Data overrun at TargetId %d\n", LunInfo->TargetId);
422 
423             /* Nothing dramatic, just copy data, but limiting the size */
424             RtlCopyMemory(LunInfo->InquiryData,
425                             InquiryBuffer,
426                             (Srb.DataTransferLength > INQUIRYDATABUFFERSIZE) ?
427                             INQUIRYDATABUFFERSIZE : Srb.DataTransferLength);
428 
429             /* Quit the loop */
430             Status = STATUS_SUCCESS;
431             KeepTrying = FALSE;
432         }
433         else if ((Srb.SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
434                  SenseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST)
435         {
436             /* LUN is not valid, but some device responds there.
437                 Mark it as invalid anyway */
438 
439             /* Quit the loop */
440             Status = STATUS_INVALID_DEVICE_REQUEST;
441             KeepTrying = FALSE;
442         }
443         else
444         {
445             /* Retry a couple of times if no timeout happened */
446             if ((RetryCount < 2) &&
447                 (SRB_STATUS(Srb.SrbStatus) != SRB_STATUS_NO_DEVICE) &&
448                 (SRB_STATUS(Srb.SrbStatus) != SRB_STATUS_SELECTION_TIMEOUT))
449             {
450                 RetryCount++;
451                 KeepTrying = TRUE;
452             }
453             else
454             {
455                 /* That's all, quit the loop */
456                 KeepTrying = FALSE;
457 
458                 /* Set status according to SRB status */
459                 if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_BAD_FUNCTION ||
460                     SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_BAD_SRB_BLOCK_LENGTH)
461                 {
462                     Status = STATUS_INVALID_DEVICE_REQUEST;
463                 }
464                 else
465                 {
466                     Status = STATUS_IO_DEVICE_ERROR;
467                 }
468             }
469         }
470 #endif
471     }
472 
473     /* Free buffers */
474     if (SrbExtension != NULL)
475         ExFreePoolWithTag(SrbExtension, TAG_SENSE_DATA);
476 
477     ExFreePoolWithTag(SenseBuffer, TAG_SENSE_DATA);
478     ExFreePoolWithTag(InquiryBuffer, TAG_INQUIRY_DATA);
479 
480     DPRINT("SpiSendInquiry() done with Status 0x%08X\n", Status);
481 
482     return Status;
483 }
484 
485 
486 static
487 NTSTATUS
488 PortFdoScanBus(
489     _In_ PFDO_DEVICE_EXTENSION DeviceExtension)
490 {
491     ULONG Bus, Target, Lun;
492     NTSTATUS Status;
493 
494 
495     DPRINT1("PortFdoScanBus(%p)\n",
496             DeviceExtension);
497 
498     DPRINT1("NumberOfBuses: %lu\n", DeviceExtension->Miniport.PortConfig.NumberOfBuses);
499     DPRINT1("MaximumNumberOfTargets: %lu\n", DeviceExtension->Miniport.PortConfig.MaximumNumberOfTargets);
500     DPRINT1("MaximumNumberOfLogicalUnits: %lu\n", DeviceExtension->Miniport.PortConfig.MaximumNumberOfLogicalUnits);
501 
502     /* Scan all buses */
503     for (Bus = 0; Bus < DeviceExtension->Miniport.PortConfig.NumberOfBuses; Bus++)
504     {
505         DPRINT1("Scanning bus %ld\n", Bus);
506 
507         /* Scan all targets */
508         for (Target = 0; Target < DeviceExtension->Miniport.PortConfig.MaximumNumberOfTargets; Target++)
509         {
510             DPRINT1("  Scanning target %ld:%ld\n", Bus, Target);
511 
512             /* Scan all logical units */
513             for (Lun = 0; Lun < DeviceExtension->Miniport.PortConfig.MaximumNumberOfLogicalUnits; Lun++)
514             {
515                 DPRINT1("    Scanning logical unit %ld:%ld:%ld\n", Bus, Target, Lun);
516 
517                 Status = SpiSendInquiry(DeviceExtension->Device, Bus, Target, Lun);
518                 DPRINT1("SpiSendInquiry returned 0x%08lx\n", Status);
519             }
520         }
521     }
522 
523     DPRINT1("Done!\n");
524 
525     return STATUS_SUCCESS;
526 }
527 
528 
529 static
530 NTSTATUS
531 PortFdoQueryBusRelations(
532     _In_ PFDO_DEVICE_EXTENSION DeviceExtension,
533     _Out_ PULONG_PTR Information)
534 {
535     NTSTATUS Status = STATUS_SUCCESS;;
536 
537     DPRINT1("PortFdoQueryBusRelations(%p %p)\n",
538             DeviceExtension, Information);
539 
540     Status = PortFdoScanBus(DeviceExtension);
541 
542     *Information = 0;
543 
544     return Status;
545 }
546 
547 
548 static
549 NTSTATUS
550 PortFdoFilterRequirements(
551     PFDO_DEVICE_EXTENSION DeviceExtension,
552     PIRP Irp)
553 {
554     PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
555 
556     DPRINT1("PortFdoFilterRequirements(%p %p)\n", DeviceExtension, Irp);
557 
558     /* Get the bus number and the slot number */
559     RequirementsList =(PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
560     if (RequirementsList != NULL)
561     {
562         DeviceExtension->BusNumber = RequirementsList->BusNumber;
563         DeviceExtension->SlotNumber = RequirementsList->SlotNumber;
564     }
565 
566     return STATUS_SUCCESS;
567 }
568 
569 
570 NTSTATUS
571 NTAPI
572 PortFdoScsi(
573     _In_ PDEVICE_OBJECT DeviceObject,
574     _In_ PIRP Irp)
575 {
576     PFDO_DEVICE_EXTENSION DeviceExtension;
577 //    PIO_STACK_LOCATION Stack;
578     ULONG_PTR Information = 0;
579     NTSTATUS Status = STATUS_NOT_SUPPORTED;
580 
581     DPRINT1("PortFdoScsi(%p %p)\n",
582             DeviceObject, Irp);
583 
584     DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
585     ASSERT(DeviceExtension);
586     ASSERT(DeviceExtension->ExtensionType == FdoExtension);
587 
588 //    Stack = IoGetCurrentIrpStackLocation(Irp);
589 
590 
591     Irp->IoStatus.Information = Information;
592     Irp->IoStatus.Status = Status;
593     IoCompleteRequest(Irp, IO_NO_INCREMENT);
594 
595     return Status;
596 }
597 
598 
599 NTSTATUS
600 NTAPI
601 PortFdoPnp(
602     _In_ PDEVICE_OBJECT DeviceObject,
603     _In_ PIRP Irp)
604 {
605     PFDO_DEVICE_EXTENSION DeviceExtension;
606     PIO_STACK_LOCATION Stack;
607     ULONG_PTR Information = 0;
608     NTSTATUS Status = STATUS_NOT_SUPPORTED;
609 
610     DPRINT1("PortFdoPnp(%p %p)\n",
611             DeviceObject, Irp);
612 
613     DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
614     ASSERT(DeviceExtension);
615     ASSERT(DeviceExtension->ExtensionType == FdoExtension);
616 
617     Stack = IoGetCurrentIrpStackLocation(Irp);
618 
619     switch (Stack->MinorFunction)
620     {
621         case IRP_MN_START_DEVICE: /* 0x00 */
622             DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
623             Status = PortFdoStartDevice(DeviceExtension, Irp);
624             break;
625 
626         case IRP_MN_QUERY_REMOVE_DEVICE: /* 0x01 */
627             DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n");
628             break;
629 
630         case IRP_MN_REMOVE_DEVICE: /* 0x02 */
631             DPRINT1("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
632             break;
633 
634         case IRP_MN_CANCEL_REMOVE_DEVICE: /* 0x03 */
635             DPRINT1("IRP_MJ_PNP / IRP_MN_CANCEL_REMOVE_DEVICE\n");
636             break;
637 
638         case IRP_MN_STOP_DEVICE: /* 0x04 */
639             DPRINT1("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
640             break;
641 
642         case IRP_MN_QUERY_STOP_DEVICE: /* 0x05 */
643             DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_STOP_DEVICE\n");
644             break;
645 
646         case IRP_MN_CANCEL_STOP_DEVICE: /* 0x06 */
647             DPRINT1("IRP_MJ_PNP / IRP_MN_CANCEL_STOP_DEVICE\n");
648             break;
649 
650         case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */
651             DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n");
652             switch (Stack->Parameters.QueryDeviceRelations.Type)
653             {
654                 case BusRelations:
655                     DPRINT1("    IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
656                     Status = PortFdoQueryBusRelations(DeviceExtension, &Information);
657                     break;
658 
659                 case RemovalRelations:
660                     DPRINT1("    IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
661                     return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp);
662 
663                 default:
664                     DPRINT1("    IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
665                             Stack->Parameters.QueryDeviceRelations.Type);
666                     return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp);
667             }
668             break;
669 
670         case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0x0d */
671             DPRINT1("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
672             PortFdoFilterRequirements(DeviceExtension, Irp);
673             return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp);
674 
675         case IRP_MN_QUERY_PNP_DEVICE_STATE: /* 0x14 */
676             DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
677             break;
678 
679         case IRP_MN_DEVICE_USAGE_NOTIFICATION: /* 0x16 */
680             DPRINT1("IRP_MJ_PNP / IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
681             break;
682 
683         case IRP_MN_SURPRISE_REMOVAL: /* 0x17 */
684             DPRINT1("IRP_MJ_PNP / IRP_MN_SURPRISE_REMOVAL\n");
685             break;
686 
687         default:
688             DPRINT1("IRP_MJ_PNP / Unknown IOCTL 0x%lx\n", Stack->MinorFunction);
689             return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp);
690     }
691 
692     Irp->IoStatus.Information = Information;
693     Irp->IoStatus.Status = Status;
694     IoCompleteRequest(Irp, IO_NO_INCREMENT);
695 
696     return Status;
697 }
698 
699 /* EOF */
700