home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / progc / mschrt3.arj / SEEKTEST.C < prev    next >
Text File  |  1990-07-24  |  19KB  |  430 lines

  1. /*---------------------------------------------------------------------------
  2.  |  Program SEEKTEST.C                                                      |
  3.  |                                                                          |
  4.  |  This program demonstrates the use of MSCHRT in timing seek performance  |
  5.  |  of a PC based hard disk drive.  The method used will determine the total|
  6.  |  seek time of the device which includes actual disk seek, controller     |
  7.  |  overhead, and ROM BIOS overhead.  This is a "real world" measurement    |
  8.  |  of disk performance under actual usage conditions.                      |
  9.  |                                                                          |
  10.  |  This program uses both inline generic timers and BIOS interrupt         |
  11.  |  timers to measure disk performance.                                     |
  12.  |                                                                          |
  13.  |  (c)1989 Ryle Design, P.O. Box 22, Mt. Pleasant, Michigan 48804          |
  14.  |                                                                          |
  15.  |  V3.00 Microsoft C Shareware Evaluation Version                          |
  16.  ---------------------------------------------------------------------------*/
  17.  
  18. #include <stdio.h>
  19. #include <conio.h>
  20. #include <dos.h>
  21. #include <process.h>
  22.  
  23. #include "pchrt.h"
  24.  
  25. union REGS      inregs,outregs;
  26.  
  27. long unsigned   seek1, seek2, hits1, hits2, seek3, hits3;
  28.  
  29.  
  30. void disk_err(int istat)
  31. /*---------------------------------------------------------------------------
  32.  |  This procedure outputs a description of an INT 13h error status, and    |
  33.  |  halts program exection.                                                 |
  34.  |                                                                          |
  35.  |  Globals referenced: none                                                |
  36.  |                                                                          |
  37.  |  Arguments: (int) istat - status returned from INT 13h in AX if carry    |
  38.  |                           flag set.                                      |
  39.  |                                                                          |
  40.  |  Returns  : void                                                         |
  41.  ---------------------------------------------------------------------------*/
  42. {
  43.     switch (istat)
  44.     {
  45.         case 0x00 : return;                                    /* no error */
  46.  
  47.         case 0x01 : printf("Disk error: Invalid command\n");
  48.                     break;
  49.  
  50.         case 0x02 : printf("Disk error: Address mark not found\n");
  51.                     break;
  52.  
  53.         case 0x03 : printf("Disk error: Disk is write-protected\n");
  54.                     break;
  55.  
  56.         case 0x04 : printf("Disk error: Requested sector not found\n");
  57.                     break;
  58.  
  59.         case 0x05 : printf("Disk error: Reset failed\n");
  60.                     break;
  61.  
  62.         case 0x06 : printf("Disk error: Floppy disk removed\n");
  63.                     break;
  64.  
  65.         case 0x07 : printf("Disk error: Bad parameter table\n");
  66.                     break;
  67.  
  68.         case 0x08 : printf("Disk error: DMA overrun\n");
  69.                     break;
  70.  
  71.         case 0x09 : printf("Disk error: DMA crossed 64KB boundary\n");
  72.                     break;
  73.  
  74.         case 0x0A : printf("Disk error: Bad sector flag set\n");
  75.                     break;
  76.  
  77.         case 0x0B : printf("Disk error: Bad track flag set\n");
  78.                     break;
  79.  
  80.         case 0x0C : printf("Disk error: Requested media type not found\n");
  81.                     break;
  82.  
  83.         case 0x0D : printf("Disk error: Invalid number of sectors on format\n");
  84.                     break;
  85.  
  86.         case 0x0E : printf("Disk error: Control data address mark detected\n");
  87.                     break;
  88.  
  89.         case 0x0F : printf("Disk error: DMA arbitration level out of range\n");
  90.                     break;
  91.  
  92.         case 0x10 : printf("Disk error: Uncorrectable CRC or ECC data error\n");
  93.                     break;
  94.  
  95.         case 0x11 : printf("Disk warning: ECC corrected data error\n");
  96.                     return;
  97.  
  98.         case 0x20 : printf("Disk error: Controller failed\n");
  99.                     break;
  100.  
  101.         case 0x40 : printf("Disk error: Seek failed\n");
  102.                     break;
  103.  
  104.         case 0x80 : printf("Disk error: Disk has timed out\n");
  105.                     break;
  106.  
  107.         case 0xAA : printf("Disk error: Drive not ready\n");
  108.                     break;
  109.  
  110.         case 0xBB : printf("Disk error: Error is undefined\n");
  111.                     break;
  112.  
  113.         case 0xCC : printf("Disk error: Write fault\n");
  114.                     break;
  115.  
  116.         case 0xE0 : printf("Disk error: Status register error\n");
  117.                     break;
  118.  
  119.         case 0xFF : printf("Disk error: Sense operation failed\n");
  120.                     break;
  121.  
  122.         default   : printf("Unknown INT 13 return status %d\n",istat);
  123.                     break;
  124.     }
  125.  
  126.     exit(1);
  127.  
  128. } /* disk_err */
  129.  
  130.  
  131. void test_disk(char disk)
  132. /*---------------------------------------------------------------------------
  133.  |  This function, which contains the actual disk test routines, does the   |
  134.  |  following:                                                              |
  135.  |      1. Seeks the test disk to track 0.                                  |
  136.  |      2. Times 100 calls to seek to track 0.  Since the heads are already |
  137.  |         on track 0, they will not move, and a estimate of the software   |
  138.  |         overhead for each seek call can be made.                         |
  139.  |      3. Times single track seeks to all cylinders (0-1,1-2,2-3,3-4,etc). |
  140.  |         This provides a measurement of single track seek time.           |
  141.  |      4. Seeks from track 0 to all tracks (0-1,0-2,0-3,0-4,etc).  This    |
  142.  |         provides average seek time for the entire disk.                  |
  143.  |      5. The results are reported.                                        |
  144.  |                                                                          |
  145.  |  int86() is used to call the ROM BIOS.  There is some software           |
  146.  |  overhead incurred using this method.                                    |
  147.  |                                                                          |
  148.  |  Generic inline timers are used to measure disk performance.             |
  149.  |                                                                          |
  150.  |  Globals referenced: inregs, outregs.                                    |
  151.  |                                                                          |
  152.  |  Arguments: (char) disk - physical disk # - add to 0x80 for BIOS call.   |
  153.  |                                                                          |
  154.  |  Returns  : void                                                         |
  155.  ---------------------------------------------------------------------------*/
  156. {
  157.     
  158.     int             maxhead,maxcyl,indx;
  159.     unsigned long   seek1,seek2,seek3,hits1,hits2,hits3;
  160.     
  161.     inregs.h.dl = 0x80 + disk;                              /* get disk config */
  162.     inregs.h.ah = 0x08;
  163.     int86(0x13,&inregs,&outregs);
  164.     if (outregs.x.cflag != 0) disk_err(outregs.h.ah);
  165.  
  166.     maxhead = outregs.h.dh;                                 /* move bits to get */
  167.     maxcyl = ((outregs.h.cl & 0xC0) << 2) + outregs.h.ch;   /* heads & tracks   */
  168.  
  169.     printf("\nPhysical drive %d shows %d cylinders, %d heads\n\n",disk,maxcyl+1,maxhead+1);
  170.  
  171.     printf("Starting single track seek test ...\n");
  172.  
  173.     inregs.h.ah = 0x0C;                                     /* seek command                        */
  174.     inregs.h.ch = 0x00;                                     /* track 0                             */
  175.     inregs.h.cl = 0x01;                                     /* XTs need sector bit set, or no seek */
  176.     inregs.h.dh = 0;                                        /* head 0                              */
  177.     inregs.h.dl = 0x80 + disk;                              /* disk #                              */
  178.  
  179.     int86(0x13,&inregs,&outregs);                           /* seek to track 0 */
  180.     if (outregs.x.cflag != 0) disk_err(outregs.h.ah);       /* stop on error   */
  181.  
  182.     for (indx=0; indx<100; indx++)                          /* seek to 0 100 times to get ave overhead */
  183.     {
  184.         t_entry(2);
  185.         int86(0x13,&inregs,&outregs);
  186.         t_exit(2);
  187.     }
  188.  
  189.     for (indx=1; indx<=maxcyl; indx++)                      /* from zero, single track seek to end of disk */
  190.     {
  191.         inregs.h.ch = indx & 0x00FF;                        /* mask track bits and stuff in cl & ch */
  192.         inregs.h.cl = ((indx & 0x0300) >> 2) + 1;           /* cl sector bit 1 for XTs              */
  193.  
  194.         t_entry(0);
  195.         int86(0x13,&inregs,&outregs);                       /* seek */
  196.         t_exit(0);
  197.  
  198.         if (outregs.x.cflag != 0) disk_err(outregs.h.ah);   /* stop on error */
  199.  
  200.         if ((indx % 100) == 0) printf("%d ",indx);          /* echo to user our progress */
  201.     }
  202.  
  203.  
  204.     printf("\nSeeking to all tracks ...\n");
  205.  
  206.     inregs.h.ch = 0x00;                                     /* back to track 0 for next test */
  207.     inregs.h.cl = 0x01;                                     /* sector bit for XTs            */
  208.     int86(0x13,&inregs,&outregs);                           /* seek                          */
  209.     if (outregs.x.cflag != 0) disk_err(outregs.h.ah);       /* stop on errors                */
  210.  
  211.     for (indx=1; indx<=maxcyl; indx++)                      /* from track 0, seek to all tracks */
  212.     {
  213.         inregs.h.ch = indx & 0x00FF;                        /* mask tracks bits and stuff in cl & ch */
  214.         inregs.h.cl = ((indx & 0x0300) >> 2) + 1;           /* cl sector bit 1 for XTs               */
  215.  
  216.         t_entry(1);
  217.         int86(0x13,&inregs,&outregs);                       /* seek */
  218.         t_exit(1);
  219.  
  220.         if (outregs.x.cflag != 0) disk_err(outregs.h.ah);   /* stop on errors */
  221.  
  222.         if ((indx % 100) == 0) printf("%d ",indx);          /* echo to user our progress */
  223.  
  224.         inregs.h.ch = 0x00;                                 /* go back to track 0 for next seek */
  225.         inregs.h.cl = 0x01;
  226.         int86(0x13,&inregs,&outregs);
  227.         if (outregs.x.cflag != 0) disk_err(outregs.h.ah);
  228.  
  229.     }
  230.  
  231.     t_ask_timer(0,&hits1,&seek1);                           /* query timers */
  232.     t_ask_timer(1,&hits2,&seek2);
  233.     t_ask_timer(2,&hits3,&seek3);
  234.  
  235.     printf("\n\nTest of physical disk %d complete.\n",disk);
  236.     printf("Average single track seek ............. %7.3f milliseconds\n",((seek1/hits1)/1000.0) );
  237.     printf("Average seek to all tracks ............ %7.3f milliseconds\n",((seek2/hits2)/1000.0) );
  238.     printf("Estimated software overhead per seek .. %7.3f milliseconds\n\n",((seek3/hits3)/1000.0) );
  239.  
  240.     t_reset(0);                                             /* reset all timers */
  241.     t_reset(1);
  242.     t_reset(2);
  243.  
  244. } /* test_disk */
  245.  
  246.  
  247. void test_disk_bios(char disk)
  248. /*---------------------------------------------------------------------------
  249.  |  This function, which contains the actual disk test routines, does the   |
  250.  |  following:                                                              |
  251.  |      1. Seeks the test disk to track 0.                                  |
  252.  |      2. Times 100 calls to seek to track 0.  Since the heads are already |
  253.  |         on track 0, they will not move, and a estimate of the software   |
  254.  |         overhead for each seek call can be made.                         |
  255.  |      3. Times single track seeks to all cylinders (0-1,1-2,2-3,3-4,etc). |
  256.  |         This provides a measurement of single track seek time.           |
  257.  |      4. Seeks from track 0 to all tracks (0-1,0-2,0-3,0-4,etc).  This    |
  258.  |         provides average seek time for the entire disk.                  |
  259.  |      5. The results are reported.                                        |
  260.  |                                                                          |
  261.  |  int86() is used to call the ROM BIOS.  There is some software           |
  262.  |  overhead incurred using this method.                                    |
  263.  |                                                                          |
  264.  |  BIOS interrupt timers are used to measure disk performance.             |
  265.  |                                                                          |
  266.  |  Globals referenced: inregs, outregs.                                    |
  267.  |                                                                          |
  268.  |  Arguments: (char) disk - physical disk # - add to 0x80 for BIOS call.   |
  269.  |                                                                          |
  270.  |  Returns  : void                                                         |
  271.  ---------------------------------------------------------------------------*/
  272. {
  273.     
  274.     int             maxhead,maxcyl,indx;
  275.     unsigned long   seek1,seek2,seek3,hits1,hits2,hits3;
  276.     
  277.     t_bios_start(DISK);
  278.     
  279.     inregs.h.dl = 0x80 + disk;                              /* get disk config */
  280.     inregs.h.ah = 0x08;
  281.     int86(0x13,&inregs,&outregs);
  282.     if (outregs.x.cflag != 0) disk_err(outregs.h.ah);
  283.  
  284.     maxhead = outregs.h.dh;                                 /* move bits to get */
  285.     maxcyl = ((outregs.h.cl & 0xC0) << 2) + outregs.h.ch;   /* heads & tracks   */
  286.  
  287.     printf("\nPhysical drive %d shows %d cylinders, %d heads\n\n",disk,maxcyl+1,maxhead+1);
  288.  
  289.     printf("Starting single track seek test ...\n");
  290.  
  291.     inregs.h.ah = 0x0C;                                     /* seek command                        */
  292.     inregs.h.ch = 0x00;                                     /* track 0                             */
  293.     inregs.h.cl = 0x01;                                     /* XTs need sector bit set, or no seek */
  294.     inregs.h.dh = 0;                                        /* head 0                              */
  295.     inregs.h.dl = 0x80 + disk;                              /* disk #                              */
  296.  
  297.     int86(0x13,&inregs,&outregs);                           /* seek to track 0 */
  298.     if (outregs.x.cflag != 0) disk_err(outregs.h.ah);       /* stop on error   */
  299.  
  300.     for (indx=0; indx<100; indx++)                          /* seek to 0 100 times to get ave overhead */
  301.         int86(0x13,&inregs,&outregs);
  302.  
  303.     t_bios_ask(DISK,0x0C,&hits1,&seek1);
  304.     t_bios_reset(DISK,0x0C);
  305.  
  306.     for (indx=1; indx<=maxcyl; indx++)                      /* from zero, single track seek to end of disk */
  307.     {
  308.         inregs.h.ch = indx & 0x00FF;                        /* mask track bits and stuff in cl & ch */
  309.         inregs.h.cl = ((indx & 0x0300) >> 2) + 1;           /* cl sector bit 1 for XTs              */
  310.  
  311.         int86(0x13,&inregs,&outregs);                       /* seek */
  312.  
  313.         if (outregs.x.cflag != 0) disk_err(outregs.h.ah);   /* stop on error */
  314.  
  315.         if ((indx % 100) == 0) printf("%d ",indx);          /* echo to user our progress */
  316.     }
  317.  
  318.     t_bios_ask(DISK,0x0C,&hits2,&seek2);
  319.  
  320.     printf("\nSeeking to all tracks ...\n");
  321.  
  322.     inregs.h.ch = 0x00;                                     /* back to track 0 for next test */
  323.     inregs.h.cl = 0x01;                                     /* sector bit for XTs            */
  324.     int86(0x13,&inregs,&outregs);                           /* seek                          */
  325.     if (outregs.x.cflag != 0) disk_err(outregs.h.ah);       /* stop on errors                */
  326.  
  327.     t_bios_reset(DISK,0x0C);
  328.     for (indx=1; indx<=maxcyl; indx++)                      /* from track 0, seek to all tracks */
  329.     {
  330.         inregs.h.ch = indx & 0x00FF;                        /* mask tracks bits and stuff in cl & ch */
  331.         inregs.h.cl = ((indx & 0x0300) >> 2) + 1;           /* cl sector bit 1 for XTs               */
  332.  
  333.         int86(0x13,&inregs,&outregs);                       /* seek */
  334.  
  335.         if (outregs.x.cflag != 0) disk_err(outregs.h.ah);   /* stop on errors */
  336.  
  337.         if ((indx % 100) == 0) printf("%d ",indx);          /* echo to user our progress */
  338.  
  339.         inregs.h.ch = 0x00;                                 /* go back to track 0 for next seek */
  340.         inregs.h.cl = 0x01;
  341.         int86(0x13,&inregs,&outregs);
  342.         if (outregs.x.cflag != 0) disk_err(outregs.h.ah);
  343.  
  344.     }
  345.     t_bios_ask(DISK,0x0C,&hits3,&seek3);
  346.  
  347.  
  348.     printf("\n\nTest of physical disk %d complete.\n",disk);
  349.     printf("Average single track seek ............. %7.3f milliseconds\n",((seek2/hits2)/1000.0) );
  350.     printf("Average seek to all tracks ............ %7.3f milliseconds\n",((seek3/hits3)/1000.0) );
  351.     printf("Estimated software overhead per seek .. %7.3f milliseconds\n\n",((seek1/hits1)/1000.0) );
  352.  
  353.     t_bios_stop();
  354.  
  355. } /* test_disk_bios */
  356.  
  357.  
  358. void main(void)
  359. {
  360.     int     indx;
  361.     int     numdisk;
  362.     char    atom;
  363.  
  364.     t_start();                                              /* start MSCHRT */
  365.  
  366.     printf("SeekTest   MSCHRT V3 Demonstration Series\n");
  367.     printf("(c)1989 Ryle Design, P.O. Box 22, Mt. Pleasant, Michigan 48804\n\n");
  368.  
  369.     printf("Checking equipment ... ");
  370.  
  371.     inregs.h.ah = 0x08;
  372.     inregs.h.dl = 0x80;
  373.     int86(0x13,&inregs,&outregs);                           /* get available physical disks */
  374.     if (outregs.x.cflag != 0)
  375.     {
  376.         printf("There are no hard disks on this system!\n\n");  /* exit on error */
  377.         printf("SeekTest complete\n");
  378.         exit(0);
  379.     }
  380.  
  381.     numdisk = outregs.h.dl;                                 /* DL has total disks on controller */
  382.     printf("%d physical hard disk(s) found\n\n",numdisk);
  383.  
  384.     printf("*** WARNING -- Do not proceed unless the test disk is backed up!\n\n");     /* A word of advice ... */
  385.  
  386.     do
  387.     {
  388.         for (indx=0; indx<numdisk; indx++)
  389.         {
  390.             printf("%d ... Test disk %d\n",indx,indx);
  391.         }
  392.         printf("%d ... Exit SeekTest\n",numdisk);
  393.  
  394.         do
  395.         {
  396.             printf("Select disk or exit (0-%d) >> ",numdisk);
  397.             atom = getche();
  398.             atom -= '0';
  399.             printf("\n");
  400.         }
  401.         while ( (atom <0) || (atom > numdisk) );
  402.  
  403.         if (atom == numdisk)
  404.         {
  405.             t_stop();                                       /* shut down MSCHRT before exit */
  406.             printf("\nSeekTest complete");
  407.             exit(0);
  408.         }
  409.  
  410.         do
  411.         {
  412.             printf("\nUse inline or BIOS interrupt timers?\n");
  413.             printf("0 ... Use inline timers\n");
  414.             printf("1 ... Use BIOS interrupt timers\n");
  415.             printf("Select 0 or 1 >> ");
  416.             indx = getche();
  417.             indx -= '0';
  418.         }
  419.         while ( (indx > 1) || (indx < 0) );
  420.  
  421.         if (indx == 0)
  422.             test_disk(atom);
  423.         else
  424.             test_disk_bios(atom);
  425.  
  426.     }
  427.     while (atom != numdisk);
  428.  
  429. } /* main */
  430.