Skip to content

Commit 4f30aaf

Browse files
authored
Merge pull request #13152 from Naim2000/sdlock
SDIO: report write lock status
2 parents 2719a56 + 1a71f0f commit 4f30aaf

File tree

2 files changed

+76
-59
lines changed

2 files changed

+76
-59
lines changed

Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp

Lines changed: 73 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -237,18 +237,23 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
237237
case SEND_CSD:
238238
{
239239
const std::array<u32, 4> csd = m_protocol == SDProtocol::V1 ? GetCSDv1() : GetCSDv2();
240-
memory.CopyToEmuSwapped(buffer_out, csd.data(), csd.size() * sizeof(u32));
240+
memory.Write_U32(csd[0], buffer_out + 12);
241+
memory.Write_U32(csd[1], buffer_out + 8);
242+
memory.Write_U32(csd[2], buffer_out + 4);
243+
memory.Write_U32(csd[3], buffer_out + 0);
241244
}
242245
break;
243246

244247
case ALL_SEND_CID:
245248
case SEND_CID:
249+
{
246250
INFO_LOG_FMT(IOS_SD, "(ALL_)SEND_CID");
247-
memory.Write_U32(0x80114d1c, buffer_out);
248-
memory.Write_U32(0x80080000, buffer_out + 4);
249-
memory.Write_U32(0x8007b520, buffer_out + 8);
250-
memory.Write_U32(0x80080000, buffer_out + 12);
251-
break;
251+
memory.Write_U32(0x00D0444F, buffer_out + 12);
252+
memory.Write_U32(0x4C504849, buffer_out + 8);
253+
memory.Write_U32(0x4E430403, buffer_out + 4);
254+
memory.Write_U32(0xAC68006B, buffer_out + 0);
255+
}
256+
break;
252257

253258
case SET_BLOCKLEN:
254259
m_block_length = req.arg;
@@ -279,24 +284,21 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
279284
INFO_LOG_FMT(IOS_SD, "{}Read {} Block(s) from {:#010x} bsize {} into {:#010x}!",
280285
req.isDMA ? "DMA " : "", req.blocks, req.arg, req.bsize, req.addr);
281286

282-
if (m_card)
283-
{
284-
const u32 size = req.bsize * req.blocks;
285-
const u64 address = GetAddressFromRequest(req.arg);
287+
const u32 size = req.bsize * req.blocks;
288+
const u64 address = GetAddressFromRequest(req.arg);
286289

287-
if (!m_card.Seek(address, File::SeekOrigin::Begin))
288-
ERROR_LOG_FMT(IOS_SD, "Seek failed");
290+
if (!m_card.Seek(address, File::SeekOrigin::Begin))
291+
ERROR_LOG_FMT(IOS_SD, "Seek failed");
289292

290-
if (m_card.ReadBytes(memory.GetPointerForRange(req.addr, size), size))
291-
{
292-
DEBUG_LOG_FMT(IOS_SD, "Outbuffer size {} got {}", rw_buffer_size, size);
293-
}
294-
else
295-
{
296-
ERROR_LOG_FMT(IOS_SD, "Read Failed - error: {}, eof: {}", std::ferror(m_card.GetHandle()),
297-
std::feof(m_card.GetHandle()));
298-
ret = RET_FAIL;
299-
}
293+
if (m_card.ReadBytes(memory.GetPointerForRange(req.addr, size), size))
294+
{
295+
DEBUG_LOG_FMT(IOS_SD, "Outbuffer size {} got {}", rw_buffer_size, size);
296+
}
297+
else
298+
{
299+
ERROR_LOG_FMT(IOS_SD, "Read Failed - error: {}, eof: {}", std::ferror(m_card.GetHandle()),
300+
std::feof(m_card.GetHandle()));
301+
ret = RET_FAIL;
300302
}
301303
}
302304
memory.Write_U32(0x900, buffer_out);
@@ -309,7 +311,12 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
309311
INFO_LOG_FMT(IOS_SD, "{}Write {} Block(s) from {:#010x} bsize {} to offset {:#010x}!",
310312
req.isDMA ? "DMA " : "", req.blocks, req.addr, req.bsize, req.arg);
311313

