Subversion Repositories HelenOS

Rev

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;