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