15#include <l4/re/util/object_registry>
20#include <l4/l4virtio/l4virtio>
21#include <l4/l4virtio/virtqueue>
67 "Allocate config dataspace capability");
70 L4Re::chksys(_device->device_config(_config_cap.get(), &ds_offset),
71 "Request virtio config page");
80 "Attach config dataspace");
82 if (memcmp(&_config->magic,
"virt", 4) != 0)
85 if (_config->version != 2)
88 _device->set_status(0);
90 _device->set_status(status);
93 _device->set_status(status);
95 if (_config->fail_state())
102 "Allocate host IRQ capability");
104 L4Re::chksys(_device->device_notification_irq(0, _host_irq.get()),
105 "Request device notification interrupt.");
111 _driver_notification =
113 "Allocate notification capability");
116 "Create semaphore for notifications from device");
118 L4Re::chksys(_device->bind(0, _driver_notification.get()),
119 "Bind driver notification interrupt");
130 {
return l4_error(_device->bind(index, irq)); }
161 "Require Virtio 1.0 device; Legacy device not supported.");
163 _config->driver_features_map[0] &= _config->dev_features_map[0];
164 _config->driver_features_map[1] &= _config->dev_features_map[1];
173 if (_config->fail_state())
199 *devaddr = next_device_address(size);
215 auto *queueconf = &_config->queues()[num];
216 queueconf->num = size;
217 queueconf->desc_addr = desc_addr;
218 queueconf->avail_addr = avail_addr;
219 queueconf->used_addr = used_addr;
220 queueconf->ready = 1;
222 return _device->config_queue(num);
232 return _config->queues()[num].num_max;
301 if (head != Virtqueue::Eoq)
321 _host_irq->trigger();
351 L4::Cap<L4virtio::Device> _device;
352 L4Re::Rm::Unique_region<L4virtio::Device::Config_hdr *> _config;
bit manipulation functions
static Env const * env() noexcept
Returns the initial environment for the current task.
C++ interface for capabilities.
Client-side implementation for a general virtio device.
int wait(int index) const
Wait for a notification from the device.
int max_queue_size(int num) const
Maximum queue size allowed by the device.
int bind_notification_irq(unsigned index, L4::Cap< L4::Triggerable > irq) const
Register a triggerable to receive notifications from 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.
bool fail_state() const
Return true if the device is in a fail state.
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.
bool feature_negotiated(unsigned int feat) const
Check if a particular feature bit was negotiated with the device.
int driver_acknowledge()
Finalize handshake with the device.
int send_and_wait(Virtqueue &queue, l4_uint16_t descno)
Send a request to the device and wait for it to be processed.
Driver-side implementation of a Virtqueue.
void enqueue_descriptor(l4_uint16_t descno)
Enqueue a descriptor in the available ring.
l4_uint16_t find_next_used(l4_uint32_t *len=nullptr)
Return the next finished block.
bool no_notify_host() const
Get the no notify flag of this queue.
Common factory related definitions.
unsigned long l4_umword_t
Unsigned machine word.
unsigned long l4_addr_t
Address type.
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_EEXIST
Already exists.
@ L4_EINVAL
Invalid argument.
@ L4_ENODEV
No such thing.
long l4_error(l4_msgtag_t tag) L4_NOTHROW
Get IPC error code if any or message tag label otherwise for an IPC call.
l4_umword_t l4_ipc_error(l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW
Get the IPC error code for an IPC operation.
#define L4_SUPERPAGESIZE
Size of a large page.
l4_addr_t l4_round_page(l4_addr_t address) L4_NOTHROW
Round address up to the next page.
#define L4_PAGESIZE
Minimal page size (in bytes).
#define L4_PAGESHIFT
Size of a page, log2-based.
#define L4_PAGEMASK
Mask for the page number.
l4_utcb_t * l4_utcb(void) L4_NOTHROW L4_PURE
Get the UTCB address.
int l4util_cmpxchg(volatile l4_umword_t *dest, l4_umword_t cmp_val, l4_umword_t new_val)
Atomic compare and exchange (machine wide fields).
unsigned l4virtio_get_feature(l4_uint32_t *feature_map, unsigned feat)
Check if the given bit in a feature map is set.
@ L4VIRTIO_FEATURE_VERSION_1
Virtio protocol version 1 supported. Must be 1 for L4virtio.
@ L4VIRTIO_STATUS_DRIVER
Guest OS knows how to drive device.
@ L4VIRTIO_STATUS_ACKNOWLEDGE
Guest OS has found device.
@ L4VIRTIO_STATUS_FEATURES_OK
Driver has acknowledged feature set.
@ L4VIRTIO_STATUS_DRIVER_OK
Driver is set up.
atomic operations header and generic implementations
Unique_cap< T > make_unique_cap()
Allocate a capability slot and wrap it in an Unique_cap.
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.
Semaphore class definition.
@ RW
Readable and writable region.
@ Search_addr
Search for a suitable address range.
Unique_cap / Unique_del_cap.