VIA southbridge fixes, including dynamic SMBus clock

This commit is contained in:
RichardG867
2021-07-08 18:54:31 -03:00
parent 0297243a50
commit 2eba22295a
5 changed files with 142 additions and 44 deletions

View File

@@ -16,7 +16,7 @@
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
* Copyright 2020 Melissa Goad.
* Copyright 2020 RichardG.
* Copyright 2020-2021 RichardG.
*/
#include <stdarg.h>
@@ -58,6 +58,7 @@
#define VIA_PIPC_596B 0x05962300
#define VIA_PIPC_686A 0x06861400
#define VIA_PIPC_686B 0x06864000
#define VIA_PIPC_8231 0x82311000
typedef struct
@@ -118,6 +119,7 @@ pipc_reset_hard(void *priv)
memset(dev->power_regs, 0, 256);
memset(dev->ac97_regs, 0, 512);
/* PCI-ISA bridge registers */
dev->pci_isa_regs[0x00] = 0x06; dev->pci_isa_regs[0x01] = 0x11;
dev->pci_isa_regs[0x02] = dev->local >> 16;
dev->pci_isa_regs[0x03] = dev->local >> 24;
@@ -167,19 +169,23 @@ pipc_reset_hard(void *priv)
if (dev->local <= VIA_PIPC_586B)
dev->ide_regs[0x40] = 0x04;
dev->ide_regs[0x41] = (dev->local <= VIA_PIPC_686A) ? 0x06 : 0x02;
dev->ide_regs[0x41] = (dev->local == VIA_PIPC_686B) ? 0x06 : 0x02;
dev->ide_regs[0x42] = 0x09;
dev->ide_regs[0x43] = (dev->local >= VIA_PIPC_686A) ? 0x0a : 0x3a;
dev->ide_regs[0x44] = 0x68;
if (dev->local == VIA_PIPC_686B)
dev->ide_regs[0x45] = 0x20;
else if (dev->local >= VIA_PIPC_8231)
dev->ide_regs[0x45] = 0x03;
dev->ide_regs[0x46] = 0xc0;
dev->ide_regs[0x48] = 0xa8; dev->ide_regs[0x49] = 0xa8;
dev->ide_regs[0x4a] = 0xa8; dev->ide_regs[0x4b] = 0xa8;
dev->ide_regs[0x4c] = 0xff;
dev->ide_regs[0x4e] = 0xff;
dev->ide_regs[0x4f] = 0xff;
dev->ide_regs[0x50] = dev->ide_regs[0x51] = dev->ide_regs[0x52] = dev->ide_regs[0x53] = (dev->local >= VIA_PIPC_686A) ? 0x07 : 0x03;
if (dev->local != VIA_PIPC_686B)
dev->ide_regs[0x4e] = dev->ide_regs[0x4f] = 0xff;
dev->ide_regs[0x50] = dev->ide_regs[0x51] = dev->ide_regs[0x52] = dev->ide_regs[0x53] = ((dev->local == VIA_PIPC_686A) || (dev->local == VIA_PIPC_686B)) ? 0x07 : 0x03;
if (dev->local >= VIA_PIPC_596A)
dev->ide_regs[0x54] = 0x06;
dev->ide_regs[0x54] = ((dev->local == VIA_PIPC_686A) || (dev->local == VIA_PIPC_686B)) ? 0x04 : 0x06;
dev->ide_regs[0x61] = 0x02;
dev->ide_regs[0x69] = 0x02;
@@ -189,6 +195,7 @@ pipc_reset_hard(void *priv)
dev->ide_regs[0xc2] = 0x02;
}
/* USB registers */
for (i = 0; i <= (dev->local >= VIA_PIPC_686A); i++) {
dev->max_func++;
dev->usb_regs[i][0x00] = 0x06; dev->usb_regs[i][0x01] = 0x11;
@@ -213,6 +220,10 @@ pipc_reset_hard(void *priv)
case VIA_PIPC_686B:
dev->usb_regs[i][0x08] = 0x1a;
break;
case VIA_PIPC_8231:
dev->usb_regs[i][0x08] = 0x1e;
break;
}
dev->usb_regs[i][0x0a] = 0x03;
@@ -220,6 +231,8 @@ pipc_reset_hard(void *priv)
dev->usb_regs[i][0x0d] = 0x16;
dev->usb_regs[i][0x20] = 0x01;
dev->usb_regs[i][0x21] = 0x03;
if (dev->local == VIA_PIPC_686B)
dev->usb_regs[i][0x34] = 0x80;
dev->usb_regs[i][0x3d] = 0x04;
dev->usb_regs[i][0x60] = 0x10;
@@ -230,21 +243,29 @@ pipc_reset_hard(void *priv)
dev->usb_regs[i][0xc1] = 0x20;
}
/* power management registers */
if (dev->acpi) {
dev->max_func++;
dev->power_regs[0x00] = 0x06; dev->power_regs[0x01] = 0x11;
if (dev->local <= VIA_PIPC_586B)
dev->power_regs[0x02] = 0x40;
else if (dev->local <= VIA_PIPC_596B)
dev->power_regs[0x02] = 0x50;
else
dev->power_regs[0x02] = 0x57;
dev->power_regs[0x03] = 0x30;
if (dev->local >= VIA_PIPC_8231) {
/* The VT8231 preliminary datasheet lists *two* inaccurate
device IDs (3068 and 3057). Real dumps have 8235. */
dev->power_regs[0x02] = 0x35; dev->power_regs[0x03] = 0x82;
} else {
if (dev->local <= VIA_PIPC_586B)
dev->power_regs[0x02] = 0x40;
else if (dev->local <= VIA_PIPC_596B)
dev->power_regs[0x02] = 0x50;
else
dev->power_regs[0x02] = 0x57;
dev->power_regs[0x03] = 0x30;
}
dev->power_regs[0x04] = 0x00; dev->power_regs[0x05] = 0x00;
dev->power_regs[0x06] = (dev->local == VIA_PIPC_686B) ? 0x90 : 0x80; dev->power_regs[0x07] = 0x02;
switch (dev->local) {
case VIA_PIPC_586B:
case VIA_PIPC_686A:
case VIA_PIPC_8231:
dev->power_regs[0x08] = 0x10;
break;
@@ -260,11 +281,18 @@ pipc_reset_hard(void *priv)
dev->power_regs[0x08] = 0x40;
break;
}
if (dev->local == VIA_PIPC_686B)
dev->power_regs[0x34] = 0x68;
dev->power_regs[0x40] = 0x20;
dev->power_regs[0x42] = 0xd0;
dev->power_regs[0x48] = 0x01;
if (dev->local == VIA_PIPC_686B) {
dev->power_regs[0x68] = 0x01;
dev->power_regs[0x6a] = 0x02;
}
if (dev->local >= VIA_PIPC_686A)
dev->power_regs[0x70] = 0x01;
@@ -274,13 +302,26 @@ pipc_reset_hard(void *priv)
dev->power_regs[0x90] = 0x01;
}
/* AC97/MC97 registers */
if (dev->local >= VIA_PIPC_686A) {
for (i = 0; i <= 1; i++) {
dev->max_func++;
dev->ac97_regs[i][0x00] = 0x06; dev->ac97_regs[i][0x01] = 0x11;
dev->ac97_regs[i][0x02] = 0x58 + (0x10 * i); dev->ac97_regs[i][0x03] = 0x30;
dev->ac97_regs[i][0x06] = 0x10 * (1 - i); dev->ac97_regs[i][0x07] = 0x02;
dev->ac97_regs[i][0x08] = (dev->local == VIA_PIPC_686A) ? 0x12 : 0x50;
switch (dev->local) {
case VIA_PIPC_686A:
dev->ac97_regs[i][0x08] = (i == 0) ? 0x12 : 0x01;
break;
case VIA_PIPC_686B:
dev->ac97_regs[i][0x08] = (i == 0) ? 0x50 : 0x30;
break;
case VIA_PIPC_8231:
dev->ac97_regs[i][0x08] = (i == 0) ? 0x40 : 0x20;
break;
}
if (i == 0) {
dev->ac97_regs[i][0x0a] = 0x01;
@@ -291,7 +332,12 @@ pipc_reset_hard(void *priv)
}
dev->ac97_regs[i][0x10] = 0x01;
dev->ac97_regs[i][0x14] = 0x01;
dev->ac97_regs[i][(dev->local >= VIA_PIPC_8231) ? 0x1c : 0x14] = 0x01;
if ((i == 0) && (dev->local >= VIA_PIPC_8231)) {
dev->ac97_regs[i][0x18] = 0x31;
dev->ac97_regs[i][0x19] = 0x03;
}
dev->ac97_regs[i][0x3d] = 0x03;
@@ -413,7 +459,7 @@ pipc_read(int func, int addr, void *priv)
if (ret & 0x80) /* bit 7 set = use bit 6 */
c = ret & 0x40;
else if (ide_drives[c]) /* bit 7 clear = use SET FEATURES mode */
c = (ide_drives[c]->mdma_mode & 0xf00) == 0x300;
c = (ide_drives[c]->mdma_mode & 0x300) == 0x300;
else /* no drive here */
c = 0;
/* 586A/B datasheet claims bit 5 must be clear for UDMA, unlike later models where
@@ -433,6 +479,12 @@ pipc_read(int func, int addr, void *priv)
ret |= 0x10;
else
ret &= ~0x10;
} else if ((addr == 0xd2) && (dev->local == VIA_PIPC_686B)) {
/* SMBus clock select bit. */
if (dev->smbus->clock == 16384)
ret &= ~0x10;
else
ret |= 0x10;
}
}
else if ((func <= (pm_func + 2)) && !(dev->pci_isa_regs[0x85] & ((func == (pm_func + 1)) ? 0x04 : 0x08))) /* AC97 / MC97 */
@@ -512,9 +564,7 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
cpu_set_isa_pci_div(2);
break;
case 0xa:
cpu_set_isa_pci_div(4);
break;
/* case 0xa: same as default */
case 0xb:
cpu_set_isa_pci_div(6);
@@ -532,7 +582,7 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
cpu_set_isa_pci_div(12);
break;
/* Half PIT clock. */
/* Half oscillator clock. */
case 0xf:
cpu_set_isa_speed(7159091);
break;
@@ -735,6 +785,8 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
case 0x41:
if (dev->local <= VIA_PIPC_686A)
dev->ide_regs[0x41] = val;
else if (dev->local == VIA_PIPC_8231)
dev->ide_regs[0x41] = val & 0xf6;
else
dev->ide_regs[0x41] = val & 0xf2;
break;
@@ -755,7 +807,7 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
dev->ide_regs[0x44] = val & 0x7b;
else if (dev->local <= VIA_PIPC_596B)
dev->ide_regs[0x44] = val & 0x7f;
else if (dev->local <= VIA_PIPC_686A)
else if ((dev->local <= VIA_PIPC_686A) || (dev->local == VIA_PIPC_8231))
dev->ide_regs[0x44] = val & 0x69;
else
dev->ide_regs[0x44] = val & 0x7d;
@@ -764,7 +816,7 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
case 0x45:
if (dev->local <= VIA_PIPC_586B)
dev->ide_regs[0x45] = val & 0x40;
else if (dev->local <= VIA_PIPC_596B)
else if ((dev->local <= VIA_PIPC_596B) || (dev->local == VIA_PIPC_8231))
dev->ide_regs[0x45] = val & 0x4f;
else if (dev->local <= VIA_PIPC_686A)
dev->ide_regs[0x45] = val & 0x5f;
@@ -773,7 +825,7 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x46:
if (dev->local <= VIA_PIPC_686A)
if ((dev->local <= VIA_PIPC_686A) || (dev->local == VIA_PIPC_8231))
dev->ide_regs[0x46] = val & 0xf3;
else
dev->ide_regs[0x46] = val & 0xc0;
@@ -784,7 +836,7 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
dev->ide_regs[addr] = val & 0xc3;
else if (dev->local <= VIA_PIPC_596B)
dev->ide_regs[addr] = val & ((addr & 1) ? 0xc3 : 0xcb);
else if (dev->local <= VIA_PIPC_686A)
else if ((dev->local <= VIA_PIPC_686A) || (dev->local == VIA_PIPC_8231))
dev->ide_regs[addr] = val & ((addr & 1) ? 0xc7 : 0xcf);
else
dev->ide_regs[addr] = val & 0xd7;
@@ -803,13 +855,16 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
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))
((addr >= 0x46) && (addr < 0x84)) || ((addr >= 0x85) && (addr < 0xc0)) || (addr >= 0xc2))
return;
/* Check disable bits for both controllers */
if ((func == 2) ? (dev->pci_isa_regs[0x48] & 0x04) : (dev->pci_isa_regs[0x85] & 0x10))
return;
if ((dev->local <= VIA_PIPC_596B) && (addr == 0x84))
return;
switch (addr) {
case 0x04:
dev->usb_regs[func - 2][0x04] = val & 0x97;
@@ -872,6 +927,13 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
acpi_set_irq_line(dev->acpi, dev->power_regs[addr]);
break;
case 0x54:
if (dev->local <= VIA_PIPC_596B)
dev->power_regs[addr] = val; /* write-only on 686A+ */
else
smbus_piix4_setclock(dev->smbus, (val & 0x80) ? 65536 : 16384); /* final clock undocumented on 686A, assume RTC*2 like 686B */
break;
case 0x61: case 0x62: case 0x63:
dev->power_regs[(addr - 0x58)] = val;
break;
@@ -883,12 +945,17 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
vt82c686_hwm_write(addr, val, subdev);
break;
case 0x80: case 0x81: case 0x84: /* 596(A) has the SMBus I/O base here instead. Enable bit is assumed. */
case 0x80: case 0x81: case 0x84: /* 596A has the SMBus I/O base and enable bit here instead. */
dev->power_regs[addr] = val;
smbus_piix4_remap(dev->smbus, (dev->power_regs[0x81] << 8) | (dev->power_regs[0x80] & 0xf0), dev->power_regs[0x84] & 0x01);
break;
case 0x90: case 0x91: case 0xd2:
case 0xd2:
if (dev->local == VIA_PIPC_686B)
smbus_piix4_setclock(dev->smbus, (val & 0x04) ? 65536 : 16384);
/* fall-through */
case 0x90: case 0x91:
dev->power_regs[addr] = val;
smbus_piix4_remap(dev->smbus, (dev->power_regs[0x91] << 8) | (dev->power_regs[0x90] & 0xf0), dev->power_regs[0xd2] & 0x01);
break;
@@ -974,7 +1041,7 @@ pipc_init(const device_t *info)
dev->nvr = device_add(&via_nvr_device);
if (dev->local >= VIA_PIPC_686B)
if (dev->local == VIA_PIPC_686B)
dev->smbus = device_add(&via_smbus_device);
else if (dev->local >= VIA_PIPC_596A)
dev->smbus = device_add(&piix4_smbus_device);
@@ -1030,8 +1097,8 @@ const device_t via_vt82c586b_device =
"VIA VT82C586B",
DEVICE_PCI,
VIA_PIPC_586B,
pipc_init,
pipc_close,
pipc_init,
pipc_close,
pipc_reset,
{ NULL },
NULL,
@@ -1039,13 +1106,13 @@ const device_t via_vt82c586b_device =
NULL
};
const device_t via_vt82c596_device =
const device_t via_vt82c596a_device =
{
"VIA VT82C596(A)",
"VIA VT82C596A",
DEVICE_PCI,
VIA_PIPC_596A,
pipc_init,
pipc_close,
pipc_init,
pipc_close,
pipc_reset,
{ NULL },
NULL,
@@ -1059,8 +1126,8 @@ const device_t via_vt82c596b_device =
"VIA VT82C596B",
DEVICE_PCI,
VIA_PIPC_596B,
pipc_init,
pipc_close,
pipc_init,
pipc_close,
pipc_reset,
{ NULL },
NULL,
@@ -1074,8 +1141,8 @@ const device_t via_vt82c686a_device =
"VIA VT82C686A",
DEVICE_PCI,
VIA_PIPC_686A,
pipc_init,
pipc_close,
pipc_init,
pipc_close,
pipc_reset,
{ NULL },
NULL,
@@ -1089,8 +1156,23 @@ const device_t via_vt82c686b_device =
"VIA VT82C686B",
DEVICE_PCI,
VIA_PIPC_686B,
pipc_init,
pipc_close,
pipc_init,
pipc_close,
pipc_reset,
{ NULL },
NULL,
NULL,
NULL
};
const device_t via_vt8231_device =
{
"VIA VT8231",
DEVICE_PCI,
VIA_PIPC_8231,
pipc_init,
pipc_close,
pipc_reset,
{ NULL },
NULL,

View File

@@ -313,8 +313,8 @@ unknown_protocol:
if (dev->next_stat) { /* schedule dispatch of any pending status register update */
dev->stat = 0x01; /* raise HOST_BUSY while waiting */
timer_disable(&dev->response_timer);
/* delay = ((half clock for start + half clock for stop) + (bytes * (8 bits + ack))) * 60us period measured on real VIA 686B */
timer_set_delay_u64(&dev->response_timer, (1 + (timer_bytes * 9)) * 60 * TIMER_USEC);
/* delay = ((half clock for start + half clock for stop) + (bytes * (8 bits + ack))) * bit period in usecs */
timer_set_delay_u64(&dev->response_timer, (1 + (timer_bytes * 9)) * dev->bit_period * TIMER_USEC);
}
}
@@ -343,6 +343,16 @@ smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable)
}
void
smbus_piix4_setclock(smbus_piix4_t *dev, int clock)
{
dev->clock = clock;
/* Set the bit period in usecs. */
dev->bit_period = 1000000.0 / dev->clock;
}
static void *
smbus_piix4_init(const device_t *info)
{
@@ -356,6 +366,8 @@ smbus_piix4_init(const device_t *info)
timer_add(&dev->response_timer, smbus_piix4_response, dev, 0);
smbus_piix4_setclock(dev, 16384); /* default to 16.384 KHz */
return dev;
}

