cs4031.c: emulated the chipsets ability to intercept gate a20 and keyboard reset commands

This commit is contained in:
Dirk Best 2013-08-03 12:44:02 +00:00
parent 600a425123
commit 9aaabd58ea
2 changed files with 133 additions and 17 deletions

View File

@ -17,9 +17,6 @@
- MC14818 RTC
TODO:
- The chipset has the ability to intercept the GATEA20 and
RESET commands sent to the 8042 keyboard controller,
this is not emulated yet
- No emulation of memory parity checks
- Move IPC core to its own file so it can be shared with
other chipsets
@ -38,7 +35,7 @@
#define LOG_REGISTER 1
#define LOG_MEMORY 1
#define LOG_IO 1
#define LOG_KEYBOARD 0
#define LOG_KEYBOARD 0
//**************************************************************************
@ -215,6 +212,9 @@ cs4031_device::cs4031_device(const machine_config &mconfig, const char *tag, dev
m_kbrst(1),
m_ext_gatea20(0),
m_fast_gatea20(0),
m_emu_gatea20(0),
m_keybc_d1_written(false),
m_keybc_data_blocked(false),
m_address(0),
m_address_valid(false)
{
@ -711,9 +711,35 @@ void cs4031_device::update_write_regions()
// KEYBOARD / 8042
//**************************************************************************
void cs4031_device::a20m()
void cs4031_device::emulated_kbreset(int state)
{
m_write_a20m(m_fast_gatea20 | m_ext_gatea20);
if (BIT(m_registers[SOFT_RESET_AND_GATEA20], 4))
{
// kbreset (input) is active low
// cpureset (output) is active high
m_write_cpureset(!state);
}
}
void cs4031_device::emulated_gatea20(int state)
{
if (BIT(m_registers[SOFT_RESET_AND_GATEA20], 5))
{
m_emu_gatea20 = state;
a20m();
}
}
void cs4031_device::fast_gatea20(int state)
{
m_fast_gatea20 = state;
a20m();
}
void cs4031_device::keyboard_gatea20(int state)
{
m_ext_gatea20 = state;
a20m();
}
READ8_MEMBER( cs4031_device::keyb_status_r )
@ -724,12 +750,83 @@ READ8_MEMBER( cs4031_device::keyb_status_r )
return m_keybc->status_r(space, 0);
}
WRITE8_MEMBER( cs4031_device::keyb_command_blocked_w )
{
// command is optionally blocked
if (!BIT(m_registers[SOFT_RESET_AND_GATEA20], 7))
m_keybc->command_w(space, 0, data);
}
WRITE8_MEMBER( cs4031_device::keyb_command_w )
{
if (LOG_KEYBOARD)
logerror("cs4031_device::keyb_command_w: %02x\n", data);
m_keybc->command_w(space, 0, data);
m_keybc_d1_written = false;
switch (data)
{
// self-test
case 0xaa:
emulated_kbreset(1);
emulated_gatea20(1);
// self-test is never blocked
m_keybc->command_w(space, 0, data);
break;
case 0xd1:
m_keybc_d1_written = true;
keyb_command_blocked_w(space, 0, data);
break;
case 0xf0:
case 0xf1:
case 0xf2:
case 0xf4:
case 0xf5:
case 0xf6:
case 0xf8:
case 0xf9:
case 0xfa:
case 0xfc:
case 0xfd:
case 0xfe:
// toggle keyboard reset?
if (!BIT(data, 0))
{
emulated_kbreset(0);
emulated_kbreset(1);
}
// toggle gatea20?
if (!BIT(data, 1))
{
emulated_gatea20(0);
emulated_gatea20(1);
}
keyb_command_blocked_w(space, 0, data);
break;
case 0xff:
// last data write was blocked?
if (m_keybc_data_blocked)
{
m_keybc_data_blocked = false;
keyb_command_blocked_w(space, 0, data);
}
else
m_keybc->command_w(space, 0, data);
break;
// everything else goes directly to the keyboard controller
default:
m_keybc->command_w(space, 0, data);
break;
}
}
READ8_MEMBER( cs4031_device::keyb_data_r )
@ -745,7 +842,18 @@ WRITE8_MEMBER( cs4031_device::keyb_data_w )
if (LOG_KEYBOARD)
logerror("cs4031_device::keyb_data_w: %02x\n", data);
m_keybc->data_w(space, 0, data);
// data is blocked only for d1 command
if (BIT(m_registers[SOFT_RESET_AND_GATEA20], 7) && m_keybc_d1_written)
{
m_keybc_data_blocked = true;
emulated_kbreset(BIT(data, 0));
emulated_gatea20(BIT(data, 1));
}
else
{
m_keybc_data_blocked = false;
m_keybc->data_w(space, 0, data);
}
}
WRITE_LINE_MEMBER( cs4031_device::gatea20_w )
@ -753,11 +861,7 @@ WRITE_LINE_MEMBER( cs4031_device::gatea20_w )
if (LOG_KEYBOARD)
logerror("cs4031_device::gatea20_w: %u\n", state);
if (m_ext_gatea20 != state)
{
m_ext_gatea20 = state;
a20m();
}
keyboard_gatea20(state);
}
WRITE_LINE_MEMBER( cs4031_device::kbrst_w )
@ -765,9 +869,10 @@ WRITE_LINE_MEMBER( cs4031_device::kbrst_w )
if (LOG_KEYBOARD)
logerror("cs4031_device::kbrst_w: %u\n", state);
// active low signal
// convert to active low signal (gets inverted in at_keybc.c)
state = (state == ASSERT_LINE ? 0 : 1);
// detect transition
if (m_kbrst == 1 && state == 0)
{
m_write_cpureset(1);
@ -789,8 +894,7 @@ WRITE8_MEMBER( cs4031_device::sysctrl_w )
if (LOG_IO)
logerror("cs4031_device::sysctrl_w: %u\n", data);
m_fast_gatea20 = BIT(data, 1);
a20m();
fast_gatea20(BIT(data, 1));
if (m_cpureset == 0 && BIT(data, 0))
{

View File

@ -148,6 +148,7 @@ public:
DECLARE_WRITE8_MEMBER( keyb_data_w );
DECLARE_READ8_MEMBER( keyb_status_r );
DECLARE_WRITE8_MEMBER( keyb_command_w );
DECLARE_WRITE8_MEMBER( keyb_command_blocked_w );
// input lines
DECLARE_WRITE_LINE_MEMBER( irq01_w ) { m_intc1->ir1_w(state); }
@ -203,8 +204,16 @@ private:
offs_t page_offset();
void set_dma_channel(int channel, bool state);
void update_dma_clock();
void nmi();
void a20m();
// gate a20, various sources are ored
void a20m() { m_write_a20m(m_fast_gatea20 | m_ext_gatea20 | m_emu_gatea20); }
void emulated_kbreset(int state);
void emulated_gatea20(int state);
void fast_gatea20(int state);
void keyboard_gatea20(int state);
void update_read_region(int index, const char *region, offs_t start, offs_t end);
void update_write_region(int index, const char *region, offs_t start, offs_t end);
@ -247,6 +256,9 @@ private:
int m_kbrst;
int m_ext_gatea20;
int m_fast_gatea20;
int m_emu_gatea20;
bool m_keybc_d1_written;
bool m_keybc_data_blocked;
// chipset configuration
static const char* m_register_names[];