DevACPI.cpp revision ec7708c74d7fc8feb18fbe1f84b320ec86fb11ef
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/* $Id$ */
247efe202344328bffb8de7e47aee60039cd95e0vboxsync/** @file
247efe202344328bffb8de7e47aee60039cd95e0vboxsync * DevACPI - Advanced Configuration and Power Interface (ACPI) Device.
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/*
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * Copyright (C) 2006-2009 Sun Microsystems, Inc.
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync *
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * available from http://www.virtualbox.org. This file is free software;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * you can redistribute it and/or modify it under the terms of the GNU
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * General Public License (GPL) as published by the Free Software
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync *
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * additional information or have any questions.
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/*******************************************************************************
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync* Header Files *
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync*******************************************************************************/
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define LOG_GROUP LOG_GROUP_DEV_ACPI
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#include <VBox/pdmdev.h>
6095269a3237b1ef8bf4edefc11f2d888d8a41ebvboxsync#include <VBox/pgm.h>
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#include <VBox/log.h>
685409983863f02e8295369273d1844dca1f51c5vboxsync#include <VBox/param.h>
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#include <iprt/assert.h>
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#include <iprt/asm.h>
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#ifdef IN_RING3
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync# include <iprt/alloc.h>
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync# include <iprt/string.h>
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync# include <iprt/uuid.h>
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync#endif /* IN_RING3 */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#include "../Builtins.h"
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync#ifdef LOG_ENABLED
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync# define DEBUG_ACPI
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#endif
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync#if defined(IN_RING3) && !defined(VBOX_DEVICE_STRUCT_TESTCASE)
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncint acpiPrepareDsdt(PPDMDEVINS pDevIns, void* *ppPtr, size_t *puDsdtLen);
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncint acpiCleanupDsdt(PPDMDEVINS pDevIns, void* pPtr);
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncint acpiPrepareSsdt(PPDMDEVINS pDevIns, void* *ppPtr, size_t *puSsdtLen);
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncint acpiCleanupSsdt(PPDMDEVINS pDevIns, void* pPtr);
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#endif /* !IN_RING3 */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/*******************************************************************************
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync* Defined Constants And Macros *
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync*******************************************************************************/
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define DEBUG_HEX 0x3000
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define DEBUG_CHR 0x3001
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define PM_TMR_FREQ 3579545
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/* Default base for PM PIIX4 device */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define PM_PORT_BASE 0x4000
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/* Port offsets in PM device */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncenum
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync{
8d4665a316d78d6587fd1c9da948f7aa37d0bfddvboxsync PM1a_EVT_OFFSET = 0x00,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync PM1b_EVT_OFFSET = -1, /**< not supported */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync PM1a_CTL_OFFSET = 0x04,
ec9aa1180070b037866f064ce720254cd9f03721vboxsync PM1b_CTL_OFFSET = -1, /**< not supported */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync PM2_CTL_OFFSET = -1, /**< not supported */
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync PM_TMR_OFFSET = 0x08,
ec9aa1180070b037866f064ce720254cd9f03721vboxsync GPE0_OFFSET = 0x20,
ec9aa1180070b037866f064ce720254cd9f03721vboxsync GPE1_OFFSET = -1 /**< not supported */
8d4665a316d78d6587fd1c9da948f7aa37d0bfddvboxsync};
dba1919dac01f490c625e0470b528e469c30651dvboxsync
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define BAT_INDEX 0x00004040
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define BAT_DATA 0x00004044
8d4665a316d78d6587fd1c9da948f7aa37d0bfddvboxsync#define SYSI_INDEX 0x00004048
dba1919dac01f490c625e0470b528e469c30651dvboxsync#define SYSI_DATA 0x0000404c
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define ACPI_RESET_BLK 0x00004050
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
8d4665a316d78d6587fd1c9da948f7aa37d0bfddvboxsync/* PM1x status register bits */
dba1919dac01f490c625e0470b528e469c30651dvboxsync#define TMR_STS RT_BIT(0)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define RSR1_STS (RT_BIT(1) | RT_BIT(2) | RT_BIT(3))
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define BM_STS RT_BIT(4)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define GBL_STS RT_BIT(5)
dba1919dac01f490c625e0470b528e469c30651dvboxsync#define RSR2_STS (RT_BIT(6) | RT_BIT(7))
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define PWRBTN_STS RT_BIT(8)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define SLPBTN_STS RT_BIT(9)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define RTC_STS RT_BIT(10)
dba1919dac01f490c625e0470b528e469c30651dvboxsync#define IGN_STS RT_BIT(11)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define RSR3_STS (RT_BIT(12) | RT_BIT(13) | RT_BIT(14))
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define WAK_STS RT_BIT(15)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define RSR_STS (RSR1_STS | RSR2_STS | RSR3_STS)
dba1919dac01f490c625e0470b528e469c30651dvboxsync
ec9aa1180070b037866f064ce720254cd9f03721vboxsync/* PM1x enable register bits */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define TMR_EN RT_BIT(0)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define RSR1_EN (RT_BIT(1) | RT_BIT(2) | RT_BIT(3) | RT_BIT(4))
dba1919dac01f490c625e0470b528e469c30651dvboxsync#define GBL_EN RT_BIT(5)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define RSR2_EN (RT_BIT(6) | RT_BIT(7))
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define PWRBTN_EN RT_BIT(8)
8d4665a316d78d6587fd1c9da948f7aa37d0bfddvboxsync#define SLPBTN_EN RT_BIT(9)
dba1919dac01f490c625e0470b528e469c30651dvboxsync#define RTC_EN RT_BIT(10)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define RSR3_EN (RT_BIT(11) | RT_BIT(12) | RT_BIT(13) | RT_BIT(14) | RT_BIT(15))
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync#define RSR_EN (RSR1_EN | RSR2_EN | RSR3_EN)
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync#define IGN_EN 0
e77749d161a9912b95090202d25c428bc8314dadvboxsync
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync/* PM1x control register bits */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define SCI_EN RT_BIT(0)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define BM_RLD RT_BIT(1)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define GBL_RLS RT_BIT(2)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define RSR1_CNT (RT_BIT(3) | RT_BIT(4) | RT_BIT(5) | RT_BIT(6) | RT_BIT(7) | RT_BIT(8))
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define IGN_CNT RT_BIT(9)
dba1919dac01f490c625e0470b528e469c30651dvboxsync#define SLP_TYPx_SHIFT 10
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define SLP_TYPx_MASK 7
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define SLP_EN RT_BIT(13)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define RSR2_CNT (RT_BIT(14) | RT_BIT(15))
dba1919dac01f490c625e0470b528e469c30651dvboxsync#define RSR_CNT (RSR1_CNT | RSR2_CNT)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define GPE0_BATTERY_INFO_CHANGED RT_BIT(0)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
ec9aa1180070b037866f064ce720254cd9f03721vboxsyncenum
ec9aa1180070b037866f064ce720254cd9f03721vboxsync{
ec9aa1180070b037866f064ce720254cd9f03721vboxsync BAT_STATUS_STATE = 0x00, /**< BST battery state */
dba1919dac01f490c625e0470b528e469c30651dvboxsync BAT_STATUS_PRESENT_RATE = 0x01, /**< BST battery present rate */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync BAT_STATUS_REMAINING_CAPACITY = 0x02, /**< BST battery remaining capacity */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync BAT_STATUS_PRESENT_VOLTAGE = 0x03, /**< BST battery present voltage */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync BAT_INFO_UNITS = 0x04, /**< BIF power unit */
dba1919dac01f490c625e0470b528e469c30651dvboxsync BAT_INFO_DESIGN_CAPACITY = 0x05, /**< BIF design capacity */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync BAT_INFO_LAST_FULL_CHARGE_CAPACITY = 0x06, /**< BIF last full charge capacity */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync BAT_INFO_TECHNOLOGY = 0x07, /**< BIF battery technology */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync BAT_INFO_DESIGN_VOLTAGE = 0x08, /**< BIF design voltage */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync BAT_INFO_DESIGN_CAPACITY_OF_WARNING = 0x09, /**< BIF design capacity of warning */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync BAT_INFO_DESIGN_CAPACITY_OF_LOW = 0x0A, /**< BIF design capacity of low */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync BAT_INFO_CAPACITY_GRANULARITY_1 = 0x0B, /**< BIF battery capacity granularity 1 */
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync BAT_INFO_CAPACITY_GRANULARITY_2 = 0x0C, /**< BIF battery capacity granularity 2 */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync BAT_DEVICE_STATUS = 0x0D, /**< STA device status */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync BAT_POWER_SOURCE = 0x0E, /**< PSR power source */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync BAT_INDEX_LAST
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync};
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncenum
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync{
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_LOW_MEMORY_LENGTH = 0,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_USE_IOAPIC = 1,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_HPET_STATUS = 2,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_SMC_STATUS = 3,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_FDC_STATUS = 4,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_CPU0_STATUS = 5,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_CPU1_STATUS = 6,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_CPU2_STATUS = 7,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_CPU3_STATUS = 8,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_HIGH_MEMORY_LENGTH= 9,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_RTC_STATUS = 10,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_CPU_LOCKED = 11,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_CPU_LOCK_CHECK = 12,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_END = 15,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_INVALID = 0x80,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync SYSTEM_INFO_INDEX_VALID = 0x200
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync};
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define AC_OFFLINE 0
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define AC_ONLINE 1
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define BAT_TECH_PRIMARY 1
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define BAT_TECH_SECONDARY 2
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define STA_DEVICE_PRESENT_MASK RT_BIT(0) /**< present */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define STA_DEVICE_ENABLED_MASK RT_BIT(1) /**< enabled and decodes its resources */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define STA_DEVICE_SHOW_IN_UI_MASK RT_BIT(2) /**< should be shown in UI */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define STA_DEVICE_FUNCTIONING_PROPERLY_MASK RT_BIT(3) /**< functioning properly */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define STA_BATTERY_PRESENT_MASK RT_BIT(4) /**< the battery is present */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/*******************************************************************************
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync* Structures and Typedefs *
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync*******************************************************************************/
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/**
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * The ACPI device state.
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsynctypedef struct ACPIState
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync{
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync PCIDevice dev;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint16_t pm1a_en;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint16_t pm1a_sts;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint16_t pm1a_ctl;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** Number of logical CPUs in guest */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint16_t cCpus;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync int64_t pm_timer_initial;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync PTMTIMERR3 tsR3;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync PTMTIMERR0 tsR0;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync PTMTIMERRC tsRC;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t gpe0_en;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t gpe0_sts;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync unsigned int uBatteryIndex;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t au8BatteryInfo[13];
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync unsigned int uSystemInfoIndex;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint64_t u64RamSize;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** The number of bytes above 4GB. */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint64_t cbRamHigh;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** The number of bytes below 4GB. */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t cbRamLow;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** Current ACPI S* state. We support S0 and S5 */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t uSleepState;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t au8RSDPPage[0x1000];
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** This is a workaround for incorrect index field handling by Intels ACPICA.
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * The system info _INI method writes to offset 0x200. We either observe a
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * write request to index 0x80 (in that case we don't change the index) or a
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * write request to offset 0x200 (in that case we divide the index value by
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * 4. Note that the _STA method is sometimes called prior to the _INI method
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * (ACPI spec 6.3.7, _STA). See the special case for BAT_DEVICE_STATUS in
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync * acpiBatIndexWrite() for handling this. */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8IndexShift;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** provide an I/O-APIC */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8UseIOApic;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** provide a floppy controller */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync bool fUseFdc;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** If High Precision Event Timer device should be supported */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync bool fUseHpet;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** If System Management Controller device should be supported */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync bool fUseSmc;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** the guest handled the last power button event */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync bool fPowerButtonHandled;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** If ACPI CPU device should be shown */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync bool fShowCpu;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** If Real Time Clock ACPI object to be shown */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync bool fShowRtc;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** I/O port address of PM device. */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync RTIOPORT uPmIoPortBase;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** Flag whether the GC part of the device is enabled. */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync bool fGCEnabled;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** Flag whether the R0 part of the device is enabled. */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync bool fR0Enabled;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** Array of flags of attached CPUs */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync VMCPUSET CpuSetAttached;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** Which CPU to check for the locked status. */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t idCpuLockCheck;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** Mask of locked CPUs (used by the guest) */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync VMCPUSET CpuSetLocked;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** Flag whether CPU hot plugging is enabled */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync bool fCpuHotPlug;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** Aligning IBase. */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync bool afAlignment[4];
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** ACPI port base interface. */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync PDMIBASE IBase;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** ACPI port interface. */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync PDMIACPIPORT IACPIPort;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** Pointer to the device instance. */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync PPDMDEVINSR3 pDevIns;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** Pointer to the driver base interface */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync R3PTRTYPE(PPDMIBASE) pDrvBase;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /** Pointer to the driver connector interface */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync R3PTRTYPE(PPDMIACPICONNECTOR) pDrv;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* Pointer to default PCI config read function */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync R3PTRTYPE(PFNPCICONFIGREAD) pfnAcpiPciConfigRead;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* Pointer to default PCI config write function */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync R3PTRTYPE(PFNPCICONFIGWRITE) pfnAcpiPciConfigWrite;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync} ACPIState;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#pragma pack(1)
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/** Generic Address Structure (see ACPIspec 3.0, 5.2.3.1) */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncstruct ACPIGENADDR
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync{
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8AddressSpaceId; /**< 0=sys, 1=IO, 2=PCICfg, 3=emb, 4=SMBus */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8RegisterBitWidth; /**< size in bits of the given register */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8RegisterBitOffset; /**< bit offset of register */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8AccessSize; /**< 1=byte, 2=word, 3=dword, 4=qword */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint64_t u64Address; /**< 64-bit address of register */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync};
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncAssertCompileSize(ACPIGENADDR, 12);
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/** Root System Description Pointer */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncstruct ACPITBLRSDP
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync{
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t au8Signature[8]; /**< 'RSD PTR ' */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8Checksum; /**< checksum for the first 20 bytes */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t au8OemId[6]; /**< OEM-supplied identifier */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8Revision; /**< revision number, currently 2 */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define ACPI_REVISION 2 /**< ACPI 3.0 */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32RSDT; /**< phys addr of RSDT */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32Length; /**< bytes of this table */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint64_t u64XSDT; /**< 64-bit phys addr of XSDT */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8ExtChecksum; /**< checksum of entire table */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8Reserved[3]; /**< reserved */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync};
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncAssertCompileSize(ACPITBLRSDP, 36);
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/** System Description Table Header */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncstruct ACPITBLHEADER
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync{
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t au8Signature[4]; /**< table identifier */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32Length; /**< length of the table including header */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8Revision; /**< revision number */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8Checksum; /**< all fields inclusive this add to zero */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t au8OemId[6]; /**< OEM-supplied string */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t au8OemTabId[8]; /**< to identify the particular data table */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32OemRevision; /**< OEM-supplied revision number */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t au8CreatorId[4]; /**< ID for the ASL compiler */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32CreatorRev; /**< revision for the ASL compiler */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync};
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncAssertCompileSize(ACPITBLHEADER, 36);
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/** Root System Description Table */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncstruct ACPITBLRSDT
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync{
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync ACPITBLHEADER header;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32Entry[1]; /**< array of phys. addresses to other tables */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync};
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncAssertCompileSize(ACPITBLRSDT, 40);
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/** Extended System Description Table */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncstruct ACPITBLXSDT
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync{
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync ACPITBLHEADER header;
247efe202344328bffb8de7e47aee60039cd95e0vboxsync uint64_t u64Entry[1]; /**< array of phys. addresses to other tables */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync};
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncAssertCompileSize(ACPITBLXSDT, 44);
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/** Fixed ACPI Description Table */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncstruct ACPITBLFADT
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync{
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync ACPITBLHEADER header;
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync uint32_t u32FACS; /**< phys. address of FACS */
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync uint32_t u32DSDT; /**< phys. address of DSDT */
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync uint8_t u8IntModel; /**< was eleminated in ACPI 2.0 */
e77749d161a9912b95090202d25c428bc8314dadvboxsync#define INT_MODEL_DUAL_PIC 1 /**< for ACPI 2+ */
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync#define INT_MODEL_MULTIPLE_APIC 2
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync uint8_t u8PreferredPMProfile; /**< preferred power management profile */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint16_t u16SCIInt; /**< system vector the SCI is wired in 8259 mode */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define SCI_INT 9
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32SMICmd; /**< system port address of SMI command port */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define SMI_CMD 0x0000442e
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync uint8_t u8AcpiEnable; /**< SMICmd val to disable ownship of ACPIregs */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define ACPI_ENABLE 0xa1
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8AcpiDisable; /**< SMICmd val to re-enable ownship of ACPIregs */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define ACPI_DISABLE 0xa0
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8S4BIOSReq; /**< SMICmd val to enter S4BIOS state */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8PStateCnt; /**< SMICmd val to assume processor performance
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync state control responsibility */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32PM1aEVTBLK; /**< port addr of PM1a event regs block */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32PM1bEVTBLK; /**< port addr of PM1b event regs block */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32PM1aCTLBLK; /**< port addr of PM1a control regs block */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32PM1bCTLBLK; /**< port addr of PM1b control regs block */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32PM2CTLBLK; /**< port addr of PM2 control regs block */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32PMTMRBLK; /**< port addr of PMTMR regs block */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32GPE0BLK; /**< port addr of gen-purp event 0 regs block */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32GPE1BLK; /**< port addr of gen-purp event 1 regs block */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8PM1EVTLEN; /**< bytes decoded by PM1a_EVT_BLK. >= 4 */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8PM1CTLLEN; /**< bytes decoded by PM1b_CNT_BLK. >= 2 */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8PM2CTLLEN; /**< bytes decoded by PM2_CNT_BLK. >= 1 or 0 */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8PMTMLEN; /**< bytes decoded by PM_TMR_BLK. ==4 */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8GPE0BLKLEN; /**< bytes decoded by GPE0_BLK. %2==0 */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define GPE0_BLK_LEN 2
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8GPE1BLKLEN; /**< bytes decoded by GPE1_BLK. %2==0 */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define GPE1_BLK_LEN 0
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8GPE1BASE; /**< offset of GPE1 based events */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define GPE1_BASE 0
ec9aa1180070b037866f064ce720254cd9f03721vboxsync uint8_t u8CSTCNT; /**< SMICmd val to indicate OS supp for C states */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync uint16_t u16PLVL2LAT; /**< us to enter/exit C2. >100 => unsupported */
dba1919dac01f490c625e0470b528e469c30651dvboxsync#define P_LVL2_LAT 101 /**< C2 state not supported */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync uint16_t u16PLVL3LAT; /**< us to enter/exit C3. >1000 => unsupported */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define P_LVL3_LAT 1001 /**< C3 state not supported */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync uint16_t u16FlushSize; /**< # of flush strides to read to flush dirty
dba1919dac01f490c625e0470b528e469c30651dvboxsync lines from any processors memory caches */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#define FLUSH_SIZE 0 /**< Ignored if WBVIND set in FADT_FLAGS */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint16_t u16FlushStride; /**< cache line width */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define FLUSH_STRIDE 0 /**< Ignored if WBVIND set in FADT_FLAGS */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8DutyOffset;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8DutyWidth;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8DayAlarm; /**< RTC CMOS RAM index of day-of-month alarm */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8MonAlarm; /**< RTC CMOS RAM index of month-of-year alarm */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8Century; /**< RTC CMOS RAM index of century */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint16_t u16IAPCBOOTARCH; /**< IA-PC boot architecture flags */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define IAPC_BOOT_ARCH_LEGACY_DEV RT_BIT(0) /**< legacy devices present such as LPT
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync (COM too?) */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define IAPC_BOOT_ARCH_8042 RT_BIT(1) /**< legacy keyboard device present */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define IAPC_BOOT_ARCH_NO_VGA RT_BIT(2) /**< VGA not present */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint8_t u8Must0_0; /**< must be 0 */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync uint32_t u32Flags; /**< fixed feature flags */
8d4665a316d78d6587fd1c9da948f7aa37d0bfddvboxsync#define FADT_FL_WBINVD RT_BIT(0) /**< emulation of WBINVD available */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define FADT_FL_WBINVD_FLUSH RT_BIT(1)
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define FADT_FL_PROC_C1 RT_BIT(2) /**< 1=C1 supported on all processors */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define FADT_FL_P_LVL2_UP RT_BIT(3) /**< 1=C2 works on SMP and UNI systems */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define FADT_FL_PWR_BUTTON RT_BIT(4) /**< 1=power button handled as ctrl method dev */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define FADT_FL_SLP_BUTTON RT_BIT(5) /**< 1=sleep button handled as ctrl method dev */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define FADT_FL_FIX_RTC RT_BIT(6) /**< 0=RTC wake status in fixed register */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#define FADT_FL_RTC_S4 RT_BIT(7) /**< 1=RTC can wake system from S4 */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync#define FADT_FL_TMR_VAL_EXT RT_BIT(8) /**< 1=TMR_VAL implemented as 32 bit */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync#define FADT_FL_DCK_CAP RT_BIT(9) /**< 0=system cannot support docking */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync#define FADT_FL_RESET_REG_SUP RT_BIT(10) /**< 1=system supports system resets */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync#define FADT_FL_SEALED_CASE RT_BIT(11) /**< 1=case is sealed */
685409983863f02e8295369273d1844dca1f51c5vboxsync#define FADT_FL_HEADLESS RT_BIT(12) /**< 1=system cannot detect moni/keyb/mouse */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync#define FADT_FL_CPU_SW_SLP RT_BIT(13)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync#define FADT_FL_PCI_EXT_WAK RT_BIT(14) /**< 1=system supports PCIEXP_WAKE_STS */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync#define FADT_FL_USE_PLATFORM_CLOCK RT_BIT(15) /**< 1=system has ACPI PM timer */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync#define FADT_FL_S4_RTC_STS_VALID RT_BIT(16) /**< 1=RTC_STS flag is valid when waking from S4 */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync#define FADT_FL_REMOVE_POWER_ON_CAPABLE RT_BIT(17) /**< 1=platform can remote power on */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync#define FADT_FL_FORCE_APIC_CLUSTER_MODEL RT_BIT(18)
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync#define FADT_FL_FORCE_APIC_PHYS_DEST_MODE RT_BIT(19)
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync /** Start of the ACPI 2.0 extension. */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync ACPIGENADDR ResetReg; /**< ext addr of reset register */
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync uint8_t u8ResetVal; /**< ResetReg value to reset the system */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync#define ACPI_RESET_REG_VAL 0x10
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t au8Must0_1[3]; /**< must be 0 */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint64_t u64XFACS; /**< 64-bit phys address of FACS */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync uint64_t u64XDSDT; /**< 64-bit phys address of DSDT */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync ACPIGENADDR X_PM1aEVTBLK; /**< ext addr of PM1a event regs block */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync ACPIGENADDR X_PM1bEVTBLK; /**< ext addr of PM1b event regs block */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync ACPIGENADDR X_PM1aCTLBLK; /**< ext addr of PM1a control regs block */
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync ACPIGENADDR X_PM1bCTLBLK; /**< ext addr of PM1b control regs block */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync ACPIGENADDR X_PM2CTLBLK; /**< ext addr of PM2 control regs block */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync ACPIGENADDR X_PMTMRBLK; /**< ext addr of PMTMR control regs block */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync ACPIGENADDR X_GPE0BLK; /**< ext addr of GPE1 regs block */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ACPIGENADDR X_GPE1BLK; /**< ext addr of GPE1 regs block */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync};
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncAssertCompileSize(ACPITBLFADT, 244);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync#define ACPITBLFADT_VERSION1_SIZE RT_OFFSETOF(ACPITBLFADT, ResetReg)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync/** Firmware ACPI Control Structure */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncstruct ACPITBLFACS
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync{
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t au8Signature[4]; /**< 'FACS' */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint32_t u32Length; /**< bytes of entire FACS structure >= 64 */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint32_t u32HWSignature; /**< systems HW signature at last boot */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint32_t u32FWVector; /**< address of waking vector */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint32_t u32GlobalLock; /**< global lock to sync HW/SW */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint32_t u32Flags; /**< FACS flags */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint64_t u64X_FWVector; /**< 64-bit waking vector */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t u8Version; /**< version of this table */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t au8Reserved[31]; /**< zero */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync};
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncAssertCompileSize(ACPITBLFACS, 64);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync/** Processor Local APIC Structure */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncstruct ACPITBLLAPIC
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync{
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t u8Type; /**< 0 = LAPIC */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t u8Length; /**< 8 */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t u8ProcId; /**< processor ID */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t u8ApicId; /**< local APIC ID */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint32_t u32Flags; /**< Flags */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync#define LAPIC_ENABLED 0x1
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync};
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncAssertCompileSize(ACPITBLLAPIC, 8);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/** I/O APIC Structure */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncstruct ACPITBLIOAPIC
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync{
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t u8Type; /**< 1 == I/O APIC */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t u8Length; /**< 12 */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t u8IOApicId; /**< I/O APIC ID */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t u8Reserved; /**< 0 */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint32_t u32Address; /**< phys address to access I/O APIC */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint32_t u32GSIB; /**< global system interrupt number to start */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync};
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncAssertCompileSize(ACPITBLIOAPIC, 12);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync/** HPET Descriptor Structure */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncstruct ACPITBLHPET
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync{
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync ACPITBLHEADER aHeader;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint32_t u32Id; /**< hardware ID of event timer block
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync [31:16] PCI vendor ID of first timer block
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync [15] legacy replacement IRQ routing capable
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync [14] reserved
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync [13] COUNT_SIZE_CAP counter size
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync [12:8] number of comparators in first timer block
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync [7:0] hardware rev ID */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync ACPIGENADDR HpetAddr; /**< lower 32-bit base address */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t u32Number; /**< sequence number starting at 0 */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint16_t u32MinTick; /**< minimum clock ticks which can be set without
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync lost interrupts while the counter is programmed
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync to operate in periodic mode. Unit: clock tick. */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t u8Attributes; /**< page protextion and OEM attribute. */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync};
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncAssertCompileSize(ACPITBLHPET, 56);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync# ifdef IN_RING3 /** @todo r=bird: Move this down to where it's used. */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync# define PCAT_COMPAT 0x1 /**< system has also a dual-8259 setup */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync/**
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * Multiple APIC Description Table.
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync *
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * This structure looks somewhat convoluted due layout of MADT table in MP case.
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * There extpected to be multiple LAPIC records for each CPU, thus we cannot
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * use regular C structure and proxy to raw memory instead.
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncclass AcpiTableMADT
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync{
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync /**
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * All actual data stored in dynamically allocated memory pointed by this field.
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint8_t *m_pbData;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync /**
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * Number of CPU entries in this MADT.
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint32_t m_cCpus;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncpublic:
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync /**
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * Address of ACPI header
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync inline ACPITBLHEADER *header_addr(void) const
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync {
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync return (ACPITBLHEADER *)m_pbData;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync /**
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * Address of local APIC for each CPU. Note that different CPUs address different LAPICs,
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * although address is the same for all of them.
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync inline uint32_t *u32LAPIC_addr(void) const
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync {
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync return (uint32_t *)(header_addr() + 1);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync /**
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * Address of APIC flags
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync inline uint32_t *u32Flags_addr(void) const
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync {
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync return (uint32_t *)(u32LAPIC_addr() + 1);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync /**
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * Address of per-CPU LAPIC descriptions
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync inline ACPITBLLAPIC *LApics_addr(void) const
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync {
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync return (ACPITBLLAPIC *)(u32Flags_addr() + 1);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync /**
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * Address of IO APIC description
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync inline ACPITBLIOAPIC *IOApic_addr(void) const
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync {
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync return (ACPITBLIOAPIC *)(LApics_addr() + m_cCpus);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync /**
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * Size of MADT.
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * Note that this function assumes IOApic to be the last field in structure.
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync inline uint32_t size(void) const
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync {
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync return (uint8_t *)(IOApic_addr() + 1) - (uint8_t *)header_addr();
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync /**
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * Raw data of MADT.
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync inline const uint8_t *data(void) const
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync {
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync return m_pbData;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync /**
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * Size of MADT for given ACPI config, useful to compute layout.
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync static uint32_t sizeFor(ACPIState *s)
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync {
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync return AcpiTableMADT(s->cCpus).size();
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync /*
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync * Constructor, only works in Ring 3, doesn't look like a big deal.
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync AcpiTableMADT(uint32_t cCpus)
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync {
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync m_cCpus = cCpus;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync m_pbData = NULL; /* size() uses this and gcc will complain if not initilized. */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync uint32_t cb = size();
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync m_pbData = (uint8_t *)RTMemAllocZ(cb);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync ~AcpiTableMADT()
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync {
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync RTMemFree(m_pbData);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync};
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync# endif /* IN_RING3 */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync#pragma pack()
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync#ifndef VBOX_DEVICE_STRUCT_TESTCASE /* exclude the rest of the file */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync/*******************************************************************************
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync* Internal Functions *
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync*******************************************************************************/
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncRT_C_DECLS_BEGIN
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncPDMBOTHCBDECL(int) acpiPMTmrRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync#ifdef IN_RING3
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncPDMBOTHCBDECL(int) acpiPm1aEnRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncPDMBOTHCBDECL(int) acpiPM1aEnWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncPDMBOTHCBDECL(int) acpiPm1aStsRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsyncPDMBOTHCBDECL(int) acpiPM1aStsWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsyncPDMBOTHCBDECL(int) acpiPm1aCtlRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncPDMBOTHCBDECL(int) acpiPM1aCtlWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsyncPDMBOTHCBDECL(int) acpiSmiWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsyncPDMBOTHCBDECL(int) acpiBatIndexWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsyncPDMBOTHCBDECL(int) acpiBatDataRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncPDMBOTHCBDECL(int) acpiSysInfoDataRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsyncPDMBOTHCBDECL(int) acpiSysInfoDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsyncPDMBOTHCBDECL(int) acpiGpe0EnRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsyncPDMBOTHCBDECL(int) acpiGpe0EnWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncPDMBOTHCBDECL(int) acpiGpe0StsRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsyncPDMBOTHCBDECL(int) acpiGpe0StsWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsyncPDMBOTHCBDECL(int) acpiResetWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync# ifdef DEBUG_ACPI
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncPDMBOTHCBDECL(int) acpiDhexWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsyncPDMBOTHCBDECL(int) acpiDchrWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync# endif
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync#endif /* IN_RING3 */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncRT_C_DECLS_END
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync#ifdef IN_RING3
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsyncstatic RTIOPORT acpiPmPort(ACPIState* pAcpi, int32_t offset)
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync{
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync Assert(pAcpi->uPmIoPortBase != 0);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync if (offset == -1)
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync return 0;
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return RTIOPORT(pAcpi->uPmIoPortBase + offset);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync}
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync/* Simple acpiChecksum: all the bytes must add up to 0. */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic uint8_t acpiChecksum(const uint8_t * const data, size_t len)
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync{
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync uint8_t sum = 0;
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync for (size_t i = 0; i < len; ++i)
685409983863f02e8295369273d1844dca1f51c5vboxsync sum += data[i];
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync return -sum;
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync}
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic void acpiPrepareHeader(ACPITBLHEADER *header, const char au8Signature[4],
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync uint32_t u32Length, uint8_t u8Revision)
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync{
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync memcpy(header->au8Signature, au8Signature, 4);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync header->u32Length = RT_H2LE_U32(u32Length);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync header->u8Revision = u8Revision;
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync memcpy(header->au8OemId, "VBOX ", 6);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync memcpy(header->au8OemTabId, "VBOX", 4);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync memcpy(header->au8OemTabId+4, au8Signature, 4);
685409983863f02e8295369273d1844dca1f51c5vboxsync header->u32OemRevision = RT_H2LE_U32(1);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync memcpy(header->au8CreatorId, "ASL ", 4);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync header->u32CreatorRev = RT_H2LE_U32(0x61);
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync}
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic void acpiWriteGenericAddr(ACPIGENADDR *g, uint8_t u8AddressSpaceId,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync uint8_t u8RegisterBitWidth, uint8_t u8RegisterBitOffset,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync uint8_t u8AccessSize, uint64_t u64Address)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync g->u8AddressSpaceId = u8AddressSpaceId;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync g->u8RegisterBitWidth = u8RegisterBitWidth;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync g->u8RegisterBitOffset = u8RegisterBitOffset;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync g->u8AccessSize = u8AccessSize;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync g->u64Address = RT_H2LE_U64(u64Address);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic void acpiPhyscpy(ACPIState *s, RTGCPHYS32 dst, const void * const src, size_t size)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PDMDevHlpPhysWrite(s->pDevIns, dst, src, size);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/** Differentiated System Description Table (DSDT) */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic void acpiSetupDSDT(ACPIState *s, RTGCPHYS32 addr,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync void* pPtr, size_t uDsdtLen)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPhyscpy(s, addr, pPtr, uDsdtLen);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/** Secondary System Description Table (SSDT) */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic void acpiSetupSSDT(ACPIState *s, RTGCPHYS32 addr,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync void* pPtr, size_t uSsdtLen)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPhyscpy(s, addr, pPtr, uSsdtLen);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/** Firmware ACPI Control Structure (FACS) */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic void acpiSetupFACS(ACPIState *s, RTGCPHYS32 addr)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ACPITBLFACS facs;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync memset(&facs, 0, sizeof(facs));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync memcpy(facs.au8Signature, "FACS", 4);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync facs.u32Length = RT_H2LE_U32(sizeof(ACPITBLFACS));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync facs.u32HWSignature = RT_H2LE_U32(0);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync facs.u32FWVector = RT_H2LE_U32(0);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync facs.u32GlobalLock = RT_H2LE_U32(0);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync facs.u32Flags = RT_H2LE_U32(0);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync facs.u64X_FWVector = RT_H2LE_U64(0);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync facs.u8Version = 1;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPhyscpy(s, addr, (const uint8_t *)&facs, sizeof(facs));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/** Fixed ACPI Description Table (FADT aka FACP) */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic void acpiSetupFADT(ACPIState *s, RTGCPHYS32 GCPhysAcpi1, RTGCPHYS32 GCPhysAcpi2, RTGCPHYS32 GCPhysFacs, RTGCPHYS GCPhysDsdt)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ACPITBLFADT fadt;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* First the ACPI version 2+ version of the structure. */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync memset(&fadt, 0, sizeof(fadt));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPrepareHeader(&fadt.header, "FACP", sizeof(fadt), 4);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u32FACS = RT_H2LE_U32(GCPhysFacs);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u32DSDT = RT_H2LE_U32(GCPhysDsdt);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8IntModel = 0; /* dropped from the ACPI 2.0 spec. */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8PreferredPMProfile = 0; /* unspecified */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u16SCIInt = RT_H2LE_U16(SCI_INT);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u32SMICmd = RT_H2LE_U32(SMI_CMD);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8AcpiEnable = ACPI_ENABLE;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8AcpiDisable = ACPI_DISABLE;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8S4BIOSReq = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8PStateCnt = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u32PM1aEVTBLK = RT_H2LE_U32(acpiPmPort(s, PM1a_EVT_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u32PM1bEVTBLK = RT_H2LE_U32(acpiPmPort(s, PM1b_EVT_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u32PM1aCTLBLK = RT_H2LE_U32(acpiPmPort(s, PM1a_CTL_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u32PM1bCTLBLK = RT_H2LE_U32(acpiPmPort(s, PM1b_CTL_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u32PM2CTLBLK = RT_H2LE_U32(acpiPmPort(s, PM2_CTL_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u32PMTMRBLK = RT_H2LE_U32(acpiPmPort(s, PM_TMR_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u32GPE0BLK = RT_H2LE_U32(acpiPmPort(s, GPE0_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u32GPE1BLK = RT_H2LE_U32(acpiPmPort(s, GPE1_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8PM1EVTLEN = 4;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8PM1CTLLEN = 2;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8PM2CTLLEN = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8PMTMLEN = 4;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8GPE0BLKLEN = GPE0_BLK_LEN;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8GPE1BLKLEN = GPE1_BLK_LEN;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8GPE1BASE = GPE1_BASE;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8CSTCNT = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u16PLVL2LAT = RT_H2LE_U16(P_LVL2_LAT);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u16PLVL3LAT = RT_H2LE_U16(P_LVL3_LAT);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u16FlushSize = RT_H2LE_U16(FLUSH_SIZE);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u16FlushStride = RT_H2LE_U16(FLUSH_STRIDE);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8DutyOffset = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8DutyWidth = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8DayAlarm = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8MonAlarm = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8Century = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u16IAPCBOOTARCH = RT_H2LE_U16(IAPC_BOOT_ARCH_LEGACY_DEV | IAPC_BOOT_ARCH_8042);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /** @note WBINVD is required for ACPI versions newer than 1.0 */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u32Flags = RT_H2LE_U32( FADT_FL_WBINVD
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync | FADT_FL_FIX_RTC
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync | FADT_FL_TMR_VAL_EXT);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* We have to force physical APIC mode or Linux can't use more than 8 CPUs */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (s->fCpuHotPlug)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u32Flags |= RT_H2LE_U32(FADT_FL_FORCE_APIC_PHYS_DEST_MODE);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiWriteGenericAddr(&fadt.ResetReg, 1, 8, 0, 1, ACPI_RESET_BLK);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8ResetVal = ACPI_RESET_REG_VAL;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u64XFACS = RT_H2LE_U64((uint64_t)GCPhysFacs);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u64XDSDT = RT_H2LE_U64((uint64_t)GCPhysDsdt);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiWriteGenericAddr(&fadt.X_PM1aEVTBLK, 1, 32, 0, 2, acpiPmPort(s, PM1a_EVT_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiWriteGenericAddr(&fadt.X_PM1bEVTBLK, 0, 0, 0, 0, acpiPmPort(s, PM1b_EVT_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiWriteGenericAddr(&fadt.X_PM1aCTLBLK, 1, 16, 0, 2, acpiPmPort(s, PM1a_CTL_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiWriteGenericAddr(&fadt.X_PM1bCTLBLK, 0, 0, 0, 0, acpiPmPort(s, PM1b_CTL_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiWriteGenericAddr(&fadt.X_PM2CTLBLK, 0, 0, 0, 0, acpiPmPort(s, PM2_CTL_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiWriteGenericAddr(&fadt.X_PMTMRBLK, 1, 32, 0, 3, acpiPmPort(s, PM_TMR_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiWriteGenericAddr(&fadt.X_GPE0BLK, 1, 16, 0, 1, acpiPmPort(s, GPE0_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiWriteGenericAddr(&fadt.X_GPE1BLK, 0, 0, 0, 0, acpiPmPort(s, GPE1_OFFSET));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.header.u8Checksum = acpiChecksum((uint8_t *)&fadt, sizeof(fadt));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPhyscpy(s, GCPhysAcpi2, &fadt, sizeof(fadt));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* Now the ACPI 1.0 version. */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.header.u32Length = ACPITBLFADT_VERSION1_SIZE;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.u8IntModel = INT_MODEL_DUAL_PIC;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.header.u8Checksum = 0; /* Must be zeroed before recalculating checksum! */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync fadt.header.u8Checksum = acpiChecksum((uint8_t *)&fadt, ACPITBLFADT_VERSION1_SIZE);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPhyscpy(s, GCPhysAcpi1, &fadt, ACPITBLFADT_VERSION1_SIZE);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/**
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * Root System Description Table.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * The RSDT and XSDT tables are basically identical. The only difference is 32 vs 64 bits
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * addresses for description headers. RSDT is for ACPI 1.0. XSDT for ACPI 2.0 and up.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic int acpiSetupRSDT(ACPIState *s, RTGCPHYS32 addr, unsigned int nb_entries, uint32_t *addrs)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ACPITBLRSDT *rsdt;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync const size_t size = sizeof(ACPITBLHEADER) + nb_entries * sizeof(rsdt->u32Entry[0]);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rsdt = (ACPITBLRSDT*)RTMemAllocZ(size);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (!rsdt)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return PDMDEV_SET_ERROR(s->pDevIns, VERR_NO_TMP_MEMORY, N_("Cannot allocate RSDT"));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPrepareHeader(&rsdt->header, "RSDT", (uint32_t)size, 1);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync for (unsigned int i = 0; i < nb_entries; ++i)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rsdt->u32Entry[i] = RT_H2LE_U32(addrs[i]);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync Log(("Setup RSDT: [%d] = %x\n", i, rsdt->u32Entry[i]));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rsdt->header.u8Checksum = acpiChecksum((uint8_t*)rsdt, size);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPhyscpy(s, addr, rsdt, size);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync RTMemFree(rsdt);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VINF_SUCCESS;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/** Extended System Description Table. */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic int acpiSetupXSDT(ACPIState *s, RTGCPHYS32 addr, unsigned int nb_entries, uint32_t *addrs)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ACPITBLXSDT *xsdt;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync const size_t size = sizeof(ACPITBLHEADER) + nb_entries * sizeof(xsdt->u64Entry[0]);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync xsdt = (ACPITBLXSDT*)RTMemAllocZ(size);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (!xsdt)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VERR_NO_TMP_MEMORY;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPrepareHeader(&xsdt->header, "XSDT", (uint32_t)size, 1 /* according to ACPI 3.0 specs */);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync for (unsigned int i = 0; i < nb_entries; ++i)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync xsdt->u64Entry[i] = RT_H2LE_U64((uint64_t)addrs[i]);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync Log(("Setup XSDT: [%d] = %RX64\n", i, xsdt->u64Entry[i]));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync xsdt->header.u8Checksum = acpiChecksum((uint8_t*)xsdt, size);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPhyscpy(s, addr, xsdt, size);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync RTMemFree(xsdt);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VINF_SUCCESS;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/** Root System Description Pointer (RSDP) */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic void acpiSetupRSDP(ACPITBLRSDP *rsdp, RTGCPHYS32 GCPhysRsdt, RTGCPHYS GCPhysXsdt)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync memset(rsdp, 0, sizeof(*rsdp));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* ACPI 1.0 part (RSDT */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync memcpy(rsdp->au8Signature, "RSD PTR ", 8);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync memcpy(rsdp->au8OemId, "VBOX ", 6);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rsdp->u8Revision = ACPI_REVISION;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rsdp->u32RSDT = RT_H2LE_U32(GCPhysRsdt);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rsdp->u8Checksum = acpiChecksum((uint8_t*)rsdp, RT_OFFSETOF(ACPITBLRSDP, u32Length));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* ACPI 2.0 part (XSDT) */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rsdp->u32Length = RT_H2LE_U32(sizeof(ACPITBLRSDP));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rsdp->u64XSDT = RT_H2LE_U64(GCPhysXsdt);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rsdp->u8ExtChecksum = acpiChecksum((uint8_t*)rsdp, sizeof(ACPITBLRSDP));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/**
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * Multiple APIC Description Table.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync *
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * @note APIC without IO-APIC hangs Windows Vista therefore we setup both
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync *
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * @todo All hardcoded, should set this up based on the actual VM config!!!!!
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic void acpiSetupMADT(ACPIState *s, RTGCPHYS32 addr)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync uint16_t cpus = s->cCpus;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AcpiTableMADT madt(cpus);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPrepareHeader(madt.header_addr(), "APIC", madt.size(), 2);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync *madt.u32LAPIC_addr() = RT_H2LE_U32(0xfee00000);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync *madt.u32Flags_addr() = RT_H2LE_U32(PCAT_COMPAT);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ACPITBLLAPIC* lapic = madt.LApics_addr();
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync for (uint16_t i = 0; i < cpus; i++)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync lapic->u8Type = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync lapic->u8Length = sizeof(ACPITBLLAPIC);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync lapic->u8ProcId = i;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync lapic->u8ApicId = i;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync lapic->u32Flags = VMCPUSET_IS_PRESENT(&s->CpuSetAttached, i) ? RT_H2LE_U32(LAPIC_ENABLED) : 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync lapic++;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ACPITBLIOAPIC* ioapic = madt.IOApic_addr();
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ioapic->u8Type = 1;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ioapic->u8Length = sizeof(ACPITBLIOAPIC);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /** @todo is this the right id? */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ioapic->u8IOApicId = cpus;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ioapic->u8Reserved = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ioapic->u32Address = RT_H2LE_U32(0xfec00000);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ioapic->u32GSIB = RT_H2LE_U32(0);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync madt.header_addr()->u8Checksum = acpiChecksum(madt.data(), madt.size());
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPhyscpy(s, addr, madt.data(), madt.size());
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/** High Performance Event Timer (HPET) descriptor */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic void acpiSetupHPET(ACPIState *s, RTGCPHYS32 addr)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ACPITBLHPET hpet;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync memset(&hpet, 0, sizeof(hpet));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPrepareHeader(&hpet.aHeader, "HPET", sizeof(hpet), 1);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* Keep base address consistent with appropriate DSDT entry (vbox.dsl) */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiWriteGenericAddr(&hpet.HpetAddr,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync 0 /* Memory address space */,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync 64 /* Register bit width */,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync 0 /* Bit offset */,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync 0, /* Register access size, is it correct? */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync 0xfed00000 /* Address */);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync hpet.u32Id = 0x8086a201; /* must match what HPET ID returns, is it correct ? */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync hpet.u32Number = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync hpet.u32MinTick = 4096;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync hpet.u8Attributes = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync hpet.aHeader.u8Checksum = acpiChecksum((uint8_t *)&hpet, sizeof(hpet));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPhyscpy(s, addr, (const uint8_t *)&hpet, sizeof(hpet));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/* SCI IRQ */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncDECLINLINE(void) acpiSetIrq(ACPIState *s, int level)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (s->pm1a_ctl & SCI_EN)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PDMDevHlpPCISetIrq(s->pDevIns, -1, level);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncDECLINLINE(uint32_t) pm1a_pure_en(uint32_t en)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return en & ~(RSR_EN | IGN_EN);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncDECLINLINE(uint32_t) pm1a_pure_sts(uint32_t sts)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return sts & ~(RSR_STS | IGN_STS);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncDECLINLINE(int) pm1a_level(ACPIState *s)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return (pm1a_pure_en(s->pm1a_en) & pm1a_pure_sts(s->pm1a_sts)) != 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncDECLINLINE(int) gpe0_level(ACPIState *s)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return (s->gpe0_en & s->gpe0_sts) != 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic void update_pm1a(ACPIState *s, uint32_t sts, uint32_t en)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync int old_level, new_level;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (gpe0_level(s))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync old_level = pm1a_level(s);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync new_level = (pm1a_pure_en(en) & pm1a_pure_sts(sts)) != 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->pm1a_en = en;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->pm1a_sts = sts;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (new_level != old_level)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiSetIrq(s, new_level);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic void update_gpe0(ACPIState *s, uint32_t sts, uint32_t en)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync int old_level, new_level;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (pm1a_level(s))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync old_level = (s->gpe0_en & s->gpe0_sts) != 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync new_level = (en & sts) != 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->gpe0_en = en;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->gpe0_sts = sts;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (new_level != old_level)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiSetIrq(s, new_level);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic int acpiPowerDown(ACPIState *s)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
3c616a9e81ee0ab32e2a3a65379eb9dd386e61d2vboxsync int rc = PDMDevHlpVMPowerOff(s->pDevIns);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync if (RT_FAILURE(rc))
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync AssertMsgFailed(("Could not power down the VM. rc = %Rrc\n", rc));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return rc;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/** Converts a ACPI port interface pointer to an ACPI state pointer. */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync#define IACPIPORT_2_ACPISTATE(pInterface) ( (ACPIState*)((uintptr_t)pInterface - RT_OFFSETOF(ACPIState, IACPIPort)) )
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/**
685409983863f02e8295369273d1844dca1f51c5vboxsync * Send an ACPI power off event.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * @returns VBox status code
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * @param pInterface Pointer to the interface structure containing the called function pointer.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic DECLCALLBACK(int) acpiPowerButtonPress(PPDMIACPIPORT pInterface)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->fPowerButtonHandled = false;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync update_pm1a(s, s->pm1a_sts | PWRBTN_STS, s->pm1a_en);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/**
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * Check if the ACPI power button event was handled.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * @returns VBox status code
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * @param pInterface Pointer to the interface structure containing the called function pointer.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * @param pfHandled Return true if the power button event was handled by the guest.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic DECLCALLBACK(int) acpiGetPowerButtonHandled(PPDMIACPIPORT pInterface, bool *pfHandled)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pfHandled = s->fPowerButtonHandled;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/**
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * Check if the Guest entered into G0 (working) or G1 (sleeping).
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *
685409983863f02e8295369273d1844dca1f51c5vboxsync * @returns VBox status code
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * @param pInterface Pointer to the interface structure containing the called function pointer.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * @param pfEntered Return true if the guest entered the ACPI mode.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic DECLCALLBACK(int) acpiGetGuestEnteredACPIMode(PPDMIACPIPORT pInterface, bool *pfEntered)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pfEntered = (s->pm1a_ctl & SCI_EN) != 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic DECLCALLBACK(int) acpiGetCpuStatus(PPDMIACPIPORT pInterface, unsigned uCpu, bool *pfLocked)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pfLocked = VMCPUSET_IS_PRESENT(&s->CpuSetLocked, uCpu);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/**
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * Send an ACPI sleep button event.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * @returns VBox status code
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * @param pInterface Pointer to the interface structure containing the called function pointer.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic DECLCALLBACK(int) acpiSleepButtonPress(PPDMIACPIPORT pInterface)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState *s = IACPIPORT_2_ACPISTATE(pInterface);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync update_pm1a(s, s->pm1a_sts | SLPBTN_STS, s->pm1a_en);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/* PM1a_EVT_BLK enable */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic uint32_t acpiPm1aEnReadw(ACPIState *s, uint32_t addr)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync uint16_t val = s->pm1a_en;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("acpi: acpiPm1aEnReadw -> %#x\n", val));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return val;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic void acpiPM1aEnWritew(ACPIState *s, uint32_t addr, uint32_t val)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("acpi: acpiPM1aEnWritew <- %#x (%#x)\n", val, val & ~(RSR_EN | IGN_EN)));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync val &= ~(RSR_EN | IGN_EN);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync update_pm1a(s, s->pm1a_sts, val);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/* PM1a_EVT_BLK status */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic uint32_t acpiPm1aStsReadw(ACPIState *s, uint32_t addr)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync uint16_t val = s->pm1a_sts;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("acpi: acpiPm1aStsReadw -> %#x\n", val));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return val;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic void acpiPM1aStsWritew(ACPIState *s, uint32_t addr, uint32_t val)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("acpi: acpiPM1aStsWritew <- %#x (%#x)\n", val, val & ~(RSR_STS | IGN_STS)));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (val & PWRBTN_STS)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->fPowerButtonHandled = true; /* Remember that the guest handled the last power button event */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync val = s->pm1a_sts & ~(val & ~(RSR_STS | IGN_STS));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync update_pm1a(s, val, s->pm1a_en);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/* PM1a_CTL_BLK */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic uint32_t acpiPm1aCtlReadw(ACPIState *s, uint32_t addr)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync uint16_t val = s->pm1a_ctl;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("acpi: acpiPm1aCtlReadw -> %#x\n", val));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return val;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic int acpiPM1aCtlWritew(ACPIState *s, uint32_t addr, uint32_t val)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync uint32_t uSleepState;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("acpi: acpiPM1aCtlWritew <- %#x (%#x)\n", val, val & ~(RSR_CNT | IGN_CNT)));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->pm1a_ctl = val & ~(RSR_CNT | IGN_CNT);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync uSleepState = (s->pm1a_ctl >> SLP_TYPx_SHIFT) & SLP_TYPx_MASK;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (uSleepState != s->uSleepState)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->uSleepState = uSleepState;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync switch (uSleepState)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case 0x00: /* S0 */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case 0x05: /* S5 */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync LogRel(("Entering S5 (power down)\n"));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return acpiPowerDown(s);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync default:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync AssertMsgFailed(("Unknown sleep state %#x\n", uSleepState));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/* GPE0_BLK */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic uint32_t acpiGpe0EnReadb(ACPIState *s, uint32_t addr)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync uint8_t val = s->gpe0_en;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("acpi: acpiGpe0EnReadl -> %#x\n", val));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return val;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic void acpiGpe0EnWriteb(ACPIState *s, uint32_t addr, uint32_t val)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("acpi: acpiGpe0EnWritel <- %#x\n", val));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync update_gpe0(s, s->gpe0_sts, val);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic uint32_t acpiGpe0StsReadb(ACPIState *s, uint32_t addr)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync uint8_t val = s->gpe0_sts;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("acpi: acpiGpe0StsReadl -> %#x\n", val));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return val;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic void acpiGpe0StsWriteb(ACPIState *s, uint32_t addr, uint32_t val)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync val = s->gpe0_sts & ~val;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync update_gpe0(s, val, s->gpe0_en);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("acpi: acpiGpe0StsWritel <- %#x\n", val));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic int acpiResetWriteU8(ACPIState *s, uint32_t addr, uint32_t val)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync int rc = VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("ACPI: acpiResetWriteU8: %x %x\n", addr, val));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (val == ACPI_RESET_REG_VAL)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync# ifndef IN_RING3
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = VINF_IOM_HC_IOPORT_WRITE;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync# else /* IN_RING3 */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = PDMDevHlpVMReset(s->pDevIns);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync# endif /* !IN_RING3 */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return rc;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/* SMI */
685409983863f02e8295369273d1844dca1f51c5vboxsyncstatic void acpiSmiWriteU8(ACPIState *s, uint32_t addr, uint32_t val)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("acpi: acpiSmiWriteU8 %#x\n", val));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (val == ACPI_ENABLE)
685409983863f02e8295369273d1844dca1f51c5vboxsync s->pm1a_ctl |= SCI_EN;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync else if (val == ACPI_DISABLE)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->pm1a_ctl &= ~SCI_EN;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync else
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("acpi: acpiSmiWriteU8 %#x <- unknown value\n", val));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic uint32_t find_rsdp_space(void)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return 0xe0000;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
685409983863f02e8295369273d1844dca1f51c5vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic int acpiPMTimerReset(ACPIState *s)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync uint64_t interval, freq;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync freq = TMTimerGetFreq(s->CTX_SUFF(ts));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync interval = ASMMultU64ByU32DivByU32(0xffffffff, freq, PM_TMR_FREQ);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("interval = %RU64\n", interval));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync TMTimerSet(s->CTX_SUFF(ts), TMTimerGet(s->CTX_SUFF(ts)) + interval);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic DECLCALLBACK(void) acpiTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState *s = (ACPIState *)pvUser;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync Log(("acpi: pm timer sts %#x (%d), en %#x (%d)\n",
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->pm1a_sts, (s->pm1a_sts & TMR_STS) != 0,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->pm1a_en, (s->pm1a_en & TMR_EN) != 0));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync update_pm1a(s, s->pm1a_sts | TMR_STS, s->pm1a_en);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPMTimerReset(s);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/**
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * _BST method.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic int acpiFetchBatteryStatus(ACPIState *s)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync uint32_t *p = s->au8BatteryInfo;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync bool fPresent; /* battery present? */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PDMACPIBATCAPACITY hostRemainingCapacity; /* 0..100 */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PDMACPIBATSTATE hostBatteryState; /* bitfield */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync uint32_t hostPresentRate; /* 0..1000 */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync int rc;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (!s->pDrv)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
685409983863f02e8295369273d1844dca1f51c5vboxsync rc = s->pDrv->pfnQueryBatteryStatus(s->pDrv, &fPresent, &hostRemainingCapacity,
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync &hostBatteryState, &hostPresentRate);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AssertRC(rc);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* default values */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_STATUS_STATE] = hostBatteryState;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_STATUS_PRESENT_RATE] = hostPresentRate == ~0U ? 0xFFFFFFFF
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync : hostPresentRate * 50; /* mW */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_STATUS_REMAINING_CAPACITY] = 50000; /* mWh */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_STATUS_PRESENT_VOLTAGE] = 10000; /* mV */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* did we get a valid battery state? */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (hostRemainingCapacity != PDM_ACPI_BAT_CAPACITY_UNKNOWN)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_STATUS_REMAINING_CAPACITY] = hostRemainingCapacity * 500; /* mWh */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (hostBatteryState == PDM_ACPI_BAT_STATE_CHARGED)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_STATUS_PRESENT_RATE] = 0; /* mV */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VINF_SUCCESS;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/**
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * _BIF method.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic int acpiFetchBatteryInfo(ACPIState *s)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync uint32_t *p = s->au8BatteryInfo;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_INFO_UNITS] = 0; /* mWh */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_INFO_DESIGN_CAPACITY] = 50000; /* mWh */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_INFO_LAST_FULL_CHARGE_CAPACITY] = 50000; /* mWh */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_INFO_TECHNOLOGY] = BAT_TECH_PRIMARY;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_INFO_DESIGN_VOLTAGE] = 10000; /* mV */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_INFO_DESIGN_CAPACITY_OF_WARNING] = 100; /* mWh */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_INFO_DESIGN_CAPACITY_OF_LOW] = 50; /* mWh */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_INFO_CAPACITY_GRANULARITY_1] = 1; /* mWh */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync p[BAT_INFO_CAPACITY_GRANULARITY_2] = 1; /* mWh */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VINF_SUCCESS;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/**
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * _STA method.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic uint32_t acpiGetBatteryDeviceStatus(ACPIState *s)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync bool fPresent; /* battery present? */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PDMACPIBATCAPACITY hostRemainingCapacity; /* 0..100 */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PDMACPIBATSTATE hostBatteryState; /* bitfield */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync uint32_t hostPresentRate; /* 0..1000 */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync int rc;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (!s->pDrv)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = s->pDrv->pfnQueryBatteryStatus(s->pDrv, &fPresent, &hostRemainingCapacity,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync &hostBatteryState, &hostPresentRate);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AssertRC(rc);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return fPresent
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ? STA_DEVICE_PRESENT_MASK /* present */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync | STA_DEVICE_ENABLED_MASK /* enabled and decodes its resources */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync | STA_DEVICE_SHOW_IN_UI_MASK /* should be shown in UI */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync | STA_DEVICE_FUNCTIONING_PROPERLY_MASK /* functioning properly */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync | STA_BATTERY_PRESENT_MASK /* battery is present */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync : 0; /* device not present */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic uint32_t acpiGetPowerSource(ACPIState *s)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync PDMACPIPOWERSOURCE ps;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* query the current power source from the host driver */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (!s->pDrv)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return AC_ONLINE;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync int rc = s->pDrv->pfnQueryPowerSource(s->pDrv, &ps);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync AssertRC(rc);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return ps == PDM_ACPI_POWER_SOURCE_BATTERY ? AC_OFFLINE : AC_ONLINE;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncPDMBOTHCBDECL(int) acpiBatIndexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState *s = (ACPIState *)pvUser;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync switch (cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case 4:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync u32 >>= s->u8IndexShift;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* see comment at the declaration of u8IndexShift */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (s->u8IndexShift == 0 && u32 == (BAT_DEVICE_STATUS << 2))
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->u8IndexShift = 2;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync u32 >>= 2;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Assert(u32 < BAT_INDEX_LAST);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->uBatteryIndex = u32;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync default:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
685409983863f02e8295369273d1844dca1f51c5vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncPDMBOTHCBDECL(int) acpiBatDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState *s = (ACPIState *)pvUser;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync switch (cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case 4:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync switch (s->uBatteryIndex)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case BAT_STATUS_STATE:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync acpiFetchBatteryStatus(s);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case BAT_STATUS_PRESENT_RATE:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case BAT_STATUS_REMAINING_CAPACITY:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case BAT_STATUS_PRESENT_VOLTAGE:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = s->au8BatteryInfo[s->uBatteryIndex];
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case BAT_INFO_UNITS:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync acpiFetchBatteryInfo(s);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case BAT_INFO_DESIGN_CAPACITY:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case BAT_INFO_LAST_FULL_CHARGE_CAPACITY:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case BAT_INFO_TECHNOLOGY:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case BAT_INFO_DESIGN_VOLTAGE:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case BAT_INFO_DESIGN_CAPACITY_OF_WARNING:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case BAT_INFO_DESIGN_CAPACITY_OF_LOW:
685409983863f02e8295369273d1844dca1f51c5vboxsync case BAT_INFO_CAPACITY_GRANULARITY_1:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case BAT_INFO_CAPACITY_GRANULARITY_2:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = s->au8BatteryInfo[s->uBatteryIndex];
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
685409983863f02e8295369273d1844dca1f51c5vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case BAT_DEVICE_STATUS:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = acpiGetBatteryDeviceStatus(s);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
685409983863f02e8295369273d1844dca1f51c5vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case BAT_POWER_SOURCE:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync *pu32 = acpiGetPowerSource(s);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync default:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync AssertMsgFailed(("Invalid battery index %d\n", s->uBatteryIndex));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync default:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VERR_IOM_IOPORT_UNUSED;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncPDMBOTHCBDECL(int) acpiSysInfoIndexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState *s = (ACPIState *)pvUser;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("system_index = %d, %d\n", u32, u32 >> 2));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync switch (cb)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case 4:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (u32 == SYSTEM_INFO_INDEX_VALID || u32 == SYSTEM_INFO_INDEX_INVALID)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->uSystemInfoIndex = u32;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync else
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* see comment at the declaration of u8IndexShift */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (s->u8IndexShift == 0)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (((u32 >> 2) < SYSTEM_INFO_INDEX_END) && ((u32 & 0x3)) == 0)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->u8IndexShift = 2;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync u32 >>= s->u8IndexShift;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Assert(u32 < SYSTEM_INFO_INDEX_END);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->uSystemInfoIndex = u32;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync default:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncPDMBOTHCBDECL(int) acpiSysInfoDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState *s = (ACPIState *)pvUser;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync switch (cb)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case 4:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync switch (s->uSystemInfoIndex)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_LOW_MEMORY_LENGTH:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = s->cbRamLow;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_HIGH_MEMORY_LENGTH:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = s->cbRamHigh >> 16; /* 64KB units */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Assert(((uint64_t)*pu32 << 16) == s->cbRamHigh);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_USE_IOAPIC:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = s->u8UseIOApic;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_HPET_STATUS:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = s->fUseHpet ? ( STA_DEVICE_PRESENT_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync | STA_DEVICE_ENABLED_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync | STA_DEVICE_SHOW_IN_UI_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync | STA_DEVICE_FUNCTIONING_PROPERLY_MASK)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync : 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_SMC_STATUS:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = s->fUseSmc ? ( STA_DEVICE_PRESENT_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync | STA_DEVICE_ENABLED_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* no need to show this device in the UI */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync | STA_DEVICE_FUNCTIONING_PROPERLY_MASK)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync : 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_FDC_STATUS:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = s->fUseFdc ? ( STA_DEVICE_PRESENT_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync | STA_DEVICE_ENABLED_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync | STA_DEVICE_SHOW_IN_UI_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync | STA_DEVICE_FUNCTIONING_PROPERLY_MASK)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync : 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_CPU0_STATUS:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_CPU1_STATUS:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_CPU2_STATUS:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_CPU3_STATUS:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = s->fShowCpu
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync && s->uSystemInfoIndex - SYSTEM_INFO_INDEX_CPU0_STATUS < s->cCpus
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync && VMCPUSET_IS_PRESENT(&s->CpuSetAttached, s->uSystemInfoIndex - SYSTEM_INFO_INDEX_CPU0_STATUS)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ?
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync STA_DEVICE_PRESENT_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync | STA_DEVICE_ENABLED_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync | STA_DEVICE_SHOW_IN_UI_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync | STA_DEVICE_FUNCTIONING_PROPERLY_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync : 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_RTC_STATUS:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = s->fShowRtc ? ( STA_DEVICE_PRESENT_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync | STA_DEVICE_ENABLED_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync | STA_DEVICE_SHOW_IN_UI_MASK
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync | STA_DEVICE_FUNCTIONING_PROPERLY_MASK)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync : 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_CPU_LOCKED:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (s->idCpuLockCheck < VMM_MAX_CPU_COUNT)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = VMCPUSET_IS_PRESENT(&s->CpuSetLocked, s->idCpuLockCheck);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->idCpuLockCheck = UINT32_C(0xffffffff); /* Make the entry invalid */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync else
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync AssertMsgFailed(("ACPI: CPU lock check protocol violation\n"));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* Always return locked status just to be safe */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = 1;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* Solaris 9 tries to read from this index */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_INVALID:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync default:
685409983863f02e8295369273d1844dca1f51c5vboxsync AssertMsgFailed(("Invalid system info index %d\n", s->uSystemInfoIndex));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
685409983863f02e8295369273d1844dca1f51c5vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync default:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VERR_IOM_IOPORT_UNUSED;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
685409983863f02e8295369273d1844dca1f51c5vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("index %d val %d\n", s->uSystemInfoIndex, *pu32));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncPDMBOTHCBDECL(int) acpiSysInfoDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
685409983863f02e8295369273d1844dca1f51c5vboxsync ACPIState *s = (ACPIState *)pvUser;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("addr=%#x cb=%d u32=%#x si=%#x\n", Port, cb, u32, s->uSystemInfoIndex));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
685409983863f02e8295369273d1844dca1f51c5vboxsync if (cb == 4)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync switch (s->uSystemInfoIndex)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
685409983863f02e8295369273d1844dca1f51c5vboxsync case SYSTEM_INFO_INDEX_INVALID:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync AssertMsg(u32 == 0xbadc0de, ("u32=%u\n", u32));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->u8IndexShift = 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
685409983863f02e8295369273d1844dca1f51c5vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_VALID:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync AssertMsg(u32 == 0xbadc0de, ("u32=%u\n", u32));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->u8IndexShift = 2;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_CPU_LOCK_CHECK:
685409983863f02e8295369273d1844dca1f51c5vboxsync if (u32 < s->cCpus)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->idCpuLockCheck = u32;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync else
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync LogRel(("ACPI: CPU %u does not exist\n", u32));
685409983863f02e8295369273d1844dca1f51c5vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case SYSTEM_INFO_INDEX_CPU_LOCKED:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (u32 < s->cCpus)
685409983863f02e8295369273d1844dca1f51c5vboxsync VMCPUSET_DEL(&s->CpuSetLocked, u32); /* Unlock the CPU */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync else
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync LogRel(("ACPI: CPU %u does not exist\n", u32));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
685409983863f02e8295369273d1844dca1f51c5vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync default:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x system_index=%#x\n",
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Port, cb, u32, s->uSystemInfoIndex));
685409983863f02e8295369273d1844dca1f51c5vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync else
685409983863f02e8295369273d1844dca1f51c5vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/** @todo Don't call functions, but do the job in the read/write handlers
685409983863f02e8295369273d1844dca1f51c5vboxsync * here! */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/* IO Helpers */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncPDMBOTHCBDECL(int) acpiPm1aEnRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
685409983863f02e8295369273d1844dca1f51c5vboxsync switch (cb)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case 2:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = acpiPm1aEnReadw((ACPIState*)pvUser, Port);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync default:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VERR_IOM_IOPORT_UNUSED;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncPDMBOTHCBDECL(int) acpiPm1aStsRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync switch (cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case 2:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = acpiPm1aStsReadw((ACPIState*)pvUser, Port);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync default:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VERR_IOM_IOPORT_UNUSED;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncPDMBOTHCBDECL(int) acpiPm1aCtlRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync switch (cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case 2:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = acpiPm1aCtlReadw((ACPIState*)pvUser, Port);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync default:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VERR_IOM_IOPORT_UNUSED;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VINF_SUCCESS;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncPDMBOTHCBDECL(int) acpiPM1aEnWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync switch (cb)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case 2:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPM1aEnWritew((ACPIState*)pvUser, Port, u32);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync default:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncPDMBOTHCBDECL(int) acpiPM1aStsWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync switch (cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync case 2:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync acpiPM1aStsWritew((ACPIState*)pvUser, Port, u32);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync default:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncPDMBOTHCBDECL(int) acpiPM1aCtlWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync switch (cb)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case 2:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return acpiPM1aCtlWritew((ACPIState*)pvUser, Port, u32);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync default:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync#endif /* IN_RING3 */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/**
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * PMTMR readable from host/guest.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncPDMBOTHCBDECL(int) acpiPMTmrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (cb == 4)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync int64_t now = TMTimerGet(s->CTX_SUFF(ts));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync int64_t elapsed = now - s->pm_timer_initial;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *pu32 = ASMMultU64ByU32DivByU32(elapsed, PM_TMR_FREQ, TMTimerGetFreq(s->CTX_SUFF(ts)));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync Log(("acpi: acpiPMTmrRead -> %#x\n", *pu32));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VERR_IOM_IOPORT_UNUSED;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync#ifdef IN_RING3
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncPDMBOTHCBDECL(int) acpiGpe0StsRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync switch (cb)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case 1:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync *pu32 = acpiGpe0StsReadb((ACPIState*)pvUser, Port);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync default:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VERR_IOM_IOPORT_UNUSED;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncPDMBOTHCBDECL(int) acpiGpe0EnRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync{
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync switch (cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case 1:
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync *pu32 = acpiGpe0EnReadb((ACPIState*)pvUser, Port);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync default:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VERR_IOM_IOPORT_UNUSED;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync return VINF_SUCCESS;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncPDMBOTHCBDECL(int) acpiGpe0StsWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync switch (cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync case 1:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiGpe0StsWriteb((ACPIState*)pvUser, Port, u32);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync default:
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync return VINF_SUCCESS;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncPDMBOTHCBDECL(int) acpiGpe0EnWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync{
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync switch (cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case 1:
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync acpiGpe0EnWriteb((ACPIState*)pvUser, Port, u32);
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync default:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync break;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VINF_SUCCESS;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsyncPDMBOTHCBDECL(int) acpiSmiWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync switch (cb)
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case 1:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiSmiWriteU8((ACPIState*)pvUser, Port, u32);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync break;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync default:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync return VINF_SUCCESS;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncPDMBOTHCBDECL(int) acpiResetWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync switch (cb)
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case 1:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return acpiResetWriteU8((ACPIState*)pvUser, Port, u32);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync default:
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VINF_SUCCESS;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync#ifdef DEBUG_ACPI
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncPDMBOTHCBDECL(int) acpiDhexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync{
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync switch (cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case 1:
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync Log(("%#x\n", u32 & 0xff));
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case 2:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync Log(("%#6x\n", u32 & 0xffff));
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync case 4:
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync Log(("%#10x\n", u32));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync default:
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncPDMBOTHCBDECL(int) acpiDchrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync switch (cb)
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case 1:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync Log(("%c", u32 & 0xff));
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync break;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync default:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync break;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VINF_SUCCESS;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync#endif /* DEBUG_ACPI */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic int acpiRegisterPmHandlers(ACPIState* pThis)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync int rc = VINF_SUCCESS;
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync#define R(offset, cnt, writer, reader, description) \
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync do { \
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync rc = PDMDevHlpIOPortRegister(pThis->pDevIns, acpiPmPort(pThis, offset), cnt, pThis, writer, reader, \
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync NULL, NULL, description); \
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc)) \
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return rc; \
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync } while (0)
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync#define L (GPE0_BLK_LEN / 2)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync R(PM1a_EVT_OFFSET+2, 1, acpiPM1aEnWrite, acpiPm1aEnRead, "ACPI PM1a Enable");
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync R(PM1a_EVT_OFFSET, 1, acpiPM1aStsWrite, acpiPm1aStsRead, "ACPI PM1a Status");
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync R(PM1a_CTL_OFFSET, 1, acpiPM1aCtlWrite, acpiPm1aCtlRead, "ACPI PM1a Control");
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync R(PM_TMR_OFFSET, 1, NULL, acpiPMTmrRead, "ACPI PM Timer");
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync R(GPE0_OFFSET + L, L, acpiGpe0EnWrite, acpiGpe0EnRead, "ACPI GPE0 Enable");
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync R(GPE0_OFFSET, L, acpiGpe0StsWrite, acpiGpe0StsRead, "ACPI GPE0 Status");
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync#undef L
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync#undef R
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync /* register RC stuff */
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync if (pThis->fGCEnabled)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = PDMDevHlpIOPortRegisterRC(pThis->pDevIns, acpiPmPort(pThis, PM_TMR_OFFSET),
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync 1, 0, NULL, "acpiPMTmrRead",
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync NULL, NULL, "ACPI PM Timer");
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AssertRCReturn(rc, rc);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync /* register R0 stuff */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (pThis->fR0Enabled)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync rc = PDMDevHlpIOPortRegisterR0(pThis->pDevIns, acpiPmPort(pThis, PM_TMR_OFFSET),
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync 1, 0, NULL, "acpiPMTmrRead",
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync NULL, NULL, "ACPI PM Timer");
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AssertRCReturn(rc, rc);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync
f36e34993b3bddde17e7a88121dc26d3ec197ee0vboxsync return rc;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic int acpiUnregisterPmHandlers(ACPIState *pThis)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync#define U(offset, cnt) \
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync do { \
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync int rc = PDMDevHlpIOPortDeregister(pThis->pDevIns, acpiPmPort(pThis, offset), cnt); \
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync AssertRCReturn(rc, rc); \
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync } while (0)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync#define L (GPE0_BLK_LEN / 2)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync U(PM1a_EVT_OFFSET+2, 1);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync U(PM1a_EVT_OFFSET, 1);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync U(PM1a_CTL_OFFSET, 1);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync U(PM_TMR_OFFSET, 1);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync U(GPE0_OFFSET + L, L);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync U(GPE0_OFFSET, L);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync#undef L
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync#undef U
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/**
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * Saved state structure description, version 4.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic const SSMFIELD g_AcpiSavedStateFields4[] =
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync SSMFIELD_ENTRY(ACPIState, pm1a_en),
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync SSMFIELD_ENTRY(ACPIState, pm1a_sts),
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync SSMFIELD_ENTRY(ACPIState, pm1a_ctl),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync SSMFIELD_ENTRY(ACPIState, pm_timer_initial),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync SSMFIELD_ENTRY(ACPIState, gpe0_en),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync SSMFIELD_ENTRY(ACPIState, gpe0_sts),
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync SSMFIELD_ENTRY(ACPIState, uBatteryIndex),
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync SSMFIELD_ENTRY(ACPIState, u64RamSize),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync SSMFIELD_ENTRY(ACPIState, u8IndexShift),
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync SSMFIELD_ENTRY(ACPIState, u8UseIOApic),
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync SSMFIELD_ENTRY(ACPIState, uSleepState),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync SSMFIELD_ENTRY_TERM()
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync};
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/**
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * Saved state structure description, version 5.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic const SSMFIELD g_AcpiSavedStateFields5[] =
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync SSMFIELD_ENTRY(ACPIState, pm1a_en),
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync SSMFIELD_ENTRY(ACPIState, pm1a_sts),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync SSMFIELD_ENTRY(ACPIState, pm1a_ctl),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync SSMFIELD_ENTRY(ACPIState, pm_timer_initial),
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync SSMFIELD_ENTRY(ACPIState, gpe0_en),
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync SSMFIELD_ENTRY(ACPIState, gpe0_sts),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync SSMFIELD_ENTRY(ACPIState, uBatteryIndex),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync SSMFIELD_ENTRY(ACPIState, uSystemInfoIndex),
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync SSMFIELD_ENTRY(ACPIState, uSleepState),
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync SSMFIELD_ENTRY(ACPIState, u8IndexShift),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync SSMFIELD_ENTRY(ACPIState, uPmIoPortBase),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync SSMFIELD_ENTRY_TERM()
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync};
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic DECLCALLBACK(int) acpi_save_state(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return SSMR3PutStruct(pSSMHandle, s, &g_AcpiSavedStateFields5[0]);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic DECLCALLBACK(int) acpi_load_state(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle,
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync uint32_t uVersion, uint32_t uPass)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /*
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * Unregister PM handlers, will register with actual base
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * after state successfully loaded.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync int rc = acpiUnregisterPmHandlers(s);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return rc;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync switch (uVersion)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case 4:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = SSMR3GetStruct(pSSMHandle, s, &g_AcpiSavedStateFields4[0]);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /** @todo Provide saner defaults for fields not found in saved state. */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync case 5:
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = SSMR3GetStruct(pSSMHandle, s, &g_AcpiSavedStateFields5[0]);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync break;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync default:
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (RT_SUCCESS(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = acpiRegisterPmHandlers(s);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (RT_FAILURE(rc))
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return rc;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = acpiFetchBatteryStatus(s);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return rc;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = acpiFetchBatteryInfo(s);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return rc;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = acpiPMTimerReset(s);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return rc;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return rc;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/**
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic DECLCALLBACK(void *) acpiQueryInterface(PPDMIBASE pInterface, const char *pszIID)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState *pThis = RT_FROM_MEMBER(pInterface, ACPIState, IBase);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIACPIPORT, &pThis->IACPIPort);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return NULL;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/**
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * Create the ACPI tables.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic int acpiPlantTables(ACPIState *s)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync int rc;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync RTGCPHYS32 GCPhysCur, GCPhysRsdt, GCPhysXsdt, GCPhysFadtAcpi1, GCPhysFadtAcpi2, GCPhysFacs, GCPhysDsdt;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync RTGCPHYS32 GCPhysHpet = 0, GCPhysApic = 0, GCPhysSsdt = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync uint32_t addend = 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync RTGCPHYS32 aGCPhysRsdt[4];
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync RTGCPHYS32 aGCPhysXsdt[4];
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync uint32_t cAddr, iMadt = 0, iHpet = 0, iSsdt = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync size_t cbRsdt = sizeof(ACPITBLHEADER);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync size_t cbXsdt = sizeof(ACPITBLHEADER);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync cAddr = 1; /* FADT */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (s->u8UseIOApic)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync iMadt = cAddr++; /* MADT */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (s->fUseHpet)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync iHpet = cAddr++; /* HPET */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync iSsdt = cAddr++; /* SSDT */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync cbRsdt += cAddr*sizeof(uint32_t); /* each entry: 32 bits phys. address. */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync cbXsdt += cAddr*sizeof(uint64_t); /* each entry: 64 bits phys. address. */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = CFGMR3QueryU64(s->pDevIns->pCfg, "RamSize", &s->u64RamSize);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return PDMDEV_SET_ERROR(s->pDevIns, rc,
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync N_("Configuration error: Querying \"RamSize\" as integer failed"));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync uint32_t cbRamHole;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = CFGMR3QueryU32Def(s->pDevIns->pCfg, "RamHoleSize", &cbRamHole, MM_RAM_HOLE_SIZE_DEFAULT);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return PDMDEV_SET_ERROR(s->pDevIns, rc,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync N_("Configuration error: Querying \"RamHoleSize\" as integer failed"));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /*
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * Calculate the sizes for the high and low regions.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync const uint64_t offRamHole = _4G - cbRamHole;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->cbRamHigh = offRamHole < s->u64RamSize ? s->u64RamSize - offRamHole : 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync uint64_t cbRamLow = offRamHole < s->u64RamSize ? offRamHole : s->u64RamSize;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (cbRamLow > UINT32_C(0xffe00000)) /* See MEM3. */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* Note: This is also enforced by DevPcBios.cpp. */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync LogRel(("DevACPI: Clipping cbRamLow=%#RX64 down to 0xffe00000.\n", cbRamLow));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync cbRamLow = UINT32_C(0xffe00000);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->cbRamLow = (uint32_t)cbRamLow;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync GCPhysCur = 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync GCPhysRsdt = GCPhysCur;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync GCPhysCur = RT_ALIGN_32(GCPhysCur + cbRsdt, 16);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync GCPhysXsdt = GCPhysCur;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync GCPhysCur = RT_ALIGN_32(GCPhysCur + cbXsdt, 16);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync GCPhysFadtAcpi1 = GCPhysCur;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync GCPhysCur = RT_ALIGN_32(GCPhysCur + ACPITBLFADT_VERSION1_SIZE, 16);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync GCPhysFadtAcpi2 = GCPhysCur;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync GCPhysCur = RT_ALIGN_32(GCPhysCur + sizeof(ACPITBLFADT), 64);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync GCPhysFacs = GCPhysCur;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync GCPhysCur = RT_ALIGN_32(GCPhysCur + sizeof(ACPITBLFACS), 16);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (s->u8UseIOApic)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync GCPhysApic = GCPhysCur;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync GCPhysCur = RT_ALIGN_32(GCPhysCur + AcpiTableMADT::sizeFor(s), 16);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (s->fUseHpet)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync GCPhysHpet = GCPhysCur;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync GCPhysCur = RT_ALIGN_32(GCPhysCur + sizeof(ACPITBLHPET), 16);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync void* pSsdtCode = NULL;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync size_t cbSsdtSize = 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = acpiPrepareSsdt(s->pDevIns, &pSsdtCode, &cbSsdtSize);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return rc;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync GCPhysSsdt = GCPhysCur;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync GCPhysCur = RT_ALIGN_32(GCPhysCur + cbSsdtSize, 16);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync GCPhysDsdt = GCPhysCur;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync void* pDsdtCode = NULL;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync size_t cbDsdtSize = 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = acpiPrepareDsdt(s->pDevIns, &pDsdtCode, &cbDsdtSize);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return rc;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync GCPhysCur = RT_ALIGN_32(GCPhysCur + cbDsdtSize, 16);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (GCPhysCur > 0x10000)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return PDMDEV_SET_ERROR(s->pDevIns, VERR_TOO_MUCH_DATA,
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync N_("Error: ACPI tables bigger than 64KB"));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync Log(("RSDP 0x%08X\n", find_rsdp_space()));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync addend = s->cbRamLow - 0x10000;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("RSDT 0x%08X XSDT 0x%08X\n", GCPhysRsdt + addend, GCPhysXsdt + addend));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("FACS 0x%08X FADT (1.0) 0x%08X, FADT (2+) 0x%08X\n", GCPhysFacs + addend, GCPhysFadtAcpi1 + addend, GCPhysFadtAcpi2 + addend));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync Log(("DSDT 0x%08X", GCPhysDsdt + addend));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (s->u8UseIOApic)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log((" MADT 0x%08X", GCPhysApic + addend));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (s->fUseHpet)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync Log((" HPET 0x%08X", GCPhysHpet + addend));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync Log((" SSDT 0x%08X", GCPhysSsdt + addend));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("\n"));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiSetupRSDP((ACPITBLRSDP*)s->au8RSDPPage, GCPhysRsdt + addend, GCPhysXsdt + addend);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiSetupDSDT(s, GCPhysDsdt + addend, pDsdtCode, cbDsdtSize);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync acpiCleanupDsdt(s->pDevIns, pDsdtCode);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync acpiSetupFACS(s, GCPhysFacs + addend);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiSetupFADT(s, GCPhysFadtAcpi1 + addend, GCPhysFadtAcpi2 + addend, GCPhysFacs + addend, GCPhysDsdt + addend);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync aGCPhysRsdt[0] = GCPhysFadtAcpi1 + addend;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync aGCPhysXsdt[0] = GCPhysFadtAcpi2 + addend;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (s->u8UseIOApic)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync acpiSetupMADT(s, GCPhysApic + addend);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync aGCPhysRsdt[iMadt] = GCPhysApic + addend;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync aGCPhysXsdt[iMadt] = GCPhysApic + addend;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (s->fUseHpet)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiSetupHPET(s, GCPhysHpet + addend);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync aGCPhysRsdt[iHpet] = GCPhysHpet + addend;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync aGCPhysXsdt[iHpet] = GCPhysHpet + addend;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiSetupSSDT(s, GCPhysSsdt + addend, pSsdtCode, cbSsdtSize);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync acpiCleanupSsdt(s->pDevIns, pSsdtCode);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync aGCPhysRsdt[iSsdt] = GCPhysSsdt + addend;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync aGCPhysXsdt[iSsdt] = GCPhysSsdt + addend;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = acpiSetupRSDT(s, GCPhysRsdt + addend, cAddr, aGCPhysRsdt);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return rc;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return acpiSetupXSDT(s, GCPhysXsdt + addend, cAddr, aGCPhysXsdt);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic int acpiUpdatePmHandlers(ACPIState *pThis, RTIOPORT uNewBase)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log(("acpi: rebasing PM 0x%x -> 0x%x\n", pThis->uPmIoPortBase, uNewBase));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (uNewBase != pThis->uPmIoPortBase)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync int rc;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = acpiUnregisterPmHandlers(pThis);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return rc;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync pThis->uPmIoPortBase = uNewBase;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = acpiRegisterPmHandlers(pThis);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return rc;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* We have to update FADT table acccording to the new base */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = acpiPlantTables(pThis);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AssertRC(rc);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return rc;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic uint32_t acpiPciConfigRead(PPCIDEVICE pPciDev, uint32_t Address, unsigned cb)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync PPDMDEVINS pDevIns = pPciDev->pDevIns;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState* pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync Log2(("acpi: PCI config read: 0x%x (%d)\n", Address, cb));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return pThis->pfnAcpiPciConfigRead(pPciDev, Address, cb);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic void acpiPciConfigWrite(PPCIDEVICE pPciDev, uint32_t Address, uint32_t u32Value, unsigned cb)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PPDMDEVINS pDevIns = pPciDev->pDevIns;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync Log2(("acpi: PCI config write: 0x%x -> 0x%x (%d)\n", u32Value, Address, cb));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync pThis->pfnAcpiPciConfigWrite(pPciDev, Address, u32Value, cb);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* PMREGMISC written */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (Address == 0x80)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* Check Power Management IO Space Enable (PMIOSE) bit */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (pPciDev->config[0x80] & 0x1)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync int rc;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync RTIOPORT uNewBase =
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync RTIOPORT(RT_LE2H_U32(*(uint32_t*)&pPciDev->config[0x40]));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync uNewBase &= 0xffc0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = acpiUpdatePmHandlers(pThis, uNewBase);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AssertRC(rc);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/**
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * Attach a new CPU.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync *
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * @returns VBox status code.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * @param pDevIns The device instance.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * @param iLUN The logical unit which is being attached.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync *
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * @remarks This code path is not used during construction.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic DECLCALLBACK(int) acpiAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync LogFlow(("acpiAttach: pDevIns=%p iLUN=%u fFlags=%#x\n", pDevIns, iLUN, fFlags));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync AssertMsgReturn(!(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ("Hot-plug flag is not set\n"),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync VERR_NOT_SUPPORTED);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AssertReturn(iLUN < VMM_MAX_CPU_COUNT, VERR_PDM_NO_SUCH_LUN);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* Check if it was already attached */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (VMCPUSET_IS_PRESENT(&s->CpuSetAttached, iLUN))
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return VINF_SUCCESS;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PPDMIBASE IBaseTmp;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync int rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &s->IBase, &IBaseTmp, "ACPI CPU");
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (RT_SUCCESS(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* Enable the CPU */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync VMCPUSET_ADD(&s->CpuSetAttached, iLUN);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /*
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * Lock the CPU because we don't know if the guest will use it or not.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * Prevents ejection while the CPU is still used
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync VMCPUSET_ADD(&s->CpuSetLocked, iLUN);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* Notify the guest */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync update_gpe0(s, s->gpe0_sts | 0x2, s->gpe0_en);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return rc;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync/**
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * Detach notification.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync *
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * @param pDevIns The device instance.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * @param iLUN The logical unit which is being detached.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic DECLCALLBACK(void) acpiDetach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync LogFlow(("acpiDetach: pDevIns=%p iLUN=%u fFlags=%#x\n", pDevIns, iLUN, fFlags));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AssertMsgReturnVoid(!(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ("Hot-plug flag is not set\n"));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* Check if it was already detached */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (VMCPUSET_IS_PRESENT(&s->CpuSetAttached, iLUN))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AssertMsgReturnVoid(!(VMCPUSET_IS_PRESENT(&s->CpuSetLocked, iLUN)), ("CPU is still locked by the guest\n"));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* Disable the CPU */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync VMCPUSET_DEL(&s->CpuSetAttached, iLUN);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* Notify the guest */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync update_gpe0(s, s->gpe0_sts | 0x2, s->gpe0_en);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync }
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic DECLCALLBACK(void) acpiReset(PPDMDEVINS pDevIns)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->pm1a_en = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->pm1a_sts = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->pm1a_ctl = 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->pm_timer_initial = TMTimerGet(s->CTX_SUFF(ts));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync acpiPMTimerReset(s);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->uBatteryIndex = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->uSystemInfoIndex = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->gpe0_en = 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->gpe0_sts = 0;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->uSleepState = 0;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /** @todo Should we really reset PM base? */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiUpdatePmHandlers(s, PM_PORT_BASE);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync acpiPlantTables(s);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/**
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * Relocates the GC pointer members.
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsyncstatic DECLCALLBACK(void) acpiRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->tsRC = TMTimerRCPtr(s->CTX_SUFF(ts));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync}
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync/**
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * @interface_method_impl{PDMDEVREG,pfnConstruct}
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsyncstatic DECLCALLBACK(int) acpiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PCIDevice *dev = &s->dev;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* Validate and read the configuration. */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (!CFGMR3AreValuesValid(pCfg,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync "RamSize\0"
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync "RamHoleSize\0"
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync "IOAPIC\0"
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync "NumCPUs\0"
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync "GCEnabled\0"
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync "R0Enabled\0"
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync "HpetEnabled\0"
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync "SmcEnabled\0"
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync "FdcEnabled\0"
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync "ShowRtc\0"
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync "ShowCpu\0"
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync "CpuHotPlug\0"
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync "AmlFilePath\0"
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync ))
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync N_("Configuration error: Invalid config key for ACPI device"));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->pDevIns = pDevIns;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* query whether we are supposed to present an IOAPIC */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync int rc = CFGMR3QueryU8Def(pCfg, "IOAPIC", &s->u8UseIOApic, 1);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync N_("Configuration error: Failed to read \"IOAPIC\""));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = CFGMR3QueryU16Def(pCfg, "NumCPUs", &s->cCpus, 1);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync N_("Configuration error: Querying \"NumCPUs\" as integer failed"));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* query whether we are supposed to present an FDC controller */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = CFGMR3QueryBoolDef(pCfg, "FdcEnabled", &s->fUseFdc, true);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (RT_FAILURE(rc))
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync N_("Configuration error: Failed to read \"FdcEnabled\""));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* query whether we are supposed to present HPET */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = CFGMR3QueryBoolDef(pCfg, "HpetEnabled", &s->fUseHpet, false);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync N_("Configuration error: Failed to read \"HpetEnabled\""));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* query whether we are supposed to present SMC */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = CFGMR3QueryBoolDef(pCfg, "SmcEnabled", &s->fUseSmc, false);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync N_("Configuration error: Failed to read \"SmcEnabled\""));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* query whether we are supposed to present RTC object */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = CFGMR3QueryBoolDef(pCfg, "ShowRtc", &s->fShowRtc, false);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync N_("Configuration error: Failed to read \"ShowRtc\""));
126f438e830df99e1ed3be89970412b0e94c371evboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* query whether we are supposed to present CPU objects */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = CFGMR3QueryBoolDef(pCfg, "ShowCpu", &s->fShowCpu, false);
126f438e830df99e1ed3be89970412b0e94c371evboxsync if (RT_FAILURE(rc))
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync N_("Configuration error: Failed to read \"ShowCpu\""));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* query whether we are allow CPU hot plugging */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = CFGMR3QueryBoolDef(pCfg, "CpuHotPlug", &s->fCpuHotPlug, false);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync N_("Configuration error: Failed to read \"CpuHotPlug\""));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = CFGMR3QueryBool(pCfg, "GCEnabled", &s->fGCEnabled);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (rc == VERR_CFGM_VALUE_NOT_FOUND)
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->fGCEnabled = true;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync else if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync N_("Configuration error: Failed to read \"GCEnabled\""));
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = CFGMR3QueryBool(pCfg, "R0Enabled", &s->fR0Enabled);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (rc == VERR_CFGM_VALUE_NOT_FOUND)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->fR0Enabled = true;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync else if (RT_FAILURE(rc))
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync return PDMDEV_SET_ERROR(pDevIns, rc,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync N_("configuration error: failed to read R0Enabled as boolean"));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /*
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync * Interfaces
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* IBase */
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->IBase.pfnQueryInterface = acpiQueryInterface;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /* IACPIPort */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->IACPIPort.pfnSleepButtonPress = acpiSleepButtonPress;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->IACPIPort.pfnPowerButtonPress = acpiPowerButtonPress;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync s->IACPIPort.pfnGetPowerButtonHandled = acpiGetPowerButtonHandled;
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync s->IACPIPort.pfnGetGuestEnteredACPIMode = acpiGetGuestEnteredACPIMode;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->IACPIPort.pfnGetCpuStatus = acpiGetCpuStatus;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync VMCPUSET_EMPTY(&s->CpuSetAttached);
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync VMCPUSET_EMPTY(&s->CpuSetLocked);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->idCpuLockCheck = UINT32_C(0xffffffff);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* The first CPU can't be attached/detached */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync VMCPUSET_ADD(&s->CpuSetAttached, 0);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync VMCPUSET_ADD(&s->CpuSetLocked, 0);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* Try to attach the other CPUs */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync for (unsigned i = 1; i < s->cCpus; i++)
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (s->fCpuHotPlug)
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PPDMIBASE IBaseTmp;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = PDMDevHlpDriverAttach(pDevIns, i, &s->IBase, &IBaseTmp, "ACPI CPU");
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync if (RT_SUCCESS(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync VMCPUSET_ADD(&s->CpuSetAttached, i);
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync VMCPUSET_ADD(&s->CpuSetLocked, i);
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync Log(("acpi: Attached CPU %u\n", i));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync Log(("acpi: CPU %u not attached yet\n", i));
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync else
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach CPU object\n"));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync else
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* CPU is always attached if hot-plug is not enabled. */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync VMCPUSET_ADD(&s->CpuSetAttached, i);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync VMCPUSET_ADD(&s->CpuSetLocked, i);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* Set default port base */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync s->uPmIoPortBase = PM_PORT_BASE;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
ec9aa1180070b037866f064ce720254cd9f03721vboxsync /*
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * FDC and SMC try to use the same non-shareable interrupt (6),
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * enable only one device.
ec9aa1180070b037866f064ce720254cd9f03721vboxsync */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync if (s->fUseSmc)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->fUseFdc = false;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
ec9aa1180070b037866f064ce720254cd9f03721vboxsync /* */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync RTGCPHYS32 GCPhysRsdp = find_rsdp_space();
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (!GCPhysRsdp)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY,
ec9aa1180070b037866f064ce720254cd9f03721vboxsync N_("Can not find space for RSDP. ACPI is disabled"));
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = acpiPlantTables(s);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
ec9aa1180070b037866f064ce720254cd9f03721vboxsync return rc;
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = PDMDevHlpROMRegister(pDevIns, GCPhysRsdp, 0x1000, s->au8RSDPPage,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PGMPHYS_ROM_FLAGS_PERMANENT_BINARY, "ACPI RSDP");
ec9aa1180070b037866f064ce720254cd9f03721vboxsync if (RT_FAILURE(rc))
ec9aa1180070b037866f064ce720254cd9f03721vboxsync return rc;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = acpiRegisterPmHandlers(s);
ec9aa1180070b037866f064ce720254cd9f03721vboxsync if (RT_FAILURE(rc))
ec9aa1180070b037866f064ce720254cd9f03721vboxsync return rc;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync#define R(addr, cnt, writer, reader, description) \
ec9aa1180070b037866f064ce720254cd9f03721vboxsync do { \
ec9aa1180070b037866f064ce720254cd9f03721vboxsync rc = PDMDevHlpIOPortRegister(pDevIns, addr, cnt, s, writer, reader, \
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync NULL, NULL, description); \
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc)) \
ec9aa1180070b037866f064ce720254cd9f03721vboxsync return rc; \
ec9aa1180070b037866f064ce720254cd9f03721vboxsync } while (0)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync R(SMI_CMD, 1, acpiSmiWrite, NULL, "ACPI SMI");
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync#ifdef DEBUG_ACPI
ec9aa1180070b037866f064ce720254cd9f03721vboxsync R(DEBUG_HEX, 1, acpiDhexWrite, NULL, "ACPI Debug hex");
ec9aa1180070b037866f064ce720254cd9f03721vboxsync R(DEBUG_CHR, 1, acpiDchrWrite, NULL, "ACPI Debug char");
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync#endif
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync R(BAT_INDEX, 1, acpiBatIndexWrite, NULL, "ACPI Battery status index");
ec9aa1180070b037866f064ce720254cd9f03721vboxsync R(BAT_DATA, 1, NULL, acpiBatDataRead, "ACPI Battery status data");
ec9aa1180070b037866f064ce720254cd9f03721vboxsync R(SYSI_INDEX, 1, acpiSysInfoIndexWrite, NULL, "ACPI system info index");
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync R(SYSI_DATA, 1, acpiSysInfoDataWrite, acpiSysInfoDataRead, "ACPI system info data");
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync R(ACPI_RESET_BLK, 1, acpiResetWrite, NULL, "ACPI Reset");
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#undef R
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, acpiTimer, dev,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "ACPI Timer", &s->tsR3);
ec9aa1180070b037866f064ce720254cd9f03721vboxsync if (RT_FAILURE(rc))
ec9aa1180070b037866f064ce720254cd9f03721vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync AssertMsgFailed(("pfnTMTimerCreate -> %Rrc\n", rc));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return rc;
ec9aa1180070b037866f064ce720254cd9f03721vboxsync }
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->tsR0 = TMTimerR0Ptr(s->tsR3);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->tsRC = TMTimerRCPtr(s->tsR3);
ec9aa1180070b037866f064ce720254cd9f03721vboxsync s->pm_timer_initial = TMTimerGet(s->tsR3);
ec9aa1180070b037866f064ce720254cd9f03721vboxsync acpiPMTimerReset(s);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PCIDevSetVendorId(dev, 0x8086); /* Intel */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync PCIDevSetDeviceId(dev, 0x7113); /* 82371AB */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* See p. 50 of PIIX4 manual */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync dev->config[0x04] = 0x01; /* command */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync dev->config[0x05] = 0x00;
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync dev->config[0x06] = 0x80; /* status */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync dev->config[0x07] = 0x02;
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
ec9aa1180070b037866f064ce720254cd9f03721vboxsync dev->config[0x08] = 0x08; /* revision number */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync dev->config[0x09] = 0x00; /* class code */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync dev->config[0x0a] = 0x80;
ec9aa1180070b037866f064ce720254cd9f03721vboxsync dev->config[0x0b] = 0x06;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync dev->config[0x0e] = 0x80; /* header type */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
ec9aa1180070b037866f064ce720254cd9f03721vboxsync dev->config[0x0f] = 0x00; /* reserved */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync dev->config[0x3c] = SCI_INT; /* interrupt line */
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
ec9aa1180070b037866f064ce720254cd9f03721vboxsync#if 0
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync dev->config[0x3d] = 0x01; /* interrupt pin */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync#endif
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
ec9aa1180070b037866f064ce720254cd9f03721vboxsync dev->config[0x40] = 0x01; /* PM base address, this bit marks it as IO range, not PA */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync#if 0
ec9aa1180070b037866f064ce720254cd9f03721vboxsync int smb_io_base = 0xb100;
ec9aa1180070b037866f064ce720254cd9f03721vboxsync dev->config[0x90] = smb_io_base | 1; /* SMBus base address */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync dev->config[0x90] = smb_io_base >> 8;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync#endif
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
ec9aa1180070b037866f064ce720254cd9f03721vboxsync rc = PDMDevHlpPCIRegister(pDevIns, dev);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return rc;
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
ec9aa1180070b037866f064ce720254cd9f03721vboxsync PDMDevHlpPCISetConfigCallbacks(pDevIns, dev,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPciConfigRead, &s->pfnAcpiPciConfigRead,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiPciConfigWrite, &s->pfnAcpiPciConfigWrite);
ec9aa1180070b037866f064ce720254cd9f03721vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync rc = PDMDevHlpSSMRegister(pDevIns, 5, sizeof(*s), acpi_save_state, acpi_load_state);
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync if (RT_FAILURE(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return rc;
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync /*
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * Get the corresponding connector interface
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync */
126f438e830df99e1ed3be89970412b0e94c371evboxsync rc = PDMDevHlpDriverAttach(pDevIns, 0, &s->IBase, &s->pDrvBase, "ACPI Driver Port");
126f438e830df99e1ed3be89970412b0e94c371evboxsync if (RT_SUCCESS(rc))
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync s->pDrv = PDMIBASE_QUERY_INTERFACE(s->pDrvBase, PDMIACPICONNECTOR);
c07a12f4bcb3336334f7b439375deae8dbd2bf83vboxsync if (!s->pDrv)
ec9aa1180070b037866f064ce720254cd9f03721vboxsync return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_MISSING_INTERFACE,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync N_("LUN #0 doesn't have an ACPI connector interface"));
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync {
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync Log(("acpi: %s/%d: warning: no driver attached to LUN #0!\n",
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync pDevIns->pReg->szName, pDevIns->iInstance));
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync rc = VINF_SUCCESS;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync }
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync else
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach LUN #0"));
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync return rc;
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync}
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync/**
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync * The device registration structure.
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsyncconst PDMDEVREG g_DeviceACPI =
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync{
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* u32Version */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PDM_DEVREG_VERSION,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* szName */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync "acpi",
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* szRCMod */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync "VBoxDDGC.gc",
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* szR0Mod */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync "VBoxDDR0.r0",
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* pszDescription */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync "Advanced Configuration and Power Interface",
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* fFlags */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* fClass */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync PDM_DEVREG_CLASS_ACPI,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* cMaxInstances */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync ~0,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* cbInstance */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync sizeof(ACPIState),
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* pfnConstruct */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync acpiConstruct,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* pfnDestruct */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync NULL,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* pfnRelocate */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync acpiRelocate,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* pfnIOCtl */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync NULL,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* pfnPowerOn */
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync NULL,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* pfnReset */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiReset,
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync /* pfnSuspend */
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync NULL,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* pfnResume */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync NULL,
969643a53adfd6346c00c1a5fbbe64d9cacff0a7vboxsync /* pfnAttach */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync acpiAttach,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* pfnDetach */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync acpiDetach,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* pfnQueryInterface. */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync NULL,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* pfnInitComplete */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync NULL,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* pfnPowerOff */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync NULL,
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync /* pfnSoftReset */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync NULL,
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync /* u32VersionEnd */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync PDM_DEVREG_VERSION
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync};
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#endif /* IN_RING3 */
1a04ec99647f9be2f2ba19cf247c0f989aa2e80cvboxsync#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
e8f997cba588730c203f0bdb07bcb9cbb5814c99vboxsync