📄 console.h
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/kernel/console.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13600 /* Code and data for the IBM console driver.
13601 *
13602 * The 6845 video controller used by the IBM PC shares its video memory with
13603 * the CPU somewhere in the 0xB0000 memory bank. To the 6845 this memory
13604 * consists of 16-bit words. Each word has a character code in the low byte
13605 * and a so-called attribute byte in the high byte. The CPU directly modifies
13606 * video memory to display characters, and sets two registers on the 6845 that
13607 * specify the video origin and the cursor position. The video origin is the
13608 * place in video memory where the first character (upper left corner) can
13609 * be found. Moving the origin is a fast way to scroll the screen. Some
13610 * video adapters wrap around the top of video memory, so the origin can
13611 * move without bounds. For other adapters screen memory must sometimes be
13612 * moved to reset the origin. All computations on video memory use character
13613 * (word) addresses for simplicity and assume there is no wrapping. The
13614 * assembly support functions translate the word addresses to byte addresses
13615 * and the scrolling function worries about wrapping.
13616 */
13617
13618 #include "kernel.h"
13619 #include <termios.h>
13620 #include <minix/callnr.h>
13621 #include <minix/com.h>
13622 #include "protect.h"
13623 #include "tty.h"
13624 #include "proc.h"
13625
13626 /* Definitions used by the console driver. */
13627 #define MONO_BASE 0xB0000L /* base of mono video memory */
13628 #define COLOR_BASE 0xB8000L /* base of color video memory */
13629 #define MONO_SIZE 0x1000 /* 4K mono video memory */
13630 #define COLOR_SIZE 0x4000 /* 16K color video memory */
13631 #define EGA_SIZE 0x8000 /* EGA & VGA have at least 32K */
13632 #define BLANK_COLOR 0x0700 /* determines cursor color on blank screen */
13633 #define SCROLL_UP 0 /* scroll forward */
13634 #define SCROLL_DOWN 1 /* scroll backward */
13635 #define BLANK_MEM ((u16_t *) 0) /* tells mem_vid_copy() to blank the screen */
13636 #define CONS_RAM_WORDS 80 /* video ram buffer size */
13637 #define MAX_ESC_PARMS 2 /* number of escape sequence params allowed */
13638
13639 /* Constants relating to the controller chips. */
13640 #define M_6845 0x3B4 /* port for 6845 mono */
13641 #define C_6845 0x3D4 /* port for 6845 color */
13642 #define EGA 0x3C4 /* port for EGA or VGA card */
13643 #define INDEX 0 /* 6845's index register */
13644 #define DATA 1 /* 6845's data register */
13645 #define VID_ORG 12 /* 6845's origin register */
13646 #define CURSOR 14 /* 6845's cursor register */
13647
13648 /* Beeper. */
13649 #define BEEP_FREQ 0x0533 /* value to put into timer to set beep freq */
13650 #define B_TIME 3 /* length of CTRL-G beep is ticks */
13651
13652 /* definitions used for font management */
13653 #define GA_SEQUENCER_INDEX 0x3C4
13654 #define GA_SEQUENCER_DATA 0x3C5
13655 #define GA_GRAPHICS_INDEX 0x3CE
13656 #define GA_GRAPHICS_DATA 0x3CF
13657 #define GA_VIDEO_ADDRESS 0xA0000L
13658 #define GA_FONT_SIZE 8192
13659
13660 /* Global variables used by the console driver. */
13661 PUBLIC unsigned vid_seg; /* video ram selector (0xB0000 or 0xB8000) */
13662 PUBLIC unsigned vid_size; /* 0x2000 for color or 0x0800 for mono */
13663 PUBLIC unsigned vid_mask; /* 0x1FFF for color or 0x07FF for mono */
13664 PUBLIC unsigned blank_color = BLANK_COLOR; /* display code for blank */
13665
13666 /* Private variables used by the console driver. */
13667 PRIVATE int vid_port; /* I/O port for accessing 6845 */
13668 PRIVATE int wrap; /* hardware can wrap? */
13669 PRIVATE int softscroll; /* 1 = software scrolling, 0 = hardware */
13670 PRIVATE unsigned vid_base; /* base of video ram (0xB000 or 0xB800) */
13671 PRIVATE int beeping; /* speaker is beeping? */
13672 #define scr_width 80 /* # characters on a line */
13673 #define scr_lines 25 /* # lines on the screen */
13674 #define scr_size (80*25) /* # characters on the screen */
13675
13676 /* Per console data. */
13677 typedef struct console {
13678 tty_t *c_tty; /* associated TTY struct */
13679 int c_column; /* current column number (0-origin) */
13680 int c_row; /* current row (0 at top of screen) */
13681 int c_rwords; /* number of WORDS (not bytes) in outqueue */
13682 unsigned c_start; /* start of video memory of this console */
13683 unsigned c_limit; /* limit of this console's video memory */
13684 unsigned c_org; /* location in RAM where 6845 base points */
13685 unsigned c_cur; /* current position of cursor in video RAM */
13686 unsigned c_attr; /* character attribute */
13687 unsigned c_blank; /* blank attribute */
13688 char c_esc_state; /* 0=normal, 1=ESC, 2=ESC[ */
13689 char c_esc_intro; /* Distinguishing character following ESC */
13690 int *c_esc_parmp; /* pointer to current escape parameter */
13691 int c_esc_parmv[MAX_ESC_PARMS]; /* list of escape parameters */
13692 u16_t c_ramqueue[CONS_RAM_WORDS]; /* buffer for video RAM */
13693 } console_t;
13694
13695 PRIVATE int nr_cons= 1; /* actual number of consoles */
13696 PRIVATE console_t cons_table[NR_CONS];
13697 PRIVATE console_t *curcons; /* currently visible */
13698
13699 /* Color if using a color controller. */
13700 #define color (vid_port == C_6845)
13701
13702 /* Map from ANSI colors to the attributes used by the PC */
13703 PRIVATE int ansi_colors[8] = {0, 4, 2, 6, 1, 5, 3, 7};
13704
13705 /* Structure used for font management */
13706 struct sequence {
13707 unsigned short index;
13708 unsigned char port;
13709 unsigned char value;
13710 };
13711
13712 FORWARD _PROTOTYPE( void cons_write, (struct tty *tp) );
13713 FORWARD _PROTOTYPE( void cons_echo, (tty_t *tp, int c) );
13714 FORWARD _PROTOTYPE( void out_char, (console_t *cons, int c) );
13715 FORWARD _PROTOTYPE( void beep, (void) );
13716 FORWARD _PROTOTYPE( void do_escape, (console_t *cons, int c) );
13717 FORWARD _PROTOTYPE( void flush, (console_t *cons) );
13718 FORWARD _PROTOTYPE( void parse_escape, (console_t *cons, int c) );
13719 FORWARD _PROTOTYPE( void scroll_screen, (console_t *cons, int dir) );
13720 FORWARD _PROTOTYPE( void set_6845, (int reg, unsigned val) );
13721 FORWARD _PROTOTYPE( void stop_beep, (void) );
13722 FORWARD _PROTOTYPE( void cons_org0, (void) );
13723 FORWARD _PROTOTYPE( void ga_program, (struct sequence *seq) );
13724
13725
13726 /*===========================================================================*
13727 * cons_write *
13728 *===========================================================================*/
13729 PRIVATE void cons_write(tp)
13730 register struct tty *tp; /* tells which terminal is to be used */
13731 {
13732 /* Copy as much data as possible to the output queue, then start I/O. On
13733 * memory-mapped terminals, such as the IBM console, the I/O will also be
13734 * finished, and the counts updated. Keep repeating until all I/O done.
13735 */
13736
13737 int count;
13738 register char *tbuf;
13739 char buf[64];
13740 phys_bytes user_phys;
13741 console_t *cons = tp->tty_priv;
13742
13743 /* Check quickly for nothing to do, so this can be called often without
13744 * unmodular tests elsewhere.
13745 */
13746 if ((count = tp->tty_outleft) == 0 || tp->tty_inhibited) return;
13747
13748 /* Copy the user bytes to buf[] for decent addressing. Loop over the
13749 * copies, since the user buffer may be much larger than buf[].
13750 */
13751 do {
13752 if (count > sizeof(buf)) count = sizeof(buf);
13753 user_phys = proc_vir2phys(proc_addr(tp->tty_outproc), tp->tty_out_vir);
13754 phys_copy(user_phys, vir2phys(buf), (phys_bytes) count);
13755 tbuf = buf;
13756
13757 /* Update terminal data structure. */
13758 tp->tty_out_vir += count;
13759 tp->tty_outcum += count;
13760 tp->tty_outleft -= count;
13761
13762 /* Output each byte of the copy to the screen. Avoid calling
13763 * out_char() for the "easy" characters, put them into the buffer
13764 * directly.
13765 */
13766 do {
13767 if ((unsigned) *tbuf < ' ' || cons->c_esc_state > 0
13768 || cons->c_column >= scr_width
13769 || cons->c_rwords >= buflen(cons->c_ramqueue))
13770 {
13771 out_char(cons, *tbuf++);
13772 } else {
13773 cons->c_ramqueue[cons->c_rwords++] =
13774 cons->c_attr | (*tbuf++ & BYTE);
13775 cons->c_column++;
13776 }
13777 } while (--count != 0);
13778 } while ((count = tp->tty_outleft) != 0 && !tp->tty_inhibited);
13779
13780 flush(cons); /* transfer anything buffered to the screen */
13781
13782 /* Reply to the writer if all output is finished. */
13783 if (tp->tty_outleft == 0) {
13784 tty_reply(tp->tty_outrepcode, tp->tty_outcaller, tp->tty_outproc,
13785 tp->tty_outcum);
13786 tp->tty_outcum = 0;
13787 }
13788 }
13791 /*===========================================================================*
13792 * cons_echo *
13793 *===========================================================================*/
13794 PRIVATE void cons_echo(tp, c)
13795 register tty_t *tp; /* pointer to tty struct */
13796 int c; /* character to be echoed */
13797 {
13798 /* Echo keyboard input (print & flush). */
13799 console_t *cons = tp->tty_priv;
13800
13801 out_char(cons, c);
13802 flush(cons);
13803 }
13806 /*===========================================================================*
13807 * out_char *
13808 *===========================================================================*/
13809 PRIVATE void out_char(cons, c)
13810 register console_t *cons; /* pointer to console struct */
13811 int c; /* character to be output */
13812 {
13813 /* Output a character on the console. Check for escape sequences first. */
13814 if (cons->c_esc_state > 0) {
13815 parse_escape(cons, c);
13816 return;
13817 }
13818
13819 switch(c) {
13820 case 000: /* null is typically used for padding */
13821 return; /* better not do anything */
13822
13823 case 007: /* ring the bell */
13824 flush(cons); /* print any chars queued for output */
13825 beep();
13826 return;
13827
13828 case '\b': /* backspace */
13829 if (--cons->c_column < 0) {
13830 if (--cons->c_row >= 0) cons->c_column += scr_width;
13831 }
13832 flush(cons);
13833 return;
13834
13835 case '\n': /* line feed */
13836 if ((cons->c_tty->tty_termios.c_oflag & (OPOST|ONLCR))
13837 == (OPOST|ONLCR)) {
13838 cons->c_column = 0;
13839 }
13840 /*FALL THROUGH*/
13841 case 013: /* CTRL-K */
13842 case 014: /* CTRL-L */
13843 if (cons->c_row == scr_lines-1) {
13844 scroll_screen(cons, SCROLL_UP);
13845 } else {
13846 cons->c_row++;
13847 }
13848 flush(cons);
13849 return;
13850
13851 case '\r': /* carriage return */
13852 cons->c_column = 0;
13853 flush(cons);
13854 return;
13855
13856 case '\t': /* tab */
13857 cons->c_column = (cons->c_column + TAB_SIZE) & ~TAB_MASK;
13858 if (cons->c_column > scr_width) {
13859 cons->c_column -= scr_width;
13860 if (cons->c_row == scr_lines-1) {
13861 scroll_screen(cons, SCROLL_UP);
13862 } else {
13863 cons->c_row++;
13864 }
13865 }
13866 flush(cons);
13867 return;
13868
13869 case 033: /* ESC - start of an escape sequence */
13870 flush(cons); /* print any chars queued for output */
13871 cons->c_esc_state = 1; /* mark ESC as seen */
13872 return;
13873
13874 default: /* printable chars are stored in ramqueue */
13875 if (cons->c_column >= scr_width) {
13876 if (!LINEWRAP) return;
13877 if (cons->c_row == scr_lines-1) {
13878 scroll_screen(cons, SCROLL_UP);
13879 } else {
13880 cons->c_row++;
13881 }
13882 cons->c_column = 0;
13883 flush(cons);
13884 }
13885 if (cons->c_rwords == buflen(cons->c_ramqueue)) flush(cons);
13886 cons->c_ramqueue[cons->c_rwords++] = cons->c_attr | (c & BYTE);
13887 cons->c_column++; /* next column */
13888 return;
13889 }
13890 }
13893 /*===========================================================================*
13894 * scroll_screen *
13895 *===========================================================================*/
13896 PRIVATE void scroll_screen(cons, dir)
13897 register console_t *cons; /* pointer to console struct */
13898 int dir; /* SCROLL_UP or SCROLL_DOWN */
13899 {
13900 unsigned new_line, new_org, chars;
13901
13902 flush(cons);
13903 chars = scr_size - scr_width; /* one screen minus one line */
13904
13905 /* Scrolling the screen is a real nuisance due to the various incompatible
13906 * video cards. This driver supports software scrolling (Hercules?),
13907 * hardware scrolling (mono and CGA cards) and hardware scrolling without
13908 * wrapping (EGA and VGA cards). In the latter case we must make sure that
13909 * c_start <= c_org && c_org + scr_size <= c_limit
13910 * holds, because EGA and VGA don't wrap around the end of video memory.
13911 */
13912 if (dir == SCROLL_UP) {
13913 /* Scroll one line up in 3 ways: soft, avoid wrap, use origin. */
13914 if (softscroll) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -