作者 江波龙 谭荣
Windows 10下的NVME存储驱动分为两种——Microsoft Inbox、OFA Reference Driver。前者为Closed source driver (Microsoft),也就是通常所说的原生态驱动;后者为Open source driver (Reviewing Companies: HGST, Intel, Samsung),方便各大厂商为了提升自己的ssd产品性能,针对性地开发自己的驱动。两者存在较大差异,最显著的是Microsoft Inbox driver只能支持到NVMe 1.0e(no support for multi-initiator, NS mgmt, controller list, etc.),而OFA Reference Driver只能支持到NVMe 1.2(multi-initiator, NS mgmt, controller list)。本文就Microsoft Inbox下vendor command制定谈下自己的理解。
很久以前有个问题一直困扰过我很久——那就是在OFA Reference Driver下制定的一套vendor command,在Microsoft Inbox下一直是行不通的,由于后者是闭源驱动,而处在底层SSD firmware的我一直不明白严谨的上层host究竟要闹哪样,为何老是要无情地拒绝我的command request?直到后来我才发现在Microsoft 官网针对这块专门有一个Working with NVMe drives的说明,其中有两段话说的很具体:
大概意思就是在StoreNVMe.sys里vendor-specific commands是通过Pass-through mechanism来pipe through的,另外每个制定的vendor commands必须在Command Effects Log描述其属性,用以告诉host这个命令将对target device会有什么影响!明白了这点后似乎豁然开朗,但是也没那么简单,千万记得host是很严谨的,细则还是很多。接下来演示一个vendor command的制定流程(欢迎来到王者荣耀!)。
第一步:identify里告诉host设备支持Supported and Effects log page命令(告诉队友——我拿buffer还是我打辅助!),这样一来每次上电host就会发送该命令用来读取device支持哪些私有命令码。
第二步:命令码的制定,请注意不要太随意了(猥琐发育别浪!),必须严格按照标准制定命令码,以admin命令为例:
首先你只能选择C0-FFh范围,其次要搞明白transfer是read or write?是否带数据?假设是read那么01:00这两个bit必须是10b。现假设制定了一个0xCE的读私有命令码。
第三步:填充Supported and Effects log page里0xCE命令的属性(修改铭文!)
这里因为你的opcode是0xCE,所以要在ACS206的字段里去填充它对应的结构体:
Csupp:表示device是支持该字段对应的Opcode的;
Lbcc:表示该私有命令会改变LBA内容;
Ncc:表示该命令会对Ns的capability产生影响;
Nic:表示该命令会对NS的数量产生影响;
CCC:表示该命令会更改ssd controler中Cap register的属性;
Cse:表示在多命令处理时该命令提交与执行的限定条件;
第四步:按照该结构将你定义好的命令码填充进去,再通过host调用相关的API下发给device。(victory!)