The website "dmilvdv.narod.ru." is not registered with uCoz.
If you are absolutely sure your website must be here,
please contact our Support Team.
If you were searching for something on the Internet and ended up here, try again:

About uCoz web-service

Community

Legal information

sceletonfb.c

sceletonfb.c

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

/*

 * linux/drivers/video/skeletonfb.c -- скелет для устройства с кадровым буфером

 *

 *  Modified to new api Jan 2001 by James Simmons (jsimmons@transvirtual.com)

 *

 *  Created 28 Dec 1997 by Geert Uytterhoeven

 *

 *

 *  Я начал переписывать этот драйвер в качестве примера развития нового API.

 *  Основной целью является удалить код консоли из fbdev и поместить его

 *  в fbcon.c. Это сокращает код и делает написание нового драйвера fbdev

 *  простым, так как автору не нужно беспокоиться о внутренностях консоли. Это

 *  также позволяет запускать fbdev без системы консоли/терминала поверх

 *  него.

 *

 *  Первоначальные роли структур fb_info и display изменились. Структура display

 *  исчезнет. Способ, которым будет работать код новой консоли с кадровым буфером,

 *  заключается в том, что он будет воздействовать на передачу данных от терминала/

 *  консоли в структуре vc_data в аппаратно-независимые данные в структуре fb_info.

 *  Затем для сохранения устройство-зависимого состояния в аналогичном поле

 *  в структуре fb_info и изменения состояния оборудования для соответствия этому

 *  состоянию будут вызываться разные функции в структуре fb_ops. Это позволяет

 *  очень точно отделить слой fbdev от слоя консоли. Это также позволяет

 *  использовать fbdev отдельно, что является бонусом для встраиваемых устройств.

 *  Причиной, по которой такой подход работает, является то, что для каждого

 *  устройства с кадровым буфером при использовании в качестве терминального/

 *  консольного устройства к нему выделяется набор виртуальных терминалов. Для

 *  каждого устройства с кадровым буфером может быть активен только один

 *  виртуальный терминал. У нас уже есть все данные, необходимые нам, в структуре

 *  vc_data, так зачем в каждом виртуальном терминале хранить кучу цветовых схем

 *  и других специфичных данных для fbdev.

 *

 *  Как можно увидеть, это делает параметр con, в значительный степени бесполезный

 *  для структуры функций fb_ops, как это и должно быть. Кроме того, наличие в

 *  fb_info структуры fb_var_screeninfo и других данных почти исключает

 *  необходимость в get_fix и get_var. После того, как все драйверы начнут

 *  использовать fix, var и cmap, fbcon можно написать с использованием этих полей.

 *  Это также избавит от необходимости восстанавливать структуры fb_var_screeninfo,

 *  fb_fix_screeninfo и fb_cmap каждый раз при вызове функций get_var, get_fix,

 *  get_cmap, как это делают сейчас многие драйверы.

 *

 *  Этот файл подчиняется условиям использования GNU General Public License.

 *  Для подробностей смотрите файл COPYING в основном каталоге этого архива.

 */

 

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/errno.h>

#include <linux/string.h>

#include <linux/mm.h>

#include <linux/slab.h>

#include <linux/delay.h>

#include <linux/fb.h>

#include <linux/init.h>

#include <linux/pci.h>

 

    /*

     *  Это всего лишь простой пример кода.

     *

     *  Нет гарантии, что он скомпилируется.

     *  Ещё меньше гарантий, что он заработает :-)

     */

 

/*

 * Данные драйвера

 */

static char *mode_option __devinitdata;

 

/*

 *  Если ваш драйвер поддерживает несколько плат, вы должны сделать ниже

 *  массивы с необходимыми типами данных, или создать их динамически

 *  (используя kmalloc()).

 */ 

 

/* 

 * Эта структура определяет состояние оборудования графической видеокарты.

 * Обычно это размещается в файле заголовка в linux/include/video. Этот файл

 * обычно также включает информацию о регистрах. Это позволяет другим

 * драйверным подсистемам и приложениям пользовательского пространства

 * использовать один и тот же заголовочный файл, чтобы избежать двойной

 * работы и упростить переносимость программного обеспечения.

 */

struct xxx_par;

 

/*

 * Здесь определяется значение по умолчанию для структур fb_fix_screeninfo и

 * fb_var_screeninfo, если не используется modedb. Если modedb действительно

 * используется, как использовать его, чтобы получить fb_var_screeninfo,

 * смотрите xxxfb_init. В противном случае определите переменную по умолчанию

 * также.

 */

static struct fb_fix_screeninfo xxxfb_fix __devinitdata = {

    .id =        "FB's name", 

    .type =      FB_TYPE_PACKED_PIXELS,

    .visual =    FB_VISUAL_PSEUDOCOLOR,

    .xpanstep =  1,

    .ypanstep =  1,

    .ywrapstep = 1, 

