/* * PROJECT: ReactOS Storport Driver * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * PURPOSE: Storport FDO code * COPYRIGHT: Copyright 2017 Eric Kohl (eric.kohl@reactos.org) */ /* INCLUDES *******************************************************************/ #include "precomp.h" #define NDEBUG #include /* FUNCTIONS ******************************************************************/ static BOOLEAN NTAPI PortFdoInterruptRoutine( _In_ PKINTERRUPT Interrupt, _In_ PVOID ServiceContext) { PFDO_DEVICE_EXTENSION DeviceExtension; DPRINT1("PortFdoInterruptRoutine(%p %p)\n", Interrupt, ServiceContext); DeviceExtension = (PFDO_DEVICE_EXTENSION)ServiceContext; return MiniportHwInterrupt(&DeviceExtension->Miniport); } static NTSTATUS PortFdoConnectInterrupt( _In_ PFDO_DEVICE_EXTENSION DeviceExtension) { ULONG Vector; KIRQL Irql; KINTERRUPT_MODE InterruptMode; BOOLEAN ShareVector; KAFFINITY Affinity; NTSTATUS Status; DPRINT1("PortFdoConnectInterrupt(%p)\n", DeviceExtension); /* No resources, no interrupt. Done! */ if (DeviceExtension->AllocatedResources == NULL || DeviceExtension->TranslatedResources == NULL) { DPRINT1("Checkpoint\n"); return STATUS_SUCCESS; } /* Get the interrupt data from the resource list */ Status = GetResourceListInterrupt(DeviceExtension, &Vector, &Irql, &InterruptMode, &ShareVector, &Affinity); if (!NT_SUCCESS(Status)) { DPRINT1("GetResourceListInterrupt() failed (Status 0x%08lx)\n", Status); return Status; } DPRINT1("Vector: %lu\n", Vector); DPRINT1("Irql: %lu\n", Irql); DPRINT1("Affinity: 0x%08lx\n", Affinity); /* Connect the interrupt */ Status = IoConnectInterrupt(&DeviceExtension->Interrupt, PortFdoInterruptRoutine, DeviceExtension, NULL, Vector, Irql, Irql, InterruptMode, ShareVector, Affinity, FALSE); if (NT_SUCCESS(Status)) { DeviceExtension->InterruptIrql = Irql; } else { DPRINT1("IoConnectInterrupt() failed (Status 0x%08lx)\n", Status); } return Status; } static NTSTATUS PortFdoStartMiniport( _In_ PFDO_DEVICE_EXTENSION DeviceExtension) { PHW_INITIALIZATION_DATA InitData; INTERFACE_TYPE InterfaceType; NTSTATUS Status; DPRINT1("PortFdoStartDevice(%p)\n", DeviceExtension); /* Get the interface type of the lower device */ InterfaceType = GetBusInterface(DeviceExtension->LowerDevice); if (InterfaceType == InterfaceTypeUndefined) return STATUS_NO_SUCH_DEVICE; /* Get the driver init data for the given interface type */ InitData = PortGetDriverInitData(DeviceExtension->DriverExtension, InterfaceType); if (InitData == NULL) return STATUS_NO_SUCH_DEVICE; /* Initialize the miniport */ Status = MiniportInitialize(&DeviceExtension->Miniport, DeviceExtension, InitData); if (!NT_SUCCESS(Status)) { DPRINT1("MiniportInitialize() failed (Status 0x%08lx)\n", Status); return Status; } /* Call the miniports FindAdapter function */ Status = MiniportFindAdapter(&DeviceExtension->Miniport); if (!NT_SUCCESS(Status)) { DPRINT1("MiniportFindAdapter() failed (Status 0x%08lx)\n", Status); return Status; } /* Connect the configured interrupt */ Status = PortFdoConnectInterrupt(DeviceExtension); if (!NT_SUCCESS(Status)) { DPRINT1("PortFdoConnectInterrupt() failed (Status 0x%08lx)\n", Status); return Status; } /* Call the miniports HwInitialize function */ Status = MiniportHwInitialize(&DeviceExtension->Miniport); if (!NT_SUCCESS(Status)) { DPRINT1("MiniportHwInitialize() failed (Status 0x%08lx)\n", Status); return Status; } /* Call the HwPassiveInitRoutine function, if available */ if (DeviceExtension->HwPassiveInitRoutine != NULL) { DPRINT1("Calling HwPassiveInitRoutine()\n"); if (!DeviceExtension->HwPassiveInitRoutine(&DeviceExtension->Miniport.MiniportExtension->HwDeviceExtension)) { DPRINT1("HwPassiveInitRoutine() failed\n"); return STATUS_UNSUCCESSFUL; } } return STATUS_SUCCESS; } static NTSTATUS NTAPI PortFdoStartDevice( _In_ PFDO_DEVICE_EXTENSION DeviceExtension, _In_ PIRP Irp) { PIO_STACK_LOCATION Stack; NTSTATUS Status; DPRINT1("PortFdoStartDevice(%p %p)\n", DeviceExtension, Irp); ASSERT(DeviceExtension->ExtensionType == FdoExtension); /* Get the current stack location */ Stack = IoGetCurrentIrpStackLocation(Irp); /* Start the lower device if the FDO is in 'stopped' state */ if (DeviceExtension->PnpState == dsStopped) { Status = ForwardIrpAndWait(DeviceExtension->LowerDevice, Irp); if (!NT_SUCCESS(Status)) { DPRINT1("ForwardIrpAndWait() failed (Status 0x%08lx)\n", Status); return Status; } } /* Change to the 'started' state */ DeviceExtension->PnpState = dsStarted; /* Copy the raw and translated resource lists into the device extension */ if (Stack->Parameters.StartDevice.AllocatedResources != NULL && Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL) { DeviceExtension->AllocatedResources = CopyResourceList(NonPagedPool, Stack->Parameters.StartDevice.AllocatedResources); if (DeviceExtension->AllocatedResources == NULL) return STATUS_NO_MEMORY; DeviceExtension->TranslatedResources = CopyResourceList(NonPagedPool, Stack->Parameters.StartDevice.AllocatedResourcesTranslated); if (DeviceExtension->TranslatedResources == NULL) return STATUS_NO_MEMORY; } /* Get the bus interface of the lower (bus) device */ Status = QueryBusInterface(DeviceExtension->LowerDevice, (PGUID)&GUID_BUS_INTERFACE_STANDARD, sizeof(BUS_INTERFACE_STANDARD), 1, &DeviceExtension->BusInterface, NULL); DPRINT1("Status: 0x%08lx\n", Status); if (NT_SUCCESS(Status)) { DPRINT1("Context: %p\n", DeviceExtension->BusInterface.Context); DeviceExtension->BusInitialized = TRUE; } /* Start the miniport (FindAdapter & Initialize) */ Status = PortFdoStartMiniport(DeviceExtension); if (!NT_SUCCESS(Status)) { DPRINT1("FdoStartMiniport() failed (Status 0x%08lx)\n", Status); DeviceExtension->PnpState = dsStopped; } return Status; } static NTSTATUS PortFdoQueryBusRelations( _In_ PFDO_DEVICE_EXTENSION DeviceExtension, _Out_ PULONG_PTR Information) { NTSTATUS Status = STATUS_SUCCESS;; DPRINT1("PortFdoQueryBusRelations(%p %p)\n", DeviceExtension, Information); *Information = 0; return Status; } static NTSTATUS PortFdoFilterRequirements( PFDO_DEVICE_EXTENSION DeviceExtension, PIRP Irp) { PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; DPRINT1("PortFdoFilterRequirements(%p %p)\n", DeviceExtension, Irp); /* Get the bus number and the slot number */ RequirementsList =(PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information; if (RequirementsList != NULL) { DeviceExtension->BusNumber = RequirementsList->BusNumber; DeviceExtension->SlotNumber = RequirementsList->SlotNumber; } return STATUS_SUCCESS; } NTSTATUS NTAPI PortFdoPnp( _In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) { PFDO_DEVICE_EXTENSION DeviceExtension; PIO_STACK_LOCATION Stack; ULONG_PTR Information = 0; NTSTATUS Status = STATUS_NOT_SUPPORTED; DPRINT1("PortFdoPnp(%p %p)\n", DeviceObject, Irp); DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ASSERT(DeviceExtension); ASSERT(DeviceExtension->ExtensionType == FdoExtension); Stack = IoGetCurrentIrpStackLocation(Irp); switch (Stack->MinorFunction) { case IRP_MN_START_DEVICE: /* 0x00 */ DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); Status = PortFdoStartDevice(DeviceExtension, Irp); break; case IRP_MN_QUERY_REMOVE_DEVICE: /* 0x01 */ DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n"); break; case IRP_MN_REMOVE_DEVICE: /* 0x02 */ DPRINT1("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n"); break; case IRP_MN_CANCEL_REMOVE_DEVICE: /* 0x03 */ DPRINT1("IRP_MJ_PNP / IRP_MN_CANCEL_REMOVE_DEVICE\n"); break; case IRP_MN_STOP_DEVICE: /* 0x04 */ DPRINT1("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n"); break; case IRP_MN_QUERY_STOP_DEVICE: /* 0x05 */ DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_STOP_DEVICE\n"); break; case IRP_MN_CANCEL_STOP_DEVICE: /* 0x06 */ DPRINT1("IRP_MJ_PNP / IRP_MN_CANCEL_STOP_DEVICE\n"); break; case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */ DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n"); switch (Stack->Parameters.QueryDeviceRelations.Type) { case BusRelations: DPRINT1(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); Status = PortFdoQueryBusRelations(DeviceExtension, &Information); break; case RemovalRelations: DPRINT1(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n"); return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp); default: DPRINT1(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", Stack->Parameters.QueryDeviceRelations.Type); return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp); } break; case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0x0d */ DPRINT1("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"); PortFdoFilterRequirements(DeviceExtension, Irp); return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp); case IRP_MN_QUERY_PNP_DEVICE_STATE: /* 0x14 */ DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n"); break; case IRP_MN_DEVICE_USAGE_NOTIFICATION: /* 0x16 */ DPRINT1("IRP_MJ_PNP / IRP_MN_DEVICE_USAGE_NOTIFICATION\n"); break; case IRP_MN_SURPRISE_REMOVAL: /* 0x17 */ DPRINT1("IRP_MJ_PNP / IRP_MN_SURPRISE_REMOVAL\n"); break; default: DPRINT1("IRP_MJ_PNP / Unknown IOCTL 0x%lx\n", Stack->MinorFunction); return ForwardIrpAndForget(DeviceExtension->LowerDevice, Irp); } Irp->IoStatus.Information = Information; Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } /* EOF */