btext.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 752 行 · 第 1/3 页

C
752
字号
/* * 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/prom.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;static int dispDeviceRowBytes;static int dispDeviceDepth;static int dispDeviceRect[4];static unsigned char *dispDeviceBase, *logicalDisplayBase;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;/* 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;	unsigned char *vbase;	/* By default, we are no longer mapped */	boot_text_mapped = 0;	if (dispDeviceBase == 0)		return;	base = ((unsigned long) dispDeviceBase) & 0xFFFFF000UL;	offset = ((unsigned long) dispDeviceBase) - base;	size = dispDeviceRowBytes * dispDeviceRect[3] + offset		+ dispDeviceRect[0];	vbase = __ioremap(base, size, _PAGE_NO_CACHE);	if (vbase == 0)		return;	logicalDisplayBase = vbase + offset;	boot_text_mapped = 1;}int btext_initialize(struct device_node *np){	unsigned int width, height, depth, pitch;	unsigned long address = 0;	u32 *prop;	prop = (u32 *)get_property(np, "width", NULL);	if (prop == NULL)		return -EINVAL;	width = *prop;	prop = (u32 *)get_property(np, "height", NULL);	if (prop == NULL)		return -EINVAL;	height = *prop;	prop = (u32 *)get_property(np, "depth", NULL);	if (prop == NULL)		return -EINVAL;	depth = *prop;	pitch = width * ((depth + 7) / 8);	prop = (u32 *)get_property(np, "linebytes", NULL);	if (prop)		pitch = *prop;	if (pitch == 1)		pitch = 0x1000;	prop = (u32 *)get_property(np, "address", NULL);	if (prop)		address = *prop;	/* FIXME: Add support for PCI reg properties */	if (address == 0)		return -EINVAL;	g_loc_X = 0;	g_loc_Y = 0;	g_max_loc_X = width / 8;	g_max_loc_Y = height / 16;	logicalDisplayBase = (unsigned char *)address;	dispDeviceBase = (unsigned char *)address;	dispDeviceRowBytes = pitch;	dispDeviceDepth = depth;	dispDeviceRect[0] = dispDeviceRect[1] = 0;	dispDeviceRect[2] = width;	dispDeviceRect[3] = height;	map_boot_text();	return 0;}/* Calc the base address of a given point (x,y) */static unsigned char * calc_base(int x, int y){	unsigned char *base;	base = logicalDisplayBase;	if (base == 0)		base = dispDeviceBase;	base += (x + dispDeviceRect[0]) * (dispDeviceDepth >> 3);	base += (y + dispDeviceRect[1]) * 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){	if (dispDeviceBase == 0)		return;	/* check it's the same frame buffer (within 256MB) */	if ((phys ^ (unsigned long)dispDeviceBase) & 0xf0000000)		return;	dispDeviceBase = (__u8 *) phys;	dispDeviceRect[0] = 0;	dispDeviceRect[1] = 0;	dispDeviceRect[2] = width;	dispDeviceRect[3] = height;	dispDeviceDepth = depth;	dispDeviceRowBytes = pitch;	if (boot_text_mapped) {		iounmap(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 *base	= (unsigned long *)calc_base(0, 0);	unsigned long width 	= ((dispDeviceRect[2] - dispDeviceRect[0]) *					(dispDeviceDepth >> 3)) >> 3;	int i,j;	for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++)	{		unsigned long *ptr = base;		for(j=width; j; --j)			*(ptr++) = 0;		base += (dispDeviceRowBytes >> 3);	}}#ifndef NO_SCROLLstatic void scrollscreen(void){	unsigned long *src     	= (unsigned long *)calc_base(0,16);	unsigned long *dst     	= (unsigned long *)calc_base(0,0);	unsigned long width    	= ((dispDeviceRect[2] - dispDeviceRect[0]) *				   (dispDeviceDepth >> 3)) >> 3;	int i,j;	for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++)	{		unsigned long *src_ptr = src;		unsigned long *dst_ptr = dst;		for(j=width; j; --j)			*(dst_ptr++) = *(src_ptr++);		src += (dispDeviceRowBytes >> 3);		dst += (dispDeviceRowBytes >> 3);	}	for (i=0; i<16; i++)	{		unsigned long *dst_ptr = dst;		for(j=width; j; --j)			*(dst_ptr++) = 0;		dst += (dispDeviceRowBytes >> 3);	}}#endif /* ndef NO_SCROLL */void btext_drawchar(char c){	int cline = 0;#ifdef NO_SCROLL	int x;#endif	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;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?