Описанный здесь драйвер КАМАКа для 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'
Драйвер имеет следующие черты:
make
в директории, где находится пакет. При этом будет создан загружаемый
модуль ppi6.o
Сказать
make camt
для трансляции программы ручной работы с КАМАКом.
Для дальнейших шагов по установке необходимы права суперпользователя;
make devices
При этом будут созданы файлы `/dev/ppia0' ... `/dev/ppia5' и
`/dev/ppib0' ... `/dev/ppib5';
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>
В этом файле находятся константы и макросы для кодирования параметров при вызове системных функций и описаны функции, облегчающие работу с КАМАКом.
Драйвер обрабатывает следующие системные вызовы:
int open(const char *pathname, int flafs);
Открыть КАМАК крейт. pathname это строка `/dev/ppi0' или
`/dev/ppi1'
( и т.д. если используется больше одной интерфейсной платы).
flags должен быть O_RDWR.
Функция возвращает дескриптор файла (fd), с которым будут работать остальные
функции, или -1 в случае ошибки.
int close(int fd);
Функция 'закрывает' КАМАК крейт.
Возвращает 0 при успешном выполнении.
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.
int read(int fd, char *buf, size_t count); int write(int fd, char *buf, size_t count);
Эти функции обеспечивают проведение КАМАК цикла с предварительно
установленными функцией lseek адресом, субадресом и функцией.
Тип проводимого КАМАК цикла зависит от значения счетчика count.
count = 2
count = 3
count = 4*n
Данные читаются/пишутся из/в buf.
При успешном выполнении возвращается количество переданных
байтов. При ошибке возвращается -1.
Ответ X и Q можно узнать через
ioctl(fd ,CAMAC_STATUS, &status).
При использовании этих функций обеспечивается максимальная скорость
передачи блоков данных. Для выполнения одиночных КАМАК функций лучше
использовать функцию ioctl().
int ioctl(int fd, int cmd, unsigned long *argp);
Самая 'развесистая' из описываемых здесь функций. Позволяет проводить
КАМАК циклы с данными и без данных, получать ответ блока и таймаут на
последний, проведенный из используемого fd, КАМАК-цикл.
Допустимы следующие команды cmd, определенные в файле ppi6camac.h:
NAF(n, a, f)
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)
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
При успешном выполнении ioctl возвращает 0 или положительное
число, в котором закодирован осмысленный ответ. При ошибке
возвращается -1 и номер ошибки записывается в errno.
Макросы и функции в файле `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
Функции
возвращают ответ 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
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 при ошибке.
int CAM_LWAITG(int fd, int g, int timeout ) - ожидает
появление LAM в групповом запросе g.
int CAM_LWAIT(int fd, int l, int timeout) - ожидает появление LAM от
блока в позиции l.
timeout > 0
request в течении
таймаута. При возникновении LAM возвращает остаток от таймаута.
( 0 так же возможен. например LAM прилетел в последний момент);
timeout = 0
0, иначе -1;
timeout < 0
При отсутствии LAM запроса в течении указанного таймаута возвращается ошибка ETIME.
Ожидание таймаута может быть также прервано немаскированным сигналом. В этом случае возвращается соответствующая ошибка.
int CAM_L2G(int l) - преобразование номера позиции в крейте в
номер группового запроса.
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 при ошибке.
Драйвер сообщает о следующих ошибках:
buf (для
функций read и write) или параметр argp (в
функции ioctl);
Проверка и обкатка драйвера, добавление новых возможностей.
Вопросы:
Нужно ли ожидание LAM по маске ?
Нужен ли захват КАМАК блоков, и, если нужно, то как это должно выглядеть ? Должна ли это быть чисто информационной функция, или надо отвергать все попытки домогаться до уже захваченного блока ?
работа над ошибками. Как улучшить ?
Принимаю вопросы, замечания и предложения
Алексей Никифоров
nikiforov@inp.nsk.su
camt ручной контроллер
Интерактивная программа camt написана для работы в качестве ручного
контроллера и для проверки и отладки КАМАК драйвера.
При старте, и после выполнения очередной строчки выдает приглашение ко вводу. Программа принимает последовательность однобуквенных команд. Команды могут сопровождаться параметрами.
Команды программы разделяются на три группы:
n, a, f. При вызове такой команды
без параметров выдается значение этой переменной, при
вызове с параметром переменной присваивается это значение;
Ниже перечислены основные команды программы.
o имя_файла
s присваивается значение полученного дескриптора;
e
C
Z
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]
G или группового запроса, указанного
командой g в течении таймаута T;
I
I<value>
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
b[val]
bs);
g[val]
G[val]
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
This document was generated on 24 February 2000 using texi2html 1.56k.