    .accel =     FB_ACCEL_NONE,

};

 

    /*

     *  Современные графические аппаратные средства не только поддерживают

     *  конвейеры, некоторые также поддерживают несколько мониторов, где

     *  у каждого дисплея могут быть собственные уникальные данные. В этом

     *  случае каждый дисплей мог бы быть представлен отдельным устройством

     *  с кадровым буфером, то есть с отдельной структурой fb_info.

     *  Сейчас структура xxx_par представляет состояние графического

     *  оборудования таким образом, что на каждую карту существует только

     *  одна. В данном случае структура xxx_par для каждой видеокарты была

     *  бы общей для всех структур fb_info, которые представляют кадровый

     *  буфер такой платы. Когда один дисплей изменяет свои параметры

     *  разрешения (info->var), это позволяет другим дисплеям узнать об этом

     *  немедленно. Каждый дисплей может всегда узнать о состоянии всего

     *  оборудования, которое его затрагивает, потому что они совместно

     *  используют одну и ту же структуру xxx_par. Другая сторона монеты

     *  - несколько видеокарт, которые раздают данные, пока они наконец

     *  не отображены на одном мониторе. Примерами этого являются карты

     *  Voodoo 1 и мощные серверы графики с NUMA. Для этого случая у нас

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

     *  графики, которая принадлежит одной структуре fb_info. В этом случае

     *  Вы бы захотели иметь *par, указывающий на массив состояний

     *  устройств и иметь отдельную структуру функций fb_ops, чтобы иметь

     *  дело со всеми этими состояниями. Я надеюсь, что это покрывает все

     *  возможные варианты дизайна оборудоания. Если нет, посылайте не

     *  стесняясь ваши идеи на jsimmons@users.sf.net

     */

 

    /*

     *  Если ваш драйвер поддерживает несколько плат, или поддерживает

     *  несколько кадровых буферов, вы должны создать эти массивы или

     *  получить их динамически используя framebuffer_alloc() и освободить

     *  их с помощью framebuffer_release().

     */ 

static struct fb_info info;

 

    /* 

     * Каждая представляет собой состояние оборудования. У большинства

     * оборудования есть только одно состояние. Здесь представлено

     * заданное по умолчанию состояние(я).

     */

static struct xxx_par __initdata current_par;

 

int xxxfb_init(void);

 

/**

 *    xxxfb_open - Необязательная функция. Вызывается при первом обращении

 *                 к кадровому буферу.

 *    @info: структура кадрового буфера, которая представляет собой один 

 *            кадровый буфер.

 *    @user: сообщает, кто обращается к буферу, пользовательское

 *            пространство (значение=1), или консоль.

 *

 *    Эта функция является первой функцией, вызываемой в api кадрового

 *    буфера. Обеспечивать эту функцию обычно нет необходимости. Случаем,

 *    когда она используется, является смена тестового режима оборудования

 *    на графический режим. 

 *

 *    Возвращает отрицательное значение при ошибке или ноль при

 *    успешном завершении.

 */

static int xxxfb_open(struct fb_info *info, int user)

{

    return 0;

}

 

/**

 *    xxxfb_release - Необязательная функция. Вызывается при закрытии

 *                устройства с кадровым буфером. 

 *    @info: структура кадрового буфера, которая представляет собой один 

 *            кадровый буфер.

 *    @user: сообщает, кто обращается к буферу, пользовательское

 *            пространство (значение=1), или консоль.

 *

 *    Эта функция вызывается при закрытии /dev/fb или при отключении

 *    консольной системы с кадровым буфером. Обычно в этой функции нет

 *    необходимости. Случаем, когда она обычно используется, является

 *    переход из графического в текстовый режим.

 *

 *    Возвращает отрицательное значение при ошибке или ноль при

 *    успешном завершении.

 */

static int xxxfb_release(struct fb_info *info, int user)

{

    return 0;

}

 

/**

 *    xxxfb_check_var - Необязательная функция. Проверяет переданную в

 *                    неё var. 

 *    @var: переменная кадрового буфера экранной структуры

 *    @info: структура кадрового буфера, представляющая один кадровый буфер 

 *

 *    Выясняет, поддерживает ли оборудование состояние, которое затребовано

 *    переданной в неё переменной var. Эта функция не изменяет состояние

 *    оборудования!!! Это означает, что данные, хранящиеся в структурах

 *    fb_info и xxx_par, не изменяются. Это включает и переменную var в

 *    структуре fb_info. НЕ изменяйте их. Эта функция может быть вызвана

 *    самостоятельно, если мы намерены только проверить режим, а не

 *    фактически установить его. Материал в modedb.c - пример этого. Если

 *    переданная переменная var немного за пределами того, что может

 *    поддержать оборудование, мы изменяем эту ПЕРЕДАВАЕМУЮ переменную var,

 *    на то, что может быть выполнено.

 *

 *    Для значений, которые вне пределов, эта функция должен округлить их

 *    _вверх_ до следующего значения, поддерживаемого оборудованием. Если

 *    значение больше, чем самое высокое значение, поддерживаемое

 *    оборудованием, эта функция должна возвратить -EINVAL.

 *

 *    Исключение к вышеупомянутому правилу: некоторые драйверы имеют

 *    фиксированный режим, то есть оборудование уже проинициализировано при

 *    загрузке и он не может быть изменён. В этом случае более приемлемо,

 *    чтобы эта функция только возвращала копию используемой в настоящее

 *    время рабочей переменной var (info->var). Лучше не реализовывать эту

 *    функцию, поскольку верхний уровень сделает копирование текущей

 *    переменной var за вас.

 *

 *    Замечание: это единственная функция, где содержание var может быть

 *    свободно откорректировано после того, как драйвер был зарегистрирован.

 *    Если вы находите, что у вас есть код за пределами этой функции,

 *    который изменяет содержание var, то вы делаете что-то не так.

 *    Обратите внимание также, что содержание info->var должно оставаться

 *    нетронутым всё время после регистрации драйвера.

 *

 *    Возвращает отрицательное значение при ошибке или ноль при

 *    успешном завершении.

 */

static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)

{

    /* ... */

    return 0;                   

}

 

/**

 *    xxxfb_set_par - Необязательная функция. Изменяет состояние оборудования.

 *    @info: структура кадрового буфера, представляющая один кадровый буфер.

 *

 *    Используя fb_var_screeninfo в fb_info мы устанавливаем разрешение этого

 *    конкретного кадрового буфера. Эта функция изменяет par И fb_fix_screeninfo,

 *    сохранённый в fb_info. Это не изменяет var в fb_info, так как мы

 *    используем эти данные. Это означает, что мы зависим от данных в var

 *    внутри fb_info, чтобы быть поддержанными оборудованием.

 *

 *    Эта функция также используется, чтобы возвратить/восстановить оборудование

 *    в известное рабочее состояние.

 *

 *    Перед xxxfb_set_par всегда вызывается xxxfb_check_var, для уверенности,

 *    что содержимое var всегда корректно.

 *

 *    И снова, если изменить разрешение нельзя, в этой функции нет необходимости.

 *

 *    Однако, даже если ваше оборудование не поддерживает изменение режима,

 *    set_par мог бы быть необходим, чтобы по крайней мере проинициализировать

 *    оборудование в известное рабочее состояние, особенно, если бы это

 *    происходило при возвращении из другого процесса, который также изменяет это

 *    же самое оборудование, такого, как X.

 *

 *    Если дело обстоит таким образом, должна работать следующая комбинация:

 *

 *    static int xxxfb_check_var(struct fb_var_screeninfo *var,

 *                               struct fb_info *info)

 *    {

 *        *var = info->var;

 *        return 0;

 *    }

 *

 *    static int xxxfb_set_par(struct fb_info *info)

 *    {

 *        инициализируйте здесь ваше оборудование

 *    }

 *

 *    Возвращает отрицательное значение при ошибке или ноль при

 *    успешном завершении.

 */

static int xxxfb_set_par(struct fb_info *info)

{

    struct xxx_par *par = info->par;

    /* ... */

    return 0;        

}

 

/**

 *    xxxfb_setcolreg - Необязательная функция. Устанавливает регистр цвета.

 *    @regno: Какой регистр в CLUT (таблица цветов) программируется.

 *    @red: Значение красного, которое может быть до 16 бит.

 *    @green: Значение зелёного, которое может быть до 16 бит.

 *    @blue: Значение синего, которое может быть до 16 бит.

 *    @transp: Значение альфа-канала, если поддерживается, может быть до 16 бит.

 *    @info: структура с информацией о кадровом буфере.

 *

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

 *    имеют размерность в 16 бит, которую необходимо отмасштабировать в этой

 *    функции для данного оборудования. Необходимо учесть, сколько регистров

 *    цвета, если таковые вообще имеются, поддерживаются текущей визуализацией

 *    цвета. В режиме truecolor никакие цветовые палитры не поддерживаются.

 *    Здесь создаётся псевдо палитра, для которой мы сохраняем значение в

 *    pseudo_palette в структуре fb_info. Для режима pseudocolor у нас

 *    есть ограниченная цветовая палитра. Чтобы иметь дело с этим, мы можем

 *    запрограммировать, какой цвет отображается для специфического значения

 *    пикселя. DirectColor аналогичен тому, в котором мы можем программировать

 *    каждое цветовое поле. Если у нас есть статическая цветовая таблица,

 *    реализовывать эту функцию нет необходимости.

 *

 *    Возвращает отрицательное значение при ошибке или ноль при

 *    успешном завершении.

 */

static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,

                           unsigned blue, unsigned transp,

                           struct fb_info *info)

{

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

        return -EINVAL;

    /*

     * Программируем оборудование... делаем всё, что хотим

     */

 

    /* в directcolor оттенки серого работают лишь частично */

    if (info->var.grayscale) {

       /* grayscale = 0.30*R + 0.59*G + 0.11*B */

       red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;

    }

 

    /* Directcolor:

     *    var->{color}.offset содержит начало битового поля

     *    var->{color}.length содержит длину битового поля

     *    {зависит от обрудования} содержит разрядность ЦАП

     *    pseudo_palette[X] программируется в (X << red.offset) |

     *                                      (X << green.offset) |

     *                                      (X << blue.offset)

     *    RAMDAC[X] программируется в (red, green, blue)

     *    глубина цвета = SUM(var->{color}.length)

     *

     * Pseudocolor:

     *    var->{color}.offset 0, если индекс палитры занимает меньше,

     *                        чем bits_per_pixel бит и хранится в старших

     *                        битах значения пикселя

     *    var->{color}.length устанавливается так, что 1 << length является

     *                        числом доступных в палитре записей

     *    pseudo_palette не используется

     *    RAMDAC[X] программируется в (red, green, blue)

     *    глубина цвета = var->{color}.length

     *

     * Static pseudocolor:

     *    так же как Pseudocolor, но RAMDAC не программируется (только читается)

     *

     * Mono01/Mono10:

     *    Имеет только 2 значения, чёрный на белом или белый на чёрном (fg на bg),

     *    var->{color}.offset равен 0

     *    white = (1 << var->{color}.length) - 1, black = 0

     *    pseudo_palette не используется

     *    RAMDAC не существует

     *    глубина цвета всегда 2

     *

     * Truecolor:

     *    does not use RAMDAC (usually has 3 of them).

     *    var->{color}.offset contains start of bitfield

     *    var->{color}.length contains length of bitfield

     *    pseudo_palette программируется в (red << red.offset) |

     *                                    (green << green.offset) |

     *                                    (blue << blue.offset) |

     *                                    (transp << transp.offset)

     *    RAMDAC не существует

     *    глубина цвета = SUM(var->{color}.length)

     *

     *  Глубина цвета используется fbcon для выбора логотипа, а также

     *  для преобразования цветовой палитры, если глубина цвета < 4.

     *

     *  Как видно из сказанного выше, поле bits_per_pixel _НЕ_ является

     *  критерием для описания видимого цвета.

     *

     *  Распространённой ошибкой является предположение, что

     *  bits_per_pixel <= 8 представляет собой pseudocolor, а выше, чем это,

     *  true/directcolor. Это неправильно, надо смотреть на fix->visual.

     *

     *  Другой распространённой ошибкой является использование bits_per_pixel

     *  для расчёта глубины цвета. Поле bits_per_pixel не перевести

     *  непосредственно в глубину цвета. Необходимы вычисления для глубины

     *  цвета (с помощью цветовых битовых полей) и fix->visual, как показано

     *  выше.

     */

 

