qemu

Форк
0
/
sparc32_dma.c 
453 строки · 14.0 Кб
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/irq.h"
30
#include "hw/qdev-properties.h"
31
#include "hw/sparc/sparc32_dma.h"
32
#include "hw/sparc/sun4m_iommu.h"
33
#include "hw/sysbus.h"
34
#include "migration/vmstate.h"
35
#include "sysemu/dma.h"
36
#include "qapi/error.h"
37
#include "qemu/module.h"
38
#include "trace.h"
39

40
/*
41
 * This is the DMA controller part of chip STP2000 (Master I/O), also
42
 * produced as NCR89C100. See
43
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
44
 * and
45
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/DMA2.txt
46
 */
47

48
#define DMA_SIZE (4 * sizeof(uint32_t))
49
/* We need the mask, because one instance of the device is not page
50
   aligned (ledma, start address 0x0010) */
51
#define DMA_MASK (DMA_SIZE - 1)
52
/* OBP says 0x20 bytes for ledma, the extras are aliased to espdma */
53
#define DMA_ETH_SIZE (8 * sizeof(uint32_t))
54
#define DMA_MAX_REG_OFFSET (2 * DMA_SIZE - 1)
55

56
#define DMA_VER 0xa0000000
57
#define DMA_INTR 1
58
#define DMA_INTREN 0x10
59
#define DMA_WRITE_MEM 0x100
60
#define DMA_EN 0x200
61
#define DMA_LOADED 0x04000000
62
#define DMA_DRAIN_FIFO 0x40
63
#define DMA_RESET 0x80
64

65
/* XXX SCSI and ethernet should have different read-only bit masks */
66
#define DMA_CSR_RO_MASK 0xfe000007
67

68
enum {
69
    GPIO_RESET = 0,
70
    GPIO_DMA,
71
};
72

73
/* Note: on sparc, the lance 16 bit bus is swapped */
74
void ledma_memory_read(void *opaque, hwaddr addr,
75
                       uint8_t *buf, int len, int do_bswap)
