mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-10 21:01:49 +00:00
dde_linux: remove legacy usb_host_drv for x86
Remove legacy platform_session API usage from legacy lx_kit/lx_emul Ref genodelabs/genode#4578
This commit is contained in:
parent
91e64c3f27
commit
b8eab65536
@ -1,242 +0,0 @@
|
||||
/*
|
||||
* \brief PCI device handling
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2016-04-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator.h>
|
||||
#include <base/entrypoint.h>
|
||||
#include <base/signal.h>
|
||||
#include <irq_session/client.h>
|
||||
#include <util/misc_math.h>
|
||||
|
||||
#include <lx_emul.h>
|
||||
#include <platform.h>
|
||||
|
||||
#include <legacy/lx_kit/env.h>
|
||||
#include <legacy/lx_kit/irq.h>
|
||||
#include <legacy/lx_kit/pci_dev_registry.h>
|
||||
#include <legacy/lx_kit/malloc.h>
|
||||
#include <legacy/lx_kit/mapped_io_mem_range.h>
|
||||
|
||||
#include <legacy/lx_emul/impl/io.h>
|
||||
#include <legacy/lx_emul/impl/pci_resource.h>
|
||||
|
||||
|
||||
/**
|
||||
* Quirks
|
||||
*/
|
||||
extern "C" void __pci_fixup_quirk_usb_early_handoff(void *data);
|
||||
|
||||
|
||||
/**
|
||||
* List of pci devices from platform driver
|
||||
*/
|
||||
class Pci_dev_list
|
||||
{
|
||||
private:
|
||||
|
||||
struct Element : public Lx_kit::List<Element>::Element
|
||||
{
|
||||
Platform::Device_capability cap;
|
||||
|
||||
Element(Platform::Device_capability cap) : cap(cap) { }
|
||||
};
|
||||
|
||||
Lx_kit::List<Element> _pci_caps;
|
||||
|
||||
public:
|
||||
|
||||
Pci_dev_list()
|
||||
{
|
||||
/*
|
||||
* Obtain first device, the operation may exceed the session quota.
|
||||
* So we use the 'with_upgrade' mechanism.
|
||||
*/
|
||||
Platform::Device_capability cap =
|
||||
Lx::pci()->with_upgrade([&] () {
|
||||
return Lx::pci()->first_device(); });
|
||||
|
||||
/*
|
||||
* Iterate over the devices of the platform session.
|
||||
*/
|
||||
while (cap.valid()) {
|
||||
|
||||
/*
|
||||
* Keep PCI devices in natural bus order. Otherwise on a Lenovo
|
||||
* ThinkCentre M57p, the system locks up when the UHCI
|
||||
* controller BIOS handoff (disabling bit 4 in the LEGSUP
|
||||
* register) for the controller with PCI BDF 00:1d:2 is
|
||||
* attempted before the handoff for the controller with BDF
|
||||
* 00:1a:0.
|
||||
*/
|
||||
_pci_caps.append(new (Lx::Malloc::mem()) Element(cap));
|
||||
|
||||
/* try next one. Upgrade session quota on demand.*/
|
||||
Lx::pci()->with_upgrade([&] () {
|
||||
cap = Lx::pci()->next_device(cap); });
|
||||
}
|
||||
}
|
||||
|
||||
template <typename FUNC>
|
||||
void for_each_pci_device(FUNC const &func)
|
||||
{
|
||||
for (Element *e = _pci_caps.first(); e; e = e->next())
|
||||
func(e->cap);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Pci_dev_list *pci_dev_list()
|
||||
{
|
||||
static Pci_dev_list _list;
|
||||
return &_list;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pci_register_driver(struct pci_driver *driver)
|
||||
{
|
||||
driver->driver.name = driver->name;
|
||||
|
||||
pci_device_id const *id_table = driver->id_table;
|
||||
if (!id_table)
|
||||
return -ENODEV;
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
bool found = false;
|
||||
|
||||
auto lamda = [&] (Platform::Device_capability cap) {
|
||||
|
||||
Platform::Device_client client(cap);
|
||||
|
||||
/* request device ID from platform driver */
|
||||
unsigned const class_code = client.class_code();
|
||||
|
||||
/* look if we find the device ID in the driver's 'id_table' */
|
||||
pci_device_id const *matching_id = nullptr;
|
||||
for (pci_device_id const *id = id_table; id->device; id++) {
|
||||
|
||||
lx_log(DEBUG_PCI,"idclass: %x idclassm: %x devclass %x", id->class_,
|
||||
id->class_mask, class_code);
|
||||
|
||||
/* check for drivers that support any device for a given class */
|
||||
if (id->device != (unsigned)PCI_ANY_ID || !id->class_mask)
|
||||
continue;
|
||||
|
||||
if ((id->class_ & id->class_mask) == (class_code & id->class_mask)) {
|
||||
matching_id = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip device that is not handled by driver */
|
||||
if (!matching_id)
|
||||
return false;
|
||||
|
||||
/* create 'pci_dev' struct for matching device */
|
||||
Lx::Pci_dev *pci_dev = new (Lx::Malloc::mem()) Lx::Pci_dev(cap);
|
||||
|
||||
/* enable ioremap to work */
|
||||
Lx::pci_dev_registry()->insert(pci_dev);
|
||||
|
||||
/* register driver at the 'pci_dev' struct */
|
||||
pci_dev->dev.driver = &driver->driver;
|
||||
|
||||
/*
|
||||
* This quirk handles device handoff from BIOS, since the BIOS may still
|
||||
* access the USB controller after bootup. For this the ext cap register of
|
||||
* the PCI config space is checked
|
||||
*/
|
||||
if (Lx_kit::env().config_rom().xml().attribute_value("bios_handoff", true))
|
||||
__pci_fixup_quirk_usb_early_handoff(pci_dev);
|
||||
|
||||
/* call probe function of the Linux driver */
|
||||
if (driver->probe(pci_dev, matching_id)) {
|
||||
|
||||
/* if the probing failed, revert the creation of 'pci_dev' */
|
||||
pci_dev_put(pci_dev);
|
||||
return false;
|
||||
}
|
||||
|
||||
found = true;
|
||||
|
||||
/* multiple device support continue */
|
||||
return true;
|
||||
};
|
||||
|
||||
pci_dev_list()->for_each_pci_device(lamda);
|
||||
|
||||
return found ? 0 : -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
/***********************
|
||||
** linux/interrupt.h **
|
||||
***********************/
|
||||
|
||||
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
|
||||
const char *name, void *dev)
|
||||
{
|
||||
for (Lx::Pci_dev *pci_dev = Lx::pci_dev_registry()->first(); pci_dev; pci_dev = pci_dev->next())
|
||||
if (pci_dev->irq == irq) {
|
||||
Genode::Irq_session_client is(pci_dev->client().irq(0));
|
||||
if ((is.info().type != Genode::Irq_session::Info::MSI)
|
||||
&& !flags) return 1;
|
||||
Lx::Irq::irq().request_irq(is.rpc_cap(), irq, handler, dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
** Platform backend alloc init **
|
||||
*********************************/
|
||||
|
||||
void backend_alloc_init(Genode::Env &env, Genode::Ram_allocator &ram,
|
||||
Genode::Allocator &alloc)
|
||||
{
|
||||
Lx::pci_init(env, ram, alloc);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void module_ehci_hcd_init();
|
||||
extern "C" void module_ehci_pci_init();
|
||||
extern "C" void module_ohci_hcd_mod_init();
|
||||
extern "C" void module_ohci_pci_init();
|
||||
extern "C" void module_uhci_hcd_init();
|
||||
extern "C" void module_xhci_hcd_init();
|
||||
extern "C" void module_xhci_pci_init();
|
||||
|
||||
void platform_hcd_init(Genode::Env &, Services *s)
|
||||
{
|
||||
if (s->xhci) {
|
||||
module_xhci_hcd_init();
|
||||
module_xhci_pci_init();
|
||||
}
|
||||
|
||||
if (s->ehci) {
|
||||
/* ehci_hcd should always be loaded before uhci_hcd and ohci_hcd, not after */
|
||||
module_ehci_hcd_init();
|
||||
module_ehci_pci_init();
|
||||
}
|
||||
|
||||
if (s->ohci) {
|
||||
module_ohci_hcd_mod_init();
|
||||
module_ohci_pci_init();
|
||||
}
|
||||
|
||||
if (s->uhci) {
|
||||
module_uhci_hcd_init();
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
include $(REP_DIR)/src/drivers/usb_host/target.inc
|
||||
|
||||
TARGET = legacy_pc_usb_host_drv
|
||||
|
||||
INC_DIR += $(REP_DIR)/src_drivers/usb_host/spec/x86
|
||||
INC_DIR += $(REP_DIR)/src/include/spec/x86
|
||||
|
||||
SRC_C += usb/core/hcd-pci.c
|
||||
SRC_C += usb/host/ehci-pci.c
|
||||
SRC_C += usb/host/ohci-hcd.c
|
||||
SRC_C += usb/host/ohci-pci.c
|
||||
SRC_C += usb/host/pci-quirks.c
|
||||
SRC_C += usb/host/uhci-hcd.c
|
||||
SRC_C += usb/host/xhci-pci.c
|
||||
|
||||
SRC_CC += lx_kit/mapped_io_mem_range.cc
|
||||
|
||||
SRC_CC += spec/x86/platform.cc
|
||||
|
||||
CC_OPT += -DCONFIG_PCI=1
|
||||
CC_OPT += -DCONFIG_USB_PCI=1
|
||||
CC_OPT += -DCONFIG_USB_EHCI_HCD=1
|
||||
CC_OPT += -DCONFIG_USB_OHCI_HCD=1
|
||||
CC_OPT += -DCONFIG_USB_UHCI_HCD=1
|
||||
CC_OPT += -DCONFIG_USB_XHCI_HCD=1
|
@ -1,4 +0,0 @@
|
||||
include $(REP_DIR)/src/drivers/usb_host/spec/x86/target.inc
|
||||
|
||||
REQUIRES = x86_32
|
||||
INC_DIR += $(REP_DIR)/src/include/spec/x86_32
|
@ -1,4 +0,0 @@
|
||||
include $(REP_DIR)/src/drivers/usb_host/spec/x86/target.inc
|
||||
|
||||
REQUIRES = x86_64
|
||||
INC_DIR += $(REP_DIR)/src/include/spec/x86_64
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* \brief Implementation of linux/io.h
|
||||
* \author Norman Feske
|
||||
* \date 2015-09-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
/* Linux kit includes */
|
||||
#include <legacy/lx_kit/pci_dev_registry.h>
|
||||
#include <legacy/lx_kit/mapped_io_mem_range.h>
|
||||
|
||||
|
||||
void *ioremap(phys_addr_t phys_addr, unsigned long size)
|
||||
{
|
||||
return Lx::ioremap(phys_addr, size, Genode::UNCACHED);
|
||||
}
|
||||
|
||||
|
||||
void *ioremap_wc(resource_size_t phys_addr, unsigned long size)
|
||||
{
|
||||
return Lx::ioremap(phys_addr, size, Genode::WRITE_COMBINED);
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
** asm-generic/io.h **
|
||||
**********************/
|
||||
|
||||
void outb(u8 value, u32 port) { Lx::pci_dev_registry()->io_write<u8> (port, value); }
|
||||
void outw(u16 value, u32 port) { Lx::pci_dev_registry()->io_write<u16>(port, value); }
|
||||
void outl(u32 value, u32 port) { Lx::pci_dev_registry()->io_write<u32>(port, value); }
|
||||
|
||||
u8 inb(u32 port) { return Lx::pci_dev_registry()->io_read<u8> (port); }
|
||||
u16 inw(u32 port) { return Lx::pci_dev_registry()->io_read<u16>(port); }
|
||||
u32 inl(u32 port) { return Lx::pci_dev_registry()->io_read<u32>(port); }
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* \brief Implementation of linux/pci.h
|
||||
* \author Norman Feske
|
||||
* \date 2015-09-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
/* Linux kit includes */
|
||||
#include <legacy/lx_kit/env.h>
|
||||
#include <legacy/lx_kit/pci_dev_registry.h>
|
||||
#include <legacy/lx_kit/mapped_io_mem_range.h>
|
||||
|
||||
#include <legacy/lx_emul/impl/pci_resource.h>
|
||||
|
||||
|
||||
extern "C" int pci_register_driver(struct pci_driver *driver)
|
||||
{
|
||||
driver->driver.name = driver->name;
|
||||
|
||||
pci_device_id const *id_table = driver->id_table;
|
||||
if (!id_table)
|
||||
return -ENODEV;
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
Lx::Pci_dev *pci_dev = nullptr;
|
||||
|
||||
auto lamda = [&] (Platform::Device_capability cap) {
|
||||
|
||||
Platform::Device_client client(cap);
|
||||
|
||||
/* request device ID from platform driver */
|
||||
unsigned const device_id = client.device_id();
|
||||
unsigned const subdevice_id = client.config_read(0x2e,
|
||||
Platform::Device::ACCESS_16BIT);
|
||||
|
||||
/* look if we find the device ID in the driver's 'id_table' */
|
||||
pci_device_id const *matching_id = nullptr;
|
||||
for (pci_device_id const *id = id_table; id->device; id++) {
|
||||
if ((id->device == device_id) &&
|
||||
(id->subdevice == (unsigned int)PCI_ANY_ID ||
|
||||
id->subdevice == subdevice_id)) {
|
||||
matching_id = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip device that is not handled by driver */
|
||||
if (!matching_id)
|
||||
return false;
|
||||
|
||||
/* create 'pci_dev' struct for matching device */
|
||||
pci_dev = new (&Lx_kit::env().heap()) Lx::Pci_dev(cap);
|
||||
|
||||
/* enable ioremap to work */
|
||||
Lx::pci_dev_registry()->insert(pci_dev);
|
||||
|
||||
/* register driver at the 'pci_dev' struct */
|
||||
pci_dev->dev.driver = &driver->driver;
|
||||
|
||||
/* call probe function of the Linux driver */
|
||||
if (driver->probe(pci_dev, matching_id)) {
|
||||
|
||||
/* if the probing failed, revert the creation of 'pci_dev' */
|
||||
pci_dev_put(pci_dev);
|
||||
pci_dev = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* aquire the device, stop iterating */
|
||||
return true;
|
||||
};
|
||||
|
||||
Lx::for_each_pci_device(lamda);
|
||||
|
||||
return pci_dev ? 0 : -ENODEV;
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
/*
|
||||
* \brief Implementation of linux/pci.h
|
||||
* \author Norman Feske
|
||||
* \date 2015-09-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
/* Linux kit includes */
|
||||
#include <legacy/lx_kit/pci_dev_registry.h>
|
||||
#include <legacy/lx_kit/mapped_io_mem_range.h>
|
||||
|
||||
|
||||
extern "C" size_t pci_resource_start(struct pci_dev *dev, unsigned bar)
|
||||
{
|
||||
if (bar >= DEVICE_COUNT_RESOURCE)
|
||||
return 0;
|
||||
|
||||
return dev->resource[bar].start;
|
||||
}
|
||||
|
||||
extern "C" size_t pci_resource_end(struct pci_dev *dev, unsigned bar)
|
||||
{
|
||||
if (bar >= DEVICE_COUNT_RESOURCE)
|
||||
return 0;
|
||||
|
||||
return dev->resource[bar].end;
|
||||
}
|
||||
|
||||
extern "C" size_t pci_resource_len(struct pci_dev *dev, unsigned bar)
|
||||
{
|
||||
size_t start = pci_resource_start(dev, bar);
|
||||
|
||||
if (!start)
|
||||
return 0;
|
||||
|
||||
return (dev->resource[bar].end - start) + 1;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void *pci_ioremap_bar(struct pci_dev *dev, int bar)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
if (bar >= DEVICE_COUNT_RESOURCE || bar < 0)
|
||||
return 0;
|
||||
|
||||
return Lx::ioremap(pci_resource_start(dev, bar),
|
||||
pci_resource_len(dev, bar),
|
||||
Genode::UNCACHED);
|
||||
}
|
||||
|
||||
|
||||
extern "C" unsigned int pci_resource_flags(struct pci_dev *dev, unsigned bar)
|
||||
{
|
||||
if (bar >= DEVICE_COUNT_RESOURCE)
|
||||
return 0;
|
||||
|
||||
return dev->resource[bar].flags;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int, int where, u8 *val)
|
||||
{
|
||||
Lx::Pci_dev *dev = (Lx::Pci_dev *)bus;
|
||||
dev->config_read(where, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pci_bus_read_config_word(struct pci_bus *bus, unsigned int, int where, u16 *val)
|
||||
{
|
||||
Lx::Pci_dev *dev = (Lx::Pci_dev *)bus;
|
||||
dev->config_read(where, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int, int where, u32 *val)
|
||||
{
|
||||
Lx::Pci_dev *dev = (Lx::Pci_dev *)bus;
|
||||
dev->config_read(where, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int, int where, u8 val)
|
||||
{
|
||||
Lx::Pci_dev *dev = (Lx::Pci_dev *)bus;
|
||||
dev->config_write(where, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pci_bus_write_config_word(struct pci_bus *bus, unsigned int, int where, u16 val)
|
||||
{
|
||||
Lx::Pci_dev *dev = (Lx::Pci_dev *)bus;
|
||||
dev->config_write(where, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int, int where, u32 val)
|
||||
{
|
||||
Lx::Pci_dev *dev = (Lx::Pci_dev *)bus;
|
||||
dev->config_write(where, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" const char *pci_name(const struct pci_dev *pdev)
|
||||
{
|
||||
/* simply return driver name */
|
||||
return "dummy";
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pcie_capability_read_word(struct pci_dev *pdev, int pos, u16 *val)
|
||||
{
|
||||
Lx::Pci_dev *dev = (Lx::Pci_dev *)pdev->bus;
|
||||
switch (pos) {
|
||||
case PCI_EXP_LNKCTL:
|
||||
dev->config_read(pdev->pcie_cap + PCI_EXP_LNKCTL, val);
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
@ -1,259 +0,0 @@
|
||||
/*
|
||||
* \brief Emulate 'pci_dev' structure
|
||||
* \author Sebastian Sumpf
|
||||
* \author Josef Soentgen
|
||||
* \author Norman Feske
|
||||
* \date 2014-10-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#ifndef _LX_KIT__INTERNAL__PCI_DEV_H_
|
||||
#define _LX_KIT__INTERNAL__PCI_DEV_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/object_pool.h>
|
||||
#include <legacy/x86/platform_session/connection.h>
|
||||
#include <legacy/x86/platform_device/client.h>
|
||||
#include <io_mem_session/connection.h>
|
||||
#include <base/attached_dataspace.h>
|
||||
#include <util/retry.h>
|
||||
|
||||
/* Linux emulation environment includes */
|
||||
#include <legacy/lx_kit/internal/list.h>
|
||||
#include <legacy/lx_kit/internal/io_port.h>
|
||||
|
||||
namespace Lx {
|
||||
|
||||
class Pci_dev;
|
||||
|
||||
/**
|
||||
* Return singleton 'Platform::Connection'
|
||||
*
|
||||
* Implementation must be provided by the driver.
|
||||
*/
|
||||
Platform::Connection *pci();
|
||||
|
||||
template <typename FUNC>
|
||||
static inline void for_each_pci_device(FUNC const &func,
|
||||
unsigned const device_class = 0,
|
||||
unsigned const class_mask = 0);
|
||||
}
|
||||
|
||||
|
||||
class Lx::Pci_dev : public pci_dev, public Lx_kit::List<Pci_dev>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
bool const verbose = true;
|
||||
|
||||
Platform::Device_client _client;
|
||||
|
||||
Io_port _io_port;
|
||||
Genode::Io_mem_session_capability _io_mem[DEVICE_COUNT_RESOURCE];
|
||||
|
||||
/* offset used in PCI config space */
|
||||
enum Pci_config { IRQ = 0x3c, REV = 0x8, CMD = 0x4,
|
||||
STATUS = 0x4, CAP = 0x34 };
|
||||
enum Pci_cap { CAP_LIST = 0x10, CAP_EXP = 0x10,
|
||||
CAP_EXP_FLAGS = 0x2, CAP_EXP_DEVCAP = 0x4 };
|
||||
|
||||
template <typename T>
|
||||
Platform::Device::Access_size _access_size(T t)
|
||||
{
|
||||
switch (sizeof(T))
|
||||
{
|
||||
case 1:
|
||||
return Platform::Device::ACCESS_8BIT;
|
||||
case 2:
|
||||
return Platform::Device::ACCESS_16BIT;
|
||||
default:
|
||||
return Platform::Device::ACCESS_32BIT;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned _virq_num()
|
||||
{
|
||||
static unsigned instance = 128;
|
||||
return ++instance;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Pci_dev(Platform::Device_capability cap)
|
||||
:
|
||||
_client(cap)
|
||||
{
|
||||
using namespace Platform;
|
||||
|
||||
Genode::memset(static_cast<pci_dev *>(this), 0, sizeof(pci_dev));
|
||||
|
||||
this->vendor = _client.vendor_id();
|
||||
this->device = _client.device_id();
|
||||
this->class_ = _client.class_code();
|
||||
this->revision = _client.config_read(REV, Device::ACCESS_8BIT);
|
||||
|
||||
/* dummy dma mask used to mark device as DMA capable */
|
||||
this->dev._dma_mask_buf = ~(u64)0;
|
||||
this->dev.dma_mask = &this->dev._dma_mask_buf;
|
||||
this->dev.coherent_dma_mask = ~0;
|
||||
|
||||
enum { USB_SUB_CLASS = 0xc0300 };
|
||||
|
||||
/*
|
||||
* For USB we generate virtual IRQ numbers so we can identify the device
|
||||
* later on
|
||||
*/
|
||||
if ((class_ & ~0xffU) == USB_SUB_CLASS)
|
||||
this->irq = _virq_num();
|
||||
else
|
||||
/* read interrupt line */
|
||||
this->irq = _client.config_read(IRQ, Device::ACCESS_8BIT);
|
||||
|
||||
|
||||
/* hide ourselfs in bus structure */
|
||||
this->bus = (struct pci_bus *)this;
|
||||
|
||||
/* setup resources */
|
||||
bool io = false;
|
||||
bool mem = false;
|
||||
for (int i = 0; i < Device::NUM_RESOURCES; i++) {
|
||||
Device::Resource res = _client.resource(i);
|
||||
if (res.type() == Device::Resource::INVALID)
|
||||
continue;
|
||||
|
||||
this->resource[i].start = res.base();
|
||||
this->resource[i].end = res.base() + res.size() - 1;
|
||||
|
||||
unsigned flags = 0;
|
||||
if (res.type() == Device::Resource::IO) flags |= IORESOURCE_IO;
|
||||
if (res.type() == Device::Resource::MEMORY) flags |= IORESOURCE_MEM;
|
||||
this->resource[i].flags = flags;
|
||||
|
||||
/* request port I/O session */
|
||||
if (res.type() == Device::Resource::IO) {
|
||||
uint8_t const virt_bar = _client.phys_bar_to_virt(i);
|
||||
_io_port.session(res.base(), res.size(), _client.io_port(virt_bar));
|
||||
io = true;
|
||||
}
|
||||
if (res.type() == Device::Resource::MEMORY)
|
||||
mem = true;
|
||||
}
|
||||
|
||||
/* enable bus master, memory and io bits */
|
||||
uint16_t cmd = _client.config_read(CMD, Device::ACCESS_16BIT);
|
||||
cmd |= io ? 0x1 : 0;
|
||||
cmd |= mem ? 0x2 : 0;
|
||||
|
||||
/* enable bus master */
|
||||
cmd |= 0x4;
|
||||
config_write(CMD, cmd);
|
||||
|
||||
/* get pci express capability */
|
||||
this->pcie_cap = 0;
|
||||
uint16_t status = _client.config_read(STATUS, Device::ACCESS_32BIT) >> 16;
|
||||
if (status & CAP_LIST) {
|
||||
uint8_t offset = _client.config_read(CAP, Device::ACCESS_8BIT);
|
||||
while (offset != 0x00) {
|
||||
uint8_t value = _client.config_read(offset, Device::ACCESS_8BIT);
|
||||
|
||||
if (value == CAP_EXP)
|
||||
this->pcie_cap = offset;
|
||||
|
||||
offset = _client.config_read(offset + 1, Device::ACCESS_8BIT);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->pcie_cap) {
|
||||
uint16_t reg_val = _client.config_read(this->pcie_cap, Device::ACCESS_16BIT);
|
||||
this->pcie_flags_reg = reg_val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read/write data from/to config space
|
||||
*/
|
||||
template <typename T>
|
||||
void config_read(unsigned int devfn, T *val)
|
||||
{
|
||||
*val = _client.config_read(devfn, _access_size(*val));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void config_write(unsigned int devfn, T val)
|
||||
{
|
||||
pci()->with_upgrade([&] () {
|
||||
_client.config_write(devfn, val, _access_size(val)); });
|
||||
}
|
||||
|
||||
Platform::Device &client() { return _client; }
|
||||
|
||||
Io_port &io_port() { return _io_port; }
|
||||
|
||||
Genode::Io_mem_session_capability io_mem(unsigned bar, Genode::Cache cache)
|
||||
{
|
||||
if (bar >= DEVICE_COUNT_RESOURCE)
|
||||
return Genode::Io_mem_session_capability();
|
||||
|
||||
if (!_io_mem[bar].valid())
|
||||
_io_mem[bar] = _client.io_mem(_client.phys_bar_to_virt(bar),
|
||||
cache);
|
||||
|
||||
return _io_mem[bar];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Call functor for each available physical PCI device
|
||||
*
|
||||
* The functor is called with the device capability as argument. If
|
||||
* returns true if we can stop iterating. In this case, the device
|
||||
* is expected to be acquired by the driver. All other devices are
|
||||
* released at the platform driver.
|
||||
*/
|
||||
template <typename FUNC>
|
||||
void Lx::for_each_pci_device(FUNC const &func, unsigned const device_class,
|
||||
unsigned const class_mask)
|
||||
{
|
||||
/*
|
||||
* Obtain first device, the operation may exceed the session quota.
|
||||
* So we use the 'retry' mechanism.
|
||||
*/
|
||||
Platform::Device_capability cap =
|
||||
Lx::pci()->with_upgrade([&] () {
|
||||
return Lx::pci()->first_device(device_class, class_mask); });
|
||||
|
||||
/*
|
||||
* Iterate over the devices of the platform session.
|
||||
*/
|
||||
while (cap.valid()) {
|
||||
|
||||
/*
|
||||
* Call functor, stop iterating depending on its return value.
|
||||
*/
|
||||
if (func(cap))
|
||||
break;
|
||||
|
||||
/*
|
||||
* Release current device and try next one. Upgrade session
|
||||
* quota on demand.
|
||||
*/
|
||||
Platform::Device_capability next_cap =
|
||||
Lx::pci()->with_upgrade([&] () {
|
||||
return pci()->next_device(cap, device_class, class_mask); });
|
||||
|
||||
Lx::pci()->release_device(cap);
|
||||
cap = next_cap;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _LX_KIT__INTERNAL__PCI_DEV_H_ */
|
@ -1,157 +0,0 @@
|
||||
/*
|
||||
* \brief Registry of PCI devices
|
||||
* \author Norman Feske
|
||||
* \date 2015-09-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#ifndef _LX_KIT__PCI_DEV_REGISTRY_H_
|
||||
#define _LX_KIT__PCI_DEV_REGISTRY_H_
|
||||
|
||||
/* Linux emulation environment includes */
|
||||
#include <legacy/lx_kit/pci.h>
|
||||
#include <legacy/lx_kit/internal/pci_dev.h>
|
||||
#include <io_port_session/connection.h>
|
||||
|
||||
namespace Lx {
|
||||
|
||||
class Pci_dev_registry;
|
||||
|
||||
/**
|
||||
* Return singleton 'Pci_dev_registry' object
|
||||
*
|
||||
* Implementation must be provided by the driver.
|
||||
*/
|
||||
Pci_dev_registry *pci_dev_registry(Genode::Env *env = nullptr);
|
||||
}
|
||||
|
||||
|
||||
class Lx::Pci_dev_registry
|
||||
{
|
||||
private:
|
||||
|
||||
Lx_kit::List<Pci_dev> _devs;
|
||||
Genode::Env &_env;
|
||||
|
||||
public:
|
||||
|
||||
Pci_dev_registry(Genode::Env &env) : _env(env) { }
|
||||
|
||||
void insert(Pci_dev *pci_dev)
|
||||
{
|
||||
/*
|
||||
* Keep PCI devices in natural bus order. Otherwise on a Lenovo
|
||||
* ThinkCentre M57p, the system locks up when the UHCI controller
|
||||
* BIOS handoff (disabling bit 4 in the LEGSUP register) for the
|
||||
* controller with PCI BDF 00:1d:2 is attempted before the handoff
|
||||
* for the controller with BDF 00:1a:0.
|
||||
*/
|
||||
_devs.append(pci_dev);
|
||||
}
|
||||
|
||||
void remove(Pci_dev *pci_dev)
|
||||
{
|
||||
_devs.remove(pci_dev);
|
||||
}
|
||||
|
||||
Pci_dev* first() { return _devs.first(); }
|
||||
|
||||
Genode::Io_mem_dataspace_capability io_mem(Genode::addr_t phys,
|
||||
Genode::Cache cache,
|
||||
Genode::size_t size,
|
||||
Genode::addr_t &offset)
|
||||
{
|
||||
enum { PCI_ROM_RESOURCE = 6 };
|
||||
|
||||
for (Pci_dev *d = _devs.first(); d; d = d->next()) {
|
||||
|
||||
unsigned bar = 0;
|
||||
for (; bar < PCI_ROM_RESOURCE; bar++) {
|
||||
if ((pci_resource_flags(d, bar) & IORESOURCE_MEM) &&
|
||||
(pci_resource_start(d, bar) <= phys) &&
|
||||
(pci_resource_end(d, bar) >= (phys+size-1)))
|
||||
break;
|
||||
}
|
||||
if (bar >= PCI_ROM_RESOURCE)
|
||||
continue;
|
||||
|
||||
/* offset from the beginning of the PCI resource */
|
||||
offset = phys - pci_resource_start(d, bar);
|
||||
|
||||
Genode::Io_mem_session_capability io_mem_cap =
|
||||
d->io_mem(bar, cache);
|
||||
|
||||
return Genode::Io_mem_session_client(io_mem_cap).dataspace();
|
||||
}
|
||||
|
||||
Genode::error("device using I/O memory of address ",
|
||||
Genode::Hex(phys), " is unknown");
|
||||
return Genode::Io_mem_dataspace_capability();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T io_read(unsigned port)
|
||||
{
|
||||
/* try I/O access on all PCI devices */
|
||||
for (Pci_dev *d = _devs.first(); d; d = d->next()) {
|
||||
T value = 0;
|
||||
if (d->io_port().in<T>(port, &value))
|
||||
return value;
|
||||
}
|
||||
|
||||
try {
|
||||
Genode::Io_port_connection iox(_env, port, sizeof(T));
|
||||
switch (sizeof(T)) {
|
||||
case 1:
|
||||
return iox.inb(port);
|
||||
case 2:
|
||||
return iox.inw(port);
|
||||
case 4:
|
||||
return iox.inl(port);
|
||||
}
|
||||
} catch (...) {
|
||||
Genode::error("unknown exception io_read");
|
||||
}
|
||||
|
||||
Genode::warning("I/O port(", port, ") read failed");
|
||||
|
||||
return (T)~0U;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void io_write(unsigned port, T value)
|
||||
{
|
||||
/* try I/O access on all PCI devices, return on first success */
|
||||
for (Pci_dev *d = _devs.first(); d; d = d->next()) {
|
||||
if (d->io_port().out<T>(port, value))
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Genode::Io_port_connection iox(_env, port, sizeof(T));
|
||||
switch (sizeof(T)) {
|
||||
case 1:
|
||||
iox.outb(port, value);
|
||||
return;
|
||||
case 2:
|
||||
iox.outw(port, value);
|
||||
return;
|
||||
case 4:
|
||||
iox.outl(port, value);
|
||||
return;
|
||||
}
|
||||
} catch (...) {
|
||||
Genode::error("unknown exception io_write");
|
||||
}
|
||||
|
||||
Genode::warning("I/O port(", port, ") write failed");
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _LX_KIT__PCI_DEV_REGISTRY_H_ */
|
@ -1,172 +0,0 @@
|
||||
/*
|
||||
* \brief Representation of a locally-mapped MMIO range
|
||||
* \author Norman Feske
|
||||
* \date 2015-09-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/attached_dataspace.h>
|
||||
#include <io_mem_session/io_mem_session.h>
|
||||
#include <rm_session/connection.h>
|
||||
#include <region_map/client.h>
|
||||
|
||||
/* Linux emulation environment */
|
||||
#include <lx_emul.h>
|
||||
|
||||
/* Linux emulation environment includes */
|
||||
#include <legacy/lx_kit/env.h>
|
||||
#include <legacy/lx_kit/internal/list.h>
|
||||
#include <legacy/lx_kit/mapped_io_mem_range.h>
|
||||
#include <legacy/lx_kit/pci_dev_registry.h>
|
||||
#include <legacy/lx_kit/types.h>
|
||||
|
||||
namespace Lx_kit { class Mapped_io_mem_range; }
|
||||
|
||||
|
||||
/**
|
||||
* Representation of a locally-mapped MMIO range
|
||||
*
|
||||
* This class is supposed to be a private utility to support 'ioremap'.
|
||||
*/
|
||||
class Lx_kit::Mapped_io_mem_range : public Lx_kit::List<Mapped_io_mem_range>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::size_t const _size;
|
||||
Genode::addr_t const _phys;
|
||||
Genode::Region_map_client _region_map;
|
||||
Genode::Attached_dataspace _ds;
|
||||
Genode::addr_t const _virt;
|
||||
|
||||
public:
|
||||
|
||||
Mapped_io_mem_range(Genode::Env &env,
|
||||
Genode::Rm_connection &rm,
|
||||
Genode::addr_t phys, Genode::size_t size,
|
||||
Genode::Io_mem_dataspace_capability ds_cap,
|
||||
Genode::addr_t offset)
|
||||
:
|
||||
_size(size),
|
||||
_phys(phys),
|
||||
_region_map(rm.create(size)),
|
||||
_ds(env.rm(), _region_map.dataspace()),
|
||||
_virt((Genode::addr_t)_ds.local_addr<void>() | (phys &0xfffUL))
|
||||
{
|
||||
_region_map.attach_at(ds_cap, 0, size, offset);
|
||||
}
|
||||
|
||||
Genode::addr_t phys() const { return _phys; }
|
||||
Genode::addr_t virt() const { return _virt; }
|
||||
Genode::Dataspace_capability cap() const { return _ds.cap(); }
|
||||
|
||||
/**
|
||||
* Return true if the mapped range contains the specified sub range
|
||||
*/
|
||||
bool phys_range(Genode::addr_t phys, Genode::size_t size) const
|
||||
{
|
||||
return (phys >= _phys) && (phys + size - 1 <= _phys + _size - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the mapped range contains the specified sub range
|
||||
*/
|
||||
bool virt_range(Genode::addr_t virt, Genode::size_t size) const
|
||||
{
|
||||
return (virt >= _virt) && (virt + size - 1 <= _virt + _size - 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static Lx_kit::List<Lx_kit::Mapped_io_mem_range> ranges;
|
||||
|
||||
|
||||
/************************************************
|
||||
** Lx_kit::Mapped_io_mem_range implementation **
|
||||
************************************************/
|
||||
|
||||
static Genode::Constructible<Genode::Rm_connection> _global_rm;
|
||||
|
||||
|
||||
void *Lx::ioremap(addr_t phys_addr, unsigned long size, Genode::Cache cache)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/* search for the requested region within the already mapped ranges */
|
||||
for (Lx_kit::Mapped_io_mem_range *r = ranges.first(); r; r = r->next()) {
|
||||
|
||||
if (r->phys_range(phys_addr, size)) {
|
||||
void * const virt = (void *)(r->virt() + phys_addr - r->phys());
|
||||
log("ioremap: return sub range phys ", Hex(phys_addr), " "
|
||||
"(size ", size, ") to virt ", virt);
|
||||
return virt;
|
||||
}
|
||||
}
|
||||
|
||||
addr_t offset = 0;
|
||||
Io_mem_dataspace_capability ds_cap =
|
||||
Lx::pci_dev_registry()->io_mem(phys_addr, cache, size, offset);
|
||||
|
||||
if (!ds_cap.valid()) {
|
||||
error("failed to request I/O memory: ",
|
||||
Hex_range<addr_t>(phys_addr, size));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!_global_rm.constructed()) {
|
||||
_global_rm.construct(Lx_kit::env().env());
|
||||
}
|
||||
|
||||
Lx_kit::Mapped_io_mem_range *io_mem = nullptr;
|
||||
|
||||
retry<Genode::Out_of_ram>(
|
||||
[&] () {
|
||||
io_mem = new (&Lx_kit::env().heap())
|
||||
Lx_kit::Mapped_io_mem_range(Lx_kit::env().env(), *_global_rm,
|
||||
phys_addr, size, ds_cap, offset);
|
||||
},
|
||||
[&] () {
|
||||
_global_rm->upgrade_ram(16384);
|
||||
},
|
||||
10
|
||||
);
|
||||
|
||||
ranges.insert(io_mem);
|
||||
|
||||
log("ioremap: mapped phys ", Hex(phys_addr), " (size ", size, ") "
|
||||
"to virt ", Hex(io_mem->virt()));
|
||||
|
||||
return (void *)io_mem->virt();
|
||||
}
|
||||
|
||||
void Lx::iounmap(volatile void * virt)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/* search for the requested region within the already mapped ranges */
|
||||
for (Lx_kit::Mapped_io_mem_range *r = ranges.first(); r; r = r->next()) {
|
||||
|
||||
if (r->virt() == (addr_t)virt) {
|
||||
ranges.remove(r);
|
||||
destroy(&Lx_kit::env().heap(), r);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Genode::Dataspace_capability
|
||||
Lx::ioremap_lookup(Genode::addr_t virt_addr, Genode::size_t size)
|
||||
{
|
||||
/* search for the requested region within the already mapped ranges */
|
||||
for (Lx_kit::Mapped_io_mem_range *r = ranges.first(); r; r = r->next())
|
||||
if (r->virt_range(virt_addr, size))
|
||||
return r->cap();
|
||||
|
||||
return Genode::Dataspace_capability();
|
||||
}
|
@ -1,181 +0,0 @@
|
||||
/*
|
||||
* \brief Backend allocator for DMA-capable memory
|
||||
* \author Sebastian Sumpf
|
||||
* \author Josef Soentgen
|
||||
* \author Norman Feske
|
||||
* \date 2014-10-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/object_pool.h>
|
||||
#include <base/env.h>
|
||||
|
||||
/* XXX only because of struct pci_dev */
|
||||
#include <lx_emul.h>
|
||||
|
||||
/* Linux emulation environment includes */
|
||||
#include <legacy/lx_kit/backend_alloc.h>
|
||||
#include <legacy/lx_kit/pci_dev_registry.h>
|
||||
|
||||
|
||||
namespace Lx_kit {
|
||||
|
||||
struct Memory_object_base;
|
||||
struct Ram_object;
|
||||
struct Dma_object;
|
||||
|
||||
Genode::Object_pool<Memory_object_base> memory_pool;
|
||||
};
|
||||
|
||||
|
||||
struct Lx_kit::Memory_object_base : Genode::Object_pool<Memory_object_base>::Entry
|
||||
{
|
||||
Memory_object_base(Genode::Ram_dataspace_capability cap)
|
||||
: Genode::Object_pool<Memory_object_base>::Entry(cap) {}
|
||||
virtual ~Memory_object_base() {};
|
||||
|
||||
virtual void free() = 0;
|
||||
|
||||
virtual Genode::addr_t dma_addr() const { return 0; }
|
||||
|
||||
Genode::Ram_dataspace_capability ram_cap()
|
||||
{
|
||||
using namespace Genode;
|
||||
return reinterpret_cap_cast<Ram_dataspace>(cap());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Lx_kit::Ram_object : Memory_object_base
|
||||
{
|
||||
Genode::Ram_allocator &_ram;
|
||||
|
||||
Ram_object(Genode::Ram_allocator &ram,
|
||||
Genode::Ram_dataspace_capability cap)
|
||||
: Memory_object_base(cap), _ram(ram) {}
|
||||
|
||||
void free() { _ram.free(ram_cap()); }
|
||||
};
|
||||
|
||||
|
||||
struct Lx_kit::Dma_object : Memory_object_base
|
||||
{
|
||||
Platform::Connection &_pci;
|
||||
|
||||
Genode::addr_t const _dma_addr = _pci.dma_addr(ram_cap());
|
||||
|
||||
Dma_object(Platform::Connection &pci,
|
||||
Genode::Ram_dataspace_capability cap)
|
||||
: Memory_object_base(cap), _pci(pci) { }
|
||||
|
||||
void free() { _pci.free_dma_buffer(ram_cap()); }
|
||||
|
||||
Genode::addr_t dma_addr() const override { return _dma_addr; }
|
||||
};
|
||||
|
||||
|
||||
/********************
|
||||
** Pci singletons **
|
||||
********************/
|
||||
|
||||
static Genode::Constructible<Platform::Connection> _global_pci;
|
||||
static Genode::Allocator *_global_md_alloc;
|
||||
static Genode::Ram_allocator *_global_ram;
|
||||
|
||||
|
||||
void Lx::pci_init(Genode::Env &env, Genode::Ram_allocator &ram,
|
||||
Genode::Allocator &md_alloc)
|
||||
{
|
||||
_global_pci.construct(env);
|
||||
_global_ram = &ram;
|
||||
_global_md_alloc = &md_alloc;
|
||||
|
||||
Lx::pci_dev_registry(&env);
|
||||
}
|
||||
|
||||
|
||||
Platform::Connection *Lx::pci()
|
||||
{
|
||||
return &*_global_pci;
|
||||
}
|
||||
|
||||
|
||||
Lx::Pci_dev_registry *Lx::pci_dev_registry(Genode::Env *env)
|
||||
{
|
||||
static Lx::Pci_dev_registry _pci_dev_registry(*env);
|
||||
return &_pci_dev_registry;
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
** Lx::Backend_alloc interface **
|
||||
*********************************/
|
||||
|
||||
Genode::Ram_dataspace_capability
|
||||
Lx::backend_alloc(Genode::addr_t size, Genode::Cache cache)
|
||||
{
|
||||
using namespace Genode;
|
||||
using namespace Lx_kit;
|
||||
|
||||
Memory_object_base *obj;
|
||||
Genode::Ram_dataspace_capability cap;
|
||||
if (cache == CACHED) {
|
||||
cap = _global_ram->alloc(size);
|
||||
obj = new (_global_md_alloc) Ram_object(*_global_ram, cap);
|
||||
} else {
|
||||
Genode::size_t donate = size;
|
||||
cap = retry<Genode::Out_of_ram>(
|
||||
[&] () {
|
||||
return retry<Genode::Out_of_caps>(
|
||||
[&] () { return _global_pci->alloc_dma_buffer(size, UNCACHED); },
|
||||
[&] () { _global_pci->upgrade_caps(2); });
|
||||
},
|
||||
[&] () {
|
||||
_global_pci->upgrade_ram(donate);
|
||||
donate = donate * 2 > size ? 4096 : donate * 2;
|
||||
});
|
||||
|
||||
obj = new (_global_md_alloc) Dma_object(*_global_pci, cap);
|
||||
}
|
||||
|
||||
memory_pool.insert(obj);
|
||||
return cap;
|
||||
}
|
||||
|
||||
|
||||
void Lx::backend_free(Genode::Ram_dataspace_capability cap)
|
||||
{
|
||||
using namespace Genode;
|
||||
using namespace Lx_kit;
|
||||
|
||||
Memory_object_base *object;
|
||||
memory_pool.apply(cap, [&] (Memory_object_base *obj) {
|
||||
object = obj;
|
||||
if (!object) { return; }
|
||||
|
||||
object->free();
|
||||
memory_pool.remove(object);
|
||||
});
|
||||
destroy(_global_md_alloc, object);
|
||||
}
|
||||
|
||||
|
||||
Genode::addr_t Lx::backend_dma_addr(Genode::Ram_dataspace_capability cap)
|
||||
{
|
||||
using namespace Genode;
|
||||
using namespace Lx_kit;
|
||||
|
||||
addr_t result = 0;
|
||||
memory_pool.apply(cap, [&] (Dma_object *obj_ptr) {
|
||||
if (obj_ptr)
|
||||
result = obj_ptr->dma_addr(); });
|
||||
|
||||
return result;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user