mirror of
https://github.com/holub/mame
synced 2025-10-05 08:41:31 +03:00
Emulate PS/2 keyboard/mouse controller - same MCU as AT, but wired
differently. (nw) Keyboard functionality works, mouse functionality is untested and not hooked up to anything. Will add slot devices for PS/2 mouse later. For some reason the ct486 driver now reports a keyboard error on boot. You can hit F1 to get past it, but it's annoying. I'll look into that later as well.
This commit is contained in:
parent
b2eb6fa02e
commit
451e5b2391
@ -510,15 +510,15 @@ MACHINE_CONFIG_START(southbridge_extended_device::device_add_mconfig)
|
||||
southbridge_device::device_add_mconfig(config);
|
||||
|
||||
at_keyboard_controller_device &keybc(AT_KEYBOARD_CONTROLLER(config, "keybc", XTAL(12'000'000)));
|
||||
keybc.system_reset_cb().set_inputline(":maincpu", INPUT_LINE_RESET);
|
||||
keybc.gate_a20_cb().set_inputline(":maincpu", INPUT_LINE_A20);
|
||||
keybc.input_buffer_full_cb().set("pic8259_master", FUNC(pic8259_device::ir1_w));
|
||||
keybc.keyboard_clock_cb().set("pc_kbdc", FUNC(pc_kbdc_device::clock_write_from_mb));
|
||||
keybc.keyboard_data_cb().set("pc_kbdc", FUNC(pc_kbdc_device::data_write_from_mb));
|
||||
keybc.hot_res().set_inputline(":maincpu", INPUT_LINE_RESET);
|
||||
keybc.gate_a20().set_inputline(":maincpu", INPUT_LINE_A20);
|
||||
keybc.kbd_irq().set("pic8259_master", FUNC(pic8259_device::ir1_w));
|
||||
keybc.kbd_clk().set("pc_kbdc", FUNC(pc_kbdc_device::clock_write_from_mb));
|
||||
keybc.kbd_data().set("pc_kbdc", FUNC(pc_kbdc_device::data_write_from_mb));
|
||||
|
||||
MCFG_DEVICE_ADD("pc_kbdc", PC_KBDC, 0)
|
||||
MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE("keybc", at_keyboard_controller_device, keyboard_clock_w))
|
||||
MCFG_PC_KBDC_OUT_DATA_CB(WRITELINE("keybc", at_keyboard_controller_device, keyboard_data_w))
|
||||
MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE("keybc", at_keyboard_controller_device, kbd_clk_w))
|
||||
MCFG_PC_KBDC_OUT_DATA_CB(WRITELINE("keybc", at_keyboard_controller_device, kbd_data_w))
|
||||
MCFG_PC_KBDC_SLOT_ADD("pc_kbdc", "kbd", pc_at_keyboards, STR_KBD_MICROSOFT_NATURAL)
|
||||
|
||||
ds12885_device &rtc(DS12885(config, "rtc"));
|
||||
|
@ -47,9 +47,7 @@ void pc_kbdc_slot_device::device_start()
|
||||
device_pc_kbd_interface *pc_kbd = dynamic_cast<device_pc_kbd_interface *>(get_card_device());
|
||||
|
||||
if (pc_kbd)
|
||||
{
|
||||
pc_kbd->set_pc_kbdc(m_kbdc_device);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -71,11 +69,11 @@ pc_kbdc_device::pc_kbdc_device(const machine_config &mconfig, const char *tag, d
|
||||
m_data_state(-1), m_mb_clock_state(0), m_mb_data_state(0),
|
||||
m_kb_clock_state(1),
|
||||
m_kb_data_state(1),
|
||||
m_keyboard( nullptr )
|
||||
m_keyboard(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void pc_kbdc_device::set_keyboard( device_pc_kbd_interface *keyboard )
|
||||
void pc_kbdc_device::set_keyboard(device_pc_kbd_interface *keyboard)
|
||||
{
|
||||
m_keyboard = keyboard;
|
||||
}
|
||||
@ -84,19 +82,22 @@ void pc_kbdc_device::set_keyboard( device_pc_kbd_interface *keyboard )
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
void pc_kbdc_device::device_start()
|
||||
void pc_kbdc_device::device_resolve_objects()
|
||||
{
|
||||
// resolve callbacks
|
||||
m_out_clock_cb.resolve_safe();
|
||||
m_out_data_cb.resolve_safe();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
void pc_kbdc_device::device_reset()
|
||||
void pc_kbdc_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_clock_state));
|
||||
save_item(NAME(m_data_state));
|
||||
|
||||
save_item(NAME(m_mb_clock_state));
|
||||
save_item(NAME(m_mb_data_state));
|
||||
save_item(NAME(m_kb_clock_state));
|
||||
save_item(NAME(m_kb_data_state));
|
||||
|
||||
m_clock_state = -1; /* initial state of calculated clock line */
|
||||
m_data_state = -1; /* initial state of calculated data line */
|
||||
|
||||
@ -112,19 +113,14 @@ void pc_kbdc_device::update_clock_state()
|
||||
{
|
||||
int new_clock_state = m_mb_clock_state & m_kb_clock_state;
|
||||
|
||||
if ( new_clock_state != m_clock_state )
|
||||
if (new_clock_state != m_clock_state)
|
||||
{
|
||||
// We first set our state to prevent possible endless loops
|
||||
m_clock_state = new_clock_state;
|
||||
|
||||
// Send state to keyboard interface logic on mainboard
|
||||
m_out_clock_cb( m_clock_state );
|
||||
|
||||
// Send state to keyboard
|
||||
if ( m_keyboard )
|
||||
{
|
||||
if (m_keyboard)
|
||||
m_keyboard->clock_write( m_clock_state );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,48 +129,51 @@ void pc_kbdc_device::update_data_state()
|
||||
{
|
||||
int new_data_state = m_mb_data_state & m_kb_data_state;
|
||||
|
||||
if ( new_data_state != m_data_state )
|
||||
if (new_data_state != m_data_state)
|
||||
{
|
||||
// We first set our state to prevent possible endless loops
|
||||
m_data_state = new_data_state;
|
||||
|
||||
// Send state to keyboard interface logic on mainboard
|
||||
m_out_data_cb( m_data_state );
|
||||
|
||||
// Send state to keyboard
|
||||
if ( m_keyboard )
|
||||
{
|
||||
m_keyboard->data_write( m_data_state );
|
||||
}
|
||||
if (m_keyboard)
|
||||
m_keyboard->data_write(m_data_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER( pc_kbdc_device::clock_write_from_mb )
|
||||
WRITE_LINE_MEMBER(pc_kbdc_device::clock_write_from_mb)
|
||||
{
|
||||
m_mb_clock_state = state;
|
||||
update_clock_state();
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER( pc_kbdc_device::data_write_from_mb )
|
||||
WRITE_LINE_MEMBER(pc_kbdc_device::data_write_from_mb)
|
||||
{
|
||||
m_mb_data_state = state;
|
||||
update_data_state();
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER( pc_kbdc_device::clock_write_from_kb )
|
||||
WRITE_LINE_MEMBER(pc_kbdc_device::clock_write_from_kb)
|
||||
{
|
||||
m_kb_clock_state = state;
|
||||
update_clock_state();
|
||||
state = state ? 1 : 0;
|
||||
if (state != m_kb_clock_state)
|
||||
{
|
||||
m_out_clock_cb(m_kb_clock_state = state);
|
||||
update_clock_state();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER( pc_kbdc_device::data_write_from_kb )
|
||||
WRITE_LINE_MEMBER(pc_kbdc_device::data_write_from_kb)
|
||||
{
|
||||
m_kb_data_state = state;
|
||||
update_data_state();
|
||||
state = state ? 1 : 0;
|
||||
if (state != m_kb_data_state)
|
||||
{
|
||||
m_out_data_cb(m_kb_data_state = state);
|
||||
update_data_state();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -203,20 +202,18 @@ device_pc_kbd_interface::~device_pc_kbd_interface()
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER( device_pc_kbd_interface::clock_write )
|
||||
WRITE_LINE_MEMBER(device_pc_kbd_interface::clock_write)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER( device_pc_kbd_interface::data_write )
|
||||
WRITE_LINE_MEMBER(device_pc_kbd_interface::data_write)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void device_pc_kbd_interface::set_pc_kbdc_device()
|
||||
{
|
||||
if ( m_pc_kbdc )
|
||||
{
|
||||
m_pc_kbdc->set_keyboard( this );
|
||||
}
|
||||
if (m_pc_kbdc)
|
||||
m_pc_kbdc->set_keyboard(this);
|
||||
}
|
||||
|
@ -43,13 +43,13 @@ public:
|
||||
// construction/destruction
|
||||
pc_kbdc_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
|
||||
// inline configuration
|
||||
void set_pc_kbdc_slot(device_t *kbdc_device) { m_kbdc_device = kbdc_device; }
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
|
||||
// configuration
|
||||
device_t *m_kbdc_device;
|
||||
};
|
||||
@ -84,8 +84,8 @@ public:
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
void update_clock_state();
|
||||
void update_data_state();
|
||||
@ -93,13 +93,13 @@ protected:
|
||||
devcb_write_line m_out_clock_cb;
|
||||
devcb_write_line m_out_data_cb;
|
||||
|
||||
int m_clock_state;
|
||||
int m_data_state;
|
||||
int8_t m_clock_state;
|
||||
int8_t m_data_state;
|
||||
|
||||
int m_mb_clock_state;
|
||||
int m_mb_data_state;
|
||||
int m_kb_clock_state;
|
||||
int m_kb_data_state;
|
||||
uint8_t m_mb_clock_state;
|
||||
uint8_t m_mb_data_state;
|
||||
uint8_t m_kb_clock_state;
|
||||
uint8_t m_kb_data_state;
|
||||
|
||||
device_pc_kbd_interface *m_keyboard;
|
||||
};
|
||||
@ -115,15 +115,10 @@ class device_pc_kbd_interface : public device_slot_card_interface
|
||||
{
|
||||
friend class pc_kbdc_device;
|
||||
public:
|
||||
// construction/destruction
|
||||
device_pc_kbd_interface(const machine_config &mconfig, device_t &device);
|
||||
virtual ~device_pc_kbd_interface();
|
||||
|
||||
void set_pc_kbdc_device();
|
||||
|
||||
int clock_signal() { return m_pc_kbdc ? m_pc_kbdc->clock_signal() : 1; }
|
||||
int data_signal() { return m_pc_kbdc ? m_pc_kbdc->data_signal() : 1; }
|
||||
|
||||
//
|
||||
// Override the clock_write and data_write methods in a keyboard implementation
|
||||
//
|
||||
@ -134,6 +129,11 @@ public:
|
||||
void set_pc_kbdc(device_t *kbdc_device) { m_pc_kbdc = dynamic_cast<pc_kbdc_device *>(kbdc_device); }
|
||||
|
||||
protected:
|
||||
device_pc_kbd_interface(const machine_config &mconfig, device_t &device);
|
||||
|
||||
int clock_signal() const { return m_pc_kbdc ? m_pc_kbdc->clock_signal() : 1; }
|
||||
int data_signal() const { return m_pc_kbdc ? m_pc_kbdc->data_signal() : 1; }
|
||||
|
||||
pc_kbdc_device *m_pc_kbdc;
|
||||
const char *m_pc_kbdc_tag;
|
||||
};
|
||||
|
@ -1,214 +1,405 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Wilbert Pol
|
||||
// copyright-holders:Vas Crabb
|
||||
/***************************************************************************
|
||||
|
||||
IBM PC AT compatibles 8042 keyboard controller
|
||||
IBM PC/AT and PS/2 keyboard controllers
|
||||
|
||||
IBM used Intel UPI-41 microcontrollers to implement bidirectional
|
||||
keyboard communication from the PC/AT and PS/2. On the PS/2, the
|
||||
microcontroller also handles mouse communication. The PS/2 host
|
||||
interface to the keyboard/mouse controller is backwards-compatible
|
||||
for documented commands. However a number of undocumented commands
|
||||
are no longer implemented, the pin assignments are different, and
|
||||
interrupt outputs are latched externally using a 74ALS74 at ZM87.
|
||||
|
||||
PC/AT I/O pin assignments:
|
||||
P10: NC no connection
|
||||
P11: NC no connection
|
||||
P12: NC no connection
|
||||
P13: NC no connection
|
||||
P14: -RAM SEL enable external RAM low disables
|
||||
P15: manufacturing setting low disables
|
||||
P16: SW1 CRT adapter switch low for CGA
|
||||
P17: +KBD INH inhibit keyboard active low
|
||||
P20: RC reset CPU active low
|
||||
P21: A20 GATE enable A20 line active high
|
||||
P22: NC no connection
|
||||
P23: NC no connection
|
||||
P24: +OPT BUF FULL output buffer full active high
|
||||
P25: NC no connection
|
||||
P26: open collector KBD CLK inverted
|
||||
P27: open collector KBD DATA not inverted
|
||||
TEST0: KBD CLK not inverted
|
||||
TEST1: KBD DATA not inverted
|
||||
|
||||
PS/2 I/O pin assignments
|
||||
P10: KYBD DATA not inverted
|
||||
P11: MOUSE DATA not inverted
|
||||
P12: keyboard/mouse power fuse low if blown
|
||||
P13: no connection
|
||||
P14: no connection
|
||||
P15: no connection
|
||||
P16: no connection
|
||||
P17: no connection
|
||||
P20: +HOT RES reset CPU inverted
|
||||
P21: A20 PASS enable A20 line not inverted
|
||||
P22: open collector MOUSE DATA inverted
|
||||
P23: open collector MOUSE CLK inverted
|
||||
P24: latched as BIRQ1 rising trigger
|
||||
P25: latched as IRQ12 rising trigger
|
||||
P26: open collector KYBD CLK inverted
|
||||
P27: open collector KYBD DATA inverted
|
||||
TEST0: KYBD CLK not inverted
|
||||
TEST1: MOUSE CLK not inverted
|
||||
|
||||
Notes:
|
||||
* PS/2 BIRQ1 and IRQ12 are cleard by reading data.
|
||||
* PS/2 BIRQ1 and IRQ12 are active low, but we use ASSERT_LINE here.
|
||||
* PS/2 IRQ12 is open collector for sharing with cards.
|
||||
|
||||
TODO:
|
||||
* Move display type and key lock controls to drivers.
|
||||
* Expose power fuse failure.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "at_keybc.h"
|
||||
|
||||
namespace {
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
DEFINE_DEVICE_TYPE(AT_KEYBOARD_CONTROLLER, at_keyboard_controller_device, "at_keybc", "AT Keyboard Controller")
|
||||
|
||||
static INPUT_PORTS_START( at_keybc )
|
||||
PORT_START("DSW")
|
||||
PORT_BIT( 0xbf, 0xbf, IPT_UNUSED )
|
||||
PORT_DIPNAME( 0x40, 0x00, "Display switch")
|
||||
PORT_DIPSETTING( 0x40, "Monochrome adapter" )
|
||||
PORT_DIPSETTING( 0x00, "Color/Graphics adapter" )
|
||||
INPUT_PORTS_END
|
||||
|
||||
// rom definition for the 8042 internal rom
|
||||
ROM_START( at_keybc )
|
||||
ROM_REGION(0x800, "at_keybc", 0)
|
||||
|
||||
// unknown controller bios, (c) 1985, 1986 PTL
|
||||
ROM_LOAD("yan25d05.bin", 0x000, 0x800, CRC(70c798f1) SHA1(ae9a79c7184a17331b70a50035ff63c757df094c))
|
||||
|
||||
// 1983 ibm controller bios
|
||||
ROM_LOAD("1503033.bin", 0x000, 0x800, CRC(5a81c0d2) SHA1(0100f8789fb4de74706ae7f9473a12ec2b9bd729))
|
||||
ROM_START(at_kbc)
|
||||
ROM_REGION(0x0800, "mcu", 0)
|
||||
ROM_SYSTEM_BIOS(0, "ibm", "IBM 1983") // 1983 IBM controller BIOS
|
||||
ROMX_LOAD("1503033.bin", 0x0000, 0x0800, CRC(5a81c0d2) SHA1(0100f8789fb4de74706ae7f9473a12ec2b9bd729), ROM_BIOS(0))
|
||||
ROM_SYSTEM_BIOS(1, "ptl", "PTL 1986") // unknown controller BIOS, (c) 1985, 1986 PTL
|
||||
ROMX_LOAD("yan25d05.bin", 0x0000, 0x0800, CRC(70c798f1) SHA1(ae9a79c7184a17331b70a50035ff63c757df094c), ROM_BIOS(1))
|
||||
ROM_END
|
||||
|
||||
ROM_START(ps2_kbc)
|
||||
ROM_REGION(0x0800, "mcu", 0)
|
||||
ROM_LOAD("72x8455.zm82", 0x0000, 0x0800, CRC(7da223d3) SHA1(54c52ff6c6a2310f79b2c7e6d1259be9de868f0e))
|
||||
ROM_END
|
||||
|
||||
INPUT_PORTS_START(at_kbc)
|
||||
PORT_START("P1")
|
||||
PORT_BIT(0x3f, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
PORT_CONFNAME(0x40, 0x00, "CRT Adapter Switch")
|
||||
PORT_CONFSETTING( 0x40, "Monochrome Display Adapter")
|
||||
PORT_CONFSETTING( 0x00, "Color Graphics Adapter")
|
||||
PORT_CONFNAME(0x80, 0x80, "Key Lock")
|
||||
PORT_CONFSETTING( 0x80, DEF_STR(Off))
|
||||
PORT_CONFSETTING( 0x00, DEF_STR(On))
|
||||
INPUT_PORTS_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
// DEVICE TYPES
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// at_keyboard_controller_device - constructor
|
||||
//-------------------------------------------------
|
||||
DEFINE_DEVICE_TYPE(AT_KEYBOARD_CONTROLLER, at_keyboard_controller_device, "at_keybc", "PC/AT Keyboard Controller")
|
||||
DEFINE_DEVICE_TYPE(PS2_KEYBOARD_CONTROLLER, ps2_keyboard_controller_device, "ps2_keybc", "PS/2 Keyboard/Mouse Controller")
|
||||
|
||||
at_keyboard_controller_device::at_keyboard_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, AT_KEYBOARD_CONTROLLER, tag, owner, clock),
|
||||
m_cpu(nullptr),
|
||||
m_system_reset_cb(*this),
|
||||
m_gate_a20_cb(*this),
|
||||
m_input_buffer_full_cb(*this),
|
||||
m_output_buffer_empty_cb(*this),
|
||||
m_keyboard_clock_cb(*this),
|
||||
m_keyboard_data_cb(*this)
|
||||
|
||||
//**************************************************************************
|
||||
// KEYBOARD CONTROLLER DEVICE BASE
|
||||
//**************************************************************************
|
||||
|
||||
READ8_MEMBER(at_kbc_device_base::data_r)
|
||||
{
|
||||
return m_mcu->upi41_master_r(space, 0U);
|
||||
}
|
||||
|
||||
READ8_MEMBER(at_kbc_device_base::status_r)
|
||||
{
|
||||
return m_mcu->upi41_master_r(space, 1U);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(at_kbc_device_base::data_w)
|
||||
{
|
||||
machine().scheduler().synchronize(timer_expired_delegate(FUNC(at_kbc_device_base::write_data), this), unsigned(data));
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(at_kbc_device_base::command_w)
|
||||
{
|
||||
machine().scheduler().synchronize(timer_expired_delegate(FUNC(at_kbc_device_base::write_command), this), unsigned(data));
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(at_kbc_device_base::kbd_clk_w)
|
||||
{
|
||||
machine().scheduler().synchronize(timer_expired_delegate(FUNC(at_kbc_device_base::set_kbd_clk_in), this), state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(at_kbc_device_base::kbd_data_w)
|
||||
{
|
||||
machine().scheduler().synchronize(timer_expired_delegate(FUNC(at_kbc_device_base::set_kbd_data_in), this), state);
|
||||
}
|
||||
|
||||
at_kbc_device_base::at_kbc_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, m_mcu(*this, "mcu")
|
||||
, m_hot_res_cb(*this), m_gate_a20_cb(*this), m_kbd_irq_cb(*this)
|
||||
, m_kbd_clk_cb(*this), m_kbd_data_cb(*this)
|
||||
, m_hot_res(0U), m_gate_a20(0U), m_kbd_irq(0U)
|
||||
, m_kbd_clk_in(1U), m_kbd_clk_out(1U), m_kbd_data_in(1U), m_kbd_data_out(1U)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// rom_region - return a pointer to the device's
|
||||
// internal ROM region
|
||||
//-------------------------------------------------
|
||||
|
||||
const tiny_rom_entry *at_keyboard_controller_device::device_rom_region() const
|
||||
void at_kbc_device_base::device_resolve_objects()
|
||||
{
|
||||
return ROM_NAME(at_keybc);
|
||||
m_hot_res_cb.resolve_safe();
|
||||
m_gate_a20_cb.resolve_safe();
|
||||
m_kbd_irq_cb.resolve_safe();
|
||||
m_kbd_clk_cb.resolve_safe();
|
||||
m_kbd_data_cb.resolve_safe();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// input_ports - device-specific input ports
|
||||
//-------------------------------------------------
|
||||
void at_kbc_device_base::device_start()
|
||||
{
|
||||
save_item(NAME(m_hot_res));
|
||||
save_item(NAME(m_gate_a20));
|
||||
save_item(NAME(m_kbd_irq));
|
||||
save_item(NAME(m_kbd_clk_in));
|
||||
save_item(NAME(m_kbd_clk_out));
|
||||
save_item(NAME(m_kbd_data_in));
|
||||
save_item(NAME(m_kbd_data_out));
|
||||
|
||||
m_hot_res = m_gate_a20 = m_kbd_irq = 0U;
|
||||
m_kbd_clk_in = m_kbd_clk_out = 1U;
|
||||
m_kbd_data_in = m_kbd_data_out = 1U;
|
||||
}
|
||||
|
||||
inline void at_kbc_device_base::set_hot_res(u8 state)
|
||||
{
|
||||
if (state != m_hot_res)
|
||||
m_hot_res_cb((m_hot_res = state) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
inline void at_kbc_device_base::set_gate_a20(u8 state)
|
||||
{
|
||||
if (state != m_gate_a20)
|
||||
m_gate_a20_cb((m_gate_a20 = state) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
inline void at_kbc_device_base::set_kbd_irq(u8 state)
|
||||
{
|
||||
if (state != m_kbd_irq)
|
||||
m_kbd_irq_cb((m_kbd_irq = state) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
inline void at_kbc_device_base::set_kbd_clk_out(u8 state)
|
||||
{
|
||||
if (state != m_kbd_clk_out)
|
||||
m_kbd_clk_cb(m_kbd_clk_out = state);
|
||||
}
|
||||
|
||||
inline void at_kbc_device_base::set_kbd_data_out(u8 state)
|
||||
{
|
||||
if (state != m_kbd_data_out)
|
||||
m_kbd_clk_cb(m_kbd_data_out = state);
|
||||
}
|
||||
|
||||
inline u8 at_kbc_device_base::kbd_clk_r() const
|
||||
{
|
||||
return m_kbd_clk_in & m_kbd_clk_out;
|
||||
}
|
||||
|
||||
inline u8 at_kbc_device_base::kbd_data_r() const
|
||||
{
|
||||
return m_kbd_data_in & m_kbd_data_out;
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(at_kbc_device_base::write_data)
|
||||
{
|
||||
m_mcu->upi41_master_w(machine().dummy_space(), 0U, u8(u32(param)));
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(at_kbc_device_base::write_command)
|
||||
{
|
||||
m_mcu->upi41_master_w(machine().dummy_space(), 1U, u8(u32(param)));
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(at_kbc_device_base::set_kbd_clk_in)
|
||||
{
|
||||
m_kbd_clk_in = param ? 1U : 0U;
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(at_kbc_device_base::set_kbd_data_in)
|
||||
{
|
||||
m_kbd_data_in = param ? 1U : 0U;
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// PC/AT KEYBOARD CONTROLLER DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
at_keyboard_controller_device::at_keyboard_controller_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: at_kbc_device_base(mconfig, AT_KEYBOARD_CONTROLLER, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
tiny_rom_entry const *at_keyboard_controller_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME(at_kbc);
|
||||
}
|
||||
|
||||
void at_keyboard_controller_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
I8042(config, m_mcu, DERIVED_CLOCK(1, 1));
|
||||
m_mcu->p1_in_cb().set_ioport("P1");
|
||||
m_mcu->p1_out_cb().set_nop();
|
||||
m_mcu->p2_in_cb().set_constant(0xffU);
|
||||
m_mcu->p2_out_cb().set(FUNC(at_keyboard_controller_device::p2_w));
|
||||
m_mcu->t0_in_cb().set([this] () { return kbd_clk_r(); });
|
||||
m_mcu->t1_in_cb().set([this] () { return kbd_data_r(); });
|
||||
}
|
||||
|
||||
ioport_constructor at_keyboard_controller_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME( at_keybc );
|
||||
return INPUT_PORTS_NAME(at_kbc);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_add_mconfig - add device configuration
|
||||
//-------------------------------------------------
|
||||
|
||||
MACHINE_CONFIG_START(at_keyboard_controller_device::device_add_mconfig)
|
||||
MCFG_DEVICE_ADD("at_keybc", I8042, DERIVED_CLOCK(1,1))
|
||||
MCFG_MCS48_PORT_T0_IN_CB(READLINE(*this, at_keyboard_controller_device, t0_r))
|
||||
MCFG_MCS48_PORT_T1_IN_CB(READLINE(*this, at_keyboard_controller_device, t1_r))
|
||||
MCFG_MCS48_PORT_P1_IN_CB(READ8(*this, at_keyboard_controller_device, p1_r))
|
||||
MCFG_MCS48_PORT_P2_IN_CB(READ8(*this, at_keyboard_controller_device, p2_r))
|
||||
MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(*this, at_keyboard_controller_device, p2_w))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
/*-------------------------------------------------
|
||||
device_start - device-specific startup
|
||||
-------------------------------------------------*/
|
||||
|
||||
void at_keyboard_controller_device::device_start()
|
||||
{
|
||||
// find our cpu
|
||||
m_cpu = downcast<upi41_cpu_device *>(subdevice("at_keybc"));
|
||||
|
||||
// resolve callbacks
|
||||
m_system_reset_cb.resolve_safe();
|
||||
m_gate_a20_cb.resolve_safe();
|
||||
m_input_buffer_full_cb.resolve_safe();
|
||||
m_output_buffer_empty_cb.resolve_safe();
|
||||
m_keyboard_clock_cb.resolve_safe();
|
||||
m_keyboard_data_cb.resolve_safe();
|
||||
|
||||
// register for save states
|
||||
save_item(NAME(m_clock_signal));
|
||||
save_item(NAME(m_data_signal));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
device_reset - device-specific reset
|
||||
-------------------------------------------------*/
|
||||
|
||||
void at_keyboard_controller_device::device_reset()
|
||||
WRITE8_MEMBER(at_keyboard_controller_device::p2_w)
|
||||
{
|
||||
set_hot_res(BIT(~data, 0));
|
||||
set_gate_a20(BIT(data, 1));
|
||||
set_kbd_irq(BIT(data, 4));
|
||||
set_kbd_clk_out(BIT(~data, 6));
|
||||
set_kbd_data_out(BIT(data, 7));
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// INTERNAL 8042 READ/WRITE HANDLERS
|
||||
// PS/2 KEYBOARD/MOUSE CONTROLLER DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
READ_LINE_MEMBER( at_keyboard_controller_device::t0_r )
|
||||
READ8_MEMBER(ps2_keyboard_controller_device::data_r)
|
||||
{
|
||||
return m_clock_signal;
|
||||
set_kbd_irq(0U);
|
||||
set_mouse_irq(0U);
|
||||
return m_mcu->upi41_master_r(space, 0U);
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER( at_keyboard_controller_device::t1_r )
|
||||
WRITE_LINE_MEMBER(ps2_keyboard_controller_device::mouse_clk_w)
|
||||
{
|
||||
return m_data_signal;
|
||||
machine().scheduler().synchronize(timer_expired_delegate(FUNC(ps2_keyboard_controller_device::set_mouse_clk_in), this), state);
|
||||
}
|
||||
|
||||
/*
|
||||
Port 1 (Input port)
|
||||
0 - P10 - Undefined
|
||||
1 - P11 - Undefined
|
||||
2 - P12 - Undefined
|
||||
3 - P13 - Undefined
|
||||
4 - P14 - External RAM (1 = Enable external RAM, 0 = Disable external RAM)
|
||||
5 - P15 - Manufacturing setting (1 = Setting enabled, 0 = Setting disabled)
|
||||
6 - P16 - Display type switch (1 = Monochrome display, 0 = Color display)
|
||||
7 - P17 - Keyboard inhibit switch (1 = Keyboard enabled, 0 = Keyboard inhibited)
|
||||
*/
|
||||
READ8_MEMBER( at_keyboard_controller_device::p1_r )
|
||||
WRITE_LINE_MEMBER(ps2_keyboard_controller_device::mouse_data_w)
|
||||
{
|
||||
return ioport("DSW")->read();
|
||||
machine().scheduler().synchronize(timer_expired_delegate(FUNC(ps2_keyboard_controller_device::set_mouse_data_in), this), state);
|
||||
}
|
||||
|
||||
READ8_MEMBER( at_keyboard_controller_device::p2_r )
|
||||
ps2_keyboard_controller_device::ps2_keyboard_controller_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: at_kbc_device_base(mconfig, PS2_KEYBOARD_CONTROLLER, tag, owner, clock)
|
||||
, m_mouse_irq_cb(*this)
|
||||
, m_mouse_clk_cb(*this), m_mouse_data_cb(*this)
|
||||
, m_mouse_irq(0U)
|
||||
, m_mouse_clk_in(1U), m_mouse_clk_out(1U), m_mouse_data_in(1U), m_mouse_data_out(1U)
|
||||
, m_p2_data(0xffU)
|
||||
{
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
Port 2 (Output port)
|
||||
0 - P20 - System Reset (1 = Normal, 0 = Reset computer)
|
||||
1 - P21 - Gate A20
|
||||
2 - P22 - Undefined
|
||||
3 - P23 - Undefined
|
||||
4 - P24 - Input Buffer Full
|
||||
5 - P25 - Output Buffer Empty
|
||||
6 - P26 - Keyboard Clock (1 = Pull Clock low, 0 = High-Z)
|
||||
7 - P27 - Keyboard Data (1 = Pull Data low, 0 = High-Z)
|
||||
*/
|
||||
WRITE8_MEMBER( at_keyboard_controller_device::p2_w )
|
||||
tiny_rom_entry const *ps2_keyboard_controller_device::device_rom_region() const
|
||||
{
|
||||
m_system_reset_cb(BIT(data, 0) ? CLEAR_LINE : ASSERT_LINE);
|
||||
m_gate_a20_cb(BIT(data, 1) ? ASSERT_LINE : CLEAR_LINE);
|
||||
m_input_buffer_full_cb(BIT(data, 4) ? ASSERT_LINE : CLEAR_LINE);
|
||||
m_output_buffer_empty_cb(BIT(data, 5) ? ASSERT_LINE : CLEAR_LINE);
|
||||
|
||||
m_clock_signal = !BIT(data, 6);
|
||||
m_data_signal = BIT(data, 7);
|
||||
|
||||
m_keyboard_data_cb(m_data_signal);
|
||||
m_keyboard_clock_cb(m_clock_signal);
|
||||
return ROM_NAME(ps2_kbc);
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// READ/WRITE HANDLERS
|
||||
//**************************************************************************
|
||||
|
||||
READ8_MEMBER( at_keyboard_controller_device::data_r )
|
||||
void ps2_keyboard_controller_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
return m_cpu->upi41_master_r(space, 0);
|
||||
I8042(config, m_mcu, DERIVED_CLOCK(1, 1));
|
||||
m_mcu->p1_in_cb().set(FUNC(ps2_keyboard_controller_device::p1_r));
|
||||
m_mcu->p1_out_cb().set_nop();
|
||||
m_mcu->p2_in_cb().set_constant(0xffU);
|
||||
m_mcu->p2_out_cb().set(FUNC(ps2_keyboard_controller_device::p2_w));
|
||||
m_mcu->t0_in_cb().set([this] () { return kbd_clk_r(); });
|
||||
m_mcu->t1_in_cb().set([this] () { return mouse_clk_r(); });
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( at_keyboard_controller_device::data_w )
|
||||
void ps2_keyboard_controller_device::device_resolve_objects()
|
||||
{
|
||||
m_cpu->upi41_master_w(space, 0, data);
|
||||
at_kbc_device_base::device_resolve_objects();
|
||||
|
||||
m_mouse_clk_cb.resolve_safe();
|
||||
m_mouse_data_cb.resolve_safe();
|
||||
}
|
||||
|
||||
READ8_MEMBER( at_keyboard_controller_device::status_r )
|
||||
void ps2_keyboard_controller_device::device_start()
|
||||
{
|
||||
return m_cpu->upi41_master_r(space, 1);
|
||||
at_kbc_device_base::device_start();
|
||||
|
||||
save_item(NAME(m_mouse_irq));
|
||||
save_item(NAME(m_mouse_clk_in));
|
||||
save_item(NAME(m_mouse_clk_out));
|
||||
save_item(NAME(m_mouse_data_in));
|
||||
save_item(NAME(m_mouse_data_out));
|
||||
save_item(NAME(m_p2_data));
|
||||
|
||||
m_mouse_irq = 0U;
|
||||
m_mouse_clk_in = m_mouse_clk_out = 1U;
|
||||
m_mouse_data_in = m_mouse_data_out = 1U;
|
||||
m_p2_data = 0xffU;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( at_keyboard_controller_device::command_w )
|
||||
inline void ps2_keyboard_controller_device::set_mouse_irq(u8 state)
|
||||
{
|
||||
m_cpu->upi41_master_w(space, 1, data);
|
||||
if (state != m_mouse_irq)
|
||||
m_mouse_irq_cb((m_mouse_irq = state) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( at_keyboard_controller_device::keyboard_clock_w )
|
||||
inline void ps2_keyboard_controller_device::set_mouse_clk_out(u8 state)
|
||||
{
|
||||
m_clock_signal = state;
|
||||
if (state != m_mouse_clk_out)
|
||||
m_mouse_clk_cb(m_mouse_clk_out = state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( at_keyboard_controller_device::keyboard_data_w )
|
||||
inline void ps2_keyboard_controller_device::set_mouse_data_out(u8 state)
|
||||
{
|
||||
m_data_signal = state;
|
||||
if (state != m_mouse_data_out)
|
||||
m_mouse_clk_cb(m_mouse_data_out = state);
|
||||
}
|
||||
|
||||
inline u8 ps2_keyboard_controller_device::mouse_clk_r() const
|
||||
{
|
||||
return m_mouse_clk_in & m_mouse_clk_out;
|
||||
}
|
||||
|
||||
inline u8 ps2_keyboard_controller_device::mouse_data_r() const
|
||||
{
|
||||
return m_mouse_data_in & m_mouse_data_out;
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(ps2_keyboard_controller_device::set_mouse_clk_in)
|
||||
{
|
||||
m_mouse_clk_in = param ? 1U : 0U;
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(ps2_keyboard_controller_device::set_mouse_data_in)
|
||||
{
|
||||
m_mouse_data_in = param ? 1U : 0U;
|
||||
}
|
||||
|
||||
READ8_MEMBER(ps2_keyboard_controller_device::p1_r)
|
||||
{
|
||||
return kbd_data_r() | (mouse_data_r() << 1) | 0xfcU;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(ps2_keyboard_controller_device::p2_w)
|
||||
{
|
||||
set_hot_res(BIT(~data, 0));
|
||||
set_gate_a20(BIT(data, 1));
|
||||
set_mouse_data_out(BIT(~data, 2));
|
||||
set_mouse_clk_out(BIT(~data, 3));
|
||||
set_kbd_clk_out(BIT(~data, 6));
|
||||
set_kbd_data_out(BIT(~data, 7));
|
||||
|
||||
if (BIT(data & ~m_p2_data, 4))
|
||||
set_kbd_irq(1U);
|
||||
if (BIT(data & ~m_p2_data, 5))
|
||||
set_mouse_irq(1U);
|
||||
m_p2_data = data;
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Wilbert Pol
|
||||
// copyright-holders:Vas Crabb
|
||||
/***************************************************************************
|
||||
|
||||
IBM PC AT compatibles 8042 keyboard controller
|
||||
IBM PC/AT and PS/2 keyboard controllers
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_MACHINE_AT_KEYBC_H
|
||||
#define MAME_MACHINE_AT_KEYBC_H
|
||||
|
||||
@ -15,70 +14,152 @@
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
// KEYBOARD CONTROLLER DEVICE BASE
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> at_keyboard_controller_device
|
||||
|
||||
class at_keyboard_controller_device : public device_t
|
||||
class at_kbc_device_base : public device_t
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
at_keyboard_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
// outputs to host
|
||||
auto hot_res() { return m_hot_res_cb.bind(); }
|
||||
auto gate_a20() { return m_gate_a20_cb.bind(); }
|
||||
auto kbd_irq() { return m_kbd_irq_cb.bind(); }
|
||||
|
||||
auto system_reset_cb() { return m_system_reset_cb.bind(); }
|
||||
auto gate_a20_cb() { return m_gate_a20_cb.bind(); }
|
||||
auto input_buffer_full_cb() { return m_input_buffer_full_cb.bind(); }
|
||||
auto output_buffer_empty_cb() { return m_output_buffer_empty_cb.bind(); }
|
||||
auto keyboard_clock_cb() { return m_keyboard_clock_cb.bind(); }
|
||||
auto keyboard_data_cb() { return m_keyboard_data_cb.bind(); }
|
||||
// outputs to keyboard
|
||||
auto kbd_clk() { return m_kbd_clk_cb.bind(); } // open collector with 10kΩ pull-up
|
||||
auto kbd_data() { return m_kbd_data_cb.bind(); } // open collector with 10kΩ pull-up
|
||||
|
||||
// interface to the host pc
|
||||
DECLARE_READ8_MEMBER( data_r );
|
||||
DECLARE_WRITE8_MEMBER( data_w );
|
||||
DECLARE_READ8_MEMBER( status_r );
|
||||
DECLARE_WRITE8_MEMBER( command_w );
|
||||
// host interface
|
||||
virtual DECLARE_READ8_MEMBER(data_r);
|
||||
virtual DECLARE_READ8_MEMBER(status_r);
|
||||
DECLARE_WRITE8_MEMBER(data_w);
|
||||
DECLARE_WRITE8_MEMBER(command_w);
|
||||
|
||||
// interface to the keyboard
|
||||
DECLARE_WRITE_LINE_MEMBER( keyboard_clock_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( keyboard_data_w );
|
||||
// inputs from keyboard
|
||||
DECLARE_WRITE_LINE_MEMBER(kbd_clk_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(kbd_data_w);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
// trampoline constructor
|
||||
at_kbc_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
// device_t implementation
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_start() override;
|
||||
|
||||
// host outputs - use 1 = asserted, 0 = deasserted
|
||||
void set_hot_res(u8 state);
|
||||
void set_gate_a20(u8 state);
|
||||
void set_kbd_irq(u8 state);
|
||||
|
||||
// keyboard line drive - use 1 = pulled up, 0 = driven low
|
||||
void set_kbd_clk_out(u8 state);
|
||||
void set_kbd_data_out(u8 state);
|
||||
u8 kbd_clk_r() const;
|
||||
u8 kbd_data_r() const;
|
||||
|
||||
required_device<upi41_cpu_device> m_mcu;
|
||||
|
||||
private:
|
||||
// internal 8042 interface
|
||||
DECLARE_READ_LINE_MEMBER( t0_r );
|
||||
DECLARE_READ_LINE_MEMBER( t1_r );
|
||||
DECLARE_READ8_MEMBER( p1_r );
|
||||
DECLARE_READ8_MEMBER( p2_r );
|
||||
DECLARE_WRITE8_MEMBER( p2_w );
|
||||
// internal sync helpers
|
||||
TIMER_CALLBACK_MEMBER(write_data);
|
||||
TIMER_CALLBACK_MEMBER(write_command);
|
||||
TIMER_CALLBACK_MEMBER(set_kbd_clk_in);
|
||||
TIMER_CALLBACK_MEMBER(set_kbd_data_in);
|
||||
|
||||
// internal state
|
||||
upi41_cpu_device *m_cpu;
|
||||
devcb_write_line m_hot_res_cb, m_gate_a20_cb, m_kbd_irq_cb;
|
||||
devcb_write_line m_kbd_clk_cb, m_kbd_data_cb;
|
||||
|
||||
// interface to the host pc
|
||||
devcb_write_line m_system_reset_cb;
|
||||
devcb_write_line m_gate_a20_cb;
|
||||
devcb_write_line m_input_buffer_full_cb;
|
||||
devcb_write_line m_output_buffer_empty_cb;
|
||||
|
||||
// interface to the keyboard
|
||||
devcb_write_line m_keyboard_clock_cb;
|
||||
devcb_write_line m_keyboard_data_cb;
|
||||
|
||||
uint8_t m_clock_signal;
|
||||
uint8_t m_data_signal;
|
||||
u8 m_hot_res, m_gate_a20, m_kbd_irq;
|
||||
u8 m_kbd_clk_in, m_kbd_clk_out, m_kbd_data_in, m_kbd_data_out;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
//**************************************************************************
|
||||
// PC/AT KEYBOARD CONTROLLER DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
class at_keyboard_controller_device : public at_kbc_device_base
|
||||
{
|
||||
public:
|
||||
// standard constructor
|
||||
at_keyboard_controller_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
protected:
|
||||
// device_t implementation
|
||||
virtual tiny_rom_entry const *device_rom_region() const override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
|
||||
private:
|
||||
// MCU I/O handlers
|
||||
DECLARE_WRITE8_MEMBER(p2_w);
|
||||
};
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// PS/2 KEYBOARD/MOUSE CONTROLLER DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
class ps2_keyboard_controller_device : public at_kbc_device_base
|
||||
{
|
||||
public:
|
||||
// outputs to host
|
||||
auto mouse_irq() { return m_mouse_irq_cb.bind(); }
|
||||
|
||||
// outputs to mouse
|
||||
auto mouse_clk() { return m_mouse_clk_cb.bind(); } // open collector with 10kΩ pull-up
|
||||
auto mouse_data() { return m_mouse_data_cb.bind(); } // open collector with 10kΩ pull-up
|
||||
|
||||
// host interface
|
||||
virtual DECLARE_READ8_MEMBER(data_r) override;
|
||||
|
||||
// inputs from mouse
|
||||
DECLARE_WRITE_LINE_MEMBER(mouse_clk_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(mouse_data_w);
|
||||
|
||||
// standard constructor
|
||||
ps2_keyboard_controller_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
protected:
|
||||
// device_t implementation
|
||||
virtual tiny_rom_entry const *device_rom_region() const override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_start() override;
|
||||
|
||||
private:
|
||||
// host outputs - use 1 = asserted, 0 = deasserted
|
||||
void set_mouse_irq(u8 state);
|
||||
|
||||
// mouse line drive - use 1 = pulled up, 0 = driven low
|
||||
void set_mouse_clk_out(u8 state);
|
||||
void set_mouse_data_out(u8 state);
|
||||
u8 mouse_clk_r() const;
|
||||
u8 mouse_data_r() const;
|
||||
|
||||
// internal sync helpers
|
||||
TIMER_CALLBACK_MEMBER(set_mouse_clk_in);
|
||||
TIMER_CALLBACK_MEMBER(set_mouse_data_in);
|
||||
|
||||
// MCU I/O handlers
|
||||
DECLARE_READ8_MEMBER(p1_r);
|
||||
DECLARE_WRITE8_MEMBER(p2_w);
|
||||
|
||||
devcb_write_line m_mouse_irq_cb;
|
||||
devcb_write_line m_mouse_clk_cb, m_mouse_data_cb;
|
||||
|
||||
u8 m_mouse_irq;
|
||||
u8 m_mouse_clk_in, m_mouse_clk_out, m_mouse_data_in, m_mouse_data_out;
|
||||
u8 m_p2_data;
|
||||
};
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE TYPES
|
||||
//**************************************************************************
|
||||
|
||||
DECLARE_DEVICE_TYPE(AT_KEYBOARD_CONTROLLER, at_keyboard_controller_device)
|
||||
DECLARE_DEVICE_TYPE(PS2_KEYBOARD_CONTROLLER, ps2_keyboard_controller_device)
|
||||
|
||||
#endif // MAME_MACHINE_AT_KEYBC_H
|
||||
|
@ -173,6 +173,13 @@ cs4031_device::cs4031_device(const machine_config &mconfig, const char *tag, dev
|
||||
m_write_cpureset(*this),
|
||||
m_write_a20m(*this),
|
||||
m_write_spkr(*this),
|
||||
m_cpu(*this, finder_base::DUMMY_TAG),
|
||||
m_keybc(*this, finder_base::DUMMY_TAG),
|
||||
m_isa(*this, finder_base::DUMMY_TAG),
|
||||
m_bios(*this, finder_base::DUMMY_TAG),
|
||||
m_space(nullptr),
|
||||
m_space_io(nullptr),
|
||||
m_ram(nullptr),
|
||||
m_dma1(*this, "dma1"),
|
||||
m_dma2(*this, "dma2"),
|
||||
m_intc1(*this, "intc1"),
|
||||
@ -239,13 +246,8 @@ void cs4031_device::device_start()
|
||||
save_item(NAME(m_address_valid));
|
||||
save_item(NAME(m_registers));
|
||||
|
||||
device_t *cpu = machine().device(m_cputag);
|
||||
m_space = &cpu->memory().space(AS_PROGRAM);
|
||||
m_space_io = &cpu->memory().space(AS_IO);
|
||||
|
||||
m_isa = machine().root_device().memregion(m_isatag)->base();
|
||||
m_bios = machine().root_device().memregion(m_biostag)->base();
|
||||
m_keybc = downcast<at_keyboard_controller_device *>(machine().device(m_keybctag));
|
||||
m_space = &m_cpu->memory().space(AS_PROGRAM);
|
||||
m_space_io = &m_cpu->memory().space(AS_IO);
|
||||
|
||||
m_ram = ram_dev->pointer();
|
||||
uint32_t ram_size = ram_dev->size();
|
||||
|
@ -35,13 +35,14 @@ class cs4031_device : public device_t
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
cs4031_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const char *cputag, const char *isatag, const char *biostag, const char *keybctag)
|
||||
template <typename T, typename U, typename V, typename W>
|
||||
cs4031_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cputag, U &&isatag, V &&biostag, W &&keybctag)
|
||||
: cs4031_device(mconfig, tag, owner, clock)
|
||||
{
|
||||
set_cputag(cputag);
|
||||
set_isatag(isatag);
|
||||
set_biostag(biostag);
|
||||
set_keybctag(keybctag);
|
||||
set_cputag(std::forward<T>(cputag));
|
||||
set_isatag(std::forward<U>(isatag));
|
||||
set_biostag(std::forward<V>(biostag));
|
||||
set_keybctag(std::forward<W>(keybctag));
|
||||
}
|
||||
|
||||
cs4031_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
@ -114,10 +115,10 @@ public:
|
||||
IRQ_CALLBACK_MEMBER(int_ack_r) { return m_intc1->acknowledge(); }
|
||||
|
||||
// inline configuration
|
||||
void set_cputag(const char *tag) { m_cputag = tag; }
|
||||
void set_isatag(const char *tag) { m_isatag = tag; }
|
||||
void set_biostag(const char *tag) { m_biostag = tag; }
|
||||
void set_keybctag(const char *tag) { m_keybctag = tag; }
|
||||
template <typename T> void set_cputag(T &&tag) { m_cpu.set_tag(std::forward<T>(tag)); }
|
||||
template <typename T> void set_isatag(T &&tag) { m_isa.set_tag(std::forward<T>(tag)); }
|
||||
template <typename T> void set_biostag(T &&tag) { m_bios.set_tag(std::forward<T>(tag)); }
|
||||
template <typename T> void set_keybctag(T &&tag) { m_keybc.set_tag(std::forward<T>(tag)); }
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
@ -156,15 +157,13 @@ private:
|
||||
void update_write_regions();
|
||||
|
||||
// internal state
|
||||
const char *m_cputag;
|
||||
const char *m_isatag;
|
||||
const char *m_biostag;
|
||||
const char *m_keybctag;
|
||||
required_device<device_memory_interface> m_cpu;
|
||||
required_device<at_kbc_device_base> m_keybc;
|
||||
required_region_ptr<uint8_t> m_isa;
|
||||
required_region_ptr<uint8_t> m_bios;
|
||||
|
||||
address_space *m_space;
|
||||
address_space *m_space_io;
|
||||
uint8_t *m_isa;
|
||||
uint8_t *m_bios;
|
||||
uint8_t *m_ram;
|
||||
|
||||
// ipc core devices
|
||||
@ -186,7 +185,6 @@ private:
|
||||
int m_nmi_mask;
|
||||
|
||||
// keyboard
|
||||
at_keyboard_controller_device *m_keybc;
|
||||
int m_cpureset;
|
||||
int m_kbrst;
|
||||
int m_ext_gatea20;
|
||||
|
@ -97,15 +97,15 @@ MACHINE_CONFIG_START(sis85c496_host_device::device_add_mconfig)
|
||||
m_pic8259_slave->in_sp_callback().set_constant(0);
|
||||
|
||||
AT_KEYBOARD_CONTROLLER(config, m_keybc, XTAL(12'000'000));
|
||||
m_keybc->system_reset_cb().set(FUNC(sis85c496_host_device::cpu_reset_w));
|
||||
m_keybc->gate_a20_cb().set(FUNC(sis85c496_host_device::cpu_a20_w));
|
||||
m_keybc->input_buffer_full_cb().set("pic8259_master", FUNC(pic8259_device::ir1_w));
|
||||
m_keybc->keyboard_clock_cb().set("pc_kbdc", FUNC(pc_kbdc_device::clock_write_from_mb));
|
||||
m_keybc->keyboard_data_cb().set("pc_kbdc", FUNC(pc_kbdc_device::data_write_from_mb));
|
||||
m_keybc->hot_res().set(FUNC(sis85c496_host_device::cpu_reset_w));
|
||||
m_keybc->gate_a20().set(FUNC(sis85c496_host_device::cpu_a20_w));
|
||||
m_keybc->kbd_irq().set("pic8259_master", FUNC(pic8259_device::ir1_w));
|
||||
m_keybc->kbd_clk().set("pc_kbdc", FUNC(pc_kbdc_device::clock_write_from_mb));
|
||||
m_keybc->kbd_data().set("pc_kbdc", FUNC(pc_kbdc_device::data_write_from_mb));
|
||||
|
||||
MCFG_DEVICE_ADD("pc_kbdc", PC_KBDC, 0)
|
||||
MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE("keybc", at_keyboard_controller_device, keyboard_clock_w))
|
||||
MCFG_PC_KBDC_OUT_DATA_CB(WRITELINE("keybc", at_keyboard_controller_device, keyboard_data_w))
|
||||
MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE("keybc", at_keyboard_controller_device, kbd_clk_w))
|
||||
MCFG_PC_KBDC_OUT_DATA_CB(WRITELINE("keybc", at_keyboard_controller_device, kbd_data_w))
|
||||
MCFG_PC_KBDC_SLOT_ADD("pc_kbdc", "kbd", pc_at_keyboards, STR_KBD_MICROSOFT_NATURAL)
|
||||
|
||||
DS12885(config, m_ds12885);
|
||||
|
@ -684,15 +684,15 @@ MACHINE_CONFIG_START(megapc_state::megapc)
|
||||
MCFG_DEVICE_ADD("isa1", ISA16_SLOT, 0, "isabus", pc_isa16_cards, nullptr, false)
|
||||
|
||||
at_keyboard_controller_device &keybc(AT_KEYBOARD_CONTROLLER(config, "keybc", 12_MHz_XTAL));
|
||||
keybc.system_reset_cb().set("wd7600", FUNC(wd7600_device::kbrst_w));
|
||||
keybc.gate_a20_cb().set("wd7600", FUNC(wd7600_device::gatea20_w));
|
||||
keybc.input_buffer_full_cb().set("wd7600", FUNC(wd7600_device::irq01_w));
|
||||
keybc.keyboard_clock_cb().set("pc_kbdc", FUNC(pc_kbdc_device::clock_write_from_mb));
|
||||
keybc.keyboard_data_cb().set("pc_kbdc", FUNC(pc_kbdc_device::data_write_from_mb));
|
||||
keybc.hot_res().set("wd7600", FUNC(wd7600_device::kbrst_w));
|
||||
keybc.gate_a20().set("wd7600", FUNC(wd7600_device::gatea20_w));
|
||||
keybc.kbd_irq().set("wd7600", FUNC(wd7600_device::irq01_w));
|
||||
keybc.kbd_clk().set("pc_kbdc", FUNC(pc_kbdc_device::clock_write_from_mb));
|
||||
keybc.kbd_data().set("pc_kbdc", FUNC(pc_kbdc_device::data_write_from_mb));
|
||||
|
||||
MCFG_DEVICE_ADD("pc_kbdc", PC_KBDC, 0)
|
||||
MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE("keybc", at_keyboard_controller_device, keyboard_clock_w))
|
||||
MCFG_PC_KBDC_OUT_DATA_CB(WRITELINE("keybc", at_keyboard_controller_device, keyboard_data_w))
|
||||
MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE("keybc", at_keyboard_controller_device, kbd_clk_w))
|
||||
MCFG_PC_KBDC_OUT_DATA_CB(WRITELINE("keybc", at_keyboard_controller_device, kbd_data_w))
|
||||
MCFG_PC_KBDC_SLOT_ADD("pc_kbdc", "kbd", pc_at_keyboards, STR_KBD_MICROSOFT_NATURAL)
|
||||
|
||||
/* internal ram */
|
||||
|
@ -132,15 +132,16 @@ MACHINE_CONFIG_START(ct486_state::ct486)
|
||||
|
||||
RAM(config, RAM_TAG).set_default_size("4M").set_extra_options("1M,2M,8M,16M,32M,64M");
|
||||
|
||||
at_keyboard_controller_device &keybc(AT_KEYBOARD_CONTROLLER(config, "keybc", XTAL(12'000'000)));
|
||||
keybc.system_reset_cb().set("cs4031", FUNC(cs4031_device::kbrst_w));
|
||||
keybc.gate_a20_cb().set("cs4031", FUNC(cs4031_device::gatea20_w));
|
||||
keybc.input_buffer_full_cb().set("cs4031", FUNC(cs4031_device::irq01_w));
|
||||
keybc.keyboard_clock_cb().set("pc_kbdc", FUNC(pc_kbdc_device::clock_write_from_mb));
|
||||
keybc.keyboard_data_cb().set("pc_kbdc", FUNC(pc_kbdc_device::data_write_from_mb));
|
||||
at_kbc_device_base &keybc(AT_KEYBOARD_CONTROLLER(config, "keybc", XTAL(12'000'000)));
|
||||
keybc.hot_res().set("cs4031", FUNC(cs4031_device::kbrst_w));
|
||||
keybc.gate_a20().set("cs4031", FUNC(cs4031_device::gatea20_w));
|
||||
keybc.kbd_irq().set("cs4031", FUNC(cs4031_device::irq01_w));
|
||||
keybc.kbd_clk().set("pc_kbdc", FUNC(pc_kbdc_device::clock_write_from_mb));
|
||||
keybc.kbd_data().set("pc_kbdc", FUNC(pc_kbdc_device::data_write_from_mb));
|
||||
|
||||
MCFG_DEVICE_ADD("pc_kbdc", PC_KBDC, 0)
|
||||
MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE("keybc", at_keyboard_controller_device, keyboard_clock_w))
|
||||
MCFG_PC_KBDC_OUT_DATA_CB(WRITELINE("keybc", at_keyboard_controller_device, keyboard_data_w))
|
||||
MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE("keybc", at_kbc_device_base, kbd_clk_w))
|
||||
MCFG_PC_KBDC_OUT_DATA_CB(WRITELINE("keybc", at_kbc_device_base, kbd_data_w))
|
||||
MCFG_PC_KBDC_SLOT_ADD("pc_kbdc", "kbd", pc_at_keyboards, STR_KBD_MICROSOFT_NATURAL)
|
||||
|
||||
MCFG_DEVICE_ADD("isabus", ISA16, 0)
|
||||
|
@ -153,8 +153,8 @@ void jazz_state::jazz(machine_config &config)
|
||||
|
||||
// pc keyboard controller?
|
||||
pc_kbdc_device &kbdc(PC_KBDC(config, "pc_kbdc", 0));
|
||||
kbdc.out_clock_cb().set(m_kbdc, FUNC(at_keyboard_controller_device::keyboard_clock_w));
|
||||
kbdc.out_data_cb().set(m_kbdc, FUNC(at_keyboard_controller_device::keyboard_data_w));
|
||||
kbdc.out_clock_cb().set(m_kbdc, FUNC(at_keyboard_controller_device::kbd_clk_w));
|
||||
kbdc.out_data_cb().set(m_kbdc, FUNC(at_keyboard_controller_device::kbd_data_w));
|
||||
|
||||
// keyboard port
|
||||
pc_kbdc_slot_device &kbd(PC_KBDC_SLOT(config, "kbd", 0));
|
||||
@ -164,9 +164,9 @@ void jazz_state::jazz(machine_config &config)
|
||||
|
||||
// at keyboard controller
|
||||
AT_KEYBOARD_CONTROLLER(config, m_kbdc, 12_MHz_XTAL);
|
||||
m_kbdc->system_reset_cb().set_inputline(m_maincpu, INPUT_LINE_RESET);
|
||||
m_kbdc->keyboard_clock_cb().set(kbdc, FUNC(pc_kbdc_device::clock_write_from_mb));
|
||||
m_kbdc->keyboard_data_cb().set(kbdc, FUNC(pc_kbdc_device::data_write_from_mb));
|
||||
m_kbdc->hot_res().set_inputline(m_maincpu, INPUT_LINE_RESET);
|
||||
m_kbdc->kbd_clk().set(kbdc, FUNC(pc_kbdc_device::clock_write_from_mb));
|
||||
m_kbdc->kbd_data().set(kbdc, FUNC(pc_kbdc_device::data_write_from_mb));
|
||||
|
||||
G364(config, m_ramdac, 0);
|
||||
}
|
||||
|
@ -135,14 +135,15 @@ MACHINE_CONFIG_START(at_mb_device::device_add_mconfig)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
|
||||
|
||||
at_keyboard_controller_device &keybc(AT_KEYBOARD_CONTROLLER(config, "keybc", 12_MHz_XTAL));
|
||||
keybc.system_reset_cb().set_inputline(":maincpu", INPUT_LINE_RESET);
|
||||
keybc.gate_a20_cb().set_inputline(":maincpu", INPUT_LINE_A20);
|
||||
keybc.input_buffer_full_cb().set("pic8259_master", FUNC(pic8259_device::ir1_w));
|
||||
keybc.keyboard_clock_cb().set("pc_kbdc", FUNC(pc_kbdc_device::clock_write_from_mb));
|
||||
keybc.keyboard_data_cb().set("pc_kbdc", FUNC(pc_kbdc_device::data_write_from_mb));
|
||||
keybc.hot_res().set_inputline(":maincpu", INPUT_LINE_RESET);
|
||||
keybc.gate_a20().set_inputline(":maincpu", INPUT_LINE_A20);
|
||||
keybc.kbd_irq().set("pic8259_master", FUNC(pic8259_device::ir1_w));
|
||||
keybc.kbd_clk().set("pc_kbdc", FUNC(pc_kbdc_device::clock_write_from_mb));
|
||||
keybc.kbd_data().set("pc_kbdc", FUNC(pc_kbdc_device::data_write_from_mb));
|
||||
|
||||
MCFG_DEVICE_ADD("pc_kbdc", PC_KBDC, 0)
|
||||
MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE("keybc", at_keyboard_controller_device, keyboard_clock_w))
|
||||
MCFG_PC_KBDC_OUT_DATA_CB(WRITELINE("keybc", at_keyboard_controller_device, keyboard_data_w))
|
||||
MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE("keybc", at_keyboard_controller_device, kbd_clk_w))
|
||||
MCFG_PC_KBDC_OUT_DATA_CB(WRITELINE("keybc", at_keyboard_controller_device, kbd_data_w))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user