summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author arbee <rb6502@users.noreply.github.com>2021-09-18 14:30:03 -0400
committer arbee <rb6502@users.noreply.github.com>2021-09-18 14:30:03 -0400
commita06f194642bb13d70401497cae27c07b00b7c867 (patch)
treef3fde9bfbf34b0229f6291d807e4c07ab1b93738
parent8ffadea809767a0167b30052f0ab7165f6b22ace (diff)
spi_sdcard: add a child device which supports the SDV2 (non-HC) standard. [R. Belmont]
-rw-r--r--src/devices/machine/spi_sdcard.cpp40
-rw-r--r--src/devices/machine/spi_sdcard.h25
2 files changed, 55 insertions, 10 deletions
diff --git a/src/devices/machine/spi_sdcard.cpp b/src/devices/machine/spi_sdcard.cpp
index eef54c96352..42a255b3255 100644
--- a/src/devices/machine/spi_sdcard.cpp
+++ b/src/devices/machine/spi_sdcard.cpp
@@ -4,9 +4,10 @@
SD Card emulation, SPI interface.
Emulation by R. Belmont
- This emulates an SDHC card, which means the block size is fixed at 512 bytes and makes things simpler.
- Adapting the code to also handle SD version 2 non-HC cards would be relatively straightforward as well;
- the block size defaults to 1 byte in that case but can be overridden with CMD16.
+ This emulates either an SDHC (SPI_SDCARD) or an SDV2 card (SPI_SDCARDV2). SDHC has a fixed
+ 512 byte block size and the arguments to the read/write commands are block numbers. SDV2
+ has a variable block size defaulting to 512 and the arguments to the read/write commands
+ are byte offsets.
The block size set with CMD16 must match the underlying CHD block size if it's not 512.
@@ -38,7 +39,8 @@
static constexpr u8 DATA_RESPONSE_OK = 0x05;
static constexpr u8 DATA_RESPONSE_IO_ERROR = 0x0d;
-DEFINE_DEVICE_TYPE(SPI_SDCARD, spi_sdcard_device, "spi_sdcard", "SD Card (SPI Interface)")
+DEFINE_DEVICE_TYPE(SPI_SDCARD, spi_sdcard_sdhc_device, "spi_sdhccard", "SDHC Card (SPI Interface)")
+DEFINE_DEVICE_TYPE(SPI_SDCARDV2, spi_sdcard_sdv2_device, "spi_sdv2card", "SDV2 Card (SPI Interface)")
spi_sdcard_device::spi_sdcard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, type, tag, owner, clock),
@@ -50,9 +52,16 @@ spi_sdcard_device::spi_sdcard_device(const machine_config &mconfig, device_type
{
}
-spi_sdcard_device::spi_sdcard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+spi_sdcard_sdv2_device::spi_sdcard_sdv2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ spi_sdcard_device(mconfig, SPI_SDCARDV2, tag, owner, clock)
+{
+ m_type = SD_TYPE_V2;
+}
+
+spi_sdcard_sdhc_device::spi_sdcard_sdhc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
spi_sdcard_device(mconfig, SPI_SDCARD, tag, owner, clock)
{
+ m_type = SD_TYPE_HC;
}
void spi_sdcard_device::device_start()
@@ -68,6 +77,8 @@ void spi_sdcard_device::device_start()
save_item(NAME(m_in_bit));
save_item(NAME(m_cur_bit));
save_item(NAME(m_write_ptr));
+ save_item(NAME(m_blksize));
+ save_item(NAME(m_type));
save_item(NAME(m_cmd));
save_item(NAME(m_data));
save_item(NAME(m_bACMD));
@@ -140,6 +151,11 @@ void spi_sdcard_device::spi_clock_w(int state)
if (m_write_ptr == (m_blksize + 2))
{
u32 blk = (m_cmd[1] << 24) | (m_cmd[2] << 16) | (m_cmd[3] << 8) | m_cmd[4];
+ if (m_type == SD_TYPE_V2)
+ {
+ blk /= m_blksize;
+ }
+
LOGMASKED(LOG_GENERAL, "writing LBA %x, data %02x %02x %02x %02x\n", blk, m_data[0], m_data[1], m_data[2], m_data[3]);
if (hard_disk_write(m_harddisk, blk, &m_data[0]))
{
@@ -211,7 +227,6 @@ void spi_sdcard_device::do_command()
case 16: // CMD16 - SET_BLOCKLEN
m_blksize = (m_cmd[3] << 8) | m_cmd[4];
- printf("SDCARD: set block size to %d\n", m_blksize);
if (hard_disk_set_block_size(m_harddisk, m_blksize))
{
m_data[0] = 0;
@@ -234,6 +249,10 @@ void spi_sdcard_device::do_command()
// byte of space between R1 and the data packet.
m_data[2] = 0xfe; // data token
u32 blk = (m_cmd[1] << 24) | (m_cmd[2] << 16) | (m_cmd[3] << 8) | m_cmd[4];
+ if (m_type == SD_TYPE_V2)
+ {
+ blk /= m_blksize;
+ }
LOGMASKED(LOG_GENERAL, "reading LBA %x\n", blk);
hard_disk_read(m_harddisk, blk, &m_data[3]);
send_data(3 + m_blksize + 2);
@@ -270,7 +289,14 @@ void spi_sdcard_device::do_command()
case 58: // CMD58 - READ_OCR
m_data[0] = 0;
- m_data[1] = 0x40; // indicate SDHC support
+ if (m_type == SD_TYPE_HC)
+ {
+ m_data[1] = 0x40; // indicate SDHC support
+ }
+ else
+ {
+ m_data[1] = 0;
+ }
m_data[2] = 0;
m_data[3] = 0;
m_data[4] = 0;
diff --git a/src/devices/machine/spi_sdcard.h b/src/devices/machine/spi_sdcard.h
index 070af7ff755..23a292664d2 100644
--- a/src/devices/machine/spi_sdcard.h
+++ b/src/devices/machine/spi_sdcard.h
@@ -10,8 +10,6 @@
class spi_sdcard_device : public device_t
{
public:
- spi_sdcard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
// SPI 4-wire interface
auto spi_miso_callback() { return write_miso.bind(); }
void spi_clock_w(int state);
@@ -23,6 +21,12 @@ public:
devcb_write_line write_miso;
protected:
+ enum
+ {
+ SD_TYPE_V2 = 0,
+ SD_TYPE_HC
+ };
+
spi_sdcard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
virtual void device_start() override;
@@ -31,6 +35,8 @@ protected:
required_device<harddisk_image_device> m_image;
+ int m_type;
+
private:
enum
{
@@ -50,6 +56,19 @@ private:
bool m_bACMD;
};
-DECLARE_DEVICE_TYPE(SPI_SDCARD, spi_sdcard_device)
+class spi_sdcard_sdhc_device : public spi_sdcard_device
+{
+public:
+ spi_sdcard_sdhc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+class spi_sdcard_sdv2_device : public spi_sdcard_device
+{
+public:
+ spi_sdcard_sdv2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+DECLARE_DEVICE_TYPE(SPI_SDCARD, spi_sdcard_sdhc_device)
+DECLARE_DEVICE_TYPE(SPI_SDCARDV2, spi_sdcard_sdv2_device)
#endif // MAME_MACHINE_SPI_SDCARD_H