mirror of
https://github.com/LNH-team/pico-loader.git
synced 2026-06-02 09:16:49 +02:00
@@ -190,7 +190,7 @@ bool DsttLoaderPlatform::InitializeSdCard(void)
|
||||
if (isSdhc)
|
||||
{
|
||||
sdHostSetRegister(DSTT_SD_HOST_REG_RESET | DSTT_SD_HOST_REG_CLEAN_ROM_MODE | DSTT_SD_HOST_REG_SDHC);
|
||||
dstt_readSd_sdsc_shift = THUMB_MOVS_REG(THUMB_R7, THUMB_R0);
|
||||
dstt_readSd_sdsc_shift = THUMB_MOVS_REG(THUMB_R6, THUMB_R0);
|
||||
dstt_writeSd_sdsc_shift = THUMB_NOP;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#pragma once
|
||||
#include "../LoaderPlatform.h"
|
||||
#include "DsttReadSdPatchCode.h"
|
||||
#include "DsttReadSdDmaPatchCode.h"
|
||||
#include "DsttWriteSdPatchCode.h"
|
||||
#include "DsttSdStopTransmissionPatchCode.h"
|
||||
#include "DsttReadSdHelperPatchCode.h"
|
||||
|
||||
/// @brief Implementation of LoaderPlatform for the DSTT flashcard
|
||||
class DsttLoaderPlatform : public LoaderPlatform
|
||||
@@ -15,11 +18,30 @@ public:
|
||||
return new DsttReadSdPatchCode(patchHeap,
|
||||
patchCodeCollection.GetOrAddSharedPatchCode([&]
|
||||
{
|
||||
return new DsttReadSdStopTransmissionPatchCode(patchHeap);
|
||||
return new DsttSdStopTransmissionPatchCode(patchHeap);
|
||||
}),
|
||||
patchCodeCollection.GetOrAddSharedPatchCode([&]
|
||||
{
|
||||
return new DsttReadSdHelperPatchCode(patchHeap);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
const IReadSectorsDmaPatchCode* CreateSdReadDmaPatchCode(PatchCodeCollection& patchCodeCollection,
|
||||
PatchHeap& patchHeap, const void* miiCardDmaCopy32Ptr) const override
|
||||
{
|
||||
return patchCodeCollection.AddUniquePatchCode<DsttReadSdDmaPatchCode>(
|
||||
patchHeap, miiCardDmaCopy32Ptr,
|
||||
patchCodeCollection.GetOrAddSharedPatchCode([&]
|
||||
{
|
||||
return new DsttSdStopTransmissionPatchCode(patchHeap);
|
||||
}),
|
||||
patchCodeCollection.GetOrAddSharedPatchCode([&]
|
||||
{
|
||||
return new DsttReadSdHelperPatchCode(patchHeap);
|
||||
}));
|
||||
}
|
||||
|
||||
const IWriteSectorsPatchCode* CreateSdWritePatchCode(
|
||||
PatchCodeCollection& patchCodeCollection, PatchHeap& patchHeap) const override
|
||||
{
|
||||
@@ -35,5 +57,7 @@ public:
|
||||
|
||||
LoaderPlatformType GetPlatformType() const override { return LoaderPlatformType::Slot1; }
|
||||
|
||||
bool HasDmaSdReads() const override { return true; }
|
||||
|
||||
bool InitializeSdCard() override;
|
||||
};
|
||||
|
||||
44
arm9/source/patches/platform/dstt/DsttReadSdDmaPatchCode.h
Normal file
44
arm9/source/patches/platform/dstt/DsttReadSdDmaPatchCode.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
#include "sections.h"
|
||||
#include "patches/PatchCode.h"
|
||||
#include "../IReadSectorsDmaPatchCode.h"
|
||||
#include "DsttSdStopTransmissionPatchCode.h"
|
||||
#include "DsttReadSdHelperPatchCode.h"
|
||||
|
||||
DEFINE_SECTION_SYMBOLS(dstt_readsddma);
|
||||
|
||||
extern "C" void dstt_readSdDma(u32 srcSector, u32 previousSrcSector, u32 dmaChannel, void* dst);
|
||||
|
||||
extern u32 dstt_readSdDma_applySectorCommand_address;
|
||||
extern u32 dstt_readSdDma_waitDataReady_address;
|
||||
extern u32 dstt_readSdDma_stopTransmission_address;
|
||||
extern u32 dstt_readSdDma_miiCardDmaCopy32Ptr;
|
||||
|
||||
class DsttReadSdDmaPatchCode : public PatchCode, public IReadSectorsDmaPatchCode
|
||||
{
|
||||
public:
|
||||
DsttReadSdDmaPatchCode(PatchHeap& patchHeap, const void* miiCardDmaCopy32Ptr,
|
||||
const DsttSdStopTransmissionPatchCode* dsttSdStopTransmissionPatchCode,
|
||||
const DsttReadSdHelperPatchCode* dsttReadSdHelperPatchCode)
|
||||
: PatchCode(SECTION_START(dstt_readsddma), SECTION_SIZE(dstt_readsddma), patchHeap)
|
||||
{
|
||||
dstt_readSdDma_miiCardDmaCopy32Ptr = (u32)miiCardDmaCopy32Ptr;
|
||||
dstt_readSdDma_stopTransmission_address = (u32)dsttSdStopTransmissionPatchCode->GetStopTransmissionFunction();
|
||||
dstt_readSdDma_applySectorCommand_address = (u32)dsttReadSdHelperPatchCode->GetApplySectorCommandFunction();
|
||||
dstt_readSdDma_waitDataReady_address = (u32)dsttReadSdHelperPatchCode->GetWaitDataReadyFunction();
|
||||
_sdReadDmaFinishFunc = (ReadSectorsDmaFinishFunc)dsttSdStopTransmissionPatchCode->GetStopTransmissionFunction();
|
||||
}
|
||||
|
||||
const ReadSectorsDmaFunc GetReadSectorsDmaFunction() const override
|
||||
{
|
||||
return (const ReadSectorsDmaFunc)GetAddressAtTarget((void*)dstt_readSdDma);
|
||||
}
|
||||
|
||||
const ReadSectorsDmaFinishFunc GetReadSectorsDmaFinishFunction() const override
|
||||
{
|
||||
return _sdReadDmaFinishFunc;
|
||||
}
|
||||
|
||||
private:
|
||||
ReadSectorsDmaFinishFunc _sdReadDmaFinishFunc = 0;
|
||||
};
|
||||
111
arm9/source/patches/platform/dstt/DsttReadSdDmaPatchCode.s
Normal file
111
arm9/source/patches/platform/dstt/DsttReadSdDmaPatchCode.s
Normal file
@@ -0,0 +1,111 @@
|
||||
.cpu arm946e-s
|
||||
.section "dstt_readsddma", "ax"
|
||||
.syntax unified
|
||||
.thumb
|
||||
|
||||
// r0 = src sector
|
||||
// r1 = previous src sector
|
||||
// r2 = dma channel
|
||||
// r3 = dst
|
||||
.global dstt_readSdDma
|
||||
.type dstt_readSdDma, %function
|
||||
dstt_readSdDma:
|
||||
push {r2-r7,lr}
|
||||
|
||||
ldr r4, =0x040001A0
|
||||
|
||||
movs r3, #0x80
|
||||
strb r3, [r4,#1]
|
||||
|
||||
adr r2, dstt_romSettings
|
||||
// r2 - dstt_romSettings
|
||||
// r3 - dstt_readSdDma_applySectorCommand_address
|
||||
// r5 - dstt_readSdDma_stopTransmission_address
|
||||
// r6 - dstt_readSdDma_waitDataReady_address
|
||||
// r7 - dstt_readSdDma_miiCardDmaCopy32Ptr
|
||||
ldmia r2, {r2, r3, r5, r6, r7}
|
||||
|
||||
cmp r1, #0
|
||||
beq applySector
|
||||
|
||||
subs r1, r0, r1
|
||||
cmp r1, #1 // if sequential
|
||||
beq sector_loop_sequential
|
||||
|
||||
blx r5 // dstt_readSdDma_stopTransmission_address
|
||||
|
||||
applySector:
|
||||
blx r3 // dstt_readSdDma_applySectorCommand_address
|
||||
|
||||
b sector_loop
|
||||
|
||||
sector_loop_sequential:
|
||||
// set sd host mode DSTT_MODE_RECEIVE_DATA_BLOCK_STOP_CLOCK
|
||||
// 51 00 00 00 00 00 07 00
|
||||
movs r1, #0x51
|
||||
str r1, [r4, #0x8]
|
||||
movs r1, #7
|
||||
lsls r1, r1, #16
|
||||
str r1, [r4, #0xC]
|
||||
|
||||
sector_loop:
|
||||
str r2, [r4,#4]
|
||||
|
||||
movs r1, #0x41
|
||||
lsls r1, r1, #20 // r1 = 0x04100000
|
||||
|
||||
cmd_wait_loop:
|
||||
ldrb r3, [r4,#6]
|
||||
lsrs r3, r3, #8
|
||||
bcc cmd_wait_loop
|
||||
|
||||
ldr r3, [r1, #0x10]
|
||||
blx r6 // dstt_readSdDma_waitDataReady_address
|
||||
|
||||
// previous push had r2 = dma channel, r3 = dst at top of stack
|
||||
// pop to the correct register for miiCardDmaCopy32
|
||||
pop {r0, r2}
|
||||
adds r1, #0x10 // Source. r1 is 0x04100000 from the calling function
|
||||
movs r3, #1
|
||||
lsls r3, r3, #9 // (1 << 9) = 512 = count
|
||||
|
||||
blx r7 // dstt_readSdDma_miiCardDmaCopy32Ptr
|
||||
|
||||
cmd81_poll_dma:
|
||||
// read sd fifo
|
||||
// 81 xx xx xx xx xx xx xx
|
||||
// xx bytes are leftover from previous command
|
||||
movs r1, #0x81
|
||||
strb r1, [r4,#0x8]
|
||||
|
||||
movs r1, #0xC0 // select rom mode, with irq
|
||||
strb r1, [r4,#0x1]
|
||||
movs r1, #0xA1
|
||||
strb r1, [r4,#7]
|
||||
|
||||
pop {r4-r7,pc}
|
||||
|
||||
.balign 4
|
||||
|
||||
dstt_romSettings:
|
||||
.word 0xA7180000
|
||||
|
||||
.global dstt_readSdDma_applySectorCommand_address
|
||||
dstt_readSdDma_applySectorCommand_address:
|
||||
.word 0
|
||||
|
||||
.global dstt_readSdDma_stopTransmission_address
|
||||
dstt_readSdDma_stopTransmission_address:
|
||||
.word 0
|
||||
|
||||
.global dstt_readSdDma_waitDataReady_address
|
||||
dstt_readSdDma_waitDataReady_address:
|
||||
.word 0
|
||||
|
||||
.global dstt_readSdDma_miiCardDmaCopy32Ptr
|
||||
dstt_readSdDma_miiCardDmaCopy32Ptr:
|
||||
.word 0
|
||||
|
||||
.pool
|
||||
|
||||
.end
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "sections.h"
|
||||
#include "thumbInstructions.h"
|
||||
#include "patches/PatchCode.h"
|
||||
|
||||
DEFINE_SECTION_SYMBOLS(dstt_readsd_helper);
|
||||
|
||||
extern "C" void dstt_readSd_applySectorCommand(void);
|
||||
extern "C" void dstt_readSd_waitDataReady(void);
|
||||
extern "C" void dstt_readSd_transferData();
|
||||
|
||||
extern u16 dstt_readSd_sdsc_shift;
|
||||
|
||||
class DsttReadSdHelperPatchCode : public PatchCode
|
||||
{
|
||||
public:
|
||||
explicit DsttReadSdHelperPatchCode(PatchHeap& patchHeap)
|
||||
: PatchCode(SECTION_START(dstt_readsd_helper), SECTION_SIZE(dstt_readsd_helper), patchHeap) { }
|
||||
|
||||
const void* GetApplySectorCommandFunction() const
|
||||
{
|
||||
return GetAddressAtTarget((void*)dstt_readSd_applySectorCommand);
|
||||
}
|
||||
|
||||
const void* GetWaitDataReadyFunction() const
|
||||
{
|
||||
return GetAddressAtTarget((void*)dstt_readSd_waitDataReady);
|
||||
}
|
||||
|
||||
const void* GetTransferDataFunction() const
|
||||
{
|
||||
return GetAddressAtTarget((void*)dstt_readSd_transferData);
|
||||
}
|
||||
};
|
||||
103
arm9/source/patches/platform/dstt/DsttReadSdHelperPatchCode.s
Normal file
103
arm9/source/patches/platform/dstt/DsttReadSdHelperPatchCode.s
Normal file
@@ -0,0 +1,103 @@
|
||||
.cpu arm7tdmi
|
||||
.section "dstt_readsd_helper", "ax"
|
||||
.syntax unified
|
||||
.thumb
|
||||
|
||||
// r0 = src sector
|
||||
.global dstt_readSd_applySectorCommand
|
||||
.type dstt_readSd_applySectorCommand, %function
|
||||
dstt_readSd_applySectorCommand:
|
||||
push {r5-r6,lr}
|
||||
|
||||
.global dstt_readSd_sdsc_shift
|
||||
dstt_readSd_sdsc_shift:
|
||||
lsls r6, r0, #9
|
||||
|
||||
// request sd read for sector 0xaabbccdd
|
||||
// 54 aa bb cc dd 00 00 00
|
||||
movs r5, #0x54
|
||||
strb r5, [r4,#0x8]
|
||||
lsrs r5, r6, #24
|
||||
strb r5, [r4,#0x9]
|
||||
lsrs r5, r6, #16
|
||||
strb r5, [r4,#0xA]
|
||||
lsrs r5, r6, #8
|
||||
strb r5, [r4,#0xB]
|
||||
// make sure the last 3 bytes are zero
|
||||
movs r5, #0xFF
|
||||
ands r6, r5
|
||||
str r6, [r4,#0xC] // storing as little-endian puts the bottom 8 bits as first byte
|
||||
|
||||
pop {r5-r6,pc}
|
||||
|
||||
.balign 4
|
||||
|
||||
.global dstt_readSd_waitDataReady
|
||||
.type dstt_readSd_waitDataReady, %function
|
||||
dstt_readSd_waitDataReady:
|
||||
push {r5-r7,lr}
|
||||
|
||||
movs r6, #0x41
|
||||
lsls r6, r6, #20 // r6 = 0x04100000
|
||||
|
||||
// sd fifo full poll
|
||||
// 80 xx xx xx xx xx xx xx
|
||||
// xx bytes are leftover from previous command
|
||||
movs r7, #0x80
|
||||
strb r7, [r4,#0x8]
|
||||
|
||||
ldr r7, =0xA7180000
|
||||
cmd80_poll_loop:
|
||||
str r7, [r4,#4]
|
||||
|
||||
cmd80_wait_loop:
|
||||
ldrb r5, [r4,#6]
|
||||
lsrs r5, r5, #8
|
||||
bcc cmd80_wait_loop
|
||||
ldr r5, [r6, #0x10]
|
||||
cmp r5, #0
|
||||
bne cmd80_poll_loop
|
||||
|
||||
pop {r5-r7,pc}
|
||||
|
||||
.balign 4
|
||||
|
||||
// r1 = dst, will be incremented by 512
|
||||
.global dstt_readSd_transferData
|
||||
.type dstt_readSd_transferData, %function
|
||||
dstt_readSd_transferData:
|
||||
push {r5-r7,lr}
|
||||
|
||||
ldr r5, =0xA7180000
|
||||
|
||||
movs r6, #0x41
|
||||
lsls r6, r6, #20 // r6 = 0x04100000
|
||||
|
||||
// read sd fifo
|
||||
// 81 xx xx xx xx xx xx xx
|
||||
// xx bytes are leftover from previous command
|
||||
movs r5, #0x81
|
||||
strb r5, [r4,#0x8]
|
||||
movs r5, #0xA1
|
||||
strb r5, [r4,#7]
|
||||
|
||||
cmd81_data_loop:
|
||||
ldrb r5, [r4,#6]
|
||||
lsrs r5, r5, #8 // check if data is ready
|
||||
bcc cmd81_data_loop_check_transfer_end // if not skip reading
|
||||
|
||||
ldr r5, [r6, #0x10]
|
||||
stmia r1!, {r5}
|
||||
|
||||
cmd81_data_loop_check_transfer_end:
|
||||
ldrb r5, [r4,#7]
|
||||
lsrs r5, r5, #8 // check if transfer is done
|
||||
bcs cmd81_data_loop
|
||||
|
||||
pop {r5-r7,pc}
|
||||
|
||||
.balign 4
|
||||
|
||||
.pool
|
||||
|
||||
.end
|
||||
@@ -3,36 +3,30 @@
|
||||
#include "thumbInstructions.h"
|
||||
#include "patches/PatchCode.h"
|
||||
#include "../IReadSectorsPatchCode.h"
|
||||
#include "DsttSdStopTransmissionPatchCode.h"
|
||||
#include "DsttReadSdHelperPatchCode.h"
|
||||
|
||||
DEFINE_SECTION_SYMBOLS(dstt_readsd);
|
||||
DEFINE_SECTION_SYMBOLS(dstt_readsd_stopTransmission);
|
||||
|
||||
extern "C" void dstt_readSd(u32 srcSector, void* dst, u32 sectorCount);
|
||||
extern "C" void dstt_stopTransmission();
|
||||
|
||||
extern u32 dstt_readSd_applySectorCommand_address;
|
||||
extern u32 dstt_waitDataReady_address;
|
||||
extern u32 dstt_transferData_address;
|
||||
extern u32 dstt_stopTransmission_address;
|
||||
extern u16 dstt_readSd_sdsc_shift;
|
||||
|
||||
class DsttReadSdStopTransmissionPatchCode : public PatchCode
|
||||
{
|
||||
public:
|
||||
explicit DsttReadSdStopTransmissionPatchCode(PatchHeap& patchHeap)
|
||||
: PatchCode(SECTION_START(dstt_readsd_stopTransmission), SECTION_SIZE(dstt_readsd_stopTransmission), patchHeap) { }
|
||||
|
||||
const void* GetStopTransmissionFunction() const
|
||||
{
|
||||
return GetAddressAtTarget((void*)dstt_stopTransmission);
|
||||
}
|
||||
};
|
||||
|
||||
class DsttReadSdPatchCode : public PatchCode, public IReadSectorsPatchCode
|
||||
{
|
||||
public:
|
||||
explicit DsttReadSdPatchCode(PatchHeap& patchHeap,
|
||||
const DsttReadSdStopTransmissionPatchCode* dsttReadSdStopTransmissionPatchCode)
|
||||
const DsttSdStopTransmissionPatchCode* dsttSdStopTransmissionPatchCode,
|
||||
const DsttReadSdHelperPatchCode* dsttReadSdHelperPatchCode)
|
||||
: PatchCode(SECTION_START(dstt_readsd), SECTION_SIZE(dstt_readsd), patchHeap)
|
||||
{
|
||||
dstt_stopTransmission_address = (u32)dsttReadSdStopTransmissionPatchCode->GetStopTransmissionFunction();
|
||||
dstt_readSd_applySectorCommand_address = (u32)dsttReadSdHelperPatchCode->GetApplySectorCommandFunction();
|
||||
dstt_stopTransmission_address = (u32)dsttSdStopTransmissionPatchCode->GetStopTransmissionFunction();
|
||||
dstt_waitDataReady_address = (u32)dsttReadSdHelperPatchCode->GetWaitDataReadyFunction();
|
||||
dstt_transferData_address = (u32)dsttReadSdHelperPatchCode->GetTransferDataFunction();
|
||||
}
|
||||
|
||||
const ReadSectorsFunc GetReadSectorsFunction() const override
|
||||
|
||||
@@ -11,27 +11,11 @@
|
||||
dstt_readSd:
|
||||
push {r4-r7,lr}
|
||||
|
||||
.global dstt_readSd_sdsc_shift
|
||||
dstt_readSd_sdsc_shift:
|
||||
lsls r7, r0, #9
|
||||
ldr r3, =0xA7180000
|
||||
ldr r4, =0x040001A0
|
||||
|
||||
adr r0, dstt_stopTransmission_address
|
||||
ldmia r0, {r0, r3, r4}
|
||||
|
||||
// request sd read for sector 0xaabbccdd
|
||||
// 54 aa bb cc dd 00 00 00
|
||||
movs r5, #0x54
|
||||
strb r5, [r4,#0x8]
|
||||
lsrs r5, r7, #24
|
||||
strb r5, [r4,#0x9]
|
||||
lsrs r5, r7, #16
|
||||
strb r5, [r4,#0xA]
|
||||
lsrs r5, r7, #8
|
||||
strb r5, [r4,#0xB]
|
||||
// make sure the last 3 bytes are zero
|
||||
movs r5, #0xFF
|
||||
ands r7, r5
|
||||
str r7, [r4,#0xC] // storing as little-endian puts the bottom 8 bits as first byte
|
||||
ldr r7, dstt_readSd_applySectorCommand_address
|
||||
bl blx_r7
|
||||
|
||||
movs r7, #0x80
|
||||
strb r7, [r4,#1]
|
||||
@@ -48,42 +32,11 @@ cmd54_wait_loop:
|
||||
bcc cmd54_wait_loop
|
||||
|
||||
ldr r5, [r6, #0x10]
|
||||
// sd fifo full poll
|
||||
// 80 xx xx xx xx xx xx xx
|
||||
// xx bytes are leftover from previous command
|
||||
strb r7, [r4,#0x8]
|
||||
ldr r7, dstt_waitDataReady_address
|
||||
bl blx_r7
|
||||
|
||||
cmd80_poll_loop:
|
||||
str r3, [r4,#4]
|
||||
|
||||
cmd80_wait_loop:
|
||||
ldrb r5, [r4,#6]
|
||||
lsrs r5, r5, #8
|
||||
bcc cmd80_wait_loop
|
||||
ldr r5, [r6, #0x10]
|
||||
cmp r5, #0
|
||||
bne cmd80_poll_loop
|
||||
|
||||
// read sd fifo
|
||||
// 81 xx xx xx xx xx xx xx
|
||||
// xx bytes are leftover from previous command
|
||||
movs r5, #0x81
|
||||
strb r5, [r4,#0x8]
|
||||
movs r5, #0xA1
|
||||
strb r5, [r4,#7]
|
||||
|
||||
cmd81_data_loop:
|
||||
ldrb r5, [r4,#6]
|
||||
lsrs r5, r5, #8 // check if data is ready
|
||||
bcc cmd81_data_loop_check_transfer_end // if not skip reading
|
||||
|
||||
ldr r5, [r6, #0x10]
|
||||
stmia r1!, {r5}
|
||||
|
||||
cmd81_data_loop_check_transfer_end:
|
||||
ldrb r5, [r4,#7]
|
||||
lsrs r5, r5, #8 // check if transfer is done
|
||||
bcs cmd81_data_loop
|
||||
ldr r7, dstt_transferData_address
|
||||
bl blx_r7
|
||||
|
||||
subs r2, #1
|
||||
beq stop_transmission
|
||||
@@ -99,77 +52,31 @@ cmd81_data_loop_check_transfer_end:
|
||||
b sector_loop
|
||||
|
||||
stop_transmission:
|
||||
bx r0
|
||||
ldr r7, dstt_stopTransmission_address
|
||||
bl blx_r7
|
||||
pop {r4-r7,pc}
|
||||
|
||||
blx_r7:
|
||||
bx r7
|
||||
|
||||
.balign 4
|
||||
|
||||
.global dstt_readSd_applySectorCommand_address
|
||||
dstt_readSd_applySectorCommand_address:
|
||||
.word 0
|
||||
|
||||
.global dstt_waitDataReady_address
|
||||
dstt_waitDataReady_address:
|
||||
.word 0
|
||||
|
||||
.global dstt_transferData_address
|
||||
dstt_transferData_address:
|
||||
.word 0
|
||||
|
||||
.global dstt_stopTransmission_address
|
||||
dstt_stopTransmission_address:
|
||||
.word 0
|
||||
|
||||
settings:
|
||||
.word 0xA7180000
|
||||
|
||||
regbase:
|
||||
.word 0x040001A0
|
||||
|
||||
.pool
|
||||
|
||||
.section "dstt_readsd_stopTransmission", "ax"
|
||||
.thumb
|
||||
.global dstt_stopTransmission
|
||||
.type dstt_stopTransmission, %function
|
||||
dstt_stopTransmission:
|
||||
// send SD_CMD12_STOP_TRANSMISSION
|
||||
|
||||
// set sd host mode DSTT_MODE_SDCMD_RESPONSE_32BIT, SD_CMD12_STOP_TRANSMISSION
|
||||
// 51 00 00 00 00 0C 01 00
|
||||
movs r5, #0x51
|
||||
str r5, [r4,#0x8]
|
||||
ldr r5,= 0x00010C00
|
||||
str r5, [r4,#0xC]
|
||||
str r3, [r4,#4]
|
||||
|
||||
cmd51_1_wait_loop:
|
||||
ldrb r5, [r4,#6]
|
||||
lsrs r5, r5, #8
|
||||
bcc cmd51_1_wait_loop
|
||||
ldr r5, [r6, #0x10]
|
||||
|
||||
// sd busy poll
|
||||
// 50 xx xx xx xx xx xx xx
|
||||
// xx bytes are leftover from previous command
|
||||
movs r5, #0x50
|
||||
strb r5, [r4,#0x8]
|
||||
|
||||
cmd50_poll_loop:
|
||||
str r3, [r4,#4]
|
||||
|
||||
cmd50_wait_loop:
|
||||
ldrb r5, [r4,#6]
|
||||
lsrs r5, r5, #8
|
||||
bcc cmd50_wait_loop
|
||||
ldr r5, [r6, #0x10]
|
||||
cmp r5, #0
|
||||
bne cmd50_poll_loop
|
||||
|
||||
// read sd response
|
||||
// 52 xx xx xx xx xx xx xx
|
||||
// xx bytes are leftover from previous command
|
||||
movs r5, #0x52
|
||||
strb r5, [r4,#0x8]
|
||||
str r3, [r4,#4]
|
||||
|
||||
cmd52_wait_loop:
|
||||
ldrb r5, [r4,#6]
|
||||
lsrs r5, r5, #8
|
||||
bcc cmd52_wait_loop
|
||||
ldr r5, [r6, #0x10]
|
||||
|
||||
pop {r4-r7,pc}
|
||||
|
||||
.balign 4
|
||||
|
||||
.pool
|
||||
|
||||
.end
|
||||
.end
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "sections.h"
|
||||
#include "thumbInstructions.h"
|
||||
#include "patches/PatchCode.h"
|
||||
|
||||
DEFINE_SECTION_SYMBOLS(dstt_sdstoptransmission);
|
||||
|
||||
extern "C" void dstt_sdStopTransmission();
|
||||
|
||||
class DsttSdStopTransmissionPatchCode : public PatchCode
|
||||
{
|
||||
public:
|
||||
explicit DsttSdStopTransmissionPatchCode(PatchHeap& patchHeap)
|
||||
: PatchCode(SECTION_START(dstt_sdstoptransmission), SECTION_SIZE(dstt_sdstoptransmission), patchHeap) { }
|
||||
|
||||
const void* GetStopTransmissionFunction() const
|
||||
{
|
||||
return GetAddressAtTarget((void*)dstt_sdStopTransmission);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
.cpu arm7tdmi
|
||||
.syntax unified
|
||||
.thumb
|
||||
|
||||
.section "dstt_sdstoptransmission", "ax"
|
||||
.global dstt_sdStopTransmission
|
||||
.type dstt_sdStopTransmission, %function
|
||||
dstt_sdStopTransmission:
|
||||
// send SD_CMD12_STOP_TRANSMISSION
|
||||
push {r3-r6,lr}
|
||||
|
||||
ldr r3, =0xA7180000
|
||||
ldr r4, =0x040001A0
|
||||
|
||||
// select rom mode, without irq
|
||||
// the caller may not have ensured this is set
|
||||
movs r6, #0x80
|
||||
strb r6, [r4,#1]
|
||||
|
||||
// set sd host mode DSTT_MODE_SDCMD_RESPONSE_32BIT, SD_CMD12_STOP_TRANSMISSION
|
||||
// 51 00 00 00 00 0C 01 00
|
||||
movs r5, #0x51
|
||||
str r5, [r4,#0x8]
|
||||
ldr r5,= 0x00010C00
|
||||
str r5, [r4,#0xC]
|
||||
str r3, [r4,#0x4]
|
||||
|
||||
movs r6, #0x41
|
||||
lsls r6, r6, #20 // r6 = 0x04100000
|
||||
|
||||
cmd51_1_wait_loop:
|
||||
ldrb r5, [r4,#6]
|
||||
lsrs r5, r5, #8
|
||||
bcc cmd51_1_wait_loop
|
||||
ldr r5, [r6, #0x10]
|
||||
|
||||
// sd busy poll
|
||||
// 50 xx xx xx xx xx xx xx
|
||||
// xx bytes are leftover from previous command
|
||||
movs r5, #0x50
|
||||
strb r5, [r4,#0x8]
|
||||
|
||||
cmd50_poll_loop:
|
||||
str r3, [r4,#4]
|
||||
|
||||
cmd50_wait_loop:
|
||||
ldrb r5, [r4,#6]
|
||||
lsrs r5, r5, #8
|
||||
bcc cmd50_wait_loop
|
||||
ldr r5, [r6, #0x10]
|
||||
cmp r5, #0
|
||||
bne cmd50_poll_loop
|
||||
|
||||
// read sd response
|
||||
// 52 xx xx xx xx xx xx xx
|
||||
// xx bytes are leftover from previous command
|
||||
movs r5, #0x52
|
||||
strb r5, [r4,#0x8]
|
||||
str r3, [r4,#4]
|
||||
|
||||
cmd52_wait_loop:
|
||||
ldrb r5, [r4,#6]
|
||||
lsrs r5, r5, #8
|
||||
bcc cmd52_wait_loop
|
||||
ldr r5, [r6, #0x10]
|
||||
|
||||
pop {r3-r6,pc}
|
||||
|
||||
.balign 4
|
||||
|
||||
.pool
|
||||
|
||||
.end
|
||||
Reference in New Issue
Block a user