
                 Краткое руководство программиста по работе
   с драйвером TMK1553B v4.08 для Microsoft Windows 98/ME/2000/XP/Vista/7
          при работе с платами терминала мультиплексного канала
            (обеспечивающими сопряжение ПЭВМ типа IBM PC AT
   c мультиплексным каналом по ГОСТ 26765.52-87 или ГОСТ Р 52070-2003).
              (Полная документация в архиве 1553docs.zip).

     Основой драйвера TMK1553B плат терминалов мультиплексного канала по 
ГОСТ 26765.52-87 или ГОСТ Р 52070-2003 (MIL-STD-1553B) для Microsoft Windows 
98/ME/2000/XP/7 является модуль драйвера 1553bwdm.sys. Установка драйвера 
производится стандартными средствами установки оборудования системы Windows. 
Для 32-битных систем надо устанавливать драйвер из папки Driver\drv32\ , а 
для 64-битных систем - из папки Driver\drv64\ . Платы PnP (все PCI платы) 
автоматически обнаруживаются и конфигурируются операционной системой при 
установленном драйвере, платы с шиной ISA не поддерживают PnP и должны 
устанавливаться и конфигурироваться вручную.

     Для каждой установленной в компьютер платы создается уникальное
символьное имя, к которому имеет доступ только один процесс, захвативший 
плату вызовом tmkconfig.

     API драйвера TMK1553B для Microsoft Windows практически полностью 
повторяет набор функций драйвера TMKLL4 для MS-DOS. Исключение составляют 
функции инициализации, конфигурации и завершения работы драйвера, а также 
обслуживание прерываний от плат. Для работы с драйвером необходимо с 
помощью директивы 

#include "wdmtmkv2.cpp"

подключить в текст программы на языке C/C++ файл wdmtmkv2.cpp, содержащий
определения всех констант и функций трансляции вызовов TMKLL4 в вызовы 
TMK1553B.

     Начинать работу с драйвером необходимо с вызова функции TmkOpen: 

DWORD TmkOpen();

которая динамически загружает драйвер в память и производит его начальную 
настройку. При успешном завершении функция возвращает нулевое значение. 
При невозможности загрузить драйвер вызовом CreateFile возвращается код 
ошибки, полученный вызовом GetLastError.

     После окончания работы с TMK1553B должна вызываться функция TmkClose:

void TmkClose();

     Все платы, установленные в компьютере, описываются в реестре Windows,
при этом каждой плате присвоен фиксированный номер от 0 до 8. Чтобы 
начать работу с конкретной платой, необходимо вызвать функцию tmkconfig, 
задав в качестве единственного параметра номер платы: 

int tmkconfig(int tmkNumber);

Если плата с заданным номером описана в реестре Windows и с платой к 
этому моменту не работает ни один процесс, то функция закрепляет эту плату 
за вызвавшим tmkconfig процессом, и в дальнейшем этот процесс получает 
исключительный доступ к плате. При этом функция tmkconfig возвращает 
нулевое значение. Если плата уже закреплена за каким-либо процессом или 
вообще не описана в реестре, то возвращается код ошибки TMK_BAD_NUMBER. 

     Процесс освобождает платы, с которыми закончил работу, через вызов 
функции tmkdone:

int tmkdone(int tmkNumber);

В качестве параметра можно задавать либо номер конкретной платы, либо 
константу ALL_TMKS, при этом освобождаются все платы, захваченные 
процессом.

     После захвата платы в вызове tmkconfig вся работа (за исключением 
работы с прерываниями) осуществляется полностью аналогично работе через 
драйвер TMKLL4 для MS-DOS, т.е. точно также существуют понятия текущей 
платы (устанавливается функций tmkselect), текущей базы в режимах КК и 
МТ, текущего подадреса в режиме ОУ.

     Описание работы с драйвером содержится в файлах tmkguide.doc и
tmkref.doc.

     В связи с конфликтом с API Windows символических имен констант 
EM_MASK и DI_MASK, все константы масок выделения битов в слове результата 
обмена ERAO_MASK, MEO_MASK, IB_MASK, TO_MASK, EM_MASK, EBC_MASK, DI_MASK, 
ELN_MASK, G1_MASK, G2_MASK изменены добавлением символов 'S_' перед
именем. Новые имена констант: S_ERAO_MASK, S_MEO_MASK, S_IB_MASK, 
S_TO_MASK, S_EM_MASK, S_EBC_MASK, S_DI_MASK, S_ELN_MASK, S_G1_MASK, 
S_G2_MASK.

     Из состава функций драйвера TMKLL4 в драйвере TMK1553B исключены все 
функции работы с прерываниями: bcdefintnorm, bcdefintexc, bcdefintx, 
bcdefintsig, rtdefintcmd, rtdefinterr, rtdefintdata, mtdefintx, 
mtdefintsig, bcrestore, rtrestore, mtrestore, tmksave, tmkrestore, 
tmkdefirq, tmkundefirq.

     В драйвере TMK1553B работа с прерываниями от плат осуществляется через 
механизм событий Win32. Прежде всего процесс должен сообщить драйверу 
идентификатор (handle) используемого события для текущей выбранной платы 
через вызов функции tmkdefevent, которой передается в качестве первого 
параметра идентификатор события Win32, полученный из вызова Win32 API 
CreateEvent:

void tmkdefevent(HANDLE hEvent, BOOL fEventSet);

Нулевое значение hEvent отменяет использование события платой. Значение 
параметра fEventSet равное TRUE указывает на необходимость установки 
события драйвером TMK1553B через вызовы SetEvent, а значение FALSE - через 
вызовы PulseEvent.

Внимание! В текущей версии драйвера значение переменной fEventSet 
игнорируется (принимается равным TRUE). Кроме того, рекомендуется вызывать
функцию ResetEvent непосредственно перед вызовом tmkdefevent.

     После получения события от драйвера процесс может запросить структуру 
данных, описывающих прерывание, ставшее причиной события. Для этого 
предназначена функция tmkgetevd:

void tmkgetevd(TTmkEventData *pEvD);

В качестве параметра передается указатель на структуру типа TTmkEventData, 
которую и заполняет драйвер соответствующими значениями:

typedef struct
{
  int nInt;
  unsigned short wMode;
  union
  {
    struct
    {
      unsigned short wResult;
      unsigned short wAW1;
      unsigned short wAW2;
    } bc;
    struct
    {
      unsigned short wBase;
      unsigned short wResultX;
    } bcx;
    struct
    {
      unsigned short wStatus;
      unsigned short wCmd;
    } rt;
    struct
    {
      unsigned short wBase;
      unsigned short wResultX;
    } mt;
    struct
    {
      unsigned short wStatus;
    } mrt;
  };
} TTmkEventData;

     Память под структуру должна быть выделена заранее в самом процессе, 
драйвер только заполняет ее! Первыми двумя полями определяется тип 
прерывания и соответствующие этому типу дополнительные поля.  Существует 
прямое соответствие между типами прерываний, существующих в драйвере 
TMKLL4 для MS-DOS и в драйвере TMK1553B для Microsoft Windows. С 
использованием имен функций задания подпрограмм пользовательской обработки 
прерывания из TMKLL4 соответствие следующее:

bcdefintnorm   wMode=BC_MODE, nInt=1, дополнительные данные bc.wResult;
bcdefintexc    wMode=BC_MODE, nInt=2, дополнительные данные bc.wResult,
               bc.wAW1, bc.wAW2;
bcdefintx      wMode=BC_MODE, nInt=3, дополнительные данные bcx.wResultX,
               bcx.wBase;
bcdefintsig    wMode=BC_MODE, nInt=4, дополнительные данные bcx.wBase;

rtdefintcmd    wMode=RT_MODE, nInt=1, дополнительные данные rt.wCmd;
rtdefinterr    wMode=RT_MODE, nInt=2, дополнительные данные rt.wStatus;
rtdefintdata   wMode=RT_MODE, nInt=3, дополнительные данные rt.wStatus;

mtdefintx      wMode=MT_MODE, nInt=3, дополнительные данные mt.wResultX,
               mt.wBase;
mtdefintsig    wMode=MT_MODE, nInt=4, дополнительные данные mt.wBase.
mtdefintx      wMode

     Если возможна ситуация, когда до получения события процессом могут
возникнуть новые прерывания (а обычно это так и есть), то после получения
события необходимо вызывать tmkgetevd в цикле до тех пор, пока в полученной
структуре TTmkEventData поле номера прерывания не окажется нулевым (значения
остальных полей структуры TTmkEventData в случае nInt=0 не определены). После
этого снова можно ждать события. Надо учитывать, что новое событие может
возникнуть еще во время цикла вызовов tmkgetevd для обработки предыдущего
события; тогда при обработке нового события первый же вызов tmkgetevd даст
нулевой номер прерывания, так как данные этого события были прочитаны раньше.

    Начиная с версии v2.00, драйвер поддерживает работу с платами TX6/TE6 в
режиме многоадресного ОУ (МОУ), а, начиная с версии v4.00, добавлена поддержка 
режима МОУ на плате TA1-PCI-32RT. В этом режиме на одном физическом устройстве
многоадресного ОУ реализуются несколько (4 на TX6/TE6, 31 на TA1-PCI-32RT) 
виртуальных ОУ (ВОУ) с разными адресами в канале. Если задать при конфигурации 
драйвера для какого-либо устройства режим МОУ, в списке устройств драйвера 
будет как это устройство с номером, заданным в реестре, так и дополнительно 
4 или 31 ВОУ с номерами, присвоенными самим драйвером.

    Для конфигурации плат TX6/TE6 в стандартном режиме или в режиме 4 ОУ 
предназначена программа m_TMK.exe.

    Для работы с МОУ введены новые функции:
TMK_DATA rtenable(TMK_DATA rtEnable);
int mrtgetmaxn();
DWORD mrtconfig(int mrtNumber);
int mrtselected();
TMK_DATA mrtgetstate();
void mrtdefbrcsubaddr0();
int mrtdefbrcpage(TMK_DATA mrtBrcPage);
TMK_DATA mrtgetbrcpage();
int mrtreset();

    Введена функция rtenable, основное назначение которой - включение или
выключение работы текущего ВОУ в МОУ. Однако с некоторыми ограничениями
этой функцией можно пользоваться и для обычных ОУ. Исключение составляют
ОУ на платах ТМК-400 и МТМК-400, которые не могут быть выключены этой
функцией. ОУ включается вызовом rtenable(RT_ENABLE), а выключается
вызовом rtenable(RT_DISABLE). Получить текущее состояние (RT_ENABLE или
RT_DISABLE) можно через вызов rtenable(RT_GET_ENABLE).

    Кроме того, изменен алгоритм работы функций rtreset и rtdefaddress для
всех ОУ. Если rtreset вызывается первый раз после tmkconfig или bcreset или
mtreset, то устройство переводится в режим ОУ, но остается выключенным как
после вызова rtenable(RT_DISABLE). Включается устройство только после
задания его адреса через rtdefaddress. Повторные вызовы rtreset не меняют
состояние включено/выключено.

    Функция mrtgetmaxn возвращает максимальный возможный номер МОУ. Этот
номер равен максимальному возможному номеру физического устройства в
драйвере. То есть для драйвера, предназначенного для работы с 8
устройствами (с 0 по 7) mrtgetmaxn возвратит 7. Функция tmkgetmaxn без
сконфигурированных в реестре МОУ работает также. При наличии МОУ драйвер
присвоит входящим в них ВОУ номера, начиная с 8, а tmkgetmaxn будет
возвращать максимальный присвоенный номер ВОУ. То есть, если будет
сконфигурировано одно МОУ с 4 ВОУ, то tmkgetmaxn вернет 11.

    Функция mrtconfig должна вызываться вместо tmkconfig для МОУ, если
программа пишется специально для работы с МОУ. Эта функция конфигурирует
само МОУ и все ВОУ, входящие в него, для работы с процессом, вызвавшим
mrtconfig. Функция mrtconfig возвращает двойное слово, младшие 16 бит
которого содержат начальный номер ВОУ, принадлежащих этому МОУ, а старшие
16 бит - число ВОУ, принадлежащих этому МОУ. При ошибке (например, если
заданный номер не является номером МОУ) функция вернет нулевое значение.

    Возможна работа с многоадресными ОУ двумя способами. Можно захватить
само МОУ и все входящие в него ВОУ вызовом mrtconfig. Другой способ - не
вызывать mrtconfig для МОУ, а вызывать tmkconfig для каждого конкретного
ВОУ. Необходимо помнить, что МОУ имеет некоторые общие для всех входящих
ВОУ ресурсы, например, арбитр доступа к подадресу БЗУ (используется в
функциях rtlock, rtunlock, rtbusy), биты управления режимами работы
(функции rtdefmode, rtgetmode, rtdefirqmode, rtgetirqmode), регистр
аппаратного сброса (функции rtreset, mrtreset). Если разные ВОУ захвачены
разными процессами через tmkconfig, то вызов этих функций для одного ВОУ,
будет влиять на работу остальных. Функция rtreset, если она вызвана для
ВОУ, выполнит полный аппаратный сброс МОУ только в том случае, если
захвачено только это ВОУ, а МОУ и остальные ВОУ не захвачены никаким
процессом. Функция mrtreset выполнит аппаратный сброс МОУ и всех входящих
в него ВОУ в любом случае.

    Захваченные через mrtconfig или tmkconfig МОУ и/или ВОУ выбираются
для работы, как и ранее, функцией tmkselect.

    Функция mrtselected позволяет узнать номер выбранного МОУ для
текущего выбранного ВОУ. Для обычных ОУ функции tmkselected и mrtselected
будут возвращать одно и то же значение. Для ВОУ tmkselected будет
возвращать номер ВОУ, а mrtselected - номер МОУ.

    Функция mrtreset выполняет аппаратный сброс и инициализацию МОУ и всех
входящих ВОУ.

    Для ВОУ и МОУ не могут вызываться функции bcreset и mtreset, поэтому
в универсальных программах, если они могут использоваться на компьютерах
с установленными МОУ, желательно проверять код возврата из этих функций.
Для обычных устройств код возврата bcreset будет нулевым. Для МОУ/ВОУ
bcreset вернет ненулевой код ошибки.

    Функция mrtgetstate позволяет прочитать регистр слова состояния МОУ
(см. техническое описание режима МОУ). Функция rtgetstate, используемая
для чтения регистра слова состояния обычных ОУ, для ВОУ прочитает
виртуальное слово состояния, формируемое самим драйвером.

    Функция mrtdefbrcsubaddr0 позволяет задать в TX6/TE6 в качестве текущего
подадреса МОУ или ВОУ с младшим номером подадрес, в который приходят
все групповые сообщения (см. техническое описание режима МОУ TX6/TE6). 
Необходимо помнить, что даже если ВОУ с младшим номером выключено, но 
включено какое либо другое в составе данного МОУ, то в этот подадрес будут 
поступать данные от сообщений с групповым адресом. По умолчанию, драйвер 
эмулирует прием групповых сообщений всеми ВОУ и автоматически переписывает 
данные принятых групповых сообщений в память каждого ВОУ, но такое поведение 
возможно только в том случае, если разрешены прерывания ВОУ по приему данных.

    Функция mrtdefbrcpage позволяет задать в TA1-PCI-32RT в качестве текущей 
страницы ВОУ страницу ОУ с групповым адресом, в которую приходят все групповые 
сообщения (см. техническое описание режима МОУ TA1-PCI32-RT). Снова обычную 
страницу памяти можно включить вызовом rtdefpage(0). По умолчанию, драйвер 
эмулирует прием групповых сообщений всеми ВОУ и автоматически переписывает 
данные принятых групповых сообщений в память каждого ВОУ, но такое поведение 
возможно только в том случае, если разрешены прерывания ВОУ по приему данных.

(c) ЗАО "Электронная компания ЭЛКУС", 1998,2011.
