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