This source file includes following definitions.
- acpimadt_match
- acpimadt_cfg_intr
- acpimadt_attach
- acpimadt_print
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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__
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
67
68 if (aaa->aaa_table == NULL)
69 return (0);
70
71
72
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;
88 int mpstrig = (flags >> 2) & 0x03;
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
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
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
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__
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__
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 }