From 77d010d7ce8f08fdcedb26050d54368039488c44 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Mon, 9 Jan 2017 11:24:10 +0700 Subject: [PATCH] tidy up dma and timer3 code --- src/mame/machine/interpro_ioga.cpp | 51 +++++++++++++++++++----------- src/mame/machine/interpro_ioga.h | 15 +++++++-- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/mame/machine/interpro_ioga.cpp b/src/mame/machine/interpro_ioga.cpp index 4874a18072d..3252f09449f 100644 --- a/src/mame/machine/interpro_ioga.cpp +++ b/src/mame/machine/interpro_ioga.cpp @@ -8,10 +8,12 @@ #define LOG_TIMER(...) logerror(__VA_ARGS__) #define LOG_INTERRUPT(...) logerror(__VA_ARGS__) #define LOG_IOGA(...) logerror(__VA_ARGS__) +#define LOG_DMA(...) logerror(__VA_ARGS__) #else #define LOG_TIMER(...) #define LOG_INTERRUPT(...) #define LOG_IOGA(...) +#define LOG_DMA(...) #endif DEVICE_ADDRESS_MAP_START(map, 32, interpro_ioga_device) @@ -70,6 +72,7 @@ void interpro_ioga_device::device_start() // allocate timer for DMA controller m_dma_timer = timer_alloc(IOGA_TIMER_DMA); m_dma_timer->adjust(attotime::never); + m_dma_active = false; } void interpro_ioga_device::device_reset() @@ -103,15 +106,15 @@ void interpro_ioga_device::write_timer(int timer, uint32_t value, device_timer_i break; case IOGA_TIMER_3: - // write the value without the top two bits to the register + // stop the timer so it won't trigger while we're fiddling with it m_timer[timer]->enable(false); - m_timer_reg[timer] = value; + + // write the new value to the timer register + m_timer3_reg.all = value; // start the timer if necessary - if (value & IOGA_TIMER3_START) - { + if (m_timer3_reg.fields.start) m_timer[timer]->adjust(attotime::zero, id, attotime::from_hz(IOGA_TIMER3_CLOCK)); - } break; default: @@ -154,17 +157,18 @@ void interpro_ioga_device::device_timer(emu_timer &timer, device_timer_id id, in break; case IOGA_TIMER_3: - m_timer_reg[3] = m_timer_reg[3] & ~IOGA_TIMER3_VMASK | ((m_timer_reg[3] & IOGA_TIMER3_VMASK) - 1); - if ((m_timer_reg[3] & IOGA_TIMER3_VMASK) == 0) + // decrement the counter field of the timer + m_timer3_reg.fields.count--; + + // check for expiry + if (m_timer3_reg.fields.count == 0) { // disable timer timer.enable(false); - // clear start flag - m_timer_reg[3] &= ~IOGA_TIMER3_START; - - // set expired flag - m_timer_reg[3] |= IOGA_TIMER3_EXPIRED; + // clear start flag and set expired flag + m_timer3_reg.fields.start = 0; + m_timer3_reg.fields.expired = 1; // throw an interrupt set_irq_line(IOGA_TIMER3_IRQ, ASSERT_LINE); @@ -176,18 +180,17 @@ void interpro_ioga_device::device_timer(emu_timer &timer, device_timer_id id, in // TODO: vice-versa // TODO: get the dma transfer address and count // TODO: implement multiple dma channels - - // TODO: must send "terminal count" (TC) signal to FDC to avoid end of cylinder errors :( { + if (!m_dma_active) + { + LOG_DMA("dma transfer started, control 0x%08x, real address 0x%08x count 0x%08x\n", m_fdc_dma[3], m_fdc_dma[0], m_fdc_dma[2]); + m_dma_active = true; + } address_space &space = m_cpu->space(AS_PROGRAM); // while the device has data and the DMA count is not empty while (m_state_drq && m_fdc_dma[2]) { - // if this is the last byte, terminate the transfer - if (m_fdc_dma[2] == 1) - m_fdc_tc_func(ASSERT_LINE); - // read a byte from the device uint8_t byte = m_dma_r_func[IOGA_DMA_CHANNEL_FLOPPY](); @@ -199,6 +202,17 @@ void interpro_ioga_device::device_timer(emu_timer &timer, device_timer_id id, in m_fdc_dma[2]--; } + // if there are no more bytes remaining, terminate the transfer + if (m_fdc_dma[2] == 0) + { + LOG_DMA("dma transfer stopped, control 0x%08x, real address 0x%08x count 0x%08x\n", m_fdc_dma[3], m_fdc_dma[0], m_fdc_dma[2]); + LOG_DMA("dma controller asserting fdc terminal count line\n"); + + m_fdc_tc_func(ASSERT_LINE); + m_fdc_tc_func(CLEAR_LINE); + + m_dma_active = false; + } } break; } @@ -483,7 +497,6 @@ WRITE_LINE_MEMBER(interpro_ioga_device::drq) if (state) { // TODO: check if dma is enabled - m_fdc_tc_func(CLEAR_LINE); m_dma_timer->adjust(attotime::zero); } } \ No newline at end of file diff --git a/src/mame/machine/interpro_ioga.h b/src/mame/machine/interpro_ioga.h index 3a782e857b0..1aba5722251 100644 --- a/src/mame/machine/interpro_ioga.h +++ b/src/mame/machine/interpro_ioga.h @@ -94,7 +94,7 @@ public: DECLARE_READ32_MEMBER(timer0_r) { return m_timer_reg[0]; } DECLARE_READ32_MEMBER(timer1_r) { return m_timer_reg[1]; } DECLARE_READ32_MEMBER(timer2_r) { return m_timer_reg[2]; } - DECLARE_READ32_MEMBER(timer3_r) { return m_timer_reg[3]; } + DECLARE_READ32_MEMBER(timer3_r) { return m_timer3_reg.all; } DECLARE_WRITE32_MEMBER(timer_prescaler_w) { m_prescaler = data; } DECLARE_WRITE32_MEMBER(timer0_w) { write_timer(0, data, IOGA_TIMER_0); } @@ -152,12 +152,23 @@ private: uint8_t m_nmictrl; uint32_t m_prescaler; - uint32_t m_timer_reg[4]; + uint32_t m_timer_reg[3]; + union timer3 + { + struct fields + { + uint32_t count : 30; + uint32_t start : 1; + uint32_t expired : 1; + } fields; + uint32_t all; + } m_timer3_reg; emu_timer *m_timer[4]; emu_timer *m_dma_timer; uint32_t m_state_drq; uint32_t m_fdc_dma[4]; + bool m_dma_active; }; // device type definition