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

📄 console.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  linux/drivers/char/console.c * *  Copyright (C) 1991, 1992  Linus Torvalds *//* * Hopefully this will be a rather complete VT102 implementation. * * Beeping thanks to John T Kohl. * * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics *   Chars, and VT100 enhancements by Peter MacDonald. * * Copy and paste function by Andrew Haylett, *   some enhancements by Alessandro Rubini. * * Code to check for different video-cards mostly by Galen Hunt, * <g-hunt@ee.utah.edu> * * Rudimentary ISO 10646/Unicode/UTF-8 character set support by * Markus Kuhn, <mskuhn@immd4.informatik.uni-erlangen.de>. * * Dynamic allocation of consoles, aeb@cwi.nl, May 1994 * Resizing of consoles, aeb, 940926 * * Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94 * <poe@daimi.aau.dk> * * User-defined bell sound, new setterm control sequences and printk * redirection by Martin Mares <mj@k332.feld.cvut.cz> 19-Nov-95 * * APM screenblank bug fixed Takashi Manabe <manabe@roy.dsl.tutics.tut.jp> * * Merge with the abstract console driver by Geert Uytterhoeven * <Geert.Uytterhoeven@cs.kuleuven.ac.be>, Jan 1997. * *   Original m68k console driver modifications by * *     - Arno Griffioen <arno@usn.nl> *     - David Carter <carter@cs.bris.ac.uk> *  *   Note that the abstract console driver allows all consoles to be of *   potentially different sizes, so the following variables depend on the *   current console (currcons): * *     - video_num_columns *     - video_num_lines *     - video_size_row *     - can_do_color * *   The abstract console driver provides a generic interface for a text *   console. It supports VGA text mode, frame buffer based graphical consoles *   and special graphics processors that are only accessible through some *   registers (e.g. a TMS340x0 GSP). * *   The interface to the hardware is specified using a special structure *   (struct consw) which contains function pointers to console operations *   (see <linux/console.h> for more information). * * Support for changeable cursor shape * by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>, August 1997 * * Ported to i386 and con_scrolldelta fixed * by Emmanuel Marty <core@ggi-project.org>, April 1998 * * Resurrected character buffers in videoram plus lots of other trickery * by Martin Mares <mj@atrey.karlin.mff.cuni.cz>, July 1998 */#include <linux/module.h>#include <linux/sched.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/kd.h>#include <linux/malloc.h>#include <linux/major.h>#include <linux/mm.h>#include <linux/console.h>#include <linux/init.h>#include <linux/vt_kern.h>#include <linux/selection.h>#include <linux/console_struct.h>#include <linux/kbd_kern.h>#include <linux/consolemap.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/config.h>#include <linux/version.h>#include <linux/tqueue.h>#ifdef CONFIG_APM#include <linux/apm_bios.h>#endif#include <asm/io.h>#include <asm/system.h>#include <asm/uaccess.h>#include <asm/bitops.h>#include <asm/linux_logo.h>#include "console_macros.h"struct consw *conswitchp = NULL;/* A bitmap for codes <32. A bit of 1 indicates that the code * corresponding to that bit number invokes some special action * (such as cursor movement) and should not be displayed as a * glyph unless the disp_ctrl mode is explicitly enabled. */#define CTRL_ACTION 0x0d00ff81#define CTRL_ALWAYS 0x0800f501	/* Cannot be overridden by disp_ctrl *//* * Here is the default bell parameters: 750HZ, 1/8th of a second */#define DEFAULT_BELL_PITCH	750#define DEFAULT_BELL_DURATION	(HZ/8)#ifndef MIN#define MIN(a,b)	((a) < (b) ? (a) : (b))#endifstatic struct tty_struct *console_table[MAX_NR_CONSOLES];static struct termios *console_termios[MAX_NR_CONSOLES];static struct termios *console_termios_locked[MAX_NR_CONSOLES];struct vc vc_cons [MAX_NR_CONSOLES];#ifndef VT_SINGLE_DRIVERstatic struct consw *con_driver_map[MAX_NR_CONSOLES];#endifstatic int con_open(struct tty_struct *, struct file *);static void vc_init(unsigned int console, unsigned int rows,		    unsigned int cols, int do_clear);static void blank_screen(void);static void gotoxy(int currcons, int new_x, int new_y);static void save_cur(int currcons);static void reset_terminal(int currcons, int do_clear);static void con_flush_chars(struct tty_struct *tty);static void set_vesa_blanking(unsigned long arg);static void set_cursor(int currcons);static void hide_cursor(int currcons);static int printable = 0;		/* Is console ready for printing? */int do_poke_blanked_console = 0;int console_blanked = 0;static int vesa_blank_mode = 0; /* 0:none 1:suspendV 2:suspendH 3:powerdown */static int blankinterval = 10*60*HZ;static int vesa_off_interval = 0;/* * fg_console is the current virtual console, * last_console is the last used one, * want_console is the console we want to switch to, * kmsg_redirect is the console for kernel messages, */int fg_console = 0;int last_console = 0;int want_console = -1;int kmsg_redirect = 0;/* * For each existing display, we have a pointer to console currently visible * on that display, allowing consoles other than fg_console to be refreshed * appropriately. Unless the low-level driver supplies its own display_fg * variable, we use this one for the "master display". */static struct vc_data *master_display_fg = NULL;/* * Unfortunately, we need to delay tty echo when we're currently writing to the * console since the code is (and always was) not re-entrant, so we insert * all filp requests to con_task_queue instead of tq_timer and run it from * the console_bh. */DECLARE_TASK_QUEUE(con_task_queue);/* * For the same reason, we defer scrollback to the console_bh. */static int scrollback_delta = 0;/* *	Low-Level Functions */#define IS_FG (currcons == fg_console)#define IS_VISIBLE CON_IS_VISIBLE(vc_cons[currcons].d)#ifdef VT_BUF_VRAM_ONLY#define DO_UPDATE 0#else#define DO_UPDATE IS_VISIBLE#endifstatic inline unsigned short *screenpos(int currcons, int offset, int viewed){	unsigned short *p;		if (!viewed)		p = (unsigned short *)(origin + offset);	else if (!sw->con_screen_pos)		p = (unsigned short *)(visible_origin + offset);	else		p = sw->con_screen_pos(vc_cons[currcons].d, offset);	return p;}static inline void scrolldelta(int lines){	scrollback_delta += lines;	mark_bh(CONSOLE_BH);}static void scrup(int currcons, unsigned int t, unsigned int b, int nr){	unsigned short *d, *s;	if (t+nr >= b)		nr = b - t - 1;	if (b > video_num_lines || t >= b || nr < 1)		return;	if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr))		return;	d = (unsigned short *) (origin+video_size_row*t);	s = (unsigned short *) (origin+video_size_row*(t+nr));	scr_memcpyw(d, s, (b-t-nr) * video_size_row);	scr_memsetw(d + (b-t-nr) * video_num_columns, video_erase_char, video_size_row*nr);}static voidscrdown(int currcons, unsigned int t, unsigned int b, int nr){	unsigned short *s;	unsigned int step;	if (t+nr >= b)		nr = b - t - 1;	if (b > video_num_lines || t >= b || nr < 1)		return;	if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr))		return;	s = (unsigned short *) (origin+video_size_row*t);	step = video_num_columns * nr;	scr_memmovew(s + step, s, (b-t-nr)*video_size_row);	scr_memsetw(s, video_erase_char, 2*step);}static void do_update_region(int currcons, unsigned long start, int count){#ifndef VT_BUF_VRAM_ONLY	unsigned int xx, yy, offset;	u16 *p;	p = (u16 *) start;	if (!sw->con_getxy) {		offset = (start - origin) / 2;		xx = offset % video_num_columns;		yy = offset / video_num_columns;	} else {		int nxx, nyy;		start = sw->con_getxy(vc_cons[currcons].d, start, &nxx, &nyy);		xx = nxx; yy = nyy;	}	for(;;) {		u16 attrib = scr_readw(p) & 0xff00;		int startx = xx;		u16 *q = p;		while (xx < video_num_columns && count) {			if (attrib != (scr_readw(p) & 0xff00)) {				if (p > q)					sw->con_putcs(vc_cons[currcons].d, q, p-q, yy, startx);				startx = xx;				q = p;				attrib = scr_readw(p) & 0xff00;			}			p++;			xx++;			count--;		}		if (p > q)			sw->con_putcs(vc_cons[currcons].d, q, p-q, yy, startx);		if (!count)			break;		xx = 0;		yy++;		if (sw->con_getxy) {			p = (u16 *)start;			start = sw->con_getxy(vc_cons[currcons].d, start, NULL, NULL);		}	}#endif}void update_region(int currcons, unsigned long start, int count){	if (DO_UPDATE) {		hide_cursor(currcons);		do_update_region(currcons, start, count);		set_cursor(currcons);	}}/* Structure of attributes is hardware-dependent */static u8 build_attr(int currcons, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse){	if (sw->con_build_attr)		return sw->con_build_attr(vc_cons[currcons].d, _color, _intensity, _blink, _underline, _reverse);#ifndef VT_BUF_VRAM_ONLY/* * ++roman: I completely changed the attribute format for monochrome * mode (!can_do_color). The formerly used MDA (monochrome display * adapter) format didn't allow the combination of certain effects. * Now the attribute is just a bit vector: *  Bit 0..1: intensity (0..2) *  Bit 2   : underline *  Bit 3   : reverse *  Bit 7   : blink */	{	u8 a = color;	if (!can_do_color)		return _intensity |		       (_underline ? 4 : 0) |		       (_reverse ? 8 : 0) |		       (_blink ? 0x80 : 0);	if (_underline)		a = (a & 0xf0) | ulcolor;	else if (_intensity == 0)		a = (a & 0xf0) | halfcolor;	if (_reverse)		a = ((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77);	if (_blink)		a ^= 0x80;	if (_intensity == 2)		a ^= 0x08;	if (hi_font_mask == 0x100)		a <<= 1;	return a;	}#else	return 0;#endif}static void update_attr(int currcons){	attr = build_attr(currcons, color, intensity, blink, underline, reverse ^ decscnm);	video_erase_char = (build_attr(currcons, color, 1, 0, 0, decscnm) << 8) | ' ';}/* Note: inverting the screen twice should revert to the original state */void invert_screen(int currcons, int offset, int count, int viewed){	unsigned short *p;	count /= 2;	p = screenpos(currcons, offset, viewed);	if (sw->con_invert_region)		sw->con_invert_region(vc_cons[currcons].d, p, count);#ifndef VT_BUF_VRAM_ONLY	else {		u16 *q = p;		int cnt = count;		if (!can_do_color) {			while (cnt--) *q++ ^= 0x0800;		} else if (hi_font_mask == 0x100) {			while (cnt--) {				u16 a = *q;				a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4);				*q++ = a;			}		} else {			while (cnt--) {				u16 a = *q;				a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);				*q++ = a;			}		}	}#endif	if (DO_UPDATE)		do_update_region(currcons, (unsigned long) p, count);}/* used by selection: complement pointer position */void complement_pos(int currcons, int offset){	static unsigned short *p = NULL;	static unsigned short old = 0;	static unsigned short oldx = 0, oldy = 0;	if (p) {		scr_writew(old, p);		if (DO_UPDATE)			sw->con_putc(vc_cons[currcons].d, old, oldy, oldx);	}	if (offset == -1)		p = NULL;	else {		unsigned short new;		p = screenpos(currcons, offset, 1);		old = scr_readw(p);		new = old ^ complement_mask;		scr_writew(new, p);		if (DO_UPDATE) {			oldx = (offset >> 1) % video_num_columns;			oldy = (offset >> 1) / video_num_columns;			sw->con_putc(vc_cons[currcons].d, new, oldy, oldx);		}	}}static void insert_char(int currcons, unsigned int nr){	unsigned short *p, *q = (unsigned short *) pos;	p = q + video_num_columns - nr - x;	while (--p >= q)		scr_writew(scr_readw(p), p + nr);	scr_memsetw(q, video_erase_char, nr*2);	need_wrap = 0;	if (DO_UPDATE) {		unsigned short oldattr = attr;		sw->con_bmove(vc_cons[currcons].d,y,x,y,x+nr,1,			      video_num_columns-x-nr);		attr = video_erase_char >> 8;		while (nr--)			sw->con_putc(vc_cons[currcons].d,				     video_erase_char,y,x+nr);		attr = oldattr;	}}static void delete_char(int currcons, unsigned int nr){	unsigned int i = x;	unsigned short *p = (unsigned short *) pos;	while (++i <= video_num_columns - nr) {		scr_writew(scr_readw(p+nr), p);		p++;	}	scr_memsetw(p, video_erase_char, nr*2);	need_wrap = 0;	if (DO_UPDATE) {		unsigned short oldattr = attr;		sw->con_bmove(vc_cons[currcons].d, y, x+nr, y, x, 1,			      video_num_columns-x-nr);		attr = video_erase_char >> 8;		while (nr--)			sw->con_putc(vc_cons[currcons].d,				     video_erase_char, y,				     video_num_columns-1-nr);		attr = oldattr;	}}static int softcursor_original;static void add_softcursor(int currcons){	int i = scr_readw((u16 *) pos);	u32 type = cursor_type;	if (! (type & 0x10)) return;	if (softcursor_original != -1) return;	softcursor_original = i;	i |= ((type >> 8) & 0xff00 );	i ^= ((type) & 0xff00 );	if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000;	if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;	scr_writew(i, (u16 *) pos);	if (DO_UPDATE)		sw->con_putc(vc_cons[currcons].d, i, y, x);}static void hide_cursor(int currcons){	if (currcons == sel_cons)		clear_selection();	if (softcursor_original != -1) {		scr_writew(softcursor_original,(u16 *) pos);		if (DO_UPDATE)			sw->con_putc(vc_cons[currcons].d, softcursor_original, y, x);		softcursor_original = -1;	}	sw->con_cursor(vc_cons[currcons].d,CM_ERASE);}static void set_cursor(int currcons){    if (!IS_FG || console_blanked || vcmode == KD_GRAPHICS)	return;    if (deccm) {	if (currcons == sel_cons)		clear_selection();	add_softcursor(currcons);	if ((cursor_type & 0x0f) != 1)	    sw->con_cursor(vc_cons[currcons].d,CM_DRAW);    } else	hide_cursor(currcons);}static void set_origin(int currcons){	if (!IS_VISIBLE ||	    !sw->con_set_origin ||	    !sw->con_set_origin(vc_cons[currcons].d))		origin = (unsigned long) screenbuf;	visible_origin = origin;	scr_end = origin + screenbuf_size;	pos = origin + video_size_row*y + 2*x;}static inline void save_screen(int currcons){	if (sw->con_save_screen)		sw->con_save_screen(vc_cons[currcons].d);}/* *	Redrawing of screen */void redraw_screen(int new_console, int is_switch){	int redraw = 1;	int currcons, old_console;	static int lock = 0;	if (lock)		return;	if (!vc_cons_allocated(new_console)) {		/* strange ... */		printk("redraw_screen: tty %d not allocated ??\n", new_console+1);		return;	}

⌨️ 快捷键说明

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