SDIOSlot0: Separate IOCtl/IOCtlV behavior into individual functions

Keeps the individual behaviors separate from one another.
This commit is contained in:
Lioncash 2017-03-13 16:22:41 -04:00
parent 13d23c21b7
commit 225ac37f21
2 changed files with 157 additions and 108 deletions

View File

@ -92,137 +92,46 @@ void SDIOSlot0::Close()
m_is_active = false; m_is_active = false;
} }
// The front SD slot
IPCCommandResult SDIOSlot0::IOCtl(const IOCtlRequest& request) IPCCommandResult SDIOSlot0::IOCtl(const IOCtlRequest& request)
{ {
Memory::Memset(request.buffer_out, 0, request.buffer_out_size); Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
s32 return_value = IPC_SUCCESS;
switch (request.request) switch (request.request)
{ {
case IOCTL_WRITEHCR: case IOCTL_WRITEHCR:
{ return WriteHCRegister(request);
u32 reg = Memory::Read_U32(request.buffer_in);
u32 val = Memory::Read_U32(request.buffer_in + 16);
INFO_LOG(IOS_SD, "IOCTL_WRITEHCR 0x%08x - 0x%08x", reg, val);
if (reg >= m_registers.size())
{
WARN_LOG(IOS_SD, "IOCTL_WRITEHCR out of range");
break;
}
if ((reg == HCR_CLOCKCONTROL) && (val & 1))
{
// Clock is set to oscillate, enable bit 1 to say it's stable
m_registers[reg] = val | 2;
}
else if ((reg == HCR_SOFTWARERESET) && val)
{
// When a reset is specified, the register gets cleared
m_registers[reg] = 0;
}
else
{
// Default to just storing the new value
m_registers[reg] = val;
}
}
break;
case IOCTL_READHCR: case IOCTL_READHCR:
{ return ReadHCRegister(request);
u32 reg = Memory::Read_U32(request.buffer_in);
if (reg >= m_registers.size())
{
WARN_LOG(IOS_SD, "IOCTL_READHCR out of range");
break;
}
u32 val = m_registers[reg];
INFO_LOG(IOS_SD, "IOCTL_READHCR 0x%08x - 0x%08x", reg, val);
// Just reading the register
Memory::Write_U32(val, request.buffer_out);
}
break;
case IOCTL_RESETCARD: case IOCTL_RESETCARD:
INFO_LOG(IOS_SD, "IOCTL_RESETCARD"); return ResetCard(request);
if (m_Card)
m_Status |= CARD_INITIALIZED;
// Returns 16bit RCA and 16bit 0s (meaning success)
Memory::Write_U32(0x9f620000, request.buffer_out);
break;
case IOCTL_SETCLK: case IOCTL_SETCLK:
{ return SetClk(request);
INFO_LOG(IOS_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(request.buffer_in);
if (clock != 1)
INFO_LOG(IOS_SD, "Setting to %i, interesting", clock);
}
break;
case IOCTL_SENDCMD: case IOCTL_SENDCMD:
INFO_LOG(IOS_SD, "IOCTL_SENDCMD %x IPC:%08x", Memory::Read_U32(request.buffer_in), return SendCommand(request);
request.address);
return_value = ExecuteCommand(request, request.buffer_in, request.buffer_in_size, 0, 0,
request.buffer_out, request.buffer_out_size);
break;
case IOCTL_GETSTATUS: case IOCTL_GETSTATUS:
if (SConfig::GetInstance().m_WiiSDCard) return GetStatus(request);
m_Status |= CARD_INSERTED;
else
m_Status = CARD_NOT_EXIST;
INFO_LOG(IOS_SD, "IOCTL_GETSTATUS. Replying that SD card is %s%s",
(m_Status & CARD_INSERTED) ? "inserted" : "not present",
(m_Status & CARD_INITIALIZED) ? " and initialized" : "");
Memory::Write_U32(m_Status, request.buffer_out);
break;
case IOCTL_GETOCR: case IOCTL_GETOCR:
INFO_LOG(IOS_SD, "IOCTL_GETOCR"); return GetOCRegister(request);
Memory::Write_U32(0x80ff8000, request.buffer_out);
break;
default: default:
ERROR_LOG(IOS_SD, "Unknown SD IOCtl command (0x%08x)", request.request); ERROR_LOG(IOS_SD, "Unknown SD IOCtl command (0x%08x)", request.request);
break; break;
} }
if (return_value == RET_EVENT_REGISTER) return GetDefaultReply(IPC_SUCCESS);
{
// Check if the condition is already true
EventNotify();
return GetNoReply();
}
return GetDefaultReply(return_value);
} }
IPCCommandResult SDIOSlot0::IOCtlV(const IOCtlVRequest& request) IPCCommandResult SDIOSlot0::IOCtlV(const IOCtlVRequest& request)
{ {
s32 return_value = IPC_SUCCESS;
switch (request.request) switch (request.request)
{ {
case IOCTLV_SENDCMD: case IOCTLV_SENDCMD:
DEBUG_LOG(IOS_SD, "IOCTLV_SENDCMD 0x%08x", Memory::Read_U32(request.in_vectors[0].address)); return SendCommand(request);
Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
return_value =
ExecuteCommand(request, request.in_vectors[0].address, request.in_vectors[0].size,
request.in_vectors[1].address, request.in_vectors[1].size,
request.io_vectors[0].address, request.io_vectors[0].size);
break;
default: default:
ERROR_LOG(IOS_SD, "Unknown SD IOCtlV command 0x%08x", request.request); ERROR_LOG(IOS_SD, "Unknown SD IOCtlV command 0x%08x", request.request);
break;
} }
return GetDefaultReply(return_value); return GetDefaultReply(IPC_SUCCESS);
} }
u32 SDIOSlot0::ExecuteCommand(const Request& request, u32 _BufferIn, u32 _BufferInSize, u32 SDIOSlot0::ExecuteCommand(const Request& request, u32 _BufferIn, u32 _BufferInSize,
@ -405,6 +314,134 @@ u32 SDIOSlot0::ExecuteCommand(const Request& request, u32 _BufferIn, u32 _Buffer
return ret; return ret;
} }
IPCCommandResult SDIOSlot0::WriteHCRegister(const IOCtlRequest& request)
{
u32 reg = Memory::Read_U32(request.buffer_in);
u32 val = Memory::Read_U32(request.buffer_in + 16);
INFO_LOG(IOS_SD, "IOCTL_WRITEHCR 0x%08x - 0x%08x", reg, val);
if (reg >= m_registers.size())
{
WARN_LOG(IOS_SD, "IOCTL_WRITEHCR out of range");
return GetDefaultReply(IPC_SUCCESS);
}
if ((reg == HCR_CLOCKCONTROL) && (val & 1))
{
// Clock is set to oscillate, enable bit 1 to say it's stable
m_registers[reg] = val | 2;
}
else if ((reg == HCR_SOFTWARERESET) && val)
{
// When a reset is specified, the register gets cleared
m_registers[reg] = 0;
}
else
{
// Default to just storing the new value
m_registers[reg] = val;
}
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0::ReadHCRegister(const IOCtlRequest& request)
{
u32 reg = Memory::Read_U32(request.buffer_in);
if (reg >= m_registers.size())
{
WARN_LOG(IOS_SD, "IOCTL_READHCR out of range");
return GetDefaultReply(IPC_SUCCESS);
}
u32 val = m_registers[reg];
INFO_LOG(IOS_SD, "IOCTL_READHCR 0x%08x - 0x%08x", reg, val);
// Just reading the register
Memory::Write_U32(val, request.buffer_out);
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0::ResetCard(const IOCtlRequest& request)
{
INFO_LOG(IOS_SD, "IOCTL_RESETCARD");
if (m_Card)
m_Status |= CARD_INITIALIZED;
// Returns 16bit RCA and 16bit 0s (meaning success)
Memory::Write_U32(0x9f620000, request.buffer_out);
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0::SetClk(const IOCtlRequest& request)
{
INFO_LOG(IOS_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(request.buffer_in);
if (clock != 1)
INFO_LOG(IOS_SD, "Setting to %i, interesting", clock);
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0::SendCommand(const IOCtlRequest& request)
{
INFO_LOG(IOS_SD, "IOCTL_SENDCMD %x IPC:%08x", Memory::Read_U32(request.buffer_in),
request.address);
const s32 return_value = ExecuteCommand(request, request.buffer_in, request.buffer_in_size, 0, 0,
request.buffer_out, request.buffer_out_size);
if (return_value == RET_EVENT_REGISTER)
{
// Check if the condition is already true
EventNotify();
return GetNoReply();
}
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0::GetStatus(const IOCtlRequest& request)
{
if (SConfig::GetInstance().m_WiiSDCard)
m_Status |= CARD_INSERTED;
else
m_Status = CARD_NOT_EXIST;
INFO_LOG(IOS_SD, "IOCTL_GETSTATUS. Replying that SD card is %s%s",
(m_Status & CARD_INSERTED) ? "inserted" : "not present",
(m_Status & CARD_INITIALIZED) ? " and initialized" : "");
Memory::Write_U32(m_Status, request.buffer_out);
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0::GetOCRegister(const IOCtlRequest& request)
{
INFO_LOG(IOS_SD, "IOCTL_GETOCR");
Memory::Write_U32(0x80ff8000, request.buffer_out);
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult SDIOSlot0::SendCommand(const IOCtlVRequest& request)
{
DEBUG_LOG(IOS_SD, "IOCTLV_SENDCMD 0x%08x", Memory::Read_U32(request.in_vectors[0].address));
Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
const s32 return_value =
ExecuteCommand(request, request.in_vectors[0].address, request.in_vectors[0].size,
request.in_vectors[1].address, request.in_vectors[1].size,
request.io_vectors[0].address, request.io_vectors[0].size);
return GetDefaultReply(return_value);
}
} // namespace Device } // namespace Device
} // namespace HLE } // namespace HLE
} // namespace IOS } // namespace IOS

View File

@ -22,6 +22,7 @@ namespace HLE
{ {
namespace Device namespace Device
{ {
// The front SD slot
class SDIOSlot0 : public Device class SDIOSlot0 : public Device
{ {
public: public:
@ -110,13 +111,28 @@ private:
EVENT_INVALID = 0xc210000 EVENT_INVALID = 0xc210000
}; };
// TODO do we need more than one?
struct Event struct Event
{ {
Event(EventType type_, Request request_) : type(type_), request(request_) {} Event(EventType type_, Request request_) : type(type_), request(request_) {}
EventType type; EventType type;
Request request; Request request;
}; };
IPCCommandResult WriteHCRegister(const IOCtlRequest& request);
IPCCommandResult ReadHCRegister(const IOCtlRequest& request);
IPCCommandResult ResetCard(const IOCtlRequest& request);
IPCCommandResult SetClk(const IOCtlRequest& request);
IPCCommandResult SendCommand(const IOCtlRequest& request);
IPCCommandResult GetStatus(const IOCtlRequest& request);
IPCCommandResult GetOCRegister(const IOCtlRequest& request);
IPCCommandResult SendCommand(const IOCtlVRequest& request);
u32 ExecuteCommand(const Request& request, u32 BufferIn, u32 BufferInSize, u32 BufferIn2,
u32 BufferInSize2, u32 _BufferOut, u32 BufferOutSize);
void OpenInternal();
// TODO: do we need more than one?
std::unique_ptr<Event> m_event; std::unique_ptr<Event> m_event;
u32 m_Status = CARD_NOT_EXIST; u32 m_Status = CARD_NOT_EXIST;
@ -126,10 +142,6 @@ private:
std::array<u32, 0x200 / sizeof(u32)> m_registers; std::array<u32, 0x200 / sizeof(u32)> m_registers;
File::IOFile m_Card; File::IOFile m_Card;
u32 ExecuteCommand(const Request& request, u32 BufferIn, u32 BufferInSize, u32 BufferIn2,
u32 BufferInSize2, u32 _BufferOut, u32 BufferOutSize);
void OpenInternal();
}; };
} // namespace Device } // namespace Device
} // namespace HLE } // namespace HLE