Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/drv/generic/interrupt.c

    r56fd7cf r8820544  
    3939#include <errno.h>
    4040#include <sys/types.h>
     41#include <macros.h>
    4142
    4243#include "ddf/interrupt.h"
    4344#include "private/driver.h"
    44 
    45 static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall);
    46 static interrupt_context_t *create_interrupt_context(void);
    47 static void delete_interrupt_context(interrupt_context_t *ctx);
    48 static void init_interrupt_context_list(interrupt_context_list_t *list);
    49 static void add_interrupt_context(interrupt_context_list_t *list,
    50     interrupt_context_t *ctx);
    51 static void remove_interrupt_context(interrupt_context_list_t *list,
    52     interrupt_context_t *ctx);
    53 static interrupt_context_t *find_interrupt_context_by_id(
    54     interrupt_context_list_t *list, int id);
    55 static interrupt_context_t *find_interrupt_context(
    56     interrupt_context_list_t *list, ddf_dev_t *dev, int irq);
    57 int register_interrupt_handler(ddf_dev_t *dev, int irq,
    58     interrupt_handler_t *handler, irq_code_t *pseudocode);
    59 int unregister_interrupt_handler(ddf_dev_t *dev, int irq);
    60 
    61 /** Interrupts */
    62 static interrupt_context_list_t interrupt_contexts;
    6345
    6446static irq_cmd_t default_cmds[] = {
     
    6850};
    6951
    70 static irq_code_t default_pseudocode = {
     52static const irq_code_t default_pseudocode = {
    7153        0,
    7254        NULL,
    73         sizeof(default_cmds) / sizeof(irq_cmd_t),
     55        ARRAY_SIZE(default_cmds),
    7456        default_cmds
    7557};
    7658
    77 void interrupt_init(void)
     59int register_interrupt_handler(ddf_dev_t *dev, int irq,
     60    interrupt_handler_t *handler, const irq_code_t *pseudocode)
    7861{
    79         /* Initialize the list of interrupt contexts. */
    80         init_interrupt_context_list(&interrupt_contexts);
    81        
    82         /* Set generic interrupt handler. */
    83         async_set_interrupt_received(driver_irq_handler);
    84 }
    85 
    86 static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall)
    87 {
    88         int id = (int)IPC_GET_IMETHOD(*icall);
    89         interrupt_context_t *ctx;
    90        
    91         ctx = find_interrupt_context_by_id(&interrupt_contexts, id);
    92         if (ctx != NULL && ctx->handler != NULL)
    93                 (*ctx->handler)(ctx->dev, iid, icall);
    94 }
    95 
    96 static interrupt_context_t *create_interrupt_context(void)
    97 {
    98         interrupt_context_t *ctx;
    99        
    100         ctx = (interrupt_context_t *) malloc(sizeof(interrupt_context_t));
    101         if (ctx != NULL)
    102                 memset(ctx, 0, sizeof(interrupt_context_t));
    103        
    104         return ctx;
    105 }
    106 
    107 static void delete_interrupt_context(interrupt_context_t *ctx)
    108 {
    109         if (ctx != NULL)
    110                 free(ctx);
    111 }
    112 
    113 static void init_interrupt_context_list(interrupt_context_list_t *list)
    114 {
    115         memset(list, 0, sizeof(interrupt_context_list_t));
    116         fibril_mutex_initialize(&list->mutex);
    117         list_initialize(&list->contexts);
    118 }
    119 
    120 static void add_interrupt_context(interrupt_context_list_t *list,
    121     interrupt_context_t *ctx)
    122 {
    123         fibril_mutex_lock(&list->mutex);
    124         ctx->id = list->curr_id++;
    125         list_append(&ctx->link, &list->contexts);
    126         fibril_mutex_unlock(&list->mutex);
    127 }
    128 
    129 static void remove_interrupt_context(interrupt_context_list_t *list,
    130     interrupt_context_t *ctx)
    131 {
    132         fibril_mutex_lock(&list->mutex);
    133         list_remove(&ctx->link);
    134         fibril_mutex_unlock(&list->mutex);
    135 }
    136 
    137 static interrupt_context_t *find_interrupt_context_by_id(
    138     interrupt_context_list_t *list, int id)
    139 {
    140         interrupt_context_t *ctx;
    141        
    142         fibril_mutex_lock(&list->mutex);
    143        
    144         list_foreach(list->contexts, link) {
    145                 ctx = list_get_instance(link, interrupt_context_t, link);
    146                 if (ctx->id == id) {
    147                         fibril_mutex_unlock(&list->mutex);
    148                         return ctx;
    149                 }
    150         }
    151        
    152         fibril_mutex_unlock(&list->mutex);
    153         return NULL;
    154 }
    155 
    156 static interrupt_context_t *find_interrupt_context(
    157     interrupt_context_list_t *list, ddf_dev_t *dev, int irq)
    158 {
    159         interrupt_context_t *ctx;
    160        
    161         fibril_mutex_lock(&list->mutex);
    162        
    163         list_foreach(list->contexts, link) {
    164                 ctx = list_get_instance(link, interrupt_context_t, link);
    165                 if (ctx->irq == irq && ctx->dev == dev) {
    166                         fibril_mutex_unlock(&list->mutex);
    167                         return ctx;
    168                 }
    169         }
    170        
    171         fibril_mutex_unlock(&list->mutex);
    172         return NULL;
    173 }
    174 
    175 
    176 int register_interrupt_handler(ddf_dev_t *dev, int irq,
    177     interrupt_handler_t *handler, irq_code_t *pseudocode)
    178 {
    179         interrupt_context_t *ctx = create_interrupt_context();
    180        
    181         ctx->dev = dev;
    182         ctx->irq = irq;
    183         ctx->handler = handler;
    184        
    185         add_interrupt_context(&interrupt_contexts, ctx);
    186        
    187         if (pseudocode == NULL)
    188                 pseudocode = &default_pseudocode;
    189        
    190         int res = irq_register(irq, dev->handle, ctx->id, pseudocode);
    191         if (res != EOK) {
    192                 remove_interrupt_context(&interrupt_contexts, ctx);
    193                 delete_interrupt_context(ctx);
    194         }
    195        
    196         return res;
     62        return async_irq_subscribe(irq, dev->handle,
     63            (async_notification_handler_t) handler, dev, pseudocode);
    19764}
    19865
    19966int unregister_interrupt_handler(ddf_dev_t *dev, int irq)
    20067{
    201         interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts,
    202             dev, irq);
    203         int res = irq_unregister(irq, dev->handle);
    204        
    205         if (ctx != NULL) {
    206                 remove_interrupt_context(&interrupt_contexts, ctx);
    207                 delete_interrupt_context(ctx);
    208         }
    209        
    210         return res;
     68        return async_irq_unsubscribe(irq, dev->handle);
    21169}
    21270
Note: See TracChangeset for help on using the changeset viewer.