Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

fbcon.h

Go to the documentation of this file.
00001 /*
00002  *  linux/drivers/video/fbcon.h -- Low level frame buffer based console driver
00003  *
00004  *      Copyright (C) 1997 Geert Uytterhoeven
00005  *
00006  *  This file is subject to the terms and conditions of the GNU General Public
00007  *  License.  See the file COPYING in the main directory of this archive
00008  *  for more details.
00009  */
00010 
00011 #ifndef _VIDEO_FBCON_H
00012 #define _VIDEO_FBCON_H
00013 
00014 #include <linux/config.h>
00015 #include <linux/console_struct.h>
00016 #include <linux/vt_buffer.h>
00017 
00018 
00019     /*                                  
00020      *  `switch' for the Low Level Operations
00021      */
00022  
00023 struct display_switch {                                                
00024     void (*setup)(struct display *p);
00025     void (*bmove)(struct display *p, int sy, int sx, int dy, int dx,
00026                   int height, int width);
00027     /* for clear, conp may be NULL, which means use a blanking (black) color */
00028     void (*clear)(struct vc_data *conp, struct display *p, int sy, int sx,
00029                   int height, int width);
00030     void (*putc)(struct vc_data *conp, struct display *p, int c, int yy,
00031                  int xx);
00032     void (*putcs)(struct vc_data *conp, struct display *p, const unsigned short *s,
00033                   int count, int yy, int xx);     
00034     void (*revc)(struct display *p, int xx, int yy);
00035     void (*cursor)(struct display *p, int mode, int xx, int yy);
00036     int  (*set_font)(struct display *p, int width, int height);
00037     void (*clear_margins)(struct vc_data *conp, struct display *p,
00038                           int bottom_only);
00039     unsigned int fontwidthmask;      /* 1 at (1 << (width - 1)) if width is supported */
00040 }; 
00041 
00042 extern struct display_switch fbcon_dummy;
00043 
00044 #define fontheight(p) ((p)->_fontheight)
00045 #define fontheightlog(p) ((p)->_fontheightlog)
00046 
00047 #ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
00048 
00049 /* fontwidth w is supported by dispsw */
00050 #define FONTWIDTH(w)    (1 << ((8) - 1))
00051 /* fontwidths w1-w2 inclusive are supported by dispsw */
00052 #define FONTWIDTHRANGE(w1,w2)   FONTWIDTH(8)
00053 
00054 #define fontwidth(p) (8)
00055 #define fontwidthlog(p) (0)
00056 
00057 #else
00058 
00059 /* fontwidth w is supported by dispsw */
00060 #define FONTWIDTH(w)    (1 << ((w) - 1))
00061 /* fontwidths w1-w2 inclusive are supported by dispsw */
00062 #define FONTWIDTHRANGE(w1,w2)   (FONTWIDTH(w2+1) - FONTWIDTH(w1))
00063 
00064 #define fontwidth(p) ((p)->_fontwidth)
00065 #define fontwidthlog(p) ((p)->_fontwidthlog)
00066 
00067 #endif
00068 
00069     /*
00070      *  Attribute Decoding
00071      */
00072 
00073 /* Color */
00074 #define attr_fgcol(p,s)    \
00075         (((s) >> ((p)->fgshift)) & 0x0f)
00076 #define attr_bgcol(p,s)    \
00077         (((s) >> ((p)->bgshift)) & 0x0f)
00078 #define attr_bgcol_ec(p,conp) \
00079         ((conp) ? (((conp)->vc_video_erase_char >> ((p)->bgshift)) & 0x0f) : 0)
00080 
00081 /* Monochrome */
00082 #define attr_bold(p,s) \
00083         ((s) & 0x200)
00084 #define attr_reverse(p,s) \
00085         (((s) & 0x800) ^ ((p)->inverse ? 0x800 : 0))
00086 #define attr_underline(p,s) \
00087         ((s) & 0x400)
00088 #define attr_blink(p,s) \
00089         ((s) & 0x8000)
00090         
00091     /*
00092      *  Scroll Method
00093      */
00094      
00095 /* Internal flags */
00096 #define __SCROLL_YPAN           0x001
00097 #define __SCROLL_YWRAP          0x002
00098 #define __SCROLL_YMOVE          0x003
00099 #define __SCROLL_YREDRAW        0x004
00100 #define __SCROLL_YMASK          0x00f
00101 #define __SCROLL_YFIXED         0x010
00102 #define __SCROLL_YNOMOVE        0x020
00103 #define __SCROLL_YPANREDRAW     0x040
00104 #define __SCROLL_YNOPARTIAL     0x080
00105 
00106 /* Only these should be used by the drivers */
00107 /* Which one should you use? If you have a fast card and slow bus,
00108    then probably just 0 to indicate fbcon should choose between
00109    YWRAP/YPAN+MOVE/YMOVE. On the other side, if you have a fast bus
00110    and even better if your card can do fonting (1->8/32bit painting),
00111    you should consider either SCROLL_YREDRAW (if your card is
00112    able to do neither YPAN/YWRAP), or SCROLL_YNOMOVE.
00113    The best is to test it with some real life scrolling (usually, not
00114    all lines on the screen are filled completely with non-space characters,
00115    and REDRAW performs much better on such lines, so don't cat a file
00116    with every line covering all screen columns, it would not be the right
00117    benchmark).
00118  */
00119 #define SCROLL_YREDRAW          (__SCROLL_YFIXED|__SCROLL_YREDRAW)
00120 #define SCROLL_YNOMOVE          (__SCROLL_YNOMOVE|__SCROLL_YPANREDRAW)
00121 
00122 /* SCROLL_YNOPARTIAL, used in combination with the above, is for video
00123    cards which can not handle using panning to scroll a portion of the
00124    screen without excessive flicker.  Panning will only be used for
00125    whole screens.
00126  */
00127 /* Namespace consistency */
00128 #define SCROLL_YNOPARTIAL       __SCROLL_YNOPARTIAL
00129 
00130 
00131 extern void fbcon_redraw_bmove(struct display *, int, int, int, int, int, int);
00132 
00133 
00134 /* ================================================================= */
00135 /*                      Utility Assembler Functions                  */
00136 /* ================================================================= */
00137 
00138 
00139 #if defined(__mc68000__)
00140 
00141 /* ====================================================================== */
00142 
00143 /* Those of a delicate disposition might like to skip the next couple of
00144  * pages.
00145  *
00146  * These functions are drop in replacements for memmove and
00147  * memset(_, 0, _). However their five instances add at least a kilobyte
00148  * to the object file. You have been warned.
00149  *
00150  * Not a great fan of assembler for the sake of it, but I think
00151  * that these routines are at least 10 times faster than their C
00152  * equivalents for large blits, and that's important to the lowest level of
00153  * a graphics driver. Question is whether some scheme with the blitter
00154  * would be faster. I suspect not for simple text system - not much
00155  * asynchrony.
00156  *
00157  * Code is very simple, just gruesome expansion. Basic strategy is to
00158  * increase data moved/cleared at each step to 16 bytes to reduce
00159  * instruction per data move overhead. movem might be faster still
00160  * For more than 15 bytes, we try to align the write direction on a
00161  * longword boundary to get maximum speed. This is even more gruesome.
00162  * Unaligned read/write used requires 68020+ - think this is a problem?
00163  *
00164  * Sorry!
00165  */
00166 
00167 
00168 /* ++roman: I've optimized Robert's original versions in some minor
00169  * aspects, e.g. moveq instead of movel, let gcc choose the registers,
00170  * use movem in some places...
00171  * For other modes than 1 plane, lots of more such assembler functions
00172  * were needed (e.g. the ones using movep or expanding color values).
00173  */
00174 
00175 /* ++andreas: more optimizations:
00176    subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
00177    addal is faster than addaw
00178    movep is rather expensive compared to ordinary move's
00179    some functions rewritten in C for clarity, no speed loss */
00180 
00181 static __inline__ void *mymemclear_small(void *s, size_t count)
00182 {
00183    if (!count)
00184       return(0);
00185 
00186    __asm__ __volatile__(
00187          "lsrl   #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
00188       "1: lsrl   #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
00189       "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
00190       "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
00191       "1: subql  #1,%1 ; jcs 3f\n\t"
00192       "2: moveml %2/%3/%4/%5,%0@-\n\t"
00193          "dbra %1,2b\n\t"
00194       "3:"
00195          : "=a" (s), "=d" (count)
00196          :  "d" (0), "d" (0), "d" (0), "d" (0),
00197             "0" ((char *)s+count), "1" (count)
00198   );
00199 
00200    return(0);
00201 }
00202 
00203 
00204 static __inline__ void *mymemclear(void *s, size_t count)
00205 {
00206    if (!count)
00207       return(0);
00208 
00209    if (count < 16) {
00210       __asm__ __volatile__(
00211             "lsrl   #1,%1 ; jcc 1f ; clrb %0@+\n\t"
00212          "1: lsrl   #1,%1 ; jcc 1f ; clrw %0@+\n\t"
00213          "1: lsrl   #1,%1 ; jcc 1f ; clrl %0@+\n\t"
00214          "1: lsrl   #1,%1 ; jcc 1f ; clrl %0@+ ; clrl %0@+\n\t"
00215          "1:"
00216             : "=a" (s), "=d" (count)
00217             : "0" (s), "1" (count)
00218      );
00219    } else {
00220       long tmp;
00221       __asm__ __volatile__(
00222             "movel %1,%2\n\t"
00223             "lsrl   #1,%2 ; jcc 1f ; clrb %0@+ ; subqw #1,%1\n\t"
00224             "lsrl   #1,%2 ; jcs 2f\n\t"  /* %0 increased=>bit 2 switched*/
00225             "clrw   %0@+  ; subqw  #2,%1 ; jra 2f\n\t"
00226          "1: lsrl   #1,%2 ; jcc 2f\n\t"
00227             "clrw   %0@+  ; subqw  #2,%1\n\t"
00228          "2: movew %1,%2; lsrl #2,%1 ; jeq 6f\n\t"
00229             "lsrl   #1,%1 ; jcc 3f ; clrl %0@+\n\t"
00230          "3: lsrl   #1,%1 ; jcc 4f ; clrl %0@+ ; clrl %0@+\n\t"
00231          "4: subql  #1,%1 ; jcs 6f\n\t"
00232          "5: clrl %0@+; clrl %0@+ ; clrl %0@+ ; clrl %0@+\n\t"
00233             "dbra %1,5b   ; clrw %1; subql #1,%1; jcc 5b\n\t"
00234          "6: movew %2,%1; btst #1,%1 ; jeq 7f ; clrw %0@+\n\t"
00235          "7:            ; btst #0,%1 ; jeq 8f ; clrb %0@+\n\t"
00236          "8:"
00237             : "=a" (s), "=d" (count), "=d" (tmp)
00238             : "0" (s), "1" (count)
00239      );
00240    }
00241 
00242    return(0);
00243 }
00244 
00245 
00246 static __inline__ void *mymemset(void *s, size_t count)
00247 {
00248    if (!count)
00249       return(0);
00250 
00251    __asm__ __volatile__(
00252          "lsrl   #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
00253       "1: lsrl   #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
00254       "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
00255       "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
00256       "1: subql  #1,%1 ; jcs 3f\n\t"
00257       "2: moveml %2/%3/%4/%5,%0@-\n\t"
00258          "dbra %1,2b\n\t"
00259       "3:"
00260          : "=a" (s), "=d" (count)
00261          :  "d" (-1), "d" (-1), "d" (-1), "d" (-1),
00262             "0" ((char *) s + count), "1" (count)
00263   );
00264 
00265    return(0);
00266 }
00267 
00268 
00269 static __inline__ void *mymemmove(void *d, const void *s, size_t count)
00270 {
00271    if (d < s) {
00272       if (count < 16) {
00273          __asm__ __volatile__(
00274                "lsrl   #1,%2 ; jcc 1f ; moveb %1@+,%0@+\n\t"
00275             "1: lsrl   #1,%2 ; jcc 1f ; movew %1@+,%0@+\n\t"
00276             "1: lsrl   #1,%2 ; jcc 1f ; movel %1@+,%0@+\n\t"
00277             "1: lsrl   #1,%2 ; jcc 1f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
00278             "1:"
00279                : "=a" (d), "=a" (s), "=d" (count)
00280                : "0" (d), "1" (s), "2" (count)
00281         );
00282       } else {
00283          long tmp;
00284          __asm__ __volatile__(
00285                "movel  %0,%3\n\t"
00286                "lsrl   #1,%3 ; jcc 1f ; moveb %1@+,%0@+ ; subqw #1,%2\n\t"
00287                "lsrl   #1,%3 ; jcs 2f\n\t"  /* %0 increased=>bit 2 switched*/
00288                "movew  %1@+,%0@+  ; subqw  #2,%2 ; jra 2f\n\t"
00289             "1: lsrl   #1,%3 ; jcc 2f\n\t"
00290                "movew  %1@+,%0@+  ; subqw  #2,%2\n\t"
00291             "2: movew  %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
00292                "lsrl   #1,%2 ; jcc 3f ; movel %1@+,%0@+\n\t"
00293             "3: lsrl   #1,%2 ; jcc 4f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
00294             "4: subql  #1,%2 ; jcs 6f\n\t"
00295             "5: movel  %1@+,%0@+;movel %1@+,%0@+\n\t"
00296                "movel  %1@+,%0@+;movel %1@+,%0@+\n\t"
00297                "dbra   %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
00298             "6: movew  %+,%2; btst #1,%2 ; jeq 7f ; movew %1@+,%0@+\n\t"
00299             "7:              ; btst #0,%2 ; jeq 8f ; moveb %1@+,%0@+\n\t"
00300             "8:"
00301                : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
00302                : "0" (d), "1" (s), "2" (count)
00303         );
00304       }
00305    } else {
00306       if (count < 16) {
00307          __asm__ __volatile__(
00308                "lsrl   #1,%2 ; jcc 1f ; moveb %1@-,%0@-\n\t"
00309             "1: lsrl   #1,%2 ; jcc 1f ; movew %1@-,%0@-\n\t"
00310             "1: lsrl   #1,%2 ; jcc 1f ; movel %1@-,%0@-\n\t"
00311             "1: lsrl   #1,%2 ; jcc 1f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
00312             "1:"
00313                : "=a" (d), "=a" (s), "=d" (count)
00314                : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
00315         );
00316       } else {
00317          long tmp;
00318          __asm__ __volatile__(
00319                "movel %0,%3\n\t"
00320                "lsrl   #1,%3 ; jcc 1f ; moveb %1@-,%0@- ; subqw #1,%2\n\t"
00321                "lsrl   #1,%3 ; jcs 2f\n\t"  /* %0 increased=>bit 2 switched*/
00322                "movew  %1@-,%0@-  ; subqw  #2,%2 ; jra 2f\n\t"
00323             "1: lsrl   #1,%3 ; jcc 2f\n\t"
00324                "movew  %1@-,%0@-  ; subqw  #2,%2\n\t"
00325             "2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
00326                "lsrl   #1,%2 ; jcc 3f ; movel %1@-,%0@-\n\t"
00327             "3: lsrl   #1,%2 ; jcc 4f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
00328             "4: subql  #1,%2 ; jcs 6f\n\t"
00329             "5: movel %1@-,%0@-;movel %1@-,%0@-\n\t"
00330                "movel %1@-,%0@-;movel %1@-,%0@-\n\t"
00331                "dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
00332             "6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@-,%0@-\n\t"
00333             "7:              ; btst #0,%2 ; jeq 8f ; moveb %1@-,%0@-\n\t"
00334             "8:"
00335                : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
00336                : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
00337         );
00338       }
00339    }
00340 
00341    return(0);
00342 }
00343 
00344 
00345 /* ++andreas: Simple and fast version of memmove, assumes size is
00346    divisible by 16, suitable for moving the whole screen bitplane */
00347 static __inline__ void fast_memmove(char *dst, const char *src, size_t size)
00348 {
00349   if (!size)
00350     return;
00351   if (dst < src)
00352     __asm__ __volatile__
00353       ("1:"
00354        "  moveml %0@+,%/d0/%/d1/%/a0/%/a1\n"
00355        "  moveml %/d0/%/d1/%/a0/%/a1,%1@\n"
00356        "  addql #8,%1; addql #8,%1\n"
00357        "  dbra %2,1b\n"
00358        "  clrw %2; subql #1,%2\n"
00359        "  jcc 1b"
00360        : "=a" (src), "=a" (dst), "=d" (size)
00361        : "0" (src), "1" (dst), "2" (size / 16 - 1)
00362        : "d0", "d1", "a0", "a1", "memory");
00363   else
00364     __asm__ __volatile__
00365       ("1:"
00366        "  subql #8,%0; subql #8,%0\n"
00367        "  moveml %0@,%/d0/%/d1/%/a0/%/a1\n"
00368        "  moveml %/d0/%/d1/%/a0/%/a1,%1@-\n"
00369        "  dbra %2,1b\n"
00370        "  clrw %2; subql #1,%2\n"
00371        "  jcc 1b"
00372        : "=a" (src), "=a" (dst), "=d" (size)
00373        : "0" (src + size), "1" (dst + size), "2" (size / 16 - 1)
00374        : "d0", "d1", "a0", "a1", "memory");
00375 }
00376 
00377 #elif defined(CONFIG_SUN4)
00378 
00379 /* You may think that I'm crazy and that I should use generic
00380    routines.  No, I'm not: sun4's framebuffer crashes if we std
00381    into it, so we cannot use memset.  */
00382 
00383 static __inline__ void *sun4_memset(void *s, char val, size_t count)
00384 {
00385     int i;
00386     for(i=0; i<count;i++)
00387         ((char *) s) [i] = val;
00388     return s;
00389 }
00390 
00391 static __inline__ void *mymemset(void *s, size_t count)
00392 {
00393     return sun4_memset(s, 255, count);
00394 }
00395 
00396 static __inline__ void *mymemclear(void *s, size_t count)
00397 {
00398     return sun4_memset(s, 0, count);
00399 }
00400 
00401 static __inline__ void *mymemclear_small(void *s, size_t count)
00402 {
00403     return sun4_memset(s, 0, count);
00404 }
00405 
00406 /* To be honest, this is slow_memmove :). But sun4 is crappy, so what we can do. */
00407 static __inline__ void fast_memmove(void *d, const void *s, size_t count)
00408 {
00409     int i;
00410     if (d<s) {
00411         for (i=0; i<count; i++)
00412             ((char *) d)[i] = ((char *) s)[i];
00413     } else
00414         for (i=0; i<count; i++)
00415             ((char *) d)[count-i-1] = ((char *) s)[count-i-1];
00416 }
00417 
00418 static __inline__ void *mymemmove(char *dst, const char *src, size_t size)
00419 {
00420     fast_memmove(dst, src, size);
00421     return dst;
00422 }
00423 
00424 #else
00425 
00426 static __inline__ void *mymemclear_small(void *s, size_t count)
00427 {
00428     return(memset(s, 0, count));
00429 }
00430 
00431 static __inline__ void *mymemclear(void *s, size_t count)
00432 {
00433     return(memset(s, 0, count));
00434 }
00435 
00436 static __inline__ void *mymemset(void *s, size_t count)
00437 {
00438     return(memset(s, 255, count));
00439 }
00440 
00441 #if defined(__i386__)
00442 
00443 static __inline__ void fast_memmove(void *d, const void *s, size_t count)
00444 {
00445   int d0, d1, d2, d3;
00446     if (d < s) {
00447 __asm__ __volatile__ (
00448         "cld\n\t"
00449         "shrl $1,%%ecx\n\t"
00450         "jnc 1f\n\t"
00451         "movsb\n"
00452         "1:\tshrl $1,%%ecx\n\t"
00453         "jnc 2f\n\t"
00454         "movsw\n"
00455         "2:\trep\n\t"
00456         "movsl"
00457         : "=&c" (d0), "=&D" (d1), "=&S" (d2)
00458         :"0"(count),"1"((long)d),"2"((long)s)
00459         :"memory");
00460     } else {
00461 __asm__ __volatile__ (
00462         "std\n\t"
00463         "shrl $1,%%ecx\n\t"
00464         "jnc 1f\n\t"
00465         "movb 3(%%esi),%%al\n\t"
00466         "movb %%al,3(%%edi)\n\t"
00467         "decl %%esi\n\t"
00468         "decl %%edi\n"
00469         "1:\tshrl $1,%%ecx\n\t"
00470         "jnc 2f\n\t"
00471         "movw 2(%%esi),%%ax\n\t"
00472         "movw %%ax,2(%%edi)\n\t"
00473         "decl %%esi\n\t"
00474         "decl %%edi\n\t"
00475         "decl %%esi\n\t"
00476         "decl %%edi\n"
00477         "2:\trep\n\t"
00478         "movsl\n\t"
00479         "cld"
00480         : "=&c" (d0), "=&D" (d1), "=&S" (d2), "=&a" (d3)
00481         :"0"(count),"1"(count-4+(long)d),"2"(count-4+(long)s)
00482         :"memory");
00483     }
00484 }
00485 
00486 static __inline__ void *mymemmove(char *dst, const char *src, size_t size)
00487 {
00488     fast_memmove(dst, src, size);
00489     return dst;
00490 }
00491 
00492 #else /* !i386 */
00493 
00494     /*
00495      *  Anyone who'd like to write asm functions for other CPUs?
00496      *   (Why are these functions better than those from include/asm/string.h?)
00497      */
00498 
00499 static __inline__ void *mymemmove(void *d, const void *s, size_t count)
00500 {
00501     return(memmove(d, s, count));
00502 }
00503 
00504 static __inline__ void fast_memmove(char *dst, const char *src, size_t size)
00505 {
00506     memmove(dst, src, size);
00507 }
00508 
00509 #endif /* !i386 */
00510 
00511 #endif
00512 
00513 #endif /* _VIDEO_FBCON_H */