1 /*
2 * linux/drivers/video/fbcon.h -- Low level frame buffer based console driver
3 *
4 * Copyright (C) 1997 Geert Uytterhoeven
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 */
10
11 #ifndef _VIDEO_FBCON_H
12 #define _VIDEO_FBCON_H
13
14 #include <linux/config.h>
15 #include <linux/types.h>
16 #include <linux/console_struct.h>
17 #include <linux/vt_buffer.h>
18
19 #include <asm/io.h>
20
21
22 /*
23 * `switch' for the Low Level Operations
24 */
25
26 struct display_switch {
27 void (*setup)(struct display *p);
28 void (*bmove)(struct display *p, int sy, int sx, int dy, int dx,
29 int height, int width);
30 /* for clear, conp may be NULL, which means use a blanking (black) color */
31 void (*clear)(struct vc_data *conp, struct display *p, int sy, int sx,
32 int height, int width);
33 void (*putc)(struct vc_data *conp, struct display *p, int c, int yy,
34 int xx);
35 void (*putcs)(struct vc_data *conp, struct display *p, const unsigned short *s,
36 int count, int yy, int xx);
37 void (*revc)(struct display *p, int xx, int yy);
38 void (*cursor)(struct display *p, int mode, int xx, int yy);
39 int (*set_font)(struct display *p, int width, int height);
40 void (*clear_margins)(struct vc_data *conp, struct display *p,
41 int bottom_only);
42 unsigned int fontwidthmask; /* 1 at (1 << (width - 1)) if width is supported */
43 };
44
45 extern struct display_switch fbcon_dummy;
46
47 /*
48 * This is the interface between the low-level console driver and the
49 * low-level frame buffer device
50 */
51
52 struct display {
53 /* Filled in by the frame buffer device */
54
55 struct fb_var_screeninfo var; /* variable infos. yoffset and vmode */
56 /* are updated by fbcon.c */
57 struct fb_cmap cmap; /* colormap */
58 char *screen_base; /* pointer to top of virtual screen */
59 /* (virtual address) */
60 int visual;
61 int type; /* see FB_TYPE_* */
62 int type_aux; /* Interleave for interleaved Planes */
63 u_short ypanstep; /* zero if no hardware ypan */
64 u_short ywrapstep; /* zero if no hardware ywrap */
65 u_long line_length; /* length of a line in bytes */
66 u_short can_soft_blank; /* zero if no hardware blanking */
67 u_short inverse; /* != 0 text black on white as default */
68 struct display_switch *dispsw; /* low level operations */
69 void *dispsw_data; /* optional dispsw helper data */
70
71 #if 0
72 struct fb_fix_cursorinfo fcrsr;
73 struct fb_var_cursorinfo *vcrsr;
74 struct fb_cursorstate crsrstate;
75 #endif
76
77 /* Filled in by the low-level console driver */
78
79 struct vc_data *conp; /* pointer to console data */
80 struct fb_info *fb_info; /* frame buffer for this console */
81 int vrows; /* number of virtual rows */
82 unsigned short cursor_x; /* current cursor position */
83 unsigned short cursor_y;
84 int fgcol; /* text colors */
85 int bgcol;
86 u_long next_line; /* offset to one line below */
87 u_long next_plane; /* offset to next plane */
88 u_char *fontdata; /* Font associated to this display */
89 unsigned short _fontheightlog;
90 unsigned short _fontwidthlog;
91 unsigned short _fontheight;
92 unsigned short _fontwidth;
93 int userfont; /* != 0 if fontdata kmalloc()ed */
94 u_short scrollmode; /* Scroll Method */
95 short yscroll; /* Hardware scrolling */
96 unsigned char fgshift, bgshift;
97 unsigned short charmask; /* 0xff or 0x1ff */
98 };
99
100 /* drivers/video/fbcon.c */
101 extern struct display fb_display[MAX_NR_CONSOLES];
102 extern char con2fb_map[MAX_NR_CONSOLES];
103 extern int PROC_CONSOLE(const struct fb_info *info);
104 extern void set_con2fb_map(int unit, int newidx);
105 extern int set_all_vcs(int fbidx, struct fb_ops *fb,
106 struct fb_var_screeninfo *var, struct fb_info *info);
107
108 #define fontheight(p) ((p)->_fontheight)
109 #define fontheightlog(p) ((p)->_fontheightlog)
110
111 #ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
112
113 /* fontwidth w is supported by dispsw */
114 #define FONTWIDTH(w) (1 << ((8) - 1))
115 /* fontwidths w1-w2 inclusive are supported by dispsw */
116 #define FONTWIDTHRANGE(w1,w2) FONTWIDTH(8)
117
118 #define fontwidth(p) (8)
119 #define fontwidthlog(p) (0)
120
121 #else
122
123 /* fontwidth w is supported by dispsw */
124 #define FONTWIDTH(w) (1 << ((w) - 1))
125 /* fontwidths w1-w2 inclusive are supported by dispsw */
126 #define FONTWIDTHRANGE(w1,w2) (FONTWIDTH(w2+1) - FONTWIDTH(w1))
127
128 #define fontwidth(p) ((p)->_fontwidth)
129 #define fontwidthlog(p) ((p)->_fontwidthlog)
130
131 #endif
132
133 /*
134 * Attribute Decoding
135 */
136
137 /* Color */
138 #define attr_fgcol(p,s) \
139 (((s) >> ((p)->fgshift)) & 0x0f)
140 #define attr_bgcol(p,s) \
141 (((s) >> ((p)->bgshift)) & 0x0f)
142 #define attr_bgcol_ec(p,conp) \
143 ((conp) ? (((conp)->vc_video_erase_char >> ((p)->bgshift)) & 0x0f) : 0)
144
145 /* Monochrome */
146 #define attr_bold(p,s) \
147 ((s) & 0x200)
148 #define attr_reverse(p,s) \
149 (((s) & 0x800) ^ ((p)->inverse ? 0x800 : 0))
150 #define attr_underline(p,s) \
151 ((s) & 0x400)
152 #define attr_blink(p,s) \
153 ((s) & 0x8000)
154
155 /*
156 * Scroll Method
157 */
158
159 /* Internal flags */
160 #define __SCROLL_YPAN 0x001
161 #define __SCROLL_YWRAP 0x002
162 #define __SCROLL_YMOVE 0x003
163 #define __SCROLL_YREDRAW 0x004
164 #define __SCROLL_YMASK 0x00f
165 #define __SCROLL_YFIXED 0x010
166 #define __SCROLL_YNOMOVE 0x020
167 #define __SCROLL_YPANREDRAW 0x040
168 #define __SCROLL_YNOPARTIAL 0x080
169
170 /* Only these should be used by the drivers */
171 /* Which one should you use? If you have a fast card and slow bus,
172 then probably just 0 to indicate fbcon should choose between
173 YWRAP/YPAN+MOVE/YMOVE. On the other side, if you have a fast bus
174 and even better if your card can do fonting (1->8/32bit painting),
175 you should consider either SCROLL_YREDRAW (if your card is
176 able to do neither YPAN/YWRAP), or SCROLL_YNOMOVE.
177 The best is to test it with some real life scrolling (usually, not
178 all lines on the screen are filled completely with non-space characters,
179 and REDRAW performs much better on such lines, so don't cat a file
180 with every line covering all screen columns, it would not be the right
181 benchmark).
182 */
183 #define SCROLL_YREDRAW (__SCROLL_YFIXED|__SCROLL_YREDRAW)
184 #define SCROLL_YNOMOVE (__SCROLL_YNOMOVE|__SCROLL_YPANREDRAW)
185
186 /* SCROLL_YNOPARTIAL, used in combination with the above, is for video
187 cards which can not handle using panning to scroll a portion of the
188 screen without excessive flicker. Panning will only be used for
189 whole screens.
190 */
191 /* Namespace consistency */
192 #define SCROLL_YNOPARTIAL __SCROLL_YNOPARTIAL
193
194
195 #if defined(__sparc__)
196
197 /* We map all of our framebuffers such that big-endian accesses
198 * are what we want, so the following is sufficient.
199 */
200
201 #define fb_readb sbus_readb
202 #define fb_readw sbus_readw
203 #define fb_readl sbus_readl
204 #define fb_writeb sbus_writeb
205 #define fb_writew sbus_writew
206 #define fb_writel sbus_writel
207 #define fb_memset sbus_memset_io
208
209 #elif defined(__i386__) || defined(__alpha__) || \
210 defined(__x86_64__) || defined(__hppa__) || \
211 defined(__powerpc64__)
212
213 #define fb_readb __raw_readb
214 #define fb_readw __raw_readw
215 #define fb_readl __raw_readl
216 #define fb_writeb __raw_writeb
217 #define fb_writew __raw_writew
218 #define fb_writel __raw_writel
219 #define fb_memset memset_io
220
221 #else
222
223 #define fb_readb(addr) (*(volatile u8 *) (addr))
224 #define fb_readw(addr) (*(volatile u16 *) (addr))
225 #define fb_readl(addr) (*(volatile u32 *) (addr))
226 #define fb_writeb(b,addr) (*(volatile u8 *) (addr) = (b))
227 #define fb_writew(b,addr) (*(volatile u16 *) (addr) = (b))
228 #define fb_writel(b,addr) (*(volatile u32 *) (addr) = (b))
229 #define fb_memset memset
230
231 #endif
232
233
234 extern void fbcon_redraw_clear(struct vc_data *, struct display *, int, int, int, int);
235 extern void fbcon_redraw_bmove(struct display *, int, int, int, int, int, int);
236
237
238 /* ================================================================= */
239 /* Utility Assembler Functions */
240 /* ================================================================= */
241
242
243 #if defined(__mc68000__)
244
245 /* ====================================================================== */
246
247 /* Those of a delicate disposition might like to skip the next couple of
248 * pages.
249 *
250 * These functions are drop in replacements for memmove and
251 * memset(_, 0, _). However their five instances add at least a kilobyte
252 * to the object file. You have been warned.
253 *
254 * Not a great fan of assembler for the sake of it, but I think
255 * that these routines are at least 10 times faster than their C
256 * equivalents for large blits, and that's important to the lowest level of
257 * a graphics driver. Question is whether some scheme with the blitter
258 * would be faster. I suspect not for simple text system - not much
259 * asynchrony.
260 *
261 * Code is very simple, just gruesome expansion. Basic strategy is to
262 * increase data moved/cleared at each step to 16 bytes to reduce
263 * instruction per data move overhead. movem might be faster still
264 * For more than 15 bytes, we try to align the write direction on a
265 * longword boundary to get maximum speed. This is even more gruesome.
266 * Unaligned read/write used requires 68020+ - think this is a problem?
267 *
268 * Sorry!
269 */
270
271
272 /* ++roman: I've optimized Robert's original versions in some minor
273 * aspects, e.g. moveq instead of movel, let gcc choose the registers,
274 * use movem in some places...
275 * For other modes than 1 plane, lots of more such assembler functions
276 * were needed (e.g. the ones using movep or expanding color values).
277 */
278
279 /* ++andreas: more optimizations:
280 subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
281 addal is faster than addaw
282 movep is rather expensive compared to ordinary move's
283 some functions rewritten in C for clarity, no speed loss */
284
fb_memclear_small(void * s,size_t count)285 static __inline__ void *fb_memclear_small(void *s, size_t count)
286 {
287 if (!count)
288 return(0);
289
290 __asm__ __volatile__(
291 "lsrl #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
292 "1: lsrl #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
293 "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
294 "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
295 "1:"
296 : "=a" (s), "=d" (count)
297 : "d" (0), "0" ((char *)s+count), "1" (count)
298 );
299 __asm__ __volatile__(
300 "subql #1,%1 ; jcs 3f\n\t"
301 "movel %2,%%d4; movel %2,%%d5; movel %2,%%d6\n\t"
302 "2: moveml %2/%%d4/%%d5/%%d6,%0@-\n\t"
303 "dbra %1,2b\n\t"
304 "3:"
305 : "=a" (s), "=d" (count)
306 : "d" (0), "0" (s), "1" (count)
307 : "d4", "d5", "d6"
308 );
309
310 return(0);
311 }
312
313
fb_memclear(void * s,size_t count)314 static __inline__ void *fb_memclear(void *s, size_t count)
315 {
316 if (!count)
317 return(0);
318
319 if (count < 16) {
320 __asm__ __volatile__(
321 "lsrl #1,%1 ; jcc 1f ; clrb %0@+\n\t"
322 "1: lsrl #1,%1 ; jcc 1f ; clrw %0@+\n\t"
323 "1: lsrl #1,%1 ; jcc 1f ; clrl %0@+\n\t"
324 "1: lsrl #1,%1 ; jcc 1f ; clrl %0@+ ; clrl %0@+\n\t"
325 "1:"
326 : "=a" (s), "=d" (count)
327 : "0" (s), "1" (count)
328 );
329 } else {
330 long tmp;
331 __asm__ __volatile__(
332 "movel %1,%2\n\t"
333 "lsrl #1,%2 ; jcc 1f ; clrb %0@+ ; subqw #1,%1\n\t"
334 "lsrl #1,%2 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
335 "clrw %0@+ ; subqw #2,%1 ; jra 2f\n\t"
336 "1: lsrl #1,%2 ; jcc 2f\n\t"
337 "clrw %0@+ ; subqw #2,%1\n\t"
338 "2: movew %1,%2; lsrl #2,%1 ; jeq 6f\n\t"
339 "lsrl #1,%1 ; jcc 3f ; clrl %0@+\n\t"
340 "3: lsrl #1,%1 ; jcc 4f ; clrl %0@+ ; clrl %0@+\n\t"
341 "4: subql #1,%1 ; jcs 6f\n\t"
342 "5: clrl %0@+; clrl %0@+ ; clrl %0@+ ; clrl %0@+\n\t"
343 "dbra %1,5b ; clrw %1; subql #1,%1; jcc 5b\n\t"
344 "6: movew %2,%1; btst #1,%1 ; jeq 7f ; clrw %0@+\n\t"
345 "7: ; btst #0,%1 ; jeq 8f ; clrb %0@+\n\t"
346 "8:"
347 : "=a" (s), "=d" (count), "=d" (tmp)
348 : "0" (s), "1" (count)
349 );
350 }
351
352 return(0);
353 }
354
355
fb_memset255(void * s,size_t count)356 static __inline__ void *fb_memset255(void *s, size_t count)
357 {
358 if (!count)
359 return(0);
360
361 __asm__ __volatile__(
362 "lsrl #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
363 "1: lsrl #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
364 "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
365 "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
366 "1:"
367 : "=a" (s), "=d" (count)
368 : "d" (-1), "0" ((char *)s+count), "1" (count)
369 );
370 __asm__ __volatile__(
371 "subql #1,%1 ; jcs 3f\n\t"
372 "movel %2,%%d4; movel %2,%%d5; movel %2,%%d6\n\t"
373 "2: moveml %2/%%d4/%%d5/%%d6,%0@-\n\t"
374 "dbra %1,2b\n\t"
375 "3:"
376 : "=a" (s), "=d" (count)
377 : "d" (-1), "0" (s), "1" (count)
378 : "d4", "d5", "d6"
379 );
380
381 return(0);
382 }
383
384
fb_memmove(void * d,const void * s,size_t count)385 static __inline__ void *fb_memmove(void *d, const void *s, size_t count)
386 {
387 if (d < s) {
388 if (count < 16) {
389 __asm__ __volatile__(
390 "lsrl #1,%2 ; jcc 1f ; moveb %1@+,%0@+\n\t"
391 "1: lsrl #1,%2 ; jcc 1f ; movew %1@+,%0@+\n\t"
392 "1: lsrl #1,%2 ; jcc 1f ; movel %1@+,%0@+\n\t"
393 "1: lsrl #1,%2 ; jcc 1f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
394 "1:"
395 : "=a" (d), "=a" (s), "=d" (count)
396 : "0" (d), "1" (s), "2" (count)
397 );
398 } else {
399 long tmp;
400 __asm__ __volatile__(
401 "movel %0,%3\n\t"
402 "lsrl #1,%3 ; jcc 1f ; moveb %1@+,%0@+ ; subqw #1,%2\n\t"
403 "lsrl #1,%3 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
404 "movew %1@+,%0@+ ; subqw #2,%2 ; jra 2f\n\t"
405 "1: lsrl #1,%3 ; jcc 2f\n\t"
406 "movew %1@+,%0@+ ; subqw #2,%2\n\t"
407 "2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
408 "lsrl #1,%2 ; jcc 3f ; movel %1@+,%0@+\n\t"
409 "3: lsrl #1,%2 ; jcc 4f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
410 "4: subql #1,%2 ; jcs 6f\n\t"
411 "5: movel %1@+,%0@+;movel %1@+,%0@+\n\t"
412 "movel %1@+,%0@+;movel %1@+,%0@+\n\t"
413 "dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
414 "6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@+,%0@+\n\t"
415 "7: ; btst #0,%2 ; jeq 8f ; moveb %1@+,%0@+\n\t"
416 "8:"
417 : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
418 : "0" (d), "1" (s), "2" (count)
419 );
420 }
421 } else {
422 if (count < 16) {
423 __asm__ __volatile__(
424 "lsrl #1,%2 ; jcc 1f ; moveb %1@-,%0@-\n\t"
425 "1: lsrl #1,%2 ; jcc 1f ; movew %1@-,%0@-\n\t"
426 "1: lsrl #1,%2 ; jcc 1f ; movel %1@-,%0@-\n\t"
427 "1: lsrl #1,%2 ; jcc 1f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
428 "1:"
429 : "=a" (d), "=a" (s), "=d" (count)
430 : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
431 );
432 } else {
433 long tmp;
434 __asm__ __volatile__(
435 "movel %0,%3\n\t"
436 "lsrl #1,%3 ; jcc 1f ; moveb %1@-,%0@- ; subqw #1,%2\n\t"
437 "lsrl #1,%3 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
438 "movew %1@-,%0@- ; subqw #2,%2 ; jra 2f\n\t"
439 "1: lsrl #1,%3 ; jcc 2f\n\t"
440 "movew %1@-,%0@- ; subqw #2,%2\n\t"
441 "2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
442 "lsrl #1,%2 ; jcc 3f ; movel %1@-,%0@-\n\t"
443 "3: lsrl #1,%2 ; jcc 4f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
444 "4: subql #1,%2 ; jcs 6f\n\t"
445 "5: movel %1@-,%0@-;movel %1@-,%0@-\n\t"
446 "movel %1@-,%0@-;movel %1@-,%0@-\n\t"
447 "dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
448 "6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@-,%0@-\n\t"
449 "7: ; btst #0,%2 ; jeq 8f ; moveb %1@-,%0@-\n\t"
450 "8:"
451 : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
452 : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
453 );
454 }
455 }
456
457 return(0);
458 }
459
460
461 /* ++andreas: Simple and fast version of memmove, assumes size is
462 divisible by 16, suitable for moving the whole screen bitplane */
fast_memmove(char * dst,const char * src,size_t size)463 static __inline__ void fast_memmove(char *dst, const char *src, size_t size)
464 {
465 if (!size)
466 return;
467 if (dst < src)
468 __asm__ __volatile__
469 ("1:"
470 " moveml %0@+,%/d0/%/d1/%/a0/%/a1\n"
471 " moveml %/d0/%/d1/%/a0/%/a1,%1@\n"
472 " addql #8,%1; addql #8,%1\n"
473 " dbra %2,1b\n"
474 " clrw %2; subql #1,%2\n"
475 " jcc 1b"
476 : "=a" (src), "=a" (dst), "=d" (size)
477 : "0" (src), "1" (dst), "2" (size / 16 - 1)
478 : "d0", "d1", "a0", "a1", "memory");
479 else
480 __asm__ __volatile__
481 ("1:"
482 " subql #8,%0; subql #8,%0\n"
483 " moveml %0@,%/d0/%/d1/%/a0/%/a1\n"
484 " moveml %/d0/%/d1/%/a0/%/a1,%1@-\n"
485 " dbra %2,1b\n"
486 " clrw %2; subql #1,%2\n"
487 " jcc 1b"
488 : "=a" (src), "=a" (dst), "=d" (size)
489 : "0" (src + size), "1" (dst + size), "2" (size / 16 - 1)
490 : "d0", "d1", "a0", "a1", "memory");
491 }
492
493 #elif defined(CONFIG_SUN4)
494
495 /* You may think that I'm crazy and that I should use generic
496 routines. No, I'm not: sun4's framebuffer crashes if we std
497 into it, so we cannot use memset. */
498
sun4_memset(void * s,char val,size_t count)499 static __inline__ void *sun4_memset(void *s, char val, size_t count)
500 {
501 int i;
502 for(i=0; i<count;i++)
503 ((char *) s) [i] = val;
504 return s;
505 }
506
fb_memset255(void * s,size_t count)507 static __inline__ void *fb_memset255(void *s, size_t count)
508 {
509 return sun4_memset(s, 255, count);
510 }
511
fb_memclear(void * s,size_t count)512 static __inline__ void *fb_memclear(void *s, size_t count)
513 {
514 return sun4_memset(s, 0, count);
515 }
516
fb_memclear_small(void * s,size_t count)517 static __inline__ void *fb_memclear_small(void *s, size_t count)
518 {
519 return sun4_memset(s, 0, count);
520 }
521
522 /* To be honest, this is slow_memmove :). But sun4 is crappy, so what we can do. */
fast_memmove(void * d,const void * s,size_t count)523 static __inline__ void fast_memmove(void *d, const void *s, size_t count)
524 {
525 int i;
526 if (d<s) {
527 for (i=0; i<count; i++)
528 ((char *) d)[i] = ((char *) s)[i];
529 } else
530 for (i=0; i<count; i++)
531 ((char *) d)[count-i-1] = ((char *) s)[count-i-1];
532 }
533
fb_memmove(char * dst,const char * src,size_t size)534 static __inline__ void *fb_memmove(char *dst, const char *src, size_t size)
535 {
536 fast_memmove(dst, src, size);
537 return dst;
538 }
539
540 #else
541
fb_memclear_small(void * s,size_t count)542 static __inline__ void *fb_memclear_small(void *s, size_t count)
543 {
544 char *xs = (char *) s;
545
546 while (count--)
547 fb_writeb(0, xs++);
548
549 return s;
550 }
551
fb_memclear(void * s,size_t count)552 static __inline__ void *fb_memclear(void *s, size_t count)
553 {
554 unsigned long xs = (unsigned long) s;
555
556 if (count < 8)
557 goto rest;
558
559 if (xs & 1) {
560 fb_writeb(0, xs++);
561 count--;
562 }
563 if (xs & 2) {
564 fb_writew(0, xs);
565 xs += 2;
566 count -= 2;
567 }
568 while (count > 3) {
569 fb_writel(0, xs);
570 xs += 4;
571 count -= 4;
572 }
573 rest:
574 while (count--)
575 fb_writeb(0, xs++);
576
577 return s;
578 }
579
fb_memset255(void * s,size_t count)580 static __inline__ void *fb_memset255(void *s, size_t count)
581 {
582 unsigned long xs = (unsigned long) s;
583
584 if (count < 8)
585 goto rest;
586
587 if (xs & 1) {
588 fb_writeb(0xff, xs++);
589 count--;
590 }
591 if (xs & 2) {
592 fb_writew(0xffff, xs);
593 xs += 2;
594 count -= 2;
595 }
596 while (count > 3) {
597 fb_writel(0xffffffff, xs);
598 xs += 4;
599 count -= 4;
600 }
601 rest:
602 while (count--)
603 fb_writeb(0xff, xs++);
604
605 return s;
606 }
607
608 #if defined(__i386__)
609
fast_memmove(void * d,const void * s,size_t count)610 static __inline__ void fast_memmove(void *d, const void *s, size_t count)
611 {
612 int d0, d1, d2, d3;
613 if (d < s) {
614 __asm__ __volatile__ (
615 "cld\n\t"
616 "shrl $1,%%ecx\n\t"
617 "jnc 1f\n\t"
618 "movsb\n"
619 "1:\tshrl $1,%%ecx\n\t"
620 "jnc 2f\n\t"
621 "movsw\n"
622 "2:\trep\n\t"
623 "movsl"
624 : "=&c" (d0), "=&D" (d1), "=&S" (d2)
625 :"0"(count),"1"((long)d),"2"((long)s)
626 :"memory");
627 } else {
628 __asm__ __volatile__ (
629 "std\n\t"
630 "shrl $1,%%ecx\n\t"
631 "jnc 1f\n\t"
632 "movb 3(%%esi),%%al\n\t"
633 "movb %%al,3(%%edi)\n\t"
634 "decl %%esi\n\t"
635 "decl %%edi\n"
636 "1:\tshrl $1,%%ecx\n\t"
637 "jnc 2f\n\t"
638 "movw 2(%%esi),%%ax\n\t"
639 "movw %%ax,2(%%edi)\n\t"
640 "decl %%esi\n\t"
641 "decl %%edi\n\t"
642 "decl %%esi\n\t"
643 "decl %%edi\n"
644 "2:\trep\n\t"
645 "movsl\n\t"
646 "cld"
647 : "=&c" (d0), "=&D" (d1), "=&S" (d2), "=&a" (d3)
648 :"0"(count),"1"(count-4+(long)d),"2"(count-4+(long)s)
649 :"memory");
650 }
651 }
652
fb_memmove(char * dst,const char * src,size_t size)653 static __inline__ void *fb_memmove(char *dst, const char *src, size_t size)
654 {
655 fast_memmove(dst, src, size);
656 return dst;
657 }
658
659 #else /* !__i386__ */
660
661 /*
662 * Anyone who'd like to write asm functions for other CPUs?
663 * (Why are these functions better than those from include/asm/string.h?)
664 */
665
fb_memmove(void * d,const void * s,size_t count)666 static __inline__ void *fb_memmove(void *d, const void *s, size_t count)
667 {
668 unsigned long dst, src;
669
670 if (d < s) {
671 dst = (unsigned long) d;
672 src = (unsigned long) s;
673
674 if ((count < 8) || ((dst ^ src) & 3))
675 goto restup;
676
677 if (dst & 1) {
678 fb_writeb(fb_readb(src++), dst++);
679 count--;
680 }
681 if (dst & 2) {
682 fb_writew(fb_readw(src), dst);
683 src += 2;
684 dst += 2;
685 count -= 2;
686 }
687 while (count > 3) {
688 fb_writel(fb_readl(src), dst);
689 src += 4;
690 dst += 4;
691 count -= 4;
692 }
693
694 restup:
695 while (count--)
696 fb_writeb(fb_readb(src++), dst++);
697 } else {
698 dst = (unsigned long) d + count;
699 src = (unsigned long) s + count;
700
701 if ((count < 8) || ((dst ^ src) & 3))
702 goto restdown;
703
704 if (dst & 1) {
705 src--;
706 dst--;
707 count--;
708 fb_writeb(fb_readb(src), dst);
709 }
710 if (dst & 2) {
711 src -= 2;
712 dst -= 2;
713 count -= 2;
714 fb_writew(fb_readw(src), dst);
715 }
716 while (count > 3) {
717 src -= 4;
718 dst -= 4;
719 count -= 4;
720 fb_writel(fb_readl(src), dst);
721 }
722
723 restdown:
724 while (count--) {
725 src--;
726 dst--;
727 fb_writeb(fb_readb(src), dst);
728 }
729 }
730
731 return d;
732 }
733
fast_memmove(char * d,const char * s,size_t count)734 static __inline__ void fast_memmove(char *d, const char *s, size_t count)
735 {
736 unsigned long dst, src;
737
738 if (d < s) {
739 dst = (unsigned long) d;
740 src = (unsigned long) s;
741
742 if ((count < 8) || ((dst ^ src) & 3))
743 goto restup;
744
745 if (dst & 1) {
746 fb_writeb(fb_readb(src++), dst++);
747 count--;
748 }
749 if (dst & 2) {
750 fb_writew(fb_readw(src), dst);
751 src += 2;
752 dst += 2;
753 count -= 2;
754 }
755 while (count > 3) {
756 fb_writel(fb_readl(src), dst);
757 src += 4;
758 dst += 4;
759 count -= 4;
760 }
761
762 restup:
763 while (count--)
764 fb_writeb(fb_readb(src++), dst++);
765 } else {
766 dst = (unsigned long) d + count;
767 src = (unsigned long) s + count;
768
769 if ((count < 8) || ((dst ^ src) & 3))
770 goto restdown;
771
772 if (dst & 1) {
773 src--;
774 dst--;
775 count--;
776 fb_writeb(fb_readb(src), dst);
777 }
778 if (dst & 2) {
779 src -= 2;
780 dst -= 2;
781 count -= 2;
782 fb_writew(fb_readw(src), dst);
783 }
784 while (count > 3) {
785 src -= 4;
786 dst -= 4;
787 count -= 4;
788 fb_writel(fb_readl(src), dst);
789 }
790
791 restdown:
792 while (count--) {
793 src--;
794 dst--;
795 fb_writeb(fb_readb(src), dst);
796 }
797 }
798 }
799
800 #endif /* !__i386__ */
801
802 #endif /* !__mc68000__ */
803
804 #endif /* _VIDEO_FBCON_H */
805