aboutsummaryrefslogtreecommitdiff
path: root/src/DSi_SD.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/DSi_SD.cpp')
-rw-r--r--src/DSi_SD.cpp105
1 files changed, 83 insertions, 22 deletions
diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp
index c9edd78..07eca83 100644
--- a/src/DSi_SD.cpp
+++ b/src/DSi_SD.cpp
@@ -73,6 +73,10 @@ void DSi_SDHost::Reset()
IRQStatus = 0;
IRQMask = 0x8B7F031D;
+ CardIRQStatus = 0;
+ CardIRQMask = 0xC007;
+ CardIRQCtl = 0;
+
DataCtl = 0;
Data32IRQ = 0;
DataMode = 0;
@@ -145,6 +149,25 @@ void DSi_SDHost::SetIRQ(u32 irq)
if (irq == 24 || irq == 25) UpdateData32IRQ();
}
+void DSi_SDHost::SetCardIRQ()
+{
+ if (!(CardIRQCtl & (1<<0))) return;
+
+ u16 oldflags = CardIRQStatus & ~CardIRQMask;
+ DSi_SDDevice* dev = Ports[PortSelect & 0x1];
+
+ if (dev->IRQ) CardIRQStatus |= (1<<0);
+ else CardIRQStatus &= ~(1<<0);
+
+ u16 newflags = CardIRQStatus & ~CardIRQMask;
+
+ if ((oldflags == 0) && (newflags != 0)) // checkme
+ {
+ NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO : NDS::IRQ2_DSi_SDMMC);
+ NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO_Data1 : NDS::IRQ2_DSi_SD_Data1);
+ }
+}
+
void DSi_SDHost::SendResponse(u32 val, bool last)
{
*(u32*)&ResponseBuffer[6] = *(u32*)&ResponseBuffer[4];
@@ -166,10 +189,10 @@ void DSi_SDHost::FinishSend(u32 param)
//if (param & 0x2) host->SetIRQ(2);
}
-void DSi_SDHost::SendData(u8* data, u32 len)
+u32 DSi_SDHost::SendData(u8* data, u32 len)
{
printf("%s: data RX, len=%d, blkcnt=%d (%d) blklen=%d, irq=%08X\n", SD_DESC, len, BlockCount16, BlockCountInternal, BlockLen16, IRQMask);
- if (len != BlockLen16) printf("!! BAD BLOCKLEN\n");
+ if (len != BlockLen16) { printf("!! BAD BLOCKLEN\n"); len = BlockLen16; }
bool last = (BlockCountInternal == 0);
@@ -187,6 +210,8 @@ void DSi_SDHost::SendData(u8* data, u32 len)
u32 param = Num | (last << 1);
NDS::ScheduleEvent(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer,
false, 512, FinishSend, param);
+
+ return len;
}
void DSi_SDHost::FinishReceive(u32 param)
@@ -200,16 +225,16 @@ void DSi_SDHost::FinishReceive(u32 param)
if (dev) dev->ContinueTransfer();
}
-bool DSi_SDHost::ReceiveData(u8* data, u32 len)
+u32 DSi_SDHost::ReceiveData(u8* data, u32 len)
{
printf("%s: data TX, len=%d, blkcnt=%d (%d) blklen=%d, irq=%08X\n", SD_DESC, len, BlockCount16, BlockCountInternal, BlockLen16, IRQMask);
- if (len != BlockLen16) printf("!! BAD BLOCKLEN\n");
+ if (len != BlockLen16) { printf("!! BAD BLOCKLEN\n"); len = BlockLen16; }
u32 f = CurFIFO;
if ((DataFIFO[f]->Level() << 1) < len)
{
printf("%s: FIFO not full enough for a transfer (%d / %d)\n", SD_DESC, DataFIFO[f]->Level()<<1, len);
- return false;
+ return 0;
}
DSi_SDDevice* dev = Ports[PortSelect & 0x1];
@@ -240,7 +265,13 @@ bool DSi_SDHost::ReceiveData(u8* data, u32 len)
BlockCountInternal--;
}
- return true;
+ return len;
+}
+
+u32 DSi_SDHost::GetTransferrableLen(u32 len)
+{
+ if (len > BlockLen16) len = BlockLen16; // checkme
+ return len;
}
@@ -278,6 +309,10 @@ u16 DSi_SDHost::Read(u32 addr)
case 0x02C: return 0; // TODO
+ case 0x034: return CardIRQCtl;
+ case 0x036: return CardIRQStatus;
+ case 0x038: return CardIRQMask;
+
case 0x030: // FIFO16
{
// TODO: decrement BlockLen????
@@ -389,7 +424,7 @@ u32 DSi_SDHost::ReadFIFO32()
return ret;
}
-
+int morp = 0;
void DSi_SDHost::Write(u32 addr, u16 val)
{
//if(Num)printf("SDIO WRITE %08X %04X %08X\n", addr, val, NDS::GetPC(1));
@@ -470,6 +505,20 @@ void DSi_SDHost::Write(u32 addr, u16 val)
}
return;
+ case 0x034:
+ CardIRQCtl = val & 0x0305;
+ printf("[%d] CardIRQCtl = %04X\n", Num, val);
+ SetCardIRQ();
+ return;
+ case 0x036:
+ CardIRQStatus &= val;
+ return;
+ case 0x038:
+ CardIRQMask = val & 0xC007;
+ printf("[%d] CardIRQMask = %04X\n", Num, val);
+ SetCardIRQ();
+ return;
+
case 0x0D8:
DataCtl = (val & 0x0022);
DataMode = ((DataCtl >> 1) & 0x1) & ((Data32IRQ >> 1) & 0x1);
@@ -729,42 +778,54 @@ void DSi_MMCStorage::ContinueTransfer()
{
if (RWCommand == 0) return;
+ u32 len = 0;
+
switch (RWCommand)
{
case 18:
- ReadBlock(RWAddress);
+ len = ReadBlock(RWAddress);
break;
case 25:
- WriteBlock(RWAddress);
+ len = WriteBlock(RWAddress);
break;
}
- RWAddress += BlockSize;
+ RWAddress += len;
}
-void DSi_MMCStorage::ReadBlock(u64 addr)
+u32 DSi_MMCStorage::ReadBlock(u64 addr)
{
- if (!File) return;
-
printf("SD/MMC: reading block @ %08X, len=%08X\n", addr, BlockSize);
+ u32 len = BlockSize;
+ len = Host->GetTransferrableLen(len);
+
u8 data[0x200];
- fseek(File, addr, SEEK_SET);
- fread(data, 1, BlockSize, File);
- Host->SendData(data, BlockSize);
+ if (File)
+ {
+ fseek(File, addr, SEEK_SET);
+ fread(data, 1, len, File);
+ }
+ return Host->SendData(data, len);
}
-void DSi_MMCStorage::WriteBlock(u64 addr)
+u32 DSi_MMCStorage::WriteBlock(u64 addr)
{
- if (!File) return;
-
printf("SD/MMC: write block @ %08X, len=%08X\n", addr, BlockSize);
+ u32 len = BlockSize;
+ len = Host->GetTransferrableLen(len);
+
u8 data[0x200];
- if (Host->ReceiveData(data, BlockSize))
+ if (len = Host->ReceiveData(data, len))
{
- fseek(File, addr, SEEK_SET);
- fwrite(data, 1, BlockSize, File);
+ if (File)
+ {
+ fseek(File, addr, SEEK_SET);
+ fwrite(data, 1, len, File);
+ }
}
+
+ return len;
}