acpica.library: Add EFI support, interrupt support, enable debugging
[AROS.git] / arch / all-pc / acpica / generate / aros / acpios_aros.c
blob3f661a4308706fd44a5501933edfb8b4faba481c
1 /*
2 * Copyright (C) 2012, The AROS Development Team
3 * All right reserved.
4 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
6 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
7 */
8 #define DEBUG 1
9 #include <aros/debug.h>
11 #include <hardware/efi/config.h>
13 #include <proto/exec.h>
14 #include <proto/timer.h>
15 #include <proto/efi.h>
16 #include <proto/kernel.h>
18 #include <asm/io.h>
20 #include <devices/timer.h>
22 #include "acpi.h"
23 #include "accommon.h"
24 #include "amlcode.h"
25 #include "acparser.h"
26 #include "acdebug.h"
27 #include "acmacros.h"
29 #define _COMPONENT ACPI_OS_SERVICES
30 ACPI_MODULE_NAME ("osarosxf")
32 struct ACPICABase {
33 struct Library ab_Lib;
34 struct MsgPort *ab_TimeMsgPort;
35 struct timerequest *ab_TimeRequest;
36 struct Library *ab_TimerBase;
38 ACPI_MCFG_ALLOCATION *ab_PCI;
39 int ab_PCIs;
41 ACPI_PHYSICAL_ADDRESS ab_RootPointer;
44 #if 1 /* Use a global. Icky */
45 struct ACPICABase *Global_ACPICABase;
47 #define NEED_ACPICABASE struct ACPICABase *ACPICABase = Global_ACPICABase;
48 #define THIS_ACPICABASE(base) Global_ACPICABase = base
49 #endif
51 ACPI_STATUS AcpiOsInitialize (void)
53 NEED_ACPICABASE
55 if ((ACPICABase->ab_TimeMsgPort = CreateMsgPort())) {
56 if ((ACPICABase->ab_TimeRequest = CreateIORequest(ACPICABase->ab_TimeMsgPort, sizeof(*ACPICABase->ab_TimeRequest)))) {
57 ACPICABase->ab_TimerBase = (struct Library *)ACPICABase->ab_TimeRequest->tr_node.io_Device;
58 return AE_OK;
60 DeleteMsgPort(ACPICABase->ab_TimeMsgPort);
63 return AE_NO_MEMORY;
66 ACPI_STATUS AcpiOsTerminate (void)
68 NEED_ACPICABASE
70 DeleteIORequest(ACPICABase->ab_TimeRequest);
71 DeleteMsgPort(ACPICABase->ab_TimeMsgPort);
73 return AE_OK;
76 ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer(void)
78 NEED_ACPICABASE
80 if (ACPICABase->ab_RootPointer == 0) {
81 struct Library *EFIBase = OpenResource("efi.resource");
82 if (EFIBase) {
83 const uuid_t acpi_20_guid = ACPI_20_TABLE_GUID;
84 const uuid_t acpi_10_guid = ACPI_TABLE_GUID;
85 ACPICABase->ab_RootPointer = (ACPI_PHYSICAL_ADDRESS)EFI_FindConfigTable(&acpi_20_guid);
87 /* No ACPI 2.0 table? */
88 if (ACPICABase->ab_RootPointer == 0) {
89 ACPICABase->ab_RootPointer = (ACPI_PHYSICAL_ADDRESS)EFI_FindConfigTable(&acpi_10_guid);
94 /* Nope, no EFI available... Scan the ROM area
96 if (ACPICABase->ab_RootPointer == 0) {
97 AcpiFindRootPointer(&ACPICABase->ab_RootPointer);
100 return ACPICABase->ab_RootPointer;
103 ACPI_STATUS AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *PredefinedObject, ACPI_STRING *NewValue)
105 *NewValue = NULL;
106 return AE_OK;
109 ACPI_STATUS AcpiOsTableOverride(ACPI_TABLE_HEADER *ExistingTable, ACPI_TABLE_HEADER **NewTable)
111 *NewTable = NULL;
112 return AE_OK;
115 ACPI_STATUS AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *ExistingTable, ACPI_PHYSICAL_ADDRESS *NewAddress, UINT32 *NewTableLength)
117 *NewAddress = 0;
118 return AE_OK;
121 void *AcpiOsMapMemory (ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length)
123 return (void *)PhysicalAddress;
126 void AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Length)
128 return;
131 ACPI_STATUS AcpiOsGetPhysicalAddress(void *LogicalAddress, ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
133 *PhysicalAddress = (IPTR)LogicalAddress;
134 return AE_OK;
137 void *AcpiOsAllocate(ACPI_SIZE Size)
139 return AllocVec(Size, MEMF_PUBLIC);
142 void AcpiOsFree(void *Memory)
144 FreeVec(Memory);
147 BOOLEAN AcpiOsReadable(void *Memory, ACPI_SIZE Length)
149 return TRUE;
152 BOOLEAN AcpiOsWritable(void *Memory, ACPI_SIZE Length)
154 /* First 4K page is not writable on any AROS architecture */
155 return ((IPTR)Memory < 4096) ? FALSE : TRUE;
158 ACPI_THREAD_ID AcpiOsGetThreadId(void)
160 ACPI_THREAD_ID tid;
162 tid = (ACPI_THREAD_ID)(ACPI_PHYSICAL_ADDRESS)FindTask(NULL);
164 /* If we are running during kernel bring-up, return
165 * TID 1
167 if (tid == 0)
168 tid = 1;
170 return tid;
173 ACPI_STATUS AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function, void *Context)
175 /* TODO: Create a thread */
176 bug("FIXME: %s\n", __func__);
177 return AE_NOT_IMPLEMENTED;
180 void AcpiOsSleep(UINT64 Milliseconds)
182 NEED_ACPICABASE
184 ACPICABase->ab_TimeRequest->tr_node.io_Command = TR_ADDREQUEST;
185 ACPICABase->ab_TimeRequest->tr_time.tv_secs = Milliseconds / 1000;
186 ACPICABase->ab_TimeRequest->tr_time.tv_micro = (Milliseconds % 1000) * 1000;
187 DoIO((struct IORequest *)ACPICABase->ab_TimeRequest);
190 void AcpiOsStall(UINT32 Microseconds)
192 NEED_ACPICABASE
194 ACPICABase->ab_TimeRequest->tr_node.io_Command = TR_ADDREQUEST;
195 ACPICABase->ab_TimeRequest->tr_time.tv_secs = Microseconds / 1000000;
196 ACPICABase->ab_TimeRequest->tr_time.tv_micro = (Microseconds % 1000000);
197 DoIO((struct IORequest *)ACPICABase->ab_TimeRequest);
200 void AcpiOsWaitEventsComplete(void)
202 bug("FIXME: %s\n", __func__);
205 ACPI_STATUS AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits, ACPI_SEMAPHORE *OutHandle)
207 struct SignalSemaphore *Handle;
209 Handle = ACPI_ALLOCATE(sizeof(*Handle));
210 if (Handle) {
211 InitSemaphore(Handle);
212 *OutHandle = Handle;
213 return AE_OK;
215 return AE_NO_MEMORY;
218 ACPI_STATUS AcpiOsDeleteSemaphore(ACPI_SEMAPHORE Handle)
220 ACPI_FREE(Handle);
221 return AE_OK;
224 ACPI_STATUS AcpiOsWaitSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units, UINT16 Timeout)
226 if (Timeout != 0xffff)
227 bug("FIXME: %s, Timeout=0x%04x\n", __func__, Timeout);
229 if (Timeout == 0) {
230 if (AttemptSemaphore(Handle)) {
231 return AE_OK;
232 } else {
233 return AE_TIME;
237 /* Forever.. */
238 ObtainSemaphore(Handle);
240 return AE_OK;
243 ACPI_STATUS AcpiOsSignalSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units)
245 ReleaseSemaphore(Handle);
246 return AE_OK;
249 ACPI_STATUS AcpiOsCreateLock(ACPI_SPINLOCK *OutHandle)
251 return AcpiOsCreateSemaphore (1, 1, OutHandle);
254 void AcpiOsDeleteLock(ACPI_SPINLOCK Handle)
256 AcpiOsDeleteSemaphore (Handle);
259 ACPI_CPU_FLAGS AcpiOsAcquireLock(ACPI_SPINLOCK Handle)
261 AcpiOsWaitSemaphore (Handle, 1, 0xFFFF);
262 return AE_OK;
265 void AcpiOsReleaseLock(ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags)
267 AcpiOsSignalSemaphore (Handle, 1);
270 struct AcpiOsInt {
271 struct Interrupt ai_Interrupt;
272 ACPI_OSD_HANDLER ai_Handler;
273 void *ai_Context;
276 static AROS_INTH1(AcpiOsIntServer, struct AcpiOsInt *, ai)
278 AROS_INTFUNC_INIT
280 UINT32 ret;
282 ret = ai->ai_Handler(ai->ai_Context);
284 return (ret == ACPI_INTERRUPT_HANDLED) ? TRUE : FALSE;
286 AROS_INTFUNC_EXIT
289 ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler, void *Context)
291 struct AcpiOsInt *ai;
293 if ((ai = ACPI_ALLOCATE(sizeof(*ai)))) {
294 ai->ai_Interrupt.is_Node.ln_Name = "ACPI";
295 ai->ai_Interrupt.is_Code = (APTR)AcpiOsIntServer;
296 ai->ai_Interrupt.is_Data = (APTR)ai;
297 ai->ai_Handler = Handler;
298 ai->ai_Context = Context;
299 AddIntServer(INTB_KERNEL + InterruptLevel, &ai->ai_Interrupt);
300 return AE_OK;
303 return AE_NO_MEMORY;
306 ACPI_STATUS AcpiOsRemoveInterruptHandler(UINT32 InterruptNumber, ACPI_OSD_HANDLER Handler)
308 bug("FIXME: %s (InterruptLevel=%d)\n", __func__, InterruptNumber);
309 return AE_NOT_IMPLEMENTED;
312 ACPI_STATUS AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value, UINT32 Width)
314 switch (Width) {
315 case 8: *Value = *(UINT8 *)Address; break;
316 case 16: *Value = *(UINT16 *)Address; break;
317 case 32: *Value = *(UINT32 *)Address; break;
318 case 64: *Value = *(UINT64 *)Address; break;
319 default: *Value = ~0; break;
322 return AE_OK;
325 ACPI_STATUS AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width)
327 switch (Width) {
328 case 8: *(UINT8 *)Address = (UINT8)Value; break;
329 case 16: *(UINT16 *)Address = (UINT16)Value; break;
330 case 32: *(UINT32 *)Address = (UINT32)Value; break;
331 case 64: *(UINT64 *)Address = (UINT64)Value; break;
332 default: break;
335 return AE_OK;
338 ACPI_STATUS AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
340 switch (Width) {
341 case 8: *Value = inb(Address); break;
342 case 16: *Value = inw(Address); break;
343 case 32: *Value = inl(Address); break;
344 default: *Value = ~0; break;
346 return AE_OK;
349 ACPI_STATUS AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
351 switch (Width) {
352 case 8: outb(Value,Address); break;
353 case 16: outw(Value,Address); break;
354 case 32: outl(Value,Address); break;
355 default: break;
357 return AE_OK;
360 static UINT8 *find_pci(struct ACPICABase *ACPICABase, ACPI_PCI_ID *PciId)
362 int i;
364 for (i = 0; i < ACPICABase->ab_PCIs; i++) {
365 ACPI_MCFG_ALLOCATION *ma = &ACPICABase->ab_PCI[i];
366 if (PciId->Segment != ma->PciSegment)
367 continue;
368 if (PciId->Bus < ma->StartBusNumber ||
369 PciId->Bus > ma->EndBusNumber)
370 continue;
372 return (UINT8 *)(ACPI_PHYSICAL_ADDRESS)ma->Address;
375 return NULL;
378 ACPI_STATUS AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value, UINT32 Width)
380 UINT8 *ecam;
382 NEED_ACPICABASE
384 if ((ecam = find_pci(ACPICABase, PciId))) {
385 UINT32 offset = (PciId->Bus << 20) | (PciId->Device << 15) | (PciId->Function << 12) | Register;
386 switch (Width) {
387 case 8: *Value = *(volatile UINT8 *)(ecam + offset); break;
388 case 16: *Value = *(volatile UINT16 *)(ecam + offset); break;
389 case 32: *Value = *(volatile UINT32 *)(ecam + offset); break;
390 case 64: *Value = *(volatile UINT64 *)(ecam + offset); break;
391 default: *Value = 0; break;
394 return AE_OK;
397 return AE_NOT_FOUND;
400 ACPI_STATUS AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 Value, UINT32 Width)
402 UINT8 *ecam;
404 NEED_ACPICABASE
406 if ((ecam = find_pci(ACPICABase, PciId))) {
407 UINT32 offset = (PciId->Bus << 20) | (PciId->Device << 15) | (PciId->Function << 12) | Register;
408 switch (Width) {
409 case 8: *(volatile UINT8 *)(ecam + offset) = Value & 0xff; break;
410 case 16: *(volatile UINT16 *)(ecam + offset) = Value & 0xffff; break;
411 case 32: *(volatile UINT32 *)(ecam + offset) = Value & 0xffffffff; break;
412 case 64: *(volatile UINT64 *)(ecam + offset) = Value; break;
413 default: break;
416 return AE_OK;
419 return AE_NOT_FOUND;
422 void AcpiOsPrintf(const char *Fmt, ...)
424 va_list Args;
426 va_start (Args, Fmt);
427 AcpiOsVprintf (Fmt, Args);
428 va_end (Args);
431 void AcpiOsVprintf(const char *Format, va_list Args)
433 vkprintf(Format, Args);
436 /* Return current time in 100ns units
438 UINT64 AcpiOsGetTimer(void)
440 struct Library *TimerBase;
441 struct timeval tv;
443 NEED_ACPICABASE
445 TimerBase = ACPICABase->ab_TimerBase;
447 GetSysTime(&tv);
449 return (tv.tv_secs*1000000ULL + tv.tv_micro)*10;
452 ACPI_STATUS AcpiOsSignal(UINT32 Function, void *Info)
454 bug("FIXME: %s\n", __func__);
455 return AE_NOT_IMPLEMENTED;
458 ACPI_STATUS AcpiOsGetLine(char *Buffer, UINT32 BufferLength, UINT32 *BytesRead)
460 bug("FIXME: %s\n", __func__);
461 return AE_NOT_IMPLEMENTED;
465 * AROS Custom Code
467 LONG AcpiScanTables(char *Signature, const struct Hook *Hook, APTR UserData)
469 int i;
470 LONG count;
472 for (count = 0, i = 1; ; i++) {
473 ACPI_STATUS err;
474 ACPI_TABLE_HEADER *hdr;
475 IPTR ok;
477 err = AcpiGetTable(Signature, i, &hdr);
478 if (err != AE_OK)
479 break;
481 if (Hook) {
482 ok = CALLHOOKPKT((struct Hook *)Hook, hdr, UserData);
483 } else {
484 ok = TRUE;
486 if (ok)
487 count++;
490 return count;
493 #define ACPI_MAX_INIT_TABLES 64
495 static int ACPICA_InitTask(struct ACPICABase *ACPICABase)
497 ACPI_STATUS err;
498 const UINT8 initlevel = ACPI_FULL_INITIALIZATION;
500 err = AcpiInitializeSubsystem();
501 if (ACPI_FAILURE(err)) {
502 D(bug("%s: AcpiInitializeSubsystem() = %d\n", __func__, err));
503 return FALSE;
506 err = AcpiLoadTables();
507 if (ACPI_FAILURE(err)) {
508 D(bug("%s: AcpiLoadTables() = %d\n", __func__, err));
509 return FALSE;
512 err = AcpiEnableSubsystem(initlevel);
513 if (ACPI_FAILURE(err)) {
514 D(bug("%s: AcpiEnableSubsystem(0x%02x) = %d\n", __func__, initlevel, err));
515 return FALSE;
518 err = AcpiInitializeObjects(initlevel);
519 if (ACPI_FAILURE(err)) {
520 D(bug("%s: AcpiInitializeObjects(0x%02x) = %d\n", __func__, initlevel, err));
521 return FALSE;
524 D(bug("[ACPI] Full initialization complete\n"));
526 return TRUE;
529 int ACPICA_init(struct ACPICABase *ACPICABase)
531 ACPI_TABLE_MCFG *mcfg;
532 ACPI_STATUS err;
533 struct Library *KernelBase;
535 if ((KernelBase = OpenResource("kernel.resource"))) {
536 struct TagItem *cmdline = LibFindTagItem(KRN_CmdLine, KrnGetBootInfo());
538 if (cmdline && strcasestr((char *)cmdline->ti_Data, "noacpi")) {
539 D(bug("[ACPI] Disabled from command line\n"));
540 return FALSE;
544 THIS_ACPICABASE(ACPICABase);
546 AcpiDbgLevel = ~0;
548 ACPICABase->ab_RootPointer = 0;
550 err = AcpiInitializeTables(NULL, ACPI_MAX_INIT_TABLES, TRUE);
551 if (ACPI_FAILURE(err)) {
552 D(bug("%s: AcpiInitializeTables() = %d\n", __func__, err));
553 return FALSE;
556 if (AcpiGetTable("MCFG", 1, (ACPI_TABLE_HEADER **)&mcfg) == AE_OK) {
557 ACPICABase->ab_PCIs = (mcfg->Header.Length - sizeof(*mcfg)) / sizeof(ACPI_MCFG_ALLOCATION);
558 ACPICABase->ab_PCI = (ACPI_MCFG_ALLOCATION *)&mcfg[1];
559 } else {
560 ACPICABase->ab_PCIs = 0;
563 /* Everything else is in the late initialization thread,
564 * which will start at the highest priority once mulitasking begins
566 if (NewCreateTask(TASKTAG_PC, ACPICA_InitTask, TASKTAG_NAME, "ACPICA_InitTask", TASKTAG_PRI, 127, TASKTAG_ARG1, ACPICABase, TAG_DONE) == NULL) {
567 AcpiTerminate();
568 return FALSE;
571 return TRUE;
573 ADD2INITLIB(ACPICA_init,0)
575 int ACPICA_expunge(struct ACPICABase *ACPICABase)
577 AcpiTerminate();
579 return TRUE;
581 ADD2EXPUNGELIB(ACPICA_expunge, 0)