lkml.org 
[lkml]   [1998]   [Aug]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[patch] vesafb panning: scrollback support and nice speedup

Hi !

Here is a patch for vesafb (against 2.1.115pre1). Changes:

* automatically adds a mtrr entry for the frame buffer
* uses the vesa protected mode interface for panning. This provides
scrollback support and boosts performance. time for "cat 64k-file"
goes from 10 sec down to 1.5 sec. This is disabled by default,
can be enabled by "video=vesa:ypan".
* "video=vesa:ywrap" enables ywrap. The poor man's cat benchmark takes
0.5 sec with this one, but gives a "black hole" at the end of video
memory for me. Seems my gfx board can't do wrap-around...

I've tested it only with a matrox mystique, 4MB, 1024x768x8.

Gerd

--------------------------------------------------------------------
diff -urN kernel/2.1.115pre1/Documentation/fb/vesafb.txt linux/Documentation/fb/vesafb.txt
--- kernel/2.1.115pre1/Documentation/fb/vesafb.txt Thu Jul 30 23:04:01 1998
+++ linux/Documentation/fb/vesafb.txt Thu Aug 6 23:17:21 1998
@@ -30,11 +30,13 @@
==============

Switching modes is done using the vga=... boot parameter. Read
-Documentation/svga.txt for details. With vesafb both text and
-graphics modes work. Text modes are handled by vgafb, graphic modes
-by the new vesafb.c.
+Documentation/svga.txt for details.

-The graphic modes are not in the list which you get if you boot with
+You should compile in both vgacon (for text mode) and vesafb (for
+graphics mode). Which of them takes over the console depends on
+whenever the specified mode is text or graphics.
+
+The graphic modes are NOT in the list which you get if you boot with
vga=ask and hit return. Here are some mode numbers:

| 640x480 800x600 1024x768
@@ -44,23 +46,30 @@
64k | 0x111 0x114 0x117
16M | 0x112 0x115 0x118

-Note 1: this are the VESA mode numbers. The video mode select code
- expects 0x200 + VESA mode number.
-Note 2: lilo can't handle hex, for booting with "vga=??" you have to
- transform the numbers to decimal.
+This are the VESA mode numbers. The video mode select code expects
+0x200 + VESA mode number. Therefore you have to enter "305" at the
+"vga=ask" prompt to boot into 1024x768x8.
+
+If this does'nt work, this might be becauce your BIOS does not support
+linear framebuffers or becauce it does'nt support this mode at all.
+Even if your board does, it might be the BIOS does not. VESA BIOS
+Extentions v2.0 are required, 1.2 is NOT sufficient. You'll get a
+"bad mode number" message if something goes wrong.
+
+Note: LILO can't handle hex, for booting directly with "vga=mode-number"
+ you have to transform the numbers to decimal.


Speed it up!
============

-Check /usr/src/linux/Documentation/mtrr.txt, enabling write-combining
-for the framebuffer memory gives a performance boost.
-
-There are two ways to do console scrolling: redraw the screen
-completely, or by copying around the video memory. You can select one
-of them using the kernel command line: video=vesa:redraw or
-video=vesa:memmove. redraw is the default, becauce this one works
-faster on my box.
+You might want to try "video=vesa:ypan" to enable panning using the
+VESA protected mode interface. This gives scrollback support and
+a performance boost for scrolling.
+
+Use "video=vesa:ywrap" to tell the vesafb driver that your gfx board
+can do wrap-around. This saves a few memcpy() operations and speeds
+up the console even more. But does'nt work with all boards....


Have fun!
diff -urN kernel/2.1.115pre1/arch/i386/boot/video.S linux/arch/i386/boot/video.S
--- kernel/2.1.115pre1/arch/i386/boot/video.S Thu Jul 30 23:03:41 1998
+++ linux/arch/i386/boot/video.S Mon Jul 27 23:09:06 1998
@@ -85,6 +85,9 @@
#define PARAM_LFB_SIZE 0x1c
#define PARAM_LFB_LINELENGTH 0x24
#define PARAM_LFB_COLORS 0x26
+#define PARAM_VESAPM_SEG 0x2e
+#define PARAM_VESAPM_OFF 0x30
+#define PARAM_LFB_PAGES 0x32

! Define DO_STORE according to CONFIG_VIDEO_RETAIN
#ifdef CONFIG_VIDEO_RETAIN
@@ -236,13 +239,14 @@
seg fs
mov [PARAM_LFB_DEPTH],ax

- mov eax,(di+40)
+ mov al,(di+29)
+ mov ah,#0
seg fs
- mov [PARAM_LFB_BASE],eax
+ mov [PARAM_LFB_PAGES],ax

- mov eax,(di+44)
+ mov eax,(di+40)
seg fs
- mov [PARAM_LFB_SIZE],eax
+ mov [PARAM_LFB_BASE],eax

