CTC++ Coverage Report - Execution Profile    #826/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: drivers/video/fbmem.c
Instrumentation mode: function-decision-multicondition
TER: 15 % (104/704)

Start/ End/    
True False - Line Source

  1 /*
  2  *  linux/drivers/video/fbmem.c
  3  *
  4  *  Copyright (C) 1994 Martin Schaller
  5  *
  6  *   2001 - Documented with DocBook
  7  *   - Brad Douglas <brad@neruo.com>
  8  *
  9  * This file is subject to the terms and conditions of the GNU General Public
  10  * License.  See the file COPYING in the main directory of this archive
  11  * for more details.
  12  */
  13 
  14 #include <linux/config.h>
  15 #include <linux/module.h>
  16 
  17 #include <linux/compat.h>
  18 #include <linux/types.h>
  19 #include <linux/errno.h>
  20 #include <linux/sched.h>
  21 #include <linux/smp_lock.h>
  22 #include <linux/kernel.h>
  23 #include <linux/major.h>
  24 #include <linux/slab.h>
  25 #include <linux/mm.h>
  26 #include <linux/mman.h>
  27 #include <linux/tty.h>
  28 #include <linux/init.h>
  29 #include <linux/linux_logo.h>
  30 #include <linux/proc_fs.h>
  31 #include <linux/console.h>
  32 #ifdef CONFIG_KMOD
  33 #include <linux/kmod.h>
  34 #endif
  35 #include <linux/devfs_fs_kernel.h>
  36 #include <linux/err.h>
  37 #include <linux/kernel.h>
  38 #include <linux/device.h>
  39 #include <linux/efi.h>
  40 
  41 #if defined(__mc68000__) || defined(CONFIG_APUS)
  42 #include <asm/setup.h>
  43 #endif
  44 
  45 #include <asm/io.h>
  46 #include <asm/uaccess.h>
  47 #include <asm/page.h>
  48 #include <asm/pgtable.h>
  49 
  50 #include <linux/fb.h>
  51 
  52     /*
  53      *  Frame buffer device initialization and setup routines
  54      */
  55 
  56 #define FBPIXMAPSIZE   (1024 * 8)
  57 
  58 static struct notifier_block *fb_notifier_list;
  59 struct fb_info *registered_fb[FB_MAX];
  60 int num_registered_fb;
  61 
  62 /*
  63  * Helpers
  64  */
  65 
 
907974   66 int fb_get_color_depth(struct fb_var_screeninfo *var,
  67              struct fb_fix_screeninfo *fix)
  68 {
  69    int depth = 0;
  70 
  71    if (fix->visual == FB_VISUAL_MONO01 ||
907974 - 72        fix->visual == FB_VISUAL_MONO10)
 - 72   T || _
 - 72   F || T
 907974   72   F || F
  73       depth = 1;
    74    else {
  75       if (var->green.length == var->blue.length &&
  76           var->green.length == var->red.length &&
  77           var->green.offset == var->blue.offset &&
907974 - 78           var->green.offset == var->red.offset)
907974    78     T && T && T && T
 - 78     T && T && T && F
 - 78     T && T && F && _
 - 78     T && F && _ && _
 - 78     F && _ && _ && _
  79          depth = var->green.length;
    80       else
  81          depth = var->green.length + var->red.length +
  82             var->blue.length;
  83    }
  84 
907974    85    return depth;
  86 }
  87 EXPORT_SYMBOL(fb_get_color_depth);
  88 
  89 /*
  90  * Data padding functions.
  91  */
 
49855 49855   92 void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
  93 {
  94    __fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height);
  95 }
  96 EXPORT_SYMBOL(fb_pad_aligned_buffer);
  97 
 
- 98 void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height,
  99             u32 shift_high, u32 shift_low, u32 mod)
  100 {
  101    u8 mask = (u8) (0xfff << shift_high), tmp;
  102    int i, j;
  103 
- 104    for (i = height; i--; ) {
- 105       for (j = 0; j < idx; j++) {
  106          tmp = dst[j];
  107          tmp &= mask;
  108          tmp |= *src >> shift_low;
  109          dst[j] = tmp;
  110          tmp = *src << shift_high;
  111          dst[j+1] = tmp;
  112          src++;
  113       }
  114       tmp = dst[idx];
  115       tmp &= mask;
  116       tmp |= *src >> shift_low;
  117       dst[idx] = tmp;
- 118       if (shift_high < mod) {
  119          tmp = *src << shift_high;
  120          dst[idx+1] = tmp;
  121       }
  122       src++;
  123       dst += d_pitch;
  124    }
  125 }
  126 EXPORT_SYMBOL(fb_pad_unaligned_buffer);
  127 
  128 /*
  129  * we need to lock this section since fb_cursor
  130  * may use fb_imageblit()
  131  */
 
