core-$(CONFIG_SPARC64) += arch/sparc64/kernel/
core-y += arch/sparc/mm/ arch/sparc/math-emu/
-libs-$(CONFIG_SPARC32) += arch/sparc/prom/
+libs-y += arch/sparc/prom/
libs-$(CONFIG_SPARC32) += arch/sparc/lib/
-libs-$(CONFIG_SPARC64) += arch/sparc64/prom/
libs-$(CONFIG_SPARC64) += arch/sparc64/lib/
drivers-$(CONFIG_OPROFILE) += arch/sparc/oprofile/
# Makefile for the Sun Boot PROM interface library under
# Linux.
#
+asflags := -ansi
+ccflags := -Werror
lib-y := bootstr_$(BITS).o
lib-$(CONFIG_SPARC32) += devmap.o
lib-y += console_$(BITS).o
lib-y += printf_$(BITS).o
lib-y += tree_$(BITS).o
+lib-$(CONFIG_SPARC64) += p1275.o
+lib-$(CONFIG_SPARC64) += cif.o
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/* 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_interface
+prom_cif_interface:
+ sethi %hi(p1275buf), %o0
+ or %o0, %lo(p1275buf), %o0
+ ldx [%o0 + 0x010], %o1 ! prom_cif_stack
+ save %o1, -192, %sp
+ ldx [%i0 + 0x008], %l2 ! prom_cif_handler
+ mov %g4, %l0
+ mov %g5, %l1
+ mov %g6, %l3
+ call %l2
+ add %i0, 0x018, %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
+
--- /dev/null
+/* 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 <asm/system.h>
+#include <linux/string.h>
+
+extern int prom_stdin, prom_stdout;
+
+/* Non blocking get character from console input device, returns -1
+ * if no input was taken. This can be used for polling.
+ */
+inline int
+prom_nbgetchar(void)
+{
+ char inc;
+
+ if (p1275_cmd("read", P1275_ARG(1,P1275_ARG_OUT_BUF)|
+ P1275_INOUT(3,1),
+ prom_stdin, &inc, P1275_SIZE(1)) == 1)
+ return inc;
+ else
+ return -1;
+}
+
+/* Non blocking put character to console device, returns -1 if
+ * unsuccessful.
+ */
+inline int
+prom_nbputchar(char c)
+{
+ char outc;
+
+ outc = c;
+ if (p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
+ P1275_INOUT(3,1),
+ prom_stdout, &outc, P1275_SIZE(1)) == 1)
+ return 0;
+ else
+ return -1;
+}
+
+/* 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)
+{
+ prom_nbputchar(c);
+ return;
+}
+
+void
+prom_puts(const char *s, int len)
+{
+ p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
+ P1275_INOUT(3,1),
+ prom_stdout, s, P1275_SIZE(len));
+}
--- /dev/null
+/*
+ * devops.c: Device operations using the PROM.
+ *
+ * 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 <asm/openprom.h>
+#include <asm/oplib.h>
+
+/* Open the device described by the string 'dstr'. Returns the handle
+ * to that device used for subsequent operations on that device.
+ * Returns 0 on failure.
+ */
+int
+prom_devopen(const char *dstr)
+{
+ return p1275_cmd ("open", P1275_ARG(0,P1275_ARG_IN_STRING)|
+ P1275_INOUT(1,1),
+ dstr);
+}
+
+/* Close the device described by device handle 'dhandle'. */
+int
+prom_devclose(int dhandle)
+{
+ p1275_cmd ("close", P1275_INOUT(1,0), dhandle);
+ 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)
+{
+ p1275_cmd ("seek", P1275_INOUT(3,1), dhandle, seekhi, seeklo);
+}
--- /dev/null
+/*
+ * 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_stdin, prom_stdout;
+int prom_chosen_node;
+
+/* 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.
+ */
+
+extern void prom_cif_init(void *, void *);
+
+void __init prom_init(void *cif_handler, void *cif_stack)
+{
+ int node;
+
+ prom_cif_init(cif_handler, cif_stack);
+
+ prom_chosen_node = prom_finddevice(prom_chosen_path);
+ if (!prom_chosen_node || prom_chosen_node == -1)
+ prom_halt();
+
+ prom_stdin = prom_getint(prom_chosen_node, "stdin");
+ prom_stdout = prom_getint(prom_chosen_node, "stdout");
+
+ node = prom_finddevice("/openprom");
+ if (!node || 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);
+}
--- /dev/null
+/*
+ * 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 <asm/openprom.h>
+#include <asm/oplib.h>
+#include <asm/system.h>
+#include <asm/ldc.h>
+
+int prom_service_exists(const char *service_name)
+{
+ int err = p1275_cmd("test", P1275_ARG(0, P1275_ARG_IN_STRING) |
+ P1275_INOUT(1, 1), service_name);
+
+ if (err)
+ return 0;
+ return 1;
+}
+
+void prom_sun4v_guest_soft_state(void)
+{
+ const char *svc = "SUNW,soft-state-supported";
+
+ if (!prom_service_exists(svc))
+ return;
+ p1275_cmd(svc, P1275_INOUT(0, 0));
+}
+
+/* Reset and reboot the machine with the command 'bcommand'. */
+void prom_reboot(const char *bcommand)
+{
+#ifdef CONFIG_SUN_LDOMS
+ if (ldom_domaining_enabled)
+ ldom_reboot(bcommand);
+#endif
+ p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) |
+ P1275_INOUT(1, 0), bcommand);
+}
+
+/* Forth evaluate the expression contained in 'fstring'. */
+void prom_feval(const char *fstring)
+{
+ if (!fstring || fstring[0] == 0)
+ return;
+ p1275_cmd("interpret", P1275_ARG(0, P1275_ARG_IN_STRING) |
+ P1275_INOUT(1, 1), fstring);
+}
+
+#ifdef CONFIG_SMP
+extern void smp_capture(void);
+extern void smp_release(void);
+#endif
+
+/* Drop into the prom, with the chance to continue with the 'go'
+ * prom command.
+ */
+void prom_cmdline(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+#ifdef CONFIG_SMP
+ smp_capture();
+#endif
+
+ p1275_cmd("enter", P1275_INOUT(0, 0));
+
+#ifdef CONFIG_SMP
+ smp_release();
+#endif
+
+ local_irq_restore(flags);
+}
+
+/* Drop into the prom, but completely terminate the program.
+ * No chance of continuing.
+ */
+void prom_halt(void)
+{
+#ifdef CONFIG_SUN_LDOMS
+ if (ldom_domaining_enabled)
+ ldom_power_off();
+#endif
+again:
+ p1275_cmd("exit", P1275_INOUT(0, 0));
+ goto again; /* PROM is out to get me -DaveM */
+}
+
+void prom_halt_power_off(void)
+{
+#ifdef CONFIG_SUN_LDOMS
+ if (ldom_domaining_enabled)
+ ldom_power_off();
+#endif
+ p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0));
+
+ /* if nothing else helps, we just halt */
+ prom_halt();
+}
+
+/* Set prom sync handler to call function 'funcp'. */
+void prom_setcallback(callback_func_t funcp)
+{
+ if (!funcp)
+ return;
+ p1275_cmd("set-callback", P1275_ARG(0, P1275_ARG_IN_FUNCTION) |
+ P1275_INOUT(1, 1), funcp);
+}
+
+/* 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)
+{
+ int node, 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;
+ int node, 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. */
+long prom_itlb_load(unsigned long index,
+ unsigned long tte_data,
+ unsigned long vaddr)
+{
+ return p1275_cmd(prom_callmethod_name,
+ (P1275_ARG(0, P1275_ARG_IN_STRING) |
+ P1275_ARG(2, P1275_ARG_IN_64B) |
+ P1275_ARG(3, P1275_ARG_IN_64B) |
+ P1275_INOUT(5, 1)),
+ "SUNW,itlb-load",
+ prom_get_mmu_ihandle(),
+ /* And then our actual args are pushed backwards. */
+ vaddr,
+ tte_data,
+ index);
+}
+
+long prom_dtlb_load(unsigned long index,
+ unsigned long tte_data,
+ unsigned long vaddr)
+{
+ return p1275_cmd(prom_callmethod_name,
+ (P1275_ARG(0, P1275_ARG_IN_STRING) |
+ P1275_ARG(2, P1275_ARG_IN_64B) |
+ P1275_ARG(3, P1275_ARG_IN_64B) |
+ P1275_INOUT(5, 1)),
+ "SUNW,dtlb-load",
+ prom_get_mmu_ihandle(),
+ /* And then our actual args are pushed backwards. */
+ vaddr,
+ tte_data,
+ index);
+}
+
+int prom_map(int mode, unsigned long size,
+ unsigned long vaddr, unsigned long paddr)
+{
+ int ret = p1275_cmd(prom_callmethod_name,
+ (P1275_ARG(0, P1275_ARG_IN_STRING) |
+ P1275_ARG(3, P1275_ARG_IN_64B) |
+ P1275_ARG(4, P1275_ARG_IN_64B) |
+ P1275_ARG(6, P1275_ARG_IN_64B) |
+ P1275_INOUT(7, 1)),
+ prom_map_name,
+ prom_get_mmu_ihandle(),
+ mode,
+ size,
+ vaddr,
+ 0,
+ paddr);
+
+ if (ret == 0)
+ ret = -1;
+ return ret;
+}
+
+void prom_unmap(unsigned long size, unsigned long vaddr)
+{
+ p1275_cmd(prom_callmethod_name,
+ (P1275_ARG(0, P1275_ARG_IN_STRING) |
+ P1275_ARG(2, P1275_ARG_IN_64B) |
+ P1275_ARG(3, P1275_ARG_IN_64B) |
+ P1275_INOUT(4, 0)),
+ prom_unmap_name,
+ prom_get_mmu_ihandle(),
+ size,
+ vaddr);
+}
+
+/* Set aside physical memory which is not touched or modified
+ * across soft resets.
+ */
+unsigned long prom_retain(const char *name,
+ unsigned long pa_low, unsigned long pa_high,
+ long size, long align)
+{
+ /* XXX I don't think we return multiple values correctly.
+ * XXX OBP supposedly returns pa_low/pa_high here, how does
+ * XXX it work?
+ */
+
+ /* If align is zero, the pa_low/pa_high args are passed,
+ * else they are not.
+ */
+ if (align == 0)
+ return p1275_cmd("SUNW,retain",
+ (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 2)),
+ name, pa_low, pa_high, size, align);
+ else
+ return p1275_cmd("SUNW,retain",
+ (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(3, 2)),
+ name, size, align);
+}
+
+/* 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)
+{
+ return p1275_cmd(prom_callmethod_name,
+ (P1275_ARG(0, P1275_ARG_IN_STRING) |
+ P1275_ARG(3, P1275_ARG_OUT_BUF) |
+ P1275_ARG(6, P1275_ARG_IN_64B) |
+ P1275_INOUT(8, 2)),
+ "SUNW,get-unumber", prom_get_memory_ihandle(),
+ buflen, buf, P1275_SIZE(buflen),
+ 0, phys_addr, syndrome_code);
+}
+
+/* Power management extensions. */
+void prom_sleepself(void)
+{
+ p1275_cmd("SUNW,sleep-self", P1275_INOUT(0, 0));
+}
+
+int prom_sleepsystem(void)
+{
+ return p1275_cmd("SUNW,sleep-system", P1275_INOUT(0, 1));
+}
+
+int prom_wakeupsystem(void)
+{
+ return p1275_cmd("SUNW,wakeup-system", P1275_INOUT(0, 1));
+}
+
+#ifdef CONFIG_SMP
+void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg)
+{
+ p1275_cmd("SUNW,start-cpu", P1275_INOUT(3, 0), cpunode, pc, arg);
+}
+
+void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg)
+{
+ p1275_cmd("SUNW,start-cpu-by-cpuid", P1275_INOUT(3, 0),
+ cpuid, pc, arg);
+}
+
+void prom_stopcpu_cpuid(int cpuid)
+{
+ p1275_cmd("SUNW,stop-cpu-by-cpuid", P1275_INOUT(1, 0),
+ cpuid);
+}
+
+void prom_stopself(void)
+{
+ p1275_cmd("SUNW,stop-self", P1275_INOUT(0, 0));
+}
+
+void prom_idleself(void)
+{
+ p1275_cmd("SUNW,idle-self", P1275_INOUT(0, 0));
+}
+
+void prom_resumecpu(int cpunode)
+{
+ p1275_cmd("SUNW,resume-cpu", P1275_INOUT(1, 0), cpunode);
+}
+#endif
--- /dev/null
+/*
+ * 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/init.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/system.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 */
+ unsigned long prom_args [23]; /* 0x18 */
+ char prom_buffer [3000];
+} p1275buf;
+
+extern void prom_world(int);
+
+extern void prom_cif_interface(void);
+extern void prom_cif_callback(void);
+
+/*
+ * This provides SMP safety on the p1275buf. prom_callback() drops this lock
+ * to allow recursuve acquisition.
+ */
+DEFINE_SPINLOCK(prom_entry_lock);
+
+long p1275_cmd(const char *service, long fmt, ...)
+{
+ char *p, *q;
+ unsigned long flags;
+ int nargs, nrets, i;
+ va_list list;
+ long attrs, x;
+
+ p = p1275buf.prom_buffer;
+
+ spin_lock_irqsave(&prom_entry_lock, flags);
+
+ p1275buf.prom_args[0] = (unsigned long)p; /* service */
+ strcpy (p, service);
+ p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
+ p1275buf.prom_args[1] = nargs = (fmt & 0x0f); /* nargs */
+ p1275buf.prom_args[2] = nrets = ((fmt & 0xf0) >> 4); /* nrets */
+ attrs = fmt >> 8;
+ va_start(list, fmt);
+ for (i = 0; i < nargs; i++, attrs >>= 3) {
+ switch (attrs & 0x7) {
+ case P1275_ARG_NUMBER:
+ p1275buf.prom_args[i + 3] =
+ (unsigned)va_arg(list, long);
+ break;
+ case P1275_ARG_IN_64B:
+ p1275buf.prom_args[i + 3] =
+ va_arg(list, unsigned long);
+ break;
+ case P1275_ARG_IN_STRING:
+ strcpy (p, va_arg(list, char *));
+ p1275buf.prom_args[i + 3] = (unsigned long)p;
+ p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
+ break;
+ case P1275_ARG_OUT_BUF:
+ (void) va_arg(list, char *);
+ p1275buf.prom_args[i + 3] = (unsigned long)p;
+ x = va_arg(list, long);
+ i++; attrs >>= 3;
+ p = (char *)(((long)(p + (int)x + 7)) & ~7);
+ p1275buf.prom_args[i + 3] = x;
+ break;
+ case P1275_ARG_IN_BUF:
+ q = va_arg(list, char *);
+ p1275buf.prom_args[i + 3] = (unsigned long)p;
+ x = va_arg(list, long);
+ i++; attrs >>= 3;
+ memcpy (p, q, (int)x);
+ p = (char *)(((long)(p + (int)x + 7)) & ~7);
+ p1275buf.prom_args[i + 3] = x;
+ break;
+ case P1275_ARG_OUT_32B:
+ (void) va_arg(list, char *);
+ p1275buf.prom_args[i + 3] = (unsigned long)p;
+ p += 32;
+ break;
+ case P1275_ARG_IN_FUNCTION:
+ p1275buf.prom_args[i + 3] =
+ (unsigned long)prom_cif_callback;
+ p1275buf.prom_callback = va_arg(list, long);
+ break;
+ }
+ }
+ va_end(list);
+
+ prom_world(1);
+ prom_cif_interface();
+ prom_world(0);
+
+ attrs = fmt >> 8;
+ va_start(list, fmt);
+ for (i = 0; i < nargs; i++, attrs >>= 3) {
+ switch (attrs & 0x7) {
+ case P1275_ARG_NUMBER:
+ (void) va_arg(list, long);
+ break;
+ case P1275_ARG_IN_STRING:
+ (void) va_arg(list, char *);
+ break;
+ case P1275_ARG_IN_FUNCTION:
+ (void) va_arg(list, long);
+ break;
+ case P1275_ARG_IN_BUF:
+ (void) va_arg(list, char *);
+ (void) va_arg(list, long);
+ i++; attrs >>= 3;
+ break;
+ case P1275_ARG_OUT_BUF:
+ p = va_arg(list, char *);
+ x = va_arg(list, long);
+ memcpy (p, (char *)(p1275buf.prom_args[i + 3]), (int)x);
+ i++; attrs >>= 3;
+ break;
+ case P1275_ARG_OUT_32B:
+ p = va_arg(list, char *);
+ memcpy (p, (char *)(p1275buf.prom_args[i + 3]), 32);
+ break;
+ }
+ }
+ va_end(list);
+ x = p1275buf.prom_args [nargs + 3];
+
+ spin_unlock_irqrestore(&prom_entry_lock, flags);
+
+ return x;
+}
+
+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;
+}
--- /dev/null
+/*
+ * 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 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.
+ * USE printk; if you need, deploy -p.
+ */
+
+#include <linux/kernel.h>
+
+#include <asm/openprom.h>
+#include <asm/oplib.h>
+
+static char ppbuf[1024];
+
+void
+prom_write(const char *buf, unsigned int n)
+{
+ char ch;
+
+ while (n != 0) {
+ --n;
+ if ((ch = *buf++) == '\n')
+ prom_putchar('\r');
+ prom_putchar(ch);
+ }
+}
+
+void
+prom_printf(const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vscnprintf(ppbuf, sizeof(ppbuf), fmt, args);
+ va_end(args);
+
+ prom_write(ppbuf, i);
+}
--- /dev/null
+/*
+ * 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 <asm/openprom.h>
+#include <asm/oplib.h>
+#include <asm/ldc.h>
+
+/* Return the child of node 'node' or zero if no this node has no
+ * direct descendent.
+ */
+inline int __prom_getchild(int node)
+{
+ return p1275_cmd ("child", P1275_INOUT(1, 1), node);
+}
+
+inline int prom_getchild(int node)
+{
+ int cnode;
+
+ if(node == -1) return 0;
+ cnode = __prom_getchild(node);
+ if(cnode == -1) return 0;
+ return (int)cnode;
+}
+
+inline int prom_getparent(int node)
+{
+ int cnode;
+
+ if(node == -1) return 0;
+ cnode = p1275_cmd ("parent", P1275_INOUT(1, 1), node);
+ if(cnode == -1) return 0;
+ return (int)cnode;
+}
+
+/* Return the next sibling of node 'node' or zero if no more siblings
+ * at this level of depth in the tree.
+ */
+inline int __prom_getsibling(int node)
+{
+ return p1275_cmd(prom_peer_name, P1275_INOUT(1, 1), node);
+}
+
+inline int prom_getsibling(int node)
+{
+ int sibnode;
+
+ if (node == -1)
+ return 0;
+ sibnode = __prom_getsibling(node);
+ if (sibnode == -1)
+ return 0;
+
+ return sibnode;
+}
+
+/* Return the length in bytes of property 'prop' at node 'node'.
+ * Return -1 on error.
+ */
+inline int prom_getproplen(int node, const char *prop)
+{
+ if((!node) || (!prop)) return -1;
+ return p1275_cmd ("getproplen",
+ P1275_ARG(1,P1275_ARG_IN_STRING)|
+ P1275_INOUT(2, 1),
+ node, prop);
+}
+
+/* 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.
+ */
+inline int prom_getproperty(int node, const char *prop,
+ char *buffer, int bufsize)
+{
+ int plen;
+
+ plen = prom_getproplen(node, prop);
+ if ((plen > bufsize) || (plen == 0) || (plen == -1)) {
+ return -1;
+ } else {
+ /* Ok, things seem all right. */
+ return p1275_cmd(prom_getprop_name,
+ P1275_ARG(1,P1275_ARG_IN_STRING)|
+ P1275_ARG(2,P1275_ARG_OUT_BUF)|
+ P1275_INOUT(4, 1),
+ node, prop, buffer, P1275_SIZE(plen));
+ }
+}
+
+/* Acquire an integer property and return its value. Returns -1
+ * on failure.
+ */
+inline int prom_getint(int node, const char *prop)
+{
+ int intprop;
+
+ if(prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1)
+ return intprop;
+
+ return -1;
+}
+
+/* Acquire an integer property, upon error return the passed default
+ * integer.
+ */
+
+int prom_getintdefault(int node, const char *property, int deflt)
+{
+ int retval;
+
+ retval = prom_getint(node, property);
+ if(retval == -1) return deflt;
+
+ return retval;
+}
+
+/* Acquire a boolean property, 1=TRUE 0=FALSE. */
+int prom_getbool(int node, const char *prop)
+{
+ int retval;
+
+ retval = prom_getproplen(node, prop);
+ if(retval == -1) return 0;
+ return 1;
+}
+
+/* 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, 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;
+ return;
+}
+
+
+/* Does the device at node 'node' have name 'name'?
+ * YES = 1 NO = 0
+ */
+int prom_nodematch(int 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.
+ */
+int prom_searchsiblings(int node_start, const char *nodename)
+{
+
+ int thisnode, 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;
+}
+
+/* Return the first property type for node 'node'.
+ * buffer should be at least 32B in length
+ */
+inline char *prom_firstprop(int node, char *buffer)
+{
+ *buffer = 0;
+ if(node == -1) return buffer;
+ p1275_cmd ("nextprop", P1275_ARG(2,P1275_ARG_OUT_32B)|
+ P1275_INOUT(3, 0),
+ node, (char *) 0x0, buffer);
+ return buffer;
+}
+
+/* Return the property type string after property type 'oprop'
+ * at node 'node' . Returns NULL string if no more
+ * property types for this node.
+ */
+inline char *prom_nextprop(int node, const char *oprop, char *buffer)
+{
+ char buf[32];
+
+ if(node == -1) {
+ *buffer = 0;
+ return buffer;
+ }
+ if (oprop == buffer) {
+ strcpy (buf, oprop);
+ oprop = buf;
+ }
+ p1275_cmd ("nextprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
+ P1275_ARG(2,P1275_ARG_OUT_32B)|
+ P1275_INOUT(3, 0),
+ node, oprop, buffer);
+ return buffer;
+}
+
+int
+prom_finddevice(const char *name)
+{
+ if (!name)
+ return 0;
+ return p1275_cmd(prom_finddev_name,
+ P1275_ARG(0,P1275_ARG_IN_STRING)|
+ P1275_INOUT(1, 1),
+ name);
+}
+
+int prom_node_has_property(int 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;
+}
+
+/* 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, const char *pname, char *value, int size)
+{
+ 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
+ return p1275_cmd ("setprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
+ P1275_ARG(2,P1275_ARG_IN_BUF)|
+ P1275_INOUT(4, 1),
+ node, pname, value, P1275_SIZE(size));
+}
+
+inline int prom_inst2pkg(int inst)
+{
+ int node;
+
+ node = p1275_cmd ("instance-to-package", P1275_INOUT(1, 1), inst);
+ 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(const char *path)
+{
+ int node, inst;
+
+ inst = prom_devopen (path);
+ if (inst == 0) return 0;
+ node = prom_inst2pkg (inst);
+ prom_devclose (inst);
+ if (node == -1) return 0;
+ return node;
+}
+
+int prom_ihandle2path(int handle, char *buffer, int bufsize)
+{
+ return p1275_cmd("instance-to-path",
+ P1275_ARG(1,P1275_ARG_OUT_BUF)|
+ P1275_INOUT(3, 1),
+ handle, buffer, P1275_SIZE(bufsize));
+}
+++ /dev/null
-# Makefile for the Sun Boot PROM interface library under
-# Linux.
-#
-
-EXTRA_AFLAGS := -ansi
-EXTRA_CFLAGS := -Werror
-
-lib-y := bootstr.o devops.o init.o misc.o \
- tree.o console.o printf.o p1275.o cif.o
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/* 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_interface
-prom_cif_interface:
- sethi %hi(p1275buf), %o0
- or %o0, %lo(p1275buf), %o0
- ldx [%o0 + 0x010], %o1 ! prom_cif_stack
- save %o1, -192, %sp
- ldx [%i0 + 0x008], %l2 ! prom_cif_handler
- mov %g4, %l0
- mov %g5, %l1
- mov %g6, %l3
- call %l2
- add %i0, 0x018, %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
-
+++ /dev/null
-/* 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 <asm/system.h>
-#include <linux/string.h>
-
-extern int prom_stdin, prom_stdout;
-
-/* Non blocking get character from console input device, returns -1
- * if no input was taken. This can be used for polling.
- */
-inline int
-prom_nbgetchar(void)
-{
- char inc;
-
- if (p1275_cmd("read", P1275_ARG(1,P1275_ARG_OUT_BUF)|
- P1275_INOUT(3,1),
- prom_stdin, &inc, P1275_SIZE(1)) == 1)
- return inc;
- else
- return -1;
-}
-
-/* Non blocking put character to console device, returns -1 if
- * unsuccessful.
- */
-inline int
-prom_nbputchar(char c)
-{
- char outc;
-
- outc = c;
- if (p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
- P1275_INOUT(3,1),
- prom_stdout, &outc, P1275_SIZE(1)) == 1)
- return 0;
- else
- return -1;
-}
-
-/* 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)
-{
- prom_nbputchar(c);
- return;
-}
-
-void
-prom_puts(const char *s, int len)
-{
- p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
- P1275_INOUT(3,1),
- prom_stdout, s, P1275_SIZE(len));
-}
+++ /dev/null
-/*
- * devops.c: Device operations using the PROM.
- *
- * 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 <asm/openprom.h>
-#include <asm/oplib.h>
-
-/* Open the device described by the string 'dstr'. Returns the handle
- * to that device used for subsequent operations on that device.
- * Returns 0 on failure.
- */
-int
-prom_devopen(const char *dstr)
-{
- return p1275_cmd ("open", P1275_ARG(0,P1275_ARG_IN_STRING)|
- P1275_INOUT(1,1),
- dstr);
-}
-
-/* Close the device described by device handle 'dhandle'. */
-int
-prom_devclose(int dhandle)
-{
- p1275_cmd ("close", P1275_INOUT(1,0), dhandle);
- 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)
-{
- p1275_cmd ("seek", P1275_INOUT(3,1), dhandle, seekhi, seeklo);
-}
+++ /dev/null
-/*
- * 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_stdin, prom_stdout;
-int prom_chosen_node;
-
-/* 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.
- */
-
-extern void prom_cif_init(void *, void *);
-
-void __init prom_init(void *cif_handler, void *cif_stack)
-{
- int node;
-
- prom_cif_init(cif_handler, cif_stack);
-
- prom_chosen_node = prom_finddevice(prom_chosen_path);
- if (!prom_chosen_node || prom_chosen_node == -1)
- prom_halt();
-
- prom_stdin = prom_getint(prom_chosen_node, "stdin");
- prom_stdout = prom_getint(prom_chosen_node, "stdout");
-
- node = prom_finddevice("/openprom");
- if (!node || 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);
-}
+++ /dev/null
-/*
- * 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 <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/system.h>
-#include <asm/ldc.h>
-
-int prom_service_exists(const char *service_name)
-{
- int err = p1275_cmd("test", P1275_ARG(0, P1275_ARG_IN_STRING) |
- P1275_INOUT(1, 1), service_name);
-
- if (err)
- return 0;
- return 1;
-}
-
-void prom_sun4v_guest_soft_state(void)
-{
- const char *svc = "SUNW,soft-state-supported";
-
- if (!prom_service_exists(svc))
- return;
- p1275_cmd(svc, P1275_INOUT(0, 0));
-}
-
-/* Reset and reboot the machine with the command 'bcommand'. */
-void prom_reboot(const char *bcommand)
-{
-#ifdef CONFIG_SUN_LDOMS
- if (ldom_domaining_enabled)
- ldom_reboot(bcommand);
-#endif
- p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) |
- P1275_INOUT(1, 0), bcommand);
-}
-
-/* Forth evaluate the expression contained in 'fstring'. */
-void prom_feval(const char *fstring)
-{
- if (!fstring || fstring[0] == 0)
- return;
- p1275_cmd("interpret", P1275_ARG(0, P1275_ARG_IN_STRING) |
- P1275_INOUT(1, 1), fstring);
-}
-
-#ifdef CONFIG_SMP
-extern void smp_capture(void);
-extern void smp_release(void);
-#endif
-
-/* Drop into the prom, with the chance to continue with the 'go'
- * prom command.
- */
-void prom_cmdline(void)
-{
- unsigned long flags;
-
- local_irq_save(flags);
-
-#ifdef CONFIG_SMP
- smp_capture();
-#endif
-
- p1275_cmd("enter", P1275_INOUT(0, 0));
-
-#ifdef CONFIG_SMP
- smp_release();
-#endif
-
- local_irq_restore(flags);
-}
-
-/* Drop into the prom, but completely terminate the program.
- * No chance of continuing.
- */
-void prom_halt(void)
-{
-#ifdef CONFIG_SUN_LDOMS
- if (ldom_domaining_enabled)
- ldom_power_off();
-#endif
-again:
- p1275_cmd("exit", P1275_INOUT(0, 0));
- goto again; /* PROM is out to get me -DaveM */
-}
-
-void prom_halt_power_off(void)
-{
-#ifdef CONFIG_SUN_LDOMS
- if (ldom_domaining_enabled)
- ldom_power_off();
-#endif
- p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0));
-
- /* if nothing else helps, we just halt */
- prom_halt();
-}
-
-/* Set prom sync handler to call function 'funcp'. */
-void prom_setcallback(callback_func_t funcp)
-{
- if (!funcp)
- return;
- p1275_cmd("set-callback", P1275_ARG(0, P1275_ARG_IN_FUNCTION) |
- P1275_INOUT(1, 1), funcp);
-}
-
-/* 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)
-{
- int node, 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;
- int node, 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. */
-long prom_itlb_load(unsigned long index,
- unsigned long tte_data,
- unsigned long vaddr)
-{
- return p1275_cmd(prom_callmethod_name,
- (P1275_ARG(0, P1275_ARG_IN_STRING) |
- P1275_ARG(2, P1275_ARG_IN_64B) |
- P1275_ARG(3, P1275_ARG_IN_64B) |
- P1275_INOUT(5, 1)),
- "SUNW,itlb-load",
- prom_get_mmu_ihandle(),
- /* And then our actual args are pushed backwards. */
- vaddr,
- tte_data,
- index);
-}
-
-long prom_dtlb_load(unsigned long index,
- unsigned long tte_data,
- unsigned long vaddr)
-{
- return p1275_cmd(prom_callmethod_name,
- (P1275_ARG(0, P1275_ARG_IN_STRING) |
- P1275_ARG(2, P1275_ARG_IN_64B) |
- P1275_ARG(3, P1275_ARG_IN_64B) |
- P1275_INOUT(5, 1)),
- "SUNW,dtlb-load",
- prom_get_mmu_ihandle(),
- /* And then our actual args are pushed backwards. */
- vaddr,
- tte_data,
- index);
-}
-
-int prom_map(int mode, unsigned long size,
- unsigned long vaddr, unsigned long paddr)
-{
- int ret = p1275_cmd(prom_callmethod_name,
- (P1275_ARG(0, P1275_ARG_IN_STRING) |
- P1275_ARG(3, P1275_ARG_IN_64B) |
- P1275_ARG(4, P1275_ARG_IN_64B) |
- P1275_ARG(6, P1275_ARG_IN_64B) |
- P1275_INOUT(7, 1)),
- prom_map_name,
- prom_get_mmu_ihandle(),
- mode,
- size,
- vaddr,
- 0,
- paddr);
-
- if (ret == 0)
- ret = -1;
- return ret;
-}
-
-void prom_unmap(unsigned long size, unsigned long vaddr)
-{
- p1275_cmd(prom_callmethod_name,
- (P1275_ARG(0, P1275_ARG_IN_STRING) |
- P1275_ARG(2, P1275_ARG_IN_64B) |
- P1275_ARG(3, P1275_ARG_IN_64B) |
- P1275_INOUT(4, 0)),
- prom_unmap_name,
- prom_get_mmu_ihandle(),
- size,
- vaddr);
-}
-
-/* Set aside physical memory which is not touched or modified
- * across soft resets.
- */
-unsigned long prom_retain(const char *name,
- unsigned long pa_low, unsigned long pa_high,
- long size, long align)
-{
- /* XXX I don't think we return multiple values correctly.
- * XXX OBP supposedly returns pa_low/pa_high here, how does
- * XXX it work?
- */
-
- /* If align is zero, the pa_low/pa_high args are passed,
- * else they are not.
- */
- if (align == 0)
- return p1275_cmd("SUNW,retain",
- (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 2)),
- name, pa_low, pa_high, size, align);
- else
- return p1275_cmd("SUNW,retain",
- (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(3, 2)),
- name, size, align);
-}
-
-/* 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)
-{
- return p1275_cmd(prom_callmethod_name,
- (P1275_ARG(0, P1275_ARG_IN_STRING) |
- P1275_ARG(3, P1275_ARG_OUT_BUF) |
- P1275_ARG(6, P1275_ARG_IN_64B) |
- P1275_INOUT(8, 2)),
- "SUNW,get-unumber", prom_get_memory_ihandle(),
- buflen, buf, P1275_SIZE(buflen),
- 0, phys_addr, syndrome_code);
-}
-
-/* Power management extensions. */
-void prom_sleepself(void)
-{
- p1275_cmd("SUNW,sleep-self", P1275_INOUT(0, 0));
-}
-
-int prom_sleepsystem(void)
-{
- return p1275_cmd("SUNW,sleep-system", P1275_INOUT(0, 1));
-}
-
-int prom_wakeupsystem(void)
-{
- return p1275_cmd("SUNW,wakeup-system", P1275_INOUT(0, 1));
-}
-
-#ifdef CONFIG_SMP
-void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg)
-{
- p1275_cmd("SUNW,start-cpu", P1275_INOUT(3, 0), cpunode, pc, arg);
-}
-
-void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg)
-{
- p1275_cmd("SUNW,start-cpu-by-cpuid", P1275_INOUT(3, 0),
- cpuid, pc, arg);
-}
-
-void prom_stopcpu_cpuid(int cpuid)
-{
- p1275_cmd("SUNW,stop-cpu-by-cpuid", P1275_INOUT(1, 0),
- cpuid);
-}
-
-void prom_stopself(void)
-{
- p1275_cmd("SUNW,stop-self", P1275_INOUT(0, 0));
-}
-
-void prom_idleself(void)
-{
- p1275_cmd("SUNW,idle-self", P1275_INOUT(0, 0));
-}
-
-void prom_resumecpu(int cpunode)
-{
- p1275_cmd("SUNW,resume-cpu", P1275_INOUT(1, 0), cpunode);
-}
-#endif
+++ /dev/null
-/*
- * 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/init.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/system.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 */
- unsigned long prom_args [23]; /* 0x18 */
- char prom_buffer [3000];
-} p1275buf;
-
-extern void prom_world(int);
-
-extern void prom_cif_interface(void);
-extern void prom_cif_callback(void);
-
-/*
- * This provides SMP safety on the p1275buf. prom_callback() drops this lock
- * to allow recursuve acquisition.
- */
-DEFINE_SPINLOCK(prom_entry_lock);
-
-long p1275_cmd(const char *service, long fmt, ...)
-{
- char *p, *q;
- unsigned long flags;
- int nargs, nrets, i;
- va_list list;
- long attrs, x;
-
- p = p1275buf.prom_buffer;
-
- spin_lock_irqsave(&prom_entry_lock, flags);
-
- p1275buf.prom_args[0] = (unsigned long)p; /* service */
- strcpy (p, service);
- p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
- p1275buf.prom_args[1] = nargs = (fmt & 0x0f); /* nargs */
- p1275buf.prom_args[2] = nrets = ((fmt & 0xf0) >> 4); /* nrets */
- attrs = fmt >> 8;
- va_start(list, fmt);
- for (i = 0; i < nargs; i++, attrs >>= 3) {
- switch (attrs & 0x7) {
- case P1275_ARG_NUMBER:
- p1275buf.prom_args[i + 3] =
- (unsigned)va_arg(list, long);
- break;
- case P1275_ARG_IN_64B:
- p1275buf.prom_args[i + 3] =
- va_arg(list, unsigned long);
- break;
- case P1275_ARG_IN_STRING:
- strcpy (p, va_arg(list, char *));
- p1275buf.prom_args[i + 3] = (unsigned long)p;
- p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
- break;
- case P1275_ARG_OUT_BUF:
- (void) va_arg(list, char *);
- p1275buf.prom_args[i + 3] = (unsigned long)p;
- x = va_arg(list, long);
- i++; attrs >>= 3;
- p = (char *)(((long)(p + (int)x + 7)) & ~7);
- p1275buf.prom_args[i + 3] = x;
- break;
- case P1275_ARG_IN_BUF:
- q = va_arg(list, char *);
- p1275buf.prom_args[i + 3] = (unsigned long)p;
- x = va_arg(list, long);
- i++; attrs >>= 3;
- memcpy (p, q, (int)x);
- p = (char *)(((long)(p + (int)x + 7)) & ~7);
- p1275buf.prom_args[i + 3] = x;
- break;
- case P1275_ARG_OUT_32B:
- (void) va_arg(list, char *);
- p1275buf.prom_args[i + 3] = (unsigned long)p;
- p += 32;
- break;
- case P1275_ARG_IN_FUNCTION:
- p1275buf.prom_args[i + 3] =
- (unsigned long)prom_cif_callback;
- p1275buf.prom_callback = va_arg(list, long);
- break;
- }
- }
- va_end(list);
-
- prom_world(1);
- prom_cif_interface();
- prom_world(0);
-
- attrs = fmt >> 8;
- va_start(list, fmt);
- for (i = 0; i < nargs; i++, attrs >>= 3) {
- switch (attrs & 0x7) {
- case P1275_ARG_NUMBER:
- (void) va_arg(list, long);
- break;
- case P1275_ARG_IN_STRING:
- (void) va_arg(list, char *);
- break;
- case P1275_ARG_IN_FUNCTION:
- (void) va_arg(list, long);
- break;
- case P1275_ARG_IN_BUF:
- (void) va_arg(list, char *);
- (void) va_arg(list, long);
- i++; attrs >>= 3;
- break;
- case P1275_ARG_OUT_BUF:
- p = va_arg(list, char *);
- x = va_arg(list, long);
- memcpy (p, (char *)(p1275buf.prom_args[i + 3]), (int)x);
- i++; attrs >>= 3;
- break;
- case P1275_ARG_OUT_32B:
- p = va_arg(list, char *);
- memcpy (p, (char *)(p1275buf.prom_args[i + 3]), 32);
- break;
- }
- }
- va_end(list);
- x = p1275buf.prom_args [nargs + 3];
-
- spin_unlock_irqrestore(&prom_entry_lock, flags);
-
- return x;
-}
-
-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;
-}
+++ /dev/null
-/*
- * 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 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.
- * USE printk; if you need, deploy -p.
- */
-
-#include <linux/kernel.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-
-static char ppbuf[1024];
-
-void
-prom_write(const char *buf, unsigned int n)
-{
- char ch;
-
- while (n != 0) {
- --n;
- if ((ch = *buf++) == '\n')
- prom_putchar('\r');
- prom_putchar(ch);
- }
-}
-
-void
-prom_printf(const char *fmt, ...)
-{
- va_list args;
- int i;
-
- va_start(args, fmt);
- i = vscnprintf(ppbuf, sizeof(ppbuf), fmt, args);
- va_end(args);
-
- prom_write(ppbuf, i);
-}
+++ /dev/null
-/*
- * 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 <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/ldc.h>
-
-/* Return the child of node 'node' or zero if no this node has no
- * direct descendent.
- */
-inline int __prom_getchild(int node)
-{
- return p1275_cmd ("child", P1275_INOUT(1, 1), node);
-}
-
-inline int prom_getchild(int node)
-{
- int cnode;
-
- if(node == -1) return 0;
- cnode = __prom_getchild(node);
- if(cnode == -1) return 0;
- return (int)cnode;
-}
-
-inline int prom_getparent(int node)
-{
- int cnode;
-
- if(node == -1) return 0;
- cnode = p1275_cmd ("parent", P1275_INOUT(1, 1), node);
- if(cnode == -1) return 0;
- return (int)cnode;
-}
-
-/* Return the next sibling of node 'node' or zero if no more siblings
- * at this level of depth in the tree.
- */
-inline int __prom_getsibling(int node)
-{
- return p1275_cmd(prom_peer_name, P1275_INOUT(1, 1), node);
-}
-
-inline int prom_getsibling(int node)
-{
- int sibnode;
-
- if (node == -1)
- return 0;
- sibnode = __prom_getsibling(node);
- if (sibnode == -1)
- return 0;
-
- return sibnode;
-}
-
-/* Return the length in bytes of property 'prop' at node 'node'.
- * Return -1 on error.
- */
-inline int prom_getproplen(int node, const char *prop)
-{
- if((!node) || (!prop)) return -1;
- return p1275_cmd ("getproplen",
- P1275_ARG(1,P1275_ARG_IN_STRING)|
- P1275_INOUT(2, 1),
- node, prop);
-}
-
-/* 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.
- */
-inline int prom_getproperty(int node, const char *prop,
- char *buffer, int bufsize)
-{
- int plen;
-
- plen = prom_getproplen(node, prop);
- if ((plen > bufsize) || (plen == 0) || (plen == -1)) {
- return -1;
- } else {
- /* Ok, things seem all right. */
- return p1275_cmd(prom_getprop_name,
- P1275_ARG(1,P1275_ARG_IN_STRING)|
- P1275_ARG(2,P1275_ARG_OUT_BUF)|
- P1275_INOUT(4, 1),
- node, prop, buffer, P1275_SIZE(plen));
- }
-}
-
-/* Acquire an integer property and return its value. Returns -1
- * on failure.
- */
-inline int prom_getint(int node, const char *prop)
-{
- int intprop;
-
- if(prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1)
- return intprop;
-
- return -1;
-}
-
-/* Acquire an integer property, upon error return the passed default
- * integer.
- */
-
-int prom_getintdefault(int node, const char *property, int deflt)
-{
- int retval;
-
- retval = prom_getint(node, property);
- if(retval == -1) return deflt;
-
- return retval;
-}
-
-/* Acquire a boolean property, 1=TRUE 0=FALSE. */
-int prom_getbool(int node, const char *prop)
-{
- int retval;
-
- retval = prom_getproplen(node, prop);
- if(retval == -1) return 0;
- return 1;
-}
-
-/* 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, 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;
- return;
-}
-
-
-/* Does the device at node 'node' have name 'name'?
- * YES = 1 NO = 0
- */
-int prom_nodematch(int 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.
- */
-int prom_searchsiblings(int node_start, const char *nodename)
-{
-
- int thisnode, 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;
-}
-
-/* Return the first property type for node 'node'.
- * buffer should be at least 32B in length
- */
-inline char *prom_firstprop(int node, char *buffer)
-{
- *buffer = 0;
- if(node == -1) return buffer;
- p1275_cmd ("nextprop", P1275_ARG(2,P1275_ARG_OUT_32B)|
- P1275_INOUT(3, 0),
- node, (char *) 0x0, buffer);
- return buffer;
-}
-
-/* Return the property type string after property type 'oprop'
- * at node 'node' . Returns NULL string if no more
- * property types for this node.
- */
-inline char *prom_nextprop(int node, const char *oprop, char *buffer)
-{
- char buf[32];
-
- if(node == -1) {
- *buffer = 0;
- return buffer;
- }
- if (oprop == buffer) {
- strcpy (buf, oprop);
- oprop = buf;
- }
- p1275_cmd ("nextprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
- P1275_ARG(2,P1275_ARG_OUT_32B)|
- P1275_INOUT(3, 0),
- node, oprop, buffer);
- return buffer;
-}
-
-int
-prom_finddevice(const char *name)
-{
- if (!name)
- return 0;
- return p1275_cmd(prom_finddev_name,
- P1275_ARG(0,P1275_ARG_IN_STRING)|
- P1275_INOUT(1, 1),
- name);
-}
-
-int prom_node_has_property(int 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;
-}
-
-/* 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, const char *pname, char *value, int size)
-{
- 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
- return p1275_cmd ("setprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
- P1275_ARG(2,P1275_ARG_IN_BUF)|
- P1275_INOUT(4, 1),
- node, pname, value, P1275_SIZE(size));
-}
-
-inline int prom_inst2pkg(int inst)
-{
- int node;
-
- node = p1275_cmd ("instance-to-package", P1275_INOUT(1, 1), inst);
- 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(const char *path)
-{
- int node, inst;
-
- inst = prom_devopen (path);
- if (inst == 0) return 0;
- node = prom_inst2pkg (inst);
- prom_devclose (inst);
- if (node == -1) return 0;
- return node;
-}
-
-int prom_ihandle2path(int handle, char *buffer, int bufsize)
-{
- return p1275_cmd("instance-to-path",
- P1275_ARG(1,P1275_ARG_OUT_BUF)|
- P1275_INOUT(3, 1),
- handle, buffer, P1275_SIZE(bufsize));
-}