#include "bga.h" #include "console.h" #include "const.h" #include "global.h" #include "keyboard.h" #include "memman.h" #include "proc.h" #include "protect.h" #include "proto.h" #include "serialport.h" #include "spinlock.h" #include "stdio.h" #include "string.h" #include "tty.h" #include "type.h" #include "x86.h" #include "yieldlock.h" static int cur_col = 0; static int cur_row = 0; static int _fnt_char_width = 0; static int _fnt_char_height = 0; static int _scr_max_rows = 0; static int _scr_max_cols = 0; static int _fbbufsize = 0; static int _fbwidth = 0; static int _fbheight = 0; static int _fbpixels_per_row = 0; static int _fbscale = 1; static int cursor_blink = 0; static uint32_t _basecolor = 0x0; static uintptr_t _fb_paddr = 0; static uint32_t* _fb = NULL; static uint32_t* cur_fb = NULL; static volatile int framecnt = 0; static char* textbuf; volatile u32 buflock; #define UNIT_CHAR_H (_fnt_char_height * _fbscale) #define UNIT_CHAR_W (_fnt_char_width * _fbscale) #define INDEX(row, col, mx) ((row) * (mx) + (col)) #include "font8x8.h" static void fast_copy(void* dst, void* src, int len); static void fbcon_draw_raw(int row, int col, char ch) { for (int x = 0; x < UNIT_CHAR_H; x++) { for (int y = 0; y < UNIT_CHAR_W; y++) { uint32_t ind = (col * UNIT_CHAR_W + x) + ((row * UNIT_CHAR_H + y) * _fbpixels_per_row); uint32_t clr = _basecolor; if (font8x8_basic[ch & 0x7f][y / _fbscale] & (1 << (x / _fbscale))) { clr ^= 0xffffffff; } cur_fb[ind] = clr; } } } static void draw_cursor() { fbcon_draw_raw(cur_row, cur_col, 0); } static void draw_cursor_clear() { fbcon_draw_raw(cur_row, cur_col, 1); } static void fbcon_scroll() { int lineoffset = _fbwidth * _fnt_char_height * _fbscale; fast_copy( (void*)cur_fb, (void*)cur_fb + lineoffset, _fbbufsize - lineoffset); memset((void*)cur_fb + _fbbufsize - lineoffset, 0, lineoffset); } static void textbuf_scroll() { memcpy((void*) textbuf, (void*)textbuf + _scr_max_cols, (_scr_max_rows-1)*_scr_max_cols); memset((void*)textbuf + (_scr_max_rows-1)*_scr_max_cols, ' ', _scr_max_cols); } static void fbcon_putchar(char ch) { switch (ch) { case '\n': cur_row ++; cur_col = 0; if (cur_row >= _scr_max_rows) { textbuf_scroll(); cur_row --; } break; case '\r': cur_col = 0; break; case '\b': if (cur_col == 0) { if (cur_row) cur_row --; cur_col = _scr_max_cols - 1; } else { cur_col --; } break; default: textbuf[INDEX(cur_row, cur_col, _scr_max_cols)] = ch; cur_col ++; if (cur_col >= _scr_max_cols) { cur_col = 0; cur_row ++; } if (cur_row >= _scr_max_rows) { textbuf_scroll(); cur_row --; } break; } } int screen_setup() { cur_col = 0; cur_row = 0; _fnt_char_width = 8; _fnt_char_height = 8; _fb = (uint32_t*)bga_ioctl(BGA_GET_BUFFER, 0); _fb_paddr = bga_ioctl(BGA_GET_BUFFER, 0); _fbwidth = bga_ioctl(BGA_GET_WIDTH, 0); _fbheight = bga_ioctl(BGA_GET_HEIGHT, 0); _fbpixels_per_row = _fbwidth; _fbbufsize = _fbwidth * _fbheight * 4; _fbscale = 2; cur_fb = _fb; _scr_max_cols = _fbwidth / _fnt_char_width / _fbscale; _scr_max_rows = _fbheight / _fnt_char_height / _fbscale; kprintf("bufsz = %p, maxsize(%d, %d)\n", _fbbufsize, _scr_max_rows, _scr_max_cols); _basecolor = 0; cursor_blink = 1; framecnt = 0; textbuf = (char*)malloc(_scr_max_cols * _scr_max_rows); memset(textbuf, ' ', _scr_max_cols * _scr_max_rows); return 0; } static void do_fbcon_write(char* buf, int nr) { disable_int(); while (nr--) { fbcon_putchar(*buf++); } enable_int(); } void fbcon_tty_write(NTTY* tty, char ch) { do_fbcon_write(&ch, 1); } static void blink_ctrl() { if (framecnt < 10) { framecnt ++; // kprintf("frame %d\n", framecnt); } else { framecnt = 0; cursor_blink = ! cursor_blink; // kprintf("should change\n"); } } static void fast_copy(void* dst, void* src, int len) { // assume all address align, 32 bytes a time uint32_t* _src = src; uint32_t* _dst = dst; int i; for (i = 0; i < len / 4; i += 8) { _dst[i + 0] = _src[i + 0]; _dst[i + 1] = _src[i + 1]; _dst[i + 2] = _src[i + 2]; _dst[i + 3] = _src[i + 3]; _dst[i + 4] = _src[i + 4]; _dst[i + 5] = _src[i + 5]; _dst[i + 6] = _src[i + 6]; _dst[i + 7] = _src[i + 7]; } } static void textbuf_render() { for (int row = 0; row < _scr_max_rows; ++ row) { for (int col = 0; col < _scr_max_cols; ++ col) { fbcon_draw_raw(row, col, textbuf[INDEX(row, col, _scr_max_cols)]); } } } void task_tty() { // main rountine for drawing framebuffered console screen_setup(); mmap((u32)_fb, _fb_paddr, _fbwidth * _fbheight * 4 * 2); buflock = 0; // fbcon_write(text1, strlen(text1)); int cur_buf = 0, last_buf = 1; while (1) { // fast_copy((void*)_fb + cur_buf * _fbbufsize, (void*)_fb + last_buf * _fbbufsize, _fbbufsize); draw_cursor_clear(); while (xchg(&buflock, 1) == 1) yield(); textbuf_render(); xchg(&buflock, 0); blink_ctrl(); if (cursor_blink) draw_cursor(); bga_ioctl(BGA_SWAP_BUFFERS, cur_buf); last_buf = cur_buf; cur_buf = !cur_buf; cur_fb = (void*)_fb + cur_buf * _fbbufsize; sleep(5); // to no need to refresh that fast } }