📄 console.c
字号:
/* * linux/kernel/console.c * * (C) 1991 Linus Torvalds *//* * console.c * * This module implements the console io functions * 'void con_init(void)' * 'void con_write(struct tty_queue * queue)' * 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. *//* * 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. *//* * Code to check for different video-cards mostly by Galen Hunt, * <g-hunt@ee.utah.edu> */#include <linux/sched.h>#include <linux/tty.h>#include <linux/config.h>#include <linux/kernel.h>#include <asm/io.h>#include <asm/system.h>#include <asm/segment.h>#include <string.h>#include <errno.h>#define DEF_TERMIOS \(struct termios) { \ ICRNL, \ OPOST | ONLCR, \ 0, \ IXON | ISIG | ICANON | ECHO | ECHOCTL | ECHOKE, \ 0, \ INIT_C_CC \}/* * These are set up by the setup-routine at boot-time: */#define ORIG_X (*(unsigned char *)0x90000)#define ORIG_Y (*(unsigned char *)0x90001)#define ORIG_VIDEO_PAGE (*(unsigned short *)0x90004)#define ORIG_VIDEO_MODE ((*(unsigned short *)0x90006) & 0xff)#define ORIG_VIDEO_COLS (((*(unsigned short *)0x90006) & 0xff00) >> 8)#define ORIG_VIDEO_LINES ((*(unsigned short *)0x9000e) & 0xff)#define ORIG_VIDEO_EGA_AX (*(unsigned short *)0x90008)#define ORIG_VIDEO_EGA_BX (*(unsigned short *)0x9000a)#define ORIG_VIDEO_EGA_CX (*(unsigned short *)0x9000c)#define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */#define VIDEO_TYPE_CGA 0x11 /* CGA Display */#define VIDEO_TYPE_EGAM 0x20 /* EGA/VGA in Monochrome Mode */#define VIDEO_TYPE_EGAC 0x21 /* EGA/VGA in Color Mode */#define NPAR 16int NR_CONSOLES = 0;extern void keyboard_interrupt(void);static unsigned char video_type; /* Type of display being used */static unsigned long video_num_columns; /* Number of text columns */static unsigned long video_mem_base; /* Base of video memory */static unsigned long video_mem_term; /* End of video memory */static unsigned long video_size_row; /* Bytes per row */static unsigned long video_num_lines; /* Number of test lines */static unsigned char video_page; /* Initial video page */static unsigned short video_port_reg; /* Video register select port */static unsigned short video_port_val; /* Video register value port */static int can_do_colour = 0;static struct { unsigned short vc_video_erase_char; unsigned char vc_attr; unsigned char vc_def_attr; int vc_bold_attr; unsigned long vc_ques; unsigned long vc_state; unsigned long vc_restate; unsigned long vc_checkin; unsigned long vc_origin; /* Used for EGA/VGA fast scroll */ unsigned long vc_scr_end; /* Used for EGA/VGA fast scroll */ unsigned long vc_pos; unsigned long vc_x,vc_y; unsigned long vc_top,vc_bottom; unsigned long vc_npar,vc_par[NPAR]; unsigned long vc_video_mem_start; /* Start of video RAM */ unsigned long vc_video_mem_end; /* End of video RAM (sort of) */ unsigned int vc_saved_x; unsigned int vc_saved_y; unsigned int vc_iscolor; char * vc_translate;} vc_cons [MAX_CONSOLES];#define origin (vc_cons[currcons].vc_origin)#define scr_end (vc_cons[currcons].vc_scr_end)#define pos (vc_cons[currcons].vc_pos)#define top (vc_cons[currcons].vc_top)#define bottom (vc_cons[currcons].vc_bottom)#define x (vc_cons[currcons].vc_x)#define y (vc_cons[currcons].vc_y)#define state (vc_cons[currcons].vc_state)#define restate (vc_cons[currcons].vc_restate)#define checkin (vc_cons[currcons].vc_checkin)#define npar (vc_cons[currcons].vc_npar)#define par (vc_cons[currcons].vc_par)#define ques (vc_cons[currcons].vc_ques)#define attr (vc_cons[currcons].vc_attr)#define saved_x (vc_cons[currcons].vc_saved_x)#define saved_y (vc_cons[currcons].vc_saved_y)#define translate (vc_cons[currcons].vc_translate)#define video_mem_start (vc_cons[currcons].vc_video_mem_start)#define video_mem_end (vc_cons[currcons].vc_video_mem_end)#define def_attr (vc_cons[currcons].vc_def_attr)#define video_erase_char (vc_cons[currcons].vc_video_erase_char) #define iscolor (vc_cons[currcons].vc_iscolor)int blankinterval = 0;int blankcount = 0;static void sysbeep(void);/* * this is what the terminal answers to a ESC-Z or csi0c * query (= vt100 response). */#define RESPONSE "\033[?1;2c"static char * translations[] = {/* normal 7-bit ascii */ " !\"#$%&'()*+,-./0123456789:;<=>?" "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" "`abcdefghijklmnopqrstuvwxyz{|}~ ",/* vt100 graphics */ " !\"#$%&'()*+,-./0123456789:;<=>?" "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ " "\004\261\007\007\007\007\370\361\007\007\275\267\326\323\327\304" "\304\304\304\304\307\266\320\322\272\363\362\343\\007\234\007 "};#define NORM_TRANS (translations[0])#define GRAF_TRANS (translations[1])/* NOTE! gotoxy thinks x==video_num_columns is ok */static inline void gotoxy(int currcons, int new_x,unsigned int new_y){ if (new_x > video_num_columns || new_y >= video_num_lines) return; x = new_x; y = new_y; pos = origin + y*video_size_row + (x<<1);}static inline void set_origin(int currcons){ if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM) return; if (currcons != fg_console) return; cli(); outb_p(12, video_port_reg); outb_p(0xff&((origin-video_mem_base)>>9), video_port_val); outb_p(13, video_port_reg); outb_p(0xff&((origin-video_mem_base)>>1), video_port_val); sti();}static void scrup(int currcons){ if (bottom<=top) return; if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM) { if (!top && bottom == video_num_lines) { origin += video_size_row; pos += video_size_row; scr_end += video_size_row; if (scr_end > video_mem_end) { __asm__("cld\n\t" "rep\n\t" "movsl\n\t" "movl _video_num_columns,%1\n\t" "rep\n\t" "stosw" ::"a" (video_erase_char), "c" ((video_num_lines-1)*video_num_columns>>1), "D" (video_mem_start), "S" (origin) :"cx","di","si"); scr_end -= origin-video_mem_start; pos -= origin-video_mem_start; origin = video_mem_start; } else { __asm__("cld\n\t" "rep\n\t" "stosw" ::"a" (video_erase_char), "c" (video_num_columns), "D" (scr_end-video_size_row) :"cx","di"); } set_origin(currcons); } else { __asm__("cld\n\t" "rep\n\t" "movsl\n\t" "movl _video_num_columns,%%ecx\n\t" "rep\n\t" "stosw" ::"a" (video_erase_char), "c" ((bottom-top-1)*video_num_columns>>1), "D" (origin+video_size_row*top), "S" (origin+video_size_row*(top+1)) :"cx","di","si"); } } else /* Not EGA/VGA */ { __asm__("cld\n\t" "rep\n\t" "movsl\n\t" "movl _video_num_columns,%%ecx\n\t" "rep\n\t" "stosw" ::"a" (video_erase_char), "c" ((bottom-top-1)*video_num_columns>>1), "D" (origin+video_size_row*top), "S" (origin+video_size_row*(top+1)) :"cx","di","si"); }}static void scrdown(int currcons){ if (bottom <= top) return; if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM) { __asm__("std\n\t" "rep\n\t" "movsl\n\t" "addl $2,%%edi\n\t" /* %edi has been decremented by 4 */ "movl _video_num_columns,%%ecx\n\t" "rep\n\t" "stosw" ::"a" (video_erase_char), "c" ((bottom-top-1)*video_num_columns>>1), "D" (origin+video_size_row*bottom-4), "S" (origin+video_size_row*(bottom-1)-4) :"ax","cx","di","si"); } else /* Not EGA/VGA */ { __asm__("std\n\t" "rep\n\t" "movsl\n\t" "addl $2,%%edi\n\t" /* %edi has been decremented by 4 */ "movl _video_num_columns,%%ecx\n\t" "rep\n\t" "stosw" ::"a" (video_erase_char), "c" ((bottom-top-1)*video_num_columns>>1), "D" (origin+video_size_row*bottom-4), "S" (origin+video_size_row*(bottom-1)-4) :"ax","cx","di","si"); }}static void lf(int currcons){ if (y+1<bottom) { y++; pos += video_size_row; return; } scrup(currcons);}static void ri(int currcons){ if (y>top) { y--; pos -= video_size_row; return; } scrdown(currcons);}static void cr(int currcons){ pos -= x<<1; x=0;}static void del(int currcons){ if (x) { pos -= 2; x--; *(unsigned short *)pos = video_erase_char; }}static void csi_J(int currcons, int vpar){ long count __asm__("cx"); long start __asm__("di"); switch (vpar) { case 0: /* erase from cursor to end of display */ count = (scr_end-pos)>>1; start = pos; break; case 1: /* erase from start to cursor */ count = (pos-origin)>>1; start = origin; break; case 2: /* erase whole display */ count = video_num_columns * video_num_lines; start = origin; break; default: return; } __asm__("cld\n\t" "rep\n\t" "stosw\n\t" ::"c" (count), "D" (start),"a" (video_erase_char) :"cx","di");}static void csi_K(int currcons, int vpar){ long count __asm__("cx"); long start __asm__("di"); switch (vpar) { case 0: /* erase from cursor to end of line */ if (x>=video_num_columns) return; count = video_num_columns-x; start = pos; break; case 1: /* erase from start of line to cursor */ start = pos - (x<<1); count = (x<video_num_columns)?x:video_num_columns; break; case 2: /* erase whole line */ start = pos - (x<<1); count = video_num_columns; break; default: return; } __asm__("cld\n\t" "rep\n\t" "stosw\n\t" ::"c" (count), "D" (start),"a" (video_erase_char) :"cx","di");}void csi_m(int currcons ){ int i; for (i=0;i<=npar;i++) switch (par[i]) { case 0: attr=def_attr;break; /* default */ case 1: attr=(iscolor?attr|0x08:attr|0x0f);break; /* bold */ /*case 4: attr=attr|0x01;break;*/ /* underline */ case 4: /* bold */ if (!iscolor) attr |= 0x01; else { /* check if forground == background */ if (vc_cons[currcons].vc_bold_attr != -1) attr = (vc_cons[currcons].vc_bold_attr&0x0f)|(0xf0&(attr)); else { short newattr = (attr&0xf0)|(0xf&(~attr)); attr = ((newattr&0xf)==((attr>>4)&0xf)? (attr&0xf0)|(((attr&0xf)+1)%0xf): newattr); } } break; case 5: attr=attr|0x80;break; /* blinking */ case 7: attr=(attr<<4)|(attr>>4);break; /* negative */ case 22: attr=attr&0xf7;break; /* not bold */ case 24: attr=attr&0xfe;break; /* not underline */ case 25: attr=attr&0x7f;break; /* not blinking */ case 27: attr=def_attr;break; /* positive image */ case 39: attr=(attr & 0xf0)|(def_attr & 0x0f); break; case 49: attr=(attr & 0x0f)|(def_attr & 0xf0); break; default: if (!can_do_colour) break; iscolor = 1; if ((par[i]>=30) && (par[i]<=38)) attr = (attr & 0xf0) | (par[i]-30); else /* Background color */ if ((par[i]>=40) && (par[i]<=48)) attr = (attr & 0x0f) | ((par[i]-40)<<4); else break; }}static inline void set_cursor(int currcons){ blankcount = blankinterval; if (currcons != fg_console) return; cli(); outb_p(14, video_port_reg); outb_p(0xff&((pos-video_mem_base)>>9), video_port_val); outb_p(15, video_port_reg); outb_p(0xff&((pos-video_mem_base)>>1), video_port_val); sti();}static inline void hide_cursor(int currcons){ outb_p(14, video_port_reg); outb_p(0xff&((scr_end-video_mem_base)>>9), video_port_val); outb_p(15, video_port_reg); outb_p(0xff&((scr_end-video_mem_base)>>1), video_port_val);}static void respond(int currcons, struct tty_struct * tty){ char * p = RESPONSE; cli(); while (*p) { PUTCH(*p,tty->read_q); p++; } sti(); copy_to_cooked(tty);}static void insert_char(int currcons){ int i=x; unsigned short tmp, old = video_erase_char; unsigned short * p = (unsigned short *) pos; while (i++<video_num_columns) { tmp=*p; *p=old; old=tmp; p++; }}static void insert_line(int currcons){ int oldtop,oldbottom; oldtop=top; oldbottom=bottom; top=y; bottom = video_num_lines; scrdown(currcons); top=oldtop; bottom=oldbottom;}static void delete_char(int currcons){ int i; unsigned short * p = (unsigned short *) pos; if (x>=video_num_columns) return; i = x; while (++i < video_num_columns) { *p = *(p+1); p++; } *p = video_erase_char;}static void delete_line(int currcons){ int oldtop,oldbottom; oldtop=top; oldbottom=bottom; top=y; bottom = video_num_lines;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -