Добавил:
Studfiles2
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Операционная система MS-DOS / 3 Том / 277-5
.html<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1251">
<TITLE>Untitled</TITLE>
<META NAME="GENERATOR" CONTENT="Internet Assistant for Microsoft Word 2.04z">
</HEAD>
<body><link REL=stylesheet HREF=http://emanual.ru/style.css TYPE=text/css><table border=0 width=100% cellspacing=0 cellpadding=0><tr><td bgcolor=gold><a href=http://emanual.ru/><img src=http://emanual.ru/logo.gif width=150 height=60 vspace=4 hspace=4 border=0></a></td><td align=center bgcolor=gold valign=center width=100%><iframe src="http://rb1.design.ru/cgi-bin/iframe/emanual?.981768849.&" width=470 height=60 marginwidth=0 marginheight=0 scrolling=no frameborder=0><a href="http://rb1.design.ru/cgi-bin/href/emanual?.981768849." target=_top><img src="http://rb1.design.ru/cgi-bin/banner/emanual?.981768849.&" alt="RB1 Network" width=470 height=60 border=0 ismap></a></iframe><img src=http://emanual.ru/blank.gif width=4 height=1 vspace=0 hspace=0 border=0><iframe src="http://120.goodoo.ru/cgi-bin/iframe/emanual?.981768850.&" width=120 height=60 marginwidth=0 marginheight=0 scrolling=no frameborder=0><a href="http://120.goodoo.ru/cgi-bin/href/emanual?.981768850." target=_top><img src="http://120.goodoo.ru/cgi-bin/banner/emanual?.981768850.&" alt="GooDoo 120" width=120 height=60 border=0 ismap></a></iframe></td></tr><tr><td bgcolor=black colspan=2 background=http://emanual.ru/line_bg.gif align=center class=fine height=20><font color=white><a href=http://softarea.ru class=top>Программы</a> •<a href=http://hardarea.ru class=top>Железо</a> • <a href=http://softarea.ru/drivers class=top>Драйверы</a> • <a href=http://majordomo.ru/hosting class=top>Хостинг</a> •<a href=http://reklamist.com class=top>Энциклопедия рекламы</a></font></td></tr></table><H2><FONT SIZE=5 COLOR=#FF0000>4. Использование функций IOCTL</FONT>
</H2>
<P>
4.1. <A HREF="#ch4_1" >Получение различной информации</A>
<P>
4.2. <A HREF="#ch4_2" >Общее управление вводом/выводом</A>
<P>
В разделе книги, посвященным драйверам, мы рассказывали о функции
управления вводом/выводом <B>IOCTL</B> - функции <B>44h</B> прерывания
<B>INT 21h</B>. Эта функция предоставляет широкие возможности
по управлению устройствами ввода/вывода посредством обмена управляющей
информацией с драйверами устройств.
<P>
В этом разделе мы вновь вернемся к функциям <B>IOCTL</B> для того,
чтобы рассказать об их использовании при работе с дисковой подсистемой.
<P>
Мы покажем, как использовать функцию <B>44h</B> прерывания <B>INT 21h</B>
для извлечения разнообразной информации об открытых файлах по
их файловому индексу, для определения момента достижения конца
файла, для получения информации об дисководах и для выполнения
таких низкоуровневых операций, как форматирование дорожки диска,
чтение/запись секторов диска и т.д.
<P>
Напомним, при вызове функции <B>44h</B> регистр <B>AL</B> содержит
код выполняемой подфункции. Для подфункции <B>0Dh</B> (<B>Generic
IO Control</B>) в регистре <B>CL</B> должен находиться код выполняемой
операции.
<H3><A NAME="ch4_1"><FONT SIZE=4 COLOR=#008000>4.1. Получение
различной информации</FONT></A></H3>
<P>
С помощью подфункции <B>00h</B> можно получить информацию об открытом
файле или устройстве по файловому индексу.
<P>
Для удобства работы с этой подфункцией мы подготовили следующую
программу:
<PRE>
<FONT COLOR=#000080 FACE="Courier New Cyr">/**
*.Name get_devi
*
*.Title Получить информацию об устройстве
*
*.Descr Функция получает информацию о файле
* или об устройстве по его файловому индексу.
*
*
*.Params int get_devi(int handle, int *info);
*
* handle - файловый индекс для
* которого необходимо получить
* информацию
*
* info - указатель на слово, в которое
* должна быть записана информация
*
*.Return 0 - если нет ошибок;
* Код ошибки - если произошла ошибка.
**/
#include <stdio.h>
#include <dos.h>
#include "sysp.h"
int get_devi(int handle, int *info) {
union REGS reg;
// Заполняем регистровые структуры для вызова
// прерывания DOS INT 21h. Код используемой
// подфункции - 00h.
reg.x.ax = 0x4400;
reg.x.bx = handle;
// Вызываем прерывание
intdos(&reg, &reg);
// Проверяем флаг переноса
if(reg.x.cflag == 0) {
// Если флаг переноса сброшен в 0, ошибок нет.
// Записываем информацию по адресу *info
*info = reg.x.dx;
return(0);
}
// Если флаг переноса установлен в 1, возвращаем
// код ошибки
else return(reg.x.ax);
}</FONT>
</PRE>
<P>
Приведенная выше функция принимает в качестве первого параметра
файловый индекс открытого файла или устройства и адрес слова,
в который она запишет информацию об устройстве или файле, связанном
с этим файловым индексом.
<P>
Вы можете использовать эту функцию так, как это сделано в следующем
примере:
<PRE>
<FONT COLOR=#000080 FACE="Courier New Cyr">#include <dos.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[]);
void main(int argc, char *argv[]) {
int handle;
int info;
int rc;
// Открываем файл или устройство с заданным именем
handle = open(argv[1], O_RDONLY);
// Если открыть невозможно, выводим сообщение
// и завершаем работу программы
if(handle == -1) {
printf("Не могу открыть файл!\n");
exit(-1);
}
// Получаем информацию для файлового индекса handle
rc = get_devi(handle, &info);
if(rc != 0) {
printf("Ошибка с кодом %d\n", rc);
exit(-1);
}
printf("\nСлово информации об устройстве: %04X",info);
close(handle);
}</FONT>
</PRE>
<P>
В качестве параметра при запуске этой программы попробуйте задавать
имена файлов или имена устройств, например -<B> CON, AUX</B>,
и т.д.
<P>
Мы уже описывали формат слова, содержащего информацию об устройстве
или файле, для удобства приведем его еще раз.
<P>
Для устройства:<BR>
<P>
<TABLE BORDER=1 >
<TR><TD WIDTH=67><I><B>Бит</B></I></TD><TD WIDTH=422><I><B>Значение</B></I>
</TD></TR>
<TR><TD WIDTH=67><B>0</B></TD><TD WIDTH=422>Это устройство является стандартным устройством ввода.
</TD></TR>
<TR><TD WIDTH=67><B>1</B></TD><TD WIDTH=422>Стандартное устройство вывода.
</TD></TR>
<TR><TD WIDTH=67><B>2</B></TD><TD WIDTH=422><B>NUL</B>-устройство.
</TD></TR>
<TR><TD WIDTH=67><B>3</B></TD><TD WIDTH=422>Часы.</TD></TR>
<TR><TD WIDTH=67><B>4</B></TD><TD WIDTH=422>Специальное устройство.
</TD></TR>
<TR><TD WIDTH=67><B>5</B></TD><TD WIDTH=422><B>1</B> - двоичный режим работы;
<BR>
<B>0</B> - режим ASCII
</TD></TR>
<TR><TD WIDTH=67><B>6</B></TD><TD WIDTH=422><B>0</B> - при чтении достигнут конец файла.
</TD></TR>
<TR><TD WIDTH=67><B>7</B></TD><TD WIDTH=422><B>1</B> - это слово информации относится к устройству (данный handle относится к устройству); <BR>
<B>0</B> - слово информации относится к файлу.
</TD></TR>
<TR><TD WIDTH=67><B>8-10</B></TD><TD WIDTH=422>Зарезервировано.
</TD></TR>
<TR><TD WIDTH=67><B>11</B></TD><TD WIDTH=422><B>1</B> - Устройство поддерживает команды открытия/закрытия.
</TD></TR>
<TR><TD WIDTH=67><B>12</B></TD><TD WIDTH=422>Сетевое устройство (только для DOS версии 3.0 и более поздних версий).
</TD></TR>
<TR><TD WIDTH=67><B>13</B></TD><TD WIDTH=422>Устройство поддерживает вывод до состояния занятости.
</TD></TR>
<TR><TD WIDTH=67><B>14</B></TD><TD WIDTH=422>Устройство может обрабатывать управляющие строки <B>IOCTL</B>, посылаемые подфункциями <B>2, 3, 4, 5</B> функции <B>44h</B>. Этот бит может быть только прочитан, его установка подфункцией <B>1</B> функции <B>44h</B> не производится.
</TD></TR>
<TR><TD WIDTH=67><B>15</B></TD><TD WIDTH=422>Зарезервировано.
</TD></TR>
</TABLE>
<P>
Для файла:<BR>
<P>
<TABLE BORDER=1 >
<TR><TD WIDTH=87><I><B>Бит</B></I></TD><TD WIDTH=401><I><B>Значение</B></I>
</TD></TR>
<TR><TD WIDTH=87><B>0-5</B></TD><TD WIDTH=401>Номер дисковода (<B>0-А:, 1-В: </B>и т.д.).
</TD></TR>
<TR><TD WIDTH=87><B>6</B></TD><TD WIDTH=401><B>0</B> - Была запись в выходной файл.
</TD></TR>
<TR><TD WIDTH=87><B>7</B></TD><TD WIDTH=401><B>1</B> - это слово информации относится к устройству (данный handle относится к устройству);
<BR>
<B>0</B> - слово информации относится к файлу.
</TD></TR>
<TR><TD WIDTH=87><B>8-11</B></TD><TD WIDTH=401>Зарезервировано.
</TD></TR>
<TR><TD WIDTH=87><B>12</B></TD><TD WIDTH=401>Сетевое устройство (только для DOS версии 3.0 и более поздних версий).
</TD></TR>
<TR><TD WIDTH=87><B>13-14</B></TD><TD WIDTH=401>Зарезервировано.
</TD></TR>
<TR><TD WIDTH=87><B>15</B></TD><TD WIDTH=401><B>1</B> - Данный файл является удаленным при работе в сети (только для DOS версии 3.0 и более поздних версий).
</TD></TR>
</TABLE>
<P>
Подфункция <B>06h</B> функции <B>44h</B> прерывания <B>INT 21h</B>
поможет вам определить момент достижения конца файла или готовность
устройства посимвольной обработки.
<P>
Для проверки условия "Конец файла" или готовности устройства
можно использовать следующую функцию:
<PRE>
<FONT COLOR=#000080 FACE="Courier New Cyr">/**
*.Name heof
*
*.Title Проверить условие "Конец файла"
*
*.Descr Функция позволяет проверить факт достижения
* конца файла или готовность устройства
*
*.Params int heof(int handle);
*
* handle - файловый индекс для
* которого необходимо получить
* информацию о состоянии
*
*.Return 0 - конец файла не достигнут (для файла),
* устройство готово (для устройства);
*
* 1 - достигнут конец файла (для файла),
* устройство не готово (для устройства);
*
* -1 - произошла ошибка.
**/
#include <stdio.h>
#include <dos.h>
#include "sysp.h"
int heof(int handle) {
union REGS reg;
// Заполняем регистровые структуры для вызова
// прерывания DOS INT 21h. Код используемой
// подфункции - 06h.
reg.x.ax = 0x4406;
reg.x.bx = handle;
// Вызываем прерывание
intdos(&reg, &reg);
// Проверяем флаг переноса
if(reg.x.cflag == 0) {
// Если флаг переноса сброшен в 0, ошибок нет.
if(reg.h.al == 0) return(1);
else return(0);
}
// Если флаг переноса установлен в 1, возвращаем
// признак ошибки
else return(-1);
}</FONT>
</PRE>
<P>
Вы можете использовать эту функцию аналогично функции<B> eof().</B>
В приведенном ниже примере программы, копирующей файлы, мы так
и поступили:
<PRE>
<FONT COLOR=#000080 FACE="Courier New Cyr">#include <stdio.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <malloc.h>
#include <errno.h>
void main(int, char *[]);
void main(int argc, char *argv[]) {
int source, target, i;
char *buffer;
unsigned count;
if(argc == 3) {
// Открываем исходный копируемый файл
if((source = open(argv[1], O_BINARY | O_RDONLY)) == - 1) {
printf("\nОшибка при открытии исходного файла: %d",
errno);
exit(-1);
}
// Открываем выходной файл. При необходимости создаем
// новый. Если файл уже существует, выводим на экран
// запрос на перезапись содержимого существующего файла
target = open(argv[2], O_BINARY | O_WRONLY | O_CREAT | O_EXCL,
S_IREAD | S_IWRITE);
if(errno == EEXIST) {
printf("\nФайл существует. Перезаписать? (Y,N)\n");
// Ожидаем ответ оператора и анализируем его
i = getch();
if((i == 'y') || (i == 'Y'))
target = open(argv[2], O_BINARY | O_WRONLY | O_CREAT | O_TRUNC,
S_IREAD | S_IWRITE);
}
// Если выходной файл открыть невозможно, выводим
// сообщение об ошибке и завершаем работу программы
if(target == -1){
printf("\nОшибка при открытии выходного файла: %d",
errno);
exit(-1);
}
// Будем читать и писать за один раз 10000 байтов
count = 10000;
// Заказываем буфер для передачи данных
if((buffer = (char *)malloc(count)) == NULL) {
printf("\nНедостаточно оперативной памяти");
exit(-1);
}
// Копируем исходный файл
while(!heof(source)) {
// Читаем count байтов в буфер buffer
if((count = read(source, buffer, count)) == -1) {
printf("\nОшибка при чтении: %d",
errno);
exit(-1);
}
// Выполняем запись count байтов из буфера в выходной файл
if((count = write(target, buffer, count)) == - 1) {
printf("\nОшибка при записи: %d",
errno);
exit(-1);
}
}
// Закрываем входной и выходной файлы
close(source);
close(target);
// Освобождаем память, заказанную под буфер
free(buffer);
}
// Если при запуске программы не были указаны
// пути для входного или выходного файла,
// выводим сообщение об ошибке
else
printf("\n"
"Задайте пути для исходного"
" и результирующего файлов!\n");
}</FONT>
</PRE>
<P>
Подфункция <B>0Ah</B> функции <B>44h</B> прерывания <B>INT 21h</B>
поможет программе, работающей в сети, определить расположение
открытого файла или устройства - на рабочей станции или на сервере.
<P>
Перед вызовом запишите в регистр <B>BX</B> файловый индекс проверяемого
файла или устройства.
<P>
После возврата из подфункции регистр <B>DX</B> содержит слово
атрибутов для файла или устройства. Если самый старший бит в этом
слове равен <B>0</B>, то файл или устройство является локальным
и расположено на рабочей станции. Если же этот бит равен <B>1</B>,
то файл или устройство удаленное и находится на сервере (подключено
к серверу, если проверяется устройство).
<P>
Обычно программы составляют таким образом, чтобы их работа не
зависела от расположения. Но если такая информация вам когда-либо
понадобится, вы можете воспользоваться подфункцйией <B>0Ah</B>.
<P>
Аналогично для проверки расположения дисковода можно использовать
подфункцию <B>09h</B>.
<P>
Перед вызовом запишите в регистр <B>BL</B> код дисковода (<B>0</B>-текущий
дисковод, <B>1</B> <B>- А:, 2 - В:,</B> и т.д.). Двенадцатый бит
регистра <B>DX</B> после вызова этой функции покажет вам расположение
дисковода: <B>0</B> - локальное, <B>1</B> - удаленное.
<P>
Для проверки возможности замены носителя данных в дисководе вы
можете воспользоваться подфункцией <B>08h</B>. Используя эту подфункцию,
вы сможете отличить НГМД от НМД. Это может вам понадобиться, например,
для операции форматирования, так как форматирование НГМД и НМД
выполняется по-разному.
<P>
Перед вызовом подфункции <B>08h</B> запишите код устройства в
регистр <B>BL</B> (<B>0 </B>-текущий дисковод, <B>1 - А:, 2 -
В:,</B> и т.д.). Если носитель данных сменный, то после выполнения
подфункции регистр <B>AL</B> будет содержать <B>0</B>, в противном
случае - <B>1</B>.
<P>
Эта подфункция не предназначена для работы с сетевыми устройствами.
<H3><A NAME="ch4_2"><FONT SIZE=4 COLOR=#008000>4.2. Общее управление
вводом/выводом</FONT></A></H3>
<P>
Подфункция <B>0Dh</B> функции <B>44h</B> прерывания <B>INT 21h</B>
обеспечивает механизм взаимодействия между прикладным программным
обеспечением и драйверами блочных устройств. Эта подфункция позволяет
программам читать и изменять параметры устройств, предоставляет
возможность выполнять аппаратно-независимое чтение, запись, форматирование
и проверку дорожек диска.
<P>
Эта подфункция была уже нами описана в разделе, посвященном драйверам.
<P>
Для удобства приведем формат вызова этй подфункции еще раз:
<H4><FONT SIZE=2>0Dh Общее управление вводом/выводом GENERIC IOCTL</FONT>
</H4>
<P>
Вызов:<BR>
<P>
<TABLE >
<TR><TD WIDTH=107><I><B>Регистр</B></I></TD><TD WIDTH=395><I><B>Содержание</B></I>
</TD></TR>
<TR><TD WIDTH=107><B>AH</B></TD><TD WIDTH=395><B>44h</B></TD>
</TR>
<TR><TD WIDTH=107><B>AL</B></TD><TD WIDTH=395><B>0Dh</B></TD>
</TR>
<TR><TD WIDTH=107><B>BL</B></TD><TD WIDTH=395>Номер дисковода (<B>0</B> - текущий дисковод, <B>1</B> - дисковод <B>А:</B> и т.д.)
</TD></TR>
<TR><TD WIDTH=107><B>CH</B></TD><TD WIDTH=395>Код категории устройства: <B>08h</B> - дисковое устройство
</TD></TR>
<TR><TD WIDTH=107><B>CL</B></TD><TD WIDTH=395>Операция:
<BR>
40h - установить параметры устройства; <BR>
60h - получить параметры устройства; <BR>
41h - записать дорожку на логическом устройстве; <BR>
61h - прочитать дорожку на логическом устройстве; <BR>
42h - форматировать дорожку на логическом устройстве; <BR>
62h - проверить дорожку на логическом устройстве
</TD></TR>
<TR><TD WIDTH=107><B>DS:DX</B></TD><TD WIDTH=395>Указатель на блок параметров.
</TD></TR>
</TABLE>
<P>
<P>
Возврат без ошибки:<BR>
<P>
<TABLE >
<TR><TD WIDTH=105><I><B>Регистр</B></I></TD><TD WIDTH=396><I><B>Содержание</B></I>
</TD></TR>
<TR><TD WIDTH=105><B>CF</B></TD><TD WIDTH=396>0</TD></TR>
</TABLE>
<P>
<P>
Возврат с ошибкой:<BR>
<P>
<TABLE >
<TR><TD WIDTH=104><I><B>Регистр</B></I></TD><TD WIDTH=399><I><B>Содержание</B></I>
</TD></TR>
<TR><TD WIDTH=104><B>CF</B></TD><TD WIDTH=399>1</TD></TR>
<TR><TD WIDTH=104><B>AX</B></TD><TD WIDTH=399>Код ошибки</TD>
</TR>
</TABLE>
<P>
<P>
Формат блока параметров зависит от выполняемой операции:
<P>
CL = 40h/60h (получить/установить параметры устройства)
<P>
<TABLE BORDER=1 >
<TR><TD WIDTH=132><I><B>Смещение</B></I></TD><TD WIDTH=87><I><B>Размер</B></I>
</TD><TD WIDTH=283><I><B>Содержимое поля</B></I></TD></TR>
<TR><TD WIDTH=132><B>(0)</B></TD><TD WIDTH=87>1</TD><TD WIDTH=283>Специальные функции:
</TD></TR>
<TR><TD WIDTH=132>(+1)</TD><TD WIDTH=87>1</TD><TD WIDTH=283>Тип устройства, возвращаемый драйвером: <BR>
<BR>
0 - 320/360 К флоппи-диск (5");<BR>
1 - 1,2 М флоппи-диск (5");<BR>
2 - 720 К флоппи-диск (3");<BR>
3 - 8" флоппи-диск нормальной плотности;<BR>
4 - 8" флоппи-диск двойной плотности;<BR>
5 - жесткий диск;<BR>
6 - накопитель на магнитной ленте;<BR>
7 - 1,44 М флоппи-диск (3") и прочие дисковые устройства.
</TD></TR>
<TR><TD WIDTH=132><B>(+2)</B></TD><TD WIDTH=87>2</TD><TD WIDTH=283>Атрибуты устройства, возвращаемые драйвером. В этом поле используются только два младших бита. <BR>
Бит 0 - признак заменяемости среды носителя данных (0 - заменяемая, 1 - не заменяемая), <BR>
бит 1 - признак наличия аппаратного контроля замены дискеты (1 - контроль выполняется, 0 - контроль не выполняется). Остальные биты зарезервированы и должны содержать 0.
</TD></TR>
<TR><TD WIDTH=132><B>(+4)</B></TD><TD WIDTH=87>2</TD><TD WIDTH=283>Максимальное количество цилиндров на физическом устройстве. Это поле устанавливается драйвером.
</TD></TR>
<TR><TD WIDTH=132><B>(+6)</B></TD><TD WIDTH=87>1</TD><TD WIDTH=283>Тип среды носителя данных. Используется для устройств, поддерживающих несколько типов носителей данных, например, для флоппи-дисковода на 1.2М значение этого поля, равное 0, соответствует дискете на 1.2М, а 1 - 360К.
</TD></TR>
<TR><TD WIDTH=132><B>(+7)</B></TD><TD WIDTH=87>31</TD><TD WIDTH=283><B>BPB</B> для устройства. Если бит 0 поля специальных функций сброшен, то в этом поле находится новый <B>BPB</B> для устройства. Если бит 0 установлен, драйвер устройства возвращает <B>BPB</B> для всех последующих запросов на построение <B>BPB</B>.
</TD></TR>
<TR><TD WIDTH=132><B>(+38)</B></TD><TD WIDTH=87>?</TD><TD WIDTH=283>Таблица разметки дорожки, имеет переменную длину.
</TD></TR>
</TABLE>
<P>
Биты специальных функций
<P>
<TABLE >
<TR><TD WIDTH=576><I><B>Бит 0:</B></I></TD></TR>
<TR><TD WIDTH=576>В операции 60h значение этого бита, равное 1, используется для извлечения текущего BPB, как если бы он был получен по команде драйвера с кодом 2 (построить BPB). Значение этого бита, равное 0, говорит о том, что надо извлечь BPB, используемый по умолчанию. Для операции с кодом 40h значение бита, равное 1, используется для извлечения текущего BPB, значение 0 приводит к использованию BPB, подготовленного в данном блоке параметров;
</TD></TR>
<TR><TD WIDTH=576><I><B>Бит 1:</B></I></TD></TR>
<TR><TD WIDTH=576>Значение этого бита, равное 1 - это указание игнорировать все поля в блоке параметров, кроме поля описания физической структуры дорожки на данном устройстве;
</TD></TR>
<TR><TD WIDTH=576><I><B>Бит 2:</B></I></TD></TR>
<TR><TD WIDTH=576>Значение этого бита, равное 1, говорит о том, что все сектора на этой дорожке имеют одинаковый размер
</TD></TR>
</TABLE>
<P>
Таблица разметки дорожки начинается с двухбайтового слова, содержащего
общее количество секторов на дорожке. Затем для каждого сектора
в таблице находится по два двухбайтовых слова, содержащих номер
сектора (1, 2 и т.д.) и размер сектора. То есть для каждого сектора
в таблице содержится два слова.
<P>
Если в поле "специальные функции" бит <B>2</B> установлен
в 1, размеры всех секторов должны быть одинаковыми.
<P>
CL = 41h/61h (записать/прочитать дорожку)
<P>
<TABLE BORDER=1 >
<TR><TD WIDTH=107><I><B>Смещение</B></I></TD><TD WIDTH=91><I><B>Размер</B></I>
</TD><TD WIDTH=295><I><B>Содержимое поля</B></I></TD></TR>
<TR><TD WIDTH=107><B>(0)</B></TD><TD WIDTH=91>1</TD><TD WIDTH=295>Специальные функции (это поле всегда содержит 0)
</TD></TR>
<TR><TD WIDTH=107><B>(+1)</B></TD><TD WIDTH=91>2</TD><TD WIDTH=295>Номер головки
</TD></TR>
<TR><TD WIDTH=107><B>(+3)</B></TD><TD WIDTH=91>2</TD><TD WIDTH=295>Номер дорожки
</TD></TR>
<TR><TD WIDTH=107><B>(+5)</B></TD><TD WIDTH=91>2</TD><TD WIDTH=295>Номер начального сектора (нумерация секторов, в отличие от нумерации головок и дорожек начинается с 0)
</TD></TR>
<TR><TD WIDTH=107><B>(+7)</B></TD><TD WIDTH=91>2</TD><TD WIDTH=295>Общее количество секторов на дорожке, уменьшенное на единицу
</TD></TR>
<TR><TD WIDTH=107><B>(+9)</B></TD><TD WIDTH=91>4</TD><TD WIDTH=295><B>FAR</B>-указатель на буфер обмена с диском, в который помещается считываемая информация или откуда берется записываемая информация
</TD></TR>
</TABLE>
<P>
CL = 42h/62h (форматировать/проверить дорожку)
<P>
<TABLE BORDER=1 >
<TR><TD WIDTH=109><I><B>Смещение</B></I></TD><TD WIDTH=91><I><B>Размер</B></I>
</TD><TD WIDTH=294><I><B>Содержимое поля</B></I></TD></TR>
<TR><TD WIDTH=109><B>(0)</B></TD><TD WIDTH=91>1</TD><TD WIDTH=294>Специальные функции. Для этой операции определен только бит 0. Перед вызовом команды значение бита, равное 0, требуется для форматирования дорожки. Если этот бит установлен в 1, то проверяется возможность использования заданного формата дорожки. Если после выполнения команды значение бита 0 равно 0, то поддерживается заданный формат дорожки и заполенную таблицу разметки дорожки можно использовать. Если значение бита 0 равно 1, то затребованный формат дорожки не поддерживается.
</TD></TR>
<TR><TD WIDTH=109><B>(+1)</B></TD><TD WIDTH=91>2</TD><TD WIDTH=294>Номер головки для форматирования/проверки
</TD></TR>
<TR><TD WIDTH=109><B>(+3)</B></TD><TD WIDTH=91>2</TD><TD WIDTH=294>Номер дорожки для форматирования/проверки
</TD></TR>
</TABLE>
<P>
Перед началом выполнения операции программа должна получить и
созранить текущие параметры устройства. Для получения текущих
параметров устройства необходимо выполнить операцию с кодом <B>60h</B>.
Затем программа должна установить новые параметры устройства,
которые будут использованы в операциях чтения/записи, проверки
или форматирования. Для установки параметров программа должна
выполнить операцию с кодом <B>40h</B>.
<P>
После выполнения операции программа должна восстановить первоначальные
параметры устройства, выполнив операцию с кодом <B>40h</B>.
<P>
Приведем пример программы, иллюстрирующей применение функции общего
управления вводом/выводом для блочных устройств.
<P>
Эта программа выполняет стандартное форматирование двадцатой дорожки
диска <B>А:</B>.
<P>
Для работы с блоками параметров файл <B>sysp.h</B> содержит определения
специальных типов данных, которые будут использованы в программе
форматирования:
<PRE>
<FONT COLOR=#000080 FACE="Courier New Cyr">#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()</FONT>
</PRE>
<P>
Программа форматирования читает текущие параметры для диска <B>А:</B>,
формирует структуру дорожки и устанавливает параметры для выполнения
операции форматирования. Затем программа проверяет возможность
использования указанной структуры дорожки и выполняет форматирование.
<PRE>
<FONT COLOR=#000080 FACE="Courier New Cyr">#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);
}</FONT>
</PRE>
<P>
Теперь приведем программу, копирующую содержимое двух первых секторов
нулевой дорожки (головка 0) в первые два сектора двадцатой дорожки.
<P>
Эта программа использует тип данных, используемый в операциях
чтения/записи:
<PRE>
<FONT COLOR=#000080 FACE="Courier New Cyr">#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()</FONT>
</PRE>
<P>
Программа пользуется текущими параметрами диска <B>А:</B>, поэтому
операции чтения текущих параметров и записи новых параметров не
используются.
<P>
Обратите внимание на то, что эта и предыдущая программа разрушают
содержимое двадцатой дорожки дискеты, поэтому для экспериментов
с этими программами надо подготовить чистую отформатированную
дискету.
<PRE>
<FONT COLOR=#000080 FACE="Courier New Cyr">#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);
}</FONT>
</PRE>
</BODY>
</HTML>
Соседние файлы в папке 3 Том