Подсистема параллельного порта Linux 2.4
<<< Назад Драйверы устройств, работающие в пространстве пользователя Далее >>>

Интерфейс программирования

Интерфейс ppdev во многом совпадает с интерфейсом символьных специальных устройств, т.к. он тоже поддерживает функции open, close, read, write и ioctl. Константы для команд ioctl имеются в файле include/linux/ppdev.h.

Начало и завершение: open и close

Файл устройства /dev/parport0 представляет любое устройство, подключенное к parport0 - первому параллельному порту в системе. Каждый раз при открытии файла устройства, он представляет (для процесса, выполняющего открытие) другое устройство. Он также может быть открыт более одного раза, но в любой момент только один экземпляр действительно будет управлять параллельным портом. Процесс, который открыл /dev/parport0, работает с параллельным портом через механизм совместного доступа таким же образом, как и любой другой драйвер устройства. Драйвер в пространстве пользователя может работать с параллельным портом совместно как с драйверами устройств пространства ядра, так и с драйверами пространства пользователя.

Управление: ioctl

Большая часть управления выполняется через вызовы ioctl. При помощи ioctl драйвер пространства пользователя может управлять как драйвером ppdev в ядре, так и самим физическим параллельным портом. Вызов ioctl принимает в качестве параметров дескриптор файла (который был получен при открытии файла устройства), команду, и (не обязательный) указатель на некоторые данные.

PPCLAIM

Затребовать доступ к порту. Необходимо сделать это перед тем, как приступить к работе с параллельным портом. Отметим, что некоторые операции действуют только на драйвер ppdev, но не на порт - например, PPSETMODE. Они могут осуществляться только в тот момент, когда доступ к порту не затребован.

PPEXCL

Указывает драйверу ядра запретить любое совместное использование с другими драйверами, то есть запрашивается исключительный доступ. Команда PPEXCL действует только пока доступ к порту ещё никем не затребован. Последующий запрос ioctl PPCLAIM может завершится неудачно, т.к. к этому моменту доступ к порту может быть предоставлен какому-то другому драйверу.

Большинству драйверов устройств не требуется эксклюзивный доступ к порту. Такой доступ предоставляется в случае, если он действительно нужен. Например, это могут быть устройства, которым требуется доступ на продолжительное время (многие секунды).

Отметим, что ioctl PPEXCL на самом деле не запрашивает доступ к порту - действие откладывается до тех пор, пока не будет выполнена команда ioctl PPCLAIM.

PPRELEASE

Освобождает порт. Освобождение порта отменяет ранее затребованный доступ к порту. Это позволит драйверам других устройств общаться с их устройствами (если они есть).

PPYIELD

Уступить порт другому драйверу. Этот ioctl является сокращенной записью освобождения доступа к порту и немедленного его повторного затребования. Это позволяет другим драйверам получить возможность пообщаться с их устройствами, но после этого доступ к порту вернётся обратно. Пример использования можно найти в драйвере принтера, работающем в пространстве пользователя: как только были записаны несколько символов, можно на некоторое время передать порт драйверу другого устройства, но если символы для отправки на принтер ещё есть, то драйвер принтера желает вернуть доступ к порту как можно раньше.

Важно не требовать параллельный порт надолго, потому что драйверам других устройств не останется времени на обслуживание их устройств. Если ваше устройство не позволяет использовать совместный доступ к порту, лучше затребовать параллельный порт в исключительный доступ (см. PPEXCL).

PPNEGOT

Производит согласование одного из режимов IEEE 1284. Согласование - это метод, по которому компьютер и периферийное устройство принимают решение об используемом протоколе передачи данных.

Устройство, совместимое с IEEE 1284, начинает работу в совместимом режиме, а затем компьютер может согласовать другой режим (например, ECP).

Параметр ioctl должен быть указателем на int. В файле incluce/linux/parport.h определены следующие значения:

  • IEEE1284_MODE_COMPAT

  • IEEE1284_MODE_NIBBLE

  • IEEE1284_MODE_BYTE

  • IEEE1284_MODE_EPP

  • IEEE1284_MODE_ECP

ioctl PPNEGOT на самом деле выполняет два действия: производит согласование режима и настраивает поведение последующих вызовов read/write, которые будут работать в этом режиме (но см. также PPSETMODE).

PPSETMODE

Задаёт режим передачи IEEE 1284, который будет использоваться вызовами read и write.

Параметр ioctl должен быть указателем на int.

PPGETMODE

Возвращает текущий режим IEEE 1284, используемый read и write.

PPGETTIME

Возвращает значение таймаута. Вызовы read и write завершаются, если периферийное устройство не ответит достаточно быстро. ioctl PPGETTIME возвращает время, в течение которого периферийное устройство считается доступным, даже если оно не отвечает.

Параметр ioctl должен быть указателем на структуру timeval.

PPSETTIME

Задаёт таймаут. Параметр ioctl должен быть указателем на структуру timeval.

PPGETMODES

Запрашивает возможности оборудования (то есть поле modes из структуры parport).

