mirror of
https://github.com/ipxe/ipxe
synced 2025-12-19 19:49:45 +03:00
[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>
This commit is contained in:
@@ -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 )
|
||||
@@ -236,6 +239,35 @@ DMAAPI_INLINE ( flat, dma_set_mask ) ( struct dma_device *dma __unused,
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
@@ -288,6 +320,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
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user