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
40 #include "hw/isa/isa.h"
41 #include "hw/ppc/mac_dbdma.h"
42 #include "qemu/main-loop.h"
48 #define DBDMA_DPRINTF(fmt, ...) \
49 do { printf("DBDMA: " fmt , ## __VA_ARGS__); } while (0)
51 #define DBDMA_DPRINTF(fmt, ...)
57 static DBDMAState
*dbdma_from_ch(DBDMA_channel
*ch
)
59 return container_of(ch
, DBDMAState
, channels
[ch
->channel
]);
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
));
74 static void dump_dbdma_cmd(dbdma_cmd
*cmd
)
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
;
111 uint16_t sel_mask
, sel_value
;
115 DBDMA_DPRINTF("%s\n", __func__
);
117 intr
= le16_to_cpu(current
->command
) & INTR_MASK
;
120 case INTR_NEVER
: /* don't interrupt */
122 case INTR_ALWAYS
: /* always interrupt */
123 qemu_irq_raise(ch
->irq
);
124 DBDMA_DPRINTF("%s: raise\n", __func__
);
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
);
136 case INTR_IFSET
: /* intr if condition bit is 1 */
138 qemu_irq_raise(ch
->irq
);
139 DBDMA_DPRINTF("%s: raise\n", __func__
);
142 case INTR_IFCLR
: /* intr if condition bit is 0 */
144 qemu_irq_raise(ch
->irq
);
145 DBDMA_DPRINTF("%s: raise\n", __func__
);
151 static int conditional_wait(DBDMA_channel
*ch
)
153 dbdma_cmd
*current
= &ch
->current
;
155 uint16_t sel_mask
, sel_value
;
159 DBDMA_DPRINTF("conditional_wait\n");
161 wait
= le16_to_cpu(current
->command
) & WAIT_MASK
;
164 case WAIT_NEVER
: /* don't wait */
166 case WAIT_ALWAYS
: /* always wait */
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
);
178 case WAIT_IFSET
: /* wait if condition bit is 1 */
182 case WAIT_IFCLR
: /* wait if condition bit is 0 */
190 static void next(DBDMA_channel
*ch
)
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
;
214 uint16_t sel_mask
, sel_value
;
218 DBDMA_DPRINTF("conditional_branch\n");
220 /* check if we must branch */
222 br
= le16_to_cpu(current
->command
) & BR_MASK
;
225 case BR_NEVER
: /* don't branch */
228 case BR_ALWAYS
: /* always branch */
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
);
241 case BR_IFSET
: /* branch if condition bit is 1 */
247 case BR_IFCLR
: /* branch if condition bit is 0 */
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
))
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
);
272 ch
->regs
[DBDMA_STATUS
] &= ~FLUSH
;
274 conditional_interrupt(ch
);
275 conditional_branch(ch
);
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
))
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
) {
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;
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
) {
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;
338 static void load_word(DBDMA_channel
*ch
, int key
, uint32_t addr
,
341 dbdma_cmd
*current
= &ch
->current
;
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
);
354 cpu_physical_memory_read(addr
, &val
, len
);
357 val
= (val
<< 16) | (current
->cmd_dep
& 0x0000ffff);
359 val
= (val
<< 24) | (current
->cmd_dep
& 0x00ffffff);
361 current
->cmd_dep
= val
;
363 if (conditional_wait(ch
))
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
);
374 DBDMA_kick(dbdma_from_ch(ch
));
377 static void store_word(DBDMA_channel
*ch
, int key
, uint32_t addr
,
380 dbdma_cmd
*current
= &ch
->current
;
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
);
393 val
= current
->cmd_dep
;
399 cpu_physical_memory_write(addr
, &val
, len
);
401 if (conditional_wait(ch
))
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
);
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
))
422 current
->xfer_status
= cpu_to_le16(ch
->regs
[DBDMA_STATUS
]);
423 dbdma_cmdptr_save(ch
);
425 conditional_interrupt(ch
);
426 conditional_branch(ch
);
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
;
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
;
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
);
477 start_output(ch
, key
, phy_addr
, req_count
, 0);
481 start_output(ch
, key
, phy_addr
, req_count
, 1);
485 start_input(ch
, key
, phy_addr
, req_count
, 0);
489 start_input(ch
, key
, phy_addr
, req_count
, 1);
493 if (key
< KEY_REGS
) {
494 printf("command %x, invalid key %x\n", cmd
, key
);
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) {
506 } else if (req_count
& 0x2) {
514 load_word(ch
, key
, phy_addr
, req_count
);
518 store_word(ch
, key
, phy_addr
, req_count
);
523 static void DBDMA_run(DBDMAState
*s
)
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
)) {
536 static void DBDMA_run_bh(void *opaque
)
538 DBDMAState
*s
= opaque
;
540 DBDMA_DPRINTF("DBDMA_run_bh\n");
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
,
554 DBDMAState
*s
= dbdma
;
555 DBDMA_channel
*ch
= &s
->channels
[nchan
];
557 DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan
);
563 ch
->io
.opaque
= opaque
;
568 dbdma_control_write(DBDMA_channel
*ch
)
570 uint16_t mask
, value
;
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
);
590 if ((ch
->regs
[DBDMA_STATUS
] & RUN
) && !(status
& RUN
)) {
592 status
&= ~(ACTIVE
|DEAD
);
595 if ((status
& FLUSH
) && ch
->flush
) {
600 DBDMA_DPRINTF(" status 0x%08x\n", status
);
602 ch
->regs
[DBDMA_STATUS
] = status
;
604 if (status
& ACTIVE
) {
605 DBDMA_kick(dbdma_from_ch(ch
));
609 static void dbdma_write(void *opaque
, hwaddr addr
,
610 uint64_t value
, unsigned size
)
612 int channel
= addr
>> DBDMA_CHANNEL_SHIFT
;
613 DBDMAState
*s
= opaque
;
614 DBDMA_channel
*ch
= &s
->channels
[channel
];
615 int reg
= (addr
- (channel
<< DBDMA_CHANNEL_SHIFT
)) >> 2;
617 DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx
" <= 0x%08"PRIx64
"\n",
619 DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
620 (uint32_t)addr
>> DBDMA_CHANNEL_SHIFT
, reg
);
622 /* cmdptr cannot be modified if channel is ACTIVE */
624 if (reg
== DBDMA_CMDPTR_LO
&& (ch
->regs
[DBDMA_STATUS
] & ACTIVE
)) {
628 ch
->regs
[reg
] = value
;
632 dbdma_control_write(ch
);
634 case DBDMA_CMDPTR_LO
:
635 /* 16-byte aligned */
636 ch
->regs
[DBDMA_CMDPTR_LO
] &= ~0xf;
637 dbdma_cmdptr_load(ch
);
641 case DBDMA_BRANCH_SEL
:
645 case DBDMA_XFER_MODE
:
646 case DBDMA_CMDPTR_HI
:
647 case DBDMA_DATA2PTR_HI
:
648 case DBDMA_DATA2PTR_LO
:
649 case DBDMA_ADDRESS_HI
:
650 case DBDMA_BRANCH_ADDR_HI
:
660 static uint64_t dbdma_read(void *opaque
, hwaddr addr
,
664 int channel
= addr
>> DBDMA_CHANNEL_SHIFT
;
665 DBDMAState
*s
= opaque
;
666 DBDMA_channel
*ch
= &s
->channels
[channel
];
667 int reg
= (addr
- (channel
<< DBDMA_CHANNEL_SHIFT
)) >> 2;
669 value
= ch
->regs
[reg
];
671 DBDMA_DPRINTF("readl 0x" TARGET_FMT_plx
" => 0x%08x\n", addr
, value
);
672 DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
673 (uint32_t)addr
>> DBDMA_CHANNEL_SHIFT
, reg
);
680 case DBDMA_CMDPTR_LO
:
682 case DBDMA_BRANCH_SEL
:
686 case DBDMA_XFER_MODE
:
687 case DBDMA_CMDPTR_HI
:
688 case DBDMA_DATA2PTR_HI
:
689 case DBDMA_DATA2PTR_LO
:
690 case DBDMA_ADDRESS_HI
:
691 case DBDMA_BRANCH_ADDR_HI
:
706 static const MemoryRegionOps dbdma_ops
= {
708 .write
= dbdma_write
,
709 .endianness
= DEVICE_LITTLE_ENDIAN
,
711 .min_access_size
= 4,
712 .max_access_size
= 4,
716 static const VMStateDescription vmstate_dbdma_channel
= {
717 .name
= "dbdma_channel",
719 .minimum_version_id
= 0,
720 .fields
= (VMStateField
[]) {
721 VMSTATE_UINT32_ARRAY(regs
, struct DBDMA_channel
, DBDMA_REGS
),
722 VMSTATE_END_OF_LIST()
726 static const VMStateDescription vmstate_dbdma
= {
729 .minimum_version_id
= 2,
730 .fields
= (VMStateField
[]) {
731 VMSTATE_STRUCT_ARRAY(channels
, DBDMAState
, DBDMA_CHANNELS
, 1,
732 vmstate_dbdma_channel
, DBDMA_channel
),
733 VMSTATE_END_OF_LIST()
737 static void dbdma_reset(void *opaque
)
739 DBDMAState
*s
= opaque
;
742 for (i
= 0; i
< DBDMA_CHANNELS
; i
++)
743 memset(s
->channels
[i
].regs
, 0, DBDMA_SIZE
);
746 void* DBDMA_init (MemoryRegion
**dbdma_mem
)
751 s
= g_malloc0(sizeof(DBDMAState
));
753 for (i
= 0; i
< DBDMA_CHANNELS
; i
++) {
754 DBDMA_io
*io
= &s
->channels
[i
].io
;
755 qemu_iovec_init(&io
->iov
, 1);
758 memory_region_init_io(&s
->mem
, NULL
, &dbdma_ops
, s
, "dbdma", 0x1000);
759 *dbdma_mem
= &s
->mem
;
760 vmstate_register(NULL
, -1, &vmstate_dbdma
, s
);
761 qemu_register_reset(dbdma_reset
, s
);
763 s
->bh
= qemu_bh_new(DBDMA_run_bh
, s
);