Перейти на главную   
  helloworld.ru - документация и книги по программированию  
helloworld.ru - документация и книги по программированию
    главная     хостинг    
Поиск по сайту:  
Смотрите также
Языки программирования
C#
MS Visual C++
Borland C++
C++ Builder
Visual Basic
Quick Basic
Turbo Pascal
Delphi
JavaScript
Java
PHP
Perl
Assembler
AutoLisp
Fortran
Python
1C

Интернет-технологии
HTML
VRML
HTTP
CGI
FTP
Proxy
DNS
протоколы TCP/IP
Apache

Web-дизайн
HTML
Дизайн
VRML
PhotoShop
Cookie
CGI
SSI
CSS
ASP
PHP
Perl

Программирование игр
DirectDraw
DirectSound
Direct3D
OpenGL
3D-графика
Графика под DOS

Алгоритмы
Численные методы
Обработка данных

Сис. программирование
Драйверы

Базы данных
MySQL
SQL

Другое

Хостинг


Друзья
demaker.ru
Реклама

Лучший хостинг. Аренда серверов




helloworld.ru

2.3.6.8. Функция init()

Эта функция не входит в file_operations но вам придется использовать ее, так как именно она регистрирует file_operations с содержащейся там VFS - - без нее запросы на драйвер будут находится в беспорядочном состоянии. Эта функция запускается во время загрузки и самоконфигурирования ядра. init() получает переменную с адресом конца используемой памяти. Затем она обнаруживает все устройства, выделяет память, исходя из их общего числа, сохраняет полезные адреса и возвращает новый адрес конца используемой памяти. Функцию init() вы должны вызывать из определенного места. Для символьных устройств это /kernel/cdr_dev/mem.c. В общем случае функции надо задавать лишь переменную memory_start.

Во время работы функции init(), она регистрирует ваш драйвер с помощью регистрирующих функций. Для символьных устройств это register_chrdev(). register_chrdev использует три аргумента :

  • int major - основной номер устройства.
  • srtring name - имя устройства.
  • адрес #DEVICE#_fops структуры file_operations.
  • После окончания работы функции, файлы становятся доступными для VFS, и она по надобности переключает устройство с одного вызова на другой.

    Функция init() обычно выводит сведения о найденном аппаратном обеспечении и информацию о драйвере.Это делается с использованием функции printk().

    2.4. Cимвольные устройства

    2.4.1. Инициализация

    Кроме функций описанных в file_operations, есть еще одна функция, кото- рую вам надо вписать в функцию foo_init(). Вам придется изменить функцию chr_dev_init() в chr_drv/mem.c для вызова вашей функции foo_init(). foo_init() вначале должна вызывать register_chrdev() для определения самой себя и установки номеров устройств. Аргументы register_chrdev() :

    • int major - основной номер драйвера.
    • char *name - имя драйвера оно может быть изменено, но не имеет практического применения.
    • struct file_operations *fops - адрес определенной вами file_operations.
    • Возвращаемые значения : 0 - в случае если указанным основным номером ни одно устройство более не обладает. не 0 в случае некорректного вызова.

    2.4.2. Прерывания или последовательный вызов?

    В драйверах, не использующих прерывания, легко пишутся функции foo_read() и foo_write() :

           static int foo_write(struct inode * inode, struct file * file,
                                char * buf, int count)
           {
               unsigned int minor = MINOR(inode-i_rdev);
               char ret;
               while (count  0) {
                   ret = foo_write_byte(minor);
           if (ret 
    
    
    
    
    
    
    
    

    foo_write_byte() и foo_handle_error() - функции, также определенные в foo.c или псевдокоде.

    WRITE - константа или определена #define.

    Из примера также видно как пишется функция foo_read(). Драйверы, управ- ляемые прерываниями, более сложны :

    Пример foo_write для драйвера, управляемого прерываниями :

            static int foo_write(struct inode * inode, struct file * file,
                                 char * but, int count)
            {
               unsigned int minor = MINOR(inode-i_rdev);
               unsigned long copy_size;
               unsigned long total_bytes_written = 0;
               unsigned long bytes_written;
               struct foo_struct *foo = &foo_table[minor];
    
               do {
                   copy_size = (count 
    foo_buffer, buf, copy_size);
    
                   while (copy_size) {
                          /* запуск прерывания */
    
                          if (some_error_has_occured) {
                              /* обработка ошибочного состояния */                       }
    
                          current-timeout = jiffies +FOO_INTERRUPT_TIMEOUT;
                              /* set timeout in case an interrupt has been missed */
                          interruptible_sleep_on(&foo-foo_wait_queue);
                          bytes_written = foo-bytes_xfered;
                          foo-bytes_written = 0;
                          if (current-signal & ~current-blocked) {
                              if (total_bytes_written + bytes_written)
                                   return total_bytes_written + bytes_written;
                              else
                                   return -EINTR; /* nothing was written, system
                                                call was interrupted, try again */
                          }
                   }
                   total_bytes_written += bytes_written;
                   buf += bytes_written;
                   count -= bytes-written;
    
               } while (count  0);
    
               return total_bytes_written;
            }
    
            static void foo_interrupt(int irq)
            {
                struct foo_struct *foo = &foo_table[foo_irq[irq]];
    
                /* Here, do whatever actions ought to be taken on an interrupt.
                   Look at a flag in foo_table to know whether you ought to be
                   reading or writing. */
    
                /* Increment foo-bytes_xfered by however many characters were
                   read or written */
                if (buffer too full/empty)
                    wake_up_ interruptible(&foo-foo_wait_queue);
             }
    

    Здесь функция foo_read также аналогична. foo_table[] - массив структур, каждая из которых имеет несколько элементов, в том числе foo_wait_queue и bytes_xfered, которые используются и для чтения, и для записи. foo_irq[] - - массив из 16 целых использующийся для контроля за приоритетами элементов foo_table[] засылаемыми в foo_interrupt().

    Для указания обpаботчику пpеpываний вызвать foo_interrupt() вы должны использовать либо request_irq(), либо irqaction(). Это делается либо пpи вызове foo_open(), либо для пpостоты в foo_init(). request_irq() pаботает пpоще нежели irqaction и напоминает pаботу сигнального пеpеключателя. У нее существует два аpгумента:

    • номеp irq, котоpым вы pасполагаете
    • указатель на пpоцедуpу упpавления пpеpываниями, имеющую аpгумент типа integer.

    request_irq() возвpащает -EINVAL, если irq 15, или в случае указателя на пpогpамму pавного NULL, EBUSY если пpеpывание уже используется или 0 в случае успеха.

    irqaction() pаботает также как функция sigaction() на пользовательском уpовне и фактически использует стpуктуpу sigaction. Поле sa_restorer() в стpуктуpе не используется, остальное - же осталось неизменным. См. pаздел "Функции поддеpжки" для более полной инфоpмации о irqaction().


    [ Назад | Оглавление | Далее ]









    helloworld.ru © 2001-2021
    Все права защищены