gint/include/gint/dma.h

115 lines
3.8 KiB
C

//---
// gint:dma - Direct Memory Access for efficient data transfer
//---
#ifndef GINT_DMA
#define GINT_DMA
/* TODO: Enable DMA on fx-9860G */
#ifdef FXCG50
#include <gint/defs/types.h>
/* dma_size_t - Transfer block size */
typedef enum
{
/* Normal transfers of 1, 2, 4, 8, 16 or 32 bytes at a time */
DMA_1B = 0,
DMA_2B = 1,
DMA_4B = 2,
DMA_8B = 7,
DMA_16B = 3,
DMA_32B = 4,
/* Transfers of 16 or 32 bytes divided in two operations */
DMA_16B_DIV = 11,
DMA_32B_DIV = 12,
} dma_size_t;
/* dma_address_t - Addressing mode for source and destination regions */
typedef enum
{
/* Fixed address mode: the same address is read/written at each step */
DMA_FIXED = 0,
/* Increment: address is incremented by transfer size at each step */
DMA_INC = 1,
/* Decrement: only allowed for 1/2/4-byte transfers */
DMA_DEC = 2,
/* Fixed division mode: address is fixed even in 16/32-divide mode */
DMA_FIXEDDIV = 3,
} dma_address_t;
/* dma_transfer() - Start a data transfer on channel 0
This function returns just when the transfer starts. The transfer will end
later on and the DMA will be stopped by an interrupt. Call
dma_transfer_wait() if you need to wait for the transfer to finish. Don't
start a new transfer until the current one is finished!
@channel DMA channel (0..5)
@size Transfer size
@blocks Number of blocks (transferred memory = size * blocks)
@src Source pointer, must be aligned with transfer size
@src_mode Source address mode
@dst Destination address, must be aligned with transfer size
@dst_mode Destination address mode */
void dma_transfer(int channel, dma_size_t size, uint length,
void const *src, dma_address_t src_mode,
void *dst, dma_address_t dst_mode);
/* dma_transfer_wait() - Wait for a transfer to finish
You should call this function when you need to transfer to be complete
before continuing execution. If you are sure that the transfer is finished,
this is not necessary (the only way to know is to look at the DMA registers
or record interrupts).
@channel DMA channel (0..5) */
void dma_transfer_wait(int channel);
/* dma_transfer_noint() - Perform a data transfer without interrupts
This function performs a transfer much like dma_transfer(), but doesn't use
interrupts and *actively waits* for the transfer to finish, returning when
it's finished. Don't call dma_transfer_wait() after using this function.
Not using interrupts is a bad design idea for a majority of programs, and is
only ever needed to display panic messages inside exception handlers. */
void dma_transfer_noint(int channel, dma_size_t size, uint blocks,
void const *src, dma_address_t src_mode,
void *dst, dma_address_t dst_mode);
//---
// DMA-based memory manipulation functions
//---
/* dma_memset(): Fast 32-aligned memset
This function is your typical memset(), except that the destination and size
must be 32-aligned, and that the pattern is 4 bytes instead of one. It is
replicated to 32 bytes then used to fill the destination area. This 4-byte
fixed size may be lifted in future versions.
This function cannot be used with virtualized (P0) addresses.
@dst Destination address (32-aligned)
@pattern 4-byte pattern to fill @dst
@size Sie of destination area (32-aligned) */
void *dma_memset(void *dst, uint32_t pattern, size_t size);
/* dma_memcpy(): Fast 32-aligned memcpy
This function works exactly like memcpy(), but it expects 32-aligned source,
destination, and size, and uses the DMA to efficiently copy.
This function cannot be used with virtualized (P0) addresses.
@dst Destination address (32-aligned)
@dst Source addresss (32-aligned)
@size Size of region (32-aligned) */
void *dma_memcpy(void * restrict dst, const void * restrict src, size_t size);
#endif /* FXCG50 */
#endif /* GINT_DMA */