mirror of
https://github.com/holub/mame
synced 2025-07-04 09:28:51 +03:00
improved timer and interrupt handling
This commit is contained in:
parent
4ebd7f9bd8
commit
8f49f5c2ba
@ -14,13 +14,28 @@
|
|||||||
#define LOG_IOGA(...)
|
#define LOG_IOGA(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DEVICE_ADDRESS_MAP_START(map, 32, interpro_ioga_device)
|
||||||
|
AM_RANGE(0x30, 0x3f) AM_READWRITE(fdc_dma_r, fdc_dma_w)
|
||||||
|
|
||||||
|
AM_RANGE(0x5c, 0x7f) AM_READWRITE16(icr_r, icr_w, 0xffffffff)
|
||||||
|
AM_RANGE(0x80, 0x83) AM_READWRITE16(icr18_r, icr18_w, 0x0000ffff)
|
||||||
|
AM_RANGE(0x80, 0x83) AM_READWRITE8(softint_r, softint_w, 0x00ff0000)
|
||||||
|
AM_RANGE(0x80, 0x83) AM_READWRITE8(nmictrl_r, nmictrl_w, 0xff000000)
|
||||||
|
|
||||||
|
AM_RANGE(0x88, 0x8b) AM_READWRITE(timer_prescaler_r, timer_prescaler_w)
|
||||||
|
AM_RANGE(0x8c, 0x8f) AM_READWRITE(timer0_r, timer0_w)
|
||||||
|
AM_RANGE(0x90, 0x93) AM_READWRITE(timer1_r, timer1_w)
|
||||||
|
|
||||||
|
AM_RANGE(0xa8, 0xab) AM_READWRITE(timer3_r, timer3_w)
|
||||||
|
ADDRESS_MAP_END
|
||||||
|
|
||||||
// InterPro IOGA
|
// InterPro IOGA
|
||||||
const device_type INTERPRO_IOGA = &device_creator<interpro_ioga_device>;
|
const device_type INTERPRO_IOGA = &device_creator<interpro_ioga_device>;
|
||||||
|
|
||||||
interpro_ioga_device::interpro_ioga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
interpro_ioga_device::interpro_ioga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||||
: device_t(mconfig, INTERPRO_IOGA, "InterPro IOGA", tag, owner, clock, "ioga", __FILE__),
|
: device_t(mconfig, INTERPRO_IOGA, "InterPro IOGA", tag, owner, clock, "ioga", __FILE__),
|
||||||
m_out_int_func(*this),
|
m_out_nmi_func(*this),
|
||||||
m_irq_lines(0)
|
m_out_int_func(*this)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,6 +47,15 @@ void interpro_ioga_device::device_start()
|
|||||||
m_cpu = machine().device<cpu_device>("cpu");
|
m_cpu = machine().device<cpu_device>("cpu");
|
||||||
m_fdc = machine().device<upd765_family_device>("fdc");
|
m_fdc = machine().device<upd765_family_device>("fdc");
|
||||||
|
|
||||||
|
// allocate ioga timers
|
||||||
|
m_timer[0] = timer_alloc(IOGA_TIMER_0);
|
||||||
|
m_timer[1] = timer_alloc(IOGA_TIMER_1);
|
||||||
|
m_timer[2] = timer_alloc(IOGA_TIMER_2);
|
||||||
|
m_timer[3] = timer_alloc(IOGA_TIMER_3);
|
||||||
|
|
||||||
|
for (auto & elem : m_timer)
|
||||||
|
elem->enable(false);
|
||||||
|
|
||||||
// allocate timer for DMA controller
|
// allocate timer for DMA controller
|
||||||
m_dma_timer = timer_alloc(IOGA_TIMER_DMA);
|
m_dma_timer = timer_alloc(IOGA_TIMER_DMA);
|
||||||
m_dma_timer->adjust(attotime::never);
|
m_dma_timer->adjust(attotime::never);
|
||||||
@ -39,9 +63,12 @@ void interpro_ioga_device::device_start()
|
|||||||
|
|
||||||
void interpro_ioga_device::device_reset()
|
void interpro_ioga_device::device_reset()
|
||||||
{
|
{
|
||||||
m_irq_lines = 0;
|
|
||||||
m_interrupt = 0;
|
m_interrupt = 0;
|
||||||
m_state_drq = 0;
|
m_state_drq = 0;
|
||||||
|
|
||||||
|
// configure timer 0 at 60Hz
|
||||||
|
//m_timer_reg[0] = 0;
|
||||||
|
//m_timer[0]->adjust(attotime::from_hz(60), IOGA_TIMER_0, attotime::from_hz(60));
|
||||||
}
|
}
|
||||||
|
|
||||||
void interpro_ioga_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
void interpro_ioga_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||||
@ -51,16 +78,40 @@ void interpro_ioga_device::device_timer(emu_timer &timer, device_timer_id id, in
|
|||||||
switch (id)
|
switch (id)
|
||||||
{
|
{
|
||||||
case IOGA_TIMER_0:
|
case IOGA_TIMER_0:
|
||||||
m_timer[0] = 0x80000000;
|
m_timer_reg[0]++;
|
||||||
set_irq_line(14, 1);
|
set_irq_line(IOGA_TIMER0_IRQ, ASSERT_LINE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOGA_TIMER_1:
|
case IOGA_TIMER_1:
|
||||||
m_timer[1] = 0x80000000;
|
m_timer_reg[1]--;
|
||||||
set_irq_line(15, 1);
|
|
||||||
|
// check if timer has expired
|
||||||
|
if (m_timer_reg[1] == 0)
|
||||||
|
{
|
||||||
|
// disable timer
|
||||||
|
m_timer[3]->enable(false);
|
||||||
|
|
||||||
|
// set expired flag
|
||||||
|
m_timer_reg[1] |= IOGA_TIMER1_EXPIRED;
|
||||||
|
|
||||||
|
// throw an interrupt
|
||||||
|
set_irq_line(IOGA_TIMER1_IRQ, ASSERT_LINE);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOGA_TIMER_3:
|
case IOGA_TIMER_3:
|
||||||
m_timer[3] = 0x80000000;
|
m_timer_reg[3]--;
|
||||||
set_irq_line(1, 1);
|
if (m_timer_reg[3] == 0)
|
||||||
|
{
|
||||||
|
// disable timer
|
||||||
|
m_timer[3]->enable(false);
|
||||||
|
|
||||||
|
// set expired flag
|
||||||
|
m_timer_reg[3] |= IOGA_TIMER3_EXPIRED;
|
||||||
|
|
||||||
|
// throw an interrupt
|
||||||
|
set_irq_line(IOGA_TIMER3_IRQ, ASSERT_LINE);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOGA_TIMER_DMA:
|
case IOGA_TIMER_DMA:
|
||||||
@ -68,80 +119,72 @@ void interpro_ioga_device::device_timer(emu_timer &timer, device_timer_id id, in
|
|||||||
// TODO: vice-versa
|
// TODO: vice-versa
|
||||||
// TODO: get the dma transfer address and count
|
// TODO: get the dma transfer address and count
|
||||||
// TODO: implement multiple dma channels
|
// TODO: implement multiple dma channels
|
||||||
{
|
{
|
||||||
address_space &space = m_cpu->space(AS_PROGRAM);
|
address_space &space = m_cpu->space(AS_PROGRAM);
|
||||||
|
|
||||||
space.write_byte(m_fdc_dma[0]++, m_fdc->dma_r());
|
space.write_byte(m_fdc_dma[0]++, m_fdc->dma_r());
|
||||||
if (--m_fdc_dma[2])
|
if (--m_fdc_dma[2])
|
||||||
m_dma_timer->adjust(attotime::from_usec(10));
|
m_dma_timer->adjust(attotime::from_usec(10));
|
||||||
else
|
else
|
||||||
m_dma_timer->adjust(attotime::never);
|
m_dma_timer->adjust(attotime::never);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_ADDRESS_MAP_START(map, 32, interpro_ioga_device)
|
|
||||||
|
|
||||||
AM_RANGE(0x30, 0x3f) AM_READWRITE(fdc_dma_r, fdc_dma_w)
|
|
||||||
|
|
||||||
AM_RANGE(0x5C, 0x81) AM_READWRITE16(icr_r, icr_w, 0xffffffff)
|
|
||||||
|
|
||||||
AM_RANGE(0x8C, 0x8F) AM_READWRITE(timer0_r, timer0_w)
|
|
||||||
AM_RANGE(0x90, 0x93) AM_READWRITE(timer1_r, timer1_w)
|
|
||||||
|
|
||||||
AM_RANGE(0xA8, 0xAB) AM_READWRITE(timer3_r, timer3_w)
|
|
||||||
ADDRESS_MAP_END
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
IOGA
|
IOGA
|
||||||
00: ethernet remap 003e0480 // ET_82586_BASE_ADDR or IOGA_ETH_REMAP
|
00: ethernet remap 003e0480 // ET_82586_BASE_ADDR or IOGA_ETH_REMAP
|
||||||
04 : ethernet map page 00fff4b0 // ET_82586_CNTL_REG or IOGA_ETH_MAPPG
|
04 : ethernet map page 00fff4b0 // ET_82586_CNTL_REG or IOGA_ETH_MAPPG
|
||||||
08 : ethernet control 000004b2 // IOGA_ETH_CTL
|
08 : ethernet control 000004b2 // IOGA_ETH_CTL
|
||||||
0C : plotter real address 00000fff
|
0C : plotter real address 00000fff
|
||||||
|
|
||||||
10 : plotter virtual address fffffffc
|
10 : plotter virtual address fffffffc
|
||||||
14 : plotter transfer count 003fffff
|
14 : plotter transfer count 003fffff
|
||||||
18 : plotter control ec000001
|
18 : plotter control ec000001
|
||||||
1C : plotter end - of - scanline counter ffffffff
|
1C : plotter end - of - scanline counter ffffffff
|
||||||
|
|
||||||
20 : SCSI real address 00000000
|
20 : SCSI real address 00000000
|
||||||
24 : SCSI virtual address 007e96b8
|
24 : SCSI virtual address 007e96b8
|
||||||
28 : SCSI transfer count
|
28 : SCSI transfer count
|
||||||
2C : SCSI control
|
2C : SCSI control
|
||||||
|
|
||||||
30 : floppy real address
|
30 : floppy real address
|
||||||
34 : floppy virtual address
|
34 : floppy virtual address
|
||||||
38 : floppy transfer count
|
38 : floppy transfer count
|
||||||
3C : floppy control
|
3C : floppy control
|
||||||
|
|
||||||
40 : serial address 0 (003ba298)
|
40 : serial address 0 (003ba298)
|
||||||
44 : serial control 0 (01000000)
|
44 : serial control 0 (01000000)
|
||||||
48 : serial address 1 (ffffffff)
|
48 : serial address 1 (ffffffff)
|
||||||
4C : serial control 1 (01200000)
|
4C : serial control 1 (01200000)
|
||||||
|
|
||||||
50 : serial address 2 (ffffffff)
|
50 : serial address 2 (ffffffff)
|
||||||
54 : serial control 2 (01200000)
|
54 : serial control 2 (01200000)
|
||||||
|
|
||||||
-- 16 bit
|
-- 16 bit
|
||||||
5A : SIB control(00ff)
|
5A : SIB control(00ff)
|
||||||
5C : internal int 3 (timer 2) 00ff
|
5C : internal int 3 (timer 2) 00ff irq 0
|
||||||
5E : internal int 4 (timer 3) 00ff
|
5E : internal int 4 (timer 3) 00ff irq 1
|
||||||
|
|
||||||
60 : external int 0 (SCSI)0a20
|
60 : external int 0 (SCSI)0a20 irq 2
|
||||||
62 : external int 1 (floppy)0621
|
62 : external int 1 (floppy)0621 irq 3
|
||||||
64 : external int 2 (plotter)1622
|
64 : external int 2 (plotter)1622 irq 4
|
||||||
66 : external int 3 (SRX / CBUS 0) 0a02
|
66 : external int 3 (SRX / CBUS 0) 0a02 irq 5
|
||||||
68 : external int 4 (SRX / CBUS 1) 0e24
|
68 : external int 4 (SRX / CBUS 1) 0e24 irq 6
|
||||||
6A : external int 5 (SRX / CBUS 2) 0e25
|
6A : external int 5 (SRX / CBUS 2) 0e25 irq 7
|
||||||
6C : external int 6 (VB)0c26
|
6C : external int 6 (VB)0c26 irq 8
|
||||||
6E : external int 7 0cff
|
6E : external int 7 0cff irq 9
|
||||||
70 : external int 8 (CBUS 3) 0cff
|
70 : external int 8 (CBUS 3) 0cff irq 10
|
||||||
72 : external int 9 (clock / calendar) 0e29
|
72 : external int 9 (clock / calendar) 0e29 irq 11
|
||||||
74 : external int 10 (clock/SGA) 04fe
|
74 : external int 10 (clock/SGA) 04fe irq 12
|
||||||
|
|
||||||
76 : internal int 0 (mouse)0010
|
76 : internal int 0 (mouse)0010 irq 13
|
||||||
78 : internal int 1 (timer 0) 0011 - 60Hz
|
78 : internal int 1 (timer 0) 0011 - 60Hz irq 14
|
||||||
7A : internal int 2 (timer 1) 0212
|
7A : internal int 2 (timer 1) 0212 irq 15
|
||||||
7C : internal int 5 (serial DMA) 0e13
|
7C : internal int 5 (serial DMA) 0e13 irq 16
|
||||||
7E : external int 11 (serial) 0a01
|
7E : external int 11 (serial) 0a01 irq 17
|
||||||
80 : external int 12 (Ethernet)162c // IOGA_EXTINT12
|
80 : external int 12 (Ethernet)162c irq 18 // IOGA_EXTINT12
|
||||||
|
|
||||||
-- 8 bit
|
-- 8 bit
|
||||||
82 : soft int 00
|
82 : soft int 00
|
||||||
@ -204,36 +247,50 @@ C8 : ethernet address C 4039f088 // IOGA_ETHADDR_C
|
|||||||
|
|
||||||
void interpro_ioga_device::set_irq_line(int irq, int state)
|
void interpro_ioga_device::set_irq_line(int irq, int state)
|
||||||
{
|
{
|
||||||
uint32_t mask = (1 << irq);
|
LOG_INTERRUPT("set_irq_line(%d, %d)\n", irq, state);
|
||||||
#define E_INTRC_INTPEND 0x0100
|
switch (state)
|
||||||
#define E_INTRC_EXT_IE 0x0200
|
|
||||||
#define E_INTRC_EDGE 0x0400
|
|
||||||
#define E_INTRC_NEGPOL 0x0800
|
|
||||||
#define E_INTRC_INT_IE 0x1000
|
|
||||||
|
|
||||||
if (m_vectors[irq] & (E_INTRC_EXT_IE | E_INTRC_INT_IE))
|
|
||||||
{
|
{
|
||||||
if (state)
|
case ASSERT_LINE:
|
||||||
|
if (m_vectors[irq] & (IOGA_INTERRUPT_ENABLE_EXTERNAL | IOGA_INTERRUPT_ENABLE_INTERNAL))
|
||||||
{
|
{
|
||||||
LOG_INTERRUPT("interpro_ioga_device::set_irq_line(%d, %d)\n", irq, state);
|
// set interrupt pending bit
|
||||||
|
m_vectors[irq] |= IOGA_INTERRUPT_PENDING;
|
||||||
|
|
||||||
m_irq_lines |= mask;
|
|
||||||
m_interrupt = irq;
|
m_interrupt = irq;
|
||||||
m_out_int_func(1);
|
m_out_int_func(ASSERT_LINE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
LOG_INTERRUPT("received disabled interrupt irq %d vector 0x%04x\n", irq, m_vectors[irq]);
|
||||||
m_irq_lines &= ~mask;
|
break;
|
||||||
m_out_int_func(0);
|
|
||||||
}
|
case CLEAR_LINE:
|
||||||
|
// clear interrupt pending bit
|
||||||
|
m_vectors[irq] &= ~IOGA_INTERRUPT_PENDING;
|
||||||
|
|
||||||
|
m_out_int_func(CLEAR_LINE);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
LOG_INTERRUPT("ignoring irq %d vector 0x%04x\n", irq, m_vectors[irq]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IRQ_CALLBACK_MEMBER(interpro_ioga_device::inta_cb)
|
IRQ_CALLBACK_MEMBER(interpro_ioga_device::inta_cb)
|
||||||
{
|
{
|
||||||
return m_vectors[m_interrupt];
|
switch (irqline)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
// return vector for current interrupt without acknowledgement
|
||||||
|
return m_vectors[m_interrupt] & 0xff;
|
||||||
|
|
||||||
|
case INPUT_LINE_IRQ0:
|
||||||
|
// acknowledge interrupt
|
||||||
|
// FIXME: clear IRQ
|
||||||
|
return m_vectors[m_interrupt] & 0xff;
|
||||||
|
|
||||||
|
case INPUT_LINE_NMI:
|
||||||
|
//return m_nmictrl;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE_LINE_MEMBER(interpro_ioga_device::drq)
|
WRITE_LINE_MEMBER(interpro_ioga_device::drq)
|
||||||
@ -247,54 +304,61 @@ WRITE_LINE_MEMBER(interpro_ioga_device::drq)
|
|||||||
m_state_drq = state;
|
m_state_drq = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void interpro_ioga_device::write_timer(int timer, uint32_t value, device_timer_id id)
|
||||||
READ32_MEMBER(interpro_ioga_device::read)
|
|
||||||
{
|
{
|
||||||
switch (offset)
|
switch (id)
|
||||||
{
|
{
|
||||||
#if 0
|
case IOGA_TIMER_1:
|
||||||
case 0x3C:
|
// disable the timer
|
||||||
// 3C: floppy control
|
m_timer[timer]->enable(false);
|
||||||
|
|
||||||
|
// store the value
|
||||||
|
m_timer_reg[timer] = value & IOGA_TIMER1_VMASK;
|
||||||
|
|
||||||
|
// start the timer if necessary
|
||||||
|
if (value & IOGA_TIMER1_START)
|
||||||
|
m_timer[timer]->adjust(attotime::from_usec(m_prescaler), id, attotime::from_usec(m_prescaler));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x9C:
|
case IOGA_TIMER_3:
|
||||||
// 9C: arbiter control 000a
|
// write the value without the top two bits to the register
|
||||||
|
m_timer_reg[timer] = value & IOGA_TIMER3_VMASK;
|
||||||
|
|
||||||
|
// start the timer if necessary
|
||||||
|
if (value & IOGA_TIMER3_START)
|
||||||
|
m_timer[timer]->adjust(attotime::from_hz(IOGA_TIMER3_CLOCK), id, attotime::from_hz(IOGA_TIMER3_CLOCK));
|
||||||
|
else
|
||||||
|
m_timer[timer]->enable(false);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_IOGA("ioga read from offset = %08x, mask = %08x, pc = %08x\n", offset, mem_mask, space.device().safe_pc());
|
// save the value
|
||||||
return 0xffffffff;
|
m_timer_reg[timer] = value;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void interpro_ioga_device::set_timer(int timer, uint32_t value, device_timer_id id)
|
// timer_set(attotime::from_usec(500), id);
|
||||||
{
|
|
||||||
m_timer[timer] = value;
|
|
||||||
if (value & 0x40000000)
|
|
||||||
//timer_set(attotime::from_usec(value & 0x3fffff), id);
|
|
||||||
timer_set(attotime::from_usec(500), id);
|
|
||||||
|
|
||||||
}
|
logerror("timer %d set to 0x%x (%d)\n", timer, m_timer_reg[timer], m_timer_reg[timer]);
|
||||||
|
|
||||||
WRITE32_MEMBER(interpro_ioga_device::write)
|
|
||||||
{
|
|
||||||
switch (offset)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
LOG_IOGA("ioga write to offset = 0x%08x, mask = 0x%08x) = 0x%08x, pc = %08x\n", offset, mem_mask, data, space.device().safe_pc());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
READ16_MEMBER(interpro_ioga_device::icr_r)
|
READ16_MEMBER(interpro_ioga_device::icr_r)
|
||||||
{
|
{
|
||||||
return m_vectors[offset];
|
return m_vectors[offset] & ~IOGA_INTERRUPT_FORCED;
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE16_MEMBER(interpro_ioga_device::icr_w)
|
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());
|
||||||
|
|
||||||
m_vectors[offset] = data;
|
if (data & IOGA_INTERRUPT_PENDING)
|
||||||
}
|
m_vectors[offset] = (data | IOGA_INTERRUPT_FORCED) & ~IOGA_INTERRUPT_PENDING;
|
||||||
|
else if (m_vectors[offset] & IOGA_INTERRUPT_FORCED)
|
||||||
|
{
|
||||||
|
m_vectors[offset] = data;
|
||||||
|
|
||||||
|
set_irq_line(offset, ASSERT_LINE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_vectors[offset] = data;
|
||||||
|
}
|
||||||
|
@ -9,9 +9,38 @@
|
|||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "machine/upd765.h"
|
#include "machine/upd765.h"
|
||||||
|
|
||||||
#define MCFG_INTERPRO_IOGA_ADD(_tag, _out_int) \
|
#define MCFG_INTERPRO_IOGA_ADD(_tag) \
|
||||||
MCFG_DEVICE_ADD(_tag, INTERPRO_IOGA, 0) \
|
MCFG_DEVICE_ADD(_tag, INTERPRO_IOGA, 0)
|
||||||
devcb = &interpro_ioga_device::static_set_out_int_callback( *device, DEVCB_##_out_int );
|
|
||||||
|
#define MCFG_INTERPRO_IOGA_NMI_CB(_out_nmi) \
|
||||||
|
devcb = &interpro_ioga_device::static_set_out_int_callback(*device, DEVCB_##_out_nmi);
|
||||||
|
|
||||||
|
#define MCFG_INTERPRO_IOGA_IRQ_CB(_out_int) \
|
||||||
|
devcb = &interpro_ioga_device::static_set_out_int_callback(*device, DEVCB_##_out_int);
|
||||||
|
|
||||||
|
// timer 0 seem to be a 60Hz cycle
|
||||||
|
#define IOGA_TIMER0_IRQ 14
|
||||||
|
|
||||||
|
// best guess for timer 1 is 10MHz based on typical prescaler value of 1000 and timer value of 100 for a delay of 100ms
|
||||||
|
#define IOGA_TIMER1_IRQ 15
|
||||||
|
#define IOGA_TIMER1_VMASK 0xffff
|
||||||
|
#define IOGA_TIMER1_START 0x10000
|
||||||
|
#define IOGA_TIMER1_EXPIRED 0x20000
|
||||||
|
|
||||||
|
// best guess for timer 3 is 12.5MHz based on typical value of 12500 for a delay of 1ms
|
||||||
|
#define IOGA_TIMER3_CLOCK XTAL_12_5MHz
|
||||||
|
#define IOGA_TIMER3_IRQ 1
|
||||||
|
#define IOGA_TIMER3_VMASK 0x3fffffff
|
||||||
|
#define IOGA_TIMER3_START 0x40000000
|
||||||
|
#define IOGA_TIMER3_EXPIRED 0x80000000
|
||||||
|
|
||||||
|
#define IOGA_INTERRUPT_PENDING 0x0100
|
||||||
|
#define IOGA_INTERRUPT_ENABLE_EXTERNAL 0x0200
|
||||||
|
#define IOGA_INTERRUPT_EDGE 0x0400
|
||||||
|
#define IOGA_INTERRUPT_NEGPOL 0x0800
|
||||||
|
#define IOGA_INTERRUPT_ENABLE_INTERNAL 0x1000
|
||||||
|
// FIXME: hack for forced interrupts
|
||||||
|
#define IOGA_INTERRUPT_FORCED 0x8000
|
||||||
|
|
||||||
class interpro_ioga_device : public device_t
|
class interpro_ioga_device : public device_t
|
||||||
{
|
{
|
||||||
@ -19,6 +48,7 @@ public:
|
|||||||
// construction/destruction
|
// construction/destruction
|
||||||
interpro_ioga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
interpro_ioga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||||
|
|
||||||
|
template<class _Object> static devcb_base &static_set_out_nmi_callback(device_t &device, _Object object) { return downcast<interpro_ioga_device &>(device).m_out_nmi_func.set_callback(object); }
|
||||||
template<class _Object> static devcb_base &static_set_out_int_callback(device_t &device, _Object object) { return downcast<interpro_ioga_device &>(device).m_out_int_func.set_callback(object); }
|
template<class _Object> static devcb_base &static_set_out_int_callback(device_t &device, _Object object) { return downcast<interpro_ioga_device &>(device).m_out_int_func.set_callback(object); }
|
||||||
|
|
||||||
virtual DECLARE_ADDRESS_MAP(map, 8);
|
virtual DECLARE_ADDRESS_MAP(map, 8);
|
||||||
@ -43,19 +73,27 @@ public:
|
|||||||
|
|
||||||
DECLARE_WRITE_LINE_MEMBER(drq);
|
DECLARE_WRITE_LINE_MEMBER(drq);
|
||||||
|
|
||||||
DECLARE_READ32_MEMBER(read);
|
DECLARE_READ32_MEMBER(timer_prescaler_r) { return m_prescaler; };
|
||||||
DECLARE_WRITE32_MEMBER(write);
|
DECLARE_READ32_MEMBER(timer0_r) { return m_timer_reg[0]; };
|
||||||
|
DECLARE_READ32_MEMBER(timer1_r) { return m_timer_reg[1]; };
|
||||||
|
DECLARE_READ32_MEMBER(timer2_r) { return m_timer_reg[2]; };
|
||||||
|
DECLARE_READ32_MEMBER(timer3_r) { return m_timer_reg[3]; };
|
||||||
|
|
||||||
DECLARE_READ32_MEMBER(timer0_r) { return m_timer[0]; };
|
DECLARE_WRITE32_MEMBER(timer_prescaler_w) { m_prescaler = data; }
|
||||||
DECLARE_READ32_MEMBER(timer1_r) { return m_timer[1]; };
|
DECLARE_WRITE32_MEMBER(timer0_w) { write_timer(0, data, IOGA_TIMER_0); }
|
||||||
DECLARE_READ32_MEMBER(timer3_r) { return m_timer[3]; };
|
DECLARE_WRITE32_MEMBER(timer1_w) { write_timer(1, data, IOGA_TIMER_1); }
|
||||||
|
DECLARE_WRITE32_MEMBER(timer2_w) { write_timer(2, data, IOGA_TIMER_2); }
|
||||||
DECLARE_WRITE32_MEMBER(timer0_w) { set_timer(0, data, IOGA_TIMER_0); }
|
DECLARE_WRITE32_MEMBER(timer3_w) { write_timer(3, data, IOGA_TIMER_3); }
|
||||||
DECLARE_WRITE32_MEMBER(timer1_w) { set_timer(1, data, IOGA_TIMER_1); }
|
|
||||||
DECLARE_WRITE32_MEMBER(timer3_w) { set_timer(3, data, IOGA_TIMER_3); }
|
|
||||||
|
|
||||||
DECLARE_READ16_MEMBER(icr_r);
|
DECLARE_READ16_MEMBER(icr_r);
|
||||||
DECLARE_WRITE16_MEMBER(icr_w);
|
DECLARE_WRITE16_MEMBER(icr_w);
|
||||||
|
DECLARE_READ16_MEMBER(icr18_r) { return icr_r(space, 18, mem_mask); };
|
||||||
|
DECLARE_WRITE16_MEMBER(icr18_w) { icr_w(space, 18, data, mem_mask); };
|
||||||
|
|
||||||
|
DECLARE_READ8_MEMBER(softint_r) { return m_softint; }
|
||||||
|
DECLARE_WRITE8_MEMBER(softint_w) { m_softint = data; }
|
||||||
|
DECLARE_READ8_MEMBER(nmictrl_r) { return m_nmictrl; }
|
||||||
|
DECLARE_WRITE8_MEMBER(nmictrl_w) { m_nmictrl = data; }
|
||||||
|
|
||||||
DECLARE_READ32_MEMBER(fdc_dma_r) { return m_fdc_dma[offset]; };
|
DECLARE_READ32_MEMBER(fdc_dma_r) { return m_fdc_dma[offset]; };
|
||||||
DECLARE_WRITE32_MEMBER(fdc_dma_w) { m_fdc_dma[offset] = data; };
|
DECLARE_WRITE32_MEMBER(fdc_dma_w) { m_fdc_dma[offset] = data; };
|
||||||
@ -77,18 +115,21 @@ private:
|
|||||||
static const device_timer_id IOGA_TIMER_DMA = 4;
|
static const device_timer_id IOGA_TIMER_DMA = 4;
|
||||||
|
|
||||||
void set_irq_line(int irq, int state);
|
void set_irq_line(int irq, int state);
|
||||||
void set_timer(int timer, uint32_t value, device_timer_id id);
|
void write_timer(int timer, uint32_t value, device_timer_id id);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
uint32_t m_irq_lines;
|
|
||||||
uint8_t m_interrupt;
|
uint8_t m_interrupt;
|
||||||
uint16_t m_vectors[19];
|
uint16_t m_vectors[19];
|
||||||
|
uint8_t m_softint, m_nmictrl;
|
||||||
|
|
||||||
uint32_t m_timer[4];
|
uint32_t m_prescaler;
|
||||||
|
uint32_t m_timer_reg[4];
|
||||||
|
emu_timer *m_timer[4];
|
||||||
|
|
||||||
emu_timer *m_dma_timer;
|
emu_timer *m_dma_timer;
|
||||||
uint32_t m_state_drq;
|
uint32_t m_state_drq;
|
||||||
|
Loading…
Reference in New Issue
Block a user