📄 vga16fb.c
字号:
par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF; par->crtc[VGA_CRTC_OVERFLOW] = r7; par->vss = 0x00; /* 3DA */ par->misc = 0xE3; /* enable CPU, ports 0x3Dx, positive sync */ if (var->sync & FB_SYNC_HOR_HIGH_ACT) par->misc &= ~0x40; if (var->sync & FB_SYNC_VERT_HIGH_ACT) par->misc &= ~0x80; par->mode = mode; if (mode & MODE_8BPP) /* pixel clock == vga clock / 2 */ vga16fb_clock_chip(par, var->pixclock, info, 1, 2); else /* pixel clock == vga clock */ vga16fb_clock_chip(par, var->pixclock, info, 1, 1); var->red.offset = var->green.offset = var->blue.offset = var->transp.offset = 0; var->red.length = var->green.length = var->blue.length = (par->isVGA) ? 6 : 2; var->transp.length = 0; var->activate = FB_ACTIVATE_NOW; var->height = -1; var->width = -1; var->accel_flags = 0; return 0;}#undef FAILstatic int vga16fb_set_par(struct fb_info *info){ struct vga16fb_par *par = info->par; u8 gdc[VGA_GFX_C]; u8 seq[VGA_SEQ_C]; u8 atc[VGA_ATT_C]; int fh, i; seq[VGA_SEQ_CLOCK_MODE] = 0x01 | par->clkdiv; if (par->mode & MODE_TEXT) seq[VGA_SEQ_PLANE_WRITE] = 0x03; else seq[VGA_SEQ_PLANE_WRITE] = 0x0F; seq[VGA_SEQ_CHARACTER_MAP] = 0x00; if (par->mode & MODE_TEXT) seq[VGA_SEQ_MEMORY_MODE] = 0x03; else if (par->mode & MODE_SKIP4) seq[VGA_SEQ_MEMORY_MODE] = 0x0E; else seq[VGA_SEQ_MEMORY_MODE] = 0x06; gdc[VGA_GFX_SR_VALUE] = 0x00; gdc[VGA_GFX_SR_ENABLE] = 0x00; gdc[VGA_GFX_COMPARE_VALUE] = 0x00; gdc[VGA_GFX_DATA_ROTATE] = 0x00; gdc[VGA_GFX_PLANE_READ] = 0; if (par->mode & MODE_TEXT) { gdc[VGA_GFX_MODE] = 0x10; gdc[VGA_GFX_MISC] = 0x06; } else { if (par->mode & MODE_CFB) gdc[VGA_GFX_MODE] = 0x40; else gdc[VGA_GFX_MODE] = 0x00; gdc[VGA_GFX_MISC] = 0x05; } gdc[VGA_GFX_COMPARE_MASK] = 0x0F; gdc[VGA_GFX_BIT_MASK] = 0xFF; for (i = 0x00; i < 0x10; i++) atc[i] = i; if (par->mode & MODE_TEXT) atc[VGA_ATC_MODE] = 0x04; else if (par->mode & MODE_8BPP) atc[VGA_ATC_MODE] = 0x41; else atc[VGA_ATC_MODE] = 0x81; atc[VGA_ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */ atc[VGA_ATC_PLANE_ENABLE] = 0x0F; if (par->mode & MODE_8BPP) atc[VGA_ATC_PEL] = (info->var.xoffset & 3) << 1; else atc[VGA_ATC_PEL] = info->var.xoffset & 7; atc[VGA_ATC_COLOR_PAGE] = 0x00; if (par->mode & MODE_TEXT) { fh = 16; // FIXME !!! Fudge font height. par->crtc[VGA_CRTC_MAX_SCAN] = (par->crtc[VGA_CRTC_MAX_SCAN] & ~0x1F) | (fh - 1); } vga_io_w(VGA_MIS_W, vga_io_r(VGA_MIS_R) | 0x01); /* Enable graphics register modification */ if (!par->isVGA) { vga_io_w(EGA_GFX_E0, 0x00); vga_io_w(EGA_GFX_E1, 0x01); } /* update misc output register */ vga_io_w(VGA_MIS_W, par->misc); /* synchronous reset on */ vga_io_wseq(0x00, 0x01); if (par->isVGA) vga_io_w(VGA_PEL_MSK, par->pel_msk); /* write sequencer registers */ vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE] | 0x20); for (i = 2; i < VGA_SEQ_C; i++) { vga_io_wseq(i, seq[i]); } /* synchronous reset off */ vga_io_wseq(0x00, 0x03); /* deprotect CRT registers 0-7 */ vga_io_wcrt(VGA_CRTC_V_SYNC_END, par->crtc[VGA_CRTC_V_SYNC_END]); /* write CRT registers */ for (i = 0; i < VGA_CRTC_REGS; i++) { vga_io_wcrt(i, par->crtc[i]); } /* write graphics controller registers */ for (i = 0; i < VGA_GFX_C; i++) { vga_io_wgfx(i, gdc[i]); } /* write attribute controller registers */ for (i = 0; i < VGA_ATT_C; i++) { vga_io_r(VGA_IS1_RC); /* reset flip-flop */ vga_io_wattr(i, atc[i]); } /* Wait for screen to stabilize. */ mdelay(50); vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE]); vga_io_r(VGA_IS1_RC); vga_io_w(VGA_ATT_IW, 0x20); vga16fb_update_fix(info); return 0;}static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue){ static const unsigned char map[] = { 000, 001, 010, 011 }; int val; if (regno >= 16) return; val = map[red>>14] | ((map[green>>14]) << 1) | ((map[blue>>14]) << 2); vga_io_r(VGA_IS1_RC); /* ! 0x3BA */ vga_io_wattr(regno, val); vga_io_r(VGA_IS1_RC); /* some clones need it */ vga_io_w(VGA_ATT_IW, 0x20); /* unblank screen */}static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue){ outb(regno, VGA_PEL_IW); outb(red >> 10, VGA_PEL_D); outb(green >> 10, VGA_PEL_D); outb(blue >> 10, VGA_PEL_D);}static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ struct vga16fb_par *par = info->par; 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 >= 256) return 1; gray = info->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 (par->isVGA) vga16_setpalette(regno,red,green,blue); else ega16_setpalette(regno,red,green,blue); return 0;}static int vga16fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { vga16fb_pan_var(info, var); return 0;}/* 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. */static void vga_vesa_blank(struct vga16fb_par *par, int mode){ unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I); unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC); /* save original values of VGA controller registers */ if(!par->vesa_blanked) { par->vga_state.CrtMiscIO = vga_io_r(VGA_MIS_R); //sti(); par->vga_state.HorizontalTotal = vga_io_rcrt(0x00); /* HorizontalTotal */ par->vga_state.HorizDisplayEnd = vga_io_rcrt(0x01); /* HorizDisplayEnd */ par->vga_state.StartHorizRetrace = vga_io_rcrt(0x04); /* StartHorizRetrace */ par->vga_state.EndHorizRetrace = vga_io_rcrt(0x05); /* EndHorizRetrace */ par->vga_state.Overflow = vga_io_rcrt(0x07); /* Overflow */ par->vga_state.StartVertRetrace = vga_io_rcrt(0x10); /* StartVertRetrace */ par->vga_state.EndVertRetrace = vga_io_rcrt(0x11); /* EndVertRetrace */ par->vga_state.ModeControl = vga_io_rcrt(0x17); /* ModeControl */ par->vga_state.ClockingMode = vga_io_rseq(0x01); /* ClockingMode */ } /* assure that video is enabled */ /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20); /* test for vertical retrace in process.... */ if ((par->vga_state.CrtMiscIO & 0x80) == 0x80) vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO & 0xef); /* * 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 & FB_BLANK_VSYNC_SUSPEND) { vga_io_wcrt(VGA_CRTC_V_SYNC_START, 0xff); vga_io_wcrt(VGA_CRTC_V_SYNC_END, 0x40); /* bits 9,10 of vert. retrace */ vga_io_wcrt(VGA_CRTC_OVERFLOW, par->vga_state.Overflow | 0x84); } if (mode & FB_BLANK_HSYNC_SUSPEND) { /* * Set <End of horizontal retrace> to minimum (0) and * <Start of horizontal Retrace> to maximum * Result: turn off horizontal sync (HSync) pulse. */ vga_io_wcrt(VGA_CRTC_H_SYNC_START, 0xff); vga_io_wcrt(VGA_CRTC_H_SYNC_END, 0x00); } /* restore both index registers */ outb_p(SeqCtrlIndex, VGA_SEQ_I); outb_p(CrtCtrlIndex, VGA_CRT_IC);}static void vga_vesa_unblank(struct vga16fb_par *par){ unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I); unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC); /* restore original values of VGA controller registers */ vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO); /* HorizontalTotal */ vga_io_wcrt(0x00, par->vga_state.HorizontalTotal); /* HorizDisplayEnd */ vga_io_wcrt(0x01, par->vga_state.HorizDisplayEnd); /* StartHorizRetrace */ vga_io_wcrt(0x04, par->vga_state.StartHorizRetrace); /* EndHorizRetrace */ vga_io_wcrt(0x05, par->vga_state.EndHorizRetrace); /* Overflow */ vga_io_wcrt(0x07, par->vga_state.Overflow); /* StartVertRetrace */ vga_io_wcrt(0x10, par->vga_state.StartVertRetrace); /* EndVertRetrace */ vga_io_wcrt(0x11, par->vga_state.EndVertRetrace); /* ModeControl */ vga_io_wcrt(0x17, par->vga_state.ModeControl); /* ClockingMode */ vga_io_wseq(0x01, par->vga_state.ClockingMode); /* restore index/control registers */ vga_io_w(VGA_SEQ_I, SeqCtrlIndex); vga_io_w(VGA_CRT_IC, CrtCtrlIndex);}static void vga_pal_blank(void){ int i; for (i=0; i<16; i++) { outb_p(i, VGA_PEL_IW); outb_p(0, VGA_PEL_D); outb_p(0, VGA_PEL_D); outb_p(0, VGA_PEL_D); }}/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */static int vga16fb_blank(int blank, struct fb_info *info){ struct vga16fb_par *par = info->par; switch (blank) { case FB_BLANK_UNBLANK: /* Unblank */ if (par->vesa_blanked) { vga_vesa_unblank(par); par->vesa_blanked = 0; } if (par->palette_blanked) { par->palette_blanked = 0; } break; case FB_BLANK_NORMAL: /* blank */ vga_pal_blank(); par->palette_blanked = 1; break; default: /* VESA blanking */ vga_vesa_blank(par, blank); par->vesa_blanked = 1; break; } return 0;}static void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect){ u32 dx = rect->dx, width = rect->width; char oldindex = getindex(); char oldmode = setmode(0x40); char oldmask = selectmask(); int line_ofs, height; char oldop, oldsr; char __iomem *where; dx /= 4; where = info->screen_base + dx + rect->dy * info->fix.line_length; if (rect->rop == ROP_COPY) { oldop = setop(0); oldsr = setsr(0); width /= 4; line_ofs = info->fix.line_length - width; setmask(0xff); height = rect->height; while (height--) { int x; /* we can do memset... */ for (x = width; x > 0; --x) { writeb(rect->color, where); where++; } where += line_ofs; } } else { char oldcolor = setcolor(0xf); int y; oldop = setop(0x18); oldsr = setsr(0xf); setmask(0x0F); for (y = 0; y < rect->height; y++) { rmw(where); rmw(where+1); where += info->fix.line_length; } setcolor(oldcolor); } setmask(oldmask); setsr(oldsr); setop(oldop); setmode(oldmode); setindex(oldindex);}static void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect){ int x, x2, y2, vxres, vyres, width, height, line_ofs; char __iomem *dst; vxres = info->var.xres_virtual; vyres = info->var.yres_virtual; if (!rect->width || !rect->height || rect->dx > vxres || rect->dy > vyres) return; /* We could use hardware clipping but on many cards you get around * hardware clipping by writing to framebuffer directly. */ x2 = rect->dx + rect->width; y2 = rect->dy + rect->height; x2 = x2 < vxres ? x2 : vxres; y2 = y2 < vyres ? y2 : vyres; width = x2 - rect->dx; switch (info->fix.type) { case FB_TYPE_VGA_PLANES: if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) { height = y2 - rect->dy; width = rect->width/8; line_ofs = info->fix.line_length - width; dst = info->screen_base + (rect->dx/8) + rect->dy * info->fix.line_length; switch (rect->rop) { case ROP_COPY: setmode(0); setop(0); setsr(0xf); setcolor(rect->color); selectmask(); setmask(0xff); while (height--) { for (x = 0; x < width; x++) { writeb(0, dst); dst++; } dst += line_ofs; } break; case ROP_XOR: setmode(0); setop(0x18); setsr(0xf); setcolor(0xf); selectmask(); setmask(0xff); while (height--) { for (x = 0; x < width; x++) { rmw(dst); dst++; } dst += line_ofs; } break; } } else vga_8planes_fillrect(info, rect); break; case FB_TYPE_PACKED_PIXELS: default: cfb_fillrect(info, rect); break; }}static void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area){ char oldindex = getindex(); char oldmode = setmode(0x41); char oldop = setop(0); char oldsr = setsr(0xf); int height, line_ofs, x; u32 sx, dx, width; char __iomem *dest; char __iomem *src; height = area->height; sx = area->sx / 4;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -