Line 1,356: |
Line 1,356: |
| Note that with the MAP MemoryOperation, the kernel will refuse to MAP memory for the specified addr1, when addr1 was already used with another MAP operation as addr1. The kernel also doesn't allow memory to be freed via the FREE MemoryOperation, when other virtual-memory is mapped to this same memory(when the MAP MemoryOperation was used with this memory with addr1). | | Note that with the MAP MemoryOperation, the kernel will refuse to MAP memory for the specified addr1, when addr1 was already used with another MAP operation as addr1. The kernel also doesn't allow memory to be freed via the FREE MemoryOperation, when other virtual-memory is mapped to this same memory(when the MAP MemoryOperation was used with this memory with addr1). |
| | | |
− | = DMA = | + | = [[DMA]] = |
| The CTRSDK code for using svcStartInterProcessDma will execute svcBreak when svcStartInterProcessDma returns an error(except for certain error value(s)). Therefore on retail, triggering a svcStartInterProcessDma via a system-module which results in an error from svcStartInterProcessDma will result in the system-module terminating. | | The CTRSDK code for using svcStartInterProcessDma will execute svcBreak when svcStartInterProcessDma returns an error(except for certain error value(s)). Therefore on retail, triggering a svcStartInterProcessDma via a system-module which results in an error from svcStartInterProcessDma will result in the system-module terminating. |
− |
| |
− | ==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: DST_CFG, bit1: SRC_CFG, bit2: SHALL_BLOCK, bit3: ???, bit6: DST_ALT_CFG, bit7: SRC_ALT_CFG
| |
− | uint8_t padding;
| |
− | uint8_t dst_cfg[10];
| |
− | // @5 Accepted values (u8): 4, 8, 12, 15.
| |
− | // @15 Accepted values (u8): 4, 8, 12, 15.
| |
− | uint8_t src_cfg[10]; // @14
| |
− | }
| |
− |
| |
− | 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 CFG or ALT_CFG is not set, default configuration is loaded:
| |
− | FF 0F 80 00 00 00 80 00 00 00
| |
− |
| |
− | 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).
| |
− |
| |
− | Each src/dst config:
| |
− | struct DmaSubConfig {
| |
− | uint8_t peripheral_id; // @0
| |
− | uint8_t unk2; // @1 Seen: 2
| |
− | uint16_t unk3; // @2
| |
− | uint16_t transfer_size?; // @4
| |
− | uint16_t unk4; // @6
| |
− | uint16_t unk5; // @8
| |
− | }
| |
− |
| |
− | 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...
| |
| | | |
| = Debugging = | | = Debugging = |