1/* $NetBSD: mpacpi.c,v 1.102 2016/07/07 06:55:40 msaitoh 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.102 2016/07/07 06:55:40 msaitoh 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 ACPI_HANDLE mpr_handle; /* Same thing really, but.. */
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_sm_loc(parent, "cpubus", locs,
387 &caa, mpacpi_cpuprint, config_stdsubmatch);
388 }
389 break;
390
391 case ACPI_MADT_TYPE_LOCAL_X2APIC:
392 x2apic = (ACPI_MADT_LOCAL_X2APIC *)hdrp;
393
394 /* ACPI spec: "Logical processors with APIC ID values
395 * less than 255 must use the Processor Local APIC
396 * structure to convey their APIC information to OSPM."
397 */
398 if (x2apic->LocalApicId <= 0xff) {
399 printf("bogus MADT X2APIC entry (id = 0x%"PRIx32")\n",
400 x2apic->LocalApicId);
401 break;
402 }
403
404 if (x2apic->LapicFlags & ACPI_MADT_ENABLED) {
405 if (x2apic->LocalApicId != cpunum)
406 caa.cpu_role = CPU_ROLE_AP;
407 else
408 caa.cpu_role = CPU_ROLE_BP;
409 caa.cpu_id = x2apic->Uid;
410 caa.cpu_number = x2apic->LocalApicId;
411 caa.cpu_func = &mp_cpu_funcs;
412 locs[CPUBUSCF_APID] = caa.cpu_number;
413 config_found_sm_loc(parent, "cpubus", locs,
414 &caa, mpacpi_cpuprint, config_stdsubmatch);
415 }
416 break;
417
418 }
419 return AE_OK;
420}
421
422static ACPI_STATUS
423mpacpi_config_ioapic(ACPI_SUBTABLE_HEADER *hdrp, void *aux)
424{
425 device_t parent = aux;
426 struct apic_attach_args aaa;
427 ACPI_MADT_IO_APIC *p;
428 int locs[IOAPICBUSCF_NLOCS];
429
430 if (hdrp->Type == ACPI_MADT_TYPE_IO_APIC) {
431 p = (ACPI_MADT_IO_APIC *)hdrp;
432 aaa.apic_id = p->Id;
433 aaa.apic_address = p->Address;
434 aaa.apic_version = -1;
435 aaa.flags = IOAPIC_VWIRE;
436 aaa.apic_vecbase = p->GlobalIrqBase;
437 locs[IOAPICBUSCF_APID] = aaa.apic_id;
438 config_found_sm_loc(parent, "ioapicbus", locs, &aaa,
439 mpacpi_ioapicprint, config_stdsubmatch);
440 }
441 return AE_OK;
442}
443
444int
445mpacpi_scan_apics(device_t self, int *ncpup)
446{
447 int rv = 0;
448
449 if (acpi_madt_map() != AE_OK)
450 return 0;
451
452 mpacpi_ncpu = mpacpi_nintsrc = mpacpi_nioapic = 0;
453 acpi_madt_walk(mpacpi_count, self);
454
455 acpi_madt_walk(mpacpi_config_ioapic, self);
456
457#if NLAPIC > 0
458 lapic_boot_init(mpacpi_lapic_base);
459#endif
460
461 acpi_madt_walk(mpacpi_config_cpu, self);
462
463 if (mpacpi_ncpu == 0)
464 goto done;
465
466#if NPCI > 0
467 /*
468 * If PCI routing tables can't be built we report failure
469 * and let MPBIOS do the work.
470 */
471 if (!mpacpi_force &&
472 (acpi_find_quirks() & (ACPI_QUIRK_BADPCI)) != 0)
473 goto done;
474#endif
475 rv = 1;
476done:
477 *ncpup = mpacpi_ncpu;
478 acpi_madt_unmap();
479 return rv;
480}
481
482#if NPCI > 0
483
484static void
485mpacpi_pci_foundbus(struct acpi_devnode *ad)
486{
487 struct mpacpi_pcibus *mpr;
488 ACPI_BUFFER buf;
489 int rv;
490
491 /*
492 * set mpr_buf from _PRT (if it exists).
493 * set mpr_seg and mpr_bus from previously cached info.
494 */
495
496 rv = acpi_get(ad->ad_handle, &buf, AcpiGetIrqRoutingTable);
497 if (ACPI_FAILURE(rv)) {
498 buf.Length = 0;
499 buf.Pointer = NULL;
500 }
501
502 mpr = kmem_zalloc(sizeof(struct mpacpi_pcibus), KM_SLEEP);
503 mpr->mpr_handle = ad->ad_handle;
504 mpr->mpr_buf = buf;
505 mpr->mpr_seg = ad->ad_pciinfo->ap_segment;
506 mpr->mpr_bus = ad->ad_pciinfo->ap_downbus;
507 TAILQ_INSERT_TAIL(&mpacpi_pcibusses, mpr, mpr_list);
508
509 if ((ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0) {
510 if (mp_verbose)
511 printf("mpacpi: found root PCI bus %d\n",
512 mpr->mpr_bus);
513 mpacpi_npciroots++;
514 } else {
515 if (mp_verbose)
516 printf("mpacpi: found subordinate bus %d\n",
517 mpr->mpr_bus);
518 }
519
520 /*
521 * XXX this wrongly assumes that bus numbers are unique
522 * even between segments.
523 */
524 if (mpr->mpr_bus > mpacpi_maxpci)
525 mpacpi_maxpci = mpr->mpr_bus;
526
527 mpacpi_npci++;
528}
529
530
531static void
532mpacpi_pci_walk(struct acpi_devnode *ad)
533{
534 struct acpi_devnode *child;
535
536 if (ad->ad_pciinfo &&
537 (ad->ad_pciinfo->ap_flags & ACPI_PCI_INFO_BRIDGE) != 0) {
538 mpacpi_pci_foundbus(ad);
539 }
540 SIMPLEQ_FOREACH(child, &ad->ad_child_head, ad_child_list) {
541 mpacpi_pci_walk(child);
542 }
543}
544
545static int
546mpacpi_find_pcibusses(struct acpi_softc *sc)
547{
548
549 TAILQ_INIT(&mpacpi_pcibusses);
550 mpacpi_pci_walk(sc->sc_root);
551 return 0;
552}
553
554/*
555 * Find all static PRT entries for a PCI bus.
556 */
557static int
558mpacpi_pciroute(struct mpacpi_pcibus *mpr)
559{
560 ACPI_PCI_ROUTING_TABLE *ptrp;
561 ACPI_HANDLE linkdev;
562 char *p;
563 struct mp_intr_map *mpi, *iter;
564 struct mp_bus *mpb;
565 struct pic *pic;
566 unsigned dev;
567 int pin;
568
569 if (mp_verbose)
570 printf("mpacpi: configuring PCI bus %d int routing\n",
571 mpr->mpr_bus);
572
573 mpb = &mp_busses[mpr->mpr_bus];
574
575 if (mpb->mb_name != NULL)
576 printf("mpacpi: PCI bus %d int routing already done!\n",
577 mpr->mpr_bus);
578
579 mpb->mb_intrs = NULL;
580 mpb->mb_name = "pci";
581 mpb->mb_idx = mpr->mpr_bus;
582 mpb->mb_intr_print = mpacpi_print_pci_intr;
583 mpb->mb_intr_cfg = NULL;
584 mpb->mb_data = 0;
585
586 if (mpr->mpr_buf.Length == 0) {
587 goto out;
588 }
589
590 for (p = mpr->mpr_buf.Pointer; ; p += ptrp->Length) {
591 ptrp = (ACPI_PCI_ROUTING_TABLE *)p;
592 if (ptrp->Length == 0)
593 break;
594 dev = ACPI_HIWORD(ptrp->Address);
595
596 if (ptrp->Source[0] == 0 &&
597 (ptrp->SourceIndex == 14 || ptrp->SourceIndex == 15)) {
598 printf("Skipping PCI routing entry for PCI IDE compat IRQ");
599 continue;
600 }
601
602 mpi = &mp_intrs[mpacpi_intr_index];
603 mpi->bus_pin = (dev << 2) | (ptrp->Pin & 3);
604 mpi->bus = mpb;
605 mpi->type = MPS_INTTYPE_INT;
606
607 /*
608 * First check if an entry for this device/pin combination
609 * was already found. Some DSDTs have more than one entry
610 * and it seems that the first is generally the right one.
611 */
612 for (iter = mpb->mb_intrs; iter != NULL; iter = iter->next) {
613 if (iter->bus_pin == mpi->bus_pin)
614 break;
615 }
616 if (iter != NULL)
617 continue;
618
619 ++mpacpi_intr_index;
620
621 if (ptrp->Source[0] != 0) {
622 if (mp_verbose > 1)
623 printf("pciroute: dev %d INT%c on lnkdev %s\n",
624 dev, 'A' + (ptrp->Pin & 3), ptrp->Source);
625 mpi->global_int = -1;
626 mpi->sourceindex = ptrp->SourceIndex;
627 if (AcpiGetHandle(ACPI_ROOT_OBJECT, ptrp->Source,
628 &linkdev) != AE_OK) {
629 printf("AcpiGetHandle failed for '%s'\n",
630 ptrp->Source);
631 continue;
632 }
633 /* acpi_allocate_resources(linkdev); */
634 mpi->ioapic_pin = -1;
635 mpi->linkdev = acpi_pci_link_devbyhandle(linkdev);
636 acpi_pci_link_add_reference(mpi->linkdev, 0,
637 mpr->mpr_bus, dev, ptrp->Pin & 3);
638 mpi->ioapic = NULL;
639 mpi->flags = MPS_INTPO_ACTLO | (MPS_INTTR_LEVEL << 2);
640 if (mp_verbose > 1)
641 printf("pciroute: done adding entry\n");
642 } else {
643 if (mp_verbose > 1)
644 printf("pciroute: dev %d INT%c on globint %d\n",
645 dev, 'A' + (ptrp->Pin & 3),
646 ptrp->SourceIndex);
647 mpi->sourceindex = 0;
648 mpi->global_int = ptrp->SourceIndex;
649 pic = intr_findpic(ptrp->SourceIndex);
650 if (pic == NULL)
651 continue;
652 /* Defaults for PCI (active low, level triggered) */
653 mpi->redir =
654 (IOAPIC_REDLO_DEL_FIXED <<IOAPIC_REDLO_DEL_SHIFT) |
655 IOAPIC_REDLO_LEVEL | IOAPIC_REDLO_ACTLO;
656 mpi->ioapic = pic;
657 pin = ptrp->SourceIndex - pic->pic_vecbase;
658 if (pic->pic_type == PIC_I8259 && pin > 15)
659 panic("bad pin %d for legacy IRQ", pin);
660 mpi->ioapic_pin = pin;
661#if NIOAPIC > 0
662 if (pic->pic_type == PIC_IOAPIC) {
663 pic->pic_ioapic->sc_pins[pin].ip_map = mpi;
664 mpi->ioapic_ih = APIC_INT_VIA_APIC |
665 (pic->pic_apicid << APIC_INT_APIC_SHIFT) |
666 (pin << APIC_INT_PIN_SHIFT);
667 } else
668#endif
669 mpi->ioapic_ih = pin;
670 mpi->linkdev = NULL;
671 mpi->flags = MPS_INTPO_ACTLO | (MPS_INTTR_LEVEL << 2);
672 if (mp_verbose > 1)
673 printf("pciroute: done adding entry\n");
674 }
675
676 mpi->cpu_id = 0;
677
678 mpi->next = mpb->mb_intrs;
679 mpb->mb_intrs = mpi;
680 }
681
682 ACPI_FREE(mpr->mpr_buf.Pointer);
683 mpr->mpr_buf.Pointer = NULL; /* be preventive to bugs */
684
685out:
686 if (mp_verbose > 1)
687 printf("pciroute: done\n");
688
689 return 0;
690}
691
692/*
693 * Count number of elements in _PRT
694 */
695static int
696mpacpi_pcircount(struct mpacpi_pcibus *mpr)
697{
698 int count = 0;
699 ACPI_PCI_ROUTING_TABLE *PrtElement;
700 uint8_t *Buffer;
701
702 if (mpr->mpr_buf.Length == 0) {
703 return 0;
704 }
705
706 for (Buffer = mpr->mpr_buf.Pointer;; Buffer += PrtElement->Length) {
707 PrtElement = (ACPI_PCI_ROUTING_TABLE *)Buffer;
708 if (PrtElement->Length == 0)
709 break;
710 count++;
711 }
712
713 return count;
714}
715#endif
716
717/*
718 * Set up the interrupt config lists, in the same format as the mpbios does.
719 */
720static void
721mpacpi_config_irouting(struct acpi_softc *acpi)
722{
723#if NPCI > 0
724 struct mpacpi_pcibus *mpr;
725#endif
726 int nintr;
727 int i;
728 struct mp_bus *mbp;
729 struct mp_intr_map *mpi;
730 struct pic *pic;
731
732 nintr = mpacpi_nintsrc + NUM_LEGACY_IRQS - 1;
733#if NPCI > 0
734 TAILQ_FOREACH(mpr, &mpacpi_pcibusses, mpr_list) {
735 nintr += mpacpi_pcircount(mpr);
736 }
737
738 mp_isa_bus = mpacpi_maxpci + BUS_BUFFER; /* XXX */
739#else
740 mp_isa_bus = 0;
741#endif
742 mp_nbus = mp_isa_bus + 1;
743 mp_nintr = nintr;
744
745 mp_busses = kmem_zalloc(sizeof(struct mp_bus) * mp_nbus, KM_SLEEP);
746 if (mp_busses == NULL)
747 panic("can't allocate mp_busses");
748
749 mp_intrs = kmem_zalloc(sizeof(struct mp_intr_map) * mp_nintr, KM_SLEEP);
750 if (mp_intrs == NULL)
751 panic("can't allocate mp_intrs");
752
753 mbp = &mp_busses[mp_isa_bus];
754 mbp->mb_name = "isa";
755 mbp->mb_idx = 0;
756 mbp->mb_intr_print = mpacpi_print_isa_intr;
757 mbp->mb_intr_cfg = NULL;
758 mbp->mb_intrs = &mp_intrs[0];
759 mbp->mb_data = 0;
760
761 pic = intr_findpic(0);
762 if (pic == NULL)
763 panic("mpacpi: can't find first PIC");
764#if NIOAPIC == 0
765 if (pic->pic_type == PIC_IOAPIC)
766 panic("mpacpi: ioapic but no i8259?");
767#endif
768
769 /*
770 * Set up default identity mapping for ISA irqs to first ioapic.
771 */
772 for (i = mpacpi_intr_index = 0; i < NUM_LEGACY_IRQS; i++) {
773 if (i == 2)
774 continue;
775 mpi = &mp_intrs[mpacpi_intr_index];
776 if (mpacpi_intr_index < (NUM_LEGACY_IRQS - 2))
777 mpi->next = &mp_intrs[mpacpi_intr_index + 1];
778 else
779 mpi->next = NULL;
780 mpi->bus = mbp;
781 mpi->bus_pin = i;
782 mpi->ioapic_pin = i;
783 mpi->ioapic = pic;
784 mpi->type = MPS_INTTYPE_INT;
785 mpi->cpu_id = 0;
786 mpi->redir = 0;
787#if NIOAPIC > 0
788 if (pic->pic_type == PIC_IOAPIC) {
789 mpi->ioapic_ih = APIC_INT_VIA_APIC |
790 (pic->pic_apicid << APIC_INT_APIC_SHIFT) |
791 (i << APIC_INT_PIN_SHIFT);
792 mpi->redir =
793 (IOAPIC_REDLO_DEL_FIXED << IOAPIC_REDLO_DEL_SHIFT);
794 pic->pic_ioapic->sc_pins[i].ip_map = mpi;
795 } else
796#endif
797 mpi->ioapic_ih = i;
798
799 mpi->flags = MPS_INTPO_DEF | (MPS_INTTR_DEF << 2);
800 mpi->global_int = i;
801 mpacpi_intr_index++;
802 }
803
804 mpacpi_user_continue("done setting up mp_bus array and ISA maps");
805
806 if (acpi_madt_map() == AE_OK) {
807 acpi_madt_walk(mpacpi_nonpci_intr, &mpacpi_intr_index);
808 acpi_madt_unmap();
809 }
810
811 mpacpi_user_continue("done with non-PCI interrupts");
812
813#if NPCI > 0
814 TAILQ_FOREACH(mpr, &mpacpi_pcibusses, mpr_list) {
815 mpacpi_pciroute(mpr);
816 }
817#endif
818
819 mpacpi_user_continue("done routing PCI interrupts");
820
821 mp_nintr = mpacpi_intr_index;
822}
823
824/*
825 * XXX code duplication with mpbios.c
826 */
827
828#if NPCI > 0
829static void
830mpacpi_print_pci_intr(int intr)
831{
832 printf(" device %d INT_%c", (intr >> 2) & 0x1f, 'A' + (intr & 0x3));
833}
834#endif
835
836static void
837mpacpi_print_isa_intr(int intr)
838{
839 printf(" irq %d", intr);
840}
841
842static const char inttype_fmt[] = "\177\020"
843 "f\0\2type\0" "=\1NMI\0" "=\2SMI\0" "=\3ExtINT\0";
844
845static const char flagtype_fmt[] = "\177\020"
846 "f\0\2pol\0" "=\1Act Hi\0" "=\3Act Lo\0"
847 "f\2\2trig\0" "=\1Edge\0" "=\3Level\0";
848
849static void
850mpacpi_print_intr(struct mp_intr_map *mpi)
851{
852 char buf[256];
853 int pin;
854 struct pic *sc;
855 const char *busname;
856
857 sc = mpi->ioapic;
858 pin = mpi->ioapic_pin;
859 if (mpi->bus != NULL)
860 busname = mpi->bus->mb_name;
861 else {
862 switch (mpi->type) {
863 case MPS_INTTYPE_NMI:
864 busname = "NMI";
865 break;
866 case MPS_INTTYPE_SMI:
867 busname = "SMI";
868 break;
869 case MPS_INTTYPE_ExtINT:
870 busname = "ExtINT";
871 break;
872 default:
873 busname = "<unknown>";
874 break;
875 }
876 }
877
878 if (mpi->linkdev != NULL)
879 printf("linkdev %s attached to %s",
880 acpi_pci_link_name(mpi->linkdev), busname);
881 else
882 printf("%s: pin %d attached to %s",
883 sc ? sc->pic_name : "local apic",
884 pin, busname);
885
886 if (mpi->bus != NULL) {
887 if (mpi->bus->mb_idx != -1)
888 printf("%d", mpi->bus->mb_idx);
889 (*(mpi->bus->mb_intr_print))(mpi->bus_pin);
890 }
891 snprintb(buf, sizeof(buf), inttype_fmt, mpi->type);
892 printf(" (type %s", buf);
893
894 snprintb(buf, sizeof(buf), flagtype_fmt, mpi->flags);
895 printf(" flags %s)\n", buf);
896
897}
898
899
900int
901mpacpi_find_interrupts(void *self)
902{
903#if NIOAPIC > 0
904 ACPI_STATUS rv;
905#endif
906 struct acpi_softc *acpi = self;
907 int i;
908
909#ifdef MPBIOS
910 /*
911 * If MPBIOS was enabled, and did the work (because the initial
912 * MADT scan failed for some reason), there's nothing left to
913 * do here. Same goes for the case where no I/O APICS were found.
914 */
915 if (mpbios_scanned)
916 return 0;
917#endif
918
919#if NIOAPIC > 0
920 if (mpacpi_nioapic != 0) {
921 /*
922 * Switch us into APIC mode by evaluating _PIC(1).
923 * Needs to be done now, since it has an effect on
924 * the interrupt information we're about to retrieve.
925 *
926 * ACPI 3.0 (section 5.8.1):
927 * 0 = PIC mode, 1 = APIC mode, 2 = SAPIC mode.
928 */
929 rv = acpi_eval_set_integer(NULL, "\\_PIC", 1);
930 if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) {
931 if (mp_verbose)
932 printf("mpacpi: switch to APIC mode failed\n");
933 return 0;
934 }
935 }
936#endif
937
938#if NPCI > 0
939 mpacpi_user_continue("finding PCI busses ");
940 mpacpi_find_pcibusses(acpi);
941 if (mp_verbose)
942 printf("mpacpi: %d PCI busses\n", mpacpi_npci);
943#endif
944 mpacpi_config_irouting(acpi);
945 if (mp_verbose)
946 for (i = 0; i < mp_nintr; i++)
947 mpacpi_print_intr(&mp_intrs[i]);
948 return 0;
949}
950
951#if NPCI > 0
952
953int
954mpacpi_pci_attach_hook(device_t parent, device_t self,
955 struct pcibus_attach_args *pba)
956{
957 struct mp_bus *mpb;
958
959#ifdef MPBIOS
960 if (mpbios_scanned != 0)
961 return ENOENT;
962#endif
963
964 if (TAILQ_EMPTY(&mpacpi_pcibusses))
965 return 0;
966
967 /*
968 * If this bus is not found in mpacpi_find_pcibusses
969 * (i.e. behind PCI-to-PCI bridge), register as an extra bus.
970 *
971 * at this point, mp_busses[] are as follows:
972 * mp_busses[0 .. mpacpi_maxpci] : PCI
973 * mp_busses[mpacpi_maxpci + BUS_BUFFER] : ISA
974 */
975 if (pba->pba_bus >= mp_isa_bus) {
976 intr_add_pcibus(pba);
977 return 0;
978 }
979
980 mpb = &mp_busses[pba->pba_bus];
981 if (mpb->mb_name != NULL) {
982 if (strcmp(mpb->mb_name, "pci"))
983 return EINVAL;
984 } else
985 /*
986 * As we cannot find all PCI-to-PCI bridge in
987 * mpacpi_find_pcibusses, some of the MP_busses may remain
988 * uninitialized.
989 */
990 mpb->mb_name = "pci";
991
992 mpb->mb_dev = self;
993 mpb->mb_pci_bridge_tag = pba->pba_bridgetag;
994 mpb->mb_pci_chipset_tag = pba->pba_pc;
995
996 if (mp_verbose)
997 printf("\n%s: added to list as bus %d", device_xname(parent),
998 pba->pba_bus);
999
1000
1001 if (pba->pba_bus > mpacpi_maxpci)
1002 mpacpi_maxpci = pba->pba_bus;
1003
1004 return 0;
1005}
1006#endif
1007
1008int
1009mpacpi_findintr_linkdev(struct mp_intr_map *mip)
1010{
1011 int irq, line, pol, trig;
1012 struct pic *pic;
1013 int pin;
1014
1015 if (mip->linkdev == NULL)
1016 return ENOENT;
1017
1018 irq = acpi_pci_link_route_interrupt(mip->linkdev, mip->sourceindex,
1019 &line, &pol, &trig);
1020 if (mp_verbose)
1021 printf("linkdev %s returned ACPI global irq %d, line %d\n",
1022 acpi_pci_link_name(mip->linkdev), irq, line);
1023 if (irq == X86_PCI_INTERRUPT_LINE_NO_CONNECTION)
1024 return ENOENT;
1025 if (irq != line) {
1026 aprint_error("%s: mpacpi_findintr_linkdev:"
1027 " irq mismatch (%d vs %d)\n",
1028 acpi_pci_link_name(mip->linkdev), irq, line);
1029 return ENOENT;
1030 }
1031
1032 /*
1033 * Convert ACPICA values to MPS values
1034 */
1035 if (pol == ACPI_ACTIVE_LOW)
1036 pol = MPS_INTPO_ACTLO;
1037 else
1038 pol = MPS_INTPO_ACTHI;
1039
1040 if (trig == ACPI_EDGE_SENSITIVE)
1041 trig = MPS_INTTR_EDGE;
1042 else
1043 trig = MPS_INTTR_LEVEL;
1044
1045 mip->flags = pol | (trig << 2);
1046 mip->global_int = irq;
1047 pic = intr_findpic(irq);
1048 if (pic == NULL)
1049 return ENOENT;
1050 mip->ioapic = pic;
1051 pin = irq - pic->pic_vecbase;
1052
1053 if (pic->pic_type == PIC_IOAPIC) {
1054#if NIOAPIC > 0
1055 mip->redir = (IOAPIC_REDLO_DEL_FIXED <<IOAPIC_REDLO_DEL_SHIFT);
1056 if (pol == MPS_INTPO_ACTLO)
1057 mip->redir |= IOAPIC_REDLO_ACTLO;
1058 if (trig == MPS_INTTR_LEVEL)
1059 mip->redir |= IOAPIC_REDLO_LEVEL;
1060 mip->ioapic_ih = APIC_INT_VIA_APIC |
1061 (pic->pic_apicid << APIC_INT_APIC_SHIFT) |
1062 (pin << APIC_INT_PIN_SHIFT);
1063 pic->pic_ioapic->sc_pins[pin].ip_map = mip;
1064 mip->ioapic_pin = pin;
1065#else
1066 return ENOENT;
1067#endif
1068 } else
1069 mip->ioapic_ih = pin;
1070 return 0;
1071}
1072
1073static void
1074mpacpi_user_continue(const char *fmt, ...)
1075{
1076 va_list ap;
1077
1078 if (!mpacpi_step)
1079 return;
1080
1081 printf("mpacpi: ");
1082 va_start(ap, fmt);
1083 vprintf(fmt, ap);
1084 va_end(ap);
1085 printf("<press any key to continue>\n>");
1086 cngetc();
1087}
1088
1089#ifdef DDB
1090void
1091mpacpi_dump(void)
1092{
1093 int i;
1094 for (i = 0; i < mp_nintr; i++)
1095 mpacpi_print_intr(&mp_intrs[i]);
1096}
1097#endif
1098