Locore.c revision 1.29.16.3 1 /* $NetBSD: Locore.c,v 1.29.16.3 2018/11/26 01:52:26 pgoyette 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 <sys/param.h>
35 #include <lib/libsa/stand.h>
36
37 #include <machine/cpu.h>
38 #include <powerpc/oea/spr.h>
39
40 #include "openfirm.h"
41
42 static int (*openfirmware)(void *);
43
44 static void startup(void *, int, int (*)(void *), char *, int)
45 __attribute__((__used__));
46 static void setup(void);
47
48 #ifdef HEAP_VARIABLE
49 #ifndef HEAP_SIZE
50 #define HEAP_SIZE 0x20000
51 #endif
52 char *heapspace;
53 #endif
54
55 static int stack[8192/4 + 4] __attribute__((__used__));
56
57 #ifdef XCOFF_GLUE
58 __asm(
59 " .text \n"
60 " .globl _entry \n"
61 "_entry: \n"
62 " .long _start,0,0 \n"
63 );
64 #endif /* XCOFF_GLUE */
65
66 __asm(
67 " .text \n"
68 " .globl _start \n"
69 "_start: \n"
70 " sync \n"
71 " isync \n"
72 " lis %r1,stack@ha \n"
73 " addi %r1,%r1,stack@l \n"
74 " addi %r1,%r1,8192 \n"
75 " \n"
76 " mfmsr %r8 \n"
77 " li %r0,0 \n"
78 " mtmsr %r0 \n"
79 " isync \n"
80 " \n"
81 " \n" /* test for 601 */
82 " mfspr %r0,287 \n" /* mfpvbr %r0 PVR = 287 */
83 " srwi %r0,%r0,0x10 \n"
84 " cmplwi %r0,0x02 \n" /* 601 CPU = 0x0001 */
85 " blt 2f \n" /* skip over non-601 BAT setup */
86 " cmplwi %r0,0x39 \n" /* PPC970 */
87 " blt 0f \n"
88 " cmplwi %r0,0x45 \n" /* PPC970GX */
89 " ble 1f \n"
90 /* non PPC 601 BATs */
91 "0: li %r0,0 \n"
92 " mtibatu 0,%r0 \n"
93 " mtibatu 1,%r0 \n"
94 " mtibatu 2,%r0 \n"
95 " mtibatu 3,%r0 \n"
96 " mtdbatu 0,%r0 \n"
97 " mtdbatu 1,%r0 \n"
98 " mtdbatu 2,%r0 \n"
99 " mtdbatu 3,%r0 \n"
100 " \n"
101 " li %r9,0x12 \n" /* BATL(0, BAT_M, BAT_PP_RW) */
102 " mtibatl 0,%r9 \n"
103 " mtdbatl 0,%r9 \n"
104 " li %r9,0x1ffe \n" /* BATU(0, BAT_BL_256M, BAT_Vs) */
105 " mtibatu 0,%r9 \n"
106 " mtdbatu 0,%r9 \n"
107 " b 3f \n"
108 /* 970 initialization stuff */
109 "1: \n"
110 /* make sure we're in bridge mode */
111 " clrldi %r8,%r8,3 \n"
112 " mtmsrd %r8 \n"
113 " isync \n"
114 /* clear HID5 DCBZ bits (56/57), need to do this early */
115 " mfspr %r9,0x3f6 \n"
116 " rldimi %r9,0,6,56 \n"
117 " sync \n"
118 " mtspr 0x3f6,%r9 \n"
119 " isync \n"
120 " sync \n"
121 /* Setup HID1 features, prefetch + i-cacheability controlled by PTE */
122 " mfspr %r9,0x3f1 \n"
123 " li %r11,0x1200 \n"
124 " sldi %r11,%r11,44 \n"
125 " or %r9,%r9,%r11 \n"
126 " mtspr 0x3f1,%r9 \n"
127 " isync \n"
128 " sync \n"
129 " b 3f \n"
130 /* PPC 601 BATs */
131 "2: li %r0,0 \n"
132 " mtibatu 0,%r0 \n"
133 " mtibatu 1,%r0 \n"
134 " mtibatu 2,%r0 \n"
135 " mtibatu 3,%r0 \n"
136 " \n"
137 " li %r9,0x7f \n"
138 " mtibatl 0,%r9 \n"
139 " li %r9,0x1a \n"
140 " mtibatu 0,%r9 \n"
141 " \n"
142 " lis %r9,0x80 \n"
143 " addi %r9,%r9,0x7f \n"
144 " mtibatl 1,%r9 \n"
145 " lis %r9,0x80 \n"
146 " addi %r9,%r9,0x1a \n"
147 " mtibatu 1,%r9 \n"
148 " \n"
149 " lis %r9,0x100 \n"
150 " addi %r9,%r9,0x7f \n"
151 " mtibatl 2,%r9 \n"
152 " lis %r9,0x100 \n"
153 " addi %r9,%r9,0x1a \n"
154 " mtibatu 2,%r9 \n"
155 " \n"
156 " lis %r9,0x180 \n"
157 " addi %r9,%r9,0x7f \n"
158 " mtibatl 3,%r9 \n"
159 " lis %r9,0x180 \n"
160 " addi %r9,%r9,0x1a \n"
161 " mtibatu 3,%r9 \n"
162 " \n"
163 "3: isync \n"
164 " \n"
165 " mtmsr %r8 \n"
166 " isync \n"
167 " \n"
168 /*
169 * Make sure that .bss is zeroed
170 */
171 " \n"
172 " li %r0,0 \n"
173 " lis %r8,_edata@ha \n"
174 " addi %r8,%r8,_edata@l\n"
175 " lis %r9,_end@ha \n"
176 " addi %r9,%r9,_end@l \n"
177 " \n"
178 "5: cmpw 0,%r8,%r9 \n"
179 " bge 6f \n"
180 /*
181 * clear by bytes to avoid ppc601 alignment exceptions
182 */
183 " stb %r0,0(%r8) \n"
184 " stb %r0,1(%r8) \n"
185 " stb %r0,2(%r8) \n"
186 " stb %r0,3(%r8) \n"
187 " addi %r8,%r8,4 \n"
188 " b 5b \n"
189 " \n"
190 "6: b startup \n"
191 );
192
193 #if 0
194 static int
195 openfirmware(void *arg)
196 {
197
198 __asm volatile ("sync; isync");
199 openfirmware_entry(arg);
200 __asm volatile ("sync; isync");
201 }
202 #endif
203
204 static void
205 startup(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl)
206 {
207
208 openfirmware = openfirm;
209 setup();
210 main();
211 OF_exit();
212 }
213
214 #if 0
215 void
216 OF_enter(void)
217 {
218 static struct {
219 const char *name;
220 int nargs;
221 int nreturns;
222 } args = {
223 "enter",
224 0,
225 0
226 };
227
228 openfirmware(&args);
229 }
230 #endif /* OF_enter */
231
232 __dead void
233 OF_exit(void)
234 {
235 static struct {
236 const char *name;
237 int nargs;
238 int nreturns;
239 } args = {
240 "exit",
241 0,
242 0
243 };
244
245 openfirmware(&args);
246 for (;;); /* just in case */
247 }
248
249 int
250 OF_finddevice(const char *name)
251 {
252 static struct {
253 const char *name;
254 int nargs;
255 int nreturns;
256 const char *device;
257 int phandle;
258 } args = {
259 "finddevice",
260 1,
261 1,
262 };
263
264 args.device = name;
265 if (openfirmware(&args) == -1)
266 return -1;
267 return args.phandle;
268 }
269
270 int
271 OF_instance_to_package(int ihandle)
272 {
273 static struct {
274 const char *name;
275 int nargs;
276 int nreturns;
277 int ihandle;
278 int phandle;
279 } args = {
280 "instance-to-package",
281 1,
282 1,
283 };
284
285 args.ihandle = ihandle;
286 if (openfirmware(&args) == -1)
287 return -1;
288 return args.phandle;
289 }
290
291 int
292 OF_getprop(int handle, const char *prop, void *buf, int buflen)
293 {
294 static struct {
295 const char *name;
296 int nargs;
297 int nreturns;
298 int phandle;
299 const char *prop;
300 void *buf;
301 int buflen;
302 int size;
303 } args = {
304 "getprop",
305 4,
306 1,
307 };
308
309 args.phandle = handle;
310 args.prop = prop;
311 args.buf = buf;
312 args.buflen = buflen;
313 if (openfirmware(&args) == -1)
314 return -1;
315 return args.size;
316 }
317
318 #ifdef __notyet__ /* Has a bug on FirePower */
319 int
320 OF_setprop(int handle, const char *prop, void *buf, int len)
321 {
322 static struct {
323 const char *name;
324 int nargs;
325 int nreturns;
326 int phandle;
327 const char *prop;
328 void *buf;
329 int len;
330 int size;
331 } args = {
332 "setprop",
333 4,
334 1,
335 };
336
337 args.phandle = handle;
338 args.prop = prop;
339 args.buf = buf;
340 args.len = len;
341 if (openfirmware(&args) == -1)
342 return -1;
343 return args.size;
344 }
345 #endif
346
347 int
348 OF_open(const char *dname)
349 {
350 static struct {
351 const char *name;
352 int nargs;
353 int nreturns;
354 const char *dname;
355 int handle;
356 } args = {
357 "open",
358 1,
359 1,
360 };
361
362 #ifdef OFW_DEBUG
363 printf("OF_open(%s) -> ", dname);
364 #endif
365 args.dname = dname;
366 if (openfirmware(&args) == -1 ||
367 args.handle == 0) {
368 #ifdef OFW_DEBUG
369 printf("lose\n");
370 #endif
371 return -1;
372 }
373 #ifdef OFW_DEBUG
374 printf("%d\n", args.handle);
375 #endif
376 return args.handle;
377 }
378
379 void
380 OF_close(int handle)
381 {
382 static struct {
383 const char *name;
384 int nargs;
385 int nreturns;
386 int handle;
387 } args = {
388 "close",
389 1,
390 0,
391 };
392
393 #ifdef OFW_DEBUG
394 printf("OF_close(%d)\n", handle);
395 #endif
396 args.handle = handle;
397 openfirmware(&args);
398 }
399
400 int
401 OF_write(int handle, void *addr, int len)
402 {
403 static struct {
404 const char *name;
405 int nargs;
406 int nreturns;
407 int ihandle;
408 void *addr;
409 int len;
410 int actual;
411 } args = {
412 "write",
413 3,
414 1,
415 };
416
417 #ifdef OFW_DEBUG
418 if (len != 1)
419 printf("OF_write(%d, %p, %x) -> ", handle, addr, len);
420 #endif
421 args.ihandle = handle;
422 args.addr = addr;
423 args.len = len;
424 if (openfirmware(&args) == -1) {
425 #ifdef OFW_DEBUG
426 printf("lose\n");
427 #endif
428 return -1;
429 }
430 #ifdef OFW_DEBUG
431 if (len != 1)
432 printf("%x\n", args.actual);
433 #endif
434 return args.actual;
435 }
436
437 int
438 OF_read(int handle, void *addr, int len)
439 {
440 static struct {
441 const char *name;
442 int nargs;
443 int nreturns;
444 int ihandle;
445 void *addr;
446 int len;
447 int actual;
448 } args = {
449 "read",
450 3,
451 1,
452 };
453
454 #ifdef OFW_DEBUG
455 if (len != 1)
456 printf("OF_read(%d, %p, %x) -> ", handle, addr, len);
457 #endif
458 args.ihandle = handle;
459 args.addr = addr;
460 args.len = len;
461 if (openfirmware(&args) == -1) {
462 #ifdef OFW_DEBUG
463 printf("lose\n");
464 #endif
465 return -1;
466 }
467 #ifdef OFW_DEBUG
468 if (len != 1)
469 printf("%x\n", args.actual);
470 #endif
471 return args.actual;
472 }
473
474 int
475 OF_seek(int handle, u_quad_t pos)
476 {
477 static struct {
478 const char *name;
479 int nargs;
480 int nreturns;
481 int handle;
482 int poshi;
483 int poslo;
484 int status;
485 } args = {
486 "seek",
487 3,
488 1,
489 };
490
491 #ifdef OFW_DEBUG
492 printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos);
493 #endif
494 args.handle = handle;
495 args.poshi = (int)(pos >> 32);
496 args.poslo = (int)pos;
497 if (openfirmware(&args) == -1) {
498 #ifdef OFW_DEBUG
499 printf("lose\n");
500 #endif
501 return -1;
502 }
503 #ifdef OFW_DEBUG
504 printf("%d\n", args.status);
505 #endif
506 return args.status;
507 }
508
509 void *
510 OF_claim(void *virt, u_int size, u_int align)
511 {
512 static struct {
513 const char *name;
514 int nargs;
515 int nreturns;
516 void *virt;
517 u_int size;
518 u_int align;
519 void *baseaddr;
520 } args = {
521 "claim",
522 3,
523 1,
524 };
525
526 #ifdef OFW_DEBUG
527 printf("OF_claim(%p, %x, %x) -> ", virt, size, align);
528 #endif
529 args.virt = virt;
530 args.size = size;
531 args.align = align;
532 if (openfirmware(&args) == -1) {
533 #ifdef OFW_DEBUG
534 printf("lose\n");
535 #endif
536 return (void *)-1;
537 }
538 #ifdef OFW_DEBUG
539 printf("%p\n", args.baseaddr);
540 #endif
541 return args.baseaddr;
542 }
543
544 void
545 OF_release(void *virt, u_int size)
546 {
547 static struct {
548 const char *name;
549 int nargs;
550 int nreturns;
551 void *virt;
552 u_int size;
553 } args = {
554 "release",
555 2,
556 0,
557 };
558
559 #ifdef OFW_DEBUG
560 printf("OF_release(%p, %x)\n", virt, size);
561 #endif
562 args.virt = virt;
563 args.size = size;
564 openfirmware(&args);
565 }
566
567 int
568 OF_milliseconds(void)
569 {
570 static struct {
571 const char *name;
572 int nargs;
573 int nreturns;
574 int ms;
575 } args = {
576 "milliseconds",
577 0,
578 1,
579 };
580
581 openfirmware(&args);
582 return args.ms;
583 }
584
585 #ifdef __notyet__
586 void
587 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
588 {
589 static struct {
590 const char *name;
591 int nargs;
592 int nreturns;
593 void *virt;
594 u_int size;
595 void (*entry)();
596 void *arg;
597 u_int len;
598 } args = {
599 "chain",
600 5,
601 0,
602 };
603
604 args.virt = virt;
605 args.size = size;
606 args.entry = entry;
607 args.arg = arg;
608 args.len = len;
609 openfirmware(&args);
610 }
611 #else
612 void
613 OF_chain(void *virt, u_int size, boot_entry_t entry, void *arg, u_int len)
614 {
615 /*
616 * This is a REALLY dirty hack till the firmware gets this going
617 */
618 #if 0
619 OF_release(virt, size);
620 #endif
621 entry(0, 0, openfirmware, arg, len);
622 }
623 #endif
624
625 int
626 OF_call_method(const char *method, int ihandle, int nargs, int nreturns, ...)
627 {
628 va_list ap;
629 static struct {
630 const char *name;
631 int nargs;
632 int nreturns;
633 const char *method;
634 int ihandle;
635 int args_n_results[12];
636 } args = {
637 "call-method",
638 2,
639 1,
640 };
641 int *ip, n;
642
643 if (nargs > 6)
644 return -1;
645 args.nargs = nargs + 2;
646 args.nreturns = nreturns + 1;
647 args.method = method;
648 args.ihandle = ihandle;
649 va_start(ap, nreturns);
650 for (ip = args.args_n_results + (n = nargs); --n >= 0;)
651 *--ip = va_arg(ap, int);
652
653 if (openfirmware(&args) == -1) {
654 va_end(ap);
655 return -1;
656 }
657 if (args.args_n_results[nargs]) {
658 va_end(ap);
659 return args.args_n_results[nargs];
660 }
661 for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
662 *va_arg(ap, int *) = *--ip;
663 va_end(ap);
664 return 0;
665 }
666
667 static int stdin;
668 static int stdout;
669
670 static void
671 setup(void)
672 {
673 int chosen;
674
675 if ((chosen = OF_finddevice("/chosen")) == -1)
676 OF_exit();
677 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) !=
678 sizeof(stdin) ||
679 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) !=
680 sizeof(stdout))
681 OF_exit();
682
683 #ifdef HEAP_VARIABLE
684 uint32_t pvr, vers, hsize = HEAP_SIZE;
685
686 __asm volatile ("mfpvr %0" : "=r"(pvr));
687 vers = pvr >> 16;
688 if (vers >= IBM970 && vers <= IBM970GX) hsize = 0x800000;
689
690 heapspace = OF_claim(0, hsize, NBPG);
691 if (heapspace == (char *)-1) {
692 panic("Failed to allocate heap");
693 }
694
695 setheap(heapspace, heapspace + HEAP_SIZE);
696 #endif /* HEAP_VARIABLE */
697 }
698
699 void
700 putchar(int c)
701 {
702 char ch = c;
703
704 if (c == '\n')
705 putchar('\r');
706 OF_write(stdout, &ch, 1);
707 }
708
709 int
710 getchar(void)
711 {
712 unsigned char ch = '\0';
713 int l;
714
715 while ((l = OF_read(stdin, &ch, 1)) != 1)
716 if (l != -2 && l != 0)
717 return -1;
718 return ch;
719 }
720