pub fn add(&mut self, inputs: &[&[u8]], outputs: &[&mut [u8]]) -> Result<u16> {
        if inputs.is_empty() && outputs.is_empty() {
            return Err(Error::InvalidParam);
        }
        if inputs.len() + outputs.len() + self.num_used as usize > self.queue_size as usize {
            return Err(Error::BufferTooSmall);
        }

        // allocate descriptors from free list
        let head = self.free_head;
        let mut last = self.free_head;
        for input in inputs.iter() {
            let desc = &mut self.desc[self.free_head as usize];
            desc.set_buf(input);
            desc.flags.write(DescFlags::NEXT);
            last = self.free_head;
            self.free_head = desc.next.read();
        }
        for output in outputs.iter() {
            let desc = &mut self.desc[self.free_head as usize];
            desc.set_buf(output);
            desc.flags.write(DescFlags::NEXT | DescFlags::WRITE);
            last = self.free_head;
            self.free_head = desc.next.read();
        }
        // set last_elem.next = NULL
        {
            let desc = &mut self.desc[last as usize];
            let mut flags = desc.flags.read();
            flags.remove(DescFlags::NEXT);
            desc.flags.write(flags);
        }
        self.num_used += (inputs.len() + outputs.len()) as u16;

        let avail_slot = self.avail_idx & (self.queue_size - 1);
        self.avail.ring[avail_slot as usize].write(head);

        // write barrier
        fence(Ordering::SeqCst);

        // increase head of avail ring
        self.avail_idx = self.avail_idx.wrapping_add(1);
        self.avail.idx.write(self.avail_idx);
        Ok(head)
    }
/// Add buffers to the virtqueue, return a token.
///
/// Ref: linux virtio_ring.c virtqueue_add
Add buffers to the virtqueue, return a token.
Add buffers to the virtqueue return a token .
pub fn add(&mut self, inputs: &[&[u8]], outputs: &[&mut [u8]]) -> Result<u16> {
        if inputs.is_empty() && outputs.is_empty() {
            return Err(Error::InvalidParam);
        }
        if inputs.len() + outputs.len() + self.num_used as usize > self.queue_size as usize {
            return Err(Error::BufferTooSmall);
        }
        // allocate descriptors from free list
        let head = self.free_head;
        let mut last = self.free_head;
        for input in inputs.iter() {
            let desc = &mut self.desc[self.free_head as usize];
            desc.set_buf(input);
            desc.flags.write(DescFlags::NEXT);
            last = self.free_head;
            self.free_head = desc.next.read();
        }
        for output in outputs.iter() {
            let desc = &mut self.desc[self.free_head as usize];
            desc.set_buf(output);
            desc.flags.write(DescFlags::NEXT | DescFlags::WRITE);
            last = self.free_head;
            self.free_head = desc.next.read();
        }
        // set last_elem.next = NULL
        {
            let desc = &mut self.desc[last as usize];
            let mut flags = desc.flags.read();
            flags.remove(DescFlags::NEXT);
            desc.flags.write(flags);
        }
        self.num_used += (inputs.len() + outputs.len()) as u16;
        let avail_slot = self.avail_idx & (self.queue_size - 1);
        self.avail.ring[avail_slot as usize].write(head);
        // write barrier
        fence(Ordering::SeqCst);
        // increase head of avail ring
        self.avail_idx = self.avail_idx.wrapping_add(1);
        self.avail.idx.write(self.avail_idx);
        Ok(head)
    }
pub fn add ( & mut self , inputs : & [ & [ u8 ] ] , outputs : & [ & mut [ u8 ] ] ) -> Result < u16 > { if inputs . is_empty ( ) && outputs . is_empty ( ) { return Err ( Error :: InvalidParam ) ; } if inputs . len ( ) + outputs . len ( ) + self . num_used as usize > self . queue_size as usize { return Err ( Error :: BufferTooSmall ) ; } // allocate descriptors from free list let head = self . free_head ; let mut last = self . free_head ; for input in inputs . iter ( ) { let desc = & mut self . desc [ self . free_head as usize ] ; desc . set_buf ( input ) ; desc . flags . write ( DescFlags :: NEXT ) ; last = self . free_head ; self . free_head = desc . next . read ( ) ; } for output in outputs . iter ( ) { let desc = & mut self . desc [ self . free_head as usize ] ; desc . set_buf ( output ) ; desc . flags . write ( DescFlags :: NEXT | DescFlags :: WRITE ) ; last = self . free_head ; self . free_head = desc . next . read ( ) ; } // set last_elem.next = NULL { let desc = & mut self . desc [ last as usize ] ; let mut flags = desc . flags . read ( ) ; flags . remove ( DescFlags :: NEXT ) ; desc . flags . write ( flags ) ; } self . num_used += ( inputs . len ( ) + outputs . len ( ) ) as u16 ; let avail_slot = self . avail_idx & ( self . queue_size - 1 ) ; self . avail . ring [ avail_slot as usize ] . write ( head ) ; // write barrier fence ( Ordering :: SeqCst ) ; // increase head of avail ring self . avail_idx = self . avail_idx . wrapping_add ( 1 ) ; self . avail . idx . write ( self . avail_idx ) ; Ok ( head ) }
Add buffers to the virtqueue, return a token.
Add buffers to the virtqueue return a token .
&mut self
inputs
&[&[u8]]
outputs
&[&mut [u8]]
&mut self
inputs
&[&[u8]]
outputs
&[&mut [u8]]