PPSETFLAGS

Задаёт флаги устройства ppdev, которые могут влиять на последующие операции ввода-вывода. Доступны следующие флаги:

  • PP_FASTWRITE

  • PP_FASTREAD

  • PP_W91284PIC

PPWCONTROL

Задаёт линии управления. Параметр ioctl - это указатель на unsigned char, содержащий результат битового ИЛИ над определениями из include/linux/parport.h, соответствующих управляющих линий.

PPRCONTROL

Возвращает последнее значение, записанное в регистр управления, в виде unsigned char: каждый бит соответствует управляющий линии (некоторые из них не используются). Параметр ioctl должен быть указателем на unsigned char.

При этом оборудование фактически не затрагивается, т.к. последнее записанное значение запоминается программно. Так сделано, поскольку некоторое аппаратное обеспечение параллельных портов не предоставляет доступ к регистру управления.

Биты управляющих линий определены в include/linux/parport.h:

  • PARPORT_CONTROL_STROBE

  • PARPORT_CONTROL_AUTOFD

  • PARPORT_CONTROL_SELECT

  • PARPORT_CONTROL_INIT

PPFCONTROL

Переключить управляющие линии. Поскольку часто бывает нужно изменить один из управляющих сигналов, не трогая остальные, было бы не очень эффективно для драйвера в пространстве пользователя сначала воспользоваться PPRCONTROL, внести изменения и затем воспользоваться PPWCONTROL. Конечно, каждому драйверу придётся запоминать состояние управляющих линий (они не могут быть изменены из другого места), но для предоставления PPRCONTROL самому ppdev тоже приходится запоминать состояние управляющих линий.

ioctl PPFCONTROL для переключения управляющих линий аналогичен PPWCONTROL, но воздействует лишь на ограниченный набор управляющих линий. Параметр ioctl - это указатель на структуру ppdev_frob_struct:

       
struct ppdev_frob_struct {
        unsigned char mask;
        unsigned char val;
};
        
       

Поля mask и val - это битовое ИЛИ над именами управляющих линий (таких же, как в PPWCONTROL). PPFCONTROL выполняет следующую операцию:

       
        new_ctr = (old_ctr & ~mask) | val;
       

Другими словами, сигналы, указанные в mask, примут значения, указанные в val.

PPRSTATUS

Возвращает unsigned char, содержащий биты для каждой из активных линий состояния (например, PARPORT_STATUS_BUSY). Параметр ioctl должен быть указателем на unsigned char.

PPDATADIR

Управление направлением линий данных. Обычно параллельный порт компьютера управляет линиями данных, но в байтовом режиме передачи от периферийного устройства на компьютер нужно отключить это управление и позволить периферийному устройству управлять этими сигналами. (Если управление параллельным портом со стороны компьютера останется активным, то порт может повредиться.)

Этот вызов бывает нужен только в сочетании с PPWDATA или PPRDATA.

Параметр ioctl - это указатель на int. Если int - ноль, управление линиями данных включается (прямое направление). Если же int - не ноль, то управление линиями данных отключается (обратное направление).

PPWDATA

Задаёт линии данных (если они находится в режиме прямого направления). Параметр ioctl - указатель на unsigned char.

PPRDATA

Читает линии данных (если они находится в режиме обратного направления). Параметр ioctl - указатель на unsigned char.

PPCLRIRQ

Очищает счётчик прерываний. Драйвер ppdev хранит счётчик произошедших прерываний. PPCLRIRQ сохранит этот счётчик в int, указатель на который передан в качестве параметра ioctl.

После этого счётчик прерываний сбрасывается в ноль.

PPWCTLONIRQ

Задаёт признак ответа. После того, как произойдёт прерывание, обработчик должен выставить линии управления в соответствии с запросом. Параметр ioctl - указатель на unsigned char, который интерпретируется так же, как в PPWCONTROL.

Этот ioctl введён по соображениям скорости. Без этого ioctl соответствующее прерывание начнёт обрабатываться в обработчике прерываний, переключится через poll или select на драйвер в пользовательском пространстве, а затем переключится обратно в ядро, чтобы обработать PPWCONTROL. Выполнение всех процедур в обработчике прерывания значительно быстрее.

Передача данных: read и write

Передача данных при помощи read и write осуществляется очевидным образом. Данные передаются с использованием текущего режима IEEE 1284 (см. ioctl PPSETMODE). В режимах, которые позволяют передавать данные только в одном направлении, будет работать только соответствующая функция.

Ожидание событий: poll и select

Драйвер ppdev позволяет драйверам устройств, работающим в пространстве пользователя, ожидать прерываний при помощи pollselect, который реализуется средствами poll).

Когда драйвер устройства, работающий в пространстве пользователя, захочет подождать прерывания, он засыпает, выполняя poll. Когда поступает прерывание, ppdev будит его (событием «read», хотя, строго говоря, читать на самом деле нечего).


<<< Назад Начало Далее >>>
Драйвер в пространстве ядра или в пространстве пользователя? Наверх Примеры