ppc/powerpc: workarounds for old Open Firmware versions

This adds code to work around some problems with old versions of
Open Firmware, such as on the early powermacs (7500 etc.) and the
"Longtrail" CHRP machine.  On these machines we have to claim
the physical and virtual address ranges explicitly when claiming
memory and then set up a V->P mapping.

The Longtrail has more problems: setprop doesn't work, and we have
to set an "allow-reclaim" variable to 0 in order to get claim on
physical memory ranges to fail if the memory is already claimed.

Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Paul Mackerras 2005-11-10 12:00:55 +11:00
parent 8b553f32db
commit a23414beb6
8 changed files with 297 additions and 85 deletions

View File

@ -1264,7 +1264,14 @@ static int __init early_init_dt_scan_memory(unsigned long node,
unsigned long l; unsigned long l;
/* We are scanning "memory" nodes only */ /* We are scanning "memory" nodes only */
if (type == NULL || strcmp(type, "memory") != 0) if (type == NULL) {
/*
* The longtrail doesn't have a device_type on the
* /memory node, so look for the node called /memory@0.
*/
if (depth != 1 || strcmp(uname, "memory@0") != 0)
return 0;
} else if (strcmp(type, "memory") != 0)
return 0; return 0;
reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);

View File

@ -94,11 +94,17 @@ extern const struct linux_logo logo_linux_clut224;
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
#define RELOC(x) (*PTRRELOC(&(x))) #define RELOC(x) (*PTRRELOC(&(x)))
#define ADDR(x) (u32) add_reloc_offset((unsigned long)(x)) #define ADDR(x) (u32) add_reloc_offset((unsigned long)(x))
#define OF_WORKAROUNDS 0
#else #else
#define RELOC(x) (x) #define RELOC(x) (x)
#define ADDR(x) (u32) (x) #define ADDR(x) (u32) (x)
#define OF_WORKAROUNDS of_workarounds
int of_workarounds;
#endif #endif
#define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */
#define OF_WA_LONGTRAIL 2 /* work around longtrail bugs */
#define PROM_BUG() do { \ #define PROM_BUG() do { \
prom_printf("kernel BUG at %s line 0x%x!\n", \ prom_printf("kernel BUG at %s line 0x%x!\n", \
RELOC(__FILE__), __LINE__); \ RELOC(__FILE__), __LINE__); \
@ -128,10 +134,11 @@ struct prom_args {
struct prom_t { struct prom_t {
ihandle root; ihandle root;
ihandle chosen; phandle chosen;
int cpu; int cpu;
ihandle stdout; ihandle stdout;
ihandle mmumap; ihandle mmumap;
ihandle memory;
}; };
struct mem_map_entry { struct mem_map_entry {
@ -360,16 +367,36 @@ static void __init prom_printf(const char *format, ...)
static unsigned int __init prom_claim(unsigned long virt, unsigned long size, static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
unsigned long align) unsigned long align)
{ {
int ret;
struct prom_t *_prom = &RELOC(prom); struct prom_t *_prom = &RELOC(prom);
ret = call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size, if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
(prom_arg_t)align); /*
if (ret != -1 && _prom->mmumap != 0) * Old OF requires we claim physical and virtual separately
/* old pmacs need us to map as well */ * and then map explicitly (assuming virtual mode)
*/
int ret;
prom_arg_t result;
ret = call_prom_ret("call-method", 5, 2, &result,
ADDR("claim"), _prom->memory,
align, size, virt);
if (ret != 0 || result == -1)
return -1;
ret = call_prom_ret("call-method", 5, 2, &result,
ADDR("claim"), _prom->mmumap,
align, size, virt);
if (ret != 0) {
call_prom("call-method", 4, 1, ADDR("release"),
_prom->memory, size, virt);
return -1;
}
/* the 0x12 is M (coherence) + PP == read/write */
call_prom("call-method", 6, 1, call_prom("call-method", 6, 1,
ADDR("map"), _prom->mmumap, 0, size, virt, virt); ADDR("map"), _prom->mmumap, 0x12, size, virt, virt);
return ret; return virt;
}
return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
(prom_arg_t)align);
} }
static void __init __attribute__((noreturn)) prom_panic(const char *reason) static void __init __attribute__((noreturn)) prom_panic(const char *reason)
@ -415,11 +442,52 @@ static int inline prom_getproplen(phandle node, const char *pname)
return call_prom("getproplen", 2, 1, node, ADDR(pname)); return call_prom("getproplen", 2, 1, node, ADDR(pname));
} }
static int inline prom_setprop(phandle node, const char *pname, static void add_string(char **str, const char *q)
void *value, size_t valuelen)
{ {
return call_prom("setprop", 4, 1, node, ADDR(pname), char *p = *str;
(u32)(unsigned long) value, (u32) valuelen);
while (*q)
*p++ = *q++;
*p++ = ' ';
*str = p;
}
static char *tohex(unsigned int x)
{
static char digits[] = "0123456789abcdef";
static char result[9];
int i;
result[8] = 0;
i = 8;
do {
--i;
result[i] = digits[x & 0xf];
x >>= 4;
} while (x != 0 && i > 0);
return &result[i];
}
static int __init prom_setprop(phandle node, const char *nodename,
const char *pname, void *value, size_t valuelen)
{
char cmd[256], *p;
if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
return call_prom("setprop", 4, 1, node, ADDR(pname),
(u32)(unsigned long) value, (u32) valuelen);
/* gah... setprop doesn't work on longtrail, have to use interpret */
p = cmd;
add_string(&p, "dev");
add_string(&p, nodename);
add_string(&p, tohex((u32)(unsigned long) value));
add_string(&p, tohex(valuelen));
add_string(&p, tohex(ADDR(pname)));
add_string(&p, tohex(strlen(RELOC(pname))));
add_string(&p, "property");
*p = 0;
return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
} }
/* We can't use the standard versions because of RELOC headaches. */ /* We can't use the standard versions because of RELOC headaches. */
@ -980,7 +1048,7 @@ static void __init prom_instantiate_rtas(void)
rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
if (!IHANDLE_VALID(rtas_inst)) { if (!IHANDLE_VALID(rtas_inst)) {
prom_printf("opening rtas package failed"); prom_printf("opening rtas package failed (%x)\n", rtas_inst);
return; return;
} }
@ -988,7 +1056,7 @@ static void __init prom_instantiate_rtas(void)
if (call_prom_ret("call-method", 3, 2, &entry, if (call_prom_ret("call-method", 3, 2, &entry,
ADDR("instantiate-rtas"), ADDR("instantiate-rtas"),
rtas_inst, base) == PROM_ERROR rtas_inst, base) != 0
|| entry == 0) { || entry == 0) {
prom_printf(" failed\n"); prom_printf(" failed\n");
return; return;
@ -997,8 +1065,10 @@ static void __init prom_instantiate_rtas(void)
reserve_mem(base, size); reserve_mem(base, size);
prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); &base, sizeof(base));
prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
&entry, sizeof(entry));
prom_debug("rtas base = 0x%x\n", base); prom_debug("rtas base = 0x%x\n", base);
prom_debug("rtas entry = 0x%x\n", entry); prom_debug("rtas entry = 0x%x\n", entry);
@ -1089,10 +1159,6 @@ static void __init prom_initialize_tce_table(void)
if (base < local_alloc_bottom) if (base < local_alloc_bottom)
local_alloc_bottom = base; local_alloc_bottom = base;
/* Save away the TCE table attributes for later use. */
prom_setprop(node, "linux,tce-base", &base, sizeof(base));
prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize));
/* It seems OF doesn't null-terminate the path :-( */ /* It seems OF doesn't null-terminate the path :-( */
memset(path, 0, sizeof(path)); memset(path, 0, sizeof(path));
/* Call OF to setup the TCE hardware */ /* Call OF to setup the TCE hardware */
@ -1101,6 +1167,10 @@ static void __init prom_initialize_tce_table(void)
prom_printf("package-to-path failed\n"); prom_printf("package-to-path failed\n");
} }
/* Save away the TCE table attributes for later use. */
prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
prom_debug("TCE table: %s\n", path); prom_debug("TCE table: %s\n", path);
prom_debug("\tnode = 0x%x\n", node); prom_debug("\tnode = 0x%x\n", node);
prom_debug("\tbase = 0x%x\n", base); prom_debug("\tbase = 0x%x\n", base);
@ -1342,6 +1412,7 @@ static void __init prom_init_client_services(unsigned long pp)
/* /*
* For really old powermacs, we need to map things we claim. * For really old powermacs, we need to map things we claim.
* For that, we need the ihandle of the mmu. * For that, we need the ihandle of the mmu.
* Also, on the longtrail, we need to work around other bugs.
*/ */
static void __init prom_find_mmu(void) static void __init prom_find_mmu(void)
{ {
@ -1355,12 +1426,19 @@ static void __init prom_find_mmu(void)
if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0) if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
return; return;
version[sizeof(version) - 1] = 0; version[sizeof(version) - 1] = 0;
prom_printf("OF version is '%s'\n", version);
/* XXX might need to add other versions here */ /* XXX might need to add other versions here */
if (strcmp(version, "Open Firmware, 1.0.5") != 0) if (strcmp(version, "Open Firmware, 1.0.5") == 0)
of_workarounds = OF_WA_CLAIM;
else if (strncmp(version, "FirmWorks,3.", 12) == 0) {
of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
} else
return; return;
_prom->memory = call_prom("open", 1, 1, ADDR("/memory"));
prom_getprop(_prom->chosen, "mmu", &_prom->mmumap, prom_getprop(_prom->chosen, "mmu", &_prom->mmumap,
sizeof(_prom->mmumap)); sizeof(_prom->mmumap));
if (!IHANDLE_VALID(_prom->memory) || !IHANDLE_VALID(_prom->mmumap))
of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
} }
#else #else
#define prom_find_mmu() #define prom_find_mmu()
@ -1382,16 +1460,17 @@ static void __init prom_init_stdout(void)
memset(path, 0, 256); memset(path, 0, 256);
call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255); call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255);
val = call_prom("instance-to-package", 1, 1, _prom->stdout); val = call_prom("instance-to-package", 1, 1, _prom->stdout);
prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val)); prom_setprop(_prom->chosen, "/chosen", "linux,stdout-package",
&val, sizeof(val));
prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device)); prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device));
prom_setprop(_prom->chosen, "linux,stdout-path", prom_setprop(_prom->chosen, "/chosen", "linux,stdout-path",
RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1); path, strlen(path) + 1);
/* If it's a display, note it */ /* If it's a display, note it */
memset(type, 0, sizeof(type)); memset(type, 0, sizeof(type));
prom_getprop(val, "device_type", type, sizeof(type)); prom_getprop(val, "device_type", type, sizeof(type));
if (strcmp(type, RELOC("display")) == 0) if (strcmp(type, RELOC("display")) == 0)
prom_setprop(val, "linux,boot-display", NULL, 0); prom_setprop(val, path, "linux,boot-display", NULL, 0);
} }
static void __init prom_close_stdin(void) static void __init prom_close_stdin(void)
@ -1514,7 +1593,7 @@ static void __init prom_check_displays(void)
/* Success */ /* Success */
prom_printf("done\n"); prom_printf("done\n");
prom_setprop(node, "linux,opened", NULL, 0); prom_setprop(node, path, "linux,opened", NULL, 0);
/* Setup a usable color table when the appropriate /* Setup a usable color table when the appropriate
* method is available. Should update this to set-colors */ * method is available. Should update this to set-colors */
@ -1884,9 +1963,11 @@ static void __init fixup_device_tree(void)
/* interrupt on this revision of u3 is number 0 and level */ /* interrupt on this revision of u3 is number 0 and level */
interrupts[0] = 0; interrupts[0] = 0;
interrupts[1] = 1; interrupts[1] = 1;
prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts)); prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
&interrupts, sizeof(interrupts));
parent = (u32)mpic; parent = (u32)mpic;
prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent)); prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
&parent, sizeof(parent));
#endif #endif
} }
@ -1922,11 +2003,11 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4; RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;
val = RELOC(prom_initrd_start); val = RELOC(prom_initrd_start);
prom_setprop(_prom->chosen, "linux,initrd-start", &val, prom_setprop(_prom->chosen, "/chosen", "linux,initrd-start",
sizeof(val)); &val, sizeof(val));
val = RELOC(prom_initrd_end); val = RELOC(prom_initrd_end);
prom_setprop(_prom->chosen, "linux,initrd-end", &val, prom_setprop(_prom->chosen, "/chosen", "linux,initrd-end",
sizeof(val)); &val, sizeof(val));
reserve_mem(RELOC(prom_initrd_start), reserve_mem(RELOC(prom_initrd_start),
RELOC(prom_initrd_end) - RELOC(prom_initrd_start)); RELOC(prom_initrd_end) - RELOC(prom_initrd_start));
@ -1968,16 +2049,17 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
*/ */
prom_init_client_services(pp); prom_init_client_services(pp);
/*
* See if this OF is old enough that we need to do explicit maps
* and other workarounds
*/
prom_find_mmu();
/* /*
* Init prom stdout device * Init prom stdout device
*/ */
prom_init_stdout(); prom_init_stdout();
/*
* See if this OF is old enough that we need to do explicit maps
*/
prom_find_mmu();
/* /*
* Check for an initrd * Check for an initrd
*/ */
@ -1989,7 +2071,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
*/ */
RELOC(of_platform) = prom_find_machine_type(); RELOC(of_platform) = prom_find_machine_type();
getprop_rval = RELOC(of_platform); getprop_rval = RELOC(of_platform);
prom_setprop(_prom->chosen, "linux,platform", prom_setprop(_prom->chosen, "/chosen", "linux,platform",
&getprop_rval, sizeof(getprop_rval)); &getprop_rval, sizeof(getprop_rval));
#ifdef CONFIG_PPC_PSERIES #ifdef CONFIG_PPC_PSERIES
@ -2050,21 +2132,23 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
* Fill in some infos for use by the kernel later on * Fill in some infos for use by the kernel later on
*/ */
if (RELOC(prom_memory_limit)) if (RELOC(prom_memory_limit))
prom_setprop(_prom->chosen, "linux,memory-limit", prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit",
&RELOC(prom_memory_limit), &RELOC(prom_memory_limit),
sizeof(prom_memory_limit)); sizeof(prom_memory_limit));
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
if (RELOC(ppc64_iommu_off)) if (RELOC(ppc64_iommu_off))
prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0); prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off",
NULL, 0);
if (RELOC(iommu_force_on)) if (RELOC(iommu_force_on))
prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0); prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on",
NULL, 0);
if (RELOC(prom_tce_alloc_start)) { if (RELOC(prom_tce_alloc_start)) {
prom_setprop(_prom->chosen, "linux,tce-alloc-start", prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-start",
&RELOC(prom_tce_alloc_start), &RELOC(prom_tce_alloc_start),
sizeof(prom_tce_alloc_start)); sizeof(prom_tce_alloc_start));
prom_setprop(_prom->chosen, "linux,tce-alloc-end", prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-end",
&RELOC(prom_tce_alloc_end), &RELOC(prom_tce_alloc_end),
sizeof(prom_tce_alloc_end)); sizeof(prom_tce_alloc_end));
} }

View File

@ -361,7 +361,9 @@ static void __init chrp_find_openpic(void)
printk(KERN_INFO "OpenPIC at %lx\n", opaddr); printk(KERN_INFO "OpenPIC at %lx\n", opaddr);
irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */
prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS - 4); prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS - 4);
/* i8259 cascade is always positive level */
init_senses[0] = IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE;
iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len);
if (iranges == NULL) if (iranges == NULL)

View File

@ -19,6 +19,9 @@ extern prom_entry of_prom_entry;
/* function declarations */ /* function declarations */
int call_prom(const char *service, int nargs, int nret, ...);
int call_prom_ret(const char *service, int nargs, int nret,
unsigned int *rets, ...);
void * claim(unsigned int virt, unsigned int size, unsigned int align); void * claim(unsigned int virt, unsigned int size, unsigned int align);
int map(unsigned int phys, unsigned int virt, unsigned int size); int map(unsigned int phys, unsigned int virt, unsigned int size);
void enter(void); void enter(void);

View File

@ -3,4 +3,4 @@
# #
lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \ lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \
ofstdio.o read.o release.o write.o map.o ofstdio.o read.o release.o write.o map.o call_prom.o

View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 1996-2005 Paul Mackerras.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include "of1275.h"
#include <stdarg.h>
int call_prom(const char *service, int nargs, int nret, ...)
{
int i;
struct prom_args {
const char *service;
int nargs;
int nret;
unsigned int args[12];
} args;
va_list list;
args.service = service;
args.nargs = nargs;
args.nret = nret;
va_start(list, nret);
for (i = 0; i < nargs; i++)
args.args[i] = va_arg(list, unsigned int);
va_end(list);
for (i = 0; i < nret; i++)
args.args[nargs+i] = 0;
if (of_prom_entry(&args) < 0)
return -1;
return (nret > 0)? args.args[nargs]: 0;
}
int call_prom_ret(const char *service, int nargs, int nret,
unsigned int *rets, ...)
{
int i;
struct prom_args {
const char *service;
int nargs;
int nret;
unsigned int args[12];
} args;
va_list list;
args.service = service;
args.nargs = nargs;
args.nret = nret;
va_start(list, rets);
for (i = 0; i < nargs; i++)
args.args[i] = va_arg(list, unsigned int);
va_end(list);
for (i = 0; i < nret; i++)
args.args[nargs+i] = 0;
if (of_prom_entry(&args) < 0)
return -1;
if (rets != (void *) 0)
for (i = 1; i < nret; ++i)
rets[i-1] = args.args[nargs+i];
return (nret > 0)? args.args[nargs]: 0;
}

View File

@ -9,27 +9,84 @@
*/ */
#include "of1275.h" #include "of1275.h"
#include "nonstdio.h"
void * /*
claim(unsigned int virt, unsigned int size, unsigned int align) * Older OF's require that when claiming a specific range of addresses,
* we claim the physical space in the /memory node and the virtual
* space in the chosen mmu node, and then do a map operation to
* map virtual to physical.
*/
static int need_map = -1;
static ihandle chosen_mmu;
static phandle memory;
/* returns true if s2 is a prefix of s1 */
static int string_match(const char *s1, const char *s2)
{ {
struct prom_args { for (; *s2; ++s2)
char *service; if (*s1++ != *s2)
int nargs; return 0;
int nret; return 1;
unsigned int virt; }
unsigned int size;
unsigned int align; static int check_of_version(void)
void *ret; {
} args; phandle oprom, chosen;
char version[64];
args.service = "claim";
args.nargs = 3; oprom = finddevice("/openprom");
args.nret = 1; if (oprom == OF_INVALID_HANDLE)
args.virt = virt; return 0;
args.size = size; if (getprop(oprom, "model", version, sizeof(version)) <= 0)
args.align = align; return 0;
args.ret = (void *) 0; version[sizeof(version)-1] = 0;
(*of_prom_entry)(&args); printf("OF version = '%s'\n", version);
return args.ret; if (!string_match(version, "Open Firmware, 1.")
&& !string_match(version, "FirmWorks,3."))
return 0;
chosen = finddevice("/chosen");
if (chosen == OF_INVALID_HANDLE) {
chosen = finddevice("/chosen@0");
if (chosen == OF_INVALID_HANDLE) {
printf("no chosen\n");
return 0;
}
}
if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
printf("no mmu\n");
return 0;
}
memory = (ihandle) call_prom("open", 1, 1, "/memory");
if (memory == OF_INVALID_HANDLE) {
memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
if (memory == OF_INVALID_HANDLE) {
printf("no memory node\n");
return 0;
}
}
printf("old OF detected\n");
return 1;
}
void *claim(unsigned int virt, unsigned int size, unsigned int align)
{
int ret;
unsigned int result;
if (need_map < 0)
need_map = check_of_version();
if (align || !need_map)
return (void *) call_prom("claim", 3, 1, virt, size, align);
ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
align, size, virt);
if (ret != 0 || result == -1)
return (void *) -1;
ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
align, size, virt);
/* 0x12 == coherent + read/write */
ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
0x12, size, virt, virt);
return virt;
} }

View File

@ -10,22 +10,7 @@
#include "of1275.h" #include "of1275.h"
phandle phandle finddevice(const char *name)
finddevice(const char *name)
{ {
struct prom_args { return (phandle) call_prom("finddevice", 1, 1, name);
char *service;
int nargs;
int nret;
const char *devspec;
phandle device;
} args;
args.service = "finddevice";
args.nargs = 1;
args.nret = 1;
args.devspec = name;
args.device = OF_INVALID_HANDLE;
(*of_prom_entry)(&args);
return args.device;
} }