Changeset 00aece0 in mainline for uspace/drv/bus/isa/isa.c
- Timestamp:
- 2012-02-18T16:47:38Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4449c6c
- Parents:
- bd5f3b7 (diff), f943dd3 (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/drv/bus/isa/isa.c
rbd5f3b7 r00aece0 2 2 * Copyright (c) 2010 Lenka Trochtova 3 3 * Copyright (c) 2011 Jiri Svoboda 4 * Copyright (c) 2011 Jan Vesely 4 5 * All rights reserved. 5 6 * … … 37 38 */ 38 39 40 #include <adt/list.h> 39 41 #include <assert.h> 40 42 #include <stdio.h> … … 50 52 #include <dirent.h> 51 53 #include <fcntl.h> 54 #include <ipc/irc.h> 55 #include <ipc/services.h> 56 #include <sysinfo.h> 57 #include <ns.h> 52 58 #include <sys/stat.h> 59 #include <ipc/irc.h> 60 #include <ipc/services.h> 61 #include <sysinfo.h> 62 #include <ns.h> 53 63 54 64 #include <ddf/driver.h> … … 60 70 #include <device/hw_res.h> 61 71 72 #include "i8237.h" 73 62 74 #define NAME "isa" 63 75 #define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev" 64 76 65 /** Obtain soft-state pointer from function node pointer */ 66 #define ISA_FUN(fnode) ((isa_fun_t *) ((fnode)->driver_data)) 67 68 #define ISA_MAX_HW_RES 4 77 /** Obtain soft-state from device node */ 78 #define ISA_BUS(dev) ((isa_bus_t *) ((dev)->driver_data)) 79 80 /** Obtain soft-state from function node */ 81 #define ISA_FUN(fun) ((isa_fun_t *) ((fun)->driver_data)) 82 83 #define ISA_MAX_HW_RES 5 84 85 typedef struct { 86 fibril_mutex_t mutex; 87 ddf_dev_t *dev; 88 ddf_fun_t *fctl; 89 list_t functions; 90 } isa_bus_t; 69 91 70 92 typedef struct isa_fun { 93 fibril_mutex_t mutex; 71 94 ddf_fun_t *fnode; 72 95 hw_resource_list_t hw_resources; 96 link_t bus_link; 73 97 } isa_fun_t; 74 98 … … 83 107 static bool isa_enable_fun_interrupt(ddf_fun_t *fnode) 84 108 { 85 /* TODO */ 86 87 return false; 109 /* This is an old ugly way, copied from pci driver */ 110 assert(fnode); 111 isa_fun_t *isa_fun = fnode->driver_data; 112 113 sysarg_t apic; 114 sysarg_t i8259; 115 116 async_sess_t *irc_sess = NULL; 117 118 if (((sysinfo_get_value("apic", &apic) == EOK) && (apic)) 119 || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) { 120 irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE, 121 SERVICE_IRC, 0, 0); 122 } 123 124 if (!irc_sess) 125 return false; 126 127 assert(isa_fun); 128 const hw_resource_list_t *res = &isa_fun->hw_resources; 129 assert(res); 130 for (size_t i = 0; i < res->count; ++i) { 131 if (res->resources[i].type == INTERRUPT) { 132 const int irq = res->resources[i].res.interrupt.irq; 133 134 async_exch_t *exch = async_exchange_begin(irc_sess); 135 const int rc = 136 async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq); 137 async_exchange_end(exch); 138 139 if (rc != EOK) { 140 async_hangup(irc_sess); 141 return false; 142 } 143 } 144 } 145 146 async_hangup(irc_sess); 147 return true; 148 } 149 150 static int isa_dma_channel_fun_setup(ddf_fun_t *fnode, 151 unsigned int channel, uint32_t pa, uint16_t size, uint8_t mode) 152 { 153 assert(fnode); 154 isa_fun_t *isa_fun = fnode->driver_data; 155 const hw_resource_list_t *res = &isa_fun->hw_resources; 156 assert(res); 157 158 const unsigned int ch = channel; 159 for (size_t i = 0; i < res->count; ++i) { 160 if (((res->resources[i].type == DMA_CHANNEL_16) && 161 (res->resources[i].res.dma_channel.dma16 == ch)) || 162 ((res->resources[i].type == DMA_CHANNEL_8) && 163 (res->resources[i].res.dma_channel.dma8 == ch))) { 164 return dma_setup_channel(channel, pa, size, mode); 165 } 166 } 167 168 return EINVAL; 88 169 } 89 170 90 171 static hw_res_ops_t isa_fun_hw_res_ops = { 91 &isa_get_fun_resources, 92 &isa_enable_fun_interrupt 172 .get_resource_list = isa_get_fun_resources, 173 .enable_interrupt = isa_enable_fun_interrupt, 174 .dma_channel_setup = isa_dma_channel_fun_setup, 93 175 }; 94 176 95 177 static ddf_dev_ops_t isa_fun_ops; 96 178 97 static int isa_add_device(ddf_dev_t *dev); 179 static int isa_dev_add(ddf_dev_t *dev); 180 static int isa_dev_remove(ddf_dev_t *dev); 181 static int isa_fun_online(ddf_fun_t *fun); 182 static int isa_fun_offline(ddf_fun_t *fun); 98 183 99 184 /** The isa device driver's standard operations */ 100 185 static driver_ops_t isa_ops = { 101 .add_device = &isa_add_device 186 .dev_add = &isa_dev_add, 187 .dev_remove = &isa_dev_remove, 188 .fun_online = &isa_fun_online, 189 .fun_offline = &isa_fun_offline 102 190 }; 103 191 … … 108 196 }; 109 197 110 static isa_fun_t *isa_fun_create(ddf_dev_t *dev, const char *name) 111 { 112 isa_fun_t *fun = calloc(1, sizeof(isa_fun_t)); 198 static isa_fun_t *isa_fun_create(isa_bus_t *isa, const char *name) 199 { 200 ddf_fun_t *fnode = ddf_fun_create(isa->dev, fun_inner, name); 201 if (fnode == NULL) 202 return NULL; 203 204 isa_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(isa_fun_t)); 113 205 if (fun == NULL) 114 206 return NULL; 115 207 116 ddf_fun_t *fnode = ddf_fun_create(dev, fun_inner, name); 117 if (fnode == NULL) { 118 free(fun); 119 return NULL; 120 } 121 208 fibril_mutex_initialize(&fun->mutex); 122 209 fun->fnode = fnode; 123 fnode->driver_data = fun;124 210 return fun; 125 211 } … … 257 343 } 258 344 345 static void isa_fun_set_dma(isa_fun_t *fun, int dma) 346 { 347 size_t count = fun->hw_resources.count; 348 hw_resource_t *resources = fun->hw_resources.resources; 349 350 if (count < ISA_MAX_HW_RES) { 351 if ((dma > 0) && (dma < 4)) { 352 resources[count].type = DMA_CHANNEL_8; 353 resources[count].res.dma_channel.dma8 = dma; 354 355 fun->hw_resources.count++; 356 ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma, 357 fun->fnode->name); 358 359 return; 360 } 361 362 if ((dma > 4) && (dma < 8)) { 363 resources[count].type = DMA_CHANNEL_16; 364 resources[count].res.dma_channel.dma16 = dma; 365 366 fun->hw_resources.count++; 367 ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma, 368 fun->fnode->name); 369 370 return; 371 } 372 373 ddf_msg(LVL_WARN, "Skipped dma 0x%x for function %s", dma, 374 fun->fnode->name); 375 } 376 } 377 259 378 static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len) 260 379 { … … 282 401 283 402 val = skip_spaces(val); 284 irq = (int) strtol(val, &end, 0x10);403 irq = (int) strtol(val, &end, 10); 285 404 286 405 if (val != end) 287 406 isa_fun_set_irq(fun, irq); 407 } 408 409 static void fun_parse_dma(isa_fun_t *fun, char *val) 410 { 411 unsigned int dma = 0; 412 char *end = NULL; 413 414 val = skip_spaces(val); 415 dma = (unsigned int) strtol(val, &end, 10); 416 417 if (val != end) 418 isa_fun_set_dma(fun, dma); 288 419 } 289 420 … … 379 510 if (!prop_parse(fun, line, "io_range", &fun_parse_io_range) && 380 511 !prop_parse(fun, line, "irq", &fun_parse_irq) && 512 !prop_parse(fun, line, "dma", &fun_parse_dma) && 381 513 !prop_parse(fun, line, "match", &fun_parse_match_id)) { 382 514 … … 388 520 static void fun_hw_res_alloc(isa_fun_t *fun) 389 521 { 390 fun->hw_resources.resources = 391 (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES); 392 } 393 394 static char *isa_fun_read_info(char *fun_conf, ddf_dev_t *dev) 522 fun->hw_resources.resources = 523 (hw_resource_t *) malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES); 524 } 525 526 static void fun_hw_res_free(isa_fun_t *fun) 527 { 528 free(fun->hw_resources.resources); 529 fun->hw_resources.resources = NULL; 530 } 531 532 static char *isa_fun_read_info(char *fun_conf, isa_bus_t *isa) 395 533 { 396 534 char *line; … … 415 553 return NULL; 416 554 417 isa_fun_t *fun = isa_fun_create( dev, fun_name);555 isa_fun_t *fun = isa_fun_create(isa, fun_name); 418 556 if (fun == NULL) { 419 557 free(fun_name); … … 448 586 (void) ddf_fun_bind(fun->fnode); 449 587 588 list_append(&fun->bus_link, &isa->functions); 589 450 590 return fun_conf; 451 591 } 452 592 453 static void fun_conf_parse(char *conf, ddf_dev_t *dev)593 static void fun_conf_parse(char *conf, isa_bus_t *isa) 454 594 { 455 595 while (conf != NULL && *conf != '\0') { 456 conf = isa_fun_read_info(conf, dev);457 } 458 } 459 460 static void isa_functions_add( ddf_dev_t *dev)596 conf = isa_fun_read_info(conf, isa); 597 } 598 } 599 600 static void isa_functions_add(isa_bus_t *isa) 461 601 { 462 602 char *fun_conf; … … 464 604 fun_conf = fun_conf_read(CHILD_FUN_CONF_PATH); 465 605 if (fun_conf != NULL) { 466 fun_conf_parse(fun_conf, dev);606 fun_conf_parse(fun_conf, isa); 467 607 free(fun_conf); 468 608 } 469 609 } 470 610 471 static int isa_add_device(ddf_dev_t *dev) 472 { 473 ddf_msg(LVL_DEBUG, "isa_add_device, device handle = %d", 611 static int isa_dev_add(ddf_dev_t *dev) 612 { 613 isa_bus_t *isa; 614 615 ddf_msg(LVL_DEBUG, "isa_dev_add, device handle = %d", 474 616 (int) dev->handle); 617 618 isa = ddf_dev_data_alloc(dev, sizeof(isa_bus_t)); 619 if (isa == NULL) 620 return ENOMEM; 621 622 fibril_mutex_initialize(&isa->mutex); 623 isa->dev = dev; 624 list_initialize(&isa->functions); 475 625 476 626 /* Make the bus device more visible. Does not do anything. */ 477 627 ddf_msg(LVL_DEBUG, "Adding a 'ctl' function"); 478 628 479 ddf_fun_t *ctl = ddf_fun_create(dev, fun_exposed, "ctl"); 480 if (ctl == NULL) { 629 fibril_mutex_lock(&isa->mutex); 630 631 isa->fctl = ddf_fun_create(dev, fun_exposed, "ctl"); 632 if (isa->fctl == NULL) { 481 633 ddf_msg(LVL_ERROR, "Failed creating control function."); 482 634 return EXDEV; 483 635 } 484 636 485 if (ddf_fun_bind(ctl) != EOK) { 637 if (ddf_fun_bind(isa->fctl) != EOK) { 638 ddf_fun_destroy(isa->fctl); 486 639 ddf_msg(LVL_ERROR, "Failed binding control function."); 487 640 return EXDEV; … … 489 642 490 643 /* Add functions as specified in the configuration file. */ 491 isa_functions_add( dev);644 isa_functions_add(isa); 492 645 ddf_msg(LVL_NOTE, "Finished enumerating legacy functions"); 493 646 647 fibril_mutex_unlock(&isa->mutex); 648 494 649 return EOK; 495 650 } 496 651 497 static void isa_init() 652 static int isa_dev_remove(ddf_dev_t *dev) 653 { 654 isa_bus_t *isa = ISA_BUS(dev); 655 int rc; 656 657 fibril_mutex_lock(&isa->mutex); 658 659 while (!list_empty(&isa->functions)) { 660 isa_fun_t *fun = list_get_instance(list_first(&isa->functions), 661 isa_fun_t, bus_link); 662 663 rc = ddf_fun_offline(fun->fnode); 664 if (rc != EOK) { 665 fibril_mutex_unlock(&isa->mutex); 666 ddf_msg(LVL_ERROR, "Failed offlining %s", fun->fnode->name); 667 return rc; 668 } 669 670 rc = ddf_fun_unbind(fun->fnode); 671 if (rc != EOK) { 672 fibril_mutex_unlock(&isa->mutex); 673 ddf_msg(LVL_ERROR, "Failed unbinding %s", fun->fnode->name); 674 return rc; 675 } 676 677 list_remove(&fun->bus_link); 678 679 fun_hw_res_free(fun); 680 ddf_fun_destroy(fun->fnode); 681 } 682 683 if (ddf_fun_unbind(isa->fctl) != EOK) { 684 fibril_mutex_unlock(&isa->mutex); 685 ddf_msg(LVL_ERROR, "Failed unbinding control function."); 686 return EXDEV; 687 } 688 689 fibril_mutex_unlock(&isa->mutex); 690 691 return EOK; 692 } 693 694 static int isa_fun_online(ddf_fun_t *fun) 695 { 696 ddf_msg(LVL_DEBUG, "isa_fun_online()"); 697 return ddf_fun_online(fun); 698 } 699 700 static int isa_fun_offline(ddf_fun_t *fun) 701 { 702 ddf_msg(LVL_DEBUG, "isa_fun_offline()"); 703 return ddf_fun_offline(fun); 704 } 705 706 707 static void isa_init() 498 708 { 499 709 ddf_log_init(NAME, LVL_ERROR);
Note:
See TracChangeset
for help on using the changeset viewer.