# Conflicts:
#	.ci/build.sh
This commit is contained in:
RichardG867
2023-04-07 22:41:45 -03:00
8 changed files with 353 additions and 123 deletions

View File

@@ -37,7 +37,6 @@
#include <86box/mem.h>
#include <86box/device.h>
#include <86box/machine.h>
#include <86box/m_xt_xi8088.h>
#include <86box/m_at_t3100e.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
@@ -81,23 +80,27 @@
#define KBC_VEN_IBM_MCA 0x08
#define KBC_VEN_QUADTEL 0x0c
#define KBC_VEN_TOSHIBA 0x10
#define KBC_VEN_XI8088 0x14
#define KBC_VEN_IBM_PS1 0x18
#define KBC_VEN_ACER 0x1c
#define KBC_VEN_INTEL_AMI 0x20
#define KBC_VEN_OLIVETTI 0x24
#define KBC_VEN_NCR 0x28
#define KBC_VEN_SAMSUNG 0x2c
#define KBC_VEN_ALI 0x30
#define KBC_VEN_PHOENIX 0x3c
#define KBC_VEN_IBM_PS1 0x14
#define KBC_VEN_ACER 0x18
#define KBC_VEN_INTEL_AMI 0x1c
#define KBC_VEN_OLIVETTI 0x20
#define KBC_VEN_NCR 0x24
#define KBC_VEN_PHOENIX 0x28
#define KBC_VEN_ALI 0x2c
#define KBC_VEN_TG 0x30
#define KBC_VEN_TG_GREEN 0x34
#define KBC_VEN_MASK 0x3c
enum {
KBC_STATE_RESET = 0,
KBC_STATE_NORMAL,
KBC_STATE_KBC_OUT,
KBC_STATE_KBC_PARAM,
KBC_STATE_KBD,
KBC_STATE_MOUSE
};
#define KBC_STATE_SCAN_KBD KBC_STATE_KBD
#define KBC_STATE_SCAN_MOUSE KBC_STATE_MOUSE
typedef struct {
uint8_t command, status, ib, out,
@@ -105,9 +108,9 @@ typedef struct {
output_port, old_output_port, key_command, output_locked,
ami_stat, want60, key_wantdata, ami_flags,
key_wantcmd, key_dat, mouse_wantcmd, mouse_dat,
kbc_state, kbd_state, mouse_state, pad;
kbc_state, kbd_state, mouse_state, pci;
uint16_t irq_levels, pad0;
uint16_t irq_levels, pad;
uint8_t mem[0x100];
@@ -584,6 +587,7 @@ static const scancode scancode_set3[512] = {
static void add_data_kbd(uint16_t val);
// #define ENABLE_KEYBOARD_AT_LOG 1
#ifdef ENABLE_KEYBOARD_AT_LOG
int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG;
@@ -708,7 +712,8 @@ add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_
{
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF))
if ((kbc_ven == KBC_VEN_AMI) || (kbc_ven == KBC_VEN_TG) ||
(kbc_ven == KBC_VEN_TG_GREEN) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF))
stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00);
else
stat_hi |= 0x10;
@@ -804,74 +809,238 @@ set_enable_mouse(atkbd_t *dev, uint8_t enable)
dev->mem[0x20] |= (enable ? 0x00 : 0x20);
}
static void
kbc_ibf_process(atkbd_t *dev)
{
/* IBF set, process both commands and data. */
dev->status &= ~STAT_IFULL;
dev->kbc_state = KBC_STATE_NORMAL;
if (dev->status & STAT_CD)
kbc_process_cmd(dev);
else {
set_enable_kbd(dev, 1);
kbc_queue_reset(4);
dev->key_wantcmd = 1;
dev->key_dat = dev->ib;
dev->kbc_state = KBC_STATE_SCAN_KBD;
}
}
static void
kbc_scan_kbd_at(atkbd_t *dev)
{
if (!(dev->mem[0x20] & 0x10)) {
/* Both OBF and IBF clear and keyboard is enabled. */
/* XT mode. */
if (dev->mem[0x20] & 0x20) {
if (dev->out_new != -1) {
add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00);
dev->out_new = -1;
dev->kbc_state = KBC_STATE_NORMAL;
} else if (dev->status & STAT_IFULL)
kbc_ibf_process(dev);
/* AT mode. */
} else {
// dev->t = dev->mem[0x28];
if (dev->mem[0x2e] != 0x00) {
// if (!(dev->t & 0x02))
// return;
dev->mem[0x2e] = 0x00;
}
dev->output_port &= 0xbf;
if (dev->out_new != -1) {
/* In our case, we never have noise on the line, so we can simplify this. */
/* Read data from the keyboard. */
if (dev->mem[0x20] & 0x40) {
if ((dev->mem[0x20] & 0x08) || (dev->input_port & 0x80))
add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00);
dev->mem[0x2d] = (dev->out_new == 0xf0) ? 0x80 : 0x00;
} else
add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00);
dev->out_new = -1;
dev->kbc_state = KBC_STATE_NORMAL;
} else if (dev->status & STAT_IFULL)
kbc_ibf_process(dev);
}
}
}
static void
kbc_poll_at(atkbd_t *dev)
{
switch (dev->kbc_state) {
case KBC_STATE_RESET:
if (dev->status & STAT_IFULL) {
dev->status = ((dev->status & 0x0f) | 0x10) & ~STAT_IFULL;
if ((dev->status & STAT_CD) && (dev->ib == 0xaa))
kbc_process_cmd(dev);
}
break;
case KBC_STATE_NORMAL:
if (dev->status & STAT_OFULL) {
/* OBF set, wait until it is cleared but still process commands. */
if ((dev->status & STAT_IFULL) && (dev->status & STAT_CD)) {
dev->status &= ~STAT_IFULL;
kbc_process_cmd(dev);
}
} else if (dev->status & STAT_IFULL)
kbc_ibf_process(dev);
else
kbc_scan_kbd_at(dev);
break;
case KBC_STATE_KBC_OUT:
/* Keyboard controller command want to output multiple bytes. */
if (dev->status & STAT_IFULL) {
/* Data from host aborts dumping. */
dev->kbc_state = KBC_STATE_NORMAL;
kbc_ibf_process(dev);
}
/* Do not continue dumping until OBF is clear. */
if (!(dev->status & STAT_OFULL)) {
kbd_log("ATkbc: %02X coming from channel 0\n", dev->out_new & 0xff);
add_to_kbc_queue_front(dev, key_ctrl_queue[key_ctrl_queue_start], 0, 0x00);
key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0x3f;
if (key_ctrl_queue_start == key_ctrl_queue_end)
dev->kbc_state = KBC_STATE_NORMAL;
}
break;
case KBC_STATE_KBC_PARAM:
/* Keyboard controller command wants data, wait for said data. */
if (dev->status & STAT_IFULL) {
/* Command written, abort current command. */
if (dev->status & STAT_CD)
dev->kbc_state = KBC_STATE_NORMAL;
dev->status &= ~STAT_IFULL;
kbc_process_cmd(dev);
}
break;
case KBC_STATE_SCAN_KBD:
kbc_scan_kbd_at(dev);
break;
}
}
static int
kbc_scan_kbd_ps2(atkbd_t *dev)
{
if (dev->out_new != -1) {
add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00);
dev->out_new = -1;
dev->kbc_state = KBC_STATE_NORMAL;
return 1;
}
return 0;
}
static int
kbc_scan_aux_ps2(atkbd_t *dev)
{
if (dev->out_new_mouse != -1) {
add_to_kbc_queue_front(dev, dev->out_new_mouse, 2, 0x00);
dev->out_new_mouse = -1;
dev->kbc_state = KBC_STATE_NORMAL;
return 1;
}
return 0;
}
static void
kbc_poll_ps2(atkbd_t *dev)
{
switch (dev->kbc_state) {
case KBC_STATE_RESET:
if (dev->status & STAT_IFULL) {
dev->status = ((dev->status & 0x0f) | 0x10) & ~STAT_IFULL;
if ((dev->status & STAT_CD) && (dev->ib == 0xaa))
kbc_process_cmd(dev);
}
break;
case KBC_STATE_NORMAL:
if (dev->status & STAT_IFULL)
kbc_ibf_process(dev);
else if (!(dev->status & STAT_OFULL)) {
if (dev->mem[0x20] & 0x20) {
if (!(dev->mem[0x20] & 0x10)) {
dev->output_port &= 0xbf;
if (kbc_scan_kbd_ps2(dev) == 0) {
if (dev->status & STAT_IFULL)
kbc_ibf_process(dev);
}
}
} else {
dev->output_port &= 0xf7;
if (dev->mem[0x20] & 0x10) {
if (kbc_scan_aux_ps2(dev) == 0) {
if (dev->status & STAT_IFULL)
kbc_ibf_process(dev);
}
} else {
dev->output_port &= 0xbf;
if (kbc_scan_kbd_ps2(dev) == 0) {
if (kbc_scan_aux_ps2(dev) == 0) {
if (dev->status & STAT_IFULL)
kbc_ibf_process(dev);
}
}
}
}
}
break;
case KBC_STATE_KBC_OUT:
/* Keyboard controller command want to output multiple bytes. */
if (dev->status & STAT_IFULL) {
/* Data from host aborts dumping. */
dev->kbc_state = KBC_STATE_NORMAL;
kbc_ibf_process(dev);
}
/* Do not continue dumping until OBF is clear. */
if (!(dev->status & STAT_OFULL)) {
kbd_log("ATkbc: %02X coming from channel 0\n", dev->out_new & 0xff);
add_to_kbc_queue_front(dev, key_ctrl_queue[key_ctrl_queue_start], 0, 0x00);
key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0x3f;
if (key_ctrl_queue_start == key_ctrl_queue_end)
dev->kbc_state = KBC_STATE_NORMAL;
}
break;
case KBC_STATE_KBC_PARAM:
/* Keyboard controller command wants data, wait for said data. */
if (dev->status & STAT_IFULL) {
/* Command written, abort current command. */
if (dev->status & STAT_CD)
dev->kbc_state = KBC_STATE_NORMAL;
dev->status &= ~STAT_IFULL;
kbc_process_cmd(dev);
}
break;
case KBC_STATE_SCAN_KBD:
(void) kbc_scan_kbd_ps2(dev);
break;
case KBC_STATE_SCAN_MOUSE:
(void) kbc_scan_aux_ps2(dev);
break;
}
}
/* TODO: State machines for controller, keyboard, and mouse. */
static void
kbd_poll(void *priv)
{
atkbd_t *dev = (atkbd_t *) priv;
int mouse_enabled;
timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC));
mouse_enabled = !(dev->mem[0x20] & 0x20) && ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF);
switch (dev->kbc_state) {
/* Reset state. */
case KBC_STATE_RESET:
if ((dev->status & STAT_IFULL) && (dev->status & STAT_CD) && (dev->ib == 0xaa))
kbc_process_cmd(dev);
break;
/* Process commands and/or monitor the attached devices. */
case KBC_STATE_NORMAL:
if (!(dev->status & STAT_OFULL)) {
if (dev->status & STAT_IFULL) {
dev->status &= ~STAT_IFULL;
if ((dev->status & STAT_CD) || dev->want60)
kbc_process_cmd(dev);
else if (!(dev->status & STAT_CD) && !dev->want60) {
dev->status &= ~STAT_IFULL;
set_enable_kbd(dev, 1);
kbc_queue_reset(4);
dev->key_wantcmd = 1;
dev->key_dat = dev->ib;
dev->kbc_state = KBC_STATE_KBD;
}
} else {
if (key_ctrl_queue_start != key_ctrl_queue_end) {
kbd_log("ATkbc: %02X coming from channel 0\n", dev->out_new & 0xff);
add_to_kbc_queue_front(dev, key_ctrl_queue[key_ctrl_queue_start], 0, 0x00);
key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0x3f;
} else if (mouse_enabled && (dev->out_new_mouse != -1)) {
kbd_log("ATkbc: %02X coming from channel 2\n", dev->out_new_mouse);
add_to_kbc_queue_front(dev, dev->out_new_mouse, 2, 0x00);
dev->out_new_mouse = -1;
} else if (!(dev->mem[0x20] & 0x10) && (dev->out_new != -1)) {
kbd_log("ATkbc: %02X coming from channel 1\n", dev->out_new);
add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00);
dev->out_new = -1;
}
}
}
break;
/* Wait for keyboard command response. */
case KBC_STATE_KBD:
if (!(dev->mem[0x20] & 0x10) && (dev->out_new != -1)) {
kbd_log("ATkbc: %02X coming from channel 1\n", dev->out_new);
add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00);
dev->out_new = -1;
dev->kbc_state = KBC_STATE_NORMAL;
}
break;
/* Wait for keyboard mouse response. */
case KBC_STATE_MOUSE:
if (mouse_enabled && (dev->out_new_mouse != -1)) {
kbd_log("ATkbc: %02X coming from channel 2\n", dev->out_new_mouse);
add_to_kbc_queue_front(dev, dev->out_new_mouse, 2, 0x00);
dev->out_new_mouse = -1;
dev->kbc_state = KBC_STATE_NORMAL;
}
break;
}
/* TODO: Use a fuction pointer for this (also needed to the AMI KBC mode switching)
and implement the password security state. */
if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)
kbc_poll_at(dev);
else
kbc_poll_ps2(dev);
if (dev->reset_delay) {
dev->reset_delay--;
@@ -1284,13 +1453,15 @@ write_cmd(atkbd_t *dev, uint8_t val)
/* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT);
PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch.
The AMIKEY firmware apparently uses this bit for something else. */
if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) {
if ((kbc_ven == KBC_VEN_AMI) || (kbc_ven == KBC_VEN_TG) ||
(kbc_ven == KBC_VEN_TG_GREEN) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) {
keyboard_mode &= ~CCB_PCMODE;
kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled");
}
if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)) {
if ((kbc_ven == KBC_VEN_AMI) || (kbc_ven == KBC_VEN_TG) ||
(kbc_ven == KBC_VEN_TG_GREEN) || ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)) {
/* Update the output port to mirror the IBF and OBF bits, if active. */
write_output(dev, (dev->output_port & 0x0f) | ((val & 0x03) << 4) | ((val & 0x20) ? 0xc0 : 0x00));
}
@@ -1392,7 +1563,16 @@ write64_generic(void *priv, uint8_t val)
0, 0x00);
dev->input_port = ((dev->input_port + 1) & 3) | (dev->input_port & 0xfc);
} else {
if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI))
if ((kbc_ven == KBC_VEN_TG) || (kbc_ven == KBC_VEN_TG_GREEN)) {
/* Bit 3, 2:
1, 1: TriGem logo;
1, 0: Garbled logo;
0, 1: Epson logo;
0, 0: Generic AMI logo. */
if (dev->pci)
fixed_bits |= 8;
add_to_kbc_queue_front(dev, dev->input_port | fixed_bits, 0, 0x00);
} else if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI))
#if 0
add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits) &
(((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef), 0, 0x00);
@@ -1409,6 +1589,7 @@ write64_generic(void *priv, uint8_t val)
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
kbd_log("ATkbc: write mouse output buffer\n");
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
return 0;
}
break;
@@ -1418,6 +1599,7 @@ write64_generic(void *priv, uint8_t val)
set_enable_mouse(dev, 1);
kbc_queue_reset(3);
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
return 0;
case 0xf0 ... 0xff:
@@ -1454,6 +1636,7 @@ write60_ami(void *priv, uint8_t val)
if (dev->secr_phase == 1) {
dev->mem_addr = val;
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
dev->secr_phase = 2;
} else if (dev->secr_phase == 2) {
dev->mem[dev->mem_addr] = val;
@@ -1490,27 +1673,36 @@ write64_ami(void *priv, uint8_t val)
case 0x40 ... 0x5f:
kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command);
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
return 0;
case 0xa0: /* copyright message */
kbc_queue_add(dev, 0x28, 0);
kbc_queue_add(dev, 0x00, 0);
dev->kbc_state = KBC_STATE_KBC_OUT;
break;
case 0xa1: /* get controller version */
kbd_log("ATkbc: AMI - get controller version\n");
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
if ((kbc_ven == KBC_VEN_TG) || (kbc_ven == KBC_VEN_TG_GREEN))
add_to_kbc_queue_front(dev, 'Z', 0, 0x00);
else if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) {
if (kbc_ven == KBC_VEN_ALI)
add_to_kbc_queue_front(dev, 'F', 0, 0x00);
else if ((dev->flags & KBC_VEN_MASK) == KBC_VEN_INTEL_AMI)
add_to_kbc_queue_front(dev, '5', 0, 0x00);
else if (is_pentium)
else if (cpu_64bitbus)
add_to_kbc_queue_front(dev, 'R', 0, 0x00);
else if (is486)
add_to_kbc_queue_front(dev, 'P', 0, 0x00);
else
add_to_kbc_queue_front(dev, 'H', 0, 0x00);
} else if (is386 && !is486)
add_to_kbc_queue_front(dev, 'B', 0, 0x00);
else if (!is386)
} else if (is386 && !is486) {
if (cpu_16bitbus)
add_to_kbc_queue_front(dev, 'D', 0, 0x00);
else
add_to_kbc_queue_front(dev, 'B', 0, 0x00);
} else if (!is386)
add_to_kbc_queue_front(dev, '8', 0, 0x00);
else
add_to_kbc_queue_front(dev, 'F', 0, 0x00);
@@ -1549,6 +1741,7 @@ write64_ami(void *priv, uint8_t val)
} else {
kbd_log("ATkbc: get extended controller RAM\n");
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
}
return 0;
@@ -1591,6 +1784,7 @@ write64_ami(void *priv, uint8_t val)
} else {
kbd_log("ATkbc: set extended controller RAM\n");
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
dev->secr_phase = 1;
}
return 0;
@@ -1631,6 +1825,7 @@ write64_ami(void *priv, uint8_t val)
case 0xc1: /* write input port */
kbd_log("ATkbc: AMI MegaKey - write input port\n");
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
return 0;
case 0xc4:
@@ -1765,6 +1960,7 @@ write64_quadtel(void *priv, uint8_t val)
case 0xcf: /*??? - sent by MegaPC BIOS*/
kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n");
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
return 0;
}
@@ -1829,6 +2025,7 @@ write64_toshiba(void *priv, uint8_t val)
case 0xb6: /* T3100e: Set colour / mono byte */
kbd_log("ATkbc: T3100e: Set colour / mono byte\n");
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
return 0;
case 0xb7: /* T3100e: Emulate PS/2 keyboard */
@@ -2073,6 +2270,10 @@ kbc_process_cmd(void *priv)
if (dev->status & STAT_CD) {
/* Controller command. */
dev->want60 = 0;
dev->kbc_state = KBC_STATE_NORMAL;
/* Clear the keyboard controller queue. */
kbc_queue_reset(0);
switch (dev->ib) {
/* Read data from KBC memory. */
@@ -2083,6 +2284,7 @@ kbc_process_cmd(void *priv)
/* Write data to KBC memory. */
case 0x60 ... 0x7f:
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
break;
case 0xaa: /* self-test */
@@ -2105,7 +2307,9 @@ kbc_process_cmd(void *priv)
} else {
if (dev->kbc_state != KBC_STATE_RESET) {
kbd_log("ATkbc: self-test reinitialization\n");
dev->input_port |= 0xff;
/* Yes, the firmware has an OR, but we need to make sure to keep any forcibly lowered bytes lowered. */
/* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */
dev->input_port = dev->input_port & 0xff;
write_output(dev, 0xcf);
}
@@ -2127,27 +2331,6 @@ kbc_process_cmd(void *priv)
dev->kbc_state = KBC_STATE_NORMAL;
add_to_kbc_queue_front(dev, 0x55, 0, 0x00);
#if 0
write_output(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x4b : 0xcf);
/* Always reinitialize all queues - the real hardware pulls keyboard and mouse
clocks high, which stops keyboard scanning. */
kbd_log("ATkbc: self-test reinitialization\n");
dev->out_new = dev->out_new_mouse = -1;
for (i = 0; i < 3; i++)
kbc_queue_reset(i);
keyboard_scan = 0;
mouse_scan = 0;
kbd_last_scan_code = 0x00;
dev->status &= ~STAT_OFULL;
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)
write_cmd(dev, 0x30 | STAT_SYSFLAG);
else
write_cmd(dev, 0x10 | STAT_SYSFLAG);
add_to_kbc_queue_front(dev, 0x55, 0, 0x00);
#endif
break;
case 0xab: /* interface test */
@@ -2168,6 +2351,7 @@ kbc_process_cmd(void *priv)
kbc_queue_add(dev, cmd_ac_conv[dev->mem[i + 0x20] & 0x0f], 0);
kbc_queue_add(dev, 0x39, 0);
}
dev->kbc_state = KBC_STATE_KBC_OUT;
}
break;
@@ -2184,6 +2368,7 @@ kbc_process_cmd(void *priv)
case 0xc7: /* set port1 bits */
kbd_log("ATkbc: Phoenix - set port1 bits\n");
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
break;
case 0xca: /* read keyboard mode */
@@ -2194,6 +2379,7 @@ kbc_process_cmd(void *priv)
case 0xcb: /* set keyboard mode */
kbd_log("ATkbc: AMI - set keyboard mode\n");
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
break;
case 0xd0: /* read output port */
@@ -2207,11 +2393,13 @@ kbc_process_cmd(void *priv)
case 0xd1: /* write output port */
kbd_log("ATkbc: write output port\n");
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
break;
case 0xd2: /* write keyboard output buffer */
kbd_log("ATkbc: write keyboard output buffer\n");
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
break;
case 0xdd: /* disable A20 address line */
@@ -2245,6 +2433,7 @@ kbc_process_cmd(void *priv)
} else if (dev->want60) {
/* Write data to controller. */
dev->want60 = 0;
dev->kbc_state = KBC_STATE_NORMAL;
switch (dev->command) {
case 0x60 ... 0x7f:
@@ -2340,6 +2529,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
}
write_output(dev, val | 0x01);
dev->want60 = 0;
dev->kbc_state = KBC_STATE_NORMAL;
return;
}
break;
@@ -2349,6 +2539,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
if (val == 0xd1) {
kbd_log("ATkbc: write output port\n");
dev->want60 = 1;
dev->kbc_state = KBC_STATE_KBC_PARAM;
dev->command = 0xd1;
return;
}
@@ -2377,7 +2568,7 @@ kbd_read(uint16_t port, void *priv)
This also means that in AT mode, the IRQ is level-triggered. */
if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)
picintc(1 << 1);
else if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) {
else if (pic_get_pci_flag() || ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF)) {
/* PS/2 MCA: Latched as level-sensitive until port 0x60 is read (and with it, OBF is cleared),
in accordance with the IBM PS/2 Model 80 Technical Reference Manual. */
kbc_irq(dev, dev->irq_levels, 0);
@@ -2412,7 +2603,7 @@ kbd_reset(void *priv)
dev->key_wantdata = 0;
/* Set up the correct Video Type bits. */
if ((kbc_ven == KBC_VEN_XI8088) || (kbc_ven == KBC_VEN_ACER))
if (!is286 || (kbc_ven == KBC_VEN_ACER))
dev->input_port = video_is_mda() ? 0xb0 : 0xf0;
else
dev->input_port = video_is_mda() ? 0xf0 : 0xb0;
@@ -2493,6 +2684,7 @@ kbd_init(const device_t *info)
memset(dev, 0x00, sizeof(atkbd_t));
dev->flags = info->local;
dev->pci = !!(info->flags & DEVICE_PCI);
video_reset(gfxcard[0]);
kbd_reset(dev);
@@ -2512,7 +2704,6 @@ kbd_init(const device_t *info)
case KBC_VEN_GENERIC:
case KBC_VEN_NCR:
case KBC_VEN_IBM_PS1:
case KBC_VEN_XI8088:
dev->write64_ven = write64_generic;
break;
@@ -2522,8 +2713,9 @@ kbd_init(const device_t *info)
case KBC_VEN_AMI:
case KBC_VEN_INTEL_AMI:
case KBC_VEN_SAMSUNG:
case KBC_VEN_ALI:
case KBC_VEN_TG:
case KBC_VEN_TG_GREEN:
dev->write60_ven = write60_ami;
dev->write64_ven = write64_ami;
break;
@@ -2577,11 +2769,11 @@ const device_t keyboard_at_ami_device = {
.config = NULL
};
const device_t keyboard_at_samsung_device = {
.name = "PC/AT Keyboard (Samsung)",
.internal_name = "keyboard_at_samsung",
const device_t keyboard_at_tg_ami_device = {
.name = "PC/AT Keyboard (TriGem AMI)",
.internal_name = "keyboard_at_tg_ami",
.flags = 0,
.local = KBC_TYPE_ISA | KBC_VEN_SAMSUNG,
.local = KBC_TYPE_ISA | KBC_VEN_TG,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
@@ -2679,7 +2871,7 @@ const device_t keyboard_ps2_xi8088_device = {
.name = "PS/2 Keyboard (Xi8088)",
.internal_name = "keyboard_ps2_xi8088",
.flags = 0,
.local = KBC_TYPE_PS2_1 | KBC_VEN_XI8088,
.local = KBC_TYPE_PS2_1 | KBC_VEN_GENERIC,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
@@ -2703,6 +2895,20 @@ const device_t keyboard_ps2_ami_device = {
.config = NULL
};
const device_t keyboard_ps2_tg_ami_device = {
.name = "PS/2 Keyboard (TriGem AMI)",
.internal_name = "keyboard_ps2_tg_ami",
.flags = 0,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_TG,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_mca_device = {
.name = "PS/2 Keyboard",
.internal_name = "keyboard_ps2_mca",
@@ -2801,6 +3007,20 @@ const device_t keyboard_ps2_intel_ami_pci_device = {
.config = NULL
};
const device_t keyboard_ps2_tg_ami_pci_device = {
.name = "PS/2 Keyboard (TriGem AMI)",
.internal_name = "keyboard_ps2_tg_ami_pci",
.flags = DEVICE_PCI,
.local = KBC_TYPE_PS2_NOREF | KBC_VEN_TG,
.init = kbd_init,
.close = kbd_close,
.reset = kbd_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_acer_pci_device = {
.name = "PS/2 Keyboard (Acer 90M002A)",
.internal_name = "keyboard_ps2_acer_pci",

View File

@@ -152,8 +152,8 @@ mouse_close(void)
static void
mouse_timer_poll(void *priv)
{
/* Poll at 3600 Hz. */
timer_on_auto(&mouse_timer, 277.0 + (7.0 / 9.0));
/* Poll at 255 Hz, maximum supported by PS/2 mic. */
timer_on_auto(&mouse_timer, 1000000.0 / 255.0);
#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */
if (gdbstub_step == GDBSTUB_EXEC)
@@ -186,8 +186,8 @@ mouse_reset(void)
timer_add(&mouse_timer, mouse_timer_poll, NULL, 0);
/* Poll at 3600 Hz. */
timer_on_auto(&mouse_timer, 277.0 + (7.0 / 9.0));
/* Poll at 255 Hz, maximum supported by PS/2 mic. */
timer_on_auto(&mouse_timer, 1000000.0 / 255.0);
}
/* Callback from the hardware driver. */

View File

@@ -159,7 +159,7 @@ extern const device_t keyboard_xt_zenith_device;
extern const device_t keyboard_xtclone_device;
extern const device_t keyboard_at_device;
extern const device_t keyboard_at_ami_device;
extern const device_t keyboard_at_samsung_device;
extern const device_t keyboard_at_tg_ami_device;
extern const device_t keyboard_at_toshiba_device;
extern const device_t keyboard_at_olivetti_device;
extern const device_t keyboard_at_ncr_device;
@@ -168,6 +168,8 @@ extern const device_t keyboard_ps2_ps1_device;
extern const device_t keyboard_ps2_ps1_pci_device;
extern const device_t keyboard_ps2_xi8088_device;
extern const device_t keyboard_ps2_ami_device;
extern const device_t keyboard_ps2_tg_ami_device;
extern const device_t keyboard_ps2_tg_ami_green_device;
extern const device_t keyboard_ps2_olivetti_device;
extern const device_t keyboard_ps2_mca_device;
extern const device_t keyboard_ps2_mca_2_device;
@@ -177,6 +179,7 @@ extern const device_t keyboard_ps2_ami_pci_device;
extern const device_t keyboard_ps2_intel_ami_pci_device;
extern const device_t keyboard_ps2_acer_pci_device;
extern const device_t keyboard_ps2_ali_pci_device;
extern const device_t keyboard_ps2_tg_ami_pci_device;
#endif /*EMU_DEVICE_H*/
extern void keyboard_init(void);

View File

@@ -43,6 +43,7 @@ extern void pic_elcr_write(uint16_t port, uint8_t val, void *priv);
extern uint8_t pic_elcr_read(uint16_t port, void *priv);
extern void pic_set_shadow(int sh);
extern int pic_get_pci_flag(void);
extern void pic_set_pci_flag(int pci);
extern void pic_set_pci(void);
extern void pic_init(void);

View File

@@ -220,7 +220,7 @@ machine_at_spc6000a_init(const machine_t *model)
if (fdc_type == FDC_INTERNAL)
device_add(&fdc_at_device);
device_add(&keyboard_at_samsung_device);
device_add(&keyboard_at_ami_device);
return ret;
}
@@ -1657,7 +1657,7 @@ machine_at_actionpc2600_init(const machine_t *model)
device_add(&umc_8886af_device);
device_add(&um8669f_device);
device_add(&intel_flash_bxt_device);
device_add(&keyboard_at_ami_device);
device_add(&keyboard_ps2_tg_ami_device);
return ret;
}
@@ -1782,7 +1782,7 @@ machine_at_tg486gp_init(const machine_t *model)
device_add(&ali1435_device);
device_add(&sst_flash_29ee010_device);
device_add(&keyboard_ps2_ami_device);
device_add(&keyboard_ps2_tg_ami_device);
return ret;
}
@@ -1806,7 +1806,7 @@ machine_at_tg486g_init(const machine_t *model)
device_add(&sis_85c471_device);
device_add(&ide_isa_device);
device_add(&fdc37c651_ide_device);
device_add(&keyboard_ps2_intel_ami_pci_device);
device_add(&keyboard_ps2_tg_ami_pci_device);
return ret;
}

View File

@@ -237,7 +237,7 @@ machine_at_hawk_init(const machine_t *model)
pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&keyboard_ps2_tg_ami_pci_device);
device_add(&i430fx_device);
device_add(&piix_device);
device_add(&fdc37c665_device);

View File

@@ -7036,7 +7036,7 @@ const machine_t machines[] = {
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_PCI,
.bus_flags = MACHINE_PS2_PCI,
.flags = MACHINE_IDE_DUAL | MACHINE_APM,
.ram = {
.min = 1024,

View File

@@ -284,6 +284,12 @@ pic_set_shadow(int sh)
shadow = sh;
}
int
pic_get_pci_flag(void)
{
return pic_pci;
}
void
pic_set_pci_flag(int pci)
{