xref: /minix3/minix/drivers/power/acpi/acpi.c (revision 3f82ac6a4e188419336747098d0d6616cd2f3d3d)
1433d6423SLionel Sambuc #include <minix/driver.h>
2433d6423SLionel Sambuc #include <acpi.h>
3433d6423SLionel Sambuc #include <assert.h>
4433d6423SLionel Sambuc #include <minix/acpi.h>
5433d6423SLionel Sambuc 
6433d6423SLionel Sambuc #include "pci.h"
7433d6423SLionel Sambuc 
8433d6423SLionel Sambuc int acpi_enabled;
9433d6423SLionel Sambuc struct machine machine;
10433d6423SLionel Sambuc 
11433d6423SLionel Sambuc /* don't know where ACPI tables are, we may need to access any memory */
init_mem_priv(void)12433d6423SLionel Sambuc static int init_mem_priv(void)
13433d6423SLionel Sambuc {
14433d6423SLionel Sambuc 	struct minix_mem_range mr;
15433d6423SLionel Sambuc 
16433d6423SLionel Sambuc 	mr.mr_base = 0;
17433d6423SLionel Sambuc 	mr.mr_limit = 0xffffffff;
18433d6423SLionel Sambuc 
19433d6423SLionel Sambuc 	return sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr);
20433d6423SLionel Sambuc }
21433d6423SLionel Sambuc 
set_machine_mode(void)22433d6423SLionel Sambuc static void set_machine_mode(void)
23433d6423SLionel Sambuc {
24433d6423SLionel Sambuc     ACPI_OBJECT arg1;
25433d6423SLionel Sambuc     ACPI_OBJECT_LIST args;
26433d6423SLionel Sambuc     ACPI_STATUS as;
27433d6423SLionel Sambuc 
28433d6423SLionel Sambuc     arg1.Type = ACPI_TYPE_INTEGER;
29433d6423SLionel Sambuc     arg1.Integer.Value = machine.apic_enabled ? 1 : 0;
30433d6423SLionel Sambuc     args.Count = 1;
31433d6423SLionel Sambuc     args.Pointer = &arg1;
32433d6423SLionel Sambuc 
33433d6423SLionel Sambuc     as = AcpiEvaluateObject(ACPI_ROOT_OBJECT, "_PIC", &args, NULL);
34433d6423SLionel Sambuc     /*
35433d6423SLionel Sambuc      * We can silently ignore failure as it may not be implemented, ACPI should
36433d6423SLionel Sambuc      * provide us with correct information anyway
37433d6423SLionel Sambuc      */
38433d6423SLionel Sambuc     if (ACPI_SUCCESS(as))
39433d6423SLionel Sambuc 	    printf("ACPI: machine set to %s mode\n",
40433d6423SLionel Sambuc 			    machine.apic_enabled ? "APIC" : "PIC");
41433d6423SLionel Sambuc }
42433d6423SLionel Sambuc 
init_acpica(void)43433d6423SLionel Sambuc static ACPI_STATUS init_acpica(void)
44433d6423SLionel Sambuc {
45433d6423SLionel Sambuc 	ACPI_STATUS status;
46433d6423SLionel Sambuc 
47433d6423SLionel Sambuc 	status = AcpiInitializeSubsystem();
48433d6423SLionel Sambuc 	if (ACPI_FAILURE(status))
49433d6423SLionel Sambuc 		return status;
50433d6423SLionel Sambuc 
51433d6423SLionel Sambuc 	status = AcpiInitializeTables(NULL, 16, FALSE);
52433d6423SLionel Sambuc 	if (ACPI_FAILURE(status))
53433d6423SLionel Sambuc 		return status;
54433d6423SLionel Sambuc 
55433d6423SLionel Sambuc 	status = AcpiLoadTables();
56433d6423SLionel Sambuc 	if (ACPI_FAILURE(status))
57433d6423SLionel Sambuc 		return status;
58433d6423SLionel Sambuc 
59433d6423SLionel Sambuc 	status = AcpiEnableSubsystem(0);
60433d6423SLionel Sambuc 	if (ACPI_FAILURE(status))
61433d6423SLionel Sambuc 		return status;
62433d6423SLionel Sambuc 
63433d6423SLionel Sambuc 	status = AcpiInitializeObjects(0);
64433d6423SLionel Sambuc 	if (ACPI_FAILURE(status))
65433d6423SLionel Sambuc 		return status;
66433d6423SLionel Sambuc 
67433d6423SLionel Sambuc 	set_machine_mode();
68433d6423SLionel Sambuc 
69433d6423SLionel Sambuc 	pci_scan_devices();
70433d6423SLionel Sambuc 
71433d6423SLionel Sambuc 	return AE_OK;
72433d6423SLionel Sambuc }
73433d6423SLionel Sambuc 
init_acpi(void)74433d6423SLionel Sambuc void init_acpi(void)
75433d6423SLionel Sambuc {
76433d6423SLionel Sambuc 	ACPI_STATUS acpi_err;
77433d6423SLionel Sambuc 	/* test conditions for acpi */
78433d6423SLionel Sambuc 	if (sys_getmachine(&machine)) {
79433d6423SLionel Sambuc 		printf("ACPI: no machine\n");
80433d6423SLionel Sambuc 		return;
81433d6423SLionel Sambuc 	}
82433d6423SLionel Sambuc 	if (machine.acpi_rsdp == 0) {
83433d6423SLionel Sambuc 		printf("ACPI: no RSDP\n");
84433d6423SLionel Sambuc 		return;
85433d6423SLionel Sambuc 	}
86433d6423SLionel Sambuc 	if (init_mem_priv()) {
87433d6423SLionel Sambuc 		printf("ACPI: no mem access\n");
88433d6423SLionel Sambuc 		return;
89433d6423SLionel Sambuc 	}
90433d6423SLionel Sambuc 
91433d6423SLionel Sambuc 	if ((acpi_err = init_acpica()) == AE_OK) {
92433d6423SLionel Sambuc 		acpi_enabled = 1;
93433d6423SLionel Sambuc 		printf("ACPI: ACPI enabled\n");
94433d6423SLionel Sambuc 	}
95433d6423SLionel Sambuc 	else {
96433d6423SLionel Sambuc 		acpi_enabled = 0;
97433d6423SLionel Sambuc 		printf("ACPI: ACPI failed with err %d\n", acpi_err);
98433d6423SLionel Sambuc 	}
99433d6423SLionel Sambuc }
100433d6423SLionel Sambuc 
sef_cb_init_fresh(int type,sef_init_info_t * info)101433d6423SLionel Sambuc static int sef_cb_init_fresh(int type, sef_init_info_t *info)
102433d6423SLionel Sambuc {
103*50b7f13fSCristiano Giuffrida 	int r;
104*50b7f13fSCristiano Giuffrida 
105433d6423SLionel Sambuc 	init_acpi();
106433d6423SLionel Sambuc 
107*50b7f13fSCristiano Giuffrida 	/* Let SEF know about ACPI special cache word. */
108*50b7f13fSCristiano Giuffrida 	r = sef_llvm_add_special_mem_region((void*)0xCACACACA, 1,
109*50b7f13fSCristiano Giuffrida 	    "%MMAP_CACHE_WORD");
110*50b7f13fSCristiano Giuffrida 	if(r < 0) {
111*50b7f13fSCristiano Giuffrida 	    printf("acpi: sef_llvm_add_special_mem_region failed %d\n", r);
112*50b7f13fSCristiano Giuffrida 	}
113*50b7f13fSCristiano Giuffrida 
114*50b7f13fSCristiano Giuffrida 	/* XXX To-do: acpi requires custom state transfer handlers for
115*50b7f13fSCristiano Giuffrida 	 * unions acpi_operand_object and acpi_generic_state (and nested unions)
116*50b7f13fSCristiano Giuffrida 	 * for generic state transfer to work correctly.
117*50b7f13fSCristiano Giuffrida 	 */
118*50b7f13fSCristiano Giuffrida 
119433d6423SLionel Sambuc 	return OK;
120433d6423SLionel Sambuc }
121433d6423SLionel Sambuc 
sef_local_startup()122433d6423SLionel Sambuc static void sef_local_startup()
123433d6423SLionel Sambuc {
124433d6423SLionel Sambuc   /* Register init callbacks. */
125433d6423SLionel Sambuc   sef_setcb_init_fresh(sef_cb_init_fresh);
126433d6423SLionel Sambuc   sef_setcb_init_lu(sef_cb_init_fresh);
127433d6423SLionel Sambuc   sef_setcb_init_restart(sef_cb_init_fresh);
128433d6423SLionel Sambuc 
129433d6423SLionel Sambuc   /* Let SEF perform startup. */
130433d6423SLionel Sambuc   sef_startup();
131433d6423SLionel Sambuc }
132433d6423SLionel Sambuc 
main(void)133433d6423SLionel Sambuc int main(void)
134433d6423SLionel Sambuc {
135433d6423SLionel Sambuc 	int err;
136433d6423SLionel Sambuc 	message m;
137433d6423SLionel Sambuc 	int ipc_status;
138433d6423SLionel Sambuc 
139433d6423SLionel Sambuc 	sef_local_startup();
140433d6423SLionel Sambuc 
141433d6423SLionel Sambuc 	for(;;) {
142433d6423SLionel Sambuc 		err = driver_receive(ANY, &m, &ipc_status);
143433d6423SLionel Sambuc 		if (err != OK) {
144433d6423SLionel Sambuc 			printf("ACPI: driver_receive failed: %d\n", err);
145433d6423SLionel Sambuc 			continue;
146433d6423SLionel Sambuc 		}
147433d6423SLionel Sambuc 
148433d6423SLionel Sambuc 		switch (((struct acpi_request_hdr *)&m)->request) {
149433d6423SLionel Sambuc 		case ACPI_REQ_GET_IRQ:
150433d6423SLionel Sambuc 			do_get_irq(&m);
151433d6423SLionel Sambuc 			break;
152433d6423SLionel Sambuc 		case ACPI_REQ_MAP_BRIDGE:
153433d6423SLionel Sambuc 			do_map_bridge(&m);
154433d6423SLionel Sambuc 			break;
155433d6423SLionel Sambuc 		default:
156433d6423SLionel Sambuc 			printf("ACPI: ignoring unsupported request %d "
157433d6423SLionel Sambuc 				"from %d\n",
158433d6423SLionel Sambuc 				((struct acpi_request_hdr *)&m)->request,
159433d6423SLionel Sambuc 				((struct acpi_request_hdr *)&m)->m_source);
160433d6423SLionel Sambuc 		}
161433d6423SLionel Sambuc 
162433d6423SLionel Sambuc 		err = ipc_send(m.m_source, &m);
163433d6423SLionel Sambuc 		if (err != OK) {
164433d6423SLionel Sambuc 			printf("ACPI: ipc_send failed: %d\n", err);
165433d6423SLionel Sambuc 		}
166433d6423SLionel Sambuc 	}
167433d6423SLionel Sambuc }
168