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; |