New device: BIM 68153

This commit is contained in:
Joakim Larsson Edstrom 2017-01-11 19:56:35 +01:00
parent 651631b86d
commit be76377dcf
5 changed files with 660 additions and 0 deletions

View File

@ -234,6 +234,18 @@ if (MACHINES["ACIA6850"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/machine/68153bim.h,MACHINES["BIM68153"] = true
---------------------------------------------------
if (MACHINES["BIM68153"]~=null) then
files {
MAME_DIR .. "src/devices/machine/68153bim.cpp",
MAME_DIR .. "src/devices/machine/68153bim.h",
}
end
---------------------------------------------------
--
--@src/devices/machine/68230pit.h,MACHINES["PIT68230"] = true

View File

@ -387,6 +387,7 @@ MACHINES["AT45DBXX"] = true
MACHINES["ATAFLASH"] = true
MACHINES["AY31015"] = true
MACHINES["BANKDEV"] = true
--MACHINES["BIM68153"] = true
MACHINES["CDP1852"] = true
MACHINES["CDP1871"] = true
MACHINES["CMOS40105"] = true
@ -505,6 +506,7 @@ MACHINES["PCF8593"] = true
MACHINES["PCI"] = true
MACHINES["PCKEYBRD"] = true
MACHINES["PIC8259"] = true
--MACHINES["PIT68230"] = true
MACHINES["PIT8253"] = true
MACHINES["PLA"] = true
--MACHINES["PROFILE"] = true

View File

@ -376,6 +376,7 @@ MACHINES["AT45DBXX"] = true
MACHINES["ATAFLASH"] = true
MACHINES["AY31015"] = true
MACHINES["BANKDEV"] = true
MACHINES["BIM68153"] = true
MACHINES["CDP1852"] = true
MACHINES["CDP1871"] = true
MACHINES["CDP1879"] = true

View File

@ -0,0 +1,420 @@
// license:BSD-3-Clause
// copyright-holders: Joakim Larsson Edstrom
/***************************************************************************
68153 BIM Bus Interrupter Module
The Bus Interrupter Module (BIM) provides an interface between interrupting devices and a system bus such as
the VMEbus or VERSAbus. It generates a maximum of 7 bus interrupts on the IRQ1-IRQ7 outputs and responds to
interrupt acknowledge cycles for up to 4 independent slaves. The BIM can also supply an interrupt vector
during an interrupt acknowledge cycle. Moreover, it sits in the interrupt acknowledge daisychain which allows
for multiple interrupts on the level acknowledged.
----- Features ----------------------------------------------------------
x 4 channels
x Programmable Interrupt Request levels
x Programmable Interrupt Vectors
x Daisy Chain support
Full functionality is implemented
-------------------------------------------------------------------------
Level of implementation: x = done p = partial
-------------------------------------------------------------------------
*/
#include "cpu/m68000/m68000.h"
#include "68153bim.h"
#define LOG_GENERAL 0x01
#define LOG_SETUP 0x02
#define LOG_PRINTF 0x04
#define LOG_INT 0x08
#define LOG_READ 0x10
#define LOG_IACK 0x20
#define VERBOSE 0 // (LOG_PRINTF | LOG_SETUP | LOG_INT | LOG_IACK) //LOG_GENERAL | LOG_READ)
#define LOGMASK(mask, ...) do { if (VERBOSE & mask) logerror(__VA_ARGS__); } while (0)
#define LOGLEVEL(mask, level, ...) do { if ((VERBOSE & mask) >= level) logerror(__VA_ARGS__); } while (0)
#define LOG(...) LOGMASK(LOG_GENERAL, __VA_ARGS__)
#define LOGSETUP(...) LOGMASK(LOG_SETUP, __VA_ARGS__)
#define LOGINT(...) LOGMASK(LOG_INT, __VA_ARGS__)
#define LOGR(...) LOGMASK(LOG_READ, __VA_ARGS__)
#define LOGIACK(...) LOGMASK(LOG_IACK, __VA_ARGS__)
#if VERBOSE & LOG_PRINTF
#define logerror printf
#endif
#ifdef _MSC_VER
#define FUNCNAME __func__
#else
#define FUNCNAME __PRETTY_FUNCTION__
#endif
#define CHN0_TAG "ch0"
#define CHN1_TAG "ch1"
#define CHN2_TAG "ch2"
#define CHN3_TAG "ch3"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
// device type definition
const device_type MC68153_CHANNEL = &device_creator<bim68153_channel>;
const device_type MC68153 = &device_creator<bim68153_device>;
const device_type EI68C153 = &device_creator<ei68c153_device>;
//-------------------------------------------------
// device_mconfig_additions -
//-------------------------------------------------
MACHINE_CONFIG_FRAGMENT( m68153 )
MCFG_DEVICE_ADD(CHN0_TAG, MC68153_CHANNEL, 0)
MCFG_DEVICE_ADD(CHN1_TAG, MC68153_CHANNEL, 0)
MCFG_DEVICE_ADD(CHN2_TAG, MC68153_CHANNEL, 0)
MCFG_DEVICE_ADD(CHN3_TAG, MC68153_CHANNEL, 0)
MACHINE_CONFIG_END
machine_config_constructor bim68153_device::device_mconfig_additions() const
{
LOG("%s\n", FUNCNAME);
return MACHINE_CONFIG_NAME( m68153 );
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// bim68153_device - constructor
//-------------------------------------------------
bim68153_device::bim68153_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, uint32_t variant, const char *shortname, const char *source)
: device_t(mconfig, type, name, tag, owner, clock, shortname, source)
,m_chn{{*this, CHN0_TAG}, {*this, CHN1_TAG}, {*this, CHN2_TAG}, {*this, CHN3_TAG}}
,m_out_int_cb(*this)
,m_out_intal0_cb(*this)
,m_out_intal1_cb(*this)
,m_out_iackout_cb(*this)
,m_iackin(ASSERT_LINE)
,m_irq_level(0)
{
LOG("%s\n", FUNCNAME);
}
bim68153_device::bim68153_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, MC68153, "Motorola MC68153 BIM", tag, owner, clock, "m68153bim", __FILE__)
,m_chn{{*this, CHN0_TAG}, {*this, CHN1_TAG}, {*this, CHN2_TAG}, {*this, CHN3_TAG}}
,m_out_int_cb(*this)
,m_out_intal0_cb(*this)
,m_out_intal1_cb(*this)
,m_out_iackout_cb(*this)
,m_iackin(ASSERT_LINE)
,m_irq_level(0)
{
LOG("%s\n", FUNCNAME);
}
/* The EPIC EI68C153 is a CMOS implementation that is fully compatible with the bipolar MC68153 from Motorola */
ei68c153_device::ei68c153_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: bim68153_device(mconfig, EI68C153, "EPIC EI68C153 BIM", tag, owner, clock, TYPE_EI68C153, "ei68c153", __FILE__)
{
LOG("%s\n", FUNCNAME);
}
//-------------------------------------------------
// get_channel_index
//-------------------------------------------------
int bim68153_device::get_channel_index(bim68153_channel *ch)
{
assert(ch == m_chn[CHN_0] || ch == m_chn[CHN_1] || ch == m_chn[CHN_2] || ch == m_chn[CHN_3]);
if (ch == m_chn[CHN_0]) return 0;
else if (ch == m_chn[CHN_1]) return 1;
else if (ch == m_chn[CHN_2]) return 2;
else return 3;
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void bim68153_device::device_start()
{
LOG("%s\n", FUNCNAME);
// resolve callbacks
m_out_int_cb.resolve_safe();
m_out_intal0_cb.resolve_safe();
m_out_intal1_cb.resolve_safe();
m_out_iackout_cb.resolve_safe(0);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void bim68153_device::device_reset()
{
LOG("%s %s \n",tag(), FUNCNAME);
// Reset on all channels
for (auto & elem : m_chn)
elem->reset();
}
/*
* Interrupts
* The BIM accepts device interrupt requests on inputs INT0, INT1, INT2 and INT3. Each input is regulated by
* Bit 4 (IRE) of the associated control register (CRO controls INT0, CR! controls INT1,etc.). If IRE (Interrupt
* Enable) is set and a device input is asserted, an Interrupt Request open-collector output (IRQ1 - IRQ7)
* is asserted. The asserted IRQX output is selected by the value programmed in Bits 0, 1, and 2 of the control
* register (L0, L1, and L3). This 3-bit field determines the interrupt request level as set by software.
*
* Two or more interrupt sources can be programmed to the same request level. The corresponding IRQX output
* will remain asserted until multiple interrupt acknowledge cycles respond to all requests.
*
* If the interrupt request level is set to zero, the interrupt is disabled because there is no corresponding IRQ output.
*/
/*
The response of an interrupt Handler to a bus interrupt request is an interrupt acknowledge cycle. The IACK
cycle is initiated in BIM by receiving IACK low R/W, A1, A2, A3 are latched, and the interrupt level on line A1-A3
is compared with any interrupt requests pending in the chip. Further activity can be one of four cases.*/
#define MAX_VECTOR 255
IRQ_CALLBACK_MEMBER(bim68153_device::iack)
{
int vec = M68K_INT_ACK_AUTOVECTOR;
int found = 0;
// int level = 0;
int ch = -1;
LOGIACK("%s %s()\n", tag(), FUNCNAME);
/* 1. No further action required — This occurs if IACKIN is not asserted. Asserting IACKN only starts the BIM activity.
* If the daisy chain signal never reaches the BIM (IACKIN is not asserted), another interrupter has responded to the
* IACK cycle. The cycle will end, the IACK is negated, and no additional action is required. */
if (m_iackin == CLEAR_LINE)
{
m_out_iackout_cb(CLEAR_LINE);
m_out_int_cb(CLEAR_LINE); // should really be tristated
return MAX_VECTOR + 1; // This is a 68K emulation specific response and will terminate the iack cycle
}
for (auto & elem : m_chn)
{ // If this channel has interrupts enabled and pending
if (elem->m_int_state == bim68153_channel::PENDING && elem->m_control & bim68153_channel::REG_CNTRL_INT_ENABLE)
{ // and the level matches
if ((elem->m_control & bim68153_channel::REG_CNTRL_INT_LVL_MSK) == irqline)
{ // then remember it
ch = get_channel_index(elem);
}
found = 1;
}
}
/* 2. Pass on the interrupt daisy chain — For this case, IACKIN input is asserted by the preceding daisy chain interrupter,
* and IACKOUT output is in turn asserted. The daisy chain signal is passed on when no interrupts are pending on a matching
* level or when any possible interrupts are disabled. The Interrupt Enable (IRE) bit of a control register can disable any
* interrupt requests, and in turn, any possible matches */
if (found == 0)
{
m_out_iackout_cb(CLEAR_LINE); // No more interrupts to serve, pass the message to next device in daisy chain
m_out_int_cb(CLEAR_LINE); // should really be tristated but board driver must make sure to mitigate if this is a problem
return MAX_VECTOR + 1; // This is a 68K emulation specific response and will terminate the iack cycle
}
m_irq_level = m_chn[ch]->m_control & bim68153_channel::REG_CNTRL_INT_LVL_MSK;
if ((m_chn[ch]->m_control & bim68153_channel::REG_CNTRL_INT_EXT) == 0)
{
/* 3. Respond internally - For this case, IACKIN is asserted and a match is found. The BIM completes the IACK cycle by
* supplying an interrupt vector from the proper vector register followed by a DTACK signal asserted because the interrupt
* acknowledge cycle is completed by this device. For the BIM to respond in this mode of operation, the EXTERNAL/INTERNAl
* control register bit (X/IN) must be zero. For each source of interrupt request, the associated control register determines
* the BIM response to an IACK cycle, and the X/IN bit sets this response either internally (X/IN = 0 ) or externally (X/IN = 1). */
vec = m_chn[ch]->m_vector; // Internal vector
}
else
{
/* 4. Respond externally — For the final case, IACKIN is also asserted, a match is found and the associated control register has
* X/IN bit set to one. The BIM does not assert IACKOUT and does assert INTAE low.INTAE signals that the requesting device must
* complete the IACK cycle (supplying a vector and DTACK) and that the 2-bit code contained on outputs INTALO and INTAL1 shows
* which interrupt source is being acknowledged*/
vec = m_chn[ch]->m_out_iack_cb(); // External vector
/* Also support INTAL0 and INTAL1 in case additional logic relies on it */
m_out_intal0_cb( ch & 1);
m_out_intal1_cb((ch >> 1) & 1);
/* TODO: Figure out a way to update the vector in case INTAL0/INTAL1 is involved creating it */
}
LOGIACK(" - Interrupt Acknowledge Vector %02x, next interrupt is off %02x\n", vec, m_irq_level);
if (m_chn[ch]->m_control & bim68153_channel::REG_CNTRL_INT_AUT_DIS)
{
LOGIACK(" - Interrupts on channel %d disabled due to the IRAC (Auto Clear) bit is set\n", ch);
m_chn[ch]->m_control &= ~bim68153_channel::REG_CNTRL_INT_ENABLE;
}
// This is not explicitly said in the 68153 datasheet but what would a flag be used for otherwise?
m_chn[ch]->m_control &= ~bim68153_channel::REG_CNTRL_INT_FLAG;
m_out_iackout_cb(CLEAR_LINE);
m_out_int_cb(CLEAR_LINE);
return vec;
}
int bim68153_device::get_irq_level()
{
LOGINT("%s %s() - %02x\n", tag(), FUNCNAME, m_irq_level);
return m_irq_level;
}
//-------------------------------------------------
// trigger_interrupt -
//-------------------------------------------------
void bim68153_device::trigger_interrupt(int ch)
{
LOGINT("%s %s CHN:%d\n",FUNCNAME, tag(), ch);
if (!(m_chn[ch]->m_control & bim68153_channel::REG_CNTRL_INT_ENABLE))
{
LOGINT("Interrupt Enable for channel %d is not set, blocking attempt to interrupt\n", ch);
return;
}
m_irq_level = (m_chn[ch]->m_control & bim68153_channel::REG_CNTRL_INT_LVL_MSK);
// trigger interrupt
m_chn[ch]->m_int_state = bim68153_channel::PENDING;
// assert daisy chain
m_out_iackout_cb(ASSERT_LINE);
// Set flag
// This is not explicitly said in the 68153 datasheet but what would a flag be used for otherwise?
m_chn[ch]->m_control |= bim68153_channel::REG_CNTRL_INT_FLAG;
// assert interrupt
m_out_int_cb(ASSERT_LINE);
}
//-------------------------------------------------
// read
//-------------------------------------------------
READ8_MEMBER( bim68153_device::read )
{
int vc = offset & REG_VECTOR;
int ch = offset & CHN_MSK;
LOGR(" * %s %d Reg %s -> %02x \n", m_owner->tag(), ch, vc ? "vector" : "control",
vc ? m_chn[ch]->do_bimreg_vector_r() : m_chn[ch]->do_bimreg_control_r());
return vc ? m_chn[ch]->do_bimreg_vector_r() : m_chn[ch]->do_bimreg_control_r();
}
//-------------------------------------------------
// write
//-------------------------------------------------
WRITE8_MEMBER( bim68153_device::write )
{
int vc = offset & REG_VECTOR;
int ch = offset & CHN_MSK;
LOGSETUP(" * %s %d Reg %s <- %02x \n", m_owner->tag(), ch, vc ? "vector" : "control", data);
if (vc)
m_chn[ch]->do_bimreg_vector_w(data);
else
m_chn[ch]->do_bimreg_control_w(data);
}
//**************************************************************************
// BIM CHANNEL
//**************************************************************************
bim68153_channel::bim68153_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, MC68153_CHANNEL, "BIM channel", tag, owner, clock, "bim68153_channel", __FILE__)
,m_out_iack_cb(*this)
,m_int_state(NONE)
,m_control(0)
,m_vector(0)
{
LOG("%s\n",FUNCNAME);
}
//-------------------------------------------------
// start - channel startup
//-------------------------------------------------
void bim68153_channel::device_start()
{
LOGSETUP("%s\n", FUNCNAME);
m_bim = downcast<bim68153_device *>(owner());
m_index = m_bim->get_channel_index(this);
// state saving
save_item(NAME(m_control));
save_item(NAME(m_vector));
save_item(NAME(m_int_state));
// Resolve callbacks
m_out_iack_cb.resolve_safe(0);
}
//-------------------------------------------------
// reset - reset channel status
//-------------------------------------------------
void bim68153_channel::device_reset()
{
LOGSETUP("%s\n", FUNCNAME);
// Reset all registers
m_control = 0;
m_vector = 0x0f;
m_int_state = NONE;
}
/* Trigger an interrupt */
WRITE_LINE_MEMBER( bim68153_channel::int_w )
{
LOGINT("%s Ch %d: %d\n",FUNCNAME, m_index, state);
if (state == ASSERT_LINE)
{
m_bim->trigger_interrupt(m_index);
}
}
uint8_t bim68153_channel::do_bimreg_control_r()
{
LOG("%s ch %d returns %02x\n", FUNCNAME, m_index, m_control);
return m_control;
}
uint8_t bim68153_channel::do_bimreg_vector_r()
{
LOG("%s ch %d returns %02x\n", FUNCNAME, m_index, m_vector);
return m_vector;
}
void bim68153_channel::do_bimreg_control_w(uint8_t data)
{
LOG("%s ch %d set control to %02x\n", FUNCNAME, m_index, data);
LOGSETUP(" - Lev:%d Auto Disable:%d Int Enable:%d Vector:%d Auto Clear:%d Flag:%d\n",
data & REG_CNTRL_INT_LVL_MSK,
data & REG_CNTRL_INT_AUT_DIS ? 1 : 0,
data & REG_CNTRL_INT_ENABLE ? 1 : 0,
data & REG_CNTRL_INT_EXT ? 1 : 0,
data & REG_CNTRL_INT_AUT_CLR ? 1 : 0,
data & REG_CNTRL_INT_FLAG ? 1 : 0);
m_control = data;
}
void bim68153_channel::do_bimreg_vector_w(uint8_t data)
{
LOG("%s ch %d set vector to %02x\n", FUNCNAME, m_index, data);
m_vector = data;
}

View File

@ -0,0 +1,225 @@
// license:BSD-3-Clause
// copyright-holders:Joakim Larsson Edstrom
/**********************************************************************
*
* Motorola MC68153 BIM - Bus Interrupter Module
*
* _____ _____
* Vcc 1 |* \_/ | 40 A3
* RW* 2 | | 39 A2
* CS* 3 | | 38 A1
* DTACK* 4 | | 37 D7
* IACK* 5 | | 36 D6
* IACKIN* 6 | | 35 D5
* IACKOUT* 7 | | 34 D4
* IRQ1* 8 | | 33 D3
* GND 9 | | 32 D2
* GND 10 | | 31 GND
* Vcc 11 | | 30 VCC
* IRQ2* 12 | MC68153 | 29 D1
* IRQ3* 13 | EI68C153 | 28 D0
* IRQ4* 14 | | 27 INTAE*
* IRQ5* 15 | | 26 INTAL1
* IRQ6* 16 | | 25 INTAL0
* IRQ7* 17 | | 24 INT3*
* CLK* 18 | | 23 INT2*
* INT0* 19 | | 22 INT1*
* GND 20 |_____________| 21 Vcc
*
**********************************************************************/
#pragma once
#ifndef MC68153BIM_H
#define MC68153BIM_H
#include "emu.h"
//**************************************************************************
// DEVICE CONFIGURATION MACROS
//**************************************************************************
/* Variant ADD macros - use the right one to enable the right feature set! */
#define MCFG_MC68153_ADD(_tag, _clock) \
MCFG_DEVICE_ADD(_tag, MC68153, _clock)
#define MCFG_EI68C153_ADD(_tag, _clock) \
MCFG_DEVICE_ADD(_tag, EI68C153, _clock)
#define MCFG_BIM68153_OUT_INT_CB(_devcb) \
devcb = &bim68153_device::set_out_int_callback(*device, DEVCB_##_devcb);
// These callback sets INTAL0 and INTAL1 but is probably not needed as the
// shorthand OUT_IACK0..OUT_IACK3 below embedd the channel information
#define MCFG_BIM68153_OUT_INTAL0_CB(_devcb) \
devcb = &bim68153_device::set_out_intal0_callback(*device, DEVCB_##_devcb);
#define MCFG_BIM68153_OUT_INTAL1_CB(_devcb) \
devcb = &bim68153_device::set_out_intal1_callback(*device, DEVCB_##_devcb);
// LOCAL IACK callbacks emulating the INTAL0 and INTAL1 outputs for INTAE requesting a vector from a sub device
#define MCFG_BIM68153_OUT_IACK0_CB(_devcb) \
devcb = &bim68153::set_out_iack1_callback(*device, DEVCB_##_devcb);
#define MCFG_BIM68153_OUT_IACK1_CB(_devcb) \
devcb = &bim68153::set_out_iack2_callback(*device, DEVCB_##_devcb);
#define MCFG_BIM68153_OUT_IACK2_CB(_devcb) \
devcb = &bim68153::set_out_iack3_callback(*device, DEVCB_##_devcb);
#define MCFG_BIM68153_OUT_IACK3_CB(_devcb) \
devcb = &bim68153::set_out_iack3_callback(*device, DEVCB_##_devcb);
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class bim68153_device;
class bim68153_channel : public device_t
{
friend class bim68153_device;
public:
bim68153_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// read register handlers
uint8_t do_bimreg_control_r();
uint8_t do_bimreg_vector_r();
// write register handlers
void do_bimreg_control_w(uint8_t data);
void do_bimreg_vector_w(uint8_t vector);
DECLARE_WRITE_LINE_MEMBER( int_w );
devcb_read8 m_out_iack_cb;
uint8_t m_int_state;
// Register state
uint8_t m_control;
uint8_t m_vector;
protected:
enum
{
NONE = 0,
PENDING = 1,
};
enum
{
RCV_IDLE = 0,
RCV_SEEKING = 1,
RCV_SAMPLING = 2
};
enum
{
REG_CNTRL_INT_LVL_MSK = 0x07,
REG_CNTRL_INT_AUT_DIS = 0x08,
REG_CNTRL_INT_ENABLE = 0x10,
REG_CNTRL_INT_EXT = 0x20,
REG_CNTRL_INT_AUT_CLR = 0x40,
REG_CNTRL_INT_FLAG = 0x80,
};
int m_int; // interrupt request from connected device
int m_index; // Which channel am I?
bim68153_device *m_bim; // my device
};
class bim68153_device : public device_t
{
friend class bim68153_channel;
public:
// construction/destruction
bim68153_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, uint32_t variant, const char *shortname, const char *source);
bim68153_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
IRQ_CALLBACK_MEMBER(iack);
int acknowledge();
int get_irq_level();
template<class _Object> static devcb_base &set_out_int_callback(device_t &device, _Object object) { return downcast<bim68153_device &>(device).m_out_int_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_intal0_callback(device_t &device, _Object object) { return downcast<bim68153_device &>(device).m_out_intal0_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_intal1_callback(device_t &device, _Object object) { return downcast<bim68153_device &>(device).m_out_intal1_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_iack0_callback(device_t &device, _Object object) { return downcast<bim68153_device &>(device).m_chn[CHN_0]->m_out_iack_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_iack1_callback(device_t &device, _Object object) { return downcast<bim68153_device &>(device).m_chn[CHN_1]->m_out_iack_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_iack2_callback(device_t &device, _Object object) { return downcast<bim68153_device &>(device).m_chn[CHN_2]->m_out_iack_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_iack4_callback(device_t &device, _Object object) { return downcast<bim68153_device &>(device).m_chn[CHN_3]->m_out_iack_cb.set_callback(object); }
DECLARE_READ8_MEMBER( read );
DECLARE_WRITE8_MEMBER( write );
DECLARE_WRITE_LINE_MEMBER( iackin_w ) { m_iackin = state; }
DECLARE_WRITE_LINE_MEMBER( int0_w ) { m_chn[CHN_0]->int_w(state); }
DECLARE_WRITE_LINE_MEMBER( int1_w ) { m_chn[CHN_1]->int_w(state); }
DECLARE_WRITE_LINE_MEMBER( int2_w ) { m_chn[CHN_2]->int_w(state); }
DECLARE_WRITE_LINE_MEMBER( int3_w ) { m_chn[CHN_3]->int_w(state); }
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual machine_config_constructor device_mconfig_additions() const override;
void trigger_interrupt(int ch);
int get_channel_index(bim68153_channel *ch);
// Register enums
enum
{
REG_CONTROL = 0x00,
REG_VECTOR = 0x04,
CHN_MSK = 0x03,
CHN_0 = 0x00,
CHN_1 = 0x01,
CHN_2 = 0x02,
CHN_3 = 0x03,
};
enum
{
INT_CHN0 = 0,
INT_CHN1 = 1,
INT_CHN2 = 2,
INT_CHN3 = 3,
};
// Variants of BIM
enum
{
TYPE_MC68153 = 0x001,
TYPE_EI68C153 = 0x002,
};
required_device<bim68153_channel> m_chn[4];
devcb_write_line m_out_int_cb;
// iack signalling towards subdevices, see also out_iack_callbacks in each bim68153_channel which overlaps
devcb_write_line m_out_intal0_cb;
devcb_write_line m_out_intal1_cb;
// Daisy chain signals
devcb_read8 m_out_iackout_cb;
int m_iackin;
int m_irq_level;
};
class ei68c153_device : public bim68153_device
{
public :
ei68c153_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
// device type definition
extern const device_type MC68153;
extern const device_type EI68C153;
extern const device_type MC68153_CHANNEL;
#endif /* MC68153BIM_H */