20 {
22 klog::Err(
"VirtioDriver: FDT reg property missing size for node '{}'",
25 }
27 if (!ctx) {
28 return std::unexpected(ctx.error());
29 }
30
31 etl::io_port_ro<uint32_t> magic_reg{reinterpret_cast<void*>(ctx->base)};
34 }
35
36
37 etl::io_port_ro<uint32_t> device_id_reg{reinterpret_cast<void*>(
38 ctx->base +
40 const auto device_id =
static_cast<DeviceId>(device_id_reg.read());
41
42 switch (device_id) {
46 "VirtioDriver: blk device pool full, device at {:#x} skipped",
47 ctx->base);
49 }
51
52
56 klog::Err(
"VirtioDriver: failed to allocate DMA buffer at {:#x}",
57 ctx->base);
59 }
60
61
62 auto [slot_size, slot_align] =
64 slot_buffers_[idx] = kstd::make_unique<IoBuffer>(slot_size, slot_align);
66 klog::Err(
"VirtioDriver: failed to allocate slot DMA buffer at {:#x}",
67 ctx->base);
70 }
71
72 uint64_t extra_features =
78
81
85 if (!result.has_value()) {
86 klog::Err(
"VirtioDriver: VirtioBlk Create failed at {:#x}", ctx->base);
89 return std::unexpected(
Error(result.error().code));
90 }
91
95
96
100 adapter_idx);
103 } else {
105 "VirtioDriver: blk adapter pool full, device at {:#x} skipped",
106 ctx->base);
107 }
108
111 "VirtioDriver: block device at {:#x}, capacity={} sectors, irq={}",
113 return {};
114 }
115
116 default:
118 }
119}
size_t blk_adapter_count_
DeviceId
VirtIO 设备类型枚举(来自 VirtIO 1.2 规范)
static constexpr size_t kMinDmaBufferSize
static constexpr uint32_t kDefaultQueueSize
static constexpr uint32_t kDefaultQueueCount
static constexpr size_t kMaxBlkDevices
std::array< etl::unique_ptr< IoBuffer >, kMaxBlkDevices > dma_buffers_
std::array< etl::unique_ptr< IoBuffer >, kMaxBlkDevices > slot_buffers_
std::array< std::optional< virtio::blk::VirtioBlkVfsAdapter >, kMaxBlkDevices > blk_adapters_
static auto Create(uint64_t mmio_base, const DmaRegion &vq_dma, const DmaRegion &slot_dma, VirtToPhysFunc virt_to_phys=IdentityVirtToPhys, uint16_t queue_count=1, uint32_t queue_size=128, uint64_t driver_features=0) -> Expected< VirtioBlk >
创建并初始化块设备
static constexpr auto GetRequiredSlotMemSize() -> std::pair< size_t, size_t >
计算 RequestSlot DMA 内存所需字节数
@ kNotSupported
不支持的操作(通用,非设备特定)
auto IdentityVirtToPhys(uintptr_t virt) -> uintptr_t
恒等映射:物理地址 == 虚拟地址(早期启动 / 无 MMU 时的默认实现)
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
auto Warn(etl::format_string< Args... > fmt, Args &&... args) -> void
以 WARN 级别记录日志
auto Prepare(const DeviceNode &node, size_t default_size) -> Expected< ProbeContext >
从节点提取 MMIO base/size 并通过 VirtualMemory 映射该区域。
@ kSegMax
设备配置空间中 seg_max 字段有效 (VIRTIO_BLK_F_SEG_MAX)
@ kSizeMax
设备配置空间中 size_max 字段有效 (VIRTIO_BLK_F_SIZE_MAX)
@ kBlkSize
设备配置空间中 blk_size 字段有效 (VIRTIO_BLK_F_BLK_SIZE)
@ kFlush
设备支持缓存刷新命令 (VIRTIO_BLK_F_FLUSH)
@ kGeometry
设备配置空间中 geometry 字段有效 (VIRTIO_BLK_F_GEOMETRY)
static constexpr uint32_t kMmioMagicValue
MMIO 魔数: little-endian "virt" = 0x74726976.
uint32_t irq
第一条中断线(需要多 IRQ 支持时扩展)
vfs::BlockDevice * block_device
char name[32]
可读的设备名称(来自 FDT 节点名)