pci_intr_machdep.c revision 1.12.10.2
11.12.10.2Sjym/* $NetBSD: pci_intr_machdep.c,v 1.12.10.2 2009/11/01 13:58:17 jym Exp $ */ 21.1Sbouyer 31.1Sbouyer/*- 41.12.10.1Sjym * Copyright (c) 1997, 1998, 2009 The NetBSD Foundation, Inc. 51.1Sbouyer * All rights reserved. 61.1Sbouyer * 71.1Sbouyer * This code is derived from software contributed to The NetBSD Foundation 81.1Sbouyer * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 91.1Sbouyer * NASA Ames Research Center. 101.1Sbouyer * 111.1Sbouyer * Redistribution and use in source and binary forms, with or without 121.1Sbouyer * modification, are permitted provided that the following conditions 131.1Sbouyer * are met: 141.1Sbouyer * 1. Redistributions of source code must retain the above copyright 151.1Sbouyer * notice, this list of conditions and the following disclaimer. 161.1Sbouyer * 2. Redistributions in binary form must reproduce the above copyright 171.1Sbouyer * notice, this list of conditions and the following disclaimer in the 181.1Sbouyer * documentation and/or other materials provided with the distribution. 191.1Sbouyer * 201.1Sbouyer * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 211.1Sbouyer * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 221.1Sbouyer * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 231.1Sbouyer * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 241.1Sbouyer * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 251.1Sbouyer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 261.1Sbouyer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 271.1Sbouyer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 281.1Sbouyer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 291.1Sbouyer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 301.1Sbouyer * POSSIBILITY OF SUCH DAMAGE. 311.1Sbouyer */ 321.1Sbouyer 331.1Sbouyer/* 341.1Sbouyer * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 351.1Sbouyer * Copyright (c) 1994 Charles M. Hannum. All rights reserved. 361.1Sbouyer * 371.1Sbouyer * Redistribution and use in source and binary forms, with or without 381.1Sbouyer * modification, are permitted provided that the following conditions 391.1Sbouyer * are met: 401.1Sbouyer * 1. Redistributions of source code must retain the above copyright 411.1Sbouyer * notice, this list of conditions and the following disclaimer. 421.1Sbouyer * 2. Redistributions in binary form must reproduce the above copyright 431.1Sbouyer * notice, this list of conditions and the following disclaimer in the 441.1Sbouyer * documentation and/or other materials provided with the distribution. 451.1Sbouyer * 3. All advertising materials mentioning features or use of this software 461.1Sbouyer * must display the following acknowledgement: 471.1Sbouyer * This product includes software developed by Charles M. Hannum. 481.1Sbouyer * 4. The name of the author may not be used to endorse or promote products 491.1Sbouyer * derived from this software without specific prior written permission. 501.1Sbouyer * 511.1Sbouyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 521.1Sbouyer * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 531.1Sbouyer * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 541.1Sbouyer * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 551.1Sbouyer * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 561.1Sbouyer * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 571.1Sbouyer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 581.1Sbouyer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 591.1Sbouyer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 601.1Sbouyer * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 611.1Sbouyer */ 621.1Sbouyer 631.1Sbouyer/* 641.1Sbouyer * Machine-specific functions for PCI autoconfiguration. 651.1Sbouyer * 661.1Sbouyer * On PCs, there are two methods of generating PCI configuration cycles. 671.1Sbouyer * We try to detect the appropriate mechanism for this machine and set 681.1Sbouyer * up a few function pointers to access the correct method directly. 691.1Sbouyer * 701.1Sbouyer * The configuration method can be hard-coded in the config file by 711.1Sbouyer * using `options PCI_CONF_MODE=N', where `N' is the configuration mode 721.1Sbouyer * as defined section 3.6.4.1, `Generating Configuration Cycles'. 731.1Sbouyer */ 741.1Sbouyer 751.1Sbouyer#include <sys/cdefs.h> 761.12.10.2Sjym__KERNEL_RCSID(0, "$NetBSD: pci_intr_machdep.c,v 1.12.10.2 2009/11/01 13:58:17 jym Exp $"); 771.1Sbouyer 781.1Sbouyer#include <sys/types.h> 791.1Sbouyer#include <sys/param.h> 801.1Sbouyer#include <sys/time.h> 811.1Sbouyer#include <sys/systm.h> 821.1Sbouyer#include <sys/errno.h> 831.1Sbouyer#include <sys/device.h> 841.7Sad#include <sys/intr.h> 851.1Sbouyer 861.1Sbouyer#include <uvm/uvm_extern.h> 871.1Sbouyer 881.1Sbouyer#include <dev/pci/pcivar.h> 891.1Sbouyer 901.1Sbouyer#include "ioapic.h" 911.1Sbouyer#include "eisa.h" 921.12.10.2Sjym#include "acpica.h" 931.1Sbouyer#include "opt_mpbios.h" 941.2Schristos#include "opt_acpi.h" 951.1Sbouyer 961.12.10.2Sjym#if NIOAPIC > 0 || NACPICA > 0 971.1Sbouyer#include <machine/i82093var.h> 981.2Schristos#include <machine/mpconfig.h> 991.1Sbouyer#include <machine/mpbiosvar.h> 1001.1Sbouyer#include <machine/pic.h> 1011.1Sbouyer#endif 1021.1Sbouyer 1031.1Sbouyer#ifdef MPBIOS 1041.1Sbouyer#include <machine/mpbiosvar.h> 1051.1Sbouyer#endif 1061.1Sbouyer 1071.12.10.2Sjym#if NACPICA > 0 1081.1Sbouyer#include <machine/mpacpi.h> 1091.1Sbouyer#endif 1101.1Sbouyer 1111.11Sad#define MPSAFE_MASK 0x80000000 1121.11Sad 1131.1Sbouyerint 1141.9Sceggerpci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 1151.1Sbouyer{ 1161.1Sbouyer int pin = pa->pa_intrpin; 1171.1Sbouyer int line = pa->pa_intrline; 1181.12.10.2Sjym#if NIOAPIC > 0 || NACPICA > 0 1191.1Sbouyer int rawpin = pa->pa_rawintrpin; 1201.1Sbouyer pci_chipset_tag_t pc = pa->pa_pc; 1211.1Sbouyer int bus, dev, func; 1221.1Sbouyer#endif 1231.1Sbouyer 1241.1Sbouyer if (pin == 0) { 1251.1Sbouyer /* No IRQ used. */ 1261.1Sbouyer goto bad; 1271.1Sbouyer } 1281.1Sbouyer 1291.2Schristos *ihp = 0; 1301.2Schristos 1311.1Sbouyer if (pin > PCI_INTERRUPT_PIN_MAX) { 1321.12.10.1Sjym aprint_normal("pci_intr_map: bad interrupt pin %d\n", pin); 1331.1Sbouyer goto bad; 1341.1Sbouyer } 1351.1Sbouyer 1361.12.10.2Sjym#if NIOAPIC > 0 || NACPICA > 0 1371.1Sbouyer pci_decompose_tag(pc, pa->pa_tag, &bus, &dev, &func); 1381.1Sbouyer if (mp_busses != NULL) { 1391.1Sbouyer if (intr_find_mpmapping(bus, (dev<<2)|(rawpin-1), ihp) == 0) { 1401.2Schristos if ((*ihp & 0xff) == 0) 1411.2Schristos *ihp |= line; 1421.1Sbouyer return 0; 1431.1Sbouyer } 1441.1Sbouyer /* 1451.1Sbouyer * No explicit PCI mapping found. This is not fatal, 1461.1Sbouyer * we'll try the ISA (or possibly EISA) mappings next. 1471.1Sbouyer */ 1481.1Sbouyer } 1491.1Sbouyer#endif 1501.1Sbouyer 1511.1Sbouyer /* 1521.1Sbouyer * Section 6.2.4, `Miscellaneous Functions', says that 255 means 1531.1Sbouyer * `unknown' or `no connection' on a PC. We assume that a device with 1541.1Sbouyer * `no connection' either doesn't have an interrupt (in which case the 1551.1Sbouyer * pin number should be 0, and would have been noticed above), or 1561.1Sbouyer * wasn't configured by the BIOS (in which case we punt, since there's 1571.1Sbouyer * no real way we can know how the interrupt lines are mapped in the 1581.1Sbouyer * hardware). 1591.1Sbouyer * 1601.1Sbouyer * XXX 1611.1Sbouyer * Since IRQ 0 is only used by the clock, and we can't actually be sure 1621.1Sbouyer * that the BIOS did its job, we also recognize that as meaning that 1631.1Sbouyer * the BIOS has not configured the device. 1641.1Sbouyer */ 1651.1Sbouyer if (line == 0 || line == X86_PCI_INTERRUPT_LINE_NO_CONNECTION) { 1661.12.10.1Sjym aprint_normal("pci_intr_map: no mapping for pin %c (line=%02x)\n", 1671.1Sbouyer '@' + pin, line); 1681.1Sbouyer goto bad; 1691.1Sbouyer } else { 1701.1Sbouyer if (line >= NUM_LEGACY_IRQS) { 1711.12.10.1Sjym aprint_normal("pci_intr_map: bad interrupt line %d\n", line); 1721.1Sbouyer goto bad; 1731.1Sbouyer } 1741.1Sbouyer if (line == 2) { 1751.12.10.1Sjym aprint_normal("pci_intr_map: changed line 2 to line 9\n"); 1761.1Sbouyer line = 9; 1771.1Sbouyer } 1781.1Sbouyer } 1791.12.10.2Sjym#if NIOAPIC > 0 || NACPICA > 0 1801.1Sbouyer if (mp_busses != NULL) { 1811.1Sbouyer if (intr_find_mpmapping(mp_isa_bus, line, ihp) == 0) { 1821.2Schristos if ((*ihp & 0xff) == 0) 1831.2Schristos *ihp |= line; 1841.1Sbouyer return 0; 1851.1Sbouyer } 1861.1Sbouyer#if NEISA > 0 1871.1Sbouyer if (intr_find_mpmapping(mp_eisa_bus, line, ihp) == 0) { 1881.2Schristos if ((*ihp & 0xff) == 0) 1891.2Schristos *ihp |= line; 1901.1Sbouyer return 0; 1911.1Sbouyer } 1921.1Sbouyer#endif 1931.12.10.1Sjym aprint_normal("pci_intr_map: bus %d dev %d func %d pin %d; line %d\n", 1941.1Sbouyer bus, dev, func, pin, line); 1951.12.10.1Sjym aprint_normal("pci_intr_map: no MP mapping found\n"); 1961.1Sbouyer } 1971.1Sbouyer#endif 1981.1Sbouyer 1991.1Sbouyer *ihp = line; 2001.1Sbouyer return 0; 2011.1Sbouyer 2021.1Sbouyerbad: 2031.1Sbouyer *ihp = -1; 2041.1Sbouyer return 1; 2051.1Sbouyer} 2061.1Sbouyer 2071.1Sbouyerconst char * 2081.6Schristospci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih) 2091.1Sbouyer{ 2101.11Sad return intr_string(ih & ~MPSAFE_MASK); 2111.1Sbouyer} 2121.1Sbouyer 2131.1Sbouyer 2141.1Sbouyerconst struct evcnt * 2151.6Schristospci_intr_evcnt(pci_chipset_tag_t pc, pci_intr_handle_t ih) 2161.1Sbouyer{ 2171.1Sbouyer 2181.1Sbouyer /* XXX for now, no evcnt parent reported */ 2191.1Sbouyer return NULL; 2201.1Sbouyer} 2211.1Sbouyer 2221.11Sadint 2231.11Sadpci_intr_setattr(pci_chipset_tag_t pc, pci_intr_handle_t *ih, 2241.11Sad int attr, uint64_t data) 2251.11Sad{ 2261.11Sad 2271.11Sad switch (attr) { 2281.11Sad case PCI_INTR_MPSAFE: 2291.11Sad if (data) { 2301.11Sad *ih |= MPSAFE_MASK; 2311.11Sad } else { 2321.11Sad *ih &= ~MPSAFE_MASK; 2331.11Sad } 2341.11Sad /* XXX Set live if already mapped. */ 2351.11Sad return 0; 2361.11Sad default: 2371.11Sad return ENODEV; 2381.11Sad } 2391.11Sad} 2401.11Sad 2411.1Sbouyervoid * 2421.6Schristospci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, 2431.5Schristos int level, int (*func)(void *), void *arg) 2441.1Sbouyer{ 2451.1Sbouyer int pin, irq; 2461.1Sbouyer struct pic *pic; 2471.12Sdrochner#if NIOAPIC > 0 2481.12Sdrochner struct ioapic_softc *ioapic; 2491.12Sdrochner#endif 2501.11Sad bool mpsafe; 2511.1Sbouyer 2521.1Sbouyer pic = &i8259_pic; 2531.11Sad pin = irq = (ih & ~MPSAFE_MASK); 2541.11Sad mpsafe = ((ih & MPSAFE_MASK) != 0); 2551.1Sbouyer 2561.1Sbouyer#if NIOAPIC > 0 2571.1Sbouyer if (ih & APIC_INT_VIA_APIC) { 2581.12Sdrochner ioapic = ioapic_find(APIC_IRQ_APIC(ih)); 2591.12Sdrochner if (ioapic == NULL) { 2601.12.10.1Sjym aprint_normal("pci_intr_establish: bad ioapic %d\n", 2611.1Sbouyer APIC_IRQ_APIC(ih)); 2621.1Sbouyer return NULL; 2631.1Sbouyer } 2641.12Sdrochner pic = &ioapic->sc_pic; 2651.1Sbouyer pin = APIC_IRQ_PIN(ih); 2661.1Sbouyer irq = APIC_IRQ_LEGACY_IRQ(ih); 2671.1Sbouyer if (irq < 0 || irq >= NUM_LEGACY_IRQS) 2681.1Sbouyer irq = -1; 2691.1Sbouyer } 2701.1Sbouyer#endif 2711.1Sbouyer 2721.10Sad return intr_establish(irq, pic, pin, IST_LEVEL, level, func, arg, 2731.11Sad mpsafe); 2741.1Sbouyer} 2751.1Sbouyer 2761.1Sbouyervoid 2771.6Schristospci_intr_disestablish(pci_chipset_tag_t pc, void *cookie) 2781.1Sbouyer{ 2791.1Sbouyer 2801.1Sbouyer intr_disestablish(cookie); 2811.1Sbouyer} 282