lx_kit/lx_emul: support for executing PCI fixups

Ref genodelabs/genode#4411
This commit is contained in:
Josef Söntgen 2022-02-04 15:48:18 +01:00 committed by Norman Feske
parent 2515196b82
commit 5a48f8ab0f
5 changed files with 94 additions and 1 deletions

View File

@ -34,6 +34,11 @@ void lx_emul_register_of_clk_initcall(char const *compat, void *fn);
void lx_emul_register_of_irqchip_initcall(char const *compat, void *fn);
struct pci_dev;
void lx_emul_register_pci_fixup(void (*fn)(struct pci_dev*), char const *name);
void lx_emul_execute_pci_fixup(struct pci_dev *pci_dev);
#ifdef __cplusplus
}
#endif

View File

@ -41,6 +41,7 @@ struct Lx_kit::Env
Genode::Env & env;
Genode::Heap heap { env.ram(), env.rm() };
Initcalls initcalls { heap };
Pci_fixup_calls pci_fixup_calls { heap };
Console console { };
Platform::Connection platform { env };
Timer::Connection timer { env };

View File

@ -22,6 +22,8 @@ namespace Lx_kit {
void initialize(Env & env);
class Initcalls;
class Pci_fixup_calls;
}
@ -48,4 +50,28 @@ class Lx_kit::Initcalls
Initcalls(Heap & heap) : _heap(heap) {}
};
struct pci_dev;
class Lx_kit::Pci_fixup_calls
{
private:
struct E : List<E>::Element
{
void (*call) (struct pci_dev *);
E(void (*fn)(struct pci_dev *)) : call { fn } { }
};
Heap & _heap;
List<E> _call_list {};
public:
void add(void (*fn)(struct pci_dev*));
void execute(struct pci_dev *);
Pci_fixup_calls(Heap & heap) : _heap(heap) { }
};
#endif /* _LX_KIT__INIT_H_ */

View File

@ -0,0 +1,46 @@
/*
* \brief Lx_emul backend for PCI fixup calls
* \author Josef Soentgen
* \date 2022-02-04
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/log.h>
#include <lx_kit/env.h>
#include <lx_emul/init.h>
#include <lx_emul/pci_fixups.h>
extern "C" __attribute__((weak)) int inhibit_pci_fixup(char const *)
{
return 0;
}
extern "C" void lx_emul_register_pci_fixup(void (*fn)(struct pci_dev*), const char * name)
{
if (inhibit_pci_fixup(name))
return;
for (unsigned i = 0; i < (sizeof(lx_emul_pci_final_fixups) / sizeof(char*));
i++) {
if (Genode::strcmp(name, lx_emul_pci_final_fixups[i]) == 0) {
Lx_kit::env().pci_fixup_calls.add(fn);
return;
}
}
Genode::error(__func__, " ignore unkown PCI fixup '", name, "'");
}
extern "C" void lx_emul_execute_pci_fixup(struct pci_dev *pci_dev)
{
Lx_kit::env().pci_fixup_calls.execute(pci_dev);
}

View File

@ -16,7 +16,11 @@
#include <lx_kit/env.h>
#include <lx_kit/init.h>
namespace Lx_kit { class Initcalls; }
namespace Lx_kit {
class Initcalls;
class Pci_fixup_calls;
}
void Lx_kit::Initcalls::add(int (*initcall)(void), unsigned int prio) {
@ -40,6 +44,17 @@ void Lx_kit::Initcalls::execute_in_order()
}
void Lx_kit::Pci_fixup_calls::add(void (*fn)(struct pci_dev*)) {
_call_list.insert(new (_heap) E(fn)); }
void Lx_kit::Pci_fixup_calls::execute(struct pci_dev *pci_dev)
{
for (E * entry = _call_list.first(); entry; entry = entry->next())
entry->call(pci_dev);
}
void Lx_kit::initialize(Genode::Env & env)
{
Lx_kit::env(&env);