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