Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
716 lvd 1
#include "std.h"
2
 
3
#include <io.h>
4
 
5
#include "emul.h"
6
#include "vars.h"
7
#include "sdcard.h"
8
 
9
#include "util.h"
10
 
11
void TSdCard::Reset()
12
{
13
//    printf(__FUNCTION__"\n");
14
 
15
    CurrState = ST_IDLE;
16
    ArgCnt = 0;
17
    Cmd = CMD_INVALID;
18
    DataBlockLen = 512;
19
    DataCnt = 0;
20
 
21
    CsdCnt = 0;
22
    Csd[0] = (1 << 6); // CSD structure (SDHC)
23
    Csd[1] = 0xE;  // TACC
24
    Csd[2] = 0x00; // NSAC
25
    Csd[3] = 0x32; // TRAN_SPEED
26
    Csd[4] = 0x5B; // CCC x1x11011
27
    Csd[5] = 0x59; // CCC 0101 | READ_BL_LEN 9
28
    Csd[6] = 0x00; // READ_BL_PARTIAL | WRITE_BLK_MISALIGN | READ_BLK_MISALIGN | DSR_IMP
29
 
30
    UpdateCsdImageSize();
31
 
32
    Csd[10] = (1 << 6) | (0x3F << 1); // ERASE_BLK_EN | SECTOR_SIZE
33
    Csd[11] = (1 << 7); // SECTOR_SIZE | WP_GRP_SIZE
34
    Csd[12] = (2 << 2) | 2; // R2W_FACTOR | WRITE_BL_LEN 9
35
    Csd[13] = (1 << 6); // WRITE_BL_LEN 9 | WRITE_BL_PARTIAL
36
    Csd[14] = 0x00; // FILE_FORMAT_GRP | COPY | PERM_WRITE_PROTECT | TMP_WRITE_PROTECT | FILE_FORMAT
37
    Csd[15] = 1; // CRC | 1
38
 
39
    CidCnt = 0;
40
    memset(Cid, 0, sizeof(Cid));
41
 
42
    Cid[1] = 'U';
43
    Cid[2] = 'S';
44
    Cid[3] = 'U';
45
    Cid[4] = 'S';
46
    Cid[5] = '3';
47
    Cid[6] = '7';
48
    Cid[7] = '3';
49
    Cid[8] = 0x37;
50
    Cid[14] = 0x04;
51
    Cid[15] = 1;
52
 
53
    Ocr = 0x80200000;
54
    OcrCnt = 0;
55
    AppCmd = false;
56
}
57
 
58
void TSdCard::UpdateCsdImageSize()
59
{
60
    Csd[7] = (ImageSize >> 16) & 0x3F; // C_SIZE
61
    Csd[8] = (ImageSize >> 8) & 0xFF; // C_SIZE
62
    Csd[9] = ImageSize & 0xFF; // C_SIZE 
63
}
64
 
65
void TSdCard::Wr(u8 Val)
66
{
67
    static u32 WrPos = -1;
68
    TState NextState = ST_IDLE;
69
//    printf(__FUNCTION__" Val = %X\n", Val);
70
 
71
    if(!Image)
72
        return;
73
 
74
    switch(CurrState)
75
    {
76
        case ST_IDLE:
77
        case ST_WR_DATA_SIG:
78
        {
79
            if((Val & 0xC0) != 0x40) // start=0, transm=1
80
               break;
81
 
82
            Cmd = TCmd(Val & 0x3F);
83
            if(!AppCmd)
84
            {
85
                switch(Cmd) // Check commands
86
                {
87
                case CMD_GO_IDLE_STATE:
88
//                    printf(__FUNCTION__" CMD_GO_IDLE_STATE, Val = %X\n", Val);
89
                    NextState = ST_RD_ARG;
90
                    ArgCnt = 0;
91
                break;
92
 
93
                case CMD_SEND_OP_COND:
94
//                    printf(__FUNCTION__" CMD_SEND_OP_COND, Val = %X\n", Val);
95
                    NextState = ST_RD_ARG;
96
                    ArgCnt = 0;
97
                break;
98
 
99
                case CMD_SET_BLOCKLEN:
100
//                    printf(__FUNCTION__" CMD_SET_BLOCKLEN, Val = %X\n", Val);
101
                    NextState = ST_RD_ARG;
102
                    ArgCnt = 0;
103
                break;
104
 
105
                case CMD_READ_SINGLE_BLOCK:
106
//                    printf(__FUNCTION__" CMD_READ_SINGLE_BLOCK, Val = %X\n", Val);
107
                    NextState = ST_RD_ARG;
108
                    ArgCnt = 0;
109
                break;
110
 
111
                case CMD_READ_MULTIPLE_BLOCK:
112
//                    printf(__FUNCTION__" CMD_READ_MULTIPLE_BLOCK, Val = %X\n", Val);
113
                    NextState = ST_RD_ARG;
114
                    ArgCnt = 0;
115
                break;
116
 
117
                case CMD_WRITE_BLOCK:
118
//                    printf(__FUNCTION__" CMD_WRITE_BLOCK, Val = %X\n", Val);
119
                    NextState = ST_RD_ARG;
120
                    ArgCnt = 0;
121
                break;
122
 
123
                case CMD_WRITE_MULTIPLE_BLOCK:
124
//                    printf(__FUNCTION__" CMD_WRITE_MULTIPLE_BLOCK, Val = %X\n", Val);
125
                    NextState = ST_RD_ARG;
126
                    ArgCnt = 0;
127
                break;
128
 
129
                case CMD_STOP_TRANSMISSION:
130
//                    printf(__FUNCTION__" CMD_STOP_TRANSMISSION, Val = %X\n", Val);
131
                    NextState = ST_RD_ARG;
132
                    ArgCnt = 0;
133
                break;
134
 
135
                case CMD_SEND_IF_COND:
136
//                    printf(__FUNCTION__" CMD_SEND_IF_COND, Val = %X\n", Val);
137
                    NextState = ST_RD_ARG;
138
                    ArgCnt = 0;
139
                break;
140
 
141
                case CMD_SEND_CSD:
142
//                    printf(__FUNCTION__" CMD_SEND_CSD, Val = %X\n", Val);
143
                    NextState = ST_RD_ARG;
144
                    ArgCnt = 0;
145
                    CsdCnt = 0;
146
                break;
147
 
148
                case CMD_SEND_CID:
149
//                    printf(__FUNCTION__" CMD_SEND_CID, Val = %X\n", Val);
150
                    NextState = ST_RD_ARG;
151
                    ArgCnt = 0;
152
                    CidCnt = 0;
153
                break;
154
 
155
                case CMD_CRC_ON_OFF:
156
//                    printf(__FUNCTION__" CMD_CRC_ON_OFF, Val = %X\n", Val);
157
                    NextState = ST_RD_ARG;
158
                    ArgCnt = 0;
159
                break;
160
 
161
                case CMD_READ_OCR:
162
//                    printf(__FUNCTION__" CMD_READ_OCR, Val = %X\n", Val);
163
//                    __debugbreak();
164
                    NextState = ST_RD_ARG;
165
                    ArgCnt = 0;
166
                    OcrCnt = 0;
167
                break;
168
 
169
                case CMD_APP_CMD:
170
//                    printf(__FUNCTION__" CMD_APP_CMD, Val = %X\n", Val);
171
                    NextState = ST_RD_ARG;
172
                    ArgCnt = 0;
173
                break;
174
 
175
                default:
176
                    printf("%s Unknown CMD = 0x%X, Val = %X\n", __FUNCTION__, Cmd, Val);
177
                    NextState = ST_RD_ARG;
178
                    ArgCnt = 0;
179
                }
180
            }
181
            else // AppCmd
182
            {
183
                switch(Cmd)
184
                {
185
                case CMD_SET_WR_BLK_ERASE_COUNT:
186
                case CMD_SD_SEND_OP_COND:
187
//                    printf(__FUNCTION__" CMD_SD_SEND_OP_COND, Val = %X\n", Val);
188
                    NextState = ST_RD_ARG;
189
                    ArgCnt = 0;
190
                break;
191
 
192
                default:
193
                    printf("%s Unknown ACMD = 0x%X, Val = %X\n", __FUNCTION__, Cmd, Val);
194
                    AppCmd = false;
195
                }
196
            }
197
        }
198
        break;
199
 
200
        case ST_RD_ARG:
201
            NextState = ST_RD_ARG;
202
            ArgArr[3 - ArgCnt++] = Val;
203
 
204
//            printf(__FUNCTION__" ST_RD_ARG val=0x%X\n", Val);
205
            if(ArgCnt == 4)
206
            {
207
                if(!AppCmd)
208
                {
209
                    switch(Cmd)
210
                    {
211
                    case CMD_READ_SINGLE_BLOCK:
212
//                        printf(__FUNCTION__" CMD_READ_SINGLE_BLOCK, Addr = 0x%X\n", Arg);
213
                        fseek(Image, Arg, SEEK_SET);
214
                        fread(Buf, 512, 1, Image);
215
                    break;
216
 
217
                    case CMD_READ_MULTIPLE_BLOCK:
218
//                        printf(__FUNCTION__" CMD_READ_MULTIPLE_BLOCK, Addr = 0x%X\n", Arg);
219
                        fseek(Image, Arg, SEEK_SET);
220
                        fread(Buf, 512, 1, Image);
221
                    break;
222
 
223
                    case CMD_WRITE_BLOCK:
224
//                        printf(__FUNCTION__" CMD_WRITE_BLOCK, Addr = 0x%X\n", Arg);
225
                    break;
226
 
227
                    case CMD_WRITE_MULTIPLE_BLOCK:
228
                        WrPos = Arg;
229
//                        printf(__FUNCTION__" CMD_WRITE_MULTIPLE_BLOCK, Addr = 0x%X\n", Arg);
230
                    break;
231
                    }
232
                }
233
 
234
                NextState = ST_RD_CRC;
235
                ArgCnt = 0;
236
            }
237
        break;
238
 
239
        case ST_RD_CRC:
240
//            printf(__FUNCTION__" ST_RD_CRC val=0x%X\n", Val);
241
            NextState = GetRespondType();
242
        break;
243
 
244
        case ST_RD_DATA_SIG:
245
            NextState = ST_RD_DATA;
246
/*
247
            if(Val != 0xFE) // Проверка сигнатуры данных
248
                __debugbreak();
249
*/
250
            DataCnt = 0;
251
        break;
252
 
253
        case ST_RD_DATA_SIG_MUL:
254
            switch(Val)
255
            {
256
            case 0xFC: // Проверка сигнатуры данных
257
//                printf(__FUNCTION__" ST_RD_DATA_SIG_MUL, Start\n");
258
                DataCnt = 0;
259
                NextState = ST_RD_DATA_MUL;
260
            break;
261
            case 0xFD: // Окончание передачи
262
//                printf(__FUNCTION__" ST_RD_DATA_SIG_MUL, Stop\n");
263
                NextState = ST_IDLE;
264
            break;
265
            default:
266
                NextState = ST_RD_DATA_SIG_MUL;
267
            }
268
        break;
269
 
270
        case ST_RD_DATA: // Прием данных в буфер
271
        {
272
//            printf(__FUNCTION__" ST_RD_DATA, Addr = 0x%X, Idx=%d\n", Arg, DataCnt);
273
            Buf[DataCnt++] = Val;
274
            NextState = ST_RD_DATA;
275
            if(DataCnt == DataBlockLen) // Запись данных в SD карту
276
            {
277
                DataCnt = 0;
278
//                printf(__FUNCTION__" ST_RD_DATA, Addr = 0x%X, write to disk\n", Arg);
279
                fseek(Image, Arg, SEEK_SET);
280
                fwrite(Buf, 512, 1, Image);
281
                NextState = ST_RD_CRC16_1;
282
            }
283
        }
284
        break;
285
 
286
        case ST_RD_DATA_MUL: // Прием данных в буфер
287
        {
288
//            printf(__FUNCTION__" ST_RD_DATA_MUL, Addr = 0x%X, Idx=%d\n", WrPos, DataCnt);
289
            Buf[DataCnt++] = Val;
290
            NextState = ST_RD_DATA_MUL;
291
            if(DataCnt == DataBlockLen) // Запись данных в SD карту
292
            {
293
                DataCnt = 0;
294
//                printf(__FUNCTION__" ST_RD_DATA_MUL, Addr = 0x%X, write to disk\n", WrPos);
295
                fseek(Image, WrPos, SEEK_SET);
296
                fwrite(Buf, 512, 1, Image);
297
                WrPos += 512;
298
                NextState = ST_RD_CRC16_1;
299
            }
300
        }
301
        break;
302
 
303
        case ST_RD_CRC16_1: // Чтение старшего байта CRC16
304
            printf("%s CRC16_1=0x%X\n", __FUNCTION__, Val);
305
            NextState = ST_RD_CRC16_2;
306
        break;
307
 
308
        case ST_RD_CRC16_2: // Чтение младшего байта CRC16
309
            printf("%s CRC16_2=0x%X\n", __FUNCTION__, Val);
310
            NextState = ST_WR_DATA_RESP;
311
        break;
312
 
313
        default:
314
            printf("%s Unknown St = 0x%X, Val = 0x%X\n", __FUNCTION__, CurrState, Val);
315
            return;
316
    }
317
 
318
    CurrState = NextState;
319
}
320
 
