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