Перевод статьи: The Linux 2.4 Parallel Port Subsystem
Автор: Тим Во (Tim Waugh)
Предыдущая часть: Подсистема параллельного порта Linux 2.4 - часть 2, ppdev - драйверы устройств, работающие в пространстве пользователя
parport_device_num -- преобразовать координаты устройства
int parport_device_num(int parport, int mux, int daisy);
Пытается найти устройство на указанном параллельном порту, порту мультиплексора и адресе в цепочке, и возвращает номер устройства или -NXIO, если устройство с такими координатами не существует.
parport_device_coords -- преобразовать канонический номера устройства
int parport_device_coords(int devnum, int * parport, int * mux, int * daisy);
Функция преобразует номер устройства в его координаты: к какому параллельному порту в системе оно подключено, к какому порту мультиплексора оно подключен, если на этом порту имеется мультиплексор, и какой адрес имеет в цепочке устройств, если оно находится в цепочке устройств.
Вызывающая сторона должна выделить области для сохранения parport, mux и daisy.
Если устройство с указанным номером отсутствует, то возвращается -ENXIO. В противном случае области, на которые указывают parport, mux и daisy, заполняются координатами устройства. Если координата не определена, то используется значение -1.
На самом деле функция не очень полезна, но этот интерфейс был предложен в IEEE 1284.3.
parport_find_device -- найти указанное устройство
int parport_find_device(const char * mfg, const char * mdl, int from);
Проходит по списку устройств на параллельных портах в поисках устройства, у которого строки 'MFG' и 'MDL' в идентификаторе устройства IEEE 1284 будут совпадать с mfg и mdl.
Если найдено устройство, соответствующее указанным требованиям, то возвращается номер этого устройства. Если подходящего устройства не найдено, то возвращается отрицательное значение.
Новый поиск начинается с передачи значения NULL в аргументе from. Если from - не NULL, то поиск продолжается с указанного устройства.
parport_find_class -- найти устройство в указанном классе
int parport_find_class(parport_device_class cls, int from);
Проходит по списку устройств на параллельных портах в поисках устройства, у которого строка 'CLS' в идентификаторе устройства IEEE 1284 совпадает с cls.
Если найдено устройство, соответствующее указанным требованиям, то возвращается номер этого устройства. Если подходящего устройства не найдено, то возвращается отрицательное значение.
Новый поиск начинается с передачи значения NULL в аргументе from. Если from - не NULL, то поиск продолжается с указанного устройства.
parport_register_driver -- зарегистрировать драйвер устройства на параллельном порту
int parport_register_driver(struct parport_driver * drv);
Может вызываться драйвером устройства на параллельном порту для приёма уведомлений о портах, обнаруженных в системе, а также о более не доступных портах.
Место для хранения структуры drv выделяется вызывающей стороной и не должно освобождаться вплоть до вызова parport_unregister_driver.
Функция attach драйвера может блокироваться. Порт, который передан в attach, действителен только на время вызова, но если драйверу нужно взять копию указателя, то он может воспользоваться parport_get_port. Вызов parport_register_device с этим портом сделает это автоматически.
Функция detach драйвера не может блокироваться. Порт, который передан в detach, действителен только на время вызова, но если драйверу нужно взять копию указателя, то для этого он должен воспользоваться parport_get_port.
В случае успеха возвращает 0. В настоящее время всегда завершается успешно.
parport_unregister_driver -- отменить регистрацию драйвера устройства на параллельном порту
void parport_unregister_driver(struct parport_driver * arg);
Должна вызываться при выгрузке драйвера устройства на параллельном порту, который зарегистрировался при помощи parport_register_driver.
После возврата подпрограмма attach драйвера больше не будет вызываться, а для каждого из портов, для которого был вызван attach, будет вызвана подпрограмма detach.
Если функция attach вызывающего может блокироваться, то драйвер сам должен дождаться её завершения перед выгрузкой.
Перед возвратом из этой функции все вызовы detach драйвера будут гарантированно завершены.
В вызове detach драйвера не разрешается блокироваться.
parport_get_port -- увеличить счётчик ссылок на порт
struct parport * parport_get_port(struct parport * port);
Позволяет убедиться, что указатель на структуру parport останется доступным вплоть до соответствующего вызова parport_put_port.
parport_put_port -- уменьшить счётчик ссылок на порт
void parport_put_port(struct parport * port);
Должна вызываться для каждого из вызовов parport_get_port, когда порт больше не требуется.
parport_find_number -- найти параллельный порт по номеру
struct parport * parport_find_number(int number);
Возвращает параллельный порт с указанным номером или NULL, если его нет.
Выполняет неявный вызов parport_get_port. Чтобы отбросить ссылку на порт, которая была получена через parport_find_number, воспользуйтесь parport_put_port.
parport_find_base -- найти параллельный порт по базовому адресу
struct parport * parport_find_base(unsigned long base);
Возвращает параллельный порт с указанным базовым адресом или NULL, если его нет.
Выполняет неявный вызов parport_get_port. Чтобы отбросить ссылку на порт, которая была получена через parport_find_base, воспользуйтесь parport_put_port.
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);
Функция, вызываемая драйверами устройств на параллельном порту, объявляет, что это устройство подключено к порту и сообщает системе всё, что ей нужно знать.
Область для хранения 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 -- отменить регистрацию устройства на параллельном порту
void parport_unregister_device(struct pardevice * dev);
Отменяет действие parport_register_device.
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);
Функция аналогична parport_register_device, за исключением того, что находит устройство по его номеру, а не по порту, к которому оно подключено. См. parport_find_device и parport_find_class.
Все параметры, за исключением devnum, такие же как и у parport_register_device. Возвращаемое значение такое же, как и у parport_register_device.
parport_close -- закрыть устройство, открытое при помощи parport_open
void parport_close(struct pardevice * dev);
То же самое по отношению к parport_open, как parport_unregister_device по отношению к parport_register_device.
parport_claim -- затребовать доступ к устройству на параллельном порту
int parport_claim(struct pardevice * dev);
Эта функция не блокируется и поэтому может использоваться в контексте прерывания. Если parport_claim получила доступ к порту, то она вернёт ноль и порт будет доступен для использования. Она также может завершиться неудачно (вернув ненулевое значение), если порт используется другим драйвером и этот драйвер не хочет отказываться от управления портом.
parport_claim_or_block -- затребовать доступ к устройству на параллельном порту
int parport_claim_or_block(struct pardevice * dev);
Ведёт себя как parport_claim, но заблокируется, если необходимо подождать, когда освободится порт. Возвращаемое значение 1 указывает, что функция спала, а 0 означает, что функция сразу выполнилась успешно. Отрицательный код ошибки свидетельствует о неудаче.
parport_release -- отказаться от доступа к устройству на параллельном порту
void parport_release(struct pardevice * dev);
Функция не может завершиться неудачно, но она не должна вызываться для порта, доступ к которому не был получен ранее. Аналогично, если доступ к порту уже был получен, не нужно пытаться получить его снова.
parport_yield -- уступить доступ к параллельному порту
int parport_yield(struct pardevice * dev);
Функция временно отказывается от порта, если он может быть полезен для работы других драйверов. Затем функция пытается вернуть доступ к порту при помощи parport_claim и возвращает такое же значение, как и parport_claim. Если функция завершится неудачно, то доступ к порту будет потерян и сам драйвер будет отвечать за его повторное получение.
Функции parport_yield и parport_yield_blocking предназначены для отметки мест в драйвере, где другие драйверы могут затребовать доступ к порту и использовать его для связи со своими устройствами. Уступка порта аналогична его освобождению и повторному затребованию, но более эффективна, т.к. если нет других драйверов, которым требуется доступ к порту, то никаких действий не предпринимается. На деле ничего не делается даже тогда, когда есть другие устройства, ожидающие доступа, но текущее устройство находится внутри своего кванта времени. По умолчанию квант времени - полсекунды, но эта длительность может настраиваться через интерфейс /proc.
parport_yield_blocking -- уступить доступ к параллельному порту
int parport_yield_blocking(struct pardevice * dev);
Функция временно отказывается от порта, если он может быть полезен для работы других драйверов. Затем функция пытается вернуть доступ к порту при помощи parport_claim_or_block и возвращает такое же значение, как и parport_claim_or_block.
parport_negotiate -- согласовать режим IEEE 1284
int parport_negotiate(struct parport * port, int mode);
Используйте для согласования определённого режима передачи IEEE 1284. Параметр mode должен быть одной из констант, определённых в файле parport.h, имя которой начинается с IEEE1284_MODE_xxx.
Возвращает значение 0, если периферийное устройство согласовало указанный режим. -1 возвращается, если периферийное устройство не совместимо со стандартом IEEE 1284 (или отсутствует). 1 возвращается, если периферийное устройство не согласовало указанный режим.
parport_write -- записать блок данных в параллельный порт
ssize_t parport_write(struct parport * port, const void * buffer, size_t len);
Пишет до len байт из буфера в указанный порт, используя последний из согласованных (при помощи parport_negotiate) режимов передачи IEEE 1284, если этот режим поддерживает прямую передачу (от компьютера к периферийному устройству).
За действительность первых len байт буфера отвечает вызывающая сторона.
Функция возвращает количество переданных байт (если передано ноль или больше), а в противном случае возвращает код ошибки.
parport_read -- прочитать блок данных из параллельного порта
ssize_t parport_read(struct parport * port, void * buffer, size_t len);
Читает до len байт данных из указанного порта в буфер, используя последний из согласованных (при помощи parport_negotiate) режимов передачи IEEE 1284, если этот режим поддерживает обратную передачу (от периферийного устройства на компьютер).
За доступность для записи первых len байт буфера отвечает вызывающая сторона.
Функция возвращает количество принятых байт (если принято ноль или больше), а в противном случае возвращает код ошибки.
parport_set_timeout -- задать таймаут бездействия устройства
long parport_set_timeout(struct pardevice * dev, long inactivity);
Задаёт таймаут бездействия указанного устройства на порту. Действует на функции, подобные parport_wait_peripheral. Специальное значение 0 означает - не использовать расписание при работе с этим устройством.
Возвращает предыдущее значение таймаута бездействия.
Все обратившиеся к parport_wait_event для этого устройства будут разбужены.
Хотя описанный в этом документе интерфейс был значительно обновлён в ядре 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.