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