| 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 |
| 79 | ACPI_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 |
| 91 | struct 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 | |
| 99 | static TAILQ_HEAD(, mpacpi_pcibus) mpacpi_pcibusses; |
| 100 | |
| 101 | #endif |
| 102 | |
| 103 | static int mpacpi_cpuprint(void *, const char *); |
| 104 | static int mpacpi_ioapicprint(void *, const char *); |
| 105 | |
| 106 | /* acpi_madt_walk callbacks */ |
| 107 | static ACPI_STATUS mpacpi_count(ACPI_SUBTABLE_HEADER *, void *); |
| 108 | static ACPI_STATUS mpacpi_config_cpu(ACPI_SUBTABLE_HEADER *, void *); |
| 109 | static ACPI_STATUS mpacpi_config_ioapic(ACPI_SUBTABLE_HEADER *, void *); |
| 110 | static ACPI_STATUS mpacpi_nonpci_intr(ACPI_SUBTABLE_HEADER *, void *); |
| 111 | |
| 112 | #if NPCI > 0 |
| 113 | static int mpacpi_pcircount(struct mpacpi_pcibus *); |
| 114 | static int mpacpi_pciroute(struct mpacpi_pcibus *); |
| 115 | static int mpacpi_find_pcibusses(struct acpi_softc *); |
| 116 | |
| 117 | static void mpacpi_print_pci_intr(int); |
| 118 | #endif |
| 119 | |
| 120 | static void mpacpi_config_irouting(struct acpi_softc *); |
| 121 | |
| 122 | static void mpacpi_print_intr(struct mp_intr_map *); |
| 123 | static void mpacpi_print_isa_intr(int); |
| 124 | |
| 125 | static void mpacpi_user_continue(const char *fmt, ...); |
| 126 | |
| 127 | #ifdef DDB |
| 128 | void mpacpi_dump(void); |
| 129 | #endif |
| 130 | |
| 131 | int mpacpi_nioapic; /* number of ioapics */ |
| 132 | int mpacpi_ncpu; /* number of cpus */ |
| 133 | int mpacpi_nintsrc; /* number of non-device interrupts */ |
| 134 | |
| 135 | #if NPCI > 0 |
| 136 | static int mpacpi_npci; |
| 137 | static int mpacpi_maxpci; |
| 138 | static int mpacpi_npciroots; |
| 139 | #endif |
| 140 | |
| 141 | static int mpacpi_intr_index; |
| 142 | static paddr_t mpacpi_lapic_base = LAPIC_BASE; |
| 143 | |
| 144 | int mpacpi_step; |
| 145 | int mpacpi_force; |
| 146 | |
| 147 | static int |
| 148 | mpacpi_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 | |
| 158 | static int |
| 159 | mpacpi_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 | */ |
| 173 | static ACPI_STATUS |
| 174 | mpacpi_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 | */ |
| 332 | static ACPI_STATUS |
| 333 | mpacpi_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 | |
| 359 | static ACPI_STATUS |
| 360 | mpacpi_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 | |
| 422 | static ACPI_STATUS |
| 423 | mpacpi_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 | |
| 444 | int |
| 445 | mpacpi_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; |
| 476 | done: |
| 477 | *ncpup = mpacpi_ncpu; |
| 478 | acpi_madt_unmap(); |
| 479 | return rv; |
| 480 | } |
| 481 | |
| 482 | #if NPCI > 0 |
| 483 | |
| 484 | static void |
| 485 | mpacpi_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 | |
| 531 | static void |
| 532 | mpacpi_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 | |
| 545 | static int |
| 546 | mpacpi_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 | */ |
| 557 | static int |
| 558 | mpacpi_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 | |
| 685 | out: |
| 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 | */ |
| 695 | static int |
| 696 | mpacpi_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 | */ |
| 720 | static void |
| 721 | mpacpi_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 |
| 829 | static void |
| 830 | mpacpi_print_pci_intr(int intr) |
| 831 | { |
| 832 | printf(" device %d INT_%c" , (intr >> 2) & 0x1f, 'A' + (intr & 0x3)); |
| 833 | } |
| 834 | #endif |
| 835 | |
| 836 | static void |
| 837 | mpacpi_print_isa_intr(int intr) |
| 838 | { |
| 839 | printf(" irq %d" , intr); |
| 840 | } |
| 841 | |
| 842 | static const char inttype_fmt[] = "\177\020" |
| 843 | "f\0\2type\0" "=\1NMI\0" "=\2SMI\0" "=\3ExtINT\0" ; |
| 844 | |
| 845 | static 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 | |
| 849 | static void |
| 850 | mpacpi_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 | |
| 900 | int |
| 901 | mpacpi_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 | |
| 953 | int |
| 954 | mpacpi_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 | |
| 1008 | int |
| 1009 | mpacpi_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 | |
| 1073 | static void |
| 1074 | mpacpi_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 |
| 1090 | void |
| 1091 | mpacpi_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 | |