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