z180: DMA fixes [R. Belmont]

- Count of 0 means 0x10000, as with other DMA controllers
- Fixed scheduling so burst mode DMA is always serviced immediately with no CPU ops interleaved
This commit is contained in:
arbee 2017-03-05 10:34:05 -05:00
parent 3c49610274
commit 18d4f730cf

View File

@ -1479,9 +1479,13 @@ void z180_device::z180_writecontrol(offs_t port, uint8_t data)
LOG(("Z180 '%s' DSTAT wr $%02x ($%02x)\n", tag(), data, data & Z180_DSTAT_WMASK)); LOG(("Z180 '%s' DSTAT wr $%02x ($%02x)\n", tag(), data, data & Z180_DSTAT_WMASK));
IO_DSTAT = (IO_DSTAT & ~Z180_DSTAT_WMASK) | (data & Z180_DSTAT_WMASK); IO_DSTAT = (IO_DSTAT & ~Z180_DSTAT_WMASK) | (data & Z180_DSTAT_WMASK);
if ((data & (Z180_DSTAT_DE1 | Z180_DSTAT_DWE1)) == Z180_DSTAT_DE1) if ((data & (Z180_DSTAT_DE1 | Z180_DSTAT_DWE1)) == Z180_DSTAT_DE1)
{
IO_DSTAT |= Z180_DSTAT_DME; /* DMA enable */ IO_DSTAT |= Z180_DSTAT_DME; /* DMA enable */
}
if ((data & (Z180_DSTAT_DE0 | Z180_DSTAT_DWE0)) == Z180_DSTAT_DE0) if ((data & (Z180_DSTAT_DE0 | Z180_DSTAT_DWE0)) == Z180_DSTAT_DE0)
{
IO_DSTAT |= Z180_DSTAT_DME; /* DMA enable */ IO_DSTAT |= Z180_DSTAT_DME; /* DMA enable */
}
break; break;
case Z180_DMODE: case Z180_DMODE:
@ -1569,12 +1573,17 @@ int z180_device::z180_dma0(int max_cycles)
offs_t sar0 = 65536 * IO_SAR0B + 256 * IO_SAR0H + IO_SAR0L; offs_t sar0 = 65536 * IO_SAR0B + 256 * IO_SAR0H + IO_SAR0L;
offs_t dar0 = 65536 * IO_DAR0B + 256 * IO_DAR0H + IO_DAR0L; offs_t dar0 = 65536 * IO_DAR0B + 256 * IO_DAR0H + IO_DAR0L;
int bcr0 = 256 * IO_BCR0H + IO_BCR0L; int bcr0 = 256 * IO_BCR0H + IO_BCR0L;
int count = (IO_DMODE & Z180_DMODE_MMOD) ? bcr0 : 1;
int cycles = 0;
if (bcr0 == 0) if (bcr0 == 0)
{ {
IO_DSTAT &= ~Z180_DSTAT_DE0; bcr0 = 0x10000;
}
int count = (IO_DMODE & Z180_DMODE_MMOD) ? bcr0 : 1;
int cycles = 0;
if (!(IO_DSTAT & Z180_DSTAT_DE0))
{
return 0; return 0;
} }
@ -1701,15 +1710,19 @@ int z180_device::z180_dma1()
offs_t mar1 = 65536 * IO_MAR1B + 256 * IO_MAR1H + IO_MAR1L; offs_t mar1 = 65536 * IO_MAR1B + 256 * IO_MAR1H + IO_MAR1L;
offs_t iar1 = 256 * IO_IAR1H + IO_IAR1L; offs_t iar1 = 256 * IO_IAR1H + IO_IAR1L;
int bcr1 = 256 * IO_BCR1H + IO_BCR1L; int bcr1 = 256 * IO_BCR1H + IO_BCR1L;
if (bcr1 == 0)
{
bcr1 = 0x10000;
}
int cycles = 0; int cycles = 0;
if ((m_iol & Z180_DREQ1) == 0) if ((m_iol & Z180_DREQ1) == 0)
return 0; return 0;
/* counter is zero? */ if (!(IO_DSTAT & Z180_DSTAT_DE1))
if (bcr1 == 0)
{ {
IO_DSTAT &= ~Z180_DSTAT_DE1;
return 0; return 0;
} }
@ -2401,6 +2414,11 @@ again:
handle_io_timers(curcycles); handle_io_timers(curcycles);
/* if channel 0 was started in burst mode, go recheck the mode */
if ((IO_DSTAT & Z180_DSTAT_DE0) == Z180_DSTAT_DE0 &&
(IO_DMODE & Z180_DMODE_MMOD) == Z180_DMODE_MMOD)
goto again;
/* FIXME: /* FIXME:
* For simultaneous DREQ0 and DREQ1 requests, channel 0 has priority * For simultaneous DREQ0 and DREQ1 requests, channel 0 has priority
* over channel 1. When channel 0 is performing a memory to/from memory * over channel 1. When channel 0 is performing a memory to/from memory
@ -2428,6 +2446,10 @@ again:
{ {
do do
{ {
/* If DMA is started go to check the mode */
if ((IO_DSTAT & Z180_DSTAT_DME) == Z180_DSTAT_DME)
goto again;
curcycles = check_interrupts(); curcycles = check_interrupts();
m_icount -= curcycles; m_icount -= curcycles;
handle_io_timers(curcycles); handle_io_timers(curcycles);
@ -2448,10 +2470,6 @@ again:
m_icount -= curcycles; m_icount -= curcycles;
handle_io_timers(curcycles); handle_io_timers(curcycles);
/* If DMA is started go to check the mode */
if ((IO_DSTAT & Z180_DSTAT_DME) == Z180_DSTAT_DME)
goto again;
} while( m_icount > 0 ); } while( m_icount > 0 );
} }
} }