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