diff --git a/hash/hp85_rom.xml b/hash/hp85_rom.xml
index 9208db26d8e..370702d02a8 100644
--- a/hash/hp85_rom.xml
+++ b/hash/hp85_rom.xml
@@ -67,4 +67,17 @@
+
+ Mass storage ROM
+ 1979
+ Hewlett-Packard
+
+
+
+
+
+
+
+
+
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index ad79fd7d66c..d838b8bfa2a 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -3162,6 +3162,18 @@ if (BUSES["HP80_OPTROM"]~=null) then
}
end
+---------------------------------------------------
+--
+--@src/devices/bus/hp80_io/hp80_io.h,BUSES["HP80_IO"] = true
+---------------------------------------------------
+
+if (BUSES["HP80_IO"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/bus/hp80_io/hp80_io.cpp",
+ MAME_DIR .. "src/devices/bus/hp80_io/82937.cpp",
+ }
+end
+
---------------------------------------------------
--
--@src/devices/bus/hp9845_io/hp9845_io.h,BUSES["HP9845_IO"] = true
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index f0bb0db561b..d5a30d27756 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -1036,6 +1036,18 @@ if (MACHINES["1MA6"]~=null) then
}
end
+---------------------------------------------------
+--
+--@src/devices/machine/1mb5.h,MACHINES["1MB5"] = true
+---------------------------------------------------
+
+if (MACHINES["1MB5"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/machine/1mb5.cpp",
+ MAME_DIR .. "src/devices/machine/1mb5.h",
+ }
+end
+
---------------------------------------------------
--
--@src/devices/machine/i2cmem.h,MACHINES["I2CMEM"] = true
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 1c1e01aea54..923ef86b342 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -418,6 +418,7 @@ MACHINES["HD63450"] = true
MACHINES["HD64610"] = true
MACHINES["HP_TACO"] = true
MACHINES["1MA6"] = true
+MACHINES["1MB5"] = true
MACHINES["I2CMEM"] = true
MACHINES["I7220"] = true
MACHINES["I80130"] = true
@@ -684,6 +685,7 @@ BUSES["ISA"] = true
BUSES["ISBX"] = true
BUSES["HP_OPTROM"] = true
BUSES["HP80_OPTROM"] = true
+BUSES["HP80_IO"] = true
BUSES["HP9845_IO"] = true
BUSES["KC"] = true
BUSES["LPCI"] = true
diff --git a/src/devices/bus/hp80_io/82937.cpp b/src/devices/bus/hp80_io/82937.cpp
new file mode 100644
index 00000000000..afeb561b8bc
--- /dev/null
+++ b/src/devices/bus/hp80_io/82937.cpp
@@ -0,0 +1,354 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ 82937.cpp
+
+ 82937 module (HPIB interface)
+
+ TODO: Implement Parallel Poll response
+
+ Thanks to Tim Nye & Everett Kaser for dumping the 8049 ROM
+
+ Main reference for this module is:
+ HP 82937-90007, oct 80, HP82937A HP-IB Installation and theory
+ of operation manual
+
+*********************************************************************/
+
+#include "emu.h"
+#include "82937.h"
+#include "coreutil.h"
+
+// Debugging
+#define VERBOSE 0
+#include "logmacro.h"
+
+// Bit manipulation
+namespace {
+ static constexpr unsigned BIT_MASK(unsigned n)
+ {
+ return 1U << n;
+ }
+
+ template void BIT_SET(T& w , unsigned n)
+ {
+ w |= (T)BIT_MASK(n);
+ }
+}
+
+// Bits in U3 (m_latch)
+static constexpr unsigned LATCH_CA_BIT = 5; // Controller Active
+static constexpr unsigned LATCH_TA_BIT = 4; // Talker Active
+static constexpr unsigned LATCH_EN_IFC_INT_BIT = 3; // Enable IFC interrupt
+static constexpr unsigned LATCH_EN_REN_INT_BIT = 2; // Enable REN interrupt
+static constexpr unsigned LATCH_EN_ATN_INT_BIT = 1; // Enable ATN interrupt
+static constexpr unsigned LATCH_EN_NDAC_BIT = 0; // Enable NDAC
+
+// Bits on P1 port of 8049
+static constexpr unsigned P1_IFC_BIT = 7;
+static constexpr unsigned P1_REN_BIT = 6;
+static constexpr unsigned P1_SRQ_BIT = 5;
+static constexpr unsigned P1_ATN_BIT = 4;
+static constexpr unsigned P1_EOI_BIT = 3;
+static constexpr unsigned P1_DAV_BIT = 2;
+static constexpr unsigned P1_NDAC_BIT = 1;
+static constexpr unsigned P1_NRFD_BIT = 0;
+
+hp82937_io_card_device::hp82937_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : hp80_io_card_device(mconfig , HP82937_IO_CARD , tag , owner , clock),
+ m_cpu(*this , "cpu"),
+ m_translator(*this , "xlator"),
+ m_sw1(*this , "sw1"),
+ m_ieee488(*this , IEEE488_TAG)
+{
+}
+
+hp82937_io_card_device::~hp82937_io_card_device()
+{
+}
+
+void hp82937_io_card_device::install_read_write_handlers(address_space& space , uint16_t base_addr)
+{
+ space.install_readwrite_handler(base_addr , base_addr + 1 , READ8_DEVICE_DELEGATE(m_translator , hp_1mb5_device , cpu_r) , WRITE8_DEVICE_DELEGATE(m_translator , hp_1mb5_device , cpu_w));
+}
+
+void hp82937_io_card_device::inten()
+{
+ m_translator->inten();
+}
+
+void hp82937_io_card_device::clear_service()
+{
+ m_translator->clear_service();
+}
+
+WRITE_LINE_MEMBER(hp82937_io_card_device::reset_w)
+{
+ m_cpu->set_input_line(INPUT_LINE_RESET , state);
+ if (state) {
+ // When reset is asserted, clear state
+ device_reset();
+ }
+}
+
+READ_LINE_MEMBER(hp82937_io_card_device::t0_r)
+{
+ return m_iatn;
+}
+
+READ8_MEMBER(hp82937_io_card_device::p1_r)
+{
+ uint8_t res = 0;
+
+ if (BIT(m_sw1->read() , 5)) {
+ // System controller
+ BIT_SET(res , P1_IFC_BIT);
+ BIT_SET(res , P1_REN_BIT);
+ } else {
+ // Not system controller
+ if (m_ieee488->ifc_r()) {
+ BIT_SET(res , P1_IFC_BIT);
+ }
+ if (m_ieee488->ren_r()) {
+ BIT_SET(res , P1_REN_BIT);
+ }
+ }
+ if (!BIT(m_latch , LATCH_CA_BIT) || m_ieee488->srq_r()) {
+ BIT_SET(res , P1_SRQ_BIT);
+ }
+ if (m_iatn) {
+ BIT_SET(res , P1_ATN_BIT);
+ }
+ bool ndac = !BIT(m_latch , LATCH_EN_NDAC_BIT) || m_iatn;
+ if (m_talker_out) {
+ BIT_SET(res , P1_EOI_BIT);
+ BIT_SET(res , P1_DAV_BIT);
+ if (ndac && m_ieee488->ndac_r()) {
+ BIT_SET(res , P1_NDAC_BIT);
+ }
+ if (m_ieee488->nrfd_r()) {
+ BIT_SET(res , P1_NRFD_BIT);
+ }
+ } else {
+ if (m_ieee488->eoi_r()) {
+ BIT_SET(res , P1_EOI_BIT);
+ }
+ if (m_ieee488->dav_r()) {
+ BIT_SET(res , P1_DAV_BIT);
+ }
+ if (ndac) {
+ BIT_SET(res , P1_NDAC_BIT);
+ }
+ BIT_SET(res , P1_NRFD_BIT);
+ }
+
+ return res;
+}
+
+WRITE8_MEMBER(hp82937_io_card_device::p1_w)
+{
+ update_signals();
+ update_data_out();
+}
+
+READ8_MEMBER(hp82937_io_card_device::dio_r)
+{
+ if (m_dio_out) {
+ return 0xff;
+ } else {
+ return m_ieee488->dio_r();
+ }
+}
+
+WRITE8_MEMBER(hp82937_io_card_device::dio_w)
+{
+ update_data_out();
+}
+
+READ8_MEMBER(hp82937_io_card_device::switch_r)
+{
+ return m_sw1->read() | 0xc0;
+}
+
+WRITE8_MEMBER(hp82937_io_card_device::latch_w)
+{
+ LOG("latch=%02x\n" , data);
+ m_latch = data;
+ update_signals();
+ update_data_out();
+}
+
+WRITE_LINE_MEMBER(hp82937_io_card_device::ieee488_ctrl_w)
+{
+ update_signals();
+ update_data_out();
+}
+
+static INPUT_PORTS_START(hp82937_port)
+ MCFG_HP80_IO_SC(7)
+ PORT_START("sw1")
+ PORT_DIPNAME(0x1f , 0x15 , "HPIB address")
+ PORT_DIPLOCATION("S1:7,6,5,4,3")
+ PORT_DIPSETTING(0x00 , "0")
+ PORT_DIPSETTING(0x01 , "1")
+ PORT_DIPSETTING(0x02 , "2")
+ PORT_DIPSETTING(0x03 , "3")
+ PORT_DIPSETTING(0x04 , "4")
+ PORT_DIPSETTING(0x05 , "5")
+ PORT_DIPSETTING(0x06 , "6")
+ PORT_DIPSETTING(0x07 , "7")
+ PORT_DIPSETTING(0x08 , "8")
+ PORT_DIPSETTING(0x09 , "9")
+ PORT_DIPSETTING(0x0a , "10")
+ PORT_DIPSETTING(0x0b , "11")
+ PORT_DIPSETTING(0x0c , "12")
+ PORT_DIPSETTING(0x0d , "13")
+ PORT_DIPSETTING(0x0e , "14")
+ PORT_DIPSETTING(0x0f , "15")
+ PORT_DIPSETTING(0x10 , "16")
+ PORT_DIPSETTING(0x11 , "17")
+ PORT_DIPSETTING(0x12 , "18")
+ PORT_DIPSETTING(0x13 , "19")
+ PORT_DIPSETTING(0x14 , "20")
+ PORT_DIPSETTING(0x15 , "21")
+ PORT_DIPSETTING(0x16 , "22")
+ PORT_DIPSETTING(0x17 , "23")
+ PORT_DIPSETTING(0x18 , "24")
+ PORT_DIPSETTING(0x19 , "25")
+ PORT_DIPSETTING(0x1a , "26")
+ PORT_DIPSETTING(0x1b , "27")
+ PORT_DIPSETTING(0x1c , "28")
+ PORT_DIPSETTING(0x1d , "29")
+ PORT_DIPSETTING(0x1e , "30")
+ PORT_DIPSETTING(0x1f , "31")
+ PORT_DIPNAME(0x20 , 0x20 , "Sys. controller")
+ PORT_DIPLOCATION("S1:2")
+ PORT_DIPSETTING(0x00 , DEF_STR(Off))
+ PORT_DIPSETTING(0x20 , DEF_STR(On))
+INPUT_PORTS_END
+
+ioport_constructor hp82937_io_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(hp82937_port);
+}
+
+void hp82937_io_card_device::device_start()
+{
+ save_item(NAME(m_dio_out));
+ save_item(NAME(m_talker_out));
+ save_item(NAME(m_iatn));
+ save_item(NAME(m_latch));
+}
+
+void hp82937_io_card_device::device_reset()
+{
+ hp80_io_card_device::device_reset();
+
+ m_latch = 0;
+ m_updating = false;
+ update_signals();
+ update_data_out();
+}
+
+void hp82937_io_card_device::update_data_out()
+{
+ m_ieee488->dio_w(m_dio_out ? m_cpu->p2_r(machine().dummy_space() , 0) : 0xff);
+}
+
+void hp82937_io_card_device::update_signals()
+{
+ // Avoid recursive re-enter when writing to IEEE488 signals
+ if (m_updating) {
+ return;
+ }
+ m_updating = true;
+ bool ctrl_active = BIT(m_latch , LATCH_CA_BIT);
+ uint8_t p1 = m_cpu->p1_r(machine().dummy_space() , 0);
+ m_iatn = BIT(p1 , P1_ATN_BIT);
+ if (ctrl_active) {
+ m_ieee488->atn_w(m_iatn);
+ m_ieee488->srq_w(1);
+ } else {
+ m_ieee488->atn_w(1);
+ m_iatn = m_iatn && m_ieee488->atn_r();
+ m_ieee488->srq_w(BIT(p1 , P1_SRQ_BIT));
+ }
+ m_talker_out = (ctrl_active && !m_iatn) || (BIT(m_latch , LATCH_TA_BIT) && m_iatn);
+ if (m_talker_out) {
+ m_ieee488->nrfd_w(1);
+ m_ieee488->dav_w(BIT(p1 , P1_DAV_BIT));
+ m_ieee488->eoi_w(BIT(p1 , P1_EOI_BIT));
+ m_ieee488->ndac_w(1);
+
+ } else {
+ m_ieee488->nrfd_w(BIT(p1 , P1_NRFD_BIT));
+ m_ieee488->dav_w(1);
+ m_ieee488->eoi_w(1);
+ bool ndac = BIT(p1 , P1_NDAC_BIT);
+ if (BIT(m_latch , LATCH_EN_NDAC_BIT) && !m_iatn) {
+ ndac = false;
+ }
+ m_ieee488->ndac_w(ndac);
+ }
+ bool iren = BIT(p1 , P1_REN_BIT);
+ if (BIT(m_sw1->read() , 5)) {
+ // System controller
+ m_ieee488->ren_w(iren);
+ m_ieee488->ifc_w(BIT(p1 , P1_IFC_BIT));
+ } else {
+ // Not system controller
+ m_ieee488->ren_w(1);
+ iren = iren && m_ieee488->ren_r();
+ m_ieee488->ifc_w(1);
+ }
+ bool not_u8_1 = m_iatn || m_ieee488->eoi_r();
+ m_dio_out = not_u8_1 && m_talker_out;
+ bool irq = (BIT(m_latch , LATCH_EN_IFC_INT_BIT) && !m_ieee488->ifc_r()) ||
+ (BIT(m_latch , LATCH_EN_REN_INT_BIT) && iren) ||
+ (BIT(m_latch , LATCH_EN_ATN_INT_BIT) && !m_iatn);
+ m_cpu->set_input_line(MCS48_INPUT_IRQ , irq);
+ m_updating = false;
+}
+
+ROM_START(hp82937)
+ ROM_REGION(0x800 , "cpu" , 0)
+ ROM_LOAD("1820-2437.bin" , 0 , 0x800 , CRC(687d1559) SHA1(44dfc8c3f431cd37a270b094f1db751214009214))
+ROM_END
+
+static ADDRESS_MAP_START(cpu_io_map , AS_IO , 8 , hp82937_io_card_device)
+ ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE(0x00 , 0x01) AM_DEVREADWRITE("xlator" , hp_1mb5_device , uc_r , uc_w)
+ AM_RANGE(0x03 , 0x03) AM_READWRITE(switch_r , latch_w)
+ADDRESS_MAP_END
+
+const tiny_rom_entry *hp82937_io_card_device::device_rom_region() const
+{
+ return ROM_NAME(hp82937);
+}
+
+MACHINE_CONFIG_MEMBER(hp82937_io_card_device::device_add_mconfig)
+ MCFG_CPU_ADD("cpu" , I8049 , XTAL_11MHz)
+ MCFG_CPU_IO_MAP(cpu_io_map)
+ MCFG_MCS48_PORT_T0_IN_CB(READLINE(hp82937_io_card_device , t0_r))
+ MCFG_MCS48_PORT_T1_IN_CB(DEVREADLINE("xlator" , hp_1mb5_device , int_r))
+ MCFG_MCS48_PORT_P1_IN_CB(READ8(hp82937_io_card_device , p1_r))
+ MCFG_MCS48_PORT_P1_OUT_CB(WRITE8(hp82937_io_card_device , p1_w))
+ MCFG_MCS48_PORT_P2_IN_CB(READ8(hp82937_io_card_device , dio_r))
+ MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(hp82937_io_card_device , dio_w))
+
+ MCFG_DEVICE_ADD("xlator" , HP_1MB5 , 0)
+ MCFG_1MB5_IRL_HANDLER(WRITELINE(hp82937_io_card_device , irl_w))
+ MCFG_1MB5_HALT_HANDLER(WRITELINE(hp82937_io_card_device , halt_w))
+ MCFG_1MB5_RESET_HANDLER(WRITELINE(hp82937_io_card_device , reset_w))
+
+ MCFG_IEEE488_SLOT_ADD("ieee_dev" , 0 , hp_ieee488_devices , nullptr)
+ MCFG_IEEE488_BUS_ADD()
+ MCFG_IEEE488_IFC_CALLBACK(WRITELINE(hp82937_io_card_device , ieee488_ctrl_w))
+ MCFG_IEEE488_ATN_CALLBACK(WRITELINE(hp82937_io_card_device , ieee488_ctrl_w))
+ MCFG_IEEE488_REN_CALLBACK(WRITELINE(hp82937_io_card_device , ieee488_ctrl_w))
+ MCFG_IEEE488_EOI_CALLBACK(WRITELINE(hp82937_io_card_device , ieee488_ctrl_w))
+MACHINE_CONFIG_END
+
+// device type definition
+DEFINE_DEVICE_TYPE(HP82937_IO_CARD, hp82937_io_card_device, "hp82937", "HP82937 card")
diff --git a/src/devices/bus/hp80_io/82937.h b/src/devices/bus/hp80_io/82937.h
new file mode 100644
index 00000000000..4402eee8a13
--- /dev/null
+++ b/src/devices/bus/hp80_io/82937.h
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ 82937.h
+
+ 82937 module (HPIB interface)
+
+*********************************************************************/
+
+#ifndef MAME_BUS_HP80_IO_82937_H
+#define MAME_BUS_HP80_IO_82937_H
+
+#pragma once
+
+#include "hp80_io.h"
+#include "cpu/mcs48/mcs48.h"
+#include "bus/ieee488/ieee488.h"
+#include "machine/1mb5.h"
+
+class hp82937_io_card_device : public hp80_io_card_device
+{
+public:
+ // construction/destruction
+ hp82937_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp82937_io_card_device();
+
+ virtual void install_read_write_handlers(address_space& space , uint16_t base_addr) override;
+
+ virtual void inten() override;
+ virtual void clear_service() override;
+
+ DECLARE_WRITE_LINE_MEMBER(reset_w);
+ DECLARE_READ_LINE_MEMBER(t0_r);
+ DECLARE_READ8_MEMBER(p1_r);
+ DECLARE_WRITE8_MEMBER(p1_w);
+ DECLARE_READ8_MEMBER(dio_r);
+ DECLARE_WRITE8_MEMBER(dio_w);
+ DECLARE_READ8_MEMBER(switch_r);
+ DECLARE_WRITE8_MEMBER(latch_w);
+ DECLARE_WRITE_LINE_MEMBER(ieee488_ctrl_w);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device m_cpu;
+ required_device m_translator;
+ required_ioport m_sw1;
+ required_device m_ieee488;
+
+ bool m_dio_out; // U8-4
+ bool m_talker_out; // U7-6
+ bool m_iatn;
+ uint8_t m_latch; // U3
+ bool m_updating;
+
+ void update_data_out();
+ void update_signals();
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HP82937_IO_CARD, hp82937_io_card_device)
+
+#endif // MAME_BUS_HP80_IO_82937_H
diff --git a/src/devices/bus/hp80_io/hp80_io.cpp b/src/devices/bus/hp80_io/hp80_io.cpp
new file mode 100644
index 00000000000..e9ab08bb43c
--- /dev/null
+++ b/src/devices/bus/hp80_io/hp80_io.cpp
@@ -0,0 +1,150 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp80_io.cpp
+
+ I/O bus of HP80 systems
+
+*********************************************************************/
+
+#include "emu.h"
+#include "hp80_io.h"
+
+// Debugging
+#define VERBOSE 0
+#include "logmacro.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(HP80_IO_SLOT, hp80_io_slot_device, "hp80_io_slot", "HP80 I/O Slot")
+
+// +-------------------+
+// |hp80_io_slot_device|
+// +-------------------+
+hp80_io_slot_device::hp80_io_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, HP80_IO_SLOT, tag, owner, clock),
+ device_slot_interface(mconfig, *this),
+ m_irl_cb_func(*this),
+ m_halt_cb_func(*this),
+ m_slot_no(0)
+{
+}
+
+hp80_io_slot_device::~hp80_io_slot_device()
+{
+}
+
+void hp80_io_slot_device::device_start()
+{
+ m_irl_cb_func.resolve_safe();
+ m_halt_cb_func.resolve_safe();
+}
+
+WRITE_LINE_MEMBER(hp80_io_slot_device::irl_w)
+{
+ LOG("irl_w slot %u=%d\n" , m_slot_no , state);
+ m_irl_cb_func(m_slot_no , state , 0xff);
+}
+
+WRITE_LINE_MEMBER(hp80_io_slot_device::halt_w)
+{
+ LOG("halt_w slot %u=%d\n" , m_slot_no , state);
+ m_halt_cb_func(m_slot_no , state , 0xff);
+}
+
+void hp80_io_slot_device::inten()
+{
+ hp80_io_card_device *card = downcast(get_card_device());
+
+ if (card != nullptr) {
+ card->inten();
+ }
+}
+
+void hp80_io_slot_device::clear_service()
+{
+ hp80_io_card_device *card = downcast(get_card_device());
+
+ if (card != nullptr) {
+ card->clear_service();
+ }
+}
+
+void hp80_io_slot_device::install_read_write_handlers(address_space& space)
+{
+ hp80_io_card_device *card = downcast(get_card_device());
+
+ if (card != nullptr) {
+ card->install_read_write_handlers(space , get_base_addr());
+ }
+}
+
+uint8_t hp80_io_slot_device::get_sc() const
+{
+ const hp80_io_card_device *card = downcast(get_card_device());
+
+ if (card != nullptr) {
+ return card->get_sc();
+ } else {
+ return 0;
+ }
+}
+
+uint16_t hp80_io_slot_device::get_base_addr() const
+{
+ const hp80_io_card_device *card = downcast(get_card_device());
+
+ if (card != nullptr) {
+ uint16_t addr = ((uint16_t)(card->get_sc() - HP80_IO_FIRST_SC) << 1) | 0xff50;
+ return addr;
+ } else {
+ return 0;
+ }
+}
+
+// +-------------------+
+// |hp80_io_card_device|
+// +-------------------+
+uint8_t hp80_io_card_device::get_sc() const
+{
+ return m_select_code_port->read() + HP80_IO_FIRST_SC;
+}
+
+void hp80_io_card_device::inten()
+{
+}
+
+void hp80_io_card_device::clear_service()
+{
+}
+
+hp80_io_card_device::hp80_io_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_slot_card_interface(mconfig, *this),
+ m_select_code_port(*this , "SC")
+{
+}
+
+hp80_io_card_device::~hp80_io_card_device()
+{
+}
+
+WRITE_LINE_MEMBER(hp80_io_card_device::irl_w)
+{
+ LOG("irl_w card=%d\n" , state);
+ hp80_io_slot_device *slot = downcast(owner());
+ slot->irl_w(state);
+}
+
+WRITE_LINE_MEMBER(hp80_io_card_device::halt_w)
+{
+ LOG("halt_w card=%d\n" , state);
+ hp80_io_slot_device *slot = downcast(owner());
+ slot->halt_w(state);
+}
+
+#include "82937.h"
+
+SLOT_INTERFACE_START(hp80_io_slot_devices)
+SLOT_INTERFACE("82937_hpib" , HP82937_IO_CARD)
+SLOT_INTERFACE_END
diff --git a/src/devices/bus/hp80_io/hp80_io.h b/src/devices/bus/hp80_io/hp80_io.h
new file mode 100644
index 00000000000..64430f8b6b4
--- /dev/null
+++ b/src/devices/bus/hp80_io/hp80_io.h
@@ -0,0 +1,107 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp80_io.h
+
+ I/O bus of HP80 systems
+
+*********************************************************************/
+
+#ifndef MAME_BUS_HP80_IO_HP80_IO_H
+#define MAME_BUS_HP80_IO_HP80_IO_H
+
+#pragma once
+
+#define MCFG_HP80_IO_SLOT_ADD(_tag , _idx) \
+ MCFG_DEVICE_ADD(_tag, HP80_IO_SLOT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(hp80_io_slot_devices, nullptr, false) \
+ hp80_io_slot_device::set_slot_no(*device , _idx);
+
+#define MCFG_HP80_IO_IRL_CB(_devcb) \
+ devcb = &hp80_io_slot_device::set_irl_cb_func(*device , DEVCB_##_devcb);
+
+#define MCFG_HP80_IO_HALT_CB(_devcb) \
+ devcb = &hp80_io_slot_device::set_halt_cb_func(*device , DEVCB_##_devcb);
+
+#define HP80_IO_FIRST_SC 3 // Lowest SC used by I/O cards
+
+#define MCFG_HP80_IO_SC(_default_sc) \
+ PORT_START("SC") \
+ PORT_CONFNAME(0xf , (_default_sc) - HP80_IO_FIRST_SC , "Select Code") \
+ PORT_CONFSETTING(0 , "3")\
+ PORT_CONFSETTING(1 , "4")\
+ PORT_CONFSETTING(2 , "5")\
+ PORT_CONFSETTING(3 , "6")\
+ PORT_CONFSETTING(4 , "7")\
+ PORT_CONFSETTING(5 , "8")\
+ PORT_CONFSETTING(6 , "9")\
+ PORT_CONFSETTING(7 , "10")
+
+class hp80_io_slot_device : public device_t,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ hp80_io_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp80_io_slot_device();
+
+ // static configuration helpers
+ static void set_slot_no(device_t &device, unsigned slot_no) { downcast(device).m_slot_no = slot_no; }
+
+ // device-level overrides
+ virtual void device_start() override;
+
+ // Callback setups
+ template static devcb_base &set_irl_cb_func(device_t &device, Object &&cb) { return downcast(device).m_irl_cb_func.set_callback(std::forward