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