Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Модемы и факс-модемы. Программирование для MS-DOS и Windows.

© Александр Фролов, Григорий Фролов
Том 16, М.: Диалог-МИФИ, 1993.

[Назад] [Содеожание] [Дальше]

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

Название FOSSIL является набором первых символов из названий нескольких коммуникационных программ - "Fido/Opus/SEAdog Standard Layer". Эти программы используют FOSSIL-драйверы для работы с асинхронным последовательным адаптером.

FOSSIL-драйверы используются для расширения функций BIOS, обслуживающих асинхронный последовательный адаптер и модем. Кроме того, FOSSIL-драйверы поддерживают несколько функций для работы с клавиатурой, видеоадаптером и системным таймером.

Использование FOSSIL-драйверов позволяет увеличить скорость обмена через последовательный адаптер до 38400 бит/с (функции BIOS допускают максимальную скорость только 9600 бит/с).

FOSSIL-драйвер самостоятельно обрабатывает прерывания от COM-портов. Он содержит два внутренних буфера, организованных в виде очереди.

В первый буфер - буфер передатчика - записываются данные, передаваемые компьютером модему. Драйвер самостоятельно определяет, когда асинхронный адаптер способен передать внешнему устройству очередной символ (т. е. когда свободен регистр данных COM-порта) и записывает его в регистр данных COM-порта. При этом переданный символ удаляется из буфера и происходит передача следующего символа.

Во второй буфер - буфер приемника - драйвер записывает данные, поступающие в компьютер через COM-порт. Затем содержимое этого буфера может быть считано программой при помощи специальной функции драйвера.

Примером такого FOSSIL-драйвера может служить драйвер Gwinn's Communications Controller, X00.SYS Version V1.30. Вы можете получить любые FOSSIL-драйверы и документацию на них практически на каждой станции BBS.

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

6.5.1. Взаимодействие программы с FOSSIL-драйвером

Интерфейс программ с FOSSIL-драйвером обеспечивается через прерывание INT_14h. При этом FOSSIL-драйвер подменяет встроенный обработчик прерывания INT 14h. FOSSIL-драйвер программирует асинхронный адаптер непосредственно через обращение к его регистрам.

Ниже мы приводим описание наиболее важных функций FOSSIL-драйверов пятого уровня.

Установка скорости передачи данных

Первая функция предназначена для инициализации портов асинхронного адаптера. Она задает формат и скорость передачи данных:

На входе:	AH = 00h;

	DX = номер порта:		0 - COM1, 1 - COM2, 
										2 - COM3, 3 - COM4 и т. д.;

	AL = параметры инициализации (см. ниже).

На выходе: AX = состояние порта асинхронного адаптера,
		(см. функцию 03h).

При вызове этой функции регистр AL должен содержать параметры инициализации (x - состояние бита безразлично):

БитыСмысл
D1 D0Длина слова в битах:

00 - 5 бит;

01 - 6 бит;

10 - 7 бит;

11 - 8 бит

D2Количество стоповых бит:

0 - 1 бит;

1 - 2 бита

D4 D3Четность:

x0 - контроль на четность не используется;

01 - контроль на нечетность;

11 - контроль на четность

D7-D5Скорость передачи данных:

000 - 19200 бит/с

001 - 38400 бит/с

010 - 300 бит/с

011 - 600 бит/с

100 - 1200 бит/с

101 - 2400 бит/с

110 - 4800 бит/с

111 - 9600 бит/с

Обратите внимание, что в отличие от функции BIOS, при задании скорости обмена (регистр AL биты D7, D6, D5) скорости в 110 и 150 бит/с заменены на 19200 и 38400 бит/с.

Передача символа с ожиданием

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

На входе:	AH = 01h;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.;

	AL = передаваемый байт.

На выходе: AX = состояние порта асинхронного адаптера
		(см. функцию 03h).

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

Прием символа с ожиданием

Функция 02h предназначена для чтения очередного символа из буфера приемника драйвера.

На входе:	AH = 02h;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.

На выходе:	AL = принятый байт;

	AH = 0.

Если буфер приемника пуст, функция ожидает поступления очередного байта из COM-порта.

Определение состояния драйвера

Состояние порта асинхронного адаптера можно узнать с помощью функции 03h:

На входе:	AH = 03h;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.

На выходе: AH = состояние буферов драйвера;

		D0 - принятые драйвером символы доступны
				 для чтения;

		D1 - приемный буфер драйвера переполнен, 
			   все символы, полученные после
			   переполнения буфера, будут потеряны;

		D5 - в буфере передатчика есть свободное
			   место;

		D6 - буфер передатчика пуст;

	AL = состояние линии DCD;

		D3 = 1;

		D7 - состояние сигнала DCD.

Инициализация FOSSIL-драйвера (COM-порта)

Данная функция используется для инициализации FOSSIL-драйвера. Эта функция должна быть вызвана перед вызовом других функций драйвера.

На входе:	AH = 04h;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.;

	если BX = 4F50h
		ES:CX - указатель на флаг .

На выходе: AX = 1954h;

	BL = максимальный номер функции (регистр AH при
		вызове прерывания INT 14h), поддерживаемой
		данным драйвером, не считая функций с
		номерами, большими 7Dh;

	BH = уровень драйвера.

Если при вызове данной функции регистр BX равен 4F50h, то регистры ES:CX указывают на однобайтный счетчик, содержимое которого увеличивается при нажатии комбинации клавиш .

При инициализации драйвера происходит установка сигнала DTR. Для сброса драйвера (очистки буферов, сброса флага управления потока и т. д.) необходимо вызвать эту функцию второй раз. Данную функцию можно использовать для проверки, установлен ли FOSSIL-драйвер.

Деинициализация драйвера

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

На входе:	AH = 05h;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.

На выходе: не используется.

6.5.2. Управление линией DTR

Функция 06h используется для управления линией DTR. Заметим, что на состояние линии DTR кроме этой функции влияет только функция инициализации FOSSIL-драйвера.

На входе:	AH = 06h;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.;

	AL = состояние линии DTR:
		01h - установить сигнал DTR;
		00h - сбросить сигнал DTR.

На выходе: не используется.

Определение параметров системного таймера

Данная функция используется для определения параметров системного таймера

На входе:	AH = 07h.

На выходе: AL = номер прерывания от системного таймера;

	AH = количество прерываний от системного
		таймера на секунду;
	
	DX = интервал между прерываниями от системного
		таймера, определяется в миллисекундах.

Передача данных

Данная функция используется для ускорения процесса передачи в COM-порт данных из буфера передатчика драйвера. Функция не возвращает управление до тех пор, пока буфер передатчика не станет пустым.

На входе:	AH = 08h;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.

На выходе: не используется.

Сброс буфера передатчика

Функция используется для очистки буфера передатчика. Все данные, находящиеся на момент вызова функции в буфере, пропадают и в COM-порт не передаются.

На входе:	AH = 09h;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.

На выходе: не используется.

Сброс буфера приемника

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

На входе:	AH = 0Ah;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.

На выходе:	не используется.

Передача символа без ожидания

Если в буфере передатчика есть свободное место, то функция записывает передаваемый байт в буфер и возвращает в регистре AX значение 01h. Если в буфере передатчика нет свободного места, функция записывает передаваемый байт в буфер и возвращает в регистре AX значение 00h.

На входе:	AH = 0Bh;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.;

	AL = передаваемый байт.

На выходе:		AX = 0001h - символ размещен в буфере
						передатчика;

	AX = 0000h - символ не размещен в буфере
				передатчика.

Чтение символа из буфера без удаления

Функция 0Ch предназначена для чтения очередного символа из буфера приемника драйвера. При этом прочитанный символ из буфера не удаляется.

На входе:	AH = 0Ch;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.

На выходе:	если AH = 0, то регистр AL содержит принятый
					байт;

	если AX = 0FFFFh, то буфер приемника пуст.

