aboutsummaryrefslogtreecommitdiff
path: root/arch/sparc/prom
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/prom')
-rw-r--r--arch/sparc/prom/Makefile18
-rw-r--r--arch/sparc/prom/bootstr_32.c (renamed from arch/sparc/prom/bootstr.c)21
-rw-r--r--arch/sparc/prom/bootstr_64.c40
-rw-r--r--arch/sparc/prom/cif.S48
-rw-r--r--arch/sparc/prom/console.c220
-rw-r--r--arch/sparc/prom/console_32.c56
-rw-r--r--arch/sparc/prom/console_64.c45
-rw-r--r--arch/sparc/prom/devmap.c54
-rw-r--r--arch/sparc/prom/devops.c89
-rw-r--r--arch/sparc/prom/init_32.c (renamed from arch/sparc/prom/init.c)40
-rw-r--r--arch/sparc/prom/init_64.c56
-rw-r--r--arch/sparc/prom/memory.c231
-rw-r--r--arch/sparc/prom/misc_32.c (renamed from arch/sparc/prom/misc.c)22
-rw-r--r--arch/sparc/prom/misc_64.c446
-rw-r--r--arch/sparc/prom/mp.c82
-rw-r--r--arch/sparc/prom/p1275.c55
-rw-r--r--arch/sparc/prom/palloc.c44
-rw-r--r--arch/sparc/prom/printf.c45
-rw-r--r--arch/sparc/prom/ranges.c21
-rw-r--r--arch/sparc/prom/segment.c29
-rw-r--r--arch/sparc/prom/sun4prom.c161
-rw-r--r--arch/sparc/prom/tree_32.c (renamed from arch/sparc/prom/tree.c)157
-rw-r--r--arch/sparc/prom/tree_64.c392
23 files changed, 1324 insertions, 1048 deletions
diff --git a/arch/sparc/prom/Makefile b/arch/sparc/prom/Makefile
index 2b217ee4070..020300b18c0 100644
--- a/arch/sparc/prom/Makefile
+++ b/arch/sparc/prom/Makefile
@@ -1,9 +1,17 @@
-# $Id: Makefile,v 1.8 2000/12/15 00:41:22 davem Exp $
# Makefile for the Sun Boot PROM interface library under
# Linux.
#
+asflags := -ansi
+ccflags := -Werror
-lib-y := bootstr.o devmap.o devops.o init.o memory.o misc.o mp.o \
- palloc.o ranges.o segment.o console.o printf.o tree.o
-
-lib-$(CONFIG_SUN4) += sun4prom.o
+lib-y := bootstr_$(BITS).o
+lib-y += init_$(BITS).o
+lib-$(CONFIG_SPARC32) += memory.o
+lib-y += misc_$(BITS).o
+lib-$(CONFIG_SPARC32) += mp.o
+lib-$(CONFIG_SPARC32) += ranges.o
+lib-y += console_$(BITS).o
+lib-y += printf.o
+lib-y += tree_$(BITS).o
+lib-$(CONFIG_SPARC64) += p1275.o
+lib-$(CONFIG_SPARC64) += cif.o
diff --git a/arch/sparc/prom/bootstr.c b/arch/sparc/prom/bootstr_32.c
index cfdeac2788d..d2b49d2365e 100644
--- a/arch/sparc/prom/bootstr.c
+++ b/arch/sparc/prom/bootstr_32.c
@@ -1,4 +1,4 @@
-/* $Id: bootstr.c,v 1.20 2000/02/08 20:24:23 davem Exp $
+/*
* bootstr.c: Boot string/argument acquisition from the PROM.
*
* Copyright(C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -6,15 +6,12 @@
#include <linux/string.h>
#include <asm/oplib.h>
-#include <asm/sun4prom.h>
#include <linux/init.h>
#define BARG_LEN 256
static char barg_buf[BARG_LEN] = { 0 };
static char fetched __initdata = 0;
-extern linux_sun4_romvec *sun4_romvec;
-
char * __init
prom_getbootargs(void)
{
@@ -26,23 +23,25 @@ prom_getbootargs(void)
return barg_buf;
}
- switch(prom_vers) {
+ switch (prom_vers) {
case PROM_V0:
- case PROM_SUN4:
cp = barg_buf;
/* Start from 1 and go over fd(0,0,0)kernel */
- for(iter = 1; iter < 8; iter++) {
+ for (iter = 1; iter < 8; iter++) {
arg = (*(romvec->pv_v0bootargs))->argv[iter];
- if(arg == 0) break;
- while(*arg != 0) {
+ if (arg == NULL)
+ break;
+ while (*arg != 0) {
/* Leave place for space and null. */
- if(cp >= barg_buf + BARG_LEN-2){
+ if (cp >= barg_buf + BARG_LEN - 2)
/* We might issue a warning here. */
break;
- }
*cp++ = *arg++;
}
*cp++ = ' ';
+ if (cp >= barg_buf + BARG_LEN - 1)
+ /* We might issue a warning here. */
+ break;
}
*cp = 0;
break;
diff --git a/arch/sparc/prom/bootstr_64.c b/arch/sparc/prom/bootstr_64.c
new file mode 100644
index 00000000000..ab9ccc63b38
--- /dev/null
+++ b/arch/sparc/prom/bootstr_64.c
@@ -0,0 +1,40 @@
+/*
+ * bootstr.c: Boot string/argument acquisition from the PROM.
+ *
+ * Copyright(C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright(C) 1996,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include <linux/string.h>
+#include <linux/init.h>
+#include <asm/oplib.h>
+
+/* WARNING: The boot loader knows that these next three variables come one right
+ * after another in the .data section. Do not move this stuff into
+ * the .bss section or it will break things.
+ */
+
+#define BARG_LEN 256
+struct {
+ int bootstr_len;
+ int bootstr_valid;
+ char bootstr_buf[BARG_LEN];
+} bootstr_info = {
+ .bootstr_len = BARG_LEN,
+#ifdef CONFIG_CMDLINE
+ .bootstr_valid = 1,
+ .bootstr_buf = CONFIG_CMDLINE,
+#endif
+};
+
+char * __init
+prom_getbootargs(void)
+{
+ /* This check saves us from a panic when bootfd patches args. */
+ if (bootstr_info.bootstr_valid)
+ return bootstr_info.bootstr_buf;
+ prom_getstring(prom_chosen_node, "bootargs",
+ bootstr_info.bootstr_buf, BARG_LEN);
+ bootstr_info.bootstr_valid = 1;
+ return bootstr_info.bootstr_buf;
+}
diff --git a/arch/sparc/prom/cif.S b/arch/sparc/prom/cif.S
new file mode 100644
index 00000000000..9c86b4b7d42
--- /dev/null
+++ b/arch/sparc/prom/cif.S
@@ -0,0 +1,48 @@
+/* cif.S: PROM entry/exit assembler trampolines.
+ *
+ * Copyright (C) 1996, 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 2005, 2006 David S. Miller <davem@davemloft.net>
+ */
+
+#include <asm/pstate.h>
+#include <asm/cpudata.h>
+#include <asm/thread_info.h>
+
+ .text
+ .globl prom_cif_direct
+prom_cif_direct:
+ sethi %hi(p1275buf), %o1
+ or %o1, %lo(p1275buf), %o1
+ ldx [%o1 + 0x0010], %o2 ! prom_cif_stack
+ save %o2, -192, %sp
+ ldx [%i1 + 0x0008], %l2 ! prom_cif_handler
+ mov %g4, %l0
+ mov %g5, %l1
+ mov %g6, %l3
+ call %l2
+ mov %i0, %o0 ! prom_args
+ mov %l0, %g4
+ mov %l1, %g5
+ mov %l3, %g6
+ ret
+ restore
+
+ .globl prom_cif_callback
+prom_cif_callback:
+ sethi %hi(p1275buf), %o1
+ or %o1, %lo(p1275buf), %o1
+ save %sp, -192, %sp
+ TRAP_LOAD_THREAD_REG(%g6, %g1)
+ LOAD_PER_CPU_BASE(%g5, %g6, %g4, %g3, %o0)
+ ldx [%g6 + TI_TASK], %g4
+ call prom_world
+ mov 0, %o0
+ ldx [%i1 + 0x000], %l2
+ call %l2
+ mov %i0, %o0
+ mov %o0, %l1
+ call prom_world
+ mov 1, %o0
+ ret
+ restore %l1, 0, %o0
+
diff --git a/arch/sparc/prom/console.c b/arch/sparc/prom/console.c
deleted file mode 100644
index 4e6e41d3291..00000000000
--- a/arch/sparc/prom/console.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/* $Id: console.c,v 1.25 2001/10/30 04:54:22 davem Exp $
- * console.c: Routines that deal with sending and receiving IO
- * to/from the current console device using the PROM.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998 Pete Zaitcev <zaitcev@yahoo.com>
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <asm/openprom.h>
-#include <asm/sun4prom.h>
-#include <asm/oplib.h>
-#include <asm/system.h>
-#include <linux/string.h>
-
-extern void restore_current(void);
-
-static char con_name_jmc[] = "/obio/su@"; /* "/obio/su@0,3002f8"; */
-#define CON_SIZE_JMC (sizeof(con_name_jmc))
-
-/* Non blocking get character from console input device, returns -1
- * if no input was taken. This can be used for polling.
- */
-int
-prom_nbgetchar(void)
-{
- static char inc;
- int i = -1;
- unsigned long flags;
-
- spin_lock_irqsave(&prom_lock, flags);
- switch(prom_vers) {
- case PROM_V0:
- case PROM_SUN4:
- i = (*(romvec->pv_nbgetchar))();
- break;
- case PROM_V2:
- case PROM_V3:
- if( (*(romvec->pv_v2devops).v2_dev_read)(*romvec->pv_v2bootargs.fd_stdin , &inc, 0x1) == 1) {
- i = inc;
- } else {
- i = -1;
- }
- break;
- default:
- i = -1;
- break;
- };
- restore_current();
- spin_unlock_irqrestore(&prom_lock, flags);
- return i; /* Ugh, we could spin forever on unsupported proms ;( */
-}
-
-/* Non blocking put character to console device, returns -1 if
- * unsuccessful.
- */
-int
-prom_nbputchar(char c)
-{
- static char outc;
- unsigned long flags;
- int i = -1;
-
- spin_lock_irqsave(&prom_lock, flags);
- switch(prom_vers) {
- case PROM_V0:
- case PROM_SUN4:
- i = (*(romvec->pv_nbputchar))(c);
- break;
- case PROM_V2:
- case PROM_V3:
- outc = c;
- if( (*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout, &outc, 0x1) == 1)
- i = 0;
- else
- i = -1;
- break;
- default:
- i = -1;
- break;
- };
- restore_current();
- spin_unlock_irqrestore(&prom_lock, flags);
- return i; /* Ugh, we could spin forever on unsupported proms ;( */
-}
-
-/* Blocking version of get character routine above. */
-char
-prom_getchar(void)
-{
- int character;
- while((character = prom_nbgetchar()) == -1) ;
- return (char) character;
-}
-
-/* Blocking version of put character routine above. */
-void
-prom_putchar(char c)
-{
- while(prom_nbputchar(c) == -1) ;
- return;
-}
-
-/* Query for input device type */
-enum prom_input_device
-prom_query_input_device(void)
-{
- unsigned long flags;
- int st_p;
- char propb[64];
- char *p;
- int propl;
-
- switch(prom_vers) {
- case PROM_V0:
- case PROM_V2:
- case PROM_SUN4:
- default:
- switch(*romvec->pv_stdin) {
- case PROMDEV_KBD: return PROMDEV_IKBD;
- case PROMDEV_TTYA: return PROMDEV_ITTYA;
- case PROMDEV_TTYB: return PROMDEV_ITTYB;
- default:
- return PROMDEV_I_UNK;
- };
- case PROM_V3:
- spin_lock_irqsave(&prom_lock, flags);
- st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin);
- restore_current();
- spin_unlock_irqrestore(&prom_lock, flags);
- if(prom_node_has_property(st_p, "keyboard"))
- return PROMDEV_IKBD;
- if (prom_getproperty(st_p, "name", propb, sizeof(propb)) != -1) {
- if(strncmp(propb, "keyboard", sizeof("serial")) == 0)
- return PROMDEV_IKBD;
- }
- if (prom_getproperty(st_p, "device_type", propb, sizeof(propb)) != -1) {
- if(strncmp(propb, "serial", sizeof("serial")))
- return PROMDEV_I_UNK;
- }
- propl = prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb));
- if(propl > 2) {
- p = propb;
- while(*p) p++; p -= 2;
- if(p[0] == ':') {
- if(p[1] == 'a')
- return PROMDEV_ITTYA;
- else if(p[1] == 'b')
- return PROMDEV_ITTYB;
- }
- }
- return PROMDEV_I_UNK;
- }
-}
-
-/* Query for output device type */
-
-enum prom_output_device
-prom_query_output_device(void)
-{
- unsigned long flags;
- int st_p;
- char propb[64];
- char *p;
- int propl;
-
- switch(prom_vers) {
- case PROM_V0:
- case PROM_SUN4:
- switch(*romvec->pv_stdin) {
- case PROMDEV_SCREEN: return PROMDEV_OSCREEN;
- case PROMDEV_TTYA: return PROMDEV_OTTYA;
- case PROMDEV_TTYB: return PROMDEV_OTTYB;
- };
- break;
- case PROM_V2:
- case PROM_V3:
- spin_lock_irqsave(&prom_lock, flags);
- st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout);
- restore_current();
- spin_unlock_irqrestore(&prom_lock, flags);
- propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb));
- if (propl == sizeof("display") &&
- strncmp("display", propb, sizeof("display")) == 0)
- {
- return PROMDEV_OSCREEN;
- }
- if(prom_vers == PROM_V3) {
- if(propl >= 0 &&
- strncmp("serial", propb, sizeof("serial")) != 0)
- return PROMDEV_O_UNK;
- propl = prom_getproperty(prom_root_node, "stdout-path",
- propb, sizeof(propb));
- if(propl == CON_SIZE_JMC &&
- strncmp(propb, con_name_jmc, CON_SIZE_JMC) == 0)
- return PROMDEV_OTTYA;
- if(propl > 2) {
- p = propb;
- while(*p) p++; p-= 2;
- if(p[0]==':') {
- if(p[1] == 'a')
- return PROMDEV_OTTYA;
- else if(p[1] == 'b')
- return PROMDEV_OTTYB;
- }
- }
- } else {
- switch(*romvec->pv_stdin) {
- case PROMDEV_TTYA: return PROMDEV_OTTYA;
- case PROMDEV_TTYB: return PROMDEV_OTTYB;
- };
- }
- break;
- default:
- ;
- };
- return PROMDEV_O_UNK;
-}
diff --git a/arch/sparc/prom/console_32.c b/arch/sparc/prom/console_32.c
new file mode 100644
index 00000000000..1cfb50f4cb9
--- /dev/null
+++ b/arch/sparc/prom/console_32.c
@@ -0,0 +1,56 @@
+/*
+ * console.c: Routines that deal with sending and receiving IO
+ * to/from the current console device using the PROM.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1998 Pete Zaitcev <zaitcev@yahoo.com>
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/openprom.h>
+#include <asm/oplib.h>
+#include <linux/string.h>
+
+extern void restore_current(void);
+
+/* Non blocking put character to console device, returns -1 if
+ * unsuccessful.
+ */
+static int prom_nbputchar(const char *buf)
+{
+ unsigned long flags;
+ int i = -1;
+
+ spin_lock_irqsave(&prom_lock, flags);
+ switch(prom_vers) {
+ case PROM_V0:
+ if ((*(romvec->pv_nbputchar))(*buf))
+ i = 1;
+ break;
+ case PROM_V2:
+ case PROM_V3:
+ if ((*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout,
+ buf, 0x1) == 1)
+ i = 1;
+ break;
+ default:
+ break;
+ }
+ restore_current();
+ spin_unlock_irqrestore(&prom_lock, flags);
+ return i; /* Ugh, we could spin forever on unsupported proms ;( */
+}
+
+void prom_console_write_buf(const char *buf, int len)
+{
+ while (len) {
+ int n = prom_nbputchar(buf);
+ if (n < 0)
+ continue;
+ len--;
+ buf++;
+ }
+}
+
diff --git a/arch/sparc/prom/console_64.c b/arch/sparc/prom/console_64.c
new file mode 100644
index 00000000000..f95edcc54fd
--- /dev/null
+++ b/arch/sparc/prom/console_64.c
@@ -0,0 +1,45 @@
+/* console.c: Routines that deal with sending and receiving IO
+ * to/from the current console device using the PROM.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/openprom.h>
+#include <asm/oplib.h>
+#include <linux/string.h>
+
+static int __prom_console_write_buf(const char *buf, int len)
+{
+ unsigned long args[7];
+ int ret;
+
+ args[0] = (unsigned long) "write";
+ args[1] = 3;
+ args[2] = 1;
+ args[3] = (unsigned int) prom_stdout;
+ args[4] = (unsigned long) buf;
+ args[5] = (unsigned int) len;
+ args[6] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ ret = (int) args[6];
+ if (ret < 0)
+ return -1;
+ return ret;
+}
+
+void prom_console_write_buf(const char *buf, int len)
+{
+ while (len) {
+ int n = __prom_console_write_buf(buf, len);
+ if (n < 0)
+ continue;
+ len -= n;
+ buf += len;
+ }
+}
diff --git a/arch/sparc/prom/devmap.c b/arch/sparc/prom/devmap.c
deleted file mode 100644
index eb12073578a..00000000000
--- a/arch/sparc/prom/devmap.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* $Id: devmap.c,v 1.7 2000/08/26 02:38:03 anton Exp $
- * promdevmap.c: Map device/IO areas to virtual addresses.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-
-extern void restore_current(void);
-
-/* Just like the routines in palloc.c, these should not be used
- * by the kernel at all. Bootloader facility mainly. And again,
- * this is only available on V2 proms and above.
- */
-
-/* Map physical device address 'paddr' in IO space 'ios' of size
- * 'num_bytes' to a virtual address, with 'vhint' being a hint to
- * the prom as to where you would prefer the mapping. We return
- * where the prom actually mapped it.
- */
-char *
-prom_mapio(char *vhint, int ios, unsigned int paddr, unsigned int num_bytes)
-{
- unsigned long flags;
- char *ret;
-
- spin_lock_irqsave(&prom_lock, flags);
- if((num_bytes == 0) || (paddr == 0)) ret = (char *) 0x0;
- else
- ret = (*(romvec->pv_v2devops.v2_dumb_mmap))(vhint, ios, paddr,
- num_bytes);
- restore_current();
- spin_unlock_irqrestore(&prom_lock, flags);
- return ret;
-}
-
-/* Unmap an IO/device area that was mapped using the above routine. */
-void
-prom_unmapio(char *vaddr, unsigned int num_bytes)
-{
- unsigned long flags;
-
- if(num_bytes == 0x0) return;
- spin_lock_irqsave(&prom_lock, flags);
- (*(romvec->pv_v2devops.v2_dumb_munmap))(vaddr, num_bytes);
- restore_current();
- spin_unlock_irqrestore(&prom_lock, flags);
- return;
-}
diff --git a/arch/sparc/prom/devops.c b/arch/sparc/prom/devops.c
deleted file mode 100644
index 61919b54f6c..00000000000
--- a/arch/sparc/prom/devops.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/* $Id: devops.c,v 1.13 2000/08/26 02:38:03 anton Exp $
- * devops.c: Device operations using the PROM.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-
-extern void restore_current(void);
-
-/* Open the device described by the string 'dstr'. Returns the handle
- * to that device used for subsequent operations on that device.
- * Returns -1 on failure.
- */
-int
-prom_devopen(char *dstr)
-{
- int handle;
- unsigned long flags;
- spin_lock_irqsave(&prom_lock, flags);
- switch(prom_vers) {
- case PROM_V0:
- handle = (*(romvec->pv_v0devops.v0_devopen))(dstr);
- if(handle == 0) handle = -1;
- break;
- case PROM_V2:
- case PROM_V3:
- handle = (*(romvec->pv_v2devops.v2_dev_open))(dstr);
- break;
- default:
- handle = -1;
- break;
- };
- restore_current();
- spin_unlock_irqrestore(&prom_lock, flags);
-
- return handle;
-}
-
-/* Close the device described by device handle 'dhandle'. */
-int
-prom_devclose(int dhandle)
-{
- unsigned long flags;
- spin_lock_irqsave(&prom_lock, flags);
- switch(prom_vers) {
- case PROM_V0:
- (*(romvec->pv_v0devops.v0_devclose))(dhandle);
- break;
- case PROM_V2:
- case PROM_V3:
- (*(romvec->pv_v2devops.v2_dev_close))(dhandle);
- break;
- default:
- break;
- };
- restore_current();
- spin_unlock_irqrestore(&prom_lock, flags);
- return 0;
-}
-
-/* Seek to specified location described by 'seekhi' and 'seeklo'
- * for device 'dhandle'.
- */
-void
-prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo)
-{
- unsigned long flags;
- spin_lock_irqsave(&prom_lock, flags);
- switch(prom_vers) {
- case PROM_V0:
- (*(romvec->pv_v0devops.v0_seekdev))(dhandle, seekhi, seeklo);
- break;
- case PROM_V2:
- case PROM_V3:
- (*(romvec->pv_v2devops.v2_dev_seek))(dhandle, seekhi, seeklo);
- break;
- default:
- break;
- };
- restore_current();
- spin_unlock_irqrestore(&prom_lock, flags);
-
- return;
-}
diff --git a/arch/sparc/prom/init.c b/arch/sparc/prom/init_32.c
index b83409c8191..9ac30c2b7db 100644
--- a/arch/sparc/prom/init.c
+++ b/arch/sparc/prom/init_32.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.14 2000/01/29 01:09:12 anton Exp $
+/*
* init.c: Initialize internal variables used by the PROM
* library functions.
*
@@ -6,41 +6,33 @@
* Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
-#include <asm/sun4prom.h>
struct linux_romvec *romvec;
+EXPORT_SYMBOL(romvec);
+
enum prom_major_version prom_vers;
unsigned int prom_rev, prom_prev;
-linux_sun4_romvec *sun4_romvec;
/* The root node of the prom device tree. */
-int prom_root_node;
-
-int prom_stdin, prom_stdout;
+phandle prom_root_node;
+EXPORT_SYMBOL(prom_root_node);
/* Pointer to the device tree operations structure. */
struct linux_nodeops *prom_nodeops;
/* You must call prom_init() before you attempt to use any of the
- * routines in the prom library. It returns 0 on success, 1 on
- * failure. It gets passed the pointer to the PROM vector.
+ * routines in the prom library.
+ * It gets passed the pointer to the PROM vector.
*/
-extern void prom_meminit(void);
-extern void prom_ranges_init(void);
-
void __init prom_init(struct linux_romvec *rp)
{
-#ifdef CONFIG_SUN4
- extern struct linux_romvec *sun4_prom_init(void);
- rp = sun4_prom_init();
-#endif
romvec = rp;
switch(romvec->pv_romvers) {
@@ -53,43 +45,31 @@ void __init prom_init(struct linux_romvec *rp)
case 3:
prom_vers = PROM_V3;
break;
- case 40:
- prom_vers = PROM_SUN4;
- break;
default:
prom_printf("PROMLIB: Bad PROM version %d\n",
romvec->pv_romvers);
prom_halt();
break;
- };
+ }
prom_rev = romvec->pv_plugin_revision;
prom_prev = romvec->pv_printrev;
prom_nodeops = romvec->pv_nodeops;
prom_root_node = prom_getsibling(0);
- if((prom_root_node == 0) || (prom_root_node == -1))
+ if ((prom_root_node == 0) || ((s32)prom_root_node == -1))
prom_halt();
if((((unsigned long) prom_nodeops) == 0) ||
(((unsigned long) prom_nodeops) == -1))
prom_halt();
- if(prom_vers == PROM_V2 || prom_vers == PROM_V3) {
- prom_stdout = *romvec->pv_v2bootargs.fd_stdout;
- prom_stdin = *romvec->pv_v2bootargs.fd_stdin;
- }
-
prom_meminit();
prom_ranges_init();
-#ifndef CONFIG_SUN4
- /* SUN4 prints this in sun4_prom_init */
printk("PROMLIB: Sun Boot Prom Version %d Revision %d\n",
romvec->pv_romvers, prom_rev);
-#endif
/* Initialization successful. */
- return;
}
diff --git a/arch/sparc/prom/init_64.c b/arch/sparc/prom/init_64.c
new file mode 100644
index 00000000000..d95db755828
--- /dev/null
+++ b/arch/sparc/prom/init_64.c
@@ -0,0 +1,56 @@
+/*
+ * init.c: Initialize internal variables used by the PROM
+ * library functions.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+
+#include <asm/openprom.h>
+#include <asm/oplib.h>
+
+/* OBP version string. */
+char prom_version[80];
+
+/* The root node of the prom device tree. */
+int prom_stdout;
+phandle prom_chosen_node;
+
+/* You must call prom_init() before you attempt to use any of the
+ * routines in the prom library.
+ * It gets passed the pointer to the PROM vector.
+ */
+
+extern void prom_cif_init(void *, void *);
+
+void __init prom_init(void *cif_handler, void *cif_stack)
+{
+ phandle node;
+
+ prom_cif_init(cif_handler, cif_stack);
+
+ prom_chosen_node = prom_finddevice(prom_chosen_path);
+ if (!prom_chosen_node || (s32)prom_chosen_node == -1)
+ prom_halt();
+
+ prom_stdout = prom_getint(prom_chosen_node, "stdout");
+
+ node = prom_finddevice("/openprom");
+ if (!node || (s32)node == -1)
+ prom_halt();
+
+ prom_getstring(node, "version", prom_version, sizeof(prom_version));
+
+ prom_printf("\n");
+}
+
+void __init prom_init_report(void)
+{
+ printk("PROMLIB: Sun IEEE Boot Prom '%s'\n", prom_version);
+ printk("PROMLIB: Root node compatible: %s\n", prom_root_compatible);
+}
diff --git a/arch/sparc/prom/memory.c b/arch/sparc/prom/memory.c
index c20e5309f8a..3f263a64857 100644
--- a/arch/sparc/prom/memory.c
+++ b/arch/sparc/prom/memory.c
@@ -1,216 +1,87 @@
-/* $Id: memory.c,v 1.15 2000/01/29 01:09:12 anton Exp $
- * memory.c: Prom routine for acquiring various bits of information
+/* memory.c: Prom routine for acquiring various bits of information
* about RAM on the machine, both virtual and physical.
*
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 2008 David S. Miller (davem@davemloft.net)
* Copyright (C) 1997 Michael A. Griffith (grif@acm.org)
*/
-#include <linux/config.h>
#include <linux/kernel.h>
+#include <linux/sort.h>
#include <linux/init.h>
#include <asm/openprom.h>
-#include <asm/sun4prom.h>
#include <asm/oplib.h>
+#include <asm/page.h>
-/* This routine, for consistency, returns the ram parameters in the
- * V0 prom memory descriptor format. I choose this format because I
- * think it was the easiest to work with. I feel the religious
- * arguments now... ;) Also, I return the linked lists sorted to
- * prevent paging_init() upset stomach as I have not yet written
- * the pepto-bismol kernel module yet.
- */
+static int __init prom_meminit_v0(void)
+{
+ struct linux_mlist_v0 *p;
+ int index;
+
+ index = 0;
+ for (p = *(romvec->pv_v0mem.v0_available); p; p = p->theres_more) {
+ sp_banks[index].base_addr = (unsigned long) p->start_adr;
+ sp_banks[index].num_bytes = p->num_bytes;
+ index++;
+ }
-struct linux_prom_registers prom_reg_memlist[64];
-struct linux_prom_registers prom_reg_tmp[64];
+ return index;
+}
-struct linux_mlist_v0 prom_phys_total[64];
-struct linux_mlist_v0 prom_prom_taken[64];
-struct linux_mlist_v0 prom_phys_avail[64];
+static int __init prom_meminit_v2(void)
+{
+ struct linux_prom_registers reg[64];
+ phandle node;
+ int size, num_ents, i;
-struct linux_mlist_v0 *prom_ptot_ptr = prom_phys_total;
-struct linux_mlist_v0 *prom_ptak_ptr = prom_prom_taken;
-struct linux_mlist_v0 *prom_pavl_ptr = prom_phys_avail;
+ node = prom_searchsiblings(prom_getchild(prom_root_node), "memory");
+ size = prom_getproperty(node, "available", (char *) reg, sizeof(reg));
+ num_ents = size / sizeof(struct linux_prom_registers);
-struct linux_mem_v0 prom_memlist;
+ for (i = 0; i < num_ents; i++) {
+ sp_banks[i].base_addr = reg[i].phys_addr;
+ sp_banks[i].num_bytes = reg[i].reg_size;
+ }
+ return num_ents;
+}
-/* Internal Prom library routine to sort a linux_mlist_v0 memory
- * list. Used below in initialization.
- */
-static void __init
-prom_sortmemlist(struct linux_mlist_v0 *thislist)
+static int sp_banks_cmp(const void *a, const void *b)
{
- int swapi = 0;
- int i, mitr, tmpsize;
- char *tmpaddr;
- char *lowest;
-
- for(i=0; thislist[i].theres_more; i++) {
- lowest = thislist[i].start_adr;
- for(mitr = i+1; thislist[mitr-1].theres_more; mitr++)
- if(thislist[mitr].start_adr < lowest) {
- lowest = thislist[mitr].start_adr;
- swapi = mitr;
- }
- if(lowest == thislist[i].start_adr) continue;
- tmpaddr = thislist[swapi].start_adr;
- tmpsize = thislist[swapi].num_bytes;
- for(mitr = swapi; mitr > i; mitr--) {
- thislist[mitr].start_adr = thislist[mitr-1].start_adr;
- thislist[mitr].num_bytes = thislist[mitr-1].num_bytes;
- }
- thislist[i].start_adr = tmpaddr;
- thislist[i].num_bytes = tmpsize;
- }
+ const struct sparc_phys_banks *x = a, *y = b;
- return;
+ if (x->base_addr > y->base_addr)
+ return 1;
+ if (x->base_addr < y->base_addr)
+ return -1;
+ return 0;
}
/* Initialize the memory lists based upon the prom version. */
void __init prom_meminit(void)
{
- int node = 0;
- unsigned int iter, num_regs;
- struct linux_mlist_v0 *mptr; /* ptr for traversal */
+ int i, num_ents = 0;
- switch(prom_vers) {
+ switch (prom_vers) {
case PROM_V0:
- /* Nice, kind of easier to do in this case. */
- /* First, the total physical descriptors. */
- for(mptr = (*(romvec->pv_v0mem.v0_totphys)), iter=0;
- mptr; mptr=mptr->theres_more, iter++) {
- prom_phys_total[iter].start_adr = mptr->start_adr;
- prom_phys_total[iter].num_bytes = mptr->num_bytes;
- prom_phys_total[iter].theres_more = &prom_phys_total[iter+1];
- }
- prom_phys_total[iter-1].theres_more = NULL;
- /* Second, the total prom taken descriptors. */
- for(mptr = (*(romvec->pv_v0mem.v0_prommap)), iter=0;
- mptr; mptr=mptr->theres_more, iter++) {
- prom_prom_taken[iter].start_adr = mptr->start_adr;
- prom_prom_taken[iter].num_bytes = mptr->num_bytes;
- prom_prom_taken[iter].theres_more = &prom_prom_taken[iter+1];
- }
- prom_prom_taken[iter-1].theres_more = NULL;
- /* Last, the available physical descriptors. */
- for(mptr = (*(romvec->pv_v0mem.v0_available)), iter=0;
- mptr; mptr=mptr->theres_more, iter++) {
- prom_phys_avail[iter].start_adr = mptr->start_adr;
- prom_phys_avail[iter].num_bytes = mptr->num_bytes;
- prom_phys_avail[iter].theres_more = &prom_phys_avail[iter+1];
- }
- prom_phys_avail[iter-1].theres_more = NULL;
- /* Sort all the lists. */
- prom_sortmemlist(prom_phys_total);
- prom_sortmemlist(prom_prom_taken);
- prom_sortmemlist(prom_phys_avail);
+ num_ents = prom_meminit_v0();
break;
+
case PROM_V2:
case PROM_V3:
- /* Grrr, have to traverse the prom device tree ;( */
- node = prom_getchild(prom_root_node);
- node = prom_searchsiblings(node, "memory");
- num_regs = prom_getproperty(node, "available",
- (char *) prom_reg_memlist,
- sizeof(prom_reg_memlist));
- num_regs = (num_regs/sizeof(struct linux_prom_registers));
- for(iter=0; iter<num_regs; iter++) {
- prom_phys_avail[iter].start_adr =
- (char *) prom_reg_memlist[iter].phys_addr;
- prom_phys_avail[iter].num_bytes =
- (unsigned long) prom_reg_memlist[iter].reg_size;
- prom_phys_avail[iter].theres_more =
- &prom_phys_avail[iter+1];
- }
- prom_phys_avail[iter-1].theres_more = NULL;
-
- num_regs = prom_getproperty(node, "reg",
- (char *) prom_reg_memlist,
- sizeof(prom_reg_memlist));
- num_regs = (num_regs/sizeof(struct linux_prom_registers));
- for(iter=0; iter<num_regs; iter++) {
- prom_phys_total[iter].start_adr =
- (char *) prom_reg_memlist[iter].phys_addr;
- prom_phys_total[iter].num_bytes =
- (unsigned long) prom_reg_memlist[iter].reg_size;
- prom_phys_total[iter].theres_more =
- &prom_phys_total[iter+1];
- }
- prom_phys_total[iter-1].theres_more = NULL;
-
- node = prom_getchild(prom_root_node);
- node = prom_searchsiblings(node, "virtual-memory");
- num_regs = prom_getproperty(node, "available",
- (char *) prom_reg_memlist,
- sizeof(prom_reg_memlist));
- num_regs = (num_regs/sizeof(struct linux_prom_registers));
-
- /* Convert available virtual areas to taken virtual
- * areas. First sort, then convert.
- */
- for(iter=0; iter<num_regs; iter++) {
- prom_prom_taken[iter].start_adr =
- (char *) prom_reg_memlist[iter].phys_addr;
- prom_prom_taken[iter].num_bytes =
- (unsigned long) prom_reg_memlist[iter].reg_size;
- prom_prom_taken[iter].theres_more =
- &prom_prom_taken[iter+1];
- }
- prom_prom_taken[iter-1].theres_more = NULL;
-
- prom_sortmemlist(prom_prom_taken);
-
- /* Finally, convert. */
- for(iter=0; iter<num_regs; iter++) {
- prom_prom_taken[iter].start_adr =
- prom_prom_taken[iter].start_adr +
- prom_prom_taken[iter].num_bytes;
- prom_prom_taken[iter].num_bytes =
- prom_prom_taken[iter+1].start_adr -
- prom_prom_taken[iter].start_adr;
- }
- prom_prom_taken[iter-1].num_bytes =
- 0xffffffff - (unsigned long) prom_prom_taken[iter-1].start_adr;
-
- /* Sort the other two lists. */
- prom_sortmemlist(prom_phys_total);
- prom_sortmemlist(prom_phys_avail);
- break;
-
- case PROM_SUN4:
-#ifdef CONFIG_SUN4
- /* how simple :) */
- prom_phys_total[0].start_adr = NULL;
- prom_phys_total[0].num_bytes = *(sun4_romvec->memorysize);
- prom_phys_total[0].theres_more = NULL;
- prom_prom_taken[0].start_adr = NULL;
- prom_prom_taken[0].num_bytes = 0x0;
- prom_prom_taken[0].theres_more = NULL;
- prom_phys_avail[0].start_adr = NULL;
- prom_phys_avail[0].num_bytes = *(sun4_romvec->memoryavail);
- prom_phys_avail[0].theres_more = NULL;
-#endif
+ num_ents = prom_meminit_v2();
break;
default:
break;
- };
-
- /* Link all the lists into the top-level descriptor. */
- prom_memlist.v0_totphys=&prom_ptot_ptr;
- prom_memlist.v0_prommap=&prom_ptak_ptr;
- prom_memlist.v0_available=&prom_pavl_ptr;
+ }
+ sort(sp_banks, num_ents, sizeof(struct sparc_phys_banks),
+ sp_banks_cmp, NULL);
- return;
-}
+ /* Sentinel. */
+ sp_banks[num_ents].base_addr = 0xdeadbeef;
+ sp_banks[num_ents].num_bytes = 0;
-/* This returns a pointer to our libraries internal v0 format
- * memory descriptor.
- */
-struct linux_mem_v0 *
-prom_meminfo(void)
-{
- return &prom_memlist;
+ for (i = 0; i < num_ents; i++)
+ sp_banks[i].num_bytes &= PAGE_MASK;
}
diff --git a/arch/sparc/prom/misc.c b/arch/sparc/prom/misc_32.c
index c840c206234..8dc0b6b271e 100644
--- a/arch/sparc/prom/misc.c
+++ b/arch/sparc/prom/misc_32.c
@@ -1,18 +1,18 @@
-/* $Id: misc.c,v 1.18 2000/08/26 02:38:03 anton Exp $
+/*
* misc.c: Miscellaneous prom functions that don't belong
* anywhere else.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/module.h>
+
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/auxio.h>
-#include <asm/system.h>
extern void restore_current(void);
@@ -45,9 +45,7 @@ prom_feval(char *fstring)
restore_current();
spin_unlock_irqrestore(&prom_lock, flags);
}
-
-/* We want to do this more nicely some day. */
-extern void (*prom_palette)(int);
+EXPORT_SYMBOL(prom_feval);
/* Drop into the prom, with the chance to continue with the 'go'
* prom command.
@@ -55,29 +53,19 @@ extern void (*prom_palette)(int);
void
prom_cmdline(void)
{
- extern void install_obp_ticker(void);
- extern void install_linux_ticker(void);
unsigned long flags;
- if(!serial_console && prom_palette)
- prom_palette (1);
spin_lock_irqsave(&prom_lock, flags);
- install_obp_ticker();
(*(romvec->pv_abort))();
restore_current();
- install_linux_ticker();
spin_unlock_irqrestore(&prom_lock, flags);
-#ifdef CONFIG_SUN_AUXIO
set_auxio(AUXIO_LED, 0);
-#endif
- if(!serial_console && prom_palette)
- prom_palette (0);
}
/* Drop into the prom, but completely terminate the program.
* No chance of continuing.
*/
-void
+void __noreturn
prom_halt(void)
{
unsigned long flags;
diff --git a/arch/sparc/prom/misc_64.c b/arch/sparc/prom/misc_64.c
new file mode 100644
index 00000000000..53a696d3eb3
--- /dev/null
+++ b/arch/sparc/prom/misc_64.c
@@ -0,0 +1,446 @@
+/*
+ * misc.c: Miscellaneous prom functions that don't belong
+ * anywhere else.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+
+#include <asm/openprom.h>
+#include <asm/oplib.h>
+#include <asm/ldc.h>
+
+static int prom_service_exists(const char *service_name)
+{
+ unsigned long args[5];
+
+ args[0] = (unsigned long) "test";
+ args[1] = 1;
+ args[2] = 1;
+ args[3] = (unsigned long) service_name;
+ args[4] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ if (args[4])
+ return 0;
+ return 1;
+}
+
+void prom_sun4v_guest_soft_state(void)
+{
+ const char *svc = "SUNW,soft-state-supported";
+ unsigned long args[3];
+
+ if (!prom_service_exists(svc))
+ return;
+ args[0] = (unsigned long) svc;
+ args[1] = 0;
+ args[2] = 0;
+ p1275_cmd_direct(args);
+}
+
+/* Reset and reboot the machine with the command 'bcommand'. */
+void prom_reboot(const char *bcommand)
+{
+ unsigned long args[4];
+
+#ifdef CONFIG_SUN_LDOMS
+ if (ldom_domaining_enabled)
+ ldom_reboot(bcommand);
+#endif
+ args[0] = (unsigned long) "boot";
+ args[1] = 1;
+ args[2] = 0;
+ args[3] = (unsigned long) bcommand;
+
+ p1275_cmd_direct(args);
+}
+
+/* Forth evaluate the expression contained in 'fstring'. */
+void prom_feval(const char *fstring)
+{
+ unsigned long args[5];
+
+ if (!fstring || fstring[0] == 0)
+ return;
+ args[0] = (unsigned long) "interpret";
+ args[1] = 1;
+ args[2] = 1;
+ args[3] = (unsigned long) fstring;
+ args[4] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+}
+EXPORT_SYMBOL(prom_feval);
+
+/* Drop into the prom, with the chance to continue with the 'go'
+ * prom command.
+ */
+void prom_cmdline(void)
+{
+ unsigned long args[3];
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+#ifdef CONFIG_SMP
+ smp_capture();
+#endif
+
+ args[0] = (unsigned long) "enter";
+ args[1] = 0;
+ args[2] = 0;
+
+ p1275_cmd_direct(args);
+
+#ifdef CONFIG_SMP
+ smp_release();
+#endif
+
+ local_irq_restore(flags);
+}
+
+/* Drop into the prom, but completely terminate the program.
+ * No chance of continuing.
+ */
+void notrace prom_halt(void)
+{
+ unsigned long args[3];
+
+#ifdef CONFIG_SUN_LDOMS
+ if (ldom_domaining_enabled)
+ ldom_power_off();
+#endif
+again:
+ args[0] = (unsigned long) "exit";
+ args[1] = 0;
+ args[2] = 0;
+ p1275_cmd_direct(args);
+ goto again; /* PROM is out to get me -DaveM */
+}
+
+void prom_halt_power_off(void)
+{
+ unsigned long args[3];
+
+#ifdef CONFIG_SUN_LDOMS
+ if (ldom_domaining_enabled)
+ ldom_power_off();
+#endif
+ args[0] = (unsigned long) "SUNW,power-off";
+ args[1] = 0;
+ args[2] = 0;
+ p1275_cmd_direct(args);
+
+ /* if nothing else helps, we just halt */
+ prom_halt();
+}
+
+/* Get the idprom and stuff it into buffer 'idbuf'. Returns the
+ * format type. 'num_bytes' is the number of bytes that your idbuf
+ * has space for. Returns 0xff on error.
+ */
+unsigned char prom_get_idprom(char *idbuf, int num_bytes)
+{
+ int len;
+
+ len = prom_getproplen(prom_root_node, "idprom");
+ if ((len >num_bytes) || (len == -1))
+ return 0xff;
+ if (!prom_getproperty(prom_root_node, "idprom", idbuf, num_bytes))
+ return idbuf[0];
+
+ return 0xff;
+}
+
+int prom_get_mmu_ihandle(void)
+{
+ phandle node;
+ int ret;
+
+ if (prom_mmu_ihandle_cache != 0)
+ return prom_mmu_ihandle_cache;
+
+ node = prom_finddevice(prom_chosen_path);
+ ret = prom_getint(node, prom_mmu_name);
+ if (ret == -1 || ret == 0)
+ prom_mmu_ihandle_cache = -1;
+ else
+ prom_mmu_ihandle_cache = ret;
+
+ return ret;
+}
+
+static int prom_get_memory_ihandle(void)
+{
+ static int memory_ihandle_cache;
+ phandle node;
+ int ret;
+
+ if (memory_ihandle_cache != 0)
+ return memory_ihandle_cache;
+
+ node = prom_finddevice("/chosen");
+ ret = prom_getint(node, "memory");
+ if (ret == -1 || ret == 0)
+ memory_ihandle_cache = -1;
+ else
+ memory_ihandle_cache = ret;
+
+ return ret;
+}
+
+/* Load explicit I/D TLB entries. */
+static long tlb_load(const char *type, unsigned long index,
+ unsigned long tte_data, unsigned long vaddr)
+{
+ unsigned long args[9];
+
+ args[0] = (unsigned long) prom_callmethod_name;
+ args[1] = 5;
+ args[2] = 1;
+ args[3] = (unsigned long) type;
+ args[4] = (unsigned int) prom_get_mmu_ihandle();
+ args[5] = vaddr;
+ args[6] = tte_data;
+ args[7] = index;
+ args[8] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ return (long) args[8];
+}
+
+long prom_itlb_load(unsigned long index,
+ unsigned long tte_data,
+ unsigned long vaddr)
+{
+ return tlb_load("SUNW,itlb-load", index, tte_data, vaddr);
+}
+
+long prom_dtlb_load(unsigned long index,
+ unsigned long tte_data,
+ unsigned long vaddr)
+{
+ return tlb_load("SUNW,dtlb-load", index, tte_data, vaddr);
+}
+
+int prom_map(int mode, unsigned long size,
+ unsigned long vaddr, unsigned long paddr)
+{
+ unsigned long args[11];
+ int ret;
+
+ args[0] = (unsigned long) prom_callmethod_name;
+ args[1] = 7;
+ args[2] = 1;
+ args[3] = (unsigned long) prom_map_name;
+ args[4] = (unsigned int) prom_get_mmu_ihandle();
+ args[5] = (unsigned int) mode;
+ args[6] = size;
+ args[7] = vaddr;
+ args[8] = 0;
+ args[9] = paddr;
+ args[10] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ ret = (int) args[10];
+ if (ret == 0)
+ ret = -1;
+ return ret;
+}
+
+void prom_unmap(unsigned long size, unsigned long vaddr)
+{
+ unsigned long args[7];
+
+ args[0] = (unsigned long) prom_callmethod_name;
+ args[1] = 4;
+ args[2] = 0;
+ args[3] = (unsigned long) prom_unmap_name;
+ args[4] = (unsigned int) prom_get_mmu_ihandle();
+ args[5] = size;
+ args[6] = vaddr;
+
+ p1275_cmd_direct(args);
+}
+
+/* Set aside physical memory which is not touched or modified
+ * across soft resets.
+ */
+int prom_retain(const char *name, unsigned long size,
+ unsigned long align, unsigned long *paddr)
+{
+ unsigned long args[11];
+
+ args[0] = (unsigned long) prom_callmethod_name;
+ args[1] = 5;
+ args[2] = 3;
+ args[3] = (unsigned long) "SUNW,retain";
+ args[4] = (unsigned int) prom_get_memory_ihandle();
+ args[5] = align;
+ args[6] = size;
+ args[7] = (unsigned long) name;
+ args[8] = (unsigned long) -1;
+ args[9] = (unsigned long) -1;
+ args[10] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ if (args[8])
+ return (int) args[8];
+
+ /* Next we get "phys_high" then "phys_low". On 64-bit
+ * the phys_high cell is don't care since the phys_low
+ * cell has the full value.
+ */
+ *paddr = args[10];
+
+ return 0;
+}
+
+/* Get "Unumber" string for the SIMM at the given
+ * memory address. Usually this will be of the form
+ * "Uxxxx" where xxxx is a decimal number which is
+ * etched into the motherboard next to the SIMM slot
+ * in question.
+ */
+int prom_getunumber(int syndrome_code,
+ unsigned long phys_addr,
+ char *buf, int buflen)
+{
+ unsigned long args[12];
+
+ args[0] = (unsigned long) prom_callmethod_name;
+ args[1] = 7;
+ args[2] = 2;
+ args[3] = (unsigned long) "SUNW,get-unumber";
+ args[4] = (unsigned int) prom_get_memory_ihandle();
+ args[5] = buflen;
+ args[6] = (unsigned long) buf;
+ args[7] = 0;
+ args[8] = phys_addr;
+ args[9] = (unsigned int) syndrome_code;
+ args[10] = (unsigned long) -1;
+ args[11] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ return (int) args[10];
+}
+
+/* Power management extensions. */
+void prom_sleepself(void)
+{
+ unsigned long args[3];
+
+ args[0] = (unsigned long) "SUNW,sleep-self";
+ args[1] = 0;
+ args[2] = 0;
+ p1275_cmd_direct(args);
+}
+
+int prom_sleepsystem(void)
+{
+ unsigned long args[4];
+
+ args[0] = (unsigned long) "SUNW,sleep-system";
+ args[1] = 0;
+ args[2] = 1;
+ args[3] = (unsigned long) -1;
+ p1275_cmd_direct(args);
+
+ return (int) args[3];
+}
+
+int prom_wakeupsystem(void)
+{
+ unsigned long args[4];
+
+ args[0] = (unsigned long) "SUNW,wakeup-system";
+ args[1] = 0;
+ args[2] = 1;
+ args[3] = (unsigned long) -1;
+ p1275_cmd_direct(args);
+
+ return (int) args[3];
+}
+
+#ifdef CONFIG_SMP
+void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg)
+{
+ unsigned long args[6];
+
+ args[0] = (unsigned long) "SUNW,start-cpu";
+ args[1] = 3;
+ args[2] = 0;
+ args[3] = (unsigned int) cpunode;
+ args[4] = pc;
+ args[5] = arg;
+ p1275_cmd_direct(args);
+}
+
+void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg)
+{
+ unsigned long args[6];
+
+ args[0] = (unsigned long) "SUNW,start-cpu-by-cpuid";
+ args[1] = 3;
+ args[2] = 0;
+ args[3] = (unsigned int) cpuid;
+ args[4] = pc;
+ args[5] = arg;
+ p1275_cmd_direct(args);
+}
+
+void prom_stopcpu_cpuid(int cpuid)
+{
+ unsigned long args[4];
+
+ args[0] = (unsigned long) "SUNW,stop-cpu-by-cpuid";
+ args[1] = 1;
+ args[2] = 0;
+ args[3] = (unsigned int) cpuid;
+ p1275_cmd_direct(args);
+}
+
+void prom_stopself(void)
+{
+ unsigned long args[3];
+
+ args[0] = (unsigned long) "SUNW,stop-self";
+ args[1] = 0;
+ args[2] = 0;
+ p1275_cmd_direct(args);
+}
+
+void prom_idleself(void)
+{
+ unsigned long args[3];
+
+ args[0] = (unsigned long) "SUNW,idle-self";
+ args[1] = 0;
+ args[2] = 0;
+ p1275_cmd_direct(args);
+}
+
+void prom_resumecpu(int cpunode)
+{
+ unsigned long args[4];
+
+ args[0] = (unsigned long) "SUNW,resume-cpu";
+ args[1] = 1;
+ args[2] = 0;
+ args[3] = (unsigned int) cpunode;
+ p1275_cmd_direct(args);
+}
+#endif
diff --git a/arch/sparc/prom/mp.c b/arch/sparc/prom/mp.c
index 92fe3739fdb..0da8256cf76 100644
--- a/arch/sparc/prom/mp.c
+++ b/arch/sparc/prom/mp.c
@@ -1,4 +1,4 @@
-/* $Id: mp.c,v 1.12 2000/08/26 02:38:03 anton Exp $
+/*
* mp.c: OpenBoot Prom Multiprocessor support routines. Don't call
* these on a UP or else you will halt and catch fire. ;)
*
@@ -35,85 +35,7 @@ prom_startcpu(int cpunode, struct linux_prom_registers *ctable_reg, int ctx, cha
case PROM_V3:
ret = (*(romvec->v3_cpustart))(cpunode, (int) ctable_reg, ctx, pc);
break;
- };
- restore_current();
- spin_unlock_irqrestore(&prom_lock, flags);
-
- return ret;
-}
-
-/* Stop CPU with device prom-tree node 'cpunode'.
- * XXX Again, what does the return value really mean? XXX
- */
-int
-prom_stopcpu(int cpunode)
-{
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&prom_lock, flags);
- switch(prom_vers) {
- case PROM_V0:
- case PROM_V2:
- default:
- ret = -1;
- break;
- case PROM_V3:
- ret = (*(romvec->v3_cpustop))(cpunode);
- break;
- };
- restore_current();
- spin_unlock_irqrestore(&prom_lock, flags);
-
- return ret;
-}
-
-/* Make CPU with device prom-tree node 'cpunode' idle.
- * XXX Return value, anyone? XXX
- */
-int
-prom_idlecpu(int cpunode)
-{
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&prom_lock, flags);
- switch(prom_vers) {
- case PROM_V0:
- case PROM_V2:
- default:
- ret = -1;
- break;
- case PROM_V3:
- ret = (*(romvec->v3_cpuidle))(cpunode);
- break;
- };
- restore_current();
- spin_unlock_irqrestore(&prom_lock, flags);
-
- return ret;
-}
-
-/* Resume the execution of CPU with nodeid 'cpunode'.
- * XXX Come on, somebody has to know... XXX
- */
-int
-prom_restartcpu(int cpunode)
-{
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&prom_lock, flags);
- switch(prom_vers) {
- case PROM_V0:
- case PROM_V2:
- default:
- ret = -1;
- break;
- case PROM_V3:
- ret = (*(romvec->v3_cpuresume))(cpunode);
- break;
- };
+ }
restore_current();
spin_unlock_irqrestore(&prom_lock, flags);
diff --git a/arch/sparc/prom/p1275.c b/arch/sparc/prom/p1275.c
new file mode 100644
index 00000000000..e58b8172631
--- /dev/null
+++ b/arch/sparc/prom/p1275.c
@@ -0,0 +1,55 @@
+/*
+ * p1275.c: Sun IEEE 1275 PROM low level interface routines
+ *
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/string.h>
+#include <linux/spinlock.h>
+
+#include <asm/openprom.h>
+#include <asm/oplib.h>
+#include <asm/spitfire.h>
+#include <asm/pstate.h>
+#include <asm/ldc.h>
+
+struct {
+ long prom_callback; /* 0x00 */
+ void (*prom_cif_handler)(long *); /* 0x08 */
+ unsigned long prom_cif_stack; /* 0x10 */
+} p1275buf;
+
+extern void prom_world(int);
+
+extern void prom_cif_direct(unsigned long *args);
+extern void prom_cif_callback(void);
+
+/*
+ * This provides SMP safety on the p1275buf.
+ */
+DEFINE_RAW_SPINLOCK(prom_entry_lock);
+
+void p1275_cmd_direct(unsigned long *args)
+{
+ unsigned long flags;
+
+ raw_local_save_flags(flags);
+ raw_local_irq_restore((unsigned long)PIL_NMI);
+ raw_spin_lock(&prom_entry_lock);
+
+ prom_world(1);
+ prom_cif_direct(args);
+ prom_world(0);
+
+ raw_spin_unlock(&prom_entry_lock);
+ raw_local_irq_restore(flags);
+}
+
+void prom_cif_init(void *cif_handler, void *cif_stack)
+{
+ p1275buf.prom_cif_handler = (void (*)(long *))cif_handler;
+ p1275buf.prom_cif_stack = (unsigned long)cif_stack;
+}
diff --git a/arch/sparc/prom/palloc.c b/arch/sparc/prom/palloc.c
deleted file mode 100644
index 84ce8bc5447..00000000000
--- a/arch/sparc/prom/palloc.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/* $Id: palloc.c,v 1.4 1996/04/25 06:09:48 davem Exp $
- * palloc.c: Memory allocation from the Sun PROM.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-
-/* You should not call these routines after memory management
- * has been initialized in the kernel, if fact you should not
- * use these if at all possible in the kernel. They are mainly
- * to be used for a bootloader for temporary allocations which
- * it will free before jumping into the kernel it has loaded.
- *
- * Also, these routines don't work on V0 proms, only V2 and later.
- */
-
-/* Allocate a chunk of memory of size 'num_bytes' giving a suggestion
- * of virtual_hint as the preferred virtual base address of this chunk.
- * There are no guarantees that you will get the allocation, or that
- * the prom will abide by your "hint". So check your return value.
- */
-char *
-prom_alloc(char *virtual_hint, unsigned int num_bytes)
-{
- if(prom_vers == PROM_V0) return (char *) 0x0;
- if(num_bytes == 0x0) return (char *) 0x0;
- return (*(romvec->pv_v2devops.v2_dumb_mem_alloc))(virtual_hint, num_bytes);
-}
-
-/* Free a previously allocated chunk back to the prom at virtual address
- * 'vaddr' of size 'num_bytes'. NOTE: This vaddr is not the hint you
- * used for the allocation, but the virtual address the prom actually
- * returned to you. They may be have been the same, they may have not,
- * doesn't matter.
- */
-void
-prom_free(char *vaddr, unsigned int num_bytes)
-{
- if((prom_vers == PROM_V0) || (num_bytes == 0x0)) return;
- (*(romvec->pv_v2devops.v2_dumb_mem_free))(vaddr, num_bytes);
- return;
-}
diff --git a/arch/sparc/prom/printf.c b/arch/sparc/prom/printf.c
index dc8b598bedb..d9682f06b3b 100644
--- a/arch/sparc/prom/printf.c
+++ b/arch/sparc/prom/printf.c
@@ -2,10 +2,11 @@
* printf.c: Internal prom library printf facility.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
* Copyright (c) 2002 Pete Zaitcev (zaitcev@yahoo.com)
*
* We used to warn all over the code: DO NOT USE prom_printf(),
- * and yet people do. Anton's banking code was outputing banks
+ * and yet people do. Anton's banking code was outputting banks
* with prom_printf for most of the 2.4 lifetime. Since an effective
* stick is not available, we deployed a carrot: an early printk
* through PROM by means of -p boot option. This ought to fix it.
@@ -13,27 +14,49 @@
*/
#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/spinlock.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
+#define CONSOLE_WRITE_BUF_SIZE 1024
+
static char ppbuf[1024];
+static char console_write_buf[CONSOLE_WRITE_BUF_SIZE];
+static DEFINE_RAW_SPINLOCK(console_write_lock);
-void
-prom_write(const char *buf, unsigned int n)
+void notrace prom_write(const char *buf, unsigned int n)
{
- char ch;
+ unsigned int dest_len;
+ unsigned long flags;
+ char *dest;
+
+ dest = console_write_buf;
+ raw_spin_lock_irqsave(&console_write_lock, flags);
- while (n != 0) {
- --n;
- if ((ch = *buf++) == '\n')
- prom_putchar('\r');
- prom_putchar(ch);
+ dest_len = 0;
+ while (n-- != 0) {
+ char ch = *buf++;
+ if (ch == '\n') {
+ *dest++ = '\r';
+ dest_len++;
+ }
+ *dest++ = ch;
+ dest_len++;
+ if (dest_len >= CONSOLE_WRITE_BUF_SIZE - 1) {
+ prom_console_write_buf(console_write_buf, dest_len);
+ dest = console_write_buf;
+ dest_len = 0;
+ }
}
+ if (dest_len)
+ prom_console_write_buf(console_write_buf, dest_len);
+
+ raw_spin_unlock_irqrestore(&console_write_lock, flags);
}
-void
-prom_printf(char *fmt, ...)
+void notrace prom_printf(const char *fmt, ...)
{
va_list args;
int i;
diff --git a/arch/sparc/prom/ranges.c b/arch/sparc/prom/ranges.c
index a2920323c90..ad143c13bdc 100644
--- a/arch/sparc/prom/ranges.c
+++ b/arch/sparc/prom/ranges.c
@@ -1,4 +1,4 @@
-/* $Id: ranges.c,v 1.15 2001/12/19 00:29:51 davem Exp $
+/*
* ranges.c: Handle ranges in newer proms for obio/sbus.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -6,14 +6,14 @@
*/
#include <linux/init.h>
+#include <linux/module.h>
+
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/types.h>
-#include <asm/sbus.h>
-#include <asm/system.h>
-struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX];
-int num_obio_ranges;
+static struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX];
+static int num_obio_ranges;
/* Adjust register values based upon the ranges parameters. */
static void
@@ -34,7 +34,7 @@ prom_adjust_regs(struct linux_prom_registers *regp, int nregs,
}
}
-void
+static void
prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1,
struct linux_prom_ranges *ranges2, int nranges2)
{
@@ -63,10 +63,11 @@ prom_apply_obio_ranges(struct linux_prom_registers *regs, int nregs)
if(num_obio_ranges)
prom_adjust_regs(regs, nregs, promlib_obio_ranges, num_obio_ranges);
}
+EXPORT_SYMBOL(prom_apply_obio_ranges);
void __init prom_ranges_init(void)
{
- int node, obio_node;
+ phandle node, obio_node;
int success;
num_obio_ranges = 0;
@@ -85,12 +86,10 @@ void __init prom_ranges_init(void)
if(num_obio_ranges)
prom_printf("PROMLIB: obio_ranges %d\n", num_obio_ranges);
-
- return;
}
-void
-prom_apply_generic_ranges (int node, int parent, struct linux_prom_registers *regs, int nregs)
+void prom_apply_generic_ranges(phandle node, phandle parent,
+ struct linux_prom_registers *regs, int nregs)
{
int success;
int num_ranges;
diff --git a/arch/sparc/prom/segment.c b/arch/sparc/prom/segment.c
deleted file mode 100644
index 09d6460165a..00000000000
--- a/arch/sparc/prom/segment.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/* $Id: segment.c,v 1.7 2000/08/26 02:38:03 anton Exp $
- * segment.c: Prom routine to map segments in other contexts before
- * a standalone is completely mapped. This is for sun4 and
- * sun4c architectures only.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-
-extern void restore_current(void);
-
-/* Set physical segment 'segment' at virtual address 'vaddr' in
- * context 'ctx'.
- */
-void
-prom_putsegment(int ctx, unsigned long vaddr, int segment)
-{
- unsigned long flags;
- spin_lock_irqsave(&prom_lock, flags);
- (*(romvec->pv_setctxt))(ctx, (char *) vaddr, segment);
- restore_current();
- spin_unlock_irqrestore(&prom_lock, flags);
- return;
-}
diff --git a/arch/sparc/prom/sun4prom.c b/arch/sparc/prom/sun4prom.c
deleted file mode 100644
index 00390a2652a..00000000000
--- a/arch/sparc/prom/sun4prom.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 1996 The Australian National University.
- * Copyright (C) 1996 Fujitsu Laboratories Limited
- * Copyright (C) 1997 Michael A. Griffith (grif@acm.org)
- * Copyright (C) 1997 Sun Weenie (ko@ko.reno.nv.us)
- * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- *
- * fake a really simple Sun prom for the SUN4
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <asm/oplib.h>
-#include <asm/idprom.h>
-#include <asm/machines.h>
-#include <asm/sun4prom.h>
-#include <asm/asi.h>
-#include <asm/contregs.h>
-#include <linux/init.h>
-
-static struct linux_romvec sun4romvec;
-static struct idprom sun4_idprom;
-
-struct property {
- char *name;
- char *value;
- int length;
-};
-
-struct node {
- int level;
- struct property *properties;
-};
-
-struct property null_properties = { NULL, NULL, -1 };
-
-struct property root_properties[] = {
- {"device_type", "cpu", 4},
- {"idprom", (char *)&sun4_idprom, sizeof(struct idprom)},
- {NULL, NULL, -1}
-};
-
-struct node nodes[] = {
- { 0, &null_properties },
- { 0, root_properties },
- { -1,&null_properties }
-};
-
-
-static int no_nextnode(int node)
-{
- if (nodes[node].level == nodes[node+1].level)
- return node+1;
- return -1;
-}
-
-static int no_child(int node)
-{
- if (nodes[node].level == nodes[node+1].level-1)
- return node+1;
- return -1;
-}
-
-static struct property *find_property(int node,char *name)
-{
- struct property *prop = &nodes[node].properties[0];
- while (prop && prop->name) {
- if (strcmp(prop->name,name) == 0) return prop;
- prop++;
- }
- return NULL;
-}
-
-static int no_proplen(int node,char *name)
-{
- struct property *prop = find_property(node,name);
- if (prop) return prop->length;
- return -1;
-}
-
-static int no_getprop(int node,char *name,char *value)
-{
- struct property *prop = find_property(node,name);
- if (prop) {
- memcpy(value,prop->value,prop->length);
- return 1;
- }
- return -1;
-}
-
-static int no_setprop(int node,char *name,char *value,int len)
-{
- return -1;
-}
-
-static char *no_nextprop(int node,char *name)
-{
- struct property *prop = find_property(node,name);
- if (prop) return prop[1].name;
- return NULL;
-}
-
-static struct linux_nodeops sun4_nodeops = {
- no_nextnode,
- no_child,
- no_proplen,
- no_getprop,
- no_setprop,
- no_nextprop
-};
-
-static int synch_hook;
-
-struct linux_romvec * __init sun4_prom_init(void)
-{
- int i;
- unsigned char x;
- char *p;
-
- p = (char *)&sun4_idprom;
- for (i = 0; i < sizeof(sun4_idprom); i++) {
- __asm__ __volatile__ ("lduba [%1] %2, %0" : "=r" (x) :
- "r" (AC_IDPROM + i), "i" (ASI_CONTROL));
- *p++ = x;
- }
-
- memset(&sun4romvec,0,sizeof(sun4romvec));
-
- sun4_romvec = (linux_sun4_romvec *) SUN4_PROM_VECTOR;
-
- sun4romvec.pv_romvers = 40;
- sun4romvec.pv_nodeops = &sun4_nodeops;
- sun4romvec.pv_reboot = sun4_romvec->reboot;
- sun4romvec.pv_abort = sun4_romvec->abortentry;
- sun4romvec.pv_halt = sun4_romvec->exittomon;
- sun4romvec.pv_synchook = (void (**)(void))&synch_hook;
- sun4romvec.pv_setctxt = sun4_romvec->setcxsegmap;
- sun4romvec.pv_v0bootargs = sun4_romvec->bootParam;
- sun4romvec.pv_nbgetchar = sun4_romvec->mayget;
- sun4romvec.pv_nbputchar = sun4_romvec->mayput;
- sun4romvec.pv_stdin = sun4_romvec->insource;
- sun4romvec.pv_stdout = sun4_romvec->outsink;
-
- /*
- * We turn on the LEDs to let folks without monitors or
- * terminals know we booted. Nothing too fancy now. They
- * are all on, except for LED 5, which blinks. When we
- * have more time, we can teach the penguin to say "By your
- * command" or "Activating turbo boost, Michael". :-)
- */
- sun4_romvec->setLEDs(NULL);
-
- printk("PROMLIB: Old Sun4 boot PROM monitor %s, romvec version %d\n",
- sun4_romvec->monid,
- sun4_romvec->romvecversion);
-
- return &sun4romvec;
-}
diff --git a/arch/sparc/prom/tree.c b/arch/sparc/prom/tree_32.c
index 2bf03ee8cde..f30e8d038f0 100644
--- a/arch/sparc/prom/tree.c
+++ b/arch/sparc/prom/tree_32.c
@@ -1,17 +1,16 @@
-/* $Id: tree.c,v 1.26 2000/08/26 02:38:03 anton Exp $
+/*
* tree.c: Basic device tree traversal/scanning for the Linux
* prom library.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*/
-#define PROMLIB_INTERNAL
-
#include <linux/string.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/ctype.h>
+#include <linux/module.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
@@ -21,10 +20,10 @@ extern void restore_current(void);
static char promlib_buf[128];
/* Internal version of prom_getchild that does not alter return values. */
-int __prom_getchild(int node)
+static phandle __prom_getchild(phandle node)
{
unsigned long flags;
- int cnode;
+ phandle cnode;
spin_lock_irqsave(&prom_lock, flags);
cnode = prom_nodeops->no_child(node);
@@ -37,25 +36,26 @@ int __prom_getchild(int node)
/* Return the child of node 'node' or zero if no this node has no
* direct descendent.
*/
-int prom_getchild(int node)
+phandle prom_getchild(phandle node)
{
- int cnode;
+ phandle cnode;
- if (node == -1)
+ if ((s32)node == -1)
return 0;
cnode = __prom_getchild(node);
- if (cnode == 0 || cnode == -1)
+ if (cnode == 0 || (s32)cnode == -1)
return 0;
return cnode;
}
+EXPORT_SYMBOL(prom_getchild);
/* Internal version of prom_getsibling that does not alter return values. */
-int __prom_getsibling(int node)
+static phandle __prom_getsibling(phandle node)
{
unsigned long flags;
- int cnode;
+ phandle cnode;
spin_lock_irqsave(&prom_lock, flags);
cnode = prom_nodeops->no_nextnode(node);
@@ -68,24 +68,25 @@ int __prom_getsibling(int node)
/* Return the next sibling of node 'node' or zero if no more siblings
* at this level of depth in the tree.
*/
-int prom_getsibling(int node)
+phandle prom_getsibling(phandle node)
{
- int sibnode;
+ phandle sibnode;
- if (node == -1)
+ if ((s32)node == -1)
return 0;
sibnode = __prom_getsibling(node);
- if (sibnode == 0 || sibnode == -1)
+ if (sibnode == 0 || (s32)sibnode == -1)
return 0;
return sibnode;
}
+EXPORT_SYMBOL(prom_getsibling);
/* Return the length in bytes of property 'prop' at node 'node'.
* Return -1 on error.
*/
-int prom_getproplen(int node, char *prop)
+int prom_getproplen(phandle node, const char *prop)
{
int ret;
unsigned long flags;
@@ -99,12 +100,13 @@ int prom_getproplen(int node, char *prop)
spin_unlock_irqrestore(&prom_lock, flags);
return ret;
}
+EXPORT_SYMBOL(prom_getproplen);
/* Acquire a property 'prop' at node 'node' and place it in
* 'buffer' which has a size of 'bufsize'. If the acquisition
* was successful the length will be returned, else -1 is returned.
*/
-int prom_getproperty(int node, char *prop, char *buffer, int bufsize)
+int prom_getproperty(phandle node, const char *prop, char *buffer, int bufsize)
{
int plen, ret;
unsigned long flags;
@@ -119,11 +121,12 @@ int prom_getproperty(int node, char *prop, char *buffer, int bufsize)
spin_unlock_irqrestore(&prom_lock, flags);
return ret;
}
+EXPORT_SYMBOL(prom_getproperty);
/* Acquire an integer property and return its value. Returns -1
* on failure.
*/
-int prom_getint(int node, char *prop)
+int prom_getint(phandle node, char *prop)
{
static int intprop;
@@ -132,11 +135,12 @@ int prom_getint(int node, char *prop)
return -1;
}
+EXPORT_SYMBOL(prom_getint);
/* Acquire an integer property, upon error return the passed default
* integer.
*/
-int prom_getintdefault(int node, char *property, int deflt)
+int prom_getintdefault(phandle node, char *property, int deflt)
{
int retval;
@@ -145,9 +149,10 @@ int prom_getintdefault(int node, char *property, int deflt)
return retval;
}
+EXPORT_SYMBOL(prom_getintdefault);
/* Acquire a boolean property, 1=TRUE 0=FALSE. */
-int prom_getbool(int node, char *prop)
+int prom_getbool(phandle node, char *prop)
{
int retval;
@@ -155,43 +160,31 @@ int prom_getbool(int node, char *prop)
if(retval == -1) return 0;
return 1;
}
+EXPORT_SYMBOL(prom_getbool);
/* Acquire a property whose value is a string, returns a null
* string on error. The char pointer is the user supplied string
* buffer.
*/
-void prom_getstring(int node, char *prop, char *user_buf, int ubuf_size)
+void prom_getstring(phandle node, char *prop, char *user_buf, int ubuf_size)
{
int len;
len = prom_getproperty(node, prop, user_buf, ubuf_size);
if(len != -1) return;
user_buf[0] = 0;
- return;
}
+EXPORT_SYMBOL(prom_getstring);
-/* Does the device at node 'node' have name 'name'?
- * YES = 1 NO = 0
- */
-int prom_nodematch(int node, char *name)
-{
- int error;
-
- static char namebuf[128];
- error = prom_getproperty(node, "name", namebuf, sizeof(namebuf));
- if (error == -1) return 0;
- if(strcmp(namebuf, name) == 0) return 1;
- return 0;
-}
-
/* Search siblings at 'node_start' for a node with name
* 'nodename'. Return node if successful, zero if not.
*/
-int prom_searchsiblings(int node_start, char *nodename)
+phandle prom_searchsiblings(phandle node_start, char *nodename)
{
- int thisnode, error;
+ phandle thisnode;
+ int error;
for(thisnode = node_start; thisnode;
thisnode=prom_getsibling(thisnode)) {
@@ -204,27 +197,10 @@ int prom_searchsiblings(int node_start, char *nodename)
return 0;
}
-
-/* Gets name in the form prom v2+ uses it (name@x,yyyyy or name (if no reg)) */
-int prom_getname (int node, char *buffer, int len)
-{
- int i;
- struct linux_prom_registers reg[PROMREG_MAX];
-
- i = prom_getproperty (node, "name", buffer, len);
- if (i <= 0) return -1;
- buffer [i] = 0;
- len -= i;
- i = prom_getproperty (node, "reg", (char *)reg, sizeof (reg));
- if (i <= 0) return 0;
- if (len < 11) return -1;
- buffer = strchr (buffer, 0);
- sprintf (buffer, "@%x,%x", reg[0].which_io, (uint)reg[0].phys_addr);
- return 0;
-}
+EXPORT_SYMBOL(prom_searchsiblings);
/* Interal version of nextprop that does not alter return values. */
-char * __prom_nextprop(int node, char * oprop)
+static char *__prom_nextprop(phandle node, char * oprop)
{
unsigned long flags;
char *prop;
@@ -237,33 +213,24 @@ char * __prom_nextprop(int node, char * oprop)
return prop;
}
-/* Return the first property name for node 'node'. */
-/* buffer is unused argument, but as v9 uses it, we need to have the same interface */
-char * prom_firstprop(int node, char *bufer)
-{
- if (node == 0 || node == -1)
- return "";
-
- return __prom_nextprop(node, "");
-}
-
/* Return the property type string after property type 'oprop'
* at node 'node' . Returns empty string if no more
* property types for this node.
*/
-char * prom_nextprop(int node, char *oprop, char *buffer)
+char *prom_nextprop(phandle node, char *oprop, char *buffer)
{
- if (node == 0 || node == -1)
+ if (node == 0 || (s32)node == -1)
return "";
return __prom_nextprop(node, oprop);
}
+EXPORT_SYMBOL(prom_nextprop);
-int prom_finddevice(char *name)
+phandle prom_finddevice(char *name)
{
char nbuf[128];
char *s = name, *d;
- int node = prom_root_node, node2;
+ phandle node = prom_root_node, node2;
unsigned int which_io, phys_addr;
struct linux_prom_registers reg[PROMREG_MAX];
@@ -286,7 +253,7 @@ int prom_finddevice(char *name)
if (d != s + 3 && (!*d || *d == '/')
&& d <= s + 3 + 8) {
node2 = node;
- while (node2 && node2 != -1) {
+ while (node2 && (s32)node2 != -1) {
if (prom_getproperty (node2, "reg", (char *)reg, sizeof (reg)) > 0) {
if (which_io == reg[0].which_io && phys_addr == reg[0].phys_addr) {
node = node2;
@@ -294,7 +261,7 @@ int prom_finddevice(char *name)
}
}
node2 = prom_getsibling(node2);
- if (!node2 || node2 == -1)
+ if (!node2 || (s32)node2 == -1)
break;
node2 = prom_searchsiblings(prom_getsibling(node2), nbuf);
}
@@ -305,60 +272,38 @@ int prom_finddevice(char *name)
}
return node;
}
-
-int prom_node_has_property(int node, char *prop)
-{
- char *current_property = "";
-
- do {
- current_property = prom_nextprop(node, current_property, NULL);
- if(!strcmp(current_property, prop))
- return 1;
- } while (*current_property);
- return 0;
-}
+EXPORT_SYMBOL(prom_finddevice);
/* Set property 'pname' at node 'node' to value 'value' which has a length
* of 'size' bytes. Return the number of bytes the prom accepted.
*/
-int prom_setprop(int node, char *pname, char *value, int size)
+int prom_setprop(phandle node, const char *pname, char *value, int size)
{
unsigned long flags;
int ret;
- if(size == 0) return 0;
- if((pname == 0) || (value == 0)) return 0;
+ if (size == 0)
+ return 0;
+ if ((pname == NULL) || (value == NULL))
+ return 0;
spin_lock_irqsave(&prom_lock, flags);
ret = prom_nodeops->no_setprop(node, pname, value, size);
restore_current();
spin_unlock_irqrestore(&prom_lock, flags);
return ret;
}
+EXPORT_SYMBOL(prom_setprop);
-int prom_inst2pkg(int inst)
+phandle prom_inst2pkg(int inst)
{
- int node;
+ phandle node;
unsigned long flags;
spin_lock_irqsave(&prom_lock, flags);
node = (*romvec->pv_v2devops.v2_inst2pkg)(inst);
restore_current();
spin_unlock_irqrestore(&prom_lock, flags);
- if (node == -1) return 0;
- return node;
-}
-
-/* Return 'node' assigned to a particular prom 'path'
- * FIXME: Should work for v0 as well
- */
-int prom_pathtoinode(char *path)
-{
- int node, inst;
-
- inst = prom_devopen (path);
- if (inst == -1) return 0;
- node = prom_inst2pkg (inst);
- prom_devclose (inst);
- if (node == -1) return 0;
+ if ((s32)node == -1)
+ return 0;
return node;
}
diff --git a/arch/sparc/prom/tree_64.c b/arch/sparc/prom/tree_64.c
new file mode 100644
index 00000000000..bd1b2a3ac34
--- /dev/null
+++ b/arch/sparc/prom/tree_64.c
@@ -0,0 +1,392 @@
+/*
+ * tree.c: Basic device tree traversal/scanning for the Linux
+ * prom library.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+
+#include <asm/openprom.h>
+#include <asm/oplib.h>
+#include <asm/ldc.h>
+
+static phandle prom_node_to_node(const char *type, phandle node)
+{
+ unsigned long args[5];
+
+ args[0] = (unsigned long) type;
+ args[1] = 1;
+ args[2] = 1;
+ args[3] = (unsigned int) node;
+ args[4] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ return (phandle) args[4];
+}
+
+/* Return the child of node 'node' or zero if no this node has no
+ * direct descendent.
+ */
+inline phandle __prom_getchild(phandle node)
+{
+ return prom_node_to_node("child", node);
+}
+
+phandle prom_getchild(phandle node)
+{
+ phandle cnode;
+
+ if ((s32)node == -1)
+ return 0;
+ cnode = __prom_getchild(node);
+ if ((s32)cnode == -1)
+ return 0;
+ return cnode;
+}
+EXPORT_SYMBOL(prom_getchild);
+
+inline phandle prom_getparent(phandle node)
+{
+ phandle cnode;
+
+ if ((s32)node == -1)
+ return 0;
+ cnode = prom_node_to_node("parent", node);
+ if ((s32)cnode == -1)
+ return 0;
+ return cnode;
+}
+
+/* Return the next sibling of node 'node' or zero if no more siblings
+ * at this level of depth in the tree.
+ */
+inline phandle __prom_getsibling(phandle node)
+{
+ return prom_node_to_node(prom_peer_name, node);
+}
+
+phandle prom_getsibling(phandle node)
+{
+ phandle sibnode;
+
+ if ((s32)node == -1)
+ return 0;
+ sibnode = __prom_getsibling(node);
+ if ((s32)sibnode == -1)
+ return 0;
+
+ return sibnode;
+}
+EXPORT_SYMBOL(prom_getsibling);
+
+/* Return the length in bytes of property 'prop' at node 'node'.
+ * Return -1 on error.
+ */
+int prom_getproplen(phandle node, const char *prop)
+{
+ unsigned long args[6];
+
+ if (!node || !prop)
+ return -1;
+
+ args[0] = (unsigned long) "getproplen";
+ args[1] = 2;
+ args[2] = 1;
+ args[3] = (unsigned int) node;
+ args[4] = (unsigned long) prop;
+ args[5] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ return (int) args[5];
+}
+EXPORT_SYMBOL(prom_getproplen);
+
+/* Acquire a property 'prop' at node 'node' and place it in
+ * 'buffer' which has a size of 'bufsize'. If the acquisition
+ * was successful the length will be returned, else -1 is returned.
+ */
+int prom_getproperty(phandle node, const char *prop,
+ char *buffer, int bufsize)
+{
+ unsigned long args[8];
+ int plen;
+
+ plen = prom_getproplen(node, prop);
+ if ((plen > bufsize) || (plen == 0) || (plen == -1))
+ return -1;
+
+ args[0] = (unsigned long) prom_getprop_name;
+ args[1] = 4;
+ args[2] = 1;
+ args[3] = (unsigned int) node;
+ args[4] = (unsigned long) prop;
+ args[5] = (unsigned long) buffer;
+ args[6] = bufsize;
+ args[7] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ return (int) args[7];
+}
+EXPORT_SYMBOL(prom_getproperty);
+
+/* Acquire an integer property and return its value. Returns -1
+ * on failure.
+ */
+int prom_getint(phandle node, const char *prop)
+{
+ int intprop;
+
+ if (prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1)
+ return intprop;
+
+ return -1;
+}
+EXPORT_SYMBOL(prom_getint);
+
+/* Acquire an integer property, upon error return the passed default
+ * integer.
+ */
+
+int prom_getintdefault(phandle node, const char *property, int deflt)
+{
+ int retval;
+
+ retval = prom_getint(node, property);
+ if (retval == -1)
+ return deflt;
+
+ return retval;
+}
+EXPORT_SYMBOL(prom_getintdefault);
+
+/* Acquire a boolean property, 1=TRUE 0=FALSE. */
+int prom_getbool(phandle node, const char *prop)
+{
+ int retval;
+
+ retval = prom_getproplen(node, prop);
+ if (retval == -1)
+ return 0;
+ return 1;
+}
+EXPORT_SYMBOL(prom_getbool);
+
+/* Acquire a property whose value is a string, returns a null
+ * string on error. The char pointer is the user supplied string
+ * buffer.
+ */
+void prom_getstring(phandle node, const char *prop, char *user_buf,
+ int ubuf_size)
+{
+ int len;
+
+ len = prom_getproperty(node, prop, user_buf, ubuf_size);
+ if (len != -1)
+ return;
+ user_buf[0] = 0;
+}
+EXPORT_SYMBOL(prom_getstring);
+
+/* Does the device at node 'node' have name 'name'?
+ * YES = 1 NO = 0
+ */
+int prom_nodematch(phandle node, const char *name)
+{
+ char namebuf[128];
+ prom_getproperty(node, "name", namebuf, sizeof(namebuf));
+ if (strcmp(namebuf, name) == 0)
+ return 1;
+ return 0;
+}
+
+/* Search siblings at 'node_start' for a node with name
+ * 'nodename'. Return node if successful, zero if not.
+ */
+phandle prom_searchsiblings(phandle node_start, const char *nodename)
+{
+ phandle thisnode;
+ int error;
+ char promlib_buf[128];
+
+ for(thisnode = node_start; thisnode;
+ thisnode=prom_getsibling(thisnode)) {
+ error = prom_getproperty(thisnode, "name", promlib_buf,
+ sizeof(promlib_buf));
+ /* Should this ever happen? */
+ if(error == -1) continue;
+ if(strcmp(nodename, promlib_buf)==0) return thisnode;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(prom_searchsiblings);
+
+static const char *prom_nextprop_name = "nextprop";
+
+/* Return the first property type for node 'node'.
+ * buffer should be at least 32B in length
+ */
+char *prom_firstprop(phandle node, char *buffer)
+{
+ unsigned long args[7];
+
+ *buffer = 0;
+ if ((s32)node == -1)
+ return buffer;
+
+ args[0] = (unsigned long) prom_nextprop_name;
+ args[1] = 3;
+ args[2] = 1;
+ args[3] = (unsigned int) node;
+ args[4] = 0;
+ args[5] = (unsigned long) buffer;
+ args[6] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ return buffer;
+}
+EXPORT_SYMBOL(prom_firstprop);
+
+/* Return the property type string after property type 'oprop'
+ * at node 'node' . Returns NULL string if no more
+ * property types for this node.
+ */
+char *prom_nextprop(phandle node, const char *oprop, char *buffer)
+{
+ unsigned long args[7];
+ char buf[32];
+
+ if ((s32)node == -1) {
+ *buffer = 0;
+ return buffer;
+ }
+ if (oprop == buffer) {
+ strcpy (buf, oprop);
+ oprop = buf;
+ }
+
+ args[0] = (unsigned long) prom_nextprop_name;
+ args[1] = 3;
+ args[2] = 1;
+ args[3] = (unsigned int) node;
+ args[4] = (unsigned long) oprop;
+ args[5] = (unsigned long) buffer;
+ args[6] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ return buffer;
+}
+EXPORT_SYMBOL(prom_nextprop);
+
+phandle prom_finddevice(const char *name)
+{
+ unsigned long args[5];
+
+ if (!name)
+ return 0;
+ args[0] = (unsigned long) "finddevice";
+ args[1] = 1;
+ args[2] = 1;
+ args[3] = (unsigned long) name;
+ args[4] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ return (int) args[4];
+}
+EXPORT_SYMBOL(prom_finddevice);
+
+int prom_node_has_property(phandle node, const char *prop)
+{
+ char buf [32];
+
+ *buf = 0;
+ do {
+ prom_nextprop(node, buf, buf);
+ if (!strcmp(buf, prop))
+ return 1;
+ } while (*buf);
+ return 0;
+}
+EXPORT_SYMBOL(prom_node_has_property);
+
+/* Set property 'pname' at node 'node' to value 'value' which has a length
+ * of 'size' bytes. Return the number of bytes the prom accepted.
+ */
+int
+prom_setprop(phandle node, const char *pname, char *value, int size)
+{
+ unsigned long args[8];
+
+ if (size == 0)
+ return 0;
+ if ((pname == 0) || (value == 0))
+ return 0;
+
+#ifdef CONFIG_SUN_LDOMS
+ if (ldom_domaining_enabled) {
+ ldom_set_var(pname, value);
+ return 0;
+ }
+#endif
+ args[0] = (unsigned long) "setprop";
+ args[1] = 4;
+ args[2] = 1;
+ args[3] = (unsigned int) node;
+ args[4] = (unsigned long) pname;
+ args[5] = (unsigned long) value;
+ args[6] = size;
+ args[7] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ return (int) args[7];
+}
+EXPORT_SYMBOL(prom_setprop);
+
+inline phandle prom_inst2pkg(int inst)
+{
+ unsigned long args[5];
+ phandle node;
+
+ args[0] = (unsigned long) "instance-to-package";
+ args[1] = 1;
+ args[2] = 1;
+ args[3] = (unsigned int) inst;
+ args[4] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ node = (int) args[4];
+ if ((s32)node == -1)
+ return 0;
+ return node;
+}
+
+int prom_ihandle2path(int handle, char *buffer, int bufsize)
+{
+ unsigned long args[7];
+
+ args[0] = (unsigned long) "instance-to-path";
+ args[1] = 3;
+ args[2] = 1;
+ args[3] = (unsigned int) handle;
+ args[4] = (unsigned long) buffer;
+ args[5] = bufsize;
+ args[6] = (unsigned long) -1;
+
+ p1275_cmd_direct(args);
+
+ return (int) args[6];
+}