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