vserver 1.9.5.x5
[linux-2.6.git] / arch / ppc64 / kernel / prom.c
index a5f8f24..eed1a70 100644 (file)
@@ -15,9 +15,7 @@
  *      2 of the License, or (at your option) any later version.
  */
 
-#if 0
-#define DEBUG_PROM
-#endif
+#undef DEBUG
 
 #include <stdarg.h>
 #include <linux/config.h>
@@ -33,6 +31,7 @@
 #include <linux/stringify.h>
 #include <linux/delay.h>
 #include <linux/initrd.h>
+#include <linux/bitops.h>
 #include <asm/prom.h>
 #include <asm/rtas.h>
 #include <asm/lmb.h>
@@ -45,8 +44,6 @@
 #include <asm/system.h>
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
-#include <asm/bitops.h>
-#include <asm/naca.h>
 #include <asm/pci.h>
 #include <asm/iommu.h>
 #include <asm/bootinfo.h>
 #include <asm/btext.h>
 #include <asm/sections.h>
 #include <asm/machdep.h>
-#include "open_pic.h"
 
-#ifdef CONFIG_LOGO_LINUX_CLUT224
-#include <linux/linux_logo.h>
-extern const struct linux_logo logo_linux_clut224;
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
 #endif
 
-/*
- * Properties whose value is longer than this get excluded from our
- * copy of the device tree. This value does need to be big enough to
- * ensure that we don't lose things like the interrupt-map property
- * on a PCI-PCI bridge.
- */
-#define MAX_PROPERTY_LENGTH    (1UL * 1024 * 1024)
-
-/*
- * prom_init() is called very early on, before the kernel text
- * and data have been mapped to KERNELBASE.  At this point the code
- * is running at whatever address it has been loaded at, so
- * references to extern and static variables must be relocated
- * explicitly.  The procedure reloc_offset() returns the address
- * we're currently running at minus the address we were linked at.
- * (Note that strings count as static variables.)
- *
- * Because OF may have mapped I/O devices into the area starting at
- * KERNELBASE, particularly on CHRP machines, we can't safely call
- * OF once the kernel has been mapped to KERNELBASE.  Therefore all
- * OF calls should be done within prom_init(), and prom_init()
- * and all routines called within it must be careful to relocate
- * references as necessary.
- *
- * Note that the bss is cleared *after* prom_init runs, so we have
- * to make sure that any static or extern variables it accesses
- * are put in the data segment.
- */
-
-
-#define PROM_BUG() do { \
-        prom_print(RELOC("kernel BUG at ")); \
-        prom_print(RELOC(__FILE__)); \
-        prom_print(RELOC(":")); \
-        prom_print_hex(__LINE__); \
-        prom_print(RELOC("!\n")); \
-        __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \
-} while (0)
-
-
-
 struct pci_reg_property {
        struct pci_address addr;
        u32 size_hi;
        u32 size_lo;
 };
 
-
 struct isa_reg_property {
        u32 space;
        u32 address;
        u32 size;
 };
 
-struct pci_intr_map {
-       struct pci_address addr;
-       u32 dunno;
-       phandle int_ctrler;
-       u32 intr;
-};
-
 
 typedef unsigned long interpret_func(struct device_node *, unsigned long,
                                     int, int, int);
 
-#ifndef FB_MAX                 /* avoid pulling in all of the fb stuff */
-#define FB_MAX 8
-#endif
-
-/* prom structure */
-struct prom_t prom;
-
-char *prom_display_paths[FB_MAX] __initdata = { 0, };
-phandle prom_display_nodes[FB_MAX] __initdata;
-unsigned int prom_num_displays = 0;
-char *of_stdout_device = 0;
-
-static int iommu_force_on;
-int ppc64_iommu_off;
-
 extern struct rtas_t rtas;
-extern unsigned long klimit;
 extern struct lmb lmb;
+extern unsigned long klimit;
 
