diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/i386/pci/pci_addr_fixup.c | 156 | ||||
-rw-r--r-- | sys/arch/i386/pci/pci_bus_fixup.c | 21 | ||||
-rw-r--r-- | sys/arch/i386/pci/pci_intr_fixup.c | 511 | ||||
-rw-r--r-- | sys/arch/i386/pci/pci_machdep.c | 39 | ||||
-rw-r--r-- | sys/arch/i386/pci/pci_machdep.h | 10 | ||||
-rw-r--r-- | sys/arch/i386/pci/pcib.c | 10 | ||||
-rw-r--r-- | sys/arch/i386/pci/pcibios.c | 65 | ||||
-rw-r--r-- | sys/arch/i386/pci/pcibiosvar.h | 81 |
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 *)); - |