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