From 3aaf9ac6fe241d5a81277f890dff11fad0f3e9cd Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 26 Apr 2020 00:49:46 +0200 Subject: [PATCH] More ACPI improvements, implementation of VIA ACPI (yet to be hooked to the southbridges), removed ISABugger stuff from acpi.h, apm.h, dma.h, and usb.h, and updated the descriptions in piix.c and piix.h. --- src/acpi.c | 412 ++++++++++++++++++++++++++++++++++++--- src/apm.c | 18 +- src/include/86box/acpi.h | 30 +-- src/include/86box/apm.h | 9 +- src/include/86box/ddma.h | 7 - src/include/86box/piix.h | 3 +- src/include/86box/usb.h | 7 - src/intel_piix.c | 23 ++- 8 files changed, 437 insertions(+), 72 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index 26855a743..d8555cb95 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -32,6 +32,7 @@ #include <86box/keyboard.h> #include <86box/nvr.h> #include <86box/pit.h> +#include <86box/apm.h> #include <86box/acpi.h> @@ -77,8 +78,28 @@ acpi_update_irq(void *priv) } +static void +acpi_raise_smi(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + + if (dev->vendor == VEN_VIA) { + if ((dev->regs.glbctl & 0x01) && (!dev->regs.smi_lock || !dev->regs.smi_active)) { + smi_line = 1; + dev->regs.smi_active = 1; + } + } else { + if (dev->regs.glbctl & 0x01) { + smi_line = 1; + /* Clear bit 16 of GLBCTL. */ + dev->regs.glbctl &= ~0x00010000; + } + } +} + + static uint32_t -acpi_reg_read_common(int size, uint16_t addr, void *p) +acpi_reg_read_intel(int size, uint16_t addr, void *p) { acpi_t *dev = (acpi_t *) p; uint32_t ret = 0x00000000; @@ -117,16 +138,6 @@ acpi_reg_read_common(int size, uint16_t addr, void *p) /* PCNTRL - Processor Control Register (IO) */ ret = (dev->regs.pcntrl >> shift32) & 0xff; break; - case 0x14: - /* PLVL2 - Processor Level 2 Register (IO) */ - if (size == 1) - ret = dev->regs.plvl2; - break; - case 0x15: - /* PLVL3 - Processor Level 3 Register (IO) */ - if (size == 1) - ret = dev->regs.plvl3; - break; case 0x18: case 0x19: /* GLBSTS - Global Status Register (IO) */ ret = (dev->regs.glbsts >> shift16) & 0xff; @@ -173,8 +184,118 @@ acpi_reg_read_common(int size, uint16_t addr, void *p) } +static uint32_t +acpi_reg_read_via(int size, uint16_t addr, void *p) +{ + acpi_t *dev = (acpi_t *) p; + uint32_t ret = 0x00000000; + int shift16, shift32; + + addr &= 0xff; + shift16 = (addr & 1) << 3; + shift32 = (addr & 3) << 3; + + switch (addr) { + case 0x00: case 0x01: + /* PMSTS - Power Management Status Register (IO) */ + ret = (dev->regs.pmsts >> shift16) & 0xff; + break; + case 0x02: case 0x03: + /* PMEN - Power Management Resume Enable Register (IO) */ + ret = (dev->regs.pmen >> shift16) & 0xff; + break; + case 0x04: case 0x05: + /* PMCNTRL - Power Management Control Register (IO) */ + ret = (dev->regs.pmcntrl >> shift16) & 0xff; + break; + case 0x08: case 0x09: case 0x0a: case 0x0b: + /* PMTMR - Power Management Timer Register (IO) */ + ret = (dev->regs.timer_val >> shift32) & 0xff; + break; + case 0x10: case 0x11: case 0x12: case 0x13: + /* PCNTRL - Processor Control Register (IO) */ + ret = (dev->regs.pcntrl >> shift32) & 0xff; + break; + case 0x20: case 0x21: + /* GPSTS - General Purpose Status Register (IO) */ + ret = (dev->regs.gpsts >> shift16) & 0xff; + break; + case 0x22: case 0x23: + /* General Purpose SCI Enable */ + ret = (dev->regs.gpscien >> shift16) & 0xff; + break; + case 0x24: case 0x25: + /* General Purpose SMI Enable */ + ret = (dev->regs.gpsmien >> shift16) & 0xff; + break; + case 0x26: case 0x27: + /* Power Supply Control */ + ret = (dev->regs.pscntrl >> shift16) & 0xff; + break; + case 0x28: case 0x29: + /* GLBSTS - Global Status Register (IO) */ + ret = (dev->regs.glbsts >> shift16) & 0xff; + break; + case 0x2a: case 0x2b: + /* GLBEN - Global Enable Register (IO) */ + ret = (dev->regs.glben >> shift16) & 0xff; + break; + case 0x2c: case 0x2d: + /* GLBCTL - Global Control Register (IO) */ + ret = (dev->regs.glbctl >> shift16) & 0xff; + ret &= ~0x0110; + ret |= (dev->regs.smi_lock ? 0x10 : 0x00); + ret |= (dev->regs.smi_active ? 0x01 : 0x00); + break; + case 0x2f: + /* SMI Command */ + if (size == 1) + ret = dev->regs.smicmd & 0xff; + break; + case 0x30: case 0x31: case 0x32: case 0x33: + /* Primary Activity Detect Status */ + ret = (dev->regs.padsts >> shift32) & 0xff; + break; + case 0x34: case 0x35: case 0x36: case 0x37: + /* Primary Activity Detect Enable */ + ret = (dev->regs.paden >> shift32) & 0xff; + break; + case 0x38: case 0x39: case 0x3a: case 0x3b: + /* GP Timer Reload Enable */ + ret = (dev->regs.gptren >> shift32) & 0xff; + break; + case 0x40: + /* GPIO Direction Control */ + if (size == 1) + ret = dev->regs.gpio_dir & 0xff; + break; + case 0x42: + /* GPIO port Output Value */ + if (size == 1) + ret = dev->regs.gpio_val & 0xff; + break; + case 0x44: + /* GPIO port Output Value */ + if (size == 1) + ret = dev->regs.extsmi_val & 0xff; + break; + case 0x46: case 0x47: + /* GPO Port Output Value */ + ret = (dev->regs.gpo_val >> shift16) & 0xff; + break; + case 0x48: case 0x49: + /* GPO Port Input Value */ + ret = (dev->regs.gpi_val >> shift16) & 0xff; + break; + } + + acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); + return ret; +} + + static void -acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *p) +acpi_reg_write_intel(int size, uint16_t addr, uint8_t val, void *p) { acpi_t *dev = (acpi_t *) p; int shift16, shift32; @@ -199,6 +320,12 @@ acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *p) case 0x04: case 0x05: /* PMCNTRL - Power Management Control Register (IO) */ dev->regs.pmcntrl = ((dev->regs.pmcntrl & ~(0xff << shift16)) | (val << shift16)) & 0x3c07; + /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ + if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { + dev->regs.glbsts |= 0x01; + if (dev->regs.glben & 0x02) + acpi_raise_smi(dev); + } if (dev->regs.pmcntrl & 0x2000) { sus_typ = (dev->regs.pmcntrl >> 10) & 7; switch (sus_typ) { @@ -240,16 +367,6 @@ acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *p) /* PCNTRL - Processor Control Register (IO) */ dev->regs.pcntrl = ((dev->regs.pcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x00023e1e; break; - case 0x14: - /* PLVL2 - Processor Level 2 Register (IO) */ - if (size == 1) - dev->regs.plvl2 = val; - break; - case 0x15: - /* PLVL3 - Processor Level 3 Register (IO) */ - if (size == 1) - dev->regs.plvl3 = val; - break; case 0x18: case 0x19: /* GLBSTS - Global Status Register (IO) */ dev->regs.glbsts &= ~((val << shift16) & 0x0df7); @@ -264,8 +381,13 @@ acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *p) break; case 0x28: case 0x29: case 0x2a: case 0x2b: /* GLBCTL - Global Control Register (IO) */ - // dev->regs.glbctl = ((dev->regs.glbctl & ~(0xff << shift32)) | (val << shift32)) & 0x0701ff07; - dev->regs.glbctl = ((dev->regs.glbctl & ~(0xff << shift32)) | (val << shift32)) & 0x0700ff07; + dev->regs.glbctl = ((dev->regs.glbctl & ~(0xff << shift32)) | (val << shift32)) & 0x0701ff07; + /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */ + if (dev->regs.glbctl & 0x00000002) { + dev->regs.pmsts |= 0x20; + if (dev->regs.pmen & 0x20) + acpi_update_irq(dev); + } break; case 0x2c: case 0x2d: case 0x2e: case 0x2f: /* DEVCTL - Device Control Register (IO) */ @@ -280,6 +402,180 @@ acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *p) } +static void +acpi_reg_write_via(int size, uint16_t addr, uint8_t val, void *p) +{ + acpi_t *dev = (acpi_t *) p; + int shift16, shift32; + int sus_typ; + + addr &= 0xff; + acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); + shift16 = (addr & 1) << 3; + shift32 = (addr & 3) << 3; + + switch (addr) { + case 0x00: case 0x01: + /* PMSTS - Power Management Status Register (IO) */ + dev->regs.pmsts &= ~((val << shift16) & 0x8d31); + acpi_update_irq(dev); + if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) + dev->regs.glbctl &= ~0x0002; + break; + case 0x02: case 0x03: + /* PMEN - Power Management Resume Enable Register (IO) */ + dev->regs.pmen = ((dev->regs.pmen & ~(0xff << shift16)) | (val << shift16)) & 0x0521; + acpi_update_irq(dev); + break; + case 0x04: case 0x05: + /* PMCNTRL - Power Management Control Register (IO) */ + dev->regs.pmcntrl = ((dev->regs.pmcntrl & ~(0xff << shift16)) | (val << shift16)) & 0x3c07; + /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ + if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { + dev->regs.glbsts |= 0x20; + if (dev->regs.glben & 0x20) + acpi_raise_smi(dev); + } + if (dev->regs.pmcntrl & 0x2000) { + sus_typ = (dev->regs.pmcntrl >> 10) & 7; + switch (sus_typ) { + case 0: + /* Soft power off. */ + exit(-1); + break; + case 1: + /* Suspend to RAM. */ + nvr_reg_write(0x000f, 0xff, dev->nvr); + + /* Do a hard reset. */ + device_reset_all_pci(); + + cpu_alt_reset = 0; + + pci_reset(); + keyboard_at_reset(); + + mem_a20_alt = 0; + mem_a20_recalc(); + + flushmmucache(); + + resetx86(); + break; + } + } + break; + case 0x10: case 0x11: case 0x12: case 0x13: + /* PCNTRL - Processor Control Register (IO) */ + dev->regs.pcntrl = ((dev->regs.pcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x0000001e; + break; + case 0x20: case 0x21: + /* GPSTS - General Purpose Status Register (IO) */ + dev->regs.gpsts &= ~((val << shift16) & 0x03ff); + break; + case 0x22: case 0x23: + /* General Purpose SCI Enable */ + dev->regs.gpscien = ((dev->regs.gpscien & ~(0xff << shift16)) | (val << shift16)) & 0x03ff; + break; + case 0x24: case 0x25: + /* General Purpose SMI Enable */ + dev->regs.gpsmien = ((dev->regs.gpsmien & ~(0xff << shift16)) | (val << shift16)) & 0x03ff; + break; + case 0x26: case 0x27: + /* Power Supply Control */ + dev->regs.pscntrl = ((dev->regs.pscntrl & ~(0xff << shift16)) | (val << shift16)) & 0x0701; + break; + case 0x28: case 0x29: + /* GLBSTS - Global Status Register (IO) */ + dev->regs.glbsts &= ~((val << shift16) & 0x007f); + break; + case 0x2a: case 0x2b: + /* GLBEN - Global Enable Register (IO) */ + dev->regs.glben = ((dev->regs.glben & ~(0xff << shift16)) | (val << shift16)) & 0x007f; + break; + case 0x2c: + /* GLBCTL - Global Control Register (IO) */ + dev->regs.glbctl = (dev->regs.glbctl & ~0xff) | (val & 0xff); + dev->regs.smi_lock = !!(dev->regs.glbctl & 0x0010); + /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */ + if (dev->regs.glbctl & 0x0002) { + dev->regs.pmsts |= 0x20; + if (dev->regs.pmen & 0x20) + acpi_update_irq(dev); + } + break; + case 0x2d: + /* GLBCTL - Global Control Register (IO) */ + dev->regs.glbctl &= ~((val << 8) & 0x0100); + if (val & 0x01) + dev->regs.smi_active = 0; + break; + case 0x2f: + /* SMI Command */ + if (size == 1) { + dev->regs.smicmd = val & 0xff; + dev->regs.glbsts |= 0x40; + if (dev->regs.glben & 0x40) + acpi_raise_smi(dev); + } + break; + case 0x30: case 0x31: case 0x32: case 0x33: + /* Primary Activity Detect Status */ + dev->regs.padsts &= ~((val << shift32) & 0x000000fd); + break; + case 0x34: case 0x35: case 0x36: case 0x37: + /* Primary Activity Detect Enable */ + dev->regs.paden = ((dev->regs.paden & ~(0xff << shift32)) | (val << shift32)) & 0x000000fd; + break; + case 0x38: case 0x39: case 0x3a: case 0x3b: + /* GP Timer Reload Enable */ + dev->regs.gptren = ((dev->regs.gptren & ~(0xff << shift32)) | (val << shift32)) & 0x000000d9; + break; + case 0x40: + /* GPIO Direction Control */ + if (size == 1) + dev->regs.gpio_dir = val & 0xff; + break; + case 0x42: + /* GPIO port Output Value */ + if (size == 1) + dev->regs.gpio_val = val & 0xff; + break; + case 0x46: case 0x47: + /* GPO Port Output Value */ + dev->regs.gpo_val = ((dev->regs.gpo_val & ~(0xff << shift16)) | (val << shift16)) & 0xffff; + break; + } +} + + +static uint32_t +acpi_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) + ret = acpi_reg_read_via(size, addr, p); + else + ret = acpi_reg_read_intel(size, addr, p); + + return ret; +} + + +static void +acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *p) +{ + acpi_t *dev = (acpi_t *) p; + + if (dev->vendor == VEN_VIA) + acpi_reg_write_via(size, addr, val, p); + else + acpi_reg_write_intel(size, addr, val, p); +} + + static uint32_t acpi_reg_readl(uint16_t addr, void *p) { @@ -440,6 +736,46 @@ acpi_set_nvr(acpi_t *dev, nvr_t *nvr) } +static void +acpi_apm_out(uint16_t port, uint8_t val, void *p) +{ + acpi_t *dev = (acpi_t *) p; + + acpi_log("[%04X:%08X] APM write: %04X = %02X (BX = %04X, CX = %04X)\n", CS, cpu_state.pc, port, val, BX, CX); + + port &= 0x0001; + + if (port == 0x0000) { + dev->apm->cmd = val; + if (dev->apm->do_smi) { + if (dev->vendor == VEN_INTEL) + dev->regs.glbsts |= 0x20; + acpi_raise_smi(dev); + } + } else + dev->apm->stat = val; +} + + +static uint8_t +acpi_apm_in(uint16_t port, void *p) +{ + acpi_t *dev = (acpi_t *) p; + uint8_t ret = 0xff; + + port &= 0x0001; + + if (port == 0x0000) + ret = dev->apm->cmd; + else + ret = dev->apm->stat; + + acpi_log("[%04X:%08X] APM read: %04X = %02X\n", CS, cpu_state.pc, port, ret); + + return ret; +} + + static void acpi_reset(void *priv) { @@ -482,6 +818,13 @@ acpi_init(const device_t *info) if (dev == NULL) return(NULL); memset(dev, 0x00, sizeof(acpi_t)); + dev->vendor = info->local; + + if (dev->vendor == VEN_INTEL) { + dev->apm = device_add(&apm_pci_acpi_device); + io_sethandler(0x00b2, 0x0002, acpi_apm_in, NULL, NULL, acpi_apm_out, NULL, NULL, dev); + } + timer_add(&dev->timer, acpi_timer_count, dev, 0); timer_set_delay_u64(&dev->timer, ACPICONST); @@ -489,11 +832,26 @@ acpi_init(const device_t *info) } -const device_t acpi_device = +const device_t acpi_intel_device = { - "ACPI", + "ACPI v1.0", DEVICE_PCI, - 0, + VEN_INTEL, + acpi_init, + acpi_close, + acpi_reset, + NULL, + acpi_speed_changed, + NULL, + NULL +}; + + +const device_t acpi_via_device = +{ + "ACPI v1.2", + DEVICE_PCI, + VEN_VIA, acpi_init, acpi_close, acpi_reset, diff --git a/src/apm.c b/src/apm.c index b197c0964..38d223e88 100644 --- a/src/apm.c +++ b/src/apm.c @@ -116,7 +116,8 @@ static void apm_t *dev = (apm_t *) malloc(sizeof(apm_t)); memset(dev, 0, sizeof(apm_t)); - io_sethandler(0x00b2, 0x0002, apm_in, NULL, NULL, apm_out, NULL, NULL, dev); + if (info->local == 0) + io_sethandler(0x00b2, 0x0002, apm_in, NULL, NULL, apm_out, NULL, NULL, dev); return dev; } @@ -150,3 +151,18 @@ const device_t apm_pci_device = NULL, NULL }; + + +const device_t apm_pci_acpi_device = +{ + "Advanced Power Management (PCI)", + DEVICE_PCI, + 1, + apm_init, + apm_close, + apm_reset, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/include/86box/acpi.h b/src/include/86box/acpi.h index ca0cb3b93..fa10aaa2f 100644 --- a/src/include/86box/acpi.h +++ b/src/include/86box/acpi.h @@ -6,13 +6,6 @@ * * This file is part of the 86Box distribution. * - * Implementation of the ISA Bus (de)Bugger expansion card - * sold as a DIY kit in the late 1980's in The Netherlands. - * This card was a assemble-yourself 8bit ISA addon card for - * PC and AT systems that had several tools to aid in low- - * level debugging (mostly for faulty BIOSes, bootloaders - * and system kernels...) - * * Definitions for the ACPI emulation. * * @@ -46,21 +39,31 @@ extern "C" { #define ACPI_ENABLE 0xf1 #define ACPI_DISABLE 0xf0 +#define VEN_INTEL 0x8086 +#define VEN_VIA 0x1106 + typedef struct { uint8_t plvl2, plvl3, + smicmd, gpio_dir, + gpio_val, extsmi_val, timer32, gpireg[3], gporeg[4]; uint16_t pmsts, pmen, pmcntrl, gpsts, - gpen, io_base; - int slot, - irq_mode, irq_pin; + gpen, io_base, + gpscien, gpsmien, + pscntrl, gpo_val, + gpi_val; + int slot, irq_mode, + irq_pin, smi_lock, + smi_active; uint32_t pcntrl, glbsts, devsts, glben, glbctl, devctl, - timer_val; + padsts, paden, + gptren, timer_val; uint64_t tmr_overflow_time; } acpi_regs_t; @@ -69,13 +72,16 @@ typedef struct { acpi_regs_t regs; uint8_t gporeg_default[4]; + int vendor; pc_timer_t timer; nvr_t *nvr; + apm_t *apm; } acpi_t; /* Global variables. */ -extern const device_t acpi_device; +extern const device_t acpi_intel_device; +extern const device_t acpi_via_device; /* Functions. */ diff --git a/src/include/86box/apm.h b/src/include/86box/apm.h index b7754f78a..1fd985951 100644 --- a/src/include/86box/apm.h +++ b/src/include/86box/apm.h @@ -6,13 +6,6 @@ * * This file is part of the 86Box distribution. * - * Implementation of the ISA Bus (de)Bugger expansion card - * sold as a DIY kit in the late 1980's in The Netherlands. - * This card was a assemble-yourself 8bit ISA addon card for - * PC and AT systems that had several tools to aid in low- - * level debugging (mostly for faulty BIOSes, bootloaders - * and system kernels...) - * * Definitions for the Advanced Power Management emulation. * * @@ -38,7 +31,9 @@ typedef struct /* Global variables. */ extern const device_t apm_device; + extern const device_t apm_pci_device; +extern const device_t apm_pci_acpi_device; /* Functions. */ diff --git a/src/include/86box/ddma.h b/src/include/86box/ddma.h index 2d0a9f8d9..64642f2ae 100644 --- a/src/include/86box/ddma.h +++ b/src/include/86box/ddma.h @@ -6,13 +6,6 @@ * * This file is part of the 86Box distribution. * - * Implementation of the ISA Bus (de)Bugger expansion card - * sold as a DIY kit in the late 1980's in The Netherlands. - * This card was a assemble-yourself 8bit ISA addon card for - * PC and AT systems that had several tools to aid in low- - * level debugging (mostly for faulty BIOSes, bootloaders - * and system kernels...) - * * Definitions for the Distributed DMA emulation. * * diff --git a/src/include/86box/piix.h b/src/include/86box/piix.h index e07607606..9f6724fae 100644 --- a/src/include/86box/piix.h +++ b/src/include/86box/piix.h @@ -4,7 +4,8 @@ * PC systems and compatibles from 1981 through fairly recent * system designs based on the PCI bus. * - * Emulation of the Intel PIIX and PIIX3 Xcelerators. + * Emulation of the Intel PIIX, PIIX3, PIIX4, PIIX4E, and SMSC + * SLC90E66 (Victory66) Xcelerators. * * Emulation core dispatcher. * diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index b027796a2..aced538c8 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -6,13 +6,6 @@ * * This file is part of the 86Box distribution. * - * Implementation of the ISA Bus (de)Bugger expansion card - * sold as a DIY kit in the late 1980's in The Netherlands. - * This card was a assemble-yourself 8bit ISA addon card for - * PC and AT systems that had several tools to aid in low- - * level debugging (mostly for faulty BIOSes, bootloaders - * and system kernels...) - * * Definitions for the Distributed DMA emulation. * * diff --git a/src/intel_piix.c b/src/intel_piix.c index 257b9be9a..4a9a80f1e 100644 --- a/src/intel_piix.c +++ b/src/intel_piix.c @@ -4,7 +4,8 @@ * PC systems and compatibles from 1981 through fairly recent * system designs based on the PCI bus. * - * Emulation of the Intel PIIX and PIIX3 Xcelerators. + * Emulation of the Intel PIIX, PIIX3, PIIX4, PIIX4E, and SMSC + * SLC90E66 (Victory66) Xcelerators. * * PRD format : * word 0 - base address @@ -779,7 +780,7 @@ piix_write(int func, int addr, uint8_t val, void *priv) case 0x04: fregs[0x04] = (val & 0x01); smbus_update_io_mapping(dev); - apm_set_do_smi(dev->apm, !!(fregs[0x5b] & 0x02) && !!(val & 0x01)); + apm_set_do_smi(dev->acpi->apm, !!(fregs[0x5b] & 0x02) && !!(val & 0x01)); break; case 0x07: if (val & 0x08) @@ -844,7 +845,7 @@ piix_write(int func, int addr, uint8_t val, void *priv) break; case 0x5b: fregs[addr] = val & 0x03; - apm_set_do_smi(dev->apm, !!(val & 0x02) && !!(fregs[0x04] & 0x01)); + apm_set_do_smi(dev->acpi->apm, !!(val & 0x02) && !!(fregs[0x04] & 0x01)); break; case 0x63: fregs[addr] = val & 0xf7; @@ -1109,9 +1110,7 @@ piix_apm_out(uint16_t port, uint8_t val, void *p) piix_t *dev = (piix_t *) p; if (dev->apm->do_smi) { - if (dev->type > 3) - dev->acpi->regs.glbsts |= 0x20; - else + if (dev->type < 4) dev->regs[0][0xaa] |= 0x80; } } @@ -1189,7 +1188,7 @@ static void dev->nvr = device_add(&piix4_nvr_device); dev->smbus = device_add(&piix4_smbus_device); - dev->acpi = device_add(&acpi_device); + dev->acpi = device_add(&acpi_intel_device); acpi_set_slot(dev->acpi, dev->pci_slot); acpi_set_nvr(dev->acpi, dev->nvr); @@ -1206,9 +1205,13 @@ static void } else cpu_fast_off_val = cpu_fast_off_count = 0; - dev->apm = device_add(&apm_pci_device); - /* APM intercept handler to update PIIX/PIIX3 and PIIX4/4E/SMSC ACPI SMI status on APM SMI. */ - io_sethandler(0x00b2, 0x0001, NULL, NULL, NULL, piix_apm_out, NULL, NULL, dev); + /* On PIIX4, PIIX4E, and SMSC, APM is added by the ACPI device. */ + if (dev->type < 4) { + dev->apm = device_add(&apm_pci_device); + /* APM intercept handler to update PIIX/PIIX3 and PIIX4/4E/SMSC ACPI SMI status on APM SMI. */ + io_sethandler(0x00b2, 0x0001, NULL, NULL, NULL, piix_apm_out, NULL, NULL, dev); + } + dev->port_92 = device_add(&port_92_pci_device); dma_alias_set();