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 "hw/hw.h"
  29#include "hw/sparc/sparc32_dma.h"
  30#include "hw/sparc/sun4m.h"
  31#include "hw/sysbus.h"
  32#include "trace.h"
  33
  34/*
  35 * This is the DMA controller part of chip STP2000 (Master I/O), also
  36 * produced as NCR89C100. See
  37 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
  38 * and
  39 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/DMA2.txt
  40 */
  41
  42#define DMA_REGS 4
  43#define DMA_SIZE (4 * sizeof(uint32_t))
  44/* We need the mask, because one instance of the device is not page
  45   aligned (ledma, start address 0x0010) */
  46#define DMA_MASK (DMA_SIZE - 1)
  47/* OBP says 0x20 bytes for ledma, the extras are aliased to espdma */
  48#define DMA_ETH_SIZE (8 * sizeof(uint32_t))
  49#define DMA_MAX_REG_OFFSET (2 * DMA_SIZE - 1)
  50
  51#define DMA_VER 0xa0000000
  52#define DMA_INTR 1
  53#define DMA_INTREN 0x10
  54#define DMA_WRITE_MEM 0x100
  55#define DMA_EN 0x200
  56#define DMA_LOADED 0x04000000
  57#define DMA_DRAIN_FIFO 0x40
  58#define DMA_RESET 0x80
  59
  60/* XXX SCSI and ethernet should have different read-only bit masks */
  61#define DMA_CSR_RO_MASK 0xfe000007
  62
  63typedef struct DMAState DMAState;
  64
  65struct DMAState {
  66    SysBusDevice busdev;
  67    MemoryRegion iomem;
  68    uint32_t dmaregs[DMA_REGS];
  69    qemu_irq irq;
  70    void *iommu;
  71    qemu_irq gpio[2];
  72    uint32_t is_ledma;
  73};
  74
  75enum {
  76    GPIO_RESET = 0,
  77    GPIO_DMA,
  78};
  79
  80/* Note: on sparc, the lance 16 bit bus is swapped */
  81void ledma_memory_read(void *opaque, hwaddr addr,
  82                       uint8_t *buf, int len, int do_bswap)
  83{
  84    DMAState *s = opaque;
  85    int i;
  86
  87    addr |= s->dmaregs[3];
  88    trace_ledma_memory_read(addr);
  89    if (do_bswap) {
  90        sparc_iommu_memory_read(s->iommu, addr, buf, len);
  91    } else {
  92        addr &= ~1;
  93        len &= ~1;
  94        sparc_iommu_memory_read(s->iommu, addr, buf, len);
  95        for(i = 0; i < len; i += 2) {
  96            bswap16s((uint16_t *)(buf + i));
  97        }
  98    }
  99}
 100
 101void ledma_memory_write(void *opaque, hwaddr addr,
 102                        uint8_t *buf, int len, int do_bswap)
 103{
 104    DMAState *s = opaque;
 105    int l, i;
 106    uint16_t tmp_buf[32];
 107
 108    addr |= s->dmaregs[3];
 109    trace_ledma_memory_write(addr);
 110    if (do_bswap) {
 111        sparc_iommu_memory_write(s->iommu, addr, buf, len);
 112    } else {
 113        addr &= ~1;
 114        len &= ~1;
 115        while (len > 0) {
 116            l = len;
 117            if (l > sizeof(tmp_buf))
 118                l = sizeof(tmp_buf);
 119            for(i = 0; i < l; i += 2) {
 120                tmp_buf[i >> 1] = bswap16(*(uint16_t *)(buf + i));
 121            }
 122            sparc_iommu_memory_write(s->iommu, addr, (uint8_t *)tmp_buf, l);
 123            len -= l;
 124            buf += l;
 125            addr += l;
 126        }
 127    }
 128}
 129
 130static void dma_set_irq(void *opaque, int irq, int level)
 131{
 132    DMAState *s = opaque;
 133    if (level) {
 134        s->dmaregs[0] |= DMA_INTR;
 135        if (s->dmaregs[0] & DMA_INTREN) {
 136            trace_sparc32_dma_set_irq_raise();
 137            qemu_irq_raise(s->irq);
 138        }
 139    } else {
 140        if (s->dmaregs[0] & DMA_INTR) {
 141            s->dmaregs[0] &= ~DMA_INTR;
 142            if (s->dmaregs[0] & DMA_INTREN) {
 143                trace_sparc32_dma_set_irq_lower();
 144                qemu_irq_lower(s->irq);
 145            }
 146        }
 147    }
 148}
 149
 150void espdma_memory_read(void *opaque, uint8_t *buf, int len)
 151{
 152    DMAState *s = opaque;
 153
 154    trace_espdma_memory_read(s->dmaregs[1]);
 155    sparc_iommu_memory_read(s->iommu, s->dmaregs[1], buf, len);
 156    s->dmaregs[1] += len;
 157}
 158
 159void espdma_memory_write(void *opaque, uint8_t *buf, int len)
 160{
 161    DMAState *s = opaque;
 162
 163    trace_espdma_memory_write(s->dmaregs[1]);
 164    sparc_iommu_memory_write(s->iommu, s->dmaregs[1], buf, len);
 165    s->dmaregs[1] += len;
 166}
 167
 168static uint64_t dma_mem_read(void *opaque, hwaddr addr,
 169                             unsigned size)
 170{
 171    DMAState *s = opaque;
 172    uint32_t saddr;
 173
 174    if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) {
 175        /* aliased to espdma, but we can't get there from here */
 176        /* buggy driver if using undocumented behavior, just return 0 */
 177        trace_sparc32_dma_mem_readl(addr, 0);
 178        return 0;
 179    }
 180    saddr = (addr & DMA_MASK) >> 2;
 181    trace_sparc32_dma_mem_readl(addr, s->dmaregs[saddr]);
 182    return s->dmaregs[saddr];
 183}
 184
 185static void dma_mem_write(void *opaque, hwaddr addr,
 186                          uint64_t val, unsigned size)
 187{
 188    DMAState *s = opaque;
 189    uint32_t saddr;
 190
 191    if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) {
 192        /* aliased to espdma, but we can't get there from here */
 193        trace_sparc32_dma_mem_writel(addr, 0, val);
 194        return;
 195    }
 196    saddr = (addr & DMA_MASK) >> 2;
 197    trace_sparc32_dma_mem_writel(addr, s->dmaregs[saddr], val);
 198    switch (saddr) {
 199    case 0:
 200        if (val & DMA_INTREN) {
 201            if (s->dmaregs[0] & DMA_INTR) {
 202                trace_sparc32_dma_set_irq_raise();
 203                qemu_irq_raise(s->irq);
 204            }
 205        } else {
 206            if (s->dmaregs[0] & (DMA_INTR | DMA_INTREN)) {
 207                trace_sparc32_dma_set_irq_lower();
 208                qemu_irq_lower(s->irq);
 209            }
 210        }
 211        if (val & DMA_RESET) {
 212            qemu_irq_raise(s->gpio[GPIO_RESET]);
 213            qemu_irq_lower(s->gpio[GPIO_RESET]);
 214        } else if (val & DMA_DRAIN_FIFO) {
 215            val &= ~DMA_DRAIN_FIFO;
 216        } else if (val == 0)
 217            val = DMA_DRAIN_FIFO;
 218
 219        if (val & DMA_EN && !(s->dmaregs[0] & DMA_EN)) {
 220            trace_sparc32_dma_enable_raise();
 221            qemu_irq_raise(s->gpio[GPIO_DMA]);
 222        } else if (!(val & DMA_EN) && !!(s->dmaregs[0] & DMA_EN)) {
 223            trace_sparc32_dma_enable_lower();
 224            qemu_irq_lower(s->gpio[GPIO_DMA]);
 225        }
 226
 227        val &= ~DMA_CSR_RO_MASK;
 228        val |= DMA_VER;
 229        s->dmaregs[0] = (s->dmaregs[0] & DMA_CSR_RO_MASK) | val;
 230        break;
 231    case 1:
 232        s->dmaregs[0] |= DMA_LOADED;
 233        /* fall through */
 234    default:
 235        s->dmaregs[saddr] = val;
 236        break;
 237    }
 238}
 239
 240static const MemoryRegionOps dma_mem_ops = {
 241    .read = dma_mem_read,
 242    .write = dma_mem_write,
 243    .endianness = DEVICE_NATIVE_ENDIAN,
 244    .valid = {
 245        .min_access_size = 4,
 246        .max_access_size = 4,
 247    },
 248};
 249
 250static void dma_reset(DeviceState *d)
 251{
 252    DMAState *s = container_of(d, DMAState, busdev.qdev);
 253
 254    memset(s->dmaregs, 0, DMA_SIZE);
 255    s->dmaregs[0] = DMA_VER;
 256}
 257
 258static const VMStateDescription vmstate_dma = {
 259    .name ="sparc32_dma",
 260    .version_id = 2,
 261    .minimum_version_id = 2,
 262    .minimum_version_id_old = 2,
 263    .fields      = (VMStateField []) {
 264        VMSTATE_UINT32_ARRAY(dmaregs, DMAState, DMA_REGS),
 265        VMSTATE_END_OF_LIST()
 266    }
 267};
 268
 269static int sparc32_dma_init1(SysBusDevice *dev)
 270{
 271    DMAState *s = FROM_SYSBUS(DMAState, dev);
 272    int reg_size;
 273
 274    sysbus_init_irq(dev, &s->irq);
 275
 276    reg_size = s->is_ledma ? DMA_ETH_SIZE : DMA_SIZE;
 277    memory_region_init_io(&s->iomem, &dma_mem_ops, s, "dma", reg_size);
 278    sysbus_init_mmio(dev, &s->iomem);
 279
 280    qdev_init_gpio_in(&dev->qdev, dma_set_irq, 1);
 281    qdev_init_gpio_out(&dev->qdev, s->gpio, 2);
 282
 283    return 0;
 284}
 285
 286static Property sparc32_dma_properties[] = {
 287    DEFINE_PROP_PTR("iommu_opaque", DMAState, iommu),
 288    DEFINE_PROP_UINT32("is_ledma", DMAState, is_ledma, 0),
 289    DEFINE_PROP_END_OF_LIST(),
 290};
 291
 292static void sparc32_dma_class_init(ObjectClass *klass, void *data)
 293{
 294    DeviceClass *dc = DEVICE_CLASS(klass);
 295    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 296
 297    k->init = sparc32_dma_init1;
 298    dc->reset = dma_reset;
 299    dc->vmsd = &vmstate_dma;
 300    dc->props = sparc32_dma_properties;
 301}
 302
 303static const TypeInfo sparc32_dma_info = {
 304    .name          = "sparc32_dma",
 305    .parent        = TYPE_SYS_BUS_DEVICE,
 306    .instance_size = sizeof(DMAState),
 307    .class_init    = sparc32_dma_class_init,
 308};
 309
 310static void sparc32_dma_register_types(void)
 311{
 312    type_register_static(&sparc32_dma_info);
 313}
 314
 315type_init(sparc32_dma_register_types)
 316