File: /usr/src/linux/drivers/video/fbcon-hga.c

1     /*
2      *  linux/drivers/video/fbcon-hga.c -- Low level frame buffer operations for
3      *				       the Hercules graphics adaptor
4      *
5      *	Created 25 Nov 1999 by Ferenc Bakonyi (fero@drama.obuda.kando.hu)
6      *	Based on fbcon-mfb.c by Geert Uytterhoeven
7      *
8      * History:
9      *
10      * - Revision 0.1.0 (6 Dec 1999): comment changes
11      * - First release (25 Nov 1999)
12      * 
13      *  This file is subject to the terms and conditions of the GNU General Public
14      *  License.  See the file COPYING in the main directory of this archive for
15      *  more details.
16      */
17     
18     #include <linux/module.h>
19     #include <linux/tty.h>
20     #include <linux/console.h>
21     #include <linux/string.h>
22     #include <linux/fb.h>
23     
24     #include <video/fbcon.h>
25     #include <video/fbcon-hga.h>
26     
27     #if 0
28     #define DPRINTK(args...) printk(KERN_DEBUG __FILE__": " ##args)
29     #else
30     #define DPRINTK(args...)
31     #endif
32     
33     #define HGA_ROWADDR(row) ((row%4)*8192 + (row>>2)*90)
34     
35         /*
36          *  Hercules monochrome
37          */
38     
39     static inline u8* rowaddr(struct display *p, u_int row)
40     {
41     	return p->screen_base + HGA_ROWADDR(row);
42     }
43     	
44     void fbcon_hga_setup(struct display *p)
45     {
46     	DPRINTK("fbcon_hga_setup: ll:%d\n", (int)p->line_length);
47     
48     	p->next_line = p->line_length;
49     	p->next_plane = 0;
50     }
51     
52     void fbcon_hga_bmove(struct display *p, int sy, int sx, int dy, int dx,
53     		     int height, int width)
54     {
55     	u8 *src, *dest;
56     	u_int rows, y1, y2;
57     	
58     #if 0
59     	if (sx == 0 && dx == 0 && width == p->next_line) {
60     		src = p->screen_base+sy*fontheight(p)*width;
61     		dest = p->screen_base+dy*fontheight(p)*width;
62     		fb_memmove(dest, src, height*fontheight(p)*width);
63     	} else 
64     #endif
65     	if (dy <= sy) {
66     		y1 = sy*fontheight(p);
67     		y2 = dy*fontheight(p);
68     		for (rows = height*fontheight(p); rows--; ) {
69     			src = rowaddr(p, y1)+sx;
70     			dest = rowaddr(p, y2)+dx;
71     			fb_memmove(dest, src, width);
72     			y1++;
73     			y2++;
74     		}
75     	} else {
76     		y1 = (sy+height)*fontheight(p)-1;
77     		y2 = (dy+height)*fontheight(p)-1;
78     		for (rows = height*fontheight(p); rows--;) {
79     			src = rowaddr(p, y1)+sx;
80     			dest = rowaddr(p, y2)+dx;
81     			fb_memmove(dest, src, width);
82     			y1--;
83     			y2--;
84     		}
85     	}
86     }
87     
88     void fbcon_hga_clear(struct vc_data *conp, struct display *p, int sy, int sx,
89     		     int height, int width)
90     {
91     	u8 *dest;
92     	u_int rows, y;
93     	int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
94     
95     	DPRINTK("fbcon_hga_clear: sx:%d, sy:%d, height:%d, width:%d\n", sx, sy, height, width);
96     	
97     	y = sy*fontheight(p);
98     #if 0
99     	if (sx == 0 && width == p->next_line) {
100     		if (inverse) {
101     			fb_memset255(dest, height*fontheight(p)*width);
102     		} else {
103     			fb_memclear(dest, height*fontheight(p)*width);
104     		}
105     	} else
106     #endif	    
107     	for (rows = height*fontheight(p); rows--; y++) {
108     		dest = rowaddr(p, y)+sx;
109     		if (inverse) {
110     			fb_memset255(dest, width);
111     		} else {
112     			fb_memclear(dest, width);
113     		}
114     	}
115     }
116     
117     void fbcon_hga_putc(struct vc_data *conp, struct display *p, int c, int yy,
118     		    int xx)
119     {
120     	u8 *dest, *cdat;
121     	u_int rows, y, bold, revs, underl;
122     	u8 d;
123     
124     	cdat = p->fontdata+(c&p->charmask)*fontheight(p);
125     	bold = attr_bold(p, c);
126     	revs = attr_reverse(p, c);
127     	underl = attr_underline(p, c);
128     	y = yy*fontheight(p);
129     
130     	for (rows = fontheight(p); rows--; y++) {
131     		d = *cdat++;
132     		if (underl && !rows)
133     			d = 0xff;
134     		else if (bold)
135     			d |= d>>1;
136     		if (revs)
137     			d = ~d;
138     		dest = rowaddr(p, y)+xx;
139     		*dest = d;
140     	}
141     }
142     
143     void fbcon_hga_putcs(struct vc_data *conp, struct display *p, 
144     		     const unsigned short *s, int count, int yy, int xx)
145     {
146     	u8 *dest, *cdat;
147     	u_int rows, y, y0, bold, revs, underl;
148     	u8 d;
149     	u16 c;
150     	
151     	bold = attr_bold(p,scr_readw(s));
152     	revs = attr_reverse(p,scr_readw(s));
153     	underl = attr_underline(p,scr_readw(s));
154     	y0 = yy*fontheight(p);
155     
156     	while (count--) {
157     		c = scr_readw(s++) & p->charmask;
158     		cdat = p->fontdata+c*fontheight(p);
159     		y = y0;
160     		for (rows = fontheight(p); rows--; y++) {
161     			d = *cdat++;
162     	    		if (underl && !rows)
163     				d = 0xff;
164     	    		else if (bold)
165     				d |= d>>1;
166     	    		if (revs)
167     				d = ~d;
168     			dest = rowaddr(p, y)+xx;
169     	    		*dest = d;
170     		}
171     		xx++;
172     	}
173     }
174     
175     void fbcon_hga_revc(struct display *p, int xx, int yy)
176     {
177     	u8 *dest;
178     	u_int rows, y;
179     
180     	y = yy*fontheight(p);
181     	for (rows = fontheight(p); rows--; y++) {
182     		dest = rowaddr(p, y)+xx;
183     		*dest = ~*dest;
184     	}
185     }
186     
187     void fbcon_hga_clear_margins(struct vc_data *conp, struct display *p,
188     			     int bottom_only)
189     {
190     	u8 *dest;
191     	u_int height, y;
192     	int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
193     
194     	DPRINTK("fbcon_hga_clear_margins: enter\n");
195     
196     	/* No need to handle right margin. */
197     
198     	y = conp->vc_rows * fontheight(p);
199     	for (height = p->var.yres - y; height-- > 0; y++) {
200     		DPRINTK("fbcon_hga_clear_margins: y:%d, height:%d\n", y, height);
201     		dest = rowaddr(p, y);
202     		if (inverse) {
203     			fb_memset255(dest, p->next_line);
204     		} else {
205     			fb_memclear(dest, p->next_line);
206     		}
207     	}
208     }
209     
210     
211     	/*
212     	 *  `switch' for the low level operations
213     	 */
214     
215     struct display_switch fbcon_hga = {
216     	setup:		fbcon_hga_setup,
217     	bmove:		fbcon_hga_bmove,
218     	clear:		fbcon_hga_clear,
219     	putc:		fbcon_hga_putc,
220     	putcs:		fbcon_hga_putcs,
221     	revc:		fbcon_hga_revc,
222     	clear_margins:	fbcon_hga_clear_margins,
223     	fontwidthmask:	FONTWIDTH(8)
224     };
225     
226     
227     #ifdef MODULE
228     MODULE_LICENSE("GPL");
229     
230     int init_module(void)
231     {
232     	return 0;
233     }
234     
235     void cleanup_module(void)
236     {
237     }
238     #endif /* MODULE */
239     
240     
241     	/*
242     	 *  Visible symbols for modules
243     	 */
244     
245     EXPORT_SYMBOL(fbcon_hga);
246     EXPORT_SYMBOL(fbcon_hga_setup);
247     EXPORT_SYMBOL(fbcon_hga_bmove);
248     EXPORT_SYMBOL(fbcon_hga_clear);
249     EXPORT_SYMBOL(fbcon_hga_putc);
250     EXPORT_SYMBOL(fbcon_hga_putcs);
251     EXPORT_SYMBOL(fbcon_hga_revc);
252     EXPORT_SYMBOL(fbcon_hga_clear_margins);
253