⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vgacon.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/drivers/video/vgacon.c -- Low level VGA based console driver * *	Created 28 Sep 1997 by Geert Uytterhoeven * *	Rewritten by Martin Mares <mj@ucw.cz>, July 1998 * *  This file is based on the old console.c, vga.c and vesa_blank.c drivers. * *	Copyright (C) 1991, 1992  Linus Torvalds *			    1995  Jay Estabrook * *	User definable mapping table and font loading by Eugene G. Crosser, *	<crosser@average.org> * *	Improved loadable font/UTF-8 support by H. Peter Anvin *	Feb-Sep 1995 <peter.anvin@linux.org> * *	Colour palette handling, by Simon Tatham *	17-Jun-95 <sgt20@cam.ac.uk> * *	if 512 char mode is already enabled don't re-enable it, *	because it causes screen to flicker, by Mitja Horvat *	5-May-96 <mitja.horvat@guest.arnes.si> * *	Use 2 outw instead of 4 outb_p to reduce erroneous text *	flashing on RHS of screen during heavy console scrolling . *	Oct 1996, Paul Gortmaker. * * *  This file is subject to the terms and conditions of the GNU General Public *  License.  See the file COPYING in the main directory of this archive for *  more details. */#include <linux/module.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/console.h>#include <linux/string.h>#include <linux/kd.h>#include <linux/slab.h>#include <linux/vt_kern.h>#include <linux/selection.h>#include <linux/spinlock.h>#include <linux/ioport.h>#include <linux/init.h>#include <linux/screen_info.h>#include <linux/smp_lock.h>#include <video/vga.h>#include <asm/io.h>static DEFINE_SPINLOCK(vga_lock);static int cursor_size_lastfrom;static int cursor_size_lastto;static u32 vgacon_xres;static u32 vgacon_yres;static struct vgastate state;#define BLANK 0x0020#define CAN_LOAD_EGA_FONTS	/* undefine if the user must not do this */#define CAN_LOAD_PALETTE	/* undefine if the user must not do this *//* You really do _NOT_ want to define this, unless you have buggy * Trident VGA which will resize cursor when moving it between column * 15 & 16. If you define this and your VGA is OK, inverse bug will * appear. */#undef TRIDENT_GLITCH#define VGA_FONTWIDTH       8   /* VGA does not support fontwidths != 8 *//* *  Interface used by the world */static const char *vgacon_startup(void);static void vgacon_init(struct vc_data *c, int init);static void vgacon_deinit(struct vc_data *c);static void vgacon_cursor(struct vc_data *c, int mode);static int vgacon_switch(struct vc_data *c);static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);static int vgacon_set_palette(struct vc_data *vc, unsigned char *table);static int vgacon_scrolldelta(struct vc_data *c, int lines);static int vgacon_set_origin(struct vc_data *c);static void vgacon_save_screen(struct vc_data *c);static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,			 int lines);static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);static unsigned long vgacon_uni_pagedir[2];/* Description of the hardware situation */static int		vga_init_done		__read_mostly;static unsigned long	vga_vram_base		__read_mostly;	/* Base of video memory */static unsigned long	vga_vram_end		__read_mostly;	/* End of video memory */static unsigned int	vga_vram_size		__read_mostly;	/* Size of video memory */static u16		vga_video_port_reg	__read_mostly;	/* Video register select port */static u16		vga_video_port_val	__read_mostly;	/* Video register value port */static unsigned int	vga_video_num_columns;			/* Number of text columns */static unsigned int	vga_video_num_lines;			/* Number of text lines */static int		vga_can_do_color	__read_mostly;	/* Do we support colors? */static unsigned int	vga_default_font_height __read_mostly;	/* Height of default screen font */static unsigned char	vga_video_type		__read_mostly;	/* Card type */static unsigned char	vga_hardscroll_enabled	__read_mostly;static unsigned char	vga_hardscroll_user_enable __read_mostly = 1;static unsigned char	vga_font_is_default = 1;static int		vga_vesa_blanked;static int 		vga_palette_blanked;static int 		vga_is_gfx;static int 		vga_512_chars;static int 		vga_video_font_height;static int 		vga_scan_lines		__read_mostly;static unsigned int 	vga_rolled_over;int vgacon_text_mode_force = 0;bool vgacon_text_force(void){	return vgacon_text_mode_force ? true : false;}EXPORT_SYMBOL(vgacon_text_force);static int __init text_mode(char *str){	vgacon_text_mode_force = 1;	return 1;}/* force text mode - used by kernel modesetting */__setup("nomodeset", text_mode);static int __init no_scroll(char *str){	/*	 * Disabling scrollback is required for the Braillex ib80-piezo	 * Braille reader made by F.H. Papenmeier (Germany).	 * Use the "no-scroll" bootflag.	 */	vga_hardscroll_user_enable = vga_hardscroll_enabled = 0;	return 1;}__setup("no-scroll", no_scroll);/* * By replacing the four outb_p with two back to back outw, we can reduce * the window of opportunity to see text mislocated to the RHS of the * console during heavy scrolling activity. However there is the remote * possibility that some pre-dinosaur hardware won't like the back to back * I/O. Since the Xservers get away with it, we should be able to as well. */static inline void write_vga(unsigned char reg, unsigned int val){	unsigned int v1, v2;	unsigned long flags;	/*	 * ddprintk might set the console position from interrupt	 * handlers, thus the write has to be IRQ-atomic.	 */	spin_lock_irqsave(&vga_lock, flags);#ifndef SLOW_VGA	v1 = reg + (val & 0xff00);	v2 = reg + 1 + ((val << 8) & 0xff00);	outw(v1, vga_video_port_reg);	outw(v2, vga_video_port_reg);#else	outb_p(reg, vga_video_port_reg);	outb_p(val >> 8, vga_video_port_val);	outb_p(reg + 1, vga_video_port_reg);	outb_p(val & 0xff, vga_video_port_val);#endif	spin_unlock_irqrestore(&vga_lock, flags);}static inline void vga_set_mem_top(struct vc_data *c){	write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);}#ifdef CONFIG_VGACON_SOFT_SCROLLBACK#include <linux/bootmem.h>/* software scrollback */static void *vgacon_scrollback;static int vgacon_scrollback_tail;static int vgacon_scrollback_size;static int vgacon_scrollback_rows;static int vgacon_scrollback_cnt;static int vgacon_scrollback_cur;static int vgacon_scrollback_save;static int vgacon_scrollback_restore;static void vgacon_scrollback_init(int pitch){	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;	if (vgacon_scrollback) {		vgacon_scrollback_cnt  = 0;		vgacon_scrollback_tail = 0;		vgacon_scrollback_cur  = 0;		vgacon_scrollback_rows = rows - 1;		vgacon_scrollback_size = rows * pitch;	}}/* * Called only duing init so call of alloc_bootmen is ok. * Marked __init_refok to silence modpost. */static void __init_refok vgacon_scrollback_startup(void){	vgacon_scrollback = alloc_bootmem(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE					  * 1024);	vgacon_scrollback_init(vga_video_num_columns * 2);}static void vgacon_scrollback_update(struct vc_data *c, int t, int count){	void *p;	if (!vgacon_scrollback_size || c->vc_num != fg_console)		return;	p = (void *) (c->vc_origin + t * c->vc_size_row);	while (count--) {		scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,			    p, c->vc_size_row);		vgacon_scrollback_cnt++;		p += c->vc_size_row;		vgacon_scrollback_tail += c->vc_size_row;		if (vgacon_scrollback_tail >= vgacon_scrollback_size)			vgacon_scrollback_tail = 0;		if (vgacon_scrollback_cnt > vgacon_scrollback_rows)			vgacon_scrollback_cnt = vgacon_scrollback_rows;		vgacon_scrollback_cur = vgacon_scrollback_cnt;	}}static void vgacon_restore_screen(struct vc_data *c){	vgacon_scrollback_save = 0;	if (!vga_is_gfx && !vgacon_scrollback_restore) {		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,			    c->vc_screenbuf_size > vga_vram_size ?			    vga_vram_size : c->vc_screenbuf_size);		vgacon_scrollback_restore = 1;		vgacon_scrollback_cur = vgacon_scrollback_cnt;	}}static int vgacon_scrolldelta(struct vc_data *c, int lines){	int start, end, count, soff;	if (!lines) {		c->vc_visible_origin = c->vc_origin;		vga_set_mem_top(c);		return 1;	}	if (!vgacon_scrollback)		return 1;	if (!vgacon_scrollback_save) {		vgacon_cursor(c, CM_ERASE);		vgacon_save_screen(c);		vgacon_scrollback_save = 1;	}	vgacon_scrollback_restore = 0;	start = vgacon_scrollback_cur + lines;	end = start + abs(lines);	if (start < 0)		start = 0;	if (start > vgacon_scrollback_cnt)		start = vgacon_scrollback_cnt;	if (end < 0)		end = 0;	if (end > vgacon_scrollback_cnt)		end = vgacon_scrollback_cnt;	vgacon_scrollback_cur = start;	count = end - start;	soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) *					 c->vc_size_row);	soff -= count * c->vc_size_row;	if (soff < 0)		soff += vgacon_scrollback_size;	count = vgacon_scrollback_cnt - start;	if (count > c->vc_rows)		count = c->vc_rows;	if (count) {		int copysize;		int diff = c->vc_rows - count;		void *d = (void *) c->vc_origin;		void *s = (void *) c->vc_screenbuf;		count *= c->vc_size_row;		/* how much memory to end of buffer left? */		copysize = min(count, vgacon_scrollback_size - soff);		scr_memcpyw(d, vgacon_scrollback + soff, copysize);		d += copysize;		count -= copysize;		if (count) {			scr_memcpyw(d, vgacon_scrollback, count);			d += count;		}		if (diff)			scr_memcpyw(d, s, diff * c->vc_size_row);	} else		vgacon_cursor(c, CM_MOVE);	return 1;}#else#define vgacon_scrollback_startup(...) do { } while (0)#define vgacon_scrollback_init(...)    do { } while (0)#define vgacon_scrollback_update(...)  do { } while (0)static void vgacon_restore_screen(struct vc_data *c){	if (c->vc_origin != c->vc_visible_origin)		vgacon_scrolldelta(c, 0);}static int vgacon_scrolldelta(struct vc_data *c, int lines){	if (!lines)		/* Turn scrollback off */		c->vc_visible_origin = c->vc_origin;	else {		int margin = c->vc_size_row * 4;		int ul, we, p, st;		if (vga_rolled_over >		    (c->vc_scr_end - vga_vram_base) + margin) {			ul = c->vc_scr_end - vga_vram_base;			we = vga_rolled_over + c->vc_size_row;		} else {			ul = 0;			we = vga_vram_size;		}		p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +		    lines * c->vc_size_row;		st = (c->vc_origin - vga_vram_base - ul + we) % we;		if (st < 2 * margin)			margin = 0;		if (p < margin)			p = 0;		if (p > st - margin)			p = st;		c->vc_visible_origin = vga_vram_base + (p + ul) % we;	}	vga_set_mem_top(c);	return 1;}#endif /* CONFIG_VGACON_SOFT_SCROLLBACK */static const char *vgacon_startup(void){	const char *display_desc = NULL;	u16 saved1, saved2;	volatile u16 *p;	if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB) {	      no_vga:#ifdef CONFIG_DUMMY_CONSOLE		conswitchp = &dummy_con;		return conswitchp->con_startup();#else		return NULL;#endif	}	/* boot_params.screen_info initialized? */	if ((screen_info.orig_video_mode  == 0) &&	    (screen_info.orig_video_lines == 0) &&	    (screen_info.orig_video_cols  == 0))		goto no_vga;	/* VGA16 modes are not handled by VGACON */	if ((screen_info.orig_video_mode == 0x0D) ||	/* 320x200/4 */	    (screen_info.orig_video_mode == 0x0E) ||	/* 640x200/4 */	    (screen_info.orig_video_mode == 0x10) ||	/* 640x350/4 */	    (screen_info.orig_video_mode == 0x12) ||	/* 640x480/4 */	    (screen_info.orig_video_mode == 0x6A))	/* 800x600/4 (VESA) */		goto no_vga;	vga_video_num_lines = screen_info.orig_video_lines;	vga_video_num_columns = screen_info.orig_video_cols;	state.vgabase = NULL;	if (screen_info.orig_video_mode == 7) {		/* Monochrome display */		vga_vram_base = 0xb0000;		vga_video_port_reg = VGA_CRT_IM;		vga_video_port_val = VGA_CRT_DM;		if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) {			static struct resource ega_console_resource =			    { .name = "ega", .start = 0x3B0, .end = 0x3BF };			vga_video_type = VIDEO_TYPE_EGAM;			vga_vram_size = 0x8000;			display_desc = "EGA+";			request_resource(&ioport_resource,					 &ega_console_resource);		} else {			static struct resource mda1_console_resource =			    { .name = "mda", .start = 0x3B0, .end = 0x3BB };			static struct resource mda2_console_resource =			    { .name = "mda", .start = 0x3BF, .end = 0x3BF };			vga_video_type = VIDEO_TYPE_MDA;			vga_vram_size = 0x2000;			display_desc = "*MDA";			request_resource(&ioport_resource,					 &mda1_console_resource);			request_resource(&ioport_resource,					 &mda2_console_resource);			vga_video_font_height = 14;		}	} else {		/* If not, it is color. */		vga_can_do_color = 1;		vga_vram_base = 0xb8000;		vga_video_port_reg = VGA_CRT_IC;		vga_video_port_val = VGA_CRT_DC;		if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) {			int i;			vga_vram_size = 0x8000;			if (!screen_info.orig_video_isVGA) {				static struct resource ega_console_resource				    = { .name = "ega", .start = 0x3C0, .end = 0x3DF };				vga_video_type = VIDEO_TYPE_EGAC;				display_desc = "EGA";				request_resource(&ioport_resource,						 &ega_console_resource);			} else {				static struct resource vga_console_resource				    = { .name = "vga+", .start = 0x3C0, .end = 0x3DF };				vga_video_type = VIDEO_TYPE_VGAC;				display_desc = "VGA+";				request_resource(&ioport_resource,						 &vga_console_resource);#ifdef VGA_CAN_DO_64KB				/*				 * get 64K rather than 32K of video RAM.				 * This doesn't actually work on all "VGA"				 * controllers (it seems like setting MM=01				 * and COE=1 isn't necessarily a good idea)				 */				vga_vram_base = 0xa0000;				vga_vram_size = 0x10000;				outb_p(6, VGA_GFX_I);				outb_p(6, VGA_GFX_D);#endif				/*				 * Normalise the palette registers, to point				 * the 16 screen colours to the first 16				 * DAC entries.

⌨️ 快捷键说明

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