mmcard.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005-2007 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  */
00032 
00083 #include <cfg/mmci.h>
00084 
00085 #if 0
00086 /* Use for local debugging. */
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  * Several routines call NutSleep, which results in a context switch.
00232  * This mutual exclusion semaphore takes care, that multiple threads
00233  * do not interfere with each other.
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     /* Enable card select. */
00250     (*ifc->mmcifc_cs) (1);
00251     /*
00252      * Repeat sending nothing until we receive nothing. Actually
00253      * it should be sufficient to send a single 0xFF value, but
00254      * running a loop seems to fix certain kind of sync problems.
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     /* Send command and parameter. */
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      * We are running with CRC disabled. However, the reset command must
00275      * be send with a valid CRC. Fortunately this command is sent with a
00276      * fixed parameter value of zero, which results in a fixed CRC value
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     /* The first byte is equal to the R1 response. */
00342     rc = MmCardRxR1(ifc);
00343     /* Receive the operating condition. */
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      * Initialize the low level card interface.
00365      */
00366     if ((*ifc->mmcifc_in) ()) {
00367         return -1;
00368     }
00369 
00370     /*
00371      * 80 bits of ones with deactivated chip select will put the card 
00372      * in SPI mode.
00373      */
00374     (*ifc->mmcifc_cs) (0);
00375     for (i = 0; i < 10; i++) {
00376         (*ifc->mmcifc_io) (0xFF);
00377     }
00378 
00379     /*
00380      * Switch to idle state and wait until initialization is running
00381      * or idle state is reached.
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      * Try to switch to SPI mode. Looks like a retry helps to fix
00411      * certain synchronization problems.
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      * Wait for a really long time until card is initialized
00424      * and enters idle state.
00425      */
00426     for (i = 0; i < MMC_MAX_INIT_POLLS; i++) {
00427         /*
00428          * In SPI mode SEND_OP_COND is a dummy, used to poll the card
00429          * for initialization finished. Thus, there are no parameters
00430          * and no operation condition data is sent back.
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             /* Initialize MMC access mutex semaphore. */
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     /* Gain mutex access. */
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     /* Release mutex access. */
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     /* Gain mutex access. */
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             // (*ifc->mmcifc_io)(0xFF);
00536             // (*ifc->mmcifc_io)(0xFF);
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     /* Release mutex access. */
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          * It would be much better to verify the checksum than to re-read
00600          * and verify the data block.
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     /* Return an error if no card is detected. */
00734     if ((*ifc->mmcifc_cd) () == 0) {
00735         errno = ENODEV;
00736         return NUTFILE_EOF;
00737     }
00738 
00739     /* Set the card in SPI mode. */
00740     if (MmCardInit(ifc)) {
00741         errno = ENODEV;
00742         return NUTFILE_EOF;
00743     }
00744 
00745     /* Parse the name for a partition number and a file system driver. */
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      * Check the list of registered devices for the given name of the
00758      * files system driver. If none has been specified, get the first
00759      * file system driver in the list. Hopefully the application
00760      * registered one only.
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     /* Read MBR. */
00787     if (MmCardReadOrVerify(ifc, 0, fcb->fcb_blkbuf, 0)) {
00788         NutHeapFree(fcb);
00789         return NUTFILE_EOF;
00790     }
00791     /* Check for the cookie at the end of this sector. */
00792     if (fcb->fcb_blkbuf[DOSPART_MAGICPOS] != 0x55 || fcb->fcb_blkbuf[DOSPART_MAGICPOS + 1] != 0xAA) {
00793         NutHeapFree(fcb);
00794         return NUTFILE_EOF;
00795     }
00796     /* Check for the partition table. */
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         /* No partition table. Assume FAT12 and 32MB size. */
00801         fcb->fcb_part.part_type = PTYPE_FAT12;
00802         fcb->fcb_part.part_sect_offs = 0;
00803         fcb->fcb_part.part_sects = 65536; /* How to find out? */
00804     }
00805     else {
00806         /* Read partition table. */
00807         part = (DOSPART *) & fcb->fcb_blkbuf[DOSPART_SECTORPOS];
00808         for (i = 1; i <= 4; i++) {
00809             if (partno) {
00810                 if (i == partno) {
00811                     /* Found specified partition number. */
00812                     fcb->fcb_part = *part;
00813                     break;
00814                 }
00815             } else if (part->part_state & 0x80) {
00816                 /* Located first active partition. */
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      * Mount the file system volume.
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     /* Gain mutex access. */
00897     NutEventWait(&mutex, 0);
00898 
00899     while (retries--) {
00900         /* Send the command to the card. This will select the card. */
00901         MmCardTxCmd(ifc, cmd, 0);
00902         /* Wait for OK response from the card. */
00903         if (MmCardRxR1(ifc) == 0x00) {
00904             /* Wait for data from the card. */
00905             if (MmCardRxR1(ifc) == 0xFE) {
00906                 for (i = 0; i < siz; i++) {
00907                     *rbp++ = (*ifc->mmcifc_io) (0xFF);
00908                 }
00909                 /* Ignore the CRC. */
00910                 (*ifc->mmcifc_io) (0xFF);
00911                 (*ifc->mmcifc_io) (0xFF);
00912                 /* De-activate card selection. */
00913                 (*ifc->mmcifc_cs) (0);
00914                 /* Return a positive result. */
00915                 rc = 0;
00916                 break;
00917             }
00918         }
00919         /* De-activate card selection. */
00920         (*ifc->mmcifc_cs) (0);
00921     }
00922 
00923     /* Release mutex access. */
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             /* Gain mutex access. */
00997             NutEventWait(&mutex, 0);
00998 
00999             MmCardTxCmd(ifc, MMCMD_SEND_STATUS, 0);
01000             *s = MmCardRxR2(ifc);
01001 
01002             /* Release mutex access. */
01003             NutEventPost(&mutex);
01004         }
01005         break;
01006     case MMCARD_GETOCR:
01007         /* Gain mutex access. */
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         /* Release mutex access. */
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 

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/