From d61fc53a6037125183bec6ca4f3976d2396486be Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Fri, 27 Jan 2012 20:37:45 -0500 Subject: [PATCH] vgabios: Add support for VBE get/set display start function. Signed-off-by: Kevin O'Connor --- 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 2a4b0d5..384e2cb 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 @@ -253,14 +253,6 @@ stdvga_set_cursor_shape(u8 start, u8 end) stdvga_crtc_write(crtc_addr, 0x0b, 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) { @@ -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 d000166..25d9729 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 -- 2.25.1