mirror of
https://github.com/holub/mame
synced 2025-06-07 05:13:46 +03:00
more interrupt handling improvements
This commit is contained in:
parent
2248bac617
commit
c8f4403de6
@ -136,9 +136,6 @@ void clipper_device::execute_run()
|
|||||||
|
|
||||||
LOG_INTERRUPT("non-maskable interrupt - current pc = 0x%08x\n", m_pc);
|
LOG_INTERRUPT("non-maskable interrupt - current pc = 0x%08x\n", m_pc);
|
||||||
m_pc = intrap(EXCEPTION_INTERRUPT_BASE, m_pc);
|
m_pc = intrap(EXCEPTION_INTERRUPT_BASE, m_pc);
|
||||||
|
|
||||||
// FIXME: should m_nmi be cleared by the ioga doing CLEAR_LINE after acknowledgement?
|
|
||||||
m_nmi = 0;
|
|
||||||
}
|
}
|
||||||
else if (m_ssw.bits.ei && m_irq)
|
else if (m_ssw.bits.ei && m_irq)
|
||||||
{
|
{
|
||||||
@ -154,9 +151,6 @@ void clipper_device::execute_run()
|
|||||||
|
|
||||||
LOG_INTERRUPT("accepting interrupt vector 0x%04x - current pc = %08x\n", ivec, m_pc);
|
LOG_INTERRUPT("accepting interrupt vector 0x%04x - current pc = %08x\n", ivec, m_pc);
|
||||||
m_pc = intrap(EXCEPTION_INTERRUPT_BASE + ivec * 8, m_pc);
|
m_pc = intrap(EXCEPTION_INTERRUPT_BASE + ivec * 8, m_pc);
|
||||||
|
|
||||||
// FIXME: should m_irq be cleared by the ioga doing CLEAR_LINE after acknowledgement?
|
|
||||||
m_irq = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,8 @@ void interpro_ioga_device::device_start()
|
|||||||
|
|
||||||
void interpro_ioga_device::device_reset()
|
void interpro_ioga_device::device_reset()
|
||||||
{
|
{
|
||||||
m_interrupt = 0;
|
m_irq_active = false;
|
||||||
|
|
||||||
m_state_drq = 0;
|
m_state_drq = 0;
|
||||||
|
|
||||||
// configure timer 0 at 60Hz
|
// configure timer 0 at 60Hz
|
||||||
@ -89,7 +90,7 @@ void interpro_ioga_device::device_timer(emu_timer &timer, device_timer_id id, in
|
|||||||
if (m_timer_reg[1] == 0)
|
if (m_timer_reg[1] == 0)
|
||||||
{
|
{
|
||||||
// disable timer
|
// disable timer
|
||||||
m_timer[3]->enable(false);
|
timer.enable(false);
|
||||||
|
|
||||||
// set expired flag
|
// set expired flag
|
||||||
m_timer_reg[1] |= IOGA_TIMER1_EXPIRED;
|
m_timer_reg[1] |= IOGA_TIMER1_EXPIRED;
|
||||||
@ -104,7 +105,7 @@ void interpro_ioga_device::device_timer(emu_timer &timer, device_timer_id id, in
|
|||||||
if (m_timer_reg[3] == 0)
|
if (m_timer_reg[3] == 0)
|
||||||
{
|
{
|
||||||
// disable timer
|
// disable timer
|
||||||
m_timer[3]->enable(false);
|
timer.enable(false);
|
||||||
|
|
||||||
// set expired flag
|
// set expired flag
|
||||||
m_timer_reg[3] |= IOGA_TIMER3_EXPIRED;
|
m_timer_reg[3] |= IOGA_TIMER3_EXPIRED;
|
||||||
@ -245,19 +246,55 @@ C8 : ethernet address C 4039f088 // IOGA_ETHADDR_C
|
|||||||
17 timer 0
|
17 timer 0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void interpro_ioga_device::update_irq(int state)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case CLEAR_LINE:
|
||||||
|
if (m_irq_active)
|
||||||
|
{
|
||||||
|
// the cpu has acknowledged the active interrupt, deassert the irq line
|
||||||
|
m_irq_active = false;
|
||||||
|
m_out_int_func(CLEAR_LINE);
|
||||||
|
|
||||||
|
}
|
||||||
|
// fall through to handle any pending interrupts
|
||||||
|
|
||||||
|
case ASSERT_LINE:
|
||||||
|
// if an irq is currently active, don't do anything
|
||||||
|
if (!m_irq_active)
|
||||||
|
{
|
||||||
|
// check for any pending interrupts
|
||||||
|
for (int irq = 0; irq < 19; irq++)
|
||||||
|
{
|
||||||
|
if (m_vectors[irq] & IOGA_INTERRUPT_PENDING)
|
||||||
|
{
|
||||||
|
m_irq_active = true;
|
||||||
|
m_irq_current = irq;
|
||||||
|
|
||||||
|
m_out_int_func(ASSERT_LINE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void interpro_ioga_device::set_irq_line(int irq, int state)
|
void interpro_ioga_device::set_irq_line(int irq, int state)
|
||||||
{
|
{
|
||||||
LOG_INTERRUPT("set_irq_line(%d, %d)\n", irq, state);
|
LOG_INTERRUPT("set_irq_line(%d, %d)\n", irq, state);
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case ASSERT_LINE:
|
case ASSERT_LINE:
|
||||||
|
// FIXME: handle internal/external interrupts properly
|
||||||
if (m_vectors[irq] & (IOGA_INTERRUPT_ENABLE_EXTERNAL | IOGA_INTERRUPT_ENABLE_INTERNAL))
|
if (m_vectors[irq] & (IOGA_INTERRUPT_ENABLE_EXTERNAL | IOGA_INTERRUPT_ENABLE_INTERNAL))
|
||||||
{
|
{
|
||||||
// set interrupt pending bit
|
// set interrupt pending bit
|
||||||
m_vectors[irq] |= IOGA_INTERRUPT_PENDING;
|
m_vectors[irq] |= IOGA_INTERRUPT_PENDING;
|
||||||
|
|
||||||
m_interrupt = irq;
|
// update irq line state
|
||||||
m_out_int_func(ASSERT_LINE);
|
update_irq(state);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LOG_INTERRUPT("received disabled interrupt irq %d vector 0x%04x\n", irq, m_vectors[irq]);
|
LOG_INTERRUPT("received disabled interrupt irq %d vector 0x%04x\n", irq, m_vectors[irq]);
|
||||||
@ -267,7 +304,8 @@ void interpro_ioga_device::set_irq_line(int irq, int state)
|
|||||||
// clear interrupt pending bit
|
// clear interrupt pending bit
|
||||||
m_vectors[irq] &= ~IOGA_INTERRUPT_PENDING;
|
m_vectors[irq] &= ~IOGA_INTERRUPT_PENDING;
|
||||||
|
|
||||||
m_out_int_func(CLEAR_LINE);
|
// update irq line state
|
||||||
|
update_irq(state);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,16 +315,24 @@ IRQ_CALLBACK_MEMBER(interpro_ioga_device::inta_cb)
|
|||||||
switch (irqline)
|
switch (irqline)
|
||||||
{
|
{
|
||||||
case -1:
|
case -1:
|
||||||
// return vector for current interrupt without acknowledgement
|
// return vector for current interrupt without clearing irq line
|
||||||
return m_vectors[m_interrupt] & 0xff;
|
return m_vectors[m_irq_current] & 0xff;
|
||||||
|
|
||||||
case INPUT_LINE_IRQ0:
|
case INPUT_LINE_IRQ0:
|
||||||
// acknowledge interrupt
|
// FIXME: clear pending bit - can't rely on device callbacks
|
||||||
// FIXME: clear IRQ
|
m_vectors[m_irq_current] &= ~IOGA_INTERRUPT_PENDING;
|
||||||
return m_vectors[m_interrupt] & 0xff;
|
|
||||||
|
// clear irq line
|
||||||
|
update_irq(CLEAR_LINE);
|
||||||
|
|
||||||
|
// return interrupt vector
|
||||||
|
return m_vectors[m_irq_current] & 0xff;
|
||||||
|
|
||||||
case INPUT_LINE_NMI:
|
case INPUT_LINE_NMI:
|
||||||
//return m_nmictrl;
|
// clear nmi line
|
||||||
|
m_out_nmi_func(CLEAR_LINE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
@ -351,6 +397,8 @@ WRITE16_MEMBER(interpro_ioga_device::icr_w)
|
|||||||
{
|
{
|
||||||
LOG_INTERRUPT("interrupt vector %d set to 0x%04x at pc 0x%08x\n", offset, data, space.device().safe_pc());
|
LOG_INTERRUPT("interrupt vector %d set to 0x%04x at pc 0x%08x\n", offset, data, space.device().safe_pc());
|
||||||
|
|
||||||
|
// FIXME: now that the interrupt handling only depends on IOGA_INTERRUPT_PENDING, we might be able
|
||||||
|
// to avoid this hack
|
||||||
if (data & IOGA_INTERRUPT_PENDING)
|
if (data & IOGA_INTERRUPT_PENDING)
|
||||||
m_vectors[offset] = (data | IOGA_INTERRUPT_FORCED) & ~IOGA_INTERRUPT_PENDING;
|
m_vectors[offset] = (data | IOGA_INTERRUPT_FORCED) & ~IOGA_INTERRUPT_PENDING;
|
||||||
else if (m_vectors[offset] & IOGA_INTERRUPT_FORCED)
|
else if (m_vectors[offset] & IOGA_INTERRUPT_FORCED)
|
||||||
|
@ -117,15 +117,20 @@ private:
|
|||||||
void set_irq_line(int irq, int state);
|
void set_irq_line(int irq, int state);
|
||||||
void write_timer(int timer, uint32_t value, device_timer_id id);
|
void write_timer(int timer, uint32_t value, device_timer_id id);
|
||||||
|
|
||||||
|
void update_irq(int state);
|
||||||
|
|
||||||
devcb_write_line m_out_nmi_func;
|
devcb_write_line m_out_nmi_func;
|
||||||
devcb_write_line m_out_int_func;
|
devcb_write_line m_out_int_func;
|
||||||
|
|
||||||
// a hack to get hold of the dma devices
|
// a hack to get hold of the dma devices
|
||||||
upd765_family_device *m_fdc;
|
upd765_family_device *m_fdc;
|
||||||
|
|
||||||
uint8_t m_interrupt;
|
bool m_irq_active;
|
||||||
|
uint32_t m_irq_current;
|
||||||
|
|
||||||
uint16_t m_vectors[19];
|
uint16_t m_vectors[19];
|
||||||
uint8_t m_softint, m_nmictrl;
|
uint8_t m_softint;
|
||||||
|
uint8_t m_nmictrl;
|
||||||
|
|
||||||
uint32_t m_prescaler;
|
uint32_t m_prescaler;
|
||||||
uint32_t m_timer_reg[4];
|
uint32_t m_timer_reg[4];
|
||||||
|
Loading…
Reference in New Issue
Block a user