mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-19 03:06:39 +00:00
parent
2b2587fde9
commit
8701b7d517
@ -121,3 +121,89 @@ void Platform::Device_component::config_write(unsigned char address,
|
|||||||
_device_config.write(&_config_access, address, value, size,
|
_device_config.write(&_config_access, address, value, size,
|
||||||
_device_config.DONT_TRACK_ACCESS);
|
_device_config.DONT_TRACK_ACCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Genode::Irq_session_capability Platform::Device_component::irq(Genode::uint8_t id)
|
||||||
|
{
|
||||||
|
if (id != 0)
|
||||||
|
return Genode::Irq_session_capability();
|
||||||
|
|
||||||
|
if (_irq_session)
|
||||||
|
return _irq_session->cap();
|
||||||
|
|
||||||
|
using Genode::construct_at;
|
||||||
|
|
||||||
|
if (!_device_config.valid()) {
|
||||||
|
/* Non PCI devices */
|
||||||
|
_irq_session = construct_at<Irq_session_component>(_mem_irq_component,
|
||||||
|
_irq_line, ~0UL);
|
||||||
|
|
||||||
|
_ep->manage(_irq_session);
|
||||||
|
return _irq_session->cap();
|
||||||
|
}
|
||||||
|
|
||||||
|
_irq_session = construct_at<Irq_session_component>(_mem_irq_component,
|
||||||
|
_configure_irq(_irq_line),
|
||||||
|
(!_session->msi_usage() || !_msi_cap()) ? ~0UL : _config_space);
|
||||||
|
_ep->manage(_irq_session);
|
||||||
|
|
||||||
|
if (_irq_session->msi()) {
|
||||||
|
|
||||||
|
Genode::addr_t msi_address = _irq_session->msi_address();
|
||||||
|
Genode::uint32_t msi_value = _irq_session->msi_data();
|
||||||
|
Genode::uint16_t msi_cap = _msi_cap();
|
||||||
|
|
||||||
|
Genode::uint16_t msi = _device_config.read(&_config_access,
|
||||||
|
msi_cap + 2,
|
||||||
|
Platform::Device::ACCESS_16BIT);
|
||||||
|
|
||||||
|
_device_config.write(&_config_access, msi_cap + 0x4, msi_address,
|
||||||
|
Platform::Device::ACCESS_32BIT);
|
||||||
|
|
||||||
|
if (msi & CAP_MSI_64) {
|
||||||
|
Genode::uint32_t upper_address = sizeof(msi_address) > 4
|
||||||
|
? (Genode::uint64_t)msi_address >> 32
|
||||||
|
: 0UL;
|
||||||
|
|
||||||
|
_device_config.write(&_config_access, msi_cap + 0x8,
|
||||||
|
upper_address,
|
||||||
|
Platform::Device::ACCESS_32BIT);
|
||||||
|
_device_config.write(&_config_access, msi_cap + 0xc,
|
||||||
|
msi_value,
|
||||||
|
Platform::Device::ACCESS_16BIT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_device_config.write(&_config_access, msi_cap + 0x8, msi_value,
|
||||||
|
Platform::Device::ACCESS_16BIT);
|
||||||
|
|
||||||
|
/* enable MSI */
|
||||||
|
_device_config.write(&_config_access, msi_cap + 2,
|
||||||
|
msi ^ MSI_ENABLED,
|
||||||
|
Platform::Device::ACCESS_8BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool msi_64 = false;
|
||||||
|
Genode::uint16_t msi_cap = _msi_cap();
|
||||||
|
if (msi_cap) {
|
||||||
|
Genode::uint16_t msi = _device_config.read(&_config_access,
|
||||||
|
msi_cap + 2,
|
||||||
|
Platform::Device::ACCESS_16BIT);
|
||||||
|
msi_64 = msi & CAP_MSI_64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_irq_session->msi())
|
||||||
|
PINF("%x:%x.%x uses MSI %s, vector 0x%lx, address 0x%lx",
|
||||||
|
_device_config.bus_number(),
|
||||||
|
_device_config.device_number(),
|
||||||
|
_device_config.function_number(),
|
||||||
|
msi_64 ? "64bit" : "32bit",
|
||||||
|
_irq_session->msi_data(), _irq_session->msi_address());
|
||||||
|
else
|
||||||
|
PINF("%x:%x.%x uses IRQ, vector 0x%x%s",
|
||||||
|
_device_config.bus_number(),
|
||||||
|
_device_config.device_number(),
|
||||||
|
_device_config.function_number(), _irq_line,
|
||||||
|
msi_cap ? (msi_64 ? ", MSI 64bit capable" :
|
||||||
|
", MSI 32bit capable") : "");
|
||||||
|
|
||||||
|
return _irq_session->cap();
|
||||||
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <io_mem_session/connection.h>
|
#include <io_mem_session/connection.h>
|
||||||
#include <util/list.h>
|
#include <util/list.h>
|
||||||
#include <util/mmio.h>
|
#include <util/mmio.h>
|
||||||
|
#include <util/construct_at.h>
|
||||||
|
|
||||||
/* os */
|
/* os */
|
||||||
#include <platform_device/platform_device.h>
|
#include <platform_device/platform_device.h>
|
||||||
@ -40,7 +41,7 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
|||||||
Genode::Rpc_entrypoint *_ep;
|
Genode::Rpc_entrypoint *_ep;
|
||||||
Platform::Session_component *_session;
|
Platform::Session_component *_session;
|
||||||
unsigned short _irq_line;
|
unsigned short _irq_line;
|
||||||
Irq_session_component _irq_session;
|
Irq_session_component *_irq_session;
|
||||||
|
|
||||||
class Io_mem : public Genode::Io_mem_connection,
|
class Io_mem : public Genode::Io_mem_connection,
|
||||||
public Genode::List<Io_mem>::Element
|
public Genode::List<Io_mem>::Element
|
||||||
@ -72,6 +73,8 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
|||||||
Genode::Slab_block _slab_iomem_block;
|
Genode::Slab_block _slab_iomem_block;
|
||||||
char _slab_iomem_block_data[IO_MEM_SIZE];
|
char _slab_iomem_block_data[IO_MEM_SIZE];
|
||||||
|
|
||||||
|
char _mem_irq_component[sizeof(Irq_session_component)];
|
||||||
|
|
||||||
Genode::Io_port_connection *_io_port_conn [Device::NUM_RESOURCES];
|
Genode::Io_port_connection *_io_port_conn [Device::NUM_RESOURCES];
|
||||||
Genode::List<Io_mem> _io_mem [Device::NUM_RESOURCES];
|
Genode::List<Io_mem> _io_mem [Device::NUM_RESOURCES];
|
||||||
|
|
||||||
@ -131,15 +134,11 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
|||||||
_device_config.function_number(),
|
_device_config.function_number(),
|
||||||
pin);
|
pin);
|
||||||
if (irq_r) {
|
if (irq_r) {
|
||||||
PINF("%x:%x.%x rewriting IRQ: %u -> %u",
|
PINF("%x:%x.%x adjust IRQ as reported by ACPI: %u -> %u",
|
||||||
_device_config.bus_number(),
|
_device_config.bus_number(),
|
||||||
_device_config.device_number(),
|
_device_config.device_number(),
|
||||||
_device_config.function_number(), irq, irq_r);
|
_device_config.function_number(), irq, irq_r);
|
||||||
|
|
||||||
if (_irq_line != irq_r)
|
|
||||||
_device_config.write(&_config_access, PCI_IRQ_LINE, irq_r,
|
|
||||||
Platform::Device::ACCESS_8BIT);
|
|
||||||
|
|
||||||
_irq_line = irq = irq_r;
|
_irq_line = irq = irq_r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,19 +188,16 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
|||||||
Device_component(Device_config device_config, Genode::addr_t addr,
|
Device_component(Device_config device_config, Genode::addr_t addr,
|
||||||
Genode::Rpc_entrypoint *ep,
|
Genode::Rpc_entrypoint *ep,
|
||||||
Platform::Session_component * session,
|
Platform::Session_component * session,
|
||||||
Genode::Allocator * md_alloc,
|
Genode::Allocator * md_alloc)
|
||||||
bool use_msi)
|
|
||||||
:
|
:
|
||||||
_device_config(device_config), _config_space(addr),
|
_device_config(device_config), _config_space(addr),
|
||||||
_ep(ep), _session(session),
|
_ep(ep), _session(session),
|
||||||
_irq_line(_device_config.read(&_config_access, PCI_IRQ_LINE,
|
_irq_line(_device_config.read(&_config_access, PCI_IRQ_LINE,
|
||||||
Platform::Device::ACCESS_8BIT)),
|
Platform::Device::ACCESS_8BIT)),
|
||||||
_irq_session(_configure_irq(_irq_line), (!use_msi || !_msi_cap()) ? ~0UL : _config_space),
|
_irq_session(nullptr),
|
||||||
_slab_ioport(md_alloc, &_slab_ioport_block),
|
_slab_ioport(md_alloc, &_slab_ioport_block),
|
||||||
_slab_iomem(md_alloc, &_slab_iomem_block)
|
_slab_iomem(md_alloc, &_slab_iomem_block)
|
||||||
{
|
{
|
||||||
_ep->manage(&_irq_session);
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
|
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
|
||||||
_io_port_conn[i] = nullptr;
|
_io_port_conn[i] = nullptr;
|
||||||
}
|
}
|
||||||
@ -213,40 +209,6 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
|||||||
|
|
||||||
_disable_bus_master_dma();
|
_disable_bus_master_dma();
|
||||||
|
|
||||||
if (!_irq_session.msi())
|
|
||||||
return;
|
|
||||||
|
|
||||||
Genode::addr_t msi_address = _irq_session.msi_address();
|
|
||||||
Genode::uint32_t msi_value = _irq_session.msi_data();
|
|
||||||
Genode::uint16_t msi_cap = _msi_cap();
|
|
||||||
|
|
||||||
Genode::uint16_t msi = _device_config.read(&_config_access,
|
|
||||||
msi_cap + 2,
|
|
||||||
Platform::Device::ACCESS_16BIT);
|
|
||||||
|
|
||||||
_device_config.write(&_config_access, msi_cap + 0x4, msi_address,
|
|
||||||
Platform::Device::ACCESS_32BIT);
|
|
||||||
|
|
||||||
if (msi & CAP_MSI_64) {
|
|
||||||
Genode::uint32_t upper_address = sizeof(msi_address) > 4
|
|
||||||
? (Genode::uint64_t)msi_address >> 32
|
|
||||||
: 0UL;
|
|
||||||
|
|
||||||
_device_config.write(&_config_access, msi_cap + 0x8,
|
|
||||||
upper_address,
|
|
||||||
Platform::Device::ACCESS_32BIT);
|
|
||||||
_device_config.write(&_config_access, msi_cap + 0xc,
|
|
||||||
msi_value,
|
|
||||||
Platform::Device::ACCESS_16BIT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_device_config.write(&_config_access, msi_cap + 0x8, msi_value,
|
|
||||||
Platform::Device::ACCESS_16BIT);
|
|
||||||
|
|
||||||
/* enable MSI */
|
|
||||||
_device_config.write(&_config_access, msi_cap + 2,
|
|
||||||
msi ^ MSI_ENABLED,
|
|
||||||
Platform::Device::ACCESS_8BIT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -258,12 +220,10 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
|||||||
_config_space(~0UL),
|
_config_space(~0UL),
|
||||||
_ep(ep), _session(session),
|
_ep(ep), _session(session),
|
||||||
_irq_line(irq),
|
_irq_line(irq),
|
||||||
_irq_session(_irq_line, _config_space),
|
_irq_session(nullptr),
|
||||||
_slab_ioport(0, &_slab_ioport_block),
|
_slab_ioport(0, &_slab_ioport_block),
|
||||||
_slab_iomem(0, &_slab_iomem_block)
|
_slab_iomem(0, &_slab_iomem_block)
|
||||||
{
|
{
|
||||||
_ep->manage(&_irq_session);
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++)
|
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++)
|
||||||
_io_port_conn[i] = nullptr;
|
_io_port_conn[i] = nullptr;
|
||||||
}
|
}
|
||||||
@ -273,7 +233,10 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
|||||||
*/
|
*/
|
||||||
~Device_component()
|
~Device_component()
|
||||||
{
|
{
|
||||||
_ep->dissolve(&_irq_session);
|
if (_irq_session) {
|
||||||
|
_ep->dissolve(_irq_session);
|
||||||
|
_irq_session->~Irq_session();
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
|
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
|
||||||
if (_io_port_conn[i])
|
if (_io_port_conn[i])
|
||||||
@ -356,40 +319,7 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
|||||||
void config_write(unsigned char address, unsigned value,
|
void config_write(unsigned char address, unsigned value,
|
||||||
Access_size size) override;
|
Access_size size) override;
|
||||||
|
|
||||||
Genode::Irq_session_capability irq(Genode::uint8_t id) override
|
Genode::Irq_session_capability irq(Genode::uint8_t) override;
|
||||||
{
|
|
||||||
if (id != 0)
|
|
||||||
return Genode::Irq_session_capability();
|
|
||||||
|
|
||||||
if (!_device_config.valid())
|
|
||||||
return _irq_session.cap();
|
|
||||||
|
|
||||||
bool msi_64 = false;
|
|
||||||
Genode::uint16_t msi_cap = _msi_cap();
|
|
||||||
if (msi_cap) {
|
|
||||||
Genode::uint16_t msi = _device_config.read(&_config_access,
|
|
||||||
msi_cap + 2,
|
|
||||||
Platform::Device::ACCESS_16BIT);
|
|
||||||
msi_64 = msi & CAP_MSI_64;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_irq_session.msi())
|
|
||||||
PINF("%x:%x.%x uses MSI %s, vector 0x%lx, address 0x%lx",
|
|
||||||
_device_config.bus_number(),
|
|
||||||
_device_config.device_number(),
|
|
||||||
_device_config.function_number(),
|
|
||||||
msi_64 ? "64bit" : "32bit",
|
|
||||||
_irq_session.msi_data(), _irq_session.msi_address());
|
|
||||||
else
|
|
||||||
PINF("%x:%x.%x uses IRQ, vector 0x%x%s",
|
|
||||||
_device_config.bus_number(),
|
|
||||||
_device_config.device_number(),
|
|
||||||
_device_config.function_number(), _irq_line,
|
|
||||||
msi_cap ? (msi_64 ? ", MSI 64bit capable" :
|
|
||||||
", MSI 32bit capable") : "");
|
|
||||||
|
|
||||||
return _irq_session.cap();
|
|
||||||
}
|
|
||||||
|
|
||||||
Genode::Io_port_session_capability io_port(Genode::uint8_t) override;
|
Genode::Io_port_session_capability io_port(Genode::uint8_t) override;
|
||||||
|
|
||||||
|
@ -163,21 +163,6 @@ namespace Platform {
|
|||||||
return ~0U;
|
return ~0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether msi usage was explicitly switched off
|
|
||||||
*/
|
|
||||||
bool msi_usage()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
char mode[8];
|
|
||||||
_policy.attribute("irq_mode").value(mode, sizeof(mode));
|
|
||||||
if (!Genode::strcmp("nomsi", mode))
|
|
||||||
return false;
|
|
||||||
} catch (Genode::Xml_node::Nonexistent_attribute) { }
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check device usage according to session policy
|
* Check device usage according to session policy
|
||||||
*/
|
*/
|
||||||
@ -461,6 +446,22 @@ namespace Platform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether msi usage was explicitly switched off
|
||||||
|
*/
|
||||||
|
bool msi_usage()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
char mode[8];
|
||||||
|
_policy.attribute("irq_mode").value(mode, sizeof(mode));
|
||||||
|
if (!Genode::strcmp("nomsi", mode))
|
||||||
|
return false;
|
||||||
|
} catch (Genode::Xml_node::Nonexistent_attribute) { }
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************
|
/***************************
|
||||||
** PCI session interface **
|
** PCI session interface **
|
||||||
***************************/
|
***************************/
|
||||||
@ -535,7 +536,7 @@ namespace Platform {
|
|||||||
try {
|
try {
|
||||||
Device_component * dev = new (_device_slab)
|
Device_component * dev = new (_device_slab)
|
||||||
Device_component(config, config_space, _ep, this,
|
Device_component(config, config_space, _ep, this,
|
||||||
&_md_alloc, msi_usage());
|
&_md_alloc);
|
||||||
|
|
||||||
/* if more than one driver uses the device - warn about */
|
/* if more than one driver uses the device - warn about */
|
||||||
if (bdf_in_use.get(Device_config::MAX_BUSES * bus +
|
if (bdf_in_use.get(Device_config::MAX_BUSES * bus +
|
||||||
|
Loading…
Reference in New Issue
Block a user