Ignore:
File:
1 edited

Legend:

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

    ref9460b rf278930  
    3737 */
    3838
     39#include <adt/list.h>
    3940#include <assert.h>
    4041#include <stdio.h>
     
    6364#define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
    6465
    65 /** Obtain soft-state pointer from function node pointer */
    66 #define ISA_FUN(fnode) ((isa_fun_t *) ((fnode)->driver_data))
     66/** Obtain soft-state from device node */
     67#define ISA_BUS(dev) ((isa_bus_t *) ((dev)->driver_data))
     68
     69/** Obtain soft-state from function node */
     70#define ISA_FUN(fun) ((isa_fun_t *) ((fun)->driver_data))
    6771
    6872#define ISA_MAX_HW_RES 4
    6973
     74typedef struct {
     75        fibril_mutex_t mutex;
     76        ddf_dev_t *dev;
     77        ddf_fun_t *fctl;
     78        list_t functions;
     79} isa_bus_t;
     80
    7081typedef struct isa_fun {
     82        fibril_mutex_t mutex;
    7183        ddf_fun_t *fnode;
    7284        hw_resource_list_t hw_resources;
     85        link_t bus_link;
    7386} isa_fun_t;
    7487
     
    96109
    97110static int isa_add_device(ddf_dev_t *dev);
     111static int isa_dev_remove(ddf_dev_t *dev);
     112static int isa_fun_online(ddf_fun_t *fun);
     113static int isa_fun_offline(ddf_fun_t *fun);
    98114
    99115/** The isa device driver's standard operations */
    100116static driver_ops_t isa_ops = {
    101         .add_device = &isa_add_device
     117        .add_device = &isa_add_device,
     118        .dev_remove = &isa_dev_remove,
     119        .fun_online = &isa_fun_online,
     120        .fun_offline = &isa_fun_offline
    102121};
    103122
     
    108127};
    109128
    110 static isa_fun_t *isa_fun_create(ddf_dev_t *dev, const char *name)
    111 {
    112         isa_fun_t *fun = calloc(1, sizeof(isa_fun_t));
     129static isa_fun_t *isa_fun_create(isa_bus_t *isa, const char *name)
     130{
     131        ddf_fun_t *fnode = ddf_fun_create(isa->dev, fun_inner, name);
     132        if (fnode == NULL)
     133                return NULL;
     134
     135        isa_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(isa_fun_t));
    113136        if (fun == NULL)
    114137                return NULL;
    115138
    116         ddf_fun_t *fnode = ddf_fun_create(dev, fun_inner, name);
    117         if (fnode == NULL) {
    118                 free(fun);
    119                 return NULL;
    120         }
    121 
     139        fibril_mutex_initialize(&fun->mutex);
    122140        fun->fnode = fnode;
    123         fnode->driver_data = fun;
    124141        return fun;
    125142}
     
    392409}
    393410
    394 static char *isa_fun_read_info(char *fun_conf, ddf_dev_t *dev)
     411static void fun_hw_res_free(isa_fun_t *fun)
     412{
     413        free(fun->hw_resources.resources);
     414        fun->hw_resources.resources = NULL;
     415}
     416
     417static char *isa_fun_read_info(char *fun_conf, isa_bus_t *isa)
    395418{
    396419        char *line;
     
    415438                return NULL;
    416439
    417         isa_fun_t *fun = isa_fun_create(dev, fun_name);
     440        isa_fun_t *fun = isa_fun_create(isa, fun_name);
    418441        if (fun == NULL) {
    419442                free(fun_name);
     
    448471        (void) ddf_fun_bind(fun->fnode);
    449472
     473        list_append(&fun->bus_link, &isa->functions);
     474
    450475        return fun_conf;
    451476}
    452477
    453 static void fun_conf_parse(char *conf, ddf_dev_t *dev)
     478static void fun_conf_parse(char *conf, isa_bus_t *isa)
    454479{
    455480        while (conf != NULL && *conf != '\0') {
    456                 conf = isa_fun_read_info(conf, dev);
    457         }
    458 }
    459 
    460 static void isa_functions_add(ddf_dev_t *dev)
     481                conf = isa_fun_read_info(conf, isa);
     482        }
     483}
     484
     485static void isa_functions_add(isa_bus_t *isa)
    461486{
    462487        char *fun_conf;
     
    464489        fun_conf = fun_conf_read(CHILD_FUN_CONF_PATH);
    465490        if (fun_conf != NULL) {
    466                 fun_conf_parse(fun_conf, dev);
     491                fun_conf_parse(fun_conf, isa);
    467492                free(fun_conf);
    468493        }
     
    471496static int isa_add_device(ddf_dev_t *dev)
    472497{
     498        isa_bus_t *isa;
     499
    473500        ddf_msg(LVL_DEBUG, "isa_add_device, device handle = %d",
    474501            (int) dev->handle);
    475502
     503        isa = ddf_dev_data_alloc(dev, sizeof(isa_bus_t));
     504        if (isa == NULL)
     505                return ENOMEM;
     506
     507        fibril_mutex_initialize(&isa->mutex);
     508        isa->dev = dev;
     509        list_initialize(&isa->functions);
     510
    476511        /* Make the bus device more visible. Does not do anything. */
    477512        ddf_msg(LVL_DEBUG, "Adding a 'ctl' function");
    478513
    479         ddf_fun_t *ctl = ddf_fun_create(dev, fun_exposed, "ctl");
    480         if (ctl == NULL) {
     514        fibril_mutex_lock(&isa->mutex);
     515
     516        isa->fctl = ddf_fun_create(dev, fun_exposed, "ctl");
     517        if (isa->fctl == NULL) {
    481518                ddf_msg(LVL_ERROR, "Failed creating control function.");
    482519                return EXDEV;
    483520        }
    484521
    485         if (ddf_fun_bind(ctl) != EOK) {
     522        if (ddf_fun_bind(isa->fctl) != EOK) {
     523                ddf_fun_destroy(isa->fctl);
    486524                ddf_msg(LVL_ERROR, "Failed binding control function.");
    487525                return EXDEV;
     
    489527
    490528        /* Add functions as specified in the configuration file. */
    491         isa_functions_add(dev);
     529        isa_functions_add(isa);
    492530        ddf_msg(LVL_NOTE, "Finished enumerating legacy functions");
    493531
     532        fibril_mutex_unlock(&isa->mutex);
     533
    494534        return EOK;
    495535}
     536
     537static int isa_dev_remove(ddf_dev_t *dev)
     538{
     539        isa_bus_t *isa = ISA_BUS(dev);
     540        int rc;
     541
     542        fibril_mutex_lock(&isa->mutex);
     543
     544        while (!list_empty(&isa->functions)) {
     545                isa_fun_t *fun = list_get_instance(list_first(&isa->functions),
     546                    isa_fun_t, bus_link);
     547
     548                rc = ddf_fun_offline(fun->fnode);
     549                if (rc != EOK) {
     550                        fibril_mutex_unlock(&isa->mutex);
     551                        ddf_msg(LVL_ERROR, "Failed offlining %s", fun->fnode->name);
     552                        return rc;
     553                }
     554
     555                rc = ddf_fun_unbind(fun->fnode);
     556                if (rc != EOK) {
     557                        fibril_mutex_unlock(&isa->mutex);
     558                        ddf_msg(LVL_ERROR, "Failed unbinding %s", fun->fnode->name);
     559                        return rc;
     560                }
     561
     562                list_remove(&fun->bus_link);
     563
     564                fun_hw_res_free(fun);
     565                ddf_fun_destroy(fun->fnode);
     566        }
     567
     568        if (ddf_fun_unbind(isa->fctl) != EOK) {
     569                fibril_mutex_unlock(&isa->mutex);
     570                ddf_msg(LVL_ERROR, "Failed unbinding control function.");
     571                return EXDEV;
     572        }
     573
     574        fibril_mutex_unlock(&isa->mutex);
     575
     576        return EOK;
     577}
     578
     579static int isa_fun_online(ddf_fun_t *fun)
     580{
     581        ddf_msg(LVL_DEBUG, "isa_fun_online()");
     582        return ddf_fun_online(fun);
     583}
     584
     585static int isa_fun_offline(ddf_fun_t *fun)
     586{
     587        ddf_msg(LVL_DEBUG, "isa_fun_offline()");
     588        return ddf_fun_offline(fun);
     589}
     590
    496591
    497592static void isa_init()
Note: See TracChangeset for help on using the changeset viewer.