Changeset 15d0046 in mainline for uspace/lib/drv/generic/interrupt.c


Ignore:
Timestamp:
2014-09-12T13:22:33Z (10 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9b20126
Parents:
8db09e4 (diff), 105d8d6 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes

File:
1 edited

Legend:

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

    r8db09e4 r15d0046  
    4444#include "private/driver.h"
    4545
    46 static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall);
    47 static interrupt_context_t *create_interrupt_context(void);
    48 static void delete_interrupt_context(interrupt_context_t *ctx);
    49 static void init_interrupt_context_list(interrupt_context_list_t *list);
    50 static void add_interrupt_context(interrupt_context_list_t *list,
    51     interrupt_context_t *ctx);
    52 static void remove_interrupt_context(interrupt_context_list_t *list,
    53     interrupt_context_t *ctx);
    54 static interrupt_context_t *find_interrupt_context_by_id(
    55     interrupt_context_list_t *list, int id);
    56 static interrupt_context_t *find_interrupt_context(
    57     interrupt_context_list_t *list, ddf_dev_t *dev, int irq);
    58 
    59 /** Interrupts */
    60 static interrupt_context_list_t interrupt_contexts;
    61 
    6246static irq_cmd_t default_cmds[] = {
    6347        {
     
    7357};
    7458
    75 void interrupt_init(void)
    76 {
    77         /* Initialize the list of interrupt contexts. */
    78         init_interrupt_context_list(&interrupt_contexts);
    79        
    80         /* Set generic interrupt handler. */
    81         async_set_interrupt_received(driver_irq_handler);
    82 }
    83 
    84 static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall)
    85 {
    86         int id = (int)IPC_GET_IMETHOD(*icall);
    87         interrupt_context_t *ctx;
    88        
    89         ctx = find_interrupt_context_by_id(&interrupt_contexts, id);
    90         if (ctx != NULL && ctx->handler != NULL)
    91                 (*ctx->handler)(ctx->dev, iid, icall);
    92 }
    93 
    94 static interrupt_context_t *create_interrupt_context(void)
    95 {
    96         interrupt_context_t *ctx;
    97        
    98         ctx = (interrupt_context_t *) malloc(sizeof(interrupt_context_t));
    99         if (ctx != NULL)
    100                 memset(ctx, 0, sizeof(interrupt_context_t));
    101        
    102         return ctx;
    103 }
    104 
    105 static void delete_interrupt_context(interrupt_context_t *ctx)
    106 {
    107         if (ctx != NULL)
    108                 free(ctx);
    109 }
    110 
    111 static void init_interrupt_context_list(interrupt_context_list_t *list)
    112 {
    113         memset(list, 0, sizeof(interrupt_context_list_t));
    114         fibril_mutex_initialize(&list->mutex);
    115         list_initialize(&list->contexts);
    116 }
    117 
    118 static void add_interrupt_context(interrupt_context_list_t *list,
    119     interrupt_context_t *ctx)
    120 {
    121         fibril_mutex_lock(&list->mutex);
    122         ctx->id = list->curr_id++;
    123         list_append(&ctx->link, &list->contexts);
    124         fibril_mutex_unlock(&list->mutex);
    125 }
    126 
    127 static void remove_interrupt_context(interrupt_context_list_t *list,
    128     interrupt_context_t *ctx)
    129 {
    130         fibril_mutex_lock(&list->mutex);
    131         list_remove(&ctx->link);
    132         fibril_mutex_unlock(&list->mutex);
    133 }
    134 
    135 static interrupt_context_t *find_interrupt_context_by_id(
    136     interrupt_context_list_t *list, int id)
    137 {
    138         fibril_mutex_lock(&list->mutex);
    139        
    140         list_foreach(list->contexts, link, interrupt_context_t, ctx) {
    141                 if (ctx->id == id) {
    142                         fibril_mutex_unlock(&list->mutex);
    143                         return ctx;
    144                 }
    145         }
    146        
    147         fibril_mutex_unlock(&list->mutex);
    148         return NULL;
    149 }
    150 
    151 static interrupt_context_t *find_interrupt_context(
    152     interrupt_context_list_t *list, ddf_dev_t *dev, int irq)
    153 {
    154         fibril_mutex_lock(&list->mutex);
    155        
    156         list_foreach(list->contexts, link, interrupt_context_t, ctx) {
    157                 if (ctx->irq == irq && ctx->dev == dev) {
    158                         fibril_mutex_unlock(&list->mutex);
    159                         return ctx;
    160                 }
    161         }
    162        
    163         fibril_mutex_unlock(&list->mutex);
    164         return NULL;
    165 }
    166 
    167 
    16859int register_interrupt_handler(ddf_dev_t *dev, int irq,
    16960    interrupt_handler_t *handler, const irq_code_t *pseudocode)
    17061{
    171         interrupt_context_t *ctx = create_interrupt_context();
    172        
    173         ctx->dev = dev;
    174         ctx->irq = irq;
    175         ctx->handler = handler;
    176        
    177         add_interrupt_context(&interrupt_contexts, ctx);
    178        
    179         if (pseudocode == NULL)
    180                 pseudocode = &default_pseudocode;
    181        
    182         int res = irq_register(irq, dev->handle, ctx->id, pseudocode);
    183         if (res != EOK) {
    184                 remove_interrupt_context(&interrupt_contexts, ctx);
    185                 delete_interrupt_context(ctx);
    186         }
    187        
    188         return res;
     62        return async_irq_subscribe(irq, dev->handle,
     63            (async_notification_handler_t) handler, dev, pseudocode);
    18964}
    19065
    19166int unregister_interrupt_handler(ddf_dev_t *dev, int irq)
    19267{
    193         interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts,
    194             dev, irq);
    195         int res = irq_unregister(irq, dev->handle);
    196        
    197         if (ctx != NULL) {
    198                 remove_interrupt_context(&interrupt_contexts, ctx);
    199                 delete_interrupt_context(ctx);
    200         }
    201        
    202         return res;
     68        return async_irq_unsubscribe(irq, dev->handle);
    20369}
    20470
Note: See TracChangeset for help on using the changeset viewer.