summaryrefslogtreecommitdiff
path: root/src/drivers/video/vga.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/video/vga.c')
-rw-r--r--src/drivers/video/vga.c235
1 files changed, 101 insertions, 134 deletions
diff --git a/src/drivers/video/vga.c b/src/drivers/video/vga.c
index 094a117..c38bee1 100644
--- a/src/drivers/video/vga.c
+++ b/src/drivers/video/vga.c
@@ -11,10 +11,83 @@
static vga_vtable_t const vga_vtable = {
{
- vga_activate,
- vga_deactivate,
- vga_deinit,
- vga_print_info
+ {
+ vga_activate,
+ vga_deactivate,
+ vga_deinit,
+ vga_print_info
+ },
+ video_register_mode,
+ video_supports_mode,
+ video_set_mode,
+ vga_switch_mode
+ }
+};
+
+// from http://files.osdev.org/mirrors/geezer/osd/graphics/modes.c
+static vga_mode_t modes[] = {
+ { { VIDEO_MODE_TYPE_TEXT, 640, 480, 4 },
+ {
+ /* MISC */
+ 0x67,
+ /* SEQ */
+ 0x03, 0x00, 0x03, 0x00, 0x02,
+ /* CRTC */
+ 0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F,
+ 0x00, 0x4F, 0x0D, 0x0E, 0x00, 0x00, 0x00, 0x50,
+ 0x9C, 0x0E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3,
+ 0xFF,
+ /* GC */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00,
+ 0xFF,
+ /* AC */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x0C, 0x00, 0x0F, 0x08, 0x00
+ },
+ NULL
+ },
+ { { VIDEO_MODE_TYPE_GRAPHICS, 320, 200, 8 },
+ {
+ /* MISC */
+ 0x63,
+ /* SEQ */
+ 0x03, 0x01, 0x0F, 0x00, 0x0E,
+ /* CRTC */
+ 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F,
+ 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
+ 0xFF,
+ /* GC */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ /* AC */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00
+ },
+ NULL
+ },
+ { { VIDEO_MODE_TYPE_GRAPHICS, 640, 480, 4 },
+ {
+ /* MISC */
+ 0xE3,
+ /* SEQ */
+ 0x03, 0x01, 0x08, 0x00, 0x06,
+ /* CRTC */
+ 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xEA, 0x0C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF,
+ /* GC */
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0F,
+ 0xFF,
+ /* AC */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x01, 0x00, 0x0F, 0x00, 0x00
+ },
+ NULL
}
};
@@ -22,7 +95,7 @@ void vga_init( vga_t *vga, interrupt_t *interrupt, void *context )
{
memset( vga, 0, sizeof( vga_t ) );
- driver_init( (driver_t *)vga, DRIVER_TYPE_VIDEO, interrupt, context );
+ video_init( (video_t *)vga, interrupt, context );
port8_init( &vga->misc_port, 0x3C2 );
port8_init( &vga->crtc_index_port, 0x3D4 );
@@ -37,6 +110,11 @@ void vga_init( vga_t *vga, interrupt_t *interrupt, void *context )
port8_init( &vga->attribute_controller_reset_port, 0x3DA );
((driver_t *)vga)->vtable = (driver_vtable_t *)&vga_vtable;
+
+ // register modes
+ for( int i = 0; modes[i].base.x != 0; i++ ) {
+ ((video_vtable_t *)(vga->base.base.vtable))->register_mode( vga, (const video_mode_t *)&modes[i] );
+ }
}
void vga_activate( void *obj )
@@ -106,113 +184,7 @@ static void write_registers( vga_t *vga, uint8_t *regs )
(void)port8_read( &vga->attribute_controller_reset_port );
port8_write( &vga->attribute_controller_index_port, 0x20 );
}
-
-vga_mode_t vga_make_mode( const vga_mode_type_t mode_type, const int x, const int y, const int color_depth )
-{
- vga_mode_t mode;
-
- mode.mode_type = mode_type;
- mode.x = x;
- mode.y = y;
- mode.color_depth = color_depth;
-
- return mode;
-}
-// from http://files.osdev.org/mirrors/geezer/osd/graphics/modes.c
-static vga_mode_t modes[] = {
- { VGA_MODE_TYPE_TEXT, 640, 480, 4,
- {
- /* MISC */
- 0x67,
- /* SEQ */
- 0x03, 0x00, 0x03, 0x00, 0x02,
- /* CRTC */
- 0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F,
- 0x00, 0x4F, 0x0D, 0x0E, 0x00, 0x00, 0x00, 0x50,
- 0x9C, 0x0E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3,
- 0xFF,
- /* GC */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00,
- 0xFF,
- /* AC */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
- 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
- 0x0C, 0x00, 0x0F, 0x08, 0x00
- },
- NULL
- },
- { VGA_MODE_TYPE_GRAPHICS, 320, 200, 8,
- {
- /* MISC */
- 0x63,
- /* SEQ */
- 0x03, 0x01, 0x0F, 0x00, 0x0E,
- /* CRTC */
- 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F,
- 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
- 0xFF,
- /* GC */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
- 0xFF,
- /* AC */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x41, 0x00, 0x0F, 0x00, 0x00
- },
- NULL
- },
- { VGA_MODE_TYPE_GRAPHICS, 640, 480, 4,
- {
- /* MISC */
- 0xE3,
- /* SEQ */
- 0x03, 0x01, 0x08, 0x00, 0x06,
- /* CRTC */
- 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E,
- 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xEA, 0x0C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
- 0xFF,
- /* GC */
- 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0F,
- 0xFF,
- /* AC */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
- 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
- 0x01, 0x00, 0x0F, 0x00, 0x00
- },
- NULL
- }
-};
-
-bool vga_supports_mode( const vga_mode_t mode )
-{
- for( int i = 0; modes[i].x != 0; i++ ) {
- if( mode.mode_type == modes[i].mode_type &&
- mode.x == modes[i].x &&
- mode.y == modes[i].y &&
- mode.color_depth == modes[i].color_depth ) {
- return true;
- }
- }
-
- return false;
-}
-
-static int get_matching_mode_idx( const vga_mode_t mode )
-{
- for( int i = 0; modes[i].x != 0; i++ ) {
- if( mode.mode_type == modes[i].mode_type &&
- mode.x == modes[i].x &&
- mode.y == modes[i].y &&
- mode.color_depth == modes[i].color_depth ) {
- return i;
- }
- }
-
- return -1;
-}
static uint8_t *get_frame_buffer_segment( vga_t *vga )
{
@@ -273,27 +245,22 @@ static size_t get_frame_buffer_segment_size( vga_t *vga )
return segment_size;
}
-bool vga_set_mode( vga_t *vga, const vga_mode_t mode )
+bool vga_switch_mode( void *obj, const video_mode_t *mode )
{
- // do not allow unknown timings!
- if( !vga_supports_mode( mode ) ) {
- return false;
- }
-
- vga_mode_t matching_mode = modes[get_matching_mode_idx( mode )];
+ vga_t *vga = (vga_t *)obj;
+ vga_mode_t *vga_mode = (vga_mode_t *)mode;
- write_registers( vga, matching_mode.regs );
+ write_registers( vga, vga_mode->regs );
- vga->mode = mode;
- vga->mode.segment = get_frame_buffer_segment( vga );
- vga->mode.segment_size = get_frame_buffer_segment_size( vga );
+ vga->mode = (vga_mode_t *)mode;
+ vga->mode->segment = get_frame_buffer_segment( vga );
+ vga->mode->segment_size = get_frame_buffer_segment_size( vga );
vga_use_z_buffer( vga, false );
return true;
}
-
vga_color_t vga_make_RGB( int R, int G, int B )
{
vga_color_t c;
@@ -336,7 +303,7 @@ static uint8_t get_color_index( const vga_color_t c )
static bool params_ok( vga_t *vga, const int x, const int y )
{
- if( x < 0 || x > vga->mode.x || y < 0 || y > vga->mode.y ) {
+ if( x < 0 || x > vga->mode->base.x || y < 0 || y > vga->mode->base.y ) {
return false;
}
@@ -347,12 +314,12 @@ void vga_set_pixel( vga_t *vga, const int x, const int y, const vga_color_t colo
{
if( !params_ok( vga, x, y ) ) {
kernel_panic( "Pixel coordinates are out of bounds: (%d, %d), resolution is only (%d, %d)",
- x, y, vga->mode.x, vga->mode.y );
+ x, y, vga->mode->base.x, vga->mode->base.y );
}
uint8_t color_idx = get_color_index( color );
- uint8_t *addr = vga->base_addr + vga->mode.x * y + x;
+ uint8_t *addr = vga->base_addr + vga->mode->base.x * y + x;
*addr = color_idx;
}
@@ -361,18 +328,18 @@ void vga_draw_rectangle( vga_t *vga, const int x, const int y, const int w, cons
{
if( !params_ok( vga, x, y ) ) {
kernel_panic( "Rectangle start coordinates are out of bounds: (%d, %d), resolution is only (%d, %d)",
- x, y, vga->mode.x, vga->mode.y );
+ x, y, vga->mode->base.x, vga->mode->base.y );
}
if( !params_ok( vga, x + w, y + h ) ) {
kernel_panic( "Rectangle end coordinates are out of bounds: (%d, %d), resolution is only (%d, %d)",
- x + w, y + h, vga->mode.x, vga->mode.y );
+ x + w, y + h, vga->mode->base.x, vga->mode->base.y );
}
uint8_t color_idx = get_color_index( color );
for( int yy = y; yy < y + h; yy++ ) {
- uint8_t *addr = vga->base_addr + vga->mode.x * yy + x;
+ uint8_t *addr = vga->base_addr + vga->mode->base.x * yy + x;
memset( addr, color_idx, w );
}
}
@@ -380,7 +347,7 @@ void vga_draw_rectangle( vga_t *vga, const int x, const int y, const int w, cons
void vga_clear_screen( vga_t *vga, const vga_color_t color )
{
memset( vga->base_addr, get_color_index( color ),
- vga->mode.x * vga->mode.y );
+ vga->mode->base.x * vga->mode->base.y );
}
void vga_draw_char( vga_t *vga, const unsigned char c, const int x, const int y, const vga_color_t background, const vga_color_t foreground )
@@ -412,7 +379,7 @@ void vga_draw_char( vga_t *vga, const unsigned char c, const int x, const int y,
data[vga_font.Width-1-xx] = fg_color_idx;
}
}
- uint8_t *addr = vga->base_addr + vga->mode.x * ( y + yy ) + x;
+ uint8_t *addr = vga->base_addr + vga->mode->base.x * ( y + yy ) + x;
memcpy( addr, data, vga_font.Width );
}
}
@@ -432,14 +399,14 @@ void vga_use_z_buffer( vga_t *vga, bool use )
vga->use_z_buffer = use;
if( vga->use_z_buffer ) {
- vga->zbuffer = (uint8_t *)malloc( vga->mode.segment_size );
+ vga->zbuffer = (uint8_t *)malloc( vga->mode->segment_size );
vga->base_addr = &vga->zbuffer[0];
} else {
if( vga->zbuffer != NULL ) {
free( vga->zbuffer );
vga->zbuffer = NULL;
}
- vga->base_addr = vga->mode.segment;
+ vga->base_addr = vga->mode->segment;
}
}
@@ -447,7 +414,7 @@ void vga_refresh( vga_t *vga )
{
if( vga->use_z_buffer ) {
vga_wait_for_retrace( vga );
- memcpy( vga->mode.segment, vga->zbuffer, vga->mode.segment_size );
+ memcpy( vga->mode->segment, vga->zbuffer, vga->mode->segment_size );
}
}