Skip to content

Commit

Permalink
scdssdhc2/ttio: refactor/rename header defines
Browse files Browse the repository at this point in the history
- Add defines for SRAM read/writes (doesn't exist in DSTT)
- Reorganize defines for 0x51 commands
  - Dubbed "SD_HOST" commands
  - Added enums for each mode available
- More code comments and renaming to more correctly align with 0x51
  naming scheme
  • Loading branch information
lifehackerhansol committed Sep 5, 2023
1 parent 88dd05e commit 22b8c2b
Show file tree
Hide file tree
Showing 5 changed files with 279 additions and 112 deletions.
2 changes: 1 addition & 1 deletion source/scdssdhc2/source/iointerface.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ static bool is_sdhc = false;
// Initialize the driver. Returns true on success.
bool startup(void)
{
is_sdhc = SCDS_SendCommand(SCDS_CMD_SD_IS_SDHC) != 0 ? true : false;
is_sdhc = SCDS_SendCommand(SCDS_CMD_SD_IS_SDHC()) != 0 ? true : false;
return true;
}

Expand Down
40 changes: 20 additions & 20 deletions source/scdssdhc2/source/scdssdhc.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ static inline void SCDS_WriteCardData(u64 command, u32 flags, const void *buffer

static inline void SCDS_FlushResponse(void)
{
while(SCDS_SendCommand(SCDS_CMD_CARD_BUSY));
SCDS_SendCommand(SCDS_CMD_CARD_RESPONSE);
while(SCDS_SendCommand(SCDS_CMD_SD_HOST_BUSY));
SCDS_SendCommand(SCDS_CMD_SD_HOST_RESPONSE);
}

// only use with 0x51 commands; they need a delay
Expand All @@ -56,58 +56,58 @@ u32 SCDS_SendCommand(const u64 command)
void SCDS_SDReadSingleSector(u32 sector, void *buffer)
{
// instruct cart what to read
SCDS_SendCommand(SCDS_CMD_SD_READ_SINGLE_SECTOR_SEND(sector));
SCDS_SendCommand(SCDS_CMD_SD_READ_SINGLE_BLOCK(sector));

// wait until data ready
while(SCDS_SendCommand(SCDS_CMD_SD_READ_REQUEST));
while(SCDS_SendCommand(SCDS_CMD_FIFO_BUSY));

// retrieve data
SCDS_ReadCardData(SCDS_CMD_SD_READ_DATA, SCDS_CTRL_READ_512B, buffer, 128);
SCDS_ReadCardData(SCDS_CMD_FIFO_READ_DATA, SCDS_CTRL_READ_512B, buffer, 128);
}

void SCDS_SDReadMultiSector(u32 sector, void *buffer, u32 num_sectors)
{
// instruct cart what to read
SCDS_SendCommand(SCDS_CMD_SD_READ_MULTI_SECTOR_SEND(sector));
SCDS_SendCommand(SCDS_CMD_SD_READ_MULTI_BLOCK(sector));

while(1)
{
// wait until data ready
while(SCDS_SendCommand(SCDS_CMD_SD_READ_REQUEST));
while(SCDS_SendCommand(SCDS_CMD_FIFO_BUSY));

// retrieve data
SCDS_ReadCardData(SCDS_CMD_SD_READ_DATA, SCDS_CTRL_READ_512B, buffer, 128);
SCDS_ReadCardData(SCDS_CMD_FIFO_READ_DATA, SCDS_CTRL_READ_512B, buffer, 128);
buffer = (u8 *)buffer + 0x200;
num_sectors--;
if(num_sectors == 0)
break;
SCDS_SendCommandDelay(SCDS_CMD_SD_READ_REQUEST_NEXT);
SCDS_SendCommandDelay(SCDS_CMD_SD_HOST_PARAM(0, 0, SCDS_SD_HOST_NEXT_DATABLOCK));
};

// end read
SCDS_SendCommandDelay(SCDS_CMD_SD_RW_MULTI_SECTOR_END);
SCDS_SendCommandDelay(SCDS_CMD_SDIO_STOP_TRANSMISSION());
SCDS_FlushResponse();
}

void SCDS_SDWriteSingleSector(u32 sector, const void *buffer)
{
// instruct cart where to write
SCDS_SendCommandDelay(SCDS_CMD_SD_WRITE_SINGLE_SECTOR_SEND(sector));
SCDS_SendCommandDelay(SCDS_CMD_SDIO_WRITE_SINGLE_BLOCK(sector));
SCDS_FlushResponse();

// write
SCDS_WriteCardData(SCDS_CMD_SD_WRITE_DATA, SCDS_CTRL_WRITE_512B, buffer, 128);
SCDS_WriteCardData(SCDS_CMD_FIFO_WRITE_DATA, SCDS_CTRL_WRITE_512B, buffer, 128);

// end write
while(SCDS_SendCommand(SCDS_CMD_CARD_BUSY));
while(SCDS_SendCommand(SCDS_CMD_SD_HOST_BUSY));
SCDS_SendCommand(SCDS_CMD_SD_WRITE_END);
while(SCDS_SendCommand(SCDS_CMD_CARD_BUSY));
while(SCDS_SendCommand(SCDS_CMD_SD_HOST_BUSY));
}

void SCDS_SDWriteMultiSector(u32 sector, const void *buffer, u32 num_sectors)
{
// instruct cart where to write
SCDS_SendCommandDelay(SCDS_CMD_SD_WRITE_MULTI_SECTOR_SEND(sector));
SCDS_SendCommandDelay(SCDS_CMD_SDIO_WRITE_MULTI_BLOCK(sector));
SCDS_FlushResponse();

do
Expand All @@ -116,17 +116,17 @@ void SCDS_SDWriteMultiSector(u32 sector, const void *buffer, u32 num_sectors)
// well, it's supposed to be end write. But the while loop starts with it, seemingly to simplify it
// it doesn't seem to affect anything, so let's just do it the way it wants us to
SCDS_SendCommand(SCDS_CMD_SD_WRITE_END);
while(SCDS_SendCommand(SCDS_CMD_CARD_BUSY));
while(SCDS_SendCommand(SCDS_CMD_SD_HOST_BUSY));
// write
SCDS_WriteCardData(SCDS_CMD_SD_WRITE_DATA, SCDS_CTRL_WRITE_512B, buffer, 128);
while(SCDS_SendCommand(SCDS_CMD_CARD_BUSY));
SCDS_WriteCardData(SCDS_CMD_FIFO_WRITE_DATA, SCDS_CTRL_WRITE_512B, buffer, 128);
while(SCDS_SendCommand(SCDS_CMD_SD_HOST_BUSY));
buffer = (u8 *)buffer + 0x200;
num_sectors--;
} while (num_sectors);

// *really* end write
SCDS_SendCommandDelay(SCDS_CMD_SD_RW_MULTI_SECTOR_END);
SCDS_SendCommandDelay(SCDS_CMD_SDIO_STOP_TRANSMISSION());
SCDS_FlushResponse();
SCDS_SendCommand(SCDS_CMD_SD_WRITE_END);
while(SCDS_SendCommand(SCDS_CMD_CARD_BUSY));
while(SCDS_SendCommand(SCDS_CMD_SD_HOST_BUSY));
}
128 changes: 102 additions & 26 deletions source/scdssdhc2/source/scdssdhc.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include <nds/ndstypes.h>

#ifndef NULL
#define NULL 0
#define NULL 0
#endif

// SCDS defines
Expand All @@ -28,46 +28,122 @@

// SCDS CARD_COMMANDs

// return 0 == idle
// return non-0 == not idle
#define SCDS_CMD_CARD_BUSY (0x50ull << 56)
/*
SRAM commands
// Others
#define SCDS_CMD_CARD_RESPONSE (0x52ull << 56)
#define SCDS_CMD_SD_WRITE_END (0x56ull << 56)
Command structure:
AA BB BB BB BB 00 00 00
AA = command
BBBBBBBB = address
*/

// return 0 == SD
// return non-0 == SDHC
#define SCDS_CMD_SD_IS_SDHC ((0x70ull << 56) | (0x7F9E0ull << 24))
static inline u64 SCDS_CMD_SRAM_READ_DATA(u32 address)
{
return (0x70ull << 56) | ((u64)address << 24);
}

#define SCDS_CMD_SD_READ_REQUEST (0x80ull << 56)
#define SCDS_CMD_SD_READ_DATA (0x81ull << 56)
#define SCDS_CMD_SD_WRITE_DATA (0x82ull << 56)
static inline u64 SCDS_CMD_SRAM_WRITE_DATA(u32 address)
{
return (0x71ull << 56) | ((u64)address << 24);
}

// 0x51 command has a whole lot of parameters. Will be split as needed
#define SCDS_CMD_CARD_PARAM (0x51ull << 56)
#define SCDS_CMD_CARD_PARAM_R1 (SCDS_CMD_CARD_PARAM | 0x100ull)
#define SCDS_CMD_SD_READ_REQUEST_NEXT (SCDS_CMD_CARD_PARAM | (7ull << 8))
#define SCDS_CMD_SD_RW_MULTI_SECTOR_END (SCDS_CMD_CARD_PARAM_R1 | (12ull << 16))
/*
This address in SRAM *usually* contains a bool for SD or SDHC
While not exactly reliable, the original driver did it, so here goes
static inline u64 SCDS_CMD_SD_READ_SINGLE_SECTOR_SEND(u32 sector)
return 0 == SD
return non-0 == SDHC
*/
static inline u64 SCDS_CMD_SD_IS_SDHC(void)
{
return (0x53ull << 56) | ((u64)sector << 24);
return SCDS_CMD_SRAM_READ_DATA(0x7F9E0);
}

// FIFO commands
#define SCDS_CMD_FIFO_BUSY (0x80ull << 56)
#define SCDS_CMD_FIFO_READ_DATA (0x81ull << 56)
#define SCDS_CMD_FIFO_WRITE_DATA (0x82ull << 56)

/*
SD host modes
Used with 0x51 command, see below
*/
enum SCDS_SD_HOST_MODES {
SCDS_SD_HOST_NORESPONSE = 0ull,
SCDS_SD_HOST_R1_4B = 1ull,
SCDS_SD_HOST_R1_4B_MULTI = 2ull, // use mode 3 to continue this read
SCDS_SD_HOST_NEXT_4B = 3ull,
SCDS_SD_HOST_SEND_CLK = 4ull,
SCDS_SD_HOST_SEND_STOP_CLK = 5ull,
SCDS_SD_HOST_READ_DATABLOCK = 6ull,
SCDS_SD_HOST_NEXT_DATABLOCK = 7ull,
SCDS_SD_HOST_CMD17_READ_DATA = 8ull, // Send SDIO CMD17 & read data
SCDS_SD_HOST_CMD18_READ_DATA = 9ull, // Send SDIO CMD18 & read data until stop
SCDS_SD_HOST_COMMIT_FIFO_DATA = 0xAull, // commit data in FIFO to SD card
SCDS_SD_HOST_CMD24_WRITE_DATA = 0xBull, // Send SDIO CMD24 & send data in SRAM buffer
SCDS_SD_HOST_WAIT_BUSY = 0xCull // wait until data transfer ends
};

/*
SD host related commands
Note:
While this is where the SDIO happens, it isn't always SDIO
Thus, it can sometimes be 0
Command structure:
51 AA AA AA AA BB CC 00
AAAAAAAA = SDIO parameter
BB = SDIO command
CC = SD host mode, see SCDS_SD_HOST_MODES enum
*/

static inline u64 SCDS_CMD_SD_HOST_PARAM(u32 parameter, u8 sdio, u8 mode)
{
return (0x51ull << 56) | ((u64)parameter << 24) | ((u64)sdio << 16) | ((u64)mode << 8);
}

static inline u64 SCDS_CMD_SD_READ_MULTI_SECTOR_SEND(u32 sector)
// useful SDIO macros
// CMD12
static inline u64 SCDS_CMD_SDIO_STOP_TRANSMISSION(void)
{
return (0x54ull << 56) | ((u64)sector << 24);
return SCDS_CMD_SD_HOST_PARAM(0, 12, SCDS_SD_HOST_R1_4B);
}

// CMD24
static inline u64 SCDS_CMD_SDIO_WRITE_SINGLE_BLOCK(u32 sector)
{
return SCDS_CMD_SD_HOST_PARAM(sector, 24, SCDS_SD_HOST_R1_4B);
}

static inline u64 SCDS_CMD_SD_WRITE_SINGLE_SECTOR_SEND(u32 sector)
// CMD25
static inline u64 SCDS_CMD_SDIO_WRITE_MULTI_BLOCK(u32 sector)
{
return SCDS_CMD_CARD_PARAM_R1 | ((u64)sector << 24) | (24ull << 16);
return SCDS_CMD_SD_HOST_PARAM(sector, 25, SCDS_SD_HOST_R1_4B);
}

static inline u64 SCDS_CMD_SD_WRITE_MULTI_SECTOR_SEND(u32 sector)
// SD host misc commands
// return 0 == idle
// return non-0 == not idle
#define SCDS_CMD_SD_HOST_BUSY (0x50ull << 56)

// Gets response of SD_HOST commands, if the sent mode is 1 or 2
#define SCDS_CMD_SD_HOST_RESPONSE (0x52ull << 56)
// Stops SD host data transfer
#define SCDS_CMD_SD_WRITE_END (0x56ull << 56)

// Sends CMD17
// This is effectively 0x51/0x50/0x52 rolled into one command
static inline u64 SCDS_CMD_SD_READ_SINGLE_BLOCK(u32 sector)
{
return SCDS_CMD_CARD_PARAM_R1 | ((u64)sector << 24) | (25ull << 16);
return (0x53ull << 56) | ((u64)sector << 24);
}

// Sends CMD18
// This is effectively 0x51/0x50/0x52 rolled into one command
static inline u64 SCDS_CMD_SD_READ_MULTI_BLOCK(u32 sector)
{
return (0x54ull << 56) | ((u64)sector << 24);
}

// user API
Expand Down
Loading

0 comments on commit 22b8c2b

Please sign in to comment.