5 #include "arch_proto.h"
7 typedef int ((* acpi_read_t
)(phys_bytes addr
, void * buff
, size_t size
));
9 struct acpi_rsdp acpi_rsdp
;
11 static acpi_read_t read_func
;
13 #define MAX_RSDT 35 /* ACPI defines 35 signatures */
14 #define SLP_EN_CODE (1 << 13) /* ACPI SLP_EN_CODE code */
15 #define AMI_PACKAGE_OP_CODE (0x12)
16 #define AMI_NAME_OP_CODE (0x8)
17 #define AMI_BYTE_PREFIX_CODE (0xA)
18 #define AMI_PACKAGE_LENGTH_ENCODING_BITS_MASK (0xC0)
19 #define AMI_PACKAGE_LENGTH_ENCODING_BITS_SHIFT (6)
20 #define AMI_MIN_PACKAGE_LENGTH (1)
21 #define AMI_NUM_ELEMENTS_LENGTH (1)
22 #define AMI_SLP_TYPA_SHIFT (10)
23 #define AMI_SLP_TYPB_SHIFT (10)
24 #define AMI_S5_NAME_OP_OFFSET_1 (-1)
25 #define AMI_S5_NAME_OP_OFFSET_2 (-2)
26 #define AMI_S5_PACKAGE_OP_OFFSET (4)
27 #define AMI_S5_PACKET_LENGTH_OFFSET (5)
29 static struct acpi_rsdt
{
30 struct acpi_sdt_header hdr
;
35 char signature
[ACPI_SDT_SIGNATURE_LEN
+ 1];
37 } sdt_trans
[MAX_RSDT
];
40 static u16_t pm1a_cnt_blk
= 0;
41 static u16_t pm1b_cnt_blk
= 0;
42 static u16_t slp_typa
= 0;
43 static u16_t slp_typb
= 0;
45 static int acpi_check_csum(struct acpi_sdt_header
* tb
, size_t size
)
49 for (i
= 0; i
< size
; i
++)
50 total
+= ((unsigned char *)tb
)[i
];
51 return total
== 0 ? 0 : -1;
54 static int acpi_check_signature(const char * orig
, const char * match
)
56 return strncmp(orig
, match
, ACPI_SDT_SIGNATURE_LEN
);
59 static u32_t
acpi_phys2vir(u32_t p
)
62 DEBUGEXTRA(("acpi: returning 0x%lx as vir addr\n", p
));
65 panic("acpi: can't get virtual address of arbitrary physical address");
68 static int acpi_phys_copy(phys_bytes phys
, void *target
, size_t len
)
71 memcpy(target
, (void *) phys
, len
);
74 panic("can't acpi_phys_copy with vm");
77 static int acpi_read_sdt_at(phys_bytes addr
,
78 struct acpi_sdt_header
* tb
,
82 struct acpi_sdt_header hdr
;
84 /* if NULL is supplied, we only return the size of the table */
86 if (read_func(addr
, &hdr
, sizeof(struct acpi_sdt_header
))) {
87 printf("ERROR acpi cannot read %s header\n", name
);
94 if (read_func(addr
, tb
, sizeof(struct acpi_sdt_header
))) {
95 printf("ERROR acpi cannot read %s header\n", name
);
99 if (acpi_check_signature(tb
->signature
, name
)) {
100 printf("ERROR acpi %s signature does not match\n", name
);
104 if (size
< tb
->length
) {
105 printf("ERROR acpi buffer too small for %s\n", name
);
109 if (read_func(addr
, tb
, size
)) {
110 printf("ERROR acpi cannot read %s\n", name
);
114 if (acpi_check_csum(tb
, tb
->length
)) {
115 printf("ERROR acpi %s checksum does not match\n", name
);
122 phys_bytes
acpi_get_table_base(const char * name
)
126 for(i
= 0; i
< sdt_count
; i
++) {
127 if (strncmp(name
, sdt_trans
[i
].signature
,
128 ACPI_SDT_SIGNATURE_LEN
) == 0)
129 return (phys_bytes
) rsdt
.data
[i
];
132 return (phys_bytes
) NULL
;
135 size_t acpi_get_table_length(const char * name
)
139 for(i
= 0; i
< sdt_count
; i
++) {
140 if (strncmp(name
, sdt_trans
[i
].signature
,
141 ACPI_SDT_SIGNATURE_LEN
) == 0)
142 return sdt_trans
[i
].length
;
148 static void * acpi_madt_get_typed_item(struct acpi_madt_hdr
* hdr
,
155 t
= (u8_t
*) hdr
+ sizeof(struct acpi_madt_hdr
);
156 end
= (u8_t
*) hdr
+ hdr
->hdr
.length
;
160 if (type
== ((struct acpi_madt_item_hdr
*) t
)->type
) {
166 t
+= ((struct acpi_madt_item_hdr
*) t
)->length
;
173 static void * acpi_madt_get_item(struct acpi_madt_hdr
* hdr
,
179 t
= (u8_t
*) hdr
+ sizeof(struct acpi_madt_hdr
);
180 end
= (u8_t
*) hdr
+ hdr
->hdr
.length
;
182 for(i
= 0 ; i
<= idx
&& t
< end
; i
++) {
185 t
+= ((struct acpi_madt_item_hdr
*) t
)->length
;
192 static int acpi_rsdp_test(void * buff
)
194 struct acpi_rsdp
* rsdp
= (struct acpi_rsdp
*) buff
;
196 if (!platform_tbl_checksum_ok(buff
, 20))
198 if (strncmp(rsdp
->signature
, "RSD PTR ", 8))
204 static int get_acpi_rsdp(void)
208 * Read 40:0Eh - to find the starting address of the EBDA.
210 acpi_phys_copy (0x40E, &ebda
, sizeof(ebda
));
213 if(platform_tbl_ptr(ebda
, ebda
+ 0x400, 16, &acpi_rsdp
,
214 sizeof(acpi_rsdp
), &machine
.acpi_rsdp
,
219 /* try BIOS read only mem space */
220 if(platform_tbl_ptr(0xE0000, 0x100000, 16, &acpi_rsdp
,
221 sizeof(acpi_rsdp
), &machine
.acpi_rsdp
,
225 machine
.acpi_rsdp
= 0; /* RSDP cannot be found at this address therefore
226 it is a valid negative value */
230 static void acpi_init_poweroff(void)
235 struct acpi_fadt_header
*fadt_header
= NULL
;
236 struct acpi_rsdt
* dsdt_header
= NULL
;
239 /* Everything used here existed since ACPI spec 1.0 */
240 /* So we can safely use them */
241 fadt_header
= (struct acpi_fadt_header
*)
242 acpi_phys2vir(acpi_get_table_base("FACP"));
243 if (fadt_header
== NULL
) {
244 msg
= "Could not load FACP";
248 dsdt_header
= (struct acpi_rsdt
*)
249 acpi_phys2vir((phys_bytes
) fadt_header
->dsdt
);
250 if (dsdt_header
== NULL
) {
251 msg
= "Could not load DSDT";
255 pm1a_cnt_blk
= fadt_header
->pm1a_cnt_blk
;
256 pm1b_cnt_blk
= fadt_header
->pm1b_cnt_blk
;
258 ptr
= start
= (u8_t
*) dsdt_header
->data
;
259 end
= start
+ dsdt_header
->hdr
.length
- 4;
261 /* See http://forum.osdev.org/viewtopic.php?t=16990 */
262 /* for layout of \_S5 */
263 while (ptr
< end
&& memcmp(ptr
, "_S5_", 4) != 0)
266 msg
= "Could not read S5 data. Use default SLP_TYPa and SLP_TYPb";
267 if (ptr
>= end
|| ptr
== start
)
270 /* validate AML structure */
271 if (*(ptr
+ AMI_S5_PACKAGE_OP_OFFSET
) != AMI_PACKAGE_OP_CODE
)
274 if ((ptr
< start
+ (-AMI_S5_NAME_OP_OFFSET_2
) ||
275 (*(ptr
+ AMI_S5_NAME_OP_OFFSET_2
) != AMI_NAME_OP_CODE
||
276 *(ptr
+ AMI_S5_NAME_OP_OFFSET_2
+ 1) != '\\')) &&
277 *(ptr
+ AMI_S5_NAME_OP_OFFSET_1
) != AMI_NAME_OP_CODE
)
280 ptr
+= AMI_S5_PACKET_LENGTH_OFFSET
;
285 ptr
+= ((*ptr
& AMI_PACKAGE_LENGTH_ENCODING_BITS_MASK
) >>
286 AMI_PACKAGE_LENGTH_ENCODING_BITS_SHIFT
) +
287 AMI_MIN_PACKAGE_LENGTH
+ AMI_NUM_ELEMENTS_LENGTH
;
291 if (*ptr
== AMI_BYTE_PREFIX_CODE
)
292 ptr
++; /* skip byte prefix */
294 slp_typa
= (*ptr
) << AMI_SLP_TYPA_SHIFT
;
296 ptr
++; /* move to SLP_TYPb */
297 if (*ptr
== AMI_BYTE_PREFIX_CODE
)
298 ptr
++; /* skip byte prefix */
300 slp_typb
= (*ptr
) << AMI_SLP_TYPB_SHIFT
;
302 msg
= "poweroff initialized";
306 DEBUGBASIC(("acpi: %s\n", msg
));
313 read_func
= acpi_phys_copy
;
315 if (!get_acpi_rsdp()) {
316 printf("WARNING : Cannot configure ACPI\n");
320 s
= acpi_read_sdt_at(acpi_rsdp
.rsdt_addr
, (struct acpi_sdt_header
*) &rsdt
,
321 sizeof(struct acpi_rsdt
), ACPI_SDT_SIGNATURE(RSDT
));
323 sdt_count
= (s
- sizeof(struct acpi_sdt_header
)) / sizeof(u32_t
);
325 for (i
= 0; i
< sdt_count
; i
++) {
326 struct acpi_sdt_header hdr
;
328 if (read_func(rsdt
.data
[i
], &hdr
, sizeof(struct acpi_sdt_header
))) {
329 printf("ERROR acpi cannot read header at 0x%x\n",
334 for (j
= 0 ; j
< ACPI_SDT_SIGNATURE_LEN
; j
++)
335 sdt_trans
[i
].signature
[j
] = hdr
.signature
[j
];
336 sdt_trans
[i
].signature
[ACPI_SDT_SIGNATURE_LEN
] = '\0';
337 sdt_trans
[i
].length
= hdr
.length
;
340 acpi_init_poweroff();
343 struct acpi_madt_ioapic
* acpi_get_ioapic_next(void)
345 static unsigned idx
= 0;
346 static struct acpi_madt_hdr
* madt_hdr
;
348 struct acpi_madt_ioapic
* ret
;
351 madt_hdr
= (struct acpi_madt_hdr
*)
352 acpi_phys2vir(acpi_get_table_base("APIC"));
353 if (madt_hdr
== NULL
)
357 ret
= (struct acpi_madt_ioapic
*)
358 acpi_madt_get_typed_item(madt_hdr
, ACPI_MADT_TYPE_IOAPIC
, idx
);
365 struct acpi_madt_lapic
* acpi_get_lapic_next(void)
367 static unsigned idx
= 0;
368 static struct acpi_madt_hdr
* madt_hdr
;
370 struct acpi_madt_lapic
* ret
;
373 madt_hdr
= (struct acpi_madt_hdr
*)
374 acpi_phys2vir(acpi_get_table_base("APIC"));
375 if (madt_hdr
== NULL
)
380 ret
= (struct acpi_madt_lapic
*)
381 acpi_madt_get_typed_item(madt_hdr
,
382 ACPI_MADT_TYPE_LAPIC
, idx
);
388 /* report only usable CPUs */
396 void __k_unpaged_acpi_poweroff(void)
398 /* NO OP poweroff symbol*/
401 void acpi_poweroff(void)
403 if (pm1a_cnt_blk
== 0) {
406 outw(pm1a_cnt_blk
, slp_typa
| SLP_EN_CODE
);
407 if (pm1b_cnt_blk
!= 0) {
408 outw(pm1b_cnt_blk
, slp_typb
| SLP_EN_CODE
);