summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/vt8231_isa.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/vt8231_isa.cpp')
-rw-r--r--src/devices/machine/vt8231_isa.cpp226
1 files changed, 226 insertions, 0 deletions
diff --git a/src/devices/machine/vt8231_isa.cpp b/src/devices/machine/vt8231_isa.cpp
new file mode 100644
index 00000000000..9fa17c6144b
--- /dev/null
+++ b/src/devices/machine/vt8231_isa.cpp
@@ -0,0 +1,226 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ VIA VT8231 South Bridge - PCI to ISA Bridge
+
+***************************************************************************/
+
+#include "emu.h"
+#include "vt8231_isa.h"
+
+#define LOG_MAPPING (1U << 1)
+#define LOG_REG (1U << 2)
+#define LOG_SUPERIO (1U << 3)
+
+#define VERBOSE (LOG_GENERAL | LOG_MAPPING | LOG_REG | LOG_SUPERIO)
+#include "logmacro.h"
+
+
+DEFINE_DEVICE_TYPE(VT8231_ISA, vt8231_isa_device, "vt8231_isa", "VT8231 South Bridge - PCI to ISA Bridge")
+
+vt8231_isa_device::vt8231_isa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ pci_device(mconfig, VT8231_ISA, tag, owner, clock),
+ m_com1(*this, "com1"),
+ m_com1_txd_cb(*this), m_com1_dtr_cb(*this), m_com1_rts_cb(*this),
+ m_initialized(false)
+{
+ set_ids(0x11068231, 0x00, 0x060100, 0x00000000);
+}
+
+void vt8231_isa_device::device_add_mconfig(machine_config &config)
+{
+ NS16550(config, m_com1, 1'843'200);
+ m_com1->out_tx_callback().set(FUNC(vt8231_isa_device::com1_txd_w));
+ m_com1->out_dtr_callback().set(FUNC(vt8231_isa_device::com1_dtr_w));
+ m_com1->out_rts_callback().set(FUNC(vt8231_isa_device::com1_rts_w));
+}
+
+void vt8231_isa_device::device_start()
+{
+ pci_device::device_start();
+
+ // register for save states (TODO)
+}
+
+void vt8231_isa_device::device_reset()
+{
+ pci_device::device_reset();
+
+ // setup superio configuration defaults
+ std::fill_n(m_superio_cfg, 0x10, 0x00);
+ m_superio_cfg[0x00] = 0x3c; // device id
+ m_superio_cfg[0x01] = 0x01; // revision
+ m_superio_cfg[0x02] = 0x03; // function select
+ m_superio_cfg[0x04] = 0xfe; // serial port base address (3f8)
+ m_superio_cfg[0x06] = 0xde; // parallel port base address (378)
+ m_superio_cfg[0x07] = 0xfc; // floppy controller base address (3f0)
+
+ m_baud_divisor = 0x01; // 115200 baud
+
+ m_initialized = true;
+ remap_cb();
+}
+
+void vt8231_isa_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
+{
+ if (!m_initialized)
+ return;
+
+ io_space->install_device(0x000, 0x7ff, *this, &vt8231_isa_device::io_map);
+
+ // serial port enabled?
+ if (BIT(m_superio_cfg[0x02], 2) == 1)
+ {
+ uint16_t com1_base = m_superio_cfg[0x04] << 2;
+ LOGMASKED(LOG_MAPPING, "Mapping COM1 from %04x to %04x\n", com1_base, com1_base + 0x0f);
+ io_space->install_device(com1_base, com1_base + 0x0f, *this, &vt8231_isa_device::com1_map);
+ }
+}
+
+void vt8231_isa_device::config_map(address_map &map)
+{
+ pci_device::config_map(map);
+ map(0x50, 0x50).rw(FUNC(vt8231_isa_device::function_control_1_r), FUNC(vt8231_isa_device::function_control_1_w));
+}
+
+uint8_t vt8231_isa_device::function_control_1_r()
+{
+ // 7------- mc97 enable
+ // -6------ ac97 enable
+ // --5----- usb enable
+ // ---4---- usb enable
+ // ----3--- ide enable
+ // -----2-- super io configuration enable
+ // ------1- super io enable
+ // -------0 internal audio enable
+
+ return 0x00;
+}
+
+void vt8231_isa_device::function_control_1_w(uint8_t data)
+{
+ LOGMASKED(LOG_REG, "function_control_1_w: %02x\n", data);
+}
+
+void vt8231_isa_device::io_map(address_map &map)
+{
+ map(0x3f0, 0x3f0).rw(FUNC(vt8231_isa_device::superio_cfg_idx_r), FUNC(vt8231_isa_device::superio_cfg_idx_w));
+ map(0x3f1, 0x3f1).rw(FUNC(vt8231_isa_device::superio_cfg_data_r), FUNC(vt8231_isa_device::superio_cfg_data_w));
+}
+
+
+//**************************************************************************
+// SUPER IO
+//**************************************************************************
+
+uint8_t vt8231_isa_device::superio_cfg_idx_r()
+{
+ return m_superio_cfg_idx;
+}
+
+void vt8231_isa_device::superio_cfg_idx_w(uint8_t data)
+{
+ LOGMASKED(LOG_SUPERIO, "superio_cfg_idx_w: %02x\n", data);
+ m_superio_cfg_idx = data & 0x0f;
+}
+
+uint8_t vt8231_isa_device::superio_cfg_data_r()
+{
+ return m_superio_cfg[m_superio_cfg_idx];
+}
+
+void vt8231_isa_device::superio_cfg_data_w(uint8_t data)
+{
+ LOGMASKED(LOG_SUPERIO, "superio_cfg_data_w: %02x\n", data);
+
+ // first two registers are read-only
+ if (m_superio_cfg_idx < 2)
+ return;
+
+ m_superio_cfg[m_superio_cfg_idx] = data;
+ remap_cb();
+
+ switch (m_superio_cfg_idx)
+ {
+ case 0x02:
+ // 765----- reserved
+ // ---4---- floppy controller enable
+ // ----3--- reserved
+ // -----2-- serial port enable
+ // ------10 parellel port enable/mode
+ LOGMASKED(LOG_SUPERIO, "SuperIO function select\n");
+ break;
+
+ case 0x03:
+ LOGMASKED(LOG_SUPERIO, "SuperIO power down control\n");
+ break;
+
+ case 0x04:
+ LOGMASKED(LOG_SUPERIO, "SuperIO serial port i/o base address\n");
+ break;
+
+ case 0x06:
+ LOGMASKED(LOG_SUPERIO, "SuperIO parallel port i/o base address\n");
+ break;
+
+ case 0x07:
+ LOGMASKED(LOG_SUPERIO, "SuperIO floppy controller base address\n");
+ break;
+
+ case 0x09:
+ LOGMASKED(LOG_SUPERIO, "SuperIO serial port control\n");
+ break;
+
+ case 0x0a:
+ LOGMASKED(LOG_SUPERIO, "SuperIO parallel port control\n");
+ break;
+
+ case 0x0b:
+ LOGMASKED(LOG_SUPERIO, "SuperIO floppy controller control\n");
+ break;
+
+ case 0x0c:
+ LOGMASKED(LOG_SUPERIO, "SuperIO floppy controller drive type\n");
+ break;
+
+ case 0x0e:
+ LOGMASKED(LOG_SUPERIO, "SuperIO test mode a\n");
+ break;
+
+ case 0x0f:
+ LOGMASKED(LOG_SUPERIO, "SuperIO test mode b\n");
+ break;
+
+ default:
+ LOGMASKED(LOG_SUPERIO, "SuperIO reserved register\n");
+ break;
+ }
+}
+
+
+//**************************************************************************
+// SERIAL PORT
+//**************************************************************************
+
+void vt8231_isa_device::com1_map(address_map &map)
+{
+ map(0x00, 0x07).rw("com1", FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w));
+ map(0x08, 0x09).rw(FUNC(vt8231_isa_device::com1_baud_r), FUNC(vt8231_isa_device::com1_baud_w));
+}
+
+uint16_t vt8231_isa_device::com1_baud_r()
+{
+ return m_baud_divisor;
+}
+
+void vt8231_isa_device::com1_baud_w(uint16_t data)
+{
+ logerror("com1_baud_w: %04x\n", data);
+ m_baud_divisor = data;
+
+ // TODO: setting this to 0 might disable it?
+ if (data > 0)
+ m_com1->set_clock_scale(1.0 / data);
+}