mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 20:05:54 +00:00
acpi: provide pci express style configs to pci_drv
Parse the mcfg table and provide the extended PCI config space data via the config file to the pci_drv.
This commit is contained in:
parent
ba566a1530
commit
822b4f2d96
@ -114,6 +114,30 @@ class Irq_override : public List<Irq_override>::Element
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* List that holds the result of the mcfg table parsing which are pointers
|
||||
* to the extended pci config space - 4k for each device.
|
||||
*/
|
||||
class Pci_config_space : public List<Pci_config_space>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
uint32_t _bdf_start;
|
||||
uint32_t _func_count;
|
||||
addr_t _base;
|
||||
|
||||
Pci_config_space(uint32_t bdf_start, uint32_t func_count, addr_t base)
|
||||
:
|
||||
_bdf_start(bdf_start), _func_count(func_count), _base(base) {}
|
||||
|
||||
static List<Pci_config_space> *list()
|
||||
{
|
||||
static List<Pci_config_space> _list;
|
||||
return &_list;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* ACPI table wrapper that for mapping tables to this address space
|
||||
*/
|
||||
@ -235,6 +259,14 @@ class Table_wrapper
|
||||
for (; mcfg < _table->mcfg_end(); mcfg = mcfg->next()) {
|
||||
PINF("MCFG BASE 0x%llx seg %02x bus %02x-%02x", mcfg->base,
|
||||
mcfg->pci_seg, mcfg->pci_bus_start, mcfg->pci_bus_end);
|
||||
|
||||
/* bus_count * up to 32 devices * 8 function per device * 4k */
|
||||
uint32_t bus_count = mcfg->pci_bus_end - mcfg->pci_bus_start + 1;
|
||||
uint32_t func_count = bus_count * 32 * 8;
|
||||
uint32_t bus_start = mcfg->pci_bus_start * 32 * 8;
|
||||
|
||||
Pci_config_space::list()->insert(
|
||||
new (env()->heap()) Pci_config_space(bus_start, func_count, mcfg->base));
|
||||
}
|
||||
}
|
||||
|
||||
@ -867,6 +899,34 @@ class Element : public List<Element>::Element
|
||||
}
|
||||
throw -1;
|
||||
}
|
||||
|
||||
static void create_config_file(char * text, size_t max)
|
||||
{
|
||||
Pci_config_space *e = Pci_config_space::list()->first();
|
||||
|
||||
int len = snprintf(text, max, "<config>");
|
||||
text += len;
|
||||
max -= len;
|
||||
for (; e; e = e->next())
|
||||
{
|
||||
using namespace Genode;
|
||||
len = snprintf(text, max, "<bdf><start>%u</start>", e->_bdf_start);
|
||||
text += len;
|
||||
max -= len;
|
||||
len = snprintf(text, max, "<count>%u</count>" , e->_func_count);
|
||||
text += len;
|
||||
max -= len;
|
||||
len = snprintf(text, max, "<base>0x%lx</base></bdf>" , e->_base);
|
||||
text += len;
|
||||
max -= len;
|
||||
}
|
||||
len = snprintf(text, max, "</config>");
|
||||
text += len;
|
||||
max -= len;
|
||||
|
||||
if (max < 2)
|
||||
PERR("config file could not be generated, buffer to small");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -960,7 +1020,6 @@ class Acpi_table
|
||||
|
||||
table.parse_madt();
|
||||
}
|
||||
|
||||
if (table.is_mcfg()) {
|
||||
PDBG("Found MCFG");
|
||||
|
||||
@ -1200,22 +1259,38 @@ static void dump_rewrite(uint32_t bdf, uint8_t line, uint8_t gsi)
|
||||
(bdf >> 8), (bdf >> 3) & 0x1f, (bdf & 0x7), line, gsi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse acpi table
|
||||
*/
|
||||
static void init_acpi_table() {
|
||||
static Acpi_table table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create config file for pci_drv
|
||||
*/
|
||||
void Acpi::create_pci_config_file(char * config_space,
|
||||
Genode::size_t config_space_max)
|
||||
{
|
||||
init_acpi_table();
|
||||
Element::create_config_file(config_space, config_space_max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite GSIs of PCI config space
|
||||
*/
|
||||
void Acpi::rewrite_irq(Pci::Session_capability &session)
|
||||
void Acpi::configure_pci_devices(Pci::Session_capability &session)
|
||||
{
|
||||
static Acpi_table table;
|
||||
init_acpi_table();
|
||||
static Pci_bridge bridge(session);
|
||||
|
||||
/* if no _PIC method could be found return */
|
||||
if (Element::supported_acpi_format())
|
||||
PINF("ACPI table format is supported by this driver");
|
||||
else {
|
||||
PWRN("ACPI table format not supported will not rewrite GSIs");
|
||||
return;
|
||||
}
|
||||
/* if no _PIC method could be found don't rewrite */
|
||||
bool acpi_rewrite = Element::supported_acpi_format();
|
||||
|
||||
if (acpi_rewrite)
|
||||
PINF("ACPI table format is supported - rewrite GSIs");
|
||||
else
|
||||
PWRN("ACPI table format not supported - will not rewrite GSIs");
|
||||
|
||||
Pci::Session_client pci(session);
|
||||
Pci::Device_capability device_cap = pci.first_device(), prev_device_cap;
|
||||
@ -1224,7 +1299,8 @@ void Acpi::rewrite_irq(Pci::Session_capability &session)
|
||||
prev_device_cap = device_cap;
|
||||
Pci_client device(device_cap);
|
||||
|
||||
if (!device.is_bridge()) {
|
||||
/* rewrite IRQs */
|
||||
if (acpi_rewrite && !device.is_bridge()) {
|
||||
uint32_t device_bdf = device.bdf();
|
||||
uint32_t bridge_bdf = Pci_bridge::bridge_bdf(device_bdf);
|
||||
uint32_t irq_pin = device.irq_pin();
|
||||
@ -1241,6 +1317,7 @@ void Acpi::rewrite_irq(Pci::Session_capability &session)
|
||||
device_cap = pci.next_device(device_cap);
|
||||
pci.release_device(prev_device_cap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,14 +22,27 @@ class Acpi
|
||||
public:
|
||||
|
||||
/**
|
||||
* Rewrite PCI-config space with GSIs found in ACPI tables
|
||||
* Constructor
|
||||
*/
|
||||
static void rewrite_irq(Pci::Session_capability &session);
|
||||
Acpi();
|
||||
|
||||
/**
|
||||
* Generate config file for pci_drv containing pointers to the
|
||||
* extended PCI config space (since PCI Express)
|
||||
*/
|
||||
static void create_pci_config_file(char * config_space,
|
||||
Genode::size_t config_space_max);
|
||||
|
||||
/**
|
||||
* Rewrite PCI-config space with GSIs found in ACPI tables.
|
||||
*/
|
||||
static void configure_pci_devices(Pci::Session_capability &session);
|
||||
|
||||
/**
|
||||
* Return override GSI for IRQ
|
||||
*/
|
||||
static unsigned override(unsigned irq, unsigned *mode);
|
||||
|
||||
};
|
||||
|
||||
#endif /* _ACPI_H_ */
|
||||
|
@ -156,12 +156,15 @@ class Pci_policy : public Genode::Slave_policy, public Pci::Provider
|
||||
Genode::Root_capability _cap;
|
||||
Genode::Rpc_entrypoint &_pci_ep;
|
||||
Genode::Rpc_entrypoint &_irq_ep;
|
||||
Genode::Lock _lock;
|
||||
|
||||
protected:
|
||||
|
||||
char const **_permitted_services() const
|
||||
{
|
||||
static char const *permitted_services[] = { "CPU", "CAP", "RM", "LOG", "IO_PORT", 0 };
|
||||
static char const *permitted_services[] = { "CPU", "CAP", "RM",
|
||||
"LOG", "IO_PORT",
|
||||
"SIGNAL", 0};
|
||||
return permitted_services;
|
||||
};
|
||||
|
||||
@ -178,7 +181,7 @@ class Pci_policy : public Genode::Slave_policy, public Pci::Provider
|
||||
session = static_cap_cast<Pci::Session>(Root_client(_cap).session(args));
|
||||
} catch (...) { return; }
|
||||
|
||||
Acpi::rewrite_irq(session);
|
||||
Acpi::configure_pci_devices(session);
|
||||
|
||||
/* announce PCI/IRQ services to parent */
|
||||
static Pci::Root pci_root(*this);
|
||||
@ -195,7 +198,9 @@ class Pci_policy : public Genode::Slave_policy, public Pci::Provider
|
||||
Pci_policy(Genode::Rpc_entrypoint &slave_ep,
|
||||
Genode::Rpc_entrypoint &pci_ep,
|
||||
Genode::Rpc_entrypoint &irq_ep)
|
||||
: Slave_policy("pci_drv", slave_ep), _pci_ep(pci_ep), _irq_ep(irq_ep)
|
||||
:
|
||||
Slave_policy("pci_drv", slave_ep, Genode::env()->ram_session()),
|
||||
_pci_ep(pci_ep), _irq_ep(irq_ep), _lock(Genode::Lock::LOCKED)
|
||||
{ }
|
||||
|
||||
bool announce_service(const char *service_name,
|
||||
@ -209,12 +214,20 @@ class Pci_policy : public Genode::Slave_policy, public Pci::Provider
|
||||
|
||||
_cap = root;
|
||||
|
||||
/* connect session and start ACPI parsing */
|
||||
_acpi_session();
|
||||
/* unblock main thread blocked in wait_for_pci_drv */
|
||||
_lock.unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wait_for_pci_drv() {
|
||||
/* wait until pci drv is ready */
|
||||
_lock.lock();
|
||||
|
||||
/* connect session and start ACPI parsing */
|
||||
_acpi_session();
|
||||
}
|
||||
|
||||
Genode::Root_capability root() { return _cap; }
|
||||
};
|
||||
|
||||
@ -224,6 +237,7 @@ int main(int argc, char **argv)
|
||||
using namespace Genode;
|
||||
|
||||
enum { STACK_SIZE = 2*4096 };
|
||||
|
||||
static Cap_connection cap;
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "acpi_ep");
|
||||
|
||||
@ -234,8 +248,18 @@ int main(int argc, char **argv)
|
||||
/* use 'pci_drv' as slave service */
|
||||
static Rpc_entrypoint pci_ep(&cap, STACK_SIZE, "pci_slave");
|
||||
static Pci_policy pci_policy(pci_ep, ep, irq_ep);
|
||||
|
||||
/* generate config file for pci_drv */
|
||||
char buf[256];
|
||||
Acpi::create_pci_config_file(buf, sizeof(buf));
|
||||
pci_policy.configure(buf);
|
||||
|
||||
/* use 'pci_drv' as slave service */
|
||||
static Genode::Slave pci_slave(pci_ep, pci_policy, 1024 * 1024);
|
||||
|
||||
/* wait until pci drv is online and then make the acpi work */
|
||||
pci_policy.wait_for_pci_drv();
|
||||
|
||||
Genode::sleep_forever();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
TARGET = acpi_drv
|
||||
TARGET = acpi_drv
|
||||
REQUIRES = x86
|
||||
SRC_CC = main.cc acpi.cc
|
||||
LIBS = base
|
||||
|
Loading…
x
Reference in New Issue
Block a user