Statistics
| Branch: | Revision:

root / hw / sparc32_dma.c @ 5dcb6b91

History | View | Annotate | Download (7.4 kB)

1
/*
2
 * QEMU Sparc32 DMA controller emulation
3
 *
4
 * Copyright (c) 2006 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "vl.h"
25

    
26
/* debug DMA */
27
//#define DEBUG_DMA
28

    
29
/*
30
 * This is the DMA controller part of chip STP2000 (Master I/O), also
31
 * produced as NCR89C100. See
32
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
33
 * and
34
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/DMA2.txt
35
 */
36

    
37
#ifdef DEBUG_DMA
38
#define DPRINTF(fmt, args...) \
39
do { printf("DMA: " fmt , ##args); } while (0)
40
#else
41
#define DPRINTF(fmt, args...)
42
#endif
43

    
44
#define DMA_REGS 8
45
#define DMA_MAXADDR (DMA_REGS * 4 - 1)
46

    
47
#define DMA_VER 0xa0000000
48
#define DMA_INTR 1
49
#define DMA_INTREN 0x10
50
#define DMA_WRITE_MEM 0x100
51
#define DMA_LOADED 0x04000000
52
#define DMA_RESET 0x80
53

    
54
typedef struct DMAState DMAState;
55

    
56
struct DMAState {
57
    uint32_t dmaregs[DMA_REGS];
58
    qemu_irq espirq, leirq;
59
    void *iommu, *esp_opaque, *lance_opaque;
60
    qemu_irq *pic;
61
};
62

    
63
/* Note: on sparc, the lance 16 bit bus is swapped */
64
void ledma_memory_read(void *opaque, target_phys_addr_t addr, 
65
                       uint8_t *buf, int len, int do_bswap)
66
{
67
    DMAState *s = opaque;
68
    int i;
69

    
70
    DPRINTF("DMA write, direction: %c, addr 0x%8.8x\n",
71
            s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
72
    addr |= s->dmaregs[7];
73
    if (do_bswap) {
74
        sparc_iommu_memory_read(s->iommu, addr, buf, len);
75
    } else {
76
        addr &= ~1;
77
        len &= ~1;
78
        sparc_iommu_memory_read(s->iommu, addr, buf, len);
79
        for(i = 0; i < len; i += 2) {
80
            bswap16s((uint16_t *)(buf + i));
81
        }
82
    }
83
}
84

    
85
void ledma_memory_write(void *opaque, target_phys_addr_t addr, 
86
                        uint8_t *buf, int len, int do_bswap)
87
{
88
    DMAState *s = opaque;
89
    int l, i;
90
    uint16_t tmp_buf[32];
91

    
92
    DPRINTF("DMA read, direction: %c, addr 0x%8.8x\n",
93
            s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
94
    addr |= s->dmaregs[7];
95
    if (do_bswap) {
96
        sparc_iommu_memory_write(s->iommu, addr, buf, len);
97
    } else {
98
        addr &= ~1;
99
        len &= ~1;
100
        while (len > 0) {
101
            l = len;
102
            if (l > sizeof(tmp_buf))
103
                l = sizeof(tmp_buf);
104
            for(i = 0; i < l; i += 2) {
105
                tmp_buf[i >> 1] = bswap16(*(uint16_t *)(buf + i));
106
            }
107
            sparc_iommu_memory_write(s->iommu, addr, (uint8_t *)tmp_buf, l);
108
            len -= l;
109
            buf += l;
110
            addr += l;
111
        }
112
    }
113
}
114

    
115
void espdma_raise_irq(void *opaque)
116
{
117
    DMAState *s = opaque;
118

    
119
    DPRINTF("Raise ESP IRQ\n");
120
    s->dmaregs[0] |= DMA_INTR;
121
    qemu_irq_raise(s->espirq);
122
}
123

    
124
void espdma_clear_irq(void *opaque)
125
{
126
    DMAState *s = opaque;
127

    
128
    s->dmaregs[0] &= ~DMA_INTR;
129
    DPRINTF("Lower ESP IRQ\n");
130
    qemu_irq_lower(s->espirq);
131
}
132

    
133
void espdma_memory_read(void *opaque, uint8_t *buf, int len)
134
{
135
    DMAState *s = opaque;
136

    
137
    DPRINTF("DMA read, direction: %c, addr 0x%8.8x\n",
138
            s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
139
    sparc_iommu_memory_read(s->iommu, s->dmaregs[1], buf, len);
140
    s->dmaregs[0] |= DMA_INTR;
141
    s->dmaregs[1] += len;
142
}
143

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

    
148
    DPRINTF("DMA write, direction: %c, addr 0x%8.8x\n",
149
            s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
150
    sparc_iommu_memory_write(s->iommu, s->dmaregs[1], buf, len);
151
    s->dmaregs[0] |= DMA_INTR;
152
    s->dmaregs[1] += len;
153
}
154

    
155
static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr)
156
{
157
    DMAState *s = opaque;
158
    uint32_t saddr;
159

    
160
    saddr = (addr & DMA_MAXADDR) >> 2;
161
    DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->dmaregs[saddr]);
162

    
163
    return s->dmaregs[saddr];
164
}
165

    
166
static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
167
{
168
    DMAState *s = opaque;
169
    uint32_t saddr;
170

    
171
    saddr = (addr & DMA_MAXADDR) >> 2;
172
    DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->dmaregs[saddr], val);
173
    switch (saddr) {
174
    case 0:
175
        if (!(val & DMA_INTREN)) {
176
            DPRINTF("Lower ESP IRQ\n");
177
            qemu_irq_lower(s->espirq);
178
        }
179
        if (val & DMA_RESET) {
180
            esp_reset(s->esp_opaque);
181
        } else if (val & 0x40) {
182
            val &= ~0x40;
183
        } else if (val == 0)
184
            val = 0x40;
185
        val &= 0x0fffffff;
186
        val |= DMA_VER;
187
        break;
188
    case 1:
189
        s->dmaregs[0] |= DMA_LOADED;
190
        break;
191
    case 4:
192
        /* ??? Should this mask out the lance IRQ?  The NIC may re-assert
193
           this IRQ unexpectedly.  */
194
        if (!(val & DMA_INTREN)) {
195
            DPRINTF("Lower Lance IRQ\n");
196
            qemu_irq_lower(s->leirq);
197
        }
198
        if (val & DMA_RESET)
199
            pcnet_h_reset(s->lance_opaque);
200
        val &= 0x0fffffff;
201
        val |= DMA_VER;
202
        break;
203
    default:
204
        break;
205
    }
206
    s->dmaregs[saddr] = val;
207
}
208

    
209
static CPUReadMemoryFunc *dma_mem_read[3] = {
210
    dma_mem_readl,
211
    dma_mem_readl,
212
    dma_mem_readl,
213
};
214

    
215
static CPUWriteMemoryFunc *dma_mem_write[3] = {
216
    dma_mem_writel,
217
    dma_mem_writel,
218
    dma_mem_writel,
219
};
220

    
221
static void dma_reset(void *opaque)
222
{
223
    DMAState *s = opaque;
224

    
225
    memset(s->dmaregs, 0, DMA_REGS * 4);
226
    s->dmaregs[0] = DMA_VER;
227
    s->dmaregs[4] = DMA_VER;
228
}
229

    
230
static void dma_save(QEMUFile *f, void *opaque)
231
{
232
    DMAState *s = opaque;
233
    unsigned int i;
234

    
235
    for (i = 0; i < DMA_REGS; i++)
236
        qemu_put_be32s(f, &s->dmaregs[i]);
237
}
238

    
239
static int dma_load(QEMUFile *f, void *opaque, int version_id)
240
{
241
    DMAState *s = opaque;
242
    unsigned int i;
243

    
244
    if (version_id != 1)
245
        return -EINVAL;
246
    for (i = 0; i < DMA_REGS; i++)
247
        qemu_get_be32s(f, &s->dmaregs[i]);
248

    
249
    return 0;
250
}
251

    
252
void *sparc32_dma_init(target_phys_addr_t daddr, qemu_irq espirq,
253
                       qemu_irq leirq, void *iommu)
254
{
255
    DMAState *s;
256
    int dma_io_memory;
257

    
258
    s = qemu_mallocz(sizeof(DMAState));
259
    if (!s)
260
        return NULL;
261

    
262
    s->espirq = espirq;
263
    s->leirq = leirq;
264
    s->iommu = iommu;
265

    
266
    dma_io_memory = cpu_register_io_memory(0, dma_mem_read, dma_mem_write, s);
267
    cpu_register_physical_memory(daddr, 16 * 2, dma_io_memory);
268

    
269
    register_savevm("sparc32_dma", daddr, 1, dma_save, dma_load, s);
270
    qemu_register_reset(dma_reset, s);
271

    
272
    return s;
273
}
274

    
275
void sparc32_dma_set_reset_data(void *opaque, void *esp_opaque,
276
                                void *lance_opaque)
277
{
278
    DMAState *s = opaque;
279

    
280
    s->esp_opaque = esp_opaque;
281
    s->lance_opaque = lance_opaque;
282
}