xref: /reactos/drivers/storage/port/storport/fdo.c (revision f7cab5a1)
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