]> Zhao Yanbai Git Server - kernel.git/commitdiff
new tty for printk
authoracevest <zhaoyanbai@126.com>
Sun, 7 Nov 2021 12:51:15 +0000 (20:51 +0800)
committeracevest <zhaoyanbai@126.com>
Sun, 7 Nov 2021 12:51:15 +0000 (20:51 +0800)
drivers/keyboard.c
include/tty.h [new file with mode: 0644]
kernel/printk.c
kernel/setup.c
kernel/syscall.c
kernel/tty.c [new file with mode: 0644]
lib/vsprintf.c

index bebef5ca44e73cd7cef8c1cd79ce09ec9c945c03..7403d902363c8cbd0c94f5b8a960c0cadd9c328f 100644 (file)
@@ -20,6 +20,7 @@
 #include <string.h>
 #include <syscall.h>
 #include <system.h>
+#include <tty.h>
 
 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 (file)
index 0000000..b5c0194
--- /dev/null
@@ -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
index 9eb1d1c0d9a2d1c3a391980eabdc326c28f09272..10d7847c577637ce43c42b84e241047a8fce97d8 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <system.h>
+#include <tty.h>
 
 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;
 }
index 606192e9a274a9f1e7ca4156c31b54ef0f3aeaa2..f4207397441288592e6cdfae4298968e1fc06c88 100644 (file)
@@ -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();
 
index 59edd8048220620aa6096f88bb2a6e7c89894732..70156d3c3d83cecb26a0a4306a95a9ab39580de7 100644 (file)
@@ -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 (file)
index 0000000..0b3f6fd
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * ------------------------------------------------------------------------
+ *   File Name: tty.c
+ *      Author: Zhao Yanbai
+ *              2021-11-07 17:17:18 Sunday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#include <assert.h>
+#include <io.h>
+#include <irq.h>
+#include <page.h>
+#include <string.h>
+#include <tty.h>
+
+#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
index 11523275359169ebbab3f9314f54e537170eebd0..f29433a45b4b9967d2ffb039bcd09701537f036a 100644 (file)
@@ -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) {