pegasos2: Initial devices for MV64361 and VT8231

Enough to get data from the initial bootloader to the serial console.
This commit is contained in:
Dirk Best 2023-04-03 13:08:38 +02:00
parent 36d2db7b0e
commit a2e265a539
6 changed files with 626 additions and 2 deletions

View File

@ -2792,6 +2792,8 @@ if (MACHINES["PCI"]~=null) then
MAME_DIR .. "src/devices/machine/lpc-pit.h",
MAME_DIR .. "src/devices/machine/mpc106.cpp",
MAME_DIR .. "src/devices/machine/mpc106.h",
MAME_DIR .. "src/devices/machine/mv6436x.cpp",
MAME_DIR .. "src/devices/machine/mv6436x.h",
MAME_DIR .. "src/devices/machine/vrc4373.cpp",
MAME_DIR .. "src/devices/machine/vrc4373.h",
MAME_DIR .. "src/devices/machine/vrc5074.cpp",
@ -2816,6 +2818,8 @@ if (MACHINES["PCI"]~=null) then
MAME_DIR .. "src/devices/machine/sis950_smbus.h",
MAME_DIR .. "src/devices/machine/sis85c496.cpp",
MAME_DIR .. "src/devices/machine/sis85c496.h",
MAME_DIR .. "src/devices/machine/vt8231_isa.cpp",
MAME_DIR .. "src/devices/machine/vt8231_isa.h",
}
end

View File

@ -0,0 +1,162 @@
// license: BSD-3-Clause
// copyright-holders: Dirk Best
/***************************************************************************
Marvell MV64360/1/2
System controller for PowerPC processors
***************************************************************************/
#include "emu.h"
#include "mv6436x.h"
//#define LOG_GENERAL (1U << 0)
#define LOG_PCI_CONFIG (1U << 1)
#define LOG_PCI_MEM (1U << 2)
#define LOG_PCI_IO (1U << 3)
#define VERBOSE (LOG_GENERAL | LOG_PCI_CONFIG | LOG_PCI_MEM | LOG_PCI_IO)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(MV64361, mv64361_device, "mv64361", "Marvell MV64361 System Controller")
DEFINE_DEVICE_TYPE(MV64361_PCI_HOST, mv64361_pci_host_device, "mv64361_pci_host", "Marvell MV64361 PCI Host")
//**************************************************************************
// MV64361 SYSTEM CONTROLLER
//**************************************************************************
mv64361_device::mv64361_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, MV64361, tag, owner, clock),
m_cpu(*this, finder_base::DUMMY_TAG)
{
}
void mv64361_device::device_start()
{
m_cpu_space = &m_cpu->space(AS_PROGRAM);
m_cpu_space->install_device(0xf1000000, 0xf100ffff, *static_cast<mv64361_device *>(this), &mv64361_device::register_map);
}
void mv64361_device::device_reset()
{
}
void mv64361_device::register_map(address_map &map)
{
map(0x0000, 0x0007).rw(FUNC(mv64361_device::cpu_config_r), FUNC(mv64361_device::cpu_config_w));
}
uint32_t mv64361_device::cpu_config_r(offs_t offset, uint32_t mem_mask)
{
LOGMASKED(LOG_GENERAL, "cpu_config_r\n");
return 0x0000;
}
void mv64361_device::cpu_config_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
LOGMASKED(LOG_GENERAL, "cpu_config_w: %08x\n", data);
}
//**************************************************************************
// MV64361 PCI HOST
//**************************************************************************
mv64361_pci_host_device::mv64361_pci_host_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
pci_host_device(mconfig, MV64361_PCI_HOST, tag, owner, clock),
m_cpu(*this, finder_base::DUMMY_TAG),
m_mem_config("memory_space", ENDIANNESS_LITTLE, 32, 32),
m_io_config("io_space", ENDIANNESS_LITTLE, 32, 32)
{
set_ids_host(0x11ab6460, 0x01, 0x00000000);
}
void mv64361_pci_host_device::device_start()
{
pci_host_device::device_start();
m_cpu_space = &m_cpu->space(AS_PROGRAM);
memory_space = &space(AS_PCI_MEM);
io_space = &space(AS_PCI_IO);
memory_window_start = 0;
memory_window_end = 0xffffffff;
memory_offset = 0;
io_window_start = 0;
io_window_end = 0xffffffff;
io_offset = 0;
m_cpu_space->install_device(0xf1000000, 0xf100ffff, *static_cast<mv64361_pci_host_device *>(this), &mv64361_pci_host_device::pci_map);
m_cpu_space->install_read_handler (0xfe000000, 0xfe00ffff, read32s_delegate(*this, FUNC(mv64361_pci_host_device::pci_io_r)));
m_cpu_space->install_write_handler(0xfe000000, 0xfe00ffff, write32s_delegate(*this, FUNC(mv64361_pci_host_device::pci_io_w)));
}
void mv64361_pci_host_device::device_reset()
{
pci_host_device::device_reset();
}
void mv64361_pci_host_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)
{
}
device_memory_interface::space_config_vector mv64361_pci_host_device::memory_space_config() const
{
auto r = pci_bridge_device::memory_space_config();
r.emplace_back(std::make_pair(AS_PCI_MEM, &m_mem_config));
r.emplace_back(std::make_pair(AS_PCI_IO, &m_io_config));
return r;
}
void mv64361_pci_host_device::pci_map(address_map &map)
{
// pci0 to pci1 offset is 0x80
int o = m_busnum * 0x80;
map(0x0cf8 - o, 0x0cfb - o).rw(FUNC(mv64361_pci_host_device::be_config_address_r), FUNC(mv64361_pci_host_device::be_config_address_w));
map(0x0cfc - o, 0x0cff - o).rw(FUNC(mv64361_pci_host_device::be_config_data_r), FUNC(mv64361_pci_host_device::be_config_data_w));
}
uint32_t mv64361_pci_host_device::be_config_address_r(offs_t offset, uint32_t mem_mask)
{
uint32_t data = pci_host_device::config_address_r();
LOGMASKED(LOG_PCI_CONFIG, "be_config_address_r: %08x & %08x\n", swapendian_int32(data), swapendian_int32(mem_mask));
return swapendian_int32(data);
}
void mv64361_pci_host_device::be_config_address_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
LOGMASKED(LOG_PCI_CONFIG, "be_config_address_w: %08x & %08x\n", swapendian_int32(data), swapendian_int32(mem_mask));
pci_host_device::config_address_w(0, swapendian_int32(data), swapendian_int32(mem_mask));
}
uint32_t mv64361_pci_host_device::be_config_data_r(offs_t offset, uint32_t mem_mask)
{
uint32_t data = pci_host_device::config_data_r(0, swapendian_int32(mem_mask));
LOGMASKED(LOG_PCI_CONFIG, "be_config_data_r: %08x & %08x\n", swapendian_int32(data), swapendian_int32(mem_mask));
return swapendian_int32(data);
}
void mv64361_pci_host_device::be_config_data_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
LOGMASKED(LOG_PCI_CONFIG, "be_config_data_w: %08x & %08x\n", swapendian_int32(data), swapendian_int32(mem_mask));
pci_host_device::config_data_w(0, swapendian_int32(data), swapendian_int32(mem_mask));
}
uint32_t mv64361_pci_host_device::pci_io_r(offs_t offset, uint32_t mem_mask)
{
uint32_t data = space(AS_PCI_IO).read_dword(offset * 4, swapendian_int32(mem_mask));
LOGMASKED(LOG_PCI_IO, "pci_io_r[%08x]: %08x & %08x\n", offset * 4, swapendian_int32(data), swapendian_int32(mem_mask));
return swapendian_int32(data);
}
void mv64361_pci_host_device::pci_io_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
LOGMASKED(LOG_PCI_IO, "pci_io_w[%08x]: %08x & %08x\n", offset * 4, swapendian_int32(data), swapendian_int32(mem_mask));
space(AS_PCI_IO).write_dword(offset * 4, swapendian_int32(data), swapendian_int32(mem_mask));
}

View File