mov eax,(di+31)
seg fs
@@ -251,7 +255,30 @@
mov eax,(di+35)
seg fs
mov [PARAM_LFB_COLORS+4],eax
-
+
+ ! get video mem size
+ lea di,modelist+1024
+ mov ax,#0x4f00
+ int 0x10
+
+ xor eax,eax
+ mov ax,(di+18)
+ seg fs
+ mov [PARAM_LFB_SIZE],eax
+
+ ! get protected mode interface informations
+ mov ax,#0x4f0a
+ xor bx,bx
+ xor di,di
+ int 0x10
+ cmp ax,#0x004f
+ jnz no_pm
+ seg fs
+ mov [PARAM_VESAPM_SEG],es
+ seg fs
+ mov [PARAM_VESAPM_OFF],di
+
+no_pm:
ret

!
diff -urN kernel/2.1.115pre1/drivers/video/vesafb.c linux/drivers/video/vesafb.c
--- kernel/2.1.115pre1/drivers/video/vesafb.c Mon Aug 3 00:33:31 1998
+++ linux/drivers/video/vesafb.c Thu Aug 6 22:59:45 1998
@@ -21,8 +21,10 @@
#include <linux/selection.h>
#include <linux/ioport.h>
#include <linux/init.h>
+#include <linux/config.h>

#include <asm/io.h>
+#include <asm/mtrr.h>

#include "fbcon.h"
#include "fbcon-cfb8.h"
@@ -77,17 +79,14 @@
static struct fb_info fb_info;
static struct { u_char red, green, blue, pad; } palette[256];

-static int inverse = 0;
+static int inverse = 0;
+static int currcon = 0;

-static int currcon = 0;
+static int ypan,ywrap = 0;
+static unsigned short *pmi_base = 0;
+static void (*pmi_start)(void);
+static void (*pmi_pal)(void);

-/* --------------------------------------------------------------------- */
-/* speed up scrolling */
-
-#define USE_REDRAW 1
-#define USE_MEMMOVE 2
-
-static int vesafb_scroll = USE_REDRAW;
static struct display_switch vesafb_sw;

/* --------------------------------------------------------------------- */
@@ -111,8 +110,38 @@
return(0);
}

-static int fb_update_var(int con, struct fb_info *info)
+static int vesafb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
{
+ int offset;
+
+ if (var->xoffset)
+ return -EINVAL;
+ if (ypan && var->yoffset+var->yres > var->yres_virtual)
+ return -EINVAL;
+ if (ywrap && var->yoffset > var->yres_virtual)
+ return -EINVAL;
+
+ /* printk("vesafb: pan: x,y=%d,%d\n",var->xoffset,var->yoffset); */
+ offset = (var->yoffset * video_linelength + var->xoffset) / 4;
+
+ __asm__ __volatile__(
+ "call *(%%edi)"
+ : /* no return value */
+ : "a" (0x4f07), /* EAX */
+ "b" (0), /* EBX */
+ "c" (offset), /* ECX */
+ "d" (offset >> 16), /* EDX */
+ "D" (&pmi_start)); /* EDI */
+ return 0;
+}
+
+static int vesafb_update_var(int con, struct fb_info *info)
+{
+ if (con == currcon && (ywrap || ypan)) {
+ struct fb_var_screeninfo *var = &fb_display[currcon].var;
+ return vesafb_pan_display(var,con,info);
+ }
return 0;
}

@@ -126,9 +155,9 @@
fix->smem_len=video_size;
fix->type = video_type;
fix->visual = video_visual;
- fix->xpanstep=0;
- fix->ypanstep=0;
- fix->ywrapstep=0;
+ fix->xpanstep = 0;
+ fix->ypanstep = ypan ? 1 : 0;
+ fix->ywrapstep = ywrap ? 1 : 0;
fix->line_length=video_linelength;
return 0;
}
@@ -191,7 +220,7 @@
}
memcpy(&vesafb_sw, sw, sizeof(*sw));
display->dispsw = &vesafb_sw;
- if (vesafb_scroll == USE_REDRAW) {
+ if (!ypan && !ywrap) {
display->scrollmode = SCROLL_YREDRAW;
vesafb_sw.bmove = fbcon_redraw_bmove;
}
@@ -317,13 +346,6 @@
return 0;
}

-static int vesafb_pan_display(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
-{
- /* no panning */
- return -EINVAL;
-}
-
static int vesafb_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg, int con,
struct fb_info *info)
@@ -360,9 +382,11 @@
if (! strcmp(this_opt, "inverse"))
inverse=1;
else if (! strcmp(this_opt, "redraw"))
- vesafb_scroll = USE_REDRAW;
- else if (! strcmp(this_opt, "memmove"))
- vesafb_scroll = USE_MEMMOVE;
+ ywrap=0,ypan=0;
+ else if (! strcmp(this_opt, "ypan"))
+ ywrap=0,ypan=1;
+ else if (! strcmp(this_opt, "ywrap"))
+ ywrap=1,ypan=0;
else if (!strncmp(this_opt, "font:", 5))
strcpy(fb_info.fontname, this_opt+5);
}
@@ -378,6 +402,7 @@
currcon = con;
/* Install new colormap */
do_install_cmap(con, info);
+ vesafb_update_var(con,info);
return 0;
}

