Changeset 8e7c9fe in mainline for uspace/lib/drv/generic/interrupt.c
- Timestamp:
- 2014-09-12T03:45:25Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- c53b58e
- Parents:
- 3eb0c85 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/interrupt.c
r3eb0c85 r8e7c9fe 44 44 #include "private/driver.h" 45 45 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 62 46 static irq_cmd_t default_cmds[] = { 63 47 { … … 73 57 }; 74 58 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 168 59 int register_interrupt_handler(ddf_dev_t *dev, int irq, 169 60 interrupt_handler_t *handler, const irq_code_t *pseudocode) 170 61 { 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); 189 64 } 190 65 191 66 int unregister_interrupt_handler(ddf_dev_t *dev, int irq) 192 67 { 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); 203 69 } 204 70
Note:
See TracChangeset
for help on using the changeset viewer.