ia64/xen-unstable

changeset 10466:5c533b9e2d3f

[HVM] ACPI support patch 2 of 4: ACPI timer.
ACPI timer is required during guest windows installation and boot.

Signed-off-by: Tang Liang <tangliang@lenovo.com>
Signed-off-by: Winston Wang <winston.l.wang@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat Jun 17 09:05:34 2006 +0100 (2006-06-17)
parents 588e1aef89e8
children e1c8212d78c3
files tools/ioemu/hw/piix4acpi.c
line diff
     1.1 --- a/tools/ioemu/hw/piix4acpi.c	Sat Jun 17 09:00:16 2006 +0100
     1.2 +++ b/tools/ioemu/hw/piix4acpi.c	Sat Jun 17 09:05:34 2006 +0100
     1.3 @@ -48,6 +48,13 @@ typedef struct AcpiDeviceState AcpiDevic
     1.4  AcpiDeviceState *acpi_device_table;
     1.5  
     1.6  /* Bits of PM1a register define here  */											
     1.7 +typedef struct PMTState {    	  
     1.8 +    uint32_t count;
     1.9 +    int irq;
    1.10 +    uint64_t next_pm_time;
    1.11 +    QEMUTimer *pm_timer;
    1.12 +}PMTState;
    1.13 +
    1.14  typedef struct PM1Event_BLK {
    1.15      uint16_t pm1_status; /* pm1a_EVT_BLK */
    1.16      uint16_t pm1_enable; /* pm1a_EVT_BLK+2 */
    1.17 @@ -62,7 +69,33 @@ typedef struct PCIAcpiState {
    1.18      uint32_t pm1_timer; /* pmtmr_BLK */
    1.19  } PCIAcpiState;
    1.20  
    1.21 +static PMTState *pmtimer_state;
    1.22  static PCIAcpiState *acpi_state;
    1.23 + 
    1.24 +static void pmtimer_save(QEMUFile *f, void *opaque)       
    1.25 +{
    1.26 +	 PMTState *s = opaque; 
    1.27 +	 
    1.28 +	 qemu_put_be32s(f, &s->count);
    1.29 +	 qemu_put_be32s(f, &s->irq);
    1.30 +         qemu_put_be64s(f, &s->next_pm_time);
    1.31 +	 qemu_put_timer(f, s->pm_timer);
    1.32 +
    1.33 +}
    1.34 +
    1.35 +static int pmtimer_load(QEMUFile *f, void *opaque, int version_id)
    1.36 +{
    1.37 +    PMTState *s = opaque;
    1.38 +
    1.39 +         if (version_id != 1)
    1.40 +         return -EINVAL;
    1.41 +         qemu_get_be32s(f, &s->count);
    1.42 +         qemu_get_be32s(f, &s->irq);
    1.43 +         qemu_get_be64s(f, &s->next_pm_time);
    1.44 +         qemu_get_timer(f, s->pm_timer);
    1.45 +         return 0;
    1.46 +           
    1.47 +}
    1.48  
    1.49  static inline void acpi_set_irq(PCIAcpiState *s)
    1.50  {
    1.51 @@ -70,6 +103,52 @@ static inline void acpi_set_irq(PCIAcpiS
    1.52  /* no real SCI event need for now, so comment the following line out */
    1.53  /*        pic_set_irq(s->irq, 1);	*/
    1.54           printf("acpi_set_irq: s->irq %x \n",s->irq);
    1.55 +
    1.56 +}
    1.57 +
    1.58 +static void pm_timer_update(void *opaque)
    1.59 +{
    1.60 +        PMTState *s = opaque;            
    1.61 +        s->next_pm_time += muldiv64(1, ticks_per_sec,FREQUENCE_PMTIMER);
    1.62 +        qemu_mod_timer(s->pm_timer, s->next_pm_time);
    1.63 +        acpi_state->pm1_timer ++;
    1.64 +           
    1.65 +        
    1.66 +    /* if pm timer is zero    reset it to zero;  */
    1.67 +        if (acpi_state->pm1_timer >= 0x1000000) 
    1.68 +        {
    1.69 +/*	    printf("pm_timerupdate: timer overflow: %x \n", acpi_state->pm1_timer); */
    1.70 +
    1.71 +              acpi_state->pm1_timer = 0;
    1.72 +              acpi_state->pm1_status =   acpi_state->pm1_status | TMROF_STS;
    1.73 +                      	//if  TMROF_EN is set send the irq
    1.74 +              if  ((acpi_state->pm1_enable & TMROF_EN) ==  TMROF_EN)
    1.75 +              {
    1.76 +               acpi_set_irq(acpi_state);
    1.77 +               acpi_state->pm1_enable = 0x00; /* only need one time...*/
    1.78 +              }
    1.79 +        }
    1.80 +        s->count = acpi_state->pm1_timer;
    1.81 +}
    1.82 +
    1.83 +static PMTState *pmtimer_init(void)
    1.84 +{
    1.85 +    PMTState *s;
    1.86 +
    1.87 +    s = qemu_mallocz(sizeof(PMTState));
    1.88 +    if (!s)
    1.89 +        return NULL;        
    1.90 +
    1.91 +    /* s->irq = irq;    */
    1.92 +         
    1.93 +    s->pm_timer = qemu_new_timer(vm_clock, pm_timer_update, s);
    1.94 + 
    1.95 +    s->count = 0;
    1.96 +    s->next_pm_time = qemu_get_clock(vm_clock) + muldiv64(1, ticks_per_sec,FREQUENCE_PMTIMER) + 1;
    1.97 +    qemu_mod_timer(s->pm_timer, s->next_pm_time);
    1.98 + 
    1.99 +    register_savevm("pm timer", 1, 1, pmtimer_save, pmtimer_load, s);
   1.100 +    return s;
   1.101  }
   1.102  
   1.103  static void acpi_reset(PCIAcpiState *s)
   1.104 @@ -224,6 +303,8 @@ static void acpiPm1Status_writew(void *o
   1.105      s->pm1_status = s->pm1_status&!GBL_STS;     
   1.106      
   1.107  /*    printf("acpiPm1Status_writew \n addr %x val:%x pm1_status:%x \n", addr, val,s->pm1_status); */
   1.108 +
   1.109 +
   1.110  } 
   1.111  
   1.112  static uint32_t acpiPm1Status_readw(void *opaque, uint32_t addr)
   1.113 @@ -289,13 +370,15 @@ static void acpiPm1Event_writel(void *op
   1.114        
   1.115  } 
   1.116  
   1.117 -static void acpiPm1Event_readl(void *opaque, uint32_t addr)
   1.118 +static uint32_t acpiPm1Event_readl(void *opaque, uint32_t addr)
   1.119  {
   1.120      PCIAcpiState *s = opaque;
   1.121      uint32_t val;
   1.122      
   1.123 -    val=s->pm1_status|(s->pm1_enable<<16);
   1.124 +    val = s->pm1_status|(s->pm1_enable<<16);
   1.125  /*    printf("acpiPm1Event_readl \n addr %x val:%x\n", addr, val);    */
   1.126 +
   1.127 +    return val;
   1.128  }
   1.129  
   1.130  static void acpiPm1Timer_writel(void *opaque, uint32_t addr, uint32_t val)
   1.131 @@ -383,7 +466,7 @@ void pci_piix4_acpi_init(PCIBus *bus)
   1.132  								  
   1.133      pci_register_io_region((PCIDevice *)d, 4, 0x10, 
   1.134                             PCI_ADDRESS_SPACE_IO, acpi_map);
   1.135 -
   1.136 +    pmtimer_state = pmtimer_init();
   1.137      acpi_reset (d);  
   1.138  
   1.139  }