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)
8 /* INCLUDES *******************************************************************/
16 /* FUNCTIONS ******************************************************************/
21 PortFdoInterruptRoutine(
22 _In_ PKINTERRUPT Interrupt
,
23 _In_ PVOID ServiceContext
)
25 PFDO_DEVICE_EXTENSION DeviceExtension
;
27 DPRINT1("PortFdoInterruptRoutine(%p %p)\n",
28 Interrupt
, ServiceContext
);
30 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)ServiceContext
;
32 return MiniportHwInterrupt(&DeviceExtension
->Miniport
);
38 PortFdoConnectInterrupt(
39 _In_ PFDO_DEVICE_EXTENSION DeviceExtension
)
43 KINTERRUPT_MODE InterruptMode
;
48 DPRINT1("PortFdoConnectInterrupt(%p)\n",
51 /* No resources, no interrupt. Done! */
52 if (DeviceExtension
->AllocatedResources
== NULL
||
53 DeviceExtension
->TranslatedResources
== NULL
)
55 DPRINT1("Checkpoint\n");
56 return STATUS_SUCCESS
;
59 /* Get the interrupt data from the resource list */
60 Status
= GetResourceListInterrupt(DeviceExtension
,
66 if (!NT_SUCCESS(Status
))
68 DPRINT1("GetResourceListInterrupt() failed (Status 0x%08lx)\n", Status
);
72 DPRINT1("Vector: %lu\n", Vector
);
73 DPRINT1("Irql: %lu\n", Irql
);
75 DPRINT1("Affinity: 0x%08lx\n", Affinity
);
77 /* Connect the interrupt */
78 Status
= IoConnectInterrupt(&DeviceExtension
->Interrupt
,
79 PortFdoInterruptRoutine
,
89 if (NT_SUCCESS(Status
))
91 DeviceExtension
->InterruptIrql
= Irql
;
95 DPRINT1("IoConnectInterrupt() failed (Status 0x%08lx)\n", Status
);
104 PortFdoStartMiniport(
105 _In_ PFDO_DEVICE_EXTENSION DeviceExtension
)
107 PHW_INITIALIZATION_DATA InitData
;
108 INTERFACE_TYPE InterfaceType
;
111 DPRINT1("PortFdoStartDevice(%p)\n", DeviceExtension
);
113 /* Get the interface type of the lower device */
114 InterfaceType
= GetBusInterface(DeviceExtension
->LowerDevice
);
115 if (InterfaceType
== InterfaceTypeUndefined
)
116 return STATUS_NO_SUCH_DEVICE
;
118 /* Get the driver init data for the given interface type */
119 InitData
= PortGetDriverInitData(DeviceExtension
->DriverExtension
,
121 if (InitData
== NULL
)
122 return STATUS_NO_SUCH_DEVICE
;
124 /* Initialize the miniport */
125 Status
= MiniportInitialize(&DeviceExtension
->Miniport
,
128 if (!NT_SUCCESS(Status
))
130 DPRINT1("MiniportInitialize() failed (Status 0x%08lx)\n", Status
);
134 /* Call the miniports FindAdapter function */
135 Status
= MiniportFindAdapter(&DeviceExtension
->Miniport
);
136 if (!NT_SUCCESS(Status
))
138 DPRINT1("MiniportFindAdapter() failed (Status 0x%08lx)\n", Status
);
142 /* Connect the configured interrupt */
143 Status
= PortFdoConnectInterrupt(DeviceExtension
);
144 if (!NT_SUCCESS(Status
))
146 DPRINT1("PortFdoConnectInterrupt() failed (Status 0x%08lx)\n", Status
);
150 /* Call the miniports HwInitialize function */
151 Status
= MiniportHwInitialize(&DeviceExtension
->Miniport
);
152 if (!NT_SUCCESS(Status
))
154 DPRINT1("MiniportHwInitialize() failed (Status 0x%08lx)\n", Status
);
158 /* Call the HwPassiveInitRoutine function, if available */
159 if (DeviceExtension
->HwPassiveInitRoutine
!= NULL
)
161 DPRINT1("Calling HwPassiveInitRoutine()\n");
162 if (!DeviceExtension
->HwPassiveInitRoutine(&DeviceExtension
->Miniport
.MiniportExtension
->HwDeviceExtension
))
164 DPRINT1("HwPassiveInitRoutine() failed\n");
165 return STATUS_UNSUCCESSFUL
;
169 return STATUS_SUCCESS
;
177 _In_ PFDO_DEVICE_EXTENSION DeviceExtension
,
180 PIO_STACK_LOCATION Stack
;
183 DPRINT1("PortFdoStartDevice(%p %p)\n",
184 DeviceExtension
, Irp
);
186 ASSERT(DeviceExtension
->ExtensionType
== FdoExtension
);
188 /* Get the current stack location */
189 Stack
= IoGetCurrentIrpStackLocation(Irp
);
191 /* Start the lower device if the FDO is in 'stopped' state */
192 if (DeviceExtension
->PnpState
== dsStopped
)
194 Status
= ForwardIrpAndWait(DeviceExtension
->LowerDevice
, Irp
);
195 if (!NT_SUCCESS(Status
))
197 DPRINT1("ForwardIrpAndWait() failed (Status 0x%08lx)\n", Status
);
202 /* Change to the 'started' state */
203 DeviceExtension
->PnpState
= dsStarted
;
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
)
209 DeviceExtension
->AllocatedResources
= CopyResourceList(NonPagedPool
,
210 Stack
->Parameters
.StartDevice
.AllocatedResources
);
211 if (DeviceExtension
->AllocatedResources
== NULL
)
212 return STATUS_NO_MEMORY
;
214 DeviceExtension
->TranslatedResources
= CopyResourceList(NonPagedPool
,
215 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
);
216 if (DeviceExtension
->TranslatedResources
== NULL
)
217 return STATUS_NO_MEMORY
;
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
),
225 &DeviceExtension
->BusInterface
,
227 DPRINT1("Status: 0x%08lx\n", Status
);
228 if (NT_SUCCESS(Status
))
230 DPRINT1("Context: %p\n", DeviceExtension
->BusInterface
.Context
);
231 DeviceExtension
->BusInitialized
= TRUE
;
234 /* Start the miniport (FindAdapter & Initialize) */
235 Status
= PortFdoStartMiniport(DeviceExtension
);
236 if (!NT_SUCCESS(Status
))
238 DPRINT1("FdoStartMiniport() failed (Status 0x%08lx)\n", Status
);
239 DeviceExtension
->PnpState
= dsStopped
;
248 _In_ PDEVICE_OBJECT DeviceObject
,
253 PINQUIRYDATA InquiryBuffer
;
254 PUCHAR
/*PSENSE_DATA*/ SenseBuffer
;
255 BOOLEAN KeepTrying
= TRUE
;
256 ULONG RetryCount
= 0;
257 SCSI_REQUEST_BLOCK Srb
;
259 PFDO_DEVICE_EXTENSION DeviceExtension
;
260 PVOID SrbExtension
= NULL
;
265 DPRINT("PortSendInquiry(%p %lu %lu %lu)\n",
266 DeviceObject
, Bus
, Target
, Lun
);
268 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
270 InquiryBuffer
= ExAllocatePoolWithTag(NonPagedPool
, INQUIRYDATABUFFERSIZE
, TAG_INQUIRY_DATA
);
271 if (InquiryBuffer
== NULL
)
272 return STATUS_INSUFFICIENT_RESOURCES
;
274 SenseBuffer
= ExAllocatePoolWithTag(NonPagedPool
, SENSE_BUFFER_SIZE
, TAG_SENSE_DATA
);
275 if (SenseBuffer
== NULL
)
277 ExFreePoolWithTag(InquiryBuffer
, TAG_INQUIRY_DATA
);
278 return STATUS_INSUFFICIENT_RESOURCES
;
281 if (DeviceExtension
->Miniport
.PortConfig
.SrbExtensionSize
!= 0)
283 SrbExtension
= ExAllocatePoolWithTag(NonPagedPool
,
284 DeviceExtension
->Miniport
.PortConfig
.SrbExtensionSize
,
286 if (SrbExtension
== NULL
)
288 ExFreePoolWithTag(SenseBuffer
, TAG_SENSE_DATA
);
289 ExFreePoolWithTag(InquiryBuffer
, TAG_INQUIRY_DATA
);
290 return STATUS_INSUFFICIENT_RESOURCES
;
297 RtlZeroMemory(&Srb
, sizeof(SCSI_REQUEST_BLOCK
));
299 Srb
.Length
= sizeof(SCSI_REQUEST_BLOCK
);
300 // Srb.OriginalRequest = Irp;
302 Srb
.TargetId
= Target
;
304 Srb
.Function
= SRB_FUNCTION_EXECUTE_SCSI
;
305 Srb
.SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
306 Srb
.TimeOutValue
= 4;
309 Srb
.SenseInfoBuffer
= SenseBuffer
;
310 Srb
.SenseInfoBufferLength
= SENSE_BUFFER_SIZE
;
312 Srb
.DataBuffer
= InquiryBuffer
;
313 Srb
.DataTransferLength
= INQUIRYDATABUFFERSIZE
;
315 Srb
.SrbExtension
= SrbExtension
;
319 Cdb
->CDB6INQUIRY3
.OperationCode
= SCSIOP_INQUIRY
;
320 Cdb
->CDB6INQUIRY3
.EnableVitalProductData
= 1;
321 Cdb
->CDB6INQUIRY3
.CommandSupportData
= 0;
322 Cdb
->CDB6INQUIRY3
.PageCode
= 0; //??
323 Cdb
->CDB6INQUIRY3
.AllocationLength
= INQUIRYDATABUFFERSIZE
;
324 Cdb
->CDB6INQUIRY3
.Control
= 0;
326 /* Call the miniport driver */
327 ret
= MiniportStartIo(&DeviceExtension
->Miniport
,
331 Status
= STATUS_IO_DEVICE_ERROR
;
336 DPRINT("SrbStatus 0x%08lx\n", Srb
.SrbStatus
);
337 if (SRB_STATUS(Srb
.SrbStatus
) == SRB_STATUS_SUCCESS
)
339 DPRINT("Found a device!\n");
341 UnitData
= ExAllocatePool(NonPagedPool
, sizeof(UNIT_DATA
));
342 if (UnitData
== NULL
)
344 Status
= STATUS_INSUFFICIENT_RESOURCES
;
349 /* All fine, copy data over */
350 RtlCopyMemory(&UnitData
->InquiryData
,
352 Srb
.DataTransferLength
);
354 InsertTailList(&DeviceExtension
->UnitListHead
,
355 &UnitData
->ListEntry
);
356 DeviceExtension
->UnitCount
++;
359 Status
= STATUS_SUCCESS
;
364 DPRINT("Inquiry SRB failed with SrbStatus 0x%08X\n", Srb
.SrbStatus
);
366 /* Retry a couple of times if no timeout happened */
367 if ((RetryCount
< 2) &&
368 (SRB_STATUS(Srb
.SrbStatus
) != SRB_STATUS_NO_DEVICE
) &&
369 (SRB_STATUS(Srb
.SrbStatus
) != SRB_STATUS_SELECTION_TIMEOUT
))
376 /* That's all, quit the loop */
379 /* Set status according to SRB status */
380 if (SRB_STATUS(Srb
.SrbStatus
) == SRB_STATUS_BAD_FUNCTION
||
381 SRB_STATUS(Srb
.SrbStatus
) == SRB_STATUS_BAD_SRB_BLOCK_LENGTH
)
383 Status
= STATUS_INVALID_DEVICE_REQUEST
;
387 Status
= STATUS_IO_DEVICE_ERROR
;
393 if (SrbExtension
!= NULL
)
394 ExFreePoolWithTag(SrbExtension
, TAG_SENSE_DATA
);
396 ExFreePoolWithTag(SenseBuffer
, TAG_SENSE_DATA
);
397 ExFreePoolWithTag(InquiryBuffer
, TAG_INQUIRY_DATA
);
399 DPRINT("PortSendInquiry() returns 0x%08lx\n", Status
);
408 _In_ PFDO_DEVICE_EXTENSION DeviceExtension
)
410 ULONG Bus
, Target
, Lun
;
413 DPRINT1("PortFdoScanBus(%p)\n",
416 DPRINT1("NumberOfBuses: %lu\n", DeviceExtension
->Miniport
.PortConfig
.NumberOfBuses
);
417 DPRINT1("MaximumNumberOfTargets: %lu\n", DeviceExtension
->Miniport
.PortConfig
.MaximumNumberOfTargets
);
418 DPRINT1("MaximumNumberOfLogicalUnits: %lu\n", DeviceExtension
->Miniport
.PortConfig
.MaximumNumberOfLogicalUnits
);
421 for (Bus
= 0; Bus
< DeviceExtension
->Miniport
.PortConfig
.NumberOfBuses
; Bus
++)
423 DPRINT1("Scanning bus %ld\n", Bus
);
425 /* Scan all targets */
426 for (Target
= 0; Target
< DeviceExtension
->Miniport
.PortConfig
.MaximumNumberOfTargets
; Target
++)
428 DPRINT1(" Scanning target %ld:%ld\n", Bus
, Target
);
430 /* Scan all logical units */
431 for (Lun
= 0; Lun
< DeviceExtension
->Miniport
.PortConfig
.MaximumNumberOfLogicalUnits
; Lun
++)
433 DPRINT1(" Scanning logical unit %ld:%ld:%ld\n", Bus
, Target
, Lun
);
435 Status
= PortSendInquiry(DeviceExtension
->Device
, Bus
, Target
, Lun
);
436 DPRINT1("PortSendInquiry returned 0x%08lx\n", Status
);
437 if (!NT_SUCCESS(Status
))
445 return STATUS_SUCCESS
;
451 PortFdoQueryBusRelations(
452 _In_ PFDO_DEVICE_EXTENSION DeviceExtension
,
453 _Out_ PULONG_PTR Information
)
455 NTSTATUS Status
= STATUS_SUCCESS
;;
457 DPRINT1("PortFdoQueryBusRelations(%p %p)\n",
458 DeviceExtension
, Information
);
460 Status
= PortFdoScanBus(DeviceExtension
);
462 DPRINT1("Units found: %lu\n", DeviceExtension
->UnitCount
);
472 PortFdoFilterRequirements(
473 PFDO_DEVICE_EXTENSION DeviceExtension
,
476 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
;
478 DPRINT1("PortFdoFilterRequirements(%p %p)\n", DeviceExtension
, Irp
);
480 /* Get the bus number and the slot number */
481 RequirementsList
=(PIO_RESOURCE_REQUIREMENTS_LIST
)Irp
->IoStatus
.Information
;
482 if (RequirementsList
!= NULL
)
484 DeviceExtension
->BusNumber
= RequirementsList
->BusNumber
;
485 DeviceExtension
->SlotNumber
= RequirementsList
->SlotNumber
;
488 return STATUS_SUCCESS
;
495 _In_ PDEVICE_OBJECT DeviceObject
,
498 PFDO_DEVICE_EXTENSION DeviceExtension
;
499 // PIO_STACK_LOCATION Stack;
500 ULONG_PTR Information
= 0;
501 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
503 DPRINT1("PortFdoScsi(%p %p)\n",
506 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
507 ASSERT(DeviceExtension
);
508 ASSERT(DeviceExtension
->ExtensionType
== FdoExtension
);
510 // Stack = IoGetCurrentIrpStackLocation(Irp);
513 Irp
->IoStatus
.Information
= Information
;
514 Irp
->IoStatus
.Status
= Status
;
515 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
524 _In_ PDEVICE_OBJECT DeviceObject
,
527 PFDO_DEVICE_EXTENSION DeviceExtension
;
528 PIO_STACK_LOCATION Stack
;
529 ULONG_PTR Information
= 0;
530 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
532 DPRINT1("PortFdoPnp(%p %p)\n",
535 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
536 ASSERT(DeviceExtension
);
537 ASSERT(DeviceExtension
->ExtensionType
== FdoExtension
);
539 Stack
= IoGetCurrentIrpStackLocation(Irp
);
541 switch (Stack
->MinorFunction
)
543 case IRP_MN_START_DEVICE
: /* 0x00 */
544 DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
545 Status
= PortFdoStartDevice(DeviceExtension
, Irp
);
548 case IRP_MN_QUERY_REMOVE_DEVICE
: /* 0x01 */
549 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n");
552 case IRP_MN_REMOVE_DEVICE
: /* 0x02 */
553 DPRINT1("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
556 case IRP_MN_CANCEL_REMOVE_DEVICE
: /* 0x03 */
557 DPRINT1("IRP_MJ_PNP / IRP_MN_CANCEL_REMOVE_DEVICE\n");
560 case IRP_MN_STOP_DEVICE
: /* 0x04 */
561 DPRINT1("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
564 case IRP_MN_QUERY_STOP_DEVICE
: /* 0x05 */
565 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_STOP_DEVICE\n");
568 case IRP_MN_CANCEL_STOP_DEVICE
: /* 0x06 */
569 DPRINT1("IRP_MJ_PNP / IRP_MN_CANCEL_STOP_DEVICE\n");
572 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x07 */
573 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n");
574 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
577 DPRINT1(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
578 Status
= PortFdoQueryBusRelations(DeviceExtension
, &Information
);
581 case RemovalRelations
:
582 DPRINT1(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
583 return ForwardIrpAndForget(DeviceExtension
->LowerDevice
, Irp
);
586 DPRINT1(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
587 Stack
->Parameters
.QueryDeviceRelations
.Type
);
588 return ForwardIrpAndForget(DeviceExtension
->LowerDevice
, Irp
);
592 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* 0x0d */
593 DPRINT1("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
594 PortFdoFilterRequirements(DeviceExtension
, Irp
);
595 return ForwardIrpAndForget(DeviceExtension
->LowerDevice
, Irp
);
597 case IRP_MN_QUERY_PNP_DEVICE_STATE
: /* 0x14 */
598 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
601 case IRP_MN_DEVICE_USAGE_NOTIFICATION
: /* 0x16 */
602 DPRINT1("IRP_MJ_PNP / IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
605 case IRP_MN_SURPRISE_REMOVAL
: /* 0x17 */
606 DPRINT1("IRP_MJ_PNP / IRP_MN_SURPRISE_REMOVAL\n");
610 DPRINT1("IRP_MJ_PNP / Unknown IOCTL 0x%lx\n", Stack
->MinorFunction
);
611 return ForwardIrpAndForget(DeviceExtension
->LowerDevice
, Irp
);
614 Irp
->IoStatus
.Information
= Information
;
615 Irp
->IoStatus
.Status
= Status
;
616 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);