|
|
//+-------------------------------------------------------------------------
//
// 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; }
|