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