Subversion Repositories pentevo

Rev

Rev 716 | Blame | Last modification | View Log | Download | RSS feed

  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;
  653.