]> git.proxmox.com Git - mirror_qemu.git/blame - hw/sparc32_dma.c
Get rid of _t suffix
[mirror_qemu.git] / hw / sparc32_dma.c
CommitLineData
67e999be
FB
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 */
6f6260c7 24
87ecb68b
PB
25#include "hw.h"
26#include "sparc32_dma.h"
27#include "sun4m.h"
6f6260c7 28#include "sysbus.h"
67e999be
FB
29
30/* debug DMA */
31//#define DEBUG_DMA
32
33/*
34 * This is the DMA controller part of chip STP2000 (Master I/O), also
35 * produced as NCR89C100. See
36 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
37 * and
38 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/DMA2.txt
39 */
40
41#ifdef DEBUG_DMA
001faf32
BS
42#define DPRINTF(fmt, ...) \
43 do { printf("DMA: " fmt , ## __VA_ARGS__); } while (0)
67e999be 44#else
001faf32 45#define DPRINTF(fmt, ...)
67e999be
FB
46#endif
47
5aca8c3b
BS
48#define DMA_REGS 4
49#define DMA_SIZE (4 * sizeof(uint32_t))
09723aa1
BS
50/* We need the mask, because one instance of the device is not page
51 aligned (ledma, start address 0x0010) */
52#define DMA_MASK (DMA_SIZE - 1)
67e999be
FB
53
54#define DMA_VER 0xa0000000
55#define DMA_INTR 1
56#define DMA_INTREN 0x10
57#define DMA_WRITE_MEM 0x100
58#define DMA_LOADED 0x04000000
5aca8c3b 59#define DMA_DRAIN_FIFO 0x40
67e999be
FB
60#define DMA_RESET 0x80
61
62typedef struct DMAState DMAState;
63
64struct DMAState {
6f6260c7 65 SysBusDevice busdev;
67e999be 66 uint32_t dmaregs[DMA_REGS];
5aca8c3b 67 qemu_irq irq;
2d069bab 68 void *iommu;
2d069bab 69 qemu_irq dev_reset;
67e999be
FB
70};
71
9b94dc32 72/* Note: on sparc, the lance 16 bit bus is swapped */
99a0949b 73void ledma_memory_read(void *opaque, a_target_phys_addr addr,
9b94dc32 74 uint8_t *buf, int len, int do_bswap)
67e999be
FB
75{
76 DMAState *s = opaque;
9b94dc32 77 int i;
67e999be
FB
78
79 DPRINTF("DMA write, direction: %c, addr 0x%8.8x\n",
80 s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
5aca8c3b 81 addr |= s->dmaregs[3];
9b94dc32
FB
82 if (do_bswap) {
83 sparc_iommu_memory_read(s->iommu, addr, buf, len);
84 } else {
85 addr &= ~1;
86 len &= ~1;
87 sparc_iommu_memory_read(s->iommu, addr, buf, len);
88 for(i = 0; i < len; i += 2) {
89 bswap16s((uint16_t *)(buf + i));
90 }
91 }
67e999be
FB
92}
93
99a0949b 94void ledma_memory_write(void *opaque, a_target_phys_addr addr,
9b94dc32 95 uint8_t *buf, int len, int do_bswap)
67e999be
FB
96{
97 DMAState *s = opaque;
9b94dc32
FB
98 int l, i;
99 uint16_t tmp_buf[32];
67e999be
FB
100
101 DPRINTF("DMA read, direction: %c, addr 0x%8.8x\n",
102 s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
5aca8c3b 103 addr |= s->dmaregs[3];
9b94dc32
FB
104 if (do_bswap) {
105 sparc_iommu_memory_write(s->iommu, addr, buf, len);
106 } else {
107 addr &= ~1;
108 len &= ~1;
109 while (len > 0) {
110 l = len;
111 if (l > sizeof(tmp_buf))
112 l = sizeof(tmp_buf);
113 for(i = 0; i < l; i += 2) {
114 tmp_buf[i >> 1] = bswap16(*(uint16_t *)(buf + i));
115 }
116 sparc_iommu_memory_write(s->iommu, addr, (uint8_t *)tmp_buf, l);
117 len -= l;
118 buf += l;
119 addr += l;
120 }
121 }
67e999be
FB
122}
123
70c0de96 124static void dma_set_irq(void *opaque, int irq, int level)
67e999be
FB
125{
126 DMAState *s = opaque;
70c0de96 127 if (level) {
9b5207aa 128 DPRINTF("Raise IRQ\n");
70c0de96
BS
129 s->dmaregs[0] |= DMA_INTR;
130 qemu_irq_raise(s->irq);
131 } else {
132 s->dmaregs[0] &= ~DMA_INTR;
9b5207aa 133 DPRINTF("Lower IRQ\n");
70c0de96
BS
134 qemu_irq_lower(s->irq);
135 }
67e999be
FB
136}
137
138void espdma_memory_read(void *opaque, uint8_t *buf, int len)
139{
140 DMAState *s = opaque;
141
142 DPRINTF("DMA read, direction: %c, addr 0x%8.8x\n",
143 s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
144 sparc_iommu_memory_read(s->iommu, s->dmaregs[1], buf, len);
145 s->dmaregs[0] |= DMA_INTR;
146 s->dmaregs[1] += len;
147}
148
149void espdma_memory_write(void *opaque, uint8_t *buf, int len)
150{
151 DMAState *s = opaque;
152
153 DPRINTF("DMA write, direction: %c, addr 0x%8.8x\n",
154 s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
155 sparc_iommu_memory_write(s->iommu, s->dmaregs[1], buf, len);
156 s->dmaregs[0] |= DMA_INTR;
157 s->dmaregs[1] += len;
158}
159
99a0949b 160static uint32_t dma_mem_readl(void *opaque, a_target_phys_addr addr)
67e999be
FB
161{
162 DMAState *s = opaque;
163 uint32_t saddr;
164
09723aa1 165 saddr = (addr & DMA_MASK) >> 2;
5aca8c3b
BS
166 DPRINTF("read dmareg " TARGET_FMT_plx ": 0x%8.8x\n", addr,
167 s->dmaregs[saddr]);
67e999be
FB
168
169 return s->dmaregs[saddr];
170}
171
99a0949b 172static void dma_mem_writel(void *opaque, a_target_phys_addr addr, uint32_t val)
67e999be
FB
173{
174 DMAState *s = opaque;
175 uint32_t saddr;
176
09723aa1 177 saddr = (addr & DMA_MASK) >> 2;
5aca8c3b
BS
178 DPRINTF("write dmareg " TARGET_FMT_plx ": 0x%8.8x -> 0x%8.8x\n", addr,
179 s->dmaregs[saddr], val);
67e999be
FB
180 switch (saddr) {
181 case 0:
d537cf6c 182 if (!(val & DMA_INTREN)) {
5aca8c3b
BS
183 DPRINTF("Lower IRQ\n");
184 qemu_irq_lower(s->irq);
d537cf6c 185 }
67e999be 186 if (val & DMA_RESET) {
2d069bab
BS
187 qemu_irq_raise(s->dev_reset);
188 qemu_irq_lower(s->dev_reset);
5aca8c3b
BS
189 } else if (val & DMA_DRAIN_FIFO) {
190 val &= ~DMA_DRAIN_FIFO;
67e999be 191 } else if (val == 0)
5aca8c3b 192 val = DMA_DRAIN_FIFO;
67e999be
FB
193 val &= 0x0fffffff;
194 val |= DMA_VER;
195 break;
196 case 1:
197 s->dmaregs[0] |= DMA_LOADED;
198 break;
67e999be
FB
199 default:
200 break;
201 }
202 s->dmaregs[saddr] = val;
203}
204
d60efc6b 205static CPUReadMemoryFunc * const dma_mem_read[3] = {
7c560456
BS
206 NULL,
207 NULL,
67e999be
FB
208 dma_mem_readl,
209};
210
d60efc6b 211static CPUWriteMemoryFunc * const dma_mem_write[3] = {
7c560456
BS
212 NULL,
213 NULL,
67e999be
FB
214 dma_mem_writel,
215};
216
217static void dma_reset(void *opaque)
218{
219 DMAState *s = opaque;
220
5aca8c3b 221 memset(s->dmaregs, 0, DMA_SIZE);
67e999be 222 s->dmaregs[0] = DMA_VER;
67e999be
FB
223}
224
75c497dc
BS
225static const VMStateDescription vmstate_dma = {
226 .name ="sparc32_dma",
227 .version_id = 2,
228 .minimum_version_id = 2,
229 .minimum_version_id_old = 2,
230 .fields = (VMStateField []) {
231 VMSTATE_UINT32_ARRAY(dmaregs, DMAState, DMA_REGS),
232 VMSTATE_END_OF_LIST()
233 }
234};
67e999be 235
81a322d4 236static int sparc32_dma_init1(SysBusDevice *dev)
6f6260c7
BS
237{
238 DMAState *s = FROM_SYSBUS(DMAState, dev);
239 int dma_io_memory;
67e999be 240
6f6260c7 241 sysbus_init_irq(dev, &s->irq);
67e999be 242
1eed09cb 243 dma_io_memory = cpu_register_io_memory(dma_mem_read, dma_mem_write, s);
6f6260c7 244 sysbus_init_mmio(dev, DMA_SIZE, dma_io_memory);
67e999be 245
75c497dc 246 vmstate_register(-1, &vmstate_dma, s);
a08d4367 247 qemu_register_reset(dma_reset, s);
67e999be 248
6f6260c7 249 qdev_init_gpio_in(&dev->qdev, dma_set_irq, 1);
74ff8d90 250 qdev_init_gpio_out(&dev->qdev, &s->dev_reset, 1);
81a322d4 251 return 0;
6f6260c7 252}
67e999be 253
6f6260c7
BS
254static SysBusDeviceInfo sparc32_dma_info = {
255 .init = sparc32_dma_init1,
256 .qdev.name = "sparc32_dma",
257 .qdev.size = sizeof(DMAState),
ee6847d1 258 .qdev.props = (Property[]) {
3180d772
GH
259 DEFINE_PROP_PTR("iommu_opaque", DMAState, iommu),
260 DEFINE_PROP_END_OF_LIST(),
6f6260c7
BS
261 }
262};
263
264static void sparc32_dma_register_devices(void)
265{
266 sysbus_register_withprop(&sparc32_dma_info);
67e999be 267}
6f6260c7
BS
268
269device_init(sparc32_dma_register_devices)