exec: Save CPUState::exception_index field
[qemu.git] / hw / misc / macio / mac_dbdma.c
blobb25e8511b2fbe8a769237557aedc76099c40be7a
1 /*
2 * PowerMac descriptor-based DMA emulation
4 * Copyright (c) 2005-2007 Fabrice Bellard
5 * Copyright (c) 2007 Jocelyn Mayer
6 * Copyright (c) 2009 Laurent Vivier
8 * some parts from linux-2.6.28, arch/powerpc/include/asm/dbdma.h
10 * Definitions for using the Apple Descriptor-Based DMA controller
11 * in Power Macintosh computers.
13 * Copyright (C) 1996 Paul Mackerras.
15 * some parts from mol 0.9.71
17 * Descriptor based DMA emulation
19 * Copyright (C) 1998-2004 Samuel Rydh (samuel@ibrium.se)
21 * Permission is hereby granted, free of charge, to any person obtaining a copy
22 * of this software and associated documentation files (the "Software"), to deal
23 * in the Software without restriction, including without limitation the rights
24 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 * copies of the Software, and to permit persons to whom the Software is
26 * furnished to do so, subject to the following conditions:
28 * The above copyright notice and this permission notice shall be included in
29 * all copies or substantial portions of the Software.
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
34 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37 * THE SOFTWARE.
39 #include "hw/hw.h"
40 #include "hw/isa/isa.h"
41 #include "hw/ppc/mac_dbdma.h"
42 #include "qemu/main-loop.h"
44 /* debug DBDMA */
45 //#define DEBUG_DBDMA
47 #ifdef DEBUG_DBDMA
48 #define DBDMA_DPRINTF(fmt, ...) \
49 do { printf("DBDMA: " fmt , ## __VA_ARGS__); } while (0)
50 #else
51 #define DBDMA_DPRINTF(fmt, ...)
52 #endif
57 static DBDMAState *dbdma_from_ch(DBDMA_channel *ch)
59 return container_of(ch, DBDMAState, channels[ch->channel]);
62 #ifdef DEBUG_DBDMA
63 static void dump_dbdma_cmd(dbdma_cmd *cmd)
65 printf("dbdma_cmd %p\n", cmd);
66 printf(" req_count 0x%04x\n", le16_to_cpu(cmd->req_count));
67 printf(" command 0x%04x\n", le16_to_cpu(cmd->command));
68 printf(" phy_addr 0x%08x\n", le32_to_cpu(cmd->phy_addr));
69 printf(" cmd_dep 0x%08x\n", le32_to_cpu(cmd->cmd_dep));
70 printf(" res_count 0x%04x\n", le16_to_cpu(cmd->res_count));
71 printf(" xfer_status 0x%04x\n", le16_to_cpu(cmd->xfer_status));
73 #else
74 static void dump_dbdma_cmd(dbdma_cmd *cmd)
77 #endif
78 static void dbdma_cmdptr_load(DBDMA_channel *ch)
80 DBDMA_DPRINTF("dbdma_cmdptr_load 0x%08x\n",
81 ch->regs[DBDMA_CMDPTR_LO]);
82 cpu_physical_memory_read(ch->regs[DBDMA_CMDPTR_LO],
83 &ch->current, sizeof(dbdma_cmd));
86 static void dbdma_cmdptr_save(DBDMA_channel *ch)
88 DBDMA_DPRINTF("dbdma_cmdptr_save 0x%08x\n",
89 ch->regs[DBDMA_CMDPTR_LO]);
90 DBDMA_DPRINTF("xfer_status 0x%08x res_count 0x%04x\n",
91 le16_to_cpu(ch->current.xfer_status),
92 le16_to_cpu(ch->current.res_count));
93 cpu_physical_memory_write(ch->regs[DBDMA_CMDPTR_LO],
94 &ch->current, sizeof(dbdma_cmd));
97 static void kill_channel(DBDMA_channel *ch)
99 DBDMA_DPRINTF("kill_channel\n");
101 ch->regs[DBDMA_STATUS] |= DEAD;
102 ch->regs[DBDMA_STATUS] &= ~ACTIVE;
104 qemu_irq_raise(ch->irq);
107 static void conditional_interrupt(DBDMA_channel *ch)
109 dbdma_cmd *current = &ch->current;
110 uint16_t intr;
111 uint16_t sel_mask, sel_value;
112 uint32_t status;
113 int cond;
115 DBDMA_DPRINTF("%s\n", __func__);
117 intr = le16_to_cpu(current->command) & INTR_MASK;
119 switch(intr) {
120 case INTR_NEVER: /* don't interrupt */
121 return;
122 case INTR_ALWAYS: /* always interrupt */
123 qemu_irq_raise(ch->irq);
124 DBDMA_DPRINTF("%s: raise\n", __func__);
125 return;
128 status = ch->regs[DBDMA_STATUS] & DEVSTAT;
130 sel_mask = (ch->regs[DBDMA_INTR_SEL] >> 16) & 0x0f;
131 sel_value = ch->regs[DBDMA_INTR_SEL] & 0x0f;
133 cond = (status & sel_mask) == (sel_value & sel_mask);
135 switch(intr) {
136 case INTR_IFSET: /* intr if condition bit is 1 */
137 if (cond) {
138 qemu_irq_raise(ch->irq);
139 DBDMA_DPRINTF("%s: raise\n", __func__);
141 return;
142 case INTR_IFCLR: /* intr if condition bit is 0 */
143 if (!cond) {
144 qemu_irq_raise(ch->irq);
145 DBDMA_DPRINTF("%s: raise\n", __func__);
147 return;
151 static int conditional_wait(DBDMA_channel *ch)
153 dbdma_cmd *current = &ch->current;
154 uint16_t wait;
155 uint16_t sel_mask, sel_value;
156 uint32_t status;
157 int cond;
159 DBDMA_DPRINTF("conditional_wait\n");
161 wait = le16_to_cpu(current->command) & WAIT_MASK;
163 switch(wait) {
164 case WAIT_NEVER: /* don't wait */
165 return 0;
166 case WAIT_ALWAYS: /* always wait */
167 return 1;
170 status = ch->regs[DBDMA_STATUS] & DEVSTAT;
172 sel_mask = (ch->regs[DBDMA_WAIT_SEL] >> 16) & 0x0f;
173 sel_value = ch->regs[DBDMA_WAIT_SEL] & 0x0f;
175 cond = (status & sel_mask) == (sel_value & sel_mask);
177 switch(wait) {
178 case WAIT_IFSET: /* wait if condition bit is 1 */
179 if (cond)
180 return 1;
181 return 0;
182 case WAIT_IFCLR: /* wait if condition bit is 0 */
183 if (!cond)
184 return 1;
185 return 0;
187 return 0;
190 static void next(DBDMA_channel *ch)
192 uint32_t cp;
194 ch->regs[DBDMA_STATUS] &= ~BT;
196 cp = ch->regs[DBDMA_CMDPTR_LO];
197 ch->regs[DBDMA_CMDPTR_LO] = cp + sizeof(dbdma_cmd);
198 dbdma_cmdptr_load(ch);
201 static void branch(DBDMA_channel *ch)
203 dbdma_cmd *current = &ch->current;
205 ch->regs[DBDMA_CMDPTR_LO] = current->cmd_dep;
206 ch->regs[DBDMA_STATUS] |= BT;
207 dbdma_cmdptr_load(ch);
210 static void conditional_branch(DBDMA_channel *ch)
212 dbdma_cmd *current = &ch->current;
213 uint16_t br;
214 uint16_t sel_mask, sel_value;
215 uint32_t status;
216 int cond;
218 DBDMA_DPRINTF("conditional_branch\n");
220 /* check if we must branch */
222 br = le16_to_cpu(current->command) & BR_MASK;
224 switch(br) {
225 case BR_NEVER: /* don't branch */
226 next(ch);
227 return;
228 case BR_ALWAYS: /* always branch */
229 branch(ch);
230 return;
233 status = ch->regs[DBDMA_STATUS] & DEVSTAT;
235 sel_mask = (ch->regs[DBDMA_BRANCH_SEL] >> 16) & 0x0f;
236 sel_value = ch->regs[DBDMA_BRANCH_SEL] & 0x0f;
238 cond = (status & sel_mask) == (sel_value & sel_mask);
240 switch(br) {
241 case BR_IFSET: /* branch if condition bit is 1 */
242 if (cond)
243 branch(ch);
244 else
245 next(ch);
246 return;
247 case BR_IFCLR: /* branch if condition bit is 0 */
248 if (!cond)
249 branch(ch);
250 else
251 next(ch);
252 return;
256 static void channel_run(DBDMA_channel *ch);
258 static void dbdma_end(DBDMA_io *io)
260 DBDMA_channel *ch = io->channel;
261 dbdma_cmd *current = &ch->current;
263 DBDMA_DPRINTF("%s\n", __func__);
265 if (conditional_wait(ch))
266 goto wait;
268 current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
269 current->res_count = cpu_to_le16(io->len);
270 dbdma_cmdptr_save(ch);
271 if (io->is_last)
272 ch->regs[DBDMA_STATUS] &= ~FLUSH;
274 conditional_interrupt(ch);
275 conditional_branch(ch);
277 wait:
278 /* Indicate that we're ready for a new DMA round */
279 ch->io.processing = false;
281 if ((ch->regs[DBDMA_STATUS] & RUN) &&
282 (ch->regs[DBDMA_STATUS] & ACTIVE))
283 channel_run(ch);
286 static void start_output(DBDMA_channel *ch, int key, uint32_t addr,
287 uint16_t req_count, int is_last)
289 DBDMA_DPRINTF("start_output\n");
291 /* KEY_REGS, KEY_DEVICE and KEY_STREAM
292 * are not implemented in the mac-io chip
295 DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
296 if (!addr || key > KEY_STREAM3) {
297 kill_channel(ch);
298 return;
301 ch->io.addr = addr;
302 ch->io.len = req_count;
303 ch->io.is_last = is_last;
304 ch->io.dma_end = dbdma_end;
305 ch->io.is_dma_out = 1;
306 ch->io.processing = true;
307 if (ch->rw) {
308 ch->rw(&ch->io);
312 static void start_input(DBDMA_channel *ch, int key, uint32_t addr,
313 uint16_t req_count, int is_last)
315 DBDMA_DPRINTF("start_input\n");
317 /* KEY_REGS, KEY_DEVICE and KEY_STREAM
318 * are not implemented in the mac-io chip
321 DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
322 if (!addr || key > KEY_STREAM3) {
323 kill_channel(ch);
324 return;
327 ch->io.addr = addr;
328 ch->io.len = req_count;
329 ch->io.is_last = is_last;
330 ch->io.dma_end = dbdma_end;
331 ch->io.is_dma_out = 0;
332 ch->io.processing = true;
333 if (ch->rw) {
334 ch->rw(&ch->io);
338 static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
339 uint16_t len)
341 dbdma_cmd *current = &ch->current;
342 uint32_t val;
344 DBDMA_DPRINTF("load_word\n");
346 /* only implements KEY_SYSTEM */
348 if (key != KEY_SYSTEM) {
349 printf("DBDMA: LOAD_WORD, unimplemented key %x\n", key);
350 kill_channel(ch);
351 return;
354 cpu_physical_memory_read(addr, &val, len);
356 if (len == 2)
357 val = (val << 16) | (current->cmd_dep & 0x0000ffff);
358 else if (len == 1)
359 val = (val << 24) | (current->cmd_dep & 0x00ffffff);
361 current->cmd_dep = val;
363 if (conditional_wait(ch))
364 goto wait;
366 current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
367 dbdma_cmdptr_save(ch);
368 ch->regs[DBDMA_STATUS] &= ~FLUSH;
370 conditional_interrupt(ch);
371 next(ch);
373 wait:
374 DBDMA_kick(dbdma_from_ch(ch));
377 static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
378 uint16_t len)
380 dbdma_cmd *current = &ch->current;
381 uint32_t val;
383 DBDMA_DPRINTF("store_word\n");
385 /* only implements KEY_SYSTEM */
387 if (key != KEY_SYSTEM) {
388 printf("DBDMA: STORE_WORD, unimplemented key %x\n", key);
389 kill_channel(ch);
390 return;
393 val = current->cmd_dep;
394 if (len == 2)
395 val >>= 16;
396 else if (len == 1)
397 val >>= 24;
399 cpu_physical_memory_write(addr, &val, len);
401 if (conditional_wait(ch))
402 goto wait;
404 current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
405 dbdma_cmdptr_save(ch);
406 ch->regs[DBDMA_STATUS] &= ~FLUSH;
408 conditional_interrupt(ch);
409 next(ch);
411 wait:
412 DBDMA_kick(dbdma_from_ch(ch));
415 static void nop(DBDMA_channel *ch)
417 dbdma_cmd *current = &ch->current;
419 if (conditional_wait(ch))
420 goto wait;
422 current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS]);
423 dbdma_cmdptr_save(ch);
425 conditional_interrupt(ch);
426 conditional_branch(ch);
428 wait:
429 DBDMA_kick(dbdma_from_ch(ch));
432 static void stop(DBDMA_channel *ch)
434 ch->regs[DBDMA_STATUS] &= ~(ACTIVE|DEAD|FLUSH);
436 /* the stop command does not increment command pointer */
439 static void channel_run(DBDMA_channel *ch)
441 dbdma_cmd *current = &ch->current;
442 uint16_t cmd, key;
443 uint16_t req_count;
444 uint32_t phy_addr;
446 DBDMA_DPRINTF("channel_run\n");
447 dump_dbdma_cmd(current);
449 /* clear WAKE flag at command fetch */
451 ch->regs[DBDMA_STATUS] &= ~WAKE;
453 cmd = le16_to_cpu(current->command) & COMMAND_MASK;
455 switch (cmd) {
456 case DBDMA_NOP:
457 nop(ch);
458 return;
460 case DBDMA_STOP:
461 stop(ch);
462 return;
465 key = le16_to_cpu(current->command) & 0x0700;
466 req_count = le16_to_cpu(current->req_count);
467 phy_addr = le32_to_cpu(current->phy_addr);
469 if (key == KEY_STREAM4) {
470 printf("command %x, invalid key 4\n", cmd);
471 kill_channel(ch);
472 return;
475 switch (cmd) {
476 case OUTPUT_MORE:
477 start_output(ch, key, phy_addr, req_count, 0);
478 return;
480 case OUTPUT_LAST:
481 start_output(ch, key, phy_addr, req_count, 1);
482 return;
484 case INPUT_MORE:
485 start_input(ch, key, phy_addr, req_count, 0);
486 return;
488 case INPUT_LAST:
489 start_input(ch, key, phy_addr, req_count, 1);
490 return;
493 if (key < KEY_REGS) {
494 printf("command %x, invalid key %x\n", cmd, key);
495 key = KEY_SYSTEM;
498 /* for LOAD_WORD and STORE_WORD, req_count is on 3 bits
499 * and BRANCH is invalid
502 req_count = req_count & 0x0007;
503 if (req_count & 0x4) {
504 req_count = 4;
505 phy_addr &= ~3;
506 } else if (req_count & 0x2) {
507 req_count = 2;
508 phy_addr &= ~1;
509 } else
510 req_count = 1;
512 switch (cmd) {
513 case LOAD_WORD:
514 load_word(ch, key, phy_addr, req_count);
515 return;
517 case STORE_WORD:
518 store_word(ch, key, phy_addr, req_count);
519 return;
523 static void DBDMA_run(DBDMAState *s)
525 int channel;
527 for (channel = 0; channel < DBDMA_CHANNELS; channel++) {
528 DBDMA_channel *ch = &s->channels[channel];
529 uint32_t status = ch->regs[DBDMA_STATUS];
530 if (!ch->io.processing && (status & RUN) && (status & ACTIVE)) {
531 channel_run(ch);
536 static void DBDMA_run_bh(void *opaque)
538 DBDMAState *s = opaque;
540 DBDMA_DPRINTF("DBDMA_run_bh\n");
542 DBDMA_run(s);
545 void DBDMA_kick(DBDMAState *dbdma)
547 qemu_bh_schedule(dbdma->bh);
550 void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
551 DBDMA_rw rw, DBDMA_flush flush,
552 void *opaque)
554 DBDMAState *s = dbdma;
555 DBDMA_channel *ch = &s->channels[nchan];
557 DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan);
559 ch->irq = irq;
560 ch->channel = nchan;
561 ch->rw = rw;
562 ch->flush = flush;
563 ch->io.opaque = opaque;
564 ch->io.channel = ch;
567 static void
568 dbdma_control_write(DBDMA_channel *ch)
570 uint16_t mask, value;
571 uint32_t status;
573 mask = (ch->regs[DBDMA_CONTROL] >> 16) & 0xffff;
574 value = ch->regs[DBDMA_CONTROL] & 0xffff;
576 value &= (RUN | PAUSE | FLUSH | WAKE | DEVSTAT);
578 status = ch->regs[DBDMA_STATUS];
580 status = (value & mask) | (status & ~mask);
582 if (status & WAKE)
583 status |= ACTIVE;
584 if (status & RUN) {
585 status |= ACTIVE;
586 status &= ~DEAD;
588 if (status & PAUSE)
589 status &= ~ACTIVE;
590 if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) {
591 /* RUN is cleared */
592 status &= ~(ACTIVE|DEAD);
593 if ((status & FLUSH) && ch->flush) {
594 ch->flush(&ch->io);
595 status &= ~FLUSH;
599 DBDMA_DPRINTF(" status 0x%08x\n", status);
601 ch->regs[DBDMA_STATUS] = status;
603 if (status & ACTIVE) {
604 DBDMA_kick(dbdma_from_ch(ch));
606 if ((status & FLUSH) && ch->flush) {
607 ch->flush(&ch->io);
611 static void dbdma_write(void *opaque, hwaddr addr,
612 uint64_t value, unsigned size)
614 int channel = addr >> DBDMA_CHANNEL_SHIFT;
615 DBDMAState *s = opaque;
616 DBDMA_channel *ch = &s->channels[channel];
617 int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
619 DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n",
620 addr, value);
621 DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
622 (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
624 /* cmdptr cannot be modified if channel is ACTIVE */
626 if (reg == DBDMA_CMDPTR_LO && (ch->regs[DBDMA_STATUS] & ACTIVE)) {
627 return;
630 ch->regs[reg] = value;
632 switch(reg) {
633 case DBDMA_CONTROL:
634 dbdma_control_write(ch);
635 break;
636 case DBDMA_CMDPTR_LO:
637 /* 16-byte aligned */
638 ch->regs[DBDMA_CMDPTR_LO] &= ~0xf;
639 dbdma_cmdptr_load(ch);
640 break;
641 case DBDMA_STATUS:
642 case DBDMA_INTR_SEL:
643 case DBDMA_BRANCH_SEL:
644 case DBDMA_WAIT_SEL:
645 /* nothing to do */
646 break;
647 case DBDMA_XFER_MODE:
648 case DBDMA_CMDPTR_HI:
649 case DBDMA_DATA2PTR_HI:
650 case DBDMA_DATA2PTR_LO:
651 case DBDMA_ADDRESS_HI:
652 case DBDMA_BRANCH_ADDR_HI:
653 case DBDMA_RES1:
654 case DBDMA_RES2:
655 case DBDMA_RES3:
656 case DBDMA_RES4:
657 /* unused */
658 break;
662 static uint64_t dbdma_read(void *opaque, hwaddr addr,
663 unsigned size)
665 uint32_t value;
666 int channel = addr >> DBDMA_CHANNEL_SHIFT;
667 DBDMAState *s = opaque;
668 DBDMA_channel *ch = &s->channels[channel];
669 int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
671 value = ch->regs[reg];
673 DBDMA_DPRINTF("readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
674 DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
675 (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
677 switch(reg) {
678 case DBDMA_CONTROL:
679 value = 0;
680 break;
681 case DBDMA_STATUS:
682 case DBDMA_CMDPTR_LO:
683 case DBDMA_INTR_SEL:
684 case DBDMA_BRANCH_SEL:
685 case DBDMA_WAIT_SEL:
686 /* nothing to do */
687 break;
688 case DBDMA_XFER_MODE:
689 case DBDMA_CMDPTR_HI:
690 case DBDMA_DATA2PTR_HI:
691 case DBDMA_DATA2PTR_LO:
692 case DBDMA_ADDRESS_HI:
693 case DBDMA_BRANCH_ADDR_HI:
694 /* unused */
695 value = 0;
696 break;
697 case DBDMA_RES1:
698 case DBDMA_RES2:
699 case DBDMA_RES3:
700 case DBDMA_RES4:
701 /* reserved */
702 break;
705 return value;
708 static const MemoryRegionOps dbdma_ops = {
709 .read = dbdma_read,
710 .write = dbdma_write,
711 .endianness = DEVICE_LITTLE_ENDIAN,
712 .valid = {
713 .min_access_size = 4,
714 .max_access_size = 4,
718 static const VMStateDescription vmstate_dbdma_channel = {
719 .name = "dbdma_channel",
720 .version_id = 0,
721 .minimum_version_id = 0,
722 .fields = (VMStateField[]) {
723 VMSTATE_UINT32_ARRAY(regs, struct DBDMA_channel, DBDMA_REGS),
724 VMSTATE_END_OF_LIST()
728 static const VMStateDescription vmstate_dbdma = {
729 .name = "dbdma",
730 .version_id = 2,
731 .minimum_version_id = 2,
732 .fields = (VMStateField[]) {
733 VMSTATE_STRUCT_ARRAY(channels, DBDMAState, DBDMA_CHANNELS, 1,
734 vmstate_dbdma_channel, DBDMA_channel),
735 VMSTATE_END_OF_LIST()
739 static void dbdma_reset(void *opaque)
741 DBDMAState *s = opaque;
742 int i;
744 for (i = 0; i < DBDMA_CHANNELS; i++)
745 memset(s->channels[i].regs, 0, DBDMA_SIZE);
748 void* DBDMA_init (MemoryRegion **dbdma_mem)
750 DBDMAState *s;
751 int i;
753 s = g_malloc0(sizeof(DBDMAState));
755 for (i = 0; i < DBDMA_CHANNELS; i++) {
756 DBDMA_io *io = &s->channels[i].io;
757 qemu_iovec_init(&io->iov, 1);
760 memory_region_init_io(&s->mem, NULL, &dbdma_ops, s, "dbdma", 0x1000);
761 *dbdma_mem = &s->mem;
762 vmstate_register(NULL, -1, &vmstate_dbdma, s);
763 qemu_register_reset(dbdma_reset, s);
765 s->bh = qemu_bh_new(DBDMA_run_bh, s);
767 return s;