Split /dev/di commands from DVDInterface

The various ioctls sometimes have different arguments than the DI command
registers, though they generally overlap.  There are also a bunch of ioctls
that don't even normally go into DVDInterface, just returning various data.
Some of the implemented ioctls are new to Dolphin.
This commit is contained in:
Pokechu22
2020-01-04 11:43:30 -08:00
parent a8ae5fa21a
commit ef2fc5a49b
6 changed files with 918 additions and 315 deletions
File diff suppressed because it is too large Load Diff
+36 -39
View File
@@ -24,38 +24,31 @@ class Mapping;
namespace DVDInterface
{
enum DICommand
enum class DICommand : u8
{
DVDLowInquiry = 0x12,
DVDLowReadDiskID = 0x70,
DVDLowRead = 0x71,
DVDLowWaitForCoverClose = 0x79,
DVDLowGetCoverReg = 0x7a, // DVDLowPrepareCoverRegister?
DVDLowNotifyReset = 0x7e,
DVDLowReadDvdPhysical = 0x80,
DVDLowReadDvdCopyright = 0x81,
DVDLowReadDvdDiscKey = 0x82,
DVDLowClearCoverInterrupt = 0x86,
DVDLowGetCoverStatus = 0x88,
DVDLowReset = 0x8a,
DVDLowOpenPartition = 0x8b,
DVDLowClosePartition = 0x8c,
DVDLowUnencryptedRead = 0x8d,
DVDLowEnableDvdVideo = 0x8e,
DVDLowReportKey = 0xa4,
DVDLowSeek = 0xab,
DVDLowReadDvd = 0xd0,
DVDLowReadDvdConfig = 0xd1,
DVDLowStopLaser = 0xd2,
DVDLowOffset = 0xd9,
DVDLowReadDiskBca = 0xda,
DVDLowRequestDiscStatus = 0xdb,
DVDLowRequestRetryNumber = 0xdc,
DVDLowSetMaximumRotation = 0xdd,
DVDLowSerMeasControl = 0xdf,
DVDLowRequestError = 0xe0,
DVDLowStopMotor = 0xe3,
DVDLowAudioBufferConfig = 0xe4
Inquiry = 0x12,
ReportKey = 0xa4,
Read = 0xa8,
Seek = 0xab,
ReadDVDMetadata = 0xad,
ReadDVD = 0xd0,
ReadDVDConfig = 0xd1,
StopLaser = 0xd2,
Offset = 0xd9,
ReadBCA = 0xda,
RequestDiscStatus = 0xdb,
RequestRetryNumber = 0xdc,
SetMaximumRotation = 0xdd,
SerMeasControl = 0xdf,
RequestError = 0xe0,
AudioStream = 0xe1,
RequestAudioStatus = 0xe2,
StopMotor = 0xe3,
AudioBufferConfig = 0xe4,
Debug = 0xfe,
DebugUnlock = 0xff,
Unknown55 = 0x55,
UnknownEE = 0xee,
};
// "low" error codes
@@ -86,12 +79,12 @@ constexpr u32 ERROR_MEDIUM = 0x062800; // Medium may have changed.
constexpr u32 ERROR_MEDIUM_REQ = 0x0b5a01; // Operator medium removal request.
constexpr u32 HIGH_ERROR_MASK = 0x00ffffff;
enum DIInterruptType : int
enum class DIInterruptType : int
{
INT_DEINT = 0,
INT_TCINT = 1,
INT_BRKINT = 2,
INT_CVRINT = 3,
DEINT = 0,
TCINT = 1,
BRKINT = 2,
CVRINT = 3,
};
enum class ReplyType : u32
@@ -99,7 +92,7 @@ enum class ReplyType : u32
NoReply,
Interrupt,
IOS,
DTK
DTK,
};
enum class EjectCause
@@ -132,8 +125,8 @@ bool UpdateRunningGameMetadata(std::optional<u64> title_id = {});
// Direct access to DI for IOS HLE (simpler to implement than how real IOS accesses DI,
// and lets us skip encrypting/decrypting in some cases)
void ChangePartition(const DiscIO::Partition& partition);
void ExecuteCommand(u32 command_0, u32 command_1, u32 command_2, u32 output_address,
u32 output_length, bool reply_to_ios);
void ExecuteCommand(ReplyType reply_type);
void PerformDecryptingRead(u32 position, u32 length, u32 output_address, ReplyType reply_type);
void SetLowError(u32 low_error);
void SetHighError(u32 high_error);
@@ -142,4 +135,8 @@ void SetHighError(u32 high_error);
void FinishExecutingCommand(ReplyType reply_type, DIInterruptType interrupt_type, s64 cycles_late,
const std::vector<u8>& data = std::vector<u8>());
// Used by IOS HLE
void SetInterruptEnabled(DIInterruptType interrupt, bool enabled);
void ClearInterrupt(DIInterruptType interrupt);
} // end of namespace DVDInterface
+2 -2
View File
@@ -354,8 +354,8 @@ static void FinishRead(u64 id, s64 cycles_late)
}
// Notify the emulated software that the command has been executed
DVDInterface::FinishExecutingCommand(request.reply_type, DVDInterface::INT_TCINT, cycles_late,
buffer);
DVDInterface::FinishExecutingCommand(request.reply_type, DVDInterface::DIInterruptType::TCINT,
cycles_late, buffer);
}
static void DVDThread()
File diff suppressed because it is too large Load Diff
+104 -3
View File
@@ -5,6 +5,7 @@
#pragma once
#include <deque>
#include <optional>
#include <string>
#include "Common/CommonTypes.h"
@@ -15,7 +16,16 @@ class PointerWrap;
namespace DVDInterface
{
enum DIInterruptType : int;
enum class DIInterruptType : int;
}
namespace CoreTiming
{
struct EventType;
}
namespace IOS::HLE
{
void Init();
}
namespace IOS::HLE::Device
@@ -25,16 +35,107 @@ class DI : public Device
public:
DI(Kernel& ios, const std::string& device_name);
static void InterruptFromDVDInterface(DVDInterface::DIInterruptType interrupt_type);
void DoState(PointerWrap& p) override;
IPCCommandResult Open(const OpenRequest& request) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
void FinishIOCtl(DVDInterface::DIInterruptType interrupt_type);
enum class DIIoctl : u32
{
DVDLowInquiry = 0x12,
DVDLowReadDiskID = 0x70,
DVDLowRead = 0x71,
DVDLowWaitForCoverClose = 0x79,
DVDLowGetCoverRegister = 0x7a, // DVDLowPrepareCoverRegister
DVDLowNotifyReset = 0x7e,
DVDLowSetSpinupFlag = 0x7f,
DVDLowReadDvdPhysical = 0x80,
DVDLowReadDvdCopyright = 0x81,
DVDLowReadDvdDiscKey = 0x82,
DVDLowGetLength = 0x83,
DVDLowGetImmBuf = 0x84, // Unconfirmed name
DVDLowUnmaskCoverInterrupt = 0x85,
DVDLowClearCoverInterrupt = 0x86,
// 0x87 is a dummied out command
DVDLowGetCoverStatus = 0x88,
DVDLowEnableCoverInterrupt = 0x89, // Unconfirmed name
DVDLowReset = 0x8a,
DVDLowOpenPartition = 0x8b, // ioctlv only
DVDLowClosePartition = 0x8c,
DVDLowUnencryptedRead = 0x8d,
DVDLowEnableDvdVideo = 0x8e,
DVDLowGetNoDiscOpenPartitionParams = 0x90, // ioctlv, dummied out
DVDLowNoDiscOpenPartition = 0x91, // ioctlv, dummied out
DVDLowGetNoDiscBufferSizes = 0x92, // ioctlv, dummied out
DVDLowOpenPartitionWithTmdAndTicket = 0x93, // ioctlv
DVDLowOpenPartitionWithTmdAndTicketView = 0x94, // ioctlv
DVDLowGetStatusRegister = 0x95, // DVDLowPrepareStatusRegsiter
DVDLowGetControlRegister = 0x96, // DVDLowPrepareControlRegister
DVDLowReportKey = 0xa4,
// 0xa8 is unusable externally
DVDLowSeek = 0xab,
DVDLowReadDvd = 0xd0,
DVDLowReadDvdConfig = 0xd1,
DVDLowStopLaser = 0xd2,
DVDLowOffset = 0xd9,
DVDLowReadDiskBca = 0xda,
DVDLowRequestDiscStatus = 0xdb,
DVDLowRequestRetryNumber = 0xdc,
DVDLowSetMaximumRotation = 0xdd,
DVDLowSerMeasControl = 0xdf,
DVDLowRequestError = 0xe0,
DVDLowAudioStream = 0xe1,
DVDLowRequestAudioStatus = 0xe2,
DVDLowStopMotor = 0xe3,
DVDLowAudioBufferConfig = 0xe4,
};
enum class DIResult : s32
{
Success = 1,
DriveError = 2,
CoverClosed = 4,
ReadTimedOut = 16,
SecurityError = 32,
VerifyError = 64,
BadArgument = 128,
};
private:
void StartIOCtl(const IOCtlRequest& request);
struct ExecutingCommandInfo
{
ExecutingCommandInfo() {}
ExecutingCommandInfo(u32 request_address)
: m_request_address(request_address), m_copy_diimmbuf(false)
{
}
u32 m_request_address;
bool m_copy_diimmbuf;
};
friend void ::IOS::HLE::Init();
void ProcessQueuedIOCtl();
std::optional<DIResult> StartIOCtl(const IOCtlRequest& request);
std::optional<DIResult> WriteIfFits(const IOCtlRequest& request, u32 value);
std::optional<DIResult> StartDMATransfer(u32 command_length, const IOCtlRequest& request);
std::optional<DIResult> StartImmediateTransfer(const IOCtlRequest& request,
bool write_to_buf = true);
void InitializeIfFirstTime();
void ResetDIRegisters();
static void FinishDICommandCallback(u64 userdata, s64 ticksbehind);
void FinishDICommand(DIResult result);
static CoreTiming::EventType* s_finish_executing_di_command;
std::optional<ExecutingCommandInfo> m_executing_command;
std::deque<u32> m_commands_to_execute;
bool m_has_initialized = false;
u32 m_last_length = 0;
};
} // namespace IOS::HLE::Device
+3
View File
@@ -782,6 +782,9 @@ void Init()
device->EventNotify();
});
Device::DI::s_finish_executing_di_command =
CoreTiming::RegisterEvent("FinishDICommand", Device::DI::FinishDICommandCallback);
// Start with IOS80 to simulate part of the Wii boot process.
s_ios = std::make_unique<EmulationKernel>(Titles::SYSTEM_MENU_IOS);
// On a Wii, boot2 launches the system menu IOS, which then launches the system menu