Если буфер приемника пуст, функция ожидает поступления очередного байта из COM-порта.

Чтение символа из буфера клавиатуры

Данная функция обеспечивает ввод с клавиатуры без ожидания. Если буфер клавиатуры пуст - функция возвращает в регистре AX значение 0FFFFh. В противном случае скан-код очередного символа, прочитанный из буфера клавиатуры, помещается в регистр AH. Заметим, что функция не удаляет код прочитанного ей символа из буфера клавиатуры.

На входе:	AH = 0Dh.

На выходе:	AX = 0FFFFh - буфер клавиатуры пуст;

	AX = скан-код нажатой клавиши.

Чтение символа из буфера клавиатуры с ожиданием

Функция 0Eh производит чтение кода очередного символа из буфера клавиатуры. Если буфер клавиатуры пуст, функция переходит в режим ожидания до тех пор, пока не будет нажата какая-нибудь клавиша.

На входе:	AH = 0Eh.

На выходе:	AX = скан-код нажатой клавиши.

Управление потоком

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

На входе:	AH = 0Fh;

	AL = способ управления потоком:

  D0		Использование для управления передачей символов XON/XOFF
  
  D1		Использование для управления потоком сигналов CTS/RTS
  
  D2		Зарезервирован
  
  D3		Использование для управления приемом символов XON/XOFF
  
  D7-D4	Зарезервированы

	DX = номер порта:		0 - COM1, 1 - COM2, 
										2 - COM3, 3 - COM4 и т. д.

На выходе:	не используется.

Вы можете выбрать тот или иной метод управления потоком, установив соответствующий бит регистра AL:

D0 - Использование для управления передачей символов XON(Ctrl-C)/XOFF(Ctrl-K). При установке данного бита FOSSIL-драйвер будет приостанавливать дальнейшую передачу данных удаленному модему при получении символа XOFF. Для возобновления передачи необходимо передать драйверу символ XON.

D1 - Использование для управления потоком сигналов CTS/RTS. При установке данного бита FOSSIL-драйвер будет приостанавливать дальнейшую передачу данных удаленному модему, если сигнал CTS переходит в неактивное состояние. Для возобновления передачи необходимо перевести линию CTS в активное состояние. FOSSIL-драйвер будет также переключать линию RTS в неактивное состояние, когда буфер приемника будет заполнен на определенную величину.

D3 - Использование символов XON/XOFF для управления приемом данных. При установке данного бита FOSSIL-драйвер будет передавать удаленному модему символ XOFF, когда буфер приемника драйвера заполнится на определенную величину. Когда программа считает символы из буфера приемника, удаленному модему будет передан символ XON, сигнализирующий, что передачу можно продолжить.

Дополнительная функция для управления потоком

На входе:	AH = 10h;

	AL = способ управления потоком:

		D0 - Если данный бит равен единице, то
			полученные через COM-порт символы
			Ctrl-C/K не записываются в буфер
			приемника, а устанавливают внутренний
			флаг. Следующий вызов функции будет
			возвращать в регистре AX значение
			этого флага.

		D1 - Если данный бит равен единице,
			процесс передачи данных драйвером
			останавливается. Если D1 равен нулю,
			передача возобновляется.

	DX = номер порта:	0 - COM1, 1 - COM2, 2 - COM3,
					3 - COM4 и т. д.

На выходе:	AX = 01h - были получены символы Ctrl-C/K;
	AX = 01h - символы Ctrl-C/K не были получены.

Установить положение курсора

Функция используется для установки курсора в заданное положение экрана. Новое положение курсора определяется регистром DX.

На входе:	AH = 11h;

	DL = номер столбца;

	DH = номер строки.

На выходе:	не используется.

Заметим, что данная функция аналогична функции 02h прерывания INT 10h.

Определение текущего положения курсора

Функция используется для определения текущего положения курсора на экране.

На входе:	AH = 12h.

На выходе:	DL = номер столбца;

	DH = номер строки.

Данная функция аналогична функции 03h прерывания INT_10h.

Вывод символа на экран

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

На входе:	AH = 13h;

	AL = код отображаемого символа.

На выходе:	не используется.

Отслеживание сигнала DCD

Если производится отслеживание сигнала DCD и сигнал DCD становится неактивным, то FOSSIL-драйвер производит перезагрузку системы.

На входе:	AH = 14h;

	DX = номер порта:	0 - COM1, 1 - COM2, 2 - COM3,
					3 - COM4 и т. д.;

	AL = 01h - производится отслеживание сигнала DCD;

	AL = 00h - отслеживание сигнала DCD не производится.

На выходе:	не используется.

Вывод символа на экран

Эта функция производит вывод символа на экран дисплея. Для вывода на экран символа данная функция использует процедуры BIOS.

На входе:	AH = 15h;

	AL = код отображаемого символа.

На выходе:	не используется.

Установка и удаление функций, вызываемых по таймеру

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

На входе:	AH = 16h;

	AL = 01h - добавить функцию;
	AL = 00h - удалить функцию;

	ES:DX - адрес функции.

На выходе:	AX = 00000h - операция выполнена успешно;
	AX = 0FFFFh - произошла ошибка.

Перезагрузка системы

Производит перезагрузку системы.

На входе: AH = 17h.

Чтение блока данных из буфера драйвера

Позволяет за один вызов функции считать сразу несколько байт из приемного буфера драйвера в буфер программы.

На входе:	AH = 18h;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.;

	CX = максимальное количество считываемых символов;

	ES:DI - адрес буфера, в который помещаются
			считанные символы.

На выходе:	AX = количество считанных символов.

Запись блока данных в буфер драйвера

Позволяет за один вызов функции записать несколько байт из буфера программы в буфер передатчика драйвера.

На входе:	AH = 19h;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.;

	CX = максимальное количество считываемых символов;

	ES:DI - адрес буфера, в который помещаются
			считанные символы.

На выходе:	AX = количество записанных символов.

Передача сигнала BREAK

Используя данную функцию, можно перевести телефонную линию в состояние BREAK.

На входе:	AH = 1Ah;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.;

	AX = 01h - начало передачи сигнала BREAK;
	AX = 00h - конец передачи сигнала BREAK.

На выходе:	не используется.

Получение информации о драйвере

С помощью данной функции вы можете получить информацию о FOSSIL-драйвере.

На входе:	AH = 1Bh;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4 и т. д.;

	ES:DI - адрес буфера, в который помещается
			информация о драйвере;

	CX = размер буфера в байтах;

На выходе:	AX = количество байтов, записанных в буфер.

Функция производит запись информации о FOSSIL-драйвере в буфер программы. Формат буфера представлен ниже:

СмещениеРазмерСмысл
0СловоРазмер заполненной части буфера (размер этой таблицы в байтах - 13h)
2БайтНомер версии драйвера
3БайтУровень драйвера
4Двойное словоУказатель на символьную строку с идентификатором драйвера
8СловоРазмер буфера приемника
0AhСловоКоличество свободных байт в буфере приемника
0ChСловоРазмер буфера передатчика
0EhСловоКоличество свободных байт в буфере передатчика
10hБайтШирина экрана в символах
11hБайтВысота экрана в символах
12hБайтСкорость обмена данными (см. функцию установки скорости передачи данных, регистр AL)

Установка внешней функции обработчика

Данная функция позволяет установить внешние (по отношению к FOSSIL-драйверу) функции. Номер устанавливаемой функции может быть от 80h до 0BFh. После успешной установки функции она может быть вызвана как соответствующая функция прерывания INT 14h.

На входе:	AH = 7Eh;

	AL = номер устанавливаемой функции (80h-0BFh);

	ES:DX - адрес точки входа функции.

На выходе:	AX = 1954h;

	BL = номер, присвоенный функции, соответствует
		регистру AL;

	BH = 01h - установка функции прошла успешно;
	BH = 00h - произошла ошибка.

Отключение внешней функции обработчика

Функция 7Fh используется для отключения внешней функции, установленной при помощи функции 7Eh.

