9400-16i HBA UEFI驱动编程指南

作者: 陈立中 | 日期: 2025年6月7日

位置: 成都瑞贺数理科技有限公司, 中国四川省成都市(http://www.chengduredhare.cn/)

目录

本指南解释了提供的UEFI驱动(DummyDriver.c)和MPI头文件(mpi2.h)中的代码流程和关键函数。该驱动使用MPIv2(消息传递接口)与9400-16i主机总线适配器(HBA)交互,通过UEFI HII(人机界面基础设施)显示HBA信息。

1. 代码流程概述

驱动入口点: DummyDriverEntry

  1. 初始化HII
    • 添加HII包(字符串、表单)以在BIOS设置中显示数据。
    • 安装EF_I_HII_CONFIG_ACCESS_PROTOCOL用于表单回调。
  2. 定位串口I/O协议
    • 配置串口用于调试输出(UseSerialPort)。
  3. 定位HBA
    • 扫描PCI总线查找9400-16i HBA(厂商ID 0x1000, 设备ID 0x00AC)。
  4. 检查HBA状态
    • 读取门铃寄存器确定HBA状态(复位/就绪/运行/故障)。
  5. 发送IOC Facts请求
    • 从HBA获取固件版本、端口数量和机箱信息。
  6. 更新HII字符串
    • 用HBA详细信息(固件版本、PCI位置等)填充BIOS设置菜单。

2. DummyDriver.c中的关键函数

Locate9400HBA

功能: 在PCI总线上查找9400-16i HBA。

步骤:

  1. 获取所有支持gEfiPciIoProtoco1Guid的句柄。
  2. 对每个句柄:
    • 读取PCI配置空间检查厂商/设备ID(0x1000/0x00AC)。
    • 将HBA详情保存到g_HBA9400(PCI位置、BARs、句柄)。

输出: 通过串口打印HBA的BDF(总线/设备/功能)。

Identify9400HBAState

功能: 从门铃寄存器(BAR1偏移0x00)读取HBA状态。

状态:

  • MPI_IOC_STATE_RESET (复位)
  • MPI_IOC_STATE_READY (就绪)
  • MPI_IOC_STATE_OPERATIONAL (运行)
  • MPI_IOC_STATE_FAULT (故障)

输出: 通过串口打印状态(如"9400HBA当前处于运行状态")。

HBA9400_issue_ioc_facts

功能: 请求HBA信息(固件版本、端口、机箱)。

步骤:

  1. 发送MPI2_FUNCTION_IOC_FACTS握手消息。
  2. 接收回复到g_HBA9400.data。
  3. 解析Mpi2IOCFactsReply_t获取:
    • 固件版本(FwVersion)
    • 端口数量(NumberOfPorts)
    • 最大机箱数(MaxEnclosures)

输出: 用检索到的数据更新g_HBA9400。

reset_9400

功能: 如果HBA卡在复位/故障状态则重置。

步骤:

  1. 通过HostInterruptMask禁用中断。
  2. 向HostDiagnostic寄存器写入MPI2_DIAG_RESET_ADAPTER。
  3. 等待50ms,然后清除复位。

验证: 通过Identify9400HBAState检查复位后状态。

send_mpt_handshake_message

功能: 发送MPI握手消息(如IOC Facts)。

步骤:

  1. 检查HBA状态(如果处于故障状态则失败)。
  2. 用消息功能/长度触发门铃(MPI2_DOORBELL_OFFSET)。
  3. 等待门铃中断(wait_for_9400HBA_doorbell)。
  4. 向门铃寄存器写入消息DWORDs。

关键: 使用wait_for_9400HBA_handshake_response确认IOC准备就绪。

recv_9400_handshake_data

功能: 接收握手回复(如IOC Facts响应)。

步骤:

  1. 为每个回复DWORD等待门铃中断。
  2. 从门铃寄存器读取回复数据。
  3. 验证回复头中的IOCStatus。

3. 关键MPI结构与寄存器(mpi2.h)

HBA寄存器(映射到BAR1)

寄存器偏移功能
Doorbell0x00状态位(31:28),向IOC发送消息。
HostInterruptStatus0x30检查中断(如MPI2_HIS_DOORBELL_INTERRUPT)。
HostInterruptMask0x34屏蔽中断(如重置期间禁用)。
HostDiagnostic0x08触发重置(MPI2_DIAG_RESET_ADAPTER)。

IOC Facts消息

typedef struct _MPI2_IOC_FACTS_REPLY {
    U16    IOCStatus;    // 状态(0x0000 = 成功)
    U32    IOCLoginfo;    // 错误详情
    U8    NumberOfPorts;    // 活动端口
    U16    MaxEnclosures;    // 最大支持机箱数
    MPI2_VERSION_UNION FwVersion;    // 固件版本
} MPI2_IOC_FACTS_REPLY;

关键字段:

  • IOCStatus: 成功/失败(如MPI2_IOCSTATUS_SUCCESS)。
  • FwVersion: 固件版本(主/次/单元/开发)。
  • NumberOfPorts: 活动SAS/SATA端口。

HBA状态(门铃位31:28)

#define MPI2_IOC_STATE_RESET    (0x00000000)
#define MPI2_IOC_STATE_READY    (0x10000000)
#define MPI2_IOC_STATE_OPERATIONAL    (0x20000000)
#define MPI2_IOC_STATE_FAULT    (0x40000000)

4. 串口调试

UseSerialPort

  • 使用EFI_SERTAL_IO_PROTOCOL初始化串口(115200波特, 8N1)。
  • 通过SerialPrintf打印调试消息(如"9400 HBA固件: X.Y.Z")。

示例输出

PRINT(L"找到9400-HBA, BDF=%02x-%02x-%02x", bus, dev, func);
PRINT(L"9400HBA当前处于运行状态");

5. HII集成

更新BIOS设置菜单

  1. 创建HII句柄:
    HiHandle = HiAddPackages(&g_leobummyDriverGuid, ImageHandle, ...);
  2. 设置动态字符串:
    UnicodeSPrint(HiMessage, ... "固件: %d.%d", major, minor);
    HiisetString(HiHandle, STRING_TOKEN(STR_9400_FW_VER), HiiMessage, NULL);
  3. 在BIOS设置中显示:
    • HBA固件版本。
    • PCI位置(总线/设备/功能)。
    • 端口/机箱数量。

6. 初级工程师重要注意事项

1. PCI枚举:
  • 始终使用EFI_PCI_IO_PROTOCOL访问PCI配置空间。
  • 检查厂商/设备ID以定位HBA。
2. 门铃协议:
  • 发送消息后轮询HostInterruptStatus检查MPI2_HIS_DOORBELL_INTERRUPT。
  • 超时处理很关键(使用gBS->Stall进行微秒级延迟)。
3. 错误处理:
  • 验证回复中的IOCStatus(非零表示失败)。
  • 操作前检查MPI_IOC_STATE_FAULT状态。
4. HII:
  • 令牌(如STRING_TOKEN(STR_9400_FW_VER))必须与.VFR文件匹配。

流程图

本指南为理解驱动与9400 HBA的交互提供了基础。研究MPI规范以了解高级功能。

7. 程序运行截图

在EFI Shell下加载驱动

在高级菜单下显示简单驱动

在简单驱动菜单中显示9400基本信息

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值