diff --git a/src/chipset/chipset.h b/src/chipset/chipset.h
index bf2cda160..50f3536f7 100644
--- a/src/chipset/chipset.h
+++ b/src/chipset/chipset.h
@@ -61,6 +61,11 @@ extern const device_t sis_85c496_device;
extern const device_t sis_85c50x_device;
#endif
+#if defined(DEV_BRANCH) && defined(USE_SS7)
+/* VIA */
+extern const device_t via_mvp3_device;
+#endif
+
/* WD */
extern const device_t wd76c10_device;
diff --git a/src/chipset/via_mvp3.c b/src/chipset/via_mvp3.c
new file mode 100644
index 000000000..dfeba12c2
--- /dev/null
+++ b/src/chipset/via_mvp3.c
@@ -0,0 +1,295 @@
+/*
+ * 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 VIA MVP3 chip.
+ *
+ * Version: @(#)via_mvp3.c 1.0.1 2019/10/19
+ *
+ * Authors: Sarah Walker,
+ * Miran Grca,
+ * Melissa Goad,
+ *
+ * Copyright 2020 Miran Grca, Melissa Goad.
+ */
+#include
+#include
+#include
+#include
+#include
+#include "../86box.h"
+#include "../mem.h"
+#include "../io.h"
+#include "../rom.h"
+#include "../pci.h"
+#include "../device.h"
+#include "../keyboard.h"
+#include "chipset.h"
+
+typedef struct via_mvp3_t
+{
+ uint8_t pci_conf[2][256];
+} via_mvp3_t;
+
+static void
+via_mvp3_recalcmapping(via_mvp3_t *dev)
+{
+ int c, d;
+ uint32_t base;
+
+ for (c = 0; c < 2; c++) {
+ for (d = 0; d < 4; d++) {
+ base = 0xc0000 + (d << 14);
+ switch (dev->pci_conf[0][0x61 + c] & (3 << (d << 1))) {
+ case 0x00:
+ mem_set_mem_state(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+ break;
+ case 0x01:
+ mem_set_mem_state(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
+ break;
+ case 0x02:
+ mem_set_mem_state(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
+ break;
+ case 0x03:
+ mem_set_mem_state(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ }
+ }
+ }
+
+ for(d = 0; d < 2; d++)
+ {
+ base = 0xe0000 + (d << 16);
+ switch (dev->pci_conf[0][0x63] & (3 << (d << 1))) {
+ case 0x00:
+ mem_set_mem_state(base, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+ break;
+ case 0x01:
+ mem_set_mem_state(base, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
+ break;
+ case 0x02:
+ mem_set_mem_state(base, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
+ break;
+ case 0x03:
+ mem_set_mem_state(base, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ }
+ }
+
+ flushmmucache_nopc();
+ shadowbios = 1;
+}
+
+static void
+via_mvp3_setup(via_mvp3_t *dev)
+{
+ memset(dev, 0, sizeof(via_mvp3_t));
+
+ /* Host Bridge */
+ dev->pci_conf[0][0x00] = 0x06; /*VIA*/
+ dev->pci_conf[0][0x01] = 0x11;
+ dev->pci_conf[0][0x02] = 0x98; /*VT82C598MVP*/
+ dev->pci_conf[0][0x03] = 0x05;
+
+ dev->pci_conf[0][0x04] = 6;
+ dev->pci_conf[0][0x05] = 0;
+
+ dev->pci_conf[0][0x06] = 0x90;
+ dev->pci_conf[0][0x07] = 0x02;
+
+ dev->pci_conf[0][0x09] = 0;
+ dev->pci_conf[0][0x0a] = 0;
+ dev->pci_conf[0][0x0b] = 6;
+ dev->pci_conf[0][0x0c] = 0;
+ dev->pci_conf[0][0x0d] = 0;
+ dev->pci_conf[0][0x0e] = 0;
+ dev->pci_conf[0][0x0f] = 0;
+ dev->pci_conf[0][0x10] = 0x08;
+ dev->pci_conf[0][0x34] = 0xa0;
+
+ dev->pci_conf[0][0x5a] = 0x01;
+ dev->pci_conf[0][0x5b] = 0x01;
+ dev->pci_conf[0][0x5c] = 0x01;
+ dev->pci_conf[0][0x5d] = 0x01;
+ dev->pci_conf[0][0x5e] = 0x01;
+ dev->pci_conf[0][0x5f] = 0x01;
+
+ dev->pci_conf[0][0x64] = 0xec;
+ dev->pci_conf[0][0x65] = 0xec;
+ dev->pci_conf[0][0x66] = 0xec;
+ dev->pci_conf[0][0x6b] = 0x01;
+
+ dev->pci_conf[0][0xa0] = 0x02;
+ dev->pci_conf[0][0xa2] = 0x10;
+ dev->pci_conf[0][0xa4] = 0x03;
+ dev->pci_conf[0][0xa5] = 0x02;
+ dev->pci_conf[0][0xa7] = 0x07;
+
+ /* PCI-to-PCI Bridge */
+
+ dev->pci_conf[1][0x00] = 0x06; /*VIA*/
+ dev->pci_conf[1][0x01] = 0x11;
+ dev->pci_conf[1][0x02] = 0x98; /*VT82C598MVP*/
+ dev->pci_conf[1][0x03] = 0x85;
+
+ dev->pci_conf[1][0x04] = 7;
+ dev->pci_conf[1][0x05] = 0;
+
+ dev->pci_conf[1][0x06] = 0x20;
+ dev->pci_conf[1][0x07] = 0x02;
+
+ dev->pci_conf[1][0x09] = 0;
+ dev->pci_conf[1][0x0a] = 4;
+ dev->pci_conf[1][0x0b] = 6;
+ dev->pci_conf[1][0x0c] = 0;
+ dev->pci_conf[1][0x0d] = 0;
+ dev->pci_conf[1][0x0e] = 1;
+ dev->pci_conf[1][0x0f] = 0;
+
+ dev->pci_conf[1][0x1c] = 0xf0;
+
+ dev->pci_conf[1][0x20] = 0xf0;
+ dev->pci_conf[1][0x21] = 0xff;
+ dev->pci_conf[1][0x24] = 0xf0;
+ dev->pci_conf[1][0x25] = 0xff;
+}
+
+static void
+via_mvp3_host_bridge_write(int func, int addr, uint8_t val, void *priv)
+{
+ via_mvp3_t *dev = (via_mvp3_t *) priv;
+
+ if (func)
+ return;
+
+ /*Read-only addresses*/
+ if ((addr < 4) || (addr >= 5 && addr < 7)
+ || (addr >= 8 && addr < 0xd)
+ || (addr >= 0xe && addr < 0x12)
+ || (addr >= 0x14 && addr < 0x50)
+ || (addr >= 0x79 && addr < 0x7e)
+ || (addr >= 0x85 && addr < 0x88)
+ || (addr >= 0x8c && addr < 0xa8)
+ || (addr >= 0xad && addr < 0xfd))
+ return;
+
+ switch(addr)
+ {
+ case 0x04:
+ dev->pci_conf[0][0x04] = (dev->pci_conf[0][0x04] & ~0x40) | (val & 0x40);
+ break;
+ case 0x07:
+ dev->pci_conf[0][0x07] &= ~(val & 0xb0);
+ case 0x61: case 0x62: case 0x63:
+ dev->pci_conf[0][addr] = val;
+ via_mvp3_recalcmapping(dev);
+ break;
+ default:
+ dev->pci_conf[0][addr] = val;
+ break;
+ }
+}
+
+static void
+via_mvp3_pci_bridge_write(int func, int addr, uint8_t val, void *priv)
+{
+ via_mvp3_t *dev = (via_mvp3_t *) priv;
+
+ if(func != 1) return;
+
+ /*Read-only addresses*/
+
+ if ((addr < 4) || (addr >= 5 && addr < 7)
+ || (addr >= 8 && addr < 0x18)
+ || (addr == 0x1b)
+ || (addr >= 0x1e && addr < 0x20)
+ || (addr >= 0x28 && addr < 0x3e)
+ || (addr >= 0x43))
+ return;
+
+ switch(addr)
+ {
+ case 0x04:
+ dev->pci_conf[1][0x04] = (dev->pci_conf[1][0x04] & ~0x47) | (val & 0x47);
+ break;
+ case 0x07:
+ dev->pci_conf[1][0x07] &= ~(val & 0x30);
+ default:
+ dev->pci_conf[1][addr] = val;
+ break;
+ }
+}
+
+static uint8_t
+via_mvp3_read(int func, int addr, void *priv)
+{
+ via_mvp3_t *dev = (via_mvp3_t *) priv;
+
+ switch(func)
+ {
+ case 0: return dev->pci_conf[0][addr];
+ case 1: return dev->pci_conf[1][addr];
+ default: return 0xff;
+ }
+}
+
+
+static void
+via_mvp3_write(int func, int addr, uint8_t val, void *priv)
+{
+ switch(func)
+ {
+ case 0:
+ via_mvp3_host_bridge_write(func, addr, val, priv);
+ break;
+ case 1:
+ via_mvp3_pci_bridge_write(func, addr, val, priv);
+ break;
+ }
+}
+
+static void
+via_mvp3_reset(void *priv)
+{
+ via_mvp3_t *dev = (via_mvp3_t *) priv;
+
+ via_mvp3_setup(dev);
+}
+
+static void *
+via_mvp3_init(const device_t *info)
+{
+ via_mvp3_t *dev = (via_mvp3_t *) malloc(sizeof(via_mvp3_t));
+
+ pci_add_card(0, via_mvp3_read, via_mvp3_write, dev);
+
+ via_mvp3_setup(dev);
+
+ return dev;
+}
+
+static void
+via_mvp3_close(void *priv)
+{
+ via_mvp3_t *dev = (via_mvp3_t *) priv;
+
+ free(dev);
+}
+
+const device_t via_mvp3_device =
+{
+ "VIA MVP3",
+ DEVICE_PCI,
+ 0,
+ via_mvp3_init,
+ via_mvp3_close,
+ via_mvp3_reset,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
diff --git a/src/machine/m_at_socket7_s7.c b/src/machine/m_at_socket7_s7.c
index 377a37bd5..9dfd1515a 100644
--- a/src/machine/m_at_socket7_s7.c
+++ b/src/machine/m_at_socket7_s7.c
@@ -12,9 +12,11 @@
*
* Authors: Sarah Walker,
* Miran Grca,
+ * Melissa Goad,
*
- * Copyright 2010-2019 Sarah Walker.
- * Copyright 2016-2019 Miran Grca.
+ * Copyright 2010-2020 Sarah Walker.
+ * Copyright 2016-2020 Miran Grca.
+ * Copyright 2020 Melissa Goad.
*/
#include
#include
@@ -35,6 +37,8 @@
#include "../intel_sio.h"
#include "../piix.h"
#include "../sio.h"
+#include "../sst_flash.h"
+#include "../via_mvp3_sb.h"
#include "../video/video.h"
#include "../video/vid_cl54xx.h"
#include "../video/vid_s3.h"
@@ -451,3 +455,33 @@ machine_at_j656vxd_init(const machine_t *model)
return ret;
}
+
+#if defined(DEV_BRANCH) && defined(USE_SS7)
+int
+machine_at_mvp3_init(const machine_t *model)
+{
+ int ret;
+
+ ret = bios_load_linear(L"roms/machines/ficva503p/je4333.bin",
+ 0x000e0000, 131072, 0);
+
+ if (bios_only || !ret)
+ return ret;
+
+ machine_at_common_init(model);
+
+ pci_init(PCI_CONFIG_TYPE_1);
+ pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0);
+ pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4);
+ pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1);
+ pci_register_slot(0x0a, PCI_CARD_NORMAL, 3, 4, 1, 2);
+ pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0);
+ device_add(&via_mvp3_device);
+ device_add(&via_mvp3_sb_device);
+ device_add(&keyboard_ps2_pci_device);
+ device_add(&w83877tf_device);
+ device_add(&sst_flash_39sf010_device);
+
+ return ret;
+}
+#endif
\ No newline at end of file
diff --git a/src/machine/machine.h b/src/machine/machine.h
index 7d4b52ab7..fdbc4bbe1 100644
--- a/src/machine/machine.h
+++ b/src/machine/machine.h
@@ -276,6 +276,10 @@ extern int machine_at_i430vx_init(const machine_t *);
extern int machine_at_p55va_init(const machine_t *);
extern int machine_at_j656vxd_init(const machine_t *);
+#if defined(DEV_BRANCH) && defined(USE_SS7)
+extern int machine_at_mvp3_init(const machine_t *);
+#endif
+
#ifdef EMU_DEVICE_H
extern const device_t *at_pb640_get_device(void);
#endif
diff --git a/src/machine/machine_table_new.c b/src/machine/machine_table_new.c
index a46e7175c..c9ae1d598 100644
--- a/src/machine/machine_table_new.c
+++ b/src/machine/machine_table_new.c
@@ -192,6 +192,10 @@ const machine_t machines[] = {
{ "[Socket 7 VX] Jetway J656VXD", "j656vxd", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_j656vxd_init, NULL },
{ "[Socket 7 VX] Shuttle HOT-557", "430vx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL },
+#if defined(DEV_BRANCH) && defined(USE_SS7)
+ { "[Super Socket 7] FIC VA503P", "ficva503p", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_mvp3_init, NULL },
+#endif
+
#if defined(DEV_BRANCH) && defined(USE_I686)
{ "[Socket 8 FX] Tyan Titan-Pro AT", "440fx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_i440fx_init, NULL },
{ "[Socket 8 FX] Tyan Titan-Pro ATX", "tpatx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_s1668_init, NULL },
diff --git a/src/sst_flash.c b/src/sst_flash.c
new file mode 100644
index 000000000..b5666659f
--- /dev/null
+++ b/src/sst_flash.c
@@ -0,0 +1,301 @@
+/*
+ * 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 an SST flash chip.
+ *
+ * Version: @(#)sst_flash.c 1.0.19 2019/06/25
+ *
+ * Authors: Sarah Walker,
+ * Miran Grca,
+ * Melissa Goad,
+ *
+ * Copyright 2008-2020 Sarah Walker.
+ * Copyright 2016-2020 Miran Grca.
+ * Copyright 2020 Melissa Goad.
+ */
+#include
+#include
+#include
+#include
+#include
+#include "86box.h"
+#include "device.h"
+#include "mem.h"
+#include "machine/machine.h"
+#include "timer.h"
+#include "nvr.h"
+#include "plat.h"
+
+typedef struct sst_t
+{
+ int command_state, id_mode,
+ erase, dirty;
+
+ uint8_t *array;
+
+ mem_mapping_t mapping[2], mapping_h[2];
+} sst_t;
+
+
+static wchar_t flash_path[1024];
+
+
+#define SST_CHIP_ERASE 0x10
+#define SST_SECTOR_ERASE 0x30
+#define SST_ERASE 0x80
+#define SST_SET_ID_MODE 0x90
+#define SST_BYTE_PROGRAM 0xa0
+#define SST_CLEAR_ID_MODE 0xf0
+
+
+static void
+sst_new_command(sst_t *dev, uint8_t val)
+{
+ switch (val) {
+ case SST_CHIP_ERASE:
+ if (dev->erase)
+ memset(dev->array, 0xff, 0x20000);
+ dev->command_state = 0;
+ dev->erase = 0;
+ break;
+
+ case SST_ERASE:
+ dev->command_state = 0;
+ dev->erase = 1;
+ break;
+
+ case SST_SET_ID_MODE:
+ if (!dev->id_mode)
+ dev->id_mode = 1;
+ dev->command_state = 0;
+ dev->erase = 0;
+ break;
+
+ case SST_BYTE_PROGRAM:
+ dev->command_state = 3;
+ dev->erase = 0;
+ break;
+
+ case SST_CLEAR_ID_MODE:
+ if (dev->id_mode)
+ dev->id_mode = 0;
+ dev->command_state = 0;
+ dev->erase = 0;
+ break;
+
+ default:
+ dev->command_state = 0;
+ dev->erase = 0;
+ }
+}
+
+
+static void
+sst_sector_erase(sst_t *dev, uint32_t addr)
+{
+ memset(&dev->array[addr & 0x1f000], 0xff, 4096);
+ dev->dirty = 1;
+}
+
+
+static uint8_t
+sst_read_id(uint32_t addr, void *p)
+{
+ if ((addr & 0xffff) == 0)
+ return 0xbf; /* SST */
+ else if ((addr & 0xffff) == 1)
+ return 0xb5; /* 39SF010 */
+ else
+ return 0xff;
+}
+
+
+static void
+sst_write(uint32_t addr, uint8_t val, void *p)
+{
+ sst_t *dev = (sst_t *) p;
+
+ switch (dev->command_state) {
+ case 0:
+ if (val == 0xf0) {
+ if (dev->id_mode)
+ dev->id_mode = 0;
+ } else if ((addr & 0xffff) == 0x5555 && val == 0xaa)
+ dev->command_state = 1;
+ else
+ dev->command_state = 0;
+ break;
+ case 1:
+ if ((addr & 0xffff) == 0x2aaa && val == 0x55)
+ dev->command_state = 2;
+ else
+ dev->command_state = 0;
+ break;
+ case 2:
+ if ((addr & 0xffff) == 0x5555)
+ sst_new_command(dev, val);
+ else if ((val == SST_SECTOR_ERASE) && dev->erase) {
+ sst_sector_erase(dev, addr);
+ dev->command_state = 0;
+ } else
+ dev->command_state = 0;
+ break;
+ case 3:
+ dev->array[addr & 0x1ffff] = val;
+ dev->command_state = 0;
+ dev->dirty = 1;
+ break;
+ }
+}
+
+
+static uint8_t
+sst_read(uint32_t addr, void *p)
+{
+ sst_t *dev = (sst_t *) p;
+ uint8_t ret = 0xff;
+
+ addr &= 0x000fffff;
+
+ if (dev->id_mode)
+ ret = sst_read_id(addr, p);
+ else {
+ if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask)))
+ ret = dev->array[addr - biosaddr];
+ }
+
+ return ret;
+}
+
+
+static uint16_t
+sst_readw(uint32_t addr, void *p)
+{
+ sst_t *dev = (sst_t *) p;
+ uint16_t ret = 0xffff;
+
+ addr &= 0x000fffff;
+
+ if (dev->id_mode)
+ ret = sst_read(addr, p) | (sst_read(addr + 1, p) << 8);
+ else {
+ if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask)))
+ ret = *(uint16_t *)&dev->array[addr - biosaddr];
+ }
+
+ return ret;
+}
+
+
+static uint32_t
+sst_readl(uint32_t addr, void *p)
+{
+ sst_t *dev = (sst_t *) p;
+ uint32_t ret = 0xffffffff;
+
+ addr &= 0x000fffff;
+
+ if (dev->id_mode)
+ ret = sst_readw(addr, p) | (sst_readw(addr + 2, p) << 16);
+ else {
+ if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask)))
+ ret = *(uint32_t *)&dev->array[addr - biosaddr];
+ }
+
+ return ret;
+}
+
+
+static void
+sst_add_mappings(sst_t *dev)
+{
+ int max = 2, i = 0;
+ uint32_t base, fbase;
+
+ for (i = 0; i < 2; i++) {
+ base = 0xe0000 + (i << 16);
+ fbase = base & biosmask;
+
+ memcpy(&dev->array[fbase], &rom[base & biosmask], 0x10000);
+
+ mem_mapping_add(&(dev->mapping[i]), base, 0x10000,
+ sst_read, sst_readw, sst_readl,
+ sst_write, NULL, NULL,
+ dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev);
+ mem_mapping_add(&(dev->mapping_h[i]), (base | 0xfff00000) - 0x40000, 0x10000,
+ sst_read, sst_readw, sst_readl,
+ sst_write, NULL, NULL,
+ dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev);
+ }
+}
+
+
+static void *
+sst_39sf010_init(const device_t *info)
+{
+ FILE *f;
+ sst_t *dev = malloc(sizeof(sst_t));
+ memset(dev, 0, sizeof(sst_t));
+
+ size_t l = strlen(machine_get_internal_name_ex(machine))+1;
+ wchar_t *machine_name = (wchar_t *) malloc(l * sizeof(wchar_t));
+ mbstowcs(machine_name, machine_get_internal_name_ex(machine), l);
+ l = wcslen(machine_name)+5;
+ wchar_t *flash_name = (wchar_t *)malloc(l*sizeof(wchar_t));
+ swprintf(flash_name, l, L"%ls.bin", machine_name);
+
+ wcscpy(flash_path, flash_name);
+
+ mem_mapping_disable(&bios_mapping);
+ mem_mapping_disable(&bios_high_mapping);
+
+ dev->array = (uint8_t *) malloc(biosmask + 1);
+ memset(dev->array, 0xff, biosmask + 1);
+
+ sst_add_mappings(dev);
+
+ f = nvr_fopen(flash_path, L"rb");
+ if (f) {
+ fread(&(dev->array[0x00000]), 0x20000, 1, f);
+ fclose(f);
+ }
+
+ free(flash_name);
+ free(machine_name);
+
+ return dev;
+}
+
+
+static void
+sst_39sf010_close(void *p)
+{
+ FILE *f;
+ sst_t *dev = (sst_t *)p;
+
+ f = nvr_fopen(flash_path, L"wb");
+ fwrite(&(dev->array[0x00000]), 0x20000, 1, f);
+ fclose(f);
+
+ free(dev->array);
+ dev->array = NULL;
+
+ free(dev);
+}
+
+
+const device_t sst_flash_39sf010_device =
+{
+ "SST 39SF010 Flash BIOS",
+ 0,
+ 0,
+ sst_39sf010_init,
+ sst_39sf010_close,
+ NULL,
+ NULL, NULL, NULL, NULL
+};
\ No newline at end of file
diff --git a/src/sst_flash.h b/src/sst_flash.h
new file mode 100644
index 000000000..f919e73d1
--- /dev/null
+++ b/src/sst_flash.h
@@ -0,0 +1,19 @@
+/*
+ * 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 an SST flash chip.
+ *
+ * Version: @(#)sst_flash.h 1.0.2 2019/06/25
+ *
+ * Author: Melissa Goad,
+ * Copyright 2020 Melissa Goad.
+ */
+
+#if defined(DEV_BRANCH) && defined(USE_SS7)
+extern const device_t sst_flash_39sf010_device;
+#endif
\ No newline at end of file
diff --git a/src/via_mvp3_sb.c b/src/via_mvp3_sb.c
new file mode 100644
index 000000000..1fa42889c
--- /dev/null
+++ b/src/via_mvp3_sb.c
@@ -0,0 +1,444 @@
+/*
+ * 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.
+ *
+ * Emulation of the VIA Apollo MVP3 southbridge
+ *
+ * Version: @(#)via_mvp3_sb.c 1.0.22 2018/10/31
+ *
+ * Authors: Sarah Walker,
+ * Miran Grca,
+ * Melissa Goad,
+ *
+ * Copyright 2008-2020 Sarah Walker.
+ * Copyright 2016-2020 Miran Grca.
+ * Copyright 2020 Melissa Goad.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include "86box.h"
+#include "cdrom/cdrom.h"
+#include "cpu/cpu.h"
+#include "scsi/scsi_device.h"
+#include "scsi/scsi_cdrom.h"
+#include "dma.h"
+#include "io.h"
+#include "device.h"
+#include "apm.h"
+#include "keyboard.h"
+#include "mem.h"
+#include "pci.h"
+#include "pic.h"
+#include "port_92.h"
+#include "disk/hdc.h"
+#include "disk/hdc_ide.h"
+#include "disk/hdc_ide_sff8038i.h"
+#include "disk/zip.h"
+#include "machine/machine.h"
+#include "via_mvp3_sb.h"
+
+typedef struct
+{
+ uint8_t pci_isa_regs[256];
+ uint8_t ide_regs[256];
+ uint8_t usb_regs[256];
+ uint8_t power_regs[256];
+ sff8038i_t *bm[2];
+} via_mvp3_sb_t;
+
+static void
+via_mvp3_sb_reset_hard(void *priv)
+{
+ via_mvp3_sb_t *via_mvp3_sb = (via_mvp3_sb_t *) priv;
+
+ uint16_t old_base = (via_mvp3_sb->ide_regs[0x20] & 0xf0) | (via_mvp3_sb->ide_regs[0x21] << 8);
+
+ sff_bus_master_reset(via_mvp3_sb->bm[0], old_base);
+ sff_bus_master_reset(via_mvp3_sb->bm[1], old_base + 8);
+
+ memset(via_mvp3_sb->pci_isa_regs, 0, 256);
+ memset(via_mvp3_sb->ide_regs, 0, 256);
+ memset(via_mvp3_sb->usb_regs, 0, 256);
+ memset(via_mvp3_sb->power_regs, 0, 256);
+
+ via_mvp3_sb->pci_isa_regs[0x00] = 0x06; via_mvp3_sb->pci_isa_regs[0x01] = 0x11; /*VIA*/
+ via_mvp3_sb->pci_isa_regs[0x02] = 0x86; via_mvp3_sb->pci_isa_regs[0x03] = 0x05; /*VT82C586B*/
+ via_mvp3_sb->pci_isa_regs[0x04] = 0x0f;
+ via_mvp3_sb->pci_isa_regs[0x07] = 0x02;
+ via_mvp3_sb->pci_isa_regs[0x0a] = 0x01;
+ via_mvp3_sb->pci_isa_regs[0x0b] = 0x06;
+ via_mvp3_sb->pci_isa_regs[0x0e] = 0x80;
+
+ via_mvp3_sb->pci_isa_regs[0x48] = 0x01;
+ via_mvp3_sb->pci_isa_regs[0x4a] = 0x04;
+ via_mvp3_sb->pci_isa_regs[0x4f] = 0x03;
+
+ via_mvp3_sb->pci_isa_regs[0x50] = 0x24;
+ via_mvp3_sb->pci_isa_regs[0x59] = 0x04;
+
+ //IDE registers
+ via_mvp3_sb->ide_regs[0x00] = 0x06; via_mvp3_sb->ide_regs[0x01] = 0x11; /*VIA*/
+ via_mvp3_sb->ide_regs[0x02] = 0x71; via_mvp3_sb->ide_regs[0x03] = 0x05; /*VT82C586B*/
+ via_mvp3_sb->ide_regs[0x04] = 0x80;
+ via_mvp3_sb->ide_regs[0x06] = 0x80; via_mvp3_sb->ide_regs[0x07] = 0x02;
+ via_mvp3_sb->ide_regs[0x09] = 0x85;
+ via_mvp3_sb->ide_regs[0x0a] = 0x01;
+ via_mvp3_sb->ide_regs[0x0b] = 0x01;
+
+ via_mvp3_sb->ide_regs[0x10] = 0xf0; via_mvp3_sb->ide_regs[0x11] = 0x01;
+ via_mvp3_sb->ide_regs[0x14] = 0xf4; via_mvp3_sb->ide_regs[0x15] = 0x03;
+ via_mvp3_sb->ide_regs[0x18] = 0x70; via_mvp3_sb->ide_regs[0x19] = 0x01;
+ via_mvp3_sb->ide_regs[0x1c] = 0x74; via_mvp3_sb->ide_regs[0x1d] = 0x03;
+ via_mvp3_sb->ide_regs[0x20] = 0x01; via_mvp3_sb->ide_regs[0x21] = 0xcc;
+
+ via_mvp3_sb->ide_regs[0x3c] = 0x0e;
+
+ via_mvp3_sb->ide_regs[0x40] = 0x08;
+ via_mvp3_sb->ide_regs[0x41] = 0x02;
+ via_mvp3_sb->ide_regs[0x42] = 0x09;
+ via_mvp3_sb->ide_regs[0x43] = 0x3a;
+ via_mvp3_sb->ide_regs[0x44] = 0x68;
+ via_mvp3_sb->ide_regs[0x46] = 0xc0;
+ via_mvp3_sb->ide_regs[0x48] = 0xa8; via_mvp3_sb->ide_regs[0x49] = 0xa8;
+ via_mvp3_sb->ide_regs[0x4a] = 0xa8; via_mvp3_sb->ide_regs[0x4b] = 0xa8;
+ via_mvp3_sb->ide_regs[0x4c] = 0xff;
+ via_mvp3_sb->ide_regs[0x4e] = 0xff;
+ via_mvp3_sb->ide_regs[0x4f] = 0xff;
+ via_mvp3_sb->ide_regs[0x50] = 0x03; via_mvp3_sb->ide_regs[0x51] = 0x03;
+ via_mvp3_sb->ide_regs[0x52] = 0x03; via_mvp3_sb->ide_regs[0x53] = 0x03;
+
+ via_mvp3_sb->ide_regs[0x61] = 0x02;
+ via_mvp3_sb->ide_regs[0x69] = 0x02;
+
+ via_mvp3_sb->usb_regs[0x00] = 0x06; via_mvp3_sb->usb_regs[0x01] = 0x11; /*VIA*/
+ via_mvp3_sb->usb_regs[0x02] = 0x38; via_mvp3_sb->usb_regs[0x03] = 0x30;
+ via_mvp3_sb->usb_regs[0x04] = 0x00; via_mvp3_sb->usb_regs[0x05] = 0x00;
+ via_mvp3_sb->usb_regs[0x06] = 0x00; via_mvp3_sb->usb_regs[0x07] = 0x02;
+ via_mvp3_sb->usb_regs[0x0a] = 0x03;
+ via_mvp3_sb->usb_regs[0x0b] = 0x0c;
+ via_mvp3_sb->usb_regs[0x0d] = 0x16;
+ via_mvp3_sb->usb_regs[0x20] = 0x01;
+ via_mvp3_sb->usb_regs[0x21] = 0x03;
+ via_mvp3_sb->usb_regs[0x3d] = 0x04;
+
+ via_mvp3_sb->usb_regs[0x60] = 0x10;
+ via_mvp3_sb->usb_regs[0xc1] = 0x20;
+
+ via_mvp3_sb->power_regs[0x00] = 0x06; via_mvp3_sb->power_regs[0x01] = 0x11; /*VIA*/
+ via_mvp3_sb->power_regs[0x02] = 0x40; via_mvp3_sb->power_regs[0x03] = 0x30;
+ via_mvp3_sb->power_regs[0x04] = 0x00; via_mvp3_sb->power_regs[0x05] = 0x00;
+ via_mvp3_sb->power_regs[0x06] = 0x80; via_mvp3_sb->power_regs[0x07] = 0x02;
+ via_mvp3_sb->power_regs[0x08] = 0x10; /*Production version (3041)*/
+ via_mvp3_sb->power_regs[0x48] = 0x01;
+
+ pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
+ pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
+ pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED);
+ pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
+
+ pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED);
+ pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED);
+ pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED);
+
+ ide_pri_disable();
+ ide_sec_disable();
+}
+
+static void
+via_mvp3_sb_bus_master_handlers(via_mvp3_sb_t *dev, uint16_t old_base)
+{
+ uint16_t base;
+
+ base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8);
+
+ sff_bus_master_handlers(dev->bm[0], old_base, base, (dev->ide_regs[0x04] & 1));
+ sff_bus_master_handlers(dev->bm[1], old_base + 8, base + 8, (dev->ide_regs[0x04] & 1));
+}
+
+static uint8_t
+via_mvp3_sb_read(int func, int addr, void *priv)
+{
+ via_mvp3_sb_t *dev = (via_mvp3_sb_t *) priv;
+
+ switch(func)
+ {
+ case 0:
+ {
+ return dev->pci_isa_regs[addr];
+ }
+ case 1:
+ {
+ return dev->ide_regs[addr];
+ }
+ case 2:
+ {
+ return dev->usb_regs[addr];
+ }
+ case 3:
+ {
+ return dev->power_regs[addr];
+ }
+ default:
+ {
+ return 0xff;
+ }
+ }
+}
+
+static void
+via_mvp3_sb_write(int func, int addr, uint8_t val, void *priv)
+{
+ via_mvp3_sb_t *dev = (via_mvp3_sb_t *) priv;
+ uint16_t old_base;
+
+ if(func > 3) return;
+
+ old_base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8);
+
+ switch(func)
+ {
+ case 0: //PCI-ISA bridge
+ {
+ /*Read-only addresses*/
+ if ((addr < 4) || (addr == 5) || (addr == 6)
+ || (addr >= 8 && addr < 0x40)
+ || (addr == 0x49)
+ || (addr == 0x4b)
+ || (addr >= 0x51 && addr < 0x54)
+ || (addr >= 0x5d && addr < 0x60)
+ || (addr >= 0x68 && addr < 0x6a)
+ || (addr >= 0x71))
+ return;
+
+ switch(addr)
+ {
+ case 0x04:
+ dev->pci_isa_regs[0x04] = (val & 8) | 7;
+ break;
+ case 0x06:
+ dev->pci_isa_regs[0x06] &= ~(val & 0xb0);
+ break;
+
+ case 0x47:
+ if((val & 0x81) == 0x81) resetx86();
+ if(val & 0x20) pci_elcr_set_enabled(1);
+ else pci_elcr_set_enabled(0);
+ dev->pci_isa_regs[0x47] = val & 0xfe;
+ break;
+
+ case 0x54:
+ if(val & 8) pci_set_irq_level(PCI_INTA, 0);
+ else pci_set_irq_level(PCI_INTA, 1);
+ if(val & 4) pci_set_irq_level(PCI_INTB, 0);
+ else pci_set_irq_level(PCI_INTB, 1);
+ if(val & 2) pci_set_irq_level(PCI_INTC, 0);
+ else pci_set_irq_level(PCI_INTC, 1);
+ if(val & 1) pci_set_irq_level(PCI_INTD, 0);
+ else pci_set_irq_level(PCI_INTD, 1);
+ break;
+
+ case 0x55:
+ if(!(val & 0xf0)) pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
+ else pci_set_irq_routing(PCI_INTD, val >> 4);
+
+ if(!(val & 0x0f)) pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED);
+ else pci_set_mirq_routing(PCI_MIRQ0, val & 0xf);
+ dev->pci_isa_regs[0x55] = val;
+ break;
+
+ case 0x56:
+ if(!(val & 0xf0)) pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
+ else pci_set_irq_routing(PCI_INTA, val >> 4);
+
+ if(!(val & 0x0f)) pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
+ else pci_set_irq_routing(PCI_INTB, val & 0xf);
+ dev->pci_isa_regs[0x56] = val;
+ break;
+
+ case 0x57:
+ if(!(val & 0xf0)) pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED);
+ else pci_set_irq_routing(PCI_INTC, val >> 4);
+
+ if(!(val & 0x0f)) pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED);
+ else pci_set_mirq_routing(PCI_MIRQ1, val & 0xf);
+ dev->pci_isa_regs[0x57] = val;
+ break;
+
+ case 0x58:
+ if(!(val & 0x0f)) pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED);
+ else pci_set_mirq_routing(PCI_MIRQ2, val & 0xf);
+ dev->pci_isa_regs[0x58] = val;
+ }
+ break;
+ }
+ case 1: /*IDE regs*/
+ {
+ /*Read-only addresses*/
+ if ((addr < 4) || (addr == 5) || (addr == 8)
+ || (addr >= 0xa && addr < 0x0d)
+ || (addr >= 0x0e && addr < 0x20)
+ || (addr >= 0x22 && addr < 0x3c)
+ || (addr >= 0x3d && addr < 0x40)
+ || (addr >= 0x54 && addr < 0x60)
+ || (addr >= 0x52 && addr < 0x68)
+ || (addr >= 0x62))
+ return;
+
+ switch(addr)
+ {
+ case 0x04:
+ {
+ uint16_t base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8);
+ ide_pri_disable();
+ ide_sec_disable();
+ if(val & PCI_COMMAND_IO)
+ {
+ if(dev->ide_regs[0x40] & 0x02) ide_pri_enable();
+ if(dev->ide_regs[0x40] & 0x01) ide_sec_enable();
+ }
+ via_mvp3_sb_bus_master_handlers(dev, base);
+ dev->ide_regs[0x04] = val & 0x85;
+ break;
+ }
+ case 0x06:
+ dev->ide_regs[0x06] &= ~(val & 0xb0);
+ break;
+
+ case 0x09:
+ dev->ide_regs[0x09] = (dev->pci_isa_regs[0x09] & ~0x70) | 0x8a;
+ break;
+
+ case 0x20:
+ {
+ dev->ide_regs[0x20] = (val & 0xf0) | 1;
+ via_mvp3_sb_bus_master_handlers(dev, old_base);
+ break;
+ }
+
+ case 0x21:
+ {
+ dev->ide_regs[0x21] = val;
+ via_mvp3_sb_bus_master_handlers(dev, old_base);
+ break;
+ }
+
+ case 0x40:
+ {
+ dev->ide_regs[0x40] = val;
+ ide_pri_disable();
+ ide_sec_disable();
+ if(val & PCI_COMMAND_IO)
+ {
+ if(dev->ide_regs[0x40] & 0x02) ide_pri_enable();
+ if(dev->ide_regs[0x40] & 0x01) ide_sec_enable();
+ }
+ break;
+ }
+
+ default:
+ dev->ide_regs[addr] = val;
+ break;
+ }
+ break;
+ }
+ case 2:
+ {
+ /*Read-only addresses*/
+ if ((addr < 4) || (addr == 5) || (addr == 6)
+ || (addr >= 8 && addr < 0xd)
+ || (addr >= 0xe && addr < 0x20)
+ || (addr >= 0x22 && addr < 0x3c)
+ || (addr >= 0x3e && addr < 0x40)
+ || (addr >= 0x42 && addr < 0x44)
+ || (addr >= 0x46 && addr < 0xc0)
+ || (addr >= 0xc2))
+ return;
+
+ switch(addr)
+ {
+ case 0x04:
+ dev->usb_regs[0x04] = val & 0x97;
+ break;
+ case 0x07:
+ dev->usb_regs[0x07] = val & 0x7f;
+ break;
+
+ case 0x20:
+ dev->usb_regs[0x20] = (val & ~0x1f) | 1;
+ break;
+
+ default:
+ dev->usb_regs[addr] = val;
+ break;
+ }
+ break;
+ }
+ case 3:
+ {
+ /*Read-only addresses*/
+ if ((addr < 0xd) || (addr >= 0xe && addr < 0x40)
+ || (addr == 0x43)
+ || (addr == 0x48)
+ || (addr >= 0x4a && addr < 0x50)
+ || (addr >= 0x54))
+ return;
+
+ dev->power_regs[addr] = val;
+ break;
+ }
+ }
+}
+
+static void
+*via_mvp3_sb_init(const device_t *info)
+{
+ via_mvp3_sb_t *via_mvp3_sb = (via_mvp3_sb_t *) malloc(sizeof(via_mvp3_sb_t));
+ memset(via_mvp3_sb, 0, sizeof(via_mvp3_sb_t));
+
+ pci_add_card(7, via_mvp3_sb_read, via_mvp3_sb_write, via_mvp3_sb);
+
+ via_mvp3_sb->bm[0] = device_add_inst(&sff8038i_device, 1);
+ via_mvp3_sb->bm[1] = device_add_inst(&sff8038i_device, 2);
+
+ via_mvp3_sb_reset_hard(via_mvp3_sb);
+
+ device_add(&port_92_pci_device);
+
+ dma_alias_set();
+
+ pci_enable_mirq(0);
+ pci_enable_mirq(1);
+ pci_enable_mirq(2);
+
+ return via_mvp3_sb;
+}
+
+static void
+via_mvp3_sb_close(void *p)
+{
+ via_mvp3_sb_t *via_mvp3_sb = (via_mvp3_sb_t *)p;
+
+ free(via_mvp3_sb);
+}
+
+const device_t via_mvp3_sb_device =
+{
+ "VIA VT82C586B",
+ DEVICE_PCI,
+ 0,
+ via_mvp3_sb_init,
+ via_mvp3_sb_close,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
\ No newline at end of file
diff --git a/src/via_mvp3_sb.h b/src/via_mvp3_sb.h
new file mode 100644
index 000000000..2e9ab7967
--- /dev/null
+++ b/src/via_mvp3_sb.h
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ *
+ * Emulation of the VIA Apollo MVP3 southbridge
+ *
+ * Version: @(#)via_mvp3_sb.c 1.0.22 2018/10/31
+ *
+ * Authors: Sarah Walker,
+ * Miran Grca,
+ * Melissa Goad,
+ *
+ * Copyright 2008-2020 Sarah Walker.
+ * Copyright 2016-2020 Miran Grca.
+ * Copyright 2020 Melissa Goad.
+ */
+
+#if defined(DEV_BRANCH) && defined(USE_SS7)
+extern const device_t via_mvp3_sb_device;
+#endif
\ No newline at end of file
diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw
index facc55327..3ee85ba09 100644
--- a/src/win/Makefile_ndr.mingw
+++ b/src/win/Makefile_ndr.mingw
@@ -74,6 +74,9 @@ ifeq ($(DEV_BUILD), y)
ifndef PS2M70T4
PS2M70T4 := y
endif
+ ifndef SS7
+ SS7 := y
+ endif
ifndef TI
TI := y
endif
@@ -138,6 +141,9 @@ else
ifndef PS2M70T4
PS2M70T4 := n
endif
+ ifndef SS7
+ SS7 := n
+ endif
ifndef TI
TI := n
endif
@@ -500,6 +506,11 @@ ifeq ($(PS2M70T4), y)
OPTS += -DUSE_PS2M70T4
endif
+ifeq ($(SS7),y)
+OPTS += -DUSE_SS7
+DEVBROBJ += via_mvp3.o via_mvp3_sb.o sst_flash.o
+endif
+
ifeq ($(TI), y)
OPTS += -DUSE_TI
endif