Signed-off-by: Kevin O'Connor kevin@koconnor.net --- Makefile | 2 +- vgasrc/swcursor.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ vgasrc/vgabios.h | 2 ++ vgasrc/vgafb.c | 57 ------------------------------------------------ 4 files changed, 68 insertions(+), 58 deletions(-) create mode 100644 vgasrc/swcursor.c
diff --git a/Makefile b/Makefile index 4930b3a..41bfcf4 100644 --- a/Makefile +++ b/Makefile @@ -207,7 +207,7 @@ $(OUT)bios.bin.elf: $(OUT)rom.o $(OUT)bios.bin.prep
# VGA src files SRCVGA=src/output.c src/string.c src/hw/pci.c src/hw/serialio.c \ - vgasrc/vgainit.c vgasrc/vgabios.c vgasrc/vgafb.c \ + vgasrc/vgainit.c vgasrc/vgabios.c vgasrc/vgafb.c vgasrc/swcursor.c \ vgasrc/vgafonts.c vgasrc/vbe.c \ vgasrc/stdvga.c vgasrc/stdvgamodes.c vgasrc/stdvgaio.c \ vgasrc/clext.c vgasrc/bochsvga.c vgasrc/geodevga.c \ diff --git a/vgasrc/swcursor.c b/vgasrc/swcursor.c new file mode 100644 index 0000000..35f857a --- /dev/null +++ b/vgasrc/swcursor.c @@ -0,0 +1,65 @@ +// Virtual software based cursor support +// +// Copyright (C) 2014-2016 Kevin O'Connor kevin@koconnor.net +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_BDA +#include "vgabios.h" // handle_gfx_op + +// Draw/undraw a cursor on the framebuffer by xor'ing the cursor cell +static void +gfx_set_swcursor(struct vgamode_s *vmode_g, int enable, struct cursorpos cp) +{ + u16 cursor_type = get_cursor_shape(); + u8 start = cursor_type >> 8, end = cursor_type & 0xff; + struct gfx_op op; + init_gfx_op(&op, vmode_g); + op.x = cp.x * 8; + int cheight = GET_BDA(char_height); + op.y = cp.y * cheight + start; + + int i; + for (i = start; i < cheight && i <= end; i++, op.y++) { + op.op = GO_READ8; + handle_gfx_op(&op); + int j; + for (j = 0; j < 8; j++) + op.pixels[j] ^= 0x07; + op.op = GO_WRITE8; + handle_gfx_op(&op); + } +} + +// Draw/undraw a cursor on the screen +void +vgafb_set_swcursor(int enable) +{ + if (!vga_emulate_text()) + return; + u8 flags = GET_BDA_EXT(flags); + if (!!(flags & BF_SWCURSOR) == enable) + // Already in requested mode. + return; + struct vgamode_s *vmode_g = get_current_mode(); + if (!vmode_g) + return; + struct cursorpos cp = get_cursor_pos(GET_BDA(video_page)); + if (cp.x >= GET_BDA(video_cols) || cp.y > GET_BDA(video_rows) + || GET_BDA(cursor_type) >= 0x2000) + // Cursor not visible + return; + + SET_BDA_EXT(flags, (flags & ~BF_SWCURSOR) | (enable ? BF_SWCURSOR : 0)); + + if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) { + gfx_set_swcursor(vmode_g, enable, cp); + return; + } + + // In text mode, swap foreground and background attributes for cursor + void *dest_far = text_address(cp) + 1; + u8 attr = GET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)dest_far); + attr = (attr >> 4) | (attr << 4); + SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)dest_far, attr); +} diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h index 9fbfb14..9764020 100644 --- a/vgasrc/vgabios.h +++ b/vgasrc/vgabios.h @@ -132,6 +132,8 @@ void vgafb_write_char(struct cursorpos cp, struct carattr ca); struct carattr vgafb_read_char(struct cursorpos cp); void vgafb_write_pixel(u8 color, u16 x, u16 y); u8 vgafb_read_pixel(u16 x, u16 y); + +// swcursor.c void vgafb_set_swcursor(int enable);
// vbe.c diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c index bd1c8dd..46a1ab8 100644 --- a/vgasrc/vgafb.c +++ b/vgasrc/vgafb.c @@ -497,30 +497,6 @@ fail: return (struct carattr){0, 0, 0}; }
-// Draw/undraw a cursor on the framebuffer by xor'ing the cursor cell -void -gfx_set_swcursor(struct vgamode_s *vmode_g, int enable, struct cursorpos cp) -{ - u16 cursor_type = get_cursor_shape(); - u8 start = cursor_type >> 8, end = cursor_type & 0xff; - struct gfx_op op; - init_gfx_op(&op, vmode_g); - op.x = cp.x * 8; - int cheight = GET_BDA(char_height); - op.y = cp.y * cheight + start; - - int i; - for (i = start; i < cheight && i <= end; i++, op.y++) { - op.op = GO_READ8; - handle_gfx_op(&op); - int j; - for (j = 0; j < 8; j++) - op.pixels[j] ^= 0x07; - op.op = GO_WRITE8; - handle_gfx_op(&op); - } -} - // Set the pixel at the given position. void vgafb_write_pixel(u8 color, u16 x, u16 y) @@ -686,36 +662,3 @@ vgafb_read_char(struct cursorpos cp) u16 v = GET_FARVAR(GET_GLOBAL(vmode_g->sstart), *dest_far); return (struct carattr){v, v>>8, 0}; } - -// Draw/undraw a cursor on the screen -void -vgafb_set_swcursor(int enable) -{ - if (!vga_emulate_text()) - return; - u8 flags = GET_BDA_EXT(flags); - if (!!(flags & BF_SWCURSOR) == enable) - // Already in requested mode. - return; - struct vgamode_s *vmode_g = get_current_mode(); - if (!vmode_g) - return; - struct cursorpos cp = get_cursor_pos(GET_BDA(video_page)); - if (cp.x >= GET_BDA(video_cols) || cp.y > GET_BDA(video_rows) - || GET_BDA(cursor_type) >= 0x2000) - // Cursor not visible - return; - - SET_BDA_EXT(flags, (flags & ~BF_SWCURSOR) | (enable ? BF_SWCURSOR : 0)); - - if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) { - gfx_set_swcursor(vmode_g, enable, cp); - return; - } - - // In text mode, swap foreground and background attributes for cursor - void *dest_far = text_address(cp) + 1; - u8 attr = GET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)dest_far); - attr = (attr >> 4) | (attr << 4); - SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)dest_far, attr); -}
The software cursor code is not frequently used (only the coreboot framebuffer vga code uses it). Move its logic out of the main code and into swcursor.c.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/swcursor.c | 37 +++++++++++++++++++++++++++++++++---- vgasrc/vgabios.c | 8 ++------ vgasrc/vgabios.h | 5 +++-- vgasrc/vgafb.c | 5 ----- vgasrc/vgainit.c | 4 +--- 5 files changed, 39 insertions(+), 20 deletions(-)
diff --git a/vgasrc/swcursor.c b/vgasrc/swcursor.c index 35f857a..83f4822 100644 --- a/vgasrc/swcursor.c +++ b/vgasrc/swcursor.c @@ -5,6 +5,7 @@ // This file may be distributed under the terms of the GNU LGPLv3 license.
#include "biosvar.h" // GET_BDA +#include "bregs.h" // struct bregs #include "vgabios.h" // handle_gfx_op
// Draw/undraw a cursor on the framebuffer by xor'ing the cursor cell @@ -32,11 +33,9 @@ gfx_set_swcursor(struct vgamode_s *vmode_g, int enable, struct cursorpos cp) }
// Draw/undraw a cursor on the screen -void -vgafb_set_swcursor(int enable) +static void +set_swcursor(int enable) { - if (!vga_emulate_text()) - return; u8 flags = GET_BDA_EXT(flags); if (!!(flags & BF_SWCURSOR) == enable) // Already in requested mode. @@ -63,3 +62,33 @@ vgafb_set_swcursor(int enable) attr = (attr >> 4) | (attr << 4); SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)dest_far, attr); } + +// Disable virtual cursor if a vgabios call accesses the framebuffer +void +swcursor_pre_handle10(struct bregs *regs) +{ + if (!vga_emulate_text()) + return; + switch (regs->ah) { + case 0x4f: + if (!CONFIG_VGA_VBE || regs->al != 0x02) + break; + // NO BREAK + case 0x00 ... 0x02: + case 0x05 ... 0x0e: + case 0x13: + set_swcursor(0); + break; + default: + break; + } +} + +// Called by periodic (18.2hz) timer +void +swcursor_check_event(void) +{ + if (!vga_emulate_text()) + return; + set_swcursor(GET_BDA(timer_counter) % 18 < 9); +} diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c index 2c8cc79..4e897c4 100644 --- a/vgasrc/vgabios.c +++ b/vgasrc/vgabios.c @@ -74,7 +74,6 @@ get_cursor_shape(void) static void set_cursor_shape(u16 cursor_type) { - vgafb_set_swcursor(0); SET_BDA(cursor_type, cursor_type); if (CONFIG_VGA_STDVGA_PORTS) stdvga_set_cursor_shape(get_cursor_shape()); @@ -89,7 +88,6 @@ set_cursor_pos(struct cursorpos cp)
if (cp.page == GET_BDA(video_page)) { // Update cursor in hardware - vgafb_set_swcursor(0); if (CONFIG_VGA_STDVGA_PORTS) stdvga_set_cursor_pos((int)text_address(cp)); } @@ -118,8 +116,6 @@ set_active_page(u8 page) if (!vmode_g) return;
- vgafb_set_swcursor(0); - // Calculate memory address of start of page struct cursorpos cp = {0, 0, page}; int address = (int)text_address(cp); @@ -268,8 +264,6 @@ vga_set_mode(int mode, int flags) if (!vmode_g) return VBE_RETURN_STATUS_FAILED;
- vgafb_set_swcursor(0); - int ret = vgahw_set_mode(vmode_g, flags); if (ret) return ret; @@ -1103,6 +1097,8 @@ void VISIBLE16 handle_10(struct bregs *regs) { debug_enter(regs, DEBUG_VGA_10); + swcursor_pre_handle10(regs); + switch (regs->ah) { case 0x00: handle_1000(regs); break; case 0x01: handle_1001(regs); break; diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h index 9764020..ffbb729 100644 --- a/vgasrc/vgabios.h +++ b/vgasrc/vgabios.h @@ -134,7 +134,9 @@ void vgafb_write_pixel(u8 color, u16 x, u16 y); u8 vgafb_read_pixel(u16 x, u16 y);
// swcursor.c -void vgafb_set_swcursor(int enable); +struct bregs; +void swcursor_pre_handle10(struct bregs *regs); +void swcursor_check_event(void);
// vbe.c extern u32 VBE_total_memory; @@ -145,7 +147,6 @@ extern u16 VBE_win_granularity; #define VBE_VENDOR_STRING "SeaBIOS Developers" #define VBE_PRODUCT_STRING "SeaBIOS VBE Adapter" #define VBE_REVISION_STRING "Rev. 1" -struct bregs; void handle_104f(struct bregs *regs);
#endif // vgabios.h diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c index 46a1ab8..57ecc9b 100644 --- a/vgasrc/vgafb.c +++ b/vgasrc/vgafb.c @@ -504,7 +504,6 @@ vgafb_write_pixel(u8 color, u16 x, u16 y) struct vgamode_s *vmode_g = get_current_mode(); if (!vmode_g) return; - vgafb_set_swcursor(0);
struct gfx_op op; init_gfx_op(&op, vmode_g); @@ -529,7 +528,6 @@ vgafb_read_pixel(u16 x, u16 y) struct vgamode_s *vmode_g = get_current_mode(); if (!vmode_g) return 0; - vgafb_set_swcursor(0);
struct gfx_op op; init_gfx_op(&op, vmode_g); @@ -599,7 +597,6 @@ void vgafb_scroll(struct cursorpos win, struct cursorpos winsize , int lines, struct carattr ca) { - vgafb_set_swcursor(0); if (!lines) { // Clear window vgafb_clear_chars(win, winsize, ca); @@ -630,7 +627,6 @@ vgafb_write_char(struct cursorpos cp, struct carattr ca) struct vgamode_s *vmode_g = get_current_mode(); if (!vmode_g) return; - vgafb_set_swcursor(0);
if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) { gfx_write_char(vmode_g, cp, ca); @@ -653,7 +649,6 @@ vgafb_read_char(struct cursorpos cp) struct vgamode_s *vmode_g = get_current_mode(); if (!vmode_g) return (struct carattr){0, 0, 0}; - vgafb_set_swcursor(0);
if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) return gfx_read_char(vmode_g, cp); diff --git a/vgasrc/vgainit.c b/vgasrc/vgainit.c index 40997db..6249e66 100644 --- a/vgasrc/vgainit.c +++ b/vgasrc/vgainit.c @@ -96,9 +96,7 @@ struct segoff_s Timer_Hook_Resume VAR16 VISIBLE16; void VISIBLE16 handle_timer_hook(void) { - if (!vga_emulate_text()) - return; - vgafb_set_swcursor(GET_BDA(timer_counter) % 18 < 9); + swcursor_check_event(); }
static void