// license:BSD-3-Clause
// copyright-holders:Joakim Larsson Edstrom
#ifndef MAME_MACHINE_FGA002_H
#define MAME_MACHINE_FGA002_H
#include "cpu/m68000/m68000.h" // The FGA002 is designed for the 68K interrupt PL0-PL2 signalling, however used on SPARC and x86 boards too
#define MCFG_FGA002_ADD(_tag, _clock) MCFG_DEVICE_ADD(_tag, FGA002, _clock)
// LOCAL IRQ callbacks
#define MCFG_FGA002_OUT_INT_CB(_devcb) \
devcb = &downcast<fga002_device &>(*device).set_out_int_callback(DEVCB_##_devcb);
#define MCFG_FGA002_OUT_LIACK4_CB(_devcb) \
devcb = &downcast<fga002_device &>(*device).set_liack4_callback(DEVCB_##_devcb);
#define MCFG_FGA002_OUT_LIACK5_CB(_devcb) \
devcb = &downcast<fga002_device &>(*device).set_liack5_callback(DEVCB_##_devcb);
#define MCFG_FGA002_OUT_LIACK6_CB(_devcb) \
devcb = &downcast<fga002_device &>(*device).set_liack6_callback(DEVCB_##_devcb);
#define MCFG_FGA002_OUT_LIACK7_CB(_devcb) \
devcb = &downcast<fga002_device &>(*device).set_liack7_callback(DEVCB_##_devcb);
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> fga002_device
class fga002_device : public device_t
// ,public device_z80daisy_interface
{
public:
// construction/destruction
fga002_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_WRITE8_MEMBER (write);
DECLARE_READ8_MEMBER (read);
void lirq_w(int status, int vector, int control, int state);
DECLARE_WRITE_LINE_MEMBER( lirq0_w );
DECLARE_WRITE_LINE_MEMBER( lirq1_w );
DECLARE_WRITE_LINE_MEMBER( lirq2_w );
DECLARE_WRITE_LINE_MEMBER( lirq3_w );
DECLARE_WRITE_LINE_MEMBER( lirq4_w );
DECLARE_WRITE_LINE_MEMBER( lirq5_w );
DECLARE_WRITE_LINE_MEMBER( lirq6_w );
DECLARE_WRITE_LINE_MEMBER( lirq7_w );
IRQ_CALLBACK_MEMBER(iack);
int acknowledge();
int get_irq_level();
template <class Object> devcb_base &set_out_int_callback(Object &&cb) { return m_out_int_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_liack4_callback(Object &&cb) { return m_liack4_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_liack5_callback(Object &&cb) { return m_liack5_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_liack6_callback(Object &&cb) { return m_liack6_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_liack7_callback(Object &&cb) { return m_liack7_cb.set_callback(std::forward<Object>(cb)); }
protected:
// type for array of mapping of FGA registers that assembles an IRQ source
typedef struct {
int vector;
int status;
int control;
} fga_irq_t;
// interrupt sources in prio order if on same interrupt level. TODO: Add all sources
const static fga_irq_t s_irq_sources[];
fga002_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
#if 0
// device_z80daisy_interface overrides
virtual int z80daisy_irq_state() override;
virtual int z80daisy_irq_ack() override;
virtual void z80daisy_irq_reti() override;
#endif
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
devcb_write_line m_out_int_cb;
devcb_read8 m_liack4_cb;
devcb_read8 m_liack5_cb;
devcb_read8 m_liack6_cb;
devcb_read8 m_liack7_cb;
int m_int_state[0x08]; // interrupt state
private:
uint8_t m_tim0count;
uint8_t m_fga002[0x500];
uint8_t do_fga002reg_ctl3_r();
void do_fga002reg_ctl3_w(uint8_t data);
/* Timer functions */
uint8_t do_fga002reg_tim0preload_r();
void do_fga002reg_tim0preload_w(uint8_t data);
uint8_t do_fga002reg_tim0ctl_r();
void do_fga002reg_tim0ctl_w(uint8_t data);
uint8_t do_fga002reg_tim0count_r();
void do_fga002reg_tim0count_w(uint8_t data);
uint8_t do_fga002reg_icrtim0_r();
void do_fga002reg_icrtim0_w(uint8_t data);
uint8_t do_fga002reg_istim0_r();
void do_fga002reg_istim0_w(uint8_t data);
emu_timer *fga_timer;
enum
{
TIMER_ID_FGA
};
enum {
REG_TIM0CTL_ZERO_STOP = 0x80,
REG_TIM0CTL_AUTOPRELOAD = 0x40,
REG_TIM0CTL_SYSFAIL = 0x20,
REG_TIM0CTL_START_STOP = 0x10,
REG_TIM0CTL_CLK_MSK = 0x0f,
REG_TIM0CTL_CLK_1_MIC = 0x00,
REG_TIM0CTL_CLK_2_MIC = 0x01,
REG_TIM0CTL_CLK_4_MIC = 0x02,
REG_TIM0CTL_CLK_8_MIC = 0x03,
REG_TIM0CTL_CLK_16_MIC = 0x04,
REG_TIM0CTL_CLK_32_MIC = 0x05,
REG_TIM0CTL_CLK_64_MIC = 0x06,
REG_TIM0CTL_CLK_128_MIC = 0x07,
REG_TIM0CTL_CLK_256_MIC = 0x08,
REG_TIM0CTL_CLK_512_MIC = 0x09,
REG_TIM0CTL_CLK_2_MIL = 0x0a,
REG_TIM0CTL_CLK_8_MIL = 0x0b,
REG_TIM0CTL_CLK_32_MIL = 0x0c,
REG_TIM0CTL_CLK_125_MIL = 0x0d,
REG_TIM0CTL_CLK_500_MIL = 0x0e,
REG_TIM0CTL_CLK_2_SEC = 0x0f,
};
enum {
REG_ISTIM0_TIM_INT = 0x80,
};
/* Interrupt support */
uint8_t m_irq_level;
uint8_t do_fga002reg_localiack_r();
void do_fga002reg_localiack_w(uint8_t data);
uint8_t do_fga002reg_islocal0_r();
uint8_t do_fga002reg_islocal1_r();
uint8_t do_fga002reg_islocal2_r();
uint8_t do_fga002reg_islocal3_r();
uint8_t do_fga002reg_islocal4_r();
uint8_t do_fga002reg_islocal5_r();
uint8_t do_fga002reg_islocal6_r();
uint8_t do_fga002reg_islocal7_r();
void islocal_w(int status, int vector, int control, int data);
void do_fga002reg_islocal0_w(uint8_t data);
void do_fga002reg_islocal1_w(uint8_t data);
void do_fga002reg_islocal2_w(uint8_t data);
void do_fga002reg_islocal3_w(uint8_t data);
void do_fga002reg_islocal4_w(uint8_t data);
void do_fga002reg_islocal5_w(uint8_t data);
void do_fga002reg_islocal6_w(uint8_t data);
void do_fga002reg_islocal7_w(uint8_t data);
uint8_t do_fga002reg_icrlocal0_r();
uint8_t do_fga002reg_icrlocal1_r();
uint8_t do_fga002reg_icrlocal2_r();
uint8_t do_fga002reg_icrlocal3_r();
uint8_t do_fga002reg_icrlocal4_r();
uint8_t do_fga002reg_icrlocal5_r();
uint8_t do_fga002reg_icrlocal6_r();
uint8_t do_fga002reg_icrlocal7_r();
void do_fga002reg_icrlocal0_w(uint8_t data);
void do_fga002reg_icrlocal1_w(uint8_t data);
void do_fga002reg_icrlocal2_w(uint8_t data);
void do_fga002reg_icrlocal3_w(uint8_t data);
void do_fga002reg_icrlocal4_w(uint8_t data);
void do_fga002reg_icrlocal5_w(uint8_t data);
void do_fga002reg_icrlocal6_w(uint8_t data);
void do_fga002reg_icrlocal7_w(uint8_t data);
void trigger_interrupt(uint8_t data);
void check_interrupts();
enum {
REG_ISLOCAL_IRQ = 0x80
};
enum {
REG_CTL3_VECTORBITS7_6 = 0x0c
};
enum{
REG_LIACK_LOCAL4_MSK = 0x03,
REG_LIACK_LOCAL5_MSK = 0x0c, // >> 2 to use patterns below
REG_LIACK_LOCAL6_MSK = 0x30, // >> 4 to use patterns below
REG_LIACK_LOCAL7_MSK = 0xc0, // >> 6 to use patterns below
REG_LIACK_INT_IACK = 0x00, // Assumes bits to be right adjusted
REG_LIACK_EXT_IACK1 = 0x01,
REG_LIACK_EXT_IACK2 = 0x02,
REG_LIACK_EXT_IACK3 = 0x03,
};
enum{
INT_LOCAL0 = 0x30,
INT_LOCAL1 = 0x31,
INT_LOCAL2 = 0x32,
INT_LOCAL3 = 0x33,
INT_LOCAL4 = 0x34,
INT_LOCAL5 = 0x35,
INT_LOCAL6 = 0x36,
INT_LOCAL7 = 0x37,
INT_EMPTY = 0x3F,
INT_ACK_AUTOVECTOR = -1,
};
enum{
REG_ICR_LVL_MSK = 0x07,
REG_ICR_ENABLE = 0x08,
REG_ICR_AUTOCLR = 0x10,
REG_ICR_ACTIVITY = 0x20,
REG_ICR_EDGE = 0x40,
};
/* Register offsets */
enum {
FGA_ICRMBOX0 = 0x0000,
FGA_ICRMBOX1 = 0x0004,
FGA_ICRMBOX2 = 0x0008,
FGA_ICRMBOX3 = 0x000c,
FGA_ICRMBOX4 = 0x0010,
FGA_ICRMBOX5 = 0x0014,
FGA_ICRMBOX6 = 0x0018,
FGA_ICRMBOX7 = 0x001C,
FGA_VMEPAGE = 0x0200,
FGA_ICRVME1 = 0x0204,
FGA_ICRVME2 = 0x0208,
FGA_ICRVME3 = 0x020c,
FGA_ICRVME4 = 0x0210,
FGA_ICRVME5 = 0x0214,
FGA_ICRVME6 = 0x0218,
FGA_ICRVME7 = 0x021c,
FGA_ICRTIM0 = 0x0220,
FGA_ICRDMANORM = 0x0230,
FGA_ICRDMAERR = 0x0234,
FGA_CTL1 = 0x0238,
FGA_CTL2 = 0x023c,
FGA_ICRFMB0REF = 0x0240,
FGA_ICRFMB1REF = 0x0244,
FGA_ICRFMB0MES = 0x0248,
FGA_ICRFMB1MES = 0x024c,
FGA_CTL3 = 0x0250,
FGA_CTL4 = 0x0254,
FGA_ICRPARITY = 0x0258,
FGA_AUXPINCTL = 0x0260,
FGA_CTL5 = 0x0264,
FGA_AUXFIFWEX = 0x0268,
FGA_AUXFIFREX = 0x026c,
FGA_CTL6 = 0x0270,
FGA_CTL7 = 0x0274,
FGA_CTL8 = 0x0278,
FGA_CTL9 = 0x027c,
FGA_ICRABORT = 0x0280,
FGA_ICRACFAIL = 0x0284,
FGA_ICRSYSFAIL = 0x0288,
FGA_ICRLOCAL0 = 0x028c,
FGA_ICRLOCAL1 = 0x0290,
FGA_ICRLOCAL2 = 0x0294,
FGA_ICRLOCAL3 = 0x0298,
FGA_ICRLOCAL4 = 0x029c,
FGA_ICRLOCAL5 = 0x02a0,
FGA_ICRLOCAL6 = 0x02a4,
FGA_ICRLOCAL7 = 0x02a8,
FGA_ENAMCODE = 0x02b4,
FGA_CTL10 = 0x02c0,
FGA_CTL11 = 0x02c4,
FGA_MAINUM = 0x02c8,
FGA_MAINUU = 0x02cc,
FGA_BOTTOMPAGEU = 0x02d0,
FGA_BOTTOMPAGEL = 0x02d4,
FGA_TOPPAGEU = 0x02d8,
FGA_TOPPAGEL = 0x02dc,
FGA_MYVMEPAGE = 0x02fc,
FGA_TIM0PRELOAD = 0x0300,
FGA_TIM0CTL = 0x0310,
FGA_DMASRCATT = 0x0320,
FGA_DMADSTATT = 0x0324,
FGA_DMA_GENERAL = 0x0328,
FGA_CTL12 = 0x032c,
FGA_LIOTIMING = 0x0330,
FGA_LOCALIACK = 0x0334,
FGA_FMBCTL = 0x0338,
FGA_FMBAREA = 0x033c,
FGA_AUXSRCSTART = 0x0340,
FGA_AUXDSTSTART = 0x0344,
FGA_AUXSRCTERM = 0x0348,
FGA_AUXDSTTERM = 0x034c,
FGA_CTL13 = 0x0350,
FGA_CTL14 = 0x0354,
FGA_CTL15 = 0x0358,
FGA_CTL16 = 0x035c,
FGA_SPECIALENA = 0x0424,
FGA_ISLOCAL0 = 0x0480,
FGA_ISLOCAL1 = 0x0484,
FGA_ISLOCAL2 = 0x0488,
FGA_ISLOCAL3 = 0x048C,
FGA_ISLOCAL4 = 0x0490,
FGA_ISLOCAL5 = 0x0494,
FGA_ISLOCAL6 = 0x0498,
FGA_ISLOCAL7 = 0x049C,
FGA_ISTIM0 = 0x04a0,
FGA_ISDMANORM = 0x04b0,
FGA_ISDMAERR = 0x04b4,
FGA_ISFMB0REF = 0x04b8,
FGA_ISFMB1REF = 0x04bc,
FGA_ISPARITY = 0x04c0,
FGA_DMARUNCTL = 0x04c4,
FGA_ISABORT = 0x04c8,
FGA_ISACFAIL = 0x04cc,
FGA_ISFMB0MES = 0x04e0,
FGA_ISFMB1MES = 0x04e4,
FGA_ISSYSFAIL = 0x04d0,
FGA_ABORTPIN = 0x04d4,
FGA_RSVMECALL = 0x04f0,
FGA_RSKEYRES = 0x04f4,
FGA_RSCPUCALL = 0x04f8,
FGA_RSLOCSW = 0x04fc,
FGA_TIM0COUNT = 0x0c00,
};
};
// device type definition
DECLARE_DEVICE_TYPE(FGA002, fga002_device)
#endif // MAME_MACHINE_FGA002_H