⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 power.c

📁 WinBond W83627 看门狗驱动
💻 C
字号:
#include "Driver.h"

/////////////////////////////////////////////////////////////////////////////

//	Description:
//		Handle IRP_MJ_POWER requests
//
//	Arguments:
//		Pointer to the FDO
//		Pointer to the IRP
//			IRP_MN_WAIT_WAKE:		IrpStack->Parameters.WaitWake.Xxx
//			IRP_MN_POWER_SEQUENCE:	IrpStack->Parameters.PowerSequence.Xxx
//			IRP_MN_SET_POWER:
//			IRP_MN_QUERY_POWER:		IrpStack->Parameters.Power.Xxx
//

NTSTATUS DRV_Power(	IN PDEVICE_OBJECT fdo,
					IN PIRP Irp)
{
	PDEVICE_EXTENSION pde = (PDEVICE_EXTENSION)fdo->DeviceExtension;
	NTSTATUS status = STATUS_SUCCESS;
	PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
	ULONG MinorFunction = IrpStack->MinorFunction;

	if( !pde->started)
		return CompleteIoReq( Irp, STATUS_DEVICE_NOT_CONNECTED, 0);
	if (!LockDevice(pde))
		return CompleteIoReq( Irp, STATUS_DELETE_PENDING, 0);

	// debugprint("Power %I",Irp);

	if( MinorFunction==IRP_MN_SET_POWER)
		status = PowerSetPower(pde,Irp);
	else
		status = DefaultPowerHandler(pde,Irp);

	UnlockDevice(pde);
	return status;
}

/////////////////////////////////////////////////////////////////////////////
//	PowerSetPower:	Handle set system and device power

NTSTATUS PowerSetPower( IN PDEVICE_EXTENSION pde, IN PIRP Irp)
{
	NTSTATUS status = STATUS_SUCCESS;
	PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
	POWER_STATE_TYPE PowerType = IrpStack->Parameters.Power.Type;
	POWER_STATE PowerState = IrpStack->Parameters.Power.State;

	/////////////////////////////////////////////////////////////////////////
	//	Set System Power

	if( PowerType==SystemPowerState)
	{
		DEVICE_POWER_STATE DesiredDevicePowerState =
			(PowerState.SystemState<=PowerSystemWorking ? PowerDeviceD0 : PowerDeviceD3);
		
		if( DesiredDevicePowerState<pde->power)
		{
			// This system state means we have to increase device power
			// debugprint("System state %d.  Increase device power to %d",
			//			PowerState.SystemState, DesiredDevicePowerState);
		// Process on way up stack...
			PoStartNextPowerIrp(Irp);
			IoCopyCurrentIrpStackLocationToNext(Irp);
			IoSetCompletionRoutine( Irp, OnCompleteIncreaseSystemPower, NULL, TRUE, TRUE, TRUE);
			return PoCallDriver( pde->StackDeviceObject, Irp);
		}
		else if( DesiredDevicePowerState>pde->power)
		{
			// This system state means we have to decrease device power
			// debugprint("System state %d.  Decrease device power to %d",
			//			PowerState.SystemState, DesiredDevicePowerState);
			// Send power down request to device
			status = SendDeviceSetPower( pde, DesiredDevicePowerState);
			if( !NT_SUCCESS(status))
			{
				PoStartNextPowerIrp(Irp);
				return CompleteIoReq( Irp, status, 0);
			}
		}
	}

	/////////////////////////////////////////////////////////////////////////
	//	Set Device Power
	else if( PowerType==DevicePowerState)
	{
		DEVICE_POWER_STATE DesiredDevicePowerState = PowerState.DeviceState;

		if( DesiredDevicePowerState<pde->power)
		{
			// Increase device power state
			// debugprint("Increase device power to %d", DesiredDevicePowerState);
			// Process on way up stack...
			PoStartNextPowerIrp(Irp);
			IoCopyCurrentIrpStackLocationToNext(Irp);
			IoSetCompletionRoutine( Irp, OnCompleteIncreaseDevicePower, NULL, TRUE, TRUE, TRUE);
			return PoCallDriver( pde->StackDeviceObject, Irp);
		}
		else if( DesiredDevicePowerState>pde->power)
		{
			// Decrease device power state
			// debugprint("Decrease device power to %d", DesiredDevicePowerState);
		// Set power state
			SetPowerState(pde,PowerState.DeviceState);
		}
	}

	// Finally pass to lower drivers
	return DefaultPowerHandler(pde,Irp);
}

/////////////////////////////////////////////////////////////////////////////
//	DefaultPowerHandler:	Pass Power IRP down stack

NTSTATUS DefaultPowerHandler( IN PDEVICE_EXTENSION pde, IN PIRP Irp)
{
	// Just pass to lower driver
	// debugprintMsg("DefaultPowerHandler");
	
	PoStartNextPowerIrp( Irp);
	IoSkipCurrentIrpStackLocation(Irp);
	return PoCallDriver( pde->StackDeviceObject, Irp);
}

/////////////////////////////////////////////////////////////////////////////
//	OnCompleteIncreaseSystemPower:	Set system power (increase device power) completed

