00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00098 #include <cfg/mmci.h>
00099
00100 #if 0
00101
00102 #define NUTDEBUG
00103 #include <stdio.h>
00104 #endif
00105
00106 #include <errno.h>
00107 #include <string.h>
00108 #include <stdlib.h>
00109 #include <memdebug.h>
00110
00111 #include <sys/heap.h>
00112 #include <sys/timer.h>
00113 #include <sys/event.h>
00114 #include <fs/dospart.h>
00115 #include <fs/fs.h>
00116
00117 #include <dev/blockdev.h>
00118 #include <dev/mmcard.h>
00119
00124
00125 #ifndef MMC_BLOCK_SIZE
00126
00132 #define MMC_BLOCK_SIZE 512
00133 #endif
00134
00135 #ifndef MMC_MAX_INIT_POLLS
00136
00143 #define MMC_MAX_INIT_POLLS 512
00144 #endif
00145
00146 #ifndef MMC_MAX_RESET_POLLS
00147
00152 #define MMC_MAX_RESET_POLLS 255
00153 #endif
00154
00155 #ifndef MMC_MAX_WRITE_POLLS
00156
00163 #define MMC_MAX_WRITE_POLLS 1024
00164 #endif
00165
00166 #ifndef MMC_MAX_WRITE_RETRIES
00167
00172 #define MMC_MAX_WRITE_RETRIES 32
00173 #endif
00174
00175 #ifndef MMC_MAX_READ_RETRIES
00176
00181 #define MMC_MAX_READ_RETRIES 8
00182 #endif
00183
00184 #ifndef MMC_MAX_REG_POLLS
00185
00190 #define MMC_MAX_REG_POLLS 512
00191 #endif
00192
00193 #ifndef MMC_MAX_CMDACK_POLLS
00194
00201 #define MMC_MAX_CMDACK_POLLS 1024
00202 #endif
00203
00204 #ifndef MMC_MAX_R1_POLLS
00205
00210 #define MMC_MAX_R1_POLLS 1024
00211 #endif
00212
00216 typedef struct _MMCFCB {
00219 NUTDEVICE *fcb_fsdev;
00220
00223 DOSPART fcb_part;
00224
00232 uint32_t fcb_blknum;
00233
00243 uint8_t fcb_blkbuf[MMC_BLOCK_SIZE];
00244 } MMCFCB;
00245
00246
00247
00248
00249
00250
00251 static HANDLE mutex;
00252
00260 static void MmCardTxCmd(MMCIFC * ifc, uint8_t cmd, uint32_t param)
00261 {
00262 unsigned int tmo = MMC_MAX_CMDACK_POLLS;
00263 uint8_t ch;
00264
00265
00266 (*ifc->mmcifc_cs) (1);
00267
00268
00269
00270
00271
00272 while ((ch = (*ifc->mmcifc_io) (0xFF)) != 0xFF) {
00273 if (--tmo == 0) {
00274 #ifdef NUTDEBUG
00275 printf("[MMCmd%u Timeout %02X]\n", cmd, ch);
00276 #endif
00277 break;
00278 }
00279 if (tmo < MMC_MAX_CMDACK_POLLS / 4) {
00280 NutSleep(1);
00281 }
00282 }
00283
00284 (*ifc->mmcifc_io) (MMCMD_HOST | cmd);
00285 (*ifc->mmcifc_io) ((uint8_t) (param >> 24));
00286 (*ifc->mmcifc_io) ((uint8_t) (param >> 16));
00287 (*ifc->mmcifc_io) ((uint8_t) (param >> 8));
00288 (*ifc->mmcifc_io) ((uint8_t) param);
00289
00290
00291
00292
00293
00294 (*ifc->mmcifc_io) (MMCMD_RESET_CRC);
00295 }
00296
00307 static uint8_t MmCardRxR1(MMCIFC * ifc)
00308 {
00309 uint8_t rc;
00310 int i;
00311
00312 for (i = 0; i < MMC_MAX_R1_POLLS; i++) {
00313 if ((rc = (*ifc->mmcifc_io) (0xFF)) != 0xFF) {
00314 break;
00315 }
00316 }
00317 return rc;
00318 }
00319
00330 static uint16_t MmCardRxR2(MMCIFC * ifc)
00331 {
00332 uint16_t rc;
00333
00334 rc = MmCardRxR1(ifc);
00335 rc <<= 8;
00336 rc += (*ifc->mmcifc_io) (0xFF);
00337
00338 return rc;
00339 }
00340
00352 static uint8_t MmCardRxR3(MMCIFC * ifc, uint32_t * ocr)
00353 {
00354 uint8_t rc;
00355 int i;
00356
00357
00358 rc = MmCardRxR1(ifc);
00359
00360 for (i = 0; i < 4; i++) {
00361 *ocr <<= 8;
00362 *ocr |= (*ifc->mmcifc_io) (0xFF);
00363 }
00364 return rc;
00365 }
00366
00374 static int MmCardReset(MMCIFC * ifc)
00375 {
00376 int i;
00377 uint8_t rsp;
00378
00379
00380
00381
00382 if ((*ifc->mmcifc_in) ()) {
00383 return -1;
00384 }
00385
00386
00387
00388
00389
00390 (*ifc->mmcifc_cs) (0);
00391 for (i = 0; i < 10; i++) {
00392 (*ifc->mmcifc_io) (0xFF);
00393 }
00394
00395
00396
00397
00398
00399 for (i = 0; i < MMC_MAX_RESET_POLLS; i++) {
00400 MmCardTxCmd(ifc, MMCMD_GO_IDLE_STATE, 0);
00401 rsp = MmCardRxR1(ifc);
00402 (*ifc->mmcifc_cs) (0);
00403 if (rsp == MMR1_IDLE_STATE || rsp == MMR1_NOT_IDLE) {
00404 return 0;
00405 }
00406 }
00407 return -1;
00408 }
00409
00420 static int MmCardInit(MMCIFC * ifc)
00421 {
00422 int i;
00423 uint8_t rsp;
00424
00425
00426
00427
00428
00429 if (MmCardReset(ifc)) {
00430 if (MmCardReset(ifc)) {
00431 #ifdef NUTDEBUG
00432 printf("[CardReset failed]");
00433 #endif
00434 return -1;
00435 }
00436 }
00437
00438
00439
00440
00441
00442 for (i = 0; i < MMC_MAX_INIT_POLLS; i++) {
00443
00444
00445
00446
00447
00448 MmCardTxCmd(ifc, MMCMD_SEND_OP_COND, 0);
00449 rsp = MmCardRxR1(ifc);
00450 (*ifc->mmcifc_cs) (0);
00451 if (rsp == MMR1_IDLE_STATE) {
00452 #ifdef NUTDEBUG
00453 printf("[CardIdle]");
00454 #endif
00455
00456 NutEventPost(&mutex);
00457 return 0;
00458 }
00459 if (i > MMC_MAX_INIT_POLLS / 4) {
00460 NutSleep(1);
00461 }
00462 }
00463 #ifdef NUTDEBUG
00464 printf("[CardInit failed]");
00465 #endif
00466 return -1;
00467 }
00468
00479 static int MmCardReadOrVerify(MMCIFC * ifc, uint32_t blk, uint8_t * buf, int vflg)
00480 {
00481 int rc = -1;
00482 int retries = 64;
00483 int i;
00484 uint8_t rsp;
00485
00486
00487 NutEventWait(&mutex, 0);
00488
00489 while (retries--) {
00490 MmCardTxCmd(ifc, MMCMD_READ_SINGLE_BLOCK, blk << 9);
00491 if ((rsp = MmCardRxR1(ifc)) == 0x00) {
00492 if ((rsp = MmCardRxR1(ifc)) == 0xFE) {
00493 rc = 0;
00494 if (vflg) {
00495 for (i = 0; i < MMC_BLOCK_SIZE; i++) {
00496 if (*buf != (*ifc->mmcifc_io) (0xFF)) {
00497 rc = -1;
00498 }
00499 buf++;
00500 }
00501 } else {
00502 for (i = 0; i < MMC_BLOCK_SIZE; i++) {
00503 *buf = (*ifc->mmcifc_io) (0xFF);
00504 buf++;
00505 }
00506 }
00507 (*ifc->mmcifc_io) (0xff);
00508 (*ifc->mmcifc_io) (0xff);
00509 (*ifc->mmcifc_cs) (0);
00510 break;
00511 }
00512 }
00513 (*ifc->mmcifc_cs) (0);
00514 }
00515
00516
00517 NutEventPost(&mutex);
00518
00519 return rc;
00520 }
00521
00531 static int MmCardWrite(MMCIFC * ifc, uint32_t blk, CONST uint8_t * buf)
00532 {
00533 int rc = -1;
00534 int retries = MMC_MAX_WRITE_RETRIES;
00535 int tmo;
00536 int i;
00537 uint8_t rsp;
00538
00539
00540 NutEventWait(&mutex, 0);
00541
00542 while (retries--) {
00543 MmCardTxCmd(ifc, MMCMD_WRITE_BLOCK, blk << 9);
00544 if ((rsp = MmCardRxR1(ifc)) == 0x00) {
00545 (*ifc->mmcifc_io) (0xFF);
00546 (*ifc->mmcifc_io) (0xFE);
00547 for (i = 0; i < MMC_BLOCK_SIZE; i++) {
00548 (*ifc->mmcifc_io) (*buf);
00549 buf++;
00550 }
00551
00552
00553 if ((rsp = MmCardRxR1(ifc)) == 0xE5) {
00554 for (tmo = 0; tmo < MMC_MAX_WRITE_POLLS; tmo++) {
00555 if ((*ifc->mmcifc_io) (0xFF) == 0xFF) {
00556 break;
00557 }
00558 if (tmo > MMC_MAX_WRITE_POLLS - MMC_MAX_WRITE_POLLS / 32) {
00559 NutSleep(1);
00560 }
00561 }
00562 if (tmo) {
00563 rc = 0;
00564 break;
00565 }
00566 #ifdef NUTDEBUG
00567 printf("[MMCWR Timeout]\n");
00568 #endif
00569 }
00570 }
00571 (*ifc->mmcifc_cs) (0);
00572 }
00573 (*ifc->mmcifc_cs) (0);
00574
00575
00576 NutEventPost(&mutex);
00577
00578 return rc;
00579 }
00580
00596 int MmCardBlockRead(NUTFILE * nfp, void *buffer, int num)
00597 {
00598 MMCFCB *fcb = (MMCFCB *) nfp->nf_fcb;
00599 uint32_t blk = fcb->fcb_blknum;
00600 NUTDEVICE *dev = (NUTDEVICE *) nfp->nf_dev;
00601 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00602
00603 if ((*ifc->mmcifc_cd) () != 1) {
00604 return -1;
00605 }
00606 if (buffer == 0) {
00607 buffer = fcb->fcb_blkbuf;
00608 }
00609 blk += fcb->fcb_part.part_sect_offs;
00610
00611 #ifdef MMC_VERIFY_AFTER
00612 {
00613 int i;
00614
00615
00616
00617
00618 for (i = 0; i < MMC_MAX_READ_RETRIES; i++) {
00619 if (MmCardReadOrVerify(ifc, blk, buffer, 0) == 0) {
00620 if (MmCardReadOrVerify(ifc, blk, buffer, 1) == 0) {
00621 return 1;
00622 }
00623 }
00624 }
00625 }
00626 #else
00627 if (MmCardReadOrVerify(ifc, blk, buffer, 0) == 0) {
00628 return 1;
00629 }
00630 #endif
00631 return -1;
00632 }
00633
00649 int MmCardBlockWrite(NUTFILE * nfp, CONST void *buffer, int num)
00650 {
00651 MMCFCB *fcb = (MMCFCB *) nfp->nf_fcb;
00652 uint32_t blk = fcb->fcb_blknum;
00653 NUTDEVICE *dev = (NUTDEVICE *) nfp->nf_dev;
00654 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00655
00656 if ((*ifc->mmcifc_cd) () != 1) {
00657 return -1;
00658 }
00659 if (buffer == 0) {
00660 buffer = fcb->fcb_blkbuf;
00661 }
00662 blk += fcb->fcb_part.part_sect_offs;
00663
00664 #ifdef MMC_VERIFY_AFTER
00665 {
00666 int i;
00667
00668 for (i = 0; i < MMC_MAX_READ_RETRIES; i++) {
00669 if (MmCardWrite(ifc, blk, buffer) == 0) {
00670 if (MmCardReadOrVerify(ifc, blk, (void *) buffer, 1) == 0) {
00671 return 1;
00672 }
00673 if (MmCardReadOrVerify(ifc, blk, (void *) buffer, 1) == 0) {
00674 return 1;
00675 }
00676 }
00677 }
00678 }
00679 #else
00680 if (MmCardWrite(ifc, blk, buffer) == 0) {
00681 return 1;
00682 }
00683 #endif
00684 return -1;
00685 }
00686
00687 #ifdef __HARVARD_ARCH__
00688
00707 int MmCardBlockWrite_P(NUTFILE * nfp, PGM_P buffer, int num)
00708 {
00709 return -1;
00710 }
00711 #endif
00712
00738 NUTFILE *MmCardMount(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00739 {
00740 int partno = 0;
00741 int i;
00742 NUTDEVICE *fsdev;
00743 NUTFILE *nfp;
00744 MMCFCB *fcb;
00745 DOSPART *part;
00746 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00747 FSCP_VOL_MOUNT mparm;
00748
00749
00750 if ((*ifc->mmcifc_cd) () == 0) {
00751 errno = ENODEV;
00752 return NUTFILE_EOF;
00753 }
00754
00755
00756 if (MmCardInit(ifc)) {
00757 errno = ENODEV;
00758 return NUTFILE_EOF;
00759 }
00760
00761
00762 if (*name) {
00763 partno = atoi(name);
00764 do {
00765 name++;
00766 } while (*name && *name != '/');
00767 if (*name == '/') {
00768 name++;
00769 }
00770 }
00771
00772
00773
00774
00775
00776
00777
00778 for (fsdev = nutDeviceList; fsdev; fsdev = fsdev->dev_next) {
00779 if (*name == 0) {
00780 if (fsdev->dev_type == IFTYP_FS) {
00781 break;
00782 }
00783 } else if (strcmp(fsdev->dev_name, name) == 0) {
00784 break;
00785 }
00786 }
00787
00788 if (fsdev == 0) {
00789 #ifdef NUTDEBUG
00790 printf("[No FSDriver]");
00791 #endif
00792 errno = ENODEV;
00793 return NUTFILE_EOF;
00794 }
00795
00796 if ((fcb = calloc(1, sizeof(MMCFCB))) == 0) {
00797 errno = ENOMEM;
00798 return NUTFILE_EOF;
00799 }
00800 fcb->fcb_fsdev = fsdev;
00801
00802
00803 if (MmCardReadOrVerify(ifc, 0, fcb->fcb_blkbuf, 0)) {
00804 free(fcb);
00805 return NUTFILE_EOF;
00806 }
00807
00808 if (fcb->fcb_blkbuf[DOSPART_MAGICPOS] != 0x55 || fcb->fcb_blkbuf[DOSPART_MAGICPOS + 1] != 0xAA) {
00809 free(fcb);
00810 return NUTFILE_EOF;
00811 }
00812
00813 if(fcb->fcb_blkbuf[DOSPART_TYPEPOS] == 'F' &&
00814 fcb->fcb_blkbuf[DOSPART_TYPEPOS + 1] == 'A' &&
00815 fcb->fcb_blkbuf[DOSPART_TYPEPOS + 2] == 'T') {
00816
00817 fcb->fcb_part.part_type = PTYPE_FAT12;
00818 fcb->fcb_part.part_sect_offs = 0;
00819 fcb->fcb_part.part_sects = 65536;
00820 }
00821 else {
00822
00823 part = (DOSPART *) & fcb->fcb_blkbuf[DOSPART_SECTORPOS];
00824 for (i = 1; i <= 4; i++) {
00825 if (partno) {
00826 if (i == partno) {
00827
00828 fcb->fcb_part = *part;
00829 break;
00830 }
00831 } else if (part->part_state & 0x80) {
00832
00833 fcb->fcb_part = *part;
00834 break;
00835 }
00836 part++;
00837 }
00838
00839 if (fcb->fcb_part.part_type == PTYPE_EMPTY) {
00840 free(fcb);
00841 return NUTFILE_EOF;
00842 }
00843 }
00844
00845 if ((nfp = NutHeapAlloc(sizeof(NUTFILE))) == 0) {
00846 free(fcb);
00847 errno = ENOMEM;
00848 return NUTFILE_EOF;
00849 }
00850 nfp->nf_next = 0;
00851 nfp->nf_dev = dev;
00852 nfp->nf_fcb = fcb;
00853
00854
00855
00856
00857 mparm.fscp_bmnt = nfp;
00858 mparm.fscp_part_type = fcb->fcb_part.part_type;
00859 if (fsdev->dev_ioctl(fsdev, FS_VOL_MOUNT, &mparm)) {
00860 MmCardUnmount(nfp);
00861 return NUTFILE_EOF;
00862 }
00863 return nfp;
00864 }
00865
00874 int MmCardUnmount(NUTFILE * nfp)
00875 {
00876 int rc = -1;
00877
00878 if (nfp) {
00879 MMCFCB *fcb = (MMCFCB *) nfp->nf_fcb;
00880
00881 if (fcb) {
00882 NUTDEVICE *dev = (NUTDEVICE *) nfp->nf_dev;
00883 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00884
00885 if ((*ifc->mmcifc_cd) () == 1) {
00886 rc = fcb->fcb_fsdev->dev_ioctl(fcb->fcb_fsdev, FS_VOL_UNMOUNT, NULL);
00887 }
00888 free(fcb);
00889 }
00890 free(nfp);
00891 }
00892 return rc;
00893 }
00894
00906 static int MmCardGetReg(MMCIFC * ifc, uint8_t cmd, uint8_t * rbp, int siz)
00907 {
00908 int rc = -1;
00909 int retries = MMC_MAX_REG_POLLS;
00910 int i;
00911
00912
00913 NutEventWait(&mutex, 0);
00914
00915 while (retries--) {
00916
00917 MmCardTxCmd(ifc, cmd, 0);
00918
00919 if (MmCardRxR1(ifc) == 0x00) {
00920
00921 if (MmCardRxR1(ifc) == 0xFE) {
00922 for (i = 0; i < siz; i++) {
00923 *rbp++ = (*ifc->mmcifc_io) (0xFF);
00924 }
00925
00926 (*ifc->mmcifc_io) (0xFF);
00927 (*ifc->mmcifc_io) (0xFF);
00928
00929 (*ifc->mmcifc_cs) (0);
00930
00931 rc = 0;
00932 break;
00933 }
00934 }
00935
00936 (*ifc->mmcifc_cs) (0);
00937 }
00938
00939
00940 NutEventPost(&mutex);
00941
00942 return rc;
00943 }
00944
00968 int MmCardIOCtl(NUTDEVICE * dev, int req, void *conf)
00969 {
00970 int rc = 0;
00971 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00972
00973 switch (req) {
00974 case NUTBLKDEV_MEDIAAVAIL:
00975 {
00976 int *flg = (int *) conf;
00977 *flg = (*ifc->mmcifc_cd) ();
00978 }
00979 break;
00980 case NUTBLKDEV_MEDIACHANGE:
00981 {
00982 int *flg = (int *) conf;
00983 if ((*ifc->mmcifc_cd) () != 1) {
00984 *flg = 1;
00985 } else {
00986 *flg = 0;
00987 }
00988 }
00989 break;
00990 case NUTBLKDEV_INFO:
00991 {
00992 BLKPAR_INFO *par = (BLKPAR_INFO *) conf;
00993 MMCFCB *fcb = (MMCFCB *) par->par_nfp->nf_fcb;
00994
00995 par->par_nblks = fcb->fcb_part.part_sects;
00996 par->par_blksz = MMC_BLOCK_SIZE;
00997 par->par_blkbp = fcb->fcb_blkbuf;
00998 }
00999 break;
01000 case NUTBLKDEV_SEEK:
01001 {
01002 BLKPAR_SEEK *par = (BLKPAR_SEEK *) conf;
01003 MMCFCB *fcb = (MMCFCB *) par->par_nfp->nf_fcb;
01004
01005 fcb->fcb_blknum = par->par_blknum;
01006 }
01007 break;
01008 case MMCARD_GETSTATUS:
01009 {
01010 uint16_t *s = (uint16_t *) conf;
01011
01012
01013 NutEventWait(&mutex, 0);
01014
01015 MmCardTxCmd(ifc, MMCMD_SEND_STATUS, 0);
01016 *s = MmCardRxR2(ifc);
01017
01018
01019 NutEventPost(&mutex);
01020 }
01021 break;
01022 case MMCARD_GETOCR:
01023
01024 NutEventWait(&mutex, 0);
01025
01026 MmCardTxCmd(ifc, MMCMD_READ_OCR, 0);
01027 if (MmCardRxR3(ifc, (uint32_t *) conf) != MMR1_IDLE_STATE) {
01028 rc = -1;
01029 }
01030
01031
01032 NutEventPost(&mutex);
01033 break;
01034 case MMCARD_GETCID:
01035 rc = MmCardGetReg(ifc, MMCMD_SEND_CID, (uint8_t *) conf, sizeof(MMC_CID));
01036 break;
01037 case MMCARD_GETCSD:
01038 rc = MmCardGetReg(ifc, MMCMD_SEND_CSD, (uint8_t *) conf, sizeof(MMC_CSD));
01039 break;
01040 default:
01041 rc = -1;
01042 break;
01043 }
01044 return rc;
01045 }
01046
01058 int MmCardDevInit(NUTDEVICE * dev)
01059 {
01060 return 0;
01061 }
01062