direct-io.hg

view tools/ioemu/hw/piix4acpi.c @ 12390:430e06e2aa08

[HVM][IA64] Due to IPF Guest Firmware will enumerate PCI, shutdown in
IPF doesn't work This patch makes shutdown work for IPF.

Signed-off-by, Anthony Xu <anthony.xu@intel.com>
author kfraser@localhost.localdomain
date Mon Nov 13 14:20:26 2006 +0000 (2006-11-13)
parents 27bef4f3c1d3
children 9a341c6ef6ae
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 3579545
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 typedef struct PM1Event_BLK {
56 uint16_t pm1_status; /* pm1a_EVT_BLK */
57 uint16_t pm1_enable; /* pm1a_EVT_BLK+2 */
58 }PM1Event_BLK;
60 typedef struct PCIAcpiState {
61 PCIDevice dev;
62 uint16_t irq;
63 uint16_t pm1_status; /* pm1a_EVT_BLK */
64 uint16_t pm1_enable; /* pm1a_EVT_BLK+2 */
65 uint16_t pm1_control; /* pm1a_ECNT_BLK */
66 uint32_t pm1_timer; /* pmtmr_BLK */
67 uint64_t old_vmck_ticks; /* using vm_clock counter */
68 } PCIAcpiState;
70 static PCIAcpiState *acpi_state;
72 static void acpi_reset(PCIAcpiState *s)
73 {
74 uint8_t *pci_conf;
75 pci_conf = s->dev.config;
77 pci_conf[0x42] = 0x00;
78 pci_conf[0x43] = 0x00;
79 s->irq = 9;
80 s->pm1_status = 0;
81 s->pm1_enable = 0x00; /* TMROF_EN should cleared */
82 s->pm1_control = SCI_EN; /* SCI_EN */
83 s->pm1_timer = 0;
84 s->old_vmck_ticks = qemu_get_clock(vm_clock);
85 }
87 /*byte access */
88 static void acpiPm1Status_writeb(void *opaque, uint32_t addr, uint32_t val)
89 {
90 PCIAcpiState *s = opaque;
92 if ((val&TMROF_STS)==TMROF_STS)
93 s->pm1_status = s->pm1_status&!TMROF_STS;
95 if ((val&GBL_STS)==GBL_STS)
96 s->pm1_status = s->pm1_status&!GBL_STS;
98 /* printf("acpiPm1Status_writeb \n addr %x val:%x pm1_status:%x \n", addr, val,s->pm1_status); */
99 }
101 static uint32_t acpiPm1Status_readb(void *opaque, uint32_t addr)
102 {
103 PCIAcpiState *s = opaque;
104 uint32_t val;
106 val = s->pm1_status;
107 /* printf("acpiPm1Status_readb \n addr %x val:%x\n", addr, val); */
109 return val;
110 }
112 static void acpiPm1StatusP1_writeb(void *opaque, uint32_t addr, uint32_t val)
113 {
114 PCIAcpiState *s = opaque;
116 s->pm1_status = (val<<8)||(s->pm1_status);
117 /* printf("acpiPm1StatusP1_writeb \n addr %x val:%x\n", addr, val); */
118 }
120 static uint32_t acpiPm1StatusP1_readb(void *opaque, uint32_t addr)
121 {
122 PCIAcpiState *s = opaque;
123 uint32_t val;
125 val = (s->pm1_status)>>8;
126 printf("acpiPm1StatusP1_readb \n addr %x val:%x\n", addr, val);
128 return val;
129 }
131 static void acpiPm1Enable_writeb(void *opaque, uint32_t addr, uint32_t val)
132 {
133 PCIAcpiState *s = opaque;
135 s->pm1_enable = val;
136 /* printf("acpiPm1Enable_writeb \n addr %x val:%x\n", addr, val); */
137 }
139 static uint32_t acpiPm1Enable_readb(void *opaque, uint32_t addr)
140 {
141 PCIAcpiState *s = opaque;
142 uint32_t val;
144 val = (s->pm1_enable)||0x1;
145 /* printf("acpiPm1Enable_readb \n addr %x val:%x\n", addr, val); */
147 return val;
148 }
150 static void acpiPm1EnableP1_writeb(void *opaque, uint32_t addr, uint32_t val)
151 {
152 PCIAcpiState *s = opaque;
154 s->pm1_enable = (val<<8)||(s->pm1_enable);
155 /* printf("acpiPm1EnableP1_writeb \n addr %x val:%x\n", addr, val); */
157 }
159 static uint32_t acpiPm1EnableP1_readb(void *opaque, uint32_t addr)
160 {
161 PCIAcpiState *s = opaque;
162 uint32_t val;
164 val = (s->pm1_enable)>>8;
165 /* printf("acpiPm1EnableP1_readb \n addr %x val:%x\n", addr, val); */
167 return val;
168 }
170 static void acpiPm1Control_writeb(void *opaque, uint32_t addr, uint32_t val)
171 {
172 PCIAcpiState *s = opaque;
174 s->pm1_control = val;
175 /* printf("acpiPm1Control_writeb \n addr %x val:%x\n", addr, val); */
177 }
179 static uint32_t acpiPm1Control_readb(void *opaque, uint32_t addr)
180 {
181 PCIAcpiState *s = opaque;
182 uint32_t val;
184 val = s->pm1_control;
185 /* printf("acpiPm1Control_readb \n addr %x val:%x\n", addr, val); */
187 return val;
188 }
190 static void acpiPm1ControlP1_writeb(void *opaque, uint32_t addr, uint32_t val)
191 {
192 PCIAcpiState *s = opaque;
194 s->pm1_control = (val<<8)||(s->pm1_control);
195 /* printf("acpiPm1ControlP1_writeb \n addr %x val:%x\n", addr, val); */
197 // Check for power off request
199 if (((val & SLP_EN) != 0) &&
200 ((val & SLP_TYP_MASK) == SLP_VAL)) {
201 s->pm1_timer=0x0; //clear ACPI timer
202 qemu_system_shutdown_request();
203 }
204 }
206 static uint32_t acpiPm1ControlP1_readb(void *opaque, uint32_t addr)
207 {
208 PCIAcpiState *s = opaque;
209 uint32_t val;
211 val = (s->pm1_control)>>8;
212 /* printf("acpiPm1ControlP1_readb \n addr %x val:%x\n", addr, val); */
214 return val;
215 }
218 /* word access */
220 static void acpiPm1Status_writew(void *opaque, uint32_t addr, uint32_t val)
221 {
222 PCIAcpiState *s = opaque;
224 if ((val&TMROF_STS)==TMROF_STS)
225 s->pm1_status = s->pm1_status&!TMROF_STS;
227 if ((val&GBL_STS)==GBL_STS)
228 s->pm1_status = s->pm1_status&!GBL_STS;
230 /* printf("acpiPm1Status_writew \n addr %x val:%x pm1_status:%x \n", addr, val,s->pm1_status); */
231 }
233 static uint32_t acpiPm1Status_readw(void *opaque, uint32_t addr)
234 {
235 PCIAcpiState *s = opaque;
236 uint32_t val;
238 val = s->pm1_status;
239 /* printf("acpiPm1Status_readw \n addr %x val:%x\n", addr, val); */
241 return val;
242 }
244 static void acpiPm1Enable_writew(void *opaque, uint32_t addr, uint32_t val)
245 {
246 PCIAcpiState *s = opaque;
248 s->pm1_enable = val;
249 /* printf("acpiPm1Enable_writew \n addr %x val:%x\n", addr, val); */
251 }
253 static uint32_t acpiPm1Enable_readw(void *opaque, uint32_t addr)
254 {
255 PCIAcpiState *s = opaque;
256 uint32_t val;
258 val = s->pm1_enable;
259 /* printf("acpiPm1Enable_readw \n addr %x val:%x\n", addr, val); */
261 return val;
262 }
264 static void acpiPm1Control_writew(void *opaque, uint32_t addr, uint32_t val)
265 {
266 PCIAcpiState *s = opaque;
268 s->pm1_control = val;
269 /* printf("acpiPm1Control_writew \n addr %x val:%x\n", addr, val); */
271 // Check for power off request
273 if (((val & SLP_EN) != 0) &&
274 ((val & SLP_TYP_MASK) == SLP_VAL)) {
275 qemu_system_shutdown_request();
276 }
278 }
280 static uint32_t acpiPm1Control_readw(void *opaque, uint32_t addr)
281 {
282 PCIAcpiState *s = opaque;
283 uint32_t val;
285 val = s->pm1_control;
286 /* printf("acpiPm1Control_readw \n addr %x val:%x\n", addr, val); */
288 return val;
289 }
291 /* dword access */
293 static void acpiPm1Event_writel(void *opaque, uint32_t addr, uint32_t val)
294 {
295 PCIAcpiState *s = opaque;
297 s->pm1_status = val;
298 s->pm1_enable = val>>16;
299 /* printf("acpiPm1Event_writel \n addr %x val:%x \n", addr, val); */
301 }
303 static uint32_t acpiPm1Event_readl(void *opaque, uint32_t addr)
304 {
305 PCIAcpiState *s = opaque;
306 uint32_t val;
308 val = s->pm1_status|(s->pm1_enable<<16);
309 /* printf("acpiPm1Event_readl \n addr %x val:%x\n", addr, val); */
311 return val;
312 }
314 static void acpiPm1Timer_writel(void *opaque, uint32_t addr, uint32_t val)
315 {
316 PCIAcpiState *s = opaque;
318 s->pm1_timer = val;
319 s->old_vmck_ticks = qemu_get_clock(vm_clock) +
320 muldiv64(val, FREQUENCE_PMTIMER, ticks_per_sec);
321 }
323 static uint32_t acpiPm1Timer_readl(void *opaque, uint32_t addr)
324 {
325 PCIAcpiState *s = opaque;
326 int64_t current_vmck_ticks = qemu_get_clock(vm_clock);
327 int64_t vmck_ticks_delta = current_vmck_ticks - s->old_vmck_ticks;
329 if (s->old_vmck_ticks)
330 s->pm1_timer += muldiv64(vmck_ticks_delta, FREQUENCE_PMTIMER,
331 ticks_per_sec);
332 s->old_vmck_ticks = current_vmck_ticks;
333 return s->pm1_timer;
334 }
336 static void acpi_map(PCIDevice *pci_dev, int region_num,
337 uint32_t addr, uint32_t size, int type)
338 {
339 PCIAcpiState *d = (PCIAcpiState *)pci_dev;
341 printf("register acpi io\n");
343 /* Byte access */
344 register_ioport_write(addr, 1, 1, acpiPm1Status_writeb, d);
345 register_ioport_read(addr, 1, 1, acpiPm1Status_readb, d);
346 register_ioport_write(addr+1, 1, 1, acpiPm1StatusP1_writeb, d);
347 register_ioport_read(addr+1, 1, 1, acpiPm1StatusP1_readb, d);
349 register_ioport_write(addr + 2, 1, 1, acpiPm1Enable_writeb, d);
350 register_ioport_read(addr + 2, 1, 1, acpiPm1Enable_readb, d);
351 register_ioport_write(addr + 2 +1, 1, 1, acpiPm1EnableP1_writeb, d);
352 register_ioport_read(addr + 2 +1, 1, 1, acpiPm1EnableP1_readb, d);
354 register_ioport_write(addr + 4, 1, 1, acpiPm1Control_writeb, d);
355 register_ioport_read(addr + 4, 1, 1, acpiPm1Control_readb, d);
356 register_ioport_write(addr + 4 + 1, 1, 1, acpiPm1ControlP1_writeb, d);
357 register_ioport_read(addr + 4 +1, 1, 1, acpiPm1ControlP1_readb, d);
359 /* Word access */
360 register_ioport_write(addr, 2, 2, acpiPm1Status_writew, d);
361 register_ioport_read(addr, 2, 2, acpiPm1Status_readw, d);
363 register_ioport_write(addr + 2, 2, 2, acpiPm1Enable_writew, d);
364 register_ioport_read(addr + 2, 2, 2, acpiPm1Enable_readw, d);
366 register_ioport_write(addr + 4, 2, 2, acpiPm1Control_writew, d);
367 register_ioport_read(addr + 4, 2, 2, acpiPm1Control_readw, d);
369 /* DWord access */
370 register_ioport_write(addr, 4, 4, acpiPm1Event_writel, d);
371 register_ioport_read(addr, 4, 4, acpiPm1Event_readl, d);
373 register_ioport_write(addr + 8, 4, 4, acpiPm1Timer_writel, d);
374 register_ioport_read(addr + 8, 4, 4, acpiPm1Timer_readl, d);
375 }
377 /* PIIX4 acpi pci configuration space, func 2 */
378 void pci_piix4_acpi_init(PCIBus *bus, int devfn)
379 {
380 PCIAcpiState *d;
381 uint8_t *pci_conf;
383 /* register a function 2 of PIIX4 */
384 d = (PCIAcpiState *)pci_register_device(
385 bus, "PIIX4 ACPI", sizeof(PCIAcpiState),
386 devfn, NULL, NULL);
388 acpi_state = d;
389 pci_conf = d->dev.config;
390 pci_conf[0x00] = 0x86; /* Intel */
391 pci_conf[0x01] = 0x80;
392 pci_conf[0x02] = 0x13;
393 pci_conf[0x03] = 0x71;
394 pci_conf[0x08] = 0x01; /* B0 stepping */
395 pci_conf[0x09] = 0x00; /* base class */
396 pci_conf[0x0a] = 0x80; /* Sub class */
397 pci_conf[0x0b] = 0x06;
398 pci_conf[0x0e] = 0x00;
399 pci_conf[0x3d] = 0x01; /* Hardwired to PIRQA is used */
402 /* PMBA POWER MANAGEMENT BASE ADDRESS, hardcoded to 0x1f40
403 * to make shutdown work for IPF, due to IPF Guest Firmware
404 * will enumerate pci devices.
405 *
406 * TODO: if Guest Firmware or Guest OS will change this PMBA,
407 * More logic will be added.
408 */
409 pci_conf[0x40] = 0x41;
410 pci_conf[0x41] = 0x1f;
411 acpi_map(d, 0, 0x1f40, 0x10, PCI_ADDRESS_SPACE_IO);
412 acpi_reset(d);
413 }