Rev 1591 | Rev 1625 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1591 | Rev 1595 | ||
---|---|---|---|
Line 154... | Line 154... | ||
154 | 154 | ||
155 | /** Unregister task from irq */ |
155 | /** Unregister task from irq */ |
156 | void ipc_irq_unregister(answerbox_t *box, int irq) |
156 | void ipc_irq_unregister(answerbox_t *box, int irq) |
157 | { |
157 | { |
158 | ipl_t ipl; |
158 | ipl_t ipl; |
- | 159 | int mq = irq + IPC_IRQ_RESERVED_VIRTUAL; |
|
159 | 160 | ||
160 | ipl = interrupts_disable(); |
161 | ipl = interrupts_disable(); |
161 | spinlock_lock(&irq_conns[irq].lock); |
162 | spinlock_lock(&irq_conns[mq].lock); |
162 | if (irq_conns[irq].box == box) { |
163 | if (irq_conns[mq].box == box) { |
163 | irq_conns[irq].box = NULL; |
164 | irq_conns[mq].box = NULL; |
164 | code_free(irq_conns[irq].code); |
165 | code_free(irq_conns[mq].code); |
165 | irq_conns[irq].code = NULL; |
166 | irq_conns[mq].code = NULL; |
166 | } |
167 | } |
167 | 168 | ||
168 | spinlock_unlock(&irq_conns[irq].lock); |
169 | spinlock_unlock(&irq_conns[mq].lock); |
169 | interrupts_restore(ipl); |
170 | interrupts_restore(ipl); |
170 | } |
171 | } |
171 | 172 | ||
172 | /** Register an answerbox as a receiving end of interrupts notifications */ |
173 | /** Register an answerbox as a receiving end of interrupts notifications */ |
173 | int ipc_irq_register(answerbox_t *box, int irq, irq_code_t *ucode) |
174 | int ipc_irq_register(answerbox_t *box, int irq, irq_code_t *ucode) |
174 | { |
175 | { |
175 | ipl_t ipl; |
176 | ipl_t ipl; |
176 | irq_code_t *code; |
177 | irq_code_t *code; |
- | 178 | int mq = irq + IPC_IRQ_RESERVED_VIRTUAL; |
|
177 | 179 | ||
178 | ASSERT(irq_conns); |
180 | ASSERT(irq_conns); |
179 | 181 | ||
180 | if (ucode) { |
182 | if (ucode) { |
181 | code = code_from_uspace(ucode); |
183 | code = code_from_uspace(ucode); |
Line 183... | Line 185... | ||
183 | return EBADMEM; |
185 | return EBADMEM; |
184 | } else |
186 | } else |
185 | code = NULL; |
187 | code = NULL; |
186 | 188 | ||
187 | ipl = interrupts_disable(); |
189 | ipl = interrupts_disable(); |
188 | spinlock_lock(&irq_conns[irq].lock); |
190 | spinlock_lock(&irq_conns[mq].lock); |
189 | 191 | ||
190 | if (irq_conns[irq].box) { |
192 | if (irq_conns[mq].box) { |
191 | spinlock_unlock(&irq_conns[irq].lock); |
193 | spinlock_unlock(&irq_conns[mq].lock); |
192 | interrupts_restore(ipl); |
194 | interrupts_restore(ipl); |
193 | code_free(code); |
195 | code_free(code); |
194 | return EEXISTS; |
196 | return EEXISTS; |
195 | } |
197 | } |
196 | irq_conns[irq].box = box; |
198 | irq_conns[mq].box = box; |
197 | irq_conns[irq].code = code; |
199 | irq_conns[mq].code = code; |
198 | atomic_set(&irq_conns[irq].counter, 0); |
200 | atomic_set(&irq_conns[mq].counter, 0); |
199 | spinlock_unlock(&irq_conns[irq].lock); |
201 | spinlock_unlock(&irq_conns[mq].lock); |
200 | interrupts_restore(ipl); |
202 | interrupts_restore(ipl); |
201 | 203 | ||
202 | return 0; |
204 | return 0; |
203 | } |
205 | } |
204 | 206 | ||
- | 207 | /** Add call to proper answerbox queue |
|
- | 208 | * |
|
- | 209 | * Assume irq_conns[mq].lock is locked */ |
|
- | 210 | static void send_call(int mq, call_t *call) |
|
- | 211 | { |
|
- | 212 | spinlock_lock(&irq_conns[mq].box->irq_lock); |
|
- | 213 | list_append(&call->link, &irq_conns[mq].box->irq_notifs); |
|
- | 214 | spinlock_unlock(&irq_conns[mq].box->irq_lock); |
|
- | 215 | ||
- | 216 | waitq_wakeup(&irq_conns[mq].box->wq, 0); |
|
- | 217 | } |
|
- | 218 | ||
- | 219 | /** Send notification message |
|
- | 220 | * |
|
- | 221 | */ |
|
- | 222 | void ipc_irq_send_msg(int irq, __native a2, __native a3) |
|
- | 223 | { |
|
- | 224 | call_t *call; |
|
- | 225 | int mq = irq + IPC_IRQ_RESERVED_VIRTUAL; |
|
- | 226 | ||
- | 227 | spinlock_lock(&irq_conns[mq].lock); |
|
- | 228 | ||
- | 229 | if (irq_conns[mq].box) { |
|
- | 230 | call = ipc_call_alloc(FRAME_ATOMIC); |
|
- | 231 | if (!call) { |
|
- | 232 | spinlock_unlock(&irq_conns[mq].lock); |
|
- | 233 | return; |
|
- | 234 | } |
|
- | 235 | call->flags |= IPC_CALL_NOTIF; |
|
- | 236 | IPC_SET_METHOD(call->data, IPC_M_INTERRUPT); |
|
- | 237 | IPC_SET_ARG1(call->data, irq); |
|
- | 238 | IPC_SET_ARG2(call->data, a2); |
|
- | 239 | IPC_SET_ARG3(call->data, a3); |
|
- | 240 | ||
- | 241 | send_call(mq, call); |
|
- | 242 | } |
|
- | 243 | spinlock_unlock(&irq_conns[mq].lock); |
|
- | 244 | } |
|
- | 245 | ||
205 | /** Notify process that an irq had happend |
246 | /** Notify process that an irq had happend |
206 | * |
247 | * |
207 | * We expect interrupts to be disabled |
248 | * We expect interrupts to be disabled |
208 | */ |
249 | */ |
209 | void ipc_irq_send_notif(int irq) |
250 | void ipc_irq_send_notif(int irq) |
210 | { |
251 | { |
211 | call_t *call; |
252 | call_t *call; |
- | 253 | int mq = irq + IPC_IRQ_RESERVED_VIRTUAL; |
|
212 | 254 | ||
213 | ASSERT(irq_conns); |
255 | ASSERT(irq_conns); |
214 | spinlock_lock(&irq_conns[irq].lock); |
256 | spinlock_lock(&irq_conns[mq].lock); |
215 | 257 | ||
216 | if (irq_conns[irq].box) { |
258 | if (irq_conns[mq].box) { |
217 | call = ipc_call_alloc(FRAME_ATOMIC); |
259 | call = ipc_call_alloc(FRAME_ATOMIC); |
218 | if (!call) { |
260 | if (!call) { |
219 | spinlock_unlock(&irq_conns[irq].lock); |
261 | spinlock_unlock(&irq_conns[mq].lock); |
220 | return; |
262 | return; |
221 | } |
263 | } |
222 | call->flags |= IPC_CALL_NOTIF; |
264 | call->flags |= IPC_CALL_NOTIF; |
223 | IPC_SET_METHOD(call->data, IPC_M_INTERRUPT); |
265 | IPC_SET_METHOD(call->data, IPC_M_INTERRUPT); |
224 | IPC_SET_ARG1(call->data, irq); |
266 | IPC_SET_ARG1(call->data, irq); |
225 | IPC_SET_ARG3(call->data, atomic_preinc(&irq_conns[irq].counter)); |
267 | IPC_SET_ARG3(call->data, atomic_preinc(&irq_conns[mq].counter)); |
226 | 268 | ||
227 | /* Execute code to handle irq */ |
269 | /* Execute code to handle irq */ |
228 | code_execute(call, irq_conns[irq].code); |
270 | code_execute(call, irq_conns[mq].code); |
229 | 271 | ||
230 | spinlock_lock(&irq_conns[irq].box->irq_lock); |
272 | send_call(mq, call); |
231 | list_append(&call->link, &irq_conns[irq].box->irq_notifs); |
- | |
232 | spinlock_unlock(&irq_conns[irq].box->irq_lock); |
- | |
233 | - | ||
234 | waitq_wakeup(&irq_conns[irq].box->wq, 0); |
- | |
235 | } |
273 | } |
236 | 274 | ||
237 | spinlock_unlock(&irq_conns[irq].lock); |
275 | spinlock_unlock(&irq_conns[mq].lock); |
238 | } |
276 | } |
239 | 277 | ||
240 | 278 | ||
241 | /** Initialize table of interrupt handlers */ |
279 | /** Initialize table of interrupt handlers |
- | 280 | * |
|
- | 281 | * @param irqcount Count of required hardware IRQs to be supported |
|
- | 282 | */ |
|
242 | void ipc_irq_make_table(int irqcount) |
283 | void ipc_irq_make_table(int irqcount) |
243 | { |
284 | { |
244 | int i; |
285 | int i; |
245 | 286 | ||
- | 287 | irqcount += IPC_IRQ_RESERVED_VIRTUAL; |
|
- | 288 | ||
246 | irq_conns_size = irqcount; |
289 | irq_conns_size = irqcount; |
247 | irq_conns = malloc(irqcount * (sizeof(*irq_conns)), 0); |
290 | irq_conns = malloc(irqcount * (sizeof(*irq_conns)), 0); |
248 | for (i=0; i < irqcount; i++) { |
291 | for (i=0; i < irqcount; i++) { |
249 | spinlock_initialize(&irq_conns[i].lock, "irq_ipc_lock"); |
292 | spinlock_initialize(&irq_conns[i].lock, "irq_ipc_lock"); |
250 | irq_conns[i].box = NULL; |
293 | irq_conns[i].box = NULL; |