Changeset 2b017ba in mainline for kernel/generic/src/ipc/irq.c


Ignore:
Timestamp:
2006-10-16T20:51:55Z (19 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5f9b4d9a
Parents:
e3890b3f
Message:

Replace the old IRQ dispatcher and IPC notifier with new implementation.
Note that all architectures except for sparc64 are now broken
and don't even compile.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/ipc/irq.c

    re3890b3f r2b017ba  
    11/*
    22 * Copyright (C) 2006 Ondrej Palkovsky
     3 * Copyright (C) 2006 Jakub Jermar
    34 * All rights reserved.
    45 *
     
    4041 *
    4142 * The structure of a notification message is as follows:
    42  * - METHOD: interrupt number
     43 * - METHOD: method as registered by the SYS_IPC_REGISTER_IRQ syscall
    4344 * - ARG1: payload modified by a 'top-half' handler
    44  * - ARG2: payload
    45  * - ARG3: payload
     45 * - ARG2: payload modified by a 'top-half' handler
     46 * - ARG3: payload modified by a 'top-half' handler
    4647 * - in_phone_hash: interrupt counter (may be needed to assure correct order
    4748 *         in multithreaded drivers)
     
    5152#include <mm/slab.h>
    5253#include <errno.h>
     54#include <ddi/irq.h>
    5355#include <ipc/ipc.h>
    5456#include <ipc/irq.h>
    55 #include <atomic.h>
    5657#include <syscall/copy.h>
    5758#include <console/console.h>
    5859#include <print.h>
    5960
    60 typedef struct {
    61         SPINLOCK_DECLARE(lock);
    62         answerbox_t *box;
    63         irq_code_t *code;
    64         atomic_t counter;
    65 } ipc_irq_t;
    66 
    67 
    68 static ipc_irq_t *irq_conns = NULL;
    69 static int irq_conns_size;
    70 
    71 
    72 /* Execute code associated with IRQ notification */
     61/** Execute code associated with IRQ notification.
     62 *
     63 * @param call Notification call.
     64 * @param code Top-half pseudocode.
     65 */
    7366static void code_execute(call_t *call, irq_code_t *code)
    7467{
     
    169162}
    170163
    171 /** Unregister task from irq */
    172 void ipc_irq_unregister(answerbox_t *box, int irq)
     164/** Unregister task from IRQ notification.
     165 *
     166 * @param box Answerbox associated with the notification.
     167 * @param inr IRQ numbe.
     168 * @param devno Device number.
     169 */
     170void ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno)
    173171{
    174172        ipl_t ipl;
    175         int mq = irq + IPC_IRQ_RESERVED_VIRTUAL;
     173        irq_t *irq;
    176174
    177175        ipl = interrupts_disable();
    178         spinlock_lock(&irq_conns[mq].lock);
    179         if (irq_conns[mq].box == box) {
    180                 irq_conns[mq].box = NULL;
    181                 code_free(irq_conns[mq].code);
    182                 irq_conns[mq].code = NULL;
    183         }
    184 
    185         spinlock_unlock(&irq_conns[mq].lock);
     176        irq = irq_find_and_lock(inr, devno);
     177        if (irq) {
     178                if (irq->notif_cfg.answerbox == box) {
     179                        code_free(irq->notif_cfg.code);
     180                        irq->notif_cfg.code = NULL;
     181                        irq->notif_cfg.answerbox = NULL;
     182                        irq->notif_cfg.method = 0;
     183                        irq->notif_cfg.counter = 0;
     184                        spinlock_unlock(&irq->lock);
     185                }
     186        }
    186187        interrupts_restore(ipl);
    187188}
    188189
    189 /** Register an answerbox as a receiving end of interrupts notifications */
    190 int ipc_irq_register(answerbox_t *box, int irq, irq_code_t *ucode)
     190/** Register an answerbox as a receiving end for IRQ notifications.
     191 *
     192 * @param box Receiving answerbox.
     193 * @param inr IRQ number.
     194 * @param devno Device number.
     195 * @param method Method to be associated with the notification.
     196 * @param ucode Uspace pointer to top-half pseudocode.
     197 *
     198 * @return EBADMEM, ENOENT or EEXISTS on failure or 0 on success.
     199 */
     200int
     201ipc_irq_register(answerbox_t *box, inr_t inr, devno_t devno, unative_t method, irq_code_t *ucode)
    191202{
    192203        ipl_t ipl;
    193204        irq_code_t *code;
    194         int mq = irq + IPC_IRQ_RESERVED_VIRTUAL;
    195 
    196         ASSERT(irq_conns);
     205        irq_t *irq;
    197206
    198207        if (ucode) {
     
    204213
    205214        ipl = interrupts_disable();
    206         spinlock_lock(&irq_conns[mq].lock);
    207 
    208         if (irq_conns[mq].box) {
    209                 spinlock_unlock(&irq_conns[mq].lock);
     215        irq = irq_find_and_lock(inr, devno);
     216        if (!irq) {
     217                interrupts_restore(ipl);
     218                code_free(code);
     219                return ENOENT;
     220        }
     221       
     222        if (irq->notif_cfg.answerbox) {
     223                spinlock_unlock(&irq->lock);
    210224                interrupts_restore(ipl);
    211225                code_free(code);
    212226                return EEXISTS;
    213227        }
    214         irq_conns[mq].box = box;
    215         irq_conns[mq].code = code;
    216         atomic_set(&irq_conns[mq].counter, 0);
    217         spinlock_unlock(&irq_conns[mq].lock);
     228       
     229        irq->notif_cfg.answerbox = box;
     230        irq->notif_cfg.method = method;
     231        irq->notif_cfg.code = code;
     232        irq->notif_cfg.counter = 0;
     233        spinlock_unlock(&irq->lock);
    218234        interrupts_restore(ipl);
    219235
     
    221237}
    222238
    223 /** Add call to proper answerbox queue
    224  *
    225  * Assume irq_conns[mq].lock is locked */
    226 static void send_call(int mq, call_t *call)
    227 {
    228         spinlock_lock(&irq_conns[mq].box->irq_lock);
    229         list_append(&call->link, &irq_conns[mq].box->irq_notifs);
    230         spinlock_unlock(&irq_conns[mq].box->irq_lock);
     239/** Add call to proper answerbox queue.
     240 *
     241 * Assume irq->lock is locked.
     242 *
     243 */
     244static void send_call(irq_t *irq, call_t *call)
     245{
     246        spinlock_lock(&irq->notif_cfg.answerbox->irq_lock);
     247        list_append(&call->link, &irq->notif_cfg.answerbox->irq_notifs);
     248        spinlock_unlock(&irq->notif_cfg.answerbox->irq_lock);
    231249               
    232         waitq_wakeup(&irq_conns[mq].box->wq, 0);
     250        waitq_wakeup(&irq->notif_cfg.answerbox->wq, WAKEUP_FIRST);
    233251}
    234252
     
    236254 *
    237255 */
    238 void ipc_irq_send_msg(int irq, unative_t a1, unative_t a2, unative_t a3)
     256void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3)
    239257{
    240258        call_t *call;
    241         int mq = irq + IPC_IRQ_RESERVED_VIRTUAL;
    242 
    243         spinlock_lock(&irq_conns[mq].lock);
    244 
    245         if (irq_conns[mq].box) {
     259
     260        spinlock_lock(&irq->lock);
     261
     262        if (irq->notif_cfg.answerbox) {
    246263                call = ipc_call_alloc(FRAME_ATOMIC);
    247264                if (!call) {
    248                         spinlock_unlock(&irq_conns[mq].lock);
     265                        spinlock_unlock(&irq->lock);
    249266                        return;
    250267                }
    251268                call->flags |= IPC_CALL_NOTIF;
    252                 IPC_SET_METHOD(call->data, irq);
     269                IPC_SET_METHOD(call->data, irq->notif_cfg.method);
    253270                IPC_SET_ARG1(call->data, a1);
    254271                IPC_SET_ARG2(call->data, a2);
    255272                IPC_SET_ARG3(call->data, a3);
    256273                /* Put a counter to the message */
    257                 call->private = atomic_preinc(&irq_conns[mq].counter);
     274                call->private = ++irq->notif_cfg.counter;
    258275               
    259                 send_call(mq, call);
    260         }
    261         spinlock_unlock(&irq_conns[mq].lock);
     276                send_call(irq, call);
     277        }
     278        spinlock_unlock(&irq->lock);
    262279}
    263280
    264281/** Notify task that an irq had occurred.
    265282 *
    266  * We expect interrupts to be disabled
    267  */
    268 void ipc_irq_send_notif(int irq)
     283 * We expect interrupts to be disabled and the irq->lock already held.
     284 */
     285void ipc_irq_send_notif(irq_t *irq)
    269286{
    270287        call_t *call;
    271         int mq = irq + IPC_IRQ_RESERVED_VIRTUAL;
    272 
    273         ASSERT(irq_conns);
    274         spinlock_lock(&irq_conns[mq].lock);
    275 
    276         if (irq_conns[mq].box) {
     288
     289        ASSERT(irq);
     290
     291        if (irq->notif_cfg.answerbox) {
    277292                call = ipc_call_alloc(FRAME_ATOMIC);
    278293                if (!call) {
    279                         spinlock_unlock(&irq_conns[mq].lock);
    280294                        return;
    281295                }
    282296                call->flags |= IPC_CALL_NOTIF;
    283297                /* Put a counter to the message */
    284                 call->private = atomic_preinc(&irq_conns[mq].counter);
     298                call->private = ++irq->notif_cfg.counter;
    285299                /* Set up args */
    286                 IPC_SET_METHOD(call->data, irq);
     300                IPC_SET_METHOD(call->data, irq->notif_cfg.method);
    287301
    288302                /* Execute code to handle irq */
    289                 code_execute(call, irq_conns[mq].code);
     303                code_execute(call, irq->notif_cfg.code);
    290304               
    291                 send_call(mq, call);
    292         }
    293                
    294         spinlock_unlock(&irq_conns[mq].lock);
    295 }
    296 
    297 
    298 /** Initialize table of interrupt handlers
    299  *
    300  * @param irqcount Count of required hardware IRQs to be supported
    301  */
    302 void ipc_irq_make_table(int irqcount)
    303 {
    304         int i;
    305 
    306         irqcount +=  IPC_IRQ_RESERVED_VIRTUAL;
    307 
    308         irq_conns_size = irqcount;
    309         irq_conns = malloc(irqcount * (sizeof(*irq_conns)), 0);
    310         for (i=0; i < irqcount; i++) {
    311                 spinlock_initialize(&irq_conns[i].lock, "irq_ipc_lock");
    312                 irq_conns[i].box = NULL;
    313                 irq_conns[i].code = NULL;
    314         }
    315 }
    316 
    317 /** Disconnect all irq's notifications
    318  *
    319  * @todo It may be better to do some linked list, so that
    320  *       we wouldn't need to go through whole array every cleanup
     305                send_call(irq, call);
     306        }
     307}
     308
     309/** Disconnect all IRQ notifications from an answerbox.
     310 *
     311 * @param box Answerbox for which we want to carry out the cleanup.
    321312 */
    322313void ipc_irq_cleanup(answerbox_t *box)
    323314{
    324         int i;
    325         ipl_t ipl;
    326        
    327         for (i=0; i < irq_conns_size; i++) {
    328                 ipl = interrupts_disable();
    329                 spinlock_lock(&irq_conns[i].lock);
    330                 if (irq_conns[i].box == box)
    331                         irq_conns[i].box = NULL;
    332                 spinlock_unlock(&irq_conns[i].lock);
    333                 interrupts_restore(ipl);
    334         }
     315        /* TODO */
    335316}
    336317
Note: See TracChangeset for help on using the changeset viewer.