aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/btext.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/btext.c')
-rw-r--r--arch/powerpc/kernel/btext.c130
1 files changed, 93 insertions, 37 deletions
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
index bdfba92b2b38..893dd24a9f67 100644
--- a/arch/powerpc/kernel/btext.c
+++ b/arch/powerpc/kernel/btext.c
@@ -31,15 +31,18 @@ static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb);
31static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb); 31static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb);
32static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb); 32static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb);
33 33
34static int g_loc_X; 34#define __force_data __attribute__((__section__(".data")))
35static int g_loc_Y;
36static int g_max_loc_X;
37static int g_max_loc_Y;
38 35
39static int dispDeviceRowBytes; 36static int g_loc_X __force_data;
40static int dispDeviceDepth; 37static int g_loc_Y __force_data;
41static int dispDeviceRect[4]; 38static int g_max_loc_X __force_data;
42static unsigned char *dispDeviceBase, *logicalDisplayBase; 39static int g_max_loc_Y __force_data;
40
41static int dispDeviceRowBytes __force_data;
42static int dispDeviceDepth __force_data;
43static int dispDeviceRect[4] __force_data;
44static unsigned char *dispDeviceBase __force_data;
45static unsigned char *logicalDisplayBase __force_data;
43 46
44unsigned long disp_BAT[2] __initdata = {0, 0}; 47unsigned long disp_BAT[2] __initdata = {0, 0};
45 48
@@ -47,7 +50,7 @@ unsigned long disp_BAT[2] __initdata = {0, 0};
47 50
48static unsigned char vga_font[cmapsz]; 51static unsigned char vga_font[cmapsz];
49 52
50int boot_text_mapped; 53int boot_text_mapped __force_data = 0;
51int force_printk_to_btext = 0; 54int force_printk_to_btext = 0;
52 55
53#ifdef CONFIG_PPC32 56#ifdef CONFIG_PPC32
@@ -66,8 +69,7 @@ int force_printk_to_btext = 0;
66 * is really badly aligned, but I didn't encounter this case 69 * is really badly aligned, but I didn't encounter this case
67 * yet. 70 * yet.
68 */ 71 */
69void __init 72void __init btext_prepare_BAT(void)
70btext_prepare_BAT(void)
71{ 73{
72 unsigned long vaddr = KERNELBASE + 0x10000000; 74 unsigned long vaddr = KERNELBASE + 0x10000000;
73 unsigned long addr; 75 unsigned long addr;
@@ -95,12 +97,13 @@ btext_prepare_BAT(void)
95} 97}
96#endif 98#endif
97 99
98/* This function will enable the early boot text when doing OF booting. This 100
99 * way, xmon output should work too 101/* This function can be used to enable the early boot text when doing
102 * OF booting or within bootx init. It must be followed by a btext_unmap()
103 * call before the logical address becomes unuseable
100 */ 104 */
101void __init 105void __init btext_setup_display(int width, int height, int depth, int pitch,
102btext_setup_display(int width, int height, int depth, int pitch, 106 unsigned long address)
103 unsigned long address)
104{ 107{
105 g_loc_X = 0; 108 g_loc_X = 0;
106 g_loc_Y = 0; 109 g_loc_Y = 0;
@@ -116,6 +119,11 @@ btext_setup_display(int width, int height, int depth, int pitch,
116 boot_text_mapped = 1; 119 boot_text_mapped = 1;
117} 120}
118 121
122void __init btext_unmap(void)
123{
124 boot_text_mapped = 0;
125}
126
119/* Here's a small text engine to use during early boot 127/* Here's a small text engine to use during early boot
120 * or for debugging purposes 128 * or for debugging purposes
121 * 129 *
@@ -127,7 +135,7 @@ btext_setup_display(int width, int height, int depth, int pitch,
127 * changes. 135 * changes.
128 */ 136 */
129 137
130void map_boot_text(void) 138static void map_boot_text(void)
131{ 139{
132 unsigned long base, offset, size; 140 unsigned long base, offset, size;
133 unsigned char *vbase; 141 unsigned char *vbase;
@@ -175,8 +183,9 @@ int btext_initialize(struct device_node *np)
175 if (prop) 183 if (prop)
176 address = *prop; 184 address = *prop;
177 185
178 /* FIXME: Add support for PCI reg properties */ 186 /* FIXME: Add support for PCI reg properties. Right now, only
179 187 * reliable on macs
188 */
180 if (address == 0) 189 if (address == 0)
181 return -EINVAL; 190 return -EINVAL;
182 191
@@ -184,7 +193,6 @@ int btext_initialize(struct device_node *np)
184 g_loc_Y = 0; 193 g_loc_Y = 0;
185 g_max_loc_X = width / 8; 194 g_max_loc_X = width / 8;
186 g_max_loc_Y = height / 16; 195 g_max_loc_Y = height / 16;
187 logicalDisplayBase = (unsigned char *)address;
188 dispDeviceBase = (unsigned char *)address; 196 dispDeviceBase = (unsigned char *)address;
189 dispDeviceRowBytes = pitch; 197 dispDeviceRowBytes = pitch;
190 dispDeviceDepth = depth; 198 dispDeviceDepth = depth;
@@ -197,7 +205,7 @@ int btext_initialize(struct device_node *np)
197 return 0; 205 return 0;
198} 206}
199 207
200void __init init_boot_display(void) 208int __init btext_find_display(int allow_nonstdout)
201{ 209{
202 char *name; 210 char *name;
203 struct device_node *np = NULL; 211 struct device_node *np = NULL;
@@ -218,8 +226,8 @@ void __init init_boot_display(void)
218 } 226 }
219 if (np) 227 if (np)
220 rc = btext_initialize(np); 228 rc = btext_initialize(np);
221 if (rc == 0) 229 if (rc == 0 || !allow_nonstdout)
222 return; 230 return rc;
223 231
224 for (np = NULL; (np = of_find_node_by_type(np, "display"));) { 232 for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
225 if (get_property(np, "linux,opened", NULL)) { 233 if (get_property(np, "linux,opened", NULL)) {
@@ -228,8 +236,9 @@ void __init init_boot_display(void)
228 printk("result: %d\n", rc); 236 printk("result: %d\n", rc);
229 } 237 }
230 if (rc == 0) 238 if (rc == 0)
231 return; 239 break;
232 } 240 }
241 return rc;
233} 242}
234 243
235/* Calc the base address of a given point (x,y) */ 244/* Calc the base address of a given point (x,y) */
@@ -277,44 +286,83 @@ EXPORT_SYMBOL(btext_update_display);
277 286
278void btext_clearscreen(void) 287void btext_clearscreen(void)
279{ 288{
280 unsigned long *base = (unsigned long *)calc_base(0, 0); 289 unsigned int *base = (unsigned int *)calc_base(0, 0);
281 unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * 290 unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
282 (dispDeviceDepth >> 3)) >> 3; 291 (dispDeviceDepth >> 3)) >> 2;
283 int i,j; 292 int i,j;
284 293
285 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++) 294 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++)
286 { 295 {
287 unsigned long *ptr = base; 296 unsigned int *ptr = base;
288 for(j=width; j; --j) 297 for(j=width; j; --j)
289 *(ptr++) = 0; 298 *(ptr++) = 0;
290 base += (dispDeviceRowBytes >> 3); 299 base += (dispDeviceRowBytes >> 2);
300 }
301}
302
303void btext_flushscreen(void)
304{
305 unsigned int *base = (unsigned int *)calc_base(0, 0);
306 unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
307 (dispDeviceDepth >> 3)) >> 2;
308 int i,j;
309
310 for (i=0; i < (dispDeviceRect[3] - dispDeviceRect[1]); i++)
311 {
312 unsigned int *ptr = base;
313 for(j = width; j > 0; j -= 8) {
314 __asm__ __volatile__ ("dcbst 0,%0" :: "r" (ptr));
315 ptr += 8;
316 }
317 base += (dispDeviceRowBytes >> 2);
291 } 318 }
319 __asm__ __volatile__ ("sync" ::: "memory");
292} 320}
293 321
322void btext_flushline(void)
323{
324 unsigned int *base = (unsigned int *)calc_base(0, g_loc_Y << 4);
325 unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
326 (dispDeviceDepth >> 3)) >> 2;
327 int i,j;
328
329 for (i=0; i < 16; i++)
330 {
331 unsigned int *ptr = base;
332 for(j = width; j > 0; j -= 8) {
333 __asm__ __volatile__ ("dcbst 0,%0" :: "r" (ptr));
334 ptr += 8;
335 }
336 base += (dispDeviceRowBytes >> 2);
337 }
338 __asm__ __volatile__ ("sync" ::: "memory");
339}
340
341
294#ifndef NO_SCROLL 342#ifndef NO_SCROLL
295static void scrollscreen(void) 343static void scrollscreen(void)
296{ 344{
297 unsigned long *src = (unsigned long *)calc_base(0,16); 345 unsigned int *src = (unsigned int *)calc_base(0,16);
298 unsigned long *dst = (unsigned long *)calc_base(0,0); 346 unsigned int *dst = (unsigned int *)calc_base(0,0);
299 unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * 347 unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
300 (dispDeviceDepth >> 3)) >> 3; 348 (dispDeviceDepth >> 3)) >> 2;
301 int i,j; 349 int i,j;
302 350
303 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++) 351 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++)
304 { 352 {
305 unsigned long *src_ptr = src; 353 unsigned int *src_ptr = src;
306 unsigned long *dst_ptr = dst; 354 unsigned int *dst_ptr = dst;
307 for(j=width; j; --j) 355 for(j=width; j; --j)
308 *(dst_ptr++) = *(src_ptr++); 356 *(dst_ptr++) = *(src_ptr++);
309 src += (dispDeviceRowBytes >> 3); 357 src += (dispDeviceRowBytes >> 2);
310 dst += (dispDeviceRowBytes >> 3); 358 dst += (dispDeviceRowBytes >> 2);
311 } 359 }
312 for (i=0; i<16; i++) 360 for (i=0; i<16; i++)
313 { 361 {
314 unsigned long *dst_ptr = dst; 362 unsigned int *dst_ptr = dst;
315 for(j=width; j; --j) 363 for(j=width; j; --j)
316 *(dst_ptr++) = 0; 364 *(dst_ptr++) = 0;
317 dst += (dispDeviceRowBytes >> 3); 365 dst += (dispDeviceRowBytes >> 2);
318 } 366 }
319} 367}
320#endif /* ndef NO_SCROLL */ 368#endif /* ndef NO_SCROLL */
@@ -377,6 +425,14 @@ void btext_drawstring(const char *c)
377 btext_drawchar(*c++); 425 btext_drawchar(*c++);
378} 426}
379 427
428void btext_drawtext(const char *c, unsigned int len)
429{
430 if (!boot_text_mapped)
431 return;
432 while (len--)
433 btext_drawchar(*c++);
434}
435
380void btext_drawhex(unsigned long v) 436void btext_drawhex(unsigned long v)
381{ 437{
382 char *hex_table = "0123456789abcdef"; 438 char *hex_table = "0123456789abcdef";