TURBO PASCAL

Новости

Программы   

Turbo Pascal 

Игры

Документация   

Странности

FAQ

Ссылки

Форум

Гостевая книга

Рассылка

Благодарности

Об авторе

 

 

3.2.2. Поддержка дисков в ДОС

Функции 2 и 3 прерывания $13 позволяют прочитать или записать любой сектор на любом диске. Однако формат обращения к этому прерыванию требует задания нескольких несущественных для программиста, но важных для правильной работы программы параметров, таких как номера головки, цилиндра, сектора на дорожке. Кроме того, это прерывание игнорирует разбивку жесткого диска на логические разделы, что обычно вызывает определенные неудобства, т.к. формат и размещение описателей логических разделов зависят от используемой программы обслуживания логических дисков, например FDisk или Disk Manager. Поэтому для операций чтения/записи чаще используются два специальных прерывания ДОС с векторами $25 и $26. Первое из них реализует чтение, а второе — запись информации. В этих прерываниях ДОС (не путайте с функциями ДОС) принят одинаковый формат использования регистров для обмена управляющей информацией с программой пользователя:

Вход: АХ — номер диска (О—А, 1—В, 2—С и т.д.);

DX — номер сектора;

СХ — количество секторов;

DS:BX = адрес буфера. Выход: CF = 1, если была обнаружена ошибка, иначе 0;

Работа с диском на физическом уровне__________ ____ 77

AX — код ошибки (если CF=1).

Для дисков большой емкости (больше 32 Мбайт) регистр DX не используется, регистр СХ должен содержать $FFFF (признак обращения к большому диску), а регистры DS:BX содержат адрес такой структуры данных:

type

TLargeDisk = record

StartSec: Longint; {Номер сектора} Nsecs : Word; {Количество секторов) AdrBuf : Pointer; {Адрес буфера}

end;

При реализации доступа к прерываниям $25 и $26 следует учесть, что в процессе их обработки ДОС помещает в вершину стека «лишнее» слово (состояние регистра флагов). По этой причине обращение к прерываниям с помощью стандартной процедуры INTR невозможно, т.к. не обеспечивается правильный выход из процедуры. Кроме того, изменяется содержимое регистров DS и ВР, которые, следовательно, нужно где — то (обычно в стеке) сохранить перед вызовом прерывания, чтобы после завершения обработки прерывания восстановить сохраненные значения. Вот почему доступ к прерываниям $25 и $26 можно программировать только с помощью ассемблера (см., например, процедуру ReadWriteSector в модуле FJDisk).

Среди многочисленных функций ДОС есть несколько весьма полезных при работе с диском. Это прежде всего функция $32. Стандартная документация по MS-DOS не содержит никаких сведений об этой функции. Говорят, что эта функция недокументирована. В отличие от остальных функций недокументированные функции могут не работать в других версиях ДОС (например, в более поздних версиях или в альтернативных разработках конкурирующих фирм). Функция $32 работает в версии 5.0, а также в версиях 4.х, З.х и 2.х MS-DOS. Она возвращает информацию о диске, которую, в принципе, можно получить и из других источников, например из ВРВ или с помощью функции 8 прерывания $13. Достоинством функции $32 является то, что информация о диске собирается воедино в структуру данных следующего типа:

type

PDrvInfo_Type ^DrvInfc^Type;

DrvInfo_Type = record

Drv Byte; {Номер диска: 0-A, 1-В и т.д.}

SubDrv Byte; {Номер устройства внутри драйвера}

SecSize Word; {Размер сектора в байтах}

SecClus Byte; {Количество секторов в кластере минус 1}

ExpClus Byte; {Сдвиг номера кластера}

Boots Word; {Количество загрузочных и резервных секторов}

FatCnt Byte; {Количество копий FAT}

RootSiz Word; {Количество элементов корневого каталога}

DataSec Word {Номер первого сектора данных} MaxClus Word {Максимальный номер кластера} FatSize Byte {Количество секторов в FAT} _•_-------------_ ддя. MS-DOS 2.х ————————}

RootSec Word {Номер первого сектора корневого каталога}

Head Pointer; {Адрес заголовка драйвера устройства}

Media Byte {Дескриптор носителя}

AccesF Byte {Флаг доступности устройства}

Next PDrvInfo_Type{Ссылка на следующий элемент списка}

DirClus : Word; {Номер начального кластера текущего

каталога или 0 для корневого каталога} DirPath : array [1..64] of Char; {Путь к текущему

каталогу в формате ASCIIZ (с нулем в конце)} {--_---..- ------ для MS-DOS З.х ——-——————}

RootSec Word; {Номер первого сектора корневого каталога}

Head Pointer; {Адрес заголовка драйвера устройства}

Media Byte; {Дескриптор носителя)

AccesF Byte; {Флаг доступности устройства}

Next PDrvInfo Type{Ссылка на следующий элемент списка}

Reserv Word; {Имеет значение 0}

Build Word; {Имеет значение $FFFF,

если данные построены заново} {-—-————Для MS-DOS 4.х и 5.0 ——————}

Reservl Word; {Имеет значение 0} RootSec Word; {Номер первого сектора

корневого каталога} Head Pointer; {Адрес заголовка драйвера устройства} Media Byte; {Дескриптор носителя} AccesF Byte; {Флаг доступности} Next PDrvInfo_Type{Ссылка на следующий элемент списка} Reserv2 Word; {Имеет значение 0} Build Word; {Имеет значение $FFFF,

если данные построены заново} end; {DrvInfo_Type}

В этой структуре поле ExpClus содержит целое число, показывающее, на сколько разрядов влево нужно сместить номер кластера, чтобы получить номер сектора (количество секторов в кластере всегда равно степени 2, т.е.

Размер_кластера = 2s,

таким образом ExpClus = N). Поле BootS фактически содержит номер сектора, в котором начинается FAT, поля DataSec и RootSec определяют начало соответственно области данных диска и корневого каталога.

При обращении к этой функции регистры процессора используются следующим образом. Вход: АН = $32;

DL — номер диска (0 — текущий, 1—А и т.д.). Выход: AL = 0 — нет ошибок

Работа с диском на физическом уровне 79

= $FF — задан неверный номер диска;

DS:BX — адрес блока информации.

Например, следующая программа читает блок информации о диске и выясняет, в соответствии с какими версиями MS-DOS он построен.

Uses DOS;

type

PDrvInfo = "DrvInfo;

Drvlnfo = record

a: array [0..15] of Byte;

Reserv: Byte; {Признак версий 4.х и выше} b: array [17..27] of Byte;

Reservl: Word end;

var

R: Registers;

P: PDrvInfo;

begin

with R do begin

ah := $32; (Номер функции ДОС} al := 2; {Для диска С:} MSDOS(R) ;

if aloO then

WriteLn('Ошибка обращения к функции: AL = ',а1) else begin

P := ptr(ds,bx) ;

if P^.Reserv^O then

WriteLn('Версия MS-DOS 4.0 и выше') else

if P^-ReservloO then

WriteLn('Версия MS-DOS 3.x') else

WriteLn('Версия MS-DOS 2.x') end end end.

Поскольку функция $32 может не работать в других версиях ДОС, ею следует пользоваться с осторожностью1. В описываемом в п.3.3 модуле F_Disk реализованы приблизительно такие же функции, но с использованием только документированных возможностей MS-DOS. Эти возможности реализуются так называемым общим вызовом IOCTL (Input/Output ConTroL — управление вводом/выводом). IOCTL представляет собой соглашение об интерфейсе (способе обмена данными) между ДОС и

' На моем ПК используется MS-DOS 6.20. Мне не удалось получить информацию о диске С помощью функции $32.

работающими в ней драйверами устройств ввода/вывода. Этому соглашению обязаны следовать все драйверы (в том числе и разработанные пользователями) для версий MS-DOS, начиная с 2.0 и выше.

Общий вызов IOCTL реализуется прерыванием $21 ДОС со следующими значениями регистров:

АН == $44 (функция $44 ДОС реализует вызов IOCTL)

AL = $OD (подфункция $OD - общий вызов IOCTL)

BL - номер диска (0 - текущий, 1 - А и т.д.)

СН - $08 (код категории устройства: $08 - дисковое устройство)

CL - операция:

$40 - установить параметры устройства

$41 - записать дорожку

$42 - форматировать дорожку

$60 - получить параметры устройства

$61 - прочитать дорожку

$62 - проверить дорожку DS:BX - адрес указателя на блок параметров

При возврате из функции флаг переноса CF содержит 0, если обращение было без ошибок, и 1, если обнаружена ошибка. В случае ошибки регистр АХ содерж IT код ошибки.

Формат блока параметров, адрес которого указывается в регистрах DS:BX, зависит от выполняемой операции.

Получить/установить параметры устройства CL = $б0/$40

При использовании этой операции блок параметров должен соответствовать такой структуре данных:

type

Tracks_Type = record

Trek: Byte; {Номер сектора}

Size: Byte {Длина сектора} end;

IOCTL_Info_Type = record

Control Byte; {Управляющий байт}

TypeDrv Byte; {Тип диска}

Attrib Word; {Атрибуты диска}

Cylindrs Word; {Число цилиндров}

Media Byte; {Тип носителя}

BPB ВРВ_Туре;

Add Add_BPB_Type;

Reserv array [1..1O] of Byte;

Sectors Word; {Количество секторов на дорожке}

Tracks {Образ дорожки}

array [1..Sectors] of Tracks_type

end;

При обращении к операции $60 (получить параметры) в поле Control используется только один младший бит 0: значение 0 этого бита указывает на то, что надо дать умалчиваемое значение ВРВ (т.е. то, которое хранится в драйвере), а значение 1 требует от драйвера построить блок параметров BIOS заново. К сожалению, операция $60 не поддерживает диски большой емкости и в этом случае возвращает нулевое количество секторов в поле BPB.TotSecs.

В операции $40 (установить параметры) используются три младших бита поля Control:

бит 0: значение 0 заставляет драйвер использовать ВРВ, подготовленный в этом вызове, а значение 1 — умалчиваемый ВРВ;

• бит 1: значение 1 указывает на то, что драйвер должен игнорировать все данные из блока параметров этого вызова, за исключением образа дорожки;

• бит 2: значение 1 сообщает драйверу, что все секторы на дорожке

имеют одинаковый размер.

Поля TypeDrv, Attrib и Cylindrs в операциях $40 и $60 заполняются драйвером. В поле TypeDrv драйвер возвращает тип устройства:

0-360 Кбайт дискета диаметром 51 / ^ дюйма 1-1.2 Мбайт дискета, 51/^ дюйма

2 - 720 Кбайт дискета, З1/^ дюйма

3 - 160 Кбайт дискета диаметром 8 дюймов

4 - 320 Кбайт дискета, 8 дюймов

5 - жесткий диск

6 - магнитная лента

7 - 1.44 Мбайт дискета, 31/^ дюйма и другие дисковые устройства

Атрибуты устройства возвращаются драйвером в поле Attrib. В этом поле используются только два младших бита:

• бит 0 — признак заменяемости носителя (1 — не заменяется);

• бит 1 — признак возможности аппаратного контроля замены дискеты (1 — есть контроль).

В поле Cylindrs драйвер записывает полное количество цилиндров на физическом устройстве.

Поле Media заполняется драйвером при вызове операции $60 и программой при вызове операции $40. Это поле конкретизирует вид носителя для ГД, поддерживающих различные форматы дискет. Например, для S^/^—f^towiowro привода, рассчитанного на 1,2 Мбайт, значение 0 этого поля сообщает, что используется дискета емкостью 1,2 Мбайт, а 1 — емкостью 360 Кбайт.

Поля ВРВ и Add заполняются драйвером при обращении к операции $60 и подготавливаются программой при обращении к операции $40. Структура этих полей рассмотрена в п.3.1.1.

Поля Sectors и Tracks используются только в функции $40 и заполняются программой. В них драйверу сообщается полное количество сек

торов на дорожке (поле Sectors) и описание каждого сектора (поле Tracks). Таким образом, длина поля Tracks зависит от текущего количества секторов на дорожке.

Записать/прочитать дорожку

CL = $41/$61 Структура блока параметров:

type

IOCTL_Read_Write__Type = record

Control Byte; /Всегда содержит 0} Head Word; {Номер головки) Cyl Word; {Номер дорожки}

Sec Word; {Номер сектора; нумерация начинается с 0} MaxSec Word; {Максимальный номер сектора на дорожке} Buf Pointer {Адрес буфера для обмена данными} end;

Обратите внимание: при обращении к IOCTL нумерация секторов, головок и цилиндров начинается с нуля (при обращении к прерыванию $13 секторы нумеруются, начиная с единицы). Таким образом, поле MaxSec содержит количество секторов на дорожке минус 1.

Форматировать/проверить дорожку CL = $42/$62

При обращении к этим функциям блок параметров имеет такую структуру:

type

IOCTL_Format_Type = record

Control: Byte; {Управляющий байт}

Head : Word; {Номер головки}

Track : Word; (Номер дорожки} end;

В поле Control используется только младший бит. При входе его значение 0 указывает на необходимость форматирования дорожки, а значение 1 — проверить, поддерживается ли нестандартный формат дорожки. При выходе значение 0 в этом бите означает, что указанный образ дорожки может использоваться, а значение 1 — не может использоваться.

В заключение обзора возможностей ДОС отмечу еще две полезные функции, функция с номером $Е устанавливает текущий диск (диск по умолчанию). Диск задается содержимым регистра DL перед обращением к функции, после возврата регистр AL содержит общее количество логических дисков, установленных на данном компьютере, функция $19 возвращает в регистре AL номер текущего (умалчиваемого) диска.

 

Глава 3

Оглавление

На первую страницу

Rambler's Top100 Rambler's Top100
PROext: Top 1000

(с)Все права защищены

По всем интересующим вопросам прошу писать на электронный адрес

Hosted by uCoz