@ -0,0 +1,114 @@
// license: BSD-3-Clause
// copyright-holders: Dirk Best
/***************************************************************************
Marvell MV64360/1/2
System controller for PowerPC processors
***************************************************************************/
#ifndef MAME_MACHINE_MV6436X_H
#define MAME_MACHINE_MV6436X_H
#pragma once
#include "cpu/powerpc/ppc.h"
#include "pci.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// forward declaration
class mv64361_pci_host_device;
// ======================> mv64361_device
class mv64361_device : public device_t
{
public:
// construction/destruction
template <typename T>
mv64361_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag):
mv64361_device(mconfig, tag, owner, clock)
{
set_cpu_tag(std::forward<T>(cpu_tag));
}
mv64361_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
template <typename T> void set_cpu_tag(T &&tag) { m_cpu.set_tag(std::forward<T>(tag)); }
protected:
virtual void device_start() override;
virtual void device_reset() override;
private:
void register_map(address_map &map);
uint32_t cpu_config_r(offs_t offset, uint32_t mem_mask);
void cpu_config_w(offs_t offset, uint32_t data, uint32_t mem_mask);
required_device<ppc_device> m_cpu;
address_space *m_cpu_space;
};
// ======================> mv64361_pci_host_device
class mv64361_pci_host_device : public pci_host_device
{
public:
// construction/destruction
template <typename T>
mv64361_pci_host_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag, int busnum):
mv64361_pci_host_device(mconfig, tag, owner, clock)
{
set_cpu_tag(std::forward<T>(cpu_tag));
m_busnum = busnum;
}
mv64361_pci_host_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
template <typename T> void set_cpu_tag(T &&tag) { m_cpu.set_tag(std::forward<T>(tag)); }
protected:
virtual void device_start() override;
virtual void device_reset() override;
virtual void 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) override;
virtual space_config_vector memory_space_config() const override;
private:
enum
{
AS_PCI_MEM = 1,
AS_PCI_IO = 2
};
void pci_map(address_map &map);
uint32_t be_config_address_r(offs_t offset, uint32_t mem_mask = ~0);
void be_config_address_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
uint32_t be_config_data_r(offs_t offset, uint32_t mem_mask = ~0);
void be_config_data_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
uint32_t pci_io_r(offs_t offset, uint32_t mem_mask);
void pci_io_w(offs_t offset, uint32_t data, uint32_t mem_mask);
required_device<ppc_device> m_cpu;
address_space_config m_mem_config, m_io_config;
address_space *m_cpu_space;
int m_busnum;
};
// device type definition
DECLARE_DEVICE_TYPE(MV64361, mv64361_device)
DECLARE_DEVICE_TYPE(MV64361_PCI_HOST, mv64361_pci_host_device)
#endif // MAME_MACHINE_MV6436X_H

View File

@ -0,0 +1,227 @@
// 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_GENERAL (1U << 0)
#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)
{
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();
// resolve callbacks
m_com1_txd_cb.resolve_safe();
m_com1_dtr_cb.resolve_safe();
m_com1_rts_cb.resolve_safe();
// 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
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)
{
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);
}

View File

@ -0,0 +1,82 @@
// license: BSD-3-Clause
// copyright-holders: Dirk Best
/***************************************************************************
VIA VT8231 South Bridge - PCI to ISA Bridge
***************************************************************************/
#ifndef MAME_MACHINE_VT8231_ISA_H
#define MAME_MACHINE_VT8231_ISA_H
#pragma once
#include "pci.h"
#include "machine/ins8250.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> vt8231_isa_device
class vt8231_isa_device : public pci_device
{
public:
vt8231_isa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto com1_txd_cb() { return m_com1_txd_cb.bind(); }
auto com1_dtr_cb() { return m_com1_dtr_cb.bind(); }
auto com1_rts_cb() { return m_com1_rts_cb.bind(); }
void com1_rxd_w(int state) { m_com1->rx_w(state); };
void com1_dcd_w(int state) { m_com1->dcd_w(state); };
void com1_dsr_w(int state) { m_com1->dsr_w(state); };
void com1_ri_w(int state) { m_com1->ri_w(state); };
void com1_cts_w(int state) { m_com1->cts_w(state); };
protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
virtual void device_reset() override;
virtual void 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) override;
virtual void config_map(address_map &map) override;
private:
uint8_t function_control_1_r();
void function_control_1_w(uint8_t data);
void io_map(address_map &map);
uint8_t superio_cfg_idx_r();
void superio_cfg_idx_w(uint8_t data);
uint8_t superio_cfg_data_r();
void superio_cfg_data_w(uint8_t data);
void com1_map(address_map &map);
uint16_t com1_baud_r();
void com1_baud_w(uint16_t data);
void com1_txd_w(int state) { m_com1_txd_cb(state); };
void com1_dtr_w(int state) { m_com1_dtr_cb(state); };
void com1_rts_w(int state) { m_com1_rts_cb(state); };
required_device<ns16550_device> m_com1;
devcb_write_line m_com1_txd_cb;
devcb_write_line m_com1_dtr_cb;
devcb_write_line m_com1_rts_cb;
uint8_t m_superio_cfg[0x10];
uint8_t m_superio_cfg_idx;
uint16_t m_baud_divisor;
};
// device type definition
DECLARE_DEVICE_TYPE(VT8231_ISA, vt8231_isa_device)
#endif // MAME_MACHINE_VT8231_ISA_H

View File

@ -27,7 +27,11 @@
***************************************************************************/
#include "emu.h"
#include "bus/rs232/rs232.h"
#include "cpu/powerpc/ppc.h"
#include "machine/mv6436x.h"
#include "machine/pci.h"
#include "machine/vt8231_isa.h"
namespace {
@ -42,7 +46,8 @@ class pegasos2_state : public driver_device
public:
pegasos2_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu")
m_maincpu(*this, "maincpu"),
m_syscon(*this, "syscon")
{
}
@ -53,7 +58,8 @@ protected:
virtual void machine_reset() override;
private:
required_device<cpu_device> m_maincpu;
required_device<ppc_device> m_maincpu;
required_device<mv64361_device> m_syscon;
void mem_map(address_map &map);
};
@ -94,10 +100,39 @@ void pegasos2_state::machine_reset()
// MACHINE DEFINTIONS
//**************************************************************************
static DEVICE_INPUT_DEFAULTS_START( com1_defaults )
DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_115200 )
DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_115200 )
DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 )
DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE )
DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 )
DEVICE_INPUT_DEFAULTS_END
void pegasos2_state::pegasos2(machine_config &config)
{
PPC604(config, m_maincpu, 100000000); // wrong cpu/clock
m_maincpu->set_addrmap(AS_PROGRAM, &pegasos2_state::mem_map);
MV64361(config, m_syscon, 0, m_maincpu);
PCI_ROOT(config, "pci0", 0);
MV64361_PCI_HOST(config, "pci0:00.0", 0, m_maincpu, 0);
PCI_ROOT(config, "pci1", 0);
MV64361_PCI_HOST(config, "pci1:00.0", 0, m_maincpu, 1);
vt8231_isa_device &isa(VT8231_ISA(config, "pci1:0c.0", 0));
isa.com1_txd_cb().set("com1", FUNC(rs232_port_device::write_txd));
isa.com1_dtr_cb().set("com1", FUNC(rs232_port_device::write_dtr));
isa.com1_rts_cb().set("com1", FUNC(rs232_port_device::write_rts));
rs232_port_device &com1(RS232_PORT(config, "com1", default_rs232_devices, "terminal"));
com1.set_option_device_input_defaults("null_modem", DEVICE_INPUT_DEFAULTS_NAME(com1_defaults));
com1.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(com1_defaults));
com1.rxd_handler().set("pci1:0c.0", FUNC(vt8231_isa_device::com1_rxd_w));
com1.dcd_handler().set("pci1:0c.0", FUNC(vt8231_isa_device::com1_dcd_w));
com1.dsr_handler().set("pci1:0c.0", FUNC(vt8231_isa_device::com1_dsr_w));
com1.ri_handler().set("pci1:0c.0", FUNC(vt8231_isa_device::com1_ri_w));
com1.cts_handler().set("pci1:0c.0", FUNC(vt8231_isa_device::com1_cts_w));
}