На входе:	AH = 7Fh;

	AL = номер, присваиваемый функции;

	ES:DX - адрес точки входа функции.

На выходе:	AX = 1954h;

	BL = номер, присвоенный функции;

	BH = 01h - удаление функции прошло успешно;
	BH = 00h - произошла ошибка.

6.5.3. FOSSIL-драйвер и эмуляция протокола MNP

Кроме буферизации передаваемых и принимаемых данных некоторые FOSSIL-драйверы выполняют еще одну функцию. При работе с модемами, не реализующими протокол аппаратной коррекции ошибок, они обеспечивают программную эмуляцию протокола MNP.

Примером таких драйверов могут служить FOSSIL-драйверы MX5 Version 1.02 - MNP Level 5 Driver и MNP Version 1.27 - MNP Level 5 Driver.

Для управления эмулятором MNP FOSSIL-драйверы, реализующие программную эмуляцию, поддерживают дополнительную функцию номер 0E0h прерывания INT 14h. Ниже мы приведем краткое описание подфункций данной функции.

Определить состояние эмулятора MNP

На входе:	AH = 0E0h;

	AL = 00h;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4.

На выходе:	ES:BX - указатель на структуру, содержащую
			информацию о текущем состоянии
			эмулятора MNP. 

При помощи данной подфункции можно определить состояние эмулятора MNP. Подфункция возвращает в регистрах ES:BX указатель на следующую структуру:

СмещениеРазмерСмысл
0БайтЕсли байт содержит 0 - эмуляция MNP включена, 1 - эмуляция MNP отключена
1БайтУровень эмулируемого протокола MNP (2, 4, 5)
2БайтСерийный номер MNP удаленного модема
3СловоОбщее число переданных пакетов
5СловоЧисло повторно переданных пакетов
7СловоМаксимальная скорость передачи
9СловоОбщее число принятых пакетов
11СловоЧисло повторно принятых пакетов
13СловоМаксимальная скорость приема

Управление уровнем протокола MNP

На входе:	AH = 0E0h;

	AL = 01h;

	BH = 00h - определить текущий уровень MNP;
	   = 01h - установить уровень MNP;

	BL - Уровень протокола MNP;
	   = 02h - уровень MNP2,
	   = 04h - уровень MNP4,
	   = 05h - уровень MNP5 (устанавливается по
	           умолчанию);

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4.

На выходе:	BL = уровень эмулируемого протокола MNP.

Управление режимом работы эмулятора

Эмулятор MNP может работать в двух режимах - режиме вызова удаленного модема и режиме ответа на вызов от удаленного модема. Данная подфункция позволяет определить текущий и установить нужный режим работы эмулятора.

На входе:	AH = 0E0h;

	AL = 02h;

	BH = 00h - определить текущий режим;
	   = 01h - установить режим;

	BL = 00h - режим вызова (устанавливается по
	           умолчанию),
	   = 01h - режим ответа;

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4.

На выходе:	BL = текущий режим эмулятора.

Ожидание соединения

Данная подфункция используется для определения и задания времени после установления соединения, в течение которого драйвер пытается установить с удаленным модемом связь с использованием MNP. Время задается в 1/55 долях миллисекунды или, другими словами, количеством прерываний от системного таймера, которые должны произойти за данный промежуток времени.

На входе:	AH = 0E0h;

	AL = 03h;

	BH = 00h - определить интервал времени;
	   = 01h - установить интервал времени;

	BL = интервал времени в 1/55 долях миллисекунды
		(по умолчанию устанавливается 14);

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4.

На выходе:	BL = интервал времени.

Управление звуком

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

На входе:	AH = 0E0h;

	AL = 04h;

	BH = 00h - определить звуковой режим,
	   = 01h - установить звуковой режим;

	BL = 00h - звук не включен,
	   = 01h - звук включен (устанавливается по умолчанию);

	DX = номер порта:		0 - COM1, 1 - COM2, 2 - COM3,
										3 - COM4.

На выходе:	BL = текущий звуковой режим.

