summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Ryan Holtz <rholtz@batcountryentertainment.com>2010-08-26 17:48:39 +0000
committer Ryan Holtz <rholtz@batcountryentertainment.com>2010-08-26 17:48:39 +0000
commit2f94dc89663db74b15b2860e4a055d7dc5ff0225 (patch)
treeb2bc4a5b1d5b27be90d4557ab313366365c29fcb
parentf0fa05178b291085dab9862cf0f4bcb838098c93 (diff)
Updated the i8237 DMA device to no longer be legacy. [Harmony]
Non-whatsnew note: I tested filetto, seems to still work properly.
-rw-r--r--src/emu/machine/8237dma.c640
-rw-r--r--src/emu/machine/8237dma.h165
2 files changed, 461 insertions, 344 deletions
diff --git a/src/emu/machine/8237dma.c b/src/emu/machine/8237dma.c
index 880400c9396..0dbeca7b2d8 100644
--- a/src/emu/machine/8237dma.c
+++ b/src/emu/machine/8237dma.c
@@ -21,74 +21,11 @@
#include "emu.h"
#include "memconv.h"
#include "8237dma.h"
+#include "devhelpr.h"
-
-/* States that the i8237 device can be in */
-typedef enum {
- DMA8237_SI, /* Idle state */
- DMA8237_S0, /* HRQ has been triggered, waiting to receive HLDA */
-// DMA8237_SW, /* Wait state */
-
- /* Normal transfer states */
- DMA8237_S1, /* Output A8-A15; only used when A8-A15 really needs to be output */
- DMA8237_S2, /* Output A0-A7 */
- DMA8237_S3, /* Initiate read; skipped in compressed timing. On the S2->S3 transition DACK is set. */
- DMA8237_S4, /* Perform read/write */
-
- /* Memory to memory transfer states */
- DMA8237_S11, /* Output A8-A15 */
-// DMA8237_S12, /* Output A0-A7 */
-// DMA8237_S13, /* Initiate read */
-// DMA8237_S14, /* Perform read/write */
-// DMA8237_S21, /* Output A8-A15 */
-// DMA8237_S22, /* Output A0-A7 */
-// DMA8237_S23, /* Initiate read */
-// DMA8237_S24, /* Perform read/write */
-} dma8237_state;
-
-
-typedef struct _i8237_t i8237_t;
-struct _i8237_t
-{
- devcb_resolved_write_line out_hrq_func;
- devcb_resolved_write_line out_eop_func;
- devcb_resolved_read8 in_memr_func;
- devcb_resolved_write8 out_memw_func;
-
- emu_timer *timer;
-
- struct
- {
- devcb_resolved_read8 in_ior_func;
- devcb_resolved_write8 out_iow_func;
- devcb_resolved_write_line out_dack_func;
- UINT16 base_address;
- UINT16 base_count;
- UINT16 address;
- UINT16 count;
- UINT8 mode;
- int high_address_changed;
- } chan[4];
-
- UINT32 msb : 1;
- UINT32 eop : 1;
- UINT8 temp;
- UINT8 temporary_data;
- UINT8 command;
- UINT8 drq;
- UINT8 mask;
- UINT8 hrq;
- UINT8 hlda;
-
- /* bits 0- 3 : Terminal count for channels 0-3
- * bits 4- 7 : Transfer in progress for channels 0-3 */
- UINT8 status;
-
- dma8237_state state; /* State the device is currently in */
- int service_channel; /* Channel we will be servicing */
- int last_service_channel; /* Previous channel we serviced; used to determine channel priority. */
-};
-
+/***************************************************************************
+ MACROS
+***************************************************************************/
#define DMA_MODE_CHANNEL(mode) ((mode) & 0x03)
#define DMA_MODE_OPERATION(mode) ((mode) & 0x0c)
@@ -107,30 +44,126 @@ struct _i8237_t
#define DMA8237_CASCADE_MODE 0xc0
-/* ----------------------------------------------------------------------- */
+//**************************************************************************
+// DEVICE CONFIGURATION
+//**************************************************************************
+
+GENERIC_DEVICE_CONFIG_SETUP(i8237, "I8237")
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
-INLINE i8237_t *get_safe_token(running_device *device) {
- assert( device != NULL );
- assert( device->type() == I8237 );
- return ( i8237_t *) downcast<legacy_device_base *>(device)->token();
+void i8237_device_config::device_config_complete()
+{
+ // inherit a copy of the static data
+ const i8237_interface *intf = reinterpret_cast<const i8237_interface *>(static_config());
+ if (intf != NULL)
+ {
+ *static_cast<i8237_interface *>(this) = *intf;
+ }
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_hrq_func, 0, sizeof(m_out_hrq_func));
+ memset(&m_out_eop_func, 0, sizeof(m_out_eop_func));
+ memset(&m_in_memr_func, 0, sizeof(m_in_memr_func));
+ memset(&m_out_memw_func, 0, sizeof(m_out_memw_func));
+ memset(&m_in_ior_func[0], 0, sizeof(m_in_ior_func[0]));
+ memset(&m_in_ior_func[1], 0, sizeof(m_in_ior_func[1]));
+ memset(&m_in_ior_func[2], 0, sizeof(m_in_ior_func[2]));
+ memset(&m_in_ior_func[3], 0, sizeof(m_in_ior_func[3]));
+ memset(&m_out_iow_func[0], 0, sizeof(m_out_iow_func[0]));
+ memset(&m_out_iow_func[1], 0, sizeof(m_out_iow_func[1]));
+ memset(&m_out_iow_func[2], 0, sizeof(m_out_iow_func[2]));
+ memset(&m_out_iow_func[3], 0, sizeof(m_out_iow_func[3]));
+ memset(&m_out_dack_func[0], 0, sizeof(m_out_dack_func[0]));
+ memset(&m_out_dack_func[1], 0, sizeof(m_out_dack_func[1]));
+ memset(&m_out_dack_func[2], 0, sizeof(m_out_dack_func[2]));
+ memset(&m_out_dack_func[3], 0, sizeof(m_out_dack_func[3]));
+ }
}
-/* ----------------------------------------------------------------------- */
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+const device_type I8237 = i8237_device_config::static_alloc_device_config;
-INLINE void dma8237_do_read( running_device *device )
+//-------------------------------------------------
+// i8237_device - constructor
+//-------------------------------------------------
+
+i8237_device::i8237_device(running_machine &_machine, const i8237_device_config &config)
+ : device_t(_machine, config),
+ m_config(config)
+{
+
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void i8237_device::device_start()
{
- i8237_t *i8237 = get_safe_token( device );
- int channel = i8237->service_channel;
+ /* resolve callbacks */
+ devcb_resolve_write_line(&m_out_hrq_func, &m_config.m_out_hrq_func, this);
+ devcb_resolve_write_line(&m_out_eop_func, &m_config.m_out_eop_func, this);
+ devcb_resolve_read8(&m_in_memr_func, &m_config.m_in_memr_func, this);
+ devcb_resolve_write8(&m_out_memw_func, &m_config.m_out_memw_func, this);
- switch( DMA_MODE_OPERATION( i8237->chan[ channel ].mode ) )
+ for (int i = 0; i < 4; i++)
+ {
+ devcb_resolve_read8(&m_chan[i].m_in_ior_func, &m_config.m_in_ior_func[i], this);
+ devcb_resolve_write8(&m_chan[i].m_out_iow_func, &m_config.m_out_iow_func[i], this);
+ devcb_resolve_write_line(&m_chan[i].m_out_dack_func, &m_config.m_out_dack_func[i], this);
+ }
+
+ m_timer = timer_alloc(&m_machine, i8237_timerproc_callback, (void *)this);
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void i8237_device::device_reset()
+{
+ m_status = 0x0F;
+ m_eop = 1;
+ m_state = DMA8237_SI;
+ m_last_service_channel = 3;
+
+ m_mask = 0x00;
+ m_status = 0x0F;
+ m_hrq = 0;
+ m_hlda = 0;
+ m_chan[0].m_mode = 0;
+ m_chan[1].m_mode = 0;
+ m_chan[2].m_mode = 0;
+ m_chan[3].m_mode = 0;
+
+ timer_adjust_periodic(m_timer, ATTOTIME_IN_HZ(clock()), 0, ATTOTIME_IN_HZ(clock()));
+}
+
+
+void i8237_device::i8237_do_read()
+{
+ int channel = m_service_channel;
+
+ switch( DMA_MODE_OPERATION( m_chan[ channel ].m_mode ) )
{
case DMA8237_WRITE_TRANSFER:
- i8237->temporary_data = devcb_call_read8(&i8237->chan[channel].in_ior_func, 0);
+ m_temporary_data = devcb_call_read8(&m_chan[channel].m_in_ior_func, 0);
break;
case DMA8237_READ_TRANSFER:
- i8237->temporary_data = devcb_call_read8(&i8237->in_memr_func, i8237->chan[ channel ].address);
+ m_temporary_data = devcb_call_read8(&m_in_memr_func, m_chan[ channel ].m_address);
break;
case DMA8237_VERIFY_TRANSFER:
case DMA8237_ILLEGAL_TRANSFER:
@@ -139,18 +172,17 @@ INLINE void dma8237_do_read( running_device *device )
}
-INLINE void dma8237_do_write( running_device *device )
+void i8237_device::i8237_do_write()
{
- i8237_t *i8237 = get_safe_token( device );
- int channel = i8237->service_channel;
+ int channel = m_service_channel;
- switch( DMA_MODE_OPERATION( i8237->chan[ channel ].mode ) )
+ switch( DMA_MODE_OPERATION( m_chan[ channel ].m_mode ) )
{
case DMA8237_WRITE_TRANSFER:
- devcb_call_write8(&i8237->out_memw_func, i8237->chan[ channel ].address, i8237->temporary_data);
+ devcb_call_write8(&m_out_memw_func, m_chan[ channel ].m_address, m_temporary_data);
break;
case DMA8237_READ_TRANSFER:
- devcb_call_write8(&i8237->chan[channel].out_iow_func, 0, i8237->temporary_data);
+ devcb_call_write8(&m_chan[channel].m_out_iow_func, 0, m_temporary_data);
break;
case DMA8237_VERIFY_TRANSFER:
case DMA8237_ILLEGAL_TRANSFER:
@@ -159,235 +191,252 @@ INLINE void dma8237_do_write( running_device *device )
}
-INLINE void dma8237_advance( running_device *device )
+void i8237_device::i8237_advance()
{
- i8237_t *i8237 = get_safe_token( device );
- int channel = i8237->service_channel;
- int mode = i8237->chan[channel].mode;
+ int channel = m_service_channel;
+ int mode = m_chan[channel].m_mode;
switch ( DMA_MODE_OPERATION( mode ) )
{
case DMA8237_VERIFY_TRANSFER:
case DMA8237_WRITE_TRANSFER:
case DMA8237_READ_TRANSFER:
- i8237->chan[channel].high_address_changed = 0;
+ m_chan[channel].m_high_address_changed = 0;
if ( DMA_MODE_DIRECTION( mode ) )
{
- i8237->chan[channel].address -= 1;
- if ( ( i8237->chan[channel].address & 0xFF ) == 0xFF )
- i8237->chan[channel].high_address_changed = 1;
+ m_chan[channel].m_address -= 1;
+ if ( ( m_chan[channel].m_address & 0xFF ) == 0xFF )
+ {
+ m_chan[channel].m_high_address_changed = 1;
+ }
}
else
{
- i8237->chan[channel].address += 1;
- if ( ( i8237->chan[channel].address & 0xFF ) == 0x00 )
- i8237->chan[channel].high_address_changed = 1;
+ m_chan[channel].m_address += 1;
+ if ( ( m_chan[channel].m_address & 0xFF ) == 0x00 )
+ {
+ m_chan[channel].m_high_address_changed = 1;
+ }
}
- i8237->chan[channel].count--;
+ m_chan[channel].m_count--;
- if ( i8237->chan[channel].count == 0xFFFF )
+ if ( m_chan[channel].m_count == 0xFFFF )
{
/* Set TC bit for this channel */
- i8237->status |= ( 0x01 << channel );
+ m_status |= ( 0x01 << channel );
if ( DMA_MODE_AUTO_INIT( mode ) )
{
- i8237->chan[channel].address = i8237->chan[channel].base_address;
- i8237->chan[channel].count = i8237->chan[channel].base_count;
- i8237->chan[channel].high_address_changed = 1;
+ m_chan[channel].m_address = m_chan[channel].m_base_address;
+ m_chan[channel].m_count = m_chan[channel].m_base_count;
+ m_chan[channel].m_high_address_changed = 1;
}
else
{
- i8237->mask |= ( 0x01 << channel );
+ m_mask |= ( 0x01 << channel );
}
}
break;
case DMA8237_ILLEGAL_TRANSFER:
break;
}
-
}
-static void set_dack(i8237_t *i8237, int channel)
-{
- int i;
- for (i = 0; i < 4; i++)
+void i8237_device::set_dack(int channel)
+{
+ for (int i = 0; i < 4; i++)
{
- int state = (i == channel) ^ !BIT(i8237->command, 7);
+ int state = (i == channel) ^ !BIT(m_command, 7);
- devcb_call_write_line(&i8237->chan[i].out_dack_func, state);
+ devcb_call_write_line(&m_chan[i].m_out_dack_func, state);
}
}
-static TIMER_CALLBACK( dma8237_timerproc )
+
+TIMER_CALLBACK( i8237_device::i8237_timerproc_callback )
{
- running_device *device = (running_device *)ptr;
- i8237_t *i8237 = get_safe_token(device);
+ reinterpret_cast<i8237_device*>(ptr)->i8237_timerproc();
+}
+
+void i8237_device::i8237_timerproc()
+{
/* Check if operation is disabled */
- if ( i8237->command & 0x04 )
+ if ( m_command & 0x04 )
+ {
return;
+ }
- switch ( i8237->state ) {
+ switch ( m_state )
+ {
case DMA8237_SI:
+ {
/* Make sure EOP is high */
- if ( ! i8237->eop )
+ if ( !m_eop )
{
- i8237->eop = 1;
- devcb_call_write_line(&i8237->out_eop_func, i8237->eop ? ASSERT_LINE : CLEAR_LINE);
+ m_eop = 1;
+ devcb_call_write_line(&m_out_eop_func, m_eop ? ASSERT_LINE : CLEAR_LINE);
}
/* Check if a new DMA request has been received. */
+ /* Bit 6 of the command register determines whether the DREQ signals are active
+ high or active low. */
+ UINT16 pending_request = ( ( m_command & 0x40 ) ? ~m_drq : m_drq ) & ~m_mask;
+
+ if ( pending_request & 0x0f )
{
- /* Bit 6 of the command register determines whether the DREQ signals are active
- high or active low. */
- UINT16 pending_request = ( ( i8237->command & 0x40 ) ? ~i8237->drq : i8237->drq ) & ~i8237->mask;
+ int prio_channel = 0;
- if ( pending_request & 0x0f )
+ /* Determine the channel that should be serviced */
+ int channel = ( m_command & 0x10 ) ? m_last_service_channel : 3;
+ for ( int i = 0; i < 4; i++ )
{
- int i, channel, prio_channel = 0;
-
- /* Determine the channel that should be serviced */
- channel = ( i8237->command & 0x10 ) ? i8237->last_service_channel : 3;
- for ( i = 0; i < 4; i++ )
+ if ( pending_request & ( 1 << channel ) )
{
- if ( pending_request & ( 1 << channel ) )
- prio_channel = channel;
- channel = ( channel - 1 ) & 0x03;
+ prio_channel = channel;
}
+ channel = ( channel - 1 ) & 0x03;
+ }
- /* Store the channel we will be servicing and go to the next state */
- i8237->service_channel = prio_channel;
- i8237->last_service_channel = prio_channel;
- i8237->hrq = 1;
- devcb_call_write_line(&i8237->out_hrq_func, i8237->hrq);
- i8237->state = DMA8237_S0;
+ /* Store the channel we will be servicing and go to the next state */
+ m_service_channel = prio_channel;
+ m_last_service_channel = prio_channel;
+ m_hrq = 1;
+ devcb_call_write_line(&m_out_hrq_func, m_hrq);
+ m_state = DMA8237_S0;
- timer_enable( i8237->timer, 1 );
- }
- else
- {
- timer_enable( i8237->timer, 0 );
- }
+ timer_enable( m_timer, 1 );
+ }
+ else
+ {
+ timer_enable( m_timer, 0 );
}
break;
+ }
case DMA8237_S0:
/* S0 is the first of the DMA service. We have requested a hold but are waiting
for confirmation. */
- if ( i8237->hlda )
+ if ( m_hlda )
{
- if ( i8237->command & 0x01 )
+ if ( m_command & 0x01 )
{
/* Memory-to-memory transfers */
- i8237->state = DMA8237_S11;
+ m_state = DMA8237_S11;
}
else
{
/* Regular transfers */
- i8237->state = DMA8237_S1;
+ m_state = DMA8237_S1;
}
}
break;
case DMA8237_S1: /* Output A8-A15 */
- i8237->state = DMA8237_S2;
+ m_state = DMA8237_S2;
break;
case DMA8237_S2: /* Output A7-A0 */
/* set DACK */
- set_dack(i8237, i8237->service_channel);
+ set_dack(m_service_channel);
/* Check for compressed timing */
- if ( i8237->command & 0x08 )
- i8237->state = DMA8237_S4;
+ if ( m_command & 0x08 )
+ {
+ m_state = DMA8237_S4;
+ }
else
- i8237->state = DMA8237_S3;
+ {
+ m_state = DMA8237_S3;
+ }
break;
case DMA8237_S3: /* Initiate read */
- dma8237_do_read( device );
- i8237->state = DMA8237_S4;
+ i8237_do_read();
+ m_state = DMA8237_S4;
break;
case DMA8237_S4: /* Perform read/write */
/* Perform read when in compressed timing mode */
- if ( i8237->command & 0x08 )
- dma8237_do_read( device );
+ if ( m_command & 0x08 )
+ {
+ i8237_do_read();
+ }
/* Perform write */
- dma8237_do_write( device );
+ i8237_do_write();
+
/* Advance */
- dma8237_advance( device );
+ i8237_advance();
{
- int channel = i8237->service_channel;
+ int channel = m_service_channel;
- switch( DMA_MODE_TRANSFERMODE( i8237->chan[channel].mode ) )
+ switch( DMA_MODE_TRANSFERMODE( m_chan[channel].m_mode ) )
{
case DMA8237_DEMAND_MODE:
/* Check for terminal count or EOP signal or DREQ begin de-asserted */
- if ( ( i8237->status & ( 0x01 << channel ) ) || ! i8237->eop || ! ( i8237->drq & ( 0x01 << channel ) ) )
+ if ( ( m_status & ( 0x01 << channel ) ) || !m_eop || !( m_drq & ( 0x01 << channel ) ) )
{
- i8237->hrq = 0;
- i8237->hlda = 0;
- devcb_call_write_line(&i8237->out_hrq_func, i8237->hrq);
- i8237->state = DMA8237_SI;
+ m_hrq = 0;
+ m_hlda = 0;
+ devcb_call_write_line(&m_out_hrq_func, m_hrq);
+ m_state = DMA8237_SI;
}
else
{
- i8237->state = i8237->chan[channel].high_address_changed ? DMA8237_S1 : DMA8237_S2;
+ m_state = m_chan[channel].m_high_address_changed ? DMA8237_S1 : DMA8237_S2;
}
break;
case DMA8237_SINGLE_MODE:
- i8237->hrq = 0;
- i8237->hlda = 0;
- devcb_call_write_line(&i8237->out_hrq_func, i8237->hrq);
- i8237->state = DMA8237_SI;
+ m_hrq = 0;
+ m_hlda = 0;
+ devcb_call_write_line(&m_out_hrq_func, m_hrq);
+ m_state = DMA8237_SI;
break;
case DMA8237_BLOCK_MODE:
/* Check for terminal count or EOP signal */
- if ( ( i8237->status & ( 0x01 << channel ) ) || ! i8237->eop )
+ if ( ( m_status & ( 0x01 << channel ) ) || !m_eop )
{
- i8237->hrq = 0;
- i8237->hlda = 0;
- devcb_call_write_line(&i8237->out_hrq_func, i8237->hrq);
- i8237->state = DMA8237_SI;
+ m_hrq = 0;
+ m_hlda = 0;
+ devcb_call_write_line(&m_out_hrq_func, m_hrq);
+ m_state = DMA8237_SI;
}
else
{
- i8237->state = i8237->chan[channel].high_address_changed ? DMA8237_S1 : DMA8237_S2;
+ m_state = m_chan[channel].m_high_address_changed ? DMA8237_S1 : DMA8237_S2;
}
break;
case DMA8237_CASCADE_MODE:
- if ( ! ( i8237->drq & ( 0x01 << channel ) ) )
+ if ( ! ( m_drq & ( 0x01 << channel ) ) )
{
- i8237->hrq = 0;
- i8237->hlda = 0;
- devcb_call_write_line(&i8237->out_hrq_func, i8237->hrq);
- i8237->state = DMA8237_SI;
+ m_hrq = 0;
+ m_hlda = 0;
+ devcb_call_write_line(&m_out_hrq_func, m_hrq);
+ m_state = DMA8237_SI;
}
break;
}
/* Check if EOP output needs to be asserted */
- if ( i8237->status & ( 0x01 << channel ) )
+ if ( m_status & ( 0x01 << channel ) )
{
- i8237->eop = 0;
- devcb_call_write_line(&i8237->out_eop_func, i8237->eop ? ASSERT_LINE : CLEAR_LINE);
+ m_eop = 0;
+ devcb_call_write_line(&m_out_eop_func, m_eop ? ASSERT_LINE : CLEAR_LINE);
}
}
/* clear DACK */
- set_dack(i8237, -1);
+ set_dack(-1);
break;
case DMA8237_S11: /* Output A8-A15 */
@@ -396,14 +445,8 @@ static TIMER_CALLBACK( dma8237_timerproc )
}
-
-
-/* ----------------------------------------------------------------------- */
-
-
-READ8_DEVICE_HANDLER( i8237_r )
+READ8_DEVICE_HANDLER_TRAMPOLINE(i8237, i8237_r)
{
- i8237_t *i8237 = get_safe_token(device);
UINT8 data = 0xFF;
offset &= 0x0F;
@@ -414,8 +457,8 @@ READ8_DEVICE_HANDLER( i8237_r )
case 4:
case 6:
/* DMA address register */
- data = i8237->chan[offset / 2].address >> (i8237->msb ? 8 : 0);
- i8237->msb ^= 1;
+ data = m_chan[offset / 2].m_address >> (m_msb ? 8 : 0);
+ m_msb ^= 1;
break;
case 1:
@@ -423,26 +466,26 @@ READ8_DEVICE_HANDLER( i8237_r )
case 5:
case 7:
/* DMA count register */
- data = i8237->chan[offset / 2].count >> (i8237->msb ? 8 : 0);
- i8237->msb ^= 1;
+ data = m_chan[offset / 2].m_count >> (m_msb ? 8 : 0);
+ m_msb ^= 1;
break;
case 8:
/* DMA status register */
- data = (UINT8) i8237->status;
+ data = (UINT8) m_status;
/* TC bits are cleared on a status read */
- i8237->status &= 0xF0;
+ m_status &= 0xF0;
break;
case 10:
/* DMA mask register */
- data = i8237->mask;
+ data = m_mask;
break;
case 13:
/* DMA master clear */
- data = i8237->temp;
+ data = m_temp;
break;
case 9: /* DMA write request register */
@@ -458,12 +501,8 @@ READ8_DEVICE_HANDLER( i8237_r )
}
-
-WRITE8_DEVICE_HANDLER( i8237_w )
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(i8237, i8237_w)
{
- i8237_t *i8237 = get_safe_token(device);
- int channel;
-
offset &= 0x0F;
logerror("i8237_w: offset = %02x, data = %02x\n", offset, data );
@@ -473,205 +512,144 @@ WRITE8_DEVICE_HANDLER( i8237_w )
case 2:
case 4:
case 6:
+ {
/* DMA address register */
- channel = offset / 2;
- if (i8237->msb)
+ int channel = offset / 2;
+ if (m_msb)
{
- i8237->chan[channel].base_address = ( i8237->chan[channel].base_address & 0x00FF ) | ( data << 8 );
- i8237->chan[channel].address = ( i8237->chan[channel].address & 0x00FF ) | ( data << 8 );
+ m_chan[channel].m_base_address = ( m_chan[channel].m_base_address & 0x00FF ) | ( data << 8 );
+ m_chan[channel].m_address = ( m_chan[channel].m_address & 0x00FF ) | ( data << 8 );
}
else
{
- i8237->chan[channel].base_address = ( i8237->chan[channel].base_address & 0xFF00 ) | data;
- i8237->chan[channel].address = ( i8237->chan[channel].address & 0xFF00 ) | data;
+ m_chan[channel].m_base_address = ( m_chan[channel].m_base_address & 0xFF00 ) | data;
+ m_chan[channel].m_address = ( m_chan[channel].m_address & 0xFF00 ) | data;
}
- i8237->msb ^= 1;
+ m_msb ^= 1;
break;
+ }
case 1:
case 3:
case 5:
case 7:
+ {
/* DMA count register */
- channel = offset / 2;
- if (i8237->msb)
+ int channel = offset / 2;
+ if (m_msb)
{
- i8237->chan[channel].base_count = ( i8237->chan[channel].base_count & 0x00FF ) | ( data << 8 );
- i8237->chan[channel].count = ( i8237->chan[channel].count & 0x00FF ) | ( data << 8 );
+ m_chan[channel].m_base_count = ( m_chan[channel].m_base_count & 0x00FF ) | ( data << 8 );
+ m_chan[channel].m_count = ( m_chan[channel].m_count & 0x00FF ) | ( data << 8 );
}
else
{
- i8237->chan[channel].base_count = ( i8237->chan[channel].base_count & 0xFF00 ) | data;
- i8237->chan[channel].count = ( i8237->chan[channel].count & 0xFF00 ) | data;
+ m_chan[channel].m_base_count = ( m_chan[channel].m_base_count & 0xFF00 ) | data;
+ m_chan[channel].m_count = ( m_chan[channel].m_count & 0xFF00 ) | data;
}
- i8237->msb ^= 1;
+ m_msb ^= 1;
break;
+ }
case 8:
/* DMA command register */
- i8237->command = data;
- timer_enable( i8237->timer, ( i8237->command & 0x04 ) ? 0 : 1 );
+ m_command = data;
+ timer_enable( m_timer, ( m_command & 0x04 ) ? 0 : 1 );
break;
case 9:
+ {
/* DMA request register */
- channel = DMA_MODE_CHANNEL(data);
+ int channel = DMA_MODE_CHANNEL(data);
if ( data & 0x04 )
{
- i8237->drq |= 0x01 << channel;
- timer_enable( i8237->timer, ( i8237->command & 0x04 ) ? 0 : 1 );
+ m_drq |= 0x01 << channel;
+ timer_enable( m_timer, ( m_command & 0x04 ) ? 0 : 1 );
}
else
{
- i8237->status &= ~ ( 0x10 << channel );
- i8237->drq &= ~ ( 0x01 << channel );
+ m_status &= ~ ( 0x10 << channel );
+ m_drq &= ~ ( 0x01 << channel );
}
break;
+ }
case 10:
+ {
/* DMA mask register */
- channel = DMA_MODE_CHANNEL(data);
+ int channel = DMA_MODE_CHANNEL(data);
if (data & 0x04)
- i8237->mask |= 0x11 << channel;
+ {
+ m_mask |= 0x11 << channel;
+ }
else
- i8237->mask &= ~(0x11 << channel);
+ {
+ m_mask &= ~(0x11 << channel);
+ }
break;
+ }
case 11:
+ {
/* DMA mode register */
- channel = DMA_MODE_CHANNEL(data);
- i8237->chan[channel].mode = data;
+ int channel = DMA_MODE_CHANNEL(data);
+ m_chan[channel].m_mode = data;
/* Apparently mode writes also clear the TC bit(?) */
- i8237->status &= ~ ( 1 << channel );
+ m_status &= ~ ( 1 << channel );
break;
+ }
case 12:
/* DMA clear byte pointer flip-flop */
- i8237->temp = data;
- i8237->msb = 0;
+ m_temp = data;
+ m_msb = 0;
break;
case 13:
/* DMA master clear */
- i8237->msb = 0;
- i8237->mask = 0x0f;
- i8237->state = DMA8237_SI;
- i8237->status &= 0xF0;
+ m_msb = 0;
+ m_mask = 0x0f;
+ m_state = DMA8237_SI;
+ m_status &= 0xF0;
break;
case 14:
/* DMA clear mask register */
- i8237->mask &= ~data;
- i8237->mask = 0;
+ m_mask &= ~data;
+ m_mask = 0;
break;
case 15:
/* DMA write mask register */
- i8237->mask = data & 0x0f;
+ m_mask = data & 0x0f;
break;
}
}
-
-static void dma8237_drq_write(running_device *device, int channel, int state)
+void i8237_device::i8237_drq_write(int channel, int state)
{
- i8237_t *i8237 = get_safe_token( device );
-
if (state)
- i8237->drq |= ( 0x01 << channel );
+ {
+ m_drq |= ( 0x01 << channel );
+ }
else
- i8237->drq &= ~( 0x01 << channel );
-
- timer_enable( i8237->timer, ( i8237->command & 0x04 ) ? 0 : 1 );
-}
-
-WRITE_LINE_DEVICE_HANDLER( i8237_hlda_w )
-{
- i8237_t *i8237 = get_safe_token( device );
-
- i8237->hlda = state;
-}
-
-WRITE_LINE_DEVICE_HANDLER( i8237_ready_w )
-{
-}
-
-WRITE_LINE_DEVICE_HANDLER( i8237_dreq0_w ) { dma8237_drq_write(device, 0, state); }
-WRITE_LINE_DEVICE_HANDLER( i8237_dreq1_w ) { dma8237_drq_write(device, 1, state); }
-WRITE_LINE_DEVICE_HANDLER( i8237_dreq2_w ) { dma8237_drq_write(device, 2, state); }
-WRITE_LINE_DEVICE_HANDLER( i8237_dreq3_w ) { dma8237_drq_write(device, 3, state); }
-
-WRITE_LINE_DEVICE_HANDLER( i8237_eop_w )
-{
-}
-
-
-static DEVICE_START( i8237 ) {
- i8237_t *i8237 = get_safe_token(device);
- i8237_interface *intf = (i8237_interface *)device->baseconfig().static_config();
- int i;
-
- /* resolve callbacks */
- devcb_resolve_write_line(&i8237->out_hrq_func, &intf->out_hrq_func, device);
- devcb_resolve_write_line(&i8237->out_eop_func, &intf->out_eop_func, device);
- devcb_resolve_read8(&i8237->in_memr_func, &intf->in_memr_func, device);
- devcb_resolve_write8(&i8237->out_memw_func, &intf->out_memw_func, device);
-
- for (i = 0; i < 4; i++)
{
- devcb_resolve_read8(&i8237->chan[i].in_ior_func, &intf->in_ior_func[i], device);
- devcb_resolve_write8(&i8237->chan[i].out_iow_func, &intf->out_iow_func[i], device);
- devcb_resolve_write_line(&i8237->chan[i].out_dack_func, &intf->out_dack_func[i], device);
+ m_drq &= ~( 0x01 << channel );
}
- i8237->timer = timer_alloc(device->machine, dma8237_timerproc, (void *)device);
+ timer_enable( m_timer, ( m_command & 0x04 ) ? 0 : 1 );
}
-static DEVICE_RESET( i8237 ) {
- i8237_t *i8237 = get_safe_token(device);
-
- i8237->status = 0x0F;
- i8237->eop = 1;
- i8237->state = DMA8237_SI;
- i8237->last_service_channel = 3;
-
- i8237->mask = 0x00;
- i8237->status = 0x0F;
- i8237->hrq = 0;
- i8237->hlda = 0;
- i8237->chan[0].mode = 0;
- i8237->chan[1].mode = 0;
- i8237->chan[2].mode = 0;
- i8237->chan[3].mode = 0;
-
- timer_adjust_periodic(i8237->timer,
- ATTOTIME_IN_HZ(device->clock()),
- 0,
- ATTOTIME_IN_HZ(device->clock()));
-}
-
-
-DEVICE_GET_INFO( i8237 ) {
- switch ( state ) {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(i8237_t); break;
- case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(i8237); break;
- case DEVINFO_FCT_STOP: /* nothing */ break;
- case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(i8237); break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case DEVINFO_STR_NAME: strcpy(info->s, "Intel 8237"); break;
- case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel 8080"); break;
- case DEVINFO_STR_VERSION: strcpy(info->s, "1.01"); break;
- case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
- case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright the MAME and MESS Teams"); break;
- }
-}
+/***************************************************************************
+ TRAMPOLINES
+***************************************************************************/
-DEFINE_LEGACY_DEVICE(I8237, i8237);
+WRITE_LINE_DEVICE_HANDLER( i8237_hlda_w ) { downcast<i8237_device*>(device)->i8237_hlda_w(state); }
+WRITE_LINE_DEVICE_HANDLER( i8237_ready_w ) { }
+WRITE_LINE_DEVICE_HANDLER( i8237_dreq0_w ) { downcast<i8237_device*>(device)->i8237_drq_write(0, state); }
+WRITE_LINE_DEVICE_HANDLER( i8237_dreq1_w ) { downcast<i8237_device*>(device)->i8237_drq_write(1, state); }
+WRITE_LINE_DEVICE_HANDLER( i8237_dreq2_w ) { downcast<i8237_device*>(device)->i8237_drq_write(2, state); }
+WRITE_LINE_DEVICE_HANDLER( i8237_dreq3_w ) { downcast<i8237_device*>(device)->i8237_drq_write(3, state); }
+WRITE_LINE_DEVICE_HANDLER( i8237_eop_w ) { }
diff --git a/src/emu/machine/8237dma.h b/src/emu/machine/8237dma.h
index fcdd82c8444..3d10feff977 100644
--- a/src/emu/machine/8237dma.h
+++ b/src/emu/machine/8237dma.h
@@ -30,18 +30,19 @@
***************************************************************************/
+#pragma once
+
#ifndef __I8237__
#define __I8237__
-#include "devlegcy.h"
+#include "emu.h"
+
/***************************************************************************
- MACROS / CONSTANTS
+ DEVICE CONFIGURATION MACROS
***************************************************************************/
-DECLARE_LEGACY_DEVICE(I8237, i8237);
-
#define MDRV_I8237_ADD(_tag, _clock, _config) \
MDRV_DEVICE_ADD(_tag, I8237, _clock) \
MDRV_DEVICE_CONFIG(_config)
@@ -49,26 +50,164 @@ DECLARE_LEGACY_DEVICE(I8237, i8237);
#define I8237_INTERFACE(_name) \
const i8237_interface (_name) =
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
-typedef struct _i8237_interface i8237_interface;
-struct _i8237_interface
+
+// ======================> i8237_interface
+
+struct i8237_interface
{
- devcb_write_line out_hrq_func;
- devcb_write_line out_eop_func;
+ devcb_write_line m_out_hrq_func;
+ devcb_write_line m_out_eop_func;
/* accessors to main memory */
- devcb_read8 in_memr_func;
- devcb_write8 out_memw_func;
+ devcb_read8 m_in_memr_func;
+ devcb_write8 m_out_memw_func;
/* channel accessors */
- devcb_read8 in_ior_func[4];
- devcb_write8 out_iow_func[4];
- devcb_write_line out_dack_func[4];
+ devcb_read8 m_in_ior_func[4];
+ devcb_write8 m_out_iow_func[4];
+ devcb_write_line m_out_dack_func[4];
};
+
+
+// ======================> i8237_device_config
+
+class i8237_device_config : public device_config,
+ public i8237_interface
+{
+ friend class i8237_device;
+
+ // construction/destruction
+ i8237_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
+
+public:
+ // allocators
+ static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
+ virtual device_t *alloc_device(running_machine &machine) const;
+
+protected:
+ // device_config overrides
+ virtual void device_config_complete();
+};
+
+
+
+// ======================> i8237_device
+
+class i8237_device : public device_t
+{
+ friend class i8237_device_config;
+
+ // construction/destruction
+ i8237_device(running_machine &_machine, const i8237_device_config &_config);
+
+public:
+
+ /* register access */
+ UINT8 i8237_r(UINT32 offset);
+ void i8237_w(UINT32 offset, UINT8 data);
+
+ /* hold acknowledge */
+ void i8237_hlda_w(UINT8 state) { m_hlda = state; }
+
+ /* data request */
+ void i8237_drq_write(int channel, int state);
+
+ void i8237_timerproc();
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load() { }
+ virtual void device_clock_changed() { }
+
+ static TIMER_CALLBACK( i8237_timerproc_callback );
+ static TIMER_CALLBACK( receive_event_callback );
+
+private:
+
+ void i8237_do_read();
+ void i8237_do_write();
+ void i8237_advance();
+ void set_dack(int channel);
+
+ /* States that the i8237 device can be in */
+ enum dma8237_state
+ {
+ DMA8237_SI, /* Idle state */
+ DMA8237_S0, /* HRQ has been triggered, waiting to receive HLDA */
+ // DMA8237_SW, /* Wait state */
+
+ /* Normal transfer states */
+ DMA8237_S1, /* Output A8-A15; only used when A8-A15 really needs to be output */
+ DMA8237_S2, /* Output A0-A7 */
+ DMA8237_S3, /* Initiate read; skipped in compressed timing. On the S2->S3 transition DACK is set. */
+ DMA8237_S4, /* Perform read/write */
+
+ /* Memory to memory transfer states */
+ DMA8237_S11, /* Output A8-A15 */
+ // DMA8237_S12, /* Output A0-A7 */
+ // DMA8237_S13, /* Initiate read */
+ // DMA8237_S14, /* Perform read/write */
+ // DMA8237_S21, /* Output A8-A15 */
+ // DMA8237_S22, /* Output A0-A7 */
+ // DMA8237_S23, /* Initiate read */
+ // DMA8237_S24, /* Perform read/write */
+ };
+
+ devcb_resolved_write_line m_out_hrq_func;
+ devcb_resolved_write_line m_out_eop_func;
+ devcb_resolved_read8 m_in_memr_func;
+ devcb_resolved_write8 m_out_memw_func;
+
+ emu_timer *m_timer;
+
+ struct
+ {
+ devcb_resolved_read8 m_in_ior_func;
+ devcb_resolved_write8 m_out_iow_func;
+ devcb_resolved_write_line m_out_dack_func;
+ UINT16 m_base_address;
+ UINT16 m_base_count;
+ UINT16 m_address;
+ UINT16 m_count;
+ UINT8 m_mode;
+ int m_high_address_changed;
+ } m_chan[4];
+
+ UINT32 m_msb : 1;
+ UINT32 m_eop : 1;
+ UINT8 m_temp;
+ UINT8 m_temporary_data;
+ UINT8 m_command;
+ UINT8 m_drq;
+ UINT8 m_mask;
+ UINT8 m_hrq;
+ UINT8 m_hlda;
+
+ /* bits 0- 3 : Terminal count for channels 0-3
+ * bits 4- 7 : Transfer in progress for channels 0-3 */
+ UINT8 m_status;
+
+ dma8237_state m_state; /* State the device is currently in */
+ int m_service_channel; /* Channel we will be servicing */
+ int m_last_service_channel; /* Previous channel we serviced; used to determine channel priority. */
+
+ const i8237_device_config &m_config;
+};
+
+
+// device type definition
+extern const device_type I8237;
+
+
+
/***************************************************************************
PROTOTYPES
***************************************************************************/