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 ---