1 /* $OpenBSD: Locore.c,v 1.18 2023/06/01 17:24:56 krw Exp $ */
2 /* $NetBSD: Locore.c,v 1.1 2000/08/20 14:58:36 mrg 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 <lib/libsa/stand.h>
36
37 #include "openfirm.h"
38
39 #include <machine/cpu.h>
40
41 #ifdef SOFTRAID
42 #include <dev/softraidvar.h>
43 #include <lib/libsa/softraid.h>
44 #endif
45
46 static vaddr_t OF_claim_virt(vaddr_t vaddr, int len);
47 static vaddr_t OF_alloc_virt(int len, int align);
48 static int OF_free_virt(vaddr_t vaddr, int len);
49 static int OF_map_phys(paddr_t paddr, off_t size, vaddr_t vaddr, int mode);
50 static paddr_t OF_alloc_phys(int len, int align);
51 static int OF_free_phys(paddr_t paddr, int len);
52
53 extern int openfirmware(void *);
54
55 void setup(void);
56
57 __dead void
_rtt(void)58 _rtt(void)
59 {
60 struct {
61 cell_t name;
62 cell_t nargs;
63 cell_t nreturns;
64 } args;
65
66 #ifdef SOFTRAID
67 sr_clear_keys();
68 #endif
69
70 args.name = ADR2CELL("exit");
71 args.nargs = 0;
72 args.nreturns = 0;
73 openfirmware(&args);
74 while (1); /* just in case */
75 }
76
77 void
OF_enter(void)78 OF_enter(void)
79 {
80 struct {
81 cell_t name;
82 cell_t nargs;
83 cell_t nreturns;
84 } args;
85
86 args.name = ADR2CELL("enter");
87 args.nargs = 0;
88 args.nreturns = 0;
89 openfirmware(&args);
90 }
91
92 int
OF_finddevice(char * name)93 OF_finddevice(char *name)
94 {
95 struct {
96 cell_t name;
97 cell_t nargs;
98 cell_t nreturns;
99 cell_t device;
100 cell_t phandle;
101 } args;
102
103 args.name = ADR2CELL("finddevice");
104 args.nargs = 1;
105 args.nreturns = 1;
106 args.device = ADR2CELL(name);
107 if (openfirmware(&args) == -1)
108 return -1;
109 return args.phandle;
110 }
111
112 int
OF_instance_to_package(int ihandle)113 OF_instance_to_package(int ihandle)
114 {
115 struct {
116 cell_t name;
117 cell_t nargs;
118 cell_t nreturns;
119 cell_t ihandle;
120 cell_t phandle;
121 } args;
122
123 args.name = ADR2CELL("instance-to-package");
124 args.nargs = 1;
125 args.nreturns = 1;
126 args.ihandle = HDL2CELL(ihandle);
127 if (openfirmware(&args) == -1)
128 return -1;
129 return args.phandle;
130 }
131
132 int
OF_getprop(int handle,char * prop,void * buf,int buflen)133 OF_getprop(int handle, char *prop, void *buf, int buflen)
134 {
135 struct {
136 cell_t name;
137 cell_t nargs;
138 cell_t nreturns;
139 cell_t phandle;
140 cell_t prop;
141 cell_t buf;
142 cell_t buflen;
143 cell_t size;
144 } args;
145
146 args.name = ADR2CELL("getprop");
147 args.nargs = 4;
148 args.nreturns = 1;
149 args.phandle = HDL2CELL(handle);
150 args.prop = ADR2CELL(prop);
151 args.buf = ADR2CELL(buf);
152 args.buflen = buflen;
153 if (openfirmware(&args) == -1)
154 return -1;
155 return args.size;
156 }
157
158 int
OF_open(char * dname)159 OF_open(char *dname)
160 {
161 struct {
162 cell_t name;
163 cell_t nargs;
164 cell_t nreturns;
165 cell_t dname;
166 cell_t handle;
167 } args;
168
169 args.name = ADR2CELL("open");
170 args.nargs = 1;
171 args.nreturns = 1;
172 args.dname = ADR2CELL(dname);
173 if (openfirmware(&args) == -1 ||
174 args.handle == 0)
175 return -1;
176 return args.handle;
177 }
178
179 void
OF_close(int handle)180 OF_close(int handle)
181 {
182 struct {
183 cell_t name;
184 cell_t nargs;
185 cell_t nreturns;
186 cell_t handle;
187 } args;
188
189 args.name = ADR2CELL("close");
190 args.nargs = 1;
191 args.nreturns = 0;
192 args.handle = HDL2CELL(handle);
193 openfirmware(&args);
194 }
195
196 int
OF_write(int handle,void * addr,int len)197 OF_write(int handle, void *addr, int len)
198 {
199 struct {
200 cell_t name;
201 cell_t nargs;
202 cell_t nreturns;
203 cell_t ihandle;
204 cell_t addr;
205 cell_t len;
206 cell_t actual;
207 } args;
208
209 args.name = ADR2CELL("write");
210 args.nargs = 3;
211 args.nreturns = 1;
212 args.ihandle = HDL2CELL(handle);
213 args.addr = ADR2CELL(addr);
214 args.len = len;
215 if (openfirmware(&args) == -1)
216 return -1;
217 return args.actual;
218 }
219
220 int
OF_read(int handle,void * addr,int len)221 OF_read(int handle, void *addr, int len)
222 {
223 struct {
224 cell_t name;
225 cell_t nargs;
226 cell_t nreturns;
227 cell_t ihandle;
228 cell_t addr;
229 cell_t len;
230 cell_t actual;
231 } args;
232
233 args.name = ADR2CELL("read");
234 args.nargs = 3;
235 args.nreturns = 1;
236 args.ihandle = HDL2CELL(handle);
237 args.addr = ADR2CELL(addr);
238 args.len = len;
239 if (openfirmware(&args) == -1) {
240 return -1;
241 }
242 return args.actual;
243 }
244
245 int
OF_seek(int handle,u_quad_t pos)246 OF_seek(int handle, u_quad_t pos)
247 {
248 struct {
249 cell_t name;
250 cell_t nargs;
251 cell_t nreturns;
252 cell_t handle;
253 cell_t poshi;
254 cell_t poslo;
255 cell_t status;
256 } args;
257
258 args.name = ADR2CELL("seek");
259 args.nargs = 3;
260 args.nreturns = 1;
261 args.handle = HDL2CELL(handle);
262 args.poshi = HDQ2CELL_HI(pos);
263 args.poslo = HDQ2CELL_LO(pos);
264 if (openfirmware(&args) == -1) {
265 return -1;
266 }
267 return args.status;
268 }
269
270 void
OF_release(void * virt,u_int size)271 OF_release(void *virt, u_int size)
272 {
273 struct {
274 cell_t name;
275 cell_t nargs;
276 cell_t nreturns;
277 cell_t virt;
278 cell_t size;
279 } args;
280
281 args.name = ADR2CELL("release");
282 args.nargs = 2;
283 args.nreturns = 0;
284 args.virt = ADR2CELL(virt);
285 args.size = size;
286 openfirmware(&args);
287 }
288
289 int
OF_milliseconds(void)290 OF_milliseconds(void)
291 {
292 struct {
293 cell_t name;
294 cell_t nargs;
295 cell_t nreturns;
296 cell_t ms;
297 } args;
298
299 args.name = ADR2CELL("milliseconds");
300 args.nargs = 0;
301 args.nreturns = 1;
302 openfirmware(&args);
303 return args.ms;
304 }
305
306 void
OF_chain(void * virt,u_int size,void (* entry)(),void * arg,u_int len)307 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
308 {
309 extern int64_t romp;
310
311 entry(0, arg, len, (unsigned long)romp, (unsigned long)romp);
312 panic("OF_chain: kernel returned!");
313 __asm("ta 2" : :);
314 }
315
316 static u_int stdin;
317 static u_int stdout;
318 static u_int mmuh = -1;
319 static u_int memh = -1;
320
321 void
setup(void)322 setup(void)
323 {
324 u_int chosen;
325
326 if ((chosen = OF_finddevice("/chosen")) == -1)
327 _rtt();
328 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != sizeof(stdin)
329 || OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) != sizeof(stdout)
330 || OF_getprop(chosen, "mmu", &mmuh, sizeof(mmuh)) != sizeof(mmuh)
331 || OF_getprop(chosen, "memory", &memh, sizeof(memh)) != sizeof(memh))
332 _rtt();
333 }
334
335 /*
336 * The following need either the handle to memory or the handle to the MMU.
337 */
338
339 /*
340 * Grab some address space from the prom
341 *
342 * Only works while the prom is actively mapping us.
343 */
344 static vaddr_t
OF_claim_virt(vaddr_t vaddr,int len)345 OF_claim_virt(vaddr_t vaddr, int len)
346 {
347 struct {
348 cell_t name;
349 cell_t nargs;
350 cell_t nreturns;
351 cell_t method;
352 cell_t ihandle;
353 cell_t align;
354 cell_t len;
355 cell_t vaddr;
356 cell_t status;
357 cell_t retaddr;
358 } args;
359
360 args.name = ADR2CELL("call-method");
361 args.nargs = 5;
362 args.nreturns = 2;
363 args.method = ADR2CELL("claim");
364 args.ihandle = HDL2CELL(mmuh);
365 args.align = 0;
366 args.len = len;
367 args.vaddr = ADR2CELL(vaddr);
368 if (openfirmware(&args) != 0)
369 return -1LL;
370 return (vaddr_t)args.retaddr;
371 }
372
373 /*
374 * Request some address space from the prom
375 *
376 * Only works while the prom is actively mapping us.
377 */
378 static vaddr_t
OF_alloc_virt(int len,int align)379 OF_alloc_virt(int len, int align)
380 {
381 int retaddr=-1;
382 struct {
383 cell_t name;
384 cell_t nargs;
385 cell_t nreturns;
386 cell_t method;
387 cell_t ihandle;
388 cell_t align;
389 cell_t len;
390 cell_t status;
391 cell_t retaddr;
392 } args;
393
394 args.name = ADR2CELL("call-method");
395 args.nargs = 4;
396 args.nreturns = 2;
397 args.method = ADR2CELL("claim");
398 args.ihandle = HDL2CELL(mmuh);
399 args.align = align;
400 args.len = len;
401 args.retaddr = ADR2CELL(&retaddr);
402 if (openfirmware(&args) != 0)
403 return -1LL;
404 return (vaddr_t)args.retaddr;
405 }
406
407 /*
408 * Release some address space to the prom
409 *
410 * Only works while the prom is actively mapping us.
411 */
412 static int
OF_free_virt(vaddr_t vaddr,int len)413 OF_free_virt(vaddr_t vaddr, int len)
414 {
415 struct {
416 cell_t name;
417 cell_t nargs;
418 cell_t nreturns;
419 cell_t method;
420 cell_t ihandle;
421 cell_t len;
422 cell_t vaddr;
423 } args;
424
425 args.name = ADR2CELL("call-method");
426 args.nargs = 4;
427 args.nreturns = 0;
428 args.method = ADR2CELL("release");
429 args.ihandle = HDL2CELL(mmuh);
430 args.vaddr = ADR2CELL(vaddr);
431 args.len = len;
432 return openfirmware(&args);
433 }
434
435
436 /*
437 * Have prom map in some memory
438 *
439 * Only works while the prom is actively mapping us.
440 */
441 static int
OF_map_phys(paddr_t paddr,off_t size,vaddr_t vaddr,int mode)442 OF_map_phys(paddr_t paddr, off_t size, vaddr_t vaddr, int mode)
443 {
444 struct {
445 cell_t name;
446 cell_t nargs;
447 cell_t nreturns;
448 cell_t method;
449 cell_t ihandle;
450 cell_t mode;
451 cell_t size;
452 cell_t vaddr;
453 cell_t paddr_hi;
454 cell_t paddr_lo;
455 } args;
456
457 args.name = ADR2CELL("call-method");
458 args.nargs = 7;
459 args.nreturns = 0;
460 args.method = ADR2CELL("map");
461 args.ihandle = HDL2CELL(mmuh);
462 args.mode = mode;
463 args.size = size;
464 args.vaddr = ADR2CELL(vaddr);
465 args.paddr_hi = HDQ2CELL_HI(paddr);
466 args.paddr_lo = HDQ2CELL_LO(paddr);
467 return openfirmware(&args);
468 }
469
470
471 /*
472 * Request some RAM from the prom
473 *
474 * Only works while the prom is actively mapping us.
475 */
476 static paddr_t
OF_alloc_phys(int len,int align)477 OF_alloc_phys(int len, int align)
478 {
479 struct {
480 cell_t name;
481 cell_t nargs;
482 cell_t nreturns;
483 cell_t method;
484 cell_t ihandle;
485 cell_t align;
486 cell_t len;
487 cell_t status;
488 cell_t phys_hi;
489 cell_t phys_lo;
490 } args;
491
492 args.name = ADR2CELL("call-method");
493 args.nargs = 4;
494 args.nreturns = 3;
495 args.method = ADR2CELL("claim");
496 args.ihandle = HDL2CELL(memh);
497 args.align = align;
498 args.len = len;
499 if (openfirmware(&args) != 0)
500 return -1LL;
501 return (paddr_t)CELL2HDQ(args.phys_hi, args.phys_lo);
502 }
503
504
505 /*
506 * Free some RAM to prom
507 *
508 * Only works while the prom is actively mapping us.
509 */
510 static int
OF_free_phys(paddr_t phys,int len)511 OF_free_phys(paddr_t phys, int len)
512 {
513 struct {
514 cell_t name;
515 cell_t nargs;
516 cell_t nreturns;
517 cell_t method;
518 cell_t ihandle;
519 cell_t len;
520 cell_t phys_hi;
521 cell_t phys_lo;
522 } args;
523
524 args.name = ADR2CELL("call-method");
525 args.nargs = 5;
526 args.nreturns = 0;
527 args.method = ADR2CELL("release");
528 args.ihandle = HDL2CELL(memh);
529 args.len = len;
530 args.phys_hi = HDQ2CELL_HI(phys);
531 args.phys_lo = HDQ2CELL_LO(phys);
532 return openfirmware(&args);
533 }
534
535
536 /*
537 * Claim virtual memory -- does not map it in.
538 */
539
540 void *
OF_claim(void * virt,u_int size,u_int align)541 OF_claim(void *virt, u_int size, u_int align)
542 {
543 /*
544 * Sun Ultra machines run the firmware with VM enabled,
545 * so you need to handle allocating and mapping both
546 * virtual and physical memory. Ugh.
547 */
548 paddr_t paddr;
549 void * newvirt = NULL;
550
551 if (virt == NULL) {
552 virt = (void *)OF_alloc_virt(size, align);
553 if (virt == (void *)-1LL) {
554 printf("OF_alloc_virt(%d,%d) failed w/%x\n",
555 size, align, virt);
556 return virt;
557 }
558 } else {
559 newvirt = (void *)OF_claim_virt((vaddr_t)virt, size);
560 if (newvirt == (void *)-1LL) {
561 printf("OF_claim_virt(%x,%d) failed w/%x\n",
562 virt, size, newvirt);
563 return newvirt;
564 }
565 virt = newvirt;
566 }
567 if ((paddr = OF_alloc_phys(size, align)) == (paddr_t)-1LL) {
568 printf("OF_alloc_phys(%d,%d) failed\n", size, align);
569 OF_free_virt((vaddr_t)virt, size);
570 return (void *)-1LL;
571 }
572 if (OF_map_phys(paddr, size, (vaddr_t)virt, -1) == -1) {
573 printf("OF_map_phys(%x,%d,%x,%d) failed\n",
574 paddr, size, virt, -1);
575 OF_free_phys((paddr_t)paddr, size);
576 OF_free_virt((vaddr_t)virt, size);
577 return (void *)-1LL;
578 }
579 return virt;
580 }
581
582 int
OF_peer(int phandle)583 OF_peer(int phandle)
584 {
585 struct {
586 cell_t name;
587 cell_t nargs;
588 cell_t nreturns;
589 cell_t phandle;
590 cell_t sibling;
591 } args;
592
593 args.name = ADR2CELL("peer");
594 args.nargs = 1;
595 args.nreturns = 1;
596 args.phandle = HDL2CELL(phandle);
597 if (openfirmware(&args) == -1)
598 return 0;
599 return args.sibling;
600 }
601
602 int
OF_child(int phandle)603 OF_child(int phandle)
604 {
605 struct {
606 cell_t name;
607 cell_t nargs;
608 cell_t nreturns;
609 cell_t phandle;
610 cell_t child;
611 } args;
612
613 args.name = ADR2CELL("child");
614 args.nargs = 1;
615 args.nreturns = 1;
616 args.phandle = HDL2CELL(phandle);
617 if (openfirmware(&args) == -1)
618 return 0;
619 return args.child;
620 }
621
622 int
OF_parent(int phandle)623 OF_parent(int phandle)
624 {
625 struct {
626 cell_t name;
627 cell_t nargs;
628 cell_t nreturns;
629 cell_t phandle;
630 cell_t parent;
631 } args;
632
633 args.name = ADR2CELL("parent");
634 args.nargs = 1;
635 args.nreturns = 1;
636 args.phandle = HDL2CELL(phandle);
637 if (openfirmware(&args) == -1)
638 return 0;
639 return args.parent;
640 }
641
642 int
OF_package_to_path(int phandle,char * buf,int buflen)643 OF_package_to_path(int phandle, char *buf, int buflen)
644 {
645 struct {
646 cell_t name;
647 cell_t nargs;
648 cell_t nreturns;
649 cell_t phandle;
650 cell_t buf;
651 cell_t buflen;
652 cell_t length;
653 } args;
654
655 if (buflen > PAGE_SIZE)
656 return -1;
657 args.name = ADR2CELL("package-to-path");
658 args.nargs = 3;
659 args.nreturns = 1;
660 args.phandle = HDL2CELL(phandle);
661 args.buf = ADR2CELL(buf);
662 args.buflen = buflen;
663 if (openfirmware(&args) < 0)
664 return -1;
665 return args.length;
666 }
667
668 void
putchar(int c)669 putchar(int c)
670 {
671 char ch = c;
672
673 if (c == '\n')
674 putchar('\r');
675 OF_write(stdout, &ch, 1);
676 }
677
678 int
getchar(void)679 getchar(void)
680 {
681 unsigned char ch = '\0';
682 int l;
683
684 while ((l = OF_read(stdin, &ch, 1)) != 1)
685 if (l != -2 && l != 0)
686 return -1;
687 return ch;
688 }
689
690 int
cngetc(void)691 cngetc(void)
692 {
693 return getchar();
694 }
695