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
40int main(void);
41
42#define ENABLE_DECREMENTER_WORKAROUND
43void bat_init(void);
44void patch_dec_intr(void);
45
46__dead void exit(void);
47
48static int (*openfirmware)(void *);
49
50static void setup(void);
51
52asm (".text; .globl _entry; _entry: .long _start,0,0");
53asm("   .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
84static int stack[8192/4 + 4] __attribute__((__used__));
85#endif
86
87__dead void
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
113void handle_decr_intr();
114__asm (	"	.globl handle_decr_intr\n"
115	"handle_decr_intr:\n"
116	"	rfi\n");
117
118void
119patch_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
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
154int
155OF_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
175int
176OF_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
196int
197OF_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
223int
224OF_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
244void
245OF_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
262int
263OF_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
287int
288OF_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
312int
313OF_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
337void *
338OF_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
364void
365OF_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
384int
385OF_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__
403void
404OF_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
429void
430OF_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
440int
441OF_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
482static int stdin;
483static int stdout;
484
485static void
486setup()
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
502void
503putchar(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
518void
519ofc_probe(struct consdev *cn)
520{
521	cn->cn_pri = CN_LOWPRI;
522	cn->cn_dev = makedev(0,0); /* WTF */
523}
524
525
526void
527ofc_init(struct consdev *cn)
528{
529}
530
531char buffered_char;
532int
533ofc_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
563void
564ofc_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
578void
579machdep()
580{
581	cninit();
582}
583