summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/z80dma.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/z80dma.cpp')
-rw-r--r--src/devices/machine/z80dma.cpp135
1 files changed, 61 insertions, 74 deletions
diff --git a/src/devices/machine/z80dma.cpp b/src/devices/machine/z80dma.cpp
index 1a347cc2f24..2e0240af8a3 100644
--- a/src/devices/machine/z80dma.cpp
+++ b/src/devices/machine/z80dma.cpp
@@ -26,7 +26,6 @@
#include "emu.h"
#include "z80dma.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_DMA (1U << 1)
//#define VERBOSE (LOG_GENERAL | LOG_DMA)
@@ -46,36 +45,13 @@ enum
INT_MATCH_END_OF_BLOCK
};
-constexpr int COMMAND_RESET = 0xc3;
-constexpr int COMMAND_RESET_PORT_A_TIMING = 0xc7;
-constexpr int COMMAND_RESET_PORT_B_TIMING = 0xcb;
-constexpr int COMMAND_LOAD = 0xcf;
-constexpr int COMMAND_CONTINUE = 0xd3;
-constexpr int COMMAND_DISABLE_INTERRUPTS = 0xaf;
-constexpr int COMMAND_ENABLE_INTERRUPTS = 0xab;
-constexpr int COMMAND_RESET_AND_DISABLE_INTERRUPTS = 0xa3;
-constexpr int COMMAND_ENABLE_AFTER_RETI = 0xb7;
-constexpr int COMMAND_READ_STATUS_BYTE = 0xbf;
-constexpr int COMMAND_REINITIALIZE_STATUS_BYTE = 0x8b;
-constexpr int COMMAND_INITIATE_READ_SEQUENCE = 0xa7;
-constexpr int COMMAND_FORCE_READY = 0xb3;
-constexpr int COMMAND_ENABLE_DMA = 0x87;
-constexpr int COMMAND_DISABLE_DMA = 0x83;
-constexpr int COMMAND_READ_MASK_FOLLOWS = 0xbb;
-
-constexpr int TM_TRANSFER = 0x01;
-constexpr int TM_SEARCH = 0x02;
-constexpr int TM_SEARCH_TRANSFER = 0x03;
-
//**************************************************************************
// MACROS
//**************************************************************************
-#define REGNUM(_m, _s) (((_m)<<3) + (_s))
#define GET_REGNUM(_r) (&(_r) - &(WR0))
-#define REG(_m, _s) m_regs[REGNUM(_m,_s)]
#define WR0 REG(0, 0)
#define WR1 REG(1, 0)
#define WR2 REG(2, 0)
@@ -135,7 +111,7 @@ constexpr int TM_SEARCH_TRANSFER = 0x03;
#define INT_ON_END_OF_BLOCK (INTERRUPT_CTRL & 0x02)
#define INT_ON_READY (INTERRUPT_CTRL & 0x40)
#define STATUS_AFFECTS_VECTOR (INTERRUPT_CTRL & 0x20)
-
+#define PULSE_GENERATED (INTERRUPT_CTRL & 0x04)
//**************************************************************************
@@ -150,15 +126,20 @@ DEFINE_DEVICE_TYPE(Z80DMA, z80dma_device, "z80dma", "Z80 DMA Controller")
//-------------------------------------------------
z80dma_device::z80dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, Z80DMA, tag, owner, clock)
+ : z80dma_device(mconfig, Z80DMA, tag, owner, clock)
+{
+}
+
+z80dma_device::z80dma_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
, device_z80daisy_interface(mconfig, *this)
, m_out_busreq_cb(*this)
, m_out_int_cb(*this)
, m_out_ieo_cb(*this)
, m_out_bao_cb(*this)
- , m_in_mreq_cb(*this)
+ , m_in_mreq_cb(*this, 0)
, m_out_mreq_cb(*this)
- , m_in_iorq_cb(*this)
+ , m_in_iorq_cb(*this, 0)
, m_out_iorq_cb(*this)
{
}
@@ -170,18 +151,8 @@ z80dma_device::z80dma_device(const machine_config &mconfig, const char *tag, dev
void z80dma_device::device_start()
{
- // resolve callbacks
- m_out_busreq_cb.resolve_safe();
- m_out_int_cb.resolve_safe();
- m_out_ieo_cb.resolve_safe();
- m_out_bao_cb.resolve_safe();
- m_in_mreq_cb.resolve_safe(0);
- m_out_mreq_cb.resolve_safe();
- m_in_iorq_cb.resolve_safe(0);
- m_out_iorq_cb.resolve_safe();
-
// allocate timer
- m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z80dma_device::timerproc), this));
+ m_timer = timer_alloc(FUNC(z80dma_device::timerproc), this);
// register for state saving
save_item(NAME(m_regs));
@@ -197,9 +168,11 @@ void z80dma_device::device_start()
save_item(NAME(m_addressA));
save_item(NAME(m_addressB));
save_item(NAME(m_count));
+ save_item(NAME(m_byte_counter));
save_item(NAME(m_rdy));
save_item(NAME(m_force_ready));
save_item(NAME(m_is_read));
+ save_item(NAME(m_is_pulse));
save_item(NAME(m_cur_cycle));
save_item(NAME(m_latch));
}
@@ -219,6 +192,7 @@ void z80dma_device::device_reset()
m_read_num_follow = m_read_cur_follow = 0;
m_reset_pointer = 0;
m_is_read = false;
+ m_is_pulse = false;
memset(m_regs, 0, sizeof(m_regs));
memset(m_regs_follow, 0, sizeof(m_regs_follow));
@@ -334,7 +308,12 @@ int z80dma_device::is_ready()
void z80dma_device::interrupt_check()
{
m_out_int_cb(m_ip ? ASSERT_LINE : CLEAR_LINE);
- m_out_ieo_cb(m_iei && !m_ip);
+
+ int ieo = m_iei;
+ if (m_ip) {
+ ieo = 0;
+ }
+ m_out_ieo_cb(ieo);
}
@@ -448,16 +427,11 @@ void z80dma_device::do_search()
}
}
-int z80dma_device::do_write()
+void z80dma_device::do_write()
{
- int done;
uint8_t mode;
mode = TRANSFER_MODE;
- if (m_count == 0x0000)
- {
- //FIXME: Any signal here
- }
switch(mode) {
case TM_TRANSFER:
do_transfer_write();
@@ -480,14 +454,7 @@ int z80dma_device::do_write()
m_addressA += PORTA_FIXED ? 0 : PORTA_INC ? 1 : -1;
m_addressB += PORTB_FIXED ? 0 : PORTB_INC ? 1 : -1;
- m_count--;
- done = (m_count == 0xFFFF); //correct?
-
- if (done)
- {
- //FIXME: interrupt ?
- }
- return done;
+ m_byte_counter++;
}
@@ -497,31 +464,48 @@ int z80dma_device::do_write()
TIMER_CALLBACK_MEMBER(z80dma_device::timerproc)
{
- int done;
-
if (--m_cur_cycle)
{
return;
}
+ if (PULSE_GENERATED)
+ {
+ if (m_is_pulse)
+ {
+ m_out_int_cb(CLEAR_LINE);
+ m_is_pulse = false;
+ }
+ else
+ {
+ if ((m_byte_counter & 0xff)==PULSE_CTRL && is_ready())
+ {
+ m_is_pulse = true;
+ m_out_int_cb(ASSERT_LINE);
+ }
+ }
+ }
+
if (m_is_read && !is_ready()) return;
if (m_is_read)
{
/* TODO: there's a nasty recursion bug with Alpha for Sharp X1 Turbo on the transfers with this function! */
do_read();
- done = 0;
m_is_read = false;
m_cur_cycle = (PORTA_IS_SOURCE ? PORTA_CYCLE_LEN : PORTB_CYCLE_LEN);
}
else
{
- done = do_write();
+ do_write();
m_is_read = true;
m_cur_cycle = (PORTB_IS_SOURCE ? PORTA_CYCLE_LEN : PORTB_CYCLE_LEN);
+
+ // param==1 indicates final transfer
+ m_timer->set_param(m_byte_counter == m_count);
}
- if (done)
+ if (m_is_read && param)
{
m_dma_enabled = 0; //FIXME: Correct?
m_status = 0x09;
@@ -546,7 +530,9 @@ TIMER_CALLBACK_MEMBER(z80dma_device::timerproc)
m_addressA = PORTA_ADDRESS;
m_addressB = PORTB_ADDRESS;
m_count = BLOCKLEN;
+ m_byte_counter = 0;
m_status |= 0x30;
+ m_timer->set_param(0);
}
}
}
@@ -558,20 +544,17 @@ TIMER_CALLBACK_MEMBER(z80dma_device::timerproc)
void z80dma_device::update_status()
{
- uint16_t pending_transfer;
- attotime next;
-
// no transfer is active right now; is there a transfer pending right now?
- pending_transfer = is_ready() & m_dma_enabled;
+ bool const pending_transfer = is_ready() && m_dma_enabled;
if (pending_transfer)
{
m_is_read = true;
m_cur_cycle = (PORTA_IS_SOURCE ? PORTA_CYCLE_LEN : PORTB_CYCLE_LEN);
- next = attotime::from_hz(clock());
+ attotime const next = attotime::from_hz(clock());
m_timer->adjust(
attotime::zero,
- 0,
+ m_timer->param(),
// 1 byte transferred in 4 clock cycles
next);
}
@@ -698,6 +681,7 @@ void z80dma_device::write(uint8_t data)
m_read_regs_follow[0] = m_status;
break;
case COMMAND_RESET_AND_DISABLE_INTERRUPTS:
+ LOG("Z80DMA Reset and Disable Interrupts\n");
WR3 &= ~0x20;
m_ip = 0;
m_ius = 0;
@@ -708,8 +692,8 @@ void z80dma_device::write(uint8_t data)
LOG("Z80DMA Initiate Read Sequence\n");
m_read_cur_follow = m_read_num_follow = 0;
if(READ_MASK & 0x01) { m_read_regs_follow[m_read_num_follow++] = m_status; }
- if(READ_MASK & 0x02) { m_read_regs_follow[m_read_num_follow++] = m_count & 0xff; } //byte counter (low)
- if(READ_MASK & 0x04) { m_read_regs_follow[m_read_num_follow++] = m_count >> 8; } //byte counter (high)
+ if(READ_MASK & 0x02) { m_read_regs_follow[m_read_num_follow++] = m_byte_counter & 0xff; } //byte counter (low)
+ if(READ_MASK & 0x04) { m_read_regs_follow[m_read_num_follow++] = m_byte_counter >> 8; } //byte counter (high)
if(READ_MASK & 0x08) { m_read_regs_follow[m_read_num_follow++] = m_addressA & 0xff; } //port A address (low)
if(READ_MASK & 0x10) { m_read_regs_follow[m_read_num_follow++] = m_addressA >> 8; } //port A address (high)
if(READ_MASK & 0x20) { m_read_regs_follow[m_read_num_follow++] = m_addressB & 0xff; } //port B address (low)
@@ -739,7 +723,9 @@ void z80dma_device::write(uint8_t data)
m_addressA = PORTA_ADDRESS;
m_addressB = PORTB_ADDRESS;
m_count = BLOCKLEN;
+ m_byte_counter = 0;
m_status |= 0x30;
+ m_timer->set_param(0);
LOG("Z80DMA Load A: %x B: %x N: %x\n", m_addressA, m_addressB, m_count);
break;
@@ -750,7 +736,6 @@ void z80dma_device::write(uint8_t data)
case COMMAND_ENABLE_DMA:
LOG("Z80DMA Enable DMA\n");
m_dma_enabled = 1;
- update_status();
break;
case COMMAND_READ_MASK_FOLLOWS:
LOG("Z80DMA Set Read Mask\n");
@@ -759,9 +744,11 @@ void z80dma_device::write(uint8_t data)
case COMMAND_CONTINUE:
LOG("Z80DMA Continue\n");
m_count = BLOCKLEN;
+ m_byte_counter = 0;
m_dma_enabled = 1;
//"match not found" & "end of block" status flags zeroed here
m_status |= 0x30;
+ m_timer->set_param(0);
break;
case COMMAND_RESET_PORT_A_TIMING:
LOG("Z80DMA Reset Port A Timing\n");
@@ -774,7 +761,6 @@ void z80dma_device::write(uint8_t data)
case COMMAND_FORCE_READY:
LOG("Z80DMA Force Ready\n");
m_force_ready = 1;
- update_status();
break;
case COMMAND_ENABLE_INTERRUPTS:
LOG("Z80DMA Enable IRQ\n");
@@ -796,6 +782,7 @@ void z80dma_device::write(uint8_t data)
default:
logerror("Z80DMA Unknown WR6 command %02x\n", data);
}
+ update_status();
}
else if(data == 0x8e) //newtype on Sharp X1, unknown purpose
logerror("Z80DMA Unknown base register %02x\n", data);
@@ -826,8 +813,8 @@ void z80dma_device::write(uint8_t data)
m_read_cur_follow = m_read_num_follow = 0;
if(READ_MASK & 0x01) { m_read_regs_follow[m_read_num_follow++] = m_status; }
- if(READ_MASK & 0x02) { m_read_regs_follow[m_read_num_follow++] = m_count & 0xff; } //byte counter (low)
- if(READ_MASK & 0x04) { m_read_regs_follow[m_read_num_follow++] = m_count >> 8; } //byte counter (high)
+ if(READ_MASK & 0x02) { m_read_regs_follow[m_read_num_follow++] = m_byte_counter & 0xff; } //byte counter (low)
+ if(READ_MASK & 0x04) { m_read_regs_follow[m_read_num_follow++] = m_byte_counter >> 8; } //byte counter (high)
if(READ_MASK & 0x08) { m_read_regs_follow[m_read_num_follow++] = m_addressA & 0xff; } //port A address (low)
if(READ_MASK & 0x10) { m_read_regs_follow[m_read_num_follow++] = m_addressA >> 8; } //port A address (high)
if(READ_MASK & 0x20) { m_read_regs_follow[m_read_num_follow++] = m_addressB & 0xff; } //port B address (low)
@@ -863,7 +850,7 @@ TIMER_CALLBACK_MEMBER(z80dma_device::rdy_write_callback)
// rdy_w - ready input
//-------------------------------------------------
-WRITE_LINE_MEMBER(z80dma_device::rdy_w)
+void z80dma_device::rdy_w(int state)
{
LOG("Z80DMA RDY: %d Active High: %d\n", state, READY_ACTIVE_HIGH);
machine().scheduler().synchronize(timer_expired_delegate(FUNC(z80dma_device::rdy_write_callback),this), state);
@@ -874,7 +861,7 @@ WRITE_LINE_MEMBER(z80dma_device::rdy_w)
// wait_w - wait input
//-------------------------------------------------
-WRITE_LINE_MEMBER(z80dma_device::wait_w)
+void z80dma_device::wait_w(int state)
{
}
@@ -883,6 +870,6 @@ WRITE_LINE_MEMBER(z80dma_device::wait_w)
// bai_w - bus acknowledge input
//-------------------------------------------------
-WRITE_LINE_MEMBER(z80dma_device::bai_w)
+void z80dma_device::bai_w(int state)
{
}