diff options
Diffstat (limited to 'src/include/ipxe')
-rw-r--r-- | src/include/ipxe/dma.h | 334 | ||||
-rw-r--r-- | src/include/ipxe/errfile.h | 1 |
2 files changed, 335 insertions, 0 deletions
diff --git a/src/include/ipxe/dma.h b/src/include/ipxe/dma.h new file mode 100644 index 000000000..d3db061f7 --- /dev/null +++ b/src/include/ipxe/dma.h @@ -0,0 +1,334 @@ +#ifndef _IPXE_DMA_H +#define _IPXE_DMA_H + +/** @file + * + * DMA mappings + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <stdint.h> +#include <ipxe/api.h> +#include <ipxe/io.h> +#include <ipxe/iobuf.h> +#include <ipxe/malloc.h> +#include <config/ioapi.h> + +#ifdef DMAAPI_OP +#define DMAAPI_PREFIX_op +#else +#define DMAAPI_PREFIX_op __op_ +#endif + +#ifdef DMAAPI_FLAT +#define DMAAPI_PREFIX_flat +#else +#define DMAAPI_PREFIX_flat __flat_ +#endif + +/** A DMA mapping */ +struct dma_mapping { + /** Device-side address */ + physaddr_t addr; +}; + +/** A DMA-capable device */ +struct dma_device { + /** DMA operations */ + struct dma_operations *op; + /** Addressable space mask */ + physaddr_t mask; + /** Total number of mappings (for debugging) */ + unsigned int mapped; + /** Total number of allocations (for debugging) */ + unsigned int allocated; +}; + +/** DMA operations */ +struct dma_operations { + /** + * Map buffer for DMA + * + * @v dma DMA device + * @v addr Buffer address + * @v len Length of buffer + * @v flags Mapping flags + * @v map DMA mapping to fill in + * @ret rc Return status code + */ + int ( * map ) ( struct dma_device *dma, physaddr_t addr, size_t len, + int flags, struct dma_mapping *map ); + /** + * Unmap buffer + * + * @v dma DMA device + * @v map DMA mapping + */ + void ( * unmap ) ( struct dma_device *dma, struct dma_mapping *map ); + /** + * Allocate and map DMA-coherent buffer + * + * @v dma DMA device + * @v len Length of buffer + * @v align Physical alignment + * @v map DMA mapping to fill in + * @ret addr Buffer address, or NULL on error + */ + void * ( * alloc ) ( struct dma_device *dma, size_t len, size_t align, + struct dma_mapping *map ); + /** + * Unmap and free DMA-coherent buffer + * + * @v dma DMA device + * @v addr Buffer address + * @v len Length of buffer + * @v map DMA mapping + */ + void ( * free ) ( struct dma_device *dma, void *addr, size_t len, + struct dma_mapping *map ); + /** + * Set addressable space mask + * + * @v dma DMA device + * @v mask Addressable space mask + */ + void ( * set_mask ) ( struct dma_device *dma, physaddr_t mask ); +}; + +/** Device will read data from host memory */ +#define DMA_TX 0x01 + +/** Device will write data to host memory */ +#define DMA_RX 0x02 + +/** Device will both read data from and write data to host memory */ +#define DMA_BI ( DMA_TX | DMA_RX ) + +/** + * Calculate static inline DMA I/O API function name + * + * @v _prefix Subsystem prefix + * @v _api_func API function + * @ret _subsys_func Subsystem API function + */ +#define DMAAPI_INLINE( _subsys, _api_func ) \ + SINGLE_API_INLINE ( DMAAPI_PREFIX_ ## _subsys, _api_func ) + +/** + * Provide a DMA I/O API implementation + * + * @v _prefix Subsystem prefix + * @v _api_func API function + * @v _func Implementing function + */ +#define PROVIDE_DMAAPI( _subsys, _api_func, _func ) \ + PROVIDE_SINGLE_API ( DMAAPI_PREFIX_ ## _subsys, _api_func, _func ) + +/** + * Provide a static inline DMA I/O API implementation + * + * @v _prefix Subsystem prefix + * @v _api_func API function + */ +#define PROVIDE_DMAAPI_INLINE( _subsys, _api_func ) \ + PROVIDE_SINGLE_API_INLINE ( DMAAPI_PREFIX_ ## _subsys, _api_func ) + +/** + * Map buffer for DMA + * + * @v dma DMA device + * @v addr Buffer address + * @v len Length of buffer + * @v flags Mapping flags + * @v map DMA mapping to fill in + * @ret rc Return status code + */ +static inline __always_inline int +DMAAPI_INLINE ( flat, dma_map ) ( struct dma_device *dma, physaddr_t addr, + size_t len __unused, int flags __unused, + struct dma_mapping *map ) { + + /* Use physical address as device address */ + map->addr = addr; + + /* Increment mapping count (for debugging) */ + if ( DBG_LOG ) + dma->mapped++; + + return 0; +} + +/** + * Unmap buffer + * + * @v dma DMA device + * @v map DMA mapping + */ +static inline __always_inline void +DMAAPI_INLINE ( flat, dma_unmap ) ( struct dma_device *dma, + struct dma_mapping *map __unused ) { + + /* Decrement mapping count (for debugging) */ + if ( DBG_LOG ) + dma->mapped--; +} + +/** + * Allocate and map DMA-coherent buffer + * + * @v dma DMA device + * @v len Length of buffer + * @v align Physical alignment + * @v map DMA mapping to fill in + * @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 ) { + void *addr; + + /* Allocate buffer */ + addr = malloc_phys ( len, align ); + map->addr = virt_to_phys ( addr ); + + /* Increment allocation count (for debugging) */ + if ( DBG_LOG && addr ) + dma->allocated++; + + return addr; +} + +/** + * Unmap and free DMA-coherent buffer + * + * @v dma DMA device + * @v addr Buffer address + * @v len Length of buffer + * @v map DMA mapping + */ +static inline __always_inline void +DMAAPI_INLINE ( flat, dma_free ) ( struct dma_device *dma, + void *addr, size_t len, + struct dma_mapping *map __unused ) { + + /* Free buffer */ + free_phys ( addr, len ); + + /* Decrement allocation count (for debugging) */ + if ( DBG_LOG ) + dma->allocated--; +} + +/** + * Set addressable space mask + * + * @v dma DMA device + * @v mask Addressable space mask + */ +static inline __always_inline void +DMAAPI_INLINE ( flat, dma_set_mask ) ( struct dma_device *dma __unused, + physaddr_t mask __unused ) { + + /* Nothing to do */ +} + +/** + * Map buffer for DMA + * + * @v dma DMA device + * @v addr Buffer address + * @v len Length of buffer + * @v flags Mapping flags + * @v map DMA mapping to fill in + * @ret rc Return status code + */ +int dma_map ( struct dma_device *dma, physaddr_t addr, size_t len, + int flags, struct dma_mapping *map ); + +/** + * Unmap buffer + * + * @v dma DMA device + * @v map DMA mapping + */ +void dma_unmap ( struct dma_device *dma, struct dma_mapping *map ); + +/** + * Allocate and map DMA-coherent buffer + * + * @v dma DMA device + * @v len Length of buffer + * @v align Physical alignment + * @v map DMA mapping to fill in + * @ret addr Buffer address, or NULL on error + */ +void * dma_alloc ( struct dma_device *dma, size_t len, size_t align, + struct dma_mapping *map ); + +/** + * Unmap and free DMA-coherent buffer + * + * @v dma DMA device + * @v addr Buffer address + * @v len Length of buffer + * @v map DMA mapping + */ +void dma_free ( struct dma_device *dma, void *addr, size_t len, + struct dma_mapping *map ); + +/** + * Set addressable space mask + * + * @v dma DMA device + * @v mask Addressable space mask + */ +void dma_set_mask ( struct dma_device *dma, physaddr_t mask ); + +/** + * Initialise DMA device + * + * @v dma DMA device + * @v op DMA operations + */ +static inline __always_inline void dma_init ( struct dma_device *dma, + struct dma_operations *op ) { + + /* Set operations table */ + dma->op = op; +} + +/** + * Set 64-bit addressable space mask + * + * @v dma DMA device + */ +static inline __always_inline void +dma_set_mask_64bit ( struct dma_device *dma ) { + + /* Set mask to maximum physical address */ + dma_set_mask ( dma, ~( ( physaddr_t ) 0 ) ); +} + +/** + * Map I/O buffer for transmitting data to device + * + * @v dma DMA device + * @v iobuf I/O buffer + * @v map DMA mapping to fill in + * @ret rc Return status code + */ +static inline __always_inline int +dma_map_tx_iob ( struct dma_device *dma, struct io_buffer *iobuf, + struct dma_mapping *map ) { + + /* Map I/O buffer */ + return dma_map ( dma, virt_to_phys ( iobuf->data ), iob_len ( iobuf ), + DMA_TX, map ); +} + +extern struct io_buffer * dma_alloc_rx_iob ( struct dma_device *dma, size_t len, + struct dma_mapping *map ); + +#endif /* _IPXE_DMA_H */ diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index 8238d4925..1c41feff3 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -75,6 +75,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define ERRFILE_sanboot ( ERRFILE_CORE | 0x00230000 ) #define ERRFILE_dummy_sanboot ( ERRFILE_CORE | 0x00240000 ) #define ERRFILE_fdt ( ERRFILE_CORE | 0x00250000 ) +#define ERRFILE_dma ( ERRFILE_CORE | 0x00260000 ) #define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 ) #define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 ) |