Locore.c revision 1.29.16.2 1 /* $NetBSD: Locore.c,v 1.29.16.2 2018/09/06 06:55:37 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 " cmpi 0,1,%r0,0x02 \n" /* 601 CPU = 0x0001 */
85 " blt 2f \n" /* skip over non-601 BAT setup */
86 " cmpi 0,1,%r0,0x39 \n" /* PPC970 */
87 " blt 0f \n"
88 " cmpi 0,1,%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 " stw %r0,0(%r8) \n"
181 " addi %r8,%r8,4 \n"
182 " b 5b \n"
183 " \n"
184 "6: b startup \n"
185 );
186
187 #if 0
188 static int
189 openfirmware(void *arg)
190 {
191
192 __asm volatile ("sync; isync");
193 openfirmware_entry(arg);
194 __asm volatile ("sync; isync");
195 }
196 #endif
197
198 static void
199 startup(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl)
200 {
201
202 openfirmware = openfirm;
203 setup();
204 main();
205 OF_exit();
206 }
207
208 #if 0
209 void
210 OF_enter(void)
211 {
212 static struct {
213 const char *name;
214 int nargs;
215 int nreturns;
216 } args = {
217 "enter",
218 0,
219 0
220 };
221
222 openfirmware(&args);
223 }
224 #endif /* OF_enter */
225
226 __dead void
227 OF_exit(void)
228 {
229 static struct {
230 const char *name;
231 int nargs;
232 int nreturns;
233 } args = {
234 "exit",
235 0,
236 0
237 };
238
239 openfirmware(&args);
240 for (;;); /* just in case */
241 }
242
243 int
244 OF_finddevice(const char *name)
245 {
246 static struct {
247 const char *name;
248 int nargs;
249 int nreturns;
250 const char *device;
251 int phandle;
252 } args = {
253 "finddevice",
254 1,
255 1,
256 };
257
258 args.device = name;
259 if (openfirmware(&args) == -1)
260 return -1;
261 return args.phandle;
262 }
263
264 int
265 OF_instance_to_package(int ihandle)
266 {
267 static struct {
268 const char *name;
269 int nargs;
270 int nreturns;
271 int ihandle;
272 int phandle;
273 } args = {
274 "instance-to-package",
275 1,
276 1,
277 };
278
279 args.ihandle = ihandle;
280 if (openfirmware(&args) == -1)
281 return -1;
282 return args.phandle;
283 }
284
285 int
286 OF_getprop(int handle, const char *prop, void *buf, int buflen)
287 {
288 static struct {
289 const char *name;
290 int nargs;
291 int nreturns;
292 int phandle;
293 const char *prop;
294 void *buf;
295 int buflen;
296 int size;
297 } args = {
298 "getprop",
299 4,
300 1,
301 };
302
303 args.phandle = handle;
304 args.prop = prop;
305 args.buf = buf;
306 args.buflen = buflen;
307 if (openfirmware(&args) == -1)
308 return -1;
309 return args.size;
310 }
311
312 #ifdef __notyet__ /* Has a bug on FirePower */
313 int
314 OF_setprop(int handle, const char *prop, void *buf, int len)
315 {
316 static struct {
317 const char *name;
318 int nargs;
319 int nreturns;
320 int phandle;
321 const char *prop;
322 void *buf;
323 int len;
324 int size;
325 } args = {
326 "setprop",
327 4,
328 1,
329 };
330
331 args.phandle = handle;
332 args.prop = prop;
333 args.buf = buf;
334 args.len = len;
335 if (openfirmware(&args) == -1)
336 return -1;
337 return args.size;
338 }
339 #endif
340
341 int
342 OF_open(const char *dname)
343 {
344 static struct {
345 const char *name;
346 int nargs;
347 int nreturns;
348 const char *dname;
349 int handle;
350 } args = {
351 "open",
352 1,
353 1,
354 };
355
356 #ifdef OFW_DEBUG
357 printf("OF_open(%s) -> ", dname);
358 #endif
359 args.dname = dname;
360 if (openfirmware(&args) == -1 ||
361 args.handle == 0) {
362 #ifdef OFW_DEBUG
363 printf("lose\n");
364 #endif
365 return -1;
366 }
367 #ifdef OFW_DEBUG
368 printf("%d\n", args.handle);
369 #endif
370 return args.handle;
371 }
372
373 void
374 OF_close(int handle)
375 {
376 static struct {
377 const char *name;
378 int nargs;
379 int nreturns;
380 int handle;
381 } args = {
382 "close",
383 1,
384 0,
385 };
386
387 #ifdef OFW_DEBUG
388 printf("OF_close(%d)\n", handle);
389 #endif
390 args.handle = handle;
391 openfirmware(&args);
392 }
393
394 int
395 OF_write(int handle, void *addr, int len)
396 {
397 static struct {
398 const char *name;
399 int nargs;
400 int nreturns;
401 int ihandle;
402 void *addr;
403 int len;
404 int actual;
405 } args = {
406 "write",
407 3,
408 1,
409 };
410
411 #ifdef OFW_DEBUG
412 if (len != 1)
413 printf("OF_write(%d, %p, %x) -> ", handle, addr, len);
414 #endif
415 args.ihandle = handle;
416 args.addr = addr;
417 args.len = len;
418 if (openfirmware(&args) == -1) {
419 #ifdef OFW_DEBUG
420 printf("lose\n");
421 #endif
422 return -1;
423 }
424 #ifdef OFW_DEBUG
425 if (len != 1)
426 printf("%x\n", args.actual);
427 #endif
428 return args.actual;
429 }
430
431 int
432 OF_read(int handle, void *addr, int len)
433 {
434 static struct {
435 const char *name;
436 int nargs;
437 int nreturns;
438 int ihandle;
439 void *addr;
440 int len;
441 int actual;
442 } args = {
443 "read",
444 3,
445 1,
446 };
447
448 #ifdef OFW_DEBUG
449 if (len != 1)
450 printf("OF_read(%d, %p, %x) -> ", handle, addr, len);
451 #endif
452 args.ihandle = handle;
453 args.addr = addr;
454 args.len = len;
455 if (openfirmware(&args) == -1) {
456 #ifdef OFW_DEBUG
457 printf("lose\n");
458 #endif
459 return -1;
460 }
461 #ifdef OFW_DEBUG
462 if (len != 1)
463 printf("%x\n", args.actual);
464 #endif
465 return args.actual;
466 }
467
468 int
469 OF_seek(int handle, u_quad_t pos)
470 {
471 static struct {
472 const char *name;
473 int nargs;
474 int nreturns;
475 int handle;
476 int poshi;
477 int poslo;
478 int status;
479 } args = {
480 "seek",
481 3,
482 1,
483 };
484
485 #ifdef OFW_DEBUG
486 printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos);
487 #endif
488 args.handle = handle;
489 args.poshi = (int)(pos >> 32);
490 args.poslo = (int)pos;
491 if (openfirmware(&args) == -1) {
492 #ifdef OFW_DEBUG
493 printf("lose\n");
494 #endif
495 return -1;
496 }
497 #ifdef OFW_DEBUG
498 printf("%d\n", args.status);
499 #endif
500 return args.status;
501 }
502
503 void *
504 OF_claim(void *virt, u_int size, u_int align)
505 {
506 static struct {
507 const char *name;
508 int nargs;
509 int nreturns;
510 void *virt;
511 u_int size;
512 u_int align;
513 void *baseaddr;
514 } args = {
515 "claim",
516 3,
517 1,
518 };
519
520 #ifdef OFW_DEBUG
521 printf("OF_claim(%p, %x, %x) -> ", virt, size, align);
522 #endif
523 args.virt = virt;
524 args.size = size;
525 args.align = align;
526 if (openfirmware(&args) == -1) {
527 #ifdef OFW_DEBUG
528 printf("lose\n");
529 #endif
530 return (void *)-1;
531 }
532 #ifdef OFW_DEBUG
533 printf("%p\n", args.baseaddr);
534 #endif
535 return args.baseaddr;
536 }
537
538 void
539 OF_release(void *virt, u_int size)
540 {
541 static struct {
542 const char *name;
543 int nargs;
544 int nreturns;
545 void *virt;
546 u_int size;
547 } args = {
548 "release",
549 2,
550 0,
551 };
552
553 #ifdef OFW_DEBUG
554 printf("OF_release(%p, %x)\n", virt, size);
555 #endif
556 args.virt = virt;
557 args.size = size;
558 openfirmware(&args);
559 }
560
561 int
562 OF_milliseconds(void)
563 {
564 static struct {
565 const char *name;
566 int nargs;
567 int nreturns;
568 int ms;
569 } args = {
570 "milliseconds",
571 0,
572 1,
573 };
574
575 openfirmware(&args);
576 return args.ms;
577 }
578
579 #ifdef __notyet__
580 void
581 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
582 {
583 static struct {
584 const char *name;
585 int nargs;
586 int nreturns;
587 void *virt;
588 u_int size;
589 void (*entry)();
590 void *arg;
591 u_int len;
592 } args = {
593 "chain",
594 5,
595 0,
596 };
597
598 args.virt = virt;
599 args.size = size;
600 args.entry = entry;
601 args.arg = arg;
602 args.len = len;
603 openfirmware(&args);
604 }
605 #else
606 void
607 OF_chain(void *virt, u_int size, boot_entry_t entry, void *arg, u_int len)
608 {
609 /*
610 * This is a REALLY dirty hack till the firmware gets this going
611 */
612 #if 0
613 OF_release(virt, size);
614 #endif
615 entry(0, 0, openfirmware, arg, len);
616 }
617 #endif
618
619 int
620 OF_call_method(const char *method, int ihandle, int nargs, int nreturns, ...)
621 {
622 va_list ap;
623 static struct {
624 const char *name;
625 int nargs;
626 int nreturns;
627 const char *method;
628 int ihandle;
629 int args_n_results[12];
630 } args = {
631 "call-method",
632 2,
633 1,
634 };
635 int *ip, n;
636
637 if (nargs > 6)
638 return -1;
639 args.nargs = nargs + 2;
640 args.nreturns = nreturns + 1;
641 args.method = method;
642 args.ihandle = ihandle;
643 va_start(ap, nreturns);
644 for (ip = args.args_n_results + (n = nargs); --n >= 0;)
645 *--ip = va_arg(ap, int);
646
647 if (openfirmware(&args) == -1) {
648 va_end(ap);
649 return -1;
650 }
651 if (args.args_n_results[nargs]) {
652 va_end(ap);
653 return args.args_n_results[nargs];
654 }
655 for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
656 *va_arg(ap, int *) = *--ip;
657 va_end(ap);
658 return 0;
659 }
660
661 static int stdin;
662 static int stdout;
663
664 static void
665 setup(void)
666 {
667 int chosen;
668
669 if ((chosen = OF_finddevice("/chosen")) == -1)
670 OF_exit();
671 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) !=
672 sizeof(stdin) ||
673 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) !=
674 sizeof(stdout))
675 OF_exit();
676
677 #ifdef HEAP_VARIABLE
678 uint32_t pvr, vers, hsize = HEAP_SIZE;
679
680 __asm volatile ("mfpvr %0" : "=r"(pvr));
681 vers = pvr >> 16;
682 if (vers >= IBM970 && vers <= IBM970GX) hsize = 0x800000;
683
684 heapspace = OF_claim(0, hsize, NBPG);
685 if (heapspace == (char *)-1) {
686 panic("Failed to allocate heap");
687 }
688
689 setheap(heapspace, heapspace + HEAP_SIZE);
690 #endif /* HEAP_VARIABLE */
691 }
692
693 void
694 putchar(int c)
695 {
696 char ch = c;
697
698 if (c == '\n')
699 putchar('\r');
700 OF_write(stdout, &ch, 1);
701 }
702
703 int
704 getchar(void)
705 {
706 unsigned char ch = '\0';
707 int l;
708
709 while ((l = OF_read(stdin, &ch, 1)) != 1)
710 if (l != -2 && l != 0)
711 return -1;
712 return ch;
713 }
714