diff options
| author | 2025-11-18 20:47:15 +0000 | |
|---|---|---|
| committer | 2025-11-18 20:47:15 +0000 | |
| commit | b223b6d110f35c117b239df6bf51e8ec4faa0ffe (patch) | |
| tree | d7d7575b831c0105478461066610046ebad99b37 | |
| parent | 01e433d5f45f13dd7ce95dac06e3016727265057 (diff) | |
machine/82c100.cpp: New 82C100 IBM PS/2 Model 30 and Super XT device.
machine/82c606.cpp: New 82C606 CHIPSpak Multifunction Controller device.
machine/psion_asic7.cpp: New Psion ASIC7 device.
| -rw-r--r-- | scripts/src/machine.lua | 27 | ||||
| -rw-r--r-- | src/devices/machine/82c100.cpp | 434 | ||||
| -rw-r--r-- | src/devices/machine/82c100.h | 146 | ||||
| -rw-r--r-- | src/devices/machine/82c606.cpp | 311 | ||||
| -rw-r--r-- | src/devices/machine/82c606.h | 105 | ||||
| -rw-r--r-- | src/devices/machine/psion_asic7.cpp | 175 | ||||
| -rw-r--r-- | src/devices/machine/psion_asic7.h | 72 |
7 files changed, 1270 insertions, 0 deletions
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 4440d44b95f..adc663e9236 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -631,6 +631,30 @@ end --------------------------------------------------- -- +--@src/devices/machine/82c100.h,MACHINES["82C100"] = true +--------------------------------------------------- + +if (MACHINES["82C100"]~=null) then + files { + MAME_DIR .. "src/devices/machine/82c100.cpp", + MAME_DIR .. "src/devices/machine/82c100.h", + } +end + +--------------------------------------------------- +-- +--@src/devices/machine/82c606.h,MACHINES["82C606"] = true +--------------------------------------------------- + +if (MACHINES["82C606"]~=null) then + files { + MAME_DIR .. "src/devices/machine/82c606.cpp", + MAME_DIR .. "src/devices/machine/82c606.h", + } +end + +--------------------------------------------------- +-- --@src/devices/machine/adc0804.h,MACHINES["ADC0804"] = true --------------------------------------------------- @@ -2954,6 +2978,7 @@ end --@src/devices/machine/psion_asic3.h,MACHINES["PSION_ASIC"] = true --@src/devices/machine/psion_asic4.h,MACHINES["PSION_ASIC"] = true --@src/devices/machine/psion_asic5.h,MACHINES["PSION_ASIC"] = true +--@src/devices/machine/psion_asic7.h,MACHINES["PSION_ASIC"] = true --@src/devices/machine/psion_asic9.h,MACHINES["PSION_ASIC"] = true --------------------------------------------------- @@ -2969,6 +2994,8 @@ if (MACHINES["PSION_ASIC"]~=null) then MAME_DIR .. "src/devices/machine/psion_asic4.h", MAME_DIR .. "src/devices/machine/psion_asic5.cpp", MAME_DIR .. "src/devices/machine/psion_asic5.h", + MAME_DIR .. "src/devices/machine/psion_asic7.cpp", + MAME_DIR .. "src/devices/machine/psion_asic7.h", MAME_DIR .. "src/devices/machine/psion_asic9.cpp", MAME_DIR .. "src/devices/machine/psion_asic9.h", } diff --git a/src/devices/machine/82c100.cpp b/src/devices/machine/82c100.cpp new file mode 100644 index 00000000000..f88ef8bda47 --- /dev/null +++ b/src/devices/machine/82c100.cpp @@ -0,0 +1,434 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + Chips 82C100 IBM PS/2 Model 30 and Super XT + + TODO: + - EMS Page Registers + - Keyboard NMI's maybe have issues + +**********************************************************************/ + +#include "emu.h" +#include "82c100.h" + +#include "multibyte.h" + + +#define VERBOSE 0 +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + + +DEFINE_DEVICE_TYPE(F82C100, f82c100_device, "82c100", "82C100 PS/2 Model 30 and Super XT") + + +f82c100_device::f82c100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, F82C100, tag, owner, clock) + , m_maincpu(*this, finder_base::DUMMY_TAG) + , m_dma8237(*this, "dma8237") + , m_pic8259(*this, "pic8259") + , m_pit8254(*this, "pit8254") + , m_ppi8255(*this, "ppi8255") + , m_intr_callback(*this) + , m_nmi_callback(*this) + , m_in_memr_callback(*this, 0) + , m_out_memw_callback(*this) + , m_in_ior_callback(*this, 0) + , m_out_iow_callback(*this) + , m_out_dack_callback(*this) + , m_tc_callback(*this) + , m_spkdata_callback(*this) + , m_clock2(0) +{ +} + + +void f82c100_device::map(address_map &map) +{ + map(0x0000, 0x000f).rw(m_dma8237, FUNC(am9517a_device::read), FUNC(am9517a_device::write)); + map(0x0020, 0x0021).rw(m_pic8259, FUNC(pic8259_device::read), FUNC(pic8259_device::write)); + map(0x0022, 0x0023).rw(FUNC(f82c100_device::config_r), FUNC(f82c100_device::config_w)); + map(0x0040, 0x0043).rw(m_pit8254, FUNC(pit8254_device::read), FUNC(pit8254_device::write)); + map(0x0060, 0x0063).rw(m_ppi8255, FUNC(i8255_device::read), FUNC(i8255_device::write)); + map(0x0072, 0x0072).rw(FUNC(f82c100_device::nmi_control_r), FUNC(f82c100_device::nmi_control_w)); + map(0x007e, 0x007e).rw(FUNC(f82c100_device::nmi_status_r), FUNC(f82c100_device::nmi_status_w)); + map(0x007f, 0x007f).rw(FUNC(f82c100_device::pwr_control_r), FUNC(f82c100_device::pwr_control_w)); + map(0x0080, 0x0083).nopr().w(FUNC(f82c100_device::dma_page_w)); + map(0x00a0, 0x00af).w(FUNC(f82c100_device::nmi_control_w)); +} + + +void f82c100_device::device_add_mconfig(machine_config &config) +{ + AM9517A(config, m_dma8237, clock() / 2); + m_dma8237->out_hreq_callback().set(m_dma8237, FUNC(am9517a_device::hack_w)); + m_dma8237->out_eop_callback().set([this](int state) { m_tc_callback(state); }); + m_dma8237->in_memr_callback().set([this](offs_t offset) { return m_in_memr_callback((m_dma_page[m_dma_channel] << 16) + offset); }); + m_dma8237->out_memw_callback().set([this](offs_t offset, u8 data) { m_out_memw_callback((m_dma_page[m_dma_channel] << 16) + offset, data); }); + m_dma8237->in_ior_callback<0>().set([this]() { return m_in_ior_callback[0](); }); + m_dma8237->in_ior_callback<1>().set([this]() { return m_in_ior_callback[1](); }); + m_dma8237->in_ior_callback<2>().set([this]() { return m_in_ior_callback[2](); }); + m_dma8237->in_ior_callback<3>().set([this]() { return m_in_ior_callback[3](); }); + m_dma8237->out_iow_callback<0>().set([this](uint8_t data) { m_out_iow_callback[0](data); }); + m_dma8237->out_iow_callback<1>().set([this](uint8_t data) { m_out_iow_callback[1](data); }); + m_dma8237->out_iow_callback<2>().set([this](uint8_t data) { m_out_iow_callback[2](data); }); + m_dma8237->out_iow_callback<3>().set([this](uint8_t data) { m_out_iow_callback[3](data); }); + m_dma8237->out_dack_callback<0>().set([this](int state) { set_dack(0, state); }); + m_dma8237->out_dack_callback<1>().set([this](int state) { set_dack(1, state); }); + m_dma8237->out_dack_callback<2>().set([this](int state) { set_dack(2, state); }); + m_dma8237->out_dack_callback<3>().set([this](int state) { set_dack(3, state); }); + + PIC8259(config, m_pic8259); + m_pic8259->out_int_callback().set([this](int state) { m_intr_callback(state); }); + + PIT8254(config, m_pit8254); + m_pit8254->set_clk<0>(clock() / 12.0); + m_pit8254->out_handler<0>().set(m_pic8259, FUNC(pic8259_device::ir0_w)); + m_pit8254->set_clk<2>(clock() / 12.0); + m_pit8254->out_handler<2>().set(FUNC(f82c100_device::pit8253_out2_changed)); + + I8255A(config, m_ppi8255); + m_ppi8255->in_pa_callback().set(FUNC(f82c100_device::ppi_porta_r)); + m_ppi8255->out_pa_callback().set([this](u8 data) { logerror("POST %d\n", data); }); + m_ppi8255->out_pb_callback().set(FUNC(f82c100_device::ppi_portb_w)); + m_ppi8255->in_pc_callback().set(FUNC(f82c100_device::ppi_portc_r)); +} + + +void f82c100_device::device_start() +{ + m_maincpu->space(AS_PROGRAM).install_read_tap(0x08, 0x0b, "nmi_vector", [this](offs_t offset, u16 &data, u16 mem_mask) + { + // Substitute NMI vector + if (BIT(m_cfg_regs[0x4b], 6)) + { + data = get_u16le(&m_cfg_regs[0x3c + offset]); // Index 44H - 47H + } + }); + + save_item(NAME(m_cfg_regs)); + save_item(NAME(m_cfg_indx)); + save_item(NAME(m_nmi_enable)); + save_item(NAME(m_nmi_status)); + save_item(NAME(m_pwr_control)); + save_item(NAME(m_nmi_control)); + save_item(NAME(m_dma_page)); + save_item(NAME(m_dma_channel)); + save_item(NAME(m_ppi_portb)); + save_item(NAME(m_scan_code)); +} + +void f82c100_device::device_reset() +{ + for (int i = 0; i < 256; i++) + m_cfg_regs[i] = 0; + + m_cfg_regs[0x40] = 0x01; + m_cfg_regs[0x43] = 0x30; + m_cfg_regs[0x48] = 0x01; + + m_cfg_indx = 0; + + m_nmi_enable = true; + m_nmi_status = 0; + m_pwr_control = 0; + m_nmi_control = 0; + + for (int i = 0; i < 4; i++) + m_dma_page[i] = 0; + m_dma_channel = 0; + + m_spkdata = 0; + m_pit_out2 = 1; + + // keyboard interface + m_kbclklo = 0; + m_kbclk = 1; + m_kbdata = 0; +} + + +//************************************************************************** +// READ/WRITE HANDLERS +//************************************************************************** + +u8 f82c100_device::config_r(offs_t offset) +{ + u8 data = 0x00; + + switch (offset & 1) + { + case 0: + data = m_cfg_indx; + break; + case 1: + data = m_cfg_regs[m_cfg_indx]; + break; + } + + return data; +} + +void f82c100_device::config_w(offs_t offset, u8 data) +{ + switch (offset & 1) + { + case 0: + m_cfg_indx = data; + break; + case 1: + m_cfg_regs[m_cfg_indx] = data; + LOG("CR[%02x] = %02x\n", m_cfg_indx, data); + + if (m_cfg_indx == 0x40) // Clock/Mode Size + { + m_maincpu->set_unscaled_clock(BIT(data, 7) ? m_clock2 / 3 : clock() / 3); + } + break; + } +} + + +void f82c100_device::pit8253_out2_changed(int state) +{ + m_pit_out2 = state; + m_spkdata_callback(m_spkdata & m_pit_out2); +} + +void f82c100_device::set_spkrdata(int state) +{ + m_spkdata = state; + m_spkdata_callback(m_spkdata & m_pit_out2); +} + + +u8 f82c100_device::ppi_porta_r() +{ + // Keyboard Scan Code + return m_scan_code; +} + +void f82c100_device::ppi_portb_w(u8 data) +{ + // b0 TMR2GTSPK - Timer 2 Gate Speaker + // b1 SPKDATA - Speaker Data + // b2 Reserved + // b3 Read High/Low Switches + // b4 nPCKEn - Parity Check Enable + // b5 nIOCHKEN - I/O Channel Check Enable + // b6 nKBCLKLO - Keyboard Clock Low + // b7 nKBEN - Keyboard enable/clear + m_ppi_portb = data; + //logerror("ppi_portb_w: %02x\n", data); + + m_pit8254->write_gate2(BIT(data, 0)); + + set_spkrdata(BIT(data, 1)); + + m_kbclklo = !BIT(data, 6); + + if (BIT(data, 7)) + { + m_scan_code = 0x00; + m_scan_bit = 0; + m_pic8259->ir1_w(CLEAR_LINE); + + if (BIT(m_nmi_control, 6)) + m_nmi_callback(ASSERT_LINE); + } +} + +u8 f82c100_device::ppi_portc_r() +{ + // b0-3 High/Low Switches + // b4 Reserved + // b5 Timer Channel 2 Out + // b6 I/O Channel Check + // b7 RAM Parity Check + u8 data = 0x00; + + if (BIT(m_ppi_portb, 3)) + data |= (m_cfg_regs[0x43] >> 4) & 0x0f; + else + data |= m_cfg_regs[0x43] & 0x0f; + + data |= m_pit_out2 << 5; + + return data; +} + + +void f82c100_device::update_nmi() +{ + //logerror("update_nmi: %d status %02x\n", m_nmi_enable, m_nmi_status); + if (m_nmi_enable && (m_nmi_status != 0x00)) + m_nmi_callback(ASSERT_LINE); + else + m_nmi_callback(CLEAR_LINE); +} + +u8 f82c100_device::nmi_control_r() +{ + // b0 Reserved + // b1 FDC Power Control + // b2 Sleep Clock ON/OFF + // b3 Enable RTC NMI + // b4 Enable Keyboard Data NMI + // b5 Enable Suspend NMI + // b6 Enable Keyboard Clear NMI + // b7 Reserved + return m_nmi_control; +} + +void f82c100_device::nmi_control_w(u8 data) +{ + //logerror("nmi_control_w: %02x\n", data); + m_nmi_control = data; +} + +u8 f82c100_device::nmi_status_r() +{ + // b0 Keyboard Data + // b1 Reserved + // b2 RTC NMI + // b3 Suspend NMI + // b4 Keyboard Clear + // b5 PERR - Parity Error + // b6 IOCHK - I/O Channel Check + // b7 Reserved + return m_nmi_status; +} + +void f82c100_device::nmi_status_w(u8 data) +{ + m_nmi_status = data; + update_nmi(); +} + +u8 f82c100_device::pwr_control_r() +{ + // b0 Reserved + // b1 Request Power Off + // b2 Reserved + // b3 Software Controlled Reset + // b4 Reserved + // b5 Reserved + // b6 External Power + // b7 Low Battery + return m_pwr_control; +} + +void f82c100_device::pwr_control_w(u8 data) +{ + m_pwr_control = data; + + // Request Power Off + if (BIT(data, 1)) + { + m_nmi_status |= 0x08; // set Suspend NMI + update_nmi(); + } +} + +void f82c100_device::nmi_mask_w(u8 data) +{ + // b7 NMI Enable + m_nmi_enable = BIT(data, 7); + + if (!m_nmi_enable) + { + m_nmi_status &= ~0x08; // clear Suspend NMI + m_nmi_status &= ~0x04; // clear RTC NMI + } + update_nmi(); +} + +void f82c100_device::npnmi_w(int state) +{ + // TODO: unknown NMI status mask, maybe 0x02? + + update_nmi(); +} + +void f82c100_device::rtcnmi_w(int state) +{ + if (state && m_nmi_enable) + m_nmi_status |= 0x04; // set RTC NMI + else + m_nmi_status &= ~0x04; // clear RTC NMI + + update_nmi(); +} + +void f82c100_device::pwrnmi_w(int state) +{ + if (state && m_nmi_enable && BIT(m_cfg_regs[0x4b], 5)) + m_nmi_status |= 0x08; // set Suspend NMI + else + m_nmi_status &= ~0x08; // clear Suspend NMI + + update_nmi(); +} + +void f82c100_device::set_dack(u8 channel, int state) +{ + if (!state) m_dma_channel = channel; + + m_out_dack_callback[channel](state); +} + +void f82c100_device::dma_page_w(offs_t offset, u8 data) +{ + switch(offset % 4) + { + case 1: + m_dma_page[2] = data; + break; + case 2: + m_dma_page[3] = data; + break; + case 3: + m_dma_page[0] = m_dma_page[1] = data; + break; + } +} + + +int f82c100_device::kbclk_r() +{ + if (m_kbclklo) + return 0; + else + return 1; // pulled high externally +} + +int f82c100_device::kbdata_r() +{ + if (!BIT(m_ppi_portb, 7)) // nKBEN + return 1; // pulled high externally + else + return 1; +} + +void f82c100_device::kbclk_w(int state) +{ + // TODO: this is crude but functional, implement start bit detection + if (!state && m_kbclk) + { + m_scan_bit++; + m_scan_code = (m_scan_code >> 1) | (m_kbdata << 7); + + if (m_scan_bit == 9) // 8 data bits + start bit + { + m_pic8259->ir1_w(ASSERT_LINE); + } + } + m_kbclk = state; +} + +void f82c100_device::kbdata_w(int state) +{ + m_kbdata = state; +} diff --git a/src/devices/machine/82c100.h b/src/devices/machine/82c100.h new file mode 100644 index 00000000000..425b5a3522a --- /dev/null +++ b/src/devices/machine/82c100.h @@ -0,0 +1,146 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + Chips 82C100 IBM PS/2 Model 30 and Super XT + +**********************************************************************/ + +#ifndef MAME_MACHINE_82C100_H +#define MAME_MACHINE_82C100_H + +#pragma once + +#include "machine/am9517a.h" +#include "machine/i8255.h" +#include "machine/pic8259.h" +#include "machine/pit8253.h" + + +class f82c100_device : public device_t +{ +public: + // construction/destruction + f82c100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + template <typename X> + f82c100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, X &&clock2) + : f82c100_device(mconfig, tag, owner, clock) + { + set_clock2(std::forward<X>(clock2)); + } + + void set_clock2(uint32_t clock) { m_clock2 = clock; } + void set_clock2(const XTAL &xtal) { set_clock2(xtal.value()); } + + void map(address_map &map) ATTR_COLD; + + template <typename T> void set_cpu_tag(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); } + + // cpu interface + auto intr() { return m_intr_callback.bind(); } + auto nmi() { return m_nmi_callback.bind(); } + + // dma and interrupt controller interface + auto memr() { return m_in_memr_callback.bind(); } + auto memw() { return m_out_memw_callback.bind(); } + template <unsigned C> auto ior() { return m_in_ior_callback[C].bind(); } + template <unsigned C> auto iow() { return m_out_iow_callback[C].bind(); } + template <unsigned C> auto dack() { return m_out_dack_callback[C].bind(); } + auto tc() { return m_tc_callback.bind(); } + void irq1_w(int state) { m_pic8259->ir1_w(state); } + void irq2_w(int state) { m_pic8259->ir2_w(state); } + void irq3_w(int state) { m_pic8259->ir3_w(state); } + void irq4_w(int state) { m_pic8259->ir4_w(state); } + void irq5_w(int state) { m_pic8259->ir5_w(state); } + void irq6_w(int state) { m_pic8259->ir6_w(state); } + void irq7_w(int state) { m_pic8259->ir7_w(state); } + void drq1_w(int state) { m_dma8237->dreq1_w(state); } + void drq2_w(int state) { m_dma8237->dreq2_w(state); } + void drq3_w(int state) { m_dma8237->dreq3_w(state); } + void npnmi_w(int state); + void rtcnmi_w(int state); + void pwrnmi_w(int state); + + IRQ_CALLBACK_MEMBER(inta_cb) { return m_pic8259->acknowledge(); } + + // keyboard and speaker interface + auto spkdata() { return m_spkdata_callback.bind(); } + void kbclk_w(int state); + void kbdata_w(int state); + int kbclk_r(); + int kbdata_r(); + +protected: + // device_t overrides + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + +private: + u8 config_r(offs_t offset); + void config_w(offs_t offset, u8 data); + + void pit8253_out2_changed(int state); + void set_spkrdata(int state); + + u8 ppi_porta_r(); + void ppi_portb_w(u8 data); + u8 ppi_portc_r(); + + void update_nmi(); + + u8 nmi_control_r(); + void nmi_control_w(u8 data); + u8 nmi_status_r(); + void nmi_status_w(u8 data); + u8 pwr_control_r(); + void pwr_control_w(u8 data); + void nmi_mask_w(u8 data); + void set_dack(u8 channel, int state); + void dma_page_w(offs_t offset, u8 data); + + required_device<cpu_device> m_maincpu; + required_device<am9517a_device> m_dma8237; + required_device<pic8259_device> m_pic8259; + required_device<pit8254_device> m_pit8254; + required_device<i8255_device> m_ppi8255; + + devcb_write_line m_intr_callback; + devcb_write_line m_nmi_callback; + + devcb_read8 m_in_memr_callback; + devcb_write8 m_out_memw_callback; + devcb_read8::array<4> m_in_ior_callback; + devcb_write8::array<4> m_out_iow_callback; + devcb_write_line::array<4> m_out_dack_callback; + devcb_write_line m_tc_callback; + devcb_write_line m_spkdata_callback; + + u32 m_clock2; + + u8 m_cfg_regs[256] { 0x00 }; + u8 m_cfg_indx; + + u8 m_ppi_portb; + int m_pit_out2; + int m_spkdata; + + bool m_nmi_enable; + u8 m_nmi_control; + u8 m_nmi_status; + u8 m_pwr_control; + u8 m_dma_page[4]; + u8 m_dma_channel; + + int m_kbclklo; + int m_kbclk; + int m_kbdata; + int m_scan_bit; + u8 m_scan_code; +}; + + +DECLARE_DEVICE_TYPE(F82C100, f82c100_device) + +#endif // MAME_MACHINE_82C100_H diff --git a/src/devices/machine/82c606.cpp b/src/devices/machine/82c606.cpp new file mode 100644 index 00000000000..855e3ca4088 --- /dev/null +++ b/src/devices/machine/82c606.cpp @@ -0,0 +1,311 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + Chips 82C606 CHIPSpak Multifunction Controller + +**********************************************************************/ + +#include "emu.h" +#include "82c606.h" + + +#define VERBOSE 0 +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + + +DEFINE_DEVICE_TYPE(P82C606, p82c606_device, "82c606", "82C606 CHIPSpak Multifunction Controller") + + +p82c606_device::p82c606_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, P82C606, tag, owner, clock) + , m_maincpu(*this, finder_base::DUMMY_TAG) + , m_rtc(*this, "rtc") + , m_cmos_ram(*this, "cmos_ram", 0x40, ENDIANNESS_LITTLE) + , m_nvram(*this, "nvram") + , m_lpt(*this, "parallel") + , m_serial(*this, "serial%u", 1U) + , m_irq3_callback(*this) + , m_irq4_callback(*this) + , m_irq5_callback(*this) + , m_irq7_callback(*this) + , m_txd1_callback(*this) + , m_dtr1_callback(*this) + , m_rts1_callback(*this) + , m_txd2_callback(*this) + , m_dtr2_callback(*this) + , m_rts2_callback(*this) +{ +} + + +void p82c606_device::device_add_mconfig(machine_config &config) +{ + // serial ports + NS16450(config, m_serial[0], clock()); + m_serial[0]->out_int_callback().set(FUNC(p82c606_device::int_select<S1>)); + m_serial[0]->out_tx_callback().set([this](int state) { m_txd1_callback(state); }); + m_serial[0]->out_dtr_callback().set([this](int state) { m_dtr1_callback(state); }); + m_serial[0]->out_rts_callback().set([this](int state) { m_rts1_callback(state); }); + + NS16450(config, m_serial[1], clock()); + m_serial[1]->out_int_callback().set(FUNC(p82c606_device::int_select<S2>)); + m_serial[1]->out_tx_callback().set([this](int state) { m_txd2_callback(state); }); + m_serial[1]->out_dtr_callback().set([this](int state) { m_dtr2_callback(state); }); + m_serial[1]->out_rts_callback().set([this](int state) { m_rts2_callback(state); }); + + // parallel port + PC_LPT(config, m_lpt); + m_lpt->irq_handler().set(FUNC(p82c606_device::int_select<PP>)); + + // rtc + MC146818(config, m_rtc, 32.768_kHz_XTAL); + m_rtc->irq().set(FUNC(p82c606_device::int_select<RC>)); + m_rtc->set_binary(true); + NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_0); +} + + +void p82c606_device::device_start() +{ + address_space &io_space = m_maincpu->space(AS_IO); + + // CHIPSpak configuration + io_space.install_write_tap(0x2fa, 0x2fb, 0x100, "chipspak6", [this](offs_t offset, u16 &data, u16 mem_mask) { chipspak_w(offset, data & 0xff); }); + + // register defaults + const u8 cfg_regs_defaults[] = { 0x00, 0x00, 0x00, 0xb0, 0xfe, 0xbe, 0x9e, 0x80, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + for (int i = 0; i < std::size(cfg_regs_defaults); i++) + { + m_cfg_regs[i] = cfg_regs_defaults[i]; + } + + m_nvram->set_base(m_cmos_ram, 0x40); + + save_item(NAME(m_cmos_addr)); + save_item(NAME(m_cfg_regs)); + save_item(NAME(m_cfg_indx)); + save_item(NAME(m_cfg_state)); +} + +void p82c606_device::device_reset() +{ +} + + +void p82c606_device::chipspak_w(offs_t offset, u8 data) +{ + LOG("chipspak_w: %04x %02x\n", offset, data); + + address_space &io_space = m_maincpu->space(AS_IO); + + // configuration sequence + if (m_cfg_state == 0 && offset == 0x2fa) + { + m_cfg_key = data; + m_cfg_state++; + } + else if (m_cfg_state == 1 && offset == 0x3fa && data == (u8)(~m_cfg_key)) + { + m_cfg_state++; + } + else if (m_cfg_state == 2 && offset == 0x3fa && data == 0x36) // part number (ASCII 6) + { + m_cfg_state++; + } + else if (m_cfg_state == 3 && offset == 0x3fa) + { + m_cfg_cri = data << 2; + m_cfg_state++; + } + else if (m_cfg_state == 4 && offset == 0x2fa && data == (u8)(~m_cfg_cri >> 2)) + { + m_cfg_state++; + m_cfg_regs[0x0f] = m_cfg_cri >> 2; // Config Addr + + LOG("CFG -- mode on -- CRI %04x\n", m_cfg_cri); + + // install the CRI and CAP ports + io_space.install_readwrite_handler(m_cfg_cri, m_cfg_cri + 1, emu::rw_delegate(*this, FUNC(p82c606_device::cfg_r)), emu::rw_delegate(*this, FUNC(p82c606_device::cfg_w))); + } + else + { + m_cfg_state = 0; + } +} + + +u8 p82c606_device::cfg_r(offs_t offset, u8 mem_mask) +{ + u8 data = 0x00; + + switch (offset & 1) + { + case 0: // CRI + data = m_cfg_indx; + break; + + case 1: // CAP + data = m_cfg_regs[m_cfg_indx]; + LOG("CR[%02x] => %02x\n", m_cfg_indx, data); + } + + return data; +} + +void p82c606_device::cfg_w(offs_t offset, u8 data, u8 mem_mask) +{ + address_space &io_space = m_maincpu->space(AS_IO); + + switch (offset & 1) + { + case 0: // CRI + m_cfg_indx = data & 0x0f; + break; + + case 1: // CAP + if (m_cfg_indx != 0x0f) + m_cfg_regs[m_cfg_indx] = data; + + switch (m_cfg_indx) + { + case 0x00: // Enable + LOG("CR[%02x] <= %02x\n", m_cfg_indx, data); + LOG("GP %s\n", BIT(data, GP) ? "enabled" : "disabled"); + LOG("S1 %s\n", BIT(data, S1) ? "enabled" : "disabled"); + LOG("S2 %s\n", BIT(data, S2) ? "enabled" : "disabled"); + LOG("PP %s\n", BIT(data, PP) ? "enabled" : "disabled"); + LOG("RC %s\n", BIT(data, RC) ? "enabled" : "disabled"); + break; + + case 0x01: // Configuration + LOG("CR[%02x] <= %02x\n", m_cfg_indx, data); + break; + + case 0x02: // Ext Baud Rate Select + LOG("CR[%02x] <= %02x\n", m_cfg_indx, data); + break; + + case 0x03: // RTC Port Base Address + LOG("CR[%02x] <= %02x RC address %04x\n", m_cfg_indx, data, data << 2); + break; + + case 0x04: // UART1 Port Base Address + LOG("CR[%02x] <= %02x S1 address %04x\n", m_cfg_indx, data, (data & 0xfe) << 2); + break; + + case 0x05: // UART2 Port Base Address + LOG("CR[%02x] <= %02x S2 address %04x\n", m_cfg_indx, data, (data & 0xfe) << 2); + break; + + case 0x06: // Parallel Port Base Address + LOG("CR[%02x] <= %02x PP address %04x\n", m_cfg_indx, data, data << 2); + break; + + case 0x07: // Game Port Base Address + LOG("CR[%02x] <= %02x GP address %04x\n", m_cfg_indx, data, data << 2); + break; + + case 0x08: // Interrupt Select + LOG("CR[%02x] <= %02x\n", m_cfg_indx, data); + break; + + case 0x0f: // Config Termination + m_cfg_state = 0; + LOG("CFG -- mode off --\n"); + + // install enabled devices + if (BIT(m_cfg_regs[0], GP)) + { + //offs_t addr = m_cfg_regs[7] << 2; + //io_space.install_readwrite_handler(addr, addr + 1, emu::rw_delegate(*m_serial[0], FUNC(ins8250_device::ins8250_r)), emu::rw_delegate(*m_serial[0], FUNC(ins8250_device::ins8250_w))); + } + if (BIT(m_cfg_regs[0], S1)) + { + offs_t addr = (m_cfg_regs[4] & 0xfe) << 2; + io_space.install_readwrite_handler(addr, addr + 7, emu::rw_delegate(*m_serial[0], FUNC(ins8250_device::ins8250_r)), emu::rw_delegate(*m_serial[0], FUNC(ins8250_device::ins8250_w))); + } + if (BIT(m_cfg_regs[0], S2)) + { + offs_t addr = (m_cfg_regs[5] & 0xfe) << 2; + io_space.install_readwrite_handler(addr, addr + 7, emu::rw_delegate(*m_serial[1], FUNC(ins8250_device::ins8250_r)), emu::rw_delegate(*m_serial[1], FUNC(ins8250_device::ins8250_w))); + } + if (BIT(m_cfg_regs[0], PP)) + { + offs_t addr = m_cfg_regs[6] << 2; + io_space.install_readwrite_handler(addr, addr + 3, emu::rw_delegate(*m_lpt, FUNC(pc_lpt_device::read)), emu::rw_delegate(*m_lpt, FUNC(pc_lpt_device::write))); + } + if (BIT(m_cfg_regs[0], RC)) + { + offs_t addr = m_cfg_regs[3] << 2; + io_space.install_readwrite_handler(addr, addr + 1, emu::rw_delegate(*this, FUNC(p82c606_device::rtc_r)), emu::rw_delegate(*this, FUNC(p82c606_device::rtc_w))); + } + break; + } + } +} + + +u8 p82c606_device::rtc_r(offs_t offset) +{ + u8 data = 0x00; + + if (offset & 1) + { + if (m_cmos_addr & 0x40) + data = m_cmos_ram[m_cmos_addr & 0x3f]; + else + data = m_rtc->read_direct(m_cmos_addr & 0x3f); + } + + return data; +} + +void p82c606_device::rtc_w(offs_t offset, u8 data) +{ + if (offset & 1) + { + if (m_cmos_addr & 0x40) + m_cmos_ram[m_cmos_addr & 0x3f] = data; + else + m_rtc->write_direct(m_cmos_addr & 0x3f, data); + } + else + { + m_cmos_addr = data & 0x7f; + } +} + + +template <unsigned N> +void p82c606_device::int_select(int state) +{ + switch (N) + { + case S1: + if (BIT(m_cfg_regs[8], 6, 2) == 2) m_irq3_callback(state); + if (BIT(m_cfg_regs[8], 4, 2) == 2) m_irq4_callback(state); + if (BIT(m_cfg_regs[8], 2, 2) == 2) m_irq5_callback(state); + break; + + case S2: + if (BIT(m_cfg_regs[8], 6, 2) == 3) m_irq3_callback(state); + if (BIT(m_cfg_regs[8], 4, 2) == 3) m_irq4_callback(state); + if (BIT(m_cfg_regs[8], 0, 2) == 2) m_irq7_callback(state); + break; + + case PP: + if (BIT(m_cfg_regs[8], 2, 2) == 3) m_irq5_callback(state); + if (BIT(m_cfg_regs[8], 0, 2) == 3) m_irq7_callback(state); + break; + + case RC: + if (BIT(m_cfg_regs[8], 6, 2) == 1) m_irq3_callback(state); + if (BIT(m_cfg_regs[8], 4, 2) == 1) m_irq4_callback(state); + if (BIT(m_cfg_regs[8], 2, 2) == 1) m_irq5_callback(state); + if (BIT(m_cfg_regs[8], 0, 2) == 1) m_irq7_callback(state); + break; + } +} diff --git a/src/devices/machine/82c606.h b/src/devices/machine/82c606.h new file mode 100644 index 00000000000..f2ec6a64781 --- /dev/null +++ b/src/devices/machine/82c606.h @@ -0,0 +1,105 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + Chips 82C606 CHIPSpak Multifunction Controller + +**********************************************************************/ + +#ifndef MAME_MACHINE_82C606_H +#define MAME_MACHINE_82C606_H + +#pragma once + +#include "machine/ins8250.h" +#include "machine/mc146818.h" +#include "machine/nvram.h" +#include "machine/pc_lpt.h" + + +class p82c606_device : public device_t +{ +public: + // construction/destruction + p82c606_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + template <typename T> void set_cpu_tag(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); } + + u8 cfg_r(offs_t offset, u8 mem_mask = ~0); + void cfg_w(offs_t offset, u8 data, u8 mem_mask = ~0); + + auto irq3() { return m_irq3_callback.bind(); } + auto irq4() { return m_irq4_callback.bind(); } + auto irq5() { return m_irq5_callback.bind(); } + auto irq7() { return m_irq7_callback.bind(); } + auto txd1() { return m_txd1_callback.bind(); } + auto dtr1() { return m_dtr1_callback.bind(); } + auto rts1() { return m_rts1_callback.bind(); } + auto txd2() { return m_txd2_callback.bind(); } + auto dtr2() { return m_dtr2_callback.bind(); } + auto rts2() { return m_rts2_callback.bind(); } + + // chip pins for uarts + void write_rxd1(int state) { m_serial[0]->rx_w(state); } + void write_dcd1(int state) { m_serial[0]->dcd_w(state); } + void write_dsr1(int state) { m_serial[0]->dsr_w(state); } + void write_ri1(int state) { m_serial[0]->ri_w(state); } + void write_cts1(int state) { m_serial[0]->cts_w(state); } + void write_rxd2(int state) { m_serial[1]->rx_w(state); } + void write_dcd2(int state) { m_serial[1]->dcd_w(state); } + void write_dsr2(int state) { m_serial[1]->dsr_w(state); } + void write_ri2(int state) { m_serial[1]->ri_w(state); } + void write_cts2(int state) { m_serial[1]->cts_w(state); } + +protected: + // device_t overrides + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + +private: + void chipspak_w(offs_t offset, u8 data); + + u8 rtc_r(offs_t offset); + void rtc_w(offs_t offset, u8 data); + + template <unsigned N> void int_select(int state); + + required_device<cpu_device> m_maincpu; + required_device<mc146818_device> m_rtc; + memory_share_creator<u8> m_cmos_ram; + required_device<nvram_device> m_nvram; + required_device<pc_lpt_device> m_lpt; + required_device_array<ns16450_device, 2> m_serial; + + devcb_write_line m_irq3_callback; // UART2 (COM2) + devcb_write_line m_irq4_callback; // UART1 (COM1) + devcb_write_line m_irq5_callback; // Parallel port 2 + devcb_write_line m_irq7_callback; // Parallel port 1 + + devcb_write_line m_txd1_callback; + devcb_write_line m_dtr1_callback; + devcb_write_line m_rts1_callback; + devcb_write_line m_txd2_callback; + devcb_write_line m_dtr2_callback; + devcb_write_line m_rts2_callback; + + static constexpr int GP = 0; // Game Port + static constexpr int S1 = 1; // UART1 + static constexpr int S2 = 2; // UART2 + static constexpr int PP = 3; // Parallel Port + static constexpr int RC = 4; // RTC + + u8 m_cfg_state = 0; + u8 m_cfg_key = 0x00; + u8 m_cfg_regs[16] = { 0 }; + u8 m_cfg_indx = 0x00; + u16 m_cfg_cri = 0x00; + + u8 m_cmos_addr = 0x00; +}; + + +DECLARE_DEVICE_TYPE(P82C606, p82c606_device) + +#endif // MAME_MACHINE_82C606_H diff --git a/src/devices/machine/psion_asic7.cpp b/src/devices/machine/psion_asic7.cpp new file mode 100644 index 00000000000..09eaf82156e --- /dev/null +++ b/src/devices/machine/psion_asic7.cpp @@ -0,0 +1,175 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/****************************************************************************** + + Psion ASIC7 + +******************************************************************************/ + +#include "emu.h" +#include "psion_asic7.h" + + +#define VERBOSE 0 +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + + +DEFINE_DEVICE_TYPE(PSION_ASIC7, psion_asic7_device, "psion_asic7", "Psion ASIC7") + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +psion_asic7_device::psion_asic7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, PSION_ASIC7, tag, owner, clock) + , m_as2rd_callback(*this, 0) + , m_as2wr_callback(*this) + , m_pgsel_callback(*this) + , m_lcdcom_callback(*this) + , m_caps_callback(*this) + , m_numl_callback(*this) + , m_scrl_callback(*this) + , m_batt_callback(*this) + , m_stby_callback(*this) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void psion_asic7_device::device_start() +{ + save_item(NAME(m_a7_control)); + save_item(NAME(m_a7_key_command)); + save_item(NAME(m_a7_access_key)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void psion_asic7_device::device_reset() +{ + m_a7_control = 0x08; // STBY + m_a7_key_command = 0x00; + m_a7_access_key = 0x00; + + m_pgsel_callback(0); +} + + +//************************************************************************** +// READ/WRITE HANDLERS +//************************************************************************** + +uint8_t psion_asic7_device::io_r(offs_t offset, uint8_t mem_mask) +{ + uint8_t data = 0x00; + + if (m_a7_access_key == 0x5aa5) + { + switch (offset & 8) + { + case 0x00: + data = m_as2rd_callback(offset); + break; + + case 0x08: + switch (offset) + { + case 0x08: // System Control + // b0 RamEnable + // b1 PageSel + // b2 MaximEnable + // b3 StandEnable + // b4 CapsLockLcd + // b5 NumLockLcd + // b6 ScrlLockLcd + // b7 BatLowLcd + data = m_a7_control; + LOG("%s io_r: A7Control => %02x\n", machine().describe_context(), data); + break; + + case 0x09: // Keyboard Command Busy Flag + // b0 KeyBusy + data = 0; + LOG("%s io_r: A7KeyStatus => %02x\n", machine().describe_context(), data); + break; + } + } + } + return data; +} + +void psion_asic7_device::io_w(offs_t offset, uint8_t data, uint8_t mem_mask) +{ + if (m_a7_access_key == 0x5aa5 || (offset & 0x0e) == 0x0a) + { + switch (offset & 0x08) + { + case 0x00: + m_as2wr_callback(offset, data); + break; + + case 0x08: + switch (offset) + { + case 0x08: // System Control + // b0 RamEnable + // b1 PageSel + // b2 MaximEnable + // b3 StandEnable + // b4 CapsLockLcd + // b5 NumLockLcd + // b6 ScrlLockLcd + // b7 BatLowLcd + LOG("%s io_w: A7Control <= %02x\n", machine().describe_context(), data); + m_pgsel_callback(BIT(data, 1)); + m_lcdcom_callback(BIT(data, 2)); + if (BIT(data, 3) != BIT(m_a7_control, 3)) + m_stby_callback(BIT(data, 3)); + if (BIT(data, 4) != BIT(m_a7_control, 4)) + m_caps_callback(BIT(data, 4)); + if (BIT(data, 5) != BIT(m_a7_control, 5)) + m_numl_callback(BIT(data, 5)); + if (BIT(data, 6) != BIT(m_a7_control, 6)) + m_scrl_callback(BIT(data, 6)); + if (BIT(data, 7) != BIT(m_a7_control, 7)) + m_batt_callback(BIT(data, 7)); + m_a7_control = data; + break; + + case 0x09: // Keyboard Command + LOG("%s io_w: A7KeyCommand <= %02x\n", machine().describe_context(), data); + m_a7_key_command = data; + break; + + case 0x0a: // Access Key 0 + case 0x0b: // Access Key 1 + LOG("%s io_w: A7KeyAccess%d <= %02x\n", machine().describe_context(), (offset & 1) + 1, data); + switch (offset & 1) + { + case 0: + m_a7_access_key = (m_a7_access_key & 0xff00) | (data << 0); + break; + case 1: + m_a7_access_key = (m_a7_access_key & 0x00ff) | (data << 8); + break; + } + break; + } + } + } +} + +void psion_asic7_device::update_ramen() +{ + if (m_intr_state || m_nmi_state) + m_a7_control |= 0x01; + else + m_a7_control &= ~0x01; +} diff --git a/src/devices/machine/psion_asic7.h b/src/devices/machine/psion_asic7.h new file mode 100644 index 00000000000..84efa3a47f5 --- /dev/null +++ b/src/devices/machine/psion_asic7.h @@ -0,0 +1,72 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/****************************************************************************** + + Psion ASIC7 + +******************************************************************************/ + +#ifndef MAME_MACHINE_PSION_ASIC7_H +#define MAME_MACHINE_PSION_ASIC7_H + +#pragma once + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> psion_asic7_device + +class psion_asic7_device : public device_t +{ +public: + // construction/destruction + psion_asic7_device(const machine_config &mconfig, const char* tag, device_t* owner, uint32_t clock); + + auto as2rd() { return m_as2rd_callback.bind(); } + auto as2wr() { return m_as2wr_callback.bind(); } + auto pgsel() { return m_pgsel_callback.bind(); } + auto lcdcom() { return m_lcdcom_callback.bind(); } + auto caps() { return m_caps_callback.bind(); } + auto numl() { return m_numl_callback.bind(); } + auto scrl() { return m_scrl_callback.bind(); } + auto batt() { return m_batt_callback.bind(); } + auto stby() { return m_stby_callback.bind(); } + + uint8_t io_r(offs_t offset, uint8_t mem_mask); + void io_w(offs_t offset, uint8_t data, uint8_t mem_mask); + + void intr_w(int state) { m_intr_state = state; update_ramen(); }; + void nmi_w(int state) { m_nmi_state = state; update_ramen(); }; + +protected: + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + +private: + void update_ramen(); + + devcb_read8 m_as2rd_callback; + devcb_write8 m_as2wr_callback; + devcb_write_line m_pgsel_callback; + devcb_write_line m_lcdcom_callback; + devcb_write_line m_caps_callback; + devcb_write_line m_numl_callback; + devcb_write_line m_scrl_callback; + devcb_write_line m_batt_callback; + devcb_write_line m_stby_callback; + + uint8_t m_a7_control; + uint8_t m_a7_key_command; + uint16_t m_a7_access_key; + + int m_intr_state; + int m_nmi_state; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(PSION_ASIC7, psion_asic7_device) + +#endif // MAME_MACHINE_PSION_ASIC7_H |