    /*

     * Это та точка, где цвет превращается во что-то, понятное оборудованию.

     */

#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)

    red = CNVT_TOHW(red, info->var.red.length);

    green = CNVT_TOHW(green, info->var.green.length);

    blue = CNVT_TOHW(blue, info->var.blue.length);

    transp = CNVT_TOHW(transp, info->var.transp.length);

#undef CNVT_TOHW

    /*

     * Это та точка, где эта функция загружает цвет в палитру оборудования

     * после преобразования цветов к чему-то понятному оборудованию.

     * Обратите внимание, только в режимах FB_VISUAL_DIRECTCOLOR и

     * FB_VISUAL_PSEUDOCOLOR необходимо писать в аппаратную палитру.

     * Если у вас есть код, который пишет в аппаратную CLUT (таблицу цветов),

     * и это не один из вышеприведённых режимов, вы делаете что-то неправильно.

     */

    if (info->fix.visual == FB_VISUAL_DIRECTCOLOR ||

        info->fix.visual == FB_VISUAL_TRUECOLOR)

        write_{red|green|blue|transp}_to_clut();

 

    /*

     * Именно на этом этапе было необходимо заполнить содержание

     * info->pseudo_palette. Эта структура используется _только_ в fbcon,

     * так что она содержит только 16 записей в соответствии с числом цветов,

     * поддерживаемых консолью. pseudo_palette используется только тогда,

     * когда визуализация происходит в режиме directcolor или truecolor.

     * В других режимах визуализации pseudo_palette не используется.

     * (Это может измениться в будущем.)

     *

     * Содержание pseudo_palette представляет собой необработанный формат

     * пиксела. То есть каждая запись может быть записана непосредственно в

     * кадровый буфер без какого-либо преобразования. pseudo_palette является

     * (void *). Тем не менее, при использовании общих функций рисования

     * (cfb_imageblit, cfb_fillrect), pseudo_palette должна быть приведена к

     * (u32 *) _независимо_ от числа битов на пиксель. Если драйвер использует

     * свои собственные функции рисования, то он может использовать любую

     * размерность, какую хочет.

     */

    if (info->fix.visual == FB_VISUAL_TRUECOLOR ||

        info->fix.visual == FB_VISUAL_DIRECTCOLOR) {

        u32 v;

 

        if (regno >= 16)

            return -EINVAL;

 

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

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

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

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

 

        ((u32*)(info->pseudo_palette))[regno] = v;

    }

 

    /* ... */

    return 0;

}

 

/**

 *    xxxfb_pan_display - НЕ обязательная функция. Панорамирует дисплей.

 *    @var: переменная кадрового буфера экранной структуры

 *    @info: структура кадрового буфера, представляющая один кадровый буфер.

 *

 *    Панорамирование (или прокрутка, зависит от поля `vmode') дисплея,

 *    используя поля `xoffset' и `yoffset' в структуре `var'.

 *    Если значения не соответствующие, возвращает -EINVAL.

 *

 *    Возвращает отрицательное значение при ошибке или ноль при

 *    успешном завершении.

 */

static int xxxfb_pan_display(struct fb_var_screeninfo *var,

                             struct fb_info *info)

{

    /*

     * Если ваше оборудование не поддерживает панорамирование, _не_

     * реализуйте эту функцию. Создание пустой функции только запутает

     * пользовательские приложения.

     */

 

    /*

     * Заметим, что даже если эта функция является полнофункциональной,

     * значение 0 в обоих xpanstep и ypanstep означает, что эта функция

     * никогда не будет вызвана.

     */

 

    /* ... */

    return 0;

}

 

/**

 *    xxxfb_blank - НЕ обязательная функция. Гашение дисплея.

 *    @blank_mode: желаемый режим гашения. 

 *    @info: структура кадрового буфера, представляющая один кадровый буфер.

 *

 *    Экран гасится, если blank_mode != FB_BLANK_UNBLANK, иначе не гасится.

 *    Возвращает 0, если гашение успешно, != 0, если не/гашение неудачно,

 *    так как видеорежим не поддерживается.

 *

 *    Реализует режимы VESA для приостановки и выключения питания

 *    оборудования, поддерживающем отключение вертикальной и горизонтальной

 *    синхронизации:

 *

 *    FB_BLANK_NORMAL = дисплей погашен, синхронизация работает.

 *    FB_BLANK_HSYNC_SUSPEND = выключена горизонтальная синхронизация.

 *    FB_BLANK_VSYNC_SUSPEND = выключена вертикальная синхронизация.

 *    FB_BLANK_POWERDOWN = горизонтальная и вертикальная синхронизация выключена.

 *

 *    Если эта функция реализуется, по крайней мере поддержите FB_BLANK_UNBLANK.

 *    Верните !0 для всех режимов, которые не реализованы.

 *

 */

