From a536b595b254fedb7ae7aa2e57347b3ef58f2524 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Mon, 5 Sep 2016 02:30:49 +0200
Subject: [PATCH 2/7] kernel/vga: Improve readability of CRTC register
 handling.

Add various definitions and inline helper functions for a better
understanding of what's going on. Of course, some VGA knowledge
will still be a benefit when reading the code.

Also add a helper function to reset the internal address flip-flop
(by reading input status register 1).
---
 sys/dev/misc/syscons/scvgarndr.c  |   2 +-
 sys/dev/video/fb/bmp/splash_bmp.c |   4 +-
 sys/dev/video/fb/vga.c            | 109 +++++++++++-------------------
 sys/dev/video/fb/vgareg.h         |  57 +++++++++++++++-
 4 files changed, 98 insertions(+), 74 deletions(-)

diff --git a/sys/dev/misc/syscons/scvgarndr.c b/sys/dev/misc/syscons/scvgarndr.c
index c4614619a8..f6dfa316a9 100644
--- a/sys/dev/misc/syscons/scvgarndr.c
+++ b/sys/dev/misc/syscons/scvgarndr.c
@@ -373,7 +373,7 @@ draw_txtmouse(scr_stat *scp, int x, int y)
 #if 1
 	/* wait for vertical retrace to avoid jitter on some videocards */
 	while (!sc_txtmouse_no_retrace_wait &&
-	    !(inb(CRTC + 6) & 0x08))
+	    !(inb(GEN_INPSTAT1) & 0x08))
 		/* idle */ ;
 #endif
 	c = scp->sc->mouse_char;
diff --git a/sys/dev/video/fb/bmp/splash_bmp.c b/sys/dev/video/fb/bmp/splash_bmp.c
index 7b8ac83dc8..afe9fd6021 100644
--- a/sys/dev/video/fb/bmp/splash_bmp.c
+++ b/sys/dev/video/fb/bmp/splash_bmp.c
@@ -590,14 +590,14 @@ bmp_Draw(video_adapter_t *adp)
 #if 0
     /* XXX: this is ugly, but necessary for EGA/VGA 1bpp/4bpp modes */
     if ((adp->va_type == KD_EGA) || (adp->va_type == KD_VGA)) {
-	inb(adp->va_crtc_addr + 6);		/* reset flip-flop */
+	vga_reset_flipflop();
 	outb(ATC, 0x14);
 	outb(ATC, 0);
 	for (i = 0; i < 16; ++i) {
 	    outb(ATC, i);
 	    outb(ATC, i);
 	}
-	inb(adp->va_crtc_addr + 6);		/* reset flip-flop */
+	vga_reset_flipflop();
 	outb(ATC, 0x20);			/* enable palette */
 
 	outw(GDCIDX, 0x0f01);			/* set/reset enable */
diff --git a/sys/dev/video/fb/vga.c b/sys/dev/video/fb/vga.c
index 53f5ab8999..9d76495a33 100644
--- a/sys/dev/video/fb/vga.c
+++ b/sys/dev/video/fb/vga.c
@@ -46,8 +46,6 @@
 #include <sys/fbio.h>
 #include <sys/thread2.h>
 
-#include <bus/isa/isareg.h>
-
 #include <machine/clock.h>
 #include <machine/md_var.h>
 #include <machine/framebuffer.h>
@@ -553,8 +551,8 @@ verify_adapter(video_adapter_t *adp)
 		return ENXIO;
 	writew(buf, v);
 
-	outb(CRTC, 7);
-	if (inb(CRTC) != 7)
+	outb(CRTC, OVERFLOW);
+	if (inb(CRTC) != OVERFLOW)
 		return ENXIO;
 
 	adp->va_flags |= V_ADP_STATELOAD | V_ADP_STATESAVE | V_ADP_PALETTE |
@@ -644,10 +642,8 @@ probe_adapters(void)
 	 * memory.
 	 * This must be done before vga_save_state() for VGA.
 	 */
-	outb(CRTC, 12);
-	outb(CRTC + 1, 0);
-	outb(CRTC, 13);
-	outb(CRTC + 1, 0);
+	vga_crtc_set(START_ADDRESS_HIGH, 0);
+	vga_crtc_set(START_ADDRESS_LOW, 0);
 
 	/*
 	 * the video mode parameter table in VGA BIOS
@@ -749,8 +745,7 @@ set_line_length(video_adapter_t *adp, int pixel)
 
 	if (mp[10 + 0x17] & 0x40)		/* CRTC mode control reg */
 		count *= 2;			/* byte mode */
-	outb(CRTC, 0x13);
-	outb(CRTC + 1, count);
+	vga_crtc_set(OFFSET, count);
 	adp->va_line_width = bpl;
 
 	return 0;
@@ -784,22 +779,17 @@ set_display_start(video_adapter_t *adp, int x, int y)
 			poff = (x + 8)%ppb;
 	}
 
-	/* start address */
-	outb(CRTC, 0xc);		/* high */
-	outb(CRTC + 1, off >> 8);
-	outb(CRTC, 0xd);		/* low */
-	outb(CRTC + 1, off & 0xff);
+	vga_crtc_set(START_ADDRESS_HIGH, off >> 8);
+	vga_crtc_set(START_ADDRESS_LOW, off & 0xff);
 
 	/* horizontal pel pan */
-	inb(CRTC + 6);
+	vga_reset_flipflop();
 	outb(ATC, 0x13 | 0x20);
 	outb(ATC, poff);
-	inb(CRTC + 6);
+	vga_reset_flipflop();
 	outb(ATC, 0x20);
 
-	/* preset row scan */
-	outb(CRTC, 8);
-	outb(CRTC + 1, roff);
+	vga_crtc_set(PRESET_ROW_SCAN, roff);
 
 	adp->va_disp_start.x = x;
 	adp->va_disp_start.y = y;
@@ -1146,13 +1136,13 @@ set_font_mode(video_adapter_t *adp, u_char *buf)
 	outb(GDCIDX, 0x04); buf[2] = inb(GDCREG);
 	outb(GDCIDX, 0x05); buf[3] = inb(GDCREG);
 	outb(GDCIDX, 0x06); buf[4] = inb(GDCREG);
-	inb(CRTC + 6);
+	vga_reset_flipflop();
 	outb(ATC, 0x10); buf[5] = inb(ATC + 1);
 
 	/* setup vga for loading fonts */
-	inb(CRTC + 6);				/* reset flip-flop */
+	vga_reset_flipflop();
 	outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01);
-	inb(CRTC + 6);				/* reset flip-flop */
+	vga_reset_flipflop();
 	outb(ATC, 0x20);			/* enable palette */
 	outw(TSIDX, 0x0402);
 	outw(TSIDX, 0x0704);
@@ -1169,9 +1159,9 @@ set_normal_mode(video_adapter_t *adp, u_char *buf)
 	crit_enter();
 
 	/* setup vga for normal operation mode again */
-	inb(CRTC + 6);				/* reset flip-flop */
+	vga_reset_flipflop();
 	outb(ATC, 0x10); outb(ATC, buf[5]);
-	inb(CRTC + 6);				/* reset flip-flop */
+	vga_reset_flipflop();
 	outb(ATC, 0x20);			/* enable palette */
 	outw(TSIDX, 0x0002 | (buf[0] << 8));
 	outw(TSIDX, 0x0004 | (buf[1] << 8));
@@ -1338,7 +1328,7 @@ vga_save_palette(video_adapter_t *adp, u_char *palette)
 	outb(PALRADR, 0x00);
 	for (i = 0; i < 256*3; ++i)
 		palette[i] = inb(PALDATA) << 2;
-	inb(CRTC + 6);		/* reset flip/flop */
+	vga_reset_flipflop();
 	return 0;
 }
 
@@ -1356,7 +1346,7 @@ vga_save_palette2(video_adapter_t *adp, int base, int count,
 		g[i] = inb(PALDATA) << 2;
 		b[i] = inb(PALDATA) << 2;
 	}
-	inb(CRTC + 6);		/* reset flip/flop */
+	vga_reset_flipflop();
 	return 0;
 }
 
@@ -1377,7 +1367,7 @@ vga_load_palette(video_adapter_t *adp, const u_char *palette)
 	outb(PALWADR, 0x00);
 	for (i = 0; i < 256*3; ++i)
 		outb(PALDATA, palette[i] >> 2);
-	inb(CRTC + 6);			/* reset flip/flop */
+	vga_reset_flipflop();
 	outb(ATC, 0x20);		/* enable palette */
 	return 0;
 }
@@ -1397,7 +1387,7 @@ vga_load_palette2(video_adapter_t *adp, int base, int count,
 		outb(PALDATA, g[i] >> 2);
 		outb(PALDATA, b[i] >> 2);
 	}
-	inb(CRTC + 6);			/* reset flip/flop */
+	vga_reset_flipflop();
 	outb(ATC, 0x20);		/* enable palette */
 	return 0;
 }
@@ -1411,7 +1401,7 @@ vga_set_border(video_adapter_t *adp, int color)
 {
 	prologue(adp, V_ADP_BORDER, ENODEV);
 
-	inb(CRTC + 6);	/* reset flip-flop */
+	vga_reset_flipflop();
 	outb(ATC, 0x31); outb(ATC, color & 0xff);
 
 	return 0;
@@ -1428,7 +1418,6 @@ vga_save_state(video_adapter_t *adp, void *p, size_t size)
 {
 	video_info_t info;
 	u_char *buf;
-	int crtc_addr;
 	int i, j;
 
 	if (size == 0) {
@@ -1443,7 +1432,6 @@ vga_save_state(video_adapter_t *adp, void *p, size_t size)
 	((adp_state_t *)p)->sig = V_STATE_SIG;
 	buf = ((adp_state_t *)p)->regs;
 	bzero(buf, V_MODE_PARAM_SIZE);
-	crtc_addr = CRTC;
 
 	crit_enter();
 
@@ -1455,12 +1443,10 @@ vga_save_state(video_adapter_t *adp, void *p, size_t size)
 	buf[9]  =  inb(MISC + 10);		/* dot-clock */
 	outb(TSIDX, 0x00); outb(TSREG, 0x03);	/* start sequencer */
 
-	for (i = 0, j = 10; i < 25; i++) {	/* crtc */
-		outb(crtc_addr, i);
-		buf[j++]  =  inb(crtc_addr + 1);
-	}
+	for (i = HORIZONTAL_TOTAL, j = 10; i <= LINE_COMPARE; i++) /* crtc */
+		buf[j++] = vga_crtc_get(i);
 	for (i = 0, j = 35; i < 20; i++) {	/* attribute ctrl */
-		inb(crtc_addr + 6);		/* reset flip-flop */
+		vga_reset_flipflop();
 		outb(ATC, i);
 		buf[j++]  =  inb(ATC + 1);
 	}
@@ -1468,7 +1454,7 @@ vga_save_state(video_adapter_t *adp, void *p, size_t size)
 		outb(GDCIDX, i);
 		buf[j++]  =  inb(GDCREG);
 	}
-	inb(crtc_addr + 6);			/* reset flip-flop */
+	vga_reset_flipflop();
 	outb(ATC, 0x20);			/* enable palette */
 
 	crit_exit();
@@ -1508,7 +1494,6 @@ static int
 vga_load_state(video_adapter_t *adp, void *p)
 {
 	u_char *buf;
-	int crtc_addr;
 	int i;
 
 	prologue(adp, V_ADP_STATELOAD, ENODEV);
@@ -1516,7 +1501,6 @@ vga_load_state(video_adapter_t *adp, void *p)
 		return EINVAL;
 
 	buf = ((adp_state_t *)p)->regs;
-	crtc_addr = CRTC;
 
 #if VGA_DEBUG > 1
 	hexdump(buf, V_MODE_PARAM_SIZE, NULL, HD_OMIT_CHARS | HD_OMIT_COUNT);
@@ -1531,13 +1515,10 @@ vga_load_state(video_adapter_t *adp, void *p)
 	}
 	outb(MISC, buf[9]);			/* set dot-clock */
 	outb(TSIDX, 0x00); outb(TSREG, 0x03);	/* start sequencer */
-	outb(crtc_addr, 0x11);
-	outb(crtc_addr + 1, inb(crtc_addr + 1) & 0x7F);
-	for (i = 0; i < 25; ++i) {		/* program crtc */
-		outb(crtc_addr, i);
-		outb(crtc_addr + 1, buf[i + 10]);
-	}
-	inb(crtc_addr+6);			/* reset flip-flop */
+	vga_crtc_and(CURSOR_END, 0x7f);
+	for (i = HORIZONTAL_TOTAL; i <= LINE_COMPARE; ++i) /* program crtc */
+		vga_crtc_set(i, buf[i + 10]);
+	vga_reset_flipflop();
 	for (i = 0; i < 20; ++i) {		/* program attribute ctrl */
 		outb(ATC, i);
 		outb(ATC, buf[i + 35]);
@@ -1546,7 +1527,7 @@ vga_load_state(video_adapter_t *adp, void *p)
 		outb(GDCIDX, i);
 		outb(GDCREG, buf[i + 55]);
 	}
-	inb(crtc_addr + 6);			/* reset flip-flop */
+	vga_reset_flipflop();
 	outb(ATC, 0x20);			/* enable palette */
 
 #if 0 /* XXX a temporary workaround for kernel panic */
@@ -1597,10 +1578,8 @@ vga_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
 		return ENODEV;
 
 	crit_enter();
-	outb(CRTC, 14);
-	off = inb(CRTC + 1);
-	outb(CRTC, 15);
-	off = (off << 8) | inb(CRTC + 1);
+	off = vga_crtc_get(CURSOR_LOCATION_HIGH) << 8 |
+	    vga_crtc_get(CURSOR_LOCATION_LOW);
 	crit_exit();
 
 	*row = off / adp->va_info.vi_width;
@@ -1631,10 +1610,8 @@ vga_set_hw_cursor(video_adapter_t *adp, int col, int row)
 	}
 
 	crit_enter();
-	outb(CRTC, 14);
-	outb(CRTC + 1, off >> 8);
-	outb(CRTC, 15);
-	outb(CRTC + 1, off & 0x00ff);
+	vga_crtc_set(CURSOR_LOCATION_HIGH, off >> 8);
+	vga_crtc_set(CURSOR_LOCATION_LOW, off & 0xff);
 	crit_exit();
 
 	return 0;
@@ -1655,15 +1632,11 @@ vga_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
 	crit_enter();
 	if (height <= 0) {
 		/* make the cursor invisible */
-		outb(CRTC, 10);
-		outb(CRTC + 1, 32);
-		outb(CRTC, 11);
-		outb(CRTC + 1, 0);
+		vga_crtc_set(CURSOR_START, 32);
+		vga_crtc_set(CURSOR_END, 0);
 	} else {
-		outb(CRTC, 10);
-		outb(CRTC + 1, celsize - base - height);
-		outb(CRTC, 11);
-		outb(CRTC + 1, celsize - base - 1);
+		vga_crtc_set(CURSOR_START, celsize - base - height);
+		vga_crtc_set(CURSOR_END, celsize - base - 1);
 	}
 	crit_exit();
 
@@ -1687,9 +1660,7 @@ vga_blank_display(video_adapter_t *adp, int mode)
 		val = inb(TSREG);
 		outb(TSIDX, 0x01);
 		outb(TSREG, val | 0x20);
-		outb(CRTC, 0x17);
-		val = inb(CRTC + 1);
-		outb(CRTC + 1, val & ~0x80);
+		vga_crtc_and(CRT_MODE_CONTROL, 0x7f);
 		break;
 	case V_DISPLAY_BLANK:
 		outb(TSIDX, 0x01);
@@ -1702,9 +1673,7 @@ vga_blank_display(video_adapter_t *adp, int mode)
 		val = inb(TSREG);
 		outb(TSIDX, 0x01);
 		outb(TSREG, val & 0xDF);
-		outb(CRTC, 0x17);
-		val = inb(CRTC + 1);
-		outb(CRTC + 1, val | 0x80);
+		vga_crtc_or(CRT_MODE_CONTROL, 0x80);
 		break;
 	}
 	crit_exit();
