#ifndef __LUNAIX_IRQ_H #define __LUNAIX_IRQ_H #include #include #include #include struct irq_domain; typedef struct irq_object* irq_t; typedef void (*irq_servant)(irq_t, const struct hart_state*); struct irq_domain_ops { int (*install_irq)(struct irq_domain*, irq_t); int (*map_irq)(struct irq_domain*, irq_t, void* irq_extra); int (*remove_irq)(struct irq_domain*, irq_t); }; struct irq_domain { POTENS_META; struct llist_header list; struct irq_domain* parent; struct btrie irq_map; const struct irq_domain_ops* ops; void* object; }; enum irq_type { IRQ_LINE, IRQ_MESSAGE }; struct irq_line_wire { ptr_t domain_local; ptr_t domain_mapped; }; struct irq_msi_wire { ptr_t message; ptr_t sideband; ptr_t wr_addr; }; struct irq_object { enum irq_type type; unsigned int vector; union { struct irq_line_wire* line; struct irq_msi_wire* msi; }; irq_servant serve; void* payload; struct irq_domain* domain; void* irq_extra; int ref; }; #define SZ sizeof(struct irq_object) struct irq_domain* irq_create_domain(struct device* intc_dev, const struct irq_domain_ops* ops); struct irq_domain* irq_owning_domain(struct device* dev); int irq_attach_domain(struct irq_domain* parent, struct irq_domain* child); irq_t irq_declare(enum irq_type, irq_servant, ptr_t, void*); void irq_revoke(irq_t); int irq_assign(struct irq_domain* domain, irq_t); irq_t irq_find(struct irq_domain* domain, int local_irq); void irq_record(struct irq_domain* domain, irq_t irq); void irq_set_default_domain(struct irq_domain*); struct irq_domain* irq_get_default_domain(); int irq_forward_install(struct irq_domain* current, irq_t irq); static inline void irq_serve(irq_t irq, struct hart_state* state) { irq->serve(irq, state); } static inline void irq_set_payload(irq_t irq, void* payload) { irq->payload = payload; } static inline void irq_set_domain_object(struct irq_domain* domain, void* obj) { domain->object = obj; } #define irq_payload(irq, type) ((type*)(irq)->payload) #define irq_domain_obj(domain, type) ((type*)(domain)->object) static inline irq_t irq_declare_line(irq_servant callback, int local_irq, void* irq_extra) { return irq_declare(IRQ_LINE, callback, (int)local_irq, irq_extra); } static inline irq_t irq_declare_msg(irq_servant callback, ptr_t message, ptr_t sideband, void* irq_extra) { irq_t irq; irq = irq_declare(IRQ_MESSAGE, callback, message, irq_extra); irq->msi->sideband = sideband; return irq; } static inline struct irq_domain* irq_get_domain(struct device* maybe_intc) { struct potens_meta* domain_m; domain_m = device_get_potens(maybe_intc, potens(INT_DOMAIN)); return domain_m ? get_potens(domain_m, struct irq_domain) : NULL; } static inline struct irq_domain* irq_parent_domain(struct irq_domain* domain) { return domain->parent; } #endif /* __LUNAIX_IRQ_H */