xref: /netbsd-src/sys/arch/powerpc/oea/ofw_subr.S (revision eb7c1594f145c931049e1fd9eb056a5987e87e59)
1/*	$NetBSD: ofw_subr.S,v 1.2 2003/02/13 15:02:49 matt 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
35	.local	firmstk
36	.local	openfirmware_entry
37	.local	ofwsrsave
38	.local	OF_buffer
39
40	.data
41GLOBAL(ofmsr)
42	.long	0,0,0,0,0		/* msr & sprg[0-3] used in OF */
43
44GLOBAL(ofwsprg0save)
45	.long	0
46
47	.comm	firmstk,NBPG,8
48	.comm	OF_buffer,NBPG,4
49	.comm	openfirmware_entry,4,4	/* openfirmware entry point */
50	.comm	ofwsrsave,64,4		/* openfirmware SR savearea */
51
52/*
53 * Called by start to save the initial OFW state so we can restore it
54 * when call back to OFW.
55 */
56ENTRY_NOPROFILE(ofwinit)
57#ifdef	FIRMWORKSBUGS
58	mfmsr	0
59	andi.	0,0,PSL_IR|PSL_DR
60	beq	1f
61
62	mflr	30
63	bl	_C_LABEL(ofwr_init)
64	mtlr	30
651:
66#endif
67	lis	8,openfirmware_entry@ha
68	stw	5,openfirmware_entry@l(8) /* save client interface handler*/
69
70	mfmsr	0
71	lis	9,ofmsr@ha
72	stwu	0,ofmsr@l(9)		/* save initial MSR value */
73
74        mfsprg  0,0			/* save SPRGs */
75       	stwu	0,4(9)
76        mfsprg  0,1
77       	stwu	0,4(9)
78        mfsprg  0,2
79       	stwu	0,4(9)
80        mfsprg  0,3
81       	stw	0,4(9)
82
83	lis	8,OF_buffer@ha
84	addi	8,8,OF_buffer@l
85	lis	9,_C_LABEL(OF_buf)@ha
86	stw	8,_C_LABEL(OF_buf)@l(9)
87
88	blr
89
90/*
91 * OpenFirmware entry point
92 */
93	.text
94ENTRY(openfirmware)
95	mflr	0			/* save return address */
96	stw	0,4(1)
97	stwu	1,-16(1)		/* setup stack frame */
98
99	mfmsr	4			/* save msr */
100	stw	4,8(1)
101
102	lis	4,openfirmware_entry@ha	/* get firmware entry point */
103	lwz	4,openfirmware_entry@l(4)
104	mtlr	4
105
106	li	0,0			/* clear battable translations */
107	mtdbatu	2,0
108	mtdbatu	3,0
109	mtibatu	2,0
110	mtibatu	3,0
111
112	lis	4,ofwsrsave@ha		/* save current SRs */
113	addi	4,4,ofwsrsave@l
114	li	5,0
1151:	mfsrin	0,5
116	stw	0,0(4)
117	addi	4,4,4
118	addis	5,5,0x10000000@h
119	cmpwi	5,0
120	bne	1b
121
122	mfsprg	5,0			/* save current sprg0 (curcpu) */
123	lis	4,ofwsprg0save@ha
124	addi	4,4,ofwsprg0save@l
125	stw	5,0(4)
126
127	lis	4,_C_LABEL(ofw_pmap)@ha	/* load OFW SR */
128	addi	4,4,_C_LABEL(ofw_pmap)@l
129	lwz	0,PM_KERNELSR(4)
130	cmpwi	0,0			/* pm_sr[KERNEL_SR] == 0? */
131	beq	2f			/* then skip (not initialized yet) */
132	li	5,0
1331:	lwz	0,0(4)
134	mtsrin	0,5
135	addi	4,4,4
136	addis	5,5,0x10000000@h
137	cmpwi	5,0
138	bne	1b
1392:
140	lis	4,ofmsr@ha		/* Open Firmware msr + sprg[0-3] */
141	lwzu	5,ofmsr+16@l(4)
142	mtsprg	3,5
143	lwzu	5,-4(4)
144	mtsprg	2,5
145	lwzu	5,-4(4)
146	mtsprg	1,5
147	lwzu	5,-4(4)
148	mtsprg	0,5
149	lwz	5,-4(4)
150	mtmsr	5
151	isync
152
153	blrl				/* call Open Firmware */
154
155	lis	4,ofwsprg0save@ha	/* restore saved sprg0 (curcpu) */
156	addi	4,4,ofwsprg0save@l
157	lwz	5,0(4)
158	mtsprg	0,5
159
160	lis	4,ofwsrsave@ha		/* restore saved SRs */
161	addi	4,4,ofwsrsave@l
162	li	5,0
1631:	lwz	0,0(4)
164	mtsrin	0,5
165	addi	4,4,4
166	addis	5,5,0x10000000@h
167	cmpwi	5,0
168	bne	1b
169
170	lwz	4,8(1)			/* restore msr */
171	mtmsr	4
172	isync
173
174	lwz	1,0(1)			/* and return */
175	lwz	0,4(1)
176	mtlr	0
177	blr
178
179/*
180 * Switch to/from OpenFirmware real mode stack
181 *
182 * Note: has to be called as the very first thing in OpenFirmware interface
183 * routines.
184 * E.g.:
185 * int
186 * OF_xxx(arg1, arg2)
187 * type arg1, arg2;
188 * {
189 *	static struct {
190 *		char *name;
191 *		int nargs;
192 *		int nreturns;
193 *		char *method;
194 *		int arg1;
195 *		int arg2;
196 *		int ret;
197 *	} args = {
198 *		"xxx",
199 *		2,
200 *		1,
201 *	};
202 *
203 *	ofw_stack();
204 *	args.arg1 = arg1;
205 *	args.arg2 = arg2;
206 *	if (openfirmware(&args) < 0)
207 *		return -1;
208 *	return args.ret;
209 * }
210 */
211
212ENTRY(ofw_stack)
213	mfmsr	8			/* turn off interrupts */
214	andi.	0,8,~(PSL_EE|PSL_RI)@l
215	mtmsr	0
216	stw	8,4(1)			/* abuse return address slot */
217
218	lwz	5,0(1)			/* get length of stack frame */
219	subf	5,1,5
220
221	lis	7,firmstk+NBPG-8@ha
222	addi	7,7,firmstk+NBPG-8@l
223	lis	6,ofw_back@ha
224	addi	6,6,ofw_back@l
225	subf	4,5,7			/* make room for stack frame on
226					   new stack */
227	stw	6,-4(7)			/* setup return pointer */
228	stwu	1,-8(7)
229
230	stw	7,-8(4)
231
232	addi	3,1,8
233	addi	1,4,-8
234	subi	5,5,8
235
236	b	_C_LABEL(ofbcopy)	/* and copy it */
237
238ofw_back:
239	lwz	1,0(1)			/* get callers original stack pointer */
240
241	lwz	0,4(1)			/* get saved msr from abused slot */
242	mtmsr	0
243
244	lwz	1,0(1)			/* return */
245	lwz	0,4(1)
246	mtlr	0
247	blr
248