physical page list mapping
[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 <lunaix/status.h>
8 #include <asm/hart.h>
9
10 #define IRQ_VECTOR_UNSET    ((unsigned)-1)
11
12 struct irq_domain;
13 typedef struct irq_object* irq_t;
14 typedef void (*irq_servant)(irq_t, const struct hart_state*);
15
16 struct irq_domain_ops
17 {
18     int
19     (*install_irq)(struct irq_domain*, irq_t);
20
21     int
22     (*map_irq)(struct irq_domain*, irq_t, void* irq_extra);
23
24     int
25     (*remove_irq)(struct irq_domain*, irq_t);
26 };
27
28 struct irq_domain
29 {
30     POTENS_META;
31
32     struct llist_header list;
33
34     struct irq_domain* parent;
35     struct btrie irq_map;
36     const struct irq_domain_ops* ops;
37     void* object;
38 };
39
40 enum irq_type
41 {
42     IRQ_DIRECT,
43     IRQ_LINE,
44     IRQ_MESSAGE
45 };
46
47 enum irq_trigger
48 {
49     IRQ_EDGE = 0,
50     IRQ_LEVEL
51 };
52
53 struct irq_line_wire
54 {
55     ptr_t domain_local;
56     ptr_t domain_mapped;
57 };
58
59 struct irq_msi_wire
60 {
61     ptr_t message;
62     ptr_t sideband;
63     ptr_t wr_addr;
64 };
65
66 struct irq_object
67 {    
68     enum irq_type type;
69     enum irq_trigger trig;
70     unsigned int vector;
71     
72     union {
73         struct irq_line_wire* line;
74         struct irq_msi_wire* msi;
75     };
76
77     irq_servant serve;
78     void* payload;
79
80     struct irq_domain* domain;
81     int ref;
82 };
83
84 struct irq_domain*
85 irq_create_domain(struct device* intc_dev, const struct irq_domain_ops* ops);
86
87 struct irq_domain*
88 irq_owning_domain(struct device* dev);
89
90 int
91 irq_attach_domain(struct irq_domain* parent, struct irq_domain* child);
92
93 irq_t
94 irq_declare(enum irq_type, irq_servant, ptr_t);
95
96 void
97 irq_revoke(irq_t);
98
99 int
100 irq_assign(struct irq_domain* domain, irq_t, void*);
101
102 irq_t
103 irq_find(struct irq_domain* domain, int local_irq);
104
105 void
106 irq_record(struct irq_domain* domain, irq_t irq);
107
108 void
109 irq_set_default_domain(struct irq_domain*);
110
111 struct irq_domain*
112 irq_get_default_domain();
113
114 int
115 irq_forward_install(struct irq_domain* current, irq_t irq);
116
117 static inline int
118 irq_alloc_id(struct irq_domain* domain, irq_t irq, int start, int end)
119 {
120     unsigned int irq_id;
121
122     if (irq->vector != IRQ_VECTOR_UNSET) {
123         return EEXIST;
124     }
125     
126     irq_id = (unsigned int)btrie_map(&domain->irq_map, start, end, irq);
127     if (irq_id == -1U) {
128         return E2BIG;
129     }
130
131     irq->vector = irq;
132     return 0;
133 }
134
135 static inline void
136 irq_serve(irq_t irq, struct hart_state* state)
137 {
138     irq->serve(irq, state);
139 }
140
141 static inline void
142 irq_set_servant(irq_t irq, irq_servant callback)
143 {
144     irq->serve = callback;
145 }
146
147 static inline void
148 irq_bind_vector(irq_t irq, int vector)
149 {
150     irq->vector = vector;
151 }
152
153 static inline void
154 irq_set_payload(irq_t irq, void* payload)
155 {
156     irq->payload = payload;
157 }
158
159 static inline void
160 irq_set_domain_object(struct irq_domain* domain, void* obj)
161 {
162     domain->object = obj;
163 }
164
165 #define irq_payload(irq, type)              ((type*)(irq)->payload)
166 #define irq_domain_obj(domain, type)        ((type*)(domain)->object)
167
168 static inline irq_t
169 irq_declare_line(irq_servant callback, int local_irq)
170 {
171     return irq_declare(IRQ_LINE, callback, (int)local_irq);
172 }
173
174 static inline irq_t
175 irq_declare_msg(irq_servant callback, 
176                 ptr_t message, ptr_t sideband)
177 {
178     irq_t irq;
179     irq = irq_declare(IRQ_MESSAGE, callback, message);
180     irq->msi->sideband = sideband;
181
182     return irq;
183 }
184
185 static inline irq_t
186 irq_declare_direct(irq_servant callback)
187 {
188     return irq_declare(IRQ_DIRECT, callback, 0);
189 }
190
191 static inline struct irq_domain*
192 irq_get_domain(struct device* maybe_intc)
193 {
194     struct potens_meta* domain_m;
195
196     domain_m = device_get_potens(maybe_intc, potens(INT_DOMAIN));
197     return domain_m ? get_potens(domain_m, struct irq_domain) : NULL;
198 }
199
200 static inline struct irq_domain*
201 irq_parent_domain(struct irq_domain* domain)
202 {
203     return domain->parent;
204 }
205
206 #endif /* __LUNAIX_IRQ_H */