Распечатка 9.3 Обычный драйвер кадрового буфера

Предыдущая  Содержание  Следующая V*D*V

Распечатка 9.3

 

/* sfb.c */

 

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/errno.h>

#include <linux/string.h>

#include <linux/mm.h>

#include <linux/tty.h>

#include <linux/slab.h>

#include <linux/vmalloc.h>

#include <linux/delay.h>

#include <linux/interrupt.h>

#include <asm/uaccess.h>

#include <linux/fb.h>

#include <linux/init.h>

 

static char *videomemory = VIDEOMEMSTART;

static u_long videomemorysize = VIDEOMEMSIZE;

static struct fb_info fb_info;

 

/* Устанавливаем начальную информацию экрана */

static struct fb_var_screeninfo sfb_default __initdata = {

    .xres            = SFB_MAX_X,

    .yres            = SFB_MAX_Y,

    .xres_virtual    = SFB_MAX_X,

    .yres_virtual    = SFB_MAX_Y,

    .bits_per_pixel  = 8,

    .red             = { 0, 8, 0 },

    .green           = { 0, 8, 0 },

    .blue            = { 0, 8, 0 },

    .activate        = FB_ACTIVATE_TEST,

    .height          = -1,

    .width           = -1,

    .left_margin     = 0,

    .right_margin    = 0,

    .upper_margin    = 0,

    .lower_margin    = 0,

    .vmode           = FB_VMODE_NONINTERLACED,

};

static struct fb_fix_screeninfo sfb_fix __initdata = {

    .id        = "SimpleFB",

    .type      = FB_TYPE_PACKED_PIXELS,

    .visual    = FB_VISUAL_PSEUDOCOLOR,

    .xpanstep  = 1,

    .ypanstep  = 1,

    .ywrapstep = 1,

    .accel     = FB_ACCEL_NONE,

};

 

/* Прототипы функций */

int sfb_init(void);

int sfb_setup(char *);

static int sfb_check_var(struct fb_var_screeninfo *var,

                         struct fb_info *info);

static int sfb_set_par(struct fb_info *info);

static int sfb_setcolreg(u_int regno, u_int red, u_int green,

                         u_int blue, u_int transp,

                         struct fb_info *info);

static int sfb_pan_display(struct fb_var_screeninfo *var,

                           struct fb_info *info);

static int sfb_mmap(struct fb_info *info, struct file *file,

                    struct vm_area_struct *vma);

 

/*

 * Определяем структуру fb_ops, которая регистрируется в ядре.

 * Замечание: процедуры cfb_xxx - это универсальные процедуры,

 * реализованные в ядре. Можно их переопределить в случае, если

 * ваше оборудование предоставляет функции ускорения графики

 */

static struct fb_ops sfb_ops = {

    .fb_check_var = sfb_check_var,

    .fb_set_par   = sfb_set_par,

    .fb_setcolreg = sfb_setcolreg,

    .fb_fillrect  = cfb_fillrect,

    .fb_copyarea  = cfb_copyarea,

    .fb_imageblit = cfb_imageblit,

};

 

/*

 * Вспомните обсуждение о line_length в разделе о графическом

 * оборудовании. Длина строки выражается в байтах, обозначая

 * число байтов в каждой строке.

 */

static u_long get_line_length(int xres_virtual, int bpp)

{

    u_long line_length;

    line_length = xres_virtual * bpp;

    line_length = (line_length + 31) & ~31;

    line_length >>= 3;

    return (line_length);

}

 

/*

 * xxxfb_check_var, не пишет что-то в оборудование, а только

 * проверяет пригодность, базируясь на данных оборудования

 */

static int sfb_check_var(struct fb_var_screeninfo *var,

                         struct fb_info *info)

{

    u_long line_length;

    /* Проверяем достоверность разрешения экрана */

    if (!var->xres)

        var->xres = SFB_MIN_XRES;

    if (!var->yres)

        var->yres = SFB_MIN_YRES;

    if (var->xres > var->xres_virtual)

        var->xres_virtual = var->xres;

    if (var->yres > var->yres_virtual)

        var->yres_virtual = var->yres;

    if (sfb_check_bpp(var)) return –EINVAL;

    if (var->xres_virtual < var->xoffset + var->xres)

        var->xres_virtual = var->xoffset + var->xres;

    if (var->yres_virtual < var->yoffset + var->yres)

        var->yres_virtual = var->yoffset + var->yres;

 

    /*

     * Убедимся, что карта имеет достаточно видеопамяти в этом режиме

     * Вызываем формулу

     * Память к/б = Ширина Дисплея * Высота Дисплея * Байтов На Пиксель

     */

    line_length = get_line_length(var->xres_virtual,

                            var->bits_per_pixel);

    if (line_length * var->yres_virtual > videomemorysize)

        return -ENOMEM;

    sfb_fixup_var_modes(var);

    return 0;

}

 

/*

 * Эта процедура реально устанавливает видеорежим. Все проверки уже

 * были сделаны

 */

static int sfb_set_par(struct fb_info *info)

{

    sfb_program_hardware(info);

    info->fix.line_length = get_line_length(

                    info->var.xres_virtual,

                    info->var.bits_per_pixel);

    return 0;

}

 

/*

 * Устанавливаем один регистр цвета. Полученные значения уже

 * подогнаны к возможностям оборудования (соответствуют записям

 * в структуре var). Возвращаем != 0 для неверного regno.

 */

static int sfb_setcolreg(u_int regno, u_int red, u_int green,

                         u_int blue, u_int transp,

                         struct fb_info *info)

{

unsigned int *palette = SFB_PALETTE_START;

 

    if (regno >= SFB_MAX_PALLETE_REG) //номера аппаратных регистров

        return 1;

    unsigned int v = (red << info->var.red.offset) |

                    (green << info->var.green.offset) |

                    (blue << info->var.blue.offset) |

                    (transp << info->var.transp.offset);

 

    /* Программируем оборудование */

    *(palette+regno) = v;

    return 0;

}

 

/* Точка входа в драйвер */

int __init sfb_init(void)

{

    /* Заполняем структуру fb_info */

    fb_info.screen_base = io_remap(videomemory, vidememory);

    fb_info.fbops = &sfb_ops;

    fb_info.var = sfb_default;

    fb_info.fix = sfb_fix;

    fb_info.flags = FBINFO_FLAG_DEFAULT;

 

    fb_alloc_cmap(&fb_info.cmap, 256, 0);

 

    /* Регистрируем драйвер */

    if (register_framebuffer(&fb_info) < 0) {

        return -EINVAL;

    }

 

    printk(KERN_INFO "fb%d: Sample frame buffer device

                    initialized \n", fb_info.node);

 

    return 0;

}

 

static void __exit sfb_cleanup(void)

{

    unregister_framebuffer(&fb_info);

}

 

module_init(sfb_init);

module_exit(sfb_cleanup);

MODULE_LICENSE("GPL");

 

Предыдущая  Содержание  Следующая