1 /* $NetBSD: Locore.c,v 1.4 2009/03/14 15:36:14 dsl Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <lib/libsa/stand.h>
35
36 #include <machine/cpu.h>
37
38 #include <arm/armreg.h>
39
40 #include "cache.h"
41 #include "extern.h"
42 #include "openfirm.h"
43
44 static int (*openfirmware_entry)(void *);
45 static int openfirmware(void *);
46
47 void startup(int (*)(void *), char *, int);
48 static void setup(void);
49
50 void (*cache_syncI)(void);
51
52 void abort(void);
abort(void)53 void abort(void)
54 {
55
56 /* Stupid compiler (__dead). */
57 for (;;)
58 continue;
59 }
60
61 static int
openfirmware(void * arg)62 openfirmware(void *arg)
63 {
64
65 (*openfirmware_entry)(arg);
66 return 0;
67 }
68
69 static vaddr_t
ofw_getcleaninfo(void)70 ofw_getcleaninfo(void)
71 {
72 int cpu, vclean;
73
74 if ((cpu = OF_finddevice("/cpu")) == -1)
75 panic("no /cpu from OFW");
76
77 if (OF_getprop(cpu, "d-cache-flush-address", &vclean,
78 sizeof(vclean)) != sizeof(vclean)) {
79 printf("WARNING: no OFW d-cache-flush-address property\n");
80 return (RELOC);
81 }
82
83 return (of_decode_int((unsigned char *)&vclean));
84 }
85
86 void
startup(int (* openfirm)(void *),char * arg,int argl)87 startup(int (*openfirm)(void *), char *arg, int argl)
88 {
89 u_int cputype = cpufunc_id() & CPU_ID_CPU_MASK;
90
91 openfirmware_entry = openfirm;
92 setup();
93
94 /*
95 * Determine the CPU type, and set up the appropriate
96 * I$ sync routine.
97 */
98 if (cputype == CPU_ID_SA110 || cputype == CPU_ID_SA1100 ||
99 cputype == CPU_ID_SA1110) {
100 extern vaddr_t sa110_cache_clean_addr;
101 cache_syncI = sa110_cache_syncI;
102 sa110_cache_clean_addr = ofw_getcleaninfo();
103 } else {
104 printf("WARNING: no I$ sync routine for CPU 0x%x\n",
105 cputype);
106 }
107
108 main();
109 OF_exit();
110 }
111
112 int
of_decode_int(const u_char * p)113 of_decode_int(const u_char *p)
114 {
115 unsigned int i = *p++ << 8;
116 i = (i + *p++) << 8;
117 i = (i + *p++) << 8;
118 return (i + *p);
119 }
120
121 __dead void
OF_exit(void)122 OF_exit(void)
123 {
124 static struct {
125 const char *name;
126 int nargs;
127 int nreturns;
128 } args = {
129 "exit",
130 0,
131 0
132 };
133
134 openfirmware(&args);
135 for (;;); /* just in case */
136 }
137
138 int
OF_finddevice(const char * name)139 OF_finddevice(const char *name)
140 {
141 static struct {
142 const char *name;
143 int nargs;
144 int nreturns;
145 const char *device;
146 int phandle;
147 } args = {
148 "finddevice",
149 1,
150 1,
151 };
152
153 args.device = name;
154 if (openfirmware(&args) == -1)
155 return -1;
156 return args.phandle;
157 }
158
159 int
OF_instance_to_package(int ihandle)160 OF_instance_to_package(int ihandle)
161 {
162 static struct {
163 const char *name;
164 int nargs;
165 int nreturns;
166 int ihandle;
167 int phandle;
168 } args = {
169 "instance-to-package",
170 1,
171 1,
172 };
173
174 args.ihandle = ihandle;
175 if (openfirmware(&args) == -1)
176 return -1;
177 return args.phandle;
178 }
179
180 int
OF_getprop(int handle,const char * prop,void * buf,int buflen)181 OF_getprop(int handle, const char *prop, void *buf, int buflen)
182 {
183 static struct {
184 const char *name;
185 int nargs;
186 int nreturns;
187 int phandle;
188 const char *prop;
189 void *buf;
190 int buflen;
191 int size;
192 } args = {
193 "getprop",
194 4,
195 1,
196 };
197
198 args.phandle = handle;
199 args.prop = prop;
200 args.buf = buf;
201 args.buflen = buflen;
202 if (openfirmware(&args) == -1)
203 return -1;
204 return args.size;
205 }
206
207 #ifdef __notyet__ /* Has a bug on FirePower */
208 int
OF_setprop(int handle,const char * prop,void * buf,int len)209 OF_setprop(int handle, const char *prop, void *buf, int len)
210 {
211 static struct {
212 const char *name;
213 int nargs;
214 int nreturns;
215 int phandle;
216 const char *prop;
217 void *buf;
218 int len;
219 int size;
220 } args = {
221 "setprop",
222 4,
223 1,
224 };
225
226 args.phandle = handle;
227 args.prop = prop;
228 args.buf = buf;
229 args.len = len;
230 if (openfirmware(&args) == -1)
231 return -1;
232 return args.size;
233 }
234 #endif
235
236 int
OF_open(char * dname)237 OF_open(char *dname)
238 {
239 static struct {
240 const char *name;
241 int nargs;
242 int nreturns;
243 char *dname;
244 int handle;
245 } args = {
246 "open",
247 1,
248 1,
249 };
250
251 #ifdef OFW_DEBUG
252 printf("OF_open(%s) -> ", dname);
253 #endif
254 args.dname = dname;
255 if (openfirmware(&args) == -1 ||
256 args.handle == 0) {
257 #ifdef OFW_DEBUG
258 printf("lose\n");
259 #endif
260 return -1;
261 }
262 #ifdef OFW_DEBUG
263 printf("%d\n", args.handle);
264 #endif
265 return args.handle;
266 }
267
268 void
OF_close(int handle)269 OF_close(int handle)
270 {
271 static struct {
272 const char *name;
273 int nargs;
274 int nreturns;
275 int handle;
276 } args = {
277 "close",
278 1,
279 0,
280 };
281
282 #ifdef OFW_DEBUG
283 printf("OF_close(%d)\n", handle);
284 #endif
285 args.handle = handle;
286 openfirmware(&args);
287 }
288
289 int
OF_write(int handle,void * addr,int len)290 OF_write(int handle, void *addr, int len)
291 {
292 static struct {
293 const char *name;
294 int nargs;
295 int nreturns;
296 int ihandle;
297 void *addr;
298 int len;
299 int actual;
300 } args = {
301 "write",
302 3,
303 1,
304 };
305
306 #ifdef OFW_DEBUG
307 if (len != 1)
308 printf("OF_write(%d, %x, %x) -> ", handle, addr, len);
309 #endif
310 args.ihandle = handle;
311 args.addr = addr;
312 args.len = len;
313 if (openfirmware(&args) == -1) {
314 #ifdef OFW_DEBUG
315 printf("lose\n");
316 #endif
317 return -1;
318 }
319 #ifdef OFW_DEBUG
320 if (len != 1)
321 printf("%x\n", args.actual);
322 #endif
323 return args.actual;
324 }
325
326 int
OF_read(int handle,void * addr,int len)327 OF_read(int handle, void *addr, int len)
328 {
329 static struct {
330 const char *name;
331 int nargs;
332 int nreturns;
333 int ihandle;
334 void *addr;
335 int len;
336 int actual;
337 } args = {
338 "read",
339 3,
340 1,
341 };
342
343 #ifdef OFW_DEBUG
344 if (len != 1)
345 printf("OF_read(%d, %x, %x) -> ", handle, addr, len);
346 #endif
347 args.ihandle = handle;
348 args.addr = addr;
349 args.len = len;
350 if (openfirmware(&args) == -1) {
351 #ifdef OFW_DEBUG
352 printf("lose\n");
353 #endif
354 return -1;
355 }
356 #ifdef OFW_DEBUG
357 if (len != 1)
358 printf("%x\n", args.actual);
359 #endif
360 return args.actual;
361 }
362
363 int
OF_seek(int handle,u_quad_t pos)364 OF_seek(int handle, u_quad_t pos)
365 {
366 static struct {
367 const char *name;
368 int nargs;
369 int nreturns;
370 int handle;
371 int poshi;
372 int poslo;
373 int status;
374 } args = {
375 "seek",
376 3,
377 1,
378 };
379
380 #ifdef OFW_DEBUG
381 printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos);
382 #endif
383 args.handle = handle;
384 args.poshi = (int)(pos >> 32);
385 args.poslo = (int)pos;
386 if (openfirmware(&args) == -1) {
387 #ifdef OFW_DEBUG
388 printf("lose\n");
389 #endif
390 return -1;
391 }
392 #ifdef OFW_DEBUG
393 printf("%d\n", args.status);
394 #endif
395 return args.status;
396 }
397
398 void *
OF_claim(void * virt,u_int size,u_int align)399 OF_claim(void *virt, u_int size, u_int align)
400 {
401 static struct {
402 const char *name;
403 int nargs;
404 int nreturns;
405 void *virt;
406 u_int size;
407 u_int align;
408 void *baseaddr;
409 } args = {
410 "claim",
411 3,
412 1,
413 };
414
415 #ifdef OFW_DEBUG
416 printf("OF_claim(%x, %x, %x) -> ", virt, size, align);
417 #endif
418 args.virt = virt;
419 args.size = size;
420 args.align = align;
421 if (openfirmware(&args) == -1) {
422 #ifdef OFW_DEBUG
423 printf("lose\n");
424 #endif
425 return (void *)-1;
426 }
427 #ifdef OFW_DEBUG
428 printf("%x\n", args.baseaddr);
429 #endif
430 return args.baseaddr;
431 }
432
433 void
OF_release(void * virt,u_int size)434 OF_release(void *virt, u_int size)
435 {
436 static struct {
437 const char *name;
438 int nargs;
439 int nreturns;
440 void *virt;
441 u_int size;
442 } args = {
443 "release",
444 2,
445 0,
446 };
447
448 #ifdef OFW_DEBUG
449 printf("OF_release(%x, %x)\n", virt, size);
450 #endif
451 args.virt = virt;
452 args.size = size;
453 openfirmware(&args);
454 }
455
456 int
OF_milliseconds(void)457 OF_milliseconds(void)
458 {
459 static struct {
460 const char *name;
461 int nargs;
462 int nreturns;
463 int ms;
464 } args = {
465 "milliseconds",
466 0,
467 1,
468 };
469
470 openfirmware(&args);
471 return args.ms;
472 }
473
474 void
OF_chain(void * virt,u_int size,void (* entry)(int (*)(void *),void *,u_int),void * arg,u_int len)475 OF_chain(void *virt, u_int size, void (*entry)(int (*)(void *), void *, u_int),
476 void *arg, u_int len)
477 {
478 struct {
479 const char *name;
480 int nargs;
481 int nreturns;
482 void *virt;
483 u_int size;
484 void (*entry)(int (*)(void *), void *, u_int);
485 void *arg;
486 u_int len;
487 } args;
488
489 args.name = "chain";
490 args.nargs = 5;
491 args.nreturns = 0;
492 args.virt = virt;
493 args.size = size;
494 args.entry = entry;
495 args.arg = arg;
496 args.len = len;
497 #if 1
498 openfirmware(&args);
499 #else
500 entry(openfirmware_entry, arg, len);
501 #endif
502 }
503
504 static int stdin;
505 static int stdout;
506
507 static void
setup(void)508 setup(void)
509 {
510 u_char buf[sizeof(int)];
511 int chosen;
512
513 if ((chosen = OF_finddevice("/chosen")) == -1)
514 OF_exit();
515
516 if (OF_getprop(chosen, "stdin", buf, sizeof(buf)) != sizeof(buf))
517 OF_exit();
518 stdin = of_decode_int(buf);
519
520 if (OF_getprop(chosen, "stdout", buf, sizeof(buf)) != sizeof(buf))
521 OF_exit();
522 stdout = of_decode_int(buf);
523 }
524
525 void
putchar(int c)526 putchar(int c)
527 {
528 char ch = c;
529
530 if (c == '\n')
531 putchar('\r');
532 OF_write(stdout, &ch, 1);
533 }
534
535 int
getchar(void)536 getchar(void)
537 {
538 unsigned char ch = '\0';
539 int l;
540
541 while ((l = OF_read(stdin, &ch, 1)) != 1)
542 if (l != -2 && l != 0)
543 return -1;
544 return ch;
545 }
546