kern/71142: vesa [1024x768] mode support

Cyrille Lefevre cyrille.lefevre at laposte.net
Mon Aug 30 02:20:24 PDT 2004


	Note: There was a bad value `no=20' for the field `>Confidential:'.
	It was set to the default value of `yes'.


>Number:         71142
>Category:       kern
>Synopsis:       vesa [1024x768] mode support
>Confidential:   yes
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Aug 30 09:20:23 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Cyrille Lefevre
>Release:        FreeBSD 5.2-CURRENT i386
>Organization:
ACME
>Environment:
System: FreeBSD gits 5.2-CURRENT FreeBSD 5.2-CURRENT #0: Mon Aug 23 04:03:3=
2 CEST 2004 root at gits.gits.invalid:/disk1/freebsd/current/obj/disk3/freebsd=
/current/src/sys/CUSTOM i386
>Description:
see the following thread entitled "[PATCH TO TEST] VESA [1024x768] mode sup=
port
for FreeBSD-CURRENT" started on "Fri, 27 Aug 2004 01:59:50 +0000" for detai=
ls :
http://docs.freebsd.org/cgi/getmsg.cgi?fetch=3D2790218+0+/usr/local/www/db/=
text/2004/freebsd-current/20040829.freebsd-current
>How-To-Repeat:
	vidcontrol MODE_259
>Fix:
Index: sys/dev/syscons/scvesactl.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/dev/syscons/scvesactl.c,v
retrieving revision 1.20
diff -u -I$Id.*$ -I$.+BSD.*$ -u -r1.20 scvesactl.c
--- sys/dev/syscons/scvesactl.c	16 Jun 2004 09:46:58 -0000	1.20
+++ sys/dev/syscons/scvesactl.c	28 Aug 2004 01:12:21 -0000
@@ -105,6 +105,17 @@
 			return ENODEV;
 		mode =3D (cmd & 0xff) + M_VESA_BASE;
 		return sc_set_graphics_mode(scp, tp, mode);
+	default:
+		if (IOCGROUP(cmd) =3D=3D 'V') {
+			if (!(scp->sc->adp->va_flags & V_ADP_MODECHANGE))
+				return ENODEV;
+
+			mode =3D (cmd & 0xff) + M_VESA_BASE;
+
+			if ((mode > M_VESA_FULL_1280) &&
+				(mode < M_VESA_MODE_MAX))
+			return sc_set_graphics_mode(scp, tp, mode);
+		}
 	}
=20
 	if (prev_user_ioctl)
Index: sys/dev/syscons/scvgarndr.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/dev/syscons/scvgarndr.c,v
retrieving revision 1.15
diff -u -I$Id.*$ -I$.+BSD.*$ -u -r1.15 scvgarndr.c
--- sys/dev/syscons/scvgarndr.c	30 May 2004 20:08:42 -0000	1.15
+++ sys/dev/syscons/scvgarndr.c	29 Aug 2004 17:07:28 -0000
@@ -47,7 +47,7 @@
 #include <isa/isareg.h>
=20
 #ifndef SC_RENDER_DEBUG
-#define SC_RENDER_DEBUG		0
+#define	SC_RENDER_DEBUG		0
 #endif
=20
 static vr_clear_t		vga_txtclear;
@@ -59,7 +59,7 @@
 #ifndef SC_NO_CUTPASTE
 static vr_draw_mouse_t		vga_txtmouse;
 #else
-#define vga_txtmouse		(vr_draw_mouse_t *)vga_nop
+#define	vga_txtmouse		(vr_draw_mouse_t *)vga_nop
 #endif
=20
 #ifdef SC_PIXEL_MODE
@@ -73,7 +73,7 @@
 #ifndef SC_NO_CUTPASTE
 static vr_draw_mouse_t		vga_pxlmouse;
 #else
-#define vga_pxlmouse		(vr_draw_mouse_t *)vga_nop
+#define	vga_pxlmouse		(vr_draw_mouse_t *)vga_nop
 #endif
 #endif /* SC_PIXEL_MODE */
=20
@@ -155,6 +155,37 @@
 #endif
 #endif
=20
+#ifdef SC_PIXEL_MODE
+static uint32_t vga_palette32[16] =3D {
+	0x000000, 0x0000ad, 0x00ad00, 0x00adad,
+	0xad0000, 0xad00ad, 0xad5200, 0xadadad,
+	0x525252, 0x5252ff, 0x52ff52, 0x52ffff,
+	0xff5252, 0xff52ff, 0xffff52, 0xffffff
+};
+
+static uint16_t vga_palette16[16] =3D {
+	0x0000, 0x0016, 0x0560, 0x0576, 0xb000, 0xb016, 0xb2a0, 0xb576,
+	0x52aa, 0x52bf, 0x57ea, 0x57ff, 0xfaaa, 0xfabf, 0xffea, 0xffff
+};
+
+static uint16_t vga_palette15[16] =3D {
+	0x0000, 0x0016, 0x02c0, 0x02d6, 0x5800, 0x5816, 0x5940, 0x5ad6,
+	0x294a, 0x295f, 0x2bea, 0x2bff, 0x7d4a, 0x7d5f, 0x7fea, 0x7fff
+};
+
+#define	VIDEO_MEMORY_POS(scp, pos, x)					\
+	scp->sc->adp->va_window +					\
+	x * scp->xoff +							\
+	scp->yoff * scp->font_size * scp->sc->adp->va_line_width +	\
+	x * (pos % scp->xsize) +					\
+	scp->font_size * scp->sc->adp->va_line_width * (pos / scp->xsize)
+
+#ifndef SC_NO_CUTPASTE
+static uint32_t mouse_buf32[256];
+static uint16_t mouse_buf16[256];
+#endif
+#endif
+
 static void
 vga_nop(scr_stat *scp, ...)
 {
@@ -359,8 +390,8 @@
 	yoffset =3D y%scp->font_size;
 	for (i =3D 0; i < 16; ++i) {
 		cursor[i + yoffset] =3D
-	    		(cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
-	    		| (mouse_or_mask[i] >> xoffset);
+			(cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
+			| (mouse_or_mask[i] >> xoffset);
 	}
 	for (i =3D 0; i < scp->font_size; ++i) {
 		font_buf[i] =3D (cursor[i] & 0xff00) >> 8;
@@ -431,7 +462,29 @@
 /* pixel (raster text) mode renderer */
=20
 static void
-vga_pxlclear(scr_stat *scp, int c, int attr)
+vga_pxlclear_direct(scr_stat *scp, int c, int attr)
+{
+	vm_offset_t p;
+	int line_width;
+	int pixel_size;
+	int lines;
+	int i;
+
+	line_width =3D scp->sc->adp->va_line_width;
+	pixel_size =3D scp->sc->adp->va_info.vi_pixel_size;
+	lines =3D scp->ysize * scp->font_size;
+	p =3D scp->sc->adp->va_window +
+	    line_width * scp->yoff * scp->font_size +
+	    scp->xoff * 8 * pixel_size;
+
+	for (i =3D 0; i < lines; ++i) {
+		bzero_io((void *)p, scp->xsize * 8 * pixel_size);
+		p +=3D line_width;
+	}
+}
+
+static void
+vga_pxlclear_planar(scr_stat *scp, int c, int attr)
 {
 	vm_offset_t p;
 	int line_width;
@@ -457,7 +510,121 @@
 }
=20
 static void
-vga_pxlborder(scr_stat *scp, int color)
+vga_pxlclear(scr_stat *scp, int c, int attr)
+{
+	switch (scp->sc->adp->va_info.vi_mem_model) {
+	case V_INFO_MM_DIRECT:
+		vga_pxlclear_direct(scp, c, attr);
+		break;
+	case V_INFO_MM_PLANAR:
+		vga_pxlclear_planar(scp, c, attr);
+		break;
+	}
+}
+
+static void
+vga_pxlborder_direct(scr_stat *scp, int color, int bpp)
+{
+	vm_offset_t s;
+	vm_offset_t e;
+	vm_offset_t f;
+	int line_width;
+	int pixel_size;
+	int x;
+	int y;
+	int i;
+
+	line_width =3D scp->sc->adp->va_line_width;
+	pixel_size =3D scp->sc->adp->va_info.vi_pixel_size;
+
+	if (scp->yoff > 0) {
+		s =3D scp->sc->adp->va_window;
+		e =3D s + line_width * scp->yoff * scp->font_size;
+
+		for (f =3D s; f < e; f +=3D pixel_size) {
+			switch (bpp) {
+			case 32:
+				writel(f, vga_palette32[color]);
+				break;
+			case 16:
+				writew(f, vga_palette16[color]);
+				break;
+			case 15:
+				writew(f, vga_palette15[color]);
+				break;
+			}
+		}
+	}
+
+	y =3D (scp->yoff + scp->ysize) * scp->font_size;
+
+	if (scp->ypixel > y) {
+		s =3D scp->sc->adp->va_window + line_width * y;
+		e =3D s + line_width * (scp->ypixel - y);
+
+		for (f =3D s; f < e; f +=3D pixel_size) {
+			switch (bpp) {
+			case 32:
+				writel(f, vga_palette32[color]);
+				break;
+			case 16:
+				writew(f, vga_palette16[color]);
+				break;
+			case 15:
+				writew(f, vga_palette15[color]);
+				break;
+			}
+		}
+	}
+
+	y =3D scp->yoff * scp->font_size;
+	x =3D scp->xpixel / 8 - scp->xoff - scp->xsize;
+
+	for (i =3D 0; i < scp->ysize * scp->font_size; ++i) {
+		if (scp->xoff > 0) {
+			s =3D scp->sc->adp->va_window + line_width * (y + i);
+			e =3D s + scp->xoff * 8 * pixel_size;
+
+			for (f =3D s; f < e; f +=3D pixel_size) {
+				switch (bpp) {
+				case 32:
+					writel(f, vga_palette32[color]);
+					break;
+				case 16:
+					writew(f, vga_palette16[color]);
+					break;
+				case 15:
+					writew(f, vga_palette15[color]);
+					break;
+				}
+			}
+		}
+
+		if (x > 0) {
+			s =3D scp->sc->adp->va_window + line_width * (y + i) +
+			    scp->xoff * 8 * pixel_size +
+			    scp->xsize * 8 * pixel_size;
+			e =3D s + x * 8 * pixel_size;
+
+			for (f =3D s; f < e; f +=3D pixel_size) {
+				switch (bpp) {
+				case 32:
+					writel(f, vga_palette32[color]);
+					break;
+				case 16:
+					writew(f, vga_palette16[color]);
+					break;
+				case 15:
+					writew(f, vga_palette15[color]);
+					break;
+				}
+			}
+		}
+	}
+}
+
+static void
+vga_pxlborder_planar(scr_stat *scp, int color)
 {
 	vm_offset_t p;
 	int line_width;
@@ -492,6 +659,27 @@
 	outw(GDCIDX, 0x0001);		/* set/reset enable */
 }
=20
+static void
+vga_pxlborder(scr_stat *scp, int color)
+{
+	int bpp;
+
+	switch (scp->sc->adp->va_info.vi_mem_model) {
+	case V_INFO_MM_DIRECT:
+		bpp =3D scp->sc->adp->va_info.vi_depth;
+
+		if ((bpp =3D=3D 16) &&
+		    (scp->sc->adp->va_info.vi_pixel_fsizes[1] =3D=3D 5))
+			bpp =3D 15;
+
+		vga_pxlborder_direct(scp, color, bpp);
+		break;
+	case V_INFO_MM_PLANAR:
+		vga_pxlborder_planar(scp, color);
+		break;
+	}
+}
+
 static void=20
 vga_egadraw(scr_stat *scp, int from, int count, int flip)
 {
@@ -506,11 +694,7 @@
 	u_char c;
=20
 	line_width =3D scp->sc->adp->va_line_width;
-	d =3D scp->sc->adp->va_window
-		+ scp->xoff=20
-		+ scp->yoff*scp->font_size*line_width=20
-		+ (from%scp->xsize)=20
-		+ scp->font_size*line_width*(from/scp->xsize);
+	d =3D VIDEO_MEMORY_POS(scp, from, 1);
=20
 	outw(GDCIDX, 0x0005);		/* read mode 0, write mode 0 */
 	outw(GDCIDX, 0x0003);		/* data rotate/function select */
@@ -541,7 +725,7 @@
 		f =3D &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
 		for (j =3D 0; j < scp->font_size; ++j, ++f) {
 			outw(GDCIDX, (*f << 8) | 0x08);	/* bit mask */
-	        	writeb(e, 0);
+			writeb(e, 0);
 			e +=3D line_width;
 		}
 		++d;
@@ -554,8 +738,87 @@
 	outw(GDCIDX, 0xff08);		/* bit mask */
 }
=20
-static void=20
-vga_vgadraw(scr_stat *scp, int from, int count, int flip)
+static void
+vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip, int bpp)
+{
+	vm_offset_t d =3D 0;
+	vm_offset_t e;
+	u_char *f;
+	u_short col1, col2, idx;
+	int line_width;
+	int i, j, k;
+	int a;
+
+	line_width =3D scp->sc->adp->va_line_width;
+
+	switch (bpp) {
+	case 32:
+		d =3D VIDEO_MEMORY_POS(scp, from, 32);
+		break;
+	case 16:
+		/* FALLTHROUGH */
+	case 15:
+		d =3D VIDEO_MEMORY_POS(scp, from, 16);
+		break;
+	}
+
+	if (from + count > scp->xsize * scp->ysize)
+		count =3D scp->xsize * scp->ysize - from;
+
+	for (i =3D from; count-- > 0; ++i) {
+		a =3D sc_vtb_geta(&scp->vtb, i);
+
+		if (flip) {
+			col1 =3D (((a & 0x7000) >> 4) | (a & 0x0800)) >> 8;
+			col2 =3D (((a & 0x8000) >> 4) | (a & 0x0700)) >> 8;
+		} else {
+			col1 =3D (a & 0x0f00) >> 8;
+			col2 =3D (a & 0xf000) >> 12;
+		}
+
+		e =3D d;
+		f =3D &(scp->font[sc_vtb_getc(&scp->vtb, i) * scp->font_size]);
+
+		for (j =3D 0; j < scp->font_size; ++j, ++f) {
+			for (k =3D 7; k >=3D 0; --k) {
+				idx =3D *f & (1 << (7 - k)) ?
+					col1 : col2;
+
+				switch (bpp) {
+				case 32:
+					writel(e + 4 * k, vga_palette32[idx]);
+					break;
+				case 16:
+					writew(e + 2 * k, vga_palette16[idx]);
+					break;
+				case 15:
+					writew(e + 2 * k, vga_palette15[idx]);
+					break;
+				}
+			}
+
+			e +=3D line_width;
+		}
+
+		switch (bpp) {
+			case 32:
+				d +=3D 32;
+				break;
+			case 16:
+				/* FALLTHROUGH */
+			case 15:
+				d +=3D 16;
+				break;
+		}
+
+		if ((i % scp->xsize) =3D=3D scp->xsize - 1)
+			d +=3D scp->xoff * 16 * scp->sc->adp->va_info.vi_pixel_size +
+		 (scp->font_size - 1) * line_width;
+	}
+}
+
+static void
+vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip)
 {
 	vm_offset_t d;
 	vm_offset_t e;
@@ -568,11 +831,7 @@
 	u_char c;
=20
 	line_width =3D scp->sc->adp->va_line_width;
-	d =3D scp->sc->adp->va_window
-		+ scp->xoff=20
-		+ scp->yoff*scp->font_size*line_width=20
-		+ (from%scp->xsize)=20
-		+ scp->font_size*line_width*(from/scp->xsize);
+	d =3D VIDEO_MEMORY_POS(scp, from, 1);
=20
 	outw(GDCIDX, 0x0305);		/* read mode 0, write mode 3 */
 	outw(GDCIDX, 0x0003);		/* data rotate/function select */
@@ -604,7 +863,7 @@
 		e =3D d;
 		f =3D &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
 		for (j =3D 0; j < scp->font_size; ++j, ++f) {
-	        	writeb(e, *f);
+			writeb(e, *f);
 			e +=3D line_width;
 		}
 		++d;
@@ -617,6 +876,27 @@
 	outw(GDCIDX, 0x0001);		/* set/reset enable */
 }
=20
+static void
+vga_vgadraw(scr_stat *scp, int from, int count, int flip)
+{
+	int bpp;
+
+	switch (scp->sc->adp->va_info.vi_mem_model) {
+	case V_INFO_MM_DIRECT:
+		bpp =3D scp->sc->adp->va_info.vi_depth;
+
+		if ((bpp =3D=3D 16) &&
+		    (scp->sc->adp->va_info.vi_pixel_fsizes[1] =3D=3D 5))
+			bpp =3D 15;
+
+		vga_vgadraw_direct(scp, from, count, flip, bpp);
+		break;
+	case V_INFO_MM_PLANAR:
+		vga_vgadraw_planar(scp, from, count, flip);
+		break;
+	}
+}
+
 static void=20
 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
 {
@@ -629,8 +909,70 @@
 #endif
 }
=20
-static void=20
-draw_pxlcursor(scr_stat *scp, int at, int on, int flip)
+static void
+draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip, int bpp)
+{
+	vm_offset_t d =3D 0;
+	u_char *f;
+	int line_width;
+	int height;
+	int col1, col2, idx;
+	int a;
+	int i, j;
+
+	line_width =3D scp->sc->adp->va_line_width;
+
+	switch (bpp) {
+	case 32:
+		d =3D VIDEO_MEMORY_POS(scp, at, 32) +
+		    (scp->font_size - scp->curs_attr.base - 1) * line_width;
+		break;
+	case 16:
+		/* FALLTHROUGH */
+	case 15:
+		d =3D VIDEO_MEMORY_POS(scp, at, 16) +
+		    (scp->font_size - scp->curs_attr.base - 1) * line_width;
+		break;
+	}
+
+	a =3D sc_vtb_geta(&scp->vtb, at);
+
+	if (flip) {
+		col1 =3D ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
+		col2 =3D ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
+	} else {
+		col1 =3D ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
+		col2 =3D ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
+	}
+
+	f =3D &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
+	      scp->font_size - scp->curs_attr.base - 1]);
+
+	height =3D imin(scp->curs_attr.height, scp->font_size);
+
+	for (i =3D 0; i < height; ++i, --f) {
+		for (j =3D 7; j >=3D 0; --j) {
+			idx =3D *f & (1 << (7 - j)) ? col1 : col2;
+
+			switch (bpp) {
+			case 32:
+				writel(d + 4 * j, vga_palette32[idx]);
+				break;
+			case 16:
+				writew(d + 2 * j, vga_palette16[idx]);
+				break;
+			case 15:
+				writew(d + 2 * j, vga_palette15[idx]);
+				break;
+			}
+		}
+
+		d -=3D line_width;
+	}
+}
+
+static void
+draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip)
 {
 	vm_offset_t d;
 	u_char *f;
@@ -642,12 +984,8 @@
 	u_char c;
=20
 	line_width =3D scp->sc->adp->va_line_width;
-	d =3D scp->sc->adp->va_window
-		+ scp->xoff=20
-		+ scp->yoff*scp->font_size*line_width=20
-		+ (at%scp->xsize)=20
-		+ scp->font_size*line_width*(at/scp->xsize)
-		+ (scp->font_size - scp->curs_attr.base - 1)*line_width;
+	d =3D VIDEO_MEMORY_POS(scp, at, 1) +
+	    (scp->font_size - scp->curs_attr.base - 1) * line_width;
=20
 	outw(GDCIDX, 0x0005);		/* read mode 0, write mode 0 */
 	outw(GDCIDX, 0x0003);		/* data rotate/function select */
@@ -673,7 +1011,7 @@
 	height =3D imin(scp->curs_attr.height, scp->font_size);
 	for (i =3D 0; i < height; ++i, --f) {
 		outw(GDCIDX, (*f << 8) | 0x08);	/* bit mask */
-	       	writeb(d, 0);
+		writeb(d, 0);
 		d -=3D line_width;
 	}
 	outw(GDCIDX, 0x0000);		/* set/reset */
@@ -681,6 +1019,27 @@
 	outw(GDCIDX, 0xff08);		/* bit mask */
 }
=20
+static void
+draw_pxlcursor(scr_stat *scp, int at, int on, int flip)
+{
+	int bpp;
+
+	switch (scp->sc->adp->va_info.vi_mem_model) {
+	case V_INFO_MM_DIRECT:
+		bpp =3D scp->sc->adp->va_info.vi_depth;
+
+		if ((bpp =3D=3D 16) &&
+		    (scp->sc->adp->va_info.vi_pixel_fsizes[1] =3D=3D 5))
+			bpp =3D 15;
+
+		draw_pxlcursor_direct(scp, at, on, flip, bpp);
+		break;
+	case V_INFO_MM_PLANAR:
+		draw_pxlcursor_planar(scp, at, on, flip);
+		break;
+	}
+}
+
 static int pxlblinkrate =3D 0;
=20
 static void=20
@@ -726,7 +1085,87 @@
 #ifndef SC_NO_CUTPASTE
=20
 static void
-draw_pxlmouse(scr_stat *scp, int x, int y)
+draw_pxlmouse_direct(scr_stat *scp, int x, int y, int bpp)
+{
+	vm_offset_t p;
+	int line_width, pixel_size;
+	int xend, yend;
+	static int x_old =3D 0, xend_old =3D 0;
+	static int y_old =3D 0, yend_old =3D 0;
+	int i, j;
+	uint32_t *u32;
+	uint16_t *u16;
+
+	line_width =3D scp->sc->adp->va_line_width;
+	pixel_size =3D scp->sc->adp->va_info.vi_pixel_size;
+
+	xend =3D imin(x + 16, scp->xpixel);
+	yend =3D imin(y + 16, scp->ypixel);
+
+	p =3D scp->sc->adp->va_window + y_old * line_width + x_old * pixel_size;
+
+	for (i =3D 0; i < (yend_old - y_old); i++) {
+		for (j =3D (xend_old - x_old - 1); j >=3D 0; j--) {
+			switch (bpp) {
+			case 32:
+				u32 =3D (uint32_t*)(p + j * pixel_size);
+				writel(u32, mouse_buf32[i * 16 + j]);
+				break;
+			case 16:
+				/* FALLTHROUGH */
+			case 15:
+				u16 =3D (uint16_t*)(p + j * pixel_size);
+				writew(u16, mouse_buf16[i * 16 + j]);
+				break;
+			}
+		}
+
+		p +=3D line_width;
+	}
+
+	p =3D scp->sc->adp->va_window + y * line_width + x * pixel_size;
+
+	for (i =3D 0; i < (yend - y); i++) {
+		for (j =3D (xend - x - 1); j >=3D 0; j--) {
+			switch (bpp) {
+			case 32:
+				u32 =3D (uint32_t*)(p + j * pixel_size);
+				mouse_buf32[i * 16 + j] =3D *u32;
+				if (mouse_or_mask[i] & (1 << (15 - j)))
+					writel(u32, vga_palette32[15]);
+				else if (mouse_and_mask[i] & (1 << (15 - j)))
+					writel(u32, 0);
+				break;
+			case 16:
+				u16 =3D (uint16_t*)(p + j * pixel_size);
+				mouse_buf16[i * 16 + j] =3D *u16;
+				if (mouse_or_mask[i] & (1 << (15 - j)))
+					writew(u16, vga_palette16[15]);
+				else if (mouse_and_mask[i] & (1 << (15 - j)))
+					writew(u16, 0);
+				break;
+			case 15:
+				u16 =3D (uint16_t*)(p  + j * pixel_size);
+				mouse_buf16[i * 16 + j] =3D *u16;
+				if (mouse_or_mask[i] & (1 << (15 - j)))
+					writew(u16, vga_palette15[15]);
+				else if (mouse_and_mask[i] & (1 << (15 - j)))
+					writew(u16, 0);
+				break;
+			}
+		}
+
+		p +=3D line_width;
+	}
+
+	x_old =3D x;
+	y_old =3D y;
+	xend_old =3D xend;
+	yend_old =3D yend;
+}
+
+static void
+draw_pxlmouse_planar(scr_stat *scp, int x, int y)
 {
 	vm_offset_t p;
 	int line_width;
@@ -801,7 +1240,28 @@
 }
=20
 static void
-remove_pxlmouse(scr_stat *scp, int x, int y)
+draw_pxlmouse(scr_stat *scp, int x, int y)
+{
+	int bpp;
+
+	switch (scp->sc->adp->va_info.vi_mem_model) {
+	case V_INFO_MM_DIRECT:
+		bpp =3D scp->sc->adp->va_info.vi_depth;
+
+		if ((bpp =3D=3D 16) &&
+		    (scp->sc->adp->va_info.vi_pixel_fsizes[1] =3D=3D 5))
+			bpp =3D 15;
+
+		draw_pxlmouse_direct(scp, x, y, bpp);
+		break;
+	case V_INFO_MM_PLANAR:
+		draw_pxlmouse_planar(scp, x, y);
+		break;
+	}
+}
+
+static void
+remove_pxlmouse_planar(scr_stat *scp, int x, int y)
 {
 	vm_offset_t p;
 	int col, row;
@@ -857,6 +1317,18 @@
 	outw(GDCIDX, 0x0001);		/* set/reset enable */
 }
=20
+static void
+remove_pxlmouse(scr_stat *scp, int x, int y)
+{
+	switch (scp->sc->adp->va_info.vi_mem_model) {
+	case V_INFO_MM_PLANAR:
+		remove_pxlmouse_planar(scp, x, y);
+		break;
+	default:
+		break;
+	}
+}
+
 static void=20
 vga_pxlmouse(scr_stat *scp, int x, int y, int on)
 {
Index: sys/dev/syscons/scvidctl.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/dev/syscons/scvidctl.c,v
retrieving revision 1.32
diff -u -I$Id.*$ -I$.+BSD.*$ -u -r1.32 scvidctl.c
--- sys/dev/syscons/scvidctl.c	13 Jul 2004 16:06:19 -0000	1.32
+++ sys/dev/syscons/scvidctl.c	27 Aug 2004 11:25:53 -0000
@@ -367,16 +367,28 @@
     if ((info.vi_width < xsize*8) || (info.vi_height < ysize*fontsize))
 	return EINVAL;
=20
-    /* only 16 color, 4 plane modes are supported XXX */
-    if ((info.vi_depth !=3D 4) || (info.vi_planes !=3D 4))
-	return ENODEV;
-
     /*
-     * set_pixel_mode() currently does not support video modes whose
-     * memory size is larger than 64K. Because such modes require
-     * bank switching to access the entire screen. XXX
+     * We currently support the following graphic modes:
+     *
+     * - 800x600 16 color planar mode
+     * - 16 and 32 bit linear modes
      */
-    if (info.vi_width*info.vi_height/8 > info.vi_window_size)
+    if (info.vi_mem_model =3D=3D V_INFO_MM_PLANAR) {
+	if (info.vi_planes !=3D 4)
+	    return ENODEV;
+
+	/*
+	 * set_pixel_mode() currently does not support video modes whose
+	 * memory size is larger than 64K. Because such modes require
+	 * bank switching to access the entire screen. XXX
+	 */
+
+	if (info.vi_width * info.vi_height / 8 > info.vi_window_size)
+	    return ENODEV;
+    } else if (info.vi_mem_model =3D=3D V_INFO_MM_DIRECT) {
+	if ((info.vi_depth !=3D 16) && (info.vi_depth !=3D 32))
+	    return ENODEV;
+    } else
 	return ENODEV;
=20
     /* stop screen saver, etc */
Index: usr.sbin/vidcontrol/vidcontrol.1
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/usr.sbin/vidcontrol/vidcontrol.1,v
retrieving revision 1.55
diff -u -I$Id.*$ -I$.+BSD.*$ -u -r1.55 vidcontrol.1
--- usr.sbin/vidcontrol/vidcontrol.1	2 Mar 2003 21:04:21 -0000	1.55
+++ usr.sbin/vidcontrol/vidcontrol.1	28 Aug 2004 01:05:13 -0000
@@ -21,7 +21,7 @@
 .Nd system console control and configuration utility
 .Sh SYNOPSIS
 .Nm
-.Op Fl CdLHPpx
+.Op Fl CdHLPpx
 .Op Fl b Ar color
 .Op Fl c Ar appearance
 .Oo
@@ -88,7 +88,13 @@
 The raster text mode
 .Ar VESA_800x600
 can also be chosen.
-See
+Alternatively, a mode can be specified with its number by using a mode nam=
e=20
+of
+the form
+.Ar MODE_<NUMBER> .
+A list of valid mode numbers can be obtained with the
+.Fl i Cm mode
+option. See
 .Sx Video Mode Support
 below.
 .It Ar foreground Op Ar background
@@ -230,7 +236,7 @@
 (The default is to permit vty switching.)
 This protection can be easily bypassed when the kernel is compiled with
 the
-.Dv DDB
+.Dv KDB
 option.
 However, you probably should not compile the kernel debugger on a box which
 is supposed to be physically secure.
@@ -292,9 +298,8 @@
 when the system starts up.
 See below.
 .Pp
-If you want to use the raster text mode
-.Ar VESA_800x600 ,
-you need to recompile your kernel with the
+If you want to use any of the raster text modes you need to recompile your
+kernel with the
 .Dv SC_PIXEL_MODE
 option.
 See
@@ -531,3 +536,4 @@
 .Sh CONTRIBUTORS
 .An Maxim Sobolev Aq sobomax at FreeBSD.org ,
 .An Nik Clayton Aq nik at FreeBSD.org
+.An Sascha Wildner Aq saw at online.de
Index: usr.sbin/vidcontrol/vidcontrol.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/usr.sbin/vidcontrol/vidcontrol.c,v
retrieving revision 1.47
diff -u -I$Id.*$ -I$.+BSD.*$ -u -r1.47 vidcontrol.c
--- usr.sbin/vidcontrol/vidcontrol.c	18 Sep 2003 16:20:32 -0000	1.47
+++ usr.sbin/vidcontrol/vidcontrol.c	28 Aug 2004 01:09:02 -0000
@@ -46,18 +46,16 @@
 #include "path.h"
 #include "decode.h"
=20
-#define _VESA_800x600_DFL_COLS 80
-#define _VESA_800x600_DFL_ROWS 25
-#define _VESA_800x600_DFL_FNSZ 16
+#define	DATASIZE(x)	((x).w * (x).h * 256 / 8)
=20
 /* Screen dump modes */
-#define DUMP_FMT_RAW	1
-#define DUMP_FMT_TXT	2
+#define	DUMP_FMT_RAW	1
+#define	DUMP_FMT_TXT	2
 /* Screen dump options */
-#define DUMP_FBF	0
-#define DUMP_ALL	1
+#define	DUMP_FBF	0
+#define	DUMP_ALL	1
 /* Screen dump file format revision */
-#define DUMP_FMT_REV	1
+#define	DUMP_FMT_REV	1
=20
 char 	legal_colors[16][16] =3D {
 	"black", "blue", "green", "cyan",
@@ -65,16 +63,113 @@
 	"grey", "lightblue", "lightgreen", "lightcyan",
 	"lightred", "lightmagenta", "yellow", "lightwhite"
 };
+
+struct {
+	int active_vty;
+	vid_info_t console_info;
+	unsigned char screen_map[256];
+	int video_mode_number;
+	struct video_info video_mode_info;
+}	cur_info;
+
 int 	hex =3D 0;
 int 	number;
-int	vesa_cols =3D _VESA_800x600_DFL_COLS;
-int	vesa_rows =3D _VESA_800x600_DFL_ROWS;
+int	vesa_cols;
+int	vesa_rows;
+int	font_height;
+int	colors_changed;
+int	video_mode_changed;
+int	normal_fore_color, normal_back_color;
+int	revers_fore_color, revers_back_color;
 char 	letter;
 struct 	vid_info info;
+struct	video_info new_mode_info;
+
+/*
+ * Initialize revert data.
+ *
+ * NOTE: the following parameters are not yet saved/restored:
+ *
+ *   screen saver timeout
+ *   cursor type
+ *   mouse character and mouse show/hide state
+ *   vty switching on/off state
+ *   history buffer size
+ *   history contents
+ *   font maps
+ */
+
+void
+init(void)
+{
+	if (ioctl(0, VT_GETACTIVE, &cur_info.active_vty) =3D=3D -1)
+		errc(1, errno, "getting active vty");
+=20
+	cur_info.console_info.size =3D sizeof(cur_info.console_info);
+=20
+	if (ioctl(0, CONS_GETINFO, &cur_info.console_info) =3D=3D -1)
+		errc(1, errno, "getting console information");
+=20
+	if (ioctl(0, GIO_SCRNMAP, &cur_info.screen_map) =3D=3D -1)
+		errc(1, errno, "getting screen map");
+=20
+	if (ioctl(0, CONS_GET, &cur_info.video_mode_number) =3D=3D -1)
+		errc(1, errno, "getting video mode number");
+=20
+	cur_info.video_mode_info.vi_mode =3D cur_info.video_mode_number;
+=20
+	if (ioctl(0, CONS_MODEINFO, &cur_info.video_mode_info) =3D=3D -1)
+		errc(1, errno, "getting video mode parameters");
+=20
+	normal_fore_color =3D cur_info.console_info.mv_norm.fore;
+	normal_back_color =3D cur_info.console_info.mv_norm.back;
+	revers_fore_color =3D cur_info.console_info.mv_rev.fore;
+	revers_back_color =3D cur_info.console_info.mv_rev.back;
+}
+
+/*
+ * If something goes wrong along the way we call revert() to go back to the
+ * console state we came from (which is assumed to be working).
+ *
+ * NOTE: please also read the comments of init().
+ */
+
+void
+revert(void)
+{
+	int size[3];
+=20
+	ioctl(0, VT_ACTIVATE, (caddr_t) (long)cur_info.active_vty);
+=20
+	fprintf(stderr, "ESC[=3D%dA", cur_info.console_info.mv_ovscan);
+	fprintf(stderr, "ESC[=3D%dF", cur_info.console_info.mv_norm.fore);
+	fprintf(stderr, "ESC[=3D%dG", cur_info.console_info.mv_norm.back);
+	fprintf(stderr, "ESC[=3D%dH", cur_info.console_info.mv_rev.fore);
+	fprintf(stderr, "ESC[=3D%dI", cur_info.console_info.mv_rev.back);
+=20
+	ioctl(0, PIO_SCRNMAP, &cur_info.screen_map);
+=20
+	if (cur_info.video_mode_number >=3D M_VESA_BASE)
+		ioctl(0, _IO('V', cur_info.video_mode_number - M_VESA_BASE), NULL);
+	else
+		ioctl(0, _IO('S', cur_info.video_mode_number), NULL);
+=20
+	if (cur_info.video_mode_info.vi_flags & V_INFO_GRAPHICS) {
+		size[0] =3D cur_info.video_mode_info.vi_width / 8;
+		size[1] =3D cur_info.video_mode_info.vi_height /
+		    cur_info.console_info.font_size;
+		size[2] =3D cur_info.console_info.font_size;
+=20
+		ioctl(0, KDRASTER, size);
+	}
+}
=20
+/*
+ * Print a short usage string describing all options, then exit.
+ */
=20
 static void
-usage()
+usage(void)
 {
 	fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
 "usage: vidcontrol [-CdHLPpx] [-b color] [-c appearance] [-f [size] file]",
@@ -85,16 +180,28 @@
 	exit(1);
 }
=20
+/*
+ * Retrieve the next argument from the command line (for options that requ=
ire
+ * more than one argument).
+ */
+
 char *
 nextarg(int ac, char **av, int *indp, int oc, int strict)
 {
 	if (*indp < ac)
 		return(av[(*indp)++]);
-	if (strict !=3D 0)
+	if (strict !=3D 0) {
+		revert();
 		errx(1, "option requires two arguments -- %c", oc);
+	}
 	return(NULL);
 }
=20
+/*
+ * Guess which file to open. Try to open each combination of a specified s=
et
+ * of file name components.
+ */
+
 FILE *
 openguess(char *a[], char *b[], char *c[], char *d[], char **name)
 {
@@ -118,6 +225,10 @@
 	return (NULL);
 }
=20
+/*
+ * Load a screenmap from a file and set it.
+ */
+
 void
 load_scrnmap(char *filename)
 {
@@ -132,44 +243,56 @@
=20
 	fd =3D openguess(a, b, c, d, &name);
 	if (fd =3D=3D NULL) {
-		warn("screenmap file not found");
-		return;
+		revert();
+		errx(1, "screenmap file not found");
 	}
 	size =3D sizeof(scrnmap);
 	if (decode(fd, (char *)&scrnmap, size) !=3D size) {
 		rewind(fd);
 		if (fread(&scrnmap, 1, size, fd) !=3D size) {
-			warnx("bad screenmap file");
 			fclose(fd);
-			return;
+			revert();
+			errx(1, "bad screenmap file");
 		}
 	}
-	if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0)
-		warn("can't load screenmap");
 	fclose(fd);
+	if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0) {
+		revert();
+		errc(1, errno, "can't load screenmap");
+	}
 }
=20
+/*
+ * Set the default screenmap.
+ */
+
 void
-load_default_scrnmap()
+load_default_scrnmap(void)
 {
 	scrmap_t scrnmap;
 	int i;
=20
 	for (i=3D0; i<256; i++)
 		*((char*)&scrnmap + i) =3D i;
-	if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0)
-		warn("can't load default screenmap");
+	if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0) {
+		revert();
+		errc(1, errno, "can't load default screenmap");
+	}
 }
=20
+/*
+ * Print the current screenmap to stdout.
+ */
+
 void
-print_scrnmap()
+print_scrnmap(void)
 {
 	unsigned char map[256];
 	int i;
=20
 	if (ioctl(0, GIO_SCRNMAP, &map) < 0) {
-		warn("getting screenmap");
-		return;
+		revert();
+		errc(1, errno, "getting screenmap");
 	}
 	for (i=3D0; i<sizeof(map); i++) {
 		if (i > 0 && i % 16 =3D=3D 0)
@@ -180,9 +303,12 @@
 			fprintf(stdout, " %03d", map[i]);
 	}
 	fprintf(stdout, "\n");
-
 }
=20
+/*
+ * Determine a file's size.
+ */
+
 int
 fsize(FILE *file)
 {
@@ -194,7 +320,9 @@
 		return -1;
 }
=20
-#define DATASIZE(x) ((x).w * (x).h * 256 / 8)
+/*
+ * Load a font from file and set it.
+ */
=20
 void
 load_font(char *type, char *filename)
@@ -220,14 +348,15 @@
=20
 	info.size =3D sizeof(info);
 	if (ioctl(0, CONS_GETINFO, &info) =3D=3D -1) {
-		warn("failed to obtain current video mode parameters");
-		return;
+		revert();
+		errc(1, errno,
+		    "failed to obtain current video mode parameters");
 	}
 	snprintf(size_sufx, sizeof(size_sufx), "-8x%d", info.font_size);
 	fd =3D openguess(a, b, c, d, &name);
 	if (fd =3D=3D NULL) {
-		warn("%s: can't load font file", filename);
-		return;
+		revert();
+		errx(1, "%s: can't load font file", filename);
 	}
 	if (type !=3D NULL) {
 		size =3D 0;
@@ -236,12 +365,13 @@
 				if (sizes[i].w =3D=3D w && sizes[i].h =3D=3D h) {
 					size =3D DATASIZE(sizes[i]);
 					io =3D sizes[i].io;
+					font_height =3D sizes[i].h;
 				}
=20
 		if (size =3D=3D 0) {
-			warnx("%s: bad font size specification", type);
 			fclose(fd);
-			return;
+			revert();
+			errx(1, "%s: bad font size specification", type);
 		}
 	} else {
 		/* Apply heuristics */
@@ -260,14 +390,15 @@
 				if (DATASIZE(sizes[i]) =3D=3D dsize[j]) {
 					size =3D dsize[j];
 					io =3D sizes[i].io;
+					font_height =3D sizes[i].h;
 					j =3D 2;	/* XXX */
 					break;
 				}
=20
 		if (size =3D=3D 0) {
-			warnx("%s: can't guess font size", filename);
 			fclose(fd);
-			return;
+			revert();
+			errx(1, "%s: can't guess font size", filename);
 		}
 		rewind(fd);
 	}
@@ -276,18 +407,25 @@
 	if (decode(fd, fontmap, size) !=3D size) {
 		rewind(fd);
 		if (fsize(fd) !=3D size || fread(fontmap, 1, size, fd) !=3D size) {
-			warnx("%s: bad font file", filename);
 			fclose(fd);
 			free(fontmap);
-			return;
+			revert();
+			errx(1, "%s: bad font file", filename);
 		}
 	}
-	if (ioctl(0, io, fontmap) < 0)
-		warn("can't load font");
 	fclose(fd);
+	if (ioctl(0, io, fontmap) < 0) {
+		free(fontmap);
+		revert();
+		errc(1, errno, "can't load font");
+	}
 	free(fontmap);
 }
=20
+/*
+ * Set the timeout for the screensaver.
+ */
+
 void
 set_screensaver_timeout(char *arg)
 {
@@ -298,14 +436,20 @@
 	else {
 		nsec =3D atoi(arg);
 		if ((*arg =3D=3D '\0') || (nsec < 1)) {
-			warnx("argument must be a positive number");
-			return;
+			revert();
+			errx(1, "argument must be a positive number");
 		}
 	}
-	if (ioctl(0, CONS_BLANKTIME, &nsec) =3D=3D -1)
-		warn("setting screensaver period");
+	if (ioctl(0, CONS_BLANKTIME, &nsec) =3D=3D -1) {
+		revert();
+		errc(1, errno, "setting screensaver period");
+	}
 }
=20
+/*
+ * Set the cursor's shape/type.
+ */
+
 void
 set_cursor_type(char *appearence)
 {
@@ -318,13 +462,20 @@
 	else if (!strcmp(appearence, "destructive"))
 		type =3D 3;
 	else {
-		warnx("argument to -c must be normal, blink or destructive");
-		return;
+		revert();
+		errx(1, "argument to -c must be normal, blink or destructive");
+	}
+	if (ioctl(0, CONS_CURSORTYPE, &type) =3D=3D -1) {
+		revert();
+		errc(1, errno, "setting cursor type");
 	}
-	ioctl(0, CONS_CURSORTYPE, &type);
 }
=20
-int
+/*
+ * Set the video mode.
+ */
+
+void
 video_mode(int argc, char **argv, int *index)
 {
 	static struct {
@@ -363,64 +514,81 @@
 		{ "VESA_800x600",	SW_VESA_800x600 },
 		{ NULL },
 	};
+	int new_mode_num =3D 0;
 	unsigned long mode =3D 0;
-	int cur_mode;=20
 	int ioerr;
 	int size[3];
 	int i;
=20
-	if (ioctl(0, CONS_GET, &cur_mode) < 0)
-		err(1, "cannot get the current video mode");
 	if (*index < argc) {
-		for (i =3D 0; modes[i].name !=3D NULL; ++i) {
-			if (!strcmp(argv[*index], modes[i].name)) {
-				mode =3D modes[i].mode;
-				break;
+		if (!strncmp(argv[*index], "MODE_", 5)) {
+			if (!isnumber(argv[*index][5]))
+				errx(1, "invalid video mode number");
+=20
+			new_mode_num =3D atoi(&argv[*index][5]);
+		} else {
+			for (i =3D 0; modes[i].name !=3D NULL; ++i) {
+				if (!strcmp(argv[*index], modes[i].name)) {
+					new_mode_num =3D modes[i].mode;
+					break;
+				}
 			}
+			if (modes[i].name =3D=3D NULL)
+				errx(1, "invalid video mode name");
 		}
-		if (modes[i].name =3D=3D NULL)
-			return EXIT_FAILURE;
-		if (ioctl(0, mode, NULL) < 0) {
-			warn("cannot set videomode");
-			return EXIT_FAILURE;
-		}
-		if (mode =3D=3D SW_VESA_800x600) {
-			/* columns */
-			if ((vesa_cols * 8 > 800) || (vesa_cols <=3D 0)) {
-				warnx("incorrect number of columns: %d",
-				      vesa_cols);
-				size[0] =3D _VESA_800x600_DFL_COLS;
-			} else {
+		/* Collect enough information about the new video mode... */
+		new_mode_info.vi_mode =3D new_mode_num;
+		if (ioctl(0, CONS_MODEINFO, &new_mode_info) =3D=3D -1) {
+			revert();
+			errc(1, errno, "obtaining new video mode parameters");
+		}
+		if (mode =3D=3D 0) {
+			if (new_mode_num >=3D M_VESA_BASE)
+				mode =3D _IO('V', new_mode_num - M_VESA_BASE);
+			else
+				mode =3D _IO('S', new_mode_num);
+		}
+		/* Try setting the new mode. */
+		if (ioctl(0, mode, NULL) =3D=3D -1) {
+			revert();
+			errc(1, errno, "cannot set videomode");
+		}
+		/*
+		 * For raster modes it's not enough to just set the mode.
+		 * We also need to explicitly set the raster mode.
+		 */
+		if (new_mode_info.vi_flags & V_INFO_GRAPHICS) {
+			/* font size */
+			if (font_height =3D=3D 0)
+				font_height =3D cur_info.console_info.font_size;
+			size[2] =3D font_height;
+			/* adjust columns */
+			if ((vesa_cols * 8 > new_mode_info.vi_width) ||
+			    (vesa_cols <=3D 0))
+				size[0] =3D new_mode_info.vi_width / 8;
+			else
 				size[0] =3D vesa_cols;
-			}
-			/* rows */
-			if ((vesa_rows * _VESA_800x600_DFL_FNSZ > 600) ||
-			    (vesa_rows <=3D0)) {
-				warnx("incorrect number of rows: %d",
-				      vesa_rows);
-				size[1] =3D _VESA_800x600_DFL_ROWS;
-			} else {
+			/* adjust rows */
+			if ((vesa_rows * font_height > new_mode_info.vi_height)
+			    || (vesa_rows <=3D 0))
+				size[1] =3D new_mode_info.vi_height / font_height;
+			else
 				size[1] =3D vesa_rows;
-			}
-			/* font size */
-			size[2] =3D _VESA_800x600_DFL_FNSZ;
+			/* set raster mode */
 			if (ioctl(0, KDRASTER, size)) {
-				ioerr =3D errno;
-				if (cur_mode >=3D M_VESA_BASE)
-					ioctl(0,
-					    _IO('V', cur_mode - M_VESA_BASE),
-					    NULL);
-				else
-					ioctl(0, _IO('S', cur_mode), NULL);
-				warnc(ioerr, "cannot activate raster display");
-				return EXIT_FAILURE;
+				revert();
+				errc(1, errno, "activating raster display");
 			}
 		}
+		video_mode_changed =3D 1;
 		(*index)++;
 	}
-	return EXIT_SUCCESS;
 }
=20
+/*
+ * Return the number for a specified color name.
+ */
+
 int
 get_color_number(char *color)
 {
@@ -432,56 +600,88 @@
 	return -1;
 }
=20
+/*
+ * Get normal text and background colors.
+ */
+
 void
-set_normal_colors(int argc, char **argv, int *index)
+get_normal_colors(int argc, char **argv, int *index)
 {
 	int color;
=20
 	if (*index < argc && (color =3D get_color_number(argv[*index])) !=3D -1) {
 		(*index)++;
-		fprintf(stderr, "=1B[=3D%dF", color);
-		if (*index < argc
-		    && (color =3D get_color_number(argv[*index])) !=3D -1
-		    && color < 8) {
+		normal_fore_color =3D color;
+		colors_changed =3D 1;
+		if (*index < argc &&
+		    (color =3D get_color_number(argv[*index])) !=3D -1) {
 			(*index)++;
-			fprintf(stderr, "=1B[=3D%dG", color);
+			normal_back_color =3D color;
 		}
 	}
 }
=20
+/*
+ * Get reverse text and background colors.
+ */
+
 void
-set_reverse_colors(int argc, char **argv, int *index)
+get_reverse_colors(int argc, char **argv, int *index)
 {
 	int color;
=20
 	if ((color =3D get_color_number(argv[*(index)-1])) !=3D -1) {
-		fprintf(stderr, "=1B[=3D%dH", color);
-		if (*index < argc
-		    && (color =3D get_color_number(argv[*index])) !=3D -1
-		    && color < 8) {
+		revers_fore_color =3D color;
+		colors_changed =3D 1;
+		if (*index < argc &&
+		    (color =3D get_color_number(argv[*index])) !=3D -1) {
 			(*index)++;
-			fprintf(stderr, "=1B[=3D%dI", color);
+			revers_back_color =3D color;
 		}
 	}
 }
=20
+/*
+ * Set normal and reverse foreground and background colors.
+ */
+
+void
+set_colors(void)
+{
+	fprintf(stderr, "ESC[=3D%dF", normal_fore_color);
+	fprintf(stderr, "ESC[=3D%dG", normal_back_color);
+	fprintf(stderr, "ESC[=3D%dH", revers_fore_color);
+	fprintf(stderr, "ESC[=3D%dI", revers_back_color);
+}
+
+/*
+ * Switch to virtual terminal #arg.
+ */
+
 void
 set_console(char *arg)
 {
 	int n;
=20
 	if( !arg || strspn(arg,"0123456789") !=3D strlen(arg)) {
-		warnx("bad console number");
-		return;
+		revert();
+		errx(1, "bad console number");
 	}
=20
 	n =3D atoi(arg);
 	if (n < 1 || n > 16) {
-		warnx("console number out of range");
-	} else if (ioctl(0, VT_ACTIVATE, (caddr_t) (long) n) =3D=3D -1)
-		warn("ioctl(VT_ACTIVATE)");
+		revert();
+		errx(1, "console number out of range");
+	} else if (ioctl(0, VT_ACTIVATE, (caddr_t) (long) n) =3D=3D -1) {
+		revert();
+		errc(1, errno, "ioctl(VT_ACTIVATE)");
+	}
 }
=20
+/*
+ * Sets the border color.
+ */
+
 void
 set_border_color(char *arg)
 {
@@ -494,6 +694,10 @@
 		usage();
 }
=20
+/*
+ * Set the mouse characer.
+ */
+
 void
 set_mouse_char(char *arg)
 {
@@ -502,14 +706,21 @@
=20
 	l =3D strtol(arg, NULL, 0);
 	if ((l < 0) || (l > UCHAR_MAX - 3)) {
-		warnx("argument to -M must be 0 through %d", UCHAR_MAX - 3);
-		return;
+		revert();
+		errx(1, "argument to -M must be 0 through %d", UCHAR_MAX - 3);
 	}
 	mouse.operation =3D MOUSE_MOUSECHAR;
 	mouse.u.mouse_char =3D (int)l;
-	ioctl(0, CONS_MOUSECTL, &mouse);
+	if (ioctl(0, CONS_MOUSECTL, &mouse) =3D=3D -1) {
+		revert();
+		errc(1, errno, "setting mouse character");
+	}
 }
=20
+/*
+ * Show/hide the mouse.
+ */
+
 void
 set_mouse(char *arg)
 {
@@ -520,10 +731,14 @@
 	else if (!strcmp(arg, "off"))
 		mouse.operation =3D MOUSE_HIDE;
 	else {
-		warnx("argument to -m must be either on or off");
-		return;
+		revert();
+		errx(1, "argument to -m must be either on or off");
+	}
+	if (ioctl(0, CONS_MOUSECTL, &mouse) =3D=3D -1) {
+		revert();
+		errc(1, errno, "%sing the mouse",
+		    mouse.operation =3D=3D MOUSE_SHOW ? "show" : "hid");
 	}
-	ioctl(0, CONS_MOUSECTL, &mouse);
 }
=20
 void
@@ -536,13 +751,20 @@
 	else if (!strcmp(arg, "on"))
 		data =3D 0x02;
 	else {
-		warnx("argument to -S must be either on or off");
-		return;
+		revert();
+		errx(1, "argument to -S must be either on or off");
+	}
+	if (ioctl(0, VT_LOCKSWITCH, &data) =3D=3D -1) {
+		revert();
+		errc(1, errno, "turning %s vty switching",
+		    data =3D=3D 0x01 ? "off" : "on");
 	}
-	if (ioctl(0, VT_LOCKSWITCH, &data) =3D=3D -1)
-		warn("ioctl(VT_LOCKSWITCH)");
 }
=20
+/*
+ * Return the adapter name for a specified type.
+ */
+
 static char
 *adapter_name(int type)
 {
@@ -567,6 +789,10 @@
     return names[i].name;
 }
=20
+/*
+ * Show graphics adapter information.
+ */
+
 void
 show_adapter_info(void)
 {
@@ -574,8 +800,8 @@
=20
 	ad.va_index =3D 0;
 	if (ioctl(0, CONS_ADPINFO, &ad)) {
-		warn("failed to obtain adapter information");
-		return;
+		revert();
+		errc(1, errno, "failed to obtain adapter information");
 	}
=20
 	printf("fb%d:\n", ad.va_index);
@@ -594,6 +820,10 @@
 	printf("    reserved:0x%x\n", ad.va_unused0);
 }
=20
+/*
+ * Show video mode information.
+ */
+
 void
 show_mode_info(void)
 {
@@ -645,13 +875,13 @@
 	else if (!strcmp(arg, "mode"))
 		show_mode_info();
 	else {
-		warnx("argument to -i must be either adapter or mode");
-		return;
+		revert();
+		errx(1, "argument to -i must be either adapter or mode");
 	}
 }
=20
 void
-test_frame()
+test_frame(void)
 {
 	int i;
=20
@@ -682,8 +912,9 @@
=20
 	info.size =3D sizeof(info);
 	if (ioctl(0, CONS_GETINFO, &info) =3D=3D -1) {
-		warn("failed to obtain current video mode parameters");
-		return;
+		revert();
+		errc(1, errno,
+		    "failed to obtain current video mode parameters");
 	}
=20
 	shot.x =3D shot.y =3D 0;
@@ -694,13 +925,13 @@
=20
 	shot.buf =3D alloca(shot.xsize * shot.ysize * sizeof(u_int16_t));
 	if (shot.buf =3D=3D NULL) {
-		warn("failed to allocate memory for dump");
-		return;
+		revert();
+		errx(1, "failed to allocate memory for dump");
 	}
=20
 	if (ioctl(0, CONS_SCRSHOT, &shot) =3D=3D -1) {
-		warn("failed to get dump of the screen");
-		return;
+		revert();
+		errc(1, errno, "failed to get dump of the screen");
 	}
=20
 	if (mode =3D=3D DUMP_FMT_RAW) {
@@ -717,8 +948,8 @@
=20
 		line =3D alloca(shot.xsize + 1);
 		if (line =3D=3D NULL) {
-			warn("failed to allocate memory for line buffer");
-			return;
+			revert();
+			errx(1, "failed to allocate memory for line buffer");
 		}
=20
 		for (y =3D 0; y < shot.ysize; y++) {
@@ -743,6 +974,10 @@
 	return;
 }
=20
+/*
+ * Set the console history buffer size.
+ */
+
 void
 set_history(char *opt)
 {
@@ -750,19 +985,27 @@
=20
 	size =3D atoi(opt);
 	if ((*opt =3D=3D '\0') || size < 0) {
-		warnx("argument must be a positive number");
-		return;
+		revert();
+		errx(1, "argument must be a positive number");
+	}
+	if (ioctl(0, CONS_HISTORY, &size) =3D=3D -1) {
+		revert();
+		errc(1, errno, "setting history buffer size");
 	}
-	if (ioctl(0, CONS_HISTORY, &size) =3D=3D -1)
-		warn("setting history buffer size");
 }
=20
+/*
+ * Clear the console history buffer.
+ */
+
 void
-clear_history()
+clear_history(void)
 {
=20
-	if (ioctl(0, CONS_CLRHIST) =3D=3D -1)
-		warn("clear history buffer");
+	if (ioctl(0, CONS_CLRHIST) =3D=3D -1) {
+		revert();
+		errc(1, errno, "clear history buffer");
+	}
 }
=20
 int
@@ -770,12 +1013,11 @@
 {
 	char	*font, *type;
 	int	dumpmod, dumpopt, opt;
-	int	reterr;
=20
-	info.size =3D sizeof(info);
 	if (argc =3D=3D 1)
 		usage();
-		/* Not reached */
+	init();
+	info.size =3D sizeof(info);
 	if (ioctl(0, CONS_GETINFO, &info) < 0)
 		err(1, "must be on a virtual console");
 	dumpmod =3D 0;
@@ -806,6 +1048,7 @@
 		case 'g':
 			if (sscanf(optarg, "%dx%d", &vesa_cols,
 			    &vesa_rows) !=3D 2) {
+				revert();
 				warnx("incorrect geometry: %s", optarg);
 				usage();
 			}
@@ -838,7 +1081,7 @@
 			dumpmod =3D DUMP_FMT_TXT;
 			break;
 		case 'r':
-			set_reverse_colors(argc, argv, &optind);
+			get_reverse_colors(argc, argv, &optind);
 			break;
 		case 'S':
 			set_lockswitch(optarg);
@@ -857,14 +1100,26 @@
 		}
 	if (dumpmod !=3D 0)
 		dump_screen(dumpmod, dumpopt);
-	reterr =3D video_mode(argc, argv, &optind);
-	set_normal_colors(argc, argv, &optind);
+	video_mode(argc, argv, &optind);
+	get_normal_colors(argc, argv, &optind);
+	if (colors_changed || video_mode_changed) {
+		if (!(new_mode_info.vi_flags & V_INFO_GRAPHICS)) {
+			if ((normal_back_color < 8) && (revers_back_color < 8)) {
+				set_colors();
+			} else {
+				revert();
+				errx(1, "background colors for text video modes must be < 8");
+			}
+		} else {
+			set_colors();
+		}
+	}
 	if (optind < argc && !strcmp(argv[optind], "show")) {
 		test_frame();
 		optind++;
 	}
 	if ((optind !=3D argc) || (argc =3D=3D 1))
 		usage();
-	return reterr;
+	return(EXIT_SUCCESS);
 }
=20
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list