1 /*
2  * Copyright (C) 2004 ReactOS Team
3  *
4  * COPYRIGHT:       See COPYING in the top level directory
5  * PROJECT:         ReactOS diskspeed.exe
6  * FILE:            apps/tests/diskspeed/diskspeed.c
7  * PURPOSE:         Determines disk transfer rates
8  * PROGRAMMER:
9  */
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #define WIN32_NO_STATUS
14 #include <windows.h>
15 #define NTOS_MODE_USER
16 #include <ndk/ntndk.h>
17 
18 #define _NTSCSI_USER_MODE_
19 #include <ntddscsi.h>
20 #include <scsi.h>
21 
GetInquiryData(HANDLE hDevice,PINQUIRYDATA InquiryData)22 BOOL GetInquiryData(HANDLE hDevice, PINQUIRYDATA InquiryData)
23 {
24   BOOL Result;
25   DWORD dwReturned;
26   SCSI_ADDRESS ScsiAddress;
27   PSCSI_ADAPTER_BUS_INFO AdapterInfo;
28   PSCSI_INQUIRY_DATA InquiryBuffer;
29   BYTE Buffer[4096];
30   int i;
31 
32   Result = DeviceIoControl(hDevice,
33 	                   IOCTL_SCSI_GET_ADDRESS,
34 			   NULL,
35 			   0,
36 			   &ScsiAddress,
37 			   sizeof(ScsiAddress),
38 			   &dwReturned,
39 			   FALSE);
40   if (Result == FALSE)
41     {
42       return FALSE;
43     }
44   Result = DeviceIoControl(hDevice,
45 	                   IOCTL_SCSI_GET_INQUIRY_DATA,
46 			   NULL,
47 			   0,
48 			   Buffer,
49 			   sizeof(Buffer),
50 			   &dwReturned,
51 			   FALSE);
52   if (Result)
53     {
54       AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer;
55       for (i = 0; i < AdapterInfo->NumberOfBuses; i++)
56 	{
57 	  InquiryBuffer = (PSCSI_INQUIRY_DATA) (Buffer + AdapterInfo->BusData[i].InquiryDataOffset);
58 	  if (AdapterInfo->BusData[i].InquiryDataOffset)
59 	    {
60 	       while (1)
61 	         {
62 		   if (InquiryBuffer->PathId == ScsiAddress.PathId &&
63 		       InquiryBuffer->TargetId == ScsiAddress.TargetId &&
64 		       InquiryBuffer->Lun == ScsiAddress.Lun)
65 		     {
66 		       memcpy(InquiryData, InquiryBuffer->InquiryData, sizeof(INQUIRYDATA));
67 		       return TRUE;
68 		     }
69 		   if (InquiryBuffer->NextInquiryDataOffset == 0)
70 		     {
71 		       break;
72 		     }
73 		   InquiryBuffer = (PSCSI_INQUIRY_DATA) (Buffer + InquiryBuffer->NextInquiryDataOffset);
74 		 }
75 	    }
76 	}
77     }
78   return FALSE;
79 }
80 
81 
82 
main(void)83 int main(void)
84 {
85     HANDLE hDevice;
86     OVERLAPPED ov;
87 
88     PBYTE Buffer = NULL ;
89     DWORD Start;
90     DWORD dwReturned;
91     DWORD dwReadTotal;
92     DWORD Size;
93     BOOL Result;
94     ULONG Drive;
95     CHAR Name[20];
96 
97     INQUIRYDATA InquiryData;
98 
99 
100     Drive = 0;
101     while (1)
102       {
103         sprintf(Name, "\\\\.\\PHYSICALDRIVE%ld", Drive);
104 	hDevice = CreateFile(Name,
105 	                     GENERIC_READ,
106 			     FILE_SHARE_READ,
107 			     NULL,
108 			     OPEN_EXISTING,
109 			     0,
110 			     NULL);
111 	if (hDevice == INVALID_HANDLE_VALUE)
112 	  {
113 	    if (Drive > 0)
114 	      {
115 	        VirtualFree(Buffer, 512 * 1024, MEM_RELEASE);
116 	      }
117 	    else
118 	      {
119 	        printf("Cannot open '%s'\n", Name);
120 	      }
121 	    break;
122 	  }
123         if (Drive == 0)
124 	  {
125             printf("Transfer Size (kB)           1     2     4     8    16    32    64   128   256\n");
126             printf("Transfer Rate (MB/s)\n");
127             printf("-------------------------------------------------------------------------------\n");
128 
129 	    Buffer = VirtualAlloc(NULL, 512 * 1024, MEM_COMMIT, PAGE_READWRITE);
130 	  }
131         Result = GetInquiryData(hDevice, &InquiryData);
132         if (Result)
133 	  {
134             printf("%.24s ", InquiryData.VendorId);
135 	  }
136 	else
137 	  {
138 	    printf("Disk %ld                   ", Drive + 1);
139 	  }
140         Size = 1024;
141         memset(&ov, 0, sizeof(OVERLAPPED));
142 	while (Size <= 256 * 1024)
143 	  {
144 	    memset(Buffer, 0, Size);
145 	    dwReadTotal = 0;
146 
147             Start = GetTickCount() + 2000;
148 	    while (Start > GetTickCount())
149 	      {
150 	        Result = ReadFile(hDevice, Buffer, Size, &dwReturned, &ov);
151 		if (Result)
152 		  {
153 		    dwReadTotal += dwReturned;
154 		    ov.Offset += dwReturned;
155 		  }
156 	      }
157 	    dwReadTotal /= 2048;
158             printf("%3ld.%ld ", dwReadTotal / 1024, (dwReadTotal % 1024) * 10 / 1024);
159 	    Size *= 2;
160 	  }
161         printf("\n");
162 	CloseHandle(hDevice);
163 	Drive++;
164       }
165     printf("\n");
166 
167 
168     return 0;
169 }
170