1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
37
38
39static inline u8* rowaddr(struct display *p, u_int row)
40{
41 return p->screen_base + HGA_ROWADDR(row);
42}
43
44void 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
52void 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
88void 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
117void 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
143void 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 c = scr_readw(s);
152 bold = attr_bold(p, c);
153 revs = attr_reverse(p, c);
154 underl = attr_underline(p, c);
155 y0 = yy*fontheight(p);
156
157 while (count--) {
158 c = scr_readw(s++) & p->charmask;
159 cdat = p->fontdata+c*fontheight(p);
160 y = y0;
161 for (rows = fontheight(p); rows--; y++) {
162 d = *cdat++;
163 if (underl && !rows)
164 d = 0xff;
165 else if (bold)
166 d |= d>>1;
167 if (revs)
168 d = ~d;
169 dest = rowaddr(p, y)+xx;
170 *dest = d;
171 }
172 xx++;
173 }
174}
175
176void fbcon_hga_revc(struct display *p, int xx, int yy)
177{
178 u8 *dest;
179 u_int rows, y;
180
181 y = yy*fontheight(p);
182 for (rows = fontheight(p); rows--; y++) {
183 dest = rowaddr(p, y)+xx;
184 *dest = ~*dest;
185 }
186}
187
188void fbcon_hga_clear_margins(struct vc_data *conp, struct display *p,
189 int bottom_only)
190{
191 u8 *dest;
192 u_int height, y;
193 int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
194
195 DPRINTK("fbcon_hga_clear_margins: enter\n");
196
197
198
199 y = conp->vc_rows * fontheight(p);
200 for (height = p->var.yres - y; height-- > 0; y++) {
201 DPRINTK("fbcon_hga_clear_margins: y:%d, height:%d\n", y, height);
202 dest = rowaddr(p, y);
203 if (inverse) {
204 fb_memset255(dest, p->next_line);
205 } else {
206 fb_memclear(dest, p->next_line);
207 }
208 }
209}
210
211
212
213
214
215
216struct display_switch fbcon_hga = {
217 setup: fbcon_hga_setup,
218 bmove: fbcon_hga_bmove,
219 clear: fbcon_hga_clear,
220 putc: fbcon_hga_putc,
221 putcs: fbcon_hga_putcs,
222 revc: fbcon_hga_revc,
223 clear_margins: fbcon_hga_clear_margins,
224 fontwidthmask: FONTWIDTH(8)
225};
226
227
228#ifdef MODULE
229MODULE_LICENSE("GPL");
230
231int init_module(void)
232{
233 return 0;
234}
235
236void cleanup_module(void)
237{
238}
239#endif
240
241
242
243
244
245
246EXPORT_SYMBOL(fbcon_hga);
247EXPORT_SYMBOL(fbcon_hga_setup);
248EXPORT_SYMBOL(fbcon_hga_bmove);
249EXPORT_SYMBOL(fbcon_hga_clear);
250EXPORT_SYMBOL(fbcon_hga_putc);
251EXPORT_SYMBOL(fbcon_hga_putcs);
252EXPORT_SYMBOL(fbcon_hga_revc);
253EXPORT_SYMBOL(fbcon_hga_clear_margins);
254