1/*	$NetBSD: ofw_subr.S,v 1.9 2011/06/12 16:35:10 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	.globl	openfirmware_entry
37	.globl	ofwmsr
38	.local	ofwsrsave
39	.local	OF_buffer
40
41	.lcomm	firmstk,NBPG,16
42	.lcomm	OF_buffer,NBPG,4
43	.comm	openfirmware_entry,4,4	/* openfirmware entry point */
44	.lcomm	ofwsrsave,64,4		/* openfirmware SR savearea */
45	.comm	ofwmsr,20,4		/* msr & sprg[0-3] used in OF */
46	.comm	ofwreal_incharge,4,4
47
48/*
49 * Called by start to save the initial OFW state so we can restore it
50 * when call back to OFW.
51 */
52ENTRY_NOPROFILE(ofwinit)
53#ifdef	FIRMWORKSBUGS
54	mfmsr	%r0
55	andi.	%r0,%r0,PSL_IR|PSL_DR
56	beq	1f
57
58	li	%r8,1
59	lis	%r9,ofwreal_incharge@ha
60	stw	%r8,ofwreal_incharge@l(%r9)
61
62	mflr	%r30
63	bl	_C_LABEL(ofwr_init)
64	mtlr	%r30
651:
66#endif
67	lis	%r8,openfirmware_entry@ha
68	stw	%r5,openfirmware_entry@l(%r8) /* save client interface handler*/
69
70	mfmsr	%r0
71/*
72 * XXX
73 * doing this here instead of later on in ofwoea_initppc() after setting
74 * up the console and such makes my PowerBook 3400c hang.
75 * Probably just another OF 2.0 weirdness
76 */
77	/*li	%r8,PSL_IP*/
78	/*andc	%r0,%r0,%r8*/			/* make sure PSL_IP is off */
79	lis	%r9,ofwmsr@ha
80	stwu	%r0,ofwmsr@l(%r9)		/* save initial MSR value */
81
82	mfsprg0	%r0				/* save SPRGs */
83	stw	%r0,4(%r9)
84	mfsprg1	%r0
85	stw	%r0,8(%r9)
86	mfsprg2	%r0
87	stw	%r0,12(%r9)
88	mfsprg3	%r0
89	stw	%r0,16(%r9)
90
91	lis	%r8,OF_buffer@ha
92	addi	%r8,%r8,OF_buffer@l
93	lis	%r9,_C_LABEL(OF_buf)@ha
94	stw	%r8,_C_LABEL(OF_buf)@l(%r9)
95
96	blr
97
98/*
99 * OpenFirmware entry point
100 */
101	.text
102ENTRY(openfirmware)
103	mflr	%r0			/* save return address */
104	stw	%r0,4(%r1)
105	stwu	%r1,-32(%r1)		/* setup stack frame */
106
107	lis	%r4,openfirmware_entry@ha	/* get firmware entry point */
108	lwz	%r4,openfirmware_entry@l(%r4)
109	mtlr	%r4
110
111	mfsprg0	%r5			/* save current sprg0 (curcpu) */
112	stw	%r5,16(%r1)
113	mfsprg1	%r5			/* save current sprg1 */
114	stw	%r5,20(%r1)
115	mfsprg2	%r5			/* save current sprg1 */
116	stw	%r5,24(%r1)
117	mfsprg3	%r5			/* save current sprg3 */
118	stw	%r5,28(%r1)
119
120#ifdef FIRMWORKSBUGS
121	lis	%r4,ofwreal_incharge@ha
122	lwz	%r4,ofwreal_incharge@l(%r4)
123	cmpwi	%r4,1
124	bne	1f
125	blrl
126	b	4f
1271:
128#endif
129	mfmsr	%r4			/* save msr */
130	stw	%r4,8(%r1)
131
132	li	%r0,0			/* clear battable translations */
133	mtmsr	%r0
134#if defined (PPC_OEA) || defined (PPC_OEA64_BRIDGE)
135	mtdbatu	2,%r0
136	mtdbatu	3,%r0
137	mtibatu	2,%r0
138	mtibatu	3,%r0
139#endif /* PPC_OEA */
140
141	lis	%r4,ofwsrsave@ha		/* save current SRs */
142	addi	%r4,%r4,ofwsrsave@l
143	li	%r5,0
1441:	mfsrin	%r0,%r5
145	stw	%r0,0(%r4)
146	addi	%r4,%r4,4
147	addis	%r5,%r5,0x10000000@h
148	cmpwi	%r5,0
149	bne	1b
150
151	lis	%r4,_C_LABEL(ofw_pmap)@ha	/* load OFW SR */
152	addi	%r4,%r4,_C_LABEL(ofw_pmap)@l
153	lwz	%r0,PM_KERNELSR(%r4)
154	cmpwi	%r0,0			/* pm_sr[KERNEL_SR] == 0? */
155	beq	2f			/* then skip (not initialized yet) */
156	li	%r5,0
1571:	lwz	%r0,0(%r4)
158	mtsrin	%r0,%r5
159	addi	%r4,%r4,4
160	addis	%r5,%r5,0x10000000@h
161	cmpwi	%r5,0
162	bne	1b
1632:
164	lis	%r4,ofwmsr+16@ha	/* Open Firmware msr + sprg[0-3] */
165	lwzu	%r5,ofwmsr+16@l(%r4)
166	mtsprg3	%r5
167	lwz	%r5,-4(%r4)
168	mtsprg2	%r5
169	lwz	%r5,-8(%r4)
170	mtsprg1	%r5
171	lwz	%r5,-12(%r4)
172	mtsprg0	%r5
173	lwz	%r5,-16(%r4)
174	mtmsr	%r5
175	isync
176
177	blrl				/* call Open Firmware */
178
179	lis	%r4,ofwsrsave@ha	/* restore saved SRs */
180	addi	%r4,%r4,ofwsrsave@l
181	li	%r5,0
1821:	lwz	%r0,0(%r4)
183	mtsrin	%r0,%r5
184	addi	%r4,%r4,4
185	addis	%r5,%r5,0x10000000@h
186	cmpwi	%r5,0
187	bne	1b
188
189	lwz	%r4,8(%r1)		/* restore msr */
190	mtmsr	%r4
191	isync
1924:
193	lwz	%r5,16(%r1)		/* restore saved sprgs (curcpu) */
194	mtsprg0	%r5
195	lwz	%r5,20(%r1)
196	mtsprg1	%r5
197	lwz	%r5,24(%r1)
198	mtsprg2	%r5
199	lwz	%r5,28(%r1)
200	mtsprg3	%r5
201
202	lwz	%r1,0(%r1)		/* and return */
203	lwz	%r0,4(%r1)
204	mtlr	%r0
205	blr
206
207/*
208 * Switch to/from OpenFirmware real mode stack
209 *
210 * Note: has to be called as the very first thing in OpenFirmware interface
211 * routines.
212 * E.g.:
213 * int
214 * OF_xxx(arg1, arg2)
215 * type arg1, arg2;
216 * {
217 *	static struct {
218 *		char *name;
219 *		int nargs;
220 *		int nreturns;
221 *		char *method;
222 *		int arg1;
223 *		int arg2;
224 *		int ret;
225 *	} args = {
226 *		"xxx",
227 *		2,
228 *		1,
229 *	};
230 *
231 *	ofw_stack();
232 *	args.arg1 = arg1;
233 *	args.arg2 = arg2;
234 *	if (openfirmware(&args) < 0)
235 *		return -1;
236 *	return args.ret;
237 * }
238 */
239
240ENTRY(ofw_stack)
241	mfmsr	%r8			/* turn off interrupts */
242	andi.	%r0,%r8,~(PSL_EE|PSL_RI)@l
243	mtmsr	%r0
244	stw	%r8,4(%r1)		/* abuse return address slot */
245
246	lwz	%r5,0(%r1)		/* get length of stack frame */
247	subf	%r5,%r1,%r5
248
249	lis	%r7,firmstk+NBPG-8@ha
250	addi	%r7,%r7,firmstk+NBPG-8@l
251	lis	%r6,ofw_back@ha
252	addi	%r6,%r6,ofw_back@l
253	subf	%r4,%r5,%r7		/* make room for stack frame on
254					   new stack */
255	stw	%r6,-4(%r7)		/* setup return pointer */
256	stwu	%r1,-8(%r7)
257
258	stw	%r7,-8(%r4)
259
260	addi	%r3,%r1,8
261	addi	%r1,%r4,-8
262	subi	%r5,%r5,8
263
264	b	_C_LABEL(ofbcopy)	/* and copy it */
265
266ofw_back:
267	lwz	%r1,0(%r1)		/* get callers original stack pointer */
268
269	lwz	%r0,4(%r1)		/* get saved msr from abused slot */
270	mtmsr	%r0
271
272	lwz	%r1,0(%r1)		/* return */
273	lwz	%r0,4(%r1)
274	mtlr	%r0
275	blr
276