📄 vga16fb.c
字号:
} /* Wait for screen to stabilize. */ mdelay(50); outb(0x01, VGA_SEQ_I); outb(par->seq[1], VGA_SEQ_D); inb(VGA_IS1_RC); outb(0x20, VGA_ATT_IW); return 0;}static int vga16fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb){ struct vga16fb_info *info = (struct vga16fb_info*)fb; struct vga16fb_par par; struct display *display; int err; if (con < 0) display = fb->disp; else display = fb_display + con; if ((err = vga16fb_decode_var(var, &par, info)) != 0) return err; vga16fb_encode_var(var, &par, info); if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST) return 0; if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { u32 oldxres, oldyres, oldvxres, oldvyres, oldbpp; oldxres = display->var.xres; oldyres = display->var.yres; oldvxres = display->var.xres_virtual; oldvyres = display->var.yres_virtual; oldbpp = display->var.bits_per_pixel; display->var = *var; if (oldxres != var->xres || oldyres != var->yres || oldvxres != var->xres_virtual || oldvyres != var->yres_virtual || oldbpp != var->bits_per_pixel) { vga16fb_set_disp(con, info); if (info->fb_info.changevar) info->fb_info.changevar(con); } if (con == currcon) vga16fb_set_par(&par, info); } return 0;}static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue){ static unsigned char map[] = { 000, 001, 010, 011 }; int val; val = map[red>>14] | ((map[green>>14]) << 1) | ((map[blue>>14]) << 2); inb_p(0x3DA); /* ! 0x3BA */ outb_p(regno, 0x3C0); outb_p(val, 0x3C0); inb_p(0x3DA); /* some clones need it */ outb_p(0x20, 0x3C0); /* unblank screen */}static int vga16_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 >= 16) return 1; *red = palette[regno].red; *green = palette[regno].green; *blue = palette[regno].blue; *transp = 0; return 0;}static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue){ outb(regno, dac_reg); outb(red >> 10, dac_val); outb(green >> 10, dac_val); outb(blue >> 10, dac_val);}static int vga16_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fb_info){ int gray; /* * 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 >= 16) return 1; palette[regno].red = red; palette[regno].green = green; palette[regno].blue = blue; if (currcon < 0) gray = disp.var.grayscale; else gray = fb_display[currcon].var.grayscale; if (gray) { /* gray = 0.30*R + 0.59*G + 0.11*B */ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; } if (((struct vga16fb_info *) fb_info)->isVGA) vga16_setpalette(regno,red,green,blue); else ega16_setpalette(regno,red,green,blue); return 0;}static void do_install_cmap(int con, struct fb_info *info){ if (con != currcon) return; if (fb_display[con].cmap.len) fb_set_cmap(&fb_display[con].cmap, 1, vga16_setcolreg, info); else fb_set_cmap(fb_default_cmap(16), 1, vga16_setcolreg, info);}static int vga16fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ if (con == currcon) /* current console? */ return fb_get_cmap(cmap, kspc, vga16_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else fb_copy_cmap(fb_default_cmap(16), cmap, kspc ? 0 : 2); return 0;}static int vga16fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ int err; if (!fb_display[con].cmap.len) { /* no colormap allocated? */ err = fb_alloc_cmap(&fb_display[con].cmap,16,0); if (err) return err; } if (con == currcon) /* current console? */ return fb_set_cmap(cmap, kspc, vga16_setcolreg, info); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0;}static int vga16fb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info) { if (var->xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual || var->yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual) return -EINVAL; if (con == currcon) vga16fb_pan_var(info, var); fb_display[con].var.xoffset = var->xoffset; fb_display[con].var.yoffset = var->yoffset; fb_display[con].var.vmode &= ~FB_VMODE_YWRAP; return 0;}static struct fb_ops vga16fb_ops = { owner: THIS_MODULE, fb_get_fix: vga16fb_get_fix, fb_get_var: vga16fb_get_var, fb_set_var: vga16fb_set_var, fb_get_cmap: vga16fb_get_cmap, fb_set_cmap: vga16fb_set_cmap, fb_pan_display: vga16fb_pan_display,};int vga16fb_setup(char *options){ char *this_opt; vga16fb.fb_info.fontname[0] = '\0'; if (!options || !*options) return 0; while ((this_opt = strsep(&options, ",")) != NULL) { if (!*this_opt) continue; if (!strncmp(this_opt, "font:", 5)) strcpy(vga16fb.fb_info.fontname, this_opt+5); } return 0;}static int vga16fb_switch(int con, struct fb_info *fb){ struct vga16fb_par par; struct vga16fb_info *info = (struct vga16fb_info*)fb; /* Do we have to save the colormap? */ if (fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, 1, vga16_getcolreg, fb); currcon = con; vga16fb_decode_var(&fb_display[con].var, &par, info); vga16fb_set_par(&par, info); vga16fb_set_disp(con, info); /* Install new colormap */ do_install_cmap(con, fb);/* vga16fb_update_var(con, fb); */ return 1;}/* The following VESA blanking code is taken from vgacon.c. The VGA blanking code was originally by Huang shi chao, and modified by Christoph Rimek (chrimek@toppoint.de) and todd j. derr (tjd@barefoot.org) for Linux. */#define attrib_port 0x3c0#define seq_port_reg 0x3c4#define seq_port_val 0x3c5#define gr_port_reg 0x3ce#define gr_port_val 0x3cf#define video_misc_rd 0x3cc#define video_misc_wr 0x3c2#define vga_video_port_reg 0x3d4#define vga_video_port_val 0x3d5static void vga_vesa_blank(struct vga16fb_info *info, int mode){ unsigned char SeqCtrlIndex; unsigned char CrtCtrlIndex; cli(); SeqCtrlIndex = inb_p(seq_port_reg); CrtCtrlIndex = inb_p(vga_video_port_reg); /* save original values of VGA controller registers */ if(!info->vesa_blanked) { info->vga_state.CrtMiscIO = inb_p(video_misc_rd); sti(); outb_p(0x00,vga_video_port_reg); /* HorizontalTotal */ info->vga_state.HorizontalTotal = inb_p(vga_video_port_val); outb_p(0x01,vga_video_port_reg); /* HorizDisplayEnd */ info->vga_state.HorizDisplayEnd = inb_p(vga_video_port_val); outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */ info->vga_state.StartHorizRetrace = inb_p(vga_video_port_val); outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */ info->vga_state.EndHorizRetrace = inb_p(vga_video_port_val); outb_p(0x07,vga_video_port_reg); /* Overflow */ info->vga_state.Overflow = inb_p(vga_video_port_val); outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */ info->vga_state.StartVertRetrace = inb_p(vga_video_port_val); outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */ info->vga_state.EndVertRetrace = inb_p(vga_video_port_val); outb_p(0x17,vga_video_port_reg); /* ModeControl */ info->vga_state.ModeControl = inb_p(vga_video_port_val); outb_p(0x01,seq_port_reg); /* ClockingMode */ info->vga_state.ClockingMode = inb_p(seq_port_val); } /* assure that video is enabled */ /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ cli(); outb_p(0x01,seq_port_reg); outb_p(info->vga_state.ClockingMode | 0x20,seq_port_val); /* test for vertical retrace in process.... */ if ((info->vga_state.CrtMiscIO & 0x80) == 0x80) outb_p(info->vga_state.CrtMiscIO & 0xef,video_misc_wr); /* * Set <End of vertical retrace> to minimum (0) and * <Start of vertical Retrace> to maximum (incl. overflow) * Result: turn off vertical sync (VSync) pulse. */ if (mode & VESA_VSYNC_SUSPEND) { outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */ outb_p(0xff,vga_video_port_val); /* maximum value */ outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */ outb_p(0x40,vga_video_port_val); /* minimum (bits 0..3) */ outb_p(0x07,vga_video_port_reg); /* Overflow */ outb_p(info->vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */ } if (mode & VESA_HSYNC_SUSPEND) { /* * Set <End of horizontal retrace> to minimum (0) and * <Start of horizontal Retrace> to maximum * Result: turn off horizontal sync (HSync) pulse. */ outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */ outb_p(0xff,vga_video_port_val); /* maximum */ outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */ outb_p(0x00,vga_video_port_val); /* minimum (0) */ } /* restore both index registers */ outb_p(SeqCtrlIndex,seq_port_reg); outb_p(CrtCtrlIndex,vga_video_port_reg); sti();}static void vga_vesa_unblank(struct vga16fb_info *info){ unsigned char SeqCtrlIndex; unsigned char CrtCtrlIndex; cli(); SeqCtrlIndex = inb_p(seq_port_reg); CrtCtrlIndex = inb_p(vga_video_port_reg); /* restore original values of VGA controller registers */ outb_p(info->vga_state.CrtMiscIO,video_misc_wr); outb_p(0x00,vga_video_port_reg); /* HorizontalTotal */ outb_p(info->vga_state.HorizontalTotal,vga_video_port_val); outb_p(0x01,vga_video_port_reg); /* HorizDisplayEnd */ outb_p(info->vga_state.HorizDisplayEnd,vga_video_port_val); outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */ outb_p(info->vga_state.StartHorizRetrace,vga_video_port_val); outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */ outb_p(info->vga_state.EndHorizRetrace,vga_video_port_val); outb_p(0x07,vga_video_port_reg); /* Overflow */ outb_p(info->vga_state.Overflow,vga_video_port_val); outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */ outb_p(info->vga_state.StartVertRetrace,vga_video_port_val); outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */ outb_p(info->vga_state.EndVertRetrace,vga_video_port_val); outb_p(0x17,vga_video_port_reg); /* ModeControl */ outb_p(info->vga_state.ModeControl,vga_video_port_val); outb_p(0x01,seq_port_reg); /* ClockingMode */ outb_p(info->vga_state.ClockingMode,seq_port_val); /* restore index/control registers */ outb_p(SeqCtrlIndex,seq_port_reg); outb_p(CrtCtrlIndex,vga_video_port_reg); sti();}static void vga_pal_blank(void){ int i; for (i=0; i<16; i++) { outb_p (i, dac_reg) ; outb_p (0, dac_val) ; outb_p (0, dac_val) ; outb_p (0, dac_val) ; }}/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */static void vga16fb_blank(int blank, struct fb_info *fb_info){ struct vga16fb_info *info = (struct vga16fb_info*)fb_info; switch (blank) { case 0: /* Unblank */ if (info->vesa_blanked) { vga_vesa_unblank(info); info->vesa_blanked = 0; } if (info->palette_blanked) { do_install_cmap(currcon, fb_info); info->palette_blanked = 0; } break; case 1: /* blank */ vga_pal_blank(); info->palette_blanked = 1; break; default: /* VESA blanking */ vga_vesa_blank(info, blank-1); info->vesa_blanked = 1; break; }}int __init vga16fb_init(void){ int i,j; printk(KERN_DEBUG "vga16fb: initializing\n"); /* XXX share VGA_FB_PHYS region with vgacon */ vga16fb.video_vbase = ioremap(VGA_FB_PHYS, VGA_FB_PHYS_LEN); if (!vga16fb.video_vbase) { printk(KERN_ERR "vga16fb: unable to map device\n"); return -ENOMEM; } printk(KERN_INFO "vga16fb: mapped to 0x%p\n", vga16fb.video_vbase); vga16fb.isVGA = ORIG_VIDEO_ISVGA; vga16fb.palette_blanked = 0; vga16fb.vesa_blanked = 0; i = vga16fb.isVGA? 6 : 2; vga16fb_defined.red.length = i; vga16fb_defined.green.length = i; vga16fb_defined.blue.length = i; for(i = 0; i < 16; i++) { j = color_table[i]; palette[i].red = default_red[j]; palette[i].green = default_grn[j]; palette[i].blue = default_blu[j]; } /* XXX share VGA I/O region with vgacon and others */ disp.var = vga16fb_defined; /* name should not depend on EGA/VGA */ strcpy(vga16fb.fb_info.modename, "VGA16 VGA"); vga16fb.fb_info.changevar = NULL; vga16fb.fb_info.node = -1; vga16fb.fb_info.fbops = &vga16fb_ops; vga16fb.fb_info.disp=&disp; vga16fb.fb_info.switch_con=&vga16fb_switch; vga16fb.fb_info.updatevar=&vga16fb_update_var; vga16fb.fb_info.blank=&vga16fb_blank; vga16fb.fb_info.flags=FBINFO_FLAG_DEFAULT; vga16fb_set_disp(-1, &vga16fb); if (register_framebuffer(&vga16fb.fb_info)<0) { iounmap(vga16fb.video_vbase); return -EINVAL; } printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(vga16fb.fb_info.node), vga16fb.fb_info.modename); return 0;}static void __exit vga16fb_exit(void){ unregister_framebuffer(&vga16fb.fb_info); iounmap(vga16fb.video_vbase); /* XXX unshare VGA regions */}#ifdef MODULEMODULE_LICENSE("GPL");module_init(vga16fb_init);#endifmodule_exit(vga16fb_exit);/* * Overrides for Emacs so that we follow Linus's tabbing style. * --------------------------------------------------------------------------- * Local variables: * c-basic-offset: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -