NVMe Passthrough for vendor specific commands returns error 1117

Raymond Shi 1 Reputation point
2021-01-27T08:56:00.157+00:00

I try to send vendor-specific cmd 0xD0 for NVMe passthrough. I have read this document in great detail, however, I can not seem to get the pass-through mechanism to work against NVMe SSD.

I have also verified, that the device is able to send the Command Effects Log with the 0xD0 and 0xD1 commands under Linux environment.

However, when i try to send a Vendor Specific Admin command with any command code from 0xD0 ~ 0xD1 i get the error 1117 (ERROR_IO_DEVICE)

Here is the code i use to send a Vendor Specific Admin command:

BOOL result;
PVOID buffer = NULL;
ULONG bufferLength = 0;
ULONG returnedLength = 0;
ULONG imageBufferLength;

PSTORAGE_PROTOCOL_COMMAND protocolCommand = NULL;
PNVME_COMMAND command = NULL;

//
// Allocate buffer for use.
//
bufferLength = FIELD_OFFSET(STORAGE_PROTOCOL_COMMAND, Command) +
STORAGE_PROTOCOL_COMMAND_LENGTH_NVME + 4096 + sizeof(NVME_ERROR_INFO_LOG);
//bufferLength += imageBufferLength;
_tprintf(_T("\t buffer bufferSize: %d\n"), bufferLength);
buffer = (PVOID)malloc(bufferLength);
if (buffer == NULL) {
_tprintf(_T("allocate buffer failed, error code:%d exit.\n"), GetLastError());
return GetLastError();
}

// Initialize query data structure to get Identify Controller Data.
//
ZeroMemory(buffer, bufferLength);
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->TimeOutValue = 10;
protocolCommand->ErrorInfoOffset = FIELD_OFFSET(STORAGE_PROTOCOL_COMMAND, Command) + STORAGE_PROTOCOL_COMMAND_LENGTH_NVME;
protocolCommand->DataFromDeviceBufferOffset = protocolCommand->ErrorInfoOffset + protocolCommand->ErrorInfoLength;
protocolCommand->CommandSpecific = STORAGE_PROTOCOL_SPECIFIC_NVME_ADMIN_COMMAND;
command = (PNVME_COMMAND)protocolCommand->Command;
command->CDW0.OPC = 0xD0;
command->u.GENERAL.CDW10 = 0;
command->u.GENERAL.CDW12 = 8;
command->u.GENERAL.CDW13 = 0;
command->u.GENERAL.CDW15 = 0;
//
// Send request down.
//
result = DeviceIoControl(hDevice,
IOCTL_STORAGE_PROTOCOL_COMMAND,
buffer,
bufferLength,
buffer,
bufferLength,
&returnedLength,
NULL
);
if (result == FALSE) {
_tprintf(_T("\t IOCTL - Send request failed. %d.\n"), GetLastError());
goto Exit;
}
if (protocolCommand->ReturnStatus != STORAGE_PROTOCOL_STATUS_SUCCESS) {
_tprintf(_T("\t - protocolCommand failed. ReturnCode %d.\n"), protocolCommand->ReturnStatus);
goto Exit;
}

Exit:

if (fileHandle != NULL) {
CloseHandle(fileHandle);
}
if (buffer != NULL) {
free(buffer);
}
return 0;

Please let me know what am i doing wrong since i need to get this to work with our device under windows.

Any help is greatly appreciated!

Windows Hardware Performance
Windows Hardware Performance
Windows: A family of Microsoft operating systems that run across personal computers, tablets, laptops, phones, internet of things devices, self-contained mixed reality headsets, large collaboration screens, and other devices.Hardware Performance: Delivering / providing hardware or hardware systems or adjusting / adapting hardware or hardware systems.
1,613 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Raymond Shi 1 Reputation point
    2021-01-29T01:36:58.977+00:00

    Hi Daisy,

    Thank you for your help!

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.