mirror of
https://github.com/LNH-team/pico-loader.git
synced 2026-06-02 01:06:50 +02:00
Perform more optimization in supercard platform (#107)
This commit is contained in:
@@ -6,8 +6,8 @@ DEFINE_SECTION_SYMBOLS(scsd_change_mode);
|
|||||||
DEFINE_SECTION_SYMBOLS(scsd_common);
|
DEFINE_SECTION_SYMBOLS(scsd_common);
|
||||||
|
|
||||||
extern "C" void sccmn_changeMode();
|
extern "C" void sccmn_changeMode();
|
||||||
|
|
||||||
extern "C" void sccmn_sdSendClock10();
|
extern "C" void sccmn_sdSendClock10();
|
||||||
|
|
||||||
extern "C" void sccmn_sdio4BitCrc16();
|
extern "C" void sccmn_sdio4BitCrc16();
|
||||||
|
|
||||||
class SuperCardChangeModePatchCode : public PatchCode
|
class SuperCardChangeModePatchCode : public PatchCode
|
||||||
@@ -20,6 +20,11 @@ public:
|
|||||||
{
|
{
|
||||||
return GetAddressAtTarget((void*)sccmn_changeMode);
|
return GetAddressAtTarget((void*)sccmn_changeMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const void* GetSdSendClock10Function() const
|
||||||
|
{
|
||||||
|
return GetAddressAtTarget((void*)sccmn_sdSendClock10);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SuperCardCommonPatchCode : public PatchCode
|
class SuperCardCommonPatchCode : public PatchCode
|
||||||
@@ -28,11 +33,6 @@ public:
|
|||||||
explicit SuperCardCommonPatchCode(PatchHeap& patchHeap)
|
explicit SuperCardCommonPatchCode(PatchHeap& patchHeap)
|
||||||
: PatchCode(SECTION_START(scsd_common), SECTION_SIZE(scsd_common), patchHeap) { }
|
: PatchCode(SECTION_START(scsd_common), SECTION_SIZE(scsd_common), patchHeap) { }
|
||||||
|
|
||||||
const void* GetSdSendClock10Function() const
|
|
||||||
{
|
|
||||||
return GetAddressAtTarget((void*)sccmn_sdSendClock10);
|
|
||||||
}
|
|
||||||
|
|
||||||
const void* GetCrc16ChecksumFunction() const
|
const void* GetCrc16ChecksumFunction() const
|
||||||
{
|
{
|
||||||
return GetAddressAtTarget((void*)sccmn_sdio4BitCrc16);
|
return GetAddressAtTarget((void*)sccmn_sdio4BitCrc16);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
@ void sc_change_mode(uint16_t mode);
|
@ void sc_change_mode(uint16_t mode);
|
||||||
BEGIN_THUMB_FUNCTION sccmn_changeMode
|
BEGIN_THUMB_FUNCTION sccmn_changeMode
|
||||||
|
push {r0-r3,lr}
|
||||||
ldr r2,= 0x09FFFFFE
|
ldr r2,= 0x09FFFFFE
|
||||||
ldr r3,= 0xA55A
|
ldr r3,= 0xA55A
|
||||||
strh r3, [r2]
|
strh r3, [r2]
|
||||||
@@ -22,21 +23,23 @@ BEGIN_THUMB_FUNCTION sccmn_changeMode
|
|||||||
ldr r2, =sd_resetaddr
|
ldr r2, =sd_resetaddr
|
||||||
strh r2, [r2]
|
strh r2, [r2]
|
||||||
1:
|
1:
|
||||||
mov pc, lr
|
pop {r0-r3,pc}
|
||||||
|
|
||||||
.section "scsd_common", "ax"
|
|
||||||
@ this function will trash r4 but leave r0 and r1 untouched
|
|
||||||
@ void SDSendClock10(void)
|
@ void SDSendClock10(void)
|
||||||
BEGIN_THUMB_FUNCTION sccmn_sdSendClock10
|
BEGIN_THUMB_FUNCTION sccmn_sdSendClock10
|
||||||
|
@ here we get lr from the caller
|
||||||
|
push {r0-r3}
|
||||||
movs r3, #0x10
|
movs r3, #0x10
|
||||||
@ loads reg_scsd_cmd
|
@ loads reg_scsd_cmd
|
||||||
movs r2, #0x98
|
movs r2, #0x98
|
||||||
lsls r2, r2, #20
|
lsls r2, r2, #20
|
||||||
1:
|
1:
|
||||||
ldrh r4, [r2]
|
ldrh r0, [r2]
|
||||||
subs r3, r3, #1
|
subs r3, r3, #1
|
||||||
bne 1b
|
bne 1b
|
||||||
mov pc, lr
|
pop {r0-r3,pc}
|
||||||
|
|
||||||
|
.section "scsd_common", "ax"
|
||||||
|
|
||||||
@ static uint64_t inline calSingleCRC16(uint64_t crc, uint32_t data_in){
|
@ static uint64_t inline calSingleCRC16(uint64_t crc, uint32_t data_in){
|
||||||
@ // Shift out 8 bits for each line
|
@ // Shift out 8 bits for each line
|
||||||
@@ -73,8 +76,10 @@ BEGIN_THUMB_FUNCTION sccmn_sdSendClock10
|
|||||||
|
|
||||||
@ uint64_t sdio_crc16_4bit_checksum(void*)
|
@ uint64_t sdio_crc16_4bit_checksum(void*)
|
||||||
@ r0 and r1 are left untouched, the result is returned in r2-r3 instead
|
@ r0 and r1 are left untouched, the result is returned in r2-r3 instead
|
||||||
|
@ a "continuation function" is provided in r5, and we have to jump to it
|
||||||
BEGIN_THUMB_FUNCTION sccmn_sdio4BitCrc16
|
BEGIN_THUMB_FUNCTION sccmn_sdio4BitCrc16
|
||||||
push {r0,r1,r4-r5,lr}
|
push {r5,lr}
|
||||||
|
push {r0,r1,r4-r5}
|
||||||
movs r4, #0 @ r4 = crc_lo
|
movs r4, #0 @ r4 = crc_lo
|
||||||
movs r5, #0 @ r5 = crc_hi
|
movs r5, #0 @ r5 = crc_hi
|
||||||
movs r1, #128
|
movs r1, #128
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ public:
|
|||||||
INTERWORK_LABEL(sclite_sdCommandAndDropResponse6, readInterwork)
|
INTERWORK_LABEL(sclite_sdCommandAndDropResponse6, readInterwork)
|
||||||
= (u32)superCardSdCommandAndDropLitePatchCode->GetSdCommandAndDropResponse6Function();
|
= (u32)superCardSdCommandAndDropLitePatchCode->GetSdCommandAndDropResponse6Function();
|
||||||
INTERWORK_LABEL(sclite_readData, readInterwork) = (u32)superCardReadDataLitePatchCode->GetReadDataLiteFunction();
|
INTERWORK_LABEL(sclite_readData, readInterwork) = (u32)superCardReadDataLitePatchCode->GetReadDataLiteFunction();
|
||||||
INTERWORK_LABEL(sccmn_sdSendClock10, readInterwork) = (u32)superCardCommonPatchCode->GetSdSendClock10Function();
|
INTERWORK_LABEL(sccmn_sdSendClock10, readInterwork) = (u32)superCardChangeModePatchCode->GetSdSendClock10Function();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ReadSectorsFunc GetReadSectorsFunction() const override
|
const ReadSectorsFunc GetReadSectorsFunction() const override
|
||||||
@@ -104,7 +104,7 @@ public:
|
|||||||
{
|
{
|
||||||
INTERWORK_LABEL(sclite_writeData, writeInterwork) = (u32)superCardWriteDataLitePatchCode->GetWriteDataLiteFunction();
|
INTERWORK_LABEL(sclite_writeData, writeInterwork) = (u32)superCardWriteDataLitePatchCode->GetWriteDataLiteFunction();
|
||||||
INTERWORK_LABEL(sccmn_sdio4BitCrc16, writeInterwork) = (u32)superCardCommonPatchCode->GetCrc16ChecksumFunction();
|
INTERWORK_LABEL(sccmn_sdio4BitCrc16, writeInterwork) = (u32)superCardCommonPatchCode->GetCrc16ChecksumFunction();
|
||||||
INTERWORK_LABEL(sccmn_sdSendClock10, writeInterwork) = (u32)superCardCommonPatchCode->GetSdSendClock10Function();
|
INTERWORK_LABEL(sccmn_sdSendClock10, writeInterwork) = (u32)superCardChangeModePatchCode->GetSdSendClock10Function();
|
||||||
INTERWORK_LABEL(sccmn_changeMode, writeInterwork) = (u32)superCardChangeModePatchCode->GetScChangeModeFunction();
|
INTERWORK_LABEL(sccmn_changeMode, writeInterwork) = (u32)superCardChangeModePatchCode->GetScChangeModeFunction();
|
||||||
INTERWORK_LABEL(sclite_sdCommandAndDropResponse6, writeInterwork)
|
INTERWORK_LABEL(sclite_sdCommandAndDropResponse6, writeInterwork)
|
||||||
= (u32)superCardSdCommandAndDropLitePatchCode->GetSdCommandAndDropResponse6Function();
|
= (u32)superCardSdCommandAndDropLitePatchCode->GetSdCommandAndDropResponse6Function();
|
||||||
|
|||||||
@@ -40,12 +40,19 @@
|
|||||||
|
|
||||||
.section "sclite_sd_command_drop", "ax"
|
.section "sclite_sd_command_drop", "ax"
|
||||||
@ void sclite_sdCommandAndDropResponse6(uint32_t dummy, uint32_t argument, SD_COMMANDS command)
|
@ void sclite_sdCommandAndDropResponse6(uint32_t dummy, uint32_t argument, SD_COMMANDS command)
|
||||||
@ command is passed in r2
|
@ command is passed in r2, in r6 is the pointer to sccmn_sdSendClock10
|
||||||
BEGIN_THUMB_FUNCTION sclite_sdCommandAndDropResponse6
|
BEGIN_THUMB_FUNCTION sclite_sdCommandAndDropResponse6
|
||||||
|
push {lr}
|
||||||
|
cmp r2, #0x52
|
||||||
|
@ if command is READ_MULTIPLE_BLOCK, don't send extra clock cycles
|
||||||
|
beq 1f
|
||||||
|
@ we need to call sccmn_sdSendClock10 after the command is sent, push sccmn_sdSendClock10 and the lr to the stack
|
||||||
|
push {r6}
|
||||||
|
1:
|
||||||
@ among the pushed registers there are the command and
|
@ among the pushed registers there are the command and
|
||||||
@ argument one, which are then used at the loop to
|
@ argument one, which are then used at the loop to
|
||||||
@ send the sd command
|
@ send the sd command
|
||||||
push {r1-r7,lr}
|
push {r1-r7}
|
||||||
|
|
||||||
@ loads reg_scsd_cmd
|
@ loads reg_scsd_cmd
|
||||||
movs r7, #0x98
|
movs r7, #0x98
|
||||||
@@ -100,8 +107,11 @@ SDCommand_drop_resp:
|
|||||||
subs r6, r6, #1
|
subs r6, r6, #1
|
||||||
bne SDCommand_drop_resp
|
bne SDCommand_drop_resp
|
||||||
|
|
||||||
@ restore stack space
|
@ we pop from the stack r6 as pc, which corresponds to sccmn_sdSendClock10 or lr, if it is sccmn_sdSendClock10 that function
|
||||||
|
@ is called, and that function doesn't push a new lr but pops a preexisting one from the stack, which in our case is the
|
||||||
|
@ lr provided to this function
|
||||||
pop {r1-r7,pc}
|
pop {r1-r7,pc}
|
||||||
|
|
||||||
.balign 4
|
.balign 4
|
||||||
.pool
|
.pool
|
||||||
|
|
||||||
@@ -110,7 +120,7 @@ SDCommand_drop_resp:
|
|||||||
BEGIN_THUMB_FUNCTION sclite_writeSector
|
BEGIN_THUMB_FUNCTION sclite_writeSector
|
||||||
push {r1,r2,r4-r7,lr}
|
push {r1,r2,r4-r7,lr}
|
||||||
|
|
||||||
@ load EXMEMCNT register
|
@ load EXMEMCNT register into r7
|
||||||
LOAD_EXMEMCNT
|
LOAD_EXMEMCNT
|
||||||
|
|
||||||
@ r1 for now holds the sector
|
@ r1 for now holds the sector
|
||||||
@@ -120,80 +130,96 @@ sclite_writeSectorSdhcLabel:
|
|||||||
lsls r1, r0, #9
|
lsls r1, r0, #9
|
||||||
@ movs r1, r0
|
@ movs r1, r0
|
||||||
|
|
||||||
|
@ r4 sccmn_changeMode
|
||||||
|
@ r5 sclite_sdCommandAndDropResponse6
|
||||||
|
@ r6 sccmn_sdSendClock10
|
||||||
|
|
||||||
|
adr r3, sccmn_changeMode_writeInterworkLite_address
|
||||||
|
ldmia r3!, {r4-r6}
|
||||||
|
|
||||||
@ enable sd access
|
@ enable sd access
|
||||||
@ this function won't touch r1
|
@ this function won't touch anything
|
||||||
movs r0, #3
|
movs r0, #3
|
||||||
CALL sccmn_changeMode writeInterwork
|
@ call sccmn_changeMode
|
||||||
|
bl interwork_r4
|
||||||
|
|
||||||
@ WRITE_MULTIPLE_BLOCK
|
@ WRITE_MULTIPLE_BLOCK
|
||||||
|
@ puts the value in r2
|
||||||
SD_COMMAND_ARGUMENT #25
|
SD_COMMAND_ARGUMENT #25
|
||||||
@ 2nd parameter is in r1 from above
|
@ 2nd parameter is in r1 from above
|
||||||
|
|
||||||
CALL sclite_sdCommandAndDropResponse6 writeInterwork
|
@ call sclite_sdCommandAndDropResponse6
|
||||||
|
bl interwork_r5
|
||||||
|
|
||||||
@ this function will trash r4 but leave r0 and r1 untouched
|
@ load the rest of the functions
|
||||||
CALL sccmn_sdSendClock10 writeInterwork
|
@ r4 sccmn_sdio4BitCrc16
|
||||||
|
@ r5 sclite_writeData
|
||||||
|
ldmia r3!, {r4-r5}
|
||||||
|
|
||||||
@ loads the saved r0 and r2 (readnum)
|
@ loads the saved r1 (buff) and r2 (writenum)
|
||||||
@ into r0 and r1
|
@ into r0 and r1
|
||||||
pop {r0,r1}
|
pop {r0,r1}
|
||||||
|
|
||||||
write_sector_loop:
|
write_sector_loop:
|
||||||
@ all the functions called in this loop don't change the value of r0 and r1
|
@ all the functions called in this loop don't change the value of any register
|
||||||
@ except sclite_writeData, which will increase r0 by 512
|
@ except sclite_writeData, which will increase r0 by 512
|
||||||
@ sccmn_sdio4BitCrc16 will write the checksum to r2-r3
|
@ sccmn_sdio4BitCrc16 will write the checksum to r2-r3
|
||||||
CALL sccmn_sdio4BitCrc16 writeInterwork
|
@ call sccmn_sdio4BitCrc16, this function will then tail call to r5 (sclite_writeData)
|
||||||
|
bl interwork_r4
|
||||||
@ first argument is buffer
|
|
||||||
@ regs r2 and r3 hold the crc
|
|
||||||
CALL sclite_writeData writeInterwork
|
|
||||||
|
|
||||||
@ this function will trash r4 but leave r0 and r1 untouched
|
|
||||||
CALL sccmn_sdSendClock10 writeInterwork
|
|
||||||
|
|
||||||
subs r1, #1
|
subs r1, #1
|
||||||
bne write_sector_loop
|
bne write_sector_loop
|
||||||
|
|
||||||
|
adr r3, sccmn_changeMode_writeInterworkLite_address
|
||||||
|
@ r4 sccmn_changeMode
|
||||||
|
@ r5 sclite_sdCommandAndDropResponse6
|
||||||
|
ldmia r3!, {r4-r5}
|
||||||
|
|
||||||
@ STOP_TRANSMISSION
|
@ STOP_TRANSMISSION
|
||||||
|
@ puts the value in r2
|
||||||
SD_COMMAND_ARGUMENT #12
|
SD_COMMAND_ARGUMENT #12
|
||||||
@ 2nd parameter is passed in r1
|
@ 2nd parameter is passed in r1
|
||||||
@ and from the loop above r1 is already 0
|
@ and from the loop above r1 is already 0
|
||||||
|
|
||||||
CALL sclite_sdCommandAndDropResponse6 writeInterwork
|
@ call sclite_sdCommandAndDropResponse6
|
||||||
|
bl interwork_r5
|
||||||
@ this function will trash r4 but leave r0 and r1 untouched
|
|
||||||
CALL sccmn_sdSendClock10 writeInterwork
|
|
||||||
|
|
||||||
@ loads sd_dataadd
|
@ loads sd_dataadd
|
||||||
movs r0, #0x90
|
movs r0, #0x90
|
||||||
lsls r0, r0, #20
|
lsls r0, r0, #20
|
||||||
|
|
||||||
@ while(*r1 &0x100) == 0
|
@ while(*r0 &0x100) == 0
|
||||||
beginwhile_WriteSector:
|
beginwhile_WriteSector:
|
||||||
ldrh r1, [r0]
|
ldrh r1, [r0]
|
||||||
lsrs r1, #9
|
lsrs r1, #9
|
||||||
bcc beginwhile_WriteSector
|
bcc beginwhile_WriteSector
|
||||||
|
|
||||||
movs r0, #1
|
movs r0, #1
|
||||||
CALL sccmn_changeMode writeInterwork
|
@ call sccmn_changeMode writeInterwork
|
||||||
|
bl interwork_r4
|
||||||
|
|
||||||
@ restore EXMEMCNT register
|
@ restore EXMEMCNT register
|
||||||
RESTORE_EXMEMCNT
|
RESTORE_EXMEMCNT
|
||||||
|
|
||||||
pop {r4-r7,pc}
|
pop {r4-r7,pc}
|
||||||
INTERWORK writeInterwork
|
interwork_r4:
|
||||||
INTERWORK_FUNCTION sclite_writeData writeInterwork
|
bx r4
|
||||||
INTERWORK_FUNCTION sccmn_sdio4BitCrc16 writeInterwork
|
interwork_r5:
|
||||||
INTERWORK_FUNCTION sccmn_sdSendClock10 writeInterwork
|
bx r5
|
||||||
INTERWORK_FUNCTION sccmn_changeMode writeInterwork
|
|
||||||
INTERWORK_FUNCTION sclite_sdCommandAndDropResponse6 writeInterwork
|
|
||||||
|
|
||||||
.balign 4
|
.balign 4
|
||||||
.pool
|
.pool
|
||||||
|
INTERWORK_FUNCTION sccmn_changeMode writeInterwork
|
||||||
|
INTERWORK_FUNCTION sclite_sdCommandAndDropResponse6 writeInterwork
|
||||||
|
INTERWORK_FUNCTION sccmn_sdSendClock10 writeInterwork
|
||||||
|
INTERWORK_FUNCTION sccmn_sdio4BitCrc16 writeInterwork
|
||||||
|
INTERWORK_FUNCTION sclite_writeData writeInterwork
|
||||||
|
|
||||||
.section "sclite_read_sector", "ax"
|
.section "sclite_read_sector", "ax"
|
||||||
@ bool sclite_readSector(uint32_t sector, uint8_t *buff, uint32_t readnum)
|
@ bool sclite_readSector(uint32_t sector, uint8_t *buff, uint32_t readnum)
|
||||||
BEGIN_THUMB_FUNCTION sclite_readSector
|
BEGIN_THUMB_FUNCTION sclite_readSector
|
||||||
push {r1,r2-r7,lr}
|
push {r1,r2-r7,lr}
|
||||||
|
|
||||||
|
@ load EXMEMCNT register into r7
|
||||||
LOAD_EXMEMCNT
|
LOAD_EXMEMCNT
|
||||||
|
|
||||||
@ r1 for now holds the sector
|
@ r1 for now holds the sector
|
||||||
@@ -204,21 +230,22 @@ sclite_readSectorSdhcLabel:
|
|||||||
@ movs r1, r0
|
@ movs r1, r0
|
||||||
|
|
||||||
@ enable sd access
|
@ enable sd access
|
||||||
@ this function won't touch r1
|
@ this function won't touch anything
|
||||||
movs r0, #3
|
movs r0, #3
|
||||||
CALL sccmn_changeMode readInterwork
|
CALL sccmn_changeMode readInterwork
|
||||||
|
|
||||||
@ READ_MULTIPLE_BLOCK
|
@ READ_MULTIPLE_BLOCK
|
||||||
|
@ puts the value in r2
|
||||||
SD_COMMAND_ARGUMENT #18
|
SD_COMMAND_ARGUMENT #18
|
||||||
@ 2nd parameter is in r1 from above
|
@ 2nd parameter is in r1 from above
|
||||||
|
|
||||||
CALL sclite_sdCommandAndDropResponse6 readInterwork
|
CALL sclite_sdCommandAndDropResponse6 readInterwork
|
||||||
|
|
||||||
@ loads the saved r0 and r2 (writenum)
|
@ loads the saved r1 (buff) and r2 (readnum)
|
||||||
@ into r0 and r1
|
@ into r0 and r1
|
||||||
pop {r0,r1}
|
pop {r0,r1}
|
||||||
read_sector_loop:
|
read_sector_loop:
|
||||||
@ all the functions called in this loop don't change the value of r0 or r1
|
@ all the functions called in this loop don't change the value of any register
|
||||||
@ except sclite_readData, which will increase r0 by 512 automatically
|
@ except sclite_readData, which will increase r0 by 512 automatically
|
||||||
CALL sclite_readData readInterwork
|
CALL sclite_readData readInterwork
|
||||||
|
|
||||||
@@ -226,14 +253,15 @@ read_sector_loop:
|
|||||||
bne read_sector_loop
|
bne read_sector_loop
|
||||||
|
|
||||||
@ STOP_TRANSMISSION
|
@ STOP_TRANSMISSION
|
||||||
|
@ puts the value in r2
|
||||||
SD_COMMAND_ARGUMENT #12
|
SD_COMMAND_ARGUMENT #12
|
||||||
@ 2nd parameter is passed in r1
|
@ 2nd parameter is passed in r1
|
||||||
@ and from the loop above r1 is already 0
|
@ and from the loop above r1 is already 0
|
||||||
|
LOAD_INTERWORK_FUNCTION sccmn_sdSendClock10 readInterwork r6
|
||||||
CALL sclite_sdCommandAndDropResponse6 readInterwork
|
CALL sclite_sdCommandAndDropResponse6 readInterwork
|
||||||
|
|
||||||
@ this function will trash r4 but leave r0 and r1 untouched
|
@ this function won't touch anything
|
||||||
CALL sccmn_sdSendClock10 readInterwork
|
@ CALL sccmn_sdSendClock10 readInterwork
|
||||||
|
|
||||||
|
|
||||||
movs r0, #1
|
movs r0, #1
|
||||||
@@ -312,15 +340,17 @@ sclite_readData_loop:
|
|||||||
|
|
||||||
.section "sclite_write_data", "ax"
|
.section "sclite_write_data", "ax"
|
||||||
@ void sclite_writeData(void*& buffer, int value_to_keep, int crc_buff1, int crc_buff2)
|
@ void sclite_writeData(void*& buffer, int value_to_keep, int crc_buff1, int crc_buff2)
|
||||||
@ this function updates r0, leaves r1 untouched and thrashes r4
|
@ this function updates r0 and leaves everything else untouched
|
||||||
|
@ in r6 is the pointer to sccmn_sdSendClock10
|
||||||
BEGIN_THUMB_FUNCTION sclite_writeData
|
BEGIN_THUMB_FUNCTION sclite_writeData
|
||||||
|
@ push sccmn_sdSendClock10 and the current lr reg to the stack, so that at the end we can
|
||||||
|
@ call in sequence sccmn_sdSendClock10 and then return
|
||||||
|
push {r6}
|
||||||
|
push {r1-r7}
|
||||||
@ loads sd_dataadd
|
@ loads sd_dataadd
|
||||||
movs r4, #0x90
|
movs r4, #0x90
|
||||||
lsls r4, r4, #20
|
lsls r4, r4, #20
|
||||||
|
|
||||||
@ save sd_dataadd constant above for later
|
|
||||||
push {r1-r7,lr}
|
|
||||||
|
|
||||||
waitOnWriteFalse_WriteData:
|
waitOnWriteFalse_WriteData:
|
||||||
ldrh r1, [r4]
|
ldrh r1, [r4]
|
||||||
lsrs r1, #9
|
lsrs r1, #9
|
||||||
@@ -356,9 +386,12 @@ sclite_writeData_loop:
|
|||||||
|
|
||||||
@ r1 holds a value that has not to be changed
|
@ r1 holds a value that has not to be changed
|
||||||
@ r2-r3 hold the crc value to be written
|
@ r2-r3 hold the crc value to be written
|
||||||
@ r4 holds the value sd_dataadd saved at the start
|
pop {r1-r3}
|
||||||
pop {r1-r4}
|
|
||||||
stmia r7!, {r2-r3}
|
stmia r7!, {r2-r3}
|
||||||
|
@ loads sd_dataadd
|
||||||
|
movs r4, #0x90
|
||||||
|
lsls r4, r4, #20
|
||||||
|
|
||||||
@ write end bit
|
@ write end bit
|
||||||
movs r3, #0xff
|
movs r3, #0xff
|
||||||
@@ -374,7 +407,11 @@ waitOnWriteTrue_WriteData:
|
|||||||
str r3, [r4]
|
str r3, [r4]
|
||||||
str r3, [r4]
|
str r3, [r4]
|
||||||
|
|
||||||
pop {r5-r7,pc}
|
|
||||||
|
@ we pop from the stack r6 as pc, which corresponds to sccmn_sdSendClock10 so we jump to it
|
||||||
|
@ sccmn_sdSendClock10 doesn't push a new lr but pops a preexisting one from the stack, which in our case is the
|
||||||
|
@ lr provided to this function
|
||||||
|
pop {r4-r7,pc}
|
||||||
|
|
||||||
.balign 4
|
.balign 4
|
||||||
.pool
|
.pool
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public:
|
|||||||
{
|
{
|
||||||
INTERWORK_LABEL(scsd_writeData, writeInterwork) = (u32)superCardWriteDataPatchCode->GetWriteDataFunction();
|
INTERWORK_LABEL(scsd_writeData, writeInterwork) = (u32)superCardWriteDataPatchCode->GetWriteDataFunction();
|
||||||
INTERWORK_LABEL(sccmn_sdio4BitCrc16, writeInterwork) = (u32)superCardCommonPatchCode->GetCrc16ChecksumFunction();
|
INTERWORK_LABEL(sccmn_sdio4BitCrc16, writeInterwork) = (u32)superCardCommonPatchCode->GetCrc16ChecksumFunction();
|
||||||
INTERWORK_LABEL(sccmn_sdSendClock10, writeInterwork) = (u32)superCardCommonPatchCode->GetSdSendClock10Function();
|
INTERWORK_LABEL(sccmn_sdSendClock10, writeInterwork) = (u32)superCardChangeModePatchCode->GetSdSendClock10Function();
|
||||||
INTERWORK_LABEL(sccmn_changeMode, writeInterwork) = (u32)superCardChangeModePatchCode->GetScChangeModeFunction();
|
INTERWORK_LABEL(sccmn_changeMode, writeInterwork) = (u32)superCardChangeModePatchCode->GetScChangeModeFunction();
|
||||||
INTERWORK_LABEL(scsd_sdCommandAndDropResponse6, writeInterwork)
|
INTERWORK_LABEL(scsd_sdCommandAndDropResponse6, writeInterwork)
|
||||||
= (u32)superCardSdCommandAndDropPatchCode->GetSdCommandAndDropResponse6Function();
|
= (u32)superCardSdCommandAndDropPatchCode->GetSdCommandAndDropResponse6Function();
|
||||||
@@ -107,7 +107,7 @@ public:
|
|||||||
INTERWORK_LABEL(scsd_sdCommandAndDropResponse6, readInterwork)
|
INTERWORK_LABEL(scsd_sdCommandAndDropResponse6, readInterwork)
|
||||||
= (u32)superCardSdCommandAndDropPatchCode->GetSdCommandAndDropResponse6Function();
|
= (u32)superCardSdCommandAndDropPatchCode->GetSdCommandAndDropResponse6Function();
|
||||||
INTERWORK_LABEL(scsd_readData, readInterwork) = (u32)superCardReadDataPatchCode->GetReadDataFunction();
|
INTERWORK_LABEL(scsd_readData, readInterwork) = (u32)superCardReadDataPatchCode->GetReadDataFunction();
|
||||||
INTERWORK_LABEL(sccmn_sdSendClock10, readInterwork) = (u32)superCardCommonPatchCode->GetSdSendClock10Function();
|
INTERWORK_LABEL(sccmn_sdSendClock10, readInterwork) = (u32)superCardChangeModePatchCode->GetSdSendClock10Function();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ReadSectorsFunc GetReadSectorsFunction() const override
|
const ReadSectorsFunc GetReadSectorsFunction() const override
|
||||||
|
|||||||
@@ -23,9 +23,9 @@
|
|||||||
|
|
||||||
.macro LOAD_FAST_EXMEMCNT
|
.macro LOAD_FAST_EXMEMCNT
|
||||||
@ loads EXMEMCNT register address
|
@ loads EXMEMCNT register address
|
||||||
movs r6, #0x18
|
movs r0, #0x18
|
||||||
@ waitstate 2,1 and arm9 slot2 access
|
@ waitstate 2,1 and arm9 slot2 access
|
||||||
strb r6, [r7, #4]
|
strb r0, [r7, #4]
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro RESTORE_EXMEMCNT
|
.macro RESTORE_EXMEMCNT
|
||||||
@@ -43,11 +43,18 @@
|
|||||||
@ void scsd_sdCommandAndDropResponse6(uint32_t dummy, uint32_t argument, SD_COMMANDS command)
|
@ void scsd_sdCommandAndDropResponse6(uint32_t dummy, uint32_t argument, SD_COMMANDS command)
|
||||||
@ argument is passed in r1
|
@ argument is passed in r1
|
||||||
BEGIN_THUMB_FUNCTION scsd_sdCommandAndDropResponse6
|
BEGIN_THUMB_FUNCTION scsd_sdCommandAndDropResponse6
|
||||||
|
push {lr}
|
||||||
|
cmp r2, #0x52
|
||||||
|
@ if command is READ_MULTIPLE_BLOCK, don't send extra clock cycles
|
||||||
|
beq 1f
|
||||||
|
@ we need to call sccmn_sdSendClock10 after the command is sent, push sccmn_sdSendClock10 and the lr to the stack
|
||||||
|
push {r6}
|
||||||
|
1:
|
||||||
@ among the pushed registers there are the command and
|
@ among the pushed registers there are the command and
|
||||||
@ argument one, which are then used by the crc7 function
|
@ argument one, which are then used by the crc7 function
|
||||||
@ and in the loop at the bottom
|
@ and in the loop at the bottom
|
||||||
@ also allocate an extra 4 bytes for the SD_CRC7 function to put the crc byte
|
@ also allocate an extra 4 bytes for the SD_CRC7 function to put the crc byte
|
||||||
push {r0-r7,lr}
|
push {r0-r7}
|
||||||
|
|
||||||
@ pass the buffer incremented by 4, so that the crc function
|
@ pass the buffer incremented by 4, so that the crc function
|
||||||
@ can use a proper indexing method
|
@ can use a proper indexing method
|
||||||
@@ -99,7 +106,9 @@ SDCommand_drop_resp:
|
|||||||
subs r6, r6, #1
|
subs r6, r6, #1
|
||||||
bne SDCommand_drop_resp
|
bne SDCommand_drop_resp
|
||||||
|
|
||||||
@ restore stack space
|
@ we pop from the stack r6 as pc, which corresponds to sccmn_sdSendClock10 or lr, if it is sccmn_sdSendClock10 that function
|
||||||
|
@ is called, and that function doesn't push a new lr but pops a preexisting one from the stack, which in our case is the
|
||||||
|
@ lr provided to this function
|
||||||
pop {r0-r7,pc}
|
pop {r0-r7,pc}
|
||||||
|
|
||||||
@ inline uint8_t CRC7_one(uint8_t crcIn, uint8_t data) {
|
@ inline uint8_t CRC7_one(uint8_t crcIn, uint8_t data) {
|
||||||
@@ -169,7 +178,7 @@ skip_xor:
|
|||||||
BEGIN_THUMB_FUNCTION scsd_writeSector
|
BEGIN_THUMB_FUNCTION scsd_writeSector
|
||||||
push {r1,r2,r4-r7,lr}
|
push {r1,r2,r4-r7,lr}
|
||||||
|
|
||||||
@ load EXMEMCNT register
|
@ load EXMEMCNT register into r7
|
||||||
LOAD_SLOW_EXMEMCNT
|
LOAD_SLOW_EXMEMCNT
|
||||||
|
|
||||||
@ r1 for now holds the sector
|
@ r1 for now holds the sector
|
||||||
@@ -179,23 +188,34 @@ scsd_writeSectorSdhcLabel:
|
|||||||
lsls r1, r0, #9
|
lsls r1, r0, #9
|
||||||
@ movs r1, r0
|
@ movs r1, r0
|
||||||
|
|
||||||
|
@ r4 sccmn_changeMode
|
||||||
|
@ r5 scsd_sdCommandAndDropResponse6
|
||||||
|
@ r6 sccmn_sdSendClock10
|
||||||
|
|
||||||
|
adr r3, sccmn_changeMode_writeInterwork_address
|
||||||
|
ldmia r3!, {r4-r6}
|
||||||
|
|
||||||
@ enable sd access
|
@ enable sd access
|
||||||
@ this function won't touch r1
|
@ this function won't touch anything
|
||||||
movs r0, #3
|
movs r0, #3
|
||||||
bl scsd_sccmn_changeMode_call
|
@ call sccmn_changeMode
|
||||||
|
bl interwork_r4
|
||||||
|
|
||||||
@ WRITE_MULTIPLE_BLOCK
|
@ WRITE_MULTIPLE_BLOCK
|
||||||
SD_COMMAND_ARGUMENT #25
|
SD_COMMAND_ARGUMENT #25
|
||||||
@ 2nd parameter is in r1 from above
|
@ 2nd parameter is in r1 from above
|
||||||
|
|
||||||
bl scsd_sdCommandAndDropResponse6_call
|
@ call scsd_sdCommandAndDropResponse6
|
||||||
|
bl interwork_r5
|
||||||
@ this function will trash r4 but leave r0 and r1 untouched
|
|
||||||
bl scsd_sccmn_sdSendClock10_call
|
|
||||||
|
|
||||||
LOAD_FAST_EXMEMCNT
|
LOAD_FAST_EXMEMCNT
|
||||||
|
|
||||||
@ loads the saved r0 and r2 (readnum)
|
@ load the rest of the functions
|
||||||
|
@ r4 sccmn_sdio4BitCrc16
|
||||||
|
@ r5 scsd_writeData
|
||||||
|
ldmia r3!, {r4-r5}
|
||||||
|
|
||||||
|
@ loads the saved r1 (buff) and r2 (writenum)
|
||||||
@ into r0 and r1
|
@ into r0 and r1
|
||||||
pop {r0,r1}
|
pop {r0,r1}
|
||||||
|
|
||||||
@@ -203,18 +223,17 @@ write_sector_loop:
|
|||||||
@ all the functions called in this loop don't change the value of r0 and r1
|
@ all the functions called in this loop don't change the value of r0 and r1
|
||||||
@ except scsd_writeData, which will increase r0 by 512
|
@ except scsd_writeData, which will increase r0 by 512
|
||||||
@ sccmn_sdio4BitCrc16 will write the checksum to r2-r3
|
@ sccmn_sdio4BitCrc16 will write the checksum to r2-r3
|
||||||
CALL sccmn_sdio4BitCrc16 writeInterwork
|
@ call sccmn_sdio4BitCrc16, this function will then tail call to r5 (scsd_writeData)
|
||||||
|
bl interwork_r4
|
||||||
@ first argument is buffer
|
|
||||||
@ regs r2 and r3 hold the crc
|
|
||||||
CALL scsd_writeData writeInterwork
|
|
||||||
|
|
||||||
@ this function will trash r4 but leave r0 and r1 untouched
|
|
||||||
bl scsd_sccmn_sdSendClock10_call
|
|
||||||
|
|
||||||
subs r1, #1
|
subs r1, #1
|
||||||
bne write_sector_loop
|
bne write_sector_loop
|
||||||
|
|
||||||
|
adr r3, sccmn_changeMode_writeInterwork_address
|
||||||
|
@ r4 sccmn_changeMode
|
||||||
|
@ r5 scsd_sdCommandAndDropResponse6
|
||||||
|
ldmia r3!, {r4-r5}
|
||||||
|
|
||||||
RELOAD_SLOW_EXMEMCNT
|
RELOAD_SLOW_EXMEMCNT
|
||||||
|
|
||||||
@ STOP_TRANSMISSION
|
@ STOP_TRANSMISSION
|
||||||
@@ -222,39 +241,38 @@ write_sector_loop:
|
|||||||
@ 2nd parameter is passed in r1
|
@ 2nd parameter is passed in r1
|
||||||
@ and from the loop above r1 is already 0
|
@ and from the loop above r1 is already 0
|
||||||
|
|
||||||
bl scsd_sdCommandAndDropResponse6_call
|
@ call scsd_sdCommandAndDropResponse6
|
||||||
|
bl interwork_r5
|
||||||
|
|
||||||
@ this function will trash r4 but leave r0 and r1 untouched
|
@ loads sd_dataadd
|
||||||
bl scsd_sccmn_sdSendClock10_call
|
movs r0, #0x90
|
||||||
|
lsls r0, r0, #20
|
||||||
|
|
||||||
@ SD_DATAADD is loaded by scsd_writeData into r5
|
@ while(*r0 &0x100) == 0
|
||||||
@ while(*r5 &0x100) == 0
|
|
||||||
beginwhile_WriteSector:
|
beginwhile_WriteSector:
|
||||||
ldrh r1, [r5]
|
ldrh r1, [r0]
|
||||||
lsrs r1, #9
|
lsrs r1, #9
|
||||||
bcc beginwhile_WriteSector
|
bcc beginwhile_WriteSector
|
||||||
|
|
||||||
movs r0, #1
|
movs r0, #1
|
||||||
bl scsd_sccmn_changeMode_call
|
@ call sccmn_changeMode writeInterwork
|
||||||
|
bl interwork_r4
|
||||||
|
|
||||||
@ restore EXMEMCNT register
|
@ restore EXMEMCNT register
|
||||||
RESTORE_EXMEMCNT
|
RESTORE_EXMEMCNT
|
||||||
|
|
||||||
pop {r4-r7,pc}
|
pop {r4-r7,pc}
|
||||||
scsd_sccmn_sdSendClock10_call:
|
interwork_r4:
|
||||||
LOAD_INTERWORK_FUNCTION sccmn_sdSendClock10 writeInterwork r4
|
|
||||||
bx r4
|
bx r4
|
||||||
scsd_sdCommandAndDropResponse6_call:
|
interwork_r5:
|
||||||
LOAD_INTERWORK_FUNCTION scsd_sdCommandAndDropResponse6 writeInterwork r4
|
bx r5
|
||||||
bx r4
|
.balign 4
|
||||||
scsd_sccmn_changeMode_call:
|
.pool
|
||||||
LOAD_INTERWORK_FUNCTION sccmn_changeMode writeInterwork r4
|
|
||||||
INTERWORK writeInterwork
|
|
||||||
INTERWORK_FUNCTION scsd_writeData writeInterwork
|
|
||||||
INTERWORK_FUNCTION sccmn_sdio4BitCrc16 writeInterwork
|
|
||||||
INTERWORK_FUNCTION sccmn_sdSendClock10 writeInterwork
|
|
||||||
INTERWORK_FUNCTION sccmn_changeMode writeInterwork
|
INTERWORK_FUNCTION sccmn_changeMode writeInterwork
|
||||||
INTERWORK_FUNCTION scsd_sdCommandAndDropResponse6 writeInterwork
|
INTERWORK_FUNCTION scsd_sdCommandAndDropResponse6 writeInterwork
|
||||||
|
INTERWORK_FUNCTION sccmn_sdSendClock10 writeInterwork
|
||||||
|
INTERWORK_FUNCTION sccmn_sdio4BitCrc16 writeInterwork
|
||||||
|
INTERWORK_FUNCTION scsd_writeData writeInterwork
|
||||||
|
|
||||||
|
|
||||||
.section "scsd_read_sector", "ax"
|
.section "scsd_read_sector", "ax"
|
||||||
@@ -283,7 +301,7 @@ scsd_readSectorSdhcLabel:
|
|||||||
|
|
||||||
LOAD_FAST_EXMEMCNT
|
LOAD_FAST_EXMEMCNT
|
||||||
|
|
||||||
@ loads the saved r0 and r2 (writenum)
|
@ loads the saved r1 (buff) and r2 (readnum)
|
||||||
@ into r0 and r1
|
@ into r0 and r1
|
||||||
pop {r0,r1}
|
pop {r0,r1}
|
||||||
read_sector_loop:
|
read_sector_loop:
|
||||||
@@ -300,13 +318,9 @@ read_sector_loop:
|
|||||||
SD_COMMAND_ARGUMENT #12
|
SD_COMMAND_ARGUMENT #12
|
||||||
@ 2nd parameter is passed in r1
|
@ 2nd parameter is passed in r1
|
||||||
@ and from the loop above r1 is already 0
|
@ and from the loop above r1 is already 0
|
||||||
|
LOAD_INTERWORK_FUNCTION sccmn_sdSendClock10 readInterwork r6
|
||||||
CALL scsd_sdCommandAndDropResponse6 readInterwork
|
CALL scsd_sdCommandAndDropResponse6 readInterwork
|
||||||
|
|
||||||
@ this function will trash r4 but leave r0 and r1 untouched
|
|
||||||
CALL sccmn_sdSendClock10 readInterwork
|
|
||||||
|
|
||||||
|
|
||||||
movs r0, #1
|
movs r0, #1
|
||||||
CALL sccmn_changeMode readInterwork
|
CALL sccmn_changeMode readInterwork
|
||||||
|
|
||||||
@@ -357,14 +371,15 @@ write32_loop:
|
|||||||
|
|
||||||
@ void scsd_writeData(void* buffer, int value_to_keep, int crc_buff1, int crc_buff2)
|
@ void scsd_writeData(void* buffer, int value_to_keep, int crc_buff1, int crc_buff2)
|
||||||
BEGIN_THUMB_FUNCTION scsd_writeData
|
BEGIN_THUMB_FUNCTION scsd_writeData
|
||||||
|
@ push sccmn_sdSendClock10 and the current lr reg to the stack, so that at the end we can
|
||||||
|
@ call in sequence sccmn_sdSendClock10 and then return
|
||||||
|
push {r6}
|
||||||
|
push {r1-r7}
|
||||||
|
|
||||||
@ loads SD_DATAADD, do it before the push so that
|
@ loads SD_DATAADD
|
||||||
@ it becomes available to the callee afterwards
|
|
||||||
movs r5, #0x90
|
movs r5, #0x90
|
||||||
lsls r5, r5, #20
|
lsls r5, r5, #20
|
||||||
|
|
||||||
push {r1-r7,lr}
|
|
||||||
|
|
||||||
@ while(*r5 &0x100) == 0
|
@ while(*r5 &0x100) == 0
|
||||||
scsd_writeData_waitOnWriteFalse:
|
scsd_writeData_waitOnWriteFalse:
|
||||||
ldrh r6, [r5]
|
ldrh r6, [r5]
|
||||||
@@ -384,6 +399,7 @@ scsd_writeData_waitOnWriteFalse:
|
|||||||
lsls r1, r1, #2
|
lsls r1, r1, #2
|
||||||
@ no need for special handling because those 2 functions will be in the same block
|
@ no need for special handling because those 2 functions will be in the same block
|
||||||
bl SCSD_writeBuffer32
|
bl SCSD_writeBuffer32
|
||||||
|
@ save incremented r0 register
|
||||||
push {r0}
|
push {r0}
|
||||||
|
|
||||||
movs r1, #8
|
movs r1, #8
|
||||||
@@ -403,6 +419,11 @@ scsd_writeData_waitOnWriteTrue:
|
|||||||
lsrs r6, #9
|
lsrs r6, #9
|
||||||
bcs scsd_writeData_waitOnWriteTrue
|
bcs scsd_writeData_waitOnWriteTrue
|
||||||
|
|
||||||
|
|
||||||
|
@ we pop from the stack r6 as pc, which corresponds to sccmn_sdSendClock10 so we jump to it
|
||||||
|
@ sccmn_sdSendClock10 doesn't push a new lr but pops a preexisting one from the stack, which in our case is the
|
||||||
|
@ lr provided to this function
|
||||||
|
@ also we load in r0 the value stored above
|
||||||
pop {r0-r7,pc}
|
pop {r0-r7,pc}
|
||||||
|
|
||||||
.balign 4
|
.balign 4
|
||||||
|
|||||||
Reference in New Issue
Block a user