Fixed SMM, overhauled the emulation of the VIA northbridges, and added the Via Apollo VP3.

This commit is contained in:
OBattler
2020-04-01 08:59:29 +02:00
parent 2c8bcea38c
commit b8b198a56a
37 changed files with 1915 additions and 5024 deletions

View File

@@ -51,7 +51,8 @@ enum
typedef struct
{
uint8_t pm2_cntrl, max_func;
uint8_t pm2_cntrl, max_func,
smram_locked;
uint8_t regs[2][256], regs_locked[2][256];
int type;
} i4x0_t;
@@ -78,6 +79,127 @@ i4x0_map(uint32_t addr, uint32_t size, int state)
}
static void
i4x0_smram_map(int smm, uint32_t addr, uint32_t size, int ram)
{
int state = ram ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
mem_set_mem_state_common(smm, addr, size, state);
flushmmucache();
}
static void
i4x0_smram_handler_phase0(i4x0_t *dev)
{
uint32_t i, n;
/* Disable any active mappings. */
if (dev->type >= INTEL_430FX) {
if (dev->type >= INTEL_440BX) {
/* Disable high extended SMRAM. */
/* TODO: This area should point to A0000-FFFFF. */
for (i = 0x100a0000; i < 0x100fffff; i += MEM_GRANULARITY_SIZE) {
/* This is to make sure that if the remaining area is smaller than
or equal to MEM_GRANULARITY_SIZE, we do not change the state of
too much memory. */
n = ((mem_size << 10) - i);
/* Cap to MEM_GRANULARITY_SIZE if i is either at or beyond the end
of RAM or the remaining area is bigger than MEM_GRANULARITY_SIZE. */
if ((i >= (mem_size << 10)) || (n > MEM_GRANULARITY_SIZE))
n = MEM_GRANULARITY_SIZE;
i4x0_smram_map(0, i, n, (i < (mem_size << 10)));
i4x0_smram_map(1, i, n, (i < (mem_size << 10)));
if (n < MEM_GRANULARITY_SIZE) {
i4x0_smram_map(0, i + n, MEM_GRANULARITY_SIZE - n, 0);
i4x0_smram_map(1, i + n, MEM_GRANULARITY_SIZE - n, 0);
}
}
/* Disable TSEG. */
i4x0_smram_map(1, ((mem_size << 10) - (1 << 20)), (1 << 20), 1);
}
/* Disable low extended SMRAM. */
i4x0_smram_map(0, 0xa0000, 0x20000, 0);
i4x0_smram_map(1, 0xa0000, 0x20000, 0);
} else {
/* Disable low extended SMRAM. */
i4x0_smram_map(0, 0xa0000, 0x20000, 0);
i4x0_smram_map(0, (mem_size << 10) - 0x10000, 0x10000, 1);
i4x0_smram_map(1, 0xa0000, 0x20000, 0);
i4x0_smram_map(1, (mem_size << 10) - 0x10000, 0x10000, 1);
}
}
static void
i4x0_smram_handler_phase1(i4x0_t *dev)
{
uint8_t *regs = (uint8_t *) dev->regs[0];
uint32_t s, base[2] = { 0x000a0000, 0x00020000 };
uint32_t size[2] = { 0, 0 };
if (dev->type >= INTEL_430FX) {
/* Set temporary bases and sizes. */
if ((dev->type >= INTEL_440BX) && (regs[0x73] & 0x80)) {
base[0] = 0x100a0000;
size[0] = 0x00060000;
} else {
base[0] = 0x000a0000;
size[0] = 0x00020000;
}
/* If D_OPEN = 1 and D_LCK = 0, extended SMRAM is visible outside SMM. */
i4x0_smram_map(0, base[0], size[0], ((regs[0x72] & 0x70) == 0x40));
/* If the register is set accordingly, disable the mapping also in SMM. */
i4x0_smram_map(1, base[0], size[0], ((regs[0x72] & 0x08) && !(regs[0x72] & 0x20)));
/* TSEG mapping. */
if (dev->type >= INTEL_440BX) {
if ((regs[0x72] & 0x08) && (regs[0x73] & 0x01)) {
size[1] = (1 << (17 + ((regs[0x73] >> 1) & 0x03)));
base[1] = (mem_size << 10) - size[1];
} else
base[1] = size[1] = 0x00000000;
i4x0_smram_map(1, base[1], size[1], 1);
} else
base[1] = size[1] = 0x00000000;
} else {
size[0] = 0x00010000;
switch (regs[0x72] & 0x03) {
case 0:
default:
base[0] = (mem_size << 10) - size[0];
s = 1;
break;
case 1:
base[0] = size[0] = 0x00000000;
s = 1;
break;
case 2:
base[0] = 0x000a0000;
s = 0;
break;
case 3:
base[0] = 0x000b0000;
s = 0;
break;
}
if (base[0] != 0x00000000) {
/* If OSS = 1 and LSS = 0, extended SMRAM is visible outside SMM. */
i4x0_smram_map(0, base[0], size[0], ((regs[0x72] & 0x38) == 0x20) || s);
/* If the register is set accordingly, disable the mapping also in SMM. */
i4x0_smram_map(0, base[0], size[0], !(regs[0x72] & 0x10) || s);
}
}
}
static void
i4x0_mask_bar(uint8_t *regs)
{
@@ -636,19 +758,27 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
}
break;
case 0x72: /* SMRAM */
i4x0_smram_handler_phase0(dev);
if (dev->type >= INTEL_430FX) {
if ((regs[0x72] & 0x10) || (val & 0x10)) {
regs[0x72] = (val & 0x38) | 0x02;
i4x0_map(0xa0000, 0x20000, 0);
} else {
regs[0x72] = (val & 0x78) | 0x02;
i4x0_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0);
if (dev->smram_locked)
regs[0x72] = (regs[0x72] & 0xdf) | (val & 0x20);
else {
regs[0x72] = (regs[0x72] & 0x87) | (val & 0x78);
dev->smram_locked = (val & 0x10);
if (dev->smram_locked)
regs[0x72] &= 0xbf;
}
} else {
if ((regs[0x72] ^ val) & 0x20)
i4x0_map(0xa0000, 0x20000, ((val & 0x20) == 0x20) ? 3 : 0);
regs[0x72] = val & 0x3f;
if (dev->smram_locked)
regs[0x72] = (regs[0x72] & 0xef) | (val & 0x10);
else {
regs[0x72] = (regs[0x72] & 0xc0) | (val & 0x3f);
dev->smram_locked = (val & 0x08);
if (dev->smram_locked)
regs[0x72] &= 0xef;
}
}
i4x0_smram_handler_phase1(dev);
break;
case 0x73:
switch (dev->type) {
@@ -656,7 +786,11 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
regs[0x73] = val & 0x03;
break;
case INTEL_440BX: case INTEL_440ZX:
regs[0x73] = val;
if (!dev->smram_locked) {
i4x0_smram_handler_phase0(dev);
regs[0x73] = (regs[0x72] & 0x38) | (val & 0xc7);
i4x0_smram_handler_phase1(dev);
}
break;
}
break;

587
src/chipset/via_apollo.c Normal file
View File

@@ -0,0 +1,587 @@
/*
* 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 Apollo series of chips.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Melissa Goad, <mszoopers@protonmail.com>
* Tiseno100,
*
* Copyright 2020 Miran Grca.
* Copyright 2020 Melissa Goad.
* Copyright 2020 Tiseno100.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/mem.h>
#include <86box/io.h>
#include <86box/rom.h>
#include <86box/pci.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/chipset.h>
typedef struct via_apollo_t
{
uint16_t id;
uint8_t pci_conf[2][256];
} via_apollo_t;
static void
apollo_map(uint32_t addr, uint32_t size, int state)
{
switch (state & 3) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 3:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
flushmmucache_nopc();
}
static void
apollo_smram_map(int smm, uint32_t addr, uint32_t size, int ram)
{
int state = (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if (ram == 0)
state = (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else if (ram == 1)
state = (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else if (ram == 2)
state = (MEM_READ_EXTERNAL_EX | MEM_WRITE_EXTANY);
else if (ram == 3)
state = (MEM_READ_DISABLED | MEM_WRITE_DISABLED);
mem_set_mem_state_common(smm, addr, size, state);
flushmmucache();
}
static void
via_apollo_setup(via_apollo_t *dev)
{
memset(dev, 0, sizeof(via_apollo_t));
/* Host Bridge */
dev->pci_conf[0][0x00] = 0x06; /*VIA*/
dev->pci_conf[0][0x01] = 0x11;
dev->pci_conf[0][0x02] = dev->id & 0xff;
dev->pci_conf[0][0x03] = (dev->id >> 8);
dev->pci_conf[0][0x04] = 6;
dev->pci_conf[0][0x05] = 0;
dev->pci_conf[0][0x06] = 0x90;
dev->pci_conf[0][0x07] = 0x02;
if (dev->id == 0x0597)
dev->pci_conf[0][0x08] = 1; /* Production Silicon ("Revision B") */
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;
if (dev->id == 0x0691) {
dev->pci_conf[0][0x56] = 0x01;
dev->pci_conf[0][0x57] = 0x01;
}
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;
if (dev->id == 0x0691)
dev->pci_conf[0][0x67] = 0xec; /* DRAM Timing for Banks 6,7. */
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] = dev->id & 0xff;
dev->pci_conf[1][0x03] = (dev->id >> 8) | 0x80;
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_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
{
via_apollo_t *dev = (via_apollo_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 == 0x69) || ((addr >= 0x79) && (addr < 0x7e)) ||
((addr >= 0x81) && (addr < 0x84)) || ((addr >= 0x85) && (addr < 0x88)) ||
((addr >= 0x8c) && (addr < 0xa8)) || ((addr >= 0xaa) && (addr < 0xac)) ||
((addr >= 0xad) && (addr < 0xf0)) || ((addr >= 0xf8) && (addr < 0xfc)) ||
(addr == 0xfd))
return;
if (((addr == 0x78) || (addr >= 0xad)) && (dev->id == 0x0597))
return;
if (((addr == 0x67) || ((addr >= 0xf0) && (addr < 0xfc))) && (dev->id != 0x0691))
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);
break;
case 0x0d:
dev->pci_conf[0][0x0d] = (dev->pci_conf[0][0x0d] & ~0x07) | (val & 0x07);
dev->pci_conf[0][0x75] = (dev->pci_conf[0][0x75] & ~0x30) | ((val & 0x06) << 3);
break;
case 0x12: /* Graphics Aperture Base */
dev->pci_conf[0][0x12] = (val & 0xf0);
break;
case 0x13: /* Graphics Aperture Base */
dev->pci_conf[0][0x13] = val;
break;
case 0x50: /* Cache Control 1 */
if (dev->id == 0x0691)
dev->pci_conf[0][0x50] = val;
else
dev->pci_conf[0][0x50] = (dev->pci_conf[0][0x50] & ~0xf8) | (val & 0xf8);
break;
case 0x51: /* Cache Control 2 */
if (dev->id == 0x0691)
dev->pci_conf[0][0x51] = val;
else
dev->pci_conf[0][0x51] = (dev->pci_conf[0][0x51] & ~0xeb) | (val & 0xeb);
break;
case 0x52: /* Non_Cacheable Control */
if (dev->id == 0x0691)
dev->pci_conf[0][0x52] = (dev->pci_conf[0][0x52] & ~0x9f) | (val & 0x9f);
else
dev->pci_conf[0][0x52] = (dev->pci_conf[0][0x52] & ~0xf5) | (val & 0xf5);
break;
case 0x53: /* System Performance Control */
if (dev->id == 0x0691)
dev->pci_conf[0][0x53] = val;
else
dev->pci_conf[0][0x53] = (dev->pci_conf[0][0x53] & ~0xf0) | (val & 0xf0);
break;
case 0x58:
if (dev->id == 0x0597)
dev->pci_conf[0][0x58] = (dev->pci_conf[0][0x58] & ~0xee) | (val & 0xee);
else
dev->pci_conf[0][0x58] = val;
break;
case 0x59:
if (dev->id == 0x0691)
dev->pci_conf[0][0x59] = val;
else
dev->pci_conf[0][0x59] = (dev->pci_conf[0][0x59] & ~0xf0) | (val & 0xf0);
break;
case 0x61: /* Shadow RAM Control 1 */
if ((dev->pci_conf[0][0x61] ^ val) & 0x03)
apollo_map(0xc0000, 0x04000, val & 0x03);
if ((dev->pci_conf[0][0x61] ^ val) & 0x0c)
apollo_map(0xc4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->pci_conf[0][0x61] ^ val) & 0x30)
apollo_map(0xc8000, 0x04000, (val & 0x30) >> 4);
if ((dev->pci_conf[0][0x61] ^ val) & 0xc0)
apollo_map(0xcc000, 0x04000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x61] = val;
break;
case 0x62: /* Shadow RAM Control 2 */
if ((dev->pci_conf[0][0x62] ^ val) & 0x03)
apollo_map(0xd0000, 0x04000, val & 0x03);
if ((dev->pci_conf[0][0x62] ^ val) & 0x0c)
apollo_map(0xd4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->pci_conf[0][0x62] ^ val) & 0x30)
apollo_map(0xd8000, 0x04000, (val & 0x30) >> 4);
if ((dev->pci_conf[0][0x62] ^ val) & 0xc0)
apollo_map(0xdc000, 0x04000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x62] = val;
break;
case 0x63: /* Shadow RAM Control 3 */
if ((dev->pci_conf[0][0x63] ^ val) & 0x30) {
apollo_map(0xf0000, 0x10000, (val & 0x30) >> 4);
shadowbios = (((val & 0x30) >> 4) & 0x02);
}
if ((dev->pci_conf[0][0x63] ^ val) & 0xc0)
apollo_map(0xe0000, 0x10000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x63] = val;
if (dev->id == 0x0691) switch (val & 0x03) {
case 0x00:
default:
apollo_smram_map(1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */
apollo_smram_map(0, 0x000a0000, 0x00020000, 0); /* Non-SMM: Code PCI, Data PCI */
break;
case 0x01:
apollo_smram_map(1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */
apollo_smram_map(0, 0x000a0000, 0x00020000, 1); /* Non-SMM: Code DRAM, Data DRAM */
break;
case 0x02:
apollo_smram_map(1, 0x000a0000, 0x00020000, 3); /* SMM: Code Invalid, Data Invalid */
apollo_smram_map(0, 0x000a0000, 0x00020000, 2); /* Non-SMM: Code DRAM, Data PCI */
break;
case 0x03:
apollo_smram_map(1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */
apollo_smram_map(0, 0x000a0000, 0x00020000, 3); /* Non-SMM: Code Invalid, Data Invalid */
break;
} else switch (val & 0x03) {
case 0x00:
default:
/* Disable SMI Address Redirection (default) */
apollo_smram_map(1, 0x000a0000, 0x00020000, 0);
if (dev->id == 0x0597)
apollo_smram_map(1, 0x00030000, 0x00020000, 1);
apollo_smram_map(0, 0x000a0000, 0x00020000, 0);
break;
case 0x01:
/* Allow access to DRAM Axxxx-Bxxxx for both normal and SMI cycles */
apollo_smram_map(1, 0x000a0000, 0x00020000, 1);
if (dev->id == 0x0597)
apollo_smram_map(1, 0x00030000, 0x00020000, 1);
apollo_smram_map(0, 0x000a0000, 0x00020000, 1);
break;
case 0x02:
/* Reserved */
apollo_smram_map(1, 0x000a0000, 0x00020000, 3);
if (dev->id == 0x0597) {
/* TODO: SMI 3xxxx-4xxxx redirect to Axxxx-Bxxxx
(this needs a 3xxxx-4xxxx mapping set to EXTERNAL). */
apollo_smram_map(1, 0x00030000, 0x00020000, 3);
}
apollo_smram_map(0, 0x000a0000, 0x00020000, 3);
break;
case 0x03:
/* Allow SMI Axxxx-Bxxxx DRAM access */
apollo_smram_map(1, 0x000a0000, 0x00020000, 1);
if (dev->id == 0x0597)
apollo_smram_map(1, 0x00030000, 0x00020000, 1);
apollo_smram_map(0, 0x000a0000, 0x00020000, 0);
break;
}
break;
case 0x68:
if (dev->id == 0x0597)
dev->pci_conf[0][0x68] = (dev->pci_conf[0][0x6b] & ~0xfe) | (val & 0xfe);
else if (dev->id == 0x0598)
dev->pci_conf[0][0x68] = val;
else
dev->pci_conf[0][0x68] = (dev->pci_conf[0][0x6b] & ~0xfd) | (val & 0xfd);
break;
case 0x6b:
if (dev->id == 0x0691)
dev->pci_conf[0][0x6b] = (dev->pci_conf[0][0x6b] & ~0xcf) | (val & 0xcf);
else
dev->pci_conf[0][0x6b] = (dev->pci_conf[0][0x6b] & ~0xc1) | (val & 0xc1);
break;
case 0x6c:
if (dev->id == 0x0597)
dev->pci_conf[0][0x6c] = (dev->pci_conf[0][0x6c] & ~0x1f) | (val & 0x1f);
else if (dev->id == 0x0598)
dev->pci_conf[0][0x6c] = (dev->pci_conf[0][0x6c] & ~0x7f) | (val & 0x7f);
else
dev->pci_conf[0][0x6c] = val;
break;
case 0x6d:
if (dev->id == 0x0597)
dev->pci_conf[0][0x6d] = (dev->pci_conf[0][0x6d] & ~0x0f) | (val & 0x0f);
else if (dev->id == 0x0598)
dev->pci_conf[0][0x6d] = (dev->pci_conf[0][0x6d] & ~0x7f) | (val & 0x7f);
else
dev->pci_conf[0][0x6d] = val;
break;
case 0x6e:
dev->pci_conf[0][0x6e] = (dev->pci_conf[0][0x6e] & ~0xb7) | (val & 0xb7);
break;
case 0x70:
if (dev->id == 0x0597)
dev->pci_conf[0][0x70] = (dev->pci_conf[0][0x70] & ~0xf1) | (val & 0xf1);
else
dev->pci_conf[0][0x70] = val;
break;
case 0x74:
dev->pci_conf[0][0x74] = (dev->pci_conf[0][0x74] & ~0xc0) | (val & 0xc0);
break;
case 0x75:
dev->pci_conf[0][0x75] = (dev->pci_conf[0][0x75] & ~0xcf) | (val & 0xcf);
break;
case 0x76:
dev->pci_conf[0][0x76] = (dev->pci_conf[0][0x76] & ~0xf0) | (val & 0xf0);
break;
case 0x77:
dev->pci_conf[0][0x77] = (dev->pci_conf[0][0x77] & ~0xc0) | (val & 0xc0);
break;
case 0x7e:
dev->pci_conf[0][0x7e] = (dev->pci_conf[0][0x7e] & ~0x3f) | (val & 0x3f);
break;
case 0x80:
dev->pci_conf[0][0x80] = (dev->pci_conf[0][0x80] & ~0x8f) | (val & 0x8f);
break;
case 0x84:
/* The datasheet first mentions 7-0 but then says 3-0 are reserved -
- minimum of 16 MB for the graphics aperture? */
dev->pci_conf[0][0x84] = (dev->pci_conf[0][0x84] & ~0xf0) | (val & 0xf0);
break;
case 0x88:
dev->pci_conf[0][0x88] = (dev->pci_conf[0][0x88] & ~0x07) | (val & 0x07);
break;
case 0x89:
dev->pci_conf[0][0x89] = (dev->pci_conf[0][0x89] & ~0xf0) | (val & 0xf0);
break;
case 0xa8:
dev->pci_conf[0][0xa8] = (dev->pci_conf[0][0xa8] & ~0x03) | (val & 0x03);
break;
case 0xa9:
dev->pci_conf[0][0xa9] = (dev->pci_conf[0][0xa9] & ~0x03) | (val & 0x03);
break;
case 0xac:
dev->pci_conf[0][0xac] = (dev->pci_conf[0][0xac] & ~0x0f) | (val & 0x0f);
break;
case 0xfc:
if (dev->id > 0x0597)
dev->pci_conf[0][0xfc] = (dev->pci_conf[0][0xfc] & ~0x01) | (val & 0x01);
break;
default:
dev->pci_conf[0][addr] = val;
break;
}
}
static void
via_apollo_pci_bridge_write(int func, int addr, uint8_t val, void *priv)
{
via_apollo_t *dev = (via_apollo_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 == 0x3f) || (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);
break;
case 0x20: /* Memory Base */
dev->pci_conf[1][0x20] = val & 0xf0;
break;
case 0x22: /* Memory Limit */
dev->pci_conf[1][0x22] = val & 0xf0;
break;
case 0x24: /* Prefetchable Memory Base */
dev->pci_conf[1][0x24] = val & 0xf0;
break;
case 0x26: /* Prefetchable Memory Limit */
dev->pci_conf[1][0x26] = val & 0xf0;
break;
case 0x3e:
dev->pci_conf[0][0x3e] = (dev->pci_conf[0][0x3e] & ~0x06) | (val & 0x06);
break;
case 0x41:
dev->pci_conf[0][0x41] = (dev->pci_conf[0][0x41] & ~0xfe) | (val & 0xfe);
break;
case 0x42:
if (dev->id == 0x0597)
dev->pci_conf[0][0x42] = (dev->pci_conf[0][0x42] & ~0xec) | (val & 0xec);
else if (dev->id == 0x0598)
dev->pci_conf[0][0x42] = (dev->pci_conf[0][0x42] & ~0xfc) | (val & 0xfc);
else
dev->pci_conf[0][0x42] = (dev->pci_conf[0][0x42] & ~0xf4) | (val & 0xf4);
break;
default:
dev->pci_conf[1][addr] = val;
break;
}
}
static uint8_t
via_apollo_read(int func, int addr, void *priv)
{
via_apollo_t *dev = (via_apollo_t *) priv;
uint8_t ret = 0xff;
switch(func) {
case 0:
ret = dev->pci_conf[0][addr];
break;
case 1:
ret = dev->pci_conf[1][addr];
break;
}
return ret;
}
static void
via_apollo_write(int func, int addr, uint8_t val, void *priv)
{
switch(func) {
case 0:
via_apollo_host_bridge_write(func, addr, val, priv);
break;
case 1:
via_apollo_pci_bridge_write(func, addr, val, priv);
break;
}
}
static void
via_apollo_reset(void *priv)
{
via_apollo_write(0, 0x61, 0x00, priv);
via_apollo_write(0, 0x62, 0x00, priv);
via_apollo_write(0, 0x63, 0x00, priv);
}
static void *
via_apollo_init(const device_t *info)
{
via_apollo_t *dev = (via_apollo_t *) malloc(sizeof(via_apollo_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, via_apollo_read, via_apollo_write, dev);
dev->id = info->local;
via_apollo_setup(dev);
via_apollo_reset(dev);
return dev;
}
static void
via_apollo_close(void *priv)
{
via_apollo_t *dev = (via_apollo_t *) priv;
free(dev);
}
const device_t via_vp3_device =
{
"VIA Apollo VP3",
DEVICE_PCI,
0x0597, /*VT82C597*/
via_apollo_init,
via_apollo_close,
via_apollo_reset,
NULL,
NULL,
NULL,
NULL
};
const device_t via_mvp3_device =
{
"VIA Apollo MVP3",
DEVICE_PCI,
0x0598, /*VT82C598MVP*/
via_apollo_init,
via_apollo_close,
via_apollo_reset,
NULL,
NULL,
NULL,
NULL
};
const device_t via_apro_device = {
"VIA Apollo Pro",
DEVICE_PCI,
0x0691, /*VT82C691*/
via_apollo_init,
via_apollo_close,
via_apollo_reset,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -1,345 +0,0 @@
/*
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.>
VIA Apollo Pro North Bridge emulation
VT82C691 used in the PC Partner APAS3 board
based on the model of VIA MVP3 by mooch & Sarah
Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
Copyright(C) 2020 Tiseno100
Copyright(C) 2020 Melissa Goad
Copyright(C) 2020 Miran Grca
Note: Due to 99.9% similarities with the VP3, MVP3 but also other later Apollo chipsets. We probably should create a common Apollo tree
just like the Intel 4x0 series.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/mem.h>
#include <86box/io.h>
#include <86box/rom.h>
#include <86box/pci.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/chipset.h>
typedef struct via_apro_t
{
uint8_t pci_conf[2][256];
} via_apro_t;
static void
apro_map(uint32_t addr, uint32_t size, int state)
{
switch (state & 3) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 3:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
flushmmucache_nopc();
}
static void
via_apro_pci_regs(via_apro_t *dev)
{
memset(dev, 0, sizeof(via_apro_t));
// Host Bridge registers
dev->pci_conf[0][0x00] = 0x06; // VIA
dev->pci_conf[0][0x01] = 0x11;
dev->pci_conf[0][0x02] = 0x91; // VT82C691
dev->pci_conf[0][0x03] = 0x06;
dev->pci_conf[0][0x04] = 6; // Command
dev->pci_conf[0][0x05] = 0;
// These(06h-0fh) probably aren't needed but as they're referenced by the MVP3 chipset code i added them too
dev->pci_conf[0][0x06] = 0; // Status
dev->pci_conf[0][0x07] = 0;
dev->pci_conf[0][0x09] = 0; // Program Interface
dev->pci_conf[0][0x0a] = 0; // Sub Class Code
dev->pci_conf[0][0x0b] = 0; // 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][0x10] = 0x08; // Graphics Aperature Base
dev->pci_conf[0][0x34] = 0xa0; // Capability Pointer
dev->pci_conf[0][0x56] = 1; // Bank 6 Ending
dev->pci_conf[0][0x57] = 1; // Bank 7 Ending
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] = 0xec; // DRAM Timing for Banks 0,1
dev->pci_conf[0][0x65] = 0xec; // DRAM Timing for Banks 2,3
dev->pci_conf[0][0x66] = 0xec; // DRAM Timing for Banks 4,5
dev->pci_conf[0][0x67] = 0x01; // DRAM Timing for Banks 6,7
dev->pci_conf[0][0x6b] = 1; // DRAM Abritration control
dev->pci_conf[0][0xa4] = 0x03; // AGP Status
dev->pci_conf[0][0xa5] = 0x02;
dev->pci_conf[0][0xa6] = 0;
dev->pci_conf[0][0xa7] = 0x07;
// PCI-to-PCI
dev->pci_conf[1][0x00] = 0x06; // VIA
dev->pci_conf[1][0x01] = 0x11;
dev->pci_conf[1][0x02] = 0x91; // VT82C691
dev->pci_conf[1][0x03] = 0x06;
dev->pci_conf[1][0x04] = 7; // Command
dev->pci_conf[1][0x05] = 0;
dev->pci_conf[1][0x06] = 0x20; // Status
dev->pci_conf[1][0x07] = 0x02;
dev->pci_conf[1][0x09] = 0; // Program Interface
dev->pci_conf[1][0x0A] = 4; // Sub Class Code
dev->pci_conf[1][0x0B] = 6; // Base Class Code
dev->pci_conf[1][0x0C] = 0; // reserved
dev->pci_conf[1][0x0D] = 0; // Latency Timer
dev->pci_conf[1][0x0E] = 1; // Header Type
dev->pci_conf[1][0x0F] = 0; // Built-in Self test
dev->pci_conf[1][0x1c] = 0xf0; // I/O Base
dev->pci_conf[1][0x20] = 0xf0; // Memory Base
dev->pci_conf[1][0x21] = 0xff;
dev->pci_conf[1][0x24] = 0xf0;
dev->pci_conf[1][0x25] = 0xff;
}
static void
host_bridge_write(int func, int addr, uint8_t val, void *priv)
{
via_apro_t *dev = (via_apro_t *) priv;
// Read-Only registers. Exact same as MVP3
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
dev->pci_conf[0][0x04] = (dev->pci_conf[0][0x04] & ~0x40) | (val & 0x40);
case 0x07: // Status
dev->pci_conf[0][0x07] &= ~(val & 0xb0);
break;
case 0x12: //Graphics Aperature Base
dev->pci_conf[0][0x12] = (val & 0xf0);
break;
case 0x13:
dev->pci_conf[0][0x13] = val;
break;
case 0x61: // Shadow RAM control 1
if ((dev->pci_conf[0][0x61] ^ val) & 0x03)
apro_map(0xc0000, 0x04000, val & 0x03);
if ((dev->pci_conf[0][0x61] ^ val) & 0x0c)
apro_map(0xc4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->pci_conf[0][0x61] ^ val) & 0x30)
apro_map(0xc8000, 0x04000, (val & 0x30) >> 4);
if ((dev->pci_conf[0][0x61] ^ val) & 0xc0)
apro_map(0xcc000, 0x04000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x61] = val;
return;
case 0x62: // Shadow RAM Control 2
if ((dev->pci_conf[0][0x62] ^ val) & 0x03)
apro_map(0xd0000, 0x04000, val & 0x03);
if ((dev->pci_conf[0][0x62] ^ val) & 0x0c)
apro_map(0xd4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->pci_conf[0][0x62] ^ val) & 0x30)
apro_map(0xd8000, 0x04000, (val & 0x30) >> 4);
if ((dev->pci_conf[0][0x62] ^ val) & 0xc0)
apro_map(0xdc000, 0x04000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x62] = val;
return;
case 0x63: // Shadow RAM Control 3
if ((dev->pci_conf[0][0x63] ^ val) & 0x30) {
apro_map(0xf0000, 0x10000, (val & 0x30) >> 4);
shadowbios = (((val & 0x30) >> 4) & 0x02);
}
if ((dev->pci_conf[0][0x63] ^ val) & 0xc0)
apro_map(0xe0000, 0x10000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x63] = val;
return;
//In case we throw somewhere
default:
dev->pci_conf[0][addr] = val;
break;
}
}
static void
pci_to_pci_bridge_write(int func, int addr, uint8_t val, void *priv)
{
via_apro_t *dev = (via_apro_t *) priv;
if (func != 1)
return;
//As with MVP3. Same deal
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);
break;
case 0x20: // Memory Base
dev->pci_conf[1][0x20] = val & 0xf0;
break;
case 0x22: // Memory Limit
dev->pci_conf[1][0x22] = val & 0xf0;
break;
case 0x24: // Prefetchable Memory base
dev->pci_conf[1][0x24] = val & 0xf0;
break;
case 0x26: // Prefetchable Memory limit
dev->pci_conf[1][0x26] = val & 0xf0;
break;
default:
dev->pci_conf[1][addr] = val;
break;
}
}
static uint8_t
via_apro_read(int func, int addr, void *priv)
{
via_apro_t *dev = (via_apro_t *) priv;
uint8_t ret = 0xff;
switch(func) {
case 0:
ret = dev->pci_conf[0][addr];
break;
case 1:
ret = dev->pci_conf[1][addr];
break;
}
return ret;
}
static void
via_apro_write(int func, int addr, uint8_t val, void *priv)
{
switch(func) {
case 0:
host_bridge_write(func, addr, val, priv);
break;
case 1:
pci_to_pci_bridge_write(func, addr, val, priv);
break;
}
}
static void
via_apro_reset(void *priv)
{
via_apro_write(0, 0x63, via_apro_read(0, 0x63, priv) & 0xcf, priv);
}
static void *
via_apro_init(const device_t *info)
{
via_apro_t *dev = (via_apro_t *) malloc(sizeof(via_apro_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, via_apro_read, via_apro_write, dev);
via_apro_pci_regs(dev);
return dev;
}
static void
via_apro_close(void *priv)
{
via_apro_t *dev = (via_apro_t *) priv;
free(dev);
}
const device_t via_apro_device = {
"VIA Apollo Pro",
DEVICE_PCI,
0,
via_apro_init,
via_apro_close,
via_apro_reset,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -1,324 +0,0 @@
/*
* 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.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Melissa Goad, <mszoopers@protonmail.com>
*
* Copyright 2020 Miran Grca, Melissa Goad.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/mem.h>
#include <86box/io.h>
#include <86box/rom.h>
#include <86box/pci.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/chipset.h>
typedef struct via_mvp3_t
{
uint8_t pci_conf[2][256];
} via_mvp3_t;
static void
mvp3_map(uint32_t addr, uint32_t size, int state)
{
switch (state & 3) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 3:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
flushmmucache_nopc();
}
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);
break;
case 0x12: /* Graphics Aperture Base */
dev->pci_conf[0][0x12] = (val & 0xf0);
break;
case 0x13: /* Graphics Aperture Base */
dev->pci_conf[0][0x13] = val;
break;
case 0x61: /* Shadow RAM Control 1 */
if ((dev->pci_conf[0][0x61] ^ val) & 0x03)
mvp3_map(0xc0000, 0x04000, val & 0x03);
if ((dev->pci_conf[0][0x61] ^ val) & 0x0c)
mvp3_map(0xc4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->pci_conf[0][0x61] ^ val) & 0x30)
mvp3_map(0xc8000, 0x04000, (val & 0x30) >> 4);
if ((dev->pci_conf[0][0x61] ^ val) & 0xc0)
mvp3_map(0xcc000, 0x04000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x61] = val;
return;
case 0x62: /* Shadow RAM Control 2 */
if ((dev->pci_conf[0][0x62] ^ val) & 0x03)
mvp3_map(0xd0000, 0x04000, val & 0x03);
if ((dev->pci_conf[0][0x62] ^ val) & 0x0c)
mvp3_map(0xd4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->pci_conf[0][0x62] ^ val) & 0x30)
mvp3_map(0xd8000, 0x04000, (val & 0x30) >> 4);
if ((dev->pci_conf[0][0x62] ^ val) & 0xc0)
mvp3_map(0xdc000, 0x04000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x62] = val;
return;
case 0x63: /* Shadow RAM Control 3 */
if ((dev->pci_conf[0][0x63] ^ val) & 0x30) {
mvp3_map(0xf0000, 0x10000, (val & 0x30) >> 4);
shadowbios = (((val & 0x30) >> 4) & 0x02);
}
if ((dev->pci_conf[0][0x63] ^ val) & 0xc0)
mvp3_map(0xe0000, 0x10000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x63] = val;
return;
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);
break;
case 0x20: /* Memory Base */
dev->pci_conf[1][0x20] = val & 0xf0;
break;
case 0x22: /* Memory Limit */
dev->pci_conf[1][0x22] = val & 0xf0;
break;
case 0x24: /* Prefetchable Memory Base */
dev->pci_conf[1][0x24] = val & 0xf0;
break;
case 0x26: /* Prefetchable Memory Limit */
dev->pci_conf[1][0x26] = val & 0xf0;
break;
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;
uint8_t ret = 0xff;
switch(func) {
case 0:
ret = dev->pci_conf[0][addr];
break;
case 1:
ret = dev->pci_conf[1][addr];
break;
}
return ret;
}
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_write(0, 0x63, via_mvp3_read(0, 0x63, priv) & 0xcf, priv);
}
static void *
via_mvp3_init(const device_t *info)
{
via_mvp3_t *dev = (via_mvp3_t *) malloc(sizeof(via_mvp3_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, 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
};