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, говорит о том, что все сектора на этой дорожке имеют одинаковый размер |
Если в поле "специальные функции" бит 2
установлен в 1, размеры всех секторов должны быть одинаковыми.
CL = 41h/61h (записать/прочитать дорожку)
Смещение | Размер | Содержимое поля |
(0) | 1 | Специальные функции (это поле всегда содержит 0) |
(+1) | 2 | Номер головки |
(+3) | 2 | Номер дорожки |
(+5) | 2 | Номер начального сектора (нумерация секторов, в отличие от нумерации головок и дорожек начинается с 0) |
(+7) | 2 | Общее количество секторов на дорожке, уменьшенное на единицу |
(+9) | 4 | FAR-указатель на буфер обмена с диском, в который помещается считываемая информация или откуда берется записываемая информация |
Смещение | Размер | Содержимое поля |
(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(®, ®, &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(®, ®, &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(®, ®, &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(®, ®, &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(®, ®, &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(®, ®, &segreg);
// Проверяем флаг переноса
if(reg.x.cflag != 0) { printf("\nОшибка: %d",reg.x.ax); exit(-1); }
// Освобождаем буфер
free(dbp_wr);
exit(0); }