fbcon-vga-planes.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:9k
源码类别:
Linux/Unix编程
开发平台:
Unix_Linux
- /*
- * linux/drivers/video/fbcon-vga-planes.c -- Low level frame buffer operations
- * for VGA 4-plane modes
- *
- * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
- * Based on code by Michael Schmitz
- * Based on the old macfb.c 4bpp code by Alan Cox
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details. */
- #include <linux/module.h>
- #include <linux/tty.h>
- #include <linux/console.h>
- #include <linux/string.h>
- #include <linux/fb.h>
- #include <linux/vt_buffer.h>
- #include <asm/io.h>
- #include <video/fbcon.h>
- #include <video/fbcon-vga-planes.h>
- #define GRAPHICS_ADDR_REG 0x3ce /* Graphics address register. */
- #define GRAPHICS_DATA_REG 0x3cf /* Graphics data register. */
- #define SET_RESET_INDEX 0 /* Set/Reset Register index. */
- #define ENABLE_SET_RESET_INDEX 1 /* Enable Set/Reset Register index. */
- #define DATA_ROTATE_INDEX 3 /* Data Rotate Register index. */
- #define GRAPHICS_MODE_INDEX 5 /* Graphics Mode Register index. */
- #define BIT_MASK_INDEX 8 /* Bit Mask Register index. */
- /* The VGA's weird architecture often requires that we read a byte and
- write a byte to the same location. It doesn't matter *what* byte
- we write, however. This is because all the action goes on behind
- the scenes in the VGA's 32-bit latch register, and reading and writing
- video memory just invokes latch behavior.
- To avoid race conditions (is this necessary?), reading and writing
- the memory byte should be done with a single instruction. One
- suitable instruction is the x86 bitwise OR. The following
- read-modify-write routine should optimize to one such bitwise
- OR. */
- static inline void rmw(volatile char *p)
- {
- readb(p);
- writeb(1, p);
- }
- /* Set the Graphics Mode Register. Bits 0-1 are write mode, bit 3 is
- read mode. */
- static inline void setmode(int mode)
- {
- outb(GRAPHICS_MODE_INDEX, GRAPHICS_ADDR_REG);
- outb(mode, GRAPHICS_DATA_REG);
- }
- /* Select the Bit Mask Register. */
- static inline void selectmask(void)
- {
- outb(BIT_MASK_INDEX, GRAPHICS_ADDR_REG);
- }
- /* Set the value of the Bit Mask Register. It must already have been
- selected with selectmask(). */
- static inline void setmask(int mask)
- {
- outb(mask, GRAPHICS_DATA_REG);
- }
- /* Set the Data Rotate Register. Bits 0-2 are rotate count, bits 3-4
- are logical operation (0=NOP, 1=AND, 2=OR, 3=XOR). */
- static inline void setop(int op)
- {
- outb(DATA_ROTATE_INDEX, GRAPHICS_ADDR_REG);
- outb(op, GRAPHICS_DATA_REG);
- }
- /* Set the Enable Set/Reset Register. The code here always uses value
- 0xf for this register. */
- static inline void setsr(int sr)
- {
- outb(ENABLE_SET_RESET_INDEX, GRAPHICS_ADDR_REG);
- outb(sr, GRAPHICS_DATA_REG);
- }
- /* Set the Set/Reset Register. */
- static inline void setcolor(int color)
- {
- outb(SET_RESET_INDEX, GRAPHICS_ADDR_REG);
- outb(color, GRAPHICS_DATA_REG);
- }
- /* Set the value in the Graphics Address Register. */
- static inline void setindex(int index)
- {
- outb(index, GRAPHICS_ADDR_REG);
- }
- void fbcon_vga_planes_setup(struct display *p)
- {
- }
- void fbcon_vga_planes_bmove(struct display *p, int sy, int sx, int dy, int dx,
- int height, int width)
- {
- char *src;
- char *dest;
- int line_ofs;
- int x;
- setmode(1);
- setop(0);
- setsr(0xf);
- sy *= fontheight(p);
- dy *= fontheight(p);
- height *= fontheight(p);
- if (dy < sy || (dy == sy && dx < sx)) {
- line_ofs = p->line_length - width;
- dest = p->screen_base + dx + dy * p->line_length;
- src = p->screen_base + sx + sy * p->line_length;
- while (height--) {
- for (x = 0; x < width; x++) {
- readb(src);
- writeb(0, dest);
- dest++;
- src++;
- }
- src += line_ofs;
- dest += line_ofs;
- }
- } else {
- line_ofs = p->line_length - width;
- dest = p->screen_base + dx + width + (dy + height - 1) * p->line_length;
- src = p->screen_base + sx + width + (sy + height - 1) * p->line_length;
- while (height--) {
- for (x = 0; x < width; x++) {
- dest--;
- src--;
- readb(src);
- writeb(0, dest);
- }
- src -= line_ofs;
- dest -= line_ofs;
- }
- }
- }
- void fbcon_vga_planes_clear(struct vc_data *conp, struct display *p, int sy, int sx,
- int height, int width)
- {
- int line_ofs = p->line_length - width;
- char *where;
- int x;
- setmode(0);
- setop(0);
- setsr(0xf);
- setcolor(attr_bgcol_ec(p, conp));
- selectmask();
- setmask(0xff);
- sy *= fontheight(p);
- height *= fontheight(p);
- where = p->screen_base + sx + sy * p->line_length;
- while (height--) {
- for (x = 0; x < width; x++) {
- writeb(0, where);
- where++;
- }
- where += line_ofs;
- }
- }
- void fbcon_ega_planes_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
- {
- int fg = attr_fgcol(p,c);
- int bg = attr_bgcol(p,c);
- int y;
- u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
- char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);
- setmode(0);
- setop(0);
- setsr(0xf);
- setcolor(bg);
- selectmask();
- setmask(0xff);
- for (y = 0; y < fontheight(p); y++, where += p->line_length)
- rmw(where);
- where -= p->line_length * y;
- setcolor(fg);
- selectmask();
- for (y = 0; y < fontheight(p); y++, where += p->line_length)
- if (cdat[y]) {
- setmask(cdat[y]);
- rmw(where);
- }
- }
- void fbcon_vga_planes_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
- {
- int fg = attr_fgcol(p,c);
- int bg = attr_bgcol(p,c);
- int y;
- u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
- char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);
- setmode(2);
- setop(0);
- setsr(0xf);
- setcolor(fg);
- selectmask();
- setmask(0xff);
- writeb(bg, where);
- rmb();
- readb(where); /* fill latches */
- setmode(3);
- wmb();
- for (y = 0; y < fontheight(p); y++, where += p->line_length)
- writeb(cdat[y], where);
- wmb();
- }
- /* 28.50 in my test */
- void fbcon_ega_planes_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
- int count, int yy, int xx)
- {
- u16 c = scr_readw(s);
- int fg = attr_fgcol(p, c);
- int bg = attr_bgcol(p, c);
- char *where;
- int n;
- setmode(2);
- setop(0);
- selectmask();
- setmask(0xff);
- where = p->screen_base + xx + yy * p->line_length * fontheight(p);
- writeb(bg, where);
- rmb();
- readb(where); /* fill latches */
- wmb();
- selectmask();
- for (n = 0; n < count; n++) {
- int c = scr_readw(s++) & p->charmask;
- u8 *cdat = p->fontdata + c * fontheight(p);
- u8 *end = cdat + fontheight(p);
- while (cdat < end) {
- outb(*cdat++, GRAPHICS_DATA_REG);
- wmb();
- writeb(fg, where);
- where += p->line_length;
- }
- where += 1 - p->line_length * fontheight(p);
- }
- wmb();
- }
- /* 6.96 in my test */
- void fbcon_vga_planes_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
- int count, int yy, int xx)
- {
- u16 c = scr_readw(s);
- int fg = attr_fgcol(p, c);
- int bg = attr_bgcol(p, c);
- char *where;
- int n;
- setmode(2);
- setop(0);
- setsr(0xf);
- setcolor(fg);
- selectmask();
- setmask(0xff);
- where = p->screen_base + xx + yy * p->line_length * fontheight(p);
- writeb(bg, where);
- rmb();
- readb(where); /* fill latches */
- setmode(3);
- wmb();
- for (n = 0; n < count; n++) {
- int y;
- int c = scr_readw(s++) & p->charmask;
- u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
- for (y = 0; y < fontheight(p); y++, cdat++) {
- writeb (*cdat, where);
- where += p->line_length;
- }
- where += 1 - p->line_length * fontheight(p);
- }
- wmb();
- }
- void fbcon_vga_planes_revc(struct display *p, int xx, int yy)
- {
- char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);
- int y;
- setmode(0);
- setop(0x18);
- setsr(0xf);
- setcolor(0xf);
- selectmask();
- setmask(0xff);
- for (y = 0; y < fontheight(p); y++) {
- rmw(where);
- where += p->line_length;
- }
- }
- struct display_switch fbcon_vga_planes = {
- setup: fbcon_vga_planes_setup,
- bmove: fbcon_vga_planes_bmove,
- clear: fbcon_vga_planes_clear,
- putc: fbcon_vga_planes_putc,
- putcs: fbcon_vga_planes_putcs,
- revc: fbcon_vga_planes_revc,
- fontwidthmask: FONTWIDTH(8)
- };
- struct display_switch fbcon_ega_planes = {
- setup: fbcon_vga_planes_setup,
- bmove: fbcon_vga_planes_bmove,
- clear: fbcon_vga_planes_clear,
- putc: fbcon_ega_planes_putc,
- putcs: fbcon_ega_planes_putcs,
- revc: fbcon_vga_planes_revc,
- fontwidthmask: FONTWIDTH(8)
- };
- #ifdef MODULE
- MODULE_LICENSE("GPL");
- int init_module(void)
- {
- return 0;
- }
- void cleanup_module(void)
- {}
- #endif /* MODULE */
- /*
- * Visible symbols for modules
- */
- EXPORT_SYMBOL(fbcon_vga_planes);
- EXPORT_SYMBOL(fbcon_vga_planes_setup);
- EXPORT_SYMBOL(fbcon_vga_planes_bmove);
- EXPORT_SYMBOL(fbcon_vga_planes_clear);
- EXPORT_SYMBOL(fbcon_vga_planes_putc);
- EXPORT_SYMBOL(fbcon_vga_planes_putcs);
- EXPORT_SYMBOL(fbcon_vga_planes_revc);
- EXPORT_SYMBOL(fbcon_ega_planes);
- EXPORT_SYMBOL(fbcon_ega_planes_putc);
- EXPORT_SYMBOL(fbcon_ega_planes_putcs);
- /*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */