📄 pnppower.c
字号:
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
pnppower.c
Abstract:
SMBus Smart Battery Subsystem Miniport Driver
(Selector, Battery, Charger) Plug and Play and
Power Management IRP dispatch routines.
Author:
Scott Brenden
Environment:
Notes:
Revision History:
Chris Windle 1/27/98 Bug Fixes
--*/
#include "smbbattp.h"
#include <devioctl.h>
#include <acpiioct.h>
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,SmbBattPnpDispatch)
#pragma alloc_text(PAGE,SmbBattPowerDispatch)
#pragma alloc_text(PAGE,SmbBattRegisterForAlarm)
#pragma alloc_text(PAGE,SmbBattUnregisterForAlarm)
#pragma alloc_text(PAGE,SmbGetSBS)
#pragma alloc_text(PAGE,SmbGetGLK)
#pragma alloc_text(PAGE,SmbBattCreatePdos)
#pragma alloc_text(PAGE,SmbBattBuildDeviceRelations)
#pragma alloc_text(PAGE,SmbBattQueryDeviceRelations)
#pragma alloc_text(PAGE,SmbBattRemoveDevice)
#pragma alloc_text(PAGE,SmbBattQueryId)
#pragma alloc_text(PAGE,SmbBattQueryCapabilities)
#pragma alloc_text(PAGE,SmbBattBuildSelectorStruct)
#endif
NTSTATUS
SmbBattPnpDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is a dispatch routine for the IRPs that come to the driver with the
IRP_MJ_PNP major code (plug-and-play IRPs).
Arguments:
DeviceObject - Pointer to the device object for this device
Irp - Pointer to the IRP for the current request
Return Value:
The function value is the final status of the call
--*/
{
PSMB_BATT smbBatt;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status;
BOOLEAN complete = TRUE;
KEVENT syncEvent;
//
// This routine handles PnP IRPs for three different types of device objects:
// the battery subsystem FDO, each battery PDO and each battery PDO. The
// subsystem PDO creates children since each battery in the system must have
// it's own device object, so this driver is essential two device drivers in
// one: the smart battery selector bus driver (It is actually it's own bus
// because the selector arbitrates between the two batteries.) and the
// battery function driver. The two drivers are integrated because it would
// not make sense to replace one and not the other, and having separate
// drivers would require additional defined interfaces between them.
//
// The device extensions for the three device types are different structures.
//
PSMB_BATT_SUBSYSTEM subsystemExt =
(PSMB_BATT_SUBSYSTEM) DeviceObject->DeviceExtension;
PSMB_NP_BATT batteryExt =
(PSMB_NP_BATT) DeviceObject->DeviceExtension;
PDEVICE_OBJECT lowerDevice = NULL;
PAGED_CODE();
status = IoAcquireRemoveLock (&batteryExt->RemoveLock, Irp);
if (NT_SUCCESS(status)) {
status = STATUS_NOT_SUPPORTED;
if (batteryExt->SmbBattFdoType == SmbTypeSubsystem) {
lowerDevice = subsystemExt->LowerDevice;
} else if (batteryExt->SmbBattFdoType == SmbTypeBattery) {
lowerDevice = batteryExt->LowerDevice;
} else {
// Assuming (batteryExt->SmbBattFdoType == SmbTypePdo)
ASSERT (batteryExt->SmbBattFdoType == SmbTypePdo);
lowerDevice = NULL;
}
switch (irpStack->MinorFunction) {
case IRP_MN_QUERY_DEVICE_RELATIONS: {
BattPrint(
BAT_IRPS,
("SmbBattPnpDispatch: got IRP_MN_QUERY_DEVICE_RELATIONS, "
"type = %x\n",
irpStack->Parameters.QueryDeviceRelations.Type)
);
status = SmbBattQueryDeviceRelations (DeviceObject, Irp);
break;
}
case IRP_MN_QUERY_CAPABILITIES: {
BattPrint(
BAT_IRPS,
("SmbBattPnpDispatch: got IRP_MN_QUERY_CAPABILITIES for device %x\n",
DeviceObject)
);
status = SmbBattQueryCapabilities (DeviceObject, Irp);
break;
}
case IRP_MN_START_DEVICE: {
BattPrint(
BAT_IRPS,
("SmbBattPnpDispatch: got IRP_MN_START_DEVICE for %x\n",
DeviceObject)
);
if (subsystemExt->SmbBattFdoType == SmbTypeSubsystem) {
//
// Get the SMB host controller FDO
//
subsystemExt->SmbHcFdo = subsystemExt->LowerDevice;
status = STATUS_SUCCESS;
} else if (subsystemExt->SmbBattFdoType == SmbTypeBattery) {
//
// This is a battery. Just get the SMB host controller FDO.
//
smbBatt = batteryExt->Batt;
smbBatt->SmbHcFdo =
((PSMB_BATT_SUBSYSTEM)(((PSMB_BATT_PDO)
(smbBatt->PDO->DeviceExtension))->
SubsystemFdo->DeviceExtension))->
LowerDevice;
status = STATUS_SUCCESS;
} else if (subsystemExt->SmbBattFdoType == SmbTypePdo) {
status = STATUS_SUCCESS;
}
break;
}
case IRP_MN_STOP_DEVICE: {
status = STATUS_SUCCESS;
BattPrint(BAT_IRPS, ("SmbBattPnpDispatch: got IRP_MN_STOP_DEVICE\n"));
break;
}
case IRP_MN_QUERY_REMOVE_DEVICE: {
status = STATUS_SUCCESS;
BattPrint(BAT_IRPS, ("SmbBattPnpDispatch: got IRP_MN_QUERY_REMOVE_DEVICE\n"));
break;
}
case IRP_MN_CANCEL_REMOVE_DEVICE: {
status = STATUS_SUCCESS;
BattPrint(BAT_IRPS, ("SmbBattPnpDispatch: got IRP_MN_CANCEL_REMOVE_DEVICE\n"));
break;
}
case IRP_MN_SURPRISE_REMOVAL: {
status = STATUS_SUCCESS;
BattPrint(BAT_IRPS, ("SmbBattPnpDispatch: got IRP_MN_SURPRISE_REMOVAL\n"));
break;
}
case IRP_MN_REMOVE_DEVICE: {
BattPrint(BAT_IRPS, ("SmbBattPnpDispatch: got IRP_MN_REMOVE_DEVICE\n"));
status = SmbBattRemoveDevice (DeviceObject, Irp);
return status;
break;
}
case IRP_MN_QUERY_ID: {
BattPrint(
BAT_IRPS,
("SmbBattPnpDispatch: got IRP_MN_QUERY_ID for %x, query type is - %x\n",
DeviceObject,
irpStack->Parameters.QueryId.IdType)
);
if (batteryExt->SmbBattFdoType == SmbTypePdo) {
status = SmbBattQueryId (DeviceObject, Irp);
}
break;
}
case IRP_MN_QUERY_PNP_DEVICE_STATE: {
BattPrint(BAT_IRPS, ("SmbBattPnpDispatch: got IRP_MN_PNP_DEVICE_STATE\n"));
if (subsystemExt->SmbBattFdoType == SmbTypeSubsystem) {
IoCopyCurrentIrpStackLocationToNext (Irp);
KeInitializeEvent(&syncEvent, SynchronizationEvent, FALSE);
IoSetCompletionRoutine(Irp, SmbBattSynchronousRequest, &syncEvent, TRUE, TRUE, TRUE);
status = IoCallDriver(lowerDevice, Irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&syncEvent, Executive, KernelMode, FALSE, NULL);
status = Irp->IoStatus.Status;
}
Irp->IoStatus.Information &= ~PNP_DEVICE_NOT_DISABLEABLE;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoReleaseRemoveLock (&batteryExt->RemoveLock, Irp);
return status;
}
break;
}
} // switch (irpStack->MinorFunction)
IoReleaseRemoveLock (&batteryExt->RemoveLock, Irp);
}
//
// Only set status if we have something to add
//
if (status != STATUS_NOT_SUPPORTED) {
Irp->IoStatus.Status = status ;
}
//
// Do we need to send it down?
//
if ((NT_SUCCESS(status) || (status == STATUS_NOT_SUPPORTED)) && (lowerDevice != NULL)) {
//
// Forward request
//
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(lowerDevice,Irp);
} else {
//
// Complete the request with the current status
//
status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return status;
}
NTSTATUS
SmbBattPowerDispatch(
IN PDEVICE_OBJECT Fdo,
IN PIRP Irp
)
/*++
Routine Description:
This is a dispatch routine for the IRPs that come to the driver with the
IRP_MJ_POWER major code (power IRPs).
Arguments:
DeviceObject - Pointer to the device object for this device
Irp - Pointer to the IRP for the current request
Return Value:
The function value is the final status of the call
--*/
{
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status = STATUS_NOT_SUPPORTED;
PSMB_NP_BATT batteryExt = (PSMB_NP_BATT) Fdo->DeviceExtension;
PSMB_BATT_SUBSYSTEM subsystemExt = (PSMB_BATT_SUBSYSTEM) Fdo->DeviceExtension;
PDEVICE_OBJECT lowerDevice;
PAGED_CODE();
//
// Not using Remove lock in this function because this function doesn't use
// any resoureces that the remove lock protects.
//
if (batteryExt->SmbBattFdoType == SmbTypeSubsystem) {
lowerDevice = subsystemExt->LowerDevice;
} else if (batteryExt->SmbBattFdoType == SmbTypeBattery) {
lowerDevice = batteryExt->LowerDevice;
} else {
// Assuming (batteryExt->SmbBattFdoType == SmbTypePdo)
ASSERT (batteryExt->SmbBattFdoType == SmbTypePdo);
lowerDevice = NULL;
status = STATUS_SUCCESS;
}
switch (irpStack->MinorFunction) {
case IRP_MN_WAIT_WAKE: {
BattPrint(BAT_IRPS, ("SmbBattPowerDispatch: got IRP_MN_WAIT_WAKE\n"));
//
// Smart batteries can't wake the system.
//
status = STATUS_NOT_SUPPORTED;
break;
}
case IRP_MN_POWER_SEQUENCE: {
BattPrint(BAT_IRPS, ("SmbBattPowerDispatch: got IRP_MN_POWER_SEQUENCE\n"));
break;
}
case IRP_MN_SET_POWER: {
BattPrint(BAT_IRPS, ("SmbBattPowerDispatch: got IRP_MN_SET_POWER\n"));
break;
}
case IRP_MN_QUERY_POWER: {
BattPrint(BAT_IRPS, ("SmbBattPowerDispatch: got IRP_MN_QUERY_POWER\n"));
break;
}
default: {
status = STATUS_NOT_SUPPORTED;
}
} // switch (irpStack->MinorFunction)
if (status != STATUS_NOT_SUPPORTED) {
Irp->IoStatus.Status = status;
}
PoStartNextPowerIrp( Irp );
if ((NT_SUCCESS(status) || (status == STATUS_NOT_SUPPORTED)) && (lowerDevice != NULL)) {
//
// Forward the request along
//
IoSkipCurrentIrpStackLocation( Irp );
status = PoCallDriver( lowerDevice, Irp );
} else {
//
// Complete the request with the current status
//
status = Irp->IoStatus.Status;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
}
return status;
}
NTSTATUS
SmbBattRegisterForAlarm(
IN PDEVICE_OBJECT Fdo
)
/*++
Routine Description:
This routine register with the SmbHc for alarm notifications. This
is only done when smart battery subsystem FDO is started.
Arguments:
Fdo - Pointer to the Fdo for this device
Irp - Pointer to the IRP for the current request
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -