Тим Во. Подсистема параллельного порта Linux 2.4 - часть 3, parport - справочник программного интерфейса драйвера параллельного порта Linux, 2000

Перевод статьи: The Linux 2.4 Parallel Port Subsystem

Автор: Тим Во (Tim Waugh)

Предыдущая часть: Подсистема параллельного порта Linux 2.4 - часть 2, ppdev - драйверы устройств, работающие в пространстве пользователя

1. Справочник программного интерфейса драйвера параллельного порта Linux

1.1. parport_device_num

1.1.1. Название

parport_device_num -- преобразовать координаты устройства

1.1.2. Обзор

int parport_device_num(int parport, int mux, int daisy);

1.1.3. Аргументы

parport
номер параллельного порта
mux
номер порта мультиплексора (-1, если мультиплексора нет)
daisy
адрес в цепочке устройств (-1, если нет адреса в цепочке)

1.1.4. Описание

Пытается найти устройство на указанном параллельном порту, порту мультиплексора и адресе в цепочке, и возвращает номер устройства или -NXIO, если устройство с такими координатами не существует.


1.2. parport_device_coords

1.2.1. Название

parport_device_coords -- преобразовать канонический номера устройства

1.2.2. Обзор

int parport_device_coords(int devnum, int * parport, int * mux, int * daisy);

1.2.3. Аргументы

devnum
номер устройства
parport
указатель на область для сохранения номера параллельного порта
mux
указатель на область для сохранения номера порта мультиплексора
daisy
указатель на область для сохранения адреса в цепочке устройств

1.2.4. Описание

Функция преобразует номер устройства в его координаты: к какому параллельному порту в системе оно подключено, к какому порту мультиплексора оно подключен, если на этом порту имеется мультиплексор, и какой адрес имеет в цепочке устройств, если оно находится в цепочке устройств.

Вызывающая сторона должна выделить области для сохранения parport, mux и daisy.

Если устройство с указанным номером отсутствует, то возвращается -ENXIO. В противном случае области, на которые указывают parport, mux и daisy, заполняются координатами устройства. Если координата не определена, то используется значение -1.

На самом деле функция не очень полезна, но этот интерфейс был предложен в IEEE 1284.3.


1.3. parport_find_device

1.3.1. Название

parport_find_device -- найти указанное устройство

1.3.2. Обзор

int parport_find_device(const char * mfg, const char * mdl, int from);

1.3.3. Аргументы

mfg
строка, содержащая название требуемого производителя
mdl
строка, содержащая название требуемой модели устройства
from
номер предыдущего устройства, найденного в процессе поиска, или NULL, если это новый поиск

1.3.4. Описание

Проходит по списку устройств на параллельных портах в поисках устройства, у которого строки 'MFG' и 'MDL' в идентификаторе устройства IEEE 1284 будут совпадать с mfg и mdl.

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

Новый поиск начинается с передачи значения NULL в аргументе from. Если from - не NULL, то поиск продолжается с указанного устройства.


1.4. parport_find_class

1.4.1. Название

parport_find_class -- найти устройство в указанном классе

1.4.2. Обзор

int parport_find_class(parport_device_class cls, int from);

1.4.3. Аргументы

cls
требуемый класс
from
номер устройства, найденного во время предыдущего поиска, или NULL, если это новый поиск

1.4.4. Описание

Проходит по списку устройств на параллельных портах в поисках устройства, у которого строка 'CLS' в идентификаторе устройства IEEE 1284 совпадает с cls.

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

Новый поиск начинается с передачи значения NULL в аргументе from. Если from - не NULL, то поиск продолжается с указанного устройства.


1.5. parport_register_driver

1.5.1. Название

parport_register_driver -- зарегистрировать драйвер устройства на параллельном порту

1.5.2. Обзор

int parport_register_driver(struct parport_driver * drv);

1.5.3. Аргументы

drv
структура, описывающая драйвер

1.5.4. Описание

Может вызываться драйвером устройства на параллельном порту для приёма уведомлений о портах, обнаруженных в системе, а также о более не доступных портах.

Место для хранения структуры drv выделяется вызывающей стороной и не должно освобождаться вплоть до вызова parport_unregister_driver.

Функция attach драйвера может блокироваться. Порт, который передан в attach, действителен только на время вызова, но если драйверу нужно взять копию указателя, то он может воспользоваться parport_get_port. Вызов parport_register_device с этим портом сделает это автоматически.

Функция detach драйвера не может блокироваться. Порт, который передан в detach, действителен только на время вызова, но если драйверу нужно взять копию указателя, то для этого он должен воспользоваться parport_get_port.

В случае успеха возвращает 0. В настоящее время всегда завершается успешно.


1.6. parport_unregister_driver

1.6.1. Название

parport_unregister_driver -- отменить регистрацию драйвера устройства на параллельном порту

1.6.2. Обзор

void parport_unregister_driver(struct parport_driver * arg);

1.6.3. Аргументы

arg
структура, описывающая драйвер, которая была передана в parport_register_driver

1.6.4. Описание

Должна вызываться при выгрузке драйвера устройства на параллельном порту, который зарегистрировался при помощи parport_register_driver.

После возврата подпрограмма attach драйвера больше не будет вызываться, а для каждого из портов, для которого был вызван attach, будет вызвана подпрограмма detach.

Если функция attach вызывающего может блокироваться, то драйвер сам должен дождаться её завершения перед выгрузкой.

Перед возвратом из этой функции все вызовы detach драйвера будут гарантированно завершены.

В вызове detach драйвера не разрешается блокироваться.


1.7. parport_get_port

1.7.1. Название

parport_get_port -- увеличить счётчик ссылок на порт

1.7.2. Обзор

struct parport * parport_get_port(struct parport * port);

1.7.3. Аргументы

port
порт

1.7.4. Описание

Позволяет убедиться, что указатель на структуру parport останется доступным вплоть до соответствующего вызова parport_put_port.


1.8. parport_put_port

1.8.1. Название

parport_put_port -- уменьшить счётчик ссылок на порт

1.8.2. Обзор

void parport_put_port(struct parport * port);

1.8.3. Аргументы

port
порт

1.8.4. Описание

Должна вызываться для каждого из вызовов parport_get_port, когда порт больше не требуется.


1.9. parport_find_number

1.9.1. Название

parport_find_number -- найти параллельный порт по номеру

1.9.2. Обзор

struct parport * parport_find_number(int number);

1.9.3. Аргументы

number
номер параллельного порта

1.9.4. Описание

Возвращает параллельный порт с указанным номером или NULL, если его нет.

Выполняет неявный вызов parport_get_port. Чтобы отбросить ссылку на порт, которая была получена через parport_find_number, воспользуйтесь parport_put_port.


1.10. parport_find_base

1.10.1. Название

parport_find_base -- найти параллельный порт по базовому адресу

1.10.2. Обзор

struct parport * parport_find_base(unsigned long base);

1.10.3. Аргументы

base
базовый адрес ввода-вывода

1.10.4. Описание

Возвращает параллельный порт с указанным базовым адресом или NULL, если его нет.

Выполняет неявный вызов parport_get_port. Чтобы отбросить ссылку на порт, которая была получена через parport_find_base, воспользуйтесь parport_put_port.


1.11. parport_register_device

1.11.1. Название

parport_register_device -- зарегистрировать устройство на параллельном порту

1.11.2. Обзор

struct pardevice * parport_register_device(struct parport * port, const char * name, int (*pf) (void *), void (*kf) (void *), void (*irq_func) (int, void *, struct pt_regs *), int flags, void * handle);

1.11.3. Аргументы

port
порт, к которому присоединено устройство
name
имя для обращения к устройству
pf
обработчик вежливой просьбы освободить порт
kf
обработчик сообщения о свободном порте
irq_func
обработчик прерывания
flags
флаги регистрации
handle
данные для функций-обработчиков

1.11.4. Описание

Функция, вызываемая драйверами устройств на параллельном порту, объявляет, что это устройство подключено к порту и сообщает системе всё, что ей нужно знать.

Область для хранения name выделяется вызывающей стороной и не должна освобождаться вплоть до того, как вызывающая сторона не вызовет parport_unregister_device для этого устройства.

pf - обработчик вежливой просьбы освободить порт. Выполняется, когда драйвер владеет доступом к порту, но к этому порту хочет получить доступ драйвер другого устройства. Если драйвер желает освободить порт, то он должен вернуть ноль и тогда порт будет им освобождён. Если драйвер желает сохранить доступ к порту, он должен вернуть ненулевое значение и никаких действий не будет выполнено. Вежливый драйвер постарается отпустить порт как можно раньше, при первой возможности после вежливой просьбы, после того как первая вежливая просьба была отклонена. Отметим, что если вежливый обработчик будет рад выполнить просьбу, то освобождать порт не требуется - это будет выполнено автоматически. Эта функция не может блокироваться, поскольку она может быть вызвана из контекста прерывания. Если драйвер устройства не поддерживает обработку вежливых просьб, pf может принимать значение NULL.

kf - обработчик сообщения о свободном порте. Выполняется, когда порт можно затребовать в исключительный доступ. Если драйвер хочет затребовать доступ к порту, то вызов parport_claim гарантированно завершится удачно внутри обработчика сообщения о свободном порте. Если драйвер хочет затребовать доступ к порту, он должен сделать это. В противном случае никаких действий предпринимать не требуется. Эта функция не может блокироваться, поскольку она может быть вызвана из контекста прерывания. Если драйвер устройства не желает получать явные приглашения затребовать порт таким образом, kf может принимать значение NULL.

irq_func - обработчик прерывания. Он вызывается, когда происходит прерывание от параллельного порта. Отметим, что если драйвер устройства желает использовать прерывания, он должен использовать parport_enable_irq, а также может отметить поле irq в структуре parport, содержащей информацию о порте.

Низкоуровневый драйвер параллельного порта - один из тех, кто вызывается из request_irq и чей обработчик прерывания выполняется первым. Этот обработчик делает всё необходимое, чтобы оборудование получило подтверждение прерывания (для портов типа PC ничего специального не делается). Затем он сообщает о прерывании коду IEEE 1284, который реагирует на событие IEEE 1284 в соответствии с текущей фазой IEEE 1284. И только после этого, он вызовет irq_func. Не стоит говорить, что irq_func будет вызываться из контекста прерывания и не может блокироваться.

Флаг PARPORT_DEV_EXCL предотвращает совместное использование порта и поэтому должен использоваться только в тех случаях, если совместное использование порта с другими устройствами не возможно и может привести к некорректному поведению. Старайтесь избегать! Обычно параметр flags равен нулю.

Функция возвращает указатель на структуру, представляющую устройство на порту, или NULL, если не хватило памяти, чтобы выделить место для этой структуры.


1.12. parport_unregister_device

1.12.1. Название

parport_unregister_device -- отменить регистрацию устройства на параллельном порту

1.12.2. Обзор

void parport_unregister_device(struct pardevice * dev);

1.12.3. Аргументы

dev
указатель на структуру, представляющую устройство

1.12.4. Описание

Отменяет действие parport_register_device.


1.13. parport_open

1.13.1. Название

parport_open -- найти устройство по каноническому номеру устройства

1.13.2. Обзор

struct pardevice * parport_open(int devnum, const char * name, int (*pf) (void *), void (*kf) (void *), void (*irqf) (int, void *, struct pt_regs *), int flags, void * handle);

1.13.3. Аргументы

devnum
канонический номер устройства
name
имя для обращения к устройству
pf
обработчик вежливой просьбы освободить порт
kf
обработчик сообщения о свободном порте
irqf
обработчик прерываний
flags
флаги регистрации
handle
данные драйвера

1.13.4. Описание

Функция аналогична parport_register_device, за исключением того, что находит устройство по его номеру, а не по порту, к которому оно подключено. См. parport_find_device и parport_find_class.

Все параметры, за исключением devnum, такие же как и у parport_register_device. Возвращаемое значение такое же, как и у parport_register_device.


1.14. parport_close

1.14.1. Название

parport_close -- закрыть устройство, открытое при помощи parport_open

1.14.2. Обзор

void parport_close(struct pardevice * dev);

1.14.3. Аргументы

dev
закрываемое устройство

1.14.4. Описание

То же самое по отношению к parport_open, как parport_unregister_device по отношению к parport_register_device.


1.15. parport_claim

1.15.1. Название

parport_claim -- затребовать доступ к устройству на параллельном порту

1.15.2. Обзор

int parport_claim(struct pardevice * dev);

1.15.3. Аргументы

dev
указатель на структуру данных, представляющую устройство на порту

1.15.4. Описание

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


1.16. parport_claim_or_block

1.16.1. Название

parport_claim_or_block -- затребовать доступ к устройству на параллельном порту

1.16.2. Обзор

int parport_claim_or_block(struct pardevice * dev);

1.16.3. Аргументы

dev
указатель на структуру, представляющую устройство на порту

1.16.4. Описание

Ведёт себя как parport_claim, но заблокируется, если необходимо подождать, когда освободится порт. Возвращаемое значение 1 указывает, что функция спала, а 0 означает, что функция сразу выполнилась успешно. Отрицательный код ошибки свидетельствует о неудаче.


1.17. parport_release

1.17.1. Название

parport_release -- отказаться от доступа к устройству на параллельном порту

1.17.2. Обзор

void parport_release(struct pardevice * dev);

1.17.3. Аргументы

dev
указатель на структуру, представляющую устройство на параллельном порту

1.17.4. Описание

Функция не может завершиться неудачно, но она не должна вызываться для порта, доступ к которому не был получен ранее. Аналогично, если доступ к порту уже был получен, не нужно пытаться получить его снова.


1.18. parport_yield

1.18.1. Название

parport_yield -- уступить доступ к параллельному порту

1.18.2. Обзор

int parport_yield(struct pardevice * dev);

1.18.3. Аргументы

dev
устройство на параллельном порту

1.18.4. Описание

