X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/9daf4fcdae88f72af60aeb0c7722841af02233d4..836d44ecb7a2c37427f6baf8b25e872e9e943d5b:/lunaix-os/includes/hal/irq.h?ds=sidebyside diff --git a/lunaix-os/includes/hal/irq.h b/lunaix-os/includes/hal/irq.h new file mode 100644 index 0000000..e592e22 --- /dev/null +++ b/lunaix-os/includes/hal/irq.h @@ -0,0 +1,162 @@ +#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 */