From: kosmirror <kos...@us...> - 2025-05-16 23:52:16
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 9c5ee7e30560a4d03fa82547e4b365ee0db73e2a (commit) via acaf32f520a78901ebe8b6f16f65fb0a9820b54d (commit) via 582d1b668ee68d60ec816cefecd578c9fbd28bc2 (commit) via c615452e133aed38bdb7768a0fc5605a87b2c07d (commit) from ea4b4439718347a99c4e11bd2adb76cd11904bfd (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 9c5ee7e30560a4d03fa82547e4b365ee0db73e2a Author: DC-SWAT <sw...@21...> Date: Tue May 13 11:42:03 2025 +0700 sd: Added creation of a block device for the entire SD card. Also use DMA for writing if possible. commit acaf32f520a78901ebe8b6f16f65fb0a9820b54d Author: DC-SWAT <sw...@21...> Date: Sun May 11 01:57:12 2025 +0700 sd: Added exports for both Dreamcast and NAOMI. Also fix read data with size that not multiple by 32 and warning in SCI. commit 582d1b668ee68d60ec816cefecd578c9fbd28bc2 Author: DC-SWAT <sw...@21...> Date: Thu May 8 23:01:20 2025 +0700 sd: Enhance speed test functionality for both SD card interfaces. commit c615452e133aed38bdb7768a0fc5605a87b2c07d Author: DC-SWAT <sw...@21...> Date: Thu May 8 23:01:13 2025 +0700 sd: Refactor SD card interface to support SCI and SCIF. Added initialization parameters for CRC checking and interface selection. ----------------------------------------------------------------------- Summary of changes: .../filesystem/sd/speedtest/sd-speedtest.c | 70 +++-- kernel/arch/dreamcast/exports-naomi.txt | 10 + kernel/arch/dreamcast/exports-pristine.txt | 10 + kernel/arch/dreamcast/hardware/sd.c | 334 +++++++++++++++------ kernel/arch/dreamcast/include/dc/sd.h | 64 +++- 5 files changed, 369 insertions(+), 119 deletions(-) diff --git a/examples/dreamcast/filesystem/sd/speedtest/sd-speedtest.c b/examples/dreamcast/filesystem/sd/speedtest/sd-speedtest.c index cd127998..76422c15 100644 --- a/examples/dreamcast/filesystem/sd/speedtest/sd-speedtest.c +++ b/examples/dreamcast/filesystem/sd/speedtest/sd-speedtest.c @@ -1,10 +1,11 @@ /* KallistiOS ##version## - speedtest.c - Copyright (C) 2023 Ruslan Rostovtsev (SWAT) + sd-speedtest.c + Copyright (C) 2023, 2025 Ruslan Rostovtsev - This example program simply attempts to read some sectors from the first - partition of an SD device attached to SCIF and then show the timing information. + This example program performs speed tests for reading sectors from the first + partition of an SD device using both SCI-SPI and SCIF-SPI interfaces with + CRC checking enabled and disabled, and then shows the timing information. */ #include <stdio.h> @@ -12,6 +13,7 @@ #include <string.h> #include <stdlib.h> #include <stdint.h> +#include <stdbool.h> #include <errno.h> #include <dc/sd.h> @@ -27,7 +29,9 @@ KOS_INIT_FLAGS(INIT_DEFAULT); -static uint8_t tbuf[1024 * 512] __attribute__((aligned(32))); +#define TEST_BLOCK_COUNT 1024 + +static uint8_t tbuf[TEST_BLOCK_COUNT * 512] __attribute__((aligned(32))); static void __attribute__((__noreturn__)) wait_exit(void) { maple_device_t *dev; @@ -49,36 +53,38 @@ static void __attribute__((__noreturn__)) wait_exit(void) { } } -int main(int argc, char *argv[]) { +static int run_speed_test(sd_interface_t interface, bool check_crc) { + sd_init_params_t params = { + .interface = interface, + .check_crc = check_crc + }; kos_blockdev_t sd_dev; uint64_t begin, end, timer, average; uint64_t sum = 0; uint8_t pt; int i; - dbgio_dev_select("fb"); - dbglog(DBG_DEBUG, "Initializing SD card.\n"); + const char *interface_name = (interface == SD_IF_SCI) ? "SCI-SPI" : "SCIF-SPI"; - if(sd_init()) { - dbglog(DBG_DEBUG, "Could not initialize the SD card. Please make sure that you " - "have an SD card adapter plugged in and an SD card inserted.\n"); - wait_exit(); + while(sd_init_ex(¶ms)) { + dbglog(DBG_DEBUG, "Could not initialize the SD card on %s interface.\n", interface_name); + return -1; } /* Grab the block device for the first partition on the SD card. Note that you must have the SD card formatted with an MBR partitioning scheme. */ if(sd_blockdev_for_partition(0, &sd_dev, &pt)) { dbglog(DBG_DEBUG, "Could not find the first partition on the SD card!\n"); - wait_exit(); + sd_shutdown(); + return -1; } - dbglog(DBG_DEBUG, "Calculating average speed for reading 1024 blocks.\n"); - for(i = 0; i < 10; i++) { begin = timer_ms_gettime64(); - if(sd_dev.read_blocks(&sd_dev, 0, 1024, tbuf)) { + if(sd_dev.read_blocks(&sd_dev, 0, TEST_BLOCK_COUNT, tbuf)) { dbglog(DBG_DEBUG, "couldn't read block: %s\n", strerror(errno)); + sd_shutdown(); return -1; } @@ -89,10 +95,38 @@ int main(int argc, char *argv[]) { average = sum / 10; - dbglog(DBG_DEBUG, "SD card read average took %llu ms (%.3f KB/sec)\n", - average, (512 * 1024) / ((double)average)); + dbglog(DBG_DEBUG, "%s: read average took %llu ms (%.3f KB/sec)\n", + interface_name, average, (512 * TEST_BLOCK_COUNT) / ((double)average)); sd_shutdown(); + return 0; +} + +int main(int argc, char *argv[]) { + // dbgio_dev_select("fb"); + + dbglog(DBG_DEBUG, "Starting SD card speed tests\n"); + + dbglog(DBG_DEBUG, "Testing SCI-SPI interface with CRC disabled\n"); + if (run_speed_test(SD_IF_SCI, false) == 0) { + dbglog(DBG_DEBUG, "Testing SCI-SPI interface with CRC enabled\n"); + run_speed_test(SD_IF_SCI, true); + } + else { + dbglog(DBG_DEBUG, "Skipping SCI-SPI interface with CRC enabled\n"); + } + + dbglog(DBG_DEBUG, "Testing SCIF-SPI interface with CRC disabled\n"); + if (run_speed_test(SD_IF_SCIF, false) == 0) { + dbglog(DBG_DEBUG, "Testing SCIF-SPI interface with CRC enabled\n"); + run_speed_test(SD_IF_SCIF, true); + } + else { + dbglog(DBG_DEBUG, "Skipping SCIF-SPI interface with CRC enabled\n"); + } + + dbglog(DBG_DEBUG, "All tests completed\n"); + wait_exit(); return 0; } diff --git a/kernel/arch/dreamcast/exports-naomi.txt b/kernel/arch/dreamcast/exports-naomi.txt index 80432e19..2f1d5a17 100644 --- a/kernel/arch/dreamcast/exports-naomi.txt +++ b/kernel/arch/dreamcast/exports-naomi.txt @@ -77,6 +77,16 @@ sci_spi_read_data sci_spi_dma_write_data sci_spi_dma_read_data +# SD Card +sd_init +sd_init_ex +sd_shutdown +sd_read_blocks +sd_write_blocks +sd_get_size +sd_blockdev_for_partition +sd_blockdev_for_device + # Timers timer_prime timer_start diff --git a/kernel/arch/dreamcast/exports-pristine.txt b/kernel/arch/dreamcast/exports-pristine.txt index 41d8fe9c..55479064 100644 --- a/kernel/arch/dreamcast/exports-pristine.txt +++ b/kernel/arch/dreamcast/exports-pristine.txt @@ -95,6 +95,16 @@ sci_spi_read_data sci_spi_dma_write_data sci_spi_dma_read_data +# SD Card +sd_init +sd_init_ex +sd_shutdown +sd_read_blocks +sd_write_blocks +sd_get_size +sd_blockdev_for_partition +sd_blockdev_for_device + # Timers timer_prime timer_start diff --git a/kernel/arch/dreamcast/hardware/sd.c b/kernel/arch/dreamcast/hardware/sd.c index c687f9a2..fa81103f 100644 --- a/kernel/arch/dreamcast/hardware/sd.c +++ b/kernel/arch/dreamcast/hardware/sd.c @@ -2,6 +2,7 @@ sd.c Copyright (C) 2012, 2013 Lawrence Sebald + Copyright (C) 2025 Ruslan Rostovtsev */ /* The code contained herein is basically directly implementing what is @@ -9,10 +10,12 @@ #include <arch/types.h> #include <dc/scif.h> +#include <dc/sci.h> #include <dc/sd.h> #include <errno.h> #include <stdlib.h> #include <string.h> +#include <stdbool.h> /* For CRC16-CCITT */ #include <kos/net.h> @@ -26,9 +29,21 @@ #define CMD(n) ((n) | 0x40) -static int byte_mode = 0; -static int is_mmc = 0; -static int initted = 0; +static bool byte_mode = false; +static bool is_mmc = false; +static bool initted = false; +static bool check_crc = true; +static sd_interface_t current_interface = SD_IF_SCIF; + +/* Unified function pointers for both interfaces */ +static uint8_t (*spi_rw_byte)(uint8_t data) = NULL; +static void (*spi_set_cs)(bool enabled) = NULL; +static int (*spi_init)(bool fast) = NULL; +static void (*spi_shutdown)(void) = NULL; +static void (*spi_read_data)(uint8_t *data, size_t len) = NULL; +static void (*spi_write_data)(const uint8_t *data, size_t len) = NULL; +static uint8_t (*spi_read_byte)(void) = NULL; +static void (*spi_write_byte)(uint8_t data) = NULL; /* The type of the dev_data in the block device structure */ typedef struct sd_devdata { @@ -86,19 +101,83 @@ uint8 sd_crc7(const uint8 *data, int size, uint8 crc) { return crc & (0x7f << 1); } -static int sd_send_cmd(uint8 cmd, uint32 arg, int slow) { - uint8 (*dfunc)(uint8 data) = &scif_spi_rw_byte; +/* Unified wrappers for different interfaces */ +static uint8_t sci_rw_byte(uint8_t data) { + uint8_t rx; + sci_spi_rw_byte(data, &rx); + return rx; +} + +static bool current_speed = false; /* false = slow, true = fast */ + +static uint8_t scif_rw_byte_wrapper(uint8_t data) { + if(current_speed) + return scif_spi_rw_byte(data); + else + return scif_spi_slow_rw_byte(data); +} + +static void scif_write_data_wrapper(const uint8_t *data, size_t len) { + while(len--) { + scif_spi_write_byte(*data++); + } +} + +static uint8_t sci_read_byte_wrapper(void) { + uint8_t rx; + sci_spi_read_byte(&rx); + return rx; +} + +static void sci_write_byte_wrapper(uint8_t data) { + sci_spi_write_byte(data); +} + +static void sci_read_data_wrapper(uint8_t *data, size_t len) { + if(len & 31) + sci_spi_read_data(data, len); + else + sci_spi_dma_read_data(data, len, NULL, NULL); +} + +static void sci_write_data_wrapper(const uint8_t *data, size_t len) { + if(len & 31) + sci_spi_write_data(data, len); + else + sci_spi_dma_write_data(data, len, NULL, NULL); +} + +static void scif_shutdown_wrapper(void) { + scif_spi_shutdown(); +} + +static void sci_shutdown_wrapper(void) { + sci_shutdown(); +} + +static int scif_init_wrapper(bool fast) { + current_speed = fast; + return scif_spi_init(); +} + +static void scif_set_cs_wrapper(bool enabled) { + scif_spi_set_cs(enabled ? 0 : 1); +} + +static int sci_init_wrapper(bool fast) { + uint32_t baud = fast ? SCI_SPI_BAUD_MAX : SCI_SPI_BAUD_INIT; + return sci_init(baud, SCI_MODE_SPI, SCI_CLK_INT); +} + +static int sd_send_cmd(uint8_t cmd, uint32 arg) { uint8 rv; int i = 0; uint8 pkt[6]; - if(slow) - dfunc = &scif_spi_slow_rw_byte; - /* Wait for the SD card to be ready to accept our command... */ - dfunc(0xFF); + spi_rw_byte(0xFF); do { - rv = dfunc(0xFF); + rv = spi_rw_byte(0xFF); ++i; } while(rv != 0xFF && i < MAX_RETRIES); @@ -115,21 +194,21 @@ static int sd_send_cmd(uint8 cmd, uint32 arg, int slow) { pkt[5] = sd_crc7(pkt, 5, 0) | 0x01; /* Write out the packet to the device */ - dfunc(pkt[0]); - dfunc(pkt[1]); - dfunc(pkt[2]); - dfunc(pkt[3]); - dfunc(pkt[4]); - dfunc(pkt[5]); + spi_rw_byte(pkt[0]); + spi_rw_byte(pkt[1]); + spi_rw_byte(pkt[2]); + spi_rw_byte(pkt[3]); + spi_rw_byte(pkt[4]); + spi_rw_byte(pkt[5]); /* Ignore the first byte after sending a CMD12 */ if(cmd == CMD(12)) - dfunc(0xFF); + spi_rw_byte(0xFF); /* Wait for a response */ i = 0; do { - rv = dfunc(0xFF); + rv = spi_rw_byte(0xFF); ++i; } while((rv & 0x80) && i < 20); @@ -145,10 +224,10 @@ static int acmd41_loop(uint32 arg) { /* Try to send ACMD41 for a while. It could take up to 1 second to come back to us, but will likely take much less. */ while(i++ < MAX_RETRIES) { - if(sd_send_cmd(CMD(55), 0, 1) > 1) + if(sd_send_cmd(CMD(55), 0) > 1) return -1; - if((rv = sd_send_cmd(CMD(41), arg, 1)) > 1) + if((rv = sd_send_cmd(CMD(41), arg)) > 1) return -1; if(rv == 0) @@ -168,7 +247,7 @@ static int cmd1_loop(void) { /* Try to send CMD1 for a while. It could take up to 1 second to come back to us, but will likely take much less. */ while(i++ < MAX_RETRIES) { - if((rv = sd_send_cmd(CMD(1), 0, 1)) > 1) + if((rv = sd_send_cmd(CMD(1), 0)) > 1) return -1; if(rv == 0) @@ -183,15 +262,52 @@ static int cmd1_loop(void) { } int sd_init(void) { + sd_init_params_t params = { + .interface = SD_IF_SCIF, + .check_crc = true + }; + return sd_init_ex(¶ms); +} + +int sd_init_ex(const sd_init_params_t *params) { int i; uint8 buf[4]; if(initted) return 0; - byte_mode = is_mmc = 0; + if(!params) { + errno = EINVAL; + return -1; + } + + byte_mode = is_mmc = false; + check_crc = params->check_crc; + current_interface = params->interface; + + if(current_interface == SD_IF_SCIF) { + spi_rw_byte = &scif_rw_byte_wrapper; + spi_set_cs = &scif_set_cs_wrapper; + spi_init = &scif_init_wrapper; + spi_shutdown = &scif_shutdown_wrapper; + spi_read_data = &scif_spi_read_data; + spi_write_data = &scif_write_data_wrapper; + spi_read_byte = &scif_spi_read_byte; + spi_write_byte = &scif_spi_write_byte; + } + else { + spi_rw_byte = &sci_rw_byte; + spi_set_cs = &sci_spi_set_cs; + spi_init = &sci_init_wrapper; + spi_shutdown = &sci_shutdown_wrapper; + spi_read_data = &sci_read_data_wrapper; + spi_write_data = &sci_write_data_wrapper; + spi_read_byte = &sci_read_byte_wrapper; + spi_write_byte = &sci_write_byte_wrapper; + } - if(scif_spi_init()) + /* Initialize interface with low speed for reliability */ + if(spi_init(false)) return -1; /* Send 10 idle bytes so as to delay the required number of clock cycles @@ -199,82 +315,87 @@ int sd_init(void) { and sending 10 idle bytes is 80 cycles). Once that is done, deassert the /CS line. */ for(i = 0; i < 10; ++i) { - scif_spi_slow_rw_byte(0xFF); + spi_rw_byte(0xFF); } - scif_spi_set_cs(0); + spi_set_cs(true); /* Reset the card, putting it in its idle state. */ - if(sd_send_cmd(CMD(0), 0, 1) != 1) { - scif_spi_set_cs(1); + if(sd_send_cmd(CMD(0), 0) != 1) { + spi_set_cs(false); return -1; } /* Detect if we're using a v2 SD card. */ - if(sd_send_cmd(CMD(8), 0x000001AA, 1) == 1) { - buf[0] = scif_spi_slow_rw_byte(0xFF); - buf[1] = scif_spi_slow_rw_byte(0xFF); - buf[2] = scif_spi_slow_rw_byte(0xFF); - buf[3] = scif_spi_slow_rw_byte(0xFF); + if(sd_send_cmd(CMD(8), 0x000001AA) == 1) { + buf[0] = spi_rw_byte(0xFF); + buf[1] = spi_rw_byte(0xFF); + buf[2] = spi_rw_byte(0xFF); + buf[3] = spi_rw_byte(0xFF); if((buf[2] & 0x0F) != 0x01 || buf[3] != 0xAA) { - scif_spi_set_cs(1); + spi_set_cs(false); return -2; } /* ACMD41 until we're ready */ if(acmd41_loop(0x40000000)) { - scif_spi_set_cs(1); + spi_set_cs(false); return -1; } /* Detect if we do byte addressing or block addressing with CMD58 */ - if(sd_send_cmd(CMD(58), 0, 1)) { - scif_spi_set_cs(1); + if(sd_send_cmd(CMD(58), 0)) { + spi_set_cs(false); return -1; } - buf[0] = scif_spi_slow_rw_byte(0xFF); - buf[1] = scif_spi_slow_rw_byte(0xFF); - buf[2] = scif_spi_slow_rw_byte(0xFF); - buf[3] = scif_spi_slow_rw_byte(0xFF); + buf[0] = spi_rw_byte(0xFF); + buf[1] = spi_rw_byte(0xFF); + buf[2] = spi_rw_byte(0xFF); + buf[3] = spi_rw_byte(0xFF); if(!(buf[0] & 0x40)) - byte_mode = 1; + byte_mode = true; } else { /* ACMD41 (SDv1) or CMD1 (MMC) until we're ready */ if(acmd41_loop(0)) { /* Try with CMD1 instead then... */ if(cmd1_loop()) { - scif_spi_set_cs(1); + spi_set_cs(false); return -1; } /* If ACMD41 failed but CMD1 succeeded, we have a MMC card. */ - is_mmc = 1; + is_mmc = true; } /* Set the block length to 512 with CMD16 */ - if(sd_send_cmd(CMD(16), 512, 1)) { - scif_spi_set_cs(1); + if(sd_send_cmd(CMD(16), 512)) { + spi_set_cs(false); ...<truncated>... hooks/post-receive -- A pseudo Operating System for the Dreamcast. |