Files
OpenCellular/src/console/btext_console.c
Stefan Reinauer 14e2277962 Since some people disapprove of white space cleanups mixed in regular commits
while others dislike them being extra commits, let's clean them up once and
for all for the existing code. If it's ugly, let it only be ugly once :-)

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Acked-by: Stefan Reinauer <stepan@coresystems.de>



git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5507 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
2010-04-27 06:56:47 +00:00

455 lines
9.8 KiB
C

/*
* Procedures for drawing on the screen early on in the boot process.
*
* Benjamin Herrenschmidt <benh@kernel.crashing.org>
*
* move to coreboot by LYH yhlu@tyan.com
*/
#if 0
#include <delay.h>
#include <stdlib.h>
#include <string.h>
#include <arch/io.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#endif
#include <arch/io.h>
#include <string.h>
#include <console/console.h>
#include <arch/byteorder.h>
#include <console/btext.h>
//#define NO_SCROLL
#ifndef NO_SCROLL
static void scrollscreen(void);
#endif
static void draw_byte(unsigned char c, u32 locX, u32 locY);
#if 0
static void draw_byte_32(unsigned char *bits, u32 *base, u32 rb);
static void draw_byte_16(unsigned char *bits, u32 *base, u32 rb);
#endif
static void draw_byte_8(unsigned char *bits, u32 *base, u32 rb);
static u32 g_loc_X;
static u32 g_loc_Y;
static u32 g_max_loc_X;
static u32 g_max_loc_Y;
#define CHAR_256 0
#if CHAR_256==1
#define cmapsz (16*256)
#else
#define cmapsz (16*96)
#endif
extern unsigned char vga_font[cmapsz];
u32 boot_text_mapped;
boot_infos_t disp_bi;
#define BTEXT
#define BTDATA
/* This function will enable the early boot text when doing OF booting. This
* way, xmon output should work too
*/
void
btext_setup_display(u32 width, u32 height, u32 depth, u32 pitch,
unsigned long address)
{
boot_infos_t* bi = &disp_bi;
g_loc_X = 0;
g_loc_Y = 0;
g_max_loc_X = width / 8;
g_max_loc_Y = height / 16;
// bi->logicalDisplayBase = (unsigned char *)address;
bi->dispDeviceBase = (unsigned char *)address;
bi->dispDeviceRowBytes = pitch;
bi->dispDeviceDepth = depth;
bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;
bi->dispDeviceRect[2] = width;
bi->dispDeviceRect[3] = height;
boot_text_mapped = 0;
}
/* Here's a small text engine to use during early boot
* or for debugging purposes
*
* todo:
*
* - build some kind of vgacon with it to enable early printk
* - move to a separate file
* - add a few video driver hooks to keep in sync with display
* changes.
*/
void
map_boot_text(void)
{
#if 0
unsigned long base, offset, size;
boot_infos_t *bi = &disp_bi;
if (bi->dispDeviceBase == 0)
return;
base = ((unsigned long) bi->dispDeviceBase) & 0xFFFFF000UL;
offset = ((unsigned long) bi->dispDeviceBase) - base;
size = bi->dispDeviceRowBytes * bi->dispDeviceRect[3] + offset
+ bi->dispDeviceRect[0];
bi->logicalDisplayBase = ioremap(base,0x800000 );
if (bi->logicalDisplayBase == 0)
return;
// bi->logicalDisplayBase += offset;
#endif
boot_text_mapped = 1;
}
/* Calc the base address of a given point (x,y) */
static unsigned char * BTEXT
calc_base(boot_infos_t *bi, u32 x, u32 y)
{
unsigned char *base;
#if 0
base = bi->logicalDisplayBase;
if (base == 0)
#endif
base = bi->dispDeviceBase;
base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3);
base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes;
return base;
}
/* Adjust the display to a new resolution */
void
btext_update_display(unsigned long phys, u32 width, u32 height,
u32 depth, u32 pitch)
{
boot_infos_t *bi = &disp_bi;
#if 0
if (bi->dispDeviceBase == 0)
return;
/* check it's the same frame buffer (within 256MB) */
if ((phys ^ (unsigned long)bi->dispDeviceBase) & 0xf0000000)
return;
#endif
bi->dispDeviceBase = (u8 *) phys;
bi->dispDeviceRect[0] = 0;
bi->dispDeviceRect[1] = 0;
bi->dispDeviceRect[2] = width;
bi->dispDeviceRect[3] = height;
bi->dispDeviceDepth = depth;
bi->dispDeviceRowBytes = pitch;
if (boot_text_mapped) {
#if 0
iounmap(bi->logicalDisplayBase);
#endif
boot_text_mapped = 0;
}
map_boot_text();
g_loc_X = 0;
g_loc_Y = 0;
g_max_loc_X = width / 8;
g_max_loc_Y = height / 16;
}
void BTEXT btext_clearscreen(void)
{
boot_infos_t* bi = &disp_bi;
u32 *base = (u32 *)calc_base(bi, 0, 0);
u32 width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
(bi->dispDeviceDepth >> 3)) >> 2;
u32 i,j;
for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++)
{
u32 *ptr = base;
for(j=width; j; --j)
*(ptr++) = 0;
base += (bi->dispDeviceRowBytes >> 2);
}
}
#if 0
__inline__ void dcbst(const void* addr)
{
__asm__ __volatile__ ("dcbst 0,%0" :: "r" (addr));
}
void BTEXT btext_flushscreen(void)
{
boot_infos_t* bi = &disp_bi;
u32 *base = (unsigned long *)calc_base(bi, 0, 0);
u32 width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
(bi->dispDeviceDepth >> 3)) >> 2;
u32 i,j;
for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++)
{
u32 *ptr = base;
for(j=width; j>0; j-=8) {
dcbst(ptr);
ptr += 8;
}
base += (bi->dispDeviceRowBytes >> 2);
}
}
#endif
#ifndef NO_SCROLL
static BTEXT void
scrollscreen(void)
{
boot_infos_t* bi = &disp_bi;
u32 *src = (u32 *)calc_base(bi,0,16);
u32 *dst = (u32 *)calc_base(bi,0,0);
u32 width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
(bi->dispDeviceDepth >> 3)) >> 2;
u32 i,j;
for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++)
{
u32 *src_ptr = src;
u32 *dst_ptr = dst;
for(j=width; j; --j)
*(dst_ptr++) = *(src_ptr++);
src += (bi->dispDeviceRowBytes >> 2);
dst += (bi->dispDeviceRowBytes >> 2);
}
for (i=0; i<16; i++)
{
u32 *dst_ptr = dst;
for(j=width; j; --j)
*(dst_ptr++) = 0;
dst += (bi->dispDeviceRowBytes >> 2);
}
}
#endif /* ndef NO_SCROLL */
void BTEXT btext_drawchar(char c)
{
u32 cline = 0;
if (!boot_text_mapped)
return;
switch (c) {
case '\b':
if (g_loc_X > 0)
--g_loc_X;
break;
case '\t':
g_loc_X = (g_loc_X & -8) + 8;
break;
case '\r':
g_loc_X = 0;
break;
case '\n':
g_loc_X = 0;
g_loc_Y++;
cline = 1;
break;
default:
draw_byte(c, g_loc_X++, g_loc_Y);
}
if (g_loc_X >= g_max_loc_X) {
g_loc_X = 0;
g_loc_Y++;
cline = 1;
}
#ifndef NO_SCROLL
while (g_loc_Y >= g_max_loc_Y) {
scrollscreen();
g_loc_Y--;
}
#else
/* wrap around from bottom to top of screen so we don't
waste time scrolling each line. -- paulus. */
if (g_loc_Y >= g_max_loc_Y)
g_loc_Y = 0;
if (cline) {
for (x = 0; x < g_max_loc_X; ++x)
draw_byte(' ', x, g_loc_Y);
}
#endif
}
#if 0
void BTEXT
btext_drawstring(const char *c)
{
if (!boot_text_mapped)
return;
while (*c)
btext_drawchar(*c++);
}
void BTEXT
btext_drawhex(u32 v)
{
static char hex_table[] = "0123456789abcdef";
if (!boot_text_mapped)
return;
btext_drawchar(hex_table[(v >> 28) & 0x0000000FUL]);
btext_drawchar(hex_table[(v >> 24) & 0x0000000FUL]);
btext_drawchar(hex_table[(v >> 20) & 0x0000000FUL]);
btext_drawchar(hex_table[(v >> 16) & 0x0000000FUL]);
btext_drawchar(hex_table[(v >> 12) & 0x0000000FUL]);
btext_drawchar(hex_table[(v >> 8) & 0x0000000FUL]);
btext_drawchar(hex_table[(v >> 4) & 0x0000000FUL]);
btext_drawchar(hex_table[(v >> 0) & 0x0000000FUL]);
btext_drawchar(' ');
}
#endif
static void BTEXT
draw_byte(unsigned char c, u32 locX, u32 locY)
{
boot_infos_t* bi = &disp_bi;
unsigned char *base = calc_base(bi, locX << 3, locY << 4);
#if CHAR_256==1
unsigned char *font = &vga_font[((u32)c) * 16];
#else
unsigned char *font = &vga_font[((u32)c-0x20) * 16]; // skip the first 0x20
#endif
u32 rb = bi->dispDeviceRowBytes;
switch(bi->dispDeviceDepth) {
#if 0
case 24:
case 32:
draw_byte_32(font, (u32 *)base, rb);
break;
case 15:
case 16:
draw_byte_16(font, (u32 *)base, rb);
break;
#endif
case 8:
draw_byte_8(font, (u32 *)base, rb);
break;
}
}
static u32 expand_bits_8[16] BTDATA = {
#if defined(__BIG_ENDIAN)
0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
0xffff0000,0xffff00ff,0xffffff00,0xffffffff
#elif defined(__LITTLE_ENDIAN)
0x00000000,0xff000000,0x00ff0000,0xffff0000,
0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
#else
#error FIXME: No endianness??
#endif
};
#if 0
static const u32 expand_bits_16[4] BTDATA = {
#if defined(__BIG_ENDIAN)
0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
#elif defined(__LITTLE_ENDIAN)
0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
#else
#error FIXME: No endianness??
#endif
};
#endif
#if 0
static void BTEXT
draw_byte_32(unsigned char *font, u32 *base, u32 rb)
{
u32 l, bits;
u32 fg = 0xFFFFFFFF;
u32 bg = 0x00000000;
for (l = 0; l < 16; ++l)
{
bits = *font++;
base[0] = (-(bits >> 7) & fg) ^ bg;
base[1] = (-((bits >> 6) & 1) & fg) ^ bg;
base[2] = (-((bits >> 5) & 1) & fg) ^ bg;
base[3] = (-((bits >> 4) & 1) & fg) ^ bg;
base[4] = (-((bits >> 3) & 1) & fg) ^ bg;
base[5] = (-((bits >> 2) & 1) & fg) ^ bg;
base[6] = (-((bits >> 1) & 1) & fg) ^ bg;
base[7] = (-(bits & 1) & fg) ^ bg;
base = (u32 *) ((char *)base + rb);
}
}
static void BTEXT
draw_byte_16(unsigned char *font, u32 *base, u32 rb)
{
u32 l, bits;
u32 fg = 0xFFFFFFFF;
u32 bg = 0x00000000;
u32 *eb = expand_bits_16;
for (l = 0; l < 16; ++l)
{
bits = *font++;
base[0] = (eb[bits >> 6] & fg) ^ bg;
base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg;
base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg;
base[3] = (eb[bits & 3] & fg) ^ bg;
base = (u32 *) ((char *)base + rb);
}
}
#endif
static void BTEXT
draw_byte_8(unsigned char *font, u32 *base, u32 rb)
{
u32 l, bits;
u32 fg = 0x0F0F0F0F;
u32 bg = 0x00000000;
u32 *eb = expand_bits_8;
for (l = 0; l < 16; ++l)
{
bits = *font++;
base[0] = (eb[bits >> 4] & fg) ^ bg;
base[1] = (eb[bits & 0xf] & fg) ^ bg;
base = (u32 *) ((char *)base + rb);
}
}
void btext_init(void)
{
btext_setup_display(640, 480, 8, 640,0xfc000000);
// Not realy init
// It will be init in xlinit.c because We only can access fb after the device resource is allocated and enabled.
}
void btext_tx_byte(unsigned char data)
{
btext_drawchar(data);
}
static const struct console_driver btext_console __console = {
.init = btext_init,
.tx_byte = btext_tx_byte,
.rx_byte = 0,
.tst_byte = 0,
};