improve ios hle error handling.

remove stubbed devices. they now fall back to the base device class, which reports the device as not available.
fixes issue 3137.
start ios fd counting at 0 instead of 0x13370000. I know it's sad, but it fixes homebrew booting and such.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6164 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Shawn Hoffman 2010-09-02 04:17:23 +00:00
parent baf82a0849
commit efd9bae449
4 changed files with 99 additions and 98 deletions

View File

@ -41,7 +41,6 @@ They will also generate a true or false return for UpdateInterrupts() in WII_IPC
#include "CommonPaths.h"
#include "WII_IPC_HLE.h"
#include "WII_IPC_HLE_Device.h"
#include "WII_IPC_HLE_Device_Error.h"
#include "WII_IPC_HLE_Device_DI.h"
#include "WII_IPC_HLE_Device_FileIO.h"
#include "WII_IPC_HLE_Device_stm.h"
@ -76,7 +75,6 @@ typedef std::queue<u32> ipc_msg_queue;
static ipc_msg_queue request_queue; // ppc -> arm
static ipc_msg_queue reply_queue; // arm -> ppc
// General IPC functions
void Init()
{
_dbg_assert_msg_(WII_IPC_HLE, g_DeviceMap.empty(), "DeviceMap isnt empty on init");
@ -93,11 +91,9 @@ void Init()
g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_kd_time(i, std::string("/dev/net/kd/time")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_ncd_manage(i, std::string("/dev/net/ncd/manage")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_ip_top(i, std::string("/dev/net/ip/top")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_usb_oh0(i, std::string("/dev/usb/oh0")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_usb_kbd(i, std::string("/dev/usb/kbd")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_usb_hid(i, std::string("/dev/usb/hid")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_sdio_slot0(i, std::string("/dev/sdio/slot0")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_Error(i, std::string("_Unknown_Device_")); i++;
g_DeviceMap[i] = new IWII_IPC_HLE_Device(i, std::string("_Unimplemented_Device_"));
g_LastDeviceID = IPC_FIRST_FILEIO_ID;
}
@ -151,7 +147,7 @@ u32 GetDeviceIDByName(const std::string& _rDeviceName)
++itr;
}
return 0;
return -1;
}
IWII_IPC_HLE_Device* AccessDeviceByID(u32 _ID)
@ -284,22 +280,29 @@ void ExecuteCommand(u32 _Address)
DeviceID = GetDeviceIDByName(DeviceName);
// check if a device with this name has been created already
if (DeviceID == 0)
if (DeviceID == -1)
{
if (DeviceName.find("/dev/") != std::string::npos)
{
ERROR_LOG(WII_IPC_FILEIO, "Unknown device: %s", DeviceName.c_str());
WARN_LOG(WII_IPC_HLE, "Unimplemented device: %s", DeviceName.c_str());
pDevice = AccessDeviceByID(GetDeviceIDByName(std::string("_Unimplemented_Device_")));
CmdSuccess = pDevice->Open(_Address, Mode);
}
u32 CurrentDeviceID = g_LastDeviceID;
pDevice = CreateFileIO(CurrentDeviceID, DeviceName);
g_DeviceMap[CurrentDeviceID] = pDevice;
g_FileNameMap[CurrentDeviceID] = DeviceName;
g_LastDeviceID++;
else
{
// create new file handle
u32 CurrentDeviceID = g_LastDeviceID;
pDevice = CreateFileIO(CurrentDeviceID, DeviceName);
g_DeviceMap[CurrentDeviceID] = pDevice;
g_FileNameMap[CurrentDeviceID] = DeviceName;
g_LastDeviceID++;
CmdSuccess = pDevice->Open(_Address, Mode);
CmdSuccess = pDevice->Open(_Address, Mode);
INFO_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, ID=%08x, Mode=%i)",
pDevice->GetDeviceName().c_str(), CurrentDeviceID, Mode);
INFO_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, ID=%08x, Mode=%i)",
pDevice->GetDeviceName().c_str(), CurrentDeviceID, Mode);
}
}
else
{
@ -356,31 +359,50 @@ void ExecuteCommand(u32 _Address)
case COMMAND_CLOSE_DEVICE:
if (pDevice)
{
pDevice->Close(_Address);
CmdSuccess = pDevice->Close(_Address);
// Don't delete hardware
if (!pDevice->IsHardware())
DeleteDeviceByID(DeviceID);
CmdSuccess = true;
}
else
{
Memory::Write_U32(FS_EINVAL, _Address + 4);
CmdSuccess = true;
}
break;
case COMMAND_READ:
if (pDevice != NULL)
if (pDevice)
CmdSuccess = pDevice->Read(_Address);
else
{
Memory::Write_U32(FS_EINVAL, _Address + 4);
CmdSuccess = true;
}
break;
case COMMAND_WRITE:
if (pDevice != NULL)
if (pDevice)
CmdSuccess = pDevice->Write(_Address);
else
{
Memory::Write_U32(FS_EINVAL, _Address + 4);
CmdSuccess = true;
}
break;
case COMMAND_SEEK:
if (pDevice != NULL)
if (pDevice)
CmdSuccess = pDevice->Seek(_Address);
else
{
Memory::Write_U32(FS_EINVAL, _Address + 4);
CmdSuccess = true;
}
break;
case COMMAND_IOCTL:
if (pDevice != NULL)
if (pDevice)
CmdSuccess = pDevice->IOCtl(_Address);
break;
@ -395,7 +417,7 @@ void ExecuteCommand(u32 _Address)
}
// It seems that the original hardware overwrites the command after it has been
// executed. We write 8 which is not any valid command, and what IOS does
// executed. We write 8 which is not any valid command, and what IOS does
Memory::Write_U32(8, _Address);
// IOS seems to write back the command that was responded to
Memory::Write_U32(Command, _Address + 8);
@ -407,7 +429,14 @@ void ExecuteCommand(u32 _Address)
}
else
{
//DEBUG_LOG(WII_IPC_HLE, "<<-- Failed or Not Ready to Reply to IPC Request @ 0x%08x ", _Address);
if (pDevice)
{
INFO_LOG(WII_IPC_HLE, "<<-- Reply Failed to %s IPC Request %i @ 0x%08x ", pDevice->GetDeviceName().c_str(), Command, _Address);
}
else
{
INFO_LOG(WII_IPC_HLE, "<<-- Reply Failed to Unknown (%08x) IPC Request %i @ 0x%08x ", DeviceID, Command, _Address);
}
}
}

View File

@ -25,8 +25,8 @@ class IWII_IPC_HLE_Device;
namespace WII_IPC_HLE_Interface
{
#define IPC_FIRST_HARDWARE_ID 0x13370000 // first IPC device ID
#define IPC_FIRST_FILEIO_ID 0x13380000 // first IPC file ID
#define IPC_FIRST_HARDWARE_ID 0 // first IPC device ID
#define IPC_FIRST_FILEIO_ID 33 // first IPC file ID
// Init
void Init();

View File

@ -23,6 +23,31 @@
class PointerWrap;
#define FS_SUCCESS (u32)0 // Success
#define FS_EACCES (u32)-1 // Permission denied
#define FS_EEXIST (u32)-2 // File exists
#define FS_EINVAL (u32)-4 // Invalid argument Invalid FD
#define FS_ENOENT (u32)-6 // File not found
#define FS_EBUSY (u32)-8 // Resource busy
#define FS_EIO (u32)-12 // returned on ECC error
#define FS_ENOMEM (u32)-22 // Alloc failed during request
#define FS_EFATAL (u32)-101 // Fatal error
#define FS_EACCESS (u32)-102 // Permission denied
#define FS_ECORRUPT (u32)-103 // returned for "corrupted" NAND
#define FS_EEXIST2 (u32)-105 // File exists
#define FS_ENOENT2 (u32)-106 // File not found
#define FS_ENFILE (u32)-107 // Too many fds open
#define FS_EFBIG (u32)-108 // max block count reached?
#define FS_ENFILE2 (u32)-109 // Too many fds open
#define FS_ENAMELEN (u32)-110 // pathname is too long
#define FS_EFDOPEN (u32)-111 // FD is already open
#define FS_EIO2 (u32)-114 // returned on ECC error
#define FS_ENOTEMPTY (u32)-115 // Directory not empty
#define FS_EDIRDEPTH (u32)-116 // max directory depth exceeded
#define FS_EBUSY2 (u32)-118 // Resource busy
//#define FS_EFATAL (u32)-119 // fatal error not used by IOS as fatal ERROR
class IWII_IPC_HLE_Device
{
public:
@ -42,19 +67,21 @@ public:
u32 GetDeviceID() const { return m_DeviceID; }
virtual bool Open(u32 _CommandAddress, u32 _Mode) {
(void)_CommandAddress; (void)_Mode;
_dbg_assert_msg_(WII_IPC_HLE, 0, "%s does not support Open()", m_Name.c_str());
(void)_Mode;
WARN_LOG(WII_IPC_HLE, "%s does not support Open()", m_Name.c_str());
Memory::Write_U32(FS_ENOENT, _CommandAddress + 4);
m_Active = true;
return true;
}
virtual bool Close(u32 _CommandAddress, bool _bForce = false) {
(void)_CommandAddress; (void)_bForce;
_dbg_assert_msg_(WII_IPC_HLE, 0, "%s does not support Close()", m_Name.c_str());
WARN_LOG(WII_IPC_HLE, "%s does not support Close()", m_Name.c_str());
if (!_bForce)
Memory::Write_U32(FS_EINVAL, _CommandAddress + 4);
m_Active = false;
return true;
}
#define UNIMPLEMENTED_CMD(cmd) _dbg_assert_msg_(WII_IPC_HLE, 0, "%s does not support "#cmd"()", m_Name.c_str()); return true;
#define UNIMPLEMENTED_CMD(cmd) WARN_LOG(WII_IPC_HLE, "%s does not support "#cmd"()", m_Name.c_str()); return true;
virtual bool Seek (u32) { UNIMPLEMENTED_CMD(Seek) }
virtual bool Read (u32) { UNIMPLEMENTED_CMD(Read) }
virtual bool Write (u32) { UNIMPLEMENTED_CMD(Write) }
@ -80,46 +107,43 @@ protected:
// A struct for IOS ioctlv calls
struct SIOCtlVBuffer
{
SIOCtlVBuffer(u32 _Address)
: m_Address(_Address)
SIOCtlVBuffer(u32 _Address) : m_Address(_Address)
{
// These are the Ioctlv parameters in the IOS communication. The BufferVector
// is a memory address offset at where the in and out buffer addresses are
// stored.
Parameter = Memory::Read_U32(m_Address + 0x0C); // command 3, arg0
NumberInBuffer = Memory::Read_U32(m_Address + 0x10); // 4, arg1
NumberPayloadBuffer = Memory::Read_U32(m_Address + 0x14); // 5, arg2
BufferVector = Memory::Read_U32(m_Address + 0x18); // 6, arg3
Parameter = Memory::Read_U32(m_Address + 0x0C); // command 3, arg0
NumberInBuffer = Memory::Read_U32(m_Address + 0x10); // 4, arg1
NumberPayloadBuffer = Memory::Read_U32(m_Address + 0x14); // 5, arg2
BufferVector = Memory::Read_U32(m_Address + 0x18); // 6, arg3
// The start of the out buffer
u32 BufferVectorOffset = BufferVector;
//if(Parameter = 0x1d) PanicAlert("%i: %i", Parameter, NumberInBuffer);
// Write the address and size for all in messages
for (u32 i = 0; i < NumberInBuffer; i++)
{
SBuffer Buffer;
Buffer.m_Address = Memory::Read_U32(BufferVectorOffset);
Buffer.m_Address = Memory::Read_U32(BufferVectorOffset);
BufferVectorOffset += 4;
Buffer.m_Size = Memory::Read_U32(BufferVectorOffset);
Buffer.m_Size = Memory::Read_U32(BufferVectorOffset);
BufferVectorOffset += 4;
InBuffer.push_back(Buffer);
DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer in%i: 0x%08x, 0x%x",
i, Buffer.m_Address, Buffer.m_Size);
InBuffer.push_back(Buffer);
}
// Write the address and size for all out or in-out messages
for (u32 i = 0; i < NumberPayloadBuffer; i++)
{
SBuffer Buffer;
Buffer.m_Address = Memory::Read_U32(BufferVectorOffset);
Buffer.m_Address = Memory::Read_U32(BufferVectorOffset);
BufferVectorOffset += 4;
Buffer.m_Size = Memory::Read_U32(BufferVectorOffset);
Buffer.m_Size = Memory::Read_U32(BufferVectorOffset);
BufferVectorOffset += 4;
PayloadBuffer.push_back(Buffer);
DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer io%i: 0x%08x, 0x%x",
i, Buffer.m_Address, Buffer.m_Size);
PayloadBuffer.push_back(Buffer);
}
}

View File

@ -1,52 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _WII_IPC_HLE_DEVICE_ERROR_H_
#define _WII_IPC_HLE_DEVICE_ERROR_H_
#include "WII_IPC_HLE_Device.h"
class CWII_IPC_HLE_Device_Error : public IWII_IPC_HLE_Device
{
public:
CWII_IPC_HLE_Device_Error(u32 _DeviceID, const std::string& _rDeviceName ) :
IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
{}
virtual ~CWII_IPC_HLE_Device_Error()
{}
virtual bool Open(u32 _CommandAddress, u32 _Mode)
{
//PanicAlert("CWII_IPC_HLE_Device_Error");
Memory::Write_U32(GetDeviceID(), _CommandAddress + 4);
m_Active = true;
return true;
}
virtual bool Close(u32 _CommandAddress, bool _bForce)
{
if (!_bForce)
Memory::Write_U32(0, _CommandAddress + 4);
m_Active = false;
return true;
}
};
#endif