12#include <l4/cxx/bitmap>
13#include <l4/cxx/static_vector>
14#include <l4/l4virtio/server/l4virtio>
15#include <l4/l4virtio/server/virtio-console>
18namespace L4virtio {
namespace Svr {
namespace Console {
31 Buffer(Driver_mem_region
const *r,
35 pos =
static_cast<char *
>(r->local(d.
addr));
44 bool poll_in_req =
true;
45 bool poll_out_req =
false;
122 Irq_object(
Device *parent) : _parent(parent) {}
124 void handle_irq() { _parent->kick(); }
132 {
return &_irq_handler; }
147 _control_message_stalled(0)
149 _ports[0].vq_max = vq_max;
150 reset_queue_configs();
162 explicit Device(
unsigned vq_max,
unsigned ports)
166 _control_message_stalled(0)
168 if (ports >
sizeof(_control_message_stalled) * 8)
170 for (
unsigned i = 0; i < ports; ++i)
171 _ports[i].vq_max = vq_max;
172 reset_queue_configs();
188 _control_message_stalled(0)
190 if (max_ports() >
sizeof(_control_message_stalled)*8)
193 for (
unsigned i = 0; i < vq_max_nums.size(); ++i)
194 _ports[i].vq_max = vq_max_nums[i];
195 reset_queue_configs();
206 {
return _irq_handler.obj_cap(); }
214 _kick_driver_irq->trigger();
236 _kick_driver_irq->trigger();
247 for (
unsigned i = 0; i < max_ports(); ++i)
250 if (p.poll_in_req && p.tx_ready() && p.tx.desc_avail())
252 p.poll_in_req =
false;
256 if (p.poll_out_req && p.rx_ready() && p.rx.desc_avail())
258 p.poll_out_req =
false;
296 : Virtqueue::Request();
303 total += p.
src.copy_to(&dst);
313 p.
request = Virtqueue::Request();
320 p.
request = Virtqueue::Request();
325 p.poll_in_req =
true;
352 src.
pos =
const_cast<char*
>(buf);
365 Device_port::Buffer dst;
380 q->
finish(r,
this, chunk);
385 p.poll_out_req =
true;
402 if (_control_message_stalled)
408 bool ctrl_work_pending()
const
411 && _ctrl_port.
tx.
desc_avail()) || _control_message_stalled;
431 for (
unsigned i = 0; i < max_ports(); ++i)
471 { check_stalled(
id,
port_open(
id, value)); }
480 for (
unsigned i = 0; i < max_ports(); ++i)
482 if (!(_control_message_stalled & (1U << i)))
485 switch(_ports[i].status)
510 Port const *
port(
unsigned idx)
const override
515 void check_stalled(
unsigned port,
int retval)
518 _control_message_stalled |= 1U <<
port;
520 _control_message_stalled &= ~1U <<
port;
524 Irq_object _irq_handler;
525 cxx::unique_ptr<Device_port[]> _ports;
C++ interface for capabilities.
Base class implementing a virtio console device with L4Re-based notification handling.
void notify_queue(Virtqueue *queue) override
Notify queue of available data.
void trigger_driver_config_irq() override
callback for triggering configuration change notification IRQ
Device(unsigned vq_max, unsigned ports)
Create a new console device.
virtual void tx_space_available(unsigned port)=0
Callback to notify that data can be written to port.
Port * port(unsigned idx) override
Return the specified port.
unsigned port_write(char const *buf, unsigned len, unsigned port=0)
Write data to port.
void resend_stalled_control_messages()
Try to resend a stalled control message and update the port and global state accordingly.
L4::Cap< L4::Irq > device_notify_irq() const override
callback to gather the device notification IRQ (old-style)
void process_port_open(l4_uint32_t id, l4_uint16_t value) override
Callback called on PORT_OPEN event.
void process_device_ready(l4_uint16_t value) override
Callback called on DEVICE_READY event.
void process_port_ready(l4_uint32_t id, l4_uint16_t value) override
Callback called on PORT_READY event.
int do_control_work()
Receive new control messages and resend stalled ones.
virtual bool queues_stopped()
Return true, if the queues should not be processed further.
Device(unsigned vq_max)
Create a new console device.
virtual void rx_data_available(unsigned port)=0
Callback to notify that new data is available to be read from port.
Device(cxx::static_vector< unsigned > const &vq_max_nums)
Create a new console Device.
unsigned port_read(char *buf, unsigned len, unsigned port=0)
Read data from port.
void register_single_driver_irq() override
callback for registering a single guest IRQ for all queues (old-style)
Base class implementing a virtio console functionality.
int port_open(unsigned idx, bool open)
Send a PORT_OPEN message and update the internal state.
virtual void process_port_ready(l4_uint32_t id, l4_uint16_t value)
Callback called on PORT_READY event.
int port_remove(unsigned idx)
Send a DEVICE_REMOVE message and update the internal state.
int port_add(unsigned idx)
Send a DEVICE_ADD message and update the internal state.
int handle_control_message()
Handle control message received from the driver.
Mem_list const * mem_info() const
Get the memory region list used for this device.
Encapsulate the state for processing a VIRTIO request.
bool next(DESC_MAN *dm, ARGS... args)
Switch to the next descriptor in a descriptor chain.
void start(DESC_MAN *dm, Virtqueue *ring, Virtqueue::Head_desc const &request, ARGS... args)
Start processing a new request.
Virtqueue implementation for the device.
bool desc_avail() const
Test for available descriptors.
Request next_avail()
Get the next available descriptor from the available ring.
void finish(Head_desc &d, QUEUE_OBSERVER *o, l4_uint32_t len=0)
Add a descriptor to the used ring, and notify an observer.
Descriptor in the descriptor table.
l4_uint32_t len
Length of described buffer.
Ptr< void > addr
Address stored in descriptor.
bool no_notify_guest() const
Get the no IRQ flag of this queue.
Simple encapsulation for a dynamically allocated array.
unsigned int l4_uint32_t
Unsigned 32bit value.
unsigned short int l4_uint16_t
Unsigned 16bit value.
@ L4_EBUSY
Object currently busy, try later.
@ L4_ENODEV
No such thing.
#define L4_LIKELY(x)
Expression is likely to execute.
@ L4VIRTIO_IRQ_STATUS_VRING
VRING IRQ pending flag.
@ L4VIRTIO_IRQ_STATUS_CONFIG
CONFIG IRQ pending flag.
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.
L4-VIRTIO Transport C++ API.
Base class for interface implementations.
Epiface implementation for interrupt handlers.
Exception used by Queue to indicate descriptor errors.
A console port with associated read/write state.
void reset() override
Reset the port to the initial state and disable its virtqueues.
Request_processor rp
Request processor associated with current request.
Virtqueue::Request request
Current virtio tx queue request.
Buffer src
Source data block to process.
Representation of a Virtio console port.
Port_status status
State the port is in.
Virtqueue rx
Transmitq of the port.
virtual void reset()
Reset the port to the initial state and disable its virtqueues.
Virtqueue tx
Receiveq of the port.
bool rx_ready() const
Check that device implementation may write to receive queues.
bool tx_ready() const
Check that device implementation may read from transmit queues.
@ Port_ready
Port is ready but still closed.
@ Port_open
Port is in a working state.
@ Port_disabled
Reset state, waiting for port to be added.
@ Port_failed
Device failure, port unusable.
bool queues_ready() const
Check that both virtqueues are set up correctly.
l4_uint32_t copy_to(Data_buffer *dst, l4_uint32_t max=UINT_MAX)
Copy contents from this buffer to the destination buffer.
l4_uint32_t left
Bytes left in buffer.
char * pos
Current buffer position.