Subversion Repositories HelenOS

Rev

Rev 1260 | Rev 1342 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1260 Rev 1281
Line 42... Line 42...
42
#include <debug.h>
42
#include <debug.h>
43
 
43
 
44
#include <print.h>
44
#include <print.h>
45
#include <proc/thread.h>
45
#include <proc/thread.h>
46
#include <arch/interrupt.h>
46
#include <arch/interrupt.h>
-
 
47
#include <ipc/irq.h>
47
 
48
 
48
/* Open channel that is assigned automatically to new tasks */
49
/* Open channel that is assigned automatically to new tasks */
49
answerbox_t *ipc_phone_0 = NULL;
50
answerbox_t *ipc_phone_0 = NULL;
50
 
51
 
51
static slab_cache_t *ipc_call_slab;
52
static slab_cache_t *ipc_call_slab;
52
 
53
 
53
typedef struct {
-
 
54
    SPINLOCK_DECLARE(lock);
-
 
55
    answerbox_t *box;
-
 
56
} ipc_irq_t;
-
 
57
 
-
 
58
static ipc_irq_t *irq_conns = NULL;
-
 
59
static int irq_conns_size;
-
 
60
 
-
 
61
/* Initialize new call */
54
/* Initialize new call */
62
static void _ipc_call_init(call_t *call)
55
static void _ipc_call_init(call_t *call)
63
{
56
{
64
    memsetb((__address)call, sizeof(*call), 0);
57
    memsetb((__address)call, sizeof(*call), 0);
65
    call->callerbox = &TASK->answerbox;
58
    call->callerbox = &TASK->answerbox;
Line 326... Line 319...
326
    spinlock_lock(&box->lock);
319
    spinlock_lock(&box->lock);
327
    if (!list_empty(&box->irq_notifs)) {
320
    if (!list_empty(&box->irq_notifs)) {
328
        ipl = interrupts_disable();
321
        ipl = interrupts_disable();
329
        spinlock_lock(&box->irq_lock);
322
        spinlock_lock(&box->irq_lock);
330
 
323
 
331
        request = list_get_instance(box->answers.next, call_t, list);
324
        request = list_get_instance(box->irq_notifs.next, call_t, list);
332
        list_remove(&request->list);
325
        list_remove(&request->list);
333
 
326
 
334
        spinlock_unlock(&box->irq_lock);
327
        spinlock_unlock(&box->irq_lock);
335
        interrupts_restore(ipl);
328
        interrupts_restore(ipl);
336
    } else if (!list_empty(&box->answers)) {
329
    } else if (!list_empty(&box->answers)) {
Line 368... Line 361...
368
        IPC_SET_RETVAL(call->data, EHANGUP);
361
        IPC_SET_RETVAL(call->data, EHANGUP);
369
        _ipc_answer_free_call(call);
362
        _ipc_answer_free_call(call);
370
    }
363
    }
371
}
364
}
372
 
365
 
373
/** Disconnect all irq's notifications
-
 
374
 *
-
 
375
 * TODO: It may be better to do some linked list, so that
-
 
376
 *       we wouldn't need to go through whole array every cleanup
-
 
377
 */
-
 
378
static void ipc_irq_cleanup(answerbox_t *box)
-
 
379
{
-
 
380
    int i;
-
 
381
    ipl_t ipl;
-
 
382
   
-
 
383
    for (i=0; i < irq_conns_size; i++) {
-
 
384
        ipl = interrupts_disable();
-
 
385
        spinlock_lock(&irq_conns[i].lock);
-
 
386
        if (irq_conns[i].box == box)
-
 
387
            irq_conns[i].box = NULL;
-
 
388
        spinlock_unlock(&irq_conns[i].lock);
-
 
389
        interrupts_restore(ipl);
-
 
390
    }
-
 
391
}
-
 
392
 
-
 
393
/** Cleans up all IPC communication of the given task
366
/** Cleans up all IPC communication of the given task
394
 *
367
 *
395
 *
368
 *
396
 */
369
 */
397
void ipc_cleanup(task_t *task)
370
void ipc_cleanup(task_t *task)
Line 441... Line 414...
441
        atomic_dec(&task->active_calls);
