Changeset d9cf684a in mainline


Ignore:
Timestamp:
2011-12-22T14:10:31Z (12 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
fe5e9629
Parents:
a438de4
Message:

cherrypick and adopt Intel 8237A DMA controller support from bzr://krabicka.net/orome/helenos/audio/

Location:
uspace
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/isa/Makefile

    ra438de4 rd9cf684a  
    11#
    22# Copyright (c) 2010 Lenka Trochtova
     3# Copyright (c) 2011 Jan Vesely
    34# All rights reserved.
    45#
     
    3334
    3435SOURCES = \
     36        i8237.c \
    3537        isa.c
    3638
  • uspace/drv/bus/isa/isa.c

    ra438de4 rd9cf684a  
    22 * Copyright (c) 2010 Lenka Trochtova
    33 * Copyright (c) 2011 Jiri Svoboda
     4 * Copyright (c) 2011 Jan Vesely
    45 * All rights reserved.
    56 *
     
    5253#include <fcntl.h>
    5354#include <sys/stat.h>
     55#include <ipc/irc.h>
     56#include <ipc/services.h>
     57#include <sysinfo.h>
     58#include <ns.h>
    5459
    5560#include <ddf/driver.h>
     
    6166#include <device/hw_res.h>
    6267
     68#include "i8237.h"
     69
    6370#define NAME "isa"
    6471#define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
     
    7077#define ISA_FUN(fun) ((isa_fun_t *) ((fun)->driver_data))
    7178
    72 #define ISA_MAX_HW_RES 4
     79#define ISA_MAX_HW_RES 5
    7380
    7481typedef struct {
     
    96103static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
    97104{
    98         /* TODO */
    99 
    100         return false;
     105        /* This is an old ugly way, copied from pci driver */
     106        assert(fnode);
     107        isa_fun_t *isa_fun = fnode->driver_data;
     108
     109        sysarg_t apic;
     110        sysarg_t i8259;
     111       
     112        async_sess_t *irc_sess = NULL;
     113       
     114        if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))
     115            || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) {
     116                irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
     117                    SERVICE_IRC, 0, 0);
     118        }
     119       
     120        if (!irc_sess)
     121                return false;
     122       
     123        assert(isa_fun);
     124        const hw_resource_list_t *res = &isa_fun->hw_resources;
     125        assert(res);
     126        for (size_t i = 0; i < res->count; ++i) {
     127                if (res->resources[i].type == INTERRUPT) {
     128                        const int irq = res->resources[i].res.interrupt.irq;
     129                       
     130                        async_exch_t *exch = async_exchange_begin(irc_sess);
     131                        const int rc =
     132                            async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq);
     133                        async_exchange_end(exch);
     134                       
     135                        if (rc != EOK) {
     136                                async_hangup(irc_sess);
     137                                return false;
     138                        }
     139                }
     140        }
     141       
     142        async_hangup(irc_sess);
     143        return true;
     144}
     145
     146static int isa_dma_channel_fun_setup(ddf_fun_t *fnode,
     147    unsigned int channel, uint32_t pa, uint16_t size, uint8_t mode)
     148{
     149        assert(fnode);
     150        isa_fun_t *isa_fun = fnode->driver_data;
     151        const hw_resource_list_t *res = &isa_fun->hw_resources;
     152        assert(res);
     153       
     154        const unsigned int ch = channel;
     155        for (size_t i = 0; i < res->count; ++i) {
     156                if (((res->resources[i].type == DMA_CHANNEL_16) &&
     157                    (res->resources[i].res.dma_channel.dma16 == ch)) ||
     158                    ((res->resources[i].type == DMA_CHANNEL_8) &&
     159                    (res->resources[i].res.dma_channel.dma8 == ch))) {
     160                        return dma_setup_channel(channel, pa, size, mode);
     161                }
     162        }
     163       
     164        return EINVAL;
    101165}
    102166
    103167static hw_res_ops_t isa_fun_hw_res_ops = {
    104         &isa_get_fun_resources,
    105         &isa_enable_fun_interrupt
     168        .get_resource_list = isa_get_fun_resources,
     169        .enable_interrupt = isa_enable_fun_interrupt,
     170        .dma_channel_setup = isa_dma_channel_fun_setup,
    106171};
    107172
     
    274339}
    275340
     341static void isa_fun_set_dma(isa_fun_t *fun, int dma)
     342{
     343        size_t count = fun->hw_resources.count;
     344        hw_resource_t *resources = fun->hw_resources.resources;
     345       
     346        if (count < ISA_MAX_HW_RES) {
     347                if ((dma > 0) && (dma < 4)) {
     348                        resources[count].type = DMA_CHANNEL_8;
     349                        resources[count].res.dma_channel.dma8 = dma;
     350                       
     351                        fun->hw_resources.count++;
     352                        ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma,
     353                            fun->fnode->name);
     354                       
     355                        return;
     356                }
     357
     358                if ((dma > 4) && (dma < 8)) {
     359                        resources[count].type = DMA_CHANNEL_16;
     360                        resources[count].res.dma_channel.dma16 = dma;
     361                       
     362                        fun->hw_resources.count++;
     363                        ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma,
     364                            fun->fnode->name);
     365                       
     366                        return;
     367                }
     368               
     369                ddf_msg(LVL_WARN, "Skipped dma 0x%x for function %s", dma,
     370                    fun->fnode->name);
     371        }
     372}
     373
    276374static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len)
    277375{
     
    303401        if (val != end)
    304402                isa_fun_set_irq(fun, irq);
     403}
     404
     405static void fun_parse_dma(isa_fun_t *fun, char *val)
     406{
     407        unsigned int dma = 0;
     408        char *end = NULL;
     409       
     410        val = skip_spaces(val);
     411        dma = (unsigned int) strtol(val, &end, 10);
     412       
     413        if (val != end)
     414                isa_fun_set_dma(fun, dma);
    305415}
    306416
     
    396506        if (!prop_parse(fun, line, "io_range", &fun_parse_io_range) &&
    397507            !prop_parse(fun, line, "irq", &fun_parse_irq) &&
     508            !prop_parse(fun, line, "dma", &fun_parse_dma) &&
    398509            !prop_parse(fun, line, "match", &fun_parse_match_id)) {
    399510
     
    406517{
    407518        fun->hw_resources.resources =
    408             (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
     519            (hw_resource_t *) malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
    409520}
    410521
     
    590701
    591702
    592 static void isa_init() 
     703static void isa_init()
    593704{
    594705        ddf_log_init(NAME, LVL_ERROR);
  • uspace/drv/bus/isa/isa.dev

    ra438de4 rd9cf684a  
    1818        irq 5
    1919        io_range 300 20
     20
     21sb16:
     22        match 100 isa/sb16
     23        io_range 220 20
     24        io_range 330 2
     25        irq 5
     26        dma 1
     27        dma 5
  • uspace/drv/bus/pci/pciintel/pci.c

    ra438de4 rd9cf684a  
    187187
    188188static hw_res_ops_t pciintel_hw_res_ops = {
    189         &pciintel_get_resources,
    190         &pciintel_enable_interrupt
     189        .get_resource_list = &pciintel_get_resources,
     190        .enable_interrupt = &pciintel_enable_interrupt,
    191191};
    192192
  • uspace/drv/infrastructure/rootpc/rootpc.c

    ra438de4 rd9cf684a  
    109109
    110110static hw_res_ops_t fun_hw_res_ops = {
    111         &rootpc_get_resources,
    112         &rootpc_enable_interrupt
     111        .get_resource_list = &rootpc_get_resources,
     112        .enable_interrupt = &rootpc_enable_interrupt,
    113113};
    114114
  • uspace/lib/c/include/device/hw_res.h

    ra438de4 rd9cf684a  
    4040#include <bool.h>
    4141
     42#define DMA_MODE_ON_DEMAND  0
     43#define DMA_MODE_WRITE      (1 << 2)
     44#define DMA_MODE_READ       (1 << 3)
     45#define DMA_MODE_AUTO       (1 << 4)
     46#define DMA_MODE_DOWN       (1 << 5)
     47#define DMA_MODE_SINGLE     (1 << 6)
     48#define DMA_MODE_BLOCK      (1 << 7)
     49
    4250/** HW resource provider interface */
    4351typedef enum {
    4452        HW_RES_GET_RESOURCE_LIST = 0,
    45         HW_RES_ENABLE_INTERRUPT
     53        HW_RES_ENABLE_INTERRUPT,
     54        HW_RES_DMA_CHANNEL_SETUP,
    4655} hw_res_method_t;
    4756
     
    5059        INTERRUPT,
    5160        IO_RANGE,
    52         MEM_RANGE
     61        MEM_RANGE,
     62        DMA_CHANNEL_8,
     63        DMA_CHANNEL_16,
    5364} hw_res_type_t;
    5465
     
    7788                        int irq;
    7889                } interrupt;
     90               
     91                union {
     92                        unsigned int dma8;
     93                        unsigned int dma16;
     94                } dma_channel;
    7995        } res;
    8096} hw_resource_t;
     
    98114extern bool hw_res_enable_interrupt(async_sess_t *);
    99115
     116extern int hw_res_dma_channel_setup(async_sess_t *, unsigned int, uint32_t,
     117    uint16_t, uint8_t);
     118
    100119#endif
    101120
  • uspace/lib/c/include/device/hw_res_parsed.h

    ra438de4 rd9cf684a  
    7272} irq_list_t;
    7373
     74/** List of ISA DMA channels */
     75typedef struct dma_list {
     76        /** Channel count */
     77        size_t count;
     78
     79        /** Array of channels */
     80        unsigned int *channels;
     81} dma_list_t;
     82
    7483/** List of memory areas */
    7584typedef struct addr_range_list {
     
    91100        /** List of IRQs */
    92101        irq_list_t irqs;
     102       
     103        /** List of DMA channels */
     104        dma_list_t dma_channels;
    93105       
    94106        /** List of memory areas */
     
    113125        free(list->io_ranges.ranges);
    114126        free(list->mem_ranges.ranges);
     127        free(list->dma_channels.channels);
    115128       
    116129        bzero(list, sizeof(hw_res_list_parsed_t));
  • uspace/lib/drv/include/ops/hw_res.h

    ra438de4 rd9cf684a  
    11/*
    2  * Copyright (c) 2010 Lenka Trochtova
     2 * Copyright (c) 2010 Lenka Trochtova
     3 * Copyright (c) 2011 Jan Vesely
    34 * All rights reserved.
    45 *
     
    4243
    4344typedef struct {
    44          hw_resource_list_t *(*get_resource_list)(ddf_fun_t *);
    45          bool (*enable_interrupt)(ddf_fun_t *);
     45        hw_resource_list_t *(*get_resource_list)(ddf_fun_t *);
     46        bool (*enable_interrupt)(ddf_fun_t *);
     47        int (*dma_channel_setup)(ddf_fun_t *, unsigned, uint32_t, uint16_t, uint8_t);
    4648} hw_res_ops_t;
    4749
Note: See TracChangeset for help on using the changeset viewer.