btext.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 747 行 · 第 1/3 页
C
747 行
/* * Procedures for drawing on the screen early on in the boot process. * * Benjamin Herrenschmidt <benh@kernel.crashing.org> */#include <linux/config.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/init.h>#include <linux/version.h>#include <asm/sections.h>#include <asm/bootx.h>#include <asm/btext.h>#include <asm/prom.h>#include <asm/page.h>#include <asm/mmu.h>#include <asm/pgtable.h>#include <asm/io.h>#include <asm/lmb.h>#include <asm/processor.h>#undef NO_SCROLL#ifndef NO_SCROLLstatic void scrollscreen(void);#endifstatic void draw_byte(unsigned char c, long locX, long locY);static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb);static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb);static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb);static int g_loc_X;static int g_loc_Y;static int g_max_loc_X;static int g_max_loc_Y;unsigned long disp_BAT[2] __initdata = {0, 0};#define cmapsz (16*256)static unsigned char vga_font[cmapsz];int boot_text_mapped;int force_printk_to_btext = 0;boot_infos_t disp_bi;/* This function will enable the early boot text when doing OF booting. This * way, xmon output should work too */void __init btext_setup_display(int width, int height, int depth, int pitch, unsigned long address){ unsigned long offset = reloc_offset(); boot_infos_t* bi = PTRRELOC(&disp_bi); RELOC(g_loc_X) = 0; RELOC(g_loc_Y) = 0; RELOC(g_max_loc_X) = width / 8; RELOC(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; RELOC(boot_text_mapped) = 1;}/* 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){ unsigned long base, offset, size; boot_infos_t *bi = &disp_bi; unsigned char *vbase; /* By default, we are no longer mapped */ boot_text_mapped = 0; 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]; vbase = __ioremap(base, size, _PAGE_NO_CACHE); if (vbase == 0) return; bi->logicalDisplayBase = vbase + offset; boot_text_mapped = 1;}/* Calc the base address of a given point (x,y) */static unsigned char * calc_base(boot_infos_t *bi, int x, int y){ unsigned char *base; base = bi->logicalDisplayBase; if (base == 0) 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, int width, int height, int depth, int pitch){ boot_infos_t *bi = &disp_bi; if (bi->dispDeviceBase == 0) return; /* check it's the same frame buffer (within 256MB) */ if ((phys ^ (unsigned long)bi->dispDeviceBase) & 0xf0000000) return; 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) { iounmap(bi->logicalDisplayBase); 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_clearscreen(void){ unsigned long offset = reloc_offset(); boot_infos_t* bi = PTRRELOC(&disp_bi); unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3)) >> 3; int i,j; for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) { unsigned long *ptr = base; for(j=width; j; --j) *(ptr++) = 0; base += (bi->dispDeviceRowBytes >> 3); }}#ifndef NO_SCROLLstatic void scrollscreen(void){ unsigned long offset = reloc_offset(); boot_infos_t* bi = PTRRELOC(&disp_bi); unsigned long *src = (unsigned long *)calc_base(bi,0,16); unsigned long *dst = (unsigned long *)calc_base(bi,0,0); unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3)) >> 3; int i,j; for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++) { unsigned long *src_ptr = src; unsigned long *dst_ptr = dst; for(j=width; j; --j) *(dst_ptr++) = *(src_ptr++); src += (bi->dispDeviceRowBytes >> 3); dst += (bi->dispDeviceRowBytes >> 3); } for (i=0; i<16; i++) { unsigned long *dst_ptr = dst; for(j=width; j; --j) *(dst_ptr++) = 0; dst += (bi->dispDeviceRowBytes >> 3); }}#endif /* ndef NO_SCROLL */void btext_drawchar(char c){ unsigned long offset = reloc_offset(); int cline = 0;#ifdef NO_SCROLL int x;#endif if (!RELOC(boot_text_mapped)) return; switch (c) { case '\b': if (RELOC(g_loc_X) > 0) --RELOC(g_loc_X); break; case '\t': RELOC(g_loc_X) = (RELOC(g_loc_X) & -8) + 8; break; case '\r': RELOC(g_loc_X) = 0; break; case '\n': RELOC(g_loc_X) = 0; RELOC(g_loc_Y)++; cline = 1; break; default: draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y)); } if (RELOC(g_loc_X) >= RELOC(g_max_loc_X)) { RELOC(g_loc_X) = 0; RELOC(g_loc_Y)++; cline = 1; }#ifndef NO_SCROLL while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) { scrollscreen(); RELOC(g_loc_Y)--; }#else /* wrap around from bottom to top of screen so we don't waste time scrolling each line. -- paulus. */ if (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) RELOC(g_loc_Y) = 0; if (cline) { for (x = 0; x < RELOC(g_max_loc_X); ++x) draw_byte(' ', x, RELOC(g_loc_Y)); }#endif}void btext_drawstring(const char *c){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?