497 lines
11 KiB
C
497 lines
11 KiB
C
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation and Litronic, 1998 - 1999
|
|
//
|
|
// File: l220powr.c
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
//////////////////////////////////////////////////////////
|
|
//
|
|
// Power Management
|
|
//
|
|
//////////////////////////////////////////////////////////
|
|
|
|
|
|
NTSTATUS
|
|
Lit220DispatchPower (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The power dispatch routine.
|
|
|
|
As this is a POWER irp, and therefore a special irp, special power irp
|
|
handling is required.
|
|
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - pointer to a device object.
|
|
|
|
Irp - pointer to an I/O Request Packet.
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION stack;
|
|
PSMARTCARD_EXTENSION SmartcardExtension = DeviceObject->DeviceExtension;
|
|
PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
|
|
NTSTATUS status;
|
|
|
|
LONG requestCount;
|
|
|
|
stack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
//
|
|
// This IRP was sent to the function driver.
|
|
// The behavior is similar with the one of SD_Pass
|
|
//
|
|
|
|
//
|
|
// This IRP was sent to the function driver.
|
|
// We don't queue power Irps, we'll only check if the
|
|
// device was removed, otherwise we'll send it to the next lower
|
|
// driver.
|
|
//
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
("%s!Lit220DispatchPower: Enter - MinorFunction %X\n",
|
|
DRIVER_NAME,
|
|
stack->MinorFunction)
|
|
);
|
|
|
|
|
|
// Increment the IRP Count
|
|
status = Lit220IncIoCount(ReaderExtension);
|
|
|
|
if (ReaderExtension->IsRemoved) {
|
|
status = STATUS_DELETE_PENDING;
|
|
PoStartNextPowerIrp (Irp);
|
|
Irp->IoStatus.Information = 0;
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
|
|
} else {
|
|
|
|
//
|
|
// We always need to start the next power irp with PoStartNextPowerIrp
|
|
//
|
|
switch (stack->MinorFunction) {
|
|
case IRP_MN_WAIT_WAKE :
|
|
SmartcardDebug(
|
|
DEBUG_DRIVER,
|
|
("%s!Lit220DispatchPower: IRP_MN_WAIT_WAKE\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
status = Lit220PassDownToNextPowerDriver(
|
|
DeviceObject,
|
|
Irp
|
|
);
|
|
|
|
break;
|
|
|
|
case IRP_MN_POWER_SEQUENCE :
|
|
SmartcardDebug(
|
|
DEBUG_DRIVER,
|
|
("%s!Lit220DispatchPower: IRP_MN_POWER_SEQUENCE\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
status = Lit220PassDownToNextPowerDriver(
|
|
DeviceObject,
|
|
Irp
|
|
);
|
|
|
|
break;
|
|
|
|
case IRP_MN_QUERY_POWER :
|
|
SmartcardDebug(
|
|
DEBUG_DRIVER,
|
|
("%s!Lit220DispatchPower: IRP_MN_QUERY_POWER\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
|
|
status = Lit220QueryPowerState(
|
|
DeviceObject,
|
|
Irp
|
|
);
|
|
|
|
break;
|
|
|
|
case IRP_MN_SET_POWER :
|
|
SmartcardDebug(
|
|
DEBUG_DRIVER,
|
|
("%s!Lit220DispatchPower: IRP_MN_SET_POWER\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
status = Lit220SetPowerState(
|
|
DeviceObject,
|
|
Irp
|
|
);
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
//
|
|
// Pass it down
|
|
//
|
|
SmartcardDebug(
|
|
DEBUG_DRIVER,
|
|
("%s!Lit220DispatchPower: IRP_MN_0x%x\n",
|
|
DRIVER_NAME,
|
|
stack->MinorFunction)
|
|
);
|
|
|
|
status = Lit220PassDownToNextPowerDriver(
|
|
DeviceObject,
|
|
Irp
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
Lit220PassDownToNextPowerDriver (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Passes the Irp to the next device in the attchement chain
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - pointer to a device object.
|
|
|
|
Irp - pointer to an I/O Request Packet.
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
PSMARTCARD_EXTENSION SmartcardExtension = DeviceObject->DeviceExtension;
|
|
PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
|
|
status = PoCallDriver(
|
|
ReaderExtension->BusDeviceObject,
|
|
Irp
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
SmartcardDebug(
|
|
DEBUG_DRIVER,
|
|
("%s!Lit220PassDownToNextPowerDriver : Lower driver fails a power irp\n",
|
|
DRIVER_NAME)
|
|
);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
Lit220QueryPowerState (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Completes the power Irp with STATUS_SUCCESS
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - pointer to a device object.
|
|
|
|
Irp - pointer to an I/O Request Packet.
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
{
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
|
|
IoCompleteRequest(
|
|
Irp,
|
|
IO_NO_INCREMENT
|
|
);
|
|
|
|
|
|
//
|
|
// Do not send this Irp down.
|
|
//
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
Lit220SetPowerState (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Processes IRP_MN_SET_POWER.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - pointer to a device object.
|
|
|
|
Irp - pointer to an I/O Request Packet.
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PSMARTCARD_EXTENSION SmartcardExtension = DeviceObject->DeviceExtension;
|
|
PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
|
|
PIO_STACK_LOCATION stack;
|
|
|
|
PFDO_POWER_CONTEXT context;
|
|
|
|
BOOLEAN passItDown;
|
|
|
|
|
|
|
|
stack = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
SmartcardDebug(
|
|
DEBUG_DRIVER,
|
|
("%s!Lit220SetPowerState: Type %X, State %X\n",
|
|
DRIVER_NAME,
|
|
stack->Parameters.Power.Type,
|
|
stack->Parameters.Power.State.SystemState)
|
|
);
|
|
|
|
context = ExAllocatePool(
|
|
NonPagedPool,
|
|
sizeof(FDO_POWER_CONTEXT)
|
|
);
|
|
|
|
if (context == NULL) {
|
|
|
|
status = STATUS_NO_MEMORY;
|
|
|
|
} else {
|
|
|
|
RtlZeroMemory(
|
|
context,
|
|
sizeof(FDO_POWER_CONTEXT)
|
|
);
|
|
|
|
stack = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
context->newPowerType = stack->Parameters.Power.Type;
|
|
context->newPowerState = stack->Parameters.Power.State;
|
|
|
|
passItDown = TRUE;
|
|
|
|
if (stack->Parameters.Power.Type == SystemPowerState) {
|
|
|
|
if (ReaderExtension->SystemPowerState ==
|
|
stack->Parameters.Power.State.SystemState)
|
|
{
|
|
|
|
//
|
|
// We are already in the given system state
|
|
//
|
|
passItDown = FALSE;
|
|
}
|
|
|
|
} else if (stack->Parameters.Power.Type == DevicePowerState) {
|
|
|
|
if (ReaderExtension->DevicePowerState !=
|
|
stack->Parameters.Power.State.DeviceState)
|
|
{
|
|
|
|
if (ReaderExtension->DevicePowerState == PowerDeviceD0) {
|
|
|
|
//
|
|
// getting out of D0 state, better call PoSetPowerState now
|
|
//
|
|
PoSetPowerState (
|
|
DeviceObject,
|
|
DevicePowerState,
|
|
stack->Parameters.Power.State
|
|
);
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// We are already in the given device state
|
|
//
|
|
passItDown = FALSE;
|
|
}
|
|
} else {
|
|
|
|
ASSERT (FALSE);
|
|
status = STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(status) && passItDown) {
|
|
|
|
IoCopyCurrentIrpStackLocationToNext (Irp);
|
|
|
|
IoSetCompletionRoutine(Irp,
|
|
Lit220PowerCompletionRoutine,
|
|
context,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
return PoCallDriver(
|
|
ReaderExtension->BusDeviceObject,
|
|
Irp
|
|
);
|
|
|
|
} else {
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Irp->IoStatus.Status = status;
|
|
PoStartNextPowerIrp (Irp);
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
//
|
|
// Free the memory now
|
|
//
|
|
if (context) {
|
|
ExFreePool (context);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
Lit220PowerCompletionRoutine (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The completion routine for IRP_MN_SET_POWER.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - pointer to a device object.
|
|
|
|
Irp - pointer to an I/O Request Packet.
|
|
|
|
Context - a pointer to a structure that contains the new power type and
|
|
new power state.
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
{
|
|
PFDO_POWER_CONTEXT context = Context;
|
|
BOOLEAN callPoSetPowerState;
|
|
PSMARTCARD_EXTENSION SmartcardExtension = DeviceObject->DeviceExtension;
|
|
PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
|
|
|
|
if (NT_SUCCESS(Irp->IoStatus.Status)) {
|
|
|
|
callPoSetPowerState = TRUE;
|
|
|
|
if (context->newPowerType == SystemPowerState) {
|
|
|
|
ReaderExtension->SystemPowerState = context->newPowerState.SystemState;
|
|
|
|
|
|
} else if (context->newPowerType == DevicePowerState) {
|
|
|
|
if (ReaderExtension->DevicePowerState == PowerDeviceD0) {
|
|
|
|
//
|
|
// PoSetPowerState is called before we get out of D0
|
|
//
|
|
callPoSetPowerState = FALSE;
|
|
}
|
|
|
|
//TODO: Send Power command to device
|
|
//Also, Not sure if we should do this yet it is
|
|
// still TBD
|
|
|
|
ReaderExtension->DevicePowerState = context->newPowerState.DeviceState;
|
|
|
|
}
|
|
|
|
if (callPoSetPowerState) {
|
|
|
|
PoSetPowerState (
|
|
DeviceObject,
|
|
context->newPowerType,
|
|
context->newPowerState
|
|
);
|
|
}
|
|
}
|
|
|
|
PoStartNextPowerIrp (Irp);
|
|
//
|
|
// We can happily free the heap here
|
|
//
|
|
ExFreePool(context);
|
|
|
|
return Irp->IoStatus.Status;
|
|
}
|
|
|
|
|
|
|