diff --git a/sys/dev/video/fb/vgareg.h b/sys/dev/video/fb/vgareg.h
index 15ea215294..978983608a 100644
--- a/sys/dev/video/fb/vgareg.h
+++ b/sys/dev/video/fb/vgareg.h
@@ -24,12 +24,13 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/fb/vgareg.h,v 1.4 1999/12/29 04:35:37 peter Exp $
- * $DragonFly: src/sys/dev/video/fb/vgareg.h,v 1.9 2008/01/09 21:29:11 swildner Exp $
  */
 
 #ifndef _DEV_FB_VGAREG_H_
 #define _DEV_FB_VGAREG_H_
 
+#include <bus/isa/isareg.h>
+
 /* physical addresses */
 #define MDA_BUF_BASE		0xb0000
 #define MDA_BUF_SIZE		0x08000
@@ -49,6 +50,7 @@
 
 /* I/O port addresses */
 #define CRTC		(IO_CGA + 0x04)		/* crt controller base */
+#define GEN_INPSTAT1	(IO_CGA + 0x0a)		/* input status register 1 */
 #define MISC		(IO_VGA + 0x02)		/* misc output register */
 #define ATC		(IO_VGA + 0x00)		/* attribute controller */
 #define TSIDX		(IO_VGA + 0x04)		/* timing sequencer idx */
