summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Sven Schnelle <41547105+svenschnelle@users.noreply.github.com>2023-03-25 04:35:18 +0100
committer GitHub <noreply@github.com>2023-03-24 23:35:18 -0400
commit972703281dae54715b2d1f59f7b9fea5b8f5e77a (patch)
tree0b1060c6a2cc25dfcf3b43b7572a6a8e3c29bbc3
parent395d41d0e9e93203c9c49ce4376a735f76de54b7 (diff)
bus/ISA: Added HP82321A BASIC Language coprocessor (#10926)
* emu: add defer_access() method, which is useful for keeping the cpu in a loop restarting the current instruction to emulate waitstates. * add HP82321A Basic Language Coprocessor This adds support for the HP82321A Basic language coprocessor, which emulates a HP9816 system with a 68K cpu. See http://www.hpmuseum.net/display_item.php?hw=681 for more details and software to run on this card.
-rw-r--r--scripts/src/bus.lua1
-rw-r--r--src/devices/bus/isa/hpblp.cpp552
-rw-r--r--src/devices/bus/isa/hpblp.h95
-rw-r--r--src/devices/bus/isa/isa_cards.cpp2
-rw-r--r--src/emu/devcpu.cpp5
-rw-r--r--src/emu/devcpu.h1
6 files changed, 656 insertions, 0 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index 2d083d46f75..d5658030f0b 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -1783,6 +1783,7 @@ if (BUSES["ISA"]~=null) then
MAME_DIR .. "src/devices/bus/isa/lrk330.h",
MAME_DIR .. "src/devices/bus/isa/opus100pm.cpp",
MAME_DIR .. "src/devices/bus/isa/opus100pm.h",
+ MAME_DIR .. "src/devices/bus/isa/hpblp.cpp",
}
end
diff --git a/src/devices/bus/isa/hpblp.cpp b/src/devices/bus/isa/hpblp.cpp
new file mode 100644
index 00000000000..d9571d7ed02
--- /dev/null
+++ b/src/devices/bus/isa/hpblp.cpp
@@ -0,0 +1,552 @@
+// license:BSD-3-Clause
+// copyright-holders:Sven Schnelle
+/***************************************************************************
+
+ HP Basic Language Coprocessor (82321A)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "bus/isa/isa.h"
+#include "bus/ieee488/ieee488.h"
+#include "bus/hp_dio/hp_dio.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/tms9914.h"
+#include "hpblp.h"
+#include "logmacro.h"
+
+#define BLP_TAG "blpcpu"
+#define TMS_TAG "tms9914"
+
+DEFINE_DEVICE_TYPE(HPBLP, isa8_hpblp_device, "hpblp", "HP Basic Language Coprocessor")
+
+static INPUT_PORTS_START(hpblp)
+ PORT_START("BLPPORT")
+ PORT_DIPNAME(3, 0, "IO Address") PORT_DIPLOCATION("SW2:0,1")
+ PORT_DIPSETTING(0, "250h-257h")
+ PORT_DIPSETTING(1, "280h-287h")
+ PORT_DIPSETTING(2, "330h-337h")
+ PORT_DIPSETTING(3, "390h-397h")
+
+ PORT_START("BLPIRQ")
+ PORT_DIPNAME(7, 3, "Interrupt") PORT_DIPLOCATION("SW3:0,1,2")
+ PORT_DIPSETTING(0x0, "IRQ 3")
+ PORT_DIPSETTING(0x1, "IRQ 4")
+ PORT_DIPSETTING(0x2, "IRQ 5")
+ PORT_DIPSETTING(0x3, "IRQ 7")
+ PORT_DIPSETTING(0x4, "IRQ 9")
+INPUT_PORTS_END
+
+ioport_constructor isa8_hpblp_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(hpblp);
+}
+
+
+isa8_hpblp_device::isa8_hpblp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, HPBLP, tag, owner, clock),
+ device_isa8_card_interface(mconfig, *this),
+ m_maincpu(*this, BLP_TAG),
+ m_tms9914(*this, TMS_TAG),
+ m_ieee488(*this, IEEE488_TAG),
+ m_timer_10ms(nullptr),
+ m_reset(false)
+{
+}
+
+void isa8_hpblp_device::device_add_mconfig(machine_config &config)
+{
+ M68000(config, m_maincpu, 16_MHz_XTAL / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &isa8_hpblp_device::m68map);
+
+ TMS9914(config, m_tms9914, XTAL(5'000'000));
+ m_tms9914->eoi_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_eoi_w));
+ m_tms9914->dav_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_dav_w));
+ m_tms9914->nrfd_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_nrfd_w));
+ m_tms9914->ndac_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ndac_w));
+ m_tms9914->ifc_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ifc_w));
+ m_tms9914->srq_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_srq_w));
+ m_tms9914->atn_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_atn_w));
+ m_tms9914->ren_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ren_w));
+ m_tms9914->dio_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_dio_w));
+ m_tms9914->dio_read_cb().set(IEEE488_TAG, FUNC(ieee488_device::dio_r));
+ m_tms9914->dio_read_cb().set(IEEE488_TAG, FUNC(ieee488_device::dio_r));
+ m_tms9914->dio_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_dio_w));
+ m_tms9914->int_write_cb().set(FUNC(isa8_hpblp_device::gpib_irq));
+
+ IEEE488(config, m_ieee488, 0);
+ m_ieee488->eoi_callback().set(m_tms9914, FUNC(tms9914_device::eoi_w));
+ m_ieee488->dav_callback().set(m_tms9914, FUNC(tms9914_device::dav_w));
+ m_ieee488->nrfd_callback().set(m_tms9914, FUNC(tms9914_device::nrfd_w));
+ m_ieee488->ndac_callback().set(m_tms9914, FUNC(tms9914_device::ndac_w));
+ m_ieee488->ifc_callback().set(m_tms9914, FUNC(tms9914_device::ifc_w));
+ m_ieee488->srq_callback().set(m_tms9914, FUNC(tms9914_device::srq_w));
+ m_ieee488->atn_callback().set(m_tms9914, FUNC(tms9914_device::atn_w));
+ m_ieee488->ren_callback().set(m_tms9914, FUNC(tms9914_device::ren_w));
+
+ ieee488_slot_device &slot0(IEEE488_SLOT(config, "ieee0", 0));
+ hp_ieee488_devices(slot0);
+ slot0.set_default_option("hp9122c");
+
+ bus::hp_dio::dio16_device &dio16(DIO16(config, "diobus", 0));
+ dio16.set_program_space(m_maincpu, AS_PROGRAM);
+ m_maincpu->reset_cb().set(dio16, FUNC(bus::hp_dio::dio16_device::reset_in));
+
+ dio16.irq1_out_cb().set_inputline(m_maincpu, M68K_IRQ_1);
+ dio16.irq2_out_cb().set_inputline(m_maincpu, M68K_IRQ_2);
+ dio16.irq3_out_cb().set_inputline(m_maincpu, M68K_IRQ_3);
+ dio16.irq4_out_cb().set_inputline(m_maincpu, M68K_IRQ_4);
+ dio16.irq5_out_cb().set_inputline(m_maincpu, M68K_IRQ_5);
+ dio16.irq6_out_cb().set_inputline(m_maincpu, M68K_IRQ_6);
+ dio16.irq7_out_cb().set_inputline(m_maincpu, M68K_IRQ_7);
+
+ DIO32_SLOT(config, "sl0", 0, "diobus", dio16_cards, nullptr, false);
+ DIO32_SLOT(config, "sl1", 0, "diobus", dio16_cards, nullptr, false);
+
+}
+
+offs_t isa8_hpblp_device::get_bus_address(offs_t offset, uint16_t mem_mask)
+{
+ if (mem_mask == 0xff)
+ offset++;
+ return offset;
+}
+
+bool isa8_hpblp_device::forward_to_host(offs_t offset)
+{
+ if (offset >= 0x200000 && offset <= 0x2fffff)
+ return true;
+ if (offset >= 0x420000 && offset <= 0x42ffff)
+ return true;
+ if (offset >= 0x510000 && offset <= 0x51ffff)
+ return true;
+ if (offset >= 0x520000 && offset <= 0x52ffff)
+ return true;
+ if (offset >= 0x538000 && offset <= 0x53ffff)
+ return true;
+ if (offset >= 0x5f2000 && offset <= 0x5f3fff)
+ return true;
+ if (offset >= 0x690000 && offset <= 0x69ffff)
+ return true;
+ if (offset >= 0x6f0000 && offset <= 0x6fffff)
+ return true;
+ if (offset >= 0x730000 && offset <= 0x73ffff)
+ return true;
+ if (offset >= 0x7a0000 && offset <= 0x7affff)
+ return true;
+ return false;
+}
+
+uint8_t isa8_hpblp_device::status_val(offs_t offset)
+{
+ if (offset >= 0x200000 && offset <= 0x2fffff)
+ return 0x30;
+ if (offset >= 0x512000 && offset <= 0x517fff)
+ return 0x70;
+ if (offset >= 0x51ff00 && offset <= 0x51ffff)
+ return 0x50;
+ if (offset >= 0x538000 && offset <= 0x53ffff)
+ return 0xb0;
+ return 0xd0;
+}
+
+uint16_t isa8_hpblp_device::bus_r(offs_t offset, uint16_t mem_mask)
+{
+ offset <<= 1;
+
+ if (machine().side_effects_disabled())
+ return m_bus_data;
+
+ if (!forward_to_host(offset)) {
+ LOG("%s: %06x -> BERR\n", __func__, offset);
+ m_maincpu->trigger_bus_error();
+ return 0xffff;
+ }
+
+ if (m_ack_buscycle) {
+ m_ack_buscycle = false;
+ m_bus_read = false;
+ m_bus_address = 0;
+ LOG("%s: %06x %04x (%04x)\n", __func__, offset, m_bus_data, mem_mask);
+ return m_bus_data;
+ } else {
+ m_bus_address = get_bus_address(offset, mem_mask);
+ m_bus_mem_mask = mem_mask;
+ m_bus_read = true;
+ }
+ m_maincpu->defer_access();
+ return 0xffff;
+}
+
+void isa8_hpblp_device::bus_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ offset <<= 1;
+
+ if (!forward_to_host(offset)) {
+ LOG("%s: %06x -> BERR\n", __func__, offset);
+ m_maincpu->trigger_bus_error();
+ return;
+ }
+
+ if (m_ack_buscycle) {
+ m_ack_buscycle = false;
+ m_bus_write = false;
+ m_bus_address = 0;
+ return;
+ }
+
+ if (!m_bus_write) {
+ m_bus_address = get_bus_address(offset, mem_mask);
+ m_bus_mem_mask = mem_mask;
+ m_bus_write = true;
+ m_bus_data = data;
+ }
+ m_maincpu->defer_access();
+}
+
+void isa8_hpblp_device::gpib_w(offs_t offset, uint16_t data)
+{
+ if (offset & 0x08) {
+ m_tms9914->write(offset & 0x07, data);
+ return;
+ }
+
+ switch (offset) {
+ case 0:
+ m_tms9914->reset();
+ break;
+
+ case 1:
+ if (data >> 8 == 0)
+ m_gpib_reg1 = 0x84;
+ else if (data >> 8 == 1)
+ m_gpib_reg1 = 0xbf;
+ else
+ m_gpib_reg1 = 0xbe;
+ break;
+ default:
+ break;
+ }
+}
+
+uint16_t isa8_hpblp_device::gpib_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (offset & 0x8)
+ return m_tms9914->read(offset & 0x07);
+
+ switch(offset) {
+ case 0: /* ID */
+ data = 0x31;
+ break;
+ case 1:
+ /* Int control */
+ data = m_gpib_reg1;
+ break;
+ case 2:
+ /* Address */
+ data = 0xbe;
+ break;
+ default:
+ break;
+ }
+ return data;
+}
+
+void isa8_hpblp_device::update_gpib_irq()
+{
+ if ((m_gpib_reg1 & 0x40) && (m_gpib_reg1 & 0x80))
+ m_maincpu->set_input_line(M68K_IRQ_3, ASSERT_LINE);
+ else
+ m_maincpu->set_input_line(M68K_IRQ_3, CLEAR_LINE);
+}
+
+WRITE_LINE_MEMBER(isa8_hpblp_device::gpib_irq)
+{
+ if (state) {
+ m_gpib_reg1 |= 0x40;
+ } else {
+ m_gpib_reg1 &= ~0x40;
+ }
+ update_gpib_irq();
+}
+
+void isa8_hpblp_device::m68map(address_map &map)
+{
+ map(0x000000, 0xffffff).rw(FUNC(isa8_hpblp_device::bus_r), FUNC(isa8_hpblp_device::bus_w));
+ map(0x000000, 0x00ffff).rom().nopw();
+ map(0x470000, 0x47001f).mirror(0x00ffe0).rw(FUNC(isa8_hpblp_device::gpib_r), FUNC(isa8_hpblp_device::gpib_w));
+ map(0xc00000, 0xffffff).ram();
+}
+
+WRITE_LINE_MEMBER(isa8_hpblp_device::hpblp_interrupt)
+{
+ switch(m_irq) {
+ case 0:
+ m_isa->irq3_w(state);
+ break;
+ case 1:
+ m_isa->irq4_w(state);
+ break;
+ case 2:
+ m_isa->irq5_w(state);
+ break;
+ case 3:
+ m_isa->irq7_w(state);
+ break;
+ case 4:
+ m_isa->irq2_w(state);
+ break;
+ default:
+ break;
+ }
+}
+
+uint8_t isa8_hpblp_device::get_bus_address_partial(int shift)
+{
+ offs_t addr;
+
+ // The value read from the bus address registers (isa reg 2,3,4) is
+ // either the address during a waiting 68k bus cycle, or, if the
+ // processor is running the current bus address which might be a data
+ // read/write or program fetch. The DOS software checks whether these
+ // register changes during normal operation. Therefore just invert
+ // the address on every read if the CPU is not waiting for the host.
+
+ if (!m_bus_read && !m_bus_write)
+ m_bus_address ^= 0xffffff;
+
+ addr = m_bus_address;
+ return (addr >> shift) & 0xff;
+}
+
+uint8_t isa8_hpblp_device::addrl_r(offs_t offset)
+{
+ return get_bus_address_partial(0);
+}
+
+uint8_t isa8_hpblp_device::addrm_r(offs_t offset)
+{
+ return get_bus_address_partial(8);
+}
+
+uint8_t isa8_hpblp_device::addrh_r(offs_t offset)
+{
+ return get_bus_address_partial(16);
+}
+
+uint8_t isa8_hpblp_device::datal_r(offs_t offset)
+{
+ return m_bus_data & 0xff;
+}
+
+uint8_t isa8_hpblp_device::datah_r(offs_t offset)
+{
+ return m_bus_data >> 8;
+}
+
+void isa8_hpblp_device::datal_w(offs_t offset, uint8_t data)
+{
+ m_bus_data &= ~0xff;
+ m_bus_data |= data;
+}
+
+void isa8_hpblp_device::datah_w(offs_t offset, uint8_t data)
+{
+ m_bus_data &= ~0xff00;
+ m_bus_data |= (data << 8);
+}
+
+uint8_t isa8_hpblp_device::status_r(offs_t offset)
+{
+ uint8_t ret;
+
+ // bits:
+ // 7-5: type of buscycle (exact encoding unknown)
+ // 4 - INT status
+ // 2 - CPU RW#
+
+ if (m_bus_read || m_bus_write)
+ ret = status_val(m_bus_address);
+ else
+ ret = 0xe4;
+
+ if (m_bus_read)
+ ret |= 0x04;
+
+ if (!m_irq_state)
+ ret |= 0x10;
+ return ret;
+}
+
+void isa8_hpblp_device::irq_w(offs_t offset, uint8_t data)
+{
+ hpblp_interrupt(1);
+}
+
+uint8_t isa8_hpblp_device::reg5_r(offs_t offset)
+{
+ // state bits:
+ // 3-0: OS running
+ // 0: BOOTROM
+ // 1: HPBASIC
+ // 2: PASCAL
+ // 4: Is a 82324A card
+ return m_reg5;
+}
+
+uint8_t isa8_hpblp_device::reg6_r(offs_t offset)
+{
+ return m_reg6;
+}
+
+void isa8_hpblp_device::reg2_w(offs_t offset, uint8_t data)
+{
+ // bit 0 - CPU RESET# line
+ m_reset = data & 1;
+ if (m_reset)
+ device_reset();
+}
+
+// reg 3: force BERR# on current bus cycle
+void isa8_hpblp_device::reg3_w(offs_t offset, uint8_t data)
+{
+ m_ack_buscycle = false;
+ m_bus_read = false;
+ m_bus_write = false;
+ m_maincpu->trigger_bus_error();
+ machine().scheduler().synchronize();
+}
+
+// reg 4: clear pending 10ms timer interrupt to host
+void isa8_hpblp_device::reg4_w(offs_t offset, uint8_t data)
+{
+ hpblp_interrupt(0);
+}
+
+// reg 5: OS status
+void isa8_hpblp_device::reg5_w(offs_t offset, uint8_t data)
+{
+ m_reg5 = data;
+}
+
+// reg 6: seems to be used to trigger interrupts on the 68k.
+// Only seen with keyboard irqs so far.
+void isa8_hpblp_device::reg6_w(offs_t offset, uint8_t data)
+{
+ // bit 2-0: IPL?
+ if (data == 6) {
+ m_maincpu->set_input_line(M68K_IRQ_1, ASSERT_LINE);
+ } else {
+ m_maincpu->set_input_line(M68K_IRQ_1, CLEAR_LINE);
+ }
+ m_reg6 = data;
+}
+
+// reg 7: acknowledge current 68k bus cycle
+void isa8_hpblp_device::reg7_w(address_space &space, offs_t offset, uint8_t data)
+{
+ if (m_reset) {
+ // DOS software write to this reg during reset, so we need to ignore
+ // this write in order to not acknowledge the first bus cycle early
+ return;
+ }
+
+ m_bus_read = false;
+ m_bus_write = false;
+ m_ack_buscycle = true;
+ // It looks like the DOS software assumes that the m68k is always faster starting
+ // the next buscycle than the PC reading the data registers. So it seems they
+ // "optimized" the code to skip checking the bus status registers before accessing
+ // the data registers during a 32 bit instruction. (which will be split into 2x 16
+ // bit bus transactions by 68k. Eat all cycles to make the scheduler switch to 68k
+ // before the x86 CPU can read the registers again.
+ machine().scheduler().synchronize();
+}
+
+void isa8_hpblp_device::isamap(address_map &map)
+{
+ map(0, 0).rw(FUNC(isa8_hpblp_device::datal_r), FUNC(isa8_hpblp_device::datal_w));
+ map(1, 1).rw(FUNC(isa8_hpblp_device::datah_r), FUNC(isa8_hpblp_device::datah_w));
+ map(2, 2).rw(FUNC(isa8_hpblp_device::addrl_r), FUNC(isa8_hpblp_device::reg2_w));
+ map(3, 3).rw(FUNC(isa8_hpblp_device::addrm_r), FUNC(isa8_hpblp_device::reg3_w));
+ map(4, 4).rw(FUNC(isa8_hpblp_device::addrh_r), FUNC(isa8_hpblp_device::reg4_w));
+ map(5, 5).rw(FUNC(isa8_hpblp_device::reg5_r), FUNC(isa8_hpblp_device::reg5_w));
+ map(6, 6).rw(FUNC(isa8_hpblp_device::reg6_r), FUNC(isa8_hpblp_device::reg6_w));
+ map(7, 7).rw(FUNC(isa8_hpblp_device::status_r), FUNC(isa8_hpblp_device::reg7_w));
+}
+
+TIMER_CALLBACK_MEMBER(isa8_hpblp_device::timer10ms)
+{
+ if (m_reg6 & 2)
+ hpblp_interrupt(1);
+ m_timer_10ms->adjust(attotime::from_msec(10));
+}
+
+void isa8_hpblp_device::device_start()
+{
+ set_isa_device();
+ m_installed = false;
+ m_timer_10ms = timer_alloc(FUNC(isa8_hpblp_device::timer10ms), this);
+ m_timer_10ms->adjust(attotime::from_msec(10));
+
+ save_item(NAME(m_bus_address));
+ save_item(NAME(m_bus_mem_mask));
+ save_item(NAME(m_bus_data));
+ save_item(NAME(m_gpib_reg1));
+ save_item(NAME(m_reg5));
+ save_item(NAME(m_reg6));
+ save_item(NAME(m_ack_buscycle));
+ save_item(NAME(m_bus_read));
+ save_item(NAME(m_bus_write));
+ save_item(NAME(m_irq_state));
+ save_item(NAME(m_reset));
+}
+
+void isa8_hpblp_device::device_reset()
+{
+ uint16_t port;
+
+ if (!m_installed) {
+ // MAME doesn't allow reading ioport at device_start
+ m_irq = ioport("BLPIRQ")->read();
+ switch(ioport("BLPPORT")->read()) {
+ case 1:
+ port = 0x280;
+ break;
+ case 2:
+ port = 0x330;
+ break;
+ case 3:
+ port = 0x390;
+ break;
+ default:
+ port = 0x250;
+ break;
+ }
+ m_isa->install_device(port, port + 7, *this, &isa8_hpblp_device::isamap);
+ m_installed = true;
+ }
+
+ m_ack_buscycle = false;
+ m_bus_read = false;
+ m_bus_write = false;
+ m_bus_address = 0;
+ m_reg5 = 0;
+ m_reg6 = 0;
+ m_maincpu->reset();
+ m_gpib_reg1 = 0xbe;
+ m_tms9914->reset();
+}
+
+ROM_START(hpblp)
+ ROM_REGION(0x20000, BLP_TAG, 0)
+ ROM_LOAD16_BYTE( "1818-4576.bin", 0x000000, 0x008000, CRC(8beb6bdb) SHA1(9b620c577aea54841608d0d46f7e8077eef607c6))
+ ROM_LOAD16_BYTE( "1818-4577.bin", 0x000001, 0x008000, CRC(e8a5c071) SHA1(9e13c0ef2aed6565c33795780b7102f2647cf2a0))
+ROM_END
+
+const tiny_rom_entry *isa8_hpblp_device::device_rom_region() const
+{
+ return ROM_NAME(hpblp);
+}
diff --git a/src/devices/bus/isa/hpblp.h b/src/devices/bus/isa/hpblp.h
new file mode 100644
index 00000000000..5cc7f37eadc
--- /dev/null
+++ b/src/devices/bus/isa/hpblp.h
@@ -0,0 +1,95 @@
+// license:BSD-3-Clause
+// copyright-holders:Sven Schnelle
+#ifndef MAME_BUS_ISA_HPBLP_H
+#define MAME_BUS_ISA_HPBLP_H
+
+#pragma once
+
+#include "isa.h"
+#include "bus/hp_dio/hp_dio.h"
+#include "bus/ieee488/ieee488.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/tms9914.h"
+
+class isa8_hpblp_device :
+ public device_t,
+ public device_isa8_card_interface
+{
+public:
+ isa8_hpblp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+private:
+ // ISA part
+ void isamap(address_map &map);
+
+ uint8_t datal_r(offs_t offset);
+ uint8_t datah_r(offs_t offset);
+ uint8_t status_r(offs_t offset);
+ uint8_t addrh_r(offs_t offset);
+ uint8_t addrm_r(offs_t offset);
+ uint8_t addrl_r(offs_t offset);
+ uint8_t reg5_r(offs_t offset);
+ uint8_t reg6_r(offs_t offset);
+
+ void datal_w(offs_t offset, uint8_t data);
+ void datah_w(offs_t offset, uint8_t data);
+ void irq_w(offs_t offset, uint8_t data);
+ void reg2_w(offs_t offset, uint8_t data);
+ void reg3_w(offs_t offset, uint8_t data);
+ void reg4_w(offs_t offset, uint8_t data);
+ void reg5_w(offs_t offset, uint8_t data);
+ void reg6_w(offs_t offset, uint8_t data);
+ void reg7_w(address_space &space, offs_t offset, uint8_t data);
+
+ static uint8_t status_val(offs_t offset);
+
+ DECLARE_WRITE_LINE_MEMBER(hpblp_interrupt);
+ TIMER_CALLBACK_MEMBER(timer10ms);
+
+ // M68000 part
+ DECLARE_WRITE_LINE_MEMBER(gpib_irq);
+ void m68map(address_map &map);
+
+ uint16_t bus_r(offs_t offset, uint16_t mem_mask);
+ void bus_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t gpib_r(offs_t offset);
+ void gpib_w(offs_t offset, uint16_t data);
+
+ static offs_t get_bus_address(offs_t offset, uint16_t mem_mask);
+ uint8_t get_bus_address_partial(int shift);
+
+ static bool forward_to_host(offs_t offset);
+ void update_gpib_irq();
+
+ required_device<m68000_device> m_maincpu;
+ required_device<tms9914_device> m_tms9914;
+ required_device<ieee488_device> m_ieee488;
+ emu_timer *m_timer_10ms;
+
+ uint32_t m_bus_address;
+ uint16_t m_bus_mem_mask;
+ uint16_t m_bus_data;
+ uint8_t m_gpib_reg1;
+ uint8_t m_reg5;
+ uint8_t m_reg6;
+ uint8_t m_irq;
+
+ bool m_installed;
+ bool m_ack_buscycle;
+ bool m_bus_read;
+ bool m_bus_write;
+ bool m_irq_state;
+ bool m_reset;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HPBLP, isa8_hpblp_device)
+
+#endif // MAME_BUS_ISA_HPBLP_H
diff --git a/src/devices/bus/isa/isa_cards.cpp b/src/devices/bus/isa/isa_cards.cpp
index 0b01c16d501..f085f7af70b 100644
--- a/src/devices/bus/isa/isa_cards.cpp
+++ b/src/devices/bus/isa/isa_cards.cpp
@@ -81,6 +81,7 @@
#include "pds.h"
// other
+#include "hpblp.h"
#include "chessmdr.h"
#include "chessmsr.h"
#include "finalchs.h"
@@ -235,4 +236,5 @@ void pc_isa16_cards(device_slot_interface &device)
device.option_add("dc820b", TEKRAM_DC820B); // actually an EISA card
device.option_add("omti8621", ISA16_OMTI8621);
device.option_add("lrk331", LRK331);
+ device.option_add("hpblp", HPBLP);
}
diff --git a/src/emu/devcpu.cpp b/src/emu/devcpu.cpp
index 6dbdd9f9fa1..1554fe5b6fc 100644
--- a/src/emu/devcpu.cpp
+++ b/src/emu/devcpu.cpp
@@ -59,6 +59,11 @@ bool cpu_device::cpu_is_interruptible() const
return false;
}
+void cpu_device::defer_access(void)
+{
+ m_access_to_be_redone = true;
+ *m_icountptr = 0;
+}
bool cpu_device::access_before_time(u64 access_time, u64 current_time)
{
diff --git a/src/emu/devcpu.h b/src/emu/devcpu.h
index 6b077529fb7..8c95fdeb58c 100644
--- a/src/emu/devcpu.h
+++ b/src/emu/devcpu.h
@@ -48,6 +48,7 @@ public:
// The access has already happened, nothing to abort
void access_after_delay(u32 cycles);
+ void defer_access(void);
protected:
// construction/destruction