From 39a46797d26f64dabe8dca82813882d3978b83cc Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 7 Jul 2020 20:43:28 +0200 Subject: [PATCH] Fixed shadowing on the OPTi 82c5x7, OPTi 82c495 now has Port 92h, and implemented the OPTi 82c611/611A VLB IDE controlled required by the Excalibur. --- src/chipset/opti495.c | 14 +- src/chipset/opti5x7.c | 40 ++--- src/disk/hdc_ide_opti611.c | 322 +++++++++++++++++++++++++++++++++++ src/include/86box/hdc.h | 6 +- src/machine/m_at_socket4_5.c | 10 +- src/sio/sio_fdc37c661.c | 1 - src/win/Makefile.mingw | 2 +- 7 files changed, 363 insertions(+), 32 deletions(-) create mode 100644 src/disk/hdc_ide_opti611.c diff --git a/src/chipset/opti495.c b/src/chipset/opti495.c index c3fa1bda4..688bbf492 100644 --- a/src/chipset/opti495.c +++ b/src/chipset/opti495.c @@ -131,12 +131,13 @@ opti495_write(uint16_t addr, uint8_t val, void *priv) switch (addr) { case 0x22: + opti495_log("[%04X:%08X] [W] dev->idx = %02X\n", CS, cpu_state.pc, val); dev->idx = val; break; case 0x24: - if ((dev->idx >= 0x20) && (dev->idx <= 0x2c)) { + if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) { dev->regs[dev->idx] = val; - opti495_log("dev->regs[%04x] = %08x\n", dev->idx, val); + opti495_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val); switch(dev->idx) { case 0x21: @@ -168,9 +169,14 @@ opti495_read(uint16_t addr, void *priv) opti495_t *dev = (opti495_t *) priv; switch (addr) { + case 0x22: + opti495_log("[%04X:%08X] [R] dev->idx = %02X\n", CS, cpu_state.pc, ret); + break; case 0x24: - if ((dev->idx >= 0x20) && (dev->idx <= 0x2c)) + if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) { ret = dev->regs[dev->idx]; + opti495_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret); + } break; case 0xe1: case 0xe2: @@ -197,6 +203,8 @@ opti495_init(const device_t *info) opti495_t *dev = (opti495_t *) malloc(sizeof(opti495_t)); memset(dev, 0, sizeof(opti495_t)); + device_add(&port_92_device); + io_sethandler(0x0022, 0x0001, opti495_read, NULL, NULL, opti495_write, NULL, NULL, dev); io_sethandler(0x0024, 0x0001, opti495_read, NULL, NULL, opti495_write, NULL, NULL, dev); diff --git a/src/chipset/opti5x7.c b/src/chipset/opti5x7.c index ef43b5343..af224437d 100644 --- a/src/chipset/opti5x7.c +++ b/src/chipset/opti5x7.c @@ -45,35 +45,38 @@ static void opti5x7_recalc(opti5x7_t *dev) { uint32_t base; - uint32_t i, j, shflags = 0; + uint32_t i, shflags = 0; uint32_t reg, lowest_bit; - uint32_t write = 0; + + shadowbios = 0; + shadowbios_write = 0; for (i = 0; i < 8; i++) { - j = i / 2.01; /*Probably not a great way of doing this, but it does work*/ - base = 0xc0000 + (j << 14); - - lowest_bit = j * 2; - reg = 0x04 + ((base >> 16) & 0x01); - - shflags = (dev->regs[reg] & (1 << lowest_bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - shflags |= (dev->regs[reg] & (1 << (lowest_bit + 1))) ? MEM_WRITE_INTERNAL : write; - write = (dev->regs[reg] & (1 << lowest_bit)) ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY; - mem_set_mem_state(base, 0x4000, shflags); + base = 0xc0000 + (i << 14); + + lowest_bit = (i << 1) & 0x07; + reg = 0x04 + ((base >> 16) & 0x01); + + shflags = (dev->regs[reg] & (1 << lowest_bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + shflags |= (dev->regs[reg] & (1 << (lowest_bit + 1))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state(base, 0x4000, shflags); } + shadowbios |= !!(dev->regs[0x06] & 0x05); + shadowbios_write |= !!(dev->regs[0x06] & 0x0a); + shflags = (dev->regs[0x06] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - shflags |= (dev->regs[0x06] & 0x02) ? MEM_WRITE_INTERNAL : write; - write = (dev->regs[0x06] & 0x01) ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY; + shflags |= (dev->regs[0x06] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; mem_set_mem_state(0xe0000, 0x10000, shflags); shflags = (dev->regs[0x06] & 0x04) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - shflags |= (dev->regs[0x06] & 0x08) ? MEM_WRITE_INTERNAL : write; - write = (dev->regs[0x06] & 0x04) ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY; + shflags |= (dev->regs[0x06] & 0x08) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; mem_set_mem_state(0xf0000, 0x10000, shflags); flushmmucache(); } + + static void opti5x7_write(uint16_t addr, uint8_t val, void *priv) { @@ -90,7 +93,7 @@ opti5x7_write(uint16_t addr, uint8_t val, void *priv) case 0x02: cpu_cache_ext_enabled = !!(dev->regs[0x02] & 0x04 & 0x08); break; - + case 0x04: case 0x05: case 0x06: @@ -138,9 +141,6 @@ opti5x7_init(const device_t *info) io_sethandler(0x0024, 0x0001, opti5x7_read, NULL, NULL, opti5x7_write, NULL, NULL, dev); dev->port_92 = device_add(&port_92_device); -// pclog("OPTi 5x7 init\n"); - opti5x7_recalc(dev); - return dev; } diff --git a/src/disk/hdc_ide_opti611.c b/src/disk/hdc_ide_opti611.c new file mode 100644 index 000000000..19c298396 --- /dev/null +++ b/src/disk/hdc_ide_opti611.c @@ -0,0 +1,322 @@ +/* + * 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 OPTi 82C611/611A VLB IDE controller. + + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/keyboard.h> +#include <86box/mem.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> + + +typedef struct +{ + uint8_t tries, + in_cfg, cfg_locked, + regs[19]; +} opti611_t; + + +static void opti611_ide_handler(opti611_t *dev); + + +static void +opti611_cfg_write(uint16_t addr, uint8_t val, void *priv) +{ + opti611_t *dev = (opti611_t *) priv; + + addr &= 0x0007; + + switch (addr) { + case 0x0000: + case 0x0001: + dev->regs[((dev->regs[0x06] & 0x01) << 4) + addr] = val; + break; + case 0x0002: + dev->regs[0x12] = (val & 0xc1) | 0x02; + if (val & 0xc0) { + dev->in_cfg = 0; + opti611_ide_handler(dev); + } + if (val & 0x40) + dev->cfg_locked = 1; + break; + case 0x0003: + dev->regs[0x03] = (val & 0xdf); + break; + case 0x0005: + dev->regs[0x05] = (dev->regs[0x05] & 0x78) | (val & 0x87); + break; + case 0x0006: + dev->regs[0x06] = val; + break; + } +} + + +static void +opti611_cfg_writew(uint16_t addr, uint16_t val, void *priv) +{ + opti611_cfg_write(addr, val & 0xff, priv); + opti611_cfg_write(addr + 1, val >> 8, priv); +} + + +static void +opti611_cfg_writel(uint16_t addr, uint32_t val, void *priv) +{ + opti611_cfg_writew(addr, val & 0xffff, priv); + opti611_cfg_writew(addr + 2, val >> 16, priv); +} + + +static uint8_t +opti611_cfg_read(uint16_t addr, void *priv) +{ + uint8_t ret = 0xff; + opti611_t *dev = (opti611_t *) priv; + + addr &= 0x0007; + + switch (addr) { + case 0x0000: + case 0x0001: + ret = dev->regs[((dev->regs[0x06] & 0x01) << 4) + addr]; + break; + case 0x0002: + ret = ((!!in_smm) << 7); + if (ret & 0x80) + ret |= (dev->regs[addr] & 0x7f); + break; + case 0x0003: case 0x0004: case 0x0005: case 0x0006: + ret = dev->regs[addr]; + break; + } + + return ret; +} + + +static uint16_t +opti611_cfg_readw(uint16_t addr, void *priv) +{ + uint16_t ret = 0xffff; + + ret = opti611_cfg_read(addr, priv); + ret |= (opti611_cfg_read(addr + 1, priv) << 8); + + return ret; +} + + +static uint32_t +opti611_cfg_readl(uint16_t addr, void *priv) +{ + uint32_t ret = 0xffffffff; + + ret = opti611_cfg_readw(addr, priv); + ret |= (opti611_cfg_readw(addr + 2, priv) << 16); + + return ret; +} + + +static void +opti611_ide_write(uint16_t addr, uint8_t val, void *priv) +{ + opti611_t *dev = (opti611_t *) priv; + + uint8_t smia9 = (!!(addr & 0x0200)) << 5; + uint8_t smia2 = (!!(addr & 0x0004)) << 4; + uint8_t smibe = (addr & 0x0003); + + if (dev->regs[0x03] & 0x02) { + smi_line = 1; + dev->regs[0x02] = smia9 | smia2 | smibe; + dev->regs[0x04] = val; + } +} + + +static void +opti611_ide_writew(uint16_t addr, uint16_t val, void *priv) +{ + opti611_t *dev = (opti611_t *) priv; + + uint8_t smia9 = (!!(addr & 0x0200)) << 5; + uint8_t smia2 = (!!(addr & 0x0004)) << 4; + uint8_t smibe = (addr & 0x0002) | 0x0001; + + if (dev->regs[0x03] & 0x02) { + smi_line = 1; + dev->regs[0x02] = smia9 | smia2 | smibe; + dev->regs[0x04] = 0x00; + } +} + + +static void +opti611_ide_writel(uint16_t addr, uint32_t val, void *priv) +{ + opti611_t *dev = (opti611_t *) priv; + + uint8_t smia9 = (!!(addr & 0x0200)) << 5; + uint8_t smia2 = (!!(addr & 0x0004)) << 4; + + if (dev->regs[0x03] & 0x02) { + smi_line = 1; + dev->regs[0x02] = smia9 | smia2 | 0x0003; + dev->regs[0x04] = 0x00; + } +} + + +static uint8_t +opti611_ide_read(uint16_t addr, void *priv) +{ + opti611_t *dev = (opti611_t *) priv; + + uint8_t smia9 = (!!(addr & 0x0200)) << 5; + uint8_t smia2 = (!!(addr & 0x0004)) << 4; + uint8_t smibe = (addr & 0x0003); + + if (dev->regs[0x03] & 0x02) { + smi_line = 1; + dev->regs[0x02] = smia9 | smia2 | smibe; + dev->regs[0x04] = 0x00; + } + + return 0xff; +} + + +static uint16_t +opti611_ide_readw(uint16_t addr, void *priv) +{ + opti611_t *dev = (opti611_t *) priv; + + uint8_t smia9 = (!!(addr & 0x0200)) << 5; + uint8_t smia2 = (!!(addr & 0x0004)) << 4; + uint8_t smibe = (addr & 0x0002) | 0x0001; + + if ((addr & 0x0007) == 0x0001) { + dev->tries = (dev->tries + 1) & 0x01; + if ((dev->tries == 0x00) && !dev->cfg_locked) { + dev->in_cfg = 1; + opti611_ide_handler(dev); + } + } + + if (dev->regs[0x03] & 0x02) { + smi_line = 1; + dev->regs[0x02] = smia9 | smia2 | smibe; + dev->regs[0x04] = 0x00; + } + + return 0xffff; +} + + +static uint32_t +opti611_ide_readl(uint16_t addr, void *priv) +{ + opti611_t *dev = (opti611_t *) priv; + + uint8_t smia9 = (!!(addr & 0x0200)) << 5; + uint8_t smia2 = (!!(addr & 0x0004)) << 4; + + if (dev->regs[0x03] & 0x02) { + smi_line = 1; + dev->regs[0x02] = smia9 | smia2 | 0x0003; + dev->regs[0x04] = 0x00; + } + + return 0xffffffff; +} + + +static void +opti611_ide_handler(opti611_t *dev) +{ + ide_pri_disable(); + io_removehandler(0x01f0, 0x0007, + opti611_ide_read, opti611_ide_readw, opti611_ide_readl, + opti611_ide_write, opti611_ide_writew, opti611_ide_writel, + dev); + io_removehandler(0x01f0, 0x0007, + opti611_cfg_read, opti611_cfg_readw, opti611_cfg_readl, + opti611_cfg_write, opti611_cfg_writew, opti611_cfg_writel, + dev); + + if (dev->in_cfg && !dev->cfg_locked) { + io_sethandler(0x01f0, 0x0007, + opti611_cfg_read, opti611_cfg_readw, opti611_cfg_readl, + opti611_cfg_write, opti611_cfg_writew, opti611_cfg_writel, + dev); + } else { + if (dev->regs[0x03] & 0x01) + ide_pri_enable(); + io_sethandler(0x01f0, 0x0007, + opti611_ide_read, opti611_ide_readw, opti611_ide_readl, + opti611_ide_write, opti611_ide_writew, opti611_ide_writel, + dev); + } +} + + +static void +opti611_close(void *priv) +{ + opti611_t *dev = (opti611_t *) priv; + + free(dev); +} + + +static void * +opti611_init(const device_t *info) +{ + opti611_t *dev = (opti611_t *) malloc(sizeof(opti611_t)); + memset(dev, 0, sizeof(opti611_t)); + + dev->regs[0x12] = 0x80; + dev->regs[0x03] = 0x01; + dev->regs[0x05] = 0x20; + + device_add(&ide_vlb_device); + + opti611_ide_handler(dev); + + return dev; +} + + +const device_t ide_opti611_vlb_device = { + "OPTi 82C611/82C611A VLB", + 0, + 0, + opti611_init, opti611_close, NULL, + NULL, NULL, NULL, + NULL +}; diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 10bf2885a..bb38d4926 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -13,8 +13,8 @@ * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #ifndef EMU_HDC_H # define EMU_HDC_H @@ -50,6 +50,8 @@ extern const device_t ide_vlb_2ch_device; /* vlb_ide_2ch */ extern const device_t ide_pci_device; /* pci_ide */ extern const device_t ide_pci_2ch_device; /* pci_ide_2ch */ +extern const device_t ide_opti611_vlb_device; /* OPTi 82c611/611A VLB */ + extern const device_t ide_ter_device; extern const device_t ide_qua_device; diff --git a/src/machine/m_at_socket4_5.c b/src/machine/m_at_socket4_5.c index 5fa8c341c..e28376d18 100644 --- a/src/machine/m_at_socket4_5.c +++ b/src/machine/m_at_socket4_5.c @@ -53,8 +53,8 @@ machine_at_excalibur_init(const machine_t *model) machine_at_common_init(model); - device_add(&ide_vlb_device); device_add(&opti5x7_device); + device_add(&ide_opti611_vlb_device); device_add(&fdc37c661_device); device_add(&keyboard_at_ami_device); @@ -182,10 +182,10 @@ machine_at_opti560l_init(const machine_t *model) pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430lx_device); - device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&keyboard_ps2_pci_device); device_add(&sio_device); device_add(&fdc37c665_device); - device_add(&intel_flash_bxt_ami_device); + device_add(&intel_flash_bxt_device); return ret; } @@ -213,10 +213,10 @@ machine_at_dellxp60_init(const machine_t *model) // Doesn't like the regular SMC pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430lx_device); - device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&keyboard_ps2_pci_device); device_add(&sio_device); device_add(&fdc37c665_device); - device_add(&intel_flash_bxt_ami_device); + device_add(&intel_flash_bxt_device); return ret; } diff --git a/src/sio/sio_fdc37c661.c b/src/sio/sio_fdc37c661.c index 6936dff7c..c742b71d0 100644 --- a/src/sio/sio_fdc37c661.c +++ b/src/sio/sio_fdc37c661.c @@ -161,7 +161,6 @@ fdc37c661_write(uint16_t port, uint8_t val, void *priv) case 0: if (valxor & 0x10) fdc_handler(dev); - break; case 1: if (valxor & 3) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 473021734..5872ad974 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -647,7 +647,7 @@ HDDOBJ := hdd.o \ hdc_xta.o \ hdc_esdi_at.o hdc_esdi_mca.o \ hdc_xtide.o hdc_ide.o \ - hdc_ide_sff8038i.o + hdc_ide_opti611.o hdc_ide_sff8038i.o CDROMOBJ := cdrom.o \ cdrom_image_backend.o cdrom_image.o