📄 console.c
字号:
/* * linux/drivers/char/console.c * * Copyright (C) 1991, 1992 Linus Torvalds *//* * console.c * * This module exports the console io functions: * * 'void do_keyboard_interrupt(void)' * * 'int vc_allocate(unsigned int console)' * 'int vc_cons_allocated(unsigned int console)' * 'int vc_resize(unsigned long lines, unsigned long cols)' * 'int vc_resize_con(unsigned long lines, unsigned long cols, * unsigned int currcons)' * 'void vc_disallocate(unsigned int currcons)' * * 'unsigned long con_init(unsigned long)' * 'int con_open(struct tty_struct *tty, struct file * filp)' * 'void con_write(struct tty_struct * tty)' * 'void console_print(const char * b)' * 'void update_screen(int new_console)' * * 'void do_blank_screen(int)' * 'void do_unblank_screen(void)' * 'void poke_blanked_console(void)' * * 'unsigned short *screen_pos(int currcons, int w_offset, int viewed)' * 'void complement_pos(int currcons, int offset)' * 'void invert_screen(int currcons, int offset, int count, int shift)' * * 'void scrollback(int lines)' * 'void scrollfront(int lines)' * * 'int con_get_font(char *)' * 'int con_set_font(char *)' * * 'void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)' * 'int mouse_reporting(void)' * * 'unsigned long get_video_num_lines(unsigned int console)' * 'unsigned long get_video_num_columns(unsigned int console)' * 'unsigned long get_video_size_row(unsigned int console)' * * 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. * * User definable mapping table and font loading by Eugene G. Crosser, * <crosser@pccross.msk.su> * * 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> * * 680x0 LINUX support by Arno Griffioen (arno@usn.nl) * * 9-Apr-94: Arno Griffioen: fixed scrolling and delete-char bug. * Scrolling code moved to amicon.c * * 18-Apr-94: David Carter [carter@cs.bris.ac.uk]. 680x0 LINUX modified * Integrated support for new low level driver `amicon_ocs.c' * */#define BLANK 0x0020#define CAN_LOAD_EGA_FONTS /* undefine if the user must not do this *//* 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)/* * NOTE!!! We sometimes disable and enable interrupts for a short while * (to put a word in video IO), but this will work even for keyboard * interrupts. We know interrupts aren't enabled when getting a keyboard * interrupt, as we use trap-gates. Hopefully all is well. */#include <linux/config.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/console.h>#include <linux/kd.h>#include <linux/malloc.h>#include <linux/major.h>#include <linux/mm.h>#include <linux/ioport.h>#include <asm/io.h>#include <asm/segment.h>#include <asm/system.h>#include <asm/bitops.h>#include "../../../drivers/char/kbd_kern.h"#include "../../../drivers/char/vt_kern.h"#include "../../../drivers/char/consolemap.h"#include "../../../drivers/char/selection.h"#ifndef MIN#define MIN(a,b) ((a) < (b) ? (a) : (b))#endifstruct tty_driver console_driver;static int console_refcount;static 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];static void vc_init(unsigned int console, int do_clear);static void update_attr(int currcons);static void gotoxy(int currcons, int new_x, int new_y);static void save_cur(int currcons);static void blank_screen(void);static void unblank_screen(void);extern void change_console(unsigned int);static inline void set_cursor(int currcons);static void reset_terminal(int currcons, int do_clear);extern void reset_vc(unsigned int new_console);extern void vt_init(void);extern void register_console(void (*proc)(const char *));extern void vesa_blank(void);extern void vesa_unblank(void);extern void compute_shiftstate(void);void poke_blanked_console(void);void do_blank_screen(int);unsigned long video_num_lines;unsigned long video_num_columns;unsigned long video_size_row;static int printable = 0; /* Is console ready for printing? */unsigned long video_font_height; /* Height of current screen font */unsigned long video_scan_lines; /* Number of scan lines on screen */unsigned long default_font_height; /* Height of default screen font */int video_mode_512ch = 0; /* 512-character mode */static unsigned short console_charmask = 0x0ff;static unsigned short *vc_scrbuf[MAX_NR_CONSOLES];/* used by kbd_bh - set by keyboard_interrupt */ int do_poke_blanked_console = 0; int console_blanked = 0;static int blankinterval = 10*60*HZ;static int vesa_off_interval = 0;static int vesa_blank_mode = 0; /* 0:none 1:suspendV 2:suspendH 3:powerdown */static struct vc { struct vc_data *d; /* might add scrmem, vt_struct, kbd at some time, to have everything in one place - the disadvantage would be that vc_cons etc can no longer be static */} vc_cons [MAX_NR_CONSOLES];struct consw *conswitchp;#define cols (vc_cons[currcons].d->vc_cols)#define rows (vc_cons[currcons].d->vc_rows)#define size_row (vc_cons[currcons].d->vc_size_row)#define screenbuf_size (vc_cons[currcons].d->vc_screenbuf_size)#define cons_num (vc_cons[currcons].d->vc_num)#define origin (vc_cons[currcons].d->vc_origin)#define scr_end (vc_cons[currcons].d->vc_scr_end)#define pos (vc_cons[currcons].d->vc_pos)#define top (vc_cons[currcons].d->vc_top)#define bottom (vc_cons[currcons].d->vc_bottom)#define x (vc_cons[currcons].d->vc_x)#define y (vc_cons[currcons].d->vc_y)#define vc_state (vc_cons[currcons].d->vc_state)#define npar (vc_cons[currcons].d->vc_npar)#define par (vc_cons[currcons].d->vc_par)#define ques (vc_cons[currcons].d->vc_ques)#define attr (vc_cons[currcons].d->vc_attr)#define saved_x (vc_cons[currcons].d->vc_saved_x)#define saved_y (vc_cons[currcons].d->vc_saved_y)#define translate (vc_cons[currcons].d->vc_translate)#define G0_charset (vc_cons[currcons].d->vc_G0_charset)#define G1_charset (vc_cons[currcons].d->vc_G1_charset)#define saved_G0 (vc_cons[currcons].d->vc_saved_G0)#define saved_G1 (vc_cons[currcons].d->vc_saved_G1)#define utf (vc_cons[currcons].d->vc_utf)#define utf_count (vc_cons[currcons].d->vc_utf_count)#define utf_char (vc_cons[currcons].d->vc_utf_char)#define video_mem_start (vc_cons[currcons].d->vc_video_mem_start)#define video_mem_end (vc_cons[currcons].d->vc_video_mem_end)#define video_erase_char (vc_cons[currcons].d->vc_video_erase_char) #define disp_ctrl (vc_cons[currcons].d->vc_disp_ctrl)#define toggle_meta (vc_cons[currcons].d->vc_toggle_meta)#define decscnm (vc_cons[currcons].d->vc_decscnm)#define decom (vc_cons[currcons].d->vc_decom)#define decawm (vc_cons[currcons].d->vc_decawm)#define deccm (vc_cons[currcons].d->vc_deccm)#define decim (vc_cons[currcons].d->vc_decim)#define deccolm (vc_cons[currcons].d->vc_deccolm)#define need_wrap (vc_cons[currcons].d->vc_need_wrap)#define has_scrolled (vc_cons[currcons].d->vc_has_scrolled)#define kmalloced (vc_cons[currcons].d->vc_kmalloced)#define report_mouse (vc_cons[currcons].d->vc_report_mouse)#define can_do_color (vc_cons[currcons].d->vc_can_do_color)#define color (vc_cons[currcons].d->vc_color)#define s_color (vc_cons[currcons].d->vc_s_color)#define def_color (vc_cons[currcons].d->vc_def_color)#define foreground (color & 0x0f)#define background (color & 0xf0)#define charset (vc_cons[currcons].d->vc_charset)#define s_charset (vc_cons[currcons].d->vc_s_charset)#define intensity (vc_cons[currcons].d->vc_intensity)#define underline (vc_cons[currcons].d->vc_underline)#define blink (vc_cons[currcons].d->vc_blink)#define reverse (vc_cons[currcons].d->vc_reverse)#define s_intensity (vc_cons[currcons].d->vc_s_intensity)#define s_underline (vc_cons[currcons].d->vc_s_underline)#define s_blink (vc_cons[currcons].d->vc_s_blink)#define s_reverse (vc_cons[currcons].d->vc_s_reverse)#define ulcolor (vc_cons[currcons].d->vc_ulcolor)#define halfcolor (vc_cons[currcons].d->vc_halfcolor)#define tab_stop (vc_cons[currcons].d->vc_tab_stop)#define bell_pitch (vc_cons[currcons].d->vc_bell_pitch)#define bell_duration (vc_cons[currcons].d->vc_bell_duration)#define sw (vc_cons[currcons].d->vc_sw)#define vcmode (vt_cons[currcons]->vc_mode)#if 0 /* XXX */#define vtmode (vt_cons[currcons]->vt_mode)#define vtpid (vt_cons[currcons]->vt_pid)#define vtnewvt (vt_cons[currcons]->vt_newvt)#endif#define structsize (sizeof(struct vc_data) + sizeof(struct vt_struct))int vc_cons_allocated(unsigned int i){ return (i < MAX_NR_CONSOLES && vc_cons[i].d);}int vc_allocate(unsigned int currcons) /* return 0 on success */{ if (currcons >= MAX_NR_CONSOLES) return -ENODEV; if (!vc_cons[currcons].d) { long p, q; /* prevent users from taking too much memory */ if (currcons >= MAX_NR_USER_CONSOLES && !suser()) return -EPERM; /* due to the granularity of kmalloc, we waste some memory here */ /* the alloc is done in two steps, to optimize the common situation of a 25x80 console (structsize=216, screenbuf_size=4000) */ p = (long) kmalloc(structsize, GFP_KERNEL); if (!p) return -ENOMEM; vc_cons[currcons].d = (struct vc_data *) p; vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data)); /* ++Geert: sw->con_init determines console size */ sw = conswitchp; cons_num = currcons; sw->con_init (vc_cons[currcons].d); size_row = cols<<1; screenbuf_size = rows*size_row; q = (long) kmalloc(screenbuf_size, GFP_KERNEL); if (!q) { kfree_s((char *) p, structsize); vc_cons[currcons].d = NULL; return -ENOMEM; } vc_scrbuf[currcons] = (unsigned short *) q; kmalloced = 1; vc_init (currcons, 1); } return 0;}/* * Change # of rows and columns (0 means the size of fg_console) * [this is to be used together with some user program * like resize that changes the hardware videomode] */int vc_resize(unsigned long lines, unsigned long columns){ unsigned long cc, ll, ss, sr; unsigned long occ, oll, oss, osr; unsigned short *p; unsigned int currcons = fg_console, i; unsigned short *newscreens[MAX_NR_CONSOLES]; long ol, nl, rlth, rrem; cc = (columns ? columns : cols); ll = (lines ? lines : rows); sr = cc << 1; ss = sr * ll; /* * Some earlier version had all consoles of potentially * different sizes, but that was really messy. * So now we only change if there is room for all consoles * of the same size. */ for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) { if (!vc_cons_allocated(currcons)) newscreens[currcons] = 0; else { p = (unsigned short *) kmalloc(ss, GFP_USER); if (!p) { for (i = 0; i< currcons; i++) if (newscreens[i]) kfree_s(newscreens[i], ss); return -ENOMEM; } newscreens[currcons] = p; } }#if 0 /* XXX */ get_scrmem(fg_console);#endif for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) { if (!vc_cons_allocated(currcons)) continue; oll = rows; occ = cols; osr = size_row; oss = screenbuf_size; rows = ll; cols = cc; size_row = sr; screenbuf_size = ss; rlth = MIN(osr, sr); rrem = sr - rlth; ol = origin; nl = (long) newscreens[currcons]; if (ll < oll) ol += (oll - ll) * osr; update_attr(currcons); while (ol < scr_end) { /* ++Geert: TODO: Because the attributes have different meanings on monochrome and color, they should really be converted if can_do_color changes... */ memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth); if (rrem) memsetw((void *)(nl + rlth), video_erase_char, rrem); ol += osr; nl += sr; } if (kmalloced) kfree_s(vc_scrbuf[currcons], oss); vc_scrbuf[currcons] = newscreens[currcons]; kmalloced = 1; screenbuf_size = ss; origin = (long) video_mem_start = vc_scrbuf[currcons]; scr_end = video_mem_end = ((long) video_mem_start) + ss; if (scr_end > nl) memsetw((void *) nl, video_erase_char, scr_end - nl); /* do part of a reset_terminal() */ top = 0; bottom = rows; gotoxy(currcons, x, y); save_cur(currcons); }#if 0 /* XXX */ set_scrmem(fg_console, 0); set_origin(fg_console);#endif /* XXX */ update_screen(fg_console); set_cursor(fg_console); return 0;}/* * ++Geert: Change # of rows and columns for one specific console. * Of course it's not messy to have all consoles of potentially different sizes, * except on PCish hardware :-) * * This is called by the low level console driver (arch/m68k/console/fbcon.c or * arch/m68k/console/txtcon.c) */void vc_resize_con(unsigned long lines, unsigned long columns, unsigned int currcons){ unsigned long cc, ll, ss, sr; unsigned long occ, oll, oss, osr; unsigned short *newscreen; long ol, nl, rlth, rrem; struct winsize ws; if (!columns || !lines || currcons >= MAX_NR_CONSOLES) return; cc = columns; ll = lines; sr = cc << 1; ss = sr * ll; if (!vc_cons_allocated(currcons)) newscreen = 0; else if (!(newscreen = (unsigned short *) kmalloc(ss, GFP_USER))) return; if (vc_cons_allocated(currcons)) { oll = rows; occ = cols; osr = size_row; oss = screenbuf_size; rows = ll; cols = cc; size_row = sr; screenbuf_size = ss; rlth = MIN(osr, sr); rrem = sr - rlth; ol = origin; nl = (long) newscreen; if (ll < oll) ol += (oll - ll) * osr; update_attr(currcons); while (ol < scr_end) { /* ++Geert: TODO: Because the attributes have different meanings on monochrome and color, they should really be converted if can_do_color changes... */ memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth); if (rrem) memsetw((void *)(nl + rlth), video_erase_char, rrem); ol += osr; nl += sr; } if (kmalloced) kfree_s(vc_scrbuf[currcons], oss); vc_scrbuf[currcons] = newscreen; kmalloced = 1; screenbuf_size = ss; origin = (long) video_mem_start = vc_scrbuf[currcons]; scr_end = video_mem_end = ((long)video_mem_start) + ss; if (scr_end > nl) memsetw((void *) nl, video_erase_char, scr_end - nl); /* do part of a reset_terminal() */ top = 0; bottom = rows; gotoxy(currcons, x, y); save_cur(currcons); ws.ws_row = rows; ws.ws_col = cols; if (memcmp(&ws, &console_table[currcons]->winsize, sizeof (struct winsize)) && console_table[currcons]->pgrp > 0) kill_pg(console_table[currcons]->pgrp, SIGWINCH, 1); console_table[currcons]->winsize = ws; } if (currcons == fg_console && vt_cons[fg_console]->vc_mode == KD_TEXT) update_screen(fg_console);}void vc_disallocate(unsigned int currcons){ if (vc_cons_allocated(currcons)) { if (kmalloced) kfree_s(vc_scrbuf[currcons], screenbuf_size); if (currcons >= MIN_NR_CONSOLES) kfree_s(vc_cons[currcons].d, structsize); vc_cons[currcons].d = 0; }}#define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)#define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)#define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)#define decarm VC_REPEAT#define decckm VC_CKMODE#define kbdapplic VC_APPLIC#define lnm VC_CRLF/* * this is what the terminal answers to a ESC-Z or csi0c query. */#define VT100ID "\033[?1;2c"#define VT102ID "\033[?6c"static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7, 8,12,10,14, 9,13,11,15 };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -