from netbsd: pci interrupt routing code.
authormickey <mickey@openbsd.org>
Sun, 26 Mar 2000 22:38:20 +0000 (22:38 +0000)
committermickey <mickey@openbsd.org>
Sun, 26 Mar 2000 22:38:20 +0000 (22:38 +0000)
also, change a few pcidevs names to match netbsd (and more descriptive).
tested on a bunch of laptops, helps resolving 'pin X unmapped'
problems for (usually) usb and cardbus cntrollers.

27 files changed:
sys/arch/i386/conf/GENERIC
sys/arch/i386/conf/files.i386
sys/arch/i386/i386/autoconf.c
sys/arch/i386/i386/bios32.c [new file with mode: 0644]
sys/arch/i386/include/biosvar.h
sys/arch/i386/pci/opti82c558.c [new file with mode: 0644]
sys/arch/i386/pci/opti82c558reg.h [new file with mode: 0644]
sys/arch/i386/pci/opti82c700.c [new file with mode: 0644]
sys/arch/i386/pci/opti82c700reg.h [new file with mode: 0644]
sys/arch/i386/pci/pci_bus_fixup.c [new file with mode: 0644]
sys/arch/i386/pci/pci_bus_fixup.h [new file with mode: 0644]
sys/arch/i386/pci/pci_intr_fixup.c [new file with mode: 0644]
sys/arch/i386/pci/pci_intr_fixup.h [new file with mode: 0644]
sys/arch/i386/pci/pcib.c
sys/arch/i386/pci/pcibios.c [new file with mode: 0644]
sys/arch/i386/pci/pcibios.h [new file with mode: 0644]
sys/arch/i386/pci/piix.c [new file with mode: 0644]
sys/arch/i386/pci/piixreg.h [new file with mode: 0644]
sys/arch/i386/pci/piixvar.h [new file with mode: 0644]
sys/arch/i386/pci/sis85c503.c [new file with mode: 0644]
sys/arch/i386/pci/sis85c503reg.h [new file with mode: 0644]
sys/arch/i386/pci/via82c586.c [new file with mode: 0644]
sys/arch/i386/pci/via82c586reg.h [new file with mode: 0644]
sys/dev/pci/files.pci
sys/dev/pci/pci_quirks.c [new file with mode: 0644]
sys/dev/pci/pcidevs
sys/dev/pci/pcivar.h

index 1d47e91..b838ef7 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: GENERIC,v 1.162 2000/03/26 18:49:43 aaron Exp $
+#      $OpenBSD: GENERIC,v 1.163 2000/03/26 22:38:31 mickey Exp $
 #      $NetBSD: GENERIC,v 1.48 1996/05/20 18:17:23 mrg Exp $
 #
 #      GENERIC -- everything that's currently supported
@@ -48,6 +48,8 @@ option                EISAVERBOSE
 #option                PCMCIAVERBOSE
 #option                USBVERBOSE
 
+option BIOS32,PCIBIOS,PCIBIOS_INTR_FIXUP
+
 pchb*  at pci? dev ? function ?        # PCI-Host bridges
 ppb*   at pci? dev ? function ?        # PCI-PCI bridges
 pci*   at ppb? bus ?
index 8c17435..8099307 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.i386,v 1.62 2000/02/21 17:09:08 mickey Exp $
+#      $OpenBSD: files.i386,v 1.63 2000/03/26 22:38:32 mickey Exp $
 #      $NetBSD: files.i386,v 1.73 1996/05/07 00:58:36 thorpej Exp $
 #
 # new style config file for i386 architecture
@@ -84,8 +84,17 @@ file arch/i386/i386/mainbus.c        mainbus
 
 include "../../../dev/pci/files.pci"
 file   arch/i386/pci/pci_machdep.c     pci
-file   arch/i386/pci/pciide_machdep.c  pciide
 file   arch/i386/pci/pci_compat.c      pci     # XXX compatibility
+file   arch/i386/pci/pcibios.c         pcibios
+file   arch/i386/pci/pci_intr_fixup.c  pcibios & pcibios_intr_fixup
+file   arch/i386/pci/piix.c            pcibios & pcibios_intr_fixup
+file   arch/i386/pci/opti82c558.c      pcibios & pcibios_intr_fixup
+file   arch/i386/pci/opti82c700.c      pcibios & pcibios_intr_fixup
+file   arch/i386/pci/sis85c503.c       pcibios & pcibios_intr_fixup
+file   arch/i386/pci/via82c586.c       pcibios & pcibios_intr_fixup
+file   arch/i386/pci/pci_bus_fixup.c   pcibios & pcibios_bus_fixup
+file   arch/i386/pci/pciide_machdep.c  pciide
+file   arch/i386/pci/pcic_pci_machdep.c        pcic_pci
 
 # PCI-Host bridge chipsets
 device pchb:   pcibus
@@ -244,6 +253,8 @@ attach apm at bios
 file   arch/i386/i386/apm.c            apm needs-count
 file   arch/i386/i386/apmcall.S        apm
 
+file   arch/i386/i386/bios32.c         bios32
+
 # XXXX pcic here because it needs to be late.  The catch: pcic needs
 # to be late, so devices which attach to it are attached late.  But it
 # needs to be before its isa and pci attachments.  This answer is
index 28c2a8e..bbff08f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: autoconf.c,v 1.30 1999/09/12 19:44:04 weingart Exp $  */
+/*     $OpenBSD: autoconf.c,v 1.31 2000/03/26 22:38:32 mickey Exp $    */
 /*     $NetBSD: autoconf.c,v 1.20 1996/05/03 19:41:56 christos Exp $   */
 
 /*-
@@ -59,6 +59,9 @@
 
 #include <machine/pte.h>
 #include <machine/cpu.h>
+#include <machine/biosvar.h>
+
+#include <i386/pci/pcibios.h>
 
 #include <dev/cons.h>
 
@@ -84,6 +87,14 @@ configure()
 
        startrtclock();
 
+#ifdef BIOS32
+       bios32_init();
+#endif
+
+#ifdef PCIBIOS
+       pcibios_init();
+#endif
+
        if (config_rootfound("mainbus", NULL) == NULL)
                panic("configure: mainbus not configured");
 
diff --git a/sys/arch/i386/i386/bios32.c b/sys/arch/i386/i386/bios32.c
new file mode 100644 (file)
index 0000000..75a0d47
--- /dev/null
@@ -0,0 +1,180 @@
+/*     $NetBSD: bios32.c,v 1.1 1999/11/17 00:55:50 thorpej Exp $       */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Basic interface to BIOS32 services.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h> 
+#include <sys/malloc.h>
+
+#include <dev/isa/isareg.h>
+#ifdef __NetBSD__
+#include <machine/isa_machdep.h>
+#include <machine/bios32.h>
+#elif defined(__OpenBSD__)
+#include <i386/isa/isa_machdep.h>
+#include <machine/biosvar.h>
+#endif
+
+#include <machine/segments.h>
+
+#define        BIOS32_START    0xe0000
+#define        BIOS32_SIZE     0x20000
+#define        BIOS32_END      (BIOS32_START + BIOS32_SIZE - 0x10)
+
+struct bios32_entry bios32_entry;
+
+/*
+ * Initialize the BIOS32 interface.
+ */
+void
+bios32_init()
+{
+       paddr_t entry = 0;
+       caddr_t p;
+       unsigned char cksum;
+       int i;
+
+       for (p = (caddr_t)ISA_HOLE_VADDR(BIOS32_START);
+            p < (caddr_t)ISA_HOLE_VADDR(BIOS32_END);
+            p += 16) {
+               if (*(int *)p != BIOS32_MAKESIG('_', '3', '2', '_'))
+                       continue;
+
+               cksum = 0;
+               for (i = 0; i < 16; i++)
+                       cksum += *(unsigned char *)(p + i);
+               if (cksum != 0)
+                       continue;
+
+               if (*(p + 9) != 1)
+                       continue;
+
+               entry = *(u_int32_t *)(p + 4);
+
+               printf("BIOS32 rev. %d found at 0x%lx\n",
+                   *(p + 8), entry);
+
+               if (entry < BIOS32_START ||
+                   entry >= BIOS32_END) {
+                       printf("BIOS32 entry point outside "
+                           "allowable range\n");
+                       entry = 0;
+               }
+               break;
+       }
+
+       if (entry != 0) {
+               bios32_entry.offset = (caddr_t)ISA_HOLE_VADDR(entry);
+               bios32_entry.segment = GSEL(GCODE_SEL, SEL_KPL);
+       }
+}
+
+/*
+ * Call BIOS32 to locate the specified BIOS32 service, and fill
+ * in the entry point information.
+ */
+int
+bios32_service(service, e, ei)
+       u_int32_t service;
+       bios32_entry_t e;
+       bios32_entry_info_t ei;
+{
+       u_int32_t eax, ebx, ecx, edx;
+       paddr_t entry;
+
+       if (bios32_entry.offset == 0)
+               return (0);     /* BIOS32 not present */
+
+       __asm __volatile("lcall (%%edi)"
+               : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
+               : "0" (service), "1" (0), "D" (&bios32_entry));
+
+       if ((eax & 0xff) != 0)
+               return (0);     /* service not found */
+
+       entry = ebx + edx;
+
+       if (entry < BIOS32_START || entry >= BIOS32_END) {
+               printf("bios32: entry point for service %c%c%c%c is outside "
+                   "allowable range\n",
+                   service & 0xff,
+                   (service >> 8) & 0xff,
+                   (service >> 16) & 0xff,
+                   (service >> 24) & 0xff);
+               return (0);
+       }
+
+       e->offset = (caddr_t)ISA_HOLE_VADDR(entry);
+       e->segment = GSEL(GCODE_SEL, SEL_KPL);
+
+       ei->bei_base = ebx;
+       ei->bei_size = ecx;
+       ei->bei_entry = entry;
+
+       return (1);
+}
index 2b77643..a80bf2f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: biosvar.h,v 1.34 2000/03/05 19:07:43 mickey Exp $     */
+/*     $OpenBSD: biosvar.h,v 1.35 2000/03/26 22:38:33 mickey Exp $     */
 
 /*
  * Copyright (c) 1997-1999 Michael Shalayeff
 #define        BIOS_MAP_ACPI   0x03    /* ACPI Reclaim memory */
 #define        BIOS_MAP_NVS    0x04    /* ACPI NVS memory */
 
+/*
+ * BIOS32
+ */
+typedef
+struct bios32_entry_info {
+       paddr_t bei_base;
+       psize_t bei_size;
+       paddr_t bei_entry;
+} *bios32_entry_info_t;
+
+typedef
+struct bios32_entry {
+       caddr_t offset;
+       u_int16_t segment;
+} __attribute__((__packed__)) *bios32_entry_t;
+
+#define        BIOS32_MAKESIG(a, b, c, d) \
+       ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
+
 /*
  * CTL_BIOS definitions.
  */
@@ -192,6 +211,10 @@ int bioscngetc __P((dev_t));
 void bioscnpollc __P((dev_t, int));
 void bios_getopt __P((void));
 
+/* bios32.c */
+void bios32_init __P((void));
+int  bios32_service __P((u_int32_t, bios32_entry_t, bios32_entry_info_t));
+
 extern u_int bootapiver;
 extern bios_memmap_t *bios_memmap;
 extern bios_pciinfo_t *bios_pciinfo;
