#include "private.hpp"
+typedef struct
+{
+ PIRP Irp;
+ PDEVICE_OBJECT DeviceObject;
+}QUERY_POWER_CONTEXT, *PQUERY_POWER_CONTEXT;
+
+
NTSTATUS
NTAPI
PortClsCreate(
NTSTATUS Status;
PPCLASS_DEVICE_EXTENSION DeviceExt;
PIO_STACK_LOCATION IoStack;
+ POWER_STATE PowerState;
IResourceList* resource_list = NULL;
+ //ULONG Index;
+ //PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor, UnPartialDescriptor;
DeviceExt = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
IoStack = IoGetCurrentIrpStackLocation(Irp);
// Assign the resource list to our extension
DeviceExt->resources = resource_list;
+ // store device power state
+ DeviceExt->DevicePowerState = PowerDeviceD0;
+ DeviceExt->SystemPowerState = PowerSystemWorking;
+
+ // notify power manager of current state
+ PowerState = *((POWER_STATE*)&DeviceExt->DevicePowerState);
+ PoSetPowerState(DeviceObject, DevicePowerState, PowerState);
+
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
DeviceExt->resources->Release();
IoDeleteDevice(DeviceObject);
- // Do not complete?
- Irp->IoStatus.Status = STATUS_SUCCESS;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
+ // Forward request
+ Status = PcForwardIrpSynchronous(DeviceObject, Irp);
+ return PcCompleteIrp(DeviceObject, Irp, Status);
case IRP_MN_QUERY_INTERFACE:
DPRINT("IRP_MN_QUERY_INTERFACE\n");
return STATUS_UNSUCCESSFUL;
}
+VOID
+CALLBACK
+PwrCompletionFunction(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN UCHAR MinorFunction,
+ IN POWER_STATE PowerState,
+ IN PVOID Context,
+ IN PIO_STATUS_BLOCK IoStatus)
+{
+ NTSTATUS Status;
+ PQUERY_POWER_CONTEXT PwrContext = (PQUERY_POWER_CONTEXT)Context;
+
+ if (NT_SUCCESS(IoStatus->Status))
+ {
+ // forward request to lower device object
+ Status = PcForwardIrpSynchronous(PwrContext->DeviceObject, PwrContext->Irp);
+ }
+ else
+ {
+ // failed
+ Status = IoStatus->Status;
+ }
+
+ // start next power irp
+ PoStartNextPowerIrp(PwrContext->Irp);
+
+ // complete request
+ PwrContext->Irp->IoStatus.Status = Status;
+ IoCompleteRequest(PwrContext->Irp, IO_NO_INCREMENT);
+
+ // free context
+ FreeItem(PwrContext, TAG_PORTCLASS);
+}
+
+
NTSTATUS
NTAPI
PortClsPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
+ PIO_STACK_LOCATION IoStack;
+ PPCLASS_DEVICE_EXTENSION DeviceExtension;
+ PQUERY_POWER_CONTEXT PwrContext;
+ POWER_STATE PowerState;
+ NTSTATUS Status = STATUS_SUCCESS;
+
DPRINT("PortClsPower called\n");
- // TODO
+ // get currrent stack location
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ if (IoStack->MinorFunction != IRP_MN_SET_POWER && IoStack->MinorFunction != IRP_MN_QUERY_POWER)
+ {
+ // just forward the request
+ Status = PcForwardIrpSynchronous(DeviceObject, Irp);
- return STATUS_SUCCESS;
+ // start next power irp
+ PoStartNextPowerIrp(Irp);
+
+ // complete request
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // done
+ return Status;
+ }
+
+
+ // get device extension
+ DeviceExtension = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+ // get current request type
+ if (IoStack->Parameters.Power.Type == DevicePowerState)
+ {
+ // request for device power state
+ if (DeviceExtension->DevicePowerState == IoStack->Parameters.Power.State.DeviceState)
+ {
+ // nothing has changed
+ if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
+ {
+ // only forward query requests
+ Status = PcForwardIrpSynchronous(DeviceObject, Irp);
+ }
+
+ // start next power irp
+ PoStartNextPowerIrp(Irp);
+
+ // complete request
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // done
+ return Status;
+ }
+
+ if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
+ {
+ // check if there is a registered adapter power management
+ if (DeviceExtension->AdapterPowerManagement)
+ {
+ // it is query if the change can be changed
+ PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState);
+ Status = DeviceExtension->AdapterPowerManagement->QueryPowerChangeState(PowerState);
+
+ // sanity check
+ PC_ASSERT(Status == STATUS_SUCCESS);
+ }
+
+ // only forward query requests
+ PcForwardIrpSynchronous(DeviceObject, Irp);
+
+ // start next power irp
+ PoStartNextPowerIrp(Irp);
+
+ // complete request
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // done
+ return Status;
+ }
+ else
+ {
+ // set power state
+ PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState);
+ PoSetPowerState(DeviceObject, DevicePowerState, PowerState);
+
+ // check if there is a registered adapter power management
+ if (DeviceExtension->AdapterPowerManagement)
+ {
+ // notify of a power change state
+ DeviceExtension->AdapterPowerManagement->PowerChangeState(PowerState);
+ }
+
+ // FIXME call all registered IPowerNotify interfaces via ISubdevice interface
+
+ // store new power state
+ DeviceExtension->DevicePowerState = IoStack->Parameters.Power.State.DeviceState;
+
+ // complete request
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // done
+ return Status;
+ }
+ }
+ else
+ {
+ // sanity check
+ PC_ASSERT(IoStack->Parameters.Power.Type == SystemPowerState);
+
+ if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
+ {
+ // mark irp as pending
+ IoMarkIrpPending(Irp);
+
+ // allocate power completion context
+ PwrContext = (PQUERY_POWER_CONTEXT)AllocateItem(NonPagedPool, sizeof(QUERY_POWER_CONTEXT), TAG_PORTCLASS);
+
+ if (!PwrContext)
+ {
+ // no memory
+ PoStartNextPowerIrp(Irp);
+
+ // complete and forget
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // done
+ return Status;
+ }
+
+ // setup power context
+ PwrContext->Irp = Irp;
+ PwrContext->DeviceObject = DeviceObject;
+
+ // pass the irp down
+ PowerState = *((POWER_STATE*)IoStack->Parameters.Power.State.SystemState);
+ Status = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject, IoStack->MinorFunction, PowerState, PwrCompletionFunction, (PVOID)PwrContext, NULL);
+
+ // check for success
+ if (!NT_SUCCESS(Status))
+ {
+ // failed
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // done
+ return Status;
+ }
+
+ // done
+ return STATUS_PENDING;
+ }
+ else
+ {
+ // set power request
+ DeviceExtension->SystemPowerState = IoStack->Parameters.Power.State.SystemState;
+
+ // only forward query requests
+ Status = PcForwardIrpSynchronous(DeviceObject, Irp);
+
+ // start next power irp
+ PoStartNextPowerIrp(Irp);
+
+ // complete request
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // done
+ return Status;
+ }
+ }
}
NTSTATUS
{
PIO_STACK_LOCATION IoStack;
- DPRINT("PcDispatchIrp called - handling IRP in PortCls\n");
-
IoStack = IoGetCurrentIrpStackLocation(Irp);
+ DPRINT("PcDispatchIrp called - handling IRP in PortCls MajorFunction %x MinorFunction %x\n", IoStack->MajorFunction, IoStack->MinorFunction);
+
switch ( IoStack->MajorFunction )
{
// PortCls