summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/i386/pci/pci_addr_fixup.c156
-rw-r--r--sys/arch/i386/pci/pci_bus_fixup.c21
-rw-r--r--sys/arch/i386/pci/pci_intr_fixup.c511
-rw-r--r--sys/arch/i386/pci/pci_machdep.c39
-rw-r--r--sys/arch/i386/pci/pci_machdep.h10
-rw-r--r--sys/arch/i386/pci/pcib.c10
-rw-r--r--sys/arch/i386/pci/pcibios.c65
-rw-r--r--sys/arch/i386/pci/pcibiosvar.h81
8 files changed, 410 insertions, 483 deletions
diff --git a/sys/arch/i386/pci/pci_addr_fixup.c b/sys/arch/i386/pci/pci_addr_fixup.c
index 71afb374439..66f4324a0e4 100644
--- a/sys/arch/i386/pci/pci_addr_fixup.c
+++ b/sys/arch/i386/pci/pci_addr_fixup.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_addr_fixup.c,v 1.7 2001/01/25 01:00:58 mickey Exp $ */
+/* $OpenBSD: pci_addr_fixup.c,v 1.8 2001/01/27 04:59:39 mickey Exp $ */
/* $NetBSD: pci_addr_fixup.c,v 1.7 2000/08/03 20:10:45 nathanw Exp $ */
/*-
@@ -42,21 +42,21 @@
#include <i386/pci/pcibiosvar.h>
-struct pciaddr pciaddr;
-
typedef int (*pciaddr_resource_manage_func_t)
- (pci_chipset_tag_t, pcitag_t, int, struct extent *, int,
- bus_addr_t *, bus_size_t);
-void pciaddr_resource_manage __P((pci_chipset_tag_t, pcitag_t,
- pciaddr_resource_manage_func_t));
-void pciaddr_resource_reserve __P((pci_chipset_tag_t, pcitag_t));
-int pciaddr_do_resource_reserve __P((pci_chipset_tag_t, pcitag_t, int,
- struct extent *, int, bus_addr_t *,
- bus_size_t));
-void pciaddr_resource_allocate __P((pci_chipset_tag_t, pcitag_t));
-int pciaddr_do_resource_allocate __P((pci_chipset_tag_t, pcitag_t, int,
- struct extent *, int, bus_addr_t *,
- bus_size_t));
+ __P((struct pcibios_softc *, pci_chipset_tag_t, pcitag_t, int,
+ struct extent *, int, bus_addr_t *, bus_size_t));
+void pciaddr_resource_manage __P((struct pcibios_softc *,
+ pci_chipset_tag_t, pcitag_t, pciaddr_resource_manage_func_t));
+void pciaddr_resource_reserve __P((struct pcibios_softc *,
+ pci_chipset_tag_t, pcitag_t));
+int pciaddr_do_resource_reserve __P((struct pcibios_softc *,
+ pci_chipset_tag_t, pcitag_t, int, struct extent *, int,
+ bus_addr_t *, bus_size_t));
+void pciaddr_resource_allocate __P((struct pcibios_softc *,
+ pci_chipset_tag_t, pcitag_t));
+int pciaddr_do_resource_allocate __P((struct pcibios_softc *,
+ pci_chipset_tag_t, pcitag_t, int, struct extent *, int, bus_addr_t *,
+ bus_size_t));
bus_addr_t pciaddr_ioaddr __P((u_int32_t));
void pciaddr_print_devid __P((pci_chipset_tag_t, pcitag_t));
@@ -70,12 +70,12 @@ void pciaddr_print_devid __P((pci_chipset_tag_t, pcitag_t));
#define PCIADDR_ISAMEM_RESERVE (16 * 1024 * 1024)
void
-pci_addr_fixup(pc, maxbus)
+pci_addr_fixup(sc, pc, maxbus)
+ struct pcibios_softc *sc;
pci_chipset_tag_t pc;
int maxbus;
{
extern paddr_t avail_end;
-#ifdef PCIBIOSVERBOSE
const char *verbose_header =
"[%s]-----------------------\n"
" device vendor product\n"
@@ -83,7 +83,7 @@ pci_addr_fixup(pc, maxbus)
"--------------------------------------------\n";
const char *verbose_footer =
"--------------------------[%3d devices bogus]\n";
-#endif
+
const struct {
bus_addr_t start;
bus_size_t size;
@@ -97,35 +97,29 @@ pci_addr_fixup(pc, maxbus)
paddr_t start;
int error;
- pciaddr.extent_mem = extent_create("PCI I/O memory space",
- PCIADDR_MEM_START,
- PCIADDR_MEM_END,
- M_DEVBUF, 0, 0, EX_NOWAIT);
- KASSERT(pciaddr.extent_mem);
- pciaddr.extent_port = extent_create("PCI I/O port space",
- PCIADDR_PORT_START,
- PCIADDR_PORT_END,
- M_DEVBUF, 0, 0, EX_NOWAIT);
- KASSERT(pciaddr.extent_port);
+ sc->extent_mem = extent_create("PCI I/O memory space",
+ PCIADDR_MEM_START, PCIADDR_MEM_END, M_DEVBUF, 0, 0, EX_NOWAIT);
+ KASSERT(sc->extent_mem);
+ sc->extent_port = extent_create("PCI I/O port space",
+ PCIADDR_PORT_START, PCIADDR_PORT_END, M_DEVBUF, 0, 0, EX_NOWAIT);
+ KASSERT(sc->extent_port);
/*
* 1. check & reserve system BIOS setting.
*/
PCIBIOS_PRINTV((verbose_header, "System BIOS Setting"));
- pci_device_foreach(pc, maxbus, pciaddr_resource_reserve);
- PCIBIOS_PRINTV((verbose_footer, pciaddr.nbogus));
+ pci_device_foreach(sc, pc, maxbus, pciaddr_resource_reserve);
+ PCIBIOS_PRINTV((verbose_footer, sc->nbogus));
/*
* 2. reserve non-PCI area.
*/
for (srp = system_reserve; srp->size; srp++) {
- error = extent_alloc_region(pciaddr.extent_mem, srp->start,
- srp->size,
- EX_NOWAIT| EX_MALLOCOK);
- if (error != 0) {
+ error = extent_alloc_region(sc->extent_mem, srp->start,
+ srp->size, EX_NOWAIT| EX_MALLOCOK);
+ if (error != 0)
printf("WARNING: can't reserve area for %s.\n",
srp->name);
- }
}
/*
@@ -134,52 +128,49 @@ pci_addr_fixup(pc, maxbus)
start = i386_round_page(avail_end + 1);
if (start < PCIADDR_ISAMEM_RESERVE)
start = PCIADDR_ISAMEM_RESERVE;
- pciaddr.mem_alloc_start = (start + 0x100000 + 1) & ~(0x100000 - 1);
- pciaddr.port_alloc_start = PCIADDR_ISAPORT_RESERVE;
+ sc->mem_alloc_start = (start + 0x100000 + 1) & ~(0x100000 - 1);
+ sc->port_alloc_start = PCIADDR_ISAPORT_RESERVE;
PCIBIOS_PRINTV((" Physical memory end: 0x%08x\n PCI memory mapped I/O "
- "space start: 0x%08x\n", (unsigned)avail_end,
- (unsigned)pciaddr.mem_alloc_start));
+ "space start: 0x%08x\n", avail_end, sc->mem_alloc_start));
- if (pciaddr.nbogus == 0)
+ if (sc->nbogus == 0)
return; /* no need to fixup */
/*
* 4. do fixup
*/
PCIBIOS_PRINTV((verbose_header, "PCIBIOS fixup stage"));
- pciaddr.nbogus = 0;
- /* XXX bus #0 only */
- pci_device_foreach(pc, 0, pciaddr_resource_allocate);
- PCIBIOS_PRINTV((verbose_footer, pciaddr.nbogus));
+ sc->nbogus = 0;
+ pci_device_foreach(sc, pc, maxbus, pciaddr_resource_allocate);
+ PCIBIOS_PRINTV((verbose_footer, sc->nbogus));
}
void
-pciaddr_resource_reserve(pc, tag)
+pciaddr_resource_reserve(sc, pc, tag)
+ struct pcibios_softc *sc;
pci_chipset_tag_t pc;
pcitag_t tag;
{
-#ifdef PCIBIOSVERBOSE
- if (pcibiosverbose)
+ if (pcibios_flags & PCIBIOS_VERBOSE)
pciaddr_print_devid(pc, tag);
-#endif
- pciaddr_resource_manage(pc, tag, pciaddr_do_resource_reserve);
+ pciaddr_resource_manage(sc, pc, tag, pciaddr_do_resource_reserve);
}
void
-pciaddr_resource_allocate(pc, tag)
+pciaddr_resource_allocate(sc, pc, tag)
+ struct pcibios_softc *sc;
pci_chipset_tag_t pc;
pcitag_t tag;
{
-#ifdef PCIBIOSVERBOSE
- if (pcibiosverbose)
+ if (pcibios_flags & PCIBIOS_VERBOSE)
pciaddr_print_devid(pc, tag);
-#endif
- pciaddr_resource_manage(pc, tag, pciaddr_do_resource_allocate);
+ pciaddr_resource_manage(sc, pc, tag, pciaddr_do_resource_allocate);
}
void
-pciaddr_resource_manage(pc, tag, func)
+pciaddr_resource_manage(sc, pc, tag, func)
+ struct pcibios_softc *sc;
pci_chipset_tag_t pc;
pcitag_t tag;
pciaddr_resource_manage_func_t func;
@@ -188,13 +179,13 @@ pciaddr_resource_manage(pc, tag, func)
pcireg_t val, mask;
bus_addr_t addr;
bus_size_t size;
- int error, useport, usemem, mapreg, type, reg_start, reg_end, width;
+ int error, mapreg, type, reg_start, reg_end, width;
val = pci_conf_read(pc, tag, PCI_BHLC_REG);
switch (PCI_HDRTYPE_TYPE(val)) {
default:
printf("WARNING: unknown PCI device header.");
- pciaddr.nbogus++;
+ sc->nbogus++;
return;
case 0:
reg_start = PCI_MAPREG_START;
@@ -209,7 +200,7 @@ pciaddr_resource_manage(pc, tag, func)
reg_end = PCI_MAPREG_PCB_END;
break;
}
- error = useport = usemem = 0;
+ error = 0;
for (mapreg = reg_start; mapreg < reg_end; mapreg += width) {
/* inquire PCI device bus space requirement */
@@ -235,24 +226,21 @@ pciaddr_resource_manage(pc, tag, func)
*/
width = 8;
}
+ addr = PCI_MAPREG_MEM_ADDR(val);
size = PCI_MAPREG_MEM_SIZE(mask);
- ex = pciaddr.extent_mem;
+ ex = sc->extent_mem;
} else {
+ /* XXX some devices give 32bit value */
+ addr = PCI_MAPREG_IO_ADDR(val) & PCIADDR_PORT_END;
size = PCI_MAPREG_IO_SIZE(mask);
- ex = pciaddr.extent_port;
+ ex = sc->extent_port;
}
- addr = pciaddr_ioaddr(val);
if (!size) /* unused register */
continue;
- if (type == PCI_MAPREG_TYPE_MEM)
- ++usemem;
- else
- ++useport;
-
/* reservation/allocation phase */
- error += (*func) (pc, tag, mapreg, ex, type, &addr, size);
+ error += (*func) (sc, pc, tag, mapreg, ex, type, &addr, size);
PCIBIOS_PRINTV(("\t%02xh %s 0x%08x 0x%08x\n",
mapreg, type ? "port" : "mem ",
@@ -270,13 +258,14 @@ pciaddr_resource_manage(pc, tag, func)
pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, val);
if (error)
- pciaddr.nbogus++;
+ sc->nbogus++;
PCIBIOS_PRINTV(("\t\t[%s]\n", error ? "NG" : "OK"));
}
int
-pciaddr_do_resource_allocate(pc, tag, mapreg, ex, type, addr, size)
+pciaddr_do_resource_allocate(sc, pc, tag, mapreg, ex, type, addr, size)
+ struct pcibios_softc *sc;
pci_chipset_tag_t pc;
pcitag_t tag;
struct extent *ex;
@@ -290,8 +279,8 @@ pciaddr_do_resource_allocate(pc, tag, mapreg, ex, type, addr, size)
if (*addr) /* no need to allocate */
return (0);
- start = type == PCI_MAPREG_TYPE_MEM ? pciaddr.mem_alloc_start
- : pciaddr.port_alloc_start;
+ start = (type == PCI_MAPREG_TYPE_MEM ? sc->mem_alloc_start
+ : sc->port_alloc_start);
if (start < ex->ex_start || start + size - 1 >= ex->ex_end) {
PCIBIOS_PRINTV(("No available resources. fixup failed\n"));
return (1);
@@ -306,9 +295,7 @@ pciaddr_do_resource_allocate(pc, tag, mapreg, ex, type, addr, size)
/* write new address to PCI device configuration header */
pci_conf_write(pc, tag, mapreg, *addr);
/* check */
-#ifdef PCIBIOSVERBOSE
- if (!pcibiosverbose)
-#endif
+ if (!pcibios_flags & PCIBIOS_VERBOSE)
{
printf("pci_addr_fixup: ");
pciaddr_print_devid(pc, tag);
@@ -316,19 +303,18 @@ pciaddr_do_resource_allocate(pc, tag, mapreg, ex, type, addr, size)
if (pciaddr_ioaddr(pci_conf_read(pc, tag, mapreg)) != *addr) {
pci_conf_write(pc, tag, mapreg, 0); /* clear */
- printf("fixup failed. (new address=%#x)\n", (unsigned)*addr);
+ printf("fixup failed. (new address=%#x)\n", *addr);
return (1);
}
-#ifdef PCIBIOSVERBOSE
- if (!pcibiosverbose)
-#endif
+ if (!pcibios_flags & PCIBIOS_VERBOSE)
printf("new address 0x%08x\n", *addr);
return (0);
}
int
-pciaddr_do_resource_reserve(pc, tag, mapreg, ex, type, addr, size)
+pciaddr_do_resource_reserve(sc, pc, tag, mapreg, ex, type, addr, size)
+ struct pcibios_softc *sc;
pci_chipset_tag_t pc;
pcitag_t tag;
struct extent *ex;
@@ -357,7 +343,7 @@ pciaddr_ioaddr(val)
{
return ((PCI_MAPREG_TYPE(val) == PCI_MAPREG_TYPE_MEM)
? PCI_MAPREG_MEM_ADDR(val)
- : PCI_MAPREG_IO_ADDR(val));
+ : (PCI_MAPREG_IO_ADDR(val) & PCIADDR_PORT_END));
}
void
@@ -370,7 +356,7 @@ pciaddr_print_devid(pc, tag)
id = pci_conf_read(pc, tag, PCI_ID_REG);
pci_decompose_tag(pc, tag, &bus, &device, &function);
- printf("%03d:%02d:%d 0x%04x 0x%04x ", bus, device, function,
+ printf("%03d:%02d:%d %04x:%04x\n", bus, device, function,
PCI_VENDOR(id), PCI_PRODUCT(id));
}
@@ -380,10 +366,14 @@ pciaddr_search(mem_port, startp, size)
bus_addr_t *startp;
bus_size_t size;
{
+ extern struct cfdriver pcibios_cd;
+ struct pcibios_softc *sc;
+
+ sc = pcibios_cd.cd_devs[0];
+
if (!(pcibios_flags & PCIBIOS_ADDR_FIXUP)) {
struct extent_region *rp;
- struct extent *ex = mem_port?
- pciaddr.extent_mem : pciaddr.extent_port;
+ struct extent *ex = mem_port? sc->extent_mem : sc->extent_port;
/* Search the PCI I/O memory space extent for free
* space that will accomodate size. Remember that the
diff --git a/sys/arch/i386/pci/pci_bus_fixup.c b/sys/arch/i386/pci/pci_bus_fixup.c
index 965ce6dc28a..80e4579cd35 100644
--- a/sys/arch/i386/pci/pci_bus_fixup.c
+++ b/sys/arch/i386/pci/pci_bus_fixup.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_bus_fixup.c,v 1.7 2001/01/24 23:16:14 mickey Exp $ */
+/* $OpenBSD: pci_bus_fixup.c,v 1.8 2001/01/27 04:59:40 mickey Exp $ */
/* $NetBSD: pci_bus_fixup.c,v 1.1 1999/11/17 07:32:58 thorpej Exp $ */
/*
@@ -49,11 +49,8 @@ pci_bus_fixup(pc, bus)
pci_chipset_tag_t pc;
int bus;
{
-#ifdef PCIBIOSVERBOSE
static int bridge_cnt;
- int bridge;
-#endif
- int device, maxdevs, function, nfuncs, bus_max, bus_sub;
+ int bridge, device, maxdevs, function, nfuncs, bus_max, bus_sub;
const struct pci_quirkdata *qd;
pcireg_t reg;
pcitag_t tag;
@@ -119,14 +116,14 @@ pci_bus_fixup(pc, bus)
reg |= bus | (bus_max << 8) | (bus_sub << 16);
pci_conf_write(pc, tag, PPB_REG_BUSINFO, reg);
-#ifdef PCIBIOSVERBOSE
- /* Assign the bridge #. */
- bridge = bridge_cnt++;
+ if (pcibios_flags & PCIBIOS_VERBOSE) {
+ /* Assign the bridge #. */
+ bridge = bridge_cnt++;
- printf("PCI bridge %d: primary %d, "
- "secondary %d, subordinate %d\n",
- bridge, bus, bus_max, bus_sub);
-#endif
+ printf("PCI bridge %d: primary %d, "
+ "secondary %d, subordinate %d\n",
+ bridge, bus, bus_max, bus_sub);
+ }
/* Next bridge's secondary bus #. */
bus_max = (bus_sub > bus_max) ?
diff --git a/sys/arch/i386/pci/pci_intr_fixup.c b/sys/arch/i386/pci/pci_intr_fixup.c
index 4a9bc997305..dd5c6b26760 100644
--- a/sys/arch/i386/pci/pci_intr_fixup.c
+++ b/sys/arch/i386/pci/pci_intr_fixup.c
@@ -1,6 +1,36 @@
-/* $OpenBSD: pci_intr_fixup.c,v 1.11 2001/01/25 00:07:40 mickey Exp $ */
+/* $OpenBSD: pci_intr_fixup.c,v 1.12 2001/01/27 04:59:40 mickey Exp $ */
/* $NetBSD: pci_intr_fixup.c,v 1.10 2000/08/10 21:18:27 soda Exp $ */
+/*
+ * Copyright (c) 2001 Michael Shalayeff
+ * 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 Michael Shalayeff.
+ * 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 OR HIS RELATIVES 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 MIND, 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 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -37,7 +67,6 @@
* 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.
@@ -85,11 +114,8 @@
#include <i386/pci/pcibiosvar.h>
struct pciintr_link_map {
- int link;
- int clink;
- int irq;
+ int link, clink, irq, fixup_stage;
u_int16_t bitmap;
- int fixup_stage;
SIMPLEQ_ENTRY(pciintr_link_map) list;
};
@@ -101,18 +127,8 @@ int pcibios_irqs_hint = PCIBIOS_IRQS_HINT;
#endif
struct pciintr_link_map *pciintr_link_lookup __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));
-static int pciintr_bitmap_count_irq __P((int, int *));
-static int pciintr_bitmap_find_lowest_irq __P((int, int *));
-int pciintr_link_init __P((void));
-int pciintr_guess_irq __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));
-void pciintr_do_header_fixup __P((pci_chipset_tag_t, pcitag_t));
+int pciintr_bitmap_count_irq __P((int, int *));
SIMPLEQ_HEAD(, pciintr_link_map) pciintr_link_map_list;
@@ -139,8 +155,12 @@ const struct pciintr_icu_table {
{ PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82C700,
opti82c700_init },
+ { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C596A,
+ via82c586_init, },
{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C586_ISA,
via82c586_init, },
+ { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C686A_ISA,
+ via82c586_init, },
{ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_85C503,
sis85c503_init },
@@ -160,13 +180,10 @@ pciintr_icu_lookup(id)
{
const struct pciintr_icu_table *piit;
- for (piit = pciintr_icu_table;
- piit->piit_init != NULL;
- 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);
}
@@ -178,18 +195,15 @@ pciintr_link_lookup(link)
struct pciintr_link_map *l;
for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
- l = SIMPLEQ_NEXT(l, list)) {
+ 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;
+static __inline struct pciintr_link_map *
+pciintr_link_alloc(pci_chipset_tag_t pc, struct pcibios_intr_routing *pir, int pin)
{
int link = pir->linkmap[pin].link, clink, irq;
struct pciintr_link_map *l, *lstart;
@@ -204,11 +218,9 @@ pciintr_link_alloc(pir, pin)
* ICU doesn't understand the link value.
* Just ignore this PIR entry.
*/
-#ifdef PCIBIOSVERBOSE
- printf("pciintr_link_alloc: bus %d device %d: "
- "ignoring link 0x%02x\n",
- pir->bus, PIR_DEVFUNC_DEVICE(pir->device), link);
-#endif
+ PCIBIOS_PRINTV(("pciintr_link_alloc: bus %d device %d: "
+ "ignoring link 0x%02x\n", pir->bus,
+ PIR_DEVFUNC_DEVICE(pir->device), link));
return (NULL);
}
@@ -223,18 +235,15 @@ pciintr_link_alloc(pir, pin)
* ICU doesn't understand the canonical link value.
* Just ignore this PIR entry.
*/
-#ifdef PCIBIOSVERBOSE
- printf("pciintr_link_alloc: "
+ PCIBIOS_PRINTV(("pciintr_link_alloc: "
"bus %d device %d link 0x%02x: "
"ignoring PIRQ 0x%02x\n", pir->bus,
- PIR_DEVFUNC_DEVICE(pir->device), link, clink);
-#endif
+ PIR_DEVFUNC_DEVICE(pir->device), link, clink));
return (NULL);
}
}
- l = malloc(sizeof(*l), M_DEVBUF, M_NOWAIT);
- if (l == NULL)
+ if ((l = malloc(sizeof(*l), M_DEVBUF, M_NOWAIT)) == NULL)
return (NULL);
memset(l, 0, sizeof(*l));
@@ -245,7 +254,7 @@ pciintr_link_alloc(pir, pin)
l->clink = clink;
l->irq = irq; /* maybe I386_PCI_INTERRUPT_LINE_NO_CONNECTION */
} else {
- l->clink = link; /* only for PCIBIOSVERBOSE diagnostic */
+ l->clink = link;
l->irq = I386_PCI_INTERRUPT_LINE_NO_CONNECTION;
}
@@ -278,43 +287,25 @@ pciintr_pir_lookup(bus, device)
return (NULL);
}
-static int
+int
pciintr_bitmap_count_irq(irq_bitmap, irqp)
int irq_bitmap, *irqp;
{
int i, bit, count = 0, irq = I386_PCI_INTERRUPT_LINE_NO_CONNECTION;
- if (irq_bitmap != 0) {
- for (i = 0, bit = 1; i < 16; i++, bit <<= 1) {
+ if (irq_bitmap != 0)
+ for (i = 0, bit = 1; i < 16; i++, bit <<= 1)
if (irq_bitmap & bit) {
irq = i;
count++;
}
- }
- }
+
*irqp = irq;
return (count);
}
-static int
-pciintr_bitmap_find_lowest_irq(irq_bitmap, irqp)
- int irq_bitmap, *irqp;
-{
- int i, bit;
-
- if (irq_bitmap != 0) {
- for (i = 0, bit = 1; i < 16; i++, bit <<= 1) {
- if (irq_bitmap & bit) {
- *irqp = i;
- return (1); /* found */
- }
- }
- }
- return (0); /* not found */
-}
-
-int
-pciintr_link_init()
+static __inline int
+pciintr_link_init(pci_chipset_tag_t pc)
{
int entry, pin, link;
struct pcibios_intr_routing *pir;
@@ -331,32 +322,28 @@ pciintr_link_init()
for (entry = 0; entry < pcibios_pir_table_nentries; entry++) {
pir = &pcibios_pir_table[entry];
for (pin = 0; pin < PCI_INTERRUPT_PIN_MAX; pin++) {
- link = pir->linkmap[pin].link;
- if (link == 0) {
+ if ((link = pir->linkmap[pin].link) == 0)
/* No connection for this pin. */
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(link);
- if (l == NULL) {
- (void) pciintr_link_alloc(pir, pin);
- } else if (pir->linkmap[pin].bitmap != l->bitmap) {
+ if ((l = pciintr_link_lookup(link)) == NULL)
+ pciintr_link_alloc(pc, pir, pin);
+ else if (pir->linkmap[pin].bitmap != l->bitmap) {
/*
* violates PCI IRQ Routing Table Specification
*/
-#ifdef PCIBIOSVERBOSE
- printf("pciintr_link_init: "
+ PCIBIOS_PRINTV(("pciintr_link_init: "
"bus %d device %d link 0x%02x: "
"bad irq bitmap 0x%04x, "
- "should be 0x%04x\n",
- pir->bus, PIR_DEVFUNC_DEVICE(pir->device),
- link, pir->linkmap[pin].bitmap, l->bitmap);
-#endif
+ "should be 0x%04x\n", pir->bus,
+ PIR_DEVFUNC_DEVICE(pir->device), link,
+ pir->linkmap[pin].bitmap, l->bitmap));
/* safer value. */
l->bitmap &= pir->linkmap[pin].bitmap;
/* XXX - or, should ignore this entry? */
@@ -371,8 +358,8 @@ pciintr_link_init()
* No compatible PCI ICU found.
* Hopes the BIOS already setup the ICU.
*/
-int
-pciintr_guess_irq()
+static __inline int
+pciintr_guess_irq(void)
{
struct pciintr_link_map *l;
int irq, guessed = 0;
@@ -387,11 +374,10 @@ pciintr_guess_irq()
if (pciintr_bitmap_count_irq(l->bitmap, &irq) == 1) {
l->irq = irq;
l->fixup_stage = 1;
-#ifdef PCIINTR_DEBUG
- printf("pciintr_guess_irq (stage 1): "
- "guessing PIRQ 0x%02x to be IRQ %d\n",
- l->clink, l->irq);
-#endif
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf("pciintr_guess_irq (stage 1): "
+ "guessing PIRQ 0x%02x to be IRQ %d\n",
+ l->clink, l->irq);
guessed = 1;
}
}
@@ -399,12 +385,12 @@ pciintr_guess_irq()
return (guessed ? 0 : -1);
}
-int
-pciintr_link_fixup()
+static __inline int
+pciintr_link_fixup(void)
{
struct pciintr_link_map *l;
- int irq;
u_int16_t pciirq = 0;
+ int irq;
/*
* First stage: Attempt to connect PIRQs which aren't
@@ -419,19 +405,19 @@ pciintr_link_fixup()
* In this case, l->fixup_stage == 0.
*/
pciirq |= 1 << l->irq;
-#ifdef PCIINTR_DEBUG
- printf("pciintr_link_fixup: PIRQ 0x%02x already "
- "connected to IRQ %d\n", l->clink, l->irq);
-#endif
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf("pciintr_link_fixup: PIRQ 0x%02x is "
+ "already connected to IRQ %d\n",
+ l->clink, l->irq);
continue;
}
/*
* Interrupt isn't connected. Attempt to assign it to an IRQ.
*/
-#ifdef PCIINTR_DEBUG
- printf("pciintr_link_fixup: PIRQ 0x%02x not connected",
- l->clink);
-#endif
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf("pciintr_link_fixup: PIRQ 0x%02x not connected",
+ l->clink);
+
/*
* Just do the easy case now; we'll defer the harder ones
* to Stage 2.
@@ -440,13 +426,11 @@ pciintr_link_fixup()
l->irq = irq;
l->fixup_stage = 1;
pciirq |= 1 << irq;
-#ifdef PCIINTR_DEBUG
- printf(", assigning IRQ %d", l->irq);
-#endif
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf(", assigning IRQ %d", l->irq);
}
-#ifdef PCIINTR_DEBUG
- printf("\n");
-#endif
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf("\n");
}
/*
@@ -454,24 +438,21 @@ pciintr_link_fixup()
* connect in Stage 1.
*/
for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
- l = SIMPLEQ_NEXT(l, list)) {
- if (l->irq != I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
- continue;
- if (pciintr_bitmap_find_lowest_irq(l->bitmap & pciirq,
- &l->irq)) {
+ l = SIMPLEQ_NEXT(l, list))
+ if (l->irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION &&
+ (irq = ffs(l->bitmap & pciirq)) > 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->fixup_stage = 2;
-#ifdef PCIINTR_DEBUG
- printf("pciintr_link_fixup (stage 2): "
- "assigning IRQ %d to PIRQ 0x%02x\n",
- l->irq, l->clink);
-#endif
+ l->irq = irq - 1;
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf("pciintr_link_fixup (stage 2): "
+ "assigning IRQ %d to PIRQ 0x%02x\n",
+ l->irq, l->clink);
}
- }
#ifdef PCIBIOS_IRQS_HINT
/*
@@ -480,224 +461,208 @@ pciintr_link_fixup()
*/
for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
l = SIMPLEQ_NEXT(l, list)) {
- if (l->irq != I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
- continue;
- if (pciintr_bitmap_find_lowest_irq(
- l->bitmap & pcibios_irqs_hint, &l->irq)) {
+ if (l->irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION &&
+ (irq = ffs(l->bitmap & pcibios_irqs_hint)) > 0) {
l->fixup_stage = 3;
-#ifdef PCIINTR_DEBUG
- printf("pciintr_link_fixup (stage 3): "
- "assigning IRQ %d to PIRQ 0x%02x\n",
- l->irq, l->clink);
-#endif
+ l->irq = irq - 1;
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf("pciintr_link_fixup (stage 3): "
+ "assigning IRQ %d to PIRQ 0x%02x\n",
+ l->irq, l->clink);
}
}
#endif /* PCIBIOS_IRQS_HINT */
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf("pciintr_link_fixup: piirq 0x%04x\n", pciirq);
+
return (0);
}
int
-pciintr_link_route(pciirq)
- u_int16_t *pciirq;
+pci_intr_route_link(pc, ihp)
+ pci_chipset_tag_t pc;
+ pci_intr_handle_t *ihp;
{
struct pciintr_link_map *l;
- int rv = 0;
+ pcireg_t intr;
+ int rv = 1;
+ char *p = NULL;
- *pciirq = 0;
+ l = ihp->link;
+ if (!l || pciintr_icu_tag == NULL)
+ return (1);
- for (l = SIMPLEQ_FIRST(&pciintr_link_map_list); l != NULL;
- l = SIMPLEQ_NEXT(l, list)) {
- if (l->fixup_stage == 0) {
- if (l->irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
- /* Appropriate interrupt was not found. */
-#ifdef PCIBIOSVERBOSE
- printf("pciintr_link_route: "
- "PIRQ 0x%02x: no IRQ, try "
- "\"options PCIBIOS_IRQS_HINT=0x%04x\"\n",
+ if (l->fixup_stage == 0) {
+ if (l->irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
+ /* Appropriate interrupt was not found. */
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf("pci_intr_route_link: PIRQ 0x%02x: "
+ "no IRQ, try "
+ "\"option PCIBIOS_IRQS_HINT=0x%04x\"\n",
l->clink,
/* suggest irq 9/10/11, if possible */
(l->bitmap & 0x0e00) ? (l->bitmap & 0x0e00)
: l->bitmap);
-#endif
- } else {
- /* BIOS setting has no problem */
-#ifdef PCIINTR_DEBUG
- printf("pciintr_link_route: "
- "route of PIRQ 0x%02x -> "
- "IRQ %d preserved BIOS setting\n",
- l->clink, l->irq);
-#endif
- *pciirq |= (1 << l->irq);
- }
- continue; /* nothing to do. */
- }
+ } else
+ p = " preserved BIOS setting";
+ } else {
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 0x%02x -> "
- "IRQ %d failed\n", l->clink, l->irq);
- rv = 1;
- } else {
- /*
- * Succssfully routed interrupt. Mark this as
- * a PCI interrupt.
- */
- *pciirq |= (1 << l->irq);
- }
+ l->clink, l->irq) != 0 ||
+ pciintr_icu_set_trigger(pciintr_icu_tag, pciintr_icu_handle,
+ l->irq, IST_LEVEL) != 0) {
+ p = " failed";
+ rv = 0;
+ } else
+ p = "";
}
+ if (p && pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf("pci_intr_route_link: route PIRQ 0x%02x -> IRQ %d%s\n",
+ l->clink, l->irq, p);
- return (rv);
-}
+ if (!rv)
+ return (0);
-int
-pciintr_irq_release(pciirq)
- u_int16_t *pciirq;
-{
- int i, bit;
+ /*
+ * IRQs 14 and 15 are reserved for PCI IDE interrupts; don't muck
+ * with them.
+ */
+ if (ihp->line == 14 || ihp->line == 15)
+ return (1);
- for (i = 0, bit = 1; i < 16; i++, bit <<= 1) {
- if ((*pciirq & bit) == 0)
- (void) pciintr_icu_set_trigger(pciintr_icu_tag,
- pciintr_icu_handle, i, IST_EDGE);
+ intr = pci_conf_read(pc, ihp->tag, PCI_INTERRUPT_REG);
+ if (ihp->line != PCI_INTERRUPT_LINE(intr)) {
+ intr &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
+ intr |= (ihp->line << PCI_INTERRUPT_LINE_SHIFT);
+ pci_conf_write(pc, ihp->tag, PCI_INTERRUPT_REG, intr);
}
- return (0);
+ return (1);
}
int
-pciintr_header_fixup(pc)
- pci_chipset_tag_t pc;
+pci_intr_post_fixup()
{
- PCIBIOS_PRINTV(("------------------------------------------\n"));
- PCIBIOS_PRINTV((" device vendor product pin PIRQ IRQ stage\n"));
- PCIBIOS_PRINTV(("------------------------------------------\n"));
- pci_device_foreach(pc, pcibios_max_bus, pciintr_do_header_fixup);
- PCIBIOS_PRINTV(("------------------------------------------\n"));
+ struct pciintr_link_map *l;
+ int i, pciirq;
+
+ if (!pciintr_icu_handle)
+ return 0;
+
+ pciirq = pcibios_pir_header.exclusive_irq;
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf("pci_intr_post_fixup: PCI IRQs:");
+ for (l = SIMPLEQ_FIRST(&pciintr_link_map_list);
+ l != NULL; l = SIMPLEQ_NEXT(l, list))
+ if (l->fixup_stage == 0 &&
+ l->irq != I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf(" %d", l->irq);
+ pciirq |= (1 << l->irq);
+ }
+
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf("; ISA IRQs:");
+ for (i = 0; i < 16; i++)
+ if (!(pciirq & (1 << i))) {
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf(" %d", i);
+ pciintr_icu_set_trigger(pciintr_icu_tag,
+ pciintr_icu_handle, i, IST_EDGE);
+ }
+
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf("\n");
return (0);
}
-void
-pciintr_do_header_fixup(pc, tag)
+int
+pci_intr_header_fixup(pc, tag, ihp)
pci_chipset_tag_t pc;
pcitag_t tag;
+ pci_intr_handle_t *ihp;
{
struct pcibios_intr_routing *pir;
struct pciintr_link_map *l;
- int pin, irq, link;
- int bus, device, function;
- pcireg_t intr, id;
+ int irq, link, bus, device, function;
+ char *p = NULL;
+ irq = ihp->line;
+ ihp->link = NULL;
+ ihp->tag = tag;
pci_decompose_tag(pc, tag, &bus, &device, &function);
- id = pci_conf_read(pc, tag, PCI_ID_REG);
- intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
- pin = PCI_INTERRUPT_PIN(intr);
- irq = PCI_INTERRUPT_LINE(intr);
-
- if (pin == 0) {
- /*
- * No interrupt used.
- */
- return;
+ if ((pir = pciintr_pir_lookup(bus, device)) == NULL ||
+ (link = pir->linkmap[ihp->pin - 1].link) == 0) {
+ PCIBIOS_PRINTV(("Interrupt not connected; no need to change."));
+ return 1;
}
- pir = pciintr_pir_lookup(bus, device);
- if (pir == NULL || (link = pir->linkmap[pin - 1].link) == 0) {
- /*
- * Interrupt not connected; no
- * need to change.
- */
- return;
- }
-
- l = pciintr_link_lookup(link);
- if (l == NULL) {
-#ifdef PCIINTR_DEBUG
+ if ((l = pciintr_link_lookup(link)) == NULL) {
/*
* No link map entry.
* Probably pciintr_icu_getclink() or pciintr_icu_get_intr()
* was failed.
*/
- printf("pciintr_header_fixup: no entry for link 0x%02x "
- "(%d:%d:%d:%c)\n", link, bus, device, function,
- '@' + pin);
-#endif
- return;
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ printf("pci_intr_header_fixup: no entry for link "
+ "0x%02x (%d:%d:%d:%c)\n",
+ link, bus, device, function, '@' + ihp->pin);
+ return 1;
}
-#ifdef PCIBIOSVERBOSE
- if (pcibiosverbose) {
- printf("%03d:%02d:%d 0x%04x 0x%04x %c 0x%02x",
- bus, device, function, PCI_VENDOR(id), PCI_PRODUCT(id),
- '@' + pin, l->clink);
- if (l->irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
- printf(" -");
- else
- printf(" %3d", l->irq);
- printf(" %d ", l->fixup_stage);
- }
-#endif
+ ihp->link = l;
+ if (irq == 14 || irq == 15)
+ p = " WARNING: ignored";
+ else if (l->irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
- /*
- * IRQs 14 and 15 are reserved for PCI IDE interrupts; don't muck
- * with them.
- */
- if (irq == 14 || irq == 15) {
- PCIBIOS_PRINTV((" WARNING: ignored\n"));
- return;
- }
-
- if (l->irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
/* Appropriate interrupt was not found. */
- if (pciintr_icu_tag == NULL &&
- irq != 0 && irq != I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
+ if (pciintr_icu_tag == NULL && ihp->line != 0 &&
+ ihp->line != I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
/*
* Do not print warning,
* if no compatible PCI ICU found,
* but the irq is already assigned by BIOS.
*/
- PCIBIOS_PRINTV(("\n"));
- } else {
- PCIBIOS_PRINTV((" WARNING: missing IRQ\n"));
- }
- return;
- }
+ p = "";
+ else
+ p = " WARNING: missing";
+ } else if (irq == 0 || irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
- if (l->irq == irq) {
- /* don't have to reconfigure */
- PCIBIOS_PRINTV((" already assigned\n"));
- return;
- }
+ p = " fixed up";
+ ihp->line = l->irq;
- if (irq == 0 || irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION) {
- PCIBIOS_PRINTV((" fixed up\n"));
} else {
/* routed by BIOS, but inconsistent */
#ifdef PCIBIOS_INTR_FIXUP_FORCE
/* believe PCI IRQ Routing table */
- PCIBIOS_PRINTV((" WARNING: overriding irq %d\n", irq));
+ p = " WARNING: overriding";
+ ihp->line = l->irq;
#else
/* believe PCI Interrupt Configuration Register (default) */
- PCIBIOS_PRINTV((" WARNING: preserving irq %d\n", irq));
- return;
+ p = " WARNING: preserving";
#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);
+ if (pcibios_flags & PCIBIOS_INTRDEBUG) {
+ register pcireg_t id = pci_conf_read(pc, tag, PCI_ID_REG);
+
+ printf("%d:%d:%d %04x:%04x pin %c clink 0x%02x irq %d stage %d"
+ "%s irq %d\n", bus, device, function,
+ PCI_VENDOR(id), PCI_PRODUCT(id), '@' + ihp->pin, l->clink,
+ ((l->irq == I386_PCI_INTERRUPT_LINE_NO_CONNECTION)?
+ -1 : l->irq), l->fixup_stage, p, irq);
+ }
+
+ return (1);
}
int
-pci_intr_fixup(pc, iot, pciirq)
+pci_intr_fixup(pc, iot)
pci_chipset_tag_t pc;
bus_space_tag_t iot;
- u_int16_t *pciirq;
{
const struct pciintr_icu_table *piit = NULL;
pcitag_t icutag;
@@ -743,8 +708,7 @@ pci_intr_fixup(pc, iot, pciirq)
if (PCI_VENDOR(icuid) == 0)
continue;
- piit = pciintr_icu_lookup(icuid);
- if (piit != NULL)
+ if ((piit = pciintr_icu_lookup(icuid)))
break;
}
}
@@ -756,12 +720,10 @@ pci_intr_fixup(pc, iot, pciirq)
PCI_VENDOR(icuid), PCI_PRODUCT(icuid));
printf("\n");
if (!(pcibios_flags & PCIBIOS_INTR_GUESS)) {
- if (pciintr_link_init())
+ if (pciintr_link_init(pc))
return (-1); /* non-fatal */
if (pciintr_guess_irq())
return (-1); /* non-fatal */
- if (pciintr_header_fixup(pc))
- return (1); /* fatal */
return (0); /* success! */
} else
return (-1); /* non-fatal */
@@ -777,7 +739,7 @@ pci_intr_fixup(pc, iot, pciirq)
/*
* Initialize the PCI interrupt link map.
*/
- if (pciintr_link_init())
+ if (pciintr_link_init(pc))
return (-1); /* non-fatal */
/*
@@ -786,28 +748,5 @@ pci_intr_fixup(pc, iot, pciirq)
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! */
+ return (0);
}
diff --git a/sys/arch/i386/pci/pci_machdep.c b/sys/arch/i386/pci/pci_machdep.c
index 58231fa1032..de242832c0a 100644
--- a/sys/arch/i386/pci/pci_machdep.c
+++ b/sys/arch/i386/pci/pci_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.c,v 1.17 2000/10/25 19:13:12 mickey Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.18 2001/01/27 04:59:40 mickey Exp $ */
/* $NetBSD: pci_machdep.c,v 1.28 1997/06/06 23:29:17 thorpej Exp $ */
/*-
@@ -105,6 +105,11 @@ extern bios_pciinfo_t *bios_pciinfo;
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
+#include "pcibios.h"
+#if NPCIBIOS > 0
+#include <i386/pci/pcibiosvar.h>
+#endif
+
int pci_mode = -1;
#define PCI_MODE1_ENABLE 0x80000000UL
@@ -406,7 +411,6 @@ pci_intr_map(pc, intrtag, pin, line, ihp)
int pin, line;
pci_intr_handle_t *ihp;
{
-
if (pin == 0) {
/* No IRQ used. */
goto bad;
@@ -417,6 +421,13 @@ pci_intr_map(pc, intrtag, pin, line, ihp)
goto bad;
}
+ ihp->line = line;
+ ihp->pin = pin;
+#if NPCIBIOS > 0
+ pci_intr_header_fixup(pc, intrtag, ihp);
+ line = ihp->line;
+#endif
+
/*
* Section 6.2.4, `Miscellaneous Functions', says that 255 means
* `unknown' or `no connection' on a PC. We assume that a device with
@@ -445,11 +456,10 @@ pci_intr_map(pc, intrtag, pin, line, ihp)
}
}
- *ihp = line;
return 0;
bad:
- *ihp = -1;
+ ihp->line = -1;
return 1;
}
@@ -460,10 +470,10 @@ pci_intr_string(pc, ih)
{
static char irqstr[8]; /* 4 + 2 + NULL + sanity */
- if (ih == 0 || ih >= ICU_LEN || ih == 2)
- panic("pci_intr_string: bogus handle 0x%x", ih);
+ if (ih.line == 0 || ih.line >= ICU_LEN || ih.line == 2)
+ panic("pci_intr_string: bogus handle 0x%x", ih.line);
- sprintf(irqstr, "irq %d", ih);
+ sprintf(irqstr, "irq %d", ih.line);
return (irqstr);
}
@@ -476,11 +486,18 @@ pci_intr_establish(pc, ih, level, func, arg, what)
void *arg;
char *what;
{
+ void *ret;
- if (ih == 0 || ih >= ICU_LEN || ih == 2)
- panic("pci_intr_establish: bogus handle 0x%x", ih);
+ if (ih.line == 0 || ih.line >= ICU_LEN || ih.line == 2)
+ panic("pci_intr_establish: bogus handle 0x%x", ih.line);
- return isa_intr_establish(NULL, ih, IST_LEVEL, level, func, arg, what);
+ ret = isa_intr_establish(NULL, ih.line,
+ IST_LEVEL, level, func, arg, what);
+#if NPCIBIOS > 0
+ if (ret)
+ pci_intr_route_link(pc, &ih);
+#endif
+ return ret;
}
void
@@ -488,6 +505,6 @@ pci_intr_disestablish(pc, cookie)
pci_chipset_tag_t pc;
void *cookie;
{
-
+ /* XXX oh, unroute the pci int link? */
return isa_intr_disestablish(NULL, cookie);
}
diff --git a/sys/arch/i386/pci/pci_machdep.h b/sys/arch/i386/pci/pci_machdep.h
index 166c959cb40..a3769766052 100644
--- a/sys/arch/i386/pci/pci_machdep.h
+++ b/sys/arch/i386/pci/pci_machdep.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.h,v 1.6 2000/08/08 19:12:48 mickey Exp $ */
+/* $OpenBSD: pci_machdep.h,v 1.7 2001/01/27 04:59:40 mickey Exp $ */
/* $NetBSD: pci_machdep.h,v 1.7 1997/06/06 23:29:18 thorpej Exp $ */
/*
@@ -62,7 +62,13 @@ extern struct i386_bus_dma_tag pci_bus_dma_tag;
*/
typedef void *pci_chipset_tag_t;
typedef union i386_pci_tag_u pcitag_t;
-typedef int pci_intr_handle_t;
+
+typedef
+struct {
+ pcitag_t tag;
+ int line, pin;
+ void *link;
+} pci_intr_handle_t;
/*
* i386-specific PCI variables and functions.
diff --git a/sys/arch/i386/pci/pcib.c b/sys/arch/i386/pci/pcib.c
index 81785b6044a..be4ef0b37b5 100644
--- a/sys/arch/i386/pci/pcib.c
+++ b/sys/arch/i386/pci/pcib.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcib.c,v 1.7 2000/03/27 08:35:22 brad Exp $ */
+/* $OpenBSD: pcib.c,v 1.8 2001/01/27 04:59:40 mickey Exp $ */
/* $NetBSD: pcib.c,v 1.6 1997/06/06 23:29:16 thorpej Exp $ */
/*-
@@ -51,6 +51,10 @@
#include <dev/pci/pcidevs.h>
#include "isa.h"
+#include "pcibios.h"
+#if NPCIBIOS > 0
+#include <i386/pci/pcibiosvar.h>
+#endif
int pcibmatch __P((struct device *, void *, void *));
void pcibattach __P((struct device *, struct device *, void *));
@@ -115,6 +119,10 @@ pcib_callback(self)
{
struct isabus_attach_args iba;
+#if NPCIBIOS > 0
+ pci_intr_post_fixup();
+#endif
+
/*
* Attach the ISA bus behind this bridge.
*/
diff --git a/sys/arch/i386/pci/pcibios.c b/sys/arch/i386/pci/pcibios.c
index 07f2319b723..38dbb2fd0c3 100644
--- a/sys/arch/i386/pci/pcibios.c
+++ b/sys/arch/i386/pci/pcibios.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcibios.c,v 1.20 2001/01/25 00:07:40 mickey Exp $ */
+/* $OpenBSD: pcibios.c,v 1.21 2001/01/27 04:59:40 mickey Exp $ */
/* $NetBSD: pcibios.c,v 1.5 2000/08/01 05:23:59 uch Exp $ */
/*
@@ -67,7 +67,6 @@
* 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.
@@ -113,24 +112,15 @@
#include <machine/biosvar.h>
-#ifdef PCIBIOSVERBOSE
-int pcibiosverbose = 1;
-#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;
struct bios32_entry_info pcibios_entry_info;
-struct pcibios_softc {
- struct device sc_dev;
-};
-
struct pcibios_intr_routing *pcibios_pir_init __P((struct pcibios_softc *));
int pcibios_get_status __P((struct pcibios_softc *,
@@ -142,9 +132,7 @@ int pcibios_get_intr_routing __P((struct pcibios_softc *,
int pcibios_return_code __P((struct pcibios_softc *, u_int16_t, const char *));
void pcibios_print_exclirq __P((struct pcibios_softc *));
-#ifdef PCIINTR_DEBUG
void pcibios_print_pir_table __P((void));
-#endif
#define PCI_IRQ_TABLE_START 0xf0000
#define PCI_IRQ_TABLE_END 0xfffff
@@ -175,13 +163,9 @@ pcibiosprobe(parent, match, aux)
rv = bios32_service(PCIBIOS_SIGNATURE, &pcibios_entry,
&pcibios_entry_info);
-#ifdef PCIBIOSVERBOSE
- printf("pcibiosprobe: 0x%lx:0x%lx at 0x%lx[0x%lx]\n",
- pcibios_entry.segment,
- pcibios_entry.offset,
- pcibios_entry_info.bei_base,
- pcibios_entry_info.bei_size);
-#endif
+ PCIBIOS_PRINTV(("pcibiosprobe: 0x%lx:0x%lx at 0x%lx[0x%lx]\n",
+ pcibios_entry.segment, pcibios_entry.offset,
+ pcibios_entry_info.bei_base, pcibios_entry_info.bei_size));
return rv &&
pcibios_get_status(NULL, &rev_maj, &rev_min, &mech1, &mech2,
@@ -202,20 +186,16 @@ pcibiosattach(parent, self, aux)
pcibios_get_status((struct pcibios_softc *)self, &rev_maj,
&rev_min, &mech1, &mech2,
- &scmech1, &scmech2, &pcibios_max_bus);
+ &scmech1, &scmech2, &sc->max_bus);
printf(": rev. %d.%d found at 0x%lx[0x%lx]\n",
rev_maj, rev_min >> 4, pcibios_entry_info.bei_base,
pcibios_entry_info.bei_size);
-#ifdef PCIBIOSVERBOSE
- printf("%s: config mechanism %s%s, special cycles %s%s, last bus %d\n",
- sc->sc_dev.dv_xname,
- mech1 ? "[1]" : "[x]",
- mech2 ? "[2]" : "[x]",
- scmech1 ? "[1]" : "[x]",
- scmech2 ? "[2]" : "[x]",
- pcibios_max_bus);
-#endif
+
+ PCIBIOS_PRINTV(("%s: config mechanism %s%s, special cycles %s%s, "
+ "last bus %d\n", sc->sc_dev.dv_xname,
+ mech1 ? "[1]" : "[x]", mech2 ? "[2]" : "[x]",
+ scmech1 ? "[1]" : "[x]", scmech2 ? "[2]" : "[x]", sc->max_bus));
/*
* The PCI BIOS tells us the config mechanism; fill it in now
@@ -232,12 +212,11 @@ pcibiosattach(parent, self, aux)
if (!(pcibios_flags & PCIBIOS_INTR_FIXUP) &&
pcibios_pir_init((struct pcibios_softc *)self) != NULL) {
int rv;
- u_int16_t pciirq;
/*
* Fixup interrupt routing.
*/
- rv = pci_intr_fixup(NULL, I386_BUS_SPACE_IO, &pciirq);
+ rv = pci_intr_fixup(NULL, I386_BUS_SPACE_IO);
switch (rv) {
case -1:
/* Non-fatal error. */
@@ -258,13 +237,13 @@ pcibiosattach(parent, self, aux)
}
if (!(pcibios_flags & PCIBIOS_BUS_FIXUP)) {
- pcibios_max_bus = pci_bus_fixup(NULL, 0);
+ sc->max_bus = pci_bus_fixup(NULL, 0);
printf("%s: PCI bus #%d is the last bus\n",
- sc->sc_dev.dv_xname, pcibios_max_bus);
+ sc->sc_dev.dv_xname, sc->max_bus);
}
if (!(pcibios_flags & PCIBIOS_ADDR_FIXUP))
- pci_addr_fixup(NULL, pcibios_max_bus);
+ pci_addr_fixup(sc, NULL, sc->max_bus);
}
struct pcibios_intr_routing *
@@ -365,9 +344,8 @@ pcibios_pir_init(sc)
}
pcibios_print_exclirq(sc);
-#ifdef PCIINTR_DEBUG
- pcibios_print_pir_table();
-#endif
+ if (pcibios_flags & PCIBIOS_INTRDEBUG)
+ pcibios_print_pir_table();
return pcibios_pir_table;
}
@@ -455,7 +433,7 @@ pcibios_get_intr_routing(sc, table, nentries, exclirq)
return (rv);
*nentries = args.size / sizeof(*table);
- *exclirq = bx;
+ *exclirq |= bx;
return (PCIBIOS_SUCCESS);
}
@@ -533,7 +511,6 @@ pcibios_print_exclirq(sc)
}
}
-#ifdef PCIINTR_DEBUG
void
pcibios_print_pir_table()
{
@@ -552,13 +529,13 @@ pcibios_print_pir_table()
}
}
}
-#endif
void
-pci_device_foreach(pc, maxbus, func)
+pci_device_foreach(sc, pc, maxbus, func)
+ struct pcibios_softc *sc;
pci_chipset_tag_t pc;
int maxbus;
- void (*func) __P((pci_chipset_tag_t, pcitag_t));
+ void (*func) __P((struct pcibios_softc *, pci_chipset_tag_t, pcitag_t));
{
const struct pci_quirkdata *qd;
int bus, device, function, maxdevs, nfuncs;
@@ -602,7 +579,7 @@ pci_device_foreach(pc, maxbus, func)
*/
if (PCI_VENDOR(id) == 0)
continue;
- (*func)(pc, tag);
+ (*func)(sc, pc, tag);
}
}
}
diff --git a/sys/arch/i386/pci/pcibiosvar.h b/sys/arch/i386/pci/pcibiosvar.h
index 9764ea2232e..a74bc33e6f7 100644
--- a/sys/arch/i386/pci/pcibiosvar.h
+++ b/sys/arch/i386/pci/pcibiosvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcibiosvar.h,v 1.5 2001/01/25 01:00:59 mickey Exp $ */
+/* $OpenBSD: pcibiosvar.h,v 1.6 2001/01/27 04:59:40 mickey Exp $ */
/* $NetBSD: pcibios.h,v 1.2 2000/04/28 17:15:16 uch Exp $ */
/*
@@ -12,18 +12,18 @@
* 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.
+ *
+ * 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.
*/
/*
@@ -34,6 +34,8 @@
#define PCIBIOS_BUS_FIXUP 0x002
#define PCIBIOS_INTR_FIXUP 0x004
#define PCIBIOS_INTR_GUESS 0x008
+#define PCIBIOS_VERBOSE 0x010
+#define PCIBIOS_INTRDEBUG 0x020
/*
* PCI BIOS return codes.
@@ -47,6 +49,19 @@
#define PCIBIOS_SET_FAILED 0x88
#define PCIBIOS_BUFFER_TOO_SMALL 0x89
+struct pcibios_softc {
+ struct device sc_dev;
+
+ int max_bus;
+
+ /* address fixup guts */
+ struct extent *extent_mem;
+ struct extent *extent_port;
+ bus_addr_t mem_alloc_start;
+ bus_addr_t port_alloc_start;
+ int nbogus;
+};
+
/*
* PCI IRQ Routing Table definitions.
*/
@@ -93,17 +108,8 @@ 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;
-
-struct pciaddr {
- struct extent *extent_mem;
- struct extent *extent_port;
- bus_addr_t mem_alloc_start;
- bus_addr_t port_alloc_start;
- int nbogus;
-};
-extern struct pciaddr pciaddr;
+int pcibios_flags;
typedef void *pciintr_icu_handle_t;
@@ -128,36 +134,24 @@ typedef const struct pciintr_icu *pciintr_icu_tag_t;
#define pciintr_icu_set_trigger(t, h, irq, trigger) \
(*(t)->pi_set_trigger)((h), (irq), (trigger))
-
-int pcibios_flags;
-
-#ifdef PCIBIOSVERBOSE
-extern int pcibiosverbose;
-
#define PCIBIOS_PRINTV(arg) \
do { \
- if (pcibiosverbose) \
- printf arg; \
- } while (0)
-#define PCIBIOS_PRINTVN(n, arg) \
- do { \
- if (pcibiosverbose > (n)) \
+ if (pcibios_flags & PCIBIOS_VERBOSE) \
printf arg; \
} while (0)
-#else
-#define PCIBIOS_PRINTV(arg)
-#define PCIBIOS_PRINTVN(n, arg)
-#endif
#define PCIADDR_SEARCH_IO 0
#define PCIADDR_SEARCH_MEM 1
struct extent *pciaddr_search __P((int, bus_addr_t *, bus_size_t));
-int pci_intr_fixup __P((pci_chipset_tag_t, bus_space_tag_t, u_int16_t *));
+int pci_intr_fixup __P((pci_chipset_tag_t, bus_space_tag_t));
int pci_bus_fixup __P((pci_chipset_tag_t, int));
-void pci_addr_fixup __P((pci_chipset_tag_t, int));
-void pci_device_foreach __P((pci_chipset_tag_t, int,
- void (*) __P((pci_chipset_tag_t, pcitag_t))));
+void pci_addr_fixup __P((struct pcibios_softc *, pci_chipset_tag_t, int));
+void pci_device_foreach __P((struct pcibios_softc *, pci_chipset_tag_t, int,
+ void (*) __P((struct pcibios_softc *, pci_chipset_tag_t, pcitag_t))));
+int pci_intr_header_fixup __P((pci_chipset_tag_t, pcitag_t, pci_intr_handle_t *));
+int pci_intr_route_link __P((pci_chipset_tag_t, pci_intr_handle_t *));
+int pci_intr_post_fixup __P((void));
/*
* Init functions for our known PCI ICUs.
@@ -174,4 +168,3 @@ int sis85c503_init __P((pci_chipset_tag_t, bus_space_tag_t, pcitag_t,
pciintr_icu_tag_t *, pciintr_icu_handle_t *));
int amd756_init __P((pci_chipset_tag_t, bus_space_tag_t, pcitag_t,
pciintr_icu_tag_t *, pciintr_icu_handle_t *));
-