Удалить FOSSIL-драйвер из памяти

Данную подфункцию можно использовать для удаления FOSSIL-драйвера из оперативной памяти компьютера. При этом драйвер освобождает телефонную линию, восстанавливает все перехваченные им векторы прерываний и возвращает адрес своего блока MCB. Далее вы можете воспользоваться функцией 49h прерывания INT 21h для освобождения этого MCB.

На входе:	AH = 0E0h;

	AL = 05h.

На выходе:	BX = адрес MCB или 0 в случае ошибки.

Приведем пример программы UNINST, удаляющей FOSSIL-драйвер из памяти. Исходный текст этой программы представлен в листинге 6.16.

Листинг 6.16. Файл UNINST.C

int uninstall(void);

//********************************************************
// Функция main
//********************************************************
void main(void) {

	int	ok;

	ok = uninstall();
	printf("Удаление FOSSIL-драйвера из памяти %s.", 
			(ok) ? "прошло успешно" : "невозможно" );
}

//********************************************************
// Функция uninstall
//********************************************************
int uninstall(void) {

	int	ok = 0;

	asm {

		// Определяем адрес MCB блока драйвера
		mov	ax,0E005h
		int	14h

		// В случае ошибки возвращаем управление
		cmp	bx,0
		je		no_uninstall

		// es = bx
		push	bx
		pop	es

		// Освобождаем MCB блок, используемый драйвером
		mov	ah,49h
		int	21h
		mov	ok,1
	}

	no_uninstall:

	return(ok);
}

Определение номера версии эмулятора MNP

На входе:	AH = 0E0h;

	AL = 06h;

	BX = 00h.

На выходе:	BX = 4D58h;

	AH = старшая часть номера версии эмулятора;

	AL = младшая часть номера версии.

Временная задержка

Данная подфункция позволяет выполнить временную задержку. Время задержки определяется количеством прерываний от системного таймера, которые должны произойти во время задержки.

На входе:	AH = 0E0h;

	AL = 07h;

	СX = время задержки.

На выходе:	не используется.

6.5.4. Коммуникационная программа

Ниже представлен исходный текст небольшой коммуникационной программы FOSSILEX, использующей для работы с модемом FOSSIL-драйвер.

При запуске программа проверяет наличие FOSSIL-драйвера и, если он не установлен, сообщает об этом и завершает свою работу.

Если FOSSIL-драйвер установлен, программа инициализирует его и устанавливает скорость обмена 2400 бит/с. Затем программа проверяет, поддерживает ли установленный FOSSIL-драйвер эмуляцию протокола MNP, и выводит на экран соответствующее сообщение.

Затем начинает выполняться цикл, в котором программа отображает принятые от модема данные на экране и посылает модему ASCII-коды символов, набранных на клавиатуре.

Если FOSSIL-драйвер поддерживает эмуляцию протокола MNP, то, нажав клавиши PageUp или PageDown, можно переключить эмулятор MNP либо в режим вызова удаленного модема, либо в режим ответа на вызов удаленного модема.

Исходный текст программы представлен в листинге 6.17.

Листинг 6.17. Файл FOSSILEX.C

#include 
#include 

void  do_chat(void);
void  help(void);
void  origin(void);
void  answer(void);

unsigned com_port_num;
unsigned char  mnp = 0;

