Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F136869881
D4664.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
17 KB
Referenced Files
None
Subscribers
None
D4664.diff
View Options
Index: sys/arm/arm/ofw_machdep.c
===================================================================
--- sys/arm/arm/ofw_machdep.c
+++ sys/arm/arm/ofw_machdep.c
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2015 Ian Lepore <ian@freebsd.org>
+ * All rights excluded.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_subr.h>
+
+int
+OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
+ bus_space_handle_t *handle)
+{
+ bus_addr_t addr;
+ bus_size_t size;
+ pcell_t pci_hi;
+ int flags, res;
+
+ res = ofw_reg_to_paddr(dev, regno, &addr, &size, &pci_hi);
+ if (res < 0)
+ return (res);
+
+ /*
+ * Nothing special to do for PCI busses right now.
+ * This may need to be handled per-platform when it does come up.
+ */
+#ifdef notyet
+ if (pci_hi == OFW_PADDR_NOT_PCI) {
+ *tag = fdtbus_bs_tag;
+ flags = 0;
+ } else {
+ *tag = fdtbus_bs_tag;
+ flags = (pci_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) ?
+ BUS_SPACE_MAP_PREFETCHABLE: 0;
+ }
+#else
+ *tag = fdtbus_bs_tag;
+ flags = 0;
+#endif
+ return (bus_space_map(*tag, addr, size, flags, handle));
+}
+
Index: sys/arm/include/ofw_machdep.h
===================================================================
--- sys/arm/include/ofw_machdep.h
+++ sys/arm/include/ofw_machdep.h
@@ -32,6 +32,9 @@
#ifndef _MACHINE_OFW_MACHDEP_H_
#define _MACHINE_OFW_MACHDEP_H_
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
#include <vm/vm.h>
typedef uint32_t cell_t;
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -2094,6 +2094,7 @@
dev/ofw/ofw_fdt.c optional fdt
dev/ofw/ofw_if.m optional fdt
dev/ofw/ofw_iicbus.c optional fdt iicbus
+dev/ofw/ofw_subr.c optional fdt
dev/ofw/ofwbus.c optional fdt
dev/ofw/openfirm.c optional fdt
dev/ofw/openfirmio.c optional fdt
Index: sys/conf/files.arm
===================================================================
--- sys/conf/files.arm
+++ sys/conf/files.arm
@@ -55,6 +55,7 @@
arm/arm/mp_machdep.c optional smp
arm/arm/mpcore_timer.c optional mpcore_timer
arm/arm/nexus.c standard
+arm/arm/ofw_machdep.c optional fdt
arm/arm/physmem.c standard
kern/pic_if.m optional arm_intrng
arm/arm/pl190.c optional pl190
Index: sys/conf/files.powerpc
===================================================================
--- sys/conf/files.powerpc
+++ sys/conf/files.powerpc
@@ -58,6 +58,7 @@
dev/ofw/ofw_iicbus.c optional iicbus aim
dev/ofw/ofwbus.c optional aim | fdt
dev/ofw/ofw_standard.c optional aim powerpc
+dev/ofw/ofw_subr.c optional aim powerpc
dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac
dev/quicc/quicc_bfe_fdt.c optional quicc mpc85xx
dev/scc/scc_bfe_macio.c optional scc powermac
Index: sys/dev/ofw/ofw_subr.h
===================================================================
--- sys/dev/ofw/ofw_subr.h
+++ sys/dev/ofw/ofw_subr.h
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2015 Ian Lepore <ian@freebsd.org>
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DEV_OFW_OFW_SUBR_H_
+#define _DEV_OFW_OFW_SUBR_H_
+
+/*
+ * Translate an address from the Nth tuple of a device node's reg properties to
+ * a physical memory address, by applying the range mappings from all ancestors.
+ * This assumes that all ancestor ranges are simple numerical offsets for which
+ * addition and subtraction operations will perform the required mapping (the
+ * bit-options in the high word of standard PCI properties are also handled).
+ * After the call, *pci_hi (if non-NULL) contains the phys.hi cell of the
+ * device's parent PCI bus, or OFW_PADDR_NOT_PCI if no PCI bus is involved.
+ *
+ * This is intended to be a helper function called by the platform-specific
+ * implementation of OF_decode_addr(), and not for direct use by device drivers.
+ */
+#define OFW_PADDR_NOT_PCI (~0)
+
+int ofw_reg_to_paddr(phandle_t _dev, int _regno, bus_addr_t *_paddr,
+ bus_size_t *_size, pcell_t *_pci_hi);
+
+#endif
Index: sys/dev/ofw/ofw_subr.c
===================================================================
--- sys/dev/ofw/ofw_subr.c
+++ sys/dev/ofw/ofw_subr.c
@@ -0,0 +1,173 @@
+/*-
+ * Copyright (c) 2015 Ian Lepore <ian@freebsd.org>
+ * All rights excluded.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/libkern.h>
+
+#include <machine/bus.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_subr.h>
+
+static void
+get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep, int *pcip)
+{
+ char type[64];
+ uint32_t addr, size;
+ int pci, res;
+
+ res = OF_getencprop(node, "#address-cells", &addr, sizeof(addr));
+ if (res == -1)
+ addr = 2;
+ res = OF_getencprop(node, "#size-cells", &size, sizeof(size));
+ if (res == -1)
+ size = 1;
+ pci = 0;
+ if (addr == 3 && size == 2) {
+ res = OF_getprop(node, "device_type", type, sizeof(type));
+ if (res != -1) {
+ type[sizeof(type) - 1] = '\0';
+ pci = (strcmp(type, "pci") == 0) ? 1 : 0;
+ }
+ }
+ if (addrp != NULL)
+ *addrp = addr;
+ if (sizep != NULL)
+ *sizep = size;
+ if (pcip != NULL)
+ *pcip = pci;
+}
+
+int
+ofw_reg_to_paddr(phandle_t dev, int regno, bus_addr_t *paddr,
+ bus_size_t *psize, pcell_t *ppci_hi)
+{
+ pcell_t cell[32], pci_hi;
+ bus_addr_t addr, raddr, baddr;
+ bus_size_t size, rsize;
+ uint32_t c, nbridge, naddr, nsize;
+ phandle_t bridge, parent;
+ u_int spc, rspc;
+ int pci, pcib, res;
+
+ /* Sanity checking. */
+ if (dev == 0)
+ return (EINVAL);
+ bridge = OF_parent(dev);
+ if (bridge == 0)
+ return (EINVAL);
+ if (regno < 0)
+ return (EINVAL);
+ if (paddr == NULL || psize == NULL)
+ return (EINVAL);
+
+ get_addr_props(bridge, &naddr, &nsize, &pci);
+ res = OF_getencprop(dev, (pci) ? "assigned-addresses" : "reg",
+ cell, sizeof(cell));
+ if (res == -1)
+ return (ENXIO);
+ if (res % sizeof(cell[0]))
+ return (ENXIO);
+ res /= sizeof(cell[0]);
+ regno *= naddr + nsize;
+ if (regno + naddr + nsize > res)
+ return (EINVAL);
+ pci_hi = pci ? cell[regno] : OFW_PADDR_NOT_PCI;
+ spc = pci_hi & OFW_PCI_PHYS_HI_SPACEMASK;
+ addr = 0;
+ for (c = 0; c < naddr; c++)
+ addr = ((uint64_t)addr << 32) | cell[regno++];
+ size = 0;
+ for (c = 0; c < nsize; c++)
+ size = ((uint64_t)size << 32) | cell[regno++];
+ /*
+ * Map the address range in the bridge's decoding window as given
+ * by the "ranges" property. If a node doesn't have such property
+ * or the property is empty, we assume an identity mapping. The
+ * standard says a missing property indicates no possible mapping.
+ * This code is more liberal since the intended use is to get a
+ * console running early, and a printf to warn of malformed data
+ * is probably futile before the console is fully set up.
+ */
+ parent = OF_parent(bridge);
+ while (parent != 0) {
+ get_addr_props(parent, &nbridge, NULL, &pcib);
+ res = OF_getencprop(bridge, "ranges", cell, sizeof(cell));
+ if (res < 1)
+ goto next;
+ if (res % sizeof(cell[0]))
+ return (ENXIO);
+ /* Capture pci_hi if we just transitioned onto a PCI bus. */
+ if (pcib && pci_hi == OFW_PADDR_NOT_PCI) {
+ pci_hi = cell[0];
+ spc = pci_hi & OFW_PCI_PHYS_HI_SPACEMASK;
+ }
+ res /= sizeof(cell[0]);
+ regno = 0;
+ while (regno < res) {
+ rspc = (pci)
+ ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK
+ : OFW_PADDR_NOT_PCI;
+ if (rspc != spc) {
+ regno += naddr + nbridge + nsize;
+ continue;
+ }
+ raddr = 0;
+ for (c = 0; c < naddr; c++)
+ raddr = ((uint64_t)raddr << 32) | cell[regno++];
+ rspc = (pcib)
+ ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK
+ : OFW_PADDR_NOT_PCI;
+ baddr = 0;
+ for (c = 0; c < nbridge; c++)
+ baddr = ((uint64_t)baddr << 32) | cell[regno++];
+ rsize = 0;
+ for (c = 0; c < nsize; c++)
+ rsize = ((uint64_t)rsize << 32) | cell[regno++];
+ if (addr < raddr || addr >= raddr + rsize)
+ continue;
+ addr = addr - raddr + baddr;
+ if (rspc != OFW_PADDR_NOT_PCI)
+ spc = rspc;
+ }
+ next:
+ bridge = parent;
+ parent = OF_parent(bridge);
+ get_addr_props(bridge, &naddr, &nsize, &pci);
+ }
+
+ *paddr = addr;
+ *psize = size;
+ if (ppci_hi != NULL)
+ *ppci_hi = pci_hi;
+
+ return (0);
+}
Index: sys/dev/ofw/openfirm.h
===================================================================
--- sys/dev/ofw/openfirm.h
+++ sys/dev/ofw/openfirm.h
@@ -167,5 +167,16 @@
/* User interface functions */
int OF_interpret(const char *cmd, int nreturns, ...);
+/*
+ * Decode the Nth register property of the given device node and create a bus
+ * space tag and handle for accessing it. This is for use in setting up things
+ * like early console output before newbus is available. The implementation is
+ * machine-dependent, and sparc uses a different function signature as well.
+ */
+#ifndef __sparc64__
+int OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *ptag,
+ bus_space_handle_t *phandle);
+#endif
+
#endif /* _KERNEL */
#endif /* _DEV_OPENFIRM_H_ */
Index: sys/powerpc/include/ofw_machdep.h
===================================================================
--- sys/powerpc/include/ofw_machdep.h
+++ sys/powerpc/include/ofw_machdep.h
@@ -37,7 +37,6 @@
typedef uint32_t cell_t;
-int OF_decode_addr(phandle_t, int, bus_space_tag_t *, bus_space_handle_t *);
void OF_getetheraddr(device_t dev, u_char *addr);
void OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *));
Index: sys/powerpc/ofw/ofw_machdep.c
===================================================================
--- sys/powerpc/ofw/ofw_machdep.c
+++ sys/powerpc/ofw/ofw_machdep.c
@@ -52,6 +52,7 @@
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_subr.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -565,135 +566,28 @@
* register in the address space of its parent and recursively walk
* the device tree upward this way.
*/
-static void
-OF_get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep, int *pcip)
-{
- char type[64];
- uint32_t addr, size;
- int pci, res;
-
- res = OF_getencprop(node, "#address-cells", &addr, sizeof(addr));
- if (res == -1)
- addr = 2;
- res = OF_getencprop(node, "#size-cells", &size, sizeof(size));
- if (res == -1)
- size = 1;
- pci = 0;
- if (addr == 3 && size == 2) {
- res = OF_getprop(node, "device_type", type, sizeof(type));
- if (res != -1) {
- type[sizeof(type) - 1] = '\0';
- pci = (strcmp(type, "pci") == 0) ? 1 : 0;
- }
- }
- if (addrp != NULL)
- *addrp = addr;
- if (sizep != NULL)
- *sizep = size;
- if (pcip != NULL)
- *pcip = pci;
-}
-
int
OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
bus_space_handle_t *handle)
{
- uint32_t cell[32];
- bus_addr_t addr, raddr, baddr;
- bus_size_t size, rsize;
- uint32_t c, nbridge, naddr, nsize;
- phandle_t bridge, parent;
- u_int spc, rspc, prefetch;
- int pci, pcib, res;
-
- /* Sanity checking. */
- if (dev == 0)
- return (EINVAL);
- bridge = OF_parent(dev);
- if (bridge == 0)
- return (EINVAL);
- if (regno < 0)
- return (EINVAL);
- if (tag == NULL || handle == NULL)
- return (EINVAL);
-
- /* Assume big-endian unless we find a PCI device */
- *tag = &bs_be_tag;
-
- /* Get the requested register. */
- OF_get_addr_props(bridge, &naddr, &nsize, &pci);
- if (pci)
+ bus_addr_t addr;
+ bus_size_t size;
+ pcell_t pci_hi;
+ int flags, res;
+
+ res = ofw_reg_to_paddr(dev, regno, &addr, &size, &pci_hi);
+ if (res < 0)
+ return (res);
+
+ if (pci_hi == OFW_PADDR_NOT_PCI) {
+ *tag = &bs_be_tag;
+ flags = 0;
+ } else {
*tag = &bs_le_tag;
- res = OF_getencprop(dev, (pci) ? "assigned-addresses" : "reg",
- cell, sizeof(cell));
- if (res == -1)
- return (ENXIO);
- if (res % sizeof(cell[0]))
- return (ENXIO);
- res /= sizeof(cell[0]);
- regno *= naddr + nsize;
- if (regno + naddr + nsize > res)
- return (EINVAL);
- spc = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK : ~0;
- prefetch = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_PREFETCHABLE : 0;
- addr = 0;
- for (c = 0; c < naddr; c++)
- addr = ((uint64_t)addr << 32) | cell[regno++];
- size = 0;
- for (c = 0; c < nsize; c++)
- size = ((uint64_t)size << 32) | cell[regno++];
-
- /*
- * Map the address range in the bridge's decoding window as given
- * by the "ranges" property. If a node doesn't have such property
- * then no mapping is done.
- */
- parent = OF_parent(bridge);
- while (parent != 0) {
- OF_get_addr_props(parent, &nbridge, NULL, &pcib);
- if (pcib)
- *tag = &bs_le_tag;
- res = OF_getencprop(bridge, "ranges", cell, sizeof(cell));
- if (res == -1)
- goto next;
- if (res % sizeof(cell[0]))
- return (ENXIO);
- res /= sizeof(cell[0]);
- regno = 0;
- while (regno < res) {
- rspc = (pci)
- ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK
- : ~0;
- if (rspc != spc) {
- regno += naddr + nbridge + nsize;
- continue;
- }
- raddr = 0;
- for (c = 0; c < naddr; c++)
- raddr = ((uint64_t)raddr << 32) | cell[regno++];
- rspc = (pcib)
- ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK
- : ~0;
- baddr = 0;
- for (c = 0; c < nbridge; c++)
- baddr = ((uint64_t)baddr << 32) | cell[regno++];
- rsize = 0;
- for (c = 0; c < nsize; c++)
- rsize = ((uint64_t)rsize << 32) | cell[regno++];
- if (addr < raddr || addr >= raddr + rsize)
- continue;
- addr = addr - raddr + baddr;
- if (rspc != ~0)
- spc = rspc;
- }
-
- next:
- bridge = parent;
- parent = OF_parent(bridge);
- OF_get_addr_props(bridge, &naddr, &nsize, &pci);
+ flags = (pci_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) ?
+ BUS_SPACE_MAP_PREFETCHABLE: 0;
}
- return (bus_space_map(*tag, addr, size,
- prefetch ? BUS_SPACE_MAP_PREFETCHABLE : 0, handle));
+ return (bus_space_map(*tag, addr, size, flags, handle));
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 21, 6:38 AM (12 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25754492
Default Alt Text
D4664.diff (17 KB)
Attached To
Mode
D4664: Implement OF_decode_addr() for arm. Move most of powerpc's implementation into a new function that other platforms can share.
Attached
Detach File
Event Timeline
Log In to Comment