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