vga.c (3418B)
1 #include <drivers/video/vga.h> 2 3 // Helper functions for port IO 4 static inline void 5 outb(uint16_t port, uint8_t val) 6 { 7 __asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); 8 } 9 10 static inline uint8_t 11 inb(uint16_t port) 12 { 13 uint8_t ret; 14 __asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port)); 15 return ret; 16 } 17 18 // Write vga registers for mode change 19 static void 20 write_regs(uint8_t *regs) 21 { 22 unsigned i; 23 24 // Write misc output register 25 outb(VGA_MISC_WRITE, *regs); 26 regs++; 27 28 // Write sequencer registers (5 registers) 29 for (i = 0; i < 5; i++) { 30 outb(VGA_SEQ_INDEX, i); 31 outb(VGA_SEQ_DATA, *regs); 32 regs++; 33 } 34 35 // Unlock CRTC registers 0-7 by clearing protect bit 36 outb(VGA_CRTC_INDEX, 0x03); 37 outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) | 0x80); 38 outb(VGA_CRTC_INDEX, 0x11); 39 outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) & ~0x80); 40 41 // Update the register values to match 42 regs[0x03] = regs[0x03] | 0x80; 43 regs[0x11] = regs[0x11] & ~0x80; 44 45 // Write CRTC registers (25 registers) 46 for (i = 0; i < 25; i++) { 47 outb(VGA_CRTC_INDEX, i); 48 outb(VGA_CRTC_DATA, *regs); 49 regs++; 50 } 51 52 // Write graphics controller registers (9 registers) 53 for (i = 0; i < 9; i++) { 54 outb(VGA_GC_INDEX, i); 55 outb(VGA_GC_DATA, *regs); 56 regs++; 57 } 58 59 // Write attribute controller registers (21 registers) 60 for (i = 0; i < 21; i++) { 61 inb(VGA_INSTAT_READ); // Reset flip-flop 62 outb(VGA_AC_INDEX, i); 63 outb(VGA_AC_WRITE, *regs); 64 regs++; 65 } 66 67 // Enable video display 68 inb(VGA_INSTAT_READ); 69 outb(VGA_AC_INDEX, 0x20); 70 } 71 72 void 73 vga_set_mode_13h(void) 74 { 75 // Register values for VGA mode 13h (320x200, 256 colors) 76 // Order: Misc, Seq[5], CRTC[25], GC[9], AC[21] 77 static uint8_t mode_320x200x256[] = { 78 // Misc output register 79 0x63, 80 // Sequencer registers 81 0x03, 0x01, 0x0F, 0x00, 0x0E, 82 // CRTC registers 83 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 84 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 85 0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3, 86 0xFF, 87 // Graphics controller registers 88 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 89 0xFF, 90 // Attribute controller registers 91 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 92 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 93 0x41, 0x00, 0x0F, 0x00, 0x00 94 }; 95 96 write_regs(mode_320x200x256); 97 } 98 99 void 100 vga_put_pixel(uint16_t x, uint16_t y, uint8_t color) 101 { 102 // check bounds 103 if (x >= VGA_WIDTH || y >= VGA_HEIGHT) return; 104 105 // Direct write to video memory: offset = y * 320 + x 106 uint8_t *vga = (uint8_t *)VGA_GRAPHICS_BUFFER; 107 vga[y * VGA_WIDTH + x] = color; 108 } 109 110 void 111 vga_clear_screen(uint8_t color) 112 { 113 uint8_t *vga = (uint8_t *)VGA_GRAPHICS_BUFFER; 114 // fill entire buffer (64k pixels) 115 for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) { 116 vga[i] = color; 117 } 118 }