cowos

custom OS from scratch in C
git clone git://git.daat.foo/cowos.git
Log | Files | Refs | README | LICENSE

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 }