Home | History | Annotate | Line # | Download | only in ofwboot
      1  1.35   thorpej /*	$NetBSD: Locore.c,v 1.35 2021/02/28 20:27:40 thorpej Exp $	*/
      2   1.1    tsubai 
      3   1.1    tsubai /*
      4   1.1    tsubai  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
      5   1.1    tsubai  * Copyright (C) 1995, 1996 TooLs GmbH.
      6   1.1    tsubai  * All rights reserved.
      7   1.1    tsubai  *
      8   1.1    tsubai  * Redistribution and use in source and binary forms, with or without
      9   1.1    tsubai  * modification, are permitted provided that the following conditions
     10   1.1    tsubai  * are met:
     11   1.1    tsubai  * 1. Redistributions of source code must retain the above copyright
     12   1.1    tsubai  *    notice, this list of conditions and the following disclaimer.
     13   1.1    tsubai  * 2. Redistributions in binary form must reproduce the above copyright
     14   1.1    tsubai  *    notice, this list of conditions and the following disclaimer in the
     15   1.1    tsubai  *    documentation and/or other materials provided with the distribution.
     16   1.1    tsubai  * 3. All advertising materials mentioning features or use of this software
     17   1.1    tsubai  *    must display the following acknowledgement:
     18   1.1    tsubai  *	This product includes software developed by TooLs GmbH.
     19   1.1    tsubai  * 4. The name of TooLs GmbH may not be used to endorse or promote products
     20   1.1    tsubai  *    derived from this software without specific prior written permission.
     21   1.1    tsubai  *
     22   1.1    tsubai  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
     23   1.1    tsubai  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24   1.1    tsubai  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25   1.1    tsubai  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26   1.1    tsubai  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     27   1.1    tsubai  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     28   1.1    tsubai  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     29   1.1    tsubai  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     30   1.1    tsubai  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     31   1.1    tsubai  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32   1.1    tsubai  */
     33   1.1    tsubai 
     34  1.30       uwe #include <sys/param.h>
     35   1.1    tsubai #include <lib/libsa/stand.h>
     36   1.1    tsubai 
     37   1.1    tsubai #include <machine/cpu.h>
     38  1.32  macallan #include <powerpc/oea/spr.h>
     39   1.1    tsubai 
     40   1.1    tsubai #include "openfirm.h"
     41   1.1    tsubai 
     42  1.15   aymeric static int (*openfirmware)(void *);
     43   1.1    tsubai 
     44  1.20       uwe static void startup(void *, int, int (*)(void *), char *, int)
     45  1.20       uwe 		__attribute__((__used__));
     46  1.15   aymeric static void setup(void);
     47   1.1    tsubai 
     48  1.30       uwe #ifdef HEAP_VARIABLE
     49  1.30       uwe #ifndef HEAP_SIZE
     50  1.30       uwe #define HEAP_SIZE 0x20000
     51  1.30       uwe #endif
     52  1.30       uwe char *heapspace;
     53  1.30       uwe #endif
     54  1.30       uwe 
     55  1.20       uwe static int stack[8192/4 + 4] __attribute__((__used__));
     56   1.1    tsubai 
     57   1.1    tsubai #ifdef XCOFF_GLUE
     58  1.18     perry __asm(
     59  1.12      matt "	.text			\n"
     60  1.12      matt "	.globl	_entry		\n"
     61  1.12      matt "_entry:			\n"
     62  1.12      matt "	.long	_start,0,0	\n"
     63  1.12      matt );
     64  1.20       uwe #endif /* XCOFF_GLUE */
     65   1.1    tsubai 
     66  1.18     perry __asm(
     67  1.12      matt "	.text			\n"
     68  1.12      matt "	.globl	_start		\n"
     69  1.12      matt "_start:			\n"
     70  1.12      matt "	sync			\n"
     71  1.12      matt "	isync			\n"
     72  1.12      matt "	lis	%r1,stack@ha	\n"
     73  1.12      matt "	addi	%r1,%r1,stack@l	\n"
     74  1.12      matt "	addi	%r1,%r1,8192	\n"
     75  1.12      matt "				\n"
     76  1.12      matt "	mfmsr	%r8		\n"
     77  1.12      matt "	li	%r0,0		\n"
     78  1.12      matt "	mtmsr	%r0		\n"
     79  1.12      matt "	isync			\n"
     80  1.12      matt "				\n"
     81  1.25  macallan "				\n" /* test for 601 */
     82  1.27   tsutsui "	mfspr	%r0,287		\n" /* mfpvbr %r0 PVR = 287 */
     83  1.27   tsutsui "	srwi	%r0,%r0,0x10	\n"
     84  1.33     scole "	cmplwi	%r0,0x02	\n" /* 601 CPU = 0x0001 */
     85  1.32  macallan "	blt	2f		\n" /* skip over non-601 BAT setup */
     86  1.33     scole "	cmplwi	%r0,0x39	\n" /* PPC970 */
     87  1.32  macallan "	blt	0f		\n"
     88  1.33     scole "	cmplwi	%r0,0x45	\n" /* PPC970GX */
     89  1.32  macallan "	ble	1f		\n"
     90  1.27   tsutsui 	/* non PPC 601 BATs */
     91  1.32  macallan "0:	li	%r0,0		\n"
     92  1.12      matt "	mtibatu	0,%r0		\n"
     93  1.12      matt "	mtibatu	1,%r0		\n"
     94  1.12      matt "	mtibatu	2,%r0		\n"
     95  1.12      matt "	mtibatu	3,%r0		\n"
     96  1.12      matt "	mtdbatu	0,%r0		\n"
     97  1.12      matt "	mtdbatu	1,%r0		\n"
     98  1.12      matt "	mtdbatu	2,%r0		\n"
     99  1.12      matt "	mtdbatu	3,%r0		\n"
    100  1.12      matt "				\n"
    101  1.27   tsutsui "	li	%r9,0x12	\n"	/* BATL(0, BAT_M, BAT_PP_RW) */
    102  1.12      matt "	mtibatl	0,%r9		\n"
    103  1.12      matt "	mtdbatl	0,%r9		\n"
    104  1.12      matt "	li	%r9,0x1ffe	\n"	/* BATU(0, BAT_BL_256M, BAT_Vs) */
    105  1.12      matt "	mtibatu	0,%r9		\n"
    106  1.12      matt "	mtdbatu	0,%r9		\n"
    107  1.32  macallan "	b	3f		\n"
    108  1.32  macallan 	/* 970 initialization stuff */
    109  1.32  macallan "1:				\n"
    110  1.32  macallan 	/* make sure we're in bridge mode */
    111  1.32  macallan "	clrldi	%r8,%r8,3	\n"
    112  1.32  macallan "	mtmsrd	%r8		\n"
    113  1.32  macallan "	isync			\n"
    114  1.32  macallan 	 /* clear HID5 DCBZ bits (56/57), need to do this early */
    115  1.32  macallan "	mfspr	%r9,0x3f6	\n"
    116  1.32  macallan "	rldimi	%r9,0,6,56	\n"
    117  1.32  macallan "	sync			\n"
    118  1.32  macallan "	mtspr	0x3f6,%r9	\n"
    119  1.32  macallan "	isync			\n"
    120  1.32  macallan "	sync			\n"
    121  1.32  macallan 	/* Setup HID1 features, prefetch + i-cacheability controlled by PTE */
    122  1.32  macallan "	mfspr	%r9,0x3f1	\n"
    123  1.32  macallan "	li	%r11,0x1200	\n"
    124  1.32  macallan "	sldi	%r11,%r11,44	\n"
    125  1.32  macallan "	or	%r9,%r9,%r11	\n"
    126  1.32  macallan "	mtspr	0x3f1,%r9	\n"
    127  1.32  macallan "	isync			\n"
    128  1.32  macallan "	sync			\n"
    129  1.32  macallan "	b	3f		\n"
    130  1.27   tsutsui 	/* PPC 601 BATs */
    131  1.32  macallan "2:	li	%r0,0		\n"
    132  1.26   tsutsui "	mtibatu	0,%r0		\n"
    133  1.27   tsutsui "	mtibatu	1,%r0		\n"
    134  1.27   tsutsui "	mtibatu	2,%r0		\n"
    135  1.27   tsutsui "	mtibatu	3,%r0		\n"
    136  1.27   tsutsui "				\n"
    137  1.27   tsutsui "	li	%r9,0x7f	\n"
    138  1.27   tsutsui "	mtibatl	0,%r9		\n"
    139  1.27   tsutsui "	li	%r9,0x1a	\n"
    140  1.27   tsutsui "	mtibatu	0,%r9		\n"
    141  1.27   tsutsui "				\n"
    142  1.27   tsutsui "	lis	%r9,0x80	\n"
    143  1.27   tsutsui "	addi	%r9,%r9,0x7f	\n"
    144  1.27   tsutsui "	mtibatl	1,%r9		\n"
    145  1.27   tsutsui "	lis	%r9,0x80	\n"
    146  1.27   tsutsui "	addi	%r9,%r9,0x1a	\n"
    147  1.27   tsutsui "	mtibatu	1,%r9		\n"
    148  1.27   tsutsui "				\n"
    149  1.27   tsutsui "	lis	%r9,0x100	\n"
    150  1.27   tsutsui "	addi	%r9,%r9,0x7f	\n"
    151  1.27   tsutsui "	mtibatl	2,%r9		\n"
    152  1.27   tsutsui "	lis	%r9,0x100	\n"
    153  1.27   tsutsui "	addi	%r9,%r9,0x1a	\n"
    154  1.27   tsutsui "	mtibatu	2,%r9		\n"
    155  1.27   tsutsui "				\n"
    156  1.27   tsutsui "	lis	%r9,0x180	\n"
    157  1.27   tsutsui "	addi	%r9,%r9,0x7f	\n"
    158  1.27   tsutsui "	mtibatl	3,%r9		\n"
    159  1.27   tsutsui "	lis	%r9,0x180	\n"
    160  1.27   tsutsui "	addi	%r9,%r9,0x1a	\n"
    161  1.27   tsutsui "	mtibatu	3,%r9		\n"
    162  1.25  macallan "				\n"
    163  1.32  macallan "3:	isync			\n"
    164  1.12      matt "				\n"
    165  1.12      matt "	mtmsr	%r8		\n"
    166  1.12      matt "	isync			\n"
    167  1.12      matt "				\n"
    168  1.16  wrstuden 	/*
    169  1.16  wrstuden 	 * Make sure that .bss is zeroed
    170  1.16  wrstuden 	 */
    171  1.16  wrstuden "				\n"
    172  1.16  wrstuden "	li	%r0,0		\n"
    173  1.16  wrstuden "	lis	%r8,_edata@ha	\n"
    174  1.16  wrstuden "	addi	%r8,%r8,_edata@l\n"
    175  1.16  wrstuden "	lis	%r9,_end@ha	\n"
    176  1.16  wrstuden "	addi	%r9,%r9,_end@l	\n"
    177  1.16  wrstuden "				\n"
    178  1.16  wrstuden "5:	cmpw	0,%r8,%r9	\n"
    179  1.16  wrstuden "	bge	6f		\n"
    180  1.33     scole 	/*
    181  1.33     scole 	 * clear by bytes to avoid ppc601 alignment exceptions
    182  1.33     scole 	 */
    183  1.33     scole "	stb	%r0,0(%r8)	\n"
    184  1.33     scole "	stb	%r0,1(%r8)	\n"
    185  1.33     scole "	stb	%r0,2(%r8)	\n"
    186  1.33     scole "	stb	%r0,3(%r8)	\n"
    187  1.16  wrstuden "	addi	%r8,%r8,4	\n"
    188  1.16  wrstuden "	b	5b		\n"
    189  1.16  wrstuden "				\n"
    190  1.16  wrstuden "6:	b	startup		\n"
    191  1.12      matt );
    192   1.1    tsubai 
    193   1.1    tsubai #if 0
    194   1.1    tsubai static int
    195  1.15   aymeric openfirmware(void *arg)
    196   1.1    tsubai {
    197   1.1    tsubai 
    198  1.18     perry 	__asm volatile ("sync; isync");
    199   1.1    tsubai 	openfirmware_entry(arg);
    200  1.18     perry 	__asm volatile ("sync; isync");
    201   1.1    tsubai }
    202   1.1    tsubai #endif
    203   1.1    tsubai 
    204  1.35   thorpej int	ofw_real_mode;
    205  1.35   thorpej int	ofw_address_cells;
    206  1.35   thorpej int	ofw_size_cells;
    207  1.35   thorpej 
    208  1.35   thorpej int	ofw_root;		/* / */
    209  1.35   thorpej int	ofw_options;		/* /options */
    210  1.35   thorpej int	ofw_openprom;		/* /openprom */
    211  1.35   thorpej int	ofw_chosen;		/* /chosen (package) */
    212  1.35   thorpej int	ofw_stdin;		/* /chosen/stdin */
    213  1.35   thorpej int	ofw_stdout;		/* /chosen/stdout */
    214  1.35   thorpej int	ofw_memory_ihandle;	/* /chosen/memory */
    215  1.35   thorpej int	ofw_mmu_ihandle;	/* /chosen/mmu */
    216  1.35   thorpej 
    217  1.35   thorpej bool
    218  1.35   thorpej ofw_option_truefalse(const char *prop, int proplen)
    219  1.35   thorpej {
    220  1.35   thorpej 	/* These are all supposed to be strings. */
    221  1.35   thorpej 	switch (prop[0]) {
    222  1.35   thorpej 	case 'y':
    223  1.35   thorpej 	case 'Y':
    224  1.35   thorpej 	case 't':
    225  1.35   thorpej 	case 'T':
    226  1.35   thorpej 	case '1':
    227  1.35   thorpej 		return true;
    228  1.35   thorpej 	}
    229  1.35   thorpej 	return false;
    230  1.35   thorpej }
    231  1.35   thorpej 
    232   1.1    tsubai static void
    233  1.15   aymeric startup(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl)
    234   1.1    tsubai {
    235   1.1    tsubai 
    236   1.1    tsubai 	openfirmware = openfirm;
    237   1.1    tsubai 	setup();
    238   1.1    tsubai 	main();
    239   1.1    tsubai 	OF_exit();
    240   1.1    tsubai }
    241   1.1    tsubai 
    242  1.31       uwe #if 0
    243  1.31       uwe void
    244  1.31       uwe OF_enter(void)
    245  1.31       uwe {
    246  1.31       uwe 	static struct {
    247  1.31       uwe 		const char *name;
    248  1.31       uwe 		int nargs;
    249  1.31       uwe 		int nreturns;
    250  1.31       uwe 	} args = {
    251  1.31       uwe 		"enter",
    252  1.31       uwe 		0,
    253  1.31       uwe 		0
    254  1.31       uwe 	};
    255  1.31       uwe 
    256  1.31       uwe 	openfirmware(&args);
    257  1.31       uwe }
    258  1.31       uwe #endif	/* OF_enter */
    259  1.31       uwe 
    260   1.1    tsubai __dead void
    261  1.15   aymeric OF_exit(void)
    262   1.1    tsubai {
    263   1.1    tsubai 	static struct {
    264  1.19       uwe 		const char *name;
    265   1.1    tsubai 		int nargs;
    266   1.1    tsubai 		int nreturns;
    267   1.1    tsubai 	} args = {
    268   1.1    tsubai 		"exit",
    269   1.1    tsubai 		0,
    270   1.1    tsubai 		0
    271   1.1    tsubai 	};
    272   1.1    tsubai 
    273   1.1    tsubai 	openfirmware(&args);
    274   1.1    tsubai 	for (;;);			/* just in case */
    275   1.1    tsubai }
    276   1.1    tsubai 
    277   1.1    tsubai int
    278  1.19       uwe OF_finddevice(const char *name)
    279   1.1    tsubai {
    280   1.1    tsubai 	static struct {
    281  1.19       uwe 		const char *name;
    282   1.1    tsubai 		int nargs;
    283   1.1    tsubai 		int nreturns;
    284  1.19       uwe 		const char *device;
    285   1.1    tsubai 		int phandle;
    286   1.1    tsubai 	} args = {
    287   1.1    tsubai 		"finddevice",
    288   1.1    tsubai 		1,
    289   1.1    tsubai 		1,
    290  1.10   tsutsui 	};
    291  1.10   tsutsui 
    292   1.1    tsubai 	args.device = name;
    293   1.1    tsubai 	if (openfirmware(&args) == -1)
    294   1.1    tsubai 		return -1;
    295   1.1    tsubai 	return args.phandle;
    296   1.1    tsubai }
    297   1.1    tsubai 
    298   1.1    tsubai int
    299  1.15   aymeric OF_instance_to_package(int ihandle)
    300   1.1    tsubai {
    301   1.1    tsubai 	static struct {
    302  1.19       uwe 		const char *name;
    303   1.1    tsubai 		int nargs;
    304   1.1    tsubai 		int nreturns;
    305   1.1    tsubai 		int ihandle;
    306   1.1    tsubai 		int phandle;
    307   1.1    tsubai 	} args = {
    308   1.1    tsubai 		"instance-to-package",
    309   1.1    tsubai 		1,
    310   1.1    tsubai 		1,
    311   1.1    tsubai 	};
    312  1.10   tsutsui 
    313   1.1    tsubai 	args.ihandle = ihandle;
    314   1.1    tsubai 	if (openfirmware(&args) == -1)
    315   1.1    tsubai 		return -1;
    316   1.1    tsubai 	return args.phandle;
    317   1.1    tsubai }
    318   1.1    tsubai 
    319   1.1    tsubai int
    320  1.19       uwe OF_getprop(int handle, const char *prop, void *buf, int buflen)
    321   1.1    tsubai {
    322   1.1    tsubai 	static struct {
    323  1.19       uwe 		const char *name;
    324   1.1    tsubai 		int nargs;
    325   1.1    tsubai 		int nreturns;
    326   1.1    tsubai 		int phandle;
    327  1.19       uwe 		const char *prop;
    328   1.1    tsubai 		void *buf;
    329   1.1    tsubai 		int buflen;
    330   1.1    tsubai 		int size;
    331   1.1    tsubai 	} args = {
    332   1.1    tsubai 		"getprop",
    333   1.1    tsubai 		4,
    334   1.1    tsubai 		1,
    335   1.1    tsubai 	};
    336  1.10   tsutsui 
    337   1.1    tsubai 	args.phandle = handle;
    338   1.1    tsubai 	args.prop = prop;
    339   1.1    tsubai 	args.buf = buf;
    340   1.1    tsubai 	args.buflen = buflen;
    341   1.1    tsubai 	if (openfirmware(&args) == -1)
    342   1.1    tsubai 		return -1;
    343   1.1    tsubai 	return args.size;
    344   1.1    tsubai }
    345   1.1    tsubai 
    346   1.1    tsubai #ifdef	__notyet__	/* Has a bug on FirePower */
    347   1.1    tsubai int
    348  1.21       uwe OF_setprop(int handle, const char *prop, void *buf, int len)
    349   1.1    tsubai {
    350   1.1    tsubai 	static struct {
    351  1.19       uwe 		const char *name;
    352   1.1    tsubai 		int nargs;
    353   1.1    tsubai 		int nreturns;
    354   1.1    tsubai 		int phandle;
    355  1.21       uwe 		const char *prop;
    356   1.1    tsubai 		void *buf;
    357   1.1    tsubai 		int len;
    358   1.1    tsubai 		int size;
    359   1.1    tsubai 	} args = {
    360   1.1    tsubai 		"setprop",
    361   1.1    tsubai 		4,
    362   1.1    tsubai 		1,
    363   1.1    tsubai 	};
    364  1.10   tsutsui 
    365   1.1    tsubai 	args.phandle = handle;
    366   1.1    tsubai 	args.prop = prop;
    367   1.1    tsubai 	args.buf = buf;
    368   1.1    tsubai 	args.len = len;
    369   1.1    tsubai 	if (openfirmware(&args) == -1)
    370   1.1    tsubai 		return -1;
    371   1.1    tsubai 	return args.size;
    372   1.1    tsubai }
    373   1.1    tsubai #endif
    374   1.1    tsubai 
    375   1.1    tsubai int
    376  1.21       uwe OF_open(const char *dname)
    377   1.1    tsubai {
    378   1.1    tsubai 	static struct {
    379  1.19       uwe 		const char *name;
    380   1.1    tsubai 		int nargs;
    381   1.1    tsubai 		int nreturns;
    382  1.21       uwe 		const char *dname;
    383   1.1    tsubai 		int handle;
    384   1.1    tsubai 	} args = {
    385   1.1    tsubai 		"open",
    386   1.1    tsubai 		1,
    387   1.1    tsubai 		1,
    388   1.1    tsubai 	};
    389  1.10   tsutsui 
    390   1.1    tsubai #ifdef OFW_DEBUG
    391   1.1    tsubai 	printf("OF_open(%s) -> ", dname);
    392   1.1    tsubai #endif
    393   1.1    tsubai 	args.dname = dname;
    394   1.1    tsubai 	if (openfirmware(&args) == -1 ||
    395   1.1    tsubai 	    args.handle == 0) {
    396   1.1    tsubai #ifdef OFW_DEBUG
    397   1.1    tsubai 		printf("lose\n");
    398   1.1    tsubai #endif
    399   1.1    tsubai 		return -1;
    400   1.1    tsubai 	}
    401   1.1    tsubai #ifdef OFW_DEBUG
    402   1.1    tsubai 	printf("%d\n", args.handle);
    403   1.1    tsubai #endif
    404   1.1    tsubai 	return args.handle;
    405   1.1    tsubai }
    406   1.1    tsubai 
    407   1.1    tsubai void
    408  1.15   aymeric OF_close(int handle)
    409   1.1    tsubai {
    410   1.1    tsubai 	static struct {
    411  1.19       uwe 		const char *name;
    412   1.1    tsubai 		int nargs;
    413   1.1    tsubai 		int nreturns;
    414   1.1    tsubai 		int handle;
    415   1.1    tsubai 	} args = {
    416   1.1    tsubai 		"close",
    417   1.1    tsubai 		1,
    418   1.1    tsubai 		0,
    419   1.1    tsubai 	};
    420  1.10   tsutsui 
    421   1.1    tsubai #ifdef OFW_DEBUG
    422   1.1    tsubai 	printf("OF_close(%d)\n", handle);
    423   1.1    tsubai #endif
    424   1.1    tsubai 	args.handle = handle;
    425   1.1    tsubai 	openfirmware(&args);
    426   1.1    tsubai }
    427   1.1    tsubai 
    428   1.1    tsubai int
    429  1.15   aymeric OF_write(int handle, void *addr, int len)
    430   1.1    tsubai {
    431   1.1    tsubai 	static struct {
    432  1.19       uwe 		const char *name;
    433   1.1    tsubai 		int nargs;
    434   1.1    tsubai 		int nreturns;
    435   1.1    tsubai 		int ihandle;
    436   1.1    tsubai 		void *addr;
    437   1.1    tsubai 		int len;
    438   1.1    tsubai 		int actual;
    439   1.1    tsubai 	} args = {
    440   1.1    tsubai 		"write",
    441   1.1    tsubai 		3,
    442   1.1    tsubai 		1,
    443   1.1    tsubai 	};
    444   1.1    tsubai 
    445   1.1    tsubai #ifdef OFW_DEBUG
    446   1.1    tsubai 	if (len != 1)
    447  1.15   aymeric 		printf("OF_write(%d, %p, %x) -> ", handle, addr, len);
    448   1.1    tsubai #endif
    449   1.1    tsubai 	args.ihandle = handle;
    450   1.1    tsubai 	args.addr = addr;
    451   1.1    tsubai 	args.len = len;
    452   1.1    tsubai 	if (openfirmware(&args) == -1) {
    453   1.1    tsubai #ifdef OFW_DEBUG
    454   1.1    tsubai 		printf("lose\n");
    455   1.1    tsubai #endif
    456   1.1    tsubai 		return -1;
    457   1.1    tsubai 	}
    458   1.1    tsubai #ifdef OFW_DEBUG
    459   1.1    tsubai 	if (len != 1)
    460   1.1    tsubai 		printf("%x\n", args.actual);
    461   1.1    tsubai #endif
    462   1.1    tsubai 	return args.actual;
    463   1.1    tsubai }
    464   1.1    tsubai 
    465   1.1    tsubai int
    466  1.15   aymeric OF_read(int handle, void *addr, int len)
    467   1.1    tsubai {
    468   1.1    tsubai 	static struct {
    469  1.19       uwe 		const char *name;
    470   1.1    tsubai 		int nargs;
    471   1.1    tsubai 		int nreturns;
    472   1.1    tsubai 		int ihandle;
    473   1.1    tsubai 		void *addr;
    474   1.1    tsubai 		int len;
    475   1.1    tsubai 		int actual;
    476   1.1    tsubai 	} args = {
    477   1.1    tsubai 		"read",
    478   1.1    tsubai 		3,
    479   1.1    tsubai 		1,
    480   1.1    tsubai 	};
    481   1.1    tsubai 
    482   1.1    tsubai #ifdef OFW_DEBUG
    483   1.1    tsubai 	if (len != 1)
    484  1.15   aymeric 		printf("OF_read(%d, %p, %x) -> ", handle, addr, len);
    485   1.1    tsubai #endif
    486   1.1    tsubai 	args.ihandle = handle;
    487   1.1    tsubai 	args.addr = addr;
    488   1.1    tsubai 	args.len = len;
    489   1.1    tsubai 	if (openfirmware(&args) == -1) {
    490   1.1    tsubai #ifdef OFW_DEBUG
    491   1.1    tsubai 		printf("lose\n");
    492   1.1    tsubai #endif
    493   1.1    tsubai 		return -1;
    494   1.1    tsubai 	}
    495   1.1    tsubai #ifdef OFW_DEBUG
    496   1.1    tsubai 	if (len != 1)
    497   1.1    tsubai 		printf("%x\n", args.actual);
    498   1.1    tsubai #endif
    499   1.1    tsubai 	return args.actual;
    500   1.1    tsubai }
    501   1.1    tsubai 
    502   1.1    tsubai int
    503  1.15   aymeric OF_seek(int handle, u_quad_t pos)
    504   1.1    tsubai {
    505   1.1    tsubai 	static struct {
    506  1.19       uwe 		const char *name;
    507   1.1    tsubai 		int nargs;
    508   1.1    tsubai 		int nreturns;
    509   1.1    tsubai 		int handle;
    510   1.1    tsubai 		int poshi;
    511   1.1    tsubai 		int poslo;
    512   1.1    tsubai 		int status;
    513   1.1    tsubai 	} args = {
    514   1.1    tsubai 		"seek",
    515   1.1    tsubai 		3,
    516   1.1    tsubai 		1,
    517   1.1    tsubai 	};
    518  1.10   tsutsui 
    519   1.1    tsubai #ifdef OFW_DEBUG
    520   1.1    tsubai 	printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos);
    521   1.1    tsubai #endif
    522   1.1    tsubai 	args.handle = handle;
    523   1.1    tsubai 	args.poshi = (int)(pos >> 32);
    524   1.1    tsubai 	args.poslo = (int)pos;
    525   1.1    tsubai 	if (openfirmware(&args) == -1) {
    526   1.1    tsubai #ifdef OFW_DEBUG
    527   1.1    tsubai 		printf("lose\n");
    528   1.1    tsubai #endif
    529   1.1    tsubai 		return -1;
    530   1.1    tsubai 	}
    531   1.1    tsubai #ifdef OFW_DEBUG
    532   1.1    tsubai 	printf("%d\n", args.status);
    533   1.1    tsubai #endif
    534   1.1    tsubai 	return args.status;
    535   1.1    tsubai }
    536   1.1    tsubai 
    537   1.1    tsubai void *
    538  1.15   aymeric OF_claim(void *virt, u_int size, u_int align)
    539   1.1    tsubai {
    540   1.1    tsubai 	static struct {
    541  1.19       uwe 		const char *name;
    542   1.1    tsubai 		int nargs;
    543   1.1    tsubai 		int nreturns;
    544   1.1    tsubai 		void *virt;
    545   1.1    tsubai 		u_int size;
    546   1.1    tsubai 		u_int align;
    547   1.1    tsubai 		void *baseaddr;
    548   1.1    tsubai 	} args = {
    549   1.1    tsubai 		"claim",
    550   1.1    tsubai 		3,
    551   1.1    tsubai 		1,
    552   1.1    tsubai 	};
    553   1.1    tsubai 
    554   1.1    tsubai #ifdef OFW_DEBUG
    555  1.15   aymeric 	printf("OF_claim(%p, %x, %x) -> ", virt, size, align);
    556   1.1    tsubai #endif
    557   1.1    tsubai 	args.virt = virt;
    558   1.1    tsubai 	args.size = size;
    559   1.1    tsubai 	args.align = align;
    560   1.1    tsubai 	if (openfirmware(&args) == -1) {
    561   1.1    tsubai #ifdef OFW_DEBUG
    562   1.1    tsubai 		printf("lose\n");
    563   1.1    tsubai #endif
    564   1.1    tsubai 		return (void *)-1;
    565   1.1    tsubai 	}
    566   1.1    tsubai #ifdef OFW_DEBUG
    567  1.15   aymeric 	printf("%p\n", args.baseaddr);
    568   1.1    tsubai #endif
    569   1.1    tsubai 	return args.baseaddr;
    570   1.1    tsubai }
    571   1.1    tsubai 
    572   1.1    tsubai void
    573  1.15   aymeric OF_release(void *virt, u_int size)
    574   1.1    tsubai {
    575   1.1    tsubai 	static struct {
    576  1.19       uwe 		const char *name;
    577   1.1    tsubai 		int nargs;
    578   1.1    tsubai 		int nreturns;
    579   1.1    tsubai 		void *virt;
    580   1.1    tsubai 		u_int size;
    581   1.1    tsubai 	} args = {
    582   1.1    tsubai 		"release",
    583   1.1    tsubai 		2,
    584   1.1    tsubai 		0,
    585   1.1    tsubai 	};
    586  1.10   tsutsui 
    587   1.1    tsubai #ifdef OFW_DEBUG
    588  1.15   aymeric 	printf("OF_release(%p, %x)\n", virt, size);
    589   1.1    tsubai #endif
    590   1.1    tsubai 	args.virt = virt;
    591   1.1    tsubai 	args.size = size;
    592   1.1    tsubai 	openfirmware(&args);
    593   1.1    tsubai }
    594   1.1    tsubai 
    595   1.1    tsubai int
    596  1.15   aymeric OF_milliseconds(void)
    597   1.1    tsubai {
    598   1.1    tsubai 	static struct {
    599  1.19       uwe 		const char *name;
    600   1.1    tsubai 		int nargs;
    601   1.1    tsubai 		int nreturns;
    602   1.1    tsubai 		int ms;
    603   1.1    tsubai 	} args = {
    604   1.1    tsubai 		"milliseconds",
    605   1.1    tsubai 		0,
    606   1.1    tsubai 		1,
    607   1.1    tsubai 	};
    608  1.10   tsutsui 
    609   1.1    tsubai 	openfirmware(&args);
    610   1.1    tsubai 	return args.ms;
    611   1.1    tsubai }
    612   1.1    tsubai 
    613   1.1    tsubai #ifdef	__notyet__
    614   1.1    tsubai void
    615  1.15   aymeric OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
    616   1.1    tsubai {
    617   1.1    tsubai 	static struct {
    618  1.19       uwe 		const char *name;
    619   1.1    tsubai 		int nargs;
    620   1.1    tsubai 		int nreturns;
    621   1.1    tsubai 		void *virt;
    622   1.1    tsubai 		u_int size;
    623   1.1    tsubai 		void (*entry)();
    624   1.1    tsubai 		void *arg;
    625   1.1    tsubai 		u_int len;
    626   1.1    tsubai 	} args = {
    627   1.1    tsubai 		"chain",
    628   1.1    tsubai 		5,
    629   1.1    tsubai 		0,
    630   1.1    tsubai 	};
    631   1.1    tsubai 
    632   1.1    tsubai 	args.virt = virt;
    633   1.1    tsubai 	args.size = size;
    634   1.1    tsubai 	args.entry = entry;
    635   1.1    tsubai 	args.arg = arg;
    636   1.1    tsubai 	args.len = len;
    637   1.1    tsubai 	openfirmware(&args);
    638   1.1    tsubai }
    639   1.1    tsubai #else
    640   1.1    tsubai void
    641  1.15   aymeric OF_chain(void *virt, u_int size, boot_entry_t entry, void *arg, u_int len)
    642   1.1    tsubai {
    643   1.1    tsubai 	/*
    644   1.1    tsubai 	 * This is a REALLY dirty hack till the firmware gets this going
    645   1.1    tsubai 	 */
    646   1.1    tsubai #if 0
    647   1.1    tsubai 	OF_release(virt, size);
    648   1.1    tsubai #endif
    649   1.1    tsubai 	entry(0, 0, openfirmware, arg, len);
    650   1.1    tsubai }
    651   1.1    tsubai #endif
    652   1.5    tsubai 
    653   1.5    tsubai int
    654  1.35   thorpej OF_call_method(const char *method, int ihandle, int nargs, int nreturns,
    655  1.35   thorpej     int *cells)
    656   1.5    tsubai {
    657   1.5    tsubai 	static struct {
    658  1.19       uwe 		const char *name;
    659   1.5    tsubai 		int nargs;
    660   1.5    tsubai 		int nreturns;
    661  1.21       uwe 		const char *method;
    662   1.5    tsubai 		int ihandle;
    663   1.5    tsubai 		int args_n_results[12];
    664   1.5    tsubai 	} args = {
    665   1.5    tsubai 		"call-method",
    666   1.5    tsubai 		2,
    667   1.5    tsubai 		1,
    668   1.5    tsubai 	};
    669   1.5    tsubai 	int *ip, n;
    670   1.5    tsubai 
    671   1.5    tsubai 	if (nargs > 6)
    672   1.5    tsubai 		return -1;
    673  1.35   thorpej 
    674   1.5    tsubai 	args.nargs = nargs + 2;
    675   1.5    tsubai 	args.nreturns = nreturns + 1;
    676   1.5    tsubai 	args.method = method;
    677   1.5    tsubai 	args.ihandle = ihandle;
    678  1.35   thorpej 
    679   1.5    tsubai 	for (ip = args.args_n_results + (n = nargs); --n >= 0;)
    680  1.35   thorpej 		*--ip = *cells++;
    681   1.5    tsubai 
    682   1.9       wiz 	if (openfirmware(&args) == -1) {
    683   1.5    tsubai 		return -1;
    684   1.9       wiz 	}
    685  1.35   thorpej 
    686   1.9       wiz 	if (args.args_n_results[nargs]) {
    687   1.5    tsubai 		return args.args_n_results[nargs];
    688   1.9       wiz 	}
    689  1.35   thorpej 
    690   1.5    tsubai 	for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
    691  1.35   thorpej 		*cells++ = *--ip;
    692  1.35   thorpej 
    693   1.5    tsubai 	return 0;
    694   1.5    tsubai }
    695   1.1    tsubai 
    696   1.1    tsubai static void
    697  1.15   aymeric setup(void)
    698   1.1    tsubai {
    699  1.35   thorpej 	char prop[32];
    700  1.35   thorpej 	int proplen;
    701  1.35   thorpej 	const char *reason = NULL;
    702   1.1    tsubai 
    703  1.35   thorpej 	if ((ofw_chosen = OF_finddevice("/chosen")) == -1)
    704   1.1    tsubai 		OF_exit();
    705  1.35   thorpej 	if (OF_getprop(ofw_chosen, "stdin", &ofw_stdin, sizeof(ofw_stdin)) !=
    706  1.35   thorpej 	    sizeof(ofw_stdin) ||
    707  1.35   thorpej 	    OF_getprop(ofw_chosen, "stdout", &ofw_stdout, sizeof(ofw_stdout)) !=
    708  1.35   thorpej 	    sizeof(ofw_stdout))
    709   1.1    tsubai 		OF_exit();
    710  1.30       uwe 
    711  1.35   thorpej 	if (ofw_stdout == 0) {
    712  1.34       rin 		/* screen should be console, but it is not open */
    713  1.35   thorpej 		ofw_stdout = OF_open("screen");
    714  1.34       rin 	}
    715  1.34       rin 
    716  1.30       uwe #ifdef HEAP_VARIABLE
    717  1.32  macallan 	uint32_t pvr, vers, hsize = HEAP_SIZE;
    718  1.32  macallan 
    719  1.32  macallan 	__asm volatile ("mfpvr %0" : "=r"(pvr));
    720  1.32  macallan 	vers = pvr >> 16;
    721  1.32  macallan 	if (vers >= IBM970 && vers <= IBM970GX) hsize = 0x800000;
    722  1.32  macallan 
    723  1.32  macallan 	heapspace = OF_claim(0, hsize, NBPG);
    724  1.30       uwe 	if (heapspace == (char *)-1) {
    725  1.30       uwe 		panic("Failed to allocate heap");
    726  1.30       uwe 	}
    727  1.30       uwe 
    728  1.30       uwe 	setheap(heapspace, heapspace + HEAP_SIZE);
    729  1.30       uwe #endif	/* HEAP_VARIABLE */
    730  1.35   thorpej 
    731  1.35   thorpej 	ofw_root = OF_finddevice("/");
    732  1.35   thorpej 	ofw_options = OF_finddevice("/options");
    733  1.35   thorpej 	ofw_openprom = OF_finddevice("/openprom");
    734  1.35   thorpej 	ofw_chosen = OF_finddevice("/chosen");
    735  1.35   thorpej 
    736  1.35   thorpej 	if (ofw_root == -1) {
    737  1.35   thorpej 		reason = "No root node";
    738  1.35   thorpej 		goto bad_environment;
    739  1.35   thorpej 	}
    740  1.35   thorpej 	if (ofw_chosen == -1) {
    741  1.35   thorpej 		reason = "No chosen node";
    742  1.35   thorpej 		goto bad_environment;
    743  1.35   thorpej 	}
    744  1.35   thorpej 
    745  1.35   thorpej 	if (ofw_options != -1) {
    746  1.35   thorpej 		proplen = OF_getprop(ofw_options, "real-mode?", prop,
    747  1.35   thorpej 		    sizeof(prop));
    748  1.35   thorpej 		if (proplen > 0) {
    749  1.35   thorpej 			ofw_real_mode = ofw_option_truefalse(prop, proplen);
    750  1.35   thorpej 		}
    751  1.35   thorpej 	}
    752  1.35   thorpej 
    753  1.35   thorpej 	/*
    754  1.35   thorpej 	 * Get #address-cells and #size-cells.
    755  1.35   thorpej 	 */
    756  1.35   thorpej 	ofw_address_cells = 1;
    757  1.35   thorpej 	ofw_size_cells = 1;
    758  1.35   thorpej 	OF_getprop(ofw_root, "#address-cells", &ofw_address_cells,
    759  1.35   thorpej 		   sizeof(ofw_address_cells));
    760  1.35   thorpej 	OF_getprop(ofw_root, "#size-cells", &ofw_size_cells,
    761  1.35   thorpej 		   sizeof(ofw_size_cells));
    762  1.35   thorpej 
    763  1.35   thorpej 	/* See loadfile_machdep.c */
    764  1.35   thorpej 	if (ofw_size_cells != 1) {
    765  1.35   thorpej 		printf("#size-cells = %d not yet supported\n", ofw_size_cells);
    766  1.35   thorpej 		reason = "unsupported #size-cells";
    767  1.35   thorpej 		goto bad_environment;
    768  1.35   thorpej 	}
    769  1.35   thorpej 
    770  1.35   thorpej 	/*
    771  1.35   thorpej 	 * Get the ihandle on /chosen/memory and /chosen/mmu.
    772  1.35   thorpej 	 */
    773  1.35   thorpej 	ofw_memory_ihandle = -1;
    774  1.35   thorpej 	ofw_mmu_ihandle = -1;
    775  1.35   thorpej 	OF_getprop(ofw_chosen, "memory", &ofw_memory_ihandle,
    776  1.35   thorpej 		   sizeof(ofw_memory_ihandle));
    777  1.35   thorpej 	OF_getprop(ofw_chosen, "mmu", &ofw_mmu_ihandle,
    778  1.35   thorpej 		   sizeof(ofw_mmu_ihandle));
    779  1.35   thorpej 	if (ofw_memory_ihandle == -1) {
    780  1.35   thorpej 		reason = "no /chosen/memory";
    781  1.35   thorpej 		goto bad_environment;
    782  1.35   thorpej 	}
    783  1.35   thorpej 	if (ofw_mmu_ihandle == -1) {
    784  1.35   thorpej 		reason = "no /chosen/mmu";
    785  1.35   thorpej 		goto bad_environment;
    786  1.35   thorpej 	}
    787  1.35   thorpej 
    788  1.35   thorpej 	return;
    789  1.35   thorpej 
    790  1.35   thorpej  bad_environment:
    791  1.35   thorpej 	if (reason == NULL) {
    792  1.35   thorpej 		reason = "unknown reason";
    793  1.35   thorpej 	}
    794  1.35   thorpej 	printf("Invalid Openfirmware environment: %s\n", reason);
    795  1.35   thorpej 	OF_exit();
    796   1.1    tsubai }
    797   1.1    tsubai 
    798   1.1    tsubai void
    799  1.15   aymeric putchar(int c)
    800   1.1    tsubai {
    801   1.1    tsubai 	char ch = c;
    802   1.1    tsubai 
    803   1.1    tsubai 	if (c == '\n')
    804   1.1    tsubai 		putchar('\r');
    805  1.35   thorpej 	OF_write(ofw_stdout, &ch, 1);
    806   1.1    tsubai }
    807   1.1    tsubai 
    808   1.1    tsubai int
    809  1.15   aymeric getchar(void)
    810   1.1    tsubai {
    811   1.1    tsubai 	unsigned char ch = '\0';
    812   1.1    tsubai 	int l;
    813   1.1    tsubai 
    814  1.35   thorpej 	while ((l = OF_read(ofw_stdin, &ch, 1)) != 1)
    815   1.1    tsubai 		if (l != -2 && l != 0)
    816   1.1    tsubai 			return -1;
    817   1.1    tsubai 	return ch;
    818   1.1    tsubai }
    819