From patchwork Fri Mar 25 10:54:39 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Isaku Yamahata X-Patchwork-Id: 88369 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 3BC6EB6F90 for ; Fri, 25 Mar 2011 21:56:39 +1100 (EST) Received: from localhost ([127.0.0.1]:39807 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q34gu-0007ZK-0p for incoming@patchwork.ozlabs.org; Fri, 25 Mar 2011 06:56:28 -0400 Received: from [140.186.70.92] (port=33261 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q34fK-0007VA-Dg for qemu-devel@nongnu.org; Fri, 25 Mar 2011 06:54:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Q34fH-0003AO-Gv for qemu-devel@nongnu.org; Fri, 25 Mar 2011 06:54:49 -0400 Received: from mail.valinux.co.jp ([210.128.90.3]:51243) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Q34fG-000398-PJ for qemu-devel@nongnu.org; Fri, 25 Mar 2011 06:54:47 -0400 Received: from ps.local.valinux.co.jp (vagw.valinux.co.jp [210.128.90.14]) by mail.valinux.co.jp (Postfix) with SMTP id 1C15D1892A; Fri, 25 Mar 2011 19:54:42 +0900 (JST) Received: (nullmailer pid 29838 invoked by uid 1000); Fri, 25 Mar 2011 10:54:41 -0000 From: Isaku Yamahata To: qemu-devel@nongnu.org Date: Fri, 25 Mar 2011 19:54:39 +0900 Message-Id: X-Mailer: git-send-email 1.7.1.1 In-Reply-To: References: In-Reply-To: References: X-Virus-Scanned: clamav-milter 0.95.2 at va-mail.local.valinux.co.jp X-Virus-Status: Clean X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 210.128.90.3 Cc: blauwirbel@gmail.com, yamahata@valinux.co.jp, Aurelien Jarno , Huacai Chen Subject: [Qemu-devel] [PATCH 2/4] acpi, acpi_piix, vt82c686: factor out PM1a EVT logic X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org factor out ACPI PM1a EVT logic. Later this will be used by ich9 acpi. Cc: Blue Swirl Cc: Huacai Chen Cc: Aurelien Jarno Signed-off-by: Isaku Yamahata --- Changes v7 -> v8: - vt82c686 --- hw/acpi.c | 37 +++++++++++++++++++++++++++++++++++++ hw/acpi.h | 13 +++++++++++++ hw/acpi_piix4.c | 52 ++++++++++++++++------------------------------------ hw/vt82c686.c | 54 +++++++++++++++--------------------------------------- 4 files changed, 81 insertions(+), 75 deletions(-) diff --git a/hw/acpi.c b/hw/acpi.c index 08cb126..07283be 100644 --- a/hw/acpi.c +++ b/hw/acpi.c @@ -15,6 +15,7 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see */ +#include "sysemu.h" #include "hw.h" #include "pc.h" #include "acpi.h" @@ -198,6 +199,42 @@ out: return -1; } +/* ACPI PM1a EVT */ +uint16_t acpi_pm1_evt_get_sts(ACPIPM1EVT *pm1, int64_t overflow_time) +{ + int64_t d = acpi_pm_tmr_get_clock(); + if (d >= overflow_time) { + pm1->sts |= ACPI_BITMASK_TIMER_STATUS; + } + return pm1->sts; +} + +void acpi_pm1_evt_write_sts(ACPIPM1EVT *pm1, ACPIPMTimer *tmr, uint16_t val) +{ + uint16_t pm1_sts = acpi_pm1_evt_get_sts(pm1, tmr->overflow_time); + if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) { + /* if TMRSTS is reset, then compute the new overflow time */ + acpi_pm_tmr_calc_overflow_time(tmr); + } + pm1->sts &= ~val; +} + +void acpi_pm1_evt_power_down(ACPIPM1EVT *pm1, ACPIPMTimer *tmr) +{ + if (!pm1) { + qemu_system_shutdown_request(); + } else if (pm1->en & ACPI_BITMASK_POWER_BUTTON_ENABLE) { + pm1->sts |= ACPI_BITMASK_POWER_BUTTON_STATUS; + tmr->update_sci(tmr); + } +} + +void acpi_pm1_evt_reset(ACPIPM1EVT *pm1) +{ + pm1->sts = 0; + pm1->en = 0; +} + /* ACPI PM_TMR */ void acpi_pm_tmr_update(ACPIPMTimer *tmr, bool enable) { diff --git a/hw/acpi.h b/hw/acpi.h index fc42501..c286d7d 100644 --- a/hw/acpi.h +++ b/hw/acpi.h @@ -99,4 +99,17 @@ static inline int64_t acpi_pm_tmr_get_clock(void) get_ticks_per_sec()); } +/* PM1a_EVT: piix and ich9 don't implement PM1b. */ +struct ACPIPM1EVT +{ + uint16_t sts; + uint16_t en; +}; +typedef struct ACPIPM1EVT ACPIPM1EVT; + +uint16_t acpi_pm1_evt_get_sts(ACPIPM1EVT *pm1, int64_t overflow_time); +void acpi_pm1_evt_write_sts(ACPIPM1EVT *pm1, ACPIPMTimer *tmr, uint16_t val); +void acpi_pm1_evt_power_down(ACPIPM1EVT *pm1, ACPIPMTimer *tmr); +void acpi_pm1_evt_reset(ACPIPM1EVT *pm1); + #endif /* !QEMU_HW_ACPI_H */ diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index d5f631a..5b4eef5 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -54,8 +54,7 @@ struct pci_status { typedef struct PIIX4PMState { PCIDevice dev; IORange ioport; - uint16_t pmsts; - uint16_t pmen; + ACPIPM1EVT pm1a; uint16_t pmcntrl; APMState apm; @@ -81,20 +80,12 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s); #define ACPI_ENABLE 0xf1 #define ACPI_DISABLE 0xf0 -static int get_pmsts(PIIX4PMState *s) -{ - int64_t d = acpi_pm_tmr_get_clock(); - if (d >= s->tmr.overflow_time) - s->pmsts |= ACPI_BITMASK_TIMER_STATUS; - return s->pmsts; -} - static void pm_update_sci(PIIX4PMState *s) { int sci_level, pmsts; - pmsts = get_pmsts(s); - sci_level = (((pmsts & s->pmen) & + pmsts = acpi_pm1_evt_get_sts(&s->pm1a, s->tmr.overflow_time); + sci_level = (((pmsts & s->pm1a.en) & (ACPI_BITMASK_RT_CLOCK_ENABLE | ACPI_BITMASK_POWER_BUTTON_ENABLE | ACPI_BITMASK_GLOBAL_LOCK_ENABLE | @@ -103,7 +94,7 @@ static void pm_update_sci(PIIX4PMState *s) qemu_set_irq(s->irq, sci_level); /* schedule a timer interruption if needed */ - acpi_pm_tmr_update(&s->tmr, (s->pmen & ACPI_BITMASK_TIMER_ENABLE) && + acpi_pm_tmr_update(&s->tmr, (s->pm1a.en & ACPI_BITMASK_TIMER_ENABLE) && !(pmsts & ACPI_BITMASK_TIMER_STATUS)); } @@ -125,19 +116,11 @@ static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width, switch(addr) { case 0x00: - { - int pmsts; - pmsts = get_pmsts(s); - if (pmsts & val & ACPI_BITMASK_TIMER_STATUS) { - /* if TMRSTS is reset, then compute the new overflow time */ - acpi_pm_tmr_calc_overflow_time(&s->tmr); - } - s->pmsts &= ~val; - pm_update_sci(s); - } + acpi_pm1_evt_write_sts(&s->pm1a, &s->tmr, val); + pm_update_sci(s); break; case 0x02: - s->pmen = val; + s->pm1a.en = val; pm_update_sci(s); break; case 0x04: @@ -154,8 +137,8 @@ static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width, case 1: /* ACPI_BITMASK_WAKE_STATUS should be set on resume. Pretend that resume was caused by power button */ - s->pmsts |= (ACPI_BITMASK_WAKE_STATUS | - ACPI_BITMASK_POWER_BUTTON_STATUS); + s->pm1a.sts |= (ACPI_BITMASK_WAKE_STATUS | + ACPI_BITMASK_POWER_BUTTON_STATUS); qemu_system_reset_request(); if (s->cmos_s3) { qemu_irq_raise(s->cmos_s3); @@ -180,10 +163,10 @@ static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width, switch(addr) { case 0x00: - val = get_pmsts(s); + val = acpi_pm1_evt_get_sts(&s->pm1a, s->tmr.overflow_time); break; case 0x02: - val = s->pmen; + val = s->pm1a.en; break; case 0x04: val = s->pmcntrl; @@ -290,8 +273,8 @@ static const VMStateDescription vmstate_acpi = { .post_load = vmstate_acpi_post_load, .fields = (VMStateField []) { VMSTATE_PCI_DEVICE(dev, PIIX4PMState), - VMSTATE_UINT16(pmsts, PIIX4PMState), - VMSTATE_UINT16(pmen, PIIX4PMState), + VMSTATE_UINT16(pm1a.sts, PIIX4PMState), + VMSTATE_UINT16(pm1a.en, PIIX4PMState), VMSTATE_UINT16(pmcntrl, PIIX4PMState), VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState), VMSTATE_TIMER(tmr.timer, PIIX4PMState), @@ -342,13 +325,10 @@ static void piix4_reset(void *opaque) static void piix4_powerdown(void *opaque, int irq, int power_failing) { PIIX4PMState *s = opaque; + ACPIPM1EVT *pm1a = s? &s->pm1a: NULL; + ACPIPMTimer *tmr = s? &s->tmr: NULL; - if (!s) { - qemu_system_shutdown_request(); - } else if (s->pmen & ACPI_BITMASK_POWER_BUTTON_ENABLE) { - s->pmsts |= ACPI_BITMASK_POWER_BUTTON_STATUS; - pm_update_sci(s); - } + acpi_pm1_evt_power_down(pm1a, tmr); } static int piix4_pm_initfn(PCIDevice *dev) diff --git a/hw/vt82c686.c b/hw/vt82c686.c index 6f9c384..10cbc74 100644 --- a/hw/vt82c686.c +++ b/hw/vt82c686.c @@ -156,8 +156,7 @@ static void vt82c686b_write_config(PCIDevice * d, uint32_t address, typedef struct VT686PMState { PCIDevice dev; - uint16_t pmsts; - uint16_t pmen; + ACPIPM1EVT pm1a; uint16_t pmcntrl; APMState apm; ACPIPMTimer tmr; @@ -173,34 +172,19 @@ typedef struct VT686MC97State { PCIDevice dev; } VT686MC97State; -#define RTC_EN (1 << 10) -#define PWRBTN_EN (1 << 8) -#define GBL_EN (1 << 5) -#define TMROF_EN (1 << 0) -#define SUS_EN (1 << 13) - -#define ACPI_ENABLE 0xf1 -#define ACPI_DISABLE 0xf0 - -static int get_pmsts(VT686PMState *s) -{ - int64_t d = acpi_pm_tmr_get_clock(); - if (d >= s->tmr.overflow_time) { - s->pmsts |= ACPI_BITMASK_TIMER_STATUS; - } - return s->pmsts; -} - static void pm_update_sci(VT686PMState *s) { int sci_level, pmsts; - pmsts = get_pmsts(s); - sci_level = (((pmsts & s->pmen) & - (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0); + pmsts = acpi_pm1_evt_get_sts(&s->pm1a, s->tmr.overflow_time); + sci_level = (((pmsts & s->pm1a.en) & + (ACPI_BITMASK_RT_CLOCK_ENABLE | + ACPI_BITMASK_POWER_BUTTON_ENABLE | + ACPI_BITMASK_GLOBAL_LOCK_ENABLE | + ACPI_BITMASK_TIMER_ENABLE)) != 0); qemu_set_irq(s->dev.irq[0], sci_level); /* schedule a timer interruption if needed */ - acpi_pm_tmr_update(&s->tmr, (s->pmen & ACPI_BITMASK_TIMER_ENABLE) && + acpi_pm_tmr_update(&s->tmr, (s->pm1a.en & ACPI_BITMASK_TIMER_ENABLE) && !(pmsts & ACPI_BITMASK_TIMER_STATUS)); } @@ -217,19 +201,11 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) addr &= 0x0f; switch (addr) { case 0x00: - { - int pmsts; - pmsts = get_pmsts(s); - if (pmsts & val & TMROF_EN) { - /* if TMRSTS is reset, then compute the new overflow time */ - acpi_pm_tmr_calc_overflow_time(&s->tmr); - } - s->pmsts &= ~val; - pm_update_sci(s); - } + acpi_pm1_evt_write_sts(&s->pm1a, &s->tmr, val); + pm_update_sci(s); break; case 0x02: - s->pmen = val; + s->pm1a.en = val; pm_update_sci(s); break; case 0x04: @@ -263,10 +239,10 @@ static uint32_t pm_ioport_readw(void *opaque, uint32_t addr) addr &= 0x0f; switch (addr) { case 0x00: - val = get_pmsts(s); + val = acpi_pm1_evt_get_sts(&s->pm1a, s->tmr.overflow_time); break; case 0x02: - val = s->pmen; + val = s->pm1a.en; break; case 0x04: val = s->pmcntrl; @@ -344,8 +320,8 @@ static const VMStateDescription vmstate_acpi = { .post_load = vmstate_acpi_post_load, .fields = (VMStateField []) { VMSTATE_PCI_DEVICE(dev, VT686PMState), - VMSTATE_UINT16(pmsts, VT686PMState), - VMSTATE_UINT16(pmen, VT686PMState), + VMSTATE_UINT16(pm1a.sts, VT686PMState), + VMSTATE_UINT16(pm1a.en, VT686PMState), VMSTATE_UINT16(pmcntrl, VT686PMState), VMSTATE_STRUCT(apm, VT686PMState, 0, vmstate_apm, APMState), VMSTATE_TIMER(tmr.timer, VT686PMState),