Unifying External Interrupt System (#51)
[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 #define IRQ_VECTOR_UNSET    ((unsigned)-1)
10
11 struct irq_domain;
12 typedef struct irq_object* irq_t;
13 typedef void (*irq_servant)(irq_t, const struct hart_state*);
14
15 struct irq_domain_ops
16 {
17     int
18     (*install_irq)(struct irq_domain*, irq_t);
19
20     int
21     (*map_irq)(struct irq_domain*, irq_t, void* irq_extra);
22
23     int
24     (*remove_irq)(struct irq_domain*, irq_t);
25 };
26
27 struct irq_domain
28 {
29     POTENS_META;
30
31     struct llist_header list;
32
33     struct irq_domain* parent;
34     struct btrie irq_map;
35     const struct irq_domain_ops* ops;
36     void* object;
37 };
38
39 enum irq_type
40 {
41     IRQ_DIRECT,
42     IRQ_LINE,
43     IRQ_MESSAGE
44 };
45
46 struct irq_line_wire
47 {
48     ptr_t domain_local;
49     ptr_t domain_mapped;
50 };
51
52 struct irq_msi_wire
53 {
54     ptr_t message;
55     ptr_t sideband;
56     ptr_t wr_addr;
57 };
58
59 struct irq_object
60 {    
61     enum irq_type type;
62     unsigned int vector;
63     
64     union {
65         struct irq_line_wire* line;
66         struct irq_msi_wire* msi;
67     };
68
69     irq_servant serve;
70     void* payload;
71
72     struct irq_domain* domain;
73     int ref;
74 };
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);
87
88 void
89 irq_revoke(irq_t);
90
91 int
92 irq_assign(struct irq_domain* domain, irq_t, void*);
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_servant(irq_t irq, irq_servant callback)
117 {
118     irq->serve = callback;
119 }
120
121 static inline void
122 irq_bind_vector(irq_t irq, int vector)
123 {
124     irq->vector = vector;
125 }
126
127 static inline void
128 irq_set_payload(irq_t irq, void* payload)
129 {
130     irq->payload = payload;
131 }
132
133 static inline void
134 irq_set_domain_object(struct irq_domain* domain, void* obj)
135 {
136     domain->object = obj;
137 }
138
139 #define irq_payload(irq, type)              ((type*)(irq)->payload)
140 #define irq_domain_obj(domain, type)        ((type*)(domain)->object)
141
142 static inline irq_t
143 irq_declare_line(irq_servant callback, int local_irq)
144 {
145     return irq_declare(IRQ_LINE, callback, (int)local_irq);
146 }
147
148 static inline irq_t
149 irq_declare_msg(irq_servant callback, 
150                 ptr_t message, ptr_t sideband)
151 {
152     irq_t irq;
153     irq = irq_declare(IRQ_MESSAGE, callback, message);
154     irq->msi->sideband = sideband;
155
156     return irq;
157 }
158
159 static inline irq_t
160 irq_declare_direct(irq_servant callback)
161 {
162     return irq_declare(IRQ_DIRECT, callback, 0);
163 }
164
165 static inline struct irq_domain*
166 irq_get_domain(struct device* maybe_intc)
167 {
168     struct potens_meta* domain_m;
169
170     domain_m = device_get_potens(maybe_intc, potens(INT_DOMAIN));
171     return domain_m ? get_potens(domain_m, struct irq_domain) : NULL;
172 }
173
174 static inline struct irq_domain*
175 irq_parent_domain(struct irq_domain* domain)
176 {
177     return domain->parent;
178 }
179
180 #endif /* __LUNAIX_IRQ_H */