home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1997 October / PCO1097.ISO / FilesBBS / OS2 / DISKIO11.ARJ / DISKIO11.ZIP / diskio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-09  |  17.2 KB  |  734 lines

  1. /* diskio.c - disk benchmark
  2.  *
  3.  * Author:  Kai Uwe Rommel <rommel@ars.muc.de>
  4.  * Created: Fri Jul 08 1994
  5.  */
  6.  
  7. static char *rcsid =
  8. "$Id: diskio.c,v 1.11 1997/02/09 15:06:38 rommel Exp rommel $";
  9. static char *rcsrev = "$Revision: 1.11 $";
  10.  
  11. /*
  12.  * $Log: diskio.c,v $
  13.  * Revision 1.11  1997/02/09 15:06:38  rommel
  14.  * changed command line interface
  15.  *
  16.  * Revision 1.10  1997/01/12 21:15:10  rommel
  17.  * added CD-ROM benchmarks
  18.  *
  19.  * Revision 1.9  1995/12/31 20:24:09  rommel
  20.  * Changed CPU load calculation
  21.  * General cleanup
  22.  *
  23.  * Revision 1.8  1995/12/28 11:28:07  rommel
  24.  * Fixed async timer problem.
  25.  *
  26.  * Revision 1.7  1995/12/28 10:04:15  rommel
  27.  * Added CPU benchmark (concurrently to disk I/O)
  28.  *
  29.  * Revision 1.6  1995/11/24 16:02:10  rommel
  30.  * Added bus/drive cache speed test by 
  31.  * repeatedly reading a small amount of data
  32.  *
  33.  * Revision 1.5  1995/08/09 13:07:02  rommel
  34.  * Changes for new diskacc2 library, minor corrections, arguments.
  35.  *
  36.  * Revision 1.4  1994/07/11 14:23:00  rommel
  37.  * Changed latency timing
  38.  *
  39.  * Revision 1.3  1994/07/09 13:07:20  rommel
  40.  * Changed transfer speed test
  41.  *
  42.  * Revision 1.2  1994/07/08 21:53:05  rommel
  43.  * Cleanup
  44.  *
  45.  * Revision 1.1  1994/07/08 21:29:41  rommel
  46.  * Initial revision
  47.  * 
  48.  */
  49.  
  50. #include <stdio.h>
  51. #include <stdlib.h>
  52. #include <string.h>
  53.  
  54. #define INCL_DOS
  55. #define INCL_DOSDEVICES
  56. #define INCL_DOSDEVIOCTL
  57. #define INCL_DOSERRORS
  58. #define INCL_NOPM
  59. #include <os2.h>
  60.  
  61. #include "diskacc2.h"
  62.  
  63. #define INTERVAL 10
  64.  
  65. #define THREADSTACK 65536
  66.  
  67. char *pBuffer;
  68.  
  69. int time_over;
  70. long dhry_time, dhry_result;
  71.  
  72. extern unsigned long Number_Of_Runs;
  73. extern long dhry_stone(void);
  74.  
  75. VOID APIENTRY timer_thread(ULONG nArg)
  76. {
  77.   HEV hSem;
  78.   HTIMER hTimer;
  79.  
  80.   // DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0);
  81.  
  82.   DosCreateEventSem(0, &hSem, DC_SEM_SHARED, 0);
  83.  
  84.   DosAsyncTimer(nArg * 1000, (HSEM) hSem, &hTimer);
  85.   DosWaitEventSem(hSem, SEM_INDEFINITE_WAIT);
  86.   DosStopTimer(hTimer);
  87.  
  88.   DosCloseEventSem(hSem);
  89.  
  90.   time_over = 1;
  91.   Number_Of_Runs = 0;
  92.  
  93.   DosExit(EXIT_THREAD, 0);
  94. }
  95.  
  96. int start_alarm(ULONG nSeconds)
  97.   TID ttid;
  98.  
  99.   time_over = 0;
  100.   Number_Of_Runs = -1;
  101.  
  102.   if (DosCreateThread(&ttid, timer_thread, nSeconds, 0, THREADSTACK))
  103.     return printf("Cannot create timer thread.\n"), -1;
  104.  
  105.   return 0;
  106. }
  107.  
  108. int start_timer(QWORD *nStart)
  109. {
  110.   if (DosTmrQueryTime(nStart))
  111.     return printf("Timer error.\n"), -1;
  112.  
  113.   return 0;
  114. }
  115.  
  116. int stop_timer(QWORD *nStart, int accuracy)
  117. {
  118.   QWORD nStop;
  119.   ULONG nFreq;
  120.  
  121.   if (DosTmrQueryTime(&nStop))
  122.     return printf("Timer error.\n"), -1;
  123.   if (DosTmrQueryFreq(&nFreq))
  124.     return printf("Timer error.\n"), -1;
  125.  
  126.   nFreq = (nFreq + accuracy / 2) / accuracy;
  127.  
  128.   return (nStop.ulLo - nStart->ulLo) / nFreq;
  129. }
  130.  
  131. VOID APIENTRY dhry_thread(ULONG nArg)
  132. {
  133.   DosSetPriority(PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MAXIMUM, 0);
  134.  
  135.   dhry_time = dhry_stone();
  136.  
  137.   DosExit(EXIT_THREAD, 0);
  138. }
  139.  
  140. int bench_hd_bus(int nHandle, unsigned nSectors)
  141. {
  142.   int nCnt, nData = 0, nTime;
  143.   QWORD nLocal;
  144.  
  145.   printf("Drive cache/bus transfer rate: ");
  146.   fflush(stdout);
  147.  
  148.   if (start_alarm(INTERVAL))
  149.     return -1;
  150.  
  151.   if (start_timer(&nLocal))
  152.     return -1;
  153.  
  154.   for (nCnt = 0; !time_over; nCnt++)
  155.   {
  156.     if (DskRead(nHandle, 0, 0, 1, nSectors, pBuffer))
  157.       return printf("Disk read error.\n"), -1;
  158.  
  159.     nData += nSectors * 512;
  160.   }
  161.  
  162.   if ((nTime = stop_timer(&nLocal, 1024)) == -1)
  163.     return -1;
  164.  
  165.   printf("%d k/sec\n", nData / nTime);
  166.  
  167.   return 0;
  168. }
  169.  
  170. int bench_hd_transfer(int nHandle, int nTrack, int nDirection, 
  171.               unsigned nSides, unsigned nSectors)
  172. {
  173.   int nCnt, nData = 0, nTime;
  174.   QWORD nLocal;
  175.  
  176.   printf("Data transfer rate on track %-4d: ", nTrack);
  177.   fflush(stdout);
  178.  
  179.   if (start_alarm(INTERVAL))
  180.     return -1;
  181.  
  182.   if (start_timer(&nLocal))
  183.     return -1;
  184.  
  185.   for (nCnt = 0; !time_over; nCnt++)
  186.   {
  187.     if (DskRead(nHandle, nCnt % nSides, 
  188.         nTrack + (nCnt / nSides) * nDirection, 1, nSectors, pBuffer))
  189.       return printf("Disk read error.\n"), -1;
  190.  
  191.     nData += nSectors * 512;
  192.   }
  193.  
  194.   if ((nTime = stop_timer(&nLocal, 1024)) == -1)
  195.     return -1;
  196.  
  197.   printf("%d k/sec\n", nData / nTime);
  198.  
  199.   return 0;
  200. }
  201.  
  202. int bench_hd_cpuusage(int nHandle, unsigned nSides, unsigned nSectors)
  203. {
  204.   int nCnt, nData = 0, nTime, nPercent;
  205.   QWORD nLocal;
  206.   TID dtid;
  207.   APIRET rc;
  208.  
  209.   printf("CPU usage by full speed disk transfers: ");
  210.   fflush(stdout);
  211.  
  212.   if (start_alarm(INTERVAL))
  213.     return -1;
  214.  
  215.   if (DosCreateThread(&dtid, dhry_thread, 0, 0, THREADSTACK))
  216.     return -1;
  217.  
  218.   if (start_timer(&nLocal))
  219.     return -1;
  220.  
  221.   for (nCnt = 0; !time_over; nCnt++)
  222.   {
  223.     if (DskRead(nHandle, nCnt % nSides, nCnt / nSides, 1, nSectors, pBuffer))
  224.       return printf("Disk read error.\n"), -1;
  225.  
  226.     nData += nSectors * 512;
  227.   }
  228.  
  229.   if ((nTime = stop_timer(&nLocal, 1024)) == -1)
  230.     return -1;
  231.  
  232.   if ((rc = DosWaitThread(&dtid, DCWW_WAIT)) && rc != ERROR_INVALID_THREADID)
  233.     return -1;                             /* it may have already terminated */
  234.  
  235.   if (dhry_result == 0)
  236.     dhry_result = 1; /* to avoid dividing by zero */
  237.  
  238.   dhry_time = (dhry_time + 500) / 1000;
  239.   nPercent = (dhry_result - Number_Of_Runs / dhry_time) * 100 / dhry_result;
  240.  
  241.   printf("%d%%\n", nPercent);
  242.  
  243.   return 0;
  244. }
  245.  
  246. int bench_hd_latency(int nHandle, unsigned nSectors)
  247. {
  248.   int nCnt, nSector, nTime;
  249.   QWORD nLocal;
  250.  
  251.   printf("Average latency time: ");
  252.   fflush(stdout);
  253.  
  254.   srand(1);
  255.  
  256.   if (start_alarm(INTERVAL))
  257.     return -1;
  258.  
  259.   if (start_timer(&nLocal))
  260.     return -1;
  261.  
  262.   for (nCnt = 0; !time_over; nCnt++)
  263.   {
  264.     nSector = rand() * nSectors / RAND_MAX + 1;
  265.  
  266.     if (DskRead(nHandle, 0, 0, nSector, 1, pBuffer))
  267.       return printf("Disk read error.\n"), -1;
  268.   }
  269.  
  270.   if ((nTime = stop_timer(&nLocal, 1000)) == -1)
  271.     return -1;
  272.  
  273.   nTime = nTime * 10 / nCnt;
  274.  
  275.   printf("%d.%d ms\n", nTime / 10, nTime % 10);
  276.  
  277.   return nTime;
  278. }
  279.  
  280. int bench_hd_seek(int nHandle, unsigned nSides, unsigned nSectors, unsigned nTracks)
  281. {
  282.   int nCnt, nSide, nTrack, nSector, nTime;
  283.   QWORD nLocal;
  284.  
  285.   printf("Average data access time: ");
  286.   fflush(stdout);
  287.  
  288.   srand(1);
  289.  
  290.   if (start_alarm(INTERVAL))
  291.     return -1;
  292.  
  293.   if (start_timer(&nLocal))
  294.     return -1;
  295.  
  296.   for (nCnt = 0; !time_over; nCnt++)
  297.   {
  298.     nSide   = rand() * nSides   / RAND_MAX;
  299.     nSector = rand() * nSectors / RAND_MAX;
  300.     nTrack  = rand() * nTracks  / RAND_MAX;
  301.  
  302.     if (DskRead(nHandle, nSide, nTrack, nSector, 1, pBuffer))
  303.       return printf("Disk read error.\n"), -1;
  304.   }
  305.  
  306.   if ((nTime = stop_timer(&nLocal, 1000)) == -1)
  307.     return -1;
  308.  
  309.   nTime = nTime * 10 / nCnt;
  310.  
  311.   printf("%d.%d ms\n", nTime / 10, nTime % 10);
  312.  
  313.   return 0;
  314. }
  315.  
  316. int bench_hd(int nDisk)
  317. {
  318.   int nHandle;
  319.   unsigned nSides, nTracks, nSectors;
  320.   char szName[8];
  321.  
  322.   sprintf(szName, "$%d:", nDisk);
  323.  
  324.   if ((nHandle = DskOpen(szName, 0, 0, &nSides, &nTracks, &nSectors)) < 0)
  325.     return printf("\nCannot access disk %d.\n", nDisk), -1;
  326.  
  327.   printf("\nHard disk %d: %d sides, %d cylinders, %d sectors per track = %d MB\n", 
  328.      nDisk, nSides, nTracks, nSectors,
  329.      nSides * nTracks * nSectors / 2048);
  330.  
  331.   if ((pBuffer = malloc(nSectors * 512)) == NULL)
  332.     return printf("\nNot enough memory.\n"), -1;
  333.  
  334.   bench_hd_bus(nHandle, nSectors);
  335.   bench_hd_transfer(nHandle, 0, 1, nSides, nSectors);
  336.   bench_hd_transfer(nHandle, nTracks - 1, -1, nSides, nSectors);
  337.   bench_hd_cpuusage(nHandle, nSides, nSectors);
  338.   bench_hd_latency(nHandle, nSectors);
  339.   bench_hd_seek(nHandle, nSides, nSectors, nTracks);
  340.  
  341.   free(pBuffer);
  342.   DskClose(nHandle);
  343.  
  344.   return 0;
  345. }
  346.  
  347. int bench_cd_transfer(int nHandle)
  348. {
  349.   int nCnt, nData = 0, nTime, nRate;
  350.   QWORD nLocal;
  351.  
  352.   printf("Data transfer rate: ");
  353.   fflush(stdout);
  354.   
  355.   if (start_alarm(INTERVAL))
  356.     return -1;
  357.  
  358.   if (start_timer(&nLocal))
  359.     return -1;
  360.  
  361.   for (nCnt = 0; !time_over; nCnt++)
  362.   {
  363.     if (CDRead(nHandle, nCnt * 32, 32, pBuffer) == -1)
  364.       return printf("CD-ROM read error.\n"), -1;
  365.  
  366.     nData += 32 * 2048;
  367.   }
  368.  
  369.   if ((nTime = stop_timer(&nLocal, 1024)) == -1)
  370.     return -1;
  371.  
  372.   nRate = nData / nTime;
  373.   printf("%d k/sec (~%.1fx)\n", nRate, (double) nRate / 150.0);
  374.  
  375.   return 0;
  376. }
  377.  
  378. int bench_cd_cpuusage(int nHandle)
  379. {
  380.   int nCnt, nData = 0, nTime, nPercent;
  381.   QWORD nLocal;
  382.   TID dtid;
  383.   APIRET rc;
  384.  
  385.   printf("CPU usage by full speed CD-ROM reads: ");
  386.   fflush(stdout);
  387.  
  388.   if (start_alarm(INTERVAL))
  389.     return -1;
  390.  
  391.   if (DosCreateThread(&dtid, dhry_thread, 0, 0, THREADSTACK))
  392.     return -1;
  393.  
  394.   if (start_timer(&nLocal))
  395.     return -1;
  396.  
  397.   for (nCnt = 0; !time_over; nCnt++)
  398.   {
  399.     if (CDRead(nHandle, nCnt * 32, 32, pBuffer) == -1)
  400.       return printf("CD-ROM read error.\n"), -1;
  401.  
  402.     nData += 32 * 2048;
  403.   }
  404.  
  405.   if ((nTime = stop_timer(&nLocal, 1024)) == -1)
  406.     return -1;
  407.  
  408.   if ((rc = DosWaitThread(&dtid, DCWW_WAIT)) && rc != ERROR_INVALID_THREADID)
  409.     return -1;                             /* it may have already terminated */
  410.  
  411.   if (dhry_result == 0)
  412.     dhry_result = 1; /* to avoid dividing by zero */
  413.  
  414.   dhry_time = (dhry_time + 500) / 1000;
  415.   nPercent = (dhry_result - Number_Of_Runs / dhry_time) * 100 / dhry_result;
  416.  
  417.   printf("%d%%\n", nPercent);
  418.  
  419.   return 0;
  420. }
  421.  
  422. int bench_cd_seek(int nHandle, unsigned nSectors)
  423. {
  424.   int nCnt, nSector, nTime;
  425.   QWORD nLocal;
  426.  
  427.   printf("Average data access time: ");
  428.   fflush(stdout);
  429.  
  430.   srand(1);
  431.  
  432.   if (start_alarm(INTERVAL))
  433.     return -1;
  434.  
  435.   if (start_timer(&nLocal))
  436.     return -1;
  437.  
  438.   for (nCnt = 0; !time_over; nCnt++)
  439.   {
  440.     nSector = (nSectors * 1000) / RAND_MAX;
  441.     nSector = nSector * rand() / 1000;
  442.  
  443.     if (CDRead(nHandle, nSector, 1, pBuffer) != 1)
  444.       return printf("CD-ROM read error.\n"), -1;
  445.   }
  446.  
  447.   if ((nTime = stop_timer(&nLocal, 1000)) == -1)
  448.     return -1;
  449.  
  450.   nTime = nTime * 10 / nCnt;
  451.  
  452.   printf("%d.%d ms\n", nTime / 10, nTime % 10);
  453.  
  454.   return 0;
  455. }
  456.  
  457. int bench_cd(int nDrive)
  458. {
  459.   int nHandle, nDriveLetter;
  460.   unsigned nSectors;
  461.   char szDrive[3], szUPC[8];
  462.  
  463.   if ((nDriveLetter = CDFind(nDrive)) == -1)
  464.     return printf("\nCannot access CD-ROM drive %d.\n", nDrive), -1;
  465.  
  466.   szDrive[0] = (char) nDriveLetter;
  467.   szDrive[1] = ':';
  468.   szDrive[2] = 0;
  469.  
  470.   if ((nHandle = CDOpen(szDrive, 1, szUPC, &nSectors)) == -1)
  471.     return -1;
  472.  
  473.   printf("\nCD-ROM drive %s %d sectors = %d MB\n", 
  474.      szDrive, nSectors, nSectors / 512);
  475.  
  476.   if ((pBuffer = malloc(32 * 2048)) == NULL)
  477.     return printf("\nNot enough memory.\n"), -1;
  478.  
  479.   /* spin up and seek to first sector */
  480.   if (CDRead(nHandle, 0, 32, pBuffer) == -1)
  481.     return printf("CD-ROM read error.\n"), -1;
  482.  
  483.   bench_cd_transfer(nHandle);
  484.   bench_cd_cpuusage(nHandle);
  485.   bench_cd_seek(nHandle, nSectors);
  486.  
  487.   free(pBuffer);
  488.   CDClose(nHandle);
  489.  
  490.   return 0;
  491. }
  492.  
  493. typedef struct 
  494. {
  495.   int nHandle, nData;
  496.   unsigned nSides, nSectors, nTracks;
  497.   void *pBuffer;
  498. }
  499. THREADPARMS;
  500.  
  501. VOID APIENTRY bench_concurrent_hd(ULONG nArg)
  502. {
  503.   THREADPARMS *ptr = (THREADPARMS *) nArg;
  504.   int nCnt;
  505.  
  506.   for (nCnt = 0; !time_over; nCnt++)
  507.   {
  508.     if (DskRead(ptr->nHandle, nCnt % ptr->nSides, nCnt / ptr->nSides, 1, 
  509.         ptr->nSectors, ptr->pBuffer))
  510.     {
  511.       printf("Disk read error.\n");
  512.       break;
  513.     }
  514.  
  515.     ptr->nData += ptr->nSectors * 512;
  516.   }
  517.  
  518.   DosExit(EXIT_THREAD, 0);
  519. }
  520.  
  521. VOID APIENTRY bench_concurrent_cd(ULONG nArg)
  522. {
  523.   THREADPARMS *ptr = (THREADPARMS *) nArg;
  524.   int nCnt;
  525.  
  526.   for (nCnt = 0; !time_over; nCnt++)
  527.   {
  528.     if (CDRead(ptr->nHandle, nCnt * 32, 32, ptr->pBuffer) == -1)
  529.     {
  530.       printf("CD-ROM read error.\n");
  531.       break;
  532.     }
  533.  
  534.     ptr->nData += 32 * 2048;
  535.   }
  536.  
  537.   DosExit(EXIT_THREAD, 0);
  538. }
  539.  
  540. int bench_concurrent(int nDisk, int nCD)
  541. {
  542.   int nDriveLetter, nTime, nPercent;
  543.   char szDrive[3], szUPC[8], szName[8];
  544.   THREADPARMS tHD, tCD;
  545.   TID tidHD, tidCD;
  546.   QWORD nLocal;
  547.   APIRET rc;
  548.  
  549.   sprintf(szName, "$%d:", nDisk);
  550.  
  551.   if ((tHD.nHandle = DskOpen(szName, 0, 0, 
  552.                  &tHD.nSides, &tHD.nTracks, &tHD.nSectors)) < 0)
  553.     return printf("\nCannot access disk %d.\n", nDisk), -1;
  554.  
  555.   if ((tHD.pBuffer = malloc(tHD.nSectors * 512)) == NULL)
  556.     return printf("\nNot enough memory.\n"), -1;
  557.  
  558.   if ((nDriveLetter = CDFind(nCD)) == -1)
  559.     return printf("\nCannot access CD-ROM drive %d.\n", nCD), -1;
  560.  
  561.   szDrive[0] = (char) nDriveLetter;
  562.   szDrive[1] = ':';
  563.   szDrive[2] = 0;
  564.  
  565.   if ((tCD.nHandle = CDOpen(szDrive, 1, szUPC, &tCD.nSectors)) == -1)
  566.     return -1;
  567.  
  568.   if ((tCD.pBuffer = malloc(32 * 2048)) == NULL)
  569.     return printf("\nNot enough memory.\n"), -1;
  570.  
  571.   /* spin up and seek to first sector */
  572.   if (CDRead(tCD.nHandle, 0, 32, tCD.pBuffer) == -1)
  573.     return printf("CD-ROM read error.\n"), -1;
  574.  
  575.   printf("\nConcurrent hard disk %d and CD-ROM %d reads at full speed:", nDisk, nCD);
  576.   fflush(stdout);
  577.   tHD.nData = tCD.nData = 0;
  578.  
  579.   if (start_alarm(INTERVAL))
  580.     return -1;
  581.  
  582.   if (start_timer(&nLocal))
  583.     return -1;
  584.  
  585.   if (DosCreateThread(&tidHD, bench_concurrent_hd, (ULONG) &tHD, 0, THREADSTACK))
  586.     return -1;
  587.   if (DosCreateThread(&tidCD, bench_concurrent_cd, (ULONG) &tCD, 0, THREADSTACK))
  588.     return -1;
  589.  
  590.   DosSetPriority(PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MAXIMUM, 0);
  591.   dhry_time = dhry_stone();
  592.   DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MINIMUM, 0);
  593.  
  594.   if ((rc = DosWaitThread(&tidHD, DCWW_WAIT)) && rc != ERROR_INVALID_THREADID)
  595.     return -1;                             /* it may have already terminated */
  596.   if ((rc = DosWaitThread(&tidCD, DCWW_WAIT)) && rc != ERROR_INVALID_THREADID)
  597.     return -1;                             /* it may have already terminated */
  598.  
  599.   if ((nTime = stop_timer(&nLocal, 1024)) == -1)
  600.     return -1;
  601.  
  602.   if (dhry_result == 0)
  603.     dhry_result = 1; /* to avoid dividing by zero */
  604.  
  605.   dhry_time = (dhry_time + 500) / 1000;
  606.   nPercent = (dhry_result - Number_Of_Runs / dhry_time) * 100 / dhry_result;
  607.  
  608.   printf("\nHard disk throughput: %d k/sec\n", tHD.nData / nTime);
  609.   printf("CD-ROM throughput: %d k/sec\n", tCD.nData / nTime);
  610.   printf("CPU usage: %d%%\n", nPercent);
  611.  
  612.   free(tCD.pBuffer);
  613.   CDClose(tCD.nHandle);
  614.  
  615.   free(tHD.pBuffer);
  616.   DskClose(tHD.nHandle);
  617.  
  618.   return 0;
  619. }
  620.  
  621. int bench_dhry(void)
  622. {
  623.   printf("Dhrystone benchmark for this CPU: ");
  624.   fflush(stdout);
  625.  
  626.   if (start_alarm(INTERVAL / 2))
  627.     return -1;
  628.  
  629.   // DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MAXIMUM, 0);
  630.   dhry_time = dhry_stone();
  631.   // DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MINIMUM, 0);
  632.  
  633.   dhry_time = (dhry_time + 500) / 1000;
  634.   dhry_result = Number_Of_Runs / dhry_time;
  635.  
  636.   printf("%d runs/sec\n", dhry_result);
  637.  
  638.   return 0;
  639. }
  640.  
  641. int main(int argc, char **argv)
  642. {
  643.   char szVersion[32];
  644.   USHORT nDisks;
  645.   int nCDROMs, nCount, xHD[26], xCD[26], cHD = 0, cCD = 0;
  646.  
  647.   strcpy(szVersion, rcsrev + sizeof("$Revision: ") - 1);
  648.   *strchr(szVersion, ' ') = 0;
  649.  
  650.   printf("\nDISKIO - Fixed Disk Benchmark, Version %s"
  651.      "\n(C) 1994-1997 Kai Uwe Rommel\n", szVersion);
  652.  
  653.   if (DosPhysicalDisk(INFO_COUNT_PARTITIONABLE_DISKS, &nDisks, sizeof(nDisks), 0, 0))
  654.     return printf("\nCannot determine number of disks.\n"), 1;
  655.  
  656.   printf("\nNumber of fixed disks: %d\n", nDisks);
  657.  
  658.   nCDROMs = CDFind(0);
  659.   printf("Number of CD-ROM drives: %d\n", nCDROMs);
  660.  
  661.   if (argc > 1)
  662.   {
  663.     nDisks = nCDROMs = 0;
  664.  
  665.     for (nCount = 1; nCount < argc; )
  666.       if (stricmp(argv[nCount], "-hd") == 0)
  667.       {
  668.     for (nCount++; argv[nCount][0] != '-'; nCount++)
  669.       xHD[nDisks++] = atoi(argv[nCount]);
  670.       }
  671.       else if (stricmp(argv[nCount], "-cd") == 0)
  672.       {
  673.     for (nCount++; argv[nCount][0] != '-'; nCount++)
  674.       xCD[nCDROMs++] = atoi(argv[nCount]);
  675.       }      
  676.       else if (stricmp(argv[nCount], "-c") == 0)
  677.       {
  678.     if (argv[nCount + 1][0] != '-' && argv[nCount + 2][0] != '-')
  679.     {
  680.       cHD = atoi(argv[nCount + 1]);
  681.       cCD = atoi(argv[nCount + 2]);
  682.       nCount += 3;
  683.     }
  684.       }
  685.       else if (stricmp(argv[nCount], "-?") == 0)
  686.       {
  687.     printf("\nUsage:\tdiskio [options]\n"
  688.            "\n\t-hd <list of hard disk numbers>"
  689.            "\n\t-cd <list of CD-ROM drive numbers>"
  690.                  "\n\t-c  <pair of hard disk and CD-ROM drive numbers>\n"
  691.            "\nHard disk and CD-ROM drive numbers are physical ones and start at 1."
  692.            "\nThe drive number lists must be blank separated.\n"
  693.            "\nWith -cd, -hd and -c you can explicitly select the drives to be used"
  694.            "\nfor hard disk, CD-ROM drive and concurrent hard disk and CD-ROM benchmarks.\n"
  695.            "\nIf none of them is used, all drives are used for hard disk and CD-ROM"
  696.            "\ndrive benchmarks and the first hard disk and CD-ROM drives are used"
  697.            "\nfor the concurrent hard disk and CD-ROM benchmark\n"
  698.            "\nExample: diskio -hd 2 3 -cd 1 -c 3 1\n");
  699.     exit(1);
  700.       }
  701.  
  702.       else
  703.     nCount++;
  704.   }
  705.   else
  706.   {
  707.     for (nCount = 1; nCount <= nDisks; nCount++)
  708.       xHD[nCount - 1] = nCount;
  709.  
  710.     for (nCount = 1; nCount <= nCDROMs; nCount++)
  711.       xCD[nCount - 1] = nCount;
  712.  
  713.     if (nDisks > 0 && nCDROMs > 0)
  714.       cHD = cCD = 1;
  715.   }
  716.  
  717.   printf("\nDhrystone 2.1 C benchmark routines (C) 1988 Reinhold P. Weicker\n");
  718.   bench_dhry();
  719.  
  720.   for (nCount = 0; nCount < nDisks; nCount++)
  721.     bench_hd(xHD[nCount]);
  722.  
  723.   for (nCount = 0; nCount < nCDROMs; nCount++)
  724.     bench_cd(xCD[nCount]);
  725.  
  726.   if (cHD != 0 && cCD != 0)
  727.     bench_concurrent(cHD, cCD);
  728.  
  729.   return 0;
  730. }
  731.  
  732. /* end of diskio.c */
  733.