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) {