ACPI: Rework suspend types and remove bogus PMCNTRL mirrors (those are SMI traps instead)

This commit is contained in:
RichardG867
2021-10-18 15:05:38 -03:00
parent 6bf299cd41
commit 878c92bf7f
4 changed files with 86 additions and 40 deletions

View File

@@ -37,6 +37,7 @@
#include <86box/acpi.h>
#include <86box/machine.h>
#include <86box/i2c.h>
#include <86box/ui.h>
int acpi_rtc_status = 0;
@@ -643,38 +644,46 @@ acpi_reg_write_common_regs(int size, uint16_t addr, uint8_t val, void *p)
case 0x04: case 0x05:
/* PMCNTRL - Power Management Control Register (IO) */
if ((addr == 0x05) && (val & 0x20)) {
sus_typ = (val >> 2) & 7;
switch (sus_typ) {
case 0:
case 6: /* Reserved according to the datasheet but used by eg. the ASUS P2B-LS. */
/* Soft power off. */
plat_power_off();
break;
case 1:
sus_typ = dev->suspend_types[(val >> 2) & 7];
if (sus_typ & SUS_POWER_OFF) {
/* Soft power off. */
plat_power_off();
return;
}
if (sus_typ & SUS_SUSPEND) {
if (sus_typ & SUS_NVR) {
/* Suspend to RAM. */
nvr_reg_write(0x000f, 0xff, dev->nvr);
}
/* Do a hard reset. */
if (sus_typ & SUS_RESET_PCI)
device_reset_all_pci();
if (sus_typ & SUS_RESET_CPU)
cpu_alt_reset = 0;
if (sus_typ & SUS_RESET_PCI) {
pci_reset();
keyboard_at_reset();
mem_a20_alt = 0;
mem_a20_recalc();
}
if (sus_typ & (SUS_RESET_CPU | SUS_RESET_CACHE))
flushmmucache();
if (sus_typ & SUS_RESET_CPU)
resetx86();
break;
default:
dev->regs.pmcntrl = ((dev->regs.pmcntrl & ~(0xff << shift16)) | (val << shift16)) & 0x3f07 /* 0x3c07 */;
break;
/* Resume immediately as a power button is not implemented yet. */
ui_msgbox_ex(MBX_INFO, L"Sleep mode", L"Press OK to resume the emulated machine.", NULL, NULL, NULL);
dev->regs.pmsts |= 0x8000;
}
} else
dev->regs.pmcntrl = ((dev->regs.pmcntrl & ~(0xff << shift16)) | (val << shift16)) & 0x3f07 /* 0x3c07 */;
}
dev->regs.pmcntrl = ((dev->regs.pmcntrl & ~(0xff << shift16)) | (val << shift16)) & 0x3f07 /* 0x3c07 */;
break;
}
}
@@ -1195,11 +1204,7 @@ acpi_aux_reg_read_common(int size, uint16_t addr, void *p)
acpi_t *dev = (acpi_t *) p;
uint8_t ret = 0xff;
if (dev->vendor == VEN_VIA_596B)
ret = acpi_reg_read_via_596b(size, addr - (0xf0 - 0x04), p);
else if (dev->vendor == VEN_INTEL)
ret = acpi_reg_read_intel(size, addr - (0x40 - 0x04), p);
else if (dev->vendor == VEN_SMC)
if (dev->vendor == VEN_SMC)
ret = acpi_aux_reg_read_smc(size, addr, p);
return ret;
@@ -1211,11 +1216,7 @@ acpi_aux_reg_write_common(int size, uint16_t addr, uint8_t val, void *p)
{
acpi_t *dev = (acpi_t *) p;
if (dev->vendor == VEN_VIA_596B)
acpi_reg_write_via_596b(size, addr - (0xf0 - 0x04), val, p);
else if (dev->vendor == VEN_INTEL)
acpi_reg_write_intel(size, addr - (0x40 - 0x04), val, p);
else if (dev->vendor == VEN_SMC)
if (dev->vendor == VEN_SMC)
acpi_aux_reg_write_smc(size, addr, val, p);
}
@@ -1273,7 +1274,7 @@ acpi_aux_reg_readl(uint16_t addr, void *p)
ret |= (acpi_aux_reg_read_common(4, addr + 2, p) << 16);
ret |= (acpi_aux_reg_read_common(4, addr + 3, p) << 24);
acpi_log("ACPI: Read L %08X from %04X\n", ret, addr);
acpi_log("ACPI: Read Aux L %08X from %04X\n", ret, addr);
return ret;
}
@@ -1287,7 +1288,7 @@ acpi_aux_reg_readw(uint16_t addr, void *p)
ret = acpi_aux_reg_read_common(2, addr, p);
ret |= (acpi_aux_reg_read_common(2, addr + 1, p) << 8);
acpi_log("ACPI: Read W %08X from %04X\n", ret, addr);
acpi_log("ACPI: Read Aux W %04X from %04X\n", ret, addr);
return ret;
}
@@ -1300,6 +1301,8 @@ acpi_aux_reg_read(uint16_t addr, void *p)
ret = acpi_aux_reg_read_common(1, addr, p);
acpi_log("ACPI: Read Aux B %02X from %04X\n", ret, addr);
return ret;
}
@@ -1338,6 +1341,8 @@ acpi_reg_write(uint16_t addr, uint8_t val, void *p)
static void
acpi_aux_reg_writel(uint16_t addr, uint32_t val, void *p)
{
acpi_log("ACPI: Write Aux L %08X to %04X\n", val, addr);
acpi_aux_reg_write_common(4, addr, val & 0xff, p);
acpi_aux_reg_write_common(4, addr + 1, (val >> 8) & 0xff, p);
acpi_aux_reg_write_common(4, addr + 2, (val >> 16) & 0xff, p);
@@ -1348,6 +1353,8 @@ acpi_aux_reg_writel(uint16_t addr, uint32_t val, void *p)
static void
acpi_aux_reg_writew(uint16_t addr, uint16_t val, void *p)
{
acpi_log("ACPI: Write Aux W %04X to %04X\n", val, addr);
acpi_aux_reg_write_common(2, addr, val & 0xff, p);
acpi_aux_reg_write_common(2, addr + 1, (val >> 8) & 0xff, p);
}
@@ -1356,6 +1363,8 @@ acpi_aux_reg_writew(uint16_t addr, uint16_t val, void *p)
static void
acpi_aux_reg_write(uint16_t addr, uint8_t val, void *p)
{
acpi_log("ACPI: Write Aux B %02X to %04X\n", val, addr);
acpi_aux_reg_write_common(1, addr, val, p);
}
@@ -1385,6 +1394,8 @@ acpi_update_io_mapping(acpi_t *dev, uint32_t base, int chipset_en)
break;
}
acpi_log("ACPI: Update I/O %04X to %04X (%sabled)\n", dev->io_base, base, chipset_en ? "en" : "dis");
if (dev->io_base != 0x0000) {
io_removehandler(dev->io_base, size,
acpi_reg_read, acpi_reg_readw, acpi_reg_readl,
@@ -1407,11 +1418,6 @@ acpi_update_aux_io_mapping(acpi_t *dev, uint32_t base, int chipset_en)
int size;
switch (dev->vendor) {
case VEN_INTEL:
case VEN_VIA_596B:
/* Undocumented mirror of PMCNTRL. */
size = 0x001;
break;
case VEN_SMC:
size = 0x008;
break;
@@ -1420,6 +1426,8 @@ acpi_update_aux_io_mapping(acpi_t *dev, uint32_t base, int chipset_en)
break;
}
acpi_log("ACPI: Update Aux I/O %04X to %04X (%sabled)\n", dev->aux_io_base, base, chipset_en ? "en" : "dis");
if (dev->aux_io_base != 0x0000) {
io_removehandler(dev->aux_io_base, size,
acpi_aux_reg_read, acpi_aux_reg_readw, acpi_aux_reg_readl,
@@ -1661,6 +1669,41 @@ acpi_init(const device_t *info)
i2c_smbus = i2c_gpio_get_bus(dev->i2c);
}
switch (dev->vendor) {
case VEN_ALI:
dev->suspend_types[0] = SUS_POWER_OFF;
dev->suspend_types[1] = SUS_POWER_OFF;
dev->suspend_types[2] = SUS_SUSPEND | SUS_NVR | SUS_RESET_CPU | SUS_RESET_PCI;
dev->suspend_types[3] = SUS_SUSPEND;
break;
case VEN_VIA:
dev->suspend_types[0] = SUS_POWER_OFF;
dev->suspend_types[2] = SUS_SUSPEND;
break;
case VEN_VIA_596B:
dev->suspend_types[1] = SUS_SUSPEND | SUS_NVR | SUS_RESET_CPU | SUS_RESET_PCI;
dev->suspend_types[2] = SUS_POWER_OFF;
dev->suspend_types[4] = SUS_SUSPEND;
dev->suspend_types[5] = SUS_SUSPEND | SUS_RESET_CPU;
dev->suspend_types[6] = SUS_SUSPEND | SUS_RESET_CPU | SUS_RESET_PCI;
break;
case VEN_INTEL:
dev->suspend_types[0] = SUS_POWER_OFF;
dev->suspend_types[1] = SUS_SUSPEND | SUS_NVR | SUS_RESET_CPU | SUS_RESET_PCI;
dev->suspend_types[2] = SUS_SUSPEND | SUS_RESET_CPU;
dev->suspend_types[3] = SUS_SUSPEND | SUS_RESET_CACHE;
dev->suspend_types[4] = SUS_SUSPEND;
break;
case VEN_SIS:
dev->suspend_types[0] = SUS_SUSPEND;
dev->suspend_types[4] = SUS_POWER_OFF;
break;
}
timer_add(&dev->timer, acpi_timer_count, dev, 0);
timer_set_delay_u64(&dev->timer, ACPICONST);

View File

@@ -813,13 +813,11 @@ piix_write(int func, int addr, uint8_t val, void *priv)
fregs[0x40] = (val & 0xc0) | 1;
dev->acpi_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0);
acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01));
acpi_update_aux_io_mapping(dev->acpi, dev->acpi_io_base + 0x40, (dev->regs[3][0x80] & 0x01));
break;
case 0x41:
fregs[0x41] = val;
dev->acpi_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0);
acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01));
acpi_update_aux_io_mapping(dev->acpi, dev->acpi_io_base + 0x40, (dev->regs[3][0x80] & 0x01));
break;
case 0x44: case 0x45: case 0x46: case 0x47:
case 0x48: case 0x49:
@@ -846,12 +844,10 @@ piix_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x4f: case 0x80: case 0xd2:
fregs[addr] = val & 0x0f;
if (addr == 0x80) {
if (addr == 0x80)
acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01));
acpi_update_aux_io_mapping(dev->acpi, dev->acpi_io_base + 0x40, (dev->regs[3][0x80] & 0x01));
} else if (addr == 0xd2) {
else if (addr == 0xd2)
smbus_update_io_mapping(dev);
}
break;
case 0x50:
fregs[addr] = val & 0x3f;

View File

@@ -1128,7 +1128,6 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
c -= 0x400;
acpi_set_timer32(dev->acpi, dev->power_regs[0x41] & 0x08);
acpi_update_io_mapping(dev->acpi, c, dev->power_regs[0x41] & 0x80);
acpi_update_aux_io_mapping(dev->acpi, c + 0xf0, dev->power_regs[0x41] & 0x80);
break;
case 0x42:

View File

@@ -39,6 +39,13 @@ extern "C" {
#define SCI_EN (1 << 0)
#define SUS_EN (1 << 13)
#define SUS_POWER_OFF (1 << 0)
#define SUS_SUSPEND (1 << 1)
#define SUS_NVR (1 << 2)
#define SUS_RESET_CPU (1 << 3)
#define SUS_RESET_CACHE (1 << 4)
#define SUS_RESET_PCI (1 << 5)
#define ACPI_ENABLE 0xf1
#define ACPI_DISABLE 0xf0
@@ -79,7 +86,8 @@ typedef struct
{
acpi_regs_t regs;
uint8_t gpireg2_default, pad[3],
gporeg_default[4];
gporeg_default[4],
suspend_types[8];
uint16_t io_base, aux_io_base;
int vendor,
slot, irq_mode,