hp_dio: add shared IRQ and DMA capabilities

This commit is contained in:
Sven Schnelle 2018-10-08 19:53:40 +02:00
parent ad129a4673
commit 9e61e6a018
2 changed files with 263 additions and 63 deletions

View File

@ -8,6 +8,11 @@
#include "emu.h"
#include "hp_dio.h"
#include "hp98543.h"
#include "hp98544.h"
#include "hp98603a.h"
#include "hp98603b.h"
#include "hp98644.h"
//**************************************************************************
// GLOBAL VARIABLES
@ -96,11 +101,17 @@ dio16_device::dio16_device(const machine_config &mconfig, device_type type, cons
device_t(mconfig, type, tag, owner, clock),
m_maincpu(*this, finder_base::DUMMY_TAG),
m_prgspace(nullptr),
m_out_irq3_cb(*this),
m_out_irq4_cb(*this),
m_out_irq5_cb(*this),
m_out_irq6_cb(*this)
m_irq1_out_cb(*this),
m_irq2_out_cb(*this),
m_irq3_out_cb(*this),
m_irq4_out_cb(*this),
m_irq5_out_cb(*this),
m_irq6_out_cb(*this),
m_irq7_out_cb(*this),
m_dmar0_out_cb(*this),
m_dmar1_out_cb(*this)
{
std::fill(std::begin(m_cards), std::end(m_cards), nullptr);
m_prgwidth = 0;
}
@ -110,13 +121,21 @@ dio16_device::dio16_device(const machine_config &mconfig, device_type type, cons
void dio16_device::device_start()
{
m_out_irq3_cb.resolve_safe();
m_out_irq4_cb.resolve_safe();
m_out_irq5_cb.resolve_safe();
m_out_irq6_cb.resolve_safe();
m_irq1_out_cb.resolve_safe();
m_irq2_out_cb.resolve_safe();
m_irq3_out_cb.resolve_safe();
m_irq4_out_cb.resolve_safe();
m_irq5_out_cb.resolve_safe();
m_irq6_out_cb.resolve_safe();
m_irq7_out_cb.resolve_safe();
m_dmar0_out_cb.resolve_safe();
m_dmar1_out_cb.resolve_safe();
m_prgspace = &m_maincpu->space(AS_PROGRAM);
m_prgwidth = m_maincpu->space_config(AS_PROGRAM)->data_width();
save_item(NAME(m_irq));
save_item(NAME(m_dmar));
}
//-------------------------------------------------
@ -127,25 +146,128 @@ void dio16_device::device_reset()
{
}
void dio16_device::install_memory(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler)
unsigned dio16_device::add_card(device_dio16_card_interface &card)
{
switch (m_prgwidth)
{
case 16:
m_prgspace->install_readwrite_handler(start, end, rhandler, whandler);
m_cards.push_back(&card);
return m_bus_index++;
}
void dio16_device::set_irq(unsigned index, unsigned int level, int state)
{
bool const changed(bool(state) != BIT(m_irq[level], index));
if (!changed)
return;
if (state)
m_irq[level] |= (1 << index);
else
m_irq[level] &= ~(1 << index);
if (m_bus_index != index) {
switch (level) {
case 0:
m_irq1_out_cb(state);
break;
case 32:
m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, 0xffffffff);
case 1:
m_irq2_out_cb(state);
break;
default:
fatalerror("DIO: Bus width %d not supported\n", m_prgwidth);
case 2:
m_irq3_out_cb(state);
break;
case 3:
m_irq4_out_cb(state);
break;
case 4:
m_irq5_out_cb(state);
break;
case 5:
m_irq6_out_cb(state);
break;
case 6:
m_irq7_out_cb(state);
break;
}
}
}
void dio16_device::set_dmar(unsigned int index, unsigned int num, int state)
{
assert(num <= 1);
bool const changed(bool(state) != BIT(m_dmar[num], index));
if (!changed)
return;
if (state)
m_dmar[num] |= (1 << index);
else
m_dmar[num] &= ~(1 << index);
for (auto & card:m_cards) {
if (card->get_index() == index)
continue;
switch (num) {
case 0:
card->dmar0_in(state);
break;
case 1:
card->dmar1_in(state);
break;
}
}
}
void dio16_device::dmack_w_out(int index, int channel, uint8_t val)
{
for (auto & card:m_cards) {
if (card->get_index() == index)
continue;
card->dmack_w_in(channel, val);
}
}
uint8_t dio16_device::dmack_r_out(int index, int channel)
{
uint8_t ret = 0xff;
for (auto & card:m_cards) {
if (card->get_index() == index)
continue;
ret &= card->dmack_r_in(channel);
}
return ret;
}
WRITE_LINE_MEMBER(dio16_device::reset_in)
{
for (auto & card:m_cards) {
if (card->get_index() != m_bus_index)
card->reset_in(state);
}
}
void dio16_device::install_memory(offs_t start, offs_t end,
read16_delegate rhandler,
write16_delegate whandler) {
switch (m_prgwidth) {
case 16:
m_prgspace->install_readwrite_handler(start, end, rhandler,
whandler);
break;
case 32:
m_prgspace->install_readwrite_handler(start, end, rhandler,
whandler, 0xffffffff);
break;
default:
fatalerror("DIO: Bus width %d not supported\n", m_prgwidth);
}
}
void dio16_device::install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data)
{
m_prgspace->install_readwrite_bank(start, end, 0, tag );
m_prgspace->install_readwrite_bank(start, end, 0, tag);
machine().root_device().membank(m_prgspace->device().siblingtag(tag).c_str())->set_base(data);
}
@ -165,6 +287,10 @@ void dio16_device::unmap_rom(offs_t start, offs_t end)
m_prgspace->unmap_read(start, end);
}
void device_dio16_card_interface::set_bus(dio16_device &bus)
{
m_index = (m_dio_dev = &bus)->add_card(*this);
}
//**************************************************************************
// DEVICE DIO16 CARD INTERFACE
@ -186,13 +312,10 @@ void device_dio16_card_interface::interface_pre_start()
throw emu_fatalerror("device_dio16_card_interface: DIO bus not configured\n");
}
//**************************************************************************
// DIO32 DEVICE
//**************************************************************************
dio32_device::dio32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
dio16_device(mconfig, DIO32, tag, owner, clock)
{
@ -203,7 +326,6 @@ void dio32_device::device_start()
dio16_device::device_start();
}
//**************************************************************************
// DEVICE DIO32 CARD INTERFACE
//**************************************************************************
@ -224,5 +346,15 @@ void device_dio32_card_interface::interface_pre_start()
if (m_dio_dev && !dynamic_cast<dio32_device *>(m_dio_dev))
throw emu_fatalerror("device_dio32_card_interface: DIO32 device %s (%s) in DIO16 slot %s\n", device().tag(), device().name(), m_dio_dev->name());
}
}
} // namespace bus::hp_dio
} // namespace bus
void hpdio_cards(device_slot_interface & device)
{
device.option_add("hp98543", HPDIO_98543);
device.option_add("hp98544", HPDIO_98544);
device.option_add("hp98603a", HPDIO_98603A);
device.option_add("hp98603b", HPDIO_98603B);
device.option_add("hp98644", HPDIO_98644);
}

