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 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 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 * 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 1193 mp_print_special_intr(int intr) 1194 { 1195 } 1196 1197 static void 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 1204 mp_print_isa_intr(int intr) 1205 { 1206 printf(" irq %d", intr); 1207 } 1208 1209 #ifdef X86_MPBIOS_SUPPORT_EISA 1210 static void 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 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 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 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 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