mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-11 13:22:33 +00:00
parent
fdba7259ab
commit
ec6f89111e
@ -14,10 +14,7 @@
|
||||
#ifndef _INCLUDE__VIRTIO__PCI_DEVICE_H_
|
||||
#define _INCLUDE__VIRTIO__PCI_DEVICE_H_
|
||||
|
||||
#include <os/attached_mmio.h>
|
||||
#include <irq_session/client.h>
|
||||
#include <legacy/x86/platform_device/client.h>
|
||||
#include <legacy/x86/platform_session/connection.h>
|
||||
#include <platform_session/device.h>
|
||||
#include <virtio/queue.h>
|
||||
|
||||
namespace Virtio {
|
||||
@ -26,7 +23,7 @@ namespace Virtio {
|
||||
class Device;
|
||||
}
|
||||
|
||||
struct Virtio::Device_mmio : public Attached_mmio
|
||||
struct Virtio::Device_mmio : public Genode::Mmio
|
||||
{
|
||||
struct DeviceFeatureSelect : Register<0x00, 32> { };
|
||||
struct DeviceFeature : Register<0x04, 32> { };
|
||||
@ -54,10 +51,7 @@ struct Virtio::Device_mmio : public Attached_mmio
|
||||
|
||||
struct IrqReason : Register<0x0, 32> { };
|
||||
|
||||
Device_mmio(Genode::Env &env,
|
||||
Genode::addr_t base,
|
||||
Genode::size_t size)
|
||||
: Attached_mmio(env, base, size, false) { }
|
||||
using Mmio::Mmio;
|
||||
};
|
||||
|
||||
class Virtio::Device
|
||||
@ -93,133 +87,112 @@ class Virtio::Device
|
||||
|
||||
enum {
|
||||
VIRTIO_PCI_BASE_ID = 0x1040,
|
||||
VIRTIO_MSI_NO_VECTOR = 0xffff
|
||||
VIRTIO_MSI_NO_VECTOR = 0xffff,
|
||||
MMIO_MAX = 6U
|
||||
};
|
||||
|
||||
Genode::Env &_env;
|
||||
Platform::Device_client &_device;
|
||||
Genode::Irq_session_client _irq { _device.irq(0) };
|
||||
uint32_t _notify_offset_multiplier = 0;
|
||||
Genode::Constructible<Device_mmio> _cfg_common { };
|
||||
Genode::Constructible<Device_mmio> _dev_config { };
|
||||
Genode::Constructible<Device_mmio> _notify { };
|
||||
Genode::Constructible<Device_mmio> _isr { };
|
||||
Env & _env;
|
||||
Platform::Connection & _plat;
|
||||
Platform::Device _device { _plat };
|
||||
Platform::Device::Irq _irq { _device, { 0 } };
|
||||
|
||||
Constructible<Platform::Device::Mmio> _mmio[MMIO_MAX] { };
|
||||
|
||||
void _configure()
|
||||
Mmio _cfg_common { _bar_offset("common") };
|
||||
Mmio _dev_config { _bar_offset("device") };
|
||||
Mmio _notify { _bar_offset("notify") };
|
||||
Mmio _isr { _bar_offset("irq_status") };
|
||||
size_t _notify_offset_multiplier { 0 };
|
||||
|
||||
template <typename FN>
|
||||
void with_virtio_range(String<16> type, FN const & fn)
|
||||
{
|
||||
typedef Platform::Device Pdev;
|
||||
_plat.update();
|
||||
_plat.with_xml([&] (Xml_node xml) {
|
||||
xml.with_optional_sub_node("device", [&] (Xml_node xml) {
|
||||
xml.with_optional_sub_node("pci-config",
|
||||
[&] (Xml_node xml) {
|
||||
xml.for_each_sub_node("virtio_range",
|
||||
[&] (Xml_node xml) {
|
||||
if (xml.attribute_value("type", String<16>()) ==
|
||||
type)
|
||||
fn(xml);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
enum { PCI_STATUS = 0x6, PCI_CAPABILITIES = 0x34, };
|
||||
addr_t _bar_offset(String<16> type)
|
||||
{
|
||||
unsigned idx = MMIO_MAX;
|
||||
addr_t off = ~0UL;
|
||||
with_virtio_range(type, [&] (Xml_node xml) {
|
||||
idx = xml.attribute_value<unsigned>("index", MMIO_MAX);
|
||||
off = xml.attribute_value("offset", ~0UL);
|
||||
});
|
||||
|
||||
auto status = _device.config_read(PCI_STATUS, Pdev::ACCESS_16BIT);
|
||||
if (!(status & 0x10)) {
|
||||
error("PCI capabilities missing according to device status!");
|
||||
throw Configuration_failed();
|
||||
}
|
||||
|
||||
auto addr = _device.config_read(PCI_CAPABILITIES, Pdev::ACCESS_8BIT);
|
||||
addr &= 0xFC;
|
||||
|
||||
while (addr) {
|
||||
enum { ID_VNDR = 0x09 };
|
||||
enum { CAP_ID = 0, CAP_LIST_NEXT = 1 };
|
||||
|
||||
auto const cap_id = _device.config_read(addr + CAP_ID, Pdev::ACCESS_8BIT);
|
||||
auto const cap_next = _device.config_read(addr + CAP_LIST_NEXT, Pdev::ACCESS_8BIT);
|
||||
|
||||
if (cap_id == ID_VNDR) {
|
||||
enum { CFG_TYPE = 0x3, BAR = 0x4, OFFSET = 0x8,
|
||||
LENGTH = 0xC, NOTIFY_OFFSET_MULT = 0x10 };
|
||||
enum { COMMON_CFG = 1, NOTIFY_CFG = 2, ISR_CFG = 3,
|
||||
DEVICE_CFG = 4, PCI_CFG = 5 };
|
||||
|
||||
auto const cfg_type = _device.config_read(addr + CFG_TYPE, Pdev::ACCESS_8BIT);
|
||||
auto const bar = _device.config_read(addr + BAR, Pdev::ACCESS_8BIT);
|
||||
auto const off = _device.config_read(addr + OFFSET, Pdev::ACCESS_32BIT);
|
||||
auto const len = _device.config_read(addr + LENGTH, Pdev::ACCESS_32BIT);
|
||||
|
||||
if (cfg_type == COMMON_CFG) {
|
||||
auto const r = _device.resource(bar);
|
||||
_cfg_common.construct(_env, r.base() + off, len);
|
||||
} else if (cfg_type == DEVICE_CFG) {
|
||||
auto const r = _device.resource(bar);
|
||||
_dev_config.construct(_env, r.base() + off, len);
|
||||
} else if (cfg_type == NOTIFY_CFG) {
|
||||
_notify_offset_multiplier = _device.config_read(
|
||||
addr + NOTIFY_OFFSET_MULT, Pdev::ACCESS_32BIT);
|
||||
auto const r = _device.resource(bar);
|
||||
_notify.construct(_env, r.base() + off, len);
|
||||
} else if (cfg_type == ISR_CFG) {
|
||||
auto const r = _device.resource(bar);
|
||||
_isr.construct(_env, r.base() + off, len);
|
||||
}
|
||||
}
|
||||
|
||||
addr = cap_next;
|
||||
}
|
||||
|
||||
if (!_cfg_common.constructed() || !_dev_config.constructed() ||
|
||||
!_notify.constructed() || !_isr.constructed()) {
|
||||
error("Required VirtIO PCI capabilities not found!");
|
||||
if (idx >= MMIO_MAX || off == ~0UL)
|
||||
throw Configuration_failed();
|
||||
}
|
||||
|
||||
_cfg_common->write<Device_mmio::MsiXConfig>(VIRTIO_MSI_NO_VECTOR);
|
||||
if (!_mmio[idx].constructed())
|
||||
_mmio[idx].construct(_device,
|
||||
Platform::Device::Mmio::Index{idx});
|
||||
return _mmio[idx]->base() + off;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Device(Genode::Env &env,
|
||||
Platform::Device_client device)
|
||||
: _env(env), _device(device)
|
||||
Device(Genode::Env & env,
|
||||
Platform::Connection & plat)
|
||||
: _env(env), _plat(plat)
|
||||
{
|
||||
_configure();
|
||||
with_virtio_range("notify", [&] (Xml_node xml) {
|
||||
_notify_offset_multiplier = xml.attribute_value("factor", 0UL);
|
||||
});
|
||||
|
||||
_cfg_common.write<Device_mmio::MsiXConfig>(VIRTIO_MSI_NO_VECTOR);
|
||||
}
|
||||
|
||||
uint32_t vendor_id() { return _device.vendor_id(); }
|
||||
uint32_t device_id() {
|
||||
return _device.device_id() - VIRTIO_PCI_BASE_ID; }
|
||||
|
||||
uint8_t get_status() {
|
||||
return _cfg_common->read<Device_mmio::DeviceStatus>(); }
|
||||
return _cfg_common.read<Device_mmio::DeviceStatus>(); }
|
||||
|
||||
bool set_status(uint8_t status)
|
||||
{
|
||||
_cfg_common->write<Device_mmio::DeviceStatus>(status);
|
||||
return _cfg_common->read<Device_mmio::DeviceStatus>() == status;
|
||||
_cfg_common.write<Device_mmio::DeviceStatus>(status);
|
||||
return _cfg_common.read<Device_mmio::DeviceStatus>() == status;
|
||||
}
|
||||
|
||||
uint32_t get_features(uint32_t selection)
|
||||
{
|
||||
_cfg_common->write<Device_mmio::DeviceFeatureSelect>(selection);
|
||||
return _cfg_common->read<Device_mmio::DeviceFeature>();
|
||||
_cfg_common.write<Device_mmio::DeviceFeatureSelect>(selection);
|
||||
return _cfg_common.read<Device_mmio::DeviceFeature>();
|
||||
}
|
||||
|
||||
void set_features(uint32_t selection, uint32_t features)
|
||||
{
|
||||
_cfg_common->write<Device_mmio::DriverFeatureSelect>(selection);
|
||||
_cfg_common->write<Device_mmio::DriverFeature>(features);
|
||||
_cfg_common.write<Device_mmio::DriverFeatureSelect>(selection);
|
||||
_cfg_common.write<Device_mmio::DriverFeature>(features);
|
||||
}
|
||||
|
||||
uint8_t get_config_generation() {
|
||||
return _cfg_common->read<Device_mmio::ConfigGeneration>(); }
|
||||
return _cfg_common.read<Device_mmio::ConfigGeneration>(); }
|
||||
|
||||
uint16_t get_max_queue_size(uint16_t queue_index)
|
||||
{
|
||||
_cfg_common->write<Device_mmio::QueueSelect>(queue_index);
|
||||
return _cfg_common->read<Device_mmio::QueueSize>();
|
||||
_cfg_common.write<Device_mmio::QueueSelect>(queue_index);
|
||||
return _cfg_common.read<Device_mmio::QueueSize>();
|
||||
}
|
||||
|
||||
uint32_t read_config(uint8_t offset, Access_size size)
|
||||
{
|
||||
switch (size) {
|
||||
case Device::ACCESS_8BIT:
|
||||
return _dev_config->read<Device_mmio::Config_8>(offset);
|
||||
return _dev_config.read<Device_mmio::Config_8>(offset);
|
||||
case Device::ACCESS_16BIT:
|
||||
return _dev_config->read<Device_mmio::Config_16>(offset >> 1);
|
||||
return _dev_config.read<Device_mmio::Config_16>(offset >> 1);
|
||||
case Device::ACCESS_32BIT:
|
||||
return _dev_config->read<Device_mmio::Config_32>(offset >> 2);
|
||||
return _dev_config.read<Device_mmio::Config_32>(offset >> 2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -228,63 +201,63 @@ class Virtio::Device
|
||||
{
|
||||
switch (size) {
|
||||
case Device::ACCESS_8BIT:
|
||||
_dev_config->write<Device_mmio::Config_8>(value, offset);
|
||||
_dev_config.write<Device_mmio::Config_8>(value, offset);
|
||||
break;
|
||||
case Device::ACCESS_16BIT:
|
||||
_dev_config->write<Device_mmio::Config_16>(value, offset >> 1);
|
||||
_dev_config.write<Device_mmio::Config_16>(value, offset >> 1);
|
||||
break;
|
||||
case Device::ACCESS_32BIT:
|
||||
_dev_config->write<Device_mmio::Config_32>(value, offset >> 2);
|
||||
_dev_config.write<Device_mmio::Config_32>(value, offset >> 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool configure_queue(uint16_t queue_index, Virtio::Queue_description desc)
|
||||
{
|
||||
_cfg_common->write<Device_mmio::QueueSelect>(queue_index);
|
||||
_cfg_common.write<Device_mmio::QueueSelect>(queue_index);
|
||||
|
||||
if (_cfg_common->read<Device_mmio::QueueEnable>()) {
|
||||
if (_cfg_common.read<Device_mmio::QueueEnable>()) {
|
||||
warning("VirtIO queues can't be re-configured after being enabled!");
|
||||
return false;
|
||||
}
|
||||
|
||||
_cfg_common->write<Device_mmio::QueueMsixVector>(VIRTIO_MSI_NO_VECTOR);
|
||||
if (_cfg_common->read<Device_mmio::QueueMsixVector>() != VIRTIO_MSI_NO_VECTOR) {
|
||||
_cfg_common.write<Device_mmio::QueueMsixVector>(VIRTIO_MSI_NO_VECTOR);
|
||||
if (_cfg_common.read<Device_mmio::QueueMsixVector>() != VIRTIO_MSI_NO_VECTOR) {
|
||||
error("Failed to disable MSI-X for queue ", queue_index);
|
||||
return false;
|
||||
}
|
||||
|
||||
_cfg_common->write<Device_mmio::QueueSize>(desc.size);
|
||||
_cfg_common.write<Device_mmio::QueueSize>(desc.size);
|
||||
|
||||
uint64_t addr = desc.desc;
|
||||
_cfg_common->write<Device_mmio::QueueDescLow>((uint32_t)addr);
|
||||
_cfg_common->write<Device_mmio::QueueDescHigh>((uint32_t)(addr >> 32));
|
||||
_cfg_common.write<Device_mmio::QueueDescLow>((uint32_t)addr);
|
||||
_cfg_common.write<Device_mmio::QueueDescHigh>((uint32_t)(addr >> 32));
|
||||
|
||||
addr = desc.avail;
|
||||
_cfg_common->write<Device_mmio::QueueAvailLow>((uint32_t)addr);
|
||||
_cfg_common->write<Device_mmio::QueueAvailHigh>((uint32_t)(addr >> 32));
|
||||
_cfg_common.write<Device_mmio::QueueAvailLow>((uint32_t)addr);
|
||||
_cfg_common.write<Device_mmio::QueueAvailHigh>((uint32_t)(addr >> 32));
|
||||
|
||||
addr = desc.used;
|
||||
_cfg_common->write<Device_mmio::QueueUsedLow>((uint32_t)addr);
|
||||
_cfg_common->write<Device_mmio::QueueUsedHigh>((uint32_t)(addr >> 32));
|
||||
_cfg_common->write<Device_mmio::QueueEnable>(1);
|
||||
return _cfg_common->read<Device_mmio::QueueEnable>() != 0;
|
||||
_cfg_common.write<Device_mmio::QueueUsedLow>((uint32_t)addr);
|
||||
_cfg_common.write<Device_mmio::QueueUsedHigh>((uint32_t)(addr >> 32));
|
||||
_cfg_common.write<Device_mmio::QueueEnable>(1);
|
||||
return _cfg_common.read<Device_mmio::QueueEnable>() != 0;
|
||||
}
|
||||
|
||||
void notify_buffers_available(uint16_t queue_index) {
|
||||
_cfg_common->write<Device_mmio::QueueSelect>(queue_index);
|
||||
auto const offset = _cfg_common->read<Device_mmio::QueueNotifyOff>();
|
||||
_cfg_common.write<Device_mmio::QueueSelect>(queue_index);
|
||||
auto const offset = _cfg_common.read<Device_mmio::QueueNotifyOff>();
|
||||
auto const addr = (offset * _notify_offset_multiplier >> 1) + 1;
|
||||
_notify->local_addr<uint16_t>()[addr] = queue_index;
|
||||
*(uint16_t*)(_notify.base() + addr) = queue_index;
|
||||
}
|
||||
|
||||
uint32_t read_isr() {
|
||||
return _isr->read<Device_mmio::IrqReason>(); }
|
||||
return _isr.read<Device_mmio::IrqReason>(); }
|
||||
|
||||
void irq_sigh(Signal_context_capability cap) {
|
||||
_irq.sigh(cap); }
|
||||
|
||||
void irq_ack() { _irq.ack_irq(); }
|
||||
void irq_ack() { _irq.ack(); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__VIRTIO__PCI_DEVICE_H_ */
|
||||
|
@ -14,9 +14,8 @@
|
||||
#ifndef _INCLUDE__VIRTIO__QUEUE_H_
|
||||
#define _INCLUDE__VIRTIO__QUEUE_H_
|
||||
|
||||
#include <base/attached_dataspace.h>
|
||||
#include <platform_session/dma_buffer.h>
|
||||
#include <base/stdint.h>
|
||||
#include <dataspace/client.h>
|
||||
#include <util/misc_math.h>
|
||||
|
||||
namespace Virtio
|
||||
@ -138,7 +137,7 @@ class Virtio::Queue
|
||||
Buffer_pool(Buffer_pool const &) = delete;
|
||||
Buffer_pool &operator = (Buffer_pool const &) = delete;
|
||||
|
||||
Attached_dataspace _ds;
|
||||
Platform::Dma_buffer _ds;
|
||||
uint16_t const _buffer_count;
|
||||
uint16_t const _buffer_size;
|
||||
addr_t const _phys_base;
|
||||
@ -156,16 +155,14 @@ class Virtio::Queue
|
||||
};
|
||||
|
||||
Buffer_pool(Platform::Connection & plat,
|
||||
Region_map & rm,
|
||||
uint16_t const buffer_count,
|
||||
uint16_t const buffer_size)
|
||||
:
|
||||
_ds(rm, plat.alloc_dma_buffer(buffer_count *
|
||||
align_natural(buffer_size),
|
||||
CACHED)),
|
||||
_ds(plat, buffer_count * align_natural(buffer_size),
|
||||
CACHED),
|
||||
_buffer_count(buffer_count),
|
||||
_buffer_size(buffer_size),
|
||||
_phys_base(_dma_addr(plat, _ds.cap())) {}
|
||||
_phys_base(_ds.dma_addr()) {}
|
||||
|
||||
const Buffer get(uint16_t descriptor_idx) const
|
||||
{
|
||||
@ -211,7 +208,7 @@ class Virtio::Queue
|
||||
|
||||
|
||||
uint16_t const _queue_size;
|
||||
Attached_dataspace _ds;
|
||||
Platform::Dma_buffer _ds;
|
||||
Buffer_pool _buffers;
|
||||
Avail volatile * const _avail;
|
||||
Used volatile * const _used;
|
||||
@ -565,18 +562,16 @@ class Virtio::Queue
|
||||
print(output, _queue_size);
|
||||
}
|
||||
|
||||
Queue(Region_map & rm,
|
||||
Platform::Connection & plat,
|
||||
Queue(Platform::Connection & plat,
|
||||
uint16_t queue_size,
|
||||
uint16_t buffer_size)
|
||||
: _queue_size(queue_size),
|
||||
_ds(rm, plat.alloc_dma_buffer(_ds_size(queue_size), UNCACHED)),
|
||||
_buffers(plat, rm, queue_size, _check_buffer_size(buffer_size)),
|
||||
_ds(plat, _ds_size(queue_size), UNCACHED),
|
||||
_buffers(plat, queue_size, _check_buffer_size(buffer_size)),
|
||||
_avail(_init_avail(_ds.local_addr<uint8_t>(), queue_size)),
|
||||
_used(_init_used(_ds.local_addr<uint8_t>(), queue_size)),
|
||||
_descriptors(_ds.local_addr<uint8_t>(), queue_size),
|
||||
_description(_init_description(queue_size,
|
||||
_dma_addr(plat, _ds.cap())))
|
||||
_description(_init_description(queue_size, _ds.dma_addr()))
|
||||
{
|
||||
_fill_descriptor_table();
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ class Virtio_fb::Driver
|
||||
Env &_env;
|
||||
Platform::Connection &_platform;
|
||||
Virtio::Device &_device;
|
||||
Control_queue _ctrl_vq { _env.rm(), _platform, 4, 512 };
|
||||
Control_queue _ctrl_vq { _platform, 4, 512 };
|
||||
uint32_t const _num_scanouts;
|
||||
Signal_handler<Driver> _irq_handler { _env.ep(), *this, &Driver::_handle_irq };
|
||||
|
||||
|
@ -137,10 +137,8 @@ class Virtio_input::Driver
|
||||
Input::Absolute_motion _abs_motion { -1, -1 };
|
||||
Abs_config _abs_config { { 0, 0 }, { 0, 0 }, 0, 0 };
|
||||
Signal_handler<Driver> _irq_handler {_env.ep(), *this, &Driver::_handle_irq};
|
||||
Events_virtqueue _events_vq { _env.rm(), _plat,
|
||||
QUEUE_SIZE, QUEUE_ELM_SIZE };
|
||||
Status_virtqueue _status_vq { _env.rm(), _plat,
|
||||
QUEUE_SIZE, QUEUE_ELM_SIZE };
|
||||
Events_virtqueue _events_vq { _plat, QUEUE_SIZE, QUEUE_ELM_SIZE };
|
||||
Status_virtqueue _status_vq { _plat, QUEUE_SIZE, QUEUE_ELM_SIZE };
|
||||
|
||||
|
||||
void _handle_event(::Event::Session_client::Batch &batch, const Event &evt)
|
||||
|
@ -288,18 +288,17 @@ class Virtio_nic::Device : Noncopyable
|
||||
|
||||
public:
|
||||
|
||||
Device(Genode::Env &env,
|
||||
Virtio::Device &device,
|
||||
Device(Virtio::Device &device,
|
||||
Platform::Connection &plat,
|
||||
Genode::Xml_node const &xml)
|
||||
try :
|
||||
_verbose { xml.attribute_value("verbose", false) },
|
||||
_device { device },
|
||||
_hw_features { _init_hw_features(xml) },
|
||||
_rx_vq { env.rm(), plat,
|
||||
_rx_vq { plat,
|
||||
_vq_size(RX_VQ, xml, "rx_queue_size"),
|
||||
_buf_size(RX_VQ, xml, "rx_buffer_size") },
|
||||
_tx_vq { env.rm(), plat,
|
||||
_tx_vq { plat,
|
||||
_vq_size(TX_VQ, xml, "tx_queue_size"),
|
||||
_buf_size(TX_VQ, xml, "tx_buffer_size") }
|
||||
{ }
|
||||
@ -496,7 +495,7 @@ class Virtio_nic::Uplink_client : public Virtio_nic::Device,
|
||||
Platform::Connection &plat,
|
||||
Genode::Xml_node const &xml)
|
||||
:
|
||||
Device { env, device, plat, xml },
|
||||
Device { device, plat, xml },
|
||||
Uplink_client_base { env, alloc, read_mac_address() },
|
||||
_irq_handler { env.ep(), *this, &Uplink_client::_handle_irq }
|
||||
{
|
||||
|
@ -14,7 +14,7 @@
|
||||
/* Genode includes */
|
||||
#include <base/component.h>
|
||||
#include <base/heap.h>
|
||||
#include <legacy/x86/platform_session/connection.h>
|
||||
#include <platform_session/connection.h>
|
||||
#include <virtio/pci_device.h>
|
||||
|
||||
/* local includes */
|
||||
@ -30,29 +30,15 @@ struct Virtio_pci_nic::Main
|
||||
struct Device_not_found : Genode::Exception { };
|
||||
|
||||
Genode::Env & env;
|
||||
Genode::Heap heap { env.ram(), env.rm() };
|
||||
Platform::Connection pci { env };
|
||||
Platform::Device_client platform_device;
|
||||
Virtio::Device virtio_device { env, platform_device };
|
||||
Attached_rom_dataspace config_rom { env, "config" };
|
||||
Genode::Heap heap { env.ram(), env.rm() };
|
||||
Platform::Connection pci { env };
|
||||
Virtio::Device virtio_device { env, pci };
|
||||
Attached_rom_dataspace config_rom { env, "config" };
|
||||
Virtio_nic::Uplink_client uplink_client { env, heap, virtio_device,
|
||||
pci, config_rom.xml() };
|
||||
|
||||
Platform::Device_capability find_platform_device()
|
||||
{
|
||||
Platform::Device_capability device_cap;
|
||||
pci.with_upgrade([&] () { device_cap = pci.first_device(); });
|
||||
|
||||
if (!device_cap.valid()) throw Device_not_found();
|
||||
|
||||
return device_cap;
|
||||
}
|
||||
|
||||
Main(Env &env)
|
||||
: env(env), platform_device(find_platform_device())
|
||||
{
|
||||
log("--- VirtIO PCI driver started ---");
|
||||
}
|
||||
Main(Env &env) : env(env) {
|
||||
log("--- VirtIO PCI driver started ---"); }
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user