📄 console.c
字号:
gotoxy(currcons,0,0); save_cur(currcons); gotoxy(currcons,orig_x,orig_y); update_screen(fg_console); printable = 1; printk("Console: %s %s %ldx%ld, %d virtual consoles\n", can_do_color?"colour":"mono", display_desc, video_num_columns,video_num_lines, NR_CONSOLES); register_console(console_print); return kmem_start;}/* * kbdsave doesn't need to do anything: it's all handled automatically * with the new data structures.. */void kbdsave(int new_console){}static void get_scrmem(int currcons){ memcpy((void *)vc_scrbuf[currcons],(void *)origin, screen_size); video_mem_start = (unsigned long)vc_scrbuf[currcons]; origin = video_mem_start; scr_end = video_mem_end = video_mem_start+screen_size; pos = origin + y*video_size_row + (x<<1);}static void set_scrmem(int currcons){#ifdef CONFIG_HGA /* This works with XFree86 1.2, 1.3 and 2.0 This code could be extended and made more generally useful if we could determine the actual video mode. It appears that this should be possible on a genuine Hercules card, but I (WM) haven't been able to read from any of the required registers on my clone card. */ /* This code should work with Hercules and MDA cards. */ if (video_type == VIDEO_TYPE_MDA) { if (vcmode == KD_TEXT) { /* Ensure that the card is in text mode. */ int i; static char herc_txt_tbl[12] = { 0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c }; outb_p(0, 0x3bf); /* Back to power-on defaults */ outb_p(0, 0x3b8); /* Blank the screen, select page 0, etc */ for ( i = 0 ; i < 12 ; i++ ) { outb_p(i, 0x3b4); outb_p(herc_txt_tbl[i], 0x3b5); } }#define HGA_BLINKER_ON 0x20#define HGA_SCREEN_ON 8 /* Make sure that the hardware is not blanked */ outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8); }#endif CONFIG_HGA video_mem_start = video_mem_base; video_mem_end = video_mem_term; origin = video_mem_start; scr_end = video_mem_start + screen_size; pos = origin + y*video_size_row + (x<<1); memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console], screen_size);}void blank_screen(void){ if (console_blanked) return; timer_table[BLANK_TIMER].fn = unblank_screen; get_scrmem(fg_console); hide_cursor(); console_blanked = 1; memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );}void unblank_screen(void){ if (!console_blanked) return; timer_table[BLANK_TIMER].fn = blank_screen; if (blankinterval) { timer_table[BLANK_TIMER].expires = jiffies + blankinterval; timer_active |= 1<<BLANK_TIMER; } console_blanked = 0; set_scrmem(fg_console); set_origin(fg_console); set_cursor(fg_console);}void update_screen(int new_console){ static int lock = 0; if (new_console == fg_console || lock) return; lock = 1; kbdsave(new_console); get_scrmem(fg_console); fg_console = new_console; set_scrmem(fg_console); set_origin(fg_console); set_cursor(new_console); set_leds(); compute_shiftstate(); lock = 0;}int do_screendump(int arg){ char *sptr, *buf = (char *)arg; int currcons, l; if (!suser()) return -EPERM; l = verify_area(VERIFY_WRITE, buf,2+video_num_columns*video_num_lines); if (l) return l; currcons = get_fs_byte(buf+1); if ((currcons<0) || (currcons>NR_CONSOLES)) return -EIO; put_fs_byte((char)(video_num_lines),buf++); put_fs_byte((char)(video_num_columns),buf++); currcons = (currcons ? currcons-1 : fg_console); sptr = (char *) origin; for (l=video_num_lines*video_num_columns; l>0 ; l--, sptr++) put_fs_byte(*sptr++,buf++); return(0);}/* * All we do is set the write and ioctl subroutines; later on maybe we'll * dynamically allocate the console screen memory. */int con_open(struct tty_struct *tty, struct file * filp){ tty->write = con_write; tty->ioctl = vt_ioctl; if (tty->line > NR_CONSOLES) return -ENODEV; return 0;}#ifdef CONFIG_SELECTION/* correction factor for when screen is hardware-scrolled */#define hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)/* set reverse video on characters s-e of console with selection. */static void highlight(const int currcons, const int s, const int e){ unsigned char *p, *p1, *p2; p1 = (unsigned char *)origin - hwscroll_offset + s + 1; p2 = (unsigned char *)origin - hwscroll_offset + e + 1; if (p1 > p2) { p = p1; p1 = p2; p2 = p; } for (p = p1; p <= p2; p += 2) *p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);}/* is c in range [a-zA-Z0-9_]? */static inline int inword(const char c) { return (isalnum(c) || c == '_'); }/* does screen address p correspond to character at LH/RH edge of screen? */static inline int atedge(const int p){ return (!(p % video_size_row) || !((p + 2) % video_size_row));}/* constrain v such that l <= v <= u */static inline short limit(const int v, const int l, const int u){ return (v < l) ? l : ((v > u) ? u : v);}/* set the current selection. Invoked by ioctl(). */int set_selection(const int arg){ unsigned short *args, xs, ys, xe, ye; int currcons = fg_console; int sel_mode, new_sel_start, new_sel_end, spc; char *bp, *obp, *spos; int i, ps, pe; char *off = (char *)origin - hwscroll_offset; unblank_screen(); args = (unsigned short *)(arg + 1); xs = get_fs_word(args++) - 1; ys = get_fs_word(args++) - 1; xe = get_fs_word(args++) - 1; ye = get_fs_word(args++) - 1; sel_mode = get_fs_word(args); xs = limit(xs, 0, video_num_columns - 1); ys = limit(ys, 0, video_num_lines - 1); xe = limit(xe, 0, video_num_columns - 1); ye = limit(ye, 0, video_num_lines - 1); ps = ys * video_size_row + (xs << 1); pe = ye * video_size_row + (xe << 1); if (ps > pe) /* make sel_start <= sel_end */ { int tmp = ps; ps = pe; pe = tmp; } switch (sel_mode) { case 0: /* character-by-character selection */ default: new_sel_start = ps; new_sel_end = pe; break; case 1: /* word-by-word selection */ spc = isspace(*(off + ps)); for (new_sel_start = ps; ; ps -= 2) { if ((spc && !isspace(*(off + ps))) || (!spc && !inword(*(off + ps)))) break; new_sel_start = ps; if (!(ps % video_size_row)) break; } spc = isspace(*(off + pe)); for (new_sel_end = pe; ; pe += 2) { if ((spc && !isspace(*(off + pe))) || (!spc && !inword(*(off + pe)))) break; new_sel_end = pe; if (!((pe + 2) % video_size_row)) break; } break; case 2: /* line-by-line selection */ new_sel_start = ps - ps % video_size_row; new_sel_end = pe + video_size_row - pe % video_size_row - 2; break; } /* select to end of line if on trailing space */ if (new_sel_end > new_sel_start && !atedge(new_sel_end) && isspace(*(off + new_sel_end))) { for (pe = new_sel_end + 2; ; pe += 2) { if (!isspace(*(off + pe)) || atedge(pe)) break; } if (isspace(*(off + pe))) new_sel_end = pe; } if (sel_cons != currcons) { clear_selection(); sel_cons = currcons; } if (sel_start == -1) /* no current selection */ highlight(sel_cons, new_sel_start, new_sel_end); else if (new_sel_start == sel_start) { if (new_sel_end == sel_end) /* no action required */ return 0; else if (new_sel_end > sel_end) /* extend to right */ highlight(sel_cons, sel_end + 2, new_sel_end); else /* contract from right */ highlight(sel_cons, new_sel_end + 2, sel_end); } else if (new_sel_end == sel_end) { if (new_sel_start < sel_start) /* extend to left */ highlight(sel_cons, new_sel_start, sel_start - 2); else /* contract from left */ highlight(sel_cons, sel_start, new_sel_start - 2); } else /* some other case; start selection from scratch */ { clear_selection(); highlight(sel_cons, new_sel_start, new_sel_end); } sel_start = new_sel_start; sel_end = new_sel_end; obp = bp = sel_buffer; for (i = sel_start; i <= sel_end; i += 2) { spos = (char *)off + i; *bp++ = *spos; if (!isspace(*spos)) obp = bp; if (! ((i + 2) % video_size_row)) { /* strip trailing blanks from line and add newline, unless non-space at end of line. */ if (obp != bp) { bp = obp; *bp++ = '\r'; } obp = bp; } /* check for space, leaving room for next character, possible newline, and null at end. */ if (bp - sel_buffer > SEL_BUFFER_SIZE - 3) break; } *bp = '\0'; return 0;}/* insert the contents of the selection buffer into the queue of the tty associated with the current console. Invoked by ioctl(). */int paste_selection(struct tty_struct *tty){ char *bp = sel_buffer; if (! *bp) return 0; unblank_screen(); while (*bp) { put_tty_queue(*bp, &tty->read_q); bp++; TTY_READ_FLUSH(tty); } return 0;}/* remove the current selection highlight, if any, from the console holding the selection. */static void clear_selection(){ if (sel_start != -1) { highlight(sel_cons, sel_start, sel_end); sel_start = -1; }}#endif /* CONFIG_SELECTION *//* * PIO_FONT support. * * The font loading code goes back to the codepage package by * Joel Hoffman (joel@wam.umd.edu). (He reports that the original * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2 * Video Systems_ by Richard Wilton. 1987. Microsoft Press".) * * Change for certain monochrome monitors by Yury Shevchuck * (sizif@botik.yaroslavl.su). */#define colourmap ((char *)0xa0000)#define blackwmap ((char *)0xb0000)#define cmapsz 8192#define seq_port_reg (0x3c4)#define seq_port_val (0x3c5)#define gr_port_reg (0x3ce)#define gr_port_val (0x3cf)static int set_get_font(char * arg, int set){#ifdef CAN_LOAD_EGA_FONTS int i; char *charmap; int beg; /* no use to "load" CGA... */ if (video_type == VIDEO_TYPE_EGAC) { charmap = colourmap; beg = 0x0e; } else if (video_type == VIDEO_TYPE_EGAM) { charmap = blackwmap; beg = 0x0a; } else return -EINVAL; i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz); if (i) return i; cli(); outb_p( 0x00, seq_port_reg ); /* First, the sequencer */ outb_p( 0x01, seq_port_val ); /* Synchronous reset */ outb_p( 0x02, seq_port_reg ); outb_p( 0x04, seq_port_val ); /* CPU writes only to map 2 */ outb_p( 0x04, seq_port_reg ); outb_p( 0x07, seq_port_val ); /* Sequential addressing */ outb_p( 0x00, seq_port_reg ); outb_p( 0x03, seq_port_val ); /* Clear synchronous reset */ outb_p( 0x04, gr_port_reg ); /* Now, the graphics controller */ outb_p( 0x02, gr_port_val ); /* select map 2 */ outb_p( 0x05, gr_port_reg ); outb_p( 0x00, gr_port_val ); /* disable odd-even addressing */ outb_p( 0x06, gr_port_reg ); outb_p( 0x00, gr_port_val ); /* map start at A000:0000 */ sti(); if (set) for (i=0; i<cmapsz ; i++) *(charmap+i) = get_fs_byte(arg+i); else for (i=0; i<cmapsz ; i++) put_fs_byte(*(charmap+i), arg+i); cli(); outb_p( 0x00, seq_port_reg ); /* Frist, the sequencer */ outb_p( 0x01, seq_port_val ); /* Synchronous reset */ outb_p( 0x02, seq_port_reg ); outb_p( 0x03, seq_port_val ); /* CPU writes to maps 0 and 1 */ outb_p( 0x04, seq_port_reg ); outb_p( 0x03, seq_port_val ); /* odd-even addressing */ outb_p( 0x00, seq_port_reg ); outb_p( 0x03, seq_port_val ); /* clear synchronous reset */ outb_p( 0x04, gr_port_reg ); /* Now, the graphics controller */ outb_p( 0x00, gr_port_val ); /* select map 0 for CPU */ outb_p( 0x05, gr_port_reg ); outb_p( 0x10, gr_port_val ); /* enable even-odd addressing */ outb_p( 0x06, gr_port_reg ); outb_p( beg, gr_port_val ); /* map starts at b800:0 or b000:0 */ sti(); return 0;#else return -EINVAL;#endif}/* * Load font into the EGA/VGA character generator. arg points to a 8192 * byte map, 32 bytes per character. Only first H of them are used for * 8xH fonts (0 < H <= 32). */int con_set_font (char *arg){ return set_get_font (arg,1);}int con_get_font (char *arg){ return set_get_font (arg,0);}/* * Load customizable translation table (USER_TRANS[]). All checks are here, * so we need only include 'return con_set_trans(arg)' in the ioctl handler * arg points to a 256 byte translation table. */int con_set_trans(char * arg){ int i; i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ); if (i) return i; for (i=0; i<E_TABSZ ; i++) USER_TRANS[i] = get_fs_byte(arg+i); USER_TRANS[012]=0; USER_TRANS[014]=0; USER_TRANS[015]=0; USER_TRANS[033]=0; return 0;}int con_get_trans(char * arg){ int i; i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ); if (i) return i; for (i=0; i<E_TABSZ ; i++) put_fs_byte(USER_TRANS[i],arg+i); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -