diff options
author | Mark A. Greer <mgreer@mvista.com> | 2007-04-28 06:48:24 +1000 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-04-30 11:02:05 +1000 |
commit | 8895ea483e144f8acca16adfff7c60a993e77b7d (patch) | |
tree | 66e22bad0ca4e2c1d6d57aa1db925deafc744bd9 /arch | |
parent | d818d7ec8bb06c1bc10270962e28fb0cbd93b64a (diff) |
[POWERPC] Add dt_xlate_addr() to bootwrapper
dt_xlate_reg() looks up the 'reg' property in the specified node
to get the address and size to translate. Add dt_xlate_addr()
which is passed in the address and size to translate.
Signed-off-by: Mark A. Greer <mgreer@mvista.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/boot/devtree.c | 47 | ||||
-rw-r--r-- | arch/powerpc/boot/ops.h | 4 |
2 files changed, 35 insertions, 16 deletions
diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c index ac4b5ee92d5..c9951550ed2 100644 --- a/arch/powerpc/boot/devtree.c +++ b/arch/powerpc/boot/devtree.c @@ -207,12 +207,13 @@ static int find_range(u32 *reg, u32 *ranges, int nregaddr, * In particular, PCI is not supported. Also, only the beginning of the * reg block is tracked; size is ignored except in ranges. */ -int dt_xlate_reg(void *node, int res, unsigned long *addr, - unsigned long *size) +static u32 dt_xlate_buf[MAX_ADDR_CELLS * MAX_RANGES * 3]; + +static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, + unsigned long *size) { u32 last_addr[MAX_ADDR_CELLS]; u32 this_addr[MAX_ADDR_CELLS]; - u32 buf[MAX_ADDR_CELLS * MAX_RANGES * 3]; void *parent; u64 ret_addr, ret_size; u32 naddr, nsize, prev_naddr; @@ -227,19 +228,18 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, if (nsize > 2) return 0; - buflen = getprop(node, "reg", buf, sizeof(buf)) / 4; offset = (naddr + nsize) * res; - if (buflen < offset + naddr + nsize || - sizeof(buf) < offset + naddr + nsize) + if (reglen < offset + naddr + nsize || + sizeof(dt_xlate_buf) < offset + naddr + nsize) return 0; - copy_val(last_addr, buf + offset, naddr); + copy_val(last_addr, dt_xlate_buf + offset, naddr); - ret_size = buf[offset + naddr]; + ret_size = dt_xlate_buf[offset + naddr]; if (nsize == 2) { ret_size <<= 32; - ret_size |= buf[offset + naddr + 1]; + ret_size |= dt_xlate_buf[offset + naddr + 1]; } while ((node = get_parent(node))) { @@ -247,24 +247,25 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, get_reg_format(node, &naddr, &nsize); - buflen = getprop(node, "ranges", buf, sizeof(buf)); + buflen = getprop(node, "ranges", dt_xlate_buf, + sizeof(dt_xlate_buf)); if (buflen < 0) continue; - if (buflen > sizeof(buf)) + if (buflen > sizeof(dt_xlate_buf)) return 0; - offset = find_range(last_addr, buf, prev_naddr, + offset = find_range(last_addr, dt_xlate_buf, prev_naddr, naddr, nsize, buflen / 4); if (offset < 0) return 0; - copy_val(this_addr, buf + offset, prev_naddr); + copy_val(this_addr, dt_xlate_buf + offset, prev_naddr); if (!sub_reg(last_addr, this_addr)) return 0; - copy_val(this_addr, buf + offset + prev_naddr, naddr); + copy_val(this_addr, dt_xlate_buf + offset + prev_naddr, naddr); if (!add_reg(last_addr, this_addr, naddr)) return 0; @@ -286,3 +287,21 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, return 1; } + +int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size) +{ + int reglen; + + reglen = getprop(node, "reg", dt_xlate_buf, sizeof(dt_xlate_buf)) / 4; + return dt_xlate(node, res, reglen, addr, size); +} + +int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr) +{ + + if (buflen > sizeof(dt_xlate_buf)) + return 0; + + memcpy(dt_xlate_buf, buf, buflen); + return dt_xlate(node, 0, buflen / 4, xlated_addr, NULL); +} diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index 20e87199f6a..73bd47a3a07 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h @@ -82,8 +82,8 @@ int ns16550_console_init(void *devp, struct serial_console_data *scdp); void *simple_alloc_init(char *base, unsigned long heap_size, unsigned long granularity, unsigned long max_allocs); extern void flush_cache(void *, unsigned long); -int dt_xlate_reg(void *node, int res, unsigned long *addr, - unsigned long *size); +int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size); +int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr); static inline void *finddevice(const char *name) { |