Changeset f278930 in mainline for uspace/drv/bus/isa/isa.c


Ignore:
Timestamp:
2011-09-03T12:02:08Z (13 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7fff38c1
Parents:
f480d7e
Message:

ISA bridge remove support.

File:
1 edited

Legend:

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

    rf480d7e 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);
    98112static int isa_fun_online(ddf_fun_t *fun);
    99113static int isa_fun_offline(ddf_fun_t *fun);
     
    102116static driver_ops_t isa_ops = {
    103117        .add_device = &isa_add_device,
     118        .dev_remove = &isa_dev_remove,
    104119        .fun_online = &isa_fun_online,
    105120        .fun_offline = &isa_fun_offline
     
    112127};
    113128
    114 static isa_fun_t *isa_fun_create(ddf_dev_t *dev, const char *name)
    115 {
    116         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));
    117136        if (fun == NULL)
    118137                return NULL;
    119138
    120         ddf_fun_t *fnode = ddf_fun_create(dev, fun_inner, name);
    121         if (fnode == NULL) {
    122                 free(fun);
    123                 return NULL;
    124         }
    125 
     139        fibril_mutex_initialize(&fun->mutex);
    126140        fun->fnode = fnode;
    127         fnode->driver_data = fun;
    128141        return fun;
    129142}
     
    396409}
    397410
    398 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)
    399418{
    400419        char *line;
     
    419438                return NULL;
    420439
    421         isa_fun_t *fun = isa_fun_create(dev, fun_name);
     440        isa_fun_t *fun = isa_fun_create(isa, fun_name);
    422441        if (fun == NULL) {
    423442                free(fun_name);
     
    452471        (void) ddf_fun_bind(fun->fnode);
    453472
     473        list_append(&fun->bus_link, &isa->functions);
     474
    454475        return fun_conf;
    455476}
    456477
    457 static void fun_conf_parse(char *conf, ddf_dev_t *dev)
     478static void fun_conf_parse(char *conf, isa_bus_t *isa)
    458479{
    459480        while (conf != NULL && *conf != '\0') {
    460                 conf = isa_fun_read_info(conf, dev);
    461         }
    462 }
    463 
    464 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)
    465486{
    466487        char *fun_conf;
     
    468489        fun_conf = fun_conf_read(CHILD_FUN_CONF_PATH);
    469490        if (fun_conf != NULL) {
    470                 fun_conf_parse(fun_conf, dev);
     491                fun_conf_parse(fun_conf, isa);
    471492                free(fun_conf);
    472493        }
     
    475496static int isa_add_device(ddf_dev_t *dev)
    476497{
     498        isa_bus_t *isa;
     499
    477500        ddf_msg(LVL_DEBUG, "isa_add_device, device handle = %d",
    478501            (int) dev->handle);
    479502
     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
    480511        /* Make the bus device more visible. Does not do anything. */
    481512        ddf_msg(LVL_DEBUG, "Adding a 'ctl' function");
    482513
    483         ddf_fun_t *ctl = ddf_fun_create(dev, fun_exposed, "ctl");
    484         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) {
    485518                ddf_msg(LVL_ERROR, "Failed creating control function.");
    486519                return EXDEV;
    487520        }
    488521
    489         if (ddf_fun_bind(ctl) != EOK) {
     522        if (ddf_fun_bind(isa->fctl) != EOK) {
     523                ddf_fun_destroy(isa->fctl);
    490524                ddf_msg(LVL_ERROR, "Failed binding control function.");
    491525                return EXDEV;
     
    493527
    494528        /* Add functions as specified in the configuration file. */
    495         isa_functions_add(dev);
     529        isa_functions_add(isa);
    496530        ddf_msg(LVL_NOTE, "Finished enumerating legacy functions");
     531
     532        fibril_mutex_unlock(&isa->mutex);
     533
     534        return EOK;
     535}
     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);
    497575
    498576        return EOK;
Note: See TracChangeset for help on using the changeset viewer.