MS-DOS для программиста© Александр Фролов, Григорий ФроловТом 19, М.: Диалог-МИФИ, 1995, 253 стр. 4.3. Примеры использования функций GENERIC IOCTLВ этом разделе мы приведем исходные тексты двух программ. Первая из них форматирует дорожку дискеты с помощью функции GENERIC IOCTL . Вторая демонстрирует способы чтения и записи секторов дискеты. Для этого она также пользуется функциями GENERIC IOCTL. Программа FMTIOCTLПриведем пример программы FMTIOCTL (листинг 4.1), иллюстрирующей применение функций общего управления GENERIC IOCTL . Эта программа выполняет стандартное форматирование двадцатой дорожки диска А:. Листинг 4.1. Файл fmtioctl\fmtioctl.cpp
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include <malloc.h>
#include <errno.h>
typedef struct _EBPB_
{
unsigned sectsize;
char clustsize;
unsigned ressecs;
char fatcnt;
unsigned rootsize;
unsigned totsecs;
char media;
unsigned fatsize;
unsigned seccnt;
unsigned headcnt;
unsigned hiddensec_low;
unsigned hiddensec_hi;
unsigned long drvsecs;
} EBPB;
typedef struct _TRK_LY_
{
unsigned no;
unsigned size;
} TRK_LY;
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;
typedef struct _DPB_FORMAT_
{
char spec;
unsigned head;
unsigned track;
} DPB_FORMAT;
int 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'))
return(-1);
// Заказываем память для блока
// параметров устройства
dbp = (DPB far*)farmalloc(sizeof(DPB));
// Заказываем память для блока параметров
// устройства, который будет
// использован для форматирования
dbp_f = (DPB_FORMAT far*)
farmalloc(sizeof(DPB_FORMAT));
if(dbp == NULL || dbp_f == NULL)
{
printf("\nМало памяти");
return(-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);
return(-1);
}
// Заполняем блок парметров для форматирования.
// Байт специальных функций содержит значение,
// равное 5. Это означает, что:
// - используется текущий блок параметров BIOS BPB ;
// - используются все поля в блоке парметров устройства;
// - все секторы на дорожке имеют одинаковый размер
dbp->spec = 5;
// Считываем из BPB количество секторов на дорожке
sectors = dbp->bpb.seccnt;
// Подготавливаем таблицу, описывающую формат дорожки
// Записываем количество секторов на дорожке
dbp->trkcnt = sectors;
// Для каждого сектора на дорожке в таблицу
// записываем его номер и размер.
// Заметьте, что записывается размер сектора
// в байтах, а не код размера, как это делается
// при форматировании с помощью
// функции 05h прерывания INT 13h
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);
return(-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);
return(-1);
}
// Если указанный формат дорожки поддерживается,
// поле специальных функций будет содержать 0.
// Проверяем это
if(dbp_f->spec != 0)
{
printf("\nФормат дорожки не поддерживается");
return(-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);
return(-1);
}
// Освобождаем память
farfree(dbp);
farfree(dbp_f);
return(0);
}
После запуска программа форматирования читает текущие параметры для диска А:, формирует структуру дорожки и устанавливает параметры для выполнения операции форматирования. Затем программа проверяет возможность использования указанной структуры дорожки и выполняет форматирование. Программа CPYIOCTLТеперь приведем программу CPYIOCTL (листинг 4.2), копирующую содержимое двух первых секторов нулевой дорожки (головка 0) в первые два сектора двадцатой дорожки. Листинг 4.2. Файл cpyioctl\cpyioctl.cpp
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include <malloc.h>
#include <errno.h>
typedef struct _DPB_WR_
{
char spec;
unsigned head;
unsigned track;
unsigned sector;
unsigned sectcnt;
void _far *buffer;
} DPB_WR;
char buf[2000];
int main(void)
{
union REGS reg;
struct SREGS segreg;
DPB_WR far *dbp_wr;
int sectors, i;
printf("\nПрограмма уничтожит содержимое"
"\n20-й дорожки диска А:."
"\nЖелаете продолжить? (Y,N)\n");
// Ожидаем ответ и анализируем его
i = getch();
if((i != 'y') && (i != 'Y'))
return(-1);
// Заказываем память для блока параметров
// устройства, который будет
// использован для чтения и записи
dbp_wr = (DPB_WR far*)farmalloc(sizeof(DPB_WR));
if(dbp_wr == NULL)
{
printf("\nМало памяти");
return(-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);
return(-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);
return(-1);
}
// Освобождаем память
farfree(dbp_wr);
return(0);
}
Программа пользуется текущими параметрами диска А:, поэтому операции чтения текущих параметров и записи новых параметров не используются. Обратите внимание на то, что эта и предыдущая программа разрушают содержимое двадцатой дорожки, поэтому для экспериментов с этими программами надо подготовить чистую отформатированную дискету. |