diff --git a/sys/arch/i386/pci/opti82c558.c b/sys/arch/i386/pci/opti82c558.c
new file mode 100644 (file)
index 0000000..74fd328
--- /dev/null
@@ -0,0 +1,248 @@
+/*     $NetBSD$        */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Support for the Opti 82c558 PCI-ISA bridge interrupt controller.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+
+#include <i386/pci/pci_intr_fixup.h>
+#include <i386/pci/opti82c558reg.h>
+
+int    opti82c558_getclink __P((pciintr_icu_handle_t, int, int *));
+int    opti82c558_get_intr __P((pciintr_icu_handle_t, int, int *));
+int    opti82c558_set_intr __P((pciintr_icu_handle_t, int, int));
+int    opti82c558_get_trigger __P((pciintr_icu_handle_t, int, int *));
+int    opti82c558_set_trigger __P((pciintr_icu_handle_t, int, int));
+
+const struct pciintr_icu opti82c558_pci_icu = {
+       opti82c558_getclink,
+       opti82c558_get_intr,
+       opti82c558_set_intr,
+       opti82c558_get_trigger,
+       opti82c558_set_trigger,
+};
+
+struct opti82c558_handle {
+       pci_chipset_tag_t ph_pc;
+       pcitag_t ph_tag;
+};
+
+static const int viper_pirq_decode[] = {
+       -1, 5, 9, 10, 11, 12, 14, 15
+};
+
+static const int viper_pirq_encode[] = {
+       -1,             /* 0 */
+       -1,             /* 1 */
+       -1,             /* 2 */
+       -1,             /* 3 */
+       -1,             /* 4 */
+       VIPER_PIRQ_5,   /* 5 */
+       -1,             /* 6 */
+       -1,             /* 7 */
+       -1,             /* 8 */
+       VIPER_PIRQ_9,   /* 9 */
+       VIPER_PIRQ_10,  /* 10 */
+       VIPER_PIRQ_11,  /* 11 */
+       VIPER_PIRQ_12,  /* 12 */
+       -1,             /* 13 */
+       VIPER_PIRQ_14,  /* 14 */
+       VIPER_PIRQ_15,  /* 15 */
+};
+
+int
+opti82c558_init(pc, iot, tag, ptagp, phandp)
+       pci_chipset_tag_t pc;
+       bus_space_tag_t iot;
+       pcitag_t tag;
+       pciintr_icu_tag_t *ptagp;
+       pciintr_icu_handle_t *phandp;
+{
+       struct opti82c558_handle *ph;
+
+       ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT);
+       if (ph == NULL)
+               return (1);
+
+       ph->ph_pc = pc;
+       ph->ph_tag = tag;
+
+       *ptagp = &opti82c558_pci_icu;
+       *phandp = ph;
+       return (0);
+}
+
+int
+opti82c558_getclink(v, link, clinkp)
+       pciintr_icu_handle_t v;
+       int link, *clinkp;
+{
+
+       if (VIPER_LEGAL_LINK(link - 1)) {
+               *clinkp = link - 1;
+               return (0);
+       }
+
+       return (1);
+}
+
+int
+opti82c558_get_intr(v, clink, irqp)
+       pciintr_icu_handle_t v;
+       int clink, *irqp;
+{
+       struct opti82c558_handle *ph = v;
+       pcireg_t reg;
+       int val;
+
+       if (VIPER_LEGAL_LINK(clink) == 0)
+               return (1);
+
+       reg = pci_conf_read(ph->ph_pc, ph->ph_tag, VIPER_CFG_PIRQ);
+       val = VIPER_PIRQ(reg, clink);
+       *irqp = (val == VIPER_PIRQ_NONE) ? 0xff : viper_pirq_decode[val];
+
+       return (0);
+}
+
+int
+opti82c558_set_intr(v, clink, irq)
+       pciintr_icu_handle_t v;
+       int clink, irq;
+{
+       struct opti82c558_handle *ph = v;
+       int shift;
+       pcireg_t reg;
+
+       if (VIPER_LEGAL_LINK(clink) == 0 || VIPER_LEGAL_IRQ(irq) == 0)
+               return (1);
+
+       reg = pci_conf_read(ph->ph_pc, ph->ph_tag, VIPER_CFG_PIRQ);
+       shift = VIPER_PIRQ_SELECT_SHIFT * clink;
+       reg &= ~(VIPER_PIRQ_SELECT_MASK << shift);
+       reg |= (viper_pirq_encode[irq] << shift);
+       pci_conf_write(ph->ph_pc, ph->ph_tag, VIPER_CFG_PIRQ, reg);
+
+       return (0);
+}
+
+int
+opti82c558_get_trigger(v, irq, triggerp)
+       pciintr_icu_handle_t v;
+       int irq, *triggerp;
+{
+       struct opti82c558_handle *ph = v;
+       pcireg_t reg;
+
+       if (VIPER_LEGAL_IRQ(irq) == 0) {
+               /* ISA IRQ? */
+               *triggerp = IST_EDGE;
+               return (0);
+       }
+
+       reg = pci_conf_read(ph->ph_pc, ph->ph_tag, VIPER_CFG_PIRQ);
+       if ((reg >> (VIPER_CFG_TRIGGER_SHIFT + viper_pirq_encode[irq])) & 1)
+               *triggerp = IST_LEVEL;
+       else
+               *triggerp = IST_EDGE;
+
+       return (0);
+}
+
+int
+opti82c558_set_trigger(v, irq, trigger)
+       pciintr_icu_handle_t v;
+       int irq, trigger;
+{
+       struct opti82c558_handle *ph = v;
+       int shift;
+       pcireg_t reg;
+
+       if (VIPER_LEGAL_IRQ(irq) == 0) {
+               /* ISA IRQ? */
+               return ((trigger != IST_LEVEL) ? 0 : 1);
+       }
+
+       reg = pci_conf_read(ph->ph_pc, ph->ph_tag, VIPER_CFG_PIRQ);
+       shift = (VIPER_CFG_TRIGGER_SHIFT + viper_pirq_encode[irq]);
+       if (trigger == IST_LEVEL)
+               reg |= (1 << shift);
+       else
+               reg &= ~(1 << shift);
+       pci_conf_write(ph->ph_pc, ph->ph_tag, VIPER_CFG_PIRQ, reg);
+
+       return (0);
+}
diff --git a/sys/arch/i386/pci/opti82c558reg.h b/sys/arch/i386/pci/opti82c558reg.h
new file mode 100644 (file)
index 0000000..f1279fa
--- /dev/null
@@ -0,0 +1,65 @@
+/*     $NetBSD$        */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Register definitions for the Opti 82c558 PCI-ISA bridge interrupt
+ * controller.
+ */
+
+/*
+ * PCI IRQ Select Register
+ */
+
+#define        VIPER_CFG_PIRQ          0x40    /* PCI configuration space */
+
+/*
+ * Trigger setting:
+ *
+ *     [1:7]=>5,9,10,11,12,14,15 Edge = 0 Level = 1
+ */
+#define        VIPER_CFG_TRIGGER_SHIFT 16
+
+#define        VIPER_LEGAL_LINK(link)  ((link) >= 0 && (link) <= 3)
+
+#define        VIPER_PIRQ_MASK         0xde20
+#define        VIPER_LEGAL_IRQ(irq)    ((irq) >= 0 && (irq) <= 15 &&           \
+                                ((1 << (irq)) & VIPER_PIRQ_MASK) != 0)
+
+#define        VIPER_PIRQ_NONE         0
+#define        VIPER_PIRQ_5            1
+#define        VIPER_PIRQ_9            2
+#define        VIPER_PIRQ_10           3
+#define        VIPER_PIRQ_11           4
+#define        VIPER_PIRQ_12           5
+#define        VIPER_PIRQ_14           6
+#define        VIPER_PIRQ_15           7
+
+#define        VIPER_PIRQ_SELECT_MASK  0x07
+#define        VIPER_PIRQ_SELECT_SHIFT 3
+
+#define        VIPER_PIRQ(reg, x)      (((reg) >> ((x) * VIPER_PIRQ_SELECT_SHIFT)) \
+                                & VIPER_PIRQ_SELECT_MASK)
diff --git a/sys/arch/i386/pci/opti82c700.c b/sys/arch/i386/pci/opti82c700.c
new file mode 100644 (file)
index 0000000..423796b
--- /dev/null
@@ -0,0 +1,290 @@
+/*     $NetBSD$        */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Support for the Opti 82c700 PCI-ISA bridge interrupt controller.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+
+#include <i386/pci/pci_intr_fixup.h>
+#include <i386/pci/opti82c700reg.h>
+
+int    opti82c700_getclink __P((pciintr_icu_handle_t, int, int *));
+int    opti82c700_get_intr __P((pciintr_icu_handle_t, int, int *));
+int    opti82c700_set_intr __P((pciintr_icu_handle_t, int, int));
+int    opti82c700_get_trigger __P((pciintr_icu_handle_t, int, int *));
+int    opti82c700_set_trigger __P((pciintr_icu_handle_t, int, int));
+
+const struct pciintr_icu opti82c700_pci_icu = {
+       opti82c700_getclink,
+       opti82c700_get_intr,
+       opti82c700_set_intr,
+       opti82c700_get_trigger,
+       opti82c700_set_trigger,
+};
+
+struct opti82c700_handle {
+       pci_chipset_tag_t ph_pc;
+       pcitag_t ph_tag;
+};
+
+int    opti82c700_addr __P((int, int *, int *));
+
+int
+opti82c700_init(pc, iot, tag, ptagp, phandp)
+       pci_chipset_tag_t pc;
+       bus_space_tag_t iot;
+       pcitag_t tag;
+       pciintr_icu_tag_t *ptagp;
+       pciintr_icu_handle_t *phandp;
+{
+       struct opti82c700_handle *ph;
+
+       ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT);
+       if (ph == NULL)
+               return (1);
+
+       ph->ph_pc = pc;
+       ph->ph_tag = tag;
+
+       *ptagp = &opti82c700_pci_icu;
+       *phandp = ph;
+       return (0);
+}
+
+int
+opti82c700_addr(link, addrofs, ofs)
+       int link, *addrofs, *ofs;
+{
+       int regofs, src;
+
+       regofs = FIRESTAR_PIR_REGOFS(link);
+       src = FIRESTAR_PIR_SELECTSRC(link);
+
+       switch (src) {
+       case FIRESTAR_PIR_SELECT_NONE:
+               return (1);
+
+       case FIRESTAR_PIR_SELECT_IRQ:
+               if (regofs < 0 || regofs > 7)
+                       return (1);
+               *addrofs = FIRESTAR_CFG_INTR_IRQ + (regofs >> 2);
+               *ofs = (regofs & 3) << 3;
+               break;
+
+       case FIRESTAR_PIR_SELECT_PIRQ:
+       case FIRESTAR_PIR_SELECT_BRIDGE:
+               if (regofs < 0 || regofs > 3)
+                       return (1);
+               *addrofs = FIRESTAR_CFG_INTR_PIRQ;
+               *ofs = regofs << 2;
+               break;
+
+       default:
+               return (1);
+       }
+
+       return (0);
+}
+
+int
+opti82c700_getclink(v, link, clinkp)
+       pciintr_icu_handle_t v;
+       int link, *clinkp;
+{
+
+       if (FIRESTAR_LEGAL_LINK(link)) {
+               *clinkp = link;
+               return (0);
+       }
+
+       return (1);
+}
+
+int
+opti82c700_get_intr(v, clink, irqp)
+       pciintr_icu_handle_t v;
+       int clink, *irqp;
+{
+       struct opti82c700_handle *ph = v;
+       pcireg_t reg;
+       int val, addrofs, ofs;
+
+       if (FIRESTAR_LEGAL_LINK(clink) == 0)
+               return (1);
+
+       if (opti82c700_addr(clink, &addrofs, &ofs))
+               return (1);
+
+       reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
+       val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
+       *irqp = (val == FIRESTAR_PIRQ_NONE) ? 0xff : val;
+
+       return (0);
+}
+
+int
+opti82c700_set_intr(v, clink, irq)
+       pciintr_icu_handle_t v;
+       int clink, irq;
+{
+       struct opti82c700_handle *ph = v;
+       int addrofs, ofs;
+       pcireg_t reg;
+
+       if (FIRESTAR_LEGAL_LINK(clink) == 0 || FIRESTAR_LEGAL_IRQ(irq) == 0)
+               return (1);
+
+       if (opti82c700_addr(clink, &addrofs, &ofs))
+               return (1);
+
+       reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
+       reg &= ~(FIRESTAR_CFG_PIRQ_MASK << ofs);
+       reg |= (irq << ofs);
+       pci_conf_write(ph->ph_pc, ph->ph_tag, addrofs, reg);
+
+       return (0);
+}
+
+int
+opti82c700_get_trigger(v, irq, triggerp)
+       pciintr_icu_handle_t v;
+       int irq, *triggerp;
+{
+       struct opti82c700_handle *ph = v;
+       int i, val, addrofs, ofs;
+       pcireg_t reg;
+
+       if (FIRESTAR_LEGAL_IRQ(irq) == 0) {
+               /* ISA IRQ? */
+               *triggerp = IST_EDGE;
+               return (0);
+       }
+
+       /*
+        * Search PCIDV1 registers.
+        */
+       for (i = 0; i < 8; i++) {
+               opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_IRQ,
+                   i), &addrofs, &ofs);
+               reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
+               val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
+               if (val != irq)
+                       continue;
+               val = ((reg >> ofs) >> FIRESTAR_TRIGGER_SHIFT) &
+                   FIRESTAR_TRIGGER_MASK;
+               *triggerp = val ? IST_LEVEL : IST_EDGE;
+               return (0);
+       }
+
+       return (1);
+}
+
+int
+opti82c700_set_trigger(v, irq, trigger)
+       pciintr_icu_handle_t v;
+       int irq, trigger;
+{
+       struct opti82c700_handle *ph = v;
+       int i, val, addrofs, ofs;
+       pcireg_t reg;
+
+       if (FIRESTAR_LEGAL_IRQ(irq) == 0) {
+               /* ISA IRQ? */
+               return ((trigger != IST_LEVEL) ? 0 : 1);
+       }
+
+       /*
+        * Search PCIDV1 registers.
+        */
+       for (i = 0; i < 8; i++) {
+               opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_IRQ,
+                   i), &addrofs, &ofs);
+               reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
+               val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
+               if (val != irq)
+                       continue;
+               if (trigger == IST_LEVEL)
+                       reg |= (FIRESTAR_TRIGGER_MASK <<
+                           (FIRESTAR_TRIGGER_SHIFT + ofs));
+               else
+                       reg &= ~(FIRESTAR_TRIGGER_MASK <<
+                           (FIRESTAR_TRIGGER_SHIFT + ofs));
+               pci_conf_write(ph->ph_pc, ph->ph_tag, addrofs, reg);
+               return (0);
+       }
+
+       return (1);
+}
diff --git a/sys/arch/i386/pci/opti82c700reg.h b/sys/arch/i386/pci/opti82c700reg.h
new file mode 100644 (file)
index 0000000..21d0b3a
--- /dev/null
@@ -0,0 +1,71 @@
+/*     $NetBSD$        */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Register definitions for the Opti 82c700 PCI-ISA bridge interrupt
+ * controller.
+ */
+
+#define        FIRESTAR_CFG_INTR_IRQ   0xb0    /* PCI configuration space */
+#define        FIRESTAR_CFG_INTR_PIRQ  0xb8    /* PCI configuration space */
+
+#define        FIRESTAR_PIRQ_NONE      0
+#define        FIRESTAR_PIRQ_MIN       FIRESTAR_CFG_INTR_IRQ
+#define        FIRESTAR_PIRQ_MAX       (FIRESTAR_CFG_INTR_PIRQ + 1)
+#define        FIRESTAR_LEGAL_LINK(link) ((link) >= FIRESTAR_PIRQ_MIN &&       \
+                                  (link) <= FIRESTAR_PIRQ_MAX)
+
+#define        FIRESTAR_PIRQ_MASK      0xdffa
+#define        FIRESTAR_LEGAL_IRQ(irq) ((irq) >= 0 && (irq) <= 15 &&           \
+                                ((1 << (irq)) & FIRESTAR_PIRQ_MASK) != 0)
+
+#define        FIRESTAR_CFG_PIRQ_MASK  0x0f
+
+#define        FIRESTAR_TRIGGER_MASK   0x01
+#define        FIRESTAR_TRIGGER_SHIFT  4
+
+/*
+ * Opti's suggested Link values.
+ */
+#define        FIRESTAR_PIR_REGOFS_MASK        0x07
+#define        FIRESTAR_PIR_REGOFS_SHIFT       4
+#define        FIRESTAR_PIR_REGOFS(link)                                       \
+       (((link) >> FIRESTAR_PIR_REGOFS_SHIFT) & FIRESTAR_PIR_REGOFS_MASK)
+
+#define        FIRESTAR_PIR_SELECTSRC_MASK     0x07
+#define        FIRESTAR_PIR_SELECTSRC_SHIFT    0
+#define        FIRESTAR_PIR_SELECTSRC(link)                                    \
+       (((link) >> FIRESTAR_PIR_SELECTSRC_SHIFT) & FIRESTAR_PIR_SELECTSRC_MASK)
+
+#define        FIRESTAR_PIR_SELECT_NONE        0
+#define        FIRESTAR_PIR_SELECT_IRQ         1
+#define        FIRESTAR_PIR_SELECT_PIRQ        2
+#define        FIRESTAR_PIR_SELECT_BRIDGE      3
+
+#define        FIRESTAR_PIR_MAKELINK(src, ofs)                                 \
+       (((src) << FIRESTAR_PIR_SELECTSRC_SHIFT) |                      \
+        ((ofs) << FIRESTAR_PIR_REGOFS_SHIFT))
diff --git a/sys/arch/i386/pci/pci_bus_fixup.c b/sys/arch/i386/pci/pci_bus_fixup.c
new file mode 100644 (file)
index 0000000..57b7d0c
--- /dev/null
@@ -0,0 +1,135 @@
+/*     $NetBSD$        */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * PCI bus renumbering support.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#include <machine/bus.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+#include <dev/pci/ppbreg.h>
+
+#include <i386/pci/pci_bus_fixup.h>
+#include <i386/pci/pcibios.h>
+
+int
+pci_bus_fixup(pc, bus)
+       pci_chipset_tag_t pc;
+       int bus;
+{
+       static int bus_total;
+       static int bridge_cnt;
+       int device, maxdevs, function, nfuncs, bridge, bus_max, bus_sub;
+       const struct pci_quirkdata *qd;
+       pcireg_t reg;
+       pcitag_t tag;
+
+       bus_max = bus;
+       bus_sub = 0;
+
+       if (++bus_total > 256)
+               panic("pci_bus_fixup: more than 256 PCI busses?");
+
+       maxdevs = pci_bus_maxdevs(pc, bus);
+
+       for (device = 0; device < maxdevs; device++) {
+               tag = pci_make_tag(pc, bus, device, 0);
+               reg = pci_conf_read(pc, tag, PCI_ID_REG);
+
+               /* Invalid vendor ID value? */
+               if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID)
+                       continue;
+               /* XXX Not invalid, but we've done this ~forever. */
+               if (PCI_VENDOR(reg) == 0)
+                       continue;
+
+               qd = pci_lookup_quirkdata(PCI_VENDOR(reg), PCI_PRODUCT(reg));
+
+               reg = pci_conf_read(pc, tag, PCI_BHLC_REG);
+               if (PCI_HDRTYPE_MULTIFN(reg) ||
+                   (qd != NULL &&
+                    (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
+                       nfuncs = 8;
+               else
+                       nfuncs = 1;
+
+               for (function = 0; function < nfuncs; function++) {
+                       tag = pci_make_tag(pc, bus, device, function);
+                       reg = pci_conf_read(pc, tag, PCI_ID_REG);
+
+                       /* Invalid vendor ID value? */
+                       if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID)
+                               continue;
+                       /* XXX Not invalid, but we've done this ~forever. */
+                       if (PCI_VENDOR(reg) == 0)
+                               continue;
+
+                       reg = pci_conf_read(pc, tag, PCI_CLASS_REG);
+                       if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE &&
+                           (PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI ||
+                            PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_CARDBUS)) {
+                               /* Assign the bridge #. */
+                               bridge = bridge_cnt++;
+
+                               /* Assign the bridge's secondary bus #. */
+                               bus_max++;
+
+                               reg = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
+                               reg &= 0xff000000;
+                               reg |= bus | (bus_max << 8) | (0xff << 16);
+                               pci_conf_write(pc, tag, PPB_REG_BUSINFO, reg);
+
+                               /* Scan subordinate bus. */
+                               bus_sub = pci_bus_fixup(pc, bus_max);
+
+                               /* Configure the bridge. */
+                               reg &= 0xff000000;
+                               reg |= bus | (bus_max << 8) | (bus_sub << 16);
+                               pci_conf_write(pc, tag, PPB_REG_BUSINFO, reg);
+
+#ifdef PCIBIOSVERBOSE
+                               printf("PCI bridge %d: primary %d, "
+                                   "secondary %d, subordinate %d\n",
+                                   bridge, bus, bus_max, bus_sub);
+#endif
+
+                               /* Next bridge's secondary bus #. */
+                               bus_max = (bus_sub > bus_max) ?
+                                   bus_sub : bus_max;
+                       }
+               }
+       }
+
+       return (bus_max);       /* last # of subordinate bus */
+}
diff --git a/sys/arch/i386/pci/pci_bus_fixup.h b/sys/arch/i386/pci/pci_bus_fixup.h
new file mode 100644 (file)
index 0000000..d93a3ac
--- /dev/null
@@ -0,0 +1,28 @@
+/*     $NetBSD$        */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+int    pci_bus_fixup __P((pci_chipset_tag_t, int));
diff --git a/sys/arch/i386/pci/pci_intr_fixup.c b/sys/arch/i386/pci/pci_intr_fixup.c
new file mode 100644 (file)
index 0000000..22f354f
--- /dev/null
@@ -0,0 +1,696 @@
+/*     $NetBSD: pci_intr_fixup.c,v 1.3 1999/12/13 15:42:05 uch Exp $   */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * PCI Interrupt Router support.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <i386/isa/icu.h>
+#include <i386/pci/pci_intr_fixup.h>
+#include <i386/pci/pcibios.h>
+
+struct pciintr_link_map {
+       int link;
+       int clink;
+       int irq;
+       u_int16_t bitmap;
+       int fixup_stage;
+       int old_irq;
+       SIMPLEQ_ENTRY(pciintr_link_map) list;
+};
+
+pciintr_icu_tag_t pciintr_icu_tag;
+pciintr_icu_handle_t pciintr_icu_handle;
+
+struct pciintr_link_map *pciintr_link_lookup_pin
+       __P((struct pcibios_intr_routing *, int));
+struct pciintr_link_map *pciintr_link_lookup_link __P((int));
+struct pciintr_link_map *pciintr_link_alloc __P((struct pcibios_intr_routing *,
+       int));
+struct pcibios_intr_routing *pciintr_pir_lookup __P((int, int));
+int    pciintr_link_init __P((void));
+int    pciintr_link_fixup __P((void));
+int    pciintr_link_route __P((u_int16_t *));
+int    pciintr_irq_release __P((u_int16_t *));
+int    pciintr_header_fixup __P((pci_chipset_tag_t));
+
+SIMPLEQ_HEAD(, pciintr_link_map) pciintr_link_map_list;
+
+const struct pciintr_icu_table {
+       pci_vendor_id_t piit_vendor;
+       pci_product_id_t piit_product;
+       int (*piit_init) __P((pci_chipset_tag_t,
+               bus_space_tag_t, pcitag_t, pciintr_icu_tag_t *,
+               pciintr_icu_handle_t *));
+} pciintr_icu_table[] = {
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82371MX,
+         piix_init },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82371AB_ISA,
+         piix_init },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82371FB_ISA,
+         piix_init },
+       { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82371SB_ISA,
+         piix_init },
+
+       { PCI_VENDOR_OPTI,      PCI_PRODUCT_OPTI_82C558,
+         opti82c558_init },
+       { PCI_VENDOR_OPTI,      PCI_PRODUCT_OPTI_82C700,
+         opti82c700_init },
+
+       { PCI_VENDOR_VIATECH,   PCI_PRODUCT_VIATECH_VT82C586_ISA,
+         via82c586_init, },
+
+       { PCI_VENDOR_SIS,       PCI_PRODUCT_SIS_85C503,
+         sis85c503_init },
+
+       { 0,                    0,
+         NULL },
+};
+
+const struct pciintr_icu_table *pciintr_icu_lookup __P((pcireg_t));
+
+const struct pciintr_icu_table *
+pciintr_icu_lookup(id)
+       pcireg_t id;
+{
+       const struct pciintr_icu_table *piit;
+
+       for (piit = pciintr_icu_table;
+            piit->piit_init != NULL;
+            piit++) {
+               if (PCI_VENDOR(id) == piit->piit_vendor &&
+                   PCI_PRODUCT(id) == piit->piit_product)
+                       return (piit);
+       }
+
+       return (NULL);
+}
+
+struct pciintr_link_map *
+pciintr_link_lookup_pin(pir, pin)
+       struct pcibios_intr_routing *pir;
+       int pin;
+{
+
+       return (pciintr_link_lookup_link(pir->linkmap[pin].link));
+}
+
+struct pciintr_link_map *
+pciintr_link_lookup_link(link)
+       int link;
+{
+       struct pciintr_link_map *l;
+
+       for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
+            l = SIMPLEQ_NEXT(l, list)) {
+               if (l->link == link)
+                       return (l);
+       }
+
+       return (NULL);
+}
+
+struct pciintr_link_map *
+pciintr_link_alloc(pir, pin)
+       struct pcibios_intr_routing *pir;
+       int pin;
+{
+       struct pciintr_link_map *l, *lstart;
+
+       l = malloc(sizeof(*l), M_DEVBUF, M_NOWAIT);
+       if (l == NULL)
+               panic("pciintr_link_alloc");
+
+       memset(l, 0, sizeof(*l));
+
+       l->link = pir->linkmap[pin].link;
+       l->bitmap = pir->linkmap[pin].bitmap;
+
+       lstart = SIMPLEQ_FIRST(&pciintr_link_map_list);
+       if (lstart == NULL || lstart->link < l->link)
+               SIMPLEQ_INSERT_TAIL(&pciintr_link_map_list, l, list);
+       else
+               SIMPLEQ_INSERT_HEAD(&pciintr_link_map_list, l, list);
+
+       return (l);
+}
+
+struct pcibios_intr_routing *
+pciintr_pir_lookup(bus, device)
+       int bus, device;
+{
+       struct pcibios_intr_routing *pir;
+       int entry;
+
+       if (pcibios_pir_table == NULL)
+               return (NULL);
+
+       for (entry = 0; entry < pcibios_pir_table_nentries; entry++) {
+               pir = &pcibios_pir_table[entry];
+               if (pir->bus == bus && ((pir->device >> 3) & 0x1f) == device)
+                       return (pir);
+       }
+
+       return (NULL);
+}
+
+int
+pciintr_link_init()
+{
+       int entry, pin, error, link, clink;
+       struct pcibios_intr_routing *pir;
+       struct pciintr_link_map *l;
+
+       if (pcibios_pir_table == NULL) {
+               /* No PIR table; can't do anything. */
+               printf("pciintr_link_init: no PIR table\n");
+               return (1);
+       }
+
+       error = 0;
+       SIMPLEQ_INIT(&pciintr_link_map_list);
+
+       for (entry = 0; entry < pcibios_pir_table_nentries; entry++) {
+               pir = &pcibios_pir_table[entry];
+               for (pin = 0; pin < 4; pin++) {
+                       link = pir->linkmap[pin].link;
+                       if (link == 0) {
+                               /* No connection for this pin. */
+                               continue;
+                       }
+
+                       /*
+                        * Check the link value by asking the ICU for
+                        * the canonical link value.
+                        */
+                       if (pciintr_icu_getclink(pciintr_icu_tag,
+                           pciintr_icu_handle, link, &clink) != 0) {
+                               /*
+                                * Table entry is bogus.  Just ignore it.
+                                */
+#ifdef PCIINTR_DEBUG
+                               printf("pciintr_link_init: bad table entry: "
+                                   "bus %d device %d link 0x%02x\n",
+                                   pir->bus, (pir->device >> 3 & 0x1f), link);
+#endif
+                               continue;
+                       }
+
+                       /*
+                        * Multiple devices may be wired to the same
+                        * interrupt; check to see if we've seen this
+                        * one already.  If not, allocate a new link
+                        * map entry and stuff it in the map.
+                        */
+                       l = pciintr_link_lookup_pin(pir, pin);
+                       if (l == NULL)
+                               (void) pciintr_link_alloc(pir, pin);
+               }
+       }
+
+       return (error);
+}
+
+int
+pciintr_link_fixup()
+{
+       struct pciintr_link_map *l;
+       u_int16_t pciirq, bitmap;
+       int i, j, cnt, irq;
+
+       /*
+        * First stage: Attempt to connect PIRQs which aren't
+        * yet connected.
+        */
+       pciirq = 0;
+
+       for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
+            l = SIMPLEQ_NEXT(l, list)) {
+               /*
+                * Get the canonical link value for this entry.
+                */
+               if (pciintr_icu_getclink(pciintr_icu_tag, pciintr_icu_handle,
+                   l->link, &l->clink) != 0) {
+                       /*
+                        * ICU doesn't understand this link value.
+                        */
+#ifdef PCIINTR_DEBUG
+                       printf("pciintr_link_fixup: link 0x%02x invalid\n",
+                           l->link);
+#endif
+                       l->clink = -1;
+                       continue;
+               }
+
+               /*
+                * Determine if this PIRQ is mapped to an IRQ.
+                */
+               if (pciintr_icu_get_intr(pciintr_icu_tag, pciintr_icu_handle,
+                   l->clink, &irq) != 0) {
+                       /*
+                        * ICU doesn't understand this PIRQ value.
+                        */
+                       l->clink = -1;
+#ifdef PCIINTR_DEBUG
+                       printf("pciintr_link_fixup: PIRQ %d invalid\n",
+                           l->clink);
+#endif
+                       continue;
+               }
+
+               if (irq == 0xff) {
+                       /*
+                        * Interrupt isn't connected.  Attempt to assign
+                        * it to an IRQ.
+                        */
+#ifdef PCIINTR_DEBUG
+                       printf("pciintr_link_fixup: PIRQ %d not connected",
+                           l->clink);
+#endif
+                       bitmap = l->bitmap;
+                       for (i = 0, j = 0xff, cnt = 0; i < 16; i++)
+                               if (bitmap & (1 << i))
+                                       j = i, cnt++;
+                       /*
+                        * Just do the easy case now; we'll defer the
+                        * harder ones to Stage 2.
+                        */
+                       if (cnt == 1) {
+                               l->irq = j;
+                               l->old_irq = irq;
+                               l->fixup_stage = 1;
+                               pciirq |= 1 << j;
+#ifdef PCIINTR_DEBUG
+                               printf(", assigning IRQ %d", l->irq);
+#endif
+                       }
+#ifdef PCIINTR_DEBUG
+                       printf("\n");
+#endif
+               } else {
+                       /*
+                        * Interrupt is already connected.  Don't do
+                        * anything to it.
+                        */
+                       l->irq = irq;
+                       pciirq |= 1 << irq;
+#ifdef PCIINTR_DEBUG
+                       printf("pciintr_link_fixup: PIRQ %d already connected "
+                           "to IRQ %d\n", l->clink, l->irq);
+#endif
+               }
+       }
+
+#ifdef PCIBIOS_IRQS
+       /* In case the user supplied a mask for the PCI irqs we use it. */
+       pciirq = PCIBIOS_IRQS;
+#endif
+
+       /*
+        * Stage 2: Attempt to connect PIRQs which we didn't
+        * connect in Stage 1.
+        */
+       for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
+            l = SIMPLEQ_NEXT(l, list)) {
+               if (l->irq == 0) {
+                       bitmap = l->bitmap;
+                       for (i = 0; i < 16; i++) {
+                               if ((pciirq & (1 << i)) != 0 &&
+                                   (bitmap & (1 << i)) != 0) {
+                                       /*
+                                        * This IRQ is a valid PCI
+                                        * IRQ already connected to
+                                        * another PIRQ, and also an
+                                        * IRQ our PIRQ can use; connect
+                                        * it up!
+                                        */
+                                       l->irq = i;
+                                       l->old_irq = 0xff;
+                                       l->fixup_stage = 2;
+#ifdef PCIINTR_DEBUG
+                                       printf("pciintr_link_fixup: assigning "
+                                           "IRQ %d to PIRQ %d\n", l->irq,
+                                           l->clink);
+#endif
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       /*
+        * Stage 3: Allow the user to specify interrupt routing
+        * information, overriding what we've done above.
+        */
+       /* XXX Not implemented. */
+
+       return (0);
+}
+
+int
+pciintr_link_route(pciirq)
+       u_int16_t *pciirq;
+{
+       struct pciintr_link_map *l;
+       int rv = 0;
+
+       *pciirq = 0;
+
+       for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
+            l = SIMPLEQ_NEXT(l, list)) {
+               if (pciintr_icu_set_intr(pciintr_icu_tag, pciintr_icu_handle,
+                                        l->clink, l->irq) != 0 ||
+                   pciintr_icu_set_trigger(pciintr_icu_tag, pciintr_icu_handle,
+                                           l->irq, IST_LEVEL) != 0) {
+                       printf("pciintr_link_route: route of PIRQ %d -> IRQ %d"
+                           " failed\n", l->clink, l->irq);
+                       rv = 1;
+               } else {
+                       /*
+                        * Succssfully routed interrupt.  Mark this as
+                        * a PCI interrupt.
+                        */
+                       *pciirq |= (1 << l->irq);
+               }
+       }
+
+       return (rv);
+}
+
+int
+pciintr_irq_release(pciirq)
+       u_int16_t *pciirq;
+{
+       int i;
+
+       for (i = 0; i < 16; i++) {
+               if ((*pciirq & (1 << i)) == 0)
+                       (void) pciintr_icu_set_trigger(pciintr_icu_tag,
+                           pciintr_icu_handle, i, IST_EDGE);
+       }
+
+       return (0);
+}
+
+int
+pciintr_header_fixup(pc)
+       pci_chipset_tag_t pc;
+{
+       const struct pci_quirkdata *qd;
+       struct pcibios_intr_routing *pir;
+       struct pciintr_link_map *l;
+       int pin, bus, device, function, maxdevs, nfuncs, irq, link;
+       pcireg_t id, bhlcr, intr;
+       pcitag_t tag;
+
+#ifdef PCIBIOSVERBOSE
+       printf("--------------------------------------------\n");
+       printf("  device vendor product pin PIRQ   IRQ stage\n");
+       printf("--------------------------------------------\n");
+#endif
+
+       for (bus = 0; bus <= pcibios_max_bus; bus++) {
+               maxdevs = pci_bus_maxdevs(pc, bus);
+               for (device = 0; device < maxdevs; device++) {
+                       tag = pci_make_tag(pc, bus, device, 0);
+                       id = pci_conf_read(pc, tag, PCI_ID_REG);
+
+                       /* Invalid vendor ID value? */
+                       if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
+                               continue;
+                       /* XXX Not invalid, but we've done this ~forever. */
+                       if (PCI_VENDOR(id) == 0)
+                               continue;
+
+                       qd = pci_lookup_quirkdata(PCI_VENDOR(id),
+                           PCI_PRODUCT(id));
+
+                       bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
+                       if (PCI_HDRTYPE_MULTIFN(bhlcr) ||
+                           (qd != NULL &&
+                            (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
+                               nfuncs = 8;
+                       else
+                               nfuncs = 1;
+
+                       for (function = 0; function < nfuncs; function++) {
+                               tag = pci_make_tag(pc, bus, device, function);
+                               id = pci_conf_read(pc, tag, PCI_ID_REG);
+                               intr = pci_conf_read(pc, tag,
+                                   PCI_INTERRUPT_REG);
+
+                               /* Invalid vendor ID value? */
+                               if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
+                                       continue;
+                               /*
+                                * XXX Not invalid, but we've done this
+                                * ~forever.
+                                */
+                               if (PCI_VENDOR(id) == 0)
+                                       continue;
+
+                               pin = PCI_INTERRUPT_PIN(intr);
+                               irq = PCI_INTERRUPT_LINE(intr);
+
+                               if (pin == 0) {
+                                       /*
+                                        * No interrupt used.
+                                        */
+                                       continue;
+                               }
+
+                               pir = pciintr_pir_lookup(bus, device);
+                               if (pir == NULL ||
+                                   (link = pir->linkmap[pin - 1].link) == 0) {
+                                       /*
+                                        * Interrupt not connected; no
+                                        * need to change.
+                                        */
+                                       continue;
+                               }
+
+                               l = pciintr_link_lookup_link(link);
+                               if (l == NULL) {
+                                       /*
+                                        * No link map entry?!
+                                        */
+                                       printf("pciintr_header_fixup: no entry "
+                                           "for link 0x%02x (%d:%d:%d:%c)\n",
+                                           link, bus, device, function,
+                                           '@' + pin);
+                                       continue;
+                               }
+
+                               /*
+                                * IRQs 14 and 15 are reserved for
+                                * PCI IDE interrupts; don't muck
+                                * with them.
+                                */
+                               if (irq == 14 || irq == 15)
+                                       continue;
+
+#ifdef PCIBIOSVERBOSE
+                               printf("%03d:%02d:%d 0x%04x 0x%04x  %c   "
+                                   "0x%02x   %02d  %d\n",
+                                   bus, device, function,
+                                   PCI_VENDOR(id), PCI_PRODUCT(id),
+                                   '@' + pin, l->clink, l->irq,
+                                   l->fixup_stage);
+#endif
+
+                               intr &= ~(PCI_INTERRUPT_LINE_MASK <<
+                                   PCI_INTERRUPT_LINE_SHIFT);
+                               intr |= (l->irq << PCI_INTERRUPT_LINE_SHIFT);
+                               pci_conf_write(pc, tag, PCI_INTERRUPT_REG,
+                                   intr);
+                       }
+               }
+       }
+
+#ifdef PCIBIOSVERBOSE
+       printf("--------------------------------------------\n");
+#endif
+
+       return (0);
+}
+
+int
+pci_intr_fixup(pc, iot, pciirq)
+       pci_chipset_tag_t pc;
+       bus_space_tag_t iot;
+       u_int16_t *pciirq;
+{
+       const struct pciintr_icu_table *piit = NULL;
+       pcitag_t icutag;
+       pcireg_t icuid;
+
+       /*
+        * Attempt to initialize our PCI interrupt router.  If
+        * the PIR Table is present in ROM, use the location
+        * specified by the PIR Table, and use the compat ID,
+        * if present.  Otherwise, we have to look for the router
+        * ourselves (the PCI-ISA bridge).
+        */
+       if (pcibios_pir_header.signature != 0) {
+               icutag = pci_make_tag(pc, pcibios_pir_header.router_bus,
+                   (pcibios_pir_header.router_devfunc >> 3) & 0x1f,
+                   pcibios_pir_header.router_devfunc & 7);
+               icuid = pcibios_pir_header.compat_router;
+               if (icuid == 0 ||
+                   (piit = pciintr_icu_lookup(icuid)) == NULL) {
+                       /*
+                        * No compat ID, or don't know the compat ID?  Read
+                        * it from the configuration header.
+                        */
+                       icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
+               }
+               if (piit == NULL)
+                       piit = pciintr_icu_lookup(icuid);
+       } else {
+               int device, maxdevs = pci_bus_maxdevs(pc, 0);
+
+               /*
+                * Search configuration space for a known interrupt
+                * router.
+                */
+               for (device = 0; device < maxdevs; device++) {
+                       icutag = pci_make_tag(pc, 0, device, 0);
+                       icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
+
+                       /* Invalid vendor ID value? */
+                       if (PCI_VENDOR(icuid) == PCI_VENDOR_INVALID)
+                               continue;
+                       /* XXX Not invalid, but we've done this ~forever. */
+                       if (PCI_VENDOR(icuid) == 0)
+                               continue;
+
+                       piit = pciintr_icu_lookup(icuid);
+                       if (piit != NULL)
+                               break;
+               }
+       }
+
+       if (piit == NULL) {
+               printf("pci_intr_fixup: no compatible PCI ICU found\n");
+               return (-1);            /* non-fatal */
+       }
+
+       /*
+        * Initialize the PCI ICU.
+        */
+       if ((*piit->piit_init)(pc, iot, icutag, &pciintr_icu_tag,
+           &pciintr_icu_handle) != 0)
+               return (-1);            /* non-fatal */
+
+       /*
+        * Initialize the PCI interrupt link map.
+        */
+       if (pciintr_link_init())
+               return (-1);            /* non-fatal */
+
+       /*
+        * Fix up the link->IRQ mappings.
+        */
+       if (pciintr_link_fixup() != 0)
+               return (-1);            /* non-fatal */
+
+       /*
+        * Now actually program the PCI ICU with the new
+        * routing information.
+        */
+       if (pciintr_link_route(pciirq) != 0)
+               return (1);             /* fatal */
+
+       /*
+        * Now that we've routed all of the PIRQs, rewrite the PCI
+        * configuration headers to reflect the new mapping.
+        */
+       if (pciintr_header_fixup(pc) != 0)
+               return (1);             /* fatal */
+
+       /*
+        * Free any unused PCI IRQs for ISA devices.
+        */
+       if (pciintr_irq_release(pciirq) != 0)
+               return (-1);            /* non-fatal */
+
+       /*
+        * All done!
+        */
+       return (0);                     /* success! */
+}
diff --git a/sys/arch/i386/pci/pci_intr_fixup.h b/sys/arch/i386/pci/pci_intr_fixup.h
new file mode 100644 (file)
index 0000000..feebdfb
--- /dev/null
@@ -0,0 +1,65 @@
+/*     $NetBSD$        */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+typedef void *pciintr_icu_handle_t;
+
+struct pciintr_icu {
+       int     (*pi_getclink) __P((pciintr_icu_handle_t, int, int *));
+       int     (*pi_get_intr) __P((pciintr_icu_handle_t, int, int *));
+       int     (*pi_set_intr) __P((pciintr_icu_handle_t, int, int));
+       int     (*pi_get_trigger) __P((pciintr_icu_handle_t, int, int *));
+       int     (*pi_set_trigger) __P((pciintr_icu_handle_t, int, int));
+};
+
+typedef const struct pciintr_icu *pciintr_icu_tag_t;
+
+#define        pciintr_icu_getclink(t, h, link, pirqp)                         \
+       (*(t)->pi_getclink)((h), (link), (pirqp))
+#define        pciintr_icu_get_intr(t, h, pirq, irqp)                          \
+       (*(t)->pi_get_intr)((h), (pirq), (irqp))
+#define        pciintr_icu_set_intr(t, h, pirq, irq)                           \
+       (*(t)->pi_set_intr)((h), (pirq), (irq))
+#define        pciintr_icu_get_trigger(t, h, irq, triggerp)                    \
+       (*(t)->pi_get_trigger)((h), (irq), (triggerp))
+#define        pciintr_icu_set_trigger(t, h, irq, trigger)                     \
+       (*(t)->pi_set_trigger)((h), (irq), (trigger))
+
+int pci_intr_fixup __P((pci_chipset_tag_t, bus_space_tag_t, u_int16_t *));
+
+/*
+ * Init functions for our known PCI ICUs.
+ */
+int    piix_init __P((pci_chipset_tag_t, bus_space_tag_t, pcitag_t,
+           pciintr_icu_tag_t *, pciintr_icu_handle_t *));
+int    opti82c558_init __P((pci_chipset_tag_t, bus_space_tag_t, pcitag_t,
+           pciintr_icu_tag_t *, pciintr_icu_handle_t *));
+int    opti82c700_init __P((pci_chipset_tag_t, bus_space_tag_t, pcitag_t,
+           pciintr_icu_tag_t *, pciintr_icu_handle_t *));
+int    via82c586_init __P((pci_chipset_tag_t, bus_space_tag_t, pcitag_t,
+           pciintr_icu_tag_t *, pciintr_icu_handle_t *));
+int    sis85c503_init __P((pci_chipset_tag_t, bus_space_tag_t, pcitag_t,
+           pciintr_icu_tag_t *, pciintr_icu_handle_t *));
index ac3f00f..3004c1e 100644 (file)
@@ -80,7 +80,7 @@ pcibmatch(parent, match, aux)
                switch (PCI_PRODUCT(pa->pa_id)) {
                case PCI_PRODUCT_INTEL_SIO:
                case PCI_PRODUCT_INTEL_82371MX:
-               case PCI_PRODUCT_INTEL_82371AB:
+               case PCI_PRODUCT_INTEL_82371AB_ISA:
                        /* The above bridges mis-identify themselves */
                        return (1);
                }
diff --git a/sys/arch/i386/pci/pcibios.c b/sys/arch/i386/pci/pcibios.c
new file mode 100644 (file)
index 0000000..70e6b6a
--- /dev/null
@@ -0,0 +1,475 @@
+/*     $NetBSD: pcibios.c,v 1.1 1999/11/17 01:16:37 thorpej Exp $      */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Interface to the PCI BIOS and PCI Interrupt Routing table.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <dev/isa/isareg.h>
+#include <i386/isa/isa_machdep.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <i386/pci/pcibios.h>
+#ifdef PCIBIOS_INTR_FIXUP
+#include <i386/pci/pci_intr_fixup.h>
+#endif
+#ifdef PCIBIOS_BUS_FIXUP
+#include <i386/pci/pci_bus_fixup.h>
+#endif
+
+#ifdef __NetBSD__
+#include <machine/bios32.h>
+#elif __OpenBSD__
+#include <machine/biosvar.h>
+#endif
+
+int pcibios_present;
+
+struct pcibios_pir_header pcibios_pir_header;
+struct pcibios_intr_routing *pcibios_pir_table;
+int pcibios_pir_table_nentries;
+int pcibios_max_bus;
+
+struct bios32_entry pcibios_entry;
+
+void   pcibios_pir_init __P((void));
+
+int    pcibios_get_status __P((u_int32_t *, u_int32_t *, u_int32_t *,
+           u_int32_t *, u_int32_t *, u_int32_t *, u_int32_t *));
+int    pcibios_get_intr_routing __P((struct pcibios_intr_routing *,
+           int *, u_int16_t *));
+
+int    pcibios_return_code __P((u_int16_t, const char *));
+
+void   pcibios_print_exclirq __P((void));
+#ifdef PCIINTR_DEBUG
+void   pcibios_print_pir_table __P((void));
+#endif
+
+#define        PCI_IRQ_TABLE_START     0xf0000
+#define        PCI_IRQ_TABLE_END       0xfffff
+
+void
+pcibios_init()
+{
+       struct bios32_entry_info ei;
+       u_int32_t rev_maj, rev_min, mech1, mech2, scmech1, scmech2;
+
+       if (bios32_service(BIOS32_MAKESIG('$', 'P', 'C', 'I'),
+           &pcibios_entry, &ei) == 0) {
+               /*
+                * No PCI BIOS found; will fall back on old
+                * mechanism.
+                */
+               return;
+       }
+
+       /*
+        * We've located the PCI BIOS service; get some information
+        * about it.
+        */
+       if (pcibios_get_status(&rev_maj, &rev_min, &mech1, &mech2,
+           &scmech1, &scmech2, &pcibios_max_bus) != PCIBIOS_SUCCESS) {
+               /*
+                * We can't use the PCI BIOS; will fall back on old
+                * mechanism.
+                */
+               return;
+       }
+
+       printf("PCI BIOS rev. %d.%d found at 0x%lx\n", rev_maj, rev_min >> 4,
+           ei.bei_entry);
+#ifdef PCIBIOSVERBOSE
+       printf("pcibios: config mechanism %s%s, special cycles %s%s, "
+           "last bus %d\n",
+           mech1 ? "[1]" : "[x]",
+           mech2 ? "[2]" : "[x]",
+           scmech1 ? "[1]" : "[x]",
+           scmech2 ? "[2]" : "[x]",
+           pcibios_max_bus);
+
+#endif
+
+       /*
+        * The PCI BIOS tells us the config mechanism; fill it in now
+        * so that pci_mode_detect() doesn't have to look for it.
+        */
+       pci_mode = mech1 ? 1 : 2;
+
+       pcibios_present = 1;
+
+       /*
+        * Find the PCI IRQ Routing table.
+        */
+       pcibios_pir_init();
+
+#ifdef PCIBIOS_INTR_FIXUP
+       if (pcibios_pir_table != NULL) {
+               int rv;
+               u_int16_t pciirq;
+
+               /*
+                * Fixup interrupt routing.
+                */
+               rv = pci_intr_fixup(NULL, I386_BUS_SPACE_IO, &pciirq);
+               switch (rv) {
+               case -1:
+                       /* Non-fatal error. */
+                       printf("Warning: unable to fix up PCI interrupt "
+                           "routing\n");
+                       break;
+
+               case 1:
+                       /* Fatal error. */
+                       panic("pcibios_init: interrupt fixup failed");
+                       break;
+               }
+
+               /*
+                * XXX Clear `pciirq' from the ISA interrupt allocation
+                * XXX mask.
+                */
+       }
+#endif
+
+#ifdef PCIBIOS_BUS_FIXUP
+       pcibios_max_bus = pci_bus_fixup(NULL, 0);
+#ifdef PCIBIOSVERBOSE
+       printf("PCI bus #%d is the last bus\n", pcibios_max_bus);
+#endif
+#endif
+}
+
+void
+pcibios_pir_init()
+{
+       char devinfo[256];
+       paddr_t pa;
+       caddr_t p;
+       unsigned char cksum;
+       u_int16_t tablesize;
+       u_int8_t rev_maj, rev_min;
+       int i;
+
+       for (pa = PCI_IRQ_TABLE_START; pa < PCI_IRQ_TABLE_END; pa += 16) {
+               p = (caddr_t)ISA_HOLE_VADDR(pa);
+               if (*(int *)p != BIOS32_MAKESIG('$', 'P', 'I', 'R'))
+                       continue;
+               
+               rev_min = *(p + 4);
+               rev_maj = *(p + 5);
+               tablesize = *(u_int16_t *)(p + 6);
+
+               cksum = 0;
+               for (i = 0; i < tablesize; i++)
+                       cksum += *(unsigned char *)(p + i);
+
+               printf("PCI IRQ Routing Table rev. %d.%d found at 0x%lx, "
+                   "size %d bytes (%d entries)\n", rev_maj, rev_min, pa,
+                   tablesize, (tablesize - 32) / 16);
+
+               if (cksum != 0) {
+                       printf("pcibios_pir_init: bad IRQ table checksum\n");
+                       continue;
+               }
+
+               if (tablesize < 32 || (tablesize % 16) != 0) {
+                       printf("pcibios_pir_init: bad IRQ table size\n");
+                       continue;
+               }
+
+               if (rev_maj != 1 || rev_min != 0) {
+                       printf("pcibios_pir_init: unsupported IRQ table "
+                           "version\n");
+                       continue;
+               }
+
+               /*
+                * We can handle this table!  Make a copy of it.
+                */
+               bcopy(p, &pcibios_pir_header, 32);
+               pcibios_pir_table = malloc(tablesize - 32, M_DEVBUF,
+                   M_NOWAIT);
+               if (pcibios_pir_table == NULL) {
+                       printf("pcibios_pir_init: no memory for $PIR\n");
+                       return;
+               }
+               bcopy(p + 32, pcibios_pir_table, tablesize - 32);
+               pcibios_pir_table_nentries = (tablesize - 32) / 16;
+
+               printf("PCI Interrupt Router at %03d:%02d:%01d",
+                   pcibios_pir_header.router_bus,
+                   (pcibios_pir_header.router_devfunc >> 3) & 0x1f,
+                   pcibios_pir_header.router_devfunc & 7);
+               if (pcibios_pir_header.compat_router != 0) {
+                       pci_devinfo(pcibios_pir_header.compat_router, 0, 0,
+                           devinfo);
+                       printf(" (%s)", devinfo);
+               }
+               printf("\n");
+               pcibios_print_exclirq();
+#ifdef PCIINTR_DEBUG
+               pcibios_print_pir_table();
+#endif
+               return;
+       }
+
+       /*
+        * If there was no PIR table found, try using the PCI BIOS
+        * Get Interrupt Routing call.
+        *
+        * XXX The interface to this call sucks; just allocate enough
+        * XXX room for 32 entries.
+        */
+       pcibios_pir_table_nentries = 32;
+       pcibios_pir_table = malloc(pcibios_pir_table_nentries *
+           sizeof(*pcibios_pir_table), M_DEVBUF, M_NOWAIT);
+       if (pcibios_pir_table == NULL) {
+               printf("pcibios_pir_init: no memory for $PIR\n");
+               return;
+       }
+       if (pcibios_get_intr_routing(pcibios_pir_table,
+           &pcibios_pir_table_nentries,
+           &pcibios_pir_header.exclusive_irq) != PCIBIOS_SUCCESS) {
+               printf("No PCI IRQ Routing information available.\n");
+               free(pcibios_pir_table, M_DEVBUF);
+               pcibios_pir_table = NULL;
+               pcibios_pir_table_nentries = 0;
+               return;
+       }
+       printf("PCI BIOS has %d Interrupt Routing table entries\n",
+           pcibios_pir_table_nentries);
+       pcibios_print_exclirq();
+#ifdef PCIINTR_DEBUG
+       pcibios_print_pir_table();
+#endif
+}
+
+int
+pcibios_get_status(rev_maj, rev_min, mech1, mech2, scmech1, scmech2, maxbus)
+       u_int32_t *rev_maj, *rev_min, *mech1, *mech2, *scmech1, *scmech2,
+           *maxbus;
+{
+       u_int16_t ax, bx, cx;
+       u_int32_t edx;
+       int rv;
+
+       __asm __volatile("lcall (%%edi)                                 ; \
+                       jc 1f                                           ; \
+                       xor %%ah, %%ah                                  ; \
+               1:"
+               : "=a" (ax), "=b" (bx), "=c" (cx), "=d" (edx)
+               : "0" (0xb101), "D" (&pcibios_entry));
+
+       rv = pcibios_return_code(ax, "pcibios_get_status");
+       if (rv != PCIBIOS_SUCCESS)
+               return (rv);
+
+       if (edx != BIOS32_MAKESIG('P', 'C', 'I', ' '))
+               return (PCIBIOS_SERVICE_NOT_PRESENT);   /* XXX */
+
+       /*
+        * Fill in the various pieces if info we're looking for.
+        */
+       *mech1 = ax & 1;
+       *mech2 = ax & (1 << 1);
+       *scmech1 = ax & (1 << 4);
+       *scmech2 = ax & (1 << 5);
+       *rev_maj = (bx >> 8) & 0xff;
+       *rev_min = bx & 0xff;
+       *maxbus = cx & 0xff;
+
+       return (PCIBIOS_SUCCESS);
+}
+
+int
+pcibios_get_intr_routing(table, nentries, exclirq)
+       struct pcibios_intr_routing *table;
+       int *nentries;
+       u_int16_t *exclirq;
+{
+       u_int16_t ax, bx;
+       int rv;
+       struct {
+               u_int16_t size;
+               caddr_t offset;
+               u_int16_t segment;
+       } __attribute__((__packed__)) args;
+
+       args.size = *nentries * sizeof(*table);
+       args.offset = (caddr_t)table;
+       args.segment = GSEL(GDATA_SEL, SEL_KPL);
+
+       memset(table, 0, args.size);
+
+       __asm __volatile("lcall (%%esi)                                 ; \
+                       jc 1f                                           ; \
+                       xor %%ah, %%ah                                  ; \
+               1:      movw %w2, %%ds                                  ; \
+                       movw %w2, %%es"
+               : "=a" (ax), "=b" (bx)
+               : "r" GSEL(GDATA_SEL, SEL_KPL), "0" (0xb10e), "1" (0),
+                 "D" (&args), "S" (&pcibios_entry));
+
+       rv = pcibios_return_code(ax, "pcibios_get_intr_routing");
+       if (rv != PCIBIOS_SUCCESS)
+               return (rv);
+
+       *nentries = args.size / sizeof(*table);
+       *exclirq = bx;
+
+       return (PCIBIOS_SUCCESS);
+}
+
+int
+pcibios_return_code(ax, func)
+       u_int16_t ax;
+       const char *func;
+{
+       const char *errstr;
+       int rv = ax >> 8;
+
+       switch (rv) {
+       case PCIBIOS_SUCCESS:
+               return (PCIBIOS_SUCCESS);
+
+       case PCIBIOS_SERVICE_NOT_PRESENT:
+               errstr = "service not present";
+               break;
+
+       case PCIBIOS_FUNCTION_NOT_SUPPORTED:
+               errstr = "function not supported";
+               break;
+
+       case PCIBIOS_BAD_VENDOR_ID:
+               errstr = "bad vendor ID";
+               break;
+
+       case PCIBIOS_DEVICE_NOT_FOUND:
+               errstr = "device not found";
+               break;
+
+       case PCIBIOS_BAD_REGISTER_NUMBER:
+               errstr = "bad register number";
+               break;
+
+       case PCIBIOS_SET_FAILED:
+               errstr = "set failed";
+               break;
+
+       case PCIBIOS_BUFFER_TOO_SMALL:
+               errstr = "buffer too small";
+               break;
+
+       default:
+               printf("%s: unknown return code 0x%x\n", func, rv);
+               return (rv);
+       }
+
+       printf("%s: %s\n", func, errstr);
+       return (rv);
+}
+
+void
+pcibios_print_exclirq()
+{
+       int i;
+
+       if (pcibios_pir_header.exclusive_irq) {
+               printf("PCI Exclusive IRQs:");
+               for (i = 0; i < 16; i++) {
+                       if (pcibios_pir_header.exclusive_irq & (1 << i))
+                               printf(" %d", i);
+               }
+               printf("\n");
+       }
+}
+
+#ifdef PCIINTR_DEBUG
+void
+pcibios_print_pir_table()
+{
+       int i, j;
+
+       for (i = 0; i < pcibios_pir_table_nentries; i++) {
+               printf("PIR Entry %d:\n", i);
+               printf("\tBus: %d  Device: %d\n",
+                   pcibios_pir_table[i].bus,
+                   pcibios_pir_table[i].device >> 3);
+               for (j = 0; j < 4; j++) {
+                       printf("\t\tINT%c: link 0x%02x bitmap 0x%04x\n",
+                           'A' + j,
+                           pcibios_pir_table[i].linkmap[j].link,
+                           pcibios_pir_table[i].linkmap[j].bitmap);
+               }
+       }
+}
+#endif
diff --git a/sys/arch/i386/pci/pcibios.h b/sys/arch/i386/pci/pcibios.h
new file mode 100644 (file)
index 0000000..6b584c9
--- /dev/null
@@ -0,0 +1,87 @@
+/*     $NetBSD$        */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Data structure definitions for the PCI BIOS interface.
+ */
+
+/*
+ * PCI BIOS return codes.
+ */
+#define        PCIBIOS_SUCCESS                 0x00
+#define        PCIBIOS_SERVICE_NOT_PRESENT     0x80
+#define        PCIBIOS_FUNCTION_NOT_SUPPORTED  0x81
+#define        PCIBIOS_BAD_VENDOR_ID           0x83
+#define        PCIBIOS_DEVICE_NOT_FOUND        0x86
+#define        PCIBIOS_BAD_REGISTER_NUMBER     0x87
+#define        PCIBIOS_SET_FAILED              0x88
+#define        PCIBIOS_BUFFER_TOO_SMALL        0x89
+
+/*
+ * PCI IRQ Routing Table definitions.
+ */
+
+/*
+ * Slot entry (per PCI 2.1)
+ */
+struct pcibios_linkmap {
+       u_int8_t        link;
+       u_int16_t       bitmap;
+} __attribute__((__packed__));
+
+struct pcibios_intr_routing {
+       u_int8_t        bus;
+       u_int8_t        device;
+       struct pcibios_linkmap linkmap[4];      /* INT[A:D]# */
+       u_int8_t        slot;
+       u_int8_t        reserved;
+} __attribute__((__packed__));
+
+/*
+ * $PIR header.  Reference:
+ *
+ *     http://www.microsoft.com/HWDEV/busbios/PCIIRQ.htm
+ */
+struct pcibios_pir_header {
+       u_int32_t       signature;              /* $PIR */
+       u_int16_t       version;
+       u_int16_t       tablesize;
+       u_int8_t        router_bus;
+       u_int8_t        router_devfunc;
+       u_int16_t       exclusive_irq;
+       u_int32_t       compat_router;          /* PCI vendor/product */
+       u_int32_t       miniport;
+       u_int8_t        reserved[11];
+       u_int8_t        checksum;
+} __attribute__((__packed__));
+
+void   pcibios_init __P((void));
+
+extern struct pcibios_pir_header pcibios_pir_header;
+extern struct pcibios_intr_routing *pcibios_pir_table;
+extern int pcibios_pir_table_nentries;
+extern int pcibios_max_bus;
diff --git a/sys/arch/i386/pci/piix.c b/sys/arch/i386/pci/piix.c
new file mode 100644 (file)
index 0000000..19cbded
--- /dev/null
@@ -0,0 +1,237 @@
+/*     $NetBSD$        */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Support for the Intel PIIX PCI-ISA bridge interrupt controller.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+
+#include <i386/pci/pci_intr_fixup.h>
+#include <i386/pci/piixreg.h>
+#include <i386/pci/piixvar.h>
+
+int    piix_getclink __P((pciintr_icu_handle_t, int, int *));
+int    piix_get_intr __P((pciintr_icu_handle_t, int, int *));
+int    piix_set_intr __P((pciintr_icu_handle_t, int, int));
+
+const struct pciintr_icu piix_pci_icu = {
+       piix_getclink,
+       piix_get_intr,
+       piix_set_intr,
+       piix_get_trigger,
+       piix_set_trigger,
+};
+
+int
+piix_init(pc, iot, tag, ptagp, phandp)
+       pci_chipset_tag_t pc;
+       bus_space_tag_t iot;
+       pcitag_t tag;
+       pciintr_icu_tag_t *ptagp;
+       pciintr_icu_handle_t *phandp;
+{
+       struct piix_handle *ph;
+
+       ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT);
+       if (ph == NULL)
+               return (1);
+
+       ph->ph_iot = iot;
+       ph->ph_pc = pc;
+       ph->ph_tag = tag;
+
+       if (bus_space_map(iot, PIIX_REG_ELCR, PIIX_REG_ELCR_SIZE, 0,
+           &ph->ph_elcr_ioh) != 0) {
+               free(ph, M_DEVBUF);
+               return (1);
+       }
+
+       *ptagp = &piix_pci_icu;
+       *phandp = ph;
+       return (0);
+}
+
+int
+piix_getclink(v, link, clinkp)
+       pciintr_icu_handle_t v;
+       int link, *clinkp;
+{
+
+       /* Pattern 1: simple. */
+       if (PIIX_LEGAL_LINK(link - 1)) {
+               *clinkp = link - 1;
+               return (0);
+       }
+
+       /* Pattern 2: configuration register offset */
+       if (link >= 0x60 && link <= 0x63) {
+               *clinkp = link - 0x60;
+               return (0);
+       }
+
+       return (1);
+}
+
+int
+piix_get_intr(v, clink, irqp)
+       pciintr_icu_handle_t v;
+       int clink, *irqp;
+{
+       struct piix_handle *ph = v;
+       int shift;
+       pcireg_t reg;
+
+       if (PIIX_LEGAL_LINK(clink) == 0)
+               return (1);
+
+       reg = pci_conf_read(ph->ph_pc, ph->ph_tag, PIIX_CFG_PIRQ);
+       shift = clink << 3;
+       if ((reg >> shift) & PIIX_CFG_PIRQ_NONE)
+               *irqp = 0xff;
+       else
+               *irqp = PIIX_PIRQ(reg, clink);
+
+       return (0);
+}
+
+int
+piix_set_intr(v, clink, irq)
+       pciintr_icu_handle_t v;
+       int clink, irq;
+{
+       struct piix_handle *ph = v;
+       int shift;
+       pcireg_t reg;
+
+       if (PIIX_LEGAL_LINK(clink) == 0 || PIIX_LEGAL_IRQ(irq) == 0)
+               return (1);
+
+       reg = pci_conf_read(ph->ph_pc, ph->ph_tag, PIIX_CFG_PIRQ);
+       shift = clink << 3;
+       reg &= ~((PIIX_CFG_PIRQ_NONE | PIIX_CFG_PIRQ_MASK) << shift);
+       reg |= irq << shift;
+       pci_conf_write(ph->ph_pc, ph->ph_tag, PIIX_CFG_PIRQ, reg);
+
+       return (0);
+}
+
+int
+piix_get_trigger(v, irq, triggerp)
+       pciintr_icu_handle_t v;
+       int irq, *triggerp;
+{
+       struct piix_handle *ph = v;
+       int off, bit;
+       u_int8_t elcr;
+
+       if (PIIX_LEGAL_IRQ(irq) == 0)
+               return (1);
+
+       off = (irq > 7) ? 1 : 0;
+       bit = irq & 7;
+
+       elcr = bus_space_read_1(ph->ph_iot, ph->ph_elcr_ioh, off);
+       if (elcr & (1 << bit))
+               *triggerp = IST_LEVEL;
+       else
+               *triggerp = IST_EDGE;
+
+       return (0);
+}
+
+int
+piix_set_trigger(v, irq, trigger)
+       pciintr_icu_handle_t v;
+       int irq, trigger;
+{
+       struct piix_handle *ph = v;
+       int off, bit;
+       u_int8_t elcr;
+
+       if (PIIX_LEGAL_IRQ(irq) == 0)
+               return (1);
+
+       off = (irq > 7) ? 1 : 0;
+       bit = irq & 7;
+
+       elcr = bus_space_read_1(ph->ph_iot, ph->ph_elcr_ioh, off);
+       if (trigger == IST_LEVEL)
+               elcr |= (1 << bit);
+       else
+               elcr &= ~(1 << bit);
+       bus_space_write_1(ph->ph_iot, ph->ph_elcr_ioh, off, elcr);
+
+       return (0);
+}
diff --git a/sys/arch/i386/pci/piixreg.h b/sys/arch/i386/pci/piixreg.h
new file mode 100644 (file)
index 0000000..36f18b8
--- /dev/null
@@ -0,0 +1,55 @@
+/*     $NetBSD$        */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Register definitions for the Intel PIIX PCI-ISA bridge interrupt controller.
+ */
+
+/*
+ * PIRQ[3:0]# - PIRQ ROUTE CONTROL REGISTERS
+ *
+ * PCI Configuration registers 0x60, 0x61, 0x62, 0x63
+ */
+
+#define        PIIX_LEGAL_LINK(link)   ((link) >= 0 && (link) <= 3)
+
+#define        PIIX_PIRQ_MASK          0xdef8
+#define        PIIX_LEGAL_IRQ(irq)     ((irq) >= 0 && (irq) <= 15 &&           \
+                                ((1 << (irq)) & PIIX_PIRQ_MASK) != 0)
+
+#define        PIIX_CFG_PIRQ           0x60    /* PCI configuration space */
+#define        PIIX_CFG_PIRQ_NONE      0x80
+#define        PIIX_CFG_PIRQ_MASK      0x0f
+#define        PIIX_PIRQ(reg, x)       (((reg) >> ((x) << 3)) & 0xff)
+
+/*
+ * ELCR - EDGE/LEVEL CONTROL REGISTER
+ *
+ * PCI I/O registers 0x4d0, 0x4d1
+ */
+#define        PIIX_REG_ELCR           0x4d0
+#define        PIIX_REG_ELCR_SIZE      2
diff --git a/sys/arch/i386/pci/piixvar.h b/sys/arch/i386/pci/piixvar.h
new file mode 100644 (file)
index 0000000..64b192c
--- /dev/null
@@ -0,0 +1,77 @@
+/*     $NetBSD$        */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Support for the Intel PIIX PCI-ISA bridge interrupt controller.
+ */
+
+int    piix_get_trigger __P((pciintr_icu_handle_t, int, int *));
+int    piix_set_trigger __P((pciintr_icu_handle_t, int, int));
+
+struct piix_handle {
+       bus_space_tag_t ph_iot;
+       bus_space_handle_t ph_elcr_ioh;
+       pci_chipset_tag_t ph_pc;
+       pcitag_t ph_tag;
+};
diff --git a/sys/arch/i386/pci/sis85c503.c b/sys/arch/i386/pci/sis85c503.c
new file mode 100644 (file)
index 0000000..50c5fbf
--- /dev/null
@@ -0,0 +1,180 @@
+/*     $NetBSD$        */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Support for the SiS 85c503 PCI-ISA bridge interrupt controller.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+
+#include <i386/pci/pci_intr_fixup.h>
+#include <i386/pci/sis85c503reg.h>
+#include <i386/pci/piixvar.h>
+
+int    sis85c503_getclink __P((pciintr_icu_handle_t, int, int *));
+int    sis85c503_get_intr __P((pciintr_icu_handle_t, int, int *));
+int    sis85c503_set_intr __P((pciintr_icu_handle_t, int, int));
+
+const struct pciintr_icu sis85c503_pci_icu = {
+       sis85c503_getclink,
+       sis85c503_get_intr,
+       sis85c503_set_intr,
+       piix_get_trigger,
+       piix_set_trigger,
+};
+
+int
+sis85c503_init(pc, iot, tag, ptagp, phandp)
+       pci_chipset_tag_t pc;
+       bus_space_tag_t iot;
+       pcitag_t tag;
+       pciintr_icu_tag_t *ptagp;
+       pciintr_icu_handle_t *phandp;
+{
+
+       if (piix_init(pc, iot, tag, ptagp, phandp) == 0) {
+               *ptagp = &sis85c503_pci_icu;
+               return (0);
+       }
+
+       return (1);
+}
+
+int
+sis85c503_getclink(v, link, clinkp)
+       pciintr_icu_handle_t v;
+       int link, *clinkp;
+{
+
+       /* Pattern 1: simple. */
+       if (link >= 1 && link <= 4) {
+               *clinkp = SIS85C503_CFG_PIRQ_REGSTART + link - 1;
+               return (0);
+       }
+
+       /* Pattern 2: configuration register offset */
+       if (link >= SIS85C503_CFG_PIRQ_REGSTART &&
+           link <= SIS85C503_CFG_PIRQ_REGEND) {
+               *clinkp = link;
+               return (0);
+       }
+
+       return (1);
+}
+
+int
+sis85c503_get_intr(v, clink, irqp)
+       pciintr_icu_handle_t v;
+       int clink, *irqp;
+{
+       struct piix_handle *ph = v;
+       pcireg_t reg;
+
+       if (SIS85C503_LEGAL_LINK(clink) == 0)
+               return (1);
+
+       reg = pci_conf_read(ph->ph_pc, ph->ph_tag,
+           SIS85C503_CFG_PIRQ_REGOFS(clink));
+       reg = SIS85C503_CFG_PIRQ_REG(reg, clink);
+
+       if (reg & SIS85C503_CFG_PIRQ_ROUTE_DISABLE)
+               *irqp = 0xff;
+       else
+               *irqp = reg & SIS85C503_CFG_PIRQ_INTR_MASK;
+
+       return (0);
+}
+
+int
+sis85c503_set_intr(v, clink, irq)
+       pciintr_icu_handle_t v;
+       int clink, irq;
+{
+       struct piix_handle *ph = v;
+       int shift;
+       pcireg_t reg;
+
+       if (SIS85C503_LEGAL_LINK(clink) == 0 || SIS85C503_LEGAL_IRQ(irq) == 0)
+               return (1);
+
+       reg = pci_conf_read(ph->ph_pc, ph->ph_tag,
+           SIS85C503_CFG_PIRQ_REGOFS(clink));
+       shift = SIS85C503_CFG_PIRQ_SHIFT(clink);
+       reg &= ~((SIS85C503_CFG_PIRQ_ROUTE_DISABLE |
+           SIS85C503_CFG_PIRQ_INTR_MASK) << shift);
+       reg |= (irq << shift);
+       pci_conf_write(ph->ph_pc, ph->ph_tag, SIS85C503_CFG_PIRQ_REGOFS(clink),
+           reg);
+
+       return (0);
+}
diff --git a/sys/arch/i386/pci/sis85c503reg.h b/sys/arch/i386/pci/sis85c503reg.h
new file mode 100644 (file)
index 0000000..a96ef90
--- /dev/null
@@ -0,0 +1,52 @@
+/*     $NetBSD$        */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Register definitions for the SiS 85c503 PCI-ISA bridge interrupt controller.
+ */
+
+#define        SIS85C503_CFG_PIRQ_REGSTART     0x41    /* PCI configuration space */
+#define        SIS85C503_CFG_PIRQ_REGEND       0x44
+
+#define        SIS85C503_LEGAL_LINK(link) ((link) >= SIS85C503_CFG_PIRQ_REGSTART && \
+                                   (link) <= SIS85C503_CFG_PIRQ_REGEND)
+
+#define        SIS85C503_CFG_PIRQ_REGOFS(regofs) (((regofs) >> 2) << 2)
+#define        SIS85C503_CFG_PIRQ_SHIFT(regofs)                                \
+       (((regofs) - SIS85C503_CFG_PIRQ_REGOFS(regofs)) << 3)
+
+#define        SIS85C503_CFG_PIRQ_MASK         0xff
+#define        SIS85C503_CFG_PIRQ_INTR_MASK    0x0f
+
+#define        SIS85C503_CFG_PIRQ_REG(reg, regofs)                             \
+       (((reg) >> SIS85C503_CFG_PIRQ_SHIFT(regofs)) & SIS85C503_CFG_PIRQ_MASK)
+
+#define        SIS85C503_CFG_PIRQ_ROUTE_DISABLE 0x80
+
+#define        SIS85C503_PIRQ_MASK             0xdef8
+#define        SIS85C503_LEGAL_IRQ(irq)        ((irq) >= 0 && (irq) <= 15 &&   \
+                                ((1 << (irq)) & SIS85C503_PIRQ_MASK) != 0)
diff --git a/sys/arch/i386/pci/via82c586.c b/sys/arch/i386/pci/via82c586.c
new file mode 100644 (file)
index 0000000..021eaa2
--- /dev/null
@@ -0,0 +1,270 @@
+/*     $NetBSD$        */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Support for the VIA 82c586 PCI-ISA bridge interrupt controller.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+
+#include <i386/pci/pci_intr_fixup.h>
+#include <i386/pci/via82c586reg.h>
+#include <i386/pci/piixvar.h>
+
+int    via82c586_getclink __P((pciintr_icu_handle_t, int, int *));
+int    via82c586_get_intr __P((pciintr_icu_handle_t, int, int *));
+int    via82c586_set_intr __P((pciintr_icu_handle_t, int, int));
+int    via82c586_get_trigger __P((pciintr_icu_handle_t, int, int *));
+int    via82c586_set_trigger __P((pciintr_icu_handle_t, int, int));
+
+const struct pciintr_icu via82c586_pci_icu = {
+       via82c586_getclink,
+       via82c586_get_intr,
+       via82c586_set_intr,
+       via82c586_get_trigger,
+       via82c586_set_trigger,
+};
+
+const int vp3_cfg_trigger_shift[] = {
+       VP3_CFG_TRIGGER_SHIFT_PIRQA,
+       VP3_CFG_TRIGGER_SHIFT_PIRQB,
+       VP3_CFG_TRIGGER_SHIFT_PIRQC,
+       VP3_CFG_TRIGGER_SHIFT_PIRQD,
+};
+
+#define        VP3_TRIGGER(reg, pirq)  (((reg) >> vp3_cfg_trigger_shift[(pirq)]) & \
+                                VP3_CFG_TRIGGER_MASK)
+
+const int vp3_cfg_intr_shift[] = {
+       VP3_CFG_INTR_SHIFT_PIRQA,
+       VP3_CFG_INTR_SHIFT_PIRQB,
+       VP3_CFG_INTR_SHIFT_PIRQC,
+       VP3_CFG_INTR_SHIFT_PIRQD,
+};
+
+#define        VP3_PIRQ(req, pirq)     (((reg) >> vp3_cfg_intr_shift[(pirq)]) & \
+                                VP3_CFG_INTR_MASK)
+
+int
+via82c586_init(pc, iot, tag, ptagp, phandp)
+       pci_chipset_tag_t pc;
+       bus_space_tag_t iot;
+       pcitag_t tag;
+       pciintr_icu_tag_t *ptagp;
+       pciintr_icu_handle_t *phandp;
+{
+       pcireg_t reg;
+
+       if (piix_init(pc, iot, tag, ptagp, phandp) == 0) {
+               *ptagp = &via82c586_pci_icu;
+               
+               /*
+                * Enable EISA ELCR.
+                */
+               reg = pci_conf_read(pc, tag, VP3_CFG_KBDMISCCTRL12_REG);
+               reg |= VP3_CFG_MISCCTRL2_EISA4D04D1PORT_ENABLE <<
+                   VP3_CFG_MISCCTRL2_SHIFT;
+               pci_conf_write(pc, tag, VP3_CFG_KBDMISCCTRL12_REG, reg);
+
+               return (0);
+       }
+
+       return (1);
+}
+
+int
+via82c586_getclink(v, link, clinkp)
+       pciintr_icu_handle_t v;
+       int link, *clinkp;
+{
+
+       if (VP3_LEGAL_LINK(link - 1)) {
+               *clinkp = link - 1;
+               return (0);
+       }
+
+       return (1);
+}
+
+int
+via82c586_get_intr(v, clink, irqp)
+       pciintr_icu_handle_t v;
+       int clink, *irqp;
+{
+       struct piix_handle *ph = v;
+       pcireg_t reg;
+       int val;
+
+       if (VP3_LEGAL_LINK(clink) == 0)
+               return (1);
+
+       reg = pci_conf_read(ph->ph_pc, ph->ph_tag, VP3_CFG_PIRQ_REG);
+       val = VP3_PIRQ(reg, clink);
+       *irqp = (val == VP3_PIRQ_NONE) ? 0xff : val;
+
+       return (0);
+}
+
+int
+via82c586_set_intr(v, clink, irq)
+       pciintr_icu_handle_t v;
+       int clink, irq;
+{
+       struct piix_handle *ph = v;
+       int shift, val;
+       pcireg_t reg;
+
+       if (VP3_LEGAL_LINK(clink) == 0 || VP3_LEGAL_IRQ(irq) == 0)
+               return (1);
+
+       reg = pci_conf_read(ph->ph_pc, ph->ph_tag, VP3_CFG_PIRQ_REG);
+       via82c586_get_intr(v, clink, &val);
+       shift = vp3_cfg_intr_shift[clink];
+       reg &= ~(VP3_CFG_INTR_MASK << shift);
+       reg |= (irq << shift);
+       pci_conf_write(ph->ph_pc, ph->ph_tag, VP3_CFG_PIRQ_REG, reg);
+       if (via82c586_get_intr(v, clink, &val) != 0 ||
+           val != irq)
+               return (1);
+
+       return (0);
+}
+
+int
+via82c586_get_trigger(v, irq, triggerp)
+       pciintr_icu_handle_t v;
+       int irq, *triggerp;
+{
+       struct piix_handle *ph = v;
+       int i, error, check_consistency, pciirq, pcitrigger = IST_NONE;
+       pcireg_t reg;
+
+       if (VP3_LEGAL_IRQ(irq) == 0)
+               return (1);
+
+       check_consistency = 0;
+       for (i = 0; i <= 3; i++) {
+               via82c586_get_intr(v, i, &pciirq);
+               if (pciirq == irq) {
+                       reg = pci_conf_read(ph->ph_pc, ph->ph_tag,
+                           VP3_CFG_PIRQ_REG);
+                       if (VP3_TRIGGER(reg, i) == VP3_CFG_TRIGGER_EDGE)
+                               pcitrigger = IST_EDGE;
+                       else
+                               pcitrigger = IST_LEVEL;
+                       check_consistency = 1;
+                       break;
+               }
+       }
+
+       error = piix_get_trigger(v, irq, triggerp);
+       if (error == 0 && check_consistency && pcitrigger != *triggerp)
+               return (1);
+       return (error);
+}
+
+int
+via82c586_set_trigger(v, irq, trigger)
+       pciintr_icu_handle_t v;
+       int irq, trigger;
+{
+       struct piix_handle *ph = v;
+       int i, pciirq, shift, testtrig;
+       pcireg_t reg;
+
+       if (VP3_LEGAL_IRQ(irq) == 0)
+               return (1);
+
+       for (i = 0; i <= 3; i++) {
+               via82c586_get_intr(v, i, &pciirq);
+               if (pciirq == irq) {
+                       reg = pci_conf_read(ph->ph_pc, ph->ph_tag,
+                           VP3_CFG_PIRQ_REG);
+                       shift = vp3_cfg_trigger_shift[i];
+                       if (trigger == IST_LEVEL)
+                               reg &= ~(VP3_CFG_TRIGGER_MASK << shift);
+                       else
+                               reg |= (VP3_CFG_TRIGGER_EDGE << shift);
+                       pci_conf_write(ph->ph_pc, ph->ph_tag,
+                           VP3_CFG_PIRQ_REG, reg);
+                       break;
+               }
+       }
+
+       if (piix_set_trigger(v, irq, trigger) != 0 ||
+           via82c586_get_trigger(v, irq, &testtrig) != 0 ||
+           testtrig != trigger)
+               return (1);
+
+       return (0);
+}
diff --git a/sys/arch/i386/pci/via82c586reg.h b/sys/arch/i386/pci/via82c586reg.h
new file mode 100644 (file)
index 0000000..fa812d1
--- /dev/null
@@ -0,0 +1,62 @@
+/*     $NetBSD$        */
+
+/*
+ * Copyright (c) 1999, by UCHIYAMA Yasushi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Register definitions for the VIA 82c586 PCI-ISA bridge interrupt controller.
+ */
+
+#define        VP3_CFG_PIRQ_REG                0x54    /* PCI configuration space */
+#define        VP3_CFG_KBDMISCCTRL12_REG       0x44
+#define        VP3_CFG_IDEMISCCTRL3_REG        0x48
+
+#define        VP3_CFG_MISCCTRL2_SHIFT         24
+#define        VP3_CFG_MISCCTRL2_MASK          0x0f
+#define        VP3_CFG_MISCCTRL2_EISA4D04D1PORT_ENABLE 0x20
+#define        VP3_CFG_MISCCTRL2_REG(reg)                                      \
+       (((reg) >> VP3_CFG_MISCCTRL2_SHIFT) & VP3_CFG_MISCCTRL2_MASK)
+
+#define        VP3_CFG_TRIGGER_LEVEL           0
+#define        VP3_CFG_TRIGGER_EDGE            1
+
+#define        VP3_CFG_TRIGGER_MASK            0x01
+#define        VP3_CFG_TRIGGER_SHIFT_PIRQA     3
+#define        VP3_CFG_TRIGGER_SHIFT_PIRQB     2
+#define        VP3_CFG_TRIGGER_SHIFT_PIRQC     1
+#define        VP3_CFG_TRIGGER_SHIFT_PIRQD     0
+
+#define        VP3_CFG_INTR_MASK               0x04
+#define        VP3_PIRQ_MASK                   0xdefa
+
+#define        VP3_CFG_INTR_SHIFT_PIRQA        0x14
+#define        VP3_CFG_INTR_SHIFT_PIRQB        0x10
+#define        VP3_CFG_INTR_SHIFT_PIRQC        0x1c
+#define        VP3_CFG_INTR_SHIFT_PIRQD        0x0c
+
+#define        VP3_PIRQ_NONE                   0
+#define        VP3_LEGAL_LINK(link)            ((link) >= 0 && (link) <= 3)
+#define        VP3_LEGAL_IRQ(irq)              ((irq) >= 0 && (irq) <= 15 &&   \
+                                        ((1 << (irq)) & VP3_PIRQ_MASK) != 0)
index eb9b9d6..2b42ef8 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.pci,v 1.65 2000/03/16 20:33:48 deraadt Exp $
+#      $OpenBSD: files.pci,v 1.66 2000/03/26 22:38:20 mickey Exp $
 #      $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $
 #
 # Config file and device description for machine-independent PCI code.
