xref: /netbsd/sys/arch/shark/stand/ofwboot/Locore.c (revision 454af1c0)
1 /*	$NetBSD: Locore.c,v 1.4 2009/03/14 15:36:14 dsl 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 <arm/armreg.h>
39 
40 #include "cache.h"
41 #include "extern.h"
42 #include "openfirm.h"
43 
44 static int (*openfirmware_entry)(void *);
45 static int openfirmware(void *);
46 
47 void startup(int (*)(void *), char *, int);
48 static void setup(void);
49 
50 void (*cache_syncI)(void);
51 
52 void abort(void);
abort(void)53 void abort(void)
54 {
55 
56 	/* Stupid compiler (__dead). */
57 	for (;;)
58 		continue;
59 }
60 
61 static int
openfirmware(void * arg)62 openfirmware(void *arg)
63 {
64 
65 	(*openfirmware_entry)(arg);
66 	return 0;
67 }
68 
69 static vaddr_t
ofw_getcleaninfo(void)70 ofw_getcleaninfo(void)
71 {
72 	int cpu, vclean;
73 
74 	if ((cpu = OF_finddevice("/cpu")) == -1)
75 		panic("no /cpu from OFW");
76 
77 	if (OF_getprop(cpu, "d-cache-flush-address", &vclean,
78 		       sizeof(vclean)) != sizeof(vclean)) {
79 		printf("WARNING: no OFW d-cache-flush-address property\n");
80 		return (RELOC);
81 	}
82 
83 	return (of_decode_int((unsigned char *)&vclean));
84 }
85 
86 void
startup(int (* openfirm)(void *),char * arg,int argl)87 startup(int (*openfirm)(void *), char *arg, int argl)
88 {
89 	u_int cputype = cpufunc_id() & CPU_ID_CPU_MASK;
90 
91 	openfirmware_entry = openfirm;
92 	setup();
93 
94 	/*
95 	 * Determine the CPU type, and set up the appropriate
96 	 * I$ sync routine.
97 	 */
98 	if (cputype == CPU_ID_SA110 || cputype == CPU_ID_SA1100 ||
99 	    cputype == CPU_ID_SA1110) {
100 		extern vaddr_t sa110_cache_clean_addr;
101 		cache_syncI = sa110_cache_syncI;
102 		sa110_cache_clean_addr = ofw_getcleaninfo();
103 	} else {
104 		printf("WARNING: no I$ sync routine for CPU 0x%x\n",
105 		    cputype);
106 	}
107 
108 	main();
109 	OF_exit();
110 }
111 
112 int
of_decode_int(const u_char * p)113 of_decode_int(const u_char *p)
114 {
115 	unsigned int i = *p++ << 8;
116 	i = (i + *p++) << 8;
117 	i = (i + *p++) << 8;
118 	return (i + *p);
119 }
120 
121 __dead void
OF_exit(void)122 OF_exit(void)
123 {
124 	static struct {
125 		const char *name;
126 		int nargs;
127 		int nreturns;
128 	} args = {
129 		"exit",
130 		0,
131 		0
132 	};
133 
134 	openfirmware(&args);
135 	for (;;);			/* just in case */
136 }
137 
138 int
OF_finddevice(const char * name)139 OF_finddevice(const char *name)
140 {
141 	static struct {
142 		const char *name;
143 		int nargs;
144 		int nreturns;
145 		const char *device;
146 		int phandle;
147 	} args = {
148 		"finddevice",
149 		1,
150 		1,
151 	};
152 
153 	args.device = name;
154 	if (openfirmware(&args) == -1)
155 		return -1;
156 	return args.phandle;
157 }
158 
159 int
OF_instance_to_package(int ihandle)160 OF_instance_to_package(int ihandle)
161 {
162 	static struct {
163 		const char *name;
164 		int nargs;
165 		int nreturns;
166 		int ihandle;
167 		int phandle;
168 	} args = {
169 		"instance-to-package",
170 		1,
171 		1,
172 	};
173 
174 	args.ihandle = ihandle;
175 	if (openfirmware(&args) == -1)
176 		return -1;
177 	return args.phandle;
178 }
179 
180 int
OF_getprop(int handle,const char * prop,void * buf,int buflen)181 OF_getprop(int handle, const char *prop, void *buf, int buflen)
182 {
183 	static struct {
184 		const char *name;
185 		int nargs;
186 		int nreturns;
187 		int phandle;
188 		const char *prop;
189 		void *buf;
190 		int buflen;
191 		int size;
192 	} args = {
193 		"getprop",
194 		4,
195 		1,
196 	};
197 
198 	args.phandle = handle;
199 	args.prop = prop;
200 	args.buf = buf;
201 	args.buflen = buflen;
202 	if (openfirmware(&args) == -1)
203 		return -1;
204 	return args.size;
205 }
206 
207 #ifdef	__notyet__	/* Has a bug on FirePower */
208 int
OF_setprop(int handle,const char * prop,void * buf,int len)209 OF_setprop(int handle, const char *prop, void *buf, int len)
210 {
211 	static struct {
212 		const char *name;
213 		int nargs;
214 		int nreturns;
215 		int phandle;
216 		const char *prop;
217 		void *buf;
218 		int len;
219 		int size;
220 	} args = {
221 		"setprop",
222 		4,
223 		1,
224 	};
225 
226 	args.phandle = handle;
227 	args.prop = prop;
228 	args.buf = buf;
229 	args.len = len;
230 	if (openfirmware(&args) == -1)
231 		return -1;
232 	return args.size;
233 }
234 #endif
235 
236 int
OF_open(char * dname)237 OF_open(char *dname)
238 {
239 	static struct {
240 		const char *name;
241 		int nargs;
242 		int nreturns;
243 		char *dname;
244 		int handle;
245 	} args = {
246 		"open",
247 		1,
248 		1,
249 	};
250 
251 #ifdef OFW_DEBUG
252 	printf("OF_open(%s) -> ", dname);
253 #endif
254 	args.dname = dname;
255 	if (openfirmware(&args) == -1 ||
256 	    args.handle == 0) {
257 #ifdef OFW_DEBUG
258 		printf("lose\n");
259 #endif
260 		return -1;
261 	}
262 #ifdef OFW_DEBUG
263 	printf("%d\n", args.handle);
264 #endif
265 	return args.handle;
266 }
267 
268 void
OF_close(int handle)269 OF_close(int handle)
270 {
271 	static struct {
272 		const char *name;
273 		int nargs;
274 		int nreturns;
275 		int handle;
276 	} args = {
277 		"close",
278 		1,
279 		0,
280 	};
281 
282 #ifdef OFW_DEBUG
283 	printf("OF_close(%d)\n", handle);
284 #endif
285 	args.handle = handle;
286 	openfirmware(&args);
287 }
288 
289 int
OF_write(int handle,void * addr,int len)290 OF_write(int handle, void *addr, int len)
291 {
292 	static struct {
293 		const char *name;
294 		int nargs;
295 		int nreturns;
296 		int ihandle;
297 		void *addr;
298 		int len;
299 		int actual;
300 	} args = {
301 		"write",
302 		3,
303 		1,
304 	};
305 
306 #ifdef OFW_DEBUG
307 	if (len != 1)
308 		printf("OF_write(%d, %x, %x) -> ", handle, addr, len);
309 #endif
310 	args.ihandle = handle;
311 	args.addr = addr;
312 	args.len = len;
313 	if (openfirmware(&args) == -1) {
314 #ifdef OFW_DEBUG
315 		printf("lose\n");
316 #endif
317 		return -1;
318 	}
319 #ifdef OFW_DEBUG
320 	if (len != 1)
321 		printf("%x\n", args.actual);
322 #endif
323 	return args.actual;
324 }
325 
326 int
OF_read(int handle,void * addr,int len)327 OF_read(int handle, void *addr, int len)
328 {
329 	static struct {
330 		const char *name;
331 		int nargs;
332 		int nreturns;
333 		int ihandle;
334 		void *addr;
335 		int len;
336 		int actual;
337 	} args = {
338 		"read",
339 		3,
340 		1,
341 	};
342 
343 #ifdef OFW_DEBUG
344 	if (len != 1)
345 		printf("OF_read(%d, %x, %x) -> ", handle, addr, len);
346 #endif
347 	args.ihandle = handle;
348 	args.addr = addr;
349 	args.len = len;
350 	if (openfirmware(&args) == -1) {
351 #ifdef OFW_DEBUG
352 		printf("lose\n");
353 #endif
354 		return -1;
355 	}
356 #ifdef OFW_DEBUG
357 	if (len != 1)
358 		printf("%x\n", args.actual);
359 #endif
360 	return args.actual;
361 }
362 
363 int
OF_seek(int handle,u_quad_t pos)364 OF_seek(int handle, u_quad_t pos)
365 {
366 	static struct {
367 		const char *name;
368 		int nargs;
369 		int nreturns;
370 		int handle;
371 		int poshi;
372 		int poslo;
373 		int status;
374 	} args = {
375 		"seek",
376 		3,
377 		1,
378 	};
379 
380 #ifdef OFW_DEBUG
381 	printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos);
382 #endif
383 	args.handle = handle;
384 	args.poshi = (int)(pos >> 32);
385 	args.poslo = (int)pos;
386 	if (openfirmware(&args) == -1) {
387 #ifdef OFW_DEBUG
388 		printf("lose\n");
389 #endif
390 		return -1;
391 	}
392 #ifdef OFW_DEBUG
393 	printf("%d\n", args.status);
394 #endif
395 	return args.status;
396 }
397 
398 void *
OF_claim(void * virt,u_int size,u_int align)399 OF_claim(void *virt, u_int size, u_int align)
400 {
401 	static struct {
402 		const char *name;
403 		int nargs;
404 		int nreturns;
405 		void *virt;
406 		u_int size;
407 		u_int align;
408 		void *baseaddr;
409 	} args = {
410 		"claim",
411 		3,
412 		1,
413 	};
414 
415 #ifdef OFW_DEBUG
416 	printf("OF_claim(%x, %x, %x) -> ", virt, size, align);
417 #endif
418 	args.virt = virt;
419 	args.size = size;
420 	args.align = align;
421 	if (openfirmware(&args) == -1) {
422 #ifdef OFW_DEBUG
423 		printf("lose\n");
424 #endif
425 		return (void *)-1;
426 	}
427 #ifdef OFW_DEBUG
428 	printf("%x\n", args.baseaddr);
429 #endif
430 	return args.baseaddr;
431 }
432 
433 void
OF_release(void * virt,u_int size)434 OF_release(void *virt, u_int size)
435 {
436 	static struct {
437 		const char *name;
438 		int nargs;
439 		int nreturns;
440 		void *virt;
441 		u_int size;
442 	} args = {
443 		"release",
444 		2,
445 		0,
446 	};
447 
448 #ifdef OFW_DEBUG
449 	printf("OF_release(%x, %x)\n", virt, size);
450 #endif
451 	args.virt = virt;
452 	args.size = size;
453 	openfirmware(&args);
454 }
455 
456 int
OF_milliseconds(void)457 OF_milliseconds(void)
458 {
459 	static struct {
460 		const char *name;
461 		int nargs;
462 		int nreturns;
463 		int ms;
464 	} args = {
465 		"milliseconds",
466 		0,
467 		1,
468 	};
469 
470 	openfirmware(&args);
471 	return args.ms;
472 }
473 
474 void
OF_chain(void * virt,u_int size,void (* entry)(int (*)(void *),void *,u_int),void * arg,u_int len)475 OF_chain(void *virt, u_int size, void (*entry)(int (*)(void *), void *, u_int),
476     void *arg, u_int len)
477 {
478 	struct {
479 		const char *name;
480 		int nargs;
481 		int nreturns;
482 		void *virt;
483 		u_int size;
484 		void (*entry)(int (*)(void *), void *, u_int);
485 		void *arg;
486 		u_int len;
487 	} args;
488 
489 	args.name = "chain";
490 	args.nargs = 5;
491 	args.nreturns = 0;
492 	args.virt = virt;
493 	args.size = size;
494 	args.entry = entry;
495 	args.arg = arg;
496 	args.len = len;
497 #if 1
498 	openfirmware(&args);
499 #else
500 	entry(openfirmware_entry, arg, len);
501 #endif
502 }
503 
504 static int stdin;
505 static int stdout;
506 
507 static void
setup(void)508 setup(void)
509 {
510 	u_char buf[sizeof(int)];
511 	int chosen;
512 
513 	if ((chosen = OF_finddevice("/chosen")) == -1)
514 		OF_exit();
515 
516 	if (OF_getprop(chosen, "stdin", buf, sizeof(buf)) != sizeof(buf))
517 		OF_exit();
518 	stdin = of_decode_int(buf);
519 
520 	if (OF_getprop(chosen, "stdout", buf, sizeof(buf)) != sizeof(buf))
521 		OF_exit();
522 	stdout = of_decode_int(buf);
523 }
524 
525 void
putchar(int c)526 putchar(int c)
527 {
528 	char ch = c;
529 
530 	if (c == '\n')
531 		putchar('\r');
532 	OF_write(stdout, &ch, 1);
533 }
534 
535 int
getchar(void)536 getchar(void)
537 {
538 	unsigned char ch = '\0';
539 	int l;
540 
541 	while ((l = OF_read(stdin, &ch, 1)) != 1)
542 		if (l != -2 && l != 0)
543 			return -1;
544 	return ch;
545 }
546