硬盘背板开发指南
更新时间: 2025/12/04
在Gitcode上查看源码

本文档主要介绍如何在openUBMC上适配一个硬盘背板。

硬盘背板介绍

服务器硬盘背板是一种硬件设备,常见于服务器机箱内,用于安装和连接硬盘驱动器。它的设计和功能有以下几个方面:
硬盘安装:服务器硬盘背板提供了安装硬盘驱动器的接口和插槽。通过固定硬盘背板上的螺丝,硬盘驱动器可以牢固地安装在服务器机箱内,并与背板上的接口相连接。
数据传输:服务器硬盘背板上的接口通常采用SATA(Serial ATA)、SAS(Serial Attached SCSI)、NVMe(Non-Volatile Memory Express)等标准。这些接口用于传输数据和信号,连接硬盘驱动器与服务器主板或RAID控制器。通过硬盘背板,硬盘驱动器可以与其他硬件设备进行数据传输和通信。
电源供应:服务器硬盘背板通常还提供了硬盘驱动器的电源接口,用于供应电源给硬盘驱动器。这些接口可以确保硬盘驱动器正常运行所需的电力供应,并与服务器主板上的电源联系起来。
散热和固定:服务器硬盘背板还具备散热和固定硬盘驱动器的功能。它通常针对硬盘驱动器的散热需求进行设计,通过散热结构和通风孔,提供有效的散热和温度控制。同时,硬盘背板上的固定装置可以确保硬盘驱动器在运行过程中保持稳定和安全。
总之,服务器硬盘背板是用来安装和连接硬盘驱动器的硬件设备。它提供了接口、传输数据、供电、散热和固定硬盘驱动器的功能。通过硬盘背板,服务器硬盘驱动器可以正常运行并与其他硬件设备进行通信和数据交互。

硬盘背板适配流程

与其他部件一样,每一个硬盘背板都有一个CSR文件,CSR文件用来告诉openUBMC如何识别硬盘背板、管理硬盘背板信息、监控硬盘背板状态、硬盘信息管理等。

新适配一张硬盘背板CSR需要做什么

  • 硬盘背板的UID、名称、类型、厂商、槽位号、硬盘起始槽位、丝印等固定信息。
  • 硬盘背板支持的硬盘类型及数量。
  • 需要监控硬盘背板的哪些状态,如硬盘背板温度、硬盘温度、硬盘状态等。
  • 硬盘背板传感器都需要哪些,如何获取这些传感器读值。
  • 需要上报哪些告警或事件及告警条件,如温度、硬盘拔插事件、硬盘定位失败、阵列告警、硬盘预故障、硬盘状态外来、硬盘写穿、硬盘重构开始、硬盘重构结束、硬盘故障、硬盘替换记录等。
  • 硬盘的状态和告警信息获取来源。
  • 硬盘背板是否需要单独的调速策略。

硬盘背板识别

  • 配置正确的SR文件名称,根据“BOM+ID+AUXID”组成对应网卡的文件名,在硬盘背板连接的上级组件(如载板)SR中,配置硬盘背板的连接器,然后根据硬件反馈的在位信号加载硬盘背板SR文件。
  • SR加载的IdentifyMode模式建议优先考虑3,如果硬盘背板不满足天池的识别协议,可配置1或2,并配置一个固定的ID
json
{
    "Connector_SEU_1": {
      "Bom": "14100665",
      "Slot": 1,
      "Position": 2,
      "Presence": "<=/Scanner_SEU_1.Value",  // 在位信号扫描信息,0表示不在位,1表示在位,如固定在位,可不检测,直接配置为1
      "Buses": [
        "I2c_2",
        "I2c_5",
        "JtagOverLocalBus_1"
      ],
      "SystemId": "${SystemId}",
      "ManagerId": "${ManagerId}",
      "ChassisId": "${ChassisId}",
      "SilkText": "SEU",
      "IdentifyMode": 3,  // 下级组件识别方式,3对应下级组件识别方式为天池标准类型组件,2对应下级组件识别方式为BoardId不可读(上报)类型组件,1对应下级组件识别方式为BoardId可读类型组件
      "Container": "Component_ComExpander",
      "Type": "DiskBackplane"
    },
    "Scanner_SEU_1": {
      "Chip": "#/Smc_ExpBoardSMC",
      "Offset": 134234368,  // SMC命令字
      "Size": 2,  // 数据字节数
      "Mask": 1,  // 数据掩码
      "Type": 0,
      "Period": 2000,  // 扫描周期,单位ms
      "Value": 0
    }
}

