mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-21 18:06:50 +00:00
pci: add support to provide PCI ECMA config
This commit is contained in:
parent
822b4f2d96
commit
c374f294c8
@ -52,7 +52,7 @@ namespace Genode {
|
|||||||
void _out_char(char c)
|
void _out_char(char c)
|
||||||
{
|
{
|
||||||
/* ensure to leave space for null-termination */
|
/* ensure to leave space for null-termination */
|
||||||
if (_w_offset > _dst_len - 2)
|
if (_w_offset + 2 > _dst_len)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_dst[_w_offset++] = c;
|
_dst[_w_offset++] = c;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <pci_session/pci_session.h>
|
#include <pci_session/pci_session.h>
|
||||||
#include <pci_device/pci_device.h>
|
#include <pci_device/pci_device.h>
|
||||||
#include <base/rpc_client.h>
|
#include <base/rpc_client.h>
|
||||||
|
#include <io_mem_session/io_mem_session.h>
|
||||||
|
|
||||||
namespace Pci {
|
namespace Pci {
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#define _INCLUDE__PCI_DEVICE__PCI_DEVICE_H_
|
#define _INCLUDE__PCI_DEVICE__PCI_DEVICE_H_
|
||||||
|
|
||||||
#include <base/rpc.h>
|
#include <base/rpc.h>
|
||||||
|
#include <io_mem_session/io_mem_session.h>
|
||||||
|
|
||||||
namespace Pci {
|
namespace Pci {
|
||||||
|
|
||||||
|
@ -32,6 +32,9 @@ namespace Pci {
|
|||||||
|
|
||||||
void release_device(Device_capability device) {
|
void release_device(Device_capability device) {
|
||||||
call<Rpc_release_device>(device); }
|
call<Rpc_release_device>(device); }
|
||||||
|
|
||||||
|
Genode::Io_mem_dataspace_capability config_extended(Device_capability device_cap) {
|
||||||
|
return call<Rpc_config_extended>(device_cap); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,16 +49,25 @@ namespace Pci {
|
|||||||
*/
|
*/
|
||||||
virtual void release_device(Device_capability device) = 0;
|
virtual void release_device(Device_capability device) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide mapping to device configuration space of 4k, known as
|
||||||
|
* "Enhanced Configuration Access Mechanism (ECAM) for PCI Express
|
||||||
|
*/
|
||||||
|
virtual Genode::Io_mem_dataspace_capability config_extended(Device_capability) = 0;
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
** RPC declaration **
|
** RPC declaration **
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
GENODE_RPC(Rpc_first_device, Device_capability, first_device);
|
GENODE_RPC(Rpc_first_device, Device_capability, first_device);
|
||||||
GENODE_RPC(Rpc_next_device, Device_capability, next_device, Device_capability);
|
GENODE_RPC(Rpc_next_device, Device_capability, next_device,
|
||||||
|
Device_capability);
|
||||||
GENODE_RPC(Rpc_release_device, void, release_device, Device_capability);
|
GENODE_RPC(Rpc_release_device, void, release_device, Device_capability);
|
||||||
|
GENODE_RPC(Rpc_config_extended, Genode::Io_mem_dataspace_capability,
|
||||||
|
config_extended, Device_capability);
|
||||||
|
|
||||||
GENODE_RPC_INTERFACE(Rpc_first_device, Rpc_next_device, Rpc_release_device);
|
GENODE_RPC_INTERFACE(Rpc_first_device, Rpc_next_device,
|
||||||
|
Rpc_release_device, Rpc_config_extended);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
using namespace Pci;
|
using namespace Pci;
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
printf("PCI driver started\n");
|
printf("PCI driver started\n");
|
||||||
@ -30,7 +29,7 @@ int main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Initialize server entry point
|
* Initialize server entry point
|
||||||
*/
|
*/
|
||||||
enum { STACK_SIZE = sizeof(addr_t)*1024 };
|
enum { STACK_SIZE = 2 * sizeof(addr_t)*1024 };
|
||||||
static Cap_connection cap;
|
static Cap_connection cap;
|
||||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "pci_ep");
|
static Rpc_entrypoint ep(&cap, STACK_SIZE, "pci_ep");
|
||||||
|
|
||||||
@ -46,6 +45,6 @@ int main(int argc, char **argv)
|
|||||||
static Pci::Root root(&ep, &sliced_heap);
|
static Pci::Root root(&ep, &sliced_heap);
|
||||||
env()->parent()->announce(ep.manage(&root));
|
env()->parent()->announce(ep.manage(&root));
|
||||||
|
|
||||||
Genode::sleep_forever();
|
sleep_forever();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#include <base/rpc_server.h>
|
#include <base/rpc_server.h>
|
||||||
#include <base/printf.h>
|
#include <base/printf.h>
|
||||||
|
|
||||||
|
#include <io_mem_session/io_mem_session.h>
|
||||||
|
|
||||||
#include "pci_device_config.h"
|
#include "pci_device_config.h"
|
||||||
|
|
||||||
namespace Pci {
|
namespace Pci {
|
||||||
@ -28,18 +30,32 @@ namespace Pci {
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Device_config _device_config;
|
Device_config _device_config;
|
||||||
|
Genode::addr_t _config_space;
|
||||||
|
Genode::Io_mem_connection *_io_mem;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
Device_component(Device_config device_config):
|
Device_component(Device_config device_config, Genode::addr_t addr)
|
||||||
_device_config(device_config) { }
|
:
|
||||||
|
_device_config(device_config), _config_space(addr),
|
||||||
|
_io_mem(0) { }
|
||||||
|
|
||||||
|
/****************************************
|
||||||
|
** Methods used solely by pci session **
|
||||||
|
****************************************/
|
||||||
|
|
||||||
Device_config config() { return _device_config; }
|
Device_config config() { return _device_config; }
|
||||||
|
|
||||||
|
Genode::addr_t config_space() { return _config_space; }
|
||||||
|
|
||||||
|
void set_config_space(Genode::Io_mem_connection * io_mem) {
|
||||||
|
_io_mem = io_mem; }
|
||||||
|
|
||||||
|
Genode::Io_mem_connection * get_config_space() { return _io_mem; }
|
||||||
|
|
||||||
/**************************
|
/**************************
|
||||||
** PCI-device interface **
|
** PCI-device interface **
|
||||||
|
@ -184,6 +184,29 @@ namespace Pci {
|
|||||||
pci_config->write(_bus, _device, _function, address, value, size);
|
pci_config->write(_bus, _device, _function, address, value, size);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Config_space : public Genode::List<Config_space>::Element
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Genode::uint32_t _bdf_start;
|
||||||
|
Genode::uint32_t _func_count;
|
||||||
|
Genode::addr_t _base;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Config_space(Genode::uint32_t bdf_start,
|
||||||
|
Genode::uint32_t func_count, Genode::addr_t base)
|
||||||
|
:
|
||||||
|
_bdf_start(bdf_start), _func_count(func_count), _base(base) {}
|
||||||
|
|
||||||
|
Genode::addr_t lookup_config_space(Genode::uint32_t bdf)
|
||||||
|
{
|
||||||
|
if ((_bdf_start <= bdf) && (bdf <= _bdf_start + _func_count - 1))
|
||||||
|
return _base + (bdf << 12);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _DEVICE_CONFIG_H_ */
|
#endif /* _DEVICE_CONFIG_H_ */
|
||||||
|
@ -18,6 +18,10 @@
|
|||||||
#include <pci_session/pci_session.h>
|
#include <pci_session/pci_session.h>
|
||||||
#include <root/component.h>
|
#include <root/component.h>
|
||||||
|
|
||||||
|
#include <io_mem_session/connection.h>
|
||||||
|
|
||||||
|
#include <os/config.h>
|
||||||
|
|
||||||
#include "pci_device_component.h"
|
#include "pci_device_component.h"
|
||||||
#include "pci_config_access.h"
|
#include "pci_config_access.h"
|
||||||
|
|
||||||
@ -77,7 +81,6 @@ namespace Pci {
|
|||||||
Genode::Allocator *_md_alloc;
|
Genode::Allocator *_md_alloc;
|
||||||
Genode::List<Device_component> _device_list;
|
Genode::List<Device_component> _device_list;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan PCI busses for a device
|
* Scan PCI busses for a device
|
||||||
*
|
*
|
||||||
@ -119,6 +122,34 @@ namespace Pci {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List containing extended PCI config space information
|
||||||
|
*/
|
||||||
|
static Genode::List<Config_space> &config_space_list() {
|
||||||
|
static Genode::List<Config_space> config_space;
|
||||||
|
return config_space;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find for a given PCI device described by the bus:dev:func triple
|
||||||
|
* the corresponding extended 4K PCI config space address.
|
||||||
|
* A io mem dataspace is created and returned.
|
||||||
|
*/
|
||||||
|
Genode::addr_t
|
||||||
|
lookup_config_space(Genode::uint8_t bus, Genode::uint8_t dev,
|
||||||
|
Genode::uint8_t func)
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
uint32_t bdf = (bus << 8) | ((dev & 0x1f) << 3) | (func & 0x7);
|
||||||
|
addr_t config_space = ~0UL; /* invalid */
|
||||||
|
|
||||||
|
Config_space *e = config_space_list().first();
|
||||||
|
for (; e && (config_space == ~0UL); e = e->next())
|
||||||
|
config_space = e->lookup_config_space(bdf);
|
||||||
|
|
||||||
|
return config_space;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -139,6 +170,17 @@ namespace Pci {
|
|||||||
release_device(_device_list.first()->cap());
|
release_device(_device_list.first()->cap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_config_space(Genode::uint32_t bdf_start,
|
||||||
|
Genode::uint32_t func_count,
|
||||||
|
Genode::addr_t base)
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
Config_space * space =
|
||||||
|
new (env()->heap()) Config_space(bdf_start, func_count,
|
||||||
|
base);
|
||||||
|
config_space_list().insert(space);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************
|
/***************************
|
||||||
** PCI session interface **
|
** PCI session interface **
|
||||||
@ -181,13 +223,22 @@ namespace Pci {
|
|||||||
if (!_find_next(bus, device, function, &config, &config_access))
|
if (!_find_next(bus, device, function, &config, &config_access))
|
||||||
return Device_capability();
|
return Device_capability();
|
||||||
|
|
||||||
|
/* get new bdf values */
|
||||||
|
bus = config.bus_number();
|
||||||
|
device = config.device_number();
|
||||||
|
function = config.function_number();
|
||||||
|
|
||||||
|
/* lookup if we have a extended pci config space */
|
||||||
|
Genode::addr_t config_space = lookup_config_space(bus, device,
|
||||||
|
function);
|
||||||
/*
|
/*
|
||||||
* A device was found. Create a new device component for the
|
* A device was found. Create a new device component for the
|
||||||
* device and return its capability.
|
* device and return its capability.
|
||||||
*
|
*
|
||||||
* FIXME: check and adjust session quota
|
* FIXME: check and adjust session quota
|
||||||
*/
|
*/
|
||||||
Device_component *device_component = new (_md_alloc) Device_component(config);
|
Device_component *device_component =
|
||||||
|
new (_md_alloc) Device_component(config, config_space);
|
||||||
|
|
||||||
if (!device_component)
|
if (!device_component)
|
||||||
return Device_capability();
|
return Device_capability();
|
||||||
@ -209,8 +260,37 @@ namespace Pci {
|
|||||||
_ep->dissolve(device);
|
_ep->dissolve(device);
|
||||||
|
|
||||||
/* FIXME: adjust quota */
|
/* FIXME: adjust quota */
|
||||||
|
Genode::Io_mem_connection * io_mem = device->get_config_space();
|
||||||
|
if (io_mem)
|
||||||
|
destroy(_md_alloc, io_mem);
|
||||||
destroy(_md_alloc, device);
|
destroy(_md_alloc, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Genode::Io_mem_dataspace_capability config_extended(Device_capability device_cap)
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
Object_pool<Device_component>::Guard
|
||||||
|
device(_ep->lookup_and_lock(device_cap));
|
||||||
|
|
||||||
|
if (!device || device->config_space() == ~0UL)
|
||||||
|
return Io_mem_dataspace_capability();
|
||||||
|
|
||||||
|
Io_mem_connection * io_mem = device->get_config_space();
|
||||||
|
if (io_mem)
|
||||||
|
return io_mem->dataspace();
|
||||||
|
|
||||||
|
try {
|
||||||
|
io_mem = new (_md_alloc) Io_mem_connection(device->config_space(),
|
||||||
|
0x1000);
|
||||||
|
} catch (Parent::Service_denied) {
|
||||||
|
return Io_mem_dataspace_capability();
|
||||||
|
}
|
||||||
|
|
||||||
|
device->set_config_space(io_mem);
|
||||||
|
|
||||||
|
return io_mem->dataspace();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -220,6 +300,35 @@ namespace Pci {
|
|||||||
|
|
||||||
Genode::Cap_session *_cap_session;
|
Genode::Cap_session *_cap_session;
|
||||||
|
|
||||||
|
|
||||||
|
void _parse_config()
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
try {
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < config()->xml_node().num_sub_nodes(); i++)
|
||||||
|
{
|
||||||
|
Xml_node node = config()->xml_node().sub_node(i);
|
||||||
|
uint32_t bdf_start = 0;
|
||||||
|
uint32_t func_count = 0;
|
||||||
|
addr_t base = 0;
|
||||||
|
node.sub_node("start").value(&bdf_start);
|
||||||
|
node.sub_node("count").value(&func_count);
|
||||||
|
node.sub_node("base").value(&base);
|
||||||
|
|
||||||
|
PINF("%2u BDF start %x, functions: 0x%x, physical base "
|
||||||
|
"0x%lx", i, bdf_start, func_count, base);
|
||||||
|
|
||||||
|
Session_component::add_config_space(bdf_start,
|
||||||
|
func_count, base);
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
PERR("PCI config space data could not be parsed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
Session_component *_create_session(const char *args)
|
Session_component *_create_session(const char *args)
|
||||||
@ -245,6 +354,8 @@ namespace Pci {
|
|||||||
:
|
:
|
||||||
Genode::Root_component<Session_component>(ep, md_alloc)
|
Genode::Root_component<Session_component>(ep, md_alloc)
|
||||||
{
|
{
|
||||||
|
_parse_config();
|
||||||
|
|
||||||
/* enforce initial bus scan */
|
/* enforce initial bus scan */
|
||||||
bus_valid();
|
bus_valid();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user