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