Revision 5aca8c3b hw/sparc32_dma.c
b/hw/sparc32_dma.c | ||
---|---|---|
41 | 41 |
#define DPRINTF(fmt, args...) |
42 | 42 |
#endif |
43 | 43 |
|
44 |
#define DMA_REGS 8 |
|
45 |
#define DMA_MAXADDR (DMA_REGS * 4 - 1) |
|
44 |
#define DMA_REGS 4 |
|
45 |
#define DMA_SIZE (4 * sizeof(uint32_t)) |
|
46 |
#define DMA_MAXADDR (DMA_SIZE - 1) |
|
46 | 47 |
|
47 | 48 |
#define DMA_VER 0xa0000000 |
48 | 49 |
#define DMA_INTR 1 |
49 | 50 |
#define DMA_INTREN 0x10 |
50 | 51 |
#define DMA_WRITE_MEM 0x100 |
51 | 52 |
#define DMA_LOADED 0x04000000 |
53 |
#define DMA_DRAIN_FIFO 0x40 |
|
52 | 54 |
#define DMA_RESET 0x80 |
53 | 55 |
|
54 | 56 |
typedef struct DMAState DMAState; |
55 | 57 |
|
56 | 58 |
struct DMAState { |
57 | 59 |
uint32_t dmaregs[DMA_REGS]; |
58 |
qemu_irq espirq, leirq; |
|
59 |
void *iommu, *esp_opaque, *lance_opaque; |
|
60 |
qemu_irq irq; |
|
61 |
void *iommu, *dev_opaque; |
|
62 |
void (*dev_reset)(void *dev_opaque); |
|
60 | 63 |
qemu_irq *pic; |
61 | 64 |
}; |
62 | 65 |
|
... | ... | |
69 | 72 |
|
70 | 73 |
DPRINTF("DMA write, direction: %c, addr 0x%8.8x\n", |
71 | 74 |
s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]); |
72 |
addr |= s->dmaregs[7];
|
|
75 |
addr |= s->dmaregs[3];
|
|
73 | 76 |
if (do_bswap) { |
74 | 77 |
sparc_iommu_memory_read(s->iommu, addr, buf, len); |
75 | 78 |
} else { |
... | ... | |
91 | 94 |
|
92 | 95 |
DPRINTF("DMA read, direction: %c, addr 0x%8.8x\n", |
93 | 96 |
s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]); |
94 |
addr |= s->dmaregs[7];
|
|
97 |
addr |= s->dmaregs[3];
|
|
95 | 98 |
if (do_bswap) { |
96 | 99 |
sparc_iommu_memory_write(s->iommu, addr, buf, len); |
97 | 100 |
} else { |
... | ... | |
118 | 121 |
|
119 | 122 |
DPRINTF("Raise ESP IRQ\n"); |
120 | 123 |
s->dmaregs[0] |= DMA_INTR; |
121 |
qemu_irq_raise(s->espirq);
|
|
124 |
qemu_irq_raise(s->irq); |
|
122 | 125 |
} |
123 | 126 |
|
124 | 127 |
void espdma_clear_irq(void *opaque) |
... | ... | |
127 | 130 |
|
128 | 131 |
s->dmaregs[0] &= ~DMA_INTR; |
129 | 132 |
DPRINTF("Lower ESP IRQ\n"); |
130 |
qemu_irq_lower(s->espirq);
|
|
133 |
qemu_irq_lower(s->irq); |
|
131 | 134 |
} |
132 | 135 |
|
133 | 136 |
void espdma_memory_read(void *opaque, uint8_t *buf, int len) |
... | ... | |
158 | 161 |
uint32_t saddr; |
159 | 162 |
|
160 | 163 |
saddr = (addr & DMA_MAXADDR) >> 2; |
161 |
DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->dmaregs[saddr]); |
|
164 |
DPRINTF("read dmareg " TARGET_FMT_plx ": 0x%8.8x\n", addr, |
|
165 |
s->dmaregs[saddr]); |
|
162 | 166 |
|
163 | 167 |
return s->dmaregs[saddr]; |
164 | 168 |
} |
... | ... | |
169 | 173 |
uint32_t saddr; |
170 | 174 |
|
171 | 175 |
saddr = (addr & DMA_MAXADDR) >> 2; |
172 |
DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->dmaregs[saddr], val); |
|
176 |
DPRINTF("write dmareg " TARGET_FMT_plx ": 0x%8.8x -> 0x%8.8x\n", addr, |
|
177 |
s->dmaregs[saddr], val); |
|
173 | 178 |
switch (saddr) { |
174 | 179 |
case 0: |
175 | 180 |
if (!(val & DMA_INTREN)) { |
176 |
DPRINTF("Lower ESP IRQ\n");
|
|
177 |
qemu_irq_lower(s->espirq);
|
|
181 |
DPRINTF("Lower IRQ\n"); |
|
182 |
qemu_irq_lower(s->irq); |
|
178 | 183 |
} |
179 | 184 |
if (val & DMA_RESET) { |
180 |
esp_reset(s->esp_opaque);
|
|
181 |
} else if (val & 0x40) {
|
|
182 |
val &= ~0x40;
|
|
185 |
s->dev_reset(s->dev_opaque);
|
|
186 |
} else if (val & DMA_DRAIN_FIFO) {
|
|
187 |
val &= ~DMA_DRAIN_FIFO;
|
|
183 | 188 |
} else if (val == 0) |
184 |
val = 0x40;
|
|
189 |
val = DMA_DRAIN_FIFO;
|
|
185 | 190 |
val &= 0x0fffffff; |
186 | 191 |
val |= DMA_VER; |
187 | 192 |
break; |
188 | 193 |
case 1: |
189 | 194 |
s->dmaregs[0] |= DMA_LOADED; |
190 | 195 |
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 | 196 |
default: |
204 | 197 |
break; |
205 | 198 |
} |
... | ... | |
222 | 215 |
{ |
223 | 216 |
DMAState *s = opaque; |
224 | 217 |
|
225 |
memset(s->dmaregs, 0, DMA_REGS * 4);
|
|
218 |
memset(s->dmaregs, 0, DMA_SIZE);
|
|
226 | 219 |
s->dmaregs[0] = DMA_VER; |
227 |
s->dmaregs[4] = DMA_VER; |
|
228 | 220 |
} |
229 | 221 |
|
230 | 222 |
static void dma_save(QEMUFile *f, void *opaque) |
... | ... | |
241 | 233 |
DMAState *s = opaque; |
242 | 234 |
unsigned int i; |
243 | 235 |
|
244 |
if (version_id != 1)
|
|
236 |
if (version_id != 2)
|
|
245 | 237 |
return -EINVAL; |
246 | 238 |
for (i = 0; i < DMA_REGS; i++) |
247 | 239 |
qemu_get_be32s(f, &s->dmaregs[i]); |
... | ... | |
249 | 241 |
return 0; |
250 | 242 |
} |
251 | 243 |
|
252 |
void *sparc32_dma_init(target_phys_addr_t daddr, qemu_irq espirq, |
|
253 |
qemu_irq leirq, void *iommu) |
|
244 |
void *sparc32_dma_init(target_phys_addr_t daddr, qemu_irq irq, void *iommu) |
|
254 | 245 |
{ |
255 | 246 |
DMAState *s; |
256 | 247 |
int dma_io_memory; |
... | ... | |
259 | 250 |
if (!s) |
260 | 251 |
return NULL; |
261 | 252 |
|
262 |
s->espirq = espirq; |
|
263 |
s->leirq = leirq; |
|
253 |
s->irq = irq; |
|
264 | 254 |
s->iommu = iommu; |
265 | 255 |
|
266 | 256 |
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);
|
|
257 |
cpu_register_physical_memory(daddr, DMA_SIZE, dma_io_memory);
|
|
268 | 258 |
|
269 |
register_savevm("sparc32_dma", daddr, 1, dma_save, dma_load, s);
|
|
259 |
register_savevm("sparc32_dma", daddr, 2, dma_save, dma_load, s);
|
|
270 | 260 |
qemu_register_reset(dma_reset, s); |
271 | 261 |
|
272 | 262 |
return s; |
273 | 263 |
} |
274 | 264 |
|
275 |
void sparc32_dma_set_reset_data(void *opaque, void *esp_opaque,
|
|
276 |
void *lance_opaque)
|
|
265 |
void sparc32_dma_set_reset_data(void *opaque, void (*dev_reset)(void *opaque),
|
|
266 |
void *dev_opaque)
|
|
277 | 267 |
{ |
278 | 268 |
DMAState *s = opaque; |
279 | 269 |
|
280 |
s->esp_opaque = esp_opaque;
|
|
281 |
s->lance_opaque = lance_opaque;
|
|
270 |
s->dev_reset = dev_reset;
|
|
271 |
s->dev_opaque = dev_opaque;
|
|
282 | 272 |
} |
Also available in: Unified diff