1/*	$NetBSD: mpacpi.c,v 1.92.8.1 2012/11/22 00:39:00 riz 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.92.8.1 2012/11/22 00:39:00 riz Exp $");
40
41#include "acpica.h"
42#include "opt_acpi.h"
43#include "opt_mpbios.h"
44#include "opt_multiprocessor.h"
45#include "pchb.h"
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/kernel.h>
50#include <sys/device.h>
51#include <sys/kmem.h>
52#include <sys/queue.h>
53
54#include <uvm/uvm_extern.h>
55
56#include <machine/specialreg.h>
57#include <machine/cpuvar.h>
58#include <sys/bus.h>
59#include <machine/mpacpi.h>
60#include <machine/mpbiosvar.h>
61
62#include <machine/i82093reg.h>
63#include <machine/i82093var.h>
64#include <machine/i82489reg.h>
65#include <machine/i82489var.h>
66#include <dev/isa/isareg.h>
67#include <dev/pci/pcivar.h>
68#include <dev/pci/pcidevs.h>
69#include <dev/pci/ppbreg.h>
70
71#include <dev/acpi/acpica.h>
72#include <dev/acpi/acpireg.h>
73#include <dev/acpi/acpivar.h>
74
75#include <dev/cons.h>
76
77#define _COMPONENT     ACPI_RESOURCE_COMPONENT
78ACPI_MODULE_NAME       ("mpacpi")
79
80#include "pci.h"
81#include "ioapic.h"
82#include "lapic.h"
83
84#include "locators.h"
85
86/* XXX room for PCI-to-PCI bus */
87#define BUS_BUFFER (16)
88
89#if NPCI > 0
90struct mpacpi_pcibus {
91	TAILQ_ENTRY(mpacpi_pcibus) mpr_list;
92	ACPI_HANDLE mpr_handle;		/* Same thing really, but.. */
93	ACPI_BUFFER mpr_buf;		/* preserve _PRT */
94	int mpr_seg;			/* PCI segment number */
95	int mpr_bus;			/* PCI bus number */
96};
97
98static TAILQ_HEAD(, mpacpi_pcibus) mpacpi_pcibusses;
99
100#endif
101
102static int mpacpi_cpuprint(void *, const char *);
103static int mpacpi_ioapicprint(void *, const char *);
104
105/* acpi_madt_walk callbacks */
106static ACPI_STATUS mpacpi_count(ACPI_SUBTABLE_HEADER *, void *);
107static ACPI_STATUS mpacpi_config_cpu(ACPI_SUBTABLE_HEADER *, void *);
108static ACPI_STATUS mpacpi_config_ioapic(ACPI_SUBTABLE_HEADER *, void *);
109static ACPI_STATUS mpacpi_nonpci_intr(ACPI_SUBTABLE_HEADER *, void *);
110
111#if NPCI > 0
112static int mpacpi_pcircount(struct mpacpi_pcibus *);
113static int mpacpi_pciroute(struct mpacpi_pcibus *);
114static int mpacpi_find_pcibusses(struct acpi_softc *);
115
116static void mpacpi_print_pci_intr(int);
117#endif
118
119static void mpacpi_config_irouting(struct acpi_softc *);
120
121static void mpacpi_print_intr(struct mp_intr_map *);
122static void mpacpi_print_isa_intr(int);
123
124static void mpacpi_user_continue(const char *fmt, ...);
125
126int mpacpi_nioapic;			/* number of ioapics */
127int mpacpi_ncpu;			/* number of cpus */
128int mpacpi_nintsrc;			/* number of non-device interrupts */
129
130#if NPCI > 0
131static int mpacpi_npci;
132static int mpacpi_maxpci;
133static int mpacpi_npciroots;
134#endif
135
136static int mpacpi_intr_index;
137static paddr_t mpacpi_lapic_base = LAPIC_BASE;
138
139int mpacpi_step;
140int mpacpi_force;
141
142static int
143mpacpi_cpuprint(void *aux, const char *pnp)
144{
145	struct cpu_attach_args *caa = aux;
146
147	if (pnp)
148		aprint_normal("cpu at %s", pnp);
149	aprint_normal(" apid %d", caa->cpu_number);
150	return (UNCONF);
151}
152
153static int
154mpacpi_ioapicprint(void *aux, const char *pnp)
155{
156	struct apic_attach_args *aaa = aux;
157
158	if (pnp)
159		aprint_normal("ioapic at %s", pnp);
160	aprint_normal(" apid %d", aaa->apic_id);
161	return (UNCONF);
162}
163
164/*
165 * Handle special interrupt sources and overrides from the MADT.
166 * This is a callback function for acpi_madt_walk() (see acpi.c).
167 */
168static ACPI_STATUS
169mpacpi_nonpci_intr(ACPI_SUBTABLE_HEADER *hdrp, void *aux)
170{
171	int *index = aux, pin, lindex;
172	struct mp_intr_map *mpi;
173	ACPI_MADT_NMI_SOURCE *ioapic_nmi;
174	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
175	ACPI_MADT_INTERRUPT_OVERRIDE *isa_ovr;
176	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
177	struct pic *pic;
178	extern struct acpi_softc *acpi_softc;	/* XXX */
179
180	switch (hdrp->Type) {
181	case ACPI_MADT_TYPE_NMI_SOURCE:
182		ioapic_nmi = (ACPI_MADT_NMI_SOURCE *)hdrp;
183		pic = intr_findpic(ioapic_nmi->GlobalIrq);
184		if (pic == NULL)
185			break;
186#if NIOAPIC == 0
187		if (pic->pic_type == PIC_IOAPIC)
188			break;
189#endif
190		mpi = &mp_intrs[*index];
191		(*index)++;
192		mpi->next = NULL;
193		mpi->bus = NULL;
194		mpi->type = MPS_INTTYPE_NMI;
195		mpi->ioapic = pic;
196		pin = ioapic_nmi->GlobalIrq - pic->pic_vecbase;
197		mpi->ioapic_pin = pin;
198		mpi->bus_pin = -1;
199		mpi->redir = (IOAPIC_REDLO_DEL_NMI<<IOAPIC_REDLO_DEL_SHIFT);
200#if NIOAPIC > 0
201		if (pic->pic_type == PIC_IOAPIC) {
202			pic->pic_ioapic->sc_pins[pin].ip_map = mpi;
203			mpi->ioapic_ih = APIC_INT_VIA_APIC |
204			    (pic->pic_apicid << APIC_INT_APIC_SHIFT) |
205			    (pin << APIC_INT_PIN_SHIFT);
206		} else
207#endif
208			mpi->ioapic_ih = pin;
209		mpi->flags = ioapic_nmi->IntiFlags;
210		mpi->global_int = ioapic_nmi->GlobalIrq;
211		break;
212	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
213		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)hdrp;
214		mpi = &mp_intrs[*index];
215		(*index)++;
216		mpi->next = NULL;
217		mpi->bus = NULL;
218		mpi->ioapic = NULL;
219		mpi->type = MPS_INTTYPE_NMI;
220		mpi->ioapic_pin = lapic_nmi->Lint;
221		mpi->cpu_id = lapic_nmi->ProcessorId;
222		mpi->redir = (IOAPIC_REDLO_DEL_NMI<<IOAPIC_REDLO_DEL_SHIFT);
223		mpi->global_int = -1;
224		break;
225	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
226		isa_ovr = (ACPI_MADT_INTERRUPT_OVERRIDE *)hdrp;
227		if (mp_verbose) {
228			printf("mpacpi: ISA interrupt override %d -> %d (%d/%d)\n",
229			    isa_ovr->SourceIrq, isa_ovr->GlobalIrq,
230			    isa_ovr->IntiFlags & ACPI_MADT_POLARITY_MASK,
231			    (isa_ovr->IntiFlags & ACPI_MADT_TRIGGER_MASK) >> 2);
232		}
233		if (isa_ovr->SourceIrq > 15 || isa_ovr->SourceIrq == 2 ||
234		    (isa_ovr->SourceIrq == 0 && isa_ovr->GlobalIrq == 2 &&
235			(acpi_softc->sc_quirks & ACPI_QUIRK_IRQ0)))
236			break;
237		pic = intr_findpic(isa_ovr->GlobalIrq);
238		if (pic == NULL)
239			break;
240#if NIOAPIC == 0
241		if (pic->pic_type == PIC_IOAPIC)
242			break;
243#endif
244		pin = isa_ovr->GlobalIrq - pic->pic_vecbase;
245		lindex = isa_ovr->SourceIrq;
246		/*
247		 * IRQ 2 was skipped in the default setup.
248		 */
249		if (lindex > 2)
250			lindex--;
251		mpi = &mp_intrs[lindex];
252#if NIOAPIC > 0
253		if (pic->pic_type == PIC_IOAPIC) {
254			mpi->ioapic_ih = APIC_INT_VIA_APIC |
255			    (pic->pic_apicid << APIC_INT_APIC_SHIFT) |
256			    (pin << APIC_INT_PIN_SHIFT);
257		} else
258#endif
259			mpi->ioapic_ih = pin;
260		mpi->bus_pin = isa_ovr->SourceIrq;
261		mpi->ioapic = (struct pic *)pic;
262		mpi->ioapic_pin = pin;
263		mpi->sflags |= MPI_OVR;
264		mpi->redir = 0;
265		mpi->global_int = isa_ovr->GlobalIrq;
266		switch (isa_ovr->IntiFlags & ACPI_MADT_POLARITY_MASK) {
267		case ACPI_MADT_POLARITY_ACTIVE_HIGH:
268			mpi->redir &= ~IOAPIC_REDLO_ACTLO;
269			break;
270		case ACPI_MADT_POLARITY_ACTIVE_LOW:
271			mpi->redir |= IOAPIC_REDLO_ACTLO;
272			break;
273		case ACPI_MADT_POLARITY_CONFORMS:
274			if (isa_ovr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
275				mpi->redir |= IOAPIC_REDLO_ACTLO;
276			else
277				mpi->redir &= ~IOAPIC_REDLO_ACTLO;
278			break;
279		}
280		mpi->redir |= (IOAPIC_REDLO_DEL_FIXED<<IOAPIC_REDLO_DEL_SHIFT);
281		switch (isa_ovr->IntiFlags & ACPI_MADT_TRIGGER_MASK) {
282		case ACPI_MADT_TRIGGER_LEVEL:
283			mpi->redir |= IOAPIC_REDLO_LEVEL;
284			break;
285		case ACPI_MADT_TRIGGER_EDGE:
286			mpi->redir &= ~IOAPIC_REDLO_LEVEL;
287			break;
288		case ACPI_MADT_TRIGGER_CONFORMS:
289			if (isa_ovr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
290				mpi->redir |= IOAPIC_REDLO_LEVEL;
291			else
292				mpi->redir &= ~IOAPIC_REDLO_LEVEL;
293			break;
294		}
295		mpi->flags = isa_ovr->IntiFlags;
296#if NIOAPIC > 0
297		if (pic->pic_type == PIC_IOAPIC)
298			pic->pic_ioapic->sc_pins[pin].ip_map = mpi;
299#endif
300		break;
301
302	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
303		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)hdrp;
304
305		mpi = &mp_intrs[*index];
306		(*index)++;
307		mpi->next = NULL;
308		mpi->bus = NULL;
309		mpi->ioapic = NULL;
310		mpi->type = MPS_INTTYPE_NMI;
311		mpi->ioapic_pin = x2apic_nmi->Lint;
312		mpi->cpu_id = x2apic_nmi->Uid;
313		mpi->redir = (IOAPIC_REDLO_DEL_NMI<<IOAPIC_REDLO_DEL_SHIFT);
314		mpi->global_int = -1;
315		break;
316
317	default:
318		break;
319	}
320	return AE_OK;
321}
322
323/*
324 * Count various MP resources present in the MADT.
325 * This is a callback function for acpi_madt_walk().
326 */
327static ACPI_STATUS
328mpacpi_count(ACPI_SUBTABLE_HEADER *hdrp, void *aux)
329{
330	ACPI_MADT_LOCAL_APIC_OVERRIDE *lop;
331
332	switch (hdrp->Type) {
333	case ACPI_MADT_TYPE_LOCAL_APIC:
334	case ACPI_MADT_TYPE_LOCAL_X2APIC:
335		mpacpi_ncpu++;
336		break;
337	case ACPI_MADT_TYPE_IO_APIC:
338		mpacpi_nioapic++;
339		break;
340	case ACPI_MADT_TYPE_NMI_SOURCE:
341	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
342	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
343		mpacpi_nintsrc++;
344		break;
345	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
346		lop = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)hdrp;
347		mpacpi_lapic_base = lop->Address;
348	default:
349		break;
350	}
351	return AE_OK;
352}
353
354static ACPI_STATUS
355mpacpi_config_cpu(ACPI_SUBTABLE_HEADER *hdrp, void *aux)
356{
357	device_t parent = aux;
358	ACPI_MADT_LOCAL_APIC *lapic;
359	ACPI_MADT_LOCAL_X2APIC *x2apic;
360	struct cpu_attach_args caa;
361	int cpunum = 0;
362	int locs[CPUBUSCF_NLOCS];
363
364#if defined(MULTIPROCESSOR) || defined(IOAPIC)
365	if (mpacpi_ncpu > 1)
366		cpunum = lapic_cpu_number();
367#endif
368
369	switch (hdrp->Type) {
370	case ACPI_MADT_TYPE_LOCAL_APIC:
371		lapic = (ACPI_MADT_LOCAL_APIC *)hdrp;
372		if (lapic->LapicFlags & ACPI_MADT_ENABLED) {
373			if (lapic->Id != cpunum)
374				caa.cpu_role = CPU_ROLE_AP;
375			else
376				caa.cpu_role = CPU_ROLE_BP;
377			caa.cpu_id = lapic->ProcessorId;
378			caa.cpu_number = lapic->Id;
379			caa.cpu_func = &mp_cpu_funcs;
380			locs[CPUBUSCF_APID] = caa.cpu_number;
381			config_found_sm_loc(parent, "cpubus", locs,
382				&caa, mpacpi_cpuprint, config_stdsubmatch);
383		}
384		break;
385
386	case ACPI_MADT_TYPE_LOCAL_X2APIC:
387		x2apic = (ACPI_MADT_LOCAL_X2APIC *)hdrp;
388
389		/* ACPI spec: "Logical processors with APIC ID values
390		 * less than 255 must use the Processor Local APIC
391		 * structure to convey their APIC information to OSPM."
392		 */
393		if (x2apic->LocalApicId <= 0xff) {
394			printf("bogus MADT X2APIC entry (id = 0x%"PRIx32")\n",
395			    x2apic->LocalApicId);
396			break;
397		}
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_sm_loc(parent, "cpubus", locs,
409				&caa, mpacpi_cpuprint, config_stdsubmatch);
410		}
411		break;
412
413	}
414	return AE_OK;
415}
416
417static ACPI_STATUS
418mpacpi_config_ioapic(ACPI_SUBTABLE_HEADER *hdrp, void *aux)
419{
420	device_t parent = aux;
421	struct apic_attach_args aaa;
422	ACPI_MADT_IO_APIC *p;
423	int locs[IOAPICBUSCF_NLOCS];
424
425	if (hdrp->Type == ACPI_MADT_TYPE_IO_APIC) {
426		p = (ACPI_MADT_IO_APIC *)hdrp;
427		aaa.apic_id = p->Id;
428		aaa.apic_address = p->Address;
429		aaa.apic_version = -1;
430		aaa.flags = IOAPIC_VWIRE;
431		aaa.apic_vecbase = p->GlobalIrqBase;
432		locs[IOAPICBUSCF_APID] = aaa.apic_id;
433		config_found_sm_loc(parent, "ioapicbus", locs, &aaa,
434			mpacpi_ioapicprint, config_stdsubmatch);
435	}
436	return AE_OK;
437}
438
439int
440mpacpi_scan_apics(device_t self, int *ncpup)
441{
442	int rv = 0;
443
444	if (acpi_madt_map() != AE_OK)
445		return 0;
446
447	mpacpi_ncpu = mpacpi_nintsrc = mpacpi_nioapic = 0;
448	acpi_madt_walk(mpacpi_count, self);
449
450#if NLAPIC > 0
451	lapic_boot_init(mpacpi_lapic_base);
452#endif
453
454	acpi_madt_walk(mpacpi_config_cpu, self);
455
456	if (mpacpi_ncpu == 0)
457		goto done;
458
459	acpi_madt_walk(mpacpi_config_ioapic, self);
460
461#if NPCI > 0
462	/*
463	 * If PCI routing tables can't be built we report failure
464	 * and let MPBIOS do the work.
465	 */
466	if (!mpacpi_force &&
467	    (acpi_find_quirks() & (ACPI_QUIRK_BADPCI)) != 0)
468		goto done;
469#endif
470	rv = 1;
471done:
472	*ncpup = mpacpi_ncpu;
473	acpi_madt_unmap();
474	return rv;
475}
476
477#if NPCI > 0
478
479static void
480mpacpi_pci_foundbus(struct acpi_devnode *ad)
481{
482	struct mpacpi_pcibus *mpr;
483	ACPI_BUFFER buf;
484	int rv;
485
486	/*
487	 * set mpr_buf from _PRT (if it exists).
488	 * set mpr_seg and mpr_bus from previously cached info.
489	 */
490
491	rv = acpi_get(ad->ad_handle, &buf, AcpiGetIrqRoutingTable);
492	if (ACPI_FAILURE(rv)) {
493		buf.Length = 0;
494		buf.Pointer = NULL;
495	}
496
497	mpr = kmem_zalloc(sizeof(struct mpacpi_pcibus), KM_SLEEP);
498	if ((ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0) {
499		if (mp_verbose)
500			printf("mpacpi: found root PCI bus %d\n",
501			    mpr->mpr_bus);
502		mpacpi_npciroots++;
503	} else {
504		if (mp_verbose)
505			printf("mpacpi: found subordinate bus %d\n",
506			    mpr->mpr_bus);
507	}
508
509	mpr->mpr_handle = ad->ad_handle;
510	mpr->mpr_buf = buf;
511	mpr->mpr_seg = ad->ad_pciinfo->ap_segment;
512	mpr->mpr_bus = ad->ad_pciinfo->ap_downbus;
513	TAILQ_INSERT_TAIL(&mpacpi_pcibusses, mpr, mpr_list);
514
515	/*
516	 * XXX this wrongly assumes that bus numbers are unique
517	 * even between segments.
518	 */
519	if (mpr->mpr_bus > mpacpi_maxpci)
520		mpacpi_maxpci = mpr->mpr_bus;
521
522	mpacpi_npci++;
523}
524
525
526static void
527mpacpi_pci_walk(struct acpi_devnode *ad)
528{
529	struct acpi_devnode *child;
530
531	if (ad->ad_pciinfo &&
532	    (ad->ad_pciinfo->ap_flags & ACPI_PCI_INFO_BRIDGE) != 0) {
533		mpacpi_pci_foundbus(ad);
534	}
535	SIMPLEQ_FOREACH(child, &ad->ad_child_head, ad_child_list) {
536		mpacpi_pci_walk(child);
537	}
538}
539
540static int
541mpacpi_find_pcibusses(struct acpi_softc *sc)
542{
543
544	TAILQ_INIT(&mpacpi_pcibusses);
545	mpacpi_pci_walk(sc->sc_root);
546	return 0;
547}
548
549/*
550 * Find all static PRT entries for a PCI bus.
551 */
552static int
553mpacpi_pciroute(struct mpacpi_pcibus *mpr)
554{
555	ACPI_PCI_ROUTING_TABLE *ptrp;
556        ACPI_HANDLE linkdev;
557	char *p;
558	struct mp_intr_map *mpi, *iter;
559	struct mp_bus *mpb;
560	struct pic *pic;
561	unsigned dev;
562	int pin;
563
564	if (mp_verbose)
565		printf("mpacpi: configuring PCI bus %d int routing\n",
566		    mpr->mpr_bus);
567
568	mpb = &mp_busses[mpr->mpr_bus];
569
570	if (mpb->mb_name != NULL)
571		printf("mpacpi: PCI bus %d int routing already done!\n",
572		    mpr->mpr_bus);
573
574	mpb->mb_intrs = NULL;
575	mpb->mb_name = "pci";
576	mpb->mb_idx = mpr->mpr_bus;
577	mpb->mb_intr_print = mpacpi_print_pci_intr;
578	mpb->mb_intr_cfg = NULL;
579	mpb->mb_data = 0;
580
581	if (mpr->mpr_buf.Length == 0) {
582		goto out;
583	}
584
585	for (p = mpr->mpr_buf.Pointer; ; p += ptrp->Length) {
586		ptrp = (ACPI_PCI_ROUTING_TABLE *)p;
587		if (ptrp->Length == 0)
588			break;
589		dev = ACPI_HIWORD(ptrp->Address);
590
591		if (ptrp->Source[0] == 0 &&
592		    (ptrp->SourceIndex == 14 || ptrp->SourceIndex == 15)) {
593			printf("Skipping PCI routing entry for PCI IDE compat IRQ");
594			continue;
595		}
596
597		mpi = &mp_intrs[mpacpi_intr_index];
598		mpi->bus_pin = (dev << 2) | (ptrp->Pin & 3);
599		mpi->bus = mpb;
600		mpi->type = MPS_INTTYPE_INT;
601
602		/*
603		 * First check if an entry for this device/pin combination
604		 * was already found.  Some DSDTs have more than one entry
605		 * and it seems that the first is generally the right one.
606		 */
607		for (iter = mpb->mb_intrs; iter != NULL; iter = iter->next) {
608			if (iter->bus_pin == mpi->bus_pin)
609				break;
610		}
611		if (iter != NULL)
612			continue;
613
614		++mpacpi_intr_index;
615
616		if (ptrp->Source[0] != 0) {
617			if (mp_verbose > 1)
618				printf("pciroute: dev %d INT%c on lnkdev %s\n",
619				    dev, 'A' + (ptrp->Pin & 3), ptrp->Source);
620			mpi->global_int = -1;
621			mpi->sourceindex = ptrp->SourceIndex;
622			if (AcpiGetHandle(ACPI_ROOT_OBJECT, ptrp->Source,
623			    &linkdev) != AE_OK) {
624				printf("AcpiGetHandle failed for '%s'\n",
625				    ptrp->Source);
626				continue;
627			}
628			/* acpi_allocate_resources(linkdev); */
629			mpi->ioapic_pin = -1;
630			mpi->linkdev = acpi_pci_link_devbyhandle(linkdev);
631			acpi_pci_link_add_reference(mpi->linkdev, 0,
632			    mpr->mpr_bus, dev, ptrp->Pin & 3);
633			mpi->ioapic = NULL;
634			mpi->flags = MPS_INTPO_ACTLO | (MPS_INTTR_LEVEL << 2);
635			if (mp_verbose > 1)
636				printf("pciroute: done adding entry\n");
637		} else {
638			if (mp_verbose > 1)
639				printf("pciroute: dev %d INT%c on globint %d\n",
640				    dev, 'A' + (ptrp->Pin & 3),
641				    ptrp->SourceIndex);
642			mpi->sourceindex = 0;
643			mpi->global_int = ptrp->SourceIndex;
644			pic = intr_findpic(ptrp->SourceIndex);
645			if (pic == NULL)
646				continue;
647			/* Defaults for PCI (active low, level triggered) */
648			mpi->redir =
649			    (IOAPIC_REDLO_DEL_FIXED<<IOAPIC_REDLO_DEL_SHIFT) |
650			    IOAPIC_REDLO_LEVEL | IOAPIC_REDLO_ACTLO;
651			mpi->ioapic = pic;
652			pin = ptrp->SourceIndex - pic->pic_vecbase;
653			if (pic->pic_type == PIC_I8259 && pin > 15)
654				panic("bad pin %d for legacy IRQ", pin);
655			mpi->ioapic_pin = pin;
656#if NIOAPIC > 0
657			if (pic->pic_type == PIC_IOAPIC) {
658				pic->pic_ioapic->sc_pins[pin].ip_map = mpi;
659				mpi->ioapic_ih = APIC_INT_VIA_APIC |
660				    (pic->pic_apicid << APIC_INT_APIC_SHIFT) |
661				    (pin << APIC_INT_PIN_SHIFT);
662			} else
663#endif
664				mpi->ioapic_ih = pin;
665			mpi->linkdev = NULL;
666			mpi->flags = MPS_INTPO_ACTLO | (MPS_INTTR_LEVEL << 2);
667			if (mp_verbose > 1)
668				printf("pciroute: done adding entry\n");
669		}
670
671		mpi->cpu_id = 0;
672
673		mpi->next = mpb->mb_intrs;
674		mpb->mb_intrs = mpi;
675	}
676
677	ACPI_FREE(mpr->mpr_buf.Pointer);
678	mpr->mpr_buf.Pointer = NULL;	/* be preventive to bugs */
679
680out:
681	if (mp_verbose > 1)
682		printf("pciroute: done\n");
683
684	return 0;
685}
686
687/*
688 * Count number of elements in _PRT
689 */
690static int
691mpacpi_pcircount(struct mpacpi_pcibus *mpr)
692{
693	int count = 0;
694	ACPI_PCI_ROUTING_TABLE *PrtElement;
695	uint8_t *Buffer;
696
697	if (mpr->mpr_buf.Length == 0) {
698		return 0;
699	}
700
701	for (Buffer = mpr->mpr_buf.Pointer;; Buffer += PrtElement->Length) {
702		PrtElement = (ACPI_PCI_ROUTING_TABLE *)Buffer;
703		if (PrtElement->Length == 0)
704			break;
705		count++;
706	}
707
708	return count;
709}
710#endif
711
712/*
713 * Set up the interrupt config lists, in the same format as the mpbios does.
714 */
715static void
716mpacpi_config_irouting(struct acpi_softc *acpi)
717{
718#if NPCI > 0
719	struct mpacpi_pcibus *mpr;
720#endif
721	int nintr;
722	int i;
723	struct mp_bus *mbp;
724	struct mp_intr_map *mpi;
725	struct pic *pic;
726
727	nintr = mpacpi_nintsrc + NUM_LEGACY_IRQS - 1;
728#if NPCI > 0
729	TAILQ_FOREACH(mpr, &mpacpi_pcibusses, mpr_list) {
730		nintr += mpacpi_pcircount(mpr);
731	}
732
733	mp_isa_bus = mpacpi_maxpci + BUS_BUFFER; /* XXX */
734#else
735	mp_isa_bus = 0;
736#endif
737	mp_nbus = mp_isa_bus + 1;
738	mp_nintr = nintr;
739
740	mp_busses = kmem_zalloc(sizeof(struct mp_bus) * mp_nbus, KM_SLEEP);
741	if (mp_busses == NULL)
742		panic("can't allocate mp_busses");
743
744	mp_intrs = kmem_zalloc(sizeof(struct mp_intr_map) * mp_nintr, KM_SLEEP);
745	if (mp_intrs == NULL)
746		panic("can't allocate mp_intrs");
747
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
824static void
825mpacpi_print_pci_intr(int intr)
826{
827	printf(" device %d INT_%c", (intr>>2)&0x1f, 'A' + (intr & 0x3));
828}
829#endif
830
831static void
832mpacpi_print_isa_intr(int intr)
833{
834	printf(" irq %d", intr);
835}
836
837static const char inttype_fmt[] = "\177\020"
838		"f\0\2type\0" "=\1NMI\0" "=\2SMI\0" "=\3ExtINT\0";
839
840static 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
844static void
845mpacpi_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
895int
896mpacpi_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
948int
949mpacpi_pci_attach_hook(device_t parent, device_t self,
950		       struct pcibus_attach_args *pba)
951{
952	struct mp_bus *mpb;
953
954#ifdef MPBIOS
955	if (mpbios_scanned != 0)
956		return ENOENT;
957#endif
958
959	if (TAILQ_EMPTY(&mpacpi_pcibusses))
960		return 0;
961
962	/*
963	 * If this bus is not found in mpacpi_find_pcibusses
964	 * (i.e. behind PCI-to-PCI bridge), register as an extra bus.
965	 *
966	 * at this point, mp_busses[] are as follows:
967	 *  mp_busses[0 .. mpacpi_maxpci] : PCI
968	 *  mp_busses[mpacpi_maxpci + BUS_BUFFER] : ISA
969	 */
970	if (pba->pba_bus >= mp_isa_bus) {
971		intr_add_pcibus(pba);
972		return 0;
973	}
974
975	mpb = &mp_busses[pba->pba_bus];
976	if (mpb->mb_name != NULL) {
977		if (strcmp(mpb->mb_name, "pci"))
978			return EINVAL;
979	} else
980		/*
981		 * As we cannot find all PCI-to-PCI bridge in
982		 * mpacpi_find_pcibusses, some of the MP_busses may remain
983		 * uninitialized.
984		 */
985		mpb->mb_name = "pci";
986
987	mpb->mb_dev = self;
988	mpb->mb_pci_bridge_tag = pba->pba_bridgetag;
989	mpb->mb_pci_chipset_tag = pba->pba_pc;
990
991	if (mp_verbose)
992		printf("\n%s: added to list as bus %d", device_xname(parent),
993		    pba->pba_bus);
994
995
996	if (pba->pba_bus > mpacpi_maxpci)
997		mpacpi_maxpci = pba->pba_bus;
998
999	return 0;
1000}
1001#endif
1002
1003int
1004mpacpi_findintr_linkdev(struct mp_intr_map *mip)
1005{
1006	int irq, line, pol, trig;
1007	struct pic *pic;
1008	int pin;
1009
1010	if (mip->linkdev == NULL)
1011		return ENOENT;
1012
1013	irq = acpi_pci_link_route_interrupt(mip->linkdev, mip->sourceindex,
1014	    &line, &pol, &trig);
1015	if (mp_verbose)
1016		printf("linkdev %s returned ACPI global irq %d, line %d\n",
1017		    acpi_pci_link_name(mip->linkdev), irq, line);
1018	if (irq == X86_PCI_INTERRUPT_LINE_NO_CONNECTION)
1019		return ENOENT;
1020	if (irq != line) {
1021		aprint_error("%s: mpacpi_findintr_linkdev:"
1022		    " irq mismatch (%d vs %d)\n",
1023		    acpi_pci_link_name(mip->linkdev), irq, line);
1024		return ENOENT;
1025	}
1026
1027	/*
1028	 * Convert ACPICA values to MPS values
1029	 */
1030	if (pol == ACPI_ACTIVE_LOW)
1031		pol = MPS_INTPO_ACTLO;
1032	else
1033		pol = MPS_INTPO_ACTHI;
1034
1035	if (trig == ACPI_EDGE_SENSITIVE)
1036		trig = MPS_INTTR_EDGE;
1037	else
1038		trig = MPS_INTTR_LEVEL;
1039
1040	mip->flags = pol | (trig << 2);
1041	mip->global_int = irq;
1042	pic = intr_findpic(irq);
1043	if (pic == NULL)
1044		return ENOENT;
1045	mip->ioapic = pic;
1046	pin = irq - pic->pic_vecbase;
1047
1048	if (pic->pic_type == PIC_IOAPIC) {
1049#if NIOAPIC > 0
1050		mip->redir = (IOAPIC_REDLO_DEL_FIXED<<IOAPIC_REDLO_DEL_SHIFT);
1051		if (pol ==  MPS_INTPO_ACTLO)
1052			mip->redir |= IOAPIC_REDLO_ACTLO;
1053		if (trig ==  MPS_INTTR_LEVEL)
1054			mip->redir |= IOAPIC_REDLO_LEVEL;
1055		mip->ioapic_ih = APIC_INT_VIA_APIC |
1056		    (pic->pic_apicid << APIC_INT_APIC_SHIFT) |
1057		    (pin << APIC_INT_PIN_SHIFT);
1058		pic->pic_ioapic->sc_pins[pin].ip_map = mip;
1059		mip->ioapic_pin = pin;
1060#else
1061		return ENOENT;
1062#endif
1063	} else
1064		mip->ioapic_ih = pin;
1065	return 0;
1066}
1067
1068static void
1069mpacpi_user_continue(const char *fmt, ...)
1070{
1071	va_list ap;
1072
1073	if (!mpacpi_step)
1074		return;
1075
1076	printf("mpacpi: ");
1077	va_start(ap, fmt);
1078	vprintf(fmt, ap);
1079	va_end(ap);
1080	printf("<press any key to continue>\n>");
1081	cngetc();
1082}
1083