1 /* $NetBSD: mpbios.c,v 1.72 2025/01/13 06:35:38 imil Exp $ */
2
3 /*-
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by RedBack Networks Inc.
9 *
10 * Author: Bill Sommerfeld
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * Copyright (c) 1999 Stefan Grefen
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the NetBSD
48 * Foundation, Inc. and its contributors.
49 * 4. Neither the name of The NetBSD Foundation nor the names of its
50 * contributors may be used to endorse or promote products derived
51 * from this software without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
54 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
64 */
65 /*
66 * Derived from FreeBSD's mp_machdep.c
67 */
68 /*
69 * Copyright (c) 1996, by Steve Passe
70 * All rights reserved.
71 *
72 * Redistribution and use in source and binary forms, with or without
73 * modification, are permitted provided that the following conditions
74 * are met:
75 * 1. Redistributions of source code must retain the above copyright
76 * notice, this list of conditions and the following disclaimer.
77 * 2. The name of the developer may NOT be used to endorse or promote products
78 * derived from this software without specific prior written permission.
79 *
80 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
81 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
82 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
83 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
84 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
85 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
86 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
87 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
88 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
89 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
90 * SUCH DAMAGE.
91 */
92
93 /*
94 * The Intel MP-stuff is just one way of x86 SMP systems
95 * so only Intel MP specific stuff is here.
96 */
97
98 #include <sys/cdefs.h>
99 __KERNEL_RCSID(0, "$NetBSD: mpbios.c,v 1.72 2025/01/13 06:35:38 imil Exp $");
100
101 #include "acpica.h"
102 #include "lapic.h"
103 #include "ioapic.h"
104 #include "opt_acpi.h"
105 #include "opt_mpbios.h"
106
107 #include <sys/param.h>
108 #include <sys/systm.h>
109 #include <sys/kernel.h>
110 #include <sys/device.h>
111 #include <sys/kmem.h>
112 #include <sys/bus.h>
113 #include <sys/reboot.h>
114
115 #include <uvm/uvm_extern.h>
116
117 #include <machine/specialreg.h>
118 #include <machine/cpuvar.h>
119 #include <machine/mpbiosvar.h>
120 #include <machine/pio.h>
121
122 #include <machine/i82093reg.h>
123 #include <machine/i82093var.h>
124 #include <machine/i82489reg.h>
125 #include <machine/i82489var.h>
126
127 #include <dev/isa/isareg.h>
128
129 #ifdef X86_MPBIOS_SUPPORT_EISA
130 #include <dev/eisa/eisavar.h> /* for ELCR* def'ns */
131 #endif
132
133 #if NACPICA > 0
134 extern int mpacpi_ncpu;
135 extern int mpacpi_nioapic;
136 #endif
137
138 int mpbios_ncpu;
139 int mpbios_nioapic;
140
141 #include "pci.h"
142
143 #if NPCI > 0
144 #include <dev/pci/pcivar.h>
145 #include <dev/pci/pcireg.h>
146 #endif
147
148 #include "locators.h"
149
150 /* descriptions of MP basetable entries */
151 struct mpbios_baseentry {
152 uint8_t type;
153 uint8_t length;
154 uint16_t count;
155 const char *name;
156 };
157
158 static const char *loc_where[] = {
159 "extended bios data area",
160 "last page of base memory",
161 "bios"
162 };
163
164 struct mp_map
165 {
166 vaddr_t baseva;
167 int vsize;
168 paddr_t pa;
169 paddr_t pg;
170 int psize;
171 };
172
173 struct dflt_conf_entry {
174 const char *bus_type[2];
175 int flags;
176 };
177
178 int mp_cpuprint(void *, const char *);
179 int mp_ioapicprint(void *, const char *);
180 static const void *mpbios_search(device_t, paddr_t, int,
181 struct mp_map *);
182 static inline int mpbios_cksum(const void *,int);
183
184 static void mp_cfg_special_intr(const struct mpbios_int *, uint32_t *);
185 static void mp_print_special_intr (int intr);
186
187 static void mp_cfg_pci_intr(const struct mpbios_int *, uint32_t *);
188 static void mp_print_pci_intr (int intr);
189
190 #ifdef X86_MPBIOS_SUPPORT_EISA
191 static void mp_print_eisa_intr (int intr);
192 static void mp_cfg_eisa_intr(const struct mpbios_int *, uint32_t *);
193 #endif
194
195 static void mp_cfg_isa_intr(const struct mpbios_int *, uint32_t *);
196 static void mp_print_isa_intr(int intr);
197
198 static void mpbios_dflt_conf_cpu(device_t);
199 static void mpbios_dflt_conf_bus(device_t, const struct dflt_conf_entry *);
200 static void mpbios_dflt_conf_ioapic(device_t);
201 static void mpbios_dflt_conf_int(device_t, const struct dflt_conf_entry *,
202 const int *);
203
204 static void mpbios_cpu(const uint8_t *, device_t);
205 static void mpbios_bus(const uint8_t *, device_t);
206 static void mpbios_ioapic(const uint8_t *, device_t);
207 static void mpbios_int(const uint8_t *, int, struct mp_intr_map *);
208
209 static const void *mpbios_map(paddr_t, int, struct mp_map *);
210 static void mpbios_unmap(struct mp_map *);
211
212 #ifdef MPTABLE_LINUX_BUG_COMPAT
213 static uint16_t compute_entry_count(const uint8_t *, const uint8_t *);
214 #endif
215 /*
216 * globals to help us bounce our way through parsing the config table.
217 */
218
219 static struct mp_map mp_cfg_table_map;
220 static struct mp_map mp_fp_map;
221 const struct mpbios_cth *mp_cth;
222 const struct mpbios_fps *mp_fps;
223
224 int mpbios_scanned;
225
226 int
mp_cpuprint(void * aux,const char * pnp)227 mp_cpuprint(void *aux, const char *pnp)
228 {
229 struct cpu_attach_args *caa = aux;
230
231 if (pnp)
232 aprint_normal("cpu at %s", pnp);
233 aprint_normal(" apid %d", caa->cpu_number);
234 return UNCONF;
235 }
236
237 int
mp_ioapicprint(void * aux,const char * pnp)238 mp_ioapicprint(void *aux, const char *pnp)
239 {
240 struct apic_attach_args *aaa = aux;
241
242 if (pnp)
243 aprint_normal("ioapic at %s", pnp);
244 aprint_normal(" apid %d", aaa->apic_id);
245 return UNCONF;
246 }
247
248 /*
249 * Map a chunk of memory read-only and return an appropriately
250 * const'ed pointer.
251 */
252
253 static const void *
mpbios_map(paddr_t pa,int len,struct mp_map * handle)254 mpbios_map(paddr_t pa, int len, struct mp_map *handle)
255 {
256 paddr_t pgpa = x86_trunc_page(pa);
257 paddr_t endpa = x86_round_page(pa + len);
258 vaddr_t va = uvm_km_alloc(kernel_map, endpa - pgpa, 0, UVM_KMF_VAONLY);
259 vaddr_t retva = va + (pa & PGOFSET);
260
261 handle->pa = pa;
262 handle->pg = pgpa;
263 handle->psize = len;
264 handle->baseva = va;
265 handle->vsize = endpa-pgpa;
266
267 do {
268 pmap_kenter_pa(va, pgpa, VM_PROT_READ, 0);
269 va += PAGE_SIZE;
270 pgpa += PAGE_SIZE;
271 } while (pgpa < endpa);
272 pmap_update(pmap_kernel());
273
274 return (const void *)retva;
275 }
276
277 inline static void
mpbios_unmap(struct mp_map * handle)278 mpbios_unmap(struct mp_map *handle)
279 {
280 pmap_kremove(handle->baseva, handle->vsize);
281 pmap_update(pmap_kernel());
282 uvm_km_free(kernel_map, handle->baseva, handle->vsize, UVM_KMF_VAONLY);
283 }
284
285 /*
286 * Look for an Intel MP spec table, indicating SMP capable hardware.
287 */
288 int
mpbios_probe(device_t self)289 mpbios_probe(device_t self)
290 {
291 paddr_t ebda, memtop;
292
293 paddr_t cthpa;
294 int cthlen;
295 const uint8_t *mpbios_page;
296 int scan_loc;
297
298 struct mp_map t;
299
300 /* If MP is disabled, don't use MPBIOS or the ioapics. */
301 if ((boothowto & RB_MD1) != 0)
302 return 0;
303
304 /* see if EBDA exists */
305
306 mpbios_page = mpbios_map(0, PAGE_SIZE, &t);
307
308 ebda = *(const uint16_t *)(&mpbios_page[0x40e]);
309 ebda <<= 4;
310
311 memtop = *(const uint16_t *)(&mpbios_page[0x413]);
312 memtop <<= 10;
313
314 mpbios_page = NULL;
315 mpbios_unmap(&t);
316
317 scan_loc = 0;
318
319 if (ebda && ebda < IOM_BEGIN ) {
320 mp_fps = mpbios_search(self, ebda, 1024, &mp_fp_map);
321 if (mp_fps != NULL)
322 goto found;
323 }
324
325 scan_loc = 1;
326
327 if (memtop && memtop <= IOM_BEGIN ) {
328 mp_fps = mpbios_search(self, memtop - 1024, 1024, &mp_fp_map);
329 if (mp_fps != NULL)
330 goto found;
331 }
332
333 scan_loc = 2;
334
335 mp_fps = mpbios_search(self, BIOS_BASE, BIOS_COUNT, &mp_fp_map);
336 if (mp_fps != NULL)
337 goto found;
338
339 #ifdef MPTABLE_LINUX_BUG_COMPAT
340 /*
341 * Linux assumes that it always has 640 kB of base memory and
342 * searches for the MP table at 639k regardless of whether that
343 * address is present in the system memory map. Some VM systems
344 * rely on this buggy behaviour.
345 */
346 mp_fps = mpbios_search(self, 639 * 1024, 1024 / 4, &mp_fp_map);
347 if (mp_fps != NULL)
348 goto found;
349 #endif
350
351
352 /* nothing found */
353 return 0;
354
355 found:
356 if (mp_verbose)
357 aprint_verbose_dev(self,
358 "MP floating pointer found in %s at 0x%jx\n",
359 loc_where[scan_loc], (uintmax_t)mp_fp_map.pa);
360
361 if (mp_fps->pap == 0) {
362 if (mp_fps->mpfb1 == 0) {
363 aprint_error_dev(self, "MP fps invalid: "
364 "no default config and no configuration table\n");
365
366 goto err;
367 }
368 return 10;
369 }
370
371 cthpa = mp_fps->pap;
372
373 mp_cth = mpbios_map (cthpa, sizeof (*mp_cth), &mp_cfg_table_map);
374 cthlen = mp_cth->base_len;
375 mpbios_unmap(&mp_cfg_table_map);
376
377 mp_cth = mpbios_map (cthpa, cthlen, &mp_cfg_table_map);
378
379 if (mp_verbose)
380 aprint_verbose_dev(self,
381 "MP config table at 0x%jx, %d bytes long\n",
382 (uintmax_t)cthpa, cthlen);
383
384 if (mp_cth->signature != MP_CT_SIG) {
385 aprint_error_dev(self, "MP signature mismatch (%x vs %x)\n",
386 MP_CT_SIG, mp_cth->signature);
387 goto err;
388 }
389
390 if (mpbios_cksum(mp_cth, cthlen)) {
391 aprint_error_dev(self,
392 "MP Configuration Table checksum mismatch\n");
393 goto err;
394 }
395 return 10;
396 err:
397 if (mp_fps) {
398 mp_fps = NULL;
399 mpbios_unmap(&mp_fp_map);
400 }
401 if (mp_cth) {
402 mp_cth = NULL;
403 mpbios_unmap(&mp_cfg_table_map);
404 }
405 return 0;
406 }
407
408
409 /*
410 * Simple byte checksum used on config tables.
411 */
412
413 inline static int
mpbios_cksum(const void * start,int len)414 mpbios_cksum(const void *start, int len)
415 {
416 unsigned char res=0;
417 const char *p = start;
418 const char *end = p + len;
419
420 while (p < end)
421 res += *p++;
422
423 return res;
424 }
425
426
427 /*
428 * Look for the MP floating pointer signature in the given physical
429 * address range.
430 *
431 * We map the memory, scan through it, and unmap it.
432 * If we find it, remap the floating pointer structure and return it.
433 */
434
435 const void *
mpbios_search(device_t self,paddr_t start,int count,struct mp_map * map)436 mpbios_search(device_t self, paddr_t start, int count,
437 struct mp_map *map)
438 {
439 struct mp_map t;
440
441 int i, len;
442 const struct mpbios_fps *m;
443 int end = count - sizeof(*m);
444 const uint8_t *base = mpbios_map (start, count, &t);
445
446 if (mp_verbose)
447 aprint_verbose_dev(self,
448 "scanning 0x%jx to 0x%jx for MP signature\n",
449 (uintmax_t)start, (uintmax_t)(start+count-sizeof(*m)));
450
451 for (i = 0; i <= end; i += 4) {
452 m = (const struct mpbios_fps *)&base[i];
453
454 if ((m->signature == MP_FP_SIG) &&
455 ((len = m->length << 4) != 0) &&
456 mpbios_cksum(m, (m->length << 4)) == 0) {
457 mpbios_unmap (&t);
458
459 return mpbios_map(start + i, len, map);
460 }
461 }
462 mpbios_unmap(&t);
463
464 return 0;
465 }
466
467 /*
468 * MP configuration table parsing.
469 */
470
471 static struct mpbios_baseentry mp_conf[] =
472 {
473 {0, 20, 0, "cpu"},
474 {1, 8, 0, "bus"},
475 {2, 8, 0, "ioapic"},
476 {3, 8, 0, "ioint"},
477 {4, 8, 0, "lint"},
478 };
479
480 static struct mp_bus extint_bus = {
481 "ExtINT",
482 -1,
483 mp_print_special_intr,
484 mp_cfg_special_intr,
485 NULL, 0, 0, NULL, 0
486 };
487 static struct mp_bus smi_bus = {
488 "SMI",
489 -1,
490 mp_print_special_intr,
491 mp_cfg_special_intr,
492 NULL, 0, 0, NULL, 0
493 };
494 static struct mp_bus nmi_bus = {
495 "NMI",
496 -1,
497 mp_print_special_intr,
498 mp_cfg_special_intr,
499 NULL, 0, 0, NULL, 0
500 };
501
502 /*
503 * MP default configuration tables (acc. MP Specification Version 1.4)
504 */
505
506 /*
507 * Default configurations always feature two processors and the local APIC IDs
508 * are assigned consecutively by hardware starting from zero (sec. 5). We set
509 * I/O APIC ID to 2.
510 */
511 #define DFLT_IOAPIC_ID 2
512
513 #define ELCR_INV 0x1
514 #define MCA_INV 0x2
515 #define IRQ_VAR 0x4
516 #define INTIN0_NC 0x8
517
518 static const struct dflt_conf_entry dflt_conf_tab[7] = {
519 /*
520 * Assume all systems with EISA and (modern) PCI chipsets have ELCRs
521 * (to control external interrupt-level inverters). MCA systems must
522 * use fixed inverters for INTIN1-INTIN15 (table 5-1; sec. 5.3.2).
523 */
524 {{"ISA ", NULL }, 0 }, /* default config 1 */
525 {{"EISA ", NULL }, ELCR_INV | IRQ_VAR }, /* default config 2 */
526 {{"EISA ", NULL }, ELCR_INV }, /* default config 3 */
527 {{"MCA ", NULL }, MCA_INV }, /* default config 4 */
528 {{"ISA ", "PCI "}, ELCR_INV }, /* default config 5 */
529 {{"EISA ", "PCI "}, ELCR_INV }, /* default config 6 */
530 {{"MCA ", "PCI "}, MCA_INV | INTIN0_NC} /* default config 7 */
531 };
532
533 #define _ (-1) /* INTINx not connected (to a bus interrupt) */
534
535 static const int dflt_bus_irq_tab[2][16] = {
536 /* Default configs 1,3-7 connect INTIN1-INTIN15 to bus interrupts. */
537 {_, 1, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
538 /*
539 * Default config 2 connects neither timer IRQ0 nor DMA chaining to
540 * INTIN2 and INTIN13 (sec. 5.3).
541 */
542 {_, 1, _, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, _, 14, 15}
543 };
544
545 #undef _
546
547 static const uint8_t dflt_lint_tab[2] = {
548 MPS_INTTYPE_ExtINT, MPS_INTTYPE_NMI
549 };
550
551
552 #ifdef MPTABLE_LINUX_BUG_COMPAT
553 /* Compute the correct entry_count value. */
554 static uint16_t
compute_entry_count(const uint8_t * entry,const uint8_t * end)555 compute_entry_count(const uint8_t *entry, const uint8_t *end)
556 {
557 size_t nentries = 0;
558
559 while (entry < end) {
560 switch (*entry) {
561 case MPS_MCT_CPU:
562 case MPS_MCT_BUS:
563 case MPS_MCT_IOAPIC:
564 case MPS_MCT_IOINT:
565 case MPS_MCT_LINT:
566 break;
567 default:
568 panic("%s: Unknown MP Config Entry %d\n", __func__,
569 (int)*entry);
570 }
571 entry += mp_conf[*entry].length;;
572 nentries++;
573 }
574 return (uint16_t)(nentries);
575 }
576 #endif
577 /*
578 * 1st pass on BIOS's Intel MP specification table.
579 *
580 * initializes:
581 * mp_ncpus = 1
582 *
583 * determines:
584 * cpu_apic_address (common to all CPUs)
585 * ioapic_address[N]
586 * mp_naps
587 * mp_nbus
588 * mp_napics
589 * nintrs
590 */
591 void
mpbios_scan(device_t self,int * ncpup)592 mpbios_scan(device_t self, int *ncpup)
593 {
594 const uint8_t *position, *end;
595 size_t i;
596 int count;
597 int type;
598 int intr_cnt, cur_intr;
599 #if NLAPIC > 0
600 paddr_t lapic_base;
601 #endif
602 #ifdef MPTABLE_LINUX_BUG_COMPAT
603 uint16_t countfix = 0;
604 #endif
605 const struct dflt_conf_entry *dflt_conf;
606 const int *dflt_bus_irq;
607 const struct mpbios_int *iep;
608 struct mpbios_int ie;
609
610 aprint_normal_dev(self, "Intel MP Specification ");
611
612 switch (mp_fps->spec_rev) {
613 case 1:
614 aprint_normal("(Version 1.1)");
615 break;
616 case 4:
617 aprint_normal("(Version 1.4)");
618 break;
619 default:
620 aprint_normal("(unrecognized rev %d)", mp_fps->spec_rev);
621 }
622
623 /*
624 * looks like we've got a MP system. start setting up
625 * infrastructure..
626 * XXX is this the right place??
627 */
628
629 #if NACPICA > 0
630 if (mpacpi_ncpu == 0) {
631 #endif
632 #if NLAPIC > 0
633 lapic_base = LAPIC_BASE;
634 if (mp_cth != NULL)
635 lapic_base = (paddr_t)mp_cth->apic_address;
636
637 lapic_boot_init(lapic_base);
638 #endif
639 #if NACPICA > 0
640 }
641 #endif
642
643 /* check for use of 'default' configuration */
644 if (mp_fps->mpfb1 != 0) {
645
646 if (mp_fps->mpfb1 > __arraycount(dflt_conf_tab))
647 panic("Unsupported MP default configuration %d\n",
648 mp_fps->mpfb1);
649
650 aprint_normal("\n");
651 aprint_normal_dev(self, "MP default configuration %d\n",
652 mp_fps->mpfb1);
653
654 dflt_conf = &dflt_conf_tab[mp_fps->mpfb1 - 1];
655 dflt_bus_irq =
656 dflt_bus_irq_tab[(dflt_conf->flags & IRQ_VAR) != 0];
657
658 #if NACPICA > 0
659 if (mpacpi_ncpu == 0)
660 #endif
661 mpbios_dflt_conf_cpu(self);
662
663 #if NACPICA > 0
664 if (mpacpi_nioapic == 0)
665 #endif
666 mpbios_dflt_conf_ioapic(self);
667
668 /*
669 * Walk the table once, counting items.
670 */
671 mp_nbus = 0;
672 for (i = 0; i < __arraycount(dflt_conf->bus_type); i++) {
673 if (dflt_conf->bus_type[i] != NULL)
674 mp_nbus++;
675 }
676 KASSERT(mp_nbus != 0);
677
678 mp_busses = kmem_zalloc(sizeof(struct mp_bus) * mp_nbus,
679 KM_SLEEP);
680 KASSERT(mp_busses != NULL);
681
682 /* INTIN0 */
683 intr_cnt = (dflt_conf->flags & INTIN0_NC) ? 0 : 1;
684 /* INTINx */
685 for (i = 0; i < __arraycount(dflt_bus_irq_tab[0]); i++) {
686 if (dflt_bus_irq[i] >= 0)
687 intr_cnt++;
688 }
689 KASSERT(intr_cnt != 0);
690
691 /* LINTINx */
692 for (i = 0; i < __arraycount(dflt_lint_tab); i++)
693 intr_cnt++;
694
695 mp_intrs = kmem_zalloc(sizeof(struct mp_intr_map) * intr_cnt,
696 KM_SLEEP);
697 KASSERT(mp_intrs != NULL);
698 mp_nintr = intr_cnt;
699
700 /*
701 * Re-walk the table, recording info of interest.
702 */
703 mpbios_dflt_conf_bus(self, dflt_conf);
704 mpbios_dflt_conf_int(self, dflt_conf, dflt_bus_irq);
705 } else {
706 /*
707 * should not happen; mp_probe returns 0 in this case,
708 * but..
709 */
710 if (mp_cth == NULL)
711 panic ("mpbios_scan: no config (can't happen?)");
712
713 printf(" (%8.8s %12.12s)\n",
714 mp_cth->oem_id, mp_cth->product_id);
715
716 /*
717 * Walk the table once, counting items
718 */
719 position = (const uint8_t *)(mp_cth);
720 end = position + mp_cth->base_len;
721 position += sizeof(*mp_cth);
722
723 count = mp_cth->entry_count;
724 #ifdef MPTABLE_LINUX_BUG_COMPAT
725 if (count == 0) {
726 /* count the correct entry_count */
727 countfix = compute_entry_count(position, end);
728 count = countfix;
729 }
730 #endif
731 intr_cnt = 0;
732
733 while ((count--) && (position < end)) {
734 type = *position;
735 if (type >= MPS_MCT_NTYPES) {
736 aprint_error_dev(self, "unknown entry type %x"
737 " in MP config table\n", type);
738 break;
739 }
740 mp_conf[type].count++;
741 if (type == MPS_MCT_BUS) {
742 const struct mpbios_bus *bp =
743 (const struct mpbios_bus *)position;
744 if (bp->bus_id >= mp_nbus)
745 mp_nbus = bp->bus_id + 1;
746 }
747 /*
748 * Count actual interrupt instances.
749 * dst_apic_id of MPS_ALL_APICS means "wired to all
750 * apics of this type".
751 */
752 if (type == MPS_MCT_IOINT) {
753 iep = (const struct mpbios_int *)position;
754 if (iep->dst_apic_id == MPS_ALL_APICS)
755 intr_cnt +=
756 mp_conf[MPS_MCT_IOAPIC].count;
757 else
758 intr_cnt++;
759 } else if (type == MPS_MCT_LINT)
760 intr_cnt++;
761 position += mp_conf[type].length;
762 }
763
764 mp_busses = kmem_zalloc(sizeof(struct mp_bus)*mp_nbus,
765 KM_SLEEP);
766 KASSERT(mp_busses != NULL);
767 mp_intrs = kmem_zalloc(sizeof(struct mp_intr_map)*intr_cnt,
768 KM_SLEEP);
769 KASSERT(mp_intrs != NULL);
770 mp_nintr = intr_cnt;
771
772 /* re-walk the table, recording info of interest */
773 position = (const uint8_t *)mp_cth + sizeof(*mp_cth);
774 count = mp_cth->entry_count;
775 #ifdef MPTABLE_LINUX_BUG_COMPAT
776 if (count == 0)
777 count = countfix;
778 #endif
779 cur_intr = 0;
780
781 while ((count--) && (position < end)) {
782 switch (type = *position) {
783 case MPS_MCT_CPU:
784 #if NACPICA > 0
785 /* ACPI has done this for us */
786 if (mpacpi_ncpu)
787 break;
788 #endif
789 mpbios_cpu(position, self);
790 break;
791 case MPS_MCT_BUS:
792 mpbios_bus(position, self);
793 break;
794 case MPS_MCT_IOAPIC:
795 #if NACPICA > 0
796 /* ACPI has done this for us */
797 if (mpacpi_nioapic)
798 break;
799 #endif
800 mpbios_ioapic(position, self);
801 break;
802 case MPS_MCT_IOINT:
803 iep = (const struct mpbios_int *)position;
804 ie = *iep;
805 if (iep->dst_apic_id == MPS_ALL_APICS) {
806 #if NIOAPIC > 0
807 struct ioapic_softc *sc;
808 for (sc = ioapics ; sc != NULL;
809 sc = sc->sc_next) {
810 ie.dst_apic_id = sc->sc_pic.pic_apicid;
811 mpbios_int((char *)&ie, type,
812 &mp_intrs[cur_intr++]);
813 }
814 #endif
815 } else {
816 mpbios_int(position, type,
817 &mp_intrs[cur_intr++]);
818 }
819 break;
820 case MPS_MCT_LINT:
821 mpbios_int(position, type,
822 &mp_intrs[cur_intr]);
823 cur_intr++;
824 break;
825 default:
826 aprint_error_dev(self, "unknown entry type %x"
827 " in MP config table\n", type);
828 /* NOTREACHED */
829 return;
830 }
831
832 position += mp_conf[type].length;
833 }
834 if (mp_verbose && mp_cth->ext_len)
835 aprint_verbose_dev(self, "MP WARNING: %d bytes of"
836 " extended entries not examined\n",
837 mp_cth->ext_len);
838 }
839 /* Clean up. */
840 mp_fps = NULL;
841 mpbios_unmap (&mp_fp_map);
842 if (mp_cth != NULL) {
843 mp_cth = NULL;
844 mpbios_unmap (&mp_cfg_table_map);
845 }
846 mpbios_scanned = 1;
847
848 *ncpup = mpbios_ncpu;
849 }
850
851 static void
mpbios_cpu(const uint8_t * ent,device_t self)852 mpbios_cpu(const uint8_t *ent, device_t self)
853 {
854 const struct mpbios_proc *entry = (const struct mpbios_proc *)ent;
855 struct cpu_attach_args caa;
856 int locs[CPUBUSCF_NLOCS];
857
858 /* XXX move this into the CPU attachment goo. */
859 /* check for usability */
860 if (!(entry->cpu_flags & PROCENTRY_FLAG_EN))
861 return;
862
863 mpbios_ncpu++;
864
865 /* check for BSP flag */
866 if (entry->cpu_flags & PROCENTRY_FLAG_BP)
867 caa.cpu_role = CPU_ROLE_BP;
868 else
869 caa.cpu_role = CPU_ROLE_AP;
870
871 caa.cpu_id = entry->apic_id;
872 caa.cpu_number = entry->apic_id;
873 caa.cpu_func = &mp_cpu_funcs;
874 locs[CPUBUSCF_APID] = caa.cpu_number;
875
876 config_found(self, &caa, mp_cpuprint,
877 CFARGS(.submatch = config_stdsubmatch,
878 .iattr = "cpubus",
879 .locators = locs));
880 }
881
882 static void
mpbios_dflt_conf_cpu(device_t self)883 mpbios_dflt_conf_cpu(device_t self)
884 {
885 struct mpbios_proc mpp;
886
887 /* mpp.type and mpp.apic_version are irrelevant for mpbios_cpu(). */
888 /*
889 * Default configurations always feature two processors and the local
890 * APIC IDs are assigned consecutively by hardware starting from zero
891 * (sec. 5). Just determine the BSP (APIC ID).
892 */
893 mpp.apic_id = cpu_info_primary.ci_cpuid;
894 mpp.cpu_flags = PROCENTRY_FLAG_EN | PROCENTRY_FLAG_BP;
895 mpbios_cpu((uint8_t *)&mpp, self);
896
897 mpp.apic_id = 1 - cpu_info_primary.ci_cpuid;
898 mpp.cpu_flags = PROCENTRY_FLAG_EN;
899 mpbios_cpu((uint8_t *)&mpp, self);
900 }
901
902 static void
mpbios_dflt_conf_bus(device_t self,const struct dflt_conf_entry * dflt_conf)903 mpbios_dflt_conf_bus(device_t self, const struct dflt_conf_entry *dflt_conf)
904 {
905 struct mpbios_bus mpb;
906 size_t i;
907
908 /* mpb.type is irrelevant for mpbios_bus(). */
909 mpb.bus_id = 0;
910 for (i = 0; i < __arraycount(dflt_conf->bus_type); i++) {
911 if (dflt_conf->bus_type[i] != NULL) {
912 memcpy(mpb.bus_type, dflt_conf->bus_type[i], 6);
913 mpbios_bus((u_int8_t *)&mpb, self);
914 mpb.bus_id++;
915 }
916 }
917 }
918
919 static void
mpbios_dflt_conf_ioapic(device_t self)920 mpbios_dflt_conf_ioapic(device_t self)
921 {
922 struct mpbios_ioapic mpio;
923
924 /* mpio.type is irrelevant for mpbios_ioapic(). */
925 mpio.apic_id = DFLT_IOAPIC_ID;
926 /* XXX Let ioapic driver read real APIC version... */
927 mpio.apic_version = 0;
928 mpio.apic_flags = IOAPICENTRY_FLAG_EN;
929 mpio.apic_address = (uint32_t)IOAPIC_BASE_DEFAULT;
930 mpbios_ioapic((uint8_t *)&mpio, self);
931 }
932
933 static void
mpbios_dflt_conf_int(device_t self,const struct dflt_conf_entry * dflt_conf,const int * dflt_bus_irq)934 mpbios_dflt_conf_int(device_t self, const struct dflt_conf_entry *dflt_conf,
935 const int *dflt_bus_irq)
936 {
937 struct mpbios_int mpi;
938 size_t i;
939 int cur_intr;
940 uint16_t level_inv;
941
942 cur_intr = 0;
943 /*
944 * INTIN0
945 */
946 /*
947 * 8259A INTR is connected to INTIN0 for default configs 1-6, but not
948 * for default config 7 (sec. 5.3).
949 */
950 if ((dflt_conf->flags & INTIN0_NC) == 0) {
951 /* mpi.type is irrelevant for mpbios_int(). */
952 mpi.int_type = MPS_INTTYPE_ExtINT;
953 mpi.int_flags = 0;
954 mpi.src_bus_id = 0;
955 mpi.src_bus_irq = 0;
956 mpi.dst_apic_id = DFLT_IOAPIC_ID;
957 mpi.dst_apic_int = 0;
958 mpbios_int((u_int8_t *)&mpi, MPS_MCT_IOINT,
959 &mp_intrs[cur_intr++]);
960 }
961
962 /*
963 * INTINx
964 */
965 /* mpi.type is irrelevant for mpbios_int(). */
966 mpi.int_type = MPS_INTTYPE_INT;
967 /*
968 * PCI interrupt lines appear as (E)ISA interrupt lines/on bus 0
969 * (sec. 5.2).
970 */
971 mpi.src_bus_id = 0;
972 mpi.dst_apic_id = DFLT_IOAPIC_ID;
973 /*
974 * Compliant systems must convert active-low, level-triggered
975 * interrupts to active-high by external inverters before INTINx
976 *(table 5-1; sec. 5.3.2).
977 */
978 if (dflt_conf->flags & ELCR_INV) {
979 #ifdef X86_MPBIOS_SUPPORT_EISA
980 /* Systems with ELCRs use them to control the inverters. */
981 level_inv = ((uint16_t)inb(ELCR1) << 8) | inb(ELCR0);
982 #else
983 level_inv = 0;
984 #endif
985 } else if (dflt_conf->flags & MCA_INV) {
986 /* MCA systems have fixed inverters. */
987 level_inv = 0xffffU;
988 } else
989 level_inv = 0;
990
991 for (i = 0; i < __arraycount(dflt_bus_irq_tab[0]); i++) {
992 if (dflt_bus_irq[i] >= 0) {
993 mpi.src_bus_irq = (uint8_t)dflt_bus_irq[i];
994 if (level_inv & (1U << mpi.src_bus_irq))
995 mpi.int_flags = (MPS_INTTR_LEVEL << 2)
996 | MPS_INTPO_ACTHI;
997 else
998 mpi.int_flags = 0; /* conforms to bus spec. */
999 mpi.dst_apic_int = (uint8_t)i;
1000 mpbios_int((u_int8_t *)&mpi, MPS_MCT_IOINT,
1001 &mp_intrs[cur_intr++]);
1002 }
1003 }
1004
1005 /*
1006 * LINTINx
1007 */
1008 /* mpi.type is irrelevant for mpbios_int(). */
1009 mpi.int_flags = 0;
1010 mpi.src_bus_id = 0;
1011 mpi.src_bus_irq = 0;
1012 mpi.dst_apic_id = MPS_ALL_APICS;
1013 for (i = 0; i < __arraycount(dflt_lint_tab); i++) {
1014 mpi.int_type = dflt_lint_tab[i];
1015 mpi.dst_apic_int = (uint8_t)i;
1016 mpbios_int((u_int8_t *)&mpi, MPS_MCT_LINT,
1017 &mp_intrs[cur_intr++]);
1018 }
1019 }
1020
1021 /*
1022 * The following functions conspire to compute base ioapic redirection
1023 * table entry for a given interrupt line.
1024 *
1025 * Fill in: trigger mode, polarity, and possibly delivery mode.
1026 */
1027 static void
mp_cfg_special_intr(const struct mpbios_int * entry,uint32_t * redir)1028 mp_cfg_special_intr(const struct mpbios_int *entry, uint32_t *redir)
1029 {
1030
1031 /*
1032 * All of these require edge triggered, zero vector,
1033 * appropriate delivery mode.
1034 * see page 13 of the 82093AA datasheet.
1035 */
1036 *redir &= ~IOAPIC_REDLO_DEL_MASK;
1037 *redir &= ~IOAPIC_REDLO_VECTOR_MASK;
1038 *redir &= ~IOAPIC_REDLO_LEVEL;
1039
1040 switch (entry->int_type) {
1041 case MPS_INTTYPE_NMI:
1042 *redir |= (IOAPIC_REDLO_DEL_NMI<<IOAPIC_REDLO_DEL_SHIFT);
1043 break;
1044
1045 case MPS_INTTYPE_SMI:
1046 *redir |= (IOAPIC_REDLO_DEL_SMI<<IOAPIC_REDLO_DEL_SHIFT);
1047 break;
1048
1049 case MPS_INTTYPE_ExtINT:
1050 /*
1051 * We are using the ioapic in "native" mode.
1052 * This indicates where the 8259 is wired to the ioapic
1053 * and/or local apic..
1054 */
1055 *redir |= (IOAPIC_REDLO_DEL_EXTINT<<IOAPIC_REDLO_DEL_SHIFT);
1056 *redir |= (IOAPIC_REDLO_MASK);
1057 break;
1058 }
1059 }
1060
1061 /* XXX too much duplicated code here. */
1062
1063 static void
mp_cfg_pci_intr(const struct mpbios_int * entry,uint32_t * redir)1064 mp_cfg_pci_intr(const struct mpbios_int *entry, uint32_t *redir)
1065 {
1066 int mpspo = entry->int_flags & 0x03; /* XXX magic */
1067 int mpstrig = (entry->int_flags >> 2) & 0x03; /* XXX magic */
1068
1069 *redir &= ~IOAPIC_REDLO_DEL_MASK;
1070 switch (mpspo) {
1071 case MPS_INTPO_ACTHI:
1072 *redir &= ~IOAPIC_REDLO_ACTLO;
1073 break;
1074 case MPS_INTPO_DEF:
1075 case MPS_INTPO_ACTLO:
1076 *redir |= IOAPIC_REDLO_ACTLO;
1077 break;
1078 default:
1079 panic("unknown MPS interrupt polarity %d", mpspo);
1080 }
1081
1082 if (entry->int_type != MPS_INTTYPE_INT) {
1083 mp_cfg_special_intr(entry, redir);
1084 return;
1085 }
1086 *redir |= (IOAPIC_REDLO_DEL_FIXED<<IOAPIC_REDLO_DEL_SHIFT);
1087
1088 switch (mpstrig) {
1089 case MPS_INTTR_DEF:
1090 case MPS_INTTR_LEVEL:
1091 *redir |= IOAPIC_REDLO_LEVEL;
1092 break;
1093 case MPS_INTTR_EDGE:
1094 *redir &= ~IOAPIC_REDLO_LEVEL;
1095 break;
1096 default:
1097 panic("unknown MPS interrupt trigger %d", mpstrig);
1098 }
1099 }
1100
1101 #ifdef X86_MPBIOS_SUPPORT_EISA
1102 static void
mp_cfg_eisa_intr(const struct mpbios_int * entry,uint32_t * redir)1103 mp_cfg_eisa_intr(const struct mpbios_int *entry, uint32_t *redir)
1104 {
1105 int mpspo = entry->int_flags & 0x03; /* XXX magic */
1106 int mpstrig = (entry->int_flags >> 2) & 0x03; /* XXX magic */
1107
1108 *redir &= ~IOAPIC_REDLO_DEL_MASK;
1109 switch (mpspo) {
1110 case MPS_INTPO_DEF:
1111 case MPS_INTPO_ACTHI:
1112 *redir &= ~IOAPIC_REDLO_ACTLO;
1113 break;
1114 case MPS_INTPO_ACTLO:
1115 *redir |= IOAPIC_REDLO_ACTLO;
1116 break;
1117 default:
1118 panic("unknown MPS interrupt polarity %d", mpspo);
1119 }
1120
1121 if (entry->int_type != MPS_INTTYPE_INT) {
1122 mp_cfg_special_intr(entry, redir);
1123 return;
1124 }
1125 *redir |= (IOAPIC_REDLO_DEL_FIXED << IOAPIC_REDLO_DEL_SHIFT);
1126
1127 switch (mpstrig) {
1128 case MPS_INTTR_LEVEL:
1129 *redir |= IOAPIC_REDLO_LEVEL;
1130 break;
1131 case MPS_INTTR_EDGE:
1132 *redir &= ~IOAPIC_REDLO_LEVEL;
1133 break;
1134 case MPS_INTTR_DEF:
1135 /*
1136 * Set "default" setting based on ELCR value snagged
1137 * earlier.
1138 */
1139 if (mp_busses[entry->src_bus_id].mb_data &
1140 (1 << entry->src_bus_irq)) {
1141 *redir |= IOAPIC_REDLO_LEVEL;
1142 } else {
1143 *redir &= ~IOAPIC_REDLO_LEVEL;
1144 }
1145 break;
1146 default:
1147 panic("unknown MPS interrupt trigger %d", mpstrig);
1148 }
1149 }
1150 #endif
1151
1152
1153 static void
mp_cfg_isa_intr(const struct mpbios_int * entry,uint32_t * redir)1154 mp_cfg_isa_intr(const struct mpbios_int *entry, uint32_t *redir)
1155 {
1156 int mpspo = entry->int_flags & 0x03; /* XXX magic */
1157 int mpstrig = (entry->int_flags >> 2) & 0x03; /* XXX magic */
1158
1159 *redir &= ~IOAPIC_REDLO_DEL_MASK;
1160 switch (mpspo) {
1161 case MPS_INTPO_DEF:
1162 case MPS_INTPO_ACTHI:
1163 *redir &= ~IOAPIC_REDLO_ACTLO;
1164 break;
1165 case MPS_INTPO_ACTLO:
1166 *redir |= IOAPIC_REDLO_ACTLO;
1167 break;
1168 default:
1169 panic("unknown MPS interrupt polarity %d", mpspo);
1170 }
1171
1172 if (entry->int_type != MPS_INTTYPE_INT) {
1173 mp_cfg_special_intr(entry, redir);
1174 return;
1175 }
1176 *redir |= (IOAPIC_REDLO_DEL_FIXED << IOAPIC_REDLO_DEL_SHIFT);
1177
1178 switch (mpstrig) {
1179 case MPS_INTTR_LEVEL:
1180 *redir |= IOAPIC_REDLO_LEVEL;
1181 break;
1182 case MPS_INTTR_DEF:
1183 case MPS_INTTR_EDGE:
1184 *redir &= ~IOAPIC_REDLO_LEVEL;
1185 break;
1186 default:
1187 panic("unknown MPS interrupt trigger %d", mpstrig);
1188 }
1189 }
1190
1191
1192 static void
mp_print_special_intr(int intr)1193 mp_print_special_intr(int intr)
1194 {
1195 }
1196
1197 static void
mp_print_pci_intr(int intr)1198 mp_print_pci_intr(int intr)
1199 {
1200 printf(" device %d INT_%c", (intr>>2)&0x1f, 'A' + (intr & 0x3));
1201 }
1202
1203 static void
mp_print_isa_intr(int intr)1204 mp_print_isa_intr(int intr)
1205 {
1206 printf(" irq %d", intr);
1207 }
1208
1209 #ifdef X86_MPBIOS_SUPPORT_EISA
1210 static void
mp_print_eisa_intr(int intr)1211 mp_print_eisa_intr(int intr)
1212 {
1213 printf(" EISA irq %d", intr);
1214 }
1215 #endif
1216
1217
1218
1219 #define TAB_UNIT 4
1220 #define TAB_ROUND(a) _TAB_ROUND(a, TAB_UNIT)
1221
1222 #define _TAB_ROUND(a,u) (((a) + (u - 1)) & ~(u-1))
1223 #define EXTEND_TAB(a,u) (!(_TAB_ROUND(a,u) == _TAB_ROUND((a+1),u)))
1224
1225 static void
mpbios_bus(const uint8_t * ent,device_t self)1226 mpbios_bus(const uint8_t *ent, device_t self)
1227 {
1228 const struct mpbios_bus *entry = (const struct mpbios_bus *)ent;
1229 int bus_id = entry->bus_id;
1230
1231 aprint_verbose("mpbios: bus %d is type %6.6s\n", bus_id,
1232 entry->bus_type);
1233
1234 #ifdef DIAGNOSTIC
1235 /*
1236 * This "should not happen" unless the table changes out
1237 * from underneath us
1238 */
1239 if (bus_id >= mp_nbus) {
1240 panic("mpbios: bus number %d out of range?? (type %6.6s)\n",
1241 bus_id, entry->bus_type);
1242 }
1243 #endif
1244
1245 mp_busses[bus_id].mb_intrs = NULL;
1246
1247 if (memcmp(entry->bus_type, "PCI ", 6) == 0) {
1248 mp_busses[bus_id].mb_name = "pci";
1249 mp_busses[bus_id].mb_idx = bus_id;
1250 mp_busses[bus_id].mb_intr_print = mp_print_pci_intr;
1251 mp_busses[bus_id].mb_intr_cfg = mp_cfg_pci_intr;
1252 #ifdef X86_MPBIOS_SUPPORT_EISA
1253 } else if (memcmp(entry->bus_type, "EISA ", 6) == 0) {
1254 mp_busses[bus_id].mb_name = "eisa";
1255 mp_busses[bus_id].mb_idx = bus_id;
1256 mp_busses[bus_id].mb_intr_print = mp_print_eisa_intr;
1257 mp_busses[bus_id].mb_intr_cfg = mp_cfg_eisa_intr;
1258
1259 mp_busses[bus_id].mb_data = inb(ELCR0) | (inb(ELCR1) << 8);
1260
1261 if (mp_eisa_bus != -1)
1262 aprint_error("oops: multiple isa busses?\n");
1263 else
1264 mp_eisa_bus = bus_id;
1265 #endif
1266
1267 } else if (memcmp(entry->bus_type, "ISA ", 6) == 0) {
1268 mp_busses[bus_id].mb_name = "isa";
1269 mp_busses[bus_id].mb_idx = 0; /* XXX */
1270 mp_busses[bus_id].mb_intr_print = mp_print_isa_intr;
1271 mp_busses[bus_id].mb_intr_cfg = mp_cfg_isa_intr;
1272 if (mp_isa_bus != -1)
1273 printf("oops: multiple isa busses?\n");
1274 else
1275 mp_isa_bus = bus_id;
1276 } else
1277 aprint_error_dev(self, "unsupported bus type %6.6s\n",
1278 entry->bus_type);
1279 }
1280
1281
1282 static void
mpbios_ioapic(const uint8_t * ent,device_t self)1283 mpbios_ioapic(const uint8_t *ent, device_t self)
1284 {
1285 const struct mpbios_ioapic *entry = (const struct mpbios_ioapic *)ent;
1286
1287 /* XXX let flags checking happen in ioapic driver.. */
1288 if (!(entry->apic_flags & IOAPICENTRY_FLAG_EN))
1289 return;
1290
1291 mpbios_nioapic++;
1292
1293 #if NIOAPIC > 0
1294 {
1295 int locs[IOAPICBUSCF_NLOCS];
1296 struct apic_attach_args aaa;
1297
1298 aaa.apic_id = entry->apic_id;
1299 aaa.apic_version = entry->apic_version;
1300 aaa.apic_address = (paddr_t)entry->apic_address;
1301 aaa.apic_vecbase = -1;
1302 aaa.flags = (mp_fps->mpfb2 & 0x80) ? IOAPIC_PICMODE : IOAPIC_VWIRE;
1303 locs[IOAPICBUSCF_APID] = aaa.apic_id;
1304
1305 config_found(self, &aaa, mp_ioapicprint,
1306 CFARGS(.submatch = config_stdsubmatch,
1307 .iattr = "ioapicbus",
1308 .locators = locs));
1309 }
1310 #endif
1311 }
1312
1313 static const char inttype_fmt[] = "\177\020"
1314 "f\0\2type\0" "=\1NMI\0" "=\2SMI\0" "=\3ExtINT\0";
1315
1316 static const char flagtype_fmt[] = "\177\020"
1317 "f\0\2pol\0" "=\1Act Hi\0" "=\3Act Lo\0"
1318 "f\2\2trig\0" "=\1Edge\0" "=\3Level\0";
1319
1320 static void
mpbios_int(const uint8_t * ent,int enttype,struct mp_intr_map * mpi)1321 mpbios_int(const uint8_t *ent, int enttype, struct mp_intr_map *mpi)
1322 {
1323 const struct mpbios_int *entry = (const struct mpbios_int *)ent;
1324 struct ioapic_softc *sc = NULL;
1325 struct pic *sc2;
1326
1327 struct mp_intr_map *altmpi;
1328 struct mp_bus *mpb;
1329
1330 uint32_t id = entry->dst_apic_id;
1331 uint32_t pin = entry->dst_apic_int;
1332 uint32_t bus = entry->src_bus_id;
1333 uint32_t dev = entry->src_bus_irq;
1334 uint32_t type = entry->int_type;
1335 uint32_t flags = entry->int_flags;
1336
1337 switch (type) {
1338 case MPS_INTTYPE_INT:
1339 mpb = &(mp_busses[bus]);
1340 break;
1341 case MPS_INTTYPE_ExtINT:
1342 mpb = &extint_bus;
1343 break;
1344 case MPS_INTTYPE_SMI:
1345 mpb = &smi_bus;
1346 break;
1347 case MPS_INTTYPE_NMI:
1348 mpb = &nmi_bus;
1349 break;
1350 default:
1351 panic("unknown MPS interrupt type %d", entry->int_type);
1352 }
1353
1354 mpi->next = mpb->mb_intrs;
1355 mpb->mb_intrs = mpi;
1356 mpi->bus = mpb;
1357 mpi->bus_pin = dev;
1358 mpi->global_int = -1;
1359
1360 mpi->type = type;
1361 mpi->flags = flags;
1362 mpi->redir = 0;
1363 if (mpb->mb_intr_cfg == NULL) {
1364 printf("mpbios: can't find bus %d for apic %d pin %d\n",
1365 bus, id, pin);
1366 return;
1367 }
1368
1369 (*mpb->mb_intr_cfg)(entry, &mpi->redir);
1370
1371 if (enttype == MPS_MCT_IOINT) {
1372 #if NIOAPIC > 0
1373 sc = ioapic_find(id);
1374 #else
1375 sc = NULL;
1376 #endif
1377 if (sc == NULL) {
1378 #if NIOAPIC > 0
1379 /*
1380 * If we couldn't find an ioapic by given id, retry to
1381 * get it by a pin number.
1382 */
1383 sc = ioapic_find_bybase(pin);
1384 if (sc == NULL) {
1385 aprint_error("mpbios: can't find ioapic by"
1386 " neither apid(%d) nor pin number(%d)\n",
1387 id, pin);
1388 return;
1389 }
1390 aprint_verbose("mpbios: use apid %d instead of %d\n",
1391 sc->sc_pic.pic_apicid, id);
1392 id = sc->sc_pic.pic_apicid;
1393 #else
1394 aprint_error("mpbios: can't find ioapic %d\n", id);
1395 return;
1396 #endif
1397 }
1398
1399 /*
1400 * XXX workaround for broken BIOSs that put the ACPI global
1401 * interrupt number in the entry, not the pin number.
1402 */
1403 if (pin >= sc->sc_apic_sz) {
1404 sc2 = intr_findpic(pin);
1405 if (sc2 && sc2->pic_ioapic != sc) {
1406 printf("mpbios: bad pin %d for apic %d\n",
1407 pin, id);
1408 return;
1409 }
1410 printf("mpbios: WARNING: pin %d for apic %d too high; "
1411 "assuming ACPI global int value\n", pin, id);
1412 pin -= sc->sc_apic_vecbase;
1413 }
1414
1415 mpi->ioapic = (struct pic *)sc;
1416 mpi->ioapic_pin = pin;
1417
1418 altmpi = sc->sc_pins[pin].ip_map;
1419
1420 if (altmpi != NULL) {
1421 if ((altmpi->type != type) ||
1422 (altmpi->flags != flags)) {
1423 printf("%s: conflicting map entries for pin %d\n",
1424 device_xname(sc->sc_dev), pin);
1425 }
1426 } else
1427 sc->sc_pins[pin].ip_map = mpi;
1428 } else {
1429 if (pin >= 2)
1430 printf("pin %d of local apic doesn't exist!\n", pin);
1431 else {
1432 mpi->ioapic = NULL;
1433 mpi->ioapic_pin = pin;
1434 mpi->cpu_id = id;
1435 }
1436 }
1437
1438 mpi->ioapic_ih = APIC_INT_VIA_APIC |
1439 ((id << APIC_INT_APIC_SHIFT) | (pin << APIC_INT_PIN_SHIFT));
1440
1441 if (mp_verbose) {
1442 char buf[256];
1443
1444 printf("%s: int%d attached to %s",
1445 sc ? device_xname(sc->sc_dev) : "local apic",
1446 pin, mpb->mb_name);
1447
1448 if (mpb->mb_idx != -1)
1449 printf("%d", mpb->mb_idx);
1450
1451 (*(mpb->mb_intr_print))(dev);
1452
1453 snprintb(buf, sizeof(buf), inttype_fmt, type);
1454 printf(" (type %s", buf);
1455
1456 snprintb(buf, sizeof(buf), flagtype_fmt, flags);
1457 printf(" flags %s)\n", buf);
1458 }
1459 }
1460
1461 #if NPCI > 0
1462 int
mpbios_pci_attach_hook(device_t parent,device_t self,struct pcibus_attach_args * pba)1463 mpbios_pci_attach_hook(device_t parent, device_t self,
1464 struct pcibus_attach_args *pba)
1465 {
1466 struct mp_bus *mpb;
1467
1468 if (mpbios_scanned == 0)
1469 return ENOENT;
1470
1471 if (pba->pba_bus >= mp_isa_bus) {
1472 intr_add_pcibus(pba);
1473 return 0;
1474 }
1475
1476 mpb = &mp_busses[pba->pba_bus];
1477 if (mpb->mb_name != NULL) {
1478 if (strcmp(mpb->mb_name, "pci"))
1479 return EINVAL;
1480 } else
1481 mpb->mb_name = "pci";
1482
1483 if (mp_verbose)
1484 printf("\n%s: added to list as bus %d", device_xname(parent),
1485 pba->pba_bus);
1486
1487 mpb->mb_dev = self;
1488 mpb->mb_pci_bridge_tag = pba->pba_bridgetag;
1489 mpb->mb_pci_chipset_tag = pba->pba_pc;
1490 return 0;
1491 }
1492 #endif
1493