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