@@ -60,6 +62,59 @@
 #define GDCIDX		(IO_VGA + 0x0E)		/* graph data controller idx */
 #define GDCREG		(IO_VGA + 0x0F)		/* graph data controller data */
 
+enum vga_crtc_reg {
+	HORIZONTAL_TOTAL	= 0x00,
+	OVERFLOW		= 0x07,
+	PRESET_ROW_SCAN		= 0x08,
+	CURSOR_START		= 0x0a,
+	CURSOR_END		= 0x0b,
+	START_ADDRESS_HIGH	= 0x0c,
+	START_ADDRESS_LOW	= 0x0d,
+	CURSOR_LOCATION_HIGH	= 0x0e,
+	CURSOR_LOCATION_LOW	= 0x0f,
+	OFFSET			= 0x13,
+	CRT_MODE_CONTROL	= 0x17,
+	LINE_COMPARE		= 0x18
+};
+
+static __inline void
+vga_reset_flipflop(void)
+{
+	inb(GEN_INPSTAT1);
+}
+
+static __inline uint8_t
+vga_crtc_get(enum vga_crtc_reg reg)
+{
+	outb(CRTC, reg);
+	return inb(CRTC + 1);
+}
+
+static __inline void
+vga_crtc_set(enum vga_crtc_reg reg, uint8_t val)
+{
+	outb(CRTC, reg);
+	outb(CRTC + 1, val);
+}
+
+static __inline void
+vga_crtc_and(enum vga_crtc_reg reg, uint8_t val)
+{
+	uint8_t oldval;
+
+	oldval = vga_crtc_get(reg);
+	vga_crtc_set(reg, oldval & val);
+}
+
+static __inline void
+vga_crtc_or(enum vga_crtc_reg reg, uint8_t val)
+{
+	uint8_t oldval;
+
+	oldval = vga_crtc_get(reg);
+	vga_crtc_set(reg, oldval | val);
+}
+
 #define VGA_DRIVER_NAME		"vga"
 #define VGA_UNIT(dev)		minor(dev)
 #define VGA_MKMINOR(unit)	(unit & 0xff)
-- 
2.23.0

