fc01e9438423cc4598dbd5a8f0b06bbdc3399920
[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     void* irq_extra;
74     int ref;
75 };
76
77 struct irq_domain*
78 irq_create_domain(struct device* intc_dev, const struct irq_domain_ops* ops);
79
80 struct irq_domain*
81 irq_owning_domain(struct device* dev);
82
83 int
84 irq_attach_domain(struct irq_domain* parent, struct irq_domain* child);
85
86 irq_t
87 irq_declare(enum irq_type, irq_servant, ptr_t, void*);
88
89 void
90 irq_revoke(irq_t);
91
92 int
93 irq_assign(struct irq_domain* domain, irq_t);
94
95 irq_t
96 irq_find(struct irq_domain* domain, int local_irq);
97
98 void
99 irq_record(struct irq_domain* domain, irq_t irq);
100
101 void
102 irq_set_default_domain(struct irq_domain*);
103
104 struct irq_domain*
105 irq_get_default_domain();
106
107 int
108 irq_forward_install(struct irq_domain* current, irq_t irq);
109
110 static inline void
111 irq_serve(irq_t irq, struct hart_state* state)
112 {
113     irq->serve(irq, state);
114 }
115
116 static inline void
117 irq_set_servant(irq_t irq, irq_servant callback)
118 {
119     irq->serve = callback;
120 }
121
122 static inline void
123 irq_bind_vector(irq_t irq, int vector)
124 {
125     irq->vector = vector;
126 }
127
128 static inline void
129 irq_set_payload(irq_t irq, void* payload)
130 {
131     irq->payload = payload;
132 }
133
134 static inline void
135 irq_set_domain_object(struct irq_domain* domain, void* obj)
136 {
137     domain->object = obj;
138 }
139
140 #define irq_payload(irq, type)              ((type*)(irq)->payload)
141 #define irq_domain_obj(domain, type)        ((type*)(domain)->object)
142
143 static inline irq_t
144 irq_declare_line(irq_servant callback, int local_irq, void* irq_extra)
145 {
146     return irq_declare(IRQ_LINE, callback, (int)local_irq, irq_extra);
147 }
148
149 static inline irq_t
150 irq_declare_msg(irq_servant callback, 
151                 ptr_t message, ptr_t sideband, void* irq_extra)
152 {
153     irq_t irq;
154     irq = irq_declare(IRQ_MESSAGE, callback, message, irq_extra);
155     irq->msi->sideband = sideband;
156
157     return irq;
158 }
159
160 static inline irq_t
161 irq_declare_direct(irq_servant callback)
162 {
163     return irq_declare(IRQ_DIRECT, callback, 0, NULL);
164 }
165
166 static inline struct irq_domain*
167 irq_get_domain(struct device* maybe_intc)
168 {
169     struct potens_meta* domain_m;
170
171     domain_m = device_get_potens(maybe_intc, potens(INT_DOMAIN));
172     return domain_m ? get_potens(domain_m, struct irq_domain) : NULL;
173 }
174
175 static inline struct irq_domain*
176 irq_parent_domain(struct irq_domain* domain)
177 {
178     return domain->parent;
179 }
180
181 #endif /* __LUNAIX_IRQ_H */