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

Операционная система MS-DOS

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

[Назад] [Содеожание]

6.6. Функции управления устройствами ввода/вывода IOCTL

В этом разделе мы рассмотрим средства управления устройствами ввода/вывода IOCTL (сокращение от Input/Output Control). Использование IOCTL - обычный метод организации связи с устройствами или получения информации об открытых файлах.

Описания будут приводиться в порядке номеров подфункций функции 44h прерывания 21h.

Для версии DOS 2.1 и более поздних версий поддерживаются подфункции с номерами от 0 до 7, для версии 3.0 дополнительно могут использоваться подфункции 8, 0Bh, для 3.1 - 9 и 0Ah, для 3.2 и более поздних версий добавляются подфункции 0Dh, 0Eh, 0Fh. Версия DOS 3.3 и более поздние версии поддерживают также подфункцию 0Ch.

00h Получить информацию об устройстве

01h Установить информацию об устройстве

02h/03h Чтение/запись управляющей информации для символьных устройств

04h/05h Чтение/запись управляющей информации для блочных устройств

06h/07h Получить состояние ввода/вывода

08h Проверить возможность замены носителя данных для блочного устройства

09h Локальное или удаленное устройство

0Ah Проверить индекс на локальный/удаленный

0Bh Установка количества повторов при обращении к файлу

0Ch Переключение кодовых страниц

0Dh Общее управление вводом/выводом (GENERIC IOCTL)

0Eh Получение информации о логическом дисководе

0Fh Установка текущего логического дисковода

# 00h Получить информацию об устройстве

Вызов:

Регистр Содержание
AH 44h
AL 00h
BX Индекс устройства (handle). Значение, которое операционная система возвращает при открытии файла или устройства и которое она затем использует для доступа к открытому файлу или устройству.

Возврат без ошибки:

Регистр Содержание
CF 0
DX Информация об устройстве

Возврат с ошибкой:

Регистр Содержание
CF 1
AX 01h - запрошена несуществующая функция;

06h - BX содержит несуществующий или неоткрытый handle.

Функция возвращает в регистре DX информацию об устройстве, которая имеет следующий формат (для устройства):

Бит Значение
0 Это устройство является стандартным устройством ввода.
1 Стандартное устройство вывода.
2 NUL-устройство.
3 Часы.
4 Специальное устройство.
5 1 - двоичный режим работы;

0 - режим ASCII.

6 0 - при чтении достигнут конец файла.
7 1 - это слово информации относится к устройству (данный handle относится к устройству);

0 - слово информации относится к файлу.

8-10 Зарезервировано.
11 1 - Устройство поддерживает команды открытия/закрытия.
12 Сетевое устройство (только для DOS версии 3.0 и более поздних версий).
13 Устройство поддерживает вывод до состояния занятости.
14 Устройство может обрабатывать управляющие строки IOCTL, посылаемые подфункциями 2, 3, 4, 5 функции 44h. Этот бит может быть только прочитан, его установка подфункцией 1 функции 44h не производится.
15 Зарезервировано.

Если при вызове этой подфункции регистр BX содержал индекс файла, формат получаемой в регистре DX информации будет следующий:

Бит Значение
0-5 Номер дисковода (0-А:, 1-В: и т.д.).
6 0 - Была запись в выходной файл.
7 1 - это слово информации относится к устройству (данный handle относится к устройству);

0 - слово информации относится к файлу.

8-11 Зарезервировано.
12 Сетевое устройство (только для DOS версии 3.0 и более поздних версий).
13-14 Зарезервировано.
15 1 - Данный файл является удаленным при работе в сети (только для DOS версии 3.0 и более поздних версий).

Особое внимание следует обратить на бит 5 слова информации об устройстве. Этот бит определяет режим обмена данными DOS и драйвера - двоичный или ASCII. В двоичном режиме управляющие символы CTRL-C, CTRL-P, CTRL-S, CTRL-Z интерпретируются как обычные данные.

# 01h Установить информацию об устройстве

Вызов:

Регистр Содержание
AH 44h
AL 01h
BX Индекс файла (handle)
DH 0
DL Устанавливаемая информация (биты 0-7 слова информации об устройстве, описанного выше)

Возврат без ошибки:

Регистр Содержание
CF 0

Возврат с ошибкой:

Регистр Содержание
CF 1
AX 01h - запрошена несуществующая функция;

06h - BX содержит несуществующий handle.

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

В зависимости от установки бита 5 (двоичный/ASCII) драйвер по-разному выполняет команды ввода-вывода.

