add simple console before tty init
This commit is contained in:
parent
a3a2bb4cfe
commit
bb51f9775a
@ -17,14 +17,20 @@
|
||||
/* CONSOLE */
|
||||
typedef struct s_console
|
||||
{
|
||||
unsigned int crtc_start; /* set CRTC start addr reg */
|
||||
unsigned int orig; /* start addr of the console */
|
||||
unsigned int con_size; /* how many words does the console have */
|
||||
unsigned int cursor;
|
||||
int is_full;
|
||||
unsigned int current_line;
|
||||
unsigned int row;
|
||||
unsigned int col;
|
||||
unsigned int buf_head; // for futher restore after true tty initialized
|
||||
unsigned int buf_tail;
|
||||
char *buf;
|
||||
} CONSOLE;
|
||||
|
||||
void simpleconsole_init();
|
||||
void simpleconsole_write(char* buf, int nr);
|
||||
void simpleconsole_transfer(void (*write)(char ch));
|
||||
void simpleconsole_setcur(int row, int col);
|
||||
|
||||
#define CON_MAX_LOGBUF 1024
|
||||
|
||||
#define SCR_UP 1 /* scroll upward */
|
||||
#define SCR_DN -1 /* scroll downward */
|
||||
|
||||
|
||||
@ -57,6 +57,7 @@ typedef struct n_tty
|
||||
void (*write)(struct n_tty *tty, char ch);
|
||||
int (*read)(struct n_tty *tty, char* buf, int nr);
|
||||
void (*recvbuf)(struct n_tty *tty, u32 ch);
|
||||
int (*ioctl)(struct n_tty *tty, u32 cmd, long arg);
|
||||
} NTTY;
|
||||
|
||||
enum CSI_state
|
||||
@ -104,11 +105,6 @@ typedef struct serial_buf
|
||||
|
||||
#include "console.h"
|
||||
|
||||
void select_console(int nr_console);
|
||||
void init_screen(TTY *tty);
|
||||
void out_char(CONSOLE *con, char ch);
|
||||
int is_current_console(CONSOLE *con);
|
||||
|
||||
NTTY *get_tty(const int nr_tty);
|
||||
|
||||
void vga_tty_init(NTTY *tty);
|
||||
|
||||
373
kernel/console.c
373
kernel/console.c
@ -1,3 +1,4 @@
|
||||
// A simple, vga textmode console ready to use before tty init
|
||||
#include "type.h"
|
||||
#include "stdio.h"
|
||||
#include "const.h"
|
||||
@ -12,175 +13,37 @@
|
||||
#include "proto.h"
|
||||
#include "x86.h"
|
||||
|
||||
/* local routines */
|
||||
static void set_cursor(unsigned int position);
|
||||
static void set_video_start_addr(u32 addr);
|
||||
static void flush(CONSOLE *con);
|
||||
static void w_copy(unsigned int dst, const unsigned int src, int size);
|
||||
static void clear_screen(int pos, int len);
|
||||
void scroll_screen(CONSOLE *con, int dir);
|
||||
#define INDEX(row, col) ((row)*SCR_WIDTH + (col))
|
||||
|
||||
/*****************************************************************************
|
||||
* init_screen
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Initialize the console of a certain tty.
|
||||
*
|
||||
* @param tty Whose console is to be initialized.
|
||||
*****************************************************************************/
|
||||
void init_screen(TTY *tty)
|
||||
static char logbuf[CON_MAX_LOGBUF];
|
||||
static CONSOLE con = {
|
||||
.row = 0,
|
||||
.col = 0,
|
||||
.buf = logbuf,
|
||||
.buf_head = 0,
|
||||
.buf_tail = 0
|
||||
};
|
||||
|
||||
static inline void vga_put_raw(u32 pos, u16 dat)
|
||||
{
|
||||
int nr_tty = 0;
|
||||
|
||||
tty->console = console_table + nr_tty;
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
* variables related to `position' and `size' below are
|
||||
* in WORDs, but not in BYTEs.
|
||||
*/
|
||||
int v_mem_size = V_MEM_SIZE >> 1; /* size of Video Memory */
|
||||
int size_per_con = (v_mem_size / NR_CONSOLES) / 80 * 80;
|
||||
tty->console->orig = nr_tty * size_per_con;
|
||||
tty->console->con_size = size_per_con / SCR_WIDTH * SCR_WIDTH;
|
||||
tty->console->cursor = tty->console->crtc_start = tty->console->orig;
|
||||
tty->console->is_full = 0;
|
||||
tty->console->current_line = 0;
|
||||
|
||||
if (nr_tty == 0)
|
||||
{
|
||||
tty->console->cursor = disp_pos / 2;
|
||||
}
|
||||
const char prompt[] = "[TTY #?]\n";
|
||||
|
||||
const char *p = prompt;
|
||||
for (; *p; p++)
|
||||
{
|
||||
out_char(tty->console, *p == '?' ? nr_tty + '0' : *p);
|
||||
}
|
||||
|
||||
set_cursor(tty->console->cursor);
|
||||
u16 *pch = (u16 *)K_PHY2LIN(V_MEM_BASE) + pos;
|
||||
*pch = dat;
|
||||
}
|
||||
|
||||
static inline void write_char_c(int pos, char ch)
|
||||
// simple scroll, just abandon those scrolled up
|
||||
static void scroll()
|
||||
{
|
||||
u16 *pch = (u16 *)K_PHY2LIN(V_MEM_BASE + pos);
|
||||
*pch = (0x0f << 8) | ch;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* out_char
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Print a char in a certain console.
|
||||
*
|
||||
* @param con The console to which the char is printed.
|
||||
* @param ch The char to print.
|
||||
*****************************************************************************/
|
||||
|
||||
void out_char(CONSOLE *con, char ch)
|
||||
{
|
||||
disable_int();
|
||||
|
||||
int cursor_x = (con->cursor - con->orig) % SCR_WIDTH;
|
||||
int cursor_y = (con->cursor - con->orig) / SCR_WIDTH;
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case '\n':
|
||||
con->cursor = con->orig + SCR_WIDTH * (cursor_y + 1);
|
||||
break;
|
||||
case '\b':
|
||||
if (con->cursor > con->orig)
|
||||
{
|
||||
con->cursor--;
|
||||
//*(pch - 2) = ' ';
|
||||
//*(pch - 1) = DEFAULT_CHAR_COLOR;
|
||||
disp_pos = con->cursor * 2;
|
||||
write_char_c(disp_pos, ' ');
|
||||
u16* video_mem = (u16 *)K_PHY2LIN(V_MEM_BASE);
|
||||
for (int i = 0; i < SCR_HEIGHT - 1; ++ i) {
|
||||
for (int j = 0; j < SCR_WIDTH; ++ j) {
|
||||
video_mem[INDEX(i, j)] = video_mem[INDEX(i+1, j)];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//*pch++ = ch;
|
||||
//*pch++ = DEFAULT_CHAR_COLOR;
|
||||
disp_pos = con->cursor * 2;
|
||||
write_char_c(disp_pos, ch);
|
||||
con->cursor++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (con->cursor - con->orig >= con->con_size)
|
||||
{
|
||||
cursor_x = (con->cursor - con->orig) % SCR_WIDTH;
|
||||
cursor_y = (con->cursor - con->orig) / SCR_WIDTH;
|
||||
int cp_orig = con->orig + (cursor_y + 1) * SCR_WIDTH - SCR_SIZE;
|
||||
w_copy(con->orig, cp_orig, SCR_SIZE - SCR_WIDTH);
|
||||
con->crtc_start = con->orig;
|
||||
con->cursor = con->orig + (SCR_SIZE - SCR_WIDTH) + cursor_x;
|
||||
clear_screen(con->cursor, SCR_WIDTH);
|
||||
if (!con->is_full)
|
||||
con->is_full = 1;
|
||||
}
|
||||
|
||||
// assert(con->cursor - con->orig < con->con_size);
|
||||
|
||||
while (con->cursor >= con->crtc_start + SCR_SIZE ||
|
||||
con->cursor < con->crtc_start)
|
||||
{
|
||||
scroll_screen(con, SCR_UP);
|
||||
|
||||
clear_screen(con->cursor, SCR_WIDTH);
|
||||
}
|
||||
|
||||
flush(con);
|
||||
|
||||
enable_int();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* clear_screen
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Write whitespaces to the screen.
|
||||
*
|
||||
* @param pos Write from here.
|
||||
* @param len How many whitespaces will be written.
|
||||
*****************************************************************************/
|
||||
static void clear_screen(int pos, int len)
|
||||
{
|
||||
u8 *pch = (u8 *)K_PHY2LIN(V_MEM_BASE + pos * 2);
|
||||
while (--len >= 0)
|
||||
{
|
||||
*pch++ = ' ';
|
||||
*pch++ = (u8)(DEFAULT_CHAR_COLOR >> 8);
|
||||
for (int j = 0; j < SCR_WIDTH; ++ j) {
|
||||
video_mem[INDEX(SCR_HEIGHT-1, j)] = BLANK;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* is_current_console
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Uses `nr_current_console' to determine if a console is the current one.
|
||||
*
|
||||
* @param con Ptr to console.
|
||||
*
|
||||
* @return TRUE if con is the current console.
|
||||
*****************************************************************************/
|
||||
int is_current_console(CONSOLE *con)
|
||||
{
|
||||
return (con == &console_table[current_console]);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* set_cursor
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Display the cursor by setting CRTC (6845 compatible) registers.
|
||||
*
|
||||
* @param position Position of the cursor based on the beginning of the video
|
||||
* memory. Note that it counts in WORDs, not in BYTEs.
|
||||
*****************************************************************************/
|
||||
static void set_cursor(unsigned int position)
|
||||
{
|
||||
disable_int();
|
||||
@ -191,152 +54,78 @@ static void set_cursor(unsigned int position)
|
||||
enable_int();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* set_video_start_addr
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Routine for hardware screen scrolling.
|
||||
*
|
||||
* @param addr Offset in the video memory.
|
||||
*****************************************************************************/
|
||||
static void set_video_start_addr(u32 addr)
|
||||
void simpleconsole_init()
|
||||
{
|
||||
disable_int();
|
||||
outb(CRTC_ADDR_REG, START_ADDR_H);
|
||||
outb(CRTC_DATA_REG, (addr >> 8) & 0xFF);
|
||||
outb(CRTC_ADDR_REG, START_ADDR_L);
|
||||
outb(CRTC_DATA_REG, addr & 0xFF);
|
||||
enable_int();
|
||||
con.row = 0;
|
||||
con.col = 0;
|
||||
con.buf = logbuf;
|
||||
con.buf_head = 0;
|
||||
con.buf_tail = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* select_console
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Select a console as the current.
|
||||
*
|
||||
* @param nr_console Console nr, range in [0, NR_CONSOLES-1].
|
||||
*****************************************************************************/
|
||||
void select_console(int nr_console)
|
||||
static void do_console_write(char ch)
|
||||
{
|
||||
if ((nr_console < 0) || (nr_console >= NR_CONSOLES))
|
||||
return;
|
||||
con.buf[con.buf_tail] = ch;
|
||||
con.buf_tail = NEXT(con.buf_tail, CON_MAX_LOGBUF);
|
||||
if (con.buf_head == con.buf_tail) con.buf_head = NEXT(con.buf_head, CON_MAX_LOGBUF);
|
||||
|
||||
flush(&console_table[current_console = nr_console]);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* scroll_screen
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Scroll the screen.
|
||||
*
|
||||
* Note that scrolling UP means the content of the screen will go upwards, so
|
||||
* that the user can see lines below the bottom. Similarly scrolling DOWN means
|
||||
* the content of the screen will go downwards so that the user can see lines
|
||||
* above the top.
|
||||
*
|
||||
* When there is no line below the bottom of the screen, scrolling UP takes no
|
||||
* effects; when there is no line above the top of the screen, scrolling DOWN
|
||||
* takes no effects.
|
||||
*
|
||||
* @param con The console whose screen is to be scrolled.
|
||||
* @param dir SCR_UP : scroll the screen upwards;
|
||||
* SCR_DN : scroll the screen downwards
|
||||
*****************************************************************************/
|
||||
void scroll_screen(CONSOLE *con, int dir)
|
||||
{
|
||||
/*
|
||||
* variables below are all in-console-offsets (based on con->orig)
|
||||
*/
|
||||
int oldest; /* addr of the oldest available line in the console */
|
||||
int newest; /* .... .. ... latest ......... .... .. ... ....... */
|
||||
int scr_top; /* position of the top of current screen */
|
||||
|
||||
newest = (con->cursor - con->orig) / SCR_WIDTH * SCR_WIDTH;
|
||||
oldest = con->is_full ? (newest + SCR_WIDTH) % con->con_size : 0;
|
||||
scr_top = con->crtc_start - con->orig;
|
||||
|
||||
if (dir == SCR_DN)
|
||||
switch (ch)
|
||||
{
|
||||
if (!con->is_full && scr_top > 0)
|
||||
{
|
||||
con->crtc_start -= SCR_WIDTH;
|
||||
case '\n':
|
||||
con.row ++;
|
||||
con.col = 0;
|
||||
if (con.row >= SCR_HEIGHT) {
|
||||
scroll();
|
||||
con.row --;
|
||||
}
|
||||
else if (con->is_full && scr_top != oldest)
|
||||
{
|
||||
if (con->cursor - con->orig >= con->con_size - SCR_SIZE)
|
||||
{
|
||||
if (con->crtc_start != con->orig)
|
||||
con->crtc_start -= SCR_WIDTH;
|
||||
}
|
||||
else if (con->crtc_start == con->orig)
|
||||
{
|
||||
scr_top = con->con_size - SCR_SIZE;
|
||||
con->crtc_start = con->orig + scr_top;
|
||||
}
|
||||
else
|
||||
{
|
||||
con->crtc_start -= SCR_WIDTH;
|
||||
}
|
||||
break;
|
||||
case '\r':
|
||||
con.col = 0;
|
||||
break;
|
||||
case '\b':
|
||||
if (con.col == 0) {
|
||||
if (con.row) con.row --;
|
||||
con.col = SCR_WIDTH - 1;
|
||||
}
|
||||
}
|
||||
else if (dir == SCR_UP)
|
||||
{
|
||||
if (!con->is_full && newest >= scr_top + SCR_SIZE)
|
||||
{
|
||||
con->crtc_start += SCR_WIDTH;
|
||||
else {
|
||||
con.col --;
|
||||
}
|
||||
else if (con->is_full && scr_top + SCR_SIZE - SCR_WIDTH != newest)
|
||||
{
|
||||
if (scr_top + SCR_SIZE == con->con_size)
|
||||
con->crtc_start = con->orig;
|
||||
else
|
||||
con->crtc_start += SCR_WIDTH;
|
||||
break;
|
||||
default:
|
||||
vga_put_raw(INDEX(con.row, con.col), MAKE_CELL(DEFAULT_CHAR_COLOR, ch));
|
||||
con.col ++;
|
||||
if (con.col >= SCR_WIDTH) {
|
||||
con.col = 0;
|
||||
con.row ++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// assert(dir == SCR_DN || dir == SCR_UP);
|
||||
}
|
||||
|
||||
flush(con);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* flush
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Set the cursor and starting address of a console by writing the
|
||||
* CRT Controller Registers.
|
||||
*
|
||||
* @param con The console to be set.
|
||||
*****************************************************************************/
|
||||
static void flush(CONSOLE *con)
|
||||
{
|
||||
if (is_current_console(con))
|
||||
{
|
||||
set_cursor(con->cursor);
|
||||
set_video_start_addr(con->crtc_start);
|
||||
if (con.row >= SCR_HEIGHT) {
|
||||
scroll();
|
||||
con.row --;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* w_copy
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Copy data in WORDS.
|
||||
*
|
||||
* Note that the addresses of dst and src are not pointers, but integers, 'coz
|
||||
* in most cases we pass integers into it as parameters.
|
||||
*
|
||||
* @param dst Addr of destination.
|
||||
* @param src Addr of source.
|
||||
* @param size How many words will be copied.
|
||||
*****************************************************************************/
|
||||
static void w_copy(unsigned int dst, const unsigned int src, int size)
|
||||
void simpleconsole_write(char* buf, int nr)
|
||||
{
|
||||
memcpy((void *)(V_MEM_BASE + (dst << 1)),
|
||||
(void *)(V_MEM_BASE + (src << 1)),
|
||||
size << 1);
|
||||
while (nr --) {
|
||||
do_console_write(*buf ++);
|
||||
}
|
||||
set_cursor(INDEX(con.row, con.col));
|
||||
}
|
||||
|
||||
void simpleconsole_transfer(void (*write)(char ch))
|
||||
{
|
||||
int i = con.buf_head;
|
||||
while (i != con.buf_tail) {
|
||||
write(con.buf[i]);
|
||||
i = NEXT(i, CON_MAX_LOGBUF);
|
||||
}
|
||||
}
|
||||
|
||||
void simpleconsole_setcur(int row, int col) {
|
||||
con.row = max(0, min(row, SCR_HEIGHT-1));
|
||||
con.col = max(0, min(row, SCR_WIDTH-1));
|
||||
set_cursor(INDEX(con.row, con.col));
|
||||
}
|
||||
17
kernel/tty.c
17
kernel/tty.c
@ -19,15 +19,13 @@ int tty_ok = 0;
|
||||
void tty_write(NTTY *tty, char *buf, int len);
|
||||
int tty_read(NTTY *tty, char *buf, int len);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
NTTY* cur_ntty;
|
||||
NTTY* ntty_table[NR_CONSOLES];
|
||||
|
||||
static void write_default_tty(char ch) {
|
||||
cur_ntty->write(cur_ntty, ch);
|
||||
}
|
||||
|
||||
inline NTTY* get_tty(const int nr_tty) {
|
||||
return ntty_table[nr_tty];
|
||||
}
|
||||
@ -65,6 +63,7 @@ void init_tty_main()
|
||||
}
|
||||
cur_ntty = ntty_table[0];
|
||||
tty_ok = 1;
|
||||
simpleconsole_transfer(write_default_tty);
|
||||
kprintf("TTY initialized\n");
|
||||
}
|
||||
|
||||
@ -97,10 +96,8 @@ void task_tty()
|
||||
void tty_write(NTTY *tty, char *buf, int len)
|
||||
{
|
||||
if (!tty_ok) {
|
||||
while (--len >= 0)
|
||||
{
|
||||
write_serial(*buf++);
|
||||
}
|
||||
simpleconsole_write(buf, len);
|
||||
// while (--len >= 0) write_serial(*buf++);
|
||||
return;
|
||||
}
|
||||
else if (tty->driver_type == 1) {
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#include "tty.h"
|
||||
#include "serialport.h"
|
||||
|
||||
static void serialputch(int ch, int *cnt)
|
||||
static void kprintfputch(int ch, int *cnt)
|
||||
{
|
||||
// write_serial(ch);
|
||||
char _ch = ch;
|
||||
@ -17,9 +17,8 @@ static void serialputch(int ch, int *cnt)
|
||||
int vkprintf(const char *fmt, va_list ap)
|
||||
{
|
||||
|
||||
// vprintfmt((void*)kprintfputch, NULL, fmt, ap);
|
||||
int cnt = 0;
|
||||
vprintfmt((void *)serialputch, &cnt, fmt, ap);
|
||||
vprintfmt((void *)kprintfputch, &cnt, fmt, ap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user