mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 13:47:56 +00:00
parent
658547d058
commit
dd8e13d6fa
@ -30,7 +30,7 @@
|
||||
/**
|
||||
* Custom handling of PD-session depletion during attach operations
|
||||
*
|
||||
* The default implementation of 'env().rm()' automatically issues a resource
|
||||
* The default implementation of 'env.rm()' automatically issues a resource
|
||||
* request if the PD session quota gets exhausted. For the device PD, we don't
|
||||
* want to issue resource requests but let the platform driver reflect this
|
||||
* condition to its client.
|
||||
@ -59,7 +59,7 @@ struct Expanding_region_map_client : Genode::Region_map_client
|
||||
[&] () {
|
||||
enum { UPGRADE_QUOTA = 4096 };
|
||||
|
||||
if (Genode::env()->ram_session()->avail() < UPGRADE_QUOTA)
|
||||
if (_env.ram().avail() < UPGRADE_QUOTA)
|
||||
throw;
|
||||
|
||||
Genode::String<32> arg("ram_quota=", (unsigned)UPGRADE_QUOTA);
|
||||
@ -172,7 +172,7 @@ void Platform::Device_pd_component::assign_pci(Genode::Io_mem_dataspace_capabili
|
||||
};
|
||||
|
||||
/* try to assign pci device to this protection domain */
|
||||
if (!env()->pd_session()->assign_pci(page, rid))
|
||||
if (!_env.pd().assign_pci(page, rid))
|
||||
Genode::error("assignment of PCI device ", Rid(rid), " failed ",
|
||||
"phys=", Genode::Hex(ds_client.phys_addr()), " "
|
||||
"virt=", Genode::Hex(page));
|
||||
@ -190,7 +190,7 @@ struct Main
|
||||
|
||||
Expanding_region_map_client rm { env };
|
||||
|
||||
Platform::Device_pd_component pd_component { rm };
|
||||
Platform::Device_pd_component pd_component { rm, env };
|
||||
|
||||
Genode::Static_root<Platform::Device_pd> root { env.ep().manage(pd_component) };
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
namespace Platform {
|
||||
class Irq_component;
|
||||
class Irq_allocator;
|
||||
class Irq_thread;
|
||||
}
|
||||
|
||||
|
||||
@ -32,9 +31,9 @@ using Genode::size_t;
|
||||
using Genode::addr_t;
|
||||
|
||||
/**
|
||||
* A simple range allocator implementation used by the Irq_proxy
|
||||
* A simple allocator implementation used by the Irq_proxy
|
||||
*/
|
||||
class Platform::Irq_allocator : public Genode::Range_allocator
|
||||
class Platform::Irq_allocator
|
||||
{
|
||||
private:
|
||||
|
||||
@ -64,76 +63,13 @@ class Platform::Irq_allocator : public Genode::Range_allocator
|
||||
|
||||
void free_msi(unsigned msi) { _msi.free(msi); }
|
||||
|
||||
Alloc_return alloc_addr(size_t size, addr_t addr) override
|
||||
bool alloc_irq(addr_t addr)
|
||||
{
|
||||
try {
|
||||
_legacy.set(addr, size);
|
||||
return Alloc_return::OK;
|
||||
_legacy.set(addr, 1);
|
||||
return true;
|
||||
} catch (...) {
|
||||
return Alloc_return::RANGE_CONFLICT;
|
||||
}
|
||||
}
|
||||
|
||||
/* unused methods */
|
||||
int remove_range(addr_t, size_t) override { return 0; }
|
||||
int add_range(addr_t, size_t) override { return 0; }
|
||||
bool valid_addr(addr_t) const override { return false; }
|
||||
size_t avail() const override { return 0; }
|
||||
bool alloc(size_t, void **) override { return false; }
|
||||
void free(void *) override { }
|
||||
void free(void *, size_t) override { }
|
||||
size_t overhead(size_t) const override { return 0; }
|
||||
bool need_size_for_free() const override { return 0; }
|
||||
|
||||
Alloc_return alloc_aligned(size_t, void **, int, addr_t, addr_t) override {
|
||||
return Alloc_return::RANGE_CONFLICT; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Required by Irq_proxy if we would like to have a thread per IRQ,
|
||||
* which we don't want to in the platform driver - one thread is sufficient.
|
||||
*/
|
||||
class NoThread
|
||||
{
|
||||
public:
|
||||
|
||||
NoThread(const char *) { }
|
||||
|
||||
void start(void) { }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Thread waiting for signals caused by IRQs
|
||||
*/
|
||||
class Platform::Irq_thread : public Genode::Thread_deprecated<4096>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Signal_receiver _sig_rec;
|
||||
|
||||
public:
|
||||
|
||||
Irq_thread() : Thread_deprecated<4096>("irq_sig_recv") { start(); }
|
||||
|
||||
Genode::Signal_receiver & sig_rec() { return _sig_rec; }
|
||||
|
||||
void entry() {
|
||||
|
||||
typedef Genode::Signal_dispatcher_base Sdb;
|
||||
|
||||
while (1) {
|
||||
Genode::Signal sig = _sig_rec.wait_for_signal();
|
||||
|
||||
Sdb *dispatcher = dynamic_cast<Sdb *>(sig.context());
|
||||
|
||||
if (!dispatcher) {
|
||||
Genode::error("dispatcher missing for signal ",
|
||||
sig.context(), " ", sig.num());
|
||||
continue;
|
||||
}
|
||||
dispatcher->dispatch(sig.num());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -144,20 +80,17 @@ class Platform::Irq_thread : public Genode::Thread_deprecated<4096>
|
||||
* for Genode signals of all hardware IRQs.
|
||||
*/
|
||||
static Platform::Irq_allocator irq_alloc;
|
||||
static Platform::Irq_thread irq_thread;
|
||||
|
||||
|
||||
/**
|
||||
* Irq_proxy interface implementation
|
||||
*/
|
||||
typedef Genode::Irq_proxy<NoThread> Proxy;
|
||||
|
||||
class Platform::Irq_component : public Proxy
|
||||
class Platform::Irq_component : public Platform::Irq_proxy
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Irq_connection _irq;
|
||||
Genode::Signal_dispatcher<Platform::Irq_component> _irq_dispatcher;
|
||||
Genode::Signal_handler<Platform::Irq_component> _irq_dispatcher;
|
||||
|
||||
bool _associated;
|
||||
|
||||
@ -178,11 +111,8 @@ class Platform::Irq_component : public Proxy
|
||||
_irq.ack_irq();
|
||||
}
|
||||
|
||||
bool _associate() { return _associated; }
|
||||
void _wait_for_irq() { }
|
||||
|
||||
virtual bool remove_sharer(Genode::Irq_sigh *s) override {
|
||||
if (!Proxy::remove_sharer(s))
|
||||
virtual bool remove_sharer(Platform::Irq_sigh *s) override {
|
||||
if (!Irq_proxy::remove_sharer(s))
|
||||
return false;
|
||||
|
||||
/* De-associate handler. */
|
||||
@ -193,15 +123,42 @@ class Platform::Irq_component : public Proxy
|
||||
|
||||
public:
|
||||
|
||||
Irq_component(unsigned gsi, Genode::Irq_session::Trigger trigger,
|
||||
Irq_component(Genode::Env &env, unsigned gsi,
|
||||
Genode::Irq_session::Trigger trigger,
|
||||
Genode::Irq_session::Polarity polarity)
|
||||
:
|
||||
Proxy(gsi),
|
||||
_irq(gsi, trigger, polarity),
|
||||
_irq_dispatcher(irq_thread.sig_rec(), *this,
|
||||
&::Proxy::notify_about_irq),
|
||||
Irq_proxy(gsi),
|
||||
_irq(env, gsi, trigger, polarity),
|
||||
_irq_dispatcher(env.ep(), *this, &Platform::Irq_proxy::notify_about_irq),
|
||||
_associated(false)
|
||||
{ }
|
||||
|
||||
static Irq_component *get_irq_proxy(unsigned irq_number,
|
||||
Irq_allocator *irq_alloc = nullptr,
|
||||
Genode::Irq_session::Trigger trigger = Genode::Irq_session::TRIGGER_UNCHANGED,
|
||||
Genode::Irq_session::Polarity polarity = Genode::Irq_session::POLARITY_UNCHANGED,
|
||||
Genode::Env *env = nullptr,
|
||||
Genode::Allocator *heap = nullptr)
|
||||
{
|
||||
static Genode::List<Irq_proxy> proxies;
|
||||
static Genode::Lock proxies_lock;
|
||||
|
||||
Genode::Lock::Guard lock_guard(proxies_lock);
|
||||
|
||||
/* lookup proxy in database */
|
||||
for (Irq_proxy *p = proxies.first(); p; p = p->next())
|
||||
if (p->irq_number() == irq_number)
|
||||
return static_cast<Irq_component *>(p);
|
||||
|
||||
/* try to create proxy */
|
||||
if (!irq_alloc || !env || !heap || !irq_alloc->alloc_irq(irq_number))
|
||||
return 0;
|
||||
|
||||
Irq_component *new_proxy = new (heap) Irq_component(*env, irq_number, trigger,
|
||||
polarity);
|
||||
proxies.insert(new_proxy);
|
||||
return new_proxy;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -218,7 +175,7 @@ void Platform::Irq_session_component::ack_irq()
|
||||
}
|
||||
|
||||
/* shared irq handling */
|
||||
Irq_component *irq_obj = Proxy::get_irq_proxy<Irq_component>(_gsi);
|
||||
Irq_component *irq_obj = Irq_component::get_irq_proxy(_gsi);
|
||||
if (!irq_obj) {
|
||||
Genode::error("expected to find IRQ proxy for IRQ ", Genode::Hex(_gsi));
|
||||
return;
|
||||
@ -230,7 +187,9 @@ void Platform::Irq_session_component::ack_irq()
|
||||
|
||||
|
||||
Platform::Irq_session_component::Irq_session_component(unsigned irq,
|
||||
addr_t pci_config_space)
|
||||
addr_t pci_config_space,
|
||||
Genode::Env &env,
|
||||
Genode::Allocator &heap)
|
||||
:
|
||||
_gsi(irq)
|
||||
{
|
||||
@ -245,7 +204,7 @@ Platform::Irq_session_component::Irq_session_component(unsigned irq,
|
||||
try {
|
||||
using namespace Genode;
|
||||
|
||||
_irq_conn.construct(msi, Irq_session::TRIGGER_UNCHANGED,
|
||||
_irq_conn.construct(env, msi, Irq_session::TRIGGER_UNCHANGED,
|
||||
Irq_session::POLARITY_UNCHANGED,
|
||||
pci_config_space);
|
||||
|
||||
@ -273,8 +232,8 @@ Platform::Irq_session_component::Irq_session_component(unsigned irq,
|
||||
|
||||
try {
|
||||
/* check if shared IRQ object was used before */
|
||||
if (Proxy::get_irq_proxy<Irq_component>(_gsi, &irq_alloc, trigger,
|
||||
polarity))
|
||||
if (Irq_component::get_irq_proxy(_gsi, &irq_alloc, trigger,
|
||||
polarity, &env, &heap))
|
||||
return;
|
||||
} catch (Genode::Parent::Service_denied) { }
|
||||
|
||||
@ -292,7 +251,7 @@ Platform::Irq_session_component::~Irq_session_component()
|
||||
}
|
||||
|
||||
/* shared irq handling */
|
||||
Irq_component *irq_obj = Proxy::get_irq_proxy<Irq_component>(_gsi);
|
||||
Irq_component *irq_obj = Irq_component::get_irq_proxy(_gsi);
|
||||
if (!irq_obj) return;
|
||||
|
||||
if (_irq_sigh.valid())
|
||||
@ -309,7 +268,7 @@ void Platform::Irq_session_component::sigh(Genode::Signal_context_capability sig
|
||||
}
|
||||
|
||||
/* shared irq handling */
|
||||
Irq_component *irq_obj = Proxy::get_irq_proxy<Irq_component>(_gsi);
|
||||
Irq_component *irq_obj = Irq_component::get_irq_proxy(_gsi);
|
||||
if (!irq_obj) {
|
||||
Genode::error("signal handler got not registered - irq object unavailable");
|
||||
return;
|
||||
|
@ -34,7 +34,7 @@ class Platform::Irq_session_component : public Genode::Rpc_object<Genode::Irq_se
|
||||
private:
|
||||
|
||||
unsigned _gsi;
|
||||
Genode::Irq_sigh _irq_sigh;
|
||||
Platform::Irq_sigh _irq_sigh;
|
||||
Genode::Irq_session::Info _msi_info;
|
||||
|
||||
Genode::Constructible<Genode::Irq_connection> _irq_conn;
|
||||
@ -43,7 +43,8 @@ class Platform::Irq_session_component : public Genode::Rpc_object<Genode::Irq_se
|
||||
|
||||
enum { INVALID_IRQ = 0xffU };
|
||||
|
||||
Irq_session_component(unsigned, Genode::addr_t);
|
||||
Irq_session_component(unsigned, Genode::addr_t, Genode::Env &,
|
||||
Genode::Allocator &heap);
|
||||
~Irq_session_component();
|
||||
|
||||
bool msi()
|
||||
|
@ -15,23 +15,20 @@
|
||||
#ifndef _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_
|
||||
#define _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_
|
||||
|
||||
#include <base/env.h>
|
||||
|
||||
|
||||
namespace Genode {
|
||||
namespace Platform {
|
||||
class Irq_sigh;
|
||||
template <typename THREAD> class Irq_proxy;
|
||||
class Irq_proxy;
|
||||
}
|
||||
|
||||
|
||||
class Genode::Irq_sigh : public Genode::Signal_context_capability,
|
||||
public Genode::List<Genode::Irq_sigh>::Element
|
||||
class Platform::Irq_sigh : public Genode::Signal_context_capability,
|
||||
public Genode::List<Platform::Irq_sigh>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
inline Irq_sigh * operator= (const Signal_context_capability &cap)
|
||||
inline Irq_sigh * operator= (const Genode::Signal_context_capability &cap)
|
||||
{
|
||||
Signal_context_capability::operator=(cap);
|
||||
Genode::Signal_context_capability::operator=(cap);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -47,121 +44,37 @@ class Genode::Irq_sigh : public Genode::Signal_context_capability,
|
||||
*
|
||||
* XXX resources are not accounted as the interrupt is shared
|
||||
*/
|
||||
template <typename THREAD>
|
||||
class Genode::Irq_proxy : public THREAD,
|
||||
public Genode::List<Genode::Irq_proxy<THREAD> >::Element
|
||||
class Platform::Irq_proxy : public Genode::List<Platform::Irq_proxy>::Element
|
||||
{
|
||||
protected:
|
||||
|
||||
char _name[32];
|
||||
Lock _startup_lock;
|
||||
|
||||
unsigned _irq_number;
|
||||
|
||||
Lock _mutex; /* protects this object */
|
||||
Genode::Lock _mutex; /* protects this object */
|
||||
int _num_sharers; /* number of clients sharing this IRQ */
|
||||
Semaphore _sleep; /* wake me up if aspired blockers return */
|
||||
List<Irq_sigh> _sigh_list;
|
||||
Genode::List<Irq_sigh> _sigh_list;
|
||||
int _num_acknowledgers; /* number of currently blocked clients */
|
||||
bool _woken_up; /* client decided to wake me up -
|
||||
this prevents multiple wakeups
|
||||
to happen during initialization */
|
||||
|
||||
|
||||
/***************
|
||||
** Interface **
|
||||
***************/
|
||||
|
||||
/**
|
||||
* Request interrupt
|
||||
*
|
||||
* \return true on success
|
||||
*/
|
||||
virtual bool _associate() = 0;
|
||||
|
||||
/**
|
||||
* Wait for associated interrupt
|
||||
*/
|
||||
virtual void _wait_for_irq() = 0;
|
||||
|
||||
/**
|
||||
* Acknowledge interrupt
|
||||
*/
|
||||
virtual void _ack_irq() = 0;
|
||||
|
||||
/********************
|
||||
** Implementation **
|
||||
********************/
|
||||
|
||||
const char *_construct_name(unsigned irq_number)
|
||||
{
|
||||
snprintf(_name, sizeof(_name), "irqproxy%02x", irq_number);
|
||||
return _name;
|
||||
}
|
||||
|
||||
void _loop()
|
||||
{
|
||||
/* wait for first blocker */
|
||||
_sleep.down();
|
||||
|
||||
while (1) {
|
||||
_wait_for_irq();
|
||||
|
||||
/* notify all */
|
||||
notify_about_irq(1);
|
||||
|
||||
/*
|
||||
* We must wait for all clients to ack their interrupt,
|
||||
* otherwise level-triggered interrupts will occur immediately
|
||||
* after acknowledgement. That's an inherent security problem
|
||||
* with shared IRQs and induces problems with dynamic driver
|
||||
* load and unload.
|
||||
*/
|
||||
_sleep.down();
|
||||
|
||||
/* acknowledge previous interrupt */
|
||||
_ack_irq();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start this thread, should be called externally from derived class
|
||||
*/
|
||||
virtual void _start()
|
||||
{
|
||||
THREAD::start();
|
||||
_startup_lock.lock();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Irq_proxy(unsigned irq_number)
|
||||
:
|
||||
THREAD(_construct_name(irq_number)),
|
||||
_startup_lock(Lock::LOCKED), _irq_number(irq_number),
|
||||
_mutex(Lock::UNLOCKED), _num_sharers(0), _num_acknowledgers(0), _woken_up(false)
|
||||
_irq_number(irq_number),
|
||||
_mutex(Genode::Lock::UNLOCKED), _num_sharers(0),
|
||||
_num_acknowledgers(0), _woken_up(false)
|
||||
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Thread interface
|
||||
*/
|
||||
void entry()
|
||||
{
|
||||
bool const associate_suceeded = _associate();
|
||||
|
||||
_startup_lock.unlock();
|
||||
|
||||
if (associate_suceeded)
|
||||
_loop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Acknowledgements of clients
|
||||
*/
|
||||
virtual bool ack_irq()
|
||||
{
|
||||
Lock::Guard lock_guard(_mutex);
|
||||
Genode::Lock::Guard lock_guard(_mutex);
|
||||
|
||||
_num_acknowledgers++;
|
||||
|
||||
@ -170,7 +83,6 @@ class Genode::Irq_proxy : public THREAD,
|
||||
* before and this client is the last aspired acknowledger.
|
||||
*/
|
||||
if (!_woken_up && _num_acknowledgers == _num_sharers) {
|
||||
_sleep.up();
|
||||
_woken_up = true;
|
||||
}
|
||||
|
||||
@ -180,9 +92,9 @@ class Genode::Irq_proxy : public THREAD,
|
||||
/**
|
||||
* Notify all clients about irq
|
||||
*/
|
||||
void notify_about_irq(unsigned)
|
||||
void notify_about_irq()
|
||||
{
|
||||
Lock::Guard lock_guard(_mutex);
|
||||
Genode::Lock::Guard lock_guard(_mutex);
|
||||
|
||||
/* reset acknowledger state */
|
||||
_num_acknowledgers = 0;
|
||||
@ -197,7 +109,7 @@ class Genode::Irq_proxy : public THREAD,
|
||||
|
||||
virtual bool add_sharer(Irq_sigh *s)
|
||||
{
|
||||
Lock::Guard lock_guard(_mutex);
|
||||
Genode::Lock::Guard lock_guard(_mutex);
|
||||
|
||||
++_num_sharers;
|
||||
_sigh_list.insert(s);
|
||||
@ -207,7 +119,7 @@ class Genode::Irq_proxy : public THREAD,
|
||||
|
||||
virtual bool remove_sharer(Irq_sigh *s)
|
||||
{
|
||||
Lock::Guard lock_guard(_mutex);
|
||||
Genode::Lock::Guard lock_guard(_mutex);
|
||||
|
||||
_sigh_list.remove(s);
|
||||
--_num_sharers;
|
||||
@ -216,38 +128,11 @@ class Genode::Irq_proxy : public THREAD,
|
||||
return _num_sharers == 0;
|
||||
|
||||
if (_num_acknowledgers == _num_sharers) {
|
||||
_sleep.up();
|
||||
_woken_up = true;
|
||||
}
|
||||
|
||||
return _num_sharers == 0;
|
||||
}
|
||||
|
||||
template <typename PROXY>
|
||||
static PROXY *get_irq_proxy(unsigned irq_number,
|
||||
Range_allocator *irq_alloc = 0,
|
||||
Genode::Irq_session::Trigger trigger = Genode::Irq_session::TRIGGER_UNCHANGED,
|
||||
Genode::Irq_session::Polarity polarity = Genode::Irq_session::POLARITY_UNCHANGED)
|
||||
{
|
||||
static List<Irq_proxy> proxies;
|
||||
static Lock proxies_lock;
|
||||
|
||||
Lock::Guard lock_guard(proxies_lock);
|
||||
|
||||
/* lookup proxy in database */
|
||||
for (Irq_proxy *p = proxies.first(); p; p = p->next())
|
||||
if (p->irq_number() == irq_number)
|
||||
return static_cast<PROXY *>(p);
|
||||
|
||||
/* try to create proxy */
|
||||
if (!irq_alloc || irq_alloc->alloc_addr(1, irq_number).error())
|
||||
return 0;
|
||||
|
||||
PROXY *new_proxy = new (env()->heap()) PROXY(irq_number, trigger,
|
||||
polarity);
|
||||
proxies.insert(new_proxy);
|
||||
return new_proxy;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_ */
|
||||
|
@ -11,13 +11,12 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/component.h>
|
||||
#include <base/env.h>
|
||||
|
||||
#include <util/reconstructible.h>
|
||||
|
||||
#include <os/attached_rom_dataspace.h>
|
||||
|
||||
#include "pci_session_component.h"
|
||||
#include "pci_device_config.h"
|
||||
#include "device_pd.h"
|
||||
@ -119,15 +118,15 @@ struct Platform::Main
|
||||
|
||||
if (_system_rom) {
|
||||
/* wait for system state changes, e.g. reset and acpi_ready */
|
||||
system_state.construct("system");
|
||||
system_state.construct(env, "system");
|
||||
system_state->sigh(_system_report);
|
||||
acpi_ready.construct("acpi_ready");
|
||||
acpi_ready.construct(env, "acpi_ready");
|
||||
acpi_ready->sigh(_system_report);
|
||||
}
|
||||
|
||||
if (wait_for_acpi == "yes") {
|
||||
/* for ACPI support, wait for the first valid acpi report */
|
||||
acpi_rom.construct("acpi");
|
||||
acpi_rom.construct(env, "acpi");
|
||||
acpi_rom->sigh(_acpi_report);
|
||||
/* check if already valid */
|
||||
acpi_update();
|
||||
|
@ -36,12 +36,14 @@ class Nonpci::Ps2 : public Platform::Device_component
|
||||
|
||||
public:
|
||||
|
||||
Ps2(Genode::Rpc_entrypoint &ep, Platform::Session_component &session)
|
||||
Ps2(Genode::Env &env, Platform::Session_component &session,
|
||||
Genode::Allocator &heap_for_irq)
|
||||
:
|
||||
Platform::Device_component(ep, session, IRQ_KEYBOARD),
|
||||
_ep(ep),
|
||||
_irq_mouse(IRQ_MOUSE, ~0UL),
|
||||
_data(REG_DATA, ACCESS_WIDTH), _status(REG_STATUS, ACCESS_WIDTH)
|
||||
Platform::Device_component(env, session, IRQ_KEYBOARD, heap_for_irq),
|
||||
_ep(env.ep().rpc_ep()),
|
||||
_irq_mouse(IRQ_MOUSE, ~0UL, env, heap_for_irq),
|
||||
_data(env, REG_DATA, ACCESS_WIDTH),
|
||||
_status(env, REG_STATUS, ACCESS_WIDTH)
|
||||
{
|
||||
_ep.manage(&_irq_mouse);
|
||||
}
|
||||
@ -97,10 +99,11 @@ class Nonpci::Pit : public Platform::Device_component
|
||||
|
||||
public:
|
||||
|
||||
Pit(Genode::Rpc_entrypoint &ep, Platform::Session_component &session)
|
||||
Pit(Genode::Env &env, Platform::Session_component &session,
|
||||
Genode::Allocator &heap_for_irq)
|
||||
:
|
||||
Platform::Device_component(ep, session, IRQ_PIT),
|
||||
_ports(PIT_PORT, PORTS_WIDTH)
|
||||
Platform::Device_component(env, session, IRQ_PIT, heap_for_irq),
|
||||
_ports(env, PIT_PORT, PORTS_WIDTH)
|
||||
{ }
|
||||
|
||||
Genode::Io_port_session_capability io_port(Genode::uint8_t io_port) override
|
||||
@ -147,17 +150,17 @@ Platform::Device_capability Platform::Session_component::device(String const &na
|
||||
|
||||
switch(devices_i) {
|
||||
case 0:
|
||||
dev = new (_md_alloc) Nonpci::Ps2(_ep, *this);
|
||||
dev = new (_md_alloc) Nonpci::Ps2(_env, *this, _global_heap);
|
||||
break;
|
||||
case 1:
|
||||
dev = new (_md_alloc) Nonpci::Pit(_ep, *this);
|
||||
dev = new (_md_alloc) Nonpci::Pit(_env, *this, _global_heap);
|
||||
break;
|
||||
default:
|
||||
return Device_capability();
|
||||
}
|
||||
|
||||
_device_list.insert(dev);
|
||||
return _ep.manage(dev);
|
||||
return _env.ep().rpc_ep().manage(dev);
|
||||
} catch (Genode::Allocator::Out_of_memory) {
|
||||
throw Out_of_metadata();
|
||||
} catch (Genode::Parent::Service_denied) {
|
||||
|
@ -24,6 +24,8 @@ namespace Platform {
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Env &_env;
|
||||
|
||||
enum { REG_ADDR = 0xcf8, REG_DATA = 0xcfc, REG_SIZE = 4 };
|
||||
|
||||
/**
|
||||
@ -47,7 +49,7 @@ namespace Platform {
|
||||
* Once created, each I/O-port session persists until
|
||||
* the PCI driver gets killed by its parent.
|
||||
*/
|
||||
static Genode::Io_port_connection io_port(port, REG_SIZE);
|
||||
static Genode::Io_port_connection io_port(_env, port, REG_SIZE);
|
||||
return &io_port;
|
||||
}
|
||||
|
||||
@ -79,6 +81,8 @@ namespace Platform {
|
||||
|
||||
public:
|
||||
|
||||
Config_access(Genode::Env &env) : _env(env) { }
|
||||
|
||||
/**
|
||||
* Read value from config space of specified device/function
|
||||
*
|
||||
|
@ -32,7 +32,7 @@ Genode::Io_port_session_capability Platform::Device_component::io_port(Genode::u
|
||||
return _io_port_conn[v_id]->cap();
|
||||
|
||||
try {
|
||||
_io_port_conn[v_id] = new (_slab_ioport) Genode::Io_port_connection(res.base(), res.size());
|
||||
_io_port_conn[v_id] = new (_slab_ioport) Genode::Io_port_connection(_env, res.base(), res.size());
|
||||
return _io_port_conn[v_id]->cap();
|
||||
} catch (...) {
|
||||
return Genode::Io_port_session_capability();
|
||||
@ -68,7 +68,8 @@ Genode::Io_mem_session_capability Platform::Device_component::io_mem(Genode::uin
|
||||
|
||||
try {
|
||||
bool const wc = caching == Genode::Cache_attribute::WRITE_COMBINED;
|
||||
Io_mem * io_mem = new (_slab_iomem) Io_mem(res.base() + offset,
|
||||
Io_mem * io_mem = new (_slab_iomem) Io_mem(_env,
|
||||
res.base() + offset,
|
||||
res_size, wc);
|
||||
_io_mem[i].insert(io_mem);
|
||||
return io_mem->cap();
|
||||
@ -144,16 +145,19 @@ Genode::Irq_session_capability Platform::Device_component::irq(Genode::uint8_t i
|
||||
if (!_device_config.valid()) {
|
||||
/* Non PCI devices */
|
||||
_irq_session = construct_at<Irq_session_component>(_mem_irq_component,
|
||||
_irq_line, ~0UL);
|
||||
_irq_line, ~0UL,
|
||||
_env,
|
||||
_global_heap);
|
||||
|
||||
_ep.manage(_irq_session);
|
||||
_env.ep().rpc_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);
|
||||
(!_session.msi_usage() || !_msi_cap()) ? ~0UL : _config_space,
|
||||
_env, _global_heap);
|
||||
_env.ep().rpc_ep().manage(_irq_session);
|
||||
|
||||
Genode::uint16_t msi_cap = _msi_cap();
|
||||
|
||||
|
@ -34,22 +34,25 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Env &_env;
|
||||
Device_config _device_config;
|
||||
Genode::addr_t _config_space;
|
||||
Config_access _config_access;
|
||||
Genode::Rpc_entrypoint &_ep;
|
||||
Config_access _config_access = { _env };
|
||||
Platform::Session_component &_session;
|
||||
unsigned short _irq_line;
|
||||
Irq_session_component *_irq_session = nullptr;
|
||||
|
||||
Genode::Constructible<Genode::Io_mem_connection> _io_mem_config_extended;
|
||||
|
||||
Genode::Allocator &_global_heap;
|
||||
|
||||
class Io_mem : public Genode::Io_mem_connection,
|
||||
public Genode::List<Io_mem>::Element
|
||||
{
|
||||
public:
|
||||
Io_mem (Genode::addr_t base, Genode::size_t size, bool wc)
|
||||
: Genode::Io_mem_connection(base, size, wc) { }
|
||||
Io_mem (Genode::Env &env, Genode::addr_t base,
|
||||
Genode::size_t size, bool wc)
|
||||
: Genode::Io_mem_connection(env, base, size, wc) { }
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -182,15 +185,18 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Device_component(Device_config device_config, Genode::addr_t addr,
|
||||
Genode::Rpc_entrypoint &ep,
|
||||
Device_component(Genode::Env &env,
|
||||
Device_config device_config, Genode::addr_t addr,
|
||||
Platform::Session_component &session,
|
||||
Genode::Allocator &md_alloc)
|
||||
Genode::Allocator &md_alloc,
|
||||
Genode::Allocator &global_heap)
|
||||
:
|
||||
_env(env),
|
||||
_device_config(device_config), _config_space(addr),
|
||||
_ep(ep), _session(session),
|
||||
_session(session),
|
||||
_irq_line(_device_config.read(&_config_access, PCI_IRQ_LINE,
|
||||
Platform::Device::ACCESS_8BIT)),
|
||||
_global_heap(global_heap),
|
||||
_slab_ioport(&md_alloc, &_slab_ioport_block_data),
|
||||
_slab_iomem(&md_alloc, &_slab_iomem_block_data)
|
||||
{
|
||||
@ -204,12 +210,15 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
/**
|
||||
* Constructor for non PCI devices
|
||||
*/
|
||||
Device_component(Genode::Rpc_entrypoint &ep,
|
||||
Platform::Session_component &session, unsigned irq)
|
||||
Device_component(Genode::Env &env,
|
||||
Platform::Session_component &session, unsigned irq,
|
||||
Genode::Allocator &global_heap)
|
||||
:
|
||||
_env(env),
|
||||
_config_space(~0UL),
|
||||
_ep(ep), _session(session),
|
||||
_session(session),
|
||||
_irq_line(irq),
|
||||
_global_heap(global_heap),
|
||||
_slab_ioport(nullptr, &_slab_ioport_block_data),
|
||||
_slab_iomem(nullptr, &_slab_iomem_block_data)
|
||||
{
|
||||
@ -223,7 +232,7 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
~Device_component()
|
||||
{
|
||||
if (_irq_session) {
|
||||
_ep.dissolve(_irq_session);
|
||||
_env.ep().rpc_ep().dissolve(_irq_session);
|
||||
_irq_session->~Irq_session();
|
||||
}
|
||||
|
||||
@ -254,7 +263,7 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
||||
|
||||
if (!_io_mem_config_extended.constructed()) {
|
||||
try {
|
||||
_io_mem_config_extended.construct(_config_space, 0x1000);
|
||||
_io_mem_config_extended.construct(_env, _config_space, 0x1000);
|
||||
} catch (...) {
|
||||
_config_space = ~0UL;
|
||||
}
|
||||
|
@ -72,10 +72,11 @@ struct Platform::Device_pd_connection : Genode::Connection<Device_pd>, Device_pd
|
||||
struct Platform::Device_pd_component : Genode::Rpc_object<Device_pd,
|
||||
Device_pd_component>
|
||||
{
|
||||
Genode::Env &_env;
|
||||
Genode::Region_map &_address_space;
|
||||
|
||||
Device_pd_component(Genode::Region_map &address_space)
|
||||
: _address_space(address_space) { }
|
||||
Device_pd_component(Genode::Region_map &address_space, Genode::Env &env)
|
||||
: _env(env), _address_space(address_space) { }
|
||||
|
||||
void attach_dma_mem(Genode::Dataspace_capability);
|
||||
void assign_pci(Genode::Io_mem_dataspace_capability, Genode::uint16_t);
|
||||
|
@ -37,12 +37,13 @@
|
||||
#include "device_pd.h"
|
||||
|
||||
namespace Platform {
|
||||
bool bus_valid(int bus = 0);
|
||||
unsigned short bridge_bdf(unsigned char bus);
|
||||
|
||||
class Pci_buses;
|
||||
class Ram_dataspace;
|
||||
class Rmrr;
|
||||
class Root;
|
||||
class Ram_dataspace;
|
||||
class Session_component;
|
||||
}
|
||||
|
||||
class Platform::Ram_dataspace : public Genode::List<Ram_dataspace>::Element {
|
||||
@ -92,7 +93,8 @@ class Platform::Rmrr : public Genode::List<Platform::Rmrr>::Element
|
||||
: _start(start), _end(end)
|
||||
{ }
|
||||
|
||||
Genode::Io_mem_dataspace_capability match(Device_config config)
|
||||
Genode::Io_mem_dataspace_capability match(Genode::Env &env,
|
||||
Device_config config)
|
||||
{
|
||||
Genode::uint8_t bus = config.bus_number();
|
||||
Genode::uint8_t device = config.device_number();
|
||||
@ -105,7 +107,7 @@ class Platform::Rmrr : public Genode::List<Platform::Rmrr>::Element
|
||||
if (_cap.valid())
|
||||
return _cap;
|
||||
|
||||
_io_mem.construct(_start, _end - _start + 1);
|
||||
_io_mem.construct(env, _start, _end - _start + 1);
|
||||
_cap = _io_mem->dataspace();
|
||||
return _cap;
|
||||
}
|
||||
@ -122,13 +124,79 @@ class Platform::Rmrr : public Genode::List<Platform::Rmrr>::Element
|
||||
};
|
||||
|
||||
|
||||
namespace Platform { class Session_component; }
|
||||
class Platform::Pci_buses
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Bit_array<Device_config::MAX_BUSES> _valid;
|
||||
|
||||
void scan_bus(Config_access &config_access, Genode::Allocator &heap,
|
||||
unsigned char bus = 0);
|
||||
|
||||
bool _bus_valid(int bus)
|
||||
{
|
||||
if (bus >= Device_config::MAX_BUSES)
|
||||
return false;
|
||||
|
||||
return _valid.get(bus, 1);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Pci_buses(Genode::Env &env, Genode::Allocator &heap)
|
||||
{
|
||||
Config_access c(env);
|
||||
scan_bus(c, heap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan PCI buses for a device
|
||||
*
|
||||
* \param bus start scanning at bus number
|
||||
* \param device start scanning at device number
|
||||
* \param function start scanning at function number
|
||||
* \param out_device_config device config information of the
|
||||
* found device
|
||||
* \param config_access interface for accessing the PCI
|
||||
* configuration
|
||||
* space
|
||||
*
|
||||
* \retval true device was found
|
||||
* \retval false no device was found
|
||||
*/
|
||||
bool find_next(int bus, int device, int function,
|
||||
Device_config *out_device_config,
|
||||
Config_access *config_access)
|
||||
{
|
||||
for (; bus < Device_config::MAX_BUSES; bus++) {
|
||||
if (!_bus_valid(bus))
|
||||
continue;
|
||||
|
||||
for (; device < Device_config::MAX_DEVICES; device++) {
|
||||
for (; function < Device_config::MAX_FUNCTIONS; function++) {
|
||||
|
||||
/* read config space */
|
||||
Device_config config(bus, device, function, config_access);
|
||||
|
||||
if (config.valid()) {
|
||||
*out_device_config = config;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
function = 0; /* init value for next device */
|
||||
}
|
||||
device = 0; /* init value for next bus */
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Rpc_entrypoint &_ep;
|
||||
Genode::Env &_env;
|
||||
Genode::Rpc_entrypoint &_device_pd_ep;
|
||||
Genode::Ram_session_guard _env_ram;
|
||||
Genode::Ram_session_capability _env_ram_cap;
|
||||
@ -137,6 +205,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
Genode::Session_label const _label;
|
||||
Genode::Session_policy const _policy { _label };
|
||||
Genode::List<Device_component> _device_list;
|
||||
Platform::Pci_buses &_pci_bus;
|
||||
Genode::Heap &_global_heap;
|
||||
bool _no_device_pd = false;
|
||||
|
||||
/**
|
||||
@ -167,8 +237,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
*
|
||||
* Restrict physical address to 3G on 32bit, 4G on 64bit
|
||||
*/
|
||||
Genode::Ram_connection _ram {
|
||||
_label.string(), 0, (sizeof(void *) == 4) ? 0xc0000000UL : 0x100000000UL };
|
||||
Genode::Ram_connection _ram { _env, _label.string(), 0,
|
||||
(sizeof(void *) == 4) ? 0xc0000000UL : 0x100000000UL };
|
||||
|
||||
/*
|
||||
* Associate session RAM session with platform_drv _ram session and
|
||||
@ -319,46 +389,6 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
static Genode::Bit_array<MAX_PCI_DEVICES> bdf_in_use;
|
||||
|
||||
|
||||
/**
|
||||
* Scan PCI buses for a device
|
||||
*
|
||||
* \param bus start scanning at bus number
|
||||
* \param device start scanning at device number
|
||||
* \param function start scanning at function number
|
||||
* \param out_device_config device config information of the
|
||||
* found device
|
||||
* \param config_access interface for accessing the PCI
|
||||
* configuration
|
||||
* space
|
||||
*
|
||||
* \retval true device was found
|
||||
* \retval false no device was found
|
||||
*/
|
||||
bool _find_next(int bus, int device, int function,
|
||||
Device_config *out_device_config,
|
||||
Config_access *config_access)
|
||||
{
|
||||
for (; bus < Device_config::MAX_BUSES; bus++) {
|
||||
if (!bus_valid(bus))
|
||||
continue;
|
||||
|
||||
for (; device < Device_config::MAX_DEVICES; device++) {
|
||||
for (; function < Device_config::MAX_FUNCTIONS; function++) {
|
||||
|
||||
/* read config space */
|
||||
Device_config config(bus, device, function, config_access);
|
||||
|
||||
if (config.valid()) {
|
||||
*out_device_config = config;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
function = 0; /* init value for next device */
|
||||
}
|
||||
device = 0; /* init value for next bus */
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* List containing extended PCI config space information
|
||||
@ -564,18 +594,20 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Session_component(Genode::Env &env,
|
||||
Genode::Rpc_entrypoint &ep,
|
||||
Session_component(Genode::Env &env,
|
||||
Genode::Rpc_entrypoint &device_pd_ep,
|
||||
Platform::Pci_buses &buses,
|
||||
Genode::Heap &global_heap,
|
||||
char const *args)
|
||||
:
|
||||
_ep(ep), _device_pd_ep(device_pd_ep),
|
||||
_env(env), _device_pd_ep(device_pd_ep),
|
||||
_env_ram(env.ram(), env.ram_session_cap(),
|
||||
Genode::Arg_string::find_arg(args, "ram_quota").long_value(0)),
|
||||
_env_ram_cap(env.ram_session_cap()),
|
||||
_local_rm(env.rm()),
|
||||
_md_alloc(_env_ram, env.rm()),
|
||||
_label(Genode::label_from_args(args))
|
||||
_label(Genode::label_from_args(args)),
|
||||
_pci_bus(buses), _global_heap(global_heap)
|
||||
{
|
||||
/* non-pci devices */
|
||||
_policy.for_each_sub_node("device", [&] (Genode::Xml_node device_node) {
|
||||
@ -689,12 +721,12 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
|
||||
static void add_config_space(Genode::uint32_t bdf_start,
|
||||
Genode::uint32_t func_count,
|
||||
Genode::addr_t base)
|
||||
Genode::addr_t base,
|
||||
Genode::Allocator &heap)
|
||||
{
|
||||
using namespace Genode;
|
||||
Config_space * space =
|
||||
new (env()->heap()) Config_space(bdf_start, func_count,
|
||||
base);
|
||||
new (heap) Config_space(bdf_start, func_count, base);
|
||||
config_space_list().insert(space);
|
||||
}
|
||||
|
||||
@ -731,7 +763,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
* Create the interface to the PCI config space.
|
||||
* This involves the creation of I/O port sessions.
|
||||
*/
|
||||
Config_access config_access;
|
||||
Config_access config_access(_env);
|
||||
|
||||
/* lookup device component for previous device */
|
||||
auto lambda = [&] (Device_component *prev)
|
||||
@ -759,8 +791,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
|
||||
while (true) {
|
||||
function += 1;
|
||||
if (!_find_next(bus, device, function, &config,
|
||||
&config_access))
|
||||
if (!_pci_bus.find_next(bus, device, function, &config,
|
||||
&config_access))
|
||||
return Device_capability();
|
||||
|
||||
/* get new bdf values */
|
||||
@ -788,8 +820,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
*/
|
||||
try {
|
||||
Device_component * dev = new (_md_alloc)
|
||||
Device_component(config, config_space, _ep, *this,
|
||||
_md_alloc);
|
||||
Device_component(_env, config, config_space, *this,
|
||||
_md_alloc, _global_heap);
|
||||
|
||||
/* if more than one driver uses the device - warn about */
|
||||
if (bdf_in_use.get(Device_config::MAX_BUSES * bus +
|
||||
@ -806,12 +838,12 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
function, 1);
|
||||
|
||||
_device_list.insert(dev);
|
||||
return _ep.manage(dev);
|
||||
return _env.ep().rpc_ep().manage(dev);
|
||||
} catch (Genode::Allocator::Out_of_memory) {
|
||||
throw Out_of_metadata();
|
||||
}
|
||||
};
|
||||
return _ep.apply(prev_device, lambda);
|
||||
return _env.ep().rpc_ep().apply(prev_device, lambda);
|
||||
}
|
||||
|
||||
void release_device(Device_capability device_cap) override
|
||||
@ -834,11 +866,11 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
Device_config::MAX_DEVICES * dev + func, 1);
|
||||
|
||||
_device_list.remove(device);
|
||||
_ep.dissolve(device);
|
||||
_env.ep().rpc_ep().dissolve(device);
|
||||
};
|
||||
|
||||
/* lookup device component for previous device */
|
||||
_ep.apply(device_cap, lambda);
|
||||
_env.ep().rpc_ep().apply(device_cap, lambda);
|
||||
|
||||
if (!device) return;
|
||||
|
||||
@ -865,7 +897,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||
_device_pd->session().assign_pci(io_mem, device->config().bdf());
|
||||
|
||||
for (Rmrr *r = Rmrr::list()->first(); r; r = r->next()) {
|
||||
Io_mem_dataspace_capability rmrr_cap = r->match(device->config());
|
||||
Io_mem_dataspace_capability rmrr_cap = r->match(_env, device->config());
|
||||
if (rmrr_cap.valid())
|
||||
_device_pd->session().attach_dma_mem(rmrr_cap);
|
||||
}
|
||||
@ -991,12 +1023,14 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
|
||||
Genode::Env &_env;
|
||||
Genode::Rpc_entrypoint _device_pd_ep;
|
||||
Genode::Heap _heap { _env.ram(), _env.rm() };
|
||||
Platform::Pci_buses _buses { _env, _heap };
|
||||
|
||||
void _parse_report_rom(const char * acpi_rom)
|
||||
void _parse_report_rom(Genode::Env &env, const char * acpi_rom)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Config_access config_access;
|
||||
Config_access config_access(env);
|
||||
|
||||
Xml_node xml_acpi(acpi_rom);
|
||||
if (!xml_acpi.has_type("acpi"))
|
||||
@ -1016,7 +1050,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
node.attribute("base").value(&base);
|
||||
|
||||
Session_component::add_config_space(bdf_start, func_count,
|
||||
base);
|
||||
base, _heap);
|
||||
}
|
||||
|
||||
if (node.has_type("irq_override")) {
|
||||
@ -1029,9 +1063,8 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
node.attribute("flags").value(&flags);
|
||||
|
||||
using Platform::Irq_override;
|
||||
Irq_override * o = new (env()->heap()) Irq_override(irq,
|
||||
gsi,
|
||||
flags);
|
||||
Irq_override * o = new (_heap) Irq_override(irq, gsi,
|
||||
flags);
|
||||
Irq_override::list()->insert(o);
|
||||
}
|
||||
|
||||
@ -1043,7 +1076,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
if (node.num_sub_nodes() == 0)
|
||||
throw 2;
|
||||
|
||||
Rmrr * rmrr = new (env()->heap()) Rmrr(mem_start, mem_end);
|
||||
Rmrr * rmrr = new (_heap) Rmrr(mem_start, mem_end);
|
||||
Rmrr::list()->insert(rmrr);
|
||||
|
||||
for (unsigned s = 0; s < node.num_sub_nodes(); s++) {
|
||||
@ -1070,8 +1103,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
Device::ACCESS_8BIT);
|
||||
}
|
||||
|
||||
rmrr->add(new (env()->heap()) Rmrr::Bdf(bus, dev,
|
||||
func));
|
||||
rmrr->add(new (_heap) Rmrr::Bdf(bus, dev, func));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1116,10 +1148,8 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
*/
|
||||
bridge_bdf = 0;
|
||||
|
||||
Irq_routing * r = new (env()->heap()) Irq_routing(gsi,
|
||||
bridge_bdf,
|
||||
device,
|
||||
device_pin);
|
||||
Irq_routing * r = new (_heap) Irq_routing(gsi, bridge_bdf,
|
||||
device, device_pin);
|
||||
Irq_routing::list()->insert(r);
|
||||
}
|
||||
}
|
||||
@ -1130,7 +1160,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
{
|
||||
try {
|
||||
return new (md_alloc())
|
||||
Session_component(_env, *ep(), _device_pd_ep, args);
|
||||
Session_component(_env, _device_pd_ep, _buses, _heap, args);
|
||||
}
|
||||
catch (Genode::Session_policy::No_policy_defined) {
|
||||
Genode::error("Invalid session request, no matching policy for ",
|
||||
@ -1164,12 +1194,9 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
_env(env),
|
||||
_device_pd_ep(&env.pd(), STACK_SIZE, "device_pd_slave")
|
||||
{
|
||||
/* enforce initial bus scan */
|
||||
bus_valid();
|
||||
|
||||
if (acpi_rom) {
|
||||
try {
|
||||
_parse_report_rom(acpi_rom);
|
||||
_parse_report_rom(env, acpi_rom);
|
||||
} catch (...) {
|
||||
Genode::error("PCI config space data could not be parsed.");
|
||||
}
|
||||
@ -1183,7 +1210,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
if (!io_port_space)
|
||||
return;
|
||||
|
||||
Config_access config_access;
|
||||
Config_access config_access(_env);
|
||||
const unsigned raw_access_size = Fadt::Gas::Access_size::get(fadt.reset_type);
|
||||
const bool reset_support = config_access.reset_support(fadt.reset_addr, raw_access_size);
|
||||
if (!reset_support)
|
||||
|
@ -33,57 +33,40 @@ unsigned short Platform::bridge_bdf(unsigned char bus)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if given PCI bus was found on initial scan
|
||||
*
|
||||
* This tremendously speeds up further scans by other drivers.
|
||||
*/
|
||||
bool Platform::bus_valid(int bus)
|
||||
void Platform::Pci_buses::scan_bus(Config_access &config_access,
|
||||
Genode::Allocator &heap, unsigned char bus)
|
||||
{
|
||||
struct Valid_buses
|
||||
{
|
||||
bool valid[Device_config::MAX_BUSES];
|
||||
for (int dev = 0; dev < Device_config::MAX_DEVICES; ++dev) {
|
||||
for (int fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) {
|
||||
|
||||
void scan_bus(Config_access &config_access, unsigned char bus = 0)
|
||||
{
|
||||
for (int dev = 0; dev < Device_config::MAX_DEVICES; ++dev) {
|
||||
for (int fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) {
|
||||
/* read config space */
|
||||
Device_config config(bus, dev, fun, &config_access);
|
||||
|
||||
/* read config space */
|
||||
Device_config config(bus, dev, fun, &config_access);
|
||||
if (!config.valid())
|
||||
continue;
|
||||
|
||||
if (!config.valid())
|
||||
continue;
|
||||
/*
|
||||
* There is at least one device on the current bus, so
|
||||
* we mark it as valid.
|
||||
*/
|
||||
if (!_valid.get(bus, 1))
|
||||
_valid.set(bus, 1);
|
||||
|
||||
/*
|
||||
* There is at least one device on the current bus, so
|
||||
* we mark it as valid.
|
||||
*/
|
||||
valid[bus] = true;
|
||||
/* scan behind bridge */
|
||||
if (config.pci_bridge()) {
|
||||
/* PCI bridge spec 3.2.5.3, 3.2.5.4 */
|
||||
unsigned char sec_bus = config.read(&config_access, 0x19,
|
||||
Device::ACCESS_8BIT);
|
||||
unsigned char sub_bus = config.read(&config_access, 0x20,
|
||||
Device::ACCESS_8BIT);
|
||||
|
||||
/* scan behind bridge */
|
||||
if (config.pci_bridge()) {
|
||||
/* PCI bridge spec 3.2.5.3, 3.2.5.4 */
|
||||
unsigned char sec_bus = config.read(&config_access,
|
||||
0x19, Device::ACCESS_8BIT);
|
||||
unsigned char sub_bus = config.read(&config_access,
|
||||
0x20, Device::ACCESS_8BIT);
|
||||
bridges()->insert(new (heap) Bridge(bus, dev, fun, sec_bus,
|
||||
sub_bus));
|
||||
|
||||
bridges()->insert(new (Genode::env()->heap()) Bridge(bus, dev, fun, sec_bus, sub_bus));
|
||||
|
||||
scan_bus(config_access, sec_bus);
|
||||
}
|
||||
}
|
||||
scan_bus(config_access, heap, sec_bus);
|
||||
}
|
||||
}
|
||||
|
||||
Valid_buses() { Config_access c; scan_bus(c); }
|
||||
};
|
||||
|
||||
static Valid_buses buses;
|
||||
|
||||
return buses.valid[bus];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user