From: acevest Date: Sun, 7 Nov 2021 12:51:15 +0000 (+0800) Subject: new tty for printk X-Git-Url: http://zhaoyanbai.com/repos/Bv9ARM.ch13.html?a=commitdiff_plain;h=6a2bff8d79bf436c287827e3cbb576ee87e221e6;p=kernel.git new tty for printk --- diff --git a/drivers/keyboard.c b/drivers/keyboard.c index bebef5c..7403d90 100644 --- a/drivers/keyboard.c +++ b/drivers/keyboard.c @@ -20,6 +20,7 @@ #include #include #include +#include void reboot(); void poweroff(); @@ -107,8 +108,13 @@ void kbd_debug(unsigned char scan_code) { while (1) ; } - if (scan_code == 0x58) // F12 - vga_dbg_toggle(); + + extern tty_t default_tty; + extern tty_t monitor_tty; + if (scan_code == 0x58) { // F12 + current_tty = current_tty != &default_tty ? &default_tty : &monitor_tty; + tty_switch(current_tty); + } // ide_status(); } diff --git a/include/tty.h b/include/tty.h new file mode 100644 index 0000000..b5c0194 --- /dev/null +++ b/include/tty.h @@ -0,0 +1,34 @@ +/* + * ------------------------------------------------------------------------ + * File Name: tty.h + * Author: Zhao Yanbai + * 2021-11-07 17:17:23 Sunday CST + * Description: none + * ------------------------------------------------------------------------ + */ + +#pragma once + +typedef struct tty { + char name[32]; + + // 记录字符显示位置 + unsigned int xpos; + unsigned int ypos; + + unsigned int fg_color; + unsigned int bg_color; + + // 记录对应的显存起始位置 + unsigned long base_addr; +} tty_t; + +void init_ttys(); + +void tty_write(tty_t *tty, const char *buf, size_t size); +void tty_write_at(tty_t *tty, int xpos, int ypos, const char *buf, size_t size); + +void tty_set_cursor(tty_t *tty); +void tty_switch(tty_t *tty); + +extern tty_t *current_tty; \ No newline at end of file diff --git a/kernel/printk.c b/kernel/printk.c index 9eb1d1c..10d7847 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -16,6 +16,7 @@ */ #include +#include extern void vga_puts(unsigned int nr, const char *buf, unsigned char color); extern void vga_dbg_puts(unsigned int line, unsigned int offset, const char *buf); @@ -30,10 +31,13 @@ void switch_printk_screen() { } char pkbuf[1024]; +extern tty_t default_tty; int printk(const char *fmtstr, ...) { char *args = (char *)(((char *)&fmtstr) + 4); - vsprintf(pkbuf, fmtstr, args); - vga_puts(printk_screen_nr, pkbuf, 0x2); + int size = vsprintf(pkbuf, fmtstr, args); + // vga_puts(printk_screen_nr, pkbuf, 0x2); + tty_write(&default_tty, pkbuf, (size_t)size); + // tty_write(&default_tty, "aaa\n", (size_t)4); return 0; } @@ -47,9 +51,12 @@ int printd(const char *fmtstr, ...) { } char plobuf[1024]; +extern tty_t monitor_tty; int printlo(unsigned int line, unsigned int offset, const char *fmtstr, ...) { char *args = (char *)(((char *)&fmtstr) + 4); - vsprintf(plobuf, fmtstr, args); - vga_dbg_puts(line, offset, plobuf); + int size = vsprintf(plobuf, fmtstr, args); + // vga_dbg_puts(line, offset, plobuf); + tty_write_at(&monitor_tty, offset, line, plobuf, (size_t)size); + // tty_write_at(&monitor_tty, 1, 2, "abc\n", (size_t)4); return 0; } diff --git a/kernel/setup.c b/kernel/setup.c index 606192e..f420739 100644 --- a/kernel/setup.c +++ b/kernel/setup.c @@ -36,6 +36,7 @@ extern void setup_ext2(); extern void reboot(); extern void cnsl_init(); extern void vga_init(); +extern void init_ttys(); #define HZ 10 #define CLOCK_TICK_RATE 1193180 @@ -57,6 +58,7 @@ const char *version = "Kernel version " VERSION " @ " BUILDER void setup_kernel() { vga_init(); + init_ttys(); init_mm(); diff --git a/kernel/syscall.c b/kernel/syscall.c index 59edd80..70156d3 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -1,79 +1,68 @@ /* *-------------------------------------------------------------------------- * File Name: syscall.c - * + * * Description: none - * - * + * + * * Author: Zhao Yanbai [zhaoyanbai@126.com] - * + * * Version: 1.0 * Create Date: Fri Jan 2 19:49:20 2009 * Last Update: Fri Jan 2 19:49:20 2009 - * + * *-------------------------------------------------------------------------- */ #include "syscall.h" -#include "system.h" -#include "sched.h" + #include "msr.h" +#include "sched.h" +#include "system.h" extern void syscall_entry(); extern void init_sysc_handler_table(); unsigned long sysc_handler_table[SYSC_NUM]; -void setup_sysc() -{ +void setup_sysc() { wrmsr(MSR_SYSENTER_CS, SELECTOR_KRNL_CS, 0); wrmsr(MSR_SYSENTER_EIP, syscall_entry, 0); - //wrmsr(MSR_SYSENTER_ESP, &(tss.esp0), 0); + // wrmsr(MSR_SYSENTER_ESP, &(tss.esp0), 0); init_sysc_handler_table(); } -int sysc_none() -{ +int sysc_none() { int sysc_nr; - asm("" - : "=a"(sysc_nr)); + asm("" : "=a"(sysc_nr)); printk("unsupport syscall:%d\n", sysc_nr); return 0; } -int sysc_pause(unsigned long tick) -{ - - return 0; -} +int sysc_pause(unsigned long tick) { return 0; } -int sysc_test() -{ +int sysc_test() { static unsigned int cnt = 0; current->cnt++; // printl(MPL_TEST, "systest cnt %u current %08x cnt %u ", // cnt++, current, cnt); - printk("systest cnt %u current %08x cnt %u\n",cnt++, current, cnt); + // printk("systest cnt %u current %08x cnt %u\n",cnt++, current, cnt); return 0; } -int sysc_debug(unsigned int v) -{ +int sysc_debug(unsigned int v) { static unsigned int cnt = 0; printl(MPL_DEBUG, "task debug syscall %u value %08x", cnt++, v); return 0; } -void init_sysc_handler_table() -{ +void init_sysc_handler_table() { int i; - for (i = 0; i < SYSC_NUM; i++) - sysc_handler_table[i] = (unsigned long)sysc_none; + for (i = 0; i < SYSC_NUM; i++) sysc_handler_table[i] = (unsigned long)sysc_none; #define _sysc_(nr, sym) \ - do \ - { \ + do { \ extern int sym(); \ sysc_handler_table[nr] = (unsigned long)sym; \ } while (0); @@ -93,12 +82,10 @@ void init_sysc_handler_table() _sysc_(SYSC_BAD_NR, sysc_bad_nr) } -int sysc_bad_nr() -{ +int sysc_bad_nr() { int sysc_nr; - asm("" - : "=a"(sysc_nr)); + asm("" : "=a"(sysc_nr)); printk("bad syscall nr:%d\n", sysc_nr); diff --git a/kernel/tty.c b/kernel/tty.c new file mode 100644 index 0000000..0b3f6fd --- /dev/null +++ b/kernel/tty.c @@ -0,0 +1,188 @@ +/* + * ------------------------------------------------------------------------ + * File Name: tty.c + * Author: Zhao Yanbai + * 2021-11-07 17:17:18 Sunday CST + * Description: none + * ------------------------------------------------------------------------ + */ + +#include +#include +#include +#include +#include +#include + +#define BLACK 0b000 +#define WHITE 0b111 +#define RED 0b100 +#define GREEN 0b010 +#define BLUE 0b001 + +// 从0xB8000处开始有32KB显存可利用 +// 而一屏所需要的显存为 80*25*2 = 4000 约为4K +// 所以大致可以分出8个tty +// 每个的起始地址以0x1000对齐 +#define VADDR ((unsigned long)pa2va(0xB8000)) +#define TTY_VRAM_SIZE (0x1000) + +#define MAX_X 80 +#define MAX_Y 25 +#define CHARS_PER_LINE (MAX_X) +#define BYTES_PER_LINE (CHARS_PER_LINE * 2) +#define TAB_SPACE 4 + +tty_t default_tty; +tty_t monitor_tty; + +void tty_clear(tty_t *tty) { + char *dst = (char *)tty->base_addr; + for (int src = 0; src < (MAX_Y * BYTES_PER_LINE); src += 2) { + *dst++ = ' '; + *dst++ = (tty->bg_color << 4) | tty->fg_color; + } +} + +void init_tty(tty_t *tty, const char *name, unsigned long base) { + assert(0 != tty); + + memset(tty, 0, sizeof(tty_t)); + + strlcpy(tty->name, name, sizeof(tty->name)); + + tty->fg_color = 0x8 | GREEN; // 高亮 + tty->bg_color = 0x0 | BLACK; // 不闪 + + tty->base_addr = base; +} + +void init_ttys() { + init_tty(&default_tty, "tty.default", VADDR + 0 * TTY_VRAM_SIZE); + init_tty(&monitor_tty, "tty.monitor", VADDR + 1 * TTY_VRAM_SIZE); + + monitor_tty.fg_color = WHITE; + monitor_tty.bg_color = BLUE; + tty_clear(&monitor_tty); + + current_tty = &default_tty; +} + +void tty_do_scroll_up(tty_t *tty) { + // 不需要上卷 + if (tty->ypos < MAX_Y) { + return; + } + + // + char *dst = (char *)tty->base_addr; + for (int src = BYTES_PER_LINE; src < (MAX_Y * BYTES_PER_LINE); src++) { + *dst++ = *(char *)(tty->base_addr + src); + } + + // 清空最后一行 + dst = (char *)(tty->base_addr + ((MAX_Y - 1) * BYTES_PER_LINE)); + for (int i = 0; i < BYTES_PER_LINE; i += 2) { + *dst++ = ' '; + *dst++ = (tty->bg_color << 4) | tty->fg_color; + } + + tty->ypos = MAX_Y - 1; +} + +void tty_putc(tty_t *tty, char c) { + bool display = false; + switch (c) { + case '\r': + tty->xpos = 0; + case '\n': + tty->xpos = 0; + tty->ypos += 1; + break; + case '\t': + tty->xpos += TAB_SPACE; + tty->xpos &= ~(TAB_SPACE - 1); + tty->ypos += tty->xpos / CHARS_PER_LINE; + tty->xpos %= CHARS_PER_LINE; + break; + default: + tty->ypos += tty->xpos / CHARS_PER_LINE; + tty->xpos %= CHARS_PER_LINE; + display = true; + break; + } + + tty_do_scroll_up(tty); + + // 显示 + if (display) { + unsigned int pos = tty->ypos * BYTES_PER_LINE + tty->xpos * 2; + char *va = (char *)(tty->base_addr + pos); + va[0] = c; + va[1] = (tty->bg_color << 4) | tty->fg_color; + + tty->xpos++; + } + + tty_set_cursor(tty); +} + +void tty_write(tty_t *tty, const char *buf, size_t size) { + assert(0 != tty); + if (0 == buf) { + return; + } + + for (size_t i = 0; i < size; i++) { + tty_putc(tty, buf[i]); + } +} + +void tty_write_at(tty_t *tty, int xpos, int ypos, const char *buf, size_t size) { + assert(0 != tty); + assert(xpos < BYTES_PER_LINE); + assert(ypos < MAX_Y); + tty->xpos = xpos; + tty->ypos = ypos; + tty_write(tty, buf, size); +} + +#define VGA_CRTC_ADDR 0x3D4 +#define VGA_CRTC_DATA 0x3D5 +#define VGA_CRTC_START_ADDR_H 0xC +#define VGA_CRTC_START_ADDR_L 0xD +#define VGA_CRTC_CURSOR_H 0xE +#define VGA_CRTC_CURSOR_L 0xF + +void tty_set_cursor(tty_t *tty) { + if (tty != current_tty) { + return; + } + unsigned int offset = tty->ypos * MAX_Y + tty->xpos; + offset += VADDR; + + unsigned long flags; + irq_save(flags); + outb(VGA_CRTC_CURSOR_H, VGA_CRTC_ADDR); + outb((offset >> 8) & 0xFF, VGA_CRTC_DATA); + outb(VGA_CRTC_CURSOR_L, VGA_CRTC_ADDR); + outb(offset & 0xFF, VGA_CRTC_DATA); + irq_restore(flags); +} + +void tty_switch(tty_t *tty) { + if (0 == tty) { + return; + } + + unsigned int offset = (tty->base_addr - VADDR) / 2; + + outb(VGA_CRTC_START_ADDR_H, VGA_CRTC_ADDR); + outb((offset >> 8) & 0xFF, VGA_CRTC_DATA); + outb(VGA_CRTC_START_ADDR_L, VGA_CRTC_ADDR); + outb((offset)&0xFF, VGA_CRTC_DATA); + + current_tty = tty; +} + +tty_t *current_tty; \ No newline at end of file diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 1152327..f29433a 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -95,6 +95,8 @@ int vsprintf(char *buf, const char *fmt, char *args) { fmt++; } *p = 0; + + return p - buf; } void swap_char(char *a, char *b) {