-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathvga.c
119 lines (98 loc) · 2.17 KB
/
vga.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include "ports.h"
#include "string.h"
#include "vga.h"
#define VIDEO_MEM 0xb8000
#define VGA_CTL_REG 0x3D4
#define VGA_DATA_REG 0x3D5
#define COLUMNS 80
#define LINES 25
/* FIXME these should go somewhere else */
#define BACKSPACE 0x08
#define TAB 0x09
enum vga_colors {
BLACK = 0x00,
BLUE,
GREEN,
CYAN,
RED,
MAGENTA,
BROWN,
LIGHT_GREY,
DARK_GREY,
LIGHT_BLUE,
LIGHT_GREEN,
LIGHT_CYAN,
LIGHT_RED,
LIGHT_MAGENTA,
LIGHT_BROWN,
WHITE
};
static uint16_t *video_mem = (uint16_t *)VIDEO_MEM;
static uint8_t cursor_x;
static uint8_t cursor_y;
static inline uint8_t
gen_color(uint8_t forground, uint8_t background)
{
return (background << 4) | (forground & 0x0F);
}
static void
update_cursor(uint8_t row, uint8_t col)
{
uint16_t pos = row * COLUMNS + col;
outb(VGA_CTL_REG, 0x0E);
outb(VGA_DATA_REG, pos >> 8);
outb(VGA_CTL_REG, 0x0F);
outb(VGA_DATA_REG, pos);
}
static void
scroll(void)
{
uint16_t blank = ((uint8_t)' ') | gen_color(WHITE, BLACK);
unsigned i;
if (cursor_y < LINES)
return;
for (i = 0; i < (LINES-1)*COLUMNS; i++)
video_mem[i] = video_mem[i + COLUMNS];
wmemset(video_mem + ((LINES - 1)*COLUMNS), blank, COLUMNS);
cursor_y = LINES - 1;
}
void
vga__putch(char c)
{
uint8_t color = gen_color(LIGHT_GREY, BLACK);
uint16_t attribute = color << 8;
uint16_t *location;
if (c == BACKSPACE && cursor_x)
cursor_x--;
else if (c == TAB)
cursor_x = (cursor_x + 8) & ~(8 - 1);
else if (c == '\r')
cursor_x = 0;
else if (c == '\n') {
cursor_x = 0;
cursor_y++;
} else if (c >= ' ') {
location = video_mem + (cursor_y * COLUMNS + cursor_x);
*location = c | attribute;
cursor_x++;
}
if (cursor_x >= COLUMNS) {
cursor_x = 0;
cursor_y++;
}
scroll();
update_cursor(cursor_y, cursor_x);
}
void
vga__puts(const char *s)
{
for (; *s != '\0'; s++)
vga__putch(*s);
}
void
vga__clear(void)
{
uint8_t color = gen_color(WHITE, BLACK);
uint16_t blank = ((uint8_t)' ') | color << 8;
wmemset(video_mem, blank, COLUMNS*LINES);
}