尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Linux 内核 RapidIO 子系统完全指南:驱动接口、枚举发现与设备模型
Linux 内核 RapidIO 子系统完全指南驱动接口、枚举发现与设备模型【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linuxRapidIO 是一种面向嵌入式市场的高速交换式互连switched fabric interconnect技术同时支持内存映射 I/O 与基于消息的事务并拥有与 PCI 总线类似的标准化设备发现机制。本文以 Linux 内核 Documentation/admin-guide/rapidio.rst 为主干结合内核源码中的include/linux/rio_drv.h、include/linux/rio.h以及drivers/rapidio/目录下的核心实现系统讲解 RapidIO 子系统的驱动开发接口、内部数据结构、枚举与发现流程以及设备模型集成方式帮助读者在 Linux 内核中为新的 RapidIO 架构提供支持、编写新的 RapidIO 驱动或深入理解该子系统的实现原理。RapidIO 子系统概览RapidIO 是面向嵌入式领域设计的高速交换式互连标准其核心特性包括内存映射 I/O 支持允许本地处理器像访问本地内存一样访问交换网络中的远程设备。基于消息的事务提供 mailbox邮箱与 doorbell门铃两种轻量级消息机制适用于控制面通信。标准化发现机制与 PCI 总线标准类似通过配置空间扫描即可简单检测网络中存在的设备无需人工配置。Linux 内核中的 RapidIO 子系统正是围绕这些特性构建的它向上为设备驱动提供统一 API向下通过主端口master port抽象屏蔽不同硬件平台的差异。该文档面向三类开发者希望在新架构上支持 RapidIO 的开发者、编写新 RapidIO 设备驱动的开发者以及希望理解子系统内部机制的开发者。从源码布局看整个子系统核心位于drivers/rapidio/目录主要包含文件职责drivers/rapidio/rio.c子系统核心mbox/doorbell/port-write 管理、内存映射、路由表操作、设备生命周期drivers/rapidio/rio-access.c配置空间读写封装本地与远端drivers/rapidio/rio-driver.cLinux 设备模型LDM集成总线注册、驱动注册、probe/removedrivers/rapidio/rio-scan.c网络枚举enumeration与发现discovery算法drivers/rapidio/rio-sysfs.csysfs 属性节点与用户态接口drivers/rapidio/rio_cm.c通道化消息channelized messaging驱动见 Documentation/driver-api/rapidio/rio_cm.rst已知缺陷与限制原文档明确列出了当前子系统的两个已知限制理解这些限制对驱动开发者尤为重要1. 不支持 RapidIO 内存区域的访问/管理RapidIO 内存区域的访问与管理功能尚未实现。这意味着子系统虽然提供了内存映射 API如rio_map_inb_region()、rio_map_outb_region()但通过通用框架对 RapidIO 地址空间的完整访问与资源管理能力仍有限驱动开发者需要依赖具体的硬件平台实现。2. 不支持多主机枚举系统仅支持单一主机对交换网络执行枚举。这与 drivers/rapidio/rio-scan.c 中的实现一致主机在枚举前通过RIO_HOST_DID_LOCK_CSR寄存器尝试获取主机设备 ID 锁rio_enum_host()中的rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, port-host_deviceid)同一网络中只允许一个主机完成枚举。此外drivers/rapidio/rio.c提供的rio_lock_device()/rio_unlock_device()也仅用于单主机场景下对目标设备的独占锁定通过向RIO_HOST_DID_LOCK_CSR写入本机 host_deviceid 并轮询验证。RapidIO 驱动接口子系统为驱动开发者提供了一整套调用接口用于获取设备信息、请求/映射内存区域资源以及管理邮箱与门铃。这些接口主要声明在 include/linux/rio_drv.h并在 drivers/rapidio/rio-driver.c 与 drivers/rapidio/rio.c 中实现。配置空间访问接口配置空间访问分为**本地local与远端网络**两类每类均支持 8/16/32 位读写本地访问__rio_local_read_config_8/16/32()、__rio_local_write_config_8/16/32()以及对应的内联封装rio_local_read_config_*()、rio_local_write_config_*()。远端访问rio_mport_read_config_8/16/32()、rio_mport_write_config_8/16/32()带destid与hopcount参数以及面向具体设备的封装rio_read_config_*()、rio_write_config_*()。这些函数的实现位于 drivers/rapidio/rio-access.c通过宏RIO_LOP_READ/WRITE本地与RIO_OP_READ/WRITE远端批量生成。注意其中包含对齐检查逻辑#define RIO_8_BAD 0 #define RIO_16_BAD (offset 1) #define RIO_32_BAD (offset 3)即 16 位访问要求 offset 对齐到 2 字节、32 位访问要求对齐到 4 字节未对齐时返回RIO_BAD_SIZE0x81见 include/linux/rio.h 中的错误码定义。所有访问最终都经由struct rio_mport的opsstruct rio_ops回调lcread/lcwrite/cread/cwrite下发到底层平台实现驱动开发者无需关心具体硬件细节。邮箱Mailbox管理邮箱用于承载基于消息的事务最多支持RIO_MAX_MBOX4个邮箱单个消息最大长度为RIO_MAX_MSG_SIZE0x1000 字节。核心接口如下接口作用rio_request_outb_mbox(mport, dev_id, mbox, entries, moutb)申请出向邮箱绑定发送回调rio_release_outb_mbox(mport, mbox)释放出向邮箱rio_add_outb_message(mport, rdev, mbox, buffer, len)将消息加入出向邮箱队列发送rio_request_inb_mbox(mport, dev_id, mbox, entries, minb)申请入向邮箱绑定接收回调rio_release_inb_mbox(mport, mbox)释放入向邮箱rio_add_inb_buffer(mport, mbox, buffer)为入向邮箱添加接收缓冲区rio_get_inb_message(mport, mbox)从入向队列取出一条消息从 drivers/rapidio/rio.c 的实现看rio_request_inb_mbox()首先通过request_resource()在mport-riores[RIO_INB_MBOX_RESOURCE]上声明资源占用防止邮箱被重复申请然后挂接回调并调用mport-ops-open_inb_mbox()打开硬件邮箱任何一步失败都会回滚释放资源。出向邮箱的申请逻辑与之对称资源挂载在RIO_OUTB_MBOX_RESOURCE。资源编号约定定义于 include/linux/rio.h值得特别注意对于RIO 设备region 0 为出向门铃region 1-15 为内存区域对于RIO 主端口mportregion 0 为入向门铃region 1 为入向邮箱region 2 为出向邮箱。门铃Doorbell管理门铃是一种携带 16 位 info 字段的轻量级消息适合快速通知场景。接口包括接口作用rio_request_inb_dbell(mport, dev_id, start, end, dinb)申请入向门铃消息区间info 值范围绑定回调rio_release_inb_dbell(mport, start, end)释放入向门铃区间rio_request_outb_dbell(rdev, start, end)从设备侧申请出向门铃区间返回struct resource *rio_release_outb_dbell(rdev, res)释放出向门铃资源rio_mport_send_doorbell(mport, destid, data)/rio_send_doorbell(rdev, data)发送门铃消息data为 16 位 inforio_send_doorbell()是面向设备的内联封装直接转发到rio_mport_send_doorbell(rdev-net-hport, rdev-destid, data)include/linux/rio_drv.h底层调用mport-ops-dsend()。辅助宏rio_init_dbell_res()可将struct resource初始化为门铃资源RIO_RESOURCE_DOORBELLrio_init_mbox_res()则初始化为邮箱资源RIO_RESOURCE_MAILBOX。内存区域与内存映射接口尽管原文档指出内存区域的访问/管理暂不支持子系统仍提供了完整的映射 API 供平台与驱动使用int rio_map_inb_region(struct rio_mport *mport, dma_addr_t local, u64 rbase, u32 size, u32 rflags); void rio_unmap_inb_region(struct rio_mport *mport, dma_addr_t lstart); int rio_map_outb_region(struct rio_mport *mport, u16 destid, u64 rbase, u32 size, u32 rflags, dma_addr_t *local); void rio_unmap_outb_region(struct rio_mport *mport, u16 destid, u64 rstart);入向映射将 RapidIO 地址空间窗口映射到本地物理内存rbase为分配给该窗口的 RIO 基地址出向映射则为指定destid建立从 RIO 地址到本地地址的转换。实现上所有映射操作在rio_mmap_lock自旋锁保护下调用mport-ops-map_inb/map_outb等回调drivers/rapidio/rio.c。Port-Write 错误管理接口Port-Write端口写是 RapidIO 的错误管理通知机制设备通过 64 字节RIO_PW_MSG_SIZE的 port-write 消息上报错误。相关接口接口作用rio_request_inb_pwrite(rdev, pwcback)为具体设备注册 port-write 回调rio_release_inb_pwrite(rdev)注销设备级回调rio_add_mport_pw_handler(mport, dev_id, pwcback)注册 mport 级 port-write 处理器rio_del_mport_pw_handler(mport, dev_id, pwcback)移除 mport 级处理器rio_inb_pwrite_handler(mport, pw_msg)入向 port-write 消息的统一分发入口rio_pw_enable(mport, enable)使能/禁止 mport 的 port-write 处理消息内容由联合体union rio_pw_msg描述include/linux/rio.hem子结构包含 Component Tag、Port Error Detect、Port ID、LTL Error Detect 等字段也可通过raw[]按原始 32 位数组访问。rio_inb_pwrite_handler()的处理流程是先根据comptag通过rio_get_comptag()查找对应设备调用设备级回调若无设备或回调未处理完再遍历 mport 级处理器列表对于交换机设备还会进一步调用rswitch-ops-em_handle()读取/清除RIO_DEV_PORT_N_ERR_STS_CSR等错误寄存器并执行设备插入/拔出服务恢复或锁定对应端口。LDM 设备模型接口RapidIO 子系统完整集成了 Linux 设备模型Linux Device Model为驱动提供标准的注册/注销与引用计数接口int rio_register_driver(struct rio_driver *rdrv); void rio_unregister_driver(struct rio_driver *rdrv); struct rio_dev *rio_dev_get(struct rio_dev *rdev); void rio_dev_put(struct rio_dev *rdev);驱动编写者通过RIO_DEVICE(did, vid)宏构造匹配表项assembly vendor/device 字段自动置为RIO_ANY_ID并在struct rio_driver中提供probe、remove、shutdown、suspend/resume等回调。此外还有rio_name()返回设备唯一标识字符串、rio_get_drvdata()/rio_set_drvdata()驱动私有数据存取等辅助函数。子系统内部机制核心数据结构子系统的主要数据结构定义在 include/linux/rio.hstruct rio_dev描述一个 RapidIO 设备包含设备/厂商 IDdid/vid、组装件 ID、扩展特性指针efptr、处理单元特性pef、源/目的操作能力src_ops/dst_ops、组件标签comp_tag、目的 IDdestid与跳数hopcount、DMA 掩码以及内嵌的struct rio_switch rswitch[]仅交换机使用。struct rio_mport描述一个主端口即访问网络的入口。关键字段包括host_deviceid主机设备 ID、sys_size传输系统大小0 表示小系统 256 个设备1 表示大系统 65536 个设备、ops低层架构相关回调struct rio_ops、riores[]端口拥有的资源、inb_msg[]/outb_msg[]消息事件描述符、nscan枚举/发现操作。struct rio_net描述一个 RapidIO 网络维护设备列表、交换机列表与关联 mport 列表hport指向访问该网络的默认端口。struct rio_switch/struct rio_switch_ops交换机信息路由表副本route_table、端口状态位图port_ok、每端口下一设备指针数组nextdev[]与交换机专属操作路由增删查、清表、域设置、错误管理em_init/em_handle。struct rio_ops底层硬件回调集合包括lcread/lcwrite本地配置读写、cread/cwrite网络配置读写、dsend门铃发送、pwenableport-write 开关、open/close_inb/outb_mbox、add_outb_message、add_inb_buffer、get_inb_message、map_inb/map_outb、unmap_inb/unmap_outb、query_mport。struct rio_driverRIO 驱动描述含id_table、probe、remove等标准回调通过内嵌struct device_driver接入 LDM。struct rio_scan/struct rio_scan_node注册枚举/发现方法的结构enumerate与discover两个回调分别执行枚举与发现。同时 include/linux/rio.h 定义了若干关键常量RIO_MAX_MPORTS8、RIO_MAX_MPORT_RESOURCES/RIO_MAX_DEV_RESOURCES16、RIO_GLOBAL_TABLE0xff表示访问交换机全局路由表、RIO_INVALID_ROUTE0xff表示路由表项无效、RIO_MAX_MBOX4。还定义了enum rio_link_speed从 1.25G 到 6.25G Baud与enum rio_link_width1x 到 16x等链路属性枚举以及struct rio_mport_attr通过rio_query_mport()查询端口能力如 DMA 支持标志RIO_MPORT_DMA、RIO_MPORT_DMA_SG、RIO_MPORT_IBSG。枚举与发现Enumeration and Discovery枚举与发现算法实现在 drivers/rapidio/rio-scan.c是整个子系统最重要的机制之一其行为与 RapidIO 规范 Annex 1 描述的基本机制一致对应 Kconfig 中的RAPIDIO_ENUM_BASIC选项。枚举enumeration由rio_enum_mport()驱动。主机首先通过rio_enum_host()在RIO_HOST_DID_LOCK_CSR写入本机host_deviceid以锁定主机身份随后从端口 0 开始逐层遍历交换机与端点设备rio_enum_peer()为每个设备分配 destid、写入组件标签component tag、填充交换机路由表最终通过rio_enum_complete()检查RIO_PORT_GEN_CTL_CSR中的RIO_PORT_GEN_DISCOVERED位确认枚举完成。发现discovery由rio_disc_mport()驱动适用于非枚举主机。发现节点等待枚举主机完成网络配置等待时长受CONFIG_RAPIDIO_DISC_TIMEOUT默认 30 秒约束若设置了RIO_SCAN_ENUM_NO_WAIT标志则不等待直接返回-EAGAIN。枚举完成后发现节点读取网络拓扑与路由信息构建本地设备视图。标准路由表操作rio_std_route_add_entry、rio_std_route_get_entry、rio_std_route_clr_table通过RIO_STD_RTE_CONF_DESTID_SEL_CSR/RIO_STD_RTE_CONF_PORT_SEL_CSR标准寄存器读写路由表项并在大系统sys_size非零下读取RIO_SWITCH_RT_LIMIT获取最大 destid 范围。此外rio_mport_get_feature()/rio_mport_get_physefb()用于遍历扩展特性块Extended Features Block判断设备是否支持指定能力并获取寄存器映射类型。驱动功能实现drivers/rapidio/rio.c除了前文介绍的接口实现外还提供设备生命周期管理rio_add_device()、rio_del_device()、网络管理rio_alloc_net()、rio_add_net()、rio_free_net()、路由表管理rio_route_add_entry()等、设备锁定rio_lock_device()/rio_unlock_device()、设备可达性检查rio_mport_chk_dev_access()最多重试RIO_MAX_CHK_RETRY次、每次延时 1ms以及扩展特性查询等核心功能。值得注意的模块参数rio.c定义了hdid数组参数用于为本地 RapidIO 控制器分配目的 IDstatic int hdid[RIO_MAX_MPORTS]; module_param_array(hdid, int, ids_num, 0); MODULE_PARM_DESC(hdid, Destination ID assignment to local RapidIO controllers);加载模块时可通过hdid参数为每个 mport 指定 host_deviceid例如modprobe rio hdid0,1。设备模型支持与 sysfsdrivers/rapidio/rio-driver.c 完成了设备模型集成定义了名为rapidio的总线类型rio_bus_type提供 match/probe/remove/shutdown/uevent 回调与名为rapidio_port的设备类rio_mport_class并在postcore_initcall(rio_bus_init)中注册。总线匹配逻辑rio_match_bus()调用rio_match_device()依次比对vid/did/asm_vid/asm_did四项支持RIO_ANY_ID通配。rio_uevent()生成形如MODALIASrapidio:vXXXXdXXXXavXXXXadXXXX的模块别名支持 udev 自动加载驱动。sysfs 属性实现在 drivers/rapidio/rio-sysfs.c可归纳为三类类别属性说明设备属性did、vid、device_rev、asm_did、asm_vid、asm_rev设备/组装件 ID 与版本设备属性destid、hopcount、modalias、lprev网络地址与拓扑上游交换机专属routes路由表、lnext各端口下游设备、hopcount仅对RIO_PEF_SWITCH设备可见二进制属性config直接读写设备配置空间需CAP_SYS_ADMIN时扩展到完整维护空间RIO_MAINT_SPACE_SZ总线属性scan向该文件写入 mport 号触发重新扫描写入-1RIO_MPORT_ANY触发全部 mport 扫描mport 属性port_destid、sys_size主端口的主机设备 ID 与系统大小PPC32 支持文档专门列出了 PPC32 平台支持章节对应实现位于 arch/powerpc/sysdev/fsl_rio.c。该文件为 Freescale 处理器的 RapidIO 控制器提供了struct rio_ops低层回调本地/网络配置空间访问、门铃、邮箱、内存映射等是理解新架构如何接入 RapidIO 子系统的典型参考即实现struct rio_ops后调用rio_mport_initialize()与rio_register_mport()声明于 include/linux/rio.h将 mport 注册进子系统。内核配置选项RapidIO 子系统的编译配置集中在 drivers/rapidio/Kconfig主要选项如下配置项类型说明RAPIDIOtristate总开关依赖HAVE_RAPIDIO或PCIRAPIDIO_DISC_TIMEOUTint发现节点等待枚举完成的超时秒数默认 30RAPIDIO_ENABLE_RX_TX_PORTSbool使能所有端口的输入接收/输出发送方向规范建议输入/输出端口默认关闭仅允许维护事务RAPIDIO_DMA_ENGINEbool通过 DMA Engine 框架执行 NREAD/NWRITE(NWRITE_R/SWRITE) 数据传输RAPIDIO_DEBUGbool子系统调试信息输出RAPIDIO_ENUM_BASICtristate基本枚举/发现机制对应规范 Annex 1RAPIDIO_CHMANtristate通道化消息驱动提供类 socket 接口供多个用户态程序共享单个邮箱RAPIDIO_MPORT_CDEVtristate通用/devmport 字符设备驱动供用户态执行 RapidIO 专用操作其中RAPIDIO_DEBUG打开后rio.c、rio-scan.c中的pr_debug()输出如RIO: enumerate master port %d, %s、路由跟踪、错误状态寄存器等会进入系统日志是排查枚举失败与链路问题的有力工具。交换机驱动子菜单见 drivers/rapidio/switches/Kconfig各具体交换机驱动如 IDT 系列位于 drivers/rapidio/switches。编写 RapidIO 驱动的快速指引综合上述接口编写一个新 RapidIO 设备驱动的最小骨架如下使用RIO_DEVICE(did, vid)构造id_table匹配表定义struct rio_driver并实现probe()/remove()在probe()中通过rio_read_config_*()读取设备能力通过rio_request_inb_dbell()/rio_request_inb_mbox()申请消息资源并绑定回调通过rio_set_drvdata()保存私有数据在remove()中对称地释放资源、注销回调调用rio_register_driver()注册驱动模块卸载时调用rio_unregister_driver()若需要接收错误通知通过rio_request_inb_pwrite()注册 port-write 回调。而在新架构上提供 RapidIO 支持则需要实现struct rio_ops的全部必需回调 → 调用rio_mport_initialize()初始化 mport → 调用rio_register_mport()注册 → 使能RAPIDIO与RAPIDIO_ENUM_BASIC后由内核完成枚举发现。结语Linux 内核的 RapidIO 子系统以 mport 抽象统一了硬件差异以标准化的枚举发现机制实现了即插即用并通过完整的 LDM 集成让驱动开发与普通总线驱动别无二致。本文以官方文档为骨架、以内核源码为佐证梳理了从驱动接口到内部机制的完整脉络。开发者如需进一步深入可直接研读 include/linux/rio.h、include/linux/rio_drv.h 中的结构体与函数注释这些注释正是文档 kernel-doc 指令的生成源以及 drivers/rapidio/rio.c 中各接口的完整实现。致谢RapidIO 子系统由以下开发者直接或间接贡献Matt Porter、Randy Vinson、Dan Malek本文档的撰写者为 Matt Porter。其工作成果在 drivers/rapidio/ 目录的源码版权声明中均有体现MontaVista Software, Inc. 与 Integrated Device Technology, Inc.。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

MISRA C从入门到落地:汽车嵌入式C语言的编码规范与工程实践

MISRA C从入门到落地:汽车嵌入式C语言的编码规范与工程实践

1. MISRA C到底在管什么:一次代码审查让我重新认识它 先说个我自己的经历。几年前我在一家做汽车电子控制器(ECU)的供应商那边参与一个车身控制模块项目,C代码量大概二十万行,用的是意法半导体的STM32系列MCU。项目开发…

📅 2026/9/11 21:31:26
三大办公套件对比:微软Office、WPS与巴别鸟

三大办公套件对比:微软Office、WPS与巴别鸟

1. 三大办公套件市场定位解析微软Office作为行业标杆已有三十余年历史,其专业版订阅费用达到每年398元(个人版)或按设备数收费的企业授权模式。WPS Office通过"基础功能免费增值服务收费"的策略,个人版完全免费&#xf…

📅 2026/9/11 21:31:26
嵌入式OTA防砖设计:A/B分区与Ping-Pong回滚实战

嵌入式OTA防砖设计:A/B分区与Ping-Pong回滚实战

1. 为什么“防砖”不是一句口号,而是嵌入式OTA升级的生死线我第一次把一块ESP32烧成砖,是在凌晨两点。当时正在调试一个远程固件更新功能,推送了一个带内存越界访问的版本——设备重启后卡在Bootloader里,LED灯都不闪,…

