Changeset 8b655705 in mainline for uspace/drv/isa/isa.c


Ignore:
Timestamp:
2011-04-15T19:38:07Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9dd730d1
Parents:
6b9e85b (diff), b2fb47f (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.
Message:

Merge mainline changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/isa/isa.c

    r6b9e85b r8b655705  
    11/*
    22 * Copyright (c) 2010 Lenka Trochtova
     3 * Copyright (c) 2011 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    4344#include <stdlib.h>
    4445#include <str.h>
     46#include <str_error.h>
    4547#include <ctype.h>
    4648#include <macros.h>
     
    5052#include <sys/stat.h>
    5153
    52 #include <driver.h>
     54#include <ddf/driver.h>
     55#include <ddf/log.h>
    5356#include <ops/hw_res.h>
    5457
     
    5861
    5962#define NAME "isa"
    60 #define CHILD_DEV_CONF_PATH "/drv/isa/isa.dev"
     63#define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
     64
     65/** Obtain soft-state pointer from function node pointer */
     66#define ISA_FUN(fnode) ((isa_fun_t *) ((fnode)->driver_data))
    6167
    6268#define ISA_MAX_HW_RES 4
    6369
    64 typedef struct isa_child_data {
     70typedef struct isa_fun {
     71        ddf_fun_t *fnode;
    6572        hw_resource_list_t hw_resources;
    66 } isa_child_data_t;
    67 
    68 static hw_resource_list_t *isa_get_child_resources(device_t *dev)
    69 {
    70         isa_child_data_t *dev_data;
    71 
    72         dev_data = (isa_child_data_t *)dev->driver_data;
    73         if (dev_data == NULL)
    74                 return NULL;
    75 
    76         return &dev_data->hw_resources;
    77 }
    78 
    79 static bool isa_enable_child_interrupt(device_t *dev)
    80 {
    81         // TODO
     73} isa_fun_t;
     74
     75static hw_resource_list_t *isa_get_fun_resources(ddf_fun_t *fnode)
     76{
     77        isa_fun_t *fun = ISA_FUN(fnode);
     78        assert(fun != NULL);
     79
     80        return &fun->hw_resources;
     81}
     82
     83static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
     84{
     85        /* TODO */
    8286
    8387        return false;
    8488}
    8589
    86 static hw_res_ops_t isa_child_hw_res_ops = {
    87         &isa_get_child_resources,
    88         &isa_enable_child_interrupt
     90static hw_res_ops_t isa_fun_hw_res_ops = {
     91        &isa_get_fun_resources,
     92        &isa_enable_fun_interrupt
    8993};
    9094
    91 static device_ops_t isa_child_dev_ops;
    92 
    93 static int isa_add_device(device_t *dev);
     95static ddf_dev_ops_t isa_fun_ops;
     96
     97static int isa_add_device(ddf_dev_t *dev);
    9498
    9599/** The isa device driver's standard operations */
     
    104108};
    105109
    106 
    107 static isa_child_data_t *create_isa_child_data()
    108 {
    109         isa_child_data_t *data;
    110 
    111         data = (isa_child_data_t *) malloc(sizeof(isa_child_data_t));
    112         if (data != NULL)
    113                 memset(data, 0, sizeof(isa_child_data_t));
    114 
    115         return data;
    116 }
    117 
    118 static device_t *create_isa_child_dev()
    119 {
    120         device_t *dev = create_device();
    121         if (dev == NULL)
     110static 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));
     113        if (fun == NULL)
    122114                return NULL;
    123115
    124         isa_child_data_t *data = create_isa_child_data();
    125         if (data == NULL) {
    126                 delete_device(dev);
     116        ddf_fun_t *fnode = ddf_fun_create(dev, fun_inner, name);
     117        if (fnode == NULL) {
     118                free(fun);
    127119                return NULL;
    128120        }
    129121
    130         dev->driver_data = data;
    131         return dev;
    132 }
    133 
    134 static char *read_dev_conf(const char *conf_path)
     122        fun->fnode = fnode;
     123        fnode->driver_data = fun;
     124        return fun;
     125}
     126
     127static char *fun_conf_read(const char *conf_path)
    135128{
    136129        bool suc = false;
     
    142135        fd = open(conf_path, O_RDONLY);
    143136        if (fd < 0) {
    144                 printf(NAME ": unable to open %s\n", conf_path);
     137                ddf_msg(LVL_ERROR, "Unable to open %s", conf_path);
    145138                goto cleanup;
    146139        }
     
    149142
    150143        len = lseek(fd, 0, SEEK_END);
    151         lseek(fd, 0, SEEK_SET); 
     144        lseek(fd, 0, SEEK_SET);
    152145        if (len == 0) {
    153                 printf(NAME ": read_dev_conf error: configuration file '%s' "
    154                     "is empty.\n", conf_path);
     146                ddf_msg(LVL_ERROR, "Configuration file '%s' is empty.",
     147                    conf_path);
    155148                goto cleanup;
    156149        }
     
    158151        buf = malloc(len + 1);
    159152        if (buf == NULL) {
    160                 printf(NAME ": read_dev_conf error: memory allocation failed.\n");
     153                ddf_msg(LVL_ERROR, "Memory allocation failed.");
    161154                goto cleanup;
    162155        }
    163156
    164157        if (0 >= read(fd, buf, len)) {
    165                 printf(NAME ": read_dev_conf error: unable to read file '%s'.\n",
    166                     conf_path);
     158                ddf_msg(LVL_ERROR, "Unable to read file '%s'.", conf_path);
    167159                goto cleanup;
    168160        }
     
    249241}
    250242
    251 static void isa_child_set_irq(device_t *dev, int irq)
    252 {
    253         isa_child_data_t *data = (isa_child_data_t *)dev->driver_data;
    254 
    255         size_t count = data->hw_resources.count;
    256         hw_resource_t *resources = data->hw_resources.resources;
     243static void isa_fun_set_irq(isa_fun_t *fun, int irq)
     244{
     245        size_t count = fun->hw_resources.count;
     246        hw_resource_t *resources = fun->hw_resources.resources;
    257247
    258248        if (count < ISA_MAX_HW_RES) {
     
    260250                resources[count].res.interrupt.irq = irq;
    261251
    262                 data->hw_resources.count++;
    263 
    264                 printf(NAME ": added irq 0x%x to device %s\n", irq, dev->name);
    265         }
    266 }
    267 
    268 static void isa_child_set_io_range(device_t *dev, size_t addr, size_t len)
    269 {
    270         isa_child_data_t *data = (isa_child_data_t *)dev->driver_data;
    271 
    272         size_t count = data->hw_resources.count;
    273         hw_resource_t *resources = data->hw_resources.resources;
     252                fun->hw_resources.count++;
     253
     254                ddf_msg(LVL_NOTE, "Added irq 0x%x to function %s", irq,
     255                    fun->fnode->name);
     256        }
     257}
     258
     259static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len)
     260{
     261        size_t count = fun->hw_resources.count;
     262        hw_resource_t *resources = fun->hw_resources.resources;
    274263
    275264        if (count < ISA_MAX_HW_RES) {
     
    279268                resources[count].res.io_range.endianness = LITTLE_ENDIAN;
    280269
    281                 data->hw_resources.count++;
    282 
    283                 printf(NAME ": added io range (addr=0x%x, size=0x%x) to "
    284                     "device %s\n", (unsigned int) addr, (unsigned int) len,
    285                     dev->name);
    286         }
    287 }
    288 
    289 static void get_dev_irq(device_t *dev, char *val)
     270                fun->hw_resources.count++;
     271
     272                ddf_msg(LVL_NOTE, "Added io range (addr=0x%x, size=0x%x) to "
     273                    "function %s", (unsigned int) addr, (unsigned int) len,
     274                    fun->fnode->name);
     275        }
     276}
     277
     278static void fun_parse_irq(isa_fun_t *fun, char *val)
    290279{
    291280        int irq = 0;
    292281        char *end = NULL;
    293282
    294         val = skip_spaces(val); 
     283        val = skip_spaces(val);
    295284        irq = (int)strtol(val, &end, 0x10);
    296285
    297286        if (val != end)
    298                 isa_child_set_irq(dev, irq);
    299 }
    300 
    301 static void get_dev_io_range(device_t *dev, char *val)
     287                isa_fun_set_irq(fun, irq);
     288}
     289
     290static void fun_parse_io_range(isa_fun_t *fun, char *val)
    302291{
    303292        size_t addr, len;
    304293        char *end = NULL;
    305294
    306         val = skip_spaces(val); 
     295        val = skip_spaces(val);
    307296        addr = strtol(val, &end, 0x10);
    308297
     
    310299                return;
    311300
    312         val = skip_spaces(end); 
     301        val = skip_spaces(end);
    313302        len = strtol(val, &end, 0x10);
    314303
     
    316305                return;
    317306
    318         isa_child_set_io_range(dev, addr, len);
     307        isa_fun_set_io_range(fun, addr, len);
    319308}
    320309
     
    331320}
    332321
    333 static void get_dev_match_id(device_t *dev, char *val)
     322static void fun_parse_match_id(isa_fun_t *fun, char *val)
    334323{
    335324        char *id = NULL;
    336325        int score = 0;
    337326        char *end = NULL;
    338 
    339         val = skip_spaces(val);
     327        int rc;
     328
     329        val = skip_spaces(val);
    340330
    341331        score = (int)strtol(val, &end, 10);
    342332        if (val == end) {
    343                 printf(NAME " : error - could not read match score for "
    344                     "device %s.\n", dev->name);
     333                ddf_msg(LVL_ERROR, "Cannot read match score for function "
     334                    "%s.", fun->fnode->name);
    345335                return;
    346336        }
    347337
    348         match_id_t *match_id = create_match_id();
    349         if (match_id == NULL) {
    350                 printf(NAME " : failed to allocate match id for device %s.\n",
    351                     dev->name);
    352                 return;
    353         }
    354 
    355         val = skip_spaces(end);
     338        val = skip_spaces(end);
    356339        get_match_id(&id, val);
    357340        if (id == NULL) {
    358                 printf(NAME " : error - could not read match id for "
    359                     "device %s.\n", dev->name);
    360                 delete_match_id(match_id);
     341                ddf_msg(LVL_ERROR, "Cannot read match ID for function %s.",
     342                    fun->fnode->name);
    361343                return;
    362344        }
    363345
    364         match_id->id = id;
    365         match_id->score = score;
    366 
    367         printf(NAME ": adding match id '%s' with score %d to device %s\n", id,
    368             score, dev->name);
    369         add_match_id(&dev->match_ids, match_id);
    370 }
    371 
    372 static bool read_dev_prop(device_t *dev, char *line, const char *prop,
    373     void (*read_fn)(device_t *, char *))
     346        ddf_msg(LVL_DEBUG, "Adding match id '%s' with score %d to "
     347            "function %s", id, score, fun->fnode->name);
     348
     349        rc = ddf_fun_add_match_id(fun->fnode, id, score);
     350        if (rc != EOK) {
     351                ddf_msg(LVL_ERROR, "Failed adding match ID: %s",
     352                    str_error(rc));
     353        }
     354}
     355
     356static bool prop_parse(isa_fun_t *fun, char *line, const char *prop,
     357    void (*read_fn)(isa_fun_t *, char *))
    374358{
    375359        size_t proplen = str_size(prop);
     
    378362                line += proplen;
    379363                line = skip_spaces(line);
    380                 (*read_fn)(dev, line);
     364                (*read_fn)(fun, line);
    381365
    382366                return true;
     
    386370}
    387371
    388 static void get_dev_prop(device_t *dev, char *line)
     372static void fun_prop_parse(isa_fun_t *fun, char *line)
    389373{
    390374        /* Skip leading spaces. */
    391375        line = skip_spaces(line);
    392376
    393         if (!read_dev_prop(dev, line, "io_range", &get_dev_io_range) &&
    394             !read_dev_prop(dev, line, "irq", &get_dev_irq) &&
    395             !read_dev_prop(dev, line, "match", &get_dev_match_id))
    396         {
    397             printf(NAME " error undefined device property at line '%s'\n",
    398                 line);
    399         }
    400 }
    401 
    402 static void child_alloc_hw_res(device_t *dev)
    403 {
    404         isa_child_data_t *data = (isa_child_data_t *)dev->driver_data;
    405         data->hw_resources.resources =
     377        if (!prop_parse(fun, line, "io_range", &fun_parse_io_range) &&
     378            !prop_parse(fun, line, "irq", &fun_parse_irq) &&
     379            !prop_parse(fun, line, "match", &fun_parse_match_id)) {
     380
     381                ddf_msg(LVL_ERROR, "Undefined device property at line '%s'",
     382                    line);
     383        }
     384}
     385
     386static void fun_hw_res_alloc(isa_fun_t *fun)
     387{
     388        fun->hw_resources.resources =
    406389            (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
    407390}
    408391
    409 static char *read_isa_dev_info(char *dev_conf, device_t *parent)
     392static char *isa_fun_read_info(char *fun_conf, ddf_dev_t *dev)
    410393{
    411394        char *line;
    412         char *dev_name = NULL;
     395        char *fun_name = NULL;
    413396
    414397        /* Skip empty lines. */
    415398        while (true) {
    416                 line = str_get_line(dev_conf, &dev_conf);
     399                line = str_get_line(fun_conf, &fun_conf);
    417400
    418401                if (line == NULL) {
     
    426409
    427410        /* Get device name. */
    428         dev_name = get_device_name(line);
    429         if (dev_name == NULL)
     411        fun_name = get_device_name(line);
     412        if (fun_name == NULL)
    430413                return NULL;
    431414
    432         device_t *dev = create_isa_child_dev();
    433         if (dev == NULL) {
    434                 free(dev_name);
     415        isa_fun_t *fun = isa_fun_create(dev, fun_name);
     416        if (fun == NULL) {
     417                free(fun_name);
    435418                return NULL;
    436419        }
    437420
    438         dev->name = dev_name;
    439 
    440421        /* Allocate buffer for the list of hardware resources of the device. */
    441         child_alloc_hw_res(dev);
     422        fun_hw_res_alloc(fun);
    442423
    443424        /* Get properties of the device (match ids, irq and io range). */
    444425        while (true) {
    445                 line = str_get_line(dev_conf, &dev_conf);
     426                line = str_get_line(fun_conf, &fun_conf);
    446427
    447428                if (line_empty(line)) {
     
    454435                 * and store it in the device structure.
    455436                 */
    456                 get_dev_prop(dev, line);
    457 
    458                 //printf(NAME ": next line ='%s'\n", dev_conf);
    459                 //printf(NAME ": current line ='%s'\n", line);
     437                fun_prop_parse(fun, line);
    460438        }
    461439
    462440        /* Set device operations to the device. */
    463         dev->ops = &isa_child_dev_ops;
    464 
    465         printf(NAME ": child_device_register(dev, parent); device is %s.\n",
    466             dev->name);
    467         child_device_register(dev, parent);
    468 
    469         return dev_conf;
    470 }
    471 
    472 static void parse_dev_conf(char *conf, device_t *parent)
     441        fun->fnode->ops = &isa_fun_ops;
     442
     443        ddf_msg(LVL_DEBUG, "Binding function %s.", fun->fnode->name);
     444
     445        /* XXX Handle error */
     446        (void) ddf_fun_bind(fun->fnode);
     447
     448        return fun_conf;
     449}
     450
     451static void fun_conf_parse(char *conf, ddf_dev_t *dev)
    473452{
    474453        while (conf != NULL && *conf != '\0') {
    475                 conf = read_isa_dev_info(conf, parent);
    476         }
    477 }
    478 
    479 static void add_legacy_children(device_t *parent)
    480 {
    481         char *dev_conf;
    482 
    483         dev_conf = read_dev_conf(CHILD_DEV_CONF_PATH);
    484         if (dev_conf != NULL) {
    485                 parse_dev_conf(dev_conf, parent);
    486                 free(dev_conf);
    487         }
    488 }
    489 
    490 static int isa_add_device(device_t *dev)
    491 {
    492         printf(NAME ": isa_add_device, device handle = %d\n",
     454                conf = isa_fun_read_info(conf, dev);
     455        }
     456}
     457
     458static void isa_functions_add(ddf_dev_t *dev)
     459{
     460        char *fun_conf;
     461
     462        fun_conf = fun_conf_read(CHILD_FUN_CONF_PATH);
     463        if (fun_conf != NULL) {
     464                fun_conf_parse(fun_conf, dev);
     465                free(fun_conf);
     466        }
     467}
     468
     469static int isa_add_device(ddf_dev_t *dev)
     470{
     471        ddf_msg(LVL_DEBUG, "isa_add_device, device handle = %d",
    493472            (int) dev->handle);
    494473
    495         /* Add child devices. */
    496         add_legacy_children(dev);
    497         printf(NAME ": finished the enumeration of legacy devices\n");
     474        /* Make the bus device more visible. Does not do anything. */
     475        ddf_msg(LVL_DEBUG, "Adding a 'ctl' function");
     476
     477        ddf_fun_t *ctl = ddf_fun_create(dev, fun_exposed, "ctl");
     478        if (ctl == NULL) {
     479                ddf_msg(LVL_ERROR, "Failed creating control function.");
     480                return EXDEV;
     481        }
     482
     483        if (ddf_fun_bind(ctl) != EOK) {
     484                ddf_msg(LVL_ERROR, "Failed binding control function.");
     485                return EXDEV;
     486        }
     487
     488        /* Add functions as specified in the configuration file. */
     489        isa_functions_add(dev);
     490        ddf_msg(LVL_NOTE, "Finished enumerating legacy functions");
    498491
    499492        return EOK;
     
    502495static void isa_init()
    503496{
    504         isa_child_dev_ops.interfaces[HW_RES_DEV_IFACE] = &isa_child_hw_res_ops;
     497        ddf_log_init(NAME, LVL_ERROR);
     498        isa_fun_ops.interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops;
    505499}
    506500
     
    509503        printf(NAME ": HelenOS ISA bus driver\n");
    510504        isa_init();
    511         return driver_main(&isa_driver);
     505        return ddf_driver_main(&isa_driver);
    512506}
    513507
     
    515509 * @}
    516510 */
    517  
Note: See TracChangeset for help on using the changeset viewer.