// 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)); }