From bb51f9775a2a016ab99535bc7e080a9353fe2985 Mon Sep 17 00:00:00 2001 From: catfood Date: Sun, 8 Jan 2023 11:12:41 +0800 Subject: [PATCH] add simple console before tty init --- include/console.h | 18 ++- include/tty.h | 6 +- kernel/console.c | 373 ++++++++++------------------------------------ kernel/tty.c | 17 +-- lib/kprintf.c | 5 +- 5 files changed, 103 insertions(+), 316 deletions(-) diff --git a/include/console.h b/include/console.h index 660e185..c36a220 100644 --- a/include/console.h +++ b/include/console.h @@ -17,14 +17,20 @@ /* CONSOLE */ typedef struct s_console { - unsigned int crtc_start; /* set CRTC start addr reg */ - unsigned int orig; /* start addr of the console */ - unsigned int con_size; /* how many words does the console have */ - unsigned int cursor; - int is_full; - unsigned int current_line; + unsigned int row; + unsigned int col; + unsigned int buf_head; // for futher restore after true tty initialized + unsigned int buf_tail; + char *buf; } CONSOLE; +void simpleconsole_init(); +void simpleconsole_write(char* buf, int nr); +void simpleconsole_transfer(void (*write)(char ch)); +void simpleconsole_setcur(int row, int col); + +#define CON_MAX_LOGBUF 1024 + #define SCR_UP 1 /* scroll upward */ #define SCR_DN -1 /* scroll downward */ diff --git a/include/tty.h b/include/tty.h index d770678..6205fc0 100644 --- a/include/tty.h +++ b/include/tty.h @@ -57,6 +57,7 @@ typedef struct n_tty void (*write)(struct n_tty *tty, char ch); int (*read)(struct n_tty *tty, char* buf, int nr); void (*recvbuf)(struct n_tty *tty, u32 ch); + int (*ioctl)(struct n_tty *tty, u32 cmd, long arg); } NTTY; enum CSI_state @@ -104,11 +105,6 @@ typedef struct serial_buf #include "console.h" -void select_console(int nr_console); -void init_screen(TTY *tty); -void out_char(CONSOLE *con, char ch); -int is_current_console(CONSOLE *con); - NTTY *get_tty(const int nr_tty); void vga_tty_init(NTTY *tty); diff --git a/kernel/console.c b/kernel/console.c index 79c4fef..410366b 100644 --- a/kernel/console.c +++ b/kernel/console.c @@ -1,3 +1,4 @@ +// A simple, vga textmode console ready to use before tty init #include "type.h" #include "stdio.h" #include "const.h" @@ -12,175 +13,37 @@ #include "proto.h" #include "x86.h" -/* local routines */ -static void set_cursor(unsigned int position); -static void set_video_start_addr(u32 addr); -static void flush(CONSOLE *con); -static void w_copy(unsigned int dst, const unsigned int src, int size); -static void clear_screen(int pos, int len); -void scroll_screen(CONSOLE *con, int dir); +#define INDEX(row, col) ((row)*SCR_WIDTH + (col)) -/***************************************************************************** - * init_screen - *****************************************************************************/ -/** - * Initialize the console of a certain tty. - * - * @param tty Whose console is to be initialized. - *****************************************************************************/ -void init_screen(TTY *tty) +static char logbuf[CON_MAX_LOGBUF]; +static CONSOLE con = { + .row = 0, + .col = 0, + .buf = logbuf, + .buf_head = 0, + .buf_tail = 0 +}; + +static inline void vga_put_raw(u32 pos, u16 dat) { - int nr_tty = 0; - - tty->console = console_table + nr_tty; - - /* - * NOTE: - * variables related to `position' and `size' below are - * in WORDs, but not in BYTEs. - */ - int v_mem_size = V_MEM_SIZE >> 1; /* size of Video Memory */ - int size_per_con = (v_mem_size / NR_CONSOLES) / 80 * 80; - tty->console->orig = nr_tty * size_per_con; - tty->console->con_size = size_per_con / SCR_WIDTH * SCR_WIDTH; - tty->console->cursor = tty->console->crtc_start = tty->console->orig; - tty->console->is_full = 0; - tty->console->current_line = 0; - - if (nr_tty == 0) - { - tty->console->cursor = disp_pos / 2; - } - const char prompt[] = "[TTY #?]\n"; - - const char *p = prompt; - for (; *p; p++) - { - out_char(tty->console, *p == '?' ? nr_tty + '0' : *p); - } - - set_cursor(tty->console->cursor); + u16 *pch = (u16 *)K_PHY2LIN(V_MEM_BASE) + pos; + *pch = dat; } -static inline void write_char_c(int pos, char ch) +// simple scroll, just abandon those scrolled up +static void scroll() { - u16 *pch = (u16 *)K_PHY2LIN(V_MEM_BASE + pos); - *pch = (0x0f << 8) | ch; -} - -/***************************************************************************** - * out_char - *****************************************************************************/ -/** - * Print a char in a certain console. - * - * @param con The console to which the char is printed. - * @param ch The char to print. - *****************************************************************************/ - -void out_char(CONSOLE *con, char ch) -{ - disable_int(); - - int cursor_x = (con->cursor - con->orig) % SCR_WIDTH; - int cursor_y = (con->cursor - con->orig) / SCR_WIDTH; - - switch (ch) - { - case '\n': - con->cursor = con->orig + SCR_WIDTH * (cursor_y + 1); - break; - case '\b': - if (con->cursor > con->orig) - { - con->cursor--; - //*(pch - 2) = ' '; - //*(pch - 1) = DEFAULT_CHAR_COLOR; - disp_pos = con->cursor * 2; - write_char_c(disp_pos, ' '); + u16* video_mem = (u16 *)K_PHY2LIN(V_MEM_BASE); + for (int i = 0; i < SCR_HEIGHT - 1; ++ i) { + for (int j = 0; j < SCR_WIDTH; ++ j) { + video_mem[INDEX(i, j)] = video_mem[INDEX(i+1, j)]; } - break; - default: - //*pch++ = ch; - //*pch++ = DEFAULT_CHAR_COLOR; - disp_pos = con->cursor * 2; - write_char_c(disp_pos, ch); - con->cursor++; - - break; } - - if (con->cursor - con->orig >= con->con_size) - { - cursor_x = (con->cursor - con->orig) % SCR_WIDTH; - cursor_y = (con->cursor - con->orig) / SCR_WIDTH; - int cp_orig = con->orig + (cursor_y + 1) * SCR_WIDTH - SCR_SIZE; - w_copy(con->orig, cp_orig, SCR_SIZE - SCR_WIDTH); - con->crtc_start = con->orig; - con->cursor = con->orig + (SCR_SIZE - SCR_WIDTH) + cursor_x; - clear_screen(con->cursor, SCR_WIDTH); - if (!con->is_full) - con->is_full = 1; - } - - // assert(con->cursor - con->orig < con->con_size); - - while (con->cursor >= con->crtc_start + SCR_SIZE || - con->cursor < con->crtc_start) - { - scroll_screen(con, SCR_UP); - - clear_screen(con->cursor, SCR_WIDTH); - } - - flush(con); - - enable_int(); -} - -/***************************************************************************** - * clear_screen - *****************************************************************************/ -/** - * Write whitespaces to the screen. - * - * @param pos Write from here. - * @param len How many whitespaces will be written. - *****************************************************************************/ -static void clear_screen(int pos, int len) -{ - u8 *pch = (u8 *)K_PHY2LIN(V_MEM_BASE + pos * 2); - while (--len >= 0) - { - *pch++ = ' '; - *pch++ = (u8)(DEFAULT_CHAR_COLOR >> 8); + for (int j = 0; j < SCR_WIDTH; ++ j) { + video_mem[INDEX(SCR_HEIGHT-1, j)] = BLANK; } } -/***************************************************************************** - * is_current_console - *****************************************************************************/ -/** - * Uses `nr_current_console' to determine if a console is the current one. - * - * @param con Ptr to console. - * - * @return TRUE if con is the current console. - *****************************************************************************/ -int is_current_console(CONSOLE *con) -{ - return (con == &console_table[current_console]); -} - -/***************************************************************************** - * set_cursor - *****************************************************************************/ -/** - * Display the cursor by setting CRTC (6845 compatible) registers. - * - * @param position Position of the cursor based on the beginning of the video - * memory. Note that it counts in WORDs, not in BYTEs. - *****************************************************************************/ static void set_cursor(unsigned int position) { disable_int(); @@ -191,152 +54,78 @@ static void set_cursor(unsigned int position) enable_int(); } -/***************************************************************************** - * set_video_start_addr - *****************************************************************************/ -/** - * Routine for hardware screen scrolling. - * - * @param addr Offset in the video memory. - *****************************************************************************/ -static void set_video_start_addr(u32 addr) +void simpleconsole_init() { - disable_int(); - outb(CRTC_ADDR_REG, START_ADDR_H); - outb(CRTC_DATA_REG, (addr >> 8) & 0xFF); - outb(CRTC_ADDR_REG, START_ADDR_L); - outb(CRTC_DATA_REG, addr & 0xFF); - enable_int(); + con.row = 0; + con.col = 0; + con.buf = logbuf; + con.buf_head = 0; + con.buf_tail = 0; } -/***************************************************************************** - * select_console - *****************************************************************************/ -/** - * Select a console as the current. - * - * @param nr_console Console nr, range in [0, NR_CONSOLES-1]. - *****************************************************************************/ -void select_console(int nr_console) +static void do_console_write(char ch) { - if ((nr_console < 0) || (nr_console >= NR_CONSOLES)) - return; + con.buf[con.buf_tail] = ch; + con.buf_tail = NEXT(con.buf_tail, CON_MAX_LOGBUF); + if (con.buf_head == con.buf_tail) con.buf_head = NEXT(con.buf_head, CON_MAX_LOGBUF); - flush(&console_table[current_console = nr_console]); -} - -/***************************************************************************** - * scroll_screen - *****************************************************************************/ -/** - * Scroll the screen. - * - * Note that scrolling UP means the content of the screen will go upwards, so - * that the user can see lines below the bottom. Similarly scrolling DOWN means - * the content of the screen will go downwards so that the user can see lines - * above the top. - * - * When there is no line below the bottom of the screen, scrolling UP takes no - * effects; when there is no line above the top of the screen, scrolling DOWN - * takes no effects. - * - * @param con The console whose screen is to be scrolled. - * @param dir SCR_UP : scroll the screen upwards; - * SCR_DN : scroll the screen downwards - *****************************************************************************/ -void scroll_screen(CONSOLE *con, int dir) -{ - /* - * variables below are all in-console-offsets (based on con->orig) - */ - int oldest; /* addr of the oldest available line in the console */ - int newest; /* .... .. ... latest ......... .... .. ... ....... */ - int scr_top; /* position of the top of current screen */ - - newest = (con->cursor - con->orig) / SCR_WIDTH * SCR_WIDTH; - oldest = con->is_full ? (newest + SCR_WIDTH) % con->con_size : 0; - scr_top = con->crtc_start - con->orig; - - if (dir == SCR_DN) + switch (ch) { - if (!con->is_full && scr_top > 0) - { - con->crtc_start -= SCR_WIDTH; + case '\n': + con.row ++; + con.col = 0; + if (con.row >= SCR_HEIGHT) { + scroll(); + con.row --; } - else if (con->is_full && scr_top != oldest) - { - if (con->cursor - con->orig >= con->con_size - SCR_SIZE) - { - if (con->crtc_start != con->orig) - con->crtc_start -= SCR_WIDTH; - } - else if (con->crtc_start == con->orig) - { - scr_top = con->con_size - SCR_SIZE; - con->crtc_start = con->orig + scr_top; - } - else - { - con->crtc_start -= SCR_WIDTH; - } + break; + case '\r': + con.col = 0; + break; + case '\b': + if (con.col == 0) { + if (con.row) con.row --; + con.col = SCR_WIDTH - 1; } - } - else if (dir == SCR_UP) - { - if (!con->is_full && newest >= scr_top + SCR_SIZE) - { - con->crtc_start += SCR_WIDTH; + else { + con.col --; } - else if (con->is_full && scr_top + SCR_SIZE - SCR_WIDTH != newest) - { - if (scr_top + SCR_SIZE == con->con_size) - con->crtc_start = con->orig; - else - con->crtc_start += SCR_WIDTH; + break; + default: + vga_put_raw(INDEX(con.row, con.col), MAKE_CELL(DEFAULT_CHAR_COLOR, ch)); + con.col ++; + if (con.col >= SCR_WIDTH) { + con.col = 0; + con.row ++; } - } - else - { - // assert(dir == SCR_DN || dir == SCR_UP); - } - flush(con); -} - -/***************************************************************************** - * flush - *****************************************************************************/ -/** - * Set the cursor and starting address of a console by writing the - * CRT Controller Registers. - * - * @param con The console to be set. - *****************************************************************************/ -static void flush(CONSOLE *con) -{ - if (is_current_console(con)) - { - set_cursor(con->cursor); - set_video_start_addr(con->crtc_start); + if (con.row >= SCR_HEIGHT) { + scroll(); + con.row --; + } + break; } } -/***************************************************************************** - * w_copy - *****************************************************************************/ -/** - * Copy data in WORDS. - * - * Note that the addresses of dst and src are not pointers, but integers, 'coz - * in most cases we pass integers into it as parameters. - * - * @param dst Addr of destination. - * @param src Addr of source. - * @param size How many words will be copied. - *****************************************************************************/ -static void w_copy(unsigned int dst, const unsigned int src, int size) +void simpleconsole_write(char* buf, int nr) { - memcpy((void *)(V_MEM_BASE + (dst << 1)), - (void *)(V_MEM_BASE + (src << 1)), - size << 1); + while (nr --) { + do_console_write(*buf ++); + } + set_cursor(INDEX(con.row, con.col)); +} + +void simpleconsole_transfer(void (*write)(char ch)) +{ + int i = con.buf_head; + while (i != con.buf_tail) { + write(con.buf[i]); + i = NEXT(i, CON_MAX_LOGBUF); + } +} + +void simpleconsole_setcur(int row, int col) { + con.row = max(0, min(row, SCR_HEIGHT-1)); + con.col = max(0, min(row, SCR_WIDTH-1)); + set_cursor(INDEX(con.row, con.col)); } \ No newline at end of file diff --git a/kernel/tty.c b/kernel/tty.c index 2bf888b..d3ddc84 100644 --- a/kernel/tty.c +++ b/kernel/tty.c @@ -19,15 +19,13 @@ int tty_ok = 0; void tty_write(NTTY *tty, char *buf, int len); int tty_read(NTTY *tty, char *buf, int len); -static void tty_mouse(TTY *tty); -static void tty_dev_read(TTY *tty); -static void tty_dev_write(TTY *tty); -static void put_key(TTY *tty, u32 key); - - NTTY* cur_ntty; NTTY* ntty_table[NR_CONSOLES]; +static void write_default_tty(char ch) { + cur_ntty->write(cur_ntty, ch); +} + inline NTTY* get_tty(const int nr_tty) { return ntty_table[nr_tty]; } @@ -65,6 +63,7 @@ void init_tty_main() } cur_ntty = ntty_table[0]; tty_ok = 1; + simpleconsole_transfer(write_default_tty); kprintf("TTY initialized\n"); } @@ -97,10 +96,8 @@ void task_tty() void tty_write(NTTY *tty, char *buf, int len) { if (!tty_ok) { - while (--len >= 0) - { - write_serial(*buf++); - } + simpleconsole_write(buf, len); + // while (--len >= 0) write_serial(*buf++); return; } else if (tty->driver_type == 1) { diff --git a/lib/kprintf.c b/lib/kprintf.c index 6ac9651..c92dba6 100644 --- a/lib/kprintf.c +++ b/lib/kprintf.c @@ -6,7 +6,7 @@ #include "tty.h" #include "serialport.h" -static void serialputch(int ch, int *cnt) +static void kprintfputch(int ch, int *cnt) { // write_serial(ch); char _ch = ch; @@ -17,9 +17,8 @@ static void serialputch(int ch, int *cnt) int vkprintf(const char *fmt, va_list ap) { - // vprintfmt((void*)kprintfputch, NULL, fmt, ap); int cnt = 0; - vprintfmt((void *)serialputch, &cnt, fmt, ap); + vprintfmt((void *)kprintfputch, &cnt, fmt, ap); return 0; }