@@ -59,10 +59,10 @@ unsafe impl ByteValued for Descriptor {}
59
59
/// https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-430008
60
60
/// 2.6.8 The Virtqueue Used Ring
61
61
#[ repr( C ) ]
62
- #[ derive( Default , Clone , Copy ) ]
63
- struct UsedElement {
64
- id : u32 ,
65
- len : u32 ,
62
+ #[ derive( Default , Debug , Clone , Copy ) ]
63
+ pub struct UsedElement {
64
+ pub id : u32 ,
65
+ pub len : u32 ,
66
66
}
67
67
68
68
// SAFETY: `UsedElement` is a POD and contains no padding.
@@ -387,7 +387,7 @@ impl Queue {
387
387
/// # Important
388
388
/// This is an internal method that ASSUMES THAT THERE ARE AVAILABLE DESCRIPTORS. Otherwise it
389
389
/// will retrieve a descriptor that contains garbage data (obsolete/empty).
390
- fn do_pop_unchecked < ' b , M : GuestMemory > (
390
+ pub fn do_pop_unchecked < ' b , M : GuestMemory > (
391
391
& mut self ,
392
392
mem : & ' b M ,
393
393
) -> Option < DescriptorChain < ' b , M > > {
@@ -466,7 +466,33 @@ impl Queue {
466
466
Ok ( ( ) )
467
467
}
468
468
469
- fn write_used_ring < M : GuestMemory > (
469
+ /// Read used element from a used ring at specified index.
470
+ #[ inline( always) ]
471
+ pub fn read_used_ring < M : GuestMemory > (
472
+ & self ,
473
+ mem : & M ,
474
+ index : u16 ,
475
+ ) -> Result < UsedElement , QueueError > {
476
+ // Used ring has layout:
477
+ // struct UsedRing {
478
+ // flags: u16,
479
+ // idx: u16,
480
+ // ring: [UsedElement; <queue size>],
481
+ // avail_event: u16,
482
+ // }
483
+ // We calculate offset into `ring` field.
484
+ let used_ring_offset = std:: mem:: size_of :: < u16 > ( )
485
+ + std:: mem:: size_of :: < u16 > ( )
486
+ + std:: mem:: size_of :: < UsedElement > ( ) * usize:: from ( index) ;
487
+ let used_element_address = self . used_ring . unchecked_add ( usize_to_u64 ( used_ring_offset) ) ;
488
+
489
+ mem. read_obj ( used_element_address)
490
+ . map_err ( QueueError :: UsedRing )
491
+ }
492
+
493
+ /// Read used element to the used ring at specified index.
494
+ #[ inline( always) ]
495
+ pub fn write_used_ring < M : GuestMemory > (
470
496
& self ,
471
497
mem : & M ,
472
498
index : u16 ,
@@ -525,7 +551,7 @@ impl Queue {
525
551
526
552
/// Helper method that writes to the `avail_event` field of the used ring.
527
553
#[ inline( always) ]
528
- fn set_used_ring_avail_event < M : GuestMemory > ( & mut self , avail_event : u16 , mem : & M ) {
554
+ pub fn set_used_ring_avail_event < M : GuestMemory > ( & mut self , avail_event : u16 , mem : & M ) {
529
555
debug_assert ! ( self . is_layout_valid( mem) ) ;
530
556
531
557
// Used ring has layout:
@@ -548,7 +574,7 @@ impl Queue {
548
574
549
575
/// Helper method that writes to the `idx` field of the used ring.
550
576
#[ inline( always) ]
551
- fn set_used_ring_idx < M : GuestMemory > ( & mut self , next_used : u16 , mem : & M ) {
577
+ pub fn set_used_ring_idx < M : GuestMemory > ( & mut self , next_used : u16 , mem : & M ) {
552
578
debug_assert ! ( self . is_layout_valid( mem) ) ;
553
579
554
580
// Used ring has layout:
0 commit comments