xref: /minix3/minix/drivers/power/acpi/acpi.c (revision 3f82ac6a4e188419336747098d0d6616cd2f3d3d)
1 #include <minix/driver.h>
2 #include <acpi.h>
3 #include <assert.h>
4 #include <minix/acpi.h>
5 
6 #include "pci.h"
7 
8 int acpi_enabled;
9 struct machine machine;
10 
11 /* don't know where ACPI tables are, we may need to access any memory */
init_mem_priv(void)12 static int init_mem_priv(void)
13 {
14 	struct minix_mem_range mr;
15 
16 	mr.mr_base = 0;
17 	mr.mr_limit = 0xffffffff;
18 
19 	return sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr);
20 }
21 
set_machine_mode(void)22 static void set_machine_mode(void)
23 {
24     ACPI_OBJECT arg1;
25     ACPI_OBJECT_LIST args;
26     ACPI_STATUS as;
27 
28     arg1.Type = ACPI_TYPE_INTEGER;
29     arg1.Integer.Value = machine.apic_enabled ? 1 : 0;
30     args.Count = 1;
31     args.Pointer = &arg1;
32 
33     as = AcpiEvaluateObject(ACPI_ROOT_OBJECT, "_PIC", &args, NULL);
34     /*
35      * We can silently ignore failure as it may not be implemented, ACPI should
36      * provide us with correct information anyway
37      */
38     if (ACPI_SUCCESS(as))
39 	    printf("ACPI: machine set to %s mode\n",
40 			    machine.apic_enabled ? "APIC" : "PIC");
41 }
42 
init_acpica(void)43 static ACPI_STATUS init_acpica(void)
44 {
45 	ACPI_STATUS status;
46 
47 	status = AcpiInitializeSubsystem();
48 	if (ACPI_FAILURE(status))
49 		return status;
50 
51 	status = AcpiInitializeTables(NULL, 16, FALSE);
52 	if (ACPI_FAILURE(status))
53 		return status;
54 
55 	status = AcpiLoadTables();
56 	if (ACPI_FAILURE(status))
57 		return status;
58 
59 	status = AcpiEnableSubsystem(0);
60 	if (ACPI_FAILURE(status))
61 		return status;
62 
63 	status = AcpiInitializeObjects(0);
64 	if (ACPI_FAILURE(status))
65 		return status;
66 
67 	set_machine_mode();
68 
69 	pci_scan_devices();
70 
71 	return AE_OK;
72 }
73 
init_acpi(void)74 void init_acpi(void)
75 {
76 	ACPI_STATUS acpi_err;
77 	/* test conditions for acpi */
78 	if (sys_getmachine(&machine)) {
79 		printf("ACPI: no machine\n");
80 		return;
81 	}
82 	if (machine.acpi_rsdp == 0) {
83 		printf("ACPI: no RSDP\n");
84 		return;
85 	}
86 	if (init_mem_priv()) {
87 		printf("ACPI: no mem access\n");
88 		return;
89 	}
90 
91 	if ((acpi_err = init_acpica()) == AE_OK) {
92 		acpi_enabled = 1;
93 		printf("ACPI: ACPI enabled\n");
94 	}
95 	else {
96 		acpi_enabled = 0;
97 		printf("ACPI: ACPI failed with err %d\n", acpi_err);
98 	}
99 }
100 
sef_cb_init_fresh(int type,sef_init_info_t * info)101 static int sef_cb_init_fresh(int type, sef_init_info_t *info)
102 {
103 	int r;
104 
105 	init_acpi();
106 
107 	/* Let SEF know about ACPI special cache word. */
108 	r = sef_llvm_add_special_mem_region((void*)0xCACACACA, 1,
109 	    "%MMAP_CACHE_WORD");
110 	if(r < 0) {
111 	    printf("acpi: sef_llvm_add_special_mem_region failed %d\n", r);
112 	}
113 
114 	/* XXX To-do: acpi requires custom state transfer handlers for
115 	 * unions acpi_operand_object and acpi_generic_state (and nested unions)
116 	 * for generic state transfer to work correctly.
117 	 */
118 
119 	return OK;
120 }
121 
sef_local_startup()122 static void sef_local_startup()
123 {
124   /* Register init callbacks. */
125   sef_setcb_init_fresh(sef_cb_init_fresh);
126   sef_setcb_init_lu(sef_cb_init_fresh);
127   sef_setcb_init_restart(sef_cb_init_fresh);
128 
129   /* Let SEF perform startup. */
130   sef_startup();
131 }
132 
main(void)133 int main(void)
134 {
135 	int err;
136 	message m;
137 	int ipc_status;
138 
139 	sef_local_startup();
140 
141 	for(;;) {
142 		err = driver_receive(ANY, &m, &ipc_status);
143 		if (err != OK) {
144 			printf("ACPI: driver_receive failed: %d\n", err);
145 			continue;
146 		}
147 
148 		switch (((struct acpi_request_hdr *)&m)->request) {
149 		case ACPI_REQ_GET_IRQ:
150 			do_get_irq(&m);
151 			break;
152 		case ACPI_REQ_MAP_BRIDGE:
153 			do_map_bridge(&m);
154 			break;
155 		default:
156 			printf("ACPI: ignoring unsupported request %d "
157 				"from %d\n",
158 				((struct acpi_request_hdr *)&m)->request,
159 				((struct acpi_request_hdr *)&m)->m_source);
160 		}
161 
162 		err = ipc_send(m.m_source, &m);
163 		if (err != OK) {
164 			printf("ACPI: ipc_send failed: %d\n", err);
165 		}
166 	}
167 }
168