diff options
author | nthnluu <nate1299@me.com> | 2024-01-28 21:20:27 -0500 |
---|---|---|
committer | nthnluu <nate1299@me.com> | 2024-01-28 21:20:27 -0500 |
commit | c63f340d90800895f007de64b7d2d14624263331 (patch) | |
tree | 2c0849fa597dd6da831c8707b6f2603403778d7b /kernel/drivers/screen.c |
Created student weenix repository
Diffstat (limited to 'kernel/drivers/screen.c')
-rw-r--r-- | kernel/drivers/screen.c | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/kernel/drivers/screen.c b/kernel/drivers/screen.c new file mode 100644 index 0000000..a14ad08 --- /dev/null +++ b/kernel/drivers/screen.c @@ -0,0 +1,513 @@ +#include <boot/config.h> +#include <boot/multiboot_macros.h> +#include <drivers/screen.h> +#include <multiboot.h> +#include <types.h> +#include <util/debug.h> +#include <util/string.h> + +#ifdef __VGABUF___ + +#define BITMAP_HEIGHT 13 + +// https://stackoverflow.com/questions/2156572/c-header-file-with-bitmapped-fonts +unsigned const char bitmap_letters[95][BITMAP_HEIGHT] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00}, // space :32 + {0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18}, // ! :33 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, + 0x36}, + {0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, + 0x00}, + {0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, + 0x18}, + {0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, + 0x70}, + {0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, + 0x38}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, + 0x0e}, + {0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, + 0x0c}, + {0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, + 0x30}, + {0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, + 0x00}, + {0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, + 0x00}, + {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, + 0x03}, + {0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, + 0x3c}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, + 0x18}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, + 0x7e}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, + 0x7e}, + {0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, + 0x0c}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, + 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, + 0x7e}, + {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, + 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, + 0x7e}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, + 0x7e}, + {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, + 0x06}, + {0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, + 0x60}, + {0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, + 0x7e}, + {0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, + 0x18}, + {0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, + 0xfe}, + {0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, + 0x7e}, + {0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, + 0xfc}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, + 0xff}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, + 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, + 0x7e}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, + 0xc3}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x7e}, + {0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06}, + {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, + 0xc3}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, + 0xc0}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, + 0xc3}, + {0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, + 0xe3}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, + 0x7e}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, + 0xfe}, + {0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, + 0x3c}, + {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, + 0xfe}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, + 0x7e}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, + 0xc3}, + {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, + 0xc3}, + {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, + 0xc3}, + {0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, + 0xc3}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, + 0xc3}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, + 0xff}, + {0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x3c}, + {0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, + 0x60}, + {0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x3c}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, + 0x18}, + {0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, + 0x70}, + {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, + 0xc0}, + {0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, + 0x03}, + {0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, + 0x1e}, + {0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, + 0xc0}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, + 0x00}, + {0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, + 0x00}, + {0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, + 0xc0}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x78}, + {0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00}, + {0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, + 0x00}, + {0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, + 0x00}, + {0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, + 0x00}, + {0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, + 0x00}, + {0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, + 0x0f}, + {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18}, + {0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, + 0xf0}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, + 0x00}, +}; + +#define DOUBLE_BUFFERING 0 + +#define BITWISE_TERNARY(condition, x, y) \ + (!!(condition) * (x) + !(condition) * (y)) + +static uint32_t *fb; +static uint32_t fb_width; +static uint32_t fb_height; +static uint32_t fb_pitch; + +static uint32_t *fb_buffer; + +void screen_init() +{ + static long inited = 0; + if (inited) + return; + inited = 1; + + struct multiboot_tag_framebuffer *fb_tag = NULL; + for (struct multiboot_tag *tag = + (struct multiboot_tag *)((uintptr_t)(mb_tag + 1) + PHYS_OFFSET); + tag->type != MULTIBOOT_TAG_TYPE_END; tag += TAG_SIZE(tag->size)) + { + if (tag->type != MULTIBOOT_TAG_TYPE_FRAMEBUFFER) + { + continue; + } + fb_tag = (struct multiboot_tag_framebuffer *)tag; + break; + } + KASSERT(fb_tag); + + fb = (uint32_t *)(PHYS_OFFSET + fb_tag->common.framebuffer_addr); + fb_width = fb_tag->common.framebuffer_width; + fb_height = fb_tag->common.framebuffer_height; + fb_pitch = fb_tag->common.framebuffer_pitch; + KASSERT(fb_pitch == fb_width * sizeof(uint32_t)); + KASSERT(fb_tag->common.framebuffer_bpp == 32); + KASSERT(fb_tag->common.framebuffer_type == 1); + KASSERT(fb_tag->framebuffer_red_field_position == 0x10); + KASSERT(fb_tag->framebuffer_green_field_position == 0x08); + KASSERT(fb_tag->framebuffer_blue_field_position == 0x00); + KASSERT(fb_tag->framebuffer_red_mask_size); + KASSERT(fb_tag->framebuffer_green_mask_size == 8); + KASSERT(fb_tag->framebuffer_blue_mask_size == 8); + + size_t npages = 0; + for (uintptr_t page = (uintptr_t)PAGE_ALIGN_DOWN(fb); + page < (uintptr_t)PAGE_ALIGN_UP(fb + fb_width * fb_height); + page += PAGE_SIZE) + { + page_mark_reserved((void *)(page - PHYS_OFFSET)); + npages++; + } + + struct multiboot_tag_vbe *vbe_info = NULL; + for (struct multiboot_tag *tag = + (struct multiboot_tag *)((uintptr_t)(mb_tag + 1) + PHYS_OFFSET); + tag->type != MULTIBOOT_TAG_TYPE_END; tag += TAG_SIZE(tag->size)) + { + if (tag->type != MULTIBOOT_TAG_TYPE_VBE) + { + continue; + } + vbe_info = (struct multiboot_tag_vbe *)tag; + break; + } + KASSERT(vbe_info); + +#if DOUBLE_BUFFERING + fb_buffer = page_alloc_n(npages); + KASSERT(fb_buffer && "couldn't allocate double buffer for screen"); +#else + fb_buffer = fb; +#endif + pt_map_range(pt_get(), (uintptr_t)fb - PHYS_OFFSET, (uintptr_t)fb, + (uintptr_t)PAGE_ALIGN_UP(fb + fb_width * fb_height), + PT_PRESENT | PT_WRITE, PT_PRESENT | PT_WRITE); + pt_set(pt_get()); + for (uint32_t i = 0; i < fb_width * fb_height; i++) + fb_buffer[i] = 0x008A2BE2; + screen_flush(); +} + +inline size_t screen_get_width() { return fb_width; } + +inline size_t screen_get_height() { return fb_height; } + +inline size_t screen_get_character_width() { return SCREEN_CHARACTER_WIDTH; } + +inline size_t screen_get_character_height() { return SCREEN_CHARACTER_HEIGHT; } + +inline void screen_draw_string(size_t x, size_t y, const char *s, size_t len, + color_t color) +{ + uint32_t *pos = fb_buffer + y * fb_width + x; + while (len--) + { + const char c = *s++; + if (c < ' ' || c > '~') + continue; + const unsigned char *bitmap = bitmap_letters[c - ' ']; + + size_t bm_row = BITMAP_HEIGHT; + while (bm_row--) + { + unsigned char cols = bitmap[bm_row]; + *pos = BITWISE_TERNARY(cols & 0x80, color.value, *pos); + pos++; + *pos = BITWISE_TERNARY(cols & 0x40, color.value, *pos); + pos++; + *pos = BITWISE_TERNARY(cols & 0x20, color.value, *pos); + pos++; + *pos = BITWISE_TERNARY(cols & 0x10, color.value, *pos); + pos++; + *pos = BITWISE_TERNARY(cols & 0x08, color.value, *pos); + pos++; + *pos = BITWISE_TERNARY(cols & 0x04, color.value, *pos); + pos++; + *pos = BITWISE_TERNARY(cols & 0x02, color.value, *pos); + pos++; + *pos = BITWISE_TERNARY(cols & 0x01, color.value, *pos); + pos++; + pos += fb_width - 8; + } + pos = pos - fb_width * BITMAP_HEIGHT + SCREEN_CHARACTER_WIDTH; + } +} + +inline void screen_draw_horizontal(uint32_t *pos, size_t count, color_t color) +{ + // while(count--) *pos++ = color.value; + __asm__ volatile("cld; rep stosl;" ::"a"(color.value), "D"(pos), "c"(count) + : "cc"); +} + +inline void screen_copy_horizontal(uint32_t *from, uint32_t *to, size_t count) +{ + __asm__ volatile("cld; rep movsl;" ::"S"(from), "D"(to), "c"(count) + : "cc"); +} + +inline void screen_draw_rect(size_t x, size_t y, size_t width, size_t height, + color_t color) +{ + uint32_t *top = fb_buffer + y * fb_width + x; + screen_draw_horizontal(top, width, color); + screen_draw_horizontal(top + height * fb_width, width, color); + while (height--) + { + *top = *(top + width) = color.value; + top += fb_width; + } +} + +inline void screen_fill(color_t color) +{ + __asm__ volatile("cld; rep stosl;" ::"a"(color.value), "D"(fb_buffer), + "c"(fb_width * fb_height) + : "cc"); +} + +inline void screen_fill_rect(size_t x, size_t y, size_t width, size_t height, + color_t color) +{ + uint32_t *top = fb_buffer + y * fb_width + x; + while (height--) + { + screen_draw_horizontal(top, width, color); + top += fb_width; + } +} + +inline void screen_copy_rect(size_t fromx, size_t fromy, size_t width, + size_t height, size_t tox, size_t toy) +{ + uint32_t *from = fb_buffer + fromy * fb_width + fromx; + uint32_t *to = fb_buffer + toy * fb_width + tox; + while (height--) + { + screen_copy_horizontal(from, to, width); + from += fb_width; + to += fb_width; + } +} + +inline void screen_flush() +{ +#if DOUBLE_BUFFERING + __asm__ volatile("cld; rep movsl;" ::"S"(fb_buffer), "D"(fb), + "c"(fb_width * fb_height) + : "cc"); +#endif +} + +static char *shutdown_message = "Weenix has halted cleanly!"; +void screen_print_shutdown() +{ + color_t background = {.value = 0x00000000}; + color_t foreground = {.value = 0x00FFFFFF}; + screen_fill(background); + size_t str_len = strlen(shutdown_message); + size_t str_width = str_len * screen_get_character_width(); + size_t str_height = screen_get_character_height(); + screen_draw_string((screen_get_width() - str_width) >> 1, + (screen_get_height() - str_height) >> 1, + shutdown_message, str_len, foreground); +} + +#else + +#include "config.h" +#include "drivers/screen.h" +#include "main/io.h" + +/* Port addresses for the CRT controller */ +#define CRT_CONTROL_ADDR 0x3d4 +#define CRT_CONTROL_DATA 0x3d5 + +/* Addresses we can pass to the CRT_CONTROLL_ADDR port */ +#define CURSOR_HIGH 0x0e +#define CURSOR_LOW 0x0f + +static uintptr_t vga_textbuffer_phys = 0xB8000; +static uint16_t *vga_textbuffer; +static uint16_t vga_blank_screen[VGA_HEIGHT][VGA_WIDTH]; +uint16_t vga_blank_row[VGA_WIDTH]; + +void vga_enable_cursor() +{ + outb(0x3D4, 0x0A); + outb(0x3D5, (inb(0x3D5) & 0xC0) | 0); + + outb(0x3D4, 0x0B); + outb(0x3D5, (inb(0x3D5) & 0xE0) | 15); +} + +void vga_disable_cursor() +{ + outb(0x3D4, 0x0A); + outb(0x3D5, 0x20); +} + +void vga_init() +{ + /* map the VGA textbuffer (vaddr) to the VGA textbuffer physical address */ + size_t pages = + ADDR_TO_PN(PAGE_ALIGN_UP((uintptr_t)sizeof(vga_blank_screen))); + vga_textbuffer = page_alloc_n(pages); + KASSERT(vga_textbuffer); + + pt_map_range(pt_get(), (uintptr_t)vga_textbuffer_phys, + (uintptr_t)vga_textbuffer, + (uintptr_t)vga_textbuffer + ((uintptr_t)PN_TO_ADDR(pages)), + PT_PRESENT | PT_WRITE, PT_PRESENT | PT_WRITE); + pt_set(pt_get()); + + for (size_t i = 0; i < VGA_WIDTH; i++) + { + vga_blank_row[i] = (VGA_DEFAULT_ATTRIB << 8) | ' '; + } + for (size_t i = 0; i < VGA_HEIGHT; i++) + { + memcpy(&vga_blank_screen[i], vga_blank_row, VGA_LINE_SIZE); + } + + vga_enable_cursor(); + vga_clear_screen(); +} + +void vga_set_cursor(size_t row, size_t col) +{ + uint16_t pos = (row * VGA_WIDTH) + col; + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t)(pos & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF)); +} + +void vga_clear_screen() +{ + memcpy(vga_textbuffer, vga_blank_screen, sizeof(vga_blank_screen)); +} + +void vga_write_char_at(size_t row, size_t col, uint16_t v) +{ + KASSERT(row < VGA_HEIGHT && col < VGA_WIDTH); + vga_textbuffer[(row * VGA_WIDTH) + col] = v; +} + +static char *shutdown_message = "Weenix has halted cleanly!"; +void screen_print_shutdown() +{ + vga_disable_cursor(); + vga_clear_screen(); + int x = (VGA_WIDTH - strlen(shutdown_message)) / 2; + int y = VGA_HEIGHT / 2; + + for (size_t i = 0; i < strlen(shutdown_message); i++) + { + vga_write_char_at(y, x + i, + (VGA_DEFAULT_ATTRIB << 8) | shutdown_message[i]); + } +} + +#endif
\ No newline at end of file |