patch-2.4.19 linux-2.4.19/arch/ppc/kernel/prom.c
Next file: linux-2.4.19/arch/ppc/kernel/prom_init.c
Previous file: linux-2.4.19/arch/ppc/kernel/prep_setup.c
Back to the patch index
Back to the overall index
- Lines: 1098
- Date:
Fri Aug 2 17:39:43 2002
- Orig file:
linux-2.4.18/arch/ppc/kernel/prom.c
- Orig date:
Mon Feb 25 11:37:55 2002
diff -urN linux-2.4.18/arch/ppc/kernel/prom.c linux-2.4.19/arch/ppc/kernel/prom.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.prom.c 1.48 12/19/01 10:50:58 paulus
+ * BK Id: SCCS/s.prom.c 1.52 04/09/02 21:01:58 paulus
*/
/*
* Procedures for interfacing to the Open Firmware PROM on
@@ -11,7 +11,6 @@
* Paul Mackerras August 1996.
* Copyright (C) 1996 Paul Mackerras.
*/
-#include <stdarg.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/string.h>
@@ -19,7 +18,6 @@
#include <linux/version.h>
#include <linux/threads.h>
#include <linux/spinlock.h>
-#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/slab.h>
@@ -28,37 +26,9 @@
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/bootx.h>
#include <asm/system.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
-#include <asm/bitops.h>
-#include <asm/bootinfo.h>
#include <asm/btext.h>
#include <asm/pci-bridge.h>
-#include "open_pic.h"
-
-#ifdef CONFIG_FB
-#include <asm/linux_logo.h>
-#endif
-
-/*
- * Properties whose value is longer than this get excluded from our
- * copy of the device tree. This way we don't waste space storing
- * things like "driver,AAPL,MacOS,PowerPC" properties. But 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 4096
-
-struct prom_args {
- const char *service;
- int nargs;
- int nret;
- void *args[10];
-};
struct pci_address {
unsigned a_hi;
@@ -72,26 +42,12 @@
unsigned size_lo;
};
-struct pci_range {
- struct pci_address addr;
- unsigned phys;
- unsigned size_hi;
- unsigned size_lo;
-};
-
struct isa_reg_property {
unsigned space;
unsigned address;
unsigned size;
};
-struct pci_intr_map {
- struct pci_address addr;
- unsigned dunno;
- phandle int_ctrler;
- unsigned intr;
-};
-
typedef unsigned long interpret_func(struct device_node *, unsigned long,
int, int);
static interpret_func interpret_pci_props;
@@ -100,27 +56,7 @@
static interpret_func interpret_macio_props;
static interpret_func interpret_root_props;
-#ifndef FB_MAX /* avoid pulling in all of the fb stuff */
-#define FB_MAX 8
-#endif
-char *prom_display_paths[FB_MAX] __initdata = { 0, };
-phandle prom_display_nodes[FB_MAX] __initdata;
-unsigned int prom_num_displays __initdata = 0;
-char *of_stdout_device __initdata = 0;
-ihandle prom_disp_node __initdata = 0;
-
-prom_entry prom __initdata = 0;
-ihandle prom_chosen __initdata = 0;
-ihandle prom_stdout __initdata = 0;
-
extern char *klimit;
-char *bootpath;
-char *bootdevice;
-
-unsigned int rtas_data; /* physical pointer */
-unsigned int rtas_entry; /* physical pointer */
-unsigned int rtas_size;
-unsigned int old_rtas;
/* Set for a newworld or CHRP machine */
int use_of_interrupt_tree;
@@ -129,554 +65,30 @@
int pmac_newworld;
-static struct device_node *allnodes;
+extern unsigned int rtas_entry; /* physical pointer */
+
+extern struct device_node *allnodes;
-static void *call_prom(const char *service, int nargs, int nret, ...);
-static void prom_exit(void);
-static unsigned long copy_device_tree(unsigned long, unsigned long);
-static unsigned long inspect_node(phandle, struct device_node *, unsigned long,
- unsigned long, struct device_node ***);
static unsigned long finish_node(struct device_node *, unsigned long,
interpret_func *, int, int);
static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
-static unsigned long check_display(unsigned long);
-static int prom_next_node(phandle *);
-static void *early_get_property(unsigned long, unsigned long, char *);
static struct device_node *find_phandle(phandle);
-#ifdef CONFIG_BOOTX_TEXT
-static void setup_disp_fake_bi(ihandle dp);
-#endif
-
extern void enter_rtas(void *);
void phys_call_rtas(int, int, int, ...);
extern char cmd_line[512]; /* XXX */
-boot_infos_t *boot_infos;
+extern boot_infos_t *boot_infos;
unsigned long dev_tree_size;
-#define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
-
-/* Is boot-info compatible ? */
-#define BOOT_INFO_IS_COMPATIBLE(bi) ((bi)->compatible_version <= BOOT_INFO_VERSION)
-#define BOOT_INFO_IS_V2_COMPATIBLE(bi) ((bi)->version >= 2)
-#define BOOT_INFO_IS_V4_COMPATIBLE(bi) ((bi)->version >= 4)
-
-/*
- * Note that prom_init() and anything called from prom_init() must
- * use the RELOC/PTRRELOC macros to access any static data in
- * memory, since the kernel may be running at an address that is
- * different from the address that it was linked at.
- * (Note that strings count as static variables.)
- */
-
-static void __init
-prom_exit()
-{
- struct prom_args args;
- unsigned long offset = reloc_offset();
-
- args.service = "exit";
- args.nargs = 0;
- args.nret = 0;
- RELOC(prom)(&args);
- for (;;) /* should never get here */
- ;
-}
-
-void __init
-prom_enter(void)
-{
- struct prom_args args;
- unsigned long offset = reloc_offset();
-
- args.service = RELOC("enter");
- args.nargs = 0;
- args.nret = 0;
- RELOC(prom)(&args);
-}
-
-static void * __init
-call_prom(const char *service, int nargs, int nret, ...)
-{
- va_list list;
- int i;
- unsigned long offset = reloc_offset();
- struct prom_args prom_args;
-
- prom_args.service = service;
- prom_args.nargs = nargs;
- prom_args.nret = nret;
- va_start(list, nret);
- for (i = 0; i < nargs; ++i)
- prom_args.args[i] = va_arg(list, void *);
- va_end(list);
- for (i = 0; i < nret; ++i)
- prom_args.args[i + nargs] = 0;
- RELOC(prom)(&prom_args);
- return prom_args.args[nargs];
-}
-
-void __init
-prom_print(const char *msg)
-{
- const char *p, *q;
- unsigned long offset = reloc_offset();
-
- if (RELOC(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, RELOC(prom_stdout),
- p, q - p);
- if (*q != 0) {
- ++q;
- call_prom(RELOC("write"), 3, 1, RELOC(prom_stdout),
- RELOC("\r\n"), 2);
- }
- }
-}
-
-static void __init
-prom_print_hex(unsigned int v)
-{
- char buf[16];
- int i, c;
-
- for (i = 0; i < 8; ++i) {
- c = (v >> ((7-i)*4)) & 0xf;
- c += (c >= 10)? ('a' - 10): '0';
- buf[i] = c;
- }
- buf[i] = ' ';
- buf[i+1] = 0;
- prom_print(buf);
-}
-
-unsigned long smp_chrp_cpu_nr __initdata = 0;
-
-#ifdef CONFIG_SMP
-/*
- * 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 high memory, puts some holding pattern
- * code there and sends the other processors off to there until
- * smp_boot_cpus tells them to do something. We do that by using
- * physical address 0x0. 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.
- *
- * -- Cort
- */
-static void __init
-prom_hold_cpus(unsigned long mem)
-{
- extern void __secondary_hold(void);
- unsigned long i;
- int cpu;
- phandle node;
- unsigned long offset = reloc_offset();
- char type[16], *path;
- unsigned int reg;
-
- /*
- * XXX: hack to make sure we're chrp, assume that if we're
- * chrp we have a device_type property -- Cort
- */
- node = call_prom(RELOC("finddevice"), 1, 1, RELOC("/"));
- if ( (int)call_prom(RELOC("getprop"), 4, 1, node,
- RELOC("device_type"),type, sizeof(type)) <= 0)
- return;
-
- /* copy the holding pattern code to someplace safe (0) */
- /* the holding pattern is now within the first 0x100
- bytes of the kernel image -- paulus */
- memcpy((void *)0, (void *)(KERNELBASE + offset), 0x100);
- flush_icache_range(0, 0x100);
-
- /* look for cpus */
- *(unsigned long *)(0x0) = 0;
- asm volatile("dcbf 0,%0": : "r" (0) : "memory");
- 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;
- path = (char *) mem;
- memset(path, 0, 256);
- if ((int) call_prom(RELOC("package-to-path"), 3, 1,
- node, path, 255) < 0)
- continue;
- reg = -1;
- call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
- ®, sizeof(reg));
- cpu = RELOC(smp_chrp_cpu_nr)++;
- RELOC(smp_hw_index)[cpu] = reg;
- /* XXX: hack - don't start cpu 0, this cpu -- Cort */
- if (cpu == 0)
- continue;
- prom_print(RELOC("starting cpu "));
- prom_print(path);
- *(ulong *)(0x4) = 0;
- call_prom(RELOC("start-cpu"), 3, 0, node,
- __pa(__secondary_hold), cpu);
- prom_print(RELOC("..."));
- for ( i = 0 ; (i < 10000) && (*(ulong *)(0x4) == 0); i++ )
- ;
- if (*(ulong *)(0x4) == cpu)
- prom_print(RELOC("ok\n"));
- else {
- prom_print(RELOC("failed: "));
- prom_print_hex(*(ulong *)0x4);
- prom_print(RELOC("\n"));
- }
- }
-}
-#endif /* CONFIG_SMP */
-
-void __init
-bootx_init(unsigned long r4, unsigned long phys)
-{
- boot_infos_t *bi = (boot_infos_t *) r4;
- unsigned long space;
- unsigned long ptr, x;
- char *model;
- unsigned long offset = reloc_offset();
-
- RELOC(boot_infos) = PTRUNRELOC(bi);
- if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
- bi->logicalDisplayBase = 0;
-
-#ifdef CONFIG_BOOTX_TEXT
- btext_init(bi);
-
- /*
- * Test if boot-info is compatible. Done only in config
- * CONFIG_BOOTX_TEXT since there is nothing much we can do
- * with an incompatible version, except display a message
- * and eventually hang the processor...
- *
- * I'll try to keep enough of boot-info compatible in the
- * future to always allow display of this message;
- */
- if (!BOOT_INFO_IS_COMPATIBLE(bi)) {
- btext_drawstring(RELOC(" !!! WARNING - Incompatible version of BootX !!!\n\n\n"));
- btext_flushscreen();
- }
-#endif /* CONFIG_BOOTX_TEXT */
-
- /* New BootX enters kernel with MMU off, i/os are not allowed
- here. This hack will have been done by the boostrap anyway.
- */
- if (bi->version < 4) {
- /*
- * XXX If this is an iMac, turn off the USB controller.
- */
- model = (char *) early_get_property
- (r4 + bi->deviceTreeOffset, 4, RELOC("model"));
- if (model
- && (strcmp(model, RELOC("iMac,1")) == 0
- || strcmp(model, RELOC("PowerMac1,1")) == 0)) {
- out_le32((unsigned *)0x80880008, 1); /* XXX */
- }
- }
-
- /* Move klimit to enclose device tree, args, ramdisk, etc... */
- if (bi->version < 5) {
- space = bi->deviceTreeOffset + bi->deviceTreeSize;
- if (bi->ramDisk)
- space = bi->ramDisk + bi->ramDiskSize;
- } else
- space = bi->totalParamsSize;
- RELOC(klimit) = PTRUNRELOC((char *) bi + space);
-
- /* New BootX will have flushed all TLBs and enters kernel with
- MMU switched OFF, so this should not be useful anymore.
- */
- if (bi->version < 4) {
- /*
- * Touch each page to make sure the PTEs for them
- * are in the hash table - the aim is to try to avoid
- * getting DSI exceptions while copying the kernel image.
- */
- for (ptr = (KERNELBASE + offset) & PAGE_MASK;
- ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)
- x = *(volatile unsigned long *)ptr;
- }
-
-#ifdef CONFIG_BOOTX_TEXT
- /*
- * Note that after we call prepare_disp_BAT, we can't do
- * prom_draw*, flushscreen or clearscreen until we turn the MMU
- * on, since prepare_disp_BAT sets disp_bi->logicalDisplayBase
- * to a virtual address.
- */
- btext_prepare_BAT();
-#endif
-}
-
-#ifdef CONFIG_PPC64BRIDGE
-/*
- * Set up a hash table with a set of entries in it to map the
- * first 64MB of RAM. This is used on 64-bit machines since
- * some of them don't have BATs.
- * We assume the PTE will fit in the primary PTEG.
- */
-
-static inline void make_pte(unsigned long htab, unsigned int hsize,
- unsigned int va, unsigned int pa, int mode)
-{
- unsigned int *pteg;
- unsigned int hash, i, vsid;
-
- vsid = ((va >> 28) * 0x111) << 12;
- hash = ((va ^ vsid) >> 5) & 0x7fff80;
- pteg = (unsigned int *)(htab + (hash & (hsize - 1)));
- for (i = 0; i < 8; ++i, pteg += 4) {
- if ((pteg[1] & 1) == 0) {
- pteg[1] = vsid | ((va >> 16) & 0xf80) | 1;
- pteg[3] = pa | mode;
- break;
- }
- }
-}
-
-extern unsigned long _SDR1;
-extern PTE *Hash;
-extern unsigned long Hash_size;
-
-static void __init
-prom_alloc_htab(void)
-{
- unsigned int hsize;
- unsigned long htab;
- unsigned int addr;
- unsigned long offset = reloc_offset();
-
- /*
- * Because of OF bugs we can't use the "claim" client
- * interface to allocate memory for the hash table.
- * This code is only used on 64-bit PPCs, and the only
- * 64-bit PPCs at the moment are RS/6000s, and their
- * OF is based at 0xc00000 (the 12M point), so we just
- * arbitrarily use the 0x800000 - 0xc00000 region for the
- * hash table.
- * -- paulus.
- */
-#ifdef CONFIG_POWER4
- hsize = 4 << 20; /* POWER4 has no BATs */
-#else
- hsize = 2 << 20;
-#endif /* CONFIG_POWER4 */
- htab = (8 << 20);
- RELOC(Hash) = (void *)(htab + KERNELBASE);
- RELOC(Hash_size) = hsize;
- RELOC(_SDR1) = htab + __ilog2(hsize) - 18;
-
- /*
- * Put in PTEs for the first 64MB of RAM
- */
- cacheable_memzero((void *)htab, hsize);
- for (addr = 0; addr < 0x4000000; addr += 0x1000)
- make_pte(htab, hsize, addr + KERNELBASE, addr,
- _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX);
-}
-#endif /* CONFIG_PPC64BRIDGE */
-
-static void __init
-prom_instantiate_rtas(void)
-{
- ihandle prom_rtas;
- unsigned int i;
- struct prom_args prom_args;
- unsigned long offset = reloc_offset();
-
- prom_rtas = call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas"));
- if (prom_rtas == (void *) -1)
- return;
-
- RELOC(rtas_size) = 0;
- call_prom(RELOC("getprop"), 4, 1, prom_rtas,
- RELOC("rtas-size"), &RELOC(rtas_size), sizeof(rtas_size));
- prom_print(RELOC("instantiating rtas"));
- if (RELOC(rtas_size) == 0) {
- RELOC(rtas_data) = 0;
- } else {
- /*
- * Ask OF for some space for RTAS.
- * Actually OF has bugs so we just arbitrarily
- * use memory at the 6MB point.
- */
- RELOC(rtas_data) = 6 << 20;
- prom_print(RELOC(" at "));
- prom_print_hex(RELOC(rtas_data));
- }
-
- prom_rtas = call_prom(RELOC("open"), 1, 1, RELOC("/rtas"));
- prom_print(RELOC("..."));
- prom_args.service = RELOC("call-method");
- prom_args.nargs = 3;
- prom_args.nret = 2;
- prom_args.args[0] = RELOC("instantiate-rtas");
- prom_args.args[1] = prom_rtas;
- prom_args.args[2] = (void *) RELOC(rtas_data);
- RELOC(prom)(&prom_args);
- i = 0;
- if (prom_args.args[3] == 0)
- i = (unsigned int)prom_args.args[4];
- RELOC(rtas_entry) = i;
- if ((RELOC(rtas_entry) == -1) || (RELOC(rtas_entry) == 0))
- prom_print(RELOC(" failed\n"));
- else
- prom_print(RELOC(" done\n"));
-}
-
-/*
- * 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(int r3, int r4, prom_entry pp)
-{
- unsigned long mem;
- ihandle prom_mmu;
- unsigned long offset = reloc_offset();
- int l;
- char *p, *d;
- unsigned long phys;
-
- /* Default */
- phys = offset + KERNELBASE;
-
- /* First get a handle for the stdout device */
- RELOC(prom) = pp;
- RELOC(prom_chosen) = call_prom(RELOC("finddevice"), 1, 1,
- RELOC("/chosen"));
- if (RELOC(prom_chosen) == (void *)-1)
- prom_exit();
- if ((int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),
- RELOC("stdout"), &RELOC(prom_stdout),
- sizeof(prom_stdout)) <= 0)
- prom_exit();
-
- /* Get the full OF pathname of the stdout device */
- mem = (unsigned long) RELOC(klimit) + offset;
- p = (char *) mem;
- memset(p, 0, 256);
- call_prom(RELOC("instance-to-path"), 3, 1, RELOC(prom_stdout), p, 255);
- RELOC(of_stdout_device) = PTRUNRELOC(p);
- mem += strlen(p) + 1;
-
- /* Get the boot device and translate it to a full OF pathname. */
- p = (char *) mem;
- l = (int) call_prom(RELOC("getprop"), 4, 1, RELOC(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 = ALIGN(mem + strlen(d) + 1);
- }
-
- prom_instantiate_rtas();
-
-#ifdef CONFIG_PPC64BRIDGE
- /*
- * Find out how much memory we have and allocate a
- * suitably-sized hash table.
- */
- prom_alloc_htab();
-#endif
-
- mem = check_display(mem);
-
- prom_print(RELOC("copying OF device tree..."));
- mem = copy_device_tree(mem, mem + (1<<20));
- prom_print(RELOC("done\n"));
-
-#ifdef CONFIG_SMP
- prom_hold_cpus(mem);
-#endif
-
- RELOC(klimit) = (char *) (mem - offset);
-
- /* If we are already running at 0xc0000000, we assume we were loaded by
- * an OF bootloader which did set a BAT for us. This breaks OF translate
- * so we force phys to be 0
- */
- if (offset == 0)
- phys = 0;
- else {
- if ((int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),
- RELOC("mmu"), &prom_mmu, sizeof(prom_mmu)) <= 0) {
- prom_print(RELOC(" no MMU found\n"));
- } else {
- int nargs;
- struct prom_args prom_args;
- nargs = 4;
- prom_args.service = RELOC("call-method");
- prom_args.nargs = nargs;
- prom_args.nret = 4;
- prom_args.args[0] = RELOC("translate");
- prom_args.args[1] = prom_mmu;
- prom_args.args[2] = (void *)(offset + KERNELBASE);
- prom_args.args[3] = (void *)1;
- RELOC(prom)(&prom_args);
-
- /* We assume the phys. address size is 3 cells */
- if (prom_args.args[nargs] != 0)
- prom_print(RELOC(" (translate failed)\n"));
- else
- phys = (unsigned long)prom_args.args[nargs+3];
- }
- }
-
-#ifdef CONFIG_BOOTX_TEXT
- if (RELOC(prom_disp_node) != 0)
- setup_disp_fake_bi(RELOC(prom_disp_node));
-#endif
-
- /* Use quiesce call to get OF to shut down any devices it's using */
- prom_print(RELOC("Calling quiesce ...\n"));
- call_prom(RELOC("quiesce"), 0, 0);
-
-#ifdef CONFIG_BOOTX_TEXT
- if (RELOC(prom_disp_node) != 0)
- btext_prepare_BAT();
-#endif
-
- prom_print(RELOC("returning "));
- prom_print_hex(phys);
- prom_print(RELOC(" from prom_init\n"));
- RELOC(prom_stdout) = 0;
-
- return phys;
-}
-
-void phys_call_rtas(int service, int nargs, int nret, ...)
+void __openfirmware
+phys_call_rtas(int service, int nargs, int nret, ...)
{
va_list list;
union {
unsigned long words[16];
double align;
} u;
- unsigned long offset = reloc_offset();
void (*rtas)(void *, unsigned long);
int i;
@@ -688,340 +100,8 @@
u.words[i+3] = va_arg(list, unsigned long);
va_end(list);
- rtas = (void (*)(void *, unsigned long)) RELOC(rtas_entry);
- rtas(&u, RELOC(rtas_data));
-}
-
-static int __init
-prom_set_color(ihandle ih, int i, int r, int g, int b)
-{
- struct prom_args prom_args;
- unsigned long offset = reloc_offset();
-
- prom_args.service = RELOC("call-method");
- prom_args.nargs = 6;
- prom_args.nret = 1;
- prom_args.args[0] = RELOC("color!");
- prom_args.args[1] = ih;
- prom_args.args[2] = (void *) i;
- prom_args.args[3] = (void *) b;
- prom_args.args[4] = (void *) g;
- prom_args.args[5] = (void *) r;
- RELOC(prom)(&prom_args);
- return (int) prom_args.args[6];
-}
-
-/*
- * 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;
- unsigned long offset = reloc_offset();
- 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
- };
-
- RELOC(prom_disp_node) = 0;
-
- 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);
- if ((int) call_prom(RELOC("package-to-path"), 3, 1,
- node, path, 255) < 0)
- continue;
-
- /*
- * 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)++;
- 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]);
- }
- }
- RELOC(prom_display_paths[i]) = PTRUNRELOC(path);
- RELOC(prom_display_nodes[i]) = node;
- if (i == 0)
- RELOC(prom_disp_node) = node;
- if (RELOC(prom_num_displays) >= FB_MAX)
- break;
- }
-
-try_again:
- /*
- * Open the first display and set its colormap.
- */
- if (RELOC(prom_num_displays) > 0) {
- path = PTRRELOC(RELOC(prom_display_paths[0]));
- prom_print(RELOC("opening display "));
- prom_print(path);
- ih = call_prom(RELOC("open"), 1, 1, path);
- if (ih == 0 || ih == (ihandle) -1) {
- prom_print(RELOC("... failed\n"));
- for (i=1; i<RELOC(prom_num_displays); i++) {
- RELOC(prom_display_paths[i-1]) = RELOC(prom_display_paths[i]);
- RELOC(prom_display_nodes[i-1]) = RELOC(prom_display_nodes[i]);
- }
- if (--RELOC(prom_num_displays) > 0)
- RELOC(prom_disp_node) = RELOC(prom_display_nodes[0]);
- else
- RELOC(prom_disp_node) = NULL;
- goto try_again;
- } else {
- prom_print(RELOC("... ok\n"));
- /*
- * Setup a usable color table when the appropriate
- * method is available.
- * Should update this to use set-colors.
- */
- for (i = 0; i < 32; i++)
- if (prom_set_color(ih, i, RELOC(default_colors)[i*3],
- RELOC(default_colors)[i*3+1],
- RELOC(default_colors)[i*3+2]) != 0)
- break;
-
-#ifdef CONFIG_FB
- for (i = 0; i < LINUX_LOGO_COLORS; i++)
- if (prom_set_color(ih, i + 32,
- RELOC(linux_logo_red)[i],
- RELOC(linux_logo_green)[i],
- RELOC(linux_logo_blue)[i]) != 0)
- break;
-#endif /* CONFIG_FB */
- }
- }
-
- return ALIGN(mem);
-}
-
-/* This function will enable the early boot text when doing OF booting. This
- * way, xmon output should work too
- */
-#ifdef CONFIG_BOOTX_TEXT
-static void __init
-setup_disp_fake_bi(ihandle dp)
-{
- int width = 640, height = 480, depth = 8, pitch;
- unsigned address;
- unsigned long offset = reloc_offset();
- struct pci_reg_property addrs[8];
- int i, naddrs;
- char name[32];
- 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;
- 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\n"));
- return;
- }
- }
- /* kludge for valkyrie */
- if (strcmp(name, RELOC("valkyrie")) == 0)
- address += 0x1000;
-
- btext_setup_display(width, height, depth, pitch, address);
-}
-#endif
-
-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;
- }
-}
-
-/*
- * Make a copy of the device tree from the PROM.
- */
-static unsigned long __init
-copy_device_tree(unsigned long mem_start, unsigned long mem_end)
-{
- phandle root;
- unsigned long new_start;
- struct device_node **allnextp;
- unsigned long offset = reloc_offset();
-
- root = call_prom(RELOC("peer"), 1, 1, (phandle)0);
- if (root == (phandle)0) {
- prom_print(RELOC("couldn't get device tree root\n"));
- prom_exit();
- }
- allnextp = &RELOC(allnodes);
- mem_start = ALIGN(mem_start);
- new_start = inspect_node(root, 0, mem_start, mem_end, &allnextp);
- *allnextp = 0;
- return new_start;
-}
-
-static unsigned long __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();
-
- np = (struct device_node *) mem_start;
- mem_start += sizeof(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 (;;) {
- pp = (struct property *) mem_start;
- namep = (char *) (pp + 1);
- pp->name = PTRUNRELOC(namep);
- if ((int) call_prom(RELOC("nextprop"), 3, 1, node, prev_name,
- namep) <= 0)
- break;
- mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1);
- prev_name = namep;
- valp = (unsigned char *) mem_start;
- pp->value = PTRUNRELOC(valp);
- pp->length = (int)
- call_prom(RELOC("getprop"), 4, 1, node, namep,
- valp, mem_end - mem_start);
- if (pp->length < 0)
- continue;
-#ifdef MAX_PROPERTY_LENGTH
- if (pp->length > MAX_PROPERTY_LENGTH)
- continue; /* ignore this property */
-#endif
- mem_start = ALIGN(mem_start + pp->length);
- *prev_propp = PTRUNRELOC(pp);
- prev_propp = &pp->next;
- }
- if (np->node != NULL) {
- /* Add a "linux,phandle" property" */
- pp = (struct property *) mem_start;
- *prev_propp = PTRUNRELOC(pp);
- prev_propp = &pp->next;
- namep = (char *) (pp + 1);
- pp->name = PTRUNRELOC(namep);
- strcpy(namep, RELOC("linux,phandle"));
- mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1);
- pp->value = (unsigned char *) PTRUNRELOC(&np->node);
- pp->length = sizeof(np->node);
- }
- *prev_propp = NULL;
-
- /* get the node's full name */
- l = (int) call_prom(RELOC("package-to-path"), 3, 1, node,
- (char *) mem_start, mem_end - mem_start);
- if (l >= 0) {
- np->full_name = PTRUNRELOC((char *) mem_start);
- *(char *)(mem_start + l) = 0;
- mem_start = ALIGN(mem_start + l + 1);
- }
-
- /* do all our children */
- child = call_prom(RELOC("child"), 1, 1, node);
- while (child != (void *)0) {
- mem_start = inspect_node(child, np, mem_start, mem_end,
- allnextpp);
- child = call_prom(RELOC("peer"), 1, 1, child);
- }
-
- return mem_start;
+ rtas = (void (*)(void *, unsigned long)) rtas_entry;
+ rtas(&u, rtas_data);
}
/*
@@ -1086,26 +166,6 @@
klimit = (char *) mem;
}
-/*
- * early_get_property is used to access the device tree image prepared
- * by BootX very early on, before the pointers in it have been relocated.
- */
-static void * __init
-early_get_property(unsigned long base, unsigned long node, char *prop)
-{
- struct device_node *np = (struct device_node *)(base + node);
- struct property *pp;
-
- for (pp = np->properties; pp != 0; pp = pp->next) {
- pp = (struct property *) (base + (unsigned long)pp);
- if (strcmp((char *)((unsigned long)pp->name + base),
- prop) == 0) {
- return (void *)((unsigned long)pp->value + base);
- }
- }
- return 0;
-}
-
static unsigned long __init
finish_node(struct device_node *np, unsigned long mem_start,
interpret_func *ifunc, int naddrc, int nsizec)
@@ -1136,19 +196,6 @@
if (ip != NULL)
nsizec = *ip;
- /*
- * The F50 sets the name to 'display' and 'compatible' to what we
- * expect for the name. -- Cort
- *
- * But sometimes you get a 'display' name for non-OF cards, and thus
- * no compatible property. And very rarely we won't have a name
- * property either. -- Tom
- */
- if (!strcmp(np->name, "display"))
- np->name = get_property(np, "compatible", 0);
- if (!np->name)
- np->name = get_property(np, "name", 0);
-
if (np->parent == NULL)
ifunc = interpret_root_props;
else if (np->type == 0)
@@ -2145,11 +1192,11 @@
u.words[i+3] = va_arg(list, unsigned long);
va_end(list);
- /* Shouldn't we enable kernel FP here ? enter_rtas will play
- * with MSR_FE0|MSR_FE1|MSR_FP so I assume rtas might use
- * floating points. If that's the case, then we need to make
- * sure any lazy FP context is backed up
- * --BenH
+ /*
+ * RTAS doesn't use floating point.
+ * Or at least, according to the CHRP spec we enter RTAS
+ * with FP disabled, and it doesn't change the FP registers.
+ * -- paulus.
*/
spin_lock_irqsave(&rtas_lock, s);
enter_rtas((void *)__pa(&u));
@@ -2160,13 +1207,3 @@
outputs[i] = u.words[i+nargs+4];
return u.words[nargs+3];
}
-
-void __init
-abort()
-{
-#ifdef CONFIG_XMON
- xmon(NULL);
-#endif
- for (;;)
- prom_exit();
-}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)