diff --git a/base/include/irq_session/connection.h b/base/include/irq_session/connection.h index 682cc2761..2c8899ea9 100644 --- a/base/include/irq_session/connection.h +++ b/base/include/irq_session/connection.h @@ -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( - 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()) { } }; diff --git a/base/include/irq_session/irq_session.h b/base/include/irq_session/irq_session.h index ffdf3c226..cfa61284d 100644 --- a/base/include/irq_session/irq_session.h +++ b/base/include/irq_session/irq_session.h @@ -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() { } diff --git a/os/src/drivers/acpi/acpi.cc b/os/src/drivers/acpi/acpi.cc index 5e785f0dc..59bdb9178 100644 --- a/os/src/drivers/acpi/acpi.cc +++ b/os/src/drivers/acpi/acpi.cc @@ -95,6 +95,7 @@ class Irq_override : public List::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); - 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; } diff --git a/os/src/drivers/acpi/acpi.h b/os/src/drivers/acpi/acpi.h index 0e067b0de..cddb3bc3d 100644 --- a/os/src/drivers/acpi/acpi.h +++ b/os/src/drivers/acpi/acpi.h @@ -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_ */ diff --git a/os/src/drivers/acpi/main.cc b/os/src/drivers/acpi/main.cc index 5737392d2..1248676a2 100644 --- a/os/src/drivers/acpi/main.cc +++ b/os/src/drivers/acpi/main.cc @@ -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(); }