Locore.c revision 1.3.14.1 1 /* $NetBSD: Locore.c,v 1.3.14.1 2005/04/29 11:28:24 kent 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 #include "openfirm.h"
36
37 #include <machine/cpu.h>
38
39 vaddr_t OF_claim_virt __P((vaddr_t vaddr, int len));
40 vaddr_t OF_alloc_virt __P((int len, int align));
41 int OF_free_virt __P((vaddr_t vaddr, int len));
42 int OF_unmap_virt __P((vaddr_t vaddr, int len));
43 vaddr_t OF_map_phys __P((paddr_t paddr, off_t size, vaddr_t vaddr, int mode));
44 paddr_t OF_alloc_phys __P((int len, int align));
45 paddr_t OF_claim_phys __P((paddr_t phys, int len));
46 int OF_free_phys __P((paddr_t paddr, int len));
47
48 extern int openfirmware(void *);
49
50 void setup __P((void));
51
52 __dead void
53 _rtt()
54 {
55 struct {
56 cell_t name;
57 cell_t nargs;
58 cell_t nreturns;
59 } args;
60
61 args.name = ADR2CELL("exit");
62 args.nargs = 0;
63 args.nreturns = 0;
64 openfirmware(&args);
65 while (1); /* just in case */
66 }
67
68 void
69 OF_enter()
70 {
71 struct {
72 cell_t name;
73 cell_t nargs;
74 cell_t nreturns;
75 } args;
76
77 args.name = ADR2CELL("enter");
78 args.nargs = 0;
79 args.nreturns = 0;
80 openfirmware(&args);
81 }
82
83 int
84 OF_finddevice(name)
85 char *name;
86 {
87 struct {
88 cell_t name;
89 cell_t nargs;
90 cell_t nreturns;
91 cell_t device;
92 cell_t phandle;
93 } args;
94
95 args.name = ADR2CELL("finddevice");
96 args.nargs = 1;
97 args.nreturns = 1;
98 args.device = ADR2CELL(name);
99 if (openfirmware(&args) == -1)
100 return -1;
101 return args.phandle;
102 }
103
104 int
105 OF_instance_to_package(ihandle)
106 int ihandle;
107 {
108 struct {
109 cell_t name;
110 cell_t nargs;
111 cell_t nreturns;
112 cell_t ihandle;
113 cell_t phandle;
114 } args;
115
116 args.name = ADR2CELL("instance-to-package");
117 args.nargs = 1;
118 args.nreturns = 1;
119 args.ihandle = HDL2CELL(ihandle);
120 if (openfirmware(&args) == -1)
121 return -1;
122 return args.phandle;
123 }
124
125 int
126 OF_getprop(handle, prop, buf, buflen)
127 int handle;
128 char *prop;
129 void *buf;
130 int buflen;
131 {
132 struct {
133 cell_t name;
134 cell_t nargs;
135 cell_t nreturns;
136 cell_t phandle;
137 cell_t prop;
138 cell_t buf;
139 cell_t buflen;
140 cell_t size;
141 } args;
142
143 args.name = ADR2CELL("getprop");
144 args.nargs = 4;
145 args.nreturns = 1;
146 args.phandle = HDL2CELL(handle);
147 args.prop = ADR2CELL(prop);
148 args.buf = ADR2CELL(buf);
149 args.buflen = buflen;
150 if (openfirmware(&args) == -1)
151 return -1;
152 return args.size;
153 }
154
155 #ifdef __notyet__ /* Has a bug on FirePower */
156 int
157 OF_setprop(handle, prop, buf, len)
158 u_int handle;
159 char *prop;
160 void *buf;
161 int len;
162 {
163 struct {
164 cell_t name;
165 cell_t nargs;
166 cell_t nreturns;
167 cell_t phandle;
168 cell_t prop;
169 cell_t buf;
170 cell_t len;
171 cell_t size;
172 } args;
173
174 args.name = ADR2CELL("setprop");
175 args.nargs = 4;
176 args.nreturns = 1;
177 args.phandle = HDL2CELL(handle);
178 args.prop = ADR2CELL(prop);
179 args.buf = ADR2CELL(buf);
180 args.len = len;
181 if (openfirmware(&args) == -1)
182 return -1;
183 return args.size;
184 }
185 #endif
186
187 int
188 OF_open(dname)
189 char *dname;
190 {
191 struct {
192 cell_t name;
193 cell_t nargs;
194 cell_t nreturns;
195 cell_t dname;
196 cell_t handle;
197 } args;
198
199 args.name = ADR2CELL("open");
200 args.nargs = 1;
201 args.nreturns = 1;
202 args.dname = ADR2CELL(dname);
203 if (openfirmware(&args) == -1 ||
204 args.handle == 0)
205 return -1;
206 return args.handle;
207 }
208
209 void
210 OF_close(handle)
211 int handle;
212 {
213 struct {
214 cell_t name;
215 cell_t nargs;
216 cell_t nreturns;
217 cell_t handle;
218 } args;
219
220 args.name = ADR2CELL("close");
221 args.nargs = 1;
222 args.nreturns = 1;
223 args.handle = HDL2CELL(handle);
224 openfirmware(&args);
225 }
226
227 int
228 OF_write(handle, addr, len)
229 int handle;
230 void *addr;
231 int len;
232 {
233 struct {
234 cell_t name;
235 cell_t nargs;
236 cell_t nreturns;
237 cell_t ihandle;
238 cell_t addr;
239 cell_t len;
240 cell_t actual;
241 } args;
242
243 args.name = ADR2CELL("write");
244 args.nargs = 3;
245 args.nreturns = 1;
246 args.ihandle = HDL2CELL(handle);
247 args.addr = ADR2CELL(addr);
248 args.len = len;
249 if (openfirmware(&args) == -1)
250 return -1;
251 return args.actual;
252 }
253
254 int
255 OF_read(handle, addr, len)
256 int handle;
257 void *addr;
258 int len;
259 {
260 struct {
261 cell_t name;
262 cell_t nargs;
263 cell_t nreturns;
264 cell_t ihandle;
265 cell_t addr;
266 cell_t len;
267 cell_t actual;
268 } args;
269
270 args.name = ADR2CELL("read");
271 args.nargs = 3;
272 args.nreturns = 1;
273 args.ihandle = HDL2CELL(handle);
274 args.addr = ADR2CELL(addr);
275 args.len = len;
276 if (openfirmware(&args) == -1) {
277 return -1;
278 }
279 return args.actual;
280 }
281
282 int
283 OF_seek(handle, pos)
284 int handle;
285 u_quad_t pos;
286 {
287 struct {
288 cell_t name;
289 cell_t nargs;
290 cell_t nreturns;
291 cell_t handle;
292 cell_t poshi;
293 cell_t poslo;
294 cell_t status;
295 } args;
296
297 args.name = ADR2CELL("seek");
298 args.nargs = 3;
299 args.nreturns = 1;
300 args.handle = HDL2CELL(handle);
301 args.poshi = HDL2CELL(pos >> 32);
302 args.poslo = HDL2CELL(pos);
303 if (openfirmware(&args) == -1) {
304 return -1;
305 }
306 return args.status;
307 }
308
309 void
310 OF_release(virt, size)
311 void *virt;
312 u_int size;
313 {
314 struct {
315 cell_t name;
316 cell_t nargs;
317 cell_t nreturns;
318 cell_t virt;
319 cell_t size;
320 } args;
321
322 args.name = ADR2CELL("release");
323 args.nargs = 2;
324 args.nreturns = 0;
325 args.virt = ADR2CELL(virt);
326 args.size = size;
327 openfirmware(&args);
328 }
329
330 int
331 OF_milliseconds()
332 {
333 struct {
334 cell_t name;
335 cell_t nargs;
336 cell_t nreturns;
337 cell_t ms;
338 } args;
339
340 args.name = ADR2CELL("milliseconds");
341 args.nargs = 0;
342 args.nreturns = 1;
343 openfirmware(&args);
344 return args.ms;
345 }
346
347 void
348 OF_chain(virt, size, entry, arg, len)
349 void *virt;
350 u_int size;
351 void (*entry)();
352 void *arg;
353 u_int len;
354 {
355 extern int64_t romp;
356 extern int debug;
357 struct {
358 cell_t name;
359 cell_t nargs;
360 cell_t nreturns;
361 cell_t virt;
362 cell_t size;
363 cell_t entry;
364 cell_t arg;
365 cell_t len;
366 } args;
367
368 args.name = ADR2CELL("chain");
369 args.nargs = 5;
370 args.nreturns = 0;
371 args.virt = ADR2CELL(virt);
372 args.size = size;
373 args.entry = ADR2CELL(entry);
374 args.arg = ADR2CELL(arg);
375 args.len = len;
376 openfirmware(&args);
377 if (debug) {
378 printf("OF_chain: prom returned!\n");
379
380 /* OK, firmware failed us. Try calling prog directly */
381 printf("Calling entry(%p, %p, %x, %lx, %lx)\n", entry, arg, len,
382 (unsigned long)romp, (unsigned long)romp);
383 }
384 entry(0, arg, len, (unsigned long)romp, (unsigned long)romp);
385 panic("OF_chain: kernel returned!");
386 __asm("ta 2" : :);
387 }
388
389 static u_int stdin;
390 static u_int stdout;
391 static u_int mmuh = -1;
392 static u_int memh = -1;
393
394 void
395 setup()
396 {
397 u_int chosen;
398
399 if ((chosen = OF_finddevice("/chosen")) == -1)
400 _rtt();
401 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != sizeof(stdin)
402 || OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) != sizeof(stdout)
403 || OF_getprop(chosen, "mmu", &mmuh, sizeof(mmuh)) != sizeof(mmuh)
404 || OF_getprop(chosen, "memory", &memh, sizeof(memh)) != sizeof(memh))
405 _rtt();
406 }
407
408 /*
409 * The following need either the handle to memory or the handle to the MMU.
410 */
411
412 /*
413 * Grab some address space from the prom
414 *
415 * Only works while the prom is actively mapping us.
416 */
417 vaddr_t
418 OF_claim_virt(vaddr, len)
419 vaddr_t vaddr;
420 int len;
421 {
422 struct {
423 cell_t name;
424 cell_t nargs;
425 cell_t nreturns;
426 cell_t method;
427 cell_t ihandle;
428 cell_t align;
429 cell_t len;
430 cell_t vaddr;
431 cell_t status;
432 cell_t retaddr;
433 } args;
434
435 #ifdef __notyet
436 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
437 OF_printf("OF_claim_virt: cannot get mmuh\r\n");
438 return -1LL;
439 }
440 #endif
441 args.name = ADR2CELL("call-method");
442 args.nargs = 5;
443 args.nreturns = 2;
444 args.method = ADR2CELL("claim");
445 args.ihandle = HDL2CELL(mmuh);
446 args.align = 0;
447 args.len = len;
448 args.vaddr = ADR2CELL(vaddr);
449 if(openfirmware(&args) != 0)
450 return -1LL;
451 return args.retaddr; /* Kluge till we go 64-bit */
452 }
453
454 /*
455 * Request some address space from the prom
456 *
457 * Only works while the prom is actively mapping us.
458 */
459 vaddr_t
460 OF_alloc_virt(len, align)
461 int len;
462 int align;
463 {
464 int retaddr=-1;
465 struct {
466 cell_t name;
467 cell_t nargs;
468 cell_t nreturns;
469 cell_t method;
470 cell_t ihandle;
471 cell_t align;
472 cell_t len;
473 cell_t status;
474 cell_t retaddr;
475 } args;
476
477 #ifdef __notyet
478 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
479 OF_printf("OF_alloc_virt: cannot get mmuh\r\n");
480 return -1LL;
481 }
482 #endif
483 args.name = ADR2CELL("call-method");
484 args.nargs = 4;
485 args.nreturns = 2;
486 args.method = ADR2CELL("claim");
487 args.ihandle = mmuh;
488 args.align = align;
489 args.len = len;
490 args.retaddr = ADR2CELL(&retaddr);
491 if(openfirmware(&args) != 0)
492 return -1LL;
493 return (vaddr_t)args.retaddr; /* Kluge till we go 64-bit */
494 }
495
496 /*
497 * Release some address space to the prom
498 *
499 * Only works while the prom is actively mapping us.
500 */
501 int
502 OF_free_virt(vaddr, len)
503 vaddr_t vaddr;
504 int len;
505 {
506 struct {
507 cell_t name;
508 cell_t nargs;
509 cell_t nreturns;
510 cell_t method;
511 cell_t ihandle;
512 cell_t len;
513 cell_t vaddr;
514 } args;
515
516 #ifdef __notyet
517 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
518 OF_printf("OF_claim_virt: cannot get mmuh\r\n");
519 return -1;
520 }
521 #endif
522 args.name = ADR2CELL("call-method");
523 args.nargs = 4;
524 args.nreturns = 0;
525 args.method = ADR2CELL("release");
526 args.ihandle = HDL2CELL(mmuh);
527 args.vaddr = ADR2CELL(vaddr);
528 args.len = len;
529 return openfirmware(&args);
530 }
531
532
533 /*
534 * Unmap some address space
535 *
536 * Only works while the prom is actively mapping us.
537 */
538 int
539 OF_unmap_virt(vaddr, len)
540 vaddr_t vaddr;
541 int len;
542 {
543 struct {
544 cell_t name;
545 cell_t nargs;
546 cell_t nreturns;
547 cell_t method;
548 cell_t ihandle;
549 cell_t len;
550 cell_t vaddr;
551 } args;
552
553 #ifdef __notyet
554 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
555 OF_printf("OF_claim_virt: cannot get mmuh\r\n");
556 return -1;
557 }
558 #endif
559 args.name = ADR2CELL("call-method");
560 args.nargs = 4;
561 args.nreturns = 0;
562 args.method = ADR2CELL("unmap");
563 args.ihandle = HDL2CELL(mmuh);
564 args.vaddr = ADR2CELL(vaddr);
565 args.len = len;
566 return openfirmware(&args);
567 }
568
569 /*
570 * Have prom map in some memory
571 *
572 * Only works while the prom is actively mapping us.
573 */
574 vaddr_t
575 OF_map_phys(paddr, size, vaddr, mode)
576 paddr_t paddr;
577 off_t size;
578 vaddr_t vaddr;
579 int mode;
580 {
581 struct {
582 cell_t name;
583 cell_t nargs;
584 cell_t nreturns;
585 cell_t method;
586 cell_t ihandle;
587 cell_t mode;
588 cell_t size;
589 cell_t vaddr;
590 cell_t paddr_hi;
591 cell_t paddr_lo;
592 cell_t status;
593 cell_t retaddr;
594 } args;
595
596 #ifdef __notyet
597 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
598 OF_printf("OF_map_phys: cannot get mmuh\r\n");
599 return 0LL;
600 }
601 #endif
602 args.name = ADR2CELL("call-method");
603 args.nargs = 7;
604 args.nreturns = 1;
605 args.method = ADR2CELL("map");
606 args.ihandle = HDL2CELL(mmuh);
607 args.mode = mode;
608 args.size = size;
609 args.vaddr = ADR2CELL(vaddr);
610 args.paddr_hi = ADR2CELL(paddr>>32);
611 args.paddr_lo = ADR2CELL(paddr);
612
613 if (openfirmware(&args) == -1)
614 return -1;
615 if (args.status)
616 return -1;
617 return (vaddr_t)args.retaddr;
618 }
619
620
621 /*
622 * Request some RAM from the prom
623 *
624 * Only works while the prom is actively mapping us.
625 */
626 paddr_t
627 OF_alloc_phys(len, align)
628 int len;
629 int align;
630 {
631 paddr_t paddr;
632 struct {
633 cell_t name;
634 cell_t nargs;
635 cell_t nreturns;
636 cell_t method;
637 cell_t ihandle;
638 cell_t align;
639 cell_t len;
640 cell_t status;
641 cell_t phys_hi;
642 cell_t phys_lo;
643 } args;
644
645 #ifdef __notyet
646 if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
647 OF_printf("OF_alloc_phys: cannot get memh\r\n");
648 return -1LL;
649 }
650 #endif
651 args.name = ADR2CELL("call-method");
652 args.nargs = 4;
653 args.nreturns = 3;
654 args.method = ADR2CELL("claim");
655 args.ihandle = HDL2CELL(memh);
656 args.align = align;
657 args.len = len;
658 if(openfirmware(&args) != 0)
659 return -1LL;
660 paddr = (paddr_t)(args.phys_hi<<32)|((unsigned int)(args.phys_lo));
661 return paddr; /* Kluge till we go 64-bit */
662 }
663
664 /*
665 * Request some specific RAM from the prom
666 *
667 * Only works while the prom is actively mapping us.
668 */
669 paddr_t
670 OF_claim_phys(phys, len)
671 paddr_t phys;
672 int len;
673 {
674 paddr_t paddr;
675 struct {
676 cell_t name;
677 cell_t nargs;
678 cell_t nreturns;
679 cell_t method;
680 cell_t ihandle;
681 cell_t align;
682 cell_t len;
683 cell_t phys_hi;
684 cell_t phys_lo;
685 cell_t status;
686 cell_t res;
687 cell_t rphys_hi;
688 cell_t rphys_lo;
689 } args;
690
691 #ifdef __notyet
692 if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
693 OF_printf("OF_alloc_phys: cannot get memh\r\n");
694 return 0LL;
695 }
696 #endif
697 args.name = ADR2CELL("call-method");
698 args.nargs = 6;
699 args.nreturns = 4;
700 args.method = ADR2CELL("claim");
701 args.ihandle = HDL2CELL(memh);
702 args.align = 0;
703 args.len = len;
704 args.phys_hi = HDL2CELL(phys>>32);
705 args.phys_lo = HDL2CELL(phys);
706 if(openfirmware(&args) != 0)
707 return 0LL;
708 paddr = (paddr_t)(args.rphys_hi<<32)|((unsigned int)(args.rphys_lo));
709 return paddr;
710 }
711
712 /*
713 * Free some RAM to prom
714 *
715 * Only works while the prom is actively mapping us.
716 */
717 int
718 OF_free_phys(phys, len)
719 paddr_t phys;
720 int len;
721 {
722 struct {
723 cell_t name;
724 cell_t nargs;
725 cell_t nreturns;
726 cell_t method;
727 cell_t ihandle;
728 cell_t len;
729 cell_t phys_hi;
730 cell_t phys_lo;
731 } args;
732
733 #ifdef __notyet
734 if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
735 OF_printf("OF_free_phys: cannot get memh\r\n");
736 return -1;
737 }
738 #endif
739 args.name = ADR2CELL("call-method");
740 args.nargs = 5;
741 args.nreturns = 0;
742 args.method = ADR2CELL("release");
743 args.ihandle = HDL2CELL(memh);
744 args.len = len;
745 args.phys_hi = HDL2CELL(phys>>32);
746 args.phys_lo = HDL2CELL(phys);
747 return openfirmware(&args);
748 }
749
750
751 /*
752 * Claim virtual memory -- does not map it in.
753 */
754
755 void *
756 OF_claim(virt, size, align)
757 void *virt;
758 u_int size;
759 u_int align;
760 {
761 #define SUNVMOF
762 #ifndef SUNVMOF
763 struct {
764 cell_t name;
765 cell_t nargs;
766 cell_t nreturns;
767 cell_t virt;
768 cell_t size;
769 cell_t align;
770 cell_t baseaddr;
771 } args;
772
773
774 args.name = ADR2CELL("claim");
775 args.nargs = 3;
776 args.nreturns = 1;
777 args.virt = virt;
778 args.size = size;
779 args.align = align;
780 if (openfirmware(&args) == -1)
781 return (void *)-1;
782 return args.baseaddr;
783 #else
784 /*
785 * Sun Ultra machines run the firmware with VM enabled,
786 * so you need to handle allocating and mapping both
787 * virtual and physical memory. Ugh.
788 */
789
790 paddr_t paddr;
791 void* newvirt = NULL;
792
793 if (virt == NULL) {
794 if ((virt = (void*)OF_alloc_virt(size, align)) == (void*)-1) {
795 printf("OF_alloc_virt(%d,%d) failed w/%x\n", size, align, virt);
796 return (void *)-1;
797 }
798 } else {
799 if ((newvirt = (void*)OF_claim_virt((vaddr_t)virt, size)) == (void*)-1) {
800 printf("OF_claim_virt(%x,%d) failed w/%x\n", virt, size, newvirt);
801 return (void *)-1;
802 }
803 }
804 if ((paddr = OF_alloc_phys(size, align)) == -1) {
805 printf("OF_alloc_phys(%d,%d) failed\n", size, align);
806 OF_free_virt((vaddr_t)virt, size);
807 return (void *)-1;
808 }
809 if (OF_map_phys(paddr, size, (vaddr_t)virt, -1) == -1) {
810 printf("OF_map_phys(%x,%d,%x,%d) failed\n", paddr, size, virt, -1);
811 OF_free_phys((paddr_t)paddr, size);
812 OF_free_virt((vaddr_t)virt, size);
813 return (void *)-1;
814 }
815 return (void *)virt;
816 #endif
817 }
818
819
820 void
821 putchar(c)
822 int c;
823 {
824 char ch = c;
825
826 if (c == '\n')
827 putchar('\r');
828 OF_write(stdout, &ch, 1);
829 }
830
831 int
832 getchar()
833 {
834 unsigned char ch = '\0';
835 int l;
836
837 while ((l = OF_read(stdin, &ch, 1)) != 1)
838 if (l != -2 && l != 0)
839 return -1;
840 return ch;
841 }
842