static int xxxfb_blank(int blank_mode, struct fb_info *info)

{

    /* ... */

    return 0;

}

 

/* ----------------- Функции ускорения --------------------- */

 

/*

 * Мы предоставляем свои функции, если у нас есть аппаратное ускорение

 * или схемы размещения пикселей в неупакованном формате. Если у нас

 * нет аппаратного ускорения, мы можем использовать общие функции

 * без акселерации. Если используется формат упакованных пикселей,

 * просто используйте функции в cfb_*.c. Каждый файл имеет одну из

 * трёх различных функций ускорения, которые мы поддерживаем.

 */

 

/**

 *    xxxfb_fillrect - ОБЯЗАТЕЛЬНАЯ функция. Если оборудование не

 *                    поддерживает ускорение и используются упакованные

 *                    пиксели, можно использовать стандартные подпрограммы.

 *                    Рисует на экране прямоугольник.

 *

 *    @info: структура кадрового буфера, представляющая один кадровый буфер.

 *    @region: структура, представляющая прямоугольную область, которую мы

 *            желаем отрисовать.

 *

 *    Она выполняет операцию по отрисовке для размещения/удаления на экране

 *    прямоугольника в зависимости от операции растеризации со значением

 *    цвета в формате текущей глубины цвета.

 */

void xxxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region)

{

/*    Содержание структуры fb_fillrect

 *

 *    @dx: x и y координаты верхнего левого угла

 *    @dy: области, которую мы хотим отрисовать.

 *    @width: Ширина прямоугольника, который мы хотим нарисовать.

 *    @height: Высота прямоугольника, который мы хотим нарисовать.

 *    @color:        Цвет заполнения прямоугольника.

 *    @rop: Операция растеризации. Мы можем рисовать прямоугольник с помощью

 *            COPY или XOR, предоставляющий эффект стирания. 

 */

}

 

/**

 *    xxxfb_copyarea - ОБЯЗАТЕЛЬНАЯ функция. Если оборудование не

 *                    поддерживает ускорение и используются упакованные

 *                    пиксели, можно использовать стандартные подпрограммы.

 *                    Копирует одну область экрана в другую.

 *

 *    @info: структура кадрового буфера, представляющая один кадровый буфер.

 *    @area: Структура, представляющая данные для копирования

 *            содержимого кадрового буфера из одной области в другую.

 *

 *    Этот операция отрисовки копирует прямоугольную область из одного места

 *    экрана в другое.

 */

void xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) 

{

/*

 *    @dx: x и y координаты верхнего левого угла

 *    @dy: области, которую мы хотим отрисовать.

 *    @width: Ширина прямоугольника, который мы хотим нарисовать.

 *    @height: Высота прямоугольника, который мы хотим нарисовать.

 *    @sx: x и y координаты верхнего левого угла

 *    @sy: области источника на экране.

 */

}

 

/**

 *    xxxfb_imageblit - ОБЯЗАТЕЛЬНАЯ функция. Если оборудование не

 *                    поддерживает ускорение и используются упакованные

 *                    пиксели, можно использовать стандартные подпрограммы.

 *                    Копирует изображение из системной памяти на экран. 

 *

 *    @info: структура кадрового буфера, представляющая один кадровый буфер.

 *    @image: структура, описывающая изображение.

 *

 *    Эта операция отрисовки орисовывает на экране изображение. Это может быть

 *    моно-изображение (требуется для обработки шрифтов) или цветное изображение

 *    (требуется для пингвина).

 */

void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image) 

{

/*

 *    @dx: x и y координаты верхнего левого угла области назначения

 *    @dy: для размещения картинки на экране.

 *    @width: Ширина изображения, которое мы хотим скопировать.

 *    @height: Высота изображения, которое мы хотим скопировать.

 *    @fg_color: Для двуцветных битовых изображений это данные о цвете для

 *    @bg_color: фона и изображения картинки для записи непосредственно в

 *                кадровый буфер.

 *    @depth: Сколько бит представляют один пиксель этого изображения.

 *    @data: Фактические данные, используемые для построения картинки на дисплее.

 *    @cmap: Цветовая таблица, используемая для цветных изображений.

 */

 

/*

 * Универсальная функция, cfb_imageblit, ожидает, что строки битовых полей

 * являются выровненными на следующем байте. Большинство аппаратных ускорителей

 * могут требовать выравнивания к следующему u16 или следующему u32. Если это

 * так, драйвер может указать это, установив info->pixmap.scan_align = 2 или 4.

 * Смотрите более подробное описание работы с растровым изображением ниже.

 */

}

 

/**

 *    xxxfb_cursor - НЕОБЯЗАТЕЛЬНА. Если ваше оборудование не имеет

 *                поддержки курсора, оставьте это поле NULL.

 *

 *    @info: структура кадрового буфера, представляющая один кадровый буфер.

 *    @cursor: структура, описывающая курсор для отрисовки.

 *

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

 *

 *    Возвращает отрицательное значение при ошибке или ноль при

 *    успешном завершении.

 */

int xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)

{

/*

 *    @set: Какие поля мы изменяем в структуре fb_cursor 

 *    @enable: Отключаем или включаем курсор.

 *    @rop: Битовая операция, которую мы хотим выполнить.

 *    @mask: Это битовая маска курсора.

 *    @dest: Изображение области, где мы собираемся отобразить курсор.

 *            Используется драйвером для внутренних целей.

 *    @hot: Горячая точка (точка, куда показывает курсор). 

 *    @image: Фактические данные для изображения курсора.

 *

 *    ЗАМЕЧАНИЯ О ФЛАГАХ (cursor->set):

 *

 *    FB_CUR_SETIMAGE - изменилось изображение курсора (cursor->image.data)

 *    FB_CUR_SETPOS   - изменилась позиция курсора (cursor->image.dx|dy)

 *    FB_CUR_SETHOT   - изменилась точка указания курсора (cursor->hot.dx|dy)

 *    FB_CUR_SETCMAP  - изменились цвета курсора (cursor->fg_color|bg_color)

 *    FB_CUR_SETSHAPE - изменилось битовая маска курсора (cursor->mask)

 *    FB_CUR_SETSIZE  - изменился размер курсора (cursor->width|height)

 *    FB_CUR_SETALL   - изменилось всё

 *

 *    ЗАМЕЧАНИЯ О БИТОВЫХ ОПЕРАЦИЯХ (cursor->rop, Операция Растеризации)

 *

 *    ROP_XOR         - cursor->image.data XOR cursor->mask

 *    ROP_COPY        - curosr->image.data AND cursor->mask

 *

 *    ДРУГИЕ ЗАМЕЧАНИЯ:

 *

 *    - fbcon поддерживает только 2-х цветный курсор (cursor->image.depth = 1)

 *    - Структура fb_cursor, @cursor, _будет_ всегда содержать достоверные

 *        поля, независимо от того, установлены или нет любые битовые поля

 *        в cursor->set.

 */

}

 

/**

 *    xxxfb_rotate -  НЕ обязательная функция. Если ваше оборудование

 *                поддерживает поворот целого экрана, вам стоит предоставить

 *                метод для этого.

 *

 *    @info: структура кадрового буфера, представляющая один кадровый буфер.

 *    @angle: Угол поворота экрана.   

 *

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

 */

void xxxfb_rotate(struct fb_info *info, int angle)

{

    /* Будет исключена */

}

 

/**

 *    xxxfb_sync - НЕ обязательная функция. Обычно ускоритель видеокарты

 *                требует определённого количества времени. Часто необходимо

 *                ждать, чтобы ускоритель завершил свою работу, прежде чем

 *                мы сможем записать кадровый буфер, чтобы иметь

 *                последовательный вывод на дисплей.

 *

 *    @info: структура кадрового буфера, представляющая один кадровый буфер.

 *

 *    Если драйвер реализует собственную функцию отрисовки, базирующуюся на

 *    возможностях оборудования, реализация этой функции настоятельно

 *    рекомендуется.

 */

int xxxfb_sync(struct fb_info *info)

{

    return 0;

}

 

    /*

     *  Операции кадрового буфера

     */

 

static struct fb_ops xxxfb_ops = {

    .owner           = THIS_MODULE,

    .fb_open         = xxxfb_open,

    .fb_read         = xxxfb_read,

    .fb_write        = xxxfb_write,

    .fb_release      = xxxfb_release,

    .fb_check_var    = xxxfb_check_var,

    .fb_set_par      = xxxfb_set_par,

    .fb_setcolreg    = xxxfb_setcolreg,

    .fb_blank        = xxxfb_blank,

    .fb_pan_display  = xxxfb_pan_display,

    .fb_fillrect     = xxxfb_fillrect,    /* Необходимо !!! */

    .fb_copyarea     = xxxfb_copyarea,    /* Необходимо !!! */

    .fb_imageblit    = xxxfb_imageblit,   /* Необходимо !!! */

    .fb_cursor       = xxxfb_cursor,      /* Необязательно !!! */

    .fb_rotate       = xxxfb_rotate,

    .fb_sync         = xxxfb_sync,

    .fb_ioctl        = xxxfb_ioctl,

    .fb_mmap         = xxxfb_mmap,

};

 

/* ------------------------------------------------------------------------- */

 

    /*

     *  Инициализация

     */

 

/* static int __init xxfb_probe (struct platform_device *pdev) -- для разработчиков платформ */

static int __devinit xxxfb_probe(struct pci_dev *dev,

                                 const struct pci_device_id *ent)

