2 * linux/drivers/video/fbcon.h -- Low level frame buffer based console driver
4 * Copyright (C) 1997 Geert Uytterhoeven
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
11 #ifndef _VIDEO_FBCON_H
12 #define _VIDEO_FBCON_H
14 #include <linux/config.h>
15 #include <linux/types.h>
16 #include <linux/console_struct.h>
17 #include <linux/vt_buffer.h>
21 * `switch' for the Low Level Operations
24 struct display_switch
{
25 void (*setup
)(struct display
*p
);
26 void (*bmove
)(struct display
*p
, int sy
, int sx
, int dy
, int dx
,
27 int height
, int width
);
28 /* for clear, conp may be NULL, which means use a blanking (black) color */
29 void (*clear
)(struct vc_data
*conp
, struct display
*p
, int sy
, int sx
,
30 int height
, int width
);
31 void (*putc
)(struct vc_data
*conp
, struct display
*p
, int c
, int yy
,
33 void (*putcs
)(struct vc_data
*conp
, struct display
*p
, const unsigned short *s
,
34 int count
, int yy
, int xx
);
35 void (*revc
)(struct display
*p
, int xx
, int yy
);
36 void (*cursor
)(struct display
*p
, int mode
, int xx
, int yy
);
37 int (*set_font
)(struct display
*p
, int width
, int height
);
38 void (*clear_margins
)(struct vc_data
*conp
, struct display
*p
,
40 unsigned int fontwidthmask
; /* 1 at (1 << (width - 1)) if width is supported */
43 extern struct display_switch fbcon_dummy
;
45 #define fontheight(p) ((p)->_fontheight)
46 #define fontheightlog(p) ((p)->_fontheightlog)
48 #ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
50 /* fontwidth w is supported by dispsw */
51 #define FONTWIDTH(w) (1 << ((8) - 1))
52 /* fontwidths w1-w2 inclusive are supported by dispsw */
53 #define FONTWIDTHRANGE(w1,w2) FONTWIDTH(8)
55 #define fontwidth(p) (8)
56 #define fontwidthlog(p) (0)
60 /* fontwidth w is supported by dispsw */
61 #define FONTWIDTH(w) (1 << ((w) - 1))
62 /* fontwidths w1-w2 inclusive are supported by dispsw */
63 #define FONTWIDTHRANGE(w1,w2) (FONTWIDTH(w2+1) - FONTWIDTH(w1))
65 #define fontwidth(p) ((p)->_fontwidth)
66 #define fontwidthlog(p) ((p)->_fontwidthlog)
75 #define attr_fgcol(p,s) \
76 (((s) >> ((p)->fgshift)) & 0x0f)
77 #define attr_bgcol(p,s) \
78 (((s) >> ((p)->bgshift)) & 0x0f)
79 #define attr_bgcol_ec(p,conp) \
80 ((conp) ? (((conp)->vc_video_erase_char >> ((p)->bgshift)) & 0x0f) : 0)
83 #define attr_bold(p,s) \
85 #define attr_reverse(p,s) \
86 (((s) & 0x800) ^ ((p)->inverse ? 0x800 : 0))
87 #define attr_underline(p,s) \
89 #define attr_blink(p,s) \
97 #define __SCROLL_YPAN 0x001
98 #define __SCROLL_YWRAP 0x002
99 #define __SCROLL_YMOVE 0x003
100 #define __SCROLL_YREDRAW 0x004
101 #define __SCROLL_YMASK 0x00f
102 #define __SCROLL_YFIXED 0x010
103 #define __SCROLL_YNOMOVE 0x020
104 #define __SCROLL_YPANREDRAW 0x040
105 #define __SCROLL_YNOPARTIAL 0x080
107 /* Only these should be used by the drivers */
108 /* Which one should you use? If you have a fast card and slow bus,
109 then probably just 0 to indicate fbcon should choose between
110 YWRAP/YPAN+MOVE/YMOVE. On the other side, if you have a fast bus
111 and even better if your card can do fonting (1->8/32bit painting),
112 you should consider either SCROLL_YREDRAW (if your card is
113 able to do neither YPAN/YWRAP), or SCROLL_YNOMOVE.
114 The best is to test it with some real life scrolling (usually, not
115 all lines on the screen are filled completely with non-space characters,
116 and REDRAW performs much better on such lines, so don't cat a file
117 with every line covering all screen columns, it would not be the right
120 #define SCROLL_YREDRAW (__SCROLL_YFIXED|__SCROLL_YREDRAW)
121 #define SCROLL_YNOMOVE (__SCROLL_YNOMOVE|__SCROLL_YPANREDRAW)
123 /* SCROLL_YNOPARTIAL, used in combination with the above, is for video
124 cards which can not handle using panning to scroll a portion of the
125 screen without excessive flicker. Panning will only be used for
128 /* Namespace consistency */
129 #define SCROLL_YNOPARTIAL __SCROLL_YNOPARTIAL
132 extern void fbcon_redraw_bmove(struct display
*, int, int, int, int, int, int);
135 /* ================================================================= */
136 /* Utility Assembler Functions */
137 /* ================================================================= */
140 #if defined(__mc68000__)
142 /* ====================================================================== */
144 /* Those of a delicate disposition might like to skip the next couple of
147 * These functions are drop in replacements for memmove and
148 * memset(_, 0, _). However their five instances add at least a kilobyte
149 * to the object file. You have been warned.
151 * Not a great fan of assembler for the sake of it, but I think
152 * that these routines are at least 10 times faster than their C
153 * equivalents for large blits, and that's important to the lowest level of
154 * a graphics driver. Question is whether some scheme with the blitter
155 * would be faster. I suspect not for simple text system - not much
158 * Code is very simple, just gruesome expansion. Basic strategy is to
159 * increase data moved/cleared at each step to 16 bytes to reduce
160 * instruction per data move overhead. movem might be faster still
161 * For more than 15 bytes, we try to align the write direction on a
162 * longword boundary to get maximum speed. This is even more gruesome.
163 * Unaligned read/write used requires 68020+ - think this is a problem?
169 /* ++roman: I've optimized Robert's original versions in some minor
170 * aspects, e.g. moveq instead of movel, let gcc choose the registers,
171 * use movem in some places...
172 * For other modes than 1 plane, lots of more such assembler functions
173 * were needed (e.g. the ones using movep or expanding color values).
176 /* ++andreas: more optimizations:
177 subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
178 addal is faster than addaw
179 movep is rather expensive compared to ordinary move's
180 some functions rewritten in C for clarity, no speed loss */
182 static __inline__
void *mymemclear_small(void *s
, size_t count
)
187 __asm__
__volatile__(
188 "lsrl #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
189 "1: lsrl #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
190 "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
191 "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
192 "1: subql #1,%1 ; jcs 3f\n\t"
193 "2: moveml %2/%3/%4/%5,%0@-\n\t"
196 : "=a" (s
), "=d" (count
)
197 : "d" (0), "d" (0), "d" (0), "d" (0),
198 "0" ((char *)s
+count
), "1" (count
)
205 static __inline__
void *mymemclear(void *s
, size_t count
)
211 __asm__
__volatile__(
212 "lsrl #1,%1 ; jcc 1f ; clrb %0@+\n\t"
213 "1: lsrl #1,%1 ; jcc 1f ; clrw %0@+\n\t"
214 "1: lsrl #1,%1 ; jcc 1f ; clrl %0@+\n\t"
215 "1: lsrl #1,%1 ; jcc 1f ; clrl %0@+ ; clrl %0@+\n\t"
217 : "=a" (s
), "=d" (count
)
218 : "0" (s
), "1" (count
)
222 __asm__
__volatile__(
224 "lsrl #1,%2 ; jcc 1f ; clrb %0@+ ; subqw #1,%1\n\t"
225 "lsrl #1,%2 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
226 "clrw %0@+ ; subqw #2,%1 ; jra 2f\n\t"
227 "1: lsrl #1,%2 ; jcc 2f\n\t"
228 "clrw %0@+ ; subqw #2,%1\n\t"
229 "2: movew %1,%2; lsrl #2,%1 ; jeq 6f\n\t"
230 "lsrl #1,%1 ; jcc 3f ; clrl %0@+\n\t"
231 "3: lsrl #1,%1 ; jcc 4f ; clrl %0@+ ; clrl %0@+\n\t"
232 "4: subql #1,%1 ; jcs 6f\n\t"
233 "5: clrl %0@+; clrl %0@+ ; clrl %0@+ ; clrl %0@+\n\t"
234 "dbra %1,5b ; clrw %1; subql #1,%1; jcc 5b\n\t"
235 "6: movew %2,%1; btst #1,%1 ; jeq 7f ; clrw %0@+\n\t"
236 "7: ; btst #0,%1 ; jeq 8f ; clrb %0@+\n\t"
238 : "=a" (s
), "=d" (count
), "=d" (tmp
)
239 : "0" (s
), "1" (count
)
247 static __inline__
void *mymemset(void *s
, size_t count
)
252 __asm__
__volatile__(
253 "lsrl #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
254 "1: lsrl #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
255 "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
256 "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
257 "1: subql #1,%1 ; jcs 3f\n\t"
258 "2: moveml %2/%3/%4/%5,%0@-\n\t"
261 : "=a" (s
), "=d" (count
)
262 : "d" (-1), "d" (-1), "d" (-1), "d" (-1),
263 "0" ((char *) s
+ count
), "1" (count
)
270 static __inline__
void *mymemmove(void *d
, const void *s
, size_t count
)
274 __asm__
__volatile__(
275 "lsrl #1,%2 ; jcc 1f ; moveb %1@+,%0@+\n\t"
276 "1: lsrl #1,%2 ; jcc 1f ; movew %1@+,%0@+\n\t"
277 "1: lsrl #1,%2 ; jcc 1f ; movel %1@+,%0@+\n\t"
278 "1: lsrl #1,%2 ; jcc 1f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
280 : "=a" (d
), "=a" (s
), "=d" (count
)
281 : "0" (d
), "1" (s
), "2" (count
)
285 __asm__
__volatile__(
287 "lsrl #1,%3 ; jcc 1f ; moveb %1@+,%0@+ ; subqw #1,%2\n\t"
288 "lsrl #1,%3 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
289 "movew %1@+,%0@+ ; subqw #2,%2 ; jra 2f\n\t"
290 "1: lsrl #1,%3 ; jcc 2f\n\t"
291 "movew %1@+,%0@+ ; subqw #2,%2\n\t"
292 "2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
293 "lsrl #1,%2 ; jcc 3f ; movel %1@+,%0@+\n\t"
294 "3: lsrl #1,%2 ; jcc 4f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
295 "4: subql #1,%2 ; jcs 6f\n\t"
296 "5: movel %1@+,%0@+;movel %1@+,%0@+\n\t"
297 "movel %1@+,%0@+;movel %1@+,%0@+\n\t"
298 "dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
299 "6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@+,%0@+\n\t"
300 "7: ; btst #0,%2 ; jeq 8f ; moveb %1@+,%0@+\n\t"
302 : "=a" (d
), "=a" (s
), "=d" (count
), "=d" (tmp
)
303 : "0" (d
), "1" (s
), "2" (count
)
308 __asm__
__volatile__(
309 "lsrl #1,%2 ; jcc 1f ; moveb %1@-,%0@-\n\t"
310 "1: lsrl #1,%2 ; jcc 1f ; movew %1@-,%0@-\n\t"
311 "1: lsrl #1,%2 ; jcc 1f ; movel %1@-,%0@-\n\t"
312 "1: lsrl #1,%2 ; jcc 1f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
314 : "=a" (d
), "=a" (s
), "=d" (count
)
315 : "0" ((char *) d
+ count
), "1" ((char *) s
+ count
), "2" (count
)
319 __asm__
__volatile__(
321 "lsrl #1,%3 ; jcc 1f ; moveb %1@-,%0@- ; subqw #1,%2\n\t"
322 "lsrl #1,%3 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
323 "movew %1@-,%0@- ; subqw #2,%2 ; jra 2f\n\t"
324 "1: lsrl #1,%3 ; jcc 2f\n\t"
325 "movew %1@-,%0@- ; subqw #2,%2\n\t"
326 "2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
327 "lsrl #1,%2 ; jcc 3f ; movel %1@-,%0@-\n\t"
328 "3: lsrl #1,%2 ; jcc 4f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
329 "4: subql #1,%2 ; jcs 6f\n\t"
330 "5: movel %1@-,%0@-;movel %1@-,%0@-\n\t"
331 "movel %1@-,%0@-;movel %1@-,%0@-\n\t"
332 "dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
333 "6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@-,%0@-\n\t"
334 "7: ; btst #0,%2 ; jeq 8f ; moveb %1@-,%0@-\n\t"
336 : "=a" (d
), "=a" (s
), "=d" (count
), "=d" (tmp
)
337 : "0" ((char *) d
+ count
), "1" ((char *) s
+ count
), "2" (count
)
346 /* ++andreas: Simple and fast version of memmove, assumes size is
347 divisible by 16, suitable for moving the whole screen bitplane */
348 static __inline__
void fast_memmove(char *dst
, const char *src
, size_t size
)
355 " moveml %0@+,%/d0/%/d1/%/a0/%/a1\n"
356 " moveml %/d0/%/d1/%/a0/%/a1,%1@\n"
357 " addql #8,%1; addql #8,%1\n"
359 " clrw %2; subql #1,%2\n"
361 : "=a" (src
), "=a" (dst
), "=d" (size
)
362 : "0" (src
), "1" (dst
), "2" (size
/ 16 - 1)
363 : "d0", "d1", "a0", "a1", "memory");
367 " subql #8,%0; subql #8,%0\n"
368 " moveml %0@,%/d0/%/d1/%/a0/%/a1\n"
369 " moveml %/d0/%/d1/%/a0/%/a1,%1@-\n"
371 " clrw %2; subql #1,%2\n"
373 : "=a" (src
), "=a" (dst
), "=d" (size
)
374 : "0" (src
+ size
), "1" (dst
+ size
), "2" (size
/ 16 - 1)
375 : "d0", "d1", "a0", "a1", "memory");
378 #elif defined(CONFIG_SUN4)
380 /* You may think that I'm crazy and that I should use generic
381 routines. No, I'm not: sun4's framebuffer crashes if we std
382 into it, so we cannot use memset. */
384 static __inline__
void *sun4_memset(void *s
, char val
, size_t count
)
387 for(i
=0; i
<count
;i
++)
388 ((char *) s
) [i
] = val
;
392 static __inline__
void *mymemset(void *s
, size_t count
)
394 return sun4_memset(s
, 255, count
);
397 static __inline__
void *mymemclear(void *s
, size_t count
)
399 return sun4_memset(s
, 0, count
);
402 static __inline__
void *mymemclear_small(void *s
, size_t count
)
404 return sun4_memset(s
, 0, count
);
407 /* To be honest, this is slow_memmove :). But sun4 is crappy, so what we can do. */
408 static __inline__
void fast_memmove(void *d
, const void *s
, size_t count
)
412 for (i
=0; i
<count
; i
++)
413 ((char *) d
)[i
] = ((char *) s
)[i
];
415 for (i
=0; i
<count
; i
++)
416 ((char *) d
)[count
-i
-1] = ((char *) s
)[count
-i
-1];
419 static __inline__
void *mymemmove(char *dst
, const char *src
, size_t size
)
421 fast_memmove(dst
, src
, size
);
427 static __inline__
void *mymemclear_small(void *s
, size_t count
)
429 return(memset(s
, 0, count
));
432 static __inline__
void *mymemclear(void *s
, size_t count
)
434 return(memset(s
, 0, count
));
437 static __inline__
void *mymemset(void *s
, size_t count
)
439 return(memset(s
, 255, count
));
442 #if defined(__i386__)
444 static __inline__
void fast_memmove(void *d
, const void *s
, size_t count
)
448 __asm__
__volatile__ (
453 "1:\tshrl $1,%%ecx\n\t"
458 : "=&c" (d0
), "=&D" (d1
), "=&S" (d2
)
459 :"0"(count
),"1"((long)d
),"2"((long)s
)
462 __asm__
__volatile__ (
466 "movb 3(%%esi),%%al\n\t"
467 "movb %%al,3(%%edi)\n\t"
470 "1:\tshrl $1,%%ecx\n\t"
472 "movw 2(%%esi),%%ax\n\t"
473 "movw %%ax,2(%%edi)\n\t"
481 : "=&c" (d0
), "=&D" (d1
), "=&S" (d2
), "=&a" (d3
)
482 :"0"(count
),"1"(count
-4+(long)d
),"2"(count
-4+(long)s
)
487 static __inline__
void *mymemmove(char *dst
, const char *src
, size_t size
)
489 fast_memmove(dst
, src
, size
);
496 * Anyone who'd like to write asm functions for other CPUs?
497 * (Why are these functions better than those from include/asm/string.h?)
500 static __inline__
void *mymemmove(void *d
, const void *s
, size_t count
)
502 return(memmove(d
, s
, count
));
505 static __inline__
void fast_memmove(char *dst
, const char *src
, size_t size
)
507 memmove(dst
, src
, size
);
515 #if defined(__i386__) || defined(__alpha__)
517 #define fb_readb __raw_readb
518 #define fb_readw __raw_readw
519 #define fb_readl __raw_readl
520 #define fb_writeb __raw_writeb
521 #define fb_writew __raw_writew
522 #define fb_writel __raw_writel
526 #define fb_readb(addr) (*(volatile u8 *) (addr))
527 #define fb_readw(addr) (*(volatile u16 *) (addr))
528 #define fb_readl(addr) (*(volatile u32 *) (addr))
529 #define fb_writeb(b,addr) (*(volatile u8 *) (addr) = (b))
530 #define fb_writew(b,addr) (*(volatile u16 *) (addr) = (b))
531 #define fb_writel(b,addr) (*(volatile u32 *) (addr) = (b))
535 #endif /* _VIDEO_FBCON_H */