- Silence TCPIP.
[reactos.git] / reactos / ntoskrnl / po / power.c
index 4a9450f..d3f8322 100644 (file)
@@ -1,37 +1,32 @@
-/*
- *  ReactOS kernel
- *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
+/* $Id$
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id: power.c,v 1.11 2004/08/15 16:39:10 chorns Exp $
+ * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/po/power.c
  * PURPOSE:         Power Manager
- * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)
- * UPDATE HISTORY:
- *   20/08/1999 EA  Created
- *   16/04/2001 CSH Stubs added
+ *
+ * PROGRAMMERS:     Casper S. Hornstrup (chorns@users.sourceforge.net)
+ *                  HervĂ© Poussineau (hpoussin@reactos.com)
  */
 
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, PoInit)
+#endif
+
+
+typedef struct _REQUEST_POWER_ITEM
+{
+  PREQUEST_POWER_COMPLETE CompletionRoutine;
+  POWER_STATE PowerState;
+  PVOID Context;
+} REQUEST_POWER_ITEM, *PREQUEST_POWER_ITEM;
 
 PDEVICE_NODE PopSystemPowerDeviceNode = NULL;
+BOOLEAN PopAcpiPresent = FALSE;
 
 /*
  * @implemented
@@ -75,20 +70,110 @@ PoRegisterSystemState(
   return NULL;
 }
 
+static
+NTSTATUS STDCALL
+PopRequestPowerIrpCompletion(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp,
+  IN PVOID Context)
+{
+  PIO_STACK_LOCATION Stack;
+  PREQUEST_POWER_ITEM RequestPowerItem;
+  
+  Stack = IoGetNextIrpStackLocation(Irp);
+  RequestPowerItem = (PREQUEST_POWER_ITEM)Context;
+  
+  RequestPowerItem->CompletionRoutine(
+    DeviceObject,
+    Stack->MinorFunction,
+    RequestPowerItem->PowerState,
+    RequestPowerItem->Context,
+    &Irp->IoStatus);
+  
+  ExFreePool(&Irp->IoStatus);
+  ExFreePool(Context);
+  return STATUS_SUCCESS;
+}
+
 /*
- * @unimplemented
+ * @implemented
  */
 NTSTATUS
 STDCALL
 PoRequestPowerIrp(
   IN PDEVICE_OBJECT DeviceObject,
-  IN UCHAR MinorFunction,  
+  IN UCHAR MinorFunction,
   IN POWER_STATE PowerState,
   IN PREQUEST_POWER_COMPLETE CompletionFunction,
   IN PVOID Context,
-  OUT PIRP *Irp   OPTIONAL)
+  OUT PIRP *pIrp OPTIONAL)
 {
-  return STATUS_NOT_IMPLEMENTED;
+  PDEVICE_OBJECT TopDeviceObject;
+  PIO_STACK_LOCATION Stack;
+  PIRP Irp;
+  PIO_STATUS_BLOCK IoStatusBlock;
+  PREQUEST_POWER_ITEM RequestPowerItem;
+  NTSTATUS Status;
+  
+  if (MinorFunction != IRP_MN_QUERY_POWER
+    && MinorFunction != IRP_MN_SET_POWER
+    && MinorFunction != IRP_MN_WAIT_WAKE)
+    return STATUS_INVALID_PARAMETER_2;
+  
+  RequestPowerItem = ExAllocatePool(NonPagedPool, sizeof(REQUEST_POWER_ITEM));
+  if (!RequestPowerItem)
+    return STATUS_INSUFFICIENT_RESOURCES;
+  IoStatusBlock = ExAllocatePool(NonPagedPool, sizeof(IO_STATUS_BLOCK));
+  if (!IoStatusBlock)
+  {
+    ExFreePool(RequestPowerItem);
+    return STATUS_INSUFFICIENT_RESOURCES;
+  }
+  
+  /* Always call the top of the device stack */
+  TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
+  
+  Irp = IoBuildSynchronousFsdRequest(
+    IRP_MJ_PNP,
+    TopDeviceObject,
+    NULL,
+    0,
+    NULL,
+    NULL,
+    IoStatusBlock);
+  if (!Irp)
+  {
+    ExFreePool(RequestPowerItem);
+    ExFreePool(IoStatusBlock);
+    return STATUS_INSUFFICIENT_RESOURCES;
+  }
+  
+  /* POWER IRPs are always initialized with a status code of
+     STATUS_NOT_IMPLEMENTED */
+  Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+  Irp->IoStatus.Information = 0;
+  
+  Stack = IoGetNextIrpStackLocation(Irp);
+  Stack->MinorFunction = MinorFunction;
+  if (MinorFunction == IRP_MN_WAIT_WAKE)
+    Stack->Parameters.WaitWake.PowerState = PowerState.SystemState;
+  else
+    Stack->Parameters.WaitWake.PowerState = PowerState.DeviceState;
+  
+  RequestPowerItem->CompletionRoutine = CompletionFunction;
+  RequestPowerItem->PowerState = PowerState;
+  RequestPowerItem->Context = Context;
+  
+  if (pIrp != NULL)
+    *pIrp = Irp;
+  
+  IoSetCompletionRoutine(Irp, PopRequestPowerIrpCompletion, RequestPowerItem, TRUE, TRUE, TRUE);
+  Status = IoCallDriver(TopDeviceObject, Irp);
+  
+  /* Always return STATUS_PENDING. The completion routine
+   * will call CompletionFunction and complete the Irp.
+   */
+  return STATUS_PENDING;
 }
 
 VOID
