mirror of
https://git.proxmox.com/git/qemu
synced 2025-08-07 18:13:00 +00:00
Ignore the wrapping of acpi timer counter again.
Revert problematic change to restore system_powerdown. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4268 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
f3ae070459
commit
7546c016e5
82
hw/acpi.c
82
hw/acpi.c
@ -50,15 +50,12 @@ typedef struct PIIX4PMState {
|
|||||||
uint8_t smb_data[32];
|
uint8_t smb_data[32];
|
||||||
uint8_t smb_index;
|
uint8_t smb_index;
|
||||||
qemu_irq irq;
|
qemu_irq irq;
|
||||||
int64_t pmtmr;
|
|
||||||
} PIIX4PMState;
|
} PIIX4PMState;
|
||||||
|
|
||||||
#define RTC_EN (1 << 10)
|
#define RTC_EN (1 << 10)
|
||||||
#define PWRBTN_EN (1 << 8)
|
#define PWRBTN_EN (1 << 8)
|
||||||
#define GBL_EN (1 << 5)
|
#define GBL_EN (1 << 5)
|
||||||
#define TMROF_EN (1 << 0)
|
#define TMROF_EN (1 << 0)
|
||||||
#define TIMER_OVERFLOW_CNT (1 << 23)
|
|
||||||
#define TIMER_MASK 0xffffffLL
|
|
||||||
|
|
||||||
#define SCI_EN (1 << 0)
|
#define SCI_EN (1 << 0)
|
||||||
|
|
||||||
@ -77,61 +74,47 @@ typedef struct PIIX4PMState {
|
|||||||
|
|
||||||
PIIX4PMState *pm_state;
|
PIIX4PMState *pm_state;
|
||||||
|
|
||||||
static void update_pmtmr(PIIX4PMState *s)
|
|
||||||
{
|
|
||||||
int64_t pmtmr;
|
|
||||||
|
|
||||||
pmtmr = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec)
|
|
||||||
& TIMER_MASK;
|
|
||||||
|
|
||||||
if (!(s->pmsts & TMROF_EN)) {
|
|
||||||
if ((pmtmr ^ s->pmtmr) & TIMER_OVERFLOW_CNT) {
|
|
||||||
s->pmsts |= TMROF_EN;
|
|
||||||
if (s->pmen & TMROF_EN)
|
|
||||||
qemu_set_irq(s->irq, 1);
|
|
||||||
} else {
|
|
||||||
/* Calculate when the timer will neet to set
|
|
||||||
* the overflow bit again */
|
|
||||||
uint64_t delta = TIMER_OVERFLOW_CNT -
|
|
||||||
(pmtmr & (TIMER_OVERFLOW_CNT - 1));
|
|
||||||
|
|
||||||
delta = muldiv64(delta, ticks_per_sec, PM_FREQ);
|
|
||||||
qemu_mod_timer(s->tmr_timer, qemu_get_clock(vm_clock) + delta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s->pmtmr = pmtmr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t get_pmtmr(PIIX4PMState *s)
|
static uint32_t get_pmtmr(PIIX4PMState *s)
|
||||||
{
|
{
|
||||||
update_pmtmr(s);
|
uint32_t d;
|
||||||
return s->pmtmr & TIMER_MASK;
|
d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
|
||||||
|
return d & 0xffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int get_pmsts(PIIX4PMState *s)
|
static int get_pmsts(PIIX4PMState *s)
|
||||||
{
|
{
|
||||||
/* Just increase the accurancy by double computing the timer value */
|
int64_t d;
|
||||||
update_pmtmr(s);
|
int pmsts;
|
||||||
|
pmsts = s->pmsts;
|
||||||
return s->pmsts;
|
d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
|
||||||
|
if (d >= s->tmr_overflow_time)
|
||||||
|
s->pmsts |= TMROF_EN;
|
||||||
|
return pmsts;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pm_update_sci(PIIX4PMState *s)
|
static void pm_update_sci(PIIX4PMState *s)
|
||||||
{
|
{
|
||||||
int sci_level;
|
int sci_level, pmsts;
|
||||||
|
int64_t expire_time;
|
||||||
|
|
||||||
sci_level = (((s->pmsts & s->pmen) &
|
pmsts = get_pmsts(s);
|
||||||
(RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
|
sci_level = (((pmsts & s->pmen) &
|
||||||
if (!sci_level)
|
(RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
|
||||||
qemu_set_irq(s->irq, sci_level);
|
qemu_set_irq(s->irq, sci_level);
|
||||||
|
/* schedule a timer interruption if needed */
|
||||||
|
if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) {
|
||||||
|
expire_time = muldiv64(s->tmr_overflow_time, ticks_per_sec, PM_FREQ);
|
||||||
|
qemu_mod_timer(s->tmr_timer, expire_time);
|
||||||
|
s->tmr_overflow_time += 0x800000;
|
||||||
|
} else {
|
||||||
|
qemu_del_timer(s->tmr_timer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pm_tmr_timer(void *opaque)
|
static void pm_tmr_timer(void *opaque)
|
||||||
{
|
{
|
||||||
PIIX4PMState *s = opaque;
|
PIIX4PMState *s = opaque;
|
||||||
update_pmtmr(s);
|
pm_update_sci(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
|
static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
|
||||||
@ -140,9 +123,18 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
|
|||||||
addr &= 0x3f;
|
addr &= 0x3f;
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
s->pmsts &= ~val;
|
{
|
||||||
update_pmtmr(s);
|
int64_t d;
|
||||||
pm_update_sci(s);
|
int pmsts;
|
||||||
|
pmsts = get_pmsts(s);
|
||||||
|
if (pmsts & val & TMROF_EN) {
|
||||||
|
/* if TMRSTS is reset, then compute the new overflow time */
|
||||||
|
d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
|
||||||
|
s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
|
||||||
|
}
|
||||||
|
s->pmsts &= ~val;
|
||||||
|
pm_update_sci(s);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x02:
|
case 0x02:
|
||||||
s->pmen = val;
|
s->pmen = val;
|
||||||
|
Loading…
Reference in New Issue
Block a user