Операционная система MS DOS (том 2)

H Общее управление вводом/выводом 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); }


Содержание раздела