diff options
Diffstat (limited to 'src/drivers/video/vga.c')
-rw-r--r-- | src/drivers/video/vga.c | 235 |
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 ); } } |