Initial SDHC support, files open but breaks directories (credit to ausar)

This commit is contained in:
Metroid Maniac 2024-02-08 12:46:18 +00:00
parent 378b8d8f16
commit 551332d5b1
8 changed files with 1068 additions and 1 deletions

View File

@ -10,6 +10,8 @@
#include "Save.h"
#include "WhiteScreenPatch.h"
#include "my_io_scsd.h"
char *stpcpy(char*, char*);
void tryAgain() {
@ -411,7 +413,8 @@ int main() {
iprintf("SCFW Kernel v0.3.3 GBA-mode\n\n");
if (fatInitDefault()) {
_my_io_scsd.startup();
if (fatMountSimple("fat", &_my_io_scsd)) {
iprintf("FAT system initialised\n");
} else {
iprintf("FAT initialisation failed!\n");

View File

@ -0,0 +1,47 @@
/*
io_m3_common.h
Routines common to all version of the Super Card
Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "my_io_sc_common.h"
/*-----------------------------------------------------------------
_SC_changeMode (was SC_Unlock)
Added by MightyMax
Modified by Chishm
Modified again by loopy
1=ram(readonly), 5=ram, 3=SD interface?
-----------------------------------------------------------------*/
void _SC_changeMode(u8 mode) {
vu16 *unlockAddress = (vu16*)0x09FFFFFE;
*unlockAddress = 0xA55A ;
*unlockAddress = 0xA55A ;
*unlockAddress = mode ;
*unlockAddress = mode ;
}

View File

@ -0,0 +1,43 @@
/*
io_sc_common.h
Routines common to all version of the Super Card
Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef IO_SC_COMMON_H
#define IO_SC_COMMON_H
#include <disc_io.h>
// Values for changing mode
#define SC_MODE_FLASH 0x1510
#define SC_MODE_RAM 0x5
#define SC_MODE_MEDIA 0x3
#define SC_MODE_RAM_RO 0x1
extern void _SC_changeMode (u8 mode);
#endif // IO_SC_COMMON_H

View File

@ -0,0 +1,423 @@
/*
io_scsd.c
Hardware Routines for reading a Secure Digital card
using the SC SD
Some code based on scsd_c.c, written by Amadeus
and Jean-Pierre Thomasset as part of DSLinux.
Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "my_io_scsd.h"
#include "my_io_sd_common.h"
#include "my_io_sc_common.h"
#define printf(...)
//---------------------------------------------------------------
// SCSD register addresses
#define REG_SCSD_CMD (*(vu16*)(0x09800000))
/* bit 0: command bit to read */
/* bit 7: command bit to write */
#define REG_SCSD_DATAWRITE (*(vu16*)(0x09000000))
#define REG_SCSD_DATAREAD (*(vu16*)(0x09100000))
#define REG_SCSD_DATAREAD_32 (*(vu32*)(0x09100000))
#define REG_SCSD_LITE_ENABLE (*(vu16*)(0x09440000))
#define REG_SCSD_LOCK (*(vu16*)(0x09FFFFFE))
/* bit 0: 1 */
/* bit 1: enable IO interface (SD,CF) */
/* bit 2: enable R/W SDRAM access */
//---------------------------------------------------------------
// Responses
#define SCSD_STS_BUSY 0x100
#define SCSD_STS_INSERTED 0x300
//---------------------------------------------------------------
// Send / receive timeouts, to stop infinite wait loops
#define NUM_STARTUP_CLOCKS 100 // Number of empty (0xFF when sending) bytes to send/receive to/from the card
#define TRANSMIT_TIMEOUT 100000 // Time to wait for the SC to respond to transmit or receive requests
#define RESPONSE_TIMEOUT 256 // Number of clocks sent to the SD card before giving up
#define BUSY_WAIT_TIMEOUT 500000
#define WRITE_TIMEOUT 3000 // Time to wait for the card to finish writing
#define BYTES_PER_READ 512
//---------------------------------------------------------------
// Variables required for tracking SD state
u32 _SCSD_relativeCardAddress = 0; // Preshifted Relative Card Address
bool isSDHC;
//---------------------------------------------------------------
// Internal SC SD functions
extern bool _SCSD_writeData_s (u8 *data, u16* crc);
void _SCSD_unlock (void) {
_SC_changeMode (SC_MODE_MEDIA);
}
void _SCSD_enable_lite (void) {
REG_SCSD_LITE_ENABLE = 0;
}
bool _SCSD_sendCommand (u8 command, u32 argument) {
u8 databuff[6]; //SD卡的命令是6个字节
u8 *tempDataPtr = databuff;
int length = 6;
u16 dataByte;
int curBit;
int i;
*tempDataPtr++ = command | 0x40; //Byte1:最高位为01剩下的6bit是command
*tempDataPtr++ = argument>>24;
*tempDataPtr++ = argument>>16;
*tempDataPtr++ = argument>>8;
*tempDataPtr++ = argument; //剩下的4byte是命令
*tempDataPtr = _SD_CRC7 (databuff, 5); //最后的是进行CRC的校验
i = BUSY_WAIT_TIMEOUT;
while (((REG_SCSD_CMD & 0x01) == 0) && (--i));
if (i == 0) {
return false;
}
dataByte = REG_SCSD_CMD;
tempDataPtr = databuff;
while (length--) {
dataByte = *tempDataPtr++;
for (curBit = 7; curBit >=0; curBit--){//#7bit也就是第8位是用来输出的不断移位输出
REG_SCSD_CMD = dataByte;
dataByte = dataByte << 1;
}
}
return true;
}
// Returns the response from the SD card to a previous command.
bool _SCSD_getResponse (u8* dest, u32 length) {
u32 i;
int dataByte;
int numBits = length * 8;
// Wait for the card to be non-busy
i = BUSY_WAIT_TIMEOUT;
while (((REG_SCSD_CMD & 0x01) != 0) && (--i));
if (dest == NULL) {
return true;
}
if (i == 0) {
// Still busy after the timeout has passed
return false;
}
// The first bit is always 0
dataByte = 0;
numBits--;
// Read the remaining bits in the response.
// It's always most significant bit first
while (numBits--) {
dataByte = (dataByte << 1) | (REG_SCSD_CMD & 0x01);
if ((numBits & 0x7) == 0) {
// It's read a whole byte, so store it
*dest++ = (u8)dataByte;
dataByte = 0;
}
}
// Send 16 more clocks, 8 more than the delay required between a response and the next command
for (i = 0; i < 16; i++) {
dataByte = REG_SCSD_CMD;
}
return true;
}
inline bool _SCSD_getResponse_R1 (u8* dest) {
return _SCSD_getResponse (dest, 6);
}
inline bool _SCSD_getResponse_R1b (u8* dest) {
return _SCSD_getResponse (dest, 6);
}
inline bool _SCSD_getResponse_R2 (u8* dest) {
return _SCSD_getResponse (dest, 17);
}
inline bool _SCSD_getResponse_R3 (u8* dest) {
return _SCSD_getResponse (dest, 6);
}
inline bool _SCSD_getResponse_R6 (u8* dest) {
return _SCSD_getResponse (dest, 6);
}
void _SCSD_sendClocks (u32 numClocks) {
do {
REG_SCSD_CMD;
} while (numClocks--);
}
bool _SCSD_cmd_6byte_response_my (u8* responseBuffer, u8 command, u32 data) {
_SCSD_sendCommand (command, data);
return _SCSD_getResponse (responseBuffer, 6);
}
bool _SCSD_cmd_17byte_response_my (u8* responseBuffer, u8 command, u32 data) {
_SCSD_sendCommand (command, data);
return _SCSD_getResponse (responseBuffer, 17);
}
bool _SCSD_initCard (void) {
_SCSD_enable_lite();
// Give the card time to stabilise
_SCSD_sendClocks (NUM_STARTUP_CLOCKS);
// Reset the card
if (!_SCSD_sendCommand (GO_IDLE_STATE, 0)) {
return false;
}
_SCSD_sendClocks (NUM_STARTUP_CLOCKS);
// Card is now reset, including it's address
_SCSD_relativeCardAddress = 0;
// Init the card
return _SD_InitCard_SDHC (_SCSD_cmd_6byte_response_my,
_SCSD_cmd_17byte_response_my,
true,
&_SCSD_relativeCardAddress,&isSDHC);
}
bool _SCSD_readData (void* buffer) {
u8* buff_u8 = (u8*)buffer;
u16* buff = (u16*)buffer;
volatile register u32 temp;
int i;
i = BUSY_WAIT_TIMEOUT;
while ((REG_SCSD_DATAREAD & SCSD_STS_BUSY) && (--i));
if (i == 0) {
return false;
}
i=256;
if ((u32)buff_u8 & 0x01) {
while(i--) {
temp = REG_SCSD_DATAREAD_32;
temp = REG_SCSD_DATAREAD_32 >> 16;
*buff_u8++ = (u8)temp;
*buff_u8++ = (u8)(temp >> 8);
}
} else {
while(i--) {
temp = REG_SCSD_DATAREAD_32;
temp = REG_SCSD_DATAREAD_32 >> 16;
*buff++ = temp;
}
}
for (i = 0; i < 8; i++) {
temp = REG_SCSD_DATAREAD_32;
}
temp = REG_SCSD_DATAREAD;
return true;
}
//---------------------------------------------------------------
// Functions needed for the external interface
bool _SCSD_startUp_my (void) {
//printf("Starting _SCSD_startUp_my...\n");
_SCSD_unlock();
//printf("Unlocked in _SCSD_startUp_my.\n");
bool initResult = _SCSD_initCard();
//printf("Init card in _SCSD_startUp_my returned %d.\n", initResult);
return initResult;
}
bool _SCSD_isInserted_my (void) {
//printf("Starting _SCSD_isInserted_my...\n");
u8 responseBuffer[6];
if (!_SCSD_sendCommand(SEND_STATUS, 0)) {
//printf("Failed to send command in _SCSD_isInserted_my.\n");
return false;
}
if (!_SCSD_getResponse_R1(responseBuffer)) {
//printf("Failed to get response in _SCSD_isInserted_my.\n");
return false;
}
if (responseBuffer[0] != SEND_STATUS) {
//printf("Incorrect response in _SCSD_isInserted_my: Expected %d, got %d\n", SEND_STATUS, responseBuffer[0]);
return false;
}
//printf("Successful execution of _SCSD_isInserted_my.\n");
return true;
}
bool _SCSD_readSectors_my (u32 sector, u32 numSectors, void* buffer) {
//printf("Starting _SCSD_readSectors_my with sector %u and numSectors %u.\n", sector, numSectors);
u32 i;
u8* dest = (u8*) buffer;
u8 responseBuffer[6];
u32 argument = isSDHC ? sector : sector * BYTES_PER_READ;
if (numSectors == 1) {
//printf("Reading single sector.\n");
if (!_SCSD_sendCommand(READ_SINGLE_BLOCK, argument)) {
//printf("Failed to send READ_SINGLE_BLOCK command.\n");
return false;
}
if (!_SCSD_readData(buffer)) {
//printf("Failed to read data for single sector.\n");
return false;
}
} else {
//printf("Reading multiple sectors.\n");
if (!_SCSD_sendCommand(READ_MULTIPLE_BLOCK, argument)) {
//printf("Failed to send READ_MULTIPLE_BLOCK command.\n");
return false;
}
for (i = 0; i < numSectors; i++, dest += BYTES_PER_READ) {
if (!_SCSD_readData(dest)) {
//printf("Failed to read data at sector %u.\n", i + sector);
return false;
}
}
//printf("Stopping transmission after multiple sectors.\n");
_SCSD_sendCommand(STOP_TRANSMISSION, 0);
_SCSD_getResponse_R1b(responseBuffer);
}
_SCSD_sendClocks(64);
//printf("Completed _SCSD_readSectors_my.\n");
return true;
}
bool _SCSD_writeSectors_my (u32 sector, u32 numSectors, const void* buffer) {
//printf("Starting _SCSD_writeSectors_my with sector %u and numSectors %u.\n", sector, numSectors);
u16 crc[4];
u8 responseBuffer[6];
u32 offset = isSDHC ? sector : sector * BYTES_PER_READ;
u8* data = (u8*) buffer;
int i;
while (numSectors--) {
//printf("Writing sector at offset %u.\n", offset);
_SD_CRC16(data, BYTES_PER_READ, (u8*)crc);
_SCSD_sendCommand(WRITE_BLOCK, offset);
if (!_SCSD_getResponse_R1(responseBuffer)) {
//printf("Failed to get response after WRITE_BLOCK command.\n");
return false;
}
if (!_SCSD_writeData_s(data, crc)) {
//printf("Failed to write data and CRC.\n");
return false;
}
_SCSD_sendClocks(64);
offset += BYTES_PER_READ;
data += BYTES_PER_READ;
i = WRITE_TIMEOUT;
do {
_SCSD_sendCommand(SEND_STATUS, _SCSD_relativeCardAddress);
if (!_SCSD_getResponse_R1(responseBuffer) || i-- <= 0) {
//printf("Timeout or error during write confirmation.\n");
return false;
}
} while (((responseBuffer[3] & 0x1f) != ((SD_STATE_TRAN << 1) | READY_FOR_DATA)));
//printf("Sector at offset %u written successfully.\n", offset - BYTES_PER_READ);
}
//printf("Completed _SCSD_writeSectors_my.\n");
return true;
}
bool _SCSD_clearStatus_my (void) {
//printf("Starting _SCSD_clearStatus_my...\n");
bool initResult = _SCSD_initCard();
//printf("Initialization in _SCSD_clearStatus_my returned %d.\n", initResult);
return initResult;
}
bool _SCSD_shutdown_my (void) {
//printf("Starting _SCSD_shutdown_my...\n");
_SC_changeMode(SC_MODE_RAM_RO);
//printf("Changed mode to SC_MODE_RAM_RO in _SCSD_shutdown_my.\n");
return true;
}
const DISC_INTERFACE _my_io_scsd = {
DEVICE_TYPE_SCSD,
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_SLOT_GBA,
(FN_MEDIUM_STARTUP)&_SCSD_startUp_my,
(FN_MEDIUM_ISINSERTED)&_SCSD_isInserted_my,
(FN_MEDIUM_READSECTORS)&_SCSD_readSectors_my,
(FN_MEDIUM_WRITESECTORS)&_SCSD_writeSectors_my,
(FN_MEDIUM_CLEARSTATUS)&_SCSD_clearStatus_my,
(FN_MEDIUM_SHUTDOWN)&_SCSD_shutdown_my
} ;

View File

@ -0,0 +1,48 @@
/*
io_scsd.h
Hardware Routines for reading a Secure Digital card
using the Supercard SD
Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2006-07-11 - Chishm
* Original release
2006-07-22 - Chishm
* First release of stable code
*/
#ifndef IO_SCSD_H
#define IO_SCSD_H
// 'SCSD'
#define DEVICE_TYPE_SCSD 0x44534353
#include <disc_io.h>
// export interface
extern const DISC_INTERFACE _my_io_scsd ;
#endif // define IO_SCSD_H

View File

@ -0,0 +1,139 @@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ io_scsd_s.s
@
@ Hardware Routines for reading a Secure Digital card
@ using the SC SD
@
@ Based on code supplied by Romman
@
@ Copyright (c) 2006 Michael "Chishm" Chisholm
@
@ Redistribution and use in source and binary forms, with or without modification,
@ are permitted provided that the following conditions are met:
@
@ 1. Redistributions of source code must retain the above copyright notice,
@ this list of conditions and the following disclaimer.
@ 2. Redistributions in binary form must reproduce the above copyright notice,
@ this list of conditions and the following disclaimer in the documentation and/or
@ other materials provided with the distribution.
@ 3. The name of the author may not be used to endorse or promote products derived
@ from this software without specific prior written permission.
@
@ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
@ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
@ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
@ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
@ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@
@ 2006-07-22 - Chishm
@ * First release of stable code
@
@ 2006-08-19 - Chishm
@ * Added SuperCard Lite support
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.align 4
.arm
.equ REG_SCSD_DATAWRITE, 0x09000000
.equ BYTES_PER_READ, 0x200
.equ SCSD_STS_BUSY, 0x100
.equ BUSY_WAIT_TIMEOUT, 0x10000
.equ FALSE, 0
.equ TRUE, 1
@ bool _SCSD_writeData_s (u8 *data, u16* crc)
.global _SCSD_writeData_s
_SCSD_writeData_s:
stmfd r13!, {r4-r5}
mov r5, #BYTES_PER_READ
mov r2, #REG_SCSD_DATAWRITE
@ Wait for a free data buffer on the SD card
mov r4, #BUSY_WAIT_TIMEOUT
_SCSD_writeData_busy_wait:
@ Test for timeout
subs r4, r4, #1
moveq r0, #FALSE @ return false on failure
beq _SCSD_writeData_return
@ Check the busy bit of the status register
ldrh r3, [r2]
tst r3, #SCSD_STS_BUSY
beq _SCSD_writeData_busy_wait
ldrh r3, [r2] @ extra clock
mov r3, #0 @ start bit
strh r3,[r2]
@ Check if the data buffer is aligned on a halfword boundary
tst r0, #1
beq _SCSD_writeData_data_loop
@ Used when the source data is unaligned
_SCSD_writeData_data_loop_unaligned:
ldrb r3, [r0], #1
ldrb r4, [r0], #1
orr r3, r3, r4, lsl #8
stmia r2, {r3-r4}
subs r5, r5, #2
bne _SCSD_writeData_data_loop_unaligned
b _SCSD_writeData_crc
@ Write the data to the card
@ 4 halfwords are transmitted to the Supercard at once, for timing purposes
@ Only the first halfword needs to contain data for standard SuperCards
@ For the SuperCard Lite, the data is split into 4 nibbles, one per halfword
_SCSD_writeData_data_loop:
ldrh r3, [r0], #2
@ This bit added for SCLite. Notice that the shift is not the same as in
@ the original (buggy) code supplied by Romman
add r3, r3, r3, lsl #20
mov r4, r3, lsr #8
stmia r2, {r3-r4}
subs r5, r5, #2
bne _SCSD_writeData_data_loop
@ Send the data CRC
_SCSD_writeData_crc:
cmp r1, #0
movne r0, r1
movne r1, #0
movne r5, #8
bne _SCSD_writeData_data_loop
mov r3, #0xff @ end bit
strh r3, [r2]
@ Wait for the SD card to signal that it is finished recieving
mov r4, #BUSY_WAIT_TIMEOUT
_SCSD_writeData_finished_wait:
@ Test for timeout
subs r4, r4, #1
moveq r0, #FALSE @ return false on failure
beq _SCSD_writeData_return
@ Check the busy bit of the status register
ldrh r3, [r2]
tst r3, #0x100
bne _SCSD_writeData_finished_wait
@ Send 8 more clocks, as required by the SD card
ldmia r2, {r3-r4}
@ return true for success
mov r0, #TRUE
_SCSD_writeData_return:
ldmfd r13!,{r4-r5}
bx r14

View File

@ -0,0 +1,248 @@
/*
io_sd_common.c
By chishm (Michael Chisholm)
Common SD card routines
SD routines partially based on sd.s by Romman
Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "my_io_sd_common.h"
#include <gba_console.h>
#define MAX_STARTUP_TRIES 1000 // Arbitrary value, check if the card is ready 20 times before giving up
#define RESPONSE_TIMEOUT 256 // Number of clocks sent to the SD card before giving up
#define iprintf(...)
/*
Improved CRC7 function provided by cory1492
Calculates the CRC of an SD command, and includes the end bit in the byte
*/
u8 _SD_CRC7_my(u8* data, int cnt) {
int i, a;
u8 crc, temp;
crc = 0;
for (a = 0; a < cnt; a++)
{
temp = data[a];
for (i = 0; i < 8; i++)
{
crc <<= 1;
if ((temp & 0x80) ^ (crc & 0x80)) crc ^= 0x09;
temp <<= 1;
}
}
crc = (crc << 1) | 1;
return(crc);
}
/*
Calculates the CRC16 for a sector of data. Calculates it
as 4 separate lots, merged into one buffer. This is used
for 4 SD data lines, not for 1 data line alone.
*/
void _SD_CRC16_my (u8* buff, int buffLength, u8* crc16buff) {
u32 a, b, c, d;
int count;
u32 bitPattern = 0x80808080; // r7
u32 crcConst = 0x1021; // r8
u32 dataByte = 0; // r2
a = 0; // r3
b = 0; // r4
c = 0; // r5
d = 0; // r6
buffLength = buffLength * 8;
do {
if (bitPattern & 0x80) dataByte = *buff++;
a = a << 1;
if ( a & 0x10000) a ^= crcConst;
if (dataByte & (bitPattern >> 24)) a ^= crcConst;
b = b << 1;
if (b & 0x10000) b ^= crcConst;
if (dataByte & (bitPattern >> 25)) b ^= crcConst;
c = c << 1;
if (c & 0x10000) c ^= crcConst;
if (dataByte & (bitPattern >> 26)) c ^= crcConst;
d = d << 1;
if (d & 0x10000) d ^= crcConst;
if (dataByte & (bitPattern >> 27)) d ^= crcConst;
bitPattern = (bitPattern >> 4) | (bitPattern << 28);
} while (buffLength-=4);
count = 16; // r8
do {
bitPattern = bitPattern << 4;
if (a & 0x8000) bitPattern |= 8;
if (b & 0x8000) bitPattern |= 4;
if (c & 0x8000) bitPattern |= 2;
if (d & 0x8000) bitPattern |= 1;
a = a << 1;
b = b << 1;
c = c << 1;
d = d << 1;
count--;
if (!(count & 0x01)) {
*crc16buff++ = (u8)(bitPattern & 0xff);
}
} while (count != 0);
return;
}
/*
Initialise the SD card, after it has been sent into an Idle state
cmd_6byte_response: a pointer to a function that sends the SD card a command and gets a 6 byte response
cmd_17byte_response: a pointer to a function that sends the SD card a command and gets a 17 byte response
use4bitBus: initialise card to use a 4 bit data bus when communicating with the card
RCA: a pointer to the location to store the card's Relative Card Address, preshifted up by 16 bits.
*/
#define CMD8 8
#define CMD58 58
#define R1_ILLEGAL_COMMAND 0x04
bool _SD_InitCard_SDHC (_SD_FN_CMD_6BYTE_RESPONSE cmd_6byte_response,
_SD_FN_CMD_17BYTE_RESPONSE cmd_17byte_response,
bool use4bitBus,
u32 *RCA,bool *isSDHC)
{
u8 responseBuffer[17] = {0};
int i;
*isSDHC = false;
bool cmd8Response = cmd_17byte_response(responseBuffer, CMD8, 0x1AA);//0xa 是确定的 0xAA是推荐值
iprintf("\n");
//CMD8 也就是 Send Interface Condition Command
//正确的回显是CMD8Ver=0,Reserved=0,EchoBack=1,EchoBack=0XAA
if (cmd8Response && responseBuffer[0] == CMD8 && responseBuffer[1] == 0 && responseBuffer[2] == 0 && responseBuffer[3] == 0x1 && responseBuffer[4] == 0xAA) {
*isSDHC = true;
iprintf("CMD8 Return OK,might be a SDHC\n");
}else{
iprintf("CMD8 ERR not SDHC\n");
iprintf("resp:");
for(int i=0;i<17;i++){
iprintf("[%d]=%X ",i,responseBuffer[i]);
}
}
for (i = 0; i < MAX_STARTUP_TRIES; i++) {
cmd_6byte_response(responseBuffer, APP_CMD, 0);//CMD55
if (responseBuffer[0] != APP_CMD) {
iprintf("Failed to send APP_CMD\n"); //进入到APP模式可以执行ACMD41
return false;
}
u32 arg = SD_OCR_VALUE;
if (*isSDHC) {
arg |= (1<<30); // Set HCS bit,Supports SDHC
arg |= (1<<28); //Max performance
}
if (cmd_6byte_response(responseBuffer, SD_APP_OP_COND, arg) &&//ACMD41
((responseBuffer[1] & (1<<7)) != 0)/*Busy:0b:initing 1b:init completed*/) {
iprintf("ACMD41 accepted init completed\n");
break; // Card is ready
}
}
if (i >= MAX_STARTUP_TRIES) {
return false;
}
if (isSDHC) {
cmd_6byte_response(responseBuffer, CMD58, 0);
iprintf("CMD58 response received\n");
// u32 ocr = (responseBuffer[1] << 24) | (responseBuffer[2] << 16) |
// (responseBuffer[3] << 8) | responseBuffer[4];
if ((responseBuffer[1] & (1<<6)) == 0) {//Card Capacity Status (CCS)
iprintf("CMD58 OCR ERROR!! Not SDHC\n\n");
*isSDHC = false;
}else{
iprintf("OCR OK! Is SDHC\n");
}
// Further processing of OCR can be done here if needed
}
// The card's name, as assigned by the manufacturer
cmd_17byte_response (responseBuffer, ALL_SEND_CID, 0);
// Get a new address
for (i = 0; i < MAX_STARTUP_TRIES ; i++) {
cmd_6byte_response (responseBuffer, SEND_RELATIVE_ADDR, 0);
*RCA = (responseBuffer[1] << 24) | (responseBuffer[2] << 16);
if ((responseBuffer[3] & 0x1e) != (SD_STATE_STBY << 1)) {
iprintf("RCA set\n");
break;
}
}
if (i >= MAX_STARTUP_TRIES) {
return false;
}
// Some cards won't go to higher speeds unless they think you checked their capabilities
cmd_17byte_response (responseBuffer, SEND_CSD, *RCA);
// Only this card should respond to all future commands
cmd_6byte_response (responseBuffer, SELECT_CARD, *RCA);
if (use4bitBus) {
// Set a 4 bit data bus
cmd_6byte_response (responseBuffer, APP_CMD, *RCA);
cmd_6byte_response (responseBuffer, SET_BUS_WIDTH, 2); // 4-bit mode.
}
// Use 512 byte blocks
cmd_6byte_response (responseBuffer, SET_BLOCKLEN, 512); // 512 byte blocks
// Wait until card is ready for data
i = 0;
do {
if (i >= RESPONSE_TIMEOUT) {
return false;
}
i++;
} while (!cmd_6byte_response (responseBuffer, SEND_STATUS, *RCA) && ((responseBuffer[3] & 0x1f) != ((SD_STATE_TRAN << 1) | READY_FOR_DATA)));
return true;
}

View File

@ -0,0 +1,116 @@
/*
io_sd_common.h
By chishm (Michael Chisholm)
Common SD card routines
SD routines partially based on sd.s by Romman
Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef IO_SD_COMMON_H
#define IO_SD_COMMON_H
#include <disc_io.h>
/* SD commands */
#define GO_IDLE_STATE 0
#define ALL_SEND_CID 2
#define SEND_RELATIVE_ADDR 3
#define SELECT_CARD 7
#define SEND_CSD 9
#define STOP_TRANSMISSION 12
#define SEND_STATUS 13
#define GO_INACTIVE_STATE 15
#define SET_BLOCKLEN 16
#define READ_SINGLE_BLOCK 17
#define READ_MULTIPLE_BLOCK 18
#define WRITE_BLOCK 24
#define WRITE_MULTIPLE_BLOCK 25
#define APP_CMD 55
#define CMD8 8
#define CMD58 58
/* SD App commands */
#define SET_BUS_WIDTH 6
#define SD_APP_OP_COND 41
/* OCR (Operating Conditions Register) send value */
#define SD_OCR_VALUE 0x00030000 /* 2.8V to 3.0V */
//#define SD_OCR_VALUE 0x003F8000 /* 2.7V to 3.4V */
//#define SD_OCR_VALUE 0x00FC0000
/* SD Data repsonses */
#define SD_CARD_BUSY 0xff
/* SD states */
#define SD_STATE_IDLE 0 // Idle state, after power on or GO_IDLE_STATE command
#define SD_STATE_READY 1 // Ready state, after card replies non-busy to SD_APP_OP_COND
#define SD_STATE_IDENT 2 // Identification state, after ALL_SEND_CID
#define SD_STATE_STBY 3 // Standby state, when card is deselected
#define SD_STATE_TRAN 4 // Transfer state, after card is selected and ready for data transfer
#define SD_STATE_DATA 5 //
#define SD_STATE_RCV 6 // Receive data state
#define SD_STATE_PRG 7 // Programming state
#define SD_STATE_DIS 8 // Disconnect state
#define SD_STATE_INA 9 // Inactive state, after GO_INACTIVE_STATE
#define READY_FOR_DATA 1 // bit 8 in card status
///Mod:
#define R1_ILLEGAL_COMMAND 0x04
/*
Calculate the CRC7 of a command and return it preshifted with
an end bit added
*/
extern u8 _SD_CRC7(u8* data, int size);
/*
Calculate the CRC16 of a block of data, ready for transmission on
four data lines at once
*/
extern void _SD_CRC16 (u8* buff, int buffLength, u8* crc16buff);
typedef bool (*_SD_FN_CMD_6BYTE_RESPONSE) (u8* responseBuffer, u8 command, u32 data);
typedef bool (*_SD_FN_CMD_17BYTE_RESPONSE) (u8* responseBuffer, u8 command, u32 data);
/*
Initialise the SD card, after it has been sent into an Idle state
cmd_6byte_response: a pointer to a function that sends the SD card a command and gets a 6 byte response
cmd_17byte_response: a pointer to a function that sends the SD card a command and gets a 17 byte response
use4bitBus: initialise card to use a 4 bit data bus when communicating with the card
RCA: a pointer to the location to store the card's Relative Card Address, preshifted up by 16 bits.
*/
extern bool _SD_InitCard_SDHC (_SD_FN_CMD_6BYTE_RESPONSE cmd_6byte_response,
_SD_FN_CMD_17BYTE_RESPONSE cmd_17byte_response,
bool use4bitBus,
u32 *RCA,bool *isSDHC);
#endif // define IO_SD_COMMON_H