diff --git a/include/console.h b/include/console.h index 783ca48..83c4989 100644 --- a/include/console.h +++ b/include/console.h @@ -30,12 +30,16 @@ typedef struct s_console #define SCR_UP 1 /* scroll upward */ #define SCR_DN -1 /* scroll downward */ -#define SCR_SIZE (80 * 25) #define SCR_WIDTH 80 +#define SCR_HEIGHT 25 +#define SCR_SIZE (SCR_HEIGHT * SCR_WIDTH) +#define SCR_BUFSIZE (8 * SCR_SIZE) +#define SCR_MAXLINE (SCR_BUFSIZE / SCR_WIDTH) -#define DEFAULT_CHAR_COLOR (MAKE_COLOR(BLACK, WHITE)) +#define DEFAULT_CHAR_COLOR (MAKE_COLOR(BLACK, WHITE | BRIGHT)) #define GRAY_CHAR (MAKE_COLOR(BLACK, BLACK) | BRIGHT) #define RED_CHAR (MAKE_COLOR(BLUE, RED) | BRIGHT) - +#define MAKE_CELL(clr, ch) ((clr << 8) | ch) +#define BLANK MAKE_CELL(DEFAULT_CHAR_COLOR, ' ') #endif /* _ORANGES_CONSOLE_H_ */ \ No newline at end of file diff --git a/include/const.h b/include/const.h index 284d050..ea8fc01 100644 --- a/include/const.h +++ b/include/const.h @@ -20,10 +20,13 @@ */ //added by mingxuan 2019-5-19 #define BLACK 0x0 /* 0000 */ -#define WHITE 0x7 /* 0111 */ -#define RED 0x4 /* 0100 */ -#define GREEN 0x2 /* 0010 */ #define BLUE 0x1 /* 0001 */ +#define GREEN 0x2 /* 0010 */ +#define CYAN 0x3 +#define RED 0x4 /* 0100 */ +#define MAGENTA 0x5 +#define BROWN 0x6 /* yellow = bright brown, which is 0xe*/ +#define WHITE 0x7 /* 0111 actually its light grey, white = bright light grey*/ #define FLASH 0x80 /* 1000 0000 */ #define BRIGHT 0x08 /* 0000 1000 */ #define MAKE_COLOR(x,y) ((x<<4) | y) /* MAKE_COLOR(Background,Foreground) */ @@ -180,5 +183,5 @@ //added by mingxuan 2019-5-19 #define max(a,b) ((a) > (b) ? (a) : (b)) #define min(a,b) ((a) < (b) ? (a) : (b)) - +#define abs(a) ((a) < 0 ? -(a) : (a)) #endif /* _ORANGES_CONST_H_ */ diff --git a/include/proto.h b/include/proto.h index f4379c3..daf4d29 100644 --- a/include/proto.h +++ b/include/proto.h @@ -49,6 +49,7 @@ void in_process(TTY* p_tty,u32 key); void task_tty(); void tty_write(TTY* tty, char* buf, int len); int tty_read(TTY* tty, char* buf, int len); +void init_tty_main(); /* printf.c */ //added by mingxuan 2019-5-19 diff --git a/include/tty.h b/include/tty.h index ec19b39..8b532eb 100644 --- a/include/tty.h +++ b/include/tty.h @@ -49,6 +49,38 @@ typedef struct s_tty struct s_console * console; }TTY; +typedef struct MouseState{ + u8 mouse_lb; + u8 mouse_mb; + u8 mouse_rb; + signed char mouse_scroll; + int mouse_x; + int mouse_y; +} MouseState; + +typedef struct n_tty { + int driver_type; // 1-vga&kbd; 2-serial + MouseState mouse; + void* input_buf; + void* output_buf; +} NTTY; + +typedef struct vga_buf { + void* buf; // 2d array, screen size, for text mode it's [maxline][80] + int max_line; // to support scroll, max line should be a lot more than screen + int scr_top_line; // the index in buf of top line on screen; + int scr_cur_line; // the index in buf of the cursor's line + int head_line; // for circular buffer use + int cur_row; + int cur_col; // cursor position, on screen +} vga_buf; + +typedef struct keyboard_buf { + void* buf; // 1d array, buffer input virtual line, works as a ldisc + int max_buf; + int tail; +} keyboard_buf; + #include "console.h" void select_console(int nr_console); @@ -60,4 +92,8 @@ int init_serial(); char read_serial(); void write_serial(char a); +void vga_tty_init(NTTY* tty); +void vga_tty_write(NTTY* tty, char ch); +void vga_tty_flush(NTTY* tty); + #endif /* _ORANGES_TTY_H_ */ \ No newline at end of file diff --git a/kernel/Makefrag b/kernel/Makefrag index eb250a7..d183bf6 100644 --- a/kernel/Makefrag +++ b/kernel/Makefrag @@ -31,6 +31,7 @@ KERN_SRCFILES :=kernel/kernel.asm \ kernel/testfunc.c \ kernel/protect.c \ kernel/serialport.c \ + kernel/vga.c \ lib/klib.c \ lib/kliba.asm \ diff --git a/kernel/console.c b/kernel/console.c index 380c45d..2294f5e 100644 --- a/kernel/console.c +++ b/kernel/console.c @@ -61,6 +61,11 @@ void init_screen(TTY* tty) } +static inline void write_char_c(int pos, char ch) { + u16* pch = (u16*)K_PHY2LIN(V_MEM_BASE + pos);\ + *pch = (0x0f << 8) | ch; +} + /***************************************************************************** * out_char *****************************************************************************/ @@ -88,14 +93,16 @@ void out_char(CONSOLE* con, char ch) //*(pch - 2) = ' '; //*(pch - 1) = DEFAULT_CHAR_COLOR; disp_pos = con->cursor*2; - write_char(' '); + // write_char(' '); + write_char_c(disp_pos, ' '); } break; default: //*pch++ = ch; //*pch++ = DEFAULT_CHAR_COLOR; disp_pos = con->cursor*2; - write_char(ch); + // write_char(ch); + write_char_c(disp_pos, ch); con->cursor++; break; diff --git a/kernel/ktest.c b/kernel/ktest.c index 37c9ad6..97a70ef 100644 --- a/kernel/ktest.c +++ b/kernel/ktest.c @@ -127,7 +127,7 @@ void initial() do_vclose(stdout); do_vclose(stderr); - exec("orange/shell_0.bin"); + exec("orange/test.bin"); while(1); } \ No newline at end of file diff --git a/kernel/main.c b/kernel/main.c index 0a4afc9..a98142f 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -34,19 +34,19 @@ int kernel_main() init_serial(); int error; - disp_pos = 0; - for (int i = 0; i < 25; i++) { - for (int j = 0; j < 80; j++) { - disp_str(" "); - } - } + // disp_pos = 0; + // for (int i = 0; i < 25; i++) { + // for (int j = 0; j < 80; j++) { + // disp_str(" "); + // } + // } disp_pos = 0; kprintf("-----Kernel Initialization Begins-----\n"); kernel_initial = 1; //kernel is in initial state. added by xw, 18/5/31 init();//内存管理模块的初始化 add by liang - + init_tty_main(); //initialize PCBs, added by xw, 18/5/26 error = initialize_processes(); if(error != 0) diff --git a/kernel/tty.c b/kernel/tty.c index 3f21ada..cf5cf43 100644 --- a/kernel/tty.c +++ b/kernel/tty.c @@ -9,6 +9,10 @@ #include "proto.h" #include "keyboard.h" #include "x86.h" +#include "memman.h" +#include "stdio.h" + +#define DEBUGNEW int current_console; //当前显示在屏幕上的console void tty_write(TTY *tty, char *buf, int len); @@ -20,6 +24,27 @@ static void tty_dev_read(TTY *tty); static void tty_dev_write(TTY *tty); static void put_key(TTY *tty, u32 key); +#ifdef DEBUGNEW + +static NTTY ntty_table[3]; +static int cur_ntty = 0; +static keyboard_buf keyboardbuf[3]; +static vga_buf vgabuf[3]; + +void init_tty_main() { + NTTY* tty; + for (int i = 0; i < 3; ++ i) { + tty = &ntty_table[i]; + tty->driver_type = 1; // vga + // tty->input_buf = (void*)do_kmalloc(sizeof(keyboard_buf)); + // tty->output_buf = (void*)do_kmalloc(sizeof(vga_buf)); + tty->input_buf = &keyboardbuf[i]; + tty->output_buf = &vgabuf[i]; + vga_tty_init(tty); + } +} + +#endif void in_process(TTY *p_tty, u32 key) { int real_line = p_tty->console->orig / SCR_WIDTH; @@ -87,6 +112,17 @@ void in_process(TTY *p_tty, u32 key) void task_tty() { + #ifdef DEBUGNEW + // NTTY* p_tty; + // for (p_tty = ntty_table; p_tty < ntty_table + 3; ++ p_tty) { + // init_ntty(p_tty); + // } + while(1) + { + // vga_tty_flush(&ntty_table[cur_ntty]); + } + + #else TTY *p_tty; for (p_tty = TTY_FIRST; p_tty < TTY_END; p_tty++) { @@ -118,6 +154,7 @@ void task_tty() } while (p_tty->ibuf_cnt); } } + #endif } static void init_tty(TTY *p_tty) @@ -258,8 +295,15 @@ static void put_key(TTY *tty, u32 key) *****************************************************************************/ void tty_write(TTY *tty, char *buf, int len) { +#ifdef DEBUGNEW + while (--len >= 0) { + vga_tty_write(&ntty_table[cur_ntty], *buf++); + } + vga_tty_flush(&ntty_table[cur_ntty]); +#else while (--len >= 0) out_char(tty->console, *buf++); +#endif } /***************************************************************************** diff --git a/kernel/vga.c b/kernel/vga.c new file mode 100644 index 0000000..86376cf --- /dev/null +++ b/kernel/vga.c @@ -0,0 +1,246 @@ +#include "type.h" +#include "stdio.h" +#include "const.h" +#include "protect.h" +#include "string.h" +#include "proc.h" +#include "tty.h" +#include "console.h" +#include "global.h" +#include "keyboard.h" +#include "proto.h" +#include "x86.h" +#include "memman.h" +#include "assert.h" + +/***************************************************************************** + * Low level vga driver + *****************************************************************************/ + +/***************************************************************************** + * 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 inline void vga_set_cursor(unsigned int position) +{ + disable_int(); + outb(CRTC_ADDR_REG, CURSOR_H); + outb(CRTC_DATA_REG, (position >> 8) & 0xFF); + outb(CRTC_ADDR_REG, CURSOR_L); + outb(CRTC_DATA_REG, position & 0xFF); + enable_int(); +} + +static inline void vga_disable_cursor() +{ + outb(CRTC_ADDR_REG, 0x0A); + outb(CRTC_DATA_REG, 0x20); +} + +static inline void vga_enable_cursor(u8 cursor_start, u8 cursor_end) +{ + outb(0x3D4, 0x0A); + outb(0x3D5, (inb(0x3D5) & 0xC0) | cursor_start); + + outb(0x3D4, 0x0B); + outb(0x3D5, (inb(0x3D5) & 0xE0) | cursor_end); +} + +/***************************************************************************** + * Routine for hardware screen scrolling. + * + * @param addr Offset in the video memory. + *****************************************************************************/ +static inline void vga_set_video_start_addr(u32 addr) +{ + 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(); +} + + +/***************************************************************************** + * Write data directly to Video Memory cell + * + * @param pos text mode position(pos*2 yourself) + * @param dat data to be written, with format [ BG | FG | ASCII ] + *****************************************************************************/ +static inline void vga_put_raw(u32 pos, u16 dat) { + u16* pch = (u16*)K_PHY2LIN(V_MEM_BASE + pos); + *pch = dat; +} + + +/***************************************************************************** + * copy a whole screen of text mode data into video memory, assume that screen + * width is 80 or 40 + * + * @param src memory block with the same size as text mode video memory() + *****************************************************************************/ +static inline void vga_flush_screen(void* src) { + u32* _src = src; + u32* dst = (u32*)K_PHY2LIN(V_MEM_BASE); + for (int i = 0; i < SCR_SIZE * sizeof(u16) / sizeof(u32); ++ i) { + *dst ++ = *_src ++; + } +} + + +/***************************************************************************** + * copy a whole screen of text mode data into video memory, assume that screen + * width is 80 or 40 + * + * @param src memory block with the same size as text mode video memory() + *****************************************************************************/ +static inline void vga_flush_line(void* src, int line_no) { + u32* _src = src; + u32* dst = (u32*)K_PHY2LIN(V_MEM_BASE + line_no * SCR_WIDTH * 2); + for (int i = 0; i < SCR_WIDTH * sizeof(u16) / sizeof(u32); ++ i) { + *dst ++ = *_src ++; + } +} + +static inline void vga_flush_blankline(int line_no) { + u32* dst = (u32*)K_PHY2LIN(V_MEM_BASE + line_no * SCR_WIDTH * 2); + for (int i = 0; i < SCR_WIDTH * sizeof(u16) / sizeof(u32); ++ i) { + *dst ++ = (BLANK << 16) | BLANK; + } +} + +/***************************************************************************** + * tty - vga driver + *****************************************************************************/ +static u16 pagebuf[3][SCR_BUFSIZE]; + +void vga_tty_init(NTTY* tty) { + assert(tty->driver_type == 1); + assert(tty->output_buf); + vga_buf* vga = tty->output_buf; + // vga->buf = (void*)do_kmalloc(sizeof(u16) * SCR_BUFSIZE); + vga->buf = (void*)pagebuf[0]; + // kprintf("malloced %p %p %p\n", vga->buf, &vga->buf, &vga->scr_top_line); + vga->cur_col = vga->cur_row = 0; + // buf->max_line = SCR_BUFSIZE / SCR_WIDTH; + vga->scr_top_line = vga->scr_cur_line = 0; + vga->head_line = 0; + u32* ptr_buf = (u32*) vga->buf; + for (int i = 0; i < SCR_BUFSIZE * sizeof(u16) / sizeof(u32); ++i) { + ptr_buf[i] = (BLANK << 16) | BLANK; // bg-black, fg-white, ascii-space + } + kprintf("%p 0x%x %d\n", vga->buf, ((u32*)vga->buf)[20], vga->scr_cur_line); + +} + +#define INDEX(row, col) ((row) * SCR_WIDTH + (col)) +#define NEXTLINE(row) (((row) + 1) % SCR_MAXLINE) +#define LASTLINE(row) (((row) - 1) >= 0 ? ((row) - 1) % SCR_MAXLINE : SCR_MAXLINE) + +static void newline(vga_buf* vgabuf) { + vgabuf->cur_col = 0; + // kprintf("bf %x\n", vgabuf->scr_cur_line); + vgabuf->scr_cur_line = NEXTLINE(vgabuf->scr_cur_line); + // kprintf("af %x\n", vgabuf->scr_cur_line); + vgabuf->cur_row = abs(vgabuf->scr_cur_line - vgabuf->scr_top_line); + if (vgabuf->cur_row == SCR_HEIGHT) { + // auto scroll + vgabuf->scr_top_line = NEXTLINE(vgabuf->scr_top_line); + if(vgabuf->scr_cur_line == vgabuf->head_line) { + vgabuf->head_line = NEXTLINE(vgabuf->head_line); + // remember to fill blank the old line + u32* ptr_buf = (u32*) (vgabuf->buf + sizeof(u16) * vgabuf->head_line * SCR_WIDTH); + for (int i = 0; i < SCR_WIDTH * sizeof(u16) / sizeof(u32); ++i) { + *ptr_buf++ = (BLANK << 16) | BLANK; // bg-black, fg-white, ascii-space + } + } + } +} + +void vga_tty_write(NTTY* tty, char ch) { + // assert(tty->driver_type == 1); + // assert(tty->output_buf); + vga_buf* vga = tty->output_buf; + u16* buf = vga->buf; + // kprintf("vga_tty_write %c to %d %d\n", ch, vga->scr_cur_line, vga->cur_col); + switch (ch) + { + case '\n': + newline(vga); + break; + case '\r': + vga->cur_col = 0; + break; + case '\b': + // this implementation is mimic to usual linux shell + // it moves cursor left but neither crosses line nor delete character + if (vga->cur_col > 0) { + vga->cur_col --; + } + break; + default: + buf[INDEX(vga->scr_cur_line, vga->cur_col)] = MAKE_CELL(DEFAULT_CHAR_COLOR, ch); + vga->cur_col ++; + if (vga->cur_col == SCR_WIDTH) { + newline(vga); + } + break; + } + vga->cur_row = abs(vga->scr_cur_line - vga->scr_top_line); + // kprintf("row: %d; ", vga->cur_row); +} + +void vga_tty_flush(NTTY* tty) { + vga_buf* vga = tty->output_buf; + u16* buf = vga->buf; + int i, cur_line; + vga_set_cursor(INDEX(vga->cur_row, vga->cur_col)); + if (vga->cur_row == SCR_WIDTH - 1) { + vga_flush_screen(&buf[INDEX(vga->scr_top_line, 0)]); + } + else { + cur_line = vga->scr_top_line; + for (i = 0; i <= vga->cur_row; ++ i){ + vga_flush_line(&buf[INDEX(cur_line, 0)], i); + cur_line = NEXTLINE(cur_line); + } + for (; i < SCR_WIDTH; ++ i) { + vga_flush_blankline(i); + } + } + // kprintf("flush: row=%d, top=%d, cur=%d\n", vga->cur_row, vga->scr_top_line, vga->scr_cur_line); +} + +void vga_tty_scroll(NTTY* tty, int direction) { + vga_buf* vga = tty->output_buf; + u16* buf = vga->buf; + if (direction > 0) { + // down + if (vga->scr_top_line == vga->scr_cur_line) return; + vga->scr_top_line = NEXTLINE(vga->scr_top_line); + } + else { + if (vga->scr_top_line == vga->head_line) return; + vga->scr_top_line = LASTLINE(vga->scr_top_line); + } + vga->cur_row = abs(vga->scr_cur_line - vga->scr_top_line); + if (vga->cur_row >= SCR_HEIGHT) { + vga_disable_cursor(); + } + else { + vga_enable_cursor(0, 15); + } +} + +void vga_scroll_to_cur(NTTY* tty) { + vga_buf* vga = tty->output_buf; + u16* buf = vga->buf; + // vga->scr_top_line = vga->scr_cur_line +} + +void vga_tty_select(NTTY* tty) { + // +} \ No newline at end of file diff --git a/user/Makefrag b/user/Makefrag index 9df3303..187ffda 100644 --- a/user/Makefrag +++ b/user/Makefrag @@ -8,6 +8,7 @@ USERLIB_OBJS := $(patsubst %.asm, $(OBJDIR)/%.o, $(USERLIB_OBJS)) # 这里给我整不会了,文件名只能长度为16位,否则会寄,原因还挺难找 USER_SRCS := user/ptTest.c \ user/shell_0.c \ + user/test.c \ USER_BINS := $(patsubst %.c, $(OBJDIR)/%.bin, $(USER_SRCS)) USER_BASENAMES := $(patsubst $(OBJDIR)/user/%, %, $(USER_BINS)) diff --git a/user/test.c b/user/test.c new file mode 100644 index 0000000..d743d74 --- /dev/null +++ b/user/test.c @@ -0,0 +1,36 @@ +#include "type.h" +#include "const.h" +#include "protect.h" +#include "string.h" +#include "proc.h" +#include "global.h" +#include "proto.h" +#include "stdio.h" + +int main(int arg, char *argv[]) +{ + int stdin = open("dev_tty0", O_RDWR); + int stdout = open("dev_tty0", O_RDWR); + int stderr = open("dev_tty0", O_RDWR); + + char buf[1024]; + int pid; + int times = 0; + for (int i = 0; i < 20; ++ i) { + printf("test %d\n", i); + } + for (int i = 0; i < 2; ++ i) { + printf("1111111111"); + printf("2222222222"); + printf("3333333333"); + printf("4444444444"); + printf("5555555555"); + printf("6666666666"); + printf("7777777777"); + printf("8888888888"); + printf("9999999999\r\b\b\n"); + } + + while(1); + return 0; +} \ No newline at end of file