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