wii sd can now get through the more intricate libogc init (which happens if the card is uninitialized). Unfortunately still doesn't work in nintendo apps... :(

Thanks a lot lpfaint99 for dumping some values!

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3035 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Shawn Hoffman 2009-04-22 06:44:49 +00:00
parent e7846a94ba
commit a5a0e0fd08
2 changed files with 96 additions and 26 deletions

View File

@ -33,6 +33,8 @@ CWII_IPC_HLE_Device_sdio_slot0::CWII_IPC_HLE_Device_sdio_slot0(u32 _DeviceID, co
m_Status = CARD_INSERTED;
m_BlockLength = 0;
m_BusWidth = 0;
// Clear the whole SD Host Control Register
Memory::Memset(SDIO_BASE, 0, 0x100);
}
CWII_IPC_HLE_Device_sdio_slot0::~CWII_IPC_HLE_Device_sdio_slot0()
@ -82,37 +84,58 @@ bool CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
u32 ReturnValue = 0;
switch (Cmd) {
case IOCTL_WRITEHCR:
// Store the 4th element of input array to the reg offset specified by the 0 element
Memory::Write_U32(Memory::Read_U32(BufferIn + 16), SDIO_BASE + Memory::Read_U32(BufferIn));
{
DEBUG_LOG(WII_IPC_SD, "IOCTL_WRITEHCR");
// Bleh, this might not be as simple as I thought at first...
u32 reg = Memory::Read_U32(BufferIn);
u32 val = Memory::Read_U32(BufferIn + 16);
if ((reg == HCR_CLOCKCONTROL) && (val & 1))
{
// Clock is set to oscilliate, enable bit 1 to say it's stable
Memory::Write_U32(val | 2, SDIO_BASE + reg);
}
else if ((reg == HCR_SOFTWARERESET) && val)
{
// When a reset is specified, the register gets cleared
Memory::Write_U32(0, SDIO_BASE + reg);
}
else
{
// Default to just storing the new value
Memory::Write_U32(val, SDIO_BASE + reg);
}
}
break;
case IOCTL_READHCR:
DEBUG_LOG(WII_IPC_SD, "IOCTL_READHCR");
// Load the specified reg into the out buffer
Memory::Write_U32(Memory::Read_U32(SDIO_BASE + Memory::Read_U32(BufferIn)), BufferOut);
DEBUG_LOG(WII_IPC_SD, "IOCTL_READHCR");
break;
case IOCTL_RESETCARD:
m_Status |= CARD_INITIALIZED;
DEBUG_LOG(WII_IPC_SD, "IOCTL_RESETCARD");
if (m_Card)
m_Status |= CARD_INITIALIZED;
// Returns 16bit RCA and 16bit 0s (meaning success)
Memory::Write_U32(0x9f620000, BufferOut);
break;
case IOCTL_SETCLK:
{
DEBUG_LOG(WII_IPC_SD, "IOCTL_SETCLK");
// libogc only sets it to 1 and makes sure the return isn't negative...
// one half of the sdclk divisor: a power of two or zero.
u32 clock = Memory::Read_U32(BufferIn);
if (clock != 1)
INFO_LOG(WII_IPC_SD, "Setting to %i, interesting", clock);
DEBUG_LOG(WII_IPC_SD, "IOCTL_SETCLK");
}
break;
case IOCTL_SENDCMD:
// Input: 24 bytes, Output: 10 bytes
DEBUG_LOG(WII_IPC_SD, "IOCTL_SENDCMD 0x%08x", Memory::Read_U32(BufferIn));
ReturnValue = ExecuteCommand(BufferIn, BufferInSize, BufferOut, BufferOutSize);
INFO_LOG(WII_IPC_SD, "IOCTL_SENDCMD 0x%08x", Memory::Read_U32(BufferIn));
ReturnValue = ExecuteCommand(BufferIn, BufferInSize, 0, 0, BufferOut, BufferOutSize);
break;
case IOCTL_GETSTATUS:
@ -123,7 +146,7 @@ bool CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
break;
case IOCTL_GETOCR:
ERROR_LOG(WII_IPC_SD, "IOCTL_GETOCR");
DEBUG_LOG(WII_IPC_SD, "IOCTL_GETOCR");
Memory::Write_U32(0x80ff8000, BufferOut);
break;
@ -132,8 +155,8 @@ bool CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
break;
}
// INFO_LOG(WII_IPC_SD, "InBuffer");
// DumpCommands(BufferIn, BufferInSize / 4, LogTypes::WII_IPC_SD);
INFO_LOG(WII_IPC_SD, "InBuffer");
DumpCommands(BufferIn, BufferInSize / 4, LogTypes::WII_IPC_SD);
INFO_LOG(WII_IPC_SD, "OutBuffer");
DumpCommands(BufferOut, BufferOutSize/4, LogTypes::WII_IPC_SD);
@ -159,10 +182,11 @@ bool CWII_IPC_HLE_Device_sdio_slot0::IOCtlV(u32 _CommandAddress)
u32 ReturnValue = 0;
switch(CommandBuffer.Parameter) {
case IOCTLV_SENDCMD:
DEBUG_LOG(WII_IPC_SD, "IOCTLV_SENDCMD");
INFO_LOG(WII_IPC_SD, "IOCTLV_SENDCMD 0x%08x", Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address));
ReturnValue = ExecuteCommand(
CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size,
CommandBuffer.InBuffer[1].m_Address, CommandBuffer.InBuffer[1].m_Size);
CommandBuffer.InBuffer[1].m_Address, CommandBuffer.InBuffer[1].m_Size,
CommandBuffer.PayloadBuffer[0].m_Address, CommandBuffer.PayloadBuffer[0].m_Size);
break;
default:
@ -178,6 +202,7 @@ bool CWII_IPC_HLE_Device_sdio_slot0::IOCtlV(u32 _CommandAddress)
}
u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize,
u32 _BufferIn2, u32 _BufferInSize2,
u32 _BufferOut, u32 _BufferOutSize)
{
// The game will send us a SendCMD with this information. To be able to read and write
@ -208,35 +233,69 @@ u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(u32 _BufferIn, u32 _BufferInS
switch (req.command)
{
case GO_IDLE_STATE:
// libogc can use it during init..
break;
case SEND_RELATIVE_ADDR:
// Technically RCA should be generated when asked and at power on...w/e :p
Memory::Write_U32(0x9f62, _BufferOut);
break;
case SELECT_CARD:
// This covers both select and deselect
// Differentiate by checking if rca is set in req.arg
// If it is, it's a select and return 0x700
Memory::Write_U32((req.arg>>16) ? 0x700 : 0x900, _BufferOut);
break;
case SEND_IF_COND:
// If the card can operate on the supplied voltage, the response echoes back the supply
// voltage and the check pattern that were set in the command argument.
Memory::Write_U32(req.arg, _BufferOut);
break;
case SEND_CSD:
ERROR_LOG(WII_IPC_SD, "SEND_CSD");
DEBUG_LOG(WII_IPC_SD, "SEND_CSD");
// <WntrMute> shuffle2_, OCR: 0x80ff8000 CID: 0x38a00000 0x480032d5 0x3c608030 0x8803d420
// CSD: 0xff928040 0xc93efbcf 0x325f5a83 0x00002600
Memory::Write_U64(0xff928040c93efbcfULL, _BufferOut);
Memory::Write_U64(0x325f5a8300002600ULL, _BufferOut + 8);
// Values used currently are from lpfaint99
Memory::Write_U32(0x80168000, _BufferOut);
Memory::Write_U32(0xa9ffffff, _BufferOut + 4);
Memory::Write_U32(0x325b5a83, _BufferOut + 8);
Memory::Write_U32(0x00002e00, _BufferOut + 12);
break;
case ALL_SEND_CID:
case SEND_CID:
ERROR_LOG(WII_IPC_SD, "(ALL_)SEND_CID");
Memory::Write_U64(0x38a00000480032d5ULL, _BufferOut);
Memory::Write_U64(0x3c6080308803d420ULL, _BufferOut + 8);
DEBUG_LOG(WII_IPC_SD, "(ALL_)SEND_CID");
Memory::Write_U32(0x80114d1c, _BufferOut);
Memory::Write_U32(0x80080000, _BufferOut + 4);
Memory::Write_U32(0x8007b520, _BufferOut + 8);
Memory::Write_U32(0x80080000, _BufferOut + 12);
break;
case SET_BLOCKLEN:
m_BlockLength = req.arg;
Memory::Write_U32(0x900, _BufferOut);
break;
case APP_CMD_NEXT:
// Next cmd is going to be ACMD_*
Memory::Write_U32(0x920, _BufferOut);
break;
case ACMD_SETBUSWIDTH:
// 0 = 1bit, 2 = 4bit
m_BusWidth = (req.arg & 3);
Memory::Write_U32(0x920, _BufferOut);
break;
case ACMD_SENDOPCOND:
// Sends host capacity support information (HCS) and asks the accessed card to send
// its operating condition register (OCR) content
Memory::Write_U32(0x80ff8000, _BufferOut);
break;
case READ_MULTIPLE_BLOCK:
@ -263,7 +322,7 @@ u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(u32 _BufferIn, u32 _BufferInS
{
Memory::Write_U8((u8)buffer[i], req.addr++);
}
DEBUG_LOG(WII_IPC_SD, "outbuffer size %i wrote %i", _BufferOutSize, i);
DEBUG_LOG(WII_IPC_SD, "outbuffer size %i got %i", _BufferInSize2, i);
rwSuccess = 1;
}
else
@ -275,14 +334,15 @@ u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(u32 _BufferIn, u32 _BufferInS
delete [] buffer;
}
}
Memory::Write_U32(0x900, _BufferOut);
break;
case WRITE_MULTIPLE_BLOCK:
{
// Data address (req.arg) is in byte units in a Standard Capacity SD Memory Card
// and in block (512 Byte) units in a High Capacity SD Memory Card.
DEBUG_LOG(WII_IPC_SD, "%sWrite %i Block(s) from 0x%08x bsize %i into 0x%08x!",
req.isDMA ? "DMA " : "", req.blocks, req.arg, req.bsize, req.addr);
DEBUG_LOG(WII_IPC_SD, "%sWrite %i Block(s) from 0x%08x bsize %i to offset 0x%08x!",
req.isDMA ? "DMA " : "", req.blocks, req.addr, req.bsize, req.arg);
if (m_Card)
{
@ -313,6 +373,7 @@ u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(u32 _BufferIn, u32 _BufferInS
delete [] buffer;
}
}
Memory::Write_U32(0x900, _BufferOut);
break;
case CRAZY_BIGN:

View File

@ -42,6 +42,13 @@ private:
SDIO_BASE = 0x8d070000,
};
// SD Host Controller Registers
enum
{
HCR_CLOCKCONTROL = 0x2C,
HCR_SOFTWARERESET = 0x2F,
};
// IOCtl
enum
{
@ -96,7 +103,9 @@ private:
FILE* m_Card;
u32 ExecuteCommand(u32 BufferIn, u32 BufferInSize, u32 _BufferOut, u32 BufferOutSize);
u32 ExecuteCommand(u32 BufferIn, u32 BufferInSize,
u32 BufferIn2, u32 BufferInSize2,
u32 _BufferOut, u32 BufferOutSize);
};
#endif