Скачиваний:
39
Добавлен:
01.05.2014
Размер:
34.62 Кб
Скачать
<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> &#149;<a href=http://hardarea.ru class=top>Железо</a> &#149; <a href=http://softarea.ru/drivers class=top>Драйверы</a> &#149; <a href=http://majordomo.ru/hosting class=top>Хостинг</a> &#149;<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&nbsp;21h</B>. Эта функция предоставляет широкие возможности
по управлению устройствами ввода/вывода посредством обмена управляющей
информацией с драйверами устройств.
<P>
В этом разделе мы вновь вернемся к функциям <B>IOCTL</B> для того,
чтобы рассказать об их использовании при работе с дисковой подсистемой.
<P>
Мы покажем, как использовать функцию <B>44h</B> прерывания <B>INT&nbsp;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 &lt;stdio.h&gt;
#include &lt;dos.h&gt;
#include &quot;sysp.h&quot;

int get_devi(int handle, int *info) {

         union REGS reg;

// Заполняем регистровые структуры для вызова
// прерывания DOS INT 21h. Код используемой
// подфункции - 00h.

         reg.x.ax = 0x4400;
         reg.x.bx = handle;

// Вызываем прерывание

         intdos(&amp;reg, &amp;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 &lt;dos.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

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(&quot;Не могу открыть файл!\n&quot;);
                exit(-1);
         }

// Получаем информацию для файлового индекса handle

         rc = get_devi(handle, &amp;info);

         if(rc != 0) {
                printf(&quot;Ошибка с кодом %d\n&quot;, rc);
                exit(-1);
         }

         printf(&quot;\nСлово информации об устройстве: %04X&quot;,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&nbsp;21h</B>
поможет вам определить момент достижения конца файла или готовность
устройства посимвольной обработки.
<P>
Для проверки условия &quot;Конец файла&quot; или готовности устройства
можно использовать следующую функцию:
<PRE>
<FONT COLOR=#000080 FACE="Courier New Cyr">/**
*.Name      heof
*
*.Title     Проверить условие &quot;Конец файла&quot;
*
*.Descr     Функция позволяет проверить факт достижения
*           конца файла или готовность устройства
*
*.Params    int heof(int handle);
*
*           handle      - файловый индекс для
*                         которого необходимо получить
*                         информацию о состоянии
*
*.Return    0           - конец файла не достигнут (для файла),
*                         устройство готово (для устройства);
*
*           1           - достигнут конец файла (для файла),
*                         устройство не готово (для устройства);
*
*          -1           - произошла ошибка.
**/

#include &lt;stdio.h&gt;
#include &lt;dos.h&gt;
#include &quot;sysp.h&quot;

int heof(int handle) {

         union REGS reg;

// Заполняем регистровые структуры для вызова
// прерывания DOS INT 21h. Код используемой
// подфункции - 06h.

         reg.x.ax = 0x4406;
         reg.x.bx = handle;

// Вызываем прерывание

         intdos(&amp;reg, &amp;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 &lt;stdio.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;sys\types.h&gt;
#include &lt;sys\stat.h&gt;
#include &lt;malloc.h&gt;
#include &lt;errno.h&gt;

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(&quot;\nОшибка при открытии исходного файла: %d&quot;,
                          errno);
                          exit(-1);

                 }

// Открываем выходной файл. При необходимости создаем
// новый. Если файл уже существует, выводим на экран
// запрос на перезапись содержимого существующего файла

                target = open(argv[2], O_BINARY | O_WRONLY | O_CREAT | O_EXCL,
                                                                         S_IREAD | S_IWRITE);
                if(errno == EEXIST) {

                        printf(&quot;\nФайл существует. Перезаписать? (Y,N)\n&quot;);

// Ожидаем ответ оператора и анализируем его

                        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(&quot;\nОшибка при открытии выходного файла: %d&quot;,
                          errno);
                          exit(-1);
                }

// Будем читать и писать за один раз 10000 байтов

                count = 10000;

// Заказываем буфер для передачи данных

                if((buffer = (char *)malloc(count)) == NULL) {
                          printf(&quot;\nНедостаточно оперативной памяти&quot;);
                          exit(-1);
                }


// Копируем исходный файл

                while(!heof(source)) {

// Читаем count байтов в буфер buffer

                        if((count = read(source, buffer, count)) == -1) {
                          printf(&quot;\nОшибка при чтении: %d&quot;,
                          errno);
                          exit(-1);
                        }

// Выполняем запись count байтов из буфера в выходной файл

                        if((count = write(target, buffer, count)) == - 1) {
                          printf(&quot;\nОшибка при записи: %d&quot;,
                          errno);
                          exit(-1);
                        }
                }

// Закрываем входной и выходной файлы

                close(source);
                close(target);

// Освобождаем память, заказанную под буфер

                free(buffer);
         }

// Если при запуске программы не были указаны
// пути для входного или выходного файла,
// выводим сообщение об ошибке

         else
                  printf(&quot;\n&quot;
                        &quot;Задайте пути для исходного&quot;
                        &quot; и результирующего файлов!\n&quot;);
}</FONT>
</PRE>
<P>
Подфункция <B>0Ah</B> функции <B>44h</B> прерывания <B>INT&nbsp;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&nbsp;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&quot;);<BR>
1 - 1,2 М флоппи-диск (5&quot;);<BR>
2 - 720 К флоппи-диск (3&quot;);<BR>
3 - 8&quot; флоппи-диск нормальной плотности;<BR>
4 - 8&quot; флоппи-диск двойной плотности;<BR>
5 - жесткий диск;<BR>
6 - накопитель на магнитной ленте;<BR>
7 - 1,44 М флоппи-диск (3&quot;) и прочие дисковые устройства.
</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>
Если в поле &quot;специальные функции&quot; бит <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 &lt;dos.h&gt;
#include &lt;stdio.h&gt;
#include &lt;malloc.h&gt;
#include &lt;errno.h&gt;
#include &quot;sysp.h&quot;

void main(void);
void main(void) {

         union REGS reg;
         struct SREGS segreg;
         DPB _far *dbp;
         DPB_FORMAT _far *dbp_f;

         int sectors, i;

         printf(&quot;\nПрограмма уничтожит содержимое&quot;
                          &quot;\n20-й дорожки диска А:.&quot;
                          &quot;\nЖелаете продолжить? (Y,N)\n&quot;);

// Ожидаем ответ оператора и анализируем его

         i = getch();
         if((i != 'y') &amp;&amp; (i != 'Y')) exit(-1);

// Заказываем память для блока параметров устройства

         dbp = _fmalloc(sizeof(DPB));

// Заказываем память для блока параметров устройства,
// который будет использован для форматирования

         dbp_f = _fmalloc(sizeof(DPB_FORMAT));

         if(dbp == NULL || dbp_f == NULL) {
                printf(&quot;\nМало оперативной памяти!&quot;);
                exit(-1);
         }

// Получаем текущие параметры диска А:

         dbp-&gt;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(&amp;reg, &amp;reg, &amp;segreg);

// Проверяем флаг переноса

         if(reg.x.cflag != 0) {
                printf(&quot;\nОшибка: %d&quot;,reg.x.ax);
                exit(-1);
         }

// Заполняем блок параметров для форматирования.
// Байт специальных функций содержит значение,
// равное 5. Это означает, что:
//    - используется текущий блок параметров BIOS BPB;
//    - используются все поля в блоке параметров устройства;
//    - все сектора на дорожке имеют одинаковый размер

         dbp-&gt;spec = 5;

// Считываем из BPB количество секторов на дорожке

         sectors = dbp-&gt;bpb.seccnt;

// Подготавливаем таблицу, описывающую формат дорожки

// Записываем количество секторов на дорожке

         dbp-&gt;trkcnt = sectors;

// Для каждого сектора на дорожке в таблицу
// записываем его номер и размер.
// Заметьте, что записывается размер сектора
// в байтах, а не код размера, как это делается
// при форматировании с помощью функции 05h прерывания INT13h

         for(i = 0; i &lt; sectors; i++) {
                dbp-&gt;trk[i].no   = i+1;
                dbp-&gt;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(&amp;reg, &amp;reg, &amp;segreg);

// Проверяем флаг переноса

         if(reg.x.cflag != 0) {
                printf(&quot;\nОшибка: %d&quot;,reg.x.ax);
                exit(-1);
         }

// Подготавливаем блок параметров устройства,
// который будет использован при вызове
// операции проверки возможности форматирования
// дорожки

// В поле специальных функций записываем 1,
// это означает, что будет выполняться проверка
// возможности использования указанного формата дорожки

         dbp_f-&gt;spec = 1;
         dbp_f-&gt;head = 0;
         dbp_f-&gt;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(&amp;reg, &amp;reg, &amp;segreg);

// Проверяем флаг переноса

         if(reg.x.cflag != 0) {
                printf(&quot;\nОшибка: %d&quot;,reg.x.ax);
                exit(-1);
         }

// Если указанный формат дорожки поддерживается,
// поле специальных функций будет содержать 0.
// Проверяем это.

         if(dbp_f-&gt;spec != 0) {
                printf(&quot;\nФормат дорожки не поддерживается!&quot;);
                exit(-1);
         }

// Заполняем блок параметров для выполнения
// операции форматирования

         dbp_f-&gt;spec = 0;
         dbp_f-&gt;head = 0;
         dbp_f-&gt;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(&amp;reg, &amp;reg, &amp;segreg);

// Проверяем флаг переноса

         if(reg.x.cflag != 0) {
                printf(&quot;\nОшибка: %d&quot;,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 &lt;dos.h&gt;
#include &lt;stdio.h&gt;
#include &lt;malloc.h&gt;
#include &lt;errno.h&gt;
#include &quot;sysp.h&quot;

void main(void);
void main(void) {

         union REGS reg;
         struct SREGS segreg;
         DPB_WR _far *dbp_wr;
         char buf[2000];

         int sectors, i;

         printf(&quot;\nПрограмма уничтожит содержимое&quot;
                          &quot;\n20-й дорожки диска А:.&quot;
                          &quot;\nЖелаете продолжить? (Y,N)\n&quot;);

// Ожидаем ответ оператора и анализируем его

         i = getch();
         if((i != 'y') &amp;&amp; (i != 'Y')) exit(-1);


// Заказываем память для блока параметров устройства,
// который будет использован для чтения/записи

         dbp_wr = malloc(sizeof(DPB_WR));

         if(dbp_wr == NULL) {
                printf(&quot;\nМало оперативной памяти!&quot;);
                exit(-1);
         }


// Заполняем блок параметров для выполнения
// операции чтения.
// Мы будем читать первые два сектора
// на нулевой дорожке, головка 0.

         dbp_wr-&gt;spec = 0;
         dbp_wr-&gt;head = 0;
         dbp_wr-&gt;track = 0;
         dbp_wr-&gt;sector = 0;
         dbp_wr-&gt;sectcnt = 2;
         dbp_wr-&gt;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(&amp;reg, &amp;reg, &amp;segreg);

// Проверяем флаг переноса

         if(reg.x.cflag != 0) {
                printf(&quot;\nОшибка: %d&quot;,reg.x.ax);
                exit(-1);
         }


// Заполняем блок параметров для выполнения
// операции записи.
// Только что прочитанные два сектора нулевой
// дорожки будут записаны на 20-ю дорожку.

         dbp_wr-&gt;spec = 0;
         dbp_wr-&gt;head = 0;
         dbp_wr-&gt;track = 20;
         dbp_wr-&gt;sector = 0;
         dbp_wr-&gt;sectcnt = 2;
         dbp_wr-&gt;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(&amp;reg, &amp;reg, &amp;segreg);

// Проверяем флаг переноса

         if(reg.x.cflag != 0) {
                printf(&quot;\nОшибка: %d&quot;,reg.x.ax);
                exit(-1);
         }


// Освобождаем буфер

         free(dbp_wr);

         exit(0);
}</FONT>
</PRE>
</BODY>
</HTML>
Соседние файлы в папке 3 Том