diff options
-rw-r--r-- | scripts/src/machine.lua | 12 | ||||
-rw-r--r-- | scripts/target/mame/mess.lua | 1 | ||||
-rw-r--r-- | src/devices/machine/am9519.cpp | 305 | ||||
-rw-r--r-- | src/devices/machine/am9519.h | 93 | ||||
-rw-r--r-- | src/mame/drivers/olyboss.cpp | 10 |
5 files changed, 420 insertions, 1 deletions
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index c59f39b69a6..7e55d344f92 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -625,6 +625,18 @@ end --------------------------------------------------- -- +--@src/devices/machine/am9519.h,MACHINES["AM9519"] = true +--------------------------------------------------- + +if (MACHINES["AM9519"]~=null) then + files { + MAME_DIR .. "src/devices/machine/am9519.cpp", + MAME_DIR .. "src/devices/machine/am9519.h", + } +end + +--------------------------------------------------- +-- --@src/devices/machine/amigafdc.h,MACHINES["AMIGAFDC"] = true --------------------------------------------------- diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index bf08e0d8f44..c38eb46c82b 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -382,6 +382,7 @@ MACHINES["AM2847"] = true MACHINES["AM53CF96"] = true MACHINES["AM9513"] = true MACHINES["AM9517A"] = true +MACHINES["AM9519"] = true MACHINES["AMIGAFDC"] = true MACHINES["AT_KEYBC"] = true MACHINES["AT28C16"] = true diff --git a/src/devices/machine/am9519.cpp b/src/devices/machine/am9519.cpp new file mode 100644 index 00000000000..99fde6fc1c1 --- /dev/null +++ b/src/devices/machine/am9519.cpp @@ -0,0 +1,305 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol,Carl + +#include "emu.h" +#include "machine/am9519.h" + +#define LOG_GENERAL (1U << 0) + +//#define VERBOSE (LOG_GENERAL) +#include "logmacro.h" + +void am9519_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if(!BIT(m_mode, 7)) // chip disabled + return; + + /* check the various IRQs */ + for(int n = 0, irq = m_prio; n < 8; n++, irq = (irq + 1) & 7) + { + u8 mask = 1 << irq; + + /* is this IRQ in service and not cascading and sfnm? */ + if(m_isr & mask) + { + LOG("am9519_timerproc(): PIC IRQ #%d still in service\n", irq); + break; + } + + bool active = !(BIT(m_mode, 4) ^ BIT(m_irr, irq)); + + /* is this IRQ pending and enabled? */ + if(active && !(m_imr & mask)) + { + LOG("am9519_timerproc(): PIC triggering IRQ #%d\n", irq); + if(BIT(m_mode, 4)) + m_out_int_func(1); + return; + } + } + m_out_int_func(0); +} + + +void am9519_device::set_irq_line(int irq, int state) +{ + u8 mask = (1 << irq); + + if(state) + { + /* setting IRQ line */ + LOG("am9519_set_irq_line(): PIC set IRQ line #%d\n", irq); + + if(!(m_irq_lines & mask)) // edge trig only + m_irr |= mask; + m_irq_lines |= mask; + } + else + { + /* clearing IRQ line */ + LOG("am9519_device::set_irq_line(): PIC cleared IRQ line #%d\n", irq); + + m_irq_lines &= ~mask; + m_irr &= ~mask; + } + set_timer(); +} + + +u32 am9519_device::acknowledge() +{ + for(int n = 0, irq = m_prio; n < 8; n++, irq = (irq + 1) & 7) + { + u8 mask = 1 << irq; + + /* is this IRQ pending and enabled? */ + if((m_irr & mask) && !(m_imr & mask)) + { + LOG("am9519_acknowledge(): PIC acknowledge IRQ #%d\n", irq); + + if(!(mask & m_aclear)) + m_isr |= mask; + + set_timer(); + + u32 ret = 0; + int irqr = BIT(m_mode, 1) ? 0 : irq; + for(int i = 0; i < m_count[irqr]; i++) + ret = (ret << 8) | m_resp[irqr][i]; + + return ret; + } + } + logerror("Spurious IRQ\n"); + return 0; +} + + +IRQ_CALLBACK_MEMBER(am9519_device::iack_cb) +{ + return acknowledge(); +} + + +READ8_MEMBER( am9519_device::stat_r ) +{ + u8 stat = 0; + for(int n = 0, irq = m_prio; n < 8; n++, irq = (irq + 1) & 7) + { + u8 mask = 1 << irq; + if((m_irr & mask) && !(m_imr & mask)) + { + stat = 0x80 | irq; + break; + } + } + stat |= BIT(m_mode, 7) << 3; + stat |= BIT(m_mode, 2) << 4; + stat |= BIT(m_mode, 0) << 5; + return stat; +} + +READ8_MEMBER( am9519_device::data_r ) +{ + switch((m_mode & 0x60) >> 5) + { + case 0: + return m_isr; + case 1: + return m_imr; + case 2: + return m_irr; + case 3: + return m_aclear; + } + return 0; +} + +WRITE8_MEMBER( am9519_device::cmd_w ) +{ + m_cmd = data; + switch(data >> 3) + { + case 0: + reset(); + break; + case 2: + m_irr = m_imr = 0; + break; + case 3: + m_irr &= ~(1 << (data & 7)); + m_imr &= ~(1 << (data & 7)); + break; + case 4: + m_imr = 0; + break; + case 5: + m_imr &= ~(1 << (data & 7)); + break; + case 6: + m_imr = 0xff; + break; + case 7: + m_imr |= 1 << (data & 7); + break; + case 8: + m_irr = 0; + break; + case 9: + m_irr &= ~(1 << (data & 7)); + break; + case 10: + m_irr = 0xff; + break; + case 11: + m_irr |= 1 << (data & 7); + break; + case 12: + case 13: + { + for(int n = 0, irq = m_prio; n < 8; n++, irq = (irq + 1) & 7) + { + if(m_isr & (1 << irq)) + m_isr &= ~(1 << irq); + } + break; + } + case 14: + m_isr = 0; + break; + case 15: + m_isr &= ~(1 << (data & 7)); + break; + case 16: + case 17: + case 18: + case 19: + m_mode = (m_mode & 0xe0) | (data & 0x1f); + break; + case 20: + case 21: + m_mode = (m_mode & 0x9f) | (data & 0x60); + switch(data & 3) + { + case 1: + m_mode |= 0x80; + break; + case 2: + m_mode &= 0x7f; + break; + } + break; + case 28: + case 29: + case 30: + case 31: + m_count[m_cmd & 7] = ((data >> 3) & 3) + 1; + m_curcnt = 0; + break; + } + set_timer(); +} + +WRITE8_MEMBER( am9519_device::data_w ) +{ + if((m_cmd & 0xf0) > 0xb0) + { + switch(m_cmd >> 4) + { + case 11: + m_imr = data; + break; + case 12: + m_aclear = data; + break; + case 14: + case 15: + if(m_curcnt < m_count[m_cmd & 7]) + { + m_resp[m_cmd & 7][m_curcnt] = data; + m_curcnt++; + return; + } + break; + } + m_cmd = 0; + } +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void am9519_device::device_start() +{ + // resolve callbacks + m_out_int_func.resolve_safe(); + + // Register save state items + save_item(NAME(m_isr)); + save_item(NAME(m_irr)); + save_item(NAME(m_prio)); + save_item(NAME(m_imr)); + save_item(NAME(m_irq_lines)); + save_item(NAME(m_mode)); + save_item(NAME(m_count)); + save_item(NAME(m_resp)); + save_item(NAME(m_aclear)); + save_item(NAME(m_cmd)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void am9519_device::device_reset() +{ + m_isr = 0; + m_irr = 0; + m_irq_lines = 0; + m_prio = 0; + m_imr = 0xff; + m_mode = 0; + m_aclear = 0; + m_cmd = 0; + m_curcnt = 0; + for(int i = 0; i < 8; i++) + { + m_count[i] = 0; + m_resp[i][0] = 0; + m_resp[i][1] = 0; + m_resp[i][2] = 0; + m_resp[i][3] = 0; + } +} + +DEFINE_DEVICE_TYPE(AM9519, am9519_device, "am9519", "AMD AM9519 Universal Interrupt Controller") + +am9519_device::am9519_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, AM9519, tag, owner, clock) + , m_out_int_func(*this) + , m_irr(0) + , m_irq_lines(0) +{ +} diff --git a/src/devices/machine/am9519.h b/src/devices/machine/am9519.h new file mode 100644 index 00000000000..2bfa9e89fe8 --- /dev/null +++ b/src/devices/machine/am9519.h @@ -0,0 +1,93 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol,Carl +/*************************************************************************** + + AMD AM9519 + + Universal Interrupt Controller + + _____ _____ + _CS 1 |* \_/ | 28 VCC + _WR 2 | | 27 C/_D + _RD 3 | | 26 _IACK + DB7 4 | | 25 IREQ7 + DB6 5 | | 24 IREQ6 + DB5 6 | | 23 IREQ5 + DB4 7 | AM9519 | 22 IREQ4 + DB3 8 | | 21 IREQ3 + DB2 9 | | 20 IREQ2 + DB1 10 | | 19 IREQ1 + DB0 11 | | 18 IREQ0 + _RIP 12 | | 17 GINT + EI 13 | | 16 _EO + GND 14 |_____________| 15 _PAUSE + +***************************************************************************/ + +#ifndef MAME_MACHINE_AM9519_H +#define MAME_MACHINE_AM9519_H + + +/*************************************************************************** + DEVICE CONFIGURATION MACROS +***************************************************************************/ + +#define MCFG_AM9519_OUT_INT_CB(_devcb) \ + devcb = &am9519_device::static_set_out_int_callback(*device, DEVCB_##_devcb); + + +class am9519_device : public device_t +{ +public: + am9519_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + template <class Object> static devcb_base &static_set_out_int_callback(device_t &device, Object &&cb) { return downcast<am9519_device &>(device).m_out_int_func.set_callback(std::forward<Object>(cb)); } + + DECLARE_READ8_MEMBER( stat_r ); + DECLARE_READ8_MEMBER( data_r ); + DECLARE_WRITE8_MEMBER( cmd_w ); + DECLARE_WRITE8_MEMBER( data_w ); + u32 acknowledge(); + + DECLARE_WRITE_LINE_MEMBER( ireq0_w ) { set_irq_line(0, state); } + DECLARE_WRITE_LINE_MEMBER( ireq1_w ) { set_irq_line(1, state); } + DECLARE_WRITE_LINE_MEMBER( ireq2_w ) { set_irq_line(2, state); } + DECLARE_WRITE_LINE_MEMBER( ireq3_w ) { set_irq_line(3, state); } + DECLARE_WRITE_LINE_MEMBER( ireq4_w ) { set_irq_line(4, state); } + DECLARE_WRITE_LINE_MEMBER( ireq5_w ) { set_irq_line(5, state); } + DECLARE_WRITE_LINE_MEMBER( ireq6_w ) { set_irq_line(6, state); } + DECLARE_WRITE_LINE_MEMBER( ireq7_w ) { set_irq_line(7, state); } + + IRQ_CALLBACK_MEMBER(iack_cb); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + +private: + static constexpr device_timer_id TIMER_CHECK_IRQ = 0; + + inline void set_timer() { timer_set(attotime::zero, TIMER_CHECK_IRQ); } + void set_irq_line(int irq, int state); + + devcb_write_line m_out_int_func; + + u8 m_isr; + u8 m_irr; + u8 m_prio; + u8 m_imr; + u8 m_irq_lines; + + u8 m_curcnt; + u8 m_mode; + u8 m_cmd; + u8 m_aclear; + u8 m_count[8]; + u8 m_resp[8][4]; +}; + +DECLARE_DEVICE_TYPE(AM9519, am9519_device) + +#endif // MAME_MACHINE_AM9519_H diff --git a/src/mame/drivers/olyboss.cpp b/src/mame/drivers/olyboss.cpp index f40b517d4f9..843bb2d08cc 100644 --- a/src/mame/drivers/olyboss.cpp +++ b/src/mame/drivers/olyboss.cpp @@ -38,6 +38,7 @@ #include "machine/keyboard.h" #include "video/upd3301.h" #include "machine/i8257.h" +#include "machine/am9519.h" #include "screen.h" #define Z80_TAG "z80" @@ -108,7 +109,10 @@ static ADDRESS_MAP_START(olyboss_io, AS_IO, 8, olyboss_state) ADDRESS_MAP_GLOBAL_MASK(0xff) ADDRESS_MAP_UNMAP_HIGH AM_RANGE(0x0, 0x8) AM_DEVREADWRITE(I8257_TAG, i8257_device, read, write) - AM_RANGE(0x9, 0x7f) AM_READWRITE(port_read,port_write) + AM_RANGE(0x9, 0x2f) AM_READWRITE(port_read,port_write) + AM_RANGE(0x30, 0x30) AM_DEVREADWRITE("uic", am9519_device, data_r, data_w) + AM_RANGE(0x31, 0x31) AM_DEVREADWRITE("uic", am9519_device, stat_r, cmd_w) + AM_RANGE(0x32, 0x7f) AM_READWRITE(port_read,port_write) AM_RANGE(0x80, 0x81) AM_DEVREADWRITE(UPD3301_TAG, upd3301_device, read, write) AM_RANGE(0x82, 0xff) AM_READWRITE(port_read,port_write) ADDRESS_MAP_END @@ -285,6 +289,7 @@ MACHINE_CONFIG_START( olyboss_state::olybossd ) MCFG_CPU_ADD(Z80_TAG, Z80, 4_MHz_XTAL) MCFG_CPU_PROGRAM_MAP(olyboss_mem) MCFG_CPU_IO_MAP(olyboss_io) + MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE("uic", am9519_device, iack_cb) /* video hardware */ @@ -296,6 +301,9 @@ MACHINE_CONFIG_START( olyboss_state::olybossd ) /* devices */ + MCFG_DEVICE_ADD("uic", AM9519, 0) + MCFG_AM9519_OUT_INT_CB(INPUTLINE(Z80_TAG, 0)) + MCFG_DEVICE_ADD(I8257_TAG, I8257, XTAL(4'000'000)) MCFG_I8257_OUT_HRQ_CB(WRITELINE(olyboss_state, hrq_w)) MCFG_I8257_IN_MEMR_CB(READ8(olyboss_state, dma_mem_r)) |