{

    struct fb_info *info;

    struct xxx_par *par;

    struct device *device = &dev->dev; /* или &pdev->dev */

    int cmap_len, retval;        

 

    /*

     * Динамическое выделение памяти для info и par

     */

    info = framebuffer_alloc(sizeof(struct xxx_par), device);

 

    if (!info) {

        /* идём по пути ошибок */

    }

 

    par = info->par;

 

    /* 

     * Здесь мы устанавливаем screen_base для кадрового буфера

     * на адрес в виртуальной памяти. Как правило, мы получаем

     * адрес ресурса от уровня шины, а затем переводим его в

     * пространство виртуальной памяти с помощью ioremap.

     * Примите во внимание ioport.h.

     */

    info->screen_base = framebuffer_virtual_memory;

    info->fbops = &xxxfb_ops;

    info->fix = xxxfb_fix; /* это будет единственным разом, когда

                    * будет использоваться xxxfb_fix, поэтому помечаем

                    * его как __devinitdata

                    */

    info->pseudo_palette = pseudo_palette; /* Псевдопалитра - это

                            * массив из 16-ти элементов

                            */

    /*

     * Установка флагов, чтобы указать, какие виды ускорения может

     * предоставить ваш драйвер (pan/wrap/copyarea/и так далее.) и

     * является ли он модулем -- смотрите FBINFO_* в include/linux/fb.h

     *

     * Если ваше оборудование может поддержать любую из функций с

     * аппаратным ускорением, производительность fbcon увеличится, если

     * соответствующим образом установить info->flags.

     *

     * FBINFO_HWACCEL_COPYAREA - оборудование двигает области

     * FBINFO_HWACCEL_FILLRECT - оборудование заливает прямоугольники

     * FBINFO_HWACCEL_IMAGEBLIT - аппаратное расширение mono->color

     * FBINFO_HWACCEL_YPAN - оборудование может панорамировать дисплей по оси y

     * FBINFO_HWACCEL_YWRAP - оборудование может прокручивать дисплей по оси y

     * FBINFO_HWACCEL_DISABLED - аппаратное ускорение поддерживается, но запрещено

     * FBINFO_READS_FAST - если установлен, предпочтение работы через расширение mono->color

     * FBINFO_MISC_TILEBLITTING - оборудование может делать копирование элементов

     *                            мозаичного изображения

     *

     * ПРИМЕЧАНИЕ: Это только для использования в fbcon.

     */

    info->flags = FBINFO_DEFAULT;

 

/********************* Этот этап является необязательным ***************************/

    /*

     * Структура pixmap - это рабочая область для функций отрисовки. Это

     * то, где высокими уровнями создаётся монохромное битовое изображение

     * и затем передаётся ускорителю. Если драйвер использует

     * cfb_imageblit, можно пропустить эту часть. Для тех, кто имеет более

     * строгие требования, этот этап необходим.

     */

 

    /* 

     * PIXMAP_SIZE должен быть достаточно небольшим, чтобы оптимизировать отрисовку,

     * но не слишком большой, чтобы впустую расходовать память. Безопасный размер

     * это (max_xres * max_font_height/8). max_xres зависит от драйвера,

     * max_font_height равно 32.

     */

    info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL);

    if (!info->pixmap.addr) {

        /* переход по ошибке */

    }

 

    info->pixmap.size = PIXMAP_SIZE;

 

    /*

     * FB_PIXMAP_SYSTEM - память в системном ОЗУ

     * FB_PIXMAP_IO     - память является отображённой на пространство ввода-вывода

     * FB_PIXMAP_SYNC   - если установлен, для доступа к pixmap будем вызывать

     *                    fb_sync(), обычно это происходит, если установлен FB_PIXMAP_IO.

     *

     * Сейчас FB_PIXMAP_IO не реализован.

     */

    info->pixmap.flags = FB_PIXMAP_SYSTEM;

 

    /*

     * scan_align это число для выравнивания каждой строки сканирования. Оно в байтах.

     * Таким образом для ускорителей, которым необходимо выравнивание к следующему,

     * установите здесь 4.

     */

    info->pixmap.scan_align = 4;

 

    /*

     * buf_align это число для выравнивания буфера. Например, для i810fb необходимо

     * scan_align равный 2, но ожидается работа с dwords, так что требуется

     * buf_align = 4.

     */

    info->pixmap.buf_align = 4;

 

    /* access_align - как много битов можно получить из кадрового буфера,

     * например, некоторые карты от epson разрешают только 16-ти битный доступ.

     * Большинство драйверов будут безопасно работать при параметре u32.

     *

     * ЗАМЕЧАНИЕ: Это поле в настоящее время не используется.

     */

    info->pixmap.access_align = 32;

/********************* Конец необязательного этапа ************************/

 

    /*

     * Должен быть задан разумный режим по умолчанию для видео. Это потребуется,

     * когда мы сможем установить режим видео. 

     */

    if (!mode_option)

        mode_option = "640x480@60";

 

    retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);

  

    if (!retval || retval == 4)

        return -EINVAL;

 

    /* Это должно быть сделано! */

    if (fb_alloc_cmap(&info->cmap, cmap_len, 0))

        return -ENOMEM;

 

    /* 

     * Это выполняется в случае, если имеется оборудование со статическим

     * режимом. Если мы устанавливаем режим самостоятельно, мы не вызываем это.

     */        

    info->var = xxxfb_var;

 

    /*

     * Для драйверов, которые могут это...

     */

    xxxfb_check_var(&info->var, info);

 

    /*

     * Необходим ли вызов fb_set_par() перед register_framebuffer? Это

     * будет зависеть от вас и оборудования. Если вы уверены, что ваш драйвер

     * является в системе только устройством, вызов fb_set_par() безопасен.

     *

     * Оборудование в x86 системах имеет ядро VGA. Вызов set_par() в этом

     * месте повредит VGA консоль, поэтому безопаснее пропустить здесь вызов

     * set_par и просто позволить fbcon сделать это за вас.

     */

    /* xxxfb_set_par(info); */

 

    if (register_framebuffer(info) < 0) {

        fb_dealloc_cmap(&info->cmap);

        return -EINVAL;

    }

    printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,

            info->fix.id);

    pci_set_drvdata(dev, info); /* или platform_set_drvdata(pdev, info) */

    return 0;

}

 

    /*

     *  Очистка

     */

/* static void __devexit xxxfb_remove(struct platform_device *pdev) */

static void __devexit xxxfb_remove(struct pci_dev *dev)

{

    struct fb_info *info = pci_get_drvdata(dev);

    /* или platform_get_drvdata(pdev); */

 

    if (info) {

        unregister_framebuffer(info);

        fb_dealloc_cmap(&info->cmap);

        /* ... */

        framebuffer_release(info);

    }

}

 

#ifdef CONFIG_PCI

#ifdef CONFIG_PM

