Changeset 5626277 in mainline


Ignore:
Timestamp:
2006-04-29T22:12:40Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
51a7dc1
Parents:
407862e
Message:

Added support for IRQ notifiactions.

  • seems to work correctly on ia32, amd64
  • the mips kbd probably lowers interrupts when the char is read from the port, we will have to find a way how to deal with it.
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • arch/amd64/src/interrupt.c

    r407862e r5626277  
    4545#include <synch/spinlock.h>
    4646#include <arch/ddi/ddi.h>
     47#include <interrupt.h>
     48#include <ipc/sysipc.h>
    4749
    4850void print_info_errcode(int n, istate_t *istate)
     
    154156
    155157}
     158
     159static void ipc_int(int n, istate_t *istate)
     160{
     161        trap_virtual_eoi();
     162        ipc_irq_send_notif(n-IVT_IRQBASE);
     163}
     164
     165
     166/* Reregister irq to be IPC-ready */
     167void irq_ipc_bind_arch(__native irq)
     168{
     169        if (irq == IRQ_CLK)
     170                return;
     171        exc_register(IVT_IRQBASE+irq, "ipc_int", ipc_int);
     172}
  • arch/ia32/src/interrupt.c

    r407862e r5626277  
    4444#include <synch/spinlock.h>
    4545#include <arch/ddi/ddi.h>
     46#include <ipc/sysipc.h>
     47#include <interrupt.h>
    4648
    4749/*
     
    185187
    186188}
     189
     190static void ipc_int(int n, istate_t *istate)
     191{
     192        trap_virtual_eoi();
     193        ipc_irq_send_notif(n-IVT_IRQBASE);
     194}
     195
     196
     197/* Reregister irq to be IPC-ready */
     198void irq_ipc_bind_arch(__native irq)
     199{
     200        if (irq == IRQ_CLK)
     201                return;
     202        exc_register(IVT_IRQBASE+irq, "ipc_int", ipc_int);
     203}
  • arch/mips32/include/interrupt.h

    r407862e r5626277  
    3434#define IVT_ITEMS   40
    3535#define INT_OFFSET  32
     36#define IRQ_COUNT   8
    3637
    3738#define int_register(it, name, handler) exc_register(((it)+INT_OFFSET),name,handler)
  • arch/mips32/src/interrupt.c

    r407862e r5626277  
    3434#include <time/clock.h>
    3535#include <arch/drivers/arc.h>
     36
     37#include <ipc/sysipc.h>
    3638
    3739/** Disable interrupts.
     
    8486{
    8587        cp0_cause_write(cp0_cause_read() & ~(1 << 8)); /* clear SW0 interrupt */
     88        ipc_irq_send_notif(0);
    8689}
    8790
     
    8992{
    9093        cp0_cause_write(cp0_cause_read() & ~(1 << 9)); /* clear SW1 interrupt */
     94        ipc_irq_send_notif(1);
    9195}
    9296
     
    98102        int_register(1, "swint1", swint1);
    99103}
     104
     105#include <print.h>
     106static void ipc_int(int n, istate_t *istate)
     107{
     108        ipc_irq_send_notif(n-INT_OFFSET);
     109}
     110
     111/* Reregister irq to be IPC-ready */
     112void irq_ipc_bind_arch(__native irq)
     113{
     114        /* Do not allow to redefine timer */
     115        /* Swint0, Swint1 are already handled */
     116        if (irq == TIMER_IRQ || irq < 2)
     117                return;
     118        int_register(irq, "ipc_int", ipc_int);
     119}
  • generic/include/errno.h

    r407862e r5626277  
    4141                        * to close the connection. Used by answerbox
    4242                        * to close the connection.  */
     43#define EEXISTS    -8  /* Entry already exists */
    4344
    4445#endif
  • generic/include/ipc/ipc.h

    r407862e r5626277  
    4444#define IPC_CALL_FORWARDED      (1<<3) /* Call was forwarded */
    4545#define IPC_CALL_CONN_ME_TO     (1<<4) /* Identify connect_me_to */
     46#define IPC_CALL_NOTIF          (1<<5) /* Interrupt notification */
    4647
    4748/* Flags for ipc_wait_for_call */
     
    120121 */
    121122#define IPC_M_PHONE_HUNGUP      3
     123/** Interrupt notification */
     124#define IPC_M_INTERRUPT         4
    122125
    123126
     
    155158
    156159        link_t answers;          /**< Answered calls */
     160
     161        SPINLOCK_DECLARE(irq_lock);
     162        link_t irq_notifs;       /**< Notifications from IRQ handlers */
    157163};
    158164
     
    196202extern void ipc_phone_connect(phone_t *phone, answerbox_t *box);
    197203extern void ipc_call_free(call_t *call);
    198 extern call_t * ipc_call_alloc(void);
     204extern call_t * ipc_call_alloc(int flags);
    199205extern void ipc_answerbox_init(answerbox_t *box);
    200206extern void ipc_call_static_init(call_t *call);
     
    205211extern void ipc_backsend_err(phone_t *phone, call_t *call, __native err);
    206212
     213extern int ipc_irq_register(answerbox_t *box, int irq);
     214extern void ipc_irq_send_notif(int irq);
     215extern void ipc_irq_unregister(answerbox_t *box, int irq);
     216
     217
    207218extern answerbox_t *ipc_phone_0;
    208219
  • generic/include/ipc/sysipc.h

    r407862e r5626277  
    3030#define __SYSIPC_H__
    3131
     32#include <ipc/ipc.h>
     33
    3234__native sys_ipc_call_sync_fast(__native phoneid, __native method,
    3335                                __native arg1, ipc_data_t *data);
     
    4446                              __native method, __native arg1);
    4547__native sys_ipc_hangup(int phoneid);
     48__native sys_ipc_register_irq(__native irq);
     49__native sys_ipc_unregister_irq(__native irq);
    4650
     51void irq_ipc_bind_arch(__native irq);
    4752
    4853#endif
  • generic/include/syscall/syscall.h

    r407862e r5626277  
    5252        SYS_IPC_WAIT,
    5353        SYS_IPC_HANGUP,
     54        SYS_IPC_REGISTER_IRQ,
     55        SYS_IPC_UNREGISTER_IRQ,
    5456        SYS_MAP_PHYSMEM,
    5557        SYS_IOSPACE_ENABLE,
  • generic/src/ipc/ipc.c

    r407862e r5626277  
    4444#include <print.h>
    4545#include <proc/thread.h>
     46#include <arch/interrupt.h>
    4647
    4748/* Open channel that is assigned automatically to new tasks */
     
    4950
    5051static slab_cache_t *ipc_call_slab;
     52
     53typedef struct {
     54        SPINLOCK_DECLARE(lock);
     55        answerbox_t *box;
     56} ipc_irq_t;
     57
     58static ipc_irq_t *irq_conns = NULL;
     59static int irq_conns_size;
    5160
    5261/* Initialize new call */
     
    6271 * The call is initialized, so that the reply will be directed
    6372 * to TASK->answerbox
    64  */
    65 call_t * ipc_call_alloc(void)
     73 *
     74 * @param flags Parameters for slab_alloc (ATOMIC, etc.)
     75 */
     76call_t * ipc_call_alloc(int flags)
    6677{
    6778        call_t *call;
    6879
    69         call = slab_alloc(ipc_call_slab, 0);
     80        call = slab_alloc(ipc_call_slab, flags);
    7081        _ipc_call_init(call);
    7182
     
    91102{
    92103        spinlock_initialize(&box->lock, "ipc_box_lock");
     104        spinlock_initialize(&box->irq_lock, "ipc_box_irqlock");
    93105        waitq_initialize(&box->wq);
    94106        list_initialize(&box->connected_phones);
     
    96108        list_initialize(&box->dispatched_calls);
    97109        list_initialize(&box->answers);
     110        list_initialize(&box->irq_notifs);
    98111        box->task = TASK;
    99112}
     
    262275        spinlock_unlock(&box->lock);
    263276
    264         call = ipc_call_alloc();
     277        call = ipc_call_alloc(0);
    265278        IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP);
    266279        call->flags |= IPC_CALL_DISCARD_ANSWER;
     
    302315{
    303316        call_t *request;
     317        ipl_t ipl;
    304318
    305319restart:     
     
    311325       
    312326        spinlock_lock(&box->lock);
    313         if (!list_empty(&box->answers)) {
     327        if (!list_empty(&box->irq_notifs)) {
     328                ipl = interrupts_disable();
     329                spinlock_lock(&box->irq_lock);
     330
     331                request = list_get_instance(box->answers.next, call_t, list);
     332                list_remove(&request->list);
     333
     334                spinlock_unlock(&box->irq_lock);
     335                interrupts_restore(ipl);
     336        } else if (!list_empty(&box->answers)) {
    314337                /* Handle asynchronous answers */
    315338                request = list_get_instance(box->answers.next, call_t, list);
     
    334357}
    335358
    336 /** Initilize ipc subsystem */
    337 void ipc_init(void)
    338 {
    339         ipc_call_slab = slab_cache_create("ipc_call",
    340                                           sizeof(call_t),
    341                                           0,
    342                                           NULL, NULL, 0);
    343 }
    344 
    345359/** Answer all calls from list with EHANGUP msg */
    346360static void ipc_cleanup_call_list(link_t *lst)
     
    354368                IPC_SET_RETVAL(call->data, EHANGUP);
    355369                _ipc_answer_free_call(call);
     370        }
     371}
     372
     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 */
     378static 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);
    356390        }
    357391}
     
    370404        for (i=0;i < IPC_MAX_PHONES; i++)
    371405                ipc_phone_hangup(&task->phones[i]);
     406
     407        /* Disconnect all connected irqs */
     408        ipc_irq_cleanup(&task->answerbox);
    372409
    373410        /* Disconnect all phones connected to our answerbox */
     
    406443        }
    407444}
     445
     446/** Initialize table of interrupt handlers */
     447static 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
     459void 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 */
     473int 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 */
     498void 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
     521/** Initilize ipc subsystem */
     522void ipc_init(void)
     523{
     524        ipc_call_slab = slab_cache_create("ipc_call",
     525                                          sizeof(call_t),
     526                                          0,
     527                                          NULL, NULL, 0);
     528        ipc_irq_make_table(IRQ_COUNT);
     529}
     530
  • generic/src/ipc/sysipc.c

    r407862e r5626277  
    3737#include <ipc/sysipc.h>
    3838#include <ipc/ipcrsc.h>
    39 
     39#include <arch/interrupt.h>
    4040
    4141#include <print.h>
     
    275275        GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL);
    276276
    277         call = ipc_call_alloc();
     277        call = ipc_call_alloc(0);
    278278        IPC_SET_METHOD(call->data, method);
    279279        IPC_SET_ARG1(call->data, arg1);
     
    303303        GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL);
    304304
    305         call = ipc_call_alloc();
     305        call = ipc_call_alloc(0);
    306306        copy_from_uspace(&call->data.args, &data->args, sizeof(call->data.args));
    307307        if (!(res=request_preprocess(call)))
     
    442442                return 0;
    443443
     444        if (call->flags & IPC_CALL_NOTIF) {
     445                ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
     446                STRUCT_TO_USPACE(&calldata->args, &call->data.args);
     447                ipc_call_free(call);
     448               
     449                return ((__native)call) | IPC_CALLID_NOTIFICATION;
     450        }
     451
    444452        if (call->flags & IPC_CALL_ANSWERED) {
    445453                process_answer(call);
     
    468476        return (__native)call;
    469477}
     478
     479/** Connect irq handler to task */
     480__native sys_ipc_register_irq(__native irq)
     481{
     482        if (irq >= IRQ_COUNT)
     483                return -ELIMIT;
     484
     485        irq_ipc_bind_arch(irq);
     486        return ipc_irq_register(&TASK->answerbox, irq);
     487}
     488
     489/* Disconnect irq handler from task */
     490__native sys_ipc_unregister_irq(__native irq)
     491{
     492        if (irq >= IRQ_COUNT)
     493                return -ELIMIT;
     494
     495        ipc_irq_unregister(&TASK->answerbox, irq);
     496
     497        return 0;
     498}
  • generic/src/syscall/syscall.c

    r407862e r5626277  
    9797        sys_ipc_wait_for_call,
    9898        sys_ipc_hangup,
    99        
     99        sys_ipc_register_irq,
     100        sys_ipc_unregister_irq,
     101
    100102        /* DDI related syscalls. */
    101103        sys_physmem_map,
Note: See TracChangeset for help on using the changeset viewer.