Locore.c revision 1.24 1 /* $NetBSD: Locore.c,v 1.24 2011/07/17 20:54:43 joerg 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 "openfirm.h"
39
40 static int (*openfirmware)(void *);
41
42 static void startup(void *, int, int (*)(void *), char *, int)
43 __attribute__((__used__));
44 static void setup(void);
45
46 static int stack[8192/4 + 4] __attribute__((__used__));
47
48 #ifdef XCOFF_GLUE
49 __asm(
50 " .text \n"
51 " .globl _entry \n"
52 "_entry: \n"
53 " .long _start,0,0 \n"
54 );
55 #endif /* XCOFF_GLUE */
56
57 __asm(
58 " .text \n"
59 " .globl _start \n"
60 "_start: \n"
61 " sync \n"
62 " isync \n"
63 " lis %r1,stack@ha \n"
64 " addi %r1,%r1,stack@l \n"
65 " addi %r1,%r1,8192 \n"
66 " \n"
67 " mfmsr %r8 \n"
68 " li %r0,0 \n"
69 " mtmsr %r0 \n"
70 " isync \n"
71 " \n"
72 " mtibatu 0,%r0 \n"
73 " mtibatu 1,%r0 \n"
74 " mtibatu 2,%r0 \n"
75 " mtibatu 3,%r0 \n"
76 " mtdbatu 0,%r0 \n"
77 " mtdbatu 1,%r0 \n"
78 " mtdbatu 2,%r0 \n"
79 " mtdbatu 3,%r0 \n"
80 " \n"
81 " li %r9,0x12 \n" /* BATL(0, BAT_M, BAT_PP_RW) */
82 " mtibatl 0,%r9 \n"
83 " mtdbatl 0,%r9 \n"
84 " li %r9,0x1ffe \n" /* BATU(0, BAT_BL_256M, BAT_Vs) */
85 " mtibatu 0,%r9 \n"
86 " mtdbatu 0,%r9 \n"
87 " isync \n"
88 " \n"
89 " mtmsr %r8 \n"
90 " isync \n"
91 " \n"
92 /*
93 * Make sure that .bss is zeroed
94 */
95 " \n"
96 " li %r0,0 \n"
97 " lis %r8,_edata@ha \n"
98 " addi %r8,%r8,_edata@l\n"
99 " lis %r9,_end@ha \n"
100 " addi %r9,%r9,_end@l \n"
101 " \n"
102 "5: cmpw 0,%r8,%r9 \n"
103 " bge 6f \n"
104 " stw %r0,0(%r8) \n"
105 " addi %r8,%r8,4 \n"
106 " b 5b \n"
107 " \n"
108 "6: b startup \n"
109 );
110
111 #if 0
112 static int
113 openfirmware(void *arg)
114 {
115
116 __asm volatile ("sync; isync");
117 openfirmware_entry(arg);
118 __asm volatile ("sync; isync");
119 }
120 #endif
121
122 static void
123 startup(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl)
124 {
125
126 openfirmware = openfirm;
127 setup();
128 main();
129 OF_exit();
130 }
131
132 __dead void
133 OF_exit(void)
134 {
135 static struct {
136 const char *name;
137 int nargs;
138 int nreturns;
139 } args = {
140 "exit",
141 0,
142 0
143 };
144
145 openfirmware(&args);
146 for (;;); /* just in case */
147 }
148
149 int
150 OF_finddevice(const char *name)
151 {
152 static struct {
153 const char *name;
154 int nargs;
155 int nreturns;
156 const char *device;
157 int phandle;
158 } args = {
159 "finddevice",
160 1,
161 1,
162 };
163
164 args.device = name;
165 if (openfirmware(&args) == -1)
166 return -1;
167 return args.phandle;
168 }
169
170 int
171 OF_instance_to_package(int ihandle)
172 {
173 static struct {
174 const char *name;
175 int nargs;
176 int nreturns;
177 int ihandle;
178 int phandle;
179 } args = {
180 "instance-to-package",
181 1,
182 1,
183 };
184
185 args.ihandle = ihandle;
186 if (openfirmware(&args) == -1)
187 return -1;
188 return args.phandle;
189 }
190
191 int
192 OF_getprop(int handle, const char *prop, void *buf, int buflen)
193 {
194 static struct {
195 const char *name;
196 int nargs;
197 int nreturns;
198 int phandle;
199 const char *prop;
200 void *buf;
201 int buflen;
202 int size;
203 } args = {
204 "getprop",
205 4,
206 1,
207 };
208
209 args.phandle = handle;
210 args.prop = prop;
211 args.buf = buf;
212 args.buflen = buflen;
213 if (openfirmware(&args) == -1)
214 return -1;
215 return args.size;
216 }
217
218 #ifdef __notyet__ /* Has a bug on FirePower */
219 int
220 OF_setprop(int handle, const char *prop, void *buf, int len)
221 {
222 static struct {
223 const char *name;
224 int nargs;
225 int nreturns;
226 int phandle;
227 const char *prop;
228 void *buf;
229 int len;
230 int size;
231 } args = {
232 "setprop",
233 4,
234 1,
235 };
236
237 args.phandle = handle;
238 args.prop = prop;
239 args.buf = buf;
240 args.len = len;
241 if (openfirmware(&args) == -1)
242 return -1;
243 return args.size;
244 }
245 #endif
246
247 int
248 OF_open(const char *dname)
249 {
250 static struct {
251 const char *name;
252 int nargs;
253 int nreturns;
254 const char *dname;
255 int handle;
256 } args = {
257 "open",
258 1,
259 1,
260 };
261
262 #ifdef OFW_DEBUG
263 printf("OF_open(%s) -> ", dname);
264 #endif
265 args.dname = dname;
266 if (openfirmware(&args) == -1 ||
267 args.handle == 0) {
268 #ifdef OFW_DEBUG
269 printf("lose\n");
270 #endif
271 return -1;
272 }
273 #ifdef OFW_DEBUG
274 printf("%d\n", args.handle);
275 #endif
276 return args.handle;
277 }
278
279 void
280 OF_close(int handle)
281 {
282 static struct {
283 const char *name;
284 int nargs;
285 int nreturns;
286 int handle;
287 } args = {
288 "close",
289 1,
290 0,
291 };
292
293 #ifdef OFW_DEBUG
294 printf("OF_close(%d)\n", handle);
295 #endif
296 args.handle = handle;
297 openfirmware(&args);
298 }
299
300 int
301 OF_write(int handle, void *addr, int len)
302 {
303 static struct {
304 const char *name;
305 int nargs;
306 int nreturns;
307 int ihandle;
308 void *addr;
309 int len;
310 int actual;
311 } args = {
312 "write",
313 3,
314 1,
315 };
316
317 #ifdef OFW_DEBUG
318 if (len != 1)
319 printf("OF_write(%d, %p, %x) -> ", handle, addr, len);
320 #endif
321 args.ihandle = handle;
322 args.addr = addr;
323 args.len = len;
324 if (openfirmware(&args) == -1) {
325 #ifdef OFW_DEBUG
326 printf("lose\n");
327 #endif
328 return -1;
329 }
330 #ifdef OFW_DEBUG
331 if (len != 1)
332 printf("%x\n", args.actual);
333 #endif
334 return args.actual;
335 }
336
337 int
338 OF_read(int handle, void *addr, int len)
339 {
340 static struct {
341 const char *name;
342 int nargs;
343 int nreturns;
344 int ihandle;
345 void *addr;
346 int len;
347 int actual;
348 } args = {
349 "read",
350 3,
351 1,
352 };
353
354 #ifdef OFW_DEBUG
355 if (len != 1)
356 printf("OF_read(%d, %p, %x) -> ", handle, addr, len);
357 #endif
358 args.ihandle = handle;
359 args.addr = addr;
360 args.len = len;
361 if (openfirmware(&args) == -1) {
362 #ifdef OFW_DEBUG
363 printf("lose\n");
364 #endif
365 return -1;
366 }
367 #ifdef OFW_DEBUG
368 if (len != 1)
369 printf("%x\n", args.actual);
370 #endif
371 return args.actual;
372 }
373
374 int
375 OF_seek(int handle, u_quad_t pos)
376 {
377 static struct {
378 const char *name;
379 int nargs;
380 int nreturns;
381 int handle;
382 int poshi;
383 int poslo;
384 int status;
385 } args = {
386 "seek",
387 3,
388 1,
389 };
390
391 #ifdef OFW_DEBUG
392 printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos);
393 #endif
394 args.handle = handle;
395 args.poshi = (int)(pos >> 32);
396 args.poslo = (int)pos;
397 if (openfirmware(&args) == -1) {
398 #ifdef OFW_DEBUG
399 printf("lose\n");
400 #endif
401 return -1;
402 }
403 #ifdef OFW_DEBUG
404 printf("%d\n", args.status);
405 #endif
406 return args.status;
407 }
408
409 void *
410 OF_claim(void *virt, u_int size, u_int align)
411 {
412 static struct {
413 const char *name;
414 int nargs;
415 int nreturns;
416 void *virt;
417 u_int size;
418 u_int align;
419 void *baseaddr;
420 } args = {
421 "claim",
422 3,
423 1,
424 };
425
426 #ifdef OFW_DEBUG
427 printf("OF_claim(%p, %x, %x) -> ", virt, size, align);
428 #endif
429 args.virt = virt;
430 args.size = size;
431 args.align = align;
432 if (openfirmware(&args) == -1) {
433 #ifdef OFW_DEBUG
434 printf("lose\n");
435 #endif
436 return (void *)-1;
437 }
438 #ifdef OFW_DEBUG
439 printf("%p\n", args.baseaddr);
440 #endif
441 return args.baseaddr;
442 }
443
444 void
445 OF_release(void *virt, u_int size)
446 {
447 static struct {
448 const char *name;
449 int nargs;
450 int nreturns;
451 void *virt;
452 u_int size;
453 } args = {
454 "release",
455 2,
456 0,
457 };
458
459 #ifdef OFW_DEBUG
460 printf("OF_release(%p, %x)\n", virt, size);
461 #endif
462 args.virt = virt;
463 args.size = size;
464 openfirmware(&args);
465 }
466
467 int
468 OF_milliseconds(void)
469 {
470 static struct {
471 const char *name;
472 int nargs;
473 int nreturns;
474 int ms;
475 } args = {
476 "milliseconds",
477 0,
478 1,
479 };
480
481 openfirmware(&args);
482 return args.ms;
483 }
484
485 #ifdef __notyet__
486 void
487 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
488 {
489 static struct {
490 const char *name;
491 int nargs;
492 int nreturns;
493 void *virt;
494 u_int size;
495 void (*entry)();
496 void *arg;
497 u_int len;
498 } args = {
499 "chain",
500 5,
501 0,
502 };
503
504 args.virt = virt;
505 args.size = size;
506 args.entry = entry;
507 args.arg = arg;
508 args.len = len;
509 openfirmware(&args);
510 }
511 #else
512 void
513 OF_chain(void *virt, u_int size, boot_entry_t entry, void *arg, u_int len)
514 {
515 /*
516 * This is a REALLY dirty hack till the firmware gets this going
517 */
518 #if 0
519 OF_release(virt, size);
520 #endif
521 entry(0, 0, openfirmware, arg, len);
522 }
523 #endif
524
525 int
526 OF_call_method(const char *method, int ihandle, int nargs, int nreturns, ...)
527 {
528 va_list ap;
529 static struct {
530 const char *name;
531 int nargs;
532 int nreturns;
533 const char *method;
534 int ihandle;
535 int args_n_results[12];
536 } args = {
537 "call-method",
538 2,
539 1,
540 };
541 int *ip, n;
542
543 if (nargs > 6)
544 return -1;
545 args.nargs = nargs + 2;
546 args.nreturns = nreturns + 1;
547 args.method = method;
548 args.ihandle = ihandle;
549 va_start(ap, nreturns);
550 for (ip = args.args_n_results + (n = nargs); --n >= 0;)
551 *--ip = va_arg(ap, int);
552
553 if (openfirmware(&args) == -1) {
554 va_end(ap);
555 return -1;
556 }
557 if (args.args_n_results[nargs]) {
558 va_end(ap);
559 return args.args_n_results[nargs];
560 }
561 for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
562 *va_arg(ap, int *) = *--ip;
563 va_end(ap);
564 return 0;
565 }
566
567 static int stdin;
568 static int stdout;
569
570 static void
571 setup(void)
572 {
573 int chosen;
574
575 if ((chosen = OF_finddevice("/chosen")) == -1)
576 OF_exit();
577 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) !=
578 sizeof(stdin) ||
579 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) !=
580 sizeof(stdout))
581 OF_exit();
582 }
583
584 void
585 putchar(int c)
586 {
587 char ch = c;
588
589 if (c == '\n')
590 putchar('\r');
591 OF_write(stdout, &ch, 1);
592 }
593
594 int
595 getchar(void)
596 {
597 unsigned char ch = '\0';
598 int l;
599
600 while ((l = OF_read(stdin, &ch, 1)) != 1)
601 if (l != -2 && l != 0)
602 return -1;
603 return ch;
604 }
605