воскресенье, 28 апреля 2019 г.

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

Перевод: The Linux 2.4 Parallel Port Subsystem
Автор: Тим Во (Tim Waugh)
Предыдущая часть: Подсистема параллельного порта Linux 2.4 - часть 2, ppdev - драйверы устройств, работающие в пространстве пользователя

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

parport_device_num

Название
parport_device_num -- преобразовать координаты устройства
Обзор
int parport_device_num(int parport, int mux, int daisy);
Аргументы
parport

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

mux

номер порта мультиплексора (-1, если мультиплексора нет)

daisy

адрес в цепочке устройств (-1, если нет адреса в цепочке)

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

parport_device_coords

Название
parport_device_coords -- преобразовать канонический номера устройства
Обзор
int parport_device_coords(int devnum, int * parport, int * mux, int * daisy);
Аргументы
devnum

номер устройства

parport

указатель на область для сохранения номера параллельного порта

mux

указатель на область для сохранения номера порта мультиплексора

daisy

указатель на область для сохранения адреса в цепочке устройств

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

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

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

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

parport_find_device

Название
parport_find_device -- найти указанное устройство
Обзор
int parport_find_device(const char * mfg, const char * mdl, int from);
Аргументы
mfg

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

mdl

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

from

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

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

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

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

parport_find_class

Название
parport_find_class -- найти устройство в указанном классе
Обзор
int parport_find_class(parport_device_class cls, int from);
Аргументы
cls

требуемый класс

from

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

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

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

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

parport_register_driver

Название
parport_register_driver -- зарегистрировать драйвер устройства на параллельном порту
Обзор
int parport_register_driver(struct parport_driver * drv);
Аргументы
drv

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

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

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

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

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

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

parport_unregister_driver

Название
parport_unregister_driver -- отменить регистрацию драйвера устройства на параллельном порту
Обзор
void parport_unregister_driver(struct parport_driver * arg);
Аргументы
arg

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

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

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

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

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

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

parport_get_port

Название
parport_get_port -- увеличить счётчик ссылок на порт
Обзор
struct parport * parport_get_port(struct parport * port);
Аргументы
port

порт

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

parport_put_port

Название
parport_put_port -- уменьшить счётчик ссылок на порт
Обзор
void parport_put_port(struct parport * port);
Аргументы
port

порт

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

parport_find_number

Название
parport_find_number -- найти параллельный порт по номеру
Обзор
struct parport * parport_find_number(int number);
Аргументы
number

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

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

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

parport_find_base

Название
parport_find_base -- найти параллельный порт по базовому адресу
Обзор
struct parport * parport_find_base(unsigned long base);
Аргументы
base

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

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

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

parport_register_device

Название
parport_register_device -- зарегистрировать устройство на параллельном порту
Обзор
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);
Аргументы
port

порт, к которому присоединено устройство

name

имя для обращения к устройству

pf

обработчик вежливой просьбы освободить порт

kf

обработчик сообщения о свободном порте

irq_func

обработчик прерывания

flags

флаги регистрации

handle

данные для функций-обработчиков

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

Область для хранения 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, если не хватило памяти, чтобы выделить место для этой структуры.

parport_unregister_device

Название
parport_unregister_device -- отменить регистрацию устройства на параллельном порту
Обзор
void parport_unregister_device(struct pardevice * dev);
Аргументы
dev

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

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

parport_open

Название
parport_open -- найти устройство по каноническому номеру устройства
Обзор
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);
Аргументы
devnum

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

name

имя для обращения к устройству

pf

обработчик вежливой просьбы освободить порт

kf

обработчик сообщения о свободном порте

irqf

обработчик прерываний

flags

флаги регистрации

handle

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

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

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

parport_close

Название
parport_close -- закрыть устройство, открытое при помощи parport_open
Обзор
void parport_close(struct pardevice * dev);
Аргументы
dev

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

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

parport_claim

Название
parport_claim -- затребовать доступ к устройству на параллельном порту
Обзор
int parport_claim(struct pardevice * dev);
Аргументы
dev

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

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

parport_claim_or_block

Название
parport_claim_or_block -- затребовать доступ к устройству на параллельном порту
Обзор
int parport_claim_or_block(struct pardevice * dev);
Аргументы
dev

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

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

parport_release

Название
parport_release -- отказаться от доступа к устройству на параллельном порту
Обзор
void parport_release(struct pardevice * dev);
Аргументы
dev

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

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

parport_yield

Название
parport_yield -- уступить доступ к параллельному порту
Обзор
int parport_yield(struct pardevice * dev);
Аргументы
dev

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

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

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

parport_yield_blocking

Название
parport_yield_blocking -- уступить доступ к параллельному порту
Обзор
int parport_yield_blocking(struct pardevice * dev);
Аргументы
dev

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

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

parport_negotiate

Название
parport_negotiate -- согласовать режим IEEE 1284
Обзор
int parport_negotiate(struct parport * port, int mode);
Аргументы
port

используемый порт

mode

согласуемый режим

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

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

parport_write

Название
parport_write -- записать блок данных в параллельный порт
Обзор
ssize_t parport_write(struct parport * port, const void * buffer, size_t len);
Аргументы
port

порт для записи

buffer

буфер данных (в пространстве ядра)

len

количество передаваемых байт данных

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

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

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

parport_read

Название
parport_read -- прочитать блок данных из параллельного порта
Обзор
ssize_t parport_read(struct parport * port, void * buffer, size_t len);
Аргументы
port

порт для чтения

buffer

буфер данных (в пространстве ядра)

len

количество принимаемых байт данных

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

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

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

parport_set_timeout

Название
parport_set_timeout -- задать таймаут бездействия устройства
Обзор
long parport_set_timeout(struct pardevice * dev, long inactivity);
Аргументы
dev

устройство на порту

inactivity

время бездействия (в тактах)

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

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

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

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

Хотя описанный в этом документе интерфейс был значительно обновлён в ядре 2.4, в ядре 2.2 используется аналогичный механизм совместного доступа. В 2.2 доступны следующие функции:
  • parport_register_device
  • parport_unregister_device
  • parport_claim
  • parport_claim_or_block
  • parport_release
  • parport_yield
  • parport_yield_blocking
А также поддерживается согласование полубайтового режима:
int parport_ieee1284_nibble_mode_ok(struct parport *port, unsigned char mode);
Единственными действующими значениями mode являются 0 (для полубайтового режима) и 4 (для чтения идентификатора устройства в полубайтовом режиме).

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

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

Комментариев нет: