aboutsummaryrefslogtreecommitdiff
path: root/src/include/ipxe/dma.h
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2020-11-25 15:52:00 +0000
committerMichael Brown <mcb30@ipxe.org>2020-11-25 16:15:55 +0000
commitcf12a41703a8b2292e5d2d7528c2733c37869681 (patch)
tree72e60b6240cdd10816b7dce5fcc98822ae94e957 /src/include/ipxe/dma.h
parent24ef743778fb47958441d8891e5104135ac4c168 (diff)
downloadipxe-cf12a41703a8b2292e5d2d7528c2733c37869681.zip
ipxe-cf12a41703a8b2292e5d2d7528c2733c37869681.tar.gz
ipxe-cf12a41703a8b2292e5d2d7528c2733c37869681.tar.bz2
[dma] Modify DMA API to simplify calculation of medial addresses
Redefine the value stored within a DMA mapping to be the offset between physical addresses and DMA addresses within the mapped region. Provide a dma() wrapper function to calculate the DMA address for any pointer within a mapped region, thereby simplifying the use cases when a device needs to be given addresses other than the region start address. On a platform using the "flat" DMA implementation the DMA offset for any mapped region is always zero, with the result that dma_map() can be optimised away completely and dma() reduces to a straightforward call to virt_to_phys(). Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/include/ipxe/dma.h')
-rw-r--r--src/include/ipxe/dma.h74
1 files changed, 64 insertions, 10 deletions
diff --git a/src/include/ipxe/dma.h b/src/include/ipxe/dma.h
index 878e03f..0577493 100644
--- a/src/include/ipxe/dma.h
+++ b/src/include/ipxe/dma.h
@@ -30,8 +30,13 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** A DMA mapping */
struct dma_mapping {
- /** Device-side address */
- physaddr_t addr;
+ /** Address offset
+ *
+ * This is the value that must be added to a physical address
+ * within the mapping in order to produce the corresponding
+ * device-side DMA address.
+ */
+ physaddr_t offset;
/** Platform mapping token */
void *token;
};
@@ -148,12 +153,10 @@ struct dma_operations {
* @ret rc Return status code
*/
static inline __always_inline int
-DMAAPI_INLINE ( flat, dma_map ) ( struct dma_device *dma, physaddr_t addr,
+DMAAPI_INLINE ( flat, dma_map ) ( struct dma_device *dma,
+ physaddr_t addr __unused,
size_t len __unused, int flags __unused,
- struct dma_mapping *map ) {
-
- /* Use physical address as device address */
- map->addr = addr;
+ struct dma_mapping *map __unused ) {
/* Increment mapping count (for debugging) */
if ( DBG_LOG )
@@ -187,13 +190,13 @@ DMAAPI_INLINE ( flat, dma_unmap ) ( struct dma_device *dma,
* @ret addr Buffer address, or NULL on error
*/
static inline __always_inline void *
-DMAAPI_INLINE ( flat, dma_alloc ) ( struct dma_device *dma, size_t len,
- size_t align, struct dma_mapping *map ) {
+DMAAPI_INLINE ( flat, dma_alloc ) ( struct dma_device *dma,
+ size_t len, size_t align,
+ struct dma_mapping *map __unused ) {
void *addr;
/* Allocate buffer */
addr = malloc_phys ( len, align );
- map->addr = virt_to_phys ( addr );
/* Increment allocation count (for debugging) */
if ( DBG_LOG && addr )
@@ -237,6 +240,35 @@ DMAAPI_INLINE ( flat, dma_set_mask ) ( struct dma_device *dma __unused,
}
/**
+ * Get DMA address from physical address
+ *
+ * @v map DMA mapping
+ * @v addr Physical address within the mapped region
+ * @ret addr Device-side DMA address
+ */
+static inline __always_inline physaddr_t
+DMAAPI_INLINE ( flat, dma_phys ) ( struct dma_mapping *map __unused,
+ physaddr_t addr ) {
+
+ /* Use physical address as device address */
+ return addr;
+}
+
+/**
+ * Get DMA address from physical address
+ *
+ * @v map DMA mapping
+ * @v addr Physical address within the mapped region
+ * @ret addr Device-side DMA address
+ */
+static inline __always_inline physaddr_t
+DMAAPI_INLINE ( op, dma_phys ) ( struct dma_mapping *map, physaddr_t addr ) {
+
+ /* Adjust physical address using mapping offset */
+ return ( addr + map->offset );
+}
+
+/**
* Map buffer for DMA
*
* @v dma DMA device
@@ -289,6 +321,28 @@ void dma_free ( struct dma_device *dma, void *addr, size_t len,
void dma_set_mask ( struct dma_device *dma, physaddr_t mask );
/**
+ * Get DMA address from physical address
+ *
+ * @v map DMA mapping
+ * @v addr Physical address within the mapped region
+ * @ret addr Device-side DMA address
+ */
+physaddr_t dma_phys ( struct dma_mapping *map, physaddr_t addr );
+
+/**
+ * Get DMA address from virtual address
+ *
+ * @v map DMA mapping
+ * @v addr Virtual address within the mapped region
+ * @ret addr Device-side DMA address
+ */
+static inline __always_inline physaddr_t dma ( struct dma_mapping *map,
+ void *addr ) {
+
+ return dma_phys ( map, virt_to_phys ( addr ) );
+}
+
+/**
* Initialise DMA device
*
* @v dma DMA device