Home | History | Annotate | Line # | Download | only in x86
      1 /*	$NetBSD: mpacpi.c,v 1.112 2025/10/06 12:27:52 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2003 Wasabi Systems, Inc.
      5  * All rights reserved.
      6  *
      7  * Written by Frank van der Linden for Wasabi Systems, Inc.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *      This product includes software developed for the NetBSD Project by
     20  *      Wasabi Systems, Inc.
     21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22  *    or promote products derived from this software without specific prior
     23  *    written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  * POSSIBILITY OF SUCH DAMAGE.
     36  */
     37 
     38 #include <sys/cdefs.h>
     39 __KERNEL_RCSID(0, "$NetBSD: mpacpi.c,v 1.112 2025/10/06 12:27:52 riastradh Exp $");
     40 
     41 #include "acpica.h"
     42 #include "opt_acpi.h"
     43 #include "opt_ddb.h"
     44 #include "opt_mpbios.h"
     45 #include "opt_multiprocessor.h"
     46 #include "opt_pci.h"
     47 #include "pchb.h"
     48 
     49 #include <sys/param.h>
     50 #include <sys/systm.h>
     51 #include <sys/kernel.h>
     52 #include <sys/device.h>
     53 #include <sys/kmem.h>
     54 #include <sys/queue.h>
     55 
     56 #include <uvm/uvm_extern.h>
     57 
     58 #include <machine/specialreg.h>
     59 #include <machine/cpuvar.h>
     60 #include <sys/bus.h>
     61 #include <machine/mpacpi.h>
     62 #include <machine/mpbiosvar.h>
     63 
     64 #include <machine/i82093reg.h>
     65 #include <machine/i82093var.h>
     66 #include <machine/i82489reg.h>
     67 #include <machine/i82489var.h>
     68 #include <dev/isa/isareg.h>
     69 #include <dev/pci/pcivar.h>
     70 #include <dev/pci/pcidevs.h>
     71 #include <dev/pci/ppbreg.h>
     72 
     73 #include <dev/acpi/acpi_mcfg.h>
     74 #include <dev/acpi/acpica.h>
     75 #include <dev/acpi/acpireg.h>
     76 #include <dev/acpi/acpivar.h>
     77 
     78 #include <dev/cons.h>
     79 
     80 #define _COMPONENT     ACPI_RESOURCE_COMPONENT
     81 ACPI_MODULE_NAME       ("mpacpi")
     82 
     83 #include "pci.h"
     84 #include "ioapic.h"
     85 #include "lapic.h"
     86 
     87 #include "locators.h"
     88 
     89 /* XXX room for PCI-to-PCI bus */
     90 #define BUS_BUFFER (16)
     91 
     92 #if NPCI > 0
     93 struct mpacpi_pcibus {
     94 	TAILQ_ENTRY(mpacpi_pcibus) mpr_list;
     95 	ACPI_HANDLE mpr_handle;
     96 	devhandle_t mpr_devhandle;
     97 	ACPI_BUFFER mpr_buf;		/* preserve _PRT */
     98 	int mpr_seg;			/* PCI segment number */
     99 	int mpr_bus;			/* PCI bus number */
    100 };
    101 
    102 static TAILQ_HEAD(, mpacpi_pcibus) mpacpi_pcibusses;
    103 
    104 #endif
    105 
    106 static int mpacpi_cpuprint(void *, const char *);
    107 static int mpacpi_ioapicprint(void *, const char *);
    108 
    109 /* acpi_madt_walk callbacks */
    110 static ACPI_STATUS mpacpi_count(ACPI_SUBTABLE_HEADER *, void *);
    111 static ACPI_STATUS mpacpi_config_cpu(ACPI_SUBTABLE_HEADER *, void *);
    112 static ACPI_STATUS mpacpi_config_ioapic(ACPI_SUBTABLE_HEADER *, void *);
    113 static ACPI_STATUS mpacpi_nonpci_intr(ACPI_SUBTABLE_HEADER *, void *);
    114 
    115 #if NPCI > 0
    116 static int mpacpi_pcircount(struct mpacpi_pcibus *);
    117 static int mpacpi_pciroute(struct mpacpi_pcibus *);
    118 static int mpacpi_find_pcibusses(struct acpi_softc *);
    119 
    120 static void mpacpi_print_pci_intr(int);
    121 #endif
    122 
    123 static void mpacpi_config_irouting(struct acpi_softc *);
    124 
    125 static void mpacpi_print_intr(struct mp_intr_map *);
    126 static void mpacpi_print_isa_intr(int);
    127 
    128 static void mpacpi_user_continue(const char *fmt, ...);
    129 
    130 #ifdef DDB
    131 void mpacpi_dump(void);
    132 #endif
    133 
    134 int mpacpi_nioapic;			/* number of ioapics */
    135 int mpacpi_ncpu;			/* number of cpus */
    136 int mpacpi_nintsrc;			/* number of non-device interrupts */
    137 
    138 #if NPCI > 0
    139 static int mpacpi_npci;
    140 static int mpacpi_maxpci;
    141 static int mpacpi_npciroots;
    142 #endif
    143 
    144 static int mpacpi_intr_index;
    145 static paddr_t mpacpi_lapic_base = LAPIC_BASE;
    146 
    147 int mpacpi_step;
    148 int mpacpi_force;
    149 
    150 static int
    151 mpacpi_cpuprint(void *aux, const char *pnp)
    152 {
    153 	struct cpu_attach_args *caa = aux;
    154 
    155 	if (pnp)
    156 		aprint_normal("cpu at %s", pnp);
    157 	aprint_normal(" apid %d", caa->cpu_number);
    158 	return UNCONF;
    159 }
    160 
    161 static int
    162 mpacpi_ioapicprint(void *aux, const char *pnp)
    163 {
    164 	struct apic_attach_args *aaa = aux;
    165 
    166 	if (pnp)
    167 		aprint_normal("ioapic at %s", pnp);
    168 	aprint_normal(" apid %d", aaa->apic_id);
    169 	return UNCONF;
    170 }
    171 
    172 /*
    173  * Handle special interrupt sources and overrides from the MADT.
    174  * This is a callback function for acpi_madt_walk() (see acpi.c).
    175  */
    176 static ACPI_STATUS
    177 mpacpi_nonpci_intr(ACPI_SUBTABLE_HEADER *hdrp, void *aux)
    178 {
    179 	int *index = aux, pin, lindex;
    180 	struct mp_intr_map *mpi;
    181 	ACPI_MADT_NMI_SOURCE *ioapic_nmi;
    182 	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
    183 	ACPI_MADT_INTERRUPT_OVERRIDE *isa_ovr;
    184 	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
    185 	struct pic *pic;
    186 	extern struct acpi_softc *acpi_softc;	/* XXX */
    187 
    188 	switch (hdrp->Type) {
    189 	case ACPI_MADT_TYPE_NMI_SOURCE:
    190 		ioapic_nmi = (ACPI_MADT_NMI_SOURCE *)hdrp;
    191 		pic = intr_findpic(ioapic_nmi->GlobalIrq);
    192 		if (pic == NULL)
    193 			break;
    194 #if NIOAPIC == 0
    195 		if (pic->pic_type == PIC_IOAPIC)
    196 			break;
    197 #endif
    198 		mpi = &mp_intrs[*index];
    199 		(*index)++;
    200 		mpi->next = NULL;
    201 		mpi->bus = NULL;
    202 		mpi->type = MPS_INTTYPE_NMI;
    203 		mpi->ioapic = pic;
    204 		pin = ioapic_nmi->GlobalIrq - pic->pic_vecbase;
    205 		mpi->ioapic_pin = pin;
    206 		mpi->bus_pin = -1;
    207 		mpi->redir = (IOAPIC_REDLO_DEL_NMI << IOAPIC_REDLO_DEL_SHIFT);
    208 #if NIOAPIC > 0
    209 		if (pic->pic_type == PIC_IOAPIC) {
    210 			pic->pic_ioapic->sc_pins[pin].ip_map = mpi;
    211 			mpi->ioapic_ih = APIC_INT_VIA_APIC |
    212 			    (pic->pic_apicid << APIC_INT_APIC_SHIFT) |
    213 			    (pin << APIC_INT_PIN_SHIFT);
    214 		} else
    215 #endif
    216 			mpi->ioapic_ih = pin;
    217 		mpi->flags = ioapic_nmi->IntiFlags;
    218 		mpi->global_int = ioapic_nmi->GlobalIrq;
    219 		break;
    220 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
    221 		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)hdrp;
    222 		mpi = &mp_intrs[*index];
    223 		(*index)++;
    224 		mpi->next = NULL;
    225 		mpi->bus = NULL;
    226 		mpi->ioapic = NULL;
    227 		mpi->type = MPS_INTTYPE_NMI;
    228 		mpi->ioapic_pin = lapic_nmi->Lint;
    229 		mpi->cpu_id = lapic_nmi->ProcessorId;
    230 		mpi->redir = (IOAPIC_REDLO_DEL_NMI << IOAPIC_REDLO_DEL_SHIFT);
    231 		mpi->global_int = -1;
    232 		break;
    233 	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
    234 		isa_ovr = (ACPI_MADT_INTERRUPT_OVERRIDE *)hdrp;
    235 		if (mp_verbose) {
    236 			printf("mpacpi: ISA interrupt override %d -> %d (%d/%d)\n",
    237 			    isa_ovr->SourceIrq, isa_ovr->GlobalIrq,
    238 			    isa_ovr->IntiFlags & ACPI_MADT_POLARITY_MASK,
    239 			    (isa_ovr->IntiFlags & ACPI_MADT_TRIGGER_MASK) >>2);
    240 		}
    241 		if (isa_ovr->SourceIrq > 15 || isa_ovr->SourceIrq == 2 ||
    242 		    (isa_ovr->SourceIrq == 0 && isa_ovr->GlobalIrq == 2 &&
    243 			(acpi_softc->sc_quirks & ACPI_QUIRK_IRQ0)))
    244 			break;
    245 		pic = intr_findpic(isa_ovr->GlobalIrq);
    246 		if (pic == NULL)
    247 			break;
    248 #if NIOAPIC == 0
    249 		if (pic->pic_type == PIC_IOAPIC)
    250 			break;
    251 #endif
    252 		pin = isa_ovr->GlobalIrq - pic->pic_vecbase;
    253 		lindex = isa_ovr->SourceIrq;
    254 		/*
    255 		 * IRQ 2 was skipped in the default setup.
    256 		 */
    257 		if (lindex > 2)
    258 			lindex--;
    259 		mpi = &mp_intrs[lindex];
    260 #if NIOAPIC > 0
    261 		if (pic->pic_type == PIC_IOAPIC) {
    262 			mpi->ioapic_ih = APIC_INT_VIA_APIC |
    263 			    (pic->pic_apicid << APIC_INT_APIC_SHIFT) |
    264 			    (pin << APIC_INT_PIN_SHIFT);
    265 		} else
    266 #endif
    267 			mpi->ioapic_ih = pin;
    268 		mpi->bus_pin = isa_ovr->SourceIrq;
    269 		mpi->ioapic = (struct pic *)pic;
    270 		mpi->ioapic_pin = pin;
    271 		mpi->sflags |= MPI_OVR;
    272 		mpi->redir = 0;
    273 		mpi->global_int = isa_ovr->GlobalIrq;
    274 		switch (isa_ovr->IntiFlags & ACPI_MADT_POLARITY_MASK) {
    275 		case ACPI_MADT_POLARITY_ACTIVE_HIGH:
    276 			mpi->redir &= ~IOAPIC_REDLO_ACTLO;
    277 			break;
    278 		case ACPI_MADT_POLARITY_ACTIVE_LOW:
    279 			mpi->redir |= IOAPIC_REDLO_ACTLO;
    280 			break;
    281 		case ACPI_MADT_POLARITY_CONFORMS:
    282 			if (isa_ovr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
    283 				mpi->redir |= IOAPIC_REDLO_ACTLO;
    284 			else
    285 				mpi->redir &= ~IOAPIC_REDLO_ACTLO;
    286 			break;
    287 		}
    288 		mpi->redir |= (IOAPIC_REDLO_DEL_FIXED<<IOAPIC_REDLO_DEL_SHIFT);
    289 		switch (isa_ovr->IntiFlags & ACPI_MADT_TRIGGER_MASK) {
    290 		case ACPI_MADT_TRIGGER_LEVEL:
    291 			mpi->redir |= IOAPIC_REDLO_LEVEL;
    292 			break;
    293 		case ACPI_MADT_TRIGGER_EDGE:
    294 			mpi->redir &= ~IOAPIC_REDLO_LEVEL;
    295 			break;
    296 		case ACPI_MADT_TRIGGER_CONFORMS:
    297 			if (isa_ovr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
    298 				mpi->redir |= IOAPIC_REDLO_LEVEL;
    299 			else
    300 				mpi->redir &= ~IOAPIC_REDLO_LEVEL;
    301 			break;
    302 		}
    303 		mpi->flags = isa_ovr->IntiFlags;
    304 #if NIOAPIC > 0
    305 		if (pic->pic_type == PIC_IOAPIC)
    306 			pic->pic_ioapic->sc_pins[pin].ip_map = mpi;
    307 #endif
    308 		break;
    309 
    310 	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
    311 		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)hdrp;
    312 
    313 		mpi = &mp_intrs[*index];
    314 		(*index)++;
    315 		mpi->next = NULL;
    316 		mpi->bus = NULL;
    317 		mpi->ioapic = NULL;
    318 		mpi->type = MPS_INTTYPE_NMI;
    319 		mpi->ioapic_pin = x2apic_nmi->Lint;
    320 		mpi->cpu_id = x2apic_nmi->Uid;
    321 		mpi->redir = (IOAPIC_REDLO_DEL_NMI << IOAPIC_REDLO_DEL_SHIFT);
    322 		mpi->global_int = -1;
    323 		break;
    324 
    325 	default:
    326 		break;
    327 	}
    328 	return AE_OK;
    329 }
    330 
    331 /*
    332  * Count various MP resources present in the MADT.
    333  * This is a callback function for acpi_madt_walk().
    334  */
    335 static ACPI_STATUS
    336 mpacpi_count(ACPI_SUBTABLE_HEADER *hdrp, void *aux)
    337 {
    338 	ACPI_MADT_LOCAL_APIC_OVERRIDE *lop;
    339 
    340 	switch (hdrp->Type) {
    341 	case ACPI_MADT_TYPE_LOCAL_APIC:
    342 	case ACPI_MADT_TYPE_LOCAL_X2APIC:
    343 		mpacpi_ncpu++;
    344 		break;
    345 	case ACPI_MADT_TYPE_IO_APIC:
    346 		mpacpi_nioapic++;
    347 		break;
    348 	case ACPI_MADT_TYPE_NMI_SOURCE:
    349 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
    350 	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
    351 		mpacpi_nintsrc++;
    352 		break;
    353 	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
    354 		lop = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)hdrp;
    355 		mpacpi_lapic_base = lop->Address;
    356 	default:
    357 		break;
    358 	}
    359 	return AE_OK;
    360 }
    361 
    362 static ACPI_STATUS
    363 mpacpi_config_cpu(ACPI_SUBTABLE_HEADER *hdrp, void *aux)
    364 {
    365 	device_t parent = aux;
    366 	ACPI_MADT_LOCAL_APIC *lapic;
    367 	ACPI_MADT_LOCAL_X2APIC *x2apic;
    368 	struct cpu_attach_args caa;
    369 	int cpunum = 0;
    370 	int locs[CPUBUSCF_NLOCS];
    371 
    372 #if defined(MULTIPROCESSOR) || defined(IOAPIC)
    373 	if (mpacpi_ncpu > 1)
    374 		cpunum = lapic_cpu_number();
    375 #endif
    376 
    377 	switch (hdrp->Type) {
    378 	case ACPI_MADT_TYPE_LOCAL_APIC:
    379 		lapic = (ACPI_MADT_LOCAL_APIC *)hdrp;
    380 		if (lapic->LapicFlags & ACPI_MADT_ENABLED) {
    381 			if (lapic->Id != cpunum)
    382 				caa.cpu_role = CPU_ROLE_AP;
    383 			else
    384 				caa.cpu_role = CPU_ROLE_BP;
    385 			caa.cpu_id = lapic->ProcessorId;
    386 			caa.cpu_number = lapic->Id;
    387 			caa.cpu_func = &mp_cpu_funcs;
    388 			locs[CPUBUSCF_APID] = caa.cpu_number;
    389 			config_found(parent, &caa, mpacpi_cpuprint,
    390 			    CFARGS(.submatch = config_stdsubmatch,
    391 				   .iattr = "cpubus",
    392 				   .locators = locs));
    393 		}
    394 		break;
    395 
    396 	case ACPI_MADT_TYPE_LOCAL_X2APIC:
    397 		x2apic = (ACPI_MADT_LOCAL_X2APIC *)hdrp;
    398 
    399 		if (x2apic->LapicFlags & ACPI_MADT_ENABLED) {
    400 			if (x2apic->LocalApicId != cpunum)
    401 				caa.cpu_role = CPU_ROLE_AP;
    402 			else
    403 				caa.cpu_role = CPU_ROLE_BP;
    404 			caa.cpu_id = x2apic->Uid;
    405 			caa.cpu_number = x2apic->LocalApicId;
    406 			caa.cpu_func = &mp_cpu_funcs;
    407 			locs[CPUBUSCF_APID] = caa.cpu_number;
    408 			config_found(parent, &caa, mpacpi_cpuprint,
    409 			    CFARGS(.submatch = config_stdsubmatch,
    410 				   .iattr = "cpubus",
    411 				   .locators = locs));
    412 		}
    413 		break;
    414 
    415 	}
    416 	return AE_OK;
    417 }
    418 
    419 static ACPI_STATUS
    420 mpacpi_config_ioapic(ACPI_SUBTABLE_HEADER *hdrp, void *aux)
    421 {
    422 	device_t parent = aux;
    423 	struct apic_attach_args aaa;
    424 	ACPI_MADT_IO_APIC *p;
    425 	int locs[IOAPICBUSCF_NLOCS];
    426 
    427 	if (hdrp->Type == ACPI_MADT_TYPE_IO_APIC) {
    428 		p = (ACPI_MADT_IO_APIC *)hdrp;
    429 		aaa.apic_id = p->Id;
    430 		aaa.apic_address = p->Address;
    431 		aaa.apic_version = -1;
    432 		aaa.flags = IOAPIC_VWIRE;
    433 		aaa.apic_vecbase = p->GlobalIrqBase;
    434 		locs[IOAPICBUSCF_APID] = aaa.apic_id;
    435 		config_found(parent, &aaa, mpacpi_ioapicprint,
    436 		    CFARGS(.submatch = config_stdsubmatch,
    437 			   .iattr = "ioapicbus",
    438 			   .locators = locs));
    439 	}
    440 	return AE_OK;
    441 }
    442 
    443 int
    444 mpacpi_scan_apics(device_t self, int *ncpup)
    445 {
    446 	int rv = 0;
    447 
    448 	if (acpi_madt_map() != AE_OK)
    449 		return 0;
    450 
    451 	mpacpi_ncpu = mpacpi_nintsrc = mpacpi_nioapic = 0;
    452 	acpi_madt_walk(mpacpi_count, self);
    453 
    454 	acpi_madt_walk(mpacpi_config_ioapic, self);
    455 
    456 #if NLAPIC > 0
    457 	lapic_boot_init(mpacpi_lapic_base);
    458 #endif
    459 
    460 	acpi_madt_walk(mpacpi_config_cpu, self);
    461 
    462 	if (mpacpi_ncpu == 0)
    463 		goto done;
    464 
    465 #if NPCI > 0
    466 	/*
    467 	 * If PCI routing tables can't be built we report failure
    468 	 * and let MPBIOS do the work.
    469 	 */
    470 	if (!mpacpi_force &&
    471 	    (acpi_find_quirks() & (ACPI_QUIRK_BADPCI)) != 0)
    472 		goto done;
    473 #endif
    474 	rv = 1;
    475 done:
    476 	*ncpup = mpacpi_ncpu;
    477 	acpi_madt_unmap();
    478 	return rv;
    479 }
    480 
    481 #if NPCI > 0
    482 
    483 static void
    484 mpacpi_pci_foundbus(struct acpi_devnode *ad)
    485 {
    486 	struct mpacpi_pcibus *mpr;
    487 	ACPI_BUFFER buf;
    488 	int rv;
    489 
    490 	/*
    491 	 * set mpr_buf from _PRT (if it exists).
    492 	 * set mpr_seg and mpr_bus from previously cached info.
    493 	 */
    494 
    495 	rv = acpi_get(ad->ad_handle, &buf, AcpiGetIrqRoutingTable);
    496 	if (ACPI_FAILURE(rv)) {
    497 		buf.Length = 0;
    498 		buf.Pointer = NULL;
    499 	}
    500 
    501 	mpr = kmem_zalloc(sizeof(struct mpacpi_pcibus), KM_SLEEP);
    502 	mpr->mpr_handle = ad->ad_handle;
    503 	mpr->mpr_devhandle =
    504 	    devhandle_from_acpi(devhandle_invalid(), ad->ad_handle);
    505 	mpr->mpr_buf = buf;
    506 	mpr->mpr_seg = ad->ad_pciinfo->ap_segment;
    507 	mpr->mpr_bus = ad->ad_pciinfo->ap_downbus;
    508 	TAILQ_INSERT_TAIL(&mpacpi_pcibusses, mpr, mpr_list);
    509 
    510 	if ((ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0) {
    511 		if (mp_verbose)
    512 			printf("mpacpi: found root PCI bus %d\n",
    513 			    mpr->mpr_bus);
    514 		mpacpi_npciroots++;
    515 	} else {
    516 		if (mp_verbose)
    517 			printf("mpacpi: found subordinate bus %d\n",
    518 			    mpr->mpr_bus);
    519 	}
    520 
    521 	/*
    522 	 * XXX this wrongly assumes that bus numbers are unique
    523 	 * even between segments.
    524 	 */
    525 	if (mpr->mpr_bus > mpacpi_maxpci)
    526 		mpacpi_maxpci = mpr->mpr_bus;
    527 
    528 	mpacpi_npci++;
    529 }
    530 
    531 
    532 static void
    533 mpacpi_pci_walk(struct acpi_devnode *ad)
    534 {
    535 	struct acpi_devnode *child;
    536 
    537 	if (ad->ad_pciinfo &&
    538 	    (ad->ad_pciinfo->ap_flags & ACPI_PCI_INFO_BRIDGE) != 0) {
    539 		mpacpi_pci_foundbus(ad);
    540 	}
    541 	SIMPLEQ_FOREACH(child, &ad->ad_child_head, ad_child_list) {
    542 		mpacpi_pci_walk(child);
    543 	}
    544 }
    545 
    546 static int
    547 mpacpi_find_pcibusses(struct acpi_softc *sc)
    548 {
    549 
    550 	TAILQ_INIT(&mpacpi_pcibusses);
    551 	mpacpi_pci_walk(sc->sc_root);
    552 	return 0;
    553 }
    554 
    555 /*
    556  * Find all static PRT entries for a PCI bus.
    557  */
    558 static int
    559 mpacpi_pciroute(struct mpacpi_pcibus *mpr)
    560 {
    561 	ACPI_PCI_ROUTING_TABLE *ptrp;
    562 	ACPI_HANDLE linkdev;
    563 	char *p;
    564 	struct mp_intr_map *mpi, *iter;
    565 	struct mp_bus *mpb;
    566 	struct pic *pic;
    567 	unsigned dev;
    568 	int pin;
    569 
    570 	if (mp_verbose)
    571 		printf("mpacpi: configuring PCI bus %d int routing\n",
    572 		    mpr->mpr_bus);
    573 
    574 	mpb = &mp_busses[mpr->mpr_bus];
    575 
    576 	if (mpb->mb_name != NULL)
    577 		printf("mpacpi: PCI bus %d int routing already done!\n",
    578 		    mpr->mpr_bus);
    579 
    580 	mpb->mb_intrs = NULL;
    581 	mpb->mb_name = "pci";
    582 	mpb->mb_idx = mpr->mpr_bus;
    583 	mpb->mb_intr_print = mpacpi_print_pci_intr;
    584 	mpb->mb_intr_cfg = NULL;
    585 	mpb->mb_data = 0;
    586 
    587 	if (mpr->mpr_buf.Length == 0) {
    588 		goto out;
    589 	}
    590 
    591 	for (p = mpr->mpr_buf.Pointer; ; p += ptrp->Length) {
    592 		ptrp = (ACPI_PCI_ROUTING_TABLE *)p;
    593 		if (ptrp->Length == 0)
    594 			break;
    595 		dev = ACPI_HIWORD(ptrp->Address);
    596 
    597 		if (ptrp->Source[0] == 0 &&
    598 		    (ptrp->SourceIndex == 14 || ptrp->SourceIndex == 15)) {
    599 			printf("Skipping PCI routing entry for PCI IDE compat IRQ");
    600 			continue;
    601 		}
    602 
    603 		mpi = &mp_intrs[mpacpi_intr_index];
    604 		mpi->bus_pin = (dev << 2) | (ptrp->Pin & 3);
    605 		mpi->bus = mpb;
    606 		mpi->type = MPS_INTTYPE_INT;
    607 
    608 		/*
    609 		 * First check if an entry for this device/pin combination
    610 		 * was already found.  Some DSDTs have more than one entry
    611 		 * and it seems that the first is generally the right one.
    612 		 */
    613 		for (iter = mpb->mb_intrs; iter != NULL; iter = iter->next) {
    614 			if (iter->bus_pin == mpi->bus_pin)
    615 				break;
    616 		}
    617 		if (iter != NULL)
    618 			continue;
    619 
    620 		++mpacpi_intr_index;
    621 
    622 		if (ptrp->Source[0] != 0) {
    623 			if (mp_verbose > 1)
    624 				printf("pciroute: dev %d INT%c on lnkdev %s\n",
    625 				    dev, 'A' + (ptrp->Pin & 3), ptrp->Source);
    626 			mpi->global_int = -1;
    627 			mpi->sourceindex = ptrp->SourceIndex;
    628 			if (AcpiGetHandle(ACPI_ROOT_OBJECT, ptrp->Source,
    629 			    &linkdev) != AE_OK) {
    630 				printf("AcpiGetHandle failed for '%s'\n",
    631 				    ptrp->Source);
    632 				continue;
    633 			}
    634 			/* acpi_allocate_resources(linkdev); */
    635 			mpi->ioapic_pin = -1;
    636 			mpi->linkdev = acpi_pci_link_devbyhandle(linkdev);
    637 			acpi_pci_link_add_reference(mpi->linkdev, NULL, 0,
    638 			    mpr->mpr_bus, dev, ptrp->Pin & 3);
    639 			mpi->ioapic = NULL;
    640 			mpi->flags = MPS_INTPO_ACTLO | (MPS_INTTR_LEVEL << 2);
    641 			if (mp_verbose > 1)
    642 				printf("pciroute: done adding entry\n");
    643 		} else {
    644 			if (mp_verbose > 1)
    645 				printf("pciroute: dev %d INT%c on globint %d\n",
    646 				    dev, 'A' + (ptrp->Pin & 3),
    647 				    ptrp->SourceIndex);
    648 			mpi->sourceindex = 0;
    649 			mpi->global_int = ptrp->SourceIndex;
    650 			pic = intr_findpic(ptrp->SourceIndex);
    651 			if (pic == NULL)
    652 				continue;
    653 			/* Defaults for PCI (active low, level triggered) */
    654 			mpi->redir =
    655 			    (IOAPIC_REDLO_DEL_FIXED <<IOAPIC_REDLO_DEL_SHIFT) |
    656 			    IOAPIC_REDLO_LEVEL | IOAPIC_REDLO_ACTLO;
    657 			mpi->ioapic = pic;
    658 			pin = ptrp->SourceIndex - pic->pic_vecbase;
    659 			if (pic->pic_type == PIC_I8259 && pin > 15)
    660 				panic("bad pin %d for legacy IRQ", pin);
    661 			mpi->ioapic_pin = pin;
    662 #if NIOAPIC > 0
    663 			if (pic->pic_type == PIC_IOAPIC) {
    664 				pic->pic_ioapic->sc_pins[pin].ip_map = mpi;
    665 				mpi->ioapic_ih = APIC_INT_VIA_APIC |
    666 				    (pic->pic_apicid << APIC_INT_APIC_SHIFT) |
    667 				    (pin << APIC_INT_PIN_SHIFT);
    668 			} else
    669 #endif
    670 				mpi->ioapic_ih = pin;
    671 			mpi->linkdev = NULL;
    672 			mpi->flags = MPS_INTPO_ACTLO | (MPS_INTTR_LEVEL << 2);
    673 			if (mp_verbose > 1)
    674 				printf("pciroute: done adding entry\n");
    675 		}
    676 
    677 		mpi->cpu_id = 0;
    678 
    679 		mpi->next = mpb->mb_intrs;
    680 		mpb->mb_intrs = mpi;
    681 	}
    682 
    683 	ACPI_FREE(mpr->mpr_buf.Pointer);
    684 	mpr->mpr_buf.Pointer = NULL;	/* be preventive to bugs */
    685 
    686 out:
    687 	if (mp_verbose > 1)
    688 		printf("pciroute: done\n");
    689 
    690 	return 0;
    691 }
    692 
    693 /*
    694  * Count number of elements in _PRT
    695  */
    696 static int
    697 mpacpi_pcircount(struct mpacpi_pcibus *mpr)
    698 {
    699 	int count = 0;
    700 	ACPI_PCI_ROUTING_TABLE *PrtElement;
    701 	uint8_t *Buffer;
    702 
    703 	if (mpr->mpr_buf.Length == 0) {
    704 		return 0;
    705 	}
    706 
    707 	for (Buffer = mpr->mpr_buf.Pointer;; Buffer += PrtElement->Length) {
    708 		PrtElement = (ACPI_PCI_ROUTING_TABLE *)Buffer;
    709 		if (PrtElement->Length == 0)
    710 			break;
    711 		count++;
    712 	}
    713 
    714 	return count;
    715 }
    716 #endif
    717 
    718 /*
    719  * Set up the interrupt config lists, in the same format as the mpbios does.
    720  */
    721 static void
    722 mpacpi_config_irouting(struct acpi_softc *acpi)
    723 {
    724 #if NPCI > 0
    725 	struct mpacpi_pcibus *mpr;
    726 #endif
    727 	int nintr;
    728 	int i;
    729 	struct mp_bus *mbp;
    730 	struct mp_intr_map *mpi;
    731 	struct pic *pic;
    732 
    733 	nintr = mpacpi_nintsrc + NUM_LEGACY_IRQS - 1;
    734 #if NPCI > 0
    735 	TAILQ_FOREACH(mpr, &mpacpi_pcibusses, mpr_list) {
    736 		nintr += mpacpi_pcircount(mpr);
    737 	}
    738 
    739 	mp_isa_bus = mpacpi_maxpci + BUS_BUFFER; /* XXX */
    740 #else
    741 	mp_isa_bus = 0;
    742 #endif
    743 	mp_nbus = mp_isa_bus + 1;
    744 	mp_nintr = nintr;
    745 
    746 	mp_busses = kmem_zalloc(sizeof(struct mp_bus) * mp_nbus, KM_SLEEP);
    747 	mp_intrs = kmem_zalloc(sizeof(struct mp_intr_map) * mp_nintr, KM_SLEEP);
    748 	mbp = &mp_busses[mp_isa_bus];
    749 	mbp->mb_name = "isa";
    750 	mbp->mb_idx = 0;
    751 	mbp->mb_intr_print = mpacpi_print_isa_intr;
    752 	mbp->mb_intr_cfg = NULL;
    753 	mbp->mb_intrs = &mp_intrs[0];
    754 	mbp->mb_data = 0;
    755 
    756 	pic = intr_findpic(0);
    757 	if (pic == NULL)
    758 		panic("mpacpi: can't find first PIC");
    759 #if NIOAPIC == 0
    760 	if (pic->pic_type == PIC_IOAPIC)
    761 		panic("mpacpi: ioapic but no i8259?");
    762 #endif
    763 
    764 	/*
    765 	 * Set up default identity mapping for ISA irqs to first ioapic.
    766 	 */
    767 	for (i = mpacpi_intr_index = 0; i < NUM_LEGACY_IRQS; i++) {
    768 		if (i == 2)
    769 			continue;
    770 		mpi = &mp_intrs[mpacpi_intr_index];
    771 		if (mpacpi_intr_index < (NUM_LEGACY_IRQS - 2))
    772 			mpi->next = &mp_intrs[mpacpi_intr_index + 1];
    773 		else
    774 			mpi->next = NULL;
    775 		mpi->bus = mbp;
    776 		mpi->bus_pin = i;
    777 		mpi->ioapic_pin = i;
    778 		mpi->ioapic = pic;
    779 		mpi->type = MPS_INTTYPE_INT;
    780 		mpi->cpu_id = 0;
    781 		mpi->redir = 0;
    782 #if NIOAPIC > 0
    783 		if (pic->pic_type == PIC_IOAPIC) {
    784 			mpi->ioapic_ih = APIC_INT_VIA_APIC |
    785 			    (pic->pic_apicid << APIC_INT_APIC_SHIFT) |
    786 			    (i << APIC_INT_PIN_SHIFT);
    787 			mpi->redir =
    788 			    (IOAPIC_REDLO_DEL_FIXED << IOAPIC_REDLO_DEL_SHIFT);
    789 			pic->pic_ioapic->sc_pins[i].ip_map = mpi;
    790 		} else
    791 #endif
    792 			mpi->ioapic_ih = i;
    793 
    794 		mpi->flags = MPS_INTPO_DEF | (MPS_INTTR_DEF << 2);
    795 		mpi->global_int = i;
    796 		mpacpi_intr_index++;
    797 	}
    798 
    799 	mpacpi_user_continue("done setting up mp_bus array and ISA maps");
    800 
    801 	if (acpi_madt_map() == AE_OK) {
    802 		acpi_madt_walk(mpacpi_nonpci_intr, &mpacpi_intr_index);
    803 		acpi_madt_unmap();
    804 	}
    805 
    806 	mpacpi_user_continue("done with non-PCI interrupts");
    807 
    808 #if NPCI > 0
    809 	TAILQ_FOREACH(mpr, &mpacpi_pcibusses, mpr_list) {
    810 		mpacpi_pciroute(mpr);
    811 	}
    812 #endif
    813 
    814 	mpacpi_user_continue("done routing PCI interrupts");
    815 
    816 	mp_nintr = mpacpi_intr_index;
    817 }
    818 
    819 /*
    820  * XXX code duplication with mpbios.c
    821  */
    822 
    823 #if NPCI > 0
    824 static void
    825 mpacpi_print_pci_intr(int intr)
    826 {
    827 	printf(" device %d INT_%c", (intr >> 2) & 0x1f, 'A' + (intr & 0x3));
    828 }
    829 #endif
    830 
    831 static void
    832 mpacpi_print_isa_intr(int intr)
    833 {
    834 	printf(" irq %d", intr);
    835 }
    836 
    837 static const char inttype_fmt[] = "\177\020"
    838 		"f\0\2type\0" "=\1NMI\0" "=\2SMI\0" "=\3ExtINT\0";
    839 
    840 static const char flagtype_fmt[] = "\177\020"
    841 		"f\0\2pol\0" "=\1Act Hi\0" "=\3Act Lo\0"
    842 		"f\2\2trig\0" "=\1Edge\0" "=\3Level\0";
    843 
    844 static void
    845 mpacpi_print_intr(struct mp_intr_map *mpi)
    846 {
    847 	char buf[256];
    848 	int pin;
    849 	struct pic *sc;
    850 	const char *busname;
    851 
    852 	sc = mpi->ioapic;
    853 	pin = mpi->ioapic_pin;
    854 	if (mpi->bus != NULL)
    855 		busname = mpi->bus->mb_name;
    856 	else {
    857 		switch (mpi->type) {
    858 		case MPS_INTTYPE_NMI:
    859 			busname = "NMI";
    860 			break;
    861 		case MPS_INTTYPE_SMI:
    862 			busname = "SMI";
    863 			break;
    864 		case MPS_INTTYPE_ExtINT:
    865 			busname = "ExtINT";
    866 			break;
    867 		default:
    868 			busname = "<unknown>";
    869 			break;
    870 		}
    871 	}
    872 
    873 	if (mpi->linkdev != NULL)
    874 		printf("linkdev %s attached to %s",
    875 		    acpi_pci_link_name(mpi->linkdev), busname);
    876 	else
    877 		printf("%s: pin %d attached to %s",
    878 		    sc ? sc->pic_name : "local apic",
    879 		    pin, busname);
    880 
    881 	if (mpi->bus != NULL) {
    882 		if (mpi->bus->mb_idx != -1)
    883 			printf("%d", mpi->bus->mb_idx);
    884 		(*(mpi->bus->mb_intr_print))(mpi->bus_pin);
    885 	}
    886 	snprintb(buf, sizeof(buf), inttype_fmt, mpi->type);
    887 	printf(" (type %s", buf);
    888 
    889 	snprintb(buf, sizeof(buf), flagtype_fmt, mpi->flags);
    890 	printf(" flags %s)\n", buf);
    891 
    892 }
    893 
    894 
    895 int
    896 mpacpi_find_interrupts(void *self)
    897 {
    898 #if NIOAPIC > 0
    899 	ACPI_STATUS rv;
    900 #endif
    901 	struct acpi_softc *acpi = self;
    902 	int i;
    903 
    904 #ifdef MPBIOS
    905 	/*
    906 	 * If MPBIOS was enabled, and did the work (because the initial
    907 	 * MADT scan failed for some reason), there's nothing left to
    908 	 * do here. Same goes for the case where no I/O APICS were found.
    909 	 */
    910 	if (mpbios_scanned)
    911 		return 0;
    912 #endif
    913 
    914 #if NIOAPIC > 0
    915 	if (mpacpi_nioapic != 0) {
    916 		/*
    917 		 * Switch us into APIC mode by evaluating _PIC(1).
    918 		 * Needs to be done now, since it has an effect on
    919 		 * the interrupt information we're about to retrieve.
    920 		 *
    921 		 * ACPI 3.0 (section 5.8.1):
    922 		 *   0 = PIC mode, 1 = APIC mode, 2 = SAPIC mode.
    923 		 */
    924 		rv = acpi_eval_set_integer(NULL, "\\_PIC", 1);
    925 		if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) {
    926 			if (mp_verbose)
    927 				printf("mpacpi: switch to APIC mode failed\n");
    928 			return 0;
    929 		}
    930 	}
    931 #endif
    932 
    933 #if NPCI > 0
    934 	mpacpi_user_continue("finding PCI busses ");
    935 	mpacpi_find_pcibusses(acpi);
    936 	if (mp_verbose)
    937 		printf("mpacpi: %d PCI busses\n", mpacpi_npci);
    938 #endif
    939 	mpacpi_config_irouting(acpi);
    940 	if (mp_verbose)
    941 		for (i = 0; i < mp_nintr; i++)
    942 			mpacpi_print_intr(&mp_intrs[i]);
    943 	return 0;
    944 }
    945 
    946 #if NPCI > 0
    947 
    948 static void
    949 mpacpi_set_devhandle(device_t self, struct pcibus_attach_args *pba)
    950 {
    951 	devhandle_t devhandle = device_handle(self);
    952 	struct mpacpi_pcibus *mpr;
    953 
    954 	/* If we already have a valid handle, eject now. */
    955 	if (devhandle_type(devhandle) != DEVHANDLE_TYPE_INVALID) {
    956 		return;
    957 	}
    958 
    959 	TAILQ_FOREACH(mpr, &mpacpi_pcibusses, mpr_list) {
    960 		/* XXX Assuming always segment 0 on x86. */
    961 		if (mpr->mpr_seg != 0) {
    962 			continue;
    963 		}
    964 		if (mpr->mpr_bus == pba->pba_bus) {
    965 			device_set_handle(self, mpr->mpr_devhandle);
    966 			return;
    967 		}
    968 	}
    969 }
    970 
    971 int
    972 mpacpi_pci_attach_hook(device_t parent, device_t self,
    973 		       struct pcibus_attach_args *pba)
    974 {
    975 	struct mp_bus *mpb;
    976 
    977 #ifdef MPBIOS
    978 	if (mpbios_scanned != 0)
    979 		return ENOENT;
    980 #endif
    981 
    982 	if (TAILQ_EMPTY(&mpacpi_pcibusses))
    983 		return 0;
    984 
    985 	/*
    986 	 * If this bus is not found in mpacpi_find_pcibusses
    987 	 * (i.e. behind PCI-to-PCI bridge), register as an extra bus.
    988 	 *
    989 	 * at this point, mp_busses[] are as follows:
    990 	 *  mp_busses[0 .. mpacpi_maxpci] : PCI
    991 	 *  mp_busses[mpacpi_maxpci + BUS_BUFFER] : ISA
    992 	 */
    993 	if (pba->pba_bus >= mp_isa_bus) {
    994 		intr_add_pcibus(pba);
    995 		return 0;
    996 	}
    997 
    998 	mpb = &mp_busses[pba->pba_bus];
    999 	if (mpb->mb_name != NULL) {
   1000 		if (strcmp(mpb->mb_name, "pci"))
   1001 			return EINVAL;
   1002 	} else {
   1003 		/*
   1004 		 * As we cannot find all PCI-to-PCI bridge in
   1005 		 * mpacpi_find_pcibusses, some of the MP_busses may remain
   1006 		 * uninitialized.
   1007 		 */
   1008 		mpb->mb_name = "pci";
   1009 	}
   1010 
   1011 	mpacpi_set_devhandle(self, pba);
   1012 
   1013 	mpb->mb_dev = self;
   1014 	mpb->mb_pci_bridge_tag = pba->pba_bridgetag;
   1015 	mpb->mb_pci_chipset_tag = pba->pba_pc;
   1016 
   1017 	if (mp_verbose)
   1018 		printf("\n%s: added to list as bus %d", device_xname(parent),
   1019 		    pba->pba_bus);
   1020 
   1021 
   1022 	if (pba->pba_bus > mpacpi_maxpci)
   1023 		mpacpi_maxpci = pba->pba_bus;
   1024 
   1025 	return 0;
   1026 }
   1027 #endif
   1028 
   1029 void
   1030 mpacpi_configure_busses(void)
   1031 {
   1032 #ifdef PCI_RESOURCE
   1033 	struct mpacpi_pcibus *mpr;
   1034 	struct mp_bus *mpb;
   1035 	int error;
   1036 
   1037 	TAILQ_FOREACH(mpr, &mpacpi_pcibusses, mpr_list) {
   1038 		if (mp_verbose) {
   1039 			printf("MPACPI PCI bus handle %s seg %d bus %d\n",
   1040 			    acpi_name(mpr->mpr_handle),
   1041 			    mpr->mpr_seg,
   1042 			    mpr->mpr_bus);
   1043 		}
   1044 
   1045 		if (mpr->mpr_bus < 0) {
   1046 			printf("MPACPI PCI bus number %d is negative\n",
   1047 			    mpr->mpr_bus);
   1048 			return;
   1049 		}
   1050 		if (mpr->mpr_bus < 0 || mpr->mpr_bus >= mpacpi_maxpci) {
   1051 			printf("MPACPI PCI bus number %d exceeds mpacpi_maxpci"
   1052 			    " %d\n",
   1053 			    mpr->mpr_bus, mpacpi_maxpci);
   1054 			return;
   1055 		}
   1056 
   1057 		mpb = &mp_busses[mpr->mpr_bus];
   1058 		error = acpimcfg_configure_bus(mpb->mb_dev,
   1059 		    mpb->mb_pci_chipset_tag, mpr->mpr_handle, mpr->mpr_bus,
   1060 		    /*mapcfgspace*/true);
   1061 		if (error) {
   1062 			printf("MPACPI PCI bus number %d configuration failed:"
   1063 			    " %d\n",
   1064 			    mpr->mpr_bus, error);
   1065 			return;
   1066 		}
   1067 	}
   1068 #endif
   1069 }
   1070 
   1071 int
   1072 mpacpi_findintr_linkdev(struct mp_intr_map *mip)
   1073 {
   1074 	int irq, line, pol, trig;
   1075 	struct pic *pic;
   1076 	int pin;
   1077 
   1078 	if (mip->linkdev == NULL)
   1079 		return ENOENT;
   1080 
   1081 	irq = acpi_pci_link_route_interrupt(mip->linkdev, NULL,
   1082 	    mip->sourceindex, &line, &pol, &trig);
   1083 	if (mp_verbose)
   1084 		printf("linkdev %s returned ACPI global irq %d, line %d\n",
   1085 		    acpi_pci_link_name(mip->linkdev), irq, line);
   1086 	if (irq == X86_PCI_INTERRUPT_LINE_NO_CONNECTION)
   1087 		return ENOENT;
   1088 	if (irq != line) {
   1089 		aprint_error("%s: mpacpi_findintr_linkdev:"
   1090 		    " irq mismatch (%d vs %d)\n",
   1091 		    acpi_pci_link_name(mip->linkdev), irq, line);
   1092 		return ENOENT;
   1093 	}
   1094 
   1095 	/*
   1096 	 * Convert ACPICA values to MPS values
   1097 	 */
   1098 	if (pol == ACPI_ACTIVE_LOW)
   1099 		pol = MPS_INTPO_ACTLO;
   1100 	else
   1101 		pol = MPS_INTPO_ACTHI;
   1102 
   1103 	if (trig == ACPI_EDGE_SENSITIVE)
   1104 		trig = MPS_INTTR_EDGE;
   1105 	else
   1106 		trig = MPS_INTTR_LEVEL;
   1107 
   1108 	mip->flags = pol | (trig << 2);
   1109 	mip->global_int = irq;
   1110 	pic = intr_findpic(irq);
   1111 	if (pic == NULL)
   1112 		return ENOENT;
   1113 	mip->ioapic = pic;
   1114 	pin = irq - pic->pic_vecbase;
   1115 
   1116 	if (pic->pic_type == PIC_IOAPIC) {
   1117 #if NIOAPIC > 0
   1118 		mip->redir = (IOAPIC_REDLO_DEL_FIXED <<IOAPIC_REDLO_DEL_SHIFT);
   1119 		if (pol ==  MPS_INTPO_ACTLO)
   1120 			mip->redir |= IOAPIC_REDLO_ACTLO;
   1121 		if (trig ==  MPS_INTTR_LEVEL)
   1122 			mip->redir |= IOAPIC_REDLO_LEVEL;
   1123 		mip->ioapic_ih = APIC_INT_VIA_APIC |
   1124 		    (pic->pic_apicid << APIC_INT_APIC_SHIFT) |
   1125 		    (pin << APIC_INT_PIN_SHIFT);
   1126 		pic->pic_ioapic->sc_pins[pin].ip_map = mip;
   1127 		mip->ioapic_pin = pin;
   1128 #else
   1129 		return ENOENT;
   1130 #endif
   1131 	} else
   1132 		mip->ioapic_ih = pin;
   1133 	return 0;
   1134 }
   1135 
   1136 static void
   1137 mpacpi_user_continue(const char *fmt, ...)
   1138 {
   1139 	va_list ap;
   1140 
   1141 	if (!mpacpi_step)
   1142 		return;
   1143 
   1144 	printf("mpacpi: ");
   1145 	va_start(ap, fmt);
   1146 	vprintf(fmt, ap);
   1147 	va_end(ap);
   1148 	printf("<press any key to continue>\n>");
   1149 	cngetc();
   1150 }
   1151 
   1152 #ifdef DDB
   1153 void
   1154 mpacpi_dump(void)
   1155 {
   1156 	int i;
   1157 	for (i = 0; i < mp_nintr; i++)
   1158 		mpacpi_print_intr(&mp_intrs[i]);
   1159 }
   1160 #endif
   1161