Ignore:
File:
1 edited

Legend:

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

    rf278930 re882e3a  
    22 * Copyright (c) 2010 Lenka Trochtova
    33 * Copyright (c) 2011 Jiri Svoboda
     4 * Copyright (c) 2011 Jan Vesely
    45 * All rights reserved.
    56 *
     
    5152#include <dirent.h>
    5253#include <fcntl.h>
     54#include <ipc/irc.h>
     55#include <ipc/services.h>
     56#include <sysinfo.h>
     57#include <ns.h>
    5358#include <sys/stat.h>
     59#include <ipc/irc.h>
     60#include <ipc/services.h>
     61#include <sysinfo.h>
     62#include <ns.h>
    5463
    5564#include <ddf/driver.h>
     
    5766#include <ops/hw_res.h>
    5867
    59 #include <devman.h>
    60 #include <ipc/devman.h>
    6168#include <device/hw_res.h>
     69
     70#include "i8237.h"
    6271
    6372#define NAME "isa"
     
    7079#define ISA_FUN(fun) ((isa_fun_t *) ((fun)->driver_data))
    7180
    72 #define ISA_MAX_HW_RES 4
     81#define ISA_MAX_HW_RES 5
    7382
    7483typedef struct {
     
    96105static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
    97106{
    98         /* TODO */
    99 
    100         return false;
     107        /* This is an old ugly way, copied from pci driver */
     108        assert(fnode);
     109        isa_fun_t *isa_fun = fnode->driver_data;
     110
     111        sysarg_t apic;
     112        sysarg_t i8259;
     113
     114        async_sess_t *irc_sess = NULL;
     115
     116        if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))
     117            || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) {
     118                irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
     119                    SERVICE_IRC, 0, 0);
     120        }
     121
     122        if (!irc_sess)
     123                return false;
     124
     125        assert(isa_fun);
     126        const hw_resource_list_t *res = &isa_fun->hw_resources;
     127        assert(res);
     128        for (size_t i = 0; i < res->count; ++i) {
     129                if (res->resources[i].type == INTERRUPT) {
     130                        const int irq = res->resources[i].res.interrupt.irq;
     131
     132                        async_exch_t *exch = async_exchange_begin(irc_sess);
     133                        const int rc =
     134                            async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq);
     135                        async_exchange_end(exch);
     136
     137                        if (rc != EOK) {
     138                                async_hangup(irc_sess);
     139                                return false;
     140                        }
     141                }
     142        }
     143
     144        async_hangup(irc_sess);
     145        return true;
     146}
     147
     148static int isa_dma_channel_fun_setup(ddf_fun_t *fnode,
     149    unsigned int channel, uint32_t pa, uint16_t size, uint8_t mode)
     150{
     151        assert(fnode);
     152        isa_fun_t *isa_fun = fnode->driver_data;
     153        const hw_resource_list_t *res = &isa_fun->hw_resources;
     154        assert(res);
     155       
     156        const unsigned int ch = channel;
     157        for (size_t i = 0; i < res->count; ++i) {
     158                if (((res->resources[i].type == DMA_CHANNEL_16) &&
     159                    (res->resources[i].res.dma_channel.dma16 == ch)) ||
     160                    ((res->resources[i].type == DMA_CHANNEL_8) &&
     161                    (res->resources[i].res.dma_channel.dma8 == ch))) {
     162                        return dma_setup_channel(channel, pa, size, mode);
     163                }
     164        }
     165       
     166        return EINVAL;
    101167}
    102168
    103169static hw_res_ops_t isa_fun_hw_res_ops = {
    104         &isa_get_fun_resources,
    105         &isa_enable_fun_interrupt
     170        .get_resource_list = isa_get_fun_resources,
     171        .enable_interrupt = isa_enable_fun_interrupt,
     172        .dma_channel_setup = isa_dma_channel_fun_setup,
    106173};
    107174
    108175static ddf_dev_ops_t isa_fun_ops;
    109176
    110 static int isa_add_device(ddf_dev_t *dev);
     177static int isa_dev_add(ddf_dev_t *dev);
    111178static int isa_dev_remove(ddf_dev_t *dev);
    112179static int isa_fun_online(ddf_fun_t *fun);
     
    115182/** The isa device driver's standard operations */
    116183static driver_ops_t isa_ops = {
    117         .add_device = &isa_add_device,
     184        .dev_add = &isa_dev_add,
    118185        .dev_remove = &isa_dev_remove,
    119186        .fun_online = &isa_fun_online,
     
    274341}
    275342
     343static void isa_fun_set_dma(isa_fun_t *fun, int dma)
     344{
     345        size_t count = fun->hw_resources.count;
     346        hw_resource_t *resources = fun->hw_resources.resources;
     347       
     348        if (count < ISA_MAX_HW_RES) {
     349                if ((dma > 0) && (dma < 4)) {
     350                        resources[count].type = DMA_CHANNEL_8;
     351                        resources[count].res.dma_channel.dma8 = dma;
     352                       
     353                        fun->hw_resources.count++;
     354                        ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma,
     355                            fun->fnode->name);
     356                       
     357                        return;
     358                }
     359
     360                if ((dma > 4) && (dma < 8)) {
     361                        resources[count].type = DMA_CHANNEL_16;
     362                        resources[count].res.dma_channel.dma16 = dma;
     363                       
     364                        fun->hw_resources.count++;
     365                        ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma,
     366                            fun->fnode->name);
     367                       
     368                        return;
     369                }
     370               
     371                ddf_msg(LVL_WARN, "Skipped dma 0x%x for function %s", dma,
     372                    fun->fnode->name);
     373        }
     374}
     375
    276376static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len)
    277377{
     
    299399
    300400        val = skip_spaces(val);
    301         irq = (int)strtol(val, &end, 0x10);
     401        irq = (int) strtol(val, &end, 10);
    302402
    303403        if (val != end)
    304404                isa_fun_set_irq(fun, irq);
     405}
     406
     407static void fun_parse_dma(isa_fun_t *fun, char *val)
     408{
     409        unsigned int dma = 0;
     410        char *end = NULL;
     411       
     412        val = skip_spaces(val);
     413        dma = (unsigned int) strtol(val, &end, 10);
     414       
     415        if (val != end)
     416                isa_fun_set_dma(fun, dma);
    305417}
    306418
     
    396508        if (!prop_parse(fun, line, "io_range", &fun_parse_io_range) &&
    397509            !prop_parse(fun, line, "irq", &fun_parse_irq) &&
     510            !prop_parse(fun, line, "dma", &fun_parse_dma) &&
    398511            !prop_parse(fun, line, "match", &fun_parse_match_id)) {
    399512
     
    405518static void fun_hw_res_alloc(isa_fun_t *fun)
    406519{
    407         fun->hw_resources.resources = 
    408             (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
     520        fun->hw_resources.resources =
     521            (hw_resource_t *) malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
    409522}
    410523
     
    494607}
    495608
    496 static int isa_add_device(ddf_dev_t *dev)
     609static int isa_dev_add(ddf_dev_t *dev)
    497610{
    498611        isa_bus_t *isa;
    499612
    500         ddf_msg(LVL_DEBUG, "isa_add_device, device handle = %d",
     613        ddf_msg(LVL_DEBUG, "isa_dev_add, device handle = %d",
    501614            (int) dev->handle);
    502615
     
    590703
    591704
    592 static void isa_init() 
     705static void isa_init()
    593706{
    594707        ddf_log_init(NAME, LVL_ERROR);
Note: See TracChangeset for help on using the changeset viewer.