xref: /haiku/src/add-ons/kernel/bus_managers/acpi/BusManager.cpp (revision 82bfaa954dcfd90582fb2c1a0e918971eea57091)
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, char** cls)
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 	if ((info->Valid & ACPI_VALID_CLS) != 0 && cls != NULL
556 		&& info->ClassCode.Length >= ACPI_PCICLS_STRING_SIZE) {
557 		*cls = strndup(info->ClassCode.String, info->ClassCode.Length);
558 	}
559 
560 	AcpiOsFree(info);
561 	return B_OK;
562 }
563 
564 
565 status_t
566 get_device_addr(const char *path, uint32 *addr)
567 {
568 	ACPI_HANDLE handle;
569 
570 	TRACE("get_device_adr: path %s, hid %s\n", path, hid);
571 	if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK)
572 		return B_ENTRY_NOT_FOUND;
573 
574 	status_t status = B_BAD_VALUE;
575 	acpi_data buf;
576 	acpi_object_type object;
577 	buf.pointer = &object;
578 	buf.length = sizeof(acpi_object_type);
579 	if (addr != NULL
580 		&& evaluate_method(handle, "_ADR", NULL, &buf) == B_OK
581 		&& object.object_type == ACPI_TYPE_INTEGER) {
582 		status = B_OK;
583 		*addr = object.integer.integer;
584 	}
585 	return status;
586 }
587 
588 
589 uint32
590 get_object_type(const char* path)
591 {
592 	ACPI_HANDLE handle;
593 	ACPI_OBJECT_TYPE type;
594 
595 	if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK)
596 		return B_ENTRY_NOT_FOUND;
597 
598 	AcpiGetType(handle, &type);
599 	return type;
600 }
601 
602 
603 status_t
604 get_object(const char* path, acpi_object_type** _returnValue)
605 {
606 	ACPI_HANDLE handle;
607 	ACPI_BUFFER buffer;
608 	ACPI_STATUS status;
609 
610 	status = AcpiGetHandle(NULL, (ACPI_STRING)path, &handle);
611 	if (status != AE_OK)
612 		return B_ENTRY_NOT_FOUND;
613 
614 	buffer.Pointer = NULL;
615 	buffer.Length = ACPI_ALLOCATE_BUFFER;
616 
617 	status = AcpiEvaluateObject(handle, NULL, NULL, &buffer);
618 
619 	*_returnValue = (acpi_object_type*)buffer.Pointer;
620 	return status == AE_OK ? B_OK : B_ERROR;
621 }
622 
623 
624 status_t
625 get_object_typed(const char* path, acpi_object_type** _returnValue,
626 	uint32 objectType)
627 {
628 	ACPI_HANDLE handle;
629 	ACPI_BUFFER buffer;
630 	ACPI_STATUS status;
631 
632 	status = AcpiGetHandle(NULL, (ACPI_STRING)path, &handle);
633 	if (status != AE_OK)
634 		return B_ENTRY_NOT_FOUND;
635 
636 	buffer.Pointer = NULL;
637 	buffer.Length = ACPI_ALLOCATE_BUFFER;
638 
639 	status = AcpiEvaluateObjectTyped(handle, NULL, NULL, &buffer, objectType);
640 
641 	*_returnValue = (acpi_object_type*)buffer.Pointer;
642 	return status == AE_OK ? B_OK : B_ERROR;
643 }
644 
645 
646 status_t
647 ns_handle_to_pathname(acpi_handle targetHandle, acpi_data *buffer)
648 {
649 	status_t status = AcpiNsHandleToPathname(targetHandle,
650 		(ACPI_BUFFER*)buffer, false);
651 	return status == AE_OK ? B_OK : B_ERROR;
652 }
653 
654 
655 status_t
656 evaluate_object(acpi_handle handle, const char* object, acpi_objects *args,
657 	acpi_object_type* returnValue, size_t bufferLength)
658 {
659 	ACPI_BUFFER buffer;
660 	ACPI_STATUS status;
661 
662 	buffer.Pointer = returnValue;
663 	buffer.Length = bufferLength;
664 
665 	status = AcpiEvaluateObject(handle, (ACPI_STRING)object,
666 		(ACPI_OBJECT_LIST*)args, returnValue != NULL ? &buffer : NULL);
667 	if (status == AE_BUFFER_OVERFLOW)
668 		dprintf("evaluate_object: the passed buffer is too small!\n");
669 
670 	return status == AE_OK ? B_OK : B_ERROR;
671 }
672 
673 
674 status_t
675 evaluate_method(acpi_handle handle, const char* method,
676 	acpi_objects *args, acpi_data *returnValue)
677 {
678 	ACPI_STATUS status;
679 
680 	status = AcpiEvaluateObject(handle, (ACPI_STRING)method,
681 		(ACPI_OBJECT_LIST*)args, (ACPI_BUFFER*)returnValue);
682 	if (status == AE_BUFFER_OVERFLOW)
683 		dprintf("evaluate_method: the passed buffer is too small!\n");
684 
685 	return status == AE_OK ? B_OK : B_ERROR;
686 }
687 
688 
689 status_t
690 get_irq_routing_table(acpi_handle busDeviceHandle, acpi_data *retBuffer)
691 {
692 	ACPI_STATUS status;
693 
694 	status = AcpiGetIrqRoutingTable(busDeviceHandle, (ACPI_BUFFER*)retBuffer);
695 	if (status == AE_BUFFER_OVERFLOW)
696 		dprintf("get_irq_routing_table: the passed buffer is too small!\n");
697 
698 	return status == AE_OK ? B_OK : B_ERROR;
699 }
700 
701 
702 status_t
703 get_current_resources(acpi_handle busDeviceHandle, acpi_data *retBuffer)
704 {
705 	return AcpiGetCurrentResources(busDeviceHandle, (ACPI_BUFFER*)retBuffer)
706 		== AE_OK ? B_OK : B_ERROR;
707 }
708 
709 
710 status_t
711 get_possible_resources(acpi_handle busDeviceHandle, acpi_data *retBuffer)
712 {
713 	return AcpiGetPossibleResources(busDeviceHandle, (ACPI_BUFFER*)retBuffer)
714 		== AE_OK ? B_OK : B_ERROR;
715 }
716 
717 
718 status_t
719 set_current_resources(acpi_handle busDeviceHandle, acpi_data *buffer)
720 {
721 	return AcpiSetCurrentResources(busDeviceHandle, (ACPI_BUFFER*)buffer)
722 		== AE_OK ? B_OK : B_ERROR;
723 }
724 
725 
726 status_t
727 walk_resources(acpi_handle busDeviceHandle, char* method,
728 	acpi_walk_resources_callback callback, void* context)
729 {
730 	return AcpiWalkResources(busDeviceHandle, method,
731 		(ACPI_WALK_RESOURCE_CALLBACK)callback, context);
732 }
733 
734 
735 status_t
736 walk_namespace(acpi_handle busDeviceHandle, uint32 objectType,
737 	uint32 maxDepth, acpi_walk_callback descendingCallback,
738 	acpi_walk_callback ascendingCallback, void* context, void** returnValue)
739 {
740 	return AcpiWalkNamespace(objectType, busDeviceHandle, maxDepth,
741 		(ACPI_WALK_CALLBACK)descendingCallback,
742 		(ACPI_WALK_CALLBACK)ascendingCallback, context, returnValue);
743 }
744 
745 
746 status_t
747 prepare_sleep_state(uint8 state, void (*wakeFunc)(void), size_t size)
748 {
749 	ACPI_STATUS acpiStatus;
750 
751 	TRACE("prepare_sleep_state %d, %p, %ld\n", state, wakeFunc, size);
752 
753 	if (state != ACPI_POWER_STATE_OFF) {
754 		physical_entry wakeVector;
755 		status_t status;
756 
757 		// Note: The supplied code must already be locked into memory.
758 		status = get_memory_map((const void*)wakeFunc, size, &wakeVector, 1);
759 		if (status != B_OK)
760 			return status;
761 
762 #	if B_HAIKU_PHYSICAL_BITS > 32
763 		if (wakeVector.address >= 0x100000000LL) {
764 			ERROR("prepare_sleep_state(): ACPI 2.0c says use 32 bit "
765 				"vector, but we have a physical address >= 4 GB\n");
766 		}
767 #	endif
768 		acpiStatus = AcpiSetFirmwareWakingVector(wakeVector.address,
769 			wakeVector.address);
770 		if (acpiStatus != AE_OK)
771 			return B_ERROR;
772 	}
773 
774 	acpiStatus = AcpiEnterSleepStatePrep(state);
775 	if (acpiStatus != AE_OK)
776 		return B_ERROR;
777 
778 	return B_OK;
779 }
780 
781 
782 status_t
783 enter_sleep_state(uint8 state)
784 {
785 	ACPI_STATUS status;
786 
787 	TRACE("enter_sleep_state %d\n", state);
788 
789 	cpu_status cpu = disable_interrupts();
790 	status = AcpiEnterSleepState(state);
791 	restore_interrupts(cpu);
792 	panic("AcpiEnterSleepState should not return.");
793 	if (status != AE_OK)
794 		return B_ERROR;
795 
796 	/*status = AcpiLeaveSleepState(state);
797 	if (status != AE_OK)
798 		return B_ERROR;*/
799 
800 	return B_OK;
801 }
802 
803 
804 status_t
805 reboot(void)
806 {
807 	ACPI_STATUS status;
808 
809 	TRACE("reboot\n");
810 
811 	status = AcpiReset();
812 	if (status == AE_NOT_EXIST)
813 		return B_UNSUPPORTED;
814 
815 	if (status != AE_OK) {
816 		ERROR("Reset failed, status = %d\n", status);
817 		return B_ERROR;
818 	}
819 
820 	snooze(1000000);
821 	ERROR("Reset failed, timeout\n");
822 	return B_ERROR;
823 }
824 
825 
826 status_t
827 get_table(const char* signature, uint32 instance, void** tableHeader)
828 {
829 	return AcpiGetTable((char*)signature, instance,
830 		(ACPI_TABLE_HEADER**)tableHeader) == AE_OK ? B_OK : B_ERROR;
831 }
832 
833 
834 status_t
835 read_bit_register(uint32 regid, uint32 *val)
836 {
837 	return AcpiReadBitRegister(regid, (UINT32 *)val);
838 }
839 
840 
841 status_t
842 write_bit_register(uint32 regid, uint32 val)
843 {
844 	return AcpiWriteBitRegister(regid, val);
845 }
846 
847 
848 struct acpi_module_info gACPIModule = {
849 	{
850 		B_ACPI_MODULE_NAME,
851 		B_KEEP_LOADED,
852 		acpi_std_ops
853 	},
854 
855 	get_handle,
856 	get_name,
857 	acquire_global_lock,
858 	release_global_lock,
859 	install_notify_handler,
860 	remove_notify_handler,
861 	update_all_gpes,
862 	enable_gpe,
863 	disable_gpe,
864 	clear_gpe,
865 	set_gpe,
866 	finish_gpe,
867 	install_gpe_handler,
868 	remove_gpe_handler,
869 	install_address_space_handler,
870 	remove_address_space_handler,
871 	enable_fixed_event,
872 	disable_fixed_event,
873 	fixed_event_status,
874 	reset_fixed_event,
875 	install_fixed_event_handler,
876 	remove_fixed_event_handler,
877 	get_next_entry,
878 	get_next_object,
879 	walk_namespace,
880 	get_device,
881 	get_device_info,
882 	get_object_type,
883 	get_object,
884 	get_object_typed,
885 	ns_handle_to_pathname,
886 	evaluate_object,
887 	evaluate_method,
888 	get_irq_routing_table,
889 	get_current_resources,
890 	get_possible_resources,
891 	set_current_resources,
892 	walk_resources,
893 	prepare_sleep_state,
894 	enter_sleep_state,
895 	reboot,
896 	get_table,
897 	read_bit_register,
898 	write_bit_register
899 };
900