321
u8 TSdCard::Rd()
322
{
323
//    printf(__FUNCTION__" cmd=0x%X, St=0x%X\n", Cmd, CurrState);
324
    if(!Image)
325
        return 0xFF;
326
 
327
    switch(Cmd)
328
    {
329
    case CMD_GO_IDLE_STATE:
330
        if(CurrState == ST_R1)
331
        {
332
//            Cmd = CMD_INVALID;
333
            CurrState = ST_IDLE;
334
            return 1;
335
        }
336
    break;
337
    case CMD_SEND_OP_COND:
338
        if(CurrState == ST_R1)
339
        {
340
//            Cmd = CMD_INVALID;
341
            CurrState = ST_IDLE;
342
            return 0;
343
        }
344
    break;
345
    case CMD_SET_BLOCKLEN:
346
        if(CurrState == ST_R1)
347
        {
348
//            Cmd = CMD_INVALID;
349
            CurrState = ST_IDLE;
350
            return 0;
351
        }
352
    break;
353
    case CMD_SEND_IF_COND:
354
        if(CurrState == ST_R7)
355
        {
356
            CurrState = ST_IDLE;
357
            return 5; // invalid command | idle state
358
        }
359
    break;
360
 
361
    case CMD_READ_OCR:
362
        if(CurrState == ST_R1)
363
        {
364
            CurrState = ST_R3;
365
            return 0;
366
        }
367
    break;
368
 
369
    case CMD_APP_CMD:
370
        if(CurrState == ST_R1)
371
        {
372
            CurrState = ST_IDLE;
373
            return 0;
374
        }
375
    break;
376
 
377
    case CMD_SET_WR_BLK_ERASE_COUNT:
378
        if(CurrState == ST_R1)
379
        {
380
            CurrState = ST_IDLE;
381
            return 0;
382
        }
383
    break;
384
 
385
    case CMD_SD_SEND_OP_COND:
386
        if(CurrState == ST_R1)
387
        {
388
            CurrState = ST_IDLE;
389
            return 0;
390
        }
391
    break;
392
 
393
    case CMD_CRC_ON_OFF:
394
        if(CurrState == ST_R1)
395
        {
396
            CurrState = ST_IDLE;
397
            return 0;
398
        }
399
    break;
400
 
401
    case CMD_STOP_TRANSMISSION:
402
        switch(CurrState)
403
        {
404
        case ST_R1:
405
            CurrState = ST_R1b;
406
            return 0;
407
        case ST_R1b:
408
            CurrState = ST_IDLE;
409
            return 0xFF;
410
        }
411
    break;
412
 
413
    case CMD_READ_SINGLE_BLOCK:
414
        switch(CurrState)
415
        {
416
        case ST_R1: // Ответ на команду (карта->хост)
417
            CurrState = ST_WR_DATA_SIG;
418
            return 0;
419
        case ST_WR_DATA_SIG: // Токен данных (карта->хост)
420
            DataCnt = 0;
421
            CurrState = ST_WR_DATA;
422
            return 0xFE;
423
        case ST_WR_DATA: // Передача данных (карта->хост)
424
        {
425
            u8 Val = Buf[DataCnt++];
426
            if(DataCnt == DataBlockLen)
427
            {
428
                DataCnt = 0;
429
                CurrState = ST_WR_CRC16_1;
430
            }
431
            return Val;
432
        }
433
        case ST_WR_CRC16_1: // Передача crc16 (карта->хост)
434
            CurrState = ST_WR_CRC16_2;
435
            return 0xFF;
436
        case ST_WR_CRC16_2: // Передача crc16 (карта->хост)
437
            CurrState = ST_IDLE;
438
            Cmd = CMD_INVALID;
439
            return 0xFF;
440
        }
441
//        Cmd = CMD_INVALID;
442
    break;
443
 
444
    case CMD_READ_MULTIPLE_BLOCK:
445
        switch(CurrState)
446
        {
447
        case ST_R1: // Ответ на команду (карта->хост)
448
            CurrState = ST_WR_DATA_SIG;
449
            return 0;
450
        case ST_WR_DATA_SIG: // Токен данных (карта->хост)
451
            DataCnt = 0;
452
            CurrState = ST_IDLE;
453
            return 0xFE;
454
        case ST_IDLE: // Передача данных (карта->хост), прерывается командой CMD_STOP_TRANSMISSION
455
        {
456
            u8 Val = Buf[DataCnt++];
457
            if(DataCnt == DataBlockLen)
458
            {
459
                DataCnt = 0;
460
                fread(Buf, 512, 1, Image);
461
                CurrState = ST_WR_CRC16_1;
462
            }
463
            return Val;
464
        }
465
        case ST_WR_CRC16_1: // Передача crc16 (карта->хост)
466
            CurrState = ST_WR_CRC16_2;
467
            return 0xFF;
468
        case ST_WR_CRC16_2: // Передача crc16 (карта->хост)
469
            CurrState = ST_WR_DATA_SIG;
470
            return 0xFF;
471
        }
472
    break;
473
 
474
    case CMD_SEND_CSD:
475
        switch(CurrState)
476
        {
477
        case ST_R1:
478
            CurrState = ST_WR_DATA_SIG;
479
            return 0;
480
        case ST_WR_DATA_SIG:
481
            CurrState = ST_WR_DATA;
482
            return 0xFE;
483
        case ST_WR_DATA:
484
        {
485
            u8 Val = Csd[CsdCnt++];
486
            if(CsdCnt == 16)
487
            {
488
                CsdCnt = 0;
489
                CurrState = ST_IDLE;
490
                Cmd = CMD_INVALID;
491
            }
492
            return Val;
493
        }
494
        }
495
//        Cmd = CMD_INVALID;
496
    break;
497
 
498
    case CMD_SEND_CID:
499
        switch(CurrState)
500
        {
501
        case ST_R1:
502
            CurrState = ST_WR_DATA_SIG;
503
            return 0x00;
504
        case ST_WR_DATA_SIG:
505
            CurrState = ST_WR_DATA;
506
            return 0xFE;
507
        case ST_WR_DATA:
508
        {
509
            u8 Val = Cid[CidCnt++];
510
            if(CidCnt == 16)
511
            {
512
                CidCnt = 0;
513
                CurrState = ST_IDLE;
514
                Cmd = CMD_INVALID;
515
            }
516
            return Val;
517
        }
518
        }
519
//        Cmd = CMD_INVALID;
520
    break;
521
 
522
    case CMD_WRITE_BLOCK:
523
//        printf(__FUNCTION__" cmd=0x%X, St=0x%X\n", Cmd, CurrState);
524
        switch(CurrState)
525
        {
526
        case ST_R1:
527
            CurrState = ST_RD_DATA_SIG;
528
            return 0;
529
 
530
        case ST_WR_DATA_RESP:
531
        {
532
            CurrState = ST_IDLE;
533
            u8 Resp = ((STAT_DATA_ACCEPTED) << 1) | 1;
534
            return Resp;
535
        }
536
        }
537
    break;
538
 
539
    case CMD_WRITE_MULTIPLE_BLOCK:
540
        switch(CurrState)
541
        {
542
        case ST_R1:
543
            CurrState = ST_RD_DATA_SIG_MUL;
544
            return 0;
545
        case ST_WR_DATA_RESP:
546
        {
547
            CurrState = ST_RD_DATA_SIG_MUL;
548
            u8 Resp = ((STAT_DATA_ACCEPTED) << 1) | 1;
549
            return Resp;
550
        }
551
        }
552
    break;
553
 
554
    default:
555
        if(!((CurrState == ST_IDLE) && (Cmd == CMD_INVALID)))
556
        {
557
            printf("%s Unknown CMD = 0x%X\n", __FUNCTION__, Cmd);
558
        }
559
 
560
        if(Cmd != CMD_INVALID)
561
        {
562
            return 4; // illegal command
563
        }
564
    }
565
 
566
    if(CurrState == ST_R3)
567
    {
568
        u8 Val = OcrArr[3 - OcrCnt++];
569
 
570
        if(OcrCnt == 4)
571
        {
572
            CurrState = ST_IDLE;
573
            OcrCnt = 0;
574
        }
575
        return Val;
576
    }
577
    return 0xFF;
578
}
579
 
