1 /*
2 * linux/drivers/video/fbcon-sti.c -- Low level frame buffer
3 * operations for generic HP video boards using STI (standard
4 * text interface) firmware
5 *
6 * Based on linux/drivers/video/fbcon-artist.c
7 * Created 5 Apr 1997 by Geert Uytterhoeven
8 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
9 *
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file COPYING in the main directory of this archive for
12 * more details. */
13
14 #include <linux/module.h>
15 #include <linux/tty.h>
16 #include <linux/console.h>
17 #include <linux/string.h>
18 #include <linux/fb.h>
19 #include <asm/delay.h>
20 #include <asm/types.h>
21
22 #include <video/fbcon.h>
23 #include <video/fbcon-mfb.h>
24
25 #include "sti.h"
26
27 /* Translate an address as it would be found in a 2048x2048x1 bit frame
28 * buffer into a logical address Artist actually expects. Addresses fed
29 * into Artist look like this:
30 * fixed Y X
31 * FFFF FFFF LLLL LLLL LLLC CCCC CCCC CC00
32 *
33 * our "RAM" addresses look like this:
34 *
35 * FFFF FFFF 0000 0LLL LLLL LLLL CCCC CCCC [CCC]
36 *
37 * */
38
39 static inline u32
40 ram2log(void * addr)
41 {
42 u32 a = (unsigned long) addr;
43 u32 r;
44
45 #if 0
46 r = a & 0xff000000; /* fixed part */
47 r += ((a & 0x000000ff) << 5);
48 r += ((a & 0x00ffff00) << 3);
49 #else
50 r = a & 0xff000000; /* fixed part */
51 r += ((a & 0x000000ff) << 5);
52 r += ((a & 0x0007ff00) << 5);
53 #endif
54
55 return r;
56 }
57
58 /* All those functions need better names. */
59
60 static void
61 memcpy_fromhp_tohp(void *dest, void *src, int count)
62 {
63 unsigned long d = ram2log(dest);
64 unsigned long s = ram2log(src);
65
66 count += 3;
67 count &= ~3; /* XXX */
68
69 while(count) {
70 count --;
71 gsc_writel(~gsc_readl(s), d);
72 d += 32*4;
73 s += 32*4;
74 }
75 }
76
77 static void
78 memcpy_tohp(void *dest, void *src, int count)
79 {
80 unsigned long d = (unsigned long) dest;
81 u32 *s = (u32 *)src;
82
83 count += 3;
84 count &= ~3; /* XXX */
85
86 d = ram2log(dest);
87
88 while(count) {
89 count--;
90 gsc_writel(*s++, d);
91 d += 32*4;
92 }
93 }
94
95 static void
96 memcopy_fromhp(void *dest, void *src, int count)
97 {
98 /* FIXME */
99 printk("uhm ...\n");
100 }
101
102 static void
103 memset_tohp(void *dest, u32 word, int count)
104 {
105 unsigned long d = ram2log(dest);
106
107 count += 3;
108 count &= ~3;
109
110 while(count) {
111 count--;
112 gsc_writel(word, d);
113 d += 32;
114 }
115 }
116
117 static u8
118 readb_hp(void *src)
119 {
120 unsigned long s = ram2log(src);
121
122 return ~gsc_readb(s);
123 }
124
125 static void
126 writeb_hp(u8 b, void *dst)
127 {
128 unsigned long d = ram2log(dst);
129
130 if((d&0xf0000000) != 0xf0000000) {
131 printk("writeb_hp %02x %p (%08lx) (%p)\n",
132 b, dst, d, __builtin_return_address(0));
133 return;
134 }
135
136 gsc_writeb(b, d);
137 }
138
139 static void
140 fbcon_sti_setup(struct display *p)
141 {
142 if (p->line_length)
143 p->next_line = p->line_length;
144 else
145 p->next_line = p->var.xres_virtual>>3;
146 p->next_plane = 0;
147 }
148
149 static void
150 fbcon_sti_bmove(struct display *p, int sy, int sx,
151 int dy, int dx,
152 int height, int width)
153 {
154 #if 0 /* Unfortunately, still broken */
155 sti_bmove(&default_sti /* FIXME */, sy, sx, dy, dx, height, width);
156 #else
157 u8 *src, *dest;
158 u_int rows;
159
160 if (sx == 0 && dx == 0 && width == p->next_line) {
161 src = p->screen_base+sy*fontheight(p)*width;
162 dest = p->screen_base+dy*fontheight(p)*width;
163 memcpy_fromhp_tohp(dest, src, height*fontheight(p)*width);
164 } else if (dy <= sy) {
165 src = p->screen_base+sy*fontheight(p)*p->next_line+sx;
166 dest = p->screen_base+dy*fontheight(p)*p->next_line+dx;
167 for (rows = height*fontheight(p); rows--;) {
168 memcpy_fromhp_tohp(dest, src, width);
169 src += p->next_line;
170 dest += p->next_line;
171 }
172 } else {
173 src = p->screen_base+((sy+height)*fontheight(p)-1)*p->next_line+sx;
174 dest = p->screen_base+((dy+height)*fontheight(p)-1)*p->next_line+dx;
175 for (rows = height*fontheight(p); rows--;) {
176 memcpy_fromhp_tohp(dest, src, width);
177 src -= p->next_line;
178 dest -= p->next_line;
179 }
180 }
181 #endif
182 }
183
184 static void
185 fbcon_sti_clear(struct vc_data *conp,
186 struct display *p, int sy, int sx,
187 int height, int width)
188 {
189 u8 *dest;
190 u_int rows;
191 int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
192
193 dest = p->screen_base+sy*fontheight(p)*p->next_line+sx;
194
195 if (sx == 0 && width == p->next_line) {
196 if (inverse)
197 memset_tohp(dest, ~0, height*fontheight(p)*width);
198 else
199 memset_tohp(dest, 0, height*fontheight(p)*width);
200 } else
201 for (rows = height*fontheight(p); rows--; dest += p->next_line)
202 if (inverse)
203 memset_tohp(dest, 0xffffffff, width);
204 else
205 memset_tohp(dest, 0x00000000, width);
206 }
207
208 static void fbcon_sti_putc(struct vc_data *conp,
209 struct display *p, int c,
210 int yy, int xx)
211 {
212 u8 *dest, *cdat;
213 u_int rows, bold, revs, underl;
214 u8 d;
215
216 dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
217 cdat = p->fontdata+(c&p->charmask)*fontheight(p);
218 bold = attr_bold(p,c);
219 revs = attr_reverse(p,c);
220 underl = attr_underline(p,c);
221
222 for (rows = fontheight(p); rows--; dest += p->next_line) {
223 d = *cdat++;
224 if (underl && !rows)
225 d = 0xff;
226 else if (bold)
227 d |= d>>1;
228 if (revs)
229 d = ~d;
230 writeb_hp (d, dest);
231 }
232 }
233
234 static void fbcon_sti_putcs(struct vc_data *conp,
235 struct display *p,
236 const unsigned short *s,
237 int count, int yy, int xx)
238 {
239 u8 *dest, *dest0, *cdat;
240 u_int rows, bold, revs, underl;
241 u8 d;
242 u16 c;
243
244 if(((unsigned)xx > 200) || ((unsigned) yy > 200)) {
245 printk("refusing to putcs %p %p %p %d %d %d (%p)\n",
246 conp, p, s, count, yy, xx, __builtin_return_address(0));
247 return;
248 }
249
250
251 dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
252 if(((u32)dest0&0xf0000000)!=0xf0000000) {
253 printk("refusing to putcs %p %p %p %d %d %d (%p) %p = %p + %d * %d * %ld + %d\n",
254 conp, p, s, count, yy, xx, __builtin_return_address(0),
255 dest0, p->screen_base, yy, fontheight(p), p->next_line,
256 xx);
257 return;
258 }
259
260 bold = attr_bold(p,scr_readw(s));
261 revs = attr_reverse(p,scr_readw(s));
262 underl = attr_underline(p,scr_readw(s));
263
264 while (count--) {
265 c = scr_readw(s++) & p->charmask;
266 dest = dest0++;
267 cdat = p->fontdata+c*fontheight(p);
268 for (rows = fontheight(p); rows--; dest += p->next_line) {
269 d = *cdat++;
270 if (0 && underl && !rows)
271 d = 0xff;
272 else if (0 && bold)
273 d |= d>>1;
274 if (revs)
275 d = ~d;
276 writeb_hp (d, dest);
277 }
278 }
279 }
280
281 static void fbcon_sti_revc(struct display *p,
282 int xx, int yy)
283 {
284 u8 *dest, d;
285 u_int rows;
286
287
288 dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
289 for (rows = fontheight(p); rows--; dest += p->next_line) {
290 d = readb_hp(dest);
291 writeb_hp (~d, dest);
292 }
293 }
294
295 static void
296 fbcon_sti_clear_margins(struct vc_data *conp,
297 struct display *p,
298 int bottom_only)
299 {
300 u8 *dest;
301 int height, bottom;
302 int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
303
304
305 /* XXX Need to handle right margin? */
306
307 height = p->var.yres - conp->vc_rows * fontheight(p);
308 if (!height)
309 return;
310 bottom = conp->vc_rows + p->yscroll;
311 if (bottom >= p->vrows)
312 bottom -= p->vrows;
313 dest = p->screen_base + bottom * fontheight(p) * p->next_line;
314 if (inverse)
315 memset_tohp(dest, 0xffffffff, height * p->next_line);
316 else
317 memset_tohp(dest, 0x00000000, height * p->next_line);
318 }
319
320
321 /*
322 * `switch' for the low level operations
323 */
324
325 struct display_switch fbcon_sti = {
326 fbcon_sti_setup, fbcon_sti_bmove, fbcon_sti_clear,
327 fbcon_sti_putc, fbcon_sti_putcs, fbcon_sti_revc,
328 NULL, NULL, fbcon_sti_clear_margins,
329 FONTWIDTH(8)
330 };
331
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.