xref: /minix3/minix/kernel/arch/i386/acpi.c (revision 9624407e7addfd8b88486acfe3a0e056e2b92ee3)
1433d6423SLionel Sambuc 
2433d6423SLionel Sambuc #include <string.h>
3433d6423SLionel Sambuc 
4433d6423SLionel Sambuc #include "acpi.h"
5433d6423SLionel Sambuc #include "arch_proto.h"
6433d6423SLionel Sambuc 
7433d6423SLionel Sambuc typedef int ((* acpi_read_t)(phys_bytes addr, void * buff, size_t size));
8433d6423SLionel Sambuc 
9433d6423SLionel Sambuc struct acpi_rsdp acpi_rsdp;
10433d6423SLionel Sambuc 
11433d6423SLionel Sambuc static acpi_read_t read_func;
12433d6423SLionel Sambuc 
13433d6423SLionel Sambuc #define MAX_RSDT	35 /* ACPI defines 35 signatures */
14433d6423SLionel Sambuc #define SLP_EN_CODE	(1 << 13) /* ACPI SLP_EN_CODE code */
15433d6423SLionel Sambuc #define AMI_PACKAGE_OP_CODE (0x12)
16433d6423SLionel Sambuc #define AMI_NAME_OP_CODE (0x8)
17433d6423SLionel Sambuc #define AMI_BYTE_PREFIX_CODE (0xA)
18433d6423SLionel Sambuc #define AMI_PACKAGE_LENGTH_ENCODING_BITS_MASK (0xC0)
19433d6423SLionel Sambuc #define AMI_PACKAGE_LENGTH_ENCODING_BITS_SHIFT (6)
20433d6423SLionel Sambuc #define AMI_MIN_PACKAGE_LENGTH (1)
21433d6423SLionel Sambuc #define AMI_NUM_ELEMENTS_LENGTH (1)
22433d6423SLionel Sambuc #define AMI_SLP_TYPA_SHIFT (10)
23433d6423SLionel Sambuc #define AMI_SLP_TYPB_SHIFT (10)
24433d6423SLionel Sambuc #define AMI_S5_NAME_OP_OFFSET_1 (-1)
25433d6423SLionel Sambuc #define AMI_S5_NAME_OP_OFFSET_2 (-2)
26433d6423SLionel Sambuc #define AMI_S5_PACKAGE_OP_OFFSET (4)
27433d6423SLionel Sambuc #define AMI_S5_PACKET_LENGTH_OFFSET (5)
28433d6423SLionel Sambuc 
29433d6423SLionel Sambuc static struct acpi_rsdt {
30433d6423SLionel Sambuc 	struct acpi_sdt_header	hdr;
31433d6423SLionel Sambuc 	u32_t			data[MAX_RSDT];
32433d6423SLionel Sambuc } rsdt;
33433d6423SLionel Sambuc 
34433d6423SLionel Sambuc static struct {
35433d6423SLionel Sambuc 	char	signature [ACPI_SDT_SIGNATURE_LEN + 1];
36433d6423SLionel Sambuc 	size_t	length;
37433d6423SLionel Sambuc } sdt_trans[MAX_RSDT];
38433d6423SLionel Sambuc 
39433d6423SLionel Sambuc static int sdt_count;
40433d6423SLionel Sambuc static u16_t pm1a_cnt_blk = 0;
41433d6423SLionel Sambuc static u16_t pm1b_cnt_blk = 0;
42433d6423SLionel Sambuc static u16_t slp_typa = 0;
43433d6423SLionel Sambuc static u16_t slp_typb = 0;
44433d6423SLionel Sambuc 
acpi_check_csum(struct acpi_sdt_header * tb,size_t size)45433d6423SLionel Sambuc static int acpi_check_csum(struct acpi_sdt_header * tb, size_t size)
46433d6423SLionel Sambuc {
47433d6423SLionel Sambuc 	u8_t total = 0;
48433d6423SLionel Sambuc 	int i;
49433d6423SLionel Sambuc 	for (i = 0; i < size; i++)
50433d6423SLionel Sambuc 		total += ((unsigned char *)tb)[i];
51433d6423SLionel Sambuc 	return total == 0 ? 0 : -1;
52433d6423SLionel Sambuc }
53433d6423SLionel Sambuc 
acpi_check_signature(const char * orig,const char * match)54433d6423SLionel Sambuc static int acpi_check_signature(const char * orig, const char * match)
55433d6423SLionel Sambuc {
56433d6423SLionel Sambuc 	return strncmp(orig, match, ACPI_SDT_SIGNATURE_LEN);
57433d6423SLionel Sambuc }
58433d6423SLionel Sambuc 
acpi_phys2vir(u32_t p)59433d6423SLionel Sambuc static u32_t acpi_phys2vir(u32_t p)
60433d6423SLionel Sambuc {
61433d6423SLionel Sambuc 	if(!vm_running) {
62*da9af514SLionel Sambuc 		DEBUGEXTRA(("acpi: returning 0x%lx as vir addr\n", p));
63433d6423SLionel Sambuc 		return p;
64433d6423SLionel Sambuc 	}
65433d6423SLionel Sambuc 	panic("acpi: can't get virtual address of arbitrary physical address");
66433d6423SLionel Sambuc }
67433d6423SLionel Sambuc 
acpi_phys_copy(phys_bytes phys,void * target,size_t len)68433d6423SLionel Sambuc static int acpi_phys_copy(phys_bytes phys, void *target, size_t len)
69433d6423SLionel Sambuc {
70433d6423SLionel Sambuc 	if(!vm_running) {
71433d6423SLionel Sambuc 		memcpy(target, (void *) phys, len);
72433d6423SLionel Sambuc 		return 0;
73433d6423SLionel Sambuc 	}
74433d6423SLionel Sambuc 	panic("can't acpi_phys_copy with vm");
75433d6423SLionel Sambuc }
76433d6423SLionel Sambuc 
acpi_read_sdt_at(phys_bytes addr,struct acpi_sdt_header * tb,size_t size,const char * name)77433d6423SLionel Sambuc static int acpi_read_sdt_at(phys_bytes addr,
78433d6423SLionel Sambuc 				struct acpi_sdt_header * tb,
79433d6423SLionel Sambuc 				size_t size,
80433d6423SLionel Sambuc 				const char * name)
81433d6423SLionel Sambuc {
82433d6423SLionel Sambuc 	struct acpi_sdt_header hdr;
83433d6423SLionel Sambuc 
84433d6423SLionel Sambuc 	/* if NULL is supplied, we only return the size of the table */
85433d6423SLionel Sambuc 	if (tb == NULL) {
86433d6423SLionel Sambuc 		if (read_func(addr, &hdr, sizeof(struct acpi_sdt_header))) {
87433d6423SLionel Sambuc 			printf("ERROR acpi cannot read %s header\n", name);
88433d6423SLionel Sambuc 			return -1;
89433d6423SLionel Sambuc 		}
90433d6423SLionel Sambuc 
91433d6423SLionel Sambuc 		return hdr.length;
92433d6423SLionel Sambuc 	}
93433d6423SLionel Sambuc 
94433d6423SLionel Sambuc 	if (read_func(addr, tb, sizeof(struct acpi_sdt_header))) {
95433d6423SLionel Sambuc 		printf("ERROR acpi cannot read %s header\n", name);
96433d6423SLionel Sambuc 		return -1;
97433d6423SLionel Sambuc 	}
98433d6423SLionel Sambuc 
99433d6423SLionel Sambuc 	if (acpi_check_signature(tb->signature, name)) {
100433d6423SLionel Sambuc 		printf("ERROR acpi %s signature does not match\n", name);
101433d6423SLionel Sambuc 		return -1;
102433d6423SLionel Sambuc 	}
103433d6423SLionel Sambuc 
104433d6423SLionel Sambuc 	if (size < tb->length) {
105433d6423SLionel Sambuc 		printf("ERROR acpi buffer too small for %s\n", name);
106433d6423SLionel Sambuc 		return -1;
107433d6423SLionel Sambuc 	}
108433d6423SLionel Sambuc 
109433d6423SLionel Sambuc 	if (read_func(addr, tb, size)) {
110433d6423SLionel Sambuc 		printf("ERROR acpi cannot read %s\n", name);
111433d6423SLionel Sambuc 		return -1;
112433d6423SLionel Sambuc 	}
113433d6423SLionel Sambuc 
114433d6423SLionel Sambuc 	if (acpi_check_csum(tb, tb->length)) {
115433d6423SLionel Sambuc 		printf("ERROR acpi %s checksum does not match\n", name);
116433d6423SLionel Sambuc 		return -1;
117433d6423SLionel Sambuc 	}
118433d6423SLionel Sambuc 
119433d6423SLionel Sambuc 	return tb->length;
120433d6423SLionel Sambuc }
121433d6423SLionel Sambuc 
acpi_get_table_base(const char * name)122433d6423SLionel Sambuc phys_bytes acpi_get_table_base(const char * name)
123433d6423SLionel Sambuc {
124433d6423SLionel Sambuc 	int i;
125433d6423SLionel Sambuc 
126433d6423SLionel Sambuc 	for(i = 0; i < sdt_count; i++) {
127433d6423SLionel Sambuc 		if (strncmp(name, sdt_trans[i].signature,
128433d6423SLionel Sambuc 					ACPI_SDT_SIGNATURE_LEN) == 0)
129433d6423SLionel Sambuc 			return (phys_bytes) rsdt.data[i];
130433d6423SLionel Sambuc 	}
131433d6423SLionel Sambuc 
132433d6423SLionel Sambuc 	return (phys_bytes) NULL;
133433d6423SLionel Sambuc }
134433d6423SLionel Sambuc 
acpi_get_table_length(const char * name)135433d6423SLionel Sambuc size_t acpi_get_table_length(const char * name)
136433d6423SLionel Sambuc {
137433d6423SLionel Sambuc 	int i;
138433d6423SLionel Sambuc 
139433d6423SLionel Sambuc 	for(i = 0; i < sdt_count; i++) {
140433d6423SLionel Sambuc 		if (strncmp(name, sdt_trans[i].signature,
141433d6423SLionel Sambuc 					ACPI_SDT_SIGNATURE_LEN) == 0)
142433d6423SLionel Sambuc 			return sdt_trans[i].length;
143433d6423SLionel Sambuc 	}
144433d6423SLionel Sambuc 
145433d6423SLionel Sambuc 	return 0;
146433d6423SLionel Sambuc }
147433d6423SLionel Sambuc 
acpi_madt_get_typed_item(struct acpi_madt_hdr * hdr,unsigned char type,unsigned idx)148433d6423SLionel Sambuc static void * acpi_madt_get_typed_item(struct acpi_madt_hdr * hdr,
149433d6423SLionel Sambuc 					unsigned char type,
150433d6423SLionel Sambuc 					unsigned idx)
151433d6423SLionel Sambuc {
152433d6423SLionel Sambuc 	u8_t * t, * end;
153433d6423SLionel Sambuc 	int i;
154433d6423SLionel Sambuc 
155433d6423SLionel Sambuc 	t = (u8_t *) hdr + sizeof(struct acpi_madt_hdr);
156433d6423SLionel Sambuc 	end = (u8_t *) hdr + hdr->hdr.length;
157433d6423SLionel Sambuc 
158433d6423SLionel Sambuc 	i = 0;
159433d6423SLionel Sambuc 	while(t < end) {
160433d6423SLionel Sambuc 		if (type == ((struct acpi_madt_item_hdr *) t)->type) {
161433d6423SLionel Sambuc 			if (i == idx)
162433d6423SLionel Sambuc 				return t;
163433d6423SLionel Sambuc 			else
164433d6423SLionel Sambuc 				i++;
165433d6423SLionel Sambuc 		}
166433d6423SLionel Sambuc 		t += ((struct acpi_madt_item_hdr *) t)->length;
167433d6423SLionel Sambuc 	}
168433d6423SLionel Sambuc 
169433d6423SLionel Sambuc 	return NULL;
170433d6423SLionel Sambuc }
171433d6423SLionel Sambuc 
172433d6423SLionel Sambuc #if 0
173433d6423SLionel Sambuc static void * acpi_madt_get_item(struct acpi_madt_hdr * hdr,
174433d6423SLionel Sambuc 				unsigned idx)
175433d6423SLionel Sambuc {
176433d6423SLionel Sambuc 	u8_t * t, * end;
177433d6423SLionel Sambuc 	int i;
178433d6423SLionel Sambuc 
179433d6423SLionel Sambuc 	t = (u8_t *) hdr + sizeof(struct acpi_madt_hdr);
180433d6423SLionel Sambuc 	end = (u8_t *) hdr + hdr->hdr.length;
181433d6423SLionel Sambuc 
182433d6423SLionel Sambuc 	for(i = 0 ; i <= idx && t < end; i++) {
183433d6423SLionel Sambuc 		if (i == idx)
184433d6423SLionel Sambuc 			return t;
185433d6423SLionel Sambuc 		t += ((struct acpi_madt_item_hdr *) t)->length;
186433d6423SLionel Sambuc 	}
187433d6423SLionel Sambuc 
188433d6423SLionel Sambuc 	return NULL;
189433d6423SLionel Sambuc }
190433d6423SLionel Sambuc #endif
191433d6423SLionel Sambuc 
acpi_rsdp_test(void * buff)192433d6423SLionel Sambuc static int acpi_rsdp_test(void * buff)
193433d6423SLionel Sambuc {
194433d6423SLionel Sambuc 	struct acpi_rsdp * rsdp = (struct acpi_rsdp *) buff;
195433d6423SLionel Sambuc 
196433d6423SLionel Sambuc 	if (!platform_tbl_checksum_ok(buff, 20))
197433d6423SLionel Sambuc 		return 0;
198433d6423SLionel Sambuc 	if (strncmp(rsdp->signature, "RSD PTR ", 8))
199433d6423SLionel Sambuc 		return 0;
200433d6423SLionel Sambuc 
201433d6423SLionel Sambuc 	return 1;
202433d6423SLionel Sambuc }
203433d6423SLionel Sambuc 
get_acpi_rsdp(void)204433d6423SLionel Sambuc static int get_acpi_rsdp(void)
205433d6423SLionel Sambuc {
206433d6423SLionel Sambuc 	u16_t ebda;
207433d6423SLionel Sambuc 	/*
208433d6423SLionel Sambuc 	 * Read 40:0Eh - to find the starting address of the EBDA.
209433d6423SLionel Sambuc 	 */
210433d6423SLionel Sambuc 	acpi_phys_copy (0x40E, &ebda, sizeof(ebda));
211433d6423SLionel Sambuc 	if (ebda) {
212433d6423SLionel Sambuc 		ebda <<= 4;
213433d6423SLionel Sambuc 		if(platform_tbl_ptr(ebda, ebda + 0x400, 16, &acpi_rsdp,
214433d6423SLionel Sambuc 					sizeof(acpi_rsdp), &machine.acpi_rsdp,
215433d6423SLionel Sambuc 					acpi_rsdp_test))
216433d6423SLionel Sambuc 			return 1;
217433d6423SLionel Sambuc 	}
218433d6423SLionel Sambuc 
219433d6423SLionel Sambuc 	/* try BIOS read only mem space */
220433d6423SLionel Sambuc 	if(platform_tbl_ptr(0xE0000, 0x100000, 16, &acpi_rsdp,
221433d6423SLionel Sambuc 				sizeof(acpi_rsdp), &machine.acpi_rsdp,
222433d6423SLionel Sambuc 				acpi_rsdp_test))
223433d6423SLionel Sambuc 		return 1;
224433d6423SLionel Sambuc 
225433d6423SLionel Sambuc 	machine.acpi_rsdp = 0; /* RSDP cannot be found at this address therefore
226433d6423SLionel Sambuc 				  it is a valid negative value */
227433d6423SLionel Sambuc 	return 0;
228433d6423SLionel Sambuc }
229433d6423SLionel Sambuc 
acpi_init_poweroff(void)230433d6423SLionel Sambuc static void acpi_init_poweroff(void)
231433d6423SLionel Sambuc {
232433d6423SLionel Sambuc 	u8_t *ptr = NULL;
233433d6423SLionel Sambuc 	u8_t *start = NULL;
234433d6423SLionel Sambuc 	u8_t *end = NULL;
235433d6423SLionel Sambuc 	struct acpi_fadt_header *fadt_header = NULL;
236433d6423SLionel Sambuc 	struct acpi_rsdt * dsdt_header = NULL;
237433d6423SLionel Sambuc 	char *msg = NULL;
238433d6423SLionel Sambuc 
239433d6423SLionel Sambuc 	/* Everything used here existed since ACPI spec 1.0 */
240433d6423SLionel Sambuc 	/* So we can safely use them */
241433d6423SLionel Sambuc 	fadt_header = (struct acpi_fadt_header *)
242433d6423SLionel Sambuc 		acpi_phys2vir(acpi_get_table_base("FACP"));
243433d6423SLionel Sambuc 	if (fadt_header == NULL) {
244433d6423SLionel Sambuc 		msg = "Could not load FACP";
245433d6423SLionel Sambuc 		goto exit;
246433d6423SLionel Sambuc 	}
247433d6423SLionel Sambuc 
248433d6423SLionel Sambuc 	dsdt_header = (struct acpi_rsdt *)
249433d6423SLionel Sambuc 		acpi_phys2vir((phys_bytes) fadt_header->dsdt);
250433d6423SLionel Sambuc 	if (dsdt_header == NULL) {
251433d6423SLionel Sambuc 		msg = "Could not load DSDT";
252433d6423SLionel Sambuc 		goto exit;
253433d6423SLionel Sambuc 	}
254433d6423SLionel Sambuc 
255433d6423SLionel Sambuc 	pm1a_cnt_blk = fadt_header->pm1a_cnt_blk;
256433d6423SLionel Sambuc 	pm1b_cnt_blk = fadt_header->pm1b_cnt_blk;
257433d6423SLionel Sambuc 
258433d6423SLionel Sambuc 	ptr = start = (u8_t *) dsdt_header->data;
259433d6423SLionel Sambuc 	end = start + dsdt_header->hdr.length - 4;
260433d6423SLionel Sambuc 
261433d6423SLionel Sambuc 	/* See http://forum.osdev.org/viewtopic.php?t=16990 */
262433d6423SLionel Sambuc 	/* for layout of \_S5 */
263433d6423SLionel Sambuc 	while (ptr < end && memcmp(ptr, "_S5_", 4) != 0)
264433d6423SLionel Sambuc 		ptr++;
265433d6423SLionel Sambuc 
266433d6423SLionel Sambuc 	msg = "Could not read S5 data. Use default SLP_TYPa and SLP_TYPb";
267433d6423SLionel Sambuc 	if (ptr >= end || ptr == start)
268433d6423SLionel Sambuc 		goto exit;
269433d6423SLionel Sambuc 
270433d6423SLionel Sambuc 	/* validate AML structure */
271433d6423SLionel Sambuc 	if (*(ptr + AMI_S5_PACKAGE_OP_OFFSET) != AMI_PACKAGE_OP_CODE)
272433d6423SLionel Sambuc 		goto exit;
273433d6423SLionel Sambuc 
274433d6423SLionel Sambuc 	if ((ptr < start + (-AMI_S5_NAME_OP_OFFSET_2) ||
275433d6423SLionel Sambuc 		(*(ptr + AMI_S5_NAME_OP_OFFSET_2) != AMI_NAME_OP_CODE ||
276433d6423SLionel Sambuc 		 *(ptr + AMI_S5_NAME_OP_OFFSET_2 + 1) != '\\')) &&
277433d6423SLionel Sambuc 		*(ptr + AMI_S5_NAME_OP_OFFSET_1) != AMI_NAME_OP_CODE)
278433d6423SLionel Sambuc 		goto exit;
279433d6423SLionel Sambuc 
280433d6423SLionel Sambuc 	ptr += AMI_S5_PACKET_LENGTH_OFFSET;
281433d6423SLionel Sambuc 	if (ptr >= end)
282433d6423SLionel Sambuc 		goto exit;
283433d6423SLionel Sambuc 
284433d6423SLionel Sambuc 	/* package length */
285433d6423SLionel Sambuc 	ptr += ((*ptr & AMI_PACKAGE_LENGTH_ENCODING_BITS_MASK) >>
286433d6423SLionel Sambuc 		AMI_PACKAGE_LENGTH_ENCODING_BITS_SHIFT) +
287433d6423SLionel Sambuc 		AMI_MIN_PACKAGE_LENGTH + AMI_NUM_ELEMENTS_LENGTH;
288433d6423SLionel Sambuc 	if (ptr >= end)
289433d6423SLionel Sambuc 		goto exit;
290433d6423SLionel Sambuc 
291433d6423SLionel Sambuc 	if (*ptr == AMI_BYTE_PREFIX_CODE)
292433d6423SLionel Sambuc 		ptr++; /* skip byte prefix */
293433d6423SLionel Sambuc 
294433d6423SLionel Sambuc 	slp_typa = (*ptr) << AMI_SLP_TYPA_SHIFT;
295433d6423SLionel Sambuc 
296433d6423SLionel Sambuc 	ptr++; /* move to SLP_TYPb */
297433d6423SLionel Sambuc 	if (*ptr == AMI_BYTE_PREFIX_CODE)
298433d6423SLionel Sambuc 		ptr++; /* skip byte prefix */
299433d6423SLionel Sambuc 
300433d6423SLionel Sambuc 	slp_typb = (*ptr) << AMI_SLP_TYPB_SHIFT;
301433d6423SLionel Sambuc 
302433d6423SLionel Sambuc 	msg = "poweroff initialized";
303433d6423SLionel Sambuc 
304433d6423SLionel Sambuc exit:
305433d6423SLionel Sambuc 	if (msg) {
306*da9af514SLionel Sambuc 		DEBUGBASIC(("acpi: %s\n", msg));
307433d6423SLionel Sambuc 	}
308433d6423SLionel Sambuc }
309433d6423SLionel Sambuc 
acpi_init(void)310433d6423SLionel Sambuc void acpi_init(void)
311433d6423SLionel Sambuc {
312433d6423SLionel Sambuc 	int s, i;
313433d6423SLionel Sambuc 	read_func = acpi_phys_copy;
314433d6423SLionel Sambuc 
315433d6423SLionel Sambuc 	if (!get_acpi_rsdp()) {
316433d6423SLionel Sambuc 		printf("WARNING : Cannot configure ACPI\n");
317433d6423SLionel Sambuc 		return;
318433d6423SLionel Sambuc 	}
319433d6423SLionel Sambuc 
320433d6423SLionel Sambuc 	s = acpi_read_sdt_at(acpi_rsdp.rsdt_addr, (struct acpi_sdt_header *) &rsdt,
321433d6423SLionel Sambuc 			sizeof(struct acpi_rsdt), ACPI_SDT_SIGNATURE(RSDT));
322433d6423SLionel Sambuc 
323433d6423SLionel Sambuc 	sdt_count = (s - sizeof(struct acpi_sdt_header)) / sizeof(u32_t);
324433d6423SLionel Sambuc 
325433d6423SLionel Sambuc 	for (i = 0; i < sdt_count; i++) {
326433d6423SLionel Sambuc 		struct acpi_sdt_header hdr;
327433d6423SLionel Sambuc 		int j;
328433d6423SLionel Sambuc 		if (read_func(rsdt.data[i], &hdr, sizeof(struct acpi_sdt_header))) {
329433d6423SLionel Sambuc 			printf("ERROR acpi cannot read header at 0x%x\n",
330433d6423SLionel Sambuc 								rsdt.data[i]);
331433d6423SLionel Sambuc 			return;
332433d6423SLionel Sambuc 		}
333433d6423SLionel Sambuc 
334433d6423SLionel Sambuc 		for (j = 0 ; j < ACPI_SDT_SIGNATURE_LEN; j++)
335433d6423SLionel Sambuc 			sdt_trans[i].signature[j] = hdr.signature[j];
336433d6423SLionel Sambuc 		sdt_trans[i].signature[ACPI_SDT_SIGNATURE_LEN] = '\0';
337433d6423SLionel Sambuc 		sdt_trans[i].length = hdr.length;
338433d6423SLionel Sambuc 	}
339433d6423SLionel Sambuc 
340433d6423SLionel Sambuc 	acpi_init_poweroff();
341433d6423SLionel Sambuc }
342433d6423SLionel Sambuc 
acpi_get_ioapic_next(void)343433d6423SLionel Sambuc struct acpi_madt_ioapic * acpi_get_ioapic_next(void)
344433d6423SLionel Sambuc {
345433d6423SLionel Sambuc 	static unsigned idx = 0;
346433d6423SLionel Sambuc 	static struct acpi_madt_hdr * madt_hdr;
347433d6423SLionel Sambuc 
348433d6423SLionel Sambuc 	struct acpi_madt_ioapic * ret;
349433d6423SLionel Sambuc 
350433d6423SLionel Sambuc 	if (idx == 0) {
351433d6423SLionel Sambuc 		madt_hdr = (struct acpi_madt_hdr *)
352433d6423SLionel Sambuc 			acpi_phys2vir(acpi_get_table_base("APIC"));
353433d6423SLionel Sambuc 		if (madt_hdr == NULL)
354433d6423SLionel Sambuc 			return NULL;
355433d6423SLionel Sambuc 	}
356433d6423SLionel Sambuc 
357433d6423SLionel Sambuc 	ret = (struct acpi_madt_ioapic *)
358433d6423SLionel Sambuc 		acpi_madt_get_typed_item(madt_hdr, ACPI_MADT_TYPE_IOAPIC, idx);
359433d6423SLionel Sambuc 	if (ret)
360433d6423SLionel Sambuc 		idx++;
361433d6423SLionel Sambuc 
362433d6423SLionel Sambuc 	return ret;
363433d6423SLionel Sambuc }
364433d6423SLionel Sambuc 
acpi_get_lapic_next(void)365433d6423SLionel Sambuc struct acpi_madt_lapic * acpi_get_lapic_next(void)
366433d6423SLionel Sambuc {
367433d6423SLionel Sambuc 	static unsigned idx = 0;
368433d6423SLionel Sambuc 	static struct acpi_madt_hdr * madt_hdr;
369433d6423SLionel Sambuc 
370433d6423SLionel Sambuc 	struct acpi_madt_lapic * ret;
371433d6423SLionel Sambuc 
372433d6423SLionel Sambuc 	if (idx == 0) {
373433d6423SLionel Sambuc 		madt_hdr = (struct acpi_madt_hdr *)
374433d6423SLionel Sambuc 			acpi_phys2vir(acpi_get_table_base("APIC"));
375433d6423SLionel Sambuc 		if (madt_hdr == NULL)
376433d6423SLionel Sambuc 			return NULL;
377433d6423SLionel Sambuc 	}
378433d6423SLionel Sambuc 
379433d6423SLionel Sambuc 	for (;;) {
380433d6423SLionel Sambuc 		ret = (struct acpi_madt_lapic *)
381433d6423SLionel Sambuc 			acpi_madt_get_typed_item(madt_hdr,
382433d6423SLionel Sambuc 					ACPI_MADT_TYPE_LAPIC, idx);
383433d6423SLionel Sambuc 		if (!ret)
384433d6423SLionel Sambuc 			break;
385433d6423SLionel Sambuc 
386433d6423SLionel Sambuc 		idx++;
387433d6423SLionel Sambuc 
388433d6423SLionel Sambuc 		/* report only usable CPUs */
389433d6423SLionel Sambuc 		if (ret->flags & 1)
390433d6423SLionel Sambuc 			break;
391433d6423SLionel Sambuc 	}
392433d6423SLionel Sambuc 
393433d6423SLionel Sambuc 	return ret;
394433d6423SLionel Sambuc }
395433d6423SLionel Sambuc 
__k_unpaged_acpi_poweroff(void)396433d6423SLionel Sambuc void __k_unpaged_acpi_poweroff(void)
397433d6423SLionel Sambuc {
398433d6423SLionel Sambuc 	/* NO OP poweroff symbol*/
399433d6423SLionel Sambuc }
400433d6423SLionel Sambuc 
acpi_poweroff(void)401433d6423SLionel Sambuc void acpi_poweroff(void)
402433d6423SLionel Sambuc {
403433d6423SLionel Sambuc 	if (pm1a_cnt_blk == 0) {
404433d6423SLionel Sambuc 		return;
405433d6423SLionel Sambuc 	}
406433d6423SLionel Sambuc 	outw(pm1a_cnt_blk, slp_typa | SLP_EN_CODE);
407433d6423SLionel Sambuc 	if (pm1b_cnt_blk != 0) {
408433d6423SLionel Sambuc 		outw(pm1b_cnt_blk, slp_typb | SLP_EN_CODE);
409433d6423SLionel Sambuc 	}
410433d6423SLionel Sambuc }
411