📄 vesafb.c
字号:
/* * framebuffer driver for VBE 2.0 compliant graphic boards * * switching to graphics mode happens at boot time (while * running in real mode, see arch/i386/boot/video.S). * * (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> * */#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/fb.h>#include <linux/console.h>#include <linux/selection.h>#include <linux/ioport.h>#include <linux/init.h>#include <asm/io.h>#include <asm/mtrr.h>#include <video/fbcon.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>#include <video/fbcon-cfb24.h>#include <video/fbcon-cfb32.h>#include <video/fbcon-mac.h>#define dac_reg (0x3c8)#define dac_val (0x3c9)/* --------------------------------------------------------------------- *//* * card parameters *//* card */unsigned long video_base; /* physical addr */int video_size;char *video_vbase; /* mapped *//* mode */static int video_bpp;static int video_width;static int video_height;static int video_height_virtual;static int video_type = FB_TYPE_PACKED_PIXELS;static int video_visual;static int video_linelength;static int video_cmap_len;/* --------------------------------------------------------------------- */static struct fb_var_screeninfo vesafb_defined = { 0,0,0,0, /* W,H, W, H (virtual) load xres,xres_virtual*/ 0,0, /* virtual -> visible no offset */ 8, /* depth -> load bits_per_pixel */ 0, /* greyscale ? */ {0,0,0}, /* R */ {0,0,0}, /* G */ {0,0,0}, /* B */ {0,0,0}, /* transparency */ 0, /* standard pixel format */ FB_ACTIVATE_NOW, -1,-1, 0, 0L,0L,0L,0L,0L, 0L,0L,0, /* No sync info */ FB_VMODE_NONINTERLACED, {0,0,0,0,0,0}};static struct display disp;static struct fb_info fb_info;static struct { u_short blue, green, red, pad; } palette[256];static union {#ifdef FBCON_HAS_CFB16 u16 cfb16[16];#endif#ifdef FBCON_HAS_CFB24 u32 cfb24[16];#endif#ifdef FBCON_HAS_CFB32 u32 cfb32[16];#endif} fbcon_cmap;static int inverse = 0;#ifdef __x86_64__static int mtrr = 1;#elsestatic int mtrr = 0;#endifstatic int vram __initdata = 0; /* needed for vram boot option */static int currcon = 0;static int pmi_setpal = 0; /* pmi for palette changes ??? */static int ypan = 0; /* 0..nothing, 1..ypan, 2..ywrap */static unsigned short *pmi_base = 0;static void (*pmi_start)(void);static void (*pmi_pal)(void);static struct display_switch vesafb_sw;/* --------------------------------------------------------------------- */static int vesafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info){#ifdef __i386__ int offset; if (!ypan) return -EINVAL; if (var->xoffset) return -EINVAL; if (var->yoffset > var->yres_virtual) return -EINVAL; if ((ypan==1) && var->yoffset+var->yres > var->yres_virtual) return -EINVAL; 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 */#endif return 0;}static int vesafb_update_var(int con, struct fb_info *info){ if (con == currcon && ypan) { struct fb_var_screeninfo *var = &fb_display[currcon].var; return vesafb_pan_display(var,con,info); } return 0;}static int vesafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){ memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id,"VESA VGA"); fix->smem_start=video_base; fix->smem_len=video_size; fix->type = video_type; fix->visual = video_visual; fix->xpanstep = 0; fix->ypanstep = ypan ? 1 : 0; fix->ywrapstep = (ypan>1) ? 1 : 0; fix->line_length=video_linelength; return 0;}static int vesafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ if(con==-1) memcpy(var, &vesafb_defined, sizeof(struct fb_var_screeninfo)); else *var=fb_display[con].var; return 0;}static void vesafb_set_disp(int con){ struct fb_fix_screeninfo fix; struct display *display; struct display_switch *sw; if (con >= 0) display = &fb_display[con]; else display = &disp; /* used during initialization */ vesafb_get_fix(&fix, con, 0); memset(display, 0, sizeof(struct display)); display->screen_base = video_vbase; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; display->ypanstep = fix.ypanstep; display->ywrapstep = fix.ywrapstep; display->line_length = fix.line_length; display->next_line = fix.line_length; display->can_soft_blank = 0; display->inverse = inverse; vesafb_get_var(&display->var, -1, &fb_info); switch (video_bpp) {#ifdef FBCON_HAS_CFB8 case 8: sw = &fbcon_cfb8; break;#endif#ifdef FBCON_HAS_CFB16 case 15: case 16: sw = &fbcon_cfb16; display->dispsw_data = fbcon_cmap.cfb16; break;#endif#ifdef FBCON_HAS_CFB24 case 24: sw = &fbcon_cfb24; display->dispsw_data = fbcon_cmap.cfb24; break;#endif#ifdef FBCON_HAS_CFB32 case 32: sw = &fbcon_cfb32; display->dispsw_data = fbcon_cmap.cfb32; break;#endif default:#ifdef FBCON_HAS_MAC sw = &fbcon_mac; break;#else sw = &fbcon_dummy; return;#endif } memcpy(&vesafb_sw, sw, sizeof(*sw)); display->dispsw = &vesafb_sw; if (!ypan) { display->scrollmode = SCROLL_YREDRAW; vesafb_sw.bmove = fbcon_redraw_bmove; }}static int vesafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ static int first = 1; if (var->xres != vesafb_defined.xres || var->yres != vesafb_defined.yres || var->xres_virtual != vesafb_defined.xres_virtual || var->yres_virtual > video_height_virtual || var->yres_virtual < video_height || var->xoffset || var->bits_per_pixel != vesafb_defined.bits_per_pixel || var->nonstd) { if (first) { printk(KERN_ERR "Vesafb does not support changing the video mode\n"); first = 0; } return -EINVAL; } if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST) return 0; if (ypan) { if (vesafb_defined.yres_virtual != var->yres_virtual) { vesafb_defined.yres_virtual = var->yres_virtual; if (con != -1) { fb_display[con].var = vesafb_defined; info->changevar(con); } } if (var->yoffset != vesafb_defined.yoffset) return vesafb_pan_display(var,con,info); return 0; } if (var->yoffset) return -EINVAL; return 0;}static int vesa_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *fb_info){ /* * Read a single color register and split it into colors/transparent. * Return != 0 for invalid regno. */ if (regno >= video_cmap_len) return 1; *red = palette[regno].red; *green = palette[regno].green; *blue = palette[regno].blue; *transp = 0; return 0;}#ifdef FBCON_HAS_CFB8static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned blue){#ifdef i386 struct { u_char blue, green, red, pad; } entry; if (pmi_setpal) { entry.red = red >> 10; entry.green = green >> 10; entry.blue = blue >> 10; entry.pad = 0; __asm__ __volatile__( "call *(%%esi)" : /* no return value */ : "a" (0x4f09), /* EAX */ "b" (0), /* EBX */ "c" (1), /* ECX */ "d" (regno), /* EDX */ "D" (&entry), /* EDI */ "S" (&pmi_pal)); /* ESI */ } else { /* without protected mode interface, try VGA registers... */ outb_p(regno, dac_reg); outb_p(red >> 10, dac_val); outb_p(green >> 10, dac_val); outb_p(blue >> 10, dac_val); }#endif}#endifstatic int vesa_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fb_info){ /* * Set a single color register. The values supplied are * already rounded down to the hardware's capabilities * (according to the entries in the `var' structure). Return * != 0 for invalid regno. */ if (regno >= video_cmap_len) return 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -