diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2006-07-13 18:02:19 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2006-07-13 18:02:19 +0000 |
commit | bd9cebb8b30f438d9adee25b85f18aaa3550285b (patch) | |
tree | 4d0cb9302ddd48da5d941b610abb1871f1a74765 | |
parent | 6806fcdcac8ff3a90690c8a30897b4bd20e44a16 (diff) |
Switch to a three-phase pci resource fixup:
1. Reserve resources for enabled devices.
2. Reserve resources for disabled devices.
3. Allocate resources.
This way we no longer need to enable/disable devices during fixup.
Based on an earlier patch by drahn@.
ok deraadt@, drahn@
-rw-r--r-- | sys/arch/i386/pci/pci_addr_fixup.c | 83 | ||||
-rw-r--r-- | sys/arch/macppc/pci/pci_addr_fixup.c | 75 |
2 files changed, 125 insertions, 33 deletions
diff --git a/sys/arch/i386/pci/pci_addr_fixup.c b/sys/arch/i386/pci/pci_addr_fixup.c index d6721f6aeb7..04e9aa216f6 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.17 2006/04/27 15:37:55 mickey Exp $ */ +/* $OpenBSD: pci_addr_fixup.c,v 1.18 2006/07/13 18:02:18 kettenis Exp $ */ /* $NetBSD: pci_addr_fixup.c,v 1.7 2000/08/03 20:10:45 nathanw Exp $ */ /*- @@ -50,8 +50,13 @@ void pciaddr_resource_manage(struct pcibios_softc *, pci_chipset_tag_t, pcitag_t, pciaddr_resource_manage_func_t); void pciaddr_resource_reserve(struct pcibios_softc *, pci_chipset_tag_t, pcitag_t); +void pciaddr_resource_reserve_disabled(struct pcibios_softc *, + pci_chipset_tag_t, pcitag_t); int pciaddr_do_resource_reserve(struct pcibios_softc *, pci_chipset_tag_t, pcitag_t, int, struct extent *, int, u_long *, bus_size_t); +int pciaddr_do_resource_reserve_disabled(struct pcibios_softc *, + pci_chipset_tag_t, pcitag_t, int, struct extent *, int, u_long *, + bus_size_t); void pciaddr_resource_allocate(struct pcibios_softc *, pci_chipset_tag_t, pcitag_t); int pciaddr_do_resource_allocate(struct pcibios_softc *, pci_chipset_tag_t, @@ -110,6 +115,7 @@ pci_addr_fixup(sc, pc, maxbus) */ PCIBIOS_PRINTV((verbose_header, "System BIOS Setting")); pci_device_foreach(sc, pc, maxbus, pciaddr_resource_reserve); + pci_device_foreach(sc, pc, maxbus, pciaddr_resource_reserve_disabled); PCIBIOS_PRINTV((verbose_footer, sc->nbogus)); /* @@ -134,9 +140,6 @@ pci_addr_fixup(sc, pc, maxbus) PCIBIOS_PRINTV((" Physical memory end: 0x%08x\n PCI memory mapped I/O " "space start: 0x%08x\n", avail_end, sc->mem_alloc_start)); - if (sc->nbogus == 0) - return; /* no need to fixup */ - /* * 4. do fixup */ @@ -155,7 +158,19 @@ pciaddr_resource_reserve(sc, pc, tag) { if (pcibios_flags & PCIBIOS_VERBOSE) pciaddr_print_devid(pc, tag); - pciaddr_resource_manage(sc, pc, tag, pciaddr_do_resource_reserve); + pciaddr_resource_manage(sc, pc, tag, pciaddr_do_resource_reserve); +} + +void +pciaddr_resource_reserve_disabled(sc, pc, tag) + struct pcibios_softc *sc; + pci_chipset_tag_t pc; + pcitag_t tag; +{ + if (pcibios_flags & PCIBIOS_VERBOSE) + pciaddr_print_devid(pc, tag); + pciaddr_resource_manage(sc, pc, tag, + pciaddr_do_resource_reserve_disabled); } void @@ -247,17 +262,7 @@ pciaddr_resource_manage(sc, pc, tag, func) mapreg, type ? "port" : "mem ", (unsigned int)addr, (unsigned int)size)); } - - /* enable/disable PCI device */ - val = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); - if (error == 0) - val |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | - PCI_COMMAND_MASTER_ENABLE); - else - val &= ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | - PCI_COMMAND_MASTER_ENABLE); - pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, val); - + if (error) sc->nbogus++; @@ -325,10 +330,56 @@ pciaddr_do_resource_reserve(sc, pc, tag, mapreg, ex, type, addr, size) u_long *addr; bus_size_t size; { + pcireg_t val; int error; if (*addr == 0) + return (0); + + val = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); + if (type == PCI_MAPREG_TYPE_MEM && + (val & PCI_COMMAND_MEM_ENABLE) != PCI_COMMAND_MEM_ENABLE) + return (0); + if (type == PCI_MAPREG_TYPE_IO && + (val & PCI_COMMAND_IO_ENABLE) != PCI_COMMAND_IO_ENABLE) + return (0); + + error = extent_alloc_region(ex, *addr, size, EX_NOWAIT | EX_MALLOCOK); + if (error) { + PCIBIOS_PRINTV(("Resource conflict.\n")); + pci_conf_write(pc, tag, mapreg, 0); /* clear */ return (1); + } + + return (0); +} + +int +pciaddr_do_resource_reserve_disabled(sc, pc, tag, mapreg, ex, type, addr, size) + struct pcibios_softc *sc; + pci_chipset_tag_t pc; + pcitag_t tag; + struct extent *ex; + int type, mapreg; + u_long *addr; + bus_size_t size; +{ + pcireg_t val; + int error; + + if (*addr == 0) + return (0); + + val = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); + if (type == PCI_MAPREG_TYPE_MEM && + (val & PCI_COMMAND_MEM_ENABLE) == PCI_COMMAND_MEM_ENABLE) + return (0); + if (type == PCI_MAPREG_TYPE_IO && + (val & PCI_COMMAND_IO_ENABLE) == PCI_COMMAND_IO_ENABLE) + return (0); + + PCIBIOS_PRINTV(("disabled %s space at addr 0x%x size 0x%x\n", + type == PCI_MAPREG_TYPE_MEM ? "mem" : "io", *addr, size)); error = extent_alloc_region(ex, *addr, size, EX_NOWAIT | EX_MALLOCOK); if (error) { diff --git a/sys/arch/macppc/pci/pci_addr_fixup.c b/sys/arch/macppc/pci/pci_addr_fixup.c index 37c15342aa3..77a989d223f 100644 --- a/sys/arch/macppc/pci/pci_addr_fixup.c +++ b/sys/arch/macppc/pci/pci_addr_fixup.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_addr_fixup.c,v 1.9 2003/12/20 22:40:27 miod Exp $ */ +/* $OpenBSD: pci_addr_fixup.c,v 1.10 2006/07/13 18:02:18 kettenis Exp $ */ /* $NetBSD: pci_addr_fixup.c,v 1.7 2000/08/03 20:10:45 nathanw Exp $ */ /*- @@ -50,9 +50,14 @@ void pciaddr_resource_manage(struct pcibr_softc *, pci_chipset_tag_t, pcitag_t, pciaddr_resource_manage_func_t); void pciaddr_resource_reserve(struct pcibr_softc *, pci_chipset_tag_t, pcitag_t); +void pciaddr_resource_reserve_disabled(struct pcibr_softc *, + pci_chipset_tag_t, pcitag_t); int pciaddr_do_resource_reserve(struct pcibr_softc *, pci_chipset_tag_t, pcitag_t, int, struct extent *, int, bus_addr_t *, bus_size_t); +int pciaddr_do_resource_reserve_disabled(struct pcibr_softc *, + pci_chipset_tag_t, pcitag_t, int, struct extent *, int, + bus_addr_t *, bus_size_t); void pciaddr_resource_allocate(struct pcibr_softc *, pci_chipset_tag_t, pcitag_t); int pciaddr_do_resource_allocate(struct pcibr_softc *, @@ -72,7 +77,7 @@ void pci_device_foreach(struct pcibr_softc *sc, pci_chipset_tag_t pc, #define PCIADDR_PORT_START 0x0 #define PCIADDR_PORT_END 0xffff -int pcibr_flags = 0; +int pcibr_flags = 1; #define PCIBR_VERBOSE 1 #define PCIBR_ADDR_FIXUP 2 @@ -105,6 +110,7 @@ pci_addr_fixup(struct pcibr_softc *sc, pci_chipset_tag_t pc, int maxbus) */ PCIBIOS_PRINTV((verbose_header, "System BIOS Setting")); pci_device_foreach(sc, pc, maxbus, pciaddr_resource_reserve); + pci_device_foreach(sc, pc, maxbus, pciaddr_resource_reserve_disabled); PCIBIOS_PRINTV((verbose_footer, sc->nbogus)); { @@ -122,9 +128,6 @@ pci_addr_fixup(struct pcibr_softc *sc, pci_chipset_tag_t pc, int maxbus) } } - if (sc->nbogus == 0) - return; /* no need to fixup */ - /* * 4. do fixup */ @@ -141,7 +144,17 @@ pciaddr_resource_reserve(struct pcibr_softc *sc, pci_chipset_tag_t pc, { if (pcibr_flags & PCIBR_VERBOSE) pciaddr_print_devid(pc, tag); - pciaddr_resource_manage(sc, pc, tag, pciaddr_do_resource_reserve); + pciaddr_resource_manage(sc, pc, tag, pciaddr_do_resource_reserve); +} + +void +pciaddr_resource_reserve_disabled(struct pcibr_softc *sc, + pci_chipset_tag_t pc, pcitag_t tag) +{ + if (pcibr_flags & PCIBR_VERBOSE) + pciaddr_print_devid(pc, tag); + pciaddr_resource_manage(sc, pc, tag, + pciaddr_do_resource_reserve_disabled); } void @@ -228,17 +241,7 @@ pciaddr_resource_manage(struct pcibr_softc *sc, pci_chipset_tag_t pc, mapreg, type ? "port" : "mem ", (unsigned int)addr, (unsigned int)size)); } - - /* enable/disable PCI device */ - val = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); - if (error == 0) - val |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | - PCI_COMMAND_MASTER_ENABLE); - else - val &= ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | - PCI_COMMAND_MASTER_ENABLE); - pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, val); - + if (error) sc->nbogus++; @@ -297,10 +300,48 @@ pciaddr_do_resource_reserve(struct pcibr_softc *sc, pci_chipset_tag_t pc, pcitag_t tag, int mapreg, struct extent *ex, int type, bus_addr_t *addr, bus_size_t size) { + pcireg_t val; int error; if (*addr == 0) + return (0); + + val = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); + if (type == PCI_MAPREG_TYPE_MEM && + (val & PCI_COMMAND_MEM_ENABLE) != PCI_COMMAND_MEM_ENABLE) + return (0); + if (type == PCI_MAPREG_TYPE_IO && + (val & PCI_COMMAND_IO_ENABLE) != PCI_COMMAND_IO_ENABLE) + return (0); + + error = extent_alloc_region(ex, *addr, size, EX_NOWAIT | EX_MALLOCOK); + if (error) { + PCIBIOS_PRINTV(("Resource conflict.\n")); + pci_conf_write(pc, tag, mapreg, 0); /* clear */ return (1); + } + + return (0); +} + +int +pciaddr_do_resource_reserve_disabled(struct pcibr_softc *sc, + pci_chipset_tag_t pc, pcitag_t tag, int mapreg, struct extent *ex, + int type, bus_addr_t *addr, bus_size_t size) +{ + pcireg_t val; + int error; + + if (*addr == 0) + return (0); + + val = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); + if (type == PCI_MAPREG_TYPE_MEM && + (val & PCI_COMMAND_MEM_ENABLE) == PCI_COMMAND_MEM_ENABLE) + return (0); + if (type == PCI_MAPREG_TYPE_IO && + (val & PCI_COMMAND_IO_ENABLE) == PCI_COMMAND_IO_ENABLE) + return (0); error = extent_alloc_region(ex, *addr, size, EX_NOWAIT | EX_MALLOCOK); if (error) { |