View File

@ -23,22 +23,8 @@ namespace bus {
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_DIO16_CPU(_cputag) \
downcast<bus::hp_dio::dio16_device &>(*device).set_cputag(_cputag);
#define MCFG_DIO32_CPU(_cputag) \
downcast<bus::hp_dio::dio32_device &>(*device).set_cputag(_cputag);
#define MCFG_ISA_OUT_IRQ3_CB(_devcb) \
downcast<bus::hp_dio::dio16_device &>(*device).set_out_irq3_callback(DEVCB_##_devcb);
#define MCFG_ISA_OUT_IRQ4_CB(_devcb) \
downcast<bus::hp_dio::dio16_device &>(*device).set_out_irq4_callback(DEVCB_##_devcb);
#define MCFG_ISA_OUT_IRQ5_CB(_devcb) \
downcast<bus::hp_dio::dio16_device &>(*device).set_out_irq5_callback(DEVCB_##_devcb);
#define MCFG_ISA_OUT_IRQ6_CB(_devcb) \
downcast<bus::hp_dio::dio16_device &>(*device).set_out_irq6_callback(DEVCB_##_devcb);
#define MCFG_DIO16_CPU(_cputag) downcast<bus::hp_dio::dio16_device &>(*device).set_cputag(_cputag);
#define MCFG_DIO32_CPU(_cputag) downcast<bus::hp_dio::dio32_device &>(*device).set_cputag(_cputag);
//**************************************************************************
// TYPE DEFINITIONS
@ -77,7 +63,6 @@ protected:
required_device<dio16_device> m_dio;
};
class device_dio16_card_interface;
// ======================> dio16_device
class dio16_device : public device_t
@ -86,11 +71,18 @@ public:
// construction/destruction
dio16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// inline configuration
template <typename T> void set_cputag(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); }
template <class Object> devcb_base &set_out_irq3_callback(Object &&cb) { return m_out_irq3_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_out_irq4_callback(Object &&cb) { return m_out_irq4_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_out_irq5_callback(Object &&cb) { return m_out_irq5_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_out_irq6_callback(Object &&cb) { return m_out_irq6_cb.set_callback(std::forward<Object>(cb)); }
template<typename T> void set_cputag(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); }
// callback configuration
auto dmar0_out_cb() { return m_dmar0_out_cb.bind(); }
auto dmar1_out_cb() { return m_dmar1_out_cb.bind(); }
auto irq1_out_cb() { return m_irq1_out_cb.bind(); }
auto irq2_out_cb() { return m_irq2_out_cb.bind(); }
auto irq3_out_cb() { return m_irq3_out_cb.bind(); }
auto irq4_out_cb() { return m_irq4_out_cb.bind(); }
auto irq5_out_cb() { return m_irq5_out_cb.bind(); }
auto irq6_out_cb() { return m_irq6_out_cb.bind(); }
auto irq7_out_cb() { return m_irq7_out_cb.bind(); }
void install_memory(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler);
@ -105,16 +97,44 @@ public:
void unmap_rom(offs_t start, offs_t end);
// IRQs 1, 2, and 7 are reserved for non-bus usage.
DECLARE_WRITE_LINE_MEMBER( irq3_w ) { m_out_irq3_cb(state); }
DECLARE_WRITE_LINE_MEMBER( irq4_w ) { m_out_irq4_cb(state); }
DECLARE_WRITE_LINE_MEMBER( irq5_w ) { m_out_irq5_cb(state); }
DECLARE_WRITE_LINE_MEMBER( irq6_w ) { m_out_irq6_cb(state); }
// input lines
DECLARE_WRITE_LINE_MEMBER(dmar0_in) { set_dmar(m_bus_index, 0, state); }
DECLARE_WRITE_LINE_MEMBER(dmar1_in) { set_dmar(m_bus_index, 1, state); }
DECLARE_WRITE_LINE_MEMBER(irq1_in) { set_irq(m_bus_index, 0, state); }
DECLARE_WRITE_LINE_MEMBER(irq2_in) { set_irq(m_bus_index, 1, state); }
DECLARE_WRITE_LINE_MEMBER(irq3_in) { set_irq(m_bus_index, 2, state); }
DECLARE_WRITE_LINE_MEMBER(irq4_in) { set_irq(m_bus_index, 3, state); }
DECLARE_WRITE_LINE_MEMBER(irq5_in) { set_irq(m_bus_index, 4, state); }
DECLARE_WRITE_LINE_MEMBER(irq6_in) { set_irq(m_bus_index, 5, state); }
DECLARE_WRITE_LINE_MEMBER(irq7_in) { set_irq(m_bus_index, 6, state); }
DECLARE_WRITE_LINE_MEMBER(reset_in);
// output lines
DECLARE_READ_LINE_MEMBER(irq1_out) const { return (m_irq[0] & ~m_bus_index) ? 1 : 0; }
DECLARE_READ_LINE_MEMBER(irq2_out) const { return (m_irq[1] & ~m_bus_index) ? 1 : 0; }
DECLARE_READ_LINE_MEMBER(irq3_out) const { return (m_irq[2] & ~m_bus_index) ? 1 : 0; }
DECLARE_READ_LINE_MEMBER(irq4_out) const { return (m_irq[3] & ~m_bus_index) ? 1 : 0; }
DECLARE_READ_LINE_MEMBER(irq5_out) const { return (m_irq[4] & ~m_bus_index) ? 1 : 0; }
DECLARE_READ_LINE_MEMBER(irq6_out) const { return (m_irq[5] & ~m_bus_index) ? 1 : 0; }
DECLARE_READ_LINE_MEMBER(irq7_out) const { return (m_irq[6] & ~m_bus_index) ? 1 : 0; }
DECLARE_READ_LINE_MEMBER(dmar0_out) const { return dmar0_r(); }
DECLARE_READ_LINE_MEMBER(dmar1_out) const { return dmar1_r(); }
bool dmar0_r() const { return (m_dmar[0] & ~m_bus_index) ? 1 : 0; }
bool dmar1_r() const { return (m_dmar[1] & ~m_bus_index) ? 1 : 0; }
uint8_t dmack_r_out(int index, int channel);
void dmack_w_out(int index, int channel, uint8_t data);
int m_prgwidth;
unsigned add_card(device_dio16_card_interface & card);
void set_irq(unsigned int index, unsigned int num, int state);
void set_dmar(unsigned int index, unsigned int num, int state);
protected:
dio16_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
void install_space(int spacenum, offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler);
// device-level overrides
@ -123,14 +143,26 @@ protected:
// internal state
required_device<cpu_device> m_maincpu;
std::list <device_dio16_card_interface *> m_cards;
// address spaces
address_space *m_prgspace;
int m_bus_index;
devcb_write_line m_out_irq3_cb;
devcb_write_line m_out_irq4_cb;
devcb_write_line m_out_irq5_cb;
devcb_write_line m_out_irq6_cb;
// packed line states
u16 m_irq[7];
u16 m_dmar[2];
devcb_write_line m_irq1_out_cb;
devcb_write_line m_irq2_out_cb;
devcb_write_line m_irq3_out_cb;
devcb_write_line m_irq4_out_cb;
devcb_write_line m_irq5_out_cb;
devcb_write_line m_irq6_out_cb;
devcb_write_line m_irq7_out_cb;
devcb_write_line m_dmar0_out_cb;
devcb_write_line m_dmar1_out_cb;
};
// ======================> device_dio16_card_interface
@ -145,20 +177,58 @@ public:
virtual ~device_dio16_card_interface();
device_dio16_card_interface *next() const { return m_next; }
// inline configuration
void set_diobus(dio16_device &dio_device) { m_dio_dev = &dio_device; }
void set_diobus(dio16_device &dio_device) {
m_dio_dev = &dio_device;
m_index = m_dio_dev->add_card(*this);
}
protected:
device_dio16_card_interface(const machine_config &mconfig, device_t &device);
dio16_device &dio() { assert(m_dio_dev); return *m_dio_dev; }
dio16_device &dio() {
assert(m_dio_dev);
return *m_dio_dev;
}
virtual void interface_pre_start() override;
int get_index() { return m_index; };
DECLARE_WRITE_LINE_MEMBER(irq1_out) { m_dio_dev->set_irq(m_index, 0, state); }
DECLARE_WRITE_LINE_MEMBER(irq2_out) { m_dio_dev->set_irq(m_index, 1, state); }
DECLARE_WRITE_LINE_MEMBER(irq3_out) { m_dio_dev->set_irq(m_index, 2, state); }
DECLARE_WRITE_LINE_MEMBER(irq4_out) { m_dio_dev->set_irq(m_index, 3, state); }
DECLARE_WRITE_LINE_MEMBER(irq5_out) { m_dio_dev->set_irq(m_index, 4, state); }
DECLARE_WRITE_LINE_MEMBER(irq6_out) { m_dio_dev->set_irq(m_index, 5, state); }
DECLARE_WRITE_LINE_MEMBER(irq7_out) { m_dio_dev->set_irq(m_index, 6, state); }
DECLARE_WRITE_LINE_MEMBER(dmar0_out) { m_dio_dev->set_dmar(m_index, 0, state); }
DECLARE_WRITE_LINE_MEMBER(dmar1_out) { m_dio_dev->set_dmar(m_index, 1, state); }
virtual DECLARE_WRITE_LINE_MEMBER(irq1_in) {}
virtual DECLARE_WRITE_LINE_MEMBER(irq2_in) {}
virtual DECLARE_WRITE_LINE_MEMBER(irq3_in) {}
virtual DECLARE_WRITE_LINE_MEMBER(irq4_in) {}
virtual DECLARE_WRITE_LINE_MEMBER(irq5_in) {}
virtual DECLARE_WRITE_LINE_MEMBER(irq6_in) {}
virtual DECLARE_WRITE_LINE_MEMBER(irq7_in) {}
virtual DECLARE_WRITE_LINE_MEMBER(dmar0_in) {}
virtual DECLARE_WRITE_LINE_MEMBER(dmar1_in) {}
virtual uint8_t dmack_r_out(int channel) { return m_dio_dev->dmack_r_out(m_index, channel); }
virtual void dmack_w_out(int channel, uint8_t data) { m_dio_dev->dmack_w_out(m_index, channel, data); }
virtual uint8_t dmack_r_in(int channel) { return 0xff; }
virtual void dmack_w_in(int channel, uint8_t data) {}
virtual DECLARE_WRITE_LINE_MEMBER(reset_in) {}
bool dmar0_r() const { return m_dio_dev->dmar0_r(); }
bool dmar1_r() const { return m_dio_dev->dmar1_r(); }
dio16_device *m_dio_dev;
private:
void set_bus(dio16_device & bus);
device_dio16_card_interface *m_next;
unsigned int m_index;
};
class dio32_device;
@ -184,8 +254,6 @@ protected:
virtual void device_start() override;
};
// ======================> dio32_device
class dio32_device : public dio16_device
{
@ -200,8 +268,6 @@ protected:
virtual void device_start() override;
};
// ======================> device_dio32_card_interface
// class representing interface-specific live dio32 card
@ -228,4 +294,6 @@ DECLARE_DEVICE_TYPE_NS(DIO32, bus::hp_dio, dio32_device)
DECLARE_DEVICE_TYPE_NS(DIO32_SLOT, bus::hp_dio, dio32_slot_device)
DECLARE_DEVICE_TYPE_NS(DIO16, bus::hp_dio, dio16_device)
void hpdio_cards(device_slot_interface &device);
#endif // MAME_BUS_HPDIO_HPDIO_H