ia64/xen-unstable

view tools/ioemu/hw/piix4acpi.c @ 10645:fd6d12935b56

[HVM] Disable pmtimer in qemu acpi device model. Needs fixing
to not burn ~25% of a 3GHz CPU.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@dhcp93.uk.xensource.com
date Mon Jul 03 16:07:20 2006 +0100 (2006-07-03)
parents b025491f0ba8
children f7b43e5c42b9
line source
1 /*
2 * PIIX4 ACPI controller emulation
3 *
4 * Winston liwen Wang, winston.l.wang@intel.com
5 * Copyright (c) 2006 , Intel Corporation.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
26 #include "vl.h"
27 #define FREQUENCE_PMTIMER 3753425
28 /* acpi register bit define here */
30 /* PM1_STS */
31 #define TMROF_STS (1 << 0)
32 #define BM_STS (1 << 4)
33 #define GBL_STS (1 << 5)
34 #define PWRBTN_STS (1 << 8)
35 #define RTC_STS (1 << 10)
36 #define PRBTNOR_STS (1 << 11)
37 #define WAK_STS (1 << 15)
38 /* PM1_EN */
39 #define TMROF_EN (1 << 0)
40 #define GBL_EN (1 << 5)
41 #define PWRBTN_EN (1 << 8)
42 #define RTC_EN (1 << 10)
43 /* PM1_CNT */
44 #define SCI_EN (1 << 0)
45 #define GBL_RLS (1 << 2)
46 #define SLP_EN (1 << 13)
48 /* Bits of PM1a register define here */
49 #define SLP_TYP_MASK 0x1C00
50 #define SLP_VAL 0x1C00
52 typedef struct AcpiDeviceState AcpiDeviceState;
53 AcpiDeviceState *acpi_device_table;
55 /* Bits of PM1a register define here */
56 typedef struct PMTState {
57 uint32_t count;
58 int irq;
59 uint64_t next_pm_time;
60 QEMUTimer *pm_timer;
61 }PMTState;
63 typedef struct PM1Event_BLK {
64 uint16_t pm1_status; /* pm1a_EVT_BLK */
65 uint16_t pm1_enable; /* pm1a_EVT_BLK+2 */
66 }PM1Event_BLK;
68 typedef struct PCIAcpiState {
69 PCIDevice dev;
70 uint16_t irq;
71 uint16_t pm1_status; /* pm1a_EVT_BLK */
72 uint16_t pm1_enable; /* pm1a_EVT_BLK+2 */
73 uint16_t pm1_control; /* pm1a_ECNT_BLK */
74 uint32_t pm1_timer; /* pmtmr_BLK */
75 } PCIAcpiState;
77 static PMTState *pmtimer_state;
78 static PCIAcpiState *acpi_state;
80 static void pmtimer_save(QEMUFile *f, void *opaque)
81 {
82 PMTState *s = opaque;
84 qemu_put_be32s(f, &s->count);
85 qemu_put_be32s(f, &s->irq);
86 qemu_put_be64s(f, &s->next_pm_time);
87 qemu_put_timer(f, s->pm_timer);
88 }
90 static int pmtimer_load(QEMUFile *f, void *opaque, int version_id)
91 {
92 PMTState *s = opaque;
94 if (version_id != 1)
95 return -EINVAL;
96 qemu_get_be32s(f, &s->count);
97 qemu_get_be32s(f, &s->irq);
98 qemu_get_be64s(f, &s->next_pm_time);
99 qemu_get_timer(f, s->pm_timer);
100 return 0;
102 }
104 static inline void acpi_set_irq(PCIAcpiState *s)
105 {
106 /* no real SCI event need for now, so comment the following line out */
107 /* pic_set_irq(s->irq, 1); */
108 printf("acpi_set_irq: s->irq %x \n",s->irq);
109 }
111 static void pm_timer_update(void *opaque)
112 {
113 PMTState *s = opaque;
114 s->next_pm_time += muldiv64(1, ticks_per_sec,FREQUENCE_PMTIMER);
115 qemu_mod_timer(s->pm_timer, s->next_pm_time);
116 acpi_state->pm1_timer ++;
118 /* If pm timer is zero then reset it to zero. */
119 if (acpi_state->pm1_timer >= 0x1000000) {
120 /* printf("pm_timerupdate: timer overflow: %x \n", acpi_state->pm1_timer); */
122 acpi_state->pm1_timer = 0;
123 acpi_state->pm1_status = acpi_state->pm1_status | TMROF_STS;
124 /* If TMROF_EN is set then send the irq. */
125 if ((acpi_state->pm1_enable & TMROF_EN) == TMROF_EN) {
126 acpi_set_irq(acpi_state);
127 acpi_state->pm1_enable = 0x00; /* only need one time...*/
128 }
129 }
130 s->count = acpi_state->pm1_timer;
131 }
133 static PMTState *pmtimer_init(void)
134 {
135 PMTState *s;
137 s = qemu_mallocz(sizeof(PMTState));
138 if (!s)
139 return NULL;
141 /* s->irq = irq; */
143 s->pm_timer = qemu_new_timer(vm_clock, pm_timer_update, s);
145 s->count = 0;
146 s->next_pm_time = qemu_get_clock(vm_clock) + muldiv64(1, ticks_per_sec,FREQUENCE_PMTIMER) + 1;
147 qemu_mod_timer(s->pm_timer, s->next_pm_time);
149 register_savevm("pm timer", 1, 1, pmtimer_save, pmtimer_load, s);
150 return s;
151 }
153 static void acpi_reset(PCIAcpiState *s)
154 {
155 uint8_t *pci_conf;
156 pci_conf = s->dev.config;
158 pci_conf[0x42] = 0x00;
159 pci_conf[0x43] = 0x00;
160 s->irq = 9;
161 s->pm1_status = 0;
162 s->pm1_enable = 0x00; /* TMROF_EN should cleared */
163 s->pm1_control = SCI_EN; /* SCI_EN */
164 s->pm1_timer = 0;
165 }
167 /*byte access */
168 static void acpiPm1Status_writeb(void *opaque, uint32_t addr, uint32_t val)
169 {
170 PCIAcpiState *s = opaque;
172 if ((val&TMROF_STS)==TMROF_STS)
173 s->pm1_status = s->pm1_status&!TMROF_STS;
175 if ((val&GBL_STS)==GBL_STS)
176 s->pm1_status = s->pm1_status&!GBL_STS;
178 /* printf("acpiPm1Status_writeb \n addr %x val:%x pm1_status:%x \n", addr, val,s->pm1_status); */
179 }
181 static uint32_t acpiPm1Status_readb(void *opaque, uint32_t addr)
182 {
183 PCIAcpiState *s = opaque;
184 uint32_t val;
186 val = s->pm1_status;
187 /* printf("acpiPm1Status_readb \n addr %x val:%x\n", addr, val); */
189 return val;
190 }
192 static void acpiPm1StatusP1_writeb(void *opaque, uint32_t addr, uint32_t val)
193 {
194 PCIAcpiState *s = opaque;
196 s->pm1_status = (val<<8)||(s->pm1_status);
197 /* printf("acpiPm1StatusP1_writeb \n addr %x val:%x\n", addr, val); */
198 }
200 static uint32_t acpiPm1StatusP1_readb(void *opaque, uint32_t addr)
201 {
202 PCIAcpiState *s = opaque;
203 uint32_t val;
205 val = (s->pm1_status)>>8;
206 printf("acpiPm1StatusP1_readb \n addr %x val:%x\n", addr, val);
208 return val;
209 }
211 static void acpiPm1Enable_writeb(void *opaque, uint32_t addr, uint32_t val)
212 {
213 PCIAcpiState *s = opaque;
215 s->pm1_enable = val;
216 /* printf("acpiPm1Enable_writeb \n addr %x val:%x\n", addr, val); */
217 }
219 static uint32_t acpiPm1Enable_readb(void *opaque, uint32_t addr)
220 {
221 PCIAcpiState *s = opaque;
222 uint32_t val;
224 val = (s->pm1_enable)||0x1;
225 /* printf("acpiPm1Enable_readb \n addr %x val:%x\n", addr, val); */
227 return val;
228 }
230 static void acpiPm1EnableP1_writeb(void *opaque, uint32_t addr, uint32_t val)
231 {
232 PCIAcpiState *s = opaque;
234 s->pm1_enable = (val<<8)||(s->pm1_enable);
235 /* printf("acpiPm1EnableP1_writeb \n addr %x val:%x\n", addr, val); */
237 }
239 static uint32_t acpiPm1EnableP1_readb(void *opaque, uint32_t addr)
240 {
241 PCIAcpiState *s = opaque;
242 uint32_t val;
244 val = (s->pm1_enable)>>8;
245 /* printf("acpiPm1EnableP1_readb \n addr %x val:%x\n", addr, val); */
247 return val;
248 }
250 static void acpiPm1Control_writeb(void *opaque, uint32_t addr, uint32_t val)
251 {
252 PCIAcpiState *s = opaque;
254 s->pm1_control = val;
255 /* printf("acpiPm1Control_writeb \n addr %x val:%x\n", addr, val); */
257 }
259 static uint32_t acpiPm1Control_readb(void *opaque, uint32_t addr)
260 {
261 PCIAcpiState *s = opaque;
262 uint32_t val;
264 val = s->pm1_control;
265 /* printf("acpiPm1Control_readb \n addr %x val:%x\n", addr, val); */
267 return val;
268 }
270 static void acpiPm1ControlP1_writeb(void *opaque, uint32_t addr, uint32_t val)
271 {
272 PCIAcpiState *s = opaque;
274 s->pm1_control = (val<<8)||(s->pm1_control);
275 /* printf("acpiPm1ControlP1_writeb \n addr %x val:%x\n", addr, val); */
277 // Check for power off request
279 if (((val & SLP_EN) != 0) &&
280 ((val & SLP_TYP_MASK) == SLP_VAL)) {
281 s->pm1_timer=0x0; //clear ACPI timer
282 qemu_system_shutdown_request();
283 }
284 }
286 static uint32_t acpiPm1ControlP1_readb(void *opaque, uint32_t addr)
287 {
288 PCIAcpiState *s = opaque;
289 uint32_t val;
291 val = (s->pm1_control)>>8;
292 /* printf("acpiPm1ControlP1_readb \n addr %x val:%x\n", addr, val); */
294 return val;
295 }
298 /* word access */
300 static void acpiPm1Status_writew(void *opaque, uint32_t addr, uint32_t val)
301 {
302 PCIAcpiState *s = opaque;
304 if ((val&TMROF_STS)==TMROF_STS)
305 s->pm1_status = s->pm1_status&!TMROF_STS;
307 if ((val&GBL_STS)==GBL_STS)
308 s->pm1_status = s->pm1_status&!GBL_STS;
310 /* printf("acpiPm1Status_writew \n addr %x val:%x pm1_status:%x \n", addr, val,s->pm1_status); */
311 }
313 static uint32_t acpiPm1Status_readw(void *opaque, uint32_t addr)
314 {
315 PCIAcpiState *s = opaque;
316 uint32_t val;
318 val = s->pm1_status;
319 /* printf("acpiPm1Status_readw \n addr %x val:%x\n", addr, val); */
321 return val;
322 }
324 static void acpiPm1Enable_writew(void *opaque, uint32_t addr, uint32_t val)
325 {
326 PCIAcpiState *s = opaque;
328 s->pm1_enable = val;
329 /* printf("acpiPm1Enable_writew \n addr %x val:%x\n", addr, val); */
331 }
333 static uint32_t acpiPm1Enable_readw(void *opaque, uint32_t addr)
334 {
335 PCIAcpiState *s = opaque;
336 uint32_t val;
338 val = s->pm1_enable;
339 /* printf("acpiPm1Enable_readw \n addr %x val:%x\n", addr, val); */
341 return val;
342 }
344 static void acpiPm1Control_writew(void *opaque, uint32_t addr, uint32_t val)
345 {
346 PCIAcpiState *s = opaque;
348 s->pm1_control = val;
349 /* printf("acpiPm1Control_writew \n addr %x val:%x\n", addr, val); */
351 // Check for power off request
353 if (((val & SLP_EN) != 0) &&
354 ((val & SLP_TYP_MASK) == SLP_VAL)) {
355 qemu_system_shutdown_request();
356 }
358 }
360 static uint32_t acpiPm1Control_readw(void *opaque, uint32_t addr)
361 {
362 PCIAcpiState *s = opaque;
363 uint32_t val;
365 val = s->pm1_control;
366 /* printf("acpiPm1Control_readw \n addr %x val:%x\n", addr, val); */
368 return val;
369 }
371 /* dword access */
373 static void acpiPm1Event_writel(void *opaque, uint32_t addr, uint32_t val)
374 {
375 PCIAcpiState *s = opaque;
377 s->pm1_status = val;
378 s->pm1_enable = val>>16;
379 /* printf("acpiPm1Event_writel \n addr %x val:%x \n", addr, val); */
381 }
383 static uint32_t acpiPm1Event_readl(void *opaque, uint32_t addr)
384 {
385 PCIAcpiState *s = opaque;
386 uint32_t val;
388 val = s->pm1_status|(s->pm1_enable<<16);
389 /* printf("acpiPm1Event_readl \n addr %x val:%x\n", addr, val); */
391 return val;
392 }
394 static void acpiPm1Timer_writel(void *opaque, uint32_t addr, uint32_t val)
395 {
396 PCIAcpiState *s = opaque;
398 s->pm1_timer = val;
399 /* printf("acpiPm1Timer_writel \n addr %x val:%x\n", addr, val); */
400 }
402 static uint32_t acpiPm1Timer_readl(void *opaque, uint32_t addr)
403 {
404 PCIAcpiState *s = opaque;
405 uint32_t val;
407 val = s->pm1_timer;
408 /* printf("acpiPm1Timer_readl \n addr %x val:%x\n", addr, val); */
409 return val;
410 }
412 static void acpi_map(PCIDevice *pci_dev, int region_num,
413 uint32_t addr, uint32_t size, int type)
414 {
415 PCIAcpiState *d = (PCIAcpiState *)pci_dev;
417 printf("register acpi io\n");
419 /* Byte access */
420 register_ioport_write(addr, 1, 1, acpiPm1Status_writeb, d);
421 register_ioport_read(addr, 1, 1, acpiPm1Status_readb, d);
422 register_ioport_write(addr+1, 1, 1, acpiPm1StatusP1_writeb, d);
423 register_ioport_read(addr+1, 1, 1, acpiPm1StatusP1_readb, d);
425 register_ioport_write(addr + 2, 1, 1, acpiPm1Enable_writeb, d);
426 register_ioport_read(addr + 2, 1, 1, acpiPm1Enable_readb, d);
427 register_ioport_write(addr + 2 +1, 1, 1, acpiPm1EnableP1_writeb, d);
428 register_ioport_read(addr + 2 +1, 1, 1, acpiPm1EnableP1_readb, d);
430 register_ioport_write(addr + 4, 1, 1, acpiPm1Control_writeb, d);
431 register_ioport_read(addr + 4, 1, 1, acpiPm1Control_readb, d);
432 register_ioport_write(addr + 4 + 1, 1, 1, acpiPm1ControlP1_writeb, d);
433 register_ioport_read(addr + 4 +1, 1, 1, acpiPm1ControlP1_readb, d);
435 /* Word access */
436 register_ioport_write(addr, 2, 2, acpiPm1Status_writew, d);
437 register_ioport_read(addr, 2, 2, acpiPm1Status_readw, d);
439 register_ioport_write(addr + 2, 2, 2, acpiPm1Enable_writew, d);
440 register_ioport_read(addr + 2, 2, 2, acpiPm1Enable_readw, d);
442 register_ioport_write(addr + 4, 2, 2, acpiPm1Control_writew, d);
443 register_ioport_read(addr + 4, 2, 2, acpiPm1Control_readw, d);
445 /* DWord access */
446 register_ioport_write(addr, 4, 4, acpiPm1Event_writel, d);
447 register_ioport_read(addr, 4, 4, acpiPm1Event_readl, d);
449 register_ioport_write(addr + 8, 4, 4, acpiPm1Timer_writel, d);
450 register_ioport_read(addr + 8, 4, 4, acpiPm1Timer_readl, d);
451 }
453 /* PIIX4 acpi pci configuration space, func 3 */
454 void pci_piix4_acpi_init(PCIBus *bus)
455 {
456 PCIAcpiState *d;
457 uint8_t *pci_conf;
459 /* register a function 3 of PIIX4 */
460 d = (PCIAcpiState *)pci_register_device(
461 bus, "PIIX4 ACPI", sizeof(PCIAcpiState),
462 ((PCIDevice *)piix3_state)->devfn + 3, NULL, NULL);
464 acpi_state = d;
465 pci_conf = d->dev.config;
466 pci_conf[0x00] = 0x86; /* Intel */
467 pci_conf[0x01] = 0x80;
468 pci_conf[0x02] = 0x13;
469 pci_conf[0x03] = 0x71;
470 pci_conf[0x08] = 0x01; /* B0 stepping */
471 pci_conf[0x09] = 0x00; /* base class */
472 pci_conf[0x0a] = 0x80; /* Sub class */
473 pci_conf[0x0b] = 0x06;
474 pci_conf[0x0e] = 0x00;
475 pci_conf[0x3d] = 0x01; /* Hardwired to PIRQA is used */
477 pci_register_io_region((PCIDevice *)d, 4, 0x10,
478 PCI_ADDRESS_SPACE_IO, acpi_map);
479 /*pmtimer_state = pmtimer_init();*/
480 acpi_reset (d);
481 }