Мы создаем простое приложение, которое открывает наш модуль и начинает бинарный отчет на штырьках с DO до D7.
Этот код компилируется с помощью дсс арр. с. По умолчанию программа собира¬ется в а. out.
арр. с
ООО //Приложение,
использующее драйвер параллельного порта
#include finclude 004 #include "parll.h"
main() {
int fptr;
int i,retval,parm =0; printf("\nopening driver now"); 012 if((fptr = open("/dev/parll",0_WR0NLY))<0) {
printf ("\nopen failed, returned=?%d", fptr); exit(l);
}
018 {
020 021 022
024
for(i=0;i<0xff ;i++)
Модуль инициализации используется для связи модуля с операционной системой. Он может применяться для ранней инициализации необходимых структур данных. Так как драйверу параллельного порта не требуется сложных структур данных, мы просто регистрируем модуль.parll.с
static int parll_init (void) {
int retval;
retval= register_chrdev(Major, MODULE_NAME, &parlport_fops);
if(retval < 0)
{
printkf "\n%s: can't register",MODULE_NAME); return retval;
}
else {
Maj or=retval;
Нижеследующее обсуждение посвящено соответствующей функции для этого проекта. Полный листинг программы для parll. с вместе с файлом parll. л приведен в конце этой книги.
1) Настройка файловых операций (fops)
Как говорилось ранее, этот модуль использует open (), close () и ioctl (), как и описанные ранее init и cleanup.
Любой поиск в сети о параллельном порте выдает огромный массив информации. Так как нашей целью в этой главе является описание модулей Linux, мы коснемся только основ этого устройства.
В этом проекте мы будем экспериментировать на х86-системе. Структуру драйвера легко портировать на PowerPC; для этого нужно просто обратиться к другому устройству на уровне ввода-вывода. Несмотря на то что параллельный порт существует на многих встроенных реализациях PowerPC, он слабо распространен на десктопах (таких, как G4 и G5).
Этот проект представляет вашему вниманию основы контроллера параллельного порта и во что сливаются ранее описанные функции ввода-вывода. Параллельный порт обычно интегрирует в Superio часть чипсета и является хорошим примером для написания осно¬вы драйвера символьного устройства. Этот драйвер, или динамически загружаемый модуль (module), не особенно полезен, хотя и годится для дальнейшего усовершенство¬вания. Так как мы адресуем устройство на уровне регистров, этот модель может исполь¬зоваться на системах PowerPC для доступа к вводу-выводу, как описано в документации по отображению в память.
Контроллер DMA является аппаратным устройством, расположенным между устройством ввода-вывода и (обычно) высокопроизводительной шиной системы. Назначение контроллера DMA заключается в перемещении большого массива данных без вмешательства процессора. Контроллер DMA без задействования процессора может быть запрограммирован на перемещение блоков данных в основную память и из нее. На уровне регистров контроллер DMA получает адреса источника и назначения и длину, необходимые для выполнения задачи.
Ранние терминалы были телетайпными машинами (отсюда и произошло имя tty для драйвера последовательного порта). Консольное устройство было разработано в середине прошлого века с целью отправки и приема текста по телеграфным сетям. В ранних 60-х телетайп превратился в ранний стандарт RS-232 и стал использоваться во множестве появляющихся микрокомпьютеров. В терминалах 70-х телетайп использовался для связи компьютеров. Настоящие терминалы стали редкостью. Популярные на мейнфреймах и мини-компьютерах в 70-х, терминалы были заменены на компьютерах 80-х программными эмуляторами терминалов.
Сетевые устройства имеют атрибуты как блочных, так и символьных устройств и зачастую рассматриваются как особый класс устройств. Подобно символьным устройствам, на физическом уровне данные передаются последовательно. При этом данные упаковываются в пакеты и передаются на и сетевой контроллер с него с помощью прямого доступа к памяти (обсуждается в подразд. 5.2.9) как для блочных устройств.
Сетевые устройства только упоминаются в этой главе, но из-за своей сложности они выходят за пределы рассмотрения этой книги.
В отличие от блочных устройств символьные устройства посылают поток данных. Все последовательные устройства являются символьными. Когда мы используем классический пример контроллера клавиатуры или последовательного терминала в качестве символьного устройства, становится интуитивно понятным, что мы не можем (и не хотим) получать данные от устройства не по порядку. Так мы подходим к серой области пакетной передачи данных. Сеть Ethernet на физическом уровне является последовательным устройством, но на уровне шины используется DMA для передачи в память и из памяти больших порций данных.
Базовое обобщенное блочное устройство имеет open, close (освобождение), ioctl и, что самое главное, функцию request. По крайней мере функции open и close могут быть простыми счетчиками. Интерфейс ioctl() может использоваться для отладки и выполнения измерений при прохождении через различные слои программного обеспечения. Функция request, вызываемая, когда запрос помещается в очередь файловой системой, извлекает структуру запроса и обрабатывает его содержимое. В зависимости от того, является ли запрос запросом на чтение или на запись, устройство выполняет соответствующее действие.