Операционная система MS DOS (том 2)

         

Функция _bios_disk()


Стандартная библиотека трансляторов Microsoft QC .01, QC .5, C .0 содержит специальную функцию, облегчающую работу с диском на уровне BIOS - _bios_disk(). Эта функция требует использования файла bios.h

и описана следующим образом:

unsigned _bios_disk(unsigned funct, struct diskinfo_t *diskinfo);

Параметр funct задает выполняемую функцию, параметр diskinfo - это указатель на структуру, описывающую необходимые параметры, такие как номер дорожки, номер головки и т.д.:

struct diskinfo_t { unsigned drive; // Номер дисковода unsigned head; // Номер головки unsigned track; // Номер дорожки unsigned sector; // Номер первого сектора unsigned nsectors; // Количество читаемых, // записываемых // или сравниваемых секторов void far *buffer; // Адрес буфера в памяти };

Перед использованием функции _bios_disk() программа должна заполнить поля структуры diskinfo и вызвать _bios_disk() с соответствующим параметром funct.

Файл bios.h содержит константы для следующих значений параметра funct:



_DISK_FORMAT Форматирование дорожки, описанной параметром diskinfo функции _bios_disk(). Для этой функции программа должна задать в структуре diskinfo номер дисковода, для которого выполняется форматирование, номера головки и форматируемой дорожки. Указатель buffer программа должна установить на подготовленный буфер формата, описанный выше. Необходимо выполнить все подготовительные действия, связанные с настройкой контроллера НГМД и таблицы параметров дискеты.
_DISK_READ Чтение одного или нескольких секторов диска. Эта функция аналогична функции 2 прерывания INT 13h. Если при чтении секторов произошла ошибка, ее код будет возвращен функцией _bios_disk() в старшем байте. При успешном завершении операции функция возвращает 0.
_DISK_WRITE Запись одного или нескольких секторов на диск. Функция аналогична предыдущей, за исключением того, что данные из буфера записываются на диск.
_DISK_RESET Сброс контроллера НГМД. Для этой функции не надо заполнять структуру diskinfo, ее содержимое игнорируется. Сброс контроллера выполняют после того, как произошла ошибка при выполнении другой операции, например, чтения или записи. После сброса можно попробовать повторить выполнение операции.
_DISK_STATUS Получение состояния НГМД после выполнения последней операции. Старший байт возвращаемого функцией bios_disk() значения содержит байт состояния.
_DISK_VERIFY Проверка диска. С помощью этой функции можно убедиться в том, что указанные сектора существуют и могут быть прочитаны в память. Дополнительно выполняется циклический избыточный тест (CRC). Функция проверки диска использует все поля структуры diskinfo. При ошибке старшие 8 битов возвращаемого функцией значения содержат байт состояния.
<
Приведем пример программы, читающей первый сектор нулевой дорожки (нулевая головка) диска А:. В случае ошибки программа пытается прочесть сектор три раза:

#include <stdio.h> #include <conio.h> #include <bios.h> #include <dos.h> #include <stdlib.h>

char _far diskbuf[512];

void main(void);

void main(void) {

unsigned status = 0, i; struct diskinfo_t di;

di.drive = 0; di.head = 0; di.track = 0; di.sector = 1; di.nsectors = 1; di.buffer = diskbuf;

for(i = 0; i < 3; i++) { status = _bios_disk(_DISK_READ, &di) >> 8; if( !status ) break; }

}

Последний пример, который мы приведем перед тем, как закончить с работой диска на физическом уровне, это форматирование дорожки. Сейчас мы будем использовать стандартное форматирование. Как отформатировать дорожку нестандартным образом, вы узнаете в разделе, посвященном защите информации от несанкционированного копирования. Там же будет приведен соответствующий пример.

Приведенная ниже программа форматирует 20-ю дорожку дискеты, установленной в дисковод А:.

#include <stdio.h> #include <conio.h> #include <dos.h> #include <stdlib.h> #include <bios.h> #include "sysp.h"

// Номер форматируемой дорожки

#define TRK 20

// Код размера сектора - 512 байт

#define SEC_SIZE 2

union REGS inregs, outregs; char _far diskbuf[512];

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

struct diskinfo_t di; unsigned status; unsigned char old_sec_size, old_fill_char, old_eot; int i, j; DPT _far *dpt_ptr;

// Получаем адрес таблицы параметров дискеты

dpt_ptr = get_dpt();

// Сохраняем старые значения из таблицы параметров

old_sec_size = dpt_ptr->sec_size; old_fill_char = dpt_ptr->fill_char; old_eot = dpt_ptr->eot;

// Устанавливаем в таблице параметров дискеты // код размера сектора, символ заполнения при // форматировании, количество секторов на дорожке

dpt_ptr->sec_size = SEC_SIZE; dpt_ptr->fill_char = 0xf8; dpt_ptr->eot = 15;

// Устанавливаем тип диска



inregs.h.ah = 0x17; inregs.h.al = 3; inregs.h.dl = 0; int86(0x13, &inregs, &outregs);

// Устанавливаем среду для форматирования

inregs.h.ah = 0x18; inregs.h.ch = TRK; inregs.h.cl = dpt_ptr->eot; inregs.h.dl = 0; int86(0x13, &inregs, &outregs);

// Подготавливаем параметры для функции форматирования

di.drive = 0; di.head = 0; di.track = TRK; di.sector = 1; di.nsectors = 15; di.buffer = diskbuf;

// Подготавливаем буфер формата для 15-ти секторов

for(i=0, j=1; j<16; i += 4, j++) { diskbuf[i] = TRK; diskbuf[i+1] = 0; diskbuf[i+2] = j; diskbuf[i+3] = SEC_SIZE; }

// Вызываем функцию форматирования дорожки

status = _bios_disk(_DISK_FORMAT, &di) >> 8; printf("\nФорматирование завершилось с кодом: %d",status);

// Восстанавливаем старые значения в // таблице параметров дискеты

dpt_ptr->sec_size = old_sec_size; dpt_ptr->fill_char = old_fill_char; dpt_ptr->eot = old_eot;

}


Содержание раздела