home *** CD-ROM | disk | FTP | other *** search
/ Inside Multimedia 1995 July / IMM0795.ISO / share / os2 / sysbench / src / pmb_disk.c < prev    next >
C/C++ Source or Header  |  1994-11-05  |  10KB  |  477 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. // modified 1994-08-10 by Henrik Harmsen 
  8.  
  9. #define INTERVAL 8
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <ctype.h>
  15. #include <string.h>
  16.  
  17. #define INCL_DOS
  18. #define INCL_DOSDEVICES
  19. #define INCL_DOSDEVIOCTL
  20. #define INCL_DOSERRORS
  21. #include <os2.h>
  22.  
  23. static int DskOpen(char *drv, int lock, 
  24.         unsigned *sides, unsigned *tracks, unsigned *sectors);
  25. static int DskClose(int handle);
  26. static int DskRead(int handle, unsigned side, unsigned  track,
  27.         unsigned sector, unsigned nsects, void *buf);
  28. static int DskWrite(int handle, unsigned side, unsigned  track,
  29.          unsigned sector, unsigned nsects, void *buf);
  30.  
  31.  
  32. static int nHandle;
  33. static unsigned nSides, nTracks, nSectors;
  34. static char *pBuffer;
  35.  
  36. static HEV hSemTimer;
  37. static HTIMER hTimer;
  38. static QWORD nStart, nStop;
  39.  
  40. extern void err(char* s);
  41. extern void warn(char* s);
  42. extern void log(char* s);
  43.  
  44. static int start_timer(void)
  45. {
  46.   ULONG nPost;
  47.   APIRET rc;
  48.  
  49.   if ((rc = DosResetEventSem(hSemTimer, &nPost)) && rc != ERROR_ALREADY_RESET) {
  50.     log("Disk IO test : Semaphore error.");
  51.     exit(1);
  52.   }
  53.  
  54.   if(DosAsyncTimer(INTERVAL * 1000, (HSEM) hSemTimer, &hTimer)) {
  55.     log("Disk IO test : Timer error.");
  56.     exit(1);
  57.   }
  58.  
  59.   if (DosTmrQueryTime(&nStart)) {
  60.     log("Disk IO test : Timer error.");
  61.     exit(1);
  62.   }
  63.  
  64.   nPost = 0;
  65.  
  66.   return 0;
  67. }
  68.  
  69. static int time_over(void)
  70. {
  71.   ULONG nPost;
  72.  
  73.   if (DosQueryEventSem(hSemTimer, &nPost))
  74.     err("Disk IO test:Semaphore error.\n"), 1;
  75.  
  76.   return nPost;
  77. }
  78.  
  79. static int stop_timer(int accuracy)
  80. {
  81.   ULONG nFreq;
  82.  
  83.   if (DosTmrQueryTime(&nStop))
  84.     err("Disk IO test:Timer error.");
  85.   if (DosTmrQueryFreq(&nFreq))
  86.     err("Disk IO test:Timer error.");
  87.  
  88.   nFreq = (nFreq + accuracy / 2) / accuracy;
  89.  
  90.   return (nStop.ulLo - nStart.ulLo) / nFreq;
  91. }
  92.  
  93. static int bench_transfer(void)
  94. {
  95.   int nCnt, nData = 0, nTime;
  96.  
  97.   DosSleep(500);
  98.  
  99.   if (start_timer())
  100.     err("disk io error: start timer error");
  101.  
  102.   for (nCnt = 0; !time_over(); nCnt++)
  103.   {
  104.     if (DskRead(nHandle, nCnt % nSides, nCnt / nSides, 1, nSectors, pBuffer))
  105.       err("disk IO test error: Disk read error.");
  106.  
  107.     nData += nSectors * 512;
  108.   }
  109.  
  110.   if ((nTime = stop_timer(1000)) == -1)
  111.     err("disk io error: stop timer error");
  112.  
  113. //  printf("%d k/sec\n", nData / nTime);
  114.  
  115.   return (double)nData / ((double)nTime * 1.0e-3);
  116. }
  117.  
  118. static double bench_latency(void)
  119. {
  120.   int nCnt, nSector, nTime;
  121.  
  122.   srand(1);
  123.  
  124.   DosSleep(500);
  125.  
  126.   if (start_timer())
  127.     err("disk io error: start timer error");
  128.  
  129.   for (nCnt = 0; !time_over(); nCnt++)
  130.   {
  131.     nSector = (rand() * nSectors) / RAND_MAX + 1;
  132.  
  133.     if (DskRead(nHandle, 0, 0, nSector, 1, pBuffer))
  134.       err("disk IO test error: Disk read error.");
  135.   }
  136.  
  137.   if ((nTime = stop_timer(1000)) == -1)
  138.     err("disk io error: stop timer error");
  139.  
  140. //  nTime = nTime * 10 / nCnt;
  141.  
  142. //  printf("%d.%d ms\n", nTime / 10, nTime % 10);
  143.  
  144.   return (double)nTime/(double)nCnt*1.0e-3;
  145.  
  146. }
  147.  
  148. static double bench_seek(double nLatency)
  149. {
  150.   int nCnt, nTrack, nTime;
  151.  
  152.   srand(1);
  153.  
  154.   DosSleep(500);
  155.  
  156.   if (start_timer())
  157.     err("disk io error: start timer error");
  158.  
  159.   for (nCnt = 0; !time_over(); nCnt++)
  160.   {
  161.     nTrack = rand() * nTracks / RAND_MAX;
  162.  
  163.     if (DskRead(nHandle, 0, nTrack, 1, 1, pBuffer))
  164.       err("disk IO test error: Disk read error.");
  165.   }
  166.  
  167.   if ((nTime = stop_timer(1000)) == -1)
  168.     err("disk io error: stop timer error");
  169.  
  170. //  nTime = nTime * 10 / nCnt;
  171.  
  172.   return (double)nTime/(double)nCnt*1.0e-3 - nLatency;
  173. }
  174.  
  175. static double bench_disk_avseek(int nDisk)
  176. {
  177.   char szName[8];
  178.   double r;
  179.  
  180.   sprintf(szName, "$%d:", nDisk);
  181.  
  182.   if ((nHandle = DskOpen(szName, 0, &nSides, &nTracks, &nSectors)) < 0) {
  183.     log("Disk IO test error : Cannot access disk.");
  184.     exit(1);
  185.   }
  186.  
  187.   if ((pBuffer = malloc(nSectors * 512)) == NULL) {
  188.     log("Disk IO test error : malloc() failed.");
  189.     exit(1);
  190.   }
  191.  
  192.   r = bench_seek(bench_latency());
  193.  
  194.   free(pBuffer);
  195.   DskClose(nHandle);
  196.  
  197.   return r;
  198. }
  199.  
  200. static double bench_disk_transfer(int nDisk)
  201. {
  202.   char szName[8];
  203.   double r;
  204.  
  205.   sprintf(szName, "$%d:", nDisk);
  206.  
  207.   if ((nHandle = DskOpen(szName, 0, &nSides, &nTracks, &nSectors)) < 0) {
  208.     log("Disk IO test error : Cannot access disk.");
  209.     exit(1);
  210.   }
  211.  
  212.   if ((pBuffer = malloc(nSectors * 512)) == NULL) {
  213.     log("Disk IO test error : malloc() failed.");
  214.     exit(1);
  215.   }
  216.  
  217.   r = bench_transfer();
  218.  
  219.   free(pBuffer);
  220.   DskClose(nHandle);
  221.  
  222.   return r;
  223. }
  224.  
  225.  
  226. double pmb_diskio_avseek(int disknr)
  227. {
  228.   double r;
  229.  
  230.   disknr++;
  231.  
  232.   DosCreateEventSem(NULL, &hSemTimer, DC_SEM_SHARED, 0);
  233.   DosSleep(500);
  234.  
  235.   r = bench_disk_avseek(disknr);
  236.  
  237.   DosCloseEventSem(hSemTimer);
  238.   hSemTimer = 0;
  239.   return r;
  240. }
  241.  
  242. double pmb_diskio_transfer(int disknr)
  243. {
  244.   double r;
  245.  
  246.   disknr++;
  247.  
  248.   DosCreateEventSem(NULL, &hSemTimer, DC_SEM_SHARED, 0);
  249.   DosSleep(500);
  250.  
  251.   r = bench_disk_transfer(disknr);
  252.  
  253.   DosCloseEventSem(hSemTimer);
  254.   hSemTimer = 0;
  255.   return r;
  256. }
  257.  
  258. // return number of bytes on disk nDisk
  259. int pmb_diskio_disksize(int nDisk) {
  260.   char szName[8];
  261.  
  262.   nDisk++;
  263.  
  264.   sprintf(szName, "$%d:", nDisk);
  265.  
  266.   if ((nHandle = DskOpen(szName, 0, &nSides, &nTracks, &nSectors)) < 0) {
  267.     log("Disk IO test error : Cannot access disk.");
  268.     exit(1);
  269.   }
  270.  
  271.   DskClose(nHandle);
  272.   return nSides * nTracks * nSectors * 512;
  273. }
  274.  
  275. int pmb_diskio_nrdisks(void) {
  276.   USHORT nDisks;
  277.   int nCount;
  278.  
  279.   if (DosPhysicalDisk(INFO_COUNT_PARTITIONABLE_DISKS, &nDisks, sizeof(nDisks), 0, 0)) {
  280.     log("Disk IO test error : Cannot determine number of disks.");
  281.     exit(1);
  282.   }
  283.   return nDisks;
  284. }
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292. #define PHYSICAL     0x1000
  293. #define CATEGORY(x)  (((x) & PHYSICAL) ? IOCTL_PHYSICALDISK : IOCTL_DISK)
  294. #define HANDLE(x)    ((x) & ~PHYSICAL)
  295.  
  296. #pragma pack(1)
  297.  
  298. typedef struct
  299. {
  300.   BYTE   bCommand;
  301.   USHORT usHead;
  302.   USHORT usCylinder;
  303.   USHORT usFirstSector;
  304.   USHORT cSectors;
  305.   struct
  306.   {
  307.     USHORT usSectorNumber;
  308.     USHORT usSectorSize;
  309.   }
  310.   TrackTable[64];
  311. }
  312. TRACK;
  313.  
  314. static ULONG DosDevIOCtl32(PVOID pData, ULONG cbData, PVOID pParms, ULONG cbParms,
  315.             ULONG usFunction, HFILE hDevice)
  316. {
  317.   ULONG ulParmLengthInOut = cbParms, ulDataLengthInOut = cbData;
  318.   return DosDevIOCtl(HANDLE(hDevice), CATEGORY(hDevice), usFunction,
  319.              pParms, cbParms, &ulParmLengthInOut, 
  320.              pData, cbData, &ulDataLengthInOut);
  321. }
  322.  
  323. static int test_sector(int handle, int side, int track, int sector)
  324. {
  325.   char buffer[1024];
  326.   TRACK trk;
  327.  
  328.   trk.bCommand      = 0;
  329.   trk.usHead        = side;
  330.   trk.usCylinder    = track;
  331.   trk.usFirstSector = 0;
  332.   trk.cSectors      = 1;
  333.  
  334.   trk.TrackTable[0].usSectorNumber = sector;
  335.   trk.TrackTable[0].usSectorSize   = 512;
  336.  
  337.   return DosDevIOCtl32(buffer, sizeof(buffer), &trk, sizeof(trk), 
  338.                DSK_READTRACK, handle) == 0;
  339. }
  340.  
  341. static int DskOpen(char *drv, int lock, 
  342.         unsigned *sides, unsigned *tracks, unsigned *sectors)
  343. {
  344.   BIOSPARAMETERBLOCK bpb;
  345.   DEVICEPARAMETERBLOCK dpb;
  346.   HFILE handle;
  347.   USHORT physical;
  348.   ULONG action;
  349.   BYTE cmd = 0;
  350.  
  351.   if (isalpha(drv[0]) && drv[1] == ':' && drv[2] == 0)
  352.   {
  353.     if (DosOpen(drv, &handle, &action, 0L, FILE_NORMAL, FILE_OPEN,
  354.         OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |
  355.         OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE, 0L))
  356.       return -1;
  357.   }
  358.   else if (drv[0] == '$' && isdigit(drv[1]) && drv[2] == ':' && drv[3] == 0)
  359.   {
  360.     if (DosPhysicalDisk(INFO_GETIOCTLHANDLE, &physical, sizeof(physical), 
  361.             drv + 1, strlen(drv + 1) + 1))
  362.       return -1;
  363.     handle = physical | PHYSICAL;
  364.   }
  365.   else
  366.     return -1;
  367.  
  368.   if (handle & PHYSICAL)
  369.   {
  370.     if (DosDevIOCtl32(&dpb, sizeof(dpb), &cmd, sizeof(cmd), 
  371.               DSK_GETDEVICEPARAMS, handle))
  372.     {
  373.       DosPhysicalDisk(INFO_FREEIOCTLHANDLE, NULL, 0, &physical, sizeof(physical));
  374.       return -1;
  375.     }
  376.  
  377.     *sectors = dpb.cSectorsPerTrack;
  378.     *tracks  = dpb.cCylinders;
  379.     *sides   = dpb.cHeads;
  380.   }
  381.   else
  382.   {
  383.     if (DosDevIOCtl32(&bpb, sizeof(bpb), &cmd, sizeof(cmd), 
  384.               DSK_GETDEVICEPARAMS, handle))
  385.     {
  386.       DosClose(handle);
  387.       return -1;
  388.     }
  389.  
  390.     *sectors = bpb.usSectorsPerTrack;
  391.     *tracks  = bpb.cCylinders;
  392.     *sides   = bpb.cHeads;
  393.   }
  394.  
  395.  
  396.   if (lock && DosDevIOCtl32(0L, 0, &cmd, sizeof(cmd), DSK_LOCKDRIVE, handle))
  397.   {
  398.     if (handle & PHYSICAL)
  399.       DosPhysicalDisk(INFO_FREEIOCTLHANDLE, NULL, 0, &physical, sizeof(physical));
  400.     else
  401.       DosClose(handle);
  402.     return -1;
  403.   }
  404.  
  405.   if (*sectors >= 15) /* 360k floppies ... */
  406.     if (!test_sector(handle, 0, 0, 15))
  407.     {
  408.       if (*sectors == 15)
  409.         *tracks = 40;
  410.  
  411.       *sectors = 9;
  412.     }
  413.  
  414.   return handle;
  415. }
  416.  
  417. static int DskClose(int handle)
  418. {
  419.   BYTE cmd = 0;
  420.   USHORT physical = handle & ~PHYSICAL;
  421.  
  422.   DosDevIOCtl32(0L, 0, &cmd, sizeof(cmd), DSK_UNLOCKDRIVE, handle);
  423.  
  424.   if (handle & PHYSICAL)
  425.     return DosPhysicalDisk(INFO_FREEIOCTLHANDLE, NULL, 0, 
  426.                &physical, sizeof(physical));
  427.   else
  428.     return DosClose(handle);
  429. }
  430.  
  431. static int DskRead(int handle, unsigned side, unsigned  track,
  432.             unsigned sector, unsigned nsects, void *buf)
  433. {
  434.   TRACK trk;
  435.   unsigned cnt;
  436.  
  437.   trk.bCommand      = 0;
  438.   trk.usHead        = side;
  439.   trk.usCylinder    = track;
  440.   trk.usFirstSector = 0;
  441.   trk.cSectors      = nsects;
  442.  
  443.   for (cnt = 0; cnt < nsects; cnt++)
  444.   {
  445.     trk.TrackTable[cnt].usSectorNumber = sector + cnt;
  446.     trk.TrackTable[cnt].usSectorSize   = 512;
  447.   }
  448.  
  449.   return DosDevIOCtl32(buf, nsects * 512, &trk, sizeof(trk), 
  450.                        DSK_READTRACK, handle);
  451. }
  452.  
  453. static int DskWrite(int handle, unsigned side, unsigned  track,
  454.              unsigned sector, unsigned nsects, void *buf)
  455. {
  456.   TRACK trk;
  457.   unsigned cnt;
  458.  
  459.   trk.bCommand      = 0;
  460.   trk.usHead        = side;
  461.   trk.usCylinder    = track;
  462.   trk.usFirstSector = 0;
  463.   trk.cSectors      = nsects;
  464.  
  465.   for (cnt = 0; cnt < nsects; cnt++)
  466.   {
  467.     trk.TrackTable[cnt].usSectorNumber = sector + cnt;
  468.     trk.TrackTable[cnt].usSectorSize   = 512;
  469.   }
  470.  
  471.   return DosDevIOCtl32(buf, nsects * 512, &trk, sizeof(trk), 
  472.                        DSK_WRITETRACK, handle);
  473. }
  474.  
  475.  
  476.  
  477.