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