В режиме ASCII обмен с драйвером символьного устройства выполняется по байтам (содержимое поля count в запросе всегда равно 1). Если Вам надо обслуживать быстродействующее устройство ввода/вывода, такой посимвольный обмен может оказаться слишком медленным. В этом случае Вы можете установить бит 5 в единицу и выполнять обмен в двоичном режиме. Разумеется, Вам придется самостоятельно отслеживать управляющие символы.

Ниже мы приведем пример программы, которая сначала устанавливает ASCII-режим для драйвера, описанного выше, выводит на него 8 символов, затем выполняет аналогичную операцию в двоичном режиме. Драйвер при каждом обращении к нему для ввода или вывода выдает сообщение на экран. Запустив программу (и не забыв подключить драйвер), Вы увидите, что в ASCII-режиме для записи или чтения восьми символов драйвер вызывается восемь раз, а в двоичном режиме - только один раз.

#include <io.h>
#include <conio.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <malloc.h>
#include <errno.h>
#include <dos.h>

int main(void);

union REGS inregs, outregs;
struct SREGS segregs;

int main(void) {

    char buf[100];
         int io_handle;
         unsigned count;

         // Открываем устройство с именем IODRIVER

         if( (io_handle = open("IODRIVER", O_RDWR)) == - 1 ) {

                // Если открыть не удалось, выводим
                // код ошибки

                printf("Ошибка при открытии устройства %d",errno);
                return errno;
         }


         // Читаем 8 байт из устройства в буфер buf

         if( (count = read(io_handle, buf, 8)) == -1 ) {

                 // Если при чтении произошла ошибка,
                 // выводим ее код

                 printf("Ошибка чтения %d",errno);
                 return errno;
        }

        // Закрываем прочитанную строку нулем
        // для последующего вывода функцией printf

        buf[8]=0;

        printf("\n___ Введена строка: %s ___",buf);

        // Выводим только что прочитанные данные
        // обратно на то же устройство

        if( (count = write(io_handle, buf, 8)) == -1 ) {

                 // Если при записи произошла ошибка,
                 // выводим ее код

                 printf("Ошибка записи %d",errno);
                 return errno;
        }

        // Получаем информацию об устройстве

        inregs.h.ah = 0x44;
        inregs.h.al = 0;
        inregs.x.bx = io_handle;
        intdos( &inregs, &outregs );
        if(outregs.x.cflag == 1) {

                // При ошибке выводим ее код

                printf("IOCTL error %x\n",&outregs.x.ax);
                exit(-1);
        }

        // Выводим слово информации об устройстве на экран

        printf("\nDevice Information:  %04X\n", outregs.x.dx);

        // Устанавливаем в 1 бит 5 (переключаем драйвер
        // в двоичный режим обмена данными

        inregs.x.dx = (outregs.x.dx | 0x0020) & 0x00ff;

        // Устанавливаем слово информации об устройстве

        inregs.h.ah = 0x44;
        inregs.h.al = 1;
        inregs.x.bx = io_handle;
        intdos( &inregs, &outregs );
        if(outregs.x.cflag == 1) {

                // При ошибке выводим код ошибки

                printf("IOCTL error %x\n",&outregs.x.ax);
                exit(-1);
        }

        // Выводим слово информации об устройстве на экран

        printf("\nDevice Information:  %04X\n", outregs.x.dx);


         // Читаем 8 байт из устройства в буфер buf
         // Обмен теперь производится в двоичном режиме

         if( (count = read(io_handle, buf, 8)) == -1 ) {

                 // Если при чтении произошла ошибка,
                 // выводим ее код

                 printf("Ошибка чтения %d",errno);
            return errno;
        }

        // Закрываем прочитанную строку нулем
        // для последующего вывода функцией printf

        buf[8]=0;

        printf("\n___ Введена строка: %s ___",buf);

        // Выводим только что прочитанные данные
        // обратно на то же устройство

        if( (count = write(io_handle, buf, 8)) == -1 ) {

                 // Если при записи произошла ошибка,
                 // выводим ее код

                 printf("Ошибка записи %d",errno);
            return errno;
        }

        // Закрываем устройство

        close(io_handle);

        exit(0);
}

# 02h/03h Чтение/запись управляющей информации для символьных устройств

Вызов:

Регистр Содержание
AH 44h
AL 02h/03h
BX Индекс (только для устройства, а не для файла)
CX Количество читаемых/записываемых байтов
DS:DX Указатель на буфер, в который надо прочитать управляющую информацию или из которого надо записать управляющую информацию

Возврат без ошибки:

Регистр Содержание
CF 0
AX Количество действительно прочитанных/записанных байтов