@@ -9,6 +9,7 @@ device  pci {[dev = -1], [function = -1]}
 attach pci at pcibus
 file   dev/pci/pci.c                   pci needs-flag
 file   dev/pci/pci_map.c               pci
+file   dev/pci/pci_quirks.c            pci
 file   dev/pci/pci_subr.c              pci
 
 # Generic VGA
diff --git a/sys/dev/pci/pci_quirks.c b/sys/dev/pci/pci_quirks.c
new file mode 100644 (file)
index 0000000..770760f
--- /dev/null
@@ -0,0 +1,62 @@
+/*     $OpenBSD: pci_quirks.c,v 1.1 2000/03/26 22:38:22 mickey Exp $   */
+/*     $NetBSD$        */
+
+/*
+ * Copyright (c) 1998 Christopher G. Demetriou.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Christopher G. Demetriou
+ *     for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * PCI Quirk data table and lookup function.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+static const struct pci_quirkdata pci_quirks[] = {
+       { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371FB_ISA,
+           PCI_QUIRK_MULTIFUNCTION },
+};
+
+const struct pci_quirkdata *
+pci_lookup_quirkdata(vendor, product)
+       pci_vendor_id_t vendor;
+       pci_product_id_t product;
+{
+       int i;
+
+       for (i = 0; i < (sizeof pci_quirks / sizeof pci_quirks[0]); i++)
+               if (vendor == pci_quirks[i].vendor &&
+                   product == pci_quirks[i].product)
+                       return (&pci_quirks[i]);
+       return (NULL);
+}
index 2564f57..eb98bb5 100644 (file)
@@ -1,4 +1,4 @@
-       $OpenBSD: pcidevs,v 1.229 2000/03/24 18:44:24 deraadt Exp $
+       $OpenBSD: pcidevs,v 1.230 2000/03/26 22:38:22 mickey Exp $
 
 /*     $NetBSD: pcidevs,v 1.30 1997/06/24 06:20:24 thorpej Exp $       */
 
@@ -989,7 +989,7 @@ product INTEL EEPRO100S             0x1228  EE Pro 100 Smart
 product INTEL 82557            0x1229  82557
 product INTEL 82559            0x1030  82559
 product INTEL 82437FX          0x122d  82437FX (Triton) PCI/Cache/DRAM
-product INTEL 82371            0x122e  82371FB (Triton) PCI-ISA
+product INTEL 82371FB_ISA      0x122e  82371FB (Triton) PCI-ISA
 product INTEL 82371FB_IDE      0x1230  82371FB (Triton) IDE
 product INTEL 82371MX          0x1234  82371 (Triton MX) PCI-ISA and IDE
 product INTEL 82437MX          0x1235  82437 (Triton MX) PCI/CACHECOMP/DRAM
@@ -1011,12 +1011,12 @@ product INTEL 82801AB_SMB       0x2423  82801AB SMBus
 product INTEL 82801AB_ACA       0x2425  82801AB AC-97 Audio
 product INTEL 82801AB_ACM       0x2426  82801AB AC-97 Modem
 product INTEL 82801AB_HPB       0x2428  82801AB Hub-to-PCI
-product INTEL 82371SB          0x7000  82371SB (Triton II) PCI-ISA
+product INTEL 82371SB_ISA      0x7000  82371SB (Triton II) PCI-ISA
 product INTEL 82371SB_IDE      0x7010  82371SB (Triton II) IDE
 product INTEL 82371USB         0x7020  82371SB (Triton II) USB
 product INTEL 82437VX          0x7030  82437VX System (TVX)
 product INTEL 82439TX          0x7100  82439TX System (MTXC)
-product INTEL 82371AB          0x7110  82371AB PIIX4 ISA
+product INTEL 82371AB_ISA      0x7110  82371AB PIIX4 ISA
 product INTEL 82371AB_IDE      0x7111  82371AB IDE (PIIX4)
 product INTEL 82371AB_USB      0x7112  82371AB USB (PIIX4)
 product INTEL 82371AB_PMC      0x7113  82371AB Power Management (PIIX4)
@@ -1471,7 +1471,7 @@ product VIATECH VT82C561  0x0561  VT82C561
 product VIATECH VT82C586A_IDE  0x0571  VT82C586A IDE
 product VIATECH VT82C576       0x0576  VT82C576 3V
 product VIATECH VT82C585       0x0585  VT82C585 (Apollo) PCI-ISA
-product VIATECH VT82C586       0x0586  VT82C586 (Apollo VP) PCI-ISA
+product VIATECH VT82C586_ISA   0x0586  VT82C586 (Apollo VP) PCI-ISA
 product VIATECH VT82C595       0x0595  VT82C595 (Apollo VP2) Host-PCI
 product VIATECH VT82C597PCI    0x0597  VT82C597 (Apollo VP3) Host-PCI
 product VIATECH VT82C598PCI    0x0598  VT82C598 (Apollo MVP3) Host-PCI
index deef4a9..3878040 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pcivar.h,v 1.16 1999/07/18 03:20:18 csapuntz Exp $    */
+/*     $OpenBSD: pcivar.h,v 1.17 2000/03/26 22:38:22 mickey Exp $      */
 /*     $NetBSD: pcivar.h,v 1.23 1997/06/06 23:48:05 thorpej Exp $      */
 
 /*
@@ -133,6 +133,16 @@ struct pci_attach_args {
 #define        PCI_FLAGS_IO_ENABLED    0x01            /* I/O space is enabled */
 #define        PCI_FLAGS_MEM_ENABLED   0x02            /* memory space is enabled */
 
+/*
+ *
+ */
+struct pci_quirkdata {
+       pci_vendor_id_t         vendor;         /* Vendor ID */
+       pci_product_id_t        product;        /* Product ID */
+       int                     quirks;         /* quirks; see below */
+};
+#define        PCI_QUIRK_MULTIFUNCTION         0x00000001
+
 /*
  * Locators devices that attach to 'pcibus', as specified to config.
  */
@@ -176,5 +186,6 @@ int pci_get_capability __P((pci_chipset_tag_t, pcitag_t, int,
  */
 void   pci_devinfo __P((pcireg_t, pcireg_t, int, char *));
 void   set_pci_isa_bridge_callback __P((void (*)(void *), void *));
-
+const struct pci_quirkdata *
+       pci_lookup_quirkdata __P((pci_vendor_id_t, pci_product_id_t));
 #endif /* _DEV_PCI_PCIVAR_H_ */