qemu/hw/dma/sparc32_dma.c
<<
>>
Prefs
   1/*
   2 * QEMU Sparc32 DMA controller emulation
   3 *
   4 * Copyright (c) 2006 Fabrice Bellard
   5 *
   6 * Modifications:
   7 *  2010-Feb-14 Artyom Tarasenko : reworked irq generation
   8 *
   9 * Permission is hereby granted, free of charge, to any person obtaining a copy
  10 * of this software and associated documentation files (the "Software"), to deal
  11 * in the Software without restriction, including without limitation the rights
  12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13 * copies of the Software, and to permit persons to whom the Software is
  14 * furnished to do so, subject to the following conditions:
  15 *
  16 * The above copyright notice and this permission notice shall be included in
  17 * all copies or substantial portions of the Software.
  18 *
  19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25 * THE SOFTWARE.
  26 */
  27
  28#include "qemu/osdep.h"
  29#include "hw/hw.h"
  30#include "hw/sparc/sparc32_dma.h"
  31#include "hw/sparc/sun4m.h"
  32#include "hw/sysbus.h"
  33#include "trace.h"
  34
  35/*
  36 * This is the DMA controller part of chip STP2000 (Master I/O), also
  37 * produced as NCR89C100. See
  38 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
  39 * and
  40 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/DMA2.txt
  41 */
  42
  43#define DMA_REGS 4
  44#define DMA_SIZE (4 * sizeof(uint32_t))
  45/* We need the mask, because one instance of the device is not page
  46   aligned (ledma, start address 0x0010) */
  47#define DMA_MASK (DMA_SIZE - 1)
  48/* OBP says 0x20 bytes for ledma, the extras are aliased to espdma */
  49#define DMA_ETH_SIZE (8 * sizeof(uint32_t))
  50#define DMA_MAX_REG_OFFSET (2 * DMA_SIZE - 1)
  51
  52#define DMA_VER 0xa0000000
  53#define DMA_INTR 1
  54#define DMA_INTREN 0x10
  55#define DMA_WRITE_MEM 0x100
  56#define DMA_EN 0x200
  57#define DMA_LOADED 0x04000000
  58#define DMA_DRAIN_FIFO 0x40
  59#define DMA_RESET 0x80
  60
  61/* XXX SCSI and ethernet should have different read-only bit masks */
  62#define DMA_CSR_RO_MASK 0xfe000007
  63
  64#define TYPE_SPARC32_DMA "sparc32_dma"
  65#define SPARC32_DMA(obj) OBJECT_CHECK(DMAState, (obj), TYPE_SPARC32_DMA)
  66
  67typedef struct DMAState DMAState;
  68
  69struct DMAState {
  70    SysBusDevice parent_obj;
  71
  72    MemoryRegion iomem;
  73    uint32_t dmaregs[DMA_REGS];
  74    qemu_irq irq;
  75    void *iommu;
  76    qemu_irq gpio[2];
  77    uint32_t is_ledma;
  78};
  79
  80enum {
  81    GPIO_RESET = 0,
  82    GPIO_DMA,
  83};
  84
  85/* Note: on sparc, the lance 16 bit bus is swapped */
  86void ledma_memory_read(void *opaque, hwaddr addr,
  87                       uint8_t *buf, int len, int do_bswap)
  88{
  89    DMAState *s = opaque;
  90    int i;
  91
  92    addr |= s->dmaregs[3];
  93    trace_ledma_memory_read(addr);
  94    if (do_bswap) {
  95        sparc_iommu_memory_read(s->iommu, addr, buf, len);
  96    } else {
  97        addr &= ~1;
  98        len &= ~1;
  99        sparc_iommu_memory_read(s->iommu, addr, buf, len);
 100        for(i = 0; i < len; i += 2) {
 101            bswap16s((uint16_t *)(buf + i));
 102        }
 103    }
 104}
 105
 106void ledma_memory_write(void *opaque, hwaddr addr,
 107                        uint8_t *buf, int len, int do_bswap)
 108{
 109    DMAState *s = opaque;
 110    int l, i;
 111    uint16_t tmp_buf[32];
 112
 113    addr |= s->dmaregs[3];
 114    trace_ledma_memory_write(addr);
 115    if (do_bswap) {
 116        sparc_iommu_memory_write(s->iommu, addr, buf, len);
 117    } else {
 118        addr &= ~1;
 119        len &= ~1;
 120        while (len > 0) {
 121            l = len;
 122            if (l > sizeof(tmp_buf))
 123                l = sizeof(tmp_buf);
 124            for(i = 0; i < l; i += 2) {
 125                tmp_buf[i >> 1] = bswap16(*(uint16_t *)(buf + i));
 126            }
 127            sparc_iommu_memory_write(s->iommu, addr, (uint8_t *)tmp_buf, l);
 128            len -= l;
 129            buf += l;
 130            addr += l;
 131        }
 132    }
 133}
 134
 135static void dma_set_irq(void *opaque, int irq, int level)
 136{
 137    DMAState *s = opaque;
 138    if (level) {
 139        s->dmaregs[0] |= DMA_INTR;
 140        if (s->dmaregs[0] & DMA_INTREN) {
 141            trace_sparc32_dma_set_irq_raise();
 142            qemu_irq_raise(s->irq);
 143        }
 144    } else {
 145        if (s->dmaregs[0] & DMA_INTR) {
 146            s->dmaregs[0] &= ~DMA_INTR;
 147            if (s->dmaregs[0] & DMA_INTREN) {
 148                trace_sparc32_dma_set_irq_lower();
 149                qemu_irq_lower(s->irq);
 150            }
 151        }
 152    }
 153}
 154
 155void espdma_memory_read(void *opaque, uint8_t *buf, int len)
 156{
 157    DMAState *s = opaque;
 158
 159    trace_espdma_memory_read(s->dmaregs[1]);
 160    sparc_iommu_memory_read(s->iommu, s->dmaregs[1], buf, len);
 161    s->dmaregs[1] += len;
 162}
 163
 164void espdma_memory_write(void *opaque, uint8_t *buf, int len)
 165{
 166    DMAState *s = opaque;
 167
 168    trace_espdma_memory_write(s->dmaregs[1]);
 169    sparc_iommu_memory_write(s->iommu, s->dmaregs[1], buf, len);
 170    s->dmaregs[1] += len;
 171}
 172
 173static uint64_t dma_mem_read(void *opaque, hwaddr addr,
 174                             unsigned size)
 175{
 176    DMAState *s = opaque;
 177    uint32_t saddr;
 178
 179    if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) {
 180        /* aliased to espdma, but we can't get there from here */
 181        /* buggy driver if using undocumented behavior, just return 0 */
 182        trace_sparc32_dma_mem_readl(addr, 0);
 183        return 0;
 184    }
 185    saddr = (addr & DMA_MASK) >> 2;
 186    trace_sparc32_dma_mem_readl(addr, s->dmaregs[saddr]);
 187    return s->dmaregs[saddr];
 188}
 189
 190static void dma_mem_write(void *opaque, hwaddr addr,
 191                          uint64_t val, unsigned size)
 192{
 193    DMAState *s = opaque;
 194    uint32_t saddr;
 195
 196    if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) {
 197        /* aliased to espdma, but we can't get there from here */
 198        trace_sparc32_dma_mem_writel(addr, 0, val);
 199        return;
 200    }
 201    saddr = (addr & DMA_MASK) >> 2;
 202    trace_sparc32_dma_mem_writel(addr, s->dmaregs[saddr], val);
 203    switch (saddr) {
 204    case 0:
 205        if (val & DMA_INTREN) {
 206            if (s->dmaregs[0] & DMA_INTR) {
 207                trace_sparc32_dma_set_irq_raise();
 208                qemu_irq_raise(s->irq);
 209            }
 210        } else {
 211            if (s->dmaregs[0] & (DMA_INTR | DMA_INTREN)) {
 212                trace_sparc32_dma_set_irq_lower();
 213                qemu_irq_lower(s->irq);
 214            }
 215        }
 216        if (val & DMA_RESET) {
 217            qemu_irq_raise(s->gpio[GPIO_RESET]);
 218            qemu_irq_lower(s->gpio[GPIO_RESET]);
 219        } else if (val & DMA_DRAIN_FIFO) {
 220            val &= ~DMA_DRAIN_FIFO;
 221        } else if (val == 0)
 222            val = DMA_DRAIN_FIFO;
 223
 224        if (val & DMA_EN && !(s->dmaregs[0] & DMA_EN)) {
 225            trace_sparc32_dma_enable_raise();
 226            qemu_irq_raise(s->gpio[GPIO_DMA]);
 227        } else if (!(val & DMA_EN) && !!(s->dmaregs[0] & DMA_EN)) {
 228            trace_sparc32_dma_enable_lower();
 229            qemu_irq_lower(s->gpio[GPIO_DMA]);
 230        }
 231
 232        val &= ~DMA_CSR_RO_MASK;
 233        val |= DMA_VER;
 234        s->dmaregs[0] = (s->dmaregs[0] & DMA_CSR_RO_MASK) | val;
 235        break;
 236    case 1:
 237        s->dmaregs[0] |= DMA_LOADED;
 238        /* fall through */
 239    default:
 240        s->dmaregs[saddr] = val;
 241        break;
 242    }
 243}
 244
 245static const MemoryRegionOps dma_mem_ops = {
 246    .read = dma_mem_read,
 247    .write = dma_mem_write,
 248    .endianness = DEVICE_NATIVE_ENDIAN,
 249    .valid = {
 250        .min_access_size = 4,
 251        .max_access_size = 4,
 252    },
 253};
 254
 255static void dma_reset(DeviceState *d)
 256{
 257    DMAState *s = SPARC32_DMA(d);
 258
 259    memset(s->dmaregs, 0, DMA_SIZE);
 260    s->dmaregs[0] = DMA_VER;
 261}
 262
 263static const VMStateDescription vmstate_dma = {
 264    .name ="sparc32_dma",
 265    .version_id = 2,
 266    .minimum_version_id = 2,
 267    .fields = (VMStateField[]) {
 268        VMSTATE_UINT32_ARRAY(dmaregs, DMAState, DMA_REGS),
 269        VMSTATE_END_OF_LIST()
 270    }
 271};
 272
 273static int sparc32_dma_init1(SysBusDevice *sbd)
 274{
 275    DeviceState *dev = DEVICE(sbd);
 276    DMAState *s = SPARC32_DMA(dev);
 277    int reg_size;
 278
 279    sysbus_init_irq(sbd, &s->irq);
 280
 281    reg_size = s->is_ledma ? DMA_ETH_SIZE : DMA_SIZE;
 282    memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s,
 283                          "dma", reg_size);
 284    sysbus_init_mmio(sbd, &s->iomem);
 285
 286    qdev_init_gpio_in(dev, dma_set_irq, 1);
 287    qdev_init_gpio_out(dev, s->gpio, 2);
 288
 289    return 0;
 290}
 291
 292static Property sparc32_dma_properties[] = {
 293    DEFINE_PROP_PTR("iommu_opaque", DMAState, iommu),
 294    DEFINE_PROP_UINT32("is_ledma", DMAState, is_ledma, 0),
 295    DEFINE_PROP_END_OF_LIST(),
 296};
 297
 298static void sparc32_dma_class_init(ObjectClass *klass, void *data)
 299{
 300    DeviceClass *dc = DEVICE_CLASS(klass);
 301    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 302
 303    k->init = sparc32_dma_init1;
 304    dc->reset = dma_reset;
 305    dc->vmsd = &vmstate_dma;
 306    dc->props = sparc32_dma_properties;
 307    /* Reason: pointer property "iommu_opaque" */
 308    dc->user_creatable = false;
 309}
 310
 311static const TypeInfo sparc32_dma_info = {
 312    .name          = TYPE_SPARC32_DMA,
 313    .parent        = TYPE_SYS_BUS_DEVICE,
 314    .instance_size = sizeof(DMAState),
 315    .class_init    = sparc32_dma_class_init,
 316};
 317
 318static void sparc32_dma_register_types(void)
 319{
 320    type_register_static(&sparc32_dma_info);
 321}
 322
 323type_init(sparc32_dma_register_types)
 324