From 9e61e6a0189a5ab9bca78a3c7ae9f6bfb6fa44f6 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Mon, 8 Oct 2018 19:53:40 +0200 Subject: [PATCH] hp_dio: add shared IRQ and DMA capabilities --- src/devices/bus/hp_dio/hp_dio.cpp | 180 ++++++++++++++++++++++++++---- src/devices/bus/hp_dio/hp_dio.h | 146 +++++++++++++++++------- 2 files changed, 263 insertions(+), 63 deletions(-) diff --git a/src/devices/bus/hp_dio/hp_dio.cpp b/src/devices/bus/hp_dio/hp_dio.cpp index e487fa5b396..b6a57b006ba 100644 --- a/src/devices/bus/hp_dio/hp_dio.cpp +++ b/src/devices/bus/hp_dio/hp_dio.cpp @@ -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(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); } diff --git a/src/devices/bus/hp_dio/hp_dio.h b/src/devices/bus/hp_dio/hp_dio.h index 9596c15107d..a1738b76f3a 100644 --- a/src/devices/bus/hp_dio/hp_dio.h +++ b/src/devices/bus/hp_dio/hp_dio.h @@ -23,22 +23,8 @@ namespace bus { // INTERFACE CONFIGURATION MACROS //************************************************************************** -#define MCFG_DIO16_CPU(_cputag) \ - downcast(*device).set_cputag(_cputag); -#define MCFG_DIO32_CPU(_cputag) \ - downcast(*device).set_cputag(_cputag); - -#define MCFG_ISA_OUT_IRQ3_CB(_devcb) \ - downcast(*device).set_out_irq3_callback(DEVCB_##_devcb); - -#define MCFG_ISA_OUT_IRQ4_CB(_devcb) \ - downcast(*device).set_out_irq4_callback(DEVCB_##_devcb); - -#define MCFG_ISA_OUT_IRQ5_CB(_devcb) \ - downcast(*device).set_out_irq5_callback(DEVCB_##_devcb); - -#define MCFG_ISA_OUT_IRQ6_CB(_devcb) \ - downcast(*device).set_out_irq6_callback(DEVCB_##_devcb); +#define MCFG_DIO16_CPU(_cputag) downcast(*device).set_cputag(_cputag); +#define MCFG_DIO32_CPU(_cputag) downcast(*device).set_cputag(_cputag); //************************************************************************** // TYPE DEFINITIONS @@ -77,7 +63,6 @@ protected: required_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 void set_cputag(T &&tag) { m_maincpu.set_tag(std::forward(tag)); } - template devcb_base &set_out_irq3_callback(Object &&cb) { return m_out_irq3_cb.set_callback(std::forward(cb)); } - template devcb_base &set_out_irq4_callback(Object &&cb) { return m_out_irq4_cb.set_callback(std::forward(cb)); } - template devcb_base &set_out_irq5_callback(Object &&cb) { return m_out_irq5_cb.set_callback(std::forward(cb)); } - template devcb_base &set_out_irq6_callback(Object &&cb) { return m_out_irq6_cb.set_callback(std::forward(cb)); } + template void set_cputag(T &&tag) { m_maincpu.set_tag(std::forward(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 m_maincpu; + std::list 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