Author: sir_richard
Date: Tue Mar 23 23:18:04 2010
New Revision: 46371
URL:
http://svn.reactos.org/svn/reactos?rev=46371&view=rev
Log:
[CMBATT]: Implement PnP handling. Only the ACPI-facing interface needs to be written now.
Modified:
trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.c
trunk/reactos/drivers/bus/acpi/cmbatt/cmbpnp.c
Modified: trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/acpi/cmbatt/cm…
==============================================================================
--- trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.c [iso-8859-1] Tue Mar 23 23:18:04 2010
@@ -225,23 +225,20 @@
BatteryClassStatusNotify(DeviceExtension->ClassData);
}
}
- else
- {
- /* The only known notification is AC/DC change */
- if (DeviceExtension->ArFlag & CMBATT_AR_NOTIFY)
- {
- for (DeviceObject =
DeviceExtension->FdoDeviceObject->DriverObject->DeviceObject;
- DeviceObject;
- DeviceObject = DeviceObject->NextDevice)
+ else if (DeviceExtension->ArFlag & CMBATT_AR_NOTIFY)
+ {
+ /* The only known notification is AC/DC change. Loop device objects. */
+ for (DeviceObject =
DeviceExtension->FdoDeviceObject->DriverObject->DeviceObject;
+ DeviceObject;
+ DeviceObject = DeviceObject->NextDevice)
+ {
+ /* Is this a battery? */
+ FdoExtension = DeviceObject->DeviceExtension;
+ if (FdoExtension->FdoType == CmBattBattery)
{
- /* Is this a battery? */
- FdoExtension = DeviceObject->DeviceExtension;
- if (FdoExtension->FdoType == CmBattBattery)
- {
- /* Send a notification to the class driver */
- FdoExtension->NotifySent = TRUE;
- BatteryClassStatusNotify(FdoExtension->ClassData);
- }
+ /* Send a notification to the class driver */
+ FdoExtension->NotifySent = TRUE;
+ BatteryClassStatusNotify(FdoExtension->ClassData);
}
}
}
@@ -466,7 +463,8 @@
else
{
/* Buffer size invalid */
- Status = STATUS_INVALID_BUFFER_SIZE; }
+ Status = STATUS_INVALID_BUFFER_SIZE;
+ }
break;
case IOCTL_BATTERY_QUERY_BIF:
Modified: trunk/reactos/drivers/bus/acpi/cmbatt/cmbpnp.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/acpi/cmbatt/cm…
==============================================================================
--- trunk/reactos/drivers/bus/acpi/cmbatt/cmbpnp.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/acpi/cmbatt/cmbpnp.c [iso-8859-1] Tue Mar 23 23:18:04 2010
@@ -12,6 +12,43 @@
/* FUNCTIONS ******************************************************************/
+VOID
+NTAPI
+CmBattWaitWakeLoop(IN PDEVICE_OBJECT DeviceObject,
+ IN UCHAR MinorFunction,
+ IN POWER_STATE PowerState,
+ IN PVOID Context,
+ IN PIO_STATUS_BLOCK IoStatusBlock)
+{
+ NTSTATUS Status;
+ PCMBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+ if (CmBattDebug & 0x20) DbgPrint("CmBattWaitWakeLoop: Entered.\n");
+
+ /* Check for success */
+ if ((NT_SUCCESS(IoStatusBlock->Status)) &&
(DeviceExtension->WaitWakeEnable))
+ {
+ /* Request a new power IRP */
+ if (CmBattDebug & 2) DbgPrint("CmBattWaitWakeLoop: completed
successfully\n");
+ Status = PoRequestPowerIrp(DeviceObject,
+ MinorFunction,
+ PowerState,
+ CmBattWaitWakeLoop,
+ Context,
+ &DeviceExtension->PowerIrp);
+ if (CmBattDebug & 2)
+ DbgPrint("CmBattWaitWakeLoop: PoRequestPowerIrp: status =
0x%08x.\n",
+ Status);
+ }
+ else
+ {
+ /* Clear the power IRP, we failed */
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattWaitWakeLoop: failed: status = 0x%08x.\n",
+ IoStatusBlock->Status);
+ DeviceExtension->PowerIrp = NULL;
+ }
+}
+
NTSTATUS
NTAPI
CmBattIoCompletion(IN PDEVICE_OBJECT DeviceObject,
@@ -222,11 +259,266 @@
NTSTATUS
NTAPI
-CmBattPnpDispatch(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+CmBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStackLocation;
+ PCMBATT_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status;
+ KEVENT Event;
+ PAGED_CODE();
+
+ /* Get stack location and device extension */
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+ DeviceExtension = DeviceObject->DeviceExtension;
+
+ /* Set default error */
+ Status = STATUS_NOT_SUPPORTED;
+
+ /* Try to acquire the lock before doing anything */
+ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Complete the request */
+ Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
+ IofCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_DEVICE_REMOVED;
+ }
+
+ /* What's the operation? */
+ switch (IoStackLocation->MinorFunction)
+ {
+ case IRP_MN_QUERY_PNP_DEVICE_STATE:
+
+ /* Initialize our wait event */
+ KeInitializeEvent(&Event, SynchronizationEvent, 0);
+
+ /* Set the completion routine */
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+ IoSetCompletionRoutine(Irp,
+ (PVOID)CmBattIoCompletion,
+ &Event,
+ TRUE,
+ TRUE,
+ TRUE);
+
+ /* Now call ACPI to inherit its PnP Device State */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ /* Wait for completion */
+ KeWaitForSingleObject(&Event,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ Status = Irp->IoStatus.Status;
+ }
+
+ /* However, a battery CAN be disabled */
+ Irp->IoStatus.Information &= ~PNP_DEVICE_NOT_DISABLEABLE;
+
+ /* Release the remove lock and complete the request */
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
+ return Status;
+
+ case IRP_MN_SURPRISE_REMOVAL:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_SURPRISE_REMOVAL\n");
+
+ /* Lock the device extension and set the handle count to invalid */
+ ExAcquireFastMutex(&DeviceExtension->FastMutex);
+ DeviceExtension->HandleCount = -1;
+ ExReleaseFastMutex(&DeviceExtension->FastMutex);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IRP_MN_START_DEVICE:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_START_DEVICE\n");
+
+ /* Mark the extension as started */
+ if (DeviceExtension->FdoType == CmBattBattery) DeviceExtension->Started
= TRUE;
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IRP_MN_STOP_DEVICE:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_STOP_DEVICE\n");
+
+ /* Mark the extension as stopped */
+ if (DeviceExtension->FdoType == CmBattBattery) DeviceExtension->Started
= FALSE;
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IRP_MN_QUERY_REMOVE_DEVICE:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_REMOVE_DEVICE\n");
+
+ /* Lock the extension and get the current handle count */
+ ExAcquireFastMutex(&DeviceExtension->FastMutex);
+ if (DeviceExtension->HandleCount == 0)
+ {
+ /* No handles. Mark it as invalid since it'll be removed */
+ DeviceExtension->HandleCount = -1;
+ Status = STATUS_SUCCESS;
+ }
+ else if (DeviceExtension->HandleCount == -1)
+ {
+ /* Don't do anything, but this is strange since it's already
removed */
+ Status = STATUS_SUCCESS;
+ if (CmBattDebug & 4)
+ DbgPrint("CmBattPnpDispatch: Recieved two consecutive
QUERY_REMOVE requests.\n");
+ }
+ else
+ {
+ /* Fail because there's still open handles */
+ Status = STATUS_UNSUCCESSFUL;
+ }
+
+ /* Release the lock and return */
+ ExReleaseFastMutex(&DeviceExtension->FastMutex);
+ break;
+
+ case IRP_MN_REMOVE_DEVICE:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_REMOVE_DEVICE\n");
+
+ /* Call the remove code */
+ Status = CmBattRemoveDevice(DeviceObject, Irp);
+ break;
+
+ case IRP_MN_CANCEL_REMOVE_DEVICE:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_CANCEL_REMOVE_DEVICE\n");
+
+ /* Lock the extension and get the handle count */
+ ExAcquireFastMutex(&DeviceExtension->FastMutex);
+ if (DeviceExtension->HandleCount == -1)
+ {
+ /* A remove was in progress, set the handle count back to 0 */
+ DeviceExtension->HandleCount = 0;
+ }
+ else if (CmBattDebug & 2)
+ {
+ /* Nop, but warn about it */
+ DbgPrint("CmBattPnpDispatch: Received CANCEL_REMOVE when OpenCount
== %x\n",
+ DeviceExtension->HandleCount);
+ }
+
+ /* Return success in all cases, and release the lock */
+ Status = STATUS_SUCCESS;
+ ExReleaseFastMutex(&DeviceExtension->FastMutex);
+ break;
+
+ case IRP_MN_QUERY_STOP_DEVICE:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_STOP_DEVICE\n");
+
+ /* There's no real support for this */
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case IRP_MN_CANCEL_STOP_DEVICE:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_CANCEL_STOP_DEVICE\n");
+
+ /* There's no real support for this */
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case IRP_MN_QUERY_CAPABILITIES:
+
+ /* Initialize our wait event */
+ KeInitializeEvent(&Event, SynchronizationEvent, 0);
+
+ /* Set the completion routine */
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+ IoSetCompletionRoutine(Irp,
+ (PVOID)CmBattIoCompletion,
+ &Event,
+ TRUE,
+ TRUE,
+ TRUE);
+
+ /* Now call ACPI */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ /* Wait for completion */
+ KeWaitForSingleObject(&Event,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ Status = Irp->IoStatus.Status;
+ }
+
+ /* Get the wake power state */
+ DeviceExtension->PowerState.SystemState =
IoStackLocation->Parameters.DeviceCapabilities.Capabilities->SystemWake;
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES %d
Capabilities->SystemWake = %x\n",
+ DeviceExtension->FdoType,
+ DeviceExtension->PowerState);
+
+ /* Check if it's invalid */
+ if (DeviceExtension->PowerState.SystemState == PowerSystemUnspecified)
+ {
+ /* Wait wake is not supported in this scenario */
+ DeviceExtension->WaitWakeEnable = FALSE;
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES Wake not
supported.\n");
+ }
+ else if (!(DeviceExtension->PowerIrp) &&
+ (DeviceExtension->WaitWakeEnable))
+ {
+ /* If it was requested in the registry, request the power IRP for it */
+ PoRequestPowerIrp(DeviceExtension->DeviceObject,
+ 0,
+ DeviceExtension->PowerState,
+ CmBattWaitWakeLoop,
+ 0,
+ &DeviceExtension->PowerIrp);
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES wait/Wake
irp sent.\n");
+ }
+
+ /* Release the remove lock and complete the request */
+ IofCompleteRequest(Irp, IO_NO_INCREMENT);
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
+ return Status;
+
+ default:
+ /* Unsupported */
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: Unimplemented minor %0x\n",
+ IoStackLocation->MinorFunction);
+ break;
+ }
+
+ /* Release the remove lock */
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
+
+ /* Set IRP status if we have one */
+ if (Status != STATUS_NOT_SUPPORTED) Irp->IoStatus.Status = Status;
+
+ /* Did someone pick it up? */
+ if ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED))
+ {
+ /* Still unsupported, try ACPI */
+ IoSkipCurrentIrpStackLocation(Irp);
+ Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
+ }
+ else
+ {
+ /* Complete the request */
+ Status = Irp->IoStatus.Status;
+ IofCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+
+ /* Release the remove lock and return status */
+ return Status;
}
NTSTATUS