Alchemy
Loading...
Searching...
No Matches

dma.h

Go to the documentation of this file.
1#ifndef ALCHEMY_DMA_H
2#define ALCHEMY_DMA_H
3
4/// @file
5/// DMA channel registers, and the DMA and CPU fills.
6
7#include "io_reg.h"
8#include "types.h"
9
10/// A DMA channel's registers (DMAxSAD, DMAxDAD, DMAxCNT).
14 u32 control; ///< The count in the low half, DMAxCNT_H's flags above it.
15};
16
17/// DMA3, the channel the game copies with, as its three registers.
18#define DMA3 ((volatile struct DmaRegisters *)REG_DMA3)
19
20/// Fills `size` bytes at `destination` with the halfword `value` by DMA3, from
21/// a volatile copy of it on the stack.
22#define Dma_Fill16(value, destination, size) \
23 { \
24 volatile u16 fill_ = (value); \
25 Dma_Set((const void *)&fill_, (destination), \
26 (DMA_ENABLE | DMA_SRC_FIXED) << 16 | ((size) / 2), REG_DMA3); \
27 }
28
29/// Fills `size` bytes at `destination` with the word `value` by DMA3.
30#define Dma_Fill32(value, destination, size) \
31 { \
32 volatile u32 fill_ = (value); \
33 Dma_Set((const void *)&fill_, (destination), \
34 (DMA_ENABLE | DMA_32BIT | DMA_SRC_FIXED) << 16 | ((size) / 4), \
35 REG_DMA3); \
36 }
37
38/// Dma_Fill32 through the caller's own volatile word `cell`, so a function that
39/// fills several blocks keeps one word for all of them and forms its address
40/// once; the word also takes the caller's place in the frame
41/// (Map_InitializePerspectiveScene's sp+28, where Dma_Fill32's would be sp+16).
42#define Dma_Fill32Cell(cell, value, destination, size) \
43 { \
44 (cell) = (value); \
45 Dma_Set((const void *)&(cell), (destination), \
46 (DMA_ENABLE | DMA_32BIT | DMA_SRC_FIXED) << 16 | ((size) / 4), \
47 REG_DMA3); \
48 }
49
50/// pret's CpuFill32: repeats one word through the BIOS CpuSet service.
51#define Cpu_Fill32(value, destination, size) \
52 { \
53 volatile u32 fill_ = (value); \
54 Bios_CpuSet((const void *)&fill_, (destination), \
55 CPU_SET_32BIT | CPU_SET_SRC_FIXED | ((size) / 4)); \
56 }
57
58/// Starts a DMA transfer: stores the source, destination and control words
59/// into `channel`'s registers with one stmia.
60CAMELOT_ASM("stmia of three registers with no paired ldmia, which no agscc "
61 "pattern emits")
62static __inline__ void Dma_Set(const volatile void *source,
63 volatile void *destination, u32 control,
64 volatile u32 *channel) {
65 // The channel is an input only, so callers keep it in a register across
66 // adjacent transfers and form nearby I/O addresses from it.
67 register volatile u32 *dma __asm__("r3") = channel;
68 register u32 src __asm__("r0") = (u32)source;
69 register u32 dst __asm__("r1") = (u32)destination;
70 register u32 cnt __asm__("r2") = control;
71 __asm__ volatile("stmia %2!, {%0, %3, %1}\n\tsub %2, #12"
72 : "+r"(src), "+r"(cnt)
73 : "r"(dma), "r"(dst)
74 : "memory", "cc");
75}
76
77#endif
static __inline__ void Dma_Set(const volatile void *source, volatile void *destination, u32 control, volatile u32 *channel)
Starts a DMA transfer: stores the source, destination and control words into channel's registers with...
Definition dma.h:62
The hardware's I/O registers and their bits, as pret names them.
A DMA channel's registers (DMAxSAD, DMAxDAD, DMAxCNT).
Definition dma.h:11
u32 control
The count in the low half, DMAxCNT_H's flags above it.
Definition dma.h:14
u32 source
Definition dma.h:12
u32 destination
Definition dma.h:13
The integer types, TRUE, UNUSED and the fixed-address macros.
unsigned int u32
Definition types.h:15
#define CAMELOT_ASM(proof)
Definition types.h:46