xref: /openbsd/sys/arch/macppc/macppc/opendev.c (revision 3d8817e4)
1 /*	$OpenBSD: opendev.c,v 1.9 2006/03/09 23:06:19 miod Exp $	*/
2 /*	$NetBSD: openfirm.c,v 1.1 1996/09/30 16:34:52 ws Exp $	*/
3 
4 /*
5  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
6  * Copyright (C) 1995, 1996 TooLs GmbH.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by TooLs GmbH.
20  * 4. The name of TooLs GmbH may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/stdarg.h>
37 #include <machine/psl.h>
38 
39 #include <dev/ofw/openfirm.h>
40 
41 extern void ofw_stack(void);
42 extern void ofbcopy(const void *, void *, size_t);
43 
44 int
45 OF_instance_to_package(int ihandle)
46 {
47 	static struct {
48 		char *name;
49 		int nargs;
50 		int nreturns;
51 		int ihandle;
52 		int phandle;
53 	} args = {
54 		"instance-to-package",
55 		1,
56 		1,
57 	};
58 
59 	ofw_stack();
60 	args.ihandle = ihandle;
61 	if (openfirmware(&args) == -1)
62 		return -1;
63 	return args.phandle;
64 }
65 
66 int
67 OF_package_to_path(int phandle, char *buf, int buflen)
68 {
69 	static struct {
70 		char *name;
71 		int nargs;
72 		int nreturns;
73 		int phandle;
74 		char *buf;
75 		int buflen;
76 		int length;
77 	} args = {
78 		"package-to-path",
79 		3,
80 		1,
81 	};
82 
83 	ofw_stack();
84 	if (buflen > PAGE_SIZE)
85 		return -1;
86 	args.phandle = phandle;
87 	args.buf = OF_buf;
88 	args.buflen = buflen;
89 	if (openfirmware(&args) < 0)
90 		return -1;
91 	if (args.length > 0)
92 		ofbcopy(OF_buf, buf, args.length);
93 	return args.length;
94 }
95 
96 
97 int
98 OF_call_method(char *method, int ihandle, int nargs, int nreturns, ...)
99 {
100 	va_list ap;
101 	static struct {
102 		char *name;
103 		int nargs;
104 		int nreturns;
105 		char *method;
106 		int ihandle;
107 		int args_n_results[12];
108 	} args = {
109 		"call-method",
110 		2,
111 		1,
112 	};
113 	int *ip, n;
114 
115 	if (nargs > 6)
116 		return -1;
117 	args.nargs = nargs + 2;
118 	args.nreturns = nreturns + 1;
119 	args.method = method;
120 	args.ihandle = ihandle;
121 	va_start(ap, nreturns);
122 	for (ip = args.args_n_results + (n = nargs); --n >= 0;)
123 		*--ip = va_arg(ap, int);
124 	ofw_stack();
125 	if (openfirmware(&args) == -1) {
126 		va_end(ap);
127 		return -1;
128 	}
129 	if (args.args_n_results[nargs]) {
130 		va_end(ap);
131 		return args.args_n_results[nargs];
132 	}
133 	for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
134 		*va_arg(ap, int *) = *--ip;
135 	va_end(ap);
136 	return 0;
137 }
138 int
139 OF_call_method_1(char *method, int ihandle, int nargs, ...)
140 {
141 	va_list ap;
142 	static struct {
143 		char *name;
144 		int nargs;
145 		int nreturns;
146 		char *method;
147 		int ihandle;
148 		int args_n_results[8];
149 	} args = {
150 		"call-method",
151 		2,
152 		2,
153 	};
154 	int *ip, n;
155 
156 	if (nargs > 6)
157 		return -1;
158 	args.nargs = nargs + 2;
159 	args.method = method;
160 	args.ihandle = ihandle;
161 	va_start(ap, nargs);
162 	for (ip = args.args_n_results + (n = nargs); --n >= 0;)
163 		*--ip = va_arg(ap, int);
164 	va_end(ap);
165 	ofw_stack();
166 	if (openfirmware(&args) == -1)
167 		return -1;
168 	if (args.args_n_results[nargs])
169 		return -1;
170 	return args.args_n_results[nargs + 1];
171 }
172 
173 int
174 OF_open(char *dname)
175 {
176 	static struct {
177 		char *name;
178 		int nargs;
179 		int nreturns;
180 		char *dname;
181 		int handle;
182 	} args = {
183 		"open",
184 		1,
185 		1,
186 	};
187 	int l;
188 
189 	ofw_stack();
190 	if ((l = strlen(dname)) >= PAGE_SIZE)
191 		return -1;
192 	ofbcopy(dname, OF_buf, l + 1);
193 	args.dname = OF_buf;
194 	if (openfirmware(&args) == -1)
195 		return -1;
196 	return args.handle;
197 }
198 
199 void
200 OF_close(int handle)
201 {
202 	static struct {
203 		char *name;
204 		int nargs;
205 		int nreturns;
206 		int handle;
207 	} args = {
208 		"close",
209 		1,
210 		0,
211 	};
212 
213 	ofw_stack();
214 	args.handle = handle;
215 	openfirmware(&args);
216 }
217 
218 /*
219  * This assumes that character devices don't read in multiples of PAGE_SIZE.
220  */
221 int
222 OF_read(int handle, void *addr, int len)
223 {
224 	static struct {
225 		char *name;
226 		int nargs;
227 		int nreturns;
228 		int ihandle;
229 		void *addr;
230 		int len;
231 		int actual;
232 	} args = {
233 		"read",
234 		3,
235 		1,
236 	};
237 	int l, act = 0;
238 
239 	ofw_stack();
240 	args.ihandle = handle;
241 	args.addr = OF_buf;
242 	for (; len > 0; len -= l, addr += l) {
243 		l = min(PAGE_SIZE, len);
244 		args.len = l;
245 		if (openfirmware(&args) == -1)
246 			return -1;
247 		if (args.actual > 0) {
248 			ofbcopy(OF_buf, addr, args.actual);
249 			act += args.actual;
250 		}
251 		if (args.actual < l) {
252 			if (act)
253 				return act;
254 			else
255 				return args.actual;
256 		}
257 	}
258 	return act;
259 }
260 
261 int
262 OF_write(int handle, void *addr, int len)
263 {
264 	static struct {
265 		char *name;
266 		int nargs;
267 		int nreturns;
268 		int ihandle;
269 		void *addr;
270 		int len;
271 		int actual;
272 	} args = {
273 		"write",
274 		3,
275 		1,
276 	};
277 	int l, act = 0;
278 
279 	ofw_stack();
280 	args.ihandle = handle;
281 	args.addr = OF_buf;
282 	for (; len > 0; len -= l, addr += l) {
283 		l = min(PAGE_SIZE, len);
284 		ofbcopy(addr, OF_buf, l);
285 		args.len = l;
286 		if (openfirmware(&args) == -1)
287 			return -1;
288 		l = args.actual;
289 		act += l;
290 	}
291 	return act;
292 }
293 
294 int
295 OF_seek(int handle, u_quad_t pos)
296 {
297 	static struct {
298 		char *name;
299 		int nargs;
300 		int nreturns;
301 		int handle;
302 		int poshi;
303 		int poslo;
304 		int status;
305 	} args = {
306 		"seek",
307 		3,
308 		1,
309 	};
310 
311 	ofw_stack();
312 	args.handle = handle;
313 	args.poshi = (int)(pos >> 32);
314 	args.poslo = (int)pos;
315 	if (openfirmware(&args) == -1)
316 		return -1;
317 	return args.status;
318 }
319