0.3.1
Direct Memory Access (DMA)

Data Structures

struct  scu_dma_xfer
 The 3-tuple represents a single transfer in direct or indirect transfer. More...
 
union  scu_dma_xfer_type
 The transfer type. More...
 
struct  scu_dma_level_cfg
 Defines a SCU-DMA level configuration. More...
 

Macros

#define SCU_DMA_LEVEL_COUNT   (3)
 The number of SCU-DMA levels.
 
#define SCU_DMA_INDIRECT_TABLE_END   (0x80000000UL)
 The bit that signifies the end of the transfer table.
 
#define SCU_DMA_MODE_XFER_INITIALIZER(_len, _dst, _src)
 Initializer for scu_dma_xfer.
 
#define SCU_DMA_MODE_XFER_END_INITIALIZER(_len, _dst, _src)
 End Initializer for scu_dma_xfer.
 

Typedefs

typedef enum scu_dma_mode scu_dma_mode_t
 SCU-DMA transfer mode.
 
typedef enum scu_dma_space scu_dma_space_t
 SCU-DMA transfer space.
 
typedef enum scu_dma_start_factor scu_dma_start_factor_t
 SCU-DMA starting factors.
 
typedef enum scu_dma_stride scu_dma_stride_t
 SCU-DMA transfer stride.
 
typedef enum scu_dma_update scu_dma_update_t
 SCU-DMA transfer update type.
 
typedef enum scu_dma_bus scu_dma_bus_t
 Different busses.
 
typedef uint32_t scu_dma_level_t
 SCU-DMA level representing one of the 3 levels.
 
typedef scu_dma_ioregs_t scu_dma_handle_t
 A SCU-DMA handle representing a copy of the level's SCU-DMA registers.
 
typedef struct scu_dma_xfer scu_dma_xfer_t
 The 3-tuple represents a single transfer in direct or indirect transfer.
 
typedef union scu_dma_xfer_type scu_dma_xfer_type_t
 The transfer type.
 
typedef struct scu_dma_level_cfg scu_dma_level_cfg_t
 Defines a SCU-DMA level configuration.
 
typedef void(* scu_dma_ihr_t) (void)
 Callback type.
 
typedef void(* scu_dma_callback_t) (void *work)
 Callback type.
 

Enumerations

enum  scu_dma_mode
 SCU-DMA transfer mode. More...
 
enum  scu_dma_space
 SCU-DMA transfer space. More...
 
enum  scu_dma_start_factor
 SCU-DMA starting factors. More...
 
enum  scu_dma_stride
 SCU-DMA transfer stride. More...
 
enum  scu_dma_update
 SCU-DMA transfer update type. More...
 
enum  scu_dma_bus
 Different busses. More...
 

Functions

void scu_dma_level_stop (scu_dma_level_t level)
 Stop a specific SCU-DMA level.
 
static uint32_t scu_dma_status_get (void)
 Obtain the 32-bit SCU DSTA value.
 
static uint32_t scu_dma_dsp_busy (void)
 Obtain the status of SCU-DSP DMA.
 
static void scu_dma_dsp_wait (void)
 Wait until SCU-DSP DMA is no longer in operation/standby.
 
static scu_dma_bus_t scu_dma_bus_access_busy (void)
 Obtain which bus(es) are being accessed during DMA.
 
static void scu_dma_bus_access_wait (scu_dma_bus_t mask)
 Wait until the mask of bus(es) are no longer being accessed during DMA.
 
static uint32_t scu_dma_level0_busy (void)
 Obtain the status of SCU-DMA level 0.
 
static uint32_t scu_dma_level1_busy (void)
 Obtain the status of SCU-DMA level 1.
 
static uint32_t scu_dma_level2_busy (void)
 Obtain the status of SCU-DMA level 2.
 
static uint32_t scu_dma_level_busy (scu_dma_level_t level)
 Obtain the status of SCU-DMA level.
 
static void scu_dma_stop (void)
 Stop all SCU-DMA levels unconditionally.
 
void scu_dma_config_buffer (scu_dma_handle_t *handle, const scu_dma_level_cfg_t *cfg)
 Generates a handle from the SCU-DMA level configuration.
 
void scu_dma_config_set (scu_dma_level_t level, scu_dma_start_factor_t start_factor, const scu_dma_handle_t *handle, scu_dma_callback_t callback)
 Commits handle to SCU-DMA level I/O registers.
 
void scu_dma_transfer (scu_dma_level_t level, void *dst, const void *src, size_t len)
 Perform a transfer.
 
void scu_dma_transfer_wait (scu_dma_level_t level)
 Wait for a transfer to complete.
 
void scu_dma_level_fast_start (scu_dma_level_t level)
 Start a SCU-DMA transfer.
 
void scu_dma_level_start (scu_dma_level_t level)
 Start a SCU-DMA transfer.
 
void scu_dma_level_wait (scu_dma_level_t level)
 Wait until the SCU-DMA level is not in operation or standby.
 
scu_dma_level_t scu_dma_level_unused_get (void)
 Obtain the first unused SCU-DMA level.
 

Detailed Description

Description goes here.

SCU-DMA should be activated by the Master CPU.

  1. SCU-DMA is for transfers between different buses:
    • HWRAM ↔ A-bus
    • HWRAM ↔ B-bus
    • A-bus ↔ B-bus
  2. Writing to the A-Bus is prohibited.
  3. Read of the VDP2 is prohibited.
  4. Reading from or writing to LWRAM locks up the machine.
  5. Restriction on write address addition value in DMA based on access address:
    • HWRAM → 0x02 can be set
    • External areas 1 to 3 → 0x02 can be set
    • External area 4 (A-bus I/O area) → 0x00 and 0x02 can be set
    • VDP1, VDP2, SCSP → all values can be set

Data Structure Documentation

◆ scu_dma_xfer

struct scu_dma_xfer

The 3-tuple represents a single transfer in direct or indirect transfer.

When a SCU-DMA level is configured to operate in direct mode (scu_dma_level_cfg::mode), then this structure represents one transfer.

However, when the mode is SCU_DMA_MODE_INDIRECT, then this structure represents possibly one of many transfers contiguously laid out in memory as a table of transfers.

Data Fields
size_t len Transfer length.
uintptr_t dst Memory transfer destination address.
uintptr_t src

Memory transfer source address.

When in indirect mode, the last entry must be bitwise OR'd with the memory transfer source address and scu_dma_xfer::src with SCU_DMA_INDIRECT_TABLE_END. Otherwise, the machine will lock up.

◆ scu_dma_xfer_type

union scu_dma_xfer_type

The transfer type.

Data Fields
scu_dma_xfer_t * indirect

When indirect mode is used via scu_dma_level_cfg::mode, use this to point to the transfer table.

scu_dma_xfer_t direct

When indirect mode is used via scu_dma_level_cfg::mode, use this to set the 3-tuple.

◆ scu_dma_level_cfg

struct scu_dma_level_cfg

Defines a SCU-DMA level configuration.

Details goes here.

Warning
When in indirect mode,
  • The last entry in the transfer table must be bitwise OR'd with the memory transfer source address and scu_dma_xfer::src with SCU_DMA_INDIRECT_TABLE_END. Otherwise, the machine will lock up.
  • The base pointer to the table of transfers (scu_dma_xfer_type::indirect) must be byte aligned proportional to the number of transfers in the table. Ignoring this condition will cause the machine to lock up.

    For example, if the transfer count in the table is 1, and because this structure is 12 bytes, first round to the nearest power of 2, the alignment of the table must be on a 16-byte boundary. If the the transfer count is 3 (36 bytes rounded to 64), then the table must be on a 64-byte boundary.

    Effectively, the formula to determine the byte alignment is \(2^{\lceil\log_2 N\rceil}\)-bytes where \(N\) is the size of the transfer table in bytes.

    When allocating dynamically, use memalign. Otherwise, when statically allocating, mind the alignment.

Data Fields
scu_dma_space_t space:3 Transfer space.
scu_dma_mode_t mode:8 Transfer mode.
scu_dma_stride_t stride:8 Transfer stride.
scu_dma_update_t update Transfer update.
scu_dma_xfer_type_t xfer Transfer 3-tuple.

Macro Definition Documentation

◆ SCU_DMA_INDIRECT_TABLE_END

#define SCU_DMA_INDIRECT_TABLE_END   (0x80000000UL)

The bit that signifies the end of the transfer table.

This bit must be set in scu_dma_xfer::src.

Warning
Forgetting to bitwise OR this value to the last scu_dma_xfer::src in the table will result in the machine locking up.

◆ SCU_DMA_MODE_XFER_INITIALIZER

#define SCU_DMA_MODE_XFER_INITIALIZER (   _len,
  _dst,
  _src 
)
Value:
{ \
.len = (_len), \
.dst = (uintptr_t)(_dst), \
.src = (uintptr_t)(_src) \
}
unsigned int uintptr_t
Not yet documented.
Definition: libc.dox:34

Initializer for scu_dma_xfer.

This macro can be used in direct or indirect mode.

Parameters
_lenThe length.
_dstThe memory transfer destination address.
_srcThe memory transfer source address.

◆ SCU_DMA_MODE_XFER_END_INITIALIZER

#define SCU_DMA_MODE_XFER_END_INITIALIZER (   _len,
  _dst,
  _src 
)
Value:
{ \
.len = _len, \
.dst = (uint32_t)(_dst), \
}
#define SCU_DMA_INDIRECT_TABLE_END
The bit that signifies the end of the transfer table.
Definition: dma.h:116
unsigned long uint32_t
Not yet documented.
Definition: libc.dox:30

End Initializer for scu_dma_xfer.

Terminates the transfer table for when the level is in indirect mode.

Parameters
_lenThe length.
_dstThe memory transfer destination address.
_srcThe memory transfer source address.

Typedef Documentation

◆ scu_dma_handle_t

A SCU-DMA handle representing a copy of the level's SCU-DMA registers.

After configuring with scu_dma_config_buffer using scu_dma_level_cfg, the end result is a handle.

See also
scu_dma_config_buffer
scu_dma_config_set

◆ scu_dma_ihr_t

typedef void(* scu_dma_ihr_t) (void)

Callback type.

See also
scu_dma_illegal_set

◆ scu_dma_callback_t

typedef void(* scu_dma_callback_t) (void *work)

Callback type.

See also
scu_dma_config_set
scu_dma_level_end_set

Enumeration Type Documentation

◆ scu_dma_mode

SCU-DMA transfer mode.

Enumerator
SCU_DMA_MODE_DIRECT 

SCU-DMA direct mode.

SCU_DMA_MODE_INDIRECT 

SCU-DMA indirect mode.

◆ scu_dma_space

SCU-DMA transfer space.

Enumerator
SCU_DMA_SPACE_BUS_A 

SCU-DMA transfer space to CS2 (Chip Select), A-Bus.

SCU_DMA_SPACE_BUS_B 

SCU-DMA transfer space to B-Bus.

SCU_DMA_SPACE_BUS_CPU 

SCU-DMA transfer space to CPU-Bus.

◆ scu_dma_start_factor

SCU-DMA starting factors.

Enumerator
SCU_DMA_START_FACTOR_VBLANK_IN 

Start DMA transfer at VBLANK-IN.

SCU_DMA_START_FACTOR_VBLANK_OUT 

Start DMA transfer at VBLANK-OUT.

SCU_DMA_START_FACTOR_HBLANK_IN 

Start DMA transfer at HBLANK-IN.

SCU_DMA_START_FACTOR_TIMER_0 

Start DMA transfer at SCU timer #0.

SCU_DMA_START_FACTOR_TIMER_1 

Start DMA transfer at SCU timer #1.

SCU_DMA_START_FACTOR_SOUND_REQ 

Start DMA transfer at sound request.

SCU_DMA_START_FACTOR_SPRITE_DRAW_END 

Start DMA transfer at VDP1 sprite end.

SCU_DMA_START_FACTOR_ENABLE 

Start DMA transfer immediately.

◆ scu_dma_stride

SCU-DMA transfer stride.

Enumerator
SCU_DMA_STRIDE_0_BYTES 

Do not add to read/write addresses.

SCU_DMA_STRIDE_2_BYTES 

2-byte stride.

SCU_DMA_STRIDE_4_BYTES 

4-byte stride.

SCU_DMA_STRIDE_8_BYTES 

8-byte stride.

SCU_DMA_STRIDE_16_BYTES 

16-byte stride.

SCU_DMA_STRIDE_32_BYTES 

32-byte stride.

SCU_DMA_STRIDE_64_BYTES 

64-byte stride.

SCU_DMA_STRIDE_128_BYTES 

128-byte stride.

◆ scu_dma_update

SCU-DMA transfer update type.

Enumerator
SCU_DMA_UPDATE_NONE 

Do not update read or write address.

SCU_DMA_UPDATE_RUP 

Read address update.

SCU_DMA_UPDATE_WUP 

Write address update.

◆ scu_dma_bus

Different busses.

Enumerator
SCU_DMA_BUS_NONE 

None.

SCU_DMA_BUS_A 

A-Bus.

SCU_DMA_BUS_B 

B-Bus.

SCU_DMA_BUS_DSP 

SCU-DSP Bus.

Function Documentation

◆ scu_dma_level_stop()

void scu_dma_level_stop ( scu_dma_level_t  level)

Stop a specific SCU-DMA level.

Parameters
levelThe SCU-DMA level.

