/* * \brief IRQ session interface * \author Alexander Boettcher * \date 2015-03-25 */ /* * Copyright (C) 2015-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. */ #ifndef _X86__IRQ_H_ #define _X86__IRQ_H_ #include #include #include #include /* platform local includes */ #include namespace Platform { class Irq_session_component; class Irq_override; class Irq_routing; } class Platform::Irq_session_component : public Genode::Rpc_object, private Genode::List::Element { private: friend class Genode::List; unsigned _gsi; Platform::Irq_sigh _irq_sigh { }; Genode::Irq_session::Info _msi_info { }; Genode::Constructible _irq_conn { }; public: enum { INVALID_IRQ = 0xffU }; Irq_session_component(unsigned, Genode::addr_t, Genode::Env &, Genode::Allocator &heap); ~Irq_session_component(); bool msi() { return _irq_conn.constructed() && _msi_info.type == Genode::Irq_session::Info::Type::MSI; } unsigned gsi() { return _gsi; } unsigned long msi_address() const { return _msi_info.address; } unsigned long msi_data() const { return _msi_info.value; } /*************************** ** Irq session interface ** ***************************/ void ack_irq() override; void sigh(Genode::Signal_context_capability) override; Info info() override { return { .type = Info::Type::INVALID, .address = 0, .value = 0 }; } }; /** * List that holds interrupt override information */ class Platform::Irq_override : public Genode::List::Element { private: unsigned short _irq; /* source IRQ */ unsigned short _gsi; /* target GSI */ Genode::Irq_session::Trigger _trigger; /* interrupt trigger mode */ Genode::Irq_session::Polarity _polarity; /* interrupt polarity */ 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: Irq_override(unsigned irq, unsigned gsi, unsigned mode) : _irq(irq), _gsi(gsi), _trigger(_mode2trigger(mode)), _polarity(_mode2polarity(mode)) { } static Genode::List *list() { static Genode::List _list; return &_list; } unsigned short irq() const { return _irq; } unsigned short gsi() const { return _gsi; } Genode::Irq_session::Trigger trigger() const { return _trigger; } Genode::Irq_session::Polarity polarity() const { return _polarity; } static unsigned irq_override (unsigned irq, Genode::Irq_session::Trigger &trigger, Genode::Irq_session::Polarity &polarity) { for (Irq_override *i = list()->first(); i; i = i->next()) if (i->irq() == irq) { trigger = i->trigger(); polarity = i->polarity(); return i->gsi(); } trigger = Genode::Irq_session::TRIGGER_UNCHANGED; polarity = Genode::Irq_session::POLARITY_UNCHANGED; return irq; } }; /** * List that holds interrupt rewrite information */ class Platform::Irq_routing : public Genode::List::Element { private: unsigned short _gsi; unsigned short _bridge_bdf; unsigned short _device; unsigned char _device_pin; public: static Genode::List *list() { static Genode::List _list; return &_list; } Irq_routing(unsigned short gsi, unsigned short bridge_bdf, unsigned char device, unsigned char device_pin) : _gsi(gsi), _bridge_bdf(bridge_bdf), _device(device), _device_pin(device_pin) { } static unsigned short rewrite(unsigned char bus, unsigned char dev, unsigned char func, unsigned char pin); }; #endif /* _X86__IRQ_H_ */