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
					
				
							
								
								
									
										74
									
								
								hw/acpi.c
								
								
								
								
							
							
						
						
									
										74
									
								
								hw/acpi.c
								
								
								
								
							| 
						 | 
				
			
			@ -50,15 +50,12 @@ typedef struct PIIX4PMState {
 | 
			
		|||
    uint8_t smb_data[32];
 | 
			
		||||
    uint8_t smb_index;
 | 
			
		||||
    qemu_irq irq;
 | 
			
		||||
    int64_t pmtmr;
 | 
			
		||||
} PIIX4PMState;
 | 
			
		||||
 | 
			
		||||
#define RTC_EN (1 << 10)
 | 
			
		||||
#define PWRBTN_EN (1 << 8)
 | 
			
		||||
#define GBL_EN (1 << 5)
 | 
			
		||||
#define TMROF_EN (1 << 0)
 | 
			
		||||
#define TIMER_OVERFLOW_CNT (1 << 23)
 | 
			
		||||
#define TIMER_MASK 0xffffffLL
 | 
			
		||||
 | 
			
		||||
#define SCI_EN (1 << 0)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -77,61 +74,47 @@ typedef struct PIIX4PMState {
 | 
			
		|||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
    update_pmtmr(s);
 | 
			
		||||
    return s->pmtmr & TIMER_MASK;
 | 
			
		||||
    uint32_t d;
 | 
			
		||||
    d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
 | 
			
		||||
    return d & 0xffffff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int get_pmsts(PIIX4PMState *s)
 | 
			
		||||
{
 | 
			
		||||
    /* Just increase the accurancy by double computing the timer value */
 | 
			
		||||
    update_pmtmr(s);
 | 
			
		||||
 | 
			
		||||
    return s->pmsts;
 | 
			
		||||
    int64_t d;
 | 
			
		||||
    int pmsts;
 | 
			
		||||
    pmsts = 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)
 | 
			
		||||
{
 | 
			
		||||
    int sci_level;
 | 
			
		||||
    int sci_level, pmsts;
 | 
			
		||||
    int64_t expire_time;
 | 
			
		||||
 | 
			
		||||
    sci_level = (((s->pmsts & s->pmen) & 
 | 
			
		||||
    pmsts = get_pmsts(s);
 | 
			
		||||
    sci_level = (((pmsts & s->pmen) &
 | 
			
		||||
                  (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
 | 
			
		||||
    if (!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)
 | 
			
		||||
{
 | 
			
		||||
    PIIX4PMState *s = opaque;
 | 
			
		||||
    update_pmtmr(s);
 | 
			
		||||
    pm_update_sci(s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
    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;
 | 
			
		||||
        update_pmtmr(s);
 | 
			
		||||
            pm_update_sci(s);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 0x02:
 | 
			
		||||
        s->pmen = val;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue