matos/drivers/vga.c

185 lines
4.2 KiB
C
Raw Permalink Normal View History

2018-07-20 15:41:58 +02:00
#include "vga.h"
#include "io.h"
2020-08-20 23:54:01 +02:00
#include "irq.h"
2021-01-24 23:51:21 +01:00
#include "klibc.h"
2021-10-25 21:29:02 +02:00
#include "paging.h"
#include "mem.h"
2018-07-20 15:41:58 +02:00
static uint vgaBgColor;
static uint vgaColor;
static int line, col;
2021-01-24 23:51:21 +01:00
static volatile short *vga = (short *)VGA_ADDR;
2021-10-25 21:29:02 +02:00
static uint fbWidth = VGA_WIDTH;
static uint fbHeight = VGA_HEIGHT;
2021-01-24 23:51:21 +01:00
static void clearScreen(uint bgColor);
2021-01-25 14:00:06 +01:00
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);
2021-01-24 23:51:21 +01:00
2018-11-08 22:08:27 +01:00
int VGASetup(uint bgColor, uint color)
2018-07-20 15:41:58 +02:00
{
vgaBgColor = bgColor;
vgaColor = color;
2021-01-24 23:51:21 +01:00
line = 0;
col = 0;
clearScreen(bgColor);
2021-01-25 14:00:06 +01:00
cursorEnable(14, 15);
return 0;
2018-07-20 15:41:58 +02:00
}
2021-10-25 21:29:02 +02:00
int VGAConfigure(int addr, uint width, uint height){
vga = (short *)addr;
fbWidth = width;
fbHeight = height;
return 0;
}
2021-01-24 23:51:21 +01:00
static void clearScreen(uint bgColor)
2018-07-20 15:41:58 +02:00
{
2020-08-20 23:54:01 +02:00
uint32_t flags;
2021-01-25 20:05:38 +01:00
long int colorAttr = bgColor << 12;
2020-08-20 23:54:01 +02:00
disable_IRQs(flags);
2021-10-25 21:29:02 +02:00
for (uint i = 0; i < fbWidth * fbHeight; i++) {
vga[i] = colorAttr;
}
2020-08-20 23:54:01 +02:00
restore_IRQs(flags);
2018-07-20 15:41:58 +02:00
}
2021-01-25 14:00:06 +01:00
void VGAclearLine(uint bgColor, uint line)
2018-11-16 19:56:38 +01:00
{
2020-08-20 23:54:01 +02:00
uint32_t flags;
2021-01-25 20:05:38 +01:00
long int colorAttr = bgColor << 12;
2020-08-20 23:54:01 +02:00
2021-10-25 21:29:02 +02:00
if (line >= fbHeight)
2021-01-24 23:51:21 +01:00
return;
2020-08-20 23:54:01 +02:00
disable_IRQs(flags);
2021-10-25 21:29:02 +02:00
for (uint i = fbWidth * line; i < fbWidth * (line + 1); i++) {
vga[i] = colorAttr;
}
2020-08-20 23:54:01 +02:00
restore_IRQs(flags);
2018-11-16 19:56:38 +01:00
}
2021-01-25 14:00:06 +01:00
void VGAPrintf(uint color, uint bgColor, int startX, int startY, const char *format, ...)
2018-07-20 15:41:58 +02:00
{
2021-01-24 23:51:21 +01:00
int flags;
2021-10-25 21:29:02 +02:00
char tmp[fbWidth];
2021-01-25 20:05:38 +01:00
int idx = 0;
2021-01-24 23:51:21 +01:00
disable_IRQs(flags);
va_list ap;
va_start(ap, format);
2021-01-25 20:05:38 +01:00
int ret = vsnprintf(tmp, sizeof(tmp), format, ap);
2021-01-24 23:51:21 +01:00
while (ret > 0 && tmp[idx]) {
2021-01-25 20:05:38 +01:00
printCharDetails(tmp[idx++], color, bgColor, startX++, startY);
}
2021-01-24 23:51:21 +01:00
va_end(ap);
restore_IRQs(flags);
2018-07-20 15:41:58 +02:00
}
2021-01-25 14:00:06 +01:00
static void printCharDetails(const char str, uint color, uint bgColor, int startX, int startY)
2018-07-20 15:41:58 +02:00
{
2021-10-25 21:29:02 +02:00
int pos = fbWidth * startY + startX;
2021-01-25 20:05:38 +01:00
2021-10-25 21:29:02 +02:00
if (pos > (int)(fbWidth * fbHeight) || pos < 0)
2021-01-25 20:05:38 +01:00
return;
long int colorAttr = (bgColor << 4 | (color & 0x0f)) << 8;
vga[pos] = colorAttr | str;
2018-07-20 15:41:58 +02:00
}
2021-01-25 14:00:06 +01:00
void VGAScrollUp(void)
2018-07-20 15:41:58 +02:00
{
2021-01-25 20:05:38 +01:00
long int colorAttr = vgaBgColor << 12;
2020-08-20 23:54:01 +02:00
int flags;
disable_IRQs(flags);
2021-10-25 21:29:02 +02:00
for (uint i = 1; i < fbHeight - VGA_STATUS_LINE_HEIGHT;
2021-01-25 20:05:38 +01:00
i++) { // last line is status line. Do not scroll it
2021-10-25 21:29:02 +02:00
memcpy((void *)&vga[fbWidth * (i - 1)], (void *)&vga[fbWidth * i],
fbWidth * sizeof(short));
}
2021-10-25 21:29:02 +02:00
for (uint i = 0; i < fbWidth; i++) {
vga[(fbHeight - 1 - VGA_STATUS_LINE_HEIGHT) * fbWidth + i] = colorAttr;
}
2020-08-20 23:54:01 +02:00
restore_IRQs(flags);
2018-07-20 15:41:58 +02:00
}
2021-01-25 14:00:06 +01:00
void VGAPutc(const char str)
2018-07-20 15:41:58 +02:00
{
2020-08-20 23:54:01 +02:00
int flags;
disable_IRQs(flags);
if (str == '\n') {
line++;
col = 0;
2021-10-25 21:29:02 +02:00
if (line >= (int)(fbHeight - VGA_STATUS_LINE_HEIGHT)) {
2021-01-25 14:00:06 +01:00
VGAScrollUp();
line--;
}
} else if (str == '\r') {
col = 0;
} else if (str == '\b') {
col--;
if (col < 0) {
2021-10-25 21:29:02 +02:00
col = fbWidth - 1;
line--;
2021-01-25 20:05:38 +01:00
if (line < 0)
line = 0;
}
printCharDetails(' ', vgaColor, vgaBgColor, col, line);
} else {
printCharDetails(str, vgaColor, vgaBgColor, col++, line);
2021-10-25 21:29:02 +02:00
if (col == (int)fbWidth) {
col = 0;
line++;
}
2021-10-25 21:29:02 +02:00
if (line >= (int)(fbHeight - VGA_STATUS_LINE_HEIGHT)) {
2021-01-25 14:00:06 +01:00
VGAScrollUp();
line--;
}
}
2018-07-20 15:41:58 +02:00
2021-01-24 23:51:21 +01:00
cursorMove(col, line);
2020-08-20 23:54:01 +02:00
restore_IRQs(flags);
2018-07-20 15:41:58 +02:00
}
2018-11-14 18:03:11 +01:00
2021-01-25 14:00:06 +01:00
static void cursorEnable(uint8_t cursor_start, uint8_t cursor_end)
2018-11-14 18:03:11 +01:00
{
outb(0x3D4, 0x0A);
outb(0x3D5, (inb(0x3D5) & 0xC0) | cursor_start);
2018-11-14 18:03:11 +01:00
outb(0x3D4, 0x0B);
outb(0x3D5, (inb(0x3D5) & 0xE0) | cursor_end);
2018-11-14 18:03:11 +01:00
}
void cursorDisable(void)
{
outb(0x3D4, 0x0A);
outb(0x3D5, 0x20);
2018-11-14 18:03:11 +01:00
}
2021-01-25 14:00:06 +01:00
static void cursorMove(int x, int y)
2018-11-14 18:03:11 +01:00
{
2021-01-25 20:05:38 +01:00
long int colorAttr = (vgaBgColor << 4 | (vgaColor & 0x0f)) << 8;
2021-10-25 21:29:02 +02:00
uint16_t pos = y * fbWidth + x;
2021-01-25 20:05:38 +01:00
vga[pos] = colorAttr;
outb(0x3D4, 0x0F);
outb(0x3D5, (uint8_t)(pos & 0xFF));
outb(0x3D4, 0x0E);
outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
2018-11-14 18:03:11 +01:00
}
2021-10-25 21:29:02 +02:00
void VGAMap(void){
for (paddr_t i = VGA_ADDR; i < VGA_ADDR + VGA_WIDTH * VGA_HEIGHT * sizeof(short) ; i += PAGE_SIZE) {
pageMap(i, i, PAGING_MEM_WRITE);
}
}