More vgabios work. At the end of this series, the remaining bochsvga capabilities are now ported from the LGPL bios (with the exception of the 32bit interface which seems like it isn't worth porting). This basically completes the porting effort.
-Kevin
Kevin O'Connor (6): vgabios: Simplify cga/packed character screen writing. vgabios: Fix screen attrs on cga scroll. vgabios: Handle VGA option rom being re-run. vgabios: Add support for VBE get/set dac palette format (func 08). vgabios: Move save/restore state code from vgabios.c to stdvga.c. vgabios: Implement VBE save/restore state function (func 04).
vgasrc/bochsvga.c | 89 +++++++++++++++++++++++++++++++++++++ vgasrc/bochsvga.h | 5 ++ vgasrc/clext.c | 43 +++++++++++++++--- vgasrc/clext.h | 3 + vgasrc/stdvga.c | 126 +++++++++++++++++++++++++++++++++++++++++++---------- vgasrc/stdvga.h | 32 ++----------- vgasrc/vbe.c | 57 ++++++++++++++++++++++-- vgasrc/vgabios.c | 111 ++++++++++++++++++----------------------------- vgasrc/vgabios.h | 5 ++- vgasrc/vgafb.c | 58 +++++++++--------------- vgasrc/vgahw.h | 36 +++++++++++++++ 11 files changed, 396 insertions(+), 169 deletions(-)
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/vgafb.c | 54 +++++++++++++++++------------------------------------- 1 files changed, 17 insertions(+), 37 deletions(-)
diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c index 79e389f..d988c88 100644 --- a/vgasrc/vgafb.c +++ b/vgasrc/vgafb.c @@ -253,40 +253,23 @@ write_gfx_char_cga(struct vgamode_s *vmode_g u8 *dest_far = (void*)(addr + (i >> 1) * 80); if (i & 1) dest_far += 0x2000; - u8 mask = 0x80; if (bpp == 1) { - u8 data = 0; + u8 colors = (ca.attr & 0x01) ? 0xff : 0x00; + u8 pixels = colors & GET_GLOBAL(fdata_g[src + i]); if (ca.attr & 0x80) - data = GET_FARVAR(SEG_CTEXT, *dest_far); - u8 j; - for (j = 0; j < 8; j++) { - if (GET_GLOBAL(fdata_g[src + i]) & mask) { - if (ca.attr & 0x80) - data ^= (ca.attr & 0x01) << (7 - j); - else - data |= (ca.attr & 0x01) << (7 - j); - } - mask >>= 1; - } - SET_FARVAR(SEG_CTEXT, *dest_far, data); + pixels ^= GET_FARVAR(SEG_GRAPH, *dest_far); + SET_FARVAR(SEG_CTEXT, *dest_far, pixels); } else { - while (mask > 0) { - u8 data = 0; - if (ca.attr & 0x80) - data = GET_FARVAR(SEG_CTEXT, *dest_far); - u8 j; - for (j = 0; j < 4; j++) { - if (GET_GLOBAL(fdata_g[src + i]) & mask) { - if (ca.attr & 0x80) - data ^= (ca.attr & 0x03) << ((3 - j) * 2); - else - data |= (ca.attr & 0x03) << ((3 - j) * 2); - } - mask >>= 1; - } - SET_FARVAR(SEG_CTEXT, *dest_far, data); - dest_far += 1; - } + u16 pixels = 0; + u8 fontline = GET_GLOBAL(fdata_g[src + i]); + int j; + for (j = 0; j < 8; j++) + if (fontline & (1<<j)) + pixels |= (ca.attr & 0x03) << (j*2); + pixels = htons(pixels); + if (ca.attr & 0x80) + pixels ^= GET_FARVAR(SEG_GRAPH, *(u16*)dest_far); + SET_FARVAR(SEG_CTEXT, *(u16*)dest_far, pixels); } } } @@ -306,14 +289,11 @@ write_gfx_char_lin(struct vgamode_s *vmode_g u8 i; for (i = 0; i < 8; i++) { u8 *dest_far = (void*)(addr + i * nbcols * 8); - u8 mask = 0x80; + u8 fontline = GET_GLOBAL(fdata_g[src + i]); u8 j; for (j = 0; j < 8; j++) { - u8 data = 0x00; - if (GET_GLOBAL(fdata_g[src + i]) & mask) - data = ca.attr; - SET_FARVAR(SEG_GRAPH, dest_far[j], data); - mask >>= 1; + u8 pixel = (fontline & (0x80>>j)) ? ca.attr : 0x00; + SET_FARVAR(SEG_GRAPH, dest_far[j], pixel); } } }
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/vgafb.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c index d988c88..a75bc81 100644 --- a/vgasrc/vgafb.c +++ b/vgasrc/vgafb.c @@ -93,6 +93,10 @@ scroll_cga(struct vgamode_s *vmode_g, int nblines, int attr } if (attr < 0) attr = 0; + if (cwidth == 1) + attr = (attr&1) | ((attr&1)<<1); + attr &= 3; + attr |= (attr<<2) | (attr<<4) | (attr<<6); int cols = lr.x - ul.x + 1; int rows = lr.y - ul.y + 1; if (nblines < rows) {
Check for the case where the option rom is executed a second time - in that case re-init the hardware, but do not set any variables. This should make the rom better behaving when run from S3 resume.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/bochsvga.c | 3 +++ vgasrc/clext.c | 19 +++++++++++-------- vgasrc/vgabios.c | 8 +++++++- vgasrc/vgabios.h | 1 + 4 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/vgasrc/bochsvga.c b/vgasrc/bochsvga.c index e6ab794..9210004 100644 --- a/vgasrc/bochsvga.c +++ b/vgasrc/bochsvga.c @@ -258,6 +258,9 @@ bochsvga_init(void)
dispi_write(VBE_DISPI_INDEX_ID, VBE_DISPI_ID5);
+ if (GET_GLOBAL(HaveRunInit)) + return 0; + u32 lfb_addr = VBE_DISPI_LFB_PHYSICAL_ADDRESS; int bdf = GET_GLOBAL(VgaBDF); if (CONFIG_VGA_PCI && bdf >= 0) { diff --git a/vgasrc/clext.c b/vgasrc/clext.c index 26b34e0..0470d80 100644 --- a/vgasrc/clext.c +++ b/vgasrc/clext.c @@ -590,6 +590,17 @@ clext_init(void) return -1; dprintf(1, "cirrus init 2\n");
+ // memory setup + stdvga_sequ_write(0x0a, stdvga_sequ_read(0x0f) & 0x18); + // set vga mode + stdvga_sequ_write(0x07, 0x00); + // reset bitblt + stdvga_grdc_write(0x31, 0x04); + stdvga_grdc_write(0x31, 0x00); + + if (GET_GLOBAL(HaveRunInit)) + return 0; + u32 lfb_addr = 0; int bdf = GET_GLOBAL(VgaBDF); if (CONFIG_VGA_PCI && bdf >= 0) @@ -600,13 +611,5 @@ clext_init(void) SET_VGA(VBE_total_memory, totalmem * 64 * 1024); SET_VGA(VBE_win_granularity, 16);
- // memory setup - stdvga_sequ_write(0x0a, stdvga_sequ_read(0x0f) & 0x18); - // set vga mode - stdvga_sequ_write(0x07, 0x00); - // reset bitblt - stdvga_grdc_write(0x31, 0x04); - stdvga_grdc_write(0x31, 0x00); - return 0; } diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c index e69c6c5..ec251fe 100644 --- a/vgasrc/vgabios.c +++ b/vgasrc/vgabios.c @@ -1271,13 +1271,14 @@ init_bios_area(void) }
int VgaBDF VAR16 = -1; +int HaveRunInit VAR16;
void VISIBLE16 vga_post(struct bregs *regs) { debug_enter(regs, DEBUG_VGA_POST);
- if (CONFIG_VGA_PCI) { + if (CONFIG_VGA_PCI && !GET_GLOBAL(HaveRunInit)) { u16 bdf = regs->ax; if ((pci_config_readw(bdf, PCI_VENDOR_ID) == GET_GLOBAL(rom_pci_data.vendor)) @@ -1292,6 +1293,9 @@ vga_post(struct bregs *regs) return; }
+ if (GET_GLOBAL(HaveRunInit)) + return; + init_bios_area();
SET_VGA(video_save_pointer_table.videoparam @@ -1303,6 +1307,8 @@ vga_post(struct bregs *regs)
// XXX - clear screen and display info
+ SET_VGA(HaveRunInit, 1); + // Fixup checksum extern u8 _rom_header_size, _rom_header_checksum; SET_VGA(_rom_header_checksum, 0); diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h index b47c669..0aff684 100644 --- a/vgasrc/vgabios.h +++ b/vgasrc/vgabios.h @@ -75,6 +75,7 @@ extern u8 vgafont16alt[];
// vgabios.c extern int VgaBDF; +extern int HaveRunInit; #define SET_VGA(var, val) SET_FARVAR(get_global_seg(), (var), (val)) struct carattr { u8 car, attr, use_attr;
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/bochsvga.c | 21 +++++++++++++++++++++ vgasrc/bochsvga.h | 2 ++ vgasrc/stdvga.c | 12 ++++++++++++ vgasrc/stdvga.h | 2 ++ vgasrc/vbe.c | 25 +++++++++++++++++++++++-- vgasrc/vgahw.h | 12 ++++++++++++ 6 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/vgasrc/bochsvga.c b/vgasrc/bochsvga.c index 9210004..0a36afc 100644 --- a/vgasrc/bochsvga.c +++ b/vgasrc/bochsvga.c @@ -180,6 +180,27 @@ bochsvga_set_displaystart(struct vgamode_s *vmode_g, int val) return 0; }
+int +bochsvga_get_dacformat(struct vgamode_s *vmode_g) +{ + u16 en = dispi_read(VBE_DISPI_INDEX_ENABLE); + return (en & VBE_DISPI_8BIT_DAC) ? 8 : 6; +} + +int +bochsvga_set_dacformat(struct vgamode_s *vmode_g, int val) +{ + u16 en = dispi_read(VBE_DISPI_INDEX_ENABLE); + if (val == 6) + en &= ~VBE_DISPI_8BIT_DAC; + else if (val == 8) + en |= VBE_DISPI_8BIT_DAC; + else + return -1; + dispi_write(VBE_DISPI_INDEX_ENABLE, en); + return 0; +} +
/**************************************************************** * Mode setting diff --git a/vgasrc/bochsvga.h b/vgasrc/bochsvga.h index 57b2b69..78a9e0a 100644 --- a/vgasrc/bochsvga.h +++ b/vgasrc/bochsvga.h @@ -60,6 +60,8 @@ 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_get_dacformat(struct vgamode_s *vmode_g); +int bochsvga_set_dacformat(struct vgamode_s *vmode_g, int val); int bochsvga_set_mode(struct vgamode_s *vmode_g, int flags); int bochsvga_init(void);
diff --git a/vgasrc/stdvga.c b/vgasrc/stdvga.c index dcc51a8..1b552db 100644 --- a/vgasrc/stdvga.c +++ b/vgasrc/stdvga.c @@ -326,6 +326,18 @@ stdvga_set_displaystart(struct vgamode_s *vmode_g, int val) return 0; }
+int +stdvga_get_dacformat(struct vgamode_s *vmode_g) +{ + return -1; +} + +int +stdvga_set_dacformat(struct vgamode_s *vmode_g, int val) +{ + return -1; +} +
/**************************************************************** * Save/Restore state diff --git a/vgasrc/stdvga.h b/vgasrc/stdvga.h index 4933723..000a097 100644 --- a/vgasrc/stdvga.h +++ b/vgasrc/stdvga.h @@ -126,6 +126,8 @@ 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); +int stdvga_get_dacformat(struct vgamode_s *vmode_g); +int stdvga_set_dacformat(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); void stdvga_enable_video_addressing(u8 disable); diff --git a/vgasrc/vbe.c b/vgasrc/vbe.c index 77b0934..0ee69b4 100644 --- a/vgasrc/vbe.c +++ b/vgasrc/vbe.c @@ -305,8 +305,29 @@ fail: static void vbe_104f08(struct bregs *regs) { - debug_stub(regs); - regs->ax = 0x0100; + struct vgamode_s *vmode_g = get_current_mode(); + if (! vmode_g) + goto fail; + u8 memmodel = GET_GLOBAL(vmode_g->memmodel); + if (memmodel == MM_DIRECT || memmodel == MM_YUV) { + regs->ax = 0x034f; + return; + } + if (regs->bl > 1) + goto fail; + if (regs->bl == 0) { + int ret = vgahw_set_dacformat(vmode_g, regs->bh); + if (ret < 0) + goto fail; + } + int ret = vgahw_get_dacformat(vmode_g); + if (ret < 0) + goto fail; + regs->bh = ret; + regs->ax = 0x004f; + return; +fail: + regs->ax = 0x014f; }
static void diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h index af6b068..585ae3d 100644 --- a/vgasrc/vgahw.h +++ b/vgasrc/vgahw.h @@ -93,4 +93,16 @@ static inline int vgahw_set_displaystart(struct vgamode_s *vmode_g, int val) { return stdvga_set_displaystart(vmode_g, val); }
+static inline int vgahw_get_dacformat(struct vgamode_s *vmode_g) { + if (CONFIG_VGA_BOCHS) + return bochsvga_get_dacformat(vmode_g); + return stdvga_get_dacformat(vmode_g); +} + +static inline int vgahw_set_dacformat(struct vgamode_s *vmode_g, int val) { + if (CONFIG_VGA_BOCHS) + return bochsvga_set_dacformat(vmode_g, val); + return stdvga_set_dacformat(vmode_g, val); +} + #endif // vgahw.h
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/stdvga.c | 114 +++++++++++++++++++++++++++++++++++++++++++----------- vgasrc/stdvga.h | 30 +------------- vgasrc/vgabios.c | 96 ++++++++++++++------------------------------- vgasrc/vgabios.h | 2 + 4 files changed, 126 insertions(+), 116 deletions(-)
diff --git a/vgasrc/stdvga.c b/vgasrc/stdvga.c index 1b552db..ae6c0be 100644 --- a/vgasrc/stdvga.c +++ b/vgasrc/stdvga.c @@ -111,25 +111,6 @@ stdvga_read_video_dac_state(u8 *pmode, u8 *curpage) ****************************************************************/
void -stdvga_save_dac_state(u16 seg, struct saveDACcolors *info) -{ - /* XXX: check this */ - SET_FARVAR(seg, info->rwmode, inb(VGAREG_DAC_STATE)); - SET_FARVAR(seg, info->peladdr, inb(VGAREG_DAC_WRITE_ADDRESS)); - SET_FARVAR(seg, info->pelmask, stdvga_pelmask_read()); - stdvga_dac_read(seg, info->dac, 0, 256); - SET_FARVAR(seg, info->color_select, 0); -} - -void -stdvga_restore_dac_state(u16 seg, struct saveDACcolors *info) -{ - stdvga_pelmask_write(GET_FARVAR(seg, info->pelmask)); - stdvga_dac_write(seg, info->dac, 0, 256); - outb(GET_FARVAR(seg, info->peladdr), VGAREG_DAC_WRITE_ADDRESS); -} - -void stdvga_perform_gray_scale_summing(u16 start, u16 count) { stdvga_attrindex_write(0x00); @@ -343,8 +324,23 @@ stdvga_set_dacformat(struct vgamode_s *vmode_g, int val) * Save/Restore state ****************************************************************/
-void -stdvga_save_state(u16 seg, struct saveVideoHardware *info) +struct saveVideoHardware { + u8 sequ_index; + u8 crtc_index; + u8 grdc_index; + u8 actl_index; + u8 feature; + u8 sequ_regs[4]; + u8 sequ0; + u8 crtc_regs[25]; + u8 actl_regs[20]; + u8 grdc_regs[9]; + u16 crtc_addr; + u8 plane_latch[4]; +}; + +static void +stdvga_save_hw_state(u16 seg, struct saveVideoHardware *info) { u16 crtc_addr = stdvga_get_crtc(); SET_FARVAR(seg, info->sequ_index, inb(VGAREG_SEQU_ADDRESS)); @@ -374,8 +370,8 @@ stdvga_save_state(u16 seg, struct saveVideoHardware *info) SET_FARVAR(seg, info->plane_latch[i], 0); }
-void -stdvga_restore_state(u16 seg, struct saveVideoHardware *info) +static void +stdvga_restore_hw_state(u16 seg, struct saveVideoHardware *info) { int i; for (i=0; i<4; i++) @@ -409,6 +405,78 @@ stdvga_restore_state(u16 seg, struct saveVideoHardware *info) outb(GET_FARVAR(seg, info->feature), crtc_addr - 0x4 + 0xa); }
+struct saveDACcolors { + u8 rwmode; + u8 peladdr; + u8 pelmask; + u8 dac[768]; + u8 color_select; +}; + +static void +stdvga_save_dac_state(u16 seg, struct saveDACcolors *info) +{ + /* XXX: check this */ + SET_FARVAR(seg, info->rwmode, inb(VGAREG_DAC_STATE)); + SET_FARVAR(seg, info->peladdr, inb(VGAREG_DAC_WRITE_ADDRESS)); + SET_FARVAR(seg, info->pelmask, stdvga_pelmask_read()); + stdvga_dac_read(seg, info->dac, 0, 256); + SET_FARVAR(seg, info->color_select, 0); +} + +static void +stdvga_restore_dac_state(u16 seg, struct saveDACcolors *info) +{ + stdvga_pelmask_write(GET_FARVAR(seg, info->pelmask)); + stdvga_dac_write(seg, info->dac, 0, 256); + outb(GET_FARVAR(seg, info->peladdr), VGAREG_DAC_WRITE_ADDRESS); +} + +int +stdvga_size_state(int states) +{ + int size = 0; + if (states & 1) + size += sizeof(struct saveVideoHardware); + if (states & 2) + size += sizeof(struct saveBDAstate); + if (states & 4) + size += sizeof(struct saveDACcolors); + return size; +} + +int +stdvga_save_state(u16 seg, void *data, int states) +{ + if (states & 1) { + stdvga_save_hw_state(seg, data); + data += sizeof(struct saveVideoHardware); + } + if (states & 2) { + save_bda_state(seg, data); + data += sizeof(struct saveBDAstate); + } + if (states & 4) + stdvga_save_dac_state(seg, data); + return 0; +} + +int +stdvga_restore_state(u16 seg, void *data, int states) +{ + if (states & 1) { + stdvga_restore_hw_state(seg, data); + data += sizeof(struct saveVideoHardware); + } + if (states & 2) { + restore_bda_state(seg, data); + data += sizeof(struct saveBDAstate); + } + if (states & 4) + stdvga_restore_dac_state(seg, data); + return 0; +} +
/**************************************************************** * Misc diff --git a/vgasrc/stdvga.h b/vgasrc/stdvga.h index 000a097..c9a9ba1 100644 --- a/vgasrc/stdvga.h +++ b/vgasrc/stdvga.h @@ -44,29 +44,6 @@ #define SEG_CTEXT 0xB800 #define SEG_MTEXT 0xB000
-struct saveVideoHardware { - u8 sequ_index; - u8 crtc_index; - u8 grdc_index; - u8 actl_index; - u8 feature; - u8 sequ_regs[4]; - u8 sequ0; - u8 crtc_regs[25]; - u8 actl_regs[20]; - u8 grdc_regs[9]; - u16 crtc_addr; - u8 plane_latch[4]; -}; - -struct saveDACcolors { - u8 rwmode; - u8 peladdr; - u8 pelmask; - u8 dac[768]; - u8 color_select; -}; - // stdvgamodes.c struct vgamode_s *stdvga_find_mode(int mode); void stdvga_list_modes(u16 seg, u16 *dest, u16 *last); @@ -107,8 +84,6 @@ void stdvga_get_all_palette_reg(u16 seg, u8 *data_far); void stdvga_toggle_intensity(u8 flag); void stdvga_select_video_dac_color_page(u8 flag, u8 data); void stdvga_read_video_dac_state(u8 *pmode, u8 *curpage); -void stdvga_save_dac_state(u16 seg, struct saveDACcolors *info); -void stdvga_restore_dac_state(u16 seg, struct saveDACcolors *info); void stdvga_perform_gray_scale_summing(u16 start, u16 count); void stdvga_set_text_block_specifier(u8 spec); void stdvga_planar4_plane(int plane); @@ -128,8 +103,9 @@ int stdvga_get_displaystart(struct vgamode_s *vmode_g); int stdvga_set_displaystart(struct vgamode_s *vmode_g, int val); int stdvga_get_dacformat(struct vgamode_s *vmode_g); int stdvga_set_dacformat(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_size_state(int states); +int stdvga_save_state(u16 seg, void *data, int states); +int stdvga_restore_state(u16 seg, void *data, int states); void stdvga_enable_video_addressing(u8 disable); int stdvga_init(void);
diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c index ec251fe..ea78c45 100644 --- a/vgasrc/vgabios.c +++ b/vgasrc/vgabios.c @@ -304,7 +304,7 @@ write_string(struct cursorpos *pcp, u8 attr, u16 count, u16 seg, u8 *offset_far) * Save and restore bda state ****************************************************************/
-static void +void save_bda_state(u16 seg, struct saveBDAstate *info) { SET_FARVAR(seg, info->video_mode, GET_BDA(video_mode)); @@ -317,7 +317,7 @@ save_bda_state(u16 seg, struct saveBDAstate *info) SET_FARVAR(seg, info->video_switches, GET_BDA(video_switches)); SET_FARVAR(seg, info->modeset_ctl, GET_BDA(modeset_ctl)); SET_FARVAR(seg, info->cursor_type, GET_BDA(cursor_type)); - u16 i; + int i; for (i=0; i<8; i++) SET_FARVAR(seg, info->cursor_pos[i], GET_BDA(cursor_pos[i])); SET_FARVAR(seg, info->video_pagestart, GET_BDA(video_pagestart)); @@ -327,7 +327,7 @@ save_bda_state(u16 seg, struct saveBDAstate *info) SET_FARVAR(seg, info->font1, GET_IVT(0x43)); }
-static void +void restore_bda_state(u16 seg, struct saveBDAstate *info) { u16 mode = GET_FARVAR(seg, info->video_mode); @@ -342,7 +342,7 @@ restore_bda_state(u16 seg, struct saveBDAstate *info) SET_BDA(video_switches, GET_FARVAR(seg, info->video_switches)); SET_BDA(modeset_ctl, GET_FARVAR(seg, info->modeset_ctl)); SET_BDA(cursor_type, GET_FARVAR(seg, info->cursor_type)); - u16 i; + int i; for (i = 0; i < 8; i++) SET_BDA(cursor_pos[i], GET_FARVAR(seg, info->cursor_pos[i])); SET_BDA(video_pagestart, GET_FARVAR(seg, info->video_pagestart)); @@ -1130,73 +1130,37 @@ handle_101b(struct bregs *regs)
static void -handle_101c00(struct bregs *regs) -{ - u16 flags = regs->cx; - u16 size = 0; - if (flags & 1) - size += sizeof(struct saveVideoHardware); - if (flags & 2) - size += sizeof(struct saveBDAstate); - if (flags & 4) - size += sizeof(struct saveDACcolors); - regs->bx = size; - regs->al = 0x1c; -} - -static void -handle_101c01(struct bregs *regs) -{ - u16 flags = regs->cx; - u16 seg = regs->es; - void *data = (void*)(regs->bx+0); - if (flags & 1) { - stdvga_save_state(seg, data); - data += sizeof(struct saveVideoHardware); - } - if (flags & 2) { - save_bda_state(seg, data); - data += sizeof(struct saveBDAstate); - } - if (flags & 4) - stdvga_save_dac_state(seg, data); - regs->al = 0x1c; -} - -static void -handle_101c02(struct bregs *regs) +handle_101c(struct bregs *regs) { - u16 flags = regs->cx; u16 seg = regs->es; void *data = (void*)(regs->bx+0); - if (flags & 1) { - stdvga_restore_state(seg, data); - data += sizeof(struct saveVideoHardware); - } - if (flags & 2) { - restore_bda_state(seg, data); - data += sizeof(struct saveBDAstate); - } - if (flags & 4) - stdvga_restore_dac_state(seg, data); - regs->al = 0x1c; -} - -static void -handle_101cXX(struct bregs *regs) -{ - debug_stub(regs); -} - -static void -handle_101c(struct bregs *regs) -{ + u16 states = regs->cx; + if (states & ~0x07) + goto fail; + int ret; switch (regs->al) { - case 0x00: handle_101c00(regs); break; - case 0x01: handle_101c01(regs); break; - case 0x02: handle_101c02(regs); break; - default: handle_101cXX(regs); break; + case 0x00: + ret = stdvga_size_state(states); + if (ret < 0) + goto fail; + regs->bx = ret / 64; + break; + case 0x01: + ret = stdvga_save_state(seg, data, states); + if (ret) + goto fail; + break; + case 0x02: + ret = stdvga_restore_state(seg, data, states); + if (ret) + goto fail; + break; + default: + goto fail; } + regs->al = 0x1c; +fail: + return; }
static void diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h index 0aff684..76ecb88 100644 --- a/vgasrc/vgabios.h +++ b/vgasrc/vgabios.h @@ -85,6 +85,8 @@ struct cursorpos { }; int vga_bpp(struct vgamode_s *vmode_g); u16 calc_page_size(u8 memmodel, u16 width, u16 height); +void save_bda_state(u16 seg, struct saveBDAstate *info); +void restore_bda_state(u16 seg, struct saveBDAstate *info); struct vgamode_s *get_current_mode(void); int vga_set_mode(int mode, int flags);
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/bochsvga.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++ vgasrc/bochsvga.h | 3 ++ vgasrc/clext.c | 24 +++++++++++++++++++ vgasrc/clext.h | 3 ++ vgasrc/vbe.c | 32 ++++++++++++++++++++++++- vgasrc/vgabios.c | 13 ++++++---- vgasrc/vgabios.h | 2 +- vgasrc/vgahw.h | 24 +++++++++++++++++++ 8 files changed, 158 insertions(+), 8 deletions(-)
diff --git a/vgasrc/bochsvga.c b/vgasrc/bochsvga.c index 0a36afc..957bde2 100644 --- a/vgasrc/bochsvga.c +++ b/vgasrc/bochsvga.c @@ -201,6 +201,71 @@ bochsvga_set_dacformat(struct vgamode_s *vmode_g, int val) return 0; }
+int +bochsvga_size_state(int states) +{ + int size = stdvga_size_state(states); + if (size < 0) + return size; + if (states & 8) + size += (VBE_DISPI_INDEX_Y_OFFSET-VBE_DISPI_INDEX_XRES+1)*sizeof(u16); + return size; +} + +int +bochsvga_save_state(u16 seg, void *data, int states) +{ + int ret = stdvga_save_state(seg, data, states); + if (ret < 0) + return ret; + + if (!(states & 8)) + return 0; + + u16 *info = (data + stdvga_size_state(states)); + u16 en = dispi_read(VBE_DISPI_INDEX_ENABLE); + SET_FARVAR(seg, *info, en); + info++; + if (!(en & VBE_DISPI_ENABLED)) + return 0; + int i; + for (i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) + if (i != VBE_DISPI_INDEX_ENABLE) { + u16 v = dispi_read(i); + SET_FARVAR(seg, *info, v); + info++; + } + return 0; +} + +int +bochsvga_restore_state(u16 seg, void *data, int states) +{ + int ret = stdvga_restore_state(seg, data, states); + if (ret < 0) + return ret; + + if (!(states & 8)) + return 0; + + u16 *info = (data + stdvga_size_state(states)); + u16 en = GET_FARVAR(seg, *info); + info++; + if (!(en & VBE_DISPI_ENABLED)) { + dispi_write(VBE_DISPI_INDEX_ENABLE, en); + return 0; + } + int i; + for (i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) + if (i == VBE_DISPI_INDEX_ENABLE) { + dispi_write(i, en); + } else { + dispi_write(i, GET_FARVAR(seg, *info)); + info++; + } + return 0; +} +
/**************************************************************** * Mode setting diff --git a/vgasrc/bochsvga.h b/vgasrc/bochsvga.h index 78a9e0a..1c98203 100644 --- a/vgasrc/bochsvga.h +++ b/vgasrc/bochsvga.h @@ -62,6 +62,9 @@ int bochsvga_get_displaystart(struct vgamode_s *vmode_g); int bochsvga_set_displaystart(struct vgamode_s *vmode_g, int val); int bochsvga_get_dacformat(struct vgamode_s *vmode_g); int bochsvga_set_dacformat(struct vgamode_s *vmode_g, int val); +int bochsvga_size_state(int states); +int bochsvga_save_state(u16 seg, void *data, int states); +int bochsvga_restore_state(u16 seg, void *data, int states); int bochsvga_set_mode(struct vgamode_s *vmode_g, int flags); int bochsvga_init(void);
diff --git a/vgasrc/clext.c b/vgasrc/clext.c index 0470d80..7d1a604 100644 --- a/vgasrc/clext.c +++ b/vgasrc/clext.c @@ -368,6 +368,30 @@ clext_set_displaystart(struct vgamode_s *vmode_g, int val) return 0; }
+int +clext_size_state(int states) +{ + if (states & 8) + return -1; + return stdvga_size_state(states); +} + +int +clext_save_state(u16 seg, void *data, int states) +{ + if (states & 8) + return -1; + return stdvga_save_state(seg, data, states); +} + +int +clext_restore_state(u16 seg, void *data, int states) +{ + if (states & 8) + return -1; + return stdvga_restore_state(seg, data, states); +} +
/**************************************************************** * Mode setting diff --git a/vgasrc/clext.h b/vgasrc/clext.h index 3d83507..78dba01 100644 --- a/vgasrc/clext.h +++ b/vgasrc/clext.h @@ -11,6 +11,9 @@ 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_size_state(int states); +int clext_save_state(u16 seg, void *data, int states); +int clext_restore_state(u16 seg, void *data, int states); int clext_set_mode(struct vgamode_s *vmode_g, int flags); struct bregs; void clext_1012(struct bregs *regs); diff --git a/vgasrc/vbe.c b/vgasrc/vbe.c index 0ee69b4..505cb61 100644 --- a/vgasrc/vbe.c +++ b/vgasrc/vbe.c @@ -201,8 +201,36 @@ vbe_104f03(struct bregs *regs) static void vbe_104f04(struct bregs *regs) { - debug_stub(regs); - regs->ax = 0x0100; + u16 seg = regs->es; + void *data = (void*)(regs->bx+0); + u16 states = regs->cx; + if (states & ~0x0f) + goto fail; + int ret; + switch (regs->dl) { + case 0x00: + ret = vgahw_size_state(states); + if (ret < 0) + goto fail; + regs->bx = ret / 64; + break; + case 0x01: + ret = vgahw_save_state(seg, data, states); + if (ret) + goto fail; + break; + case 0x02: + ret = vgahw_restore_state(seg, data, states); + if (ret) + goto fail; + break; + default: + goto fail; + } + regs->ax = 0x004f; + return; +fail: + regs->ax = 0x014f; }
void VISIBLE16 diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c index ea78c45..7b6c50a 100644 --- a/vgasrc/vgabios.c +++ b/vgasrc/vgabios.c @@ -307,7 +307,7 @@ write_string(struct cursorpos *pcp, u8 attr, u16 count, u16 seg, u8 *offset_far) void save_bda_state(u16 seg, struct saveBDAstate *info) { - SET_FARVAR(seg, info->video_mode, GET_BDA(video_mode)); + SET_FARVAR(seg, info->video_mode, GET_BDA(vbe_mode)); SET_FARVAR(seg, info->video_cols, GET_BDA(video_cols)); SET_FARVAR(seg, info->video_pagesize, GET_BDA(video_pagesize)); SET_FARVAR(seg, info->crtc_address, GET_BDA(crtc_address)); @@ -331,8 +331,11 @@ void restore_bda_state(u16 seg, struct saveBDAstate *info) { u16 mode = GET_FARVAR(seg, info->video_mode); - SET_BDA(video_mode, mode); SET_BDA(vbe_mode, mode); + if (mode < 0x100) + SET_BDA(video_mode, mode); + else + SET_BDA(video_mode, 0xff); 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)); @@ -1140,18 +1143,18 @@ handle_101c(struct bregs *regs) int ret; switch (regs->al) { case 0x00: - ret = stdvga_size_state(states); + ret = vgahw_size_state(states); if (ret < 0) goto fail; regs->bx = ret / 64; break; case 0x01: - ret = stdvga_save_state(seg, data, states); + ret = vgahw_save_state(seg, data, states); if (ret) goto fail; break; case 0x02: - ret = stdvga_restore_state(seg, data, states); + ret = vgahw_restore_state(seg, data, states); if (ret) goto fail; break; diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h index 76ecb88..d32e1b0 100644 --- a/vgasrc/vgabios.h +++ b/vgasrc/vgabios.h @@ -20,7 +20,7 @@ struct VideoParam_s { extern struct VideoParam_s video_param_table[29];
struct saveBDAstate { - u8 video_mode; + u16 video_mode; u16 video_cols; u16 video_pagesize; u16 crtc_address; diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h index 585ae3d..044cd32 100644 --- a/vgasrc/vgahw.h +++ b/vgasrc/vgahw.h @@ -105,4 +105,28 @@ static inline int vgahw_set_dacformat(struct vgamode_s *vmode_g, int val) { return stdvga_set_dacformat(vmode_g, val); }
+static inline int vgahw_size_state(int states) { + if (CONFIG_VGA_CIRRUS) + return clext_size_state(states); + if (CONFIG_VGA_BOCHS) + return bochsvga_size_state(states); + return stdvga_size_state(states); +} + +static inline int vgahw_save_state(u16 seg, void *data, int states) { + if (CONFIG_VGA_CIRRUS) + return clext_save_state(seg, data, states); + if (CONFIG_VGA_BOCHS) + return bochsvga_save_state(seg, data, states); + return stdvga_save_state(seg, data, states); +} + +static inline int vgahw_restore_state(u16 seg, void *data, int states) { + if (CONFIG_VGA_CIRRUS) + return clext_restore_state(seg, data, states); + if (CONFIG_VGA_BOCHS) + return bochsvga_restore_state(seg, data, states); + return stdvga_restore_state(seg, data, states); +} + #endif // vgahw.h