www.pudn.com > minix.instalation.cd-rom-2.0.rar > DISK_IO.CPP


/*  
	FIPS - the First nondestructive Interactive Partition Splitting program  
  
	Module disk_io.cpp  
  
	RCS - Header:  
	$Header: c:/daten/fips/source/main/RCS/disk_io.cpp 1.4 1995/01/19 00:00:51 schaefer Exp schaefer $  
  
	Copyright (C) 1993 Arno Schaefer  
  
	This program is free software; you can redistribute it and/or modify  
	it under the terms of the GNU General Public License as published by  
	the Free Software Foundation; either version 2 of the License, or  
	(at your option) any later version.  
  
	This program is distributed in the hope that it will be useful,  
	but WITHOUT ANY WARRANTY; without even the implied warranty of  
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
	GNU General Public License for more details.  
  
	You should have received a copy of the GNU General Public License  
	along with this program; if not, write to the Free Software  
	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
  
  
	Report problems and direct all questions to:  
  
	schaefer@rbg.informatik.th-darmstadt.de  
*/  
  
#include "disk_io.h"  
#include   
#include   
  
#define DISK_INT 0x13  
  
#define RESET_DISK 0  
#define READ_SECTOR 2  
#define WRITE_SECTOR 3  
#define VERIFY_SECTOR 4  
#define GET_DRIVE_PARAMS 8  
#define GET_DISK_TYPE 0x15  
  
  
/* ----------------------------------------------------------------------- */  
/* Bios call to get the number of drives attached                          */  
/* ----------------------------------------------------------------------- */  
  
int get_no_of_drives (void)  
{  
	union REGS regs;  
  
	regs.h.ah = GET_DRIVE_PARAMS;  
	regs.h.dl = 0x80;  
	int86 (DISK_INT, ®s, ®s);  
  
	if (regs.h.ah != 0) return (1); // will be checked again  
	return (regs.h.dl);  
}  
  
  
/* ----------------------------------------------------------------------- */  
/* Calculates physical sector number (Head, Cylinder, Sector).             */  
/* Log_sector is absolute logical sector number (0 = master boot record).  */  
/* ----------------------------------------------------------------------- */  
  
physical_sector_no::physical_sector_no  
(  
	dword logical_sector,  
	const drive_geometry &geometry  
)  
{  
	cylinder =  
		logical_sector  
		/ (geometry.heads * geometry.sectors);  
  
	head =  
	(  
		logical_sector  
		- (cylinder * geometry.heads * geometry.sectors)  
	)  
	/ geometry.sectors;  
  
	sector =  
		logical_sector  
		- (cylinder * geometry.heads * geometry.sectors)  
		- (head * geometry.sectors)  
		+ 1;  
}  
  
  
/* ----------------------------------------------------------------------- */  
/* Bios call get_drive_geometry, returns error status in var errorcode     */  
/* ----------------------------------------------------------------------- */  
  
void physical_drive::get_geometry (void)  
{  
	union REGS regs;  
  
	regs.h.ah = GET_DRIVE_PARAMS;  
	regs.h.dl = number;  
	int86 (DISK_INT, ®s, ®s);  
  
	if ((errorcode = regs.h.ah) != 0) return;  
  
	geometry.heads = (dword) regs.h.dh + 1;  
	geometry.sectors = (dword) regs.h.cl & 0x3f;  
	geometry.cylinders =  
	(  
		(dword) regs.h.ch  
		| (((dword) regs.h.cl << 2) & 0x300)  
	) + 1;  
}  
  
  
/* ----------------------------------------------------------------------- */  
/* Bios call reset_drive, returns error status in var errorcode            */  
/* ----------------------------------------------------------------------- */  
  
void physical_drive::reset (void)  
{  
	union REGS regs;  
  
	regs.h.ah = RESET_DISK;  
	regs.h.dl = number;  
	int86 (DISK_INT, ®s, ®s);  
  
	errorcode = regs.h.ah;  
}  
  
  
/* ----------------------------------------------------------------------- */  
/* Initialization physical_drive, requires drive number.                   */  
/* Calls get_drive_geometry, errorcode contains return status              */  
/* ----------------------------------------------------------------------- */  
  
physical_drive::physical_drive (int number)  
{  
	physical_drive::number = number;  
	get_geometry ();  
};  
  
  
/* ----------------------------------------------------------------------- */  
/* Initialization physical_drive with physical_drive object                */  
/* ----------------------------------------------------------------------- */  
  
physical_drive::physical_drive (physical_drive &pd)  
{  
	number = pd.number;  
	errorcode = pd.errorcode;  
	geometry = pd.geometry;  
}  
  
  
/* ----------------------------------------------------------------------- */  
/* Assignment operator for physical drive                                  */  
/* ----------------------------------------------------------------------- */  
  
void physical_drive::operator= (physical_drive &pd)  
{  
	number = pd.number;  
	errorcode = pd.errorcode;  
	geometry = pd.geometry;  
}  
  
  
/* ----------------------------------------------------------------------- */  
/* Read sector                                                             */  
/* ----------------------------------------------------------------------- */  
  
int physical_drive::read_sector (struct sector *sector, dword sector_number)  
{  
	physical_sector_no p (sector_number, geometry);  
  
	boolean done = false;  
  
	for (int i=0; i<3; i++)  
	{  
		if (biosdisk  
		(  
			READ_SECTOR,  
			number,  
			p.head,  
			p.cylinder,  
			p.sector,  
			1,  
			sector->data  
		) == 0)  
		{  
			done=true;  
			break;  
		}  
  
		reset ();  
	}  
  
	if (!done) return (-1);  
	return 0;  
}  
  
  
/* ----------------------------------------------------------------------- */  
/* Write sector with verify                                                */  
/* ----------------------------------------------------------------------- */  
  
int physical_drive::write_sector (struct sector *sector, dword sector_number)  
{  
	physical_sector_no p (sector_number,geometry);  
  
	boolean done = false;  
  
	for (int i=0; i<3; i++)  
	{  
		if (biosdisk  
		(  
			WRITE_SECTOR,  
			number,  
			p.head,  
			p.cylinder,  
			p.sector,  
			1,  
			sector->data  
		) == 0)  
		{  
			done=true;  
			break;  
		}  
  
		reset ();  
	}  
  
	if (!done) return (-1);  
  
	if (biosdisk  
	(  
		VERIFY_SECTOR,  
		number,  
		p.head,  
		p.cylinder,  
		p.sector,  
		1,  
		sector->data  
  
	) != 0) return (-1);  
  
	return 0;  
}  
  
  
/* ----------------------------------------------------------------------- */  
/* Bios call get_disk_type - returns 0 if drive not present.               */  
/* Valid drive numbers: 0 - 255, result: 1 - floppy without disk change    */  
/* detection, 2 - floppy with disk change detection, 3 - harddisk          */  
/* ----------------------------------------------------------------------- */  
  
int get_disk_type (int drive_number)  
{  
	union REGS regs;  
  
	regs.h.ah = GET_DISK_TYPE;  
	regs.h.dl = drive_number;  
	int86 (DISK_INT, ®s, ®s);  
  
	if (regs.x.cflag) return 0;  
	return (regs.h.ah);                     // disk type  
}