View File

@@ -144,10 +144,11 @@ extern const device_t via_apro133_device;
extern const device_t via_apro133a_device;
extern const device_t via_vt8601_device;
extern const device_t via_vt82c586b_device;
extern const device_t via_vt82c596_device;
extern const device_t via_vt82c596a_device;
extern const device_t via_vt82c596b_device;
extern const device_t via_vt82c686a_device;
extern const device_t via_vt82c686b_device;
extern const device_t via_vt8231_device;
/* VLSI */
extern const device_t vl82c480_device;

View File

@@ -30,6 +30,8 @@ enum {
typedef struct {
uint32_t local;
uint16_t io_base;
int clock;
double bit_period;
uint8_t stat, next_stat, ctl, cmd, addr,
data0, data1,
index, data[SMBUS_PIIX4_BLOCK_DATA_SIZE];
@@ -39,6 +41,7 @@ typedef struct {
extern void smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable);
extern void smbus_piix4_setclock(smbus_piix4_t *dev, int clock);
#ifdef EMU_DEVICE_H

View File

@@ -540,7 +540,7 @@ machine_at_ficka6130_init(const machine_t *model)
pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3);
pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4);
device_add(&via_apro_device);
device_add(&via_vt82c596_device);
device_add(&via_vt82c596a_device);
device_add(&w83877tf_device);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&sst_flash_29ee020_device);