1 // Copyright 2016 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 #pragma once 5 6 #include <ddk/io-buffer.h> 7 #include <virtio/virtio_ring.h> 8 #include <zircon/types.h> 9 10 #include "trace.h" 11 12 namespace virtio { 13 14 class Device; 15 16 class Ring { 17 public: 18 Ring(Device* device); 19 ~Ring(); 20 21 // Initialize ring |index| with default (device-offered) size. 22 zx_status_t Init(uint16_t index); 23 zx_status_t Init(uint16_t index, uint16_t count); 24 25 void FreeDesc(uint16_t desc_index); 26 struct vring_desc* AllocDescChain(uint16_t count, uint16_t* start_index); 27 void SubmitChain(uint16_t desc_index); 28 void Kick(); 29 DescFromIndex(uint16_t index)30 struct vring_desc* DescFromIndex(uint16_t index) { 31 return &ring_.desc[index]; 32 } 33 34 template <typename T> 35 void IrqRingUpdate(T free_chain); 36 37 private: 38 Device* device_ = nullptr; 39 40 io_buffer_t ring_buf_; 41 42 uint16_t index_ = 0; 43 44 vring ring_ = {}; 45 }; 46 47 // perform the main loop of finding free descriptor chains and passing it to a passed in function 48 template <typename T> IrqRingUpdate(T free_chain)49inline void Ring::IrqRingUpdate(T free_chain) { 50 // TRACEF("used flags %#x idx %#x last_used %u\n", 51 // ring_.used->flags, ring_.used->idx, ring_.last_used); 52 53 // find a new free chain of descriptors 54 uint16_t cur_idx = ring_.used->idx; 55 uint16_t i = ring_.last_used; 56 for (; i != cur_idx; ++i) { 57 // TRACEF("looking at idx %u\n", i); 58 59 struct vring_used_elem* used_elem = &ring_.used->ring[i & ring_.num_mask]; 60 // TRACEF("used chain id %u, len %u\n", used_elem->id, used_elem->len); 61 62 // free the chain 63 free_chain(used_elem); 64 } 65 ring_.last_used = i; 66 } 67 68 void virtio_dump_desc(const struct vring_desc* desc); 69 70 } // namespace virtio 71