Overview   API Reference  

irq_manager.hpp

00001 #if !defined(__IRQ_MANAGER_HPP__)
00002 #define __IRQ_MANAGER_HPP__
00003 
00004 //
00005 // local includes
00006 //
00007 #include "core/machine/generic/resource_manager.hpp"
00008 #include "irq_source.hpp"
00009 #include "irq.hpp"
00010 
00011 //
00012 // forward declarations
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     //     irq_line_t must be unsigned, since values below 0 are used for error codes
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         // attribute bits to store the current (management) state and mechanism routines
00049         //     derived from base classes
00050         //
00051         /* const */ l4_irq_t l4vmm_irq;         // this IRQ's line
00052         /* const */ int l4vmm_handle;           // handle to be returned by l4vmm_irq_attach
00053 
00054         l4_irq_t omega0_irq;                    // omega0's IRQ (the real one)
00055         int omega0_handle;                      // handle returned by omega0_attach
00056 
00057         irq_source *src;                        // the source (the device); stored here to
00058                                                 // remap the IRQ later
00059         l4_threadid_t client;                   // attached client thread's ID
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         // query functions
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         // source (device) management functions
00082         //
00083         inline irq_state &register_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 &copy_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         // client (the attached thread) management functions
00103         //     note: omega0_irq should have already been set by the source (the device)
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         // reset everything back to defaults
00123         //
00124         inline int reset(void)
00125         {
00126             clear(USE_MASK | ATTACHED);
00127             // clear any information about physical usage
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     // TODO: should be protected, but at first I need to move the API
00145     //       implementation into the machine_base class.
00146     //
00150     lock irq_lock;
00151 
00152   protected:
00156     irq_state irq_states[NUM_IRQS];
00157 
00158   public:
00159     //
00160     // constructors & destructors
00161     //
00162     irq_manager(const machine_config &config);
00163     virtual ~irq_manager(void);
00164 
00165     //
00166     // convert line/handle/source/client thread ID to irq_state struct
00167     // TODO: should be protected or return const objects, but at first I need to
00168     //       move the API implementation into the machine_base class.
00169     //
00170     inline const irq_state *irq_state_from_line(const l4_irq_t irq) const
00171     {
00172         // no need to search the irq_state object. they are already ordered.
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         // no need to search the irq_state object. they are already ordered.
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     // IRQ management functions regarding sources (devices)
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     // debug stuff
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 // ***** end of source ***** //
00249 

L4vmm Reference Manual, written by Mario Schwalbe  © 2006-2008