312-
if (m_card && Config::Get(Config::MAIN_ALLOW_SD_WRITES))
314+
if (!Config::Get(Config::MAIN_ALLOW_SD_WRITES))
315+
{
316+
ERROR_LOG_FMT(IOS_SD, "Write attempted while locked.");
317+
ret = RET_LOCKED;
318+
}
319+
else
313320
{
314321
const u32 size = req.bsize * req.blocks;
315322
const u64 address = GetAddressFromRequest(req.arg);
@@ -465,34 +472,35 @@ std::optional<IPCReply> SDIOSlot0Device::SendCommand(const IOCtlRequest& request
465472
IPCReply SDIOSlot0Device::GetStatus(const IOCtlRequest& request)
466473
{
467474
// Since IOS does the SD initialization itself, we just say we're always initialized.
468-
if (m_card)
475+
if (m_card.GetSize() <= SDSC_MAX_SIZE)
469476
{
470-
if (m_card.GetSize() <= SDSC_MAX_SIZE)
471-
{
472-
// No further initialization required.
473-
m_status |= CARD_INITIALIZED;
474-
}
475-
else
477+
// No further initialization required.
478+
m_status |= CARD_INITIALIZED;
479+
}
480+
else
481+
{
482+
// Some IOS versions support SDHC.
483+
// Others will work if they are manually initialized (SEND_IF_COND)
484+
if (m_sdhc_supported)
476485
{
477-
// Some IOS versions support SDHC.
478-
// Others will work if they are manually initialized (SEND_IF_COND)
479-
if (m_sdhc_supported)
480-
{
481-
// All of the initialization is done internally by IOS, so we get to skip some steps.
482-
InitSDHC();
483-
}
484-
m_status |= CARD_SDHC;
486+
// All of the initialization is done internally by IOS, so we get to skip some steps.
487+
InitSDHC();
485488
}
489+
m_status |= CARD_SDHC;
486490
}
487491

488492
// Evaluate whether a card is currently inserted (config value).
489493
// Make sure we don't modify m_status so we don't lose track of whether the card is SDHC.
490494
const bool sd_card_inserted = Config::Get(Config::MAIN_WII_SD_CARD);
491-
const u32 status = sd_card_inserted ? (m_status | CARD_INSERTED) : CARD_NOT_EXIST;
495+
const bool sd_card_locked = !Config::Get(Config::MAIN_ALLOW_SD_WRITES);
496+
const u32 status = sd_card_inserted ?
497+
(m_status | CARD_INSERTED | (sd_card_locked ? CARD_LOCKED : 0)) :
498+
CARD_NOT_EXIST;
492499

493-
INFO_LOG_FMT(IOS_SD, "IOCTL_GETSTATUS. Replying that {} card is {}{}",
500+
INFO_LOG_FMT(IOS_SD, "IOCTL_GETSTATUS. Replying that {} card is {}{}{}",
494501
(status & CARD_SDHC) ? "SDHC" : "SD",
495502
(status & CARD_INSERTED) ? "inserted" : "not present",
503+
(status & CARD_LOCKED) ? " and locked" : "",
496504
(status & CARD_INITIALIZED) ? " and initialized" : "");
497505

498506
auto& system = GetSystem();
@@ -543,9 +551,8 @@ std::array<u32, 4> SDIOSlot0Device::GetCSDv1() const
543551
{
544552
u64 size = m_card.GetSize();
545553

546-
// 2048 bytes/sector
547-
// We could make this dynamic to support a wider range of file sizes
548-
constexpr u32 read_bl_len = 11;
554+
// 512 bytes/sector. A 2GB card should only ever have to bump this up to 10
555+
u32 read_bl_len = 9;
549556

550557
// size = (c_size + 1) * (1 << (2 + c_size_mult + read_bl_len))
551558
u32 c_size_mult = 0;
@@ -554,7 +561,7 @@ std::array<u32, 4> SDIOSlot0Device::GetCSDv1() const
554561
{
555562
invalid_size |= size & 1;
556563
size >>= 1;
557-
if (++c_size_mult >= 8 + 2 + read_bl_len)
564+
if (++c_size_mult > 7 + 2 + read_bl_len && ++read_bl_len > 15)
558565
{
559566
ERROR_LOG_FMT(IOS_SD, "SD Card is too big!");
560567
// Set max values
@@ -567,9 +574,14 @@ std::array<u32, 4> SDIOSlot0Device::GetCSDv1() const
567574
const u32 c_size(size);
568575

569576
if (invalid_size)
577+
{
570578
WARN_LOG_FMT(IOS_SD, "SD Card size is invalid");
579+
}
571580
else
572-
INFO_LOG_FMT(IOS_SD, "SD C_SIZE = {}, C_SIZE_MULT = {}", c_size, c_size_mult);
581+
{
582+
INFO_LOG_FMT(IOS_SD, "SD C_SIZE = {}, C_SIZE_MULT = {}, READ_BL_LEN = {}", c_size, c_size_mult,
583+
read_bl_len);
584+
}
573585

574586
// 0b00 CSD_STRUCTURE (SDv1)
575587
// 0b000000 reserved
@@ -578,7 +590,7 @@ std::array<u32, 4> SDIOSlot0Device::GetCSDv1() const
578590
// 0b00110010 TRAN_SPEED (2.5 * 10 Mbit/s, max operating frequency)
579591

580592
// 0b010110110101 CCC
581-
// 0b1111 READ_BL_LEN (2048 bytes)
593+
// 0b???? READ_BL_LEN
582594
// 0b1 READ_BL_PARTIAL
583595
// 0b0 WRITE_BL_MISALIGN
584596
// 0b0 READ_BLK_MISALIGN
@@ -599,7 +611,7 @@ std::array<u32, 4> SDIOSlot0Device::GetCSDv1() const
599611
// 0b0 WP_GRP_ENABLE (no write protection)
600612
// 0b00 reserved
601613
// 0b001 R2W_FACTOR (write half as fast as read)
602-
// 0b1111 WRITE_BL_LEN (= READ_BL_LEN)
614+
// 0b???? WRITE_BL_LEN (= READ_BL_LEN)
603615
// 0b0 WRITE_BL_PARTIAL (no partial block writes)
604616
// 0b00000 reserved
605617
// 0b0 FILE_FORMAT_GRP (default)
@@ -612,14 +624,16 @@ std::array<u32, 4> SDIOSlot0Device::GetCSDv1() const
612624
// 0b1 reserved
613625

614626
// TODO: CRC7 (but so far it looks like nobody is actually verifying this)
615-
constexpr u32 crc = 0;
627+
// constexpr u32 crc = 0; // The CRC doesn't seem to be sent any at all.
628+
// Additionally, the entire response seems to be shifted to the right by 8 bits. Or the entire CSD
629+
// was sent in reverse and IOS is only flipping the endianness of the four words.... It's weird.
616630

617631
// Form the csd using the description above
618632
return {{
619-
0x007f003,
620-
0x5b5f8000 | (c_size >> 2),
621-
0x3ffc7f80 | (c_size << 30) | (c_size_mult << 15),
622-
0x07c04001 | (crc << 1),
633+
0x000007f0,
634+
0x035b5080 | (read_bl_len << 8) | (c_size >> 10),
635+
0x003ffc7f | (c_size << 22) | (c_size_mult << 7),
636+
0x80040040 | (read_bl_len << 18),
623637
}};
624638
}
625639

@@ -668,15 +682,16 @@ std::array<u32, 4> SDIOSlot0Device::GetCSDv2() const
668682
// 0b0000000 CRC
669683
// 0b1 reserved
670684

671-
// TODO: CRC7 (but so far it looks like nobody is actually verifying this)
672-
constexpr u32 crc = 0;
685+
// TODO: CRC7 (but so far it looks like nobody is actually verifying this) // See GetCSDv1 notes
686+
// on this
687+
// constexpr u32 crc = 0;
673688

674689
// Form the csd using the description above
675690
return {{
676-
0x400e005a,
677-
0x5f590000 | (c_size >> 16),
678-
0x00007f80 | (c_size << 16),
679-
0x0a400001 | (crc << 1),
691+
0x00400e00,
692+
0x5a5f5900,
693+
0x0000007f | (c_size << 8),
694+
0x800a4000,
680695
}};
681696
}
682697

Source/Core/Core/IOS/SDIO/SDIOSlot0.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,16 @@ class SDIOSlot0Device : public EmulationDevice
6363
{
6464
RET_OK,
6565
RET_FAIL,
66+
RET_LOCKED = -10,
6667
RET_EVENT_REGISTER, // internal state only - not actually returned
6768
};
6869

6970
// Status
7071
enum
7172
{
7273
CARD_NOT_EXIST = 0,
73-
CARD_INSERTED = 1,
74+
CARD_INSERTED = 0x1,
75+
CARD_LOCKED = 0x4,
7476
CARD_INITIALIZED = 0x10000,
7577
CARD_SDHC = 0x100000,
7678
};

0 commit comments

Comments
 (0)