diff options
Diffstat (limited to 'src/devices/machine/vt8231_isa.cpp')
-rw-r--r-- | src/devices/machine/vt8231_isa.cpp | 226 |
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); +} |