130 lines
2.4 KiB
C
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));
|
|
}
|