76
{
77
    DMADeviceState *s = opaque;
78
    IOMMUState *is = (IOMMUState *)s->iommu;
79
    int i;
80

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

95
void ledma_memory_write(void *opaque, hwaddr addr,
96
                        uint8_t *buf, int len, int do_bswap)
97
{
98
    DMADeviceState *s = opaque;
99
    IOMMUState *is = (IOMMUState *)s->iommu;
100
    int l, i;
101
    uint16_t tmp_buf[32];
102

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

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

147
void espdma_memory_read(void *opaque, uint8_t *buf, int len)
148
{
149
    DMADeviceState *s = opaque;
150
    IOMMUState *is = (IOMMUState *)s->iommu;
151

152
    trace_espdma_memory_read(s->dmaregs[1], len);
153
    dma_memory_read(&is->iommu_as, s->dmaregs[1], buf, len,
154
                    MEMTXATTRS_UNSPECIFIED);
155
    s->dmaregs[1] += len;
156
}
157

158
void espdma_memory_write(void *opaque, uint8_t *buf, int len)
159
{
160
    DMADeviceState *s = opaque;
161
    IOMMUState *is = (IOMMUState *)s->iommu;
162

163
    trace_espdma_memory_write(s->dmaregs[1], len);
164
    dma_memory_write(&is->iommu_as, s->dmaregs[1], buf, len,
165
                     MEMTXATTRS_UNSPECIFIED);
166
    s->dmaregs[1] += len;
167
}
168

169
static uint64_t dma_mem_read(void *opaque, hwaddr addr,
170
                             unsigned size)
171
{
172
    DMADeviceState *s = opaque;
173
    uint32_t saddr;
174

175
    saddr = (addr & DMA_MASK) >> 2;
176
    trace_sparc32_dma_mem_readl(addr, s->dmaregs[saddr]);
177
    return s->dmaregs[saddr];
178
}
179

180
static void dma_mem_write(void *opaque, hwaddr addr,
181
                          uint64_t val, unsigned size)
182
{
183
    DMADeviceState *s = opaque;
184
    uint32_t saddr;
185

186
    saddr = (addr & DMA_MASK) >> 2;
187
    trace_sparc32_dma_mem_writel(addr, s->dmaregs[saddr], val);
188
    switch (saddr) {
189
    case 0:
190
        if (val & DMA_INTREN) {
191
            if (s->dmaregs[0] & DMA_INTR) {
192
                trace_sparc32_dma_set_irq_raise();
193
                qemu_irq_raise(s->irq);
194
            }
195
        } else {
196
            if (s->dmaregs[0] & (DMA_INTR | DMA_INTREN)) {
197
                trace_sparc32_dma_set_irq_lower();
198
                qemu_irq_lower(s->irq);
199
            }
200
        }
201
        if (val & DMA_RESET) {
202
            qemu_irq_raise(s->gpio[GPIO_RESET]);
203
            qemu_irq_lower(s->gpio[GPIO_RESET]);
204
        } else if (val & DMA_DRAIN_FIFO) {
205
            val &= ~DMA_DRAIN_FIFO;
206
        } else if (val == 0)
207
            val = DMA_DRAIN_FIFO;
208

209
        if (val & DMA_EN && !(s->dmaregs[0] & DMA_EN)) {
210
            trace_sparc32_dma_enable_raise();
211
            qemu_irq_raise(s->gpio[GPIO_DMA]);
212
        } else if (!(val & DMA_EN) && !!(s->dmaregs[0] & DMA_EN)) {
213
            trace_sparc32_dma_enable_lower();
214
            qemu_irq_lower(s->gpio[GPIO_DMA]);
215
        }
216

217
        val &= ~DMA_CSR_RO_MASK;
218
        val |= DMA_VER;
219
        s->dmaregs[0] = (s->dmaregs[0] & DMA_CSR_RO_MASK) | val;
220
        break;
221
    case 1:
222
        s->dmaregs[0] |= DMA_LOADED;
223
        /* fall through */
224
    default:
225
        s->dmaregs[saddr] = val;
226
        break;
227
    }
228
}
229

230
static const MemoryRegionOps dma_mem_ops = {
231
    .read = dma_mem_read,
232
    .write = dma_mem_write,
233
    .endianness = DEVICE_NATIVE_ENDIAN,
234
    .valid = {
235
        .min_access_size = 4,
236
        .max_access_size = 4,
237
    },
238
};
239

240
static void sparc32_dma_device_reset(DeviceState *d)
241
{
242
    DMADeviceState *s = SPARC32_DMA_DEVICE(d);
243

244
    memset(s->dmaregs, 0, DMA_SIZE);
245
    s->dmaregs[0] = DMA_VER;
246
}
247

248
static const VMStateDescription vmstate_sparc32_dma_device = {
249
    .name ="sparc32_dma",
250
    .version_id = 2,
251
    .minimum_version_id = 2,
252
    .fields = (const VMStateField[]) {
253
        VMSTATE_UINT32_ARRAY(dmaregs, DMADeviceState, DMA_REGS),
254
        VMSTATE_END_OF_LIST()
255
    }
256
};
257

258
static void sparc32_dma_device_init(Object *obj)
259
{
260
    DeviceState *dev = DEVICE(obj);
261
    DMADeviceState *s = SPARC32_DMA_DEVICE(obj);
262
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
263

264
    sysbus_init_irq(sbd, &s->irq);
265

266
    sysbus_init_mmio(sbd, &s->iomem);
267

268
    object_property_add_link(OBJECT(dev), "iommu", TYPE_SUN4M_IOMMU,
269
                             (Object **) &s->iommu,
270
                             qdev_prop_allow_set_link_before_realize,
271
                             0);
272

273
    qdev_init_gpio_in(dev, dma_set_irq, 1);
274
    qdev_init_gpio_out(dev, s->gpio, 2);
275
}
276

277
static void sparc32_dma_device_class_init(ObjectClass *klass, void *data)
278
{
279
    DeviceClass *dc = DEVICE_CLASS(klass);
280

281
    dc->reset = sparc32_dma_device_reset;
282
    dc->vmsd = &vmstate_sparc32_dma_device;
283
}
284

285
static const TypeInfo sparc32_dma_device_info = {
286
    .name          = TYPE_SPARC32_DMA_DEVICE,
287
    .parent        = TYPE_SYS_BUS_DEVICE,
288
    .abstract      = true,
289
    .instance_size = sizeof(DMADeviceState),
290
    .instance_init = sparc32_dma_device_init,
291
    .class_init    = sparc32_dma_device_class_init,
292
};
293

294
static void sparc32_espdma_device_init(Object *obj)
295
{
296
    DMADeviceState *s = SPARC32_DMA_DEVICE(obj);
297
    ESPDMADeviceState *es = SPARC32_ESPDMA_DEVICE(obj);
298

299
    memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s,
300
                          "espdma-mmio", DMA_SIZE);
301

302
    object_initialize_child(obj, "esp", &es->esp, TYPE_SYSBUS_ESP);
303
}
304

305
static void sparc32_espdma_device_realize(DeviceState *dev, Error **errp)
306
{
307
    ESPDMADeviceState *es = SPARC32_ESPDMA_DEVICE(dev);
308
    SysBusESPState *sysbus = SYSBUS_ESP(&es->esp);
309
    ESPState *esp = &sysbus->esp;
310

311
    esp->dma_memory_read = espdma_memory_read;
312
    esp->dma_memory_write = espdma_memory_write;
313
    esp->dma_opaque = SPARC32_DMA_DEVICE(dev);
314
    sysbus->it_shift = 2;
315
    esp->dma_enabled = 1;
316
    sysbus_realize(SYS_BUS_DEVICE(sysbus), &error_fatal);
317
}
318

319
static void sparc32_espdma_device_class_init(ObjectClass *klass, void *data)
320
{
321
    DeviceClass *dc = DEVICE_CLASS(klass);
322

323
    dc->realize = sparc32_espdma_device_realize;
324
}
325

326
static const TypeInfo sparc32_espdma_device_info = {
327
    .name          = TYPE_SPARC32_ESPDMA_DEVICE,
328
    .parent        = TYPE_SPARC32_DMA_DEVICE,
329
    .instance_size = sizeof(ESPDMADeviceState),
330
    .instance_init = sparc32_espdma_device_init,
331
    .class_init    = sparc32_espdma_device_class_init,
332
};
333

334
static void sparc32_ledma_device_init(Object *obj)
335
{
336
    DMADeviceState *s = SPARC32_DMA_DEVICE(obj);
337
    LEDMADeviceState *ls = SPARC32_LEDMA_DEVICE(obj);
338

339
    memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s,
340
                          "ledma-mmio", DMA_SIZE);
341

342
    object_initialize_child(obj, "lance", &ls->lance, TYPE_LANCE);
343
}
344

