@@ -38,7 +38,27 @@ void virtio_status_driver_ok(struct virtio_device *dev)
3838{
3939 _virtio_dev_check (dev );
4040
41- dev -> mmio_config -> status |= VIRTIO_STATUS_FEATURES_OK | VIRTIO_STATUS_DRIVER_OK ;
41+ if (dev -> version == 1 )
42+ {
43+ /* Legacy virtio */
44+ dev -> mmio_config -> status |= VIRTIO_STATUS_FEATURES_OK | VIRTIO_STATUS_DRIVER_OK ;
45+ }
46+ else
47+ {
48+ /* Modern virtio: set FEATURES_OK and verify it */
49+ dev -> mmio_config -> status |= VIRTIO_STATUS_FEATURES_OK ;
50+
51+ /* Verify that device accepted the features */
52+ if (!(dev -> mmio_config -> status & VIRTIO_STATUS_FEATURES_OK ))
53+ {
54+ /* Device doesn't support our feature subset */
55+ dev -> mmio_config -> status |= VIRTIO_STATUS_FAILED ;
56+ return ;
57+ }
58+
59+ /* Now set DRIVER_OK */
60+ dev -> mmio_config -> status |= VIRTIO_STATUS_DRIVER_OK ;
61+ }
4262}
4363
4464void virtio_interrupt_ack (struct virtio_device * dev )
@@ -59,7 +79,66 @@ rt_bool_t virtio_has_feature(struct virtio_device *dev, rt_uint32_t feature_bit)
5979{
6080 _virtio_dev_check (dev );
6181
62- return !!(dev -> mmio_config -> device_features & (1UL << feature_bit ));
82+ if (dev -> version == 1 )
83+ {
84+ /* Legacy: 32-bit feature bits only */
85+ return !!(dev -> mmio_config -> device_features & (1UL << feature_bit ));
86+ }
87+ else
88+ {
89+ /* Modern: Use 64-bit feature access */
90+ rt_uint64_t features = virtio_get_features (dev );
91+ return !!(features & (1ULL << feature_bit ));
92+ }
93+ }
94+
95+ rt_uint64_t virtio_get_features (struct virtio_device * dev )
96+ {
97+ rt_uint64_t features = 0 ;
98+
99+ _virtio_dev_check (dev );
100+
101+ if (dev -> version == 1 )
102+ {
103+ /* Legacy: only lower 32 bits */
104+ features = dev -> mmio_config -> device_features ;
105+ }
106+ else
107+ {
108+ /* Modern: read both 32-bit halves */
109+ dev -> mmio_config -> device_features_sel = 0 ;
110+ features = dev -> mmio_config -> device_features ;
111+
112+ dev -> mmio_config -> device_features_sel = 1 ;
113+ features |= ((rt_uint64_t )dev -> mmio_config -> device_features ) << 32 ;
114+ }
115+
116+ return features ;
117+ }
118+
119+ void virtio_set_features (struct virtio_device * dev , rt_uint64_t features )
120+ {
121+ _virtio_dev_check (dev );
122+
123+ if (dev -> version == 1 )
124+ {
125+ /* Legacy: only lower 32 bits */
126+ dev -> mmio_config -> driver_features = (rt_uint32_t )features ;
127+ }
128+ else
129+ {
130+ /* Modern: write both 32-bit halves */
131+ dev -> mmio_config -> driver_features_sel = 0 ;
132+ dev -> mmio_config -> driver_features = (rt_uint32_t )features ;
133+
134+ dev -> mmio_config -> driver_features_sel = 1 ;
135+ dev -> mmio_config -> driver_features = (rt_uint32_t )(features >> 32 );
136+ }
137+ }
138+
139+ rt_bool_t virtio_has_feature_64 (struct virtio_device * dev , rt_uint64_t features , rt_uint32_t feature_bit )
140+ {
141+ return !!(features & (1ULL << feature_bit ));
63142}
64143
65144rt_err_t virtio_queues_alloc (struct virtio_device * dev , rt_size_t queues_num )
@@ -93,6 +172,7 @@ rt_err_t virtio_queue_init(struct virtio_device *dev, rt_uint32_t queue_index, r
93172 void * pages ;
94173 rt_size_t pages_total_size ;
95174 struct virtq * queue ;
175+ rt_uint64_t desc_addr , avail_addr , used_addr ;
96176
97177 _virtio_dev_check (dev );
98178
@@ -123,18 +203,44 @@ rt_err_t virtio_queue_init(struct virtio_device *dev, rt_uint32_t queue_index, r
123203
124204 rt_memset (pages , 0 , pages_total_size );
125205
126- dev -> mmio_config -> guest_page_size = VIRTIO_PAGE_SIZE ;
206+ /* Set queue selector */
127207 dev -> mmio_config -> queue_sel = queue_index ;
128208 dev -> mmio_config -> queue_num = ring_size ;
129- dev -> mmio_config -> queue_align = VIRTIO_PAGE_SIZE ;
130- dev -> mmio_config -> queue_pfn = VIRTIO_VA2PA (pages ) >> VIRTIO_PAGE_SHIFT ;
131209
210+ /* Calculate queue area addresses */
132211 queue -> num = ring_size ;
133212 queue -> desc = (struct virtq_desc * )((rt_ubase_t )pages );
134213 queue -> avail = (struct virtq_avail * )(((rt_ubase_t )pages ) + VIRTQ_DESC_TOTAL_SIZE (ring_size ));
135214 queue -> used = (struct virtq_used * )VIRTIO_PAGE_ALIGN (
136215 (rt_ubase_t )& queue -> avail -> ring [ring_size ] + VIRTQ_AVAIL_RES_SIZE );
137216
217+ desc_addr = VIRTIO_VA2PA (queue -> desc );
218+ avail_addr = VIRTIO_VA2PA (queue -> avail );
219+ used_addr = VIRTIO_VA2PA (queue -> used );
220+
221+ if (dev -> version == 1 )
222+ {
223+ /* Legacy virtio: use queue_pfn */
224+ dev -> mmio_config -> guest_page_size = VIRTIO_PAGE_SIZE ;
225+ dev -> mmio_config -> queue_align = VIRTIO_PAGE_SIZE ;
226+ dev -> mmio_config -> queue_pfn = desc_addr >> VIRTIO_PAGE_SHIFT ;
227+ }
228+ else
229+ {
230+ /* Modern virtio: use separate descriptor/driver/device registers */
231+ dev -> mmio_config -> queue_desc_low = (rt_uint32_t )desc_addr ;
232+ dev -> mmio_config -> queue_desc_high = (rt_uint32_t )(desc_addr >> 32 );
233+
234+ dev -> mmio_config -> queue_driver_low = (rt_uint32_t )avail_addr ;
235+ dev -> mmio_config -> queue_driver_high = (rt_uint32_t )(avail_addr >> 32 );
236+
237+ dev -> mmio_config -> queue_device_low = (rt_uint32_t )used_addr ;
238+ dev -> mmio_config -> queue_device_high = (rt_uint32_t )(used_addr >> 32 );
239+
240+ /* Enable the queue */
241+ dev -> mmio_config -> queue_ready = 1 ;
242+ }
243+
138244 queue -> used_idx = 0 ;
139245
140246 /* All descriptors start out unused */
@@ -165,7 +271,17 @@ void virtio_queue_destroy(struct virtio_device *dev, rt_uint32_t queue_index)
165271 rt_free_align ((void * )queue -> desc );
166272
167273 dev -> mmio_config -> queue_sel = queue_index ;
168- dev -> mmio_config -> queue_pfn = RT_NULL ;
274+
275+ if (dev -> version == 1 )
276+ {
277+ /* Legacy virtio */
278+ dev -> mmio_config -> queue_pfn = 0 ;
279+ }
280+ else
281+ {
282+ /* Modern virtio */
283+ dev -> mmio_config -> queue_ready = 0 ;
284+ }
169285
170286 queue -> num = 0 ;
171287 queue -> desc = RT_NULL ;
0 commit comments