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.
This commit is contained in:
SarahW 2018-12-02 12:38:31 +00:00
commit 99ca11d148
10 changed files with 765 additions and 2 deletions

View file

@ -465,6 +465,7 @@ enum
ROM_XI8088, ROM_XI8088,
ROM_IBMPS2_M70_TYPE3, ROM_IBMPS2_M70_TYPE3,
ROM_IBMPS2_M70_TYPE4, ROM_IBMPS2_M70_TYPE4,
ROM_FIC_VA503P,
ROM_MAX ROM_MAX
}; };

View file

@ -900,6 +900,14 @@ int loadbios()
fclose(f); fclose(f);
biosmask = 0x1ffff; biosmask = 0x1ffff;
return 1; 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"); printf("Failed to load ROM!\n");
if (f) fclose(f); if (f) fclose(f);

View file

@ -34,6 +34,7 @@
#include "lpt.h" #include "lpt.h"
#include "mem.h" #include "mem.h"
#include "mouse_ps2.h" #include "mouse_ps2.h"
#include "mvp3.h"
#include "neat.h" #include "neat.h"
#include "nmi.h" #include "nmi.h"
#include "nvr.h" #include "nvr.h"
@ -61,6 +62,8 @@
#include "vid_pcjr.h" #include "vid_pcjr.h"
#include "vid_tandy.h" #include "vid_tandy.h"
#include "vid_t1000.h" #include "vid_t1000.h"
#include "vt82c586b.h"
#include "w83877tf.h"
#include "wd76c10.h" #include "wd76c10.h"
#include "xi8088.h" #include "xi8088.h"
@ -106,6 +109,7 @@ void at_pb520r_init();
void at_pb570_init(); void at_pb570_init();
void compaq_pip_init(); void compaq_pip_init();
void xt_xi8088_init(); void xt_xi8088_init();
void at_mvp3_init();
int model; int model;
int AMSTRAD, AT, PCI, TANDY; 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}, {"[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} {"", -1, "", {{"", 0}, {"", 0}, {"", 0}}, 0,0,0, 0}
}; };
@ -659,6 +665,18 @@ void at_i430vx_init()
device_add(&intel_flash_bxt_device); 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() void model_init()
{ {
pclog("Initting as %s\n", model_getname()); pclog("Initting as %s\n", model_getname());

219
src/mvp3.c Normal file
View file

@ -0,0 +1,219 @@
#include <string.h>
#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;
}

1
src/mvp3.h Normal file
View file

@ -0,0 +1 @@
void mvp3_init();

View file

@ -306,6 +306,7 @@ void loadnvr()
case ROM_XI8088: f = nvrfopen("xi8088.nvr", "rb"); nvrmask = 127; break; 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_TYPE3: f = nvrfopen("ibmps2_m70_type3.nvr","rb"); break;
case ROM_IBMPS2_M70_TYPE4: f = nvrfopen("ibmps2_m70_type4.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; default: return;
} }
@ -396,6 +397,7 @@ void savenvr()
case ROM_XI8088: f = nvrfopen("xi8088.nvr", "wb"); break; 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_TYPE3: f = nvrfopen("ibmps2_m70_type3.nvr","wb"); break;
case ROM_IBMPS2_M70_TYPE4: f = nvrfopen("ibmps2_m70_type4.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; default: return;
} }

310
src/vt82c586b.c Normal file
View file

@ -0,0 +1,310 @@
#include <string.h>
#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);
}

1
src/vt82c586b.h Normal file
View file

@ -0,0 +1 @@
void vt82c586b_init(int card, int pci_a, int pci_b, int pci_c, int pci_d);

202
src/w83877tf.c Normal file
View file

@ -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;
}

1
src/w83877tf.h Normal file
View file

@ -0,0 +1 @@
void w83877tf_init();