ofw_subr.S revision 1.2.32.1 1 /* $NetBSD: ofw_subr.S,v 1.2.32.1 2006/09/09 02:42:28 rpaulo 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 .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 */
56 ENTRY_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
65 1:
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
94 ENTRY(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 #if defined (PPC_OEA) && !defined (PPC_OEA64) && !defined (PPC_OEA64_BRIDGE)
108 mtdbatu 2,0
109 mtdbatu 3,0
110 mtibatu 2,0
111 mtibatu 3,0
112 #endif /* PPC_OEA */
113
114 lis 4,ofwsrsave@ha /* save current SRs */
115 addi 4,4,ofwsrsave@l
116 li 5,0
117 1: mfsrin 0,5
118 stw 0,0(4)
119 addi 4,4,4
120 addis 5,5,0x10000000@h
121 cmpwi 5,0
122 bne 1b
123
124 mfsprg 5,0 /* save current sprg0 (curcpu) */
125 lis 4,ofwsprg0save@ha
126 addi 4,4,ofwsprg0save@l
127 stw 5,0(4)
128
129 lis 4,_C_LABEL(ofw_pmap)@ha /* load OFW SR */
130 addi 4,4,_C_LABEL(ofw_pmap)@l
131 lwz 0,PM_KERNELSR(4)
132 cmpwi 0,0 /* pm_sr[KERNEL_SR] == 0? */
133 beq 2f /* then skip (not initialized yet) */
134 li 5,0
135 1: lwz 0,0(4)
136 mtsrin 0,5
137 addi 4,4,4
138 addis 5,5,0x10000000@h
139 cmpwi 5,0
140 bne 1b
141 2:
142 lis 4,ofmsr@ha /* Open Firmware msr + sprg[0-3] */
143 lwzu 5,ofmsr+16@l(4)
144 mtsprg 3,5
145 lwzu 5,-4(4)
146 mtsprg 2,5
147 lwzu 5,-4(4)
148 mtsprg 1,5
149 lwzu 5,-4(4)
150 mtsprg 0,5
151 lwz 5,-4(4)
152 mtmsr 5
153 isync
154
155 blrl /* call Open Firmware */
156
157 lis 4,ofwsprg0save@ha /* restore saved sprg0 (curcpu) */
158 addi 4,4,ofwsprg0save@l
159 lwz 5,0(4)
160 mtsprg 0,5
161
162 lis 4,ofwsrsave@ha /* restore saved SRs */
163 addi 4,4,ofwsrsave@l
164 li 5,0
165 1: lwz 0,0(4)
166 mtsrin 0,5
167 addi 4,4,4
168 addis 5,5,0x10000000@h
169 cmpwi 5,0
170 bne 1b
171
172 lwz 4,8(1) /* restore msr */
173 mtmsr 4
174 isync
175
176 lwz 1,0(1) /* and return */
177 lwz 0,4(1)
178 mtlr 0
179 blr
180
181 /*
182 * Switch to/from OpenFirmware real mode stack
183 *
184 * Note: has to be called as the very first thing in OpenFirmware interface
185 * routines.
186 * E.g.:
187 * int
188 * OF_xxx(arg1, arg2)
189 * type arg1, arg2;
190 * {
191 * static struct {
192 * char *name;
193 * int nargs;
194 * int nreturns;
195 * char *method;
196 * int arg1;
197 * int arg2;
198 * int ret;
199 * } args = {
200 * "xxx",
201 * 2,
202 * 1,
203 * };
204 *
205 * ofw_stack();
206 * args.arg1 = arg1;
207 * args.arg2 = arg2;
208 * if (openfirmware(&args) < 0)
209 * return -1;
210 * return args.ret;
211 * }
212 */
213
214 ENTRY(ofw_stack)
215 mfmsr 8 /* turn off interrupts */
216 andi. 0,8,~(PSL_EE|PSL_RI)@l
217 mtmsr 0
218 stw 8,4(1) /* abuse return address slot */
219
220 lwz 5,0(1) /* get length of stack frame */
221 subf 5,1,5
222
223 lis 7,firmstk+NBPG-8@ha
224 addi 7,7,firmstk+NBPG-8@l
225 lis 6,ofw_back@ha
226 addi 6,6,ofw_back@l
227 subf 4,5,7 /* make room for stack frame on
228 new stack */
229 stw 6,-4(7) /* setup return pointer */
230 stwu 1,-8(7)
231
232 stw 7,-8(4)
233
234 addi 3,1,8
235 addi 1,4,-8
236 subi 5,5,8
237
238 b _C_LABEL(ofbcopy) /* and copy it */
239
240 ofw_back:
241 lwz 1,0(1) /* get callers original stack pointer */
242
243 lwz 0,4(1) /* get saved msr from abused slot */
244 mtmsr 0
245
246 lwz 1,0(1) /* return */
247 lwz 0,4(1)
248 mtlr 0
249 blr
250