aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/boot/of1275
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/boot/of1275')
-rw-r--r--arch/ppc/boot/of1275/Makefile2
-rw-r--r--arch/ppc/boot/of1275/call_prom.c74
-rw-r--r--arch/ppc/boot/of1275/claim.c97
-rw-r--r--arch/ppc/boot/of1275/finddevice.c19
4 files changed, 154 insertions, 38 deletions
diff --git a/arch/ppc/boot/of1275/Makefile b/arch/ppc/boot/of1275/Makefile
index 02e6f235d7cb..0b979c004972 100644
--- a/arch/ppc/boot/of1275/Makefile
+++ b/arch/ppc/boot/of1275/Makefile
@@ -3,4 +3,4 @@
3# 3#
4 4
5lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \ 5lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \
6 ofstdio.o read.o release.o write.o map.o 6 ofstdio.o read.o release.o write.o map.o call_prom.o
diff --git a/arch/ppc/boot/of1275/call_prom.c b/arch/ppc/boot/of1275/call_prom.c
new file mode 100644
index 000000000000..9479a3a2b8c7
--- /dev/null
+++ b/arch/ppc/boot/of1275/call_prom.c
@@ -0,0 +1,74 @@
1/*
2 * Copyright (C) 1996-2005 Paul Mackerras.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include "of1275.h"
11#include <stdarg.h>
12
13int call_prom(const char *service, int nargs, int nret, ...)
14{
15 int i;
16 struct prom_args {
17 const char *service;
18 int nargs;
19 int nret;
20 unsigned int args[12];
21 } args;
22 va_list list;
23
24 args.service = service;
25 args.nargs = nargs;
26 args.nret = nret;
27
28 va_start(list, nret);
29 for (i = 0; i < nargs; i++)
30 args.args[i] = va_arg(list, unsigned int);
31 va_end(list);
32
33 for (i = 0; i < nret; i++)
34 args.args[nargs+i] = 0;
35
36 if (of_prom_entry(&args) < 0)
37 return -1;
38
39 return (nret > 0)? args.args[nargs]: 0;
40}
41
42int call_prom_ret(const char *service, int nargs, int nret,
43 unsigned int *rets, ...)
44{
45 int i;
46 struct prom_args {
47 const char *service;
48 int nargs;
49 int nret;
50 unsigned int args[12];
51 } args;
52 va_list list;
53
54 args.service = service;
55 args.nargs = nargs;
56 args.nret = nret;
57
58 va_start(list, rets);
59 for (i = 0; i < nargs; i++)
60 args.args[i] = va_arg(list, unsigned int);
61 va_end(list);
62
63 for (i = 0; i < nret; i++)
64 args.args[nargs+i] = 0;
65
66 if (of_prom_entry(&args) < 0)
67 return -1;
68
69 if (rets != (void *) 0)
70 for (i = 1; i < nret; ++i)
71 rets[i-1] = args.args[nargs+i];
72
73 return (nret > 0)? args.args[nargs]: 0;
74}
diff --git a/arch/ppc/boot/of1275/claim.c b/arch/ppc/boot/of1275/claim.c
index 13169a5c4339..1ed3aeeff8ae 100644
--- a/arch/ppc/boot/of1275/claim.c
+++ b/arch/ppc/boot/of1275/claim.c
@@ -9,27 +9,84 @@
9 */ 9 */
10 10
11#include "of1275.h" 11#include "of1275.h"
12#include "nonstdio.h"
12 13
13void * 14/*
14claim(unsigned int virt, unsigned int size, unsigned int align) 15 * Older OF's require that when claiming a specific range of addresses,
16 * we claim the physical space in the /memory node and the virtual
17 * space in the chosen mmu node, and then do a map operation to
18 * map virtual to physical.
19 */
20static int need_map = -1;
21static ihandle chosen_mmu;
22static phandle memory;
23
24/* returns true if s2 is a prefix of s1 */
25static int string_match(const char *s1, const char *s2)
26{
27 for (; *s2; ++s2)
28 if (*s1++ != *s2)
29 return 0;
30 return 1;
31}
32
33static int check_of_version(void)
34{
35 phandle oprom, chosen;
36 char version[64];
37
38 oprom = finddevice("/openprom");
39 if (oprom == OF_INVALID_HANDLE)
40 return 0;
41 if (getprop(oprom, "model", version, sizeof(version)) <= 0)
42 return 0;
43 version[sizeof(version)-1] = 0;
44 printf("OF version = '%s'\n", version);
45 if (!string_match(version, "Open Firmware, 1.")
46 && !string_match(version, "FirmWorks,3."))
47 return 0;
48 chosen = finddevice("/chosen");
49 if (chosen == OF_INVALID_HANDLE) {
50 chosen = finddevice("/chosen@0");
51 if (chosen == OF_INVALID_HANDLE) {
52 printf("no chosen\n");
53 return 0;
54 }
55 }
56 if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
57 printf("no mmu\n");
58 return 0;
59 }
60 memory = (ihandle) call_prom("open", 1, 1, "/memory");
61 if (memory == OF_INVALID_HANDLE) {
62 memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
63 if (memory == OF_INVALID_HANDLE) {
64 printf("no memory node\n");
65 return 0;
66 }
67 }
68 printf("old OF detected\n");
69 return 1;
70}
71
72void *claim(unsigned int virt, unsigned int size, unsigned int align)
15{ 73{
16 struct prom_args { 74 int ret;
17 char *service; 75 unsigned int result;
18 int nargs;
19 int nret;
20 unsigned int virt;
21 unsigned int size;
22 unsigned int align;
23 void *ret;
24 } args;
25 76
26 args.service = "claim"; 77 if (need_map < 0)
27 args.nargs = 3; 78 need_map = check_of_version();
28 args.nret = 1; 79 if (align || !need_map)
29 args.virt = virt; 80 return (void *) call_prom("claim", 3, 1, virt, size, align);
30 args.size = size; 81
31 args.align = align; 82 ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
32 args.ret = (void *) 0; 83 align, size, virt);
33 (*of_prom_entry)(&args); 84 if (ret != 0 || result == -1)
34 return args.ret; 85 return (void *) -1;
86 ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
87 align, size, virt);
88 /* 0x12 == coherent + read/write */
89 ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
90 0x12, size, virt, virt);
91 return virt;
35} 92}
diff --git a/arch/ppc/boot/of1275/finddevice.c b/arch/ppc/boot/of1275/finddevice.c
index 2c0f7cbb793e..0dcb1201b772 100644
--- a/arch/ppc/boot/of1275/finddevice.c
+++ b/arch/ppc/boot/of1275/finddevice.c
@@ -10,22 +10,7 @@
10 10
11#include "of1275.h" 11#include "of1275.h"
12 12
13phandle 13phandle finddevice(const char *name)
14finddevice(const char *name)
15{ 14{
16 struct prom_args { 15 return (phandle) call_prom("finddevice", 1, 1, name);
17 char *service;
18 int nargs;
19 int nret;
20 const char *devspec;
21 phandle device;
22 } args;
23
24 args.service = "finddevice";
25 args.nargs = 1;
26 args.nret = 1;
27 args.devspec = name;
28 args.device = OF_INVALID_HANDLE;
29 (*of_prom_entry)(&args);
30 return args.device;
31} 16}