BigOS/kernel/console.c
2023-01-14 16:27:28 +08:00

130 lines
2.4 KiB
C

// A simple, vga textmode console ready to use before tty init
#include "type.h"
#include "stdio.h"
#include "const.h"
#include "protect.h"
#include "string.h"
#include "fs.h"
#include "proc.h"
#include "tty.h"
#include "console.h"
#include "global.h"
#include "keyboard.h"
#include "proto.h"
#include "x86.h"
#define INDEX(row, col) ((row)*SCR_WIDTH + (col))
static char logbuf[CON_MAX_LOGBUF];
static s_console con = {
.row = 0,
.col = 0,
.buf = logbuf,
.buf_head = 0,
.buf_tail = 0
};
static inline void vga_put_raw(u32 pos, u16 dat)
{
u16 *pch = (u16 *)K_PHY2LIN(V_MEM_BASE) + pos;
*pch = dat;
}
// simple scroll, just abandon those scrolled up
static void scroll()
{
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)];
}
}
for (int j = 0; j < SCR_WIDTH; ++ j) {
video_mem[INDEX(SCR_HEIGHT-1, j)] = BLANK;
}
}
static void set_cursor(unsigned int position)
{
outb(CRTC_ADDR_REG, CURSOR_H);
outb(CRTC_DATA_REG, (position >> 8) & 0xFF);
outb(CRTC_ADDR_REG, CURSOR_L);
outb(CRTC_DATA_REG, position & 0xFF);
}
void simpleconsole_init()
{
con.row = 0;
con.col = 0;
con.buf = logbuf;
con.buf_head = 0;
con.buf_tail = 0;
}
static void do_console_write(char ch)
{
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);
switch (ch)
{
case '\n':
con.row ++;
con.col = 0;
if (con.row >= SCR_HEIGHT) {
scroll();
con.row --;
}
break;
case '\r':
con.col = 0;
break;
case '\b':
if (con.col == 0) {
if (con.row) con.row --;
con.col = SCR_WIDTH - 1;
}
else {
con.col --;
}
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 ++;
}
if (con.row >= SCR_HEIGHT) {
scroll();
con.row --;
}
break;
}
}
void simpleconsole_write(char* buf, int nr)
{
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));
}