svn commit: r205983 - stable/8/sys/dev/fb

Jung-uk Kim jkim at FreeBSD.org
Wed Mar 31 15:45:11 UTC 2010


Author: jkim
Date: Wed Mar 31 15:45:11 2010
New Revision: 205983
URL: http://svn.freebsd.org/changeset/base/205983

Log:
  MFC:	r205557, r205558, r205564, r205566, r205604, r205653
  
  Sync. pixel mode support for VESA and VGA frame buffers with HEAD.
  
  - Map entire video memory again.  Although we do not use them all directly,
  it seems VGA renderer may access unmapped memory region and cause kernel
  panic.
  - Fall back to VGA palette functions if VESA function failed and DAC is
  still in 6-bit mode.  Although we have to check non-VGA compatibility bit
  here, it seems there are too many broken VESA BIOSes out to rely on it.
  - Be careful when we determine bytes per scan line information.  We compare
  mode table data against minimum value.  If the mode table does not make
  sense, we set the minimum in the mode info.
  - Teach VGA framebuffer about 8-bit palette format for VESA.
  - Add my copyright here.

Modified:
  stable/8/sys/dev/fb/vesa.c
  stable/8/sys/dev/fb/vga.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/dev/fb/vesa.c
==============================================================================
--- stable/8/sys/dev/fb/vesa.c	Wed Mar 31 15:39:46 2010	(r205982)
+++ stable/8/sys/dev/fb/vesa.c	Wed Mar 31 15:45:11 2010	(r205983)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 1998 Kazutaka YOKOTA and Michael Smith
+ * Copyright (c) 2009-2010 Jung-uk Kim <jkim at FreeBSD.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -188,7 +189,7 @@ static int vesa_bios_load_palette2(int s
 #define STATE_ALL	(STATE_HW | STATE_DATA | STATE_DAC | STATE_REG)
 static ssize_t vesa_bios_state_buf_size(void);
 static int vesa_bios_save_restore(int code, void *p, size_t size);
-#if 0
+#ifdef MODE_TABLE_BROKEN
 static int vesa_bios_get_line_length(void);
 #endif
 static int vesa_bios_set_line_length(int pixel, int *bytes, int *lines);
@@ -199,6 +200,7 @@ static int vesa_bios_set_start(int x, in
 static int vesa_map_gen_mode_num(int type, int color, int mode);
 static int vesa_translate_flags(u_int16_t vflags);
 static int vesa_translate_mmodel(u_int8_t vmodel);
+static int vesa_get_bpscanline(struct vesa_mode *vmode);
 static int vesa_bios_init(void);
 static void vesa_clear_modes(video_info_t *info, int color);
 
@@ -558,7 +560,7 @@ vesa_bios_save_restore(int code, void *p
 	return (regs.R_AX != 0x004f);
 }
 
-#if 0
+#ifdef MODE_TABLE_BROKEN
 static int
 vesa_bios_get_line_length(void)
 {
@@ -709,6 +711,43 @@ vesa_translate_mmodel(u_int8_t vmodel)
 	return (V_INFO_MM_OTHER);
 }
 
+static int
+vesa_get_bpscanline(struct vesa_mode *vmode)
+{
+	int bpsl;
+
+	if ((vmode->v_modeattr & V_MODEGRAPHICS) != 0) {
+		/* Find the minimum length. */
+		switch (vmode->v_bpp / vmode->v_planes) {
+		case 1:
+			bpsl = vmode->v_width / 8;
+			break;
+		case 2:
+			bpsl = vmode->v_width / 4;
+			break;
+		case 4:
+			bpsl = vmode->v_width / 2;
+			break;
+		default:
+			bpsl = vmode->v_width * ((vmode->v_bpp + 7) / 8);
+			bpsl /= vmode->v_planes;
+			break;
+		}
+
+		/* Use VBE 3.0 information if it looks sane. */
+		if ((vmode->v_modeattr & V_MODELFB) != 0 &&
+		    vesa_adp_info->v_version >= 0x0300 &&
+		    vmode->v_linbpscanline > bpsl)
+			return (vmode->v_linbpscanline);
+
+		/* Return the minimum if the mode table looks absurd. */
+		if (vmode->v_bpscanline < bpsl)
+			return (bpsl);
+	}
+
+	return (vmode->v_bpscanline);
+}
+
 #define	VESA_MAXSTR		256
 
 #define	VESA_STRCPY(dst, src)	do {				\
@@ -733,7 +772,6 @@ vesa_bios_init(void)
 	void *vmbuf;
 	uint32_t offs;
 	uint16_t vers;
-	int bpsl;
 	int is_via_cle266;
 	int modes;
 	int i;
@@ -858,9 +896,7 @@ vesa_bios_init(void)
 		}
 #endif
 
-		bpsl = (vmode.v_modeattr & V_MODELFB) != 0 && vers >= 0x0300 ?
-		    vmode.v_linbpscanline : vmode.v_bpscanline;
-		bsize = bpsl * vmode.v_height;
+		bsize = vesa_get_bpscanline(&vmode) * vmode.v_height;
 		if ((vmode.v_modeattr & V_MODEGRAPHICS) != 0)
 			bsize *= vmode.v_planes;
 
@@ -1209,7 +1245,7 @@ vesa_set_mode(video_adapter_t *adp, int 
 			int10_set_mode(adp->va_initial_bios_mode);
 			if (adp->va_info.vi_flags & V_INFO_LINEAR)
 				pmap_unmapdev(adp->va_buffer,
-				    adp->va_buffer_size);
+				    vesa_adp_info->v_memsize * 64 * 1024);
 			/* 
 			 * Once (*prevvidsw->get_info)() succeeded, 
 			 * (*prevvidsw->set_mode)() below won't fail...
@@ -1241,12 +1277,12 @@ vesa_set_mode(video_adapter_t *adp, int 
 
 	if ((vesa_adp_info->v_flags & V_DAC8) != 0 &&
 	    (info.vi_flags & V_INFO_GRAPHICS) != 0 &&
-	    (info.vi_flags & V_INFO_NONVGA) != 0 &&
 	    vesa_bios_set_dac(8) > 6)
 		adp->va_flags |= V_ADP_DAC8;
 
 	if (adp->va_info.vi_flags & V_INFO_LINEAR)
-		pmap_unmapdev(adp->va_buffer, adp->va_buffer_size);
+		pmap_unmapdev(adp->va_buffer,
+		    vesa_adp_info->v_memsize * 64 * 1024);
 
 #if VESA_DEBUG > 0
 	printf("VESA: mode set!\n");
@@ -1257,13 +1293,31 @@ vesa_set_mode(video_adapter_t *adp, int 
 		(info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
 	vesa_adp->va_crtc_addr =
 		(vesa_adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC;
+
+	vesa_adp->va_line_width = info.vi_buffer_size / info.vi_height;
+	if ((info.vi_flags & V_INFO_GRAPHICS) != 0)
+		vesa_adp->va_line_width /= info.vi_planes;
+
+#ifdef MODE_TABLE_BROKEN
+	/* If VBE function returns bigger bytes per scan line, use it. */
+	{
+		int bpsl = vesa_bios_get_line_length();
+		if (bpsl > vesa_adp->va_line_width) {
+			vesa_adp->va_line_width = bpsl;
+			info.vi_buffer_size = bpsl * info.vi_height;
+			if ((info.vi_flags & V_INFO_GRAPHICS) != 0)
+				info.vi_buffer_size *= info.vi_planes;
+		}
+	}
+#endif
+
 	if (info.vi_flags & V_INFO_LINEAR) {
 #if VESA_DEBUG > 1
 		printf("VESA: setting up LFB\n");
 #endif
 		vesa_adp->va_buffer =
 		    (vm_offset_t)pmap_mapdev_attr(info.vi_buffer,
-		    info.vi_buffer_size, PAT_WRITE_COMBINING);
+		    vesa_adp_info->v_memsize * 64 * 1024, PAT_WRITE_COMBINING);
 		vesa_adp->va_window = vesa_adp->va_buffer;
 		vesa_adp->va_window_size = info.vi_buffer_size / info.vi_planes;
 		vesa_adp->va_window_gran = info.vi_buffer_size / info.vi_planes;
@@ -1275,9 +1329,6 @@ vesa_set_mode(video_adapter_t *adp, int 
 	}
 	vesa_adp->va_buffer_size = info.vi_buffer_size;
 	vesa_adp->va_window_orig = 0;
-	vesa_adp->va_line_width = info.vi_buffer_size / info.vi_height;
-	if ((info.vi_flags & V_INFO_GRAPHICS) != 0)
-		vesa_adp->va_line_width /= info.vi_planes;
 	vesa_adp->va_disp_start.x = 0;
 	vesa_adp->va_disp_start.y = 0;
 #if VESA_DEBUG > 0
@@ -1322,10 +1373,10 @@ vesa_save_palette(video_adapter_t *adp, 
 {
 	int bits;
 
-	if (adp == vesa_adp && VESA_MODE(adp->va_mode) &&
-	    (adp->va_info.vi_flags & V_INFO_NONVGA) != 0) {
+	if (adp == vesa_adp && VESA_MODE(adp->va_mode)) {
 		bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 8 : 6;
-		return (vesa_bios_save_palette(0, 256, palette, bits));
+		if (vesa_bios_save_palette(0, 256, palette, bits) == 0)
+			return (0);
 	}
 
 	return ((*prevvidsw->save_palette)(adp, palette));
@@ -1336,10 +1387,10 @@ vesa_load_palette(video_adapter_t *adp, 
 {
 	int bits;
 
-	if (adp == vesa_adp && VESA_MODE(adp->va_mode) &&
-	    (adp->va_info.vi_flags & V_INFO_NONVGA) != 0) {
+	if (adp == vesa_adp && VESA_MODE(adp->va_mode)) {
 		bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 8 : 6;
-		return (vesa_bios_load_palette(0, 256, palette, bits));
+		if (vesa_bios_load_palette(0, 256, palette, bits) == 0)
+			return (0);
 	}
 
 	return ((*prevvidsw->load_palette)(adp, palette));
@@ -1544,8 +1595,6 @@ get_palette(video_adapter_t *adp, int ba
 		return (1);
 	if (!VESA_MODE(adp->va_mode))
 		return (1);
-	if ((adp->va_info.vi_flags & V_INFO_NONVGA) == 0)
-		return (1);
 
 	bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 8 : 6;
 	r = malloc(count * 3, M_DEVBUF, M_WAITOK);
@@ -1582,8 +1631,6 @@ set_palette(video_adapter_t *adp, int ba
 		return (1);
 	if (!VESA_MODE(adp->va_mode))
 		return (1);
-	if ((adp->va_info.vi_flags & V_INFO_NONVGA) == 0)
-		return (1);
 
 	bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 8 : 6;
 	r = malloc(count * 3, M_DEVBUF, M_WAITOK);

Modified: stable/8/sys/dev/fb/vga.c
==============================================================================
--- stable/8/sys/dev/fb/vga.c	Wed Mar 31 15:39:46 2010	(r205982)
+++ stable/8/sys/dev/fb/vga.c	Wed Mar 31 15:45:11 2010	(r205983)
@@ -1979,6 +1979,7 @@ vga_show_font(video_adapter_t *adp, int 
 static int
 vga_save_palette(video_adapter_t *adp, u_char *palette)
 {
+    int bits;
     int i;
 
     prologue(adp, V_ADP_PALETTE, ENODEV);
@@ -1988,8 +1989,9 @@ vga_save_palette(video_adapter_t *adp, u
      * VGA has 6 bit DAC .
      */
     outb(PALRADR, 0x00);
+    bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 0 : 2;
     for (i = 0; i < 256*3; ++i)
-	palette[i] = inb(PALDATA) << 2; 
+	palette[i] = inb(PALDATA) << bits; 
     inb(adp->va_crtc_addr + 6);	/* reset flip/flop */
     return 0;
 }
@@ -1998,15 +2000,17 @@ static int
 vga_save_palette2(video_adapter_t *adp, int base, int count,
 		  u_char *r, u_char *g, u_char *b)
 {
+    int bits;
     int i;
 
     prologue(adp, V_ADP_PALETTE, ENODEV);
 
     outb(PALRADR, base);
+    bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 0 : 2;
     for (i = 0; i < count; ++i) {
-	r[i] = inb(PALDATA) << 2; 
-	g[i] = inb(PALDATA) << 2; 
-	b[i] = inb(PALDATA) << 2; 
+	r[i] = inb(PALDATA) << bits; 
+	g[i] = inb(PALDATA) << bits; 
+	b[i] = inb(PALDATA) << bits;
     }
     inb(adp->va_crtc_addr + 6);		/* reset flip/flop */
     return 0;
@@ -2021,14 +2025,16 @@ vga_save_palette2(video_adapter_t *adp, 
 static int
 vga_load_palette(video_adapter_t *adp, u_char *palette)
 {
+    int bits;
     int i;
 
     prologue(adp, V_ADP_PALETTE, ENODEV);
 
     outb(PIXMASK, 0xff);		/* no pixelmask */
     outb(PALWADR, 0x00);
+    bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 0 : 2;
     for (i = 0; i < 256*3; ++i)
-	outb(PALDATA, palette[i] >> 2);
+	outb(PALDATA, palette[i] >> bits);
     inb(adp->va_crtc_addr + 6);	/* reset flip/flop */
     outb(ATC, 0x20);			/* enable palette */
     return 0;
@@ -2038,16 +2044,18 @@ static int
 vga_load_palette2(video_adapter_t *adp, int base, int count,
 		  u_char *r, u_char *g, u_char *b)
 {
+    int bits;
     int i;
 
     prologue(adp, V_ADP_PALETTE, ENODEV);
 
     outb(PIXMASK, 0xff);		/* no pixelmask */
     outb(PALWADR, base);
+    bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 0 : 2;
     for (i = 0; i < count; ++i) {
-	outb(PALDATA, r[i] >> 2);
-	outb(PALDATA, g[i] >> 2);
-	outb(PALDATA, b[i] >> 2);
+	outb(PALDATA, r[i] >> bits);
+	outb(PALDATA, g[i] >> bits);
+	outb(PALDATA, b[i] >> bits);
     }
     inb(adp->va_crtc_addr + 6);		/* reset flip/flop */
     outb(ATC, 0x20);			/* enable palette */


More information about the svn-src-stable-8 mailing list