RK3588 kernel-6.1 drivers/usb/storage 代码功能与实现原理
1. 定位:两套路径(BOT vs UAS)
模块(Makefile) |
典型名称 | 作用 |
|---|---|---|
usb-storage(CONFIG_USB_STORAGE) |
usb-storage.ko |
USB Mass Storage Bulk-Only Transport(BOT) 及旧 CB/CBI 等:Bulk 管道搬运 SCSI CDB |
uas(CONFIG_USB_UAS) |
uas.ko |
USB Attached SCSI:命令/状态/数据 多管道 + 可选 USB3 Streams,更接近原生 SCSI 异步模型 |
二者均依赖 SCSI 子系统;常见块设备还需 CONFIG_BLK_DEV_SD(sd 磁盘)。
2. USB Mass Storage 类规范与分层
usb.h 头部注释说明实现依据 USB Mass Storage Class,命令形态贴近 SCSI-II / ATAPI;类规范对 NAK/STALL/ACK 的语义与通用 USB 略有差异,部分设备用 中断端点 上报命令状态(CBI)。
内核内部分层(struct us_data):
| 层级 | 文件 | 职责 |
|---|---|---|
| 协议(Protocol) | protocol.c |
把 scsi_cmnd 打成设备可接受的 CDB 长度/变体(透明 SCSI、UFI、Pad12 等),再调用传输 |
| 传输(Transport) | transport.c |
CB/CBI/Bulk-Only:打包 URB、Bulk 收发、REQUEST_SENSE 自动 sense、复位与错误恢复 |
| SCSI 胶水 | scsiglue.c |
注册 struct scsi_host_template、queuecommand、slave_configure(队列 max_hw_sectors、DMA bounce)、eh_abort / reset |
| 设备生命周期与线程 | usb.c |
usb_driver probe、根据接口 bInterfaceSubClass / Protocol 绑定 transport + proto_handler、控制内核线程 |
大量 unusual_*.h / usual-tables.c:VID/PID + quirks + 可选 init,覆盖不按规范暴露 SubClass/Protocol 的固件。
3. 核心数据结构:us_data(usb.h)
每个已绑定的 U 盘对应一块 us_data(挂在 Scsi_Host->hostdata):
- USB:
pusb_dev、pusb_intf、缓存的 bulk/control/intr pipe - 传输/协议:
transport、transport_reset、proto_handler、subclass/protocol/max_lun - 并发模型:单命令槽
srb+completion cmnd_ready+usb_stor_control_thread - 缓冲:
iobuf(小 DMA 缓冲)、current_urb、usb_sg_request - quirks:
fflags/dflags、use_last_sector_hacks等
4. 命令路径:queuecommand → 内核线程 → invoke_transport
4.1 SCSI 中层下发
scsiglue.c 中 queuecommand_lck(持 scsi_lock):
- 保证
us->srb为空(同一时间 一条 SCSI 命令); us->srb = srb;complete(&us->cmnd_ready)唤醒usb-storage线程。
4.2 控制线程 usb_stor_control_thread(usb.c)
循环 wait_for_completion(&cmnd_ready),取 us->srb,校验 LUN/target/方向,处理 FIX_INQUIRY 等特殊路径,否则调用:
1 | else { |
即 协议层入口。
4.3 协议层(protocol.c)
usb_stor_transparent_scsi_command:直接usb_stor_invoke_transportusb_stor_pad12_command:CDB padding 到 12 字节(RBC/8070 等)usb_stor_ufi_command:UFI 命令长度与 INQUIRY/MODE_SENSE/REQUEST_SENSE 长度裁剪
4.4 传输与会聚:usb_stor_invoke_transport(transport.c)
usb_stor_invoke_transport:
result = us->transport(srb, us)—— Bulk-Only 则 CBW → Data → CSW(或 CB/CBI 控制传输路径);- 根据返回值决定是否 自动 REQUEST_SENSE、是否 端口复位;
- 处理 last sector 等与劣质固件相关的补丁逻辑。
传输返回值语义(transport.h):USB_STOR_TRANSPORT_GOOD/FAILED/NO_SENSE/ERROR,区分 命令失败 与 USB 链路错误。
5. get_transport / get_protocol(usb.c)
接口 bInterfaceProtocol → 传输:
USB_PR_BULK:Bulk-Only(绝大多数 U 盘)USB_PR_CB/USB_PR_CBI:Control-Bulk[-Interrupt]
bInterfaceSubClass → 协议处理器:
USB_SC_SCSI:透明 SCSIUSB_SC_UFI:软驱类 UFIUSB_SC_RBC、USB_SC_8020、USB_SC_QIC、USB_SC_8070:各类缩减/光学命令集
6. SCSI Host 与块层(scsiglue.c)
slave_alloc:INQUIRY 长度 36、队列 DMA 对齐slave_configure:限制 单次传输扇区数(兼容弱设备;SuperSpeed 提到 2048 sectors)、PIO HCD 时 bounce limitqueuecommand:DEF_SCSI_QCMD 包装锁- 错误处理:abort、bus reset、device reset 与
us->dflags、URB unlink 协作
7. uas.c(独立于 BOT 路径)
- 不为每个命令占用单一
usb-storage线程;使用usb_anchor、workqueue、tag ↔ scsi_cmnd 映射(MAX_CMNDS)。 - 命令 URB、状态 URB、数据 IN/OUT URB 按 UAS 规范并行;可选 Bulk Streams。
uas-detect.h:与usb-storage协同 探测:若设备支持 UAS 且无黑名单,优先绑定uas驱动(避免同一设备双驱动冲突)。
原理:BOT 串行 CSW、单队列;UAS 多命令流水,更适合 SSD / USB3。
8. 子驱动(ums-*)
alauda.c、datafab.c、isd200.c 等:面向 非标准桥片,实现私有 transport/init,编译为独立 ums-*.ko,由 usb_storage_usb_ids / unusual 表挂载。
9. 其它文件
initializers.c:部分 unusual 设备的 probe 阶段初始化debug.c:CONFIG_USB_STORAGE_DEBUGsierra_ms.c/option_ms.c:调制解调器 / 复合设备 存储相关 quirks
10. 数据流简图(BOT)
1 | blk_mq / sd |
11. 延伸阅读(本仓库)
| 文档 |
|---|
| drivers-usb-core详细分析.md |
| USB总线枚举匹配与数据传输分析.md |
基于 rk3588/kernel-6.1/drivers/usb/storage 源码归纳。
正在加载留言…