302579   132 char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size)
  133 {
  134    u32 align = buf->buf_align - 1, offset;
  135    char *addr = buf->addr;
  136 
  137    /* If IO mapped, we need to sync before access, no sharing of
  138     * the pixmap is done
  139     */
302579 - 140    if (buf->flags & FB_PIXMAP_IO) {
- 141       if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
 - 141     T && (T)
 - 141     T && (F)
 - 141     F && (_)
  142          info->fbops->fb_sync(info);
 - 143       return addr;
  144    }
  145 
  146    /* See if we fit in the remaining pixmap space */
  147    offset = buf->offset + align;
  148    offset &= ~align;
6145 296434   149    if (offset + size > buf->size) {
  150       /* We do not fit. In order to be able to re-use the buffer,
  151        * we must ensure no asynchronous DMA'ing or whatever operation
  152        * is in progress, we sync for that.
  153        */
6145 - 154       if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
 - 154     T && (T)
 6145   154     T && (F)
 - 154     F && (_)
  155          info->fbops->fb_sync(info);
  156       offset = 0;
  157    }
  158    buf->offset = offset + size;
  159    addr += offset;
  160 
302579    161    return addr;
  162 }
  163 
  164 #ifdef CONFIG_LOGO
  165 #include <linux/linux_logo.h>
  166 
 
- 167 static inline unsigned safe_shift(unsigned d, int n)
  168 {
    169    return n < 0 ? d >> -n : d << n;
- 169 ternary-?: n < 0
 - 169 return n < 0 ? d >> - n : d << n
  170 }
  171 
 
  172 static void fb_set_logocmap(struct fb_info *info,
  173                const struct linux_logo *logo)
  174 {
  175    struct fb_cmap palette_cmap;
  176    u16 palette_green[16];
  177    u16 palette_blue[16];
  178    u16 palette_red[16];
  179    int i, j, n;
  180    const unsigned char *clut = logo->clut;
  181 
  182    palette_cmap.start = 0;
  183    palette_cmap.len = 16;
  184    palette_cmap.red = palette_red;
  185    palette_cmap.green = palette_green;
  186    palette_cmap.blue = palette_blue;
  187    palette_cmap.transp = NULL;
  188 
72   189    for (i = 0; i < logo->clutsize; i += n) {
  190       n = logo->clutsize - i;
  191       /* palette_cmap provides space for only 16 colors at once */
66   192       if (n > 16)
  193          n = 16;
  194       palette_cmap.start = 32 + i;
  195       palette_cmap.len = n;
1122 72   196       for (j = 0; j < n; ++j) {
  197          palette_cmap.red[j] = clut[0] << 8 | clut[0];
  198          palette_cmap.green[j] = clut[1] << 8 | clut[1];
  199          palette_cmap.blue[j] = clut[2] << 8 | clut[2];
  200          clut += 3;
  201       }
  202       fb_set_cmap(&palette_cmap, info);
  203    }
  204 }
  205 
 
- 206 static void  fb_set_logo_truepalette(struct fb_info *info,
  207                    const struct linux_logo *logo,
  208                    u32 *palette)
  209 {
  210    unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
  211    unsigned char redmask, greenmask, bluemask;
  212    int redshift, greenshift, blueshift;
  213    int i;
  214    const unsigned char *clut = logo->clut;
  215 
  216    /*
  217     * We have to create a temporary palette since console palette is only
  218     * 16 colors long.
  219     */
  220    /* Bug: Doesn't obey msb_right ... (who needs that?) */
    221    redmask   = mask[info->var.red.length   < 8 ? info->var.red.length   : 8];
- 221 ternary-?: info -> var . red . length < 8
    222    greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
- 222 ternary-?: info -> var . green . length < 8
    223    bluemask  = mask[info->var.blue.length  < 8 ? info->var.blue.length  : 8];
- 223 ternary-?: info -> var . blue . length < 8
  224    redshift   = info->var.red.offset   - (8 - info->var.red.length);
  225    greenshift = info->var.green.offset - (8 - info->var.green.length);
  226    blueshift  = info->var.blue.offset  - (8 - info->var.blue.length);
  227 
- 228    for ( i = 0; i < logo->clutsize; i++) {
  229       palette[i+32] = (safe_shift((clut[0] & redmask), redshift) |
  230              safe_shift((clut[1] & greenmask), greenshift) |
  231              safe_shift((clut[2] & bluemask), blueshift));
  232       clut += 3;
  233    }
  234 }
  235 
 
- 236 static void fb_set_logo_directpalette(struct fb_info *info,
  237                     const struct linux_logo *logo,
  238                     u32 *palette)
  239 {
  240    int redshift, greenshift, blueshift;
  241    int i;
  242 
  243    redshift = info->var.red.offset;
  244    greenshift = info->var.green.offset;
  245    blueshift = info->var.blue.offset;
  246 
- 247    for (i = 32; i < logo->clutsize; i++)
  248       palette[i] = i << redshift | i << greenshift | i << blueshift;
  249 }
  250 
 