Функция временно отказывается от порта, если он может быть полезен для работы других драйверов. Затем функция пытается вернуть доступ к порту при помощи parport_claim и возвращает такое же значение, как и parport_claim. Если функция завершится неудачно, то доступ к порту будет потерян и сам драйвер будет отвечать за его повторное получение.

Функции parport_yield и parport_yield_blocking предназначены для отметки мест в драйвере, где другие драйверы могут затребовать доступ к порту и использовать его для связи со своими устройствами. Уступка порта аналогична его освобождению и повторному затребованию, но более эффективна, т.к. если нет других драйверов, которым требуется доступ к порту, то никаких действий не предпринимается. На деле ничего не делается даже тогда, когда есть другие устройства, ожидающие доступа, но текущее устройство находится внутри своего кванта времени. По умолчанию квант времени - полсекунды, но эта длительность может настраиваться через интерфейс /proc.


1.19. parport_yield_blocking

1.19.1. Название

parport_yield_blocking -- уступить доступ к параллельному порту

1.19.2. Обзор

int parport_yield_blocking(struct pardevice * dev);

1.19.3. Аргументы

dev
устройство на параллельном порту

1.19.4. Описание

Функция временно отказывается от порта, если он может быть полезен для работы других драйверов. Затем функция пытается вернуть доступ к порту при помощи parport_claim_or_block и возвращает такое же значение, как и parport_claim_or_block.


1.20. parport_negotiate

1.20.1. Название

parport_negotiate -- согласовать режим IEEE 1284

1.20.2. Обзор

int parport_negotiate(struct parport * port, int mode);

1.20.3. Аргументы

port
используемый порт
mode
согласуемый режим

1.20.4. Описание

Используйте для согласования определённого режима передачи IEEE 1284. Параметр mode должен быть одной из констант, определённых в файле parport.h, имя которой начинается с IEEE1284_MODE_xxx.

Возвращает значение 0, если периферийное устройство согласовало указанный режим. -1 возвращается, если периферийное устройство не совместимо со стандартом IEEE 1284 (или отсутствует). 1 возвращается, если периферийное устройство не согласовало указанный режим.


1.21. parport_write

1.21.1. Название

parport_write -- записать блок данных в параллельный порт

1.21.2. Обзор

ssize_t parport_write(struct parport * port, const void * buffer, size_t len);

1.21.3. Аргументы

port
порт для записи
buffer
буфер данных (в пространстве ядра)
len
количество передаваемых байт данных

1.21.4. Описание

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

За действительность первых len байт буфера отвечает вызывающая сторона.

Функция возвращает количество переданных байт (если передано ноль или больше), а в противном случае возвращает код ошибки.


1.22. parport_read

1.22.1. Название

parport_read -- прочитать блок данных из параллельного порта

1.22.2. Обзор

ssize_t parport_read(struct parport * port, void * buffer, size_t len);

1.22.3. Аргументы

port
порт для чтения
buffer
буфер данных (в пространстве ядра)
len
количество принимаемых байт данных

1.22.4. Описание

Читает до len байт данных из указанного порта в буфер, используя последний из согласованных (при помощи parport_negotiate) режимов передачи IEEE 1284, если этот режим поддерживает обратную передачу (от периферийного устройства на компьютер).

За доступность для записи первых len байт буфера отвечает вызывающая сторона.

Функция возвращает количество принятых байт (если принято ноль или больше), а в противном случае возвращает код ошибки.


1.23. parport_set_timeout

1.23.1. Название

parport_set_timeout -- задать таймаут бездействия устройства

1.23.2. Обзор

long parport_set_timeout(struct pardevice * dev, long inactivity);

1.23.3. Аргументы

dev
устройство на порту
inactivity
время бездействия (в тактах)

1.23.4. Описание

Задаёт таймаут бездействия указанного устройства на порту. Действует на функции, подобные parport_wait_peripheral. Специальное значение 0 означает - не использовать расписание при работе с этим устройством.

Возвращает предыдущее значение таймаута бездействия.

Все обратившиеся к parport_wait_event для этого устройства будут разбужены.

2. Подсистема параллельного порта Linux 2.2

Хотя описанный в этом документе интерфейс был значительно обновлён в ядре 2.4, в ядре 2.2 используется аналогичный механизм совместного доступа. В 2.2 доступны следующие функции:

А также поддерживается согласование полубайтового режима:

int parport_ieee1284_nibble_mode_ok(struct parport *port, unsigned char mode);

Единственными действующими значениями mode являются 0 (для полубайтового режима) и 4 (для чтения идентификатора устройства в полубайтовом режиме).

Эта функция устарела и в Linux 2.4 была заменена на parport_negotiate.

Полную версию перевода, оформленную аналогично исходному документу и содержащую все три части, опубликованные в блоге, можно найти по ссылке: Подсистема параллельного порта Linux 2.4.

Написать автору перевода