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.c136
1 files changed, 95 insertions, 41 deletions
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
index bdfba92b2b38..6223d39177cb 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
@@ -57,7 +60,7 @@ int force_printk_to_btext = 0;
57 * 60 *
58 * The display is mapped to virtual address 0xD0000000, rather 61 * The display is mapped to virtual address 0xD0000000, rather
59 * than 1:1, because some some CHRP machines put the frame buffer 62 * than 1:1, because some some CHRP machines put the frame buffer
60 * in the region starting at 0xC0000000 (KERNELBASE). 63 * in the region starting at 0xC0000000 (PAGE_OFFSET).
61 * This mapping is temporary and will disappear as soon as the 64 * This mapping is temporary and will disappear as soon as the
62 * setup done by MMU_Init() is applied. 65 * setup done by MMU_Init() is applied.
63 * 66 *
@@ -66,10 +69,9 @@ 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 = PAGE_OFFSET + 0x10000000;
73 unsigned long addr; 75 unsigned long addr;
74 unsigned long lowbits; 76 unsigned long lowbits;
75 77
@@ -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,14 +205,12 @@ 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;
204 int rc = -ENODEV; 212 int rc = -ENODEV;
205 213
206 printk("trying to initialize btext ...\n");
207
208 name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); 214 name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
209 if (name != NULL) { 215 if (name != NULL) {
210 np = of_find_node_by_path(name); 216 np = of_find_node_by_path(name);
@@ -218,8 +224,8 @@ void __init init_boot_display(void)
218 } 224 }
219 if (np) 225 if (np)
220 rc = btext_initialize(np); 226 rc = btext_initialize(np);
221 if (rc == 0) 227 if (rc == 0 || !allow_nonstdout)
222 return; 228 return rc;
223 229
224 for (np = NULL; (np = of_find_node_by_type(np, "display"));) { 230 for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
225 if (get_property(np, "linux,opened", NULL)) { 231 if (get_property(np, "linux,opened", NULL)) {
@@ -228,8 +234,9 @@ void __init init_boot_display(void)
228 printk("result: %d\n", rc); 234 printk("result: %d\n", rc);
229 } 235 }
230 if (rc == 0) 236 if (rc == 0)
231 return; 237 break;
232 } 238 }
239 return rc;
233} 240}
234 241
235/* Calc the base address of a given point (x,y) */ 242/* Calc the base address of a given point (x,y) */
@@ -277,44 +284,83 @@ EXPORT_SYMBOL(btext_update_display);
277 284
278void btext_clearscreen(void) 285void btext_clearscreen(void)
279{ 286{
280 unsigned long *base = (unsigned long *)calc_base(0, 0); 287 unsigned int *base = (unsigned int *)calc_base(0, 0);
281 unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * 288 unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
282 (dispDeviceDepth >> 3)) >> 3; 289 (dispDeviceDepth >> 3)) >> 2;
283 int i,j; 290 int i,j;
284 291
285 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++) 292 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++)
286 { 293 {
287 unsigned long *ptr = base; 294 unsigned int *ptr = base;
288 for(j=width; j; --j) 295 for(j=width; j; --j)
289 *(ptr++) = 0; 296 *(ptr++) = 0;
290 base += (dispDeviceRowBytes >> 3); 297 base += (dispDeviceRowBytes >> 2);
291 } 298 }
292} 299}
293 300
301void btext_flushscreen(void)
302{
303 unsigned int *base = (unsigned int *)calc_base(0, 0);
304 unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
305 (dispDeviceDepth >> 3)) >> 2;
306 int i,j;
307
308 for (i=0; i < (dispDeviceRect[3] - dispDeviceRect[1]); i++)
309 {
310 unsigned int *ptr = base;
311 for(j = width; j > 0; j -= 8) {
312 __asm__ __volatile__ ("dcbst 0,%0" :: "r" (ptr));
313 ptr += 8;
314 }
315 base += (dispDeviceRowBytes >> 2);
316 }
317 __asm__ __volatile__ ("sync" ::: "memory");
318}
319
320void btext_flushline(void)
321{
322 unsigned int *base = (unsigned int *)calc_base(0, g_loc_Y << 4);
323 unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
324 (dispDeviceDepth >> 3)) >> 2;
325 int i,j;
326
327 for (i=0; i < 16; i++)
328 {
329 unsigned int *ptr = base;
330 for(j = width; j > 0; j -= 8) {
331 __asm__ __volatile__ ("dcbst 0,%0" :: "r" (ptr));
332 ptr += 8;
333 }
334 base += (dispDeviceRowBytes >> 2);
335 }
336 __asm__ __volatile__ ("sync" ::: "memory");
337}
338
339
294#ifndef NO_SCROLL 340#ifndef NO_SCROLL
295static void scrollscreen(void) 341static void scrollscreen(void)
296{ 342{
297 unsigned long *src = (unsigned long *)calc_base(0,16); 343 unsigned int *src = (unsigned int *)calc_base(0,16);
298 unsigned long *dst = (unsigned long *)calc_base(0,0); 344 unsigned int *dst = (unsigned int *)calc_base(0,0);
299 unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * 345 unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
300 (dispDeviceDepth >> 3)) >> 3; 346 (dispDeviceDepth >> 3)) >> 2;
301 int i,j; 347 int i,j;
302 348
303 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++) 349 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++)
304 { 350 {
305 unsigned long *src_ptr = src; 351 unsigned int *src_ptr = src;
306 unsigned long *dst_ptr = dst; 352 unsigned int *dst_ptr = dst;
307 for(j=width; j; --j) 353 for(j=width; j; --j)
308 *(dst_ptr++) = *(src_ptr++); 354 *(dst_ptr++) = *(src_ptr++);
309 src += (dispDeviceRowBytes >> 3); 355 src += (dispDeviceRowBytes >> 2);
310 dst += (dispDeviceRowBytes >> 3); 356 dst += (dispDeviceRowBytes >> 2);
311 } 357 }
312 for (i=0; i<16; i++) 358 for (i=0; i<16; i++)
313 { 359 {
314 unsigned long *dst_ptr = dst; 360 unsigned int *dst_ptr = dst;
315 for(j=width; j; --j) 361 for(j=width; j; --j)
316 *(dst_ptr++) = 0; 362 *(dst_ptr++) = 0;
317 dst += (dispDeviceRowBytes >> 3); 363 dst += (dispDeviceRowBytes >> 2);
318 } 364 }
319} 365}
320#endif /* ndef NO_SCROLL */ 366#endif /* ndef NO_SCROLL */
@@ -377,6 +423,14 @@ void btext_drawstring(const char *c)
377 btext_drawchar(*c++); 423 btext_drawchar(*c++);
378} 424}
379 425
426void btext_drawtext(const char *c, unsigned int len)
427{
428 if (!boot_text_mapped)
429 return;
430 while (len--)
431 btext_drawchar(*c++);
432}
433
380void btext_drawhex(unsigned long v) 434void btext_drawhex(unsigned long v)
381{ 435{
382 char *hex_table = "0123456789abcdef"; 436 char *hex_table = "0123456789abcdef";