Annotation of sys/dev/acpi/acpimadt.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: acpimadt.c,v 1.10 2007/02/21 19:17:23 kettenis Exp $ */
2: /*
3: * Copyright (c) 2006 Mark Kettenis <kettenis@openbsd.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17:
18: #include <sys/param.h>
19: #include <sys/systm.h>
20: #include <sys/device.h>
21: #include <sys/malloc.h>
22:
23: #include <machine/apicvar.h>
24: #include <machine/cpuvar.h>
25: #include <machine/bus.h>
26:
27: #include <dev/acpi/acpireg.h>
28: #include <dev/acpi/acpivar.h>
29: #include <dev/acpi/acpidev.h>
30: #include <dev/acpi/amltypes.h>
31: #include <dev/acpi/dsdt.h>
32:
33: #include <machine/i8259.h>
34: #include <machine/i82093reg.h>
35: #include <machine/i82093var.h>
36:
37: #include <machine/mpbiosvar.h>
38:
39: #include "ioapic.h"
40:
41: #ifdef __amd64__ /* XXX */
42: #define mp_nintrs mp_nintr
43: #endif
44:
45: int acpimadt_match(struct device *, void *, void *);
46: void acpimadt_attach(struct device *, struct device *, void *);
47:
48: struct cfattach acpimadt_ca = {
49: sizeof(struct device), acpimadt_match, acpimadt_attach
50: };
51:
52: struct cfdriver acpimadt_cd = {
53: NULL, "acpimadt", DV_DULL
54: };
55:
56: void acpimadt_cfg_intr(int, u_int32_t *);
57: int acpimadt_print(void *, const char *);
58:
59: int
60: acpimadt_match(struct device *parent, void *match, void *aux)
61: {
62: struct acpi_attach_args *aaa = aux;
63: struct acpi_table_header *hdr;
64:
65: /*
66: * If we do not have a table, it is not us
67: */
68: if (aaa->aaa_table == NULL)
69: return (0);
70:
71: /*
72: * If it is an MADT table, we can attach
73: */
74: hdr = (struct acpi_table_header *)aaa->aaa_table;
75: if (memcmp(hdr->signature, MADT_SIG, sizeof(MADT_SIG) - 1) != 0)
76: return (0);
77:
78: return (1);
79: }
80:
81: struct mp_bus acpimadt_busses[256];
82: struct mp_bus acpimadt_isa_bus;
83:
84: void
85: acpimadt_cfg_intr(int flags, u_int32_t *redir)
86: {
87: int mpspo = flags & 0x03; /* XXX magic */
88: int mpstrig = (flags >> 2) & 0x03; /* XXX magic */
89:
90: *redir &= ~IOAPIC_REDLO_DEL_MASK;
91: switch (mpspo) {
92: case MPS_INTPO_DEF:
93: case MPS_INTPO_ACTHI:
94: *redir &= ~IOAPIC_REDLO_ACTLO;
95: break;
96: case MPS_INTPO_ACTLO:
97: *redir |= IOAPIC_REDLO_ACTLO;
98: break;
99: default:
100: panic("unknown MPS interrupt polarity %d", mpspo);
101: }
102:
103: *redir |= (IOAPIC_REDLO_DEL_LOPRI << IOAPIC_REDLO_DEL_SHIFT);
104:
105: switch (mpstrig) {
106: case MPS_INTTR_LEVEL:
107: *redir |= IOAPIC_REDLO_LEVEL;
108: break;
109: case MPS_INTTR_DEF:
110: case MPS_INTTR_EDGE:
111: *redir &= ~IOAPIC_REDLO_LEVEL;
112: break;
113: default:
114: panic("unknown MPS interrupt trigger %d", mpstrig);
115: }
116: }
117:
118: static u_int8_t lapic_map[256];
119:
120: void
121: acpimadt_attach(struct device *parent, struct device *self, void *aux)
122: {
123: struct acpi_softc *acpi_sc = (struct acpi_softc *)parent;
124: struct device *mainbus = parent->dv_parent;
125: struct acpi_attach_args *aaa = aux;
126: struct acpi_madt *madt = (struct acpi_madt *)aaa->aaa_table;
127: caddr_t addr = (caddr_t)(madt + 1);
128: struct aml_node *node;
129: struct aml_value arg;
130: struct mp_intr_map *map;
131: struct ioapic_softc *apic;
132: int cpu_role = CPU_ROLE_BP;
133: int nlapic_nmis = 0;
134: int pin;
135:
136: printf(" addr 0x%x", madt->local_apic_address);
137: if (madt->flags & ACPI_APIC_PCAT_COMPAT)
138: printf(": PC-AT compat");
139: printf("\n");
140:
141: /* Tell the BIOS we will be using APIC mode. */
142: node = aml_searchname(NULL, "\\_PIC");
143: if (node == 0)
144: return;
145: memset(&arg, 0, sizeof(arg));
146: arg.type = AML_OBJTYPE_INTEGER;
147: arg.v_integer = 1;
148: aml_evalnode(acpi_sc, node, 1, &arg, NULL);
149:
150: mp_busses = acpimadt_busses;
151: mp_isa_bus = &acpimadt_isa_bus;
152:
153: lapic_boot_init(madt->local_apic_address);
154:
155: /* 1st pass, get CPUs and IOAPICs */
156: while (addr < (caddr_t)madt + madt->hdr.length) {
157: union acpi_madt_entry *entry = (union acpi_madt_entry *)addr;
158:
159: switch (entry->madt_lapic.apic_type) {
160: case ACPI_MADT_LAPIC:
161: dprintf("%s: LAPIC: acpi_proc_id %x, apic_id %x, flags 0x%x\n",
162: self->dv_xname, entry->madt_lapic.acpi_proc_id,
163: entry->madt_lapic.apic_id,
164: entry->madt_lapic.flags);
165:
166: lapic_map[entry->madt_lapic.acpi_proc_id] =
167: entry->madt_lapic.apic_id;
168:
169: {
170: struct cpu_attach_args caa;
171:
172: if ((entry->madt_lapic.flags & ACPI_PROC_ENABLE) == 0)
173: break;
174:
175: memset(&caa, 0, sizeof(struct cpu_attach_args));
176: caa.cpu_role = cpu_role;
177: caa.caa_name = "cpu";
178: caa.cpu_number = entry->madt_lapic.apic_id;
179: caa.cpu_func = &mp_cpu_funcs;
180: #ifdef __i386__
181: extern int cpu_id, cpu_feature;
182: caa.cpu_signature = cpu_id;
183: caa.feature_flags = cpu_feature;
184: #endif
185:
186: config_found(mainbus, &caa, acpimadt_print);
187:
188: cpu_role = CPU_ROLE_AP;
189: }
190: break;
191: case ACPI_MADT_IOAPIC:
192: dprintf("%s: IOAPIC: acpi_ioapic_id %x, address 0x%x, global_int_base 0x%x\n",
193: self->dv_xname, entry->madt_ioapic.acpi_ioapic_id,
194: entry->madt_ioapic.address,
195: entry->madt_ioapic.global_int_base);
196:
197: {
198: struct apic_attach_args aaa;
199:
200: memset(&aaa, 0, sizeof(struct apic_attach_args));
201: aaa.aaa_name = "ioapic";
202: aaa.apic_id = entry->madt_ioapic.acpi_ioapic_id;
203: aaa.apic_address = entry->madt_ioapic.address;
204: aaa.apic_vecbase = entry->madt_ioapic.global_int_base;
205:
206: config_found(mainbus, &aaa, acpimadt_print);
207: }
208: break;
209: case ACPI_MADT_LAPIC_NMI:
210: nlapic_nmis++;
211: break;
212: }
213: addr += entry->madt_lapic.length;
214: }
215:
216: mp_intrs = malloc(nlapic_nmis * sizeof (struct mp_intr_map), M_DEVBUF, M_NOWAIT);
217: if (mp_intrs == NULL)
218: return;
219:
220: /* 2nd pass, get interrupt overrides */
221: addr = (caddr_t)(madt + 1);
222: while (addr < (caddr_t)madt + madt->hdr.length) {
223: union acpi_madt_entry *entry = (union acpi_madt_entry *)addr;
224:
225: switch (entry->madt_lapic.apic_type) {
226: case ACPI_MADT_LAPIC:
227: case ACPI_MADT_IOAPIC:
228: break;
229:
230: case ACPI_MADT_OVERRIDE:
231: dprintf("%s: OVERRIDE: bus %x, source %x, global_int %x, flags %x\n",
232: self->dv_xname, entry->madt_override.bus,
233: entry->madt_override.source,
234: entry->madt_override.global_int,
235: entry->madt_override.flags);
236:
237: pin = entry->madt_override.global_int;
238: apic = ioapic_find_bybase(pin);
239:
240: map = malloc(sizeof (struct mp_intr_map), M_DEVBUF, M_NOWAIT);
241: if (map == NULL)
242: return;
243:
244: memset(map, 0, sizeof *map);
245: map->ioapic = apic;
246: map->ioapic_pin = pin - apic->sc_apic_vecbase;
247: map->bus_pin = entry->madt_override.source;
248: map->flags = entry->madt_override.flags;
249: #ifdef __amd64__ /* XXX */
250: map->global_int = entry->madt_override.global_int;
251: #endif
252: acpimadt_cfg_intr(entry->madt_override.flags, &map->redir);
253:
254: map->ioapic_ih = APIC_INT_VIA_APIC |
255: ((apic->sc_apicid << APIC_INT_APIC_SHIFT) |
256: (pin << APIC_INT_PIN_SHIFT));
257:
258: apic->sc_pins[pin].ip_map = map;
259:
260: map->next = mp_isa_bus->mb_intrs;
261: mp_isa_bus->mb_intrs = map;
262: break;
263:
264: case ACPI_MADT_LAPIC_NMI:
265: dprintf("%s: LAPIC_NMI: acpi_proc_id %x, local_apic_lint %x, flags %x\n",
266: self->dv_xname, entry->madt_lapic_nmi.acpi_proc_id,
267: entry->madt_lapic_nmi.local_apic_lint,
268: entry->madt_lapic_nmi.flags);
269:
270: pin = entry->madt_lapic_nmi.local_apic_lint;
271:
272: map = &mp_intrs[mp_nintrs++];
273: memset(map, 0, sizeof *map);
274: map->cpu_id = lapic_map[entry->madt_lapic_nmi.acpi_proc_id];
275: map->ioapic_pin = pin;
276: map->flags = entry->madt_lapic_nmi.flags;
277:
278: acpimadt_cfg_intr(entry->madt_lapic_nmi.flags, &map->redir);
279: map->redir &= ~IOAPIC_REDLO_DEL_MASK;
280: map->redir |= (IOAPIC_REDLO_DEL_NMI << IOAPIC_REDLO_DEL_SHIFT);
281: break;
282:
283: default:
284: printf("%s: unknown apic structure type %x\n",
285: self->dv_xname, entry->madt_lapic.apic_type);
286: }
287:
288: addr += entry->madt_lapic.length;
289: }
290:
291: for (pin = 0; pin < ICU_LEN; pin++) {
292: apic = ioapic_find_bybase(pin);
293: if (apic->sc_pins[pin].ip_map != NULL)
294: continue;
295:
296: map = malloc(sizeof (struct mp_intr_map), M_DEVBUF, M_NOWAIT);
297: if (map == NULL)
298: return;
299:
300: memset(map, 0, sizeof *map);
301: map->ioapic = apic;
302: map->ioapic_pin = pin;
303: map->bus_pin = pin;
304: #ifdef __amd64__ /* XXX */
305: map->global_int = -1;
306: #endif
307: map->redir = (IOAPIC_REDLO_DEL_LOPRI << IOAPIC_REDLO_DEL_SHIFT);
308:
309: map->ioapic_ih = APIC_INT_VIA_APIC |
310: ((apic->sc_apicid << APIC_INT_APIC_SHIFT) |
311: (pin << APIC_INT_PIN_SHIFT));
312:
313: apic->sc_pins[pin].ip_map = map;
314:
315: map->next = mp_isa_bus->mb_intrs;
316: mp_isa_bus->mb_intrs = map;
317: }
318: }
319:
320: int
321: acpimadt_print(void *aux, const char *pnp)
322: {
323: struct apic_attach_args *aaa = aux;
324:
325: if (pnp)
326: printf("%s at %s:", aaa->aaa_name, pnp);
327:
328: return (UNCONF);
329: }
CVSweb