xref: /freebsd/sys/amd64/acpica/acpi_machdep.c (revision d95e7f5a)
1f86214b6SMitsuru IWASAKI /*-
2f86214b6SMitsuru IWASAKI  * Copyright (c) 2001 Mitsuru IWASAKI
3f86214b6SMitsuru IWASAKI  * All rights reserved.
4f86214b6SMitsuru IWASAKI  *
5f86214b6SMitsuru IWASAKI  * Redistribution and use in source and binary forms, with or without
6f86214b6SMitsuru IWASAKI  * modification, are permitted provided that the following conditions
7f86214b6SMitsuru IWASAKI  * are met:
8f86214b6SMitsuru IWASAKI  * 1. Redistributions of source code must retain the above copyright
9f86214b6SMitsuru IWASAKI  *    notice, this list of conditions and the following disclaimer.
10f86214b6SMitsuru IWASAKI  * 2. Redistributions in binary form must reproduce the above copyright
11f86214b6SMitsuru IWASAKI  *    notice, this list of conditions and the following disclaimer in the
12f86214b6SMitsuru IWASAKI  *    documentation and/or other materials provided with the distribution.
13f86214b6SMitsuru IWASAKI  *
14f86214b6SMitsuru IWASAKI  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15f86214b6SMitsuru IWASAKI  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16f86214b6SMitsuru IWASAKI  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17f86214b6SMitsuru IWASAKI  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18f86214b6SMitsuru IWASAKI  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19f86214b6SMitsuru IWASAKI  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20f86214b6SMitsuru IWASAKI  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21f86214b6SMitsuru IWASAKI  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22f86214b6SMitsuru IWASAKI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23f86214b6SMitsuru IWASAKI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24f86214b6SMitsuru IWASAKI  * SUCH DAMAGE.
25f86214b6SMitsuru IWASAKI  */
26f86214b6SMitsuru IWASAKI 
2712ea2cfeSDavid E. O'Brien #include <sys/cdefs.h>
2812ea2cfeSDavid E. O'Brien __FBSDID("$FreeBSD$");
2912ea2cfeSDavid E. O'Brien 
30f86214b6SMitsuru IWASAKI #include <sys/param.h>
31f86214b6SMitsuru IWASAKI #include <sys/bus.h>
325217af30SJohn Baldwin #include <sys/kernel.h>
335217af30SJohn Baldwin #include <sys/module.h>
34c66d2b38SJung-uk Kim #include <sys/sysctl.h>
35d95e7f5aSJohn Baldwin #include <vm/vm.h>
36d95e7f5aSJohn Baldwin #include <vm/pmap.h>
37f86214b6SMitsuru IWASAKI 
38129d3046SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h>
39d95e7f5aSJohn Baldwin #include <contrib/dev/acpica/include/accommon.h>
40d95e7f5aSJohn Baldwin #include <contrib/dev/acpica/include/actables.h>
41129d3046SJung-uk Kim 
42f86214b6SMitsuru IWASAKI #include <dev/acpica/acpivar.h>
43f86214b6SMitsuru IWASAKI 
445217af30SJohn Baldwin #include <machine/nexusvar.h>
455217af30SJohn Baldwin 
46c66d2b38SJung-uk Kim SYSCTL_DECL(_debug_acpi);
47c66d2b38SJung-uk Kim 
48d2b227cdSJung-uk Kim int acpi_resume_beep;
49c66d2b38SJung-uk Kim TUNABLE_INT("debug.acpi.resume_beep", &acpi_resume_beep);
50d2b227cdSJung-uk Kim SYSCTL_INT(_debug_acpi, OID_AUTO, resume_beep, CTLFLAG_RW, &acpi_resume_beep,
51c66d2b38SJung-uk Kim     0, "Beep the PC speaker when resuming");
52d2b227cdSJung-uk Kim 
53d2b227cdSJung-uk Kim int acpi_reset_video;
54c66d2b38SJung-uk Kim TUNABLE_INT("hw.acpi.reset_video", &acpi_reset_video);
55c66d2b38SJung-uk Kim 
568848ad86SPeter Wemm static int intr_model = ACPI_INTR_PIC;
57c66d2b38SJung-uk Kim static struct apm_clone_data acpi_clone;
588848ad86SPeter Wemm 
59f86214b6SMitsuru IWASAKI int
60f86214b6SMitsuru IWASAKI acpi_machdep_init(device_t dev)
61f86214b6SMitsuru IWASAKI {
62f86214b6SMitsuru IWASAKI 	struct acpi_softc	*sc;
63f86214b6SMitsuru IWASAKI 
64e8802274SPeter Wemm 	sc = devclass_get_softc(devclass_find("acpi"), 0);
65c66d2b38SJung-uk Kim 
66c66d2b38SJung-uk Kim 	/* Create a fake clone for /dev/acpi. */
67c66d2b38SJung-uk Kim 	STAILQ_INIT(&sc->apm_cdevs);
68c66d2b38SJung-uk Kim 	acpi_clone.cdev = sc->acpi_dev_t;
69c66d2b38SJung-uk Kim 	acpi_clone.acpi_sc = sc;
70c66d2b38SJung-uk Kim 	ACPI_LOCK(acpi);
71c66d2b38SJung-uk Kim 	STAILQ_INSERT_TAIL(&sc->apm_cdevs, &acpi_clone, entries);
72c66d2b38SJung-uk Kim 	ACPI_UNLOCK(acpi);
73c66d2b38SJung-uk Kim 	sc->acpi_clone = &acpi_clone;
74f86214b6SMitsuru IWASAKI 	acpi_install_wakeup_handler(sc);
75f86214b6SMitsuru IWASAKI 
768848ad86SPeter Wemm 	if (intr_model != ACPI_INTR_PIC)
778848ad86SPeter Wemm 		acpi_SetIntrModel(intr_model);
788848ad86SPeter Wemm 
79c66d2b38SJung-uk Kim 	SYSCTL_ADD_UINT(&sc->acpi_sysctl_ctx,
80c66d2b38SJung-uk Kim 	    SYSCTL_CHILDREN(sc->acpi_sysctl_tree), OID_AUTO,
81c66d2b38SJung-uk Kim 	    "reset_video", CTLFLAG_RW, &acpi_reset_video, 0,
82c66d2b38SJung-uk Kim 	    "Call the VESA reset BIOS vector on the resume path");
83c66d2b38SJung-uk Kim 
84f86214b6SMitsuru IWASAKI 	return (0);
85f86214b6SMitsuru IWASAKI }
868848ad86SPeter Wemm 
878848ad86SPeter Wemm void
888848ad86SPeter Wemm acpi_SetDefaultIntrModel(int model)
898848ad86SPeter Wemm {
908848ad86SPeter Wemm 
918848ad86SPeter Wemm 	intr_model = model;
928848ad86SPeter Wemm }
931a26ea7fSNate Lawson 
941a26ea7fSNate Lawson int
951a26ea7fSNate Lawson acpi_machdep_quirks(int *quirks)
961a26ea7fSNate Lawson {
971a26ea7fSNate Lawson 	return (0);
981a26ea7fSNate Lawson }
9931ad3b88SNate Lawson 
10031ad3b88SNate Lawson void
10131ad3b88SNate Lawson acpi_cpu_c1()
10231ad3b88SNate Lawson {
10331ad3b88SNate Lawson 	__asm __volatile("sti; hlt");
10431ad3b88SNate Lawson }
1055217af30SJohn Baldwin 
1065217af30SJohn Baldwin /*
107d95e7f5aSJohn Baldwin  * Support for mapping ACPI tables during early boot.  Currently this
108d95e7f5aSJohn Baldwin  * uses the crashdump map to map each table.  However, the crashdump
109d95e7f5aSJohn Baldwin  * map is created in pmap_bootstrap() right after the direct map, so
110d95e7f5aSJohn Baldwin  * we should be able to just use pmap_mapbios() here instead.
111d95e7f5aSJohn Baldwin  *
112d95e7f5aSJohn Baldwin  * This makes the following assumptions about how we use this KVA:
113d95e7f5aSJohn Baldwin  * pages 0 and 1 are used to map in the header of each table found via
114d95e7f5aSJohn Baldwin  * the RSDT or XSDT and pages 2 to n are used to map in the RSDT or
115d95e7f5aSJohn Baldwin  * XSDT.  This has to use 2 pages for the table headers in case a
116d95e7f5aSJohn Baldwin  * header spans a page boundary.
117d95e7f5aSJohn Baldwin  *
118d95e7f5aSJohn Baldwin  * XXX: We don't ensure the table fits in the available address space
119d95e7f5aSJohn Baldwin  * in the crashdump map.
120d95e7f5aSJohn Baldwin  */
121d95e7f5aSJohn Baldwin 
122d95e7f5aSJohn Baldwin /*
123d95e7f5aSJohn Baldwin  * Map some memory using the crashdump map.  'offset' is an offset in
124d95e7f5aSJohn Baldwin  * pages into the crashdump map to use for the start of the mapping.
125d95e7f5aSJohn Baldwin  */
126d95e7f5aSJohn Baldwin static void *
127d95e7f5aSJohn Baldwin table_map(vm_paddr_t pa, int offset, vm_offset_t length)
128d95e7f5aSJohn Baldwin {
129d95e7f5aSJohn Baldwin 	vm_offset_t va, off;
130d95e7f5aSJohn Baldwin 	void *data;
131d95e7f5aSJohn Baldwin 
132d95e7f5aSJohn Baldwin 	off = pa & PAGE_MASK;
133d95e7f5aSJohn Baldwin 	length = roundup(length + off, PAGE_SIZE);
134d95e7f5aSJohn Baldwin 	pa = pa & PG_FRAME;
135d95e7f5aSJohn Baldwin 	va = (vm_offset_t)pmap_kenter_temporary(pa, offset) +
136d95e7f5aSJohn Baldwin 	    (offset * PAGE_SIZE);
137d95e7f5aSJohn Baldwin 	data = (void *)(va + off);
138d95e7f5aSJohn Baldwin 	length -= PAGE_SIZE;
139d95e7f5aSJohn Baldwin 	while (length > 0) {
140d95e7f5aSJohn Baldwin 		va += PAGE_SIZE;
141d95e7f5aSJohn Baldwin 		pa += PAGE_SIZE;
142d95e7f5aSJohn Baldwin 		length -= PAGE_SIZE;
143d95e7f5aSJohn Baldwin 		pmap_kenter(va, pa);
144d95e7f5aSJohn Baldwin 		invlpg(va);
145d95e7f5aSJohn Baldwin 	}
146d95e7f5aSJohn Baldwin 	return (data);
147d95e7f5aSJohn Baldwin }
148d95e7f5aSJohn Baldwin 
149d95e7f5aSJohn Baldwin /* Unmap memory previously mapped with table_map(). */
150d95e7f5aSJohn Baldwin static void
151d95e7f5aSJohn Baldwin table_unmap(void *data, vm_offset_t length)
152d95e7f5aSJohn Baldwin {
153d95e7f5aSJohn Baldwin 	vm_offset_t va, off;
154d95e7f5aSJohn Baldwin 
155d95e7f5aSJohn Baldwin 	va = (vm_offset_t)data;
156d95e7f5aSJohn Baldwin 	off = va & PAGE_MASK;
157d95e7f5aSJohn Baldwin 	length = roundup(length + off, PAGE_SIZE);
158d95e7f5aSJohn Baldwin 	va &= ~PAGE_MASK;
159d95e7f5aSJohn Baldwin 	while (length > 0) {
160d95e7f5aSJohn Baldwin 		pmap_kremove(va);
161d95e7f5aSJohn Baldwin 		invlpg(va);
162d95e7f5aSJohn Baldwin 		va += PAGE_SIZE;
163d95e7f5aSJohn Baldwin 		length -= PAGE_SIZE;
164d95e7f5aSJohn Baldwin 	}
165d95e7f5aSJohn Baldwin }
166d95e7f5aSJohn Baldwin 
167d95e7f5aSJohn Baldwin /*
168d95e7f5aSJohn Baldwin  * Map a table at a given offset into the crashdump map.  It first
169d95e7f5aSJohn Baldwin  * maps the header to determine the table length and then maps the
170d95e7f5aSJohn Baldwin  * entire table.
171d95e7f5aSJohn Baldwin  */
172d95e7f5aSJohn Baldwin static void *
173d95e7f5aSJohn Baldwin map_table(vm_paddr_t pa, int offset, const char *sig)
174d95e7f5aSJohn Baldwin {
175d95e7f5aSJohn Baldwin 	ACPI_TABLE_HEADER *header;
176d95e7f5aSJohn Baldwin 	vm_offset_t length;
177d95e7f5aSJohn Baldwin 	void *table;
178d95e7f5aSJohn Baldwin 
179d95e7f5aSJohn Baldwin 	header = table_map(pa, offset, sizeof(ACPI_TABLE_HEADER));
180d95e7f5aSJohn Baldwin 	if (strncmp(header->Signature, sig, ACPI_NAME_SIZE) != 0) {
181d95e7f5aSJohn Baldwin 		table_unmap(header, sizeof(ACPI_TABLE_HEADER));
182d95e7f5aSJohn Baldwin 		return (NULL);
183d95e7f5aSJohn Baldwin 	}
184d95e7f5aSJohn Baldwin 	length = header->Length;
185d95e7f5aSJohn Baldwin 	table_unmap(header, sizeof(ACPI_TABLE_HEADER));
186d95e7f5aSJohn Baldwin 	table = table_map(pa, offset, length);
187d95e7f5aSJohn Baldwin 	if (ACPI_FAILURE(AcpiTbChecksum(table, length))) {
188d95e7f5aSJohn Baldwin 		if (bootverbose)
189d95e7f5aSJohn Baldwin 			printf("ACPI: Failed checksum for table %s\n", sig);
190d95e7f5aSJohn Baldwin 		table_unmap(table, length);
191d95e7f5aSJohn Baldwin 		return (NULL);
192d95e7f5aSJohn Baldwin 	}
193d95e7f5aSJohn Baldwin 	return (table);
194d95e7f5aSJohn Baldwin }
195d95e7f5aSJohn Baldwin 
196d95e7f5aSJohn Baldwin /*
197d95e7f5aSJohn Baldwin  * See if a given ACPI table is the requested table.  Returns the
198d95e7f5aSJohn Baldwin  * length of the able if it matches or zero on failure.
199d95e7f5aSJohn Baldwin  */
200d95e7f5aSJohn Baldwin static int
201d95e7f5aSJohn Baldwin probe_table(vm_paddr_t address, const char *sig)
202d95e7f5aSJohn Baldwin {
203d95e7f5aSJohn Baldwin 	ACPI_TABLE_HEADER *table;
204d95e7f5aSJohn Baldwin 
205d95e7f5aSJohn Baldwin 	table = table_map(address, 0, sizeof(ACPI_TABLE_HEADER));
206d95e7f5aSJohn Baldwin 	if (table == NULL) {
207d95e7f5aSJohn Baldwin 		if (bootverbose)
208d95e7f5aSJohn Baldwin 			printf("ACPI: Failed to map table at 0x%jx\n",
209d95e7f5aSJohn Baldwin 			    (uintmax_t)address);
210d95e7f5aSJohn Baldwin 		return (0);
211d95e7f5aSJohn Baldwin 	}
212d95e7f5aSJohn Baldwin 	if (bootverbose)
213d95e7f5aSJohn Baldwin 		printf("Table '%.4s' at 0x%jx\n", table->Signature,
214d95e7f5aSJohn Baldwin 		    (uintmax_t)address);
215d95e7f5aSJohn Baldwin 
216d95e7f5aSJohn Baldwin 	if (strncmp(table->Signature, sig, ACPI_NAME_SIZE) != 0) {
217d95e7f5aSJohn Baldwin 		table_unmap(table, sizeof(ACPI_TABLE_HEADER));
218d95e7f5aSJohn Baldwin 		return (0);
219d95e7f5aSJohn Baldwin 	}
220d95e7f5aSJohn Baldwin 	table_unmap(table, sizeof(ACPI_TABLE_HEADER));
221d95e7f5aSJohn Baldwin 	return (1);
222d95e7f5aSJohn Baldwin }
223d95e7f5aSJohn Baldwin 
224d95e7f5aSJohn Baldwin /*
225d95e7f5aSJohn Baldwin  * Try to map a table at a given physical address previously returned
226d95e7f5aSJohn Baldwin  * by acpi_find_table().
227d95e7f5aSJohn Baldwin  */
228d95e7f5aSJohn Baldwin void *
229d95e7f5aSJohn Baldwin acpi_map_table(vm_paddr_t pa, const char *sig)
230d95e7f5aSJohn Baldwin {
231d95e7f5aSJohn Baldwin 
232d95e7f5aSJohn Baldwin 	return (map_table(pa, 0, sig));
233d95e7f5aSJohn Baldwin }
234d95e7f5aSJohn Baldwin 
235d95e7f5aSJohn Baldwin /* Unmap a table previously mapped via acpi_map_table(). */
236d95e7f5aSJohn Baldwin void
237d95e7f5aSJohn Baldwin acpi_unmap_table(void *table)
238d95e7f5aSJohn Baldwin {
239d95e7f5aSJohn Baldwin 	ACPI_TABLE_HEADER *header;
240d95e7f5aSJohn Baldwin 
241d95e7f5aSJohn Baldwin 	header = (ACPI_TABLE_HEADER *)table;
242d95e7f5aSJohn Baldwin 	table_unmap(table, header->Length);
243d95e7f5aSJohn Baldwin }
244d95e7f5aSJohn Baldwin 
245d95e7f5aSJohn Baldwin /*
246d95e7f5aSJohn Baldwin  * Return the physical address of the requested table or zero if one
247d95e7f5aSJohn Baldwin  * is not found.
248d95e7f5aSJohn Baldwin  */
249d95e7f5aSJohn Baldwin vm_paddr_t
250d95e7f5aSJohn Baldwin acpi_find_table(const char *sig)
251d95e7f5aSJohn Baldwin {
252d95e7f5aSJohn Baldwin 	ACPI_PHYSICAL_ADDRESS rsdp_ptr;
253d95e7f5aSJohn Baldwin 	ACPI_TABLE_RSDP *rsdp;
254d95e7f5aSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
255d95e7f5aSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
256d95e7f5aSJohn Baldwin 	ACPI_TABLE_HEADER *table;
257d95e7f5aSJohn Baldwin 	vm_paddr_t addr;
258d95e7f5aSJohn Baldwin 	int i, count;
259d95e7f5aSJohn Baldwin 
260d95e7f5aSJohn Baldwin 	if (resource_disabled("acpi", 0))
261d95e7f5aSJohn Baldwin 		return (0);
262d95e7f5aSJohn Baldwin 
263d95e7f5aSJohn Baldwin 	/*
264d95e7f5aSJohn Baldwin 	 * Map in the RSDP.  Since ACPI uses AcpiOsMapMemory() which in turn
265d95e7f5aSJohn Baldwin 	 * calls pmap_mapbios() to find the RSDP, we assume that we can use
266d95e7f5aSJohn Baldwin 	 * pmap_mapbios() to map the RSDP.
267d95e7f5aSJohn Baldwin 	 */
268d95e7f5aSJohn Baldwin 	if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0)
269d95e7f5aSJohn Baldwin 		return (0);
270d95e7f5aSJohn Baldwin 	rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP));
271d95e7f5aSJohn Baldwin 	if (rsdp == NULL) {
272d95e7f5aSJohn Baldwin 		if (bootverbose)
273d95e7f5aSJohn Baldwin 			printf("ACPI: Failed to map RSDP\n");
274d95e7f5aSJohn Baldwin 		return (0);
275d95e7f5aSJohn Baldwin 	}
276d95e7f5aSJohn Baldwin 
277d95e7f5aSJohn Baldwin 	/*
278d95e7f5aSJohn Baldwin 	 * For ACPI >= 2.0, use the XSDT if it is available.
279d95e7f5aSJohn Baldwin 	 * Otherwise, use the RSDT.  We map the XSDT or RSDT at page 2
280d95e7f5aSJohn Baldwin 	 * in the crashdump area.  Pages 0 and 1 are used to map in the
281d95e7f5aSJohn Baldwin 	 * headers of candidate ACPI tables.
282d95e7f5aSJohn Baldwin 	 */
283d95e7f5aSJohn Baldwin 	addr = 0;
284d95e7f5aSJohn Baldwin 	if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) {
285d95e7f5aSJohn Baldwin 		/*
286d95e7f5aSJohn Baldwin 		 * AcpiOsGetRootPointer only verifies the checksum for
287d95e7f5aSJohn Baldwin 		 * the version 1.0 portion of the RSDP.  Version 2.0 has
288d95e7f5aSJohn Baldwin 		 * an additional checksum that we verify first.
289d95e7f5aSJohn Baldwin 		 */
290d95e7f5aSJohn Baldwin 		if (AcpiTbChecksum((UINT8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)) {
291d95e7f5aSJohn Baldwin 			if (bootverbose)
292d95e7f5aSJohn Baldwin 				printf("ACPI: RSDP failed extended checksum\n");
293d95e7f5aSJohn Baldwin 			return (0);
294d95e7f5aSJohn Baldwin 		}
295d95e7f5aSJohn Baldwin 		xsdt = map_table(rsdp->XsdtPhysicalAddress, 2, ACPI_SIG_XSDT);
296d95e7f5aSJohn Baldwin 		if (xsdt == NULL) {
297d95e7f5aSJohn Baldwin 			if (bootverbose)
298d95e7f5aSJohn Baldwin 				printf("ACPI: Failed to map XSDT\n");
299d95e7f5aSJohn Baldwin 			return (0);
300d95e7f5aSJohn Baldwin 		}
301d95e7f5aSJohn Baldwin 		count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
302d95e7f5aSJohn Baldwin 		    sizeof(UINT64);
303d95e7f5aSJohn Baldwin 		for (i = 0; i < count; i++)
304d95e7f5aSJohn Baldwin 			if (probe_table(xsdt->TableOffsetEntry[i], sig)) {
305d95e7f5aSJohn Baldwin 				addr = xsdt->TableOffsetEntry[i];
306d95e7f5aSJohn Baldwin 				break;
307d95e7f5aSJohn Baldwin 			}
308d95e7f5aSJohn Baldwin 		acpi_unmap_table(xsdt);
309d95e7f5aSJohn Baldwin 	} else {
310d95e7f5aSJohn Baldwin 		rsdt = map_table(rsdp->RsdtPhysicalAddress, 2, ACPI_SIG_RSDT);
311d95e7f5aSJohn Baldwin 		if (rsdt == NULL) {
312d95e7f5aSJohn Baldwin 			if (bootverbose)
313d95e7f5aSJohn Baldwin 				printf("ACPI: Failed to map RSDT\n");
314d95e7f5aSJohn Baldwin 			return (0);
315d95e7f5aSJohn Baldwin 		}
316d95e7f5aSJohn Baldwin 		count = (rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
317d95e7f5aSJohn Baldwin 		    sizeof(UINT32);
318d95e7f5aSJohn Baldwin 		for (i = 0; i < count; i++)
319d95e7f5aSJohn Baldwin 			if (probe_table(rsdt->TableOffsetEntry[i], sig)) {
320d95e7f5aSJohn Baldwin 				addr = rsdt->TableOffsetEntry[i];
321d95e7f5aSJohn Baldwin 				break;
322d95e7f5aSJohn Baldwin 			}
323d95e7f5aSJohn Baldwin 		acpi_unmap_table(rsdt);
324d95e7f5aSJohn Baldwin 	}
325d95e7f5aSJohn Baldwin 	pmap_unmapbios((vm_offset_t)rsdp, sizeof(ACPI_TABLE_RSDP));
326d95e7f5aSJohn Baldwin 	if (addr == 0) {
327d95e7f5aSJohn Baldwin 		if (bootverbose)
328d95e7f5aSJohn Baldwin 			printf("ACPI: No %s table found\n", sig);
329d95e7f5aSJohn Baldwin 		return (0);
330d95e7f5aSJohn Baldwin 	}
331d95e7f5aSJohn Baldwin 	if (bootverbose)
332d95e7f5aSJohn Baldwin 		printf("%s: Found table at 0x%jx\n", sig, (uintmax_t)addr);
333d95e7f5aSJohn Baldwin 
334d95e7f5aSJohn Baldwin 	/*
335d95e7f5aSJohn Baldwin 	 * Verify that we can map the full table and that its checksum is
336d95e7f5aSJohn Baldwin 	 * correct, etc.
337d95e7f5aSJohn Baldwin 	 */
338d95e7f5aSJohn Baldwin 	table = map_table(addr, 0, sig);
339d95e7f5aSJohn Baldwin 	if (table == NULL)
340d95e7f5aSJohn Baldwin 		return (0);
341d95e7f5aSJohn Baldwin 	acpi_unmap_table(table);
342d95e7f5aSJohn Baldwin 
343d95e7f5aSJohn Baldwin 	return (addr);
344d95e7f5aSJohn Baldwin }
345d95e7f5aSJohn Baldwin 
346d95e7f5aSJohn Baldwin /*
3475217af30SJohn Baldwin  * ACPI nexus(4) driver.
3485217af30SJohn Baldwin  */
3495217af30SJohn Baldwin static int
3505217af30SJohn Baldwin nexus_acpi_probe(device_t dev)
3515217af30SJohn Baldwin {
3525217af30SJohn Baldwin 	int error;
3535217af30SJohn Baldwin 
3545217af30SJohn Baldwin 	error = acpi_identify();
3555217af30SJohn Baldwin 	if (error)
3565217af30SJohn Baldwin 		return (error);
3575217af30SJohn Baldwin 
3585217af30SJohn Baldwin 	return (BUS_PROBE_DEFAULT);
3595217af30SJohn Baldwin }
3605217af30SJohn Baldwin 
3615217af30SJohn Baldwin static int
3625217af30SJohn Baldwin nexus_acpi_attach(device_t dev)
3635217af30SJohn Baldwin {
3645217af30SJohn Baldwin 
3655217af30SJohn Baldwin 	nexus_init_resources();
3665217af30SJohn Baldwin 	bus_generic_probe(dev);
3675217af30SJohn Baldwin 	if (BUS_ADD_CHILD(dev, 10, "acpi", 0) == NULL)
3685217af30SJohn Baldwin 		panic("failed to add acpi0 device");
3695217af30SJohn Baldwin 
3705217af30SJohn Baldwin 	return (bus_generic_attach(dev));
3715217af30SJohn Baldwin }
3725217af30SJohn Baldwin 
3735217af30SJohn Baldwin static device_method_t nexus_acpi_methods[] = {
3745217af30SJohn Baldwin 	/* Device interface */
3755217af30SJohn Baldwin 	DEVMETHOD(device_probe,		nexus_acpi_probe),
3765217af30SJohn Baldwin 	DEVMETHOD(device_attach,	nexus_acpi_attach),
3775217af30SJohn Baldwin 
3785217af30SJohn Baldwin 	{ 0, 0 }
3795217af30SJohn Baldwin };
3805217af30SJohn Baldwin 
3815217af30SJohn Baldwin DEFINE_CLASS_1(nexus, nexus_acpi_driver, nexus_acpi_methods, 1, nexus_driver);
3825217af30SJohn Baldwin static devclass_t nexus_devclass;
3835217af30SJohn Baldwin 
3845217af30SJohn Baldwin DRIVER_MODULE(nexus_acpi, root, nexus_acpi_driver, nexus_devclass, 0, 0);
385