Skip to content

Commit

Permalink
hb: R/W SD data all at once instead of in blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
RocketRobz committed Mar 16, 2024
1 parent 9939593 commit 91d60a6
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 23 deletions.
73 changes: 73 additions & 0 deletions hb/dldi/source/dcache.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*---------------------------------------------------------------------------------
Copyright (C) 2005
Michael Noland (joat)
Jason Rogers (dovoto)
Dave Murphy (WinterMute)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
---------------------------------------------------------------------------------*/
#include <nds/asminc.h>

//---------------------------------------------------------------------------------
.arm
//---------------------------------------------------------------------------------
BEGIN_ASM_FUNC DC_FlushRange
/*---------------------------------------------------------------------------------
Clean and invalidate a range
---------------------------------------------------------------------------------*/
add r1, r1, r0
bic r0, r0, #(CACHE_LINE_SIZE - 1)
.flush:
mcr p15, 0, r0, c7, c14, 1 @ clean and flush address
add r0, r0, #CACHE_LINE_SIZE
cmp r0, r1
blt .flush

drainWriteBuffer:
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
bx lr

//---------------------------------------------------------------------------------
BEGIN_ASM_FUNC DC_InvalidateAll
/*---------------------------------------------------------------------------------
Clean and invalidate entire data cache
---------------------------------------------------------------------------------*/
mov r0, #0
mcr p15, 0, r0, c7, c6, 0
bx lr

//---------------------------------------------------------------------------------
BEGIN_ASM_FUNC DC_InvalidateRange
/*---------------------------------------------------------------------------------
Invalidate a range
---------------------------------------------------------------------------------*/
add r1, r1, r0
tst r0, #CACHE_LINE_SIZE - 1
mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
tst r1, #CACHE_LINE_SIZE - 1
mcrne p15, 0, r1, c7, c10, 1 @ clean D entry
bic r0, r0, #CACHE_LINE_SIZE - 1
.invalidate:
mcr p15, 0, r0, c7, c6, 1
add r0, r0, #CACHE_LINE_SIZE
cmp r0, r1
blt .invalidate
bx lr
92 changes: 69 additions & 23 deletions hb/dldi/source/iointerface.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,27 @@
#include "locations.h"
#include "aeabi.h"

/*! \fn DC_FlushRange(const void *base, u32 size)
\brief flush the data cache for a range of addresses to memory.
\param base base address of the region to flush.
\param size size of the region to flush.
*/
void DC_FlushRange(const void *base, u32 size);


/*! \fn DC_InvalidateAll()
\brief invalidate the entire data cache.
*/
void DC_InvalidateAll();


/*! \fn DC_InvalidateRange(const void *base, u32 size)
\brief invalidate the data cache for a range of addresses.
\param base base address of the region to invalidate
\param size size of the region to invalidate.
*/
void DC_InvalidateRange(const void *base, u32 size);

extern char ioType[4];
extern u32 dataStartOffset;
//extern vu32 word_command; // word_command_offset
Expand Down Expand Up @@ -165,29 +186,42 @@ bool sd_ReadSectors(sec_t sector, sec_t numSectors,void* buffer) {
//nocashMessage("sd_ReadSectors");
FifoMessage msg;
int result = 0;
sec_t startsector, readsectors;
if ((u32)buffer < 0x02000000 || (u32)buffer >= 0x04000000) {
sec_t startsector, readsectors;

int max_reads = ((1 << allocated_space) / 512) - 11;

for(int numreads =0; numreads<numSectors; numreads+=max_reads) {
startsector = sector+numreads;
if(numSectors - numreads < max_reads) readsectors = numSectors - numreads ;
else readsectors = max_reads;

msg.type = SDMMC_SD_READ_SECTORS;
msg.sdParams.startsector = startsector;
msg.sdParams.numsectors = readsectors;
msg.sdParams.buffer = (u32*)tmp_buf_addr;

int max_reads = ((1 << allocated_space) / 512) - 11;
DC_InvalidateRange((u32*)tmp_buf_addr, readsectors*512);
sendMsg(sizeof(msg), (u8*)&msg);

for(int numreads =0; numreads<numSectors; numreads+=max_reads) {
startsector = sector+numreads;
if(numSectors - numreads < max_reads) readsectors = numSectors - numreads ;
else readsectors = max_reads;
waitValue32();

vu32* mybuffer = (vu32*)((u32)tmp_buf_addr + (dsiMode ? 0x0A000000 : 0x00400000));
result = getValue32();

__aeabi_memcpy(buffer+numreads*512, (u32*)tmp_buf_addr, readsectors*512);
}
} else {
msg.type = SDMMC_SD_READ_SECTORS;
msg.sdParams.startsector = startsector;
msg.sdParams.numsectors = readsectors;
msg.sdParams.buffer = (u32*)mybuffer;
msg.sdParams.startsector = sector;
msg.sdParams.numsectors = numSectors;
msg.sdParams.buffer = buffer;

DC_InvalidateRange(buffer, numSectors*512);
sendMsg(sizeof(msg), (u8*)&msg);

waitValue32();

result = getValue32();

__aeabi_memcpy(buffer+numreads*512, (u32*)mybuffer, readsectors*512);
}

/*sec_t alignedSector = (sector/cacheBlockSectors)*cacheBlockSectors;
Expand Down Expand Up @@ -240,24 +274,36 @@ bool sd_WriteSectors(sec_t sector, sec_t numSectors,void* buffer) {
//nocashMessage("sd_ReadSectors");
FifoMessage msg;
int result = 0;
sec_t startsector, readsectors;
if ((u32)buffer < 0x02000000 || (u32)buffer >= 0x04000000) {
sec_t startsector, readsectors;

int max_reads = ((1 << allocated_space) / 512) - 11;
int max_reads = ((1 << allocated_space) / 512) - 11;

for(int numreads =0; numreads<numSectors; numreads+=max_reads) {
startsector = sector+numreads;
if(numSectors - numreads < max_reads) readsectors = numSectors - numreads ;
else readsectors = max_reads;
for(int numreads =0; numreads<numSectors; numreads+=max_reads) {
startsector = sector+numreads;
if(numSectors - numreads < max_reads) readsectors = numSectors - numreads ;
else readsectors = max_reads;

vu32* mybuffer = (vu32*)((u32)tmp_buf_addr + (dsiMode ? 0x0A000000 : 0x00400000));
msg.type = SDMMC_SD_WRITE_SECTORS;
msg.sdParams.startsector = startsector;
msg.sdParams.numsectors = readsectors;
msg.sdParams.buffer = (u32*)tmp_buf_addr;

__aeabi_memcpy((u32*)mybuffer, buffer+numreads*512, readsectors*512);
__aeabi_memcpy((u32*)tmp_buf_addr, buffer+numreads*512, readsectors*512);
DC_FlushRange((u32*)tmp_buf_addr, numSectors*512);
sendMsg(sizeof(msg), (u8*)&msg);

waitValue32();

result = getValue32();
}
} else {
msg.type = SDMMC_SD_WRITE_SECTORS;
msg.sdParams.startsector = startsector;
msg.sdParams.numsectors = readsectors;
msg.sdParams.buffer = (u32*)mybuffer;
msg.sdParams.startsector = sector;
msg.sdParams.numsectors = numSectors;
msg.sdParams.buffer = buffer;

DC_FlushRange(buffer, numSectors*512);
sendMsg(sizeof(msg), (u8*)&msg);

waitValue32();
Expand Down

0 comments on commit 91d60a6

Please sign in to comment.