mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
New device: BIM 68153
This commit is contained in:
parent
651631b86d
commit
be76377dcf
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
420
src/devices/machine/68153bim.cpp
Normal file
420
src/devices/machine/68153bim.cpp
Normal 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;
|
||||
}
|
225
src/devices/machine/68153bim.h
Normal file
225
src/devices/machine/68153bim.h
Normal 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 */
|
Loading…
Reference in New Issue
Block a user