NVMe Sef-Test Windows 10

Category: windows hardware wdk and driver development

Question

Ashok_ai on Fri, 31 Aug 2018 18:04:59


I am trying to develop self test  for NVMe drives on Windows 10 OS using IOCTL's. However, DeviceIoControl() method returned 0 and GetLastError() method showed error code as 87 on RS2 (and 317 error code on RS3). I tested the code on NVMe 1.3 version drives (WDC PC SN720 SDAPNTW-512G-1006 and others) "Drive self Test" bit is enabled in Idenitfy structure.

Can some one suggest what could be wrong with the following code.  And also I would like to know if RS3 OS supports NVMe self Test implementation. 

BOOL NVMeTest::NVMeSelfTest(std::string driveHandleStr)
{
 BOOL   result;
 PVOID buffer = NULL;
 ULONG bufferLength = 0;
 ULONG   returnedLength = 0;

PSTORAGE_PROPERTY_QUERY query = NULL;
 PSTORAGE_PROTOCOL_SPECIFIC_DATA protocolData = NULL;
 PSTORAGE_PROTOCOL_DATA_DESCRIPTOR protocolDataDescr = NULL;

HANDLE hPhyDrive = CreateFile(LPCSTR(driveHandleStr.c_str()),
  GENERIC_READ | GENERIC_WRITE,
  FILE_SHARE_READ | FILE_SHARE_WRITE,
  NULL,
  OPEN_EXISTING,
  0,
  NULL);

if (hPhyDrive == INVALID_HANDLE_VALUE)
 {
  //printf("Invalid handle!");
  return FALSE;
 }
 //
 // Allocate buffer for use.
 //
 ULONG testlength = FIELD_OFFSET(STORAGE_PROTOCOL_COMMAND, Command);
 bufferLength = FIELD_OFFSET(STORAGE_PROTOCOL_COMMAND, Command) + STORAGE_PROTOCOL_COMMAND_LENGTH_NVME +
  4096 + sizeof(NVME_ERROR_INFO_LOG);
 buffer = malloc(bufferLength);
 ZeroMemory(buffer, bufferLength);
 if (buffer == NULL) {
  //printf("DeviceNVMeQueryProtocolDataTest: allocate buffer failed, exit.\n");
  return FALSE;
 }

 PSTORAGE_PROTOCOL_COMMAND protocolCommand = (PSTORAGE_PROTOCOL_COMMAND)buffer;

 protocolCommand->Version = STORAGE_PROTOCOL_STRUCTURE_VERSION;
 protocolCommand->Length = sizeof(STORAGE_PROTOCOL_COMMAND);
 protocolCommand->ProtocolType = ProtocolTypeNvme;
 protocolCommand->Flags = STORAGE_PROTOCOL_COMMAND_FLAG_ADAPTER_REQUEST;
 protocolCommand->CommandLength = STORAGE_PROTOCOL_COMMAND_LENGTH_NVME;
 protocolCommand->ErrorInfoLength = sizeof(NVME_ERROR_INFO_LOG);
 // protocolCommand->DataFromDeviceTransferLength = 4096;
 protocolCommand->DataToDeviceTransferLength = 4096; // 4096;
 protocolCommand->TimeOutValue = 180;
 protocolCommand->ErrorInfoOffset = FIELD_OFFSET(STORAGE_PROTOCOL_COMMAND, Command) + STORAGE_PROTOCOL_COMMAND_LENGTH_NVME;
 // protocolCommand->DataFromDeviceBufferOffset = protocolCommand->ErrorInfoOffset + protocolCommand->ErrorInfoLength;
 protocolCommand->DataToDeviceBufferOffset = protocolCommand->ErrorInfoOffset + protocolCommand->ErrorInfoLength;
 protocolCommand->CommandSpecific = STORAGE_PROTOCOL_SPECIFIC_NVME_ADMIN_COMMAND;

 PNVME_COMMAND command = (PNVME_COMMAND)protocolCommand->Command;

 command->CDW0.OPC = 0x14;
 //command->NSID = 0x01;
 command->u.GENERAL.CDW10 = 0x01;

 // 
 // Send request down. 
 // 
 result = DeviceIoControl(hPhyDrive,
  IOCTL_STORAGE_PROTOCOL_COMMAND,
  buffer,
  bufferLength,
  buffer,
  bufferLength,
  &returnedLength,
  NULL
 );
 if (result == 0)
 {
  printf("Error occurred %d\n", GetLastError()); // Returns 87 for RS2 OS and 317 for RS3 OS
  free(buffer);
  return FALSE;
 }

 return TRUE;
}

Replies

moojito on Sat, 01 Sep 2018 01:22:37


NVMe passthru on MS only supports vendors specific admin and io commands, device also needs to support command effects log and mark the vendor specific command as supported.