summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2006-07-13 18:02:19 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2006-07-13 18:02:19 +0000
commitbd9cebb8b30f438d9adee25b85f18aaa3550285b (patch)
tree4d0cb9302ddd48da5d941b610abb1871f1a74765
parent6806fcdcac8ff3a90690c8a30897b4bd20e44a16 (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.c83
-rw-r--r--sys/arch/macppc/pci/pci_addr_fixup.c75
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) {