This round includes more vgabios porting and refactoring. At the end of this round, all cirrus functions should now be ported - Cirrus vgabios should be feature complete with the lgpl vgabios.
-Kevin
Kevin O'Connor (10): vgabios: Use stored total memory in cirrus code instead of recalculating. vgabios: Set cwidth/cheight/sstart in vgamode_s for cirrus/bochs. vgabios: Extract out current mode finding into new function. vgabios: Move BDA setting from driver code to common code. vgabios: Add support for vesa get/set window function. vgabios: Add support for vbe get/set line length function. vgabios: Add support for VBE get/set display start function. vgabios: Add VBE power management (10h) stub function. vgabios: Minor - pass display address to stdvga_set_cursor_pos(). vgabios: Move stdvga_set_mode() to stdvgamodes.c.
vgasrc/bochsvga.c | 209 +++++++++++++++++++++------------- vgasrc/bochsvga.h | 8 +- vgasrc/clext.c | 317 +++++++++++++++++-------------------------------- vgasrc/clext.h | 8 +- vgasrc/stdvga.c | 183 +++++++++++------------------ vgasrc/stdvga.h | 29 ++--- vgasrc/stdvgaio.c | 1 + vgasrc/stdvgamodes.c | 123 +++++++++++++++++++ vgasrc/vbe.c | 131 ++++++++++++++++++--- vgasrc/vgabios.c | 66 +++++++++-- vgasrc/vgabios.h | 5 +- vgasrc/vgaentry.S | 5 + vgasrc/vgafb.c | 12 +- vgasrc/vgahw.h | 57 +++++++++- 14 files changed, 688 insertions(+), 466 deletions(-)
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/clext.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/vgasrc/clext.c b/vgasrc/clext.c index 5468db3..39f3b2a 100644 --- a/vgasrc/clext.c +++ b/vgasrc/clext.c @@ -404,7 +404,7 @@ static void cirrus_clear_vram(u16 param) { cirrus_enable_16k_granularity(); - u8 count = cirrus_get_memsize() * 4; + u8 count = GET_GLOBAL(VBE_total_memory) / (16 * 1024); u8 i; for (i=0; i<count; i++) { stdvga_grdc_write(0x09, i); @@ -479,7 +479,7 @@ clext_101282(struct bregs *regs) static void clext_101285(struct bregs *regs) { - regs->al = cirrus_get_memsize(); + regs->al = GET_GLOBAL(VBE_total_memory) / (64*1024); }
static void @@ -655,7 +655,7 @@ cirrus_vesa_06h(struct bregs *regs) u32 v = cirrus_get_line_offset(); regs->cx = v / cirrus_get_bpp_bytes(); regs->bx = v; - regs->dx = (cirrus_get_memsize() * 64 * 1024) / v; + regs->dx = GET_GLOBAL(VBE_total_memory) / v; regs->ax = 0x004f; }
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/bochsvga.c | 122 ++++++++++++++++++++++++++-------------------------- vgasrc/clext.c | 32 +++++++------- vgasrc/vbe.c | 6 +- 3 files changed, 80 insertions(+), 80 deletions(-)
diff --git a/vgasrc/bochsvga.c b/vgasrc/bochsvga.c index cbd0b41..213dbcd 100644 --- a/vgasrc/bochsvga.c +++ b/vgasrc/bochsvga.c @@ -14,68 +14,68 @@ static struct bochsvga_mode struct vgamode_s info; } bochsvga_modes[] VAR16 = { /* standard modes */ - { 0x100, { MM_PACKED, 640, 400, 8 } }, - { 0x101, { MM_PACKED, 640, 480, 8 } }, - { 0x102, { MM_PLANAR, 800, 600, 4 } }, - { 0x103, { MM_PACKED, 800, 600, 8 } }, - { 0x104, { MM_PLANAR, 1024, 768, 4 } }, - { 0x105, { MM_PACKED, 1024, 768, 8 } }, - { 0x106, { MM_PLANAR, 1280, 1024, 4 } }, - { 0x107, { MM_PACKED, 1280, 1024, 8 } }, - { 0x10D, { MM_DIRECT, 320, 200, 15 } }, - { 0x10E, { MM_DIRECT, 320, 200, 16 } }, - { 0x10F, { MM_DIRECT, 320, 200, 24 } }, - { 0x110, { MM_DIRECT, 640, 480, 15 } }, - { 0x111, { MM_DIRECT, 640, 480, 16 } }, - { 0x112, { MM_DIRECT, 640, 480, 24 } }, - { 0x113, { MM_DIRECT, 800, 600, 15 } }, - { 0x114, { MM_DIRECT, 800, 600, 16 } }, - { 0x115, { MM_DIRECT, 800, 600, 24 } }, - { 0x116, { MM_DIRECT, 1024, 768, 15 } }, - { 0x117, { MM_DIRECT, 1024, 768, 16 } }, - { 0x118, { MM_DIRECT, 1024, 768, 24 } }, - { 0x119, { MM_DIRECT, 1280, 1024, 15 } }, - { 0x11A, { MM_DIRECT, 1280, 1024, 16 } }, - { 0x11B, { MM_DIRECT, 1280, 1024, 24 } }, - { 0x11C, { MM_PACKED, 1600, 1200, 8 } }, - { 0x11D, { MM_DIRECT, 1600, 1200, 15 } }, - { 0x11E, { MM_DIRECT, 1600, 1200, 16 } }, - { 0x11F, { MM_DIRECT, 1600, 1200, 24 } }, + { 0x100, { MM_PACKED, 640, 400, 8, 8, 16, SEG_GRAPH } }, + { 0x101, { MM_PACKED, 640, 480, 8, 8, 16, SEG_GRAPH } }, + { 0x102, { MM_PLANAR, 800, 600, 4, 8, 16, SEG_GRAPH } }, + { 0x103, { MM_PACKED, 800, 600, 8, 8, 16, SEG_GRAPH } }, + { 0x104, { MM_PLANAR, 1024, 768, 4, 8, 16, SEG_GRAPH } }, + { 0x105, { MM_PACKED, 1024, 768, 8, 8, 16, SEG_GRAPH } }, + { 0x106, { MM_PLANAR, 1280, 1024, 4, 8, 16, SEG_GRAPH } }, + { 0x107, { MM_PACKED, 1280, 1024, 8, 8, 16, SEG_GRAPH } }, + { 0x10D, { MM_DIRECT, 320, 200, 15, 8, 16, SEG_GRAPH } }, + { 0x10E, { MM_DIRECT, 320, 200, 16, 8, 16, SEG_GRAPH } }, + { 0x10F, { MM_DIRECT, 320, 200, 24, 8, 16, SEG_GRAPH } }, + { 0x110, { MM_DIRECT, 640, 480, 15, 8, 16, SEG_GRAPH } }, + { 0x111, { MM_DIRECT, 640, 480, 16, 8, 16, SEG_GRAPH } }, + { 0x112, { MM_DIRECT, 640, 480, 24, 8, 16, SEG_GRAPH } }, + { 0x113, { MM_DIRECT, 800, 600, 15, 8, 16, SEG_GRAPH } }, + { 0x114, { MM_DIRECT, 800, 600, 16, 8, 16, SEG_GRAPH } }, + { 0x115, { MM_DIRECT, 800, 600, 24, 8, 16, SEG_GRAPH } }, + { 0x116, { MM_DIRECT, 1024, 768, 15, 8, 16, SEG_GRAPH } }, + { 0x117, { MM_DIRECT, 1024, 768, 16, 8, 16, SEG_GRAPH } }, + { 0x118, { MM_DIRECT, 1024, 768, 24, 8, 16, SEG_GRAPH } }, + { 0x119, { MM_DIRECT, 1280, 1024, 15, 8, 16, SEG_GRAPH } }, + { 0x11A, { MM_DIRECT, 1280, 1024, 16, 8, 16, SEG_GRAPH } }, + { 0x11B, { MM_DIRECT, 1280, 1024, 24, 8, 16, SEG_GRAPH } }, + { 0x11C, { MM_PACKED, 1600, 1200, 8, 8, 16, SEG_GRAPH } }, + { 0x11D, { MM_DIRECT, 1600, 1200, 15, 8, 16, SEG_GRAPH } }, + { 0x11E, { MM_DIRECT, 1600, 1200, 16, 8, 16, SEG_GRAPH } }, + { 0x11F, { MM_DIRECT, 1600, 1200, 24, 8, 16, SEG_GRAPH } }, /* BOCHS modes */ - { 0x140, { MM_DIRECT, 320, 200, 32 } }, - { 0x141, { MM_DIRECT, 640, 400, 32 } }, - { 0x142, { MM_DIRECT, 640, 480, 32 } }, - { 0x143, { MM_DIRECT, 800, 600, 32 } }, - { 0x144, { MM_DIRECT, 1024, 768, 32 } }, - { 0x145, { MM_DIRECT, 1280, 1024, 32 } }, - { 0x146, { MM_PACKED, 320, 200, 8 } }, - { 0x147, { MM_DIRECT, 1600, 1200, 32 } }, - { 0x148, { MM_PACKED, 1152, 864, 8 } }, - { 0x149, { MM_DIRECT, 1152, 864, 15 } }, - { 0x14a, { MM_DIRECT, 1152, 864, 16 } }, - { 0x14b, { MM_DIRECT, 1152, 864, 24 } }, - { 0x14c, { MM_DIRECT, 1152, 864, 32 } }, - { 0x178, { MM_DIRECT, 1280, 800, 16 } }, - { 0x179, { MM_DIRECT, 1280, 800, 24 } }, - { 0x17a, { MM_DIRECT, 1280, 800, 32 } }, - { 0x17b, { MM_DIRECT, 1280, 960, 16 } }, - { 0x17c, { MM_DIRECT, 1280, 960, 24 } }, - { 0x17d, { MM_DIRECT, 1280, 960, 32 } }, - { 0x17e, { MM_DIRECT, 1440, 900, 16 } }, - { 0x17f, { MM_DIRECT, 1440, 900, 24 } }, - { 0x180, { MM_DIRECT, 1440, 900, 32 } }, - { 0x181, { MM_DIRECT, 1400, 1050, 16 } }, - { 0x182, { MM_DIRECT, 1400, 1050, 24 } }, - { 0x183, { MM_DIRECT, 1400, 1050, 32 } }, - { 0x184, { MM_DIRECT, 1680, 1050, 16 } }, - { 0x185, { MM_DIRECT, 1680, 1050, 24 } }, - { 0x186, { MM_DIRECT, 1680, 1050, 32 } }, - { 0x187, { MM_DIRECT, 1920, 1200, 16 } }, - { 0x188, { MM_DIRECT, 1920, 1200, 24 } }, - { 0x189, { MM_DIRECT, 1920, 1200, 32 } }, - { 0x18a, { MM_DIRECT, 2560, 1600, 16 } }, - { 0x18b, { MM_DIRECT, 2560, 1600, 24 } }, - { 0x18c, { MM_DIRECT, 2560, 1600, 32 } }, + { 0x140, { MM_DIRECT, 320, 200, 32, 8, 16, SEG_GRAPH } }, + { 0x141, { MM_DIRECT, 640, 400, 32, 8, 16, SEG_GRAPH } }, + { 0x142, { MM_DIRECT, 640, 480, 32, 8, 16, SEG_GRAPH } }, + { 0x143, { MM_DIRECT, 800, 600, 32, 8, 16, SEG_GRAPH } }, + { 0x144, { MM_DIRECT, 1024, 768, 32, 8, 16, SEG_GRAPH } }, + { 0x145, { MM_DIRECT, 1280, 1024, 32, 8, 16, SEG_GRAPH } }, + { 0x146, { MM_PACKED, 320, 200, 8, 8, 16, SEG_GRAPH } }, + { 0x147, { MM_DIRECT, 1600, 1200, 32, 8, 16, SEG_GRAPH } }, + { 0x148, { MM_PACKED, 1152, 864, 8, 8, 16, SEG_GRAPH } }, + { 0x149, { MM_DIRECT, 1152, 864, 15, 8, 16, SEG_GRAPH } }, + { 0x14a, { MM_DIRECT, 1152, 864, 16, 8, 16, SEG_GRAPH } }, + { 0x14b, { MM_DIRECT, 1152, 864, 24, 8, 16, SEG_GRAPH } }, + { 0x14c, { MM_DIRECT, 1152, 864, 32, 8, 16, SEG_GRAPH } }, + { 0x178, { MM_DIRECT, 1280, 800, 16, 8, 16, SEG_GRAPH } }, + { 0x179, { MM_DIRECT, 1280, 800, 24, 8, 16, SEG_GRAPH } }, + { 0x17a, { MM_DIRECT, 1280, 800, 32, 8, 16, SEG_GRAPH } }, + { 0x17b, { MM_DIRECT, 1280, 960, 16, 8, 16, SEG_GRAPH } }, + { 0x17c, { MM_DIRECT, 1280, 960, 24, 8, 16, SEG_GRAPH } }, + { 0x17d, { MM_DIRECT, 1280, 960, 32, 8, 16, SEG_GRAPH } }, + { 0x17e, { MM_DIRECT, 1440, 900, 16, 8, 16, SEG_GRAPH } }, + { 0x17f, { MM_DIRECT, 1440, 900, 24, 8, 16, SEG_GRAPH } }, + { 0x180, { MM_DIRECT, 1440, 900, 32, 8, 16, SEG_GRAPH } }, + { 0x181, { MM_DIRECT, 1400, 1050, 16, 8, 16, SEG_GRAPH } }, + { 0x182, { MM_DIRECT, 1400, 1050, 24, 8, 16, SEG_GRAPH } }, + { 0x183, { MM_DIRECT, 1400, 1050, 32, 8, 16, SEG_GRAPH } }, + { 0x184, { MM_DIRECT, 1680, 1050, 16, 8, 16, SEG_GRAPH } }, + { 0x185, { MM_DIRECT, 1680, 1050, 24, 8, 16, SEG_GRAPH } }, + { 0x186, { MM_DIRECT, 1680, 1050, 32, 8, 16, SEG_GRAPH } }, + { 0x187, { MM_DIRECT, 1920, 1200, 16, 8, 16, SEG_GRAPH } }, + { 0x188, { MM_DIRECT, 1920, 1200, 24, 8, 16, SEG_GRAPH } }, + { 0x189, { MM_DIRECT, 1920, 1200, 32, 8, 16, SEG_GRAPH } }, + { 0x18a, { MM_DIRECT, 2560, 1600, 16, 8, 16, SEG_GRAPH } }, + { 0x18b, { MM_DIRECT, 2560, 1600, 24, 8, 16, SEG_GRAPH } }, + { 0x18c, { MM_DIRECT, 2560, 1600, 32, 8, 16, SEG_GRAPH } }, };
static u16 dispi_get_max_xres(void) diff --git a/vgasrc/clext.c b/vgasrc/clext.c index 39f3b2a..ea2b428 100644 --- a/vgasrc/clext.c +++ b/vgasrc/clext.c @@ -227,42 +227,42 @@ struct cirrus_mode_s { };
static struct cirrus_mode_s cirrus_modes[] VAR16 = { - {0x5f,{MM_PACKED,640,480,8},0x00, + {0x5f,{MM_PACKED,640,480,8,8,16,SEG_GRAPH},0x00, cseq_640x480x8,cgraph_svgacolor,ccrtc_640x480x8}, - {0x64,{MM_DIRECT,640,480,16},0xe1, + {0x64,{MM_DIRECT,640,480,16,8,16,SEG_GRAPH},0xe1, cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16}, - {0x66,{MM_DIRECT,640,480,15},0xf0, + {0x66,{MM_DIRECT,640,480,15,8,16,SEG_GRAPH},0xf0, cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16}, - {0x71,{MM_DIRECT,640,480,24},0xe5, + {0x71,{MM_DIRECT,640,480,24,8,16,SEG_GRAPH},0xe5, cseq_640x480x24,cgraph_svgacolor,ccrtc_640x480x24},
- {0x5c,{MM_PACKED,800,600,8},0x00, + {0x5c,{MM_PACKED,800,600,8,8,16,SEG_GRAPH},0x00, cseq_800x600x8,cgraph_svgacolor,ccrtc_800x600x8}, - {0x65,{MM_DIRECT,800,600,16},0xe1, + {0x65,{MM_DIRECT,800,600,16,8,16,SEG_GRAPH},0xe1, cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16}, - {0x67,{MM_DIRECT,800,600,15},0xf0, + {0x67,{MM_DIRECT,800,600,15,8,16,SEG_GRAPH},0xf0, cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16},
- {0x60,{MM_PACKED,1024,768,8},0x00, + {0x60,{MM_PACKED,1024,768,8,8,16,SEG_GRAPH},0x00, cseq_1024x768x8,cgraph_svgacolor,ccrtc_1024x768x8}, - {0x74,{MM_DIRECT,1024,768,16},0xe1, + {0x74,{MM_DIRECT,1024,768,16,8,16,SEG_GRAPH},0xe1, cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16}, - {0x68,{MM_DIRECT,1024,768,15},0xf0, + {0x68,{MM_DIRECT,1024,768,15,8,16,SEG_GRAPH},0xf0, cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16},
- {0x78,{MM_DIRECT,800,600,24},0xe5, + {0x78,{MM_DIRECT,800,600,24,8,16,SEG_GRAPH},0xe5, cseq_800x600x24,cgraph_svgacolor,ccrtc_800x600x24}, - {0x79,{MM_DIRECT,1024,768,24},0xe5, + {0x79,{MM_DIRECT,1024,768,24,8,16,SEG_GRAPH},0xe5, cseq_1024x768x24,cgraph_svgacolor,ccrtc_1024x768x24},
- {0x6d,{MM_PACKED,1280,1024,8},0x00, + {0x6d,{MM_PACKED,1280,1024,8,8,16,SEG_GRAPH},0x00, cseq_1280x1024x8,cgraph_svgacolor,ccrtc_1280x1024x8}, - {0x69,{MM_DIRECT,1280,1024,15},0xf0, + {0x69,{MM_DIRECT,1280,1024,15,8,16,SEG_GRAPH},0xf0, cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16}, - {0x75,{MM_DIRECT,1280,1024,16},0xe1, + {0x75,{MM_DIRECT,1280,1024,16,8,16,SEG_GRAPH},0xe1, cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16},
- {0x7b,{MM_PACKED,1600,1200,8},0x00, + {0x7b,{MM_PACKED,1600,1200,8,8,16,SEG_GRAPH},0x00, cseq_1600x1200x8,cgraph_svgacolor,ccrtc_1600x1200x8}, };
diff --git a/vgasrc/vbe.c b/vgasrc/vbe.c index d7dd8b4..caf856d 100644 --- a/vgasrc/vbe.c +++ b/vgasrc/vbe.c @@ -100,7 +100,7 @@ vbe_104f01(struct bregs *regs) SET_FARVAR(seg, info->winB_attributes, 0); SET_FARVAR(seg, info->win_granularity, GET_GLOBAL(VBE_win_granularity)); SET_FARVAR(seg, info->win_size, 64); /* Bank size 64K */ - SET_FARVAR(seg, info->winA_seg, SEG_GRAPH); + SET_FARVAR(seg, info->winA_seg, GET_GLOBAL(vmode_g->sstart)); SET_FARVAR(seg, info->winB_seg, 0x0); SET_FARVAR(seg, info->win_func_ptr.segoff, 0x0); int width = GET_GLOBAL(vmode_g->width); @@ -109,8 +109,8 @@ vbe_104f01(struct bregs *regs) SET_FARVAR(seg, info->bytes_per_scanline, linesize); SET_FARVAR(seg, info->xres, width); SET_FARVAR(seg, info->yres, height); - SET_FARVAR(seg, info->xcharsize, 8); - SET_FARVAR(seg, info->ycharsize, 16); + SET_FARVAR(seg, info->xcharsize, GET_GLOBAL(vmode_g->cwidth)); + SET_FARVAR(seg, info->ycharsize, GET_GLOBAL(vmode_g->cheight)); if (depth == 4) SET_FARVAR(seg, info->planes, 4); else
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/vgabios.c | 13 ++++++++++++- vgasrc/vgabios.h | 1 + vgasrc/vgafb.c | 11 +++++------ 3 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c index 5ce7c0c..62b09b4 100644 --- a/vgasrc/vgabios.c +++ b/vgasrc/vgabios.c @@ -151,7 +151,7 @@ set_active_page(u8 page) return;
// Get the mode - struct vgamode_s *vmode_g = vgahw_find_mode(GET_BDA(video_mode)); + struct vgamode_s *vmode_g = get_current_mode(); if (!vmode_g) return;
@@ -336,6 +336,17 @@ restore_bda_state(u16 seg, struct saveBDAstate *info) SET_IVT(0x43, GET_FARVAR(seg, info->font1)); }
+ +/**************************************************************** + * Mode setting + ****************************************************************/ + +struct vgamode_s * +get_current_mode(void) +{ + return vgahw_find_mode(GET_BDA(video_mode)); +} + // Setup BDA after a mode switch. void modeswitch_set_bda(int mode, int flags, struct vgamode_s *vmode_g) diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h index 6895a39..6a3a379 100644 --- a/vgasrc/vgabios.h +++ b/vgasrc/vgabios.h @@ -82,6 +82,7 @@ struct cursorpos { u8 x, y, page; }; u16 calc_page_size(u8 memmodel, u16 width, u16 height); +struct vgamode_s *get_current_mode(void); void modeswitch_set_bda(int mode, int flags, struct vgamode_s *vmode_g);
// vgafb.c diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c index 71a5719..f0bd71e 100644 --- a/vgasrc/vgafb.c +++ b/vgasrc/vgafb.c @@ -7,7 +7,6 @@
#include "biosvar.h" // GET_BDA #include "util.h" // memset_far -#include "vgahw.h" // vgahw_find_mode #include "stdvga.h" // stdvga_planar4_plane
@@ -171,7 +170,7 @@ void vgafb_scroll(int nblines, int attr, struct cursorpos ul, struct cursorpos lr) { // Get the mode - struct vgamode_s *vmode_g = vgahw_find_mode(GET_BDA(video_mode)); + struct vgamode_s *vmode_g = get_current_mode(); if (!vmode_g) return;
@@ -339,7 +338,7 @@ void vgafb_write_char(struct cursorpos cp, struct carattr ca) { // Get the mode - struct vgamode_s *vmode_g = vgahw_find_mode(GET_BDA(video_mode)); + struct vgamode_s *vmode_g = get_current_mode(); if (!vmode_g) return;
@@ -365,7 +364,7 @@ struct carattr vgafb_read_char(struct cursorpos cp) { // Get the mode - struct vgamode_s *vmode_g = vgahw_find_mode(GET_BDA(video_mode)); + struct vgamode_s *vmode_g = get_current_mode(); if (!vmode_g) goto fail;
@@ -397,7 +396,7 @@ void vgafb_write_pixel(u8 color, u16 x, u16 y) { // Get the mode - struct vgamode_s *vmode_g = vgahw_find_mode(GET_BDA(video_mode)); + struct vgamode_s *vmode_g = get_current_mode(); if (!vmode_g) return;
@@ -453,7 +452,7 @@ u8 vgafb_read_pixel(u16 x, u16 y) { // Get the mode - struct vgamode_s *vmode_g = vgahw_find_mode(GET_BDA(video_mode)); + struct vgamode_s *vmode_g = get_current_mode(); if (!vmode_g) return 0;
Always setup the BDA on a mode switch. Call that BDA setup code unconditionally.
Also, always set vbe_mode and use that for finding the current mode and for reporting the mode to vbe callers.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/bochsvga.c | 30 +++++++++++++----------------- vgasrc/bochsvga.h | 2 +- vgasrc/clext.c | 37 ++++++++++++++++++++----------------- vgasrc/clext.h | 2 +- vgasrc/stdvga.c | 15 +++++---------- vgasrc/stdvga.h | 3 ++- vgasrc/stdvgamodes.c | 7 +++++++ vgasrc/vbe.c | 12 ++++-------- vgasrc/vgabios.c | 26 +++++++++++++++++++++----- vgasrc/vgabios.h | 3 ++- vgasrc/vgahw.h | 8 ++++---- 11 files changed, 80 insertions(+), 65 deletions(-)
diff --git a/vgasrc/bochsvga.c b/vgasrc/bochsvga.c index 213dbcd..6cbbf9c 100644 --- a/vgasrc/bochsvga.c +++ b/vgasrc/bochsvga.c @@ -1,9 +1,9 @@ #include "vgabios.h" // struct vbe_modeinfo -#include "vbe.h" // VBE_MODE_VESA_DEFINED +#include "vbe.h" // VBE_CAPABILITY_8BIT_DAC #include "bochsvga.h" // bochsvga_set_mode #include "util.h" // dprintf #include "config.h" // CONFIG_* -#include "biosvar.h" // SET_BDA +#include "biosvar.h" // GET_GLOBAL #include "stdvga.h" // VGAREG_SEQU_ADDRESS #include "pci.h" // pci_config_readl #include "pci_regs.h" // PCI_BASE_ADDRESS_0 @@ -78,6 +78,12 @@ static struct bochsvga_mode { 0x18c, { MM_DIRECT, 2560, 1600, 32, 8, 16, SEG_GRAPH } }, };
+static int is_bochsvga_mode(struct vgamode_s *vmode_g) +{ + return (vmode_g >= &bochsvga_modes[0].info + && vmode_g <= &bochsvga_modes[ARRAY_SIZE(bochsvga_modes)-1].info); +} + static u16 dispi_get_max_xres(void) { u16 en; @@ -203,26 +209,18 @@ bochsvga_clear_scr(void) }
int -bochsvga_set_mode(int mode, int flags) +bochsvga_set_mode(struct vgamode_s *vmode_g, int flags) { - if (!(mode & VBE_MODE_VESA_DEFINED)) { - dprintf(1, "set VGA mode %x\n", mode); - - SET_BDA(vbe_mode, 0); + if (! is_bochsvga_mode(vmode_g)) { bochsvga_hires_enable(0); - return stdvga_set_mode(mode, flags); + return stdvga_set_mode(vmode_g, flags); }
- struct vgamode_s *vmode_g = bochsvga_find_mode(mode); - if (!vmode_g) { - dprintf(1, "VBE mode %x not found\n", mode); - return VBE_RETURN_STATUS_FAILED; - } bochsvga_hires_enable(1);
u8 depth = GET_GLOBAL(vmode_g->depth); if (depth == 4) - stdvga_set_mode(0x6a, 0); + stdvga_set_mode(stdvga_find_mode(0x6a), 0); if (depth == 8) // XXX load_dac_palette(3); ; @@ -260,13 +258,11 @@ bochsvga_set_mode(int mode, int flags) stdvga_grdc_mask(0x05, 0x20, 0x40); }
- SET_BDA(vbe_mode, mode | flags); - if (flags & MF_LINEARFB) { /* Linear frame buffer */ /* XXX: ??? */ } - if (!(mode & MF_NOCLEARMEM)) { + if (!(flags & MF_NOCLEARMEM)) { bochsvga_clear_scr(); }
diff --git a/vgasrc/bochsvga.h b/vgasrc/bochsvga.h index 81fb8f7..1eaa91a 100644 --- a/vgasrc/bochsvga.h +++ b/vgasrc/bochsvga.h @@ -55,6 +55,6 @@ static inline void dispi_write(u16 reg, u16 val) int bochsvga_init(void); void bochsvga_list_modes(u16 seg, u16 *dest, u16 *last); struct vgamode_s *bochsvga_find_mode(int mode); -int bochsvga_set_mode(int mode, int flags); +int bochsvga_set_mode(struct vgamode_s *vmode_g, int flags);
#endif // bochsvga.h diff --git a/vgasrc/clext.c b/vgasrc/clext.c index ea2b428..363ef5d 100644 --- a/vgasrc/clext.c +++ b/vgasrc/clext.c @@ -10,7 +10,6 @@ #include "biosvar.h" // GET_GLOBAL #include "util.h" // dprintf #include "bregs.h" // struct bregs -#include "vbe.h" // struct vbe_info #include "stdvga.h" // VGAREG_SEQU_ADDRESS #include "pci.h" // pci_config_readl #include "pci_regs.h" // PCI_BASE_ADDRESS_0 @@ -309,6 +308,13 @@ static struct { * helper functions ****************************************************************/
+int +is_cirrus_mode(struct vgamode_s *vmode_g) +{ + return (vmode_g >= &cirrus_modes[0].info + && vmode_g <= &cirrus_modes[ARRAY_SIZE(cirrus_modes)-1].info); +} + static u16 cirrus_vesamode_to_mode(u16 vesamode) { @@ -414,24 +420,21 @@ cirrus_clear_vram(u16 param) }
int -clext_set_mode(int mode, int flags) +clext_set_mode(struct vgamode_s *vmode_g, int flags) { - dprintf(1, "cirrus mode %x\n", mode); - SET_BDA(vbe_mode, 0); - struct cirrus_mode_s *table_g = cirrus_get_modeentry(mode); - if (table_g) { - cirrus_switch_mode(table_g); - if (!(flags & MF_LINEARFB)) - cirrus_enable_16k_granularity(); - if (!(flags & MF_NOCLEARMEM)) - cirrus_clear_vram(0); - SET_BDA(video_mode, mode); - SET_BDA(vbe_mode, mode | flags); - return 0; + if (!is_cirrus_mode(vmode_g)) { + cirrus_switch_mode(&mode_switchback); + dprintf(1, "cirrus mode switch regular\n"); + return stdvga_set_mode(vmode_g, flags); } - cirrus_switch_mode(&mode_switchback); - dprintf(1, "cirrus mode switch regular\n"); - return stdvga_set_mode(mode, flags); + struct cirrus_mode_s *table_g = container_of( + vmode_g, struct cirrus_mode_s, info); + cirrus_switch_mode(table_g); + if (!(flags & MF_LINEARFB)) + cirrus_enable_16k_granularity(); + if (!(flags & MF_NOCLEARMEM)) + cirrus_clear_vram(0); + return 0; }
static int diff --git a/vgasrc/clext.h b/vgasrc/clext.h index a14cf13..718b756 100644 --- a/vgasrc/clext.h +++ b/vgasrc/clext.h @@ -4,7 +4,7 @@ #include "types.h" // u16
struct vgamode_s *clext_find_mode(int mode); -int clext_set_mode(int mode, int flags); +int clext_set_mode(struct vgamode_s *vmode_g, int flags); void clext_list_modes(u16 seg, u16 *dest, u16 *last); int clext_init(void); struct bregs; diff --git a/vgasrc/stdvga.c b/vgasrc/stdvga.c index 0fab905..b7def32 100644 --- a/vgasrc/stdvga.c +++ b/vgasrc/stdvga.c @@ -10,7 +10,6 @@ #include "farptr.h" // SET_FARVAR #include "biosvar.h" // GET_GLOBAL #include "util.h" // memcpy_far -#include "vbe.h" // VBE_RETURN_STATUS_FAILED
/**************************************************************** @@ -360,13 +359,12 @@ clear_screen(struct vgamode_s *vmode_g) }
int -stdvga_set_mode(int mode, int flags) +stdvga_set_mode(struct vgamode_s *vmode_g, int flags) { - // find the entry in the video modes - struct vgamode_s *vmode_g = stdvga_find_mode(mode); - dprintf(1, "mode search %02x found %p\n", mode, vmode_g); - if (!vmode_g) - return VBE_RETURN_STATUS_FAILED; + if (! stdvga_is_mode(vmode_g)) { + warn_internalerror(); + return -1; + } struct stdvga_mode_s *stdmode_g = container_of( vmode_g, struct stdvga_mode_s, info);
@@ -436,9 +434,6 @@ stdvga_set_mode(int mode, int flags) if (memmodel == MM_TEXT) stdvga_load_font(get_global_seg(), vgafont16, 0x100, 0, 0, 16);
- // Setup BDA variables - modeswitch_set_bda(mode, flags, vmode_g); - return 0; }
diff --git a/vgasrc/stdvga.h b/vgasrc/stdvga.h index ee14358..cc93f0d 100644 --- a/vgasrc/stdvga.h +++ b/vgasrc/stdvga.h @@ -84,6 +84,7 @@ struct saveDACcolors {
// stdvgamodes.c struct vgamode_s *stdvga_find_mode(int mode); +int stdvga_is_mode(struct vgamode_s *vmode_g); void stdvga_build_video_param(void); void stdvga_override_crtc(int mode, u8 *crtc);
@@ -135,7 +136,7 @@ void stdvga_set_scan_lines(u8 lines); u16 stdvga_get_vde(void); void stdvga_save_state(u16 seg, struct saveVideoHardware *info); void stdvga_restore_state(u16 seg, struct saveVideoHardware *info); -int stdvga_set_mode(int mode, int flags); +int stdvga_set_mode(struct vgamode_s *vmode_g, int flags); void stdvga_enable_video_addressing(u8 disable); void stdvga_list_modes(u16 seg, u16 *dest, u16 *last); int stdvga_init(void); diff --git a/vgasrc/stdvgamodes.c b/vgasrc/stdvgamodes.c index 08c3a58..1b47e98 100644 --- a/vgasrc/stdvgamodes.c +++ b/vgasrc/stdvgamodes.c @@ -298,6 +298,13 @@ static struct stdvga_mode_s vga_modes[] VAR16 = { * Mode functions ****************************************************************/
+int +stdvga_is_mode(struct vgamode_s *vmode_g) +{ + return (vmode_g >= &vga_modes[0].info + && vmode_g <= &vga_modes[ARRAY_SIZE(vga_modes)-1].info); +} + struct vgamode_s * stdvga_find_mode(int mode) { diff --git a/vgasrc/vbe.c b/vgasrc/vbe.c index caf856d..b6ffb97 100644 --- a/vgasrc/vbe.c +++ b/vgasrc/vbe.c @@ -184,9 +184,9 @@ vbe_104f02(struct bregs *regs) { dprintf(1, "VBE mode set: %x\n", regs->bx);
- int mode = regs->bx & 0x1ff; - int flags = regs->bx & (MF_CUSTOMCRTC|MF_LINEARFB|MF_NOCLEARMEM); - int ret = vgahw_set_mode(mode, flags); + int mode = regs->bx & ~MF_VBEFLAGS; + int flags = regs->bx & MF_VBEFLAGS; + int ret = vga_set_mode(mode, flags);
regs->ah = ret; regs->al = 0x4f; @@ -195,12 +195,8 @@ vbe_104f02(struct bregs *regs) static void vbe_104f03(struct bregs *regs) { - u16 mode = GET_BDA(vbe_mode); - if (!mode) - regs->bx = GET_BDA(video_mode); - + regs->bx = GET_BDA(vbe_mode); dprintf(1, "VBE current mode=%x\n", regs->bx); - regs->ax = 0x004f; }
diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c index 62b09b4..efc4a39 100644 --- a/vgasrc/vgabios.c +++ b/vgasrc/vgabios.c @@ -20,6 +20,7 @@ #include "stdvga.h" // stdvga_set_cursor_shape #include "clext.h" // clext_1012 #include "vgahw.h" // vgahw_set_mode +#include "vbe.h" // VBE_RETURN_STATUS_FAILED #include "pci.h" // pci_config_readw #include "pci_regs.h" // PCI_VENDOR_ID
@@ -344,19 +345,32 @@ restore_bda_state(u16 seg, struct saveBDAstate *info) struct vgamode_s * get_current_mode(void) { - return vgahw_find_mode(GET_BDA(video_mode)); + return vgahw_find_mode(GET_BDA(vbe_mode) & ~MF_VBEFLAGS); }
// Setup BDA after a mode switch. -void -modeswitch_set_bda(int mode, int flags, struct vgamode_s *vmode_g) +int +vga_set_mode(int mode, int flags) { + dprintf(1, "set VGA mode %x\n", mode); + struct vgamode_s *vmode_g = vgahw_find_mode(mode); + if (!vmode_g) + return VBE_RETURN_STATUS_FAILED; + + int ret = vgahw_set_mode(vmode_g, flags); + if (ret) + return ret; + // Set the BIOS mem int width = GET_GLOBAL(vmode_g->width); int height = GET_GLOBAL(vmode_g->height); u8 memmodel = GET_GLOBAL(vmode_g->memmodel); int cheight = GET_GLOBAL(vmode_g->cheight); - SET_BDA(video_mode, mode); + if (mode < 0x100) + SET_BDA(video_mode, mode); + else + SET_BDA(video_mode, 0xff); + SET_BDA(vbe_mode, mode | (flags & MF_VBEFLAGS)); if (memmodel == MM_TEXT) { SET_BDA(video_cols, width); SET_BDA(video_rows, height-1); @@ -402,6 +416,8 @@ modeswitch_set_bda(int mode, int flags, struct vgamode_s *vmode_g) SET_IVT(0x43, SEGOFF(get_global_seg(), (u32)vgafont16)); break; } + + return 0; }
@@ -426,7 +442,7 @@ handle_1000(struct bregs *regs) if (regs->al & 0x80) flags |= MF_NOCLEARMEM;
- vgahw_set_mode(mode, flags); + vga_set_mode(mode, flags); }
static void diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h index 6a3a379..23d234a 100644 --- a/vgasrc/vgabios.h +++ b/vgasrc/vgabios.h @@ -44,6 +44,7 @@ struct saveBDAstate { #define MF_CUSTOMCRTC 0x0800 #define MF_LINEARFB 0x4000 #define MF_NOCLEARMEM 0x8000 +#define MF_VBEFLAGS 0xfe00
// Memory model types #define MM_TEXT 0x00 @@ -83,7 +84,7 @@ struct cursorpos { }; u16 calc_page_size(u8 memmodel, u16 width, u16 height); struct vgamode_s *get_current_mode(void); -void modeswitch_set_bda(int mode, int flags, struct vgamode_s *vmode_g); +int vga_set_mode(int mode, int flags);
// vgafb.c void vgafb_scroll(int nblines, int attr diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h index 1101e51..bb5112a 100644 --- a/vgasrc/vgahw.h +++ b/vgasrc/vgahw.h @@ -17,12 +17,12 @@ static inline struct vgamode_s *vgahw_find_mode(int mode) { return stdvga_find_mode(mode); }
-static inline int vgahw_set_mode(int mode, int flags) { +static inline int vgahw_set_mode(struct vgamode_s *vmode_g, int flags) { if (CONFIG_VGA_CIRRUS) - return clext_set_mode(mode, flags); + return clext_set_mode(vmode_g, flags); if (CONFIG_VGA_BOCHS) - return bochsvga_set_mode(mode, flags); - return stdvga_set_mode(mode, flags); + return bochsvga_set_mode(vmode_g, flags); + return stdvga_set_mode(vmode_g, flags); }
static inline void vgahw_list_modes(u16 seg, u16 *dest, u16 *last) {
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/bochsvga.c | 19 +++++++++++++++++++ vgasrc/bochsvga.h | 2 ++ vgasrc/clext.c | 38 +++++++++++++++----------------------- vgasrc/clext.h | 2 ++ vgasrc/stdvga.c | 12 ++++++++++++ vgasrc/stdvga.h | 2 ++ vgasrc/vbe.c | 30 +++++++++++++++++++++++++++--- vgasrc/vgaentry.S | 5 +++++ vgasrc/vgahw.h | 17 +++++++++++++++++ 9 files changed, 101 insertions(+), 26 deletions(-)
diff --git a/vgasrc/bochsvga.c b/vgasrc/bochsvga.c index 6cbbf9c..74da887 100644 --- a/vgasrc/bochsvga.c +++ b/vgasrc/bochsvga.c @@ -198,6 +198,25 @@ bochsvga_hires_enable(int enable) dispi_write(VBE_DISPI_INDEX_ENABLE, flags); }
+int +bochsvga_get_window(struct vgamode_s *vmode_g, int window) +{ + if (window != 0) + return -1; + return dispi_read(VBE_DISPI_INDEX_BANK); +} + +int +bochsvga_set_window(struct vgamode_s *vmode_g, int window, int val) +{ + if (window != 0) + return -1; + dispi_write(VBE_DISPI_INDEX_BANK, val); + if (dispi_read(VBE_DISPI_INDEX_BANK) != val) + return -1; + return 0; +} + static void bochsvga_clear_scr(void) { diff --git a/vgasrc/bochsvga.h b/vgasrc/bochsvga.h index 1eaa91a..26a82e0 100644 --- a/vgasrc/bochsvga.h +++ b/vgasrc/bochsvga.h @@ -55,6 +55,8 @@ static inline void dispi_write(u16 reg, u16 val) int bochsvga_init(void); void bochsvga_list_modes(u16 seg, u16 *dest, u16 *last); struct vgamode_s *bochsvga_find_mode(int mode); +int bochsvga_get_window(struct vgamode_s *vmode_g, int window); +int bochsvga_set_window(struct vgamode_s *vmode_g, int window, int val); int bochsvga_set_mode(struct vgamode_s *vmode_g, int flags);
#endif // bochsvga.h diff --git a/vgasrc/clext.c b/vgasrc/clext.c index 363ef5d..ee39c5e 100644 --- a/vgasrc/clext.c +++ b/vgasrc/clext.c @@ -400,6 +400,21 @@ cirrus_get_memsize(void) return 0x04 << x; }
+int +clext_get_window(struct vgamode_s *vmode_g, int window) +{ + return stdvga_grdc_read(window + 9); +} + +int +clext_set_window(struct vgamode_s *vmode_g, int window, int val) +{ + if (val >= 0x100) + return -1; + stdvga_grdc_write(window + 9, val); + return 0; +} + static void cirrus_enable_16k_granularity(void) { @@ -620,28 +635,6 @@ cirrus_get_start_addr(void) }
static void -cirrus_vesa_05h(struct bregs *regs) -{ - if (regs->bl > 1) - goto fail; - if (regs->bh == 0) { - // set mempage - if (regs->dx >= 0x100) - goto fail; - stdvga_grdc_write(regs->bl + 9, regs->dx); - } else if (regs->bh == 1) { - // get mempage - regs->dx = stdvga_grdc_read(regs->bl + 9); - } else - goto fail; - - regs->ax = 0x004f; - return; -fail: - regs->ax = 0x014f; -} - -static void cirrus_vesa_06h(struct bregs *regs) { if (regs->bl > 2) { @@ -714,7 +707,6 @@ void cirrus_vesa(struct bregs *regs) { switch (regs->al) { - case 0x05: cirrus_vesa_05h(regs); break; case 0x06: cirrus_vesa_06h(regs); break; case 0x07: cirrus_vesa_07h(regs); break; case 0x10: cirrus_vesa_10h(regs); break; diff --git a/vgasrc/clext.h b/vgasrc/clext.h index 718b756..b300cf4 100644 --- a/vgasrc/clext.h +++ b/vgasrc/clext.h @@ -4,6 +4,8 @@ #include "types.h" // u16
struct vgamode_s *clext_find_mode(int mode); +int clext_get_window(struct vgamode_s *vmode_g, int window); +int clext_set_window(struct vgamode_s *vmode_g, int window, int val); int clext_set_mode(struct vgamode_s *vmode_g, int flags); void clext_list_modes(u16 seg, u16 *dest, u16 *last); int clext_init(void); diff --git a/vgasrc/stdvga.c b/vgasrc/stdvga.c index b7def32..9c0cba9 100644 --- a/vgasrc/stdvga.c +++ b/vgasrc/stdvga.c @@ -270,6 +270,18 @@ stdvga_get_vde(void) return vde; }
+int +stdvga_get_window(struct vgamode_s *vmode_g, int window) +{ + return -1; +} + +int +stdvga_set_window(struct vgamode_s *vmode_g, int window, int val) +{ + return -1; +} +
/**************************************************************** * Save/Restore/Set state diff --git a/vgasrc/stdvga.h b/vgasrc/stdvga.h index cc93f0d..05f2bf5 100644 --- a/vgasrc/stdvga.h +++ b/vgasrc/stdvga.h @@ -134,6 +134,8 @@ void stdvga_set_active_page(u16 address); void stdvga_set_cursor_pos(u16 address); void stdvga_set_scan_lines(u8 lines); u16 stdvga_get_vde(void); +int stdvga_get_window(struct vgamode_s *vmode_g, int window); +int stdvga_set_window(struct vgamode_s *vmode_g, int window, int val); void stdvga_save_state(u16 seg, struct saveVideoHardware *info); void stdvga_restore_state(u16 seg, struct saveVideoHardware *info); int stdvga_set_mode(struct vgamode_s *vmode_g, int flags); diff --git a/vgasrc/vbe.c b/vgasrc/vbe.c index b6ffb97..7e84794 100644 --- a/vgasrc/vbe.c +++ b/vgasrc/vbe.c @@ -102,7 +102,9 @@ vbe_104f01(struct bregs *regs) SET_FARVAR(seg, info->win_size, 64); /* Bank size 64K */ SET_FARVAR(seg, info->winA_seg, GET_GLOBAL(vmode_g->sstart)); SET_FARVAR(seg, info->winB_seg, 0x0); - SET_FARVAR(seg, info->win_func_ptr.segoff, 0x0); + extern void entry_104f05(void); + SET_FARVAR(seg, info->win_func_ptr + , SEGOFF(get_global_seg(), (u32)entry_104f05)); int width = GET_GLOBAL(vmode_g->width); int height = GET_GLOBAL(vmode_g->height); int linesize = width * DIV_ROUND_UP(depth, 8); @@ -207,10 +209,32 @@ vbe_104f04(struct bregs *regs) regs->ax = 0x0100; }
-static void +void VISIBLE16 vbe_104f05(struct bregs *regs) { - debug_stub(regs); + if (regs->bh > 1 || regs->bl > 1) + goto fail; + if (GET_BDA(vbe_mode) & MF_LINEARFB) { + regs->ah = VBE_RETURN_STATUS_INVALID; + return; + } + struct vgamode_s *vmode_g = get_current_mode(); + if (! vmode_g) + goto fail; + if (regs->bh) { + int ret = vgahw_get_window(vmode_g, regs->bl); + if (ret < 0) + goto fail; + regs->dx = ret; + regs->ax = 0x004f; + return; + } + int ret = vgahw_set_window(vmode_g, regs->bl, regs->dx); + if (ret) + goto fail; + regs->ax = 0x004f; + return; +fail: regs->ax = 0x0100; }
diff --git a/vgasrc/vgaentry.S b/vgasrc/vgaentry.S index 112857b..785d91f 100644 --- a/vgasrc/vgaentry.S +++ b/vgasrc/vgaentry.S @@ -50,6 +50,11 @@ _rom_header_signature: * Entry points ****************************************************************/
+ DECLFUNC entry_104f05 +entry_104f05: + ENTRY_ARG vbe_104f05 + lretw + DECLFUNC _optionrom_entry _optionrom_entry: ENTRY_ARG vga_post diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h index bb5112a..ca8798c 100644 --- a/vgasrc/vgahw.h +++ b/vgasrc/vgahw.h @@ -44,4 +44,21 @@ static inline int vgahw_init(void) { return stdvga_init(); }
+static inline int vgahw_get_window(struct vgamode_s *vmode_g, int window) { + if (CONFIG_VGA_CIRRUS) + return clext_get_window(vmode_g, window); + if (CONFIG_VGA_BOCHS) + return bochsvga_get_window(vmode_g, window); + return stdvga_get_window(vmode_g, window); +} + +static inline int vgahw_set_window(struct vgamode_s *vmode_g, int window + , int val) { + if (CONFIG_VGA_CIRRUS) + return clext_set_window(vmode_g, window, val); + if (CONFIG_VGA_BOCHS) + return bochsvga_set_window(vmode_g, window, val); + return stdvga_set_window(vmode_g, window, val); +} + #endif // vgahw.h
Also, this changes the bochsvga mode set to call stdvga_set_linelength instead of setting the dispi virtual line length as it appears that is what the original vgabios code did.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/bochsvga.c | 17 ++++++++++++++++- vgasrc/bochsvga.h | 2 ++ vgasrc/clext.c | 51 ++++++++++++++++++++------------------------------- vgasrc/clext.h | 2 ++ vgasrc/stdvga.c | 31 +++++++++++++++++++++++++++++++ vgasrc/stdvga.h | 3 +++ vgasrc/vbe.c | 29 +++++++++++++++++++++++++++-- vgasrc/vgabios.c | 16 ++++++++++++++++ vgasrc/vgabios.h | 1 + vgasrc/vgahw.h | 16 ++++++++++++++++ 10 files changed, 134 insertions(+), 34 deletions(-)
diff --git a/vgasrc/bochsvga.c b/vgasrc/bochsvga.c index 74da887..3e5e907 100644 --- a/vgasrc/bochsvga.c +++ b/vgasrc/bochsvga.c @@ -217,6 +217,21 @@ bochsvga_set_window(struct vgamode_s *vmode_g, int window, int val) return 0; }
+int +bochsvga_get_linelength(struct vgamode_s *vmode_g) +{ + return dispi_read(VBE_DISPI_INDEX_VIRT_WIDTH) * vga_bpp(vmode_g) / 8; +} + +int +bochsvga_set_linelength(struct vgamode_s *vmode_g, int val) +{ + stdvga_set_linelength(vmode_g, val); + int pixels = (val * 8) / vga_bpp(vmode_g); + dispi_write(VBE_DISPI_INDEX_VIRT_WIDTH, pixels); + return 0; +} + static void bochsvga_clear_scr(void) { @@ -256,7 +271,7 @@ bochsvga_set_mode(struct vgamode_s *vmode_g, int flags) u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS; stdvga_crtc_write(crtc_addr, 0x11, 0x00); stdvga_crtc_write(crtc_addr, 0x01, width / 8 - 1); - dispi_write(VBE_DISPI_INDEX_VIRT_WIDTH, width); + stdvga_set_linelength(vmode_g, width); stdvga_crtc_write(crtc_addr, 0x12, height - 1); u8 v = 0; if ((height - 1) & 0x0100) diff --git a/vgasrc/bochsvga.h b/vgasrc/bochsvga.h index 26a82e0..b6abf0a 100644 --- a/vgasrc/bochsvga.h +++ b/vgasrc/bochsvga.h @@ -57,6 +57,8 @@ void bochsvga_list_modes(u16 seg, u16 *dest, u16 *last); struct vgamode_s *bochsvga_find_mode(int mode); int bochsvga_get_window(struct vgamode_s *vmode_g, int window); int bochsvga_set_window(struct vgamode_s *vmode_g, int window, int val); +int bochsvga_get_linelength(struct vgamode_s *vmode_g); +int bochsvga_set_linelength(struct vgamode_s *vmode_g, int val); int bochsvga_set_mode(struct vgamode_s *vmode_g, int flags);
#endif // bochsvga.h diff --git a/vgasrc/clext.c b/vgasrc/clext.c index ee39c5e..27af810 100644 --- a/vgasrc/clext.c +++ b/vgasrc/clext.c @@ -415,6 +415,26 @@ clext_set_window(struct vgamode_s *vmode_g, int window, int val) return 0; }
+int +clext_get_linelength(struct vgamode_s *vmode_g) +{ + u16 crtc_addr = stdvga_get_crtc(); + u8 reg13 = stdvga_crtc_read(crtc_addr, 0x13); + u8 reg1b = stdvga_crtc_read(crtc_addr, 0x1b); + return (((reg1b & 0x10) << 4) + reg13) * stdvga_bpp_factor(vmode_g) * 2; +} + +int +clext_set_linelength(struct vgamode_s *vmode_g, int val) +{ + u16 crtc_addr = stdvga_get_crtc(); + int factor = stdvga_bpp_factor(vmode_g) * 2; + int new_line_offset = DIV_ROUND_UP(val, factor); + stdvga_crtc_write(crtc_addr, 0x13, new_line_offset); + stdvga_crtc_mask(crtc_addr, 0x1b, 0x10, (new_line_offset & 0x100) >> 4); + return 0; +} + static void cirrus_enable_16k_granularity(void) { @@ -593,15 +613,6 @@ cirrus_get_bpp_bytes(void) return v; }
-static void -cirrus_set_line_offset(u16 new_line_offset) -{ - new_line_offset /= 8; - u16 crtc_addr = stdvga_get_crtc(); - stdvga_crtc_write(crtc_addr, 0x13, new_line_offset); - stdvga_crtc_mask(crtc_addr, 0x1b, 0x10, (new_line_offset & 0x100) >> 4); -} - static u16 cirrus_get_line_offset(void) { @@ -635,27 +646,6 @@ cirrus_get_start_addr(void) }
static void -cirrus_vesa_06h(struct bregs *regs) -{ - if (regs->bl > 2) { - regs->ax = 0x0100; - return; - } - - if (regs->bl == 0x00) { - cirrus_set_line_offset(cirrus_get_bpp_bytes() * regs->cx); - } else if (regs->bl == 0x02) { - cirrus_set_line_offset(regs->cx); - } - - u32 v = cirrus_get_line_offset(); - regs->cx = v / cirrus_get_bpp_bytes(); - regs->bx = v; - regs->dx = GET_GLOBAL(VBE_total_memory) / v; - regs->ax = 0x004f; -} - -static void cirrus_vesa_07h(struct bregs *regs) { if (regs->bl == 0x80 || regs->bl == 0x00) { @@ -707,7 +697,6 @@ void cirrus_vesa(struct bregs *regs) { switch (regs->al) { - case 0x06: cirrus_vesa_06h(regs); break; case 0x07: cirrus_vesa_07h(regs); break; case 0x10: cirrus_vesa_10h(regs); break; default: cirrus_vesa_not_handled(regs); break; diff --git a/vgasrc/clext.h b/vgasrc/clext.h index b300cf4..55476a0 100644 --- a/vgasrc/clext.h +++ b/vgasrc/clext.h @@ -6,6 +6,8 @@ struct vgamode_s *clext_find_mode(int mode); int clext_get_window(struct vgamode_s *vmode_g, int window); int clext_set_window(struct vgamode_s *vmode_g, int window, int val); +int clext_get_linelength(struct vgamode_s *vmode_g); +int clext_set_linelength(struct vgamode_s *vmode_g, int val); int clext_set_mode(struct vgamode_s *vmode_g, int flags); void clext_list_modes(u16 seg, u16 *dest, u16 *last); int clext_init(void); diff --git a/vgasrc/stdvga.c b/vgasrc/stdvga.c index 9c0cba9..a310167 100644 --- a/vgasrc/stdvga.c +++ b/vgasrc/stdvga.c @@ -229,6 +229,22 @@ stdvga_get_crtc(void) return VGAREG_MDA_CRTC_ADDRESS; }
+// Return the multiplication factor needed for the vga offset register. +int +stdvga_bpp_factor(struct vgamode_s *vmode_g) +{ + switch (GET_GLOBAL(vmode_g->memmodel)) { + case MM_TEXT: + return 2; + case MM_CGA: + return GET_GLOBAL(vmode_g->depth); + case MM_PLANAR: + return 1; + default: + return 4; + } +} + void stdvga_set_cursor_shape(u8 start, u8 end) { @@ -282,6 +298,21 @@ stdvga_set_window(struct vgamode_s *vmode_g, int window, int val) return -1; }
+int +stdvga_get_linelength(struct vgamode_s *vmode_g) +{ + u8 val = stdvga_crtc_read(stdvga_get_crtc(), 0x13); + return val * stdvga_bpp_factor(vmode_g) * 2; +} + +int +stdvga_set_linelength(struct vgamode_s *vmode_g, int val) +{ + int factor = stdvga_bpp_factor(vmode_g) * 2; + stdvga_crtc_write(stdvga_get_crtc(), 0x13, DIV_ROUND_UP(val, factor)); + return 0; +} +
/**************************************************************** * Save/Restore/Set state diff --git a/vgasrc/stdvga.h b/vgasrc/stdvga.h index 05f2bf5..ad496b5 100644 --- a/vgasrc/stdvga.h +++ b/vgasrc/stdvga.h @@ -129,6 +129,7 @@ void stdvga_planar4_plane(int plane); void stdvga_load_font(u16 seg, void *src_far, u16 count , u16 start, u8 destflags, u8 fontsize); u16 stdvga_get_crtc(void); +int stdvga_bpp_factor(struct vgamode_s *vmode_g); void stdvga_set_cursor_shape(u8 start, u8 end); void stdvga_set_active_page(u16 address); void stdvga_set_cursor_pos(u16 address); @@ -136,6 +137,8 @@ void stdvga_set_scan_lines(u8 lines); u16 stdvga_get_vde(void); int stdvga_get_window(struct vgamode_s *vmode_g, int window); int stdvga_set_window(struct vgamode_s *vmode_g, int window, int val); +int stdvga_get_linelength(struct vgamode_s *vmode_g); +int stdvga_set_linelength(struct vgamode_s *vmode_g, int val); void stdvga_save_state(u16 seg, struct saveVideoHardware *info); void stdvga_restore_state(u16 seg, struct saveVideoHardware *info); int stdvga_set_mode(struct vgamode_s *vmode_g, int flags); diff --git a/vgasrc/vbe.c b/vgasrc/vbe.c index 7e84794..68d2025 100644 --- a/vgasrc/vbe.c +++ b/vgasrc/vbe.c @@ -241,8 +241,33 @@ fail: static void vbe_104f06(struct bregs *regs) { - debug_stub(regs); - regs->ax = 0x0100; + if (regs->bl > 0x02) + goto fail; + struct vgamode_s *vmode_g = get_current_mode(); + if (! vmode_g) + goto fail; + int bpp = vga_bpp(vmode_g); + + if (regs->bl == 0x00) { + int ret = vgahw_set_linelength(vmode_g, DIV_ROUND_UP(regs->cx * bpp, 8)); + if (ret) + goto fail; + } else if (regs->bl == 0x02) { + int ret = vgahw_set_linelength(vmode_g, regs->cx); + if (ret) + goto fail; + } + int linelength = vgahw_get_linelength(vmode_g); + if (linelength < 0) + goto fail; + + regs->bx = linelength; + regs->cx = (linelength * 8) / bpp; + regs->dx = GET_GLOBAL(VBE_total_memory) / linelength; + regs->ax = 0x004f; + return; +fail: + regs->ax = 0x014f; }
static void diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c index efc4a39..6b01b73 100644 --- a/vgasrc/vgabios.c +++ b/vgasrc/vgabios.c @@ -63,6 +63,22 @@ struct pci_data rom_pci_data VAR16VISIBLE = { * Helper functions ****************************************************************/
+// Return the bits per pixel in system memory for a given mode. +int +vga_bpp(struct vgamode_s *vmode_g) +{ + switch (GET_GLOBAL(vmode_g->memmodel)) { + case MM_TEXT: + return 16; + case MM_PLANAR: + return 1; + } + u8 depth = GET_GLOBAL(vmode_g->depth); + if (depth > 8) + return ALIGN(depth, 8); + return depth; +} + u16 calc_page_size(u8 memmodel, u16 width, u16 height) { diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h index 23d234a..aca95be 100644 --- a/vgasrc/vgabios.h +++ b/vgasrc/vgabios.h @@ -82,6 +82,7 @@ struct carattr { struct cursorpos { u8 x, y, page; }; +int vga_bpp(struct vgamode_s *vmode_g); u16 calc_page_size(u8 memmodel, u16 width, u16 height); struct vgamode_s *get_current_mode(void); int vga_set_mode(int mode, int flags); diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h index ca8798c..494309b 100644 --- a/vgasrc/vgahw.h +++ b/vgasrc/vgahw.h @@ -61,4 +61,20 @@ static inline int vgahw_set_window(struct vgamode_s *vmode_g, int window return stdvga_set_window(vmode_g, window, val); }
+static inline int vgahw_get_linelength(struct vgamode_s *vmode_g) { + if (CONFIG_VGA_CIRRUS) + return clext_get_linelength(vmode_g); + if (CONFIG_VGA_BOCHS) + return bochsvga_get_linelength(vmode_g); + return stdvga_get_linelength(vmode_g); +} + +static inline int vgahw_set_linelength(struct vgamode_s *vmode_g, int val) { + if (CONFIG_VGA_CIRRUS) + return clext_set_linelength(vmode_g, val); + if (CONFIG_VGA_BOCHS) + return bochsvga_set_linelength(vmode_g, val); + return stdvga_set_linelength(vmode_g, val); +} + #endif // vgahw.h
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/bochsvga.c | 21 ++++++++++++ vgasrc/bochsvga.h | 2 + vgasrc/clext.c | 91 +++++++++++++++------------------------------------- vgasrc/clext.h | 2 + vgasrc/stdvga.c | 27 +++++++++++----- vgasrc/stdvga.h | 3 +- vgasrc/vbe.c | 33 ++++++++++++++++++- vgasrc/vgabios.c | 5 +-- vgasrc/vgahw.h | 16 +++++++++ 9 files changed, 121 insertions(+), 79 deletions(-)
diff --git a/vgasrc/bochsvga.c b/vgasrc/bochsvga.c index 3e5e907..0ab2b32 100644 --- a/vgasrc/bochsvga.c +++ b/vgasrc/bochsvga.c @@ -232,6 +232,27 @@ bochsvga_set_linelength(struct vgamode_s *vmode_g, int val) return 0; }
+int +bochsvga_get_displaystart(struct vgamode_s *vmode_g) +{ + int bpp = vga_bpp(vmode_g); + int linelength = dispi_read(VBE_DISPI_INDEX_VIRT_WIDTH) * bpp / 8; + int x = dispi_read(VBE_DISPI_INDEX_X_OFFSET); + int y = dispi_read(VBE_DISPI_INDEX_Y_OFFSET); + return x * bpp / 8 + linelength * y; +} + +int +bochsvga_set_displaystart(struct vgamode_s *vmode_g, int val) +{ + stdvga_set_displaystart(vmode_g, val); + int bpp = vga_bpp(vmode_g); + int linelength = dispi_read(VBE_DISPI_INDEX_VIRT_WIDTH) * bpp / 8; + dispi_write(VBE_DISPI_INDEX_X_OFFSET, (val % linelength) * 8 / bpp); + dispi_write(VBE_DISPI_INDEX_Y_OFFSET, val / linelength); + return 0; +} + static void bochsvga_clear_scr(void) { diff --git a/vgasrc/bochsvga.h b/vgasrc/bochsvga.h index b6abf0a..d36c92a 100644 --- a/vgasrc/bochsvga.h +++ b/vgasrc/bochsvga.h @@ -59,6 +59,8 @@ int bochsvga_get_window(struct vgamode_s *vmode_g, int window); int bochsvga_set_window(struct vgamode_s *vmode_g, int window, int val); int bochsvga_get_linelength(struct vgamode_s *vmode_g); int bochsvga_set_linelength(struct vgamode_s *vmode_g, int val); +int bochsvga_get_displaystart(struct vgamode_s *vmode_g); +int bochsvga_set_displaystart(struct vgamode_s *vmode_g, int val); int bochsvga_set_mode(struct vgamode_s *vmode_g, int flags);
#endif // bochsvga.h diff --git a/vgasrc/clext.c b/vgasrc/clext.c index 27af810..0640752 100644 --- a/vgasrc/clext.c +++ b/vgasrc/clext.c @@ -435,6 +435,32 @@ clext_set_linelength(struct vgamode_s *vmode_g, int val) return 0; }
+int +clext_get_displaystart(struct vgamode_s *vmode_g) +{ + u16 crtc_addr = stdvga_get_crtc(); + u8 b2 = stdvga_crtc_read(crtc_addr, 0x0c); + u8 b1 = stdvga_crtc_read(crtc_addr, 0x0d); + u8 b3 = stdvga_crtc_read(crtc_addr, 0x1b); + u8 b4 = stdvga_crtc_read(crtc_addr, 0x1d); + int val = (b1 | (b2<<8) | ((b3 & 0x01) << 16) | ((b3 & 0x0c) << 15) + | ((b4 & 0x80) << 12)); + return val * stdvga_bpp_factor(vmode_g); +} + +int +clext_set_displaystart(struct vgamode_s *vmode_g, int val) +{ + u16 crtc_addr = stdvga_get_crtc(); + val /= stdvga_bpp_factor(vmode_g); + stdvga_crtc_write(crtc_addr, 0x0d, val); + stdvga_crtc_write(crtc_addr, 0x0c, val >> 8); + stdvga_crtc_mask(crtc_addr, 0x1d, 0x80, (val & 0x0800) >> 4); + stdvga_crtc_mask(crtc_addr, 0x1b, 0x0d + , ((val & 0x0100) >> 8) | ((val & 0x0600) >> 7)); + return 0; +} + static void cirrus_enable_16k_granularity(void) { @@ -601,70 +627,6 @@ clext_list_modes(u16 seg, u16 *dest, u16 *last) stdvga_list_modes(seg, dest, last); }
-static u8 -cirrus_get_bpp_bytes(void) -{ - u8 v = stdvga_sequ_read(0x07) & 0x0e; - if (v == 0x06) - v &= 0x02; - v >>= 1; - if (v != 0x04) - v++; - return v; -} - -static u16 -cirrus_get_line_offset(void) -{ - u16 crtc_addr = stdvga_get_crtc(); - u8 reg13 = stdvga_crtc_read(crtc_addr, 0x13); - u8 reg1b = stdvga_crtc_read(crtc_addr, 0x1b); - return (((reg1b & 0x10) << 4) + reg13) * 8; -} - -static void -cirrus_set_start_addr(u32 addr) -{ - u16 crtc_addr = stdvga_get_crtc(); - stdvga_crtc_write(crtc_addr, 0x0d, addr); - stdvga_crtc_write(crtc_addr, 0x0c, addr >> 8); - stdvga_crtc_mask(crtc_addr, 0x1d, 0x80, (addr & 0x0800) >> 4); - stdvga_crtc_mask(crtc_addr, 0x1b, 0x0d - , ((addr & 0x0100) >> 8) | ((addr & 0x0600) >> 7)); -} - -static u32 -cirrus_get_start_addr(void) -{ - u16 crtc_addr = stdvga_get_crtc(); - u8 b2 = stdvga_crtc_read(crtc_addr, 0x0c); - u8 b1 = stdvga_crtc_read(crtc_addr, 0x0d); - u8 b3 = stdvga_crtc_read(crtc_addr, 0x1b); - u8 b4 = stdvga_crtc_read(crtc_addr, 0x1d); - return (b1 | (b2<<8) | ((b3 & 0x01) << 16) | ((b3 & 0x0c) << 15) - | ((b4 & 0x80) << 12)); -} - -static void -cirrus_vesa_07h(struct bregs *regs) -{ - if (regs->bl == 0x80 || regs->bl == 0x00) { - u32 addr = (cirrus_get_bpp_bytes() * regs->cx - + cirrus_get_line_offset() * regs->dx); - cirrus_set_start_addr(addr / 4); - } else if (regs->bl == 0x01) { - u32 addr = cirrus_get_start_addr() * 4; - u32 linelength = cirrus_get_line_offset(); - regs->dx = addr / linelength; - regs->cx = (addr % linelength) / cirrus_get_bpp_bytes(); - } else { - regs->ax = 0x0100; - return; - } - - regs->ax = 0x004f; -} - static void cirrus_vesa_10h(struct bregs *regs) { @@ -697,7 +659,6 @@ void cirrus_vesa(struct bregs *regs) { switch (regs->al) { - case 0x07: cirrus_vesa_07h(regs); break; case 0x10: cirrus_vesa_10h(regs); break; default: cirrus_vesa_not_handled(regs); break; } diff --git a/vgasrc/clext.h b/vgasrc/clext.h index 55476a0..1e4506c 100644 --- a/vgasrc/clext.h +++ b/vgasrc/clext.h @@ -8,6 +8,8 @@ int clext_get_window(struct vgamode_s *vmode_g, int window); int clext_set_window(struct vgamode_s *vmode_g, int window, int val); int clext_get_linelength(struct vgamode_s *vmode_g); int clext_set_linelength(struct vgamode_s *vmode_g, int val); +int clext_get_displaystart(struct vgamode_s *vmode_g); +int clext_set_displaystart(struct vgamode_s *vmode_g, int val); int clext_set_mode(struct vgamode_s *vmode_g, int flags); void clext_list_modes(u16 seg, u16 *dest, u16 *last); int clext_init(void); diff --git a/vgasrc/stdvga.c b/vgasrc/stdvga.c index a310167..13334ed 100644 --- a/vgasrc/stdvga.c +++ b/vgasrc/stdvga.c @@ -254,14 +254,6 @@ stdvga_set_cursor_shape(u8 start, u8 end) }
void -stdvga_set_active_page(u16 address) -{ - u16 crtc_addr = stdvga_get_crtc(); - stdvga_crtc_write(crtc_addr, 0x0c, address >> 8); - stdvga_crtc_write(crtc_addr, 0x0d, address); -} - -void stdvga_set_cursor_pos(u16 address) { u16 crtc_addr = stdvga_get_crtc(); @@ -313,6 +305,25 @@ stdvga_set_linelength(struct vgamode_s *vmode_g, int val) return 0; }
+int +stdvga_get_displaystart(struct vgamode_s *vmode_g) +{ + u16 crtc_addr = stdvga_get_crtc(); + int addr = (stdvga_crtc_read(crtc_addr, 0x0c) << 8 + | stdvga_crtc_read(crtc_addr, 0x0d)); + return addr * stdvga_bpp_factor(vmode_g); +} + +int +stdvga_set_displaystart(struct vgamode_s *vmode_g, int val) +{ + u16 crtc_addr = stdvga_get_crtc(); + val /= stdvga_bpp_factor(vmode_g); + stdvga_crtc_write(crtc_addr, 0x0c, val >> 8); + stdvga_crtc_write(crtc_addr, 0x0d, val); + return 0; +} +
/**************************************************************** * Save/Restore/Set state diff --git a/vgasrc/stdvga.h b/vgasrc/stdvga.h index ad496b5..f6fda00 100644 --- a/vgasrc/stdvga.h +++ b/vgasrc/stdvga.h @@ -131,7 +131,6 @@ void stdvga_load_font(u16 seg, void *src_far, u16 count u16 stdvga_get_crtc(void); int stdvga_bpp_factor(struct vgamode_s *vmode_g); void stdvga_set_cursor_shape(u8 start, u8 end); -void stdvga_set_active_page(u16 address); void stdvga_set_cursor_pos(u16 address); void stdvga_set_scan_lines(u8 lines); u16 stdvga_get_vde(void); @@ -139,6 +138,8 @@ int stdvga_get_window(struct vgamode_s *vmode_g, int window); int stdvga_set_window(struct vgamode_s *vmode_g, int window, int val); int stdvga_get_linelength(struct vgamode_s *vmode_g); int stdvga_set_linelength(struct vgamode_s *vmode_g, int val); +int stdvga_get_displaystart(struct vgamode_s *vmode_g); +int stdvga_set_displaystart(struct vgamode_s *vmode_g, int val); void stdvga_save_state(u16 seg, struct saveVideoHardware *info); void stdvga_restore_state(u16 seg, struct saveVideoHardware *info); int stdvga_set_mode(struct vgamode_s *vmode_g, int flags); diff --git a/vgasrc/vbe.c b/vgasrc/vbe.c index 68d2025..9e1fe1c 100644 --- a/vgasrc/vbe.c +++ b/vgasrc/vbe.c @@ -273,8 +273,37 @@ fail: static void vbe_104f07(struct bregs *regs) { - debug_stub(regs); - regs->ax = 0x0100; + struct vgamode_s *vmode_g = get_current_mode(); + if (! vmode_g) + goto fail; + int bpp = vga_bpp(vmode_g); + int linelength = vgahw_get_linelength(vmode_g); + if (linelength < 0) + goto fail; + + int ret; + switch (regs->bl) { + case 0x80: + case 0x00: + ret = vgahw_set_displaystart( + vmode_g, DIV_ROUND_UP(regs->cx * bpp, 8) + linelength * regs->dx); + if (ret) + goto fail; + break; + case 0x01: + ret = vgahw_get_displaystart(vmode_g); + if (ret < 0) + goto fail; + regs->dx = ret / linelength; + regs->cx = (ret % linelength) * 8 / bpp; + break; + default: + goto fail; + } + regs->ax = 0x004f; + return; +fail: + regs->ax = 0x014f; }
static void diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c index 6b01b73..3c63337 100644 --- a/vgasrc/vgabios.c +++ b/vgasrc/vgabios.c @@ -176,9 +176,8 @@ set_active_page(u8 page) struct cursorpos cp = get_cursor_pos(page);
// Calculate memory address of start of page - u8 memmodel = GET_GLOBAL(vmode_g->memmodel); - u16 address = GET_BDA(video_pagesize) * page; - stdvga_set_active_page(memmodel == MM_TEXT ? address / 2 : address); + int address = GET_BDA(video_pagesize) * page; + vgahw_set_displaystart(vmode_g, address);
// And change the BIOS page SET_BDA(video_pagestart, address); diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h index 494309b..af6b068 100644 --- a/vgasrc/vgahw.h +++ b/vgasrc/vgahw.h @@ -77,4 +77,20 @@ static inline int vgahw_set_linelength(struct vgamode_s *vmode_g, int val) { return stdvga_set_linelength(vmode_g, val); }
+static inline int vgahw_get_displaystart(struct vgamode_s *vmode_g) { + if (CONFIG_VGA_CIRRUS) + return clext_get_displaystart(vmode_g); + if (CONFIG_VGA_BOCHS) + return bochsvga_get_displaystart(vmode_g); + return stdvga_get_displaystart(vmode_g); +} + +static inline int vgahw_set_displaystart(struct vgamode_s *vmode_g, int val) { + if (CONFIG_VGA_CIRRUS) + return clext_set_displaystart(vmode_g, val); + if (CONFIG_VGA_BOCHS) + return bochsvga_set_displaystart(vmode_g, val); + return stdvga_set_displaystart(vmode_g, val); +} + #endif // vgahw.h
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/clext.c | 64 +++++++++---------------------------------------------- vgasrc/vbe.c | 21 ++++++++++++++++++ 2 files changed, 32 insertions(+), 53 deletions(-)
diff --git a/vgasrc/clext.c b/vgasrc/clext.c index 0640752..45fab80 100644 --- a/vgasrc/clext.c +++ b/vgasrc/clext.c @@ -315,6 +315,17 @@ is_cirrus_mode(struct vgamode_s *vmode_g) && vmode_g <= &cirrus_modes[ARRAY_SIZE(cirrus_modes)-1].info); }
+void +clext_list_modes(u16 seg, u16 *dest, u16 *last) +{ + int i; + for (i=0; i<ARRAY_SIZE(cirrus_vesa_modelist) && dest<last; i++) { + SET_FARVAR(seg, *dest, GET_GLOBAL(cirrus_vesa_modelist[i].vesamode)); + dest++; + } + stdvga_list_modes(seg, dest, last); +} + static u16 cirrus_vesamode_to_mode(u16 vesamode) { @@ -613,59 +624,6 @@ clext_1012(struct bregs *regs)
/**************************************************************** - * vesa calls - ****************************************************************/ - -void -clext_list_modes(u16 seg, u16 *dest, u16 *last) -{ - int i; - for (i=0; i<ARRAY_SIZE(cirrus_vesa_modelist) && dest<last; i++) { - SET_FARVAR(seg, *dest, GET_GLOBAL(cirrus_vesa_modelist[i].vesamode)); - dest++; - } - stdvga_list_modes(seg, dest, last); -} - -static void -cirrus_vesa_10h(struct bregs *regs) -{ - if (regs->bl == 0x00) { - regs->bx = 0x0f30; - regs->ax = 0x004f; - return; - } - if (regs->bl == 0x01) { - SET_BDA(vbe_flag, regs->bh); - regs->ax = 0x004f; - return; - } - if (regs->bl == 0x02) { - regs->bh = GET_BDA(vbe_flag); - regs->ax = 0x004f; - return; - } - regs->ax = 0x014f; -} - -static void -cirrus_vesa_not_handled(struct bregs *regs) -{ - debug_stub(regs); - regs->ax = 0x014f; -} - -void -cirrus_vesa(struct bregs *regs) -{ - switch (regs->al) { - case 0x10: cirrus_vesa_10h(regs); break; - default: cirrus_vesa_not_handled(regs); break; - } -} - - -/**************************************************************** * init ****************************************************************/
diff --git a/vgasrc/vbe.c b/vgasrc/vbe.c index 9e1fe1c..c1b03f0 100644 --- a/vgasrc/vbe.c +++ b/vgasrc/vbe.c @@ -321,6 +321,26 @@ vbe_104f0a(struct bregs *regs) }
static void +vbe_104f10(struct bregs *regs) +{ + switch (regs->bl) { + case 0x00: + regs->bx = 0x0f30; + break; + case 0x01: + SET_BDA(vbe_flag, regs->bh); + break; + case 0x02: + regs->bh = GET_BDA(vbe_flag); + break; + default: + regs->ax = 0x014f; + return; + } + regs->ax = 0x004f; +} + +static void vbe_104fXX(struct bregs *regs) { debug_stub(regs); @@ -346,6 +366,7 @@ handle_104f(struct bregs *regs) case 0x07: vbe_104f07(regs); break; case 0x08: vbe_104f08(regs); break; case 0x0a: vbe_104f0a(regs); break; + case 0x10: vbe_104f10(regs); break; default: vbe_104fXX(regs); break; } }
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/stdvga.c | 3 ++- vgasrc/stdvga.h | 2 +- vgasrc/vgabios.c | 8 +++----- 3 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/vgasrc/stdvga.c b/vgasrc/stdvga.c index 13334ed..ed4dcd2 100644 --- a/vgasrc/stdvga.c +++ b/vgasrc/stdvga.c @@ -254,9 +254,10 @@ stdvga_set_cursor_shape(u8 start, u8 end) }
void -stdvga_set_cursor_pos(u16 address) +stdvga_set_cursor_pos(int address) { u16 crtc_addr = stdvga_get_crtc(); + address /= 2; // Assume we're in text mode. stdvga_crtc_write(crtc_addr, 0x0e, address >> 8); stdvga_crtc_write(crtc_addr, 0x0f, address); } diff --git a/vgasrc/stdvga.h b/vgasrc/stdvga.h index f6fda00..94b22ff 100644 --- a/vgasrc/stdvga.h +++ b/vgasrc/stdvga.h @@ -131,7 +131,7 @@ void stdvga_load_font(u16 seg, void *src_far, u16 count u16 stdvga_get_crtc(void); int stdvga_bpp_factor(struct vgamode_s *vmode_g); void stdvga_set_cursor_shape(u8 start, u8 end); -void stdvga_set_cursor_pos(u16 address); +void stdvga_set_cursor_pos(int address); void stdvga_set_scan_lines(u8 lines); u16 stdvga_get_vde(void); int stdvga_get_window(struct vgamode_s *vmode_g, int window); diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c index 3c63337..b801093 100644 --- a/vgasrc/vgabios.c +++ b/vgasrc/vgabios.c @@ -138,11 +138,9 @@ set_cursor_pos(struct cursorpos cp) return;
// Calculate the memory address - u16 nbcols = GET_BDA(video_cols); - u16 address = (GET_BDA(video_pagesize) * cp.page - + (cp.x + cp.y * nbcols) * 2); - - stdvga_set_cursor_pos(address / 2); + int address = (GET_BDA(video_pagesize) * cp.page + + (cp.x + cp.y * GET_BDA(video_cols)) * 2); + stdvga_set_cursor_pos(address); }
static struct cursorpos
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/stdvga.c | 105 +------------------------------------------- vgasrc/stdvga.h | 20 +-------- vgasrc/stdvgaio.c | 1 + vgasrc/stdvgamodes.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++- vgasrc/vgafb.c | 1 + 5 files changed, 124 insertions(+), 123 deletions(-)
diff --git a/vgasrc/stdvga.c b/vgasrc/stdvga.c index ed4dcd2..dcc51a8 100644 --- a/vgasrc/stdvga.c +++ b/vgasrc/stdvga.c @@ -5,6 +5,7 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license.
+#include "vgabios.h" // struct vgamode_s #include "stdvga.h" // stdvga_init #include "ioport.h" // outb #include "farptr.h" // SET_FARVAR @@ -327,7 +328,7 @@ stdvga_set_displaystart(struct vgamode_s *vmode_g, int val)
/**************************************************************** - * Save/Restore/Set state + * Save/Restore state ****************************************************************/
void @@ -396,114 +397,12 @@ stdvga_restore_state(u16 seg, struct saveVideoHardware *info) outb(GET_FARVAR(seg, info->feature), crtc_addr - 0x4 + 0xa); }
-static void -clear_screen(struct vgamode_s *vmode_g) -{ - switch (GET_GLOBAL(vmode_g->memmodel)) { - case MM_TEXT: - memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0720, 32*1024); - break; - case MM_CGA: - memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 32*1024); - break; - default: - // XXX - old code gets/sets/restores sequ register 2 to 0xf - - // but it should always be 0xf anyway. - memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 64*1024); - } -} - -int -stdvga_set_mode(struct vgamode_s *vmode_g, int flags) -{ - if (! stdvga_is_mode(vmode_g)) { - warn_internalerror(); - return -1; - } - struct stdvga_mode_s *stdmode_g = container_of( - vmode_g, struct stdvga_mode_s, info); - - // if palette loading (bit 3 of modeset ctl = 0) - if (!(flags & MF_NOPALETTE)) { // Set the PEL mask - stdvga_pelmask_write(GET_GLOBAL(stdmode_g->pelmask)); - - // From which palette - u8 *palette_g = GET_GLOBAL(stdmode_g->dac); - u16 palsize = GET_GLOBAL(stdmode_g->dacsize) / 3; - - // Always 256*3 values - stdvga_dac_write(get_global_seg(), palette_g, 0, palsize); - int i; - for (i = palsize; i < 0x0100; i++) { - static u8 rgb[3] VAR16; - stdvga_dac_write(get_global_seg(), rgb, i, 1); - } - - if (flags & MF_GRAYSUM) - stdvga_perform_gray_scale_summing(0x00, 0x100); - } - - // Set Attribute Ctl - u8 *regs = GET_GLOBAL(stdmode_g->actl_regs); - int i; - for (i = 0; i <= 0x13; i++) - stdvga_attr_write(i, GET_GLOBAL(regs[i])); - stdvga_attr_write(0x14, 0x00); - - // Set Sequencer Ctl - stdvga_sequ_write(0x00, 0x03); - regs = GET_GLOBAL(stdmode_g->sequ_regs); - for (i = 1; i <= 4; i++) - stdvga_sequ_write(i, GET_GLOBAL(regs[i - 1])); - - // Set Grafx Ctl - regs = GET_GLOBAL(stdmode_g->grdc_regs); - for (i = 0; i <= 8; i++) - stdvga_grdc_write(i, GET_GLOBAL(regs[i])); - - // Set CRTC address VGA or MDA - u8 miscreg = GET_GLOBAL(stdmode_g->miscreg); - u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS; - if (!(miscreg & 1)) - crtc_addr = VGAREG_MDA_CRTC_ADDRESS; - - // Disable CRTC write protection - stdvga_crtc_write(crtc_addr, 0x11, 0x00); - // Set CRTC regs - regs = GET_GLOBAL(stdmode_g->crtc_regs); - for (i = 0; i <= 0x18; i++) - stdvga_crtc_write(crtc_addr, i, GET_GLOBAL(regs[i])); - - // Set the misc register - stdvga_misc_write(miscreg); - - // Enable video - stdvga_attrindex_write(0x20); - - // Clear screen - if (!(flags & MF_NOCLEARMEM)) - clear_screen(vmode_g); - - // Write the fonts in memory - u8 memmodel = GET_GLOBAL(vmode_g->memmodel); - if (memmodel == MM_TEXT) - stdvga_load_font(get_global_seg(), vgafont16, 0x100, 0, 0, 16); - - return 0; -} -
/**************************************************************** * Misc ****************************************************************/
void -stdvga_list_modes(u16 seg, u16 *dest, u16 *last) -{ - SET_FARVAR(seg, *dest, 0xffff); -} - -void stdvga_enable_video_addressing(u8 disable) { u8 v = (disable & 1) ? 0x00 : 0x02; diff --git a/vgasrc/stdvga.h b/vgasrc/stdvga.h index 94b22ff..4933723 100644 --- a/vgasrc/stdvga.h +++ b/vgasrc/stdvga.h @@ -2,7 +2,6 @@ #define __STDVGA_H
#include "types.h" // u8 -#include "vgabios.h" // struct vgamode_s
// VGA registers #define VGAREG_ACTL_ADDRESS 0x3c0 @@ -45,20 +44,6 @@ #define SEG_CTEXT 0xB800 #define SEG_MTEXT 0xB000
-struct stdvga_mode_s { - u16 mode; - struct vgamode_s info; - - u8 pelmask; - u8 *dac; - u16 dacsize; - u8 *sequ_regs; - u8 miscreg; - u8 *crtc_regs; - u8 *actl_regs; - u8 *grdc_regs; -}; - struct saveVideoHardware { u8 sequ_index; u8 crtc_index; @@ -84,9 +69,10 @@ struct saveDACcolors {
// stdvgamodes.c struct vgamode_s *stdvga_find_mode(int mode); -int stdvga_is_mode(struct vgamode_s *vmode_g); +void stdvga_list_modes(u16 seg, u16 *dest, u16 *last); void stdvga_build_video_param(void); void stdvga_override_crtc(int mode, u8 *crtc); +int stdvga_set_mode(struct vgamode_s *vmode_g, int flags);
// stdvgaio.c u8 stdvga_pelmask_read(void); @@ -142,9 +128,7 @@ int stdvga_get_displaystart(struct vgamode_s *vmode_g); int stdvga_set_displaystart(struct vgamode_s *vmode_g, int val); void stdvga_save_state(u16 seg, struct saveVideoHardware *info); void stdvga_restore_state(u16 seg, struct saveVideoHardware *info); -int stdvga_set_mode(struct vgamode_s *vmode_g, int flags); void stdvga_enable_video_addressing(u8 disable); -void stdvga_list_modes(u16 seg, u16 *dest, u16 *last); int stdvga_init(void);
#endif // stdvga.h diff --git a/vgasrc/stdvgaio.c b/vgasrc/stdvgaio.c index 5591ad2..b370d1a 100644 --- a/vgasrc/stdvgaio.c +++ b/vgasrc/stdvgaio.c @@ -5,6 +5,7 @@ // This file may be distributed under the terms of the GNU LGPLv3 license.
#include "stdvga.h" // stdvga_pelmask_read +#include "farptr.h" // GET_FARVAR #include "ioport.h" // inb
u8 diff --git a/vgasrc/stdvgamodes.c b/vgasrc/stdvgamodes.c index 1b47e98..5497da8 100644 --- a/vgasrc/stdvgamodes.c +++ b/vgasrc/stdvgamodes.c @@ -256,6 +256,20 @@ static u8 crtc_6A[] VAR16 = {
#define PAL(x) x, sizeof(x)
+struct stdvga_mode_s { + u16 mode; + struct vgamode_s info; + + u8 pelmask; + u8 *dac; + u16 dacsize; + u8 *sequ_regs; + u8 miscreg; + u8 *crtc_regs; + u8 *actl_regs; + u8 *grdc_regs; +}; + static struct stdvga_mode_s vga_modes[] VAR16 = { //mode { model tx ty bpp cw ch sstart } // pelm dac sequ misc crtc actl grdc @@ -298,8 +312,8 @@ static struct stdvga_mode_s vga_modes[] VAR16 = { * Mode functions ****************************************************************/
-int -stdvga_is_mode(struct vgamode_s *vmode_g) +static int +is_stdvga_mode(struct vgamode_s *vmode_g) { return (vmode_g >= &vga_modes[0].info && vmode_g <= &vga_modes[ARRAY_SIZE(vga_modes)-1].info); @@ -318,6 +332,12 @@ stdvga_find_mode(int mode) }
void +stdvga_list_modes(u16 seg, u16 *dest, u16 *last) +{ + SET_FARVAR(seg, *dest, 0xffff); +} + +void stdvga_build_video_param(void) { static u8 parammodes[] VAR16 = { @@ -378,3 +398,99 @@ stdvga_override_crtc(int mode, u8 *crtc) vmode_g, struct stdvga_mode_s, info); SET_VGA(stdmode_g->crtc_regs, crtc); } + +static void +clear_screen(struct vgamode_s *vmode_g) +{ + switch (GET_GLOBAL(vmode_g->memmodel)) { + case MM_TEXT: + memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0720, 32*1024); + break; + case MM_CGA: + memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 32*1024); + break; + default: + // XXX - old code gets/sets/restores sequ register 2 to 0xf - + // but it should always be 0xf anyway. + memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 64*1024); + } +} + +int +stdvga_set_mode(struct vgamode_s *vmode_g, int flags) +{ + if (! is_stdvga_mode(vmode_g)) { + warn_internalerror(); + return -1; + } + struct stdvga_mode_s *stdmode_g = container_of( + vmode_g, struct stdvga_mode_s, info); + + // if palette loading (bit 3 of modeset ctl = 0) + if (!(flags & MF_NOPALETTE)) { // Set the PEL mask + stdvga_pelmask_write(GET_GLOBAL(stdmode_g->pelmask)); + + // From which palette + u8 *palette_g = GET_GLOBAL(stdmode_g->dac); + u16 palsize = GET_GLOBAL(stdmode_g->dacsize) / 3; + + // Always 256*3 values + stdvga_dac_write(get_global_seg(), palette_g, 0, palsize); + int i; + for (i = palsize; i < 0x0100; i++) { + static u8 rgb[3] VAR16; + stdvga_dac_write(get_global_seg(), rgb, i, 1); + } + + if (flags & MF_GRAYSUM) + stdvga_perform_gray_scale_summing(0x00, 0x100); + } + + // Set Attribute Ctl + u8 *regs = GET_GLOBAL(stdmode_g->actl_regs); + int i; + for (i = 0; i <= 0x13; i++) + stdvga_attr_write(i, GET_GLOBAL(regs[i])); + stdvga_attr_write(0x14, 0x00); + + // Set Sequencer Ctl + stdvga_sequ_write(0x00, 0x03); + regs = GET_GLOBAL(stdmode_g->sequ_regs); + for (i = 1; i <= 4; i++) + stdvga_sequ_write(i, GET_GLOBAL(regs[i - 1])); + + // Set Grafx Ctl + regs = GET_GLOBAL(stdmode_g->grdc_regs); + for (i = 0; i <= 8; i++) + stdvga_grdc_write(i, GET_GLOBAL(regs[i])); + + // Set CRTC address VGA or MDA + u8 miscreg = GET_GLOBAL(stdmode_g->miscreg); + u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS; + if (!(miscreg & 1)) + crtc_addr = VGAREG_MDA_CRTC_ADDRESS; + + // Disable CRTC write protection + stdvga_crtc_write(crtc_addr, 0x11, 0x00); + // Set CRTC regs + regs = GET_GLOBAL(stdmode_g->crtc_regs); + for (i = 0; i <= 0x18; i++) + stdvga_crtc_write(crtc_addr, i, GET_GLOBAL(regs[i])); + + // Set the misc register + stdvga_misc_write(miscreg); + + // Enable video + stdvga_attrindex_write(0x20); + + // Clear screen + if (!(flags & MF_NOCLEARMEM)) + clear_screen(vmode_g); + + // Write the fonts in memory + u8 memmodel = GET_GLOBAL(vmode_g->memmodel); + if (memmodel == MM_TEXT) + stdvga_load_font(get_global_seg(), vgafont16, 0x100, 0, 0, 16); + + return 0; +} diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c index f0bd71e..79e389f 100644 --- a/vgasrc/vgafb.c +++ b/vgasrc/vgafb.c @@ -5,6 +5,7 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license.
+#include "vgabios.h" // vgafb_scroll #include "biosvar.h" // GET_BDA #include "util.h" // memset_far #include "stdvga.h" // stdvga_planar4_plane