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