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
00080 #include <cfg/mmci.h>
00081
00082 #if 0
00083
00084 #define NUTDEBUG
00085 #include <stdio.h>
00086 #endif
00087
00088 #include <errno.h>
00089 #include <string.h>
00090 #include <stdlib.h>
00091
00092 #include <sys/heap.h>
00093 #include <sys/timer.h>
00094 #include <sys/event.h>
00095 #include <fs/dospart.h>
00096 #include <fs/fs.h>
00097
00098 #include <dev/blockdev.h>
00099 #include <dev/mmcard.h>
00100
00105
00106 #ifndef MMC_BLOCK_SIZE
00107
00113 #define MMC_BLOCK_SIZE 512
00114 #endif
00115
00116 #ifndef MMC_MAX_INIT_POLLS
00117
00124 #define MMC_MAX_INIT_POLLS 512
00125 #endif
00126
00127 #ifndef MMC_MAX_RESET_POLLS
00128
00133 #define MMC_MAX_RESET_POLLS 255
00134 #endif
00135
00136 #ifndef MMC_MAX_WRITE_POLLS
00137
00144 #define MMC_MAX_WRITE_POLLS 1024
00145 #endif
00146
00147 #ifndef MMC_MAX_WRITE_RETRIES
00148
00153 #define MMC_MAX_WRITE_RETRIES 32
00154 #endif
00155
00156 #ifndef MMC_MAX_READ_RETRIES
00157
00162 #define MMC_MAX_READ_RETRIES 8
00163 #endif
00164
00165 #ifndef MMC_MAX_REG_POLLS
00166
00171 #define MMC_MAX_REG_POLLS 512
00172 #endif
00173
00174 #ifndef MMC_MAX_CMDACK_POLLS
00175
00182 #define MMC_MAX_CMDACK_POLLS 1024
00183 #endif
00184
00185 #ifndef MMC_MAX_R1_POLLS
00186
00191 #define MMC_MAX_R1_POLLS 1024
00192 #endif
00193
00197 typedef struct _MMCFCB {
00200 NUTDEVICE *fcb_fsdev;
00201
00204 DOSPART fcb_part;
00205
00213 u_long fcb_blknum;
00214
00224 u_char fcb_blkbuf[MMC_BLOCK_SIZE];
00225 } MMCFCB;
00226
00227
00228
00229
00230
00231
00232 static HANDLE mutex;
00233
00241 static void MmCardTxCmd(MMCIFC * ifc, u_char cmd, u_long param)
00242 {
00243 u_int tmo = MMC_MAX_CMDACK_POLLS;
00244 u_char ch;
00245
00246
00247 (*ifc->mmcifc_cs) (1);
00248
00249
00250
00251
00252
00253 while ((ch = (*ifc->mmcifc_io) (0xFF)) != 0xFF) {
00254 if (--tmo == 0) {
00255 #ifdef NUTDEBUG
00256 printf("[MMCmd%u Timeout %02X]\n", cmd, ch);
00257 #endif
00258 break;
00259 }
00260 if (tmo < MMC_MAX_CMDACK_POLLS / 4) {
00261 NutSleep(1);
00262 }
00263 }
00264
00265 (*ifc->mmcifc_io) (MMCMD_HOST | cmd);
00266 (*ifc->mmcifc_io) ((u_char) (param >> 24));
00267 (*ifc->mmcifc_io) ((u_char) (param >> 16));
00268 (*ifc->mmcifc_io) ((u_char) (param >> 8));
00269 (*ifc->mmcifc_io) ((u_char) param);
00270
00271
00272
00273
00274
00275 (*ifc->mmcifc_io) (MMCMD_RESET_CRC);
00276 }
00277
00288 static u_char MmCardRxR1(MMCIFC * ifc)
00289 {
00290 u_char rc;
00291 int i;
00292
00293 for (i = 0; i < MMC_MAX_R1_POLLS; i++) {
00294 if ((rc = (*ifc->mmcifc_io) (0xFF)) != 0xFF) {
00295 break;
00296 }
00297 }
00298 return rc;
00299 }
00300
00311 static u_short MmCardRxR2(MMCIFC * ifc)
00312 {
00313 u_short rc;
00314
00315 rc = MmCardRxR1(ifc);
00316 rc <<= 8;
00317 rc += (*ifc->mmcifc_io) (0xFF);
00318
00319 return rc;
00320 }
00321
00333 static u_char MmCardRxR3(MMCIFC * ifc, u_long * ocr)
00334 {
00335 u_char rc;
00336 int i;
00337
00338
00339 rc = MmCardRxR1(ifc);
00340
00341 for (i = 0; i < 4; i++) {
00342 *ocr <<= 8;
00343 *ocr |= (*ifc->mmcifc_io) (0xFF);
00344 }
00345 return rc;
00346 }
00347
00355 static int MmCardReset(MMCIFC * ifc)
00356 {
00357 int i;
00358 u_char rsp;
00359
00360
00361
00362
00363 if ((*ifc->mmcifc_in) ()) {
00364 return -1;
00365 }
00366
00367
00368
00369
00370
00371 (*ifc->mmcifc_cs) (0);
00372 for (i = 0; i < 10; i++) {
00373 (*ifc->mmcifc_io) (0xFF);
00374 }
00375
00376
00377
00378
00379
00380 for (i = 0; i < MMC_MAX_RESET_POLLS; i++) {
00381 MmCardTxCmd(ifc, MMCMD_GO_IDLE_STATE, 0);
00382 rsp = MmCardRxR1(ifc);
00383 (*ifc->mmcifc_cs) (0);
00384 if (rsp == MMR1_IDLE_STATE || rsp == MMR1_NOT_IDLE) {
00385 return 0;
00386 }
00387 }
00388 return -1;
00389 }
00390
00401 static int MmCardInit(MMCIFC * ifc)
00402 {
00403 int i;
00404 u_char rsp;
00405
00406
00407
00408
00409
00410 if (MmCardReset(ifc)) {
00411 if (MmCardReset(ifc)) {
00412 #ifdef NUTDEBUG
00413 printf("[CardReset failed]");
00414 #endif
00415 return -1;
00416 }
00417 }
00418
00419
00420
00421
00422
00423 for (i = 0; i < MMC_MAX_INIT_POLLS; i++) {
00424
00425
00426
00427
00428
00429 MmCardTxCmd(ifc, MMCMD_SEND_OP_COND, 0);
00430 rsp = MmCardRxR1(ifc);
00431 (*ifc->mmcifc_cs) (0);
00432 if (rsp == MMR1_IDLE_STATE) {
00433 #ifdef NUTDEBUG
00434 printf("[CardIdle]");
00435 #endif
00436
00437 NutEventPost(&mutex);
00438 return 0;
00439 }
00440 if (i > MMC_MAX_INIT_POLLS / 4) {
00441 NutSleep(1);
00442 }
00443 }
00444 #ifdef NUTDEBUG
00445 printf("[CardInit failed]");
00446 #endif
00447 return -1;
00448 }
00449
00460 static int MmCardReadOrVerify(MMCIFC * ifc, u_long blk, u_char * buf, int vflg)
00461 {
00462 int rc = -1;
00463 int retries = 64;
00464 int i;
00465 u_char rsp;
00466
00467
00468 NutEventWait(&mutex, 0);
00469
00470 while (retries--) {
00471 MmCardTxCmd(ifc, MMCMD_READ_SINGLE_BLOCK, blk << 9);
00472 if ((rsp = MmCardRxR1(ifc)) == 0x00) {
00473 if ((rsp = MmCardRxR1(ifc)) == 0xFE) {
00474 rc = 0;
00475 if (vflg) {
00476 for (i = 0; i < MMC_BLOCK_SIZE; i++) {
00477 if (*buf != (*ifc->mmcifc_io) (0xFF)) {
00478 rc = -1;
00479 }
00480 buf++;
00481 }
00482 } else {
00483 for (i = 0; i < MMC_BLOCK_SIZE; i++) {
00484 *buf = (*ifc->mmcifc_io) (0xFF);
00485 buf++;
00486 }
00487 }
00488 (*ifc->mmcifc_io) (0xff);
00489 (*ifc->mmcifc_io) (0xff);
00490 (*ifc->mmcifc_cs) (0);
00491 break;
00492 }
00493 }
00494 (*ifc->mmcifc_cs) (0);
00495 }
00496
00497
00498 NutEventPost(&mutex);
00499
00500 return rc;
00501 }
00502
00512 static int MmCardWrite(MMCIFC * ifc, u_long blk, CONST u_char * buf)
00513 {
00514 int rc = -1;
00515 int retries = MMC_MAX_WRITE_RETRIES;
00516 int tmo;
00517 int i;
00518 u_char rsp;
00519
00520
00521 NutEventWait(&mutex, 0);
00522
00523 while (retries--) {
00524 MmCardTxCmd(ifc, MMCMD_WRITE_BLOCK, blk << 9);
00525 if ((rsp = MmCardRxR1(ifc)) == 0x00) {
00526 (*ifc->mmcifc_io) (0xFF);
00527 (*ifc->mmcifc_io) (0xFE);
00528 for (i = 0; i < MMC_BLOCK_SIZE; i++) {
00529 (*ifc->mmcifc_io) (*buf);
00530 buf++;
00531 }
00532
00533
00534 if ((rsp = MmCardRxR1(ifc)) == 0xE5) {
00535 for (tmo = 0; tmo < MMC_MAX_WRITE_POLLS; tmo++) {
00536 if ((*ifc->mmcifc_io) (0xFF) == 0xFF) {
00537 break;
00538 }
00539 if (tmo > MMC_MAX_WRITE_POLLS - MMC_MAX_WRITE_POLLS / 32) {
00540 NutSleep(1);
00541 }
00542 }
00543 if (tmo) {
00544 rc = 0;
00545 break;
00546 }
00547 #ifdef NUTDEBUG
00548 printf("[MMCWR Timeout]\n");
00549 #endif
00550 }
00551 }
00552 (*ifc->mmcifc_cs) (0);
00553 }
00554 (*ifc->mmcifc_cs) (0);
00555
00556
00557 NutEventPost(&mutex);
00558
00559 return rc;
00560 }
00561
00577 int MmCardBlockRead(NUTFILE * nfp, void *buffer, int num)
00578 {
00579 MMCFCB *fcb = (MMCFCB *) nfp->nf_fcb;
00580 u_long blk = fcb->fcb_blknum;
00581 NUTDEVICE *dev = (NUTDEVICE *) nfp->nf_dev;
00582 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00583
00584 if ((*ifc->mmcifc_cd) () != 1) {
00585 return -1;
00586 }
00587 if (buffer == 0) {
00588 buffer = fcb->fcb_blkbuf;
00589 }
00590 blk += fcb->fcb_part.part_sect_offs;
00591
00592 #ifdef MMC_VERIFY_AFTER
00593 {
00594 int i;
00595
00596
00597
00598
00599 for (i = 0; i < MMC_MAX_READ_RETRIES; i++) {
00600 if (MmCardReadOrVerify(ifc, blk, buffer, 0) == 0) {
00601 if (MmCardReadOrVerify(ifc, blk, buffer, 1) == 0) {
00602 return 1;
00603 }
00604 }
00605 }
00606 }
00607 #else
00608 if (MmCardReadOrVerify(ifc, blk, buffer, 0) == 0) {
00609 return 1;
00610 }
00611 #endif
00612 return -1;
00613 }
00614
00630 int MmCardBlockWrite(NUTFILE * nfp, CONST void *buffer, int num)
00631 {
00632 MMCFCB *fcb = (MMCFCB *) nfp->nf_fcb;
00633 u_long blk = fcb->fcb_blknum;
00634 NUTDEVICE *dev = (NUTDEVICE *) nfp->nf_dev;
00635 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00636
00637 if ((*ifc->mmcifc_cd) () != 1) {
00638 return -1;
00639 }
00640 if (buffer == 0) {
00641 buffer = fcb->fcb_blkbuf;
00642 }
00643 blk += fcb->fcb_part.part_sect_offs;
00644
00645 #ifdef MMC_VERIFY_AFTER
00646 {
00647 int i;
00648
00649 for (i = 0; i < MMC_MAX_READ_RETRIES; i++) {
00650 if (MmCardWrite(ifc, blk, buffer) == 0) {
00651 if (MmCardReadOrVerify(ifc, blk, (void *) buffer, 1) == 0) {
00652 return 1;
00653 }
00654 if (MmCardReadOrVerify(ifc, blk, (void *) buffer, 1) == 0) {
00655 return 1;
00656 }
00657 }
00658 }
00659 }
00660 #else
00661 if (MmCardWrite(ifc, blk, buffer) == 0) {
00662 return 1;
00663 }
00664 #endif
00665 return -1;
00666 }
00667
00668 #ifdef __HARVARD_ARCH__
00669
00688 int MmCardBlockWrite_P(NUTFILE * nfp, PGM_P buffer, int num)
00689 {
00690 return -1;
00691 }
00692 #endif
00693
00719 NUTFILE *MmCardMount(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00720 {
00721 int partno = 0;
00722 int i;
00723 NUTDEVICE *fsdev;
00724 NUTFILE *nfp;
00725 MMCFCB *fcb;
00726 DOSPART *part;
00727 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00728 FSCP_VOL_MOUNT mparm;
00729
00730
00731 if ((*ifc->mmcifc_cd) () == 0) {
00732 errno = ENODEV;
00733 return NUTFILE_EOF;
00734 }
00735
00736
00737 if (MmCardInit(ifc)) {
00738 errno = ENODEV;
00739 return NUTFILE_EOF;
00740 }
00741
00742
00743 if (*name) {
00744 partno = atoi(name);
00745 do {
00746 name++;
00747 } while (*name && *name != '/');
00748 if (*name == '/') {
00749 name++;
00750 }
00751 }
00752
00753
00754
00755
00756
00757
00758
00759 for (fsdev = nutDeviceList; fsdev; fsdev = fsdev->dev_next) {
00760 if (*name == 0) {
00761 if (fsdev->dev_type == IFTYP_FS) {
00762 break;
00763 }
00764 } else if (strcmp(fsdev->dev_name, name) == 0) {
00765 break;
00766 }
00767 }
00768
00769 if (fsdev == 0) {
00770 #ifdef NUTDEBUG
00771 printf("[No FSDriver]");
00772 #endif
00773 errno = ENODEV;
00774 return NUTFILE_EOF;
00775 }
00776
00777 if ((fcb = NutHeapAllocClear(sizeof(MMCFCB))) == 0) {
00778 errno = ENOMEM;
00779 return NUTFILE_EOF;
00780 }
00781 fcb->fcb_fsdev = fsdev;
00782
00783
00784 if (MmCardReadOrVerify(ifc, 0, fcb->fcb_blkbuf, 0)) {
00785 NutHeapFree(fcb);
00786 return NUTFILE_EOF;
00787 }
00788
00789
00790 part = (DOSPART *) & fcb->fcb_blkbuf[DOSPART_SECTORPOS];
00791 for (i = 1; i <= 4; i++) {
00792 if (partno) {
00793 if (i == partno) {
00794
00795 fcb->fcb_part = *part;
00796 break;
00797 }
00798 } else if (part->part_state & 0x80) {
00799
00800 fcb->fcb_part = *part;
00801 break;
00802 }
00803 part++;
00804 }
00805
00806 if (fcb->fcb_part.part_type == PTYPE_EMPTY) {
00807 NutHeapFree(fcb);
00808 return NUTFILE_EOF;
00809 }
00810
00811 if ((nfp = NutHeapAlloc(sizeof(NUTFILE))) == 0) {
00812 NutHeapFree(fcb);
00813 errno = ENOMEM;
00814 return NUTFILE_EOF;
00815 }
00816 nfp->nf_next = 0;
00817 nfp->nf_dev = dev;
00818 nfp->nf_fcb = fcb;
00819
00820
00821
00822
00823 mparm.fscp_bmnt = nfp;
00824 mparm.fscp_part_type = fcb->fcb_part.part_type;
00825 if (fsdev->dev_ioctl(fsdev, FS_VOL_MOUNT, &mparm)) {
00826 MmCardUnmount(nfp);
00827 return NUTFILE_EOF;
00828 }
00829 return nfp;
00830 }
00831
00840 int MmCardUnmount(NUTFILE * nfp)
00841 {
00842 int rc = -1;
00843
00844 if (nfp) {
00845 MMCFCB *fcb = (MMCFCB *) nfp->nf_fcb;
00846
00847 if (fcb) {
00848 NUTDEVICE *dev = (NUTDEVICE *) nfp->nf_dev;
00849 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00850
00851 if ((*ifc->mmcifc_cd) () == 1) {
00852 rc = fcb->fcb_fsdev->dev_ioctl(fcb->fcb_fsdev, FS_VOL_UNMOUNT, NULL);
00853 }
00854 NutHeapFree(fcb);
00855 }
00856 NutHeapFree(nfp);
00857 }
00858 return rc;
00859 }
00860
00872 static int MmCardGetReg(MMCIFC * ifc, u_char cmd, u_char * rbp, int siz)
00873 {
00874 int rc = -1;
00875 int retries = MMC_MAX_REG_POLLS;
00876 int i;
00877
00878
00879 NutEventWait(&mutex, 0);
00880
00881 while (retries--) {
00882
00883 MmCardTxCmd(ifc, cmd, 0);
00884
00885 if (MmCardRxR1(ifc) == 0x00) {
00886
00887 if (MmCardRxR1(ifc) == 0xFE) {
00888 for (i = 0; i < siz; i++) {
00889 *rbp++ = (*ifc->mmcifc_io) (0xFF);
00890 }
00891
00892 (*ifc->mmcifc_io) (0xFF);
00893 (*ifc->mmcifc_io) (0xFF);
00894
00895 (*ifc->mmcifc_cs) (0);
00896
00897 rc = 0;
00898 break;
00899 }
00900 }
00901
00902 (*ifc->mmcifc_cs) (0);
00903 }
00904
00905
00906 NutEventPost(&mutex);
00907
00908 return rc;
00909 }
00910
00934 int MmCardIOCtl(NUTDEVICE * dev, int req, void *conf)
00935 {
00936 int rc = 0;
00937 MMCIFC *ifc = (MMCIFC *) dev->dev_icb;
00938
00939 switch (req) {
00940 case NUTBLKDEV_MEDIAAVAIL:
00941 {
00942 int *flg = (int *) conf;
00943 *flg = (*ifc->mmcifc_cd) ();
00944 }
00945 break;
00946 case NUTBLKDEV_MEDIACHANGE:
00947 {
00948 int *flg = (int *) conf;
00949 if ((*ifc->mmcifc_cd) () != 1) {
00950 *flg = 1;
00951 } else {
00952 *flg = 0;
00953 }
00954 }
00955 break;
00956 case NUTBLKDEV_INFO:
00957 {
00958 BLKPAR_INFO *par = (BLKPAR_INFO *) conf;
00959 MMCFCB *fcb = (MMCFCB *) par->par_nfp->nf_fcb;
00960
00961 par->par_nblks = fcb->fcb_part.part_sects;
00962 par->par_blksz = MMC_BLOCK_SIZE;
00963 par->par_blkbp = fcb->fcb_blkbuf;
00964 }
00965 break;
00966 case NUTBLKDEV_SEEK:
00967 {
00968 BLKPAR_SEEK *par = (BLKPAR_SEEK *) conf;
00969 MMCFCB *fcb = (MMCFCB *) par->par_nfp->nf_fcb;
00970
00971 fcb->fcb_blknum = par->par_blknum;
00972 }
00973 break;
00974 case MMCARD_GETSTATUS:
00975 {
00976 u_short *s = (u_short *) conf;
00977
00978
00979 NutEventWait(&mutex, 0);
00980
00981 MmCardTxCmd(ifc, MMCMD_SEND_STATUS, 0);
00982 *s = MmCardRxR2(ifc);
00983
00984
00985 NutEventPost(&mutex);
00986 }
00987 break;
00988 case MMCARD_GETOCR:
00989
00990 NutEventWait(&mutex, 0);
00991
00992 MmCardTxCmd(ifc, MMCMD_READ_OCR, 0);
00993 if (MmCardRxR3(ifc, (u_long *) conf) != MMR1_IDLE_STATE) {
00994 rc = -1;
00995 }
00996
00997
00998 NutEventPost(&mutex);
00999 break;
01000 case MMCARD_GETCID:
01001 rc = MmCardGetReg(ifc, MMCMD_SEND_CID, (u_char *) conf, sizeof(MMC_CID));
01002 break;
01003 case MMCARD_GETCSD:
01004 rc = MmCardGetReg(ifc, MMCMD_SEND_CSD, (u_char *) conf, sizeof(MMC_CSD));
01005 break;
01006 default:
01007 rc = -1;
01008 break;
01009 }
01010 return rc;
01011 }
01012
01024 int MmCardDevInit(NUTDEVICE * dev)
01025 {
01026 return 0;
01027 }
01028