xref: /haiku/src/add-ons/kernel/bus_managers/acpi/BusManager.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
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
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
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
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 
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
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;
221 
222 			if (checkAndLogFailure(AcpiInitializeTables(NULL, 0, TRUE),
223 					"AcpiInitializeTables failed"))
224 				goto err;
225 
226 			if (checkAndLogFailure(AcpiLoadTables(),
227 					"AcpiLoadTables failed"))
228 				goto err;
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;
238 
239 			if (checkAndLogFailure(AcpiInitializeObjects(
240 						ACPI_FULL_INITIALIZATION),
241 					"AcpiInitializeObjects failed"))
242 				goto err;
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:
265 			return B_ERROR;
266 		}
267 
268 		case B_MODULE_UNINIT:
269 		{
270 			checkAndLogFailure(AcpiTerminate(),
271 				"Could not bring system out of ACPI mode. Oh well.");
272 
273 			gDPC->delete_dpc_queue(gDPCHandle);
274 			gDPCHandle = NULL;
275 			break;
276 		}
277 
278 		default:
279 			return B_ERROR;
280 	}
281 	return B_OK;
282 }
283 
284 
285 status_t
286 get_handle(acpi_handle parent, const char *pathname, acpi_handle *retHandle)
287 {
288 	return AcpiGetHandle(parent, (ACPI_STRING)pathname, retHandle) == AE_OK
289 		? B_OK : B_ERROR;
290 }
291 
292 
293 status_t
294 get_name(acpi_handle handle, uint32 nameType, char* returnedName,
295 	size_t bufferLength)
296 {
297 	ACPI_BUFFER buffer = {bufferLength, (void*)returnedName};
298 	return AcpiGetName(handle, nameType, &buffer) == AE_OK ? B_OK : B_ERROR;
299 }
300 
301 
302 status_t
303 acquire_global_lock(uint16 timeout, uint32 *handle)
304 {
305 	return AcpiAcquireGlobalLock(timeout, (UINT32*)handle) == AE_OK
306 		? B_OK : B_ERROR;
307 }
308 
309 
310 status_t
311 release_global_lock(uint32 handle)
312 {
313 	return AcpiReleaseGlobalLock(handle) == AE_OK ? B_OK : B_ERROR;
314 }
315 
316 
317 status_t
318 install_notify_handler(acpi_handle device, uint32 handlerType,
319 	acpi_notify_handler handler, void *context)
320 {
321 	return AcpiInstallNotifyHandler(device, handlerType,
322 		(ACPI_NOTIFY_HANDLER)handler, context) == AE_OK ? B_OK : B_ERROR;
323 }
324 
325 
326 status_t
327 remove_notify_handler(acpi_handle device, uint32 handlerType,
328 	acpi_notify_handler handler)
329 {
330 	return AcpiRemoveNotifyHandler(device, handlerType,
331 		(ACPI_NOTIFY_HANDLER)handler) == AE_OK ? B_OK : B_ERROR;
332 }
333 
334 
335 status_t
336 update_all_gpes()
337 {
338 	return AcpiUpdateAllGpes() == AE_OK ? B_OK : B_ERROR;
339 }
340 
341 
342 status_t
343 enable_gpe(acpi_handle handle, uint32 gpeNumber)
344 {
345 	return AcpiEnableGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR;
346 }
347 
348 
349 status_t
350 disable_gpe(acpi_handle handle, uint32 gpeNumber)
351 {
352 	return AcpiDisableGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR;
353 }
354 
355 
356 status_t
357 clear_gpe(acpi_handle handle, uint32 gpeNumber)
358 {
359 	return AcpiClearGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR;
360 }
361 
362 
363 status_t
364 set_gpe(acpi_handle handle, uint32 gpeNumber, uint8 action)
365 {
366 	return AcpiSetGpe(handle, gpeNumber, action) == AE_OK ? B_OK : B_ERROR;
367 }
368 
369 
370 status_t
371 finish_gpe(acpi_handle handle, uint32 gpeNumber)
372 {
373 	return AcpiFinishGpe(handle, gpeNumber) == AE_OK ? B_OK : B_ERROR;
374 }
375 
376 
377 status_t
378 install_gpe_handler(acpi_handle handle, uint32 gpeNumber, uint32 type,
379 	acpi_gpe_handler handler, void *data)
380 {
381 	return AcpiInstallGpeHandler(handle, gpeNumber, type,
382 		(ACPI_GPE_HANDLER)handler, data) == AE_OK ? B_OK : B_ERROR;
383 }
384 
385 
386 status_t
387 remove_gpe_handler(acpi_handle handle, uint32 gpeNumber,
388 	acpi_gpe_handler address)
389 {
390 	return AcpiRemoveGpeHandler(handle, gpeNumber, (ACPI_GPE_HANDLER)address)
391 		== AE_OK ? B_OK : B_ERROR;
392 }
393 
394 
395 status_t
396 install_address_space_handler(acpi_handle handle, uint32 spaceId,
397 	acpi_adr_space_handler handler, acpi_adr_space_setup setup,	void *data)
398 {
399 	return AcpiInstallAddressSpaceHandler(handle, spaceId,
400 		(ACPI_ADR_SPACE_HANDLER)handler, (ACPI_ADR_SPACE_SETUP)setup, data)
401 		== AE_OK ? B_OK : B_ERROR;
402 }
403 
404 
405 status_t
406 remove_address_space_handler(acpi_handle handle, uint32 spaceId,
407 	acpi_adr_space_handler handler)
408 {
409 	return AcpiRemoveAddressSpaceHandler(handle, spaceId,
410 		(ACPI_ADR_SPACE_HANDLER)handler) == AE_OK ? B_OK : B_ERROR;
411 }
412 
413 
414 void
415 enable_fixed_event(uint32 event)
416 {
417 	AcpiEnableEvent(event, 0);
418 }
419 
420 
421 void
422 disable_fixed_event(uint32 event)
423 {
424 	AcpiDisableEvent(event, 0);
425 }
426 
427 
428 uint32
429 fixed_event_status(uint32 event)
430 {
431 	ACPI_EVENT_STATUS status = 0;
432 	AcpiGetEventStatus(event, &status);
433 	return status/* & ACPI_EVENT_FLAG_SET*/;
434 }
435 
436 
437 void
438 reset_fixed_event(uint32 event)
439 {
440 	AcpiClearEvent(event);
441 }
442 
443 
444 status_t
445 install_fixed_event_handler(uint32 event, acpi_event_handler handler,
446 	void *data)
447 {
448 	return AcpiInstallFixedEventHandler(event, (ACPI_EVENT_HANDLER)handler, data) == AE_OK
449 		? B_OK : B_ERROR;
450 }
451 
452 
453 status_t
454 remove_fixed_event_handler(uint32 event, acpi_event_handler handler)
455 {
456 	return AcpiRemoveFixedEventHandler(event, (ACPI_EVENT_HANDLER)handler) == AE_OK
457 		? B_OK : B_ERROR;
458 }
459 
460 
461 status_t
462 get_next_entry(uint32 objectType, const char *base, char *result,
463 	size_t length, void **counter)
464 {
465 	ACPI_HANDLE parent, child, newChild;
466 	ACPI_BUFFER buffer;
467 	ACPI_STATUS status;
468 
469 	TRACE("get_next_entry %ld, %s\n", objectType, base);
470 
471 	if (base == NULL || !strcmp(base, "\\")) {
472 		parent = ACPI_ROOT_OBJECT;
473 	} else {
474 		status = AcpiGetHandle(NULL, (ACPI_STRING)base, &parent);
475 		if (status != AE_OK)
476 			return B_ENTRY_NOT_FOUND;
477 	}
478 
479 	child = *counter;
480 
481 	status = AcpiGetNextObject(objectType, parent, child, &newChild);
482 	if (status != AE_OK)
483 		return B_ENTRY_NOT_FOUND;
484 
485 	*counter = newChild;
486 	buffer.Length = length;
487 	buffer.Pointer = result;
488 
489 	status = AcpiGetName(newChild, ACPI_FULL_PATHNAME, &buffer);
490 	if (status != AE_OK)
491 		return B_NO_MEMORY; /* Corresponds to AE_BUFFER_OVERFLOW */
492 
493 	return B_OK;
494 }
495 
496 
497 status_t
498 get_next_object(uint32 objectType, acpi_handle parent,
499 	acpi_handle* currentChild)
500 {
501 	acpi_handle child = *currentChild;
502 	return AcpiGetNextObject(objectType, parent, child, currentChild) == AE_OK
503 		? B_OK : B_ERROR;
504 }
505 
506 
507 status_t
508 get_device(const char* hid, uint32 index, char* result, size_t resultLength)
509 {
510 	ACPI_STATUS status;
511 	uint32 counter[2] = {index, 0};
512 	char *buffer = NULL;
513 
514 	TRACE("get_device %s, index %ld\n", hid, index);
515 	status = AcpiGetDevices((ACPI_STRING)hid, (ACPI_WALK_CALLBACK)&get_device_by_hid_callback,
516 		counter, (void**)&buffer);
517 	if (status != AE_OK || buffer == NULL)
518 		return B_ENTRY_NOT_FOUND;
519 
520 	strlcpy(result, buffer, resultLength);
521 	free(buffer);
522 	return B_OK;
523 }
524 
525 
526 status_t
527 get_device_info(const char *path, char** hid, char** cidList,
528 	size_t cidListCount, char** uid)
529 {
530 	ACPI_HANDLE handle;
531 	ACPI_DEVICE_INFO *info;
532 
533 	TRACE("get_device_info: path %s\n", path);
534 	if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK)
535 		return B_ENTRY_NOT_FOUND;
536 
537 	if (AcpiGetObjectInfo(handle, &info) != AE_OK)
538 		return B_BAD_TYPE;
539 
540 	if ((info->Valid & ACPI_VALID_HID) != 0 && hid != NULL)
541 		*hid = strndup(info->HardwareId.String, info->HardwareId.Length);
542 
543 	if ((info->Valid & ACPI_VALID_CID) != 0 && cidList != NULL) {
544 		if (cidListCount > info->CompatibleIdList.Count)
545 			cidListCount = info->CompatibleIdList.Count;
546 		for (size_t i = 0; i < cidListCount; i++) {
547 			cidList[i] = strndup(info->CompatibleIdList.Ids[i].String,
548 				info->CompatibleIdList.Ids[i].Length);
549 		}
550 	}
551 
552 	if ((info->Valid & ACPI_VALID_UID) != 0 && uid != NULL)
553 		*uid = strndup(info->UniqueId.String, info->UniqueId.Length);
554 
555 	AcpiOsFree(info);
556 	return B_OK;
557 }
558 
559 
560 status_t
561 get_device_addr(const char *path, uint32 *addr)
562 {
563 	ACPI_HANDLE handle;
564 
565 	TRACE("get_device_adr: path %s, hid %s\n", path, hid);
566 	if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK)
567 		return B_ENTRY_NOT_FOUND;
568 
569 	status_t status = B_BAD_VALUE;
570 	acpi_data buf;
571 	acpi_object_type object;
572 	buf.pointer = &object;
573 	buf.length = sizeof(acpi_object_type);
574 	if (addr != NULL
575 		&& evaluate_method(handle, "_ADR", NULL, &buf) == B_OK
576 		&& object.object_type == ACPI_TYPE_INTEGER) {
577 		status = B_OK;
578 		*addr = object.integer.integer;
579 	}
580 	return status;
581 }
582 
583 
584 uint32
585 get_object_type(const char* path)
586 {
587 	ACPI_HANDLE handle;
588 	ACPI_OBJECT_TYPE type;
589 
590 	if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK)
591 		return B_ENTRY_NOT_FOUND;
592 
593 	AcpiGetType(handle, &type);
594 	return type;
595 }
596 
597 
598 status_t
599 get_object(const char* path, acpi_object_type** _returnValue)
600 {
601 	ACPI_HANDLE handle;
602 	ACPI_BUFFER buffer;
603 	ACPI_STATUS status;
604 
605 	status = AcpiGetHandle(NULL, (ACPI_STRING)path, &handle);
606 	if (status != AE_OK)
607 		return B_ENTRY_NOT_FOUND;
608 
609 	buffer.Pointer = NULL;
610 	buffer.Length = ACPI_ALLOCATE_BUFFER;
611 
612 	status = AcpiEvaluateObject(handle, NULL, NULL, &buffer);
613 
614 	*_returnValue = (acpi_object_type*)buffer.Pointer;
615 	return status == AE_OK ? B_OK : B_ERROR;
616 }
617 
618 
619 status_t
620 get_object_typed(const char* path, acpi_object_type** _returnValue,
621 	uint32 objectType)
622 {
623 	ACPI_HANDLE handle;
624 	ACPI_BUFFER buffer;
625 	ACPI_STATUS status;
626 
627 	status = AcpiGetHandle(NULL, (ACPI_STRING)path, &handle);
628 	if (status != AE_OK)
629 		return B_ENTRY_NOT_FOUND;
630 
631 	buffer.Pointer = NULL;
632 	buffer.Length = ACPI_ALLOCATE_BUFFER;
633 
634 	status = AcpiEvaluateObjectTyped(handle, NULL, NULL, &buffer, objectType);
635 
636 	*_returnValue = (acpi_object_type*)buffer.Pointer;
637 	return status == AE_OK ? B_OK : B_ERROR;
638 }
639 
640 
641 status_t
642 ns_handle_to_pathname(acpi_handle targetHandle, acpi_data *buffer)
643 {
644 	status_t status = AcpiNsHandleToPathname(targetHandle,
645 		(ACPI_BUFFER*)buffer, false);
646 	return status == AE_OK ? B_OK : B_ERROR;
647 }
648 
649 
650 status_t
651 evaluate_object(acpi_handle handle, const char* object, acpi_objects *args,
652 	acpi_object_type* returnValue, size_t bufferLength)
653 {
654 	ACPI_BUFFER buffer;
655 	ACPI_STATUS status;
656 
657 	buffer.Pointer = returnValue;
658 	buffer.Length = bufferLength;
659 
660 	status = AcpiEvaluateObject(handle, (ACPI_STRING)object,
661 		(ACPI_OBJECT_LIST*)args, returnValue != NULL ? &buffer : NULL);
662 	if (status == AE_BUFFER_OVERFLOW)
663 		dprintf("evaluate_object: the passed buffer is too small!\n");
664 
665 	return status == AE_OK ? B_OK : B_ERROR;
666 }
667 
668 
669 status_t
670 evaluate_method(acpi_handle handle, const char* method,
671 	acpi_objects *args, acpi_data *returnValue)
672 {
673 	ACPI_STATUS status;
674 
675 	status = AcpiEvaluateObject(handle, (ACPI_STRING)method,
676 		(ACPI_OBJECT_LIST*)args, (ACPI_BUFFER*)returnValue);
677 	if (status == AE_BUFFER_OVERFLOW)
678 		dprintf("evaluate_method: the passed buffer is too small!\n");
679 
680 	return status == AE_OK ? B_OK : B_ERROR;
681 }
682 
683 
684 status_t
685 get_irq_routing_table(acpi_handle busDeviceHandle, acpi_data *retBuffer)
686 {
687 	ACPI_STATUS status;
688 
689 	status = AcpiGetIrqRoutingTable(busDeviceHandle, (ACPI_BUFFER*)retBuffer);
690 	if (status == AE_BUFFER_OVERFLOW)
691 		dprintf("get_irq_routing_table: the passed buffer is too small!\n");
692 
693 	return status == AE_OK ? B_OK : B_ERROR;
694 }
695 
696 
697 status_t
698 get_current_resources(acpi_handle busDeviceHandle, acpi_data *retBuffer)
699 {
700 	return AcpiGetCurrentResources(busDeviceHandle, (ACPI_BUFFER*)retBuffer)
701 		== AE_OK ? B_OK : B_ERROR;
702 }
703 
704 
705 status_t
706 get_possible_resources(acpi_handle busDeviceHandle, acpi_data *retBuffer)
707 {
708 	return AcpiGetPossibleResources(busDeviceHandle, (ACPI_BUFFER*)retBuffer)
709 		== AE_OK ? B_OK : B_ERROR;
710 }
711 
712 
713 status_t
714 set_current_resources(acpi_handle busDeviceHandle, acpi_data *buffer)
715 {
716 	return AcpiSetCurrentResources(busDeviceHandle, (ACPI_BUFFER*)buffer)
717 		== AE_OK ? B_OK : B_ERROR;
718 }
719 
720 
721 status_t
722 walk_resources(acpi_handle busDeviceHandle, char* method,
723 	acpi_walk_resources_callback callback, void* context)
724 {
725 	return AcpiWalkResources(busDeviceHandle, method,
726 		(ACPI_WALK_RESOURCE_CALLBACK)callback, context);
727 }
728 
729 
730 status_t
731 walk_namespace(acpi_handle busDeviceHandle, uint32 objectType,
732 	uint32 maxDepth, acpi_walk_callback descendingCallback,
733 	acpi_walk_callback ascendingCallback, void* context, void** returnValue)
734 {
735 	return AcpiWalkNamespace(objectType, busDeviceHandle, maxDepth,
736 		(ACPI_WALK_CALLBACK)descendingCallback,
737 		(ACPI_WALK_CALLBACK)ascendingCallback, context, returnValue);
738 }
739 
740 
741 status_t
742 prepare_sleep_state(uint8 state, void (*wakeFunc)(void), size_t size)
743 {
744 	ACPI_STATUS acpiStatus;
745 
746 	TRACE("prepare_sleep_state %d, %p, %ld\n", state, wakeFunc, size);
747 
748 	if (state != ACPI_POWER_STATE_OFF) {
749 		physical_entry wakeVector;
750 		status_t status;
751 
752 		// Note: The supplied code must already be locked into memory.
753 		status = get_memory_map((const void*)wakeFunc, size, &wakeVector, 1);
754 		if (status != B_OK)
755 			return status;
756 
757 #	if B_HAIKU_PHYSICAL_BITS > 32
758 		if (wakeVector.address >= 0x100000000LL) {
759 			ERROR("prepare_sleep_state(): ACPI 2.0c says use 32 bit "
760 				"vector, but we have a physical address >= 4 GB\n");
761 		}
762 #	endif
763 		acpiStatus = AcpiSetFirmwareWakingVector(wakeVector.address,
764 			wakeVector.address);
765 		if (acpiStatus != AE_OK)
766 			return B_ERROR;
767 	}
768 
769 	acpiStatus = AcpiEnterSleepStatePrep(state);
770 	if (acpiStatus != AE_OK)
771 		return B_ERROR;
772 
773 	return B_OK;
774 }
775 
776 
777 status_t
778 enter_sleep_state(uint8 state)
779 {
780 	ACPI_STATUS status;
781 
782 	TRACE("enter_sleep_state %d\n", state);
783 
784 	cpu_status cpu = disable_interrupts();
785 	status = AcpiEnterSleepState(state);
786 	restore_interrupts(cpu);
787 	panic("AcpiEnterSleepState should not return.");
788 	if (status != AE_OK)
789 		return B_ERROR;
790 
791 	/*status = AcpiLeaveSleepState(state);
792 	if (status != AE_OK)
793 		return B_ERROR;*/
794 
795 	return B_OK;
796 }
797 
798 
799 status_t
800 reboot(void)
801 {
802 	ACPI_STATUS status;
803 
804 	TRACE("reboot\n");
805 
806 	status = AcpiReset();
807 	if (status == AE_NOT_EXIST)
808 		return B_UNSUPPORTED;
809 
810 	if (status != AE_OK) {
811 		ERROR("Reset failed, status = %d\n", status);
812 		return B_ERROR;
813 	}
814 
815 	snooze(1000000);
816 	ERROR("Reset failed, timeout\n");
817 	return B_ERROR;
818 }
819 
820 
821 status_t
822 get_table(const char* signature, uint32 instance, void** tableHeader)
823 {
824 	return AcpiGetTable((char*)signature, instance,
825 		(ACPI_TABLE_HEADER**)tableHeader) == AE_OK ? B_OK : B_ERROR;
826 }
827 
828 
829 status_t
830 read_bit_register(uint32 regid, uint32 *val)
831 {
832 	return AcpiReadBitRegister(regid, (UINT32 *)val);
833 }
834 
835 
836 status_t
837 write_bit_register(uint32 regid, uint32 val)
838 {
839 	return AcpiWriteBitRegister(regid, val);
840 }
841 
842 
843 struct acpi_module_info gACPIModule = {
844 	{
845 		B_ACPI_MODULE_NAME,
846 		B_KEEP_LOADED,
847 		acpi_std_ops
848 	},
849 
850 	get_handle,
851 	get_name,
852 	acquire_global_lock,
853 	release_global_lock,
854 	install_notify_handler,
855 	remove_notify_handler,
856 	update_all_gpes,
857 	enable_gpe,
858 	disable_gpe,
859 	clear_gpe,
860 	set_gpe,
861 	finish_gpe,
862 	install_gpe_handler,
863 	remove_gpe_handler,
864 	install_address_space_handler,
865 	remove_address_space_handler,
866 	enable_fixed_event,
867 	disable_fixed_event,
868 	fixed_event_status,
869 	reset_fixed_event,
870 	install_fixed_event_handler,
871 	remove_fixed_event_handler,
872 	get_next_entry,
873 	get_next_object,
874 	walk_namespace,
875 	get_device,
876 	get_device_info,
877 	get_object_type,
878 	get_object,
879 	get_object_typed,
880 	ns_handle_to_pathname,
881 	evaluate_object,
882 	evaluate_method,
883 	get_irq_routing_table,
884 	get_current_resources,
885 	get_possible_resources,
886 	set_current_resources,
887 	walk_resources,
888 	prepare_sleep_state,
889 	enter_sleep_state,
890 	reboot,
891 	get_table,
892 	read_bit_register,
893 	write_bit_register
894 };
895