BigOS/kernel/tty.c
2022-12-13 13:29:17 +08:00

295 lines
6.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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 "proto.h"
#include "keyboard.h"
#include "x86.h"
int current_console; //当前显示在屏幕上的console
void tty_write(TTY *tty, char *buf, int len);
int tty_read(TTY *tty, char *buf, int len);
static void init_tty(TTY *tty);
static void tty_mouse(TTY *tty);
static void tty_dev_read(TTY *tty);
static void tty_dev_write(TTY *tty);
static void put_key(TTY *tty, u32 key);
void in_process(TTY *p_tty, u32 key)
{
int real_line = p_tty->console->orig / SCR_WIDTH;
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');
p_tty->status = p_tty->status & 3; //&3'b011
break;
case BACKSPACE:
put_key(p_tty, '\b');
break;
case UP:
if (p_tty->console->current_line < 43)
{
disable_int();
p_tty->console->current_line++;
outb(CRTC_ADDR_REG, START_ADDR_H);
outb(CRTC_DATA_REG, ((80 * (p_tty->console->current_line + real_line)) >> 8) & 0xFF);
outb(CRTC_ADDR_REG, START_ADDR_L);
outb(CRTC_DATA_REG, (80 * (p_tty->console->current_line + real_line)) & 0xFF);
enable_int();
}
break;
case DOWN:
if (p_tty->console->current_line > 0)
{
disable_int();
p_tty->console->current_line--;
outb(CRTC_ADDR_REG, START_ADDR_H);
outb(CRTC_DATA_REG, ((80 * (p_tty->console->current_line + real_line)) >> 8) & 0xFF);
outb(CRTC_ADDR_REG, START_ADDR_L);
outb(CRTC_DATA_REG, (80 * (p_tty->console->current_line + real_line)) & 0xFF);
enable_int();
}
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:
select_console(raw_code - F1);
break;
}
}
}
#define TTY_FIRST (tty_table)
#define TTY_END (tty_table + NR_CONSOLES)
void task_tty()
{
TTY *p_tty;
for (p_tty = TTY_FIRST; p_tty < TTY_END; p_tty++)
{
init_tty(p_tty);
}
p_tty = tty_table;
select_console(0);
//设置第一个tty光标位置第一个tty需要特殊处理
disable_int();
outb(CRTC_ADDR_REG, CURSOR_H);
outb(CRTC_DATA_REG, ((disp_pos / 2) >> 8) & 0xFF);
outb(CRTC_ADDR_REG, CURSOR_L);
outb(CRTC_DATA_REG, (disp_pos / 2) & 0xFF);
enable_int();
//轮询
while (1)
{
for (p_tty = TTY_FIRST; p_tty < TTY_END; p_tty++)
{
do
{
tty_mouse(p_tty); /* tty判断鼠标操作 */
tty_dev_read(p_tty); /* 从键盘输入缓冲区读到这个tty自己的缓冲区 */
tty_dev_write(p_tty); /* 把tty缓存区的数据写到这个tty占有的显存 */
} while (p_tty->ibuf_cnt);
}
}
}
static void init_tty(TTY *p_tty)
{
p_tty->ibuf_read_cnt = p_tty->ibuf_cnt = 0;
p_tty->status = TTY_STATE_DISPLAY;
p_tty->ibuf_read = p_tty->ibuf_head = p_tty->ibuf_tail = p_tty->ibuf;
int det = p_tty - tty_table;
p_tty->console = console_table + det;
p_tty->mouse_left_button = 0;
p_tty->mouse_mid_button = 0;
p_tty->mouse_X = 0;
p_tty->mouse_Y = 0;
init_screen(p_tty);
}
static void tty_mouse(TTY *tty)
{
if (is_current_console(tty->console))
{
int real_line = tty->console->orig / SCR_WIDTH;
if (tty->mouse_left_button)
{
if (tty->mouse_Y > MOUSE_UPDOWN_BOUND)
{ //按住鼠标左键向上滚动
if (tty->console->current_line < 43)
{
disable_int();
tty->console->current_line++;
outb(CRTC_ADDR_REG, START_ADDR_H);
outb(CRTC_DATA_REG, ((80 * (tty->console->current_line + real_line)) >> 8) & 0xFF);
outb(CRTC_ADDR_REG, START_ADDR_L);
outb(CRTC_DATA_REG, (80 * (tty->console->current_line + real_line)) & 0xFF);
enable_int();
tty->mouse_Y = 0;
}
}
else if (tty->mouse_Y < -MOUSE_UPDOWN_BOUND)
{ //按住鼠标左键向下滚动
if (tty->console->current_line > 0)
{
disable_int();
tty->console->current_line--;
outb(CRTC_ADDR_REG, START_ADDR_H);
outb(CRTC_DATA_REG, ((80 * (tty->console->current_line + real_line)) >> 8) & 0xFF);
outb(CRTC_ADDR_REG, START_ADDR_L);
outb(CRTC_DATA_REG, (80 * (tty->console->current_line + real_line)) & 0xFF);
enable_int();
tty->mouse_Y = 0;
}
}
}
if (tty->mouse_mid_button)
{ //点击中键复原
disable_int();
tty->console->current_line = 0;
outb(CRTC_ADDR_REG, START_ADDR_H);
outb(CRTC_DATA_REG, ((80 * (tty->console->current_line + real_line)) >> 8) & 0xFF);
outb(CRTC_ADDR_REG, START_ADDR_L);
outb(CRTC_DATA_REG, (80 * (tty->console->current_line + real_line)) & 0xFF);
enable_int();
tty->mouse_Y = 0;
}
}
}
static void tty_dev_read(TTY *tty)
{
if (is_current_console(tty->console))
{
keyboard_read(tty);
}
}
static void tty_dev_write(TTY *tty)
{
if (tty->ibuf_cnt)
{
char ch = *(tty->ibuf_tail);
tty->ibuf_tail++;
if (tty->ibuf_tail == tty->ibuf + TTY_IN_BYTES)
{
tty->ibuf_tail = tty->ibuf;
}
tty->ibuf_cnt--;
if (ch == '\b')
{
if (tty->ibuf_read_cnt == 1)
{
tty->ibuf_read_cnt--;
tty->ibuf_head--;
tty->ibuf_tail--;
return;
}
else
{
tty->ibuf_read_cnt -= 2;
if (tty->ibuf_head == tty->ibuf)
{
tty->ibuf_head = tty->ibuf_tail = &tty->ibuf[256 - 2];
}
else
{
tty->ibuf_head--;
tty->ibuf_tail--;
tty->ibuf_head--;
tty->ibuf_tail--;
}
}
}
out_char(tty->console, ch);
}
}
static void put_key(TTY *tty, u32 key)
{
if (tty->ibuf_cnt < TTY_IN_BYTES)
{
*(tty->ibuf_head) = key;
tty->ibuf_head++;
if (tty->ibuf_head == tty->ibuf + TTY_IN_BYTES)
tty->ibuf_head = tty->ibuf;
tty->ibuf_cnt++;
tty->ibuf_read_cnt++;
}
}
/*****************************************************************************
* tty_write
****************************************************************************
* 当fd=STD_OUT时write()系统调用转发到此函数
*****************************************************************************/
void tty_write(TTY *tty, char *buf, int len)
{
while (--len >= 0)
out_char(tty->console, *buf++);
}
/*****************************************************************************
* tty_read
****************************************************************************
* 当fd=STD_IN时read()系统调用转发到此函数
*****************************************************************************/
int tty_read(TTY *tty, char *buf, int len)
{
int i = 0;
if (!tty->ibuf_read_cnt)
{
tty->status |= TTY_STATE_WAIT_ENTER;
}
while ((tty->status & TTY_STATE_WAIT_ENTER))
;
while (tty->ibuf_read_cnt && i < len)
{
buf[i] = *tty->ibuf_read;
tty->ibuf_read++;
if (tty->ibuf_read == tty->ibuf + TTY_IN_BYTES)
{
tty->ibuf_read = tty->ibuf;
}
tty->ibuf_read_cnt--;
i++;
}
return i;
}