| 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);
}
Программа пользуется текущими параметрами диска А:, поэтому операции чтения текущих параметров и записи новых параметров не используются. Обратите внимание на то, что эта и предыдущая программа разрушают содержимое двадцатой дорожки, поэтому для экспериментов с этими программами надо подготовить чистую отформатированную дискету. 
 | 


![[Назад]](../../prev.gif)
![[Содеожание]](../../sod.gif)
![[Дальше]](../../next.gif)