345
static void sparc32_ledma_device_realize(DeviceState *dev, Error **errp)
346
{
347
    LEDMADeviceState *s = SPARC32_LEDMA_DEVICE(dev);
348
    SysBusPCNetState *lance = SYSBUS_PCNET(&s->lance);
349

350
    object_property_set_link(OBJECT(lance), "dma", OBJECT(dev), &error_abort);
351
    sysbus_realize(SYS_BUS_DEVICE(lance), &error_fatal);
352
}
353

354
static void sparc32_ledma_device_class_init(ObjectClass *klass, void *data)
355
{
356
    DeviceClass *dc = DEVICE_CLASS(klass);
357

358
    dc->realize = sparc32_ledma_device_realize;
359
}
360

361
static const TypeInfo sparc32_ledma_device_info = {
362
    .name          = TYPE_SPARC32_LEDMA_DEVICE,
363
    .parent        = TYPE_SPARC32_DMA_DEVICE,
364
    .instance_size = sizeof(LEDMADeviceState),
365
    .instance_init = sparc32_ledma_device_init,
366
    .class_init    = sparc32_ledma_device_class_init,
367
};
368

369
static void sparc32_dma_realize(DeviceState *dev, Error **errp)
370
{
371
    SPARC32DMAState *s = SPARC32_DMA(dev);
372
    DeviceState *espdma, *esp, *ledma, *lance;
373
    SysBusDevice *sbd;
374
    Object *iommu;
375

376
    iommu = object_resolve_path_type("", TYPE_SUN4M_IOMMU, NULL);
377
    if (!iommu) {
378
        error_setg(errp, "unable to locate sun4m IOMMU device");
379
        return;
380
    }
381

382
    espdma = DEVICE(&s->espdma);
383
    object_property_set_link(OBJECT(espdma), "iommu", iommu, &error_abort);
384
    sysbus_realize(SYS_BUS_DEVICE(espdma), &error_fatal);
385

386
    esp = DEVICE(object_resolve_path_component(OBJECT(espdma), "esp"));
387
    sbd = SYS_BUS_DEVICE(esp);
388
    sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(espdma, 0));
