2 * Copyright (C) 2012, The AROS Development Team
4 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
6 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.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>
20 #include <devices/timer.h>
29 #define _COMPONENT ACPI_OS_SERVICES
30 ACPI_MODULE_NAME ("osarosxf")
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
;
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
51 ACPI_STATUS
AcpiOsInitialize (void)
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
;
60 DeleteMsgPort(ACPICABase
->ab_TimeMsgPort
);
66 ACPI_STATUS
AcpiOsTerminate (void)
70 DeleteIORequest(ACPICABase
->ab_TimeRequest
);
71 DeleteMsgPort(ACPICABase
->ab_TimeMsgPort
);
76 ACPI_PHYSICAL_ADDRESS
AcpiOsGetRootPointer(void)
80 if (ACPICABase
->ab_RootPointer
== 0) {
81 struct Library
*EFIBase
= OpenResource("efi.resource");
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
)
109 ACPI_STATUS
AcpiOsTableOverride(ACPI_TABLE_HEADER
*ExistingTable
, ACPI_TABLE_HEADER
**NewTable
)
115 ACPI_STATUS
AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER
*ExistingTable
, ACPI_PHYSICAL_ADDRESS
*NewAddress
, UINT32
*NewTableLength
)
121 void *AcpiOsMapMemory (ACPI_PHYSICAL_ADDRESS PhysicalAddress
, ACPI_SIZE Length
)
123 return (void *)PhysicalAddress
;
126 void AcpiOsUnmapMemory(void *LogicalAddress
, ACPI_SIZE Length
)
131 ACPI_STATUS
AcpiOsGetPhysicalAddress(void *LogicalAddress
, ACPI_PHYSICAL_ADDRESS
*PhysicalAddress
)
133 *PhysicalAddress
= (IPTR
)LogicalAddress
;
137 void *AcpiOsAllocate(ACPI_SIZE Size
)
139 return AllocVec(Size
, MEMF_PUBLIC
);
142 void AcpiOsFree(void *Memory
)
147 BOOLEAN
AcpiOsReadable(void *Memory
, ACPI_SIZE Length
)
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)
162 tid
= (ACPI_THREAD_ID
)(ACPI_PHYSICAL_ADDRESS
)FindTask(NULL
);
164 /* If we are running during kernel bring-up, return
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
)
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
)
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
));
211 InitSemaphore(Handle
);
218 ACPI_STATUS
AcpiOsDeleteSemaphore(ACPI_SEMAPHORE Handle
)
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
);
230 if (AttemptSemaphore(Handle
)) {
238 ObtainSemaphore(Handle
);
243 ACPI_STATUS
AcpiOsSignalSemaphore(ACPI_SEMAPHORE Handle
, UINT32 Units
)
245 ReleaseSemaphore(Handle
);
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);
265 void AcpiOsReleaseLock(ACPI_SPINLOCK Handle
, ACPI_CPU_FLAGS Flags
)
267 AcpiOsSignalSemaphore (Handle
, 1);
271 struct Interrupt ai_Interrupt
;
272 ACPI_OSD_HANDLER ai_Handler
;
276 static AROS_INTH1(AcpiOsIntServer
, struct AcpiOsInt
*, ai
)
282 ret
= ai
->ai_Handler(ai
->ai_Context
);
284 return (ret
== ACPI_INTERRUPT_HANDLED
) ? TRUE
: FALSE
;
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
);
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
)
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;
325 ACPI_STATUS
AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address
, UINT64 Value
, UINT32 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;
338 ACPI_STATUS
AcpiOsReadPort(ACPI_IO_ADDRESS Address
, UINT32
*Value
, UINT32 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;
349 ACPI_STATUS
AcpiOsWritePort(ACPI_IO_ADDRESS Address
, UINT32 Value
, UINT32 Width
)
352 case 8: outb(Value
,Address
); break;
353 case 16: outw(Value
,Address
); break;
354 case 32: outl(Value
,Address
); break;
360 static UINT8
*find_pci(struct ACPICABase
*ACPICABase
, ACPI_PCI_ID
*PciId
)
364 for (i
= 0; i
< ACPICABase
->ab_PCIs
; i
++) {
365 ACPI_MCFG_ALLOCATION
*ma
= &ACPICABase
->ab_PCI
[i
];
366 if (PciId
->Segment
!= ma
->PciSegment
)
368 if (PciId
->Bus
< ma
->StartBusNumber
||
369 PciId
->Bus
> ma
->EndBusNumber
)
372 return (UINT8
*)(ACPI_PHYSICAL_ADDRESS
)ma
->Address
;
378 ACPI_STATUS
AcpiOsReadPciConfiguration(ACPI_PCI_ID
*PciId
, UINT32 Register
, UINT64
*Value
, UINT32 Width
)
384 if ((ecam
= find_pci(ACPICABase
, PciId
))) {
385 UINT32 offset
= (PciId
->Bus
<< 20) | (PciId
->Device
<< 15) | (PciId
->Function
<< 12) | Register
;
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;
400 ACPI_STATUS
AcpiOsWritePciConfiguration(ACPI_PCI_ID
*PciId
, UINT32 Register
, UINT64 Value
, UINT32 Width
)
406 if ((ecam
= find_pci(ACPICABase
, PciId
))) {
407 UINT32 offset
= (PciId
->Bus
<< 20) | (PciId
->Device
<< 15) | (PciId
->Function
<< 12) | Register
;
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;
422 void AcpiOsPrintf(const char *Fmt
, ...)
426 va_start (Args
, Fmt
);
427 AcpiOsVprintf (Fmt
, 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
;
445 TimerBase
= ACPICABase
->ab_TimerBase
;
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
;
467 LONG
AcpiScanTables(char *Signature
, const struct Hook
*Hook
, APTR UserData
)
472 for (count
= 0, i
= 1; ; i
++) {
474 ACPI_TABLE_HEADER
*hdr
;
477 err
= AcpiGetTable(Signature
, i
, &hdr
);
482 ok
= CALLHOOKPKT((struct Hook
*)Hook
, hdr
, UserData
);
493 #define ACPI_MAX_INIT_TABLES 64
495 static int ACPICA_InitTask(struct ACPICABase
*ACPICABase
)
498 const UINT8 initlevel
= ACPI_FULL_INITIALIZATION
;
500 err
= AcpiInitializeSubsystem();
501 if (ACPI_FAILURE(err
)) {
502 D(bug("%s: AcpiInitializeSubsystem() = %d\n", __func__
, err
));
506 err
= AcpiLoadTables();
507 if (ACPI_FAILURE(err
)) {
508 D(bug("%s: AcpiLoadTables() = %d\n", __func__
, err
));
512 err
= AcpiEnableSubsystem(initlevel
);
513 if (ACPI_FAILURE(err
)) {
514 D(bug("%s: AcpiEnableSubsystem(0x%02x) = %d\n", __func__
, initlevel
, err
));
518 err
= AcpiInitializeObjects(initlevel
);
519 if (ACPI_FAILURE(err
)) {
520 D(bug("%s: AcpiInitializeObjects(0x%02x) = %d\n", __func__
, initlevel
, err
));
524 D(bug("[ACPI] Full initialization complete\n"));
529 int ACPICA_init(struct ACPICABase
*ACPICABase
)
531 ACPI_TABLE_MCFG
*mcfg
;
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"));
544 THIS_ACPICABASE(ACPICABase
);
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
));
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];
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
) {
573 ADD2INITLIB(ACPICA_init
,0)
575 int ACPICA_expunge(struct ACPICABase
*ACPICABase
)
581 ADD2EXPUNGELIB(ACPICA_expunge
, 0)