diff --git a/os/include/dde_kit/pci.h b/os/include/dde_kit/pci.h
index d22a6db11b..989e5d1e02 100644
--- a/os/include/dde_kit/pci.h
+++ b/os/include/dde_kit/pci.h
@@ -135,6 +135,19 @@ int dde_kit_pci_first_device(int *bus, int *dev, int *fun);
*/
int dde_kit_pci_next_device(int *bus, int *dev, int *fun);
+/**
+ * Allocate a DMA buffer and map it. If an IOMMU is available this functions
+ * takes care that DMA to this buffer for the given PCI device is permitted.
+ *
+ * \retval bus bus number
+ * \retval dev device number
+ * \retval fun function number
+ *
+ * \return 0 in case of failure, otherwise the virtual address of the buffer.
+ */
+dde_kit_addr_t dde_kit_pci_alloc_dma_buffer(int bus, int dev, int fun,
+ dde_kit_size_t size);
+
/**
* Initialize PCI subsystem
*
diff --git a/os/src/lib/dde_kit/pci.cc b/os/src/lib/dde_kit/pci.cc
index 37f3970f78..17420cd565 100644
--- a/os/src/lib/dde_kit/pci.cc
+++ b/os/src/lib/dde_kit/pci.cc
@@ -21,9 +21,11 @@
*/
#include
+#include
extern "C" {
#include
+#include
}
#include "pci_tree.h"
@@ -137,6 +139,26 @@ extern "C" int dde_kit_pci_next_device(int *bus, int *dev, int *fun)
}
}
+extern "C" dde_kit_addr_t dde_kit_pci_alloc_dma_buffer(int bus, int dev,
+ int fun,
+ dde_kit_size_t size)
+{
+ try {
+ using namespace Genode;
+
+ Ram_dataspace_capability ram_cap;
+ ram_cap = pci_tree()->alloc_dma_buffer(bus, dev, fun, size);
+ addr_t base = (addr_t)env()->rm_session()->attach(ram_cap);
+
+ /* add to DDE-kit page tables */
+ addr_t phys = Dataspace_client(ram_cap).phys_addr();
+ dde_kit_pgtab_set_region_with_size((void *)base, phys, size);
+
+ return base;
+ } catch (...) {
+ return 0;
+ }
+}
/********************
** Initialization **
diff --git a/os/src/lib/dde_kit/pci_tree.h b/os/src/lib/dde_kit/pci_tree.h
index 809c06f2b7..60da227265 100644
--- a/os/src/lib/dde_kit/pci_tree.h
+++ b/os/src/lib/dde_kit/pci_tree.h
@@ -40,12 +40,14 @@ namespace Dde_kit {
private:
- Pci::Device_client _device;
- unsigned short _bdf; /* bus:device:function */
+ Pci::Device_client _device;
+ unsigned short _bdf; /* bus:device:function */
public:
- Pci_device(Pci::Device_capability device_cap) : _device(device_cap)
+ Pci_device(Pci::Device_capability device_cap)
+ :
+ _device(device_cap)
{
unsigned char bus = ~0, dev = ~0, fun = ~0;
@@ -118,6 +120,14 @@ namespace Dde_kit {
if (child(RIGHT)) child(RIGHT)->show();
}
+
+ Ram_dataspace_capability alloc_dma_buffer(Pci::Connection &pci_drv,
+ size_t size)
+ {
+ /* trigger that the device gets assigned to this driver */
+ pci_drv.config_extended(_device);
+ return pci_drv.alloc_dma_buffer(_device, size);
+ }
};
class Pci_tree
@@ -241,6 +251,16 @@ namespace Dde_kit {
_next_bdf(d, bus, dev, fun);
}
+
+ Ram_dataspace_capability alloc_dma_buffer(int bus, int dev,
+ int fun, size_t size)
+ {
+ Lock::Guard lock_guard(_lock);
+
+ unsigned short bdf = Pci_device::knit_bdf(bus, dev, fun);
+
+ return _lookup(bdf)->alloc_dma_buffer(_pci_drv, size);
+ }
};
}