ppi6camac


Введение

Описанный здесь драйвер КАМАКа для Linux-а работает с платой интерфейса ППИ-6 и контроллером крейта К0607, разработанными Путьмаковым, ИЯФ.

За основу был взят драйвер, написанный Ole Streicher для Aachen DBCC Controller with PCCPI Card.

Каждому подключенному к компьютеру крейту КАМАК ставится в соответствие специальный файл. При установке по умолчанию эти файлы находятся в директории `/dev'. В компьютер может быть установленно две платы интерфейса. Для именования крейтов, подключенных к первой плате приняты имена, начинающиеся с `ppia', ко второй - с `ppib'. Пример:

`/dev/ppia0' - для первого крейта, подключенного к первой плате интерфейса;

`/dev/ppib3' - для третьего крейта, подключенного ко второй плате интерфейса.

Открыв эти файлы, можно работать с КАМАКом, используя функции работы с файлами: open, close, ioctl, lseek, read, write и макросы из файла `ppi6camac.h'

Драйвер имеет следующие черты:

Установка драйвера

Трансляция драйвера

  1. Распаковать пакет в подходящем месте;
  2. Оттранслировать. Для чего достаточно сказать make в директории, где находится пакет. При этом будет создан загружаемый модуль ppi6.o Сказать make camt для трансляции программы ручной работы с КАМАКом. Для дальнейших шагов по установке необходимы права суперпользователя;
  3. Создать специальные файлы, соответствующие крейтам. Для этого надо сказать make devices При этом будут созданы файлы `/dev/ppia0' ... `/dev/ppia5' и `/dev/ppib0' ... `/dev/ppib5';
  4. Установить пакет, для чего сказать make install Файл `ppi6.o' будет скопирован в `/lib/modules/$(VERSION)/misc'; файл `ppi6camac.h' будет скопирован в `/usr/local/include'; файл `camt' будет скопирован в `/usr/local/bin'; info описание драйвера будет установлено в систему.

Установка модуля

Есть несколько способов установки загружаемого модуля `ppi6.o' в систему.

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

    insmod ppi6 [irq=15] [major=120] [io=0x250]

Для каждой платы интерфейса должен быть загружен свой экземпляр модуля со своим уникальным именем. Например `ppia' и `ppib'.

Необязательные параметры irq, major, io предназначены для настройки драйвера под конкретную интерфейсную плату и конфигурацию.

Для удаления модуля из системы надо сказать, обладая правами суперпользователя

    rmmod ppi6

Другой способ -- описать параметры в файле `/etc/conf.modules':

alias ppia ppi6
options ppia -o ppia io=0x240 irq=10 major=120
alias ppib ppi6
options ppib -o ppib io=0x250 irq=12 major=121

Теперь для установки драйвера для первой платы достаточно сказать

	modprobe ppia

А добавив в тот же файл:

alias char-major-120 ppi6
options char-major-120 -o ppia io=0x240 irq=10 major=120
alias char-major-121 ppi6
options char-major-121 -o ppib io=0x250 irq=12 major=121

Драйвер будет `сам' устанавливаться при открытии соответствующего файла.

Использование драйвера.

Драйвер доступен через специальные файлы. При установке по умолчанию это файлы `/dev/ppia0' и `/dev/ppia1'. Файлы соответствуют первому и второму крейтам, подключенным к первой плате интерфейса.

В программе на "C" и "C++" для использования драйвера необходимо подключить файл `ppi6camac.h':

#include<ppi6camac.h>

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

Системные вызовы

Драйвер обрабатывает следующие системные вызовы:

open()

int open(const char *pathname, int flafs);

Открыть КАМАК крейт. pathname это строка `/dev/ppi0' или `/dev/ppi1' ( и т.д. если используется больше одной интерфейсной платы). flags должен быть O_RDWR.

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

close()

int close(int fd);

Функция 'закрывает' КАМАК крейт.

Возвращает 0 при успешном выполнении.

lseek()

off_t lseek(int fd, off_t offset, int whence)

Функция передает в драйвер адрес N, субадрес A, функцию F и, возможно, признак 24-х битовой работы через offset параметр. Следующие за этим функции read и write будут проводить CAMAC обмены, использую переданные параметры.

offset можно построить, используя макро NAF(N,A,F) или NAF24(N,A,F) из `ppi6camac.h'.

whence параметр может быть только SEEK_SET. Функция возвращает -1 при ошибке. Т.о. типичное использование этой функции:

 lseek(fd, NAF(n, a, f), SEEK_SET);

lseek не выполняет никаких операций обмена с крейтом, она только устанавливает в драйвере 'указатель позиции в файле', согласно N, A и F для последующего использования.

При отсутствии ошибки функция возвращает параметр offset.

read() и write()

int read(int fd, char *buf, size_t count);
int write(int fd, char *buf, size_t count);

Эти функции обеспечивают проведение КАМАК цикла с предварительно установленными функцией lseek адресом, субадресом и функцией.

Тип проводимого КАМАК цикла зависит от значения счетчика count.

count = 2
- проводится 16-и разрядный КАМАК цикл
count = 3
- проводится 24-х разрядный КАМАК цикл
count = 4*n
- проводится n 16-и или 24-х разрядных КАМАК циклов ( аналог LONG NAF )

Данные читаются/пишутся из/в buf.

При успешном выполнении возвращается количество переданных байтов. При ошибке возвращается -1.

Ответ X и Q можно узнать через ioctl(fd ,CAMAC_STATUS, &status).

При использовании этих функций обеспечивается максимальная скорость передачи блоков данных. Для выполнения одиночных КАМАК функций лучше использовать функцию ioctl().

ioctl()

int ioctl(int fd, int cmd, unsigned long *argp);

Самая 'развесистая' из описываемых здесь функций. Позволяет проводить КАМАК циклы с данными и без данных, получать ответ блока и таймаут на последний, проведенный из используемого fd, КАМАК-цикл.

Допустимы следующие команды cmd, определенные в файле ppi6camac.h:

NAF(n, a, f)
- провести 16-и разрядный КАМАК цикл. для команд чтения ( F0 - F7), argp - куда писать, для команд записи ( F16 - F23), argp - откуда читать. argp может быть NULL. В этом случае проводится КАМАК цикл, данные не передаются. Возвращает ответ X, Q в младших двух битах. При ошибке или таймауте возвращает -1. Код ошибки можно посмотреть в errno.
CAMAC_24 | NAF(n, a, f)
- то же что и NAF, но проводится 24-х разрядный КАМАК цикл.
NAF24(n, a, f)
- см. выше.
CAMAC_STATUS
- кладет в *argp ответы timeout,X,Q в младшие три бита. Ответ дается от последнего, проведенного через используемый дескриптор fd, КАМАК цикла. Так можно получить эти ответы от long naf, проведенного через read или write.
CAMAC_NON_DATA
- провести КАМАК цикл без данных, с N, A, F предварительно установленных через lseek. Ответ timeout, X, Q можно получить через ioctl командой CAMAC_STATUS.
CAMAC_LWAIT(lgroup)
- ожидание появления LAM в групповом запросе lgroup. timeout=argp если timeout > 0 то ждать LAM в течении этого таймаута; если timeout < 0 - ждать вечно; если timeout == 0 то провести проверку наличия LAM запроса. timeout указывается в "тиках". (для x86 тик равен 10 миллисекунд). Возвращает остаток таймаута, если LAM появился в указанный срок, иначе -1 и errno=ETIME. Для "вечного" ожидания при появлении LAM возвращается 0. При ошибках возвращается -1.
CAMAC_ION(1)
- включает линию INHIBIT
CAMAC_IOFF(2) - выключает линию INHIBIT

Команды доступа к регистрам контроллера крейта:

CAMAC_READ_LM
- прочитать в *argp регистр маски и запросов;
CAMAC_WRITE_LM
- запиши из *argp регистр маски и запросов. Формат этого регистра можно найти в описании крейт-контроллера К0607;
CAMAC_READ_HB
- прочитай в *argp регистр старшего байта;
CAMAC_WRITE_HB
- запиши из *argp в регистр старшего байта;
CAMAC_READ_CONTROL
- прочитать регистр статуса и управления контроллера;
CAMAC_WRITE_CONTROL
- записать регистр статуса и управления контроллера Формат этого регистра можно найти в описании крейт-контроллера К0607.

При успешном выполнении ioctl возвращает 0 или положительное число, в котором закодирован осмысленный ответ. При ошибке возвращается -1 и номер ошибки записывается в errno.

Макросы, определенные в ppi6camac.h

Макросы и функции в файле `ppi6camac.h' служат двум целям.

Во-первых они кодируют параметры, такие как N, A, F и другие, для передачи через системные вызова драйверу. (see section ioctl(), see section lseek()).

Во-вторых они используются для сокрытия деталей реализации и облегчения работы с КАМАКом. В этом разделе описаны именно последние. Описанные макросы обеспечивают достаточно полный набор инструментов для работы с КАМАКом.

Кодирование

int NAF(n,a,f) - кодирует n, a, f для функций lseek, ioctl и CAM для проведения 16-и битового КАМАК цикла.

int NAF24(n,a,f) - кодирует n, a, f для функций lseek, ioctl и CAM для проведения 24-х битового КАМАК цикла.

int CAM_L2G(int l) - преобразование номера позиции в крейте в номер группового запроса.

Проведение КАМАК цикла

int CAM(int fd, int naf, unsigned *pdata) - проводит 16-и разрядный КАМАК цикл, с данными *pdata. pdata может быть NULL.

int CAMW(int fd, int naf, unsigned data) - проводит 16-и разрядный КАМАК цикл записи, с данными data.

int CAM24(int fd, int naf, unsigned *pdata) - проводит 24-х разрядный КАМАК цикл, с данными *pdata. pdata может быть NULL.

int CAM24W(int fd, int naf, unsigned data) - проводит 24-х разрядный КАМАК цикл записи, с данными data.

Параметры функции:

fd
дескриптор открытого файла устройства, соответствующего КАМАК крейту;
naf
NAF инструкция для проведения обмена.

Функции возвращают ответ X, Q в младших двух битах. При ошибках возвращают -1.

Блочные передачи

int CAM_READ( int fd, int naf, unsigned * buf, int num)

int CAM_WRITE( int fd, int naf, unsigned * buf, int num)

CAM_READ служит для чтения блока данных из КАМАК блока, CAM_WRITE для записи блока данных в КАМАК блок.

Параметры функции:

fd
дескриптор открытого файла устройства, соответствующего КАМАК крейту;
naf
NAF инструкция для проведения обмена. Может означать как 16-и так и 24-х битовый обмен.(See section Кодирование.);
buf
адрес массива данных. Массив должен состоять из беззнаковых целых и иметь достаточный размер;
num
требуемое количество обменов.

При успешном проведении обмена CAM_READ и CAM_WRITE возвращают ответ X и Q в двух младших битах. При ошибке возвращается -1.

Специальные функции

int CAM_C(int fd) - проводит Clear цикл.

Возвращает 0 при успешном выполнении, -1 при ошибке.

int CAM_Z(int fd) - проводит Zero цикл.

Возвращает 0 при успешном выполнении, -1 при ошибке.

Ожидание LAM запроса

int CAM_LWAITG(int fd, int g, int timeout ) - ожидает появление LAM в групповом запросе g.

int CAM_LWAIT(int fd, int l, int timeout) - ожидает появление LAM от блока в позиции l.

timeout > 0
- ожидает появление LAM в групповом запросе request в течении таймаута. При возникновении LAM возвращает остаток от таймаута. ( 0 так же возможен. например LAM прилетел в последний момент);
timeout = 0
- проверяет наличие указанного LAM запроса. При его наличие возвращает 0, иначе -1;
timeout < 0
- навеки зависает в ожидании LAM

При отсутствии LAM запроса в течении указанного таймаута возвращается ошибка ETIME.

Ожидание таймаута может быть также прервано немаскированным сигналом. В этом случае возвращается соответствующая ошибка.

int CAM_L2G(int l) - преобразование номера позиции в крейте в номер группового запроса.

Линия INHIBIT

int CAM_ION(int fd) -- включает линию INHIBIT;

int CAM_IOFF(int fd) -- выключает линию INHIBIT;

int CAM_I(int fd) - проверка состояния линии INHIBIT. Возвращает 0 если выключена, 1 если включена.

Функции CAM_ION, CAM_IOFF и CAM_I возвращают -1 при ошибке.

Сообщения об ошибках

Драйвер сообщает о следующих ошибках:

EIO
ошибка ввода/вывода. Например выключен или отключен крейт(3);
EFAULT
в функцию передан неправильный адрес буфера buf (для функций read и write) или параметр argp (в функции ioctl);
EINVAL
неправильный аргумент при вызове функции;
ENOMEM
не хватает памяти для выполнения операции;
ETIME
не дождались указанного LAM запроса в указанный отрезок времени.

Планы на будущее

Проверка и обкатка драйвера, добавление новых возможностей.

Вопросы:

Нужно ли ожидание LAM по маске ?

Нужен ли захват КАМАК блоков, и, если нужно, то как это должно выглядеть ? Должна ли это быть чисто информационной функция, или надо отвергать все попытки домогаться до уже захваченного блока ?

работа над ошибками. Как улучшить ?

Принимаю вопросы, замечания и предложения

Алексей Никифоров

nikiforov@inp.nsk.su

Программа camt ручной контроллер

Интерактивная программа camt написана для работы в качестве ручного контроллера и для проверки и отладки КАМАК драйвера.

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

Команды

Команды программы разделяются на три группы:

  1. Команды, выполняющие реальные действия, такие как открытие файла или проведение КАМАК цикла. За большинством таких команд может следовать необязательный параметр - к-во повторений этой команды. При отсутствии этого параметра команда повторяется один раз;
  2. Команды, изменяющие или проверяющие содержимое переменных программы, таких как n, a, f. При вызове такой команды без параметров выдается значение этой переменной, при вызове с параметром переменной присваивается это значение;
  3. информационные команды, показывающие результат выполнения других команд.

Ниже перечислены основные команды программы.

Команды обмена

o имя_файла
открывает файл устройства, соответствующего КАМАК крейту. Переменной s присваивается значение полученного дескриптора;
e
закрывает текущий дескриптор;
C
проводит цикл Clear;
Z
проводит цикл Zero
c [count]
проводит КАМАК цикл с текущими n, a, f. Данные читаются/пишутся в/из переменной d (data). Результат проведения КАМАК цикла можно посмотреть командой x;
r [count]
проводит КАМАК цикл чтения с блоком данных (CAM_READ). Данные читаются в массив D(Data), размер блока данных определяется переменой b(block_size);
w [count]
проводит КАМАК цикл записи с блоком данных (CAM_WRITE). Данные записываются в массив D(Data), размер блока данных определяется переменой b(block_size);
L [count]
ждет появления LAM запроса от позиции в крейте, указанной командой G или группового запроса, указанного командой g в течении таймаута T;
I
проверить состояние линии Inhibit;
I<value>
включить/выключить Inhibit;
l[count]
выполняет lseek с установленными n, a, f и признаком работы со старшим байтом h;
R [count]
выполняет read с параметрами установленными функцией lseek;
W [count]
выполняет write с параметрами установленными функцией lseek;
q
выход из программы.

Команды-переменные

s[value]
дескриптор файла;
n,a,f
n,a,f;
h[value]
признак работы со старшим байтом;
d[value]
данные для обмена (data);
D[val [val [val ...]]]
массив данных (Data);
F
заполни массив данных последовательностью 0, 1, 2, ... , bs-1;
b[val]
размер массива данных в словах (bs);
g[val]
номер группового запроса;
G[val]
номер блока, от которого ожидается LAM запрос;
T[val]
таймаут;

Если при выполнении этих команд произошла ошибка, то об этом будет выведено соответствующее сообщение.

Информационные команды

x
ответ на последнюю проведенную операцию;
t
сколько времени заняла последняя операция;
?
печатает экран подсказки.

Пример работы

$ camt
 camt from ppi6camac 0.3.1a
>o /dev/ppi0
fd=3
>n6 f16 a0 d0xa c x
res=3
>f0 c d x
data=0xa
res=3
>

Список функций

Jump to: c - l - n - o - r - w

c

  • CAM
  • CAM24
  • CAM24W
  • CAM_C
  • CAM_I
  • CAM_IOFF
  • CAM_ION
  • CAM_L2G
  • CAM_LWAIT
  • CAM_LWAITG
  • CAM_READ
  • CAM_WRITE
  • CAM_Z
  • CAMW
  • close
  • l

  • lseek
  • n

  • NAF
  • NAF24
  • o

  • open
  • r

  • read
  • w

  • write

  • This document was generated on 24 February 2000 using texi2html 1.56k.