SDIOSlot0: Separate IOCtl/IOCtlV behavior into individual functions
Keeps the individual behaviors separate from one another.
This commit is contained in:
parent
13d23c21b7
commit
225ac37f21
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue