vgabios: Move BDA setting from driver code to common code.
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>
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 @@
{ 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 @@
}
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 @@
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 @@
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 @@
* 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 @@
}
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 @@
}
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 @@
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 @@
// 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 @@
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 @@
* 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 @@
{
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 @@
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..d35cb02 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
@@ -316,7 +317,9 @@
static void
restore_bda_state(u16 seg, struct saveBDAstate *info)
{
- SET_BDA(video_mode, GET_FARVAR(seg, info->video_mode));
+ u16 mode = GET_FARVAR(seg, info->video_mode);
+ SET_BDA(video_mode, mode);
+ SET_BDA(vbe_mode, mode);
SET_BDA(video_cols, GET_FARVAR(seg, info->video_cols));
SET_BDA(video_pagesize, GET_FARVAR(seg, info->video_pagesize));
SET_BDA(crtc_address, GET_FARVAR(seg, info->crtc_address));
@@ -344,19 +347,32 @@
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 +418,8 @@
SET_IVT(0x43, SEGOFF(get_global_seg(), (u32)vgafont16));
break;
}
+
+ return 0;
}
@@ -426,7 +444,7 @@
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 @@
#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 @@
};
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 @@
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) {