pic8259: Emulate three-cycle acknowledge for non-8086 mode

This commit is contained in:
AJR 2020-05-08 08:24:12 -04:00
parent af74a6d50f
commit 015b1ab880
17 changed files with 124 additions and 58 deletions

View File

@ -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);

View File

@ -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();
}

View File

@ -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

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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()));

View File

@ -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);

View File

@ -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);

View File

@ -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));

View File

@ -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;
}

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);