📄 pnppower.c
字号:
Return Value:
The function value is the final status of the call
--*/
{
PIRP irp;
PIO_STACK_LOCATION irpStack;
SMB_REGISTER_ALARM registerAlarm;
KEVENT event;
NTSTATUS status;
PSMB_BATT_SUBSYSTEM subsystemExtension =
(PSMB_BATT_SUBSYSTEM) Fdo->DeviceExtension;
PAGED_CODE();
//
// Register for alarm notifications
//
registerAlarm.MinAddress = SMB_CHARGER_ADDRESS;
registerAlarm.MaxAddress = SMB_BATTERY_ADDRESS;
registerAlarm.NotifyFunction = SmbBattAlarm;
registerAlarm.NotifyContext = subsystemExtension;
KeInitializeEvent (&event, NotificationEvent, FALSE);
irp = IoAllocateIrp (subsystemExtension->SmbHcFdo->StackSize, FALSE);
if (!irp) {
BattPrint(BAT_ERROR, ("SmbBattRegisterForAlarm: couldn't allocate irp\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
irpStack = IoGetNextIrpStackLocation(irp);
irp->UserBuffer = &subsystemExtension->SmbAlarmHandle;
irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
irpStack->Parameters.DeviceIoControl.IoControlCode = SMB_REGISTER_ALARM_NOTIFY;
irpStack->Parameters.DeviceIoControl.InputBufferLength = sizeof(registerAlarm);
irpStack->Parameters.DeviceIoControl.Type3InputBuffer = ®isterAlarm;
irpStack->Parameters.DeviceIoControl.OutputBufferLength = sizeof(subsystemExtension->SmbAlarmHandle);
IoSetCompletionRoutine (irp, SmbBattSynchronousRequest, &event, TRUE, TRUE, TRUE);
IoCallDriver (subsystemExtension->SmbHcFdo, irp);
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = irp->IoStatus.Status;
if (!NT_SUCCESS(status)) {
BattPrint(BAT_ERROR, ("SmbBattRegisterForAlarm: couldn't register for alarms - %x\n", status));
}
IoFreeIrp (irp);
return status;
}
NTSTATUS
SmbBattUnregisterForAlarm(
IN PDEVICE_OBJECT Fdo
)
/*++
Routine Description:
This routine unregisters with the SmbHc for alarm notifications. This
is only done when smart battery subsystem FDO is stopped or unloaded.
Arguments:
Fdo - Pointer to the Fdo for this device
Irp - Pointer to the IRP for the current request
Return Value:
The function value is the final status of the call
--*/
{
PIRP irp;
PIO_STACK_LOCATION irpStack;
KEVENT event;
NTSTATUS status;
PSMB_BATT_SUBSYSTEM subsystemExtension = (PSMB_BATT_SUBSYSTEM) Fdo->DeviceExtension;
PAGED_CODE();
//
// DeRegister for alarm notifications
//
KeInitializeEvent (&event, NotificationEvent, FALSE);
irp = IoAllocateIrp (subsystemExtension->SmbHcFdo->StackSize, FALSE);
if (!irp) {
BattPrint(BAT_ERROR, ("SmbBattUnregisterForAlarm: couldn't allocate irp\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
irpStack = IoGetNextIrpStackLocation(irp);
irp->UserBuffer = NULL;
irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
irpStack->Parameters.DeviceIoControl.IoControlCode = SMB_DEREGISTER_ALARM_NOTIFY;
irpStack->Parameters.DeviceIoControl.InputBufferLength = sizeof(subsystemExtension->SmbAlarmHandle);
irpStack->Parameters.DeviceIoControl.Type3InputBuffer = &subsystemExtension->SmbAlarmHandle;
irpStack->Parameters.DeviceIoControl.OutputBufferLength = 0;
IoSetCompletionRoutine (irp, SmbBattSynchronousRequest, &event, TRUE, TRUE, TRUE);
IoCallDriver (subsystemExtension->SmbHcFdo, irp);
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = irp->IoStatus.Status;
if (!NT_SUCCESS(status)) {
BattPrint(BAT_ERROR, ("SmbBattUnregisterForAlarm: couldn't unregister for alarms - %x\n", status));
}
IoFreeIrp (irp);
return status;
}
NTSTATUS
SmbGetSBS (
IN PULONG NumberOfBatteries,
IN PBOOLEAN SelectorPresent,
IN PDEVICE_OBJECT LowerDevice
)
/*++
Routine Description:
This routine has the ACPI driver run the control method _SBS for the smart battery
subsystem. This control method returns a value that tells the driver how many
batteries are supported and whether or not the system contains a selector.
Arguments:
NumberOfBatteries - pointer to return the number of batteries
SelectorPresent - Pointer to return whether a selector is present (TRUE)
LowerDevice - device object to call
Return Value:
Status of the IOCTL to the ACPI driver.
--*/
{
ACPI_EVAL_INPUT_BUFFER inputBuffer;
ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
KEVENT event;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
PACPI_METHOD_ARGUMENT argument;
PIRP irp;
PAGED_CODE();
BattPrint (BAT_TRACE, ("SmbGetSBS: Entering\n"));
//
// Initialize the input structure
//
RtlZeroMemory( &inputBuffer, sizeof(ACPI_EVAL_INPUT_BUFFER) );
inputBuffer.MethodNameAsUlong = SMBATT_SBS_METHOD;
inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
//
// Set the event object to the unsignaled state.
// It will be used to signal request completion.
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
//
// Build synchronous request with no transfer.
//
irp = IoBuildDeviceIoControlRequest(
IOCTL_ACPI_ASYNC_EVAL_METHOD,
LowerDevice,
&inputBuffer,
sizeof(ACPI_EVAL_INPUT_BUFFER),
&outputBuffer,
sizeof(ACPI_EVAL_OUTPUT_BUFFER),
FALSE,
&event,
&ioStatusBlock
);
if (irp == NULL) {
BattPrint (BAT_ERROR, ("SmbGetSBS: couldn't create Irp\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Pass request to port driver and wait for request to complete.
//
status = IoCallDriver (LowerDevice, irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatusBlock.Status;
}
//
// Sanity check the data
//
if (outputBuffer.Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE ||
outputBuffer.Count == 0) {
status = STATUS_ACPI_INVALID_DATA;
}
*SelectorPresent = FALSE;
*NumberOfBatteries = 0;
if (!NT_SUCCESS(status)) {
BattPrint (BAT_BIOS_ERROR | BAT_ERROR, ("SmbGetSBS: Irp failed - %x\n", status));
} else {
argument = outputBuffer.Argument;
if (argument->Type != ACPI_METHOD_ARGUMENT_INTEGER) {
return STATUS_ACPI_INVALID_DATA;
}
switch (argument->Argument) {
case 0:
BattPrint(BAT_DATA, ("SmbGetSBS: Number of batteries = 1, no selector\n"));
*NumberOfBatteries = 1;
break;
case 1:
case 2:
case 3:
case 4:
BattPrint(BAT_DATA, ("SmbGetSBS: Number of batteries found - %x\n", argument->Argument));
*SelectorPresent = TRUE;
*NumberOfBatteries = argument->Argument;
break;
default:
BattPrint(BAT_ERROR, ("SmbGetSBS: Invalid number of batteries - %x\n", argument->Argument));
return STATUS_NO_SUCH_DEVICE;
}
}
return status;
}
NTSTATUS
SmbGetGLK (
IN PBOOLEAN GlobalLockRequired,
IN PDEVICE_OBJECT LowerDevice
)
/*++
Routine Description:
This routine has the ACPI driver run the control method _SBS for the smart battery
subsystem. This control method returns a value that tells the driver how many
batteries are supported and whether or not the system contains a selector.
Arguments:
GlobalLockRequired - Pointer to return whether lock acquisition is needed
LowerDevice - device object to call
Return Value:
Status of the IOCTL to the ACPI driver.
--*/
{
ACPI_EVAL_INPUT_BUFFER inputBuffer;
ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
KEVENT event;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
PACPI_METHOD_ARGUMENT argument;
PIRP irp;
PAGED_CODE();
BattPrint (BAT_TRACE, ("SmbGetGLK: Entering\n"));
//
// Initialize the input structure
//
RtlZeroMemory( &inputBuffer, sizeof(ACPI_EVAL_INPUT_BUFFER) );
inputBuffer.MethodNameAsUlong = SMBATT_GLK_METHOD;
inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
//
// Set the event object to the unsignaled state.
// It will be used to signal request completion.
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
//
// Build synchronous request with no transfer.
//
irp = IoBuildDeviceIoControlRequest(
IOCTL_ACPI_ASYNC_EVAL_METHOD,
LowerDevice,
&inputBuffer,
sizeof(ACPI_EVAL_INPUT_BUFFER),
&outputBuffer,
sizeof(ACPI_EVAL_OUTPUT_BUFFER),
FALSE,
&event,
&ioStatusBlock
);
if (irp == NULL) {
BattPrint (BAT_ERROR, ("SmbGetGLK: couldn't create Irp\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Pass request to port driver and wait for request to complete.
//
status = IoCallDriver (LowerDevice, irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatusBlock.Status;
}
if (!NT_SUCCESS(status)) {
if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
status = STATUS_SUCCESS;
*GlobalLockRequired = FALSE;
BattPrint (BAT_NOTE, ("SmbGetGLK: _GLK not found assuming lock is not needed.\n"));
} else {
BattPrint (BAT_ERROR, ("SmbGetGLK: Irp failed - %x\n", status));
}
} else {
//
// Sanity check the data
//
if (outputBuffer.Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE ||
outputBuffer.Count == 0) {
return STATUS_ACPI_INVALID_DATA;
}
argument = outputBuffer.Argument;
if (argument->Type != ACPI_METHOD_ARGUMENT_INTEGER) {
return STATUS_ACPI_INVALID_DATA;
}
if (argument->Argument == 0) {
*GlobalLockRequired = FALSE;
} else if (argument->Argument == 1) {
*GlobalLockRequired = TRUE;
} else {
BattPrint(BAT_BIOS_ERROR, ("SmbGetGLK: Invalid value returned - %x\n", argument->Argument));
status = STATUS_UNSUCCESSFUL;
}
}
BattPrint (BAT_DATA, ("SmbGetGLK: Returning %x GLK = %d\n", status, SmbBattUseGlobalLock));
return status;
}
NTSTATUS
SmbBattCreatePdos(
IN PDEVICE_OBJECT SubsystemFdo
)
/*++
Routine Description:
This routine creates a PDO for each battery supported by the system and puts
it into a list kept with the FDO for the smart battery subsystem.
Arguments:
SubsystemFdo - Fdo for the smart battery subsystem
Return Value:
Status for creation of battery PDO.
--*/
{
ULONG i;
NTSTATUS status;
PSMB_BATT_PDO batteryPdoExt;
UNICODE_STRING numberString;
WCHAR numberBuffer[10];
PDEVICE_OBJECT pdo;
PSMB_BATT_SUBSYSTEM subsystemExt = (PSMB_BATT_SUBSYSTEM) SubsystemFdo->DeviceExtension;
BOOLEAN selectorPresent = FALSE;
PAGED_CODE();
//
// Find out if there are multiple batteries and a selector on this machine.
//
status = SmbGetSBS (
&subsystemExt->NumberOfBatteries,
&subsystemExt->SelectorPresent,
subsystemExt->LowerDevice
);
if (!NT_SUCCESS(status)) {
BattPrint(BAT_ERROR, ("SmbBattCreatePdos: error reading SBS\n"));
return status;
}
status = SmbGetGLK (
&SmbBattUseGlobalLock,
subsystemExt->LowerDevice
);
if (!NT_SUCCESS(status)) {
BattPrint(BAT_ERROR, ("SmbBattCreatePdos: error reading GLK\n"));
//
// If this failed, ignore the failure and continue. This is not critical.
//
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -