Changes in uspace/drv/bus/isa/isa.c [7e9e652:3e6a98c5] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/isa/isa.c
r7e9e652 r3e6a98c5 54 54 #include <ipc/irc.h> 55 55 #include <ipc/services.h> 56 #include <sysinfo.h> 57 #include <ns.h> 56 58 #include <sys/stat.h> 57 #include <irc.h> 59 #include <ipc/irc.h> 60 #include <ipc/services.h> 61 #include <sysinfo.h> 58 62 #include <ns.h> 59 63 … … 61 65 #include <ddf/log.h> 62 66 #include <ops/hw_res.h> 63 #include <ops/pio_window.h>64 67 65 68 #include <device/hw_res.h> 66 #include <device/pio_window.h>67 68 #include <pci_dev_iface.h>69 69 70 70 #include "i8237.h" 71 71 72 72 #define NAME "isa" 73 #define ISA_CHILD_FUN_CONF_PATH "/drv/isa/isa.dev" 74 #define EBUS_CHILD_FUN_CONF_PATH "/drv/isa/ebus.dev" 73 #define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev" 75 74 76 75 #define ISA_MAX_HW_RES 5 … … 78 77 typedef struct { 79 78 fibril_mutex_t mutex; 80 uint16_t pci_vendor_id;81 uint16_t pci_device_id;82 uint8_t pci_class;83 uint8_t pci_subclass;84 79 ddf_dev_t *dev; 85 80 ddf_fun_t *fctl; 86 pio_window_t pio_win;87 81 list_t functions; 88 82 } isa_bus_t; … … 91 85 fibril_mutex_t mutex; 92 86 ddf_fun_t *fnode; 93 hw_resource_t resources[ISA_MAX_HW_RES];94 87 hw_resource_list_t hw_resources; 95 88 link_t bus_link; … … 108 101 } 109 102 110 static hw_resource_list_t *isa_ fun_get_resources(ddf_fun_t *fnode)103 static hw_resource_list_t *isa_get_fun_resources(ddf_fun_t *fnode) 111 104 { 112 105 isa_fun_t *fun = isa_fun(fnode); 113 assert(fun );106 assert(fun != NULL); 114 107 115 108 return &fun->hw_resources; 116 109 } 117 110 118 static bool isa_ fun_enable_interrupt(ddf_fun_t *fnode)111 static bool isa_enable_fun_interrupt(ddf_fun_t *fnode) 119 112 { 120 113 /* This is an old ugly way, copied from pci driver */ 121 114 assert(fnode); 122 115 isa_fun_t *fun = isa_fun(fnode); 123 assert(fun); 116 117 sysarg_t apic; 118 sysarg_t i8259; 119 120 async_sess_t *irc_sess = NULL; 121 122 if (((sysinfo_get_value("apic", &apic) == EOK) && (apic)) 123 || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) { 124 irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE, 125 SERVICE_IRC, 0, 0); 126 } 127 128 if (!irc_sess) 129 return false; 124 130 125 131 const hw_resource_list_t *res = &fun->hw_resources; … … 127 133 for (size_t i = 0; i < res->count; ++i) { 128 134 if (res->resources[i].type == INTERRUPT) { 129 int rc = irc_enable_interrupt( 130 res->resources[i].res.interrupt.irq); 131 132 if (rc != EOK) 135 const int irq = res->resources[i].res.interrupt.irq; 136 137 async_exch_t *exch = async_exchange_begin(irc_sess); 138 const int rc = 139 async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq); 140 async_exchange_end(exch); 141 142 if (rc != EOK) { 143 async_hangup(irc_sess); 133 144 return false; 145 } 134 146 } 135 147 } 136 148 149 async_hangup(irc_sess); 137 150 return true; 138 151 } 139 152 140 static int isa_ fun_setup_dma(ddf_fun_t *fnode,141 unsigned int channel, uint32_t pa, uint 32_t size, uint8_t mode)153 static int isa_dma_channel_fun_setup(ddf_fun_t *fnode, 154 unsigned int channel, uint32_t pa, uint16_t size, uint8_t mode) 142 155 { 143 156 assert(fnode); 144 157 isa_fun_t *fun = isa_fun(fnode); 145 assert(fun);146 158 const hw_resource_list_t *res = &fun->hw_resources; 147 159 assert(res); 148 160 161 const unsigned int ch = channel; 149 162 for (size_t i = 0; i < res->count; ++i) { 150 /* Check for assigned channel */151 163 if (((res->resources[i].type == DMA_CHANNEL_16) && 152 (res->resources[i].res.dma_channel.dma16 == ch annel)) ||164 (res->resources[i].res.dma_channel.dma16 == ch)) || 153 165 ((res->resources[i].type == DMA_CHANNEL_8) && 154 (res->resources[i].res.dma_channel.dma8 == ch annel))) {155 return dma_ channel_setup(channel, pa, size, mode);166 (res->resources[i].res.dma_channel.dma8 == ch))) { 167 return dma_setup_channel(channel, pa, size, mode); 156 168 } 157 169 } 158 170 159 171 return EINVAL; 160 172 } 161 173 162 static int isa_fun_remain_dma(ddf_fun_t *fnode,163 unsigned channel, size_t *size)164 {165 assert(size);166 assert(fnode);167 isa_fun_t *fun = isa_fun(fnode);168 assert(fun);169 const hw_resource_list_t *res = &fun->hw_resources;170 assert(res);171 172 for (size_t i = 0; i < res->count; ++i) {173 /* Check for assigned channel */174 if (((res->resources[i].type == DMA_CHANNEL_16) &&175 (res->resources[i].res.dma_channel.dma16 == channel)) ||176 ((res->resources[i].type == DMA_CHANNEL_8) &&177 (res->resources[i].res.dma_channel.dma8 == channel))) {178 return dma_channel_remain(channel, size);179 }180 }181 182 return EINVAL;183 }184 185 174 static hw_res_ops_t isa_fun_hw_res_ops = { 186 .get_resource_list = isa_fun_get_resources, 187 .enable_interrupt = isa_fun_enable_interrupt, 188 .dma_channel_setup = isa_fun_setup_dma, 189 .dma_channel_remain = isa_fun_remain_dma, 175 .get_resource_list = isa_get_fun_resources, 176 .enable_interrupt = isa_enable_fun_interrupt, 177 .dma_channel_setup = isa_dma_channel_fun_setup, 190 178 }; 191 179 192 static pio_window_t *isa_fun_get_pio_window(ddf_fun_t *fnode) 193 { 194 ddf_dev_t *dev = ddf_fun_get_dev(fnode); 195 isa_bus_t *isa = isa_bus(dev); 196 assert(isa); 197 198 return &isa->pio_win; 199 } 200 201 static pio_window_ops_t isa_fun_pio_window_ops = { 202 .get_pio_window = isa_fun_get_pio_window 203 }; 204 205 static ddf_dev_ops_t isa_fun_ops= { 206 .interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops, 207 .interfaces[PIO_WINDOW_DEV_IFACE] = &isa_fun_pio_window_ops, 208 }; 180 static ddf_dev_ops_t isa_fun_ops; 209 181 210 182 static int isa_dev_add(ddf_dev_t *dev); … … 240 212 241 213 fibril_mutex_initialize(&fun->mutex); 242 fun->hw_resources.resources = fun->resources;243 244 214 fun->fnode = fnode; 245 215 return fun; … … 252 222 bool opened = false; 253 223 int fd; 254 size_t len; 255 ssize_t r; 224 size_t len = 0; 256 225 257 226 fd = open(conf_path, O_RDONLY); … … 277 246 } 278 247 279 r = read(fd, buf, len); 280 if (r < 0) { 248 if (0 >= read(fd, buf, len)) { 281 249 ddf_msg(LVL_ERROR, "Unable to read file '%s'.", conf_path); 282 250 goto cleanup; … … 302 270 { 303 271 char *line = str; 304 *next = NULL;305 272 306 273 if (str == NULL) { 274 *next = NULL; 307 275 return NULL; 308 276 } … … 314 282 if (*str != '\0') { 315 283 *next = str + 1; 284 } else { 285 *next = NULL; 316 286 } 317 287 … … 339 309 340 310 /* Get the name part of the rest of the line. */ 341 str_tok(line, ":", NULL); 342 return line; 343 } 344 345 static inline const char *skip_spaces(const char *line) 311 strtok(line, ":"); 312 313 /* Allocate output buffer. */ 314 size_t size = str_size(line) + 1; 315 char *name = malloc(size); 316 317 if (name != NULL) { 318 /* Copy the result to the output buffer. */ 319 str_cpy(name, size, line); 320 } 321 322 return name; 323 } 324 325 static inline char *skip_spaces(char *line) 346 326 { 347 327 /* Skip leading spaces. */ … … 352 332 } 353 333 354 static void isa_fun_ add_irq(isa_fun_t *fun, int irq)334 static void isa_fun_set_irq(isa_fun_t *fun, int irq) 355 335 { 356 336 size_t count = fun->hw_resources.count; … … 368 348 } 369 349 370 static void isa_fun_ add_dma(isa_fun_t *fun, int dma)350 static void isa_fun_set_dma(isa_fun_t *fun, int dma) 371 351 { 372 352 size_t count = fun->hw_resources.count; … … 401 381 } 402 382 403 static void isa_fun_ add_io_range(isa_fun_t *fun, size_t addr, size_t len)383 static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len) 404 384 { 405 385 size_t count = fun->hw_resources.count; 406 386 hw_resource_t *resources = fun->hw_resources.resources; 407 408 isa_bus_t *isa = isa_bus(ddf_fun_get_dev(fun->fnode));409 387 410 388 if (count < ISA_MAX_HW_RES) { 411 389 resources[count].type = IO_RANGE; 412 390 resources[count].res.io_range.address = addr; 413 resources[count].res.io_range.address += isa->pio_win.io.base;414 391 resources[count].res.io_range.size = len; 415 resources[count].res.io_range.relative = false;416 392 resources[count].res.io_range.endianness = LITTLE_ENDIAN; 417 393 … … 424 400 } 425 401 426 static void fun_parse_irq(isa_fun_t *fun, c onst char *val)402 static void fun_parse_irq(isa_fun_t *fun, char *val) 427 403 { 428 404 int irq = 0; … … 433 409 434 410 if (val != end) 435 isa_fun_add_irq(fun, irq); 436 } 437 438 static void fun_parse_dma(isa_fun_t *fun, const char *val) 439 { 411 isa_fun_set_irq(fun, irq); 412 } 413 414 static void fun_parse_dma(isa_fun_t *fun, char *val) 415 { 416 unsigned int dma = 0; 440 417 char *end = NULL; 441 418 442 419 val = skip_spaces(val); 443 const int dma =strtol(val, &end, 10);420 dma = (unsigned int) strtol(val, &end, 10); 444 421 445 422 if (val != end) 446 isa_fun_ add_dma(fun, dma);447 } 448 449 static void fun_parse_io_range(isa_fun_t *fun, c onst char *val)423 isa_fun_set_dma(fun, dma); 424 } 425 426 static void fun_parse_io_range(isa_fun_t *fun, char *val) 450 427 { 451 428 size_t addr, len; … … 464 441 return; 465 442 466 isa_fun_ add_io_range(fun, addr, len);467 } 468 469 static void get_match_id(char **id, c onst char *val)470 { 471 c onst char *end = val;443 isa_fun_set_io_range(fun, addr, len); 444 } 445 446 static void get_match_id(char **id, char *val) 447 { 448 char *end = val; 472 449 473 450 while (!isspace(*end)) … … 479 456 } 480 457 481 static void fun_parse_match_id(isa_fun_t *fun, c onst char *val)458 static void fun_parse_match_id(isa_fun_t *fun, char *val) 482 459 { 483 460 char *id = NULL; 461 int score = 0; 484 462 char *end = NULL; 463 int rc; 485 464 486 465 val = skip_spaces(val); 487 466 488 intscore = (int)strtol(val, &end, 10);467 score = (int)strtol(val, &end, 10); 489 468 if (val == end) { 490 469 ddf_msg(LVL_ERROR, "Cannot read match score for function " … … 504 483 "function %s", id, score, ddf_fun_get_name(fun->fnode)); 505 484 506 intrc = ddf_fun_add_match_id(fun->fnode, id, score);485 rc = ddf_fun_add_match_id(fun->fnode, id, score); 507 486 if (rc != EOK) { 508 487 ddf_msg(LVL_ERROR, "Failed adding match ID: %s", … … 513 492 } 514 493 515 static bool prop_parse(isa_fun_t *fun, c onst char *line, const char *prop,516 void (*read_fn)(isa_fun_t *, c onst char *))494 static bool prop_parse(isa_fun_t *fun, char *line, const char *prop, 495 void (*read_fn)(isa_fun_t *, char *)) 517 496 { 518 497 size_t proplen = str_size(prop); … … 529 508 } 530 509 531 static void fun_prop_parse(isa_fun_t *fun, c onst char *line)510 static void fun_prop_parse(isa_fun_t *fun, char *line) 532 511 { 533 512 /* Skip leading spaces. */ … … 544 523 } 545 524 525 static void fun_hw_res_alloc(isa_fun_t *fun) 526 { 527 fun->hw_resources.resources = 528 (hw_resource_t *) malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES); 529 } 530 531 static void fun_hw_res_free(isa_fun_t *fun) 532 { 533 free(fun->hw_resources.resources); 534 fun->hw_resources.resources = NULL; 535 } 536 546 537 static char *isa_fun_read_info(char *fun_conf, isa_bus_t *isa) 547 538 { 548 539 char *line; 540 char *fun_name = NULL; 549 541 550 542 /* Skip empty lines. */ 551 do{543 while (true) { 552 544 line = str_get_line(fun_conf, &fun_conf); 553 545 … … 557 549 } 558 550 559 } while (line_empty(line)); 551 if (!line_empty(line)) 552 break; 553 } 560 554 561 555 /* Get device name. */ 562 const char *fun_name = get_device_name(line);556 fun_name = get_device_name(line); 563 557 if (fun_name == NULL) 564 558 return NULL; 565 559 566 560 isa_fun_t *fun = isa_fun_create(isa, fun_name); 561 free(fun_name); 567 562 if (fun == NULL) { 568 563 return NULL; 569 564 } 565 566 /* Allocate buffer for the list of hardware resources of the device. */ 567 fun_hw_res_alloc(fun); 570 568 571 569 /* Get properties of the device (match ids, irq and io range). */ … … 598 596 } 599 597 600 static void isa_functions_add(isa_bus_t *isa) 601 { 602 #define BASE_CLASS_BRIDGE 0x06 603 #define SUB_CLASS_BRIDGE_ISA 0x01 604 bool isa_bridge = ((isa->pci_class == BASE_CLASS_BRIDGE) && 605 (isa->pci_subclass == SUB_CLASS_BRIDGE_ISA)); 606 607 #define VENDOR_ID_SUN 0x108e 608 #define DEVICE_ID_EBUS 0x1000 609 bool ebus = ((isa->pci_vendor_id == VENDOR_ID_SUN) && 610 (isa->pci_device_id == DEVICE_ID_EBUS)); 611 612 const char *conf_path = NULL; 613 if (isa_bridge) 614 conf_path = ISA_CHILD_FUN_CONF_PATH; 615 else if (ebus) 616 conf_path = EBUS_CHILD_FUN_CONF_PATH; 617 618 char *conf = fun_conf_read(conf_path); 598 static void fun_conf_parse(char *conf, isa_bus_t *isa) 599 { 619 600 while (conf != NULL && *conf != '\0') { 620 601 conf = isa_fun_read_info(conf, isa); 621 602 } 622 free(conf); 603 } 604 605 static void isa_functions_add(isa_bus_t *isa) 606 { 607 char *fun_conf; 608 609 fun_conf = fun_conf_read(CHILD_FUN_CONF_PATH); 610 if (fun_conf != NULL) { 611 fun_conf_parse(fun_conf, isa); 612 free(fun_conf); 613 } 623 614 } 624 615 625 616 static int isa_dev_add(ddf_dev_t *dev) 626 617 { 627 async_sess_t *sess; 628 int rc; 618 isa_bus_t *isa; 629 619 630 620 ddf_msg(LVL_DEBUG, "isa_dev_add, device handle = %d", 631 621 (int) ddf_dev_get_handle(dev)); 632 622 633 isa _bus_t *isa= ddf_dev_data_alloc(dev, sizeof(isa_bus_t));623 isa = ddf_dev_data_alloc(dev, sizeof(isa_bus_t)); 634 624 if (isa == NULL) 635 625 return ENOMEM; … … 638 628 isa->dev = dev; 639 629 list_initialize(&isa->functions); 640 641 sess = ddf_dev_parent_sess_create(dev);642 if (sess == NULL) {643 ddf_msg(LVL_ERROR, "isa_dev_add failed to connect to the "644 "parent driver.");645 return ENOENT;646 }647 648 rc = pci_config_space_read_16(sess, PCI_VENDOR_ID, &isa->pci_vendor_id);649 if (rc != EOK)650 return rc;651 rc = pci_config_space_read_16(sess, PCI_DEVICE_ID, &isa->pci_device_id);652 if (rc != EOK)653 return rc;654 rc = pci_config_space_read_8(sess, PCI_BASE_CLASS, &isa->pci_class);655 if (rc != EOK)656 return rc;657 rc = pci_config_space_read_8(sess, PCI_SUB_CLASS, &isa->pci_subclass);658 if (rc != EOK)659 return rc;660 661 rc = pio_window_get(sess, &isa->pio_win);662 if (rc != EOK) {663 ddf_msg(LVL_ERROR, "isa_dev_add failed to get PIO window "664 "for the device.");665 return rc;666 }667 630 668 631 /* Make the bus device more visible. Does not do anything. */ … … 695 658 { 696 659 isa_bus_t *isa = isa_bus(dev); 660 int rc; 697 661 698 662 fibril_mutex_lock(&isa->mutex); … … 702 666 isa_fun_t, bus_link); 703 667 704 intrc = ddf_fun_offline(fun->fnode);668 rc = ddf_fun_offline(fun->fnode); 705 669 if (rc != EOK) { 706 670 fibril_mutex_unlock(&isa->mutex); … … 718 682 list_remove(&fun->bus_link); 719 683 684 fun_hw_res_free(fun); 720 685 ddf_fun_destroy(fun->fnode); 721 686 } … … 744 709 } 745 710 711 712 static void isa_init() 713 { 714 ddf_log_init(NAME); 715 isa_fun_ops.interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops; 716 } 717 746 718 int main(int argc, char *argv[]) 747 719 { 748 720 printf(NAME ": HelenOS ISA bus driver\n"); 749 ddf_log_init(NAME);721 isa_init(); 750 722 return ddf_driver_main(&isa_driver); 751 723 }
Note:
See TracChangeset
for help on using the changeset viewer.