From 78a897f07aaf24c9e3b0cbcfa52fe0f6678df5b9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 26 Apr 2023 01:42:23 +0200 Subject: [PATCH] Some minor fixes, the PS/2 mouse command F0h (set remote mode) is now implemented, the PS/2 mouse command F3h (set sample rate) now actually changes the host mouse polling rate, and the Intel SIO IB and ZB now forcibly initialize a keyboard and mouse IRQ latch if the board has a PS/2 keyboard controller, to simulate the presence of a latch external to the chip. --- src/chipset/intel_sio.c | 20 +++++++++++++++++--- src/device/kbc_at.c | 3 ++- src/device/kbc_at_dev.c | 4 ++-- src/device/mouse.c | 24 ++++++++++++++++++------ src/device/mouse_ps2.c | 14 +++++++++++++- src/include/86box/mouse.h | 2 ++ src/pic.c | 4 ++-- 7 files changed, 56 insertions(+), 15 deletions(-) diff --git a/src/chipset/intel_sio.c b/src/chipset/intel_sio.c index eb7aad983..3f253d832 100644 --- a/src/chipset/intel_sio.c +++ b/src/chipset/intel_sio.c @@ -200,9 +200,11 @@ sio_write(int func, int addr, uint8_t val, void *priv) dev->regs[addr] = val; break; case 0x4c: + dev->regs[addr] = (val & 0x7f); + break; case 0x4d: dev->regs[addr] = (val & 0x7f); - pic_mouse_latch(!!(val & 0x10)); + // pic_mouse_latch(!!(val & 0x10)); break; case 0x4f: dev->regs[addr] = val; @@ -394,7 +396,7 @@ sio_reset_hard(void *priv) dev->regs[0x4b] = 0x0f; dev->regs[0x4c] = 0x56; dev->regs[0x4d] = 0x40; - pic_mouse_latch(0x00); + // pic_mouse_latch(0x00); dev->regs[0x4e] = 0x07; dev->regs[0x4f] = 0x4f; dev->regs[0x57] = 0x04; @@ -544,7 +546,19 @@ sio_init(const device_t *info) // device_add(&i8254_sec_device); - pic_kbd_latch(0x01); + // pic_kbd_latch(0x01); + + /* The situation is as follow: SIO.AB has the IRQ 1 latch but SIO.IB and SIO.ZB do not, + and I suspect that because of that, the IRQ 12 latch on SIO.IB and SIO.ZB, while + evidently planned and documented in the datashet, was basically non-functional, and + motherboard manufacturers had to install their own latches to use PS/2 keyboards + and/or mice. One such example is the AMI Excalibur PCI Pentium, which never enables + the SIO.ZB's IRQ 12 latch but clearly expects one since otherwise, the PS/2 mouse + behaves erractically in the WinBIOS CMOS Setup. */ + if (machine_has_bus(machine, MACHINE_BUS_PS2)) { + pic_kbd_latch(0x01); + pic_mouse_latch(0x01); + } return dev; } diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 9b8a3de3d..24121e699 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -1024,7 +1024,7 @@ write64_ami(void *priv, uint8_t val) kbc_at_queue_add(dev, 0x28); kbc_at_queue_add(dev, 0x00); dev->state = STATE_KBC_OUT; - break; + return 0; case 0xa1: /* get controller version */ kbc_at_log("ATkbc: AMI - get controller version\n"); @@ -1118,6 +1118,7 @@ write64_ami(void *priv, uint8_t val) add_to_kbc_queue_front(dev, 0x00, 0, 0x00); return 0; + /* TODO: The ICS SB486PV sends command B4 but expects to read *TWO* bytes. */ case 0xb4: case 0xb5: /* set KBC lines P22-P23 (P2 bits 2-3) low */ kbc_at_log("ATkbc: set KBC lines P22-P23 (P2 bits 2-3) low\n"); diff --git a/src/device/kbc_at_dev.c b/src/device/kbc_at_dev.c index ca3dc1361..71a0b4e08 100644 --- a/src/device/kbc_at_dev.c +++ b/src/device/kbc_at_dev.c @@ -173,9 +173,9 @@ kbc_at_dev_reset(atkbc_dev_t *dev, int do_fa) if (do_fa) kbc_at_dev_queue_add(dev, 0xfa, 0); - dev->execute_bat(dev); - dev->state = DEV_STATE_MAIN_OUT; + + dev->execute_bat(dev); } atkbc_dev_t * diff --git a/src/device/mouse.c b/src/device/mouse.c index 13d9999c7..0ee714377 100644 --- a/src/device/mouse.c +++ b/src/device/mouse.c @@ -102,6 +102,8 @@ static int mouse_nbut; static int (*mouse_dev_poll)(int x, int y, int z, int b, void *priv); static void (*mouse_poll_ex)(void) = NULL; +static double sample_rate = 200.0; + #ifdef ENABLE_MOUSE_LOG int mouse_do_log = ENABLE_MOUSE_LOG; @@ -153,7 +155,7 @@ static void mouse_timer_poll(void *priv) { /* Poll at 255 Hz, maximum supported by PS/2 mic. */ - timer_on_auto(&mouse_timer, 1000000.0 / 255.0); + timer_on_auto(&mouse_timer, 1000000.0 / sample_rate); #ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */ if (gdbstub_step == GDBSTUB_EXEC) @@ -161,6 +163,15 @@ mouse_timer_poll(void *priv) mouse_process(); } +void +mouse_set_sample_rate(double new_rate) +{ + timer_stop(&mouse_timer); + + sample_rate = new_rate; + timer_on_auto(&mouse_timer, 1000000.0 / sample_rate); +} + void mouse_reset(void) { @@ -179,15 +190,16 @@ mouse_reset(void) if (mouse_type == 0) return; + timer_add(&mouse_timer, mouse_timer_poll, NULL, 0); + + /* Poll at 100 Hz, the default of a PS/2 mouse. */ + sample_rate = 100.0; + timer_on_auto(&mouse_timer, 1000000.0 / sample_rate); + mouse_curr = mouse_devices[mouse_type].device; if (mouse_curr != NULL) mouse_priv = device_add(mouse_curr); - - timer_add(&mouse_timer, mouse_timer_poll, NULL, 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. */ diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index 5563909ba..7d9730f28 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -133,7 +133,9 @@ static void ps2_set_defaults(atkbc_dev_t *dev) { dev->mode = MODE_STREAM; - dev->rate = 1; + dev->rate = 100; + mouse_set_sample_rate(100.0); + dev->resolution = 2; dev->flags &= 0x88; mouse_scan = 0; } @@ -177,6 +179,7 @@ ps2_write(void *priv) case 0xf3: /* set sample rate */ dev->rate = val; + mouse_set_sample_rate((double) val); kbc_at_dev_queue_add(dev, 0xfa, 0); /* Command response */ mouse_ps2_log("%s: Set sample rate [%02X]\n", dev->name, val); break; @@ -227,6 +230,7 @@ ps2_write(void *priv) case 0xea: /* set stream */ mouse_ps2_log("%s: Set stream\n", dev->name); dev->flags &= ~FLAG_CTRLDAT; + dev->mode = MODE_STREAM; mouse_scan = 1; kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */ break; @@ -238,6 +242,14 @@ ps2_write(void *priv) ps2_report_coordinates(dev, 0); break; + case 0xf0: /* set remote */ + mouse_ps2_log("%s: Set remote\n", dev->name); + dev->flags &= ~FLAG_CTRLDAT; + dev->mode = MODE_REMOTE; + mouse_scan = 1; + kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */ + break; + case 0xf2: /* read ID */ mouse_ps2_log("%s: Read ID\n", dev->name); kbc_at_dev_queue_add(dev, 0xfa, 0); diff --git a/src/include/86box/mouse.h b/src/include/86box/mouse.h index 317e267a0..b697c5d38 100644 --- a/src/include/86box/mouse.h +++ b/src/include/86box/mouse.h @@ -80,6 +80,8 @@ extern void mouse_poll(void); extern void mouse_bus_set_irq(void *priv, int irq); +extern void mouse_set_sample_rate(double new_rate); + extern char *mouse_get_name(int mouse); extern char *mouse_get_internal_name(int mouse); extern int mouse_get_from_internal_name(char *s); diff --git a/src/pic.c b/src/pic.c index 25a90e1c7..4f9b8aa8f 100644 --- a/src/pic.c +++ b/src/pic.c @@ -202,7 +202,7 @@ find_best_interrupt(pic_t *dev) intr = dev->interrupt = (ret == -1) ? 0x17 : ret; - if (dev->at && (ret != 1)) { + if (dev->at && (ret != -1)) { if (dev == &pic2) intr += 8; @@ -644,7 +644,7 @@ picint_common(uint16_t num, int level, int set) pic2.lines |= (num >> 8); /* Latch IRQ 12 if the mouse latch is enabled. */ - if (mouse_latch && (num & 0x1000)) + if ((num & 0x1000) && mouse_latch) pic2.lines |= 0x10; pic2.irr |= (num >> 8);