1/* 2 * linux/drivers/video/fbcon-vga.c -- Low level frame buffer operations for 3 * VGA characters/attributes 4 * 5 * Created 28 Mar 1998 by Geert Uytterhoeven 6 * Monochrome attributes added May 1998 by Andrew Apted 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file COPYING in the main directory of this archive for 10 * more details. 11 */ 12 13#include <linux/module.h> 14#include <linux/tty.h> 15#include <linux/console.h> 16#include <linux/string.h> 17#include <linux/fb.h> 18 19#include <asm/io.h> 20 21#include <video/fbcon.h> 22#include <video/fbcon-vga.h> 23 24 25 /* 26 * VGA screen access 27 */ 28 29static inline void vga_writew(u16 val, u16 *addr) 30{ 31#ifdef __powerpc__ 32 st_le16(addr, val); 33#else 34 writew(val, (unsigned long)addr); 35#endif /* !__powerpc__ */ 36} 37 38static inline u16 vga_readw(u16 *addr) 39{ 40#ifdef __powerpc__ 41 return ld_le16(addr); 42#else 43 return readw((unsigned long)addr); 44#endif /* !__powerpc__ */ 45} 46 47static inline void vga_memsetw(void *s, u16 c, unsigned int count) 48{ 49 u16 *addr = (u16 *)s; 50 51 while (count) { 52 count--; 53 vga_writew(c, addr++); 54 } 55} 56 57static inline void vga_memmovew(u16 *to, u16 *from, unsigned int count) 58{ 59 if (to < from) { 60 while (count) { 61 count--; 62 vga_writew(vga_readw(from++), to++); 63 } 64 } else { 65 from += count; 66 to += count; 67 while (count) { 68 count--; 69 vga_writew(vga_readw(--from), --to); 70 } 71 } 72} 73 74 75 /* 76 * VGA characters/attributes 77 */ 78 79static inline u16 fbcon_vga_attr(struct display *p, 80 unsigned short s) 81{ 82 /* Underline and reverse-video are mutually exclusive on MDA. 83 * Since reverse-video is used for cursors and selected areas, 84 * it takes precedence. 85 */ 86 87 return (attr_reverse(p, s) ? 0x7000 : 88 (attr_underline(p, s) ? 0x0100 : 0x0700)) | 89 (attr_bold(p, s) ? 0x0800 : 0) | 90 (attr_blink(p, s) ? 0x8000 : 0); 91} 92 93void fbcon_vga_setup(struct display *p) 94{ 95 p->next_line = p->line_length; 96 p->next_plane = 0; 97} 98 99void fbcon_vga_bmove(struct display *p, int sy, int sx, int dy, int dx, 100 int height, int width) 101{ 102 u16 *src, *dst; 103 int rows; 104 105 if (sx == 0 && dx == 0 && width == p->next_line/2) { 106 src = (u16 *)(p->screen_base+sy*p->next_line); 107 dst = (u16 *)(p->screen_base+dy*p->next_line); 108 vga_memmovew(dst, src, height*width); 109 } else if (dy < sy || (dy == sy && dx < sx)) { 110 src = (u16 *)(p->screen_base+sy*p->next_line+sx*2); 111 dst = (u16 *)(p->screen_base+dy*p->next_line+dx*2); 112 for (rows = height; rows-- ;) { 113 vga_memmovew(dst, src, width); 114 src += p->next_line/2; 115 dst += p->next_line/2; 116 } 117 } else { 118 src = (u16 *)(p->screen_base+(sy+height-1)*p->next_line+sx*2); 119 dst = (u16 *)(p->screen_base+(dy+height-1)*p->next_line+dx*2); 120 for (rows = height; rows-- ;) { 121 vga_memmovew(dst, src, width); 122 src -= p->next_line/2; 123 dst -= p->next_line/2; 124 } 125 } 126} 127 128void fbcon_vga_clear(struct vc_data *conp, struct display *p, int sy, int sx, 129 int height, int width) 130{ 131 u16 *dest = (u16 *)(p->screen_base+sy*p->next_line+sx*2); 132 int rows; 133 134 if (sx == 0 && width*2 == p->next_line) 135 vga_memsetw(dest, conp->vc_video_erase_char, height*width); 136 else 137 for (rows = height; rows-- ; dest += p->next_line/2) 138 vga_memsetw(dest, conp->vc_video_erase_char, width); 139} 140 141void fbcon_vga_putc(struct vc_data *conp, struct display *p, int c, int y, 142 int x) 143{ 144 u16 *dst = (u16 *)(p->screen_base+y*p->next_line+x*2); 145 if (conp->vc_can_do_color) 146 vga_writew(c, dst); 147 else 148 vga_writew(fbcon_vga_attr(p, c) | (c & 0xff), dst); 149} 150 151void fbcon_vga_putcs(struct vc_data *conp, struct display *p, 152 const unsigned short *s, int count, int y, int x) 153{ 154 u16 *dst = (u16 *)(p->screen_base+y*p->next_line+x*2); 155 u16 sattr; 156 if (conp->vc_can_do_color) 157 while (count--) 158 vga_writew(scr_readw(s++), dst++); 159 else { 160 sattr = fbcon_vga_attr(p, scr_readw(s)); 161 while (count--) 162 vga_writew(sattr | ((int) (scr_readw(s++)) & 0xff), dst++); 163 } 164} 165 166void fbcon_vga_revc(struct display *p, int x, int y) 167{ 168 u16 *dst = (u16 *)(p->screen_base+y*p->next_line+x*2); 169 u16 val = vga_readw(dst); 170 val = (val & 0x88ff) | ((val<<4) & 0x7000) | ((val>>4) & 0x0700); 171 vga_writew(val, dst); 172} 173 174 175 /* 176 * `switch' for the low level operations 177 */ 178 179struct display_switch fbcon_vga = { 180 setup: fbcon_vga_setup, 181 bmove: fbcon_vga_bmove, 182 clear: fbcon_vga_clear, 183 putc: fbcon_vga_putc, 184 putcs: fbcon_vga_putcs, 185 revc: fbcon_vga_revc, 186 fontwidthmask: FONTWIDTH(8) 187}; 188 189 190#ifdef MODULE 191MODULE_LICENSE("GPL"); 192 193int init_module(void) 194{ 195 return 0; 196} 197 198void cleanup_module(void) 199{} 200#endif /* MODULE */ 201 202 203 /* 204 * Visible symbols for modules 205 */ 206 207EXPORT_SYMBOL(fbcon_vga); 208EXPORT_SYMBOL(fbcon_vga_setup); 209EXPORT_SYMBOL(fbcon_vga_bmove); 210EXPORT_SYMBOL(fbcon_vga_clear); 211EXPORT_SYMBOL(fbcon_vga_putc); 212EXPORT_SYMBOL(fbcon_vga_putcs); 213EXPORT_SYMBOL(fbcon_vga_revc); 214