@@ -142,12 +142,12 @@ ALLOW_SAVE_TYPE(spi_sdcard_device::sd_state);
142
142
143
143
DEFINE_DEVICE_TYPE (SPI_SDCARD, spi_sdcard_device, " spi_sdcard" , " SD Card (SPI interface)" )
144
144
145
- spi_sdcard_device::spi_sdcard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
145
+ spi_sdcard_device::spi_sdcard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
146
146
spi_sdcard_device(mconfig, SPI_SDCARD, tag, owner, clock)
147
147
{
148
148
}
149
149
150
- spi_sdcard_device::spi_sdcard_device (const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
150
+ spi_sdcard_device::spi_sdcard_device (const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
151
151
device_t(mconfig, type, tag, owner, clock),
152
152
write_miso(*this ),
153
153
m_image(*this , " image" ),
@@ -158,7 +158,7 @@ spi_sdcard_device::spi_sdcard_device(const machine_config &mconfig, device_type
158
158
m_state(SD_STATE_IDLE),
159
159
m_ss(0 ), m_in_bit(0 ), m_clk_state(0 ),
160
160
m_in_latch(0 ), m_out_latch(0xff ), m_cur_bit(0 ),
161
- m_out_count(0 ), m_out_ptr(0 ), m_write_ptr(0 ), m_blknext(0 ),
161
+ m_out_delay( 0 ), m_out_count(0 ), m_out_ptr(0 ), m_write_ptr(0 ), m_xferblk( 512 ), m_blknext(0 ),
162
162
m_bACMD(false )
163
163
{
164
164
std::fill (std::begin (m_csd), std::end (m_csd), 0 );
@@ -170,18 +170,22 @@ spi_sdcard_device::~spi_sdcard_device()
170
170
171
171
void spi_sdcard_device::device_start ()
172
172
{
173
- save_item (NAME (m_state));
174
- save_item (NAME (m_data));
173
+ m_data = make_unique_clear<u8 []>(2048 + 8 );
174
+
175
+ save_pointer (NAME (m_data), 2048 + 8 );
175
176
save_item (NAME (m_cmd));
177
+ save_item (NAME (m_state));
176
178
save_item (NAME (m_ss));
177
179
save_item (NAME (m_in_bit));
178
180
save_item (NAME (m_clk_state));
179
181
save_item (NAME (m_in_latch));
180
182
save_item (NAME (m_out_latch));
181
183
save_item (NAME (m_cur_bit));
184
+ save_item (NAME (m_out_delay));
182
185
save_item (NAME (m_out_count));
183
186
save_item (NAME (m_out_ptr));
184
187
save_item (NAME (m_write_ptr));
188
+ save_item (NAME (m_xferblk));
185
189
save_item (NAME (m_blknext));
186
190
save_item (NAME (m_bACMD));
187
191
}
@@ -190,40 +194,50 @@ std::error_condition spi_sdcard_device::image_loaded(device_image_interface &ima
190
194
{
191
195
// need block size and total blocks to create CSD
192
196
auto const info = m_image->get_info ();
193
- uint64_t const total_blocks = uint64_t (info.cylinders ) * info.heads * info.sectors ;
197
+ u64 const total_blocks = u64 (info.cylinders ) * info.heads * info.sectors ;
194
198
if (!total_blocks)
195
199
{
196
- osd_printf_error (" %s: SD card cannot mount a zero-block image\n " , tag ());
200
+ osd_printf_error (" %s: SD Card cannot mount a zero-block image\n " , tag ());
197
201
return image_error::INVALIDIMAGE;
198
202
}
199
203
200
204
// ensure block size can be expressed in the CSD
201
205
if ((info.sectorbytes & (info.sectorbytes - 1 )) || !info.sectorbytes || (512 > info.sectorbytes ) || (2048 < info.sectorbytes ))
202
206
{
203
- osd_printf_error (" %s: SD card cannot use sector size %u (must be a power of 2 from 512 to 2048)\n " , tag ());
207
+ osd_printf_error (" %s: SD Card cannot use sector size %u (must be a power of 2 from 512 to 2048)\n " , tag ());
204
208
return image_error::INVALIDIMAGE;
205
209
}
206
210
u8 block_size_exp = 0 ;
207
211
for (auto i = info.sectorbytes ; !BIT (i, 0 ); i >>= 1 )
208
212
++block_size_exp;
209
213
210
214
// see how we can express the total block count
211
- uint64_t total_mant = total_blocks;
212
- uint8_t total_exp = 0 ;
215
+ u64 total_mant = total_blocks;
216
+ u8 total_exp = 0 ;
213
217
while (!BIT (total_mant, 0 ))
214
218
{
215
219
total_mant >>= 1 ;
216
220
++total_exp;
217
221
}
218
222
bool const sd_ok = (2 <= total_exp) && ((1 << 12 ) >= (total_mant << ((9 < total_exp) ? (total_exp - 9 ) : 0 )));
219
- bool const sdhc_ok = (512 == info.sectorbytes ) && (10 <= total_exp) && ((uint32_t (1 ) << 16 ) >= (total_mant << (total_exp - 10 )));
223
+ bool const sdhc_ok = (512 == info.sectorbytes ) && (10 <= total_exp) && ((u32 (1 ) << 16 ) >= (total_mant << (total_exp - 10 )));
220
224
if (!sd_ok && !sdhc_ok)
221
225
{
222
- osd_printf_error (" %s: image size %u blocks of %u bytes is not supported by SD or SDHC\n " , tag (), total_blocks, info.sectorbytes );
226
+ osd_printf_error (" %s: SD Card image size %u blocks of %u bytes is not supported by SD or SDHC\n " , tag (), total_blocks, info.sectorbytes );
223
227
return image_error::INVALIDIMAGE;
224
228
}
225
229
226
- m_blksize = info.sectorbytes ;
230
+ try
231
+ {
232
+ m_sectorbuf.resize (info.sectorbytes );
233
+ }
234
+ catch (std::bad_alloc const &)
235
+ {
236
+ osd_printf_error (" %s: Error allocating %u-byte SD Card sector buffer\n " , tag (), info.sectorbytes );
237
+ return std::errc::not_enough_memory;
238
+ }
239
+
240
+ m_blksize = m_xferblk = info.sectorbytes ;
227
241
228
242
// set up common CSD fields
229
243
m_csd[0 ] = 0x00 ; // 127: CSD_STRUCTURE:2 (00b) 0:6
@@ -233,7 +247,7 @@ std::error_condition spi_sdcard_device::image_loaded(device_image_interface &ima
233
247
m_csd[4 ] = 0x5b ; // 95: CCC:12 (01x110110101b)
234
248
m_csd[5 ] = 0x50 ; // .. READ_BL_LN:4
235
249
m_csd[5 ] |= block_size_exp;
236
- m_csd[6 ] = 0x80 ; // 79: READ_BL_PARTIAL:1 WRITE_BLK_MISALIGN:1 READ_BLK_MISALIGN:1 DSR_IMP:1 0:2 C_SIZE:12
250
+ m_csd[6 ] = 0x00 ; // 79: READ_BL_PARTIAL:1 WRITE_BLK_MISALIGN:1 READ_BLK_MISALIGN:1 DSR_IMP:1 0:2 C_SIZE:12
237
251
m_csd[7 ] = 0x00 ; // ..
238
252
m_csd[8 ] = 0x00 ; // .. VDD_R_CURR_MIN:3 VDD_R_CURR_MAX:3
239
253
m_csd[9 ] = 0x00 ; // 55: VDD_W_CURR_MIN:3 VDD_W_CURR_MAX:3 C_SIZE_MUL:3
@@ -248,9 +262,9 @@ std::error_condition spi_sdcard_device::image_loaded(device_image_interface &ima
248
262
249
263
if (sdhc_ok && ((SD_TYPE_HC == m_preferred_type) || !sd_ok))
250
264
{
251
- uint32_t const c_size = (total_blocks >> 10 ) - 1 ;
265
+ u32 const c_size = (total_blocks >> 10 ) - 1 ;
252
266
osd_printf_verbose (
253
- " %s: mounted as SDHC, %u blocks of %u bytes, device size ((%u + 1) << 10) * (1 << %u)\n " ,
267
+ " %s: SD Card image mounted as SDHC, %u blocks of %u bytes, device size ((%u + 1) << 10) * (1 << %u)\n " ,
254
268
tag (),
255
269
total_blocks, info.sectorbytes ,
256
270
c_size, block_size_exp);
@@ -267,10 +281,10 @@ std::error_condition spi_sdcard_device::image_loaded(device_image_interface &ima
267
281
}
268
282
else
269
283
{
270
- uint8_t const c_size_mult = std::min<uint8_t >(total_exp, 9 ) - 2 ;
271
- uint16_t const c_size = (total_blocks >> (c_size_mult + 2 )) - 1 ;
284
+ u8 const c_size_mult = std::min<u8 >(total_exp, 9 ) - 2 ;
285
+ u16 const c_size = (total_blocks >> (c_size_mult + 2 )) - 1 ;
272
286
osd_printf_verbose (
273
- " %s: mounted as SD, %u blocks of %u bytes, device size ((%u + 1) << (%u + 2)) * (1 << %u)\n " ,
287
+ " %s: SD Card image mounted as SD, %u blocks of %u bytes, device size ((%u + 1) << (%u + 2)) * (1 << %u)\n " ,
274
288
tag (),
275
289
total_blocks, info.sectorbytes ,
276
290
c_size, c_size_mult, block_size_exp);
@@ -281,7 +295,8 @@ std::error_condition spi_sdcard_device::image_loaded(device_image_interface &ima
281
295
m_csd[0 ] |= CSD_STRUCTURE_V10 << 6 ; // 127: CSD_STRUCTURE:2 (00b) 0:6
282
296
m_csd[1 ] = TAAC_UNIT_1MS | TAAC_VALUE_1_5; // 119: TAAC:8
283
297
284
- m_csd[6 ] |= BIT (c_size, 10 , 2 ); // 79: READ_BL_PARTIAL:1 WRITE_BLK_MISALIGN:1 READ_BLK_MISALIGN:1 DSR_IMP:1 0:2 C_SIZE:12
298
+ m_csd[6 ] |= 0x80 ; // 79: READ_BL_PARTIAL:1 WRITE_BLK_MISALIGN:1 READ_BLK_MISALIGN:1 DSR_IMP:1 0:2 C_SIZE:12
299
+ m_csd[6 ] |= BIT (c_size, 10 , 2 );
285
300
m_csd[7 ] |= BIT (c_size, 2 , 8 ); // ..
286
301
m_csd[8 ] |= BIT (c_size, 0 , 2 ) << 6 ; // .. VDD_R_CURR_MIN:3 VDD_R_CURR_MAX:3
287
302
m_csd[8 ] |= VDD_CURR_MIN_100MA << 3 ;
@@ -312,8 +327,9 @@ void spi_sdcard_device::device_add_mconfig(machine_config &config)
312
327
m_image->set_device_unload (FUNC (spi_sdcard_device::image_unloaded));
313
328
}
314
329
315
- void spi_sdcard_device::send_data (u16 count, sd_state new_state)
330
+ void spi_sdcard_device::send_data (u16 count, sd_state new_state, u8 delay )
316
331
{
332
+ m_out_delay = delay;
317
333
m_out_ptr = 0 ;
318
334
m_out_count = count;
319
335
change_state (new_state);
@@ -359,9 +375,10 @@ void spi_sdcard_device::latch_in()
359
375
else if (m_state == SD_STATE_WRITE_DATA)
360
376
{
361
377
m_data[m_write_ptr++] = m_in_latch;
362
- if (m_write_ptr == (m_blksize + 2 ))
378
+ if (m_write_ptr == (m_xferblk + 2 ))
363
379
{
364
380
LOG (" writing LBA %x, data %02x %02x %02x %02x\n " , m_blknext, m_data[0 ], m_data[1 ], m_data[2 ], m_data[3 ]);
381
+ // TODO: this is supposed to be a CRC response, the actual write will take some time
365
382
if (m_image->write (m_blknext, &m_data[0 ]))
366
383
{
367
384
m_data[0 ] = DATA_RESPONSE_OK;
@@ -372,7 +389,7 @@ void spi_sdcard_device::latch_in()
372
389
}
373
390
m_data[1 ] = 0x01 ;
374
391
375
- send_data (2 , SD_STATE_IDLE);
392
+ send_data (2 , SD_STATE_IDLE, 0 ); // zero delay - must immediately follow the data
376
393
}
377
394
}
378
395
else // receive CMD
@@ -385,6 +402,7 @@ void spi_sdcard_device::latch_in()
385
402
do_command ();
386
403
if (m_state == SD_STATE_DATA_MULTI && m_out_count == 0 )
387
404
{
405
+ // FIXME: support multi-block read when transfer size is smaller than block size
388
406
m_data[0 ] = 0xfe ; // data token
389
407
m_image->read (m_blknext++, &m_data[1 ]);
390
408
util::crc16_t crc16 = util::crc16_creator::simple (&m_data[1 ], m_blksize);
@@ -411,13 +429,13 @@ void spi_sdcard_device::shift_out()
411
429
m_cur_bit &= 0x07 ;
412
430
if (m_cur_bit == 0 )
413
431
{
414
- if (m_out_ptr < SPI_DELAY_RESPONSE )
432
+ if (m_out_ptr < m_out_delay )
415
433
{
416
434
m_out_ptr++;
417
435
}
418
436
else if (m_out_count > 0 )
419
437
{
420
- m_out_latch = m_data[m_out_ptr - SPI_DELAY_RESPONSE ];
438
+ m_out_latch = m_data[m_out_ptr - m_out_delay ];
421
439
m_out_ptr++;
422
440
LOGMASKED (LOG_SPI, " SDCARD: latching %02x (start of shift)\n " , m_out_latch);
423
441
m_out_count--;
@@ -471,16 +489,16 @@ void spi_sdcard_device::do_command()
471
489
break ;
472
490
473
491
case 10 : // CMD10 - SEND_CID
474
- m_data[0 ] = 0x00 ; // initial R1 response
475
- m_data[1 ] = 0xff ; // throwaway byte before data transfer
476
- m_data[2 ] = 0xfe ; // data token
477
- m_data[3 ] = ' M' ; // Manufacturer ID - we'll use M for MAME
478
- m_data[4 ] = ' M' ; // OEM ID - MD for MAMEdev
479
- m_data[5 ] = ' D' ;
480
- m_data[6 ] = ' M' ; // Product Name - "MCARD"
481
- m_data[7 ] = ' C' ;
482
- m_data[8 ] = ' A' ;
483
- m_data[9 ] = ' R' ;
492
+ m_data[0 ] = 0x00 ; // initial R1 response
493
+ m_data[1 ] = 0xff ; // throwaway byte before data transfer
494
+ m_data[2 ] = 0xfe ; // data token
495
+ m_data[3 ] = ' M' ; // Manufacturer ID - we'll use M for MAME
496
+ m_data[4 ] = ' M' ; // OEM ID - MD for MAMEdev
497
+ m_data[5 ] = ' D' ;
498
+ m_data[6 ] = ' M' ; // Product Name - "MCARD"
499
+ m_data[7 ] = ' C' ;
500
+ m_data[8 ] = ' A' ;
501
+ m_data[9 ] = ' R' ;
484
502
m_data[10 ] = ' D' ;
485
503
m_data[11 ] = 0x10 ; // Product Revision in BCD (1.0)
486
504
{
@@ -509,17 +527,22 @@ void spi_sdcard_device::do_command()
509
527
break ;
510
528
511
529
case 16 : // CMD16 - SET_BLOCKLEN
512
- m_blksize = get_u16be (&m_cmd[3 ]);
513
- if (m_image->exists () && m_image->set_block_size (m_blksize))
530
+ if (m_image->exists ())
514
531
{
515
- m_data[0 ] = 0 ;
532
+ u16 const blocklen = get_u16be (&m_cmd[3 ]);
533
+ if (blocklen && ((m_type == SD_TYPE_V2) || (blocklen == m_blksize)) && (blocklen <= m_blksize))
534
+ {
535
+ m_xferblk = blocklen;
536
+ m_data[0 ] = 0x00 ;
537
+ }
538
+ else
539
+ {
540
+ m_data[0 ] = 0x40 ; // parameter error
541
+ }
516
542
}
517
543
else
518
544
{
519
- m_data[0 ] = 0xff ; // indicate an error
520
- // if false was returned, it means the hard disk is a CHD file, and we can't resize the
521
- // blocks on CHD files.
522
- logerror (" spi_sdcard: Couldn't change block size to %d, wrong CHD file?" , m_blksize);
545
+ m_data[0 ] = 0xff ; // show an error
523
546
}
524
547
send_data (1 , SD_STATE_TRAN);
525
548
break ;
@@ -533,53 +556,101 @@ void spi_sdcard_device::do_command()
533
556
m_data[1 ] = 0xff ;
534
557
m_data[2 ] = 0xfe ; // data token
535
558
u32 blk = get_u32be (&m_cmd[1 ]);
536
- if (m_type == SD_TYPE_V2)
559
+ if ((m_type == SD_TYPE_V2) && ((blk / m_blksize) != ((blk + (m_xferblk - 1 )) / m_blksize)))
560
+ {
561
+ LOG (" rejecting read of %u bytes at %u that crosses %u-byte block boundary\n " , m_xferblk, blk, m_blksize);
562
+ m_data[0 ] = 0x40 ; // parameter error
563
+ send_data (1 , SD_STATE_TRAN);
564
+ }
565
+ else if (m_xferblk == m_blksize)
537
566
{
538
- blk /= m_blksize;
567
+ // optimise for reading an entire block
568
+ if (m_type == SD_TYPE_V2)
569
+ {
570
+ blk /= m_blksize;
571
+ }
572
+ m_image->read (blk, &m_data[3 ]);
573
+ util::crc16_t crc16 = util::crc16_creator::simple (&m_data[3 ], m_xferblk);
574
+ put_u16be (&m_data[m_xferblk + 3 ], crc16);
575
+ LOG (" reading LBA %x: [0] %02x %02x .. [%d] %02x %02x [crc16] %04x\n " , blk, m_data[3 ], m_data[4 ], m_xferblk - 2 , m_data[m_xferblk + 1 ], m_data[m_xferblk + 2 ], crc16);
576
+ send_data (3 + m_xferblk + 2 , SD_STATE_DATA);
539
577
}
540
- m_image-> read (blk, &m_data[ 3 ]);
578
+ else
541
579
{
542
- util::crc16_t crc16 = util::crc16_creator::simple (&m_data[3 ], m_blksize);
543
- put_u16be (&m_data[m_blksize + 3 ], crc16);
544
- LOG (" reading LBA %x: [0] %02x %02x .. [%d] %02x %02x [crc16] %04x\n " , blk, m_data[3 ], m_data[4 ], m_blksize - 2 , m_data[m_blksize + 1 ], m_data[m_blksize + 2 ], crc16);
580
+ assert (m_type == SD_TYPE_V2);
581
+ m_image->read (blk / m_blksize, &m_sectorbuf[0 ]);
582
+ std::copy_n (&m_sectorbuf[blk % m_blksize], m_xferblk, &m_data[3 ]);
583
+ util::crc16_t crc16 = util::crc16_creator::simple (&m_data[3 ], m_xferblk);
584
+ put_u16be (&m_data[m_xferblk + 3 ], crc16);
585
+ LOG (" reading LBA %x+%x: [0] %02x %02x .. [%d] %02x %02x [crc16] %04x\n " , blk / m_blksize, blk % m_blksize, m_data[3 ], m_data[4 ], m_xferblk - 2 , m_data[m_xferblk + 1 ], m_data[m_xferblk + 2 ], crc16);
586
+ send_data (3 + m_xferblk + 2 , SD_STATE_DATA);
545
587
}
546
- send_data (3 + m_blksize + 2 , SD_STATE_DATA);
547
588
}
548
589
else
549
590
{
550
591
m_data[0 ] = 0xff ; // show an error
551
- send_data (1 , SD_STATE_DATA );
592
+ send_data (1 , SD_STATE_TRAN );
552
593
}
553
594
break ;
554
595
555
596
case 18 : // CMD18 - CMD_READ_MULTIPLE_BLOCK
556
597
if (m_image->exists ())
557
598
{
558
- m_data[0 ] = 0x00 ; // initial R1 response
559
- // data token occurs some time after the R1 response. A2SD
560
- // expects at least 1 byte of space between R1 and the data
561
- // packet.
562
- m_blknext = get_u32be (&m_cmd[1 ]);
563
- if (m_type == SD_TYPE_V2)
599
+ if (m_xferblk == m_blksize)
564
600
{
565
- m_blknext /= m_blksize;
601
+ m_data[0 ] = 0x00 ; // initial R1 response
602
+ // data token occurs some time after the R1 response. A2SD
603
+ // expects at least 1 byte of space between R1 and the data
604
+ // packet.
605
+ m_blknext = get_u32be (&m_cmd[1 ]);
606
+ if (m_type == SD_TYPE_V2)
607
+ {
608
+ m_blknext /= m_xferblk;
609
+ }
610
+ send_data (1 , SD_STATE_DATA_MULTI);
611
+ }
612
+ else
613
+ {
614
+ // FIXME: support multi-block read when transfer size is smaller than block size
615
+ m_data[0 ] = 0x40 ; // parameter error
616
+ send_data (1 , SD_STATE_TRAN);
566
617
}
567
618
}
568
619
else
569
620
{
570
621
m_data[0 ] = 0xff ; // show an error
622
+ send_data (1 , SD_STATE_TRAN);
571
623
}
572
- send_data (1 , SD_STATE_DATA_MULTI);
573
624
break ;
574
625
575
626
case 24 : // CMD24 - WRITE_BLOCK
576
- m_data[0 ] = 0 ;
577
- m_blknext = get_u32be (&m_cmd[1 ]);
578
- if (m_type == SD_TYPE_V2)
627
+ if (m_xferblk != m_blksize)
579
628
{
580
- m_blknext /= m_blksize;
629
+ // partial block write not supported
630
+ LOG (" rejecting write of %u bytes that is not a full %u-byte block\n " , m_xferblk, m_blksize);
631
+ m_data[0 ] = 0x40 ; // parameter error
632
+ send_data (1 , SD_STATE_TRAN);
633
+ }
634
+ else
635
+ {
636
+ m_blknext = get_u32be (&m_cmd[1 ]);
637
+ if ((m_type == SD_TYPE_V2) && (m_blknext % m_blksize))
638
+ {
639
+ // misaligned write not supported
640
+ LOG (" rejecting write of %u bytes at %u that crosses %u-byte block boundary\n " , m_xferblk, m_blknext, m_blksize);
641
+ m_data[0 ] = 0x40 ; // parameter error
642
+ send_data (1 , SD_STATE_TRAN);
643
+ }
644
+ else
645
+ {
646
+ if (m_type == SD_TYPE_V2)
647
+ {
648
+ m_blknext /= m_xferblk;
649
+ }
650
+ m_data[0 ] = 0 ;
651
+ send_data (1 , SD_STATE_WRITE_WAITFE);
652
+ }
581
653
}
582
- send_data (1 , SD_STATE_WRITE_WAITFE);
583
654
break ;
584
655
585
656
case 41 :
0 commit comments