Распечатка 9.3 Обычный драйвер кадрового буфера |
Предыдущая Содержание Следующая |
Распечатка 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");
|
Предыдущая Содержание Следующая |