mirror of
https://github.com/LNH-team/pico-loader.git
synced 2026-06-03 01:36:58 +02:00
139 lines
3.2 KiB
ArmAsm
139 lines
3.2 KiB
ArmAsm
.cpu arm7tdmi
|
|
.syntax unified
|
|
|
|
#include "SuperCardSDAddresses.h"
|
|
|
|
.section "scsd_sd_command_drop", "ax"
|
|
@ void scsd_sdCommandAndDropResponse6(uint32_t dummy, uint32_t argument, SD_COMMANDS command)
|
|
@ command is passed in r2, in r6 is the pointer to sccmn_sdSendClock10
|
|
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
|
|
@ argument one, which are then used by the crc7 function
|
|
@ and in the loop at the bottom
|
|
@ also allocate an extra 4 bytes for the SD_CRC7 function to put the crc byte
|
|
push {r0-r7}
|
|
|
|
@ pass the buffer incremented by 4, so that the crc function
|
|
@ can use a proper indexing method
|
|
add r0, sp, #4
|
|
@ after this call, we get sp back in r1
|
|
bl SD_CRC7
|
|
|
|
@ loads reg_scsd_cmd
|
|
movs r7, #0x98
|
|
lsls r7, r7, #20
|
|
|
|
@ while(*r7 & 0x01) == 0
|
|
SDCommand_loop:
|
|
ldrh r0, [r7]
|
|
lsrs r0, r0, #1
|
|
bcc SDCommand_loop
|
|
|
|
@ perform an extra read
|
|
ldrh r0, [r7]
|
|
|
|
@ the sd command buffer is 6 bytes long
|
|
@ and starts at sp+8 in descending order
|
|
@ r1 holds sp-4, so rather than incrementing it by 3
|
|
@ we decrement it by 1
|
|
subs r2, r1, #1
|
|
movs r0, #5
|
|
write_SDCommand_loop:
|
|
ldrb r3, [r2, r0]
|
|
lsls r1, r3, #17
|
|
orrs r3, r1
|
|
lsls r4, r3, #2
|
|
lsls r5, r4, #2
|
|
lsls r6, r5, #2
|
|
stmia r7!, {r3-r6}
|
|
subs r0, #1
|
|
bpl write_SDCommand_loop
|
|
|
|
@ drop_response
|
|
|
|
@ while(*r7 & 0x01) != 0
|
|
SDCommand_drop_resp_nonbusy_loop:
|
|
ldrh r0, [r7]
|
|
lsrs r0, r0, #1
|
|
bcs SDCommand_drop_resp_nonbusy_loop
|
|
|
|
movs r6, #4
|
|
SDCommand_drop_resp:
|
|
ldmia r7!, {r0-r5}
|
|
subs r6, r6, #1
|
|
bne SDCommand_drop_resp
|
|
|
|
@ 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}
|
|
|
|
@ inline uint8_t CRC7_one(uint8_t crcIn, uint8_t data) {
|
|
@ const uint8_t g = 0x89;
|
|
@ uint8_t i;
|
|
|
|
@ crcIn ^= data;
|
|
@ for (i = 0; i < 8; i++) {
|
|
@ if (crcIn & 0x80) crcIn ^= g;
|
|
@ crcIn <<= 1;
|
|
@ }
|
|
|
|
@ return crcIn;
|
|
@ }
|
|
|
|
@ // Calculate CRC7 value of the buffer
|
|
@ // input:
|
|
@ // pBuf - pointer to the buffer
|
|
@ // return: the CRC7 value
|
|
@ uint32_t CRC7_buf(uint8_t *pBuf) {
|
|
@ uint32_t crc = 0;
|
|
|
|
@ for (int i = 4; i >= 0; --i) crc = CRC7_one(crc,pBuf[i]);
|
|
|
|
@ return crc << 24;
|
|
@ }
|
|
|
|
@ in r1 puts back the argument it took in in r0
|
|
@ SD_CRC7(uint8_t* buff)
|
|
SD_CRC7:
|
|
push {r0,r4-r6,lr}
|
|
movs r3, #0
|
|
movs r5, #0x89
|
|
movs r1, #4
|
|
movs r4, #0x80
|
|
|
|
SD_CRC7_loop:
|
|
movs r2, #8
|
|
ldrb r6, [r0, r1]
|
|
eors r3, r6
|
|
|
|
CRC7_one_loop:
|
|
|
|
@ r4 & 0x80
|
|
tst r3, r4
|
|
|
|
beq skip_xor
|
|
eors r3, r5
|
|
|
|
skip_xor:
|
|
lsls r3, #1
|
|
subs r2, #1
|
|
bne CRC7_one_loop
|
|
|
|
subs r1, #1
|
|
bpl SD_CRC7_loop
|
|
|
|
@ write at buffer index -1
|
|
strb r3, [r0, r1]
|
|
pop {r1,r4-r6,pc}
|
|
|
|
.balign 4
|
|
.pool
|