mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-09 01:28:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
17
arch/sparc/prom/Makefile
Normal file
17
arch/sparc/prom/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Makefile for the Sun Boot PROM interface library under
|
||||
# Linux.
|
||||
#
|
||||
asflags := -ansi
|
||||
ccflags := -Werror
|
||||
|
||||
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
|
62
arch/sparc/prom/bootstr_32.c
Normal file
62
arch/sparc/prom/bootstr_32.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* bootstr.c: Boot string/argument acquisition from the PROM.
|
||||
*
|
||||
* Copyright(C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||
*/
|
||||
|
||||
#include <linux/string.h>
|
||||
#include <asm/oplib.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#define BARG_LEN 256
|
||||
static char barg_buf[BARG_LEN] = { 0 };
|
||||
static char fetched __initdata = 0;
|
||||
|
||||
char * __init
|
||||
prom_getbootargs(void)
|
||||
{
|
||||
int iter;
|
||||
char *cp, *arg;
|
||||
|
||||
/* This check saves us from a panic when bootfd patches args. */
|
||||
if (fetched) {
|
||||
return barg_buf;
|
||||
}
|
||||
|
||||
switch (prom_vers) {
|
||||
case PROM_V0:
|
||||
cp = barg_buf;
|
||||
/* Start from 1 and go over fd(0,0,0)kernel */
|
||||
for (iter = 1; iter < 8; iter++) {
|
||||
arg = (*(romvec->pv_v0bootargs))->argv[iter];
|
||||
if (arg == NULL)
|
||||
break;
|
||||
while (*arg != 0) {
|
||||
/* Leave place for space and null. */
|
||||
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;
|
||||
case PROM_V2:
|
||||
case PROM_V3:
|
||||
/*
|
||||
* V3 PROM cannot supply as with more than 128 bytes
|
||||
* of an argument. But a smart bootstrap loader can.
|
||||
*/
|
||||
strlcpy(barg_buf, *romvec->pv_v2bootargs.bootargs, sizeof(barg_buf));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fetched = 1;
|
||||
return barg_buf;
|
||||
}
|
43
arch/sparc/prom/bootstr_64.c
Normal file
43
arch/sparc/prom/bootstr_64.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* We limit BARG_LEN to 1024 because this is the size of the
|
||||
* 'barg_out' command line buffer in the SILO bootloader.
|
||||
*/
|
||||
#define BARG_LEN 1024
|
||||
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;
|
||||
}
|
47
arch/sparc/prom/cif.S
Normal file
47
arch/sparc/prom/cif.S
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* 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:
|
||||
save %sp, -192, %sp
|
||||
sethi %hi(p1275buf), %o1
|
||||
or %o1, %lo(p1275buf), %o1
|
||||
ldx [%o1 + 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
|
||||
|
56
arch/sparc/prom/console_32.c
Normal file
56
arch/sparc/prom/console_32.c
Normal file
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
45
arch/sparc/prom/console_64.c
Normal file
45
arch/sparc/prom/console_64.c
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
75
arch/sparc/prom/init_32.c
Normal file
75
arch/sparc/prom/init_32.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* init.c: Initialize internal variables used by the PROM
|
||||
* library functions.
|
||||
*
|
||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||
* Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/openprom.h>
|
||||
#include <asm/oplib.h>
|
||||
|
||||
struct linux_romvec *romvec;
|
||||
EXPORT_SYMBOL(romvec);
|
||||
|
||||
enum prom_major_version prom_vers;
|
||||
unsigned int prom_rev, prom_prev;
|
||||
|
||||
/* The root node of the prom device tree. */
|
||||
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 gets passed the pointer to the PROM vector.
|
||||
*/
|
||||
|
||||
void __init prom_init(struct linux_romvec *rp)
|
||||
{
|
||||
romvec = rp;
|
||||
|
||||
switch(romvec->pv_romvers) {
|
||||
case 0:
|
||||
prom_vers = PROM_V0;
|
||||
break;
|
||||
case 2:
|
||||
prom_vers = PROM_V2;
|
||||
break;
|
||||
case 3:
|
||||
prom_vers = PROM_V3;
|
||||
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) || ((s32)prom_root_node == -1))
|
||||
prom_halt();
|
||||
|
||||
if((((unsigned long) prom_nodeops) == 0) ||
|
||||
(((unsigned long) prom_nodeops) == -1))
|
||||
prom_halt();
|
||||
|
||||
prom_meminit();
|
||||
|
||||
prom_ranges_init();
|
||||
|
||||
printk("PROMLIB: Sun Boot Prom Version %d Revision %d\n",
|
||||
romvec->pv_romvers, prom_rev);
|
||||
|
||||
/* Initialization successful. */
|
||||
}
|
56
arch/sparc/prom/init_64.c
Normal file
56
arch/sparc/prom/init_64.c
Normal file
|
@ -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 __init prom_init(void *cif_handler)
|
||||
{
|
||||
phandle node;
|
||||
|
||||
prom_cif_init(cif_handler);
|
||||
|
||||
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);
|
||||
}
|
87
arch/sparc/prom/memory.c
Normal file
87
arch/sparc/prom/memory.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/* memory.c: Prom routine for acquiring various bits of information
|
||||
* about RAM on the machine, both virtual and physical.
|
||||
*
|
||||
* Copyright (C) 1995, 2008 David S. Miller (davem@davemloft.net)
|
||||
* Copyright (C) 1997 Michael A. Griffith (grif@acm.org)
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sort.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/openprom.h>
|
||||
#include <asm/oplib.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static int __init prom_meminit_v2(void)
|
||||
{
|
||||
struct linux_prom_registers reg[64];
|
||||
phandle node;
|
||||
int size, num_ents, i;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int sp_banks_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct sparc_phys_banks *x = a, *y = b;
|
||||
|
||||
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 i, num_ents = 0;
|
||||
|
||||
switch (prom_vers) {
|
||||
case PROM_V0:
|
||||
num_ents = prom_meminit_v0();
|
||||
break;
|
||||
|
||||
case PROM_V2:
|
||||
case PROM_V3:
|
||||
num_ents = prom_meminit_v2();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sort(sp_banks, num_ents, sizeof(struct sparc_phys_banks),
|
||||
sp_banks_cmp, NULL);
|
||||
|
||||
/* Sentinel. */
|
||||
sp_banks[num_ents].base_addr = 0xdeadbeef;
|
||||
sp_banks[num_ents].num_bytes = 0;
|
||||
|
||||
for (i = 0; i < num_ents; i++)
|
||||
sp_banks[i].num_bytes &= PAGE_MASK;
|
||||
}
|
127
arch/sparc/prom/misc_32.c
Normal file
127
arch/sparc/prom/misc_32.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* misc.c: Miscellaneous prom functions that don't belong
|
||||
* anywhere else.
|
||||
*
|
||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
extern void restore_current(void);
|
||||
|
||||
DEFINE_SPINLOCK(prom_lock);
|
||||
|
||||
/* Reset and reboot the machine with the command 'bcommand'. */
|
||||
void
|
||||
prom_reboot(char *bcommand)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
(*(romvec->pv_reboot))(bcommand);
|
||||
/* Never get here. */
|
||||
restore_current();
|
||||
spin_unlock_irqrestore(&prom_lock, flags);
|
||||
}
|
||||
|
||||
/* Forth evaluate the expression contained in 'fstring'. */
|
||||
void
|
||||
prom_feval(char *fstring)
|
||||
{
|
||||
unsigned long flags;
|
||||
if(!fstring || fstring[0] == 0)
|
||||
return;
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
if(prom_vers == PROM_V0)
|
||||
(*(romvec->pv_fortheval.v0_eval))(strlen(fstring), fstring);
|
||||
else
|
||||
(*(romvec->pv_fortheval.v2_eval))(fstring);
|
||||
restore_current();
|
||||
spin_unlock_irqrestore(&prom_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(prom_feval);
|
||||
|
||||
/* Drop into the prom, with the chance to continue with the 'go'
|
||||
* prom command.
|
||||
*/
|
||||
void
|
||||
prom_cmdline(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
(*(romvec->pv_abort))();
|
||||
restore_current();
|
||||
spin_unlock_irqrestore(&prom_lock, flags);
|
||||
set_auxio(AUXIO_LED, 0);
|
||||
}
|
||||
|
||||
/* Drop into the prom, but completely terminate the program.
|
||||
* No chance of continuing.
|
||||
*/
|
||||
void __noreturn
|
||||
prom_halt(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
again:
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
(*(romvec->pv_halt))();
|
||||
/* Never get here. */
|
||||
restore_current();
|
||||
spin_unlock_irqrestore(&prom_lock, flags);
|
||||
goto again; /* PROM is out to get me -DaveM */
|
||||
}
|
||||
|
||||
typedef void (*sfunc_t)(void);
|
||||
|
||||
/* Set prom sync handler to call function 'funcp'. */
|
||||
void
|
||||
prom_setsync(sfunc_t funcp)
|
||||
{
|
||||
if(!funcp) return;
|
||||
*romvec->pv_synchook = 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;
|
||||
}
|
||||
|
||||
/* Get the major prom version number. */
|
||||
int
|
||||
prom_version(void)
|
||||
{
|
||||
return romvec->pv_romvers;
|
||||
}
|
||||
|
||||
/* Get the prom plugin-revision. */
|
||||
int
|
||||
prom_getrev(void)
|
||||
{
|
||||
return prom_rev;
|
||||
}
|
||||
|
||||
/* Get the prom firmware print revision. */
|
||||
int
|
||||
prom_getprev(void)
|
||||
{
|
||||
return prom_prev;
|
||||
}
|
446
arch/sparc/prom/misc_64.c
Normal file
446
arch/sparc/prom/misc_64.c
Normal file
|
@ -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
|
43
arch/sparc/prom/mp.c
Normal file
43
arch/sparc/prom/mp.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* mp.c: OpenBoot Prom Multiprocessor support routines. Don't call
|
||||
* these on a UP or else you will halt and catch fire. ;)
|
||||
*
|
||||
* 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);
|
||||
|
||||
/* Start cpu with prom-tree node 'cpunode' using context described
|
||||
* by 'ctable_reg' in context 'ctx' at program counter 'pc'.
|
||||
*
|
||||
* XXX Have to look into what the return values mean. XXX
|
||||
*/
|
||||
int
|
||||
prom_startcpu(int cpunode, struct linux_prom_registers *ctable_reg, int ctx, char *pc)
|
||||
{
|
||||
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_cpustart))(cpunode, (int) ctable_reg, ctx, pc);
|
||||
break;
|
||||
}
|
||||
restore_current();
|
||||
spin_unlock_irqrestore(&prom_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
54
arch/sparc/prom/p1275.c
Normal file
54
arch/sparc/prom/p1275.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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 <linux/irqflags.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 */
|
||||
} 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;
|
||||
|
||||
local_save_flags(flags);
|
||||
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);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
void prom_cif_init(void *cif_handler, void *cif_stack)
|
||||
{
|
||||
p1275buf.prom_cif_handler = (void (*)(long *))cif_handler;
|
||||
}
|
69
arch/sparc/prom/printf.c
Normal file
69
arch/sparc/prom/printf.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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 <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 notrace prom_write(const char *buf, unsigned int n)
|
||||
{
|
||||
unsigned int dest_len;
|
||||
unsigned long flags;
|
||||
char *dest;
|
||||
|
||||
dest = console_write_buf;
|
||||
raw_spin_lock_irqsave(&console_write_lock, flags);
|
||||
|
||||
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 notrace 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);
|
||||
}
|
117
arch/sparc/prom/ranges.c
Normal file
117
arch/sparc/prom/ranges.c
Normal file
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* ranges.c: Handle ranges in newer proms for obio/sbus.
|
||||
*
|
||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/openprom.h>
|
||||
#include <asm/oplib.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
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
|
||||
prom_adjust_regs(struct linux_prom_registers *regp, int nregs,
|
||||
struct linux_prom_ranges *rangep, int nranges)
|
||||
{
|
||||
int regc, rngc;
|
||||
|
||||
for (regc = 0; regc < nregs; regc++) {
|
||||
for (rngc = 0; rngc < nranges; rngc++)
|
||||
if (regp[regc].which_io == rangep[rngc].ot_child_space)
|
||||
break; /* Fount it */
|
||||
if (rngc == nranges) /* oops */
|
||||
prom_printf("adjust_regs: Could not find range with matching bus type...\n");
|
||||
regp[regc].which_io = rangep[rngc].ot_parent_space;
|
||||
regp[regc].phys_addr -= rangep[rngc].ot_child_base;
|
||||
regp[regc].phys_addr += rangep[rngc].ot_parent_base;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1,
|
||||
struct linux_prom_ranges *ranges2, int nranges2)
|
||||
{
|
||||
int rng1c, rng2c;
|
||||
|
||||
for(rng1c=0; rng1c < nranges1; rng1c++) {
|
||||
for(rng2c=0; rng2c < nranges2; rng2c++)
|
||||
if(ranges1[rng1c].ot_parent_space == ranges2[rng2c].ot_child_space &&
|
||||
ranges1[rng1c].ot_parent_base >= ranges2[rng2c].ot_child_base &&
|
||||
ranges2[rng2c].ot_child_base + ranges2[rng2c].or_size - ranges1[rng1c].ot_parent_base > 0U)
|
||||
break;
|
||||
if(rng2c == nranges2) /* oops */
|
||||
prom_printf("adjust_ranges: Could not find matching bus type...\n");
|
||||
else if (ranges1[rng1c].ot_parent_base + ranges1[rng1c].or_size > ranges2[rng2c].ot_child_base + ranges2[rng2c].or_size)
|
||||
ranges1[rng1c].or_size =
|
||||
ranges2[rng2c].ot_child_base + ranges2[rng2c].or_size - ranges1[rng1c].ot_parent_base;
|
||||
ranges1[rng1c].ot_parent_space = ranges2[rng2c].ot_parent_space;
|
||||
ranges1[rng1c].ot_parent_base += ranges2[rng2c].ot_parent_base;
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply probed obio ranges to registers passed, if no ranges return. */
|
||||
void
|
||||
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)
|
||||
{
|
||||
phandle node, obio_node;
|
||||
int success;
|
||||
|
||||
num_obio_ranges = 0;
|
||||
|
||||
/* Check for obio and sbus ranges. */
|
||||
node = prom_getchild(prom_root_node);
|
||||
obio_node = prom_searchsiblings(node, "obio");
|
||||
|
||||
if(obio_node) {
|
||||
success = prom_getproperty(obio_node, "ranges",
|
||||
(char *) promlib_obio_ranges,
|
||||
sizeof(promlib_obio_ranges));
|
||||
if(success != -1)
|
||||
num_obio_ranges = (success/sizeof(struct linux_prom_ranges));
|
||||
}
|
||||
|
||||
if(num_obio_ranges)
|
||||
prom_printf("PROMLIB: obio_ranges %d\n", num_obio_ranges);
|
||||
}
|
||||
|
||||
void prom_apply_generic_ranges(phandle node, phandle parent,
|
||||
struct linux_prom_registers *regs, int nregs)
|
||||
{
|
||||
int success;
|
||||
int num_ranges;
|
||||
struct linux_prom_ranges ranges[PROMREG_MAX];
|
||||
|
||||
success = prom_getproperty(node, "ranges",
|
||||
(char *) ranges,
|
||||
sizeof (ranges));
|
||||
if (success != -1) {
|
||||
num_ranges = (success/sizeof(struct linux_prom_ranges));
|
||||
if (parent) {
|
||||
struct linux_prom_ranges parent_ranges[PROMREG_MAX];
|
||||
int num_parent_ranges;
|
||||
|
||||
success = prom_getproperty(parent, "ranges",
|
||||
(char *) parent_ranges,
|
||||
sizeof (parent_ranges));
|
||||
if (success != -1) {
|
||||
num_parent_ranges = (success/sizeof(struct linux_prom_ranges));
|
||||
prom_adjust_ranges (ranges, num_ranges, parent_ranges, num_parent_ranges);
|
||||
}
|
||||
}
|
||||
prom_adjust_regs(regs, nregs, ranges, num_ranges);
|
||||
}
|
||||
}
|
309
arch/sparc/prom/tree_32.c
Normal file
309
arch/sparc/prom/tree_32.c
Normal file
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
* tree.c: Basic device tree traversal/scanning for the Linux
|
||||
* prom library.
|
||||
*
|
||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
extern void restore_current(void);
|
||||
|
||||
static char promlib_buf[128];
|
||||
|
||||
/* Internal version of prom_getchild that does not alter return values. */
|
||||
static phandle __prom_getchild(phandle node)
|
||||
{
|
||||
unsigned long flags;
|
||||
phandle cnode;
|
||||
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
cnode = prom_nodeops->no_child(node);
|
||||
restore_current();
|
||||
spin_unlock_irqrestore(&prom_lock, flags);
|
||||
|
||||
return cnode;
|
||||
}
|
||||
|
||||
/* Return the child of node 'node' or zero if no this node has no
|
||||
* direct descendent.
|
||||
*/
|
||||
phandle prom_getchild(phandle node)
|
||||
{
|
||||
phandle cnode;
|
||||
|
||||
if ((s32)node == -1)
|
||||
return 0;
|
||||
|
||||
cnode = __prom_getchild(node);
|
||||
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. */
|
||||
static phandle __prom_getsibling(phandle node)
|
||||
{
|
||||
unsigned long flags;
|
||||
phandle cnode;
|
||||
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
cnode = prom_nodeops->no_nextnode(node);
|
||||
restore_current();
|
||||
spin_unlock_irqrestore(&prom_lock, flags);
|
||||
|
||||
return cnode;
|
||||
}
|
||||
|
||||
/* Return the next sibling of node 'node' or zero if no more siblings
|
||||
* at this level of depth in the tree.
|
||||
*/
|
||||
phandle prom_getsibling(phandle node)
|
||||
{
|
||||
phandle sibnode;
|
||||
|
||||
if ((s32)node == -1)
|
||||
return 0;
|
||||
|
||||
sibnode = __prom_getsibling(node);
|
||||
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(phandle node, const char *prop)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
if((!node) || (!prop))
|
||||
return -1;
|
||||
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
ret = prom_nodeops->no_proplen(node, prop);
|
||||
restore_current();
|
||||
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(phandle node, const char *prop, char *buffer, int bufsize)
|
||||
{
|
||||
int plen, ret;
|
||||
unsigned long flags;
|
||||
|
||||
plen = prom_getproplen(node, prop);
|
||||
if((plen > bufsize) || (plen == 0) || (plen == -1))
|
||||
return -1;
|
||||
/* Ok, things seem all right. */
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
ret = prom_nodeops->no_getprop(node, prop, buffer);
|
||||
restore_current();
|
||||
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(phandle node, char *prop)
|
||||
{
|
||||
static 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, 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, 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, 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);
|
||||
|
||||
|
||||
/* Search siblings at 'node_start' for a node with name
|
||||
* 'nodename'. Return node if successful, zero if not.
|
||||
*/
|
||||
phandle prom_searchsiblings(phandle node_start, char *nodename)
|
||||
{
|
||||
|
||||
phandle thisnode;
|
||||
int error;
|
||||
|
||||
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);
|
||||
|
||||
/* Interal version of nextprop that does not alter return values. */
|
||||
static char *__prom_nextprop(phandle node, char * oprop)
|
||||
{
|
||||
unsigned long flags;
|
||||
char *prop;
|
||||
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
prop = prom_nodeops->no_nextprop(node, oprop);
|
||||
restore_current();
|
||||
spin_unlock_irqrestore(&prom_lock, flags);
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
/* 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(phandle node, char *oprop, char *buffer)
|
||||
{
|
||||
if (node == 0 || (s32)node == -1)
|
||||
return "";
|
||||
|
||||
return __prom_nextprop(node, oprop);
|
||||
}
|
||||
EXPORT_SYMBOL(prom_nextprop);
|
||||
|
||||
phandle prom_finddevice(char *name)
|
||||
{
|
||||
char nbuf[128];
|
||||
char *s = name, *d;
|
||||
phandle node = prom_root_node, node2;
|
||||
unsigned int which_io, phys_addr;
|
||||
struct linux_prom_registers reg[PROMREG_MAX];
|
||||
|
||||
while (*s++) {
|
||||
if (!*s) return node; /* path '.../' is legal */
|
||||
node = prom_getchild(node);
|
||||
|
||||
for (d = nbuf; *s != 0 && *s != '@' && *s != '/';)
|
||||
*d++ = *s++;
|
||||
*d = 0;
|
||||
|
||||
node = prom_searchsiblings(node, nbuf);
|
||||
if (!node)
|
||||
return 0;
|
||||
|
||||
if (*s == '@') {
|
||||
if (isxdigit(s[1]) && s[2] == ',') {
|
||||
which_io = simple_strtoul(s+1, NULL, 16);
|
||||
phys_addr = simple_strtoul(s+3, &d, 16);
|
||||
if (d != s + 3 && (!*d || *d == '/')
|
||||
&& d <= s + 3 + 8) {
|
||||
node2 = node;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
node2 = prom_getsibling(node2);
|
||||
if (!node2 || (s32)node2 == -1)
|
||||
break;
|
||||
node2 = prom_searchsiblings(prom_getsibling(node2), nbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (*s != 0 && *s != '/') s++;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
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(phandle node, const char *pname, char *value, int size)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
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);
|
||||
|
||||
phandle prom_inst2pkg(int inst)
|
||||
{
|
||||
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 ((s32)node == -1)
|
||||
return 0;
|
||||
return node;
|
||||
}
|
392
arch/sparc/prom/tree_64.c
Normal file
392
arch/sparc/prom/tree_64.c
Normal file
|
@ -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];
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue