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.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 <util/list.h>
|
||||
#include <util/mmio.h>
|
||||
#include <util/construct_at.h>
|
||||
|
||||
/* os */
|
||||
#include <platform_device/platform_device.h>
|
||||
@ -40,7 +41,7 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
Genode::Rpc_entrypoint *_ep;
|
||||
Platform::Session_component *_session;
|
||||
unsigned short _irq_line;
|
||||
Irq_session_component _irq_session;
|
||||
Irq_session_component *_irq_session;
|
||||
|
||||
class Io_mem : public Genode::Io_mem_connection,
|
||||
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;
|
||||
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::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(),
|
||||
pin);
|
||||
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.device_number(),
|
||||
_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;
|
||||
}
|
||||
|
||||
@ -189,19 +188,16 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
Device_component(Device_config device_config, Genode::addr_t addr,
|
||||
Genode::Rpc_entrypoint *ep,
|
||||
Platform::Session_component * session,
|
||||
Genode::Allocator * md_alloc,
|
||||
bool use_msi)
|
||||
Genode::Allocator * md_alloc)
|
||||
:
|
||||
_device_config(device_config), _config_space(addr),
|
||||
_ep(ep), _session(session),
|
||||
_irq_line(_device_config.read(&_config_access, PCI_IRQ_LINE,
|
||||
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_iomem(md_alloc, &_slab_iomem_block)
|
||||
{
|
||||
_ep->manage(&_irq_session);
|
||||
|
||||
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
|
||||
_io_port_conn[i] = nullptr;
|
||||
}
|
||||
@ -213,40 +209,6 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
|
||||
_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),
|
||||
_ep(ep), _session(session),
|
||||
_irq_line(irq),
|
||||
_irq_session(_irq_line, _config_space),
|
||||
_irq_session(nullptr),
|
||||
_slab_ioport(0, &_slab_ioport_block),
|
||||
_slab_iomem(0, &_slab_iomem_block)
|
||||
{
|
||||
_ep->manage(&_irq_session);
|
||||
|
||||
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++)
|
||||
_io_port_conn[i] = nullptr;
|
||||
}
|
||||
@ -273,7 +233,10 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
*/
|
||||
~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++) {
|
||||
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,
|
||||
Access_size size) override;
|
||||
|
||||
Genode::Irq_session_capability irq(Genode::uint8_t id) 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::Irq_session_capability irq(Genode::uint8_t) override;
|
||||
|
||||
Genode::Io_port_session_capability io_port(Genode::uint8_t) override;
|
||||
|
||||
|
@ -163,21 +163,6 @@ namespace Platform {
|
||||
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
|
||||
*/
|
||||
@ -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 **
|
||||
***************************/
|
||||
@ -535,7 +536,7 @@ namespace Platform {
|
||||
try {
|
||||
Device_component * dev = new (_device_slab)
|
||||
Device_component(config, config_space, _ep, this,
|
||||
&_md_alloc, msi_usage());
|
||||
&_md_alloc);
|
||||
|
||||
/* if more than one driver uses the device - warn about */
|
||||
if (bdf_in_use.get(Device_config::MAX_BUSES * bus +
|
||||
|
Loading…
Reference in New Issue
Block a user