root / hw / acpi.c @ 7ef4da1c
History | View | Annotate | Download (22 kB)
1 |
/*
|
---|---|
2 |
* ACPI implementation
|
3 |
*
|
4 |
* Copyright (c) 2006 Fabrice Bellard
|
5 |
*
|
6 |
* This library is free software; you can redistribute it and/or
|
7 |
* modify it under the terms of the GNU Lesser General Public
|
8 |
* License version 2 as published by the Free Software Foundation.
|
9 |
*
|
10 |
* This library is distributed in the hope that it will be useful,
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13 |
* Lesser General Public License for more details.
|
14 |
*
|
15 |
* You should have received a copy of the GNU Lesser General Public
|
16 |
* License along with this library; if not, write to the Free Software
|
17 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
18 |
*/
|
19 |
#include "vl.h" |
20 |
|
21 |
//#define DEBUG
|
22 |
|
23 |
/* i82731AB (PIIX4) compatible power management function */
|
24 |
#define PM_FREQ 3579545 |
25 |
|
26 |
/* XXX: make them variable */
|
27 |
#define PM_IO_BASE 0xb000 |
28 |
#define SMI_CMD_IO_ADDR 0xb040 |
29 |
#define ACPI_DBG_IO_ADDR 0xb044 |
30 |
|
31 |
typedef struct PIIX4PMState { |
32 |
PCIDevice dev; |
33 |
uint16_t pmsts; |
34 |
uint16_t pmen; |
35 |
uint16_t pmcntrl; |
36 |
QEMUTimer *tmr_timer; |
37 |
int64_t tmr_overflow_time; |
38 |
} PIIX4PMState; |
39 |
|
40 |
#define RTC_EN (1 << 10) |
41 |
#define PWRBTN_EN (1 << 8) |
42 |
#define GBL_EN (1 << 5) |
43 |
#define TMROF_EN (1 << 0) |
44 |
|
45 |
#define SCI_EN (1 << 0) |
46 |
|
47 |
#define SUS_EN (1 << 13) |
48 |
|
49 |
/* Note: only used for ACPI bios init. Could be deleted when ACPI init
|
50 |
is integrated in Bochs BIOS */
|
51 |
static PIIX4PMState *piix4_pm_state;
|
52 |
|
53 |
static uint32_t get_pmtmr(PIIX4PMState *s)
|
54 |
{ |
55 |
uint32_t d; |
56 |
d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec); |
57 |
return d & 0xffffff; |
58 |
} |
59 |
|
60 |
static int get_pmsts(PIIX4PMState *s) |
61 |
{ |
62 |
int64_t d; |
63 |
int pmsts;
|
64 |
pmsts = s->pmsts; |
65 |
d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec); |
66 |
if (d >= s->tmr_overflow_time)
|
67 |
s->pmsts |= TMROF_EN; |
68 |
return pmsts;
|
69 |
} |
70 |
|
71 |
static void pm_update_sci(PIIX4PMState *s) |
72 |
{ |
73 |
int sci_level, pmsts;
|
74 |
int64_t expire_time; |
75 |
|
76 |
pmsts = get_pmsts(s); |
77 |
sci_level = (((pmsts & s->pmen) & |
78 |
(RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
|
79 |
pci_set_irq(&s->dev, 0, sci_level);
|
80 |
/* schedule a timer interruption if needed */
|
81 |
if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) {
|
82 |
expire_time = muldiv64(s->tmr_overflow_time, ticks_per_sec, PM_FREQ); |
83 |
qemu_mod_timer(s->tmr_timer, expire_time); |
84 |
} else {
|
85 |
qemu_del_timer(s->tmr_timer); |
86 |
} |
87 |
} |
88 |
|
89 |
static void pm_tmr_timer(void *opaque) |
90 |
{ |
91 |
PIIX4PMState *s = opaque; |
92 |
pm_update_sci(s); |
93 |
} |
94 |
|
95 |
static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) |
96 |
{ |
97 |
PIIX4PMState *s = opaque; |
98 |
addr &= 0x3f;
|
99 |
switch(addr) {
|
100 |
case 0x00: |
101 |
{ |
102 |
int64_t d; |
103 |
int pmsts;
|
104 |
pmsts = get_pmsts(s); |
105 |
if (pmsts & val & TMROF_EN) {
|
106 |
/* if TMRSTS is reset, then compute the new overflow time */
|
107 |
d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec); |
108 |
s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL; |
109 |
} |
110 |
s->pmsts &= ~val; |
111 |
pm_update_sci(s); |
112 |
} |
113 |
break;
|
114 |
case 0x02: |
115 |
s->pmen = val; |
116 |
pm_update_sci(s); |
117 |
break;
|
118 |
case 0x04: |
119 |
{ |
120 |
int sus_typ;
|
121 |
s->pmcntrl = val & ~(SUS_EN); |
122 |
if (val & SUS_EN) {
|
123 |
/* change suspend type */
|
124 |
sus_typ = (val >> 10) & 3; |
125 |
switch(sus_typ) {
|
126 |
case 0: /* soft power off */ |
127 |
qemu_system_shutdown_request(); |
128 |
break;
|
129 |
default:
|
130 |
break;
|
131 |
} |
132 |
} |
133 |
} |
134 |
break;
|
135 |
default:
|
136 |
break;
|
137 |
} |
138 |
#ifdef DEBUG
|
139 |
printf("PM writew port=0x%04x val=0x%04x\n", addr, val);
|
140 |
#endif
|
141 |
} |
142 |
|
143 |
static uint32_t pm_ioport_readw(void *opaque, uint32_t addr) |
144 |
{ |
145 |
PIIX4PMState *s = opaque; |
146 |
uint32_t val; |
147 |
|
148 |
addr &= 0x3f;
|
149 |
switch(addr) {
|
150 |
case 0x00: |
151 |
val = get_pmsts(s); |
152 |
break;
|
153 |
case 0x02: |
154 |
val = s->pmen; |
155 |
break;
|
156 |
case 0x04: |
157 |
val = s->pmcntrl; |
158 |
break;
|
159 |
default:
|
160 |
val = 0;
|
161 |
break;
|
162 |
} |
163 |
#ifdef DEBUG
|
164 |
printf("PM readw port=0x%04x val=0x%04x\n", addr, val);
|
165 |
#endif
|
166 |
return val;
|
167 |
} |
168 |
|
169 |
static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val) |
170 |
{ |
171 |
// PIIX4PMState *s = opaque;
|
172 |
addr &= 0x3f;
|
173 |
#ifdef DEBUG
|
174 |
printf("PM writel port=0x%04x val=0x%08x\n", addr, val);
|
175 |
#endif
|
176 |
} |
177 |
|
178 |
static uint32_t pm_ioport_readl(void *opaque, uint32_t addr) |
179 |
{ |
180 |
PIIX4PMState *s = opaque; |
181 |
uint32_t val; |
182 |
|
183 |
addr &= 0x3f;
|
184 |
switch(addr) {
|
185 |
case 0x08: |
186 |
val = get_pmtmr(s); |
187 |
break;
|
188 |
default:
|
189 |
val = 0;
|
190 |
break;
|
191 |
} |
192 |
#ifdef DEBUG
|
193 |
printf("PM readl port=0x%04x val=0x%08x\n", addr, val);
|
194 |
#endif
|
195 |
return val;
|
196 |
} |
197 |
|
198 |
static void smi_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) |
199 |
{ |
200 |
PIIX4PMState *s = opaque; |
201 |
#ifdef DEBUG
|
202 |
printf("SMI cmd val=0x%02x\n", val);
|
203 |
#endif
|
204 |
switch(val) {
|
205 |
case 0xf0: /* ACPI disable */ |
206 |
s->pmcntrl &= ~SCI_EN; |
207 |
break;
|
208 |
case 0xf1: /* ACPI enable */ |
209 |
s->pmcntrl |= SCI_EN; |
210 |
break;
|
211 |
} |
212 |
} |
213 |
|
214 |
static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val) |
215 |
{ |
216 |
#if defined(DEBUG)
|
217 |
printf("ACPI: DBG: 0x%08x\n", val);
|
218 |
#endif
|
219 |
} |
220 |
|
221 |
/* XXX: we still add it to the PIIX3 and we count on the fact that
|
222 |
OSes are smart enough to accept this strange configuration */
|
223 |
void piix4_pm_init(PCIBus *bus)
|
224 |
{ |
225 |
PIIX4PMState *s; |
226 |
uint8_t *pci_conf; |
227 |
uint32_t pm_io_base; |
228 |
|
229 |
s = (PIIX4PMState *)pci_register_device(bus, |
230 |
"PM", sizeof(PIIX4PMState), |
231 |
((PCIDevice *)piix3_state)->devfn + 3,
|
232 |
NULL, NULL); |
233 |
pci_conf = s->dev.config; |
234 |
pci_conf[0x00] = 0x86; |
235 |
pci_conf[0x01] = 0x80; |
236 |
pci_conf[0x02] = 0x13; |
237 |
pci_conf[0x03] = 0x71; |
238 |
pci_conf[0x08] = 0x00; // revision number |
239 |
pci_conf[0x09] = 0x00; |
240 |
pci_conf[0x0a] = 0x80; // other bridge device |
241 |
pci_conf[0x0b] = 0x06; // bridge device |
242 |
pci_conf[0x0e] = 0x00; // header_type |
243 |
pci_conf[0x3d] = 0x01; // interrupt pin 1 |
244 |
pci_conf[0x60] = 0x10; // release number |
245 |
|
246 |
pm_io_base = PM_IO_BASE; |
247 |
pci_conf[0x40] = pm_io_base | 1; |
248 |
pci_conf[0x41] = pm_io_base >> 8; |
249 |
register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s); |
250 |
register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s); |
251 |
register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s); |
252 |
register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s); |
253 |
|
254 |
register_ioport_write(SMI_CMD_IO_ADDR, 1, 1, smi_cmd_writeb, s); |
255 |
register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s); |
256 |
|
257 |
s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s); |
258 |
piix4_pm_state = s; |
259 |
} |
260 |
|
261 |
/* ACPI tables */
|
262 |
/* XXX: move them in the Bochs BIOS ? */
|
263 |
|
264 |
/*************************************************/
|
265 |
|
266 |
/* Table structure from Linux kernel (the ACPI tables are under the
|
267 |
BSD license) */
|
268 |
|
269 |
#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \ |
270 |
uint8_t signature [4]; /* ACPI signature (4 ASCII characters) */\ |
271 |
uint32_t length; /* Length of table, in bytes, including header */\
|
272 |
uint8_t revision; /* ACPI Specification minor version # */\
|
273 |
uint8_t checksum; /* To make sum of entire table == 0 */\
|
274 |
uint8_t oem_id [6]; /* OEM identification */\ |
275 |
uint8_t oem_table_id [8]; /* OEM table identification */\ |
276 |
uint32_t oem_revision; /* OEM revision number */\
|
277 |
uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */\ |
278 |
uint32_t asl_compiler_revision; /* ASL compiler revision number */
|
279 |
|
280 |
|
281 |
struct acpi_table_header /* ACPI common table header */ |
282 |
{ |
283 |
ACPI_TABLE_HEADER_DEF |
284 |
}; |
285 |
|
286 |
struct rsdp_descriptor /* Root System Descriptor Pointer */ |
287 |
{ |
288 |
uint8_t signature [8]; /* ACPI signature, contains "RSD PTR " */ |
289 |
uint8_t checksum; /* To make sum of struct == 0 */
|
290 |
uint8_t oem_id [6]; /* OEM identification */ |
291 |
uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */
|
292 |
uint32_t rsdt_physical_address; /* 32-bit physical address of RSDT */
|
293 |
uint32_t length; /* XSDT Length in bytes including hdr */
|
294 |
uint64_t xsdt_physical_address; /* 64-bit physical address of XSDT */
|
295 |
uint8_t extended_checksum; /* Checksum of entire table */
|
296 |
uint8_t reserved [3]; /* Reserved field must be 0 */ |
297 |
}; |
298 |
|
299 |
/*
|
300 |
* ACPI 1.0 Root System Description Table (RSDT)
|
301 |
*/
|
302 |
struct rsdt_descriptor_rev1
|
303 |
{ |
304 |
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
305 |
uint32_t table_offset_entry [2]; /* Array of pointers to other */ |
306 |
/* ACPI tables */
|
307 |
}; |
308 |
|
309 |
/*
|
310 |
* ACPI 1.0 Firmware ACPI Control Structure (FACS)
|
311 |
*/
|
312 |
struct facs_descriptor_rev1
|
313 |
{ |
314 |
uint8_t signature[4]; /* ACPI Signature */ |
315 |
uint32_t length; /* Length of structure, in bytes */
|
316 |
uint32_t hardware_signature; /* Hardware configuration signature */
|
317 |
uint32_t firmware_waking_vector; /* ACPI OS waking vector */
|
318 |
uint32_t global_lock; /* Global Lock */
|
319 |
uint32_t S4bios_f : 1; /* Indicates if S4BIOS support is present */ |
320 |
uint32_t reserved1 : 31; /* Must be 0 */ |
321 |
uint8_t resverved3 [40]; /* Reserved - must be zero */ |
322 |
}; |
323 |
|
324 |
|
325 |
/*
|
326 |
* ACPI 1.0 Fixed ACPI Description Table (FADT)
|
327 |
*/
|
328 |
struct fadt_descriptor_rev1
|
329 |
{ |
330 |
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
331 |
uint32_t firmware_ctrl; /* Physical address of FACS */
|
332 |
uint32_t dsdt; /* Physical address of DSDT */
|
333 |
uint8_t model; /* System Interrupt Model */
|
334 |
uint8_t reserved1; /* Reserved */
|
335 |
uint16_t sci_int; /* System vector of SCI interrupt */
|
336 |
uint32_t smi_cmd; /* Port address of SMI command port */
|
337 |
uint8_t acpi_enable; /* Value to write to smi_cmd to enable ACPI */
|
338 |
uint8_t acpi_disable; /* Value to write to smi_cmd to disable ACPI */
|
339 |
uint8_t S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */
|
340 |
uint8_t reserved2; /* Reserved - must be zero */
|
341 |
uint32_t pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
|
342 |
uint32_t pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
|
343 |
uint32_t pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
|
344 |
uint32_t pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
|
345 |
uint32_t pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
|
346 |
uint32_t pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
|
347 |
uint32_t gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
|
348 |
uint32_t gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */
|
349 |
uint8_t pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */
|
350 |
uint8_t pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */
|
351 |
uint8_t pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */
|
352 |
uint8_t pm_tmr_len; /* Byte Length of ports at pm_tm_blk */
|
353 |
uint8_t gpe0_blk_len; /* Byte Length of ports at gpe0_blk */
|
354 |
uint8_t gpe1_blk_len; /* Byte Length of ports at gpe1_blk */
|
355 |
uint8_t gpe1_base; /* Offset in gpe model where gpe1 events start */
|
356 |
uint8_t reserved3; /* Reserved */
|
357 |
uint16_t plvl2_lat; /* Worst case HW latency to enter/exit C2 state */
|
358 |
uint16_t plvl3_lat; /* Worst case HW latency to enter/exit C3 state */
|
359 |
uint16_t flush_size; /* Size of area read to flush caches */
|
360 |
uint16_t flush_stride; /* Stride used in flushing caches */
|
361 |
uint8_t duty_offset; /* Bit location of duty cycle field in p_cnt reg */
|
362 |
uint8_t duty_width; /* Bit width of duty cycle field in p_cnt reg */
|
363 |
uint8_t day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */
|
364 |
uint8_t mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */
|
365 |
uint8_t century; /* Index to century in RTC CMOS RAM */
|
366 |
uint8_t reserved4; /* Reserved */
|
367 |
uint8_t reserved4a; /* Reserved */
|
368 |
uint8_t reserved4b; /* Reserved */
|
369 |
#if 0
|
370 |
uint32_t wb_invd : 1; /* The wbinvd instruction works properly */
|
371 |
uint32_t wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */
|
372 |
uint32_t proc_c1 : 1; /* All processors support C1 state */
|
373 |
uint32_t plvl2_up : 1; /* C2 state works on MP system */
|
374 |
uint32_t pwr_button : 1; /* Power button is handled as a generic feature */
|
375 |
uint32_t sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */
|
376 |
uint32_t fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */
|
377 |
uint32_t rtcs4 : 1; /* RTC wakeup stat not possible from S4 */
|
378 |
uint32_t tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */
|
379 |
uint32_t reserved5 : 23; /* Reserved - must be zero */
|
380 |
#else
|
381 |
uint32_t flags; |
382 |
#endif
|
383 |
}; |
384 |
|
385 |
/*
|
386 |
* MADT values and structures
|
387 |
*/
|
388 |
|
389 |
/* Values for MADT PCATCompat */
|
390 |
|
391 |
#define DUAL_PIC 0 |
392 |
#define MULTIPLE_APIC 1 |
393 |
|
394 |
|
395 |
/* Master MADT */
|
396 |
|
397 |
struct multiple_apic_table
|
398 |
{ |
399 |
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
|
400 |
uint32_t local_apic_address; /* Physical address of local APIC */
|
401 |
#if 0
|
402 |
uint32_t PCATcompat : 1; /* A one indicates system also has dual 8259s */
|
403 |
uint32_t reserved1 : 31;
|
404 |
#else
|
405 |
uint32_t flags; |
406 |
#endif
|
407 |
}; |
408 |
|
409 |
|
410 |
/* Values for Type in APIC_HEADER_DEF */
|
411 |
|
412 |
#define APIC_PROCESSOR 0 |
413 |
#define APIC_IO 1 |
414 |
#define APIC_XRUPT_OVERRIDE 2 |
415 |
#define APIC_NMI 3 |
416 |
#define APIC_LOCAL_NMI 4 |
417 |
#define APIC_ADDRESS_OVERRIDE 5 |
418 |
#define APIC_IO_SAPIC 6 |
419 |
#define APIC_LOCAL_SAPIC 7 |
420 |
#define APIC_XRUPT_SOURCE 8 |
421 |
#define APIC_RESERVED 9 /* 9 and greater are reserved */ |
422 |
|
423 |
/*
|
424 |
* MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
|
425 |
*/
|
426 |
#define APIC_HEADER_DEF /* Common APIC sub-structure header */\ |
427 |
uint8_t type; \ |
428 |
uint8_t length; |
429 |
|
430 |
/* Sub-structures for MADT */
|
431 |
|
432 |
struct madt_processor_apic
|
433 |
{ |
434 |
APIC_HEADER_DEF |
435 |
uint8_t processor_id; /* ACPI processor id */
|
436 |
uint8_t local_apic_id; /* Processor's local APIC id */
|
437 |
#if 0
|
438 |
uint32_t processor_enabled: 1; /* Processor is usable if set */
|
439 |
uint32_t reserved2 : 31; /* Reserved, must be zero */
|
440 |
#else
|
441 |
uint32_t flags; |
442 |
#endif
|
443 |
}; |
444 |
|
445 |
struct madt_io_apic
|
446 |
{ |
447 |
APIC_HEADER_DEF |
448 |
uint8_t io_apic_id; /* I/O APIC ID */
|
449 |
uint8_t reserved; /* Reserved - must be zero */
|
450 |
uint32_t address; /* APIC physical address */
|
451 |
uint32_t interrupt; /* Global system interrupt where INTI
|
452 |
* lines start */
|
453 |
}; |
454 |
|
455 |
#include "acpi-dsdt.hex" |
456 |
|
457 |
static int acpi_checksum(const uint8_t *data, int len) |
458 |
{ |
459 |
int sum, i;
|
460 |
sum = 0;
|
461 |
for(i = 0; i < len; i++) |
462 |
sum += data[i]; |
463 |
return (-sum) & 0xff; |
464 |
} |
465 |
|
466 |
static void acpi_build_table_header(struct acpi_table_header *h, |
467 |
char *sig, int len) |
468 |
{ |
469 |
memcpy(h->signature, sig, 4);
|
470 |
h->length = cpu_to_le32(len); |
471 |
h->revision = 0;
|
472 |
memcpy(h->oem_id, "QEMU ", 6); |
473 |
memcpy(h->oem_table_id, "QEMU", 4); |
474 |
memcpy(h->oem_table_id + 4, sig, 4); |
475 |
h->oem_revision = cpu_to_le32(1);
|
476 |
memcpy(h->asl_compiler_id, "QEMU", 4); |
477 |
h->asl_compiler_revision = cpu_to_le32(1);
|
478 |
h->checksum = acpi_checksum((void *)h, len);
|
479 |
} |
480 |
|
481 |
#define ACPI_TABLES_BASE 0x000e8000 |
482 |
|
483 |
/* base_addr must be a multiple of 4KB */
|
484 |
void acpi_bios_init(void) |
485 |
{ |
486 |
struct rsdp_descriptor *rsdp;
|
487 |
struct rsdt_descriptor_rev1 *rsdt;
|
488 |
struct fadt_descriptor_rev1 *fadt;
|
489 |
struct facs_descriptor_rev1 *facs;
|
490 |
struct multiple_apic_table *madt;
|
491 |
uint8_t *dsdt; |
492 |
uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr; |
493 |
uint32_t pm_io_base, acpi_tables_size, madt_addr, madt_size; |
494 |
int i;
|
495 |
|
496 |
/* compute PCI I/O addresses */
|
497 |
pm_io_base = (piix4_pm_state->dev.config[0x40] |
|
498 |
(piix4_pm_state->dev.config[0x41] << 8)) & ~0x3f; |
499 |
|
500 |
base_addr = ACPI_TABLES_BASE; |
501 |
|
502 |
/* reserve memory space for tables */
|
503 |
addr = base_addr; |
504 |
rsdp = (void *)(phys_ram_base + addr);
|
505 |
addr += sizeof(*rsdp);
|
506 |
|
507 |
rsdt_addr = addr; |
508 |
rsdt = (void *)(phys_ram_base + addr);
|
509 |
addr += sizeof(*rsdt);
|
510 |
|
511 |
fadt_addr = addr; |
512 |
fadt = (void *)(phys_ram_base + addr);
|
513 |
addr += sizeof(*fadt);
|
514 |
|
515 |
/* XXX: FACS should be in RAM */
|
516 |
addr = (addr + 63) & ~63; /* 64 byte alignment for FACS */ |
517 |
facs_addr = addr; |
518 |
facs = (void *)(phys_ram_base + addr);
|
519 |
addr += sizeof(*facs);
|
520 |
|
521 |
dsdt_addr = addr; |
522 |
dsdt = (void *)(phys_ram_base + addr);
|
523 |
addr += sizeof(AmlCode);
|
524 |
|
525 |
madt_addr = addr; |
526 |
madt_size = sizeof(*madt) +
|
527 |
sizeof(struct madt_processor_apic) * smp_cpus + |
528 |
sizeof(struct madt_io_apic); |
529 |
madt = (void *)(phys_ram_base + addr);
|
530 |
addr += madt_size; |
531 |
|
532 |
acpi_tables_size = addr - base_addr; |
533 |
|
534 |
cpu_register_physical_memory(base_addr, acpi_tables_size, |
535 |
base_addr | IO_MEM_ROM); |
536 |
|
537 |
/* RSDP */
|
538 |
memset(rsdp, 0, sizeof(*rsdp)); |
539 |
memcpy(rsdp->signature, "RSD PTR ", 8); |
540 |
memcpy(rsdp->oem_id, "QEMU ", 6); |
541 |
rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr); |
542 |
rsdp->checksum = acpi_checksum((void *)rsdp, 20); |
543 |
|
544 |
/* RSDT */
|
545 |
rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
|
546 |
rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
|
547 |
acpi_build_table_header((struct acpi_table_header *)rsdt,
|
548 |
"RSDT", sizeof(*rsdt)); |
549 |
|
550 |
/* FADT */
|
551 |
memset(fadt, 0, sizeof(*fadt)); |
552 |
fadt->firmware_ctrl = cpu_to_le32(facs_addr); |
553 |
fadt->dsdt = cpu_to_le32(dsdt_addr); |
554 |
fadt->model = 1;
|
555 |
fadt->reserved1 = 0;
|
556 |
fadt->sci_int = cpu_to_le16(piix4_pm_state->dev.config[0x3c]);
|
557 |
fadt->smi_cmd = cpu_to_le32(SMI_CMD_IO_ADDR); |
558 |
fadt->acpi_enable = 0xf1;
|
559 |
fadt->acpi_disable = 0xf0;
|
560 |
fadt->pm1a_evt_blk = cpu_to_le32(pm_io_base); |
561 |
fadt->pm1a_cnt_blk = cpu_to_le32(pm_io_base + 0x04);
|
562 |
fadt->pm_tmr_blk = cpu_to_le32(pm_io_base + 0x08);
|
563 |
fadt->pm1_evt_len = 4;
|
564 |
fadt->pm1_cnt_len = 2;
|
565 |
fadt->pm_tmr_len = 4;
|
566 |
fadt->plvl2_lat = cpu_to_le16(50);
|
567 |
fadt->plvl3_lat = cpu_to_le16(50);
|
568 |
fadt->plvl3_lat = cpu_to_le16(50);
|
569 |
/* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */
|
570 |
fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6)); |
571 |
acpi_build_table_header((struct acpi_table_header *)fadt, "FACP", |
572 |
sizeof(*fadt));
|
573 |
|
574 |
/* FACS */
|
575 |
memset(facs, 0, sizeof(*facs)); |
576 |
memcpy(facs->signature, "FACS", 4); |
577 |
facs->length = cpu_to_le32(sizeof(*facs));
|
578 |
|
579 |
/* DSDT */
|
580 |
memcpy(dsdt, AmlCode, sizeof(AmlCode));
|
581 |
|
582 |
/* MADT */
|
583 |
{ |
584 |
struct madt_processor_apic *apic;
|
585 |
struct madt_io_apic *io_apic;
|
586 |
|
587 |
memset(madt, 0, madt_size);
|
588 |
madt->local_apic_address = cpu_to_le32(0xfee00000);
|
589 |
madt->flags = cpu_to_le32(1);
|
590 |
apic = (void *)(madt + 1); |
591 |
for(i=0;i<smp_cpus;i++) { |
592 |
apic->type = APIC_PROCESSOR; |
593 |
apic->length = sizeof(*apic);
|
594 |
apic->processor_id = i; |
595 |
apic->local_apic_id = i; |
596 |
apic->flags = cpu_to_le32(1);
|
597 |
apic++; |
598 |
} |
599 |
io_apic = (void *)apic;
|
600 |
io_apic->type = APIC_IO; |
601 |
io_apic->length = sizeof(*io_apic);
|
602 |
io_apic->io_apic_id = smp_cpus; |
603 |
io_apic->address = cpu_to_le32(0xfec00000);
|
604 |
io_apic->interrupt = cpu_to_le32(0);
|
605 |
|
606 |
acpi_build_table_header((struct acpi_table_header *)madt,
|
607 |
"APIC", madt_size);
|
608 |
} |
609 |
} |