mirror of
https://github.com/holub/mame
synced 2025-06-30 07:58:56 +03:00
pic8259: Emulate three-cycle acknowledge for non-8086 mode
This commit is contained in:
parent
af74a6d50f
commit
015b1ab880
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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()));
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user