openfirm.c revision 67204
1139749Simp/*	$NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $	*/
2185015Simp
367276Sjon/*
467276Sjon * Copyright (C) 1995, 1996 Wolfgang Solfrank.
553343Simp * Copyright (C) 1995, 1996 TooLs GmbH.
653343Simp * All rights reserved.
753343Simp *
853343Simp * Redistribution and use in source and binary forms, with or without
953343Simp * modification, are permitted provided that the following conditions
10140198Simp * are met:
1153343Simp * 1. Redistributions of source code must retain the above copyright
12140198Simp *    notice, this list of conditions and the following disclaimer.
13140198Simp * 2. Redistributions in binary form must reproduce the above copyright
1453343Simp *    notice, this list of conditions and the following disclaimer in the
1567276Sjon *    documentation and/or other materials provided with the distribution.
1667276Sjon * 3. All advertising materials mentioning features or use of this software
1767276Sjon *    must display the following acknowledgement:
18140198Simp *	This product includes software developed by TooLs GmbH.
19140198Simp * 4. The name of TooLs GmbH may not be used to endorse or promote products
2067276Sjon *    derived from this software without specific prior written permission.
2167276Sjon *
2267276Sjon * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2367276Sjon * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2467276Sjon * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2567276Sjon * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2653343Simp * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2767276Sjon * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2853343Simp * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2953343Simp * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3067276Sjon * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3167276Sjon * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3267276Sjon */
33185015Simp/*
34185015Simp * Copyright (C) 2000 Benno Rice.
35185015Simp * All rights reserved.
36185015Simp *
37185015Simp * Redistribution and use in source and binary forms, with or without
38185015Simp * modification, are permitted provided that the following conditions
39185015Simp * are met:
40185015Simp * 1. Redistributions of source code must retain the above copyright
41185015Simp *    notice, this list of conditions and the following disclaimer.
42185015Simp * 2. Redistributions in binary form must reproduce the above copyright
43185015Simp *    notice, this list of conditions and the following disclaimer in the
44185015Simp *    documentation and/or other materials provided with the distribution.
45185015Simp *
46185015Simp * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
47185015Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48151782Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49151782Simp * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
5091355Simp * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51109925Simp * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
52109925Simp * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
53109925Simp * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
54109925Simp * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
55107301Simp * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56107301Simp *
57107301Simp * $FreeBSD: head/sys/boot/ofw/libofw/openfirm.c 67204 2000-10-16 10:46:22Z obrien $
58109925Simp */
59107301Simp
60107301Simp#include <machine/stdarg.h>
61109925Simp
62185015Simp#include "openfirm.h"
63185015Simp
6453343Simpstatic int (*openfirmware)(void *);
65153811Simpstatic ihandle_t stdin;
66185015Simpstatic ihandle_t stdout;
67185015Simp
68185015Simp/* Initialiaser */
69153811Simp
70153811Simpvoid
71153811SimpOF_init(int (*openfirm)(void *))
72280970Sjhb{
73280970Sjhb	openfirmware = openfirm;
74280970Sjhb}
75153811Simp
76153811Simp/*
77185015Simp * Generic functions
78185015Simp */
79185015Simp
80153811Simp/* Test to see if a service exists. */
81153811Simpint
82153811SimpOF_test(char *name)
83153811Simp{
84153811Simp	static struct {
85153811Simp		char	*name;
86153811Simp		int	nargs;
87153811Simp		int	nreturns;
88153811Simp		char	*service;
89153811Simp		int	missing;
90185015Simp	} args = {
91185015Simp		"test",
92185015Simp		1,
93153811Simp		1,
94153811Simp	};
95
96	args.service = name;
97	if (openfirmware(&args) == -1)
98		return -1;
99	return args.missing;
100}
101
102/* Return firmware millisecond count. */
103int
104OF_milliseconds()
105{
106	static struct {
107		char	*name;
108		int	nargs;
109		int	nreturns;
110		int	ms;
111	} args = {
112		"milliseconds",
113		0,
114		1,
115	};
116
117	openfirmware(&args);
118	return args.ms;
119}
120
121/*
122 * Device tree functions
123 */
124
125/* Return the next sibling of this node or 0. */
126phandle_t
127OF_peer(phandle_t node)
128{
129	static struct {
130		char		*name;
131		int		nargs;
132		int		nreturns;
133		phandle_t	node;
134		phandle_t	next;
135	} args = {
136		"peer",
137		1,
138		1,
139	};
140
141	args.node = node;
142	if (openfirmware(&args) == -1)
143		return -1;
144	return args.next;
145}
146
147/* Return the first child of this node or 0. */
148phandle_t
149OF_child(phandle_t node)
150{
151	static struct {
152		char		*name;
153		int		nargs;
154		int		nreturns;
155		phandle_t	node;
156		phandle_t	child;
157	} args = {
158		"child",
159		1,
160		1,
161	};
162
163	args.node = node;
164	if (openfirmware(&args) == -1)
165		return -1;
166	return args.child;
167}
168
169/* Return the parent of this node or 0. */
170phandle_t
171OF_parent(phandle_t node)
172{
173	static struct {
174		char		*name;
175		int		nargs;
176		int		nreturns;
177		phandle_t	node;
178		phandle_t	parent;
179	} args = {
180		"parent",
181		1,
182		1,
183	};
184
185	args.node = node;
186	if (openfirmware(&args) == -1)
187		return -1;
188	return args.parent;
189}
190
191/* Return the package handle that corresponds to an instance handle. */
192phandle_t
193OF_instance_to_package(ihandle_t instance)
194{
195	static struct {
196		char		*name;
197		int		nargs;
198		int		nreturns;
199		ihandle_t	instance;
200		phandle_t	package;
201	} args = {
202		"instance-to-package",
203		1,
204		1,
205	};
206
207	args.instance = instance;
208	if (openfirmware(&args) == -1)
209		return -1;
210	return args.package;
211}
212
213/* Get the length of a property of a package. */
214int
215OF_getproplen(phandle_t package, char *propname)
216{
217	static struct {
218		char		*name;
219		int		nargs;
220		int		nreturns;
221		phandle_t	package;
222		char 		*propname;
223		int		proplen;
224	} args = {
225		"getproplen",
226		2,
227		1,
228	};
229
230	args.package = package;
231	args.propname = propname;
232	if (openfirmware(&args) == -1)
233		return -1;
234	return args.proplen;
235}
236
237/* Get the value of a property of a package. */
238int
239OF_getprop(phandle_t package, char *propname, void *buf, int buflen)
240{
241	static struct {
242		char		*name;
243		int		nargs;
244		int		nreturns;
245		phandle_t	package;
246		char		*propname;
247		void		*buf;
248		int		buflen;
249		int		size;
250	} args = {
251		"getprop",
252		4,
253		1,
254	};
255
256	args.package = package;
257	args.propname = propname;
258	args.buf = buf;
259	args.buflen = buflen;
260	if (openfirmware(&args) == -1)
261		return -1;
262	return args.size;
263}
264
265/* Get the next property of a package. */
266int
267OF_nextprop(phandle_t package, char *previous, char *buf)
268{
269	static struct {
270		char		*name;
271		int		nargs;
272		int		nreturns;
273		phandle_t	package;
274		char 		*previous;
275		char		*buf;
276		int		flag;
277	} args = {
278		"nextprop",
279		3,
280		1,
281	};
282
283	args.package = package;
284	args.previous = previous;
285	args.buf = buf;
286	if (openfirmware(&args) == -1)
287		return -1;
288	return args.flag;
289}
290
291/* Set the value of a property of a package. */
292/* XXX Has a bug on FirePower */
293int
294OF_setprop(phandle_t package, char *propname, void *buf, int len)
295{
296	static struct {
297		char		*name;
298		int		nargs;
299		int		nreturns;
300		phandle_t	package;
301		char		*propname;
302		void		*buf;
303		int		len;
304		int		size;
305	} args = {
306		"setprop",
307		4,
308		1,
309	};
310
311	args.package = package;
312	args.propname = propname;
313	args.buf = buf;
314	args.len = len;
315	if (openfirmware(&args) == -1)
316		return -1;
317	return args.size;
318}
319
320/* Convert a device specifier to a fully qualified pathname. */
321int
322OF_canon(char *device, char *buf, int len)
323{
324	static struct {
325		char	*name;
326		int	nargs;
327		int	nreturns;
328		char	*device;
329		char	*buf;
330		int	len;
331		int	size;
332	} args = {
333		"canon",
334		3,
335		1,
336	};
337
338	args.device = device;
339	args.buf = buf;
340	args.len = len;
341	if (openfirmware(&args) == -1)
342		return -1;
343	return args.size;
344}
345
346/* Return a package handle for the specified device. */
347phandle_t
348OF_finddevice(char *device)
349{
350	static struct {
351		char		*name;
352		int		nargs;
353		int		nreturns;
354		char		*device;
355		phandle_t	package;
356	} args = {
357		"finddevice",
358		1,
359		1,
360	};
361
362	args.device = device;
363	if (openfirmware(&args) == -1)
364		return -1;
365	return args.package;
366}
367
368/* Return the fully qualified pathname corresponding to an instance. */
369int
370OF_instance_to_path(ihandle_t instance, char *buf, int len)
371{
372	static struct {
373		char		*name;
374		int		nargs;
375		int		nreturns;
376		ihandle_t	instance;
377		char		*buf;
378		int		len;
379		int		size;
380	} args = {
381		"instance-to-path",
382		3,
383		1,
384	};
385
386	args.instance = instance;
387	args.buf = buf;
388	args.len = len;
389	if (openfirmware(&args) == -1)
390		return -1;
391	return(args.size);
392}
393
394/* Return the fully qualified pathname corresponding to a package. */
395int
396OF_package_to_path(phandle_t package, char *buf, int len)
397{
398	static struct {
399		char		*name;
400		int		nargs;
401		int		nreturns;
402		phandle_t	package;
403		char		*buf;
404		int		len;
405		int		size;
406	} args = {
407		"package-to-path",
408		3,
409		1,
410	};
411
412	args.package = package;
413	args.buf = buf;
414	args.len = len;
415	if (openfirmware(&args) == -1)
416		return -1;
417	return(args.size);
418}
419
420/*  Call the method in the scope of a given instance. */
421int
422OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
423{
424	va_list ap;
425	static struct {
426		char		*name;
427		int		nargs;
428		int		nreturns;
429		char		*method;
430		ihandle_t	instance;
431		int		args_n_results[12];
432	} args = {
433		"call-method",
434		2,
435		1,
436	};
437	int *ip, n;
438
439	if (nargs > 6)
440		return -1;
441	args.nargs = nargs + 2;
442	args.nreturns = nreturns + 1;
443	args.method = method;
444	args.instance = instance;
445	va_start(ap, nreturns);
446	for (ip = args.args_n_results + (n = nargs); --n >= 0;)
447		*--ip = va_arg(ap, int);
448
449	if (openfirmware(&args) == -1)
450		return -1;
451	if (args.args_n_results[nargs])
452		return args.args_n_results[nargs];
453	for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
454		*va_arg(ap, int *) = *--ip;
455	va_end(ap);
456	return 0;
457}
458
459/*
460 * Device I/O functions.
461 */
462
463/* Open an instance for a device. */
464ihandle_t
465OF_open(char *device)
466{
467	static struct {
468		char		*name;
469		int		nargs;
470		int		nreturns;
471		char		*device;
472		ihandle_t	instance;
473	} args = {
474		"open",
475		1,
476		1,
477	};
478
479	args.device = device;
480	if (openfirmware(&args) == -1 || args.instance == 0) {
481		return -1;
482	}
483	return args.instance;
484}
485
486/* Close an instance. */
487void
488OF_close(ihandle_t instance)
489{
490	static struct {
491		char		*name;
492		int		nargs;
493		int		nreturns;
494		ihandle_t	instance;
495	} args = {
496		"close",
497		1,
498		0,
499	};
500
501	args.instance = instance;
502	openfirmware(&args);
503}
504
505/* Read from an instance. */
506int
507OF_read(ihandle_t instance, void *addr, int len)
508{
509	static struct {
510		char		*name;
511		int		nargs;
512		int		nreturns;
513		ihandle_t	instance;
514		void		*addr;
515		int		len;
516		int		actual;
517	} args = {
518		"read",
519		3,
520		1,
521	};
522
523	args.instance = instance;
524	args.addr = addr;
525	args.len = len;
526	if (openfirmware(&args) == -1)
527		return -1;
528	return args.actual;
529}
530
531/* Write to an instance. */
532int
533OF_write(ihandle_t instance, void *addr, int len)
534{
535	static struct {
536		char		*name;
537		int		nargs;
538		int		nreturns;
539		ihandle_t	instance;
540		void		*addr;
541		int		len;
542		int		actual;
543	} args = {
544		"write",
545		3,
546		1,
547	};
548
549	args.instance = instance;
550	args.addr = addr;
551	args.len = len;
552	if (openfirmware(&args) == -1)
553		return -1;
554	return args.actual;
555}
556
557/* Seek to a position. */
558int
559OF_seek(ihandle_t instance, u_quad_t pos)
560{
561	static struct {
562		char		*name;
563		int		nargs;
564		int		nreturns;
565		ihandle_t	instance;
566		int		poshi;
567		int		poslo;
568		int		status;
569	} args = {
570		"seek",
571		3,
572		1,
573	};
574
575	args.instance = instance;
576	args.poshi = (int)(pos >> 32);
577	args.poslo = (int)pos;
578	if (openfirmware(&args) == -1)
579		return -1;
580	return args.status;
581}
582
583/*
584 * Memory functions.
585 */
586
587/* Claim an area of memory. */
588void *
589OF_claim(void *virt, u_int size, u_int align)
590{
591	static struct {
592		char	*name;
593		int	 nargs;
594		int	 nreturns;
595		void	 *virt;
596		u_int	 size;
597		u_int	 align;
598		void	 *baseaddr;
599	} args = {
600		"claim",
601		3,
602		1,
603	};
604
605	args.virt = virt;
606	args.size = size;
607	args.align = align;
608	if (openfirmware(&args) == -1)
609		return (void *)-1;
610	return args.baseaddr;
611}
612
613/* Release an area of memory. */
614void
615OF_release(void *virt, u_int size)
616{
617	static struct {
618		char	*name;
619		int	nargs;
620		int	nreturns;
621		void	*virt;
622		u_int	size;
623	} args = {
624		"release",
625		2,
626		0,
627	};
628
629	args.virt = virt;
630	args.size = size;
631	openfirmware(&args);
632}
633
634/*
635 * Control transfer functions.
636 */
637
638/* Reset the system and call "boot <bootspec>". */
639void
640OF_boot(char *bootspec)
641{
642	static struct {
643		char	*name;
644		int	nargs;
645		int	nreturns;
646		char	*bootspec;
647	} args = {
648		"boot",
649		1,
650		0,
651	};
652
653	args.bootspec = bootspec;
654	openfirmware(&args);
655	for (;;);			/* just in case */
656}
657
658/* Suspend and drop back to the OpenFirmware interface. */
659void
660OF_enter()
661{
662	static struct {
663		char *name;
664		int nargs;
665		int nreturns;
666	} args = {
667		"enter",
668		0,
669		0
670	};
671
672	openfirmware(&args);
673	return;				/* We may come back. */
674}
675
676/* Shut down and drop back to the OpenFirmware interface. */
677__dead void
678OF_exit()
679{
680	static struct {
681		char *name;
682		int nargs;
683		int nreturns;
684	} args = {
685		"exit",
686		0,
687		0
688	};
689
690	openfirmware(&args);
691	for (;;);			/* just in case */
692}
693
694/* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
695#ifdef	__notyet__
696void
697OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
698{
699	static struct {
700		char	*name;
701		int	nargs;
702		int	nreturns;
703		void	*virt;
704		u_int	size;
705		void	(*entry)();
706		void	*arg;
707		u_int	len;
708	} args = {
709		"chain",
710		5,
711		0,
712	};
713
714	args.virt = virt;
715	args.size = size;
716	args.entry = entry;
717	args.arg = arg;
718	args.len = len;
719	openfirmware(&args);
720}
721#else
722void
723OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
724{
725	/*
726	 * This is a REALLY dirty hack till the firmware gets this going
727	 */
728#if 0
729	OF_release(virt, size);
730#endif
731	entry(0, 0, openfirmware, arg, len);
732}
733#endif
734