@@ -110,6 +195,8 @@ PoSetPowerState(
 {
   POWER_STATE ps;
 
+  ASSERT_IRQL(DISPATCH_LEVEL);
+
   ps.SystemState = PowerSystemWorking;  // Fully on
   ps.DeviceState = PowerDeviceD0;       // Fully on
 
@@ -147,12 +234,10 @@ PoUnregisterSystemState(
 }
 
 NTSTATUS
+NTAPI
 PopSetSystemPowerState(
   SYSTEM_POWER_STATE PowerState)
 {
-
-#ifdef ACPI
-
   IO_STATUS_BLOCK IoStatusBlock;
   PDEVICE_OBJECT DeviceObject;
   PIO_STACK_LOCATION IrpSp;
@@ -161,6 +246,8 @@ PopSetSystemPowerState(
   KEVENT Event;
   PIRP Irp;
 
+  if (!PopAcpiPresent) return STATUS_NOT_IMPLEMENTED;
+
   Status = IopGetSystemPowerDeviceObject(&DeviceObject);
   if (!NT_SUCCESS(Status)) {
     CPRINT("No system power driver available\n");
@@ -206,15 +293,24 @@ PopSetSystemPowerState(
   ObDereferenceObject(Fdo);
 
   return Status;
-
-#endif /* ACPI */
-
-  return STATUS_NOT_IMPLEMENTED;
 }
 
-VOID INIT_FUNCTION
-PoInit(VOID)
+VOID
+INIT_FUNCTION
+NTAPI
+PoInit(PLOADER_PARAMETER_BLOCK LoaderBlock,
+       BOOLEAN ForceAcpiDisable)
 {
+  if (ForceAcpiDisable)
+    {
+      /* Set the ACPI State to False if it's been forced that way */
+      PopAcpiPresent = FALSE;
+    }
+  else
+    {
+      /* Otherwise check the LoaderBlock's Flag */
+      PopAcpiPresent = (LoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE : FALSE;
+    }
 }
 
 /*
@@ -223,10 +319,10 @@ PoInit(VOID)
 NTSTATUS
 STDCALL
 NtInitiatePowerAction (
-       POWER_ACTION SystemAction,
-       SYSTEM_POWER_STATE MinSystemState,
-       ULONG Flags,
-       BOOLEAN Asynchronous)
+       IN POWER_ACTION SystemAction,
+       IN SYSTEM_POWER_STATE MinSystemState,
+       IN ULONG Flags,
+       IN BOOLEAN Asynchronous)
 {
        UNIMPLEMENTED;
        return STATUS_NOT_IMPLEMENTED;
@@ -235,20 +331,68 @@ NtInitiatePowerAction (
 /*
  * @unimplemented
  */
-NTSTATUS 
-STDCALL 
+NTSTATUS
+STDCALL
 NtPowerInformation(
-       POWER_INFORMATION_LEVEL PowerInformationLevel,
-    PVOID InputBuffer, 
-       ULONG InputBufferLength,
-    PVOID OutputBuffer,
-       ULONG OutputBufferLength
+       IN POWER_INFORMATION_LEVEL PowerInformationLevel,
+       IN PVOID InputBuffer  OPTIONAL,
+       IN ULONG InputBufferLength,
+       OUT PVOID OutputBuffer  OPTIONAL,
+       IN ULONG OutputBufferLength
        )
 {
-       UNIMPLEMENTED;
-       return STATUS_NOT_IMPLEMENTED;
+   NTSTATUS Status;
+
+   PAGED_CODE();
+
+   DPRINT("NtPowerInformation(PowerInformationLevel 0x%x, InputBuffer 0x%x, "
+          "InputBufferLength 0x%x, OutputBuffer 0x%x, OutputBufferLength 0x%x)\n",
+          PowerInformationLevel,
+          InputBuffer, InputBufferLength,
+          OutputBuffer, OutputBufferLength);
+   switch (PowerInformationLevel)
+   {
+   case SystemBatteryState:
+      {
+      PSYSTEM_BATTERY_STATE BatteryState = (PSYSTEM_BATTERY_STATE)OutputBuffer;
+
+      if (InputBuffer != NULL)
+         return STATUS_INVALID_PARAMETER;
+      if (OutputBufferLength < sizeof(SYSTEM_BATTERY_STATE))
+         return STATUS_BUFFER_TOO_SMALL;
+
+      /* Just zero the struct (and thus set BatteryState->BatteryPresent = FALSE) */
+      RtlZeroMemory(BatteryState, sizeof(SYSTEM_BATTERY_STATE));
+      BatteryState->EstimatedTime = (ULONG)-1;
+
+      Status = STATUS_SUCCESS;
+      break;
+      }
+
+   default:
+      Status = STATUS_NOT_IMPLEMENTED;
+      DPRINT1("PowerInformationLevel 0x%x is UNIMPLEMENTED! Have a nice day.\n",
+              PowerInformationLevel);
+      for (;;);
+      break;
+   }
+
+   return Status;
 }
 
 
+NTSTATUS
+STDCALL
+PoQueueShutdownWorkItem(
+       IN PWORK_QUEUE_ITEM WorkItem
+       )
+{
+  PAGED_CODE();
+
+  DPRINT1("PoQueueShutdownWorkItem(%p)\n", WorkItem);
+
+  return STATUS_NOT_IMPLEMENTED;
+}
+
 
 /* EOF */