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