irq_manager.hpp
00001 #if !defined(__IRQ_MANAGER_HPP__)
00002 #define __IRQ_MANAGER_HPP__
00003
00004
00005
00006
00007 #include "core/machine/generic/resource_manager.hpp"
00008 #include "irq_source.hpp"
00009 #include "irq.hpp"
00010
00011
00012
00013
00014 struct machine_config;
00015
00019 struct irq_manager : public resource_manager, private noncopyable
00020 {
00021 static const bool VERBOSE_ALLOCATION = false;
00022 static const int FIRST_HANDLE = 0x100;
00023 static const uint16_t NUM_IRQS = 24;
00024
00025
00026
00027
00028 static_assert(is_unsigned<l4_irq_t>::conforms, "l4_irq_t must be an unsigned integer");
00029 static_assert(integer_traits<l4_irq_t>::const_max >= NUM_IRQS - 1,
00030 "l4_irq_t's max value is too small");
00031
00032 enum irqs_constants
00033 {
00038 NO_IRQ = integer_traits<l4_irq_t>::const_max,
00039 };
00040
00041 static_assert(NO_IRQ >= NUM_IRQS, "NO_IRQ must be >= NUM_IRQS");
00042
00043 typedef resource_flags irq_flags;
00044
00045 struct irq_state : public irq_flags, public irq
00046 {
00047
00048
00049
00050
00051 l4_irq_t l4vmm_irq;
00052 int l4vmm_handle;
00053
00054 l4_irq_t omega0_irq;
00055 int omega0_handle;
00056
00057 irq_source *src;
00058
00059 l4_threadid_t client;
00060
00061 inline irq_state(void)
00062 : irq_flags(0), l4vmm_irq(NO_IRQ), l4vmm_handle(-L4_ENOHANDLE),
00063 omega0_irq(NO_IRQ), omega0_handle(-L4_ENOHANDLE),
00064 src(nullptr), client(L4_INVALID_ID)
00065 {}
00066
00067
00068
00069
00070 inline bool is_source(const irq_source *src) const
00071 {
00072 return this->src == src;
00073 }
00074
00075 inline bool is_client(const l4_threadid_t client) const
00076 {
00077 return l4_thread_equal(this->client, client);
00078 }
00079
00080
00081
00082
00083 inline irq_state ®ister_source(irq_source *src, const irq_flags use,
00084 const l4_irq_t physical_irq=NO_IRQ)
00085 {
00086 set(use & USE_MASK);
00087 omega0_irq=use.is_physical() ? physical_irq : static_cast<l4_irq_t>(NO_IRQ);
00088 this->src=src;
00089 return *this;
00090 }
00091
00092 inline irq_state ©_source(const irq_state &other)
00093 {
00094 clear(USE_MASK);
00095 set(other.bits & USE_MASK);
00096 omega0_irq=other.omega0_irq;
00097 src=other.src;
00098 return *this;
00099 }
00100
00101
00102
00103
00104
00105 inline irq_state &attach(const l4_threadid_t client, const int handle=-L4_ENOHANDLE)
00106 {
00107 set(ATTACHED);
00108 this->omega0_handle=handle;
00109 this->client=client;
00110 return *this;
00111 }
00112
00113 inline irq_state &detach(void)
00114 {
00115 clear(ATTACHED);
00116 omega0_handle=-L4_ENOHANDLE;
00117 client=L4_INVALID_ID;
00118 return *this;
00119 }
00120
00121
00122
00123
00124 inline int reset(void)
00125 {
00126 clear(USE_MASK | ATTACHED);
00127
00128 omega0_irq=NO_IRQ;
00129 omega0_handle=-L4_ENOHANDLE;
00130 src=nullptr;
00131 client=L4_INVALID_ID;
00132 return 0;
00133 }
00134 };
00135
00136 protected:
00140 const machine_config &config;
00141
00142 public:
00143
00144
00145
00146
00150 lock irq_lock;
00151
00152 protected:
00156 irq_state irq_states[NUM_IRQS];
00157
00158 public:
00159
00160
00161
00162 irq_manager(const machine_config &config);
00163 virtual ~irq_manager(void);
00164
00165
00166
00167
00168
00169
00170 inline const irq_state *irq_state_from_line(const l4_irq_t irq) const
00171 {
00172
00173 return is_valid_irq(irq) ? &irq_states[irq] : nullptr;
00174 }
00175
00176 inline irq_state *irq_state_from_line(const l4_irq_t irq)
00177 {
00178
00179 return is_valid_irq(irq) ? &irq_states[irq] : nullptr;
00180 }
00181
00182 inline irq_state *irq_state_from_handle(const int handle)
00183 {
00184 return irq_state_from_line(handle - FIRST_HANDLE);
00185 }
00186
00187 inline irq_state *irq_state_from_source(const irq_source *src)
00188 {
00189 for (irq_state *state=beginof(irq_states); state != endof(irq_states); state++)
00190 if (state->is_source(src)) return state;
00191 return nullptr;
00192 }
00193
00194 inline irq_state *irq_state_from_client(const l4_threadid_t client)
00195 {
00196 for (irq_state *state=beginof(irq_states); state != endof(irq_states); state++)
00197 if (state->is_client(client)) return state;
00198 return nullptr;
00199 }
00200
00201
00202
00203
00204 virtual int check_irq_request(const irq_source *src, irq_flags use,
00205 l4_irq_t irq, l4_irq_t physical_irq,
00206 bool verbose=VERBOSE_ALLOCATION) const;
00207
00208 virtual int request_irq(irq_source *src, irq_flags use,
00209 l4_irq_t physical_irq=NO_IRQ, bool verbose=VERBOSE_ALLOCATION);
00210
00211 virtual int register_irq(irq_source *src, irq_flags use, l4_irq_t irq=NO_IRQ,
00212 l4_irq_t physical_irq=NO_IRQ, bool verbose=VERBOSE_ALLOCATION);
00213
00214 virtual int unregister_irq(const irq_source *src, l4_irq_t irq, bool verbose=VERBOSE_ALLOCATION);
00215
00216 inline void assert_irq(const l4_irq_t irq)
00217 {
00218 assert_logd(L4VMM_DEBUG_IRQS, is_valid_irq(irq), "irq: "l4_irq_fmt"\n", irq);
00219 irq_state_from_line(irq)->assert_irq();
00220 }
00221
00222 inline void assert_irq(const irq_source *src, const l4_irq_t irq)
00223 {
00224 assert_logd(L4VMM_DEBUG_IRQS, is_valid_irq(irq), "irq: "l4_irq_fmt"\n", irq);
00225 irq_state *state=irq_state_from_line(irq);
00226 if (!state->is_source(src)) enter_kdebug(" wrong IRQ asserted ");
00227 state->assert_irq();
00228 }
00229
00230
00231
00232
00233 virtual void print_irq_states(const char *header=nullptr);
00234
00235 protected:
00236 virtual int init_irqs(void);
00237 virtual irq_state *find_free_irq(irq_flags use);
00238
00239 public:
00240 static inline bool is_valid_irq(const l4_irq_t irq)
00241 {
00242 return range_traits<l4_irq_t, NUM_IRQS>::is_valid(irq);
00243 }
00244 };
00245
00246 #endif
00247
00248
00249