windows-nt/Source/XPSP1/NT/sdktools/wcache/wcache.c
2020-09-26 16:20:57 +08:00

376 lines
12 KiB
C

#include <nt.h>
#include <ntddscsi.h>
#include <ntdddisk.h>
#include <ntddcdrm.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdio.h>
#include <process.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <scsi.h>
typedef struct _MODE_SENSE_PASS_THROUGH {
SCSI_PASS_THROUGH Srb;
ULONG Reserved;
UCHAR SenseData[32];
UCHAR DataBuffer[256];
} MODE_SENSE_PASS_THROUGH, *PMODE_SENSE_PASS_THROUGH;
VOID
Usage(
VOID
);
int __cdecl
main( int argc, char **argv )
{
ULONG portNumber = 0;
ULONG physicalDrive = 0,
selectedDrive = 0xFFFFFFFF;
HANDLE volumeHandle,driveHandle;
UNICODE_STRING unicodeString;
OBJECT_ATTRIBUTES objectAttributes;
NTSTATUS ntStatus;
PSCSI_ADAPTER_BUS_INFO adapterInfo;
PSCSI_BUS_DATA busData;
PSCSI_INQUIRY_DATA inquiryData;
PINQUIRYDATA deviceInquiryData;
ULONG bytesTransferred;
ULONG i, j;
PCHAR pageData,pch;
UCHAR modeOperation,
cacheSettings;
INT args;
BOOLEAN disableCache = FALSE,
enableCache = FALSE;
BOOLEAN displayAll = TRUE;
UCHAR buffer[32];
UCHAR driveBuffer[20];
CHAR driver[9];
MODE_SENSE_PASS_THROUGH modeSenseData;
if ( argc > 3 ) {
Usage();
exit(1);
} else if (argc > 1 ) {
displayAll = FALSE;
args = 1;
while ( args < argc ) {
pch = argv[args];
if ( *pch == '-' ) {
BOOL exitSwitch = FALSE;
pch++;
switch( *pch ) {
case 'd':
disableCache = TRUE;
break;
case 'e':
enableCache = TRUE;
break;
case '?':
Usage();
exit(1);
break;
default:
Usage();
exit(1);
}
pch++;
} else {
if (!isdigit(*pch)) {
Usage();
exit(1);
}
selectedDrive = atol(pch);
}
args++;
}
}
printf("\nDrive Port Bus TID LUN Vendor ReadCache WriteCache\n");
printf( "--------------------------------------------------------------------");
while (TRUE) {
memset( buffer, 0, sizeof( buffer ) );
sprintf( buffer,"\\\\.\\Scsi%d:",portNumber);
//
// Open the volume with the DOS name.
//
volumeHandle = CreateFile(buffer,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
0);
if( volumeHandle == INVALID_HANDLE_VALUE ) {
break;
}
//
// Allocate memory to store the inquiry data.
//
adapterInfo = (PSCSI_ADAPTER_BUS_INFO)malloc( 0x400 );
if (adapterInfo == NULL) {
printf( "Can't allocate memory for bus data\n" );
CloseHandle( volumeHandle );
return 1;
}
//
// Issue device control to get configuration information.
//
if (!DeviceIoControl( volumeHandle,
IOCTL_SCSI_GET_INQUIRY_DATA,
NULL,
0,
adapterInfo,
0x400,
&bytesTransferred,
NULL)) {
fprintf(stderr, "IOCTL_SCSI_GET_INQUIRY_DATA failed [Error %d].\n", GetLastError() );
free(adapterInfo);
CloseHandle( volumeHandle );
return 2;
}
//
// Display devices on buses.
//
for (i=0; i < adapterInfo->NumberOfBuses; i++) {
busData = &adapterInfo->BusData[i];
inquiryData = (PSCSI_INQUIRY_DATA)((PUCHAR)adapterInfo + busData->InquiryDataOffset);
for (j=0; j<busData->NumberOfLogicalUnits; j++) {
//
// Make sure VendorId string is null terminated.
//
deviceInquiryData = (PINQUIRYDATA)&inquiryData->InquiryData[0];
//
// Determine the perpherial type.
//
if (deviceInquiryData->DeviceType == DIRECT_ACCESS_DEVICE) {
deviceInquiryData->ProductRevisionLevel[0] = '\0';
if (displayAll || (selectedDrive == physicalDrive)) {
printf("\n%2d %2d %2d %2d %2d ",
physicalDrive,
portNumber,
inquiryData->PathId,
inquiryData->TargetId,
inquiryData->Lun);
//
// Display product information.
//
printf(" %s", deviceInquiryData->VendorId);
//
// Open handle to the PhysicalDrive
//
sprintf(driveBuffer,"\\\\.\\PhysicalDrive%d",physicalDrive);
driveHandle = CreateFile(driveBuffer,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (driveHandle == INVALID_HANDLE_VALUE) {
printf("CreateFile for %s failed. Error = %x\n",
driveBuffer,
GetLastError() );
return 3;
}
//
// Issue mode sense to see if caches are enabled.
//
ZeroMemory(&modeSenseData, sizeof(MODE_SENSE_PASS_THROUGH));
modeSenseData.Srb.Length = sizeof(SCSI_PASS_THROUGH);
modeSenseData.Srb.CdbLength = 6;
modeSenseData.Srb.DataIn = SCSI_IOCTL_DATA_IN;
modeSenseData.Srb.DataBufferOffset = offsetof(MODE_SENSE_PASS_THROUGH, DataBuffer);
modeSenseData.Srb.SenseInfoOffset = offsetof(MODE_SENSE_PASS_THROUGH, SenseData);
modeSenseData.Srb.DataTransferLength = 0xFF;
modeSenseData.Srb.TimeOutValue = 10;
ZeroMemory(&modeSenseData.Srb.Cdb, 16);
modeSenseData.Srb.Cdb[0] = 0x1A;
modeSenseData.Srb.Cdb[2] = 8;
modeSenseData.Srb.Cdb[4] = 0xFF;
if (!DeviceIoControl(driveHandle,
IOCTL_SCSI_PASS_THROUGH_DIRECT,
&modeSenseData,
sizeof(modeSenseData),
&modeSenseData,
sizeof(modeSenseData),
&bytesTransferred,
FALSE)) {
fprintf(stderr,"Mode sense failed. Error = %x\n",
GetLastError() );
return 4;
}
//
// Display current values
//
pageData = modeSenseData.DataBuffer;
(ULONG_PTR)pageData += 6 + pageData[3];
cacheSettings = *pageData;
if (displayAll || (physicalDrive == selectedDrive)) {
printf(" %s ", (cacheSettings & 1) ? "Disabled" : "Enabled");
printf(" %s", (cacheSettings & 4) ? "Enabled" : "Disabled");
}
if ((enableCache || disableCache) && (physicalDrive == selectedDrive)) {
//
// Build mode select - caching page.
//
// Clean out reserved areas of data buffer and update others
//
modeSenseData.Srb.SenseInfoLength = 32;
pageData = modeSenseData.DataBuffer;
modeSenseData.Srb.Cdb[4] = *pageData + 1;
modeSenseData.Srb.Cdb[2] = 0x00;
modeSenseData.Srb.Cdb[1] = 0x11;
*pageData = 0;
(ULONG_PTR)pageData += 4 + pageData[3];
*pageData &= 0x3F;
pageData++;
pageData++;
*pageData &= 0x07;
modeSenseData.DataBuffer[5] = 0x00;
modeSenseData.DataBuffer[6] = 0x00;
modeSenseData.DataBuffer[7] = 0x00;
modeSenseData.Srb.DataIn = SCSI_IOCTL_DATA_OUT;
modeSenseData.Srb.DataTransferLength = modeSenseData.Srb.Cdb[4];
if (disableCache) {
//
// Disable write cache
//
*pageData &= 0x03;
} else {
//
// Enable the cache.
//
*pageData |= 0x04;
}
modeSenseData.Srb.Cdb[0] = 0x15;
if (!DeviceIoControl(driveHandle,
IOCTL_SCSI_PASS_THROUGH_DIRECT,
&modeSenseData,
sizeof(modeSenseData),
&modeSenseData,
sizeof(modeSenseData),
&bytesTransferred,
FALSE)) {
fprintf(stderr,"Mode select failed. Error = %x\n",
GetLastError() );
} else {
printf("\nWrite cache successfully %s\n", (enableCache ? "Enabled" : "Disabled"));
}
}
CloseHandle(driveHandle );
}
physicalDrive++;
}
//
// Get next device data.
//
inquiryData =
(PSCSI_INQUIRY_DATA)((PUCHAR)adapterInfo + inquiryData->NextInquiryDataOffset);
}
}
free (adapterInfo);
CloseHandle(volumeHandle );
portNumber++;
}
printf("\n");
return 0;
}
VOID Usage(
VOID
) {
fprintf(stderr,"WCACHE: Usage wcache [-options] <PhysicalDrive Number>\n");
fprintf(stderr,"\n");
fprintf(stderr," where options are: e - Enable Write Cache for the <PhysicalDrive>\n");
fprintf(stderr," d - Disable Write Cache for the <PhysicalDrive>\n");
fprintf(stderr," dumps current values for all drives when invoked with no options\n");
fprintf(stderr,"\n");
}