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 + -
显示快捷键?