From 99ca11d148793c3b13f8be51a80d75e4f12ca836 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 2 Dec 2018 12:38:31 +0000 Subject: [PATCH] Added initial emulation of FIC VA-503+ (Super 7). This includes preliminary emulation of the VIA MVP3 northbridge, VT82C586B 'PIPC' southbridge, and Winbond W83877TF SuperIO chip. --- src/ibm.h | 1 + src/mem_bios.c | 8 ++ src/model.c | 18 +++ src/mvp3.c | 219 ++++++++++++++++++++++++++++++++++ src/mvp3.h | 1 + src/nvr.c | 6 +- src/vt82c586b.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++ src/vt82c586b.h | 1 + src/w83877tf.c | 202 +++++++++++++++++++++++++++++++ src/w83877tf.h | 1 + 10 files changed, 765 insertions(+), 2 deletions(-) create mode 100644 src/mvp3.c create mode 100644 src/mvp3.h create mode 100644 src/vt82c586b.c create mode 100644 src/vt82c586b.h create mode 100644 src/w83877tf.c create mode 100644 src/w83877tf.h diff --git a/src/ibm.h b/src/ibm.h index 2221e8c..fb7865c 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -465,6 +465,7 @@ enum ROM_XI8088, ROM_IBMPS2_M70_TYPE3, ROM_IBMPS2_M70_TYPE4, + ROM_FIC_VA503P, ROM_MAX }; diff --git a/src/mem_bios.c b/src/mem_bios.c index dc5a904..c4229c5 100644 --- a/src/mem_bios.c +++ b/src/mem_bios.c @@ -900,6 +900,14 @@ int loadbios() fclose(f); biosmask = 0x1ffff; return 1; + + case ROM_FIC_VA503P: + f = romfopen("fic_va503p/je4333.bin","rb"); + if (!f) break; + romfread(rom, 0x20000, 1, f); + fclose(f); + biosmask = 0x1ffff; + return 1; } printf("Failed to load ROM!\n"); if (f) fclose(f); diff --git a/src/model.c b/src/model.c index 55be58b..5fe572d 100644 --- a/src/model.c +++ b/src/model.c @@ -34,6 +34,7 @@ #include "lpt.h" #include "mem.h" #include "mouse_ps2.h" +#include "mvp3.h" #include "neat.h" #include "nmi.h" #include "nvr.h" @@ -61,6 +62,8 @@ #include "vid_pcjr.h" #include "vid_tandy.h" #include "vid_t1000.h" +#include "vt82c586b.h" +#include "w83877tf.h" #include "wd76c10.h" #include "xi8088.h" @@ -106,6 +109,7 @@ void at_pb520r_init(); void at_pb570_init(); void compaq_pip_init(); void xt_xi8088_init(); +void at_mvp3_init(); int model; int AMSTRAD, AT, PCI, TANDY; @@ -189,6 +193,8 @@ MODEL models[] = {"[Socket 7] Award 430VX PCI", ROM_430VX, "430vx", { {"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 256, 1, at_i430vx_init, NULL}, + {"[Super 7] FIC VA-503+", ROM_FIC_VA503P, "fic_va503p", { {"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 512, 1, at_mvp3_init, NULL}, + {"", -1, "", {{"", 0}, {"", 0}, {"", 0}}, 0,0,0, 0} }; @@ -659,6 +665,18 @@ void at_i430vx_init() device_add(&intel_flash_bxt_device); } +void at_mvp3_init() +{ + at_init(); + pci_init(PCI_CONFIG_TYPE_1); + pci_slot(8); + pci_slot(9); + pci_slot(10); + mvp3_init(); + vt82c586b_init(7, 8, 9, 10, 0); + w83877tf_init(); +} + void model_init() { pclog("Initting as %s\n", model_getname()); diff --git a/src/mvp3.c b/src/mvp3.c new file mode 100644 index 0000000..2760d99 --- /dev/null +++ b/src/mvp3.c @@ -0,0 +1,219 @@ +#include + +#include "ibm.h" +#include "io.h" +#include "mem.h" +#include "pci.h" + +#include "mvp3.h" + +static struct +{ + uint8_t host_bridge_regs[256]; + uint8_t pci_bridge_regs[256]; +} mvp3; + +static void mvp3_map(uint32_t addr, uint32_t size, int state) +{ + pclog("mvp3_map: addr=%08x size=%08x state=%i\n", addr, size, state); + switch (state & 3) + { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + flushmmucache_nopc(); +} + +static uint8_t mvp3_read(int func, int addr, void *priv) +{ + switch (func) + { + case 0: + return mvp3.host_bridge_regs[addr]; + + case 1: + return mvp3.pci_bridge_regs[addr]; + + default: + return 0xff; + } +} + + +static void mvp3_host_bridge_write(int addr, uint8_t val) +{ + /*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: /*Command*/ + mvp3.host_bridge_regs[0x04] = (mvp3.host_bridge_regs[0x04] & ~0x40) | (val & 0x40); + break; + case 0x07: /*Status*/ + mvp3.host_bridge_regs[0x07] &= ~(val & 0xb0); + break; + + case 0x12: /*Graphics Aperture Base*/ + mvp3.host_bridge_regs[0x12] = (val & 0xf0); + break; + case 0x13: /*Graphics Aperture Base*/ + mvp3.host_bridge_regs[0x13] = val; + break; + + case 0x61: /*Shadow RAM Control 1*/ + if ((mvp3.host_bridge_regs[0x61] ^ val) & 0x03) + mvp3_map(0xc0000, 0x04000, val & 0x03); + if ((mvp3.host_bridge_regs[0x61] ^ val) & 0x0c) + mvp3_map(0xc4000, 0x04000, (val & 0x0c) >> 2); + if ((mvp3.host_bridge_regs[0x61] ^ val) & 0x30) + mvp3_map(0xc8000, 0x04000, (val & 0x30) >> 4); + if ((mvp3.host_bridge_regs[0x61] ^ val) & 0xc0) + mvp3_map(0xcc000, 0x04000, (val & 0xc0) >> 6); + mvp3.host_bridge_regs[0x61] = val; + return; + case 0x62: /*Shadow RAM Control 2*/ + if ((mvp3.host_bridge_regs[0x62] ^ val) & 0x03) + mvp3_map(0xd0000, 0x04000, val & 0x03); + if ((mvp3.host_bridge_regs[0x62] ^ val) & 0x0c) + mvp3_map(0xd4000, 0x04000, (val & 0x0c) >> 2); + if ((mvp3.host_bridge_regs[0x62] ^ val) & 0x30) + mvp3_map(0xd8000, 0x04000, (val & 0x30) >> 4); + if ((mvp3.host_bridge_regs[0x62] ^ val) & 0xc0) + mvp3_map(0xdc000, 0x04000, (val & 0xc0) >> 6); + mvp3.host_bridge_regs[0x62] = val; + return; + case 0x63: /*Shadow RAM Control 3*/ + if ((mvp3.host_bridge_regs[0x63] ^ val) & 0x30) + mvp3_map(0xf0000, 0x10000, (val & 0x30) >> 4); + if ((mvp3.host_bridge_regs[0x63] ^ val) & 0xc0) + mvp3_map(0xe0000, 0x10000, (val & 0xc0) >> 6); + mvp3.host_bridge_regs[0x63] = val; +// if (val == 0xb0) +// output = 3; + return; + + default: + mvp3.host_bridge_regs[addr] = val; + break; + } +} +static void mvp3_pci_bridge_write(int addr, uint8_t val) +{ + /*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: /*Command*/ + mvp3.pci_bridge_regs[0x04] = (mvp3.pci_bridge_regs[0x04] & ~0x47) | (val & 0x47); + break; + case 0x07: /*Status*/ + mvp3.pci_bridge_regs[0x07] &= ~(val & 0x30); + break; + + case 0x20: /*Memory Base*/ + mvp3.pci_bridge_regs[0x20] = val & 0xf0; + break; + case 0x22: /*Memory Limit*/ + mvp3.pci_bridge_regs[0x22] = val & 0xf0; + break; + case 0x24: /*Prefetchable Memory Base*/ + mvp3.pci_bridge_regs[0x24] = val & 0xf0; + break; + case 0x26: /*Prefetchable Memory Limit*/ + mvp3.pci_bridge_regs[0x26] = val & 0xf0; + break; + + default: + mvp3.pci_bridge_regs[addr] = val; + break; + } +} + +static void mvp3_write(int func, int addr, uint8_t val, void *priv) +{ + switch (func) + { + case 0: + mvp3_host_bridge_write(addr, val); + break; + + case 1: + mvp3_pci_bridge_write(addr, val); + break; + } +} + +void mvp3_init() +{ + pci_add_specific(0, mvp3_read, mvp3_write, NULL); + + memset(&mvp3, 0, sizeof(mvp3)); + mvp3.host_bridge_regs[0x00] = 0x06; mvp3.host_bridge_regs[0x01] = 0x11; /*VIA*/ + mvp3.host_bridge_regs[0x02] = 0x98; mvp3.host_bridge_regs[0x03] = 0x05; /*VT82C598MVP*/ + mvp3.host_bridge_regs[0x04] = 0x06; mvp3.host_bridge_regs[0x05] = 0x00; + mvp3.host_bridge_regs[0x06] = 0x90; mvp3.host_bridge_regs[0x07] = 0x02; + mvp3.host_bridge_regs[0x0b] = 0x06; + mvp3.host_bridge_regs[0x10] = 0x08; + mvp3.host_bridge_regs[0x34] = 0xa0; + + mvp3.host_bridge_regs[0x5a] = 0x01; + mvp3.host_bridge_regs[0x5b] = 0x01; + mvp3.host_bridge_regs[0x5c] = 0x01; + mvp3.host_bridge_regs[0x5d] = 0x01; + mvp3.host_bridge_regs[0x5e] = 0x01; + mvp3.host_bridge_regs[0x5f] = 0x01; + + mvp3.host_bridge_regs[0x64] = 0xec; + mvp3.host_bridge_regs[0x65] = 0xec; + mvp3.host_bridge_regs[0x66] = 0xec; + mvp3.host_bridge_regs[0x6b] = 0x01; + + mvp3.host_bridge_regs[0xa0] = 0x02; + mvp3.host_bridge_regs[0xa2] = 0x10; + mvp3.host_bridge_regs[0xa4] = 0x03; + mvp3.host_bridge_regs[0xa5] = 0x02; + mvp3.host_bridge_regs[0xa6] = 0x00; + mvp3.host_bridge_regs[0xa7] = 0x07; + + mvp3.pci_bridge_regs[0x00] = 0x06; mvp3.pci_bridge_regs[0x01] = 0x11; /*VIA*/ + mvp3.pci_bridge_regs[0x02] = 0x98; mvp3.pci_bridge_regs[0x03] = 0x85; /*VT82C598MVP*/ + mvp3.pci_bridge_regs[0x04] = 0x07; mvp3.pci_bridge_regs[0x05] = 0x00; + mvp3.pci_bridge_regs[0x06] = 0x20; mvp3.pci_bridge_regs[0x07] = 0x02; + mvp3.pci_bridge_regs[0x0a] = 0x04; + mvp3.pci_bridge_regs[0x0b] = 0x06; + mvp3.pci_bridge_regs[0x0e] = 0x01; + + mvp3.pci_bridge_regs[0x1c] = 0xf0; + + mvp3.pci_bridge_regs[0x20] = 0xf0; + mvp3.pci_bridge_regs[0x21] = 0xff; + + mvp3.pci_bridge_regs[0x24] = 0xf0; + mvp3.pci_bridge_regs[0x25] = 0xff; +} diff --git a/src/mvp3.h b/src/mvp3.h new file mode 100644 index 0000000..69dac83 --- /dev/null +++ b/src/mvp3.h @@ -0,0 +1 @@ +void mvp3_init(); diff --git a/src/nvr.c b/src/nvr.c index fa8c1f4..edabac9 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -306,7 +306,8 @@ void loadnvr() case ROM_XI8088: f = nvrfopen("xi8088.nvr", "rb"); nvrmask = 127; break; case ROM_IBMPS2_M70_TYPE3: f = nvrfopen("ibmps2_m70_type3.nvr","rb"); break; case ROM_IBMPS2_M70_TYPE4: f = nvrfopen("ibmps2_m70_type4.nvr","rb"); break; - + case ROM_FIC_VA503P: f = nvrfopen("fic_va503p.nvr", "rb"); nvrmask = 127; break; + default: return; } if (!f) @@ -396,7 +397,8 @@ void savenvr() case ROM_XI8088: f = nvrfopen("xi8088.nvr", "wb"); break; case ROM_IBMPS2_M70_TYPE3: f = nvrfopen("ibmps2_m70_type3.nvr","wb"); break; case ROM_IBMPS2_M70_TYPE4: f = nvrfopen("ibmps2_m70_type4.nvr","wb"); break; - + case ROM_FIC_VA503P: f = nvrfopen("fic_va503p.nvr", "wb"); break; + default: return; } fwrite(nvrram,128,1,f); diff --git a/src/vt82c586b.c b/src/vt82c586b.c new file mode 100644 index 0000000..fd67002 --- /dev/null +++ b/src/vt82c586b.c @@ -0,0 +1,310 @@ +#include + +#include "ibm.h" +#include "io.h" +#include "mem.h" +#include "pci.h" +#include "x86.h" + +#include "vt82c586b.h" + +static struct +{ + uint8_t pci_isa_bridge_regs[256]; + uint8_t ide_regs[256]; + uint8_t usb_regs[256]; + uint8_t power_regs[256]; + + uint8_t sysctrl; +} vt82c586b; + +static uint8_t vt82c586b_read(int func, int addr, void *priv) +{ + switch (func) + { + case 0: + return vt82c586b.pci_isa_bridge_regs[addr]; + + case 1: + return vt82c586b.ide_regs[addr]; + + case 2: + return vt82c586b.usb_regs[addr]; + + case 3: + return vt82c586b.power_regs[addr]; + + default: + return 0xff; + } +} + +static void vt82c586b_pci_isa_bridge_write(int addr, uint8_t val) +{ + /*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 4: + vt82c586b.pci_isa_bridge_regs[4] = (val & 8) | 7; + break; + case 6: + vt82c586b.pci_isa_bridge_regs[6] &= ~(val & 0xb0); + break; + + case 0x47: + if ((val & 0x81) == 0x81) + resetx86(); + vt82c586b.pci_isa_bridge_regs[0x47] = val & 0xfe; + break; + + case 0x55: + if (!(val & 0xf0)) + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTD, val >> 4); + vt82c586b.pci_isa_bridge_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); + vt82c586b.pci_isa_bridge_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); + vt82c586b.pci_isa_bridge_regs[0x57] = val; + break; + + default: + vt82c586b.pci_isa_bridge_regs[addr] = val; + break; + } +} +static void vt82c586b_ide_write(int addr, uint8_t val) +{ + /*Read-only addresses*/ + if ((addr < 6) || (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 4: + vt82c586b.ide_regs[4] = (val & 8) | 7; + break; + case 6: + vt82c586b.ide_regs[6] &= ~(val & 0xb0); + break; + + case 9: + vt82c586b.ide_regs[9] = (vt82c586b.pci_isa_bridge_regs[9] & ~0x70) | 0x8a; + break; + + case 0x20: + vt82c586b.ide_regs[0x20] = (val & ~0xf) | 1; + break; + + default: + vt82c586b.ide_regs[addr] = val; + break; + } +} +static void vt82c586b_usb_write(int addr, uint8_t val) +{ + /*Read-only addresses*/ + if ((addr < 7) || (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 7: + vt82c586b.usb_regs[7] = val & 0x7f; + break; + + case 0x20: + vt82c586b.usb_regs[0x20] = (val & ~0x1f) | 1; + break; + + default: + vt82c586b.usb_regs[addr] = val; + break; + } +} +static void vt82c586b_power_write(int addr, uint8_t val) +{ + /*Read-only addresses*/ + if ((addr < 0xd) || (addr >= 0xe && addr < 0x40) + || (addr == 0x43) + || (addr == 0x48) + || (addr >= 0x4a && addr < 0x50) + || (addr >= 0x54)) + return; + + switch (addr) + { + default: + vt82c586b.power_regs[addr] = val; + break; + } +} + +static void vt82c586b_write(int func, int addr, uint8_t val, void *priv) +{ + switch (func) + { + case 0: + vt82c586b_pci_isa_bridge_write(addr, val); + break; + + case 1: + vt82c586b_ide_write(addr, val); + break; + + case 2: + vt82c586b_usb_write(addr, val); + break; + + case 3: + vt82c586b_power_write(addr, val); + break; + } +} + +uint8_t vt82c586b_read_sysctrl(uint16_t port, void *p) +{ + return vt82c586b.sysctrl; +} + +void vt82c586b_write_sysctrl(uint16_t port, uint8_t val, void *p) +{ + if ((mem_a20_alt ^ val) & 2) + { + mem_a20_alt = val & 2; + mem_a20_recalc(); + } + if ((~vt82c586b.sysctrl & val) & 1) + { + softresetx86(); + cpu_set_edx(); + } + vt82c586b.sysctrl = val; +} + +void vt82c586b_init(int card, int pci_a, int pci_b, int pci_c, int pci_d) +{ + pci_add_specific(card, vt82c586b_read, vt82c586b_write, NULL); + io_sethandler(0x0092, 0x0001, vt82c586b_read_sysctrl, NULL, NULL, vt82c586b_write_sysctrl, NULL, NULL, NULL); + + memset(&vt82c586b, 0, sizeof(vt82c586b)); + vt82c586b.pci_isa_bridge_regs[0x00] = 0x06; vt82c586b.pci_isa_bridge_regs[0x01] = 0x11; /*VIA*/ + vt82c586b.pci_isa_bridge_regs[0x02] = 0x86; vt82c586b.pci_isa_bridge_regs[0x03] = 0x05; /*VT82C586B*/ + vt82c586b.pci_isa_bridge_regs[0x04] = 0x0f; vt82c586b.pci_isa_bridge_regs[0x05] = 0x00; + vt82c586b.pci_isa_bridge_regs[0x06] = 0x00; vt82c586b.pci_isa_bridge_regs[0x07] = 0x02; + vt82c586b.pci_isa_bridge_regs[0x0a] = 0x01; + vt82c586b.pci_isa_bridge_regs[0x0b] = 0x06; + vt82c586b.pci_isa_bridge_regs[0x0e] = 0x80; + + /*ISA bus control*/ + vt82c586b.pci_isa_bridge_regs[0x48] = 0x01; + vt82c586b.pci_isa_bridge_regs[0x4a] = 0x04; + vt82c586b.pci_isa_bridge_regs[0x4f] = 0x03; + + /*Plug and Play control*/ + vt82c586b.pci_isa_bridge_regs[0x50] = 0x24; + vt82c586b.pci_isa_bridge_regs[0x59] = 0x04; + + vt82c586b.ide_regs[0x00] = 0x06; vt82c586b.ide_regs[0x01] = 0x11; /*VIA*/ + vt82c586b.ide_regs[0x02] = 0x71; vt82c586b.ide_regs[0x03] = 0x05; + vt82c586b.ide_regs[0x04] = 0x80; vt82c586b.ide_regs[0x05] = 0x00; + vt82c586b.ide_regs[0x06] = 0x80; vt82c586b.ide_regs[0x07] = 0x02; + vt82c586b.ide_regs[0x09] = 0x85; + vt82c586b.ide_regs[0x0a] = 0x01; + vt82c586b.ide_regs[0x0b] = 0x01; + + vt82c586b.ide_regs[0x10] = 0xf1; vt82c586b.ide_regs[0x11] = 0x01; + vt82c586b.ide_regs[0x14] = 0xf5; vt82c586b.ide_regs[0x15] = 0x03; + vt82c586b.ide_regs[0x18] = 0x71; vt82c586b.ide_regs[0x19] = 0x01; + vt82c586b.ide_regs[0x1c] = 0x75; vt82c586b.ide_regs[0x1d] = 0x03; + vt82c586b.ide_regs[0x20] = 0x01; vt82c586b.ide_regs[0x21] = 0xcc; + vt82c586b.ide_regs[0x3c] = 0x0e; + + vt82c586b.ide_regs[0x40] = 0x08; + vt82c586b.ide_regs[0x41] = 0x02; + vt82c586b.ide_regs[0x42] = 0x09; + vt82c586b.ide_regs[0x43] = 0x3a; + vt82c586b.ide_regs[0x44] = 0x68; + vt82c586b.ide_regs[0x46] = 0xc0; + vt82c586b.ide_regs[0x48] = 0xa8; + vt82c586b.ide_regs[0x49] = 0xa8; + vt82c586b.ide_regs[0x4a] = 0xa8; + vt82c586b.ide_regs[0x4b] = 0xa8; + vt82c586b.ide_regs[0x4c] = 0xff; + vt82c586b.ide_regs[0x4e] = 0xff; + vt82c586b.ide_regs[0x4f] = 0xff; + vt82c586b.ide_regs[0x50] = 0x03; + vt82c586b.ide_regs[0x51] = 0x03; + vt82c586b.ide_regs[0x52] = 0x03; + vt82c586b.ide_regs[0x53] = 0x03; + vt82c586b.ide_regs[0x61] = 0x02; + vt82c586b.ide_regs[0x68] = 0x02; + + vt82c586b.usb_regs[0x00] = 0x06; vt82c586b.usb_regs[0x01] = 0x11; /*VIA*/ + vt82c586b.usb_regs[0x02] = 0x38; vt82c586b.usb_regs[0x03] = 0x30; + vt82c586b.usb_regs[0x04] = 0x00; vt82c586b.usb_regs[0x05] = 0x00; + vt82c586b.usb_regs[0x06] = 0x00; vt82c586b.usb_regs[0x07] = 0x02; + vt82c586b.usb_regs[0x0a] = 0x03; + vt82c586b.usb_regs[0x0b] = 0x0c; + vt82c586b.usb_regs[0x0d] = 0x16; + vt82c586b.usb_regs[0x20] = 0x01; + vt82c586b.usb_regs[0x21] = 0x03; + vt82c586b.usb_regs[0x3d] = 0x04; + + vt82c586b.usb_regs[0x60] = 0x10; + vt82c586b.usb_regs[0xc1] = 0x20; + + vt82c586b.power_regs[0x00] = 0x06; vt82c586b.power_regs[0x01] = 0x11; /*VIA*/ + vt82c586b.power_regs[0x02] = 0x40; vt82c586b.power_regs[0x03] = 0x30; + vt82c586b.power_regs[0x04] = 0x00; vt82c586b.power_regs[0x05] = 0x00; + vt82c586b.power_regs[0x06] = 0x80; vt82c586b.power_regs[0x07] = 0x02; + vt82c586b.power_regs[0x08] = 0x10; /*Production version (3041)*/ + vt82c586b.power_regs[0x48] = 0x01; + + if (pci_a) + pci_set_card_routing(pci_a, PCI_INTA); + if (pci_b) + pci_set_card_routing(pci_b, PCI_INTB); + if (pci_c) + pci_set_card_routing(pci_c, PCI_INTC); + if (pci_d) + pci_set_card_routing(pci_d, PCI_INTD); +} diff --git a/src/vt82c586b.h b/src/vt82c586b.h new file mode 100644 index 0000000..0f6981f --- /dev/null +++ b/src/vt82c586b.h @@ -0,0 +1 @@ +void vt82c586b_init(int card, int pci_a, int pci_b, int pci_c, int pci_d); diff --git a/src/w83877tf.c b/src/w83877tf.c new file mode 100644 index 0000000..78c2a63 --- /dev/null +++ b/src/w83877tf.c @@ -0,0 +1,202 @@ +#include "ibm.h" + +#include "fdc.h" +#include "io.h" +#include "lpt.h" +#include "serial.h" +#include "w83877tf.h" + +typedef struct w83877tf_t +{ + int enable_regs; + uint8_t key[2]; + int index; + uint8_t regs[256]; +} w83877tf_t; + +static w83877tf_t w83877tf_global; + +static void w83877tf_write_25x(uint16_t port, uint8_t val, void *p); +static uint8_t w83877tf_read_25x(uint16_t port, void *p); +static void w83877tf_write_3fx(uint16_t port, uint8_t val, void *p); +static uint8_t w83877tf_read_3fx(uint16_t port, void *p); + +static void w83877tf_write_reg(w83877tf_t *w83877tf, int index, uint8_t val) +{ +// pclog("w83877tf_write: index=%02x val=%02x\n", index, val); + switch (index) + { + case 0x16: + if (val == 2) /*Written by VA-503+ BIOS. Apparently should not change IO mapping*/ + return; + + io_removehandler(0x0250, 0x0003, w83877tf_read_25x, NULL, NULL, w83877tf_write_25x, NULL, NULL, &w83877tf_global); + io_removehandler(0x03f0, 0x0002, w83877tf_read_3fx, NULL, NULL, w83877tf_write_3fx, NULL, NULL, &w83877tf_global); + if (val & 0x01) + io_sethandler(0x03f0, 0x0002, w83877tf_read_3fx, NULL, NULL, w83877tf_write_3fx, NULL, NULL, &w83877tf_global); + else + io_sethandler(0x0250, 0x0003, w83877tf_read_25x, NULL, NULL, w83877tf_write_25x, NULL, NULL, &w83877tf_global); + + if ((w83877tf->regs[0x16] & 4) && !(val & 4)) + { + w83877tf->regs[0x20] = 0; + w83877tf->regs[0x23] = 0; + w83877tf->regs[0x24] = 0; + w83877tf->regs[0x25] = 0; + w83877tf->regs[0x26] = 0; + w83877tf->regs[0x27] = 0; + w83877tf->regs[0x28] = 0; + w83877tf->regs[0x29] = 0; + } + break; + } + + w83877tf->regs[index] = val; + + + fdc_remove(); + if (w83877tf->regs[0x20] >= 0x40) + fdc_add(); + + lpt1_remove(); + lpt2_remove(); + if (w83877tf->regs[0x23] >= 0x40) + lpt1_init(w83877tf->regs[0x23] << 2); + + serial1_remove(); + if (w83877tf->regs[0x24] >= 0x40) + serial1_set((w83877tf->regs[0x24] & ~1) << 2, w83877tf->regs[0x28] >> 4); + + serial2_remove(); + if (w83877tf->regs[0x25] >= 0x40) + serial2_set((w83877tf->regs[0x25] & ~1) << 2, w83877tf->regs[0x28] & 0xf); + +// pclog("LPT at %04x\n", w83877tf->regs[0x23] << 2); +// pclog("Serial1 at %04x %i\n", (w83877tf->regs[0x24] & ~1) << 2, w83877tf->regs[0x28] >> 4); +// pclog("Serial2 at %04x %i\n", (w83877tf->regs[0x25] & ~1) << 2, w83877tf->regs[0x28] & 0xf); +} + +static uint8_t w83877tf_read_reg(w83877tf_t *w83877tf, int index) +{ + switch (w83877tf->index) + { + case 0x09: + return 0x0c; /*W83877TF ID*/ + } + return w83877tf->regs[index]; +} + +static void w83877tf_write_25x(uint16_t port, uint8_t val, void *p) +{ + w83877tf_t *w83877tf = (w83877tf_t *)p; + +// pclog("w83877tf_write: port=%04x val=%02x\n", port, val); + + switch (port) + { + case 0x250: /*Enable register*/ + w83877tf->enable_regs = (val == 0x89) ? 1 : 0; + break; + case 0x251: /*Index*/ + if (w83877tf->enable_regs) + w83877tf->index = val; + break; + case 0x252: /*Data*/ + if (w83877tf->enable_regs) + w83877tf_write_reg(w83877tf, w83877tf->index, val); + break; + } +} + +static uint8_t w83877tf_read_25x(uint16_t port, void *p) +{ + w83877tf_t *w83877tf = (w83877tf_t *)p; + + switch (port) + { + case 0x251: /*Index*/ + if (w83877tf->enable_regs) + return w83877tf->index; + break; + + case 0x252: /*Data*/ + if (w83877tf->enable_regs) + return w83877tf_read_reg(w83877tf, w83877tf->index); + break; + } + + return 0xff; +} + +static void w83877tf_write_3fx(uint16_t port, uint8_t val, void *p) +{ + w83877tf_t *w83877tf = (w83877tf_t *)p; + +// pclog("w83877tf_write: port=%04x val=%02x\n", port, val); + + switch (port) + { + case 0x3f0: /*Enable/index register*/ + if (val == 0xaa) + w83877tf->enable_regs = 0; + else if (!w83877tf->enable_regs) + { + w83877tf->key[1] = w83877tf->key[0]; + w83877tf->key[0] = val; + w83877tf->enable_regs = (w83877tf->key[0] == 0x87 && w83877tf->key[1] == 0x87); + } + else + w83877tf->index = val; + break; + case 0x3f1: /*Data*/ + if (w83877tf->enable_regs) + w83877tf_write_reg(w83877tf, w83877tf->index, val); + break; + } +} + +static uint8_t w83877tf_read_3fx(uint16_t port, void *p) +{ + w83877tf_t *w83877tf = (w83877tf_t *)p; + uint8_t ret = 0xff; + + switch (port) + { + case 0x3f0: /*Index*/ + if (w83877tf->enable_regs) + ret = w83877tf->index; + break; + + case 0x3f1: /*Data*/ + if (w83877tf->enable_regs) + ret = w83877tf_read_reg(w83877tf, w83877tf->index); + break; + } + +// pclog("w83877tf_read: port=%04x val=%02x\n", port, ret); + + return ret; +} + +void w83877tf_init() +{ + memset(&w83877tf_global, 0, sizeof(w83877tf_t)); + + io_sethandler(0x0250, 0x0003, w83877tf_read_25x, NULL, NULL, w83877tf_write_25x, NULL, NULL, &w83877tf_global); + + /*Defaults*/ + w83877tf_global.regs[0x03] = 0x30; + w83877tf_global.regs[0x09] = 0x0c; + w83877tf_global.regs[0x0b] = 0x0c; + w83877tf_global.regs[0x0c] = 0x28; + w83877tf_global.regs[0x0d] = 0xa3; + w83877tf_global.regs[0x16] = 0x04; + w83877tf_global.regs[0x20] = 0xfc; + w83877tf_global.regs[0x23] = 0xde; + w83877tf_global.regs[0x24] = 0xfe; + w83877tf_global.regs[0x25] = 0xbe; + w83877tf_global.regs[0x26] = 0x23; + w83877tf_global.regs[0x27] = 0x05; + w83877tf_global.regs[0x28] = 0x43; + w83877tf_global.regs[0x29] = 0x60; +} diff --git a/src/w83877tf.h b/src/w83877tf.h new file mode 100644 index 0000000..dcfb853 --- /dev/null +++ b/src/w83877tf.h @@ -0,0 +1 @@ +void w83877tf_init();