mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 20:05:54 +00:00
ACPI: GSI parser, fix #34
Read GSIs from ACPI tables and rewrite PCI-config space IRQs
This commit is contained in:
parent
c2c87c8833
commit
7e00ef96ee
35
os/src/drivers/acpi/README
Normal file
35
os/src/drivers/acpi/README
Normal file
@ -0,0 +1,35 @@
|
||||
This directory contains an implementation of a simple ACPI parser
|
||||
|
||||
Behavior
|
||||
--------
|
||||
|
||||
This server should be used when using a kernel (like Fiasco.OC or Nova) that
|
||||
takes advantage of x86's APIC. The server traverses the ACPI tables and sets the
|
||||
interrupt line of devices within the PCI config space to the GSIs found in the
|
||||
ACPI tables.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Start the 'acpi_drv' in your Genode environment. Do not start the 'pci_drv'
|
||||
since this will be used as a slave of the 'acpi_drv'. You still must load the
|
||||
'pci_drv' in your boot loader.
|
||||
|
||||
Configuration snipped:
|
||||
|
||||
!<start name="acpi">
|
||||
! <resource name="RAM" quantum="2M"/>
|
||||
! <binary name="acpi_drv"/>
|
||||
! <provides><service name="PCI"/></provides>
|
||||
! <route>
|
||||
! <service name="ROM"> <parent/> </service>
|
||||
! <any-service> <any-child/> <parent/> </any-service>
|
||||
! </route>
|
||||
!</start>
|
||||
|
||||
Limitations and known issues
|
||||
----------------------------
|
||||
|
||||
Currently there is no interface to set the interrupt mode for Irq_sessions
|
||||
(e.g., level or edge triggered). This is required by Fiasco.OCs kernel
|
||||
interface. We regard this as future work.
|
1073
os/src/drivers/acpi/acpi.cc
Normal file
1073
os/src/drivers/acpi/acpi.cc
Normal file
File diff suppressed because it is too large
Load Diff
31
os/src/drivers/acpi/acpi.h
Normal file
31
os/src/drivers/acpi/acpi.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* \brief Interface to ACPI
|
||||
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
|
||||
* \date 2012-02-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2012 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _ACPI_H_
|
||||
#define _ACPI_H_
|
||||
|
||||
#include <base/thread.h>
|
||||
#include <pci_session/capability.h>
|
||||
|
||||
class Acpi
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Rewrite PCI-config space with GSIs found in ACPI tables
|
||||
*/
|
||||
static void rewrite_irq(Pci::Session_capability &session);
|
||||
};
|
||||
|
||||
#endif /* _ACPI_H_ */
|
||||
|
155
os/src/drivers/acpi/main.cc
Normal file
155
os/src/drivers/acpi/main.cc
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* \brief Service and session interface
|
||||
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
|
||||
* \date 2012-02-25
|
||||
*
|
||||
* The 'acpi_drv' provides the 'PCI' after rewriting the IRQ information of PCI
|
||||
* devices. For this it uses the 'pci_drv' as a client and forwards the session
|
||||
* capability of the 'pci_drv' afterwards
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2012 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <os/slave.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/env.h>
|
||||
#include <base/sleep.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <pci_session/client.h>
|
||||
|
||||
#include "acpi.h"
|
||||
|
||||
namespace Pci {
|
||||
|
||||
struct Provider
|
||||
{
|
||||
bool ready_to_use() { return root().valid(); }
|
||||
|
||||
virtual Genode::Root_capability root() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Root interface of PCI service
|
||||
*/
|
||||
class Root : public Genode::Rpc_object<Genode::Typed_root<Pci::Session> >
|
||||
{
|
||||
private:
|
||||
|
||||
Provider &_pci_provider;
|
||||
|
||||
public:
|
||||
|
||||
Genode::Session_capability session(Session_args const &args)
|
||||
{
|
||||
if (!args.is_valid_string()) throw Invalid_args();
|
||||
|
||||
if (!_pci_provider.ready_to_use())
|
||||
throw Unavailable();
|
||||
|
||||
try {
|
||||
return Genode::Root_client(_pci_provider.root()).session(args.string());
|
||||
} catch (...) {
|
||||
throw Unavailable();
|
||||
}
|
||||
}
|
||||
|
||||
void upgrade(Genode::Session_capability, Upgrade_args const &) { }
|
||||
|
||||
void close(Genode::Session_capability session)
|
||||
{
|
||||
Genode::Root_client(_pci_provider.root()).close(session);
|
||||
}
|
||||
|
||||
Root(Provider &pci_provider) : _pci_provider(pci_provider) { }
|
||||
};
|
||||
}
|
||||
|
||||
typedef Genode::Capability<Genode::Typed_root<Pci::Session> > Service_capability;
|
||||
|
||||
class Pci_policy : public Genode::Slave_policy, public Pci::Provider
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Root_capability _cap;
|
||||
Genode::Rpc_entrypoint &_ep;
|
||||
|
||||
protected:
|
||||
|
||||
char const **_permitted_services() const
|
||||
{
|
||||
static char const *permitted_services[] = {
|
||||
"CAP", "RM", "LOG", "IO_PORT", 0 };
|
||||
|
||||
return permitted_services;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse ACPI tables and announce slave PCI service
|
||||
*/
|
||||
void _acpi_session()
|
||||
{
|
||||
Pci::Session_capability session;
|
||||
const char *args = "ram_quota=4K";
|
||||
|
||||
try {
|
||||
using namespace Genode;
|
||||
session = static_cap_cast<Pci::Session>(Root_client(_cap).session(args));
|
||||
} catch (...) { return; }
|
||||
|
||||
Acpi::rewrite_irq(session);
|
||||
|
||||
/* announce service PCI to parent */
|
||||
static Pci::Root pci_root(*this);
|
||||
Genode::env()->parent()->announce(_ep.manage(&pci_root));
|
||||
|
||||
Genode::Root_client(_cap).close(session);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Pci_policy(Genode::Rpc_entrypoint &slave_ep, Genode::Rpc_entrypoint &ep)
|
||||
: Slave_policy("pci_drv", slave_ep), _ep(ep)
|
||||
{ }
|
||||
|
||||
bool announce_service(const char *service_name,
|
||||
Genode::Root_capability root,
|
||||
Genode::Allocator *alloc)
|
||||
{
|
||||
/* wait for 'pci_drv' to announce the PCI service */
|
||||
if (Genode::strcmp(service_name, "PCI"))
|
||||
return false;
|
||||
|
||||
_cap = root;
|
||||
|
||||
/* connect session and start ACPI parsing */
|
||||
_acpi_session();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Genode::Root_capability root() { return _cap; }
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
enum { STACK_SIZE = 2*4096 };
|
||||
static Cap_connection cap;
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "acpi_ep");
|
||||
|
||||
/* use 'pci_drv' as slave service */
|
||||
static Rpc_entrypoint pci_ep(&cap, STACK_SIZE, "pci_slave");
|
||||
static Pci_policy pci_policy(pci_ep, ep);
|
||||
static Genode::Slave pci_slave(pci_ep, pci_policy, 512 * 1024);
|
||||
|
||||
Genode::sleep_forever();
|
||||
return 0;
|
||||
}
|
||||
|
9
os/src/drivers/acpi/x86/target.mk
Normal file
9
os/src/drivers/acpi/x86/target.mk
Normal file
@ -0,0 +1,9 @@
|
||||
TARGET = acpi_drv
|
||||
REQUIRES = x86
|
||||
SRC_CC = main.cc acpi.cc
|
||||
LIBS = cxx env server process
|
||||
|
||||
INC_DIR = $(PRG_DIR)/..
|
||||
|
||||
vpath main.cc $(PRG_DIR)/..
|
||||
vpath acpi.cc $(PRG_DIR)/..
|
Loading…
x
Reference in New Issue
Block a user