home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / eidete19.zip / EIDETEST.CPP < prev    next >
C/C++ Source or Header  |  1995-10-29  |  15KB  |  552 lines

  1. /*  EIDEtest 1.9
  2.     Tests if simultaneous I/O corrupts disk reading.  If so, likely causes are the
  3.     PCI RZ-1000 EIDE chip, the CMD PCIO-640 EIDE chip or a faulty DMA controller.
  4.     Runs under DOS, DESQview, Windows, NT and OS/2 in DOS emulation mode.
  5.  
  6.     This program may be copied freely and used for any purpose except military.
  7.     (c) copyright 1995 by
  8.     Roedy Green
  9.     Canadian Mind Products
  10.     #601 - 1330 Burrard Street
  11.     Vancouver, BC Canada V6Z 2B8
  12.     (604) 685-8412
  13.     Internet Roedy@bix.com
  14.  
  15.     compiled under SMALL model under Borland C++ 4.5
  16.  
  17.     It works by writing a file with no I/O interfering, then
  18.     reads it back multiple times with as much DMA as possible
  19.     interfering.  It ensures the same pattern written comes back.
  20.  
  21.     This code is written in an extremely pedestrian C-like way.  My intent was
  22.     that the widest audience of programmers should understand it,
  23.     and to make it as easy as possible to port to other operating systems.
  24.  
  25.     Version history
  26.  
  27.     1.9 - consistent use of term CMD-640.
  28.  
  29.     1.8 - warnings about background execution configuration.
  30.  
  31.     1.7 - keep in sync with FAQ.
  32.  
  33.     1.6 - keep in sync with FAQ.
  34.  
  35.     1.5 - correct minor typos in the prompts.
  36.           focus on simultaneous floppy/tape I/O.
  37.  
  38.     1.4 - make mention also of the flawed CMD PCIO-640 chip
  39.         - Suggest running modem, mouse, sound card as well.
  40.         - Warning that a pass does not mean a perfect chip.
  41.  
  42.     1.3 - give different prompts on which background tests to
  43.           use depending on which OS you are using.
  44.           Make clear you must turn on simultaneous I/O in backup.
  45.  
  46.     1.2 - give proper fail if wrong length read comes back.
  47.         - Formerly code was hidden by an ill-formed comment.
  48.         - lint tidy up.
  49.         - Change prompts to indicate new understanding that
  50.         - simultaneou DMA rather than interrupts trigger the flaw.
  51.         - Allow abort at each prompt.
  52.         - Extra pause at the start.
  53.         - More status messages.
  54.         - Re-order routines top-down.
  55.         - clear screen at various stages to hide previous prompts.
  56.         - ack invalid ignored keystrokes with a beep
  57.  
  58.     1.1 - get rid of all 8-bit chars in source
  59.         - run test indefinitely, till the user hits ESC
  60.         - more elaborate prompting.
  61.  
  62.     1.0 - first release beta.
  63.  
  64.     */
  65.  
  66. /* ***************************************** */
  67.  
  68. /* D E F I N E S */
  69.  
  70. /* By redefining these constants, you could create a program to test a
  71.    floppy.  You would need to use a smaller file, and turn off caching on
  72.    the floppy. */
  73.  
  74. #define BufferSizeInWords 15872
  75. #define BufferSizeInBytes 31744
  76. /* size of buffer for write/reading the file.
  77.    This size should generate lots of physical I/O.
  78.    Smaller sizes might come out of cache.
  79.    Bigger sizes do only a few big I/Os */
  80.  
  81. #define NumChunks  240
  82. /* size of test file in blocks.  Size in bytes is 240 * 31744 = 7,618,560.
  83.    File must be bigger than cache, or little physical I/O will occur */
  84.  
  85. #define WORD unsigned short
  86.  
  87. #define StartDecorate "\xb0\xb1\xb2\xdb"
  88. /* line of pretty blobs in oemfont to attract attention */
  89. #define EndDecorate   "\xdb\xb2\xb1\xb0"
  90.  
  91. #define Esc   '\x1b'
  92.  
  93. /* ***************************************** */
  94.  
  95. /* I N C L U D E S */
  96.  
  97. #include <stdlib.h>
  98. // e.g. exit
  99.  
  100. #include <stdio.h>
  101. // e.g. FILE, printf, fopen
  102.  
  103. #include <conio.h>
  104. // e.g. getch kbhit crlscr
  105.  
  106. #include <alloc.h>
  107. // e.g. malloc free
  108.  
  109. /* ***************************************** */
  110.  
  111. /* G L O B A L S */
  112.  
  113. FILE *TempFile;
  114. /* temporary Test file */
  115.  
  116. char TempFileName[] = "C:\\EIDETEST.TMP";
  117. /* name of the temporary file on an EIDE drive */
  118.  
  119. WORD *Buffer;
  120. /* buffer for I/O on TempFile */
  121.  
  122. /* ***************************************** */
  123.  
  124. /* P R O T O T Y P E S */
  125.  
  126. int main( int argc,  char *argv[] );
  127. void banner ( void );
  128. int Phase1 ( void );
  129. int Phase2 ( void );
  130. void DisplayResults( int RetCode );
  131.  
  132. void beep (void );
  133. int pause ( void );
  134. int DoesOSDoSimultaneousIO ( void );
  135. int CheckForEsc ( void );
  136.  
  137. /* ***************************************** */
  138.  
  139. /* F U N C T I O N   D E F I N I T I O N S */
  140.  
  141. int main( int argc,  char *argv[] )
  142.  
  143. {
  144.     int RetCode = 0;
  145.  
  146.     banner();
  147.  
  148.     /* allocate RAM for buffer */
  149.     Buffer = (WORD *) malloc( BufferSizeInBytes );
  150.     if ( Buffer == 0)
  151.     {
  152.     printf("Oops!  not enough RAM to run the test.");
  153.     exit (2);
  154.     }
  155.  
  156.     if ( argc != 2 /*  0=EIDEtest.Exe 1=C: */ )
  157.     {
  158.     printf("Oops!  usage:  EIDEtest  C:"
  159.         "\nwhere C: is the EIDE hard drive to test.");
  160.     exit (2);
  161.     }
  162.  
  163.     /* replace first letter of TempFilename with Drive Letter */
  164.     /* e.g. TempFileName might now read:  D:\EIDETEST.TMP */
  165.     TempFileName[0] = *argv[1];
  166.  
  167.     printf("\nYou must run EIDEtest with background execution configured on."
  168.     "\nAbort now if you have not done so."
  169.     "\n");
  170.  
  171.     if ( pause() == 2 )  RetCode =2; /* user ESC abort */
  172.     else
  173.     {
  174.     printf("\nTesting by writing and reading file %s"
  175.         "\nwhich will need %lu bytes."
  176.         "\nThe test will not prove anything unless this file is on an EIDE hard disk.\n",
  177.         TempFileName, (long) NumChunks * (long) BufferSizeInBytes);
  178.     if ( pause() == 2 ) RetCode = 2; /* user ESC abort */
  179.     }
  180.     /* Stop processing when non-zero RetCode indicates trouble */
  181.  
  182.     /* do Phase 1 */
  183.     if (RetCode == 0) RetCode = Phase1();
  184.     beep(); /* announce Phase1 over */
  185.  
  186.     /* do Phase 2 */
  187.     if (RetCode == 0) RetCode = Phase2();
  188.     beep(); /* announce Phase2 over */
  189.  
  190.     DisplayResults(RetCode); /* report good or bad news */
  191.  
  192.     /* We are now done without background I/O, so these should be safe. */
  193.     fclose(TempFile);
  194.     unlink(TempFileName);
  195.     free (Buffer);
  196.  
  197.     return RetCode;
  198.  
  199. } /* end main */
  200.  
  201. /* ***************************************** */
  202.  
  203. void banner(void)
  204. {
  205.     /* display copyright banner. */
  206.  
  207.     clrscr(); /* clear screen */
  208.  
  209.     printf("\n" StartDecorate " EIDEtest 1.9 " EndDecorate
  210.     "\n"
  211.     "\nFreeware to test for the flawed EIDE controllers such as the"
  212.     "\nPC-Tech RZ-1000 and the CMD-640."
  213.     "\nRuns under DESQview, Windows, Windows For WorkGroups, Windows-95, NT"
  214.     "\nand OS/2 all in DOS emulation mode."
  215.     "\n"
  216.     "\nCopyright (c) 1995 Canadian Mind Products"
  217.     "\n#601 - 1330 Burrard Street, Vancouver BC CANADA V6Z 2B8  (604) 685-8412"
  218.     "\nInternet: Roedy@bix.com <Roedy Green>"
  219.     "\nMay be used freely for non-military use only."
  220.     "\n\n");
  221.  
  222. } /* end banner */
  223.  
  224. /* ***************************************** */
  225.  
  226. int Phase1 ( void )
  227.  
  228. { /* returns:
  229.      0 = ok
  230.      1 = failed
  231.      2 = could not run test */
  232.  
  233.     WORD Chunk; /* indexing chunks/blocks of file */
  234.     WORD i;     /* indexing chars in buffer */
  235.  
  236.  
  237.     clrscr(); /* clear screen */
  238.  
  239.     printf("\n" StartDecorate " PHASE 1 " EndDecorate
  240.     "\n"
  241.     "\nDuring phase 1, do not run any other programs."
  242.     "\nEspecially avoid using the tape or floppy drive."
  243.     "\nShutdown all background programs BEFORE you proceed."
  244.     "\nIf you can't get them all, not to worry;"
  245.     "\nthe test results will still be valid."
  246.     "\n");
  247.  
  248.     if ( pause() == 2 )
  249.     return 2; /* user abort */
  250.  
  251.     printf("\nPhase 1 in progress.  Please stand by...\n");
  252.  
  253.     /* create a temporary file */
  254.     TempFile = fopen(TempFileName,"w+b"); /* create binary mode */
  255.     if (TempFile == 0 )
  256.     {
  257.     return 2; /* Failed to create test file */
  258.     }
  259.  
  260.     /* fill buffer with pattern */
  261.     for ( i=0 ; i < BufferSizeInWords ; i++ )
  262.     { Buffer [i] = i;}
  263.  
  264.     /* write a test file full of a set pattern */
  265.  
  266.     for ( Chunk=0 ; Chunk < NumChunks ; Chunk++ )
  267.     {
  268.  
  269.     if (fwrite(Buffer, BufferSizeInBytes , 1, TempFile) != 1)
  270.         {
  271.         return 2; /* could not create test file */
  272.         }
  273.     }
  274.     /* all ok */
  275.     return 0;
  276.  
  277. } /* end Phase1 */
  278.  
  279. /* ***************************************** */
  280.  
  281. int Phase2 ( void )
  282.  
  283. { /* returns:
  284.     0 = ok
  285.     1 = failed
  286.     2 = could not run test */
  287.  
  288.     WORD Chunk; /* indexing chunks/blocks of file */
  289.     WORD i;     /* indexing chars in buffer */
  290.     switch (DoesOSDoSimultaneousIO())
  291.     {
  292.  
  293.     case 0: /* DOS */
  294.         clrscr(); /* clear screen */
  295.         printf( "\n" StartDecorate " PHASE 2 " EndDecorate
  296.         "\n"
  297.         "\nDURING phase 2, do as many of these tests with as you can"
  298.         "\neach with background execution configured ON,"
  299.         "\nto generate simultaneous I/O:"
  300.         "\n"
  301.         "\n- Backup some files to floppy with MWBackup, MSBackup, Norton Backup"
  302.         "\n  or other high performance floppy backup program with fast-mode"
  303.         "\n  simultaneous disk I/O configured."
  304.         "\n- Backup a file using your mag tape backup software with fast-mode"
  305.         "\n  simultaneous disk I/O configured."
  306.         "\n- Exercise any simultaneous I/O devices e.g. modem, mouse or sound card."
  307.         "\n");
  308.         break;
  309.  
  310.     case 1: /* OS */
  311.         clrscr(); /* clear screen */
  312.         printf( "\n" StartDecorate " PHASE 2 " EndDecorate
  313.         "\n"
  314.         "\nDURING phase 2, do as many of these tests with as you can"
  315.         "\neach with background execution configured ON,"
  316.         "\nto generate simultaneous I/O:"
  317.         "\n"
  318.         "\n- Format a floppy."
  319.         "\n- Backup some files to floppy with MWBackup, MSBackup, Norton Backup"
  320.         "\n  or other high performance floppy backup program with fast-mode"
  321.         "\n  simultaneous disk I/O configured."
  322.         "\n- Backup a file using your mag tape backup software with fast-mode"
  323.         "\n  simultaneous disk I/O configured."
  324.         "\n- Scan a document with your scanner."
  325.         "\n- Browse some files on other hard disks and CD-ROM."
  326.         "\n- Exercise any simultaneous I/O devices e.g. modem, mouse or sound card."
  327.         "\n");
  328.         break;
  329.  
  330.     case 2: /* esc */
  331.         return 2;
  332.     }
  333.  
  334.  
  335.     printf("\nYour experiments may run slowly because of EIDEtest's disk overhead."
  336.     "\n"
  337.     "\nBEGIN YOUR EXPERIMENTS NOW!"
  338.     "\n"
  339.     "\nTake all the time you want -- days even."
  340.     "\nWhen you have FINISHED your experiments, come back and hit the space bar."
  341.     "\n"
  342.     "\nPhase 2 in progress..."
  343.     "\n");
  344.  
  345.     /* read a test file full of the test pattern, over and over */
  346.     /* keep going till user hits Esc */
  347.  
  348.     while ( 1 )
  349.     {
  350.  
  351.     /* seek to the beginning of the file */
  352.     fseek(TempFile, SEEK_SET, 0);
  353.  
  354.     for ( Chunk=0 ; Chunk < NumChunks ; Chunk++)
  355.         {
  356.         if (CheckForEsc())
  357.         {
  358.         /* all went well, we ran without incident until the user hit space or ESC */
  359.         return 0;  /* EXIT */
  360.         }
  361.         if (fread(Buffer, BufferSizeInBytes, 1, TempFile) != 1)
  362.         {
  363.         /* File corrupted */
  364.         return 1; /* EXIT */
  365.         }
  366.         /* check that buffer is same pattern as written */
  367.         for ( i=0 ; i < BufferSizeInWords ; i++ )
  368.         {
  369.         if (Buffer [i] != i)
  370.             {
  371.             /* discrepancy detected */
  372.             return 1;  /* EXIT */
  373.             }
  374.         }
  375.         }
  376.     } /* end while forever */
  377.  
  378.     /* never get here */
  379.  
  380. } /* end Phase2 */
  381.  
  382. /* ***************************************** */
  383.  
  384. void DisplayResults( int RetCode )
  385. {
  386.     /* display results of the test */
  387.     /*  0 = test ok
  388.     1 = fail
  389.     2 = could not run test */
  390.  
  391.     clrscr(); /* clear screen */
  392.  
  393.     printf( "\n" StartDecorate " TEST RESULTS " EndDecorate
  394.     "\n\n");
  395.  
  396.     switch (RetCode)
  397.     {
  398.     case 0:
  399.         printf("\n\nEIDEtest passed.  No flaws found."
  400.         "\nYou may still have a flawed EIDE controller chip with a"
  401.         "\nsuccessful software bypass."
  402.         "\nKeep in mind, that unless you carefully followed the"
  403.         " instructions on the,"
  404.         "\nscreen, especially running all tests with background execution"
  405.         "\nconfigured on, the results of this test are meaningless."
  406.         "\n");
  407.         break;
  408.  
  409.     case 1:
  410.         printf("\n\nEIDEtest failed."
  411.         "\nIf you have a PCI motherboard the failure is probably due to a faultly"
  412.         "\nPC-Tech RZ-1000 or CMD-640 EIDE controller chip."
  413.         "\nIt could also be due to overheating, a faulty DMA controller,"
  414.         "\nor software bugs."
  415.         "\nPlease ensure you have stopped all your experiments that were"
  416.         "\ngenerating background I/O activity.");
  417.         break;
  418.  
  419.     case 2:
  420.     default:
  421.         printf("\n\nEIDEtest could not be run."
  422.         "\nPossibly a user abort or problems creating the test file."
  423.         "\nProbably not enough room on the test disk drive."
  424.         "\n");
  425.         break;
  426.  
  427.     }
  428.     printf("\nPlease admire the test results.\n");
  429.     pause();
  430.  
  431. } /* end DisplayResults */
  432.  
  433. /* ***************************************** */
  434.  
  435. void beep (void)
  436. {
  437.     /* long beep to attract attention */
  438.     printf("\x07\x07\x07\x07");
  439.  
  440. } /* end beep */
  441.  
  442. /* ***************************************** */
  443.  
  444. int pause (void)
  445. {
  446.     /*
  447.     returns 1=user hit space
  448.     returns 2=user hit ESC
  449.     */
  450.     int Result = 0;
  451.     /* pause until the user hits the space bar */
  452.     printf ("\nWhen you are ready to proceed, hit the space bar; hit ESC to abort");
  453.  
  454.     while (!Result)
  455.     {
  456.     switch (getch())
  457.         {
  458.         case ' ':
  459.         Result = 1; /*  space we are done */
  460.         break;
  461.         case Esc:
  462.         Result = 2; /* Esc, Abort */
  463.         break;
  464.         default:
  465.         printf("\x07" );  /* beep to indicate char ignored. */
  466.         break;
  467.         }
  468.     }
  469.     printf("\r                                                                  \n\n");
  470.     /* erase the  prompt line, to acknowledge the space bar */
  471.     return Result;
  472.  
  473. } /* end pause */
  474.  
  475. /* ***************************************** */
  476.  
  477. int DoesOSDoSimultaneousIO (void)
  478. {
  479.     /*
  480.       returns 0= no, DESQiew, Windows,...
  481.       returns 1= yes. OS/2, NT...
  482.       returns 2=user hit ESC
  483.        */
  484.     int Result = -1;
  485.  
  486.     printf( "\nDoes your operating system do more than one I/O at a time?"
  487.     "\nAnswer N for DOS, DESQview, Windows, Windows for Workgroups or Windows-95."
  488.     "\nAnswer Y for OS/2, Warp, NT, Linux, SCO XENIX or UNIX.");
  489.     /* don't advertise the ESC possibility */
  490.  
  491.     while (Result == -1)
  492.     {
  493.     switch (getch())
  494.         {
  495.         case 'N':
  496.         case 'n':
  497.         Result = 0; /*  No */
  498.         break;
  499.         case 'Y':
  500.         case 'y':
  501.         Result = 1; /* Yes */
  502.         break;
  503.         case Esc:
  504.         Result = 2; /* Esc, Abort */
  505.         break;
  506.         default:
  507.         printf("\x07" );  /* beep to indicate char ignored. */
  508.         break;
  509.         }
  510.     }
  511.  
  512.     return Result;
  513. } /* end DoesOSDoSimultaneousIO */
  514.  
  515. /* ***************************************** */
  516.  
  517. int CheckForEsc (void)
  518. {
  519.  
  520.     /*
  521.       returns 0=user did nothing.  We don't wait for him to hit a key.
  522.       returns 1=user hit space
  523.       returns 2=user hit ESC
  524.        */
  525.     int Result = 0;
  526.  
  527.     if (kbhit())
  528.     {
  529.     switch (getch())
  530.         {
  531.         case ' ':
  532.         Result = 1; /*  space we are done */
  533.         break;
  534.         case Esc:
  535.         Result = 2; /* Esc, Abort */
  536.         break;
  537.         default:
  538.         printf("\x07" );  /* beep to indicate char ignored. */
  539.         Result = 0;
  540.         break;
  541.         }
  542.     }
  543.     else
  544.     Result = 0; /* no key hit */
  545.     return Result;
  546. } /* end CheckForEsc */
  547.  
  548. /* ***************************************** */
  549.  
  550. /* -30- */
  551.  
  552.