diff --git a/repos/os/include/platform_session/connection.h b/repos/os/include/platform_session/connection.h index ee56301602..05809cf5fa 100644 --- a/repos/os/include/platform_session/connection.h +++ b/repos/os/include/platform_session/connection.h @@ -24,6 +24,7 @@ namespace Platform { struct Device; + struct Dma_buffer; struct Connection; } @@ -33,7 +34,9 @@ class Platform::Connection : public Genode::Connection, { private: - friend class Device; /* 'Device' accesses '_rm' */ + /* 'Device' and 'Dma_buffer' access the '_rm' member */ + friend class Device; + friend class Dma_buffer; Region_map &_rm; Rom_session_client _rom {devices_rom()}; diff --git a/repos/os/include/platform_session/dma_buffer.h b/repos/os/include/platform_session/dma_buffer.h new file mode 100644 index 0000000000..7ffae8d7d9 --- /dev/null +++ b/repos/os/include/platform_session/dma_buffer.h @@ -0,0 +1,85 @@ +/* + * \brief Utility to allocate and locally attach a DMA buffer + * \author Norman Feske + * \date 2022-02-02 + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__PLATFORM_SESSION__DMA_BUFFER_H_ +#define _INCLUDE__PLATFORM_SESSION__DMA_BUFFER_H_ + +/* Genode includes */ +#include +#include + +class Platform::Dma_buffer : Noncopyable +{ + private: + + struct Allocation + { + Platform::Connection &platform; + + size_t const size; + Cache const cache; + + Ram_dataspace_capability _alloc() + { + return platform.retry_with_upgrade(Ram_quota{4096}, Cap_quota{2}, + [&] () { return platform.alloc_dma_buffer(size, cache); }); + } + + Ram_dataspace_capability cap = _alloc(); + + addr_t const dma_addr = platform.dma_addr(cap); + + Allocation(Connection &platform, size_t size, Cache cache) + : platform(platform), size(size), cache(cache) { } + + ~Allocation() { platform.free_dma_buffer(cap); } + + } _allocation; + + Attached_dataspace _ds { _allocation.platform._rm, _allocation.cap }; + + public: + + /** + * Constructor + * + * \param platform platform session used for the buffer allocation + * \param size DMA buffer size in bytes + * + * \throw Out_of_ram + * \throw Out_of_caps + * \throw Region_map::Region_conflict + */ + Dma_buffer(Connection &platform, size_t size, Cache cache) + : + _allocation(platform, size, cache) + { } + + /** + * Return component-local base address + */ + template T *local_addr() { return _ds.local_addr(); } + template T const *local_addr() const { return _ds.local_addr(); } + + /** + * Return bus address to be used for DMA operations + */ + addr_t dma_addr() const { return _allocation.dma_addr; } + + /** + * Return DMA-buffer size in bytes + */ + size_t size() const { return _allocation.size; } +}; + +#endif /* _INCLUDE__PLATFORM_SESSION__DMA_BUFFER_H_ */