xref: /reactos/drivers/bus/acpi/power.c (revision 1734f297)
1 #include "precomp.h"
2 
3 #define NDEBUG
4 #include <debug.h>
5 
6 NTSTATUS
7 NTAPI
8 Bus_Power (
9      PDEVICE_OBJECT DeviceObject,
10      PIRP Irp
11     )
12 {
13     PIO_STACK_LOCATION  irpStack;
14     NTSTATUS            status;
15     PCOMMON_DEVICE_DATA commonData;
16 
17     status = STATUS_SUCCESS;
18     irpStack = IoGetCurrentIrpStackLocation (Irp);
19     ASSERT (IRP_MJ_POWER == irpStack->MajorFunction);
20 
21     commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
22 
23     if (commonData->IsFDO) {
24 
25             DPRINT("FDO %s IRP:0x%p %s %s\n",
26             PowerMinorFunctionString(irpStack->MinorFunction), Irp,
27             DbgSystemPowerString(commonData->SystemPowerState),
28             DbgDevicePowerString(commonData->DevicePowerState));
29 
30 
31         status = Bus_FDO_Power ((PFDO_DEVICE_DATA)DeviceObject->DeviceExtension,
32                                 Irp);
33     } else {
34 
35             DPRINT("PDO %s IRP:0x%p %s %s\n",
36             PowerMinorFunctionString(irpStack->MinorFunction), Irp,
37             DbgSystemPowerString(commonData->SystemPowerState),
38             DbgDevicePowerString(commonData->DevicePowerState));
39 
40         status = Bus_PDO_Power ((PPDO_DEVICE_DATA)DeviceObject->DeviceExtension,
41                                 Irp);
42     }
43 
44     return status;
45 }
46 
47 
48 NTSTATUS
49 Bus_FDO_Power (
50     PFDO_DEVICE_DATA    Data,
51     PIRP                Irp
52     )
53 {
54     NTSTATUS            status = STATUS_SUCCESS;
55     POWER_STATE         powerState;
56     POWER_STATE_TYPE    powerType;
57     PIO_STACK_LOCATION  stack;
58 	ULONG AcpiState;
59 	ACPI_STATUS AcpiStatus;
60     SYSTEM_POWER_STATE  oldPowerState;
61 
62     stack = IoGetCurrentIrpStackLocation (Irp);
63     powerType = stack->Parameters.Power.Type;
64     powerState = stack->Parameters.Power.State;
65 
66 
67     if (stack->MinorFunction == IRP_MN_SET_POWER) {
68         DPRINT("\tRequest to set %s state to %s\n",
69                ((powerType == SystemPowerState) ?  "System" : "Device"),
70                ((powerType == SystemPowerState) ? \
71                DbgSystemPowerString(powerState.SystemState) :\
72                DbgDevicePowerString(powerState.DeviceState)));
73 
74   if (powerType == SystemPowerState)
75   {
76     switch (powerState.SystemState) {
77     case PowerSystemSleeping1:
78       AcpiState = ACPI_STATE_S1;
79       break;
80     case PowerSystemSleeping2:
81       AcpiState = ACPI_STATE_S2;
82       break;
83     case PowerSystemSleeping3:
84       AcpiState = ACPI_STATE_S3;
85       break;
86     case PowerSystemHibernate:
87       AcpiState = ACPI_STATE_S4;
88       break;
89     case PowerSystemShutdown:
90       AcpiState = ACPI_STATE_S5;
91       break;
92     default:
93       AcpiState = ACPI_STATE_UNKNOWN;
94       ASSERT(FALSE);
95       break;
96     }
97       oldPowerState = Data->Common.SystemPowerState;
98       Data->Common.SystemPowerState = powerState.SystemState;
99       AcpiStatus = acpi_suspend(AcpiState);
100       if (!ACPI_SUCCESS(AcpiStatus)) {
101         DPRINT1("Failed to enter sleep state %d (Status 0x%X)\n",
102           AcpiState, AcpiStatus);
103         Data->Common.SystemPowerState = oldPowerState;
104         status = STATUS_UNSUCCESSFUL;
105       }
106   }
107     }
108     PoStartNextPowerIrp (Irp);
109     IoSkipCurrentIrpStackLocation(Irp);
110     status =  PoCallDriver (Data->NextLowerDriver, Irp);
111     return status;
112 }
113 
114 
115 NTSTATUS
116 Bus_PDO_Power (
117     PPDO_DEVICE_DATA    PdoData,
118     PIRP                Irp
119     )
120 {
121     NTSTATUS            status;
122     PIO_STACK_LOCATION  stack;
123     POWER_STATE         powerState;
124     POWER_STATE_TYPE    powerType;
125     ULONG               error;
126 
127     stack = IoGetCurrentIrpStackLocation (Irp);
128     powerType = stack->Parameters.Power.Type;
129     powerState = stack->Parameters.Power.State;
130 
131     switch (stack->MinorFunction) {
132     case IRP_MN_SET_POWER:
133 
134         DPRINT("\tSetting %s power state to %s\n",
135                ((powerType == SystemPowerState) ?  "System" : "Device"),
136                ((powerType == SystemPowerState) ? \
137                DbgSystemPowerString(powerState.SystemState) : \
138                DbgDevicePowerString(powerState.DeviceState)));
139 
140         switch (powerType) {
141             case DevicePowerState:
142                 if (!PdoData->AcpiHandle || !acpi_bus_power_manageable(PdoData->AcpiHandle))
143                 {
144                     PoSetPowerState(PdoData->Common.Self, DevicePowerState, powerState);
145                     PdoData->Common.DevicePowerState = powerState.DeviceState;
146                     status = STATUS_SUCCESS;
147                     break;
148                 }
149 
150                 switch (powerState.DeviceState)
151                 {
152                     case PowerDeviceD0:
153                       error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D0);
154                       break;
155 
156                     case PowerDeviceD1:
157                       error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D1);
158                       break;
159 
160                     case PowerDeviceD2:
161                       error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D2);
162                       break;
163 
164                     case PowerDeviceD3:
165                       error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D3);
166                       break;
167 
168                     default:
169                       error = 0;
170                       break;
171                 }
172 
173                 if (ACPI_SUCCESS(error))
174                 {
175                     PoSetPowerState(PdoData->Common.Self, DevicePowerState, powerState);
176                     PdoData->Common.DevicePowerState = powerState.DeviceState;
177                     status = STATUS_SUCCESS;
178                 }
179                 else
180                     status = STATUS_UNSUCCESSFUL;
181                 break;
182 
183             case SystemPowerState:
184                 PdoData->Common.SystemPowerState = powerState.SystemState;
185                 status = STATUS_SUCCESS;
186                 break;
187 
188             default:
189                 status = STATUS_NOT_SUPPORTED;
190                 break;
191         }
192         break;
193 
194     case IRP_MN_QUERY_POWER:
195         status = STATUS_SUCCESS;
196         break;
197 
198     case IRP_MN_WAIT_WAKE:
199         //
200         // We cannot support wait-wake because we are root-enumerated
201         // driver, and our parent, the PnP manager, doesn't support wait-wake.
202         //
203     case IRP_MN_POWER_SEQUENCE:
204     default:
205         status = STATUS_NOT_SUPPORTED;
206         break;
207     }
208 
209     if (status != STATUS_NOT_SUPPORTED) {
210 
211         Irp->IoStatus.Status = status;
212     }
213 
214     PoStartNextPowerIrp(Irp);
215     status = Irp->IoStatus.Status;
216     IoCompleteRequest (Irp, IO_NO_INCREMENT);
217 
218     return status;
219 }
220 
221 #if !defined(NDEBUG) || defined(_MSC_VER)
222 
223 PCHAR
224 PowerMinorFunctionString (
225     UCHAR MinorFunction
226 )
227 {
228     switch (MinorFunction)
229     {
230         case IRP_MN_SET_POWER:
231             return "IRP_MN_SET_POWER";
232         case IRP_MN_QUERY_POWER:
233             return "IRP_MN_QUERY_POWER";
234         case IRP_MN_POWER_SEQUENCE:
235             return "IRP_MN_POWER_SEQUENCE";
236         case IRP_MN_WAIT_WAKE:
237             return "IRP_MN_WAIT_WAKE";
238 
239         default:
240             return "unknown_power_irp";
241     }
242 }
243 
244 PCHAR
245 DbgSystemPowerString(
246      SYSTEM_POWER_STATE Type
247     )
248 {
249     switch (Type)
250     {
251         case PowerSystemUnspecified:
252             return "PowerSystemUnspecified";
253         case PowerSystemWorking:
254             return "PowerSystemWorking";
255         case PowerSystemSleeping1:
256             return "PowerSystemSleeping1";
257         case PowerSystemSleeping2:
258             return "PowerSystemSleeping2";
259         case PowerSystemSleeping3:
260             return "PowerSystemSleeping3";
261         case PowerSystemHibernate:
262             return "PowerSystemHibernate";
263         case PowerSystemShutdown:
264             return "PowerSystemShutdown";
265         case PowerSystemMaximum:
266             return "PowerSystemMaximum";
267         default:
268             return "UnKnown System Power State";
269     }
270  }
271 
272 PCHAR
273 DbgDevicePowerString(
274      DEVICE_POWER_STATE Type
275     )
276 {
277     switch (Type)
278     {
279         case PowerDeviceUnspecified:
280             return "PowerDeviceUnspecified";
281         case PowerDeviceD0:
282             return "PowerDeviceD0";
283         case PowerDeviceD1:
284             return "PowerDeviceD1";
285         case PowerDeviceD2:
286             return "PowerDeviceD2";
287         case PowerDeviceD3:
288             return "PowerDeviceD3";
289         case PowerDeviceMaximum:
290             return "PowerDeviceMaximum";
291         default:
292             return "UnKnown Device Power State";
293     }
294 }
295 
296 #endif
297