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