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/acpi.h>
|
||||||
#include <86box/machine.h>
|
#include <86box/machine.h>
|
||||||
#include <86box/i2c.h>
|
#include <86box/i2c.h>
|
||||||
|
#include <86box/ui.h>
|
||||||
|
|
||||||
|
|
||||||
int acpi_rtc_status = 0;
|
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:
|
case 0x04: case 0x05:
|
||||||
/* PMCNTRL - Power Management Control Register (IO) */
|
/* PMCNTRL - Power Management Control Register (IO) */
|
||||||
if ((addr == 0x05) && (val & 0x20)) {
|
if ((addr == 0x05) && (val & 0x20)) {
|
||||||
sus_typ = (val >> 2) & 7;
|
sus_typ = dev->suspend_types[(val >> 2) & 7];
|
||||||
switch (sus_typ) {
|
|
||||||
case 0:
|
if (sus_typ & SUS_POWER_OFF) {
|
||||||
case 6: /* Reserved according to the datasheet but used by eg. the ASUS P2B-LS. */
|
/* Soft power off. */
|
||||||
/* Soft power off. */
|
plat_power_off();
|
||||||
plat_power_off();
|
return;
|
||||||
break;
|
}
|
||||||
case 1:
|
|
||||||
|
if (sus_typ & SUS_SUSPEND) {
|
||||||
|
if (sus_typ & SUS_NVR) {
|
||||||
/* Suspend to RAM. */
|
/* Suspend to RAM. */
|
||||||
nvr_reg_write(0x000f, 0xff, dev->nvr);
|
nvr_reg_write(0x000f, 0xff, dev->nvr);
|
||||||
|
}
|
||||||
|
|
||||||
/* Do a hard reset. */
|
if (sus_typ & SUS_RESET_PCI)
|
||||||
device_reset_all_pci();
|
device_reset_all_pci();
|
||||||
|
|
||||||
|
if (sus_typ & SUS_RESET_CPU)
|
||||||
cpu_alt_reset = 0;
|
cpu_alt_reset = 0;
|
||||||
|
|
||||||
|
if (sus_typ & SUS_RESET_PCI) {
|
||||||
pci_reset();
|
pci_reset();
|
||||||
keyboard_at_reset();
|
keyboard_at_reset();
|
||||||
|
|
||||||
mem_a20_alt = 0;
|
mem_a20_alt = 0;
|
||||||
mem_a20_recalc();
|
mem_a20_recalc();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sus_typ & (SUS_RESET_CPU | SUS_RESET_CACHE))
|
||||||
flushmmucache();
|
flushmmucache();
|
||||||
|
|
||||||
|
if (sus_typ & SUS_RESET_CPU)
|
||||||
resetx86();
|
resetx86();
|
||||||
break;
|
|
||||||
default:
|
/* Resume immediately as a power button is not implemented yet. */
|
||||||
dev->regs.pmcntrl = ((dev->regs.pmcntrl & ~(0xff << shift16)) | (val << shift16)) & 0x3f07 /* 0x3c07 */;
|
ui_msgbox_ex(MBX_INFO, L"Sleep mode", L"Press OK to resume the emulated machine.", NULL, NULL, NULL);
|
||||||
break;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1195,11 +1204,7 @@ acpi_aux_reg_read_common(int size, uint16_t addr, void *p)
|
|||||||
acpi_t *dev = (acpi_t *) p;
|
acpi_t *dev = (acpi_t *) p;
|
||||||
uint8_t ret = 0xff;
|
uint8_t ret = 0xff;
|
||||||
|
|
||||||
if (dev->vendor == VEN_VIA_596B)
|
if (dev->vendor == VEN_SMC)
|
||||||
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)
|
|
||||||
ret = acpi_aux_reg_read_smc(size, addr, p);
|
ret = acpi_aux_reg_read_smc(size, addr, p);
|
||||||
|
|
||||||
return ret;
|
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;
|
acpi_t *dev = (acpi_t *) p;
|
||||||
|
|
||||||
if (dev->vendor == VEN_VIA_596B)
|
if (dev->vendor == VEN_SMC)
|
||||||
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)
|
|
||||||
acpi_aux_reg_write_smc(size, addr, val, p);
|
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 + 2, p) << 16);
|
||||||
ret |= (acpi_aux_reg_read_common(4, addr + 3, p) << 24);
|
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;
|
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, p);
|
||||||
ret |= (acpi_aux_reg_read_common(2, addr + 1, p) << 8);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1300,6 +1301,8 @@ acpi_aux_reg_read(uint16_t addr, void *p)
|
|||||||
|
|
||||||
ret = acpi_aux_reg_read_common(1, addr, p);
|
ret = acpi_aux_reg_read_common(1, addr, p);
|
||||||
|
|
||||||
|
acpi_log("ACPI: Read Aux B %02X from %04X\n", ret, addr);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1338,6 +1341,8 @@ acpi_reg_write(uint16_t addr, uint8_t val, void *p)
|
|||||||
static void
|
static void
|
||||||
acpi_aux_reg_writel(uint16_t addr, uint32_t val, void *p)
|
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, val & 0xff, p);
|
||||||
acpi_aux_reg_write_common(4, addr + 1, (val >> 8) & 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);
|
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
|
static void
|
||||||
acpi_aux_reg_writew(uint16_t addr, uint16_t val, void *p)
|
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, val & 0xff, p);
|
||||||
acpi_aux_reg_write_common(2, addr + 1, (val >> 8) & 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
|
static void
|
||||||
acpi_aux_reg_write(uint16_t addr, uint8_t val, void *p)
|
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);
|
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;
|
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) {
|
if (dev->io_base != 0x0000) {
|
||||||
io_removehandler(dev->io_base, size,
|
io_removehandler(dev->io_base, size,
|
||||||
acpi_reg_read, acpi_reg_readw, acpi_reg_readl,
|
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;
|
int size;
|
||||||
|
|
||||||
switch (dev->vendor) {
|
switch (dev->vendor) {
|
||||||
case VEN_INTEL:
|
|
||||||
case VEN_VIA_596B:
|
|
||||||
/* Undocumented mirror of PMCNTRL. */
|
|
||||||
size = 0x001;
|
|
||||||
break;
|
|
||||||
case VEN_SMC:
|
case VEN_SMC:
|
||||||
size = 0x008;
|
size = 0x008;
|
||||||
break;
|
break;
|
||||||
@@ -1420,6 +1426,8 @@ acpi_update_aux_io_mapping(acpi_t *dev, uint32_t base, int chipset_en)
|
|||||||
break;
|
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) {
|
if (dev->aux_io_base != 0x0000) {
|
||||||
io_removehandler(dev->aux_io_base, size,
|
io_removehandler(dev->aux_io_base, size,
|
||||||
acpi_aux_reg_read, acpi_aux_reg_readw, acpi_aux_reg_readl,
|
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);
|
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_add(&dev->timer, acpi_timer_count, dev, 0);
|
||||||
timer_set_delay_u64(&dev->timer, ACPICONST);
|
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;
|
fregs[0x40] = (val & 0xc0) | 1;
|
||||||
dev->acpi_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0);
|
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_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;
|
break;
|
||||||
case 0x41:
|
case 0x41:
|
||||||
fregs[0x41] = val;
|
fregs[0x41] = val;
|
||||||
dev->acpi_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0);
|
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_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;
|
break;
|
||||||
case 0x44: case 0x45: case 0x46: case 0x47:
|
case 0x44: case 0x45: case 0x46: case 0x47:
|
||||||
case 0x48: case 0x49:
|
case 0x48: case 0x49:
|
||||||
@@ -846,12 +844,10 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
|||||||
break;
|
break;
|
||||||
case 0x4f: case 0x80: case 0xd2:
|
case 0x4f: case 0x80: case 0xd2:
|
||||||
fregs[addr] = val & 0x0f;
|
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_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);
|
smbus_update_io_mapping(dev);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 0x50:
|
case 0x50:
|
||||||
fregs[addr] = val & 0x3f;
|
fregs[addr] = val & 0x3f;
|
||||||
|
@@ -1128,7 +1128,6 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
|
|||||||
c -= 0x400;
|
c -= 0x400;
|
||||||
acpi_set_timer32(dev->acpi, dev->power_regs[0x41] & 0x08);
|
acpi_set_timer32(dev->acpi, dev->power_regs[0x41] & 0x08);
|
||||||
acpi_update_io_mapping(dev->acpi, c, dev->power_regs[0x41] & 0x80);
|
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;
|
break;
|
||||||
|
|
||||||
case 0x42:
|
case 0x42:
|
||||||
|
@@ -39,6 +39,13 @@ extern "C" {
|
|||||||
#define SCI_EN (1 << 0)
|
#define SCI_EN (1 << 0)
|
||||||
#define SUS_EN (1 << 13)
|
#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_ENABLE 0xf1
|
||||||
#define ACPI_DISABLE 0xf0
|
#define ACPI_DISABLE 0xf0
|
||||||
|
|
||||||
@@ -79,7 +86,8 @@ typedef struct
|
|||||||
{
|
{
|
||||||
acpi_regs_t regs;
|
acpi_regs_t regs;
|
||||||
uint8_t gpireg2_default, pad[3],
|
uint8_t gpireg2_default, pad[3],
|
||||||
gporeg_default[4];
|
gporeg_default[4],
|
||||||
|
suspend_types[8];
|
||||||
uint16_t io_base, aux_io_base;
|
uint16_t io_base, aux_io_base;
|
||||||
int vendor,
|
int vendor,
|
||||||
slot, irq_mode,
|
slot, irq_mode,
|
||||||
|
Reference in New Issue
Block a user