diff options
Diffstat (limited to 'src/devices/machine/z80dma.cpp')
-rw-r--r-- | src/devices/machine/z80dma.cpp | 135 |
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) { } |