1 /*
2 * Copyright 2009, Vincent Duvert, vincent.duvert@free.fr
3 * Copyright 2009, Clemens Zeidler, haiku@clemens-zeidler.de
4 * Copyright 2008-2015, Axel Dörfler, axeld@pinc-software.de.
5 * Copyright 2006, Bryan Varner. All rights reserved.
6 * Copyright 2005, Nathan Whitehorn. All rights reserved.
7 *
8 * Distributed under the terms of the MIT License.
9 */
10
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include <ACPI.h>
17 #include <dpc.h>
18 #include <KernelExport.h>
19 #include <PCI.h>
20
21 #include <safemode.h>
22
23 extern "C" {
24 #include "acpi.h"
25 #include "accommon.h"
26 #include "acdisasm.h"
27 #include "acnamesp.h"
28 }
29 #include "ACPIPrivate.h"
30
31 #include "arch_init.h"
32
33
34 //#define TRACE_ACPI_BUS
35 #ifdef TRACE_ACPI_BUS
36 #define TRACE(x...) dprintf("acpi: " x)
37 #else
38 #define TRACE(x...)
39 #endif
40
41 #define ERROR(x...) dprintf("acpi: " x)
42
43 #define ACPI_DEVICE_ID_LENGTH 0x08
44
45 extern dpc_module_info* gDPC;
46 void* gDPCHandle = NULL;
47
48
49 static bool
checkAndLogFailure(const ACPI_STATUS status,const char * msg)50 checkAndLogFailure(const ACPI_STATUS status, const char* msg)
51 {
52 bool failure = ACPI_FAILURE(status);
53 if (failure)
54 dprintf("acpi: %s %s\n", msg, AcpiFormatException(status));
55
56 return failure;
57 }
58
59
60 static ACPI_STATUS
get_device_by_hid_callback(ACPI_HANDLE object,UINT32 depth,void * context,void ** _returnValue)61 get_device_by_hid_callback(ACPI_HANDLE object, UINT32 depth, void* context,
62 void** _returnValue)
63 {
64 uint32* counter = (uint32*)context;
65 ACPI_BUFFER buffer;
66
67 TRACE("get_device_by_hid_callback %p, %d, %p\n", object, depth, context);
68
69 *_returnValue = NULL;
70
71 if (counter[0] == counter[1]) {
72 buffer.Length = 254;
73 buffer.Pointer = malloc(255);
74
75 if (checkAndLogFailure(AcpiGetName(object, ACPI_FULL_PATHNAME, &buffer),
76 "Failed to find device")) {
77 free(buffer.Pointer);
78 return AE_CTRL_TERMINATE;
79 }
80
81 ((char*)buffer.Pointer)[buffer.Length] = '\0';
82 *_returnValue = buffer.Pointer;
83 return AE_CTRL_TERMINATE;
84 }
85
86 counter[1]++;
87 return AE_OK;
88 }
89
90
91 #ifdef ACPI_DEBUG_OUTPUT
92
93
94 static void
globalGPEHandler(UINT32 eventType,ACPI_HANDLE device,UINT32 eventNumber,void * context)95 globalGPEHandler(UINT32 eventType, ACPI_HANDLE device, UINT32 eventNumber,
96 void* context)
97 {
98 ACPI_BUFFER path;
99 char deviceName[256];
100 path.Length = sizeof(deviceName);
101 path.Pointer = deviceName;
102
103 ACPI_STATUS status = AcpiNsHandleToPathname(device, &path);
104 if (ACPI_FAILURE(status))
105 strcpy(deviceName, "(missing)");
106
107 switch (eventType) {
108 case ACPI_EVENT_TYPE_GPE:
109 dprintf("acpi: GPE Event %d for %s\n", eventNumber, deviceName);
110 break;
111
112 case ACPI_EVENT_TYPE_FIXED:
113 {
114 switch (eventNumber) {
115 case ACPI_EVENT_PMTIMER:
116 dprintf("acpi: PMTIMER(%d) event for %s\n", eventNumber,
117 deviceName);
118 break;
119
120 case ACPI_EVENT_GLOBAL:
121 dprintf("acpi: Global(%d) event for %s\n", eventNumber,
122 deviceName);
123 break;
124
125 case ACPI_EVENT_POWER_BUTTON:
126 dprintf("acpi: Powerbutton(%d) event for %s\n", eventNumber,
127 deviceName);
128 break;
129
130 case ACPI_EVENT_SLEEP_BUTTON:
131 dprintf("acpi: sleepbutton(%d) event for %s\n", eventNumber,
132 deviceName);
133 break;
134
135 case ACPI_EVENT_RTC:
136 dprintf("acpi: RTC(%d) event for %s\n", eventNumber,
137 deviceName);
138 break;
139
140 default:
141 dprintf("acpi: unknown fixed(%d) event for %s\n",
142 eventNumber, deviceName);
143 }
144 break;
145 }
146
147 default:
148 dprintf("acpi: unknown event type (%d:%d) event for %s\n",
149 eventType, eventNumber, deviceName);
150 }
151 }
152
153
globalNotifyHandler(ACPI_HANDLE device,UINT32 value,void * context)154 static void globalNotifyHandler(ACPI_HANDLE device, UINT32 value, void* context)
155 {
156 ACPI_BUFFER path;
157 char deviceName[256];
158 path.Length = sizeof(deviceName);
159 path.Pointer = deviceName;
160
161 ACPI_STATUS status = AcpiNsHandleToPathname(device, &path);
162 if (ACPI_FAILURE(status))
163 strcpy(deviceName, "(missing)");
164
165 dprintf("acpi: Notify event %d for %s\n", value, deviceName);
166 }
167
168
169 #endif
170
171
172 // #pragma mark - ACPI bus manager API
173
174
175 static status_t
acpi_std_ops(int32 op,...)176 acpi_std_ops(int32 op,...)
177 {
178 switch (op) {
179 case B_MODULE_INIT:
180 {
181 void *settings;
182 bool acpiDisabled = false;
183 AcpiGbl_CopyDsdtLocally = true;
184
185 settings = load_driver_settings("kernel");
186 if (settings != NULL) {
187 acpiDisabled = !get_driver_boolean_parameter(settings, "acpi",
188 true, true);
189 unload_driver_settings(settings);
190 }
191
192 if (!acpiDisabled) {
193 // check if safemode settings disable ACPI
194 settings = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS);
195 if (settings != NULL) {
196 acpiDisabled = get_driver_boolean_parameter(settings,
197 B_SAFEMODE_DISABLE_ACPI, false, false);
198 unload_driver_settings(settings);
199 }
200 }
201
202 if (acpiDisabled) {
203 ERROR("ACPI disabled\n");
204 return ENOSYS;
205 }
206
207 if (gDPC->new_dpc_queue(&gDPCHandle, "acpi_task",
208 B_URGENT_DISPLAY_PRIORITY + 1) != B_OK) {
209 ERROR("failed to create os execution queue\n");
210 return B_ERROR;
211 }
212
213 #ifdef ACPI_DEBUG_OUTPUT
214 AcpiDbgLevel = ACPI_DEBUG_ALL | ACPI_LV_VERBOSE;
215 AcpiDbgLayer = ACPI_ALL_COMPONENTS;
216 #endif
217
218 if (checkAndLogFailure(AcpiInitializeSubsystem(),
219 "AcpiInitializeSubsystem failed"))
220 goto err_dpc;
221
222 if (checkAndLogFailure(AcpiInitializeTables(NULL, 0, TRUE),
223 "AcpiInitializeTables failed"))
224 goto err_acpi;
225
226 if (checkAndLogFailure(AcpiLoadTables(),
227 "AcpiLoadTables failed"))
228 goto err_acpi;
229
230 /* Install the default address space handlers. */
231
232 arch_init_interrupt_controller();
233
234 if (checkAndLogFailure(AcpiEnableSubsystem(
235 ACPI_FULL_INITIALIZATION),
236 "AcpiEnableSubsystem failed"))
237 goto err_acpi;
238
239 if (checkAndLogFailure(AcpiInitializeObjects(
240 ACPI_FULL_INITIALIZATION),
241 "AcpiInitializeObjects failed"))
242 goto err_acpi;
243
244 //TODO: Walk namespace init ALL _PRW's
245
246 #ifdef ACPI_DEBUG_OUTPUT
247 checkAndLogFailure(
248 AcpiInstallGlobalEventHandler(globalGPEHandler, NULL),
249 "Failed to install global GPE-handler.");
250
251 checkAndLogFailure(AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT,
252 ACPI_ALL_NOTIFY, globalNotifyHandler, NULL),
253 "Failed to install global Notify-handler.");
254 #endif
255 checkAndLogFailure(AcpiEnableAllRuntimeGpes(),
256 "Failed to enable all runtime Gpes");
257
258 checkAndLogFailure(AcpiUpdateAllGpes(),
259 "Failed to update all Gpes");
260
261 TRACE("ACPI initialized\n");
262 return B_OK;
263
264 err_acpi:
265 checkAndLogFailure(AcpiTerminate(), "AcpiTerminate failed");
266
267 err_dpc:
268 gDPC->delete_dpc_queue(gDPCHandle);
269 gDPCHandle = NULL;
270
271 return B_ERROR;
272 }
273
274 case B_MODULE_UNINIT:
275 {
276 checkAndLogFailure(AcpiTerminate(),
277 "Could not bring system out of ACPI mode. Oh well.");
278
279 gDPC->delete_dpc_queue(gDPCHandle);
280 gDPCHandle = NULL;
281 break;
282 }
283
284 default:
285 return B_ERROR;
286 }
287 return B_OK;
288 }
289
290
291 status_t
get_handle(acpi_handle parent,const char * pathname,acpi_handle * retHandle)292 get_handle(acpi_handle parent, const char *pathname, acpi_handle *retHandle)
293 {
294 return AcpiGetHandle(parent, (ACPI_STRING)pathname, retHandle) == AE_OK
295 ? B_OK : B_ERROR;
296 }
297
298
299 status_t
get_name(acpi_handle handle,uint32 nameType,char * returnedName,size_t bufferLength)300 get_name(acpi_handle handle, uint32 nameType, char* returnedName,
301 size_t bufferLength)
302 {
303 ACPI_BUFFER buffer = {bufferLength, (void*)returnedName};
304 return AcpiGetName(handle, nameType, &buffer) == AE_OK ? B_OK : B_ERROR;
305 }
306
307
308 status_t
acquire_global_lock(uint16 timeout,uint32 * handle)309 acquire_global_lock(uint16 timeout, uint32 *handle)
310 {
311 return AcpiAcquireGlobalLock(timeout, (UINT32*)handle) == AE_OK
312 ? B_OK : B_ERROR;
313 }
314
315
316 status_t
release_global_lock(uint32 handle)317 release_global_lock(uint32 handle)
318 {
319 return AcpiReleaseGlobalLock(handle) == AE_OK ? B_OK : B_ERROR;
320 }
321
322
323 status_t
install_notify_handler(acpi_handle device,uint32 handlerType,acpi_notify_handler handler,void * context)324 install_notify_handler(acpi_handle device, uint32 handlerType,
325 acpi_notify_handler handler, void *context)
326 {
327 return AcpiInstallNotifyHandler(device, handlerType,
328 (ACPI_NOTIFY_HANDLER)handler, context) == AE_OK ? B_OK : B_ERROR;
329 }
330
331
332 status_t
remove_notify_handler(acpi_handle device,uint32 handlerType,acpi_notify_handler handler)333 remove_notify_handler(acpi_handle device, uint32 handlerType,
334 acpi_notify_handler handler)
335 {
336 return AcpiRemoveNotifyHandler(device, handlerType,
337 (ACPI_NOTIFY_HANDLER)handler) == AE_OK ? B_OK : B_ERROR;
338 }
339
340
341 status_t
update_all_gpes()342 update_all_gpes()
343 {
344 return AcpiUpdateAllGpes() == AE_OK ? B_OK : B_ERROR;
345 }
346
347
348 status_t
enable_gpe(acpi_handle handle,uint32 gpeNumber)349 enable_gpe(acpi_handle handle, uint32 gpeNumber)
350 {
351 return AcpiEnableGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR;
352 }
353
354
355 status_t
disable_gpe(acpi_handle handle,uint32 gpeNumber)356 disable_gpe(acpi_handle handle, uint32 gpeNumber)
357 {
358 return AcpiDisableGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR;
359 }
360
361
362 status_t
clear_gpe(acpi_handle handle,uint32 gpeNumber)363 clear_gpe(acpi_handle handle, uint32 gpeNumber)
364 {
365 return AcpiClearGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR;
366 }
367
368
369 status_t
set_gpe(acpi_handle handle,uint32 gpeNumber,uint8 action)370 set_gpe(acpi_handle handle, uint32 gpeNumber, uint8 action)
371 {
372 return AcpiSetGpe(handle, gpeNumber, action) == AE_OK ? B_OK : B_ERROR;
373 }
374
375
376 status_t
finish_gpe(acpi_handle handle,uint32 gpeNumber)377 finish_gpe(acpi_handle handle, uint32 gpeNumber)
378 {
379 return AcpiFinishGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR;
380 }
381
382
383 status_t
install_gpe_handler(acpi_handle handle,uint32 gpeNumber,uint32 type,acpi_gpe_handler handler,void * data)384 install_gpe_handler(acpi_handle handle, uint32 gpeNumber, uint32 type,
385 acpi_gpe_handler handler, void *data)
386 {
387 return AcpiInstallGpeHandler(handle, gpeNumber, type,
388 (ACPI_GPE_HANDLER)handler, data) == AE_OK ? B_OK : B_ERROR;
389 }
390
391
392 status_t
remove_gpe_handler(acpi_handle handle,uint32 gpeNumber,acpi_gpe_handler address)393 remove_gpe_handler(acpi_handle handle, uint32 gpeNumber,
394 acpi_gpe_handler address)
395 {
396 return AcpiRemoveGpeHandler(handle, gpeNumber, (ACPI_GPE_HANDLER)address)
397 == AE_OK ? B_OK : B_ERROR;
398 }
399
400
401 status_t
install_address_space_handler(acpi_handle handle,uint32 spaceId,acpi_adr_space_handler handler,acpi_adr_space_setup setup,void * data)402 install_address_space_handler(acpi_handle handle, uint32 spaceId,
403 acpi_adr_space_handler handler, acpi_adr_space_setup setup, void *data)
404 {
405 return AcpiInstallAddressSpaceHandler(handle, spaceId,
406 (ACPI_ADR_SPACE_HANDLER)handler, (ACPI_ADR_SPACE_SETUP)setup, data)
407 == AE_OK ? B_OK : B_ERROR;
408 }
409
410
411 status_t
remove_address_space_handler(acpi_handle handle,uint32 spaceId,acpi_adr_space_handler handler)412 remove_address_space_handler(acpi_handle handle, uint32 spaceId,
413 acpi_adr_space_handler handler)
414 {
415 return AcpiRemoveAddressSpaceHandler(handle, spaceId,
416 (ACPI_ADR_SPACE_HANDLER)handler) == AE_OK ? B_OK : B_ERROR;
417 }
418
419
420 void
enable_fixed_event(uint32 event)421 enable_fixed_event(uint32 event)
422 {
423 AcpiEnableEvent(event, 0);
424 }
425
426
427 void
disable_fixed_event(uint32 event)428 disable_fixed_event(uint32 event)
429 {
430 AcpiDisableEvent(event, 0);
431 }
432
433
434 uint32
fixed_event_status(uint32 event)435 fixed_event_status(uint32 event)
436 {
437 ACPI_EVENT_STATUS status = 0;
438 AcpiGetEventStatus(event, &status);
439 return status/* & ACPI_EVENT_FLAG_SET*/;
440 }
441
442
443 void
reset_fixed_event(uint32 event)444 reset_fixed_event(uint32 event)
445 {
446 AcpiClearEvent(event);
447 }
448
449
450 status_t
install_fixed_event_handler(uint32 event,acpi_event_handler handler,void * data)451 install_fixed_event_handler(uint32 event, acpi_event_handler handler,
452 void *data)
453 {
454 return AcpiInstallFixedEventHandler(event, (ACPI_EVENT_HANDLER)handler, data) == AE_OK
455 ? B_OK : B_ERROR;
456 }
457
458
459 status_t
remove_fixed_event_handler(uint32 event,acpi_event_handler handler)460 remove_fixed_event_handler(uint32 event, acpi_event_handler handler)
461 {
462 return AcpiRemoveFixedEventHandler(event, (ACPI_EVENT_HANDLER)handler) == AE_OK
463 ? B_OK : B_ERROR;
464 }
465
466
467 status_t
get_next_entry(uint32 objectType,const char * base,char * result,size_t length,void ** counter)468 get_next_entry(uint32 objectType, const char *base, char *result,
469 size_t length, void **counter)
470 {
471 ACPI_HANDLE parent, child, newChild;
472 ACPI_BUFFER buffer;
473 ACPI_STATUS status;
474
475 TRACE("get_next_entry %ld, %s\n", objectType, base);
476
477 if (base == NULL || !strcmp(base, "\\")) {
478 parent = ACPI_ROOT_OBJECT;
479 } else {
480 status = AcpiGetHandle(NULL, (ACPI_STRING)base, &parent);
481 if (status != AE_OK)
482 return B_ENTRY_NOT_FOUND;
483 }
484
485 child = *counter;
486
487 status = AcpiGetNextObject(objectType, parent, child, &newChild);
488 if (status != AE_OK)
489 return B_ENTRY_NOT_FOUND;
490
491 *counter = newChild;
492 buffer.Length = length;
493 buffer.Pointer = result;
494
495 status = AcpiGetName(newChild, ACPI_FULL_PATHNAME, &buffer);
496 if (status != AE_OK)
497 return B_NO_MEMORY; /* Corresponds to AE_BUFFER_OVERFLOW */
498
499 return B_OK;
500 }
501
502
503 status_t
get_next_object(uint32 objectType,acpi_handle parent,acpi_handle * currentChild)504 get_next_object(uint32 objectType, acpi_handle parent,
505 acpi_handle* currentChild)
506 {
507 acpi_handle child = *currentChild;
508 return AcpiGetNextObject(objectType, parent, child, currentChild) == AE_OK
509 ? B_OK : B_ERROR;
510 }
511
512
513 status_t
get_device(const char * hid,uint32 index,char * result,size_t resultLength)514 get_device(const char* hid, uint32 index, char* result, size_t resultLength)
515 {
516 ACPI_STATUS status;
517 uint32 counter[2] = {index, 0};
518 char *buffer = NULL;
519
520 TRACE("get_device %s, index %ld\n", hid, index);
521 status = AcpiGetDevices((ACPI_STRING)hid, (ACPI_WALK_CALLBACK)&get_device_by_hid_callback,
522 counter, (void**)&buffer);
523 if (status != AE_OK || buffer == NULL)
524 return B_ENTRY_NOT_FOUND;
525
526 strlcpy(result, buffer, resultLength);
527 free(buffer);
528 return B_OK;
529 }
530
531
532 status_t
get_device_info(const char * path,char ** hid,char ** cidList,size_t cidListCount,char ** uid,char ** cls)533 get_device_info(const char *path, char** hid, char** cidList,
534 size_t cidListCount, char** uid, char** cls)
535 {
536 ACPI_HANDLE handle;
537 ACPI_DEVICE_INFO *info;
538
539 TRACE("get_device_info: path %s\n", path);
540 if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK)
541 return B_ENTRY_NOT_FOUND;
542
543 if (AcpiGetObjectInfo(handle, &info) != AE_OK)
544 return B_BAD_TYPE;
545
546 if ((info->Valid & ACPI_VALID_HID) != 0 && hid != NULL)
547 *hid = strndup(info->HardwareId.String, info->HardwareId.Length);
548
549 if ((info->Valid & ACPI_VALID_CID) != 0 && cidList != NULL) {
550 if (cidListCount > info->CompatibleIdList.Count)
551 cidListCount = info->CompatibleIdList.Count;
552 for (size_t i = 0; i < cidListCount; i++) {
553 cidList[i] = strndup(info->CompatibleIdList.Ids[i].String,
554 info->CompatibleIdList.Ids[i].Length);
555 }
556 }
557
558 if ((info->Valid & ACPI_VALID_UID) != 0 && uid != NULL)
559 *uid = strndup(info->UniqueId.String, info->UniqueId.Length);
560
561 if ((info->Valid & ACPI_VALID_CLS) != 0 && cls != NULL
562 && info->ClassCode.Length >= ACPI_PCICLS_STRING_SIZE) {
563 *cls = strndup(info->ClassCode.String, info->ClassCode.Length);
564 }
565
566 AcpiOsFree(info);
567 return B_OK;
568 }
569
570
571 status_t
get_device_addr(const char * path,uint32 * addr)572 get_device_addr(const char *path, uint32 *addr)
573 {
574 ACPI_HANDLE handle;
575
576 TRACE("get_device_adr: path %s, hid %s\n", path, hid);
577 if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK)
578 return B_ENTRY_NOT_FOUND;
579
580 status_t status = B_BAD_VALUE;
581 acpi_data buf;
582 acpi_object_type object;
583 buf.pointer = &object;
584 buf.length = sizeof(acpi_object_type);
585 if (addr != NULL
586 && evaluate_method(handle, "_ADR", NULL, &buf) == B_OK
587 && object.object_type == ACPI_TYPE_INTEGER) {
588 status = B_OK;
589 *addr = object.integer.integer;
590 }
591 return status;
592 }
593
594
595 uint32
get_object_type(const char * path)596 get_object_type(const char* path)
597 {
598 ACPI_HANDLE handle;
599 ACPI_OBJECT_TYPE type;
600
601 if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK)
602 return B_ENTRY_NOT_FOUND;
603
604 AcpiGetType(handle, &type);
605 return type;
606 }
607
608
609 status_t
get_object(const char * path,acpi_object_type ** _returnValue)610 get_object(const char* path, acpi_object_type** _returnValue)
611 {
612 ACPI_HANDLE handle;
613 ACPI_BUFFER buffer;
614 ACPI_STATUS status;
615
616 status = AcpiGetHandle(NULL, (ACPI_STRING)path, &handle);
617 if (status != AE_OK)
618 return B_ENTRY_NOT_FOUND;
619
620 buffer.Pointer = NULL;
621 buffer.Length = ACPI_ALLOCATE_BUFFER;
622
623 status = AcpiEvaluateObject(handle, NULL, NULL, &buffer);
624
625 *_returnValue = (acpi_object_type*)buffer.Pointer;
626 return status == AE_OK ? B_OK : B_ERROR;
627 }
628
629
630 status_t
get_object_typed(const char * path,acpi_object_type ** _returnValue,uint32 objectType)631 get_object_typed(const char* path, acpi_object_type** _returnValue,
632 uint32 objectType)
633 {
634 ACPI_HANDLE handle;
635 ACPI_BUFFER buffer;
636 ACPI_STATUS status;
637
638 status = AcpiGetHandle(NULL, (ACPI_STRING)path, &handle);
639 if (status != AE_OK)
640 return B_ENTRY_NOT_FOUND;
641
642 buffer.Pointer = NULL;
643 buffer.Length = ACPI_ALLOCATE_BUFFER;
644
645 status = AcpiEvaluateObjectTyped(handle, NULL, NULL, &buffer, objectType);
646
647 *_returnValue = (acpi_object_type*)buffer.Pointer;
648 return status == AE_OK ? B_OK : B_ERROR;
649 }
650
651
652 status_t
ns_handle_to_pathname(acpi_handle targetHandle,acpi_data * buffer)653 ns_handle_to_pathname(acpi_handle targetHandle, acpi_data *buffer)
654 {
655 status_t status = AcpiNsHandleToPathname(targetHandle,
656 (ACPI_BUFFER*)buffer, false);
657 return status == AE_OK ? B_OK : B_ERROR;
658 }
659
660
661 status_t
evaluate_object(acpi_handle handle,const char * object,acpi_objects * args,acpi_object_type * returnValue,size_t bufferLength)662 evaluate_object(acpi_handle handle, const char* object, acpi_objects *args,
663 acpi_object_type* returnValue, size_t bufferLength)
664 {
665 ACPI_BUFFER buffer;
666 ACPI_STATUS status;
667
668 buffer.Pointer = returnValue;
669 buffer.Length = bufferLength;
670
671 status = AcpiEvaluateObject(handle, (ACPI_STRING)object,
672 (ACPI_OBJECT_LIST*)args, returnValue != NULL ? &buffer : NULL);
673 if (status == AE_BUFFER_OVERFLOW)
674 dprintf("evaluate_object: the passed buffer is too small!\n");
675
676 return status == AE_OK ? B_OK : B_ERROR;
677 }
678
679
680 status_t
evaluate_method(acpi_handle handle,const char * method,acpi_objects * args,acpi_data * returnValue)681 evaluate_method(acpi_handle handle, const char* method,
682 acpi_objects *args, acpi_data *returnValue)
683 {
684 ACPI_STATUS status;
685
686 status = AcpiEvaluateObject(handle, (ACPI_STRING)method,
687 (ACPI_OBJECT_LIST*)args, (ACPI_BUFFER*)returnValue);
688 if (status == AE_BUFFER_OVERFLOW)
689 dprintf("evaluate_method: the passed buffer is too small!\n");
690
691 return status == AE_OK ? B_OK : B_ERROR;
692 }
693
694
695 status_t
get_irq_routing_table(acpi_handle busDeviceHandle,acpi_data * retBuffer)696 get_irq_routing_table(acpi_handle busDeviceHandle, acpi_data *retBuffer)
697 {
698 ACPI_STATUS status;
699
700 status = AcpiGetIrqRoutingTable(busDeviceHandle, (ACPI_BUFFER*)retBuffer);
701 if (status == AE_BUFFER_OVERFLOW)
702 dprintf("get_irq_routing_table: the passed buffer is too small!\n");
703
704 return status == AE_OK ? B_OK : B_ERROR;
705 }
706
707
708 status_t
get_current_resources(acpi_handle busDeviceHandle,acpi_data * retBuffer)709 get_current_resources(acpi_handle busDeviceHandle, acpi_data *retBuffer)
710 {
711 return AcpiGetCurrentResources(busDeviceHandle, (ACPI_BUFFER*)retBuffer)
712 == AE_OK ? B_OK : B_ERROR;
713 }
714
715
716 status_t
get_possible_resources(acpi_handle busDeviceHandle,acpi_data * retBuffer)717 get_possible_resources(acpi_handle busDeviceHandle, acpi_data *retBuffer)
718 {
719 return AcpiGetPossibleResources(busDeviceHandle, (ACPI_BUFFER*)retBuffer)
720 == AE_OK ? B_OK : B_ERROR;
721 }
722
723
724 status_t
set_current_resources(acpi_handle busDeviceHandle,acpi_data * buffer)725 set_current_resources(acpi_handle busDeviceHandle, acpi_data *buffer)
726 {
727 return AcpiSetCurrentResources(busDeviceHandle, (ACPI_BUFFER*)buffer)
728 == AE_OK ? B_OK : B_ERROR;
729 }
730
731
732 status_t
walk_resources(acpi_handle busDeviceHandle,char * method,acpi_walk_resources_callback callback,void * context)733 walk_resources(acpi_handle busDeviceHandle, char* method,
734 acpi_walk_resources_callback callback, void* context)
735 {
736 return AcpiWalkResources(busDeviceHandle, method,
737 (ACPI_WALK_RESOURCE_CALLBACK)callback, context);
738 }
739
740
741 status_t
walk_namespace(acpi_handle busDeviceHandle,uint32 objectType,uint32 maxDepth,acpi_walk_callback descendingCallback,acpi_walk_callback ascendingCallback,void * context,void ** returnValue)742 walk_namespace(acpi_handle busDeviceHandle, uint32 objectType,
743 uint32 maxDepth, acpi_walk_callback descendingCallback,
744 acpi_walk_callback ascendingCallback, void* context, void** returnValue)
745 {
746 return AcpiWalkNamespace(objectType, busDeviceHandle, maxDepth,
747 (ACPI_WALK_CALLBACK)descendingCallback,
748 (ACPI_WALK_CALLBACK)ascendingCallback, context, returnValue);
749 }
750
751
752 status_t
prepare_sleep_state(uint8 state,void (* wakeFunc)(void),size_t size)753 prepare_sleep_state(uint8 state, void (*wakeFunc)(void), size_t size)
754 {
755 ACPI_STATUS acpiStatus;
756
757 TRACE("prepare_sleep_state %d, %p, %ld\n", state, wakeFunc, size);
758
759 if (state != ACPI_POWER_STATE_OFF) {
760 physical_entry wakeVector;
761 status_t status;
762
763 // Note: The supplied code must already be locked into memory.
764 status = get_memory_map((const void*)wakeFunc, size, &wakeVector, 1);
765 if (status != B_OK)
766 return status;
767
768 # if B_HAIKU_PHYSICAL_BITS > 32
769 if (wakeVector.address >= 0x100000000LL) {
770 ERROR("prepare_sleep_state(): ACPI 2.0c says use 32 bit "
771 "vector, but we have a physical address >= 4 GB\n");
772 }
773 # endif
774 acpiStatus = AcpiSetFirmwareWakingVector(wakeVector.address,
775 wakeVector.address);
776 if (acpiStatus != AE_OK)
777 return B_ERROR;
778 }
779
780 acpiStatus = AcpiEnterSleepStatePrep(state);
781 if (acpiStatus != AE_OK)
782 return B_ERROR;
783
784 return B_OK;
785 }
786
787
788 status_t
enter_sleep_state(uint8 state)789 enter_sleep_state(uint8 state)
790 {
791 ACPI_STATUS status;
792
793 TRACE("enter_sleep_state %d\n", state);
794
795 cpu_status cpu = disable_interrupts();
796 status = AcpiEnterSleepState(state);
797 restore_interrupts(cpu);
798 panic("AcpiEnterSleepState should not return.");
799 if (status != AE_OK)
800 return B_ERROR;
801
802 /*status = AcpiLeaveSleepState(state);
803 if (status != AE_OK)
804 return B_ERROR;*/
805
806 return B_OK;
807 }
808
809
810 status_t
reboot(void)811 reboot(void)
812 {
813 ACPI_STATUS status;
814
815 TRACE("reboot\n");
816
817 status = AcpiReset();
818 if (status == AE_NOT_EXIST)
819 return B_UNSUPPORTED;
820
821 if (status != AE_OK) {
822 ERROR("Reset failed, status = %d\n", status);
823 return B_ERROR;
824 }
825
826 snooze(1000000);
827 ERROR("Reset failed, timeout\n");
828 return B_ERROR;
829 }
830
831
832 status_t
get_table(const char * signature,uint32 instance,void ** tableHeader)833 get_table(const char* signature, uint32 instance, void** tableHeader)
834 {
835 return AcpiGetTable((char*)signature, instance,
836 (ACPI_TABLE_HEADER**)tableHeader) == AE_OK ? B_OK : B_ERROR;
837 }
838
839
840 status_t
read_bit_register(uint32 regid,uint32 * val)841 read_bit_register(uint32 regid, uint32 *val)
842 {
843 return AcpiReadBitRegister(regid, (UINT32 *)val);
844 }
845
846
847 status_t
write_bit_register(uint32 regid,uint32 val)848 write_bit_register(uint32 regid, uint32 val)
849 {
850 return AcpiWriteBitRegister(regid, val);
851 }
852
853
854 struct acpi_module_info gACPIModule = {
855 {
856 B_ACPI_MODULE_NAME,
857 B_KEEP_LOADED,
858 acpi_std_ops
859 },
860
861 get_handle,
862 get_name,
863 acquire_global_lock,
864 release_global_lock,
865 install_notify_handler,
866 remove_notify_handler,
867 update_all_gpes,
868 enable_gpe,
869 disable_gpe,
870 clear_gpe,
871 set_gpe,
872 finish_gpe,
873 install_gpe_handler,
874 remove_gpe_handler,
875 install_address_space_handler,
876 remove_address_space_handler,
877 enable_fixed_event,
878 disable_fixed_event,
879 fixed_event_status,
880 reset_fixed_event,
881 install_fixed_event_handler,
882 remove_fixed_event_handler,
883 get_next_entry,
884 get_next_object,
885 walk_namespace,
886 get_device,
887 get_device_info,
888 get_object_type,
889 get_object,
890 get_object_typed,
891 ns_handle_to_pathname,
892 evaluate_object,
893 evaluate_method,
894 get_irq_routing_table,
895 get_current_resources,
896 get_possible_resources,
897 set_current_resources,
898 walk_resources,
899 prepare_sleep_state,
900 enter_sleep_state,
901 reboot,
902 get_table,
903 read_bit_register,
904 write_bit_register
905 };
906