mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 08:25:38 +00:00
ACPI/IRQ: Add interrupt mode to IRQ connection
Read flags (polarity/trigger) from MADT and add information to 'Irq_connection' arguments. Issue #390
This commit is contained in:
parent
4a1b545770
commit
ff0c7825e4
@ -24,13 +24,17 @@ namespace Genode {
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param irq physical interrupt number
|
||||
* \param irq physical interrupt number
|
||||
* \param trigger interrupt trigger (e.g., level/edge)
|
||||
* \param polarity interrupt trigger polarity (e.g., low/high)
|
||||
*/
|
||||
Irq_connection(unsigned irq)
|
||||
Irq_connection(unsigned irq,
|
||||
Irq_session::Trigger trigger = Irq_session::TRIGGER_UNCHANGED,
|
||||
Irq_session::Polarity polarity = Irq_session::POLARITY_UNCHANGED)
|
||||
:
|
||||
Connection<Irq_session>(
|
||||
session("ram_quota=4K, irq_number=%u", irq)),
|
||||
|
||||
session("ram_quota=4K, irq_number=%u, irq_trigger=%u, irq_polarity=%u",
|
||||
irq, trigger, polarity)),
|
||||
Irq_session_client(cap())
|
||||
{ }
|
||||
};
|
||||
|
@ -28,6 +28,17 @@ namespace Genode {
|
||||
|
||||
struct Irq_session : Session
|
||||
{
|
||||
|
||||
/**
|
||||
* Interrupt trigger
|
||||
*/
|
||||
enum Trigger { TRIGGER_UNCHANGED = 0, TRIGGER_LEVEL, TRIGGER_EDGE };
|
||||
|
||||
/**
|
||||
* Interrupt trigger polarity
|
||||
*/
|
||||
enum Polarity { POLARITY_UNCHANGED = 0, POLARITY_HIGH, POLARITY_LOW };
|
||||
|
||||
static const char *service_name() { return "IRQ"; }
|
||||
|
||||
virtual ~Irq_session() { }
|
||||
|
@ -95,6 +95,7 @@ class Irq_override : public List<Irq_override>::Element
|
||||
|
||||
bool match(uint32_t irq) const { return irq == _irq; }
|
||||
uint32_t gsi() const { return _gsi; }
|
||||
uint32_t flags() const { return _flags; }
|
||||
};
|
||||
|
||||
|
||||
@ -196,8 +197,7 @@ class Table_wrapper
|
||||
|
||||
Apic_override *o = static_cast<Apic_override *>(apic);
|
||||
|
||||
if (verbose)
|
||||
PDBG("Found IRQ %u -> GSI %u", o->irq, o->gsi);
|
||||
PINF("MADT IRQ %u -> GSI %u flags: %x", o->irq, o->gsi, o->flags);
|
||||
|
||||
Irq_override::list()->insert(new (env()->heap()) Irq_override(o->irq, o->gsi, o->flags));
|
||||
}
|
||||
@ -944,7 +944,6 @@ class Acpi_table
|
||||
}
|
||||
|
||||
if (table.is_madt()) {
|
||||
if (verbose)
|
||||
PDBG("Found MADT");
|
||||
|
||||
table.parse_madt();
|
||||
@ -1127,7 +1126,7 @@ void Acpi::rewrite_irq(Pci::Session_capability &session)
|
||||
if (Element::supported_acpi_format())
|
||||
PINF("ACPI table format is supported by this driver");
|
||||
else {
|
||||
PERR("ACPI table format not supported (is too old) by this driver");
|
||||
PWRN("ACPI table format not supported will not rewrite GSIs");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1161,11 +1160,14 @@ void Acpi::rewrite_irq(Pci::Session_capability &session)
|
||||
/**
|
||||
* Search override structures
|
||||
*/
|
||||
unsigned Acpi::override(unsigned irq)
|
||||
unsigned Acpi::override(unsigned irq, unsigned *mode)
|
||||
{
|
||||
for (Irq_override *i = Irq_override::list()->first(); i; i = i->next())
|
||||
if (i->match(irq))
|
||||
if (i->match(irq)) {
|
||||
*mode = i->flags();
|
||||
return i->gsi();
|
||||
}
|
||||
|
||||
*mode = 0;
|
||||
return irq;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class Acpi
|
||||
/**
|
||||
* Return override GSI for IRQ
|
||||
*/
|
||||
static unsigned override(unsigned irq);
|
||||
static unsigned override(unsigned irq, unsigned *mode);
|
||||
};
|
||||
|
||||
#endif /* _ACPI_H_ */
|
||||
|
@ -38,6 +38,37 @@ namespace Irq {
|
||||
*/
|
||||
class Root : public Irq_session
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Irq_session::Trigger _mode2trigger(unsigned mode)
|
||||
{
|
||||
enum { EDGE = 0x4, LEVEL = 0xc };
|
||||
|
||||
switch (mode & 0xc) {
|
||||
case EDGE:
|
||||
return Genode::Irq_session::TRIGGER_EDGE;
|
||||
case LEVEL:
|
||||
return Genode::Irq_session::TRIGGER_LEVEL;
|
||||
default:
|
||||
return Genode::Irq_session::TRIGGER_UNCHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
Genode::Irq_session::Polarity _mode2polarity(unsigned mode)
|
||||
{
|
||||
using namespace Genode;
|
||||
enum { HIGH = 0x1, LOW = 0x3 };
|
||||
|
||||
switch (mode & 0x3) {
|
||||
case HIGH:
|
||||
return Genode::Irq_session::POLARITY_HIGH;
|
||||
case LOW:
|
||||
return Genode::Irq_session::POLARITY_LOW;
|
||||
default:
|
||||
return Genode::Irq_session::POLARITY_UNCHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -52,11 +83,12 @@ namespace Irq {
|
||||
long irq_number = Arg_string::find_arg(args.string(), "irq_number").long_value(-1);
|
||||
|
||||
/* check for 'MADT' overrides */
|
||||
irq_number = Acpi::override(irq_number);
|
||||
unsigned mode;
|
||||
irq_number = Acpi::override(irq_number, &mode);
|
||||
|
||||
/* allocate IRQ at parent*/
|
||||
try {
|
||||
Irq_connection irq(irq_number);
|
||||
Irq_connection irq(irq_number, _mode2trigger(mode), _mode2polarity(mode));
|
||||
irq.on_destruction(Irq_connection::KEEP_OPEN);
|
||||
return irq.cap();
|
||||
} catch (...) { throw Root::Unavailable(); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user