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
00086 #include <cfg/mmci.h>
00087
00088 #if 0
00089
00090 #define NUTDEBUG
00091 #include <stdio.h>
00092 #endif
00093
00094 #include <errno.h>
00095 #include <string.h>
00096 #include <stdlib.h>
00097
00098 #include <sys/heap.h>
00099 #include <sys/timer.h>
00100 #include <sys/event.h>
00101 #include <fs/dospart.h>
00102 #include <fs/fs.h>
00103
00104 #include <dev/blockdev.h>
00105 #include <dev/mmcard.h>
00106
00111
00112 #ifndef MMC_BLOCK_SIZE
00113
00119 #define MMC_BLOCK_SIZE 512
00120 #endif
00121
00122 #ifndef MMC_MAX_INIT_POLLS
00123
00130 #define MMC_MAX_INIT_POLLS 512
00131 #endif
00132
00133 #ifndef MMC_MAX_RESET_POLLS
00134
00139 #define MMC_MAX_RESET_POLLS 255
00140 #endif
00141
00142 #ifndef MMC_MAX_WRITE_POLLS
00143
00150 #define MMC_MAX_WRITE_POLLS 1024
00151 #endif
00152
00153 #ifndef MMC_MAX_WRITE_RETRIES
00154
00159 #define MMC_MAX_WRITE_RETRIES 32
00160 #endif
00161
00162 #ifndef MMC_MAX_READ_RETRIES
00163
00168 #define MMC_MAX_READ_RETRIES 8
00169 #endif
00170
00171 #ifndef MMC_MAX_REG_POLLS
00172
00177 #define MMC_MAX_REG_POLLS 512
00178 #endif
00179
00180 #ifndef MMC_MAX_CMDACK_POLLS
00181
00188 #define MMC_MAX_CMDACK_POLLS 1024
00189 #endif
00190
00191 #ifndef MMC_MAX_R1_POLLS
00192
00197 #define MMC_MAX_R1_POLLS 1024
00198 #endif
00199
00203 typedef struct _MMCFCB {
00206 NUTDEVICE *fcb_fsdev;
00207
00210 DOSPART fcb_part;
00211
00219 uint32_t fcb_blknum;
00220
00230 uint8_t fcb_blkbuf[MMC_BLOCK_SIZE];
00231 } MMCFCB;
00232
00233
00234
00235
00236
00237
00238 static HANDLE mutex;
00239
00247 static void MmCardTxCmd(MMCIFC * ifc, uint8_t cmd, uint32_t param)
00248 {
00249 u_int tmo = MMC_MAX_CMDACK_POLLS;
00250 uint8_t ch;
00251
00252
00253 (*ifc->mmcifc_cs) (1);
00254
00255
00256
00257
00258
00259 while ((ch = (*ifc->mmcifc_io) (0xFF)) != 0xFF) {
00260 if (--tmo == 0) {
00261 #ifdef NUTDEBUG
00262 printf("[MMCmd%u Timeout %02X]\n", cmd, ch);
00263 #endif
00264 break;
00265 }
00266 if (tmo < MMC_MAX_CMDACK_POLLS / 4) {
00267 NutSleep(1);
00268 }
00269 }
00270
00271 (*ifc->mmcifc_io) (MMCMD_HOST | cmd);
00272 (*ifc->mmcifc_io) ((uint8_t) (param >> 24));
00273 (*ifc->mmcifc_io) ((uint8_t) (param >> 16));
00274 (*ifc->mmcifc_io) ((uint8_t) (param >> 8));
00275 (*ifc->mmcifc_io) ((uint8_t) param);
00276
00277
00278
00279
00280
00281 (*ifc->mmcifc_io) (MMCMD_RESET_CRC);
00282 }
00283
00294 static uint8_t MmCardRxR1(MMCIFC * ifc)
00295 {
00296 uint8_t rc;
00297 int i;
00298
00299 for (i = 0; i < MMC_MAX_R1_POLLS; i++) {
00300 if ((rc = (*ifc->mmcifc_io) (0xFF)) != 0xFF) {
00301 break;
00302 }
00303 }
00304 return rc;
00305 }
00306
00317 static uint16_t MmCardRxR2(MMCIFC * ifc)
00318 {
00319 uint16_t rc;
00320
00321 rc = MmCardRxR1(ifc);
00322 rc <<= 8;
00323 rc += (*ifc->mmcifc_io) (0xFF);
00324
00325 return rc;
00326 }
00327
00339 static uint8_t MmCardRxR3(MMCIFC * ifc, uint32_t * ocr)
00340 {
00341 uint8_t rc;
00342 int i;
00343
00344
00345 rc = MmCardRxR1(ifc);
00346
00347 for (i = 0; i < 4; i++) {
00348 *ocr <<= 8;
00349 *ocr |= (*ifc->mmcifc_io) (0xFF);
00350 }
00351 return rc;
00352 }
00353
00361 static int MmCardReset(MMCIFC * ifc)
00362 {
00363 int i;
00364 uint8_t rsp;
00365
00366
00367
00368
00369 if ((*ifc->mmcifc_in) ()) {
00370 return -1;
00371 }
00372
00373
00374
00375
00376
00377 (*ifc->mmcifc_cs) (0);
00378 for (i = 0; i < 10; i++) {
00379 (*ifc->mmcifc_io) (0xFF);
00380 }
00381
00382
00383
00384
00385
00386 for (i = 0; i < MMC_MAX_RESET_POLLS; i++) {
00387 MmCardTxCmd(ifc, MMCMD_GO_IDLE_STATE, 0);
00388 rsp = MmCardRxR1(ifc);
00389 (*ifc->mmcifc_cs) (0);
00390 if (rsp == MMR1_IDLE_STATE || rsp == MMR1_NOT_IDLE) {
00391 return 0;
00392 }
00393 }
00394 return -1;
00395 }
00396
00407 static int MmCardInit(MMCIFC * ifc)
00408 {
00409 int i;
00410 uint8_t rsp;
00411
00412
00413
00414
00415
00416 if (MmCardReset(ifc)) {
00417 if (MmCardReset(ifc)) {
00418 #ifdef NUTDEBUG
00419 printf("[CardReset failed]");
00420 #endif
00421 return -1;
00422 }
00423 }
00424
00425
00426
00427
00428
00429 for (i = 0; i < MMC_MAX_INIT_POLLS; i++) {
00430
00431
00432
00433
00434
00435 MmCardTxCmd(ifc, MMCMD_SEND_OP_COND, 0);
00436 rsp = MmCardRxR1(ifc);
00437 (*ifc->mmcifc_cs) (0);
00438 if (rsp == MMR1_IDLE_STATE) {
00439 #ifdef NUTDEBUG
00440 printf("[CardIdle]");
00441 #endif
00442
00443 NutEventPost(&mutex);
00444 return 0;
00445 }
00446 if (i > MMC_MAX_INIT_POLLS / 4) {
00447 NutSleep(1);
00448 }
00449 }
00450 #ifdef NUTDEBUG
00451 printf("[CardInit failed]");
00452 #endif
00453 return -1;
00454 }
00455
00466 static int MmCardReadOrVerify(MMCIFC * ifc, uint32_t blk, uint8_t * buf, int vflg)
00467 {
00468 int rc = -1;
00469 int retries = 64;
00470 int i;
00471 uint8_t rsp;
00472
00473
00474 NutEventWait(&mutex, 0);
00475
00476 while (retries--) {
00477 MmCardTxCmd(ifc, MMCMD_READ_SINGLE_BLOCK, blk << 9);
00478 if ((rsp = MmCardRxR1(ifc)) == 0x00) {
00479 if ((rsp = MmCardRxR1(ifc)) == 0xFE) {
00480 rc = 0;
00481 if (vflg) {
00482 for (i = 0; i < MMC_BLOCK_SIZE; i++) {
00483 if (*buf != (*ifc->mmcifc_io) (0xFF)) {
00484 rc = -1;
00485 }
00486 buf++;
00487 }
00488 } else {
00489 for (i = 0; i < MMC_BLOCK_SIZE; i++) {
00490 *buf = (*ifc->mmcifc_io) (0xFF);
00491 buf++;
00492 }
00493 }
00494 (*ifc->mmcifc_io) (0xff);
00495 (*ifc->mmcifc_io) (0xff);
00496 (*ifc->mmcifc_cs) (0);
00497 break;
00498 }
00499 }
00500 (*ifc->mmcifc_cs) (0);
00501 }
00502
00503
00504 NutEventPost(&mutex);
00505
00506 return rc;
00507 }
00508
00518 static int MmCardWrite(MMCIFC * ifc, uint32_t blk, CONST uint8_t * buf)
00519 {
00520 int rc = -1;
00521 int retries = MMC_MAX_WRITE_RETRIES;
00522 int tmo;
00523 int i;
00524 uint8_t rsp;
00525
00526
00527 NutEventWait(&mutex, 0);
00528
00529 while (retries--) {
00530 MmCardTxCmd(ifc, MMCMD_WRITE_BLOCK, blk << 9);
00531 if ((rsp = MmCardRxR1(ifc)) == 0x00) {
00532 (*ifc->mmcifc_io) (0xFF);
00533 (*ifc->mmcifc_io) (0xFE);
00534 for (i = 0; i < MMC_BLOCK_SIZE; i++) {
00535 (*ifc->mmcifc_io) (*buf);
00536 buf++;
00537 }
00538
00539
00540 if ((rsp = MmCardRxR1(ifc)) == 0xE5) {
00541 for (tmo = 0; tmo < MMC_MAX_WRITE_POLLS; tmo++) {
00542 if ((*ifc->mmcifc_io) (0xFF) == 0xFF) {
00543 break;
00544 }
00545 if (tmo > MMC_MAX_WRITE_POLLS - MMC_MAX_WRITE_POLLS / 32) {
00546 NutSleep(1);
00547 }
00548 }
00549 if (tmo) {
00550 rc = 0;
00551 break;
00552 }
00553 #ifdef NUTDEBUG
00554 printf("[MMCWR Timeout]\n");
00555 #endif
00556 }
00557 }
00558 (*ifc->mmcifc_cs) (0);
00559 }
00560 (*ifc->mmcifc_cs) (0);
00561
00562
00563 NutEventPost(&mutex);
00564
00565 return rc;
00566 }
00567
00583 int MmCardBlockRead(NUTFILE * nfp, void *buffer, int num)
00584 {
00585 MMCFCB *fcb = (MMCFCB *) nfp->nf_fcb;
00586 uint32_t blk = fcb->fcb_blknum;
00587 NUTDEVICE *dev = (NUTDEVICE *) nfp->nf_dev;
00588 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00589
00590 if ((*ifc->mmcifc_cd) () != 1) {
00591 return -1;
00592 }
00593 if (buffer == 0) {
00594 buffer = fcb->fcb_blkbuf;
00595 }
00596 blk += fcb->fcb_part.part_sect_offs;
00597
00598 #ifdef MMC_VERIFY_AFTER
00599 {
00600 int i;
00601
00602
00603
00604
00605 for (i = 0; i < MMC_MAX_READ_RETRIES; i++) {
00606 if (MmCardReadOrVerify(ifc, blk, buffer, 0) == 0) {
00607 if (MmCardReadOrVerify(ifc, blk, buffer, 1) == 0) {
00608 return 1;
00609 }
00610 }
00611 }
00612 }
00613 #else
00614 if (MmCardReadOrVerify(ifc, blk, buffer, 0) == 0) {
00615 return 1;
00616 }
00617 #endif
00618 return -1;
00619 }
00620
00636 int MmCardBlockWrite(NUTFILE * nfp, CONST void *buffer, int num)
00637 {
00638 MMCFCB *fcb = (MMCFCB *) nfp->nf_fcb;
00639 uint32_t blk = fcb->fcb_blknum;
00640 NUTDEVICE *dev = (NUTDEVICE *) nfp->nf_dev;
00641 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00642
00643 if ((*ifc->mmcifc_cd) () != 1) {
00644 return -1;
00645 }
00646 if (buffer == 0) {
00647 buffer = fcb->fcb_blkbuf;
00648 }
00649 blk += fcb->fcb_part.part_sect_offs;
00650
00651 #ifdef MMC_VERIFY_AFTER
00652 {
00653 int i;
00654
00655 for (i = 0; i < MMC_MAX_READ_RETRIES; i++) {
00656 if (MmCardWrite(ifc, blk, buffer) == 0) {
00657 if (MmCardReadOrVerify(ifc, blk, (void *) buffer, 1) == 0) {
00658 return 1;
00659 }
00660 if (MmCardReadOrVerify(ifc, blk, (void *) buffer, 1) == 0) {
00661 return 1;
00662 }
00663 }
00664 }
00665 }
00666 #else
00667 if (MmCardWrite(ifc, blk, buffer) == 0) {
00668 return 1;
00669 }
00670 #endif
00671 return -1;
00672 }
00673
00674 #ifdef __HARVARD_ARCH__
00675
00694 int MmCardBlockWrite_P(NUTFILE * nfp, PGM_P buffer, int num)
00695 {
00696 return -1;
00697 }
00698 #endif
00699
00725 NUTFILE *MmCardMount(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00726 {
00727 int partno = 0;
00728 int i;
00729 NUTDEVICE *fsdev;
00730 NUTFILE *nfp;
00731 MMCFCB *fcb;
00732 DOSPART *part;
00733 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00734 FSCP_VOL_MOUNT mparm;
00735
00736
00737 if ((*ifc->mmcifc_cd) () == 0) {
00738 errno = ENODEV;
00739 return NUTFILE_EOF;
00740 }
00741
00742
00743 if (MmCardInit(ifc)) {
00744 errno = ENODEV;
00745 return NUTFILE_EOF;
00746 }
00747
00748
00749 if (*name) {
00750 partno = atoi(name);
00751 do {
00752 name++;
00753 } while (*name && *name != '/');
00754 if (*name == '/') {
00755 name++;
00756 }
00757 }
00758
00759
00760
00761
00762
00763
00764
00765 for (fsdev = nutDeviceList; fsdev; fsdev = fsdev->dev_next) {
00766 if (*name == 0) {
00767 if (fsdev->dev_type == IFTYP_FS) {
00768 break;
00769 }
00770 } else if (strcmp(fsdev->dev_name, name) == 0) {
00771 break;
00772 }
00773 }
00774
00775 if (fsdev == 0) {
00776 #ifdef NUTDEBUG
00777 printf("[No FSDriver]");
00778 #endif
00779 errno = ENODEV;
00780 return NUTFILE_EOF;
00781 }
00782
00783 if ((fcb = NutHeapAllocClear(sizeof(MMCFCB))) == 0) {
00784 errno = ENOMEM;
00785 return NUTFILE_EOF;
00786 }
00787 fcb->fcb_fsdev = fsdev;
00788
00789
00790 if (MmCardReadOrVerify(ifc, 0, fcb->fcb_blkbuf, 0)) {
00791 NutHeapFree(fcb);
00792 return NUTFILE_EOF;
00793 }
00794
00795 if (fcb->fcb_blkbuf[DOSPART_MAGICPOS] != 0x55 || fcb->fcb_blkbuf[DOSPART_MAGICPOS + 1] != 0xAA) {
00796 NutHeapFree(fcb);
00797 return NUTFILE_EOF;
00798 }
00799
00800 if(fcb->fcb_blkbuf[DOSPART_TYPEPOS] == 'F' &&
00801 fcb->fcb_blkbuf[DOSPART_TYPEPOS + 1] == 'A' &&
00802 fcb->fcb_blkbuf[DOSPART_TYPEPOS + 2] == 'T') {
00803
00804 fcb->fcb_part.part_type = PTYPE_FAT12;
00805 fcb->fcb_part.part_sect_offs = 0;
00806 fcb->fcb_part.part_sects = 65536;
00807 }
00808 else {
00809
00810 part = (DOSPART *) & fcb->fcb_blkbuf[DOSPART_SECTORPOS];
00811 for (i = 1; i <= 4; i++) {
00812 if (partno) {
00813 if (i == partno) {
00814
00815 fcb->fcb_part = *part;
00816 break;
00817 }
00818 } else if (part->part_state & 0x80) {
00819
00820 fcb->fcb_part = *part;
00821 break;
00822 }
00823 part++;
00824 }
00825
00826 if (fcb->fcb_part.part_type == PTYPE_EMPTY) {
00827 NutHeapFree(fcb);
00828 return NUTFILE_EOF;
00829 }
00830 }
00831
00832 if ((nfp = NutHeapAlloc(sizeof(NUTFILE))) == 0) {
00833 NutHeapFree(fcb);
00834 errno = ENOMEM;
00835 return NUTFILE_EOF;
00836 }
00837 nfp->nf_next = 0;
00838 nfp->nf_dev = dev;
00839 nfp->nf_fcb = fcb;
00840
00841
00842
00843
00844 mparm.fscp_bmnt = nfp;
00845 mparm.fscp_part_type = fcb->fcb_part.part_type;
00846 if (fsdev->dev_ioctl(fsdev, FS_VOL_MOUNT, &mparm)) {
00847 MmCardUnmount(nfp);
00848 return NUTFILE_EOF;
00849 }
00850 return nfp;
00851 }
00852
00861 int MmCardUnmount(NUTFILE * nfp)
00862 {
00863 int rc = -1;
00864
00865 if (nfp) {
00866 MMCFCB *fcb = (MMCFCB *) nfp->nf_fcb;
00867
00868 if (fcb) {
00869 NUTDEVICE *dev = (NUTDEVICE *) nfp->nf_dev;
00870 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00871
00872 if ((*ifc->mmcifc_cd) () == 1) {
00873 rc = fcb->fcb_fsdev->dev_ioctl(fcb->fcb_fsdev, FS_VOL_UNMOUNT, NULL);
00874 }
00875 NutHeapFree(fcb);
00876 }
00877 NutHeapFree(nfp);
00878 }
00879 return rc;
00880 }
00881
00893 static int MmCardGetReg(MMCIFC * ifc, uint8_t cmd, uint8_t * rbp, int siz)
00894 {
00895 int rc = -1;
00896 int retries = MMC_MAX_REG_POLLS;
00897 int i;
00898
00899
00900 NutEventWait(&mutex, 0);
00901
00902 while (retries--) {
00903
00904 MmCardTxCmd(ifc, cmd, 0);
00905
00906 if (MmCardRxR1(ifc) == 0x00) {
00907
00908 if (MmCardRxR1(ifc) == 0xFE) {
00909 for (i = 0; i < siz; i++) {
00910 *rbp++ = (*ifc->mmcifc_io) (0xFF);
00911 }
00912
00913 (*ifc->mmcifc_io) (0xFF);
00914 (*ifc->mmcifc_io) (0xFF);
00915
00916 (*ifc->mmcifc_cs) (0);
00917
00918 rc = 0;
00919 break;
00920 }
00921 }
00922
00923 (*ifc->mmcifc_cs) (0);
00924 }
00925
00926
00927 NutEventPost(&mutex);
00928
00929 return rc;
00930 }
00931
00955 int MmCardIOCtl(NUTDEVICE * dev, int req, void *conf)
00956 {
00957 int rc = 0;
00958 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00959
00960 switch (req) {
00961 case NUTBLKDEV_MEDIAAVAIL:
00962 {
00963 int *flg = (int *) conf;
00964 *flg = (*ifc->mmcifc_cd) ();
00965 }
00966 break;
00967 case NUTBLKDEV_MEDIACHANGE:
00968 {
00969 int *flg = (int *) conf;
00970 if ((*ifc->mmcifc_cd) () != 1) {
00971 *flg = 1;
00972 } else {
00973 *flg = 0;
00974 }
00975 }
00976 break;
00977 case NUTBLKDEV_INFO:
00978 {
00979 BLKPAR_INFO *par = (BLKPAR_INFO *) conf;
00980 MMCFCB *fcb = (MMCFCB *) par->par_nfp->nf_fcb;
00981
00982 par->par_nblks = fcb->fcb_part.part_sects;
00983 par->par_blksz = MMC_BLOCK_SIZE;
00984 par->par_blkbp = fcb->fcb_blkbuf;
00985 }
00986 break;
00987 case NUTBLKDEV_SEEK:
00988 {
00989 BLKPAR_SEEK *par = (BLKPAR_SEEK *) conf;
00990 MMCFCB *fcb = (MMCFCB *) par->par_nfp->nf_fcb;
00991
00992 fcb->fcb_blknum = par->par_blknum;
00993 }
00994 break;
00995 case MMCARD_GETSTATUS:
00996 {
00997 uint16_t *s = (uint16_t *) conf;
00998
00999
01000 NutEventWait(&mutex, 0);
01001
01002 MmCardTxCmd(ifc, MMCMD_SEND_STATUS, 0);
01003 *s = MmCardRxR2(ifc);
01004
01005
01006 NutEventPost(&mutex);
01007 }
01008 break;
01009 case MMCARD_GETOCR:
01010
01011 NutEventWait(&mutex, 0);
01012
01013 MmCardTxCmd(ifc, MMCMD_READ_OCR, 0);
01014 if (MmCardRxR3(ifc, (uint32_t *) conf) != MMR1_IDLE_STATE) {
01015 rc = -1;
01016 }
01017
01018
01019 NutEventPost(&mutex);
01020 break;
01021 case MMCARD_GETCID:
01022 rc = MmCardGetReg(ifc, MMCMD_SEND_CID, (uint8_t *) conf, sizeof(MMC_CID));
01023 break;
01024 case MMCARD_GETCSD:
01025 rc = MmCardGetReg(ifc, MMCMD_SEND_CSD, (uint8_t *) conf, sizeof(MMC_CSD));
01026 break;
01027 default:
01028 rc = -1;
01029 break;
01030 }
01031 return rc;
01032 }
01033
01045 int MmCardDevInit(NUTDEVICE * dev)
01046 {
01047 return 0;
01048 }
01049