diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 148d2b85491..fbf92d44e67 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -920,6 +920,8 @@ if (BUSES["HPDIO"]~=null) then MAME_DIR .. "src/devices/bus/hp_dio/hp98603b.h", MAME_DIR .. "src/devices/bus/hp_dio/hp98620.cpp", MAME_DIR .. "src/devices/bus/hp_dio/hp98620.h", + MAME_DIR .. "src/devices/bus/hp_dio/hp98643.cpp", + MAME_DIR .. "src/devices/bus/hp_dio/hp98643.h", MAME_DIR .. "src/devices/bus/hp_dio/hp98644.cpp", MAME_DIR .. "src/devices/bus/hp_dio/hp98644.h", MAME_DIR .. "src/devices/bus/hp_dio/human_interface.cpp", diff --git a/src/devices/bus/hp_dio/hp98643.cpp b/src/devices/bus/hp_dio/hp98643.cpp new file mode 100644 index 00000000000..1054f4abe95 --- /dev/null +++ b/src/devices/bus/hp_dio/hp98643.cpp @@ -0,0 +1,215 @@ +// license:BSD-3-Clause +// copyright-holders:Sven Schnelle +/*************************************************************************** + + HP98643 LANIC Ethernet card + +***************************************************************************/ + +#include "emu.h" +#include "hp98643.h" +#include "machine/am79c90.h" + +//#define VERBOSE 1 +#include "logmacro.h" + +DEFINE_DEVICE_TYPE_NS(HPDIO_98643, bus::hp_dio, dio16_98643_device, "dio98643", "HP98643A LANIC Ethernet card") + +namespace bus { namespace hp_dio { + +void dio16_98643_device::device_add_mconfig(machine_config &config) +{ + AM7990(config, m_lance, XTAL(20'000'000)); + m_lance->intr_out().set(FUNC(dio16_98643_device::lance_int_w)); + m_lance->dma_out().set(FUNC(dio16_98643_device::lance_dma_out)); + m_lance->dma_in().set(FUNC(dio16_98643_device::lance_dma_in)); +} + +dio16_98643_device::dio16_98643_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + dio16_98643_device(mconfig, HPDIO_98643, tag, owner, clock) +{ +} + +dio16_98643_device::dio16_98643_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_dio16_card_interface(mconfig, *this), + m_lance(*this, "lance"), + m_switches{*this, "switches"} +{ +} + +static INPUT_PORTS_START(hp98643_port) + PORT_START("switches") + PORT_DIPNAME(REG_SWITCHES_REMOTE, 0x00, "Remote") + PORT_DIPSETTING(0x00, DEF_STR(Off)) + PORT_DIPSETTING(REG_SWITCHES_REMOTE, DEF_STR(On)) + + PORT_DIPNAME(REG_SWITCHES_INT_LEVEL_MASK << REG_SWITCHES_INT_LEVEL_SHIFT, 0x02 << REG_SWITCHES_INT_LEVEL_SHIFT, "Interrupt level") + PORT_DIPSETTING(0 << REG_SWITCHES_INT_LEVEL_SHIFT, "3") + PORT_DIPSETTING(1 << REG_SWITCHES_INT_LEVEL_SHIFT, "4") + PORT_DIPSETTING(2 << REG_SWITCHES_INT_LEVEL_SHIFT, "5") + PORT_DIPSETTING(3 << REG_SWITCHES_INT_LEVEL_SHIFT, "6") + + PORT_DIPNAME(REG_SWITCHES_SELECT_CODE_MASK << REG_SWITCHES_SELECT_CODE_SHIFT, 21 << REG_SWITCHES_SELECT_CODE_SHIFT, "Select code") + PORT_DIPSETTING(0 << REG_SWITCHES_SELECT_CODE_SHIFT, "0") + PORT_DIPSETTING(1 << REG_SWITCHES_SELECT_CODE_SHIFT, "1") + PORT_DIPSETTING(2 << REG_SWITCHES_SELECT_CODE_SHIFT, "2") + PORT_DIPSETTING(3 << REG_SWITCHES_SELECT_CODE_SHIFT, "3") + PORT_DIPSETTING(4 << REG_SWITCHES_SELECT_CODE_SHIFT, "4") + PORT_DIPSETTING(5 << REG_SWITCHES_SELECT_CODE_SHIFT, "5") + PORT_DIPSETTING(6 << REG_SWITCHES_SELECT_CODE_SHIFT, "6") + PORT_DIPSETTING(7 << REG_SWITCHES_SELECT_CODE_SHIFT, "7") + PORT_DIPSETTING(8 << REG_SWITCHES_SELECT_CODE_SHIFT, "8") + PORT_DIPSETTING(9 << REG_SWITCHES_SELECT_CODE_SHIFT, "9") + PORT_DIPSETTING(10 << REG_SWITCHES_SELECT_CODE_SHIFT, "10") + PORT_DIPSETTING(11 << REG_SWITCHES_SELECT_CODE_SHIFT, "11") + PORT_DIPSETTING(12 << REG_SWITCHES_SELECT_CODE_SHIFT, "12") + PORT_DIPSETTING(13 << REG_SWITCHES_SELECT_CODE_SHIFT, "13") + PORT_DIPSETTING(14 << REG_SWITCHES_SELECT_CODE_SHIFT, "14") + PORT_DIPSETTING(15 << REG_SWITCHES_SELECT_CODE_SHIFT, "15") + PORT_DIPSETTING(16 << REG_SWITCHES_SELECT_CODE_SHIFT, "16") + PORT_DIPSETTING(17 << REG_SWITCHES_SELECT_CODE_SHIFT, "17") + PORT_DIPSETTING(18 << REG_SWITCHES_SELECT_CODE_SHIFT, "18") + PORT_DIPSETTING(19 << REG_SWITCHES_SELECT_CODE_SHIFT, "19") + PORT_DIPSETTING(20 << REG_SWITCHES_SELECT_CODE_SHIFT, "20") + PORT_DIPSETTING(21 << REG_SWITCHES_SELECT_CODE_SHIFT, "21") + PORT_DIPSETTING(22 << REG_SWITCHES_SELECT_CODE_SHIFT, "22") + PORT_DIPSETTING(23 << REG_SWITCHES_SELECT_CODE_SHIFT, "23") + PORT_DIPSETTING(24 << REG_SWITCHES_SELECT_CODE_SHIFT, "24") + PORT_DIPSETTING(25 << REG_SWITCHES_SELECT_CODE_SHIFT, "25") + PORT_DIPSETTING(26 << REG_SWITCHES_SELECT_CODE_SHIFT, "26") + PORT_DIPSETTING(27 << REG_SWITCHES_SELECT_CODE_SHIFT, "27") + PORT_DIPSETTING(28 << REG_SWITCHES_SELECT_CODE_SHIFT, "28") + PORT_DIPSETTING(29 << REG_SWITCHES_SELECT_CODE_SHIFT, "29") + PORT_DIPSETTING(30 << REG_SWITCHES_SELECT_CODE_SHIFT, "30") + PORT_DIPSETTING(31 << REG_SWITCHES_SELECT_CODE_SHIFT, "31") +INPUT_PORTS_END + +ioport_constructor dio16_98643_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(hp98643_port); +} + +void dio16_98643_device::device_start() +{ + save_item(NAME(m_sc)); + save_item(NAME(m_installed_io)); + save_item(NAME(m_ram)); +} + +void dio16_98643_device::device_reset() +{ + if (!m_installed_io) { + uint8_t code = (m_switches->read() >> REG_SWITCHES_SELECT_CODE_SHIFT) + & REG_SWITCHES_SELECT_CODE_MASK; + + uint32_t baseaddr = 0x600000 + (code << 16); + + program_space()->install_device(baseaddr, baseaddr + 0xffff, + *this, &dio16_98643_device::addrmap); + m_installed_io = true; + } + m_sc = REG_SC_REV; + m_sc |= get_irq_line() << 4; +} + +WRITE_LINE_MEMBER(dio16_98643_device::lance_int_w) +{ + if (state) + m_sc &= ~REG_SC_IP; + else + m_sc |= REG_SC_IP; + update_int(); +} + +WRITE16_MEMBER(dio16_98643_device::sc_w) +{ + LOG("%s: %02x\n", __func__, data); + data &= (REG_SC_LOCK|REG_SC_IE); + m_sc &= ~(REG_SC_LOCK|REG_SC_IE); + + if (data & REG_SC_LOCK) + data |= REG_STATUS_ACK; + + m_sc |= data; + update_int(); +} + +READ16_MEMBER(dio16_98643_device::sc_r) +{ + LOG("%s: %02x\n", __func__, m_sc); + return m_sc; +} + +READ16_MEMBER(dio16_98643_device::id_r) +{ + return (REG_ID | (m_switches->read() & REG_SWITCHES_REMOTE)); +} + +WRITE16_MEMBER(dio16_98643_device::id_w) +{ + reset(); +} +READ16_MEMBER(dio16_98643_device::novram_r) +{ + return m_novram[offset]; +} + +WRITE16_MEMBER(dio16_98643_device::novram_w) +{ + COMBINE_DATA(&m_novram[offset & 0x3f]); +} + +WRITE16_MEMBER(dio16_98643_device::lance_dma_out) +{ + LOG("%s: offset=%04x, data=%d\n", __func__, offset, data); + m_ram[(offset >>1) & 0x1fff] = data; +} + +READ16_MEMBER(dio16_98643_device::lance_dma_in) +{ + uint16_t ret = m_ram[(offset >> 1) & 0x1fff]; + + LOG("%s: offset=%04x data %04x\n", __func__, offset, ret); + return ret; +} + +int dio16_98643_device::get_irq_line() +{ + return (m_switches->read() >> REG_SWITCHES_INT_LEVEL_SHIFT) & REG_SWITCHES_INT_LEVEL_MASK; +} + +void dio16_98643_device::update_int() +{ + const int line = get_irq_line() + 3; + const bool state = (m_sc & (REG_SC_IE|REG_SC_IP)) == (REG_SC_IE|REG_SC_IP); + LOG("%s: line %d, state %d\n", __func__, line, state); + irq3_out(state && line == 3); + irq4_out(state && line == 4); + irq5_out(state && line == 5); + irq6_out(state && line == 6); +} + +void dio16_98643_device::addrmap(address_map &map) +{ + map(0x0000, 0x0001).rw(FUNC(dio16_98643_device::id_r), FUNC(dio16_98643_device::id_w)); + map(0x0002, 0x0003).rw(FUNC(dio16_98643_device::sc_r), FUNC(dio16_98643_device::sc_w)); + map(0x4000, 0x4003).lrw16("lance", + [this](address_space &space, offs_t offset, u16 mem_mask) -> u16 { + m_sc |= REG_STATUS_ACK; + return m_lance->regs_r(space, offset, mem_mask); + }, + [this](address_space &space, offs_t offset, u16 data, u16 mem_mask) { + m_sc |= REG_STATUS_ACK; + return m_lance->regs_w(space, offset, data, mem_mask); + }); + + map(0x8000, 0xbfff).lrw16("lanceram", + [this](offs_t offset) -> u16 { return m_ram[offset]; }, + [this](offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&m_ram[offset]); }); + + map(0xc000, 0xffff).rw(FUNC(dio16_98643_device::novram_r), FUNC(dio16_98643_device::novram_w)); +} + +} // namespace bus::hp_dio +} // namespace bus diff --git a/src/devices/bus/hp_dio/hp98643.h b/src/devices/bus/hp_dio/hp98643.h new file mode 100644 index 00000000000..d2b018c4b57 --- /dev/null +++ b/src/devices/bus/hp_dio/hp98643.h @@ -0,0 +1,92 @@ +// license:BSD-3-Clause +// copyright-holders:Sven Schnelle + +#ifndef MAME_BUS_HPDIO_98643_H +#define MAME_BUS_HPDIO_98643_H + +#pragma once + +#include "hp_dio.h" +#include "machine/am79c90.h" + +namespace bus { namespace hp_dio { + +static constexpr int REG_SWITCHES_REMOTE = 0x80; + +static constexpr int REG_SWITCHES_SELECT_CODE_MASK = 0x1f; +static constexpr int REG_SWITCHES_SELECT_CODE_SHIFT = 0x00; + +static constexpr int REG_SWITCHES_INT_LEVEL_MASK = 0x03; +static constexpr int REG_SWITCHES_INT_LEVEL_SHIFT = 0x05; + +static constexpr uint16_t REG_ID = 0x15; + +static constexpr uint16_t REG_STATUS_ACK = 0x04; + +static constexpr uint16_t REG_SC_REV = 0x01; +static constexpr uint16_t REG_SC_LOCK = 0x08; +static constexpr uint16_t REG_SC_IP = 0x40; +static constexpr uint16_t REG_SC_IE = 0x80; + +class dio16_98643_device : + public device_t, + public device_dio16_card_interface +{ +public: + // construction/destruction + dio16_98643_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + dio16_98643_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + virtual ioport_constructor device_input_ports() const override; + virtual void device_add_mconfig(machine_config &config) override; + +private: + required_device m_lance; + required_ioport m_switches; + + void addrmap(address_map &map); + void update_int(); + int get_irq_line(); + + READ16_MEMBER(sc_r); + WRITE16_MEMBER(sc_w); + READ16_MEMBER(id_r); + WRITE16_MEMBER(id_w); + READ16_MEMBER(novram_r); + WRITE16_MEMBER(novram_w); + + DECLARE_WRITE_LINE_MEMBER(lance_int_w); + DECLARE_WRITE16_MEMBER(lance_dma_out); + DECLARE_READ16_MEMBER(lance_dma_in); + + uint16_t m_novram[32] = { + 0xfff0, 0xfff0, 0xfff0, 0xfff0, + 0xfff0, 0xfff8, 0xfff0, 0xfff0, + 0xfff0, 0xfff9, 0xfff0, 0xfff6, + 0xfffa, 0xfff1, 0xffff, 0xfff1, + 0xfff0, 0xfff0, 0xfff0, 0xfff0, + 0xfff0, 0xfff0, 0xfff0, 0xfff0, + 0xfff0, 0xfff0, 0xfff0, 0xfff0, + 0xfff0, 0xfff0, 0xfffa, 0xfff9, + }; + + std::array m_ram; + + uint16_t m_sc; + bool m_installed_io; +}; + +} // namespace bus::hp_dio +} // namespace bus + +// device type definition +DECLARE_DEVICE_TYPE_NS(HPDIO_98643, bus::hp_dio, dio16_98643_device) + +#endif // MAME_BUS_HPDIO_98643_H diff --git a/src/devices/bus/hp_dio/hp_dio.cpp b/src/devices/bus/hp_dio/hp_dio.cpp index ed553d6ea05..dfa228dc8af 100644 --- a/src/devices/bus/hp_dio/hp_dio.cpp +++ b/src/devices/bus/hp_dio/hp_dio.cpp @@ -15,6 +15,7 @@ #include "hp98603a.h" #include "hp98603b.h" #include "hp98620.h" +#include "hp98643.h" #include "hp98644.h" #include "human_interface.h" @@ -360,6 +361,7 @@ void dio16_cards(device_slot_interface & device) device.option_add("98544", HPDIO_98544); device.option_add("98603a", HPDIO_98603A); device.option_add("98603b", HPDIO_98603B); + device.option_add("98643", HPDIO_98643); device.option_add("98644", HPDIO_98644); device.option_add("human_interface", HPDIO_HUMAN_INTERFACE); } @@ -368,6 +370,6 @@ void dio32_cards(device_slot_interface & device) { dio16_cards(device); device.option_add("98265a", HPDIO_98265A); - device.option_add("98620", HPDIO_98620); device.option_add("98550", HPDIO_98550); + device.option_add("98620", HPDIO_98620); } diff --git a/src/mame/drivers/hp9k_3xx.cpp b/src/mame/drivers/hp9k_3xx.cpp index 4ccf982dd4c..70f05245f5d 100644 --- a/src/mame/drivers/hp9k_3xx.cpp +++ b/src/mame/drivers/hp9k_3xx.cpp @@ -345,8 +345,9 @@ MACHINE_CONFIG_START(hp9k3xx_state::hp9k310) DIO16_SLOT(config, "sl0", 0, "diobus", dio16_cards, "human_interface", false); DIO16_SLOT(config, "sl1", 0, "diobus", dio16_cards, "98544", false); DIO16_SLOT(config, "sl2", 0, "diobus", dio16_cards, "98603b", false); - DIO16_SLOT(config, "sl3", 0, "diobus", dio16_cards, "98644", false); - DIO16_SLOT(config, "sl4", 0, "diobus", dio16_cards, nullptr, false); + DIO32_SLOT(config, "sl3", 0, "diobus", dio32_cards, "98643", false); + DIO16_SLOT(config, "sl4", 0, "diobus", dio16_cards, "98644", false); + DIO16_SLOT(config, "sl5", 0, "diobus", dio16_cards, nullptr, false); MACHINE_CONFIG_END @@ -360,10 +361,11 @@ MACHINE_CONFIG_START(hp9k3xx_state::hp9k320) DIO32_SLOT(config, "sl0", 0, "diobus", dio32_cards, "human_interface", true); DIO32_SLOT(config, "sl1", 0, "diobus", dio32_cards, "98543", false); DIO32_SLOT(config, "sl2", 0, "diobus", dio32_cards, "98603b", false); - DIO32_SLOT(config, "sl3", 0, "diobus", dio32_cards, "98644", false); - DIO32_SLOT(config, "sl4", 0, "diobus", dio32_cards, "98620", false); - DIO32_SLOT(config, "sl5", 0, "diobus", dio32_cards, "98265a", false); - DIO32_SLOT(config, "sl6", 0, "diobus", dio32_cards, nullptr, false); + DIO32_SLOT(config, "sl3", 0, "diobus", dio32_cards, "98643", false); + DIO32_SLOT(config, "sl4", 0, "diobus", dio32_cards, "98644", false); + DIO32_SLOT(config, "sl5", 0, "diobus", dio32_cards, "98620", false); + DIO32_SLOT(config, "sl6", 0, "diobus", dio32_cards, "98265a", false); + DIO32_SLOT(config, "sl7", 0, "diobus", dio32_cards, nullptr, false); MACHINE_CONFIG_END MACHINE_CONFIG_START(hp9k3xx_state::hp9k330)