X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=kitten%2Fdrivers%2Fconsole%2Fvga.c;fp=kitten%2Fdrivers%2Fconsole%2Fvga.c;h=55e82538b8797f9137f59e28ae5b4fd1e5889e97;hb=66a1a4c7a9edcd7d8bc207aca093d694a6e6b5b2;hp=0000000000000000000000000000000000000000;hpb=f7cf9c19ecb0a589dd45ae0d2c91814bd3c2acc2;p=palacios-OLD.git diff --git a/kitten/drivers/console/vga.c b/kitten/drivers/console/vga.c new file mode 100644 index 0000000..55e8253 --- /dev/null +++ b/kitten/drivers/console/vga.c @@ -0,0 +1,144 @@ +#include +#include +#include + +/** Base address of the VGA frame buffer. */ +static volatile uint8_t * const vga_fb = (uint8_t *) 0xffffffff800b8000ul; + +/** Current cursor row coordinate. */ +static int row = 0; + +/** Current cursor column coordinate. */ +static int col = 0; + +/** Number of rows on the screen. */ +static int nrows = 25; + +/** Number of columns on the screen. */ +static int ncols = 80; + +/** Set when vga console has been initialized. */ +static int initialized = 0; + +/** Calculates the offset in the vga_fb corresponding to (row, col). */ +static inline int cursor(int row, int col) +{ + return (row * ncols * 2) + col * 2; +} + +/** + * Scrolls everything on the screen up by one row. + */ +static void vga_scroll(void) +{ + int i; + + // Move all existing lines up by one + memmove( + (void *) vga_fb, + (void *) (vga_fb + cursor(1, 0)), + (nrows - 1) * ncols * sizeof(uint16_t) + ); + + // Blank the new line at the bottom of the screen + for (i = 0; i < ncols; i++) + vga_fb[cursor(nrows-1, i)] = ' '; +} + +/** + * Moves cursor to the next line. + */ +static void vga_newline(void) +{ + row = row + 1; + col = 0; + + if (row == nrows) { + row = nrows - 1; + vga_scroll(); + } +} + +/** + * Sets the VGA font color. + */ +static void vga_set_font_color(uint8_t color) +{ + int i, j; + for (i = 0; i < nrows; i++) + for (j = 0; j < ncols; j++) + vga_fb[cursor(i, j) + 1] = color; +} + +/** + * Prints a single character to the screen. + */ +static void vga_putc(unsigned char c) +{ + // Print the character + vga_fb[cursor(row, col)] = c; + + // Move cursor + if (++col == ncols) + vga_newline(); +} + +/** + * Writes a string to the screen at the current cursor location. + */ +static void vga_write(struct console *con, const char *str) +{ + unsigned char c; + + while ((c = *str++) != '\0') { + switch (c) { + case '\n': + vga_newline(); + break; + + case '\t': + /* Emulate a TAB */ + vga_putc(' '); + while ((col % 8) != 0) + vga_putc(' '); + break; + + default: + vga_putc(c); + } + } +} + +/** + * VGA console device. + */ +static struct console vga_console = { + .name = "VGA Console", + .write = vga_write +}; + +/** + * Initializes and registers the VGA console driver. + */ +void vga_console_init(void) +{ + if (initialized) { + printk(KERN_ERR "VGA console already initialized.\n"); + return; + } + + vga_set_font_color(0x0F /* White */); + console_register(&vga_console); + initialized = 1; +} + +driver_init(vga_console_init); + +/** + * Sets the row on the screen to start printing at. + * This is used to avoid overwriting BIOS/boot messages. + * At least on x86-64, this is set automatically as part + * of the bootstrap process. + */ +driver_param(row, int); +