📅 2026/9/11 21:31:26
MORE NEWS

更多资讯

📰

Carbon 语言包声明语法统一提案解读:`package`/`library` 声明中 `impl` 修饰符前置与 `api` 关键字移除

Carbon 语言包声明语法统一提案解读:package/library 声明中 impl 修饰符前置与 api 关键字移除 【免费下载链接】carbon-lang Carbon Languages main repository: documents, design, implementation, and related tools. (NOTE: Carbon Language is experimental;…

📰

H5仿翻书效果实战:turn.js生产级兼容方案

简介:本资源是一套开箱即用的H5仿翻书效果实现方案,面向前端开发者及交互设计学习者,解决电子杂志、在线图书、产品展示等场景中沉浸式翻页体验的技术落地问题。压缩包共17个文件,含8张页面PNG素材(用于模拟书页内容&a…

📰

WordPress块主题架构与开发实践解析

1. WordPress块主题架构解析在WordPress 5.9版本引入的FSE(全站编辑)架构中,块主题(Block Theme)彻底改变了传统主题的开发模式。以Twenty Twenty-Five为代表的官方块主题,其目录结构和加载机制体现了WordP…

📰

comprehensive-rust 课程深度解析:Lifetime Elision 生命周期省略规则实战指南

comprehensive-rust 课程深度解析:Lifetime Elision 生命周期省略规则实战指南 【免费下载链接】comprehensive-rust This is the Rust course used by the Android team at Google. It provides you the material to quickly teach Rust. 项目地址: https://gitc…

📰

基于Playwright的短视频矩阵自动发布系统实践

简介:短视频矩阵内容分发系统设计资源包,面向正在做课程设计、期末大作业或毕业设计的计算机相关专业学生,也适合有一定编程基础、希望研究浏览器自动化与多平台内容分发的技术爱好者。资源瞄准视频多平台分发的典型痛点,围绕Play…

📰

OpenClaw服务参数校验错误分析与解决方案

1. 问题现象与初步定位 最近在调试OpenClaw服务时遇到了一个典型的参数校验错误。具体报错信息如下&#xff1a; 400 <400> InternalError.Algo.InvalidParameter: Range of input leng这个错误表面看起来是参数长度问题&#xff0c;但实际排查过程中发现情况比预想的复…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