diff --git a/src/devices/machine/i82357.cpp b/src/devices/machine/i82357.cpp index 7fa9a62d556..80319a8a52a 100644 --- a/src/devices/machine/i82357.cpp +++ b/src/devices/machine/i82357.cpp @@ -46,12 +46,12 @@ void i82357_device::device_add_mconfig(machine_config &config) PIC8259(config, m_pic[0], 0); m_pic[0]->in_sp_callback().set_constant(1); m_pic[0]->read_slave_ack_callback().set( - [this](offs_t offset) + [this](offs_t offset) -> u8 { if (offset == 2) return m_pic[1]->acknowledge(); - return u32(0); + return 0; }); PIC8259(config, m_pic[1], 0); diff --git a/src/devices/machine/pic8259.cpp b/src/devices/machine/pic8259.cpp index b7e048170ed..bc1b4b72411 100644 --- a/src/devices/machine/pic8259.cpp +++ b/src/devices/machine/pic8259.cpp @@ -39,14 +39,15 @@ void pic8259_device::device_timer(emu_timer &timer, device_timer_id id, int para /* is this IRQ in service and not cascading and sfnm? */ if ((m_isr & mask) && !(m_master && m_cascade && m_nested && (m_slave & mask))) { - LOG("pic8259_timerproc(): PIC IRQ #%d still in service\n", irq); + LOG("pic8259_timerproc(): PIC IR%d still in service\n", irq); break; } /* is this IRQ pending and enabled? */ if ((m_state == state_t::READY) && (m_irr & mask) && !(m_imr & mask)) { - LOG("pic8259_timerproc(): PIC triggering IRQ #%d\n", irq); + LOG("pic8259_timerproc(): PIC triggering IR%d\n", irq); + m_current_level = irq; m_out_int_func(1); return; } @@ -54,6 +55,7 @@ void pic8259_device::device_timer(emu_timer &timer, device_timer_id id, int para if((m_isr & mask) && m_master && m_cascade && m_nested && (m_slave & mask)) break; } + m_current_level = -1; m_out_int_func(0); } @@ -64,7 +66,7 @@ void pic8259_device::set_irq_line(int irq, int state) if (state) { /* setting IRQ line */ - LOG("set_irq_line(): PIC set IRQ line #%d\n", irq); + LOG("set_irq_line(): PIC set IR%d line\n", irq); if(m_level_trig_mode || (!m_level_trig_mode && !(m_irq_lines & mask))) { @@ -75,26 +77,28 @@ void pic8259_device::set_irq_line(int irq, int state) else { /* clearing IRQ line */ - LOG("set_irq_line(): PIC cleared IRQ line #%d\n", irq); + LOG("set_irq_line(): PIC cleared IR%d line\n", irq); m_irq_lines &= ~mask; m_irr &= ~mask; } - set_timer(); + + if (m_inta_sequence == 0) + set_timer(); } -uint32_t pic8259_device::acknowledge() +uint8_t pic8259_device::acknowledge() { - for (int n = 0, irq = m_prio; n < 8; n++, irq = (irq + 1) & 7) + if (is_x86()) { - uint8_t mask = 1 << irq; - /* is this IRQ pending and enabled? */ - if ((m_irr & mask) && !(m_imr & mask)) + if (m_current_level != -1) { - if (!machine().side_effects_disabled()) { - LOG("pic8259_acknowledge(): PIC acknowledge IRQ #%d\n", irq); + uint8_t mask = 1 << m_current_level; + if (!machine().side_effects_disabled()) + { + LOG("pic8259_acknowledge(): PIC acknowledge IR%d\n", m_current_level); if (!m_level_trig_mode) m_irr &= ~mask; @@ -107,29 +111,70 @@ uint32_t pic8259_device::acknowledge() if ((m_cascade!=0) && (m_master!=0) && (mask & m_slave)) { // it's from slave device - return m_read_slave_ack_func(irq); + return m_read_slave_ack_func(m_current_level); } else { - if (is_x86()) - { - /* For x86 mode*/ - return irq + m_base; - } - else - { - /* in case of 8080/85) */ - return 0xcd0000 + (m_vector_addr_high << 8) + m_vector_addr_low + (irq << (3-m_vector_size)); - } + /* For x86 mode*/ + return m_current_level + m_base; } } + else + { + if (!machine().side_effects_disabled()) + logerror("Spurious INTA\n"); + return m_base + 7; + } } - if (!machine().side_effects_disabled()) - logerror("Spurious IRQ\n"); - if (is_x86()) - return m_base + 7; else - return 0xcd0000 + (m_vector_addr_high << 8) + m_vector_addr_low + (7 << (3-m_vector_size)); + { + /* in case of 8080/85 */ + if (m_inta_sequence == 0) + { + if (!machine().side_effects_disabled()) + { + if (m_current_level != -1) + { + LOG("pic8259_acknowledge(): PIC acknowledge IR%d\n", m_current_level); + + uint8_t mask = 1 << m_current_level; + if (!m_level_trig_mode) + m_irr &= ~mask; + m_isr |= mask; + } + else + logerror("Spurious INTA\n"); + m_inta_sequence = 1; + } + if (m_cascade && m_master && m_current_level != -1 && BIT(m_slave, m_current_level)) + return m_read_slave_ack_func(m_current_level); + else + return 0xcd; + } + else if (m_inta_sequence == 1) + { + if (!machine().side_effects_disabled()) + m_inta_sequence = 2; + if (m_cascade && m_master && m_current_level != -1 && BIT(m_slave, m_current_level)) + return m_read_slave_ack_func(m_current_level); + else + return m_vector_addr_low + ((m_current_level & 7) << (3-m_vector_size)); + } + else + { + if (!machine().side_effects_disabled()) + { + m_inta_sequence = 0; + if (m_auto_eoi && m_current_level != -1) + m_isr &= ~(1 << m_current_level); + set_timer(); + } + if (m_cascade && m_master && m_current_level != -1 && BIT(m_slave, m_current_level)) + return m_read_slave_ack_func(m_current_level); + else + return m_vector_addr_high; + } + } } @@ -138,6 +183,15 @@ IRQ_CALLBACK_MEMBER(pic8259_device::inta_cb) return acknowledge(); } +IRQ_CALLBACK_MEMBER(pic8259_device::inta_call) +{ + // FIXME: make 8085 and Z80 devices read CALL vectors one byte at a time, not all at once + uint32_t vector = acknowledge() << 16; + vector |= acknowledge(); + vector |= acknowledge() << 8; + return vector; +} + uint8_t pic8259_device::read(offs_t offset) { @@ -150,18 +204,17 @@ uint8_t pic8259_device::read(offs_t offset) if ( m_ocw3 & 0x04 ) { /* Polling mode */ - if ( m_irr & ~m_imr ) + if (m_current_level != -1) { - /* check the various IRQs */ - for (int n = 0, irq = m_prio; n < 8; n++, irq = (irq + 1) & 7) - { - if ( ( 1 << irq ) & m_irr & ~m_imr ) - { - data = 0x80 | irq; - break; - } - } - acknowledge(); + data = 0x80 | m_current_level; + + if (!m_level_trig_mode) + m_irr &= ~(1 << m_current_level); + + if (!m_auto_eoi) + m_isr |= 1 << m_current_level; + + set_timer(); } } else @@ -207,7 +260,9 @@ void pic8259_device::write(offs_t offset, uint8_t data) m_cascade = (data & 0x02) ? 0 : 1; m_icw4_needed = (data & 0x01) ? 1 : 0; m_vector_addr_low = (data & 0xe0); - m_state = state_t::ICW2; + m_state = state_t::ICW2; + m_current_level = -1; + m_inta_sequence = 0; m_out_int_func(0); } else if (m_state == state_t::READY) @@ -377,6 +432,8 @@ void pic8259_device::device_start() save_item(NAME(m_mode)); save_item(NAME(m_auto_eoi)); save_item(NAME(m_is_x86)); + save_item(NAME(m_current_level)); + save_item(NAME(m_inta_sequence)); } @@ -406,6 +463,8 @@ void pic8259_device::device_reset() m_is_x86 = 0; m_vector_addr_low = 0; m_vector_addr_high = 0; + m_current_level = -1; + m_inta_sequence = 0; m_master = m_in_sp_func(); } diff --git a/src/devices/machine/pic8259.h b/src/devices/machine/pic8259.h index f3968b4fdc1..93e3b4dcceb 100644 --- a/src/devices/machine/pic8259.h +++ b/src/devices/machine/pic8259.h @@ -39,7 +39,7 @@ public: uint8_t read(offs_t offset); void write(offs_t offset, uint8_t data); - uint32_t acknowledge(); + uint8_t acknowledge(); DECLARE_WRITE_LINE_MEMBER( ir0_w ) { set_irq_line(0, state); } DECLARE_WRITE_LINE_MEMBER( ir1_w ) { set_irq_line(1, state); } @@ -51,6 +51,7 @@ public: DECLARE_WRITE_LINE_MEMBER( ir7_w ) { set_irq_line(7, state); } IRQ_CALLBACK_MEMBER(inta_cb); + IRQ_CALLBACK_MEMBER(inta_call); protected: pic8259_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); @@ -81,7 +82,7 @@ private: devcb_write_line m_out_int_func; devcb_read_line m_in_sp_func; - devcb_read32 m_read_slave_ack_func; + devcb_read8 m_read_slave_ack_func; state_t m_state; @@ -113,6 +114,9 @@ private: uint8_t m_mode; uint8_t m_auto_eoi; uint8_t m_is_x86; + + int8_t m_current_level; + uint8_t m_inta_sequence; }; class v5x_icu_device : public pic8259_device diff --git a/src/mame/drivers/b2m.cpp b/src/mame/drivers/b2m.cpp index 929c08c7a36..33176cfa60b 100644 --- a/src/mame/drivers/b2m.cpp +++ b/src/mame/drivers/b2m.cpp @@ -193,7 +193,7 @@ void b2m_state::b2m(machine_config &config) m_maincpu->set_addrmap(AS_PROGRAM, &b2m_state::b2m_mem); m_maincpu->set_addrmap(AS_IO, &b2m_state::b2m_io); m_maincpu->set_vblank_int("screen", FUNC(b2m_state::b2m_vblank_interrupt)); - m_maincpu->set_irq_acknowledge_callback("pic8259", FUNC(pic8259_device::inta_cb)); + m_maincpu->set_irq_acknowledge_callback("pic8259", FUNC(pic8259_device::inta_call)); /* video hardware */ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); diff --git a/src/mame/drivers/dvk_ksm.cpp b/src/mame/drivers/dvk_ksm.cpp index 4ed4f335f49..2f0c3b72d9d 100644 --- a/src/mame/drivers/dvk_ksm.cpp +++ b/src/mame/drivers/dvk_ksm.cpp @@ -416,7 +416,7 @@ void ksm_state::ksm(machine_config &config) I8080(config, m_maincpu, XTAL(15'400'000)/10); m_maincpu->set_addrmap(AS_PROGRAM, &ksm_state::ksm_mem); m_maincpu->set_addrmap(AS_IO, &ksm_state::ksm_io); - m_maincpu->set_irq_acknowledge_callback("pic8259", FUNC(pic8259_device::inta_cb)); + m_maincpu->set_irq_acknowledge_callback("pic8259", FUNC(pic8259_device::inta_call)); TIMER(config, "scantimer").configure_scanline(FUNC(ksm_state::scanline_callback), "screen", 0, 1); diff --git a/src/mame/drivers/fastinvaders.cpp b/src/mame/drivers/fastinvaders.cpp index be476450b7a..c836b49a914 100644 --- a/src/mame/drivers/fastinvaders.cpp +++ b/src/mame/drivers/fastinvaders.cpp @@ -634,7 +634,7 @@ void fastinvaders_state::fastinvaders(machine_config &config) // m_maincpu->set_addrmap(AS_IO, &fastinvaders_state::fastinvaders_io_map); // m_maincpu->set_vblank_int("screen", FUNC(fastinvaders_state::irq0_line_hold)); m_maincpu->in_sid_func().set(FUNC(fastinvaders_state::sid_read)); - m_maincpu->set_irq_acknowledge_callback("pic8259", FUNC(pic8259_device::inta_cb)); + m_maincpu->set_irq_acknowledge_callback("pic8259", FUNC(pic8259_device::inta_call)); TIMER(config, "scantimer").configure_scanline(FUNC(fastinvaders_state::scanline_timer), "screen", 0, 1); diff --git a/src/mame/drivers/imds2.cpp b/src/mame/drivers/imds2.cpp index 1d059f11269..a175629243f 100644 --- a/src/mame/drivers/imds2.cpp +++ b/src/mame/drivers/imds2.cpp @@ -258,7 +258,7 @@ void imds2_state::imds2(machine_config &config) I8085A(config, m_ipccpu, IPC_XTAL_Y2); // CLK OUT = 4 MHz m_ipccpu->set_addrmap(AS_PROGRAM, &imds2_state::ipc_mem_map); m_ipccpu->set_addrmap(AS_IO, &imds2_state::ipc_io_map); - m_ipccpu->set_irq_acknowledge_callback("ipcsyspic", FUNC(pic8259_device::inta_cb)); + m_ipccpu->set_irq_acknowledge_callback("ipcsyspic", FUNC(pic8259_device::inta_call)); //config.set_maximum_quantum(attotime::from_hz(100)); PIC8259(config, m_ipcsyspic, 0); @@ -267,7 +267,7 @@ void imds2_state::imds2(machine_config &config) PIC8259(config, m_ipclocpic, 0); m_ipclocpic->out_int_callback().set(m_ipcsyspic, FUNC(pic8259_device::ir7_w)); - m_ipclocpic->in_sp_callback().set_constant(1); + m_ipclocpic->in_sp_callback().set_constant(0); PIT8253(config, m_ipctimer, 0); m_ipctimer->set_clk<0>(IPC_XTAL_Y1 / 16); diff --git a/src/mame/drivers/iq151.cpp b/src/mame/drivers/iq151.cpp index 21e39460884..941c30be802 100644 --- a/src/mame/drivers/iq151.cpp +++ b/src/mame/drivers/iq151.cpp @@ -395,7 +395,7 @@ void iq151_state::iq151(machine_config &config) m_maincpu->set_addrmap(AS_PROGRAM, &iq151_state::iq151_mem); m_maincpu->set_addrmap(AS_IO, &iq151_state::iq151_io); m_maincpu->set_vblank_int("screen", FUNC(iq151_state::iq151_vblank_interrupt)); - m_maincpu->set_irq_acknowledge_callback("pic8259", FUNC(pic8259_device::inta_cb)); + m_maincpu->set_irq_acknowledge_callback("pic8259", FUNC(pic8259_device::inta_call)); /* video hardware */ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER, rgb_t::green())); diff --git a/src/mame/drivers/isbc8030.cpp b/src/mame/drivers/isbc8030.cpp index 36752136c1f..6e3c6018f54 100644 --- a/src/mame/drivers/isbc8030.cpp +++ b/src/mame/drivers/isbc8030.cpp @@ -90,6 +90,7 @@ void isbc8030_state::isbc8030(machine_config &config) I8085A(config, m_maincpu, XTAL(22'118'400) / 4); m_maincpu->set_addrmap(AS_PROGRAM, &isbc8030_state::isbc8030_mem); m_maincpu->set_addrmap(AS_IO, &isbc8030_state::isbc8030_io); + m_maincpu->set_irq_acknowledge_callback(m_pic, FUNC(pic8259_device::inta_call)); PIC8259(config, m_pic, 0); m_pic->out_int_callback().set_inputline(m_maincpu, 0); diff --git a/src/mame/drivers/juku.cpp b/src/mame/drivers/juku.cpp index 0da5ae5672a..e010f881ea9 100644 --- a/src/mame/drivers/juku.cpp +++ b/src/mame/drivers/juku.cpp @@ -456,7 +456,7 @@ void juku_state::juku(machine_config &config) I8080A(config, m_maincpu, 2000000); m_maincpu->set_addrmap(AS_PROGRAM, &juku_state::mem_map); m_maincpu->set_addrmap(AS_IO, &juku_state::io_map); - m_maincpu->set_irq_acknowledge_callback("pic", FUNC(pic8259_device::inta_cb)); + m_maincpu->set_irq_acknowledge_callback("pic", FUNC(pic8259_device::inta_call)); ADDRESS_MAP_BANK(config, m_bank); m_bank->set_map(&juku_state::bank_map); diff --git a/src/mame/drivers/okean240.cpp b/src/mame/drivers/okean240.cpp index 207089c5ae5..9501f21f970 100644 --- a/src/mame/drivers/okean240.cpp +++ b/src/mame/drivers/okean240.cpp @@ -513,6 +513,7 @@ void okean240_state::okean240t(machine_config &config) I8080(config, m_maincpu, XTAL(12'000'000) / 6); m_maincpu->set_addrmap(AS_PROGRAM, &okean240_state::okean240_mem); m_maincpu->set_addrmap(AS_IO, &okean240_state::okean240t_io); + m_maincpu->set_irq_acknowledge_callback("pic", FUNC(pic8259_device::inta_call)); i8251_device &uart(I8251(config, "uart", 0)); uart.txd_handler().set("rs232", FUNC(rs232_port_device::write_txd)); diff --git a/src/mame/drivers/olyboss.cpp b/src/mame/drivers/olyboss.cpp index f1a667f5f88..22465931d9f 100644 --- a/src/mame/drivers/olyboss.cpp +++ b/src/mame/drivers/olyboss.cpp @@ -255,7 +255,7 @@ WRITE_LINE_MEMBER( olyboss_state::romdis_w ) IRQ_CALLBACK_MEMBER( olyboss_state::irq_cb ) { if(!irqline) - return m_pic->acknowledge(); + return m_pic->inta_call(device, 0); return 0; } diff --git a/src/mame/drivers/pk8020.cpp b/src/mame/drivers/pk8020.cpp index e533baba70a..0dcd791e172 100644 --- a/src/mame/drivers/pk8020.cpp +++ b/src/mame/drivers/pk8020.cpp @@ -241,7 +241,7 @@ void pk8020_state::pk8020(machine_config &config) m_maincpu->set_addrmap(AS_PROGRAM, &pk8020_state::pk8020_mem); m_maincpu->set_addrmap(AS_IO, &pk8020_state::pk8020_io); m_maincpu->set_vblank_int("screen", FUNC(pk8020_state::pk8020_interrupt)); - m_maincpu->set_irq_acknowledge_callback("inr", FUNC(pic8259_device::inta_cb)); + m_maincpu->set_irq_acknowledge_callback("inr", FUNC(pic8259_device::inta_call)); PLS100(config, m_decplm); // КР556РТ2 (82S100 equivalent; D31) diff --git a/src/mame/drivers/qx10.cpp b/src/mame/drivers/qx10.cpp index dbe89116984..74dd553aa6b 100644 --- a/src/mame/drivers/qx10.cpp +++ b/src/mame/drivers/qx10.cpp @@ -113,7 +113,7 @@ private: DECLARE_WRITE_LINE_MEMBER( tc_w ); DECLARE_READ8_MEMBER( mc146818_r ); DECLARE_WRITE8_MEMBER( mc146818_w ); - DECLARE_READ32_MEMBER( get_slave_ack ); + uint8_t get_slave_ack(offs_t offset); DECLARE_READ8_MEMBER( vram_bank_r ); DECLARE_WRITE8_MEMBER( vram_bank_w ); DECLARE_READ16_MEMBER( vram_r ); @@ -504,7 +504,7 @@ WRITE_LINE_MEMBER(qx10_state::keyboard_clk) IR7 Slave cascade */ -READ32_MEMBER( qx10_state::get_slave_ack ) +uint8_t qx10_state::get_slave_ack(offs_t offset) { if (offset==7) { // IRQ = 7 return m_pic_s->acknowledge(); @@ -727,7 +727,7 @@ void qx10_state::qx10(machine_config &config) Z80(config, m_maincpu, MAIN_CLK / 4); m_maincpu->set_addrmap(AS_PROGRAM, &qx10_state::qx10_mem); m_maincpu->set_addrmap(AS_IO, &qx10_state::qx10_io); - m_maincpu->set_irq_acknowledge_callback("pic8259_master", FUNC(pic8259_device::inta_cb)); + m_maincpu->set_irq_acknowledge_callback("pic8259_master", FUNC(pic8259_device::inta_call)); /* video hardware */ SCREEN(config, m_screen, SCREEN_TYPE_RASTER); diff --git a/src/mame/drivers/sm7238.cpp b/src/mame/drivers/sm7238.cpp index 9b86da964d7..a4ae72a188e 100644 --- a/src/mame/drivers/sm7238.cpp +++ b/src/mame/drivers/sm7238.cpp @@ -357,7 +357,7 @@ void sm7238_state::sm7238(machine_config &config) I8080(config, m_maincpu, 16.5888_MHz_XTAL/9); m_maincpu->set_addrmap(AS_PROGRAM, &sm7238_state::sm7238_mem); m_maincpu->set_addrmap(AS_IO, &sm7238_state::sm7238_io); - m_maincpu->set_irq_acknowledge_callback("pic8259", FUNC(pic8259_device::inta_cb)); + m_maincpu->set_irq_acknowledge_callback("pic8259", FUNC(pic8259_device::inta_call)); ADDRESS_MAP_BANK(config, "videobank").set_map(&sm7238_state::videobank_map).set_options(ENDIANNESS_LITTLE, 8, 32, 0x2000); diff --git a/src/mame/drivers/tdv2324.cpp b/src/mame/drivers/tdv2324.cpp index a5add5199fa..34c98f64925 100644 --- a/src/mame/drivers/tdv2324.cpp +++ b/src/mame/drivers/tdv2324.cpp @@ -270,6 +270,7 @@ void tdv2324_state::tdv2324(machine_config &config) I8085A(config, m_maincpu, 8700000/2); // ??? m_maincpu->set_addrmap(AS_PROGRAM, &tdv2324_state::tdv2324_mem); m_maincpu->set_addrmap(AS_IO, &tdv2324_state::tdv2324_io); + m_maincpu->set_irq_acknowledge_callback("pic", FUNC(pic8259_device::inta_call)); I8085A(config, m_subcpu, 8000000/2); // ??? m_subcpu->set_addrmap(AS_PROGRAM, &tdv2324_state::tdv2324_sub_mem); diff --git a/src/mame/drivers/vta2000.cpp b/src/mame/drivers/vta2000.cpp index 23e2226eafe..13fcfeaf03b 100644 --- a/src/mame/drivers/vta2000.cpp +++ b/src/mame/drivers/vta2000.cpp @@ -186,7 +186,7 @@ void vta2000_state::vta2000(machine_config &config) I8080(config, m_maincpu, XTAL(4'000'000) / 4); m_maincpu->set_addrmap(AS_PROGRAM, &vta2000_state::mem_map); m_maincpu->set_addrmap(AS_IO, &vta2000_state::io_map); - m_maincpu->set_irq_acknowledge_callback("pic", FUNC(pic8259_device::inta_cb)); + m_maincpu->set_irq_acknowledge_callback("pic", FUNC(pic8259_device::inta_call)); PIT8253(config, m_mainpit, 0); m_mainpit->set_clk<0>(500'000);