4 #include "kernel/kernel.h"
6 #include "arch_proto.h"
8 typedef int ((* acpi_read_t
)(phys_bytes addr
, void * buff
, size_t size
));
10 struct acpi_rsdp acpi_rsdp
;
12 static acpi_read_t read_func
;
14 #define MAX_RSDT 35 /* ACPI defines 35 signatures */
15 #define SLP_EN_CODE (1 << 13) /* ACPI SLP_EN_CODE code */
16 #define AMI_PACKAGE_OP_CODE (0x12)
17 #define AMI_NAME_OP_CODE (0x8)
18 #define AMI_BYTE_PREFIX_CODE (0xA)
19 #define AMI_PACKAGE_LENGTH_ENCODING_BITS_MASK (0xC0)
20 #define AMI_PACKAGE_LENGTH_ENCODING_BITS_SHIFT (6)
21 #define AMI_MIN_PACKAGE_LENGTH (1)
22 #define AMI_NUM_ELEMENTS_LENGTH (1)
23 #define AMI_SLP_TYPA_SHIFT (10)
24 #define AMI_SLP_TYPB_SHIFT (10)
25 #define AMI_S5_NAME_OP_OFFSET_1 (-1)
26 #define AMI_S5_NAME_OP_OFFSET_2 (-2)
27 #define AMI_S5_PACKAGE_OP_OFFSET (4)
28 #define AMI_S5_PACKET_LENGTH_OFFSET (5)
30 static struct acpi_rsdt
{
31 struct acpi_sdt_header hdr
;
36 char signature
[ACPI_SDT_SIGNATURE_LEN
+ 1];
38 } sdt_trans
[MAX_RSDT
];
41 static u16_t pm1a_cnt_blk
= 0;
42 static u16_t pm1b_cnt_blk
= 0;
43 static u16_t slp_typa
= 0;
44 static u16_t slp_typb
= 0;
46 static int acpi_check_csum(struct acpi_sdt_header
* tb
, size_t size
)
50 for (i
= 0; i
< size
; i
++)
51 total
+= ((unsigned char *)tb
)[i
];
52 return total
== 0 ? 0 : -1;
55 static int acpi_check_signature(const char * orig
, const char * match
)
57 return strncmp(orig
, match
, ACPI_SDT_SIGNATURE_LEN
);
60 static u32_t
acpi_phys2vir(u32_t p
)
63 printf("acpi: returning 0x%lx as vir addr\n", p
);
66 panic("acpi: can't get virtual address of arbitrary physical address");
69 static int acpi_phys_copy(phys_bytes phys
, void *target
, size_t len
)
72 memcpy(target
, (void *) phys
, len
);
75 panic("can't acpi_phys_copy with vm");
78 static int acpi_read_sdt_at(phys_bytes addr
,
79 struct acpi_sdt_header
* tb
,
83 struct acpi_sdt_header hdr
;
85 /* if NULL is supplied, we only return the size of the table */
87 if (read_func(addr
, &hdr
, sizeof(struct acpi_sdt_header
))) {
88 printf("ERROR acpi cannot read %s header\n", name
);
95 if (read_func(addr
, tb
, sizeof(struct acpi_sdt_header
))) {
96 printf("ERROR acpi cannot read %s header\n", name
);
100 if (acpi_check_signature(tb
->signature
, name
)) {
101 printf("ERROR acpi %s signature does not match\n", name
);
105 if (size
< tb
->length
) {
106 printf("ERROR acpi buffer too small for %s\n", name
);
110 if (read_func(addr
, tb
, size
)) {
111 printf("ERROR acpi cannot read %s\n", name
);
115 if (acpi_check_csum(tb
, tb
->length
)) {
116 printf("ERROR acpi %s checksum does not match\n", name
);
123 phys_bytes
acpi_get_table_base(const char * name
)
127 for(i
= 0; i
< sdt_count
; i
++) {
128 if (strncmp(name
, sdt_trans
[i
].signature
,
129 ACPI_SDT_SIGNATURE_LEN
) == 0)
130 return (phys_bytes
) rsdt
.data
[i
];
133 return (phys_bytes
) NULL
;
136 size_t acpi_get_table_length(const char * name
)
140 for(i
= 0; i
< sdt_count
; i
++) {
141 if (strncmp(name
, sdt_trans
[i
].signature
,
142 ACPI_SDT_SIGNATURE_LEN
) == 0)
143 return sdt_trans
[i
].length
;
149 static void * acpi_madt_get_typed_item(struct acpi_madt_hdr
* hdr
,
156 t
= (u8_t
*) hdr
+ sizeof(struct acpi_madt_hdr
);
157 end
= (u8_t
*) hdr
+ hdr
->hdr
.length
;
161 if (type
== ((struct acpi_madt_item_hdr
*) t
)->type
) {
167 t
+= ((struct acpi_madt_item_hdr
*) t
)->length
;
174 static void * acpi_madt_get_item(struct acpi_madt_hdr
* hdr
,
180 t
= (u8_t
*) hdr
+ sizeof(struct acpi_madt_hdr
);
181 end
= (u8_t
*) hdr
+ hdr
->hdr
.length
;
183 for(i
= 0 ; i
<= idx
&& t
< end
; i
++) {
186 t
+= ((struct acpi_madt_item_hdr
*) t
)->length
;
193 static int acpi_rsdp_test(void * buff
)
195 struct acpi_rsdp
* rsdp
= (struct acpi_rsdp
*) buff
;
197 if (!platform_tbl_checksum_ok(buff
, 20))
199 if (strncmp(rsdp
->signature
, "RSD PTR ", 8))
205 static int get_acpi_rsdp(void)
209 * Read 40:0Eh - to find the starting address of the EBDA.
211 acpi_phys_copy (0x40E, &ebda
, sizeof(ebda
));
214 if(platform_tbl_ptr(ebda
, ebda
+ 0x400, 16, &acpi_rsdp
,
215 sizeof(acpi_rsdp
), &machine
.acpi_rsdp
,
220 /* try BIOS read only mem space */
221 if(platform_tbl_ptr(0xE0000, 0x100000, 16, &acpi_rsdp
,
222 sizeof(acpi_rsdp
), &machine
.acpi_rsdp
,
226 machine
.acpi_rsdp
= 0; /* RSDP cannot be found at this address therefore
227 it is a valid negative value */
231 static void acpi_init_poweroff(void)
236 struct acpi_fadt_header
*fadt_header
= NULL
;
237 struct acpi_rsdt
* dsdt_header
= NULL
;
240 /* Everything used here existed since ACPI spec 1.0 */
241 /* So we can safely use them */
242 fadt_header
= (struct acpi_fadt_header
*)
243 acpi_phys2vir(acpi_get_table_base("FACP"));
244 if (fadt_header
== NULL
) {
245 msg
= "Could not load FACP";
249 dsdt_header
= (struct acpi_rsdt
*)
250 acpi_phys2vir((phys_bytes
) fadt_header
->dsdt
);
251 if (dsdt_header
== NULL
) {
252 msg
= "Could not load DSDT";
256 pm1a_cnt_blk
= fadt_header
->pm1a_cnt_blk
;
257 pm1b_cnt_blk
= fadt_header
->pm1b_cnt_blk
;
259 ptr
= start
= (u8_t
*) dsdt_header
->data
;
260 end
= start
+ dsdt_header
->hdr
.length
- 4;
262 /* See http://forum.osdev.org/viewtopic.php?t=16990 */
263 /* for layout of \_S5 */
264 while (ptr
< end
&& memcmp(ptr
, "_S5_", 4) != 0)
267 msg
= "Could not read S5 data. Use default SLP_TYPa and SLP_TYPb";
268 if (ptr
>= end
|| ptr
== start
)
271 /* validate AML structure */
272 if (*(ptr
+ AMI_S5_PACKAGE_OP_OFFSET
) != AMI_PACKAGE_OP_CODE
)
275 if ((ptr
< start
+ (-AMI_S5_NAME_OP_OFFSET_2
) ||
276 (*(ptr
+ AMI_S5_NAME_OP_OFFSET_2
) != AMI_NAME_OP_CODE
||
277 *(ptr
+ AMI_S5_NAME_OP_OFFSET_2
+ 1) != '\\')) &&
278 *(ptr
+ AMI_S5_NAME_OP_OFFSET_1
) != AMI_NAME_OP_CODE
)
281 ptr
+= AMI_S5_PACKET_LENGTH_OFFSET
;
286 ptr
+= ((*ptr
& AMI_PACKAGE_LENGTH_ENCODING_BITS_MASK
) >>
287 AMI_PACKAGE_LENGTH_ENCODING_BITS_SHIFT
) +
288 AMI_MIN_PACKAGE_LENGTH
+ AMI_NUM_ELEMENTS_LENGTH
;
292 if (*ptr
== AMI_BYTE_PREFIX_CODE
)
293 ptr
++; /* skip byte prefix */
295 slp_typa
= (*ptr
) << AMI_SLP_TYPA_SHIFT
;
297 ptr
++; /* move to SLP_TYPb */
298 if (*ptr
== AMI_BYTE_PREFIX_CODE
)
299 ptr
++; /* skip byte prefix */
301 slp_typb
= (*ptr
) << AMI_SLP_TYPB_SHIFT
;
303 msg
= "poweroff initialized";
307 printf("acpi: %s\n", msg
);
314 read_func
= acpi_phys_copy
;
316 if (!get_acpi_rsdp()) {
317 printf("WARNING : Cannot configure ACPI\n");
321 s
= acpi_read_sdt_at(acpi_rsdp
.rsdt_addr
, (struct acpi_sdt_header
*) &rsdt
,
322 sizeof(struct acpi_rsdt
), ACPI_SDT_SIGNATURE(RSDT
));
324 sdt_count
= (s
- sizeof(struct acpi_sdt_header
)) / sizeof(u32_t
);
326 for (i
= 0; i
< sdt_count
; i
++) {
327 struct acpi_sdt_header hdr
;
329 if (read_func(rsdt
.data
[i
], &hdr
, sizeof(struct acpi_sdt_header
))) {
330 printf("ERROR acpi cannot read header at 0x%x\n",
335 for (j
= 0 ; j
< ACPI_SDT_SIGNATURE_LEN
; j
++)
336 sdt_trans
[i
].signature
[j
] = hdr
.signature
[j
];
337 sdt_trans
[i
].signature
[ACPI_SDT_SIGNATURE_LEN
] = '\0';
338 sdt_trans
[i
].length
= hdr
.length
;
341 acpi_init_poweroff();
344 struct acpi_madt_ioapic
* acpi_get_ioapic_next(void)
346 static unsigned idx
= 0;
347 static struct acpi_madt_hdr
* madt_hdr
;
349 struct acpi_madt_ioapic
* ret
;
352 madt_hdr
= (struct acpi_madt_hdr
*)
353 acpi_phys2vir(acpi_get_table_base("APIC"));
354 if (madt_hdr
== NULL
)
358 ret
= (struct acpi_madt_ioapic
*)
359 acpi_madt_get_typed_item(madt_hdr
, ACPI_MADT_TYPE_IOAPIC
, idx
);
366 struct acpi_madt_lapic
* acpi_get_lapic_next(void)
368 static unsigned idx
= 0;
369 static struct acpi_madt_hdr
* madt_hdr
;
371 struct acpi_madt_lapic
* ret
;
374 madt_hdr
= (struct acpi_madt_hdr
*)
375 acpi_phys2vir(acpi_get_table_base("APIC"));
376 if (madt_hdr
== NULL
)
381 ret
= (struct acpi_madt_lapic
*)
382 acpi_madt_get_typed_item(madt_hdr
,
383 ACPI_MADT_TYPE_LAPIC
, idx
);
389 /* report only usable CPUs */
397 void __k_unpaged_acpi_poweroff(void)
399 /* NO OP poweroff symbol*/
402 void acpi_poweroff(void)
404 if (pm1a_cnt_blk
== 0) {
407 outw(pm1a_cnt_blk
, slp_typa
| SLP_EN_CODE
);
408 if (pm1b_cnt_blk
!= 0) {
409 outw(pm1b_cnt_blk
, slp_typb
| SLP_EN_CODE
);