Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

MS-DOS для программиста

© Александр Фролов, Григорий Фролов
Том 19, М.: Диалог-МИФИ, 1995, 253 стр.

[Назад] [Содеожание] [Дальше]

1.7. Функция _bios_disk

Стандартная библиотека Borland C++ содержит специальную функцию _bios_disk , облегчающую работу с диском на уровне BIOS. Эта функция описана в файле 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 и указать соответствующий параметр funct.

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

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

Программа FDBIOS

Приведем пример программы FDBIOS (листинг 1.6), которая читает первый сектор нулевой дорожки (нулевая головка) диска А: и записывает его содержимое в файл. В случае ошибки программа пытается прочесть сектор три раза.


Листинг 1.6. Файл fdbios\ fdbios.cpp


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

char diskbuf[512];

void main(void)
{
  unsigned status = 0, i;
  struct diskinfo_t di;
  FILE  *sect;

  // Открываем файл, в который будем записывать
  // содержимое самого первого сектора дискеты
  sect = fopen ("!sector.dat","wb+");

  di.drive    = 0;
  di.head     = 0;
  di.track    = 0;
  di.sector   = 1;
  di.nsectors = 1;
  di.buffer   = (void far*)diskbuf;

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

  // Выводим содержимое считанного сектора в файл
  for(i=0; i<512; i++) fputc (diskbuf[i], sect);
  fclose (sect);
}

Программа FDFORMAT

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

Программа FDFORMAT (листинг 1.7) форматирует 20 дорожку дискеты, установленной в НГМД А:.


Листинг 1.7. Файл fdformat\ fdformat.cpp


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

typedef struct _DPT _
{
  unsigned char srt_hut;
  unsigned char dma_hlt;
  unsigned char motor_w;
  unsigned char sec_size;
  unsigned char eot;
  unsigned char gap_rw;
  unsigned char dtl;
  unsigned char gap_f;
  unsigned char fill_char;
  unsigned char hst;
  unsigned char mot_start;
} DPT ;

DPT  far *get_dpt(void);

// Номер форматируемой дорожки
#define TRK 20

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

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

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   = (void far*)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;
}

/**
* get_dpt
*
* Вычислить адрес таблицы параметров дискеты
*
* Функция возвращает указатель на таблицу
* параметров дискеты
*
**/
DPT  far *get_dpt(void)
{
  void far * far *ptr;
  ptr = (void far * far *)MK_FP(0x0, 0x78);
  return(DPT  far*)(*ptr);
}

[Назад] [Содеожание] [Дальше]