weixin_43787407 2024-12-28 11:59 采纳率: 0%
浏览 82
已结题

windows 上位机与nvme盘片通讯

问题描述:
我打算开发一款上位机程序,通过windows API 的nvme部分下发nvne指令给nvme 盘片,发现有很多问题,,我无法确定这种操作是否可行。(我的代码时参考微软nvme部分示例)

img

#include <iostream>

#include  <string>
#include  <Windows.h>
#include <nvme.h>

using namespace  std;

int main()
{
    // 打开设备
    string devicePath = "\\\\.\\PhysicalDrive0";
    HANDLE deviceHandle = CreateFileA(devicePath.c_str(), GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
    printf("deviceHandle = %d", deviceHandle);
    if (deviceHandle == INVALID_HANDLE_VALUE) {
        DWORD error = GetLastError();
        cout << "\r\nFailed to open device. Error code: \r\n" << error << endl;
        system("pause");
        return 0;
    }

    if (deviceHandle == INVALID_HANDLE_VALUE) {
        DWORD error = GetLastError();
        cout << "\r\nFailed to open device. Error code: \r\n" << error;
        system("pause");
        return 0;

    }

    // 构造协议命令
    const int bufferLength = 4096*2;
    char* inputbuffer = new char[bufferLength];
    char* outputbuffer = new char[bufferLength];
    //char outputbuffer[bufferLength];
    ZeroMemory(inputbuffer, bufferLength);
    ZeroMemory(outputbuffer, bufferLength);

    PSTORAGE_PROTOCOL_COMMAND protocolCommand = (PSTORAGE_PROTOCOL_COMMAND)inputbuffer;

    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;

    //NVME_COMMAND_User *command = (PNVME_COMMAND)protocolCommand->Command;

    //NVME_COMMAND_User *command = new NVME_COMMAND_User();
    PNVME_COMMAND command = (PNVME_COMMAND)protocolCommand->Command;
    command->CDW0.OPC = 0x06;  // 自定义操作码
    command->u.GENERAL.CDW10 = 0x1;  // 填充数据
    command->u.GENERAL.CDW11 = 0x0;
    //command->u.GENERAL.CDW12 = 0x00000000;
    //command->u.GENERAL.CDW13 = 0x00000000;
    command->u.GENERAL.CDW14 = 0x0;

    // 发送命令
    DWORD returnedLength = 0;


    BOOL result = DeviceIoControl(deviceHandle,
        IOCTL_STORAGE_PROTOCOL_COMMAND,
        inputbuffer, bufferLength,
        inputbuffer, bufferLength,
        &returnedLength, nullptr);

    cout << "\r\n protocolCommand->ReturnStatus: " << protocolCommand->ReturnStatus<<"\n";
    cout << "\r\nresult: " << result<<"\n";

    cout << "\rreturnedLength:  " << returnedLength<<"\n";

    if (!result) {
        DWORD error = GetLastError();
        cout << "\r\nFailed to send protocol command. Error code: \r\n" << error;
        CloseHandle(deviceHandle);
        system("pause");
        return 0;
    }
    else
    {
        cout << "\r\nSuccess to DeviceIoControl.\r\n" << endl;
    }
    // 打印 outputbuffer 中的数据
    cout << "\r\nOutput Buffer: \n";
    for (DWORD i = protocolCommand->ErrorInfoOffset + protocolCommand->ErrorInfoLength; i < returnedLength; ++i) {
        printf("%02X ", (unsigned char)inputbuffer[i]);
        if ((i + 1) % 32 == 0) {
            printf("\n"); // 每16个字节换行
            //break;
        }
    }


    // 关闭设备句柄
    CloseHandle(deviceHandle);

    system("pause");
    return 0;
}

报错内容:

deviceHandle = 180
protocolCommand->ReturnStatus: 0

result: 0
returnedLength: 0

Failed to send protocol command. Error code:
317请按任意键继续. . .
我的初步解决思路是参数配置不对,需要继续修改参数
操作环境是:Windows
软件是visual studio 2022
我的Nvme盘片,支持的协议是M2.0

问题:
1、我想问一下,这个开发可行性怎么样,理论上可以实现不,实际上可以实现不,怎么实现?
2、开发是否需要再开发一款windows pcie驱动,从而配套开发,开发代码怎么写?
3、在visual studio直接调用windows API的话,理论上可以实现不,实际上可以实现不,怎么实现?
4、我的程序代码遇到的问题怎么解决,有没有更好的方式?

  • 写回答

35条回答 默认 最新

  • 阿里嘎多学长 2024-12-28 12:00
    关注
    获得0.15元问题酬金

    阿里嘎多学长整理AIGC生成,因移动端显示问题导致当前答案未能完全显示,请使用PC端查看更加详细的解答过程

    解答

    你想在 Windows 上位机中使用 NVMe API 与 NVMe 盘片通讯,这是一个非常有趣的项目!根据你的描述,你已经参考了微软提供的 NVMe 示例代码,但是你遇到了问题,无法确定这种操作是否可行。

    首先,NVMe API 是一个复杂的技术栈,需要你对 Windows API 和 NVMe 协议有深入的了解。NVMe API 提供了许多函数来控制 NVMe 盘片,例如发送命令、读取响应、管理队列等。

    在 Windows 中,NVMe API 是通过 NvMeApi.h 头文件提供的,你可以使用 Visual Studio 中的 C++ 项目来编写 NVMe 应用程序。

    为了确定这种操作是否可行,你可以尝试以下步骤:

    1. 检查 NVMe 盘片是否支持 NVMe API。可以使用 NvMeApi.h 头文件中的 NvMeGetCapabilities 函数来获取 NVMe 盘片的能力。
    2. 确认 NVMe 盘片是否已经初始化。可以使用 NvMeApi.h 头文件中的 NvMeInitialize 函数来初始化 NVMe 盘片。
    3. 使用 NvMeApi.h 头文件中的 NvMeSendCommand 函数来发送 NVMe 命令到 NVMe 盘片。
    4. 使用 NvMeApi.h 头文件中的 NvMeGetResults 函数来获取 NVMe 命令的响应结果。

    如果你遇到了问题,可以尝试查看 NVMe API 的文档和示例代码,或者查看 Windows 的 NVMe 驱动程序的日志来了解错误原因。

    以下是一个简单的示例代码,演示如何使用 NVMe API 发送 NVMe 命令:

    #include <NvMeApi.h>
    
    int main() {
        // 初始化 NVMe 盘片
        NvMeInitialize();
    
        // 发送 NVMe 命令
        NvMeSendCommand(NVME_CMD_READ, 0, 0, 0, 0);
    
        // 获取 NVMe 命令的响应结果
        NvMeGetResults();
    
        return 0;
    }
    

    请注意,这只是一个简单的示例代码,你需要根据你的实际需求和 NVMe 盘片的能力来修改代码。

    评论

报告相同问题?

问题事件

  • 系统已结题 1月5日
  • 创建了问题 12月28日