/**

 *    xxxfb_suspend - Необязательная, но рекомендуемая функция.Приостановка

 *                    работы устройства.

 *    @dev: PCI устройство

 *    @msg: код события приобстановки.

 *

 *    Для большей информации смотрите Documentation/power/devices.txt

 */

static int xxxfb_suspend(struct pci_dev *dev, pm_message_t msg)

{

    struct fb_info *info = pci_get_drvdata(dev);

    struct xxxfb_par *par = info->par;

 

    /* приостанавливаем работу устройства здесь */

    return 0;

}

 

/**

 *    xxxfb_resume - Необязательная, но рекомендуемая функция. Возобновление

 *                    работы устройства.

 *    @dev: PCI устройство

 *

 *    Для большей информации смотрите Documentation/power/devices.txt

 */

static int xxxfb_resume(struct pci_dev *dev)

{

    struct fb_info *info = pci_get_drvdata(dev);

    struct xxxfb_par *par = info->par;

 

    /* восстанавливаем работу устройства здесь */

    return 0;

}

#else

#define xxxfb_suspend NULL

#define xxxfb_resume NULL

#endif /* CONFIG_PM */

 

static struct pci_device_id xxxfb_id_table[] = {

    { PCI_VENDOR_ID_XXX, PCI_DEVICE_ID_XXX,

      PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,

      PCI_CLASS_MASK, 0 },

    { 0, }

};

 

/* Для драйверов PCI */

static struct pci_driver xxxfb_driver = {

    .name     = "xxxfb",

    .id_table = xxxfb_id_table,

    .probe    = xxxfb_probe,

    .remove   = __devexit_p(xxxfb_remove),

    .suspend  = xxxfb_suspend, /* необязательно, но рекомендуется */

    .resume   = xxxfb_resume,  /* необязательно, но рекомендуется */

};

 

MODULE_DEVICE_TABLE(pci, xxxfb_id_table);

 

int __init xxxfb_init(void)

{

    /*

     *  Для параметров загрузки ядра (в формате 'video=xxxfb:<options>')

     */

#ifndef MODULE

    char *option = NULL;

 

    if (fb_get_options("xxxfb", &option))

        return -ENODEV;

    xxxfb_setup(option);

#endif

 

    return pci_register_driver(&xxxfb_driver);

}

 

static void __exit xxxfb_exit(void)

{

    pci_unregister_driver(&xxxfb_driver);

}

#else /* не PCI, устройства платформы */

#include <linux/platform_device.h>

/* для устройств платформы */

 

#ifdef CONFIG_PM

/**

 *    xxxfb_suspend - Необязательная, но рекомендуемая функция. Приостановка

 *                    работы устройства.

 *    @dev: устройство платформы.

 *    @msg: код события приостановки.

 *

 *    Для большей информации смотрите Documentation/power/devices.txt

 */

static int xxxfb_suspend(struct platform_device *dev, pm_message_t msg)

{

    struct fb_info *info = platform_get_drvdata(dev);

    struct xxxfb_par *par = info->par;

 

    /* приостанавливаем работу устройства здесь */

    return 0;

}

 

/**

 *    xxxfb_resume - Необязательная, но рекомендуемая функция. Возобновление

 *                    работы устройства.

 *    @dev: устройство платформы.

 *

 *    Для большей информации смотрите Documentation/power/devices.txt

 */

static int xxxfb_resume(struct platform_dev *dev)

{

    struct fb_info *info = platform_get_drvdata(dev);

    struct xxxfb_par *par = info->par;

 

    /* восстанавливаем работу устройства здесь */

    return 0;

}

#else

#define xxxfb_suspend NULL

#define xxxfb_resume NULL

#endif /* CONFIG_PM */

 

static struct platform_device_driver xxxfb_driver = {

    .probe = xxxfb_probe,

    .remove = xxxfb_remove,

    .suspend = xxxfb_suspend, /* необязательно, но рекомендуется */

    .resume = xxxfb_resume,   /* необязательно, но рекомендуется */

    .driver = {

    .name = "xxxfb",

    },

};

 

static struct platform_device *xxxfb_device;

 

#ifndef MODULE

    /*

     *  Установка

     */

 

/*

 * Необходимо только если драйвер имеет специальные возможности,

 * в противном случае мы откатываемся к обычному fb_setup().

 */

int __init xxxfb_setup(char *options)

{

    /* Анализ заданных пользователем параметров (`video=xxxfb:') */

}

#endif /* MODULE */

 

static int __init xxxfb_init(void)

{

    int ret;

    /*

     *  Параметры для загрузки ядра (в формате 'video=xxxfb:<options>')

     */

#ifndef MODULE

    char *option = NULL;

 

    if (fb_get_options("xxxfb", &option))

        return -ENODEV;

    xxxfb_setup(option);

#endif

    ret = platform_driver_register(&xxxfb_driver);

 

    if (!ret) {

        xxxfb_device = platform_device_register_simple("xxxfb", 0,

                        NULL, 0);

 

        if (IS_ERR(xxxfb_device)) {

            platform_driver_unregister(&xxxfb_driver);

            ret = PTR_ERR(xxxfb_device);

        }

    }

 

    return ret;

}

 

static void __exit xxxfb_exit(void)

{

    platform_device_unregister(xxxfb_device);

    platform_driver_unregister(&xxxfb_driver);

}

#endif /* CONFIG_PCI */

 

/* ------------------------------------------------------------------------- */

 

 

    /*

     *  Модуляризация

     */

 

module_init(xxxfb_init);

module_exit(xxxfb_remove);

 

MODULE_LICENSE("GPL");

 

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