管理拓扑对象

  • 配置硬盘背板的所有总线信息
  • 配置所有通道信息
  • 配置所有chip信息
json
{
    "ManagementTopology": {
        "Anchor": {
        "Buses": ["I2c_2",
            "I2c_5",
            "JtagOverLocalBus_1"]
        },
        "I2c_5": {
            "Chips": ["Smc_EnclSMC",
            "Eeprom_SEU"],
            "Connectors": ["Connector_SEU_Inner_1",
            "Connector_SEU_Inner_2"]
        },
        "I2c_2": {
            "Chips": ["Smc_ExpBoardSMC"]
        },
        "JtagOverLocalBus_1": {
            "Chips": ["Cpld_1"]
        }
    }
}

component对象

  • 配置硬盘背板和硬盘的FruId
  • 配置硬盘背板和硬盘类型
  • 配置硬盘背板和硬盘位置信息
  • 配置硬盘背板和硬盘序列号来源
  • 配置硬盘背板和硬盘位置信息
json
{
    "Component_HddBackplane": {
        "FruId": "<=/Fru_SEU.FruId",  // 无Fru则默认255,有Fru则引用Fru对象的FruId
        "Instance": "${Slot}",
        "Type": 5,  // 部件类型,对应代码中的COMPONENT_TYPE*
        "Location": "<=/HddBackplane_1.Position",  // 位置信息
        "Name": "<=/HddBackplane_1.DeviceName",  // 名称
        "Presence": 1,  // 在位信息
        "Health": 0,  // 健康状态
        "PowerState": 1,  // 电源状态
        "GroupId": 1,  // 组ID
        "UniqueId": "00000001030302023934", // 唯一ID
        "ReplaceFlag": 0,  // 是否被替换标记
        "PreviousSN": "",  // 上一个序列号
        "SerialNumber": "<=/HddBackplane_1.SerialNumber",  // 序列号
        "NodeId": "<=/HddBackplane_1.Position;<=/HddBackplane_1.DeviceName |> string.format('%s%s',$1,$2)",  // 节点ID
        "BoardId": "<=/HddBackplane_1.BoardID"  // 板卡ID
    },
    "Component_Drive0": {  // 每个硬盘都需要配置一个对应的Component对象
        "FruId": 255,
        "Instance": 255,
        "Type": 2,
        "Name": "Disk0",
        "Presence": 1,
        "Health": 0,
        "PowerState": 1,
        "NodeId": "Disk0",
        "ReplaceFlag": 0,
        "PreviousSN": "",
        "SerialNumber": "<=/Drive_1.SerialNumber"
        },
    "Component_Cable": {  // 硬盘背板通常包含线缆检测,需要配置对应的Component对象
        "FruId": 255,
        "Instance": 255,
        "Type": 40,
        "Name": "cable",
        "Presence": 1,
        "Health": 0,
        "PowerState": 1,
        "GroupId": 1
    }
}

Entity对象

如果需要配置传感器,则每个硬件组件都需要配置一个Entity对象,包含硬盘背板和硬盘。

json
{
    "Entity_HddCard": {
    "Id": 11,
    "Name": "HddCard${Slot}",
    "PowerState": "<=/Scanner_PowerGood.Value",
    "Presence": 1,
    "Instance": 112
    },
    "Entity_Disk0": {
    "Id": 4,
    "Instance": 96,
    "Name": "Disk0",
    "PowerState": 1,
    "Presence": 1
    }
}

硬盘对象

定义硬盘的基本信息和属性

  • 名称
  • ID
  • 位置信息
  • 定位灯扫描信息
  • 故障扫描信息
  • 类型
