genode/repos/libports/src/lib/acpica/osl.cc

325 lines
6.6 KiB
C++

/*
* \brief OS specific backend for ACPICA library
* \author Alexander Boettcher
* \date 2016-11-14
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <base/log.h>
#include <util/misc_math.h>
#include <io_port_session/connection.h>
#include <timer_session/connection.h>
#include <acpica/acpica.h>
#include "env.h"
extern "C" {
#include "acpi.h"
#include "acpiosxf.h"
}
#define FAIL(retval) \
{ \
Genode::error(__func__, ":", __LINE__, " called - dead"); \
Genode::Lock lock; \
while (1) lock.lock(); \
return retval; \
}
ACPI_STATUS AcpiOsPredefinedOverride (const ACPI_PREDEFINED_NAMES *pre,
ACPI_STRING *newobj)
{
*newobj = nullptr;
return AE_OK;
}
void * AcpiOsAllocate (ACPI_SIZE size) { return Acpica::heap().alloc(size); }
void AcpiOsFree (void *ptr)
{
if (Acpica::heap().need_size_for_free())
Genode::warning(__func__, " called - warning - ptr=", ptr);
Acpica::heap().free(ptr, 0);
}
ACPI_STATUS AcpiOsCreateLock (ACPI_SPINLOCK *spin_lock)
{
*spin_lock = new (Acpica::heap()) Genode::Lock();
return AE_OK;
}
ACPI_CPU_FLAGS AcpiOsAcquireLock (ACPI_SPINLOCK h)
{
Genode::Lock *lock = reinterpret_cast<Genode::Lock *>(h);
lock->lock();
return AE_OK;
}
void AcpiOsReleaseLock (ACPI_SPINLOCK h, ACPI_CPU_FLAGS flags)
{
Genode::Lock *lock = reinterpret_cast<Genode::Lock *>(h);
if (flags != AE_OK)
Genode::warning("warning - unknown flags in ", __func__);
lock->unlock();
return;
}
ACPI_STATUS AcpiOsCreateSemaphore (UINT32 max, UINT32 initial,
ACPI_SEMAPHORE *sem)
{
*sem = new (Acpica::heap()) Genode::Semaphore(initial);
return AE_OK;
}
ACPI_STATUS AcpiOsWaitSemaphore(ACPI_SEMAPHORE h, UINT32 units,
UINT16 timeout_ms)
{
Genode::Semaphore *sem = reinterpret_cast<Genode::Semaphore *>(h);
if (!units)
FAIL(AE_BAD_PARAMETER)
/**
* Timeouts not supported yet ...
* == 0 means - try and don't block - we're single threaded - ignore
* == 0xfff means - wait endless - fine
*/
if (0 < timeout_ms && timeout_ms < 0xffff)
FAIL(AE_BAD_PARAMETER)
/* timeout == forever case */
while (units) {
sem->down();
units--;
}
return AE_OK;
}
ACPI_STATUS AcpiOsSignalSemaphore (ACPI_SEMAPHORE h, UINT32 units)
{
Genode::Semaphore *sem = reinterpret_cast<Genode::Semaphore *>(h);
while (units) {
sem->up();
units--;
}
return AE_OK;
}
ACPI_STATUS AcpiOsDeleteSemaphore (ACPI_SEMAPHORE)
FAIL(AE_BAD_PARAMETER)
ACPI_THREAD_ID AcpiOsGetThreadId (void) {
return reinterpret_cast<Genode::addr_t>(Genode::Thread::myself()); }
ACPI_STATUS AcpiOsTableOverride (ACPI_TABLE_HEADER *x, ACPI_TABLE_HEADER **y)
{
*y = nullptr;
return AE_OK;
}
ACPI_STATUS AcpiOsPhysicalTableOverride (ACPI_TABLE_HEADER *x,
ACPI_PHYSICAL_ADDRESS *y, UINT32 *z)
{
*y = 0;
return AE_OK;
}
ACPI_STATUS AcpiOsReadPort (ACPI_IO_ADDRESS port, UINT32 *value, UINT32 width)
{
if (width % 8 != 0)
FAIL(AE_BAD_PARAMETER)
/* the I/O port may be owned by drivers, which will cause exceptions */
try {
unsigned const bytes = width / 8;
Genode::Io_port_connection io_port(Acpica::env(), port, bytes);
switch (bytes) {
case 1 :
*value = io_port.inb(port);
break;
case 2 :
*value = io_port.inw(port);
break;
case 4 :
*value = io_port.inl(port);
break;
default:
FAIL(AE_BAD_PARAMETER)
}
}
catch (Genode::Service_denied) { return AE_BAD_PARAMETER; }
return AE_OK;
}
ACPI_STATUS AcpiOsWritePort (ACPI_IO_ADDRESS port, UINT32 value, UINT32 width)
{
if (width % 8 != 0)
FAIL(AE_BAD_PARAMETER)
/* the I/O port may be owned by drivers, which will cause exceptions */
try {
unsigned const bytes = width / 8;
Genode::Io_port_connection io_port(Acpica::env(), port, bytes);
switch (bytes) {
case 1 :
io_port.outb(port, value);
break;
case 2 :
io_port.outw(port, value);
break;
case 4 :
io_port.outl(port, value);
break;
default:
FAIL(AE_BAD_PARAMETER)
}
}
catch (Genode::Service_denied) { return AE_BAD_PARAMETER; }
return AE_OK;
}
static struct
{
ACPI_EXECUTE_TYPE type;
ACPI_OSD_EXEC_CALLBACK func;
void *context;
} deferred[8];
ACPI_STATUS AcpiOsExecute(ACPI_EXECUTE_TYPE type, ACPI_OSD_EXEC_CALLBACK func,
void *context)
{
if (type == OSL_GPE_HANDLER) {
func(context);
return AE_OK;
}
if (type != OSL_NOTIFY_HANDLER)
FAIL(AE_BAD_PARAMETER)
for (unsigned i = 0; i < sizeof(deferred) / sizeof (deferred[0]); i++) {
if (deferred[i].func)
continue;
deferred[i].type = type;
deferred[i].func = func;
deferred[i].context = context;
return AE_OK;
}
Genode::error("queue full for deferred handlers");
return AE_BAD_PARAMETER;
}
void AcpiOsWaitEventsComplete()
{
for (unsigned i = 0; i < sizeof(deferred) / sizeof (deferred[0]); i++) {
if (!deferred[i].func)
continue;
ACPI_OSD_EXEC_CALLBACK func = deferred[i].func;
deferred[i].func = nullptr;
func(deferred[i].context);
}
}
static Timer::Connection &timer_connection()
{
static Timer::Connection connection(Acpica::env());
return connection;
}
void AcpiOsSleep (UINT64 sleep_ms)
{
Genode::log(__func__, " ", sleep_ms, " ms");
timer_connection().msleep(sleep_ms);
}
void AcpiOsStall (UINT32 stall_us)
{
Genode::log(__func__, " ", stall_us, " us");
timer_connection().usleep(stall_us);
}
/********************************
* unsupported/unused functions *
********************************/
ACPI_STATUS AcpiOsSignal (UINT32, void *)
FAIL(AE_BAD_PARAMETER)
UINT64 AcpiOsGetTimer (void)
{
return timer_connection().elapsed_us() * 10;
}
ACPI_STATUS AcpiOsReadMemory (ACPI_PHYSICAL_ADDRESS, UINT64 *, UINT32)
FAIL(AE_BAD_PARAMETER)
ACPI_STATUS AcpiOsWriteMemory (ACPI_PHYSICAL_ADDRESS, UINT64, UINT32)
FAIL(AE_BAD_PARAMETER)
ACPI_STATUS AcpiOsRemoveInterruptHandler (UINT32, ACPI_OSD_HANDLER)
FAIL(AE_BAD_PARAMETER)
ACPI_STATUS AcpiOsGetLine (char *, UINT32, UINT32 *)
FAIL(AE_BAD_PARAMETER)
ACPI_STATUS
AcpiOsWaitCommandReady (
void)
{
FAIL(AE_BAD_PARAMETER)
}
ACPI_STATUS
AcpiOsNotifyCommandComplete (
void)
{
FAIL(AE_BAD_PARAMETER)
}
ACPI_STATUS
AcpiOsEnterSleep (
UINT8 SleepState,
UINT32 RegaValue,
UINT32 RegbValue)
{
FAIL(AE_BAD_PARAMETER)
}
extern "C"
{
void AcpiAhMatchUuid() FAIL()
void AcpiAhMatchHardwareId() FAIL()
void AcpiDbCommandDispatch() FAIL()
void AcpiDbSetOutputDestination() FAIL()
void MpSaveSerialInfo() FAIL()
void MpSaveGpioInfo() FAIL()
}