@@ -400,24 +425,61 @@
video_width = screen_info.lfb_width;
video_height = screen_info.lfb_height;
video_linelength = screen_info.lfb_linelength;
- video_size = video_linelength * video_height /* screen_info.lfb_size */;
+ video_size = screen_info.lfb_size * 65536;
video_visual = (video_bpp == 8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
video_vbase = ioremap((unsigned long)video_base, video_size);

- printk("vesafb: %dx%dx%d, linelength=%d\n",
- video_width, video_height, video_bpp, video_linelength);
- printk("vesafb: framebuffer at 0x%p, mapped to 0x%p, size %d\n",
- video_base, video_vbase, video_size);
- if (vesafb_scroll == USE_REDRAW) printk("vesafb: scrolling=redraw\n");
- if (vesafb_scroll == USE_MEMMOVE) printk("vesafb: scrolling=memmove\n");
-
+ printk("vesafb: framebuffer at 0x%p, mapped to 0x%p, size %dk\n",
+ video_base, video_vbase, video_size/1024);
+ printk("vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
+ video_width, video_height, video_bpp, video_linelength, screen_info.pages);
+
+ if (screen_info.vesapm_seg) {
+ printk("vesafb: protected mode interface info at %04x:%04x\n",
+ screen_info.vesapm_seg,screen_info.vesapm_off);
+ }
+ if (screen_info.vesapm_seg < 0xc000)
+ ywrap = ypan = 0; /* not available or some DOS TSR ... */
+ if (screen_info.pages < 2)
+ ywrap = ypan = 0; /* need at least two screen pages */
+
+ if (ypan || ywrap) {
+ pmi_base = (unsigned short*)(__PAGE_OFFSET+((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
+ pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
+ pmi_pal = (void*)((char*)pmi_base + pmi_base[2]);
+ printk("vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal);
+ printk("vesafb: pmi: ports = ");
+ for (i = pmi_base[3]/2; pmi_base[i] != 0xffff; i++)
+ printk("%x ",pmi_base[i]);
+ printk(", memory = ");
+ for (i++; pmi_base[i] != 0xffff; i+=3)
+ printk("%lx+%x ",
+ ((unsigned long)pmi_base[i]<<16)
+ + pmi_base[i+1], pmi_base[i+3]);
+ printk("\n");
+ }
+
vesafb_defined.xres=video_width;
vesafb_defined.yres=video_height;
vesafb_defined.xres_virtual=video_width;
vesafb_defined.yres_virtual=video_height;
vesafb_defined.bits_per_pixel=video_bpp;

+ if (ypan) {
+ printk("vesafb: scrolling: ypan using protected mode interface\n");
+ vesafb_defined.yres_virtual = video_height * screen_info.pages;
+ } else if (ywrap) {
+ printk("vesafb: scrolling: ywrap using protected mode interface\n");
+#if 0
+ vesafb_defined.yres_virtual = video_height * screen_info.pages; /* available pages */
+#else
+ vesafb_defined.yres_virtual = video_size / video_linelength; /* whole video memory */
+#endif
+ } else {
+ printk("vesafb: scrolling: redraw\n");
+ }
+
if (video_bpp > 8) {
vesafb_defined.red.offset = screen_info.red_pos;
vesafb_defined.red.length = screen_info.red_size;
@@ -451,6 +513,9 @@
video_cmap_len = 256;
}
request_region(0x3c0, 32, "vga+");
+#ifdef CONFIG_MTRR
+ mtrr_add((unsigned long)video_base, video_size, MTRR_TYPE_WRCOMB, 1);
+#endif

strcpy(fb_info.modename, "VESA VGA");
fb_info.changevar = NULL;
@@ -458,7 +523,7 @@
fb_info.fbops = &vesafb_ops;
fb_info.disp=&disp;
fb_info.switch_con=&vesafb_switch;
- fb_info.updatevar=&fb_update_var;
+ fb_info.updatevar=&vesafb_update_var;
fb_info.blank=&vesafb_blank;
vesafb_set_disp(-1);

diff -urN kernel/2.1.115pre1/include/linux/tty.h linux/include/linux/tty.h
--- kernel/2.1.115pre1/include/linux/tty.h Thu Jul 30 23:03:55 1998
+++ linux/include/linux/tty.h Tue Aug 4 23:24:10 1998
@@ -69,7 +69,10 @@
unsigned char blue_pos; /* 0x2b */
unsigned char rsvd_size; /* 0x2c */
unsigned char rsvd_pos; /* 0x2d */
- /* 0x2e -- 0x3f reserved for future expansion */
+ unsigned short vesapm_seg; /* 0x2e */
+ unsigned short vesapm_off; /* 0x30 */
+ unsigned short pages; /* 0x32 */
+ /* 0x34 -- 0x3f reserved for future expansion */
};

extern struct screen_info screen_info;


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html

\
 
 \ /
  Last update: 2005-03-22 13:43    [W:0.054 / U:0.412 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site