windows環境之下如何新增NVMe VSC 命令
work with NVMe driver
Vendor Specific Command
筆者剛開始使用pass through傳送VSC的命令總是不能成功,最後發現是這個問題。
windows Inbox Driver 的pass through 機制要求如果要支援VSCcommand, 那麼必須要有Command Support and Effects log,這個log裡面填寫所有主控晶片支援的命令。因此在設定一個新的命令之前需要在主控中實現Command Support and Effects log。
1. 首先在Identify裡面需要將Log Page Attributes (LPA)的bit 1 置為1以告訴Host,我們支援Command Support and Effects log, 主機上電後會先發送Identify command,主機會解析收到的回覆內容
2.後面主機會發行get log page command 來取走Command Support and Effects log.
3.主機解析完所有的Command Support and Effects log,就知道了你的主控晶片支援的命令列表,不在此列表中的命令使用pass through的時候都會被driver擋掉,DeviceIoControl函式的返回值為1(INVALID FUNCTION)
4. 在這之後你就可以愉快地傳送命令了
5. DeviceIOControl函式的用法
PVOID buffer = NULL;
ULONG bufferLength = 0;
ULONG returnedLength = 0;
PSTORAGE_PROTOCOL_COMMAND protocolCommand = NULL;
bufferLength = FIELD_OFFSET(STORAGE_PROTOCOL_COMMAND, Command) +
STORAGE_PROTOCOL_COMMAND_LENGTH_NVME +
sizeof(NVME_ERROR_INFO_LOG) + 4096 ;
buffer = malloc(bufferLength);
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 = 0xFF;
command->u.GENERAL.CDW10 = 0xto_fill_in;
command->u.GENERAL.CDW12 = 0xto_fill_in;
command->u.GENERAL.CDW13 = 0xto_fill_in;
//
// Send request down.
//
result = DeviceIoControl(DeviceList[DeviceIndex].Handle,
IOCTL_STORAGE_PROTOCOL_COMMAND,
buffer,
bufferLength,
buffer,
bufferLength,
&returnedLength,
NULL
);
至於Command Support and Effects log裡面的結構體怎麼填寫請自己看 NVMe Express。
參考:https://technet.microsoft.com/zh-cn/mt718131(v=vs.80)