Ignore:
File:
1 edited

Legend:

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

    r3e6a98c5 r7e9e652  
    5454#include <ipc/irc.h>
    5555#include <ipc/services.h>
    56 #include <sysinfo.h>
    57 #include <ns.h>
    5856#include <sys/stat.h>
    59 #include <ipc/irc.h>
    60 #include <ipc/services.h>
    61 #include <sysinfo.h>
     57#include <irc.h>
    6258#include <ns.h>
    6359
     
    6561#include <ddf/log.h>
    6662#include <ops/hw_res.h>
     63#include <ops/pio_window.h>
    6764
    6865#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 CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
     73#define ISA_CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
     74#define EBUS_CHILD_FUN_CONF_PATH "/drv/isa/ebus.dev"
    7475
    7576#define ISA_MAX_HW_RES 5
     
    7778typedef struct {
    7879        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;
    7984        ddf_dev_t *dev;
    8085        ddf_fun_t *fctl;
     86        pio_window_t pio_win;
    8187        list_t functions;
    8288} isa_bus_t;
     
    8591        fibril_mutex_t mutex;
    8692        ddf_fun_t *fnode;
     93        hw_resource_t resources[ISA_MAX_HW_RES];
    8794        hw_resource_list_t hw_resources;
    8895        link_t bus_link;
     
    101108}
    102109
    103 static hw_resource_list_t *isa_get_fun_resources(ddf_fun_t *fnode)
     110static hw_resource_list_t *isa_fun_get_resources(ddf_fun_t *fnode)
    104111{
    105112        isa_fun_t *fun = isa_fun(fnode);
    106         assert(fun != NULL);
     113        assert(fun);
    107114
    108115        return &fun->hw_resources;
    109116}
    110117
    111 static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
     118static bool isa_fun_enable_interrupt(ddf_fun_t *fnode)
    112119{
    113120        /* This is an old ugly way, copied from pci driver */
    114121        assert(fnode);
    115122        isa_fun_t *fun = isa_fun(fnode);
    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;
     123        assert(fun);
    130124
    131125        const hw_resource_list_t *res = &fun->hw_resources;
     
    133127        for (size_t i = 0; i < res->count; ++i) {
    134128                if (res->resources[i].type == INTERRUPT) {
    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);
     129                        int rc = irc_enable_interrupt(
     130                            res->resources[i].res.interrupt.irq);
     131
     132                        if (rc != EOK)
    144133                                return false;
    145                         }
    146                 }
    147         }
    148 
    149         async_hangup(irc_sess);
     134                }
     135        }
     136
    150137        return true;
    151138}
    152139
    153 static int isa_dma_channel_fun_setup(ddf_fun_t *fnode,
    154     unsigned int channel, uint32_t pa, uint16_t size, uint8_t mode)
     140static int isa_fun_setup_dma(ddf_fun_t *fnode,
     141    unsigned int channel, uint32_t pa, uint32_t size, uint8_t mode)
    155142{
    156143        assert(fnode);
    157144        isa_fun_t *fun = isa_fun(fnode);
     145        assert(fun);
    158146        const hw_resource_list_t *res = &fun->hw_resources;
    159147        assert(res);
    160        
    161         const unsigned int ch = channel;
     148
    162149        for (size_t i = 0; i < res->count; ++i) {
     150                /* Check for assigned channel */
    163151                if (((res->resources[i].type == DMA_CHANNEL_16) &&
    164                     (res->resources[i].res.dma_channel.dma16 == ch)) ||
     152                    (res->resources[i].res.dma_channel.dma16 == channel)) ||
    165153                    ((res->resources[i].type == DMA_CHANNEL_8) &&
    166                     (res->resources[i].res.dma_channel.dma8 == ch))) {
    167                         return dma_setup_channel(channel, pa, size, mode);
    168                 }
    169         }
    170        
     154                    (res->resources[i].res.dma_channel.dma8 == channel))) {
     155                        return dma_channel_setup(channel, pa, size, mode);
     156                }
     157        }
     158
    171159        return EINVAL;
    172160}
    173161
     162static 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
    174185static hw_res_ops_t isa_fun_hw_res_ops = {
    175         .get_resource_list = isa_get_fun_resources,
    176         .enable_interrupt = isa_enable_fun_interrupt,
    177         .dma_channel_setup = isa_dma_channel_fun_setup,
     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,
    178190};
    179191
    180 static ddf_dev_ops_t isa_fun_ops;
     192static 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
     201static pio_window_ops_t isa_fun_pio_window_ops = {
     202        .get_pio_window = isa_fun_get_pio_window
     203};
     204
     205static 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};
    181209
    182210static int isa_dev_add(ddf_dev_t *dev);
     
    212240
    213241        fibril_mutex_initialize(&fun->mutex);
     242        fun->hw_resources.resources = fun->resources;
     243
    214244        fun->fnode = fnode;
    215245        return fun;
     
    222252        bool opened = false;
    223253        int fd;
    224         size_t len = 0;
     254        size_t len;
     255        ssize_t r;
    225256
    226257        fd = open(conf_path, O_RDONLY);
     
    246277        }
    247278
    248         if (0 >= read(fd, buf, len)) {
     279        r = read(fd, buf, len);
     280        if (r < 0) {
    249281                ddf_msg(LVL_ERROR, "Unable to read file '%s'.", conf_path);
    250282                goto cleanup;
     
    270302{
    271303        char *line = str;
     304        *next = NULL;
    272305
    273306        if (str == NULL) {
    274                 *next = NULL;
    275307                return NULL;
    276308        }
     
    282314        if (*str != '\0') {
    283315                *next = str + 1;
    284         } else {
    285                 *next = NULL;
    286316        }
    287317
     
    309339
    310340        /* Get the name part of the rest of the 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 
    325 static inline char *skip_spaces(char *line)
     341        str_tok(line, ":", NULL);
     342        return line;
     343}
     344
     345static inline const char *skip_spaces(const char *line)
    326346{
    327347        /* Skip leading spaces. */
     
    332352}
    333353
    334 static void isa_fun_set_irq(isa_fun_t *fun, int irq)
     354static void isa_fun_add_irq(isa_fun_t *fun, int irq)
    335355{
    336356        size_t count = fun->hw_resources.count;
     
    348368}
    349369
    350 static void isa_fun_set_dma(isa_fun_t *fun, int dma)
     370static void isa_fun_add_dma(isa_fun_t *fun, int dma)
    351371{
    352372        size_t count = fun->hw_resources.count;
     
    381401}
    382402
    383 static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len)
     403static void isa_fun_add_io_range(isa_fun_t *fun, size_t addr, size_t len)
    384404{
    385405        size_t count = fun->hw_resources.count;
    386406        hw_resource_t *resources = fun->hw_resources.resources;
     407
     408        isa_bus_t *isa = isa_bus(ddf_fun_get_dev(fun->fnode));
    387409
    388410        if (count < ISA_MAX_HW_RES) {
    389411                resources[count].type = IO_RANGE;
    390412                resources[count].res.io_range.address = addr;
     413                resources[count].res.io_range.address += isa->pio_win.io.base;
    391414                resources[count].res.io_range.size = len;
     415                resources[count].res.io_range.relative = false;
    392416                resources[count].res.io_range.endianness = LITTLE_ENDIAN;
    393417
     
    400424}
    401425
    402 static void fun_parse_irq(isa_fun_t *fun, char *val)
     426static void fun_parse_irq(isa_fun_t *fun, const char *val)
    403427{
    404428        int irq = 0;
     
    409433
    410434        if (val != end)
    411                 isa_fun_set_irq(fun, irq);
    412 }
    413 
    414 static void fun_parse_dma(isa_fun_t *fun, char *val)
    415 {
    416         unsigned int dma = 0;
     435                isa_fun_add_irq(fun, irq);
     436}
     437
     438static void fun_parse_dma(isa_fun_t *fun, const char *val)
     439{
    417440        char *end = NULL;
    418441       
    419442        val = skip_spaces(val);
    420         dma = (unsigned int) strtol(val, &end, 10);
     443        const int dma = strtol(val, &end, 10);
    421444       
    422445        if (val != end)
    423                 isa_fun_set_dma(fun, dma);
    424 }
    425 
    426 static void fun_parse_io_range(isa_fun_t *fun, char *val)
     446                isa_fun_add_dma(fun, dma);
     447}
     448
     449static void fun_parse_io_range(isa_fun_t *fun, const char *val)
    427450{
    428451        size_t addr, len;
     
    441464                return;
    442465
    443         isa_fun_set_io_range(fun, addr, len);
    444 }
    445 
    446 static void get_match_id(char **id, char *val)
    447 {
    448         char *end = val;
     466        isa_fun_add_io_range(fun, addr, len);
     467}
     468
     469static void get_match_id(char **id, const char *val)
     470{
     471        const char *end = val;
    449472
    450473        while (!isspace(*end))
     
    456479}
    457480
    458 static void fun_parse_match_id(isa_fun_t *fun, char *val)
     481static void fun_parse_match_id(isa_fun_t *fun, const char *val)
    459482{
    460483        char *id = NULL;
    461         int score = 0;
    462484        char *end = NULL;
    463         int rc;
    464485
    465486        val = skip_spaces(val);
    466487
    467         score = (int)strtol(val, &end, 10);
     488        int score = (int)strtol(val, &end, 10);
    468489        if (val == end) {
    469490                ddf_msg(LVL_ERROR, "Cannot read match score for function "
     
    483504            "function %s", id, score, ddf_fun_get_name(fun->fnode));
    484505
    485         rc = ddf_fun_add_match_id(fun->fnode, id, score);
     506        int rc = ddf_fun_add_match_id(fun->fnode, id, score);
    486507        if (rc != EOK) {
    487508                ddf_msg(LVL_ERROR, "Failed adding match ID: %s",
     
    492513}
    493514
    494 static bool prop_parse(isa_fun_t *fun, char *line, const char *prop,
    495     void (*read_fn)(isa_fun_t *, char *))
     515static bool prop_parse(isa_fun_t *fun, const char *line, const char *prop,
     516    void (*read_fn)(isa_fun_t *, const char *))
    496517{
    497518        size_t proplen = str_size(prop);
     
    508529}
    509530
    510 static void fun_prop_parse(isa_fun_t *fun, char *line)
     531static void fun_prop_parse(isa_fun_t *fun, const char *line)
    511532{
    512533        /* Skip leading spaces. */
     
    523544}
    524545
    525 static 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 
    531 static void fun_hw_res_free(isa_fun_t *fun)
    532 {
    533         free(fun->hw_resources.resources);
    534         fun->hw_resources.resources = NULL;
    535 }
    536 
    537546static char *isa_fun_read_info(char *fun_conf, isa_bus_t *isa)
    538547{
    539548        char *line;
    540         char *fun_name = NULL;
    541549
    542550        /* Skip empty lines. */
    543         while (true) {
     551        do {
    544552                line = str_get_line(fun_conf, &fun_conf);
    545553
     
    549557                }
    550558
    551                 if (!line_empty(line))
    552                         break;
    553         }
     559        } while (line_empty(line));
    554560
    555561        /* Get device name. */
    556         fun_name = get_device_name(line);
     562        const char *fun_name = get_device_name(line);
    557563        if (fun_name == NULL)
    558564                return NULL;
    559565
    560566        isa_fun_t *fun = isa_fun_create(isa, fun_name);
    561         free(fun_name);
    562567        if (fun == NULL) {
    563568                return NULL;
    564569        }
    565 
    566         /* Allocate buffer for the list of hardware resources of the device. */
    567         fun_hw_res_alloc(fun);
    568570
    569571        /* Get properties of the device (match ids, irq and io range). */
     
    596598}
    597599
    598 static void fun_conf_parse(char *conf, isa_bus_t *isa)
    599 {
     600static 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);
    600619        while (conf != NULL && *conf != '\0') {
    601620                conf = isa_fun_read_info(conf, isa);
    602621        }
    603 }
    604 
    605 static 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         }
     622        free(conf);
    614623}
    615624
    616625static int isa_dev_add(ddf_dev_t *dev)
    617626{
    618         isa_bus_t *isa;
     627        async_sess_t *sess;
     628        int rc;
    619629
    620630        ddf_msg(LVL_DEBUG, "isa_dev_add, device handle = %d",
    621631            (int) ddf_dev_get_handle(dev));
    622632
    623         isa = ddf_dev_data_alloc(dev, sizeof(isa_bus_t));
     633        isa_bus_t *isa = ddf_dev_data_alloc(dev, sizeof(isa_bus_t));
    624634        if (isa == NULL)
    625635                return ENOMEM;
     
    628638        isa->dev = dev;
    629639        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        }       
    630667
    631668        /* Make the bus device more visible. Does not do anything. */
     
    658695{
    659696        isa_bus_t *isa = isa_bus(dev);
    660         int rc;
    661697
    662698        fibril_mutex_lock(&isa->mutex);
     
    666702                    isa_fun_t, bus_link);
    667703
    668                 rc = ddf_fun_offline(fun->fnode);
     704                int rc = ddf_fun_offline(fun->fnode);
    669705                if (rc != EOK) {
    670706                        fibril_mutex_unlock(&isa->mutex);
     
    682718                list_remove(&fun->bus_link);
    683719
    684                 fun_hw_res_free(fun);
    685720                ddf_fun_destroy(fun->fnode);
    686721        }
     
    709744}
    710745
    711 
    712 static void isa_init()
    713 {
     746int main(int argc, char *argv[])
     747{
     748        printf(NAME ": HelenOS ISA bus driver\n");
    714749        ddf_log_init(NAME);
    715         isa_fun_ops.interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops;
    716 }
    717 
    718 int main(int argc, char *argv[])
    719 {
    720         printf(NAME ": HelenOS ISA bus driver\n");
    721         isa_init();
    722750        return ddf_driver_main(&isa_driver);
    723751}
Note: See TracChangeset for help on using the changeset viewer.