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