NTSTATUS OnCompleteIncreaseSystemPower( IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PVOID context)
{
	PIO_STACK_LOCATION IrpStack;
	POWER_STATE PowerState;
	DEVICE_POWER_STATE DesiredDevicePowerState;
	PDEVICE_EXTENSION pde = (PDEVICE_EXTENSION)fdo->DeviceExtension;
	NTSTATUS status = Irp->IoStatus.Status;
	
	if (Irp->PendingReturned)
		IoMarkIrpPending(Irp);
	if( !NT_SUCCESS(status))
		return status;
	
	// debugprint("OnCompleteIncreaseSystemPower %x",status);
	
	IrpStack = IoGetCurrentIrpStackLocation(Irp);
	PowerState = IrpStack->Parameters.Power.State;
	DesiredDevicePowerState =
		(PowerState.SystemState<=PowerSystemWorking ? PowerDeviceD0 : PowerDeviceD3);
	if( DesiredDevicePowerState<pde->power)
		status = SendDeviceSetPower( pde, DesiredDevicePowerState);

	PoStartNextPowerIrp(Irp);
	return status;
}

/////////////////////////////////////////////////////////////////////////////
//	OnCompleteIncreaseDevicePower:	Set device power completed

NTSTATUS OnCompleteIncreaseDevicePower( IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PVOID context)
{
	PIO_STACK_LOCATION IrpStack;
	POWER_STATE PowerState ;
	NTSTATUS status;

	PDEVICE_EXTENSION pde = (PDEVICE_EXTENSION)fdo->DeviceExtension;
	if (Irp->PendingReturned)
		IoMarkIrpPending(Irp);
	status = Irp->IoStatus.Status;
	
	// debugprint("OnCompleteIncreaseDevicePower %x",status);
	
	if( !NT_SUCCESS(status))
		return status;

	IrpStack = IoGetCurrentIrpStackLocation(Irp);
	PowerState = IrpStack->Parameters.Power.State;
	SetPowerState(pde,PowerState.DeviceState);

	PoStartNextPowerIrp(Irp);
	return status;
}

/////////////////////////////////////////////////////////////////////////////
//	SendDeviceSetPower:	Send set power for device
//						Must not be called from set device power as it waits on an event

NTSTATUS
SendDeviceSetPower( IN PDEVICE_EXTENSION pde, IN DEVICE_POWER_STATE NewDevicePowerState)
{
	POWER_STATE NewState;
	SDSP sdsp;
	NTSTATUS status ;

	
	NewState.DeviceState = NewDevicePowerState;
	// debugprint("SendDeviceSetPower to %d", NewDevicePowerState);
	
	KeInitializeEvent( &sdsp.event, NotificationEvent, FALSE);
	sdsp.Status = STATUS_SUCCESS;
	status = PoRequestPowerIrp( pde->pdo, IRP_MN_SET_POWER, NewState,\
		OnCompleteDeviceSetPower, &sdsp, NULL);
	if( status==STATUS_PENDING)
	{
		KeWaitForSingleObject( &sdsp.event, Executive, KernelMode, FALSE, NULL);
		status = sdsp.Status;
	}

	// Cope with W98 not passing power irp to us
	if( NT_SUCCESS(status) && pde->power!=NewDevicePowerState)
	{
		SetPowerState(pde,NewDevicePowerState);
	}

	return status;
}

/////////////////////////////////////////////////////////////////////////////
//	OnCompleteDeviceSetPower:	Set device power IRP completed

VOID OnCompleteDeviceSetPower( IN PDEVICE_OBJECT fdo, IN UCHAR MinorFunction,
					IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus)
{
	PSDSP psdsp = (PSDSP)Context;

	// debugprintMsg("OnCompleteDeviceSetPower");

	psdsp->Status = IoStatus->Status;
	KeSetEvent( &psdsp->event, 0, FALSE);
}

/////////////////////////////////////////////////////////////////////////////
void SetPowerState( IN PDEVICE_EXTENSION pde, IN DEVICE_POWER_STATE NewDevicePowerState)
{
	// Use KeSynchronizeExecution if necessary to actually change power in device
	// Remember new state
	POWER_STATE NewState;
	pde->power = NewDevicePowerState;
	NewState.DeviceState = NewDevicePowerState;
	if( KeGetCurrentIrql()==DISPATCH_LEVEL && NewDevicePowerState!=PowerDeviceD0)
	{
		;//DebugPrint("SetPowerState IRQL %d fail", KeGetCurrentIrql());
	}
	else
		PoSetPowerState( pde->DeviceObject, DevicePowerState, NewState);

}

NTSTATUS 
PowerUpDevice( IN PDEVICE_OBJECT fdo)
{
	PDEVICE_EXTENSION pde = (PDEVICE_EXTENSION)fdo->DeviceExtension;
	// If need be, increase power
	if( pde->power>PowerDeviceD0)
	{
		NTSTATUS status = SendDeviceSetPower( pde, PowerDeviceD0);
		if (!NT_SUCCESS(status))
			return status;
	}
	// Zero our idle counter
	if( pde->idle)
		PoSetDeviceBusy(pde->idle);
	return STATUS_SUCCESS;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -