source: mainline/boot/genarch/ofw.c@ fb0e6f03

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fb0e6f03 was fb0e6f03, checked in by jermar <jermar@…>, 17 years ago

Merge the boot branch.

  • Property mode set to 100644
File size: 6.4 KB
Line 
1/*
2 * Copyright (C) 2005 Martin Decky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "ofw.h"
30#include <printf.h>
31#include <asm.h>
32#include <types.h>
33
34uintptr_t ofw_cif;
35
36phandle ofw_chosen;
37ihandle ofw_stdout;
38phandle ofw_root;
39ihandle ofw_mmu;
40phandle ofw_memory;
41phandle ofw_aliases;
42
43static unsigned long ofw_call(const char *service, const int nargs, const int nret, ofw_arg_t *rets, ...)
44{
45 va_list list;
46 ofw_args_t args;
47 int i;
48
49 args.service = service;
50 args.nargs = nargs;
51 args.nret = nret;
52
53 va_start(list, rets);
54 for (i = 0; i < nargs; i++)
55 args.args[i] = va_arg(list, ofw_arg_t);
56 va_end(list);
57
58 for (i = 0; i < nret; i++)
59 args.args[i + nargs] = 0;
60
61 (void) ofw(&args);
62
63 for (i = 1; i < nret; i++)
64 rets[i - 1] = args.args[i + nargs];
65
66 return args.args[nargs];
67}
68
69
70phandle ofw_find_device(const char *name)
71{
72 return ofw_call("finddevice", 1, 1, NULL, name);
73}
74
75
76int ofw_get_property(const phandle device, const char *name, const void *buf, const int buflen)
77{
78 return ofw_call("getprop", 4, 1, NULL, device, name, buf, buflen);
79}
80
81
82static unsigned int ofw_get_address_cells(const phandle device)
83{
84 unsigned int ret;
85
86 if (ofw_get_property(device, "#address-cells", &ret, sizeof(ret)) <= 0)
87 if (ofw_get_property(ofw_root, "#address-cells", &ret, sizeof(ret)) <= 0)
88 ret = 1;
89
90 return ret;
91}
92
93
94static unsigned int ofw_get_size_cells(const phandle device)
95{
96 unsigned int ret;
97
98 if (ofw_get_property(device, "#size-cells", &ret, sizeof(ret)) <= 0)
99 if (ofw_get_property(ofw_root, "#size-cells", &ret, sizeof(ret)) <= 0)
100 ret = 1;
101
102 return ret;
103}
104
105
106static ihandle ofw_open(const char *name)
107{
108 return ofw_call("open", 1, 1, NULL, name);
109}
110
111
112void init(void)
113{
114 ofw_chosen = ofw_find_device("/chosen");
115 if (ofw_chosen == -1)
116 halt();
117
118 if (ofw_get_property(ofw_chosen, "stdout", &ofw_stdout, sizeof(ofw_stdout)) <= 0)
119 ofw_stdout = 0;
120
121 ofw_root = ofw_find_device("/");
122 if (ofw_root == -1) {
123 puts("\r\nError: Unable to find / device, halted.\r\n");
124 halt();
125 }
126
127 if (ofw_get_property(ofw_chosen, "mmu", &ofw_mmu, sizeof(ofw_mmu)) <= 0) {
128 puts("\r\nError: Unable to get mmu property, halted.\r\n");
129 halt();
130 }
131
132 ofw_memory = ofw_find_device("/memory");
133 if (ofw_memory == -1) {
134 puts("\r\nError: Unable to find /memory device, halted.\r\n");
135 halt();
136 }
137
138 ofw_aliases = ofw_find_device("/aliases");
139 if (ofw_aliases == -1) {
140 puts("\r\nError: Unable to find /aliases device, halted.\r\n");
141 halt();
142 }
143}
144
145
146void ofw_write(const char *str, const int len)
147{
148 if (ofw_stdout == 0)
149 return;
150
151 ofw_call("write", 3, 1, NULL, ofw_stdout, str, len);
152}
153
154
155void *ofw_translate(const void *virt)
156{
157 ofw_arg_t result[4];
158 int shift;
159
160 if (ofw_call("call-method", 3, 5, result, "translate", ofw_mmu, virt) != 0) {
161 puts("Error: MMU method translate() failed, halting.\n");
162 halt();
163 }
164
165 if (ofw_translate_failed(result[0]))
166 return NULL;
167
168 if (sizeof(unative_t) == 8)
169 shift = 32;
170 else
171 shift = 0;
172
173 return (void *) ((result[2]<<shift)|result[3]);
174}
175
176void *ofw_claim(const void *virt, const int len)
177{
178 ofw_arg_t retaddr;
179 int shift;
180
181 if (ofw_call("call-method", 5, 2, &retaddr, "claim", ofw_mmu, 0, len, virt) != 0) {
182 puts("Error: MMU method claim() failed, halting.\n");
183 halt();
184 }
185
186 return (void *) retaddr;
187}
188
189int ofw_map(const void *phys, const void *virt, const int size, const int mode)
190{
191 uintptr_t phys_hi, phys_lo;
192
193 if (sizeof(unative_t) == 8) {
194 int shift = 32;
195 phys_hi = (uintptr_t) phys >> shift;
196 phys_lo = (uintptr_t) phys & 0xffffffff;
197 } else {
198 phys_hi = 0;
199 phys_lo = (uintptr_t) phys;
200 }
201
202 return ofw_call("call-method", 7, 1, NULL, "map", ofw_mmu, mode, size, virt,
203 phys_hi, phys_lo);
204}
205
206
207int ofw_memmap(memmap_t *map)
208{
209 unsigned long buf[BUF_SIZE];
210 int ret = ofw_get_property(ofw_memory, "reg", buf, sizeof(buf));
211 if (ret <= 0)
212 return false;
213
214 unsigned int ac = ofw_get_address_cells(ofw_memory);
215 unsigned int sc = ofw_get_size_cells(ofw_memory);
216
217 int pos;
218 map->total = 0;
219 map->count = 0;
220 for (pos = 0; (pos < ret / sizeof(unsigned long)) && (map->count < MEMMAP_MAX_RECORDS); pos += ac + sc) {
221 void * start = (void *) buf[pos + ac - 1];
222 unsigned int size = buf[pos + ac + sc - 1];
223
224 if (size > 0) {
225 map->zones[map->count].start = start;
226 map->zones[map->count].size = size;
227 map->count++;
228 map->total += size;
229 }
230 }
231}
232
233
234int ofw_screen(screen_t *screen)
235{
236 char device_name[BUF_SIZE];
237
238 if (ofw_get_property(ofw_aliases, "screen", device_name, sizeof(device_name)) <= 0)
239 return false;
240
241 phandle device = ofw_find_device(device_name);
242 if (device == -1)
243 return false;
244
245 if (ofw_get_property(device, "address", &screen->addr, sizeof(screen->addr)) <= 0)
246 return false;
247
248 if (ofw_get_property(device, "width", &screen->width, sizeof(screen->width)) <= 0)
249 return false;
250
251 if (ofw_get_property(device, "height", &screen->height, sizeof(screen->height)) <= 0)
252 return false;
253
254 if (ofw_get_property(device, "depth", &screen->bpp, sizeof(screen->bpp)) <= 0)
255 return false;
256
257 if (ofw_get_property(device, "linebytes", &screen->scanline, sizeof(screen->scanline)) <= 0)
258 return false;
259
260 return true;
261}
Note: See TracBrowser for help on using the repository browser.