summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/powerpc
diff options
context:
space:
mode:
author Ville Linde <villelin@mamedev.org>2012-07-30 22:20:30 +0000
committer Ville Linde <villelin@mamedev.org>2012-07-30 22:20:30 +0000
commit6c8cba3503cb4f22816a43e4679cafc64e62b441 (patch)
tree71d5b67dff4c51434769597c3d72a4910e81c4bd /src/emu/cpu/powerpc
parent9eaa7414e71a2ba6824b4bfbda4e9df94fc62905 (diff)
ppc: Added callbacks for buffered external DMAs. [Ville Linde]
Diffstat (limited to 'src/emu/cpu/powerpc')
-rw-r--r--src/emu/cpu/powerpc/ppc.h4
-rw-r--r--src/emu/cpu/powerpc/ppccom.c119
-rw-r--r--src/emu/cpu/powerpc/ppccom.h3
3 files changed, 125 insertions, 1 deletions
diff --git a/src/emu/cpu/powerpc/ppc.h b/src/emu/cpu/powerpc/ppc.h
index 50f9612f203..d4e3257b029 100644
--- a/src/emu/cpu/powerpc/ppc.h
+++ b/src/emu/cpu/powerpc/ppc.h
@@ -173,6 +173,8 @@ struct _powerpc_config
};
typedef void (*ppc_dcstore_handler)(device_t *device, UINT32 address);
+typedef UINT32 (*ppc4xx_dma_read_handler)(device_t *device, int width);
+typedef void (*ppc4xx_dma_write_handler)(device_t *device, int width, UINT32 data);
/***************************************************************************
@@ -187,6 +189,8 @@ void ppc4xx_spu_set_tx_handler(device_t *device, ppc4xx_spu_tx_handler handler);
void ppc4xx_spu_receive_byte(device_t *device, UINT8 byteval);
void ppc_set_dcstore_callback(device_t *device, ppc_dcstore_handler handler);
+void ppc4xx_set_dma_read_handler(device_t *device, int channel, ppc4xx_dma_read_handler handler);
+void ppc4xx_set_dma_write_handler(device_t *device, int channel, ppc4xx_dma_write_handler handler);
DECLARE_LEGACY_CPU_DEVICE(PPC403GA, ppc403ga);
diff --git a/src/emu/cpu/powerpc/ppccom.c b/src/emu/cpu/powerpc/ppccom.c
index 4fcf36bca33..bcf132910da 100644
--- a/src/emu/cpu/powerpc/ppccom.c
+++ b/src/emu/cpu/powerpc/ppccom.c
@@ -1856,7 +1856,102 @@ static void ppc4xx_dma_exec(powerpc_state *ppc, int dmachan)
{
/* buffered mode DMA */
case 0:
- /* nothing to do; this happens asynchronously and is driven by the SPU */
+ if (((dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_PL) >> 28) == 0)
+ {
+ /* buffered DMA with external peripheral */
+
+ width = dma_transfer_width[(dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_PW_MASK) >> 26];
+ destinc = (dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_DAI) ? width : 0;
+
+ if (dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_TD)
+ {
+ /* peripheral to memory */
+
+ switch (width)
+ {
+ /* byte transfer */
+ case 1:
+ do
+ {
+ UINT8 data = 0;
+ if (ppc->ext_dma_read_handler[dmachan] != NULL)
+ data = (*ppc->ext_dma_read_handler[dmachan])(ppc->device, 1);
+ ppc->program->write_byte(dmaregs[DCR4XX_DMADA0], data);
+ dmaregs[DCR4XX_DMADA0] += destinc;
+ } while (!ppc4xx_dma_decrement_count(ppc, dmachan));
+ break;
+
+ /* word transfer */
+ case 2:
+ do
+ {
+ UINT16 data = 0;
+ if (ppc->ext_dma_read_handler[dmachan] != NULL)
+ data = (*ppc->ext_dma_read_handler[dmachan])(ppc->device, 2);
+ ppc->program->write_word(dmaregs[DCR4XX_DMADA0], data);
+ dmaregs[DCR4XX_DMADA0] += destinc;
+ } while (!ppc4xx_dma_decrement_count(ppc, dmachan));
+ break;
+
+ /* dword transfer */
+ case 4:
+ do
+ {
+ UINT32 data = 0;
+ if (ppc->ext_dma_read_handler[dmachan] != NULL)
+ data = (*ppc->ext_dma_read_handler[dmachan])(ppc->device, 4);
+ ppc->program->write_dword(dmaregs[DCR4XX_DMADA0], data);
+ dmaregs[DCR4XX_DMADA0] += destinc;
+ } while (!ppc4xx_dma_decrement_count(ppc, dmachan));
+ break;
+ }
+ }
+ else
+ {
+ /* memory to peripheral */
+
+ // data is read from destination address!
+ switch (width)
+ {
+ /* byte transfer */
+ case 1:
+ do
+ {
+ UINT8 data = ppc->program->read_byte(dmaregs[DCR4XX_DMADA0]);
+ if (ppc->ext_dma_write_handler[dmachan] != NULL)
+ (*ppc->ext_dma_write_handler[dmachan])(ppc->device, 1, data);
+ dmaregs[DCR4XX_DMADA0] += destinc;
+ } while (!ppc4xx_dma_decrement_count(ppc, dmachan));
+ break;
+
+ /* word transfer */
+ case 2:
+ do
+ {
+ UINT16 data = ppc->program->read_word(dmaregs[DCR4XX_DMADA0]);
+ if (ppc->ext_dma_write_handler[dmachan] != NULL)
+ (*ppc->ext_dma_write_handler[dmachan])(ppc->device, 2, data);
+ dmaregs[DCR4XX_DMADA0] += destinc;
+ } while (!ppc4xx_dma_decrement_count(ppc, dmachan));
+ break;
+
+ /* dword transfer */
+ case 4:
+ do
+ {
+ UINT32 data = ppc->program->read_dword(dmaregs[DCR4XX_DMADA0]);
+ if (ppc->ext_dma_write_handler[dmachan] != NULL)
+ (*ppc->ext_dma_write_handler[dmachan])(ppc->device, 4, data);
+ dmaregs[DCR4XX_DMADA0] += destinc;
+ } while (!ppc4xx_dma_decrement_count(ppc, dmachan));
+ break;
+ }
+ }
+ }
+ else /* buffered DMA with internal peripheral (SPU) */
+ {
+ /* nothing to do; this happens asynchronously and is driven by the SPU */
+ }
break;
/* fly-by mode DMA */
@@ -2260,6 +2355,28 @@ void ppc4xx_spu_receive_byte(device_t *device, UINT8 byteval)
ppc4xx_spu_rx_data(ppc, byteval);
}
+/*-------------------------------------------------
+ ppc4xx_set_dma_read_handler - PowerPC 4XX-
+ specific external DMA read handler configuration
+-------------------------------------------------*/
+
+void ppc4xx_set_dma_read_handler(device_t *device, int channel, ppc4xx_dma_read_handler handler)
+{
+ powerpc_state *ppc = *(powerpc_state **)downcast<legacy_cpu_device *>(device)->token();
+ ppc->ext_dma_read_handler[channel] = handler;
+}
+
+/*-------------------------------------------------
+ ppc4xx_set_dma_write_handler - PowerPC 4XX-
+ specific external DMA write handler configuration
+-------------------------------------------------*/
+
+void ppc4xx_set_dma_write_handler(device_t *device, int channel, ppc4xx_dma_write_handler handler)
+{
+ powerpc_state *ppc = *(powerpc_state **)downcast<legacy_cpu_device *>(device)->token();
+ ppc->ext_dma_write_handler[channel] = handler;
+}
+
/*-------------------------------------------------
ppc4xx_set_info - PowerPC 4XX-specific
diff --git a/src/emu/cpu/powerpc/ppccom.h b/src/emu/cpu/powerpc/ppccom.h
index c72a5f48cb1..fa42265bc27 100644
--- a/src/emu/cpu/powerpc/ppccom.h
+++ b/src/emu/cpu/powerpc/ppccom.h
@@ -571,6 +571,9 @@ struct _powerpc_state
write32_device_func dcr_write_func;
ppc_dcstore_handler dcstore_handler;
+
+ ppc4xx_dma_read_handler ext_dma_read_handler[4];
+ ppc4xx_dma_write_handler ext_dma_write_handler[4];
};