Statistics
| Branch: | Revision:

root / hw / sparc32_dma.c @ 2507c12a

History | View | Annotate | Download (7.9 kB)

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.h"
29
#include "sparc32_dma.h"
30
#include "sun4m.h"
31
#include "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

    
48
#define DMA_VER 0xa0000000
49
#define DMA_INTR 1
50
#define DMA_INTREN 0x10
51
#define DMA_WRITE_MEM 0x100
52
#define DMA_EN 0x200
53
#define DMA_LOADED 0x04000000
54
#define DMA_DRAIN_FIFO 0x40
55
#define DMA_RESET 0x80
56

    
57
/* XXX SCSI and ethernet should have different read-only bit masks */
58
#define DMA_CSR_RO_MASK 0xfe000007
59

    
60
typedef struct DMAState DMAState;
61

    
62
struct DMAState {
63
    SysBusDevice busdev;
64
    uint32_t dmaregs[DMA_REGS];
65
    qemu_irq irq;
66
    void *iommu;
67
    qemu_irq gpio[2];
68
};
69

    
70
enum {
71
    GPIO_RESET = 0,
72
    GPIO_DMA,
73
};
74

    
75
/* Note: on sparc, the lance 16 bit bus is swapped */
76
void ledma_memory_read(void *opaque, target_phys_addr_t addr,
77
                       uint8_t *buf, int len, int do_bswap)
78
{
79
    DMAState *s = opaque;
80
    int i;
81

    
82
    addr |= s->dmaregs[3];
83
    trace_ledma_memory_read(addr);
84
    if (do_bswap) {
85
        sparc_iommu_memory_read(s->iommu, addr, buf, len);
86
    } else {
87
        addr &= ~1;
88
        len &= ~1;
89
        sparc_iommu_memory_read(s->iommu, addr, buf, len);
90
        for(i = 0; i < len; i += 2) {
91
            bswap16s((uint16_t *)(buf + i));
92
        }
93
    }
94
}
95

    
96
void ledma_memory_write(void *opaque, target_phys_addr_t addr,
97
                        uint8_t *buf, int len, int do_bswap)