- 251 static void fb_set_logo(struct fb_info *info,
  252                 const struct linux_logo *logo, u8 *dst,
  253                 int depth)
  254 {
  255    int i, j, k;
  256    const u8 *src = logo->data;
    257    u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
- 257 ternary-?: ( info -> fix . visual == 0 )
  258    u8 fg = 1, d;
  259 
- 260    if (fb_get_color_depth(&info->var, &info->fix) == 3)
  261       fg = 7;
  262 
  263    if (info->fix.visual == FB_VISUAL_MONO01 ||
- 264        info->fix.visual == FB_VISUAL_MONO10)
 - 264   T || _
 - 264   F || T
 - 264   F || F
  265       fg = ~((u8) (0xfff << info->var.green.length));
  266 
    267    switch (depth) {
 - 268    case 4:
- 269       for (i = 0; i < logo->height; i++)
- 270          for (j = 0; j < logo->width; src++) {
  271             *dst++ = *src >> 4;
  272             j++;
- 273             if (j < logo->width) {
  274                *dst++ = *src & 0x0f;
  275                j++;
  276             }
  277          }
 - 278       break;
 - 279    case 1:
- 280       for (i = 0; i < logo->height; i++) {
- 281          for (j = 0; j < logo->width; src++) {
  282             d = *src ^ xor;
- 283             for (k = 7; k >= 0; k--) {
    284                *dst++ = ((d >> k) & 1) ? fg : 0;
- 284         ternary-?: ( ( d >> k ) & 1 )
  285                j++;
  286             }
  287          }
  288       }
 - 289       break;
  290    }
  291 }
  292 
  293 /*
  294  * Three (3) kinds of logo maps exist.  linux_logo_clut224 (>16 colors),
  295  * linux_logo_vga16 (16 colors) and linux_logo_mono (2 colors).  Depending on
  296  * the visual format and color depth of the framebuffer, the DAC, the
  297  * pseudo_palette, and the logo data will be adjusted accordingly.
  298  *
  299  * Case 1 - linux_logo_clut224:
  300  * Color exceeds the number of console colors (16), thus we set the hardware DAC
  301  * using fb_set_cmap() appropriately.  The "needs_cmapreset"  flag will be set.
  302  *
  303  * For visuals that require color info from the pseudo_palette, we also construct
  304  * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags
  305  * will be set.
  306  *
  307  * Case 2 - linux_logo_vga16:
  308  * The number of colors just matches the console colors, thus there is no need
  309  * to set the DAC or the pseudo_palette.  However, the bitmap is packed, ie,
  310  * each byte contains color information for two pixels (upper and lower nibble).
  311  * To be consistent with fb_imageblit() usage, we therefore separate the two
  312  * nibbles into separate bytes. The "depth" flag will be set to 4.
  313  *
  314  * Case 3 - linux_logo_mono:
  315  * This is similar with Case 2.  Each byte contains information for 8 pixels.
  316  * We isolate each bit and expand each into a byte. The "depth" flag will
  317  * be set to 1.
  318  */
  319 static struct logo_data {
  320    int depth;
  321    int needs_directpalette;
  322    int needs_truepalette;
  323    int needs_cmapreset;
  324    const struct linux_logo *logo;
  325 } fb_logo;
  326 
 
- 327 static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height)
  328 {
  329    u32 size = width * height, i;
  330 
  331    out += size - 1;
  332 
- 333    for (i = size; i--; )
  334       *out-- = *in++;
  335 }
  336 
 
- 337 static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height)
  338 {
  339    int i, j, w = width - 1;
  340 
- 341    for (i = 0; i < height; i++)
- 342       for (j = 0; j < width; j++)
  343          out[height * j + w - i] = *in++;
  344 }
  345 
 
- 346 static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height)
  347 {
  348    int i, j, w = width - 1;
  349 
- 350    for (i = 0; i < height; i++)
- 351       for (j = 0; j < width; j++)
  352          out[height * (w - j) + i] = *in++;
  353 }
  354 
 
- 355 static void fb_rotate_logo(struct fb_info *info, u8 *dst,
  356             struct fb_image *image, int rotate)
  357 {
  358    u32 tmp;
  359 
- 360    if (rotate == FB_ROTATE_UD) {
  361       image->dx = info->var.xres - image->width;
  362       image->dy = info->var.yres - image->height;
  363       fb_rotate_logo_ud(image->data, dst, image->width,
  364               image->height);
- 365    } else if (rotate == FB_ROTATE_CW) {
  366       tmp = image->width;
  367       image->width = image->height;
  368       image->height = tmp;
  369       image->dx = info->var.xres - image->height;
  370       fb_rotate_logo_cw(image->data, dst, image->width,
  371               image->height);
- 372    } else if (rotate == FB_ROTATE_CCW) {
  373       tmp = image->width;
  374       image->width = image->height;
  375       image->height = tmp;
  376       image->dy = info->var.yres - image->width;
  377       fb_rotate_logo_ccw(image->data, dst, image->width,
  378                image->height);
  379    }
  380 
  381    image->data = dst;
  382 }
  383 
 
  384 static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
  385              int rotate)
  386 {
  387    int x;
  388 
- 389    if (rotate == FB_ROTATE_UR) {
  390       for (x = 0; x < num_online_cpus() &&
  391               x * (fb_logo.logo->width + 8) <=
  392               info->var.xres - fb_logo.logo->width; x++) {
   392     T && T
 - 392     T && F
   392     F && _
  393          info->fbops->fb_imageblit(info, image);
  394          image->dx += fb_logo.logo->width + 8;
  395       }
- 396    } else if (rotate == FB_ROTATE_UD) {
  397       for (x = 0; x < num_online_cpus() &&
  398               x * (fb_logo.logo->width + 8) <=
- 399               info->var.xres - fb_logo.logo->width; x++) {
 - 399     T && T
 - 399     T && F
 - 399     F && _
  400          info->fbops->fb_imageblit(info, image);
  401          image->dx -= fb_logo.logo->width + 8;
  402       }
- 403    } else if (rotate == FB_ROTATE_CW) {
  404       for (x = 0; x < num_online_cpus() &&
  405               x * (fb_logo.logo->width + 8) <=
- 406               info->var.yres - fb_logo.logo->width; x++) {
 - 406     T && T
 - 406     T && F
 - 406     F && _
  407          info->fbops->fb_imageblit(info, image);
  408          image->dy += fb_logo.logo->width + 8;
  409       }
- 410    } else if (rotate == FB_ROTATE_CCW) {
  411       for (x = 0; x < num_online_cpus() &&
  412               x * (fb_logo.logo->width + 8) <=
- 413               info->var.yres - fb_logo.logo->width; x++) {
 - 413     T && T
 - 413     T && F
 - 413     F && _
  414          info->fbops->fb_imageblit(info, image);
  415          image->dy -= fb_logo.logo->width + 8;
  416       }
  417    }
  418 }
  419 
 
  420 int fb_prepare_logo(struct fb_info *info, int rotate)
  421 {
  422    int depth = fb_get_color_depth(&info->var, &info->fix);
  423    int yres;
  424 
  425    memset(&fb_logo, 0, sizeof(struct logo_data));
  426 
- 427    if (info->flags & FBINFO_MISC_TILEBLITTING)
 - 428       return 0;
  429 
- 430    if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
  431       depth = info->var.blue.length;
- 432       if (info->var.red.length < depth)
  433          depth = info->var.red.length;
- 434       if (info->var.green.length < depth)
  435          depth = info->var.green.length;
  436    }
  437 
- 438    if (depth >= 8) {
    439       switch (info->fix.visual) {
 - 440       case FB_VISUAL_TRUECOLOR:
  441          fb_logo.needs_truepalette = 1;
 - 442          break;
 - 443       case FB_VISUAL_DIRECTCOLOR:
  444          fb_logo.needs_directpalette = 1;
  445          fb_logo.needs_cmapreset = 1;
 - 446          break;
   447       case FB_VISUAL_PSEUDOCOLOR:
  448          fb_logo.needs_cmapreset = 1;
   449          break;
  450       }
  451    }
  452 
  453    /* Return if no suitable logo was found */
  454    fb_logo.logo = fb_find_logo(depth);
  455 
- 456    if (!fb_logo.logo) {
 - 457       return 0;
  458    }
  459    
- 460    if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)
   460   T || _
 - 460   F || T
 - 460   F || F
  461       yres = info->var.yres;
    462    else
  463       yres = info->var.xres;
  464 
- 465    if (fb_logo.logo->height > yres) {
  466       fb_logo.logo = NULL;
 - 467       return 0;
  468    }
  469 
  470    /* What depth we asked for might be different from what we get */
- 471    if (fb_logo.logo->type == LINUX_LOGO_CLUT224)
  472       fb_logo.depth = 8;
- 473    else if (fb_logo.logo->type == LINUX_LOGO_VGA16)
  474       fb_logo.depth = 4;
    475    else
  476       fb_logo.depth = 1;      
   477    return fb_logo.logo->height;
  478 }
  479 
 
  480 int fb_show_logo(struct fb_info *info, int rotate)
  481 {
  482    u32 *palette = NULL, *saved_pseudo_palette = NULL;
  483    unsigned char *logo_new = NULL, *logo_rotate = NULL;
  484    struct fb_image image;
  485 
  486    /* R