-#define MAX_PHB (32 * 6)  /* 32 drawers * 6 PHBs/drawer */
-struct of_tce_table of_tce_table[MAX_PHB + 1];
-
-char *bootpath = 0;
-char *bootdevice = 0;
-
-int boot_cpuid = 0;
-#define MAX_CPU_THREADS 2
-
-struct device_node *allnodes = 0;
-/* use when traversing tree through the allnext, child, sibling,
- * or parent members of struct device_node.
- */
-static rwlock_t devtree_lock = RW_LOCK_UNLOCKED;
-
-extern unsigned long reloc_offset(void);
-
-extern void enter_prom(struct prom_args *args);
-extern void copy_and_flush(unsigned long dest, unsigned long src,
-                          unsigned long size, unsigned long offset);
-
-unsigned long dev_tree_size;
-unsigned long _get_PIR(void);
-
-#ifdef CONFIG_HMT
-struct {
-       unsigned int pir;
-       unsigned int threadid;
-} hmt_thread_data[NR_CPUS];
-#endif /* CONFIG_HMT */
-
-char testString[] = "LINUX\n"; 
-
-
-/* This is the one and *ONLY* place where we actually call open
- * firmware from, since we need to make sure we're running in 32b
- * mode when we do.  We switch back to 64b mode upon return.
- */
-
-#define PROM_ERROR     (0x00000000fffffffful)
-
-static unsigned long __init call_prom(const char *service, int nargs, int nret, ...)
-{
-       int i;
-       unsigned long offset = reloc_offset();
-       struct prom_t *_prom = PTRRELOC(&prom);
-       va_list list;
-        
-       _prom->args.service = (u32)LONG_LSW(service);
-       _prom->args.nargs = nargs;
-       _prom->args.nret = nret;
-        _prom->args.rets = (prom_arg_t *)&(_prom->args.args[nargs]);
-
-        va_start(list, nret);
-       for (i=0; i < nargs ;i++)
-               _prom->args.args[i] = (prom_arg_t)LONG_LSW(va_arg(list, unsigned long));
-        va_end(list);
-
-       for (i=0; i < nret ;i++)
-               _prom->args.rets[i] = 0;
-
-       enter_prom(&_prom->args);
-
-       return (unsigned long)((nret > 0) ? _prom->args.rets[0] : 0);
-}
-
-
-static void __init prom_print(const char *msg)
-{
-       const char *p, *q;
-       unsigned long offset = reloc_offset();
-       struct prom_t *_prom = PTRRELOC(&prom);
-
-       if (_prom->stdout == 0)
-               return;
-
-       for (p = msg; *p != 0; p = q) {
-               for (q = p; *q != 0 && *q != '\n'; ++q)
-                       ;
-               if (q > p)
-                       call_prom(RELOC("write"), 3, 1, _prom->stdout,
-                                 p, q - p);
-               if (*q != 0) {
-                       ++q;
-                       call_prom(RELOC("write"), 3, 1, _prom->stdout,
-                                 RELOC("\r\n"), 2);
-               }
-       }
-}
-
-
-static void __init prom_print_hex(unsigned long val)
-{
-        int i, nibbles = sizeof(val)*2;
-        char buf[sizeof(val)*2+1];
-
-        for (i = nibbles-1;  i >= 0;  i--) {
-                buf[i] = (val & 0xf) + '0';
-                if (buf[i] > '9')
-                    buf[i] += ('a'-'0'-10);
-                val >>= 4;
-        }
-        buf[nibbles] = '\0';
-       prom_print(buf);
-}
-
-
-static void __init prom_print_nl(void)
-{
-       unsigned long offset = reloc_offset();
-       prom_print(RELOC("\n"));
-}
-
-
-static void __init prom_panic(const char *reason)
-{
-       unsigned long offset = reloc_offset();
-
-       prom_print(reason);
-       /* ToDo: should put up an SRC here */
-       call_prom(RELOC("exit"), 0, 0);
-
-       for (;;)                        /* should never get here */
-               ;
-}
-
-
-static int __init prom_next_node(phandle *nodep)
-{
-       phandle node;
-       unsigned long offset = reloc_offset();
-
-       if ((node = *nodep) != 0
-           && (*nodep = call_prom(RELOC("child"), 1, 1, node)) != 0)
-               return 1;
-       if ((*nodep = call_prom(RELOC("peer"), 1, 1, node)) != 0)
-               return 1;
-       for (;;) {
-               if ((node = call_prom(RELOC("parent"), 1, 1, node)) == 0)
-                       return 0;
-               if ((*nodep = call_prom(RELOC("peer"), 1, 1, node)) != 0)
-                       return 1;
-       }
-}
-
-
-static void __init prom_initialize_naca(void)
-{
-       phandle node;
-       char type[64];
-        unsigned long num_cpus = 0;
-        unsigned long offset = reloc_offset();
-       struct prom_t *_prom = PTRRELOC(&prom);
-        struct naca_struct *_naca = RELOC(naca);
-        struct systemcfg *_systemcfg = RELOC(systemcfg);
-
-       /* NOTE: _naca->debug_switch is already initialized. */
-#ifdef DEBUG_PROM
-       prom_print(RELOC("prom_initialize_naca: start...\n"));
-#endif
-
-       _naca->pftSize = 0;     /* ilog2 of htab size.  computed below. */
-
-        for (node = 0; prom_next_node(&node); ) {
-                type[0] = 0;
-                call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
-                          type, sizeof(type));
-
-                if (!strcmp(type, RELOC("cpu"))) {
-                       num_cpus += 1;
-
-                       /* We're assuming *all* of the CPUs have the same
-                        * d-cache and i-cache sizes... -Peter
-                        */
-                       if ( num_cpus == 1 ) {
-                               u32 size, lsize;
-
-                               call_prom(RELOC("getprop"), 4, 1, node,
-                                         RELOC("d-cache-size"),
-                                         &size, sizeof(size));
-
-                               if (_systemcfg->platform == PLATFORM_POWERMAC)
-                                       call_prom(RELOC("getprop"), 4, 1, node,
-                                                 RELOC("d-cache-block-size"),
-                                                 &lsize, sizeof(lsize));
-                               else
-                                       call_prom(RELOC("getprop"), 4, 1, node,
-                                                 RELOC("d-cache-line-size"),
-                                                 &lsize, sizeof(lsize));
-
-                               _systemcfg->dCacheL1Size = size;
-                               _systemcfg->dCacheL1LineSize = lsize;
-                               _naca->dCacheL1LogLineSize = __ilog2(lsize);
-                               _naca->dCacheL1LinesPerPage = PAGE_SIZE/lsize;
-
-                               call_prom(RELOC("getprop"), 4, 1, node,
-                                         RELOC("i-cache-size"),
-                                         &size, sizeof(size));
-
-                               if (_systemcfg->platform == PLATFORM_POWERMAC)
-                                       call_prom(RELOC("getprop"), 4, 1, node,
-                                                 RELOC("i-cache-block-size"),
-                                                 &lsize, sizeof(lsize));
-                               else
-                                       call_prom(RELOC("getprop"), 4, 1, node,
-                                                 RELOC("i-cache-line-size"),
-                                                 &lsize, sizeof(lsize));
-
-                               _systemcfg->iCacheL1Size = size;
-                               _systemcfg->iCacheL1LineSize = lsize;
-                               _naca->iCacheL1LogLineSize = __ilog2(lsize);
-                               _naca->iCacheL1LinesPerPage = PAGE_SIZE/lsize;
-
-                               if (_systemcfg->platform == PLATFORM_PSERIES_LPAR) {
-                                       u32 pft_size[2];
-                                       call_prom(RELOC("getprop"), 4, 1, node, 
-                                                 RELOC("ibm,pft-size"),
-                                                 &pft_size, sizeof(pft_size));
-                               /* pft_size[0] is the NUMA CEC cookie */
-                                       _naca->pftSize = pft_size[1];
-                               }
-                       }
-                } else if (!strcmp(type, RELOC("serial"))) {
-                       phandle isa, pci;
-                       struct isa_reg_property reg;
-                       union pci_range ranges;
-
-                       if (_systemcfg->platform == PLATFORM_POWERMAC)
-                               continue;
-                       type[0] = 0;
-                       call_prom(RELOC("getprop"), 4, 1, node,
-                                 RELOC("ibm,aix-loc"), type, sizeof(type));
-
-                       if (strcmp(type, RELOC("S1")))
-                               continue;
-
-                       call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
-                                 &reg, sizeof(reg));
-
-                       isa = call_prom(RELOC("parent"), 1, 1, node);
-                       if (!isa)
-                               PROM_BUG();
-                       pci = call_prom(RELOC("parent"), 1, 1, isa);
-                       if (!pci)
-                               PROM_BUG();
-
-                       call_prom(RELOC("getprop"), 4, 1, pci, RELOC("ranges"),
-                                 &ranges, sizeof(ranges));
-
-                       if ( _prom->encode_phys_size == 32 )
-                               _naca->serialPortAddr = ranges.pci32.phys+reg.address;
-                       else {
-                               _naca->serialPortAddr = 
-                                       ((((unsigned long)ranges.pci64.phys_hi) << 32) |
-                                        (ranges.pci64.phys_lo)) + reg.address;
-                       }
-                }
-       }
-
-       if (_systemcfg->platform == PLATFORM_POWERMAC)
-               _naca->interrupt_controller = IC_OPEN_PIC;
-       else {
-               _naca->interrupt_controller = IC_INVALID;
-               for (node = 0; prom_next_node(&node); ) {
-                       type[0] = 0;
-                       call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"),
-                                 type, sizeof(type));
-                       if (strcmp(type, RELOC("interrupt-controller")))
-                               continue;
-                       call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"),
-                                 type, sizeof(type));
-                       if (strstr(type, RELOC("open-pic")))
-                               _naca->interrupt_controller = IC_OPEN_PIC;
-                       else if (strstr(type, RELOC("ppc-xicp")))
-                               _naca->interrupt_controller = IC_PPC_XIC;
-                       else
-                               prom_print(RELOC("prom: failed to recognize"
-                                                " interrupt-controller\n"));
-                       break;
-               }
-       }
-
-       if (_naca->interrupt_controller == IC_INVALID) {
-               prom_print(RELOC("prom: failed to find interrupt-controller\n"));
-               PROM_BUG();
-       }
-
-       /* We gotta have at least 1 cpu... */
-        if ( (_systemcfg->processorCount = num_cpus) < 1 )
-                PROM_BUG();
-
-       _systemcfg->physicalMemorySize = lmb_phys_mem_size();
-
-       if (_systemcfg->platform == PLATFORM_PSERIES ||
-           _systemcfg->platform == PLATFORM_POWERMAC) {
-               unsigned long rnd_mem_size, pteg_count;
-
-               /* round mem_size up to next power of 2 */
-               rnd_mem_size = 1UL << __ilog2(_systemcfg->physicalMemorySize);
-               if (rnd_mem_size < _systemcfg->physicalMemorySize)
-                       rnd_mem_size <<= 1;
-
-               /* # pages / 2 */
-               pteg_count = (rnd_mem_size >> (12 + 1));
-
-               _naca->pftSize = __ilog2(pteg_count << 7);
-       }
-
-       if (_naca->pftSize == 0) {
-               prom_print(RELOC("prom: failed to compute pftSize!\n"));
-               PROM_BUG();
-       }
-
-       /* Add an eye catcher and the systemcfg layout version number */
-       strcpy(_systemcfg->eye_catcher, RELOC("SYSTEMCFG:PPC64"));
-       _systemcfg->version.major = SYSTEMCFG_MAJOR;
-       _systemcfg->version.minor = SYSTEMCFG_MINOR;
-       _systemcfg->processor = _get_PVR();
-
-#ifdef DEBUG_PROM
-        prom_print(RELOC("systemcfg->processorCount       = 0x"));
-        prom_print_hex(_systemcfg->processorCount);
-        prom_print_nl();
-
-        prom_print(RELOC("systemcfg->physicalMemorySize   = 0x"));
-        prom_print_hex(_systemcfg->physicalMemorySize);
-        prom_print_nl();
-
-        prom_print(RELOC("naca->pftSize                   = 0x"));
-        prom_print_hex(_naca->pftSize);
-        prom_print_nl();
-
-        prom_print(RELOC("systemcfg->dCacheL1LineSize     = 0x"));
-        prom_print_hex(_systemcfg->dCacheL1LineSize);
-        prom_print_nl();
-
-        prom_print(RELOC("systemcfg->iCacheL1LineSize     = 0x"));
-        prom_print_hex(_systemcfg->iCacheL1LineSize);
-        prom_print_nl();
-
-        prom_print(RELOC("naca->serialPortAddr            = 0x"));
-        prom_print_hex(_naca->serialPortAddr);
-        prom_print_nl();
-
-        prom_print(RELOC("naca->interrupt_controller      = 0x"));
-        prom_print_hex(_naca->interrupt_controller);
-        prom_print_nl();
-
-        prom_print(RELOC("systemcfg->platform             = 0x"));
-        prom_print_hex(_systemcfg->platform);
-        prom_print_nl();
-
-       prom_print(RELOC("prom_initialize_naca: end...\n"));
-#endif
-}
-
-
-static void __init early_cmdline_parse(void)
-{
-       unsigned long offset = reloc_offset();
-       char *opt;
-#ifndef CONFIG_PMAC_DART
-       struct systemcfg *_systemcfg = RELOC(systemcfg);
-#endif
-
-       opt = strstr(RELOC(cmd_line), RELOC("iommu="));
-       if (opt) {
-               prom_print(RELOC("opt is:"));
-               prom_print(opt);
-               prom_print(RELOC("\n"));
-               opt += 6;
-               while (*opt && *opt == ' ')
-                       opt++;
-               if (!strncmp(opt, RELOC("off"), 3))
-                       RELOC(ppc64_iommu_off) = 1;
-               else if (!strncmp(opt, RELOC("force"), 5))
-                       RELOC(iommu_force_on) = 1;
-       }
-
-#ifndef CONFIG_PMAC_DART
-       if (_systemcfg->platform == PLATFORM_POWERMAC) {
-               RELOC(ppc64_iommu_off) = 1;
-               prom_print(RELOC("DART disabled on PowerMac !\n"));
-       }
-#endif
-}
-
-#ifdef DEBUG_PROM
-void prom_dump_lmb(void)
-{
-        unsigned long i;
-        unsigned long offset = reloc_offset();
-       struct lmb *_lmb  = PTRRELOC(&lmb);
-
-        prom_print(RELOC("\nprom_dump_lmb:\n"));
-        prom_print(RELOC("    memory.cnt                  = 0x"));
-        prom_print_hex(_lmb->memory.cnt);
-       prom_print_nl();
-        prom_print(RELOC("    memory.size                 = 0x"));
-        prom_print_hex(_lmb->memory.size);
-       prom_print_nl();
-        for (i=0; i < _lmb->memory.cnt ;i++) {
-                prom_print(RELOC("    memory.region[0x"));
-               prom_print_hex(i);
-               prom_print(RELOC("].base       = 0x"));
-                prom_print_hex(_lmb->memory.region[i].base);
-               prom_print_nl();
-                prom_print(RELOC("                      .physbase = 0x"));
-                prom_print_hex(_lmb->memory.region[i].physbase);
-               prom_print_nl();
-                prom_print(RELOC("                      .size     = 0x"));
-                prom_print_hex(_lmb->memory.region[i].size);
-               prom_print_nl();
-        }
-
-       prom_print_nl();
-        prom_print(RELOC("    reserved.cnt                  = 0x"));
-        prom_print_hex(_lmb->reserved.cnt);
-       prom_print_nl();
-        prom_print(RELOC("    reserved.size                 = 0x"));
-        prom_print_hex(_lmb->reserved.size);
-       prom_print_nl();
-        for (i=0; i < _lmb->reserved.cnt ;i++) {
-                prom_print(RELOC("    reserved.region[0x"));
-               prom_print_hex(i);
-               prom_print(RELOC("].base       = 0x"));
-                prom_print_hex(_lmb->reserved.region[i].base);
-               prom_print_nl();
-                prom_print(RELOC("                      .physbase = 0x"));
-                prom_print_hex(_lmb->reserved.region[i].physbase);
-               prom_print_nl();
-                prom_print(RELOC("                      .size     = 0x"));
-                prom_print_hex(_lmb->reserved.region[i].size);
-               prom_print_nl();
-        }
-}
-#endif /* DEBUG_PROM */
-
-static void __init prom_initialize_lmb(void)
-{
-       phandle node;
-       char type[64];
-        unsigned long i, offset = reloc_offset();
-       struct prom_t *_prom = PTRRELOC(&prom);
-        struct systemcfg *_systemcfg = RELOC(systemcfg);
-       union lmb_reg_property reg;
-       unsigned long lmb_base, lmb_size;
-       unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8;
-
-       lmb_init();
-
-       /* XXX Quick HACK. Proper fix is to drop those structures and properly use
-        * #address-cells. PowerMac has #size-cell set to 1 and #address-cells to 2
-        */
-       if (_systemcfg->platform == PLATFORM_POWERMAC)
-               bytes_per_reg = 12;
-
-        for (node = 0; prom_next_node(&node); ) {
-                type[0] = 0;
-                call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
-                          type, sizeof(type));
-
-                if (strcmp(type, RELOC("memory")))
-                       continue;
-
-               num_regs = call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
-                       &reg, sizeof(reg)) / bytes_per_reg;
-
-               for (i=0; i < num_regs ;i++) {
-                       if (_systemcfg->platform == PLATFORM_POWERMAC) {
-                               lmb_base = ((unsigned long)reg.addrPM[i].address_hi) << 32;
-                               lmb_base |= (unsigned long)reg.addrPM[i].address_lo;
-                               lmb_size = reg.addrPM[i].size;
-                       } else if (_prom->encode_phys_size == 32) {
-                               lmb_base = reg.addr32[i].address;
-                               lmb_size = reg.addr32[i].size;
-                       } else {
-                               lmb_base = reg.addr64[i].address;
-                               lmb_size = reg.addr64[i].size;
-                       }
-
-                       /* We limit memory to 2GB if the IOMMU is off */
-                       if (RELOC(ppc64_iommu_off)) {
-                               if (lmb_base >= 0x80000000UL)
-                                       continue;
-
-                               if ((lmb_base + lmb_size) > 0x80000000UL)
-                                       lmb_size = 0x80000000UL - lmb_base;
-                       }
-
-                       if (lmb_add(lmb_base, lmb_size) < 0)
-                               prom_print(RELOC("Too many LMB's, discarding this one...\n"));
-               }
-
-       }
-
-       lmb_analyze();
-#ifdef DEBUG_PROM
-       prom_dump_lmb();
-#endif /* DEBUG_PROM */
-}
-
-static void __init
-prom_instantiate_rtas(void)
-{
-       unsigned long offset = reloc_offset();
-       struct prom_t *_prom = PTRRELOC(&prom);
-       struct rtas_t *_rtas = PTRRELOC(&rtas);
-       struct systemcfg *_systemcfg = RELOC(systemcfg);
-       ihandle prom_rtas;
-        u32 getprop_rval;
-       char hypertas_funcs[4];
-
-#ifdef DEBUG_PROM
-       prom_print(RELOC("prom_instantiate_rtas: start...\n"));
-#endif
-       prom_rtas = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas"));
-       if (prom_rtas != (ihandle) -1) {
-               unsigned long x;
-               x = call_prom(RELOC("getprop"),
-                                 4, 1, prom_rtas,
-                                 RELOC("ibm,hypertas-functions"), 
-                                 hypertas_funcs, 
-                             sizeof(hypertas_funcs));
-
-               if (x != PROM_ERROR) {
-                       prom_print(RELOC("Hypertas detected, assuming LPAR !\n"));
-                       _systemcfg->platform = PLATFORM_PSERIES_LPAR;
-               }
-
-               call_prom(RELOC("getprop"), 
-                         4, 1, prom_rtas,
-                         RELOC("rtas-size"), 
-                         &getprop_rval, 
-                         sizeof(getprop_rval));
-               _rtas->size = getprop_rval;
-               prom_print(RELOC("instantiating rtas"));
-               if (_rtas->size != 0) {
-                       unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
-
-                       /* Grab some space within the first RTAS_INSTANTIATE_MAX bytes
-                        * of physical memory (or within the RMO region) because RTAS
-                        * runs in 32-bit mode and relocate off.
-                        */
-                       if ( _systemcfg->platform == PLATFORM_PSERIES_LPAR ) {
-                               struct lmb *_lmb  = PTRRELOC(&lmb);
-                               rtas_region = min(_lmb->rmo_size, RTAS_INSTANTIATE_MAX);
-                       }
-
-                       _rtas->base = lmb_alloc_base(_rtas->size, PAGE_SIZE, rtas_region);
-
-                       prom_print(RELOC(" at 0x"));
-                       prom_print_hex(_rtas->base);
-
-                       prom_rtas = (ihandle)call_prom(RELOC("open"), 
-                                               1, 1, RELOC("/rtas"));
-                       prom_print(RELOC("..."));
-
-                       if (call_prom(RELOC("call-method"), 3, 2,
-                                                     RELOC("instantiate-rtas"),
-                                                     prom_rtas,
-                                                     _rtas->base) != PROM_ERROR) {
-                               _rtas->entry = (long)_prom->args.rets[1];
-                       }
-                       RELOC(rtas_rmo_buf)
-                               = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE,
-                                                       rtas_region);
-               }
-
-               if (_rtas->entry <= 0) {
-                       prom_print(RELOC(" failed\n"));
-               } else {
-                       prom_print(RELOC(" done\n"));
-               }
-
-#ifdef DEBUG_PROM
-               prom_print(RELOC("rtas->base                 = 0x"));
-               prom_print_hex(_rtas->base);
-               prom_print_nl();
-               prom_print(RELOC("rtas->entry                = 0x"));
-               prom_print_hex(_rtas->entry);
-               prom_print_nl();
-               prom_print(RELOC("rtas->size                 = 0x"));
-               prom_print_hex(_rtas->size);
-               prom_print_nl();
-#endif
-       }
-#ifdef DEBUG_PROM
-       prom_print(RELOC("prom_instantiate_rtas: end...\n"));
-#endif
-}
-
-
-#ifdef CONFIG_PMAC_DART
-static void __init prom_initialize_dart_table(void)
-{
-       unsigned long offset = reloc_offset();
-       extern unsigned long dart_tablebase;
-       extern unsigned long dart_tablesize;
-
-       /* Only reserve DART space if machine has more than 2GB of RAM
-        * or if requested with iommu=on on cmdline.
-        */
-       if (lmb_end_of_DRAM() <= 0x80000000ull && !RELOC(iommu_force_on))
-               return;
-
-       /* 512 pages (2MB) is max DART tablesize. */
-       RELOC(dart_tablesize) = 1UL << 21;
-       /* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we
-        * will blow up an entire large page anyway in the kernel mapping
-        */
-       RELOC(dart_tablebase) = (unsigned long)
-               abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
-
-       prom_print(RELOC("Dart at: "));
-       prom_print_hex(RELOC(dart_tablebase));
-       prom_print(RELOC("\n"));
-}
-#endif /* CONFIG_PMAC_DART */
-
-static void __init prom_initialize_tce_table(void)
-{
-       phandle node;
-       ihandle phb_node;
-        unsigned long offset = reloc_offset();
-       char compatible[64], path[64], type[64], model[64];
-       unsigned long i, table = 0;
-       unsigned long base, vbase, align;
-       unsigned int minalign, minsize;
-       struct of_tce_table *prom_tce_table = RELOC(of_tce_table);
-       unsigned long tce_entry, *tce_entryp;
-
-       if (RELOC(ppc64_iommu_off))
-               return;
-
-#ifdef DEBUG_PROM
-       prom_print(RELOC("starting prom_initialize_tce_table\n"));
-#endif
-
-       /* Search all nodes looking for PHBs. */
-       for (node = 0; prom_next_node(&node); ) {
-               if (table == MAX_PHB) {
-                       prom_print(RELOC("WARNING: PCI host bridge ignored, "
-                                        "need to increase MAX_PHB\n"));
-                       continue;
-               }
-
-               compatible[0] = 0;
-               type[0] = 0;
-               model[0] = 0;
-               call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"),
-                         compatible, sizeof(compatible));
-               call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
-                         type, sizeof(type));
-               call_prom(RELOC("getprop"), 4, 1, node, RELOC("model"),
-                         model, sizeof(model));
-
-               /* Keep the old logic in tack to avoid regression. */
-               if (compatible[0] != 0) {
-                       if((strstr(compatible, RELOC("python")) == NULL) &&
-                          (strstr(compatible, RELOC("Speedwagon")) == NULL) &&
-                          (strstr(compatible, RELOC("Winnipeg")) == NULL))
-                               continue;
-               } else if (model[0] != 0) {
-                       if ((strstr(model, RELOC("ython")) == NULL) &&
-                           (strstr(model, RELOC("peedwagon")) == NULL) &&
-                           (strstr(model, RELOC("innipeg")) == NULL))
-                               continue;
-               }
-
-               if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL)) {
-                       continue;
-               }
-
-               if (call_prom(RELOC("getprop"), 4, 1, node, 
-                            RELOC("tce-table-minalign"), &minalign, 
-                            sizeof(minalign)) == PROM_ERROR) {
-                       minalign = 0;
-               }
-
-               if (call_prom(RELOC("getprop"), 4, 1, node, 
-                            RELOC("tce-table-minsize"), &minsize, 
-                            sizeof(minsize)) == PROM_ERROR) {
-                       minsize = 4UL << 20;
-               }
-
-               /*
-                * Even though we read what OF wants, we just set the table
-                * size to 4 MB.  This is enough to map 2GB of PCI DMA space.
-                * By doing this, we avoid the pitfalls of trying to DMA to
-                * MMIO space and the DMA alias hole.
-                *
-                * On POWER4, firmware sets the TCE region by assuming
-                * each TCE table is 8MB. Using this memory for anything
-                * else will impact performance, so we always allocate 8MB.
-                * Anton
-                */
-               if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p))
-                       minsize = 8UL << 20;
-               else
-                       minsize = 4UL << 20;
-
-               /* Align to the greater of the align or size */
-               align = max(minalign, minsize);
-
-               /* Carve out storage for the TCE table. */
-               base = lmb_alloc(minsize, align);
-
-               if ( !base ) {
-                       prom_panic(RELOC("ERROR, cannot find space for TCE table.\n"));
-               }
-
-               vbase = (unsigned long)abs_to_virt(base);
-
-               /* Save away the TCE table attributes for later use. */
-               prom_tce_table[table].node = node;
-               prom_tce_table[table].base = vbase;
-               prom_tce_table[table].size = minsize;
-
-#ifdef DEBUG_PROM
-               prom_print(RELOC("TCE table: 0x"));
-               prom_print_hex(table);
-               prom_print_nl();
-
-               prom_print(RELOC("\tnode = 0x"));
-               prom_print_hex(node);
-               prom_print_nl();
-
-               prom_print(RELOC("\tbase = 0x"));
-               prom_print_hex(vbase);
-               prom_print_nl();
-
-               prom_print(RELOC("\tsize = 0x"));
-               prom_print_hex(minsize);
-               prom_print_nl();
-#endif
-
-               /* Initialize the table to have a one-to-one mapping
-                * over the allocated size.
-                */
-               tce_entryp = (unsigned long *)base;
-               for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
-                       tce_entry = (i << PAGE_SHIFT);
-                       tce_entry |= 0x3;
-                       *tce_entryp = tce_entry;
-               }
-
-               /* It seems OF doesn't null-terminate the path :-( */
-               memset(path, 0, sizeof(path));
-               /* Call OF to setup the TCE hardware */
-               if (call_prom(RELOC("package-to-path"), 3, 1, node,
-                             path, sizeof(path)-1) == PROM_ERROR) {
-                        prom_print(RELOC("package-to-path failed\n"));
-                } else {
-                        prom_print(RELOC("opening PHB "));
-                        prom_print(path);
-                }
-
-                phb_node = (ihandle)call_prom(RELOC("open"), 1, 1, path);
-                if ( (long)phb_node <= 0) {
-                        prom_print(RELOC("... failed\n"));
-                } else {
-                        prom_print(RELOC("... done\n"));
-                }
-                call_prom(RELOC("call-method"), 6, 0,
-                             RELOC("set-64-bit-addressing"),
-                            phb_node,
-                            -1,
-                             minsize, 
-                             base & 0xffffffff,
-                             (base >> 32) & 0xffffffff);
-                call_prom(RELOC("close"), 1, 0, phb_node);
-
-               table++;
-       }
-
-       /* Flag the first invalid entry */
-       prom_tce_table[table].node = 0;
-#ifdef DEBUG_PROM
-       prom_print(RELOC("ending prom_initialize_tce_table\n"));
-#endif
-}
-
-/*
- * With CHRP SMP we need to use the OF to start the other
- * processors so we can't wait until smp_boot_cpus (the OF is
- * trashed by then) so we have to put the processors into
- * a holding pattern controlled by the kernel (not OF) before
- * we destroy the OF.
- *
- * This uses a chunk of low memory, puts some holding pattern
- * code there and sends the other processors off to there until
- * smp_boot_cpus tells them to do something.  The holding pattern
- * checks that address until its cpu # is there, when it is that
- * cpu jumps to __secondary_start().  smp_boot_cpus() takes care
- * of setting those values.
- *
- * We also use physical address 0x4 here to tell when a cpu
- * is in its holding pattern code.
- *
- * Fixup comment... DRENG / PPPBBB - Peter
- *
- * -- Cort
- */
-static void __init prom_hold_cpus(unsigned long mem)
-{
-       unsigned long i;
-       unsigned int reg;
-       phandle node;
-       unsigned long offset = reloc_offset();
-       char type[64], *path;
-       int cpuid = 0;
-       unsigned int interrupt_server[MAX_CPU_THREADS];
-       unsigned int cpu_threads, hw_cpu_num;
-       int propsize;
-       extern void __secondary_hold(void);
-        extern unsigned long __secondary_hold_spinloop;
-        extern unsigned long __secondary_hold_acknowledge;
-        unsigned long *spinloop
-               = (void *)virt_to_abs(&__secondary_hold_spinloop);
-        unsigned long *acknowledge
-               = (void *)virt_to_abs(&__secondary_hold_acknowledge);
-        unsigned long secondary_hold
-               = virt_to_abs(*PTRRELOC((unsigned long *)__secondary_hold));
-        struct systemcfg *_systemcfg = RELOC(systemcfg);
-       struct paca_struct *_xPaca = PTRRELOC(&paca[0]);
-       struct prom_t *_prom = PTRRELOC(&prom);
-#ifdef CONFIG_SMP
-       struct naca_struct *_naca = RELOC(naca);
-#endif
-
-       /* On pmac, we just fill out the various global bitmasks and
-        * arrays indicating our CPUs are here, they are actually started
-        * later on from pmac_smp
-        */
-       if (_systemcfg->platform == PLATFORM_POWERMAC) {
-               for (node = 0; prom_next_node(&node); ) {
-                       type[0] = 0;
-                       call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
-                                 type, sizeof(type));
-                       if (strcmp(type, RELOC("cpu")) != 0)
-                               continue;
-                       reg = -1;
-                       call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
-                                 &reg, sizeof(reg));
-                       _xPaca[cpuid].xHwProcNum = reg;
-
-#ifdef CONFIG_SMP
-                       cpu_set(cpuid, RELOC(cpu_available_map));
-                       cpu_set(cpuid, RELOC(cpu_possible_map));
-                       cpu_set(cpuid, RELOC(cpu_present_at_boot));
-                       if (reg == 0)
-                               cpu_set(cpuid, RELOC(cpu_online_map));
-#endif /* CONFIG_SMP */
-                       cpuid++;
-               }
-               return;
-       }
-
-       /* Initially, we must have one active CPU. */
-       _systemcfg->processorCount = 1;
-
-#ifdef DEBUG_PROM
-       prom_print(RELOC("prom_hold_cpus: start...\n"));
-       prom_print(RELOC("    1) spinloop       = 0x"));
-       prom_print_hex((unsigned long)spinloop);
-       prom_print_nl();
-       prom_print(RELOC("    1) *spinloop      = 0x"));
-       prom_print_hex(*spinloop);
-       prom_print_nl();
-       prom_print(RELOC("    1) acknowledge    = 0x"));
-       prom_print_hex((unsigned long)acknowledge);
-       prom_print_nl();
-       prom_print(RELOC("    1) *acknowledge   = 0x"));
-       prom_print_hex(*acknowledge);
-       prom_print_nl();
-       prom_print(RELOC("    1) secondary_hold = 0x"));
-       prom_print_hex(secondary_hold);
-       prom_print_nl();
-#endif
-
-        /* Set the common spinloop variable, so all of the secondary cpus
-        * will block when they are awakened from their OF spinloop.
-        * This must occur for both SMP and non SMP kernels, since OF will
-        * be trashed when we move the kernel.
-         */
-        *spinloop = 0;
-
-#ifdef CONFIG_HMT
-       for (i=0; i < NR_CPUS; i++) {
-               RELOC(hmt_thread_data)[i].pir = 0xdeadbeef;
-       }
-#endif
-       /* look for cpus */
-       for (node = 0; prom_next_node(&node); ) {
-               type[0] = 0;
-               call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
-                         type, sizeof(type));
-               if (strcmp(type, RELOC("cpu")) != 0)
-                       continue;
-
-               /* Skip non-configured cpus. */
-               call_prom(RELOC("getprop"), 4, 1, node, RELOC("status"),
-                         type, sizeof(type));
-               if (strcmp(type, RELOC("okay")) != 0)
-                       continue;
-
-                reg = -1;
-               call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
-                         &reg, sizeof(reg));
-
-               path = (char *) mem;
-               memset(path, 0, 256);
-               if ((long) call_prom(RELOC("package-to-path"), 3, 1,
-                                    node, path, 255) == PROM_ERROR)
-                       continue;
-
-#ifdef DEBUG_PROM
-               prom_print_nl();
-               prom_print(RELOC("cpuid        = 0x"));
-               prom_print_hex(cpuid);
-               prom_print_nl();
-               prom_print(RELOC("cpu hw idx   = 0x"));
-               prom_print_hex(reg);
-               prom_print_nl();
-#endif
-               _xPaca[cpuid].xHwProcNum = reg;
-
-               /* Init the acknowledge var which will be reset by
-                * the secondary cpu when it awakens from its OF
-                * spinloop.
-                */
-               *acknowledge = (unsigned long)-1;
-
-               propsize = call_prom(RELOC("getprop"), 4, 1, node,
-                                    RELOC("ibm,ppc-interrupt-server#s"), 
-                                    &interrupt_server, 
-                                    sizeof(interrupt_server));
-               if (propsize < 0) {
-                       /* no property.  old hardware has no SMT */
-                       cpu_threads = 1;
-                       interrupt_server[0] = reg; /* fake it with phys id */
-               } else {
-                       /* We have a threaded processor */
-                       cpu_threads = propsize / sizeof(u32);
-                       if (cpu_threads > MAX_CPU_THREADS) {
-                               prom_print(RELOC("SMT: too many threads!\nSMT: found "));
-                               prom_print_hex(cpu_threads);
-                               prom_print(RELOC(", max is "));
-                               prom_print_hex(MAX_CPU_THREADS);
-                               prom_print_nl();
-                               cpu_threads = 1; /* ToDo: panic? */
-                       }
-               }
-
-               hw_cpu_num = interrupt_server[0];
-               if (hw_cpu_num != _prom->cpu) {
-                       /* Primary Thread of non-boot cpu */
-                       prom_print_hex(cpuid);
-                       prom_print(RELOC(" : starting cpu "));
-                       prom_print(path);
-                       prom_print(RELOC("... "));
-                       call_prom(RELOC("start-cpu"), 3, 0, node, 
-                                 secondary_hold, cpuid);
-
-                       for ( i = 0 ; (i < 100000000) && 
-                             (*acknowledge == ((unsigned long)-1)); i++ ) ;
-
-                       if (*acknowledge == cpuid) {
-                               prom_print(RELOC("... done\n"));
-                               /* We have to get every CPU out of OF,
-                                * even if we never start it. */
-                               if (cpuid >= NR_CPUS)
-                                       goto next;
-#ifdef CONFIG_SMP
-                               /* Set the number of active processors. */
-                               _systemcfg->processorCount++;
-                               cpu_set(cpuid, RELOC(cpu_available_map));
-                               cpu_set(cpuid, RELOC(cpu_possible_map));
-                               cpu_set(cpuid, RELOC(cpu_present_at_boot));
-#endif
-                       } else {
-                               prom_print(RELOC("... failed: "));
-                               prom_print_hex(*acknowledge);
-                               prom_print_nl();
-                       }
-               }
-#ifdef CONFIG_SMP
-               else {
-                       prom_print_hex(cpuid);
-                       prom_print(RELOC(" : booting  cpu "));
-                       prom_print(path);
-                       prom_print_nl();
-                       cpu_set(cpuid, RELOC(cpu_available_map));
-                       cpu_set(cpuid, RELOC(cpu_possible_map));
-                       cpu_set(cpuid, RELOC(cpu_online_map));
-                       cpu_set(cpuid, RELOC(cpu_present_at_boot));
-               }
-#endif
-next:
-#ifdef CONFIG_SMP
-               /* Init paca for secondary threads.   They start later. */
-               for (i=1; i < cpu_threads; i++) {
-                       cpuid++;
-                       if (cpuid >= NR_CPUS)
-                               continue;
-                       _xPaca[cpuid].xHwProcNum = interrupt_server[i];
-                       prom_print_hex(interrupt_server[i]);
-                       prom_print(RELOC(" : preparing thread ... "));
-                       if (_naca->smt_state) {
-                               cpu_set(cpuid, RELOC(cpu_available_map));
-                               cpu_set(cpuid, RELOC(cpu_present_at_boot));
-                               prom_print(RELOC("available"));
-                       } else {
-                               prom_print(RELOC("not available"));
-                       }
-                       prom_print_nl();
-               }
-#endif
-               cpuid++;
-       }
-#ifdef CONFIG_HMT
-       /* Only enable HMT on processors that provide support. */
-       if (__is_processor(PV_PULSAR) || 
-           __is_processor(PV_ICESTAR) ||
-           __is_processor(PV_SSTAR)) {
-               prom_print(RELOC("    starting secondary threads\n"));
-
-               for (i = 0; i < NR_CPUS; i += 2) {
-                       if (!cpu_online(i))
-                               continue;
-
-                       if (i == 0) {
-                               unsigned long pir = _get_PIR();
-                               if (__is_processor(PV_PULSAR)) {
-                                       RELOC(hmt_thread_data)[i].pir = 
-                                               pir & 0x1f;
-                               } else {
-                                       RELOC(hmt_thread_data)[i].pir = 
-                                               pir & 0x3ff;
-                               }
-                       }
-/*                     cpu_set(i+1, cpu_online_map); */
-                       cpu_set(i+1, RELOC(cpu_possible_map));
-               }
-               _systemcfg->processorCount *= 2;
-       } else {
-               prom_print(RELOC("Processor is not HMT capable\n"));
-       }
-#endif
-
-       if (cpuid >= NR_CPUS)
-               prom_print(RELOC("WARNING: maximum CPUs (" __stringify(NR_CPUS)
-                                ") exceeded: ignoring extras\n"));
-
-#ifdef DEBUG_PROM
-       prom_print(RELOC("prom_hold_cpus: end...\n"));
-#endif
-}
-
-static void __init smt_setup(void)
-{
-       char *p, *q;
-       char my_smt_enabled = SMT_DYNAMIC;
-       ihandle prom_options = NULL;
-       char option[9];
-       unsigned long offset = reloc_offset();
-        struct naca_struct *_naca = RELOC(naca);
-       char found = 0;
-
-       if (strstr(RELOC(cmd_line), RELOC("smt-enabled="))) {
-               for (q = RELOC(cmd_line); (p = strstr(q, RELOC("smt-enabled="))) != 0; ) {
-                       q = p + 12;
-                       if (p > RELOC(cmd_line) && p[-1] != ' ')
-                               continue;
-                       found = 1;
-                       if (q[0] == 'o' && q[1] == 'f' && 
-                           q[2] == 'f' && (q[3] == ' ' || q[3] == '\0')) {
-                               my_smt_enabled = SMT_OFF;
-                       } else if (q[0]=='o' && q[1] == 'n' && 
-                                  (q[2] == ' ' || q[2] == '\0')) {
-                               my_smt_enabled = SMT_ON;
-                       } else {
-                               my_smt_enabled = SMT_DYNAMIC;
-                       } 
-               }
-       }
-       if (!found) {
-               prom_options = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/options"));
-               if (prom_options != (ihandle) -1) {
-                       call_prom(RELOC("getprop"), 
-                               4, 1, prom_options,
-                               RELOC("ibm,smt-enabled"), 
-                               option, 
-                               sizeof(option));
-                       if (option[0] != 0) {
-                               found = 1;
-                               if (!strcmp(option, RELOC("off")))
-                                       my_smt_enabled = SMT_OFF;
-                               else if (!strcmp(option, RELOC("on")))
-                                       my_smt_enabled = SMT_ON;
-                               else
-                                       my_smt_enabled = SMT_DYNAMIC;
-                       }
-               }
-       }
-
-       if (!found )
-               my_smt_enabled = SMT_DYNAMIC; /* default to on */
-
-       _naca->smt_state = my_smt_enabled;
-}
-
-
-#ifdef CONFIG_BOOTX_TEXT
-
-/* This function will enable the early boot text when doing OF booting. This
- * way, xmon output should work too
- */
-static void __init setup_disp_fake_bi(ihandle dp)
-{
-       int width = 640, height = 480, depth = 8, pitch;
-       unsigned address;
-       struct pci_reg_property addrs[8];
-       int i, naddrs;
-       char name[64];
-       unsigned long offset = reloc_offset();
-       char *getprop = RELOC("getprop");
-
-       prom_print(RELOC("Initializing fake screen: "));
-
-       memset(name, 0, sizeof(name));
-       call_prom(getprop, 4, 1, dp, RELOC("name"), name, sizeof(name));
-       name[sizeof(name)-1] = 0;
-       prom_print(name);
-       prom_print(RELOC("\n"));
-       call_prom(getprop, 4, 1, dp, RELOC("width"), &width, sizeof(width));
-       call_prom(getprop, 4, 1, dp, RELOC("height"), &height, sizeof(height));
-       call_prom(getprop, 4, 1, dp, RELOC("depth"), &depth, sizeof(depth));
-       pitch = width * ((depth + 7) / 8);
-       call_prom(getprop, 4, 1, dp, RELOC("linebytes"),
-                 &pitch, sizeof(pitch));
-       if (pitch == 1)
-               pitch = 0x1000;         /* for strange IBM display */
-       address = 0;
-
-       prom_print(RELOC("width "));
-       prom_print_hex(width);
-       prom_print(RELOC(" height "));
-       prom_print_hex(height);
-       prom_print(RELOC(" depth "));
-       prom_print_hex(depth);
-       prom_print(RELOC(" linebytes "));
-       prom_print_hex(pitch);
-       prom_print(RELOC("\n"));
-
-
-       call_prom(getprop, 4, 1, dp, RELOC("address"),
-                 &address, sizeof(address));
-       if (address == 0) {
-               /* look for an assigned address with a size of >= 1MB */
-               naddrs = (int) call_prom(getprop, 4, 1, dp,
-                               RELOC("assigned-addresses"),
-                               addrs, sizeof(addrs));
-               naddrs /= sizeof(struct pci_reg_property);
-               for (i = 0; i < naddrs; ++i) {
-                       if (addrs[i].size_lo >= (1 << 20)) {
-                               address = addrs[i].addr.a_lo;
-                               /* use the BE aperture if possible */
-                               if (addrs[i].size_lo >= (16 << 20))
-                                       address += (8 << 20);
-                               break;
-                       }
-               }
-               if (address == 0) {
-                       prom_print(RELOC("Failed to get address of frame buffer\n"));
-                       return;
-               }
-       }
-       btext_setup_display(width, height, depth, pitch, address);
-       prom_print(RELOC("Addr of fb: "));
-       prom_print_hex(address);
-       prom_print_nl();
-       RELOC(boot_text_mapped) = 0;
-}
-#endif /* CONFIG_BOOTX_TEXT */
-
-static void __init prom_init_client_services(unsigned long pp)
-{
-       unsigned long offset = reloc_offset();
-       struct prom_t *_prom = PTRRELOC(&prom);
-
-       /* Get a handle to the prom entry point before anything else */
-       _prom->entry = pp;
-
-       /* Init default value for phys size */
-       _prom->encode_phys_size = 32;
-
-       /* get a handle for the stdout device */
-       _prom->chosen = (ihandle)call_prom(RELOC("finddevice"), 1, 1,
-                                      RELOC("/chosen"));
-       if ((long)_prom->chosen <= 0)
-               prom_panic(RELOC("cannot find chosen")); /* msg won't be printed :( */
-
-       /* get device tree root */
-       _prom->root = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/"));
-       if ((long)_prom->root <= 0)
-               prom_panic(RELOC("cannot find device tree root")); /* msg won't be printed :( */
-}
-
-static void __init prom_init_stdout(void)
-{
-       unsigned long offset = reloc_offset();
-       struct prom_t *_prom = PTRRELOC(&prom);
-       u32 val;
-
-        if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
-                           RELOC("stdout"), &val,
-                           sizeof(val)) <= 0)
-                prom_panic(RELOC("cannot find stdout"));
-
-        _prom->stdout = (ihandle)(unsigned long)val;
-}
-
-static int __init prom_find_machine_type(void)
-{
-       unsigned long offset = reloc_offset();
-       struct prom_t *_prom = PTRRELOC(&prom);
-       char compat[256];
-       int len, i = 0;
-
-       len = (int)(long)call_prom(RELOC("getprop"), 4, 1, _prom->root,
-                                  RELOC("compatible"),
-                                  compat, sizeof(compat)-1);
-       if (len > 0) {
-               compat[len] = 0;
-               while (i < len) {
-                       char *p = &compat[i];
-                       int sl = strlen(p);
-                       if (sl == 0)
-                               break;
-                       if (strstr(p, RELOC("Power Macintosh")) ||
-                           strstr(p, RELOC("MacRISC4")))
-                               return PLATFORM_POWERMAC;
-                       i += sl + 1;
-               }
-       }
-       /* Default to pSeries */
-       return PLATFORM_PSERIES;
-}
-
-static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
-{
-       unsigned long offset = reloc_offset();
-
-       return (int)(long)call_prom(RELOC("call-method"), 6, 1,
-                                   RELOC("color!"),
-                                    ih,
-                                    (void *)(long) i,
-                                    (void *)(long) b,
-                                    (void *)(long) g,
-                                    (void *)(long) r );
-}
-
-/*
- * If we have a display that we don't know how to drive,
- * we will want to try to execute OF's open method for it
- * later.  However, OF will probably fall over if we do that
- * we've taken over the MMU.
- * So we check whether we will need to open the display,
- * and if so, open it now.
- */
-static unsigned long __init check_display(unsigned long mem)
-{
-       phandle node;
-       ihandle ih;
-       int i, j;
-       unsigned long offset = reloc_offset();
-        struct prom_t *_prom = PTRRELOC(&prom);
-       char type[16], *path;
-       static unsigned char default_colors[] = {
-               0x00, 0x00, 0x00,
-               0x00, 0x00, 0xaa,
-               0x00, 0xaa, 0x00,
-               0x00, 0xaa, 0xaa,
-               0xaa, 0x00, 0x00,
-               0xaa, 0x00, 0xaa,
-               0xaa, 0xaa, 0x00,
-               0xaa, 0xaa, 0xaa,
-               0x55, 0x55, 0x55,
-               0x55, 0x55, 0xff,
-               0x55, 0xff, 0x55,
-               0x55, 0xff, 0xff,
-               0xff, 0x55, 0x55,
-               0xff, 0x55, 0xff,
-               0xff, 0xff, 0x55,
-               0xff, 0xff, 0xff
-       };
-       const unsigned char *clut;
-
-       _prom->disp_node = 0;
-
-       prom_print(RELOC("Looking for displays\n"));
-       if (RELOC(of_stdout_device) != 0) {
-               prom_print(RELOC("OF stdout is    : "));
-               prom_print(PTRRELOC(RELOC(of_stdout_device)));
-               prom_print(RELOC("\n"));
-       }
-       for (node = 0; prom_next_node(&node); ) {
-               type[0] = 0;
-               call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
-                         type, sizeof(type));
-               if (strcmp(type, RELOC("display")) != 0)
-                       continue;
-               /* It seems OF doesn't null-terminate the path :-( */
-               path = (char *) mem;
-               memset(path, 0, 256);
-
-               /*
-                * leave some room at the end of the path for appending extra
-                * arguments
-                */
-               if ((long) call_prom(RELOC("package-to-path"), 3, 1,
-                                   node, path, 250) < 0)
-                       continue;
-               prom_print(RELOC("found display   : "));
-               prom_print(path);
-               prom_print(RELOC("\n"));
-               
-               /*
-                * If this display is the device that OF is using for stdout,
-                * move it to the front of the list.
-                */
-               mem += strlen(path) + 1;
-               i = RELOC(prom_num_displays);
-               RELOC(prom_num_displays) = i + 1;
-               if (RELOC(of_stdout_device) != 0 && i > 0
-                   && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) {
-                       for (; i > 0; --i) {
-                               RELOC(prom_display_paths[i])
-                                       = RELOC(prom_display_paths[i-1]);
-                               RELOC(prom_display_nodes[i])
-                                       = RELOC(prom_display_nodes[i-1]);
-                       }
-                       _prom->disp_node = (ihandle)(unsigned long)node;
-               }
-               RELOC(prom_display_paths[i]) = PTRUNRELOC(path);
-               RELOC(prom_display_nodes[i]) = node;
-               if (_prom->disp_node == 0)
-                       _prom->disp_node = (ihandle)(unsigned long)node;
-               if (RELOC(prom_num_displays) >= FB_MAX)
-                       break;
-       }
-       prom_print(RELOC("Opening displays...\n"));
-       for (j = RELOC(prom_num_displays) - 1; j >= 0; j--) {
-               path = PTRRELOC(RELOC(prom_display_paths[j]));
-               prom_print(RELOC("opening display : "));
-               prom_print(path);
-               ih = (ihandle)call_prom(RELOC("open"), 1, 1, path);
-               if (ih == (ihandle)0 || ih == (ihandle)-1) {
-                       prom_print(RELOC("... failed\n"));
-                       continue;
-               }
-
-               prom_print(RELOC("... done\n"));
-
-               /* Setup a useable color table when the appropriate
-                * method is available. Should update this to set-colors */
-               clut = RELOC(default_colors);
-               for (i = 0; i < 32; i++, clut += 3)
-                       if (prom_set_color(ih, i, clut[0], clut[1],
-                                          clut[2]) != 0)
-                               break;
-
-#ifdef CONFIG_LOGO_LINUX_CLUT224
-               clut = PTRRELOC(RELOC(logo_linux_clut224.clut));
-               for (i = 0; i < RELOC(logo_linux_clut224.clutsize); i++, clut += 3)
-                       if (prom_set_color(ih, i + 32, clut[0], clut[1],
-                                          clut[2]) != 0)
-                               break;
-#endif /* CONFIG_LOGO_LINUX_CLUT224 */
-       }
-       
-       return DOUBLEWORD_ALIGN(mem);
-}
-
-/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
-static void __init *__make_room(unsigned long *mem_start, unsigned long *mem_end,
-                               unsigned long needed, unsigned long align)
-{
-       void *ret;
-       unsigned long offset = reloc_offset();
-
-       *mem_start = ALIGN(*mem_start, align);
-       if (*mem_start + needed > *mem_end) {
-#ifdef CONFIG_BLK_DEV_INITRD
-               /* FIXME: Apple OF doesn't map unclaimed mem.  If this
-                * ever happened on G5, we'd need to fix. */
-               unsigned long initrd_len;
-
-               if (*mem_end != RELOC(initrd_start))
-                       prom_panic(RELOC("No memory for copy_device_tree"));
-
-               prom_print(RELOC("Huge device_tree: moving initrd\n"));
-               /* Move by 4M. */
-               initrd_len = RELOC(initrd_end) - RELOC(initrd_start);
-               *mem_end = RELOC(initrd_start) + 4 * 1024 * 1024;
-               memmove((void *)*mem_end, (void *)RELOC(initrd_start),
-                       initrd_len);
-               RELOC(initrd_start) = *mem_end;
-               RELOC(initrd_end) = RELOC(initrd_start) + initrd_len;
-#else
-               prom_panic(RELOC("No memory for copy_device_tree"));
-#endif
-       }
-
-       ret = (void *)*mem_start;
-       *mem_start += needed;
-
-       return ret;
-}
-
-#define make_room(startp, endp, type) \
-       __make_room(startp, endp, sizeof(type), __alignof__(type))
-
-static void __init
-inspect_node(phandle node, struct device_node *dad,
-            unsigned long *mem_start, unsigned long *mem_end,
-            struct device_node ***allnextpp)
-{
-       int l;
-       phandle child;
-       struct device_node *np;
-       struct property *pp, **prev_propp;
-       char *prev_name, *namep;
-       unsigned char *valp;
-       unsigned long offset = reloc_offset();
-       phandle ibm_phandle;
-
-       np = make_room(mem_start, mem_end, struct device_node);
-       memset(np, 0, sizeof(*np));
-
-       np->node = node;
-       **allnextpp = PTRUNRELOC(np);
-       *allnextpp = &np->allnext;
-       if (dad != 0) {
-               np->parent = PTRUNRELOC(dad);
-               /* we temporarily use the `next' field as `last_child'. */
-               if (dad->next == 0)
-                       dad->child = PTRUNRELOC(np);
-               else
-                       dad->next->sibling = PTRUNRELOC(np);
-               dad->next = np;
-       }
-
-       /* get and store all properties */
-       prev_propp = &np->properties;
-       prev_name = RELOC("");
-       for (;;) {
-               /* 32 is max len of name including nul. */
-               namep = make_room(mem_start, mem_end, char[32]);
-               if ((long) call_prom(RELOC("nextprop"), 3, 1, node, prev_name,
-                                    namep) <= 0) {
-                       /* No more nodes: unwind alloc */
-                       *mem_start = (unsigned long)namep;
-                       break;
-               }
-               /* Trim off some if we can */
-               *mem_start = DOUBLEWORD_ALIGN((unsigned long)namep
-                                            + strlen(namep) + 1);
-               pp = make_room(mem_start, mem_end, struct property);
-               pp->name = PTRUNRELOC(namep);
-               prev_name = namep;
-
-               pp->length = call_prom(RELOC("getproplen"), 2, 1, node, namep);
-               if (pp->length < 0)
-                       continue;
-               if (pp->length > MAX_PROPERTY_LENGTH) {
-                       char path[128];
-
-                       prom_print(RELOC("WARNING: ignoring large property "));
-                       /* It seems OF doesn't null-terminate the path :-( */
-                       memset(path, 0, sizeof(path));
-                       if (call_prom(RELOC("package-to-path"), 3, 1, node,
-                            path, sizeof(path)-1) > 0)
-                               prom_print(path);
-                       prom_print(namep);
-                       prom_print(RELOC(" length 0x"));
-                       prom_print_hex(pp->length);
-                       prom_print_nl();
-
-                       continue;
-               }
-               valp = __make_room(mem_start, mem_end, pp->length, 1);
-               pp->value = PTRUNRELOC(valp);
-               call_prom(RELOC("getprop"), 4, 1, node, namep,valp,pp->length);
-               *prev_propp = PTRUNRELOC(pp);
-               prev_propp = &pp->next;
-       }
-
-       /* Add a "linux,phandle" property. */
-       namep = make_room(mem_start, mem_end, char[16]);
-       strcpy(namep, RELOC("linux,phandle"));
-       pp = make_room(mem_start, mem_end, struct property);
-       pp->name = PTRUNRELOC(namep);
-       pp->length = sizeof(phandle);
-       valp = make_room(mem_start, mem_end, phandle);
-       pp->value = PTRUNRELOC(valp);
-       *(phandle *)valp = node;
-       *prev_propp = PTRUNRELOC(pp);
-       pp->next = NULL;
-
-       /* Set np->linux_phandle to the value of the ibm,phandle property
-          if it exists, otherwise to the phandle for this node. */
-       np->linux_phandle = node;
-       if ((int)call_prom(RELOC("getprop"), 4, 1, node, RELOC("ibm,phandle"),
-                          &ibm_phandle, sizeof(ibm_phandle)) > 0)
-               np->linux_phandle = ibm_phandle;
-
-       /* get the node's full name */
-       namep = (char *)*mem_start;
-       l = (long) call_prom(RELOC("package-to-path"), 3, 1, node,
-                            namep, *mem_end - *mem_start);
-       if (l >= 0) {
-               /* Didn't fit?  Get more room. */
-               if (l+1 > *mem_end - *mem_start) {
-                       namep = __make_room(mem_start, mem_end, l+1, 1);
-                       call_prom(RELOC("package-to-path"),3,1,node,namep,l);
-               }
-               np->full_name = PTRUNRELOC(namep);
-               namep[l] = '\0';
-               *mem_start = DOUBLEWORD_ALIGN(*mem_start + l + 1);
-       }
-
-       /* do all our children */
-       child = call_prom(RELOC("child"), 1, 1, node);
-       while (child != (phandle)0) {
-               inspect_node(child, np, mem_start, mem_end,
-                                        allnextpp);
-               child = call_prom(RELOC("peer"), 1, 1, child);
-       }
-}
-
-/*
- * Make a copy of the device tree from the PROM.
- */
-static unsigned long __init
-copy_device_tree(unsigned long mem_start)
-{
-       phandle root;
-       struct device_node **allnextp;
-       unsigned long offset = reloc_offset();
-       unsigned long mem_end;
-
-       /* We pass mem_end-mem_start to OF: keep it well under 32-bit */
-       mem_end = mem_start + 1024*1024*1024;
-#ifdef CONFIG_BLK_DEV_INITRD
-       if (RELOC(initrd_start) && RELOC(initrd_start) > mem_start)
-               mem_end = RELOC(initrd_start);
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-       root = call_prom(RELOC("peer"), 1, 1, (phandle)0);
-       if (root == (phandle)0) {
-               prom_panic(RELOC("couldn't get device tree root\n"));
-       }
-       allnextp = &RELOC(allnodes);
-       inspect_node(root, 0, &mem_start, &mem_end, &allnextp);
-       *allnextp = 0;
-       return mem_start;
-}
-
-/* Verify bi_recs are good */
-static struct bi_record * __init prom_bi_rec_verify(struct bi_record *bi_recs)
-{
-       struct bi_record *first, *last;
-#ifdef DEBUG_PROM
-       unsigned long offset = reloc_offset();
-
-       prom_print(RELOC("birec_verify: r6=0x"));
-       prom_print_hex((unsigned long)bi_recs);
-       prom_print_nl();
-       if (bi_recs != NULL) {
-               prom_print(RELOC("  tag=0x"));
-               prom_print_hex(bi_recs->tag);
-               prom_print_nl();
-       }
-#endif /* DEBUG_PROM */
-
-       if ( bi_recs == NULL || bi_recs->tag != BI_FIRST )
-               return NULL;
-
-       last = (struct bi_record *)(long)bi_recs->data[0];
-
-#ifdef DEBUG_PROM
-       prom_print(RELOC("  last=0x"));
-       prom_print_hex((unsigned long)last);
-       prom_print_nl();
-       if (last != NULL) {
-               prom_print(RELOC("  last_tag=0x"));
-               prom_print_hex(last->tag);
-               prom_print_nl();
-       }
-#endif /* DEBUG_PROM */
-
-       if ( last == NULL || last->tag != BI_LAST )
-               return NULL;
-
-       first = (struct bi_record *)(long)last->data[0];
-#ifdef DEBUG_PROM
-       prom_print(RELOC("  first=0x"));
-       prom_print_hex((unsigned long)first);
-       prom_print_nl();
-#endif /* DEBUG_PROM */
-
-       if ( first == NULL || first != bi_recs )
-               return NULL;
-
-       return bi_recs;
-}
-
-static void __init prom_bi_rec_reserve(void)
-{
-       unsigned long offset = reloc_offset();
-       struct prom_t *_prom = PTRRELOC(&prom);
-       struct bi_record *rec;
-
-       if ( _prom->bi_recs != NULL) {
-
-               for ( rec=_prom->bi_recs;
-                     rec->tag != BI_LAST;
-                     rec=bi_rec_next(rec) ) {
-#ifdef DEBUG_PROM
-                       prom_print(RELOC("bi: 0x"));
-                       prom_print_hex(rec->tag);
-                       prom_print_nl();
-#endif /* DEBUG_PROM */
-                       switch (rec->tag) {
-#ifdef CONFIG_BLK_DEV_INITRD
-                       case BI_INITRD:
-                               RELOC(initrd_start) = (unsigned long)(rec->data[0]);
-                               RELOC(initrd_end) = RELOC(initrd_start) + rec->data[1];
-                               break;
-#endif /* CONFIG_BLK_DEV_INITRD */
-                       }
-               }
-               /* The next use of this field will be after relocation
-                * is enabled, so convert this physical address into a
-                * virtual address.
-                */
-               _prom->bi_recs = PTRUNRELOC(_prom->bi_recs);
-       }
-}
-
-/*
- * We enter here early on, when the Open Firmware prom is still
- * handling exceptions and the MMU hash table for us.
- */
-
-unsigned long __init
-prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
-         unsigned long r6, unsigned long r7)
-{
-       unsigned long mem;
-       ihandle prom_cpu;
-       phandle cpu_pkg;
-       unsigned long offset = reloc_offset();
-       long l;
-       char *p, *d;
-       unsigned long phys;
-       u32 getprop_rval;
-       struct systemcfg *_systemcfg;
-       struct paca_struct *_xPaca = PTRRELOC(&paca[0]);
-       struct prom_t *_prom = PTRRELOC(&prom);
-
-       /* First zero the BSS -- use memset, some arches don't have
-        * caches on yet */
-       memset(PTRRELOC(&__bss_start), 0, __bss_stop - __bss_start);
-
-       /* Setup systemcfg and NACA pointers now */
-       RELOC(systemcfg) = _systemcfg = (struct systemcfg *)(SYSTEMCFG_VIRT_ADDR - offset);
-       RELOC(naca) = (struct naca_struct *)(NACA_VIRT_ADDR - offset);
-
-       /* Init interface to Open Firmware and pickup bi-recs */
-       prom_init_client_services(pp);
-
-       /* Init prom stdout device */
-       prom_init_stdout();
-
-#ifdef DEBUG_PROM
-       prom_print(RELOC("klimit=0x"));
-       prom_print_hex(RELOC(klimit));
-       prom_print_nl();
-       prom_print(RELOC("offset=0x"));
-       prom_print_hex(offset);
-       prom_print_nl();
-       prom_print(RELOC("->mem=0x"));
-       prom_print_hex(RELOC(klimit) - offset);
-       prom_print_nl();
-#endif /* DEBUG_PROM */
-
-       /* check out if we have bi_recs */
-       _prom->bi_recs = prom_bi_rec_verify((struct bi_record *)r6);
-       if ( _prom->bi_recs != NULL ) {
-               RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs +
-                                          _prom->bi_recs->data[1]);
-#ifdef DEBUG_PROM
-               prom_print(RELOC("bi_recs=0x"));
-               prom_print_hex((unsigned long)_prom->bi_recs);
-               prom_print_nl();
-               prom_print(RELOC("new mem=0x"));
-               prom_print_hex(RELOC(klimit) - offset);
-               prom_print_nl();
-#endif /* DEBUG_PROM */
-       }
-
-       /* If we don't have birec's or didn't find them, check for an initrd
-        * using the "yaboot" way
-        */
-#ifdef CONFIG_BLK_DEV_INITRD
-       if ( _prom->bi_recs == NULL && r3 && r4 && r4 != 0xdeadbeef) {
-               RELOC(initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3;
-               RELOC(initrd_end) = RELOC(initrd_start) + r4;
-               RELOC(initrd_below_start_ok) = 1;
-       }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-       /* Default machine type. */
-       _systemcfg->platform = prom_find_machine_type();
-
-       /* On pSeries, copy the CPU hold code */
-       if (_systemcfg->platform == PLATFORM_PSERIES)
-               copy_and_flush(0, KERNELBASE - offset, 0x100, 0);
-
-       /* Start storing things at klimit */
-       mem = RELOC(klimit) - offset;
-
-       /* Get the full OF pathname of the stdout device */
-       p = (char *) mem;
-       memset(p, 0, 256);
-       call_prom(RELOC("instance-to-path"), 3, 1, _prom->stdout, p, 255);
-       RELOC(of_stdout_device) = PTRUNRELOC(p);
-       mem += strlen(p) + 1;
-
-       getprop_rval = 1;
-       call_prom(RELOC("getprop"), 4, 1,
-                 _prom->root, RELOC("#size-cells"),
-                 &getprop_rval, sizeof(getprop_rval));
-       _prom->encode_phys_size = (getprop_rval == 1) ? 32 : 64;
-
-       /* Determine which cpu is actually running right _now_ */
-        if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
-                           RELOC("cpu"), &getprop_rval,
-                           sizeof(getprop_rval)) <= 0)
-                prom_panic(RELOC("cannot find boot cpu"));
-
-       prom_cpu = (ihandle)(unsigned long)getprop_rval;
-       cpu_pkg = call_prom(RELOC("instance-to-package"), 1, 1, prom_cpu);
-       call_prom(RELOC("getprop"), 4, 1,
-               cpu_pkg, RELOC("reg"),
-               &getprop_rval, sizeof(getprop_rval));
-       _prom->cpu = (int)(unsigned long)getprop_rval;
-       _xPaca[0].xHwProcNum = _prom->cpu;
-
-       RELOC(boot_cpuid) = 0;
-
-#ifdef DEBUG_PROM
-       prom_print(RELOC("Booting CPU hw index = 0x"));
-       prom_print_hex(_prom->cpu);
-       prom_print_nl();
-#endif
-
-       /* Get the boot device and translate it to a full OF pathname. */
-       p = (char *) mem;
-       l = (long) call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
-                           RELOC("bootpath"), p, 1<<20);
-       if (l > 0) {
-               p[l] = 0;       /* should already be null-terminated */
-               RELOC(bootpath) = PTRUNRELOC(p);
-               mem += l + 1;
-               d = (char *) mem;
-               *d = 0;
-               call_prom(RELOC("canon"), 3, 1, p, d, 1<<20);
-               RELOC(bootdevice) = PTRUNRELOC(d);
-               mem = DOUBLEWORD_ALIGN(mem + strlen(d) + 1);
-       }
-
-       RELOC(cmd_line[0]) = 0;
-       if ((long)_prom->chosen > 0) {
-               call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
-                         RELOC("bootargs"), p, sizeof(cmd_line));
-               if (p != NULL && p[0] != 0)
-                       strlcpy(RELOC(cmd_line), p, sizeof(cmd_line));
-       }
-
-       early_cmdline_parse();
-
-       prom_initialize_lmb();
-
-       prom_bi_rec_reserve();
-
-       mem = check_display(mem);
-
-       if (_systemcfg->platform != PLATFORM_POWERMAC)
-               prom_instantiate_rtas();
-
-        /* Initialize some system info into the Naca early... */
-        prom_initialize_naca();
-
-       smt_setup();
-
-        /* If we are on an SMP machine, then we *MUST* do the
-         * following, regardless of whether we have an SMP
-         * kernel or not.
-         */
-       prom_hold_cpus(mem);
-
-#ifdef DEBUG_PROM
-       prom_print(RELOC("after basic inits, mem=0x"));
-       prom_print_hex(mem);
-       prom_print_nl();
-#ifdef CONFIG_BLK_DEV_INITRD
-       prom_print(RELOC("initrd_start=0x"));
-       prom_print_hex(RELOC(initrd_start));
-       prom_print_nl();
-       prom_print(RELOC("initrd_end=0x"));
-       prom_print_hex(RELOC(initrd_end));
-       prom_print_nl();
-#endif /* CONFIG_BLK_DEV_INITRD */
-       prom_print(RELOC("copying OF device tree...\n"));
-#endif /* DEBUG_PROM */
-       mem = copy_device_tree(mem);
-
-       RELOC(klimit) = mem + offset;
-
-#ifdef DEBUG_PROM
-       prom_print(RELOC("new klimit is\n"));
-       prom_print(RELOC("klimit=0x"));
-       prom_print_hex(RELOC(klimit));
-       prom_print(RELOC(" ->mem=0x\n"));
-       prom_print(RELOC("klimit=0x"));
-       prom_print_hex(mem);
-       prom_print_nl();
-#endif /* DEBUG_PROM */
-
-       lmb_reserve(0, __pa(RELOC(klimit)));
-
-#ifdef CONFIG_BLK_DEV_INITRD
-       if (RELOC(initrd_start)) {
-               unsigned long initrd_len;
-               initrd_len = RELOC(initrd_end) - RELOC(initrd_start);
-
-               /* Move initrd if it's where we're going to copy kernel. */
-               if (RELOC(initrd_start) < __pa(RELOC(klimit))) {
-                       memmove((void *)mem, (void *)RELOC(initrd_start),
-                               initrd_len);
-                       RELOC(initrd_start) = mem;
-                       RELOC(initrd_end) = mem + initrd_len;
-               }
-
-               lmb_reserve(RELOC(initrd_start), initrd_len);
-       }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-       if (_systemcfg->platform == PLATFORM_PSERIES)
-               prom_initialize_tce_table();
+static int __initdata dt_root_addr_cells;
+static int __initdata dt_root_size_cells;
+static int __initdata iommu_is_off;
+int __initdata iommu_force_on;
+typedef u32 cell_t;
 
