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();