rework external irq system, introduce hierarchical irq
[lunaix-os.git] / lunaix-os / includes / hal / irq.h
1 #ifndef __LUNAIX_IRQ_H
2 #define __LUNAIX_IRQ_H
3
4 #include <lunaix/changeling.h>
5 #include <lunaix/device.h>
6 #include <lunaix/ds/btrie.h>
7 #include <asm/hart.h>
8
9 struct irq_domain;
10 typedef struct irq_object* irq_t;
11 typedef void (*irq_servant)(irq_t, const struct hart_state*);
12
13 struct irq_domain_ops
14 {
15     int
16     (*install_irq)(struct irq_domain*, irq_t);
17
18     int
19     (*map_irq)(struct irq_domain*, irq_t, void* irq_extra);
20
21     int
22     (*remove_irq)(struct irq_domain*, irq_t);
23 };
24
25 struct irq_domain
26 {
27     POTENS_META;
28
29     struct llist_header list;
30
31     struct irq_domain* parent;
32     struct btrie irq_map;
33     const struct irq_domain_ops* ops;
34     void* object;
35 };
36
37 enum irq_type
38 {
39     IRQ_LINE,
40     IRQ_MESSAGE
41 };
42
43 struct irq_line_wire
44 {
45     ptr_t domain_local;
46     ptr_t domain_mapped;
47 };
48
49 struct irq_msi_wire
50 {
51     ptr_t message;
52     ptr_t sideband;
53     ptr_t wr_addr;
54 };
55
56 struct irq_object
57 {    
58     enum irq_type type;
59     unsigned int vector;
60     
61     union {
62         struct irq_line_wire* line;
63         struct irq_msi_wire* msi;
64     };
65
66     irq_servant serve;
67     void* payload;
68
69     struct irq_domain* domain;
70     void* irq_extra;
71     int ref;
72 };
73
74 #define SZ sizeof(struct irq_object)
75
76 struct irq_domain*
77 irq_create_domain(struct device* intc_dev, const struct irq_domain_ops* ops);
78
79 struct irq_domain*
80 irq_owning_domain(struct device* dev);
81
82 int
83 irq_attach_domain(struct irq_domain* parent, struct irq_domain* child);
84
85 irq_t
86 irq_declare(enum irq_type, irq_servant, ptr_t, void*);
87
88 void
89 irq_revoke(irq_t);
90
91 int
92 irq_assign(struct irq_domain* domain, irq_t);
93
94 irq_t
95 irq_find(struct irq_domain* domain, int local_irq);
96
97 void
98 irq_record(struct irq_domain* domain, irq_t irq);
99
100 void
101 irq_set_default_domain(struct irq_domain*);
102
103 struct irq_domain*
104 irq_get_default_domain();
105
106 int
107 irq_forward_install(struct irq_domain* current, irq_t irq);
108
109 static inline void
110 irq_serve(irq_t irq, struct hart_state* state)
111 {
112     irq->serve(irq, state);
113 }
114
115 static inline void
116 irq_set_payload(irq_t irq, void* payload)
117 {
118     irq->payload = payload;
119 }
120
121 static inline void
122 irq_set_domain_object(struct irq_domain* domain, void* obj)
123 {
124     domain->object = obj;
125 }
126
127 #define irq_payload(irq, type)              ((type*)(irq)->payload)
128 #define irq_domain_obj(domain, type)        ((type*)(domain)->object)
129
130 static inline irq_t
131 irq_declare_line(irq_servant callback, int local_irq, void* irq_extra)
132 {
133     return irq_declare(IRQ_LINE, callback, (int)local_irq, irq_extra);
134 }
135
136 static inline irq_t
137 irq_declare_msg(irq_servant callback, 
138                 ptr_t message, ptr_t sideband, void* irq_extra)
139 {
140     irq_t irq;
141     irq = irq_declare(IRQ_MESSAGE, callback, message, irq_extra);
142     irq->msi->sideband = sideband;
143
144     return irq;
145 }
146
147 static inline struct irq_domain*
148 irq_get_domain(struct device* maybe_intc)
149 {
150     struct potens_meta* domain_m;
151
152     domain_m = device_get_potens(maybe_intc, potens(INT_DOMAIN));
153     return domain_m ? get_potens(domain_m, struct irq_domain) : NULL;
154 }
155
156 static inline struct irq_domain*
157 irq_parent_domain(struct irq_domain* domain)
158 {
159     return domain->parent;
160 }
161
162 #endif /* __LUNAIX_IRQ_H */