xref: /haiku/src/add-ons/kernel/bus_managers/acpi/BusManager.cpp (revision 357ab76ef23def7d2300661d174ea98b6b99731c)
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