/* PARKHARD.C

   program to park hard disk drives

   portions Copyright (c) Thomas P. Keller 1987
   portions Copyright (c) Borland International 1987
   All Rights Reserved.
*/

/**********************************************************************

This program reads the hard disk parameters from the drive parameter
table by invoking bios interupt 0x13 function 0x8 and then parks the
drive heads on the cylinder 1 past the last one used by DOS

**********************************************************************/


#include <stdio.h>
#include <dos.h>

void main()
	{
	union REGS outregs;

	unsigned int drive_no, max_drives,error_flag,error_code;

	void get_drive_parms(unsigned int drive_no, union REGS *regs);
	void park_drive(unsigned int drive_no, union REGS *regs);
	void print_drive_error(unsigned char error_code);	

	printf("\nHard Disk Park Program\n");
	printf("Copyright (c) Thomas P. Keller & Borland International 1987\n");
	printf("All Rights Reserved\n");
	drive_no = 0;	/* drive c: */

	get_drive_parms( drive_no, &outregs);

	max_drives = outregs.h.dl;
	error_flag = outregs.x.cflag;
	error_code = outregs.h.ah;

	if (error_flag != 0)
		print_drive_error(error_code);
	else {

		if (max_drives == 0)
			printf("\nNo hard disks installed\n\n");
		else
		{
			printf("\nNumber of hard disks = %2hu\n\n",max_drives);
			do {
				get_drive_parms( drive_no, &outregs);
		 		park_drive( drive_no, &outregs);
				drive_no = drive_no + 1;
			} while (drive_no < max_drives);
		}
	}
	return;
}
/* end of main */

/* functions */

void get_drive_parms(unsigned int drive_no, union REGS *regs)
{
	#define DISK    0x13

	regs->h.ah = 0x08;	/* get drive parameters */
	regs->h.al = 0x00;
	regs->h.dh = 0x00;
	regs->h.dl = 0x80+drive_no;	/* drive number +0x80 */
	regs->h.cl = 0x00;
	regs->h.ch = 0x00;
	regs->x.cflag = 0x00;

	int86(DISK, regs, regs);

	return;
}

void park_drive(unsigned int drive_no, union REGS *regs)
{

	unsigned char error_code;

	unsigned int error_flag,max_heads,max_sectors,max_cylinders,max_tracks;

	void print_drive_error(unsigned char error_code);	

	#define DISK    0x13

	max_tracks = regs->h.ch + ((regs->h.cl & 0xc0)<<2) + 1;

	printf ("Parking hard disk number %2u at cylinder number %4u\n",drive_no+1,max_tracks);

	regs->h.ah = 0x0c;	/* seek cylinder */
	regs->h.al = 0x00;
	regs->h.dh = 0x00;
	regs->h.dl = 0x80+drive_no;	/* drive number +0x80 */
	regs->h.ch = max_tracks & 0xff; /* low bits of track */
	regs->h.cl = ((max_tracks & 0x300) >> 2) + 1; /* high bits of track + sector 1 */
	regs->x.cflag = 0x00;

	int86(DISK, regs, regs);

	error_flag = regs->x.cflag;
	error_code = regs->h.ah;

	if (error_flag != 0) {
		print_drive_error(error_code);
		printf("\n");
		}
	else
		printf("Drive parked successfully\n\n");

	return;
}

/* end of  */


void print_drive_error(unsigned char error_code)
{

	printf("\nBios Interrupt 19 Error Code Recieved\n");

	if ((error_code & 0x01) == 0x01)
		printf("Bad Command\n");
	if ((error_code & 0x02) == 0x02) 
		printf("Address Mark Not Found\n");
	if ((error_code & 0x03) == 0x03) 
		printf("Write Attempted on Write-Protected Disk\n");
	if ((error_code & 0x04) == 0x04)
		printf("Sector Not Found\n");
	if ((error_code & 0x06) == 0x06) 
		printf("Diskette Removed\n");
	if ((error_code & 0x08) == 0x08) 
		printf("DMA Overrun\n");
	if ((error_code & 0x09) == 0x09) 
		printf("DMA Across 64k Boundary\n");
	if ((error_code & 0x10) == 0x10) 
		printf("Bad CRC\n");
	if ((error_code & 0x20) == 0x20) 
		printf("Controller Failure\n");
	if ((error_code & 0x40) == 0x40)
		printf("Seek Failed\n");
	if ((error_code & 0x80) == 0x80) 
		printf("Time Out\n");
	if ((error_code & 0xFF) == 0xFF) 
		printf("Unknown Error\n");

    return ;

}

/* end of program */
