2 * Procedures for drawing on the screen early on in the boot process.
4 * Benjamin Herrenschmidt <benh@kernel.crashing.org>
6 * move to coreboot by LYH yhlu@tyan.com
16 #include <console/console.h>
17 #include <device/device.h>
18 #include <device/pci.h>
19 #include <device/pci_ids.h>
20 #include <device/pci_ops.h>
26 #include <console/console.h>
29 #include <arch/byteorder.h>
31 #include <console/btext.h>
36 static void scrollscreen(void);
39 static void draw_byte(unsigned char c
, u32 locX
, u32 locY
);
41 static void draw_byte_32(unsigned char *bits
, u32
*base
, u32 rb
);
42 static void draw_byte_16(unsigned char *bits
, u32
*base
, u32 rb
);
44 static void draw_byte_8(unsigned char *bits
, u32
*base
, u32 rb
);
48 static u32 g_max_loc_X
;
49 static u32 g_max_loc_Y
;
54 #define cmapsz (16*256)
56 #define cmapsz (16*96)
59 extern unsigned char vga_font
[cmapsz
];
69 /* This function will enable the early boot text when doing OF booting. This
70 * way, xmon output should work too
73 btext_setup_display(u32 width
, u32 height
, u32 depth
, u32 pitch
,
74 unsigned long address
)
76 boot_infos_t
* bi
= &disp_bi
;
80 g_max_loc_X
= width
/ 8;
81 g_max_loc_Y
= height
/ 16;
82 // bi->logicalDisplayBase = (unsigned char *)address;
83 bi
->dispDeviceBase
= (unsigned char *)address
;
84 bi
->dispDeviceRowBytes
= pitch
;
85 bi
->dispDeviceDepth
= depth
;
86 bi
->dispDeviceRect
[0] = bi
->dispDeviceRect
[1] = 0;
87 bi
->dispDeviceRect
[2] = width
;
88 bi
->dispDeviceRect
[3] = height
;
92 /* Here's a small text engine to use during early boot
93 * or for debugging purposes
97 * - build some kind of vgacon with it to enable early printk
98 * - move to a separate file
99 * - add a few video driver hooks to keep in sync with display
107 unsigned long base
, offset
, size
;
108 boot_infos_t
*bi
= &disp_bi
;
110 if (bi
->dispDeviceBase
== 0)
112 base
= ((unsigned long) bi
->dispDeviceBase
) & 0xFFFFF000UL
;
113 offset
= ((unsigned long) bi
->dispDeviceBase
) - base
;
114 size
= bi
->dispDeviceRowBytes
* bi
->dispDeviceRect
[3] + offset
115 + bi
->dispDeviceRect
[0];
116 bi
->logicalDisplayBase
= ioremap(base
,0x800000 );
117 if (bi
->logicalDisplayBase
== 0)
119 // bi->logicalDisplayBase += offset;
121 boot_text_mapped
= 1;
124 /* Calc the base address of a given point (x,y) */
125 static unsigned char * BTEXT
126 calc_base(boot_infos_t
*bi
, u32 x
, u32 y
)
130 base
= bi
->logicalDisplayBase
;
133 base
= bi
->dispDeviceBase
;
134 base
+= (x
+ bi
->dispDeviceRect
[0]) * (bi
->dispDeviceDepth
>> 3);
135 base
+= (y
+ bi
->dispDeviceRect
[1]) * bi
->dispDeviceRowBytes
;
139 /* Adjust the display to a new resolution */
141 btext_update_display(unsigned long phys
, u32 width
, u32 height
,
142 u32 depth
, u32 pitch
)
144 boot_infos_t
*bi
= &disp_bi
;
146 if (bi
->dispDeviceBase
== 0)
148 /* check it's the same frame buffer (within 256MB) */
149 if ((phys
^ (unsigned long)bi
->dispDeviceBase
) & 0xf0000000)
153 bi
->dispDeviceBase
= (u8
*) phys
;
154 bi
->dispDeviceRect
[0] = 0;
155 bi
->dispDeviceRect
[1] = 0;
156 bi
->dispDeviceRect
[2] = width
;
157 bi
->dispDeviceRect
[3] = height
;
158 bi
->dispDeviceDepth
= depth
;
159 bi
->dispDeviceRowBytes
= pitch
;
160 if (boot_text_mapped
) {
162 iounmap(bi
->logicalDisplayBase
);
164 boot_text_mapped
= 0;
169 g_max_loc_X
= width
/ 8;
170 g_max_loc_Y
= height
/ 16;
173 void BTEXT
btext_clearscreen(void)
175 boot_infos_t
* bi
= &disp_bi
;
176 u32
*base
= (u32
*)calc_base(bi
, 0, 0);
177 u32 width
= ((bi
->dispDeviceRect
[2] - bi
->dispDeviceRect
[0]) *
178 (bi
->dispDeviceDepth
>> 3)) >> 2;
181 for (i
=0; i
<(bi
->dispDeviceRect
[3] - bi
->dispDeviceRect
[1]); i
++)
186 base
+= (bi
->dispDeviceRowBytes
>> 2);
191 __inline__
void dcbst(const void* addr
)
193 __asm__
__volatile__ ("dcbst 0,%0" :: "r" (addr
));
196 void BTEXT
btext_flushscreen(void)
198 boot_infos_t
* bi
= &disp_bi
;
199 u32
*base
= (unsigned long *)calc_base(bi
, 0, 0);
200 u32 width
= ((bi
->dispDeviceRect
[2] - bi
->dispDeviceRect
[0]) *
201 (bi
->dispDeviceDepth
>> 3)) >> 2;
204 for (i
=0; i
<(bi
->dispDeviceRect
[3] - bi
->dispDeviceRect
[1]); i
++)
207 for(j
=width
; j
>0; j
-=8) {
211 base
+= (bi
->dispDeviceRowBytes
>> 2);
221 boot_infos_t
* bi
= &disp_bi
;
222 u32
*src
= (u32
*)calc_base(bi
,0,16);
223 u32
*dst
= (u32
*)calc_base(bi
,0,0);
224 u32 width
= ((bi
->dispDeviceRect
[2] - bi
->dispDeviceRect
[0]) *
225 (bi
->dispDeviceDepth
>> 3)) >> 2;
228 for (i
=0; i
<(bi
->dispDeviceRect
[3] - bi
->dispDeviceRect
[1] - 16); i
++)
233 *(dst_ptr
++) = *(src_ptr
++);
234 src
+= (bi
->dispDeviceRowBytes
>> 2);
235 dst
+= (bi
->dispDeviceRowBytes
>> 2);
242 dst
+= (bi
->dispDeviceRowBytes
>> 2);
245 #endif /* ndef NO_SCROLL */
247 void BTEXT
btext_drawchar(char c
)
251 if (!boot_text_mapped
)
260 g_loc_X
= (g_loc_X
& -8) + 8;
271 draw_byte(c
, g_loc_X
++, g_loc_Y
);
273 if (g_loc_X
>= g_max_loc_X
) {
279 while (g_loc_Y
>= g_max_loc_Y
) {
284 /* wrap around from bottom to top of screen so we don't
285 waste time scrolling each line. -- paulus. */
286 if (g_loc_Y
>= g_max_loc_Y
)
289 for (x
= 0; x
< g_max_loc_X
; ++x
)
290 draw_byte(' ', x
, g_loc_Y
);
296 btext_drawstring(const char *c
)
298 if (!boot_text_mapped
)
301 btext_drawchar(*c
++);
307 static char hex_table
[] = "0123456789abcdef";
309 if (!boot_text_mapped
)
311 btext_drawchar(hex_table
[(v
>> 28) & 0x0000000FUL
]);
312 btext_drawchar(hex_table
[(v
>> 24) & 0x0000000FUL
]);
313 btext_drawchar(hex_table
[(v
>> 20) & 0x0000000FUL
]);
314 btext_drawchar(hex_table
[(v
>> 16) & 0x0000000FUL
]);
315 btext_drawchar(hex_table
[(v
>> 12) & 0x0000000FUL
]);
316 btext_drawchar(hex_table
[(v
>> 8) & 0x0000000FUL
]);
317 btext_drawchar(hex_table
[(v
>> 4) & 0x0000000FUL
]);
318 btext_drawchar(hex_table
[(v
>> 0) & 0x0000000FUL
]);
323 draw_byte(unsigned char c
, u32 locX
, u32 locY
)
325 boot_infos_t
* bi
= &disp_bi
;
326 unsigned char *base
= calc_base(bi
, locX
<< 3, locY
<< 4);
328 unsigned char *font
= &vga_font
[((u32
)c
) * 16];
330 unsigned char *font
= &vga_font
[((u32
)c
-0x20) * 16]; // skip the first 0x20
332 u32 rb
= bi
->dispDeviceRowBytes
;
334 switch(bi
->dispDeviceDepth
) {
338 draw_byte_32(font
, (u32
*)base
, rb
);
342 draw_byte_16(font
, (u32
*)base
, rb
);
346 draw_byte_8(font
, (u32
*)base
, rb
);
350 static u32 expand_bits_8
[16] BTDATA
= {
351 #if defined(__BIG_ENDIAN)
352 0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
353 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
354 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
355 0xffff0000,0xffff00ff,0xffffff00,0xffffffff
356 #elif defined(__LITTLE_ENDIAN)
357 0x00000000,0xff000000,0x00ff0000,0xffff0000,
358 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
359 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
360 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
362 #error FIXME: No endianness??
366 static const u32 expand_bits_16
[4] BTDATA
= {
367 #if defined(__BIG_ENDIAN)
368 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
369 #elif defined(__LITTLE_ENDIAN)
370 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
372 #error FIXME: No endianness??
378 draw_byte_32(unsigned char *font
, u32
*base
, u32 rb
)
384 for (l
= 0; l
< 16; ++l
)
387 base
[0] = (-(bits
>> 7) & fg
) ^ bg
;
388 base
[1] = (-((bits
>> 6) & 1) & fg
) ^ bg
;
389 base
[2] = (-((bits
>> 5) & 1) & fg
) ^ bg
;
390 base
[3] = (-((bits
>> 4) & 1) & fg
) ^ bg
;
391 base
[4] = (-((bits
>> 3) & 1) & fg
) ^ bg
;
392 base
[5] = (-((bits
>> 2) & 1) & fg
) ^ bg
;
393 base
[6] = (-((bits
>> 1) & 1) & fg
) ^ bg
;
394 base
[7] = (-(bits
& 1) & fg
) ^ bg
;
395 base
= (u32
*) ((char *)base
+ rb
);
400 draw_byte_16(unsigned char *font
, u32
*base
, u32 rb
)
405 u32
*eb
= expand_bits_16
;
407 for (l
= 0; l
< 16; ++l
)
410 base
[0] = (eb
[bits
>> 6] & fg
) ^ bg
;
411 base
[1] = (eb
[(bits
>> 4) & 3] & fg
) ^ bg
;
412 base
[2] = (eb
[(bits
>> 2) & 3] & fg
) ^ bg
;
413 base
[3] = (eb
[bits
& 3] & fg
) ^ bg
;
414 base
= (u32
*) ((char *)base
+ rb
);
419 draw_byte_8(unsigned char *font
, u32
*base
, u32 rb
)
424 u32
*eb
= expand_bits_8
;
426 for (l
= 0; l
< 16; ++l
)
429 base
[0] = (eb
[bits
>> 4] & fg
) ^ bg
;
430 base
[1] = (eb
[bits
& 0xf] & fg
) ^ bg
;
431 base
= (u32
*) ((char *)base
+ rb
);
435 void btext_init(void)
437 btext_setup_display(640, 480, 8, 640,0xfc000000);
439 // It will be init in xlinit.c because We only can access fb after the device resource is allocated and enabled.
443 void btext_tx_byte(unsigned char data
)
445 btext_drawchar(data
);
448 static const struct console_driver btext_console __console
= {
450 .tx_byte
= btext_tx_byte
,