c378a499796bf8bb8b5e61b8c262a029139b7eef
[monolithium.git] / drivers / acpica / src / osmlxf.c
1 /*
2  * osmlxf.c (Monolithium ACPICA OSL)
3  *
4  * Copyright (C) 2016 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as
8  * published by the Free Software Foundation, either version 3 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <common.h>
21 #include <log.h>
22 #include <heap.h>
23 #include <memory.h>
24 #include <thread.h>
25 #include <cpu.h>
26 #include <timer.h>
27 #include <interrupt.h>
28 #include <acpi.h>
29 #include <stdio.h>
30 #include <power.h>
31 #include <semaphore.h>
32
33 const char driver_name[] = "acpica";
34
35 static ACPI_OSD_HANDLER acpica_int_handlers[256] = { NULL };
36 static void *acpica_int_contexts[256] = { NULL };
37
38 static void acpica_osl_handler(registers_t *regs, byte_t int_num)
39 {
40     acpica_int_handlers[int_num](acpica_int_contexts[int_num]);
41 }
42
43 ACPI_STATUS AcpiOsInitialize(void)
44 {
45     return AE_OK;
46 }
47
48 ACPI_STATUS AcpiOsTerminate(void)
49 {
50     return AE_OK;
51 }
52
53 ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer(void)
54 {
55     ACPI_PHYSICAL_ADDRESS Address;
56     AcpiFindRootPointer(&Address);
57     return Address;
58 }
59
60 ACPI_STATUS AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *PredefinedObject, ACPI_STRING *NewValue)
61 {
62     *NewValue = NULL;
63     return AE_OK;
64 }
65
66 ACPI_STATUS AcpiOsTableOverride(ACPI_TABLE_HEADER *ExistingTable, ACPI_TABLE_HEADER **NewTable)
67 {
68     *NewTable = NULL;
69     return AE_OK;
70 }
71
72 ACPI_STATUS AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *ExistingTable, ACPI_PHYSICAL_ADDRESS *NewAddress, UINT32 *NewTableLength)
73 {
74     *NewAddress = 0;
75     return AE_OK;
76 }
77
78 ACPI_STATUS AcpiOsSignal(UINT32 Function, void *Info)
79 {
80     return AE_SUPPORT; // TODO
81 }
82
83 void AcpiOsVprintf(const char *Format, va_list Args)
84 {
85     char buffer[MAX_LOG_MESSAGE_SIZE];
86     vsnprintf(buffer, MAX_LOG_MESSAGE_SIZE, Format, Args);
87     log_write(LOG_NORMAL, buffer);
88 }
89
90 void AcpiOsPrintf(const char *Format, ...)
91 {
92     va_list args;
93     va_start(args, Format);
94     AcpiOsVprintf(Format, args);
95     va_end(args);
96 }
97
98 ACPI_STATUS AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
99 {
100     switch (Width)
101     {
102     case 8:
103         *Value = cpu_read_port_byte(Address);
104         break;
105     case 16:
106         *Value = cpu_read_port_word(Address);
107         break;
108     case 32:
109         *Value = cpu_read_port_dword(Address);
110         break;
111     default:
112         return AE_SUPPORT;
113     }
114
115     return AE_OK;
116 }
117
118 ACPI_STATUS AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
119 {
120     switch (Width)
121     {
122     case 8:
123         cpu_write_port_byte(Address, Value);
124         break;
125     case 16:
126         cpu_write_port_word(Address, Value);
127         break;
128     case 32:
129         cpu_write_port_dword(Address, Value);
130         break;
131     default:
132         return AE_SUPPORT;
133     }
134
135     return AE_OK;
136 }
137
138 void *AcpiOsAllocate(ACPI_SIZE Size)
139 {
140     return malloc(Size);
141 }
142
143 void AcpiOsFree(void *Memory)
144 {
145     free(Memory);
146 }
147
148 ACPI_STATUS AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value, UINT32 Width)
149 {
150     *Value = 0;
151     dword_t ret = read_physical((void*)((uintptr_t)Address), Value, Width / 8);
152
153     if (ret == ERR_SUCCESS) return AE_OK;
154     if (ret == ERR_NOMEMORY) return AE_NO_MEMORY;
155     return AE_ERROR;
156 }
157
158 ACPI_STATUS AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width)
159 {
160     dword_t ret = write_physical((void*)((uintptr_t)Address), &Value, Width / 8);
161
162     if (ret == ERR_SUCCESS) return AE_OK;
163     if (ret == ERR_NOMEMORY) return AE_NO_MEMORY;
164     return AE_ERROR;
165 }
166
167 void *AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS Address, ACPI_SIZE Length)
168 {
169     void *virtual = NULL;
170
171     if (map_memory((void*)PAGE_ALIGN((uintptr_t)Address),
172                    &virtual,
173                    PAGE_ALIGN_UP(PAGE_OFFSET((uintptr_t)Address) + Length),
174                    MEMORY_BLOCK_ACCESSIBLE | MEMORY_BLOCK_WRITABLE) == ERR_SUCCESS)
175     {
176         return (void*)((uintptr_t)virtual + PAGE_OFFSET((uintptr_t)Address));
177     }
178     else
179     {
180         return NULL;
181     }
182 }
183
184 void AcpiOsUnmapMemory(void *Address, ACPI_SIZE Length)
185 {
186     UNUSED_PARAMETER(Length);
187     unmap_memory(Address);
188 }
189
190 ACPI_STATUS AcpiOsCreateLock(ACPI_SPINLOCK *OutHandle)
191 {
192     *OutHandle = malloc(sizeof(critical_t));
193     if (*OutHandle == NULL) return AE_NO_MEMORY;
194     return AE_OK;
195 }
196
197 void AcpiOsDeleteLock(ACPI_SPINLOCK Handle)
198 {
199     free(Handle);
200 }
201
202 ACPI_CPU_FLAGS AcpiOsAcquireLock(ACPI_SPINLOCK Handle)
203 {
204     enter_critical(Handle);
205     return *(critical_t*)Handle;
206 }
207
208 void AcpiOsReleaseLock(ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags)
209 {
210     UNUSED_PARAMETER(Flags);
211     leave_critical(Handle);
212 }
213
214 ACPI_STATUS AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits, ACPI_SEMAPHORE *OutHandle)
215 {
216     semaphore_t *semaphore = malloc(sizeof(semaphore_t));
217     if (semaphore == NULL) return AE_NO_MEMORY;
218
219     init_semaphore(semaphore, InitialUnits, MaxUnits);
220     *OutHandle = (ACPI_SEMAPHORE)semaphore;
221     return AE_OK;
222 }
223
224 ACPI_STATUS AcpiOsDeleteSemaphore(ACPI_SEMAPHORE Handle)
225 {
226     free(Handle);
227     return AE_OK;
228 }
229
230 ACPI_STATUS AcpiOsWaitSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units, UINT16 Timeout)
231 {
232     dword_t ret = wait_semaphore((semaphore_t*)Handle, Units, (int32_t)((int16_t)Timeout));
233
234     if (ret == ERR_SUCCESS) return AE_OK;
235     else if (ret == ERR_TIMEOUT) return AE_TIME;
236     else return AE_ERROR;
237 }
238
239 ACPI_STATUS AcpiOsSignalSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units)
240 {
241     release_semaphore((semaphore_t*)Handle, Units);
242     return AE_OK;
243 }
244
245 UINT64 AcpiOsGetTimer(void)
246 {
247     return syscall_get_nanoseconds() / 100ULL;
248 }
249
250 void AcpiOsSleep(UINT64 Milliseconds)
251 {
252     syscall_sleep(Milliseconds);
253 }
254
255 void AcpiOsStall(UINT32 Microseconds)
256 {
257     qword_t end_time = syscall_get_nanoseconds() + (qword_t)Microseconds * 1000ULL;
258     while (syscall_get_nanoseconds() < end_time) continue;
259 }
260
261 ACPI_THREAD_ID AcpiOsGetThreadId(void)
262 {
263     return get_current_thread()->tid + 1;
264 }
265
266 ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler, void *Context)
267 {
268     if (InterruptLevel >= 256) return AE_BAD_PARAMETER;
269
270     acpica_int_handlers[InterruptLevel] = Handler;
271     acpica_int_contexts[InterruptLevel] = Context;
272     return AE_OK;
273 }
274
275 ACPI_STATUS AcpiOsRemoveInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler)
276 {
277     acpica_int_handlers[InterruptLevel] = NULL;
278     acpica_int_contexts[InterruptLevel] = NULL;
279     return AE_OK;
280 }
281
282 ACPI_STATUS AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function, void *Context)
283 {
284     thread_t *thread;
285     dword_t ret = create_system_thread((thread_procedure_t)Function, 0, THREAD_PRIORITY_MID, 0, Context, &thread);
286
287     if (ret == ERR_SUCCESS)
288     {
289         dereference(&thread->header);
290         return AE_OK;
291     }
292     else if (ret == ERR_INVALID)
293     {
294         return AE_BAD_PARAMETER;
295     }
296     else
297     {
298         return AE_ERROR;
299     }
300 }
301
302 void AcpiOsWaitEventsComplete(void)
303 {
304     // TODO
305 }
306
307 ACPI_STATUS AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value, UINT32 Width)
308 {
309     return AE_SUPPORT; // TODO
310 }
311
312 ACPI_STATUS AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 Value, UINT32 Width)
313 {
314      return AE_SUPPORT; // TODO
315 }
316
317 dword_t acpica_set_state(power_state_t state)
318 {
319     switch (state)
320     {
321     case POWER_STATE_STANDBY:
322     case POWER_STATE_SUSPEND:
323         /* Not implemented */
324         return ERR_NOSYSCALL;
325
326     case POWER_STATE_OFF:
327         AcpiEnterSleepStatePrep(ACPI_STATE_S5);
328         cpu_disable_interrupts();
329         AcpiEnterSleepState(ACPI_STATE_S5);
330         break;
331
332     default:
333         return ERR_INVALID;
334     }
335
336     return ERR_SUCCESS;
337 }
338
339 dword_t driver_load(const char *parameters)
340 {
341     static power_callbacks_t callbacks = {
342         .set_state = acpica_set_state,
343     };
344
345     dword_t ret = register_power_callbacks(&callbacks);
346     if (ret != ERR_SUCCESS) return ret;
347
348     if (ACPI_FAILURE(AcpiInitializeSubsystem())
349         || ACPI_FAILURE(AcpiInitializeTables(NULL, 16, FALSE))
350         || ACPI_FAILURE(AcpiLoadTables())
351         || ACPI_FAILURE(AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION)))
352     {
353         register_power_callbacks(NULL);
354         return ERR_HARDWARE;
355     }
356
357     return ERR_SUCCESS;
358 }