Wed Jul 27 22:04:23 2011 UTC ()
move clearing PSL_IP in ofwmsr back where it was - if we do it too early my
PowerBook 3400c hangs on startup.


(macallan)
diff -r1.9 -r1.10 src/sys/arch/powerpc/oea/ofw_subr.S
diff -r1.24 -r1.25 src/sys/arch/powerpc/oea/ofwoea_machdep.c

cvs diff -r1.9 -r1.10 src/sys/arch/powerpc/oea/ofw_subr.S (switch to unified diff)

--- src/sys/arch/powerpc/oea/ofw_subr.S 2011/06/12 16:35:10 1.9
+++ src/sys/arch/powerpc/oea/ofw_subr.S 2011/07/27 22:04:23 1.10
@@ -1,268 +1,275 @@ @@ -1,268 +1,275 @@
1/* $NetBSD: ofw_subr.S,v 1.9 2011/06/12 16:35:10 matt Exp $ */ 1/* $NetBSD: ofw_subr.S,v 1.10 2011/07/27 22:04:23 macallan Exp $ */
2 2
3/* 3/*
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH. 5 * Copyright (C) 1995, 1996 TooLs GmbH.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software 16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement: 17 * must display the following acknowledgement:
18 * This product includes software developed by TooLs GmbH. 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 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. 20 * derived from this software without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 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 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 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, 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, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 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, 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 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 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34 34
35 .local firmstk 35 .local firmstk
36 .globl openfirmware_entry 36 .globl openfirmware_entry
 37 .globl ofwmsr
37 .local ofwsrsave 38 .local ofwsrsave
38 .local OF_buffer 39 .local OF_buffer
39 40
40 .lcomm firmstk,NBPG,16 41 .lcomm firmstk,NBPG,16
41 .lcomm OF_buffer,NBPG,4 42 .lcomm OF_buffer,NBPG,4
42 .comm openfirmware_entry,4,4 /* openfirmware entry point */ 43 .comm openfirmware_entry,4,4 /* openfirmware entry point */
43 .lcomm ofwsrsave,64,4 /* openfirmware SR savearea */ 44 .lcomm ofwsrsave,64,4 /* openfirmware SR savearea */
44 .lcomm ofwmsr,20,4 /* msr & sprg[0-3] used in OF */ 45 .comm ofwmsr,20,4 /* msr & sprg[0-3] used in OF */
45 .comm ofwreal_incharge,4,4 46 .comm ofwreal_incharge,4,4
46 47
47/* 48/*
48 * Called by start to save the initial OFW state so we can restore it 49 * Called by start to save the initial OFW state so we can restore it
49 * when call back to OFW. 50 * when call back to OFW.
50 */ 51 */
51ENTRY_NOPROFILE(ofwinit) 52ENTRY_NOPROFILE(ofwinit)
52#ifdef FIRMWORKSBUGS 53#ifdef FIRMWORKSBUGS
53 mfmsr %r0 54 mfmsr %r0
54 andi. %r0,%r0,PSL_IR|PSL_DR 55 andi. %r0,%r0,PSL_IR|PSL_DR
55 beq 1f 56 beq 1f
56 57
57 li %r8,1 58 li %r8,1
58 lis %r9,ofwreal_incharge@ha 59 lis %r9,ofwreal_incharge@ha
59 stw %r8,ofwreal_incharge@l(%r9) 60 stw %r8,ofwreal_incharge@l(%r9)
60 61
61 mflr %r30 62 mflr %r30
62 bl _C_LABEL(ofwr_init) 63 bl _C_LABEL(ofwr_init)
63 mtlr %r30 64 mtlr %r30
641: 651:
65#endif 66#endif
66 lis %r8,openfirmware_entry@ha 67 lis %r8,openfirmware_entry@ha
67 stw %r5,openfirmware_entry@l(%r8) /* save client interface handler*/ 68 stw %r5,openfirmware_entry@l(%r8) /* save client interface handler*/
68 69
69 mfmsr %r0 70 mfmsr %r0
70 li %r8,PSL_IP 71/*
71 andc %r0,%r0,%r8 /* make sure PSL_IP is off */ 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 */
72 lis %r9,ofwmsr@ha 79 lis %r9,ofwmsr@ha
73 stwu %r0,ofwmsr@l(%r9) /* save initial MSR value */ 80 stwu %r0,ofwmsr@l(%r9) /* save initial MSR value */
74 81
75 mfsprg0 %r0 /* save SPRGs */ 82 mfsprg0 %r0 /* save SPRGs */
76 stw %r0,4(%r9) 83 stw %r0,4(%r9)
77 mfsprg1 %r0 84 mfsprg1 %r0
78 stw %r0,8(%r9) 85 stw %r0,8(%r9)
79 mfsprg2 %r0 86 mfsprg2 %r0
80 stw %r0,12(%r9) 87 stw %r0,12(%r9)
81 mfsprg3 %r0 88 mfsprg3 %r0
82 stw %r0,16(%r9) 89 stw %r0,16(%r9)
83 90
84 lis %r8,OF_buffer@ha 91 lis %r8,OF_buffer@ha
85 addi %r8,%r8,OF_buffer@l 92 addi %r8,%r8,OF_buffer@l
86 lis %r9,_C_LABEL(OF_buf)@ha 93 lis %r9,_C_LABEL(OF_buf)@ha
87 stw %r8,_C_LABEL(OF_buf)@l(%r9) 94 stw %r8,_C_LABEL(OF_buf)@l(%r9)
88 95
89 blr 96 blr
90 97
91/* 98/*
92 * OpenFirmware entry point 99 * OpenFirmware entry point
93 */ 100 */
94 .text 101 .text
95ENTRY(openfirmware) 102ENTRY(openfirmware)
96 mflr %r0 /* save return address */ 103 mflr %r0 /* save return address */
97 stw %r0,4(%r1) 104 stw %r0,4(%r1)
98 stwu %r1,-32(%r1) /* setup stack frame */ 105 stwu %r1,-32(%r1) /* setup stack frame */
99 106
100 lis %r4,openfirmware_entry@ha /* get firmware entry point */ 107 lis %r4,openfirmware_entry@ha /* get firmware entry point */
101 lwz %r4,openfirmware_entry@l(%r4) 108 lwz %r4,openfirmware_entry@l(%r4)
102 mtlr %r4 109 mtlr %r4
103 110
104 mfsprg0 %r5 /* save current sprg0 (curcpu) */ 111 mfsprg0 %r5 /* save current sprg0 (curcpu) */
105 stw %r5,16(%r1) 112 stw %r5,16(%r1)
106 mfsprg1 %r5 /* save current sprg1 */ 113 mfsprg1 %r5 /* save current sprg1 */
107 stw %r5,20(%r1) 114 stw %r5,20(%r1)
108 mfsprg2 %r5 /* save current sprg1 */ 115 mfsprg2 %r5 /* save current sprg1 */
109 stw %r5,24(%r1) 116 stw %r5,24(%r1)
110 mfsprg3 %r5 /* save current sprg3 */ 117 mfsprg3 %r5 /* save current sprg3 */
111 stw %r5,28(%r1) 118 stw %r5,28(%r1)
112 119
113#ifdef FIRMWORKSBUGS 120#ifdef FIRMWORKSBUGS
114 lis %r4,ofwreal_incharge@ha 121 lis %r4,ofwreal_incharge@ha
115 lwz %r4,ofwreal_incharge@l(%r4) 122 lwz %r4,ofwreal_incharge@l(%r4)
116 cmpwi %r4,1 123 cmpwi %r4,1
117 bne 1f 124 bne 1f
118 blrl 125 blrl
119 b 4f 126 b 4f
1201: 1271:
121#endif 128#endif
122 mfmsr %r4 /* save msr */ 129 mfmsr %r4 /* save msr */
123 stw %r4,8(%r1) 130 stw %r4,8(%r1)
124 131
125 li %r0,0 /* clear battable translations */ 132 li %r0,0 /* clear battable translations */
126 mtmsr %r0 133 mtmsr %r0
127#if defined (PPC_OEA) || defined (PPC_OEA64_BRIDGE) 134#if defined (PPC_OEA) || defined (PPC_OEA64_BRIDGE)
128 mtdbatu 2,%r0 135 mtdbatu 2,%r0
129 mtdbatu 3,%r0 136 mtdbatu 3,%r0
130 mtibatu 2,%r0 137 mtibatu 2,%r0
131 mtibatu 3,%r0 138 mtibatu 3,%r0
132#endif /* PPC_OEA */ 139#endif /* PPC_OEA */
133 140
134 lis %r4,ofwsrsave@ha /* save current SRs */ 141 lis %r4,ofwsrsave@ha /* save current SRs */
135 addi %r4,%r4,ofwsrsave@l 142 addi %r4,%r4,ofwsrsave@l
136 li %r5,0 143 li %r5,0
1371: mfsrin %r0,%r5 1441: mfsrin %r0,%r5
138 stw %r0,0(%r4) 145 stw %r0,0(%r4)
139 addi %r4,%r4,4 146 addi %r4,%r4,4
140 addis %r5,%r5,0x10000000@h 147 addis %r5,%r5,0x10000000@h
141 cmpwi %r5,0 148 cmpwi %r5,0
142 bne 1b 149 bne 1b
143 150
144 lis %r4,_C_LABEL(ofw_pmap)@ha /* load OFW SR */ 151 lis %r4,_C_LABEL(ofw_pmap)@ha /* load OFW SR */
145 addi %r4,%r4,_C_LABEL(ofw_pmap)@l 152 addi %r4,%r4,_C_LABEL(ofw_pmap)@l
146 lwz %r0,PM_KERNELSR(%r4) 153 lwz %r0,PM_KERNELSR(%r4)
147 cmpwi %r0,0 /* pm_sr[KERNEL_SR] == 0? */ 154 cmpwi %r0,0 /* pm_sr[KERNEL_SR] == 0? */
148 beq 2f /* then skip (not initialized yet) */ 155 beq 2f /* then skip (not initialized yet) */
149 li %r5,0 156 li %r5,0
1501: lwz %r0,0(%r4) 1571: lwz %r0,0(%r4)
151 mtsrin %r0,%r5 158 mtsrin %r0,%r5
152 addi %r4,%r4,4 159 addi %r4,%r4,4
153 addis %r5,%r5,0x10000000@h 160 addis %r5,%r5,0x10000000@h
154 cmpwi %r5,0 161 cmpwi %r5,0
155 bne 1b 162 bne 1b
1562: 1632:
157 lis %r4,ofwmsr+16@ha /* Open Firmware msr + sprg[0-3] */ 164 lis %r4,ofwmsr+16@ha /* Open Firmware msr + sprg[0-3] */
158 lwzu %r5,ofwmsr+16@l(%r4) 165 lwzu %r5,ofwmsr+16@l(%r4)
159 mtsprg3 %r5 166 mtsprg3 %r5
160 lwz %r5,-4(%r4) 167 lwz %r5,-4(%r4)
161 mtsprg2 %r5 168 mtsprg2 %r5
162 lwz %r5,-8(%r4) 169 lwz %r5,-8(%r4)
163 mtsprg1 %r5 170 mtsprg1 %r5
164 lwz %r5,-12(%r4) 171 lwz %r5,-12(%r4)
165 mtsprg0 %r5 172 mtsprg0 %r5
166 lwz %r5,-16(%r4) 173 lwz %r5,-16(%r4)
167 mtmsr %r5 174 mtmsr %r5
168 isync 175 isync
169 176
170 blrl /* call Open Firmware */ 177 blrl /* call Open Firmware */
171 178
172 lis %r4,ofwsrsave@ha /* restore saved SRs */ 179 lis %r4,ofwsrsave@ha /* restore saved SRs */
173 addi %r4,%r4,ofwsrsave@l 180 addi %r4,%r4,ofwsrsave@l
174 li %r5,0 181 li %r5,0
1751: lwz %r0,0(%r4) 1821: lwz %r0,0(%r4)
176 mtsrin %r0,%r5 183 mtsrin %r0,%r5
177 addi %r4,%r4,4 184 addi %r4,%r4,4
178 addis %r5,%r5,0x10000000@h 185 addis %r5,%r5,0x10000000@h
179 cmpwi %r5,0 186 cmpwi %r5,0
180 bne 1b 187 bne 1b
181 188
182 lwz %r4,8(%r1) /* restore msr */ 189 lwz %r4,8(%r1) /* restore msr */
183 mtmsr %r4 190 mtmsr %r4
184 isync 191 isync
1854:  1924:
186 lwz %r5,16(%r1) /* restore saved sprgs (curcpu) */ 193 lwz %r5,16(%r1) /* restore saved sprgs (curcpu) */
187 mtsprg0 %r5 194 mtsprg0 %r5
188 lwz %r5,20(%r1) 195 lwz %r5,20(%r1)
189 mtsprg1 %r5 196 mtsprg1 %r5
190 lwz %r5,24(%r1) 197 lwz %r5,24(%r1)
191 mtsprg2 %r5 198 mtsprg2 %r5
192 lwz %r5,28(%r1) 199 lwz %r5,28(%r1)
193 mtsprg3 %r5 200 mtsprg3 %r5
194 201
195 lwz %r1,0(%r1) /* and return */ 202 lwz %r1,0(%r1) /* and return */
196 lwz %r0,4(%r1) 203 lwz %r0,4(%r1)
197 mtlr %r0 204 mtlr %r0
198 blr 205 blr
199 206
200/* 207/*
201 * Switch to/from OpenFirmware real mode stack 208 * Switch to/from OpenFirmware real mode stack
202 * 209 *
203 * Note: has to be called as the very first thing in OpenFirmware interface 210 * Note: has to be called as the very first thing in OpenFirmware interface
204 * routines. 211 * routines.
205 * E.g.: 212 * E.g.:
206 * int 213 * int
207 * OF_xxx(arg1, arg2) 214 * OF_xxx(arg1, arg2)
208 * type arg1, arg2; 215 * type arg1, arg2;
209 * { 216 * {
210 * static struct { 217 * static struct {
211 * char *name; 218 * char *name;
212 * int nargs; 219 * int nargs;
213 * int nreturns; 220 * int nreturns;
214 * char *method; 221 * char *method;
215 * int arg1; 222 * int arg1;
216 * int arg2; 223 * int arg2;
217 * int ret; 224 * int ret;
218 * } args = { 225 * } args = {
219 * "xxx", 226 * "xxx",
220 * 2, 227 * 2,
221 * 1, 228 * 1,
222 * }; 229 * };
223 * 230 *
224 * ofw_stack(); 231 * ofw_stack();
225 * args.arg1 = arg1; 232 * args.arg1 = arg1;
226 * args.arg2 = arg2; 233 * args.arg2 = arg2;
227 * if (openfirmware(&args) < 0) 234 * if (openfirmware(&args) < 0)
228 * return -1; 235 * return -1;
229 * return args.ret; 236 * return args.ret;
230 * } 237 * }
231 */ 238 */
232 239
233ENTRY(ofw_stack) 240ENTRY(ofw_stack)
234 mfmsr %r8 /* turn off interrupts */ 241 mfmsr %r8 /* turn off interrupts */
235 andi. %r0,%r8,~(PSL_EE|PSL_RI)@l 242 andi. %r0,%r8,~(PSL_EE|PSL_RI)@l
236 mtmsr %r0 243 mtmsr %r0
237 stw %r8,4(%r1) /* abuse return address slot */ 244 stw %r8,4(%r1) /* abuse return address slot */
238 245
239 lwz %r5,0(%r1) /* get length of stack frame */ 246 lwz %r5,0(%r1) /* get length of stack frame */
240 subf %r5,%r1,%r5 247 subf %r5,%r1,%r5
241 248
242 lis %r7,firmstk+NBPG-8@ha 249 lis %r7,firmstk+NBPG-8@ha
243 addi %r7,%r7,firmstk+NBPG-8@l 250 addi %r7,%r7,firmstk+NBPG-8@l
244 lis %r6,ofw_back@ha 251 lis %r6,ofw_back@ha
245 addi %r6,%r6,ofw_back@l 252 addi %r6,%r6,ofw_back@l
246 subf %r4,%r5,%r7 /* make room for stack frame on 253 subf %r4,%r5,%r7 /* make room for stack frame on
247 new stack */ 254 new stack */
248 stw %r6,-4(%r7) /* setup return pointer */ 255 stw %r6,-4(%r7) /* setup return pointer */
249 stwu %r1,-8(%r7) 256 stwu %r1,-8(%r7)
250 257
251 stw %r7,-8(%r4) 258 stw %r7,-8(%r4)
252 259
253 addi %r3,%r1,8 260 addi %r3,%r1,8
254 addi %r1,%r4,-8 261 addi %r1,%r4,-8
255 subi %r5,%r5,8 262 subi %r5,%r5,8
256 263
257 b _C_LABEL(ofbcopy) /* and copy it */ 264 b _C_LABEL(ofbcopy) /* and copy it */
258 265
259ofw_back: 266ofw_back:
260 lwz %r1,0(%r1) /* get callers original stack pointer */ 267 lwz %r1,0(%r1) /* get callers original stack pointer */
261 268
262 lwz %r0,4(%r1) /* get saved msr from abused slot */ 269 lwz %r0,4(%r1) /* get saved msr from abused slot */
263 mtmsr %r0 270 mtmsr %r0
264 271
265 lwz %r1,0(%r1) /* return */ 272 lwz %r1,0(%r1) /* return */
266 lwz %r0,4(%r1) 273 lwz %r0,4(%r1)
267 mtlr %r0 274 mtlr %r0
268 blr 275 blr

cvs diff -r1.24 -r1.25 src/sys/arch/powerpc/oea/ofwoea_machdep.c (switch to unified diff)

--- src/sys/arch/powerpc/oea/ofwoea_machdep.c 2011/07/17 23:23:54 1.24
+++ src/sys/arch/powerpc/oea/ofwoea_machdep.c 2011/07/27 22:04:23 1.25
@@ -1,724 +1,732 @@ @@ -1,724 +1,732 @@
1/* $NetBSD: ofwoea_machdep.c,v 1.24 2011/07/17 23:23:54 dyoung Exp $ */ 1/* $NetBSD: ofwoea_machdep.c,v 1.25 2011/07/27 22:04:23 macallan Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2007 The NetBSD Foundation, Inc. 4 * Copyright (c) 2007 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tim Rightnour 8 * by Tim Rightnour
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: ofwoea_machdep.c,v 1.24 2011/07/17 23:23:54 dyoung Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: ofwoea_machdep.c,v 1.25 2011/07/27 22:04:23 macallan Exp $");
34 34
35#include "opt_ppcarch.h" 35#include "opt_ppcarch.h"
36#include "opt_compat_netbsd.h" 36#include "opt_compat_netbsd.h"
37#include "opt_ddb.h" 37#include "opt_ddb.h"
38#include "opt_kgdb.h" 38#include "opt_kgdb.h"
39#include "opt_ipkdb.h" 39#include "opt_ipkdb.h"
40#include "opt_modular.h" 40#include "opt_modular.h"
41 41
42#include <sys/param.h> 42#include <sys/param.h>
43#include <sys/buf.h> 43#include <sys/buf.h>
44#include <sys/boot_flag.h> 44#include <sys/boot_flag.h>
45#include <sys/extent.h> 45#include <sys/extent.h>
46#include <sys/kernel.h> 46#include <sys/kernel.h>
47#include <sys/ksyms.h> 47#include <sys/ksyms.h>
48#include <uvm/uvm_extern.h> 48#include <uvm/uvm_extern.h>
49 49
50#include <dev/ofw/openfirm.h> 50#include <dev/ofw/openfirm.h>
51#include <machine/pmap.h> 51#include <machine/pmap.h>
52#include <machine/powerpc.h> 52#include <machine/powerpc.h>
53#include <machine/trap.h> 53#include <machine/trap.h>
54#include <machine/vmparam.h> 54#include <machine/vmparam.h>
55#include <machine/autoconf.h> 55#include <machine/autoconf.h>
56#include <sys/bus.h> 56#include <sys/bus.h>
57#include <powerpc/oea/bat.h> 57#include <powerpc/oea/bat.h>
58#include <powerpc/oea/cpufeat.h> 58#include <powerpc/oea/cpufeat.h>
59#include <powerpc/ofw_cons.h> 59#include <powerpc/ofw_cons.h>
60#include <powerpc/spr.h> 60#include <powerpc/spr.h>
61#include <powerpc/pic/picvar.h> 61#include <powerpc/pic/picvar.h>
62 62
63#include "opt_oea.h" 63#include "opt_oea.h"
64 64
65#include "ksyms.h" 65#include "ksyms.h"
66 66
67#ifdef DDB 67#ifdef DDB
68#include <machine/db_machdep.h> 68#include <machine/db_machdep.h>
69#include <ddb/db_extern.h> 69#include <ddb/db_extern.h>
70#endif 70#endif
71 71
72#ifdef KGDB 72#ifdef KGDB
73#include <sys/kgdb.h> 73#include <sys/kgdb.h>
74#endif 74#endif
75 75
76#ifdef IPKDB 76#ifdef IPKDB
77#include <ipkdb/ipkdb.h> 77#include <ipkdb/ipkdb.h>
78#endif 78#endif
79 79
80#include "opt_ofwoea.h" 80#include "opt_ofwoea.h"
81 81
82#ifdef ofppc 82#ifdef ofppc
83extern struct model_data modeldata; 83extern struct model_data modeldata;
84#endif 84#endif
85 85
86#ifdef OFWOEA_DEBUG 86#ifdef OFWOEA_DEBUG
87#define DPRINTF printf 87#define DPRINTF printf
88#else 88#else
89#define DPRINTF while (0) printf 89#define DPRINTF while (0) printf
90#endif 90#endif
91 91
92typedef struct _rangemap { 92typedef struct _rangemap {
93 u_int32_t addr; 93 u_int32_t addr;
94 u_int32_t size; 94 u_int32_t size;
95 int type; 95 int type;
96} rangemap_t; 96} rangemap_t;
97 97
98struct ofw_translations { 98struct ofw_translations {
99 vaddr_t va; 99 vaddr_t va;
100 int len; 100 int len;
101#if defined (PMAC_G5) 101#if defined (PMAC_G5)
102 register64_t pa; 102 register64_t pa;
103#else 103#else
104 register_t pa; 104 register_t pa;
105#endif 105#endif
106 int mode; 106 int mode;
107}__attribute__((packed)); 107}__attribute__((packed));
108 108
109struct pmap ofw_pmap; 109struct pmap ofw_pmap;
110struct ofw_translations ofmap[32]; 110struct ofw_translations ofmap[32];
111char bootpath[256]; 111char bootpath[256];
112char model_name[64]; 112char model_name[64];
113#if NKSYMS || defined(DDB) || defined(MODULAR) 113#if NKSYMS || defined(DDB) || defined(MODULAR)
114void *startsym, *endsym; 114void *startsym, *endsym;
115#endif 115#endif
116#ifdef TIMEBASE_FREQ 116#ifdef TIMEBASE_FREQ
117u_int timebase_freq = TIMEBASE_FREQ; 117u_int timebase_freq = TIMEBASE_FREQ;
118#else 118#else
119u_int timebase_freq = 0; 119u_int timebase_freq = 0;
120#endif 120#endif
121 121
 122extern int ofwmsr;
122extern int chosen; 123extern int chosen;
123extern uint32_t ticks_per_sec; 124extern uint32_t ticks_per_sec;
124extern uint32_t ns_per_tick; 125extern uint32_t ns_per_tick;
125extern uint32_t ticks_per_intr; 126extern uint32_t ticks_per_intr;
126 127
127static int save_ofmap(struct ofw_translations *, int); 128static int save_ofmap(struct ofw_translations *, int);
128static void restore_ofmap(struct ofw_translations *, int); 129static void restore_ofmap(struct ofw_translations *, int);
129static void set_timebase(void); 130static void set_timebase(void);
130 131
131extern void cpu_spinstart(u_int); 132extern void cpu_spinstart(u_int);
132volatile u_int cpu_spinstart_ack, cpu_spinstart_cpunum; 133volatile u_int cpu_spinstart_ack, cpu_spinstart_cpunum;
133 134
134void 135void
135ofwoea_initppc(u_int startkernel, u_int endkernel, char *args) 136ofwoea_initppc(u_int startkernel, u_int endkernel, char *args)
136{ 137{
137 int ofmaplen, node, l; 138 int ofmaplen, node, l;
138 register_t scratch; 139 register_t scratch;
139 140
140#if defined(MULTIPROCESSOR) && defined(ofppc) 141#if defined(MULTIPROCESSOR) && defined(ofppc)
141 char cpupath[32]; 142 char cpupath[32];
142 int i; 143 int i;
143#endif 144#endif
144 145
145 /* initialze bats */ 146 /* initialze bats */
146 if ((oeacpufeat & OEACPU_NOBAT) == 0) 147 if ((oeacpufeat & OEACPU_NOBAT) == 0)
147 ofwoea_batinit(); 148 ofwoea_batinit();
148 149
149#if NKSYMS || defined(DDB) || defined(MODULAR) 150#if NKSYMS || defined(DDB) || defined(MODULAR)
150 /* get info of kernel symbol table from bootloader */ 151 /* get info of kernel symbol table from bootloader */
151 memcpy(&startsym, args + strlen(args) + 1, sizeof(startsym)); 152 memcpy(&startsym, args + strlen(args) + 1, sizeof(startsym));
152 memcpy(&endsym, args + strlen(args) + 1 + sizeof(startsym), 153 memcpy(&endsym, args + strlen(args) + 1 + sizeof(startsym),
153 sizeof(endsym)); 154 sizeof(endsym));
154 if (startsym == NULL || endsym == NULL) 155 if (startsym == NULL || endsym == NULL)
155 startsym = endsym = NULL; 156 startsym = endsym = NULL;
156#endif 157#endif
157 158
158 /* get model name and perform model-specific actions */ 159 /* get model name and perform model-specific actions */
159 memset(model_name, 0, sizeof(model_name)); 160 memset(model_name, 0, sizeof(model_name));
160 node = OF_finddevice("/"); 161 node = OF_finddevice("/");
161 if (node >= 0) { 162 if (node >= 0) {
162 l = OF_getprop(node, "model", model_name, sizeof(model_name)); 163 l = OF_getprop(node, "model", model_name, sizeof(model_name));
163 if (l == -1) 164 if (l == -1)
164 OF_getprop(node, "name", model_name, 165 OF_getprop(node, "name", model_name,
165 sizeof(model_name)); 166 sizeof(model_name));
166 model_init(); 167 model_init();
167 } 168 }
168 /* Initialize bus_space */ 169 /* Initialize bus_space */
169 ofwoea_bus_space_init(); 170 ofwoea_bus_space_init();
170 171
171 ofwoea_consinit(); 172 ofwoea_consinit();
172 173
173#if defined(MULTIPROCESSOR) && defined(ofppc) 174#if defined(MULTIPROCESSOR) && defined(ofppc)
174 for (i=1; i < CPU_MAXNUM; i++) { 175 for (i=1; i < CPU_MAXNUM; i++) {
175 sprintf(cpupath, "/cpus/@%x", i); 176 sprintf(cpupath, "/cpus/@%x", i);
176 node = OF_finddevice(cpupath); 177 node = OF_finddevice(cpupath);
177 if (node <= 0) 178 if (node <= 0)
178 continue; 179 continue;
179 aprint_verbose("Starting up CPU %d %s\n", i, cpupath); 180 aprint_verbose("Starting up CPU %d %s\n", i, cpupath);
180 OF_start_cpu(node, (u_int)cpu_spinstart, i); 181 OF_start_cpu(node, (u_int)cpu_spinstart, i);
181 for (l=0; l < 100000000; l++) { 182 for (l=0; l < 100000000; l++) {
182 if (cpu_spinstart_ack == i) { 183 if (cpu_spinstart_ack == i) {
183 aprint_verbose("CPU %d spun up.\n", i); 184 aprint_verbose("CPU %d spun up.\n", i);
184 break; 185 break;
185 } 186 }
186 __asm volatile ("sync"); 187 __asm volatile ("sync");
187 } 188 }
188 } 189 }
189#endif 190#endif
190 191
191#if defined (PPC_OEA64_BRIDGE) && defined (PPC_OEA) 192#if defined (PPC_OEA64_BRIDGE) && defined (PPC_OEA)
192 if (oeacpufeat & OEACPU_64_BRIDGE) 193 if (oeacpufeat & OEACPU_64_BRIDGE)
193 pmap_setup64bridge(); 194 pmap_setup64bridge();
194 else 195 else
195 pmap_setup32(); 196 pmap_setup32();
196#endif 197#endif
197 198
198 oea_init(pic_ext_intr); 199 oea_init(pic_ext_intr);
199 200
200 ofmaplen = save_ofmap(NULL, 0); 201 ofmaplen = save_ofmap(NULL, 0);
201 if (ofmaplen > 0) 202 if (ofmaplen > 0)
202 save_ofmap(ofmap, ofmaplen); 203 save_ofmap(ofmap, ofmaplen);
203 204
 205/*
 206 * XXX
 207 * we need to do this here instead of earlier on in ofwinit() for some reason
 208 * At least some versions of Apple OF 2.0.1 hang if we do this earlier
 209 */
 210 ofwmsr &= ~PSL_IP;
 211
