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

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

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

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

4.2. Общее управление вводом/выводом

Подфункция 0Dh функции 44h прерывания INT 21h обеспечивает механизм взаимодействия между прикладным программным обеспечением и драйверами блочных устройств. Эта подфункция позволяет программам читать и изменять параметры устройств, предоставляет возможность выполнять аппаратно-независимое чтение, запись, форматирование и проверку дорожек диска.

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

Для удобства приведем формат вызова этй подфункции еще раз:

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 Код ошибки

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

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

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

0 - 320/360 К флоппи-диск (5");
1 - 1,2 М флоппи-диск (5");
2 - 720 К флоппи-диск (3");
3 - 8" флоппи-диск нормальной плотности;
4 - 8" флоппи-диск двойной плотности;
5 - жесткий диск;
6 - накопитель на магнитной ленте;
7 - 1,44 М флоппи-диск (3") и прочие дисковые устройства.
(+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 Номер дорожки для форматирования/проверки

Перед началом выполнения операции программа должна получить и созранить текущие параметры устройства. Для получения текущих параметров устройства необходимо выполнить операцию с кодом 60h. Затем программа должна установить новые параметры устройства, которые будут использованы в операциях чтения/записи, проверки или форматирования. Для установки параметров программа должна выполнить операцию с кодом 40h.

После выполнения операции программа должна восстановить первоначальные параметры устройства, выполнив операцию с кодом 40h.

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

Эта программа выполняет стандартное форматирование двадцатой дорожки диска А:.

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

#pragma pack(1)

/* Формат дорожки для GENERIC IOCTL */

typedef struct _TRK_LY_ {
        unsigned no;
        unsigned size;
} TRK_LY;


/* Параметры устройства для GENERIC IOCTL */

typedef struct _DPB_ {

        char spec;
        char devtype;
        unsigned devattr;
        unsigned numofcyl;
        char media_type;

        EBPB bpb;
        char reserved[6];

        unsigned trkcnt;
        TRK_LY trk[100];

} DPB;


/* Параметры для форматирования функцией GENERIC IOCTL */

typedef struct _DPB_FORMAT_ {

        char spec;
        unsigned head;
        unsigned track;

} DPB_FORMAT;

#pragma pack()

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

#include <dos.h>
#include <stdio.h>
#include <malloc.h>
#include <errno.h>
#include "sysp.h"

void main(void);
void main(void) {

         union REGS reg;
         struct SREGS segreg;
         DPB _far *dbp;
         DPB_FORMAT _far *dbp_f;

         int sectors, i;

         printf("\nПрограмма уничтожит содержимое"
                          "\n20-й дорожки диска А:."
                          "\nЖелаете продолжить? (Y,N)\n");

// Ожидаем ответ оператора и анализируем его

         i = getch();
         if((i != 'y') && (i != 'Y')) exit(-1);

// Заказываем память для блока параметров устройства

         dbp = _fmalloc(sizeof(DPB));

// Заказываем память для блока параметров устройства,
// который будет использован для форматирования

         dbp_f = _fmalloc(sizeof(DPB_FORMAT));

         if(dbp == NULL || dbp_f == NULL) {
                printf("\nМало оперативной памяти!");
                exit(-1);
         }

// Получаем текущие параметры диска А:

         dbp->spec = 0;

// Вызываем подфункцию 0Dh для выполнения
// операции чтения текущих параметров диска А:

         reg.x.ax = 0x440d;
         reg.h.bl = 1;
         reg.x.cx = 0x0860;
         reg.x.dx =  FP_OFF(dbp);
         segreg.ds = FP_SEG(dbp);

         intdosx(&reg, &reg, &segreg);

// Проверяем флаг переноса

         if(reg.x.cflag != 0) {
                printf("\nОшибка: %d",reg.x.ax);
                exit(-1);
         }

// Заполняем блок параметров для форматирования.
// Байт специальных функций содержит значение,
// равное 5. Это означает, что:
//    - используется текущий блок параметров BIOS BPB;
//    - используются все поля в блоке параметров устройства;
//    - все сектора на дорожке имеют одинаковый размер

         dbp->spec = 5;

// Считываем из BPB количество секторов на дорожке

         sectors = dbp->bpb.seccnt;

// Подготавливаем таблицу, описывающую формат дорожки

// Записываем количество секторов на дорожке

         dbp->trkcnt = sectors;

// Для каждого сектора на дорожке в таблицу
// записываем его номер и размер.
// Заметьте, что записывается размер сектора
// в байтах, а не код размера, как это делается
// при форматировании с помощью функции 05h прерывания INT13h

         for(i = 0; i < sectors; i++) {
                dbp->trk[i].no   = i+1;
                dbp->trk[i].size = 512;
         }

// Устанавливаем новые параметры для диска А:

         reg.x.ax = 0x440d;
         reg.h.bl = 1;
         reg.x.cx = 0x0840;
         reg.x.dx =  FP_OFF(dbp);
         segreg.ds = FP_SEG(dbp);

         intdosx(&reg, &reg, &segreg);

// Проверяем флаг переноса

         if(reg.x.cflag != 0) {
                printf("\nОшибка: %d",reg.x.ax);
                exit(-1);
         }

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

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

         dbp_f->spec = 1;
         dbp_f->head = 0;
         dbp_f->track = 20;

         reg.x.ax = 0x440d;
         reg.h.bl = 1;
         reg.x.cx = 0x0842;
         reg.x.dx =  FP_OFF(dbp_f);
         segreg.ds = FP_SEG(dbp_f);

         intdosx(&reg, &reg, &segreg);

// Проверяем флаг переноса

         if(reg.x.cflag != 0) {
                printf("\nОшибка: %d",reg.x.ax);
                exit(-1);
         }

// Если указанный формат дорожки поддерживается,
// поле специальных функций будет содержать 0.
// Проверяем это.

         if(dbp_f->spec != 0) {
                printf("\nФормат дорожки не поддерживается!");
                exit(-1);
         }

// Заполняем блок параметров для выполнения
// операции форматирования

         dbp_f->spec = 0;
         dbp_f->head = 0;
         dbp_f->track = 20;

// Форматируем дорожку с номером 20, головка 0

         reg.x.ax = 0x440d;
         reg.h.bl = 1;
         reg.x.cx = 0x0842;
         reg.x.dx =  FP_OFF(dbp_f);
         segreg.ds = FP_SEG(dbp_f);

         intdosx(&reg, &reg, &segreg);

// Проверяем флаг переноса

         if(reg.x.cflag != 0) {
                printf("\nОшибка: %d",reg.x.ax);
                exit(-1);
         }

// Освобождаем буфера

         _ffree(dbp);
         _ffree(dbp_f);

         exit(0);
}

Теперь приведем программу, копирующую содержимое двух первых секторов нулевой дорожки (головка 0) в первые два сектора двадцатой дорожки.

Эта программа использует тип данных, используемый в операциях чтения/записи:

#pragma pack(1)

/* Параметры для чтения/записи функцией GENERIC IOCTL */

typedef struct _DPB_WR_ {

        char spec;
        unsigned head;
        unsigned track;
        unsigned sector;
        unsigned sectcnt;
        void _far *buffer;

} DPB_WR;

#pragma pack()

Программа пользуется текущими параметрами диска А:, поэтому операции чтения текущих параметров и записи новых параметров не используются.

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

#include <dos.h>
#include <stdio.h>
#include <malloc.h>
#include <errno.h>
#include "sysp.h"

void main(void);
void main(void) {

         union REGS reg;
         struct SREGS segreg;
         DPB_WR _far *dbp_wr;
         char buf[2000];

         int sectors, i;

         printf("\nПрограмма уничтожит содержимое"
                          "\n20-й дорожки диска А:."
                          "\nЖелаете продолжить? (Y,N)\n");

// Ожидаем ответ оператора и анализируем его

         i = getch();
         if((i != 'y') && (i != 'Y')) exit(-1);


// Заказываем память для блока параметров устройства,
// который будет использован для чтения/записи

         dbp_wr = malloc(sizeof(DPB_WR));

         if(dbp_wr == NULL) {
                printf("\nМало оперативной памяти!");
                exit(-1);
         }


// Заполняем блок параметров для выполнения
// операции чтения.
// Мы будем читать первые два сектора
// на нулевой дорожке, головка 0.

         dbp_wr->spec = 0;
         dbp_wr->head = 0;
         dbp_wr->track = 0;
         dbp_wr->sector = 0;
         dbp_wr->sectcnt = 2;
         dbp_wr->buffer = buf;

// Выполняем операцию чтения дорожки

         reg.x.ax = 0x440d;
         reg.h.bl = 1;
         reg.x.cx = 0x0861;
         reg.x.dx =  FP_OFF(dbp_wr);
         segreg.ds = FP_SEG(dbp_wr);

         intdosx(&reg, &reg, &segreg);

// Проверяем флаг переноса

         if(reg.x.cflag != 0) {
                printf("\nОшибка: %d",reg.x.ax);
                exit(-1);
         }


// Заполняем блок параметров для выполнения
// операции записи.
// Только что прочитанные два сектора нулевой
// дорожки будут записаны на 20-ю дорожку.

         dbp_wr->spec = 0;
         dbp_wr->head = 0;
         dbp_wr->track = 20;
         dbp_wr->sector = 0;
         dbp_wr->sectcnt = 2;
         dbp_wr->buffer = buf;

// Выполняем операцию записи

         reg.x.ax = 0x440d;
         reg.h.bl = 1;
         reg.x.cx = 0x0841;
         reg.x.dx =  FP_OFF(dbp_wr);
         segreg.ds = FP_SEG(dbp_wr);

         intdosx(&reg, &reg, &segreg);

// Проверяем флаг переноса

         if(reg.x.cflag != 0) {
                printf("\nОшибка: %d",reg.x.ax);
                exit(-1);
         }


// Освобождаем буфер

         free(dbp_wr);

         exit(0);
}
[Назад] [Содеожание] [Дальше]