summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/pc87306.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/pc87306.cpp')
-rw-r--r--src/devices/machine/pc87306.cpp220
1 files changed, 205 insertions, 15 deletions
diff --git a/src/devices/machine/pc87306.cpp b/src/devices/machine/pc87306.cpp
index bc26d2e5c82..8bc2deb00b0 100644
--- a/src/devices/machine/pc87306.cpp
+++ b/src/devices/machine/pc87306.cpp
@@ -1,18 +1,19 @@
// license:BSD-3-Clause
// copyright-holders: Angelo Salese
-/***************************************************************************
+/**************************************************************************************************
National Semiconductor PC87306 Super I/O
TODO:
-- Barely enough to make it surpass POST test 0x05 in misc/odyssey.cpp
+- Barely enough to make it surpass POST test 0x05 in misc/odyssey.cpp;
+- COM1/COM2/LPT1 address and irq select;
-***************************************************************************/
+**************************************************************************************************/
#include "emu.h"
-#include "bus/isa/isa.h"
+#include "pc87306.h"
+
//#include "machine/ds128x.h"
-#include "machine/pc87306.h"
#include "machine/pckeybrd.h"
#define LOG_WARN (1U << 1) // Show warnings
@@ -32,18 +33,19 @@ pc87306_device::pc87306_device(const machine_config &mconfig, const char *tag, d
, m_space_config("superio_config_regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(pc87306_device::config_map), this))
, m_kbdc(*this, "pc_kbdc")
, m_rtc(*this, "rtc")
- //, m_logical_view(*this, "logical_view")
+ , m_pc_com(*this, "uart%d", 0U)
+ , m_pc_lpt(*this, "lpta")
, m_gp20_reset_callback(*this)
, m_gp25_gatea20_callback(*this)
, m_irq1_callback(*this)
, m_irq8_callback(*this)
, m_irq9_callback(*this)
-// , m_txd1_callback(*this)
-// , m_ndtr1_callback(*this)
-// , m_nrts1_callback(*this)
-// , m_txd2_callback(*this)
-// , m_ndtr2_callback(*this)
-// , m_nrts2_callback(*this)
+ , m_txd1_callback(*this)
+ , m_ndtr1_callback(*this)
+ , m_nrts1_callback(*this)
+ , m_txd2_callback(*this)
+ , m_ndtr2_callback(*this)
+ , m_nrts2_callback(*this)
{ }
@@ -89,6 +91,21 @@ void pc87306_device::device_add_mconfig(machine_config &config)
at_keyboard_device &at_keyb(AT_KEYB(config, "at_keyboard", pc_keyboard_device::KEYBOARD_TYPE::AT, 1));
at_keyb.keypress().set(m_kbdc, FUNC(kbdc8042_device::keyboard_w));
+
+ PC_LPT(config, m_pc_lpt);
+ m_pc_lpt->irq_handler().set(FUNC(pc87306_device::irq_parallel_w));
+
+ NS16550(config, m_pc_com[0], XTAL(1'843'200));
+ m_pc_com[0]->out_int_callback().set(FUNC(pc87306_device::irq_serial1_w));
+ m_pc_com[0]->out_tx_callback().set(FUNC(pc87306_device::txd_serial1_w));
+ m_pc_com[0]->out_dtr_callback().set(FUNC(pc87306_device::dtr_serial1_w));
+ m_pc_com[0]->out_rts_callback().set(FUNC(pc87306_device::rts_serial1_w));
+
+ NS16550(config, m_pc_com[1], XTAL(1'843'200));
+ m_pc_com[1]->out_int_callback().set(FUNC(pc87306_device::irq_serial2_w));
+ m_pc_com[1]->out_tx_callback().set(FUNC(pc87306_device::txd_serial2_w));
+ m_pc_com[1]->out_dtr_callback().set(FUNC(pc87306_device::dtr_serial2_w));
+ m_pc_com[1]->out_rts_callback().set(FUNC(pc87306_device::rts_serial2_w));
}
void pc87306_device::remap(int space_id, offs_t start, offs_t end)
@@ -107,6 +124,16 @@ void pc87306_device::remap(int space_id, offs_t start, offs_t end)
if (BIT(m_krr, 3))
m_isa->install_device(0x70, 0x71, read8sm_delegate(*this, FUNC(pc87306_device::rtc_r)), write8sm_delegate(*this, FUNC(pc87306_device::rtc_w)));
+
+ if (BIT(m_fer, 0))
+ m_isa->install_device(0x378, 0x37f, read8sm_delegate(*m_pc_lpt, FUNC(pc_lpt_device::read)), write8sm_delegate(*m_pc_lpt, FUNC(pc_lpt_device::write)));
+
+ if (BIT(m_fer, 1))
+ m_isa->install_device(0x3f8, 0x3ff, read8sm_delegate(*m_pc_com[0], FUNC(ns16450_device::ins8250_r)), write8sm_delegate(*m_pc_com[0], FUNC(ns16450_device::ins8250_w)));
+
+ if (BIT(m_fer, 2))
+ m_isa->install_device(0x2f8, 0x2ff, read8sm_delegate(*m_pc_com[1], FUNC(ns16450_device::ins8250_r)), write8sm_delegate(*m_pc_com[1], FUNC(ns16450_device::ins8250_w)));
+
}
}
@@ -140,8 +167,8 @@ void pc87306_device::write(offs_t offset, u8 data)
void pc87306_device::config_map(address_map &map)
{
-// map(0x00, 0x00) FER Function Enable Register
-// map(0x01, 0x01) FAR Function Address Register
+ map(0x00, 0x00).rw(FUNC(pc87306_device::fer_r), FUNC(pc87306_device::fer_w));
+ map(0x01, 0x01).rw(FUNC(pc87306_device::far_r), FUNC(pc87306_device::far_w));
// map(0x02, 0x02) PTR Power and Test Register
// map(0x03, 0x03) FCR Function Control Register
// map(0x04, 0x04) PCR Printer Control Register
@@ -171,8 +198,49 @@ void pc87306_device::config_map(address_map &map)
// map(0x1c, 0x1c) PNP1 Plug and Play Configuration 1 Register
}
-// [0x05] KRR KBC and RTC Control Register
/*
+ * [0x00] FER Function Enable Register
+ * x--- ---- IDE address select
+ * -x-- ---- IDE i/f enable
+ * --x- ---- FDC address select
+ * ---x ---- (0) x2 floppy drives (1) x4 floppy drives
+ * ---- x--- FDC enable
+ * ---- -x-- UART2 enable
+ * ---- --x- UART1 enable
+ * ---- ---x Parallel Port enable
+ */
+u8 pc87306_device::fer_r(offs_t offset)
+{
+ return m_fer;
+}
+
+void pc87306_device::fer_w(offs_t offset, u8 data)
+{
+ m_fer = data;
+ remap(AS_IO, 0, 0x400);
+}
+
+/*
+ * [0x01] FAR Function Address Register
+ * xxxx ---- UART2 address select
+ * xx-- xx-- UART1 address select
+ * ---- --xx parallel address select
+ */
+u8 pc87306_device::far_r(offs_t offset)
+{
+ return m_far;
+}
+
+void pc87306_device::far_w(offs_t offset, u8 data)
+{
+ m_far = data;
+ remap(AS_IO, 0, 0x400);
+}
+
+
+/*
+ * [0x05] KRR KBC and RTC Control Register
+ *
* x--- ---- KBC clock source select (0) X1 clock (1) SYSCLK
* --x- ---- RAMSREL RTC bank select
* ---- x--- RTC enable bit
@@ -254,6 +322,128 @@ void pc87306_device::irq_mouse_w(int state)
request_irq(12, state ? ASSERT_LINE : CLEAR_LINE);
}
+/*
+ * Serial
+ */
+
+void pc87306_device::irq_serial1_w(int state)
+{
+ if (!(BIT(m_fer, 1)))
+ return;
+ request_irq(3, state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+void pc87306_device::irq_serial2_w(int state)
+{
+ if (!(BIT(m_fer, 2)))
+ return;
+ request_irq(4, state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+void pc87306_device::txd_serial1_w(int state)
+{
+ if (!(BIT(m_fer, 1)))
+ return;
+ m_txd1_callback(state);
+}
+
+void pc87306_device::txd_serial2_w(int state)
+{
+ if (!(BIT(m_fer, 2)))
+ return;
+ m_txd2_callback(state);
+}
+
+void pc87306_device::dtr_serial1_w(int state)
+{
+ if (!(BIT(m_fer, 1)))
+ return;
+ m_ndtr1_callback(state);
+}
+
+void pc87306_device::dtr_serial2_w(int state)
+{
+ if (!(BIT(m_fer, 2)))
+ return;
+ m_ndtr2_callback(state);
+}
+
+void pc87306_device::rts_serial1_w(int state)
+{
+ if (!(BIT(m_fer, 1)))
+ return;
+ m_nrts1_callback(state);
+}
+
+void pc87306_device::rts_serial2_w(int state)
+{
+ if (!(BIT(m_fer, 2)))
+ return;
+ m_nrts2_callback(state);
+}
+
+void pc87306_device::rxd1_w(int state)
+{
+ m_pc_com[0]->rx_w(state);
+}
+
+void pc87306_device::ndcd1_w(int state)
+{
+ m_pc_com[0]->dcd_w(state);
+}
+
+void pc87306_device::ndsr1_w(int state)
+{
+ m_pc_com[0]->dsr_w(state);
+}
+
+void pc87306_device::nri1_w(int state)
+{
+ m_pc_com[0]->ri_w(state);
+}
+
+void pc87306_device::ncts1_w(int state)
+{
+ m_pc_com[0]->cts_w(state);
+}
+
+void pc87306_device::rxd2_w(int state)
+{
+ m_pc_com[1]->rx_w(state);
+}
+
+void pc87306_device::ndcd2_w(int state)
+{
+ m_pc_com[1]->dcd_w(state);
+}
+
+void pc87306_device::ndsr2_w(int state)
+{
+ m_pc_com[1]->dsr_w(state);
+}
+
+void pc87306_device::nri2_w(int state)
+{
+ m_pc_com[1]->ri_w(state);
+}
+
+void pc87306_device::ncts2_w(int state)
+{
+ m_pc_com[1]->cts_w(state);
+}
+
+/*
+ * Parallel
+ */
+
+void pc87306_device::irq_parallel_w(int state)
+{
+ if (!(BIT(m_fer, 0)))
+ return;
+ request_irq(5, state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
void pc87306_device::request_irq(int irq, int state)
{
switch (irq)