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