ofw_subr.S revision 1.7 1 /* $NetBSD: ofw_subr.S,v 1.7 2008/02/14 19:41:54 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
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 %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
72 1:
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
101 ENTRY(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
122 1:
123 #endif
124 mfmsr %r4 /* save msr */
125 stw %r4,8(%r1)
126
127 li %r0,0 /* clear battable translations */
128 #if defined (PPC_OEA) || defined (PPC_OEA64_BRIDGE)
129 mtdbatu 2,%r0
130 mtdbatu 3,%r0
131 mtibatu 2,%r0
132 mtibatu 3,%r0
133 #endif /* PPC_OEA */
134
135 lis %r4,ofwsrsave@ha /* save current SRs */
136 addi %r4,%r4,ofwsrsave@l
137 li %r5,0
138 1: mfsrin %r0,%r5
139 stw %r0,0(%r4)
140 addi %r4,%r4,4
141 addis %r5,%r5,0x10000000@h
142 cmpwi %r5,0
143 bne 1b
144
145 lis %r4,_C_LABEL(ofw_pmap)@ha /* load OFW SR */
146 addi %r4,%r4,_C_LABEL(ofw_pmap)@l
147 lwz %r0,PM_KERNELSR(%r4)
148 cmpwi %r0,0 /* pm_sr[KERNEL_SR] == 0? */
149 beq 2f /* then skip (not initialized yet) */
150 li %r5,0
151 1: lwz %r0,0(%r4)
152 mtsrin %r0,%r5
153 addi %r4,%r4,4
154 addis %r5,%r5,0x10000000@h
155 cmpwi %r5,0
156 bne 1b
157 2:
158 lis %r4,ofmsr@ha /* Open Firmware msr + sprg[0-3] */
159 lwzu %r5,ofmsr+16@l(%r4)
160 mtsprg 3,%r5
161 lwzu %r5,-4(%r4)
162 mtsprg 2,%r5
163 lwzu %r5,-4(%r4)
164 mtsprg 1,%r5
165 lwzu %r5,-4(%r4)
166 mtsprg 0,%r5
167 lwz %r5,-4(%r4)
168 mtmsr %r5
169 isync
170
171 blrl /* call Open Firmware */
172
173 lis %r4,ofwsrsave@ha /* restore saved SRs */
174 addi %r4,%r4,ofwsrsave@l
175 li %r5,0
176 1: lwz %r0,0(%r4)
177 mtsrin %r0,%r5
178 addi %r4,%r4,4
179 addis %r5,%r5,0x10000000@h
180 cmpwi %r5,0
181 bne 1b
182
183 lwz %r4,8(%r1) /* restore msr */
184 mtmsr %r4
185 isync
186 4:
187 lis %r4,ofwsprg0save@ha /* restore saved sprg0 (curcpu) */
188 addi %r4,%r4,ofwsprg0save@l
189 lwz %r5,0(%r4)
190 mtsprg 0,%r5
191
192 lwz %r1,0(%r1) /* and return */
193 lwz %r0,4(%r1)
194 mtlr %r0
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 %r8 /* turn off interrupts */
232 andi. %r0,%r8,~(PSL_EE|PSL_RI)@l
233 mtmsr %r0
234 stw %r8,4(%r1) /* abuse return address slot */
235
236 lwz %r5,0(%r1) /* get length of stack frame */
237 subf %r5,%r1,%r5
238
239 lis %r7,firmstk+NBPG-8@ha
240 addi %r7,%r7,firmstk+NBPG-8@l
241 lis %r6,ofw_back@ha
242 addi %r6,%r6,ofw_back@l
243 subf %r4,%r5,%r7 /* make room for stack frame on
244 new stack */
245 stw %r6,-4(%r7) /* setup return pointer */
246 stwu %r1,-8(%r7)
247
248 stw %r7,-8(%r4)
249
250 addi %r3,%r1,8
251 addi %r1,%r4,-8
252 subi %r5,%r5,8
253
254 b _C_LABEL(ofbcopy) /* and copy it */
255
256 ofw_back:
257 lwz %r1,0(%r1) /* get callers original stack pointer */
258
259 lwz %r0,4(%r1) /* get saved msr from abused slot */
260 mtmsr %r0
261
262 lwz %r1,0(%r1) /* return */
263 lwz %r0,4(%r1)
264 mtlr %r0
265 blr
266