mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-09 04:15:52 +00:00
parent
1895931918
commit
df71cecc66
@ -184,6 +184,222 @@ void Driver::Device::generate(Xml_generator & xml, bool info) const
|
||||
}
|
||||
|
||||
|
||||
void Driver::Device::update(Allocator &alloc, Xml_node const &node)
|
||||
{
|
||||
using Bar = Device::Pci_bar;
|
||||
|
||||
update_list_model_from_xml(_irq_list, node,
|
||||
|
||||
/* create */
|
||||
[&] (Xml_node const &node) -> Irq &
|
||||
{
|
||||
unsigned number = node.attribute_value<unsigned>("number", 0);
|
||||
|
||||
Irq &irq = *(new (alloc) Irq(number));
|
||||
|
||||
String<16> polarity = node.attribute_value("polarity", String<16>());
|
||||
String<16> mode = node.attribute_value("mode", String<16>());
|
||||
String<16> type = node.attribute_value("type", String<16>());
|
||||
if (polarity.valid())
|
||||
irq.polarity = (polarity == "high") ? Irq_session::POLARITY_HIGH
|
||||
: Irq_session::POLARITY_LOW;
|
||||
if (mode.valid())
|
||||
irq.mode = (mode == "edge") ? Irq_session::TRIGGER_EDGE
|
||||
: Irq_session::TRIGGER_LEVEL;
|
||||
if (type.valid())
|
||||
irq.type = (type == "msi-x") ? Irq::MSIX : Irq::MSI;
|
||||
|
||||
return irq;
|
||||
},
|
||||
|
||||
/* destroy */
|
||||
[&] (Irq &irq) { destroy(alloc, &irq); },
|
||||
|
||||
/* update */
|
||||
[&] (Irq &, Xml_node const &) { }
|
||||
);
|
||||
|
||||
update_list_model_from_xml(_io_mem_list, node,
|
||||
|
||||
/* create */
|
||||
[&] (Xml_node const &node) -> Io_mem &
|
||||
{
|
||||
using Range = Io_mem::Range;
|
||||
|
||||
Bar bar { node.attribute_value<uint8_t>("pci_bar", Bar::INVALID) };
|
||||
Range range { node.attribute_value<addr_t>("address", 0),
|
||||
node.attribute_value<size_t>("size", 0) };
|
||||
bool pf { node.attribute_value("prefetchable", false) };
|
||||
|
||||
return *new (alloc) Io_mem(bar, range, pf);
|
||||
},
|
||||
|
||||
/* destroy */
|
||||
[&] (Io_mem &io_mem) { destroy(alloc, &io_mem); },
|
||||
|
||||
/* update */
|
||||
[&] (Io_mem &, Xml_node const &) { }
|
||||
);
|
||||
|
||||
update_list_model_from_xml(_io_port_range_list, node,
|
||||
|
||||
/* create */
|
||||
[&] (Xml_node const &node) -> Io_port_range &
|
||||
{
|
||||
using Range = Io_port_range::Range;
|
||||
|
||||
Bar bar { node.attribute_value<uint8_t>("pci_bar", Bar::INVALID) };
|
||||
Range range { node.attribute_value<uint16_t>("address", 0),
|
||||
node.attribute_value<uint16_t>("size", 0) };
|
||||
|
||||
return *new (alloc) Io_port_range(bar, range);
|
||||
},
|
||||
|
||||
/* destroy */
|
||||
[&] (Io_port_range &ipr) { destroy(alloc, &ipr); },
|
||||
|
||||
/* update */
|
||||
[&] (Io_port_range &, Xml_node const &) { }
|
||||
);
|
||||
|
||||
update_list_model_from_xml(_property_list, node,
|
||||
|
||||
/* create */
|
||||
[&] (Xml_node const &node) -> Property &
|
||||
{
|
||||
return *new (alloc)
|
||||
Property(node.attribute_value("name", Property::Name()),
|
||||
node.attribute_value("value", Property::Value()));
|
||||
},
|
||||
|
||||
/* destroy */
|
||||
[&] (Property &property) { destroy(alloc, &property); },
|
||||
|
||||
/* update */
|
||||
[&] (Property &, Xml_node const &) { }
|
||||
);
|
||||
|
||||
update_list_model_from_xml(_clock_list, node,
|
||||
|
||||
/* create */
|
||||
[&] (Xml_node const &node) -> Clock &
|
||||
{
|
||||
return *new (alloc)
|
||||
Clock(node.attribute_value("name", Clock::Name()),
|
||||
node.attribute_value("parent", Clock::Name()),
|
||||
node.attribute_value("driver_name", Clock::Name()),
|
||||
node.attribute_value("rate", 0UL));
|
||||
},
|
||||
|
||||
/* destroy */
|
||||
[&] (Clock &clock) { destroy(alloc, &clock); },
|
||||
|
||||
/* update */
|
||||
[&] (Clock &, Xml_node const &) { }
|
||||
);
|
||||
|
||||
update_list_model_from_xml(_power_domain_list, node,
|
||||
|
||||
/* create */
|
||||
[&] (Xml_node const &node) -> Power_domain &
|
||||
{
|
||||
return *new (alloc)
|
||||
Power_domain(node.attribute_value("name", Power_domain::Name()));
|
||||
},
|
||||
|
||||
/* destroy */
|
||||
[&] (Power_domain &power) { destroy(alloc, &power); },
|
||||
|
||||
/* update */
|
||||
[&] (Power_domain &, Xml_node const &) { }
|
||||
);
|
||||
|
||||
update_list_model_from_xml(_reset_domain_list, node,
|
||||
|
||||
/* create */
|
||||
[&] (Xml_node const &node) -> Reset_domain &
|
||||
{
|
||||
return *new (alloc)
|
||||
Reset_domain(node.attribute_value("name", Reset_domain::Name()));
|
||||
},
|
||||
|
||||
/* destroy */
|
||||
[&] (Reset_domain &reset) { destroy(alloc, &reset); },
|
||||
|
||||
/* update */
|
||||
[&] (Reset_domain &, Xml_node const &) { }
|
||||
);
|
||||
|
||||
update_list_model_from_xml(_pci_config_list, node,
|
||||
|
||||
/* create */
|
||||
[&] (Xml_node const &node) -> Pci_config &
|
||||
{
|
||||
using namespace Pci;
|
||||
|
||||
addr_t addr = node.attribute_value("address", ~0UL);
|
||||
bus_t bus_num = node.attribute_value<bus_t>("bus", 0);
|
||||
dev_t dev_num = node.attribute_value<dev_t>("device", 0);
|
||||
func_t func_num = node.attribute_value<func_t>("function", 0);
|
||||
vendor_t vendor_id = node.attribute_value<vendor_t>("vendor_id",
|
||||
0xffff);
|
||||
device_t device_id = node.attribute_value<device_t>("device_id",
|
||||
0xffff);
|
||||
class_t class_code = node.attribute_value<class_t>("class", 0xff);
|
||||
rev_t rev = node.attribute_value<rev_t>("revision", 0xff);
|
||||
vendor_t sub_v_id = node.attribute_value<vendor_t>("sub_vendor_id",
|
||||
0xffff);
|
||||
device_t sub_d_id = node.attribute_value<device_t>("sub_device_id",
|
||||
0xffff);
|
||||
bool bridge = node.attribute_value("bridge", false);
|
||||
|
||||
return *(new (alloc) Pci_config(addr, bus_num, dev_num, func_num,
|
||||
vendor_id, device_id, class_code,
|
||||
rev, sub_v_id, sub_d_id, bridge));
|
||||
},
|
||||
|
||||
/* destroy */
|
||||
[&] (Pci_config &pci) { destroy(alloc, &pci); },
|
||||
|
||||
/* update */
|
||||
[&] (Pci_config &, Xml_node const &) { }
|
||||
);
|
||||
|
||||
update_list_model_from_xml(_reserved_mem_list, node,
|
||||
|
||||
/* create */
|
||||
[&] (Xml_node const &node) -> Reserved_memory &
|
||||
{
|
||||
addr_t addr = node.attribute_value("address", 0UL);
|
||||
size_t size = node.attribute_value("size", 0UL);
|
||||
return *(new (alloc) Reserved_memory({addr, size}));
|
||||
},
|
||||
|
||||
/* destroy */
|
||||
[&] (Reserved_memory &reserved) { destroy(alloc, &reserved); },
|
||||
|
||||
/* update */
|
||||
[&] (Reserved_memory &, Xml_node const &) { }
|
||||
);
|
||||
|
||||
update_list_model_from_xml(_io_mmu_list, node,
|
||||
|
||||
/* create */
|
||||
[&] (Xml_node const &node) -> Io_mmu &
|
||||
{
|
||||
return *new (alloc)
|
||||
Io_mmu(node.attribute_value("name", Io_mmu::Name()));
|
||||
},
|
||||
|
||||
/* destroy */
|
||||
[&] (Io_mmu &io_mmu) { destroy(alloc, &io_mmu); },
|
||||
|
||||
/* update */
|
||||
[&] (Io_mmu &, Xml_node const &) { }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Driver::Device::Device(Env & env, Device_model & model, Name name, Type type,
|
||||
bool leave_operational)
|
||||
:
|
||||
@ -213,7 +429,31 @@ void Driver::Device_model::generate(Xml_generator & xml) const
|
||||
|
||||
void Driver::Device_model::update(Xml_node const & node)
|
||||
{
|
||||
_model.update_from_xml(*this, node);
|
||||
update_list_model_from_xml(_model, node,
|
||||
|
||||
/* create */
|
||||
[&] (Xml_node const &node) -> Device &
|
||||
{
|
||||
Device::Name name = node.attribute_value("name", Device::Name());
|
||||
Device::Type type = node.attribute_value("type", Device::Type());
|
||||
bool leave_operational = node.attribute_value("leave_operational", false);
|
||||
return *(new (_heap) Device(_env, *this, name, type, leave_operational));
|
||||
},
|
||||
|
||||
/* destroy */
|
||||
[&] (Device &device)
|
||||
{
|
||||
device.update(_heap, Xml_node("<empty/>"));
|
||||
device.release(_owner);
|
||||
destroy(_heap, &device);
|
||||
},
|
||||
|
||||
/* update */
|
||||
[&] (Device &device, Xml_node const &node)
|
||||
{
|
||||
device.update(_heap, node);
|
||||
}
|
||||
);
|
||||
|
||||
/*
|
||||
* Detect all shared interrupts
|
||||
|
@ -38,16 +38,6 @@ namespace Driver {
|
||||
struct Device_reporter;
|
||||
struct Device_model;
|
||||
struct Device_owner;
|
||||
struct Irq_update_policy;
|
||||
struct Io_mem_update_policy;
|
||||
struct Io_port_update_policy;
|
||||
struct Property_update_policy;
|
||||
struct Clock_update_policy;
|
||||
struct Reset_domain_update_policy;
|
||||
struct Power_domain_update_policy;
|
||||
struct Pci_config_update_policy;
|
||||
struct Reserved_memory_update_policy;
|
||||
struct Io_mmu_update_policy;
|
||||
}
|
||||
|
||||
|
||||
@ -91,6 +81,18 @@ class Driver::Device : private List_model<Device>::Element
|
||||
|
||||
Io_mem(Pci_bar bar, Range range, bool pf)
|
||||
: bar(bar), range(range), prefetchable(pf) {}
|
||||
|
||||
bool matches(Xml_node const &node) const
|
||||
{
|
||||
Range r { node.attribute_value<Genode::addr_t>("address", 0),
|
||||
node.attribute_value<Genode::size_t>("size", 0) };
|
||||
return (r.start == range.start) && (r.size == range.size);
|
||||
}
|
||||
|
||||
static bool type_matches(Xml_node const &node)
|
||||
{
|
||||
return node.has_type("io_mem");
|
||||
}
|
||||
};
|
||||
|
||||
struct Irq : List_model<Irq>::Element
|
||||
@ -104,6 +106,16 @@ class Driver::Device : private List_model<Device>::Element
|
||||
bool shared { false };
|
||||
|
||||
Irq(unsigned number) : number(number) {}
|
||||
|
||||
bool matches(Xml_node const &node) const
|
||||
{
|
||||
return (node.attribute_value<unsigned>("number", 0u) == number);
|
||||
}
|
||||
|
||||
static bool type_matches(Xml_node const &node)
|
||||
{
|
||||
return node.has_type("irq");
|
||||
}
|
||||
};
|
||||
|
||||
struct Io_port_range : List_model<Io_port_range>::Element
|
||||
@ -115,6 +127,17 @@ class Driver::Device : private List_model<Device>::Element
|
||||
|
||||
Io_port_range(Pci_bar bar, Range range)
|
||||
: bar(bar), range(range) {}
|
||||
|
||||
bool matches(Xml_node const &node) const
|
||||
{
|
||||
return (node.attribute_value<uint16_t>("address", 0) == range.addr)
|
||||
&& (node.attribute_value<uint16_t>("size", 0) == range.size);
|
||||
}
|
||||
|
||||
static bool type_matches(Xml_node const &node)
|
||||
{
|
||||
return node.has_type("io_port_range");
|
||||
}
|
||||
};
|
||||
|
||||
struct Property : List_model<Property>::Element
|
||||
@ -127,6 +150,17 @@ class Driver::Device : private List_model<Device>::Element
|
||||
|
||||
Property(Name name, Value value)
|
||||
: name(name), value(value) {}
|
||||
|
||||
bool matches(Xml_node const &node) const
|
||||
{
|
||||
return (node.attribute_value("name", Name()) == name)
|
||||
&& (node.attribute_value("value", Value()) == value);
|
||||
}
|
||||
|
||||
static bool type_matches(Xml_node const &node)
|
||||
{
|
||||
return node.has_type("property");
|
||||
}
|
||||
};
|
||||
|
||||
struct Clock : List_model<Clock>::Element
|
||||
@ -144,6 +178,17 @@ class Driver::Device : private List_model<Device>::Element
|
||||
unsigned long rate)
|
||||
: name(name), parent(parent),
|
||||
driver_name(driver_name), rate(rate) {}
|
||||
|
||||
bool matches(Xml_node const &node) const
|
||||
{
|
||||
return (node.attribute_value("name", Name()) == name)
|
||||
&& (node.attribute_value("driver_name", Name()) == driver_name);
|
||||
}
|
||||
|
||||
static bool type_matches(Xml_node const &node)
|
||||
{
|
||||
return node.has_type("clock");
|
||||
}
|
||||
};
|
||||
|
||||
struct Power_domain : List_model<Power_domain>::Element
|
||||
@ -153,6 +198,16 @@ class Driver::Device : private List_model<Device>::Element
|
||||
Name name;
|
||||
|
||||
Power_domain(Name name) : name(name) {}
|
||||
|
||||
bool matches(Xml_node const &node) const
|
||||
{
|
||||
return (node.attribute_value("name", Name()) == name);
|
||||
}
|
||||
|
||||
static bool type_matches(Xml_node const &node)
|
||||
{
|
||||
return node.has_type("power-domain");
|
||||
}
|
||||
};
|
||||
|
||||
struct Reset_domain : List_model<Reset_domain>::Element
|
||||
@ -162,6 +217,16 @@ class Driver::Device : private List_model<Device>::Element
|
||||
Name name;
|
||||
|
||||
Reset_domain(Name name) : name(name) {}
|
||||
|
||||
bool matches(Xml_node const &node) const
|
||||
{
|
||||
return (node.attribute_value("name", Name()) == name);
|
||||
}
|
||||
|
||||
static bool type_matches(Xml_node const &node)
|
||||
{
|
||||
return node.has_type("reset-domain");
|
||||
}
|
||||
};
|
||||
|
||||
struct Pci_config : List_model<Pci_config>::Element
|
||||
@ -200,7 +265,18 @@ class Driver::Device : private List_model<Device>::Element
|
||||
revision(revision),
|
||||
sub_vendor_id(sub_vendor_id),
|
||||
sub_device_id(sub_device_id),
|
||||
bridge(bridge) {}
|
||||
bridge(bridge)
|
||||
{ }
|
||||
|
||||
bool matches(Xml_node const &node) const
|
||||
{
|
||||
return (node.attribute_value("address", ~0UL) == addr);
|
||||
}
|
||||
|
||||
static bool type_matches(Xml_node const &node)
|
||||
{
|
||||
return node.has_type("pci-config");
|
||||
}
|
||||
};
|
||||
|
||||
struct Reserved_memory : List_model<Reserved_memory>::Element
|
||||
@ -210,6 +286,17 @@ class Driver::Device : private List_model<Device>::Element
|
||||
Range range;
|
||||
|
||||
Reserved_memory(Range range) : range(range) {}
|
||||
|
||||
bool matches(Xml_node const &node) const
|
||||
{
|
||||
return (node.attribute_value("address", 0UL) == range.start)
|
||||
&& (node.attribute_value("size", 0UL) == range.size);
|
||||
}
|
||||
|
||||
static bool type_matches(Xml_node const &node)
|
||||
{
|
||||
return node.has_type("reserved_memory");
|
||||
}
|
||||
};
|
||||
|
||||
struct Io_mmu : List_model<Io_mmu>::Element
|
||||
@ -219,6 +306,16 @@ class Driver::Device : private List_model<Device>::Element
|
||||
Name name;
|
||||
|
||||
Io_mmu(Name name) : name(name) {}
|
||||
|
||||
bool matches(Xml_node const &node) const
|
||||
{
|
||||
return (node.attribute_value("name", Name()) == name);
|
||||
}
|
||||
|
||||
static bool type_matches(Xml_node const &node)
|
||||
{
|
||||
return node.has_type("io_mmu");
|
||||
}
|
||||
};
|
||||
|
||||
Device(Env & env, Device_model & model, Name name, Type type,
|
||||
@ -294,6 +391,25 @@ class Driver::Device : private List_model<Device>::Element
|
||||
|
||||
void generate(Xml_generator &, bool) const;
|
||||
|
||||
void update(Allocator &, Xml_node const &);
|
||||
|
||||
/**
|
||||
* List_model::Element
|
||||
*/
|
||||
bool matches(Xml_node const &node) const
|
||||
{
|
||||
return name() == node.attribute_value("name", Device::Name()) &&
|
||||
type() == node.attribute_value("type", Device::Type());
|
||||
}
|
||||
|
||||
/**
|
||||
* List_model::Element
|
||||
*/
|
||||
static bool type_matches(Xml_node const &node)
|
||||
{
|
||||
return node.has_type("device");
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
friend class Driver::Device_model;
|
||||
@ -333,8 +449,7 @@ struct Driver::Device_reporter
|
||||
};
|
||||
|
||||
|
||||
class Driver::Device_model :
|
||||
public List_model<Device>::Update_policy
|
||||
class Driver::Device_model
|
||||
{
|
||||
private:
|
||||
|
||||
@ -360,8 +475,7 @@ class Driver::Device_model :
|
||||
Device_owner & owner)
|
||||
: _env(env), _heap(heap), _reporter(reporter), _owner(owner) { }
|
||||
|
||||
~Device_model() {
|
||||
_model.destroy_all_elements(*this); }
|
||||
~Device_model() { update(Xml_node("<empty/>")); }
|
||||
|
||||
template <typename FN>
|
||||
void for_each(FN const & fn) { _model.for_each(fn); }
|
||||
@ -376,388 +490,9 @@ class Driver::Device_model :
|
||||
if (sirq.number() == number) fn(sirq); });
|
||||
}
|
||||
|
||||
|
||||
/***********************
|
||||
** Update_policy API **
|
||||
***********************/
|
||||
|
||||
void destroy_element(Device & device);
|
||||
Device & create_element(Xml_node node);
|
||||
void update_element(Device & device, Xml_node node);
|
||||
static bool element_matches_xml_node(Device const & dev,
|
||||
Genode::Xml_node n)
|
||||
{
|
||||
return dev.name() == n.attribute_value("name", Device::Name()) &&
|
||||
dev.type() == n.attribute_value("type", Device::Type());
|
||||
}
|
||||
|
||||
static bool node_is_element(Genode::Xml_node node) {
|
||||
return node.has_type("device"); }
|
||||
|
||||
Clocks & clocks() { return _clocks; };
|
||||
Resets & resets() { return _resets; };
|
||||
Powers & powers() { return _powers; };
|
||||
};
|
||||
|
||||
|
||||
struct Driver::Irq_update_policy : Genode::List_model<Device::Irq>::Update_policy
|
||||
{
|
||||
Genode::Allocator & alloc;
|
||||
|
||||
Irq_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
|
||||
|
||||
void destroy_element(Element & irq) {
|
||||
Genode::destroy(alloc, &irq); }
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
unsigned number = node.attribute_value<unsigned>("number", 0);
|
||||
Element & elem = *(new (alloc) Element(number));
|
||||
|
||||
String<16> polarity = node.attribute_value("polarity", String<16>());
|
||||
String<16> mode = node.attribute_value("mode", String<16>());
|
||||
String<16> type = node.attribute_value("type", String<16>());
|
||||
if (polarity.valid())
|
||||
elem.polarity = (polarity == "high") ? Irq_session::POLARITY_HIGH
|
||||
: Irq_session::POLARITY_LOW;
|
||||
if (mode.valid())
|
||||
elem.mode = (mode == "edge") ? Irq_session::TRIGGER_EDGE
|
||||
: Irq_session::TRIGGER_LEVEL;
|
||||
if (type.valid())
|
||||
elem.type = (type == "msi-x") ? Element::MSIX : Element::MSI;
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
||||
static bool element_matches_xml_node(Element const & irq, Genode::Xml_node node)
|
||||
{
|
||||
unsigned number = node.attribute_value<unsigned>("number", 0);
|
||||
return number == irq.number;
|
||||
}
|
||||
|
||||
static bool node_is_element(Genode::Xml_node node)
|
||||
{
|
||||
return node.has_type("irq");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Driver::Io_mem_update_policy : Genode::List_model<Device::Io_mem>::Update_policy
|
||||
{
|
||||
using Range = Device::Io_mem::Range;
|
||||
using Bar = Device::Pci_bar;
|
||||
|
||||
Genode::Allocator & alloc;
|
||||
|
||||
Io_mem_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
|
||||
|
||||
void destroy_element(Element & iomem) {
|
||||
Genode::destroy(alloc, &iomem); }
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
Bar bar { node.attribute_value<uint8_t>("pci_bar", Bar::INVALID) };
|
||||
Range range { node.attribute_value<Genode::addr_t>("address", 0),
|
||||
node.attribute_value<Genode::size_t>("size", 0) };
|
||||
bool pf { node.attribute_value("prefetchable", false) };
|
||||
return *(new (alloc) Element(bar, range, pf));
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
||||
static bool element_matches_xml_node(Element const & iomem, Genode::Xml_node node)
|
||||
{
|
||||
Range range { node.attribute_value<Genode::addr_t>("address", 0),
|
||||
node.attribute_value<Genode::size_t>("size", 0) };
|
||||
return (range.start == iomem.range.start) && (range.size == iomem.range.size);
|
||||
}
|
||||
|
||||
static bool node_is_element(Genode::Xml_node node)
|
||||
{
|
||||
return node.has_type("io_mem");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Driver::Io_port_update_policy
|
||||
: Genode::List_model<Device::Io_port_range>::Update_policy
|
||||
{
|
||||
using Range = Device::Io_port_range::Range;
|
||||
using Bar = Device::Pci_bar;
|
||||
|
||||
Genode::Allocator & alloc;
|
||||
|
||||
Io_port_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
|
||||
|
||||
void destroy_element(Element & ipr) {
|
||||
Genode::destroy(alloc, &ipr); }
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
Bar bar { node.attribute_value<uint8_t>("pci_bar", Bar::INVALID) };
|
||||
Range range { node.attribute_value<uint16_t>("address", 0),
|
||||
node.attribute_value<uint16_t>("size", 0) };
|
||||
return *(new (alloc) Element(bar, range));
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
||||
static bool element_matches_xml_node(Element const & ipr, Genode::Xml_node node)
|
||||
{
|
||||
Range range { node.attribute_value<uint16_t>("address", 0),
|
||||
node.attribute_value<uint16_t>("size", 0) };
|
||||
return range.addr == ipr.range.addr && range.size == ipr.range.size;
|
||||
}
|
||||
|
||||
static bool node_is_element(Genode::Xml_node node)
|
||||
{
|
||||
return node.has_type("io_port_range");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Driver::Property_update_policy : Genode::List_model<Device::Property>::Update_policy
|
||||
{
|
||||
Genode::Allocator & alloc;
|
||||
|
||||
Property_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
|
||||
|
||||
void destroy_element(Element & p) {
|
||||
Genode::destroy(alloc, &p); }
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
return *(new (alloc)
|
||||
Element(node.attribute_value("name", Element::Name()),
|
||||
node.attribute_value("value", Element::Value())));
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
||||
static bool element_matches_xml_node(Element const & prop, Genode::Xml_node node)
|
||||
{
|
||||
Element::Name n = node.attribute_value("name", Element::Name());
|
||||
Element::Value v = node.attribute_value("value", Element::Value());
|
||||
return (n == prop.name) && (v == prop.value);
|
||||
}
|
||||
|
||||
static bool node_is_element(Genode::Xml_node node) {
|
||||
return node.has_type("property"); }
|
||||
};
|
||||
|
||||
|
||||
struct Driver::Clock_update_policy
|
||||
: Genode::List_model<Device::Clock>::Update_policy
|
||||
{
|
||||
Genode::Allocator & alloc;
|
||||
|
||||
Clock_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
|
||||
|
||||
void destroy_element(Element & clock) {
|
||||
Genode::destroy(alloc, &clock); }
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
Element::Name name = node.attribute_value("name", Element::Name());
|
||||
Element::Name parent = node.attribute_value("parent", Element::Name());
|
||||
Element::Name driver = node.attribute_value("driver_name", Element::Name());
|
||||
unsigned long rate = node.attribute_value<unsigned long >("rate", 0);
|
||||
return *(new (alloc) Element(name, parent, driver, rate));
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
||||
static bool element_matches_xml_node(Element const & clock, Genode::Xml_node node)
|
||||
{
|
||||
Element::Name name = node.attribute_value("name", Element::Name());
|
||||
Element::Name driver_name = node.attribute_value("driver_name", Element::Name());
|
||||
return name == clock.name && driver_name == clock.driver_name;
|
||||
}
|
||||
|
||||
static bool node_is_element(Genode::Xml_node node)
|
||||
{
|
||||
return node.has_type("clock");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Driver::Power_domain_update_policy
|
||||
: Genode::List_model<Device::Power_domain>::Update_policy
|
||||
{
|
||||
Genode::Allocator & alloc;
|
||||
|
||||
Power_domain_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
|
||||
|
||||
void destroy_element(Element & pd) {
|
||||
Genode::destroy(alloc, &pd); }
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
Element::Name name = node.attribute_value("name", Element::Name());
|
||||
return *(new (alloc) Element(name));
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
||||
static bool element_matches_xml_node(Element const & pd, Genode::Xml_node node)
|
||||
{
|
||||
Element::Name name = node.attribute_value("name", Element::Name());
|
||||
return name == pd.name;
|
||||
}
|
||||
|
||||
static bool node_is_element(Genode::Xml_node node)
|
||||
{
|
||||
return node.has_type("power-domain");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Driver::Reset_domain_update_policy
|
||||
: Genode::List_model<Device::Reset_domain>::Update_policy
|
||||
{
|
||||
Genode::Allocator & alloc;
|
||||
|
||||
Reset_domain_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
|
||||
|
||||
void destroy_element(Element & pd) {
|
||||
Genode::destroy(alloc, &pd); }
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
Element::Name name = node.attribute_value("name", Element::Name());
|
||||
return *(new (alloc) Element(name));
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
||||
static bool element_matches_xml_node(Element const & pd, Genode::Xml_node node)
|
||||
{
|
||||
Element::Name name = node.attribute_value("name", Element::Name());
|
||||
return name == pd.name;
|
||||
}
|
||||
|
||||
static bool node_is_element(Genode::Xml_node node)
|
||||
{
|
||||
return node.has_type("reset-domain");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Driver::Pci_config_update_policy
|
||||
: Genode::List_model<Device::Pci_config>::Update_policy
|
||||
{
|
||||
Genode::Allocator & alloc;
|
||||
|
||||
Pci_config_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
|
||||
|
||||
void destroy_element(Element & pd) {
|
||||
Genode::destroy(alloc, &pd); }
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
using namespace Pci;
|
||||
|
||||
addr_t addr = node.attribute_value("address", ~0UL);
|
||||
bus_t bus_num = node.attribute_value<bus_t>("bus", 0);
|
||||
dev_t dev_num = node.attribute_value<dev_t>("device", 0);
|
||||
func_t func_num = node.attribute_value<func_t>("function", 0);
|
||||
vendor_t vendor_id = node.attribute_value<vendor_t>("vendor_id",
|
||||
0xffff);
|
||||
device_t device_id = node.attribute_value<device_t>("device_id",
|
||||
0xffff);
|
||||
class_t class_code = node.attribute_value<class_t>("class", 0xff);
|
||||
rev_t rev = node.attribute_value<rev_t>("revision", 0xff);
|
||||
vendor_t sub_v_id = node.attribute_value<vendor_t>("sub_vendor_id",
|
||||
0xffff);
|
||||
device_t sub_d_id = node.attribute_value<device_t>("sub_device_id",
|
||||
0xffff);
|
||||
bool bridge = node.attribute_value("bridge", false);
|
||||
|
||||
return *(new (alloc) Element(addr, bus_num, dev_num, func_num,
|
||||
vendor_id, device_id, class_code,
|
||||
rev, sub_v_id, sub_d_id, bridge));
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
||||
static bool element_matches_xml_node(Element const & e, Genode::Xml_node node)
|
||||
{
|
||||
addr_t addr = node.attribute_value("address", ~0UL);
|
||||
return addr == e.addr;
|
||||
}
|
||||
|
||||
static bool node_is_element(Genode::Xml_node node)
|
||||
{
|
||||
return node.has_type("pci-config");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Driver::Reserved_memory_update_policy
|
||||
: Genode::List_model<Device::Reserved_memory>::Update_policy
|
||||
{
|
||||
Genode::Allocator & alloc;
|
||||
|
||||
Reserved_memory_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
|
||||
|
||||
void destroy_element(Element & pd) {
|
||||
Genode::destroy(alloc, &pd); }
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
using namespace Pci;
|
||||
|
||||
addr_t addr = node.attribute_value("address", 0UL);
|
||||
size_t size = node.attribute_value("size", 0UL);
|
||||
return *(new (alloc) Element({addr, size}));
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
||||
static bool element_matches_xml_node(Element const & e, Genode::Xml_node node)
|
||||
{
|
||||
addr_t addr = node.attribute_value("address", 0UL);
|
||||
size_t size = node.attribute_value("size", 0UL);
|
||||
return addr == e.range.start && size == e.range.size;
|
||||
}
|
||||
|
||||
static bool node_is_element(Genode::Xml_node node)
|
||||
{
|
||||
return node.has_type("reserved_memory");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Driver::Io_mmu_update_policy
|
||||
: Genode::List_model<Device::Io_mmu>::Update_policy
|
||||
{
|
||||
Genode::Allocator & alloc;
|
||||
|
||||
Io_mmu_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
|
||||
|
||||
void destroy_element(Element & pd) {
|
||||
Genode::destroy(alloc, &pd); }
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
Element::Name name = node.attribute_value("name", Element::Name());
|
||||
return *(new (alloc) Element(name));
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
||||
static bool element_matches_xml_node(Element const & e, Genode::Xml_node node)
|
||||
{
|
||||
Element::Name name = node.attribute_value("name", Element::Name());
|
||||
return name == e.name;
|
||||
}
|
||||
|
||||
static bool node_is_element(Genode::Xml_node node)
|
||||
{
|
||||
return node.has_type("io_mmu");
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _SRC__DRIVERS__PLATFORM__DEVICE_H_ */
|
||||
|
@ -1,137 +0,0 @@
|
||||
/*
|
||||
* \brief Platform driver - Device model policy
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-05-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#include <device.h>
|
||||
|
||||
using Driver::Device_model;
|
||||
using Driver::Device;
|
||||
|
||||
void Device_model::destroy_element(Device & device)
|
||||
{
|
||||
{
|
||||
Irq_update_policy policy(_heap);
|
||||
device._irq_list.destroy_all_elements(policy);
|
||||
}
|
||||
|
||||
{
|
||||
Io_mem_update_policy policy(_heap);
|
||||
device._io_mem_list.destroy_all_elements(policy);
|
||||
}
|
||||
|
||||
{
|
||||
Io_port_update_policy policy(_heap);
|
||||
device._io_port_range_list.destroy_all_elements(policy);
|
||||
}
|
||||
|
||||
{
|
||||
Property_update_policy policy(_heap);
|
||||
device._property_list.destroy_all_elements(policy);
|
||||
}
|
||||
|
||||
{
|
||||
Clock_update_policy policy(_heap);
|
||||
device._clock_list.destroy_all_elements(policy);
|
||||
}
|
||||
|
||||
{
|
||||
Power_domain_update_policy policy(_heap);
|
||||
device._power_domain_list.destroy_all_elements(policy);
|
||||
}
|
||||
|
||||
{
|
||||
Reset_domain_update_policy policy(_heap);
|
||||
device._reset_domain_list.destroy_all_elements(policy);
|
||||
}
|
||||
|
||||
{
|
||||
Pci_config_update_policy policy(_heap);
|
||||
device._pci_config_list.destroy_all_elements(policy);
|
||||
}
|
||||
|
||||
{
|
||||
Reserved_memory_update_policy policy(_heap);
|
||||
device._reserved_mem_list.destroy_all_elements(policy);
|
||||
}
|
||||
|
||||
{
|
||||
Io_mmu_update_policy policy(_heap);
|
||||
device._io_mmu_list.destroy_all_elements(policy);
|
||||
}
|
||||
|
||||
device.release(_owner);
|
||||
Genode::destroy(_heap, &device);
|
||||
}
|
||||
|
||||
|
||||
Device & Device_model::create_element(Genode::Xml_node node)
|
||||
{
|
||||
Device::Name name = node.attribute_value("name", Device::Name());
|
||||
Device::Type type = node.attribute_value("type", Device::Type());
|
||||
bool leave_operational = node.attribute_value("leave_operational", false);
|
||||
return *(new (_heap) Device(_env, *this, name, type, leave_operational));
|
||||
}
|
||||
|
||||
|
||||
void Device_model::update_element(Device & device,
|
||||
Genode::Xml_node node)
|
||||
{
|
||||
{
|
||||
Irq_update_policy policy(_heap);
|
||||
device._irq_list.update_from_xml(policy, node);
|
||||
}
|
||||
|
||||
{
|
||||
Io_mem_update_policy policy(_heap);
|
||||
device._io_mem_list.update_from_xml(policy, node);
|
||||
}
|
||||
|
||||
{
|
||||
Io_port_update_policy policy(_heap);
|
||||
device._io_port_range_list.update_from_xml(policy, node);
|
||||
}
|
||||
|
||||
{
|
||||
Property_update_policy policy(_heap);
|
||||
device._property_list.update_from_xml(policy, node);
|
||||
}
|
||||
|
||||
{
|
||||
Clock_update_policy policy(_heap);
|
||||
device._clock_list.update_from_xml(policy, node);
|
||||
}
|
||||
|
||||
{
|
||||
Power_domain_update_policy policy(_heap);
|
||||
device._power_domain_list.update_from_xml(policy, node);
|
||||
}
|
||||
|
||||
{
|
||||
Reset_domain_update_policy policy(_heap);
|
||||
device._reset_domain_list.update_from_xml(policy, node);
|
||||
}
|
||||
|
||||
{
|
||||
Pci_config_update_policy policy(_heap);
|
||||
device._pci_config_list.update_from_xml(policy, node);
|
||||
}
|
||||
|
||||
{
|
||||
Reserved_memory_update_policy policy(_heap);
|
||||
device._reserved_mem_list.update_from_xml(policy, node);
|
||||
}
|
||||
|
||||
{
|
||||
Io_mmu_update_policy policy(_heap);
|
||||
device._io_mmu_list.update_from_xml(policy, node);
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
SRC_CC += device.cc
|
||||
SRC_CC += device_component.cc
|
||||
SRC_CC += device_model_policy.cc
|
||||
SRC_CC += device_pd.cc
|
||||
SRC_CC += main.cc
|
||||
SRC_CC += pci.cc
|
||||
|
Loading…
x
Reference in New Issue
Block a user