Возврат с ошибкой:

Регистр Содержание
CF 1
AX 01h - запрошена несуществующая функция;

06h - BX содержит несуществующий индекс (handle).

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

Для использования этих подфункций драйвер должен поддерживать интерфейс IOCTL. Для проверки можно использвать подфункцию 0 (чтение информации устройства). Если бит 14 установлен, драйвер поддерживает IOCTL.

# 04h/05h Чтение/запись управляющей информации для блочных устройств

Вызов:

Регистр Содержание
AH 44h
AL 04h/05h
BL Номер дисковода (0 - текущий дисковод, 1 - дисковод А: и т.д.)
CX Количество читаемых/записываемых байтов
DS:DX Указатель на буфер, в который надо прочитать управляющую информацию или из которого надо записать управляющую информацию

Возврат без ошибки:

Регистр Содержание
CF 0
AX Количество действительно прочитанных/записанных байтов

Возврат с ошибкой:

Регистр Содержание
CF 1
AX 01h - запрошена несуществующая функция;

05h - доступ к дисководу запрещен.

Для использования этих подфункций драйвер должен поддерживать интерфейс IOCTL. Для проверки можно использовать подфункцию 0 (чтение информации устройства). Если бит 14 установлен, драйвер поддерживает IOCTL.

# 06h/07h Получить состояние ввода/вывода

Вызов:

Регистр Содержание
AH 44h
AL 06h/07h
BX Индекс (устройства или файла)

Возврат без ошибки:

Регистр Содержание
CF 0
AL Для устройства:

00h - устройство не готово к приему/передаче;

0FFh - устройство готово к приему/передаче.

Для файла:

00h - достигнут конец файла;

0FFh - конец файла не достигнут.

Возврат с ошибкой:

Регистр Содержание
CF 1
AX 01h - запрошена несуществующая функция;

05h - доступ к дисководу запрещен;

06h - BX содержит несуществующий индекс;

0Dh - неправильные данные.

Эти подфункции предназначены для проверки готовности устройства к вводу/выводу данных или для проверки на достижение конца файла.

# 08h Проверить возможность замены носителя данных для блочного устройства

Вызов:

Регистр Содержание
AH 44h
AL 08h
BL Номер дисковода (0 - текущий дисковод, 1 - дисковод А: и т.д.)

Возврат без ошибки:

Регистр Содержание
CF 0
AX 00h - замена носителя возможна;

01h - носитель данных несменный

Возврат с ошибкой:

Регистр Содержание
CF 1
AX 01h - запрошена несуществующая функция;

0Fh - неправильный идентификатор дисковода

Эта подфункция проверяет возможность замены носителя данных. Дискета - заменяемый носитель данных, а жесткий диск или электронный (RAM) диск - нет.

# 09h Получить информацию о том, является ли устройство локальным или удаленным (при работе в сети)

Вызов:

Регистр Содержание
AH 44h
AL 09h
BL Номер дисковода (0 - текущий дисковод, 1 - дисковод А: и т.д.)

Возврат без ошибки:

Регистр Содержание
CF 0
DX Биты атрибута устройства. Если блочное устройство является локальным (расположено на рабочей станции сети Microsoft Networks), бит 12 установлен в 0, остальные биты копируются из заголовка драйвера устройства. Если устройство является удаленным (находится на сервере), устанавливается в 1 только бит 12, остальные биты зарезервированы и равны нулю.

Возврат с ошибкой:

Регистр Содержание
CF 1
AX 01h - запрошена несуществующая функция;

0Fh - неправильный идентификатор дисковода;

Ошибка 01h может возникнуть, если не загружена команда SHARE.

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

# 0Ah Проверить индекс на локальный/удаленный

Вызов:

Регистр Содержание
AH 44h
AL 0Ah
BX Индекс (только для устройства, а не для файла)

Возврат без ошибки:

Регистр Содержание
CF 0
DX Слово атрибутов устройства, если бит 15 установлен в 1, это удаленное устройство, в противном случае устройство является локальным

Возврат с ошибкой:

Регистр Содержание
CF 1
AX 01h - запрошена несуществующая функция;

06h - BX содержит несуществующий индекс.

Ошибка 01h может возникнуть, если не загружена команда SHARE.

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

# 0Bh Установка количества повторов при обращении к файлу

Вызов:

Регистр Содержание
AH 44h
AL 0Bh
CX Продолжительность паузы (по умолчанию используется значение 1)
DX Число повторов (по умолчанию равно 3) до вызова программы обработки прерывания 24h - прерывания по критической ошибке ввода/вывода

Возврат без ошибки:

Регистр Содержание
CF 0

Возврат с ошибкой:

Регистр Содержание
CF 1
AX 01h - запрошена несуществующая функция;

Код ошибки 01h появляется, если задан недопустимый номер подфункции или не загружена команда SHARE.

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

mov  cx,pause
loop $

# 0Ch Переключение кодовых страниц

Вызов:

Регистр Содержание
AH 44h
AL 0Ch
BX Индекс для открытого устройства
CH Код категории устройства:

00 - неизвестное устройство;

01 - устройства COM1, COM2 и т.д.;

03 - консоль CON;

05 - устройства печати LPT1, LPT2 и т.д.

CL Код операции:

45h - установить число повторений операции;

4Ah - выбор кодовой страницы;

4Ch - начало подготовки кодовой страницы;

4Dh - конец подготовки кодовой страницы;

5Fh - установить устройство "дисплей";

65h - получить число повторений операции;

6Ah - получить выбранную кодовую страницу;

6Bh - получить подготовленный список;

7Ah - получить параметры дисплея (ширина, длина и цвет)

DS:DX Указатель на блок параметров.

Возврат без ошибки:

Регистр Содержание
CF 0

Возврат с ошибкой:

Регистр Содержание
CF 1
AX 01h - запрошена несуществующая функция;

06h - BX содержит несуществующий индекс.

Для подготовки кодовой страницы сначала вызывают эту подфункцию с кодом операции CL=4Ch, затем должна идти серия вызовов подфункции 03h функции 44h прерывания INT 21h - запись IOCTL на символьное устройство.

Формат записываемых данных зависит от типа устройства. Драйверы DISPLAY.SYS и PRINTER.SYS, входящие в состав дистрибутива DOS, получают эти данные из файлов с расширением имени .CPI, таких как EGA.CPI, LCD.CPI, 4201.CPI и т.д.

Блок параметров имеет различный формат для разных кодов операций:

CL = 45h блок параметров состоит из слова, содержащего количество повторений;
CL = 4Ah, 4Dh, 6Ah блок параметров состоит из двух слов, первое слово - длина данных (0002), второе - идентификатор кодовой страницы;
CL = 4Ch в начале блока параметров расположены три слова - флаги (0000), длина остальной части блока параметров в байтах и количество кодовых страниц, за этими тремя словами следуют слова кодовых страниц. Количество слов кодовых страниц в зависимости от значения MAXFONTS при установке драйвера и может достигать 12;
CL = 6Bh первым располагается слово, содержащее длину остальной части блока в байтах, затем идет количество аппаратных кодовых страниц и слова для этих кодовых страниц, в конце расположено слово, содержащее количество подготовленных кодовых страниц и слова с подготовленными кодовыми страницами. Возвращаемый блок может иметь длину до 56 байтов.

# 0Dh Общее управление вводом/выводом (GENERIC IOCTL)

Вызов:

Регистр Содержание
AH 44h
AL 0Dh
BL Номер дисковода (0 - текущий дисковод, 1 - дисковод А: и т.д.)
CH Код категории устройства: 08h - дисковое устройство
CL Операция:

40h - установить параметры устройства;

60h - получить параметры устройства;

41h - записать дорожку на логическом устройстве;

61h - прочитать дорожку на логическом устройстве;

42h - форматировать дорожку на логическом устройстве;

62h - проверить дорожку на логическом устройстве

DS:DX Указатель на блок параметров.

Возврат без ошибки:

Регистр Содержание
CF 0

Возврат с ошибкой:

Регистр Содержание
CF 1
AX Код ошибки

Общая схема использования этой подфункции:

  1. Сохранить параметры устройства операцией 40h.
  2. Установить нужные параметры.
  3. Выполнить операцию ввода/вывода или форматирования.
  4. Восстановить предыдущие параметры.

Формат блока параметров зависит от выполняемой операции:

CL = 40h/60h (получить/установить параметры устройства)

Смещение Размер Содержимое поля
(0) 1 Специальные функции
(+1) 1 Тип устройства, возвращаемый драйвером:

0 - 320/360 К флоппи-диск (5,25");

1 - 1,2 М флоппи-диск (5,25");

2 - 720 К флоппи-диск (3,5");

3 - 8" флоппи-диск нормальной плотности;

4 - 8" флоппи-диск двойной плотности;

5 - жесткий диск;

6 - накопитель на магнитной ленте;

7 - 1,44 М флоппи-диск (3,5")

(+2) 2 Атрибуты устройства, возвращаемые драйвером. В этом поле используются только два младших бита. Бит 0 - признак заменяемости среды носителя данных (0 - заменяемая, 1 - не заменяемая), бит 1 - признак наличия аппаратного контроля замены дискеты (1 - контроль выполняется, 0 - контроль не выполняется). Остальные биты зарезервированы и должны содержать 0.
(+4) 2 Максимальное количество цилиндров на физическом устройстве. Это поле устанавливается драйвером.
(+6) 1 Тип среды носителя данных. Используется для устройств, поддерживающих несколько типов носителей данных, например, для флоппи-дисковода на 1.2М значение этого поля, равное 0, соответствует дискете на 1.2М, а 1 - 360К.
(+7) 31 BPB для устройства. Если бит 0 поля специальных функций сброшен, то в этом поле находится новый BPB для устройства. Если бит 0 установлен, драйвер устройства возвращает BPB для всех последующих запросов на построение BPB.
(+38) ? Таблица разметки дорожки, имеет переменную длину.

Биты байта специальных функций имеют следующее значение:

  • Бит 0:

В операции 60h значение этого бита, равное 1, используется для извлечения текущего BPB, как если бы он был получен по команде драйвера с кодом 2 (построить BPB). Значение этого бита, равное 0, говорит о том, что надо извлечь BPB, используемый по умолчанию.

Для операции с кодом 40h значение бита, равное 1, используется для извлечения текущего BPB, значение 0 приводит к использованию BPB, подготовленного в данном блоке параметров.

  • Бит 1:

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

  • Бит 2:

Значение этого бита, равное 1, говорит о том, что все сектора на этой дорожке имеют одинаковый размер.

Таблица разметки дорожки начинается с двухбайтового слова, содержащего общее количество секторов на дорожке. Затем для каждого сектора в таблице находится по два двухбайтовых слова, содержащих номер сектора (1, 2 и т.д.) и размер сектора. То есть для каждого сектора в таблице содержится два слова.

Если в поле "специальные функции" бит 2 установлен в 1, размеры всех секторов должны быть одинаковыми.

CL = 41h/61h (записать/прочитать дорожку)

Смещение Размер Содержимое поля
(0) 1 Специальные функции (это поле всегда содержит 0)
(+1) 2 Номер головки
(+3) 2 Номер дорожки
(+5) 2 Номер начального сектора (нумерация секторов, в отличие от нумерации головок и дорожек начинается с 0)
(+7) 2 Общее количество секторов на дорожке, уменьшенное на единицу
(+9) 4 FAR-указатель на буфер обмена с диском, в который помещается считываемая информация или откуда берется записываемая информация

CL = 42h/62h (форматировать/проверить дорожку)

Смещение Размер Содержимое поля
(0) 1 Специальные функции. Для этой операции определен только бит 0. Перед вызовом команды значение бита, равное 0, требуется для форматирования дорожки. Если этот бит установлен в 1, то проверяется возможность использования заданного формата трека. Если после выполнения команды значение бита 0 равно 0, то поддерживается заданный формат трека и заполненную таблицу разметки дорожки можно использовать. Если значение бита 0 равно 1, то затребованный формат дорожки не поддерживается.
(+1) 2 Номер головки для форматирования/проверки
(+3) 2 Номер дорожки для форматирования/проверки

# 0Eh Получение информации о логическом дисководе

Вызов:

Регистр Содержание
AH 44h
AL 0Eh
BL Номер дисковода (0 - текущий дисковод, 1 - дисковод А: и т.д.)

Возврат без ошибки:

Регистр Содержание
CF 0
AL Содержимое этого регистра равно 0, если данному дисководу соответствует только одно логическое устройство, или номеру текущего логического дисковода (1 - А:, 2 - В: и т.д.).

Возврат с ошибкой:

Регистр Содержание
CF 1
AX 01h - запрошена несуществующая функция;

0Fh - неправильный идентификатор дисковода;

# 0Fh Установка текущего логического дисковода

Вызов:

Регистр Содержание
AH 44h
AL 0Fh
BL Номер дисковода, который должен стать текущим (0 - текущий дисковод, 1 - дисковод А: и т.д.)

Возврат без ошибки:

Регистр Содержание
CF 0
AL Содержимое этого регистра равно 0, если данному дисководу соответствует только одно логическое устройство, или номеру логического дисковода, который будет использоваться в последующих операциях ввода/вывода (1-А:, 2-В: и т.д.).

Возврат с ошибкой:

Регистр Содержание
CF 1
AX 01h - запрошена несуществующая функция;

0Fh - неправильный идентификатор дисковода;

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

[Назад] [Содеожание]