@@ -59,10 +59,10 @@ unsafe impl ByteValued for Descriptor {}
5959/// https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-430008
6060/// 2.6.8 The Virtqueue Used Ring
6161#[ 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 ,
6666}
6767
6868// SAFETY: `UsedElement` is a POD and contains no padding.
@@ -387,7 +387,7 @@ impl Queue {
387387 /// # Important
388388 /// This is an internal method that ASSUMES THAT THERE ARE AVAILABLE DESCRIPTORS. Otherwise it
389389 /// 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 > (
391391 & mut self ,
392392 mem : & ' b M ,
393393 ) -> Option < DescriptorChain < ' b , M > > {
@@ -466,7 +466,33 @@ impl Queue {
466466 Ok ( ( ) )
467467 }
468468
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 > (
470496 & self ,
471497 mem : & M ,
472498 index : u16 ,
@@ -525,7 +551,7 @@ impl Queue {
525551
526552 /// Helper method that writes to the `avail_event` field of the used ring.
527553 #[ 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 ) {
529555 debug_assert ! ( self . is_layout_valid( mem) ) ;
530556
531557 // Used ring has layout:
@@ -548,7 +574,7 @@ impl Queue {
548574
549575 /// Helper method that writes to the `idx` field of the used ring.
550576 #[ 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 ) {
552578 debug_assert ! ( self . is_layout_valid( mem) ) ;
553579
554580 // Used ring has layout:
0 commit comments