第七章 输入输出系统之显示器和TTY

来源:互联网 发布:windows 7 启动过程 编辑:程序博客网 时间:2024/05/16 05:00

总体

程序b是简单的键盘

程序d加入优化过的tty

程序e加入优化的键盘处理

程序ftask_ttyTestA, TestB, TestC分开产生,一个任务和三个用户进程

程序g加入了一个printf函数

 

一、基本概率

1.开机时候是80x25文本模式

显存的范围为0xB8000~0xBFFFF,共计32KB。一个屏幕总共25行,每行80个字符,高位表示字符的属性,低位表示字符ASCII码。

 

2.VGA模式

 

 

二、TTY任务

 

 

1.TTY结构

Include\tty.h

typedef struct s_tty

{

t_32in_buf[TTY_IN_BYTES];/* TTY输入缓冲区 */

t_32* p_inbuf_head; /* 指向缓冲区中下一个空闲位置 */

t_32* p_inbuf_tail; /* 指向键盘任务应处理的键值 */

int inbuf_count;     /* 缓冲区中已经填充了多少 */

struct s_console * p_console;

}TTY;

2.CONSOLE结构

Include\console.h

typedef struct s_console

{

//struct s_tty* p_tty;

unsigned int current_start_addr; /* 当前显示到了什么位置   */

unsigned int original_addr; /* 当前控制台对应显存位置 */

unsigned int v_mem_limit; /* 当前控制台占的显存大小 */

unsigned int cursor; /* 当前光标位置 */

}CONSOLE;

 

三、程序e我们多加入一个控制台

按住alt+f1 f2 f3在三个控制台切换

Shift+箭头可以上下滚屏

可以回车和换行

 

1.kernel/tty.c

/*======================================================================*

                           init_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);

}

 

2.kernel/console.c

/*======================================================================*

                           init_screen

 *======================================================================*/

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 / SCREEN_WIDTH * SCREEN_WIDTH; /*当前控制台占的显存大小 (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);

}

 

 

 

 

 

3.调用控制台切换代码

按下alt+fn做切换工作

kernel/tty.c 

/*======================================================================*

                           in_process

 *======================================================================*/

PUBLIC void in_process(TTY* p_tty, t_32 key)

{

if (!(key & FLAG_EXT)) {

put_key(p_tty, key);

}

else {

int raw_code = key & MASK_RAW;

switch(raw_code) {

case ENTER:相应回车和换行

put_key(p_tty, '\n');

break;

case BACKSPACE:相应回车和换行

put_key(p_tty, '\b');

break;

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;

}

}

}

 

4. 控制台切换代码

kernel/console.c

/*======================================================================*

                           select_console

 *======================================================================*/

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;

flush(&console_table[nr_console]);

}

5.使用数字键盘

Kernel\keyboard.c

Caps Lock NumLock Scroll Lock这三个键有点特殊,每一个都对应一个小灯LED,实际上不通过敲击键盘来可以控制这些灯的亮灭,通过写8042的输入缓冲区可以做到这一点。

 

0x64读取状态寄存器,得到的值第1位如果是0表示,输入缓冲区为空,可以写数据

PRIVATE void kb_wait() /* 等待 8042的输入缓冲区空 */

{

t_8 kb_stat;

do {

kb_stat = in_byte(KB_CMD);// #define KB_CMD 0x64

} while (kb_stat & 0x02);  //缓冲区是否为空,不为空机箱等待

}

从输入缓冲区读取数据

PRIVATE void kb_ack()

{

t_8 kb_read;

do {

kb_read = in_byte(KB_DATA);  //#define KB_DATA 0x60

} while (kb_read =! KB_ACK);    // #define KB_ACK 0xFA

}

 

四、程序f分析

ch7_f_mynote

程序e以后我们有四,TTY,A,B,C其中ABC是用户只需的,而TTY很重要没有他我们都不能使用键盘

ABC运行在ring3,任务TTYring1

 

 

1. include\proc.h文件

以前是

#define NR_TASKS 4

改成

#define NR_TASKS1

#define NR_PROCS3

 

2.kernel\global.c

PUBLIC PROCESS proc_table[NR_TASKS + NR_PROCS];

 

PUBLIC TASK task_table[NR_TASKS] = {{task_tty, STACK_SIZE_TTY, "tty"}};

 

PUBLIC TASK user_proc_table[NR_PROCS] = {

{TestA, STACK_SIZE_TESTA, "TestA"},

{TestB, STACK_SIZE_TESTB, "TestB"},

{TestC, STACK_SIZE_TESTC, "TestC"}};

3.kernel\main.c

 

 

 

改变了用户进程的特权级,改变了eflags和剥夺了用户进程所有的I/O权限

其余的代码没多少变化

 

 

0 0
原创粉丝点击