Merge trunk head (46467)
[reactos.git] / reactos / drivers / bus / acpi / cmbatt / cmexec.c
1 /*
2 * PROJECT: ReactOS ACPI-Compliant Control Method Battery
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: boot/drivers/bus/acpi/cmbatt/cmexec.c
5 * PURPOSE: ACPI Method Execution/Evaluation Glue
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "cmbatt.h"
12 #include "ntstatus.h"
13
14 /* FUNCTIONS ******************************************************************/
15
16 NTSTATUS
17 NTAPI
18 GetDwordElement(IN PACPI_METHOD_ARGUMENT Argument,
19 OUT PULONG Value)
20 {
21 NTSTATUS Status;
22
23 /* Must have an integer */
24 if (Argument->Type != ACPI_METHOD_ARGUMENT_INTEGER)
25 {
26 /* Not an integer, fail */
27 Status = STATUS_ACPI_INVALID_DATA;
28 if (CmBattDebug & 0x4C)
29 DbgPrint("GetDwordElement: Object contained wrong data type - %d\n",
30 Argument->Type);
31 }
32 else
33 {
34 /* Read the integer value */
35 *Value = Argument->Argument;
36 Status = STATUS_SUCCESS;
37 }
38
39 /* Return status */
40 return Status;
41 }
42
43 NTSTATUS
44 NTAPI
45 GetStringElement(IN PACPI_METHOD_ARGUMENT Argument,
46 OUT PCHAR Value)
47 {
48 NTSTATUS Status;
49
50 /* Must have a string of buffer */
51 if ((Argument->Type == ACPI_METHOD_ARGUMENT_STRING) ||
52 (Argument->Type == ACPI_METHOD_ARGUMENT_BUFFER))
53 {
54 /* String must be less than 256 characters */
55 if (Argument->DataLength < 256)
56 {
57 /* Copy the buffer */
58 RtlCopyMemory(Value, Argument->Data, Argument->DataLength);
59 Status = STATUS_SUCCESS;
60 }
61 else
62 {
63 /* The buffer is too small (the string is too large) */
64 Status = STATUS_BUFFER_TOO_SMALL;
65 if (CmBattDebug & 0x4C)
66 DbgPrint("GetStringElement: return buffer not big enough - %d\n", Argument->DataLength);
67 }
68 }
69 else
70 {
71 /* Not valid string data */
72 Status = STATUS_ACPI_INVALID_DATA;
73 if (CmBattDebug & 0x4C)
74 DbgPrint("GetStringElement: Object contained wrong data type - %d\n", Argument->Type);
75 }
76
77 /* Return the status */
78 return Status;
79 }
80
81 NTSTATUS
82 NTAPI
83 CmBattSendDownStreamIrp(IN PDEVICE_OBJECT DeviceObject,
84 IN ULONG IoControlCode,
85 IN PVOID InputBuffer,
86 IN ULONG InputBufferLength,
87 IN PACPI_EVAL_OUTPUT_BUFFER OutputBuffer,
88 IN ULONG OutputBufferLength)
89 {
90 PIRP Irp;
91 NTSTATUS Status;
92 KEVENT Event;
93 IO_STATUS_BLOCK IoStatusBlock;
94 PAGED_CODE();
95
96 /* Initialize our wait event */
97 KeInitializeEvent(&Event, SynchronizationEvent, 0);
98
99 /* Allocate the IRP */
100 Irp = IoBuildDeviceIoControlRequest(IoControlCode,
101 DeviceObject,
102 InputBuffer,
103 InputBufferLength,
104 OutputBuffer,
105 OutputBufferLength,
106 0,
107 &Event,
108 &IoStatusBlock);
109 if (!Irp)
110 {
111 /* No IRP, fail */
112 if (CmBattDebug & 0x4C)
113 DbgPrint("CmBattSendDownStreamIrp: Failed to allocate Irp\n");
114 return STATUS_INSUFFICIENT_RESOURCES;
115 }
116
117 /* Call ACPI */
118 if (CmBattDebug & 0x40)
119 DbgPrint("CmBattSendDownStreamIrp: Irp %x [Tid] %x\n",
120 Irp, KeGetCurrentThread());
121 Status = IoCallDriver(DeviceObject, Irp);
122 if (Status == STATUS_PENDING)
123 {
124 /* Wait for completion */
125 KeWaitForSingleObject(&Event,
126 Executive,
127 KernelMode,
128 FALSE,
129 NULL);
130 Status = Irp->IoStatus.Status;
131 }
132
133 /* Check if caller wanted output */
134 if (OutputBuffer)
135 {
136 /* Make sure it's valid ACPI output buffer */
137 if ((OutputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) ||
138 !(OutputBuffer->Count))
139 {
140 /* It isn't, so set failure code */
141 Status = STATUS_ACPI_INVALID_DATA;
142 }
143 }
144
145 /* Return status */
146 if (CmBattDebug & 0x40)
147 DbgPrint("CmBattSendDownStreamIrp: Irp %x completed %x! [Tid] %x\n",
148 Irp, Status, KeGetCurrentThread());
149 return Status;
150 }
151
152 NTSTATUS
153 NTAPI
154 CmBattGetPsrData(IN PDEVICE_OBJECT DeviceObject,
155 OUT PULONG PsrData)
156 {
157 NTSTATUS Status;
158 ACPI_EVAL_OUTPUT_BUFFER OutputBuffer;
159 ACPI_EVAL_INPUT_BUFFER InputBuffer;
160 PAGED_CODE();
161 if (CmBattDebug & 0x40)
162 DbgPrint("CmBattGetPsrData: Entered with Pdo %x Tid %x\n",
163 DeviceObject, KeGetCurrentThread());
164
165 /* Initialize to zero */
166 ASSERT(PsrData != NULL);
167 *PsrData = 0;
168
169 /* Request the _PSR method */
170 *(PULONG)InputBuffer.MethodName = 'RSP_';
171 InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
172
173 /* Send it to ACPI */
174 Status = CmBattSendDownStreamIrp(DeviceObject,
175 IOCTL_ACPI_EVAL_METHOD,
176 &InputBuffer,
177 sizeof(InputBuffer),
178 &OutputBuffer,
179 sizeof(OutputBuffer));
180 if (NT_SUCCESS(Status))
181 {
182 /* Read the result */
183 Status = GetDwordElement(OutputBuffer.Argument, PsrData);
184 if (CmBattDebug & 0x440)
185 DbgPrint("CmBattGetPsrData: _PSR method returned %x \n", *PsrData);
186 }
187 else if (CmBattDebug & 0x44C)
188 {
189 /* Failure */
190 DbgPrint("CmBattGetPsrData: Failed _PSR method - Status (0x%x)\n", Status);
191 }
192
193 /* Return status */
194 return Status;
195 }
196
197 NTSTATUS
198 NTAPI
199 CmBattGetStaData(IN PDEVICE_OBJECT DeviceObject,
200 OUT PULONG StaData)
201 {
202 NTSTATUS Status;
203 ACPI_EVAL_OUTPUT_BUFFER OutputBuffer;
204 ACPI_EVAL_INPUT_BUFFER InputBuffer;
205 PAGED_CODE();
206 if (CmBattDebug & 0x40)
207 DbgPrint("CmBattGetStaData: Entered with Pdo %x Tid %x\n",
208 DeviceObject, KeGetCurrentThread());
209
210 /* Initialize to zero */
211 ASSERT(StaData != NULL);
212 *StaData = 0;
213
214 /* Request the _PSR method */
215 *(PULONG)InputBuffer.MethodName = 'ATS_';
216 InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
217
218 /* Send it to ACPI */
219 Status = CmBattSendDownStreamIrp(DeviceObject,
220 IOCTL_ACPI_EVAL_METHOD,
221 &InputBuffer,
222 sizeof(InputBuffer),
223 &OutputBuffer,
224 sizeof(OutputBuffer));
225 if (NT_SUCCESS(Status))
226 {
227 /* Read the result */
228 Status = GetDwordElement(OutputBuffer.Argument, StaData);
229 if (CmBattDebug & 0x440)
230 DbgPrint("CmBattGetStaData: _STA method returned %x \n", *StaData);
231 }
232 else if (CmBattDebug & 0x44C)
233 {
234 /* Failure */
235 DbgPrint("CmBattGetStaData: Failed _STA method - Status (0x%x)\n", Status);
236 Status = STATUS_NO_SUCH_DEVICE;
237 }
238
239 /* Return status */
240 return Status;
241 }
242
243 NTSTATUS
244 NTAPI
245 CmBattGetUniqueId(IN PDEVICE_OBJECT DeviceObject,
246 OUT PULONG UniqueId)
247 {
248 NTSTATUS Status;
249 ACPI_EVAL_OUTPUT_BUFFER OutputBuffer;
250 ACPI_EVAL_INPUT_BUFFER InputBuffer;
251 PAGED_CODE();
252 if (CmBattDebug & 0x40)
253 DbgPrint("CmBattGetUniqueId: Entered with Pdo %x Tid %x\n",
254 DeviceObject, KeGetCurrentThread());
255
256 /* Initialize to zero */
257 ASSERT(UniqueId != NULL);
258 *UniqueId = 0;
259
260 /* Request the _PSR method */
261 *(PULONG)InputBuffer.MethodName = 'DIU_';
262 InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
263
264 /* Send it to ACPI */
265 Status = CmBattSendDownStreamIrp(DeviceObject,
266 IOCTL_ACPI_EVAL_METHOD,
267 &InputBuffer,
268 sizeof(InputBuffer),
269 &OutputBuffer,
270 sizeof(OutputBuffer));
271 if (NT_SUCCESS(Status))
272 {
273 /* Read the result */
274 Status = GetDwordElement(OutputBuffer.Argument, UniqueId);
275 if (CmBattDebug & 0x440)
276 DbgPrint("CmBattGetUniqueId: _UID method returned %x \n", *UniqueId);
277 }
278 else if (CmBattDebug & 0x44C)
279 {
280 /* Failure */
281 DbgPrint("CmBattGetUniqueId: Failed _UID method - Status (0x%x)\n", Status);
282 Status = STATUS_NO_SUCH_DEVICE;
283 }
284
285 /* Return status */
286 return Status;
287 }
288
289 NTSTATUS
290 NTAPI
291 CmBattSetTripPpoint(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
292 IN ULONG AlarmValue)
293 {
294 NTSTATUS Status;
295 ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER InputBuffer;
296 PAGED_CODE();
297 if (CmBattDebug & 0x440)
298 DbgPrint("CmBattSetTripPpoint: _BTP Alarm Value %x Device %x Tid %x\n",
299 AlarmValue, DeviceExtension->DeviceId, KeGetCurrentThread);
300
301 /* Request the _BTP method */
302 *(PULONG)InputBuffer.MethodName = 'PTB_';
303 InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE;
304 InputBuffer.IntegerArgument = AlarmValue;
305
306 /* Send it to ACPI */
307 Status = CmBattSendDownStreamIrp(DeviceExtension->AttachedDevice,
308 IOCTL_ACPI_EVAL_METHOD,
309 &InputBuffer,
310 sizeof(InputBuffer),
311 NULL,
312 0);
313 if (!(NT_SUCCESS(Status)) && (CmBattDebug & 0x440))
314 DbgPrint("CmBattSetTripPpoint: Failed _BTP method on device %x - Status (0x%x)\n",
315 DeviceExtension->DeviceId, Status);
316
317 /* Return status */
318 return Status;
319 }
320
321 NTSTATUS
322 NTAPI
323 CmBattGetBifData(PCMBATT_DEVICE_EXTENSION DeviceExtension,
324 PACPI_BIF_DATA BifData)
325 {
326 UNIMPLEMENTED;
327 return STATUS_NOT_IMPLEMENTED;
328 }
329
330 NTSTATUS
331 NTAPI
332 CmBattGetBstData(PCMBATT_DEVICE_EXTENSION DeviceExtension,
333 PACPI_BST_DATA BstData)
334 {
335 PIRP Irp;
336 NTSTATUS Status;
337 KEVENT Event;
338 IO_STATUS_BLOCK IoStatusBlock;
339 PAGED_CODE();
340
341 /* Initialize our wait event */
342 KeInitializeEvent(&Event, SynchronizationEvent, 0);
343
344 /* Allocate the IRP */
345 Irp = IoBuildDeviceIoControlRequest(IoControlCode,
346 DeviceObject,
347 InputBuffer,
348 InputBufferLength,
349 OutputBuffer,
350 OutputBufferLength,
351 0,
352 &Event,
353 &IoStatusBlock);
354 if (!Irp)
355 {
356 /* No IRP, fail */
357 if (CmBattDebug & 0x4C)
358 DbgPrint("CmBattSendDownStreamIrp: Failed to allocate Irp\n");
359 return STATUS_INSUFFICIENT_RESOURCES;
360 }
361
362 /* Call ACPI */
363 if (CmBattDebug & 0x40)
364 DbgPrint("CmBattSendDownStreamIrp: Irp %x [Tid] %x\n", Irp, KeGetCurrentThread());
365 Status = IoCallDriver(DeviceObject, Irp);
366 if (Status == STATUS_PENDING)
367 {
368 /* Wait for completion */
369 KeWaitForSingleObject(&Event,
370 Executive,
371 KernelMode,
372 FALSE,
373 NULL);
374 Status = Irp->IoStatus.Status;
375 }
376
377 /* Check if caller wanted output */
378 if (OutputBuffer)
379 {
380 /* Make sure it's valid ACPI output buffer */
381 if ((OutputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) ||
382 !(OutputBuffer->Count))
383 {
384 /* It isn't, so set failure code */
385 Status = STATUS_ACPI_INVALID_DATA;
386 }
387 }
388
389 /* Return status */
390 if (CmBattDebug & 0x40)
391 DbgPrint("CmBattSendDownStreamIrp: Irp %x completed %x! [Tid] %x\n",
392 Irp, Status, KeGetCurrentThread());
393 return Status;
394 }
395
396 /* EOF */