mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
parent
df50d1b29d
commit
06e7c947bc
@ -24,7 +24,7 @@ struct Pci::Connection : Genode::Connection<Session>, Session_client
|
||||
{
|
||||
Connection()
|
||||
:
|
||||
Genode::Connection<Session>(session("ram_quota=4K")),
|
||||
Genode::Connection<Session>(session("ram_quota=12K")),
|
||||
Session_client(cap())
|
||||
{ }
|
||||
};
|
||||
|
@ -86,16 +86,20 @@ struct Pci::Session : Genode::Session
|
||||
** RPC declaration **
|
||||
*********************/
|
||||
|
||||
GENODE_RPC(Rpc_first_device, Device_capability, first_device,
|
||||
unsigned, unsigned);
|
||||
GENODE_RPC(Rpc_next_device, Device_capability, next_device,
|
||||
Device_capability, unsigned, unsigned);
|
||||
GENODE_RPC_THROW(Rpc_first_device, Device_capability, first_device,
|
||||
GENODE_TYPE_LIST(Pci::Device::Quota_exceeded),
|
||||
unsigned, unsigned);
|
||||
GENODE_RPC_THROW(Rpc_next_device, Device_capability, next_device,
|
||||
GENODE_TYPE_LIST(Pci::Device::Quota_exceeded),
|
||||
Device_capability, unsigned, unsigned);
|
||||
GENODE_RPC(Rpc_release_device, void, release_device, Device_capability);
|
||||
GENODE_RPC(Rpc_config_extended, Genode::Io_mem_dataspace_capability,
|
||||
config_extended, Device_capability);
|
||||
GENODE_RPC_THROW(Rpc_config_extended, Genode::Io_mem_dataspace_capability,
|
||||
config_extended,
|
||||
GENODE_TYPE_LIST(Pci::Device::Quota_exceeded),
|
||||
Device_capability);
|
||||
GENODE_RPC_THROW(Rpc_alloc_dma_buffer, Genode::Ram_dataspace_capability,
|
||||
alloc_dma_buffer,
|
||||
GENODE_TYPE_LIST(Genode::Ram_session::Quota_exceeded),
|
||||
GENODE_TYPE_LIST(Pci::Device::Quota_exceeded),
|
||||
Genode::size_t);
|
||||
GENODE_RPC(Rpc_free_dma_buffer, void, free_dma_buffer,
|
||||
Genode::Ram_dataspace_capability);
|
||||
|
@ -147,7 +147,11 @@ namespace Pci {
|
||||
void close(Genode::Session_capability session) {
|
||||
Genode::Root_client(_pci_provider.root()).close(session); }
|
||||
|
||||
void upgrade(Genode::Session_capability, Upgrade_args const &) { }
|
||||
void upgrade(Genode::Session_capability s, Upgrade_args const & u)
|
||||
{
|
||||
try { Genode::Root_client(_pci_provider.root()).upgrade(s, u); }
|
||||
catch (...) { throw Invalid_args(); }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -178,7 +182,7 @@ class Pci_policy : public Genode::Slave_policy, public Pci::Provider
|
||||
void _acpi_session()
|
||||
{
|
||||
Pci::Session_capability session;
|
||||
const char *args = "label=\"acpi_drv\", ram_quota=4K";
|
||||
const char *args = "label=\"acpi_drv\", ram_quota=16K";
|
||||
|
||||
try {
|
||||
using namespace Genode;
|
||||
|
@ -114,7 +114,7 @@ class Pci::Device_component : public Genode::Rpc_object<Pci::Device>,
|
||||
{
|
||||
/* return invalid resource if device is invalid */
|
||||
if (!_device_config.valid())
|
||||
Resource(0, 0);
|
||||
return Resource(0, 0);
|
||||
|
||||
return _device_config.resource(resource_id);
|
||||
}
|
||||
|
@ -56,6 +56,8 @@ namespace Pci {
|
||||
return resource_id >= 0 && resource_id < max_num;
|
||||
}
|
||||
|
||||
enum { INVALID_VENDOR = 0xffffU };
|
||||
|
||||
public:
|
||||
|
||||
enum { MAX_BUSES = 256, MAX_DEVICES = 32, MAX_FUNCTIONS = 8 };
|
||||
@ -63,7 +65,8 @@ namespace Pci {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Device_config() { }
|
||||
Device_config() : _vendor_id(INVALID_VENDOR) { }
|
||||
|
||||
Device_config(int bus, int device, int function,
|
||||
Config_access *pci_config):
|
||||
_bus(bus), _device(device), _function(function)
|
||||
@ -71,7 +74,7 @@ namespace Pci {
|
||||
_vendor_id = pci_config->read(bus, device, function, 0, Device::ACCESS_16BIT);
|
||||
|
||||
/* break here if device is invalid */
|
||||
if (_vendor_id == 0xffff)
|
||||
if (_vendor_id == INVALID_VENDOR)
|
||||
return;
|
||||
|
||||
_device_id = pci_config->read(bus, device, function, 2, Device::ACCESS_16BIT);
|
||||
@ -88,7 +91,7 @@ namespace Pci {
|
||||
*/
|
||||
if (function != 0
|
||||
&& !(pci_config->read(bus, device, 0, 0xe, Device::ACCESS_8BIT) & 0x80)) {
|
||||
_vendor_id = 0xffff;
|
||||
_vendor_id = INVALID_VENDOR;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -152,7 +155,7 @@ namespace Pci {
|
||||
/**
|
||||
* Return true if device is valid
|
||||
*/
|
||||
bool valid() { return _vendor_id != 0xffff; }
|
||||
bool valid() { return _vendor_id != INVALID_VENDOR; }
|
||||
|
||||
/**
|
||||
* Return resource description by resource ID
|
||||
|
@ -15,7 +15,10 @@
|
||||
#define _PCI_SESSION_COMPONENT_H_
|
||||
|
||||
/* base */
|
||||
#include <base/allocator_guard.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/tslab.h>
|
||||
|
||||
#include <ram_session/connection.h>
|
||||
#include <root/component.h>
|
||||
|
||||
@ -40,13 +43,14 @@ namespace Pci {
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Rpc_entrypoint *_ep;
|
||||
Genode::Allocator *_md_alloc;
|
||||
Genode::List<Device_component> _device_list;
|
||||
Device_pd_client *_child;
|
||||
Genode::Ram_connection *_ram;
|
||||
Genode::Session_label _label;
|
||||
Genode::Session_policy _policy;
|
||||
Genode::Rpc_entrypoint *_ep;
|
||||
Genode::Allocator_guard _md_alloc;
|
||||
Genode::Tslab<Device_component, 4096 - 64> _device_slab;
|
||||
Genode::List<Device_component> _device_list;
|
||||
Device_pd_client *_child;
|
||||
Genode::Ram_connection *_ram;
|
||||
Genode::Session_label _label;
|
||||
Genode::Session_policy _policy;
|
||||
|
||||
/**
|
||||
* Scan PCI buses for a device
|
||||
@ -296,7 +300,9 @@ namespace Pci {
|
||||
Genode::Ram_connection *ram,
|
||||
const char *args)
|
||||
:
|
||||
_ep(ep), _md_alloc(md_alloc),
|
||||
_ep(ep),
|
||||
_md_alloc(md_alloc, Genode::Arg_string::find_arg(args, "ram_quota").long_value(0)),
|
||||
_device_slab(&_md_alloc),
|
||||
_child(child), _ram(ram), _label(args), _policy(_label)
|
||||
{
|
||||
/* non-pci devices */
|
||||
@ -403,6 +409,10 @@ namespace Pci {
|
||||
release_device(_device_list.first()->cap());
|
||||
}
|
||||
|
||||
|
||||
void upgrade_ram_quota(long quota) { _md_alloc.upgrade(quota); }
|
||||
|
||||
|
||||
static void add_config_space(Genode::uint32_t bdf_start,
|
||||
Genode::uint32_t func_count,
|
||||
Genode::addr_t base)
|
||||
@ -484,17 +494,14 @@ namespace Pci {
|
||||
/*
|
||||
* A device was found. Create a new device component for the
|
||||
* device and return its capability.
|
||||
*
|
||||
* FIXME: check and adjust session quota
|
||||
*/
|
||||
Device_component *device_component =
|
||||
new (_md_alloc) Device_component(config, config_space, _ep, this);
|
||||
|
||||
if (!device_component)
|
||||
return Device_capability();
|
||||
|
||||
_device_list.insert(device_component);
|
||||
return _ep->manage(device_component);
|
||||
try {
|
||||
Device_component * dev = new (_device_slab) Device_component(config, config_space, _ep, this);
|
||||
_device_list.insert(dev);
|
||||
return _ep->manage(dev);
|
||||
} catch (Genode::Allocator::Out_of_memory) {
|
||||
throw Device::Quota_exceeded();
|
||||
}
|
||||
}
|
||||
|
||||
void release_device(Device_capability device_cap)
|
||||
@ -509,11 +516,14 @@ namespace Pci {
|
||||
_device_list.remove(device);
|
||||
_ep->dissolve(device);
|
||||
|
||||
/* FIXME: adjust quota */
|
||||
Genode::Io_mem_connection * io_mem = device->get_config_space();
|
||||
if (io_mem)
|
||||
destroy(_md_alloc, io_mem);
|
||||
destroy(_md_alloc, device);
|
||||
|
||||
if (device->config().valid())
|
||||
destroy(_device_slab, device);
|
||||
else
|
||||
destroy(_md_alloc, device);
|
||||
}
|
||||
|
||||
Genode::Io_mem_dataspace_capability config_extended(Device_capability device_cap)
|
||||
@ -533,6 +543,8 @@ namespace Pci {
|
||||
try {
|
||||
io_mem = new (_md_alloc) Io_mem_connection(device->config_space(),
|
||||
0x1000);
|
||||
} catch (Genode::Allocator::Out_of_memory) {
|
||||
throw Device::Quota_exceeded();
|
||||
} catch (Parent::Service_denied) {
|
||||
return Io_mem_dataspace_capability();
|
||||
}
|
||||
@ -552,17 +564,30 @@ namespace Pci {
|
||||
|
||||
Ram_capability alloc_dma_buffer(Genode::size_t size)
|
||||
{
|
||||
if (Genode::env()->ram_session()->transfer_quota(_ram->cap(),
|
||||
size))
|
||||
if (!_md_alloc.withdraw(size))
|
||||
throw Device::Quota_exceeded();
|
||||
|
||||
Genode::Ram_session * const rs = Genode::env()->ram_session();
|
||||
if (rs->transfer_quota(_ram->cap(), size)) {
|
||||
_md_alloc.upgrade(size);
|
||||
return Ram_capability();
|
||||
}
|
||||
|
||||
Ram_capability ram = _ram->alloc(size, Genode::UNCACHED);
|
||||
if (!ram.valid() || !_child)
|
||||
return ram;
|
||||
Ram_capability ram_cap;
|
||||
try {
|
||||
|
||||
_child->attach_dma_mem(ram);
|
||||
ram_cap = _ram->alloc(size, Genode::UNCACHED);
|
||||
} catch (Genode::Ram_session::Quota_exceeded) {
|
||||
_md_alloc.upgrade(size);
|
||||
return Ram_capability();
|
||||
}
|
||||
|
||||
return ram;
|
||||
if (!ram_cap.valid() || !_child)
|
||||
return ram_cap;
|
||||
|
||||
_child->attach_dma_mem(ram_cap);
|
||||
|
||||
return ram_cap;
|
||||
}
|
||||
|
||||
void free_dma_buffer(Ram_capability ram)
|
||||
@ -623,9 +648,6 @@ namespace Pci {
|
||||
|
||||
Session_component *_create_session(const char *args)
|
||||
{
|
||||
/* FIXME: extract quota from args */
|
||||
/* FIXME: pass quota to session-component constructor */
|
||||
|
||||
try {
|
||||
return new (md_alloc()) Session_component(ep(), md_alloc(),
|
||||
_pd_device_client,
|
||||
@ -637,6 +659,14 @@ namespace Pci {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _upgrade_session(Session_component *s, const char *args) override
|
||||
{
|
||||
long ram_quota = Genode::Arg_string::find_arg(args, "ram_quota").long_value(0);
|
||||
s->upgrade_ram_quota(ram_quota);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -653,7 +683,6 @@ namespace Pci {
|
||||
:
|
||||
Genode::Root_component<Session_component>(ep, md_alloc),
|
||||
_pd_device_client(0),
|
||||
/* restrict physical address to 4G on 32/64bit in general XXX */
|
||||
/* restrict physical address to 3G on 32bit with device_pd */
|
||||
_ram("dma", 0, (pci_device_pd.valid() && sizeof(void *) == 4) ?
|
||||
0xc0000000UL : 0x100000000ULL)
|
||||
@ -661,7 +690,7 @@ namespace Pci {
|
||||
_parse_config();
|
||||
|
||||
if (pci_device_pd.valid())
|
||||
_pd_device_client = new (md_alloc) Device_pd_client(pci_device_pd);
|
||||
_pd_device_client = new (Genode::env()->heap()) Device_pd_client(pci_device_pd);
|
||||
|
||||
/* associate _ram session with ram_session of process */
|
||||
_ram.ref_account(Genode::env()->ram_session_cap());
|
||||
|
Loading…
x
Reference in New Issue
Block a user