414
        atomic_dec(&task->active_calls);
442
        ipc_call_free(call);
415
        ipc_call_free(call);
443
    }
416
    }
444
}
417
}
445
 
418
 
446
/** Initialize table of interrupt handlers */
-
 
447
static void ipc_irq_make_table(int irqcount)
-
 
448
{
-
 
449
    int i;
-
 
450
 
-
 
451
    irq_conns_size = irqcount;
-
 
452
    irq_conns = malloc(irqcount * (sizeof(*irq_conns)), 0);
-
 
453
    for (i=0; i < irqcount; i++) {
-
 
454
        spinlock_initialize(&irq_conns[i].lock, "irq_ipc_lock");
-
 
455
        irq_conns[i].box = NULL;
-
 
456
    }
-
 
457
}
-
 
458
 
-
 
459
void ipc_irq_unregister(answerbox_t *box, int irq)
-
 
460
{
-
 
461
    ipl_t ipl;
-
 
462
 
-
 
463
    ipl = interrupts_disable();
-
 
464
    spinlock_lock(&irq_conns[irq].lock);
-
 
465
    if (irq_conns[irq].box == box)
-
 
466
        irq_conns[irq].box = NULL;
-
 
467
 
-
 
468
    spinlock_unlock(&irq_conns[irq].lock);
-
 
469
    interrupts_restore(ipl);
-
 
470
}
-
 
471
 
-
 
472
/** Register an answerbox as a receiving end of interrupts notifications */
-
 
473
int ipc_irq_register(answerbox_t *box, int irq)
-
 
474
{
-
 
475
    ipl_t ipl;
-
 
476
 
-
 
477
    ASSERT(irq_conns);
-
 
478
 
-
 
479
    ipl = interrupts_disable();
-
 
480
    spinlock_lock(&irq_conns[irq].lock);
-
 
481
 
-
 
482
    if (irq_conns[irq].box) {
-
 
483
        spinlock_unlock(&irq_conns[irq].lock);
-
 
484
        interrupts_restore(ipl);
-
 
485
        return EEXISTS;
-
 
486
    }
-
 
487
    irq_conns[irq].box = box;
-
 
488
    spinlock_unlock(&irq_conns[irq].lock);
-
 
489
    interrupts_restore(ipl);
-
 
490
 
-
 
491
    return 0;
-
 
492
}
-
 
493
 
-
 
494
/** Notify process that an irq had happend
-
 
495
 *
-
 
496
 * We expect interrupts to be disabled
-
 
497
 */
-
 
498
void ipc_irq_send_notif(int irq)
-
 
499
{
-
 
500
    call_t *call;
-
 
501
 
-
 
502
    ASSERT(irq_conns);
-
 
503
    spinlock_lock(&irq_conns[irq].lock);
-
 
504
 
-
 
505
    if (irq_conns[irq].box) {
-
 
506
        call = ipc_call_alloc(FRAME_ATOMIC);
-
 
507
        call->flags |= IPC_CALL_NOTIF;
-
 
508
        IPC_SET_METHOD(call->data, IPC_M_INTERRUPT);
-
 
509
        IPC_SET_ARG1(call->data, irq);
-
 
510
 
-
 
511
        spinlock_lock(&irq_conns[irq].box->irq_lock);
-
 
512
        list_append(&call->list, &irq_conns[irq].box->irq_notifs);
-
 
513
        spinlock_unlock(&irq_conns[irq].box->irq_lock);
-
 
514
 
-
 
515
        waitq_wakeup(&irq_conns[irq].box->wq, 0);
-
 
516
    }
-
 
517
       
-
 
518
    spinlock_unlock(&irq_conns[irq].lock);
-
 
519
}
-
 
520
 
419
 
521
/** Initilize ipc subsystem */
420
/** Initilize ipc subsystem */
522
void ipc_init(void)
421
void ipc_init(void)
523
{
422
{
524
    ipc_call_slab = slab_cache_create("ipc_call",
423
    ipc_call_slab = slab_cache_create("ipc_call",