The "cursor scaling" mode is determined by the first bit of the video_ctl bda value, not the modeset_ctl value. Also, on a set_scan_lines() call, the shape should be set to lines-3/lines-2 and the shape must be set after char_height has been updated.
The existing cursor shape code matches the legacy "lgpl vgabios", but the behavior doesn't match bios documentation nor observations with an ati vga bios.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/vgabios.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c index 8ec6aa6..47bf581 100644 --- a/vgasrc/vgabios.c +++ b/vgasrc/vgabios.c @@ -62,9 +62,9 @@ set_cursor_shape(u8 start, u8 end) if (!CONFIG_VGA_STDVGA_PORTS) return;
- u8 modeset_ctl = GET_BDA(modeset_ctl); + u8 emulate_cursor = (GET_BDA(video_ctl) & 1) == 0; u16 cheight = GET_BDA(char_height); - if ((modeset_ctl & 0x01) && (cheight > 8) && (end < 8) && (start < 0x20)) { + if (emulate_cursor && (cheight > 8) && (end < 8) && (start < 0x20)) { if (end != (start + 1)) start = ((start + 1) * cheight / 8) - 1; else @@ -79,7 +79,6 @@ get_cursor_shape(u8 page) { if (page > 7) return 0; - // FIXME should handle VGA 14/16 lines return GET_BDA(cursor_type); }
@@ -117,7 +116,6 @@ get_cursor_pos(u8 page) struct cursorpos cp = { 0, 0, 0xfe }; return cp; } - // FIXME should handle VGA 14/16 lines u16 xy = GET_BDA(cursor_pos[page]); struct cursorpos cp = {xy, xy>>8, page}; return cp; @@ -153,16 +151,16 @@ static void set_scan_lines(u8 lines) { stdvga_set_scan_lines(lines); - if (lines == 8) - set_cursor_shape(0x06, 0x07); - else - set_cursor_shape(lines - 4, lines - 3); SET_BDA(char_height, lines); u16 vde = stdvga_get_vde(); u8 rows = vde / lines; SET_BDA(video_rows, rows - 1); u16 cols = GET_BDA(video_cols); SET_BDA(video_pagesize, calc_page_size(MM_TEXT, cols, rows)); + if (lines == 8) + set_cursor_shape(0x06, 0x07); + else + set_cursor_shape(lines - 3, lines - 2); }
@@ -981,9 +979,7 @@ handle_101233(struct bregs *regs) static void handle_101234(struct bregs *regs) { - u8 v = (regs->al & 0x01) ^ 0x01; - u8 v2 = GET_BDA(modeset_ctl) & ~0x01; - SET_BDA(modeset_ctl, v | v2); + SET_BDA(video_ctl, (GET_BDA(video_ctl) & ~0x01) | (regs->al & 0x01)); regs->al = 0x12; }
Rework the code so that it is possible to calculate the current cursor shape even when not changing it.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- vgasrc/stdvga.c | 6 +++--- vgasrc/stdvga.h | 2 +- vgasrc/vgabios.c | 53 +++++++++++++++++++++++++---------------------------- 3 files changed, 29 insertions(+), 32 deletions(-)
diff --git a/vgasrc/stdvga.c b/vgasrc/stdvga.c index 70cceed..00a0fc5 100644 --- a/vgasrc/stdvga.c +++ b/vgasrc/stdvga.c @@ -229,11 +229,11 @@ stdvga_vram_ratio(struct vgamode_s *vmode_g) }
void -stdvga_set_cursor_shape(u8 start, u8 end) +stdvga_set_cursor_shape(u16 cursor_type) { u16 crtc_addr = stdvga_get_crtc(); - stdvga_crtc_write(crtc_addr, 0x0a, start); - stdvga_crtc_write(crtc_addr, 0x0b, end); + stdvga_crtc_write(crtc_addr, 0x0a, cursor_type >> 8); + stdvga_crtc_write(crtc_addr, 0x0b, cursor_type); }
void diff --git a/vgasrc/stdvga.h b/vgasrc/stdvga.h index df09bab..39753b4 100644 --- a/vgasrc/stdvga.h +++ b/vgasrc/stdvga.h @@ -92,7 +92,7 @@ void stdvga_load_font(u16 seg, void *src_far, u16 count , u16 start, u8 destflags, u8 fontsize); u16 stdvga_get_crtc(void); int stdvga_vram_ratio(struct vgamode_s *vmode_g); -void stdvga_set_cursor_shape(u8 start, u8 end); +void stdvga_set_cursor_shape(u16 cursor_type); void stdvga_set_cursor_pos(int address); void stdvga_set_scan_lines(u8 lines); u16 stdvga_get_vde(void); diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c index 47bf581..786c009 100644 --- a/vgasrc/vgabios.c +++ b/vgasrc/vgabios.c @@ -50,36 +50,33 @@ calc_page_size(u8 memmodel, u16 width, u16 height) } }
-static void -set_cursor_shape(u8 start, u8 end) +// Determine cursor shape (taking into account possible cursor scaling) +static u16 +get_cursor_shape(void) { - start &= 0x3f; - end &= 0x1f; - - u16 curs = (start << 8) + end; - SET_BDA(cursor_type, curs); - - if (!CONFIG_VGA_STDVGA_PORTS) - return; - + u16 cursor_type = GET_BDA(cursor_type); u8 emulate_cursor = (GET_BDA(video_ctl) & 1) == 0; + if (!emulate_cursor) + return cursor_type; + u8 start = (cursor_type >> 8) & 0x3f; + u8 end = cursor_type & 0x1f; u16 cheight = GET_BDA(char_height); - if (emulate_cursor && (cheight > 8) && (end < 8) && (start < 0x20)) { - if (end != (start + 1)) - start = ((start + 1) * cheight / 8) - 1; - else - start = ((end + 1) * cheight / 8) - 2; - end = ((end + 1) * cheight / 8) - 1; - } - stdvga_set_cursor_shape(start, end); + if (cheight <= 8 || end >= 8 || start >= 0x20) + return cursor_type; + if (end != (start + 1)) + start = ((start + 1) * cheight / 8) - 1; + else + start = ((end + 1) * cheight / 8) - 2; + end = ((end + 1) * cheight / 8) - 1; + return (start << 8) | end; }
-static u16 -get_cursor_shape(u8 page) +static void +set_cursor_shape(u16 cursor_type) { - if (page > 7) - return 0; - return GET_BDA(cursor_type); + SET_BDA(cursor_type, cursor_type); + if (CONFIG_VGA_STDVGA_PORTS) + stdvga_set_cursor_shape(get_cursor_shape()); }
static void @@ -158,9 +155,9 @@ set_scan_lines(u8 lines) u16 cols = GET_BDA(video_cols); SET_BDA(video_pagesize, calc_page_size(MM_TEXT, cols, rows)); if (lines == 8) - set_cursor_shape(0x06, 0x07); + set_cursor_shape(0x0607); else - set_cursor_shape(lines - 3, lines - 2); + set_cursor_shape(((lines - 3) << 8) | (lines - 2)); }
@@ -377,7 +374,7 @@ handle_1000(struct bregs *regs) static void handle_1001(struct bregs *regs) { - set_cursor_shape(regs->ch, regs->cl); + set_cursor_shape(regs->cx); }
static void @@ -390,7 +387,7 @@ handle_1002(struct bregs *regs) static void handle_1003(struct bregs *regs) { - regs->cx = get_cursor_shape(regs->bh); + regs->cx = GET_BDA(cursor_type); struct cursorpos cp = get_cursor_pos(regs->bh); regs->dl = cp.x; regs->dh = cp.y;