Ignore:
File:
1 edited

Legend:

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

    r7e9e652 r3e6a98c5  
    5454#include <ipc/irc.h>
    5555#include <ipc/services.h>
     56#include <sysinfo.h>
     57#include <ns.h>
    5658#include <sys/stat.h>
    57 #include <irc.h>
     59#include <ipc/irc.h>
     60#include <ipc/services.h>
     61#include <sysinfo.h>
    5862#include <ns.h>
    5963
     
    6165#include <ddf/log.h>
    6266#include <ops/hw_res.h>
    63 #include <ops/pio_window.h>
    6467
    6568#include <device/hw_res.h>
    66 #include <device/pio_window.h>
    67 
    68 #include <pci_dev_iface.h>
    6969
    7070#include "i8237.h"
    7171
    7272#define NAME "isa"
    73 #define ISA_CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
    74 #define EBUS_CHILD_FUN_CONF_PATH "/drv/isa/ebus.dev"
     73#define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
    7574
    7675#define ISA_MAX_HW_RES 5
     
    7877typedef struct {
    7978        fibril_mutex_t mutex;
    80         uint16_t pci_vendor_id;
    81         uint16_t pci_device_id;
    82         uint8_t pci_class;
    83         uint8_t pci_subclass;
    8479        ddf_dev_t *dev;
    8580        ddf_fun_t *fctl;
    86         pio_window_t pio_win;
    8781        list_t functions;
    8882} isa_bus_t;
     
    9185        fibril_mutex_t mutex;
    9286        ddf_fun_t *fnode;
    93         hw_resource_t resources[ISA_MAX_HW_RES];
    9487        hw_resource_list_t hw_resources;
    9588        link_t bus_link;
     
    108101}
    109102
    110 static hw_resource_list_t *isa_fun_get_resources(ddf_fun_t *fnode)
     103static hw_resource_list_t *isa_get_fun_resources(ddf_fun_t *fnode)
    111104{
    112105        isa_fun_t *fun = isa_fun(fnode);
    113         assert(fun);
     106        assert(fun != NULL);
    114107
    115108        return &fun->hw_resources;
    116109}
    117110
    118 static bool isa_fun_enable_interrupt(ddf_fun_t *fnode)
     111static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
    119112{
    120113        /* This is an old ugly way, copied from pci driver */
    121114        assert(fnode);
    122115        isa_fun_t *fun = isa_fun(fnode);
    123         assert(fun);
     116
     117        sysarg_t apic;
     118        sysarg_t i8259;
     119
     120        async_sess_t *irc_sess = NULL;
     121
     122        if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))
     123            || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) {
     124                irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
     125                    SERVICE_IRC, 0, 0);
     126        }
     127
     128        if (!irc_sess)
     129                return false;
    124130
    125131        const hw_resource_list_t *res = &fun->hw_resources;
     
    127133        for (size_t i = 0; i < res->count; ++i) {
    128134                if (res->resources[i].type == INTERRUPT) {
    129                         int rc = irc_enable_interrupt(
    130                             res->resources[i].res.interrupt.irq);
    131 
    132                         if (rc != EOK)
     135                        const int irq = res->resources[i].res.interrupt.irq;
     136
     137                        async_exch_t *exch = async_exchange_begin(irc_sess);
     138                        const int rc =
     139                            async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq);
     140                        async_exchange_end(exch);
     141
     142                        if (rc != EOK) {
     143                                async_hangup(irc_sess);
    133144                                return false;
     145                        }
    134146                }
    135147        }
    136148
     149        async_hangup(irc_sess);
    137150        return true;
    138151}
    139152
    140 static int isa_fun_setup_dma(ddf_fun_t *fnode,
    141     unsigned int channel, uint32_t pa, uint32_t size, uint8_t mode)
     153static int isa_dma_channel_fun_setup(ddf_fun_t *fnode,
     154    unsigned int channel, uint32_t pa, uint16_t size, uint8_t mode)
    142155{
    143156        assert(fnode);
    144157        isa_fun_t *fun = isa_fun(fnode);
    145         assert(fun);
    146158        const hw_resource_list_t *res = &fun->hw_resources;
    147159        assert(res);
    148 
     160       
     161        const unsigned int ch = channel;
    149162        for (size_t i = 0; i < res->count; ++i) {
    150                 /* Check for assigned channel */
    151163                if (((res->resources[i].type == DMA_CHANNEL_16) &&
    152                     (res->resources[i].res.dma_channel.dma16 == channel)) ||
     164                    (res->resources[i].res.dma_channel.dma16 == ch)) ||
    153165                    ((res->resources[i].type == DMA_CHANNEL_8) &&
    154                     (res->resources[i].res.dma_channel.dma8 == channel))) {
    155                         return dma_channel_setup(channel, pa, size, mode);
     166                    (res->resources[i].res.dma_channel.dma8 == ch))) {
     167                        return dma_setup_channel(channel, pa, size, mode);
    156168                }
    157169        }
    158 
     170       
    159171        return EINVAL;
    160172}
    161173
    162 static int isa_fun_remain_dma(ddf_fun_t *fnode,
    163     unsigned channel, size_t *size)
    164 {
    165         assert(size);
    166         assert(fnode);
    167         isa_fun_t *fun = isa_fun(fnode);
    168         assert(fun);
    169         const hw_resource_list_t *res = &fun->hw_resources;
    170         assert(res);
    171 
    172         for (size_t i = 0; i < res->count; ++i) {
    173                 /* Check for assigned channel */
    174                 if (((res->resources[i].type == DMA_CHANNEL_16) &&
    175                     (res->resources[i].res.dma_channel.dma16 == channel)) ||
    176                     ((res->resources[i].type == DMA_CHANNEL_8) &&
    177                     (res->resources[i].res.dma_channel.dma8 == channel))) {
    178                         return dma_channel_remain(channel, size);
    179                 }
    180         }
    181 
    182         return EINVAL;
    183 }
    184 
    185174static hw_res_ops_t isa_fun_hw_res_ops = {
    186         .get_resource_list = isa_fun_get_resources,
    187         .enable_interrupt = isa_fun_enable_interrupt,
    188         .dma_channel_setup = isa_fun_setup_dma,
    189         .dma_channel_remain = isa_fun_remain_dma,
     175        .get_resource_list = isa_get_fun_resources,
     176        .enable_interrupt = isa_enable_fun_interrupt,
     177        .dma_channel_setup = isa_dma_channel_fun_setup,
    190178};
    191179
    192 static pio_window_t *isa_fun_get_pio_window(ddf_fun_t *fnode)
    193 {
    194         ddf_dev_t *dev = ddf_fun_get_dev(fnode);
    195         isa_bus_t *isa = isa_bus(dev);
    196         assert(isa);
    197 
    198         return &isa->pio_win;
    199 }
    200 
    201 static pio_window_ops_t isa_fun_pio_window_ops = {
    202         .get_pio_window = isa_fun_get_pio_window
    203 };
    204 
    205 static ddf_dev_ops_t isa_fun_ops= {
    206         .interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops,
    207         .interfaces[PIO_WINDOW_DEV_IFACE] = &isa_fun_pio_window_ops,
    208 };
     180static ddf_dev_ops_t isa_fun_ops;
    209181
    210182static int isa_dev_add(ddf_dev_t *dev);
     
    240212
    241213        fibril_mutex_initialize(&fun->mutex);
    242         fun->hw_resources.resources = fun->resources;
    243 
    244214        fun->fnode = fnode;
    245215        return fun;
     
    252222        bool opened = false;
    253223        int fd;
    254         size_t len;
    255         ssize_t r;
     224        size_t len = 0;
    256225
    257226        fd = open(conf_path, O_RDONLY);
     
    277246        }
    278247
    279         r = read(fd, buf, len);
    280         if (r < 0) {
     248        if (0 >= read(fd, buf, len)) {
    281249                ddf_msg(LVL_ERROR, "Unable to read file '%s'.", conf_path);
    282250                goto cleanup;
     
    302270{
    303271        char *line = str;
    304         *next = NULL;
    305272
    306273        if (str == NULL) {
     274                *next = NULL;
    307275                return NULL;
    308276        }
     
    314282        if (*str != '\0') {
    315283                *next = str + 1;
     284        } else {
     285                *next = NULL;
    316286        }
    317287
     
    339309
    340310        /* Get the name part of the rest of the line. */
    341         str_tok(line, ":", NULL);
    342         return line;
    343 }
    344 
    345 static inline const char *skip_spaces(const char *line)
     311        strtok(line, ":");
     312
     313        /* Allocate output buffer. */
     314        size_t size = str_size(line) + 1;
     315        char *name = malloc(size);
     316
     317        if (name != NULL) {
     318                /* Copy the result to the output buffer. */
     319                str_cpy(name, size, line);
     320        }
     321
     322        return name;
     323}
     324
     325static inline char *skip_spaces(char *line)
    346326{
    347327        /* Skip leading spaces. */
     
    352332}
    353333
    354 static void isa_fun_add_irq(isa_fun_t *fun, int irq)
     334static void isa_fun_set_irq(isa_fun_t *fun, int irq)
    355335{
    356336        size_t count = fun->hw_resources.count;
     
    368348}
    369349
    370 static void isa_fun_add_dma(isa_fun_t *fun, int dma)
     350static void isa_fun_set_dma(isa_fun_t *fun, int dma)
    371351{
    372352        size_t count = fun->hw_resources.count;
     
    401381}
    402382
    403 static void isa_fun_add_io_range(isa_fun_t *fun, size_t addr, size_t len)
     383static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len)
    404384{
    405385        size_t count = fun->hw_resources.count;
    406386        hw_resource_t *resources = fun->hw_resources.resources;
    407 
    408         isa_bus_t *isa = isa_bus(ddf_fun_get_dev(fun->fnode));
    409387
    410388        if (count < ISA_MAX_HW_RES) {
    411389                resources[count].type = IO_RANGE;
    412390                resources[count].res.io_range.address = addr;
    413                 resources[count].res.io_range.address += isa->pio_win.io.base;
    414391                resources[count].res.io_range.size = len;
    415                 resources[count].res.io_range.relative = false;
    416392                resources[count].res.io_range.endianness = LITTLE_ENDIAN;
    417393
     
    424400}
    425401
    426 static void fun_parse_irq(isa_fun_t *fun, const char *val)
     402static void fun_parse_irq(isa_fun_t *fun, char *val)
    427403{
    428404        int irq = 0;
     
    433409
    434410        if (val != end)
    435                 isa_fun_add_irq(fun, irq);
    436 }
    437 
    438 static void fun_parse_dma(isa_fun_t *fun, const char *val)
    439 {
     411                isa_fun_set_irq(fun, irq);
     412}
     413
     414static void fun_parse_dma(isa_fun_t *fun, char *val)
     415{
     416        unsigned int dma = 0;
    440417        char *end = NULL;
    441418       
    442419        val = skip_spaces(val);
    443         const int dma = strtol(val, &end, 10);
     420        dma = (unsigned int) strtol(val, &end, 10);
    444421       
    445422        if (val != end)
    446                 isa_fun_add_dma(fun, dma);
    447 }
    448 
    449 static void fun_parse_io_range(isa_fun_t *fun, const char *val)
     423                isa_fun_set_dma(fun, dma);
     424}
     425
     426static void fun_parse_io_range(isa_fun_t *fun, char *val)
    450427{
    451428        size_t addr, len;
     
    464441                return;
    465442
    466         isa_fun_add_io_range(fun, addr, len);
    467 }
    468 
    469 static void get_match_id(char **id, const char *val)
    470 {
    471         const char *end = val;
     443        isa_fun_set_io_range(fun, addr, len);
     444}
     445
     446static void get_match_id(char **id, char *val)
     447{
     448        char *end = val;
    472449
    473450        while (!isspace(*end))
     
    479456}
    480457
    481 static void fun_parse_match_id(isa_fun_t *fun, const char *val)
     458static void fun_parse_match_id(isa_fun_t *fun, char *val)
    482459{
    483460        char *id = NULL;
     461        int score = 0;
    484462        char *end = NULL;
     463        int rc;
    485464
    486465        val = skip_spaces(val);
    487466
    488         int score = (int)strtol(val, &end, 10);
     467        score = (int)strtol(val, &end, 10);
    489468        if (val == end) {
    490469                ddf_msg(LVL_ERROR, "Cannot read match score for function "
     
    504483            "function %s", id, score, ddf_fun_get_name(fun->fnode));
    505484
    506         int rc = ddf_fun_add_match_id(fun->fnode, id, score);
     485        rc = ddf_fun_add_match_id(fun->fnode, id, score);
    507486        if (rc != EOK) {
    508487                ddf_msg(LVL_ERROR, "Failed adding match ID: %s",
     
    513492}
    514493
    515 static bool prop_parse(isa_fun_t *fun, const char *line, const char *prop,
    516     void (*read_fn)(isa_fun_t *, const char *))
     494static bool prop_parse(isa_fun_t *fun, char *line, const char *prop,
     495    void (*read_fn)(isa_fun_t *, char *))
    517496{
    518497        size_t proplen = str_size(prop);
     
    529508}
    530509
    531 static void fun_prop_parse(isa_fun_t *fun, const char *line)
     510static void fun_prop_parse(isa_fun_t *fun, char *line)
    532511{
    533512        /* Skip leading spaces. */
     
    544523}
    545524
     525static void fun_hw_res_alloc(isa_fun_t *fun)
     526{
     527        fun->hw_resources.resources =
     528            (hw_resource_t *) malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
     529}
     530
     531static void fun_hw_res_free(isa_fun_t *fun)
     532{
     533        free(fun->hw_resources.resources);
     534        fun->hw_resources.resources = NULL;
     535}
     536
    546537static char *isa_fun_read_info(char *fun_conf, isa_bus_t *isa)
    547538{
    548539        char *line;
     540        char *fun_name = NULL;
    549541
    550542        /* Skip empty lines. */
    551         do {
     543        while (true) {
    552544                line = str_get_line(fun_conf, &fun_conf);
    553545
     
    557549                }
    558550
    559         } while (line_empty(line));
     551                if (!line_empty(line))
     552                        break;
     553        }
    560554
    561555        /* Get device name. */
    562         const char *fun_name = get_device_name(line);
     556        fun_name = get_device_name(line);
    563557        if (fun_name == NULL)
    564558                return NULL;
    565559
    566560        isa_fun_t *fun = isa_fun_create(isa, fun_name);
     561        free(fun_name);
    567562        if (fun == NULL) {
    568563                return NULL;
    569564        }
     565
     566        /* Allocate buffer for the list of hardware resources of the device. */
     567        fun_hw_res_alloc(fun);
    570568
    571569        /* Get properties of the device (match ids, irq and io range). */
     
    598596}
    599597
    600 static void isa_functions_add(isa_bus_t *isa)
    601 {
    602 #define BASE_CLASS_BRIDGE       0x06
    603 #define SUB_CLASS_BRIDGE_ISA    0x01
    604         bool isa_bridge = ((isa->pci_class == BASE_CLASS_BRIDGE) &&
    605             (isa->pci_subclass == SUB_CLASS_BRIDGE_ISA));
    606 
    607 #define VENDOR_ID_SUN   0x108e
    608 #define DEVICE_ID_EBUS  0x1000
    609         bool ebus = ((isa->pci_vendor_id == VENDOR_ID_SUN) &&
    610             (isa->pci_device_id == DEVICE_ID_EBUS));
    611 
    612         const char *conf_path = NULL;
    613         if (isa_bridge)
    614                 conf_path = ISA_CHILD_FUN_CONF_PATH;
    615         else if (ebus)
    616                 conf_path = EBUS_CHILD_FUN_CONF_PATH;
    617 
    618         char *conf = fun_conf_read(conf_path);
     598static void fun_conf_parse(char *conf, isa_bus_t *isa)
     599{
    619600        while (conf != NULL && *conf != '\0') {
    620601                conf = isa_fun_read_info(conf, isa);
    621602        }
    622         free(conf);
     603}
     604
     605static void isa_functions_add(isa_bus_t *isa)
     606{
     607        char *fun_conf;
     608
     609        fun_conf = fun_conf_read(CHILD_FUN_CONF_PATH);
     610        if (fun_conf != NULL) {
     611                fun_conf_parse(fun_conf, isa);
     612                free(fun_conf);
     613        }
    623614}
    624615
    625616static int isa_dev_add(ddf_dev_t *dev)
    626617{
    627         async_sess_t *sess;
    628         int rc;
     618        isa_bus_t *isa;
    629619
    630620        ddf_msg(LVL_DEBUG, "isa_dev_add, device handle = %d",
    631621            (int) ddf_dev_get_handle(dev));
    632622
    633         isa_bus_t *isa = ddf_dev_data_alloc(dev, sizeof(isa_bus_t));
     623        isa = ddf_dev_data_alloc(dev, sizeof(isa_bus_t));
    634624        if (isa == NULL)
    635625                return ENOMEM;
     
    638628        isa->dev = dev;
    639629        list_initialize(&isa->functions);
    640 
    641         sess = ddf_dev_parent_sess_create(dev);
    642         if (sess == NULL) {
    643                 ddf_msg(LVL_ERROR, "isa_dev_add failed to connect to the "
    644                     "parent driver.");
    645                 return ENOENT;
    646         }
    647 
    648         rc = pci_config_space_read_16(sess, PCI_VENDOR_ID, &isa->pci_vendor_id);
    649         if (rc != EOK)
    650                 return rc;
    651         rc = pci_config_space_read_16(sess, PCI_DEVICE_ID, &isa->pci_device_id);
    652         if (rc != EOK)
    653                 return rc;
    654         rc = pci_config_space_read_8(sess, PCI_BASE_CLASS, &isa->pci_class);
    655         if (rc != EOK)
    656                 return rc;
    657         rc = pci_config_space_read_8(sess, PCI_SUB_CLASS, &isa->pci_subclass);
    658         if (rc != EOK)
    659                 return rc;
    660        
    661         rc = pio_window_get(sess, &isa->pio_win);
    662         if (rc != EOK) {
    663                 ddf_msg(LVL_ERROR, "isa_dev_add failed to get PIO window "
    664                     "for the device.");
    665                 return rc;
    666         }       
    667630
    668631        /* Make the bus device more visible. Does not do anything. */
     
    695658{
    696659        isa_bus_t *isa = isa_bus(dev);
     660        int rc;
    697661
    698662        fibril_mutex_lock(&isa->mutex);
     
    702666                    isa_fun_t, bus_link);
    703667
    704                 int rc = ddf_fun_offline(fun->fnode);
     668                rc = ddf_fun_offline(fun->fnode);
    705669                if (rc != EOK) {
    706670                        fibril_mutex_unlock(&isa->mutex);
     
    718682                list_remove(&fun->bus_link);
    719683
     684                fun_hw_res_free(fun);
    720685                ddf_fun_destroy(fun->fnode);
    721686        }
     
    744709}
    745710
     711
     712static void isa_init()
     713{
     714        ddf_log_init(NAME);
     715        isa_fun_ops.interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops;
     716}
     717
    746718int main(int argc, char *argv[])
    747719{
    748720        printf(NAME ": HelenOS ISA bus driver\n");
    749         ddf_log_init(NAME);
     721        isa_init();
    750722        return ddf_driver_main(&isa_driver);
    751723}
Note: See TracChangeset for help on using the changeset viewer.