IOS HLE: Deduplicate request code in sdio_slot0
This commit is contained in:
parent
a04902086a
commit
469a31db32
|
@ -38,15 +38,16 @@ void CWII_IPC_HLE_Device_sdio_slot0::DoState(PointerWrap& p)
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_sdio_slot0::EventNotify()
|
void CWII_IPC_HLE_Device_sdio_slot0::EventNotify()
|
||||||
{
|
{
|
||||||
|
if (!m_event)
|
||||||
|
return;
|
||||||
// Accessing SConfig variables like this isn't really threadsafe,
|
// Accessing SConfig variables like this isn't really threadsafe,
|
||||||
// but this is how it's done all over the place...
|
// but this is how it's done all over the place...
|
||||||
if ((SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_INSERT) ||
|
if ((SConfig::GetInstance().m_WiiSDCard && m_event->type == EVENT_INSERT) ||
|
||||||
(!SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_REMOVE))
|
(!SConfig::GetInstance().m_WiiSDCard && m_event->type == EVENT_REMOVE))
|
||||||
{
|
{
|
||||||
Memory::Write_U32(m_event.type, m_event.addr + 4);
|
m_event->request.SetReturnValue(m_event->type);
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(m_event.addr);
|
WII_IPC_HLE_Interface::EnqueueReply(m_event->request);
|
||||||
m_event.addr = 0;
|
m_event.reset();
|
||||||
m_event.type = EVENT_NONE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,50 +71,35 @@ void CWII_IPC_HLE_Device_sdio_slot0::OpenInternal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::Open(u32 _CommandAddress, u32 _Mode)
|
IOSReturnCode CWII_IPC_HLE_Device_sdio_slot0::Open(const IOSOpenRequest& request)
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_SD, "Open");
|
|
||||||
|
|
||||||
OpenInternal();
|
OpenInternal();
|
||||||
|
|
||||||
m_registers.fill(0);
|
m_registers.fill(0);
|
||||||
|
|
||||||
m_is_active = true;
|
m_is_active = true;
|
||||||
return GetDefaultReply();
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::Close(u32 _CommandAddress, bool _bForce)
|
void CWII_IPC_HLE_Device_sdio_slot0::Close()
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_SD, "Close");
|
|
||||||
|
|
||||||
m_Card.Close();
|
m_Card.Close();
|
||||||
m_BlockLength = 0;
|
m_BlockLength = 0;
|
||||||
m_BusWidth = 0;
|
m_BusWidth = 0;
|
||||||
|
|
||||||
m_is_active = false;
|
m_is_active = false;
|
||||||
return GetDefaultReply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The front SD slot
|
// The front SD slot
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
|
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(const IOSIOCtlRequest& request)
|
||||||
{
|
{
|
||||||
u32 Cmd = Memory::Read_U32(_CommandAddress + 0xC);
|
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
|
||||||
|
s32 return_value = IPC_SUCCESS;
|
||||||
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
|
switch (request.request)
|
||||||
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
|
|
||||||
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
|
|
||||||
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
|
|
||||||
|
|
||||||
// As a safety precaution we fill the out buffer with zeros to avoid
|
|
||||||
// returning nonsense values
|
|
||||||
Memory::Memset(BufferOut, 0, BufferOutSize);
|
|
||||||
|
|
||||||
u32 ReturnValue = 0;
|
|
||||||
switch (Cmd)
|
|
||||||
{
|
{
|
||||||
case IOCTL_WRITEHCR:
|
case IOCTL_WRITEHCR:
|
||||||
{
|
{
|
||||||
u32 reg = Memory::Read_U32(BufferIn);
|
u32 reg = Memory::Read_U32(request.buffer_in);
|
||||||
u32 val = Memory::Read_U32(BufferIn + 16);
|
u32 val = Memory::Read_U32(request.buffer_in + 16);
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_SD, "IOCTL_WRITEHCR 0x%08x - 0x%08x", reg, val);
|
INFO_LOG(WII_IPC_SD, "IOCTL_WRITEHCR 0x%08x - 0x%08x", reg, val);
|
||||||
|
|
||||||
|
@ -143,7 +129,7 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
|
||||||
|
|
||||||
case IOCTL_READHCR:
|
case IOCTL_READHCR:
|
||||||
{
|
{
|
||||||
u32 reg = Memory::Read_U32(BufferIn);
|
u32 reg = Memory::Read_U32(request.buffer_in);
|
||||||
|
|
||||||
if (reg >= m_registers.size())
|
if (reg >= m_registers.size())
|
||||||
{
|
{
|
||||||
|
@ -155,7 +141,7 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
|
||||||
INFO_LOG(WII_IPC_SD, "IOCTL_READHCR 0x%08x - 0x%08x", reg, val);
|
INFO_LOG(WII_IPC_SD, "IOCTL_READHCR 0x%08x - 0x%08x", reg, val);
|
||||||
|
|
||||||
// Just reading the register
|
// Just reading the register
|
||||||
Memory::Write_U32(val, BufferOut);
|
Memory::Write_U32(val, request.buffer_out);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -164,7 +150,7 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
|
||||||
if (m_Card)
|
if (m_Card)
|
||||||
m_Status |= CARD_INITIALIZED;
|
m_Status |= CARD_INITIALIZED;
|
||||||
// Returns 16bit RCA and 16bit 0s (meaning success)
|
// Returns 16bit RCA and 16bit 0s (meaning success)
|
||||||
Memory::Write_U32(0x9f620000, BufferOut);
|
Memory::Write_U32(0x9f620000, request.buffer_out);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_SETCLK:
|
case IOCTL_SETCLK:
|
||||||
|
@ -172,15 +158,17 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
|
||||||
INFO_LOG(WII_IPC_SD, "IOCTL_SETCLK");
|
INFO_LOG(WII_IPC_SD, "IOCTL_SETCLK");
|
||||||
// libogc only sets it to 1 and makes sure the return isn't negative...
|
// 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.
|
// one half of the sdclk divisor: a power of two or zero.
|
||||||
u32 clock = Memory::Read_U32(BufferIn);
|
u32 clock = Memory::Read_U32(request.buffer_in);
|
||||||
if (clock != 1)
|
if (clock != 1)
|
||||||
INFO_LOG(WII_IPC_SD, "Setting to %i, interesting", clock);
|
INFO_LOG(WII_IPC_SD, "Setting to %i, interesting", clock);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_SENDCMD:
|
case IOCTL_SENDCMD:
|
||||||
INFO_LOG(WII_IPC_SD, "IOCTL_SENDCMD %x IPC:%08x", Memory::Read_U32(BufferIn), _CommandAddress);
|
INFO_LOG(WII_IPC_SD, "IOCTL_SENDCMD %x IPC:%08x", Memory::Read_U32(request.buffer_in),
|
||||||
ReturnValue = ExecuteCommand(BufferIn, BufferInSize, 0, 0, BufferOut, BufferOutSize);
|
request.address);
|
||||||
|
return_value = ExecuteCommand(request, request.buffer_in, request.buffer_in_size, 0, 0,
|
||||||
|
request.buffer_out, request.buffer_out_size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_GETSTATUS:
|
case IOCTL_GETSTATUS:
|
||||||
|
@ -191,81 +179,53 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
|
||||||
INFO_LOG(WII_IPC_SD, "IOCTL_GETSTATUS. Replying that SD card is %s%s",
|
INFO_LOG(WII_IPC_SD, "IOCTL_GETSTATUS. Replying that SD card is %s%s",
|
||||||
(m_Status & CARD_INSERTED) ? "inserted" : "not present",
|
(m_Status & CARD_INSERTED) ? "inserted" : "not present",
|
||||||
(m_Status & CARD_INITIALIZED) ? " and initialized" : "");
|
(m_Status & CARD_INITIALIZED) ? " and initialized" : "");
|
||||||
Memory::Write_U32(m_Status, BufferOut);
|
Memory::Write_U32(m_Status, request.buffer_out);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_GETOCR:
|
case IOCTL_GETOCR:
|
||||||
INFO_LOG(WII_IPC_SD, "IOCTL_GETOCR");
|
INFO_LOG(WII_IPC_SD, "IOCTL_GETOCR");
|
||||||
Memory::Write_U32(0x80ff8000, BufferOut);
|
Memory::Write_U32(0x80ff8000, request.buffer_out);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtl command (0x%08x)", Cmd);
|
ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtl command (0x%08x)", request.request);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ReturnValue == RET_EVENT_REGISTER)
|
if (return_value == RET_EVENT_REGISTER)
|
||||||
{
|
{
|
||||||
// async
|
|
||||||
m_event.addr = _CommandAddress;
|
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
|
||||||
// Check if the condition is already true
|
// Check if the condition is already true
|
||||||
EventNotify();
|
EventNotify();
|
||||||
return GetNoReply();
|
return GetNoReply();
|
||||||
}
|
}
|
||||||
else if (ReturnValue == RET_EVENT_UNREGISTER)
|
request.SetReturnValue(return_value);
|
||||||
{
|
|
||||||
// release returns 0
|
|
||||||
// unknown sd int
|
|
||||||
// technically we do it out of order, oh well
|
|
||||||
Memory::Write_U32(EVENT_INVALID, m_event.addr + 4);
|
|
||||||
WII_IPC_HLE_Interface::EnqueueReply(m_event.addr);
|
|
||||||
m_event.addr = 0;
|
|
||||||
m_event.type = EVENT_NONE;
|
|
||||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
|
||||||
return GetDefaultReply();
|
return GetDefaultReply();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtlV(const IOSIOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
s32 return_value = IPC_SUCCESS;
|
||||||
return GetDefaultReply();
|
switch (request.request)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtlV(u32 _CommandAddress)
|
|
||||||
{
|
|
||||||
// PPC sending commands
|
|
||||||
|
|
||||||
SIOCtlVBuffer CommandBuffer(_CommandAddress);
|
|
||||||
|
|
||||||
// Prepare the out buffer(s) with zeros as a safety precaution
|
|
||||||
// to avoid returning bad values
|
|
||||||
for (const auto& buffer : CommandBuffer.PayloadBuffer)
|
|
||||||
Memory::Memset(buffer.m_Address, 0, buffer.m_Size);
|
|
||||||
|
|
||||||
u32 ReturnValue = 0;
|
|
||||||
switch (CommandBuffer.Parameter)
|
|
||||||
{
|
{
|
||||||
case IOCTLV_SENDCMD:
|
case IOCTLV_SENDCMD:
|
||||||
DEBUG_LOG(WII_IPC_SD, "IOCTLV_SENDCMD 0x%08x",
|
DEBUG_LOG(WII_IPC_SD, "IOCTLV_SENDCMD 0x%08x", Memory::Read_U32(request.in_vectors[0].address));
|
||||||
Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address));
|
Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
|
||||||
ReturnValue = ExecuteCommand(
|
return_value =
|
||||||
CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size,
|
ExecuteCommand(request, request.in_vectors[0].address, request.in_vectors[0].size,
|
||||||
CommandBuffer.InBuffer[1].m_Address, CommandBuffer.InBuffer[1].m_Size,
|
request.in_vectors[1].address, request.in_vectors[1].size,
|
||||||
CommandBuffer.PayloadBuffer[0].m_Address, CommandBuffer.PayloadBuffer[0].m_Size);
|
request.io_vectors[0].address, request.io_vectors[0].size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtlV command 0x%08x", CommandBuffer.Parameter);
|
ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtlV command 0x%08x", request.request);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
request.SetReturnValue(return_value);
|
||||||
|
|
||||||
return GetDefaultReply();
|
return GetDefaultReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 _rwBuffer,
|
u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(const IOSRequest& request, u32 _BufferIn,
|
||||||
|
u32 _BufferInSize, u32 _rwBuffer,
|
||||||
u32 _rwBufferSize, u32 _BufferOut,
|
u32 _rwBufferSize, u32 _BufferOut,
|
||||||
u32 _BufferOutSize)
|
u32 _BufferOutSize)
|
||||||
{
|
{
|
||||||
|
@ -421,15 +381,24 @@ u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(u32 _BufferIn, u32 _BufferInS
|
||||||
|
|
||||||
case EVENT_REGISTER: // async
|
case EVENT_REGISTER: // async
|
||||||
INFO_LOG(WII_IPC_SD, "Register event %x", req.arg);
|
INFO_LOG(WII_IPC_SD, "Register event %x", req.arg);
|
||||||
m_event.type = (EventType)req.arg;
|
m_event = std::make_unique<Event>(static_cast<EventType>(req.arg), request);
|
||||||
ret = RET_EVENT_REGISTER;
|
ret = RET_EVENT_REGISTER;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EVENT_UNREGISTER: // synchronous
|
// Used to cancel an event that was already registered.
|
||||||
|
case EVENT_UNREGISTER:
|
||||||
|
{
|
||||||
INFO_LOG(WII_IPC_SD, "Unregister event %x", req.arg);
|
INFO_LOG(WII_IPC_SD, "Unregister event %x", req.arg);
|
||||||
m_event.type = (EventType)req.arg;
|
if (!m_event)
|
||||||
ret = RET_EVENT_UNREGISTER;
|
return IPC_EINVAL;
|
||||||
|
// release returns 0
|
||||||
|
// unknown sd int
|
||||||
|
// technically we do it out of order, oh well
|
||||||
|
m_event->request.SetReturnValue(EVENT_INVALID);
|
||||||
|
WII_IPC_HLE_Interface::EnqueueReply(m_event->request);
|
||||||
|
m_event.reset();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(WII_IPC_SD, "Unknown SD command 0x%08x", req.command);
|
ERROR_LOG(WII_IPC_SD, "Unknown SD command 0x%08x", req.command);
|
||||||
|
|
|
@ -23,11 +23,10 @@ public:
|
||||||
|
|
||||||
void DoState(PointerWrap& p) override;
|
void DoState(PointerWrap& p) override;
|
||||||
|
|
||||||
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override;
|
IOSReturnCode Open(const IOSOpenRequest& request) override;
|
||||||
IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override;
|
void Close() override;
|
||||||
|
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
|
||||||
IPCCommandResult IOCtl(u32 _CommandAddress) override;
|
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
|
||||||
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
|
|
||||||
|
|
||||||
void EventNotify();
|
void EventNotify();
|
||||||
|
|
||||||
|
@ -63,7 +62,6 @@ private:
|
||||||
RET_OK,
|
RET_OK,
|
||||||
RET_FAIL,
|
RET_FAIL,
|
||||||
RET_EVENT_REGISTER, // internal state only - not actually returned
|
RET_EVENT_REGISTER, // internal state only - not actually returned
|
||||||
RET_EVENT_UNREGISTER
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Status
|
// Status
|
||||||
|
@ -100,9 +98,8 @@ private:
|
||||||
|
|
||||||
enum EventType
|
enum EventType
|
||||||
{
|
{
|
||||||
EVENT_NONE = 0,
|
EVENT_INSERT = 1,
|
||||||
EVENT_INSERT,
|
EVENT_REMOVE = 2,
|
||||||
EVENT_REMOVE,
|
|
||||||
// from unregister, i think it is just meant to be invalid
|
// from unregister, i think it is just meant to be invalid
|
||||||
EVENT_INVALID = 0xc210000
|
EVENT_INVALID = 0xc210000
|
||||||
};
|
};
|
||||||
|
@ -110,9 +107,11 @@ private:
|
||||||
// TODO do we need more than one?
|
// TODO do we need more than one?
|
||||||
struct Event
|
struct Event
|
||||||
{
|
{
|
||||||
EventType type = EVENT_NONE;
|
Event(EventType type_, IOSRequest request_) : type(type_), request(request_) {}
|
||||||
u32 addr = 0;
|
EventType type;
|
||||||
} m_event;
|
IOSRequest request;
|
||||||
|
};
|
||||||
|
std::unique_ptr<Event> m_event;
|
||||||
|
|
||||||
u32 m_Status = CARD_NOT_EXIST;
|
u32 m_Status = CARD_NOT_EXIST;
|
||||||
u32 m_BlockLength = 0;
|
u32 m_BlockLength = 0;
|
||||||
|
@ -122,7 +121,7 @@ private:
|
||||||
|
|
||||||
File::IOFile m_Card;
|
File::IOFile m_Card;
|
||||||
|
|
||||||
u32 ExecuteCommand(u32 BufferIn, u32 BufferInSize, u32 BufferIn2, u32 BufferInSize2,
|
u32 ExecuteCommand(const IOSRequest& request, u32 BufferIn, u32 BufferInSize, u32 BufferIn2,
|
||||||
u32 _BufferOut, u32 BufferOutSize);
|
u32 BufferInSize2, u32 _BufferOut, u32 BufferOutSize);
|
||||||
void OpenInternal();
|
void OpenInternal();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue