mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-27 11:53:32 +00:00
[NTOS:PNP] Halfplement IoInvalidateDeviceState
Implement the correct start-stop sequence for resource rebalancing without the actual rebalancing. Also move IoInvalidateDeviceState processing into the enumeration thread as it should be. CORE-17519
This commit is contained in:
@@ -527,7 +527,8 @@ typedef enum _DEVICE_ACTION
|
|||||||
PiActionEnumRootDevices,
|
PiActionEnumRootDevices,
|
||||||
PiActionResetDevice,
|
PiActionResetDevice,
|
||||||
PiActionAddBootDevices,
|
PiActionAddBootDevices,
|
||||||
PiActionStartDevice
|
PiActionStartDevice,
|
||||||
|
PiActionQueryState,
|
||||||
} DEVICE_ACTION;
|
} DEVICE_ACTION;
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -1403,6 +1404,16 @@ PiIrpQueryDeviceRelations(
|
|||||||
_In_ PDEVICE_NODE DeviceNode,
|
_In_ PDEVICE_NODE DeviceNode,
|
||||||
_In_ DEVICE_RELATION_TYPE Type);
|
_In_ DEVICE_RELATION_TYPE Type);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
PiIrpQueryResources(
|
||||||
|
_In_ PDEVICE_NODE DeviceNode,
|
||||||
|
_Out_ PCM_RESOURCE_LIST *Resources);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
PiIrpQueryResourceRequirements(
|
||||||
|
_In_ PDEVICE_NODE DeviceNode,
|
||||||
|
_Out_ PIO_RESOURCE_REQUIREMENTS_LIST *Resources);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
PiIrpQueryDeviceText(
|
PiIrpQueryDeviceText(
|
||||||
_In_ PDEVICE_NODE DeviceNode,
|
_In_ PDEVICE_NODE DeviceNode,
|
||||||
|
|||||||
@@ -1552,8 +1552,8 @@ PiStartDeviceFinal(
|
|||||||
DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status);
|
DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Invalidate device state so IRP_MN_QUERY_PNP_DEVICE_STATE is sent */
|
// Query the device state (IRP_MN_QUERY_PNP_DEVICE_STATE)
|
||||||
IoInvalidateDeviceState(DeviceNode->PhysicalDeviceObject);
|
PiQueueDeviceAction(DeviceNode->PhysicalDeviceObject, PiActionQueryState, NULL, NULL);
|
||||||
|
|
||||||
DPRINT("Sending GUID_DEVICE_ARRIVAL %wZ\n", &DeviceNode->InstancePath);
|
DPRINT("Sending GUID_DEVICE_ARRIVAL %wZ\n", &DeviceNode->InstancePath);
|
||||||
IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, &DeviceNode->InstancePath);
|
IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, &DeviceNode->InstancePath);
|
||||||
@@ -2025,25 +2025,27 @@ IopRemoveDevice(PDEVICE_NODE DeviceNode)
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* @implemented
|
* @brief Processes the IoInvalidateDeviceState request
|
||||||
|
*
|
||||||
|
* Sends IRP_MN_QUERY_PNP_DEVICE_STATE request and sets device node's flags
|
||||||
|
* according to the result.
|
||||||
|
* Tree reenumeration should be started upon a successful return of the function.
|
||||||
|
*
|
||||||
|
* @todo Do not return STATUS_SUCCESS if nothing is changed.
|
||||||
*/
|
*/
|
||||||
VOID
|
static
|
||||||
NTAPI
|
NTSTATUS
|
||||||
IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject)
|
PiUpdateDeviceState(
|
||||||
|
_In_ PDEVICE_NODE DeviceNode)
|
||||||
{
|
{
|
||||||
PDEVICE_NODE DeviceNode = IopGetDeviceNode(PhysicalDeviceObject);
|
|
||||||
PNP_DEVICE_STATE PnPFlags;
|
PNP_DEVICE_STATE PnPFlags;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
Status = PiIrpQueryPnPDeviceState(DeviceNode, &PnPFlags);
|
Status = PiIrpQueryPnPDeviceState(DeviceNode, &PnPFlags);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
if (Status != STATUS_NOT_SUPPORTED)
|
return Status;
|
||||||
{
|
|
||||||
DPRINT1("IRP_MN_QUERY_PNP_DEVICE_STATE failed with status 0x%lx\n", Status);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PnPFlags & PNP_DEVICE_NOT_DISABLEABLE)
|
if (PnPFlags & PNP_DEVICE_NOT_DISABLEABLE)
|
||||||
@@ -2056,83 +2058,37 @@ IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject)
|
|||||||
else
|
else
|
||||||
DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
|
DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
|
||||||
|
|
||||||
if ((PnPFlags & PNP_DEVICE_REMOVED) ||
|
if (PnPFlags & PNP_DEVICE_REMOVED || PnPFlags & PNP_DEVICE_DISABLED)
|
||||||
((PnPFlags & PNP_DEVICE_FAILED) && !(PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)))
|
|
||||||
{
|
{
|
||||||
/* Flag it if it's failed */
|
PiSetDevNodeProblem(DeviceNode,
|
||||||
if (PnPFlags & PNP_DEVICE_FAILED)
|
PnPFlags & PNP_DEVICE_DISABLED
|
||||||
{
|
? CM_PROB_HARDWARE_DISABLED
|
||||||
PiSetDevNodeProblem(DeviceNode, CM_PROB_FAILED_POST_START);
|
: CM_PROB_DEVICE_NOT_THERE);
|
||||||
}
|
|
||||||
|
|
||||||
DeviceNode->Flags |= DNF_DEVICE_GONE;
|
|
||||||
PiSetDevNodeState(DeviceNode, DeviceNodeAwaitingQueuedRemoval);
|
PiSetDevNodeState(DeviceNode, DeviceNodeAwaitingQueuedRemoval);
|
||||||
}
|
}
|
||||||
// it doesn't work anyway. A real resource rebalancing should be implemented
|
else if (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)
|
||||||
#if 0
|
|
||||||
else if ((PnPFlags & PNP_DEVICE_FAILED) && (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED))
|
|
||||||
{
|
{
|
||||||
/* Stop for resource rebalance */
|
// Query resource rebalance
|
||||||
Status = IopStopDevice(DeviceNode);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to stop device for rebalancing\n");
|
|
||||||
|
|
||||||
/* Stop failed so don't rebalance */
|
if (PnPFlags & PNP_DEVICE_FAILED)
|
||||||
PnPFlags &= ~PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED;
|
DeviceNode->Flags &= DNF_NON_STOPPED_REBALANCE;
|
||||||
}
|
else
|
||||||
|
DeviceNode->Flags |= DNF_NON_STOPPED_REBALANCE;
|
||||||
|
|
||||||
|
// Clear DNF_NO_RESOURCE_REQUIRED just in case (will be set back if needed)
|
||||||
|
DeviceNode->Flags &= ~DNF_NO_RESOURCE_REQUIRED;
|
||||||
|
|
||||||
|
// This will be caught up later by enumeration
|
||||||
|
DeviceNode->Flags |= DNF_RESOURCE_REQUIREMENTS_CHANGED;
|
||||||
|
}
|
||||||
|
else if (PnPFlags & PNP_DEVICE_FAILED)
|
||||||
|
{
|
||||||
|
PiSetDevNodeProblem(DeviceNode, CM_PROB_FAILED_POST_START);
|
||||||
|
PiSetDevNodeState(DeviceNode, DeviceNodeAwaitingQueuedRemoval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resource rebalance */
|
return STATUS_SUCCESS;
|
||||||
if (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)
|
|
||||||
{
|
|
||||||
DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
|
|
||||||
|
|
||||||
Status = IopInitiatePnpIrp(PhysicalDeviceObject,
|
|
||||||
&IoStatusBlock,
|
|
||||||
IRP_MN_QUERY_RESOURCES,
|
|
||||||
NULL);
|
|
||||||
if (NT_SUCCESS(Status) && IoStatusBlock.Information)
|
|
||||||
{
|
|
||||||
DeviceNode->BootResources =
|
|
||||||
(PCM_RESOURCE_LIST)IoStatusBlock.Information;
|
|
||||||
IopDeviceNodeSetFlag(DeviceNode, DNF_HAS_BOOT_CONFIG);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
|
|
||||||
DeviceNode->BootResources = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
|
|
||||||
|
|
||||||
Status = IopInitiatePnpIrp(PhysicalDeviceObject,
|
|
||||||
&IoStatusBlock,
|
|
||||||
IRP_MN_QUERY_RESOURCE_REQUIREMENTS,
|
|
||||||
NULL);
|
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DeviceNode->ResourceRequirements =
|
|
||||||
(PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
|
|
||||||
DeviceNode->ResourceRequirements = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* IRP_MN_FILTER_RESOURCE_REQUIREMENTS is called indirectly by IopStartDevice */
|
|
||||||
if (IopStartDevice(DeviceNode) != STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
DPRINT1("Restart after resource rebalance failed\n");
|
|
||||||
|
|
||||||
DeviceNode->Flags &= ~(DNF_STARTED | DNF_START_REQUEST_PENDING);
|
|
||||||
DeviceNode->Flags |= DNF_START_FAILED;
|
|
||||||
|
|
||||||
IopRemoveDevice(DeviceNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@@ -2327,6 +2283,30 @@ cleanup:
|
|||||||
&DeviceNode->InstancePath);
|
&DeviceNode->InstancePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
PiFakeResourceRebalance(
|
||||||
|
_In_ PDEVICE_NODE DeviceNode)
|
||||||
|
{
|
||||||
|
ASSERT(DeviceNode->Flags & DNF_RESOURCE_REQUIREMENTS_CHANGED);
|
||||||
|
|
||||||
|
PCM_RESOURCE_LIST bootConfig = NULL;
|
||||||
|
PIO_RESOURCE_REQUIREMENTS_LIST resourceRequirements = NULL;
|
||||||
|
|
||||||
|
PiIrpQueryResources(DeviceNode, &bootConfig);
|
||||||
|
PiIrpQueryResourceRequirements(DeviceNode, &resourceRequirements);
|
||||||
|
|
||||||
|
DeviceNode->BootResources = bootConfig;
|
||||||
|
DeviceNode->ResourceRequirements = resourceRequirements;
|
||||||
|
|
||||||
|
if (bootConfig)
|
||||||
|
{
|
||||||
|
DeviceNode->Flags |= DNF_HAS_BOOT_CONFIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceNode->Flags &= ~DNF_RESOURCE_REQUIREMENTS_CHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
VOID
|
VOID
|
||||||
PiDevNodeStateMachine(
|
PiDevNodeStateMachine(
|
||||||
@@ -2420,12 +2400,28 @@ PiDevNodeStateMachine(
|
|||||||
PiSetDevNodeState(currentNode, DeviceNodeEnumerateCompletion);
|
PiSetDevNodeState(currentNode, DeviceNodeEnumerateCompletion);
|
||||||
doProcessAgain = TRUE;
|
doProcessAgain = TRUE;
|
||||||
}
|
}
|
||||||
|
else if (currentNode->Flags & DNF_RESOURCE_REQUIREMENTS_CHANGED)
|
||||||
|
{
|
||||||
|
if (currentNode->Flags & DNF_NON_STOPPED_REBALANCE)
|
||||||
|
{
|
||||||
|
PiFakeResourceRebalance(currentNode);
|
||||||
|
currentNode->Flags &= ~DNF_NON_STOPPED_REBALANCE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PiIrpQueryStopDevice(currentNode);
|
||||||
|
PiSetDevNodeState(currentNode, DeviceNodeQueryStopped);
|
||||||
|
}
|
||||||
|
|
||||||
|
doProcessAgain = TRUE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case DeviceNodeQueryStopped:
|
case DeviceNodeQueryStopped:
|
||||||
// we're here after sending IRP_MN_QUERY_STOP_DEVICE
|
// we're here after sending IRP_MN_QUERY_STOP_DEVICE
|
||||||
status = currentNode->CompletionStatus;
|
status = currentNode->CompletionStatus;
|
||||||
if (NT_SUCCESS(status))
|
if (NT_SUCCESS(status))
|
||||||
{
|
{
|
||||||
|
PiIrpStopDevice(currentNode);
|
||||||
PiSetDevNodeState(currentNode, DeviceNodeStopped);
|
PiSetDevNodeState(currentNode, DeviceNodeStopped);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2433,10 +2429,14 @@ PiDevNodeStateMachine(
|
|||||||
PiIrpCancelStopDevice(currentNode);
|
PiIrpCancelStopDevice(currentNode);
|
||||||
PiSetDevNodeState(currentNode, DeviceNodeStarted);
|
PiSetDevNodeState(currentNode, DeviceNodeStarted);
|
||||||
}
|
}
|
||||||
|
doProcessAgain = TRUE;
|
||||||
break;
|
break;
|
||||||
case DeviceNodeStopped:
|
case DeviceNodeStopped:
|
||||||
// TODO: do resource rebalance (not implemented)
|
// TODO: do resource rebalance (not implemented)
|
||||||
ASSERT(FALSE);
|
PiFakeResourceRebalance(currentNode);
|
||||||
|
|
||||||
|
PiSetDevNodeState(currentNode, DeviceNodeDriversAdded);
|
||||||
|
doProcessAgain = TRUE;
|
||||||
break;
|
break;
|
||||||
case DeviceNodeRestartCompletion:
|
case DeviceNodeRestartCompletion:
|
||||||
break;
|
break;
|
||||||
@@ -2522,6 +2522,8 @@ ActionToStr(
|
|||||||
return "PiActionAddBootDevices";
|
return "PiActionAddBootDevices";
|
||||||
case PiActionStartDevice:
|
case PiActionStartDevice:
|
||||||
return "PiActionStartDevice";
|
return "PiActionStartDevice";
|
||||||
|
case PiActionQueryState:
|
||||||
|
return "PiActionQueryState";
|
||||||
default:
|
default:
|
||||||
return "(request unknown)";
|
return "(request unknown)";
|
||||||
}
|
}
|
||||||
@@ -2596,6 +2598,16 @@ PipDeviceActionWorker(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PiActionQueryState:
|
||||||
|
// First, do a IRP_MN_QUERY_PNP_DEVICE_STATE request,
|
||||||
|
// it will update node's flags and then do enumeration if something changed
|
||||||
|
status = PiUpdateDeviceState(deviceNode);
|
||||||
|
if (NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
PiDevNodeStateMachine(deviceNode);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DPRINT1("Unimplemented device action %u\n", Request->Action);
|
DPRINT1("Unimplemented device action %u\n", Request->Action);
|
||||||
status = STATUS_NOT_IMPLEMENTED;
|
status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
|||||||
@@ -196,6 +196,58 @@ PiIrpQueryDeviceRelations(
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IRP_MN_QUERY_RESOURCES (0x0A)
|
||||||
|
NTSTATUS
|
||||||
|
PiIrpQueryResources(
|
||||||
|
_In_ PDEVICE_NODE DeviceNode,
|
||||||
|
_Out_ PCM_RESOURCE_LIST *Resources)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
ASSERT(DeviceNode);
|
||||||
|
|
||||||
|
ULONG_PTR longRes;
|
||||||
|
IO_STACK_LOCATION stack = {
|
||||||
|
.MajorFunction = IRP_MJ_PNP,
|
||||||
|
.MinorFunction = IRP_MN_QUERY_RESOURCES
|
||||||
|
};
|
||||||
|
|
||||||
|
NTSTATUS status;
|
||||||
|
status = IopSynchronousCall(DeviceNode->PhysicalDeviceObject, &stack, (PVOID)&longRes);
|
||||||
|
if (NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
*Resources = (PVOID)longRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IRP_MN_QUERY_RESOURCE_REQUIREMENTS (0x0B)
|
||||||
|
NTSTATUS
|
||||||
|
PiIrpQueryResourceRequirements(
|
||||||
|
_In_ PDEVICE_NODE DeviceNode,
|
||||||
|
_Out_ PIO_RESOURCE_REQUIREMENTS_LIST *Resources)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
ASSERT(DeviceNode);
|
||||||
|
|
||||||
|
ULONG_PTR longRes;
|
||||||
|
IO_STACK_LOCATION stack = {
|
||||||
|
.MajorFunction = IRP_MJ_PNP,
|
||||||
|
.MinorFunction = IRP_MN_QUERY_RESOURCE_REQUIREMENTS
|
||||||
|
};
|
||||||
|
|
||||||
|
NTSTATUS status;
|
||||||
|
status = IopSynchronousCall(DeviceNode->PhysicalDeviceObject, &stack, (PVOID)&longRes);
|
||||||
|
if (NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
*Resources = (PVOID)longRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
// IRP_MN_QUERY_DEVICE_TEXT (0x0C)
|
// IRP_MN_QUERY_DEVICE_TEXT (0x0C)
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
PiIrpQueryDeviceText(
|
PiIrpQueryDeviceText(
|
||||||
@@ -236,7 +288,8 @@ PiIrpQueryPnPDeviceState(
|
|||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
ASSERT(DeviceNode);
|
ASSERT(DeviceNode);
|
||||||
ASSERT(DeviceNode->State == DeviceNodeStartPostWork ||
|
ASSERT(DeviceNode->State == DeviceNodeResourcesAssigned ||
|
||||||
|
DeviceNode->State == DeviceNodeStartPostWork ||
|
||||||
DeviceNode->State == DeviceNodeStarted);
|
DeviceNode->State == DeviceNodeStarted);
|
||||||
|
|
||||||
ULONG_PTR longState;
|
ULONG_PTR longState;
|
||||||
|
|||||||
@@ -2412,3 +2412,11 @@ IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
|
|||||||
AddressSpace,
|
AddressSpace,
|
||||||
TranslatedAddress);
|
TranslatedAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
IoInvalidateDeviceState(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PiQueueDeviceAction(DeviceObject, PiActionQueryState, NULL, NULL);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user