static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) { PIIX4PMState *s = opaque; addr &= 0x3f; switch(addr) { case 0x00: { int64_t d; int pmsts; pmsts = get_pmsts(s); if (pmsts & val & ACPI_BITMASK_TIMER_STATUS) { /* if TMRSTS is reset, then compute the new overflow time */ d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec()); s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL; } s->pmsts &= ~val; pm_update_sci(s); } break; case 0x02: s->pmen = val; pm_update_sci(s); break; case 0x04: { int sus_typ; s->pmcntrl = val & ~(ACPI_BITMASK_SLEEP_ENABLE); if (val & ACPI_BITMASK_SLEEP_ENABLE) { /* change suspend type */ sus_typ = (val >> 10) & 7; switch(sus_typ) { case 0: /* soft power off */ qemu_system_shutdown_request(); break; 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); qemu_system_reset_request(); if (s->cmos_s3) { qemu_irq_raise(s->cmos_s3); } default: break; } } } break; default: break; }
static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) { PIIX4PMState *s = opaque; addr &= 0x3f; switch(addr) { case 0x00: { int64_t d; 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, get_ticks_per_sec()); s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL; } s->pmsts &= ~val; pm_update_sci(s); } break; case 0x02: s->pmen = val; qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_RTC, val & RTC_EN); qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_PMTIMER, val & TMROF_EN); pm_update_sci(s); break; case 0x04: { int sus_typ; s->pmcntrl = val & ~(SUS_EN); if (val & SUS_EN) { /* change suspend type */ sus_typ = (val >> 10) & 7; switch(sus_typ) { case 0: /* soft power off */ qemu_system_shutdown_request(); break; case 1: qemu_system_suspend_request(); break; default: if (sus_typ == s->s4_val) { /* S4 request */ monitor_protocol_event(QEVENT_SUSPEND_DISK, NULL); qemu_system_shutdown_request(); } break; } } } break; default: break; }
static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) { PIIX4PMState *s = opaque; addr &= 0x3f; switch(addr) { case 0x00: { int64_t d; 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, get_ticks_per_sec()); s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL; } s->pmsts &= ~val; pm_update_sci(s); } break; case 0x02: s->pmen = val; pm_update_sci(s); break; case 0x04: { int sus_typ; s->pmcntrl = val & ~(SUS_EN); if (val & SUS_EN) { /* change suspend type */ sus_typ = (val >> 10) & 7; switch(sus_typ) { case 0: /* soft power off */ qemu_system_shutdown_request(); break; case 1: /* RSM_STS should be set on resume. Pretend that resume was caused by power button */ s->pmsts |= (RSM_STS | PWRBTN_STS); qemu_system_reset_request(); #if defined(TARGET_I386) cmos_set_s3_resume(); #endif default: break; } } } break; default: break; }
static void pm_update_sci(PIIX4PMState *s) { int sci_level, pmsts; int64_t expire_time; pmsts = get_pmsts(s); sci_level = (((pmsts & s->pmen) & (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0); 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, get_ticks_per_sec(), PM_FREQ); qemu_mod_timer(s->tmr_timer, expire_time); } else { qemu_del_timer(s->tmr_timer); } }
static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) { PIIX4PMState *s = opaque; addr &= 0x3f; switch(addr) { case 0x00: { int64_t d; 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; case 0x02: s->pmen = val; pm_update_sci(s); break; case 0x04: { int sus_typ; s->pmcntrl = val & ~(SUS_EN); if (val & SUS_EN) { /* change suspend type */ sus_typ = (val >> 10) & 3; switch(sus_typ) { case 0: /* soft power off */ qemu_system_shutdown_request(); break; default: break; } } } break; default: break; }
static void pm_update_sci(PIIX4PMState *s) { int sci_level, pmsts; int64_t expire_time; pmsts = get_pmsts(s); sci_level = (((pmsts & s->pmen) & (ACPI_BITMASK_RT_CLOCK_ENABLE | ACPI_BITMASK_POWER_BUTTON_ENABLE | ACPI_BITMASK_GLOBAL_LOCK_ENABLE | ACPI_BITMASK_TIMER_ENABLE)) != 0); qemu_set_irq(s->irq, sci_level); /* schedule a timer interruption if needed */ if ((s->pmen & ACPI_BITMASK_TIMER_ENABLE) && !(pmsts & ACPI_BITMASK_TIMER_STATUS)) { expire_time = muldiv64(s->tmr_overflow_time, get_ticks_per_sec(), PM_TIMER_FREQUENCY); qemu_mod_timer(s->tmr_timer, expire_time); } else { qemu_del_timer(s->tmr_timer); } }