mirror of
https://github.com/reactos/reactos.git
synced 2024-10-31 03:48:17 +00:00
5cfc1e3152
CORE-13866
382 lines
11 KiB
C
382 lines
11 KiB
C
/*
|
|
* 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 <debug.h>
|
|
|
|
|
|
/* 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;
|
|
}
|
|
|
|
|
|
Status = PortFdoConnectInterrupt(DeviceExtension);
|
|
|
|
|
|
/* 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 */
|