diff options
Diffstat (limited to 'src/kernel/graphics/vesa.c')
-rw-r--r-- | src/kernel/graphics/vesa.c | 134 |
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, ®s); + enable_paging(); - if (regs.ax == 0x004F) { - regs.ax = 0x4F01; - regs.cx = mode; - regs.es = 0xA000; - regs.di = 0x0000; - int32(0x10, ®s); - 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, ®s); + 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, ®s); + 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, ®s2); - - 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); |