diff options
author | AJR <ajrhacker@users.noreply.github.com> | 2019-04-19 08:18:45 -0400 |
---|---|---|
committer | AJR <ajrhacker@users.noreply.github.com> | 2019-04-19 08:22:29 -0400 |
commit | 7ad4b4d1949aa978fa023cf3d3182ea8ed29edc6 (patch) | |
tree | ea34a25f22a74cd560bfd703a70657bba663da23 | |
parent | 64b78571137faf9a553acfa3d36032ae76a2262e (diff) |
hd63450: More accurate IRQ handling with a tidier interface
-rw-r--r-- | src/devices/bus/vme/vme_fcscsi.cpp | 36 | ||||
-rw-r--r-- | src/devices/bus/vme/vme_fcscsi.h | 6 | ||||
-rw-r--r-- | src/devices/machine/hd63450.cpp | 83 | ||||
-rw-r--r-- | src/devices/machine/hd63450.h | 14 | ||||
-rw-r--r-- | src/mame/drivers/esq5505.cpp | 39 | ||||
-rw-r--r-- | src/mame/drivers/x68k.cpp | 41 | ||||
-rw-r--r-- | src/mame/includes/x68k.h | 5 |
7 files changed, 112 insertions, 112 deletions
diff --git a/src/devices/bus/vme/vme_fcscsi.cpp b/src/devices/bus/vme/vme_fcscsi.cpp index e48f058d4db..f5d8378cb89 100644 --- a/src/devices/bus/vme/vme_fcscsi.cpp +++ b/src/devices/bus/vme/vme_fcscsi.cpp @@ -242,12 +242,7 @@ void vme_fcscsi1_card_device::update_irq_to_maincpu() { void vme_fcscsi1_card_device::cpu_space_map(address_map &map) { map(0xfffff0, 0xffffff).m(m_maincpu, FUNC(m68000_base_device::autovectors_map)); - map(0xfffff4, 0xfffff5).lr16("dmac irq", [this]() -> u16 { - dmac_irq_state = 0; - u16 vector = B41 ? dmac_irq_vector : 0x18+2; - update_irq_to_maincpu(); - return vector; - }); + map(0xfffff5, 0xfffff5).r(m_dmac, FUNC(hd63450_device::iack)); } FLOPPY_FORMATS_MEMBER( vme_fcscsi1_card_device::floppy_formats ) @@ -301,8 +296,7 @@ void vme_fcscsi1_card_device::device_add_mconfig(machine_config &config) HD63450(config, m_dmac, CPU_CRYSTAL / 2, "maincpu"); // MC68450 compatible m_dmac->set_clocks(attotime::from_usec(32), attotime::from_nsec(450), attotime::from_usec(4), attotime::from_hz(15625/2)); m_dmac->set_burst_clocks(attotime::from_usec(32), attotime::from_nsec(450), attotime::from_nsec(50), attotime::from_nsec(50)); - m_dmac->dma_end().set(FUNC(vme_fcscsi1_card_device::dma_end)); - m_dmac->dma_error().set(FUNC(vme_fcscsi1_card_device::dma_error)); + m_dmac->irq_callback().set(FUNC(vme_fcscsi1_card_device::dma_irq)); //m_dmac->dma_read<0>().set(FUNC(vme_fcscsi1_card_device::scsi_read_byte)); // ch 0 = SCSI //m_dmac->dma_write<0>().set(FUNC(vme_fcscsi1_card_device::scsi_write_byte)); m_dmac->dma_read<1>().set(FUNC(vme_fcscsi1_card_device::fdc_read_byte)); // ch 1 = fdc @@ -420,12 +414,12 @@ WRITE8_MEMBER (vme_fcscsi1_card_device::led_w){ return; } -WRITE8_MEMBER(vme_fcscsi1_card_device::dma_end) +WRITE_LINE_MEMBER(vme_fcscsi1_card_device::dma_irq) { - if (data != 0) + if(state != CLEAR_LINE) { + logerror("DMAC IRQ, vector = %x\n", m_dmac->iack()); dmac_irq_state = 1; - dmac_irq_vector = m_dmac->get_vector(offset); } else { @@ -435,25 +429,9 @@ WRITE8_MEMBER(vme_fcscsi1_card_device::dma_end) update_irq_to_maincpu(); } -WRITE8_MEMBER(vme_fcscsi1_card_device::dma_error) +WRITE_LINE_MEMBER(vme_fcscsi1_card_device::fdc_irq) { - if(data != 0) - { - logerror("DMAC error, vector = %x\n", m_dmac->get_error_vector(offset)); - dmac_irq_state = 1; - dmac_irq_vector = m_dmac->get_vector(offset); - } - else - { - dmac_irq_state = 0; - } - - update_irq_to_maincpu(); -} - -WRITE8_MEMBER(vme_fcscsi1_card_device::fdc_irq) -{ - if (data != 0) + if (state != 0) { fdc_irq_state = 1; } diff --git a/src/devices/bus/vme/vme_fcscsi.h b/src/devices/bus/vme/vme_fcscsi.h index 02f22d1eaa1..fa0622f8c99 100644 --- a/src/devices/bus/vme/vme_fcscsi.h +++ b/src/devices/bus/vme/vme_fcscsi.h @@ -32,15 +32,13 @@ protected: uint8_t fdc_irq_state; uint8_t dmac_irq_state; - int dmac_irq_vector; private: //dmac - DECLARE_WRITE8_MEMBER(dma_end); - DECLARE_WRITE8_MEMBER(dma_error); + DECLARE_WRITE_LINE_MEMBER(dma_irq); //fdc - DECLARE_WRITE8_MEMBER(fdc_irq); + DECLARE_WRITE_LINE_MEMBER(fdc_irq); DECLARE_READ8_MEMBER(fdc_read_byte); DECLARE_WRITE8_MEMBER(fdc_write_byte); DECLARE_FLOPPY_FORMATS(floppy_formats); diff --git a/src/devices/machine/hd63450.cpp b/src/devices/machine/hd63450.cpp index 25932cec032..44343895fa9 100644 --- a/src/devices/machine/hd63450.cpp +++ b/src/devices/machine/hd63450.cpp @@ -16,8 +16,8 @@ DEFINE_DEVICE_TYPE(HD63450, hd63450_device, "hd63450", "Hitachi HD63450 DMAC") hd63450_device::hd63450_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, HD63450, tag, owner, clock), + m_irq_callback(*this), m_dma_end(*this), - m_dma_error(*this), m_dma_read{{*this}, {*this}, {*this}, {*this}}, m_dma_write{{*this}, {*this}, {*this}, {*this}}, m_cpu(*this, finder_base::DUMMY_TAG) @@ -43,8 +43,8 @@ hd63450_device::hd63450_device(const machine_config &mconfig, const char *tag, d void hd63450_device::device_start() { // resolve callbacks - m_dma_end.resolve(); - m_dma_error.resolve_safe(); + m_irq_callback.resolve_safe(); + m_dma_end.resolve_safe(); for (auto &cb : m_dma_read) cb.resolve(); for (auto &cb : m_dma_write) @@ -77,10 +77,13 @@ void hd63450_device::device_start() save_item(NAME(m_transfer_size)); save_item(NAME(m_halted)); save_item(NAME(m_drq_state)); + save_item(NAME(m_irq_channel)); } void hd63450_device::device_reset() { + // Device is reset by pulling /BEC0-/BEC2 all low for 10 clocks + for (int x = 0; x < 4; x++) { m_reg[x].niv = 0x0f; @@ -97,6 +100,9 @@ void hd63450_device::device_reset() m_timer[x]->adjust(attotime::never); m_halted[x] = 0; } + + m_irq_channel = -1; + m_irq_callback(CLEAR_LINE); } READ16_MEMBER(hd63450_device::read) @@ -166,6 +172,9 @@ WRITE16_MEMBER(hd63450_device::write) // Clearing ERR also resets CER (which is otherwise read-only) if ((data & 0x1000) != 0) m_reg[channel].cer = 0; + + if ((m_reg[channel].csr & 0xf2) == 0) + clear_irq(channel); } break; case 0x02: // DCR / OCR @@ -317,11 +326,7 @@ void hd63450_device::dma_transfer_abort(int channel) LOG("DMA#%i: Transfer aborted\n",channel); m_timer[channel]->adjust(attotime::never); - m_reg[channel].csr |= 0x90; // channel error - m_reg[channel].csr &= ~0x08; // channel no longer active - m_reg[channel].cer = 0x11; - m_reg[channel].ccr &= ~0xc0; - m_dma_error((offs_t)3, m_reg[channel].ccr & 0x08); + set_error(channel, 0x11); } void hd63450_device::dma_transfer_halt(int channel) @@ -467,11 +472,21 @@ void hd63450_device::single_transfer(int x) m_cpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); } - if (!m_dma_end.isnull()) - m_dma_end((offs_t)x, m_reg[x].ccr & 0x08); + m_dma_end((offs_t)x, 0); + set_irq(x); } } +void hd63450_device::set_error(int channel, uint8_t code) +{ + m_reg[channel].csr |= 0x90; // channel error + m_reg[channel].csr &= ~0x08; // channel no longer active + m_reg[channel].cer = code; + m_reg[channel].ccr &= ~0xc0; + + set_irq(channel); +} + WRITE_LINE_MEMBER(hd63450_device::drq0_w) { bool ostate = m_drq_state[0]; @@ -529,12 +544,52 @@ WRITE_LINE_MEMBER(hd63450_device::drq3_w) m_timer[3]->adjust(attotime::never); } -int hd63450_device::get_vector(int channel) +void hd63450_device::set_irq(int channel) { - return m_reg[channel].niv; + if ((m_reg[channel].ccr & 0x08) == 0) + return; + + if (m_irq_channel == -1) + { + m_irq_channel = channel; + m_irq_callback(ASSERT_LINE); + } + else if ((m_reg[channel].cpr & 0x03) < (m_reg[m_irq_channel].cpr & 0x03)) + m_irq_channel = channel; } -int hd63450_device::get_error_vector(int channel) +void hd63450_device::clear_irq(int channel) { - return m_reg[channel].eiv; + if (m_irq_channel != channel) + return; + + for (int pri = m_reg[channel].cpr & 0x03; pri <= 3; pri++) + { + for (int offset = 1; offset <= 3; offset++) + { + if ((m_reg[(channel + offset) & 3].ccr & 0x08) != 0 && + (m_reg[(channel + offset) & 3].csr & 0xf2) != 0) + { + m_irq_channel = (channel + offset) & 3; + return; + } + } + } + + m_irq_channel = -1; + m_irq_callback(CLEAR_LINE); +} + +uint8_t hd63450_device::iack() +{ + if (m_irq_channel != -1) + { + if ((m_reg[m_irq_channel].csr & 0x10) != 0) + return m_reg[m_irq_channel].eiv; + else + return m_reg[m_irq_channel].niv; + } + + // Spurious interrupt (no response actually) + return 0x18; } diff --git a/src/devices/machine/hd63450.h b/src/devices/machine/hd63450.h index cf0381937bf..63e32c5a5d6 100644 --- a/src/devices/machine/hd63450.h +++ b/src/devices/machine/hd63450.h @@ -20,8 +20,8 @@ public: hd63450_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + auto irq_callback() { return m_irq_callback.bind(); } auto dma_end() { return m_dma_end.bind(); } - auto dma_error() { return m_dma_error.bind(); } template<int Ch> auto dma_read() { return m_dma_read[Ch].bind(); } template<int Ch> auto dma_write() { return m_dma_write[Ch].bind(); } @@ -47,11 +47,10 @@ public: DECLARE_WRITE_LINE_MEMBER(drq1_w); DECLARE_WRITE_LINE_MEMBER(drq2_w); DECLARE_WRITE_LINE_MEMBER(drq3_w); + uint8_t iack(); void single_transfer(int x); void set_timer(int channel, const attotime &tm); - int get_vector(int channel); - int get_error_vector(int channel); protected: // device-level overrides @@ -81,8 +80,8 @@ private: uint8_t gcr; // [3f] General Control Register (R/W) }; + devcb_write_line m_irq_callback; devcb_write8 m_dma_end; - devcb_write8 m_dma_error; devcb_read8 m_dma_read[4]; devcb_write8 m_dma_write[4]; @@ -97,6 +96,8 @@ private: required_device<cpu_device> m_cpu; bool m_drq_state[4]; + int8_t m_irq_channel; + // tell if a channel is in use bool dma_in_progress(int channel) const { return (m_reg[channel].csr & 0x08) != 0; } @@ -105,6 +106,11 @@ private: void dma_transfer_halt(int channel); void dma_transfer_continue(int channel); void dma_transfer_start(int channel); + void set_error(int channel, uint8_t code); + + // interrupt helpers + void set_irq(int channel); + void clear_irq(int channel); }; DECLARE_DEVICE_TYPE(HD63450, hd63450_device) diff --git a/src/mame/drivers/esq5505.cpp b/src/mame/drivers/esq5505.cpp index 3aa75ca76ab..9cfc251f3cc 100644 --- a/src/mame/drivers/esq5505.cpp +++ b/src/mame/drivers/esq5505.cpp @@ -229,9 +229,7 @@ private: uint8_t m_duart_io; uint8_t otis_irq_state; uint8_t dmac_irq_state; - int dmac_irq_vector; uint8_t duart_irq_state; - int duart_irq_vector; void update_irq_to_maincpu(); @@ -246,8 +244,7 @@ private: uint16_t m_analog_values[8]; //dmac - DECLARE_WRITE8_MEMBER(dma_end); - DECLARE_WRITE8_MEMBER(dma_error); + DECLARE_WRITE_LINE_MEMBER(dma_irq); }; FLOPPY_FORMATS_MEMBER( esq5505_state::floppy_formats ) @@ -257,8 +254,8 @@ FLOPPY_FORMATS_END void esq5505_state::cpu_space_map(address_map &map) { map(0xfffff0, 0xffffff).m(m_maincpu, FUNC(m68000_base_device::autovectors_map)); - map(0xfffff4, 0xfffff5).lr16("dmac irq", [this]() -> u16 { return dmac_irq_vector; }); - map(0xfffff6, 0xfffff7).lr16("duart irq", [this]() -> u16 { return duart_irq_vector; }); + map(0xfffff5, 0xfffff5).r(m_dmac, FUNC(hd63450_device::iack)); + map(0xfffff7, 0xfffff7).r(m_duart, FUNC(mc68681_device::get_irq_vector)); } void esq5505_state::machine_start() @@ -448,12 +445,11 @@ WRITE_LINE_MEMBER(esq5505_state::duart_irq_handler) // printf("\nDUART IRQ: state %d vector %d\n", state, vector); if (state == ASSERT_LINE) { - duart_irq_vector = m_duart->get_irq_vector(); duart_irq_state = 1; } else { - duart_irq_state = 0; + duart_irq_state = 0; } update_irq_to_maincpu(); } @@ -524,30 +520,12 @@ WRITE_LINE_MEMBER(esq5505_state::duart_tx_b) m_panel->rx_w(state); } -WRITE8_MEMBER(esq5505_state::dma_end) +WRITE_LINE_MEMBER(esq5505_state::dma_irq) { - if (data != 0) + if (state != CLEAR_LINE) { - //printf("DMAC IRQ, vector = %x\n", m_dmac->get_vector(offset)); + logerror("DMAC error, vector = %x\n", m_dmac->iack()); dmac_irq_state = 1; - dmac_irq_vector = m_dmac->get_vector(offset); - } - else - { - dmac_irq_state = 0; - } - - // printf("IRQ update from DMAC: have OTIS=%d, DMAC=%d, DUART=%d\n", otis_irq_state, dmac_irq_state, duart_irq_state); - update_irq_to_maincpu(); -} - -WRITE8_MEMBER(esq5505_state::dma_error) -{ - if(data != 0) - { - logerror("DMAC error, vector = %x\n", m_dmac->get_error_vector(offset)); - dmac_irq_state = 1; - dmac_irq_vector = m_dmac->get_vector(offset); } else { @@ -683,8 +661,7 @@ void esq5505_state::eps(machine_config &config) m_dmac->set_cpu_tag(m_maincpu); m_dmac->set_clocks(attotime::from_usec(32), attotime::from_nsec(450), attotime::from_usec(4), attotime::from_hz(15625/2)); m_dmac->set_burst_clocks(attotime::from_usec(32), attotime::from_nsec(450), attotime::from_nsec(50), attotime::from_nsec(50)); - m_dmac->dma_end().set(FUNC(esq5505_state::dma_end)); - m_dmac->dma_error().set(FUNC(esq5505_state::dma_error)); + m_dmac->irq_callback().set(FUNC(esq5505_state::dma_irq)); m_dmac->dma_read<0>().set(m_fdc, FUNC(wd1772_device::data_r)); // ch 0 = fdc, ch 1 = 340001 (ADC?) m_dmac->dma_write<0>().set(m_fdc, FUNC(wd1772_device::data_w)); } diff --git a/src/mame/drivers/x68k.cpp b/src/mame/drivers/x68k.cpp index bbc00fd67ef..e77750dcb06 100644 --- a/src/mame/drivers/x68k.cpp +++ b/src/mame/drivers/x68k.cpp @@ -313,7 +313,7 @@ TIMER_CALLBACK_MEMBER(x68k_state::scc_ack) { m_mouse.irqactive = 1; m_current_vector[5] = 0x54; - m_current_irq_line = 5; + //m_current_irq_line = 5; m_maincpu->set_input_line(5,ASSERT_LINE); } } @@ -680,7 +680,7 @@ WRITE_LINE_MEMBER( x68k_state::fdc_irq ) { m_current_vector[1] = m_ioc.fdcvector; m_ioc.irqstatus |= 0x80; - m_current_irq_line = 1; + //m_current_irq_line = 1; LOGMASKED(LOG_FDC, "FDC: IRQ triggered\n"); m_maincpu->set_input_line(1, ASSERT_LINE); } @@ -998,37 +998,24 @@ WRITE16_MEMBER(x68k_state::exp_w) set_bus_error((offset << 1) + 0xeafa00, 1, mem_mask); } -void x68k_state::dma_irq(int channel) +WRITE_LINE_MEMBER(x68k_state::dma_irq) { - m_current_vector[3] = m_hd63450->get_vector(channel); - m_current_irq_line = 3; - LOGMASKED(LOG_SYS, "DMA#%i: DMA End (vector 0x%02x)\n",channel,m_current_vector[3]); - m_maincpu->set_input_line(3,ASSERT_LINE); + if (state != CLEAR_LINE) + { + //m_current_irq_line = 3; + LOGMASKED(LOG_SYS, "DMA IRQ (vector 0x%02x)\n", m_hd63450->iack()); + } + m_maincpu->set_input_line(3, state); } WRITE8_MEMBER(x68k_state::dma_end) { - if(data != 0) - { - dma_irq(offset); - } if(offset == 0) { m_fdc_tc->adjust(attotime::from_usec(1), 0, attotime::never); } } -WRITE8_MEMBER(x68k_state::dma_error) -{ - if(data != 0) - { - m_current_vector[3] = m_hd63450->get_error_vector(offset); - m_current_irq_line = 3; - LOGMASKED(LOG_SYS, "DMA#%i: DMA Error (vector 0x%02x)\n",offset,m_current_vector[3]); - m_maincpu->set_input_line(3,ASSERT_LINE); - } -} - WRITE_LINE_MEMBER(x68k_state::fm_irq) { if(state == CLEAR_LINE) @@ -1104,7 +1091,7 @@ void x68k_state::cpu_space_map(address_map &map) map.global_mask(0xffffff); map(0xfffff3, 0xfffff3).r(FUNC(x68k_state::int_ack<1>)); map(0xfffff5, 0xfffff5).r(FUNC(x68k_state::int_ack<2>)); - map(0xfffff7, 0xfffff7).r(FUNC(x68k_state::int_ack<3>)); + map(0xfffff7, 0xfffff7).r(m_hd63450, FUNC(hd63450_device::iack)); map(0xfffff9, 0xfffff9).r(FUNC(x68k_state::int_ack<4>)); map(0xfffffb, 0xfffffb).r(FUNC(x68k_state::int_ack<5>)); map(0xfffffd, 0xfffffd).r(FUNC(x68k_state::mfp_ack)); @@ -1117,7 +1104,7 @@ WRITE_LINE_MEMBER(x68ksupr_state::scsi_irq) if(state != 0) { m_current_vector[1] = 0x6c; - m_current_irq_line = 1; + //m_current_irq_line = 1; m_maincpu->set_input_line(1,ASSERT_LINE); } } @@ -1383,7 +1370,7 @@ void x68k_state::floppy_load_unload(bool load, floppy_image_device *dev) { m_current_vector[1] = 0x61; m_ioc.irqstatus |= 0x40; - m_current_irq_line = 1; + //m_current_irq_line = 1; m_maincpu->set_input_line(1,ASSERT_LINE); // Disk insert/eject interrupt LOGMASKED(LOG_FDC, "IOC: Disk image inserted\n"); } @@ -1403,7 +1390,7 @@ void x68k_state::floppy_unload(floppy_image_device *dev) TIMER_CALLBACK_MEMBER(x68k_state::net_irq) { m_current_vector[2] = 0xf9; - m_current_irq_line = 2; + //m_current_irq_line = 2; m_maincpu->set_input_line(2,ASSERT_LINE); } @@ -1594,8 +1581,8 @@ void x68k_state::x68000_base(machine_config &config) HD63450(config, m_hd63450, 40_MHz_XTAL / 4, "maincpu"); m_hd63450->set_clocks(attotime::from_usec(2), attotime::from_nsec(450), attotime::from_usec(4), attotime::from_hz(15625/2)); m_hd63450->set_burst_clocks(attotime::from_usec(2), attotime::from_nsec(450), attotime::from_nsec(50), attotime::from_nsec(50)); + m_hd63450->irq_callback().set(FUNC(x68k_state::dma_irq)); m_hd63450->dma_end().set(FUNC(x68k_state::dma_end)); - m_hd63450->dma_error().set(FUNC(x68k_state::dma_error)); m_hd63450->dma_read<0>().set("upd72065", FUNC(upd72065_device::dma_r)); m_hd63450->dma_write<0>().set("upd72065", FUNC(upd72065_device::dma_w)); diff --git a/src/mame/includes/x68k.h b/src/mame/includes/x68k.h index 2712344c67f..c12110b5399 100644 --- a/src/mame/includes/x68k.h +++ b/src/mame/includes/x68k.h @@ -229,7 +229,7 @@ protected: } m_mdctrl; uint8_t m_ppi_port[3]; int m_current_vector[8]; - uint8_t m_current_irq_line; + //uint8_t m_current_irq_line; int m_led_state; emu_timer* m_mouse_timer; emu_timer* m_led_timer; @@ -270,9 +270,8 @@ protected: DECLARE_WRITE_LINE_MEMBER(mfp_irq_callback); //dmac - void dma_irq(int channel); + DECLARE_WRITE_LINE_MEMBER(dma_irq); DECLARE_WRITE8_MEMBER(dma_end); - DECLARE_WRITE8_MEMBER(dma_error); int read_mouse(); void set_adpcm(); |