Improved the VIA VPX code

Moved host bridge write code via_vpx_write.
Default registers are now on via_vpx_init.
Read only registers are hardcoded.
This commit is contained in:
tiseno100
2020-04-29 10:50:53 +03:00
committed by GitHub
parent 19eed0a404
commit 570034cb09

View File

@@ -12,6 +12,9 @@ VIA Apollo VPX North Bridge emulation
VT82C585VPX used in the Zida Tomato TX100 board VT82C585VPX used in the Zida Tomato TX100 board
based on the model of VIA MVP3 by mooch & Sarah based on the model of VIA MVP3 by mooch & Sarah
There's also a SOYO board using the ETEQ chipset which is a rebranded
VPX + 586B but fails to save on CMOS properly.
Authors: Sarah Walker, <http://pcem-emulator.co.uk/> Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
Copyright(C) 2020 Tiseno100 Copyright(C) 2020 Tiseno100
Copyright(C) 2020 Melissa Goad Copyright(C) 2020 Melissa Goad
@@ -35,7 +38,7 @@ Copyright(C) 2020 Miran Grca
typedef struct via_vpx_t typedef struct via_vpx_t
{ {
uint8_t pci_conf[2][256]; uint8_t pci_conf[256];
} via_vpx_t; } via_vpx_t;
static void static void
@@ -60,109 +63,63 @@ vpx_map(uint32_t addr, uint32_t size, int state)
} }
static void static void
via_vpx_pci_regs(via_vpx_t *dev) via_vpx_write(int func, int addr, uint8_t val, void *priv)
{
memset(dev, 0, sizeof(via_vpx_t));
// Host Bridge registers
dev->pci_conf[0][0x00] = 0x06; // VIA
dev->pci_conf[0][0x01] = 0x11;
dev->pci_conf[0][0x02] = 0x85; // VT82C585VPX
dev->pci_conf[0][0x03] = 0x05;
dev->pci_conf[0][0x04] = 7; // Command
dev->pci_conf[0][0x05] = 0;
dev->pci_conf[0][0x06] = 0xa0; // Status
dev->pci_conf[0][0x07] = 2;
dev->pci_conf[0][0x09] = 0; // Program Interface
dev->pci_conf[0][0x0a] = 0; // Sub Class Code
dev->pci_conf[0][0x0b] = 6; // Base Class Code
dev->pci_conf[0][0x0c] = 0; // reserved
dev->pci_conf[0][0x0d] = 0; // Latency Timer
dev->pci_conf[0][0x0e] = 0; // Header Type
dev->pci_conf[0][0x0f] = 0; // Built-in Self test
dev->pci_conf[0][0x58] = 0x40; // DRAM Configuration 1
dev->pci_conf[0][0x59] = 5; // DRAM Configuration 2
dev->pci_conf[0][0x5a] = 1; // Bank 0 Ending
dev->pci_conf[0][0x5b] = 1; // Bank 1 Ending
dev->pci_conf[0][0x5c] = 1; // Bank 2 Ending
dev->pci_conf[0][0x5d] = 1; // Bank 3 Ending
dev->pci_conf[0][0x5e] = 1; // Bank 4 Ending
dev->pci_conf[0][0x5f] = 1; // Bank 5 Ending
dev->pci_conf[0][0x64] = 0xab; // DRAM reference timing
}
static void
host_bridge_write(int func, int addr, uint8_t val, void *priv)
{ {
via_vpx_t *dev = (via_vpx_t *) priv; via_vpx_t *dev = (via_vpx_t *) priv;
// Read-Only registers. Exact same as MVP3 // Read-Only registers
if ((addr < 4) || ((addr >= 5) && (addr < 7)) || ((addr >= 8) && (addr < 0xd)) || ((addr >= 0xe) && (addr < 0x12)) || switch(addr){
((addr >= 0x14) && (addr < 0x50)) || ((addr >= 0x79) && (addr < 0x7e)) || ((addr >= 0x85) && (addr < 0x88)) || case 0x00: case 0x01: case 0x02: case 0x03:
((addr >= 0x8c) && (addr < 0xa8)) || ((addr >= 0xad) && (addr < 0xfd))) case 0x08: case 0x09: case 0x0a: case 0x0b:
return; case 0x0e: case 0x0f:
return;
}
switch(addr){ switch(addr){
case 0x04: // Command case 0x04: // Command. On Bitfield 6 RW
dev->pci_conf[0][0x04] = (dev->pci_conf[0][0x04] & ~0x40) | (val & 0x40); dev->pci_conf[0x04] = (dev->pci_conf[0x04] & ~0x40) | (val & 0x40);
case 0x07: // Status case 0x07: // Status
dev->pci_conf[0][0x07] &= ~(val & 0xb0); dev->pci_conf[0x07] &= ~(val & 0xb0);
break; break;
case 0x61: // Shadow RAM control 1 case 0x61: // Shadow RAM control 1
if ((dev->pci_conf[0][0x61] ^ val) & 0x03) if ((dev->pci_conf[0x61] ^ val) & 0x03)
vpx_map(0xc0000, 0x04000, val & 0x03); vpx_map(0xc0000, 0x04000, val & 0x03);
if ((dev->pci_conf[0][0x61] ^ val) & 0x0c) if ((dev->pci_conf[0x61] ^ val) & 0x0c)
vpx_map(0xc4000, 0x04000, (val & 0x0c) >> 2); vpx_map(0xc4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->pci_conf[0][0x61] ^ val) & 0x30) if ((dev->pci_conf[0x61] ^ val) & 0x30)
vpx_map(0xc8000, 0x04000, (val & 0x30) >> 4); vpx_map(0xc8000, 0x04000, (val & 0x30) >> 4);
if ((dev->pci_conf[0][0x61] ^ val) & 0xc0) if ((dev->pci_conf[0x61] ^ val) & 0xc0)
vpx_map(0xcc000, 0x04000, (val & 0xc0) >> 6); vpx_map(0xcc000, 0x04000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x61] = val; dev->pci_conf[0x61] = val;
return; return;
case 0x62: // Shadow RAM Control 2 case 0x62: // Shadow RAM Control 2
if ((dev->pci_conf[0][0x62] ^ val) & 0x03) if ((dev->pci_conf[0x62] ^ val) & 0x03)
vpx_map(0xd0000, 0x04000, val & 0x03); vpx_map(0xd0000, 0x04000, val & 0x03);
if ((dev->pci_conf[0][0x62] ^ val) & 0x0c) if ((dev->pci_conf[0x62] ^ val) & 0x0c)
vpx_map(0xd4000, 0x04000, (val & 0x0c) >> 2); vpx_map(0xd4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->pci_conf[0][0x62] ^ val) & 0x30) if ((dev->pci_conf[0x62] ^ val) & 0x30)
vpx_map(0xd8000, 0x04000, (val & 0x30) >> 4); vpx_map(0xd8000, 0x04000, (val & 0x30) >> 4);
if ((dev->pci_conf[0][0x62] ^ val) & 0xc0) if ((dev->pci_conf[0x62] ^ val) & 0xc0)
vpx_map(0xdc000, 0x04000, (val & 0xc0) >> 6); vpx_map(0xdc000, 0x04000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x62] = val; dev->pci_conf[0x62] = val;
return; return;
case 0x63: // Shadow RAM Control 3 case 0x63: // Shadow RAM Control 3
if ((dev->pci_conf[0][0x63] ^ val) & 0x30) { if ((dev->pci_conf[0x63] ^ val) & 0x30) {
vpx_map(0xf0000, 0x10000, (val & 0x30) >> 4); vpx_map(0xf0000, 0x10000, (val & 0x30) >> 4);
shadowbios = (((val & 0x30) >> 4) & 0x02); shadowbios = (((val & 0x30) >> 4) & 0x02);
} }
if ((dev->pci_conf[0][0x63] ^ val) & 0xc0) if ((dev->pci_conf[0x63] ^ val) & 0xc0)
vpx_map(0xe0000, 0x10000, (val & 0xc0) >> 6); vpx_map(0xe0000, 0x10000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x63] = val; dev->pci_conf[0x63] = val;
return; return;
//In case we throw somewhere
default: default:
dev->pci_conf[0][addr] = val; dev->pci_conf[addr] = val;
break; break;
} }
} }
@@ -175,19 +132,13 @@ via_vpx_read(int func, int addr, void *priv)
switch(func) { switch(func) {
case 0: case 0:
ret = dev->pci_conf[0][addr]; ret = dev->pci_conf[addr];
break; break;
} }
return ret; return ret;
} }
static void
via_vpx_write(int func, int addr, uint8_t val, void *priv)
{
host_bridge_write(func, addr, val, priv);
}
static void static void
via_vpx_reset(void *priv) via_vpx_reset(void *priv)
{ {
@@ -198,10 +149,47 @@ static void *
via_vpx_init(const device_t *info) via_vpx_init(const device_t *info)
{ {
via_vpx_t *dev = (via_vpx_t *) malloc(sizeof(via_vpx_t)); via_vpx_t *dev = (via_vpx_t *) malloc(sizeof(via_vpx_t));
memset(dev, 0, sizeof(via_vpx_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, via_vpx_read, via_vpx_write, dev); pci_add_card(PCI_ADD_NORTHBRIDGE, via_vpx_read, via_vpx_write, dev);
via_vpx_pci_regs(dev); dev->pci_conf[0x00] = 0x06; // VIA
dev->pci_conf[0x01] = 0x11;
dev->pci_conf[0x02] = 0x85; // VT82C585VPX
dev->pci_conf[0x03] = 0x05;
dev->pci_conf[0x04] = 7; // Command
dev->pci_conf[0x05] = 0;
dev->pci_conf[0x06] = 0xa0; // Status
dev->pci_conf[0x07] = 2;
dev->pci_conf[0x09] = 0; // Program Interface
dev->pci_conf[0x0a] = 0; // Sub Class Code
dev->pci_conf[0x0b] = 6; // Base Class Code
dev->pci_conf[0x0c] = 0; // reserved
dev->pci_conf[0x0d] = 0; // Latency Timer
dev->pci_conf[0x0e] = 0; // Header Type
dev->pci_conf[0x0f] = 0; // Built-in Self test
dev->pci_conf[0x58] = 0x40; // DRAM Configuration 1
dev->pci_conf[0x59] = 0x05; // DRAM Configuration 2
dev->pci_conf[0x5a] = 1; // Bank 0 Ending
dev->pci_conf[0x5b] = 1; // Bank 1 Ending
dev->pci_conf[0x5c] = 1; // Bank 2 Ending
dev->pci_conf[0x5d] = 1; // Bank 3 Ending
dev->pci_conf[0x5e] = 1; // Bank 4 Ending
dev->pci_conf[0x5f] = 1; // Bank 5 Ending
dev->pci_conf[0x64] = 0xab; // DRAM reference timing
return dev; return dev;
} }