Changeset 0c968a17 in mainline


Ignore:
Timestamp:
2011-02-15T22:58:28Z (14 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8b1ea2d4
Parents:
6a343bdf (diff), aa7dc64 (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 DDF and drivers refactoring work. Major points:

  • Split driver.h into ddf/driver.h and ddf/interrupt.h
  • Rename entities in ddf/driver.h (now they start with 'ddf_')
  • Refactor driver.h API (ddf_fun_create/destroy/bind, for example)
  • Refactor drivers to use soft-state structures for context
Location:
uspace
Files:
1 added
25 edited
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/app/tester/hw/serial/serial1.c

    r6a343bdf r0c968a17  
    7474       
    7575        devman_handle_t handle;
    76         res = devman_device_get_handle("/hw/pci0/00:01.0/com1", &handle,
     76        res = devman_device_get_handle("/hw/pci0/00:01.0/com1/a", &handle,
    7777            IPC_FLAG_BLOCKING);
    7878        if (res != EOK)
  • uspace/drv/isa/isa.c

    r6a343bdf r0c968a17  
    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>
    5355#include <ops/hw_res.h>
    5456
     
    5860
    5961#define NAME "isa"
    60 #define CHILD_DEV_CONF_PATH "/drv/isa/isa.dev"
     62#define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
     63
     64/** Obtain soft-state pointer from function node pointer */
     65#define ISA_FUN(fnode) ((isa_fun_t *) ((fnode)->driver_data))
    6166
    6267#define ISA_MAX_HW_RES 4
    6368
    64 typedef struct isa_child_data {
     69typedef struct isa_fun {
     70        ddf_fun_t *fnode;
    6571        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)
     72} isa_fun_t;
     73
     74static hw_resource_list_t *isa_get_fun_resources(ddf_fun_t *fnode)
     75{
     76        isa_fun_t *fun = ISA_FUN(fnode);
     77        assert(fun != NULL);
     78
     79        return &fun->hw_resources;
     80}
     81
     82static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
    8083{
    8184        // TODO
     
    8487}
    8588
    86 static hw_res_ops_t isa_child_hw_res_ops = {
    87         &isa_get_child_resources,
    88         &isa_enable_child_interrupt
     89static hw_res_ops_t isa_fun_hw_res_ops = {
     90        &isa_get_fun_resources,
     91        &isa_enable_fun_interrupt
    8992};
    9093
    91 static device_ops_t isa_child_dev_ops;
    92 
    93 static int isa_add_device(device_t *dev);
     94static ddf_dev_ops_t isa_fun_ops;
     95
     96static int isa_add_device(ddf_dev_t *dev);
    9497
    9598/** The isa device driver's standard operations */
     
    104107};
    105108
    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)
     109static isa_fun_t *isa_fun_create(ddf_dev_t *dev, const char *name)
     110{
     111        isa_fun_t *fun = calloc(1, sizeof(isa_fun_t));
     112        if (fun == NULL)
    122113                return NULL;
    123114
    124         isa_child_data_t *data = create_isa_child_data();
    125         if (data == NULL) {
    126                 delete_device(dev);
     115        ddf_fun_t *fnode = ddf_fun_create(dev, fun_inner, name);
     116        if (fnode == NULL) {
     117                free(fun);
    127118                return NULL;
    128119        }
    129120
    130         dev->driver_data = data;
    131         return dev;
    132 }
    133 
    134 static char *read_dev_conf(const char *conf_path)
     121        fun->fnode = fnode;
     122        fnode->driver_data = fun;
     123        return fun;
     124}
     125
     126static char *fun_conf_read(const char *conf_path)
    135127{
    136128        bool suc = false;
     
    151143        lseek(fd, 0, SEEK_SET);
    152144        if (len == 0) {
    153                 printf(NAME ": read_dev_conf error: configuration file '%s' "
     145                printf(NAME ": fun_conf_read error: configuration file '%s' "
    154146                    "is empty.\n", conf_path);
    155147                goto cleanup;
     
    158150        buf = malloc(len + 1);
    159151        if (buf == NULL) {
    160                 printf(NAME ": read_dev_conf error: memory allocation failed.\n");
     152                printf(NAME ": fun_conf_read error: memory allocation failed.\n");
    161153                goto cleanup;
    162154        }
    163155
    164156        if (0 >= read(fd, buf, len)) {
    165                 printf(NAME ": read_dev_conf error: unable to read file '%s'.\n",
     157                printf(NAME ": fun_conf_read error: unable to read file '%s'.\n",
    166158                    conf_path);
    167159                goto cleanup;
     
    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                printf(NAME ": added irq 0x%x to function %s\n", 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++;
     270                fun->hw_resources.count++;
    282271
    283272                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)
     273                    "function %s\n", (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) {
    343333                printf(NAME " : error - could not read match score for "
    344                     "device %s.\n", dev->name);
     334                    "function %s.\n", 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) {
    358341                printf(NAME " : error - could not read match id for "
    359                     "device %s.\n", dev->name);
    360                 delete_match_id(match_id);
     342                    "function %s.\n", 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        printf(NAME ": adding match id '%s' with score %d to function %s\n", id,
     347            score, fun->fnode->name);
     348
     349        rc = ddf_fun_add_match_id(fun->fnode, id, score);
     350        if (rc != EOK)
     351                printf(NAME ": error adding match ID: %s\n", str_error(rc));
     352}
     353
     354static bool prop_parse(isa_fun_t *fun, char *line, const char *prop,
     355    void (*read_fn)(isa_fun_t *, char *))
    374356{
    375357        size_t proplen = str_size(prop);
     
    378360                line += proplen;
    379361                line = skip_spaces(line);
    380                 (*read_fn)(dev, line);
     362                (*read_fn)(fun, line);
    381363
    382364                return true;
     
    386368}
    387369
    388 static void get_dev_prop(device_t *dev, char *line)
     370static void fun_prop_parse(isa_fun_t *fun, char *line)
    389371{
    390372        /* Skip leading spaces. */
    391373        line = skip_spaces(line);
    392374
    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))
     375        if (!prop_parse(fun, line, "io_range", &fun_parse_io_range) &&
     376            !prop_parse(fun, line, "irq", &fun_parse_irq) &&
     377            !prop_parse(fun, line, "match", &fun_parse_match_id))
    396378        {
    397379            printf(NAME " error undefined device property at line '%s'\n",
     
    400382}
    401383
    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 =
     384static void fun_hw_res_alloc(isa_fun_t *fun)
     385{
     386        fun->hw_resources.resources =
    406387            (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
    407388}
    408389
    409 static char *read_isa_dev_info(char *dev_conf, device_t *parent)
     390static char *isa_fun_read_info(char *fun_conf, ddf_dev_t *dev)
    410391{
    411392        char *line;
    412         char *dev_name = NULL;
     393        char *fun_name = NULL;
    413394
    414395        /* Skip empty lines. */
    415396        while (true) {
    416                 line = str_get_line(dev_conf, &dev_conf);
     397                line = str_get_line(fun_conf, &fun_conf);
    417398
    418399                if (line == NULL) {
     
    426407
    427408        /* Get device name. */
    428         dev_name = get_device_name(line);
    429         if (dev_name == NULL)
     409        fun_name = get_device_name(line);
     410        if (fun_name == NULL)
    430411                return NULL;
    431412
    432         device_t *dev = create_isa_child_dev();
    433         if (dev == NULL) {
    434                 free(dev_name);
     413        isa_fun_t *fun = isa_fun_create(dev, fun_name);
     414        if (fun == NULL) {
     415                free(fun_name);
    435416                return NULL;
    436417        }
    437418
    438         dev->name = dev_name;
    439 
    440419        /* Allocate buffer for the list of hardware resources of the device. */
    441         child_alloc_hw_res(dev);
     420        fun_hw_res_alloc(fun);
    442421
    443422        /* Get properties of the device (match ids, irq and io range). */
    444423        while (true) {
    445                 line = str_get_line(dev_conf, &dev_conf);
     424                line = str_get_line(fun_conf, &fun_conf);
    446425
    447426                if (line_empty(line)) {
     
    454433                 * and store it in the device structure.
    455434                 */
    456                 get_dev_prop(dev, line);
    457 
    458                 //printf(NAME ": next line ='%s'\n", dev_conf);
    459                 //printf(NAME ": current line ='%s'\n", line);
     435                fun_prop_parse(fun, line);
    460436        }
    461437
    462438        /* 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)
     439        fun->fnode->ops = &isa_fun_ops;
     440
     441        printf(NAME ": Binding function %s.\n", fun->fnode->name);
     442
     443        /* XXX Handle error */
     444        (void) ddf_fun_bind(fun->fnode);
     445
     446        return fun_conf;
     447}
     448
     449static void fun_conf_parse(char *conf, ddf_dev_t *dev)
    473450{
    474451        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)
     452                conf = isa_fun_read_info(conf, dev);
     453        }
     454}
     455
     456static void isa_functions_add(ddf_dev_t *dev)
     457{
     458        char *fun_conf;
     459
     460        fun_conf = fun_conf_read(CHILD_FUN_CONF_PATH);
     461        if (fun_conf != NULL) {
     462                fun_conf_parse(fun_conf, dev);
     463                free(fun_conf);
     464        }
     465}
     466
     467static int isa_add_device(ddf_dev_t *dev)
    491468{
    492469        printf(NAME ": isa_add_device, device handle = %d\n",
    493470            (int) dev->handle);
    494471
    495         /* Add child devices. */
    496         add_legacy_children(dev);
    497         printf(NAME ": finished the enumeration of legacy devices\n");
     472        /* Make the bus device more visible. Does not do anything. */
     473        printf(NAME ": adding a 'ctl' function\n");
     474
     475        ddf_fun_t *ctl = ddf_fun_create(dev, fun_exposed, "ctl");
     476        if (ctl == NULL) {
     477                printf(NAME ": Error creating control function.\n");
     478                return EXDEV;
     479        }
     480
     481        if (ddf_fun_bind(ctl) != EOK) {
     482                printf(NAME ": Error binding control function.\n");
     483                return EXDEV;
     484        }
     485
     486        /* Add functions as specified in the configuration file. */
     487        isa_functions_add(dev);
     488        printf(NAME ": finished the enumeration of legacy functions\n");
    498489
    499490        return EOK;
     
    502493static void isa_init()
    503494{
    504         isa_child_dev_ops.interfaces[HW_RES_DEV_IFACE] = &isa_child_hw_res_ops;
     495        isa_fun_ops.interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops;
    505496}
    506497
     
    509500        printf(NAME ": HelenOS ISA bus driver\n");
    510501        isa_init();
    511         return driver_main(&isa_driver);
     502        return ddf_driver_main(&isa_driver);
    512503}
    513504
     
    515506 * @}
    516507 */
    517  
  • uspace/drv/ns8250/ns8250.c

    r6a343bdf r0c968a17  
    11/*
    22 * Copyright (c) 2010 Lenka Trochtova
     3 * Copyright (c) 2011 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    5253#include <libarch/ddi.h>
    5354
    54 #include <driver.h>
     55#include <ddf/driver.h>
     56#include <ddf/interrupt.h>
    5557#include <ops/char_dev.h>
    5658
     
    6769#define MAX_BAUD_RATE 115200
    6870#define DLAB_MASK (1 << 7)
     71
     72/** Obtain soft-state structure from function node */
     73#define NS8250(fnode) ((ns8250_t *) ((fnode)->dev->driver_data))
     74
     75/** Obtain soft-state structure from device node */
     76#define NS8250_FROM_DEV(dnode) ((ns8250_t *) ((dnode)->driver_data))
    6977
    7078/** The number of bits of one data unit send by the serial port. */
     
    8593
    8694/** The driver data for the serial port devices. */
    87 typedef struct ns8250_dev_data {
     95typedef struct ns8250 {
     96        /** DDF device node */
     97        ddf_dev_t *dev;
     98        /** DDF function node */
     99        ddf_fun_t *fun;
    88100        /** Is there any client conntected to the device? */
    89101        bool client_connected;
     
    98110        /** The fibril mutex for synchronizing the access to the device. */
    99111        fibril_mutex_t mutex;
    100 } ns8250_dev_data_t;
    101 
    102 /** Create driver data for a device.
    103  *
    104  * @return              The driver data.
    105  */
    106 static ns8250_dev_data_t *create_ns8250_dev_data(void)
    107 {
    108         ns8250_dev_data_t *data;
    109        
    110         data = (ns8250_dev_data_t *) malloc(sizeof(ns8250_dev_data_t));
    111         if (NULL != data) {
    112                 memset(data, 0, sizeof(ns8250_dev_data_t));
    113                 fibril_mutex_initialize(&data->mutex);
    114         }
    115         return data;
    116 }
    117 
    118 /** Delete driver data.
    119  *
    120  * @param data          The driver data structure.
    121  */
    122 static void delete_ns8250_dev_data(ns8250_dev_data_t *data)
    123 {
    124         if (data != NULL)
    125                 free(data);
     112} ns8250_t;
     113
     114/** Create per-device soft-state structure.
     115 *
     116 * @return      Pointer to soft-state structure.
     117 */
     118static ns8250_t *ns8250_new(void)
     119{
     120        ns8250_t *ns;
     121       
     122        ns = (ns8250_t *) calloc(1, sizeof(ns8250_t));
     123        if (ns == NULL)
     124                return NULL;
     125       
     126        fibril_mutex_initialize(&ns->mutex);
     127        return ns;
     128}
     129
     130/** Delete soft-state structure.
     131 *
     132 * @param ns    The driver data structure.
     133 */
     134static void ns8250_delete(ns8250_t *ns)
     135{
     136        assert(ns != NULL);
     137        free(ns);
    126138}
    127139
     
    171183/** Read data from the serial port device.
    172184 *
    173  * @param dev           The serial port device.
     185 * @param fun           The serial port function
    174186 * @param buf           The ouput buffer for read data.
    175187 * @param count         The number of bytes to be read.
     
    178190 *                      error number otherwise.
    179191 */
    180 static int ns8250_read(device_t *dev, char *buf, size_t count)
    181 {
     192static int ns8250_read(ddf_fun_t *fun, char *buf, size_t count)
     193{
     194        ns8250_t *ns = NS8250(fun);
    182195        int ret = EOK;
    183         ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
    184        
    185         fibril_mutex_lock(&data->mutex);
    186         while (!buf_is_empty(&data->input_buffer) && (size_t)ret < count) {
    187                 buf[ret] = (char)buf_pop_front(&data->input_buffer);
     196       
     197        fibril_mutex_lock(&ns->mutex);
     198        while (!buf_is_empty(&ns->input_buffer) && (size_t)ret < count) {
     199                buf[ret] = (char)buf_pop_front(&ns->input_buffer);
    188200                ret++;
    189201        }
    190         fibril_mutex_unlock(&data->mutex);
     202        fibril_mutex_unlock(&ns->mutex);
    191203       
    192204        return ret;
     
    195207/** Write a character to the serial port.
    196208 *
    197  * @param data          The serial port device's driver data.
    198  * @param c             The character to be written.
    199  */
    200 static inline void ns8250_putchar(ns8250_dev_data_t *data, uint8_t c)
    201 {
    202         fibril_mutex_lock(&data->mutex);
    203         ns8250_write_8(data->port, c);
    204         fibril_mutex_unlock(&data->mutex);
     209 * @param ns            Serial port device
     210 * @param c             The character to be written
     211 */
     212static inline void ns8250_putchar(ns8250_t *ns, uint8_t c)
     213{
     214        fibril_mutex_lock(&ns->mutex);
     215        ns8250_write_8(ns->port, c);
     216        fibril_mutex_unlock(&ns->mutex);
    205217}
    206218
    207219/** Write data to the serial port.
    208220 *
    209  * @param dev           The serial port device.
    210  * @param buf           The data to be written.
    211  * @param count         The number of bytes to be written.
    212  * @return              Zero on success.
    213  */
    214 static int ns8250_write(device_t *dev, char *buf, size_t count)
    215 {
    216         ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
     221 * @param fun           The serial port function
     222 * @param buf           The data to be written
     223 * @param count         The number of bytes to be written
     224 * @return              Zero on success
     225 */
     226static int ns8250_write(ddf_fun_t *fun, char *buf, size_t count)
     227{
     228        ns8250_t *ns = NS8250(fun);
    217229        size_t idx;
    218230       
    219231        for (idx = 0; idx < count; idx++)
    220                 ns8250_putchar(data, (uint8_t) buf[idx]);
     232                ns8250_putchar(ns, (uint8_t) buf[idx]);
    221233       
    222234        return 0;
    223235}
    224236
    225 static device_ops_t ns8250_dev_ops;
     237static ddf_dev_ops_t ns8250_dev_ops;
    226238
    227239/** The character interface's callbacks. */
     
    231243};
    232244
    233 static int ns8250_add_device(device_t *dev);
     245static int ns8250_add_device(ddf_dev_t *dev);
    234246
    235247/** The serial port device driver's standard operations. */
     
    244256};
    245257
    246 /** Clean up the serial port device structure.
    247  *
    248  * @param dev           The device structure.
    249  */
    250 static void ns8250_dev_cleanup(device_t *dev)
    251 {
    252         if (dev->driver_data != NULL) {
    253                 delete_ns8250_dev_data((ns8250_dev_data_t*) dev->driver_data);
    254                 dev->driver_data = NULL;
    255         }
    256        
    257         if (dev->parent_phone > 0) {
    258                 async_hangup(dev->parent_phone);
    259                 dev->parent_phone = 0;
     258/** Clean up the serial port soft-state
     259 *
     260 * @param ns            Serial port device
     261 */
     262static void ns8250_dev_cleanup(ns8250_t *ns)
     263{
     264        if (ns->dev->parent_phone > 0) {
     265                async_hangup(ns->dev->parent_phone);
     266                ns->dev->parent_phone = 0;
    260267        }
    261268}
     
    263270/** Enable the i/o ports of the device.
    264271 *
    265  * @param dev           The serial port device.
    266  * @return              True on success, false otherwise.
    267  */
    268 static bool ns8250_pio_enable(device_t *dev)
    269 {
    270         printf(NAME ": ns8250_pio_enable %s\n", dev->name);
    271        
    272         ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
     272 * @param ns            Serial port device
     273 * @return              True on success, false otherwise
     274 */
     275static bool ns8250_pio_enable(ns8250_t *ns)
     276{
     277        printf(NAME ": ns8250_pio_enable %s\n", ns->dev->name);
    273278       
    274279        /* Gain control over port's registers. */
    275         if (pio_enable((void *)(uintptr_t) data->io_addr, REG_COUNT,
    276             (void **) &data->port)) {
     280        if (pio_enable((void *)(uintptr_t) ns->io_addr, REG_COUNT,
     281            (void **) &ns->port)) {
    277282                printf(NAME ": error - cannot gain the port %#" PRIx32 " for device "
    278                     "%s.\n", data->io_addr, dev->name);
     283                    "%s.\n", ns->io_addr, ns->dev->name);
    279284                return false;
    280285        }
     
    285290/** Probe the serial port device for its presence.
    286291 *
    287  * @param dev           The serial port device.
    288  * @return              True if the device is present, false otherwise.
    289  */
    290 static bool ns8250_dev_probe(device_t *dev)
    291 {
    292         printf(NAME ": ns8250_dev_probe %s\n", dev->name);
    293        
    294         ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
    295         ioport8_t *port_addr = data->port;
     292 * @param ns            Serial port device
     293 * @return              True if the device is present, false otherwise
     294 */
     295static bool ns8250_dev_probe(ns8250_t *ns)
     296{
     297        printf(NAME ": ns8250_dev_probe %s\n", ns->dev->name);
     298       
     299        ioport8_t *port_addr = ns->port;
    296300        bool res = true;
    297301        uint8_t olddata;
     
    310314       
    311315        if (!res)
    312                 printf(NAME ": device %s is not present.\n", dev->name);
     316                printf(NAME ": device %s is not present.\n", ns->dev->name);
    313317       
    314318        return res;
     
    317321/** Initialize serial port device.
    318322 *
    319  * @param dev           The serial port device.
    320  * @return              Zero on success, negative error number otherwise.
    321  */
    322 static int ns8250_dev_initialize(device_t *dev)
    323 {
    324         printf(NAME ": ns8250_dev_initialize %s\n", dev->name);
     323 * @param ns            Serial port device
     324 * @return              Zero on success, negative error number otherwise
     325 */
     326static int ns8250_dev_initialize(ns8250_t *ns)
     327{
     328        printf(NAME ": ns8250_dev_initialize %s\n", ns->dev->name);
    325329       
    326330        int ret = EOK;
     
    329333        memset(&hw_resources, 0, sizeof(hw_resource_list_t));
    330334       
    331         /* Allocate driver data for the device. */
    332         ns8250_dev_data_t *data = create_ns8250_dev_data();
    333         if (data == NULL)
    334                 return ENOMEM;
    335         dev->driver_data = data;
    336        
    337335        /* Connect to the parent's driver. */
    338         dev->parent_phone = devman_parent_device_connect(dev->handle,
     336        ns->dev->parent_phone = devman_parent_device_connect(ns->dev->handle,
    339337            IPC_FLAG_BLOCKING);
    340         if (dev->parent_phone < 0) {
     338        if (ns->dev->parent_phone < 0) {
    341339                printf(NAME ": failed to connect to the parent driver of the "
    342                     "device %s.\n", dev->name);
    343                 ret = dev->parent_phone;
     340                    "device %s.\n", ns->dev->name);
     341                ret = ns->dev->parent_phone;
    344342                goto failed;
    345343        }
    346344       
    347345        /* Get hw resources. */
    348         ret = hw_res_get_resource_list(dev->parent_phone, &hw_resources);
     346        ret = hw_res_get_resource_list(ns->dev->parent_phone, &hw_resources);
    349347        if (ret != EOK) {
    350348                printf(NAME ": failed to get hw resources for the device "
    351                     "%s.\n", dev->name);
     349                    "%s.\n", ns->dev->name);
    352350                goto failed;
    353351        }
     
    362360                switch (res->type) {
    363361                case INTERRUPT:
    364                         data->irq = res->res.interrupt.irq;
     362                        ns->irq = res->res.interrupt.irq;
    365363                        irq = true;
    366364                        printf(NAME ": the %s device was asigned irq = 0x%x.\n",
    367                             dev->name, data->irq);
     365                            ns->dev->name, ns->irq);
    368366                        break;
    369367                       
    370368                case IO_RANGE:
    371                         data->io_addr = res->res.io_range.address;
     369                        ns->io_addr = res->res.io_range.address;
    372370                        if (res->res.io_range.size < REG_COUNT) {
    373371                                printf(NAME ": i/o range assigned to the device "
    374                                     "%s is too small.\n", dev->name);
     372                                    "%s is too small.\n", ns->dev->name);
    375373                                ret = ELIMIT;
    376374                                goto failed;
     
    378376                        ioport = true;
    379377                        printf(NAME ": the %s device was asigned i/o address = "
    380                             "0x%x.\n", dev->name, data->io_addr);
     378                            "0x%x.\n", ns->dev->name, ns->io_addr);
    381379                        break;
    382380                       
     
    388386        if (!irq || !ioport) {
    389387                printf(NAME ": missing hw resource(s) for the device %s.\n",
    390                     dev->name);
     388                    ns->dev->name);
    391389                ret = ENOENT;
    392390                goto failed;
     
    397395       
    398396failed:
    399         ns8250_dev_cleanup(dev);
     397        ns8250_dev_cleanup(ns);
    400398        hw_res_clean_resource_list(&hw_resources);
    401399        return ret;
     
    404402/** Enable interrupts on the serial port device.
    405403 *
    406  * Interrupt when data is received.
     404 * Interrupt when data is received
    407405 *
    408406 * @param port          The base address of the serial port device's ports.
    409407 */
    410408static inline void ns8250_port_interrupts_enable(ioport8_t *port)
    411 {       
     409{
    412410        pio_write_8(port + 1, 0x1);     /* Interrupt when data received. */
    413411        pio_write_8(port + 4, 0xB);
     
    416414/** Disable interrupts on the serial port device.
    417415 *
    418  * @param port          The base address of the serial port device's ports.
     416 * @param port          The base address of the serial port device's ports
    419417 */
    420418static inline void ns8250_port_interrupts_disable(ioport8_t *port)
     
    425423/** Enable interrupts for the serial port device.
    426424 *
    427  * @param dev           The device.
    428  * @return              Zero on success, negative error number otherwise.
    429  */
    430 static int ns8250_interrupt_enable(device_t *dev)
    431 {
    432         ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
    433        
     425 * @param ns            Serial port device
     426 * @return              Zero on success, negative error number otherwise
     427 */
     428static int ns8250_interrupt_enable(ns8250_t *ns)
     429{
    434430        /* Enable interrupt on the serial port. */
    435         ns8250_port_interrupts_enable(data->port);
     431        ns8250_port_interrupts_enable(ns->port);
    436432       
    437433        return EOK;
     
    618614 * Set the default parameters of the serial communication.
    619615 *
    620  * @param dev           The serial port device.
    621  */
    622 static void ns8250_initialize_port(device_t *dev)
    623 {
    624         ns8250_dev_data_t *data = (ns8250_dev_data_t *)dev->driver_data;
    625         ioport8_t *port = data->port;
     616 * @param ns            Serial port device
     617 */
     618static void ns8250_initialize_port(ns8250_t *ns)
     619{
     620        ioport8_t *port = ns->port;
    626621       
    627622        /* Disable interrupts. */
     
    643638 * buffer.
    644639 *
    645  * @param dev           The serial port device.
    646  */
    647 static void ns8250_read_from_device(device_t *dev)
    648 {
    649         ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
    650         ioport8_t *port = data->port;
     640 * @param ns            Serial port device
     641 */
     642static void ns8250_read_from_device(ns8250_t *ns)
     643{
     644        ioport8_t *port = ns->port;
    651645        bool cont = true;
    652646       
    653647        while (cont) {
    654                 fibril_mutex_lock(&data->mutex);
     648                fibril_mutex_lock(&ns->mutex);
    655649               
    656650                cont = ns8250_received(port);
     
    658652                        uint8_t val = ns8250_read_8(port);
    659653                       
    660                         if (data->client_connected) {
    661                                 if (!buf_push_back(&data->input_buffer, val)) {
     654                        if (ns->client_connected) {
     655                                if (!buf_push_back(&ns->input_buffer, val)) {
    662656                                        printf(NAME ": buffer overflow on "
    663                                             "%s.\n", dev->name);
     657                                            "%s.\n", ns->dev->name);
    664658                                } else {
    665659                                        printf(NAME ": the character %c saved "
    666660                                            "to the buffer of %s.\n",
    667                                             val, dev->name);
     661                                            val, ns->dev->name);
    668662                                }
    669663                        }
    670664                }
    671665               
    672                 fibril_mutex_unlock(&data->mutex);
     666                fibril_mutex_unlock(&ns->mutex);
    673667                fibril_yield();
    674668        }
     
    682676 * @param dev           The serial port device.
    683677 */
    684 static inline void ns8250_interrupt_handler(device_t *dev, ipc_callid_t iid,
     678static inline void ns8250_interrupt_handler(ddf_dev_t *dev, ipc_callid_t iid,
    685679    ipc_call_t *icall)
    686680{
    687         ns8250_read_from_device(dev);
     681        ns8250_read_from_device(NS8250_FROM_DEV(dev));
    688682}
    689683
    690684/** Register the interrupt handler for the device.
    691685 *
     686 * @param ns            Serial port device
     687 */
     688static inline int ns8250_register_interrupt_handler(ns8250_t *ns)
     689{
     690        return register_interrupt_handler(ns->dev, ns->irq,
     691            ns8250_interrupt_handler, NULL);
     692}
     693
     694/** Unregister the interrupt handler for the device.
     695 *
     696 * @param ns            Serial port device
     697 */
     698static inline int ns8250_unregister_interrupt_handler(ns8250_t *ns)
     699{
     700        return unregister_interrupt_handler(ns->dev, ns->irq);
     701}
     702
     703/** The add_device callback method of the serial port driver.
     704 *
     705 * Probe and initialize the newly added device.
     706 *
    692707 * @param dev           The serial port device.
    693708 */
    694 static inline int ns8250_register_interrupt_handler(device_t *dev)
    695 {
    696         ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
    697        
    698         return register_interrupt_handler(dev, data->irq,
    699             ns8250_interrupt_handler, NULL);
    700 }
    701 
    702 /** Unregister the interrupt handler for the device.
    703  *
    704  * @param dev           The serial port device.
    705  */
    706 static inline int ns8250_unregister_interrupt_handler(device_t *dev)
    707 {
    708         ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
    709        
    710         return unregister_interrupt_handler(dev, data->irq);
    711 }
    712 
    713 /** The add_device callback method of the serial port driver.
    714  *
    715  * Probe and initialize the newly added device.
    716  *
    717  * @param dev           The serial port device.
    718  */
    719 static int ns8250_add_device(device_t *dev)
    720 {
     709static int ns8250_add_device(ddf_dev_t *dev)
     710{
     711        ns8250_t *ns = NULL;
     712        ddf_fun_t *fun = NULL;
     713        bool need_cleanup = false;
     714        int rc;
     715       
    721716        printf(NAME ": ns8250_add_device %s (handle = %d)\n",
    722717            dev->name, (int) dev->handle);
    723718       
    724         int res = ns8250_dev_initialize(dev);
    725         if (res != EOK)
    726                 return res;
    727        
    728         if (!ns8250_pio_enable(dev)) {
    729                 ns8250_dev_cleanup(dev);
    730                 return EADDRNOTAVAIL;
     719        /* Allocate soft-state for the device */
     720        ns = ns8250_new();
     721        if (ns == NULL) {
     722                rc = ENOMEM;
     723                goto fail;
     724        }
     725       
     726        ns->dev = dev;
     727        dev->driver_data = ns;
     728       
     729        rc = ns8250_dev_initialize(ns);
     730        if (rc != EOK)
     731                goto fail;
     732       
     733        need_cleanup = true;
     734       
     735        if (!ns8250_pio_enable(ns)) {
     736                rc = EADDRNOTAVAIL;
     737                goto fail;
    731738        }
    732739       
    733740        /* Find out whether the device is present. */
    734         if (!ns8250_dev_probe(dev)) {
    735                 ns8250_dev_cleanup(dev);
    736                 return ENOENT;
     741        if (!ns8250_dev_probe(ns)) {
     742                rc = ENOENT;
     743                goto fail;
    737744        }
    738745       
    739746        /* Serial port initialization (baud rate etc.). */
    740         ns8250_initialize_port(dev);
     747        ns8250_initialize_port(ns);
    741748       
    742749        /* Register interrupt handler. */
    743         if (ns8250_register_interrupt_handler(dev) != EOK) {
     750        if (ns8250_register_interrupt_handler(ns) != EOK) {
    744751                printf(NAME ": failed to register interrupt handler.\n");
    745                 ns8250_dev_cleanup(dev);
    746                 return res;
     752                rc = EADDRNOTAVAIL;
     753                goto fail;
    747754        }
    748755       
    749756        /* Enable interrupt. */
    750         res = ns8250_interrupt_enable(dev);
    751         if (res != EOK) {
     757        rc = ns8250_interrupt_enable(ns);
     758        if (rc != EOK) {
    752759                printf(NAME ": failed to enable the interrupt. Error code = "
    753                     "%d.\n", res);
    754                 ns8250_dev_cleanup(dev);
    755                 ns8250_unregister_interrupt_handler(dev);
    756                 return res;
     760                    "%d.\n", rc);
     761                goto fail;
     762        }
     763       
     764        fun = ddf_fun_create(dev, fun_exposed, "a");
     765        if (fun == NULL) {
     766                printf(NAME ": error creating function.\n");
     767                goto fail;
    757768        }
    758769       
    759770        /* Set device operations. */
    760         dev->ops = &ns8250_dev_ops;
    761        
    762         add_device_to_class(dev, "serial");
     771        fun->ops = &ns8250_dev_ops;
     772        rc = ddf_fun_bind(fun);
     773        if (rc != EOK) {
     774                printf(NAME ": error binding function.\n");
     775                goto fail;
     776        }
     777
     778        ns->fun = fun;
     779       
     780        ddf_fun_add_to_class(fun, "serial");
    763781       
    764782        printf(NAME ": the %s device has been successfully initialized.\n",
     
    766784       
    767785        return EOK;
     786fail:
     787        if (fun != NULL)
     788                ddf_fun_destroy(fun);
     789        if (need_cleanup)
     790                ns8250_dev_cleanup(ns);
     791        if (ns != NULL)
     792                ns8250_delete(ns);
     793        return rc;
    768794}
    769795
     
    775801 * @param dev           The device.
    776802 */
    777 static int ns8250_open(device_t *dev)
    778 {
    779         ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
     803static int ns8250_open(ddf_fun_t *fun)
     804{
     805        ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
    780806        int res;
    781807       
     
    788814        }
    789815        fibril_mutex_unlock(&data->mutex);
    790 
     816       
    791817        return res;
    792818}
     
    799825 * @param dev           The device.
    800826 */
    801 static void ns8250_close(device_t *dev)
    802 {
    803         ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
     827static void ns8250_close(ddf_fun_t *fun)
     828{
     829        ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
    804830       
    805831        fibril_mutex_lock(&data->mutex);
     
    823849 */
    824850static void
    825 ns8250_get_props(device_t *dev, unsigned int *baud_rate, unsigned int *parity,
     851ns8250_get_props(ddf_dev_t *dev, unsigned int *baud_rate, unsigned int *parity,
    826852    unsigned int *word_length, unsigned int* stop_bits)
    827853{
    828         ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
     854        ns8250_t *data = (ns8250_t *) dev->driver_data;
    829855        ioport8_t *port = data->port;
    830856       
     
    850876 * @param stop_bits     The number of stop bits to be used.
    851877 */
    852 static int ns8250_set_props(device_t *dev, unsigned int baud_rate,
     878static int ns8250_set_props(ddf_dev_t *dev, unsigned int baud_rate,
    853879    unsigned int parity, unsigned int word_length, unsigned int stop_bits)
    854880{
     
    857883            stop_bits);
    858884       
    859         ns8250_dev_data_t *data = (ns8250_dev_data_t *) dev->driver_data;
     885        ns8250_t *data = (ns8250_t *) dev->driver_data;
    860886        ioport8_t *port = data->port;
    861887        int ret;
     
    877903 * Configure the parameters of the serial communication.
    878904 */
    879 static void ns8250_default_handler(device_t *dev, ipc_callid_t callid,
     905static void ns8250_default_handler(ddf_fun_t *fun, ipc_callid_t callid,
    880906    ipc_call_t *call)
    881907{
     
    886912        switch (method) {
    887913        case SERIAL_GET_COM_PROPS:
    888                 ns8250_get_props(dev, &baud_rate, &parity, &word_length,
     914                ns8250_get_props(fun->dev, &baud_rate, &parity, &word_length,
    889915                    &stop_bits);
    890916                async_answer_4(callid, EOK, baud_rate, parity, word_length,
     
    897923                word_length = IPC_GET_ARG3(*call);
    898924                stop_bits = IPC_GET_ARG4(*call);
    899                 ret = ns8250_set_props(dev, baud_rate, parity, word_length,
     925                ret = ns8250_set_props(fun->dev, baud_rate, parity, word_length,
    900926                    stop_bits);
    901927                async_answer_0(callid, ret);
     
    925951        printf(NAME ": HelenOS serial port driver\n");
    926952        ns8250_init();
    927         return driver_main(&ns8250_driver);
     953        return ddf_driver_main(&ns8250_driver);
    928954}
    929955
  • uspace/drv/pciintel/pci.c

    r6a343bdf r0c968a17  
    11/*
    22 * Copyright (c) 2010 Lenka Trochtova
     3 * Copyright (c) 2011 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    4445#include <ctype.h>
    4546#include <macros.h>
    46 
    47 #include <driver.h>
     47#include <str_error.h>
     48
     49#include <ddf/driver.h>
    4850#include <devman.h>
    4951#include <ipc/devman.h>
     
    6163        ((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
    6264
    63 static hw_resource_list_t *pciintel_get_child_resources(device_t *dev)
    64 {
    65         pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
    66        
    67         if (dev_data == NULL)
     65/** Obtain PCI function soft-state from DDF function node */
     66#define PCI_FUN(fnode) ((pci_fun_t *) (fnode)->driver_data)
     67
     68/** Obtain PCI bus soft-state from DDF device node */
     69#define PCI_BUS(dnode) ((pci_bus_t *) (dnode)->driver_data)
     70
     71/** Obtain PCI bus soft-state from function soft-state */
     72#define PCI_BUS_FROM_FUN(fun) ((fun)->busptr)
     73
     74static hw_resource_list_t *pciintel_get_resources(ddf_fun_t *fnode)
     75{
     76        pci_fun_t *fun = PCI_FUN(fnode);
     77       
     78        if (fun == NULL)
    6879                return NULL;
    69         return &dev_data->hw_resources;
    70 }
    71 
    72 static bool pciintel_enable_child_interrupt(device_t *dev)
     80        return &fun->hw_resources;
     81}
     82
     83static bool pciintel_enable_interrupt(ddf_fun_t *fnode)
    7384{
    7485        /* TODO */
     
    7788}
    7889
    79 static hw_res_ops_t pciintel_child_hw_res_ops = {
    80         &pciintel_get_child_resources,
    81         &pciintel_enable_child_interrupt
     90static hw_res_ops_t pciintel_hw_res_ops = {
     91        &pciintel_get_resources,
     92        &pciintel_enable_interrupt
    8293};
    8394
    84 static device_ops_t pci_child_ops;
    85 
    86 static int pci_add_device(device_t *);
    87 
    88 /** The pci bus driver's standard operations. */
     95static ddf_dev_ops_t pci_fun_ops;
     96
     97static int pci_add_device(ddf_dev_t *);
     98
     99/** PCI bus driver standard operations */
    89100static driver_ops_t pci_ops = {
    90101        .add_device = &pci_add_device
    91102};
    92103
    93 /** The pci bus driver structure. */
     104/** PCI bus driver structure */
    94105static driver_t pci_driver = {
    95106        .name = NAME,
     
    97108};
    98109
    99 typedef struct pciintel_bus_data {
    100         uint32_t conf_io_addr;
    101         void *conf_data_port;
    102         void *conf_addr_port;
    103         fibril_mutex_t conf_mutex;
    104 } pci_bus_data_t;
    105 
    106 static pci_bus_data_t *create_pci_bus_data(void)
    107 {
    108         pci_bus_data_t *bus_data;
    109        
    110         bus_data = (pci_bus_data_t *) malloc(sizeof(pci_bus_data_t));
    111         if (bus_data != NULL) {
    112                 memset(bus_data, 0, sizeof(pci_bus_data_t));
    113                 fibril_mutex_initialize(&bus_data->conf_mutex);
    114         }
    115 
    116         return bus_data;
    117 }
    118 
    119 static void delete_pci_bus_data(pci_bus_data_t *bus_data)
    120 {
    121         free(bus_data);
    122 }
    123 
    124 static void pci_conf_read(device_t *dev, int reg, uint8_t *buf, size_t len)
    125 {
    126         assert(dev->parent != NULL);
    127        
    128         pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
    129         pci_bus_data_t *bus_data = (pci_bus_data_t *) dev->parent->driver_data;
    130        
    131         fibril_mutex_lock(&bus_data->conf_mutex);
     110static pci_bus_t *pci_bus_new(void)
     111{
     112        pci_bus_t *bus;
     113       
     114        bus = (pci_bus_t *) calloc(1, sizeof(pci_bus_t));
     115        if (bus == NULL)
     116                return NULL;
     117       
     118        fibril_mutex_initialize(&bus->conf_mutex);
     119        return bus;
     120}
     121
     122static void pci_bus_delete(pci_bus_t *bus)
     123{
     124        assert(bus != NULL);
     125        free(bus);
     126}
     127
     128static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
     129{
     130        pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
     131       
     132        fibril_mutex_lock(&bus->conf_mutex);
    132133       
    133134        uint32_t conf_addr;
    134         conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg);
    135         void *addr = bus_data->conf_data_port + (reg & 3);
    136        
    137         pio_write_32(bus_data->conf_addr_port, conf_addr);
     135        conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
     136        void *addr = bus->conf_data_port + (reg & 3);
     137       
     138        pio_write_32(bus->conf_addr_port, conf_addr);
    138139       
    139140        switch (len) {
     
    149150        }
    150151       
    151         fibril_mutex_unlock(&bus_data->conf_mutex);
    152 }
    153 
    154 static void pci_conf_write(device_t *dev, int reg, uint8_t *buf, size_t len)
    155 {
    156         assert(dev->parent != NULL);
    157        
    158         pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
    159         pci_bus_data_t *bus_data = (pci_bus_data_t *) dev->parent->driver_data;
    160        
    161         fibril_mutex_lock(&bus_data->conf_mutex);
     152        fibril_mutex_unlock(&bus->conf_mutex);
     153}
     154
     155static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
     156{
     157        pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
     158       
     159        fibril_mutex_lock(&bus->conf_mutex);
    162160       
    163161        uint32_t conf_addr;
    164         conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg);
    165         void *addr = bus_data->conf_data_port + (reg & 3);
    166        
    167         pio_write_32(bus_data->conf_addr_port, conf_addr);
     162        conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
     163        void *addr = bus->conf_data_port + (reg & 3);
     164       
     165        pio_write_32(bus->conf_addr_port, conf_addr);
    168166       
    169167        switch (len) {
     
    179177        }
    180178       
    181         fibril_mutex_unlock(&bus_data->conf_mutex);
    182 }
    183 
    184 uint8_t pci_conf_read_8(device_t *dev, int reg)
     179        fibril_mutex_unlock(&bus->conf_mutex);
     180}
     181
     182uint8_t pci_conf_read_8(pci_fun_t *fun, int reg)
    185183{
    186184        uint8_t res;
    187         pci_conf_read(dev, reg, &res, 1);
     185        pci_conf_read(fun, reg, &res, 1);
    188186        return res;
    189187}
    190188
    191 uint16_t pci_conf_read_16(device_t *dev, int reg)
     189uint16_t pci_conf_read_16(pci_fun_t *fun, int reg)
    192190{
    193191        uint16_t res;
    194         pci_conf_read(dev, reg, (uint8_t *) &res, 2);
     192        pci_conf_read(fun, reg, (uint8_t *) &res, 2);
    195193        return res;
    196194}
    197195
    198 uint32_t pci_conf_read_32(device_t *dev, int reg)
     196uint32_t pci_conf_read_32(pci_fun_t *fun, int reg)
    199197{
    200198        uint32_t res;
    201         pci_conf_read(dev, reg, (uint8_t *) &res, 4);
     199        pci_conf_read(fun, reg, (uint8_t *) &res, 4);
    202200        return res;
    203201}
    204202
    205 void pci_conf_write_8(device_t *dev, int reg, uint8_t val)
    206 {
    207         pci_conf_write(dev, reg, (uint8_t *) &val, 1);
    208 }
    209 
    210 void pci_conf_write_16(device_t *dev, int reg, uint16_t val)
    211 {
    212         pci_conf_write(dev, reg, (uint8_t *) &val, 2);
    213 }
    214 
    215 void pci_conf_write_32(device_t *dev, int reg, uint32_t val)
    216 {
    217         pci_conf_write(dev, reg, (uint8_t *) &val, 4);
    218 }
    219 
    220 void create_pci_match_ids(device_t *dev)
    221 {
    222         pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
    223         match_id_t *match_id = NULL;
     203void pci_conf_write_8(pci_fun_t *fun, int reg, uint8_t val)
     204{
     205        pci_conf_write(fun, reg, (uint8_t *) &val, 1);
     206}
     207
     208void pci_conf_write_16(pci_fun_t *fun, int reg, uint16_t val)
     209{
     210        pci_conf_write(fun, reg, (uint8_t *) &val, 2);
     211}
     212
     213void pci_conf_write_32(pci_fun_t *fun, int reg, uint32_t val)
     214{
     215        pci_conf_write(fun, reg, (uint8_t *) &val, 4);
     216}
     217
     218void pci_fun_create_match_ids(pci_fun_t *fun)
     219{
    224220        char *match_id_str;
    225        
    226         match_id = create_match_id();
    227         if (match_id != NULL) {
    228                 asprintf(&match_id_str, "pci/ven=%04x&dev=%04x",
    229                     dev_data->vendor_id, dev_data->device_id);
    230                 match_id->id = match_id_str;
    231                 match_id->score = 90;
    232                 add_match_id(&dev->match_ids, match_id);
    233         }
    234 
     221        int rc;
     222       
     223        asprintf(&match_id_str, "pci/ven=%04x&dev=%04x",
     224            fun->vendor_id, fun->device_id);
     225
     226        if (match_id_str == NULL) {
     227                printf(NAME ": out of memory creating match ID.\n");
     228                return;
     229        }
     230
     231        rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 90);
     232        if (rc != EOK) {
     233                printf(NAME ": error adding match ID: %s\n",
     234                    str_error(rc));
     235        }
     236       
    235237        /* TODO add more ids (with subsys ids, using class id etc.) */
    236238}
    237239
    238 void
    239 pci_add_range(device_t *dev, uint64_t range_addr, size_t range_size, bool io)
    240 {
    241         pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
    242         hw_resource_list_t *hw_res_list = &dev_data->hw_resources;
     240void pci_add_range(pci_fun_t *fun, uint64_t range_addr, size_t range_size,
     241    bool io)
     242{
     243        hw_resource_list_t *hw_res_list = &fun->hw_resources;
    243244        hw_resource_t *hw_resources =  hw_res_list->resources;
    244245        size_t count = hw_res_list->count;
     
    265266 * address add it to the devices hw resource list.
    266267 *
    267  * @param dev   The pci device.
     268 * @param fun   PCI function
    268269 * @param addr  The address of the BAR in the PCI configuration address space of
    269  *              the device.
    270  * @return      The addr the address of the BAR which should be read next.
     270 *              the device
     271 * @return      The addr the address of the BAR which should be read next
    271272 */
    272 int pci_read_bar(device_t *dev, int addr)
    273 {       
     273int pci_read_bar(pci_fun_t *fun, int addr)
     274{
    274275        /* Value of the BAR */
    275276        uint32_t val, mask;
     
    285286       
    286287        /* Get the value of the BAR. */
    287         val = pci_conf_read_32(dev, addr);
     288        val = pci_conf_read_32(fun, addr);
    288289       
    289290        io = (bool) (val & 1);
     
    305306       
    306307        /* Get the address mask. */
    307         pci_conf_write_32(dev, addr, 0xffffffff);
    308         mask = pci_conf_read_32(dev, addr);
     308        pci_conf_write_32(fun, addr, 0xffffffff);
     309        mask = pci_conf_read_32(fun, addr);
    309310       
    310311        /* Restore the original value. */
    311         pci_conf_write_32(dev, addr, val);
    312         val = pci_conf_read_32(dev, addr);
     312        pci_conf_write_32(fun, addr, val);
     313        val = pci_conf_read_32(fun, addr);
    313314       
    314315        range_size = pci_bar_mask_to_size(mask);
    315316       
    316317        if (addrw64) {
    317                 range_addr = ((uint64_t)pci_conf_read_32(dev, addr + 4) << 32) |
     318                range_addr = ((uint64_t)pci_conf_read_32(fun, addr + 4) << 32) |
    318319                    (val & 0xfffffff0);
    319320        } else {
     
    322323       
    323324        if (range_addr != 0) {
    324                 printf(NAME ": device %s : ", dev->name);
     325                printf(NAME ": function %s : ", fun->fnode->name);
    325326                printf("address = %" PRIx64, range_addr);
    326327                printf(", size = %x\n", (unsigned int) range_size);
    327328        }
    328329       
    329         pci_add_range(dev, range_addr, range_size, io);
     330        pci_add_range(fun, range_addr, range_size, io);
    330331       
    331332        if (addrw64)
     
    335336}
    336337
    337 void pci_add_interrupt(device_t *dev, int irq)
    338 {
    339         pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
    340         hw_resource_list_t *hw_res_list = &dev_data->hw_resources;
     338void pci_add_interrupt(pci_fun_t *fun, int irq)
     339{
     340        hw_resource_list_t *hw_res_list = &fun->hw_resources;
    341341        hw_resource_t *hw_resources = hw_res_list->resources;
    342342        size_t count = hw_res_list->count;
     
    350350        hw_res_list->count++;
    351351       
    352         printf(NAME ": device %s uses irq %x.\n", dev->name, irq);
    353 }
    354 
    355 void pci_read_interrupt(device_t *dev)
    356 {
    357         uint8_t irq = pci_conf_read_8(dev, PCI_BRIDGE_INT_LINE);
     352        printf(NAME ": function %s uses irq %x.\n", fun->fnode->name, irq);
     353}
     354
     355void pci_read_interrupt(pci_fun_t *fun)
     356{
     357        uint8_t irq = pci_conf_read_8(fun, PCI_BRIDGE_INT_LINE);
    358358        if (irq != 0xff)
    359                 pci_add_interrupt(dev, irq);
     359                pci_add_interrupt(fun, irq);
    360360}
    361361
    362362/** Enumerate (recursively) and register the devices connected to a pci bus.
    363363 *
    364  * @param parent        The host-to-pci bridge device.
    365  * @param bus_num       The bus number.
     364 * @param bus           Host-to-PCI bridge
     365 * @param bus_num       Bus number
    366366 */
    367 void pci_bus_scan(device_t *parent, int bus_num)
    368 {
    369         device_t *dev = create_device();
    370         pci_dev_data_t *dev_data = create_pci_dev_data();
    371         dev->driver_data = dev_data;
    372         dev->parent = parent;
     367void pci_bus_scan(pci_bus_t *bus, int bus_num)
     368{
     369        ddf_fun_t *fnode;
     370        pci_fun_t *fun;
    373371       
    374372        int child_bus = 0;
    375373        int dnum, fnum;
    376374        bool multi;
    377         uint8_t header_type;
     375        uint8_t header_type;
     376       
     377        fun = pci_fun_new(bus);
    378378       
    379379        for (dnum = 0; dnum < 32; dnum++) {
    380380                multi = true;
    381381                for (fnum = 0; multi && fnum < 8; fnum++) {
    382                         init_pci_dev_data(dev_data, bus_num, dnum, fnum);
    383                         dev_data->vendor_id = pci_conf_read_16(dev,
     382                        pci_fun_init(fun, bus_num, dnum, fnum);
     383                        fun->vendor_id = pci_conf_read_16(fun,
    384384                            PCI_VENDOR_ID);
    385                         dev_data->device_id = pci_conf_read_16(dev,
     385                        fun->device_id = pci_conf_read_16(fun,
    386386                            PCI_DEVICE_ID);
    387                         if (dev_data->vendor_id == 0xffff) {
     387                        if (fun->vendor_id == 0xffff) {
    388388                                /*
    389389                                 * The device is not present, go on scanning the
     
    396396                        }
    397397                       
    398                         header_type = pci_conf_read_8(dev, PCI_HEADER_TYPE);
     398                        header_type = pci_conf_read_8(fun, PCI_HEADER_TYPE);
    399399                        if (fnum == 0) {
    400400                                /* Is the device multifunction? */
     
    404404                        header_type = header_type & 0x7F;
    405405                       
    406                         create_pci_dev_name(dev);
    407                        
    408                         pci_alloc_resource_list(dev);
    409                         pci_read_bars(dev);
    410                         pci_read_interrupt(dev);
    411                        
    412                         dev->ops = &pci_child_ops;
    413                        
    414                         printf(NAME ": adding new child device %s.\n",
    415                             dev->name);
    416                        
    417                         create_pci_match_ids(dev);
    418                        
    419                         if (child_device_register(dev, parent) != EOK) {
    420                                 pci_clean_resource_list(dev);
    421                                 clean_match_ids(&dev->match_ids);
    422                                 free((char *) dev->name);
    423                                 dev->name = NULL;
     406                        char *fun_name = pci_fun_create_name(fun);
     407                        if (fun_name == NULL) {
     408                                printf(NAME ": out of memory.\n");
     409                                return;
     410                        }
     411                       
     412                        fnode = ddf_fun_create(bus->dnode, fun_inner, fun_name);
     413                        if (fnode == NULL) {
     414                                printf(NAME ": error creating function.\n");
     415                                return;
     416                        }
     417                       
     418                        free(fun_name);
     419                        fun->fnode = fnode;
     420                       
     421                        pci_alloc_resource_list(fun);
     422                        pci_read_bars(fun);
     423                        pci_read_interrupt(fun);
     424                       
     425                        fnode->ops = &pci_fun_ops;
     426                        fnode->driver_data = fun;
     427                       
     428                        printf(NAME ": adding new function %s.\n",
     429                            fnode->name);
     430                       
     431                        pci_fun_create_match_ids(fun);
     432                       
     433                        if (ddf_fun_bind(fnode) != EOK) {
     434                                pci_clean_resource_list(fun);
     435                                clean_match_ids(&fnode->match_ids);
     436                                free((char *) fnode->name);
     437                                fnode->name = NULL;
    424438                                continue;
    425439                        }
     
    427441                        if (header_type == PCI_HEADER_TYPE_BRIDGE ||
    428442                            header_type == PCI_HEADER_TYPE_CARDBUS) {
    429                                 child_bus = pci_conf_read_8(dev,
     443                                child_bus = pci_conf_read_8(fun,
    430444                                    PCI_BRIDGE_SEC_BUS_NUM);
    431445                                printf(NAME ": device is pci-to-pci bridge, "
    432446                                    "secondary bus number = %d.\n", bus_num);
    433447                                if (child_bus > bus_num)
    434                                         pci_bus_scan(parent, child_bus);
     448                                        pci_bus_scan(bus, child_bus);
    435449                        }
    436450                       
    437                         /* Alloc new aux. dev. structure. */
    438                         dev = create_device();
    439                         dev_data = create_pci_dev_data();
    440                         dev->driver_data = dev_data;
    441                         dev->parent = parent;
     451                        fun = pci_fun_new(bus);
    442452                }
    443453        }
    444454       
    445         if (dev_data->vendor_id == 0xffff) {
    446                 delete_device(dev);
    447                 /* Free the auxiliary device structure. */
    448                 delete_pci_dev_data(dev_data);
    449         }
    450 }
    451 
    452 static int pci_add_device(device_t *dev)
    453 {
     455        if (fun->vendor_id == 0xffff) {
     456                /* Free the auxiliary function structure. */
     457                pci_fun_delete(fun);
     458        }
     459}
     460
     461static int pci_add_device(ddf_dev_t *dnode)
     462{
     463        pci_bus_t *bus = NULL;
     464        ddf_fun_t *ctl = NULL;
     465        bool got_res = false;
    454466        int rc;
    455 
     467       
    456468        printf(NAME ": pci_add_device\n");
    457        
    458         pci_bus_data_t *bus_data = create_pci_bus_data();
    459         if (bus_data == NULL) {
     469        dnode->parent_phone = -1;
     470       
     471        bus = pci_bus_new();
     472        if (bus == NULL) {
    460473                printf(NAME ": pci_add_device allocation failed.\n");
    461                 return ENOMEM;
    462         }
    463        
    464         dev->parent_phone = devman_parent_device_connect(dev->handle,
     474                rc = ENOMEM;
     475                goto fail;
     476        }
     477        bus->dnode = dnode;
     478        dnode->driver_data = bus;
     479       
     480        dnode->parent_phone = devman_parent_device_connect(dnode->handle,
    465481            IPC_FLAG_BLOCKING);
    466         if (dev->parent_phone < 0) {
     482        if (dnode->parent_phone < 0) {
    467483                printf(NAME ": pci_add_device failed to connect to the "
    468484                    "parent's driver.\n");
    469                 delete_pci_bus_data(bus_data);
    470                 return dev->parent_phone;
     485                rc = dnode->parent_phone;
     486                goto fail;
    471487        }
    472488       
    473489        hw_resource_list_t hw_resources;
    474490       
    475         rc = hw_res_get_resource_list(dev->parent_phone, &hw_resources);
     491        rc = hw_res_get_resource_list(dnode->parent_phone, &hw_resources);
    476492        if (rc != EOK) {
    477493                printf(NAME ": pci_add_device failed to get hw resources for "
    478494                    "the device.\n");
    479                 delete_pci_bus_data(bus_data);
    480                 async_hangup(dev->parent_phone);
    481                 return rc;
    482         }       
     495                goto fail;
     496        }
     497        got_res = true;
    483498       
    484499        printf(NAME ": conf_addr = %" PRIx64 ".\n",
     
    489504        assert(hw_resources.resources[0].res.io_range.size == 8);
    490505       
    491         bus_data->conf_io_addr =
     506        bus->conf_io_addr =
    492507            (uint32_t) hw_resources.resources[0].res.io_range.address;
    493508       
    494         if (pio_enable((void *)(uintptr_t)bus_data->conf_io_addr, 8,
    495             &bus_data->conf_addr_port)) {
     509        if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 8,
     510            &bus->conf_addr_port)) {
    496511                printf(NAME ": failed to enable configuration ports.\n");
    497                 delete_pci_bus_data(bus_data);
    498                 async_hangup(dev->parent_phone);
     512                rc = EADDRNOTAVAIL;
     513                goto fail;
     514        }
     515        bus->conf_data_port = (char *) bus->conf_addr_port + 4;
     516       
     517        /* Make the bus device more visible. It has no use yet. */
     518        printf(NAME ": adding a 'ctl' function\n");
     519       
     520        ctl = ddf_fun_create(bus->dnode, fun_exposed, "ctl");
     521        if (ctl == NULL) {
     522                printf(NAME ": error creating control function.\n");
     523                rc = ENOMEM;
     524                goto fail;
     525        }
     526       
     527        rc = ddf_fun_bind(ctl);
     528        if (rc != EOK) {
     529                printf(NAME ": error binding control function.\n");
     530                goto fail;
     531        }
     532       
     533        /* Enumerate functions. */
     534        printf(NAME ": scanning the bus\n");
     535        pci_bus_scan(bus, 0);
     536       
     537        hw_res_clean_resource_list(&hw_resources);
     538       
     539        return EOK;
     540       
     541fail:
     542        if (bus != NULL)
     543                pci_bus_delete(bus);
     544        if (dnode->parent_phone >= 0)
     545                async_hangup(dnode->parent_phone);
     546        if (got_res)
    499547                hw_res_clean_resource_list(&hw_resources);
    500                 return EADDRNOTAVAIL;
    501         }
    502         bus_data->conf_data_port = (char *) bus_data->conf_addr_port + 4;
    503        
    504         dev->driver_data = bus_data;
    505        
    506         /* Enumerate child devices. */
    507         printf(NAME ": scanning the bus\n");
    508         pci_bus_scan(dev, 0);
    509        
    510         hw_res_clean_resource_list(&hw_resources);
    511        
    512         return EOK;
     548        if (ctl != NULL)
     549                ddf_fun_destroy(ctl);
     550
     551        return rc;
    513552}
    514553
    515554static void pciintel_init(void)
    516555{
    517         pci_child_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_child_hw_res_ops;
    518 }
    519 
    520 pci_dev_data_t *create_pci_dev_data(void)
    521 {
    522         pci_dev_data_t *res = (pci_dev_data_t *) malloc(sizeof(pci_dev_data_t));
    523        
    524         if (res != NULL)
    525                 memset(res, 0, sizeof(pci_dev_data_t));
    526         return res;
    527 }
    528 
    529 void init_pci_dev_data(pci_dev_data_t *dev_data, int bus, int dev, int fn)
    530 {
    531         dev_data->bus = bus;
    532         dev_data->dev = dev;
    533         dev_data->fn = fn;
    534 }
    535 
    536 void delete_pci_dev_data(pci_dev_data_t *dev_data)
    537 {
    538         if (dev_data != NULL) {
    539                 hw_res_clean_resource_list(&dev_data->hw_resources);
    540                 free(dev_data);
    541         }
    542 }
    543 
    544 void create_pci_dev_name(device_t *dev)
    545 {
    546         pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
     556        pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
     557}
     558
     559pci_fun_t *pci_fun_new(pci_bus_t *bus)
     560{
     561        pci_fun_t *fun;
     562       
     563        fun = (pci_fun_t *) calloc(1, sizeof(pci_fun_t));
     564        if (fun == NULL)
     565                return NULL;
     566
     567        fun->busptr = bus;
     568        return fun;
     569}
     570
     571void pci_fun_init(pci_fun_t *fun, int bus, int dev, int fn)
     572{
     573        fun->bus = bus;
     574        fun->dev = dev;
     575        fun->fn = fn;
     576}
     577
     578void pci_fun_delete(pci_fun_t *fun)
     579{
     580        assert(fun != NULL);
     581        hw_res_clean_resource_list(&fun->hw_resources);
     582        free(fun);
     583}
     584
     585char *pci_fun_create_name(pci_fun_t *fun)
     586{
    547587        char *name = NULL;
    548588       
    549         asprintf(&name, "%02x:%02x.%01x", dev_data->bus, dev_data->dev,
    550             dev_data->fn);
    551         dev->name = name;
    552 }
    553 
    554 bool pci_alloc_resource_list(device_t *dev)
    555 {
    556         pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data;
    557        
    558         dev_data->hw_resources.resources =
     589        asprintf(&name, "%02x:%02x.%01x", fun->bus, fun->dev,
     590            fun->fn);
     591        return name;
     592}
     593
     594bool pci_alloc_resource_list(pci_fun_t *fun)
     595{
     596        fun->hw_resources.resources =
    559597            (hw_resource_t *) malloc(PCI_MAX_HW_RES * sizeof(hw_resource_t));
    560         return dev_data->hw_resources.resources != NULL;
    561 }
    562 
    563 void pci_clean_resource_list(device_t *dev)
    564 {
    565         pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
    566        
    567         if (dev_data->hw_resources.resources != NULL) {
    568                 free(dev_data->hw_resources.resources);
    569                 dev_data->hw_resources.resources = NULL;
    570         }
    571 }
    572 
    573 /** Read the base address registers (BARs) of the device and adds the addresses
    574  * to its hw resource list.
     598        return fun->hw_resources.resources != NULL;
     599}
     600
     601void pci_clean_resource_list(pci_fun_t *fun)
     602{
     603        if (fun->hw_resources.resources != NULL) {
     604                free(fun->hw_resources.resources);
     605                fun->hw_resources.resources = NULL;
     606        }
     607}
     608
     609/** Read the base address registers (BARs) of the function and add the addresses
     610 * to its HW resource list.
    575611 *
    576  * @param dev the pci device.
     612 * @param fun   PCI function
    577613 */
    578 void pci_read_bars(device_t *dev)
     614void pci_read_bars(pci_fun_t *fun)
    579615{
    580616        /*
     
    585621       
    586622        while (addr <= PCI_BASE_ADDR_5)
    587                 addr = pci_read_bar(dev, addr);
     623                addr = pci_read_bar(fun, addr);
    588624}
    589625
     
    597633        printf(NAME ": HelenOS pci bus driver (intel method 1).\n");
    598634        pciintel_init();
    599         return driver_main(&pci_driver);
     635        return ddf_driver_main(&pci_driver);
    600636}
    601637
  • uspace/drv/pciintel/pci.h

    r6a343bdf r0c968a17  
    11/*
    22 * Copyright (c) 2010 Lenka Trochtova
     3 * Copyright (c) 2011 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    3637#define PCI_H_
    3738
    38 #include <stdlib.h>
    39 #include <driver.h>
    40 #include <malloc.h>
    41 
     39#include <ddf/driver.h>
    4240#include "pci_regs.h"
    4341
    4442#define PCI_MAX_HW_RES 8
    4543
    46 typedef struct pci_dev_data {
     44typedef struct pciintel_bus {
     45        /** DDF device node */
     46        ddf_dev_t *dnode;
     47        uint32_t conf_io_addr;
     48        void *conf_data_port;
     49        void *conf_addr_port;
     50        fibril_mutex_t conf_mutex;
     51} pci_bus_t;
     52
     53typedef struct pci_fun_data {
     54        pci_bus_t *busptr;
     55        ddf_fun_t *fnode;
     56
    4757        int bus;
    4858        int dev;
     
    5161        int device_id;
    5262        hw_resource_list_t hw_resources;
    53 } pci_dev_data_t;
     63} pci_fun_t;
    5464
    55 extern void create_pci_match_ids(device_t *);
     65extern void pci_fun_create_match_ids(pci_fun_t *);
    5666
    57 extern uint8_t pci_conf_read_8(device_t *, int);
    58 extern uint16_t pci_conf_read_16(device_t *, int);
    59 extern uint32_t pci_conf_read_32(device_t *, int);
    60 extern void pci_conf_write_8(device_t *, int, uint8_t);
    61 extern void pci_conf_write_16(device_t *, int, uint16_t);
    62 extern void pci_conf_write_32(device_t *, int, uint32_t);
     67extern uint8_t pci_conf_read_8(pci_fun_t *, int);
     68extern uint16_t pci_conf_read_16(pci_fun_t *, int);
     69extern uint32_t pci_conf_read_32(pci_fun_t *, int);
     70extern void pci_conf_write_8(pci_fun_t *, int, uint8_t);
     71extern void pci_conf_write_16(pci_fun_t *, int, uint16_t);
     72extern void pci_conf_write_32(pci_fun_t *, int, uint32_t);
    6373
    64 extern void pci_add_range(device_t *, uint64_t, size_t, bool);
    65 extern int pci_read_bar(device_t *, int);
    66 extern void pci_read_interrupt(device_t *);
    67 extern void pci_add_interrupt(device_t *, int);
     74extern void pci_add_range(pci_fun_t *, uint64_t, size_t, bool);
     75extern int pci_read_bar(pci_fun_t *, int);
     76extern void pci_read_interrupt(pci_fun_t *);
     77extern void pci_add_interrupt(pci_fun_t *, int);
    6878
    69 extern void pci_bus_scan(device_t *, int);
     79extern pci_fun_t *pci_fun_new(pci_bus_t *);
     80extern void pci_fun_init(pci_fun_t *, int, int, int);
     81extern void pci_fun_delete(pci_fun_t *);
     82extern char *pci_fun_create_name(pci_fun_t *);
    7083
    71 extern pci_dev_data_t *create_pci_dev_data(void);
    72 extern void init_pci_dev_data(pci_dev_data_t *, int, int, int);
    73 extern void delete_pci_dev_data(pci_dev_data_t *);
    74 extern void create_pci_dev_name(device_t *);
     84extern void pci_bus_scan(pci_bus_t *, int);
    7585
    76 extern bool pci_alloc_resource_list(device_t *);
    77 extern void pci_clean_resource_list(device_t *);
     86extern bool pci_alloc_resource_list(pci_fun_t *);
     87extern void pci_clean_resource_list(pci_fun_t *);
    7888
    79 extern void pci_read_bars(device_t *);
     89extern void pci_read_bars(pci_fun_t *);
    8090extern size_t pci_bar_mask_to_size(uint32_t);
    8191
  • uspace/drv/root/root.c

    r6a343bdf r0c968a17  
    22 * Copyright (c) 2010 Lenka Trochtova
    33 * Copyright (c) 2010 Vojtech Horky
     4 * Copyright (c) 2011 Jiri Svoboda
    45 * All rights reserved.
    56 *
     
    4445#include <stdlib.h>
    4546#include <str.h>
     47#include <str_error.h>
    4648#include <ctype.h>
    4749#include <macros.h>
     
    4951#include <sysinfo.h>
    5052
    51 #include <driver.h>
     53#include <ddf/driver.h>
    5254#include <devman.h>
    5355#include <ipc/devman.h>
     
    5557#define NAME "root"
    5658
    57 #define PLATFORM_DEVICE_NAME "hw"
    58 #define PLATFORM_DEVICE_MATCH_ID_FMT "platform/%s"
    59 #define PLATFORM_DEVICE_MATCH_SCORE 100
    60 
    61 #define VIRTUAL_DEVICE_NAME "virt"
    62 #define VIRTUAL_DEVICE_MATCH_ID "rootvirt"
    63 #define VIRTUAL_DEVICE_MATCH_SCORE 100
    64 
    65 static int root_add_device(device_t *dev);
     59#define PLATFORM_FUN_NAME "hw"
     60#define PLATFORM_FUN_MATCH_ID_FMT "platform/%s"
     61#define PLATFORM_FUN_MATCH_SCORE 100
     62
     63#define VIRTUAL_FUN_NAME "virt"
     64#define VIRTUAL_FUN_MATCH_ID "rootvirt"
     65#define VIRTUAL_FUN_MATCH_SCORE 100
     66
     67static int root_add_device(ddf_dev_t *dev);
    6668
    6769/** The root device driver's standard operations. */
     
    7678};
    7779
    78 /** Create the device which represents the root of virtual device tree.
    79  *
    80  * @param parent Parent of the newly created device.
    81  * @return Error code.
    82  */
    83 static int add_virtual_root_child(device_t *parent)
    84 {
    85         printf(NAME ": adding new child for virtual devices.\n");
    86         printf(NAME ":   device node is `%s' (%d %s)\n", VIRTUAL_DEVICE_NAME,
    87             VIRTUAL_DEVICE_MATCH_SCORE, VIRTUAL_DEVICE_MATCH_ID);
    88 
    89         int res = child_device_register_wrapper(parent, VIRTUAL_DEVICE_NAME,
    90             VIRTUAL_DEVICE_MATCH_ID, VIRTUAL_DEVICE_MATCH_SCORE);
    91 
    92         return res;
    93 }
    94 
    95 /** Create the device which represents the root of HW device tree.
    96  *
    97  * @param parent        Parent of the newly created device.
    98  * @return 0 on success, negative error number otherwise.
    99  */
    100 static int add_platform_child(device_t *parent)
     80/** Create the function which represents the root of virtual device tree.
     81 *
     82 * @param dev   Device
     83 * @return      EOK on success or negative error code
     84 */
     85static int add_virtual_root_fun(ddf_dev_t *dev)
     86{
     87        const char *name = VIRTUAL_FUN_NAME;
     88        ddf_fun_t *fun;
     89        int rc;
     90
     91        printf(NAME ": adding new function for virtual devices.\n");
     92        printf(NAME ":   function node is `%s' (%d %s)\n", name,
     93            VIRTUAL_FUN_MATCH_SCORE, VIRTUAL_FUN_MATCH_ID);
     94
     95        fun = ddf_fun_create(dev, fun_inner, name);
     96        if (fun == NULL) {
     97                printf(NAME ": error creating function %s\n", name);
     98                return ENOMEM;
     99        }
     100
     101        rc = ddf_fun_add_match_id(fun, VIRTUAL_FUN_MATCH_ID,
     102            VIRTUAL_FUN_MATCH_SCORE);
     103        if (rc != EOK) {
     104                printf(NAME ": error adding match IDs to function %s\n", name);
     105                ddf_fun_destroy(fun);
     106                return rc;
     107        }
     108
     109        rc = ddf_fun_bind(fun);
     110        if (rc != EOK) {
     111                printf(NAME ": error binding function %s: %s\n", name,
     112                    str_error(rc));
     113                ddf_fun_destroy(fun);
     114                return rc;
     115        }
     116
     117        return EOK;
     118}
     119
     120/** Create the function which represents the root of HW device tree.
     121 *
     122 * @param dev   Device
     123 * @return      EOK on success or negative error code
     124 */
     125static int add_platform_fun(ddf_dev_t *dev)
    101126{
    102127        char *match_id;
    103128        char *platform;
    104129        size_t platform_size;
    105         int res;
     130
     131        const char *name = PLATFORM_FUN_NAME;
     132        ddf_fun_t *fun;
     133        int rc;
    106134
    107135        /* Get platform name from sysinfo. */
    108 
    109136        platform = sysinfo_get_data("platform", &platform_size);
    110137        if (platform == NULL) {
     
    123150
    124151        /* Construct match ID. */
    125 
    126         if (asprintf(&match_id, PLATFORM_DEVICE_MATCH_ID_FMT, platform) == -1) {
     152        if (asprintf(&match_id, PLATFORM_FUN_MATCH_ID_FMT, platform) == -1) {
    127153                printf(NAME ": Memory allocation failed.\n");
    128154                return ENOMEM;
    129155        }
    130156
    131         /* Add child. */
    132 
    133         printf(NAME ": adding new child for platform device.\n");
    134         printf(NAME ":   device node is `%s' (%d %s)\n", PLATFORM_DEVICE_NAME,
    135             PLATFORM_DEVICE_MATCH_SCORE, match_id);
    136 
    137         res = child_device_register_wrapper(parent, PLATFORM_DEVICE_NAME,
    138             match_id, PLATFORM_DEVICE_MATCH_SCORE);
    139 
    140         return res;
     157        /* Add function. */
     158        printf(NAME ": adding platform function\n");
     159        printf(NAME ":   function node is `%s' (%d %s)\n", PLATFORM_FUN_NAME,
     160            PLATFORM_FUN_MATCH_SCORE, match_id);
     161
     162        fun = ddf_fun_create(dev, fun_inner, name);
     163        if (fun == NULL) {
     164                printf(NAME ": error creating function %s\n", name);
     165                return ENOMEM;
     166        }
     167
     168        rc = ddf_fun_add_match_id(fun, match_id, PLATFORM_FUN_MATCH_SCORE);
     169        if (rc != EOK) {
     170                printf(NAME ": error adding match IDs to function %s\n", name);
     171                ddf_fun_destroy(fun);
     172                return rc;
     173        }
     174
     175        rc = ddf_fun_bind(fun);
     176        if (rc != EOK) {
     177                printf(NAME ": error binding function %s: %s\n", name,
     178                    str_error(rc));
     179                ddf_fun_destroy(fun);
     180                return rc;
     181        }
     182
     183        return EOK;
    141184}
    142185
     
    146189 *                      of HW and pseudo devices).
    147190 */
    148 static int root_add_device(device_t *dev)
     191static int root_add_device(ddf_dev_t *dev)
    149192{
    150193        printf(NAME ": root_add_device, device handle=%" PRIun "\n",
    151194            dev->handle);
    152        
     195
    153196        /*
    154197         * Register virtual devices root.
     
    156199         * vital for the system.
    157200         */
    158         add_virtual_root_child(dev);
     201        add_virtual_root_fun(dev);
    159202
    160203        /* Register root device's children. */
    161         int res = add_platform_child(dev);
     204        int res = add_platform_fun(dev);
    162205        if (EOK != res)
    163206                printf(NAME ": failed to add child device for platform.\n");
    164        
     207
    165208        return res;
    166209}
     
    169212{
    170213        printf(NAME ": HelenOS root device driver\n");
    171         return driver_main(&root_driver);
     214        return ddf_driver_main(&root_driver);
    172215}
    173216
  • uspace/drv/rootpc/rootpc.c

    r6a343bdf r0c968a17  
    4646#include <macros.h>
    4747
    48 #include <driver.h>
     48#include <ddf/driver.h>
    4949#include <devman.h>
    5050#include <ipc/devman.h>
     
    5555#define NAME "rootpc"
    5656
    57 typedef struct rootpc_child_dev_data {
     57/** Obtain function soft-state from DDF function node */
     58#define ROOTPC_FUN(fnode) ((rootpc_fun_t *) (fnode)->driver_data)
     59
     60typedef struct rootpc_fun {
    5861        hw_resource_list_t hw_resources;
    59 } rootpc_child_dev_data_t;
    60 
    61 static int rootpc_add_device(device_t *dev);
     62} rootpc_fun_t;
     63
     64static int rootpc_add_device(ddf_dev_t *dev);
    6265static void root_pc_init(void);
    6366
     
    8285};
    8386
    84 static rootpc_child_dev_data_t pci_data = {
     87static rootpc_fun_t pci_data = {
    8588        .hw_resources = {
    8689                1,
     
    8992};
    9093
    91 static hw_resource_list_t *rootpc_get_child_resources(device_t *dev)
    92 {
    93         rootpc_child_dev_data_t *data;
    94        
    95         data = (rootpc_child_dev_data_t *) dev->driver_data;
    96         if (NULL == data)
    97                 return NULL;
    98        
    99         return &data->hw_resources;
    100 }
    101 
    102 static bool rootpc_enable_child_interrupt(device_t *dev)
     94static hw_resource_list_t *rootpc_get_resources(ddf_fun_t *fnode)
     95{
     96        rootpc_fun_t *fun = ROOTPC_FUN(fnode);
     97       
     98        assert(fun != NULL);
     99        return &fun->hw_resources;
     100}
     101
     102static bool rootpc_enable_interrupt(ddf_fun_t *fun)
    103103{
    104104        /* TODO */
     
    107107}
    108108
    109 static hw_res_ops_t child_hw_res_ops = {
    110         &rootpc_get_child_resources,
    111         &rootpc_enable_child_interrupt
     109static hw_res_ops_t fun_hw_res_ops = {
     110        &rootpc_get_resources,
     111        &rootpc_enable_interrupt
    112112};
    113113
    114114/* Initialized in root_pc_init() function. */
    115 static device_ops_t rootpc_child_ops;
     115static ddf_dev_ops_t rootpc_fun_ops;
    116116
    117117static bool
    118 rootpc_add_child(device_t *parent, const char *name, const char *str_match_id,
    119     rootpc_child_dev_data_t *drv_data)
    120 {
    121         printf(NAME ": adding new child device '%s'.\n", name);
    122        
    123         device_t *child = NULL;
     118rootpc_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id,
     119    rootpc_fun_t *fun)
     120{
     121        printf(NAME ": adding new function '%s'.\n", name);
     122       
     123        ddf_fun_t *fnode = NULL;
    124124        match_id_t *match_id = NULL;
    125125       
    126126        /* Create new device. */
    127         child = create_device();
    128         if (NULL == child)
     127        fnode = ddf_fun_create(dev, fun_inner, name);
     128        if (fnode == NULL)
    129129                goto failure;
    130130       
    131         child->name = name;
    132         child->driver_data = drv_data;
     131        fnode->driver_data = fun;
    133132       
    134133        /* Initialize match id list */
    135134        match_id = create_match_id();
    136         if (NULL == match_id)
     135        if (match_id == NULL)
    137136                goto failure;
    138137       
    139138        match_id->id = str_match_id;
    140139        match_id->score = 100;
    141         add_match_id(&child->match_ids, match_id);
     140        add_match_id(&fnode->match_ids, match_id);
    142141       
    143142        /* Set provided operations to the device. */
    144         child->ops = &rootpc_child_ops;
    145        
    146         /* Register child device. */
    147         if (EOK != child_device_register(child, parent))
     143        fnode->ops = &rootpc_fun_ops;
     144       
     145        /* Register function. */
     146        if (ddf_fun_bind(fnode) != EOK) {
     147                printf(NAME ": error binding function %s.\n", name);
    148148                goto failure;
     149        }
    149150       
    150151        return true;
    151152       
    152153failure:
    153         if (NULL != match_id)
     154        if (match_id != NULL)
    154155                match_id->id = NULL;
    155156       
    156         if (NULL != child) {
    157                 child->name = NULL;
    158                 delete_device(child);
    159         }
    160        
    161         printf(NAME ": failed to add child device '%s'.\n", name);
     157        if (fnode != NULL)
     158                ddf_fun_destroy(fnode);
     159       
     160        printf(NAME ": failed to add function '%s'.\n", name);
    162161       
    163162        return false;
    164163}
    165164
    166 static bool rootpc_add_children(device_t *dev)
    167 {
    168         return rootpc_add_child(dev, "pci0", "intel_pci", &pci_data);
     165static bool rootpc_add_functions(ddf_dev_t *dev)
     166{
     167        return rootpc_add_fun(dev, "pci0", "intel_pci", &pci_data);
    169168}
    170169
     
    175174 * @return              Zero on success, negative error number otherwise.
    176175 */
    177 static int rootpc_add_device(device_t *dev)
     176static int rootpc_add_device(ddf_dev_t *dev)
    178177{
    179178        printf(NAME ": rootpc_add_device, device handle = %d\n",
    180179            (int)dev->handle);
    181180       
    182         /* Register child devices. */
    183         if (!rootpc_add_children(dev)) {
    184                 printf(NAME ": failed to add child devices for PC platform.\n");
     181        /* Register functions. */
     182        if (!rootpc_add_functions(dev)) {
     183                printf(NAME ": failed to add functions for PC platform.\n");
    185184        }
    186185       
     
    190189static void root_pc_init(void)
    191190{
    192         rootpc_child_ops.interfaces[HW_RES_DEV_IFACE] = &child_hw_res_ops;
     191        rootpc_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
    193192}
    194193
     
    197196        printf(NAME ": HelenOS PC platform driver\n");
    198197        root_pc_init();
    199         return driver_main(&rootpc_driver);
     198        return ddf_driver_main(&rootpc_driver);
    200199}
    201200
  • uspace/drv/rootvirt/rootvirt.c

    r6a343bdf r0c968a17  
    3939#include <errno.h>
    4040#include <str_error.h>
    41 #include <driver.h>
     41#include <ddf/driver.h>
    4242
    4343#define NAME "rootvirt"
    4444
    45 /** Virtual device entry. */
     45/** Virtual function entry */
    4646typedef struct {
    47         /** Device name. */
     47        /** Function name */
    4848        const char *name;
    49         /** Device match id. */
     49        /** Function match ID */
    5050        const char *match_id;
    51 } virtual_device_t;
     51} virtual_function_t;
    5252
    53 /** List of existing virtual devices. */
    54 virtual_device_t virtual_devices[] = {
     53/** List of existing virtual functions */
     54virtual_function_t virtual_functions[] = {
    5555#include "devices.def"
    56         /* Terminating item. */
     56        /* Terminating item */
    5757        {
    5858                .name = NULL,
     
    6161};
    6262
    63 static int add_device(device_t *dev);
     63static int rootvirt_add_device(ddf_dev_t *dev);
    6464
    6565static driver_ops_t rootvirt_ops = {
    66         .add_device = &add_device
     66        .add_device = &rootvirt_add_device
    6767};
    6868
     
    7272};
    7373
    74 /** Add child device.
     74/** Add function to the virtual device.
    7575 *
    76  * @param parent Parent device.
    77  * @param virt_dev Virtual device to add.
    78  * @return Error code.
     76 * @param vdev          The virtual device
     77 * @param vfun          Virtual function description
     78 * @return              EOK on success or negative error code.
    7979 */
    80 static int add_child(device_t *parent, virtual_device_t *virt_dev)
     80static int rootvirt_add_fun(ddf_dev_t *vdev, virtual_function_t *vfun)
    8181{
    82         printf(NAME ": registering child device `%s' (match \"%s\")\n",
    83             virt_dev->name, virt_dev->match_id);
     82        ddf_fun_t *fun;
     83        int rc;
    8484
    85         int rc = child_device_register_wrapper(parent, virt_dev->name,
    86             virt_dev->match_id, 10);
     85        printf(NAME ": registering function `%s' (match \"%s\")\n",
     86            vfun->name, vfun->match_id);
    8787
    88         if (rc == EOK) {
    89                 printf(NAME ": registered child device `%s'\n",
    90                     virt_dev->name);
    91         } else {
    92                 printf(NAME ": failed to register child device `%s': %s\n",
    93                     virt_dev->name, str_error(rc));
     88        fun = ddf_fun_create(vdev, fun_inner, vfun->name);
     89        if (fun == NULL) {
     90                printf(NAME ": error creating function %s\n", vfun->name);
     91                return ENOMEM;
    9492        }
    9593
    96         return rc;
     94        rc = ddf_fun_add_match_id(fun, vfun->match_id, 10);
     95        if (rc != EOK) {
     96                printf(NAME ": error adding match IDs to function %s\n",
     97                    vfun->name);
     98                ddf_fun_destroy(fun);
     99                return rc;
     100        }
     101
     102        rc = ddf_fun_bind(fun);
     103        if (rc != EOK) {
     104                printf(NAME ": error binding function %s: %s\n", vfun->name,
     105                    str_error(rc));
     106                ddf_fun_destroy(fun);
     107                return rc;
     108        }
     109
     110        printf(NAME ": registered child device `%s'\n", vfun->name);
     111        return EOK;
    97112}
    98113
    99 static int add_device(device_t *dev)
     114static int rootvirt_add_device(ddf_dev_t *dev)
    100115{
    101116        static int instances = 0;
     
    109124        }
    110125
    111         printf(NAME ": add_device(name=\"%s\", handle=%d)\n",
    112             dev->name, (int)dev->handle);
    113        
     126        printf(NAME ": add_device(handle=%d)\n", (int)dev->handle);
     127
    114128        /*
    115          * Go through all virtual devices and try to add them.
     129         * Go through all virtual functions and try to add them.
    116130         * We silently ignore failures.
    117131         */
    118         virtual_device_t *virt_dev = virtual_devices;
    119         while (virt_dev->name != NULL) {
    120                 (void) add_child(dev, virt_dev);
    121                 virt_dev++;
     132        virtual_function_t *vfun = virtual_functions;
     133        while (vfun->name != NULL) {
     134                (void) rootvirt_add_fun(dev, vfun);
     135                vfun++;
    122136        }
    123137
     
    128142{
    129143        printf(NAME ": HelenOS virtual devices root driver\n");
    130         return driver_main(&rootvirt_driver);
     144        return ddf_driver_main(&rootvirt_driver);
    131145}
    132146
  • uspace/drv/test1/char.c

    r6a343bdf r0c968a17  
    3737#include "test1.h"
    3838
    39 static int impl_char_read(device_t *dev, char *buf, size_t count) {
     39static int impl_char_read(ddf_fun_t *fun, char *buf, size_t count) {
    4040        memset(buf, 0, count);
    4141        return count;
    4242}
    4343
    44 static int imp_char_write(device_t *dev, char *buf, size_t count) {
     44static int imp_char_write(ddf_fun_t *fun, char *buf, size_t count) {
    4545        return count;
    4646}
     
    5151};
    5252
    53 device_ops_t char_device_ops = {
     53ddf_dev_ops_t char_device_ops = {
    5454        .interfaces[CHAR_DEV_IFACE] = &char_dev_ops
    5555};
  • uspace/drv/test1/test1.c

    r6a343bdf r0c968a17  
    3434#include <errno.h>
    3535#include <str_error.h>
     36#include <ddf/driver.h>
     37
    3638#include "test1.h"
    3739
    38 static int add_device(device_t *dev);
     40static int test1_add_device(ddf_dev_t *dev);
    3941
    4042static driver_ops_t driver_ops = {
    41         .add_device = &add_device
     43        .add_device = &test1_add_device
    4244};
    4345
    44 static driver_t the_driver = {
     46static driver_t test1_driver = {
    4547        .name = NAME,
    4648        .driver_ops = &driver_ops
     
    5557 * @param score Device match score.
    5658 */
    57 static void register_child_verbose(device_t *parent, const char *message,
     59static int register_fun_verbose(ddf_dev_t *parent, const char *message,
    5860    const char *name, const char *match_id, int match_score)
    5961{
    60         printf(NAME ": registering child device `%s': %s.\n",
    61            name, message);
     62        ddf_fun_t *fun;
     63        int rc;
    6264
    63         int rc = child_device_register_wrapper(parent, name,
    64             match_id, match_score);
     65        printf(NAME ": registering function `%s': %s.\n", name, message);
    6566
    66         if (rc == EOK) {
    67                 printf(NAME ": registered child device `%s'.\n", name);
    68         } else {
    69                 printf(NAME ": failed to register child `%s' (%s).\n",
    70                     name, str_error(rc));
     67        fun = ddf_fun_create(parent, fun_inner, name);
     68        if (fun == NULL) {
     69                printf(NAME ": error creating function %s\n", name);
     70                return ENOMEM;
    7171        }
     72
     73        rc = ddf_fun_add_match_id(fun, match_id, match_score);
     74        if (rc != EOK) {
     75                printf(NAME ": error adding match IDs to function %s\n", name);
     76                ddf_fun_destroy(fun);
     77                return rc;
     78        }
     79
     80        rc = ddf_fun_bind(fun);
     81        if (rc != EOK) {
     82                printf(NAME ": error binding function %s: %s\n", name,
     83                    str_error(rc));
     84                ddf_fun_destroy(fun);
     85                return rc;
     86        }
     87
     88        printf(NAME ": registered child device `%s'\n", name);
     89        return EOK;
    7290}
    7391
     
    89107 * @return Error code reporting success of the operation.
    90108 */
    91 static int add_device(device_t *dev)
     109static int test1_add_device(ddf_dev_t *dev)
    92110{
     111        ddf_fun_t *fun_a;
     112        int rc;
     113
    93114        printf(NAME ": add_device(name=\"%s\", handle=%d)\n",
    94115            dev->name, (int) dev->handle);
    95116
    96         add_device_to_class(dev, "virtual");
     117        fun_a = ddf_fun_create(dev, fun_exposed, "a");
     118        if (fun_a == NULL) {
     119                printf(NAME ": error creating function 'a'.\n");
     120                return ENOMEM;
     121        }
     122
     123        rc = ddf_fun_bind(fun_a);
     124        if (rc != EOK) {
     125                printf(NAME ": error binding function 'a'.\n");
     126                return rc;
     127        }
     128
     129        ddf_fun_add_to_class(fun_a, "virtual");
    97130
    98131        if (str_cmp(dev->name, "null") == 0) {
    99                 dev->ops = &char_device_ops;
    100                 add_device_to_class(dev, "virt-null");
    101         } else if (dev->parent == NULL) {
    102                 register_child_verbose(dev, "cloning myself ;-)", "clone",
     132                fun_a->ops = &char_device_ops;
     133                ddf_fun_add_to_class(fun_a, "virt-null");
     134        } else if (str_cmp(dev->name, "test1") == 0) {
     135                (void) register_fun_verbose(dev, "cloning myself ;-)", "clone",
    103136                    "virtual&test1", 10);
    104137        } else if (str_cmp(dev->name, "clone") == 0) {
    105                 register_child_verbose(dev, "run by the same task", "child",
     138                (void) register_fun_verbose(dev, "run by the same task", "child",
    106139                    "virtual&test1&child", 10);
    107140        }
     
    115148{
    116149        printf(NAME ": HelenOS test1 virtual device driver\n");
    117         return driver_main(&the_driver);
     150        return ddf_driver_main(&test1_driver);
    118151}
    119152
  • uspace/drv/test1/test1.h

    r6a343bdf r0c968a17  
    3232#define DRV_TEST1_TEST1_H_
    3333
    34 #include <driver.h>
     34#include <ddf/driver.h>
    3535
    3636#define NAME "test1"
    3737
    38 extern device_ops_t char_device_ops;
     38extern ddf_dev_ops_t char_device_ops;
    3939
    4040#endif
  • uspace/drv/test2/test2.c

    r6a343bdf r0c968a17  
    3131
    3232#include <assert.h>
     33#include <async.h>
    3334#include <stdio.h>
    3435#include <errno.h>
    3536#include <str_error.h>
    36 #include <driver.h>
     37#include <ddf/driver.h>
    3738
    3839#define NAME "test2"
    3940
    40 static int add_device(device_t *dev);
     41static int test2_add_device(ddf_dev_t *dev);
    4142
    4243static driver_ops_t driver_ops = {
    43         .add_device = &add_device
     44        .add_device = &test2_add_device
    4445};
    4546
    46 static driver_t the_driver = {
     47static driver_t test2_driver = {
    4748        .name = NAME,
    4849        .driver_ops = &driver_ops
     
    5758 * @param score Device match score.
    5859 */
    59 static void register_child_verbose(device_t *parent, const char *message,
     60static int register_fun_verbose(ddf_dev_t *parent, const char *message,
    6061    const char *name, const char *match_id, int match_score)
    6162{
    62         printf(NAME ": registering child device `%s': %s.\n",
    63            name, message);
     63        ddf_fun_t *fun;
     64        int rc;
    6465
    65         int rc = child_device_register_wrapper(parent, name,
    66             match_id, match_score);
     66        printf(NAME ": registering function `%s': %s.\n", name, message);
    6767
    68         if (rc == EOK) {
    69                 printf(NAME ": registered child device `%s'.\n", name);
    70         } else {
    71                 printf(NAME ": failed to register child `%s' (%s).\n",
    72                     name, str_error(rc));
     68        fun = ddf_fun_create(parent, fun_inner, name);
     69        if (fun == NULL) {
     70                printf(NAME ": error creating function %s\n", name);
     71                return ENOMEM;
    7372        }
     73
     74        rc = ddf_fun_add_match_id(fun, match_id, match_score);
     75        if (rc != EOK) {
     76                printf(NAME ": error adding match IDs to function %s\n", name);
     77                ddf_fun_destroy(fun);
     78                return rc;
     79        }
     80
     81        rc = ddf_fun_bind(fun);
     82        if (rc != EOK) {
     83                printf(NAME ": error binding function %s: %s\n", name,
     84                    str_error(rc));
     85                ddf_fun_destroy(fun);
     86                return rc;
     87        }
     88
     89        printf(NAME ": registered child device `%s'\n", name);
     90        return EOK;
    7491}
    7592
    7693/** Add child devices after some sleep.
    7794 *
    78  * @param arg Parent device structure (device_t *).
     95 * @param arg Parent device structure (ddf_dev_t *).
    7996 * @return Always EOK.
    8097 */
    8198static int postponed_birth(void *arg)
    8299{
    83         device_t *dev = (device_t *) arg;
     100        ddf_dev_t *dev = (ddf_dev_t *) arg;
     101        ddf_fun_t *fun_a;
     102        int rc;
    84103
    85104        async_usleep(1000);
    86105
    87         register_child_verbose(dev, "child driven by the same task",
     106        (void) register_fun_verbose(dev, "child driven by the same task",
    88107            "child", "virtual&test2", 10);
    89         register_child_verbose(dev, "child driven by test1",
     108        (void) register_fun_verbose(dev, "child driven by test1",
    90109            "test1", "virtual&test1", 10);
    91110
    92         add_device_to_class(dev, "virtual");
     111        fun_a = ddf_fun_create(dev, fun_exposed, "a");
     112        if (fun_a == NULL) {
     113                printf(NAME ": error creating function 'a'.\n");
     114                return ENOMEM;
     115        }
     116
     117        rc = ddf_fun_bind(fun_a);
     118        if (rc != EOK) {
     119                printf(NAME ": error binding function 'a'.\n");
     120                return rc;
     121        }
     122
     123        ddf_fun_add_to_class(fun_a, "virtual");
    93124
    94125        return EOK;
    95126}
    96127
    97 
    98 static int add_device(device_t *dev)
     128static int test2_add_device(ddf_dev_t *dev)
    99129{
    100         printf(NAME ": add_device(name=\"%s\", handle=%d)\n",
     130        printf(NAME ": test2_add_device(name=\"%s\", handle=%d)\n",
    101131            dev->name, (int) dev->handle);
    102132
    103         if (dev->parent == NULL) {
     133        if (str_cmp(dev->name, "child") != 0) {
    104134                fid_t postpone = fibril_create(postponed_birth, dev);
    105135                if (postpone == 0) {
     
    109139                fibril_add_ready(postpone);
    110140        } else {
    111                 register_child_verbose(dev, "child without available driver",
     141                (void) register_fun_verbose(dev, "child without available driver",
    112142                    "ERROR", "non-existent.match.id", 10);
    113143        }
     
    119149{
    120150        printf(NAME ": HelenOS test2 virtual device driver\n");
    121         return driver_main(&the_driver);
     151        return ddf_driver_main(&test2_driver);
    122152}
    123153
  • uspace/lib/c/generic/devman.c

    r6a343bdf r0c968a17  
    123123}
    124124
    125 static int devman_send_match_id(int phone, match_id_t *match_id) \
    126 {
    127         ipc_call_t answer;
    128         aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score, &answer);
    129         int retval = async_data_write_start(phone, match_id->id, str_size(match_id->id));
     125static int devman_send_match_id(int phone, match_id_t *match_id)
     126{
     127        ipc_call_t answer;
     128
     129        aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score,
     130            &answer);
     131        int retval = async_data_write_start(phone, match_id->id,
     132            str_size(match_id->id));
     133
    130134        async_wait_for(req, NULL);
    131135        return retval;
     
    133137
    134138
    135 static int devman_send_match_ids(int phone, match_id_list_t *match_ids) 
     139static int devman_send_match_ids(int phone, match_id_list_t *match_ids)
    136140{
    137141        link_t *link = match_ids->ids.next;
    138142        match_id_t *match_id = NULL;
    139143        int ret = EOK;
    140        
     144
    141145        while (link != &match_ids->ids) {
    142146                match_id = list_get_instance(link, match_id_t, link);
    143                 if (EOK != (ret = devman_send_match_id(phone, match_id)))
    144                 {
    145                         printf("Driver failed to send match id, error number = %d\n", ret);
    146                         return ret;                     
    147                 }
     147                ret = devman_send_match_id(phone, match_id);
     148                if (ret != EOK) {
     149                        printf("Driver failed to send match id, error %d\n",
     150                            ret);
     151                        return ret;
     152                }
     153
    148154                link = link->next;
    149155        }
    150         return ret;     
    151 }
    152 
    153 int devman_child_device_register(
    154         const char *name, match_id_list_t *match_ids, devman_handle_t parent_handle, devman_handle_t *handle)
    155 {               
     156
     157        return ret;
     158}
     159
     160/** Add function to a device.
     161 *
     162 * Request devman to add a new function to the specified device owned by
     163 * this driver task.
     164 *
     165 * @param name          Name of the new function
     166 * @param ftype         Function type, fun_inner or fun_exposed
     167 * @param match_ids     Match IDs (should be empty for fun_exposed)
     168 * @param devh          Devman handle of the device
     169 * @param funh          Place to store handle of the new function
     170 *
     171 * @return              EOK on success or negative error code.
     172 */
     173int devman_add_function(const char *name, fun_type_t ftype,
     174    match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
     175{
    156176        int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
     177        int fun_handle;
    157178       
    158179        if (phone < 0)
     
    161182        async_serialize_start();
    162183       
    163         int match_count = list_count(&match_ids->ids); 
    164         ipc_call_t answer;
    165         aid_t req = async_send_2(phone, DEVMAN_ADD_CHILD_DEVICE, parent_handle, match_count, &answer);
     184        int match_count = list_count(&match_ids->ids);
     185        ipc_call_t answer;
     186
     187        aid_t req = async_send_3(phone, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
     188            devh, match_count, &answer);
    166189
    167190        sysarg_t retval = async_data_write_start(phone, name, str_size(name));
     
    178201        async_serialize_end();
    179202       
    180         if (retval != EOK) {
    181                 if (handle != NULL) {
    182                         *handle = -1;
    183                 }
    184                 return retval;
    185         }       
    186        
    187         if (handle != NULL)
    188                 *handle = (int) IPC_GET_ARG1(answer);   
    189                
    190         return retval;
    191 }
    192 
    193 int devman_add_device_to_class(devman_handle_t devman_handle, const char *class_name)
     203        if (retval == EOK)
     204                fun_handle = (int) IPC_GET_ARG1(answer);
     205        else
     206                fun_handle = -1;
     207       
     208        *funh = fun_handle;
     209
     210        return retval;
     211}
     212
     213int devman_add_device_to_class(devman_handle_t devman_handle,
     214    const char *class_name)
    194215{
    195216        int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
     
    200221        async_serialize_start();
    201222        ipc_call_t answer;
    202         aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS, devman_handle, &answer);
    203        
    204         sysarg_t retval = async_data_write_start(phone, class_name, str_size(class_name));
     223        aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS,
     224            devman_handle, &answer);
     225       
     226        sysarg_t retval = async_data_write_start(phone, class_name,
     227            str_size(class_name));
    205228        if (retval != EOK) {
    206229                async_wait_for(req, NULL);
     
    212235        async_serialize_end();
    213236       
    214         return retval; 
     237        return retval;
    215238}
    216239
     
    265288}
    266289
    267 int devman_device_get_handle(const char *pathname, devman_handle_t *handle, unsigned int flags)
     290int devman_device_get_handle(const char *pathname, devman_handle_t *handle,
     291    unsigned int flags)
    268292{
    269293        int phone = devman_get_phone(DEVMAN_CLIENT, flags);
     
    278302            &answer);
    279303       
    280         sysarg_t retval = async_data_write_start(phone, pathname, str_size(pathname));
     304        sysarg_t retval = async_data_write_start(phone, pathname,
     305            str_size(pathname));
    281306        if (retval != EOK) {
    282307                async_wait_for(req, NULL);
  • uspace/lib/c/include/devman.h

    r6a343bdf r0c968a17  
    4545
    4646extern int devman_driver_register(const char *, async_client_conn_t);
    47 extern int devman_child_device_register(const char *, match_id_list_t *,
     47extern int devman_add_function(const char *, fun_type_t, match_id_list_t *,
    4848    devman_handle_t, devman_handle_t *);
    4949
  • uspace/lib/c/include/ipc/devman.h

    r6a343bdf r0c968a17  
    4242
    4343typedef sysarg_t devman_handle_t;
     44
     45typedef enum {
     46        /** Invalid value for debugging purposes */
     47        fun_invalid = 0,
     48        /** Function to which child devices attach */
     49        fun_inner,
     50        /** Fuction exported to external clients (leaf function) */
     51        fun_exposed
     52} fun_type_t;
    4453
    4554/** Ids of device models used for device-to-driver matching.
     
    127136typedef enum {
    128137        DEVMAN_DRIVER_REGISTER = IPC_FIRST_USER_METHOD,
    129         DEVMAN_ADD_CHILD_DEVICE,
     138        DEVMAN_ADD_FUNCTION,
    130139        DEVMAN_ADD_MATCH_ID,
    131140        DEVMAN_ADD_DEVICE_TO_CLASS
  • uspace/lib/drv/generic/driver.c

    r6a343bdf r0c968a17  
    11/*
    22 * Copyright (c) 2010 Lenka Trochtova
     3 * Copyright (c) 2011 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    4950#include <errno.h>
    5051#include <inttypes.h>
     52#include <devman.h>
    5153
    5254#include <ipc/driver.h>
    5355
    5456#include "dev_iface.h"
    55 #include "driver.h"
     57#include "ddf/driver.h"
     58#include "ddf/interrupt.h"
    5659
    5760/** Driver structure */
     
    5962
    6063/** Devices */
    61 LIST_INITIALIZE(devices);
    62 FIBRIL_MUTEX_INITIALIZE(devices_mutex);
     64LIST_INITIALIZE(functions);
     65FIBRIL_MUTEX_INITIALIZE(functions_mutex);
    6366
    6467/** Interrupts */
     
    7679};
    7780
     81static ddf_dev_t *create_device(void);
     82static void delete_device(ddf_dev_t *);
     83static remote_handler_t *function_get_default_handler(ddf_fun_t *);
     84static void *function_get_ops(ddf_fun_t *, dev_inferface_idx_t);
    7885
    7986static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall)
     
    150157
    151158interrupt_context_t *
    152 find_interrupt_context(interrupt_context_list_t *list, device_t *dev, int irq)
     159find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq)
    153160{
    154161        fibril_mutex_lock(&list->mutex);
     
    172179
    173180int
    174 register_interrupt_handler(device_t *dev, int irq, interrupt_handler_t *handler,
     181register_interrupt_handler(ddf_dev_t *dev, int irq, interrupt_handler_t *handler,
    175182    irq_code_t *pseudocode)
    176183{
     
    195202}
    196203
    197 int unregister_interrupt_handler(device_t *dev, int irq)
     204int unregister_interrupt_handler(ddf_dev_t *dev, int irq)
    198205{
    199206        interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts,
     
    209216}
    210217
    211 static void add_to_devices_list(device_t *dev)
    212 {
    213         fibril_mutex_lock(&devices_mutex);
    214         list_append(&dev->link, &devices);
    215         fibril_mutex_unlock(&devices_mutex);
    216 }
    217 
    218 static void remove_from_devices_list(device_t *dev)
    219 {
    220         fibril_mutex_lock(&devices_mutex);
    221         list_remove(&dev->link);
    222         fibril_mutex_unlock(&devices_mutex);
    223 }
    224 
    225 static device_t *driver_get_device(link_t *devices, devman_handle_t handle)
    226 {
    227         device_t *dev = NULL;
    228        
    229         fibril_mutex_lock(&devices_mutex);
    230         link_t *link = devices->next;
    231        
    232         while (link != devices) {
    233                 dev = list_get_instance(link, device_t, link);
    234                 if (dev->handle == handle) {
    235                         fibril_mutex_unlock(&devices_mutex);
    236                         return dev;
     218static void add_to_functions_list(ddf_fun_t *fun)
     219{
     220        fibril_mutex_lock(&functions_mutex);
     221        list_append(&fun->link, &functions);
     222        fibril_mutex_unlock(&functions_mutex);
     223}
     224
     225static void remove_from_functions_list(ddf_fun_t *fun)
     226{
     227        fibril_mutex_lock(&functions_mutex);
     228        list_remove(&fun->link);
     229        fibril_mutex_unlock(&functions_mutex);
     230}
     231
     232static ddf_fun_t *driver_get_function(link_t *functions, devman_handle_t handle)
     233{
     234        ddf_fun_t *fun = NULL;
     235       
     236        fibril_mutex_lock(&functions_mutex);
     237        link_t *link = functions->next;
     238       
     239        while (link != functions) {
     240                fun = list_get_instance(link, ddf_fun_t, link);
     241                if (fun->handle == handle) {
     242                        fibril_mutex_unlock(&functions_mutex);
     243                        return fun;
    237244                }
     245               
    238246                link = link->next;
    239247        }
    240248       
    241         fibril_mutex_unlock(&devices_mutex);
     249        fibril_mutex_unlock(&functions_mutex);
    242250       
    243251        return NULL;
     
    250258       
    251259        devman_handle_t dev_handle = IPC_GET_ARG1(*icall);
    252         devman_handle_t parent_dev_handle = IPC_GET_ARG2(*icall);
    253        
    254         device_t *dev = create_device();
     260        devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall);
     261       
     262        ddf_dev_t *dev = create_device();
    255263        dev->handle = dev_handle;
    256        
     264
    257265        async_data_write_accept((void **) &dev_name, true, 0, 0, 0, 0);
    258266        dev->name = dev_name;
    259        
    260         add_to_devices_list(dev);
    261         dev->parent = driver_get_device(&devices, parent_dev_handle);
     267
     268        /*
     269         * Currently not used, parent fun handle is stored in context
     270         * of the connection to the parent device driver.
     271         */
     272        (void) parent_fun_handle;
    262273       
    263274        res = driver->driver_ops->add_device(dev);
     
    268279                printf("%s: failed to add a new device with handle = %" PRIun ".\n",
    269280                    driver->name, dev_handle);
    270                 remove_from_devices_list(dev);
    271281                delete_device(dev);
    272282        }
     
    311321         */
    312322        devman_handle_t handle = IPC_GET_ARG2(*icall);
    313         device_t *dev = driver_get_device(&devices, handle);
    314 
    315         if (dev == NULL) {
    316                 printf("%s: driver_connection_gen error - no device with handle"
     323        ddf_fun_t *fun = driver_get_function(&functions, handle);
     324
     325        if (fun == NULL) {
     326                printf("%s: driver_connection_gen error - no function with handle"
    317327                    " %" PRIun " was found.\n", driver->name, handle);
    318328                async_answer_0(iid, ENOENT);
     
    327337       
    328338        int ret = EOK;
    329         /* open the device */
    330         if (dev->ops != NULL && dev->ops->open != NULL)
    331                 ret = (*dev->ops->open)(dev);
     339        /* Open device function */
     340        if (fun->ops != NULL && fun->ops->open != NULL)
     341                ret = (*fun->ops->open)(fun);
    332342       
    333343        async_answer_0(iid, ret);
     
    344354                switch  (method) {
    345355                case IPC_M_PHONE_HUNGUP:
    346                         /* close the device */
    347                         if (dev->ops != NULL && dev->ops->close != NULL)
    348                                 (*dev->ops->close)(dev);
     356                        /* Close device function */
     357                        if (fun->ops != NULL && fun->ops->close != NULL)
     358                                (*fun->ops->close)(fun);
    349359                        async_answer_0(callid, EOK);
    350360                        return;
     
    356366                        if (!is_valid_iface_idx(iface_idx)) {
    357367                                remote_handler_t *default_handler =
    358                                     device_get_default_handler(dev);
     368                                    function_get_default_handler(fun);
    359369                                if (default_handler != NULL) {
    360                                         (*default_handler)(dev, callid, &call);
     370                                        (*default_handler)(fun, callid, &call);
    361371                                        break;
    362372                                }
     373                               
    363374                                /*
    364                                  * This is not device's interface and the
     375                                 * Function has no such interface and
    365376                                 * default handler is not provided.
    366377                                 */
     
    372383                        }
    373384                       
    374                         /* calling one of the device's interfaces */
     385                        /* calling one of the function's interfaces */
    375386                       
    376387                        /* Get the interface ops structure. */
    377                         void *ops = device_get_ops(dev, iface_idx);
     388                        void *ops = function_get_ops(fun, iface_idx);
    378389                        if (ops == NULL) {
    379390                                printf("%s: driver_connection_gen error - ",
    380391                                    driver->name);
    381                                 printf("device with handle %" PRIun " has no interface "
     392                                printf("Function with handle %" PRIun " has no interface "
    382393                                    "with id %d.\n", handle, iface_idx);
    383394                                async_answer_0(callid, ENOTSUP);
     
    408419                         * receive parameters from the remote client and it will
    409420                         * pass it to the corresponding local interface method
    410                          * associated with the device by its driver.
     421                         * associated with the function by its driver.
    411422                         */
    412                         (*iface_method_ptr)(dev, ops, callid, &call);
     423                        (*iface_method_ptr)(fun, ops, callid, &call);
    413424                        break;
    414425                }
     
    425436        driver_connection_gen(iid, icall, false);
    426437}
    427 
    428438
    429439/** Function for handling connections to device driver. */
     
    454464 * @return              The device structure.
    455465 */
    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 
     466static ddf_dev_t *create_device(void)
     467{
     468        ddf_dev_t *dev;
     469
     470        dev = malloc(sizeof(ddf_dev_t));
     471        if (dev == NULL)
     472                return NULL;
     473
     474        memset(dev, 0, sizeof(ddf_dev_t));
    465475        return dev;
    466476}
    467477
     478/** Create new function structure.
     479 *
     480 * @return              The device structure.
     481 */
     482static ddf_fun_t *create_function(void)
     483{
     484        ddf_fun_t *fun;
     485
     486        fun = calloc(1, sizeof(ddf_fun_t));
     487        if (fun == NULL)
     488                return NULL;
     489
     490        init_match_ids(&fun->match_ids);
     491        link_initialize(&fun->link);
     492
     493        return fun;
     494}
     495
    468496/** Delete device structure.
    469497 *
    470498 * @param dev           The device structure.
    471499 */
    472 void delete_device(device_t *dev)
    473 {
    474         clean_match_ids(&dev->match_ids);
    475         if (dev->name != NULL)
    476                 free(dev->name);
     500static void delete_device(ddf_dev_t *dev)
     501{
    477502        free(dev);
    478503}
    479504
    480 void *device_get_ops(device_t *dev, dev_inferface_idx_t idx)
     505/** Delete device structure.
     506 *
     507 * @param dev           The device structure.
     508 */
     509static void delete_function(ddf_fun_t *fun)
     510{
     511        clean_match_ids(&fun->match_ids);
     512        if (fun->name != NULL)
     513                free(fun->name);
     514        free(fun);
     515}
     516
     517/** Create a DDF function node.
     518 *
     519 * Create a DDF function (in memory). Both child devices and external clients
     520 * communicate with a device via its functions.
     521 *
     522 * The created function node is fully formed, but only exists in the memory
     523 * of the client task. In order to be visible to the system, the function
     524 * must be bound using ddf_fun_bind().
     525 *
     526 * This function should only fail if there is not enough free memory.
     527 * Specifically, this function succeeds even if @a dev already has
     528 * a (bound) function with the same name.
     529 *
     530 * Type: A function of type fun_inner indicates that DDF should attempt
     531 * to attach child devices to the function. fun_exposed means that
     532 * the function should be exported to external clients (applications).
     533 *
     534 * @param dev           Device to which we are adding function
     535 * @param ftype         Type of function (fun_inner or fun_exposed)
     536 * @param name          Name of function
     537 *
     538 * @return              New function or @c NULL if memory is not available
     539 */
     540ddf_fun_t *ddf_fun_create(ddf_dev_t *dev, fun_type_t ftype, const char *name)
     541{
     542        ddf_fun_t *fun;
     543
     544        fun = create_function();
     545        if (fun == NULL)
     546                return NULL;
     547
     548        fun->bound = false;
     549        fun->dev = dev;
     550        fun->ftype = ftype;
     551
     552        fun->name = str_dup(name);
     553        if (fun->name == NULL) {
     554                delete_function(fun);
     555                return NULL;
     556        }
     557
     558        return fun;
     559}
     560
     561/** Destroy DDF function node.
     562 *
     563 * Destroy a function previously created with ddf_fun_create(). The function
     564 * must not be bound.
     565 *
     566 * @param fun           Function to destroy
     567 */
     568void ddf_fun_destroy(ddf_fun_t *fun)
     569{
     570        assert(fun->bound == false);
     571        delete_function(fun);
     572}
     573
     574static void *function_get_ops(ddf_fun_t *fun, dev_inferface_idx_t idx)
    481575{
    482576        assert(is_valid_iface_idx(idx));
    483         if (dev->ops == NULL)
     577        if (fun->ops == NULL)
    484578                return NULL;
    485         return dev->ops->interfaces[idx];
    486 }
    487 
    488 int child_device_register(device_t *child, device_t *parent)
    489 {
    490         assert(child->name != NULL);
     579        return fun->ops->interfaces[idx];
     580}
     581
     582/** Bind a function node.
     583 *
     584 * Bind the specified function to the system. This effectively makes
     585 * the function visible to the system (uploads it to the server).
     586 *
     587 * This function can fail for several reasons. Specifically,
     588 * it will fail if the device already has a bound function of
     589 * the same name.
     590 *
     591 * @param fun           Function to bind
     592 * @return              EOK on success or negative error code
     593 */
     594int ddf_fun_bind(ddf_fun_t *fun)
     595{
     596        assert(fun->name != NULL);
    491597       
    492598        int res;
    493599       
    494         add_to_devices_list(child);
    495         res = devman_child_device_register(child->name, &child->match_ids,
    496             parent->handle, &child->handle);
     600        add_to_functions_list(fun);
     601        res = devman_add_function(fun->name, fun->ftype, &fun->match_ids,
     602            fun->dev->handle, &fun->handle);
    497603        if (res != EOK) {
    498                 remove_from_devices_list(child);
     604                remove_from_functions_list(fun);
    499605                return res;
    500606        }
    501607       
     608        fun->bound = true;
    502609        return res;
    503610}
    504611
    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;
     612/** Add single match ID to inner function.
     613 *
     614 * Construct and add a single match ID to the specified function.
     615 * Cannot be called when the function node is bound.
     616 *
     617 * @param fun                   Function
     618 * @param match_id_str          Match string
     619 * @param match_score           Match score
     620 * @return                      EOK on success, ENOMEM if out of memory.
     621 */
     622int ddf_fun_add_match_id(ddf_fun_t *fun, const char *match_id_str,
     623    int match_score)
     624{
     625        match_id_t *match_id;
     626       
     627        assert(fun->bound == false);
     628        assert(fun->ftype == fun_inner);
    527629       
    528630        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        
     631        if (match_id == NULL)
     632                return ENOMEM;
     633       
     634        match_id->id = match_id_str;
     635        match_id->score = 90;
     636       
     637        add_match_id(&fun->match_ids, match_id);
    542638        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;
    556639}
    557640
    558641/** Get default handler for client requests */
    559 remote_handler_t *device_get_default_handler(device_t *dev)
    560 {
    561         if (dev->ops == NULL)
     642static remote_handler_t *function_get_default_handler(ddf_fun_t *fun)
     643{
     644        if (fun->ops == NULL)
    562645                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);
    569 }
    570 
    571 int driver_main(driver_t *drv)
     646        return fun->ops->default_handler;
     647}
     648
     649/** Add exposed function to class.
     650 *
     651 * Must only be called when the function is bound.
     652 */
     653int ddf_fun_add_to_class(ddf_fun_t *fun, const char *class_name)
     654{
     655        assert(fun->bound == true);
     656        assert(fun->ftype == fun_exposed);
     657       
     658        return devman_add_device_to_class(fun->handle, class_name);
     659}
     660
     661int ddf_driver_main(driver_t *drv)
    572662{
    573663        /*
  • uspace/lib/drv/generic/remote_char_dev.c

    r6a343bdf r0c968a17  
    3737
    3838#include "ops/char_dev.h"
    39 #include "driver.h"
     39#include "ddf/driver.h"
    4040
    4141#define MAX_CHAR_RW_COUNT 256
    4242
    43 static void remote_char_read(device_t *, void *, ipc_callid_t, ipc_call_t *);
    44 static void remote_char_write(device_t *, void *, ipc_callid_t, ipc_call_t *);
     43static void remote_char_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     44static void remote_char_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    4545
    4646/** Remote character interface operations. */
     
    6767 * local interface to the remote client.
    6868 *
    69  * @param dev           The device from which the data are read.
     69 * @param fun           The function from which the data are read.
    7070 * @param ops           The local ops structure.
    7171 */
    7272static void
    73 remote_char_read(device_t *dev, void *ops, ipc_callid_t callid,
     73remote_char_read(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
    7474    ipc_call_t *call)
    7575{
     
    9494       
    9595        char buf[MAX_CHAR_RW_COUNT];
    96         int ret = (*char_dev_ops->read)(dev, buf, len);
     96        int ret = (*char_dev_ops->read)(fun, buf, len);
    9797       
    9898        if (ret < 0) {
     
    114114 * local interface to the remote client.
    115115 *
    116  * @param dev           The device to which the data are written.
     116 * @param fun           The function to which the data are written.
    117117 * @param ops           The local ops structure.
    118118 */
    119119static void
    120 remote_char_write(device_t *dev, void *ops, ipc_callid_t callid,
     120remote_char_write(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
    121121    ipc_call_t *call)
    122122{
     
    144144        async_data_write_finalize(cid, buf, len);
    145145       
    146         int ret = (*char_dev_ops->write)(dev, buf, len);
     146        int ret = (*char_dev_ops->write)(fun, buf, len);
    147147        if (ret < 0) {
    148148                /* Some error occured. */
  • uspace/lib/drv/generic/remote_hw_res.c

    r6a343bdf r0c968a17  
    3737
    3838#include "ops/hw_res.h"
    39 #include "driver.h"
     39#include "ddf/driver.h"
    4040
    41 static void remote_hw_res_get_resource_list(device_t *, void *, ipc_callid_t,
     41static void remote_hw_res_get_resource_list(ddf_fun_t *, void *, ipc_callid_t,
    4242    ipc_call_t *);
    43 static void remote_hw_res_enable_interrupt(device_t *, void *, ipc_callid_t,
     43static void remote_hw_res_enable_interrupt(ddf_fun_t *, void *, ipc_callid_t,
    4444    ipc_call_t *);
    4545
     
    5555};
    5656
    57 static void remote_hw_res_enable_interrupt(device_t *dev, void *ops,
     57static void remote_hw_res_enable_interrupt(ddf_fun_t *fun, void *ops,
    5858    ipc_callid_t callid, ipc_call_t *call)
    5959{
     
    6262        if (hw_res_ops->enable_interrupt == NULL)
    6363                async_answer_0(callid, ENOTSUP);
    64         else if (hw_res_ops->enable_interrupt(dev))
     64        else if (hw_res_ops->enable_interrupt(fun))
    6565                async_answer_0(callid, EOK);
    6666        else
     
    6868}
    6969
    70 static void remote_hw_res_get_resource_list(device_t *dev, void *ops,
     70static void remote_hw_res_get_resource_list(ddf_fun_t *fun, void *ops,
    7171    ipc_callid_t callid, ipc_call_t *call)
    7272{
     
    7878        }
    7979       
    80         hw_resource_list_t *hw_resources = hw_res_ops->get_resource_list(dev);
     80        hw_resource_list_t *hw_resources = hw_res_ops->get_resource_list(fun);
    8181        if (hw_resources == NULL){
    8282                async_answer_0(callid, ENOENT);
  • uspace/lib/drv/include/ddf/driver.h

    r6a343bdf r0c968a17  
    11/*
    22 * Copyright (c) 2010 Lenka Trochtova
     3 * Copyright (c) 2011 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    3334 */
    3435
    35 #ifndef LIBDRV_DRIVER_H_
    36 #define LIBDRV_DRIVER_H_
     36#ifndef DDF_DRIVER_H_
     37#define DDF_DRIVER_H_
    3738
    38 #include <kernel/ddi/irq.h>
    39 #include <adt/list.h>
    40 #include <devman.h>
    4139#include <ipc/devman.h>
    4240#include <ipc/dev_iface.h>
    43 #include <assert.h>
    44 #include <ddi.h>
    45 #include <libarch/ddi.h>
    46 #include <fibril_synch.h>
    47 #include <malloc.h>
    4841
    49 #include "dev_iface.h"
     42#include "../dev_iface.h"
    5043
    51 struct device;
    52 typedef struct device device_t;
     44typedef struct ddf_dev ddf_dev_t;
     45typedef struct ddf_fun ddf_fun_t;
    5346
    5447/*
    55  * Device class
     48 * Device
    5649 */
    5750
    5851/** Devices operations */
    59 typedef struct device_ops {
     52typedef struct ddf_dev_ops {
    6053        /**
    6154         * Optional callback function called when a client is connecting to the
    6255         * device.
    6356         */
    64         int (*open)(device_t *);
     57        int (*open)(ddf_fun_t *);
    6558       
    6659        /**
     
    6861         * the device.
    6962         */
    70         void (*close)(device_t *);
     63        void (*close)(ddf_fun_t *);
    7164       
    7265        /** The table of standard interfaces implemented by the device. */
     
    7972         */
    8073        remote_handler_t *default_handler;
    81 } device_ops_t;
    82 
    83 
    84 /*
    85  * Device
    86  */
     74} ddf_dev_ops_t;
    8775
    8876/** Device structure */
    89 struct device {
     77struct ddf_dev {
    9078        /**
    9179         * Globally unique device identifier (assigned to the device by the
     
    10088        int parent_phone;
    10189       
    102         /** Parent device if handled by this driver, NULL otherwise */
    103         device_t *parent;
    10490        /** Device name */
    10591        const char *name;
    106         /** List of device ids for device-to-driver matching */
    107         match_id_list_t match_ids;
     92       
    10893        /** Driver-specific data associated with this device */
    10994        void *driver_data;
    110         /** The implementation of operations provided by this device */
    111         device_ops_t *ops;
    11295       
    11396        /** Link in the list of devices handled by the driver */
     97        link_t link;
     98};
     99
     100/** Function structure */
     101struct ddf_fun {
     102        /** True if bound to the device manager */
     103        bool bound;
     104        /** Function indentifier (asigned by device manager) */
     105        devman_handle_t handle;
     106       
     107        /** Device which this function belogs to */
     108        ddf_dev_t *dev;
     109       
     110        /** Function type */
     111        fun_type_t ftype;
     112        /** Function name */
     113        const char *name;
     114        /** List of device ids for driver matching */
     115        match_id_list_t match_ids;
     116        /** Driver-specific data associated with this function */
     117        void *driver_data;
     118        /** Implementation of operations provided by this function */
     119        ddf_dev_ops_t *ops;
     120       
     121        /** Link in the list of functions handled by the driver */
    114122        link_t link;
    115123};
     
    122130typedef struct driver_ops {
    123131        /** Callback method for passing a new device to the device driver */
    124         int (*add_device)(device_t *dev);
     132        int (*add_device)(ddf_dev_t *dev);
    125133        /* TODO: add other generic driver operations */
    126134} driver_ops_t;
     
    134142} driver_t;
    135143
    136 int driver_main(driver_t *);
     144extern int ddf_driver_main(driver_t *);
    137145
    138 /** Create new device structure.
    139  *
    140  * @return              The device structure.
    141  */
    142 extern device_t *create_device(void);
    143 extern void delete_device(device_t *);
    144 extern void *device_get_ops(device_t *, dev_inferface_idx_t);
     146extern ddf_fun_t *ddf_fun_create(ddf_dev_t *, fun_type_t, const char *);
     147extern void ddf_fun_destroy(ddf_fun_t *);
     148extern int ddf_fun_bind(ddf_fun_t *);
     149extern int ddf_fun_add_match_id(ddf_fun_t *, const char *, int);
    145150
    146 extern int child_device_register(device_t *, device_t *);
    147 extern int child_device_register_wrapper(device_t *, const char *, const char *,
    148     int);
    149 
    150 /*
    151  * Interrupts
    152  */
    153 
    154 typedef void interrupt_handler_t(device_t *, ipc_callid_t, ipc_call_t *);
    155 
    156 typedef struct interrupt_context {
    157         int id;
    158         device_t *dev;
    159         int irq;
    160         interrupt_handler_t *handler;
    161         link_t link;
    162 } interrupt_context_t;
    163 
    164 typedef struct interrupt_context_list {
    165         int curr_id;
    166         link_t contexts;
    167         fibril_mutex_t mutex;
    168 } interrupt_context_list_t;
    169 
    170 extern interrupt_context_t *create_interrupt_context(void);
    171 extern void delete_interrupt_context(interrupt_context_t *);
    172 extern void init_interrupt_context_list(interrupt_context_list_t *);
    173 extern void add_interrupt_context(interrupt_context_list_t *,
    174     interrupt_context_t *);
    175 extern void remove_interrupt_context(interrupt_context_list_t *,
    176     interrupt_context_t *);
    177 extern interrupt_context_t *find_interrupt_context_by_id(
    178     interrupt_context_list_t *, int);
    179 extern interrupt_context_t *find_interrupt_context(
    180     interrupt_context_list_t *, device_t *, int);
    181 
    182 extern int register_interrupt_handler(device_t *, int, interrupt_handler_t *,
    183     irq_code_t *);
    184 extern int unregister_interrupt_handler(device_t *, int);
    185 
    186 extern remote_handler_t *device_get_default_handler(device_t *);
    187 extern int add_device_to_class(device_t *, const char *);
     151extern int ddf_fun_add_to_class(ddf_fun_t *, const char *);
    188152
    189153#endif
  • uspace/lib/drv/include/dev_iface.h

    r6a343bdf r0c968a17  
    4343 */
    4444
    45 struct device;
     45struct ddf_fun;
    4646
    4747/*
     
    4949 * devices driver.
    5050 */
    51 typedef void remote_iface_func_t(struct device *, void *, ipc_callid_t,
     51typedef void remote_iface_func_t(struct ddf_fun *, void *, ipc_callid_t,
    5252    ipc_call_t *);
    5353typedef remote_iface_func_t *remote_iface_func_ptr_t;
    54 typedef void remote_handler_t(struct device *, ipc_callid_t, ipc_call_t *);
     54typedef void remote_handler_t(struct ddf_fun *, ipc_callid_t, ipc_call_t *);
    5555
    5656typedef struct {
  • uspace/lib/drv/include/ops/char_dev.h

    r6a343bdf r0c968a17  
    3636#define LIBDRV_OPS_CHAR_DEV_H_
    3737
    38 #include "../driver.h"
     38#include "../ddf/driver.h"
    3939
    4040typedef struct {
    41         int (*read)(device_t *, char *, size_t);
    42         int (*write)(device_t *, char *, size_t);
     41        int (*read)(ddf_fun_t *, char *, size_t);
     42        int (*write)(ddf_fun_t *, char *, size_t);
    4343} char_dev_ops_t;
    4444
  • uspace/lib/drv/include/ops/hw_res.h

    r6a343bdf r0c968a17  
    3939#include <sys/types.h>
    4040
    41 #include "../driver.h"
     41#include "../ddf/driver.h"
    4242
    4343typedef struct {
    44          hw_resource_list_t *(*get_resource_list)(device_t *);
    45          bool (*enable_interrupt)(device_t *);
     44         hw_resource_list_t *(*get_resource_list)(ddf_fun_t *);
     45         bool (*enable_interrupt)(ddf_fun_t *);
    4646} hw_res_ops_t;
    4747
  • uspace/srv/devman/devman.c

    r6a343bdf r0c968a17  
    4141#include "devman.h"
    4242
     43fun_node_t *find_node_child(fun_node_t *parent, const char *name);
     44
    4345/* hash table operations */
    4446
     
    5153    link_t *item)
    5254{
    53         node_t *dev = hash_table_get_instance(item, node_t, devman_link);
     55        dev_node_t *dev = hash_table_get_instance(item, dev_node_t, devman_dev);
    5456        return (dev->handle == (devman_handle_t) key[0]);
    5557}
    5658
    57 static int devmap_devices_compare(unsigned long key[], hash_count_t keys,
     59static int devman_functions_compare(unsigned long key[], hash_count_t keys,
    5860    link_t *item)
    5961{
    60         node_t *dev = hash_table_get_instance(item, node_t, devmap_link);
    61         return (dev->devmap_handle == (devmap_handle_t) key[0]);
     62        fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devman_fun);
     63        return (fun->handle == (devman_handle_t) key[0]);
     64}
     65
     66static int devmap_functions_compare(unsigned long key[], hash_count_t keys,
     67    link_t *item)
     68{
     69        fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devmap_fun);
     70        return (fun->devmap_handle == (devmap_handle_t) key[0]);
    6271}
    6372
     
    8291};
    8392
     93static hash_table_operations_t devman_functions_ops = {
     94        .hash = devices_hash,
     95        .compare = devman_functions_compare,
     96        .remove_callback = devices_remove_callback
     97};
     98
    8499static hash_table_operations_t devmap_devices_ops = {
    85100        .hash = devices_hash,
    86         .compare = devmap_devices_compare,
     101        .compare = devmap_functions_compare,
    87102        .remove_callback = devices_remove_callback
    88103};
     
    373388}
    374389
    375 /** Create root device node in the device tree.
     390/** Create root device and function node in the device tree.
    376391 *
    377392 * @param tree  The device tree.
    378393 * @return      True on success, false otherwise.
    379394 */
    380 bool create_root_node(dev_tree_t *tree)
    381 {
    382         node_t *node;
    383 
    384         printf(NAME ": create_root_node\n");
    385 
     395bool create_root_nodes(dev_tree_t *tree)
     396{
     397        fun_node_t *fun;
     398        dev_node_t *dev;
     399       
     400        printf(NAME ": create_root_nodes\n");
     401       
    386402        fibril_rwlock_write_lock(&tree->rwlock);
    387         node = create_dev_node();
    388         if (node != NULL) {
    389                 insert_dev_node(tree, node, clone_string(""), NULL);
    390                 match_id_t *id = create_match_id();
    391                 id->id = clone_string("root");
    392                 id->score = 100;
    393                 add_match_id(&node->match_ids, id);
    394                 tree->root_node = node;
    395         }
     403       
     404        /*
     405         * Create root function. This is a pseudo function to which
     406         * the root device node is attached. It allows us to match
     407         * the root device driver in a standard manner, i.e. against
     408         * the parent function.
     409         */
     410       
     411        fun = create_fun_node();
     412        if (fun == NULL) {
     413                fibril_rwlock_write_unlock(&tree->rwlock);
     414                return false;
     415        }
     416       
     417        insert_fun_node(tree, fun, clone_string(""), NULL);
     418        match_id_t *id = create_match_id();
     419        id->id = clone_string("root");
     420        id->score = 100;
     421        add_match_id(&fun->match_ids, id);
     422        tree->root_node = fun;
     423       
     424        /*
     425         * Create root device node.
     426         */
     427        dev = create_dev_node();
     428        if (dev == NULL) {
     429                fibril_rwlock_write_unlock(&tree->rwlock);
     430                return false;
     431        }
     432       
     433        insert_dev_node(tree, dev, fun);
     434       
    396435        fibril_rwlock_write_unlock(&tree->rwlock);
    397 
    398         return node != NULL;
     436       
     437        return dev != NULL;
    399438}
    400439
     
    414453 *                      is found.
    415454 */
    416 driver_t *find_best_match_driver(driver_list_t *drivers_list, node_t *node)
     455driver_t *find_best_match_driver(driver_list_t *drivers_list, dev_node_t *node)
    417456{
    418457        driver_t *best_drv = NULL, *drv = NULL;
     
    442481 * @param drv           The driver.
    443482 */
    444 void attach_driver(node_t *node, driver_t *drv)
     483void attach_driver(dev_node_t *dev, driver_t *drv)
    445484{
    446485        printf(NAME ": attach_driver %s to device %s\n",
    447             drv->name, node->pathname);
     486            drv->name, dev->pfun->pathname);
    448487       
    449488        fibril_mutex_lock(&drv->driver_mutex);
    450489       
    451         node->drv = drv;
    452         list_append(&node->driver_devices, &drv->devices);
     490        dev->drv = drv;
     491        list_append(&dev->driver_devices, &drv->devices);
    453492       
    454493        fibril_mutex_unlock(&drv->driver_mutex);
     
    530569static void pass_devices_to_driver(driver_t *driver, dev_tree_t *tree)
    531570{
    532         node_t *dev;
     571        dev_node_t *dev;
    533572        link_t *link;
    534573        int phone;
     
    551590        link = driver->devices.next;
    552591        while (link != &driver->devices) {
    553                 dev = list_get_instance(link, node_t, driver_devices);
     592                dev = list_get_instance(link, dev_node_t, driver_devices);
    554593                if (dev->passed_to_driver) {
    555594                        link = link->next;
     
    669708}
    670709
    671 /** Create devmap path and name for the device. */
    672 static void devmap_register_tree_device(node_t *node, dev_tree_t *tree)
     710/** Create devmap path and name for the function. */
     711void devmap_register_tree_function(fun_node_t *fun, dev_tree_t *tree)
    673712{
    674713        char *devmap_pathname = NULL;
    675714        char *devmap_name = NULL;
    676715       
    677         asprintf(&devmap_name, "%s", node->pathname);
     716        asprintf(&devmap_name, "%s", fun->pathname);
    678717        if (devmap_name == NULL)
    679718                return;
     
    689728       
    690729        devmap_device_register_with_iface(devmap_pathname,
    691             &node->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
    692        
    693         tree_add_devmap_device(tree, node);
     730            &fun->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
     731       
     732        tree_add_devmap_function(tree, fun);
    694733       
    695734        free(devmap_name);
     
    702741 * @param node          The device's node in the device tree.
    703742 */
    704 void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree)
     743void add_device(int phone, driver_t *drv, dev_node_t *dev, dev_tree_t *tree)
    705744{
    706745        /*
     
    709748         */
    710749        printf(NAME ": add_device (driver `%s', device `%s')\n", drv->name,
    711             node->name);
     750            dev->pfun->name);
    712751       
    713752        sysarg_t rc;
     
    716755        /* Send the device to the driver. */
    717756        devman_handle_t parent_handle;
    718         if (node->parent) {
    719                 parent_handle = node->parent->handle;
     757        if (dev->pfun) {
     758                parent_handle = dev->pfun->handle;
    720759        } else {
    721760                parent_handle = 0;
    722761        }
    723762
    724         aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, node->handle,
     763        aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, dev->handle,
    725764            parent_handle, &answer);
    726765       
    727766        /* Send the device's name to the driver. */
    728         rc = async_data_write_start(phone, node->name,
    729             str_size(node->name) + 1);
     767        rc = async_data_write_start(phone, dev->pfun->name,
     768            str_size(dev->pfun->name) + 1);
    730769        if (rc != EOK) {
    731770                /* TODO handle error */
     
    737776        switch(rc) {
    738777        case EOK:
    739                 node->state = DEVICE_USABLE;
    740                 devmap_register_tree_device(node, tree);
     778                dev->state = DEVICE_USABLE;
    741779                break;
    742780        case ENOENT:
    743                 node->state = DEVICE_NOT_PRESENT;
     781                dev->state = DEVICE_NOT_PRESENT;
    744782                break;
    745783        default:
    746                 node->state = DEVICE_INVALID;
    747         }
    748        
    749         node->passed_to_driver = true;
     784                dev->state = DEVICE_INVALID;
     785        }
     786       
     787        dev->passed_to_driver = true;
    750788
    751789        return;
     
    759797 *                      successfully assigned to the device, false otherwise.
    760798 */
    761 bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree)
    762 {
     799bool assign_driver(dev_node_t *dev, driver_list_t *drivers_list,
     800    dev_tree_t *tree)
     801{
     802        assert(dev != NULL);
     803        assert(drivers_list != NULL);
     804        assert(tree != NULL);
     805       
    763806        /*
    764807         * Find the driver which is the most suitable for handling this device.
    765808         */
    766         driver_t *drv = find_best_match_driver(drivers_list, node);
     809        driver_t *drv = find_best_match_driver(drivers_list, dev);
    767810        if (drv == NULL) {
    768811                printf(NAME ": no driver found for device '%s'.\n",
    769                     node->pathname);
     812                    dev->pfun->pathname);
    770813                return false;
    771814        }
    772815       
    773816        /* Attach the driver to the device. */
    774         attach_driver(node, drv);
     817        attach_driver(dev, drv);
    775818       
    776819        fibril_mutex_lock(&drv->driver_mutex);
     
    786829                int phone = async_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
    787830                if (phone >= 0) {
    788                         add_device(phone, drv, node, tree);
     831                        add_device(phone, drv, dev, tree);
    789832                        async_hangup(phone);
    790833                }
     
    810853        hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1,
    811854            &devman_devices_ops);
    812         hash_table_create(&tree->devmap_devices, DEVICE_BUCKETS, 1,
     855        hash_table_create(&tree->devman_functions, DEVICE_BUCKETS, 1,
     856            &devman_functions_ops);
     857        hash_table_create(&tree->devmap_functions, DEVICE_BUCKETS, 1,
    813858            &devmap_devices_ops);
    814859       
    815860        fibril_rwlock_initialize(&tree->rwlock);
    816861       
    817         /* Create root node and add it to the device tree. */
    818         if (!create_root_node(tree))
     862        /* Create root function and root device and add them to the device tree. */
     863        if (!create_root_nodes(tree))
    819864                return false;
    820865
    821866        /* Find suitable driver and start it. */
    822         return assign_driver(tree->root_node, drivers_list, tree);
     867        return assign_driver(tree->root_node->child, drivers_list, tree);
    823868}
    824869
     
    829874 * @return              A device node structure.
    830875 */
    831 node_t *create_dev_node(void)
    832 {
    833         node_t *res = malloc(sizeof(node_t));
     876dev_node_t *create_dev_node(void)
     877{
     878        dev_node_t *res = malloc(sizeof(dev_node_t));
    834879       
    835880        if (res != NULL) {
    836                 memset(res, 0, sizeof(node_t));
    837                 list_initialize(&res->children);
    838                 list_initialize(&res->match_ids.ids);
    839                 list_initialize(&res->classes);
     881                memset(res, 0, sizeof(dev_node_t));
     882                list_initialize(&res->functions);
     883                link_initialize(&res->driver_devices);
     884                link_initialize(&res->devman_dev);
    840885        }
    841886       
     
    847892 * @param node          The device node structure.
    848893 */
    849 void delete_dev_node(node_t *node)
    850 {
    851         assert(list_empty(&node->children));
    852         assert(node->parent == NULL);
    853         assert(node->drv == NULL);
    854        
    855         clean_match_ids(&node->match_ids);
    856         free_not_null(node->name);
    857         free_not_null(node->pathname);
    858         free(node);
     894void delete_dev_node(dev_node_t *dev)
     895{
     896        assert(list_empty(&dev->functions));
     897        assert(dev->pfun == NULL);
     898        assert(dev->drv == NULL);
     899       
     900        free(dev);
    859901}
    860902
     
    865907 * @return              The device node.
    866908 */
    867 node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
     909dev_node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
    868910{
    869911        unsigned long key = handle;
     
    873915       
    874916        link = hash_table_find(&tree->devman_devices, &key);
    875         return hash_table_get_instance(link, node_t, devman_link);
     917        return hash_table_get_instance(link, dev_node_t, devman_dev);
    876918}
    877919
     
    882924 * @return              The device node.
    883925 */
    884 node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle)
    885 {
    886         node_t *node = NULL;
     926dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle)
     927{
     928        dev_node_t *dev = NULL;
    887929       
    888930        fibril_rwlock_read_lock(&tree->rwlock);
    889         node = find_dev_node_no_lock(tree, handle);
     931        dev = find_dev_node_no_lock(tree, handle);
    890932        fibril_rwlock_read_unlock(&tree->rwlock);
    891933       
    892         return node;
    893 }
    894 
     934        return dev;
     935}
     936
     937/* Function nodes */
     938
     939/** Create a new function node.
     940 *
     941 * @return              A function node structure.
     942 */
     943fun_node_t *create_fun_node(void)
     944{
     945        fun_node_t *res = malloc(sizeof(fun_node_t));
     946       
     947        if (res != NULL) {
     948                memset(res, 0, sizeof(fun_node_t));
     949                link_initialize(&res->dev_functions);
     950                list_initialize(&res->match_ids.ids);
     951                list_initialize(&res->classes);
     952                link_initialize(&res->devman_fun);
     953                link_initialize(&res->devmap_fun);
     954        }
     955       
     956        return res;
     957}
     958
     959/** Delete a function node.
     960 *
     961 * @param fun           The device node structure.
     962 */
     963void delete_fun_node(fun_node_t *fun)
     964{
     965        assert(fun->dev == NULL);
     966        assert(fun->child == NULL);
     967       
     968        clean_match_ids(&fun->match_ids);
     969        free_not_null(fun->name);
     970        free_not_null(fun->pathname);
     971        free(fun);
     972}
     973
     974/** Find the function node with the specified handle.
     975 *
     976 * @param tree          The device tree where we look for the device node.
     977 * @param handle        The handle of the function.
     978 * @return              The function node.
     979 */
     980fun_node_t *find_fun_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
     981{
     982        unsigned long key = handle;
     983        link_t *link;
     984       
     985        assert(fibril_rwlock_is_locked(&tree->rwlock));
     986       
     987        link = hash_table_find(&tree->devman_functions, &key);
     988        if (link == NULL)
     989                return NULL;
     990       
     991        return hash_table_get_instance(link, fun_node_t, devman_fun);
     992}
     993
     994/** Find the function node with the specified handle.
     995 *
     996 * @param tree          The device tree where we look for the device node.
     997 * @param handle        The handle of the function.
     998 * @return              The function node.
     999 */
     1000fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle)
     1001{
     1002        fun_node_t *fun = NULL;
     1003       
     1004        fibril_rwlock_read_lock(&tree->rwlock);
     1005        fun = find_fun_node_no_lock(tree, handle);
     1006        fibril_rwlock_read_unlock(&tree->rwlock);
     1007       
     1008        return fun;
     1009}
    8951010
    8961011/** Create and set device's full path in device tree.
     
    9011016 *                      resources etc.).
    9021017 */
    903 static bool set_dev_path(node_t *node, node_t *parent)
    904 {
    905         assert(node->name != NULL);
    906        
    907         size_t pathsize = (str_size(node->name) + 1);
     1018static bool set_fun_path(fun_node_t *fun, fun_node_t *parent)
     1019{
     1020        assert(fun->name != NULL);
     1021       
     1022        size_t pathsize = (str_size(fun->name) + 1);
    9081023        if (parent != NULL)
    9091024                pathsize += str_size(parent->pathname) + 1;
    9101025       
    911         node->pathname = (char *) malloc(pathsize);
    912         if (node->pathname == NULL) {
     1026        fun->pathname = (char *) malloc(pathsize);
     1027        if (fun->pathname == NULL) {
    9131028                printf(NAME ": failed to allocate device path.\n");
    9141029                return false;
     
    9161031       
    9171032        if (parent != NULL) {
    918                 str_cpy(node->pathname, pathsize, parent->pathname);
    919                 str_append(node->pathname, pathsize, "/");
    920                 str_append(node->pathname, pathsize, node->name);
     1033                str_cpy(fun->pathname, pathsize, parent->pathname);
     1034                str_append(fun->pathname, pathsize, "/");
     1035                str_append(fun->pathname, pathsize, fun->name);
    9211036        } else {
    922                 str_cpy(node->pathname, pathsize, node->name);
     1037                str_cpy(fun->pathname, pathsize, fun->name);
    9231038        }
    9241039       
     
    9361051 *                      etc.).
    9371052 */
    938 bool insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name,
    939     node_t *parent)
    940 {
    941         assert(node != NULL);
     1053bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun)
     1054{
     1055        assert(dev != NULL);
    9421056        assert(tree != NULL);
    943         assert(dev_name != NULL);
    9441057        assert(fibril_rwlock_is_write_locked(&tree->rwlock));
    9451058       
    946         node->name = dev_name;
    947         if (!set_dev_path(node, parent)) {
     1059        /* Add the node to the handle-to-node map. */
     1060        dev->handle = ++tree->current_handle;
     1061        unsigned long key = dev->handle;
     1062        hash_table_insert(&tree->devman_devices, &key, &dev->devman_dev);
     1063
     1064        /* Add the node to the list of its parent's children. */
     1065        printf("insert_dev_node: dev=%p, dev->pfun := %p\n", dev, pfun);
     1066        dev->pfun = pfun;
     1067        pfun->child = dev;
     1068       
     1069        return true;
     1070}
     1071
     1072/** Insert new function into device tree.
     1073 *
     1074 * @param tree          The device tree.
     1075 * @param node          The newly added function node.
     1076 * @param dev_name      The name of the newly added function.
     1077 * @param parent        Owning device node.
     1078 *
     1079 * @return              True on success, false otherwise (insufficient resources
     1080 *                      etc.).
     1081 */
     1082bool insert_fun_node(dev_tree_t *tree, fun_node_t *fun, char *fun_name,
     1083    dev_node_t *dev)
     1084{
     1085        fun_node_t *pfun;
     1086       
     1087        assert(fun != NULL);
     1088        assert(tree != NULL);
     1089        assert(fun_name != NULL);
     1090        assert(fibril_rwlock_is_write_locked(&tree->rwlock));
     1091       
     1092        /*
     1093         * The root function is a special case, it does not belong to any
     1094         * device so for the root function dev == NULL.
     1095         */
     1096        pfun = (dev != NULL) ? dev->pfun : NULL;
     1097       
     1098        fun->name = fun_name;
     1099        if (!set_fun_path(fun, pfun)) {
    9481100                return false;
    9491101        }
    9501102       
    9511103        /* Add the node to the handle-to-node map. */
    952         node->handle = ++tree->current_handle;
    953         unsigned long key = node->handle;
    954         hash_table_insert(&tree->devman_devices, &key, &node->devman_link);
     1104        fun->handle = ++tree->current_handle;
     1105        unsigned long key = fun->handle;
     1106        hash_table_insert(&tree->devman_functions, &key, &fun->devman_fun);
    9551107
    9561108        /* Add the node to the list of its parent's children. */
    957         node->parent = parent;
    958         if (parent != NULL)
    959                 list_append(&node->sibling, &parent->children);
     1109        fun->dev = dev;
     1110        if (dev != NULL)
     1111                list_append(&fun->dev_functions, &dev->functions);
    9601112       
    9611113        return true;
    9621114}
    9631115
    964 /** Find device node with a specified path in the device tree.
     1116/** Find function node with a specified path in the device tree.
    9651117 *
    966  * @param path          The path of the device node in the device tree.
     1118 * @param path          The path of the function node in the device tree.
    9671119 * @param tree          The device tree.
    968  * @return              The device node if it is present in the tree, NULL
     1120 * @return              The function node if it is present in the tree, NULL
    9691121 *                      otherwise.
    9701122 */
    971 node_t *find_dev_node_by_path(dev_tree_t *tree, char *path)
     1123fun_node_t *find_fun_node_by_path(dev_tree_t *tree, char *path)
    9721124{
    9731125        fibril_rwlock_read_lock(&tree->rwlock);
    9741126       
    975         node_t *dev = tree->root_node;
     1127        fun_node_t *fun = tree->root_node;
    9761128        /*
    977          * Relative path to the device from its parent (but with '/' at the
     1129         * Relative path to the function from its parent (but with '/' at the
    9781130         * beginning)
    9791131         */
     
    9821134        bool cont = (rel_path[0] == '/');
    9831135       
    984         while (cont && dev != NULL) {
     1136        while (cont && fun != NULL) {
    9851137                next_path_elem  = get_path_elem_end(rel_path + 1);
    9861138                if (next_path_elem[0] == '/') {
     
    9911143                }
    9921144               
    993                 dev = find_node_child(dev, rel_path + 1);
     1145                fun = find_node_child(fun, rel_path + 1);
    9941146               
    9951147                if (cont) {
     
    10021154        fibril_rwlock_read_unlock(&tree->rwlock);
    10031155       
    1004         return dev;
    1005 }
    1006 
    1007 /** Find child device node with a specified name.
     1156        return fun;
     1157}
     1158
     1159/** Find child function node with a specified name.
    10081160 *
    10091161 * Device tree rwlock should be held at least for reading.
    10101162 *
    1011  * @param parent        The parent device node.
    1012  * @param name          The name of the child device node.
    1013  * @return              The child device node.
    1014  */
    1015 node_t *find_node_child(node_t *parent, const char *name)
    1016 {
    1017         node_t *dev;
     1163 * @param parent        The parent function node.
     1164 * @param name          The name of the child function.
     1165 * @return              The child function node.
     1166 */
     1167fun_node_t *find_node_child(fun_node_t *pfun, const char *name)
     1168{
     1169        fun_node_t *fun;
    10181170        link_t *link;
    10191171       
    1020         link = parent->children.next;
    1021        
    1022         while (link != &parent->children) {
    1023                 dev = list_get_instance(link, node_t, sibling);
     1172        link = pfun->child->functions.next;
     1173       
     1174        while (link != &pfun->child->functions) {
     1175                fun = list_get_instance(link, fun_node_t, dev_functions);
    10241176               
    1025                 if (str_cmp(name, dev->name) == 0)
    1026                         return dev;
     1177                if (str_cmp(name, fun->name) == 0)
     1178                        return fun;
    10271179               
    10281180                link = link->next;
     
    11071259}
    11081260
    1109 /** Add the device to the class.
     1261/** Add the device function to the class.
    11101262 *
    11111263 * The device may be added to multiple classes and a class may contain multiple
     
    11201272 *                      with the class.
    11211273 */
    1122 dev_class_info_t *add_device_to_class(node_t *dev, dev_class_t *cl,
     1274dev_class_info_t *add_function_to_class(fun_node_t *fun, dev_class_t *cl,
    11231275    const char *base_dev_name)
    11241276{
    1125         dev_class_info_t *info = create_dev_class_info();
     1277        dev_class_info_t *info;
     1278
     1279        assert(fun != NULL);
     1280        assert(cl != NULL);
     1281
     1282        info = create_dev_class_info();
     1283
    11261284       
    11271285        if (info != NULL) {
    11281286                info->dev_class = cl;
    1129                 info->dev = dev;
     1287                info->fun = fun;
    11301288               
    11311289                /* Add the device to the class. */
     
    11351293               
    11361294                /* Add the class to the device. */
    1137                 list_append(&info->dev_classes, &dev->classes);
     1295                list_append(&info->dev_classes, &fun->classes);
    11381296               
    11391297                /* Create unique name for the device within the class. */
     
    11891347        list_initialize(&class_list->classes);
    11901348        fibril_rwlock_initialize(&class_list->rwlock);
    1191         hash_table_create(&class_list->devmap_devices, DEVICE_BUCKETS, 1,
     1349        hash_table_create(&class_list->devmap_functions, DEVICE_BUCKETS, 1,
    11921350            &devmap_devices_class_ops);
    11931351}
     
    11961354/* Devmap devices */
    11971355
    1198 node_t *find_devmap_tree_device(dev_tree_t *tree, devmap_handle_t devmap_handle)
    1199 {
    1200         node_t *dev = NULL;
     1356fun_node_t *find_devmap_tree_function(dev_tree_t *tree, devmap_handle_t devmap_handle)
     1357{
     1358        fun_node_t *fun = NULL;
    12011359        link_t *link;
    12021360        unsigned long key = (unsigned long) devmap_handle;
    12031361       
    12041362        fibril_rwlock_read_lock(&tree->rwlock);
    1205         link = hash_table_find(&tree->devmap_devices, &key);
     1363        link = hash_table_find(&tree->devmap_functions, &key);
    12061364        if (link != NULL)
    1207                 dev = hash_table_get_instance(link, node_t, devmap_link);
     1365                fun = hash_table_get_instance(link, fun_node_t, devmap_fun);
    12081366        fibril_rwlock_read_unlock(&tree->rwlock);
    12091367       
    1210         return dev;
    1211 }
    1212 
    1213 node_t *find_devmap_class_device(class_list_t *classes,
     1368        return fun;
     1369}
     1370
     1371fun_node_t *find_devmap_class_function(class_list_t *classes,
    12141372    devmap_handle_t devmap_handle)
    12151373{
    1216         node_t *dev = NULL;
     1374        fun_node_t *fun = NULL;
    12171375        dev_class_info_t *cli;
    12181376        link_t *link;
     
    12201378       
    12211379        fibril_rwlock_read_lock(&classes->rwlock);
    1222         link = hash_table_find(&classes->devmap_devices, &key);
     1380        link = hash_table_find(&classes->devmap_functions, &key);
    12231381        if (link != NULL) {
    12241382                cli = hash_table_get_instance(link, dev_class_info_t,
    12251383                    devmap_link);
    1226                 dev = cli->dev;
     1384                fun = cli->fun;
    12271385        }
    12281386        fibril_rwlock_read_unlock(&classes->rwlock);
    12291387       
    1230         return dev;
    1231 }
    1232 
    1233 void class_add_devmap_device(class_list_t *class_list, dev_class_info_t *cli)
     1388        return fun;
     1389}
     1390
     1391void class_add_devmap_function(class_list_t *class_list, dev_class_info_t *cli)
    12341392{
    12351393        unsigned long key = (unsigned long) cli->devmap_handle;
    12361394       
    12371395        fibril_rwlock_write_lock(&class_list->rwlock);
    1238         hash_table_insert(&class_list->devmap_devices, &key, &cli->devmap_link);
     1396        hash_table_insert(&class_list->devmap_functions, &key, &cli->devmap_link);
    12391397        fibril_rwlock_write_unlock(&class_list->rwlock);
    12401398
    1241         assert(find_devmap_class_device(class_list, cli->devmap_handle) != NULL);
    1242 }
    1243 
    1244 void tree_add_devmap_device(dev_tree_t *tree, node_t *node)
    1245 {
    1246         unsigned long key = (unsigned long) node->devmap_handle;
     1399        assert(find_devmap_class_function(class_list, cli->devmap_handle) != NULL);
     1400}
     1401
     1402void tree_add_devmap_function(dev_tree_t *tree, fun_node_t *fun)
     1403{
     1404        unsigned long key = (unsigned long) fun->devmap_handle;
    12471405        fibril_rwlock_write_lock(&tree->rwlock);
    1248         hash_table_insert(&tree->devmap_devices, &key, &node->devmap_link);
     1406        hash_table_insert(&tree->devmap_functions, &key, &fun->devmap_fun);
    12491407        fibril_rwlock_write_unlock(&tree->rwlock);
    12501408}
  • uspace/srv/devman/devman.h

    r6a343bdf r0c968a17  
    5656#define DEVMAP_SEPARATOR '\\'
    5757
    58 struct node;
    59 typedef struct node node_t;
     58struct dev_node;
     59typedef struct dev_node dev_node_t;
     60
     61struct fun_node;
     62typedef struct fun_node fun_node_t;
    6063
    6164typedef enum {
     
    117120} device_state_t;
    118121
    119 /** Representation of a node in the device tree. */
    120 struct node {
     122/** Device node in the device tree. */
     123struct dev_node {
    121124        /** The global unique identifier of the device. */
    122125        devman_handle_t handle;
    123         /** The name of the device specified by its parent. */
    124         char *name;
    125        
    126         /**
    127          * Full path and name of the device in device hierarchi (i. e. in full
    128          * path in device tree).
    129          */
    130         char *pathname;
    131        
    132         /** The node of the parent device. */
    133         node_t *parent;
    134        
    135         /**
    136          * Pointers to previous and next child devices in the linked list of
    137          * parent device's node.
    138          */
    139         link_t sibling;
    140        
    141         /** List of child device nodes. */
    142         link_t children;
    143         /** List of device ids for device-to-driver matching. */
    144         match_id_list_t match_ids;
     126       
     127        /** (Parent) function the device is attached to. */
     128        fun_node_t *pfun;
     129       
     130        /** List of device functions. */
     131        link_t functions;
    145132        /** Driver of this device. */
    146133        driver_t *drv;
    147134        /** The state of the device. */
    148135        device_state_t state;
    149         /**
    150          * Pointer to the previous and next device in the list of devices
    151          * owned by one driver.
    152          */
     136        /** Link to list of devices owned by driver (driver_t.devices) */
    153137        link_t driver_devices;
    154138       
    155         /** The list of device classes to which this device belongs. */
    156         link_t classes;
    157         /** Devmap handle if the device is registered by devmapper. */
    158         devmap_handle_t devmap_handle;
    159        
    160139        /**
    161140         * Used by the hash table of devices indexed by devman device handles.
    162141         */
    163         link_t devman_link;
    164        
    165         /**
    166          * Used by the hash table of devices indexed by devmap device handles.
    167          */
    168         link_t devmap_link;
    169 
     142        link_t devman_dev;
     143       
    170144        /**
    171145         * Whether this device was already passed to the driver.
     
    173147        bool passed_to_driver;
    174148};
     149
     150/** Function node in the device tree. */
     151struct fun_node {
     152        /** The global unique identifier of the function */
     153        devman_handle_t handle;
     154        /** Name of the function, assigned by the device driver */
     155        char *name;
     156       
     157        /** Full path and name of the device in device hierarchy */
     158        char *pathname;
     159       
     160        /** Device which this function belongs to */
     161        dev_node_t *dev;
     162       
     163        /** Link to list of functions in the device (ddf_dev_t.functions) */
     164        link_t dev_functions;
     165       
     166        /** Child device node (if any attached). */
     167        dev_node_t *child;
     168        /** List of device ids for device-to-driver matching. */
     169        match_id_list_t match_ids;
     170       
     171        /** The list of device classes to which this device function belongs. */
     172        link_t classes;
     173        /** Devmap handle if the device function is registered by devmap. */
     174        devmap_handle_t devmap_handle;
     175       
     176        /**
     177         * Used by the hash table of functions indexed by devman device handles.
     178         */
     179        link_t devman_fun;
     180       
     181        /**
     182         * Used by the hash table of functions indexed by devmap device handles.
     183         */
     184        link_t devmap_fun;
     185};
     186
    175187
    176188/** Represents device tree. */
    177189typedef struct dev_tree {
    178190        /** Root device node. */
    179         node_t *root_node;
     191        fun_node_t *root_node;
    180192       
    181193        /**
     
    191203        hash_table_t devman_devices;
    192204       
     205        /** Hash table of all devices indexed by devman handles. */
     206        hash_table_t devman_functions;
     207       
    193208        /**
    194209         * Hash table of devices registered by devmapper, indexed by devmap
    195210         * handles.
    196211         */
    197         hash_table_t devmap_devices;
     212        hash_table_t devmap_functions;
    198213} dev_tree_t;
    199214
     
    227242
    228243/**
    229  * Provides n-to-m mapping between device nodes and classes - each device may
    230  * be register to the arbitrary number of classes and each class may contain
    231  * the arbitrary number of devices.
     244 * Provides n-to-m mapping between function nodes and classes - each function
     245 * can register in an arbitrary number of classes and each class can contain
     246 * an arbitrary number of device functions.
    232247 */
    233248typedef struct dev_class_info {
     
    235250        dev_class_t *dev_class;
    236251        /** The device. */
    237         node_t *dev;
     252        fun_node_t *fun;
    238253       
    239254        /**
     
    249264        link_t dev_classes;
    250265       
    251         /** The name of the device within the class. */
     266        /** The name of the device function within the class. */
    252267        char *dev_name;
    253268        /** The handle of the device by device mapper in the class namespace. */
     
    270285         * indexed by devmap handles.
    271286         */
    272         hash_table_t devmap_devices;
     287        hash_table_t devmap_functions;
    273288       
    274289        /** Fibril mutex for list of classes. */
     
    278293/* Match ids and scores */
    279294
    280 extern int get_match_score(driver_t *, node_t *);
     295extern int get_match_score(driver_t *, dev_node_t *);
    281296
    282297extern bool parse_match_ids(char *, match_id_list_t *);
     
    292307extern int lookup_available_drivers(driver_list_t *, const char *);
    293308
    294 extern driver_t *find_best_match_driver(driver_list_t *, node_t *);
    295 extern bool assign_driver(node_t *, driver_list_t *, dev_tree_t *);
     309extern driver_t *find_best_match_driver(driver_list_t *, dev_node_t *);
     310extern bool assign_driver(dev_node_t *, driver_list_t *, dev_tree_t *);
    296311
    297312extern void add_driver(driver_list_t *, driver_t *);
    298 extern void attach_driver(node_t *, driver_t *);
    299 extern void add_device(int, driver_t *, node_t *, dev_tree_t *);
     313extern void attach_driver(dev_node_t *, driver_t *);
     314extern void add_device(int, driver_t *, dev_node_t *, dev_tree_t *);
    300315extern bool start_driver(driver_t *);
    301316
     
    310325/* Device nodes */
    311326
    312 extern node_t *create_dev_node(void);
    313 extern void delete_dev_node(node_t *node);
    314 extern node_t *find_dev_node_no_lock(dev_tree_t *tree,
     327extern dev_node_t *create_dev_node(void);
     328extern void delete_dev_node(dev_node_t *node);
     329extern dev_node_t *find_dev_node_no_lock(dev_tree_t *tree,
    315330    devman_handle_t handle);
    316 extern node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle);
    317 extern node_t *find_dev_node_by_path(dev_tree_t *, char *);
    318 extern node_t *find_node_child(node_t *, const char *);
     331extern dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle);
     332extern dev_node_t *find_dev_function(dev_node_t *, const char *);
     333
     334extern fun_node_t *create_fun_node(void);
     335extern void delete_fun_node(fun_node_t *);
     336extern fun_node_t *find_fun_node_no_lock(dev_tree_t *tree,
     337    devman_handle_t handle);
     338extern fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle);
     339extern fun_node_t *find_fun_node_by_path(dev_tree_t *, char *);
    319340
    320341/* Device tree */
    321342
    322343extern bool init_device_tree(dev_tree_t *, driver_list_t *);
    323 extern bool create_root_node(dev_tree_t *);
    324 extern bool insert_dev_node(dev_tree_t *, node_t *, char *, node_t *);
     344extern bool create_root_nodes(dev_tree_t *);
     345extern bool insert_dev_node(dev_tree_t *, dev_node_t *, fun_node_t *);
     346extern bool insert_fun_node(dev_tree_t *, fun_node_t *, char *, dev_node_t *);
    325347
    326348/* Device classes */
     
    330352extern size_t get_new_class_dev_idx(dev_class_t *);
    331353extern char *create_dev_name_for_class(dev_class_t *, const char *);
    332 extern dev_class_info_t *add_device_to_class(node_t *, dev_class_t *,
     354extern dev_class_info_t *add_function_to_class(fun_node_t *, dev_class_t *,
    333355    const char *);
    334356
     
    341363/* Devmap devices */
    342364
    343 extern node_t *find_devmap_tree_device(dev_tree_t *, devmap_handle_t);
    344 extern node_t *find_devmap_class_device(class_list_t *, devmap_handle_t);
    345 
    346 extern void class_add_devmap_device(class_list_t *, dev_class_info_t *);
    347 extern void tree_add_devmap_device(dev_tree_t *, node_t *);
     365extern void devmap_register_tree_function(fun_node_t *, dev_tree_t *);
     366
     367extern fun_node_t *find_devmap_tree_function(dev_tree_t *, devmap_handle_t);
     368extern fun_node_t *find_devmap_class_function(class_list_t *, devmap_handle_t);
     369
     370extern void class_add_devmap_function(class_list_t *, dev_class_info_t *);
     371extern void tree_add_devmap_function(dev_tree_t *, fun_node_t *);
    348372
    349373#endif
  • uspace/srv/devman/main.c

    r6a343bdf r0c968a17  
    199199static int assign_driver_fibril(void *arg)
    200200{
    201         node_t *node = (node_t *) arg;
    202         assign_driver(node, &drivers_list, &device_tree);
     201        dev_node_t *dev_node = (dev_node_t *) arg;
     202        assign_driver(dev_node, &drivers_list, &device_tree);
    203203        return EOK;
    204204}
    205205
    206 /** Handle child device registration.
     206/** Handle function registration.
    207207 *
    208208 * Child devices are registered by their parent's device driver.
    209209 */
    210 static void devman_add_child(ipc_callid_t callid, ipc_call_t *call)
    211 {
    212         devman_handle_t parent_handle = IPC_GET_ARG1(*call);
    213         sysarg_t match_count = IPC_GET_ARG2(*call);
     210static void devman_add_function(ipc_callid_t callid, ipc_call_t *call)
     211{
     212        fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call);
     213        devman_handle_t dev_handle = IPC_GET_ARG2(*call);
     214        sysarg_t match_count = IPC_GET_ARG3(*call);
    214215        dev_tree_t *tree = &device_tree;
    215216       
    216217        fibril_rwlock_write_lock(&tree->rwlock);
    217         node_t *parent = find_dev_node_no_lock(&device_tree, parent_handle);
    218        
    219         if (parent == NULL) {
     218
     219        dev_node_t *dev = NULL;
     220        dev_node_t *pdev = find_dev_node_no_lock(&device_tree, dev_handle);
     221       
     222        if (pdev == NULL) {
    220223                fibril_rwlock_write_unlock(&tree->rwlock);
    221224                async_answer_0(callid, ENOENT);
     
    223226        }
    224227       
    225         char *dev_name = NULL;
    226         int rc = async_data_write_accept((void **)&dev_name, true, 0, 0, 0, 0);
     228        if (ftype != fun_inner && ftype != fun_exposed) {
     229                /* Unknown function type */
     230                printf(NAME ": Error, unknown function type provided by driver!\n");
     231
     232                fibril_rwlock_write_unlock(&tree->rwlock);
     233                async_answer_0(callid, EINVAL);
     234                return;
     235        }
     236       
     237        char *fun_name = NULL;
     238        int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0);
    227239        if (rc != EOK) {
    228240                fibril_rwlock_write_unlock(&tree->rwlock);
     
    231243        }
    232244       
    233         node_t *node = create_dev_node();
    234         if (!insert_dev_node(&device_tree, node, dev_name, parent)) {
     245        fun_node_t *fun = create_fun_node();
     246        if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) {
    235247                fibril_rwlock_write_unlock(&tree->rwlock);
    236                 delete_dev_node(node);
     248                delete_fun_node(fun);
    237249                async_answer_0(callid, ENOMEM);
    238250                return;
    239251        }
    240252
     253        if (ftype == fun_inner) {
     254                dev = create_dev_node();
     255                if (dev == NULL) {
     256                        fibril_rwlock_write_unlock(&tree->rwlock);
     257                        delete_fun_node(fun);
     258                        async_answer_0(callid, ENOMEM);
     259                        return;
     260                }
     261
     262                insert_dev_node(tree, dev, fun);
     263        }
     264
    241265        fibril_rwlock_write_unlock(&tree->rwlock);
    242266       
    243         printf(NAME ": devman_add_child %s\n", node->pathname);
    244        
    245         devman_receive_match_ids(match_count, &node->match_ids);
    246 
    247         /*
    248          * Try to find a suitable driver and assign it to the device.  We do
    249          * not want to block the current fibril that is used for processing
    250          * incoming calls: we will launch a separate fibril to handle the
    251          * driver assigning. That is because assign_driver can actually include
    252          * task spawning which could take some time.
    253          */
    254         fid_t assign_fibril = fibril_create(assign_driver_fibril, node);
    255         if (assign_fibril == 0) {
     267        printf(NAME ": devman_add_function %s\n", fun->pathname);
     268       
     269        devman_receive_match_ids(match_count, &fun->match_ids);
     270
     271        if (ftype == fun_inner) {
     272                assert(dev != NULL);
    256273                /*
    257                  * Fallback in case we are out of memory.
    258                  * Probably not needed as we will die soon anyway ;-).
     274                 * Try to find a suitable driver and assign it to the device.  We do
     275                 * not want to block the current fibril that is used for processing
     276                 * incoming calls: we will launch a separate fibril to handle the
     277                 * driver assigning. That is because assign_driver can actually include
     278                 * task spawning which could take some time.
    259279                 */
    260                 (void) assign_driver_fibril(node);
     280                fid_t assign_fibril = fibril_create(assign_driver_fibril, dev);
     281                if (assign_fibril == 0) {
     282                        /*
     283                         * Fallback in case we are out of memory.
     284                         * Probably not needed as we will die soon anyway ;-).
     285                         */
     286                        (void) assign_driver_fibril(fun);
     287                } else {
     288                        fibril_add_ready(assign_fibril);
     289                }
    261290        } else {
    262                 fibril_add_ready(assign_fibril);
    263         }
    264 
     291                devmap_register_tree_function(fun, tree);
     292        }
     293       
    265294        /* Return device handle to parent's driver. */
    266         async_answer_1(callid, EOK, node->handle);
     295        async_answer_1(callid, EOK, fun->handle);
    267296}
    268297
     
    288317         * mapper.
    289318         */
    290         class_add_devmap_device(&class_list, cli);
     319        class_add_devmap_function(&class_list, cli);
    291320       
    292321        free(devmap_pathname);
    293322}
    294323
    295 static void devman_add_device_to_class(ipc_callid_t callid, ipc_call_t *call)
     324static void devman_add_function_to_class(ipc_callid_t callid, ipc_call_t *call)
    296325{
    297326        devman_handle_t handle = IPC_GET_ARG1(*call);
     
    306335        }       
    307336       
    308         node_t *dev = find_dev_node(&device_tree, handle);
    309         if (dev == NULL) {
     337        fun_node_t *fun = find_fun_node(&device_tree, handle);
     338        if (fun == NULL) {
    310339                async_answer_0(callid, ENOENT);
    311340                return;
     
    313342       
    314343        dev_class_t *cl = get_dev_class(&class_list, class_name);
    315         dev_class_info_t *class_info = add_device_to_class(dev, cl, NULL);
     344        dev_class_info_t *class_info = add_function_to_class(fun, cl, NULL);
    316345       
    317346        /* Register the device's class alias by devmapper. */
    318347        devmap_register_class_dev(class_info);
    319348       
    320         printf(NAME ": device '%s' added to class '%s', class name '%s' was "
    321             "asigned to it\n", dev->pathname, class_name, class_info->dev_name);
     349        printf(NAME ": function'%s' added to class '%s', class name '%s' was "
     350            "asigned to it\n", fun->pathname, class_name, class_info->dev_name);
    322351
    323352        async_answer_0(callid, EOK);
     
    372401                        cont = false;
    373402                        continue;
    374                 case DEVMAN_ADD_CHILD_DEVICE:
    375                         devman_add_child(callid, &call);
     403                case DEVMAN_ADD_FUNCTION:
     404                        devman_add_function(callid, &call);
    376405                        break;
    377406                case DEVMAN_ADD_DEVICE_TO_CLASS:
    378                         devman_add_device_to_class(callid, &call);
     407                        devman_add_function_to_class(callid, &call);
    379408                        break;
    380409                default:
     
    387416/** Find handle for the device instance identified by the device's path in the
    388417 * device tree. */
    389 static void devman_device_get_handle(ipc_callid_t iid, ipc_call_t *icall)
     418static void devman_function_get_handle(ipc_callid_t iid, ipc_call_t *icall)
    390419{
    391420        char *pathname;
     
    397426        }
    398427       
    399         node_t * dev = find_dev_node_by_path(&device_tree, pathname);
     428        fun_node_t *fun = find_fun_node_by_path(&device_tree, pathname);
    400429       
    401430        free(pathname);
    402431
    403         if (dev == NULL) {
     432        if (fun == NULL) {
    404433                async_answer_0(iid, ENOENT);
    405434                return;
    406435        }
    407        
    408         async_answer_1(iid, EOK, dev->handle);
     436
     437        async_answer_1(iid, EOK, fun->handle);
    409438}
    410439
     
    426455                        continue;
    427456                case DEVMAN_DEVICE_GET_HANDLE:
    428                         devman_device_get_handle(callid, &call);
     457                        devman_function_get_handle(callid, &call);
    429458                        break;
    430459                default:
     
    438467{
    439468        devman_handle_t handle = IPC_GET_ARG2(*icall);
    440        
    441         node_t *dev = find_dev_node(&device_tree, handle);
    442         if (dev == NULL) {
    443                 printf(NAME ": devman_forward error - no device with handle %" PRIun
    444                     " was found.\n", handle);
     469        devman_handle_t fwd_h;
     470        fun_node_t *fun = NULL;
     471        dev_node_t *dev = NULL;
     472       
     473        fun = find_fun_node(&device_tree, handle);
     474        if (fun == NULL)
     475                dev = find_dev_node(&device_tree, handle);
     476        else
     477                dev = fun->dev;
     478
     479        if (fun == NULL && dev == NULL) {
     480                printf(NAME ": devman_forward error - no device or function with "
     481                    "handle %" PRIun " was found.\n", handle);
    445482                async_answer_0(iid, ENOENT);
    446483                return;
    447484        }
     485
     486        if (fun == NULL && !drv_to_parent) {
     487                printf(NAME ": devman_forward error - cannot connect to "
     488                    "handle %" PRIun ", refers to a device.\n", handle);
     489                async_answer_0(iid, ENOENT);
     490                return;
     491        }
    448492       
    449493        driver_t *driver = NULL;
    450494       
    451495        if (drv_to_parent) {
    452                 if (dev->parent != NULL)
    453                         driver = dev->parent->drv;
     496                /* Connect to parent function of a device (or device function). */
     497                if (dev->pfun->dev != NULL)
     498                        driver = dev->pfun->dev->drv;
     499                fwd_h = dev->pfun->handle;
    454500        } else if (dev->state == DEVICE_USABLE) {
     501                /* Connect to the specified function */
    455502                driver = dev->drv;
    456503                assert(driver != NULL);
     504
     505                fwd_h = handle;
    457506        }
    458507       
     
    478527        }
    479528
    480         printf(NAME ": devman_forward: forward connection to device %s to "
    481             "driver %s.\n", dev->pathname, driver->name);
    482         async_forward_fast(iid, driver->phone, method, dev->handle, 0, IPC_FF_NONE);
     529        if (fun != NULL) {
     530                printf(NAME ": devman_forward: forward connection to function %s to "
     531                    "driver %s.\n", fun->pathname, driver->name);
     532        } else {
     533                printf(NAME ": devman_forward: forward connection to device %s to "
     534                    "driver %s.\n", dev->pfun->pathname, driver->name);
     535        }
     536
     537        async_forward_fast(iid, driver->phone, method, fwd_h, 0, IPC_FF_NONE);
    483538}
    484539
     
    488543{
    489544        devmap_handle_t devmap_handle = IPC_GET_ARG2(*icall);
    490         node_t *dev;
    491 
    492         dev = find_devmap_tree_device(&device_tree, devmap_handle);
    493         if (dev == NULL)
    494                 dev = find_devmap_class_device(&class_list, devmap_handle);
    495        
    496         if (dev == NULL || dev->drv == NULL) {
     545        fun_node_t *fun;
     546        dev_node_t *dev;
     547
     548        fun = find_devmap_tree_function(&device_tree, devmap_handle);
     549        if (fun == NULL)
     550                fun = find_devmap_class_function(&class_list, devmap_handle);
     551       
     552        if (fun == NULL || fun->dev->drv == NULL) {
    497553                async_answer_0(iid, ENOENT);
    498554                return;
    499555        }
     556       
     557        dev = fun->dev;
    500558       
    501559        if (dev->state != DEVICE_USABLE || dev->drv->phone <= 0) {
     
    507565            IPC_FF_NONE);
    508566        printf(NAME ": devman_connection_devmapper: forwarded connection to "
    509             "device %s to driver %s.\n", dev->pathname, dev->drv->name);
     567            "device %s to driver %s.\n", fun->pathname, dev->drv->name);
    510568}
    511569
  • uspace/srv/devman/match.c

    r6a343bdf r0c968a17  
    5757}
    5858
    59 int get_match_score(driver_t *drv, node_t *dev)
     59int get_match_score(driver_t *drv, dev_node_t *dev)
    6060{
    6161        link_t *drv_head = &drv->match_ids.ids;
    62         link_t *dev_head = &dev->match_ids.ids;
     62        link_t *dev_head = &dev->pfun->match_ids.ids;
    6363       
    6464        if (list_empty(drv_head) || list_empty(dev_head))
Note: See TracChangeset for help on using the changeset viewer.