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