Changes in uspace/lib/drv/generic/driver.c [bf31e3f:f302586] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/driver.c
rbf31e3f rf302586 70 70 FIBRIL_MUTEX_INITIALIZE(functions_mutex); 71 71 72 /** Interrupts */ 73 static interrupt_context_list_t interrupt_contexts; 74 75 static irq_cmd_t default_cmds[] = { 76 { 77 .cmd = CMD_ACCEPT 78 } 79 }; 80 81 static irq_code_t default_pseudocode = { 82 sizeof(default_cmds) / sizeof(irq_cmd_t), 83 default_cmds 84 }; 85 72 86 static ddf_dev_t *create_device(void); 73 87 static void delete_device(ddf_dev_t *); … … 79 93 static void *function_get_ops(ddf_fun_t *, dev_inferface_idx_t); 80 94 95 static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall) 96 { 97 int id = (int)IPC_GET_IMETHOD(*icall); 98 interrupt_context_t *ctx; 99 100 ctx = find_interrupt_context_by_id(&interrupt_contexts, id); 101 if (ctx != NULL && ctx->handler != NULL) 102 (*ctx->handler)(ctx->dev, iid, icall); 103 } 104 105 interrupt_context_t *create_interrupt_context(void) 106 { 107 interrupt_context_t *ctx; 108 109 ctx = (interrupt_context_t *) malloc(sizeof(interrupt_context_t)); 110 if (ctx != NULL) 111 memset(ctx, 0, sizeof(interrupt_context_t)); 112 113 return ctx; 114 } 115 116 void delete_interrupt_context(interrupt_context_t *ctx) 117 { 118 if (ctx != NULL) 119 free(ctx); 120 } 121 122 void init_interrupt_context_list(interrupt_context_list_t *list) 123 { 124 memset(list, 0, sizeof(interrupt_context_list_t)); 125 fibril_mutex_initialize(&list->mutex); 126 list_initialize(&list->contexts); 127 } 128 129 void 130 add_interrupt_context(interrupt_context_list_t *list, interrupt_context_t *ctx) 131 { 132 fibril_mutex_lock(&list->mutex); 133 ctx->id = list->curr_id++; 134 list_append(&ctx->link, &list->contexts); 135 fibril_mutex_unlock(&list->mutex); 136 } 137 138 void remove_interrupt_context(interrupt_context_list_t *list, 139 interrupt_context_t *ctx) 140 { 141 fibril_mutex_lock(&list->mutex); 142 list_remove(&ctx->link); 143 fibril_mutex_unlock(&list->mutex); 144 } 145 146 interrupt_context_t * 147 find_interrupt_context_by_id(interrupt_context_list_t *list, int id) 148 { 149 interrupt_context_t *ctx; 150 151 fibril_mutex_lock(&list->mutex); 152 153 list_foreach(list->contexts, link) { 154 ctx = list_get_instance(link, interrupt_context_t, link); 155 if (ctx->id == id) { 156 fibril_mutex_unlock(&list->mutex); 157 return ctx; 158 } 159 } 160 161 fibril_mutex_unlock(&list->mutex); 162 return NULL; 163 } 164 165 interrupt_context_t * 166 find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq) 167 { 168 interrupt_context_t *ctx; 169 170 fibril_mutex_lock(&list->mutex); 171 172 list_foreach(list->contexts, link) { 173 ctx = list_get_instance(link, interrupt_context_t, link); 174 if (ctx->irq == irq && ctx->dev == dev) { 175 fibril_mutex_unlock(&list->mutex); 176 return ctx; 177 } 178 } 179 180 fibril_mutex_unlock(&list->mutex); 181 return NULL; 182 } 183 184 185 int 186 register_interrupt_handler(ddf_dev_t *dev, int irq, interrupt_handler_t *handler, 187 irq_code_t *pseudocode) 188 { 189 interrupt_context_t *ctx = create_interrupt_context(); 190 191 ctx->dev = dev; 192 ctx->irq = irq; 193 ctx->handler = handler; 194 195 add_interrupt_context(&interrupt_contexts, ctx); 196 197 if (pseudocode == NULL) 198 pseudocode = &default_pseudocode; 199 200 int res = irq_register(irq, dev->handle, ctx->id, pseudocode); 201 if (res != EOK) { 202 remove_interrupt_context(&interrupt_contexts, ctx); 203 delete_interrupt_context(ctx); 204 } 205 206 return res; 207 } 208 209 int unregister_interrupt_handler(ddf_dev_t *dev, int irq) 210 { 211 interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts, 212 dev, irq); 213 int res = irq_unregister(irq, dev->handle); 214 215 if (ctx != NULL) { 216 remove_interrupt_context(&interrupt_contexts, ctx); 217 delete_interrupt_context(ctx); 218 } 219 220 return res; 221 } 222 81 223 static void add_to_functions_list(ddf_fun_t *fun) 82 224 { … … 159 301 160 302 async_answer_0(iid, res); 303 } 304 305 static void driver_dev_added(ipc_callid_t iid, ipc_call_t *icall) 306 { 307 fibril_mutex_lock(&devices_mutex); 308 ddf_dev_t *dev = driver_get_device(IPC_GET_ARG1(*icall)); 309 fibril_mutex_unlock(&devices_mutex); 310 311 if (dev != NULL && driver->driver_ops->device_added != NULL) 312 driver->driver_ops->device_added(dev); 161 313 } 162 314 … … 308 460 case DRIVER_DEV_ADD: 309 461 driver_dev_add(callid, &call); 462 break; 463 case DRIVER_DEV_ADDED: 464 async_answer_0(callid, EOK); 465 driver_dev_added(callid, &call); 310 466 break; 311 467 case DRIVER_DEV_REMOVE: … … 595 751 596 752 /** Allocate driver-specific device data. */ 597 void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size)753 extern void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size) 598 754 { 599 755 void *data; … … 657 813 658 814 /** Allocate driver-specific function data. */ 659 void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size)815 extern void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size) 660 816 { 661 817 void *data; … … 850 1006 driver = drv; 851 1007 852 /* Initialize interrupt module */ 853 interrupt_init(); 1008 /* Initialize the list of interrupt contexts. */ 1009 init_interrupt_context_list(&interrupt_contexts); 1010 1011 /* Set generic interrupt handler. */ 1012 async_set_interrupt_received(driver_irq_handler); 854 1013 855 1014 /*
Note:
See TracChangeset
for help on using the changeset viewer.