1/* $NetBSD: ofw_subr.S,v 1.8 2008/04/08 02:33:03 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 41GLOBAL(ofmsr) 42 .long 0,0,0,0,0 /* msr & sprg[0-3] used in OF */ 43 44GLOBAL(ofwsprg0save) 45 .long 0 46 47GLOBAL(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 */ 59ENTRY_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 721: 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 101ENTRY(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 1221: 123#endif 124 mfmsr %r4 /* save msr */ 125 stw %r4,8(%r1) 126 127 li %r0,0 /* clear battable translations */ 128 mtmsr %r0 129#if defined (PPC_OEA) || defined (PPC_OEA64_BRIDGE) 130 mtdbatu 2,%r0 131 mtdbatu 3,%r0 132 mtibatu 2,%r0 133 mtibatu 3,%r0 134#endif /* PPC_OEA */ 135 136 lis %r4,ofwsrsave@ha /* save current SRs */ 137 addi %r4,%r4,ofwsrsave@l 138 li %r5,0 1391: mfsrin %r0,%r5 140 stw %r0,0(%r4) 141 addi %r4,%r4,4 142 addis %r5,%r5,0x10000000@h 143 cmpwi %r5,0 144 bne 1b 145 146 lis %r4,_C_LABEL(ofw_pmap)@ha /* load OFW SR */ 147 addi %r4,%r4,_C_LABEL(ofw_pmap)@l 148 lwz %r0,PM_KERNELSR(%r4) 149 cmpwi %r0,0 /* pm_sr[KERNEL_SR] == 0? */ 150 beq 2f /* then skip (not initialized yet) */ 151 li %r5,0 1521: lwz %r0,0(%r4) 153 mtsrin %r0,%r5 154 addi %r4,%r4,4 155 addis %r5,%r5,0x10000000@h 156 cmpwi %r5,0 157 bne 1b 1582: 159 lis %r4,ofmsr@ha /* Open Firmware msr + sprg[0-3] */ 160 lwzu %r5,ofmsr+16@l(%r4) 161 mtsprg 3,%r5 162 lwzu %r5,-4(%r4) 163 mtsprg 2,%r5 164 lwzu %r5,-4(%r4) 165 mtsprg 1,%r5 166 lwzu %r5,-4(%r4) 167 mtsprg 0,%r5 168 lwz %r5,-4(%r4) 169 mtmsr %r5 170 isync 171 172 blrl /* call Open Firmware */ 173 174 lis %r4,ofwsrsave@ha /* restore saved SRs */ 175 addi %r4,%r4,ofwsrsave@l 176 li %r5,0 1771: lwz %r0,0(%r4) 178 mtsrin %r0,%r5 179 addi %r4,%r4,4 180 addis %r5,%r5,0x10000000@h 181 cmpwi %r5,0 182 bne 1b 183 184 lwz %r4,8(%r1) /* restore msr */ 185 mtmsr %r4 186 isync 1874: 188 lis %r4,ofwsprg0save@ha /* restore saved sprg0 (curcpu) */ 189 addi %r4,%r4,ofwsprg0save@l 190 lwz %r5,0(%r4) 191 mtsprg 0,%r5 192 193 lwz %r1,0(%r1) /* and return */ 194 lwz %r0,4(%r1) 195 mtlr %r0 196 blr 197 198/* 199 * Switch to/from OpenFirmware real mode stack 200 * 201 * Note: has to be called as the very first thing in OpenFirmware interface 202 * routines. 203 * E.g.: 204 * int 205 * OF_xxx(arg1, arg2) 206 * type arg1, arg2; 207 * { 208 * static struct { 209 * char *name; 210 * int nargs; 211 * int nreturns; 212 * char *method; 213 * int arg1; 214 * int arg2; 215 * int ret; 216 * } args = { 217 * "xxx", 218 * 2, 219 * 1, 220 * }; 221 * 222 * ofw_stack(); 223 * args.arg1 = arg1; 224 * args.arg2 = arg2; 225 * if (openfirmware(&args) < 0) 226 * return -1; 227 * return args.ret; 228 * } 229 */ 230 231ENTRY(ofw_stack) 232 mfmsr %r8 /* turn off interrupts */ 233 andi. %r0,%r8,~(PSL_EE|PSL_RI)@l 234 mtmsr %r0 235 stw %r8,4(%r1) /* abuse return address slot */ 236 237 lwz %r5,0(%r1) /* get length of stack frame */ 238 subf %r5,%r1,%r5 239 240 lis %r7,firmstk+NBPG-8@ha 241 addi %r7,%r7,firmstk+NBPG-8@l 242 lis %r6,ofw_back@ha 243 addi %r6,%r6,ofw_back@l 244 subf %r4,%r5,%r7 /* make room for stack frame on 245 new stack */ 246 stw %r6,-4(%r7) /* setup return pointer */ 247 stwu %r1,-8(%r7) 248 249 stw %r7,-8(%r4) 250 251 addi %r3,%r1,8 252 addi %r1,%r4,-8 253 subi %r5,%r5,8 254 255 b _C_LABEL(ofbcopy) /* and copy it */ 256 257ofw_back: 258 lwz %r1,0(%r1) /* get callers original stack pointer */ 259 260 lwz %r0,4(%r1) /* get saved msr from abused slot */ 261 mtmsr %r0 262 263 lwz %r1,0(%r1) /* return */ 264 lwz %r0,4(%r1) 265 mtlr %r0 266 blr 267