xref: /openbsd-src/sys/dev/acpi/acpimadt.c (revision baca640c15ba51d502a6f731bb10a1e67045d6d2)
1*baca640cSjmatthew /* $OpenBSD: acpimadt.c,v 1.39 2022/11/24 04:04:39 jmatthew Exp $ */
22d9ec9b4Skettenis /*
32d9ec9b4Skettenis  * Copyright (c) 2006 Mark Kettenis <kettenis@openbsd.org>
42d9ec9b4Skettenis  *
52d9ec9b4Skettenis  * Permission to use, copy, modify, and distribute this software for any
62d9ec9b4Skettenis  * purpose with or without fee is hereby granted, provided that the above
72d9ec9b4Skettenis  * copyright notice and this permission notice appear in all copies.
82d9ec9b4Skettenis  *
92d9ec9b4Skettenis  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
102d9ec9b4Skettenis  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
112d9ec9b4Skettenis  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
122d9ec9b4Skettenis  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
132d9ec9b4Skettenis  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
142d9ec9b4Skettenis  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
152d9ec9b4Skettenis  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
162d9ec9b4Skettenis  */
172d9ec9b4Skettenis 
182d9ec9b4Skettenis #include <sys/param.h>
192d9ec9b4Skettenis #include <sys/systm.h>
202d9ec9b4Skettenis #include <sys/device.h>
212d9ec9b4Skettenis #include <sys/malloc.h>
222d9ec9b4Skettenis 
232d9ec9b4Skettenis #include <machine/apicvar.h>
242d9ec9b4Skettenis #include <machine/cpuvar.h>
252d9ec9b4Skettenis #include <machine/bus.h>
262d9ec9b4Skettenis 
272d9ec9b4Skettenis #include <dev/acpi/acpireg.h>
282d9ec9b4Skettenis #include <dev/acpi/acpivar.h>
292d9ec9b4Skettenis #include <dev/acpi/acpidev.h>
30ad5960baSkettenis #include <dev/acpi/amltypes.h>
31ad5960baSkettenis #include <dev/acpi/dsdt.h>
322d9ec9b4Skettenis 
332d9ec9b4Skettenis #include <machine/i8259.h>
342d9ec9b4Skettenis #include <machine/i82093reg.h>
352d9ec9b4Skettenis #include <machine/i82093var.h>
36264deefeSkettenis #include <machine/i82489reg.h>
37264deefeSkettenis #include <machine/i82489var.h>
382d9ec9b4Skettenis 
392d9ec9b4Skettenis #include <machine/mpbiosvar.h>
402d9ec9b4Skettenis 
412d9ec9b4Skettenis #include "ioapic.h"
422d9ec9b4Skettenis 
432d9ec9b4Skettenis int acpimadt_match(struct device *, void *, void *);
442d9ec9b4Skettenis void acpimadt_attach(struct device *, struct device *, void *);
452d9ec9b4Skettenis 
46471aeecfSnaddy const struct cfattach acpimadt_ca = {
472d9ec9b4Skettenis 	sizeof(struct device), acpimadt_match, acpimadt_attach
482d9ec9b4Skettenis };
492d9ec9b4Skettenis 
502d9ec9b4Skettenis struct cfdriver acpimadt_cd = {
512d9ec9b4Skettenis 	NULL, "acpimadt", DV_DULL
522d9ec9b4Skettenis };
532d9ec9b4Skettenis 
54a156810eSkettenis int acpimadt_validate(struct acpi_madt *);
55d2eaebe9Skettenis int acpimadt_cfg_intr(int, uint32_t *);
562d9ec9b4Skettenis int acpimadt_print(void *, const char *);
572d9ec9b4Skettenis 
582d9ec9b4Skettenis int
acpimadt_match(struct device * parent,void * match,void * aux)592d9ec9b4Skettenis acpimadt_match(struct device *parent, void *match, void *aux)
602d9ec9b4Skettenis {
612d9ec9b4Skettenis 	struct acpi_attach_args *aaa = aux;
622d9ec9b4Skettenis 	struct acpi_table_header *hdr;
632d9ec9b4Skettenis 
642d9ec9b4Skettenis 	/*
652d9ec9b4Skettenis 	 * If we do not have a table, it is not us
662d9ec9b4Skettenis 	 */
672d9ec9b4Skettenis 	if (aaa->aaa_table == NULL)
682d9ec9b4Skettenis 		return (0);
692d9ec9b4Skettenis 
702d9ec9b4Skettenis 	/*
712d9ec9b4Skettenis 	 * If it is an MADT table, we can attach
722d9ec9b4Skettenis 	 */
732d9ec9b4Skettenis 	hdr = (struct acpi_table_header *)aaa->aaa_table;
742d9ec9b4Skettenis 	if (memcmp(hdr->signature, MADT_SIG, sizeof(MADT_SIG) - 1) != 0)
752d9ec9b4Skettenis 		return (0);
762d9ec9b4Skettenis 
772d9ec9b4Skettenis 	return (1);
782d9ec9b4Skettenis }
792d9ec9b4Skettenis 
80a156810eSkettenis int
acpimadt_validate(struct acpi_madt * madt)81a156810eSkettenis acpimadt_validate(struct acpi_madt *madt)
82a156810eSkettenis {
83a156810eSkettenis 	caddr_t addr = (caddr_t)(madt + 1);
84a156810eSkettenis 
85a156810eSkettenis 	while (addr < (caddr_t)madt + madt->hdr.length) {
86a156810eSkettenis 		union acpi_madt_entry *entry = (union acpi_madt_entry *)addr;
87d2eaebe9Skettenis 		uint8_t length = entry->madt_lapic.length;
88a156810eSkettenis 
89a156810eSkettenis 		if (length < 2)
90a156810eSkettenis 			return (0);
91a156810eSkettenis 
92a156810eSkettenis 		if (addr + length > (caddr_t)madt + madt->hdr.length)
93a156810eSkettenis 			return (0);
94a156810eSkettenis 
95a156810eSkettenis 		switch (entry->madt_lapic.apic_type) {
96a156810eSkettenis 		case ACPI_MADT_LAPIC:
97a156810eSkettenis 			if (length != sizeof(entry->madt_lapic))
98a156810eSkettenis 				return (0);
99a156810eSkettenis 			break;
100a156810eSkettenis 		case ACPI_MADT_IOAPIC:
101a156810eSkettenis 			if (length != sizeof(entry->madt_ioapic))
102a156810eSkettenis 				return (0);
103a156810eSkettenis 			break;
104a156810eSkettenis 		case ACPI_MADT_OVERRIDE:
105a156810eSkettenis 			if (length != sizeof(entry->madt_override))
106a156810eSkettenis 				return (0);
107a156810eSkettenis 			break;
108a156810eSkettenis 		case ACPI_MADT_NMI:
109a156810eSkettenis 			if (length != sizeof(entry->madt_nmi))
110a156810eSkettenis 				return (0);
111a156810eSkettenis 			break;
112a156810eSkettenis 		case ACPI_MADT_LAPIC_NMI:
113a156810eSkettenis 			if (length != sizeof(entry->madt_lapic_nmi))
114a156810eSkettenis 				return (0);
115a156810eSkettenis 			break;
116a156810eSkettenis 		case ACPI_MADT_LAPIC_OVERRIDE:
117a156810eSkettenis 			if (length != sizeof(entry->madt_lapic_override))
118a156810eSkettenis 				return (0);
119a156810eSkettenis 			break;
120a156810eSkettenis 		case ACPI_MADT_IO_SAPIC:
121a156810eSkettenis 			if (length != sizeof(entry->madt_io_sapic))
122a156810eSkettenis 				return (0);
123a156810eSkettenis 			break;
124a156810eSkettenis 		case ACPI_MADT_LOCAL_SAPIC:
125a156810eSkettenis 			if (length != sizeof(entry->madt_local_sapic))
126a156810eSkettenis 				return (0);
127a156810eSkettenis 			break;
128a156810eSkettenis 		case ACPI_MADT_PLATFORM_INT:
129a156810eSkettenis 			if (length != sizeof(entry->madt_platform_int))
130a156810eSkettenis 				return (0);
131a156810eSkettenis 			break;
1320dd0b244Skettenis 		case ACPI_MADT_X2APIC:
1330dd0b244Skettenis 			if (length != sizeof(entry->madt_x2apic))
1340dd0b244Skettenis 				return (0);
1350dd0b244Skettenis 			break;
1360dd0b244Skettenis 		case ACPI_MADT_X2APIC_NMI:
1370dd0b244Skettenis 			if (length != sizeof(entry->madt_x2apic_nmi))
1380dd0b244Skettenis 				return (0);
1390dd0b244Skettenis 			break;
140a156810eSkettenis 		}
141a156810eSkettenis 
142a156810eSkettenis 		addr += length;
143a156810eSkettenis 	}
144a156810eSkettenis 
145a156810eSkettenis 	return (1);
146a156810eSkettenis }
147a156810eSkettenis 
1482d9ec9b4Skettenis struct mp_bus acpimadt_busses[256];
1492d9ec9b4Skettenis struct mp_bus acpimadt_isa_bus;
1502d9ec9b4Skettenis 
151118f4c3aSkettenis int
acpimadt_cfg_intr(int flags,uint32_t * redir)152d2eaebe9Skettenis acpimadt_cfg_intr(int flags, uint32_t *redir)
1532d9ec9b4Skettenis {
1543238e9e9Skettenis 	int mpspo = (flags >> MPS_INTPO_SHIFT) & MPS_INTPO_MASK;
1553238e9e9Skettenis 	int mpstrig = (flags >> MPS_INTTR_SHIFT) & MPS_INTTR_MASK;
1562d9ec9b4Skettenis 
1572d9ec9b4Skettenis 	*redir &= ~IOAPIC_REDLO_DEL_MASK;
1582d9ec9b4Skettenis 	switch (mpspo) {
1592d9ec9b4Skettenis 	case MPS_INTPO_DEF:
1602d9ec9b4Skettenis 	case MPS_INTPO_ACTHI:
1612d9ec9b4Skettenis 		*redir &= ~IOAPIC_REDLO_ACTLO;
1622d9ec9b4Skettenis 		break;
1632d9ec9b4Skettenis 	case MPS_INTPO_ACTLO:
1642d9ec9b4Skettenis 		*redir |= IOAPIC_REDLO_ACTLO;
1652d9ec9b4Skettenis 		break;
1662d9ec9b4Skettenis 	default:
167118f4c3aSkettenis 		return (0);
1682d9ec9b4Skettenis 	}
1692d9ec9b4Skettenis 
1702d9ec9b4Skettenis 	*redir |= (IOAPIC_REDLO_DEL_LOPRI << IOAPIC_REDLO_DEL_SHIFT);
1712d9ec9b4Skettenis 
1722d9ec9b4Skettenis 	switch (mpstrig) {
1732d9ec9b4Skettenis 	case MPS_INTTR_LEVEL:
1742d9ec9b4Skettenis 		*redir |= IOAPIC_REDLO_LEVEL;
1752d9ec9b4Skettenis 		break;
1762d9ec9b4Skettenis 	case MPS_INTTR_DEF:
1772d9ec9b4Skettenis 	case MPS_INTTR_EDGE:
1782d9ec9b4Skettenis 		*redir &= ~IOAPIC_REDLO_LEVEL;
1792d9ec9b4Skettenis 		break;
1802d9ec9b4Skettenis 	default:
181118f4c3aSkettenis 		return (0);
1822d9ec9b4Skettenis 	}
183118f4c3aSkettenis 
184118f4c3aSkettenis 	return (1);
1852d9ec9b4Skettenis }
1862d9ec9b4Skettenis 
187d2eaebe9Skettenis static uint8_t lapic_map[256];
1884b944973Skettenis 
1892d9ec9b4Skettenis void
acpimadt_attach(struct device * parent,struct device * self,void * aux)1902d9ec9b4Skettenis acpimadt_attach(struct device *parent, struct device *self, void *aux)
1912d9ec9b4Skettenis {
192ad5960baSkettenis 	struct acpi_softc *acpi_sc = (struct acpi_softc *)parent;
193f63689adSderaadt 	struct device *mainbus = parent->dv_parent->dv_parent;
1942d9ec9b4Skettenis 	struct acpi_attach_args *aaa = aux;
1952d9ec9b4Skettenis 	struct acpi_madt *madt = (struct acpi_madt *)aaa->aaa_table;
1962d9ec9b4Skettenis 	caddr_t addr = (caddr_t)(madt + 1);
197ad5960baSkettenis 	struct aml_value arg;
1982d9ec9b4Skettenis 	struct mp_intr_map *map;
1992d9ec9b4Skettenis 	struct ioapic_softc *apic;
2004b944973Skettenis 	int nlapic_nmis = 0;
2012d9ec9b4Skettenis 	int pin;
2022d9ec9b4Skettenis 
203a156810eSkettenis 	/* Do some sanity checks before committing to run in APIC mode. */
204a156810eSkettenis 	if (!acpimadt_validate(madt)) {
205a156810eSkettenis 		printf(": invalid, skipping\n");
206a156810eSkettenis 		return;
207a156810eSkettenis 	}
208a156810eSkettenis 
2092d9ec9b4Skettenis 	printf(" addr 0x%x", madt->local_apic_address);
2102d9ec9b4Skettenis 	if (madt->flags & ACPI_APIC_PCAT_COMPAT)
2112d9ec9b4Skettenis 		printf(": PC-AT compat");
2122d9ec9b4Skettenis 	printf("\n");
2132d9ec9b4Skettenis 
214ad5960baSkettenis 	/* Tell the BIOS we will be using APIC mode. */
215ad5960baSkettenis 	memset(&arg, 0, sizeof(arg));
216ad5960baSkettenis 	arg.type = AML_OBJTYPE_INTEGER;
217ad5960baSkettenis 	arg.v_integer = 1;
218bf91997dSfgsch 
219d75e4e40Smlarkin 	aml_evalname(acpi_sc, NULL, "\\_PIC", 1, &arg, NULL);
220ad5960baSkettenis 
2212d9ec9b4Skettenis 	mp_busses = acpimadt_busses;
222d7aa013fSkettenis 	mp_nbusses = nitems(acpimadt_busses);
2232d9ec9b4Skettenis 	mp_isa_bus = &acpimadt_isa_bus;
2242d9ec9b4Skettenis 
2252d9ec9b4Skettenis 	lapic_boot_init(madt->local_apic_address);
2262d9ec9b4Skettenis 
227e3cf60a4Sjordan 	/* 1st pass, get CPUs and IOAPICs */
2282d9ec9b4Skettenis 	while (addr < (caddr_t)madt + madt->hdr.length) {
2292d9ec9b4Skettenis 		union acpi_madt_entry *entry = (union acpi_madt_entry *)addr;
23077d5040fSkettenis 		struct cpu_attach_args caa;
23177d5040fSkettenis 		struct apic_attach_args aaa;
2322d9ec9b4Skettenis 
2332d9ec9b4Skettenis 		switch (entry->madt_lapic.apic_type) {
2344595568dSguenther 		case ACPI_MADT_LAPIC_OVERRIDE:
2354595568dSguenther 			if (entry->madt_lapic_override.lapic_address !=
2364595568dSguenther 			    madt->local_apic_address) {
2374595568dSguenther 				printf("%s: ignored LAPIC override 0x%llx\n",
2384595568dSguenther 				    self->dv_xname,
2394595568dSguenther 				    entry->madt_lapic_override.lapic_address);
2404595568dSguenther 			}
2414595568dSguenther 			break;
2422d9ec9b4Skettenis 		case ACPI_MADT_LAPIC:
2433b65508fSkettenis 			dprintf("%s: LAPIC: acpi_proc_id %x, apic_id %x, flags 0x%x\n",
2443b65508fSkettenis 			    self->dv_xname, entry->madt_lapic.acpi_proc_id,
2452d9ec9b4Skettenis 			    entry->madt_lapic.apic_id,
2462d9ec9b4Skettenis 			    entry->madt_lapic.flags);
2474b944973Skettenis 
248695525ceSguenther 			if ((entry->madt_lapic.flags & ACPI_PROC_ENABLE) == 0)
249695525ceSguenther 				break;
250695525ceSguenther 
2514b944973Skettenis 			lapic_map[entry->madt_lapic.acpi_proc_id] =
2524b944973Skettenis 			    entry->madt_lapic.apic_id;
2534b944973Skettenis 
2542d9ec9b4Skettenis 			memset(&caa, 0, sizeof(struct cpu_attach_args));
25577d5040fSkettenis 			if (lapic_cpu_number() == entry->madt_lapic.apic_id)
25677d5040fSkettenis 				caa.cpu_role = CPU_ROLE_BP;
257663f3520Sderaadt 			else {
25877d5040fSkettenis 				caa.cpu_role = CPU_ROLE_AP;
259663f3520Sderaadt 				ncpusfound++;
260663f3520Sderaadt 			}
2612d9ec9b4Skettenis 			caa.caa_name = "cpu";
262a2e7ce2eSkettenis 			caa.cpu_apicid = entry->madt_lapic.apic_id;
263a2e7ce2eSkettenis 			caa.cpu_acpi_proc_id = entry->madt_lapic.acpi_proc_id;
264264deefeSkettenis #ifdef MULTIPROCESSOR
2652d9ec9b4Skettenis 			caa.cpu_func = &mp_cpu_funcs;
266264deefeSkettenis #endif
267b51539b6Sniklas #ifdef __i386__
26864f77341Sderaadt 			/*
26964f77341Sderaadt 			 * XXX utterly wrong.  These are the
27077d5040fSkettenis 			 * cpu_feature/cpu_id from the BSP cpu, now
27177d5040fSkettenis 			 * being given to another cpu.  This is
27277d5040fSkettenis 			 * bullshit.
27364f77341Sderaadt 			 */
2742d9ec9b4Skettenis 			extern int cpu_id, cpu_feature;
2752d9ec9b4Skettenis 			caa.cpu_signature = cpu_id;
2762d9ec9b4Skettenis 			caa.feature_flags = cpu_feature;
277b51539b6Sniklas #endif
2782d9ec9b4Skettenis 
2792d9ec9b4Skettenis 			config_found(mainbus, &caa, acpimadt_print);
2802d9ec9b4Skettenis 			break;
2812d9ec9b4Skettenis 		case ACPI_MADT_IOAPIC:
2823b65508fSkettenis 			dprintf("%s: IOAPIC: acpi_ioapic_id %x, address 0x%x, global_int_base 0x%x\n",
2833b65508fSkettenis 			    self->dv_xname, entry->madt_ioapic.acpi_ioapic_id,
2842d9ec9b4Skettenis 			    entry->madt_ioapic.address,
2852d9ec9b4Skettenis 			    entry->madt_ioapic.global_int_base);
2862d9ec9b4Skettenis 
2872d9ec9b4Skettenis 			memset(&aaa, 0, sizeof(struct apic_attach_args));
2882d9ec9b4Skettenis 			aaa.aaa_name = "ioapic";
2892d9ec9b4Skettenis 			aaa.apic_id = entry->madt_ioapic.acpi_ioapic_id;
2902d9ec9b4Skettenis 			aaa.apic_address = entry->madt_ioapic.address;
2912d9ec9b4Skettenis 			aaa.apic_vecbase = entry->madt_ioapic.global_int_base;
2922d9ec9b4Skettenis 
2932d9ec9b4Skettenis 			config_found(mainbus, &aaa, acpimadt_print);
2942d9ec9b4Skettenis 			break;
2954b944973Skettenis 		case ACPI_MADT_LAPIC_NMI:
2964b944973Skettenis 			nlapic_nmis++;
2974b944973Skettenis 			break;
298b62da5e2Skettenis 		case ACPI_MADT_X2APIC:
299b62da5e2Skettenis 			dprintf("%s: X2APIC: acpi_proc_uid %x, apic_id %x, flags 0x%x\n",
300b62da5e2Skettenis 			    self->dv_xname, entry->madt_x2apic.acpi_proc_uid,
301b62da5e2Skettenis 			    entry->madt_x2apic.apic_id,
302b62da5e2Skettenis 			    entry->madt_x2apic.flags);
303b62da5e2Skettenis 
304b62da5e2Skettenis 			if (entry->madt_x2apic.apic_id > 255 ||
305b62da5e2Skettenis 			    (entry->madt_x2apic.flags & ACPI_PROC_ENABLE) == 0)
306b62da5e2Skettenis 				break;
307b62da5e2Skettenis 
308b62da5e2Skettenis 			memset(&caa, 0, sizeof(struct cpu_attach_args));
309b62da5e2Skettenis 			if (lapic_cpu_number() == entry->madt_x2apic.apic_id)
310b62da5e2Skettenis 				caa.cpu_role = CPU_ROLE_BP;
311b62da5e2Skettenis 			else {
312b62da5e2Skettenis 				caa.cpu_role = CPU_ROLE_AP;
313b62da5e2Skettenis 				ncpusfound++;
314b62da5e2Skettenis 			}
315b62da5e2Skettenis 			caa.caa_name = "cpu";
316a2e7ce2eSkettenis 			caa.cpu_apicid = entry->madt_x2apic.apic_id;
317a2e7ce2eSkettenis 			caa.cpu_acpi_proc_id = entry->madt_x2apic.acpi_proc_uid;
318b62da5e2Skettenis #ifdef MULTIPROCESSOR
319b62da5e2Skettenis 			caa.cpu_func = &mp_cpu_funcs;
320b62da5e2Skettenis #endif
321b62da5e2Skettenis #ifdef __i386__
322b62da5e2Skettenis 			/*
323b62da5e2Skettenis 			 * XXX utterly wrong.  These are the
324b62da5e2Skettenis 			 * cpu_feature/cpu_id from the BSP cpu, now
325b62da5e2Skettenis 			 * being given to another cpu.  This is
326b62da5e2Skettenis 			 * bullshit.
327b62da5e2Skettenis 			 */
328b62da5e2Skettenis 			extern int cpu_id, cpu_feature;
329b62da5e2Skettenis 			caa.cpu_signature = cpu_id;
330b62da5e2Skettenis 			caa.feature_flags = cpu_feature;
331b62da5e2Skettenis #endif
332b62da5e2Skettenis 
333b62da5e2Skettenis 			config_found(mainbus, &caa, acpimadt_print);
334b62da5e2Skettenis 			break;
335e3cf60a4Sjordan 		}
336e3cf60a4Sjordan 		addr += entry->madt_lapic.length;
337e3cf60a4Sjordan 	}
338e3cf60a4Sjordan 
3395714159aSdoug 	mp_intrs = mallocarray(nlapic_nmis, sizeof(struct mp_intr_map),
3405714159aSdoug 	    M_DEVBUF, M_NOWAIT);
3414b944973Skettenis 	if (mp_intrs == NULL)
3424b944973Skettenis 		return;
3434b944973Skettenis 
344e3cf60a4Sjordan 	/* 2nd pass, get interrupt overrides */
345e3cf60a4Sjordan 	addr = (caddr_t)(madt + 1);
346e3cf60a4Sjordan 	while (addr < (caddr_t)madt + madt->hdr.length) {
347e3cf60a4Sjordan 		union acpi_madt_entry *entry = (union acpi_madt_entry *)addr;
348e3cf60a4Sjordan 
349e3cf60a4Sjordan 		switch (entry->madt_lapic.apic_type) {
350e3cf60a4Sjordan 		case ACPI_MADT_LAPIC:
351e3cf60a4Sjordan 		case ACPI_MADT_IOAPIC:
352e3cf60a4Sjordan 			break;
3532d9ec9b4Skettenis 
3542d9ec9b4Skettenis 		case ACPI_MADT_OVERRIDE:
3553b65508fSkettenis 			dprintf("%s: OVERRIDE: bus %x, source %x, global_int %x, flags %x\n",
3563b65508fSkettenis 			    self->dv_xname, entry->madt_override.bus,
3572d9ec9b4Skettenis 			    entry->madt_override.source,
3582d9ec9b4Skettenis 			    entry->madt_override.global_int,
3592d9ec9b4Skettenis 			    entry->madt_override.flags);
3602d9ec9b4Skettenis 
3612d9ec9b4Skettenis 			pin = entry->madt_override.global_int;
3622d9ec9b4Skettenis 			apic = ioapic_find_bybase(pin);
3632d9ec9b4Skettenis 
3648b13d1b4Skrw 			map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT | M_ZERO);
3652d9ec9b4Skettenis 			if (map == NULL)
3662d9ec9b4Skettenis 				return;
3672d9ec9b4Skettenis 
368b51539b6Sniklas 			map->ioapic = apic;
369b51539b6Sniklas 			map->ioapic_pin = pin - apic->sc_apic_vecbase;
3702d9ec9b4Skettenis 			map->bus_pin = entry->madt_override.source;
3712d9ec9b4Skettenis 			map->flags = entry->madt_override.flags;
372444e6e9cSderaadt 
373118f4c3aSkettenis 			if (!acpimadt_cfg_intr(entry->madt_override.flags, &map->redir)) {
374118f4c3aSkettenis 				printf("%s: bogus override for pin %d\n",
375118f4c3aSkettenis 				    self->dv_xname, pin);
3761ccca4d2Sderaadt 				free(map, M_DEVBUF, sizeof(*map));
377118f4c3aSkettenis 				break;
378118f4c3aSkettenis 			}
3792d9ec9b4Skettenis 
3802d9ec9b4Skettenis 			map->ioapic_ih = APIC_INT_VIA_APIC |
381292241c5Sderaadt 			    ((apic->sc_apicid << APIC_INT_APIC_SHIFT) |
382292241c5Sderaadt 			    (pin << APIC_INT_PIN_SHIFT));
3832d9ec9b4Skettenis 
3842d9ec9b4Skettenis 			apic->sc_pins[pin].ip_map = map;
3852d9ec9b4Skettenis 
3862d9ec9b4Skettenis 			map->next = mp_isa_bus->mb_intrs;
3872d9ec9b4Skettenis 			mp_isa_bus->mb_intrs = map;
3882d9ec9b4Skettenis 			break;
3892d9ec9b4Skettenis 
3904b944973Skettenis 		case ACPI_MADT_LAPIC_NMI:
3913b65508fSkettenis 			dprintf("%s: LAPIC_NMI: acpi_proc_id %x, local_apic_lint %x, flags %x\n",
3923b65508fSkettenis 			    self->dv_xname, entry->madt_lapic_nmi.acpi_proc_id,
3934b944973Skettenis 			    entry->madt_lapic_nmi.local_apic_lint,
3944b944973Skettenis 			    entry->madt_lapic_nmi.flags);
3954b944973Skettenis 
3964b944973Skettenis 			pin = entry->madt_lapic_nmi.local_apic_lint;
3974b944973Skettenis 
3984b944973Skettenis 			map = &mp_intrs[mp_nintrs++];
3994b944973Skettenis 			memset(map, 0, sizeof *map);
4004b944973Skettenis 			map->cpu_id = lapic_map[entry->madt_lapic_nmi.acpi_proc_id];
4014b944973Skettenis 			map->ioapic_pin = pin;
4024b944973Skettenis 			map->flags = entry->madt_lapic_nmi.flags;
4034b944973Skettenis 
40419deb3b9Skettenis 			if ((pin != 0 && pin != 1) ||
40519deb3b9Skettenis 			    !acpimadt_cfg_intr(entry->madt_lapic_nmi.flags, &map->redir)) {
406118f4c3aSkettenis 				printf("%s: bogus nmi for apid %d\n",
407118f4c3aSkettenis 				    self->dv_xname, map->cpu_id);
408118f4c3aSkettenis 				mp_nintrs--;
409118f4c3aSkettenis 				break;
410118f4c3aSkettenis 			}
411118f4c3aSkettenis 
4124b944973Skettenis 			map->redir &= ~IOAPIC_REDLO_DEL_MASK;
4134b944973Skettenis 			map->redir |= (IOAPIC_REDLO_DEL_NMI << IOAPIC_REDLO_DEL_SHIFT);
4144b944973Skettenis 			break;
4154b944973Skettenis 
4160dd0b244Skettenis 		case ACPI_MADT_X2APIC:
4170dd0b244Skettenis 		case ACPI_MADT_X2APIC_NMI:
4180dd0b244Skettenis 			break;
4190dd0b244Skettenis 
4202d9ec9b4Skettenis 		default:
421*baca640cSjmatthew 			if (entry->madt_lapic.apic_type < ACPI_MADT_OEM_RSVD) {
4223b65508fSkettenis 				printf("%s: unknown apic structure type %x\n",
423*baca640cSjmatthew 				    self->dv_xname,
424*baca640cSjmatthew 				    entry->madt_lapic.apic_type);
425*baca640cSjmatthew 			}
4262d9ec9b4Skettenis 		}
4272d9ec9b4Skettenis 
4282d9ec9b4Skettenis 		addr += entry->madt_lapic.length;
4292d9ec9b4Skettenis 	}
4302d9ec9b4Skettenis 
4317c8d6483Skettenis 	/*
4327c8d6483Skettenis 	 * ISA interrupts are supposed to be identity mapped unless
4337c8d6483Skettenis 	 * there is an override, in which case we will already have a
4347c8d6483Skettenis 	 * mapping for the interrupt.
4357c8d6483Skettenis 	 */
4362d9ec9b4Skettenis 	for (pin = 0; pin < ICU_LEN; pin++) {
4377c8d6483Skettenis 		/* Skip if we already have a mapping for this interrupt. */
4387c8d6483Skettenis 		for (map = mp_isa_bus->mb_intrs; map != NULL; map = map->next)
4397c8d6483Skettenis 			if (map->bus_pin == pin)
4407c8d6483Skettenis 				break;
4417c8d6483Skettenis 		if (map != NULL)
4422d9ec9b4Skettenis 			continue;
4432d9ec9b4Skettenis 
4447c8d6483Skettenis 		apic = ioapic_find_bybase(pin);
4457c8d6483Skettenis 
4468b13d1b4Skrw 		map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT | M_ZERO);
4472d9ec9b4Skettenis 		if (map == NULL)
4482d9ec9b4Skettenis 			return;
4492d9ec9b4Skettenis 
450b51539b6Sniklas 		map->ioapic = apic;
451b51539b6Sniklas 		map->ioapic_pin = pin;
4522d9ec9b4Skettenis 		map->bus_pin = pin;
4532d9ec9b4Skettenis 		map->redir = (IOAPIC_REDLO_DEL_LOPRI << IOAPIC_REDLO_DEL_SHIFT);
4542d9ec9b4Skettenis 
4552d9ec9b4Skettenis 		map->ioapic_ih = APIC_INT_VIA_APIC |
456292241c5Sderaadt 		    ((apic->sc_apicid << APIC_INT_APIC_SHIFT) |
457292241c5Sderaadt 		    (pin << APIC_INT_PIN_SHIFT));
4582d9ec9b4Skettenis 
4592d9ec9b4Skettenis 		apic->sc_pins[pin].ip_map = map;
4602d9ec9b4Skettenis 
4612d9ec9b4Skettenis 		map->next = mp_isa_bus->mb_intrs;
4622d9ec9b4Skettenis 		mp_isa_bus->mb_intrs = map;
4632d9ec9b4Skettenis 	}
4642d9ec9b4Skettenis }
4652d9ec9b4Skettenis 
4662d9ec9b4Skettenis int
acpimadt_print(void * aux,const char * pnp)4672d9ec9b4Skettenis acpimadt_print(void *aux, const char *pnp)
4682d9ec9b4Skettenis {
4692d9ec9b4Skettenis 	struct apic_attach_args *aaa = aux;
4702d9ec9b4Skettenis 
4712d9ec9b4Skettenis 	if (pnp)
4722d9ec9b4Skettenis 		printf("%s at %s:", aaa->aaa_name, pnp);
4732d9ec9b4Skettenis 
4742d9ec9b4Skettenis 	return (UNCONF);
4752d9ec9b4Skettenis }
476