580
TSdCard::TState TSdCard::GetRespondType()
581
{
582
    if(!AppCmd)
583
    {
584
        switch(Cmd)
585
        {
586
        case CMD_APP_CMD:
587
            AppCmd = true;
588
        case CMD_GO_IDLE_STATE:
589
        case CMD_SEND_OP_COND:
590
        case CMD_SET_BLOCKLEN:
591
        case CMD_READ_SINGLE_BLOCK:
592
        case CMD_READ_MULTIPLE_BLOCK:
593
        case CMD_CRC_ON_OFF:
594
        case CMD_STOP_TRANSMISSION:
595
        case CMD_SEND_CSD:
596
        case CMD_SEND_CID:
597
        case CMD_WRITE_BLOCK:
598
        case CMD_WRITE_MULTIPLE_BLOCK:
599
            return ST_R1;
600
        case CMD_READ_OCR:
601
            return ST_R1; // R3
602
        case CMD_SEND_IF_COND:
603
            return ST_R7;
604
        default:
605
            printf("%s Unknown CMD = 0x%X\n", __FUNCTION__, Cmd);
606
            return ST_R1;
607
        }
608
    }
609
    else
610
    {
611
        AppCmd = false;
612
        switch(Cmd)
613
        {
614
            case CMD_SET_WR_BLK_ERASE_COUNT:
615
            case CMD_SD_SEND_OP_COND:
616
                AppCmd = false;
617
                return ST_R1;
618
            default:
619
                printf("%s Unknown ACMD = 0x%X\n", __FUNCTION__, Cmd);
620
        }
621
    }
622
 
623
    return ST_IDLE;
624
}
625
 
626
void TSdCard::Open(const char *Name)
627
{
628
//    printf(__FUNCTION__"\n");
629
    assert(!Image);
630
    Image = fopen(Name, "r+b");
631
    if(!Image)
632
    {
633
        if(Name[0])
634
        {
635
            errmsg("can't find SD card image `%s'", Name);
636
        }
637
        return;
638
    }
639
    ImageSize = u32(_filelengthi64(fileno(Image)) / (512 * 1024)) - 1;
640
    UpdateCsdImageSize();
641
}
642
 
643
void TSdCard::Close()
644
{
645
    if(Image)
646
    {
647
        fclose(Image);
648
        Image = 0;
649
    }
650
}
651
 
652
TSdCard SdCard;