aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/graphics/vesa.c
diff options
context:
space:
mode:
authorMarvin Borner2019-10-15 22:22:23 +0200
committerGitHub2019-10-15 22:22:23 +0200
commit2e988c84fc9b282e7618ba89a5c3b2ef9406121e (patch)
tree6e9741c6b2117796a2e40da1f0fade84c090aac7 /src/kernel/graphics/vesa.c
parent8754542ce074bef0984f91ce1b1cd8aff9b3d5e9 (diff)
parent0e75de0452774c1d4f9a16ff593d9ec2fac829bc (diff)
Merged VESA-paging fix
Fixed paging activation before initialization of VESA driver
Diffstat (limited to 'src/kernel/graphics/vesa.c')
-rw-r--r--src/kernel/graphics/vesa.c134
1 files changed, 78 insertions, 56 deletions
diff --git a/src/kernel/graphics/vesa.c b/src/kernel/graphics/vesa.c
index d19e7d8..3c55f70 100644
--- a/src/kernel/graphics/vesa.c
+++ b/src/kernel/graphics/vesa.c
@@ -5,6 +5,9 @@
#include "../paging/kheap.h"
#include "../io/io.h"
#include "font.h"
+#include "../paging/paging.h"
+
+extern page_directory_t *kernel_directory;
void switch_to_vga() {
serial_write("Force switch to VGA!\n");
@@ -29,92 +32,111 @@ struct edid_data get_edid() {
return *edid;
}
-struct vbe_mode_info *vbe_set_mode(unsigned short mode) {
- serial_write("Setting VBE mode!\n");
+void vbe_set_mode(unsigned short mode) {
+ serial_write("Setting VBE mode: ");
+ serial_write_hex(mode);
+ serial_write("\n");
vesa_available = 0;
regs16_t regs;
regs.ax = 0x4F02;
+ regs.bx = mode;
regs.bx = mode | (1 << 14);
+ disable_paging();
int32(0x10, &regs);
+ enable_paging();
- if (regs.ax == 0x004F) {
- regs.ax = 0x4F01;
- regs.cx = mode;
- regs.es = 0xA000;
- regs.di = 0x0000;
- int32(0x10, &regs);
- if (regs.ax != 0x004F) {
- switch_to_vga();
- return ((void *) 0);
- }
-
- struct vbe_mode_info *vbe_info = (struct vbe_mode_info *) 0xA0000;
-
- vbe_width = vbe_info->width;
- vbe_height = vbe_info->height;
- vbe_bpp = vbe_info->bpp / 8;
- vbe_pitch = vbe_info->pitch;
- fb = (char *) vbe_info->framebuffer;
-
- /*for (int i = 0; i < vbe_width * vbe_height * vbe_bpp; i++) {
- fb[i] = 100;
- fb[i + 1] = 100;
- fb[i + 2] = 100;
- }*/
-
- vesa_available = 1;
-
- return vbe_info;
- } else {
- switch_to_vga();
- return ((void *) 0);
- }
+ if (regs.ax != 0x004F) switch_to_vga();
+ else vesa_available = 1;
}
-void set_optimal_resolution() {
+uint16_t *vbe_get_modes() {
vesa_available = 0;
- struct vbe_info *info = (struct vbe_info *) 0x2000;
- struct vbe_mode_info *mode_info = (struct vbe_mode_info *) 0x3000;
-
- memory_copy(info->signature, "VBE2", 4);
+ char *info_address = (char *) 0x7E00;
+ strcpy(info_address, "VBE2");
+ for (int i = 4; i < 512; i++) *(info_address + i) = 0;
regs16_t regs;
regs.ax = 0x4F00;
regs.es = 0;
- regs.di = 0x2000;
+ regs.di = 0x7E00;
+ disable_paging();
int32(0x10, &regs);
+ enable_paging();
+
+ struct vbe_info *info = (struct vbe_info *) info_address;
if (regs.ax != 0x004F || strcmp(info->signature, "VESA") != 0) {
switch_to_vga();
- return;
+ return ((void *) 0);
}
+ // Get number of modes
uint16_t *mode_ptr = get_ptr(info->video_modes);
- uint16_t mode;
+ int number_modes = 1;
+ for (uint16_t *p = mode_ptr; *p != 0xFFFF; p++) number_modes++;
+
+ uint16_t *video_modes = (uint16_t *) kmalloc(sizeof(uint16_t) * number_modes);
+ for (int i = 0; i < number_modes; i++)
+ video_modes[i] = mode_ptr[i];
+
+ return video_modes;
+}
+
+struct vbe_mode_info *vbe_get_mode_info(uint16_t mode) {
+ regs16_t regs;
+ regs.ax = 0x4F01;
+ regs.cx = mode;
+ regs.es = 0;
+ regs.di = 0x7E00;
+ disable_paging();
+ int32(0x10, &regs);
+ enable_paging();
+
+ struct vbe_mode_info_all *mode_info = (struct vbe_mode_info_all *) 0x7E00;
+ struct vbe_mode_info *mode_info_final = (struct vbe_mode_info *) kmalloc(sizeof(struct vbe_mode_info));
+ mode_info_final->attributes = mode_info->attributes;
+ mode_info_final->width = mode_info->width;
+ mode_info_final->height = mode_info->height;
+ mode_info_final->bpp = mode_info->bpp;
+ mode_info_final->pitch = mode_info->pitch;
+ mode_info_final->memory_model = mode_info->memory_model;
+ mode_info_final->framebuffer = mode_info->framebuffer;
+
+ return mode_info_final;
+}
+
+void set_optimal_resolution() {
+ uint16_t *video_modes = vbe_get_modes();
uint16_t highest = 0x11B;
uint16_t highest_width = 0;
- while ((mode = *mode_ptr++) != 0xFFFF) {
- mode &= 0x1FF;
- regs16_t regs2;
- regs2.ax = 0x4F01;
- regs2.cx = mode;
- regs2.es = get_segment(mode_info);
- regs2.di = get_offset(mode_info);
- int32(0x10, &regs2);
-
- if ((mode_info->attributes & 0x90) != 0x90) continue;
+ for (uint16_t *mode = video_modes; *mode != 0xFFFF; mode++) {
+ struct vbe_mode_info *mode_info = vbe_get_mode_info(*mode);
if (mode_info->width >= highest_width &&
(float) mode_info->width / (float) mode_info->height < 2.0 &&
(mode_info->attributes & 0x1) != 0x1 &&
(mode_info->attributes & 0x90) != 0x90 &&
mode_info->memory_model != 6) {
- highest = mode;
+ highest = *mode;
highest_width = mode_info->width;
+ kfree(mode_info);
}
+ kfree(mode_info);
}
-
+ kfree(video_modes);
+
+ struct vbe_mode_info *highest_info = vbe_get_mode_info(highest);
+ vbe_width = highest_info->width;
+ vbe_height = highest_info->height;
+ vbe_bpp = highest_info->bpp / 8;
+ vbe_pitch = highest_info->pitch;
+ fb = (char *) highest_info->framebuffer;
+ uint32_t fb_psize = vbe_width * vbe_height * vbe_bpp;
+ for (uint32_t z = 0; z < fb_psize; z += 4096)
+ alloc_frame(get_page((uint32_t) (fb + z), 1, kernel_directory), 1, 1);
+
+ serial_write("Reached set mode!\n");
vbe_set_mode(highest);
}
@@ -133,7 +155,7 @@ void vesa_clear() {
}
void vesa_set_pixel(uint16_t x, uint16_t y, uint32_t color) {
- unsigned pos = x * (vbe_bpp) + y * vbe_pitch;
+ unsigned pos = x * vbe_bpp + y * vbe_pitch;
fb[pos] = color & 255;
fb[pos + 1] = (color >> 8) & 255;
fb[pos + 2] = (color >> 16) & 255;
@@ -169,7 +191,7 @@ void vesa_draw_rectangle(int x1, int y1, int x2, int y2, int color) {
}
void vesa_draw_string(char *data) {
- vesa_clear();
+ // vesa_clear(); // PAGE FAULT?!
int i = 0;
while (data[i] != '\0') {
vesa_draw_char(data[i], terminal_x, terminal_y);