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