json
{
    "Drive_1": {
        "Id": 0,  // 硬盘ID,是硬盘对象的主键,不能重复,计算方式:HddBackplaneStartSlot + RelativeSlot
        "Name": "Disk0",  // 硬盘名称
        "PhysicalLocation": "HDD Plane",  // 位置信息
        "NodeId": "HDDPlaneDisk0",  // 资源的唯一ID
        "Presence": "<=/Scanner_Drive0PresentAccessor.Status;<=/Scanner_Drive0PresentAccessor.Value |> expr($1 != 0 ? 255 : $2)",  // 硬盘在位状态,0:不在位,1:在位,255:无效值
        "LocateLed": "<=/Scanner_Drive0LocateAccessor.Value",  // 硬盘定位灯状态,0:关闭',1:闪烁,2:常亮
        "FaultLed": "<=/Scanner_Drive0FalutAccessor.Value",  // 硬盘故障灯状态,0:关闭,1:常亮,2:闪烁
        "ActivationLed": "<=/Scanner_Drive0ActivationAccessor.Value",  // 硬盘活动状态灯,0:关闭,1:开启
        "SetLocateLed": "#/Accessor_Drive0LocateAccessor.Value",  // 设置硬盘定位灯,0:关定位灯,1:开定位灯(闪烁)
        "SetFaultLed": "#/Accessor_Drive0FaultAccessor.Value",  // 设置硬盘故障灯,0:关故障灯,1:点故障灯(常亮)
        "TemperatureCelsius": 255,  // 硬盘温度(摄氏度),255是无效值
        "Missing": 0,  // 硬盘的missing状态
        "Health": "<=/Component_Drive0.Health",  // 硬盘健康状态,0:OK,1:Minor,2:Major,3:Critical
        "RebuildState": 0,  // 指定硬盘数据重建状态
        "FirmwareStatus": 255,  // 硬盘固件状态,来自于BMA或者Raid,255为无效值
        "PredictiveFailure": 0,  // 硬盘设备预故障检测,来自Raid,0:正常,1:故障
        "InAFailedArray": 0,  // 硬盘是否归属于一个故障阵列,来自Raid,0:否,1:是
        "FirmwareStatusError": false,  // 关联硬盘FaultLed状态,true:有故障,false:正常
        "PredictedMediaLifeLeftPercent": 255,  // 硬盘静态磨损率
        "SerialNumber": "",  // 硬盘SN编码,来源BMA、Raid、VPD
        "Type": "SATA/SAS",  // 硬盘丝印类型,PcieAddressInfo对象使用
        "IODeteriorationHealthCode": 0,  // 硬盘I/O性能健康码
        "HddBackplaneStartSlot": "<=/HddBackplane_1.StartSlot",  // 硬盘背板起始槽位号
        "RelativeSlot": 0  // 槽位相对硬盘背板起始槽位的偏移量,一般配置和ID相等
    }
}

配置告警和事件

传感器定制与开发请参考《传感器定制与开发》进行配置,以下仅举例硬盘背板和硬盘相关传感器。

  • 设置温度监控阈值,用于告警或调速

阈值传感器对象 (ThresholdSensor)

  • 6个阈值
  • 告警取消滞后值
  • 读值数据源
  • 合理的M,RBExp值,使计算出的传感器读值在一个字节的有效区间
json
{
    "ThresholdSensor_HddBpTemp": {
        "OwnerId": 32,
        "OwnerLun": 0,
        "EntityId": "<=/Entity_HddCard.Id",
        "EntityInstance": "<=/Entity_HddCard.Instance",
        "Initialization": 127,
        "Capabilities": 232,  // 传感器生效条件
        "SensorType": 1,  // 传感器类型,参考ipmi规范42章
        "ReadingType": 1,
        "SensorName": "Disk BP${Slot} Temp",
        "Unit": 128,
        "BaseUnit": 1,
        "ModifierUnit": 0,
        "Analog": 1,
        "NominalReading": 25,
        "NormalMaximum": 0,
        "NormalMinimum": 0,
        "MaximumReading": 127,
        "MinimumReading": 128,
        "Reading": "<=/Scanner_HddBPTemp.TemperatureCelsius",
        "ReadingStatus": "<=/Scanner_HddBPTemp.Status",
        "AssertMask": 128,  // 告警能力掩码,参考ipmi规范Assertion Event Mask
        "DeassertMask": 28800,  // 参考ipmi规范Deassertion Event Mask
        "ReadingMask": 2056,
        "Linearization": 0,
        "M": 100,
        "RBExp": 224,
        "UpperNoncritical": 105,
        "PositiveHysteresis": 2,
        "NegativeHysteresis": 2
    }
}

离散传感器对象 (DiscreteSensor)

json
{
    "DiscreteSensor_Disk0": {
        "EntityId": "<=/Entity_Disk0.Id",
        "EntityInstance": "<=/Entity_Disk0.Instance",
        "Initialization": 99,
        "Capabilities": 192,
        "SensorType": 13,
        "ReadingType": 111,
        "SensorName": "DISK0",
        "AssertMask": 199,
        "DeassertMask": 199,
        "DiscreteMask": 199,
        "DiscreteType": 0,
        "Unit": 192,
        "BaseUnit": 0,
        "ModifierUnit": 0,
        "RecordSharing": 1,
        "Reading": 0
    },
    "DiscreteEvent_Disk0Presence": {  // DiscreteEvent事件根据自己的需要添加,可参考其他硬盘背板的sr文件添加
        "Property": "<=/Drive_1.Presence",
        "ListenType": 1,
        "EventData1": 0,
        "EventData2": 255,
        "EventData3": 255,
        "EventDir": "<=/Drive_1.Presence",
        "Conversion": 0,
        "InvalidReadingIgnore": 1,
        "InvalidReading": 255,
        "SensorObject": "#/DiscreteSensor_Disk0"
    },
    "Scanner_Drive0PresentAccessor": {
        "Chip": "#/Smc_EnclSMC",
        "Offset": 335545601,
        "Size": 2,
        "Mask": 1,
        "Type": 0,
        "Period": 2000,
        "Debounce": "None",
        "Value": 255
    },
    "Event_Disk0Missing": {  // Event事件根据自己的需要添加,可参考其他硬盘背板的sr文件添加
        "EventKeyId": "Disk.DiskMissing",
        "Reading": "<=/Drive_1.Missing",
        "Condition": 2,
        "OperatorId": 5,
        "Enabled": true,
        "DescArg2": "Disk0",
        "Component": "#/Component_Drive0",
        "ComponentHealth": "#/Component_Drive0.Health"
    },
    "Event_SEU3_UBNotPresent": {  // 线缆检测事件根据自己的需要添加,可参考其他硬盘背板的sr文件添加
        "EventKeyId": "Cable.UBNotPresent",  // 事件标识,相当于告警的唯一标识ID
        "InvalidReadingIgnore": 1,  // 是否忽略无效值,1:开启 0:关闭,开启后读值如果等于InvalidReading则忽略
        "InvalidReading": 255,  // 需要忽略的无效值
        "Reading": "<=/Scanner_SEU_Inner_1.Value;<=/Scanner_Inner_1_CablePresent.Value;<=/Scanner_Inner_2_CablePresent.Value |> expr($1 == 1 ? (($2 == 0 && $3 == 0) ? 1 : 0) : 0)",  // Reading与Condition按照OperatorId的规则进行比较,结果为True则触发告警,精度最多小数点后四位
        "@Default": {  // 默认值
            "Reading": 0
        },
        "ComponentId": 40,
        "Condition": 1,
        "OperatorId": 5,  // 判断符号,1:小于;2:小于等于;3:大于;4:大于等于;5:等于;6:不等于;7:上升沿0->1产生,1->0恢复;8:下降沿1->0产生,0->1恢复
        "Enabled": true,  // 告警是否使能
        "DescArg1": "#/Accessor_Id_1.Value |> expr($1 == 51 ? 1030302023930 : 1030302023928) |> string.format('%020d(SEUSlot3)',$1)",  // 事件的描述/建议参数,用于格式化参数,仅支持字符串格式,最多10个
        "AdditionalInfo": "1", // 事件的附加信息,常用于告警上报给上层网管时区分告警对象
        "Component": "#/Component_Cable",  // 关联的Component对象
        "ComponentHealth": "#/Component_Cable.Health"
    }
}

散热控制对象

  • 目标温度
  • 最大允许温度
json
{
    "CoolingConfig_Basic": {  // CoolingConfig类通常不配置在板卡的配置文件中
        "SmartCoolingState": "Enabled",  // 智能调速是否启用,取值范围"Enabled","Disabled"
        "SmartCoolingMode": "EnergySaving",  // 智能调速模式,取值范围"EnergySaving","HighPerformance","LowNoise","Custom","LiquidCooling"
        "LevelPercentRange": [20, 100],  // 智能调速等级范围,样例中为调速范围为20-100
        "InitLevelInStartup": 100,  // 启动时默认调速等级,取值范围LevelPercentRange
        "DiskRowTemperatureAvailable": false,  // 硬盘温度是否可获取
        "SysHDDsMaxTemperature": 80.0,  // HDD硬盘最大温度阈值
        "SysSSDsMaxTemperature": 80.0,  // SSD硬盘最大温度阈值
        "SensorLocationSupported": false  // 是否支持温度海洋界面
    }
    "CoolingPolicy_EnergySaving": {
        "PolicyIdx": 6,  // 线性调速策略Id,PolicyIdx必须全局唯一
        "ExpCondVal": "EnergySaving",  // 预期生效条件,CoolingPolicy生效前提是实际条件与期望条件一致,取值范围"EnergySaving","HighPerformance","LowNoise","Custom","LiquidCooling"
        "ActualCondVal": "<=/CoolingConfig_1.SmartCoolingMode",  // 实际生效条件,取值范围"EnergySaving","HighPerformance","LowNoise","Custom","LiquidCooling"
        "TemperatureRangeLow": [-127, 20, 30, 40, 50],  // 线性调速策略温度区间低门限
        "TemperatureRangeHigh": [20, 30, 40, 50, 127],  // 线性调速策略温度区间高门限
        "SpeedRangeLow": [20, 32, 70, 100],  // 线性调速策略转速区间低门限
        "SpeedRangeHigh": [20, 32, 70, 100],  // 线性调速策略转速区间高门限
        "FanType": ["02314BLG 8038+"]  // 风扇类型列表,环境风扇类型为列表之一时,风扇条件生效
    }
    "CoolingRequirement_1_7": {
        "RequirementId": 7,  // 目标调速策略Id,Id必须全局唯一,当前Id支持有效16位,前8位baseid,后8位槽位号
        "TemperatureType": 11,  // 目标调速温度点类型,1:Cpu 2:Outlet 3:Disk 4:Memory 5:PCH 6:VRD 7:VDDQ 8:NPUHbm 9:NPUAiCore 10:NPUBoard 11:Inlet 12:SoCBoardOutlet 13:SoCBoardInlet
        "MonitoringStatus": "<=/Scanner_Lm75_Inlet.Status",  // 温度点传感器状态,0:正常 1:异常
        "MonitoringValue": "<=/Scanner_Lm75_Inlet.Value;<=/Scanner_Lm75_Inlet.Value |> expr((($1 + 5) > ($2 - 10)) ? ($1 + 5) : ($2 - 10))",  // 参与调速的温度值
        "FailedValue": 80,  // 温度状态异常后的异常调速转速,不配代表不触发异常调速;如果配置了值,温度点读取失败的时候,异常调速会固定下发这个转速值
        "TargetTemperatureCelsius": 50,  // 当前调速目标值
        "MaxAllowedTemperatureCelsius": 60,
        "TargetTemperatureRangeCelsius": [  // 自定义温度允许范围,用于自定义目标值时的合法性判断
            40,
            60
        ],
        "SmartCoolingTargetTemperature": [  // EnergySaving/HighPerformance/LowNoise 三种模式下的目标温度值,可不配置
            50,
            47,
            53
        ],
        "CustomSupported": true,  // 是否支持自定义目标温度值,true:支持,false:不支持
        "CustomTargetTemperatureCelsius": 50,  // 用户自定义温度值,255为无效值
        "SensorName": "#/ThresholdSensor_InletTemp.SensorName"  // 传感器名称
    },
    "CoolingArea_1_25": {
        "AreaId": 25,
        "RequirementIdx": 25,
        "PolicyIdxGroup": [],
        "FanIdxGroup": [
            1,
            2,
            3,
            4
        ]
    }
}

FRU对象

json
{
    "Eeprom_NetCard": {
        "OffsetWidth": 2,
        "AddrWidth": 1,
        "Address": 172,
        "WriteTmout": 100,
        "ReadTmout": 100,
        "RwBlockSize": 32,
        "WriteInterval": 20,
        "HealthStatus": 0
    },
    "Fru_SEU": {
        "PcbId": "#/Accessor_PcbID.Value",
        "FruId": 1,
        "FruName": "DiskBP${Slot}",
        "PowerState": 1,
        "Health": 0,
        "EepStatus": 1,
        "Type": 5,
        "FruDataId": "#/FruData_SEU"
    },
    "FruData_SEU": {
      "FruId": 1,
      "FruDev": "#/Eeprom_SEU",
      "EepromWp": "#/Accessor_WP.Value",
      "StorageType": "TianChi"  // 常用的电子标签格式有TianChi、EepromV2、File、MCU、Power
    }
}

cpld升级管理对象

json
{
    "LogicFirmware_SEU_1": {
        "UId": "00000001030302023934",  // 组件cpld的唯一标识,vendor(00000001)+单板类型(03)+单板编码(0302023934)
        "Name": "SEU_CPLD",  // 组件cpld的名称
        "Manufacturer": "Huawei",  // 固件厂商
        "Version": "#/Accessor_LogicVerId.Value",  // 固件版本号,用于区分不同的cpld版本
        "Location": 3,  // 固件所在器件的位号,BMC展示会在前面加U
        "UpgradeChip": "#/Cpld_1",  // 升级CPLD使用JTAG链路升级对应的芯片
        "ChipInfo": "#/Cpld_1",  // 获取CPLD厂商和bypass使能
        "Routes": "#/Accessor_JtagSwitch.Value",  // Jtag路由值,通常由载板cpld提供组件cpld升级的路由功能和信息
        "DefaultRoute": 0,  // 默认路由值,通常由载板cpld提供组件cpld升级的路由功能和信息,且该值默认指向载板
        "FirmwareRoute": 2,  // 与Routes关联的SMC对应,升级时会设置对应值切到对应链路,0代表不需要切换
        "SoftwareId": "CPLD-BC83HBBH"  // CPLD编码信息,配置格式为'固件类型-单板名称'
    },
    "Accessor_JtagSwitch": {
        "Chip": "#/Smc_ExpBoardSMC",
        "Offset": 469776896,
        "Size": 1,
        "Mask": 255,
        "Type": 0,
        "Value": 0
    }
}

PcieAddrInfo对象

json
    "PcieAddrInfo_SAS_1": {  // 硬盘背板里面通常需要配置硬盘对应的PcieAddrInfo对象,用于匹配iBMA上报的硬盘信息
      "Location": "HddBackplane${Slot}",  // PCIe槽位所在的位置
      "ComponentType": 71,  // 部件类型,对应代码中的COMPONENT_TYPE
      "ContainerSlot": "${Slot}",
      "ContainerUID": "00000001030302023934",  // 容器UID
      "ContainerUnitType": "SEU SAS",  // 容器单板类型
      "GroupPosition": "PcieAddrInfo_1_${GroupPosition}",
      "ControllerType": 2, // PCIe控制器类型,0:PCIeCore,1:NIC,2:SAS,3:SATA,4:ZIP,5:SEC
      "Segment": 0,  // 多PCI Bridge场景的编号,每一个Segment对应一个PCI Bus空间
      "GroupID": 0,  // 逻辑组ID
      "SlotID": 1,  // PCIe设备的槽位号
      "SocketID": 0,  // CPU ID,0:CPU1,1:CPU 2
      "Bus": 0,  // root port Bus号
      "Device": 125,  // root port Device号
      "Function": 0  // root port Function号
    }

硬盘管理

硬盘加载流程

非直通盘:Drive为抽象的硬盘对象,配置在硬盘背板的CSR中,每一个硬盘槽位对应配置一个Drive对象。
特殊协议直通盘:Drive对象负责上树硬盘的共同属性,属性从协议中获取。
普通直通盘:Drive对象负责上树硬盘的共同属性,属性只有默认值,可通过iBMA获取。

非直通盘一般是受RAID卡管理的硬盘,其Drive对象通常直接配置在硬盘背板的SR中,在storage中主要体现为不对外暴露的PD类,PD对应建链流程如下:

特殊协议直通盘sr加载不同于非直通盘,需要加载单独的sr文件,加载由通过在位和类型信息共同决定:

json
{
    "Connector_ComVPDConnect_1": {
        "Bom": "14140224",
        "Slot": 0,
        "Position": 1,
        "Presence": "<=/Scanner_Drive0PresentAccessor.Value;<=/Scanner_Drive1PCIeType.Value|> expr(($1 == 1) && ($2 == 1))",
        "Id": "VPD",
        "AuxId": "0",
        "Buses": ["I2cMux_SMC_1"],
        "SystemId": "${SystemId}",
        "ManagerId": "${ManagerId}",
        "ChassisId": "${ChassisId}",
        "SilkText": "J11",
        "IdentifyMode": 2,
        "Type": "NVMe"
    }
}

NVMe对象通过slot与Drive对象建链,不需要非直通盘的建链流程,且NVMe对象的属性从协议中获取后更新到Drive对象中,由Drive对象上树。
特殊协议直通盘需要配置对应的vpd信息,并根据代码识别到的协议类型加载不同PROTOCOL的sr文件和调速文件。

json
{
    "VirtualVPDConnect": {
        "Slot": "${Slot}",
        "RefVPDChip": "#/Chip_Virtual_SSD",
        "RefConnector": "#/Connector_ComVPD",
        "RefPolicyConnector": "#/Connector_Policy"
        },
    "Chip_Virtual_SSD": {
        "Address": 166,
        "AddrWidth": 1,
        "OffsetWidth": 1,
        "WriteTmout": 100,
        "ReadTmout": 100,
        "HealthStatus": 0
        },
    "Connector_ComVPD": {
        "Bom": "14140224",
        "Slot": "${Slot}",
        "Position": 1,
        "Presence": 0,
        "Id": "PROTOCOL",
        "AuxId": "255",
        "Buses": ["I2cMux_SMC"],
        "SystemId": "${SystemId}",
        "ManagerId": "${ManagerId}",
        "ChassisId": "${ChassisId}",
        "SilkText": "",
        "IdentifyMode": 2,
        "Type": "NVMe"
        },
    "Connector_Policy": {
        "Bom": "14140224",
        "Slot": "${Slot}",
        "Position": 2,
        "Presence": 0,
        "Id": "POLICY",
        "AuxId": "255",
        "Buses": ["I2cMux_SMC"],
        "SystemId": "${SystemId}",
        "ManagerId": "${ManagerId}",
        "ChassisId": "${ChassisId}",
        "SilkText": "",
        "IdentifyMode": 2,
        "Type": "NVMe"
    }
}

常见问题

1、SAS/SATA盘信息无法获取
说明:SAS/SATA盘信息获取主要来源于RAID卡或iBMA,本身无法直接获取,无RAID卡的情况下需要适配iBMA:
->整机适配时,在硬盘背板的SR文件中配置SAS/SATA盘的PcieAddrInfo对象,如PcieAddrInfo_SAS对象中的Bus、Device、Function、PortID、SlotID、SocketID、ComponentType、ControllerType、Segment。
->iBMA启动后上报对应的硬盘信息给BMC。
->BMC根据BDF等信息匹配上报的信息并更新到Drive对象中。


2、NVMe盘信息无法获取/获取的不全
说明:NVMe盘的信息获取主要来源于协议从硬盘固件获取:
->全新的未适配过的NVMe盘可能需要适配NVME-mi/SSD-Format协议。
->硬盘固件的协议版本BMC不兼容。
->硬盘固件中写入的协议数据不符合预期,常见国产较小的厂商,对协议理解不够透彻。
->硬盘固件中写入的数据不全。
->部分属性标准协议中只有NVME-mi才有,如磁盘容量,硬盘固件是SSD-Format协议。
->部分厂商增加了OEM属性,需要BMC开发代码适配。


3、NVME盘无法识别协议
说明:NVME盘是根据VPD的数据进行协议解析,VPD无数据、数据不符合协议规范或VPD无法访问则无法识别协议,排查以上问题一般可以解决。


4、非直通硬盘无法关联对应的RAID卡
说明:非直通硬盘识别需要进行点灯操作,操作失败则无法关联。
->检查硬盘背板下对应的Drive信息配置是否符合预期。
->检查硬盘对应的在位信息和定位信息是否符合预期。
->检查RAID卡和硬盘背板的高速线连接是否符合预期。
->检查RAID卡是否正常工作。
->检查RAID卡是否支持带外管理。
->检查CPLD点灯能力是否正常,可通过带内点灯进行交叉验证。