diff options
Diffstat (limited to 'src/devices/machine/z80dma.cpp')
-rw-r--r-- | src/devices/machine/z80dma.cpp | 665 |
1 files changed, 334 insertions, 331 deletions
diff --git a/src/devices/machine/z80dma.cpp b/src/devices/machine/z80dma.cpp index 831c20e7aff..1e6ce280b0f 100644 --- a/src/devices/machine/z80dma.cpp +++ b/src/devices/machine/z80dma.cpp @@ -18,26 +18,25 @@ - rewrite to match documentation - implement missing features - implement more asserts - - implement a INPUT_LINE_BUSREQ for Z80. As a workaround, - HALT is used. This implies burst mode. **********************************************************************/ #include "emu.h" #include "z80dma.h" -#define LOG_GENERAL (1U << 0) #define LOG_DMA (1U << 1) +#define LOG_INT (1U << 2) -//#define VERBOSE (LOG_GENERAL | LOG_DMA) +//#define VERBOSE (LOG_GENERAL | LOG_DMA | LOG_INT) #include "logmacro.h" #define LOGDMA(...) LOGMASKED(LOG_DMA, __VA_ARGS__) +#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__) -//************************************************************************** -// CONSTANTS -//************************************************************************** +/**************************************************************************** + * CONSTANTS + ****************************************************************************/ enum { INT_RDY = 0, @@ -46,36 +45,26 @@ 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; - - +enum +{ + SEQ_WAIT_READY = 0, + SEQ_REQUEST_BUS, + SEQ_WAITING_ACK, + SEQ_TRANS1_INC_DEC_SOURCE_ADDRESS, + SEQ_TRANS1_READ_SOURCE, + SEQ_TRANS1_INC_DEC_DEST_ADDRESS, + SEQ_TRANS1_WRITE_DEST, + SEQ_TRANS1_BYTE_MATCH, + SEQ_TRANS1_INC_BYTE_COUNTER, + SEQ_TRANS1_SET_FLAGS, + SEQ_FINISH +}; -//************************************************************************** -// MACROS -//************************************************************************** -#define REGNUM(_m, _s) (((_m)<<3) + (_s)) +/**************************************************************************** + * MACROS + ****************************************************************************/ #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) @@ -115,13 +104,12 @@ constexpr int TM_SEARCH_TRANSFER = 0x03; #define PORTA_MEMORY (((WR1 >> 3) & 0x01) == 0x00) #define PORTB_MEMORY (((WR2 >> 3) & 0x01) == 0x00) -#define PORTA_CYCLE_LEN (4-(PORTA_TIMING & 0x03)) -#define PORTB_CYCLE_LEN (4-(PORTB_TIMING & 0x03)) - #define PORTA_IS_SOURCE ((WR0 >> 2) & 0x01) #define PORTB_IS_SOURCE (!PORTA_IS_SOURCE) #define TRANSFER_MODE (WR0 & 0x03) +#define OPERATING_MODE ((WR4 >> 5) & 0x03) // 0b00: Byte; 0b01: Continuous; 0b10: Burst; 0b11: Do not program + #define MATCH_F_SET (m_status &= ~0x10) #define MATCH_F_CLEAR (m_status |= 0x10) #define EOB_F_SET (m_status &= ~0x20) @@ -135,51 +123,43 @@ 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) - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -// device type definition +/**************************************************************************** + * device type definition + ****************************************************************************/ DEFINE_DEVICE_TYPE(Z80DMA, z80dma_device, "z80dma", "Z80 DMA Controller") -//------------------------------------------------- -// z80dma_device - constructor -//------------------------------------------------- +/**************************************************************************** + * z80dma_device - constructor + ****************************************************************************/ +z80dma_device::z80dma_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : z80dma_device(mconfig, Z80DMA, tag, owner, clock) +{ +} -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::z80dma_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 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) { } - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - +/**************************************************************************** + * device_start - device-specific startup + ****************************************************************************/ void z80dma_device::device_start() { - // resolve callbacks - m_out_busreq_cb.resolve_safe(); - m_out_int_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::clock_w), this); // register for state saving save_item(NAME(m_regs)); @@ -187,35 +167,41 @@ void z80dma_device::device_start() save_item(NAME(m_num_follow)); save_item(NAME(m_cur_follow)); save_item(NAME(m_status)); - save_item(NAME(m_dma_enabled)); + save_item(NAME(m_dma_seq)); save_item(NAME(m_vector)); + save_item(NAME(m_iei)); save_item(NAME(m_ip)); save_item(NAME(m_ius)); 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_cur_cycle)); + save_item(NAME(m_wait)); + save_item(NAME(m_busrq_ack)); + save_item(NAME(m_is_pulse)); save_item(NAME(m_latch)); } -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - +/**************************************************************************** + * device_reset - device-specific reset + ****************************************************************************/ void z80dma_device::device_reset() { + m_timer->reset(); + m_status = 0; + m_dma_seq = ~0; m_rdy = 0; m_force_ready = 0; + m_wait = 0; m_num_follow = 0; - m_dma_enabled = 0; m_read_num_follow = m_read_cur_follow = 0; m_reset_pointer = 0; - m_is_read = false; + m_busrq_ack = 0; + m_is_pulse = false; memset(m_regs, 0, sizeof(m_regs)); memset(m_regs_follow, 0, sizeof(m_regs_follow)); @@ -224,21 +210,17 @@ void z80dma_device::device_reset() m_ip = 0; m_ius = 0; m_vector = 0; - - update_status(); } +/**************************************************************************** + * DAISY CHAIN INTERFACE + ****************************************************************************/ -//************************************************************************** -// DAISY CHAIN INTERFACE -//************************************************************************** - -//------------------------------------------------- -// z80daisy_irq_state - return the overall IRQ -// state for this device -//------------------------------------------------- - +/**************************************************************************** + * z80daisy_irq_state - return the overall IRQ + * state for this device + ****************************************************************************/ int z80dma_device::z80daisy_irq_state() { int state = 0; @@ -253,23 +235,20 @@ int z80dma_device::z80daisy_irq_state() // interrupt under service state = Z80_DAISY_IEO; } - - LOG("Z80DMA Interrupt State: %u\n", state); + LOGINT("Z80DMA Interrupt State: %u\n", state); return state; } - -//------------------------------------------------- -// z80daisy_irq_ack - acknowledge an IRQ and -// return the appropriate vector -//------------------------------------------------- - +/**************************************************************************** + * z80daisy_irq_ack - acknowledge an IRQ and + * return the appropriate vector + ****************************************************************************/ int z80dma_device::z80daisy_irq_ack() { if (m_ip) { - LOG("Z80DMA Interrupt Acknowledge\n"); + LOGINT("Z80DMA Interrupt Acknowledge\n"); // clear interrupt pending flag m_ip = 0; @@ -280,64 +259,74 @@ int z80dma_device::z80daisy_irq_ack() return m_vector; } - - //logerror("z80dma_irq_ack: failed to find an interrupt to ack!\n"); - - return 0; + else + { + LOGINT("z80dma_irq_ack: failed to find an interrupt to ack!\n"); + return 0; + } } - -//------------------------------------------------- -// z80daisy_irq_reti - clear the interrupt -// pending state to allow other interrupts through -//------------------------------------------------- - +/**************************************************************************** + * z80daisy_irq_reti - clear the interrupt + * pending state to allow other interrupts through + ****************************************************************************/ void z80dma_device::z80daisy_irq_reti() { if (m_ius) { - LOG("Z80DMA Return from Interrupt\n"); + LOGINT("Z80DMA Return from Interrupt\n"); // clear interrupt under service flag m_ius = 0; interrupt_check(); - - return; } - - //logerror("z80dma_irq_reti: failed to find an interrupt to clear IEO on!\n"); + else + { + LOGINT("z80dma_irq_reti: failed to find an interrupt to clear IEO on!\n"); + } } - //************************************************************************** // INTERNAL STATE MANAGEMENT //************************************************************************** -//------------------------------------------------- -// is_ready - ready for DMA transfer? -//------------------------------------------------- - -int z80dma_device::is_ready() +void z80dma_device::enable() { - return (m_force_ready) || (m_rdy == READY_ACTIVE_HIGH); + const attotime curtime = machine().time(); + m_timer->adjust(attotime::from_ticks(curtime.as_ticks(clock()) + 1, clock()) - curtime, 0, clocks_to_attotime(1)); + m_dma_seq = SEQ_WAIT_READY; } +void z80dma_device::disable() +{ + m_timer->reset(); + if (m_busrq_ack == 1) + { + m_out_busreq_cb(CLEAR_LINE); + } +} -//------------------------------------------------- -// interrupt_check - update IRQ line state -//------------------------------------------------- +/**************************************************************************** + * is_ready - ready for DMA transfer? + ****************************************************************************/ +int z80dma_device::is_ready() +{ + return m_force_ready || (m_rdy == READY_ACTIVE_HIGH); +} +/**************************************************************************** + * interrupt_check - update IRQ line state + ****************************************************************************/ void z80dma_device::interrupt_check() { m_out_int_cb(m_ip ? ASSERT_LINE : CLEAR_LINE); + m_out_ieo_cb(m_ip ? 0 : m_iei); } - -//------------------------------------------------- -// trigger_interrupt - trigger DMA interrupt -//------------------------------------------------- - +/**************************************************************************** + * trigger_interrupt - trigger DMA interrupt + ****************************************************************************/ void z80dma_device::trigger_interrupt(int level) { if (!m_ius && INTERRUPT_ENABLE) @@ -357,23 +346,19 @@ void z80dma_device::trigger_interrupt(int level) m_status &= ~0x08; - LOG("Z80DMA Interrupt Pending\n"); + LOGINT("Z80DMA Interrupt Pending\n"); interrupt_check(); } } - -//------------------------------------------------- -// do_read - perform DMA read -//------------------------------------------------- - +/**************************************************************************** + * do_read - perform DMA read + ****************************************************************************/ void z80dma_device::do_read() { - uint8_t mode; - - mode = TRANSFER_MODE; - switch(mode) { + switch(TRANSFER_MODE) + { case TM_TRANSFER: case TM_SEARCH: case TM_SEARCH_TRANSFER: @@ -397,16 +382,14 @@ void z80dma_device::do_read() } break; default: - logerror("z80dma_do_operation: invalid mode %d!\n", mode); + logerror("z80dma_do_operation: invalid mode %d!\n", TRANSFER_MODE); break; } } - -//------------------------------------------------- -// do_write - perform DMA write -//------------------------------------------------- - +/**************************************************************************** + * do_write - perform DMA write + ****************************************************************************/ void z80dma_device::do_transfer_write() { if (PORTA_IS_SOURCE) @@ -431,30 +414,19 @@ void z80dma_device::do_transfer_write() void z80dma_device::do_search() { - uint8_t load_byte,match_byte; - load_byte = m_latch | MASK_BYTE; - match_byte = MATCH_BYTE | MASK_BYTE; - //LOG("%02x %02x\n",load_byte,match_byte)); - if (load_byte == match_byte) + const u8 load_byte = m_latch | MASK_BYTE; + const u8 match_byte = MATCH_BYTE | MASK_BYTE; + LOGDMA("SEARCH: %02x %02x\n", load_byte, match_byte); + if (INT_ON_MATCH && load_byte == match_byte) { - if (INT_ON_MATCH) - { - trigger_interrupt(INT_MATCH); - } + trigger_interrupt(INT_MATCH); } } -int z80dma_device::do_write() +void z80dma_device::do_write() { - int done; - uint8_t mode; - - mode = TRANSFER_MODE; - if (m_count == 0x0000) + switch(TRANSFER_MODE) { - //FIXME: Any signal here - } - switch(mode) { case TM_TRANSFER: do_transfer_write(); break; @@ -469,157 +441,196 @@ int z80dma_device::do_write() break; default: - logerror("z80dma_do_operation: invalid mode %d!\n", mode); + logerror("z80dma_do_operation: invalid mode %d!\n", TRANSFER_MODE); break; } 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++; } - -//------------------------------------------------- -// timerproc -//------------------------------------------------- - -TIMER_CALLBACK_MEMBER(z80dma_device::timerproc) +/**************************************************************************** + * clock_w - raising edge + ****************************************************************************/ +TIMER_CALLBACK_MEMBER(z80dma_device::clock_w) { - int done; - - if (--m_cur_cycle) + switch (m_dma_seq) { - return; - } - - if (m_is_read && !is_ready()) return; + case SEQ_WAIT_READY: + if (is_ready()) + { + // Continuos mode only request BUS during start + if (OPERATING_MODE != 0b01 || m_byte_counter == 0) + { + m_dma_seq = SEQ_REQUEST_BUS; + } + else + { + m_dma_seq = SEQ_TRANS1_INC_DEC_SOURCE_ADDRESS; + } + } + break; - 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(); - m_is_read = true; - m_cur_cycle = (PORTB_IS_SOURCE ? PORTA_CYCLE_LEN : PORTB_CYCLE_LEN); - } + case SEQ_REQUEST_BUS: + if (m_busrq_ack == 0) + { + m_out_busreq_cb(ASSERT_LINE); + } + m_dma_seq = SEQ_WAITING_ACK; + break; - if (done) - { - m_dma_enabled = 0; //FIXME: Correct? - m_status = 0x09; + case SEQ_WAITING_ACK: + if (m_busrq_ack == 1) + { + m_dma_seq = SEQ_TRANS1_INC_DEC_SOURCE_ADDRESS; + } + break; - m_status |= !is_ready() << 1; // ready line status + case SEQ_TRANS1_INC_DEC_SOURCE_ADDRESS: + { + if (PULSE_GENERATED && (m_byte_counter & 0xff) == PULSE_CTRL) + { + m_is_pulse = true; + m_out_int_cb(ASSERT_LINE); + } - if(TRANSFER_MODE == TM_TRANSFER) m_status |= 0x10; // no match found + const attotime clock = clocks_to_attotime(1); + const attotime next = clock * (3 - ((PORTA_IS_SOURCE ? PORTA_TIMING : PORTB_TIMING) & 0x03)); + m_timer->adjust(next, 0, clock); - update_status(); - LOG("Z80DMA End of Block\n"); + m_dma_seq = SEQ_TRANS1_READ_SOURCE; + } + break; - if (INT_ON_END_OF_BLOCK) - { - trigger_interrupt(INT_END_OF_BLOCK); - } + case SEQ_TRANS1_READ_SOURCE: + if (!m_wait) + { + // TODO: there's a nasty recursion bug with Alpha for Sharp X1 Turbo on the transfers with this function! + do_read(); - if (AUTO_RESTART) - { - LOG("Z80DMA Auto Restart\n"); + m_dma_seq = SEQ_TRANS1_INC_DEC_DEST_ADDRESS; + } + break; - m_dma_enabled = 1; - m_addressA = PORTA_ADDRESS; - m_addressB = PORTB_ADDRESS; - m_count = BLOCKLEN; - m_status |= 0x30; - } - } -} + case SEQ_TRANS1_INC_DEC_DEST_ADDRESS: + { + const attotime clock = clocks_to_attotime(1); + const attotime next = clock * (3 - ((PORTB_IS_SOURCE ? PORTA_TIMING : PORTB_TIMING) & 0x03)); + m_timer->adjust(next, 0, clock); + m_dma_seq = SEQ_TRANS1_WRITE_DEST; + } + break; -//------------------------------------------------- -// update_status - update DMA status -//------------------------------------------------- + case SEQ_TRANS1_WRITE_DEST: + if (!m_wait) + { + // hack?: count=0 cause infinite loop in 'x1turbo40 suikoden' and makes it work. + const bool is_final = m_count && m_byte_counter == m_count; + + do_write(); + + if (PULSE_GENERATED && m_is_pulse) + { + m_out_int_cb(CLEAR_LINE); + m_is_pulse = false; + } + + const u8 mode = is_final ? 0b11 : OPERATING_MODE; + switch (mode) + { + case 0b00: // Byte/Single/byte-at-a-time + m_out_busreq_cb(CLEAR_LINE); + m_dma_seq = SEQ_WAIT_READY; + break; + + case 0b10: // Burst/Demand + if (is_ready()) + { + m_dma_seq = SEQ_TRANS1_INC_DEC_SOURCE_ADDRESS; + } + else + { + m_out_busreq_cb(CLEAR_LINE); + m_dma_seq = SEQ_WAIT_READY; + } + break; + + case 0b01: // Continuous/Block + m_dma_seq = is_ready() ? SEQ_TRANS1_INC_DEC_SOURCE_ADDRESS : SEQ_WAIT_READY; + break; + + default: // Undefined || final + m_dma_seq = SEQ_FINISH; + break; + } + } + break; -void z80dma_device::update_status() -{ - uint16_t pending_transfer; - attotime next; + case SEQ_TRANS1_BYTE_MATCH: + case SEQ_TRANS1_INC_BYTE_COUNTER: + case SEQ_TRANS1_SET_FLAGS: + case SEQ_FINISH: + disable(); + m_status = 0x09; + m_status |= !is_ready() << 1; // ready line status - // no transfer is active right now; is there a transfer pending right now? - pending_transfer = is_ready() & m_dma_enabled; + if(TRANSFER_MODE == TM_TRANSFER) m_status |= 0x10; // no match found - if (pending_transfer) - { - m_is_read = true; - m_cur_cycle = (PORTA_IS_SOURCE ? PORTA_CYCLE_LEN : PORTB_CYCLE_LEN); - next = attotime::from_hz(clock()); - m_timer->adjust( - attotime::zero, - 0, - // 1 byte transferred in 4 clock cycles - next); - } - else - { - if (m_is_read) - { - // no transfers active right now - m_timer->reset(); - } - } + LOG("Z80DMA End of Block\n"); - // set the busreq line - m_out_busreq_cb(pending_transfer ? ASSERT_LINE : CLEAR_LINE); -} + if (INT_ON_END_OF_BLOCK) + { + trigger_interrupt(INT_END_OF_BLOCK); + } + if (AUTO_RESTART) + { + LOG("Z80DMA Auto Restart\n"); + + m_addressA = PORTA_ADDRESS; + m_addressB = PORTB_ADDRESS; + m_count = BLOCKLEN; + m_byte_counter = 0; + m_status |= 0x30; + enable(); + } + break; + default: + break; + } +} -//************************************************************************** -// READ/WRITE INTERFACES -//************************************************************************** -//------------------------------------------------- -// read - register read -//------------------------------------------------- +/**************************************************************************** + * READ/WRITE INTERFACES + ****************************************************************************/ -uint8_t z80dma_device::read() +/**************************************************************************** + * read - register read + ****************************************************************************/ +u8 z80dma_device::read() { - uint8_t res; - - if(m_read_num_follow == 0) // special case: Legend of Kage on X1 Turbo - res = m_status; - else { - res = m_read_regs_follow[m_read_cur_follow]; - } - - m_read_cur_follow++; - - if(m_read_cur_follow >= m_read_num_follow) - m_read_cur_follow = 0; + const u8 res = m_read_regs_follow[m_read_cur_follow]; + if (!machine().side_effects_disabled()) + { + m_read_cur_follow++; - LOG("Z80DMA Read %02x\n", res); + if(m_read_cur_follow >= m_read_num_follow) + m_read_cur_follow = 0; + LOG("Z80DMA Read %02x\n", res); + } return res; } - -//------------------------------------------------- -// write - register write -//------------------------------------------------- - -void z80dma_device::write(uint8_t data) +/**************************************************************************** + * write - register write + ****************************************************************************/ +void z80dma_device::write(u8 data) { if (m_num_follow == 0) { @@ -660,6 +671,11 @@ void z80dma_device::write(uint8_t data) m_regs_follow[m_num_follow++] = GET_REGNUM(MASK_BYTE); if (data & 0x10) m_regs_follow[m_num_follow++] = GET_REGNUM(MATCH_BYTE); + + if (BIT(data, 6)) + { + enable(); + } } else if ((data & 0x83) == 0x81) // WR4 { @@ -680,8 +696,6 @@ void z80dma_device::write(uint8_t data) else if ((data & 0x83) == 0x83) // WR6 { LOG("Z80DMA WR6 %02x\n", data); - m_dma_enabled = 0; - WR6 = data; switch (data) @@ -694,6 +708,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; @@ -703,30 +718,31 @@ void z80dma_device::write(uint8_t data) case COMMAND_INITIATE_READ_SEQUENCE: 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 & 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) - if(READ_MASK & 0x40) { m_read_regs_follow[m_read_num_follow++] = m_addressB >> 8; } //port B address (high) + 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_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) + if (READ_MASK & 0x40) { m_read_regs_follow[m_read_num_follow++] = m_addressB >> 8; } //port B address (high) break; case COMMAND_RESET: LOG("Z80DMA Reset\n"); - m_dma_enabled = 0; + disable(); m_force_ready = 0; m_ip = 0; m_ius = 0; interrupt_check(); // Needs six reset commands to reset the DMA { - uint8_t WRi; - - for(WRi=0;WRi<7;WRi++) + for (u8 WRi = 0; WRi < 7; WRi++) REG(WRi,m_reset_pointer) = 0; m_reset_pointer++; - if(m_reset_pointer >= 6) { m_reset_pointer = 0; } + if (m_reset_pointer >= 6) + { + m_reset_pointer = 0; + } } m_status = 0x38; break; @@ -735,18 +751,18 @@ 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; LOG("Z80DMA Load A: %x B: %x N: %x\n", m_addressA, m_addressB, m_count); break; case COMMAND_DISABLE_DMA: LOG("Z80DMA Disable DMA\n"); - m_dma_enabled = 0; + disable(); break; case COMMAND_ENABLE_DMA: LOG("Z80DMA Enable DMA\n"); - m_dma_enabled = 1; - update_status(); + enable(); break; case COMMAND_READ_MASK_FOLLOWS: LOG("Z80DMA Set Read Mask\n"); @@ -755,7 +771,8 @@ void z80dma_device::write(uint8_t data) case COMMAND_CONTINUE: LOG("Z80DMA Continue\n"); m_count = BLOCKLEN; - m_dma_enabled = 1; + m_byte_counter = 0; + //enable(); //???m_dma_enabled = 1; //"match not found" & "end of block" status flags zeroed here m_status |= 0x30; break; @@ -770,7 +787,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"); @@ -793,7 +809,7 @@ void z80dma_device::write(uint8_t data) logerror("Z80DMA Unknown WR6 command %02x\n", data); } } - else if(data == 0x8e) //newtype on Sharp X1, unknown purpose + else if (data == 0x8e) //newtype on Sharp X1, unknown purpose logerror("Z80DMA Unknown base register %02x\n", data); else fatalerror("Z80DMA '%s' Unknown base register %02x\n", tag(), data); @@ -806,7 +822,7 @@ void z80dma_device::write(uint8_t data) int nreg = m_regs_follow[m_cur_follow]; m_regs[nreg] = data; m_cur_follow++; - if (m_cur_follow>=m_num_follow) + if (m_cur_follow >= m_num_follow) m_num_follow = 0; if (nreg == REGNUM(4,3)) { @@ -821,64 +837,51 @@ 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 & 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) - if(READ_MASK & 0x40) { m_read_regs_follow[m_read_num_follow++] = m_addressB >> 8; } //port B address (high) + 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_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) + if (READ_MASK & 0x40) { m_read_regs_follow[m_read_num_follow++] = m_addressB >> 8; } //port B address (high) } m_reset_pointer++; - if(m_reset_pointer >= 6) { m_reset_pointer = 0; } + if (m_reset_pointer >= 6) + { + m_reset_pointer = 0; + } } } - -//------------------------------------------------- -// rdy_write_callback - deferred RDY signal write -//------------------------------------------------- - +/**************************************************************************** + * rdy_write_callback - deferred RDY signal write + ****************************************************************************/ TIMER_CALLBACK_MEMBER(z80dma_device::rdy_write_callback) { // normalize state m_rdy = param; m_status = (m_status & 0xFD) | (!is_ready() << 1); - update_status(); - if (is_ready() && INT_ON_READY) { trigger_interrupt(INT_RDY); } } - -//------------------------------------------------- -// rdy_w - ready input -//------------------------------------------------- - -WRITE_LINE_MEMBER(z80dma_device::rdy_w) +/**************************************************************************** + * rdy_w - ready input + ****************************************************************************/ +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); } - -//------------------------------------------------- -// wait_w - wait input -//------------------------------------------------- - -WRITE_LINE_MEMBER(z80dma_device::wait_w) -{ -} - - -//------------------------------------------------- -// bai_w - bus acknowledge input -//------------------------------------------------- - -WRITE_LINE_MEMBER(z80dma_device::bai_w) +/**************************************************************************** + * bai_w - bus acknowledge input + ****************************************************************************/ +void z80dma_device::bai_w(int state) { + m_busrq_ack = state; } |