Category : C Source Code
Archive   : MSCHRT3.ZIP
Filename : SEEKTEST.C

 
Output of file : SEEKTEST.C contained in archive : MSCHRT3.ZIP
/*---------------------------------------------------------------------------
| Program SEEKTEST.C |
| |
| This program demonstrates the use of MSCHRT in timing seek performance |
| of a PC based hard disk drive. The method used will determine the total|
| seek time of the device which includes actual disk seek, controller |
| overhead, and ROM BIOS overhead. This is a "real world" measurement |
| of disk performance under actual usage conditions. |
| |
| This program uses both inline generic timers and BIOS interrupt |
| timers to measure disk performance. |
| |
| (c)1989 Ryle Design, P.O. Box 22, Mt. Pleasant, Michigan 48804 |
| |
| V3.00 Microsoft C Shareware Evaluation Version |
---------------------------------------------------------------------------*/

#include
#include
#include
#include

#include "pchrt.h"

union REGS inregs,outregs;

long unsigned seek1, seek2, hits1, hits2, seek3, hits3;


void disk_err(int istat)
/*---------------------------------------------------------------------------
| This procedure outputs a description of an INT 13h error status, and |
| halts program exection. |
| |
| Globals referenced: none |
| |
| Arguments: (int) istat - status returned from INT 13h in AX if carry |
| flag set. |
| |
| Returns : void |
---------------------------------------------------------------------------*/
{
switch (istat)
{
case 0x00 : return; /* no error */

case 0x01 : printf("Disk error: Invalid command\n");
break;

case 0x02 : printf("Disk error: Address mark not found\n");
break;

case 0x03 : printf("Disk error: Disk is write-protected\n");
break;

case 0x04 : printf("Disk error: Requested sector not found\n");
break;

case 0x05 : printf("Disk error: Reset failed\n");
break;

case 0x06 : printf("Disk error: Floppy disk removed\n");
break;

case 0x07 : printf("Disk error: Bad parameter table\n");
break;

case 0x08 : printf("Disk error: DMA overrun\n");
break;

case 0x09 : printf("Disk error: DMA crossed 64KB boundary\n");
break;

case 0x0A : printf("Disk error: Bad sector flag set\n");
break;

case 0x0B : printf("Disk error: Bad track flag set\n");
break;

case 0x0C : printf("Disk error: Requested media type not found\n");
break;

case 0x0D : printf("Disk error: Invalid number of sectors on format\n");
break;

case 0x0E : printf("Disk error: Control data address mark detected\n");
break;

case 0x0F : printf("Disk error: DMA arbitration level out of range\n");
break;

case 0x10 : printf("Disk error: Uncorrectable CRC or ECC data error\n");
break;

case 0x11 : printf("Disk warning: ECC corrected data error\n");
return;

case 0x20 : printf("Disk error: Controller failed\n");
break;

case 0x40 : printf("Disk error: Seek failed\n");
break;

case 0x80 : printf("Disk error: Disk has timed out\n");
break;

case 0xAA : printf("Disk error: Drive not ready\n");
break;

case 0xBB : printf("Disk error: Error is undefined\n");
break;

case 0xCC : printf("Disk error: Write fault\n");
break;

case 0xE0 : printf("Disk error: Status register error\n");
break;

case 0xFF : printf("Disk error: Sense operation failed\n");
break;

default : printf("Unknown INT 13 return status %d\n",istat);
break;
}

exit(1);

} /* disk_err */


void test_disk(char disk)
/*---------------------------------------------------------------------------
| This function, which contains the actual disk test routines, does the |
| following: |
| 1. Seeks the test disk to track 0. |
| 2. Times 100 calls to seek to track 0. Since the heads are already |
| on track 0, they will not move, and a estimate of the software |
| overhead for each seek call can be made. |
| 3. Times single track seeks to all cylinders (0-1,1-2,2-3,3-4,etc). |
| This provides a measurement of single track seek time. |
| 4. Seeks from track 0 to all tracks (0-1,0-2,0-3,0-4,etc). This |
| provides average seek time for the entire disk. |
| 5. The results are reported. |
| |
| int86() is used to call the ROM BIOS. There is some software |
| overhead incurred using this method. |
| |
| Generic inline timers are used to measure disk performance. |
| |
| Globals referenced: inregs, outregs. |
| |
| Arguments: (char) disk - physical disk # - add to 0x80 for BIOS call. |
| |
| Returns : void |
---------------------------------------------------------------------------*/
{

int maxhead,maxcyl,indx;
unsigned long seek1,seek2,seek3,hits1,hits2,hits3;

inregs.h.dl = 0x80 + disk; /* get disk config */
inregs.h.ah = 0x08;
int86(0x13,&inregs,&outregs);
if (outregs.x.cflag != 0) disk_err(outregs.h.ah);

maxhead = outregs.h.dh; /* move bits to get */
maxcyl = ((outregs.h.cl & 0xC0) << 2) + outregs.h.ch; /* heads & tracks */

printf("\nPhysical drive %d shows %d cylinders, %d heads\n\n",disk,maxcyl+1,maxhead+1);

printf("Starting single track seek test ...\n");

inregs.h.ah = 0x0C; /* seek command */
inregs.h.ch = 0x00; /* track 0 */
inregs.h.cl = 0x01; /* XTs need sector bit set, or no seek */
inregs.h.dh = 0; /* head 0 */
inregs.h.dl = 0x80 + disk; /* disk # */

int86(0x13,&inregs,&outregs); /* seek to track 0 */
if (outregs.x.cflag != 0) disk_err(outregs.h.ah); /* stop on error */

for (indx=0; indx<100; indx++) /* seek to 0 100 times to get ave overhead */
{
t_entry(2);
int86(0x13,&inregs,&outregs);
t_exit(2);
}

for (indx=1; indx<=maxcyl; indx++) /* from zero, single track seek to end of disk */
{
inregs.h.ch = indx & 0x00FF; /* mask track bits and stuff in cl & ch */
inregs.h.cl = ((indx & 0x0300) >> 2) + 1; /* cl sector bit 1 for XTs */

t_entry(0);
int86(0x13,&inregs,&outregs); /* seek */
t_exit(0);

if (outregs.x.cflag != 0) disk_err(outregs.h.ah); /* stop on error */

if ((indx % 100) == 0) printf("%d ",indx); /* echo to user our progress */
}


printf("\nSeeking to all tracks ...\n");

inregs.h.ch = 0x00; /* back to track 0 for next test */
inregs.h.cl = 0x01; /* sector bit for XTs */
int86(0x13,&inregs,&outregs); /* seek */
if (outregs.x.cflag != 0) disk_err(outregs.h.ah); /* stop on errors */

for (indx=1; indx<=maxcyl; indx++) /* from track 0, seek to all tracks */
{
inregs.h.ch = indx & 0x00FF; /* mask tracks bits and stuff in cl & ch */
inregs.h.cl = ((indx & 0x0300) >> 2) + 1; /* cl sector bit 1 for XTs */

t_entry(1);
int86(0x13,&inregs,&outregs); /* seek */
t_exit(1);

if (outregs.x.cflag != 0) disk_err(outregs.h.ah); /* stop on errors */

if ((indx % 100) == 0) printf("%d ",indx); /* echo to user our progress */

inregs.h.ch = 0x00; /* go back to track 0 for next seek */
inregs.h.cl = 0x01;
int86(0x13,&inregs,&outregs);
if (outregs.x.cflag != 0) disk_err(outregs.h.ah);

}

t_ask_timer(0,&hits1,&seek1); /* query timers */
t_ask_timer(1,&hits2,&seek2);
t_ask_timer(2,&hits3,&seek3);

printf("\n\nTest of physical disk %d complete.\n",disk);
printf("Average single track seek ............. %7.3f milliseconds\n",((seek1/hits1)/1000.0) );
printf("Average seek to all tracks ............ %7.3f milliseconds\n",((seek2/hits2)/1000.0) );
printf("Estimated software overhead per seek .. %7.3f milliseconds\n\n",((seek3/hits3)/1000.0) );

t_reset(0); /* reset all timers */
t_reset(1);
t_reset(2);

} /* test_disk */


void test_disk_bios(char disk)
/*---------------------------------------------------------------------------
| This function, which contains the actual disk test routines, does the |
| following: |
| 1. Seeks the test disk to track 0. |
| 2. Times 100 calls to seek to track 0. Since the heads are already |
| on track 0, they will not move, and a estimate of the software |
| overhead for each seek call can be made. |
| 3. Times single track seeks to all cylinders (0-1,1-2,2-3,3-4,etc). |
| This provides a measurement of single track seek time. |
| 4. Seeks from track 0 to all tracks (0-1,0-2,0-3,0-4,etc). This |
| provides average seek time for the entire disk. |
| 5. The results are reported. |
| |
| int86() is used to call the ROM BIOS. There is some software |
| overhead incurred using this method. |
| |
| BIOS interrupt timers are used to measure disk performance. |
| |
| Globals referenced: inregs, outregs. |
| |
| Arguments: (char) disk - physical disk # - add to 0x80 for BIOS call. |
| |
| Returns : void |
---------------------------------------------------------------------------*/
{

int maxhead,maxcyl,indx;
unsigned long seek1,seek2,seek3,hits1,hits2,hits3;

t_bios_start(DISK);

inregs.h.dl = 0x80 + disk; /* get disk config */
inregs.h.ah = 0x08;
int86(0x13,&inregs,&outregs);
if (outregs.x.cflag != 0) disk_err(outregs.h.ah);

maxhead = outregs.h.dh; /* move bits to get */
maxcyl = ((outregs.h.cl & 0xC0) << 2) + outregs.h.ch; /* heads & tracks */

printf("\nPhysical drive %d shows %d cylinders, %d heads\n\n",disk,maxcyl+1,maxhead+1);

printf("Starting single track seek test ...\n");

inregs.h.ah = 0x0C; /* seek command */
inregs.h.ch = 0x00; /* track 0 */
inregs.h.cl = 0x01; /* XTs need sector bit set, or no seek */
inregs.h.dh = 0; /* head 0 */
inregs.h.dl = 0x80 + disk; /* disk # */

int86(0x13,&inregs,&outregs); /* seek to track 0 */
if (outregs.x.cflag != 0) disk_err(outregs.h.ah); /* stop on error */

for (indx=0; indx<100; indx++) /* seek to 0 100 times to get ave overhead */
int86(0x13,&inregs,&outregs);

t_bios_ask(DISK,0x0C,&hits1,&seek1);
t_bios_reset(DISK,0x0C);

for (indx=1; indx<=maxcyl; indx++) /* from zero, single track seek to end of disk */
{
inregs.h.ch = indx & 0x00FF; /* mask track bits and stuff in cl & ch */
inregs.h.cl = ((indx & 0x0300) >> 2) + 1; /* cl sector bit 1 for XTs */

int86(0x13,&inregs,&outregs); /* seek */

if (outregs.x.cflag != 0) disk_err(outregs.h.ah); /* stop on error */

if ((indx % 100) == 0) printf("%d ",indx); /* echo to user our progress */
}

t_bios_ask(DISK,0x0C,&hits2,&seek2);

printf("\nSeeking to all tracks ...\n");

inregs.h.ch = 0x00; /* back to track 0 for next test */
inregs.h.cl = 0x01; /* sector bit for XTs */
int86(0x13,&inregs,&outregs); /* seek */
if (outregs.x.cflag != 0) disk_err(outregs.h.ah); /* stop on errors */

t_bios_reset(DISK,0x0C);
for (indx=1; indx<=maxcyl; indx++) /* from track 0, seek to all tracks */
{
inregs.h.ch = indx & 0x00FF; /* mask tracks bits and stuff in cl & ch */
inregs.h.cl = ((indx & 0x0300) >> 2) + 1; /* cl sector bit 1 for XTs */

int86(0x13,&inregs,&outregs); /* seek */

if (outregs.x.cflag != 0) disk_err(outregs.h.ah); /* stop on errors */

if ((indx % 100) == 0) printf("%d ",indx); /* echo to user our progress */

inregs.h.ch = 0x00; /* go back to track 0 for next seek */
inregs.h.cl = 0x01;
int86(0x13,&inregs,&outregs);
if (outregs.x.cflag != 0) disk_err(outregs.h.ah);

}
t_bios_ask(DISK,0x0C,&hits3,&seek3);


printf("\n\nTest of physical disk %d complete.\n",disk);
printf("Average single track seek ............. %7.3f milliseconds\n",((seek2/hits2)/1000.0) );
printf("Average seek to all tracks ............ %7.3f milliseconds\n",((seek3/hits3)/1000.0) );
printf("Estimated software overhead per seek .. %7.3f milliseconds\n\n",((seek1/hits1)/1000.0) );

t_bios_stop();

} /* test_disk_bios */


void main(void)
{
int indx;
int numdisk;
char atom;

t_start(); /* start MSCHRT */

printf("SeekTest MSCHRT V3 Demonstration Series\n");
printf("(c)1989 Ryle Design, P.O. Box 22, Mt. Pleasant, Michigan 48804\n\n");

printf("Checking equipment ... ");

inregs.h.ah = 0x08;
inregs.h.dl = 0x80;
int86(0x13,&inregs,&outregs); /* get available physical disks */
if (outregs.x.cflag != 0)
{
printf("There are no hard disks on this system!\n\n"); /* exit on error */
printf("SeekTest complete\n");
exit(0);
}

numdisk = outregs.h.dl; /* DL has total disks on controller */
printf("%d physical hard disk(s) found\n\n",numdisk);

printf("*** WARNING -- Do not proceed unless the test disk is backed up!\n\n"); /* A word of advice ... */

do
{
for (indx=0; indx {
printf("%d ... Test disk %d\n",indx,indx);
}
printf("%d ... Exit SeekTest\n",numdisk);

do
{
printf("Select disk or exit (0-%d) >> ",numdisk);
atom = getche();
atom -= '0';
printf("\n");
}
while ( (atom <0) || (atom > numdisk) );

if (atom == numdisk)
{
t_stop(); /* shut down MSCHRT before exit */
printf("\nSeekTest complete");
exit(0);
}

do
{
printf("\nUse inline or BIOS interrupt timers?\n");
printf("0 ... Use inline timers\n");
printf("1 ... Use BIOS interrupt timers\n");
printf("Select 0 or 1 >> ");
indx = getche();
indx -= '0';
}
while ( (indx > 1) || (indx < 0) );

if (indx == 0)
test_disk(atom);
else
test_disk_bios(atom);

}
while (atom != numdisk);

} /* main */


  3 Responses to “Category : C Source Code
Archive   : MSCHRT3.ZIP
Filename : SEEKTEST.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/