summaryrefslogtreecommitdiff
path: root/hw/misc/macio/mac_dbdma.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/misc/macio/mac_dbdma.c')
-rw-r--r--hw/misc/macio/mac_dbdma.c135
1 files changed, 71 insertions, 64 deletions
diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c
index 6051f17db..15452b9a2 100644
--- a/hw/misc/macio/mac_dbdma.c
+++ b/hw/misc/macio/mac_dbdma.c
@@ -41,16 +41,26 @@
#include "hw/isa/isa.h"
#include "hw/ppc/mac_dbdma.h"
#include "qemu/main-loop.h"
+#include "qemu/log.h"
+#include "sysemu/dma.h"
/* debug DBDMA */
-//#define DEBUG_DBDMA
-
-#ifdef DEBUG_DBDMA
-#define DBDMA_DPRINTF(fmt, ...) \
- do { printf("DBDMA: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DBDMA_DPRINTF(fmt, ...)
-#endif
+#define DEBUG_DBDMA 0
+#define DEBUG_DBDMA_CHANMASK ((1ull << DBDMA_CHANNELS) - 1)
+
+#define DBDMA_DPRINTF(fmt, ...) do { \
+ if (DEBUG_DBDMA) { \
+ printf("DBDMA: " fmt , ## __VA_ARGS__); \
+ } \
+} while (0);
+
+#define DBDMA_DPRINTFCH(ch, fmt, ...) do { \
+ if (DEBUG_DBDMA) { \
+ if ((1ul << (ch)->channel) & DEBUG_DBDMA_CHANMASK) { \
+ printf("DBDMA[%02x]: " fmt , (ch)->channel, ## __VA_ARGS__); \
+ } \
+ } \
+} while (0);
/*
*/
@@ -60,7 +70,7 @@ static DBDMAState *dbdma_from_ch(DBDMA_channel *ch)
return container_of(ch, DBDMAState, channels[ch->channel]);
}
-#ifdef DEBUG_DBDMA
+#if DEBUG_DBDMA
static void dump_dbdma_cmd(dbdma_cmd *cmd)
{
printf("dbdma_cmd %p\n", cmd);
@@ -78,26 +88,26 @@ static void dump_dbdma_cmd(dbdma_cmd *cmd)
#endif
static void dbdma_cmdptr_load(DBDMA_channel *ch)
{
- DBDMA_DPRINTF("dbdma_cmdptr_load 0x%08x\n",
- ch->regs[DBDMA_CMDPTR_LO]);
- cpu_physical_memory_read(ch->regs[DBDMA_CMDPTR_LO],
- &ch->current, sizeof(dbdma_cmd));
+ DBDMA_DPRINTFCH(ch, "dbdma_cmdptr_load 0x%08x\n",
+ ch->regs[DBDMA_CMDPTR_LO]);
+ dma_memory_read(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO],
+ &ch->current, sizeof(dbdma_cmd));
}
static void dbdma_cmdptr_save(DBDMA_channel *ch)
{
- DBDMA_DPRINTF("dbdma_cmdptr_save 0x%08x\n",
- ch->regs[DBDMA_CMDPTR_LO]);
- DBDMA_DPRINTF("xfer_status 0x%08x res_count 0x%04x\n",
- le16_to_cpu(ch->current.xfer_status),
- le16_to_cpu(ch->current.res_count));
- cpu_physical_memory_write(ch->regs[DBDMA_CMDPTR_LO],
- &ch->current, sizeof(dbdma_cmd));
+ DBDMA_DPRINTFCH(ch, "dbdma_cmdptr_save 0x%08x\n",
+ ch->regs[DBDMA_CMDPTR_LO]);
+ DBDMA_DPRINTFCH(ch, "xfer_status 0x%08x res_count 0x%04x\n",
+ le16_to_cpu(ch->current.xfer_status),
+ le16_to_cpu(ch->current.res_count));
+ dma_memory_write(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO],
+ &ch->current, sizeof(dbdma_cmd));
}
static void kill_channel(DBDMA_channel *ch)
{
- DBDMA_DPRINTF("kill_channel\n");
+ DBDMA_DPRINTFCH(ch, "kill_channel\n");
ch->regs[DBDMA_STATUS] |= DEAD;
ch->regs[DBDMA_STATUS] &= ~ACTIVE;
@@ -113,7 +123,7 @@ static void conditional_interrupt(DBDMA_channel *ch)
uint32_t status;
int cond;
- DBDMA_DPRINTF("%s\n", __func__);
+ DBDMA_DPRINTFCH(ch, "%s\n", __func__);
intr = le16_to_cpu(current->command) & INTR_MASK;
@@ -122,7 +132,7 @@ static void conditional_interrupt(DBDMA_channel *ch)
return;
case INTR_ALWAYS: /* always interrupt */
qemu_irq_raise(ch->irq);
- DBDMA_DPRINTF("%s: raise\n", __func__);
+ DBDMA_DPRINTFCH(ch, "%s: raise\n", __func__);
return;
}
@@ -137,13 +147,13 @@ static void conditional_interrupt(DBDMA_channel *ch)
case INTR_IFSET: /* intr if condition bit is 1 */
if (cond) {
qemu_irq_raise(ch->irq);
- DBDMA_DPRINTF("%s: raise\n", __func__);
+ DBDMA_DPRINTFCH(ch, "%s: raise\n", __func__);
}
return;
case INTR_IFCLR: /* intr if condition bit is 0 */
if (!cond) {
qemu_irq_raise(ch->irq);
- DBDMA_DPRINTF("%s: raise\n", __func__);
+ DBDMA_DPRINTFCH(ch, "%s: raise\n", __func__);
}
return;
}
@@ -157,7 +167,7 @@ static int conditional_wait(DBDMA_channel *ch)
uint32_t status;
int cond;
- DBDMA_DPRINTF("conditional_wait\n");
+ DBDMA_DPRINTFCH(ch, "conditional_wait\n");
wait = le16_to_cpu(current->command) & WAIT_MASK;
@@ -203,7 +213,7 @@ static void branch(DBDMA_channel *ch)
{
dbdma_cmd *current = &ch->current;
- ch->regs[DBDMA_CMDPTR_LO] = current->cmd_dep;
+ ch->regs[DBDMA_CMDPTR_LO] = le32_to_cpu(current->cmd_dep);
ch->regs[DBDMA_STATUS] |= BT;
dbdma_cmdptr_load(ch);
}
@@ -216,7 +226,7 @@ static void conditional_branch(DBDMA_channel *ch)
uint32_t status;
int cond;
- DBDMA_DPRINTF("conditional_branch\n");
+ DBDMA_DPRINTFCH(ch, "conditional_branch\n");
/* check if we must branch */
@@ -261,7 +271,7 @@ static void dbdma_end(DBDMA_io *io)
DBDMA_channel *ch = io->channel;
dbdma_cmd *current = &ch->current;
- DBDMA_DPRINTF("%s\n", __func__);
+ DBDMA_DPRINTFCH(ch, "%s\n", __func__);
if (conditional_wait(ch))
goto wait;
@@ -287,13 +297,13 @@ wait:
static void start_output(DBDMA_channel *ch, int key, uint32_t addr,
uint16_t req_count, int is_last)
{
- DBDMA_DPRINTF("start_output\n");
+ DBDMA_DPRINTFCH(ch, "start_output\n");
/* KEY_REGS, KEY_DEVICE and KEY_STREAM
* are not implemented in the mac-io chip
*/
- DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
+ DBDMA_DPRINTFCH(ch, "addr 0x%x key 0x%x\n", addr, key);
if (!addr || key > KEY_STREAM3) {
kill_channel(ch);
return;
@@ -313,13 +323,13 @@ static void start_output(DBDMA_channel *ch, int key, uint32_t addr,
static void start_input(DBDMA_channel *ch, int key, uint32_t addr,
uint16_t req_count, int is_last)
{
- DBDMA_DPRINTF("start_input\n");
+ DBDMA_DPRINTFCH(ch, "start_input\n");
/* KEY_REGS, KEY_DEVICE and KEY_STREAM
* are not implemented in the mac-io chip
*/
- DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
+ DBDMA_DPRINTFCH(ch, "addr 0x%x key 0x%x\n", addr, key);
if (!addr || key > KEY_STREAM3) {
kill_channel(ch);
return;
@@ -340,9 +350,8 @@ static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
uint16_t len)
{
dbdma_cmd *current = &ch->current;
- uint32_t val;
- DBDMA_DPRINTF("load_word\n");
+ DBDMA_DPRINTFCH(ch, "load_word %d bytes, addr=%08x\n", len, addr);
/* only implements KEY_SYSTEM */
@@ -352,14 +361,7 @@ static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
return;
}
- cpu_physical_memory_read(addr, &val, len);
-
- if (len == 2)
- val = (val << 16) | (current->cmd_dep & 0x0000ffff);
- else if (len == 1)
- val = (val << 24) | (current->cmd_dep & 0x00ffffff);
-
- current->cmd_dep = val;
+ dma_memory_read(&address_space_memory, addr, &current->cmd_dep, len);
if (conditional_wait(ch))
goto wait;
@@ -379,9 +381,9 @@ static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
uint16_t len)
{
dbdma_cmd *current = &ch->current;
- uint32_t val;
- DBDMA_DPRINTF("store_word\n");
+ DBDMA_DPRINTFCH(ch, "store_word %d bytes, addr=%08x pa=%x\n",
+ len, addr, le32_to_cpu(current->cmd_dep));
/* only implements KEY_SYSTEM */
@@ -391,13 +393,7 @@ static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
return;
}
- val = current->cmd_dep;
- if (len == 2)
- val >>= 16;
- else if (len == 1)
- val >>= 24;
-
- cpu_physical_memory_write(addr, &val, len);
+ dma_memory_write(&address_space_memory, addr, &current->cmd_dep, len);
if (conditional_wait(ch))
goto wait;
@@ -444,7 +440,7 @@ static void channel_run(DBDMA_channel *ch)
uint16_t req_count;
uint32_t phy_addr;
- DBDMA_DPRINTF("channel_run\n");
+ DBDMA_DPRINTFCH(ch, "channel_run\n");
dump_dbdma_cmd(current);
/* clear WAKE flag at command fetch */
@@ -538,9 +534,9 @@ static void DBDMA_run_bh(void *opaque)
{
DBDMAState *s = opaque;
- DBDMA_DPRINTF("DBDMA_run_bh\n");
-
+ DBDMA_DPRINTF("-> DBDMA_run_bh\n");
DBDMA_run(s);
+ DBDMA_DPRINTF("<- DBDMA_run_bh\n");
}
void DBDMA_kick(DBDMAState *dbdma)
@@ -555,7 +551,7 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
DBDMAState *s = dbdma;
DBDMA_channel *ch = &s->channels[nchan];
- DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan);
+ DBDMA_DPRINTFCH(ch, "DBDMA_register_channel 0x%x\n", nchan);
assert(rw);
assert(flush);
@@ -599,7 +595,7 @@ dbdma_control_write(DBDMA_channel *ch)
status &= ~FLUSH;
}
- DBDMA_DPRINTF(" status 0x%08x\n", status);
+ DBDMA_DPRINTFCH(ch, " status 0x%08x\n", status);
ch->regs[DBDMA_STATUS] = status;
@@ -616,10 +612,10 @@ static void dbdma_write(void *opaque, hwaddr addr,
DBDMA_channel *ch = &s->channels[channel];
int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
- DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n",
- addr, value);
- DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
- (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
+ DBDMA_DPRINTFCH(ch, "writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n",
+ addr, value);
+ DBDMA_DPRINTFCH(ch, "channel 0x%x reg 0x%x\n",
+ (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
/* cmdptr cannot be modified if channel is ACTIVE */
@@ -670,9 +666,9 @@ static uint64_t dbdma_read(void *opaque, hwaddr addr,
value = ch->regs[reg];
- DBDMA_DPRINTF("readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
- DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
- (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
+ DBDMA_DPRINTFCH(ch, "readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
+ DBDMA_DPRINTFCH(ch, "channel 0x%x reg 0x%x\n",
+ (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
switch(reg) {
case DBDMA_CONTROL:
@@ -782,13 +778,24 @@ static void dbdma_unassigned_rw(DBDMA_io *io)
DBDMA_channel *ch = io->channel;
qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
__func__, ch->channel);
+ ch->io.processing = false;
}
static void dbdma_unassigned_flush(DBDMA_io *io)
{
DBDMA_channel *ch = io->channel;
+ dbdma_cmd *current = &ch->current;
+ uint16_t cmd;
qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n",
__func__, ch->channel);
+
+ cmd = le16_to_cpu(current->command) & COMMAND_MASK;
+ if (cmd == OUTPUT_MORE || cmd == OUTPUT_LAST ||
+ cmd == INPUT_MORE || cmd == INPUT_LAST) {
+ current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS] | FLUSH);
+ current->res_count = cpu_to_le16(io->len);
+ dbdma_cmdptr_save(ch);
+ }
}
void* DBDMA_init (MemoryRegion **dbdma_mem)