ACPI: Rework suspend types and remove bogus PMCNTRL mirrors (those are SMI traps instead)
This commit is contained in:
107
src/acpi.c
107
src/acpi.c
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user