Revision 58229933
b/hw/dma.c | ||
---|---|---|
58 | 58 |
int dshift; |
59 | 59 |
struct dma_regs regs[4]; |
60 | 60 |
qemu_irq *cpu_request_exit; |
61 |
MemoryRegion channel_io; |
|
62 |
MemoryRegion cont_io; |
|
61 | 63 |
} dma_controllers[2]; |
62 | 64 |
|
63 | 65 |
enum { |
... | ... | |
149 | 151 |
return ff; |
150 | 152 |
} |
151 | 153 |
|
152 |
static uint32_t read_chan (void *opaque, uint32_t nport)
|
|
154 |
static uint64_t read_chan(void *opaque, hwaddr nport, unsigned size)
|
|
153 | 155 |
{ |
154 | 156 |
struct dma_cont *d = opaque; |
155 | 157 |
int ichan, nreg, iport, ff, val, dir; |
... | ... | |
171 | 173 |
return (val >> (d->dshift + (ff << 3))) & 0xff; |
172 | 174 |
} |
173 | 175 |
|
174 |
static void write_chan (void *opaque, uint32_t nport, uint32_t data) |
|
176 |
static void write_chan(void *opaque, hwaddr nport, uint64_t data, |
|
177 |
unsigned size) |
|
175 | 178 |
{ |
176 | 179 |
struct dma_cont *d = opaque; |
177 | 180 |
int iport, ichan, nreg; |
... | ... | |
189 | 192 |
} |
190 | 193 |
} |
191 | 194 |
|
192 |
static void write_cont (void *opaque, uint32_t nport, uint32_t data) |
|
195 |
static void write_cont(void *opaque, hwaddr nport, uint64_t data, |
|
196 |
unsigned size) |
|
193 | 197 |
{ |
194 | 198 |
struct dma_cont *d = opaque; |
195 | 199 |
int iport, ichan = 0; |
196 | 200 |
|
197 | 201 |
iport = (nport >> d->dshift) & 0x0f; |
198 | 202 |
switch (iport) { |
199 |
case 0x08: /* command */
|
|
203 |
case 0x01: /* command */
|
|
200 | 204 |
if ((data != 0) && (data & CMD_NOT_SUPPORTED)) { |
201 |
dolog ("command %#x not supported\n", data);
|
|
205 |
dolog("command %"PRIx64" not supported\n", data);
|
|
202 | 206 |
return; |
203 | 207 |
} |
204 | 208 |
d->command = data; |
205 | 209 |
break; |
206 | 210 |
|
207 |
case 0x09:
|
|
211 |
case 0x02:
|
|
208 | 212 |
ichan = data & 3; |
209 | 213 |
if (data & 4) { |
210 | 214 |
d->status |= 1 << (ichan + 4); |
... | ... | |
216 | 220 |
DMA_run(); |
217 | 221 |
break; |
218 | 222 |
|
219 |
case 0x0a: /* single mask */
|
|
223 |
case 0x03: /* single mask */
|
|
220 | 224 |
if (data & 4) |
221 | 225 |
d->mask |= 1 << (data & 3); |
222 | 226 |
else |
... | ... | |
224 | 228 |
DMA_run(); |
225 | 229 |
break; |
226 | 230 |
|
227 |
case 0x0b: /* mode */
|
|
231 |
case 0x04: /* mode */
|
|
228 | 232 |
{ |
229 | 233 |
ichan = data & 3; |
230 | 234 |
#ifdef DEBUG_DMA |
... | ... | |
243 | 247 |
break; |
244 | 248 |
} |
245 | 249 |
|
246 |
case 0x0c: /* clear flip flop */
|
|
250 |
case 0x05: /* clear flip flop */
|
|
247 | 251 |
d->flip_flop = 0; |
248 | 252 |
break; |
249 | 253 |
|
250 |
case 0x0d: /* reset */
|
|
254 |
case 0x06: /* reset */
|
|
251 | 255 |
d->flip_flop = 0; |
252 | 256 |
d->mask = ~0; |
253 | 257 |
d->status = 0; |
254 | 258 |
d->command = 0; |
255 | 259 |
break; |
256 | 260 |
|
257 |
case 0x0e: /* clear mask for all channels */
|
|
261 |
case 0x07: /* clear mask for all channels */
|
|
258 | 262 |
d->mask = 0; |
259 | 263 |
DMA_run(); |
260 | 264 |
break; |
261 | 265 |
|
262 |
case 0x0f: /* write mask for all channels */
|
|
266 |
case 0x08: /* write mask for all channels */
|
|
263 | 267 |
d->mask = data; |
264 | 268 |
DMA_run(); |
265 | 269 |
break; |
... | ... | |
277 | 281 |
#endif |
278 | 282 |
} |
279 | 283 |
|
280 |
static uint32_t read_cont (void *opaque, uint32_t nport)
|
|
284 |
static uint64_t read_cont(void *opaque, hwaddr nport, unsigned size)
|
|
281 | 285 |
{ |
282 | 286 |
struct dma_cont *d = opaque; |
283 | 287 |
int iport, val; |
... | ... | |
463 | 467 |
static void dma_reset(void *opaque) |
464 | 468 |
{ |
465 | 469 |
struct dma_cont *d = opaque; |
466 |
write_cont (d, (0x0d << d->dshift), 0);
|
|
470 |
write_cont(d, (0x06 << d->dshift), 0, 1);
|
|
467 | 471 |
} |
468 | 472 |
|
469 | 473 |
static int dma_phony_handler (void *opaque, int nchan, int dma_pos, int dma_len) |
... | ... | |
473 | 477 |
return dma_pos; |
474 | 478 |
} |
475 | 479 |
|
480 |
|
|
481 |
static const MemoryRegionOps channel_io_ops = { |
|
482 |
.read = read_chan, |
|
483 |
.write = write_chan, |
|
484 |
.endianness = DEVICE_NATIVE_ENDIAN, |
|
485 |
.impl = { |
|
486 |
.min_access_size = 1, |
|
487 |
.max_access_size = 1, |
|
488 |
}, |
|
489 |
}; |
|
490 |
|
|
491 |
/* IOport from page_base */ |
|
492 |
static const MemoryRegionPortio page_portio_list[] = { |
|
493 |
{ 0x01, 3, 1, .write = write_page, .read = read_page, }, |
|
494 |
{ 0x07, 1, 1, .write = write_page, .read = read_page, }, |
|
495 |
PORTIO_END_OF_LIST(), |
|
496 |
}; |
|
497 |
|
|
498 |
/* IOport from pageh_base */ |
|
499 |
static const MemoryRegionPortio pageh_portio_list[] = { |
|
500 |
{ 0x01, 3, 1, .write = write_pageh, .read = read_pageh, }, |
|
501 |
{ 0x07, 3, 1, .write = write_pageh, .read = read_pageh, }, |
|
502 |
PORTIO_END_OF_LIST(), |
|
503 |
}; |
|
504 |
|
|
505 |
static const MemoryRegionOps cont_io_ops = { |
|
506 |
.read = read_cont, |
|
507 |
.write = write_cont, |
|
508 |
.endianness = DEVICE_NATIVE_ENDIAN, |
|
509 |
.impl = { |
|
510 |
.min_access_size = 1, |
|
511 |
.max_access_size = 1, |
|
512 |
}, |
|
513 |
}; |
|
514 |
|
|
476 | 515 |
/* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */ |
477 | 516 |
static void dma_init2(struct dma_cont *d, int base, int dshift, |
478 | 517 |
int page_base, int pageh_base, |
479 | 518 |
qemu_irq *cpu_request_exit) |
480 | 519 |
{ |
481 |
static const int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 }; |
|
482 | 520 |
int i; |
483 | 521 |
|
484 | 522 |
d->dshift = dshift; |
485 | 523 |
d->cpu_request_exit = cpu_request_exit; |
486 |
for (i = 0; i < 8; i++) { |
|
487 |
register_ioport_write (base + (i << dshift), 1, 1, write_chan, d); |
|
488 |
register_ioport_read (base + (i << dshift), 1, 1, read_chan, d); |
|
489 |
} |
|
490 |
for (i = 0; i < ARRAY_SIZE (page_port_list); i++) { |
|
491 |
register_ioport_write (page_base + page_port_list[i], 1, 1, |
|
492 |
write_page, d); |
|
493 |
register_ioport_read (page_base + page_port_list[i], 1, 1, |
|
494 |
read_page, d); |
|
495 |
if (pageh_base >= 0) { |
|
496 |
register_ioport_write (pageh_base + page_port_list[i], 1, 1, |
|
497 |
write_pageh, d); |
|
498 |
register_ioport_read (pageh_base + page_port_list[i], 1, 1, |
|
499 |
read_pageh, d); |
|
500 |
} |
|
501 |
} |
|
502 |
for (i = 0; i < 8; i++) { |
|
503 |
register_ioport_write (base + ((i + 8) << dshift), 1, 1, |
|
504 |
write_cont, d); |
|
505 |
register_ioport_read (base + ((i + 8) << dshift), 1, 1, |
|
506 |
read_cont, d); |
|
524 |
|
|
525 |
memory_region_init_io(&d->channel_io, &channel_io_ops, d, |
|
526 |
"dma-chan", 8 << d->dshift); |
|
527 |
memory_region_add_subregion(isa_address_space_io(NULL), |
|
528 |
base, &d->channel_io); |
|
529 |
|
|
530 |
isa_register_portio_list(NULL, page_base, page_portio_list, d, |
|
531 |
"dma-page"); |
|
532 |
if (pageh_base >= 0) { |
|
533 |
isa_register_portio_list(NULL, pageh_base, pageh_portio_list, d, |
|
534 |
"dma-pageh"); |
|
507 | 535 |
} |
536 |
|
|
537 |
memory_region_init_io(&d->cont_io, &cont_io_ops, d, "dma-cont", |
|
538 |
8 << d->dshift); |
|
539 |
memory_region_add_subregion(isa_address_space_io(NULL), |
|
540 |
base + (8 << d->dshift), &d->cont_io); |
|
541 |
|
|
508 | 542 |
qemu_register_reset(dma_reset, d); |
509 | 543 |
dma_reset(d); |
510 | 544 |
for (i = 0; i < ARRAY_SIZE (d->regs); ++i) { |
Also available in: Unified diff