xref: /openbsd/sys/arch/macppc/stand/Locore.c (revision 103c086e)
1 /*	$OpenBSD: Locore.c,v 1.18 2022/10/21 21:26:49 gkoehler Exp $	*/
2 /*	$NetBSD: Locore.c,v 1.1 1997/04/16 20:29:11 thorpej 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 
35 #include <macppc/stand/openfirm.h>
36 #include <dev/cons.h>
37 
38 #include "libsa.h"
39 
40 int main(void);
41 
42 #define ENABLE_DECREMENTER_WORKAROUND
43 void bat_init(void);
44 void patch_dec_intr(void);
45 
46 __dead void exit(void);
47 
48 static int (*openfirmware)(void *);
49 
50 static void setup(void);
51 
52 asm (".text; .globl _entry; _entry: .long _start,0,0");
53 asm("   .text			\n"
54 "	.globl	bat_init	\n"
55 "bat_init:			\n"
56 "				\n"
57 "	mfmsr   8		\n"
58 "	li      0,0		\n"
59 "	mtmsr   0		\n"
60 "	isync			\n"
61 "				\n"
62 "	mtibatu 0,0		\n"
63 "	mtibatu 1,0		\n"
64 "	mtibatu 2,0		\n"
65 "	mtibatu 3,0		\n"
66 "	mtdbatu 0,0		\n"
67 "	mtdbatu 1,0		\n"
68 "	mtdbatu 2,0		\n"
69 "	mtdbatu 3,0		\n"
70 "				\n"
71 "	li      9,0x12         	\n"	 /* BATL(0, BAT_M, BAT_PP_RW) */
72 "	mtibatl 0,9		\n"
73 "	mtdbatl 0,9		\n"
74 "	li      9,0x1ffe        \n"	/* BATU(0, BAT_BL_256M, BAT_Vs) */
75 "	mtibatu 0,9		\n"
76 "	mtdbatu 0,9		\n"
77 "	isync			\n"
78 "				\n"
79 "	mtmsr 8  		\n"
80 "	isync			\n"
81 "	blr			\n");
82 
83 #ifdef XCOFF_GLUE
84 static int stack[8192/4 + 4] __attribute__((__used__));
85 #endif
86 
87 __dead void
_start(void * vpd,int res,int (* openfirm)(void *),char * arg,int argl)88 _start(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl)
89 {
90 	extern char etext[];
91 
92 #ifdef XCOFF_GLUE
93 	asm(
94 	"sync			\n"
95 	"isync			\n"
96 	"lis	%r1,stack@ha	\n"
97 	"addi	%r1,%r1,stack@l	\n"
98 	"addi	%r1,%r1,8192	\n");
99 #endif
100 	syncicache((void *)RELOC, etext - (char *)RELOC);
101 
102 	bat_init();
103 	openfirmware = openfirm;	/* Save entry to Open Firmware */
104 #ifdef ENABLE_DECREMENTER_WORKAROUND
105 	patch_dec_intr();
106 #endif
107 	setup();
108 	main();
109 	exit();
110 }
111 
112 #ifdef ENABLE_DECREMENTER_WORKAROUND
113 void handle_decr_intr();
114 __asm (	"	.globl handle_decr_intr\n"
115 	"handle_decr_intr:\n"
116 	"	rfi\n");
117 
118 void
patch_dec_intr()119 patch_dec_intr()
120 {
121 	int time;
122 	unsigned int *decr_intr = (unsigned int *)0x900;
123 	unsigned int br_instr;
124 
125 	/* this hack is to prevent unexpected Decrementer Exceptions
126 	 * when Apple openfirmware enables interrupts
127 	 */
128 	time = 0x40000000;
129 	asm("mtdec %0" :: "r"(time));
130 
131 	/* we assume that handle_decr_intr is in the first 128 Meg */
132 	br_instr = (18 << 23) | (unsigned int)handle_decr_intr;
133 	*decr_intr = br_instr;
134 }
135 #endif
136 
137 __dead void
_rtt()138 _rtt()
139 {
140 	static struct {
141 		char *name;
142 		int nargs;
143 		int nreturns;
144 	} args = {
145 		"exit",
146 		0,
147 		0
148 	};
149 
150 	openfirmware(&args);
151 	while (1);			/* just in case */
152 }
153 
154 int
OF_finddevice(char * name)155 OF_finddevice(char *name)
156 {
157 	static struct {
158 		char *name;
159 		int nargs;
160 		int nreturns;
161 		char *device;
162 		int phandle;
163 	} args = {
164 		"finddevice",
165 		1,
166 		1,
167 	};
168 
169 	args.device = name;
170 	if (openfirmware(&args) == -1)
171 		return -1;
172 	return args.phandle;
173 }
174 
175 int
OF_instance_to_package(int ihandle)176 OF_instance_to_package(int ihandle)
177 {
178 	static struct {
179 		char *name;
180 		int nargs;
181 		int nreturns;
182 		int ihandle;
183 		int phandle;
184 	} args = {
185 		"instance-to-package",
186 		1,
187 		1,
188 	};
189 
190 	args.ihandle = ihandle;
191 	if (openfirmware(&args) == -1)
192 		return -1;
193 	return args.phandle;
194 }
195 
196 int
OF_getprop(int handle,char * prop,void * buf,int buflen)197 OF_getprop(int handle, char *prop, void *buf, int buflen)
198 {
199 	static struct {
200 		char *name;
201 		int nargs;
202 		int nreturns;
203 		int phandle;
204 		char *prop;
205 		void *buf;
206 		int buflen;
207 		int size;
208 	} args = {
209 		"getprop",
210 		4,
211 		1,
212 	};
213 
214 	args.phandle = handle;
215 	args.prop = prop;
216 	args.buf = buf;
217 	args.buflen = buflen;
218 	if (openfirmware(&args) == -1)
219 		return -1;
220 	return args.size;
221 }
222 
223 int
OF_open(char * dname)224 OF_open(char *dname)
225 {
226 	static struct {
227 		char *name;
228 		int nargs;
229 		int nreturns;
230 		char *dname;
231 		int handle;
232 	} args = {
233 		"open",
234 		1,
235 		1,
236 	};
237 
238 	args.dname = dname;
239 	if (openfirmware(&args) == -1)
240 		return -1;
241 	return args.handle;
242 }
243 
244 void
OF_close(int handle)245 OF_close(int handle)
246 {
247 	static struct {
248 		char *name;
249 		int nargs;
250 		int nreturns;
251 		int handle;
252 	} args = {
253 		"close",
254 		1,
255 		0,
256 	};
257 
258 	args.handle = handle;
259 	openfirmware(&args);
260 }
261 
262 int
OF_write(int handle,void * addr,int len)263 OF_write(int handle, void *addr, int len)
264 {
265 	static struct {
266 		char *name;
267 		int nargs;
268 		int nreturns;
269 		int ihandle;
270 		void *addr;
271 		int len;
272 		int actual;
273 	} args = {
274 		"write",
275 		3,
276 		1,
277 	};
278 
279 	args.ihandle = handle;
280 	args.addr = addr;
281 	args.len = len;
282 	if (openfirmware(&args) == -1)
283 		return -1;
284 	return args.actual;
285 }
286 
287 int
OF_read(int handle,void * addr,int len)288 OF_read(int handle, void *addr, int len)
289 {
290 	static struct {
291 		char *name;
292 		int nargs;
293 		int nreturns;
294 		int ihandle;
295 		void *addr;
296 		int len;
297 		int actual;
298 	} args = {
299 		"read",
300 		3,
301 		1,
302 	};
303 
304 	args.ihandle = handle;
305 	args.addr = addr;
306 	args.len = len;
307 	if (openfirmware(&args) == -1)
308 		return -1;
309 	return args.actual;
310 }
311 
312 int
OF_seek(int handle,u_quad_t pos)313 OF_seek(int handle, u_quad_t pos)
314 {
315 	static struct {
316 		char *name;
317 		int nargs;
318 		int nreturns;
319 		int handle;
320 		int poshi;
321 		int poslo;
322 		int status;
323 	} args = {
324 		"seek",
325 		3,
326 		1,
327 	};
328 
329 	args.handle = handle;
330 	args.poshi = (int)(pos >> 32);
331 	args.poslo = (int)pos;
332 	if (openfirmware(&args) == -1)
333 		return -1;
334 	return args.status;
335 }
336 
337 void *
OF_claim(void * virt,u_int size,u_int align)338 OF_claim(void *virt, u_int size, u_int align)
339 {
340 	static struct {
341 		char *name;
342 		int nargs;
343 		int nreturns;
344 		void *virt;
345 		u_int size;
346 		u_int align;
347 		void *baseaddr;
348 	} args = {
349 		"claim",
350 		3,
351 		1,
352 	};
353 
354 	args.virt = virt;
355 	args.size = size;
356 	args.align = align;
357 	if (openfirmware(&args) == -1)
358 		return (void *)-1;
359 	if (virt != 0)
360 		return virt;
361 	return args.baseaddr;
362 }
363 
364 void
OF_release(void * virt,u_int size)365 OF_release(void *virt, u_int size)
366 {
367 	static struct {
368 		char *name;
369 		int nargs;
370 		int nreturns;
371 		void *virt;
372 		u_int size;
373 	} args = {
374 		"release",
375 		2,
376 		0,
377 	};
378 
379 	args.virt = virt;
380 	args.size = size;
381 	openfirmware(&args);
382 }
383 
384 int
OF_milliseconds()385 OF_milliseconds()
386 {
387 	static struct {
388 		char *name;
389 		int nargs;
390 		int nreturns;
391 		int ms;
392 	} args = {
393 		"milliseconds",
394 		0,
395 		1,
396 	};
397 
398 	openfirmware(&args);
399 	return args.ms;
400 }
401 
402 #ifdef __notyet__
403 void
OF_chain(void * virt,u_int size,void (* entry)(),void * arg,u_int len)404 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
405 {
406 	static struct {
407 		char *name;
408 		int nargs;
409 		int nreturns;
410 		void *virt;
411 		u_int size;
412 		void (*entry)();
413 		void *arg;
414 		u_int len;
415 	} args = {
416 		"chain",
417 		5,
418 		0,
419 	};
420 
421 	args.virt = virt;
422 	args.size = size;
423 	args.entry = entry;
424 	args.arg = arg;
425 	args.len = len;
426 	openfirmware(&args);
427 }
428 #else
429 void
OF_chain(void * virt,u_int size,void (* entry)(),void * arg,u_int len)430 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
431 {
432 	/*
433 	 * This is a REALLY dirty hack till the firmware gets this going
434 	OF_release(virt, size);
435 	 */
436 	entry(0, 0, openfirmware, arg, len);
437 }
438 #endif
439 
440 int
OF_call_method(char * method,int ihandle,int nargs,int nreturns,...)441 OF_call_method(char *method, int ihandle, int nargs, int nreturns, ...)
442 {
443 	va_list ap;
444 	static struct {
445 		char *name;
446 		int nargs;
447 		int nreturns;
448 		char *method;
449 		int ihandle;
450 		int args_n_results[12];
451 	} args = {
452 		"call-method",
453 		2,
454 		1,
455 	};
456 	int *ip, n;
457 
458 	if (nargs > 6)
459 		return -1;
460 	args.nargs = nargs + 2;
461 	args.nreturns = nreturns + 1;
462 	args.method = method;
463 	args.ihandle = ihandle;
464 	va_start(ap, nreturns);
465 	for (ip = args.args_n_results + (n = nargs); --n >= 0;)
466 		*--ip = va_arg(ap, int);
467 
468 	if (openfirmware(&args) == -1) {
469 		va_end(ap);
470 		return -1;
471 	}
472 	if (args.args_n_results[nargs]) {
473 		va_end(ap);
474 		return args.args_n_results[nargs];
475 	}
476 	for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
477 		*va_arg(ap, int *) = *--ip;
478 	va_end(ap);
479 	return 0;
480 }
481 
482 static int stdin;
483 static int stdout;
484 
485 static void
setup()486 setup()
487 {
488 	int chosen;
489 
490 	if ((chosen = OF_finddevice("/chosen")) == -1)
491 		_rtt();
492 	if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != sizeof(stdin)
493 	    || OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) !=
494 	    sizeof(stdout))
495 		_rtt();
496 	if (stdout == 0) {
497 		/* screen should be console, but it is not open */
498 		stdout = OF_open("screen");
499 	}
500 }
501 
502 void
putchar(int c)503 putchar(int c)
504 {
505 	char ch = c;
506 	if (c == '\177') {
507 		ch = '\b';
508 		OF_write(stdout, &ch, 1);
509 		ch = ' ';
510 		OF_write(stdout, &ch, 1);
511 		ch = '\b';
512 	}
513 	if (c == '\n')
514 		putchar('\r');
515 	OF_write(stdout, &ch, 1);
516 }
517 
518 void
ofc_probe(struct consdev * cn)519 ofc_probe(struct consdev *cn)
520 {
521 	cn->cn_pri = CN_LOWPRI;
522 	cn->cn_dev = makedev(0,0); /* WTF */
523 }
524 
525 
526 void
ofc_init(struct consdev * cn)527 ofc_init(struct consdev *cn)
528 {
529 }
530 
531 char buffered_char;
532 int
ofc_getc(dev_t dev)533 ofc_getc(dev_t dev)
534 {
535 	u_int8_t ch;
536 	int l;
537 
538 	if (dev & 0x80)  {
539 		if (buffered_char != 0)
540 			return 1;
541 
542 		l = OF_read(stdin, &ch, 1);
543 		if (l == 1) {
544 			buffered_char = ch;
545 			return 1;
546 		}
547 		return 0;
548 	}
549 
550 	if (buffered_char != 0) {
551 		ch = buffered_char;
552 		buffered_char = 0;
553 		return ch;
554 	}
555 
556 	while ((l = OF_read(stdin, &ch, 1)) != 1)
557 		if (l != -2 && l != 0)
558 			return 0;
559 	return ch;
560 
561 }
562 
563 void
ofc_putc(dev_t dev,int c)564 ofc_putc(dev_t dev, int c)
565 {
566 	char ch;
567 
568 	ch = 'a';
569 	OF_write(stdout, &ch, 1);
570 	ch = c;
571 	if (c == '\177' && c == '\b') {
572 		ch = 'A';
573 	}
574 	OF_write(stdout, &ch, 1);
575 }
576 
577 
578 void
machdep()579 machdep()
580 {
581 	cninit();
582 }
583