aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Evans <bde@FreeBSD.org>2017-04-20 13:46:55 +0000
committerBruce Evans <bde@FreeBSD.org>2017-04-20 13:46:55 +0000
commitecb56aaf6099f5336b8816cbc1ad21ae55c8a101 (patch)
tree806556af21606181ba52b6959f6a1629fc351b5b
parent05d06ecac32d892eafc5e8e13652324d8f5ac46a (diff)
downloadsrc-ecb56aaf6099f5336b8816cbc1ad21ae55c8a101.tar.gz
src-ecb56aaf6099f5336b8816cbc1ad21ae55c8a101.zip
Attempt to determine the modes in which 8-bit wide characters are actually
9 wide. I only need this to improve the mouse cursor, but it has always been needed to select and/or adjust fonts. This is complicated because there are no standard parameter tables giving this bit of information directly, and the device register bit giving the information can't be trusted even if it is read from the hardware. Use a heuristic to guess if the device register can be trusted. (The device register is normally read from the BIOS mode table, but on my system where the device register is wrong, the mode table doesn't match the hardware and is not used; the device registers are used in this case.)
Notes
Notes: svn path=/head/; revision=317190
-rw-r--r--sys/dev/fb/vesa.c1
-rw-r--r--sys/dev/fb/vga.c26
-rw-r--r--sys/sys/fbio.h2
3 files changed, 29 insertions, 0 deletions
diff --git a/sys/dev/fb/vesa.c b/sys/dev/fb/vesa.c
index 0698220de78b..d51e560c7f84 100644
--- a/sys/dev/fb/vesa.c
+++ b/sys/dev/fb/vesa.c
@@ -1359,6 +1359,7 @@ vesa_set_mode(video_adapter_t *adp, int mode)
vesa_adp->va_crtc_addr =
(vesa_adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC;
+ vesa_adp->va_flags &= ~V_ADP_CWIDTH9;
vesa_adp->va_line_width = info.vi_buffer_size / info.vi_height;
if ((info.vi_flags & V_INFO_GRAPHICS) != 0)
vesa_adp->va_line_width /= info.vi_planes;
diff --git a/sys/dev/fb/vga.c b/sys/dev/fb/vga.c
index f9ef2abf3935..286202d72d0b 100644
--- a/sys/dev/fb/vga.c
+++ b/sys/dev/fb/vga.c
@@ -862,6 +862,9 @@ update_adapter_info(video_adapter_t *adp, video_info_t *info)
/* XXX */
adp->va_buffer = info->vi_buffer;
adp->va_buffer_size = info->vi_buffer_size;
+ adp->va_flags &= ~V_ADP_CWIDTH9;
+ if (info->vi_flags & V_INFO_CWIDTH9)
+ adp->va_flags |= V_ADP_CWIDTH9;
if (info->vi_mem_model == V_INFO_MM_VGAX) {
adp->va_line_width = info->vi_width/2;
} else if (info->vi_flags & V_INFO_GRAPHICS) {
@@ -1221,6 +1224,29 @@ probe_adapters(void)
}
}
+#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
+ /*
+ * Attempt to determine the real character width for each mode. 9 wide
+ * is supposed to be standard for EGA mono mode and most VGA text modes,
+ * but some hardware doesn't support it, so dynamic configuration is
+ * needed. Bit 0 in sequencer register 1 is supposed control the width
+ * (set = 8), but this is unreliable too. Trust that 0 in the sequencer
+ * bit means 9 wide after verifying that 9 is consistent with some CRTC
+ * timing. The ratio (Horizontal Total) / (Horizontal Displayed) is
+ * about 1.2 in all standard 9-wide modes and should be about 9/8 larger
+ * again in similar 8-wide modes; in practice it is usually about 1.4
+ * times larger.
+ */
+ for (i = 0; i < nitems(bios_vmode); ++i) {
+ if (bios_vmode[i].vi_mem_model == V_INFO_MM_TEXT &&
+ bios_vmode[i].vi_width != 90) {
+ mp = get_mode_param(map_mode_num(bios_vmode[i].vi_mode));
+ if (mp != NULL && !(mp[5] & 1) && mp[10] <= mp[11] * 125 / 100)
+ bios_vmode[i].vi_flags |= V_INFO_CWIDTH9;
+ }
+ }
+#endif
+
/* buffer address */
vga_get_info(&biosadapter[V_ADP_PRIMARY],
biosadapter[V_ADP_PRIMARY].va_initial_mode, &info);
diff --git a/sys/sys/fbio.h b/sys/sys/fbio.h
index 0d16402cb077..4aea3c37ab7d 100644
--- a/sys/sys/fbio.h
+++ b/sys/sys/fbio.h
@@ -338,6 +338,7 @@ struct video_info {
#define V_INFO_LINEAR (1 << 2)
#define V_INFO_VESA (1 << 3)
#define V_INFO_NONVGA (1 << 4)
+#define V_INFO_CWIDTH9 (1 << 5)
int vi_width;
int vi_height;
int vi_cwidth;
@@ -400,6 +401,7 @@ struct video_adapter {
#define V_ADP_REGISTERED (1 << 18)
#define V_ADP_ATTACHED (1 << 19)
#define V_ADP_DAC8 (1 << 20)
+#define V_ADP_CWIDTH9 (1 << 21)
vm_offset_t va_io_base;
int va_io_size;
vm_offset_t va_crtc_addr;