-#ifdef CONFIG_PMAC_DART
-       if (_systemcfg->platform == PLATFORM_POWERMAC)
-               prom_initialize_dart_table();
+#if 0
+static struct boot_param_header *initial_boot_params __initdata;
+#else
+struct boot_param_header *initial_boot_params;
 #endif
 
-#ifdef CONFIG_BOOTX_TEXT
-       if(_prom->disp_node) {
-               prom_print(RELOC("Setting up bi display...\n"));
-               setup_disp_fake_bi(_prom->disp_node);
-       }
-#endif /* CONFIG_BOOTX_TEXT */
-
-       prom_print(RELOC("Calling quiesce ...\n"));
-       call_prom(RELOC("quiesce"), 0, 0);
-       phys = KERNELBASE - offset;
+static struct device_node *allnodes = NULL;
 
-#ifdef CONFIG_BLK_DEV_INITRD
-       /* If we had an initrd, we convert its address to virtual */
-       if (RELOC(initrd_start)) {
-               RELOC(initrd_start) = (unsigned long)__va(RELOC(initrd_start));
-               RELOC(initrd_end) = (unsigned long)__va(RELOC(initrd_end));
-       }
-#endif /* CONFIG_BLK_DEV_INITRD */
+/* use when traversing tree through the allnext, child, sibling,
+ * or parent members of struct device_node.
+ */
+static DEFINE_RWLOCK(devtree_lock);
 
-       prom_print(RELOC("returning from prom_init\n"));
-       return phys;
-}
+/* export that to outside world */
+struct device_node *of_chosen;
 
 /*
  * Find the device_node with a given phandle.
  */
-static struct device_node * __devinit
-find_phandle(phandle ph)
+static struct device_node * find_phandle(phandle ph)
 {
        struct device_node *np;
 
@@ -2056,8 +116,7 @@ find_phandle(phandle ph)
 /*
  * Find the interrupt parent of a node.
  */
-static struct device_node * __devinit
-intr_parent(struct device_node *p)
+static struct device_node * __devinit intr_parent(struct device_node *p)
 {
        phandle *parp;
 
@@ -2071,8 +130,7 @@ intr_parent(struct device_node *p)
  * Find out the size of each entry of the interrupts property
  * for a node.
  */
-static int __devinit
-prom_n_intr_cells(struct device_node *np)
+int __devinit prom_n_intr_cells(struct device_node *np)
 {
        struct device_node *p;
        unsigned int *icp;
@@ -2086,7 +144,7 @@ prom_n_intr_cells(struct device_node *np)
                    || get_property(p, "interrupt-map", NULL) != NULL) {
                        printk("oops, node %s doesn't have #interrupt-cells\n",
                               p->full_name);
-               return 1;
+                       return 1;
                }
        }
 #ifdef DEBUG_IRQ
@@ -2099,14 +157,14 @@ prom_n_intr_cells(struct device_node *np)
  * Map an interrupt from a device up to the platform interrupt
  * descriptor.
  */
-static int __devinit
-map_interrupt(unsigned int **irq, struct device_node **ictrler,
-             struct device_node *np, unsigned int *ints, int nintrc)
+static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictrler,
+                                  struct device_node *np, unsigned int *ints,
+                                  int nintrc)
 {
        struct device_node *p, *ipar;
        unsigned int *imap, *imask, *ip;
        int i, imaplen, match;
-       int newintrc, newaddrc;
+       int newintrc = 0, newaddrc = 0;
        unsigned int *reg;
        int naddrc;
 
@@ -2195,9 +253,9 @@ map_interrupt(unsigned int **irq, struct device_node **ictrler,
        return nintrc;
 }
 
-static unsigned long __init
-finish_node_interrupts(struct device_node *np, unsigned long mem_start,
-                      int measure_only)
+static unsigned long __init finish_node_interrupts(struct device_node *np,
+                                                  unsigned long mem_start,
+                                                  int measure_only)
 {
        unsigned int *ints;
        int intlen, intrcells, intrcount;
@@ -2258,9 +316,10 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start,
        return mem_start;
 }
 
-static unsigned long __init
-interpret_pci_props(struct device_node *np, unsigned long mem_start,
-                   int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_pci_props(struct device_node *np,
+                                               unsigned long mem_start,
+                                               int naddrc, int nsizec,
+                                               int measure_only)
 {
        struct address_range *adr;
        struct pci_reg_property *pci_addrs;
@@ -2272,7 +331,7 @@ interpret_pci_props(struct device_node *np, unsigned long mem_start,
                i = 0;
                adr = (struct address_range *) mem_start;
                while ((l -= sizeof(struct pci_reg_property)) >= 0) {
-                       if (!measure_only) {
+                       if (!measure_only) {
                                adr[i].space = pci_addrs[i].addr.a_hi;
                                adr[i].address = pci_addrs[i].addr.a_lo;
                                adr[i].size = pci_addrs[i].size_lo;
@@ -2286,9 +345,10 @@ interpret_pci_props(struct device_node *np, unsigned long mem_start,
        return mem_start;
 }
 
-static unsigned long __init
-interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
-                     int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_dbdma_props(struct device_node *np,
+                                                 unsigned long mem_start,
+                                                 int naddrc, int nsizec,
+                                                 int measure_only)
 {
        struct reg_property32 *rp;
        struct address_range *adr;
@@ -2311,7 +371,7 @@ interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
                i = 0;
                adr = (struct address_range *) mem_start;
                while ((l -= sizeof(struct reg_property32)) >= 0) {
-                       if (!measure_only) {
+                       if (!measure_only) {
                                adr[i].space = 2;
                                adr[i].address = rp[i].address + base_address;
                                adr[i].size = rp[i].size;
@@ -2326,9 +386,10 @@ interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
        return mem_start;
 }
 
-static unsigned long __init
-interpret_macio_props(struct device_node *np, unsigned long mem_start,
-                     int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_macio_props(struct device_node *np,
+                                                 unsigned long mem_start,
+                                                 int naddrc, int nsizec,
+                                                 int measure_only)
 {
        struct reg_property32 *rp;
        struct address_range *adr;
@@ -2351,7 +412,7 @@ interpret_macio_props(struct device_node *np, unsigned long mem_start,
                i = 0;
                adr = (struct address_range *) mem_start;
                while ((l -= sizeof(struct reg_property32)) >= 0) {
-                       if (!measure_only) {
+                       if (!measure_only) {
                                adr[i].space = 2;
                                adr[i].address = rp[i].address + base_address;
                                adr[i].size = rp[i].size;
@@ -2366,9 +427,10 @@ interpret_macio_props(struct device_node *np, unsigned long mem_start,
        return mem_start;
 }
 
-static unsigned long __init
-interpret_isa_props(struct device_node *np, unsigned long mem_start,
-                   int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_isa_props(struct device_node *np,
+                                               unsigned long mem_start,
+                                               int naddrc, int nsizec,
+                                               int measure_only)
 {
        struct isa_reg_property *rp;
        struct address_range *adr;
@@ -2378,8 +440,8 @@ interpret_isa_props(struct device_node *np, unsigned long mem_start,
        if (rp != 0 && l >= sizeof(struct isa_reg_property)) {
                i = 0;
                adr = (struct address_range *) mem_start;
-               while ((l -= sizeof(struct reg_property)) >= 0) {
-                       if (!measure_only) {
+               while ((l -= sizeof(struct isa_reg_property)) >= 0) {
+                       if (!measure_only) {
                                adr[i].space = rp[i].space;
                                adr[i].address = rp[i].address;
                                adr[i].size = rp[i].size;
@@ -2394,9 +456,10 @@ interpret_isa_props(struct device_node *np, unsigned long mem_start,
        return mem_start;
 }
 
-static unsigned long __init
-interpret_root_props(struct device_node *np, unsigned long mem_start,
-                    int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_root_props(struct device_node *np,
+                                                unsigned long mem_start,
+                                                int naddrc, int nsizec,
+                                                int measure_only)
 {
        struct address_range *adr;
        int i, l;
@@ -2408,7 +471,7 @@ interpret_root_props(struct device_node *np, unsigned long mem_start,
                i = 0;
                adr = (struct address_range *) mem_start;
                while ((l -= rpsize) >= 0) {
-                       if (!measure_only) {
+                       if (!measure_only) {
                                adr[i].space = 0;
                                adr[i].address = rp[naddrc - 1];
                                adr[i].size = rp[naddrc + nsizec - 1];
@@ -2424,21 +487,15 @@ interpret_root_props(struct device_node *np, unsigned long mem_start,
        return mem_start;
 }
 
-static unsigned long __init
-finish_node(struct device_node *np, unsigned long mem_start,
-           interpret_func *ifunc, int naddrc, int nsizec, int measure_only)
+static unsigned long __init finish_node(struct device_node *np,
+                                       unsigned long mem_start,
+                                       interpret_func *ifunc,
+                                       int naddrc, int nsizec,
+                                       int measure_only)
 {
        struct device_node *child;
        int *ip;
 
-       np->name = get_property(np, "name", 0);
-       np->type = get_property(np, "device_type", 0);
-
-       if (!np->name)
-               np->name = "<NULL>";
-       if (!np->type)
-               np->type = "<NULL>";
-
        /* get the device addresses and interrupts */
        if (ifunc != NULL)
                mem_start = ifunc(np, mem_start, naddrc, nsizec, measure_only);
@@ -2446,10 +503,10 @@ finish_node(struct device_node *np, unsigned long mem_start,
        mem_start = finish_node_interrupts(np, mem_start, measure_only);
 
        /* Look for #address-cells and #size-cells properties. */
-       ip = (int *) get_property(np, "#address-cells", 0);
+       ip = (int *) get_property(np, "#address-cells", NULL);
        if (ip != NULL)
                naddrc = *ip;
-       ip = (int *) get_property(np, "#size-cells", 0);
+       ip = (int *) get_property(np, "#size-cells", NULL);
        if (ip != NULL)
                nsizec = *ip;
 
@@ -2457,7 +514,7 @@ finish_node(struct device_node *np, unsigned long mem_start,
         * expect for the name -- Cort
         */
        if (!strcmp(np->name, "display"))
-               np->name = get_property(np, "compatible", 0);
+               np->name = get_property(np, "compatible", NULL);
 
        if (!strcmp(np->name, "device-tree") || np->parent == NULL)
                ifunc = interpret_root_props;
@@ -2486,27 +543,530 @@ finish_node(struct device_node *np, unsigned long mem_start,
        return mem_start;
 }
 
-/*
+/**
  * finish_device_tree is called once things are running normally
  * (i.e. with text and data mapped to the address they were linked at).
- * It traverses the device tree and fills in the name, type,
- * {n_}addrs and {n_}intrs fields of each node.
+ * It traverses the device tree and fills in some of the additional,
+ * fields in each node like {n_}addrs and {n_}intrs, the virt interrupt
+ * mapping is also initialized at this point.
  */
-void __init
-finish_device_tree(void)
+void __init finish_device_tree(void)
 {
-       unsigned long mem = klimit;
+       unsigned long mem, size;
 
+       DBG(" -> finish_device_tree\n");
+
+       if (ppc64_interrupt_controller == IC_INVALID) {
+               DBG("failed to configure interrupt controller type\n");
+               panic("failed to configure interrupt controller type\n");
+       }
+       
+       /* Initialize virtual IRQ map */
        virt_irq_init();
 
-       dev_tree_size = finish_node(allnodes, 0, NULL, 0, 0, 1);
-       mem = (long)abs_to_virt(lmb_alloc(dev_tree_size,
-                                         __alignof__(struct device_node)));
-       if (finish_node(allnodes, mem, NULL, 0, 0, 0) != mem + dev_tree_size)
+       /* Finish device-tree (pre-parsing some properties etc...) */
+       size = finish_node(allnodes, 0, NULL, 0, 0, 1);
+       mem = (unsigned long)abs_to_virt(lmb_alloc(size, 128));
+       if (finish_node(allnodes, mem, NULL, 0, 0, 0) != mem + size)
                BUG();
-       rtas.dev = of_find_node_by_name(NULL, "rtas");
+
+       DBG(" <- finish_device_tree\n");
+}
+
+#ifdef DEBUG
+#define printk udbg_printf
+#endif
+
+static inline char *find_flat_dt_string(u32 offset)
+{
+       return ((char *)initial_boot_params) + initial_boot_params->off_dt_strings
+               + offset;
+}
+
+/**
+ * This function is used to scan the flattened device-tree, it is
+ * used to extract the memory informations at boot before we can
+ * unflatten the tree
+ */
+static int __init scan_flat_dt(int (*it)(unsigned long node,
+                                        const char *full_path, void *data),
+                              void *data)
+{
+       unsigned long p = ((unsigned long)initial_boot_params) +
+               initial_boot_params->off_dt_struct;
+       int rc = 0;
+
+       do {
+               u32 tag = *((u32 *)p);
+               char *pathp;
+               
+               p += 4;
+               if (tag == OF_DT_END_NODE)
+                       continue;
+               if (tag == OF_DT_END)
+                       break;
+               if (tag == OF_DT_PROP) {
+                       u32 sz = *((u32 *)p);
+                       p += 8;
+                       p = _ALIGN(p, sz >= 8 ? 8 : 4);
+                       p += sz;
+                       p = _ALIGN(p, 4);
+                       continue;
+               }
+               if (tag != OF_DT_BEGIN_NODE) {
+                       printk(KERN_WARNING "Invalid tag %x scanning flattened"
+                              " device tree !\n", tag);
+                       return -EINVAL;
+               }
+               pathp = (char *)p;
+               p = _ALIGN(p + strlen(pathp) + 1, 4);
+               rc = it(p, pathp, data);
+               if (rc != 0)
+                       break;          
+       } while(1);
+
+       return rc;
+}
+
+/**
+ * This  function can be used within scan_flattened_dt callback to get
+ * access to properties
+ */
+static void* __init get_flat_dt_prop(unsigned long node, const char *name,
+                                    unsigned long *size)
+{
+       unsigned long p = node;
+
+       do {
+               u32 tag = *((u32 *)p);
+               u32 sz, noff;
+               const char *nstr;
+
+               p += 4;
+               if (tag != OF_DT_PROP)
+                       return NULL;
+
+               sz = *((u32 *)p);
+               noff = *((u32 *)(p + 4));
+               p += 8;
+               p = _ALIGN(p, sz >= 8 ? 8 : 4);
+
+               nstr = find_flat_dt_string(noff);
+               if (nstr == NULL) {
+                       printk(KERN_WARNING "Can't find property index name !\n");
+                       return NULL;
+               }
+               if (strcmp(name, nstr) == 0) {
+                       if (size)
+                               *size = sz;
+                       return (void *)p;
+               }
+               p += sz;
+               p = _ALIGN(p, 4);
+       } while(1);
+}
+
+static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
+                                              unsigned long align)
+{
+       void *res;
+
+       *mem = _ALIGN(*mem, align);
+       res = (void *)*mem;
+       *mem += size;
+
+       return res;
+}
+
+static unsigned long __init unflatten_dt_node(unsigned long mem,
+                                             unsigned long *p,
+                                             struct device_node *dad,
+                                             struct device_node ***allnextpp)
+{
+       struct device_node *np;
+       struct property *pp, **prev_pp = NULL;
+       char *pathp;
+       u32 tag;
+       unsigned int l;
+
+       tag = *((u32 *)(*p));
+       if (tag != OF_DT_BEGIN_NODE) {
+               printk("Weird tag at start of node: %x\n", tag);
+               return mem;
+       }
+       *p += 4;
+       pathp = (char *)*p;
+       l = strlen(pathp) + 1;
+       *p = _ALIGN(*p + l, 4);
+
+       np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + l,
+                               __alignof__(struct device_node));
+       if (allnextpp) {
+               memset(np, 0, sizeof(*np));
+               np->full_name = ((char*)np) + sizeof(struct device_node);
+               memcpy(np->full_name, pathp, l);
+               prev_pp = &np->properties;
+               **allnextpp = np;
+               *allnextpp = &np->allnext;
+               if (dad != NULL) {
+                       np->parent = dad;
+                       /* we temporarily use the `next' field as `last_child'. */
+                       if (dad->next == 0)
+                               dad->child = np;
+                       else
+                               dad->next->sibling = np;
+                       dad->next = np;
+               }
+               kref_init(&np->kref);
+       }
+       while(1) {
+               u32 sz, noff;
+               char *pname;
+
+               tag = *((u32 *)(*p));
+               if (tag != OF_DT_PROP)
+                       break;
+               *p += 4;
+               sz = *((u32 *)(*p));
+               noff = *((u32 *)((*p) + 4));
+               *p = _ALIGN((*p) + 8, sz >= 8 ? 8 : 4);
+
+               pname = find_flat_dt_string(noff);
+               if (pname == NULL) {
+                       printk("Can't find property name in list !\n");
+                       break;
+               }
+               l = strlen(pname) + 1;
+               pp = unflatten_dt_alloc(&mem, sizeof(struct property),
+                                       __alignof__(struct property));
+               if (allnextpp) {
+                       if (strcmp(pname, "linux,phandle") == 0) {
+                               np->node = *((u32 *)*p);
+                               if (np->linux_phandle == 0)
+                                       np->linux_phandle = np->node;
+                       }
+                       if (strcmp(pname, "ibm,phandle") == 0)
+                               np->linux_phandle = *((u32 *)*p);
+                       pp->name = pname;
+                       pp->length = sz;
+                       pp->value = (void *)*p;
+                       *prev_pp = pp;
+                       prev_pp = &pp->next;
+               }
+               *p = _ALIGN((*p) + sz, 4);
+       }
+       if (allnextpp) {
+               *prev_pp = NULL;
+               np->name = get_property(np, "name", NULL);
+               np->type = get_property(np, "device_type", NULL);
+
+               if (!np->name)
+                       np->name = "<NULL>";
+               if (!np->type)
+                       np->type = "<NULL>";
+       }
+       while (tag == OF_DT_BEGIN_NODE) {
+               mem = unflatten_dt_node(mem, p, np, allnextpp);
+               tag = *((u32 *)(*p));
+       }
+       if (tag != OF_DT_END_NODE) {
+               printk("Weird tag at start of node: %x\n", tag);
+               return mem;
+       }
+       *p += 4;
+       return mem;
+}
+
+
+/**
+ * unflattens the device-tree passed by the firmware, creating the
+ * tree of struct device_node. It also fills the "name" and "type"
+ * pointers of the nodes so the normal device-tree walking functions
+ * can be used (this used to be done by finish_device_tree)
+ */
+void __init unflatten_device_tree(void)
+{
+       unsigned long start, mem, size;
+       struct device_node **allnextp = &allnodes;
+       char *p;
+       int l = 0;
+
+       DBG(" -> unflatten_device_tree()\n");
+
+       /* First pass, scan for size */
+       start = ((unsigned long)initial_boot_params) +
+               initial_boot_params->off_dt_struct;
+       size = unflatten_dt_node(0, &start, NULL, NULL);
+
+       DBG("  size is %lx, allocating...\n", size);
+
+       /* Allocate memory for the expanded device tree */
+       mem = (unsigned long)abs_to_virt(lmb_alloc(size,
+                                                  __alignof__(struct device_node)));
+       DBG("  unflattening...\n", mem);
+
+       /* Second pass, do actual unflattening */
+       start = ((unsigned long)initial_boot_params) +
+               initial_boot_params->off_dt_struct;
+       unflatten_dt_node(mem, &start, NULL, &allnextp);
+       if (*((u32 *)start) != OF_DT_END)
+               printk(KERN_WARNING "Weird tag at end of tree: %x\n", *((u32 *)start));
+       *allnextp = NULL;
+
+       /* Get pointer to OF "/chosen" node for use everywhere */
+       of_chosen = of_find_node_by_path("/chosen");
+
+       /* Retreive command line */
+       if (of_chosen != NULL) {
+               p = (char *)get_property(of_chosen, "bootargs", &l);
+               if (p != NULL && l > 0)
+                       strlcpy(cmd_line, p, min(l, COMMAND_LINE_SIZE));
+       }
+#ifdef CONFIG_CMDLINE
+       if (l == 0 || (l == 1 && (*p) == 0))
+               strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+#endif /* CONFIG_CMDLINE */
+
+       DBG("Command line is: %s\n", cmd_line);
+
+       DBG(" <- unflatten_device_tree()\n");
+}
+
+
+static int __init early_init_dt_scan_cpus(unsigned long node,
+                                         const char *full_path, void *data)
+{
+       char *type = get_flat_dt_prop(node, "device_type", NULL);
+
+       /* We are scanning "cpu" nodes only */
+       if (type == NULL || strcmp(type, "cpu") != 0)
+               return 0;
+
+       /* On LPAR, look for the first ibm,pft-size property for the  hash table size
+        */
+       if (systemcfg->platform == PLATFORM_PSERIES_LPAR && ppc64_pft_size == 0) {
+               u32 *pft_size;
+               pft_size = (u32 *)get_flat_dt_prop(node, "ibm,pft-size", NULL);
+               if (pft_size != NULL) {
+                       /* pft_size[0] is the NUMA CEC cookie */
+                       ppc64_pft_size = pft_size[1];
+               }
+       }
+
+       if (initial_boot_params && initial_boot_params->version >= 2) {
+               /* version 2 of the kexec param format adds the phys cpuid
+                * of booted proc.
+                */
+               boot_cpuid_phys = initial_boot_params->boot_cpuid_phys;
+               boot_cpuid = 0;
+       } else {
+               /* Check if it's the boot-cpu, set it's hw index in paca now */
+               if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) {
+                       u32 *prop = get_flat_dt_prop(node, "reg", NULL);
+                       set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop);
+                       boot_cpuid_phys = get_hard_smp_processor_id(0);
+               }
+       }
+
+       return 0;
+}
+
+static int __init early_init_dt_scan_chosen(unsigned long node,
+                                           const char *full_path, void *data)
+{
+       u32 *prop;
+
+       if (strcmp(full_path, "/chosen") != 0)
+               return 0;
+
+       /* get platform type */
+       prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL);
+       if (prop == NULL)
+               return 0;
+       systemcfg->platform = *prop;
+
+       /* check if iommu is forced on or off */
+       if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
+               iommu_is_off = 1;
+       if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)
+               iommu_force_on = 1;
+
+#ifdef CONFIG_PPC_PSERIES
+       /* To help early debugging via the front panel, we retreive a minimal
+        * set of RTAS infos now if available
+        */
+       {
+               u64 *basep, *entryp;
+
+               basep = (u64*)get_flat_dt_prop(node, "linux,rtas-base", NULL);
+               entryp = (u64*)get_flat_dt_prop(node, "linux,rtas-entry", NULL);
+               prop = (u32*)get_flat_dt_prop(node, "linux,rtas-size", NULL);
+               if (basep && entryp && prop) {
+                       rtas.base = *basep;
+                       rtas.entry = *entryp;
+                       rtas.size = *prop;
+               }
+       }
+#endif /* CONFIG_PPC_PSERIES */
+
+       /* break now */
+       return 1;
+}
+
+static int __init early_init_dt_scan_root(unsigned long node,
+                                         const char *full_path, void *data)
+{
+       u32 *prop;
+
+       if (strcmp(full_path, "/") != 0)
+               return 0;
+
+       prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL);
+       dt_root_size_cells = (prop == NULL) ? 1 : *prop;
+               
+       prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL);
+       dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
+       
+       /* break now */
+       return 1;
+}
+
+static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp)
+{
+       cell_t *p = *cellp;
+       unsigned long r = 0;
+
+       /* Ignore more than 2 cells */
+       while (s > 2) {
+               p++;
+               s--;
+       }
+       while (s) {
+               r <<= 32;
+               r |= *(p++);
+               s--;
+       }
+
+       *cellp = p;
+       return r;
+}
+
+
+static int __init early_init_dt_scan_memory(unsigned long node,
+                                           const char *full_path, void *data)
+{
+       char *type = get_flat_dt_prop(node, "device_type", NULL);
+       cell_t *reg, *endp;
+       unsigned long l;
+
+       /* We are scanning "memory" nodes only */
+       if (type == NULL || strcmp(type, "memory") != 0)
+               return 0;
+
+       reg = (cell_t *)get_flat_dt_prop(node, "reg", &l);
+       if (reg == NULL)
+               return 0;
+
+       endp = reg + (l / sizeof(cell_t));
+
+       DBG("memory scan node %s ...\n", full_path);
+       while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
+               unsigned long base, size;
+
+               base = dt_mem_next_cell(dt_root_addr_cells, &reg);
+               size = dt_mem_next_cell(dt_root_size_cells, &reg);
+
+               if (size == 0)
+                       continue;
+               DBG(" - %lx ,  %lx\n", base, size);
+               if (iommu_is_off) {
+                       if (base >= 0x80000000ul)
+                               continue;
+                       if ((base + size) > 0x80000000ul)
+                               size = 0x80000000ul - base;
+               }
+               lmb_add(base, size);
+       }
+       return 0;
+}
+
+static void __init early_reserve_mem(void)
+{
+       u64 base, size;
+       u64 *reserve_map = (u64 *)(((unsigned long)initial_boot_params) +
+                                  initial_boot_params->off_mem_rsvmap);
+       while (1) {
+               base = *(reserve_map++);
+               size = *(reserve_map++);
+               if (size == 0)
+                       break;
+               DBG("reserving: %lx -> %lx\n", base, size);
+               lmb_reserve(base, size);
+       }
+
+#if 0
+       DBG("memory reserved, lmbs :\n");
+       lmb_dump_all();
+#endif
+}
+
+void __init early_init_devtree(void *params)
+{
+       DBG(" -> early_init_devtree()\n");
+
+       /* Setup flat device-tree pointer */
+       initial_boot_params = params;
+
+       /* By default, hash size is not set */
+       ppc64_pft_size = 0;
+
+       /* Retreive various informations from the /chosen node of the
+        * device-tree, including the platform type, initrd location and
+        * size, TCE reserve, and more ...
+        */
+       scan_flat_dt(early_init_dt_scan_chosen, NULL);
+
+       /* Scan memory nodes and rebuild LMBs */
+       lmb_init();
+       scan_flat_dt(early_init_dt_scan_root, NULL);
+       scan_flat_dt(early_init_dt_scan_memory, NULL);
+       lmb_analyze();
+       systemcfg->physicalMemorySize = lmb_phys_mem_size();
+       lmb_reserve(0, __pa(klimit));
+
+       DBG("Phys. mem: %lx\n", systemcfg->physicalMemorySize);
+
+       /* Reserve LMB regions used by kernel, initrd, dt, etc... */
+       early_reserve_mem();
+
+       DBG("Scanning CPUs ...\n");
+
+       /* Retreive hash table size from flattened tree */
+       scan_flat_dt(early_init_dt_scan_cpus, NULL);
+
+       /* If hash size wasn't obtained above, we calculate it now based on
+        * the total RAM size
+        */
+       if (ppc64_pft_size == 0) {
+               unsigned long rnd_mem_size, pteg_count;
+
+               /* round mem_size up to next power of 2 */
+               rnd_mem_size = 1UL << __ilog2(systemcfg->physicalMemorySize);
+               if (rnd_mem_size < systemcfg->physicalMemorySize)
+                       rnd_mem_size <<= 1;
+
+               /* # pages / 2 */
+               pteg_count = max(rnd_mem_size >> (12 + 1), 1UL << 11);
+
+               ppc64_pft_size = __ilog2(pteg_count << 7);
+       }
+
+       DBG("Hash pftSize: %x\n", (int)ppc64_pft_size);
+       DBG(" <- early_init_devtree()\n");
 }
 
+#undef printk
+
 int
 prom_n_addr_cells(struct device_node* np)
 {
@@ -2514,7 +1074,7 @@ prom_n_addr_cells(struct device_node* np)
        do {
                if (np->parent)
                        np = np->parent;
-               ip = (int *) get_property(np, "#address-cells", 0);
+               ip = (int *) get_property(np, "#address-cells", NULL);
                if (ip != NULL)
                        return *ip;
        } while (np->parent);
@@ -2529,7 +1089,7 @@ prom_n_size_cells(struct device_node* np)
        do {
                if (np->parent)
                        np = np->parent;
-               ip = (int *) get_property(np, "#size-cells", 0);
+               ip = (int *) get_property(np, "#size-cells", NULL);
                if (ip != NULL)
                        return *ip;
        } while (np->parent);
@@ -2537,12 +1097,11 @@ prom_n_size_cells(struct device_node* np)
        return 1;
 }
 
-/*
+/**
  * Work out the sense (active-low level / active-high edge)
  * of each interrupt from the device tree.
  */
-void __init
-prom_get_irq_senses(unsigned char *senses, int off, int max)
+void __init prom_get_irq_senses(unsigned char *senses, int off, int max)
 {
        struct device_node *np;
        int i, j;
@@ -2554,12 +1113,14 @@ prom_get_irq_senses(unsigned char *senses, int off, int max)
                for (j = 0; j < np->n_intrs; j++) {
                        i = np->intrs[j].line;
                        if (i >= off && i < max)
-                               senses[i-off] = np->intrs[j].sense;
+                               senses[i-off] = np->intrs[j].sense ?
+                                       IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE :
+                                       IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE;
                }
        }
 }
 
-/*
+/**
  * Construct and return a list of the device_nodes with a given name.
  */
 struct device_node *
@@ -2574,11 +1135,11 @@ find_devices(const char *name)
                        prevp = &np->next;
                }
        }
-       *prevp = 0;
+       *prevp = NULL;
        return head;
 }
 
-/*
+/**
  * Construct and return a list of the device_nodes with a given type.
  */
 struct device_node *
@@ -2593,11 +1154,11 @@ find_type_devices(const char *type)
                        prevp = &np->next;
                }
        }
-       *prevp = 0;
+       *prevp = NULL;
        return head;
 }
 
-/*
+/**
  * Returns all nodes linked together
  */
 struct device_node *
@@ -2610,11 +1171,11 @@ find_all_nodes(void)
                *prevp = np;
                prevp = &np->next;
        }
-       *prevp = 0;
+       *prevp = NULL;
        return head;
 }
 
-/* Checks if the given "compat" string matches one of the strings in
+/** Checks if the given "compat" string matches one of the strings in
  * the device's "compatible" property
  */
 int
@@ -2638,7 +1199,7 @@ device_is_compatible(struct device_node *device, const char *compat)
 }
 
 
-/*
+/**
  * Indicates whether the root node has a given value in its
  * compatible property.
  */
@@ -2647,7 +1208,7 @@ machine_is_compatible(const char *compat)
 {
        struct device_node *root;
        int rc = 0;
-  
+
        root = of_find_node_by_path("/");
        if (root) {
                rc = device_is_compatible(root, compat);
@@ -2656,7 +1217,7 @@ machine_is_compatible(const char *compat)
        return rc;
 }
 
-/*
+/**
  * Construct and return a list of the device_nodes with a given type
  * and compatible property.
  */
@@ -2675,11 +1236,11 @@ find_compatible_devices(const char *type, const char *compat)
                        prevp = &np->next;
                }
        }
-       *prevp = 0;
+       *prevp = NULL;
        return head;
 }
 
-/*
+/**
  * Find the device_node with a given full_name.
  */
 struct device_node *
@@ -2818,6 +1379,28 @@ struct device_node *of_find_node_by_path(const char *path)
 }
 EXPORT_SYMBOL(of_find_node_by_path);
 
+/**
+ *     of_find_node_by_phandle - Find a node given a phandle
+ *     @handle:        phandle of the node to find
+ *
+ *     Returns a node pointer with refcount incremented, use
+ *     of_node_put() on it when done.
+ */
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+       struct device_node *np;
+
+       read_lock(&devtree_lock);
+       for (np = allnodes; np != 0; np = np->allnext)
+               if (np->linux_phandle == handle)
+                       break;
+       if (np)
+               of_node_get(np);
+       read_unlock(&devtree_lock);
+       return np;
+}
+EXPORT_SYMBOL(of_find_node_by_phandle);
+
 /**
  *     of_find_all_nodes - Get next node in global list
  *     @prev:  Previous node or NULL to start iteration
@@ -2893,24 +1476,31 @@ EXPORT_SYMBOL(of_get_next_child);
  *     @node:  Node to inc refcount, NULL is supported to
  *             simplify writing of callers
  *
- *     Returns the node itself or NULL if gone.
+ *     Returns node.
  */
 struct device_node *of_node_get(struct device_node *node)
 {
-       if (node && !OF_IS_STALE(node)) {
-               atomic_inc(&node->_users);
-               return node;
-       }
-       return NULL;
+       if (node)
+               kref_get(&node->kref);
+       return node;
 }
 EXPORT_SYMBOL(of_node_get);
 
+static inline struct device_node * kref_to_device_node(struct kref *kref)
+{
+       return container_of(kref, struct device_node, kref);
+}
+
 /**
- *     of_node_cleanup - release a dynamically allocated node
- *     @arg:  Node to be released
+ *     of_node_release - release a dynamically allocated node
+ *     @kref:  kref element of the node to be released
+ *
+ *     In of_node_put() this function is passed to kref_put()
+ *     as the destructor.
  */
-static void of_node_cleanup(struct device_node *node)
+static void of_node_release(struct kref *kref)
 {
+       struct device_node *node = kref_to_device_node(kref);
        struct property *prop = node->properties;
 
        if (!OF_IS_DYNAMIC(node))
@@ -2936,19 +1526,8 @@ static void of_node_cleanup(struct device_node *node)
  */
 void of_node_put(struct device_node *node)
 {
-       if (!node)
-               return;
-
-       WARN_ON(0 == atomic_read(&node->_users));
-
-       if (OF_IS_STALE(node)) {
-               if (atomic_dec_and_test(&node->_users)) {
-                       of_node_cleanup(node);
-                       return;
-               }
-       }
-       else
-               atomic_dec(&node->_users);
+       if (node)
+               kref_put(&node->kref, of_node_release);
 }
 EXPORT_SYMBOL(of_node_put);
 
@@ -3077,6 +1656,7 @@ static int of_finish_dynamic_node_interrupts(struct device_node *node)
        return 0;
 }
 
+
 /*
  * Fix up the uninitialized fields in a new device node:
  * name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields
@@ -3094,9 +1674,9 @@ static int of_finish_dynamic_node(struct device_node *node)
        u32 *regs;
        int err = 0;
        phandle *ibm_phandle;
-       node->name = get_property(node, "name", 0);
-       node->type = get_property(node, "device_type", 0);
+
+       node->name = get_property(node, "name", NULL);
+       node->type = get_property(node, "device_type", NULL);
 
        if (!parent) {
                err = -ENODEV;
@@ -3142,33 +1722,23 @@ static int of_finish_dynamic_node(struct device_node *node)
        }
 
        /* now do the work of finish_node_interrupts */
-       if (get_property(node, "interrupts", 0)) {
+       if (get_property(node, "interrupts", NULL)) {
                err = of_finish_dynamic_node_interrupts(node);
                if (err) goto out;
        }
 
-       /* now do the rough equivalent of update_dn_pci_info, this
-        * probably is not correct for phb's, but should work for
-       * IOAs and slots.
-        */
-
-       node->phb = parent->phb;
-
-       regs = (u32 *)get_property(node, "reg", 0);
-       if (regs) {
-               node->busno = (regs[0] >> 16) & 0xff;
-               node->devfn = (regs[0] >> 8) & 0xff;
-       }
+       /* now do the rough equivalent of update_dn_pci_info, this
+        * probably is not correct for phb's, but should work for
+        * IOAs and slots.
+        */
 
-       /* fixing up iommu_table */
+       node->phb = parent->phb;
 
-       if(strcmp(node->name, "pci") == 0 &&
-                get_property(node, "ibm,dma-window", NULL)) {
-                node->bussubno = node->busno;
-                iommu_devnode_init(node);
-        }
-       else
-               node->iommu_table = parent->iommu_table;
+       regs = (u32 *)get_property(node, "reg", NULL);
+       if (regs) {
+               node->busno = (regs[0] >> 16) & 0xff;
+               node->devfn = (regs[0] >> 8) & 0xff;
+       }
 
 out:
        of_node_put(parent);
@@ -3200,6 +1770,7 @@ int of_add_node(const char *path, struct property *proplist)
 
        np->properties = proplist;
        OF_MARK_DYNAMIC(np);
+       kref_init(&np->kref);
        of_node_get(np);
        np->parent = derive_parent(path);
        if (!np->parent) {
@@ -3227,8 +1798,18 @@ int of_add_node(const char *path, struct property *proplist)
 }
 
 /*
- * Remove an OF device node from the system.
- * Caller should have already "gotten" np.
+ * Prepare an OF node for removal from system
+ */
+static void of_cleanup_node(struct device_node *np)
+{
+       if (np->iommu_table && get_property(np, "ibm,dma-window", NULL))
+               iommu_free_table(np);
+}
+
+/*
+ * "Unplug" a node from the device tree.  The caller must hold
+ * a reference to the node.  The memory associated with the node
+ * is not freed until its refcount goes to zero.
  */
 int of_remove_node(struct device_node *np)
 {
@@ -3243,8 +1824,9 @@ int of_remove_node(struct device_node *np)
                return -EBUSY;
        }
 
+       of_cleanup_node(np);
+
        write_lock(&devtree_lock);
-       OF_MARK_STALE(np);
        remove_node_proc_entries(np);
        if (allnodes == np)
                allnodes = np->allnext;
@@ -3269,6 +1851,7 @@ int of_remove_node(struct device_node *np)
        }
        write_unlock(&devtree_lock);
        of_node_put(parent);
+       of_node_put(np); /* Must decrement the refcount */
        return 0;
 }
 
@@ -3287,7 +1870,7 @@ get_property(struct device_node *np, const char *name, int *lenp)
                                *lenp = pp->length;
                        return pp->value;
                }
-       return 0;
+       return NULL;
 }
 
 /*
@@ -3355,3 +1938,13 @@ print_properties(struct device_node *np)
        }
 }
 #endif
+
+
+
+
+
+
+
+
+
+