389
    qdev_connect_gpio_out(espdma, 0, qdev_get_gpio_in(esp, 0));
390
    qdev_connect_gpio_out(espdma, 1, qdev_get_gpio_in(esp, 1));
391

392
    sbd = SYS_BUS_DEVICE(espdma);
393
    memory_region_add_subregion(&s->dmamem, 0x0,
394
                                sysbus_mmio_get_region(sbd, 0));
395

396
    ledma = DEVICE(&s->ledma);
397
    object_property_set_link(OBJECT(ledma), "iommu", iommu, &error_abort);
398
    sysbus_realize(SYS_BUS_DEVICE(ledma), &error_fatal);
399

400
    lance = DEVICE(object_resolve_path_component(OBJECT(ledma), "lance"));
401
    sbd = SYS_BUS_DEVICE(lance);
402
    sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(ledma, 0));
403
    qdev_connect_gpio_out(ledma, 0, qdev_get_gpio_in(lance, 0));
404

405
    sbd = SYS_BUS_DEVICE(ledma);
406
    memory_region_add_subregion(&s->dmamem, 0x10,
407
                                sysbus_mmio_get_region(sbd, 0));
408

409
    /* Add ledma alias to handle SunOS 5.7 - Solaris 9 invalid access bug */
410
    memory_region_init_alias(&s->ledma_alias, OBJECT(dev), "ledma-alias",
411
                             sysbus_mmio_get_region(sbd, 0), 0x4, 0x4);
412
    memory_region_add_subregion(&s->dmamem, 0x20, &s->ledma_alias);
413
}
414

415
static void sparc32_dma_init(Object *obj)
416
{
417
    SPARC32DMAState *s = SPARC32_DMA(obj);
418
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
419

420
    memory_region_init(&s->dmamem, OBJECT(s), "dma", DMA_SIZE + DMA_ETH_SIZE);
421
    sysbus_init_mmio(sbd, &s->dmamem);
422

423
    object_initialize_child(obj, "espdma", &s->espdma,
424
                            TYPE_SPARC32_ESPDMA_DEVICE);
425
    object_initialize_child(obj, "ledma", &s->ledma,
426
                            TYPE_SPARC32_LEDMA_DEVICE);
427
}
428

429
static void sparc32_dma_class_init(ObjectClass *klass, void *data)
430
{
431
    DeviceClass *dc = DEVICE_CLASS(klass);
432

433
    dc->realize = sparc32_dma_realize;
434
}
435

436
static const TypeInfo sparc32_dma_info = {
437
    .name          = TYPE_SPARC32_DMA,
438
    .parent        = TYPE_SYS_BUS_DEVICE,
439
    .instance_size = sizeof(SPARC32DMAState),
440
    .instance_init = sparc32_dma_init,
441
    .class_init    = sparc32_dma_class_init,
442
};
443

444

445
static void sparc32_dma_register_types(void)
446
{
447
    type_register_static(&sparc32_dma_device_info);
448
    type_register_static(&sparc32_espdma_device_info);
449
    type_register_static(&sparc32_ledma_device_info);
450
    type_register_static(&sparc32_dma_info);
451
}
452

453
type_init(sparc32_dma_register_types)
454

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.