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