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);
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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:
|
||||
|
@@ -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,
|
||||
|
Reference in New Issue
Block a user