Since some people disapprove of white space cleanups mixed in regular commits
[coreboot.git] / src / console / btext_console.c
1 /*
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 coreboot 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
31 #include <console/btext.h>
32
33 //#define NO_SCROLL
34
35 #ifndef NO_SCROLL
36 static void scrollscreen(void);
37 #endif
38
39 static void draw_byte(unsigned char c, u32 locX, u32 locY);
40 #if 0
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);
43 #endif
44 static void draw_byte_8(unsigned char *bits, u32 *base, u32 rb);
45
46 static u32 g_loc_X;
47 static u32 g_loc_Y;
48 static u32 g_max_loc_X;
49 static u32 g_max_loc_Y;
50
51 #define CHAR_256 0
52
53 #if CHAR_256==1
54 #define cmapsz  (16*256)
55 #else
56 #define cmapsz        (16*96)
57 #endif
58
59 extern unsigned char vga_font[cmapsz];
60
61 u32 boot_text_mapped;
62
63 boot_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  */
72 void
73 btext_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
103 void
104 map_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) */
125 static unsigned char * BTEXT
126 calc_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 */
140 void
141 btext_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
173 void 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
196 void 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
218 static BTEXT void
219 scrollscreen(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
247 void 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 }
294 #if 0
295 void BTEXT
296 btext_drawstring(const char *c)
297 {
298         if (!boot_text_mapped)
299                 return;
300         while (*c)
301                 btext_drawchar(*c++);
302 }
303
304 void BTEXT
305 btext_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 }
321 #endif
322 static void BTEXT
323 draw_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);
327 #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
332         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 }
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
361 #else
362 #error FIXME: No endianness??
363 #endif
364 };
365 #if 0
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
371 #else
372 #error FIXME: No endianness??
373 #endif
374 };
375 #endif
376 #if 0
377 static void BTEXT
378 draw_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
399 static void BTEXT
400 draw_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
418 static void BTEXT
419 draw_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
435 void 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
443 void btext_tx_byte(unsigned char data)
444 {
445         btext_drawchar(data);
446 }
447
448 static const 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