Changes in uspace/lib/drv/generic/driver.c [7e752b2:ffa2c8ef] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/driver.c
r7e752b2 rffa2c8ef 52 52 #include <ipc/driver.h> 53 53 54 #include "dev_iface.h" 54 55 #include "driver.h" 55 56 56 /* driver structure */ 57 57 /** Driver structure */ 58 58 static driver_t *driver; 59 59 60 /* devices */ 61 60 /** Devices */ 62 61 LIST_INITIALIZE(devices); 63 62 FIBRIL_MUTEX_INITIALIZE(devices_mutex); 64 63 65 /* interrupts */ 66 64 /** Interrupts */ 67 65 static interrupt_context_list_t interrupt_contexts; 68 66 … … 81 79 static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall) 82 80 { 83 int id = (int)IPC_GET_ METHOD(*icall);81 int id = (int)IPC_GET_IMETHOD(*icall); 84 82 interrupt_context_t *ctx; 85 83 86 84 ctx = find_interrupt_context_by_id(&interrupt_contexts, id); 87 if ( NULL != ctx && NULL != ctx->handler)85 if (ctx != NULL && ctx->handler != NULL) 88 86 (*ctx->handler)(ctx->dev, iid, icall); 89 87 } 88 89 interrupt_context_t *create_interrupt_context(void) 90 { 91 interrupt_context_t *ctx; 92 93 ctx = (interrupt_context_t *) malloc(sizeof(interrupt_context_t)); 94 if (ctx != NULL) 95 memset(ctx, 0, sizeof(interrupt_context_t)); 96 97 return ctx; 98 } 99 100 void delete_interrupt_context(interrupt_context_t *ctx) 101 { 102 if (ctx != NULL) 103 free(ctx); 104 } 105 106 void init_interrupt_context_list(interrupt_context_list_t *list) 107 { 108 memset(list, 0, sizeof(interrupt_context_list_t)); 109 fibril_mutex_initialize(&list->mutex); 110 list_initialize(&list->contexts); 111 } 112 113 void 114 add_interrupt_context(interrupt_context_list_t *list, interrupt_context_t *ctx) 115 { 116 fibril_mutex_lock(&list->mutex); 117 ctx->id = list->curr_id++; 118 list_append(&ctx->link, &list->contexts); 119 fibril_mutex_unlock(&list->mutex); 120 } 121 122 void remove_interrupt_context(interrupt_context_list_t *list, 123 interrupt_context_t *ctx) 124 { 125 fibril_mutex_lock(&list->mutex); 126 list_remove(&ctx->link); 127 fibril_mutex_unlock(&list->mutex); 128 } 129 130 interrupt_context_t * 131 find_interrupt_context_by_id(interrupt_context_list_t *list, int id) 132 { 133 fibril_mutex_lock(&list->mutex); 134 135 link_t *link = list->contexts.next; 136 interrupt_context_t *ctx; 137 138 while (link != &list->contexts) { 139 ctx = list_get_instance(link, interrupt_context_t, link); 140 if (ctx->id == id) { 141 fibril_mutex_unlock(&list->mutex); 142 return ctx; 143 } 144 link = link->next; 145 } 146 147 fibril_mutex_unlock(&list->mutex); 148 return NULL; 149 } 150 151 interrupt_context_t * 152 find_interrupt_context(interrupt_context_list_t *list, device_t *dev, int irq) 153 { 154 fibril_mutex_lock(&list->mutex); 155 156 link_t *link = list->contexts.next; 157 interrupt_context_t *ctx; 158 159 while (link != &list->contexts) { 160 ctx = list_get_instance(link, interrupt_context_t, link); 161 if (ctx->irq == irq && ctx->dev == dev) { 162 fibril_mutex_unlock(&list->mutex); 163 return ctx; 164 } 165 link = link->next; 166 } 167 168 fibril_mutex_unlock(&list->mutex); 169 return NULL; 170 } 171 90 172 91 173 int … … 101 183 add_interrupt_context(&interrupt_contexts, ctx); 102 184 103 if ( NULL == pseudocode)185 if (pseudocode == NULL) 104 186 pseudocode = &default_pseudocode; 105 187 106 int res = ipc_register_irq(irq, dev->handle, ctx->id, pseudocode);107 if ( 0 != res) {188 int res = register_irq(irq, dev->handle, ctx->id, pseudocode); 189 if (res != EOK) { 108 190 remove_interrupt_context(&interrupt_contexts, ctx); 109 191 delete_interrupt_context(ctx); … … 117 199 interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts, 118 200 dev, irq); 119 int res = ipc_unregister_irq(irq, dev->handle);120 121 if ( NULL != ctx) {201 int res = unregister_irq(irq, dev->handle); 202 203 if (ctx != NULL) { 122 204 remove_interrupt_context(&interrupt_contexts, ctx); 123 205 delete_interrupt_context(ctx); 124 206 } 207 125 208 return res; 126 209 } … … 140 223 } 141 224 142 static device_t * 225 static device_t *driver_get_device(link_t *devices, devman_handle_t handle) 143 226 { 144 227 device_t *dev = NULL; … … 146 229 fibril_mutex_lock(&devices_mutex); 147 230 link_t *link = devices->next; 231 148 232 while (link != devices) { 149 233 dev = list_get_instance(link, device_t, link); 150 if ( handle == dev->handle) {234 if (dev->handle == handle) { 151 235 fibril_mutex_unlock(&devices_mutex); 152 236 return dev; … … 154 238 link = link->next; 155 239 } 240 156 241 fibril_mutex_unlock(&devices_mutex); 157 242 158 243 return NULL; 159 244 } … … 162 247 { 163 248 char *dev_name = NULL; 164 int res = EOK; 165 166 devman_handle_t dev_handle = IPC_GET_ARG1(*icall); 249 int res; 250 251 devman_handle_t dev_handle = IPC_GET_ARG1(*icall); 252 devman_handle_t parent_dev_handle = IPC_GET_ARG2(*icall); 253 167 254 device_t *dev = create_device(); 168 255 dev->handle = dev_handle; … … 172 259 173 260 add_to_devices_list(dev); 261 dev->parent = driver_get_device(&devices, parent_dev_handle); 262 174 263 res = driver->driver_ops->add_device(dev); 175 if ( 0 == res) {264 if (res == EOK) { 176 265 printf("%s: new device with handle=%" PRIun " was added.\n", 177 266 driver->name, dev_handle); … … 183 272 } 184 273 185 ipc_answer_0(iid, res);274 async_answer_0(iid, res); 186 275 } 187 276 … … 189 278 { 190 279 /* Accept connection */ 191 ipc_answer_0(iid, EOK);192 280 async_answer_0(iid, EOK); 281 193 282 bool cont = true; 194 283 while (cont) { 195 284 ipc_call_t call; 196 285 ipc_callid_t callid = async_get_call(&call); 197 198 switch (IPC_GET_ METHOD(call)) {286 287 switch (IPC_GET_IMETHOD(call)) { 199 288 case IPC_M_PHONE_HUNGUP: 200 289 cont = false; … … 204 293 break; 205 294 default: 206 ipc_answer_0(callid, ENOENT);295 async_answer_0(callid, ENOENT); 207 296 } 208 297 } … … 227 316 printf("%s: driver_connection_gen error - no device with handle" 228 317 " %" PRIun " was found.\n", driver->name, handle); 229 ipc_answer_0(iid, ENOENT);318 async_answer_0(iid, ENOENT); 230 319 return; 231 320 } … … 236 325 * use the device. 237 326 */ 238 327 239 328 int ret = EOK; 240 329 /* open the device */ 241 if ( NULL != dev->ops && NULL != dev->ops->open)330 if (dev->ops != NULL && dev->ops->open != NULL) 242 331 ret = (*dev->ops->open)(dev); 243 332 244 ipc_answer_0(iid, ret);245 if ( EOK != ret)333 async_answer_0(iid, ret); 334 if (ret != EOK) 246 335 return; 247 336 248 337 while (1) { 249 338 ipc_callid_t callid; 250 339 ipc_call_t call; 251 340 callid = async_get_call(&call); 252 ipcarg_t method = IPC_GET_METHOD(call);341 sysarg_t method = IPC_GET_IMETHOD(call); 253 342 int iface_idx; 254 343 255 344 switch (method) { 256 case IPC_M_PHONE_HUNGUP: 345 case IPC_M_PHONE_HUNGUP: 257 346 /* close the device */ 258 if ( NULL != dev->ops && NULL != dev->ops->close)347 if (dev->ops != NULL && dev->ops->close != NULL) 259 348 (*dev->ops->close)(dev); 260 ipc_answer_0(callid, EOK);349 async_answer_0(callid, EOK); 261 350 return; 262 default: 351 default: 263 352 /* convert ipc interface id to interface index */ 264 353 … … 268 357 remote_handler_t *default_handler = 269 358 device_get_default_handler(dev); 270 if ( NULL != default_handler) {359 if (default_handler != NULL) { 271 360 (*default_handler)(dev, callid, &call); 272 361 break; … … 279 368 "invalid interface id %d.", 280 369 driver->name, iface_idx); 281 ipc_answer_0(callid, ENOTSUP);370 async_answer_0(callid, ENOTSUP); 282 371 break; 283 372 } 284 373 285 374 /* calling one of the device's interfaces */ 286 375 287 /* get the device interface structure*/288 void * iface = device_get_iface(dev, iface_idx);289 if ( NULL == iface) {376 /* Get the interface ops structure. */ 377 void *ops = device_get_ops(dev, iface_idx); 378 if (ops == NULL) { 290 379 printf("%s: driver_connection_gen error - ", 291 380 driver->name); 292 381 printf("device with handle %" PRIun " has no interface " 293 382 "with id %d.\n", handle, iface_idx); 294 ipc_answer_0(callid, ENOTSUP);383 async_answer_0(callid, ENOTSUP); 295 384 break; 296 385 } 297 386 298 387 /* 299 388 * Get the corresponding interface for remote request 300 389 * handling ("remote interface"). 301 390 */ 302 remote_iface_t *rem_iface = get_remote_iface(iface_idx);303 assert( NULL != rem_iface);304 391 remote_iface_t *rem_iface = get_remote_iface(iface_idx); 392 assert(rem_iface != NULL); 393 305 394 /* get the method of the remote interface */ 306 ipcarg_t iface_method_idx = IPC_GET_ARG1(call);395 sysarg_t iface_method_idx = IPC_GET_ARG1(call); 307 396 remote_iface_func_ptr_t iface_method_ptr = 308 397 get_remote_method(rem_iface, iface_method_idx); 309 if ( NULL == iface_method_ptr) {398 if (iface_method_ptr == NULL) { 310 399 // the interface has not such method 311 400 printf("%s: driver_connection_gen error - " 312 401 "invalid interface method.", driver->name); 313 ipc_answer_0(callid, ENOTSUP);402 async_answer_0(callid, ENOTSUP); 314 403 break; 315 404 } … … 321 410 * associated with the device by its driver. 322 411 */ 323 (*iface_method_ptr)(dev, iface, callid, &call);412 (*iface_method_ptr)(dev, ops, callid, &call); 324 413 break; 325 414 } … … 342 431 { 343 432 /* Select interface */ 344 switch (( ipcarg_t) (IPC_GET_ARG1(*icall))) {433 switch ((sysarg_t) (IPC_GET_ARG1(*icall))) { 345 434 case DRIVER_DEVMAN: 346 /* handle PnP eventsfrom device manager */435 /* Handle request from device manager */ 347 436 driver_connection_devman(iid, icall); 348 437 break; 349 438 case DRIVER_DRIVER: 350 /* handle request from drivers of child devices */439 /* Handle request from drivers of child devices */ 351 440 driver_connection_driver(iid, icall); 352 441 break; 353 442 case DRIVER_CLIENT: 354 /* handle requestsfrom client applications */443 /* Handle request from client applications */ 355 444 driver_connection_client(iid, icall); 356 445 break; 357 358 446 default: 359 447 /* No such interface */ 360 ipc_answer_0(iid, ENOENT); 361 } 448 async_answer_0(iid, ENOENT); 449 } 450 } 451 452 /** Create new device structure. 453 * 454 * @return The device structure. 455 */ 456 device_t *create_device(void) 457 { 458 device_t *dev = malloc(sizeof(device_t)); 459 460 if (dev != NULL) { 461 memset(dev, 0, sizeof(device_t)); 462 init_match_ids(&dev->match_ids); 463 } 464 465 return dev; 466 } 467 468 /** Delete device structure. 469 * 470 * @param dev The device structure. 471 */ 472 void delete_device(device_t *dev) 473 { 474 clean_match_ids(&dev->match_ids); 475 if (dev->name != NULL) 476 free(dev->name); 477 free(dev); 478 } 479 480 void *device_get_ops(device_t *dev, dev_inferface_idx_t idx) 481 { 482 assert(is_valid_iface_idx(idx)); 483 if (dev->ops == NULL) 484 return NULL; 485 return dev->ops->interfaces[idx]; 362 486 } 363 487 364 488 int child_device_register(device_t *child, device_t *parent) 365 489 { 366 assert( NULL != child->name);367 490 assert(child->name != NULL); 491 368 492 int res; 369 493 … … 371 495 res = devman_child_device_register(child->name, &child->match_ids, 372 496 parent->handle, &child->handle); 373 if (EOK == res) 497 if (res != EOK) { 498 remove_from_devices_list(child); 374 499 return res; 375 remove_from_devices_list(child); 500 } 501 376 502 return res; 503 } 504 505 /** Wrapper for child_device_register for devices with single match id. 506 * 507 * @param parent Parent device. 508 * @param child_name Child device name. 509 * @param child_match_id Child device match id. 510 * @param child_match_score Child device match score. 511 * @return Error code. 512 */ 513 int child_device_register_wrapper(device_t *parent, const char *child_name, 514 const char *child_match_id, int child_match_score) 515 { 516 device_t *child = NULL; 517 match_id_t *match_id = NULL; 518 int rc; 519 520 child = create_device(); 521 if (child == NULL) { 522 rc = ENOMEM; 523 goto failure; 524 } 525 526 child->name = child_name; 527 528 match_id = create_match_id(); 529 if (match_id == NULL) { 530 rc = ENOMEM; 531 goto failure; 532 } 533 534 match_id->id = child_match_id; 535 match_id->score = child_match_score; 536 add_match_id(&child->match_ids, match_id); 537 538 rc = child_device_register(child, parent); 539 if (rc != EOK) 540 goto failure; 541 542 return EOK; 543 544 failure: 545 if (match_id != NULL) { 546 match_id->id = NULL; 547 delete_match_id(match_id); 548 } 549 550 if (child != NULL) { 551 child->name = NULL; 552 delete_device(child); 553 } 554 555 return rc; 556 } 557 558 /** Get default handler for client requests */ 559 remote_handler_t *device_get_default_handler(device_t *dev) 560 { 561 if (dev->ops == NULL) 562 return NULL; 563 return dev->ops->default_handler; 564 } 565 566 int add_device_to_class(device_t *dev, const char *class_name) 567 { 568 return devman_add_device_to_class(dev->handle, class_name); 377 569 } 378 570 … … 384 576 */ 385 577 driver = drv; 386 578 387 579 /* Initialize the list of interrupt contexts. */ 388 580 init_interrupt_context_list(&interrupt_contexts); … … 396 588 */ 397 589 devman_driver_register(driver->name, driver_connection); 398 590 399 591 async_manager(); 400 592 401 593 /* Never reached. */ 402 594 return 0;
Note:
See TracChangeset
for help on using the changeset viewer.