98
{
99
    DMAState *s = opaque;
100
    int l, i;
101
    uint16_t tmp_buf[32];
102

    
103
    addr |= s->dmaregs[3];
104
    trace_ledma_memory_write(addr);
105
    if (do_bswap) {
106
        sparc_iommu_memory_write(s->iommu, addr, buf, len);
107
    } else {
108
        addr &= ~1;
109
        len &= ~1;
110
        while (len > 0) {
111
            l = len;
112
            if (l > sizeof(tmp_buf))
113
                l = sizeof(tmp_buf);
114
            for(i = 0; i < l; i += 2) {
115
                tmp_buf[i >> 1] = bswap16(*(uint16_t *)(buf + i));
116
            }
117
            sparc_iommu_memory_write(s->iommu, addr, (uint8_t *)tmp_buf, l);
118
            len -= l;
119
            buf += l;
120
            addr += l;
121
        }
122
    }
123
}
124

    
125
static void dma_set_irq(void *opaque, int irq, int level)
126
{
127
    DMAState *s = opaque;
128
    if (level) {
129
        s->dmaregs[0] |= DMA_INTR;
130
        if (s->dmaregs[0] & DMA_INTREN) {
131
            trace_sparc32_dma_set_irq_raise();
132
            qemu_irq_raise(s->irq);
133
        }
134
    } else {
135
        if (s->dmaregs[0] & DMA_INTR) {
136
            s->dmaregs[0] &= ~DMA_INTR;
137
            if (s->dmaregs[0] & DMA_INTREN) {
138
                trace_sparc32_dma_set_irq_lower();
139
                qemu_irq_lower(s->irq);
140
            }
141
        }
142
    }
143
}
144

    
145
void espdma_memory_read(void *opaque, uint8_t *buf, int len)
146
{
147
    DMAState *s = opaque;
148

    
149
    trace_espdma_memory_read(s->dmaregs[1]);
150
    sparc_iommu_memory_read(s->iommu, s->dmaregs[1], buf, len);
151
    s->dmaregs[1] += len;
152
}
153

    
154
void espdma_memory_write(void *opaque, uint8_t *buf, int len)
155
{
156
    DMAState *s = opaque;
157

    
158
    trace_espdma_memory_write(s->dmaregs[1]);
159
    sparc_iommu_memory_write(s->iommu, s->dmaregs[1], buf, len);
160
    s->dmaregs[1] += len;
161
}
162

    
163
static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr)
164
{
165
    DMAState *s = opaque;
166
    uint32_t saddr;
167

    
168
    saddr = (addr & DMA_MASK) >> 2;
169
    trace_sparc32_dma_mem_readl(addr, s->dmaregs[saddr]);
170
    return s->dmaregs[saddr];
171
}
172

    
173
static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
174
{
175
    DMAState *s = opaque;
176
    uint32_t saddr;
177

    
178
    saddr = (addr & DMA_MASK) >> 2;
179
    trace_sparc32_dma_mem_writel(addr, s->dmaregs[saddr], val);
180
    switch (saddr) {
181
    case 0:
182
        if (val & DMA_INTREN) {
183
            if (s->dmaregs[0] & DMA_INTR) {
184
                trace_sparc32_dma_set_irq_raise();
185
                qemu_irq_raise(s->irq);
186
            }
187
        } else {
188
            if (s->dmaregs[0] & (DMA_INTR | DMA_INTREN)) {
189
                trace_sparc32_dma_set_irq_lower();
190
                qemu_irq_lower(s->irq);
191
            }
192
        }
193
        if (val & DMA_RESET) {
194
            qemu_irq_raise(s->gpio[GPIO_RESET]);
195
            qemu_irq_lower(s->gpio[GPIO_RESET]);
196
        } else if (val & DMA_DRAIN_FIFO) {
197
            val &= ~DMA_DRAIN_FIFO;
198
        } else if (val == 0)
199
            val = DMA_DRAIN_FIFO;
200

    
201
        if (val & DMA_EN && !(s->dmaregs[0] & DMA_EN)) {
202
            trace_sparc32_dma_enable_raise();
203
            qemu_irq_raise(s->gpio[GPIO_DMA]);
204
        } else if (!(val & DMA_EN) && !!(s->dmaregs[0] & DMA_EN)) {
205
            trace_sparc32_dma_enable_lower();
206
            qemu_irq_lower(s->gpio[GPIO_DMA]);
207
        }
208

    
209
        val &= ~DMA_CSR_RO_MASK;
210
        val |= DMA_VER;
211
        s->dmaregs[0] = (s->dmaregs[0] & DMA_CSR_RO_MASK) | val;
212
        break;
213
    case 1:
214
        s->dmaregs[0] |= DMA_LOADED;
215
        /* fall through */
216
    default:
217
        s->dmaregs[saddr] = val;
218
        break;
219
    }
220
}
221

    
222
static CPUReadMemoryFunc * const dma_mem_read[3] = {
223
    NULL,
224
    NULL,
225
    dma_mem_readl,
226
};
227

    
228
static CPUWriteMemoryFunc * const dma_mem_write[3] = {
229
    NULL,
230
    NULL,
231
    dma_mem_writel,
232
};
233

    
234
static void dma_reset(DeviceState *d)
235
{
236
    DMAState *s = container_of(d, DMAState, busdev.qdev);
237

    
238
    memset(s->dmaregs, 0, DMA_SIZE);
239
    s->dmaregs[0] = DMA_VER;
240
}
241

    
242
static const VMStateDescription vmstate_dma = {
243
    .name ="sparc32_dma",
244
    .version_id = 2,
245
    .minimum_version_id = 2,
246
    .minimum_version_id_old = 2,
247
    .fields      = (VMStateField []) {
248
        VMSTATE_UINT32_ARRAY(dmaregs, DMAState, DMA_REGS),
249
        VMSTATE_END_OF_LIST()
250
    }
251
};
252

    
253
static int sparc32_dma_init1(SysBusDevice *dev)
254
{
255
    DMAState *s = FROM_SYSBUS(DMAState, dev);
256
    int dma_io_memory;
257

    
258
    sysbus_init_irq(dev, &s->irq);
259

    
260
    dma_io_memory = cpu_register_io_memory(dma_mem_read, dma_mem_write, s,
261
                                           DEVICE_NATIVE_ENDIAN);
262
    sysbus_init_mmio(dev, DMA_SIZE, dma_io_memory);
263

    
264
    qdev_init_gpio_in(&dev->qdev, dma_set_irq, 1);
265
    qdev_init_gpio_out(&dev->qdev, s->gpio, 2);
266

    
267
    return 0;
268
}
269

    
270
static SysBusDeviceInfo sparc32_dma_info = {
271
    .init = sparc32_dma_init1,
272
    .qdev.name  = "sparc32_dma",
273
    .qdev.size  = sizeof(DMAState),
274
    .qdev.vmsd  = &vmstate_dma,
275
    .qdev.reset = dma_reset,
276
    .qdev.props = (Property[]) {
277
        DEFINE_PROP_PTR("iommu_opaque", DMAState, iommu),
278
        DEFINE_PROP_END_OF_LIST(),
279
    }
280
};
281

    
282
static void sparc32_dma_register_devices(void)
283
{
284
    sysbus_register_withprop(&sparc32_dma_info);
285
}
286

    
287
device_init(sparc32_dma_register_devices)