#include "vga.h" #include "io.h" #include "irq.h" #include "klibc.h" #include "paging.h" #include "mem.h" static uint vgaBgColor; static uint vgaColor; static int line, col; static volatile short *vga = (short *)VGA_ADDR; static uint fbWidth = VGA_WIDTH; static uint fbHeight = VGA_HEIGHT; static void clearScreen(uint bgColor); static void cursorMove(int x, int y); static void cursorEnable(uint8_t cursor_start, uint8_t cursor_end); static void printCharDetails(char str, uint color, uint bgColor, int startX, int startY); int VGASetup(uint bgColor, uint color) { vgaBgColor = bgColor; vgaColor = color; line = 0; col = 0; clearScreen(bgColor); cursorEnable(14, 15); return 0; } int VGAConfigure(int addr, uint width, uint height){ vga = (short *)addr; fbWidth = width; fbHeight = height; return 0; } static void clearScreen(uint bgColor) { uint32_t flags; long int colorAttr = bgColor << 12; disable_IRQs(flags); for (uint i = 0; i < fbWidth * fbHeight; i++) { vga[i] = colorAttr; } restore_IRQs(flags); } void VGAclearLine(uint bgColor, uint line) { uint32_t flags; long int colorAttr = bgColor << 12; if (line >= fbHeight) return; disable_IRQs(flags); for (uint i = fbWidth * line; i < fbWidth * (line + 1); i++) { vga[i] = colorAttr; } restore_IRQs(flags); } void VGAPrintf(uint color, uint bgColor, int startX, int startY, const char *format, ...) { int flags; char tmp[fbWidth]; int idx = 0; disable_IRQs(flags); va_list ap; va_start(ap, format); int ret = vsnprintf(tmp, sizeof(tmp), format, ap); while (ret > 0 && tmp[idx]) { printCharDetails(tmp[idx++], color, bgColor, startX++, startY); } va_end(ap); restore_IRQs(flags); } static void printCharDetails(const char str, uint color, uint bgColor, int startX, int startY) { int pos = fbWidth * startY + startX; if (pos > (int)(fbWidth * fbHeight) || pos < 0) return; long int colorAttr = (bgColor << 4 | (color & 0x0f)) << 8; vga[pos] = colorAttr | str; } void VGAScrollUp(void) { long int colorAttr = vgaBgColor << 12; int flags; disable_IRQs(flags); for (uint i = 1; i < fbHeight - VGA_STATUS_LINE_HEIGHT; i++) { // last line is status line. Do not scroll it memcpy((void *)&vga[fbWidth * (i - 1)], (void *)&vga[fbWidth * i], fbWidth * sizeof(short)); } for (uint i = 0; i < fbWidth; i++) { vga[(fbHeight - 1 - VGA_STATUS_LINE_HEIGHT) * fbWidth + i] = colorAttr; } restore_IRQs(flags); } void VGAPutc(const char str) { int flags; disable_IRQs(flags); if (str == '\n') { line++; col = 0; if (line >= (int)(fbHeight - VGA_STATUS_LINE_HEIGHT)) { VGAScrollUp(); line--; } } else if (str == '\r') { col = 0; } else if (str == '\b') { col--; if (col < 0) { col = fbWidth - 1; line--; if (line < 0) line = 0; } printCharDetails(' ', vgaColor, vgaBgColor, col, line); } else { printCharDetails(str, vgaColor, vgaBgColor, col++, line); if (col == (int)fbWidth) { col = 0; line++; } if (line >= (int)(fbHeight - VGA_STATUS_LINE_HEIGHT)) { VGAScrollUp(); line--; } } cursorMove(col, line); restore_IRQs(flags); } static void cursorEnable(uint8_t cursor_start, uint8_t cursor_end) { outb(0x3D4, 0x0A); outb(0x3D5, (inb(0x3D5) & 0xC0) | cursor_start); outb(0x3D4, 0x0B); outb(0x3D5, (inb(0x3D5) & 0xE0) | cursor_end); } void cursorDisable(void) { outb(0x3D4, 0x0A); outb(0x3D5, 0x20); } static void cursorMove(int x, int y) { long int colorAttr = (vgaBgColor << 4 | (vgaColor & 0x0f)) << 8; uint16_t pos = y * fbWidth + x; vga[pos] = colorAttr; outb(0x3D4, 0x0F); outb(0x3D5, (uint8_t)(pos & 0xFF)); outb(0x3D4, 0x0E); outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF)); } void VGAMap(void){ for (paddr_t i = (paddr_t)vga; i < (paddr_t)vga + fbWidth * fbHeight * sizeof(short) ; i += PAGE_SIZE) { pageMap(i, i, PAGING_MEM_WRITE); } }