Re: [PATCH TO TEST] VESA [1024x768] mode support for FreeBSD-CURRENT

From: Cyrille Lefevre <clefevre-current_at_9online.fr>
Date: Sat, 28 Aug 2004 03:45:52 +0200 (CEST)
On Aug 27, 2004 01:59:50 am +0000, Deng XueFeng wrote:
> First to thanks Sascha Wildner <saw_at_online.de>.
> he hack syscons to make dfbsd support 1024x768(16/24/32) syscons,
> then I ported that to current. and it works well with my ati MOBILITY 
> 7500[T31]/9200 [NX7000].
> To make console support 1024x768; just type
> #vidcontrol MODE_279
> 
> The originer patch can be get from dfbsd's maillist.

here it is :)
http://leaf.dragonflybsd.org/mailarchive/submit/2004-08/msg00074.html

> and the attachment is against with FreeBSD CURRENT and 5.3
> enjoy it!
> 
> NOTE:
>       current-vidcontrol.1 current-vidcontrol.c is taken from dfbsd. which 
> is include
>       Sascha's patch.

Hi,

I don't know why, but your patch set doesn't apply cleanly against -current !
so, I merged it in manually. also, take care while importing things to -current
from DFBSD, since DFBSD is a fork from -stable. in other words, your patch set
backout some change done in -current. the following patch set take care of this.
I also tried to reduce the diff against -current whenever possible and made some
style(9) changes (#define<tab> and <space>...<space> to <tab>).

thanks anyway and good luck.

PS : the following patch set applies and compiles cleanly against -current.
however, I didn't have tested it yet since I can't reboot right now.

Index: sys/dev/syscons/scvesactl.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/syscons/scvesactl.c,v
retrieving revision 1.20
diff -u -I$Id.*$ -I$.+BSD.*$ -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
_at__at_ -105,6 +105,17 _at__at_
 			return ENODEV;
 		mode = (cmd & 0xff) + M_VESA_BASE;
 		return sc_set_graphics_mode(scp, tp, mode);
+	default:
+		if (IOCGROUP(cmd) == 'V') {
+			if (!(scp->sc->adp->va_flags & V_ADP_MODECHANGE))
+				return ENODEV;
+
+			mode = (cmd & 0xff) + M_VESA_BASE;
+
+			if ((mode > M_VESA_FULL_1280) &&
+				(mode < M_VESA_MODE_MAX))
+			return sc_set_graphics_mode(scp, tp, mode);
+		}
 	}
 
 	if (prev_user_ioctl)
Index: sys/dev/syscons/scvgarndr.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/syscons/scvgarndr.c,v
retrieving revision 1.15
diff -u -I$Id.*$ -I$.+BSD.*$ -r1.15 scvgarndr.c
--- sys/dev/syscons/scvgarndr.c	30 May 2004 20:08:42 -0000	1.15
+++ sys/dev/syscons/scvgarndr.c	28 Aug 2004 00:59:19 -0000
_at__at_ -47,7 +47,7 _at__at_
 #include <isa/isareg.h>
 
 #ifndef SC_RENDER_DEBUG
-#define SC_RENDER_DEBUG		0
+#define	SC_RENDER_DEBUG		0
 #endif
 
 static vr_clear_t		vga_txtclear;
_at__at_ -59,7 +59,7 _at__at_
 #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
 
 #ifdef SC_PIXEL_MODE
_at__at_ -73,7 +73,7 _at__at_
 #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 */
 
_at__at_ -155,6 +155,37 _at__at_
 #endif
 #endif
 
+#ifdef SC_PIXEL_MODE
+static uint32_t vga_palette32[16] = {
+	0x000000, 0x0000ad, 0x00ad00, 0x00adad,
+	0xad0000, 0xad00ad, 0xad5200, 0xadadad,
+	0x525252, 0x5252ff, 0x52ff52, 0x52ffff,
+	0xff5252, 0xff52ff, 0xffff52, 0xffffff
+};
+
+static uint16_t vga_palette16[16] = {
+	0x0000, 0x0016, 0x0560, 0x0576, 0xb000, 0xb016, 0xb2a0, 0xb576,
+	0x52aa, 0x52bf, 0x57ea, 0x57ff, 0xfaaa, 0xfabf, 0xffea, 0xffff
+};
+
+static uint16_t vga_palette15[16] = {
+	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, ...)
 {
_at__at_ -359,8 +390,8 _at__at_
 	yoffset = y%scp->font_size;
 	for (i = 0; i < 16; ++i) {
 		cursor[i + yoffset] =
-	    		(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 = 0; i < scp->font_size; ++i) {
 		font_buf[i] = (cursor[i] & 0xff00) >> 8;
_at__at_ -431,7 +462,29 _at__at_
 /* pixel (raster text) mode renderer */
 
 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 = scp->sc->adp->va_line_width;
+	pixel_size = scp->sc->adp->va_info.vi_pixel_size;
+	lines = scp->ysize * scp->font_size;
+	p = scp->sc->adp->va_window +
+	    line_width * scp->yoff * scp->font_size +
+	    scp->xoff * 8 * pixel_size;
+
+	for (i = 0; i < lines; ++i) {
+		bzero_io((void *)p, scp->xsize * 8 * pixel_size);
+		p += line_width;
+	}
+}
+
+static void
+vga_pxlclear_planar(scr_stat *scp, int c, int attr)
 {
 	vm_offset_t p;
 	int line_width;
_at__at_ -456,8 +509,121 _at__at_
 	outw(GDCIDX, 0x0001);		/* set/reset enable */
 }
 
+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(scr_stat *scp, int color)
+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 = scp->sc->adp->va_line_width;
+	pixel_size = scp->sc->adp->va_info.vi_pixel_size;
+
+	if (scp->yoff > 0) {
+		s = scp->sc->adp->va_window;
+		e = s + line_width * scp->yoff * scp->font_size;
+
+		for (f = s; f < e; f += 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 = (scp->yoff + scp->ysize) * scp->font_size;
+
+	if (scp->ypixel > y) {
+		s = scp->sc->adp->va_window + line_width * y;
+		e = s + line_width * (scp->ypixel - y);
+
+		for (f = s; f < e; f += 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 = scp->yoff * scp->font_size;
+	x = scp->xpixel / 8 - scp->xoff - scp->xsize;
+
+	for (i = 0; i < scp->ysize * scp->font_size; ++i) {
+		if (scp->xoff > 0) {
+			s = scp->sc->adp->va_window + line_width * (y + i);
+			e = s + scp->xoff * 8 * pixel_size;
+
+			for (f = s; f < e; f += 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 = scp->sc->adp->va_window + line_width * (y + i) +
+			    scp->xoff * 8 * pixel_size +
+			    scp->xsize * 8 * pixel_size;
+			e = s + x * 8 * pixel_size;
+
+			for (f = s; f < e; f += 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;
_at__at_ -492,6 +658,27 _at__at_
 	outw(GDCIDX, 0x0001);		/* set/reset enable */
 }
 
+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 = scp->sc->adp->va_info.vi_depth;
+
+		if ((bpp == 16) &&
+		    (scp->sc->adp->va_info.vi_pixel_fsizes[1] == 5))
+			bpp = 15;
+
+		vga_pxlborder_direct(scp, color, bpp);
+		break;
+	case V_INFO_MM_PLANAR:
+		vga_pxlborder_planar(scp, color);
+		break;
+	}
+}
+
 static void 
 vga_egadraw(scr_stat *scp, int from, int count, int flip)
 {
_at__at_ -506,11 +693,7 _at__at_
 	u_char c;
 
 	line_width = scp->sc->adp->va_line_width;
-	d = scp->sc->adp->va_window
-		+ scp->xoff 
-		+ scp->yoff*scp->font_size*line_width 
-		+ (from%scp->xsize) 
-		+ scp->font_size*line_width*(from/scp->xsize);
+	d = VIDEO_MEMORY_POS(scp, from, 1);
 
 	outw(GDCIDX, 0x0005);		/* read mode 0, write mode 0 */
 	outw(GDCIDX, 0x0003);		/* data rotate/function select */
_at__at_ -541,7 +724,7 _at__at_
 		f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
 		for (j = 0; j < scp->font_size; ++j, ++f) {
 			outw(GDCIDX, (*f << 8) | 0x08);	/* bit mask */
-	        	writeb(e, 0);
+			writeb(e, 0);
 			e += line_width;
 		}
 		++d;
_at__at_ -554,8 +737,87 _at__at_
 	outw(GDCIDX, 0xff08);		/* bit mask */
 }
 
-static void 
-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 = 0;
+	vm_offset_t e;
+	u_char *f;
+	u_short col1, col2, idx;
+	int line_width;
+	int i, j, k;
+	int a;
+
+	line_width = scp->sc->adp->va_line_width;
+
+	switch (bpp) {
+	case 32:
+		d = VIDEO_MEMORY_POS(scp, from, 32);
+		break;
+	case 16:
+		/* FALLTHROUGH */
+	case 15:
+		d = VIDEO_MEMORY_POS(scp, from, 16);
+		break;
+	}
+
+	if (from + count > scp->xsize * scp->ysize)
+		count = scp->xsize * scp->ysize - from;
+
+	for (i = from; count-- > 0; ++i) {
+		a = sc_vtb_geta(&scp->vtb, i);
+
+		if (flip) {
+			col1 = (((a & 0x7000) >> 4) | (a & 0x0800)) >> 8;
+			col2 = (((a & 0x8000) >> 4) | (a & 0x0700)) >> 8;
+		} else {
+			col1 = (a & 0x0f00) >> 8;
+			col2 = (a & 0xf000) >> 12;
+		}
+
+		e = d;
+		f = &(scp->font[sc_vtb_getc(&scp->vtb, i) * scp->font_size]);
+
+		for (j = 0; j < scp->font_size; ++j, ++f) {
+			for (k = 7; k >= 0; --k) {
+				idx = *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 += line_width;
+		}
+
+		switch (bpp) {
+			case 32:
+				d += 32;
+				break;
+			case 16:
+				/* FALLTHROUGH */
+			case 15:
+				d += 16;
+				break;
+		}
+
+		if ((i % scp->xsize) == scp->xsize - 1)
+			d += 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;
_at__at_ -568,11 +830,7 _at__at_
 	u_char c;
 
 	line_width = scp->sc->adp->va_line_width;
-	d = scp->sc->adp->va_window
-		+ scp->xoff 
-		+ scp->yoff*scp->font_size*line_width 
-		+ (from%scp->xsize) 
-		+ scp->font_size*line_width*(from/scp->xsize);
+	d = VIDEO_MEMORY_POS(scp, from, 1);
 
 	outw(GDCIDX, 0x0305);		/* read mode 0, write mode 3 */
 	outw(GDCIDX, 0x0003);		/* data rotate/function select */
_at__at_ -604,7 +862,7 _at__at_
 		e = d;
 		f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
 		for (j = 0; j < scp->font_size; ++j, ++f) {
-	        	writeb(e, *f);
+			writeb(e, *f);
 			e += line_width;
 		}
 		++d;
_at__at_ -617,6 +875,27 _at__at_
 	outw(GDCIDX, 0x0001);		/* set/reset enable */
 }
 
+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 = scp->sc->adp->va_info.vi_depth;
+
+		if ((bpp == 16) &&
+		    (scp->sc->adp->va_info.vi_pixel_fsizes[1] == 5))
+			bpp = 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 
 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
 {
_at__at_ -629,8 +908,69 _at__at_
 #endif
 }
 
-static void 
-draw_pxlcursor(scr_stat *scp, int at, int on, int flip)
+draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip, int bpp)
+{
+	vm_offset_t d = 0;
+	u_char *f;
+	int line_width;
+	int height;
+	int col1, col2, idx;
+	int a;
+	int i, j;
+
+	line_width = scp->sc->adp->va_line_width;
+
+	switch (bpp) {
+	case 32:
+		d = VIDEO_MEMORY_POS(scp, at, 32) +
+		    (scp->font_size - scp->curs_attr.base - 1) * line_width;
+		break;
+	case 16:
+		/* FALLTHROUGH */
+	case 15:
+		d = VIDEO_MEMORY_POS(scp, at, 16) +
+		    (scp->font_size - scp->curs_attr.base - 1) * line_width;
+		break;
+	}
+
+	a = sc_vtb_geta(&scp->vtb, at);
+
+	if (flip) {
+		col1 = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
+		col2 = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
+	} else {
+		col1 = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
+		col2 = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
+	}
+
+	f = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
+	      scp->font_size - scp->curs_attr.base - 1]);
+
+	height = imin(scp->curs_attr.height, scp->font_size);
+
+	for (i = 0; i < height; ++i, --f) {
+		for (j = 7; j >= 0; --j) {
+			idx = *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 -= line_width;
+	}
+}
+
+static void
+draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip)
 {
 	vm_offset_t d;
 	u_char *f;
_at__at_ -642,12 +982,8 _at__at_
 	u_char c;
 
 	line_width = scp->sc->adp->va_line_width;
-	d = scp->sc->adp->va_window
-		+ scp->xoff 
-		+ scp->yoff*scp->font_size*line_width 
-		+ (at%scp->xsize) 
-		+ scp->font_size*line_width*(at/scp->xsize)
-		+ (scp->font_size - scp->curs_attr.base - 1)*line_width;
+	d = VIDEO_MEMORY_POS(scp, at, 1) +
+	    (scp->font_size - scp->curs_attr.base - 1) * line_width;
 
 	outw(GDCIDX, 0x0005);		/* read mode 0, write mode 0 */
 	outw(GDCIDX, 0x0003);		/* data rotate/function select */
_at__at_ -673,7 +1009,7 _at__at_
 	height = imin(scp->curs_attr.height, scp->font_size);
 	for (i = 0; i < height; ++i, --f) {
 		outw(GDCIDX, (*f << 8) | 0x08);	/* bit mask */
-	       	writeb(d, 0);
+		writeb(d, 0);
 		d -= line_width;
 	}
 	outw(GDCIDX, 0x0000);		/* set/reset */
_at__at_ -681,6 +1017,27 _at__at_
 	outw(GDCIDX, 0xff08);		/* bit mask */
 }
 
+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 = scp->sc->adp->va_info.vi_depth;
+
+		if ((bpp == 16) &&
+		    (scp->sc->adp->va_info.vi_pixel_fsizes[1] == 5))
+			bpp = 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 = 0;
 
 static void 
_at__at_ -725,8 +1082,87 _at__at_
 
 #ifndef SC_NO_CUTPASTE
 
+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 = 0, xend_old = 0;
+	static int y_old = 0, yend_old = 0;
+	int i, j;
+	uint32_t *u32;
+	uint16_t *u16;
+
+	line_width = scp->sc->adp->va_line_width;
+	pixel_size = scp->sc->adp->va_info.vi_pixel_size;
+
+	xend = imin(x + 16, scp->xpixel);
+	yend = imin(y + 16, scp->ypixel);
+
+	p = scp->sc->adp->va_window + y_old * line_width + x_old * pixel_size;
+
+	for (i = 0; i < (yend_old - y_old); i++) {
+		for (j = (xend_old - x_old - 1); j >= 0; j--) {
+			switch (bpp) {
+			case 32:
+				u32 = (uint32_t*)(p + j * pixel_size);
+				writel(u32, mouse_buf32[i * 16 + j]);
+				break;
+			case 16:
+				/* FALLTHROUGH */
+			case 15:
+				u16 = (uint16_t*)(p + j * pixel_size);
+				writew(u16, mouse_buf16[i * 16 + j]);
+				break;
+			}
+		}
+
+		p += line_width;
+	}
+
+	p = scp->sc->adp->va_window + y * line_width + x * pixel_size;
+
+	for (i = 0; i < (yend - y); i++) {
+		for (j = (xend - x - 1); j >= 0; j--) {
+			switch (bpp) {
+			case 32:
+				u32 = (uint32_t*)(p + j * pixel_size);
+				mouse_buf32[i * 16 + j] = *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 = (uint16_t*)(p + j * pixel_size);
+				mouse_buf16[i * 16 + j] = *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 = (uint16_t*)(p  + j * pixel_size);
+				mouse_buf16[i * 16 + j] = *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 += line_width;
+	}
+
+	x_old = x;
+	y_old = y;
+	xend_old = xend;
+	yend_old = yend;
+}
+
 static void
-draw_pxlmouse(scr_stat *scp, int x, int y)
+draw_pxlmouse_planar(scr_stat *scp, int x, int y)
 {
 	vm_offset_t p;
 	int line_width;
_at__at_ -800,8 +1236,28 _at__at_
 	outw(GDCIDX, 0x0003);		/* data rotate/function select */
 }
 
+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 = scp->sc->adp->va_info.vi_depth;
+
+		if ((bpp == 16) &&
+		    (scp->sc->adp->va_info.vi_pixel_fsizes[1] == 5))
+			bpp = 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(scr_stat *scp, int x, int y)
+remove_pxlmouse_planar(scr_stat *scp, int x, int y)
 {
 	vm_offset_t p;
 	int col, row;
_at__at_ -857,6 +1313,18 _at__at_
 	outw(GDCIDX, 0x0001);		/* set/reset enable */
 }
 
+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 
 vga_pxlmouse(scr_stat *scp, int x, int y, int on)
 {
Index: sys/dev/syscons/scvidctl.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/syscons/scvidctl.c,v
retrieving revision 1.32
diff -u -I$Id.*$ -I$.+BSD.*$ -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
_at__at_ -367,16 +367,28 _at__at_
     if ((info.vi_width < xsize*8) || (info.vi_height < ysize*fontsize))
 	return EINVAL;
 
-    /* only 16 color, 4 plane modes are supported XXX */
-    if ((info.vi_depth != 4) || (info.vi_planes != 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 == V_INFO_MM_PLANAR) {
+	if (info.vi_planes != 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 == V_INFO_MM_DIRECT) {
+	if ((info.vi_depth != 16) && (info.vi_depth != 32))
+	    return ENODEV;
+    } else
 	return ENODEV;
 
     /* stop screen saver, etc */
Index: usr.sbin/vidcontrol/vidcontrol.1
===================================================================
RCS file: /home/ncvs/src/usr.sbin/vidcontrol/vidcontrol.1,v
retrieving revision 1.55
diff -u -I$Id.*$ -I$.+BSD.*$ -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
_at__at_ -21,7 +21,7 _at__at_
 .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
_at__at_ -88,7 +88,13 _at__at_
 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 name 
+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
_at__at_ -230,7 +236,7 _at__at_
 (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.
_at__at_ -292,9 +298,8 _at__at_
 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
_at__at_ -531,3 +536,4 _at__at_
 .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
===================================================================
RCS file: /home/ncvs/src/usr.sbin/vidcontrol/vidcontrol.c,v
retrieving revision 1.47
diff -u -I$Id.*$ -I$.+BSD.*$ -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
_at__at_ -46,18 +46,16 _at__at_
 #include "path.h"
 #include "decode.h"
 
-#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)
 
 /* 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
 
 char 	legal_colors[16][16] = {
 	"black", "blue", "green", "cyan",
_at__at_ -65,16 +63,113 _at__at_
 	"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 = 0;
 int 	number;
-int	vesa_cols = _VESA_800x600_DFL_COLS;
-int	vesa_rows = _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) == -1)
+		errc(1, errno, "getting active vty");
+ 
+	cur_info.console_info.size = sizeof(cur_info.console_info);
+ 
+	if (ioctl(0, CONS_GETINFO, &cur_info.console_info) == -1)
+		errc(1, errno, "getting console information");
+ 
+	if (ioctl(0, GIO_SCRNMAP, &cur_info.screen_map) == -1)
+		errc(1, errno, "getting screen map");
+ 
+	if (ioctl(0, CONS_GET, &cur_info.video_mode_number) == -1)
+		errc(1, errno, "getting video mode number");
+ 
+	cur_info.video_mode_info.vi_mode = cur_info.video_mode_number;
+ 
+	if (ioctl(0, CONS_MODEINFO, &cur_info.video_mode_info) == -1)
+		errc(1, errno, "getting video mode parameters");
+ 
+	normal_fore_color = cur_info.console_info.mv_norm.fore;
+	normal_back_color = cur_info.console_info.mv_norm.back;
+	revers_fore_color = cur_info.console_info.mv_rev.fore;
+	revers_back_color = 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];
+ 
+	ioctl(0, VT_ACTIVATE, (caddr_t) (long)cur_info.active_vty);
+ 
+	fprintf(stderr, "ESC[=%dA", cur_info.console_info.mv_ovscan);
+	fprintf(stderr, "ESC[=%dF", cur_info.console_info.mv_norm.fore);
+	fprintf(stderr, "ESC[=%dG", cur_info.console_info.mv_norm.back);
+	fprintf(stderr, "ESC[=%dH", cur_info.console_info.mv_rev.fore);
+	fprintf(stderr, "ESC[=%dI", cur_info.console_info.mv_rev.back);
+ 
+	ioctl(0, PIO_SCRNMAP, &cur_info.screen_map);
+ 
+	if (cur_info.video_mode_number >= 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);
+ 
+	if (cur_info.video_mode_info.vi_flags & V_INFO_GRAPHICS) {
+		size[0] = cur_info.video_mode_info.vi_width / 8;
+		size[1] = cur_info.video_mode_info.vi_height /
+		    cur_info.console_info.font_size;
+		size[2] = cur_info.console_info.font_size;
+ 
+		ioctl(0, KDRASTER, size);
+	}
+}
 
+/*
+ * Print a short usage string describing all options, then exit.
+ */
 
 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]",
_at__at_ -85,16 +180,28 _at__at_
 	exit(1);
 }
 
+/*
+ * Retrieve the next argument from the command line (for options that require
+ * more than one argument).
+ */
+
 char *
 nextarg(int ac, char **av, int *indp, int oc, int strict)
 {
 	if (*indp < ac)
 		return(av[(*indp)++]);
-	if (strict != 0)
+	if (strict != 0) {
+		revert();
 		errx(1, "option requires two arguments -- %c", oc);
+	}
 	return(NULL);
 }
 
+/*
+ * Guess which file to open. Try to open each combination of a specified set
+ * of file name components.
+ */
+
 FILE *
 openguess(char *a[], char *b[], char *c[], char *d[], char **name)
 {
_at__at_ -118,6 +225,10 _at__at_
 	return (NULL);
 }
 
+/*
+ * Load a screenmap from a file and set it.
+ */
+
 void
 load_scrnmap(char *filename)
 {
_at__at_ -132,44 +243,56 _at__at_
 
 	fd = openguess(a, b, c, d, &name);
 	if (fd == NULL) {
-		warn("screenmap file not found");
-		return;
+		revert();
+		errx(1, "screenmap file not found");
 	}
 	size = sizeof(scrnmap);
 	if (decode(fd, (char *)&scrnmap, size) != size) {
 		rewind(fd);
 		if (fread(&scrnmap, 1, size, fd) != 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");
+	}
 }
 
+/*
+ * Set the default screenmap.
+ */
+
 void
-load_default_scrnmap()
+load_default_scrnmap(void)
 {
 	scrmap_t scrnmap;
 	int i;
 
 	for (i=0; i<256; i++)
 		*((char*)&scrnmap + i) = 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");
+	}
 }
 
+/*
+ * Print the current screenmap to stdout.
+ */
+
 void
-print_scrnmap()
+print_scrnmap(void)
 {
 	unsigned char map[256];
 	int i;
 
 	if (ioctl(0, GIO_SCRNMAP, &map) < 0) {
-		warn("getting screenmap");
-		return;
+		revert();
+		errc(1, errno, "getting screenmap");
 	}
 	for (i=0; i<sizeof(map); i++) {
 		if (i > 0 && i % 16 == 0)
_at__at_ -180,9 +303,12 _at__at_
 			fprintf(stdout, " %03d", map[i]);
 	}
 	fprintf(stdout, "\n");
-
 }
 
+/*
+ * Determine a file's size.
+ */
+
 int
 fsize(FILE *file)
 {
_at__at_ -194,7 +320,9 _at__at_
 		return -1;
 }
 
-#define DATASIZE(x) ((x).w * (x).h * 256 / 8)
+/*
+ * Load a font from file and set it.
+ */
 
 void
 load_font(char *type, char *filename)
_at__at_ -220,14 +348,15 _at__at_
 
 	info.size = sizeof(info);
 	if (ioctl(0, CONS_GETINFO, &info) == -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 = openguess(a, b, c, d, &name);
 	if (fd == NULL) {
-		warn("%s: can't load font file", filename);
-		return;
+		revert();
+		errx(1, "%s: can't load font file", filename);
 	}
 	if (type != NULL) {
 		size = 0;
_at__at_ -236,12 +365,13 _at__at_
 				if (sizes[i].w == w && sizes[i].h == h) {
 					size = DATASIZE(sizes[i]);
 					io = sizes[i].io;
+					font_height = sizes[i].h;
 				}
 
 		if (size == 0) {
-			warnx("%s: bad font size specification", type);
 			fclose(fd);
-			return;
+			revert();
+			errx(1, "%s: bad font size specification", type);
 		}
 	} else {
 		/* Apply heuristics */
_at__at_ -260,14 +390,15 _at__at_
 				if (DATASIZE(sizes[i]) == dsize[j]) {
 					size = dsize[j];
 					io = sizes[i].io;
+					font_height = sizes[i].h;
 					j = 2;	/* XXX */
 					break;
 				}
 
 		if (size == 0) {
-			warnx("%s: can't guess font size", filename);
 			fclose(fd);
-			return;
+			revert();
+			errx(1, "%s: can't guess font size", filename);
 		}
 		rewind(fd);
 	}
_at__at_ -276,18 +407,25 _at__at_
 	if (decode(fd, fontmap, size) != size) {
 		rewind(fd);
 		if (fsize(fd) != size || fread(fontmap, 1, size, fd) != 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);
 }
 
+/*
+ * Set the timeout for the screensaver.
+ */
+
 void
 set_screensaver_timeout(char *arg)
 {
_at__at_ -298,14 +436,20 _at__at_
 	else {
 		nsec = atoi(arg);
 		if ((*arg == '\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) == -1)
-		warn("setting screensaver period");
+	if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) {
+		revert();
+		errc(1, errno, "setting screensaver period");
+	}
 }
 
+/*
+ * Set the cursor's shape/type.
+ */
+
 void
 set_cursor_type(char *appearence)
 {
_at__at_ -318,13 +462,20 _at__at_
 	else if (!strcmp(appearence, "destructive"))
 		type = 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) == -1) {
+		revert();
+		errc(1, errno, "setting cursor type");
 	}
-	ioctl(0, CONS_CURSORTYPE, &type);
 }
 
-int
+/*
+ * Set the video mode.
+ */
+
+void
 video_mode(int argc, char **argv, int *index)
 {
 	static struct {
_at__at_ -363,64 +514,81 _at__at_
 		{ "VESA_800x600",	SW_VESA_800x600 },
 		{ NULL },
 	};
+	int new_mode_num = 0;
 	unsigned long mode = 0;
-	int cur_mode; 
 	int ioerr;
 	int size[3];
 	int i;
 
-	if (ioctl(0, CONS_GET, &cur_mode) < 0)
-		err(1, "cannot get the current video mode");
 	if (*index < argc) {
-		for (i = 0; modes[i].name != NULL; ++i) {
-			if (!strcmp(argv[*index], modes[i].name)) {
-				mode = modes[i].mode;
-				break;
+		if (!strncmp(argv[*index], "MODE_", 5)) {
+			if (!isnumber(argv[*index][5]))
+				errx(1, "invalid video mode number");
+ 
+			new_mode_num = atoi(&argv[*index][5]);
+		} else {
+			for (i = 0; modes[i].name != NULL; ++i) {
+				if (!strcmp(argv[*index], modes[i].name)) {
+					new_mode_num = modes[i].mode;
+					break;
+				}
 			}
+			if (modes[i].name == NULL)
+				errx(1, "invalid video mode name");
 		}
-		if (modes[i].name == NULL)
-			return EXIT_FAILURE;
-		if (ioctl(0, mode, NULL) < 0) {
-			warn("cannot set videomode");
-			return EXIT_FAILURE;
-		}
-		if (mode == SW_VESA_800x600) {
-			/* columns */
-			if ((vesa_cols * 8 > 800) || (vesa_cols <= 0)) {
-				warnx("incorrect number of columns: %d",
-				      vesa_cols);
-				size[0] = _VESA_800x600_DFL_COLS;
-			} else {
+		/* Collect enough information about the new video mode... */
+		new_mode_info.vi_mode = new_mode_num;
+		if (ioctl(0, CONS_MODEINFO, &new_mode_info) == -1) {
+			revert();
+			errc(1, errno, "obtaining new video mode parameters");
+		}
+		if (mode == 0) {
+			if (new_mode_num >= M_VESA_BASE)
+				mode = _IO('V', new_mode_num - M_VESA_BASE);
+			else
+				mode = _IO('S', new_mode_num);
+		}
+		/* Try setting the new mode. */
+		if (ioctl(0, mode, NULL) == -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 == 0)
+				font_height = cur_info.console_info.font_size;
+			size[2] = font_height;
+			/* adjust columns */
+			if ((vesa_cols * 8 > new_mode_info.vi_width) ||
+			    (vesa_cols <= 0))
+				size[0] = new_mode_info.vi_width / 8;
+			else
 				size[0] = vesa_cols;
-			}
-			/* rows */
-			if ((vesa_rows * _VESA_800x600_DFL_FNSZ > 600) ||
-			    (vesa_rows <=0)) {
-				warnx("incorrect number of rows: %d",
-				      vesa_rows);
-				size[1] = _VESA_800x600_DFL_ROWS;
-			} else {
+			/* adjust rows */
+			if ((vesa_rows * font_height > new_mode_info.vi_height)
+			    || (vesa_rows <= 0))
+				size[1] = new_mode_info.vi_height / font_height;
+			else
 				size[1] = vesa_rows;
-			}
-			/* font size */
-			size[2] = _VESA_800x600_DFL_FNSZ;
+			/* set raster mode */
 			if (ioctl(0, KDRASTER, size)) {
-				ioerr = errno;
-				if (cur_mode >= 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 = 1;
 		(*index)++;
 	}
-	return EXIT_SUCCESS;
 }
 
+/*
+ * Return the number for a specified color name.
+ */
+
 int
 get_color_number(char *color)
 {
_at__at_ -432,56 +600,88 _at__at_
 	return -1;
 }
 
+/*
+ * 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;
 
 	if (*index < argc && (color = get_color_number(argv[*index])) != -1) {
 		(*index)++;
-		fprintf(stderr, "[=%dF", color);
-		if (*index < argc
-		    && (color = get_color_number(argv[*index])) != -1
-		    && color < 8) {
+		normal_fore_color = color;
+		colors_changed = 1;
+		if (*index < argc &&
+		    (color = get_color_number(argv[*index])) != -1) {
 			(*index)++;
-			fprintf(stderr, "[=%dG", color);
+			normal_back_color = color;
 		}
 	}
 }
 
+/*
+ * 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;
 
 	if ((color = get_color_number(argv[*(index)-1])) != -1) {
-		fprintf(stderr, "[=%dH", color);
-		if (*index < argc
-		    && (color = get_color_number(argv[*index])) != -1
-		    && color < 8) {
+		revers_fore_color = color;
+		colors_changed = 1;
+		if (*index < argc &&
+		    (color = get_color_number(argv[*index])) != -1) {
 			(*index)++;
-			fprintf(stderr, "[=%dI", color);
+			revers_back_color = color;
 		}
 	}
 }
 
+/*
+ * Set normal and reverse foreground and background colors.
+ */
+
+void
+set_colors(void)
+{
+	fprintf(stderr, "ESC[=%dF", normal_fore_color);
+	fprintf(stderr, "ESC[=%dG", normal_back_color);
+	fprintf(stderr, "ESC[=%dH", revers_fore_color);
+	fprintf(stderr, "ESC[=%dI", revers_back_color);
+}
+
+/*
+ * Switch to virtual terminal #arg.
+ */
+
 void
 set_console(char *arg)
 {
 	int n;
 
 	if( !arg || strspn(arg,"0123456789") != strlen(arg)) {
-		warnx("bad console number");
-		return;
+		revert();
+		errx(1, "bad console number");
 	}
 
 	n = atoi(arg);
 	if (n < 1 || n > 16) {
-		warnx("console number out of range");
-	} else if (ioctl(0, VT_ACTIVATE, (caddr_t) (long) n) == -1)
-		warn("ioctl(VT_ACTIVATE)");
+		revert();
+		errx(1, "console number out of range");
+	} else if (ioctl(0, VT_ACTIVATE, (caddr_t) (long) n) == -1) {
+		revert();
+		errc(1, errno, "ioctl(VT_ACTIVATE)");
+	}
 }
 
+/*
+ * Sets the border color.
+ */
+
 void
 set_border_color(char *arg)
 {
_at__at_ -494,6 +694,10 _at__at_
 		usage();
 }
 
+/*
+ * Set the mouse characer.
+ */
+
 void
 set_mouse_char(char *arg)
 {
_at__at_ -502,14 +706,21 _at__at_
 
 	l = 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 = MOUSE_MOUSECHAR;
 	mouse.u.mouse_char = (int)l;
-	ioctl(0, CONS_MOUSECTL, &mouse);
+	if (ioctl(0, CONS_MOUSECTL, &mouse) == -1) {
+		revert();
+		errc(1, errno, "setting mouse character");
+	}
 }
 
+/*
+ * Show/hide the mouse.
+ */
+
 void
 set_mouse(char *arg)
 {
_at__at_ -520,10 +731,14 _at__at_
 	else if (!strcmp(arg, "off"))
 		mouse.operation = 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) == -1) {
+		revert();
+		errc(1, errno, "%sing the mouse",
+		    mouse.operation == MOUSE_SHOW ? "show" : "hid");
 	}
-	ioctl(0, CONS_MOUSECTL, &mouse);
 }
 
 void
_at__at_ -536,13 +751,20 _at__at_
 	else if (!strcmp(arg, "on"))
 		data = 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) == -1) {
+		revert();
+		errc(1, errno, "turning %s vty switching",
+		    data == 0x01 ? "off" : "on");
 	}
-	if (ioctl(0, VT_LOCKSWITCH, &data) == -1)
-		warn("ioctl(VT_LOCKSWITCH)");
 }
 
+/*
+ * Return the adapter name for a specified type.
+ */
+
 static char
 *adapter_name(int type)
 {
_at__at_ -567,6 +789,10 _at__at_
     return names[i].name;
 }
 
+/*
+ * Show graphics adapter information.
+ */
+
 void
 show_adapter_info(void)
 {
_at__at_ -574,8 +800,8 _at__at_
 
 	ad.va_index = 0;
 	if (ioctl(0, CONS_ADPINFO, &ad)) {
-		warn("failed to obtain adapter information");
-		return;
+		revert();
+		errc(1, errno, "failed to obtain adapter information");
 	}
 
 	printf("fb%d:\n", ad.va_index);
_at__at_ -594,6 +820,10 _at__at_
 	printf("    reserved:0x%x\n", ad.va_unused0);
 }
 
+/*
+ * Show video mode information.
+ */
+
 void
 show_mode_info(void)
 {
_at__at_ -645,13 +875,13 _at__at_
 	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");
 	}
 }
 
 void
-test_frame()
+test_frame(void)
 {
 	int i;
 
_at__at_ -682,8 +912,9 _at__at_
 
 	info.size = sizeof(info);
 	if (ioctl(0, CONS_GETINFO, &info) == -1) {
-		warn("failed to obtain current video mode parameters");
-		return;
+		revert();
+		errc(1, errno,
+		    "failed to obtain current video mode parameters");
 	}
 
 	shot.x = shot.y = 0;
_at__at_ -694,13 +925,13 _at__at_
 
 	shot.buf = alloca(shot.xsize * shot.ysize * sizeof(u_int16_t));
 	if (shot.buf == NULL) {
-		warn("failed to allocate memory for dump");
-		return;
+		revert();
+		errx(1, "failed to allocate memory for dump");
 	}
 
 	if (ioctl(0, CONS_SCRSHOT, &shot) == -1) {
-		warn("failed to get dump of the screen");
-		return;
+		revert();
+		errc(1, errno, "failed to get dump of the screen");
 	}
 
 	if (mode == DUMP_FMT_RAW) {
_at__at_ -717,8 +948,8 _at__at_
 
 		line = alloca(shot.xsize + 1);
 		if (line == NULL) {
-			warn("failed to allocate memory for line buffer");
-			return;
+			revert();
+			errx(1, "failed to allocate memory for line buffer");
 		}
 
 		for (y = 0; y < shot.ysize; y++) {
_at__at_ -743,6 +974,10 _at__at_
 	return;
 }
 
+/*
+ * Set the console history buffer size.
+ */
+
 void
 set_history(char *opt)
 {
_at__at_ -750,19 +985,27 _at__at_
 
 	size = atoi(opt);
 	if ((*opt == '\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) == -1) {
+		revert();
+		errc(1, errno, "setting history buffer size");
 	}
-	if (ioctl(0, CONS_HISTORY, &size) == -1)
-		warn("setting history buffer size");
 }
 
+/*
+ * Clear the console history buffer.
+ */
+
 void
-clear_history()
+clear_history(void)
 {
 
-	if (ioctl(0, CONS_CLRHIST) == -1)
-		warn("clear history buffer");
+	if (ioctl(0, CONS_CLRHIST) == -1) {
+		revert();
+		errc(1, errno, "clear history buffer");
+	}
 }
 
 int
_at__at_ -770,12 +1013,11 _at__at_
 {
 	char	*font, *type;
 	int	dumpmod, dumpopt, opt;
-	int	reterr;
 
-	info.size = sizeof(info);
 	if (argc == 1)
 		usage();
-		/* Not reached */
+	init();
+	info.size = sizeof(info);
 	if (ioctl(0, CONS_GETINFO, &info) < 0)
 		err(1, "must be on a virtual console");
 	dumpmod = 0;
_at__at_ -806,6 +1048,7 _at__at_
 		case 'g':
 			if (sscanf(optarg, "%dx%d", &vesa_cols,
 			    &vesa_rows) != 2) {
+				revert();
 				warnx("incorrect geometry: %s", optarg);
 				usage();
 			}
_at__at_ -838,7 +1081,7 _at__at_
 			dumpmod = DUMP_FMT_TXT;
 			break;
 		case 'r':
-			set_reverse_colors(argc, argv, &optind);
+			get_reverse_colors(argc, argv, &optind);
 			break;
 		case 'S':
 			set_lockswitch(optarg);
_at__at_ -857,14 +1100,26 _at__at_
 		}
 	if (dumpmod != 0)
 		dump_screen(dumpmod, dumpopt);
-	reterr = 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 != argc) || (argc == 1))
 		usage();
-	return reterr;
+	return(EXIT_SUCCESS);
 }
 

Cyrille Lefevre
-- 
mailto:cyrille.lefevre_at_laposte.net
Received on Sat Aug 28 2004 - 00:45:55 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:09 UTC