204 /* Parse the args string */ 212 /* Parse the args string */
205 if (args) { 213 if (args) {
206 strcpy(bootpath, args); 214 strcpy(bootpath, args);
207 args = bootpath; 215 args = bootpath;
208 while (*++args && *args != ' '); 216 while (*++args && *args != ' ');
209 if (*args) { 217 if (*args) {
210 *args++ = 0; 218 *args++ = 0;
211 while (*args) 219 while (*args)
212 BOOT_FLAG(*args++, boothowto); 220 BOOT_FLAG(*args++, boothowto);
213 } 221 }
214 } 222 }
215 223
216 uvm_setpagesize(); 224 uvm_setpagesize();
217 225
218 pmap_bootstrap(startkernel, endkernel); 226 pmap_bootstrap(startkernel, endkernel);
219 227
220/* as far as I can tell, the pmap_setup_seg0 stuff is horribly broken */ 228/* as far as I can tell, the pmap_setup_seg0 stuff is horribly broken */
221#if defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE) 229#if defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
222#if defined (PMAC_G5) 230#if defined (PMAC_G5)
223 /* Mapin 1st 256MB segment 1:1, also map in mem needed to access OFW*/ 231 /* Mapin 1st 256MB segment 1:1, also map in mem needed to access OFW*/
224 if (oeacpufeat & OEACPU_64_BRIDGE) 232 if (oeacpufeat & OEACPU_64_BRIDGE)
225 pmap_setup_segment0_map(0, 0xff800000, 0x3fc00000, 0x400000, 233 pmap_setup_segment0_map(0, 0xff800000, 0x3fc00000, 0x400000,
226 0x0); 234 0x0);
227#elif defined (MAMBO) 235#elif defined (MAMBO)
228 /* Mapin 1st 256MB segment 1:1, also map in mem needed to access OFW*/ 236 /* Mapin 1st 256MB segment 1:1, also map in mem needed to access OFW*/
229 if (oeacpufeat & OEACPU_64_BRIDGE) 237 if (oeacpufeat & OEACPU_64_BRIDGE)
230 pmap_setup_segment0_map(0, 0xf4000000, 0xf4000000, 0x1000, 0x0); 238 pmap_setup_segment0_map(0, 0xf4000000, 0xf4000000, 0x1000, 0x0);
231#endif /* PMAC_G5 */ 239#endif /* PMAC_G5 */
232#endif /* PPC_OEA64 || PPC_OEA64_BRIDGE */ 240#endif /* PPC_OEA64 || PPC_OEA64_BRIDGE */
233 241
234 /* Now enable translation (and machine checks/recoverable interrupts) */ 242 /* Now enable translation (and machine checks/recoverable interrupts) */
235 __asm __volatile ("sync; mfmsr %0; ori %0,%0,%1; mtmsr %0; isync" 243 __asm __volatile ("sync; mfmsr %0; ori %0,%0,%1; mtmsr %0; isync"
236 : "=r"(scratch) 244 : "=r"(scratch)
237 : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI)); 245 : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI));
238 246
239 restore_ofmap(ofmap, ofmaplen); 247 restore_ofmap(ofmap, ofmaplen);
240 248
241#if NKSYMS || defined(DDB) || defined(MODULAR) 249#if NKSYMS || defined(DDB) || defined(MODULAR)
242 ksyms_addsyms_elf((int)((u_int)endsym - (u_int)startsym), startsym, endsym); 250 ksyms_addsyms_elf((int)((u_int)endsym - (u_int)startsym), startsym, endsym);
243#endif 251#endif
244 252
245 /* CPU clock stuff */ 253 /* CPU clock stuff */
246 set_timebase(); 254 set_timebase();
247} 255}
248 256
249void 257void
250set_timebase(void) 258set_timebase(void)
251{ 259{
252 int qhandle, phandle, msr, scratch; 260 int qhandle, phandle, msr, scratch;
253 char type[32]; 261 char type[32];
254 262
255 if (timebase_freq != 0) { 263 if (timebase_freq != 0) {
256 ticks_per_sec = timebase_freq; 264 ticks_per_sec = timebase_freq;
257 goto found; 265 goto found;
258 } 266 }
259 267
260 for (qhandle = OF_peer(0); qhandle; qhandle = phandle) { 268 for (qhandle = OF_peer(0); qhandle; qhandle = phandle) {
261 if (OF_getprop(qhandle, "device_type", type, sizeof type) > 0 269 if (OF_getprop(qhandle, "device_type", type, sizeof type) > 0
262 && strcmp(type, "cpu") == 0 270 && strcmp(type, "cpu") == 0
263 && OF_getprop(qhandle, "timebase-frequency", 271 && OF_getprop(qhandle, "timebase-frequency",
264 &ticks_per_sec, sizeof ticks_per_sec) > 0) { 272 &ticks_per_sec, sizeof ticks_per_sec) > 0) {
265 goto found; 273 goto found;
266 } 274 }
267 if ((phandle = OF_child(qhandle))) 275 if ((phandle = OF_child(qhandle)))
268 continue; 276 continue;
269 while (qhandle) { 277 while (qhandle) {
270 if ((phandle = OF_peer(qhandle))) 278 if ((phandle = OF_peer(qhandle)))
271 break; 279 break;
272 qhandle = OF_parent(qhandle); 280 qhandle = OF_parent(qhandle);
273 } 281 }
274 } 282 }
275 panic("no cpu node"); 283 panic("no cpu node");
276 284
277found: 285found:
278 __asm volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1" 286 __asm volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1"
279 : "=r"(msr), "=r"(scratch) : "K"((u_short)~PSL_EE)); 287 : "=r"(msr), "=r"(scratch) : "K"((u_short)~PSL_EE));
280 ns_per_tick = 1000000000 / ticks_per_sec; 288 ns_per_tick = 1000000000 / ticks_per_sec;
281 ticks_per_intr = ticks_per_sec / hz; 289 ticks_per_intr = ticks_per_sec / hz;
282 cpu_timebase = ticks_per_sec; 290 cpu_timebase = ticks_per_sec;
283 curcpu()->ci_lasttb = mftbl(); 291 curcpu()->ci_lasttb = mftbl();
284 mtspr(SPR_DEC, ticks_per_intr); 292 mtspr(SPR_DEC, ticks_per_intr);
285 mtmsr(msr); 293 mtmsr(msr);
286} 294}
287 295
288static int 296static int
289save_ofmap(struct ofw_translations *map, int maxlen) 297save_ofmap(struct ofw_translations *map, int maxlen)
290{ 298{
291 int mmui, mmu, len; 299 int mmui, mmu, len;
292 300
293 OF_getprop(chosen, "mmu", &mmui, sizeof mmui); 301 OF_getprop(chosen, "mmu", &mmui, sizeof mmui);
294 mmu = OF_instance_to_package(mmui); 302 mmu = OF_instance_to_package(mmui);
295 303
296 if (map) { 304 if (map) {
297 memset(map, 0, maxlen); /* to be safe */ 305 memset(map, 0, maxlen); /* to be safe */
298 len = OF_getprop(mmu, "translations", map, maxlen); 306 len = OF_getprop(mmu, "translations", map, maxlen);
299 } else 307 } else
300 len = OF_getproplen(mmu, "translations"); 308 len = OF_getproplen(mmu, "translations");
301 309
302 if (len < 0) 310 if (len < 0)
303 len = 0; 311 len = 0;
304 return len; 312 return len;
305} 313}
306 314
307 315
308/* The PMAC_G5 code here needs to be replaced by code that looks for the 316/* The PMAC_G5 code here needs to be replaced by code that looks for the
309 size_cells and does the right thing automatically. 317 size_cells and does the right thing automatically.
310*/ 318*/
311void 319void
312restore_ofmap(struct ofw_translations *map, int len) 320restore_ofmap(struct ofw_translations *map, int len)
313{ 321{
314 int n = len / sizeof(struct ofw_translations); 322 int n = len / sizeof(struct ofw_translations);
315 int i; 323 int i;
316 324
317 pmap_pinit(&ofw_pmap); 325 pmap_pinit(&ofw_pmap);
318 326
319 ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT; 327 ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT;
320 328
321#ifdef KERNEL2_SR 329#ifdef KERNEL2_SR
322 ofw_pmap.pm_sr[KERNEL2_SR] = KERNEL2_SEGMENT; 330 ofw_pmap.pm_sr[KERNEL2_SR] = KERNEL2_SEGMENT;
323#endif 331#endif
324 332
325 for (i = 0; i < n; i++) { 333 for (i = 0; i < n; i++) {
326#if defined (PMAC_G5) 334#if defined (PMAC_G5)
327 register64_t pa = map[i].pa; 335 register64_t pa = map[i].pa;
328#else 336#else
329 register_t pa = map[i].pa; 337 register_t pa = map[i].pa;
330#endif 338#endif
331 vaddr_t va = map[i].va; 339 vaddr_t va = map[i].va;
332 size_t length = map[i].len; 340 size_t length = map[i].len;
333 341
334 if (va < 0xf0000000) /* XXX */ 342 if (va < 0xf0000000) /* XXX */
335 continue; 343 continue;
336 344
337 while (length > 0) { 345 while (length > 0) {
338 pmap_enter(&ofw_pmap, va, (paddr_t)pa, VM_PROT_ALL, 346 pmap_enter(&ofw_pmap, va, (paddr_t)pa, VM_PROT_ALL,
339 VM_PROT_ALL|PMAP_WIRED); 347 VM_PROT_ALL|PMAP_WIRED);
340 pa += PAGE_SIZE; 348 pa += PAGE_SIZE;
341 va += PAGE_SIZE; 349 va += PAGE_SIZE;
342 length -= PAGE_SIZE; 350 length -= PAGE_SIZE;
343 } 351 }
344 } 352 }
345 pmap_update(&ofw_pmap); 353 pmap_update(&ofw_pmap);
346} 354}
347 355
348 356
349 357
350/* 358/*
351 * Scan the device tree for ranges, and return them as bitmap 0..15 359 * Scan the device tree for ranges, and return them as bitmap 0..15
352 */ 360 */
353 361
354static u_int16_t 362static u_int16_t
355ranges_bitmap(int node, u_int16_t bitmap) 363ranges_bitmap(int node, u_int16_t bitmap)
356{ 364{
357 int child, mlen, acells, scells, reclen, i, j; 365 int child, mlen, acells, scells, reclen, i, j;
358 u_int32_t addr, len, map[160]; 366 u_int32_t addr, len, map[160];
359 367
360 for (child = OF_child(node); child; child = OF_peer(child)) { 368 for (child = OF_child(node); child; child = OF_peer(child)) {
361 mlen = OF_getprop(child, "ranges", map, sizeof(map)); 369 mlen = OF_getprop(child, "ranges", map, sizeof(map));
362 if (mlen == -1) 370 if (mlen == -1)
363 goto noranges; 371 goto noranges;
364 372
365 j = OF_getprop(child, "#address-cells", &acells, 373 j = OF_getprop(child, "#address-cells", &acells,
366 sizeof(acells)); 374 sizeof(acells));
367 if (j == -1) 375 if (j == -1)
368 goto noranges; 376 goto noranges;
369 377
370 j = OF_getprop(child, "#size-cells", &scells, 378 j = OF_getprop(child, "#size-cells", &scells,
371 sizeof(scells)); 379 sizeof(scells));
372 if (j == -1) 380 if (j == -1)
373 goto noranges; 381 goto noranges;
374 382
375#ifdef ofppc 383#ifdef ofppc
376 reclen = acells + modeldata.ranges_offset + scells; 384 reclen = acells + modeldata.ranges_offset + scells;
377#else 385#else
378 reclen = acells + 1 + scells; 386 reclen = acells + 1 + scells;
379#endif 387#endif
380 388
381 for (i=0; i < (mlen/4)/reclen; i++) { 389 for (i=0; i < (mlen/4)/reclen; i++) {
382 addr = map[reclen * i + acells]; 390 addr = map[reclen * i + acells];
383 len = map[reclen * i + reclen - 1]; 391 len = map[reclen * i + reclen - 1];
384 for (j = 0; j < len / 0x10000000; j++) 392 for (j = 0; j < len / 0x10000000; j++)
385 bitmap |= 1 << ((addr+j*0x10000000) >>28); 393 bitmap |= 1 << ((addr+j*0x10000000) >>28);
386 bitmap |= 1 << (addr >> 28); 394 bitmap |= 1 << (addr >> 28);
387 } 395 }
388noranges: 396noranges:
389 bitmap |= ranges_bitmap(child, bitmap); 397 bitmap |= ranges_bitmap(child, bitmap);
390 continue; 398 continue;
391 } 399 }
392 return bitmap; 400 return bitmap;
393} 401}
394 402
395void 403void
396ofwoea_batinit(void) 404ofwoea_batinit(void)
397{ 405{
398#if defined (PPC_OEA) 406#if defined (PPC_OEA)
399 u_int16_t bitmap; 407 u_int16_t bitmap;
400 int node, i; 408 int node, i;
401 409
402 node = OF_finddevice("/"); 410 node = OF_finddevice("/");
403 bitmap = ranges_bitmap(node, 0); 411 bitmap = ranges_bitmap(node, 0);
404 oea_batinit(0); 412 oea_batinit(0);
405 413
406#ifdef macppc 414#ifdef macppc
407 /* XXX this is a macppc-specific hack */ 415 /* XXX this is a macppc-specific hack */
408 bitmap = 0x8f00; 416 bitmap = 0x8f00;
409#endif 417#endif
410 for (i=1; i < 0x10; i++) { 418 for (i=1; i < 0x10; i++) {
411 /* skip the three vital SR regions */ 419 /* skip the three vital SR regions */
412 if (i == USER_SR || i == KERNEL_SR || i == KERNEL2_SR) 420 if (i == USER_SR || i == KERNEL_SR || i == KERNEL2_SR)
413 continue; 421 continue;
414 if (bitmap & (1 << i)) { 422 if (bitmap & (1 << i)) {
415 oea_iobat_add(0x10000000 * i, BAT_BL_256M); 423 oea_iobat_add(0x10000000 * i, BAT_BL_256M);
416 DPRINTF("Batmapped 256M at 0x%x\n", 0x10000000 * i); 424 DPRINTF("Batmapped 256M at 0x%x\n", 0x10000000 * i);
417 } 425 }
418 } 426 }
419#endif /* OEA */ 427#endif /* OEA */
420} 428}
421 429
422 430
423/* we define these partially, as we will fill the rest in later */ 431/* we define these partially, as we will fill the rest in later */
424struct powerpc_bus_space genppc_isa_io_space_tag = { 432struct powerpc_bus_space genppc_isa_io_space_tag = {
425 .pbs_flags = _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE, 433 .pbs_flags = _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE,
426 .pbs_base = 0x00000000, 434 .pbs_base = 0x00000000,
427}; 435};
428 436
429struct powerpc_bus_space genppc_isa_mem_space_tag = { 437struct powerpc_bus_space genppc_isa_mem_space_tag = {
430 .pbs_flags = _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE, 438 .pbs_flags = _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE,
431 .pbs_base = 0x00000000, 439 .pbs_base = 0x00000000,
432}; 440};
433 441
434/* This gives us a maximum of 6 PCI busses, assuming both io/mem on each. 442/* This gives us a maximum of 6 PCI busses, assuming both io/mem on each.
435 * Increase if necc. 443 * Increase if necc.
436 */ 444 */
437static char ex_storage[EXSTORAGE_MAX][EXTENT_FIXED_STORAGE_SIZE(EXTMAP_RANGES)] 445static char ex_storage[EXSTORAGE_MAX][EXTENT_FIXED_STORAGE_SIZE(EXTMAP_RANGES)]
438 __attribute__((aligned(8))); 446 __attribute__((aligned(8)));
439 447
440 448
441static void 449static void
442find_ranges(int base, rangemap_t *regions, int *cur, int type) 450find_ranges(int base, rangemap_t *regions, int *cur, int type)
443{ 451{
444 int node, i, len, reclen; 452 int node, i, len, reclen;
445 u_int32_t acells, scells, map[160]; 453 u_int32_t acells, scells, map[160];
446 char tmp[32]; 454 char tmp[32];
447 455
448 node = base; 456 node = base;
449 if (OF_getprop(node, "device_type", tmp, sizeof(tmp)) == -1) 457 if (OF_getprop(node, "device_type", tmp, sizeof(tmp)) == -1)
450 goto rec; 458 goto rec;
451 if ((type == RANGE_TYPE_PCI || type == RANGE_TYPE_FIRSTPCI) && 459 if ((type == RANGE_TYPE_PCI || type == RANGE_TYPE_FIRSTPCI) &&
452 strcmp("pci", tmp) != 0) 460 strcmp("pci", tmp) != 0)
453 goto rec; 461 goto rec;
454 if (type == RANGE_TYPE_ISA && strcmp("isa", tmp) != 0) 462 if (type == RANGE_TYPE_ISA && strcmp("isa", tmp) != 0)
455 goto rec; 463 goto rec;
456 len = OF_getprop(node, "ranges", map, sizeof(map)); 464 len = OF_getprop(node, "ranges", map, sizeof(map));
457 if (len == -1) 465 if (len == -1)
458 goto rec; 466 goto rec;
459 if (OF_getprop(node, "#address-cells", &acells, 467 if (OF_getprop(node, "#address-cells", &acells,
460 sizeof(acells)) != sizeof(acells)) 468 sizeof(acells)) != sizeof(acells))
461 acells = 1; 469 acells = 1;
462 if (OF_getprop(node, "#size-cells", &scells, 470 if (OF_getprop(node, "#size-cells", &scells,
463 sizeof(scells)) != sizeof(scells)) 471 sizeof(scells)) != sizeof(scells))
464 scells = 1; 472 scells = 1;
465#ifdef ofppc 473#ifdef ofppc
466 if (modeldata.ranges_offset == 0) 474 if (modeldata.ranges_offset == 0)
467 scells -= 1; 475 scells -= 1;
468#endif 476#endif
469 if (type == RANGE_TYPE_ISA) 477 if (type == RANGE_TYPE_ISA)
470 reclen = 6; 478 reclen = 6;
471 else 479 else
472 reclen = acells + scells + 1; 480 reclen = acells + scells + 1;
473 /* 481 /*
474 * There exist ISA buses with empty ranges properties. This is 482 * There exist ISA buses with empty ranges properties. This is
475 * known to occur on the Pegasos II machine, and likely others. 483 * known to occur on the Pegasos II machine, and likely others.
476 * According to them, that means that the isa bus is a fake bus, and 484 * According to them, that means that the isa bus is a fake bus, and
477 * the real maps are the PCI maps of the preceeding bus. To deal 485 * the real maps are the PCI maps of the preceeding bus. To deal
478 * with this, we will set cur to -1 and return. 486 * with this, we will set cur to -1 and return.
479 */ 487 */
480 if (type == RANGE_TYPE_ISA && strcmp("isa", tmp) == 0 && len == 0) { 488 if (type == RANGE_TYPE_ISA && strcmp("isa", tmp) == 0 && len == 0) {
481 *cur = -1; 489 *cur = -1;
482 DPRINTF("Found empty range in isa bus\n"); 490 DPRINTF("Found empty range in isa bus\n");
483 return; 491 return;
484 } 492 }
485 493
486 DPRINTF("found a map reclen=%d cur=%d len=%d\n", reclen, *cur, len); 494 DPRINTF("found a map reclen=%d cur=%d len=%d\n", reclen, *cur, len);
487 switch (type) { 495 switch (type) {
488 case RANGE_TYPE_PCI: 496 case RANGE_TYPE_PCI:
489 case RANGE_TYPE_FIRSTPCI: 497 case RANGE_TYPE_FIRSTPCI:
490 for (i=0; i < len/(4*reclen); i++) { 498 for (i=0; i < len/(4*reclen); i++) {
491 DPRINTF("FOUND PCI RANGE\n"); 499 DPRINTF("FOUND PCI RANGE\n");
492 regions[*cur].size = 500 regions[*cur].size =
493 map[i*reclen + acells + scells]; 501 map[i*reclen + acells + scells];
494 /* skip ranges of size==0 */ 502 /* skip ranges of size==0 */
495 if (regions[*cur].size == 0) 503 if (regions[*cur].size == 0)
496 continue; 504 continue;
497 regions[*cur].type = map[i*reclen] >> 24; 505 regions[*cur].type = map[i*reclen] >> 24;
498 regions[*cur].addr = map[i*reclen + acells]; 506 regions[*cur].addr = map[i*reclen + acells];
499 (*cur)++; 507 (*cur)++;
500 } 508 }
501 break; 509 break;
502 case RANGE_TYPE_ISA: 510 case RANGE_TYPE_ISA:
503 for (i=0; i < len/(4*reclen); i++) { 511 for (i=0; i < len/(4*reclen); i++) {
504 if (map[i*reclen] == 1) 512 if (map[i*reclen] == 1)
505 regions[*cur].type = RANGE_IO; 513 regions[*cur].type = RANGE_IO;
506 else 514 else
507 regions[*cur].type = RANGE_MEM; 515 regions[*cur].type = RANGE_MEM;
508 DPRINTF("FOUND ISA RANGE TYPE=%d\n", 516 DPRINTF("FOUND ISA RANGE TYPE=%d\n",
509 regions[*cur].type); 517 regions[*cur].type);
510 regions[*cur].size = 518 regions[*cur].size =
511 map[i*reclen + acells + scells]; 519 map[i*reclen + acells + scells];
512 (*cur)++; 520 (*cur)++;
513 } 521 }
514 break; 522 break;
515 } 523 }
516 DPRINTF("returning with CUR=%d\n", *cur); 524 DPRINTF("returning with CUR=%d\n", *cur);
517 return; 525 return;
518rec: 526rec:
519 for (node = OF_child(base); node; node = OF_peer(node)) { 527 for (node = OF_child(base); node; node = OF_peer(node)) {
520 DPRINTF("RECURSE 1 STEP\n"); 528 DPRINTF("RECURSE 1 STEP\n");
521 find_ranges(node, regions, cur, type); 529 find_ranges(node, regions, cur, type);
522 if (*cur == -1) 530 if (*cur == -1)
523 return; 531 return;
524 } 532 }
525} 533}
526 534
527static int 535static int
528find_lowest_range(rangemap_t *ranges, int nrof, int type) 536find_lowest_range(rangemap_t *ranges, int nrof, int type)
529{ 537{
530 int i, low = 0; 538 int i, low = 0;
531 u_int32_t addr = 0xffffffff; 539 u_int32_t addr = 0xffffffff;
532 540
533 for (i=0; i < nrof; i++) { 541 for (i=0; i < nrof; i++) {
534 if (ranges[i].type == type && ranges[i].addr != 0 && 542 if (ranges[i].type == type && ranges[i].addr != 0 &&
535 ranges[i].addr < addr) { 543 ranges[i].addr < addr) {
536 low = i; 544 low = i;
537 addr = ranges[i].addr; 545 addr = ranges[i].addr;
538 } 546 }
539 } 547 }
540 if (addr == 0xffffffff) 548 if (addr == 0xffffffff)
541 return -1; 549 return -1;
542 return low; 550 return low;
543} 551}
544 552
545/* 553/*
546 * Find a region of memory, and create a bus_space_tag for it. 554 * Find a region of memory, and create a bus_space_tag for it.
547 * Notes: 555 * Notes:
548 * For ISA node is ignored. 556 * For ISA node is ignored.
549 * node is the starting node. if -1, we start at / and map everything. 557 * node is the starting node. if -1, we start at / and map everything.
550 */ 558 */
551 559
552int 560int
553ofwoea_map_space(int rangetype, int iomem, int node, 561ofwoea_map_space(int rangetype, int iomem, int node,
554 struct powerpc_bus_space *tag, const char *name) 562 struct powerpc_bus_space *tag, const char *name)
555{ 563{
556 int i, cur, range, nrofholes, error; 564 int i, cur, range, nrofholes, error;
557 static int exmap=0; 565 static int exmap=0;
558 u_int32_t addr; 566 u_int32_t addr;
559 rangemap_t region, holes[32], list[32]; 567 rangemap_t region, holes[32], list[32];
560 568
561 memset(list, 0, sizeof(list)); 569 memset(list, 0, sizeof(list));
562 cur = 0; 570 cur = 0;
563 if (rangetype == RANGE_TYPE_ISA || node == -1) 571 if (rangetype == RANGE_TYPE_ISA || node == -1)
564 node = OF_finddevice("/"); 572 node = OF_finddevice("/");
565 if (rangetype == RANGE_TYPE_ISA) { 573 if (rangetype == RANGE_TYPE_ISA) {
566 u_int32_t size = 0; 574 u_int32_t size = 0;
567 rangemap_t regions[32]; 575 rangemap_t regions[32];
568 576
569 DPRINTF("LOOKING FOR FIRSTPCI\n"); 577 DPRINTF("LOOKING FOR FIRSTPCI\n");
570 find_ranges(node, list, &cur, RANGE_TYPE_FIRSTPCI); 578 find_ranges(node, list, &cur, RANGE_TYPE_FIRSTPCI);
571 range = 0; 579 range = 0;
572 DPRINTF("LOOKING FOR ISA\n"); 580 DPRINTF("LOOKING FOR ISA\n");
573 find_ranges(node, regions, &range, RANGE_TYPE_ISA); 581 find_ranges(node, regions, &range, RANGE_TYPE_ISA);
574 if (range == 0 || cur == 0) 582 if (range == 0 || cur == 0)
575 return -1; /* no isa stuff found */ 583 return -1; /* no isa stuff found */
576 /* 584 /*
577 * This may be confusing to some. The ISA ranges property 585 * This may be confusing to some. The ISA ranges property
578 * is supposed to be a set of IO ranges for the ISA bus, but 586 * is supposed to be a set of IO ranges for the ISA bus, but
579 * generally, it's just a set of pci devfunc lists that tell 587 * generally, it's just a set of pci devfunc lists that tell
580 * you to go look at the parent PCI device for the actual 588 * you to go look at the parent PCI device for the actual
581 * ranges. 589 * ranges.
582 */ 590 */
583 if (range == -1) { 591 if (range == -1) {
584 /* we found a rangeless isa bus */ 592 /* we found a rangeless isa bus */
585 if (iomem == RANGE_IO) 593 if (iomem == RANGE_IO)
586 size = 0x10000; 594 size = 0x10000;
587 else 595 else
588 size = 0x1000000; 596 size = 0x1000000;
589 } 597 }
590 DPRINTF("found isa stuff\n"); 598 DPRINTF("found isa stuff\n");
591 for (i=0; i < range; i++) 599 for (i=0; i < range; i++)
592 if (regions[i].type == iomem) 600 if (regions[i].type == iomem)
593 size = regions[i].size; 601 size = regions[i].size;
594 if (iomem == RANGE_IO) { 602 if (iomem == RANGE_IO) {
595 /* the first io range is the one */ 603 /* the first io range is the one */
596 for (i=0; i < cur; i++) 604 for (i=0; i < cur; i++)
597 if (list[i].type == RANGE_IO && size) { 605 if (list[i].type == RANGE_IO && size) {
598 DPRINTF("found IO\n"); 606 DPRINTF("found IO\n");
599 tag->pbs_offset = list[i].addr; 607 tag->pbs_offset = list[i].addr;
600 tag->pbs_limit = size; 608 tag->pbs_limit = size;
601 error = bus_space_init(tag, name, 609 error = bus_space_init(tag, name,
602 ex_storage[exmap], 610 ex_storage[exmap],
603 sizeof(ex_storage[exmap])); 611 sizeof(ex_storage[exmap]));
604 exmap++; 612 exmap++;
605 return error; 613 return error;
606 } 614 }
607 } else { 615 } else {
608 for (i=0; i < cur; i++) 616 for (i=0; i < cur; i++)
609 if (list[i].type == RANGE_MEM && 617 if (list[i].type == RANGE_MEM &&
610 list[i].size == size) { 618 list[i].size == size) {
611 DPRINTF("found mem\n"); 619 DPRINTF("found mem\n");
612 tag->pbs_offset = list[i].addr; 620 tag->pbs_offset = list[i].addr;
613 tag->pbs_limit = size; 621 tag->pbs_limit = size;
614 error = bus_space_init(tag, name, 622 error = bus_space_init(tag, name,
615 ex_storage[exmap], 623 ex_storage[exmap],
616 sizeof(ex_storage[exmap])); 624 sizeof(ex_storage[exmap]));
617 exmap++; 625 exmap++;
618 return error; 626 return error;
619 } 627 }
620 } 628 }
621 return -1; /* NO ISA FOUND */ 629 return -1; /* NO ISA FOUND */
622 } 630 }
623 find_ranges(node, list, &cur, rangetype); 631 find_ranges(node, list, &cur, rangetype);
624 632
625 DPRINTF("cur == %d\n", cur); 633 DPRINTF("cur == %d\n", cur);
626 /* now list should contain a list of memory regions */ 634 /* now list should contain a list of memory regions */
627 for (i=0; i < cur; i++) 635 for (i=0; i < cur; i++)
628 DPRINTF("addr=0x%x size=0x%x type=%d\n", list[i].addr, 636 DPRINTF("addr=0x%x size=0x%x type=%d\n", list[i].addr,
629 list[i].size, list[i].type); 637 list[i].size, list[i].type);
630 638
631 addr=0; 639 addr=0;
632 range = find_lowest_range(list, cur, iomem); 640 range = find_lowest_range(list, cur, iomem);
633 i = 0; 641 i = 0;
634 nrofholes = 0; 642 nrofholes = 0;
635 while (range != -1) { 643 while (range != -1) {
636 DPRINTF("range==%d\n", range); 644 DPRINTF("range==%d\n", range);
637 DPRINTF("i==%d\n", i); 645 DPRINTF("i==%d\n", i);
638 if (i == 0) { 646 if (i == 0) {
639 memcpy(&region, &list[range], sizeof(rangemap_t)); 647 memcpy(&region, &list[range], sizeof(rangemap_t));
640 list[range].addr = 0; 648 list[range].addr = 0;
641 i++; 649 i++;
642 range = find_lowest_range(list, cur, iomem); 650 range = find_lowest_range(list, cur, iomem);
643 continue; 651 continue;
644 } 652 }
645 if (region.addr + region.size < list[range].addr) { 653 if (region.addr + region.size < list[range].addr) {
646 /* allocate a hole */ 654 /* allocate a hole */
647 holes[nrofholes].type = iomem; 655 holes[nrofholes].type = iomem;
648 holes[nrofholes].addr = region.size + region.addr; 656 holes[nrofholes].addr = region.size + region.addr;
649 holes[nrofholes].size = list[range].addr - 657 holes[nrofholes].size = list[range].addr -
650 holes[nrofholes].addr - 1; 658 holes[nrofholes].addr - 1;
651 nrofholes++; 659 nrofholes++;
652 } 660 }
653 region.size = list[range].size + list[range].addr - 661 region.size = list[range].size + list[range].addr -
654 region.addr; 662 region.addr;
655 list[range].addr = 0; 663 list[range].addr = 0;
656 range = find_lowest_range(list, cur, iomem); 664 range = find_lowest_range(list, cur, iomem);
657 } 665 }
658 DPRINTF("RANGE iomem=%d FOUND\n", iomem); 666 DPRINTF("RANGE iomem=%d FOUND\n", iomem);
659 DPRINTF("addr=0x%x size=0x%x type=%d\n", region.addr, 667 DPRINTF("addr=0x%x size=0x%x type=%d\n", region.addr,
660 region.size, region.type); 668 region.size, region.type);
661 DPRINTF("HOLES FOUND\n"); 669 DPRINTF("HOLES FOUND\n");
662 for (i=0; i < nrofholes; i++) 670 for (i=0; i < nrofholes; i++)
663 DPRINTF("addr=0x%x size=0x%x type=%d\n", holes[i].addr, 671 DPRINTF("addr=0x%x size=0x%x type=%d\n", holes[i].addr,
664 holes[i].size, holes[i].type); 672 holes[i].size, holes[i].type);
665 /* AT THIS POINT WE MAP IT */ 673 /* AT THIS POINT WE MAP IT */
666 674
667 if (rangetype == RANGE_TYPE_PCI) { 675 if (rangetype == RANGE_TYPE_PCI) {
668 if (exmap == EXSTORAGE_MAX) 676 if (exmap == EXSTORAGE_MAX)
669 panic("Not enough ex_storage space. " 677 panic("Not enough ex_storage space. "
670 "Increase EXSTORAGE_MAX"); 678 "Increase EXSTORAGE_MAX");
671 679
672 /* XXX doing this in here might be wrong */ 680 /* XXX doing this in here might be wrong */
673 if (iomem == 1) { 681 if (iomem == 1) {
674 /* we map an IO region */ 682 /* we map an IO region */
675 tag->pbs_offset = region.addr; 683 tag->pbs_offset = region.addr;
676 tag->pbs_base = 0; 684 tag->pbs_base = 0;
677 tag->pbs_limit = region.size; 685 tag->pbs_limit = region.size;
678 } else { 686 } else {
679 /* ... or a memory region */ 687 /* ... or a memory region */
680 tag->pbs_offset = 0; 688 tag->pbs_offset = 0;
681 tag->pbs_base = region.addr; 689 tag->pbs_base = region.addr;
682 tag->pbs_limit = region.size + region.addr; 690 tag->pbs_limit = region.size + region.addr;
683 } 691 }
684 692
685 error = bus_space_init(tag, name, ex_storage[exmap], 693 error = bus_space_init(tag, name, ex_storage[exmap],
686 sizeof(ex_storage[exmap])); 694 sizeof(ex_storage[exmap]));
687 exmap++; 695 exmap++;
688 if (error) 696 if (error)
689 panic("ofwoea_bus_space_init: can't init tag %s", name); 697 panic("ofwoea_bus_space_init: can't init tag %s", name);
690 for (i=0; i < nrofholes; i++) { 698 for (i=0; i < nrofholes; i++) {
691 if (holes[i].type == RANGE_IO) { 699 if (holes[i].type == RANGE_IO) {
692 error = extent_alloc_region(tag->pbs_extent, 700 error = extent_alloc_region(tag->pbs_extent,
693 holes[i].addr - tag->pbs_offset, 701 holes[i].addr - tag->pbs_offset,
694 holes[i].size, EX_NOWAIT); 702 holes[i].size, EX_NOWAIT);
695 } else { 703 } else {
696 error = extent_alloc_region(tag->pbs_extent, 704 error = extent_alloc_region(tag->pbs_extent,
697 holes[i].addr, holes[i].size, EX_NOWAIT); 705 holes[i].addr, holes[i].size, EX_NOWAIT);
698 } 706 }
699 if (error) 707 if (error)
700 panic("ofwoea_bus_space_init: can't block out" 708 panic("ofwoea_bus_space_init: can't block out"
701 " reserved space 0x%x-0x%x: error=%d", 709 " reserved space 0x%x-0x%x: error=%d",
702 holes[i].addr, holes[i].addr+holes[i].size, 710 holes[i].addr, holes[i].addr+holes[i].size,
703 error); 711 error);
704 } 712 }
705 return error; 713 return error;
706 } 714 }
707 return -1; 715 return -1;
708} 716}
709 717
710void 718void
711ofwoea_bus_space_init(void) 719ofwoea_bus_space_init(void)
712{ 720{
713 int error; 721 int error;
714 722
715 error = ofwoea_map_space(RANGE_TYPE_ISA, RANGE_IO, -1, 723 error = ofwoea_map_space(RANGE_TYPE_ISA, RANGE_IO, -1,
716 &genppc_isa_io_space_tag, "isa-ioport"); 724 &genppc_isa_io_space_tag, "isa-ioport");
717 if (error > 0) 725 if (error > 0)
718 panic("Could not map ISA IO"); 726 panic("Could not map ISA IO");
719 727
720 error = ofwoea_map_space(RANGE_TYPE_ISA, RANGE_MEM, -1, 728 error = ofwoea_map_space(RANGE_TYPE_ISA, RANGE_MEM, -1,
721 &genppc_isa_mem_space_tag, "isa-iomem"); 729 &genppc_isa_mem_space_tag, "isa-iomem");
722 if (error > 0) 730 if (error > 0)
723 panic("Could not map ISA MEM"); 731 panic("Could not map ISA MEM");
724} 732}