Описанный здесь драйвер КАМАКа для 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.