mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-16 07:27:35 +00:00
pci: export BAR indices, sub-vendor, -product, rev
The pci_decode has to extract the additional fields from the PCI configuration space. The platform driver again has to parse and forward the knowledge too. The PCI BAR indices are exported when info="yes" is set in the policy node for the corresponding session. Fix genodelabs/genode#4577
This commit is contained in:
parent
5bf3e72d37
commit
2cc6c1adef
@ -64,6 +64,7 @@ struct Pci::Config : Genode::Mmio
|
||||
|
||||
struct Class_code_rev_id : Register<0x8, 32>
|
||||
{
|
||||
struct Revision : Bitfield<0, 8> {};
|
||||
struct Class_code : Bitfield<8, 24> {};
|
||||
};
|
||||
|
||||
@ -522,10 +523,10 @@ struct Pci::Config : Genode::Mmio
|
||||
if (!reg0.valid())
|
||||
continue;
|
||||
if (reg0.memory()) {
|
||||
memory(reg0.addr(), reg0.size(), i);
|
||||
if (reg0.bit64()) i++;
|
||||
memory(reg0.addr(), reg0.size());
|
||||
} else
|
||||
io(reg0.addr(), reg0.size());
|
||||
io(reg0.addr(), reg0.size(), i);
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -541,6 +542,9 @@ struct Pci::Config_type0 : Pci::Config
|
||||
Base_address bar3 { base() + BASE_ADDRESS_0 + 0xc };
|
||||
Base_address bar4 { base() + BASE_ADDRESS_0 + 0x10 };
|
||||
Base_address bar5 { base() + BASE_ADDRESS_0 + 0x14 };
|
||||
|
||||
struct Subsystem_vendor : Register<0x2c, 16> { };
|
||||
struct Subsystem_device : Register<0x2e, 16> { };
|
||||
};
|
||||
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define __INCLUDE__PCI__TYPES_H__
|
||||
|
||||
#include <base/stdint.h>
|
||||
#include <util/register.h>
|
||||
#include <util/string.h>
|
||||
|
||||
namespace Pci {
|
||||
@ -41,6 +42,7 @@ namespace Pci {
|
||||
using vendor_t = Genode::uint16_t;
|
||||
using device_t = Genode::uint16_t;
|
||||
using class_t = Genode::uint32_t;
|
||||
using rev_t = Genode::uint8_t;
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,18 +70,12 @@ struct Main
|
||||
void Main::parse_pci_function(Bdf bdf,
|
||||
Config & cfg,
|
||||
addr_t cfg_phys_base,
|
||||
Xml_generator & generator)
|
||||
Xml_generator & gen)
|
||||
{
|
||||
cfg.scan();
|
||||
|
||||
Config::Vendor::access_t vendor = cfg.read<Config::Vendor>();
|
||||
Config::Device::access_t device = cfg.read<Config::Device>();
|
||||
Config::Header_type::Type::access_t type =
|
||||
cfg.read<Config::Header_type::Type>();
|
||||
Config::Class_code_rev_id::Class_code::access_t dclass =
|
||||
cfg.read<Config::Class_code_rev_id::Class_code>();
|
||||
|
||||
if (type) {
|
||||
/* check for bridges */
|
||||
if (cfg.read<Config::Header_type::Type>()) {
|
||||
for_bridge(bdf.bus, [&] (Bridge & parent) {
|
||||
Config_type1 bcfg(cfg.base());
|
||||
new (heap) Bridge(parent.sub_bridges, bdf,
|
||||
@ -94,34 +88,52 @@ void Main::parse_pci_function(Bdf bdf,
|
||||
bool msi_x = cfg.msi_x_cap.constructed();
|
||||
irq_pin_t irq_pin = cfg.read<Config::Irq_pin>();
|
||||
|
||||
generator.node("device", [&]
|
||||
gen.node("device", [&]
|
||||
{
|
||||
generator.attribute("name", Bdf::string(bdf));
|
||||
generator.attribute("type", "pci");
|
||||
auto string = [&] (uint64_t v) { return String<16>(Hex(v)); };
|
||||
|
||||
generator.node("pci-config", [&]
|
||||
gen.attribute("name", Bdf::string(bdf));
|
||||
gen.attribute("type", "pci");
|
||||
|
||||
gen.node("pci-config", [&]
|
||||
{
|
||||
generator.attribute("address", String<16>(Hex(cfg_phys_base)));
|
||||
generator.attribute("bus", String<16>(Hex(bdf.bus)));
|
||||
generator.attribute("device", String<16>(Hex(bdf.dev)));
|
||||
generator.attribute("function", String<16>(Hex(bdf.fn)));
|
||||
generator.attribute("vendor_id", String<16>(Hex(vendor)));
|
||||
generator.attribute("device_id", String<16>(Hex(device)));
|
||||
generator.attribute("class", String<16>(Hex(dclass)));
|
||||
generator.attribute("bridge", cfg.bridge() ? "yes" : "no");
|
||||
using C = Config;
|
||||
using C0 = Config_type0;
|
||||
using Cc = Config::Class_code_rev_id;
|
||||
|
||||
gen.attribute("address", string(cfg_phys_base));
|
||||
gen.attribute("bus", string(bdf.bus));
|
||||
gen.attribute("device", string(bdf.dev));
|
||||
gen.attribute("function", string(bdf.fn));
|
||||
gen.attribute("vendor_id", string(cfg.read<C::Vendor>()));
|
||||
gen.attribute("device_id", string(cfg.read<C::Device>()));
|
||||
gen.attribute("class", string(cfg.read<Cc::Class_code>()));
|
||||
gen.attribute("revision", string(cfg.read<Cc::Revision>()));
|
||||
gen.attribute("bridge", cfg.bridge() ? "yes" : "no");
|
||||
if (!cfg.bridge()) {
|
||||
C0 cfg0(cfg.base());
|
||||
gen.attribute("sub_vendor_id",
|
||||
string(cfg0.read<C0::Subsystem_vendor>()));
|
||||
gen.attribute("sub_device_id",
|
||||
string(cfg0.read<C0::Subsystem_device>()));
|
||||
}
|
||||
});
|
||||
|
||||
cfg.for_each_bar([&] (uint64_t addr, size_t size) {
|
||||
generator.node("io_mem", [&]
|
||||
cfg.for_each_bar([&] (uint64_t addr, size_t size, unsigned bar) {
|
||||
gen.node("io_mem", [&]
|
||||
{
|
||||
generator.attribute("address", String<16>(Hex(addr)));
|
||||
generator.attribute("size", String<16>(Hex(size)));
|
||||
gen.attribute("pci_bar", bar);
|
||||
gen.attribute("address", string(addr));
|
||||
gen.attribute("size", string(size));
|
||||
});
|
||||
}, [&] (uint64_t addr, size_t size) {
|
||||
generator.node("io_port_range", [&]
|
||||
}, [&] (uint64_t addr, size_t size, unsigned bar) {
|
||||
gen.node("io_port_range", [&]
|
||||
{
|
||||
generator.attribute("address", String<16>(Hex(addr)));
|
||||
generator.attribute("size", String<16>(Hex(size)));
|
||||
gen.attribute("pci_bar", bar);
|
||||
gen.attribute("address", string(addr));
|
||||
|
||||
/* on x86 I/O ports can be in range 0-64KB only */
|
||||
gen.attribute("size", string(size & 0xffff));
|
||||
});
|
||||
});
|
||||
|
||||
@ -130,17 +142,17 @@ void Main::parse_pci_function(Bdf bdf,
|
||||
if (!irq_pin)
|
||||
return;
|
||||
|
||||
generator.node("irq", [&]
|
||||
gen.node("irq", [&]
|
||||
{
|
||||
if (msi_capable && msi_x) {
|
||||
generator.attribute("type", "msi-x");
|
||||
generator.attribute("number", msi_number++);
|
||||
gen.attribute("type", "msi-x");
|
||||
gen.attribute("number", msi_number++);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msi_capable && msi) {
|
||||
generator.attribute("type", "msi");
|
||||
generator.attribute("number", msi_number++);
|
||||
gen.attribute("type", "msi");
|
||||
gen.attribute("number", msi_number++);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -152,9 +164,9 @@ void Main::parse_pci_function(Bdf bdf,
|
||||
});
|
||||
|
||||
irq_override_list.for_each([&] (Irq_override & io) {
|
||||
io.generate(generator, irq); });
|
||||
io.generate(gen, irq); });
|
||||
|
||||
generator.attribute("number", irq);
|
||||
gen.attribute("number", irq);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
TARGET = pci_decode
|
||||
LIBS = base
|
||||
SRC_CC = main.cc
|
||||
INC_DIR = $(PRG_DIR)
|
||||
TARGET = pci_decode
|
||||
REQUIRES = x86
|
||||
LIBS = base
|
||||
SRC_CC = main.cc
|
||||
INC_DIR = $(PRG_DIR)
|
||||
|
@ -124,6 +124,8 @@ void Driver::Device::generate(Xml_generator & xml, bool info) const
|
||||
xml.attribute("used", _owner.valid());
|
||||
_io_mem_list.for_each([&] (Io_mem const & io_mem) {
|
||||
xml.node("io_mem", [&] () {
|
||||
if (io_mem.bar.valid())
|
||||
xml.attribute("pci_bar", io_mem.bar.number);
|
||||
if (!info)
|
||||
return;
|
||||
xml.attribute("phys_addr", String<16>(Hex(io_mem.range.start)));
|
||||
@ -137,12 +139,14 @@ void Driver::Device::generate(Xml_generator & xml, bool info) const
|
||||
xml.attribute("number", irq.number);
|
||||
});
|
||||
});
|
||||
_io_port_range_list.for_each([&] (Io_port_range const & io_port_range) {
|
||||
_io_port_range_list.for_each([&] (Io_port_range const & iop) {
|
||||
xml.node("io_port_range", [&] () {
|
||||
if (iop.bar.valid())
|
||||
xml.attribute("pci_bar", iop.bar.number);
|
||||
if (!info)
|
||||
return;
|
||||
xml.attribute("phys_addr", String<16>(Hex(io_port_range.addr)));
|
||||
xml.attribute("size", String<16>(Hex(io_port_range.size)));
|
||||
xml.attribute("phys_addr", String<16>(Hex(iop.range.addr)));
|
||||
xml.attribute("size", String<16>(Hex(iop.range.size)));
|
||||
});
|
||||
});
|
||||
_property_list.for_each([&] (Property const & p) {
|
||||
@ -164,6 +168,9 @@ void Driver::Device::generate(Xml_generator & xml, bool info) const
|
||||
xml.attribute("vendor_id", String<16>(Hex(pci.vendor_id)));
|
||||
xml.attribute("device_id", String<16>(Hex(pci.device_id)));
|
||||
xml.attribute("class", String<16>(Hex(pci.class_code)));
|
||||
xml.attribute("revision", String<16>(Hex(pci.revision)));
|
||||
xml.attribute("sub_vendor_id", String<16>(Hex(pci.sub_vendor_id)));
|
||||
xml.attribute("sub_device_id", String<16>(Hex(pci.sub_device_id)));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -53,7 +53,15 @@ class Driver::Device : private List_model<Device>::Element
|
||||
|
||||
using Name = Genode::String<64>;
|
||||
using Type = Genode::String<64>;
|
||||
using Range = Platform::Device_interface::Range;
|
||||
|
||||
struct Pci_bar
|
||||
{
|
||||
enum { INVALID = 255 };
|
||||
|
||||
unsigned char number { INVALID };
|
||||
|
||||
bool valid() const { return number < INVALID; }
|
||||
};
|
||||
|
||||
struct Owner
|
||||
{
|
||||
@ -71,9 +79,13 @@ class Driver::Device : private List_model<Device>::Element
|
||||
|
||||
struct Io_mem : List_model<Io_mem>::Element
|
||||
{
|
||||
Range range;
|
||||
using Range = Platform::Device_interface::Range;
|
||||
|
||||
Io_mem(Range range) : range(range) {}
|
||||
Pci_bar bar;
|
||||
Range range;
|
||||
|
||||
Io_mem(Pci_bar bar, Range range)
|
||||
: bar(bar), range(range) {}
|
||||
};
|
||||
|
||||
struct Irq : List_model<Irq>::Element
|
||||
@ -90,11 +102,13 @@ class Driver::Device : private List_model<Device>::Element
|
||||
|
||||
struct Io_port_range : List_model<Io_port_range>::Element
|
||||
{
|
||||
uint16_t addr;
|
||||
uint16_t size;
|
||||
struct Range { uint16_t addr; uint16_t size; };
|
||||
|
||||
Io_port_range(uint16_t addr, uint16_t size)
|
||||
: addr(addr), size(size) {}
|
||||
Pci_bar bar;
|
||||
Range range;
|
||||
|
||||
Io_port_range(Pci_bar bar, Range range)
|
||||
: bar(bar), range(range) {}
|
||||
};
|
||||
|
||||
struct Property : List_model<Property>::Element
|
||||
@ -153,6 +167,9 @@ class Driver::Device : private List_model<Device>::Element
|
||||
Pci::vendor_t vendor_id;
|
||||
Pci::device_t device_id;
|
||||
Pci::class_t class_code;
|
||||
Pci::rev_t revision;
|
||||
Pci::vendor_t sub_vendor_id;
|
||||
Pci::device_t sub_device_id;
|
||||
bool bridge;
|
||||
|
||||
Pci_config(addr_t addr,
|
||||
@ -162,6 +179,9 @@ class Driver::Device : private List_model<Device>::Element
|
||||
Pci::vendor_t vendor_id,
|
||||
Pci::device_t device_id,
|
||||
Pci::class_t class_code,
|
||||
Pci::rev_t revision,
|
||||
Pci::vendor_t sub_vendor_id,
|
||||
Pci::device_t sub_device_id,
|
||||
bool bridge)
|
||||
:
|
||||
addr(addr),
|
||||
@ -171,6 +191,9 @@ class Driver::Device : private List_model<Device>::Element
|
||||
vendor_id(vendor_id),
|
||||
device_id(device_id),
|
||||
class_code(class_code),
|
||||
revision(revision),
|
||||
sub_vendor_id(sub_vendor_id),
|
||||
sub_device_id(sub_device_id),
|
||||
bridge(bridge) {}
|
||||
};
|
||||
|
||||
@ -202,7 +225,7 @@ class Driver::Device : private List_model<Device>::Element
|
||||
{
|
||||
unsigned idx = 0;
|
||||
_io_port_range_list.for_each([&] (Io_port_range const & ipr) {
|
||||
fn(idx++, ipr.addr, ipr.size); });
|
||||
fn(idx++, ipr.range); });
|
||||
}
|
||||
|
||||
template <typename FN> void for_pci_config(FN const & fn) const
|
||||
@ -360,6 +383,9 @@ struct Driver::Irq_update_policy : Genode::List_model<Device::Irq>::Update_polic
|
||||
|
||||
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) {}
|
||||
@ -369,17 +395,18 @@ struct Driver::Io_mem_update_policy : Genode::List_model<Device::Io_mem>::Update
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
Device::Range range { node.attribute_value<Genode::addr_t>("address", 0),
|
||||
node.attribute_value<Genode::size_t>("size", 0) };
|
||||
return *(new (alloc) Element(range));
|
||||
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) };
|
||||
return *(new (alloc) Element(bar, range));
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
||||
static bool element_matches_xml_node(Element const & iomem, Genode::Xml_node node)
|
||||
{
|
||||
Device::Range range { node.attribute_value<Genode::addr_t>("address", 0),
|
||||
node.attribute_value<Genode::size_t>("size", 0) };
|
||||
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);
|
||||
}
|
||||
|
||||
@ -393,6 +420,9 @@ struct Driver::Io_mem_update_policy : Genode::List_model<Device::Io_mem>::Update
|
||||
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) {}
|
||||
@ -402,18 +432,19 @@ struct Driver::Io_port_update_policy
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
uint16_t addr = node.attribute_value<uint16_t>("address", 0);
|
||||
uint16_t size = node.attribute_value<uint16_t>("size", 0);
|
||||
return *(new (alloc) Element(addr, size));
|
||||
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)
|
||||
{
|
||||
uint16_t addr = node.attribute_value<uint16_t>("address", 0);
|
||||
uint16_t size = node.attribute_value<uint16_t>("size", 0);
|
||||
return addr == ipr.addr && size == ipr.size;
|
||||
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)
|
||||
@ -573,10 +604,16 @@ struct Driver::Pci_config_update_policy
|
||||
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, bridge));
|
||||
vendor_id, device_id, class_code,
|
||||
rev, sub_v_id, sub_d_id, bridge));
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
@ -103,7 +103,8 @@ Genode::Io_port_session_capability Device_component::io_port_range(unsigned idx)
|
||||
return;
|
||||
|
||||
if (!ipr.io_port_range.constructed())
|
||||
ipr.io_port_range.construct(_session.env(), ipr.addr, ipr.size);
|
||||
ipr.io_port_range.construct(_session.env(), ipr.range.addr,
|
||||
ipr.range.size);
|
||||
|
||||
cap = ipr.io_port_range->cap();
|
||||
});
|
||||
@ -154,15 +155,13 @@ Device_component::Device_component(Registry<Device_component> & registry,
|
||||
new (session.heap()) Io_mem(_io_mem_registry, idx, range);
|
||||
});
|
||||
|
||||
device.for_each_io_port_range([&] (unsigned idx, uint16_t addr,
|
||||
uint16_t size)
|
||||
device.for_each_io_port_range([&] (unsigned idx, Io_port_range::Range range)
|
||||
{
|
||||
session.ram_quota_guard().withdraw(Ram_quota{Io_port_session::RAM_QUOTA});
|
||||
_ram_quota += Io_port_session::RAM_QUOTA;
|
||||
session.cap_quota_guard().withdraw(Cap_quota{Io_port_session::CAP_QUOTA});
|
||||
_cap_quota += Io_port_session::CAP_QUOTA;
|
||||
new (session.heap()) Io_port_range(_io_port_range_registry,
|
||||
idx, addr, size);
|
||||
new (session.heap()) Io_port_range(_io_port_range_registry, idx, range);
|
||||
});
|
||||
|
||||
device.for_pci_config([&] (Device::Pci_config const & cfg)
|
||||
|
@ -73,18 +73,18 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
|
||||
|
||||
struct Io_port_range : Registry<Io_port_range>::Element
|
||||
{
|
||||
using Range = Device::Io_port_range::Range;
|
||||
|
||||
unsigned idx;
|
||||
uint16_t addr;
|
||||
uint16_t size;
|
||||
Range range;
|
||||
Constructible<Io_port_connection> io_port_range {};
|
||||
|
||||
Io_port_range(Registry<Io_port_range> & registry,
|
||||
unsigned idx,
|
||||
uint16_t addr,
|
||||
uint16_t size)
|
||||
unsigned idx,
|
||||
Range range)
|
||||
:
|
||||
Registry<Io_port_range>::Element(registry, *this),
|
||||
idx(idx), addr(addr), size(size) {}
|
||||
idx(idx), range(range) {}
|
||||
};
|
||||
|
||||
struct Pci_config
|
||||
|
@ -47,12 +47,13 @@ struct Config_helper
|
||||
Config::Command::Bus_master_enable::set(cmd, 1);
|
||||
|
||||
/* enable memory space when I/O mem is defined */
|
||||
_dev.for_each_io_mem([&] (unsigned, Driver::Device::Range) {
|
||||
_dev.for_each_io_mem([&] (unsigned, Driver::Device::Io_mem::Range) {
|
||||
Config::Command::Memory_space_enable::set(cmd, 1); });
|
||||
|
||||
/* enable i/o space when I/O ports are defined */
|
||||
_dev.for_each_io_port_range([&] (unsigned, uint16_t, uint16_t) {
|
||||
Config::Command::Io_space_enable::set(cmd, 1); });
|
||||
_dev.for_each_io_port_range(
|
||||
[&] (unsigned, Driver::Device::Io_port_range::Range) {
|
||||
Config::Command::Io_space_enable::set(cmd, 1); });
|
||||
|
||||
_config.write<Config::Command>(cmd);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user