#ifndef INTERRUPT_HH_ #define INTERRUPT_HH_ #include <functional> #include <map> #include <list> #include "sched.hh" #include "drivers/pci.hh" #include "drivers/pci-function.hh" #include "types.hh" using namespace pci; // max vectors per request const int max_vectors = 256; class msix_vector { public: msix_vector(pci_function* dev); virtual ~msix_vector(); pci_function* get_pci_function(void); unsigned get_vector(void); void msix_unmask_entries(void); void msix_mask_entries(void); void add_entryid(unsigned entry_id); void interrupt(void); void set_handler(std::function<void ()> handler); private: // Handler to invoke... std::function<void ()> _handler; // The device that owns this vector pci_function * _dev; // Entry ids used by this vector std::list<unsigned> _entryids; unsigned _vector; unsigned _num_entries; }; // Used to communicate assigned vectors back to driver class assigned_vectors { public: assigned_vectors() : _num(0) { for (int i=0; i<max_vectors; i++) { _vectors[i] = 0; } } unsigned _vectors[max_vectors]; unsigned _num; }; // entry -> thread to wake typedef std::map<unsigned, sched::thread *> msix_isr_list; class interrupt_manager { public: interrupt_manager(); virtual ~interrupt_manager(); static interrupt_manager * instance() { if (_instance == nullptr) { _instance = new interrupt_manager(); } return (_instance); } //////////////////// // Easy Interface // //////////////////// // 1. Enabled MSI-x For device // 2. Allocate vectors and assign ISRs // 3. Setup entries // 4. Unmask interrupts bool easy_register(pci_function* dev, msix_isr_list& isrs); void easy_unregister(pci_function* dev); ///////////////////// // Multi Interface // ///////////////////// assigned_vectors request_vectors(pci_function* dev, unsigned num_vectors); void free_vectors(const assigned_vectors& vectors); bool assign_isr(unsigned vector, std::function<void ()> handler); // Multiple entry can be assigned the same vector bool setup_entry(unsigned entry_id, unsigned vector); // unmasks all interrupts bool unmask_interrupts(const assigned_vectors& vectors); private: static interrupt_manager* _instance; msix_vector* _vectors[max_vectors]; // Used by the easy interface std::map<pci_function *, assigned_vectors> _easy_dev2vectors; }; #endif /* INTERRUPT_HH_ */