Skip to content

Commit 32f99cb

Browse files
committed
sd: Improved robustness and data writing.
Updated the SPI read and write data functions to return status codes. This change improves error handling in the SD card read and write operations. Additionally, introduced a reinitialization mechanism for the SD card in case of read/write failures, enhancing robustness. Also impoved data writing for SCI interface by changing per-byte operations to per-sector.
1 parent b4ba510 commit 32f99cb

File tree

1 file changed

+77
-29
lines changed
  • kernel/arch/dreamcast/hardware

1 file changed

+77
-29
lines changed

kernel/arch/dreamcast/hardware/sd.c

Lines changed: 77 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ static uint8_t (*spi_rw_byte)(uint8_t data) = NULL;
4040
static void (*spi_set_cs)(bool enabled) = NULL;
4141
static int (*spi_init)(bool fast) = NULL;
4242
static void (*spi_shutdown)(void) = NULL;
43-
static void (*spi_read_data)(uint8_t *data, size_t len) = NULL;
44-
static void (*spi_write_data)(const uint8_t *data, size_t len) = NULL;
43+
static int (*spi_read_data)(uint8_t *data, size_t len) = NULL;
44+
static int (*spi_write_data)(const uint8_t *data, size_t len) = NULL;
4545
static uint8_t (*spi_read_byte)(void) = NULL;
4646
static void (*spi_write_byte)(uint8_t data) = NULL;
4747

@@ -117,10 +117,16 @@ static uint8_t scif_rw_byte_wrapper(uint8_t data) {
117117
return scif_spi_slow_rw_byte(data);
118118
}
119119

