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