Difference between revisions of "Corelink DMA Engines"

From 3dbrew
Jump to navigation Jump to search
(Create page by moving some stuff from SVC)
 
(22 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 +
XDMA cannot access the ARM9 bootrom at all.
 +
 
==DmaConfig==
 
==DmaConfig==
 
Size of struct is 24 bytes.
 
Size of struct is 24 bytes.
Line 4: Line 6:
 
  struct DmaConfig {
 
  struct DmaConfig {
 
     sint8_t channel_sel; // @0 Selects which DMA channel to use: 0-7, -1 = don't care.
 
     sint8_t channel_sel; // @0 Selects which DMA channel to use: 0-7, -1 = don't care.
     uint8_t endian_swap_size; // @1 Accepted values: 0=none,2=16bit,4=32bit,8=64bit.
+
     uint8_t endian_swap_size; // @1 Accepted values: 0=none, 2=16bit, 4=32bit, 8=64bit.
     uint8_t flags;       // @2 bit0: DST_CFG, bit1: SRC_CFG, bit2: SHALL_BLOCK, bit3: ???, bit6: DST_ALT_CFG, bit7: SRC_ALT_CFG
+
     uint8_t flags; // @2 bit0: SRC_IS_PERIPHERAL, bit1: DST_IS_PERIPHERAL, bit2: SHALL_BLOCK, bit3: KEEP_ALIVE, bit6: SRC_IS_RAM, bit7: DST_IS_RAM
 
     uint8_t padding;
 
     uint8_t padding;
     uint8_t dst_cfg[10];
+
     DmaSubConfig dst_cfg;
     // @5 Accepted values (u8): 4, 8, 12, 15.
+
     DmaSubConfig src_cfg;
     // @15 Accepted values (u8): 4, 8, 12, 15.
+
}
     uint8_t src_cfg[10]; // @14
+
 
 +
struct DmaSubConfig {
 +
    sint8_t peripheral_id; // @0 If not *_IS_RAM set, this must be < 0x1E.
 +
    uint8_t allowed_burst_sizes; // @1 Accepted values: 4, 8, 4|8 = 12, 1|2|4|8 = 15  
 +
     sint16_t gather_granule_size; // @2
 +
    sint16_t gather_stride; // @4 Has to be >= 0, must not be 0 if peripheral_id == 0xFF.
 +
     sint16_t scatter_granule_size; // @6
 +
    sint16_t scatter_stride; // @8 Can be negative.
 
  }
 
  }
  
If SRC_CFG/DST_CFG is set in the flags field, the configuration for src/dst is loaded from src_cfg/dst_cfg respectively. If the *_ALT_CFG flag is set same thing goes, except byte0 of each cfg is forced to 0xFF. ALT_CFG has priority over CFG.
+
If SRC_IS_PERIPHERAL/SRC_IS_PERIPHERAL is set in the flags field, the configuration for src/dst is loaded from src_cfg/dst_cfg respectively and the transfer will be done from/to a fixed address. If the *_IS_RAM flag is set same thing goes, except byte0 of each cfg is forced to 0xFF (RAM) and the transfer will be done from/to an incrementing address. *_IS_RAM has priority over _IS_PERIPHERAL.
  
If CFG or ALT_CFG is not set, default configuration is loaded:
+
If neither *_IS_PERIPHERAL or *_IS_RAM is set, default configuration is loaded:
  FF 0F 80 00 00 00 80 00 00 00
+
 
 +
  .peripheral_id = 0xFF,
 +
.allowed_burst_sizes = 1 | 2 | 4 | 8,
 +
.gather_granule_size = 0x80,
 +
.gather_stride = 0,
 +
.scatter_granule_size = 0x80,
 +
.scatter_stride = 0,
  
 
If SHALL_BLOCK is set, the thread will sleep until the DMA engine is ready. If not set, the SVC will return 0xD04007F0 if the DMA channel is busy.
 
If SHALL_BLOCK is set, the thread will sleep until the DMA engine is ready. If not set, the SVC will return 0xD04007F0 if the DMA channel is busy.
  
The format of src_cfg/dst_cfg is unknown, but both have the same format. Checks suggest that the second byte of cfg equalling 4 means NO_INCREMENT (don't increment after read/write).
+
The generated bytecode starts with a FLUSHP on the peripheral_ids for src/dst (if specified). After that, it always moves 0 into DAR. Then it moves the src/dst addresses into SAR/DAR respectively...
  
Each src/dst config:
+
== CDMA Peripheral IDs ==
  struct DmaSubConfig {
+
 
    uint8_t peripheral_id; // @0
+
{| class="wikitable" border="1"
    uint8_t unk2; // @1 Seen: 2
+
! ID
    uint16_t unk3; // @2
+
! Module
    uint16_t transfer_size?; // @4
+
! Description
    uint16_t unk4; // @6
+
|-
    uint16_t unk5; // @8
+
| 0x2
}
+
| camera (cam)
 +
| Camera Port 1
 +
|-
 +
| 0x3
 +
| camera (cam)
 +
| Camera Port 2
 +
|-
 +
| 0x4
 +
| nwm
 +
| ?
 +
|-
 +
| 0x5
 +
| nwm
 +
| ?
 +
|-
 +
| 0x6
 +
| camera (y2r)
 +
| SetSendingY
 +
|-
 +
| 0x7
 +
| camera (y2r)
 +
| SetSendingU
 +
|-
 +
| 0x8
 +
| camera (y2r)
 +
| SetSendingV
 +
|-
 +
| 0x9
 +
| camera (y2r)
 +
| SetSendingYUYV
 +
|-
 +
| 0xA
 +
| camera (y2r)
 +
| SetReceiving
 +
|-
 +
| 0xB
 +
| fs
 +
| HASH
 +
|-
 +
| 0xD
 +
| TwlBg
 +
| LGYFB0/1
 +
|-
 +
| 0xE
 +
| TwlBg
 +
| LGYFB0/1
 +
|-
 +
| 0x12
 +
| mvd (y2r2)
 +
| SetSendingY
 +
|-
 +
| 0x13
 +
| mvd (y2r2)
 +
| SetSendingU
 +
|-
 +
| 0x14
 +
| mvd (y2r2)
 +
| SetSendingV
 +
|-
 +
| 0x15
 +
| mvd (y2r2)
 +
| SetSendingYUV
 +
|-
 +
| 0x16
 +
| mvd (y2r2)
 +
| SetReceiving
 +
|-
 +
| 0x17
 +
| mvd
 +
| Related to l2b
 +
|-
 +
| 0x18
 +
| mvd
 +
| Related to l2b
 +
|-
 +
| 0x19
 +
| mvd
 +
| Related to l2b
 +
|-
 +
| 0x1A
 +
| mvd
 +
| Related to l2b
 +
|}
 +
 
 +
== XDMA Peripheral IDs ==
  
The generated bytecode starts with a FLUSHP on the peripheral_ids for src/dst (if specified). After that, it always moves 0 into DAR. Then it moves the src/dst addresses into SAR/DAR respectively...
+
{| class="wikitable" border="1"
 +
!  ID
 +
!  Module
 +
!  Description
 +
|-
 +
| 0
 +
| Process9
 +
| CTRCARD
 +
|-
 +
| 7
 +
| Process9
 +
| SHA
 +
|-
 +
|}

Revision as of 12:13, 29 June 2018

XDMA cannot access the ARM9 bootrom at all.

DmaConfig

Size of struct is 24 bytes.

struct DmaConfig {
    sint8_t channel_sel; // @0 Selects which DMA channel to use: 0-7, -1 = don't care.
    uint8_t endian_swap_size; // @1 Accepted values: 0=none, 2=16bit, 4=32bit, 8=64bit.
    uint8_t flags; // @2 bit0: SRC_IS_PERIPHERAL, bit1: DST_IS_PERIPHERAL, bit2: SHALL_BLOCK, bit3: KEEP_ALIVE, bit6: SRC_IS_RAM, bit7: DST_IS_RAM
    uint8_t padding;
    DmaSubConfig dst_cfg;
    DmaSubConfig src_cfg;
}
struct DmaSubConfig {
    sint8_t peripheral_id; // @0 If not *_IS_RAM set, this must be < 0x1E.
    uint8_t allowed_burst_sizes; // @1 Accepted values: 4, 8, 4|8 = 12, 1|2|4|8 = 15 
    sint16_t gather_granule_size; // @2
    sint16_t gather_stride; // @4 Has to be >= 0, must not be 0 if peripheral_id == 0xFF.
    sint16_t scatter_granule_size; // @6
    sint16_t scatter_stride; // @8 Can be negative.
}

If SRC_IS_PERIPHERAL/SRC_IS_PERIPHERAL is set in the flags field, the configuration for src/dst is loaded from src_cfg/dst_cfg respectively and the transfer will be done from/to a fixed address. If the *_IS_RAM flag is set same thing goes, except byte0 of each cfg is forced to 0xFF (RAM) and the transfer will be done from/to an incrementing address. *_IS_RAM has priority over _IS_PERIPHERAL.

If neither *_IS_PERIPHERAL or *_IS_RAM is set, default configuration is loaded:

.peripheral_id = 0xFF,
.allowed_burst_sizes = 1 | 2 | 4 | 8,
.gather_granule_size = 0x80,
.gather_stride = 0,
.scatter_granule_size = 0x80,
.scatter_stride = 0,

If SHALL_BLOCK is set, the thread will sleep until the DMA engine is ready. If not set, the SVC will return 0xD04007F0 if the DMA channel is busy.

The generated bytecode starts with a FLUSHP on the peripheral_ids for src/dst (if specified). After that, it always moves 0 into DAR. Then it moves the src/dst addresses into SAR/DAR respectively...

CDMA Peripheral IDs

ID Module Description
0x2 camera (cam) Camera Port 1
0x3 camera (cam) Camera Port 2
0x4 nwm ?
0x5 nwm ?
0x6 camera (y2r) SetSendingY
0x7 camera (y2r) SetSendingU
0x8 camera (y2r) SetSendingV
0x9 camera (y2r) SetSendingYUYV
0xA camera (y2r) SetReceiving
0xB fs HASH
0xD TwlBg LGYFB0/1
0xE TwlBg LGYFB0/1
0x12 mvd (y2r2) SetSendingY
0x13 mvd (y2r2) SetSendingU
0x14 mvd (y2r2) SetSendingV
0x15 mvd (y2r2) SetSendingYUV
0x16 mvd (y2r2) SetReceiving
0x17 mvd Related to l2b
0x18 mvd Related to l2b
0x19 mvd Related to l2b
0x1A mvd Related to l2b

XDMA Peripheral IDs

ID Module Description
0 Process9 CTRCARD
7 Process9 SHA