120-
static void scif_write_data_wrapper(const uint8_t *data, size_t len) {
120+
static int scif_read_data_wrapper(uint8_t *data, size_t len) {
121+
scif_spi_read_data(data, len);
122+
return 0;
123+
}
124+
125+
static int scif_write_data_wrapper(const uint8_t *data, size_t len) {
121126
while(len--) {
122127
scif_spi_write_byte(*data++);
123128
}
129+
return 0;
124130
}
125131

126132
static uint8_t sci_read_byte_wrapper(void) {
@@ -133,18 +139,18 @@ static void sci_write_byte_wrapper(uint8_t data) {
133139
sci_spi_write_byte(data);
134140
}
135141

136-
static void sci_read_data_wrapper(uint8_t *data, size_t len) {
142+
static int sci_read_data_wrapper(uint8_t *data, size_t len) {
137143
if(len & 31)
138-
sci_spi_read_data(data, len);
144+
return sci_spi_read_data(data, len);
139145
else
140-
sci_spi_dma_read_data(data, len, NULL, NULL);
146+
return sci_spi_dma_read_data(data, len, NULL, NULL);
141147
}
142148

143-
static void sci_write_data_wrapper(const uint8_t *data, size_t len) {
149+
static int sci_write_data_wrapper(const uint8_t *data, size_t len) {
144150
if(len & 31)
145-
sci_spi_write_data(data, len);
151+
return sci_spi_write_data(data, len);
146152
else
147-
sci_spi_dma_write_data(data, len, NULL, NULL);
153+
return sci_spi_dma_write_data(data, len, NULL, NULL);
148154
}
149155

150156
static void scif_shutdown_wrapper(void) {
@@ -269,6 +275,21 @@ int sd_init(void) {
269275
return sd_init_ex(&params);
270276
}
271277

278+
static int sd_reinit(void) {
279+
sd_init_params_t params = {
280+
.interface = current_interface,
281+
.check_crc = check_crc
282+
};
283+
284+
spi_set_cs(false);
285+
spi_rw_byte(0xFF);
286+
287+
spi_shutdown();
288+
289+
initted = false;
290+
return sd_init_ex(&params);
291+
}
292+
272293
int sd_init_ex(const sd_init_params_t *params) {
273294
int i;
274295
uint8 buf[4];
@@ -290,7 +311,7 @@ int sd_init_ex(const sd_init_params_t *params) {
290311
spi_set_cs = &scif_set_cs_wrapper;
291312
spi_init = &scif_init_wrapper;
292313
spi_shutdown = &scif_shutdown_wrapper;
293-
spi_read_data = &scif_spi_read_data;
314+
spi_read_data = &scif_read_data_wrapper;
294315
spi_write_data = &scif_write_data_wrapper;
295316
spi_read_byte = &scif_spi_read_byte;
296317
spi_write_byte = &scif_spi_write_byte;
@@ -440,7 +461,9 @@ static int read_data(size_t bytes, uint8 *buf) {
440461
return -1;
441462

442463
/* Read in the data */
443-
spi_read_data(buf, bytes);
464+
if(spi_read_data(buf, bytes)) {
465+
return -1;
466+
}
444467

445468
/* Read in the trailing CRC */
446469
if(check_crc) {
@@ -455,7 +478,10 @@ static int read_data(size_t bytes, uint8 *buf) {
455478
}
456479

457480
int sd_read_blocks(uint32 block, size_t count, uint8 *buf) {
458-
int rv = 0;
481+
int rv;
482+
size_t read_count;
483+
uint8_t *read_buf;
484+
bool retried = false;
459485

460486
if(!initted) {
461487
errno = ENXIO;
@@ -466,9 +492,13 @@ int sd_read_blocks(uint32 block, size_t count, uint8 *buf) {
466492
if(byte_mode)
467493
block <<= 9;
468494

495+
read_blocks:
496+
read_count = count;
497+
read_buf = buf;
498+
rv = 0;
469499
spi_set_cs(true);
470500

471-
if(count == 1) {
501+
if(read_count == 1) {
472502
/* Ask the card for the block */
473503
if(sd_send_cmd(CMD(17), block)) {
474504
rv = -1;
@@ -477,7 +507,7 @@ int sd_read_blocks(uint32 block, size_t count, uint8 *buf) {
477507
}
478508

479509
/* Read the block back */
480-
if(read_data(512, buf)) {
510+
if(read_data(512, read_buf)) {
481511
rv = -1;
482512
errno = EIO;
483513
goto out;
@@ -491,14 +521,14 @@ int sd_read_blocks(uint32 block, size_t count, uint8 *buf) {
491521
goto out;
492522
}
493523

494-
while(count--) {
495-
if(read_data(512, buf)) {
524+
while(read_count--) {
525+
if(read_data(512, read_buf)) {
496526
rv = -1;
497527
errno = EIO;
498528
goto out;
499529
}
500530

501-
buf += 512;
531+
read_buf += 512;
502532
}
503533

504534
/* Stop the data transfer */
@@ -507,6 +537,12 @@ int sd_read_blocks(uint32 block, size_t count, uint8 *buf) {
507537

508538
out:
509539
spi_set_cs(false);
540+
if(rv && !retried) {
541+
retried = true;
542+
if(!sd_reinit()) {
543+
goto read_blocks;
544+
}
545+
}
510546
spi_rw_byte(0xFF);
511547

512548
return rv;
@@ -516,7 +552,6 @@ static int write_data(uint8 tag, size_t bytes, const uint8 *buf) {
516552
uint8 rv;
517553
int i = 0;
518554
uint16 crc;
519-
const uint8 *ptr = buf;
520555

521556
/* Wait for the card to be ready for our data */
522557
spi_rw_byte(0xFF);
@@ -532,8 +567,8 @@ static int write_data(uint8 tag, size_t bytes, const uint8 *buf) {
532567

533568
/* Send the data. */
534569
crc = net_crc16ccitt(buf, bytes, 0);
535-
while(bytes--) {
536-
spi_write_byte(*ptr++);
570+
if(spi_write_data(buf, bytes)) {
571+
return -1;
537572
}
538573

539574
/* Write out the block's crc */
@@ -549,8 +584,11 @@ static int write_data(uint8 tag, size_t bytes, const uint8 *buf) {
549584
}
550585

551586
int sd_write_blocks(uint32 block, size_t count, const uint8 *buf) {
552-
int rv = 0, i = 0;
553-
uint8 byte;
587+
int rv, i = 0;
588+
uint8_t byte;
589+
size_t write_count;
590+
uint8_t *write_buf;
591+
bool retried = false;
554592

555593
if(!initted) {
556594
errno = ENXIO;
@@ -561,18 +599,22 @@ int sd_write_blocks(uint32 block, size_t count, const uint8 *buf) {
561599
if(byte_mode)
562600
block <<= 9;
563601

602+
write_blocks:
603+
write_count = count;
604+
write_buf = buf;
605+
rv = 0;
564606
spi_set_cs(true);
565607

566-
if(count == 1) {
608+
if(write_count == 1) {
567609
/* Prepare the card for the block */
568610
if(sd_send_cmd(CMD(24), block)) {
569611
rv = -1;
570612
errno = EIO;
571613
goto out;
572614
}
573615

574-
/* Read the block back */
575-
if(write_data(0xFE, 512, buf)) {
616+
/* Write the block */
617+
if(write_data(0xFE, 512, write_buf)) {
576618
rv = -1;
577619
errno = EIO;
578620
goto out;
@@ -583,7 +625,7 @@ int sd_write_blocks(uint32 block, size_t count, const uint8 *buf) {
583625
we intend to write. */
584626
if(!is_mmc) {
585627
sd_send_cmd(CMD(55), 0);
586-
sd_send_cmd(CMD(23), count);
628+
sd_send_cmd(CMD(23), write_count);
587629
}
588630

589631
/* Set up the multi-block write */
@@ -593,15 +635,15 @@ int sd_write_blocks(uint32 block, size_t count, const uint8 *buf) {
593635
goto out;
594636
}
595637

596-
while(count--) {
597-
if(write_data(0xFC, 512, buf)) {
638+
while(write_count--) {
639+
if(write_data(0xFC, 512, write_buf)) {
598640
/* Make sure we at least try to stop the transfer... */
599641
rv = -1;
600642
errno = EIO;
601643
break;
602644
}
603645

604-
buf += 512;
646+
write_buf += 512;
605647
}
606648

607649
/* Write the end data token. */
@@ -622,6 +664,12 @@ int sd_write_blocks(uint32 block, size_t count, const uint8 *buf) {
622664

623665
out:
624666
spi_set_cs(false);
667+
if(rv && !retried) {
668+
retried = true;
669+
if(!sd_reinit()) {
670+
goto write_blocks;
671+
}
672+
}
625673
spi_rw_byte(0xFF);
626674

627675
return rv;

0 commit comments

Comments
 (0)