--------------------------------------------------------
多控制台
--------------------------------------------------------
上一节我们搭建起了多控制台的平台,在上一节的平台上来实现多控制台应该来说是相对容易的...
// ----------------------------
// <console.c>
// Jack Zheng 12.1
// ----------------------------
#include "type.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"
/* 本文件内函数声明 */
PRIVATE void set_cursor(unsigned int position);
PRIVATE void set_video_start_addr(t_32 addr);
PUBLIC void init_screen(TTY* p_tty)
{
int nr_tty = p_tty - tty_table;
p_tty->p_console = console_table + nr_tty;
int v_mem_size = V_MEM_SIZE >> 1; /* 显存总大小 (in WORD) */
int con_v_mem_size = v_mem_size / NR_CONSOLES; /* 每个控制台占的显存大小 (in WORD) */
p_tty->p_console->original_addr = nr_tty * con_v_mem_size; /* 当前控制台占的显存开始地址 (in WORD) */
p_tty->p_console->v_mem_limit = con_v_mem_size; /* 当前控制台占的显存大小 (in WORD) */
p_tty->p_console->current_start_addr = p_tty->p_console->original_addr; /* 当前控制台显示到了显存的什么位置 (in WORD) */
p_tty->p_console->cursor = p_tty->p_console->original_addr; /* 默认光标位置在最开始处 */
if (nr_tty == 0) {
p_tty->p_console->cursor = disp_pos / 2; /* 第一个控制台延用原来的光标位置 */
disp_pos = 0;
}
else {
out_char(p_tty->p_console, nr_tty + '0');
out_char(p_tty->p_console, '#');
}
set_cursor(p_tty->p_console->cursor);
}
PUBLIC void out_char(CONSOLE* p_con, char ch)
{
t_8* p_vmem = (t_8*)(V_MEM_BASE + p_con->cursor * 2);
*p_vmem++ = ch;
*p_vmem++ = DEFAULT_CHAR_COLOR;
p_con->cursor++;
set_cursor(p_con->cursor);
}
PUBLIC t_bool is_current_console(CONSOLE* p_con)
{
return (p_con == &console_table[nr_current_console]);
}
PRIVATE void set_cursor(unsigned int position)
{
disable_int();
out_byte(CRTC_ADDR_REG, CRTC_DATA_IDX_CURSOR_H);
out_byte(CRTC_DATA_REG, (position >> 8) & 0xFF);
out_byte(CRTC_ADDR_REG, CRTC_DATA_IDX_CURSOR_L);
out_byte(CRTC_DATA_REG, position & 0xFF);
enable_int();
}
PRIVATE void set_video_start_addr(t_32 addr)
{
disable_int();
out_byte(CRTC_ADDR_REG, CRTC_DATA_IDX_START_ADDR_H);
out_byte(CRTC_DATA_REG, (addr >> 8) & 0xFF);
out_byte(CRTC_ADDR_REG, CRTC_DATA_IDX_START_ADDR_L);
out_byte(CRTC_DATA_REG, addr & 0xFF);
enable_int();
}
PUBLIC void select_console(int nr_console) /* 0 ~ (NR_CONSOLES - 1) */
{
if ((nr_console < 0) || (nr_console >= NR_CONSOLES)) { /* invalid console number */
return;
}
nr_current_console = nr_console;
set_cursor(console_table[nr_console].cursor);
set_video_start_addr(console_table[nr_console].current_start_addr);
}
PUBLIC void scroll_screen(CONSOLE* p_con, int direction)
{
if (direction == SCROLL_SCREEN_UP) {
if (p_con->current_start_addr > p_con->original_addr) {
p_con->current_start_addr -= SCREEN_WIDTH;
}
}
else if (direction == SCROLL_SCREEN_DOWN) {
if (p_con->current_start_addr + SCREEN_SIZE < p_con->original_addr + p_con->v_mem_limit) {
p_con->current_start_addr += SCREEN_WIDTH;
}
}
else{
}
set_video_start_addr(p_con->current_start_addr);
set_cursor(p_con->cursor);
}
// ----------------------------
// <tty.c>
// Jack Zheng 11.30
// ----------------------------
#include "type.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"
#define TTY_FIRST (tty_table)
#define TTY_END (tty_table + NR_CONSOLES)
/* 本文件内函数声明 */
PRIVATE void init_tty(TTY* p_tty);
PRIVATE void tty_do_read(TTY* p_tty);
PRIVATE void tty_do_write(TTY* p_tty);
PUBLIC void task_tty()
{
TTY* p_tty;
init_keyboard();
for (p_tty=TTY_FIRST;p_tty<TTY_END;p_tty++) {
init_tty(p_tty);
}
select_console(0);
while (1) {
for (p_tty=TTY_FIRST;p_tty<TTY_END;p_tty++) {
tty_do_read(p_tty);
tty_do_write(p_tty);
}
}
}
PRIVATE void init_tty(TTY* p_tty)
{
p_tty->inbuf_count = 0;
p_tty->p_inbuf_head = p_tty->p_inbuf_tail = p_tty->in_buf;
init_screen(p_tty);
}
PUBLIC void in_process(TTY* p_tty, t_32 key)
{
#ifdef __TINIX_DEBUG__
disp_color_str("<", MAKE_COLOR(BLACK,RED));
disp_int(key);
disp_color_str(">", MAKE_COLOR(BLACK,RED));
#endif
if (!(key & FLAG_EXT)) {
if (p_tty->inbuf_count < TTY_IN_BYTES) {
*(p_tty->p_inbuf_head) = key;
p_tty->p_inbuf_head++;
if (p_tty->p_inbuf_head == p_tty->in_buf + TTY_IN_BYTES) {
p_tty->p_inbuf_head = p_tty->in_buf;
}
p_tty->inbuf_count++;
}
}
else {
int raw_code = key & MASK_RAW;
switch(raw_code) {
case UP:
if ((key & FLAG_SHIFT_L) || (key & FLAG_SHIFT_R)) { /* Shift + Up */
scroll_screen(p_tty->p_console, SCROLL_SCREEN_UP);
}
break;
case DOWN:
if ((key & FLAG_SHIFT_L) || (key & FLAG_SHIFT_R)) { /* Shift + Down */
scroll_screen(p_tty->p_console, SCROLL_SCREEN_DOWN);
}
break;
case F1:
case F2:
case F3:
case F4:
case F5:
case F6:
case F7:
case F8:
case F9:
case F10:
case F11:
case F12:
if ((key & FLAG_ALT_L) || (key & FLAG_ALT_R)) { /* Alt + F1~F12 */
select_console(raw_code - F1);
}
break;
default:
break;
}
}
}
PRIVATE void tty_do_read(TTY* p_tty)
{
if (is_current_console(p_tty->p_console)) {
keyboard_read(p_tty);
}
}
PRIVATE void tty_do_write(TTY* p_tty)
{
if (p_tty->inbuf_count) {
char ch = *(p_tty->p_inbuf_tail);
p_tty->p_inbuf_tail++;
if (p_tty->p_inbuf_tail == p_tty->in_buf + TTY_IN_BYTES) {
p_tty->p_inbuf_tail = p_tty->in_buf;
}
p_tty->inbuf_count--;
out_char(p_tty->p_console, ch);
}
}
运行:
OK,看来我们的 TTY 框架还不错!