13#include <l4/cxx/minmax>
18#include <l4/sys/consts.h>
20#include <l4/l4virtio/client/l4virtio>
21#include <l4/l4virtio/l4virtio>
22#include <l4/l4virtio/virtio_net.h>
23#include <l4/l4virtio/virtqueue>
25namespace L4virtio {
namespace Driver {
74 if (_config->num_queues < 2)
83 L4virtio::Virtqueue::Desc_align);
85 L4virtio::Virtqueue::Desc_align);
86 auto txpktoff = rxpktoff + rxqsz *
sizeof(
Packet);
87 auto totalsz = txpktoff + txqsz *
sizeof(
Packet);
89 _queue_ds =
L4Re::chkcap(L4Re::Util::make_unique_cap<L4Re::Dataspace>(),
90 "Allocate queue dataspace capability");
92 L4Re::chksys(e->mem_alloc()->alloc(totalsz, _queue_ds.get(),
95 "Allocate memory for virtio structures");
101 "Attach dataspace for virtio structures");
105 "Register queue dataspace with device");
117 _rxpkts =
reinterpret_cast<Packet*
>(_queue_region.
get() + rxpktoff);
118 _txpkts =
reinterpret_cast<Packet*
>(_queue_region.
get() + txpktoff);
121 for (
l4_uint16_t descno = 0; descno < rxqsz; ++descno)
123 auto &desc = _rxq.
desc(descno);
126 desc.len =
sizeof(
Packet);
127 desc.flags.write() = 1;
129 for (
l4_uint16_t descno = 0; descno < txqsz; ++descno)
131 auto &desc = _txq.
desc(descno);
134 desc.len =
sizeof(
Packet);
160 if (descno >= _rxq.
num())
162 return _rxpkts[descno];
182 *len = cxx::min(*len -
sizeof(_rxpkts[0].hdr),
sizeof(_rxpkts[0].data));
227 if (descno == Virtqueue::Eoq)
230 free_used_tx_descriptors();
232 if (descno == Virtqueue::Eoq)
236 auto &pkt = _txpkts[descno];
237 auto &desc = _txq.
desc(descno);
238 desc.
len =
sizeof(pkt.hdr) + prepare(pkt);
244 void free_used_tx_descriptors()
249 if (used >= _txq.
num())
259 Packet *_rxpkts, *_txpkts;
static Env const * env() noexcept
Returns the initial environment for the current task.
@ Continuous
Allocate physically contiguous memory.
@ Pinned
Deprecated, use L4Re::Dma_space instead.
T get() const noexcept
Return the address.
C++ interface for capabilities.
Client-side implementation for a general virtio device.
int max_queue_size(int num) const
Maximum queue size allowed by the device.
int wait_for_next_used(Virtqueue &queue, l4_uint32_t *len=nullptr) const
Wait for the next item to arrive in the used queue and return it.
void driver_connect(L4::Cap< L4virtio::Device > srvcap, bool manage_notify=true)
Contacts the device and starts the initial handshake.
void send(Virtqueue &queue, l4_uint16_t descno)
Send a request to the device.
int register_ds(L4::Cap< L4Re::Dataspace > ds, l4_umword_t offset, l4_umword_t size, l4_uint64_t *devaddr)
Share a dataspace with the device.
int config_queue(int num, unsigned size, l4_uint64_t desc_addr, l4_uint64_t avail_addr, l4_uint64_t used_addr)
Send the virtqueue configuration to the device.
int driver_acknowledge()
Finalize handshake with the device.
Simple class for accessing a virtio net device.
int rx_queue_size() const
Return the maximum receive queue size allowed by the device.
void finish_rx(l4_uint16_t descno)
Free an RX descriptor number to make it available for the RX queue again.
Packet & rx_pkt(l4_uint16_t descno)
Return a reference to the RX packet buffer of the specified descriptor, e.g.
l4virtio_net_config_t const & device_config() const
Return a reference to the device configuration.
l4_uint16_t wait_rx(l4_uint32_t *len=nullptr)
Block until a network packet has been received from the device and return the descriptor number.
int tx_queue_size() const
Return the maximum transmit queue size allowed by the device.
void setup_device(L4::Cap< L4virtio::Device > srvcap)
Establish a connection to the device and set up shared memory.
bool tx(std::function< l4_uint32_t(Packet &)> prepare)
Attempt to allocate a descriptor in the TX queue and transmit the packet, after calling the prepare c...
void queue_rx()
Queue new available descriptors in the RX queue.
Driver-side implementation of a Virtqueue.
void free_descriptor(l4_uint16_t head, l4_uint16_t tail)
Free a chained list of descriptors in the descriptor queue.
void enqueue_descriptor(l4_uint16_t descno)
Enqueue a descriptor in the available ring.
l4_uint16_t alloc_descriptor()
Allocate and return an unused descriptor from the descriptor table.
l4_uint16_t find_next_used(l4_uint32_t *len=nullptr)
Return the next finished block.
void init_queue(unsigned num, void *desc, void *avail, void *used)
Initialize this virtqueue.
Desc & desc(l4_uint16_t descno)
Return a reference to a descriptor in the descriptor table.
Pointer used in virtio descriptors.
l4_uint32_t len
Length of described buffer.
Ptr< void > addr
Address stored in descriptor.
unsigned long avail_offset() const
Get the offset of the available ring from the descriptor table.
static unsigned long total_size(unsigned num)
Calculate the total size for a virtqueue of the given dimensions.
unsigned long used_offset() const
Get the offset of the used ring from the descriptor table.
unsigned char l4_uint8_t
Unsigned 8bit value.
unsigned int l4_uint32_t
Unsigned 32bit value.
unsigned short int l4_uint16_t
Unsigned 16bit value.
unsigned long long l4_uint64_t
Unsigned 64bit value.
@ L4_EINVAL
Invalid argument.
@ L4_ENODEV
No such thing.
#define L4_PAGESHIFT
Size of a page, log2-based.
l4_addr_t l4_round_size(l4_addr_t value, unsigned char bits) L4_NOTHROW
Round value up to the next alignment with bits size.
void l4virtio_set_feature(l4_uint32_t *feature_map, unsigned feat)
Set the given feature bit in a feature map.
@ L4VIRTIO_FEATURE_VERSION_1
Virtio protocol version 1 supported. Must be 1 for L4virtio.
@ L4VIRTIO_ID_NET
Virtual ethernet card.
L4::Detail::Unique_cap_impl< T, Smart_cap_auto< L4_FP_ALL_SPACES > > Unique_cap
Unique capability that implements automatic free and unmap of the capability selector.
long chksys(long err, char const *extra="", long ret=0)
Generate C++ exception on error.
T chkcap(T &&cap, char const *extra="", long err=-L4_ENOMEM)
Check for valid capability or raise C++ exception.
Cap< T > make_cap_rw(L4::Cap< T > cap) noexcept
Make an L4::Ipc::Cap<T> for the given capability with L4_CAP_FPAGE_RW rights.
L4-VIRTIO Transport C++ API.
@ RW
Readable and writable region.
@ Search_addr
Search for a suitable address range.
Structure for a network packet (header including data) with maximum size, assuming that no extra feat...
Device configuration for network devices.
Unique_cap / Unique_del_cap.