blob: ae8dc8ca10ba6d12fe5da288ec9dbac8fd92ee26 [file] [log] [blame]
Stefan Reinauerf05dcb82004-04-24 22:29:44 +00001/*
2 * Procedures for drawing on the screen early on in the boot process.
3 *
4 * Benjamin Herrenschmidt <benh@kernel.crashing.org>
5 *
6 * move to LinuxBIOS by LYH yhlu@tyan.com
7 */
8
9#if 0
10
11#include <delay.h>
12#include <stdlib.h>
13#include <string.h>
14#include <arch/io.h>
15
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>
21
22#endif
23
24#include <arch/io.h>
25#include <string.h>
26#include <console/console.h>
27
28
29#include <arch/byteorder.h>
30
Stefan Reinauer234454d2004-04-24 23:10:51 +000031#include <console/btext.h>
Stefan Reinauerf05dcb82004-04-24 22:29:44 +000032
33//#define NO_SCROLL
34
35#ifndef NO_SCROLL
36static void scrollscreen(void);
37#endif
38
39static void draw_byte(unsigned char c, u32 locX, u32 locY);
40#if 0
41static void draw_byte_32(unsigned char *bits, u32 *base, u32 rb);
42static void draw_byte_16(unsigned char *bits, u32 *base, u32 rb);
43#endif
44static void draw_byte_8(unsigned char *bits, u32 *base, u32 rb);
45
46static u32 g_loc_X;
47static u32 g_loc_Y;
48static u32 g_max_loc_X;
49static u32 g_max_loc_Y;
50
Yinghai Lu97c49472004-04-28 05:37:36 +000051#define CHAR_256 0
52
53#if CHAR_256==1
Stefan Reinauerf05dcb82004-04-24 22:29:44 +000054#define cmapsz (16*256)
Yinghai Lu97c49472004-04-28 05:37:36 +000055#else
56#define cmapsz (16*96)
57#endif
Stefan Reinauerf05dcb82004-04-24 22:29:44 +000058
Yinghai Lu97099082004-12-16 02:44:25 +000059extern unsigned char vga_font[cmapsz];
Stefan Reinauerf05dcb82004-04-24 22:29:44 +000060
61u32 boot_text_mapped;
62
63boot_infos_t disp_bi;
64
65#define BTEXT
66#define BTDATA
67
68
69/* This function will enable the early boot text when doing OF booting. This
70 * way, xmon output should work too
71 */
72void
73btext_setup_display(u32 width, u32 height, u32 depth, u32 pitch,
74 unsigned long address)
75{
76 boot_infos_t* bi = &disp_bi;
77
78 g_loc_X = 0;
79 g_loc_Y = 0;
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;
89 boot_text_mapped = 0;
90}
91
92/* Here's a small text engine to use during early boot
93 * or for debugging purposes
94 *
95 * todo:
96 *
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
100 * changes.
101 */
102
103void
104map_boot_text(void)
105{
106#if 0
107 unsigned long base, offset, size;
108 boot_infos_t *bi = &disp_bi;
109
110 if (bi->dispDeviceBase == 0)
111 return;
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)
118 return;
119// bi->logicalDisplayBase += offset;
120#endif
121 boot_text_mapped = 1;
122}
123
124/* Calc the base address of a given point (x,y) */
125static unsigned char * BTEXT
126calc_base(boot_infos_t *bi, u32 x, u32 y)
127{
128 unsigned char *base;
129#if 0
130 base = bi->logicalDisplayBase;
131 if (base == 0)
132#endif
133 base = bi->dispDeviceBase;
134 base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3);
135 base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes;
136 return base;
137}
138
139/* Adjust the display to a new resolution */
140void
141btext_update_display(unsigned long phys, u32 width, u32 height,
142 u32 depth, u32 pitch)
143{
144 boot_infos_t *bi = &disp_bi;
145#if 0
146 if (bi->dispDeviceBase == 0)
147 return;
148 /* check it's the same frame buffer (within 256MB) */
149 if ((phys ^ (unsigned long)bi->dispDeviceBase) & 0xf0000000)
150 return;
151#endif
152
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) {
161#if 0
162 iounmap(bi->logicalDisplayBase);
163#endif
164 boot_text_mapped = 0;
165 }
166 map_boot_text();
167 g_loc_X = 0;
168 g_loc_Y = 0;
169 g_max_loc_X = width / 8;
170 g_max_loc_Y = height / 16;
171}
172
173void BTEXT btext_clearscreen(void)
174{
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;
179 u32 i,j;
180
181 for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++)
182 {
183 u32 *ptr = base;
184 for(j=width; j; --j)
185 *(ptr++) = 0;
186 base += (bi->dispDeviceRowBytes >> 2);
187 }
188}
189
190#if 0
191__inline__ void dcbst(const void* addr)
192{
193 __asm__ __volatile__ ("dcbst 0,%0" :: "r" (addr));
194}
195
196void BTEXT btext_flushscreen(void)
197{
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;
202 u32 i,j;
203
204 for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++)
205 {
206 u32 *ptr = base;
207 for(j=width; j>0; j-=8) {
208 dcbst(ptr);
209 ptr += 8;
210 }
211 base += (bi->dispDeviceRowBytes >> 2);
212 }
213}
214#endif
215
216
217#ifndef NO_SCROLL
218static BTEXT void
219scrollscreen(void)
220{
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;
226 u32 i,j;
227
228 for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++)
229 {
230 u32 *src_ptr = src;
231 u32 *dst_ptr = dst;
232 for(j=width; j; --j)
233 *(dst_ptr++) = *(src_ptr++);
234 src += (bi->dispDeviceRowBytes >> 2);
235 dst += (bi->dispDeviceRowBytes >> 2);
236 }
237 for (i=0; i<16; i++)
238 {
239 u32 *dst_ptr = dst;
240 for(j=width; j; --j)
241 *(dst_ptr++) = 0;
242 dst += (bi->dispDeviceRowBytes >> 2);
243 }
244}
245#endif /* ndef NO_SCROLL */
246
247void BTEXT btext_drawchar(char c)
248{
249 u32 cline = 0;
250
251 if (!boot_text_mapped)
252 return;
253
254 switch (c) {
255 case '\b':
256 if (g_loc_X > 0)
257 --g_loc_X;
258 break;
259 case '\t':
260 g_loc_X = (g_loc_X & -8) + 8;
261 break;
262 case '\r':
263 g_loc_X = 0;
264 break;
265 case '\n':
266 g_loc_X = 0;
267 g_loc_Y++;
268 cline = 1;
269 break;
270 default:
271 draw_byte(c, g_loc_X++, g_loc_Y);
272 }
273 if (g_loc_X >= g_max_loc_X) {
274 g_loc_X = 0;
275 g_loc_Y++;
276 cline = 1;
277 }
278#ifndef NO_SCROLL
279 while (g_loc_Y >= g_max_loc_Y) {
280 scrollscreen();
281 g_loc_Y--;
282 }
283#else
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)
287 g_loc_Y = 0;
288 if (cline) {
289 for (x = 0; x < g_max_loc_X; ++x)
290 draw_byte(' ', x, g_loc_Y);
291 }
292#endif
293}
Yinghai Lu97c49472004-04-28 05:37:36 +0000294#if 0
Stefan Reinauerf05dcb82004-04-24 22:29:44 +0000295void BTEXT
296btext_drawstring(const char *c)
297{
298 if (!boot_text_mapped)
299 return;
300 while (*c)
301 btext_drawchar(*c++);
302}
303
304void BTEXT
305btext_drawhex(u32 v)
306{
307 static char hex_table[] = "0123456789abcdef";
308
309 if (!boot_text_mapped)
310 return;
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]);
319 btext_drawchar(' ');
320}
Yinghai Lu97c49472004-04-28 05:37:36 +0000321#endif
Stefan Reinauerf05dcb82004-04-24 22:29:44 +0000322static void BTEXT
323draw_byte(unsigned char c, u32 locX, u32 locY)
324{
325 boot_infos_t* bi = &disp_bi;
326 unsigned char *base = calc_base(bi, locX << 3, locY << 4);
Yinghai Lu97c49472004-04-28 05:37:36 +0000327#if CHAR_256==1
328 unsigned char *font = &vga_font[((u32)c) * 16];
329#else
330 unsigned char *font = &vga_font[((u32)c-0x20) * 16]; // skip the first 0x20
331#endif
Stefan Reinauerf05dcb82004-04-24 22:29:44 +0000332 u32 rb = bi->dispDeviceRowBytes;
333
334 switch(bi->dispDeviceDepth) {
335#if 0
336 case 24:
337 case 32:
338 draw_byte_32(font, (u32 *)base, rb);
339 break;
340 case 15:
341 case 16:
342 draw_byte_16(font, (u32 *)base, rb);
343 break;
344#endif
345 case 8:
346 draw_byte_8(font, (u32 *)base, rb);
347 break;
348 }
349}
350static 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
361#else
362#error FIXME: No endianness??
363#endif
364};
365#if 0
366static 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
371#else
372#error FIXME: No endianness??
373#endif
374};
375#endif
376#if 0
377static void BTEXT
378draw_byte_32(unsigned char *font, u32 *base, u32 rb)
379{
380 u32 l, bits;
381 u32 fg = 0xFFFFFFFF;
382 u32 bg = 0x00000000;
383
384 for (l = 0; l < 16; ++l)
385 {
386 bits = *font++;
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);
396 }
397}
398
399static void BTEXT
400draw_byte_16(unsigned char *font, u32 *base, u32 rb)
401{
402 u32 l, bits;
403 u32 fg = 0xFFFFFFFF;
404 u32 bg = 0x00000000;
405 u32 *eb = expand_bits_16;
406
407 for (l = 0; l < 16; ++l)
408 {
409 bits = *font++;
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);
415 }
416}
417#endif
418static void BTEXT
419draw_byte_8(unsigned char *font, u32 *base, u32 rb)
420{
421 u32 l, bits;
422 u32 fg = 0x0F0F0F0F;
423 u32 bg = 0x00000000;
424 u32 *eb = expand_bits_8;
425
426 for (l = 0; l < 16; ++l)
427 {
428 bits = *font++;
429 base[0] = (eb[bits >> 4] & fg) ^ bg;
430 base[1] = (eb[bits & 0xf] & fg) ^ bg;
431 base = (u32 *) ((char *)base + rb);
432 }
433}
434
435void btext_init(void)
436{
437 btext_setup_display(640, 480, 8, 640,0xfc000000);
438// Not realy init
439// It will be init in xlinit.c because We only can access fb after the device resource is allocated and enabled.
440
441}
442
443void btext_tx_byte(unsigned char data)
444{
445 btext_drawchar(data);
446}
447
448static struct console_driver btext_console __console = {
449 .init = btext_init,
450 .tx_byte = btext_tx_byte,
451 .rx_byte = 0,
452 .tst_byte = 0,
453};
454