| @@ -1,461 +1,461 @@ | | | @@ -1,461 +1,461 @@ |
1 | /* $NetBSD: machdep.c,v 1.161 2011/07/13 22:54:33 macallan Exp $ */ | | 1 | /* $NetBSD: machdep.c,v 1.162 2011/07/28 15:29:52 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 | #include <sys/cdefs.h> | | 34 | #include <sys/cdefs.h> |
35 | __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.161 2011/07/13 22:54:33 macallan Exp $"); | | 35 | __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.162 2011/07/28 15:29:52 macallan Exp $"); |
36 | | | 36 | |
37 | #include "opt_compat_netbsd.h" | | 37 | #include "opt_compat_netbsd.h" |
38 | #include "opt_ddb.h" | | 38 | #include "opt_ddb.h" |
39 | #include "opt_kgdb.h" | | 39 | #include "opt_kgdb.h" |
40 | #include "opt_ipkdb.h" | | 40 | #include "opt_ipkdb.h" |
41 | #include "opt_altivec.h" | | 41 | #include "opt_altivec.h" |
42 | #include "opt_multiprocessor.h" | | 42 | #include "opt_multiprocessor.h" |
43 | #include "adb.h" | | 43 | #include "adb.h" |
44 | #include "zsc.h" | | 44 | #include "zsc.h" |
45 | | | 45 | |
46 | #include <sys/param.h> | | 46 | #include <sys/param.h> |
47 | #include <sys/buf.h> | | 47 | #include <sys/buf.h> |
48 | #include <sys/boot_flag.h> | | 48 | #include <sys/boot_flag.h> |
49 | #include <sys/bus.h> | | 49 | #include <sys/bus.h> |
50 | #include <sys/conf.h> | | 50 | #include <sys/conf.h> |
51 | #include <sys/device.h> | | 51 | #include <sys/device.h> |
52 | #include <sys/exec.h> | | 52 | #include <sys/exec.h> |
53 | #include <sys/kernel.h> | | 53 | #include <sys/kernel.h> |
54 | #include <sys/ksyms.h> | | 54 | #include <sys/ksyms.h> |
55 | #include <sys/malloc.h> | | 55 | #include <sys/malloc.h> |
56 | #include <sys/mbuf.h> | | 56 | #include <sys/mbuf.h> |
57 | #include <sys/mount.h> | | 57 | #include <sys/mount.h> |
58 | #include <sys/msgbuf.h> | | 58 | #include <sys/msgbuf.h> |
59 | #include <sys/proc.h> | | 59 | #include <sys/proc.h> |
60 | #include <sys/reboot.h> | | 60 | #include <sys/reboot.h> |
61 | #include <sys/syscallargs.h> | | 61 | #include <sys/syscallargs.h> |
62 | #include <sys/syslog.h> | | 62 | #include <sys/syslog.h> |
63 | #include <sys/systm.h> | | 63 | #include <sys/systm.h> |
64 | | | 64 | |
65 | #ifdef DDB | | 65 | #ifdef DDB |
66 | #include <powerpc/db_machdep.h> | | 66 | #include <powerpc/db_machdep.h> |
67 | #include <ddb/db_extern.h> | | 67 | #include <ddb/db_extern.h> |
68 | #endif | | 68 | #endif |
69 | | | 69 | |
70 | #ifdef KGDB | | 70 | #ifdef KGDB |
71 | #include <sys/kgdb.h> | | 71 | #include <sys/kgdb.h> |
72 | #endif | | 72 | #endif |
73 | | | 73 | |
74 | #ifdef IPKDB | | 74 | #ifdef IPKDB |
75 | #include <ipkdb/ipkdb.h> | | 75 | #include <ipkdb/ipkdb.h> |
76 | #endif | | 76 | #endif |
77 | | | 77 | |
78 | #include <dev/ofw/openfirm.h> | | 78 | #include <dev/ofw/openfirm.h> |
79 | #include <dev/wsfb/genfbvar.h> | | 79 | #include <dev/wsfb/genfbvar.h> |
80 | | | 80 | |
81 | #include <machine/autoconf.h> | | 81 | #include <machine/autoconf.h> |
82 | #include <machine/powerpc.h> | | 82 | #include <machine/powerpc.h> |
83 | | | 83 | |
84 | #include <powerpc/trap.h> | | 84 | #include <powerpc/trap.h> |
85 | #include <powerpc/fpu.h> | | 85 | #include <powerpc/fpu.h> |
86 | #include <powerpc/oea/bat.h> | | 86 | #include <powerpc/oea/bat.h> |
87 | #include <powerpc/spr.h> | | 87 | #include <powerpc/spr.h> |
88 | #ifdef ALTIVEC | | 88 | #ifdef ALTIVEC |
89 | #include <powerpc/altivec.h> | | 89 | #include <powerpc/altivec.h> |
90 | #endif | | 90 | #endif |
91 | #include <powerpc/ofw_cons.h> | | 91 | #include <powerpc/ofw_cons.h> |
92 | | | 92 | |
93 | #include <powerpc/pic/picvar.h> | | 93 | #include <powerpc/pic/picvar.h> |
94 | #ifdef MULTIPROCESSOR | | 94 | #ifdef MULTIPROCESSOR |
95 | #include <powerpc/pic/ipivar.h> | | 95 | #include <powerpc/pic/ipivar.h> |
96 | #endif | | 96 | #endif |
97 | | | 97 | |
98 | #include <macppc/dev/adbvar.h> | | 98 | #include <macppc/dev/adbvar.h> |
99 | #include <macppc/dev/pmuvar.h> | | 99 | #include <macppc/dev/pmuvar.h> |
100 | #include <macppc/dev/cudavar.h> | | 100 | #include <macppc/dev/cudavar.h> |
101 | | | 101 | |
102 | #include <macppc/macppc/static_edid.h> | | 102 | #include <macppc/macppc/static_edid.h> |
103 | | | 103 | |
104 | #include "ksyms.h" | | 104 | #include "ksyms.h" |
105 | #include "pmu.h" | | 105 | #include "pmu.h" |
106 | #include "cuda.h" | | 106 | #include "cuda.h" |
107 | | | 107 | |
108 | struct genfb_colormap_callback gfb_cb; | | 108 | struct genfb_colormap_callback gfb_cb; |
109 | struct genfb_parameter_callback gpc_backlight, gpc_brightness; | | 109 | struct genfb_parameter_callback gpc_backlight, gpc_brightness; |
110 | | | 110 | |
111 | /* | | 111 | /* |
112 | * OpenFirmware gives us no way to check the brightness level or the backlight | | 112 | * OpenFirmware gives us no way to check the brightness level or the backlight |
113 | * state so we assume the backlight is on and about 4/5 up which seems | | 113 | * state so we assume the backlight is on and about 4/5 up which seems |
114 | * reasonable for most laptops | | 114 | * reasonable for most laptops |
115 | */ | | 115 | */ |
116 | int backlight_state = 1; | | 116 | int backlight_state = 1; |
117 | int brightness_level = 200; | | 117 | int brightness_level = 200; |
118 | | | 118 | |
119 | static void of_set_palette(void *, int, int, int, int); | | 119 | static void of_set_palette(void *, int, int, int, int); |
120 | static void add_model_specifics(prop_dictionary_t); | | 120 | static void add_model_specifics(prop_dictionary_t); |
121 | static int of_get_backlight(void *, int *); | | 121 | static int of_get_backlight(void *, int *); |
122 | static int of_set_backlight(void *, int); | | 122 | static int of_set_backlight(void *, int); |
123 | static int of_get_brightness(void *, int *); | | 123 | static int of_get_brightness(void *, int *); |
124 | static int of_set_brightness(void *, int); | | 124 | static int of_set_brightness(void *, int); |
125 | static int of_upd_brightness(void *, int); | | 125 | static int of_upd_brightness(void *, int); |
126 | | | 126 | |
127 | void | | 127 | void |
128 | initppc(u_int startkernel, u_int endkernel, char *args) | | 128 | initppc(u_int startkernel, u_int endkernel, char *args) |
129 | { | | 129 | { |
130 | ofwoea_initppc(startkernel, endkernel, args); | | 130 | ofwoea_initppc(startkernel, endkernel, args); |
131 | } | | 131 | } |
132 | | | 132 | |
133 | /* perform model-specific actions at initppc() */ | | 133 | /* perform model-specific actions at initppc() */ |
134 | void | | 134 | void |
135 | model_init(void) | | 135 | model_init(void) |
136 | { | | 136 | { |
137 | } | | 137 | } |
138 | | | 138 | |
139 | void | | 139 | void |
140 | consinit(void) | | 140 | consinit(void) |
141 | { | | 141 | { |
142 | ofwoea_consinit(); | | 142 | ofwoea_consinit(); |
143 | } | | 143 | } |
144 | | | 144 | |
145 | /* | | 145 | /* |
146 | * Machine dependent startup code. | | 146 | * Machine dependent startup code. |
147 | */ | | 147 | */ |
148 | void | | 148 | void |
149 | cpu_startup(void) | | 149 | cpu_startup(void) |
150 | { | | 150 | { |
151 | oea_startup(NULL); | | 151 | oea_startup(NULL); |
152 | } | | 152 | } |
153 | | | 153 | |
154 | /* | | 154 | /* |
155 | * Crash dump handling. | | 155 | * Crash dump handling. |
156 | */ | | 156 | */ |
157 | | | 157 | |
158 | void | | 158 | void |
159 | dumpsys(void) | | 159 | dumpsys(void) |
160 | { | | 160 | { |
161 | printf("dumpsys: TBD\n"); | | 161 | printf("dumpsys: TBD\n"); |
162 | } | | 162 | } |
163 | | | 163 | |
164 | /* | | 164 | /* |
165 | * Halt or reboot the machine after syncing/dumping according to howto. | | 165 | * Halt or reboot the machine after syncing/dumping according to howto. |
166 | */ | | 166 | */ |
167 | void | | 167 | void |
168 | cpu_reboot(int howto, char *what) | | 168 | cpu_reboot(int howto, char *what) |
169 | { | | 169 | { |
170 | static int syncing; | | 170 | static int syncing; |
171 | static char str[256]; | | 171 | static char str[256]; |
172 | char *ap = str, *ap1 = ap; | | 172 | char *ap = str, *ap1 = ap; |
173 | | | 173 | |
174 | /* | | 174 | /* |
175 | * Enable external interrupts in case someone is rebooting | | 175 | * Enable external interrupts in case someone is rebooting |
176 | * from a strange context via ddb. | | 176 | * from a strange context via ddb. |
177 | */ | | 177 | */ |
178 | mtmsr(mfmsr() | PSL_EE); | | 178 | mtmsr(mfmsr() | PSL_EE); |
179 | | | 179 | |
180 | boothowto = howto; | | 180 | boothowto = howto; |
181 | if (!cold && !(howto & RB_NOSYNC) && !syncing) { | | 181 | if (!cold && !(howto & RB_NOSYNC) && !syncing) { |
182 | syncing = 1; | | 182 | syncing = 1; |
183 | vfs_shutdown(); /* sync */ | | 183 | vfs_shutdown(); /* sync */ |
184 | resettodr(); /* set wall clock */ | | 184 | resettodr(); /* set wall clock */ |
185 | } | | 185 | } |
186 | | | 186 | |
187 | #ifdef MULTIPROCESSOR | | 187 | #ifdef MULTIPROCESSOR |
188 | /* Halt other CPU */ | | 188 | /* Halt other CPU */ |
189 | cpu_send_ipi(IPI_DST_NOTME, IPI_HALT); | | 189 | cpu_send_ipi(IPI_DST_NOTME, IPI_HALT); |
190 | delay(100000); /* XXX */ | | 190 | delay(100000); /* XXX */ |
191 | #endif | | 191 | #endif |
192 | | | 192 | |
193 | splhigh(); | | 193 | splhigh(); |
194 | | | 194 | |
195 | if (!cold && (howto & RB_DUMP)) | | 195 | if (!cold && (howto & RB_DUMP)) |
196 | dumpsys(); | | 196 | dumpsys(); |
197 | | | 197 | |
198 | doshutdownhooks(); | | 198 | doshutdownhooks(); |
199 | | | 199 | |
200 | pmf_system_shutdown(boothowto); | | 200 | pmf_system_shutdown(boothowto); |
201 | | | 201 | |
202 | if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { | | 202 | if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { |
203 | delay(1000000); | | 203 | delay(1000000); |
204 | #if NCUDA > 0 | | 204 | #if NCUDA > 0 |
205 | cuda_poweroff(); | | 205 | cuda_poweroff(); |
206 | #endif | | 206 | #endif |
207 | #if NPMU > 0 | | 207 | #if NPMU > 0 |
208 | pmu_poweroff(); | | 208 | pmu_poweroff(); |
209 | #endif | | 209 | #endif |
210 | #if NADB > 0 | | 210 | #if NADB > 0 |
211 | adb_poweroff(); | | 211 | adb_poweroff(); |
212 | printf("WARNING: powerdown failed!\n"); | | 212 | printf("WARNING: powerdown failed!\n"); |
213 | #endif | | 213 | #endif |
214 | } | | 214 | } |
215 | | | 215 | |
216 | if (howto & RB_HALT) { | | 216 | if (howto & RB_HALT) { |
217 | printf("halted\n\n"); | | 217 | printf("halted\n\n"); |
218 | | | 218 | |
219 | /* flush cache for msgbuf */ | | 219 | /* flush cache for msgbuf */ |
220 | __syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE)); | | 220 | __syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE)); |
221 | | | 221 | |
222 | ppc_exit(); | | 222 | ppc_exit(); |
223 | } | | 223 | } |
224 | | | 224 | |
225 | printf("rebooting\n\n"); | | 225 | printf("rebooting\n\n"); |
226 | if (what && *what) { | | 226 | if (what && *what) { |
227 | if (strlen(what) > sizeof str - 5) | | 227 | if (strlen(what) > sizeof str - 5) |
228 | printf("boot string too large, ignored\n"); | | 228 | printf("boot string too large, ignored\n"); |
229 | else { | | 229 | else { |
230 | strcpy(str, what); | | 230 | strcpy(str, what); |
231 | ap1 = ap = str + strlen(str); | | 231 | ap1 = ap = str + strlen(str); |
232 | *ap++ = ' '; | | 232 | *ap++ = ' '; |
233 | } | | 233 | } |
234 | } | | 234 | } |
235 | *ap++ = '-'; | | 235 | *ap++ = '-'; |
236 | if (howto & RB_SINGLE) | | 236 | if (howto & RB_SINGLE) |
237 | *ap++ = 's'; | | 237 | *ap++ = 's'; |
238 | if (howto & RB_KDB) | | 238 | if (howto & RB_KDB) |
239 | *ap++ = 'd'; | | 239 | *ap++ = 'd'; |
240 | *ap++ = 0; | | 240 | *ap++ = 0; |
241 | if (ap[-2] == '-') | | 241 | if (ap[-2] == '-') |
242 | *ap1 = 0; | | 242 | *ap1 = 0; |
243 | | | 243 | |
244 | /* flush cache for msgbuf */ | | 244 | /* flush cache for msgbuf */ |
245 | __syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE)); | | 245 | __syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE)); |
246 | | | 246 | |
247 | #if NCUDA > 0 | | 247 | #if NCUDA > 0 |
248 | cuda_restart(); | | 248 | cuda_restart(); |
249 | #endif | | 249 | #endif |
250 | #if NPMU > 0 | | 250 | #if NPMU > 0 |
251 | pmu_restart(); | | 251 | pmu_restart(); |
252 | #endif | | 252 | #endif |
253 | #if NADB > 0 | | 253 | #if NADB > 0 |
254 | adb_restart(); /* not return */ | | 254 | adb_restart(); /* not return */ |
255 | #endif | | 255 | #endif |
256 | ppc_exit(); | | 256 | ppc_exit(); |
257 | } | | 257 | } |
258 | | | 258 | |
259 | #if 0 | | 259 | #if 0 |
260 | /* | | 260 | /* |
261 | * OpenFirmware callback routine | | 261 | * OpenFirmware callback routine |
262 | */ | | 262 | */ |
263 | void | | 263 | void |
264 | callback(void *p) | | 264 | callback(void *p) |
265 | { | | 265 | { |
266 | panic("callback"); /* for now XXX */ | | 266 | panic("callback"); /* for now XXX */ |
267 | } | | 267 | } |
268 | #endif | | 268 | #endif |
269 | | | 269 | |
270 | void | | 270 | void |
271 | copy_disp_props(device_t dev, int node, prop_dictionary_t dict) | | 271 | copy_disp_props(device_t dev, int node, prop_dictionary_t dict) |
272 | { | | 272 | { |
273 | uint32_t temp; | | 273 | uint32_t temp; |
274 | uint64_t cmap_cb, backlight_cb, brightness_cb; | | 274 | uint64_t cmap_cb, backlight_cb, brightness_cb; |
275 | int have_backlight = 0; | | 275 | int have_backlight = 0; |
276 | | | 276 | |
277 | if (node != console_node) { | | 277 | if (node != console_node) { |
278 | /* | | 278 | /* |
279 | * see if any child matches since OF attaches nodes for | | 279 | * see if any child matches since OF attaches nodes for |
280 | * each head and /chosen/stdout points to the head | | 280 | * each head and /chosen/stdout points to the head |
281 | * rather than the device itself in this case | | 281 | * rather than the device itself in this case |
282 | */ | | 282 | */ |
283 | int sub; | | 283 | int sub; |
284 | | | 284 | |
285 | sub = OF_child(node); | | 285 | sub = OF_child(node); |
286 | while ((sub != 0) && (sub != console_node)) { | | 286 | while ((sub != 0) && (sub != console_node)) { |
287 | sub = OF_peer(sub); | | 287 | sub = OF_peer(sub); |
288 | } | | 288 | } |
289 | if (sub != console_node) | | 289 | if (sub != console_node) |
290 | return; | | 290 | return; |
291 | node = sub; | | 291 | node = sub; |
292 | } | | 292 | } |
293 | | | 293 | |
294 | prop_dictionary_set_bool(dict, "is_console", 1); | | 294 | prop_dictionary_set_bool(dict, "is_console", 1); |
295 | if (!of_to_uint32_prop(dict, node, "width", "width")) { | | 295 | if (!of_to_uint32_prop(dict, node, "width", "width")) { |
296 | | | 296 | |
297 | OF_interpret("screen-width", 0, 1, &temp); | | 297 | OF_interpret("screen-width", 0, 1, &temp); |
298 | prop_dictionary_set_uint32(dict, "width", temp); | | 298 | prop_dictionary_set_uint32(dict, "width", temp); |
299 | } | | 299 | } |
300 | if (!of_to_uint32_prop(dict, node, "height", "height")) { | | 300 | if (!of_to_uint32_prop(dict, node, "height", "height")) { |
301 | | | 301 | |
302 | OF_interpret("screen-height", 0, 1, &temp); | | 302 | OF_interpret("screen-height", 0, 1, &temp); |
303 | prop_dictionary_set_uint32(dict, "height", temp); | | 303 | prop_dictionary_set_uint32(dict, "height", temp); |
304 | } | | 304 | } |
305 | of_to_uint32_prop(dict, node, "linebytes", "linebytes"); | | 305 | of_to_uint32_prop(dict, node, "linebytes", "linebytes"); |
306 | if (!of_to_uint32_prop(dict, node, "depth", "depth")) { | | 306 | if (!of_to_uint32_prop(dict, node, "depth", "depth")) { |
307 | /* | | 307 | /* |
308 | * XXX we should check linebytes vs. width but those | | 308 | * XXX we should check linebytes vs. width but those |
309 | * FBs that don't have a depth property ( /chaos/control... ) | | 309 | * FBs that don't have a depth property ( /chaos/control... ) |
310 | * won't have linebytes either | | 310 | * won't have linebytes either |
311 | */ | | 311 | */ |
312 | prop_dictionary_set_uint32(dict, "depth", 8); | | 312 | prop_dictionary_set_uint32(dict, "depth", 8); |
313 | } | | 313 | } |
314 | if (!of_to_uint32_prop(dict, node, "address", "address")) { | | 314 | if (!of_to_uint32_prop(dict, node, "address", "address")) { |
315 | uint32_t fbaddr = 0; | | 315 | uint32_t fbaddr = 0; |
316 | OF_interpret("frame-buffer-adr", 0, 1, &fbaddr); | | 316 | OF_interpret("frame-buffer-adr", 0, 1, &fbaddr); |
317 | if (fbaddr != 0) | | 317 | if (fbaddr != 0) |
318 | prop_dictionary_set_uint32(dict, "address", fbaddr); | | 318 | prop_dictionary_set_uint32(dict, "address", fbaddr); |
319 | } | | 319 | } |
320 | of_to_dataprop(dict, node, "EDID", "EDID"); | | 320 | of_to_dataprop(dict, node, "EDID", "EDID"); |
321 | add_model_specifics(dict); | | 321 | add_model_specifics(dict); |
322 | | | 322 | |
323 | temp = 0; | | 323 | temp = 0; |
324 | if (OF_getprop(node, "ATY,RefCLK", &temp, sizeof(temp)) != 4) { | | 324 | if (OF_getprop(node, "ATY,RefCLK", &temp, sizeof(temp)) != 4) { |
325 | | | 325 | |
326 | OF_getprop(OF_parent(node), "ATY,RefCLK", &temp, | | 326 | OF_getprop(OF_parent(node), "ATY,RefCLK", &temp, |
327 | sizeof(temp)); | | 327 | sizeof(temp)); |
328 | } | | 328 | } |
329 | if (temp != 0) | | 329 | if (temp != 0) |
330 | prop_dictionary_set_uint32(dict, "refclk", temp / 10); | | 330 | prop_dictionary_set_uint32(dict, "refclk", temp / 10); |
331 | | | 331 | |
332 | gfb_cb.gcc_cookie = (void *)console_instance; | | 332 | gfb_cb.gcc_cookie = (void *)console_instance; |
333 | gfb_cb.gcc_set_mapreg = of_set_palette; | | 333 | gfb_cb.gcc_set_mapreg = of_set_palette; |
334 | cmap_cb = (uint64_t)(uintptr_t)&gfb_cb; | | 334 | cmap_cb = (uint64_t)(uintptr_t)&gfb_cb; |
335 | prop_dictionary_set_uint64(dict, "cmap_callback", cmap_cb); | | 335 | prop_dictionary_set_uint64(dict, "cmap_callback", cmap_cb); |
336 | | | 336 | |
337 | /* not let's look for backlight control */ | | 337 | /* not let's look for backlight control */ |
338 | have_backlight = 0; | | 338 | have_backlight = 0; |
339 | if (OF_getprop(node, "backlight-control", &temp, sizeof(temp)) == 4) { | | 339 | if (OF_getprop(node, "backlight-control", &temp, sizeof(temp)) == 4) { |
340 | have_backlight = 1; | | 340 | have_backlight = 1; |
341 | } else if (OF_getprop(OF_parent(node), "backlight-control", &temp, | | 341 | } else if (OF_getprop(OF_parent(node), "backlight-control", &temp, |
342 | sizeof(temp)) == 4) { | | 342 | sizeof(temp)) == 4) { |
343 | have_backlight = 1; | | 343 | have_backlight = 1; |
344 | } | | 344 | } |
345 | if (have_backlight) { | | 345 | if (have_backlight) { |
346 | gpc_backlight.gpc_cookie = (void *)console_instance; | | 346 | gpc_backlight.gpc_cookie = (void *)console_instance; |
347 | gpc_backlight.gpc_set_parameter = of_set_backlight; | | 347 | gpc_backlight.gpc_set_parameter = of_set_backlight; |
348 | gpc_backlight.gpc_get_parameter = of_get_backlight; | | 348 | gpc_backlight.gpc_get_parameter = of_get_backlight; |
349 | gpc_backlight.gpc_upd_parameter = NULL; | | 349 | gpc_backlight.gpc_upd_parameter = NULL; |
350 | backlight_cb = (uint64_t)&gpc_backlight; | | 350 | backlight_cb = (uint64_t)(uintptr_t)&gpc_backlight; |
351 | prop_dictionary_set_uint64(dict, "backlight_callback", | | 351 | prop_dictionary_set_uint64(dict, "backlight_callback", |
352 | backlight_cb); | | 352 | backlight_cb); |
353 | | | 353 | |
354 | gpc_brightness.gpc_cookie = (void *)console_instance; | | 354 | gpc_brightness.gpc_cookie = (void *)console_instance; |
355 | gpc_brightness.gpc_set_parameter = of_set_brightness; | | 355 | gpc_brightness.gpc_set_parameter = of_set_brightness; |
356 | gpc_brightness.gpc_get_parameter = of_get_brightness; | | 356 | gpc_brightness.gpc_get_parameter = of_get_brightness; |
357 | gpc_brightness.gpc_upd_parameter = of_upd_brightness; | | 357 | gpc_brightness.gpc_upd_parameter = of_upd_brightness; |
358 | brightness_cb = (uint64_t)&gpc_brightness; | | 358 | brightness_cb = (uint64_t)(uintptr_t)&gpc_brightness; |
359 | prop_dictionary_set_uint64(dict, "brightness_callback", | | 359 | prop_dictionary_set_uint64(dict, "brightness_callback", |
360 | brightness_cb); | | 360 | brightness_cb); |
361 | } | | 361 | } |
362 | } | | 362 | } |
363 | | | 363 | |
364 | static void | | 364 | static void |
365 | add_model_specifics(prop_dictionary_t dict) | | 365 | add_model_specifics(prop_dictionary_t dict) |
366 | { | | 366 | { |
367 | const char *bl_rev_models[] = { | | 367 | const char *bl_rev_models[] = { |
368 | "PowerBook4,3", "PowerBook6,3", "PowerBook6,5", NULL}; | | 368 | "PowerBook4,3", "PowerBook6,3", "PowerBook6,5", NULL}; |
369 | const char *pismo[] = { | | 369 | const char *pismo[] = { |
370 | "PowerBook3,1", NULL}; | | 370 | "PowerBook3,1", NULL}; |
371 | int node; | | 371 | int node; |
372 | | | 372 | |
373 | node = OF_finddevice("/"); | | 373 | node = OF_finddevice("/"); |
374 | | | 374 | |
375 | if (of_compatible(node, bl_rev_models) != -1) { | | 375 | if (of_compatible(node, bl_rev_models) != -1) { |
376 | prop_dictionary_set_bool(dict, "backlight_level_reverted", 1); | | 376 | prop_dictionary_set_bool(dict, "backlight_level_reverted", 1); |
377 | } | | 377 | } |
378 | if (of_compatible(node, pismo) != -1) { | | 378 | if (of_compatible(node, pismo) != -1) { |
379 | prop_data_t edid; | | 379 | prop_data_t edid; |
380 | | | 380 | |
381 | edid = prop_data_create_data(edid_pismo, sizeof(edid_pismo)); | | 381 | edid = prop_data_create_data(edid_pismo, sizeof(edid_pismo)); |
382 | prop_dictionary_set(dict, "EDID", edid); | | 382 | prop_dictionary_set(dict, "EDID", edid); |
383 | prop_object_release(edid); | | 383 | prop_object_release(edid); |
384 | } | | 384 | } |
385 | } | | 385 | } |
386 | | | 386 | |
387 | static void | | 387 | static void |
388 | of_set_palette(void *cookie, int index, int r, int g, int b) | | 388 | of_set_palette(void *cookie, int index, int r, int g, int b) |
389 | { | | 389 | { |
390 | int ih = (int)cookie; | | 390 | int ih = (int)cookie; |
391 | | | 391 | |
392 | OF_call_method_1("color!", ih, 4, r, g, b, index); | | 392 | OF_call_method_1("color!", ih, 4, r, g, b, index); |
393 | } | | 393 | } |
394 | | | 394 | |
395 | static int | | 395 | static int |
396 | of_get_backlight(void *cookie, int *state) | | 396 | of_get_backlight(void *cookie, int *state) |
397 | { | | 397 | { |
398 | if (backlight_state < 0) | | 398 | if (backlight_state < 0) |
399 | return ENODEV; | | 399 | return ENODEV; |
400 | *state = backlight_state; | | 400 | *state = backlight_state; |
401 | return 0; | | 401 | return 0; |
402 | } | | 402 | } |
403 | | | 403 | |
404 | static int | | 404 | static int |
405 | of_set_backlight(void *cookie, int state) | | 405 | of_set_backlight(void *cookie, int state) |
406 | { | | 406 | { |
407 | int ih = (int)cookie; | | 407 | int ih = (int)cookie; |
408 | | | 408 | |
409 | KASSERT(state >= 0 && state <= 1); | | 409 | KASSERT(state >= 0 && state <= 1); |
410 | | | 410 | |
411 | backlight_state = state; | | 411 | backlight_state = state; |
412 | if (state) | | 412 | if (state) |
413 | OF_call_method_1("backlight-on", ih, 0); | | 413 | OF_call_method_1("backlight-on", ih, 0); |
414 | else | | 414 | else |
415 | OF_call_method_1("backlight-off", ih, 0); | | 415 | OF_call_method_1("backlight-off", ih, 0); |
416 | | | 416 | |
417 | return 0; /* XXX or use return value of OF_call_method_1? */ | | 417 | return 0; /* XXX or use return value of OF_call_method_1? */ |
418 | } | | 418 | } |
419 | | | 419 | |
420 | static int | | 420 | static int |
421 | of_get_brightness(void *cookie, int *level) | | 421 | of_get_brightness(void *cookie, int *level) |
422 | { | | 422 | { |
423 | /* | | 423 | /* |
424 | * We don't know how to read the brightness level from OF alone - we | | 424 | * We don't know how to read the brightness level from OF alone - we |
425 | * should read the value from the PMU. Here, we just return whatever | | 425 | * should read the value from the PMU. Here, we just return whatever |
426 | * we set last (if any). | | 426 | * we set last (if any). |
427 | */ | | 427 | */ |
428 | if (brightness_level < 0) | | 428 | if (brightness_level < 0) |
429 | return ENODEV; | | 429 | return ENODEV; |
430 | *level = brightness_level; | | 430 | *level = brightness_level; |
431 | return 0; | | 431 | return 0; |
432 | } | | 432 | } |
433 | | | 433 | |
434 | static int | | 434 | static int |
435 | of_set_brightness(void *cookie, int level) | | 435 | of_set_brightness(void *cookie, int level) |
436 | { | | 436 | { |
437 | int ih = (int)cookie; | | 437 | int ih = (int)cookie; |
438 | | | 438 | |
439 | KASSERT(level >= 0 && level <= 255); | | 439 | KASSERT(level >= 0 && level <= 255); |
440 | | | 440 | |
441 | brightness_level = level; | | 441 | brightness_level = level; |
442 | OF_call_method_1("set-contrast", ih, 1, brightness_level); | | 442 | OF_call_method_1("set-contrast", ih, 1, brightness_level); |
443 | | | 443 | |
444 | return 0; /* XXX or use return value of OF_call_method_1? */ | | 444 | return 0; /* XXX or use return value of OF_call_method_1? */ |
445 | } | | 445 | } |
446 | | | 446 | |
447 | static int | | 447 | static int |
448 | of_upd_brightness(void *cookie, int delta) | | 448 | of_upd_brightness(void *cookie, int delta) |
449 | { | | 449 | { |
450 | int ih = (int)cookie; | | 450 | int ih = (int)cookie; |
451 | | | 451 | |
452 | if (brightness_level < 0) | | 452 | if (brightness_level < 0) |
453 | return ENODEV; | | 453 | return ENODEV; |
454 | | | 454 | |
455 | brightness_level += delta; | | 455 | brightness_level += delta; |
456 | if (brightness_level < 0) brightness_level = 0; | | 456 | if (brightness_level < 0) brightness_level = 0; |
457 | if (brightness_level > 255) brightness_level = 255; | | 457 | if (brightness_level > 255) brightness_level = 255; |
458 | OF_call_method_1("set-contrast", ih, 1, brightness_level); | | 458 | OF_call_method_1("set-contrast", ih, 1, brightness_level); |
459 | | | 459 | |
460 | return 0; /* XXX or use return value of OF_call_method_1? */ | | 460 | return 0; /* XXX or use return value of OF_call_method_1? */ |
461 | } | | 461 | } |