Messages in this thread Patch in this message | | | Date | Fri, 7 Aug 1998 00:08:36 +0200 (MEST) | From | Gerd Knorr <> | 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
| |