//********************************************************
// Функция main
//********************************************************
void main( int argc, char *argv[] ) {

	unsigned key, f_num, doc = 0,
				signatura;

	printf("\n(С) Frolov G.V. Коммуникационная программа, "
		  "использующая FOSSIL-драйвер\n");

	// Параметр программы должен содержать номер
	// используемого COM-порта
	if( argc < 2 ) help();
	com_port_num = ( unsigned ) atoi( argv[1] );

	// Инициализируем FOSSIL-драйвер
	_asm {
		mov   ah,4h
		mov   dx,com_port_num
		int   14h
		mov   key,ax
		mov   f_num,bl
		mov   doc,bh
	}

	// Если FOSSIL-драйвер не установлен завершаем программу
	if( key != 0x1954 ) {
		printf("\nFOSSIL-драйвер неустановлен\n");
		exit(-1);
	}

	// Определяем возможность эмуляции FOSSIL-драйвером
	// протокола MNP
	_asm {
		mov   ah,0E0h
		mov   al,6h
		xor   bx,bx
		int   14h
		mov   signatura,bx
	}

	mnp = ( signatura != 0x4D58 ) ? 0 : 1;

	printf("Эмуляция MNP %s.\n\n", (mnp) ? "поддерживается"
								  : "не поддерживается");

	if(mnp)
		printf("PageUp - режим вызова, "
						"PageDown - режим ответа\n\n");

	_asm {

		// Устанавливаем скорость обмена и формат данных
		xor   ah,ah
		mov   al,0A3h
		mov   dx,com_port_num
		int   14h

		// Устанавливаем сигнал DTR в активное состояние
		mov   ah,6
		mov   al,1
		mov   dx,com_port_num
		int   14h

		// Запрещаем использование режима управления потоком
		mov   ah,0Fh
		xor   al,al
		mov   dx,com_port_num
		int   14h
	}

	// Начинаем обмен данными между компьютером и модемом
	do_chat();
}

//********************************************************
// Функция do_chat
//********************************************************
void do_chat( void ) {

	while(1) {

		unsigned char key,stey;
		unsigned i,j;

		// Если пользователь нажал на клавиатуру, получаем код
		// нажатого символа и передаем его модему
		if( kbhit() ) {
			key =  getch();

			if(( key == 0 ) && mnp) {
				key =  getch();
				if( key == 73 )      origin();
				else if( key == 81 ) answer();
				continue;
			}

			// По нажатию клавиши Esc выходим из программы
			if( key == 27 ) {

				_asm {

					// Сбрасываем сигнал DTR
					mov   ah,06h
					xor   al,al
					mov   dx,com_port_num
					int   14h

					// Отключаем FOSSIL-драйвер
					mov   ah,05h
					mov   dx,com_port_num
					int   14h
				}

				return;
			}

			// Если нажата клавиша Enter переводим строку
			if( key == '\r' ) {
				key = 13;
				putch('\n');
			}

			// Выводим ASCII код нажатого на клавиатуре символа
			// на экран
			putch(key);

			// Передаем ASCII код нажатого на клавиатуре символа
			// FOSSIL-драйверу, для дальнейшей передачи его модему
			_asm {
				mov   dx,com_port_num
				mov   ah,1
				mov   al,key
				int   14h
			}
		}

		// Определяем состояние приемного буфера FOSSIL-драйвера
		_asm {
			mov   dx,com_port_num
			mov   ah,3
			int   14h
			and   ah,01h
			mov   stey,ah
		}

		// Если приемный буфер содержит данные, выводим их
		// на экран дисплея
		if( stey > 0 ) {
			_asm {
				mov   dx,com_port_num
				mov   ah,2
				int   14h
				mov   stey,al
			}
			putch(stey);
		}
	}
}

//********************************************************
// Функция help
//********************************************************
void help( void ) {

	printf("Неправильно задан параметр программы \n"
			 "FOSSILEX n, где n - номер порта от 0 до 3\n");
	exit(0);
}

//********************************************************
// Функция origin
//********************************************************
void  origin(void) {

	// Переключаем эмулятор MNP в режим вызова удаленного модема
	_asm {
		mov   ah,0E0h
		mov   al, 2
		mov   bl,0
		mov   bh,1
		mov   dx,com_port_num
		int   14h
	}
	putch(7);
}

//********************************************************
// Функция answer
//********************************************************
void  answer(void){

	// Переключаем эмулятор MNP в режим ответа на
	// вызов удаленного модема

	_asm {
		mov   ah,0E0h
		mov   al,2
		mov   bl,1
		mov   bh,1
		mov   dx,com_port_num
		int   14h
	}
	putch(7);
	putch(7);
}
[Назад] [Содеожание] [Дальше]