mmc_drv.c
Upload User: yj_qqy
Upload Date: 2017-01-28
Package Size: 2911k
Code Size: 12k
Category:

uCOS

Development Platform:

C/C++

  1. /*
  2. **********************************************************************
  3. *                          Micrium, Inc.
  4. *                      949 Crestview Circle
  5. *                     Weston,  FL 33327-1848
  6. *
  7. *                            uC/FS
  8. *
  9. *             (c) Copyright 2001 - 2003, Micrium, Inc.
  10. *                      All rights reserved.
  11. *
  12. ***********************************************************************
  13. ----------------------------------------------------------------------
  14. File        : mmc_drv.c
  15. Purpose     : File system generic MMC/SD driver
  16. ---------------------------END-OF-HEADER------------------------------
  17. */
  18. /*********************************************************************
  19. *
  20. *             #include Section
  21. *
  22. **********************************************************************
  23. */
  24. #include <stdio.h>
  25. #include "fs_api.h"
  26. #include "fs_clib.h"
  27. #include "fs_dev.h"
  28. #if FS_USE_MMC_DRIVER
  29. #include "bsp.h"
  30. #include "sddriver.h"
  31. #include "fs_lbl.h"
  32. #define FS__DEV_MBRFLAG_CLI     0xFA
  33. #define FS__DEV_MBRFLAG_JUMP1   0xEB
  34. #define FS__DEV_MBRFLAG_JUMP2   0xE9
  35. #define FS__DEV_MBRSECTORFLAG_L 0x55
  36. #define FS__DEV_MBRSECTORFLAG_H 0xAA
  37. #define FS__DEV_PART_0_TABLE    0x01BE
  38. /*********************************************************************
  39. *
  40. *             Local Variables        
  41. *
  42. **********************************************************************
  43. */
  44. static FS_u32   _FS_mmc_logicalstart[FS_MMC_MAXUNIT]; /* start of partition */
  45. static char     _FS_mmc_mbrbuffer[0x200];             /* buffer for reading MBR */   
  46. static char     _FS_mmc_diskchange[FS_MMC_MAXUNIT];   /* signal flag for driver */
  47. static char     _FS_mmc_busycnt[FS_MMC_MAXUNIT];      /* counter for BSY LED on/off */
  48. /*********************************************************************
  49. *
  50. *             Local functions
  51. *
  52. **********************************************************************
  53. */
  54. /*********************************************************************
  55. *
  56. *             FS_MMC_HW_X_BusyLedOff
  57. *
  58. *  Description:
  59. *    FS low level function. Switches the busy LED off.
  60. *
  61. *  Parameters:
  62. *    Unit      - Device Index
  63. *
  64. *  Return value:
  65. *    void
  66. */
  67. static void FS_MMC_HW_X_BusyLedOff (FS_u8 Unit) {
  68. GPIO_ResetBits(GPIOC, DEF_BIT_07);
  69. }
  70. /*********************************************************************
  71. *
  72. *             FS_MMC_HW_X_BusyLedOn
  73. *
  74. *  Description:
  75. *    FS low level function. Switches the busy LED off.
  76. *
  77. *  Parameters:
  78. *    Unit      - Device Index
  79. *
  80. *  Return value:
  81. *    void
  82. */
  83. static void FS_MMC_HW_X_BusyLedOn(FS_u8 Unit) {
  84. GPIO_SetBits(GPIOC, DEF_BIT_07);
  85. }
  86. /*********************************************************************
  87. *
  88. *             FS_MMC_HW_X_IsPresent
  89. *
  90. *  Description:
  91. *    Returns the state of the media. If you do not know the state, return
  92. *    FS_MEDIA_STATEUNKNOWN and the higher layer will try to figure out if
  93. *    a media is present.
  94. *
  95. *  Parameters:
  96. *    Unit                 - Device Index
  97. *
  98. *  Return value:
  99. *    FS_MEDIA_STATEUNKNOWN       - the state of the media is unkown
  100. *    FS_MEDIA_ISNOTPRESENT       - no card is present
  101. *    FS_MEDIA_ISPRESENT          - a card is present
  102. */
  103. static char FS_MMC_HW_X_IsPresent(FS_u8 Unit) {
  104.   return FS_MEDIA_STATEUNKNOWN;
  105. }
  106. /*********************************************************************
  107. *
  108. *             FS_GetMediaStartSec
  109. *
  110. *  Description:
  111. *    FS api function. Get logical start sector from master boot record
  112. *    or partition table.
  113. *
  114. *  Parameters:
  115. *    DevIndex        - DevIndex number.
  116. *    pBuffer         - A pointer to a buffer containing the first
  117. *                      sector of the media. This should contain the
  118. *                      master boot record (MBR) or Bios Parameter Block
  119. *                      (BPB) if the device has no partition table.
  120. *  Return value:
  121. *    < 0xFFFF        - Number of the first sector of the medium.
  122. *    ==0xFFFF        - No valid MBR/BPB found.
  123. */
  124. static FS_u32 FS_GetMediaStartSec(const FS_u8 *pBuffer) {
  125.   FS_u8  c;
  126.   FS_u32 StartSec;
  127.  
  128.   c = pBuffer[0x1FE]; /* check first part of the signature */
  129.   if (c != FS__DEV_MBRSECTORFLAG_L) {
  130.      return 0xFFFFFFFF;
  131.   }
  132.   c = pBuffer[0x1FF]; /* check second part of the signature */
  133.   if (c != FS__DEV_MBRSECTORFLAG_H) {
  134.     return 0xFFFFFFFF;
  135.   }
  136.   c = pBuffer[0x000]; /* check if boot or partition record */
  137.   if (c == FS__DEV_MBRFLAG_JUMP1) {
  138.     return 0; /* if first byte is a jump command, there is no partition table */
  139.   } 
  140.   if (c == FS__DEV_MBRFLAG_JUMP2) {
  141.     return 0; /* if first byte is a jump command, there is no partition table */
  142.   } /* this calculation makes sure big/little endian system get the right value from the table */
  143.   /* read first entry of the partition table */
  144.   StartSec  = (FS_u32)pBuffer[FS__DEV_PART_0_TABLE + 11] & 0xFFUL;
  145.   StartSec <<= 8;
  146.   StartSec += (FS_u32)pBuffer[FS__DEV_PART_0_TABLE + 10] & 0xFFUL;
  147.   StartSec <<= 8;
  148.   StartSec += (FS_u32)pBuffer[FS__DEV_PART_0_TABLE + 9] & 0xFFUL;
  149.   StartSec <<= 8;
  150.   StartSec += (FS_u32)pBuffer[FS__DEV_PART_0_TABLE + 8] & 0xFFUL; 
  151.  return StartSec;
  152. }
  153. /*********************************************************************
  154. *
  155. *             _FS_MMC_DevStatus
  156. *
  157.   Description:
  158.   FS driver function. Get status of the media.
  159.   Parameters:
  160.   Unit        - Unit number.
  161.  
  162.   Return value:
  163.   ==1 (FS_LBL_MEDIACHANGED) - The media of the device has changed.
  164.   ==0                       - Device okay and ready for operation.
  165.   <0                        - An error has occured.
  166. */
  167. static int _FS_MMC_DevStatus(FS_u32 Unit) {
  168. static int init = 0;
  169. int x;
  170. char a;
  171. FS_u32 ul;
  172. FS_MMC_HW_X_BusyLedOn(1);
  173. if (!init) {
  174. /* 
  175. The function is called the first time. For each unit,
  176. the flag for 'diskchange' is set. That makes sure, that
  177. FS_LBL_MEDIACHANGED is returned, if there is already a
  178. media in the reader.
  179. */
  180. for (init = 0; init < FS_MMC_MAXUNIT; init++) {
  181. _FS_mmc_diskchange[init] = 1;
  182. }
  183. init = 1;
  184. }
  185. if (Unit >= FS_MMC_MAXUNIT) {
  186. return -1;  /* No valid unit number */
  187. }
  188. a = FS_MMC_HW_X_IsPresent(Unit);/* Check if a card is present */
  189. if (!a) {
  190.   return -1;  /* No card in reader */
  191. }
  192. /* When you get here, then there is a card in the reader */
  193. a = _FS_mmc_diskchange[Unit];  /* Check if the media has changed */
  194. if (a) {
  195. /* 
  196. A diskchange took place. The following code reads the MBR of the
  197. card to get its partition information.
  198. */
  199. _FS_mmc_diskchange[Unit] = 0;  /* Reset 'diskchange' flag */
  200. x = SD_Initialize();
  201. if (x > 0) {
  202. printf("SD_Initialize error! CODE: 0x%02Xrn", x);
  203. return -1;
  204. }
  205. x = SD_ReadBlock(0, 512, (FS_u8*)&_FS_mmc_mbrbuffer[0]);
  206. if (x > 0) {
  207. printf("SD_ReadBlock error! CODE: 0x%02Xrn", x);
  208. return -1;
  209. }
  210. /* Calculate start sector of the first partition */
  211.     ul = FS_GetMediaStartSec((FS_u8*)&_FS_mmc_mbrbuffer[0]);
  212.     if (ul == 0xFFFFFFFF) { /* check if MBR was invalid */
  213.       return -1;
  214.     }
  215. _FS_mmc_logicalstart[Unit] = ul;
  216. return FS_LBL_MEDIACHANGED;
  217. }
  218. FS_MMC_HW_X_BusyLedOff(1);
  219. return 0;
  220. }
  221. /*********************************************************************
  222. *
  223. *             _FS_MMC_DevRead
  224. *
  225.   Description:
  226.   FS driver function. Read a sector from the media.
  227.   Parameters:
  228.   Unit        - Unit number.
  229.   Sector      - Sector to be read from the device.
  230.   pBuffer     - Pointer to buffer for storing the data.
  231.  
  232.   Return value:
  233.   ==0         - Sector has been read and copied to pBuffer.
  234.   <0          - An error has occured.
  235. */
  236. static int _FS_MMC_DevRead(FS_u32 Unit, FS_u32 Sector, void *pBuffer){
  237. int x;
  238. if (Unit >= FS_MMC_MAXUNIT) {
  239. return -1;  /* No valid unit number */
  240. }
  241. FS_MMC_HW_X_BusyLedOn(1);
  242. x = SD_ReadBlock(Sector+_FS_mmc_logicalstart[Unit], 512, (FS_u8*)pBuffer);
  243. if(x > 0) {
  244. printf("SD_ReadBlock error! CODE: 0x%02Xrn", x);
  245. x = -1;
  246. }    
  247. else {
  248. x = 0;
  249. }
  250. FS_MMC_HW_X_BusyLedOff(1);
  251. return x;
  252. }
  253. /*********************************************************************
  254. *
  255. *             _FS_MMC_DevWrite
  256. *
  257.   Description:
  258.   FS driver function. Write sector to the media.
  259.   Parameters:
  260.   Unit        - Unit number.
  261.   Sector      - Sector to be written to the device.
  262.   pBuffer     - Pointer to data to be stored.
  263.  
  264.   Return value:
  265.   ==0         - Sector has been written to the device.
  266.   <0          - An error has occured.
  267. */
  268. static int _FS_MMC_DevWrite(FS_u32 Unit, FS_u32 Sector, void *pBuffer){
  269. int x;
  270. if (Unit >= FS_MMC_MAXUNIT) {
  271. return -1;  /* No valid unit number */
  272. }
  273. FS_MMC_HW_X_BusyLedOn(1);
  274. x = SD_WriteBlock(Sector+_FS_mmc_logicalstart[Unit], 512, (FS_u8*)pBuffer); 
  275. if (x > 0) {
  276. printf("SD_WriteBlock error! CODE: 0x%02Xrn", x);
  277. x = -1;
  278. }
  279. else {
  280. x = 0;
  281. }
  282. FS_MMC_HW_X_BusyLedOff(1);
  283. return x;
  284. }
  285. /*********************************************************************
  286. *
  287. *             _FS_MMC_DevIoCtl
  288. *
  289.   Description:
  290.   FS driver function. Execute device command.
  291.   Parameters:
  292.   Unit        - Unit number.
  293.   Cmd         - Command to be executed.
  294.   Aux         - Parameter depending on command.
  295.   pBuffer     - Pointer to a buffer used for the command.
  296.  
  297.   Return value:
  298.   Command specific. In general a negative value means an error.
  299. */
  300. static int _FS_MMC_DevIoCtl(FS_u32 Unit, FS_i32 Cmd, FS_i32 Aux, void *pBuffer){
  301.    FS_u32 *info, ul;
  302.    int x;
  303.    FS_MMC_HW_X_BusyLedOn(1);
  304.    Aux = Aux;  /* Get rid of compiler warning */
  305.    if (Unit >= FS_MMC_MAXUNIT) {
  306.       return -1;  /* No valid unit number */
  307.    }
  308.    switch(Cmd){
  309.      case FS_CMD_INC_BUSYCNT:
  310.        _FS_mmc_busycnt[Unit]++;
  311.        if(_FS_mmc_busycnt[Unit] > 0){
  312.           FS_MMC_HW_X_BusyLedOn(Unit);
  313.        }
  314.        break;
  315.      case FS_CMD_DEC_BUSYCNT:
  316.        _FS_mmc_busycnt[Unit]--;
  317.        if(_FS_mmc_busycnt[Unit] <= 0){
  318.           _FS_mmc_busycnt[Unit] = 0;
  319.           FS_MMC_HW_X_BusyLedOff(Unit);
  320.        }
  321.        break;
  322.      case FS_CMD_CHK_DSKCHANGE:
  323.        //a = FS_MMC_HW_X_DetectStatus(Unit);
  324.        //if(a){
  325.        //   _FS_mmc_diskchange[Unit] = 1;
  326.        //}    
  327.        break;
  328.      case FS_CMD_GET_DEVINFO:
  329.        if (!pBuffer) {
  330.          return -1;
  331.        }
  332.        info = pBuffer;
  333.    x = SD_Initialize();
  334.        if (x > 0) {
  335.           return -1;
  336.        }
  337.    x = SD_ReadBlock(0, 512, (FS_u8*)&_FS_mmc_mbrbuffer[0]);
  338.        if (x > 0) {
  339.           return -1;
  340.        }
  341.       ul = FS_GetMediaStartSec((FS_u8*)&_FS_mmc_mbrbuffer[0]);
  342.       if (ul == 0xFFFFFFFF) { /* check if MBR was invalid */
  343.         return -1;
  344.       }
  345.       if (ul != 0) {
  346.         /* READ (1) 512 BYTE SECTOR */
  347. x = SD_ReadBlock(ul, 512, (FS_u8*)&_FS_mmc_mbrbuffer[0]);
  348. if (x > 0) {
  349.   return -1;
  350. }
  351.       }
  352.        /* hidden */
  353.        *info = _FS_mmc_mbrbuffer[0x1c6];
  354.        *info += (0x100UL * _FS_mmc_mbrbuffer[0x1c7]);
  355.        *info += (0x10000UL * _FS_mmc_mbrbuffer[0x1c8]);
  356.        *info += (0x1000000UL * _FS_mmc_mbrbuffer[0x1c9]);
  357.        info++;
  358.        /* head */
  359.        *info = _FS_mmc_mbrbuffer[0x1c3]; 
  360.        info++;
  361.        /* sec per track */
  362.        *info = _FS_mmc_mbrbuffer[0x1c4]; 
  363.        info++;
  364.        /* size */
  365.        *info = _FS_mmc_mbrbuffer[0x1ca];
  366.        *info += (0x100UL * _FS_mmc_mbrbuffer[0x1cb]);
  367.        *info += (0x10000UL * _FS_mmc_mbrbuffer[0x1cc]);
  368.        *info += (0x1000000UL * _FS_mmc_mbrbuffer[0x1cd]);
  369.        break;
  370.      default:
  371.        break;
  372.    }
  373.    FS_MMC_HW_X_BusyLedOff(1);
  374.    return 0; 
  375. }
  376. /*********************************************************************
  377. *
  378. *             Global variables
  379. *
  380. **********************************************************************
  381. */
  382. const FS__device_type FS__mmcdevice_driver = {
  383.   "MMC device",
  384.   _FS_MMC_DevStatus,
  385.   _FS_MMC_DevRead,
  386.   _FS_MMC_DevWrite,
  387.   _FS_MMC_DevIoCtl
  388. };
  389. #endif /* FS_USE_MMC_DRIVER */
  390. /*************************** End of file ****************************/