btext.c (3d5271f9883cba7b54762bc4fe027d4172f06db7) | btext.c (51d3082fe6e55aecfa17113dbe98077c749f724c) |
---|---|
1/* 2 * Procedures for drawing on the screen early on in the boot process. 3 * 4 * Benjamin Herrenschmidt <benh@kernel.crashing.org> 5 */ 6#include <linux/config.h> 7#include <linux/kernel.h> 8#include <linux/string.h> --- 17 unchanged lines hidden (view full) --- 26static void scrollscreen(void); 27#endif 28 29static void draw_byte(unsigned char c, long locX, long locY); 30static 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); 32static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb); 33 | 1/* 2 * Procedures for drawing on the screen early on in the boot process. 3 * 4 * Benjamin Herrenschmidt <benh@kernel.crashing.org> 5 */ 6#include <linux/config.h> 7#include <linux/kernel.h> 8#include <linux/string.h> --- 17 unchanged lines hidden (view full) --- 26static void scrollscreen(void); 27#endif 28 29static void draw_byte(unsigned char c, long locX, long locY); 30static 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); 32static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb); 33 |
34static int g_loc_X; 35static int g_loc_Y; 36static int g_max_loc_X; 37static int g_max_loc_Y; | 34#define __force_data __attribute__((__section__(".data"))) |
38 | 35 |
39static int dispDeviceRowBytes; 40static int dispDeviceDepth; 41static int dispDeviceRect[4]; 42static unsigned char *dispDeviceBase, *logicalDisplayBase; | 36static int g_loc_X __force_data; 37static int g_loc_Y __force_data; 38static int g_max_loc_X __force_data; 39static int g_max_loc_Y __force_data; |
43 | 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; 46 |
|
44unsigned long disp_BAT[2] __initdata = {0, 0}; 45 46#define cmapsz (16*256) 47 48static unsigned char vga_font[cmapsz]; 49 | 47unsigned long disp_BAT[2] __initdata = {0, 0}; 48 49#define cmapsz (16*256) 50 51static unsigned char vga_font[cmapsz]; 52 |
50int boot_text_mapped; | 53int boot_text_mapped __force_data = 0; |
51int force_printk_to_btext = 0; 52 53#ifdef CONFIG_PPC32 54/* Calc BAT values for mapping the display and store them 55 * in disp_BAT. Those values are then used from head.S to map 56 * the display during identify_machine() and MMU_Init() 57 * 58 * The display is mapped to virtual address 0xD0000000, rather 59 * than 1:1, because some some CHRP machines put the frame buffer 60 * in the region starting at 0xC0000000 (KERNELBASE). 61 * This mapping is temporary and will disappear as soon as the 62 * setup done by MMU_Init() is applied. 63 * 64 * For now, we align the BAT and then map 8Mb on 601 and 16Mb 65 * on other PPCs. This may cause trouble if the framebuffer 66 * is really badly aligned, but I didn't encounter this case 67 * yet. 68 */ | 54int force_printk_to_btext = 0; 55 56#ifdef CONFIG_PPC32 57/* Calc BAT values for mapping the display and store them 58 * in disp_BAT. Those values are then used from head.S to map 59 * the display during identify_machine() and MMU_Init() 60 * 61 * The display is mapped to virtual address 0xD0000000, rather 62 * than 1:1, because some some CHRP machines put the frame buffer 63 * in the region starting at 0xC0000000 (KERNELBASE). 64 * This mapping is temporary and will disappear as soon as the 65 * setup done by MMU_Init() is applied. 66 * 67 * For now, we align the BAT and then map 8Mb on 601 and 16Mb 68 * on other PPCs. This may cause trouble if the framebuffer 69 * is really badly aligned, but I didn't encounter this case 70 * yet. 71 */ |
69void __init 70btext_prepare_BAT(void) | 72void __init btext_prepare_BAT(void) |
71{ 72 unsigned long vaddr = KERNELBASE + 0x10000000; 73 unsigned long addr; 74 unsigned long lowbits; 75 76 addr = (unsigned long)dispDeviceBase; 77 if (!addr) { 78 boot_text_mapped = 0; --- 11 unchanged lines hidden (view full) --- 90 addr &= 0xFF800000UL; 91 disp_BAT[0] = vaddr | (_PAGE_NO_CACHE | PP_RWXX) | 4; 92 disp_BAT[1] = addr | BL_8M | 0x40; 93 } 94 logicalDisplayBase = (void *) (vaddr + lowbits); 95} 96#endif 97 | 73{ 74 unsigned long vaddr = KERNELBASE + 0x10000000; 75 unsigned long addr; 76 unsigned long lowbits; 77 78 addr = (unsigned long)dispDeviceBase; 79 if (!addr) { 80 boot_text_mapped = 0; --- 11 unchanged lines hidden (view full) --- 92 addr &= 0xFF800000UL; 93 disp_BAT[0] = vaddr | (_PAGE_NO_CACHE | PP_RWXX) | 4; 94 disp_BAT[1] = addr | BL_8M | 0x40; 95 } 96 logicalDisplayBase = (void *) (vaddr + lowbits); 97} 98#endif 99 |
98/* This function will enable the early boot text when doing OF booting. This 99 * way, xmon output should work too | 100 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 102btext_setup_display(int width, int height, int depth, int pitch, 103 unsigned long address) | 105void __init btext_setup_display(int width, int height, int depth, int pitch, 106 unsigned long address) |
104{ 105 g_loc_X = 0; 106 g_loc_Y = 0; 107 g_max_loc_X = width / 8; 108 g_max_loc_Y = height / 16; 109 logicalDisplayBase = (unsigned char *)address; 110 dispDeviceBase = (unsigned char *)address; 111 dispDeviceRowBytes = pitch; 112 dispDeviceDepth = depth; 113 dispDeviceRect[0] = dispDeviceRect[1] = 0; 114 dispDeviceRect[2] = width; 115 dispDeviceRect[3] = height; 116 boot_text_mapped = 1; 117} 118 | 107{ 108 g_loc_X = 0; 109 g_loc_Y = 0; 110 g_max_loc_X = width / 8; 111 g_max_loc_Y = height / 16; 112 logicalDisplayBase = (unsigned char *)address; 113 dispDeviceBase = (unsigned char *)address; 114 dispDeviceRowBytes = pitch; 115 dispDeviceDepth = depth; 116 dispDeviceRect[0] = dispDeviceRect[1] = 0; 117 dispDeviceRect[2] = width; 118 dispDeviceRect[3] = height; 119 boot_text_mapped = 1; 120} 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 120 * or for debugging purposes 121 * 122 * todo: 123 * 124 * - build some kind of vgacon with it to enable early printk 125 * - move to a separate file 126 * - add a few video driver hooks to keep in sync with display 127 * changes. 128 */ 129 | 127/* Here's a small text engine to use during early boot 128 * or for debugging purposes 129 * 130 * todo: 131 * 132 * - build some kind of vgacon with it to enable early printk 133 * - move to a separate file 134 * - add a few video driver hooks to keep in sync with display 135 * changes. 136 */ 137 |
130void map_boot_text(void) | 138static void map_boot_text(void) |
131{ 132 unsigned long base, offset, size; 133 unsigned char *vbase; 134 135 /* By default, we are no longer mapped */ 136 boot_text_mapped = 0; 137 if (dispDeviceBase == 0) 138 return; --- 31 unchanged lines hidden (view full) --- 170 if (prop) 171 pitch = *prop; 172 if (pitch == 1) 173 pitch = 0x1000; 174 prop = (u32 *)get_property(np, "address", NULL); 175 if (prop) 176 address = *prop; 177 | 139{ 140 unsigned long base, offset, size; 141 unsigned char *vbase; 142 143 /* By default, we are no longer mapped */ 144 boot_text_mapped = 0; 145 if (dispDeviceBase == 0) 146 return; --- 31 unchanged lines hidden (view full) --- 178 if (prop) 179 pitch = *prop; 180 if (pitch == 1) 181 pitch = 0x1000; 182 prop = (u32 *)get_property(np, "address", NULL); 183 if (prop) 184 address = *prop; 185 |
178 /* FIXME: Add support for PCI reg properties */ 179 | 186 /* FIXME: Add support for PCI reg properties. Right now, only 187 * reliable on macs 188 */ |
180 if (address == 0) 181 return -EINVAL; 182 183 g_loc_X = 0; 184 g_loc_Y = 0; 185 g_max_loc_X = width / 8; 186 g_max_loc_Y = height / 16; | 189 if (address == 0) 190 return -EINVAL; 191 192 g_loc_X = 0; 193 g_loc_Y = 0; 194 g_max_loc_X = width / 8; 195 g_max_loc_Y = height / 16; |
187 logicalDisplayBase = (unsigned char *)address; | |
188 dispDeviceBase = (unsigned char *)address; 189 dispDeviceRowBytes = pitch; 190 dispDeviceDepth = depth; 191 dispDeviceRect[0] = dispDeviceRect[1] = 0; 192 dispDeviceRect[2] = width; 193 dispDeviceRect[3] = height; 194 195 map_boot_text(); 196 197 return 0; 198} 199 | 196 dispDeviceBase = (unsigned char *)address; 197 dispDeviceRowBytes = pitch; 198 dispDeviceDepth = depth; 199 dispDeviceRect[0] = dispDeviceRect[1] = 0; 200 dispDeviceRect[2] = width; 201 dispDeviceRect[3] = height; 202 203 map_boot_text(); 204 205 return 0; 206} 207 |
200void __init init_boot_display(void) | 208int __init btext_find_display(int allow_nonstdout) |
201{ 202 char *name; 203 struct device_node *np = NULL; 204 int rc = -ENODEV; 205 206 printk("trying to initialize btext ...\n"); 207 208 name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); --- 4 unchanged lines hidden (view full) --- 213 printk("boot stdout isn't a display !\n"); 214 of_node_put(np); 215 np = NULL; 216 } 217 } 218 } 219 if (np) 220 rc = btext_initialize(np); | 209{ 210 char *name; 211 struct device_node *np = NULL; 212 int rc = -ENODEV; 213 214 printk("trying to initialize btext ...\n"); 215 216 name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); --- 4 unchanged lines hidden (view full) --- 221 printk("boot stdout isn't a display !\n"); 222 of_node_put(np); 223 np = NULL; 224 } 225 } 226 } 227 if (np) 228 rc = btext_initialize(np); |
221 if (rc == 0) 222 return; | 229 if (rc == 0 || !allow_nonstdout) 230 return rc; |
223 224 for (np = NULL; (np = of_find_node_by_type(np, "display"));) { 225 if (get_property(np, "linux,opened", NULL)) { 226 printk("trying %s ...\n", np->full_name); 227 rc = btext_initialize(np); 228 printk("result: %d\n", rc); 229 } 230 if (rc == 0) | 231 232 for (np = NULL; (np = of_find_node_by_type(np, "display"));) { 233 if (get_property(np, "linux,opened", NULL)) { 234 printk("trying %s ...\n", np->full_name); 235 rc = btext_initialize(np); 236 printk("result: %d\n", rc); 237 } 238 if (rc == 0) |
231 return; | 239 break; |
232 } | 240 } |
241 return rc; |
|
233} 234 235/* Calc the base address of a given point (x,y) */ 236static unsigned char * calc_base(int x, int y) 237{ 238 unsigned char *base; 239 240 base = logicalDisplayBase; --- 31 unchanged lines hidden (view full) --- 272 g_loc_Y = 0; 273 g_max_loc_X = width / 8; 274 g_max_loc_Y = height / 16; 275} 276EXPORT_SYMBOL(btext_update_display); 277 278void btext_clearscreen(void) 279{ | 242} 243 244/* Calc the base address of a given point (x,y) */ 245static unsigned char * calc_base(int x, int y) 246{ 247 unsigned char *base; 248 249 base = logicalDisplayBase; --- 31 unchanged lines hidden (view full) --- 281 g_loc_Y = 0; 282 g_max_loc_X = width / 8; 283 g_max_loc_Y = height / 16; 284} 285EXPORT_SYMBOL(btext_update_display); 286 287void btext_clearscreen(void) 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; 284 285 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++) 286 { | 292 int i,j; 293 294 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++) 295 { |
287 unsigned long *ptr = base; | 296 unsigned int *ptr = base; |
288 for(j=width; j; --j) 289 *(ptr++) = 0; | 297 for(j=width; j; --j) 298 *(ptr++) = 0; |
290 base += (dispDeviceRowBytes >> 3); | 299 base += (dispDeviceRowBytes >> 2); |
291 } 292} 293 | 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); 318 } 319 __asm__ __volatile__ ("sync" ::: "memory"); 320} 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 295static void scrollscreen(void) 296{ | 342#ifndef NO_SCROLL 343static void scrollscreen(void) 344{ |
297 unsigned long *src = (unsigned long *)calc_base(0,16); 298 unsigned long *dst = (unsigned long *)calc_base(0,0); | 345 unsigned int *src = (unsigned int *)calc_base(0,16); 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; 302 303 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++) 304 { | 349 int i,j; 350 351 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++) 352 { |
305 unsigned long *src_ptr = src; 306 unsigned long *dst_ptr = dst; | 353 unsigned int *src_ptr = src; 354 unsigned int *dst_ptr = dst; |
307 for(j=width; j; --j) 308 *(dst_ptr++) = *(src_ptr++); | 355 for(j=width; j; --j) 356 *(dst_ptr++) = *(src_ptr++); |
309 src += (dispDeviceRowBytes >> 3); 310 dst += (dispDeviceRowBytes >> 3); | 357 src += (dispDeviceRowBytes >> 2); 358 dst += (dispDeviceRowBytes >> 2); |
311 } 312 for (i=0; i<16; i++) 313 { | 359 } 360 for (i=0; i<16; i++) 361 { |
314 unsigned long *dst_ptr = dst; | 362 unsigned int *dst_ptr = dst; |
315 for(j=width; j; --j) 316 *(dst_ptr++) = 0; | 363 for(j=width; j; --j) 364 *(dst_ptr++) = 0; |
317 dst += (dispDeviceRowBytes >> 3); | 365 dst += (dispDeviceRowBytes >> 2); |
318 } 319} 320#endif /* ndef NO_SCROLL */ 321 322void btext_drawchar(char c) 323{ 324 int cline = 0; 325#ifdef NO_SCROLL --- 46 unchanged lines hidden (view full) --- 372void btext_drawstring(const char *c) 373{ 374 if (!boot_text_mapped) 375 return; 376 while (*c) 377 btext_drawchar(*c++); 378} 379 | 366 } 367} 368#endif /* ndef NO_SCROLL */ 369 370void btext_drawchar(char c) 371{ 372 int cline = 0; 373#ifdef NO_SCROLL --- 46 unchanged lines hidden (view full) --- 420void btext_drawstring(const char *c) 421{ 422 if (!boot_text_mapped) 423 return; 424 while (*c) 425 btext_drawchar(*c++); 426} 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) 381{ 382 char *hex_table = "0123456789abcdef"; 383 384 if (!boot_text_mapped) 385 return; 386#ifdef CONFIG_PPC64 387 btext_drawchar(hex_table[(v >> 60) & 0x0000000FUL]); --- 466 unchanged lines hidden --- | 436void btext_drawhex(unsigned long v) 437{ 438 char *hex_table = "0123456789abcdef"; 439 440 if (!boot_text_mapped) 441 return; 442#ifdef CONFIG_PPC64 443 btext_drawchar(hex_table[(v >> 60) & 0x0000000FUL]); --- 466 unchanged lines hidden --- |