diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 6b7d46987..7f40203b4 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -88,6 +88,7 @@ extern const device_t um8669f_device; extern const device_t um8669f_ide_device; extern const device_t um8669f_ide_sec_device; extern const device_t via_vt82c686_sio_device; +extern const device_t vl82c113_device; extern const device_t w83787f_88h_device; extern const device_t w83787f_device; extern const device_t w83787f_ide_device; diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index e81eae1f1..4632e00df 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -644,7 +644,12 @@ machine_at_cmdsl386sx25_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(&gd5402_onboard_device); - machine_at_scamp_common_init(model, 1); + machine_at_common_ide_init(model); + + device_add(&ali5105_device); /* The FDC is part of the ALi M5105. */ + device_add(&vl82c113_device); /* The keyboard controller is part of the VL82c113. */ + + device_add(&vlsi_scamp_device); return ret; } diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 966639476..82f946314 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -375,7 +375,7 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems if (gfxcard[0] == VID_INTERNAL) device_add(&gd5428_onboard_device); - device_add(&keyboard_ps2_ami_device); + device_add(&vl82c113_device); device_add(&fdc37c651_ide_device); return ret; diff --git a/src/sio/CMakeLists.txt b/src/sio/CMakeLists.txt index dff0fcd0f..ecb780a9b 100644 --- a/src/sio/CMakeLists.txt +++ b/src/sio/CMakeLists.txt @@ -20,7 +20,7 @@ add_library(sio OBJECT sio_acc3221.c sio_ali5123.c sio_f82c710.c sio_82091aa.c sio_prime3b.c sio_prime3c.c sio_w83787f.c sio_w83877f.c sio_w83977f.c sio_um8663f.c sio_um8669f.c - sio_vt82c686.c) + sio_vl82c113.c sio_vt82c686.c) if(SIO_DETECT) target_sources(sio PRIVATE sio_detect.c) diff --git a/src/sio/sio_vl82c113.c b/src/sio/sio_vl82c113.c new file mode 100644 index 000000000..6a02ef359 --- /dev/null +++ b/src/sio/sio_vl82c113.c @@ -0,0 +1,163 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the VLSI VL82c113 Combination I/O Chip. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/keyboard.h> +#include <86box/nvr.h> +#include <86box/sio.h> + +typedef struct vl82c113_t { + uint8_t index; + uint8_t nvr_enabled; + uint8_t regs[3]; + uint8_t pad; + uint16_t nvr_base; + int cur_reg; + nvr_t *nvr; + void *kbc; +} vl82c113_t; + +static void +vl82c113_nvr_handler(vl82c113_t *dev) +{ + const uint8_t nvr_enabled = (dev->regs[0x00]) & 0x01; + const uint16_t nvr_base = ((dev->regs[0x01] << 8) | dev->regs[0x00]) & 0xfffe; + + if ((nvr_enabled != dev->nvr_enabled) || (nvr_base != dev->nvr_base)) { + if (dev->nvr_enabled && (dev->nvr_base != 0x0000)) + nvr_at_handler(0, dev->nvr_base, dev->nvr); + + dev->nvr_enabled = nvr_enabled; + dev->nvr_base = nvr_base; + + if (dev->nvr_enabled && (dev->nvr_base != 0x0000)) + nvr_at_handler(1, dev->nvr_base, dev->nvr); + } +} + +static void +vl82c113_out(uint16_t port, uint8_t val, void *priv) +{ + vl82c113_t *dev = (vl82c113_t *) priv; + + if (port == 0xec) + dev->index = val; + else if ((dev->index >= 0x1b) && (dev->index <= 0x1d)) { + const uint8_t index = dev->index - 0x1b; + const uint8_t valxor = dev->regs[index] ^ val; + + dev->regs[index] = val; + + switch (index) { + default: + break; + + case 0x00: + case 0x01: + if (valxor) + vl82c113_nvr_handler(dev); + break; + + case 0x02: + if (valxor & 0x02) + kbc_at_set_ps2(dev->kbc, !(val & 0x02)); + break; + } + } +} + +static uint8_t +vl82c113_in(uint16_t port, void *priv) +{ + const vl82c113_t *dev = (vl82c113_t *) priv; + uint8_t ret = 0xff; + + if (port == 0xed) { + if ((dev->index >= 0x1b) && (dev->index <= 0x1d)) + ret = dev->regs[dev->index - 0x1b]; + else if (dev->index == 0x1f) + /* REVID */ + ret = 0xc0; + } + + return ret; +} + +static void +vl82c113_reset(void *priv) +{ + vl82c113_t *dev = (vl82c113_t *) priv; + + memset(dev->regs, 0x00, sizeof(dev->regs)); + + dev->regs[0x00] = 0x71; + dev->regs[0x01] = 0x00; + + dev->regs[0x02] = 0xc3; + + kbc_at_set_ps2(dev->kbc, 0); + + vl82c113_nvr_handler(dev); +} + +static void +vl82c113_close(void *priv) +{ + vl82c113_t *dev = (vl82c113_t *) priv; + + free(dev); +} + +static void * +vl82c113_init(const device_t *info) +{ + vl82c113_t *dev = (vl82c113_t *) calloc(1, sizeof(vl82c113_t)); + + dev->nvr = device_add(&at_nvr_device); + + dev->nvr_enabled = 1; + dev->nvr_base = 0x0070; + + /* Commands are standard. */ + dev->kbc = device_add(&keyboard_at_device); + + vl82c113_reset(dev); + + io_sethandler(0x00ec, 0x0002, vl82c113_in, NULL, NULL, vl82c113_out, NULL, NULL, dev); + + return dev; +} + +const device_t vl82c113_device = { + .name = "VLSI VL82c113 Combination I/O", + .internal_name = "vl82c113", + .flags = 0, + .local = 0, + .init = vl82c113_init, + .close = vl82c113_close, + .reset = vl82c113_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; +