◆ scu_dma_status_get()

static uint32_t scu_dma_status_get ( void  )
inlinestatic

Obtain the 32-bit SCU DSTA value.

Returns
The 32-bit SCU DSTA value.

◆ scu_dma_dsp_busy()

static uint32_t scu_dma_dsp_busy ( void  )
inlinestatic

Obtain the status of SCU-DSP DMA.

Returns
Whether SCU-DSP DMA is in operation, on standby, or interrupted to background.

◆ scu_dma_bus_access_busy()

static scu_dma_bus_t scu_dma_bus_access_busy ( void  )
inlinestatic

Obtain which bus(es) are being accessed during DMA.

Returns
The mask of bus(es) that are being accessed during DMA.

◆ scu_dma_bus_access_wait()

static void scu_dma_bus_access_wait ( scu_dma_bus_t  mask)
inlinestatic

Wait until the mask of bus(es) are no longer being accessed during DMA.

Parameters
maskThe mask of bus(es).

◆ scu_dma_level0_busy()

static uint32_t scu_dma_level0_busy ( void  )
inlinestatic

Obtain the status of SCU-DMA level 0.

Returns
Whether SCU-DMA level 0 is in operation, on standby, or interrupted.

◆ scu_dma_level1_busy()

static uint32_t scu_dma_level1_busy ( void  )
inlinestatic

Obtain the status of SCU-DMA level 1.

Returns
Whether SCU-DMA level 1 is in operation, on standby, or interrupted.

◆ scu_dma_level2_busy()

static uint32_t scu_dma_level2_busy ( void  )
inlinestatic

Obtain the status of SCU-DMA level 2.

Returns
Whether SCU-DMA level 2 is in operation, on standby, or interrupted.

◆ scu_dma_level_busy()

static uint32_t scu_dma_level_busy ( scu_dma_level_t  level)
inlinestatic

Obtain the status of SCU-DMA level.

Parameters
levelThe SCU-DMA level.
Returns
Whether SCU-DMA level is in operation, on standby, or interrupted.

◆ scu_dma_config_buffer()

void scu_dma_config_buffer ( scu_dma_handle_t handle,
const scu_dma_level_cfg_t cfg 
)

Generates a handle from the SCU-DMA level configuration.

Parameters
[out]handleThe handle.
[in]cfgThe configuration.

◆ scu_dma_config_set()

void scu_dma_config_set ( scu_dma_level_t  level,
scu_dma_start_factor_t  start_factor,
const scu_dma_handle_t handle,
scu_dma_callback_t  callback 
)

Commits handle to SCU-DMA level I/O registers.

Parameters
levelThe SCU-DMA level.
start_factorThe starting factor.
[in]handleThe handle.
callbackThe callback when transfer is complete.

◆ scu_dma_transfer()

void scu_dma_transfer ( scu_dma_level_t  level,
void *  dst,
const void *  src,
size_t  len 
)

Perform a transfer.

Transfer is asynchronous. Use scu_dma_transfer_wait to wait for the transfer to complete.

Parameters
levelThe SCU-DMA level.
[in]dstThe pointer to write to.
[in]srcThe pointer to read from.
lenThe amount to transfer in bytes.

◆ scu_dma_transfer_wait()

void scu_dma_transfer_wait ( scu_dma_level_t  level)

Wait for a transfer to complete.

Parameters
levelThe SCU-DMA level.

◆ scu_dma_level_fast_start()

void scu_dma_level_fast_start ( scu_dma_level_t  level)

Start a SCU-DMA transfer.

There is no check if the SCU-DMA level level is currently operating.

There is no check if the SCU-DMA level level has been configured.

Parameters
level

◆ scu_dma_level_start()

void scu_dma_level_start ( scu_dma_level_t  level)

Start a SCU-DMA transfer.

The function waits until the SCU-DMA level level is not in operation or standby. There is also a check if level is 2, then it also waits until SCU-DMA level 1 is not in operation or standby.

There is no check if the SCU-DMA level level has been configured.

Parameters
level

◆ scu_dma_level_wait()

void scu_dma_level_wait ( scu_dma_level_t  level)

Wait until the SCU-DMA level is not in operation or standby.

Waits indefinitely until the SCU-DMA level level is not in operation or standby.

Parameters
levelThe SCU-DMA level.

◆ scu_dma_level_unused_get()

scu_dma_level_t scu_dma_level_unused_get ( void  )

Obtain the first unused SCU-DMA level.

Returns
SCU-DMA level 0, then 1, then 2. Otherwise, 0xFFFFFFFF is returned.