Subversion Repositories pentevo

Rev

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