fat_ioct.c
上传用户:yj_qqy
上传日期:2017-01-28
资源大小:2911k
文件大小:32k
源码类别:

uCOS

开发平台:

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        : fat_ioctc.c
  15. Purpose     : FAT File System Layer IOCTL
  16. ----------------------------------------------------------------------
  17. Known problems or limitations with current version
  18. ----------------------------------------------------------------------
  19. None.
  20. ---------------------------END-OF-HEADER------------------------------
  21. */
  22. /*********************************************************************
  23. *
  24. *             #include Section
  25. *
  26. **********************************************************************
  27. */
  28. #include "fs_conf.h"
  29. #include "fs_port.h"
  30. #include "fs_dev.h"
  31. #include "fs_api.h"
  32. #include "fs_fsl.h"
  33. #include "fs_int.h"
  34. #include "fs_os.h"
  35. #include "fs_lbl.h"
  36. #include "fs_fat.h"
  37. #include "fs_clib.h"
  38. /*********************************************************************
  39. *
  40. *             #define constants
  41. *
  42. **********************************************************************
  43. */
  44. #define FS_KNOWNMEDIA_NUM   sizeof(_FS_wd_format_media_table) / sizeof(_FS_wd_format_media_type)
  45. #ifndef FS_FAT_NOFORMAT
  46.   #define FS_FAT_NOFORMAT       0
  47. #endif
  48. #ifndef FS_FAT_DISKINFO
  49.   #define FS_FAT_DISKINFO       1
  50. #endif
  51. #ifndef FS_SUPPORT_SEC_ACCESS
  52.   #define FS_SUPPORT_SEC_ACCESS 1
  53. #endif
  54. /*********************************************************************
  55. *
  56. *             Local data types
  57. *
  58. **********************************************************************
  59. */
  60. #if (FS_FAT_NOFORMAT==0)
  61. typedef struct {
  62.   FS_i32  media_id;
  63.   FS_u32  totsec32;
  64.   FS_u32  hiddsec;
  65.   FS_u16  totsec16;
  66.   FS_u16  rootentcnt;
  67.   FS_u16  fatsz16;
  68.   FS_u16  secpertrk;
  69.   FS_u16  numheads;
  70.   char    secperclus;
  71.   char    media; 
  72.   char    fsystype;
  73. } _FS_wd_format_media_type;
  74. typedef struct {
  75.   FS_u32 SecNum;
  76.   FS_u32 Num;
  77. } _FS_FAT_ROOTENTCNT ;
  78. typedef struct {
  79.   FS_u32 SecNum;
  80.   FS_u16 Num;
  81. } _FS_FAT_SECPERCLUST;
  82. /*********************************************************************
  83. *
  84. *             Local Variables        
  85. *
  86. **********************************************************************
  87. */
  88. /*  media_id              totsec32       hidsec    totsec16   rootent  fatsz16  secpertrk  numheads secperclus  media   fstype */ 
  89. static const _FS_wd_format_media_type _FS_wd_format_media_table[] = {
  90.   { FS_MEDIA_RAM_16KB,  0x00000000UL, 0x00000000UL, 0x0020,   0x0040,  0x0001,  0x0004,     0x0004,   0x01, (char) 0xf8, 0 },
  91.   { FS_MEDIA_RAM_64KB,  0x00000000UL, 0x00000000UL, 0x0080,   0x0040,  0x0001,  0x0004,     0x0004,   0x01, (char) 0xf8, 0 },
  92.   { FS_MEDIA_RAM_128KB, 0x00000000UL, 0x00000000UL, 0x0100,   0x0080,  0x0001,  0x0004,     0x0004,   0x01, (char) 0xf8, 0 },
  93.   { FS_MEDIA_RAM_256KB, 0x00000000UL, 0x00000000UL, 0x0200,   0x0080,  0x0002,  0x0004,     0x0004,   0x01, (char) 0xf8, 0 },
  94.   { FS_MEDIA_RAM_512KB, 0x00000000UL, 0x00000000UL, 0x0400,   0x00e0,  0x0003,  0x0004,     0x0004,   0x01, (char) 0xf8, 0 },
  95.   { FS_MEDIA_FD_144MB,  0x00000000UL, 0x00000000UL, 0x0b40,   0x00e0,  0x0009,  0x0012,     0x0002,   0x01, (char) 0xf0, 0 },
  96.   { FS_MEDIA_SMC_1MB,   0x00000000UL, 0x0000000DUL, 0x07c3,   0x0100,  0x0001,  0x0004,     0x0004,   0x08, (char) 0xf8, 0 },
  97.   { FS_MEDIA_SMC_2MB,   0x00000000UL, 0x0000000bUL, 0x0f95,   0x0100,  0x0002,  0x0008,     0x0004,   0x08, (char) 0xf8, 0 },
  98.   { FS_MEDIA_SMC_4MB,   0x00000000UL, 0x0000001bUL, 0x1f25,   0x0100,  0x0002,  0x0008,     0x0004,   0x10, (char) 0xf8, 0 },
  99.   { FS_MEDIA_SMC_8MB,   0x00000000UL, 0x00000019UL, 0x3e67,   0x0100,  0x0003,  0x0010,     0x0004,   0x10, (char) 0xf8, 0 },
  100.   { FS_MEDIA_SMC_16MB,  0x00000000UL, 0x00000029UL, 0x7cd7,   0x0100,  0x0003,  0x0010,     0x0004,   0x20, (char) 0xf8, 0 },
  101.   { FS_MEDIA_SMC_32MB,  0x00000000UL, 0x00000023UL, 0xf9dd,   0x0100,  0x0006,  0x0010,     0x0008,   0x20, (char) 0xf8, 0 },
  102.   { FS_MEDIA_SMC_64MB,  0x0001f3c9UL, 0x00000037UL, 0x0000,   0x0100,  0x000c,  0x0020,     0x0008,   0x20, (char) 0xf8, 0 },
  103.   { FS_MEDIA_SMC_128MB, 0x0003e7d1UL, 0x0000002fUL, 0x0000,   0x0100,  0x0020,  0x0020,     0x0010,   0x20, (char) 0xf8, 1 },
  104.   { FS_MEDIA_MMC_32MB,  0x00000000UL, 0x00000020UL, 0xf460,   0x0200,  0x003d,  0x0020,     0x0004,   0x04, (char) 0xf8, 1 },
  105.   { FS_MEDIA_MMC_64MB,  0x0001e8e0UL, 0x00000020UL, 0x0000,   0x0200,  0x007a,  0x0020,     0x0008,   0x04, (char) 0xf8, 1 },
  106.   { FS_MEDIA_MMC_128MB, 0x0003d2e0UL, 0x00000020UL, 0x0000,   0x0200,  0x00f5,  0x0020,     0x0008,   0x04, (char) 0xf8, 1 },
  107.   { FS_MEDIA_SD_16MB,   0x00000000UL, 0x00000039UL, 0x7187,   0x0200,  0x0003,  0x0020,     0x0002,   0x20, (char) 0xf8, 0 },
  108.   { FS_MEDIA_SD_64MB,   0x0001dbd9UL, 0x00000027UL, 0x0000,   0x0200,  0x000c,  0x0020,     0x0008,   0x20, (char) 0xf8, 0 },
  109.   { FS_MEDIA_SD_128MB,  0x0003c09fUL, 0x00000061UL, 0x0000,   0x0200,  0x001f,  0x0020,     0x0008,   0x20, (char) 0xf8, 1 },
  110.   { FS_MEDIA_CF_32MB,   0x00000000UL, 0x00000020UL, 0xf760,   0x0200,  0x007c,  0x0020,     0x0004,   0x02, (char) 0xf8, 1 },
  111.   { FS_MEDIA_CF_64MB,   0x0001e860UL, 0x00000020UL, 0x0000,   0x0200,  0x007b,  0x0020,     0x0004,   0x04, (char) 0xf8, 1 }
  112. };
  113. /* table for getting number of root entries for a given media size */
  114. static const _FS_FAT_ROOTENTCNT _FS_auto_rootcnt[] = {
  115.   {         0x100,     0x40 },
  116.   {         0x200,     0x80 },
  117.   {      0x0b40UL,     0xe0 },
  118.   {  0x0001f3c9UL,    0x100 },
  119.   {  0xffffffffUL,    0x200 }
  120. };
  121. /* table for calculating cluster size */
  122. static const _FS_FAT_SECPERCLUST _FS_auto_secperclust[] = {
  123.   /* medias up to 512MB are formatted with FAT16 */
  124.   {     0x0b40UL, 0x0001 },
  125.   {      32680UL, 0x0002 },
  126.   {     262144UL, 0x0004 },
  127.   {     524288UL, 0x0008 },
  128.   {    1048576UL, 0x0010 },
  129.   /* medias bigger than 512MB are formatted with FAT32 */
  130.   {   16777216UL, 0x0008 },
  131.   {   33554432UL, 0x0010 },
  132.   {   67108864UL, 0x0020 },
  133.   { 0xffffffffUL, 0x0040 }
  134. };
  135. #endif /* FS_FAT_NOFORMAT==0 */
  136. /*********************************************************************
  137. *
  138. *             Local functions
  139. *
  140. **********************************************************************
  141. */
  142. #if (FS_FAT_NOFORMAT==0)
  143. /*********************************************************************
  144. *
  145. *             _FS_fat_format
  146. *
  147.   Description:
  148.   FS internal function. Format a media using specified parameters.
  149.   Currently this function needs many parameters. The function will be
  150.   improved. 
  151.   Parameters:
  152.   pDriver     - Pointer to a device driver function table.
  153.   Unit        - Unit number.
  154.   SecPerClus  - Number of sector per allocation unit.
  155.   RootEntCnt  - For FAT12/FAT16, this is the number of 32 byte root
  156.                 directory entries. 0 for FAT32.
  157.   TotSec16    - 16-bit total count of sectors. If zero, TotSec32 must 
  158.                 be none-zero.
  159.   TotSec32    - 32-bit total count of sectors. If zero, TotSec16 must 
  160.                 be none-zero.
  161.   Media       - Media byte.
  162.   FATSz16     - 16-bit count of sectors occupied by one FAT. 0 for
  163.                 FAT32 volumes, which use FATSz32.
  164.   FATSz32     - 32-bit count of sectors occupied by one FAT. This is
  165.                 valid for FAT32 medias only.
  166.   SecPerTrk   - Sectors per track.
  167.   NumHeads    - Number of heads.
  168.   HiddSec     - Count of hidden sectors preceding the partition.
  169.   FSysType    - ==0 => FAT12
  170.                 ==1 => FAT16
  171.                 ==2 => FAT32
  172.   
  173.   Return value:
  174.   >=0         - Media has been formatted.
  175.   <0          - An error has occured.
  176. */
  177. static int _FS_fat_format(const FS__device_type *pDriver,FS_u32 Unit, char SecPerClus, 
  178.                           FS_u16 RootEntCnt, FS_u16 TotSec16, FS_u32 TotSec32, char Media, 
  179.                           FS_u16 FATSz16, FS_u32 FATSz32, FS_u16 SecPerTrk,FS_u16 NumHeads, 
  180.                           FS_u32 HiddSec, char FSysType) {
  181.   FS__FAT_BPB bpb;
  182.   FS_u32 sector;
  183.   FS_u32 value;
  184.   char *buffer;
  185.   int i;
  186.   int j;
  187.   int n;
  188.   
  189.   buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
  190.   if (!buffer) {
  191.     return -1;
  192.   }
  193.   FS__CLIB_memset(buffer, 0x00, (FS_size_t)FS_FAT_SEC_SIZE);
  194.   /* Setup BPB */
  195.   FS__CLIB_memset(&bpb, 0x00, (FS_size_t)sizeof(bpb));
  196.   bpb.BytesPerSec = 0x0200;       /* _512_,1024,2048,4096           */
  197.   bpb.SecPerClus  = SecPerClus;   /* sec in allocation unit         */
  198.   if (FSysType != 2) {
  199.     bpb.RsvdSecCnt  = 0x0001;       /* 1 for FAT12 & FAT16            */
  200.   }
  201. #if (FS_FAT_NOFAT32==0)
  202.   else {
  203.     bpb.RsvdSecCnt  = 0x0020;       /* 32 for FAT32                   */
  204.   }
  205. #else
  206.   /* FAT32 disabled */
  207.   else {
  208.     FS__fat_free(buffer);
  209.     return -1;
  210.   }
  211. #endif /* FS_FAT_NOFAT32==0 */
  212.   bpb.NumFATs     = 0x02;         /* 2                              */
  213.   bpb.RootEntCnt  = RootEntCnt;   /* number of root dir entries     */
  214.   bpb.TotSec16    = TotSec16;     /* RSVD+FAT+ROOT+DATA (<64k)      */
  215.   bpb.FATSz16     = FATSz16;      /* number of FAT sectors          */
  216.   bpb.TotSec32    = TotSec32;     /* RSVD+FAT+ROOT+FATA (>=64k)     */
  217.   bpb.Signature   = 0xaa55;       /* 0xAA55 Signature               */
  218.   /* setup BPB specifics for FAT32 */
  219.   bpb.FATSz32     = FATSz32;      /* number of FAT sectors          */
  220.   bpb.ExtFlags    = 0x0000;       /* mirroring info                 */
  221.   bpb.RootClus    = 0x00000002UL; /* root dir clus for FAT32        */
  222.   bpb.FSInfo      = 0x0001;       /* position of FSInfo structure   */
  223.   /* 
  224.      Prepare buffer with information of the BPB 
  225.      offset 0 - 35 is same for FAT12/FAT16 and FAT32 
  226.   */
  227.   /* jmpBoot = 0xe9 0x0000 */
  228.   buffer[0]   = (char)0xe9;
  229.   buffer[1]   = (char)0x00;
  230.   buffer[2]   = (char)0x00;
  231.   /* OEMName = '        ' */
  232.   for (i = 3; i < 11; i++) {
  233.     buffer[i] = (char)0x20;
  234.   }
  235.   /* BytesPerSec */
  236.   buffer[11]  = (char)(bpb.BytesPerSec & 0xff);
  237.   buffer[12]  = (char)((unsigned int)(bpb.BytesPerSec & 0xff00) >> 8);
  238.   /* SecPerClus */
  239.   buffer[13]  = (char)bpb.SecPerClus;
  240.   /* RsvdSecCnt */
  241.   buffer[14]  = (char)(bpb.RsvdSecCnt & 0xff);
  242.   buffer[15]  = (char)((unsigned int)(bpb.RsvdSecCnt & 0xff00) >> 8);
  243.   /* NumFATs */
  244.   buffer[16]  = (char)bpb.NumFATs;
  245.   /* RootEntCnt */
  246.   buffer[17]  = (char)(bpb.RootEntCnt & 0xff);
  247.   buffer[18]  = (char)((unsigned int)(bpb.RootEntCnt & 0xff00) >> 8);
  248.   /* TotSec16 */
  249.   buffer[19]  = (char)(bpb.TotSec16 & 0xff);
  250.   buffer[20]  = (char)((unsigned int)(bpb.TotSec16 & 0xff00) >> 8);
  251.   /* Media */
  252.   buffer[21]  = Media;
  253.   /* FATSz16 */
  254.   buffer[22]  = (char)(bpb.FATSz16 & 0xff);
  255.   buffer[23]  = (char)((unsigned int)(bpb.FATSz16 & 0xff00) >> 8);
  256.   /* SecPerTrk */
  257.   buffer[24]  = (char)(SecPerTrk & 0xff);
  258.   buffer[25]  = (char)((unsigned int)(SecPerTrk & 0xff00) >> 8);
  259.   /* NumHeads */
  260.   buffer[26]  = (char)(NumHeads & 0xff);
  261.   buffer[27]  = (char)((unsigned int)(NumHeads & 0xff00) >> 8);
  262.   /* HiddSec */
  263.   buffer[28]  = (char)(HiddSec & 0xff);
  264.   buffer[29]  = (char)((FS_u32)(HiddSec & 0x0000ff00UL) >> 8);
  265.   buffer[30]  = (char)((FS_u32)(HiddSec & 0x00ff0000UL) >> 16);
  266.   buffer[31]  = (char)((FS_u32)(HiddSec & 0xff000000UL) >> 24);
  267.   /* TotSec32 */
  268.   buffer[32]  = (char)(bpb.TotSec32 & 0xff);
  269.   buffer[33]  = (char)((FS_u32)(bpb.TotSec32 & 0x0000ff00UL) >> 8);
  270.   buffer[34]  = (char)((FS_u32)(bpb.TotSec32 & 0x00ff0000UL) >> 16);
  271.   buffer[35]  = (char)((FS_u32)(bpb.TotSec32 & 0xff000000UL) >> 24);
  272.   /* Offset 36 and above have different meanings for FAT12/FAT16 and FAT32 */
  273.   if (FSysType != 2) {
  274.     /* FAT12/FAT16 */
  275.     /* DrvNum = 0x00 (floppy) */
  276.     buffer[36]  = (char)0x00;  
  277.     /* Reserved1 = 0x00 (floppy) */
  278.     buffer[37]  = (char)0x00;
  279.     /* BootSig = 0x00 (next three fields are not 'present') */
  280.     buffer[38]  = (char)0x00;
  281.     /* VolID = 0x00000000 (serial number, e.g. date/time) */
  282.     for (i = 39; i < 43; i++) {
  283.       buffer[i] = (char)0x00;
  284.     }
  285.     /* VolLab = ' ' */
  286.     for (i = 43; i < 54; i++) {
  287.       buffer[i] = (char)0x20;
  288.     }
  289.     /* FilSysType = 'FAT12' */
  290.     if (FSysType == 0) {
  291.       FS__CLIB_strncpy(&buffer[54], "FAT12   ", 8);
  292.     }
  293.     else {
  294.       FS__CLIB_strncpy(&buffer[54], "FAT16   ", 8);
  295.     }
  296.   }
  297. #if (FS_FAT_NOFAT32==0)
  298.   else {
  299.     /* FAT32 */
  300.     /* FATSz32 */
  301.     buffer[36]  = (char)(bpb.FATSz32 & 0xff);
  302.     buffer[37]  = (char)((FS_u32)(bpb.FATSz32 & 0x0000ff00UL) >> 8);
  303.     buffer[38]  = (char)((FS_u32)(bpb.FATSz32 & 0x00ff0000UL) >> 16);
  304.     buffer[39]  = (char)((FS_u32)(bpb.FATSz32 & 0xff000000UL) >> 24);
  305.     /* EXTFlags */
  306.     buffer[40]  = (char)(bpb.ExtFlags & 0xff);
  307.     buffer[41]  = (char)((unsigned int)(bpb.ExtFlags & 0xff00) >> 8);
  308.     /* FSVer = 0:0 */
  309.     buffer[42]  = 0x00;
  310.     buffer[43]  = 0x00;
  311.     /* RootClus */
  312.     buffer[44]  = (char)(bpb.RootClus & 0xff);
  313.     buffer[45]  = (char)((FS_u32)(bpb.RootClus & 0x0000ff00UL) >> 8);
  314.     buffer[46]  = (char)((FS_u32)(bpb.RootClus & 0x00ff0000UL) >> 16);
  315.     buffer[47]  = (char)((FS_u32)(bpb.RootClus & 0xff000000UL) >> 24);
  316.     /* FSInfo */
  317.     buffer[48]  = (char)(bpb.FSInfo & 0xff);
  318.     buffer[49]  = (char)((unsigned int)(bpb.FSInfo & 0xff00) >> 8);
  319.     /* BkBootSec = 0x0006; */
  320.     buffer[50]  = 0x06;
  321.     buffer[51]  = 0x00;
  322.     /* Reserved */
  323.     for (i = 52; i < 64; i++) {
  324.       buffer[i] = (char)0x00;
  325.     }
  326.     /* DrvNum = 0x00 (floppy) */
  327.     buffer[64]  = (char)0x00;
  328.     /* Reserved1 = 0x00 (floppy) */
  329.     buffer[65]  = (char)0x00;
  330.     /* BootSig = 0x00 (next three fields are not 'present') */
  331.     buffer[66]  = (char)0x00;
  332.     /* VolID = 0x00000000 (serial number, e.g. date/time) */
  333.     for (i = 67; i < 71; i++) {
  334.       buffer[i] = (char)0x00;
  335.     }
  336.     /* VolLab = ' ' */
  337.     for (i = 71; i < 82; i++) {
  338.       buffer[i] = (char)0x20;
  339.     }
  340.     /* FilSysType = 'FAT12' */
  341.     FS__CLIB_strncpy(&buffer[82], "FAT32   ", 8);
  342.   }
  343. #endif /* FS_FAT_NOFAT32==0 */
  344.   /* Signature = 0xAA55 */
  345.   buffer[510] = (char)0x55;
  346.   buffer[511] = (char)0xaa;
  347.   /* Write BPB to media */
  348.   i = FS__lb_write(pDriver, Unit, 0, (void*)buffer);
  349.   if (i < 0) {
  350.     FS__fat_free(buffer);
  351.     return -1;
  352.   }
  353.   if (FSysType == 2) {
  354.     /* Write backup BPB */
  355.     i = FS__lb_write(pDriver, Unit, 6, (void*)buffer);
  356.     if (i<0) {
  357.       FS__fat_free(buffer);
  358.       return -1;
  359.     }
  360.   }
  361.   /*  Init FAT 1 & 2   */
  362.   FS__CLIB_memset(buffer, 0x00, (FS_size_t)FS_FAT_SEC_SIZE);
  363.   for (sector = 0; sector < 2 * (bpb.FATSz16 + bpb.FATSz32); sector++) {
  364.     value = sector % (bpb.FATSz16 + bpb.FATSz32);
  365.     if (value != 0) {
  366.       i = FS__lb_write(pDriver, Unit, bpb.RsvdSecCnt + sector, (void*)buffer);
  367.       if (i<0) {
  368.         FS__fat_free(buffer);
  369.         return -1;
  370.       }
  371.     }
  372.   }
  373.   buffer[0] = (char)Media;
  374.   buffer[1] = (char)0xff;
  375.   buffer[2] = (char)0xff;
  376.   if (FSysType != 0) {
  377.     buffer[3] = (char)0xff;
  378.   }
  379. #if (FS_FAT_NOFAT32==0)
  380.   if (FSysType == 2) {
  381.     buffer[4]   = (char)0xff;
  382.     buffer[5]   = (char)0xff;
  383.     buffer[6]   = (char)0xff;
  384.     buffer[7]   = (char)0x0f;
  385.     buffer[8]   = (char)0xff;
  386.     buffer[9]   = (char)0xff;
  387.     buffer[10]  = (char)0xff;
  388.     buffer[11]  = (char)0x0f;
  389.   }
  390. #endif /* FS_FAT_NOFAT32==0 */
  391.   for (i = 0; i < 2; i++) {
  392.     j = FS__lb_write(pDriver, Unit, (FS_u32)bpb.RsvdSecCnt + i * ((FS_u32)bpb.FATSz16+bpb.FATSz32), (void*)buffer);
  393.     if (j < 0) {
  394.       FS__fat_free(buffer);
  395.       return -1;
  396.     } // two fat table
  397.   }
  398.   /* Init root directory area */
  399.   FS__CLIB_memset(buffer, 0x00, (FS_size_t)FS_FAT_SEC_SIZE);
  400.   if (bpb.RootEntCnt != 0) {
  401.     /* FAT12/FAT16 */
  402.     n = (((FS_u32)bpb.RootEntCnt * 32) / (FS_u32)512); //n show the sectors accupied by root directory entries
  403.     for (i = 0; i < n; i++) {
  404.       j = FS__lb_write(pDriver, Unit, bpb.RsvdSecCnt + 2 * bpb.FATSz16 + i, (void*)buffer); //reserved sectors under fat12/16 is 1
  405.       if (j < 0) {
  406.         FS__fat_free(buffer);
  407.         return -1;
  408.       }
  409.     }
  410.   }
  411. #if (FS_FAT_NOFAT32==0)
  412.   else {
  413.     /* FAT32 */
  414.     n = bpb.SecPerClus;
  415.     for (i = 0; i < n; i++) {
  416.       j = FS__lb_write(pDriver, Unit, bpb.RsvdSecCnt + 2 * bpb.FATSz32 + (bpb.RootClus - 2) * n + i, (void*)buffer);
  417.       if (j < 0) {
  418.         FS__fat_free(buffer);
  419.         return -1;
  420.       }
  421.     }
  422.   }
  423. #endif /* FS_FAT_NOFAT32==0 */
  424. #if (FS_FAT_NOFAT32==0)
  425.   if (FSysType == 2) {
  426.     /* Init FSInfo */
  427.     FS__CLIB_memset(buffer, 0x00, (FS_size_t)FS_FAT_SEC_SIZE);
  428.     /* LeadSig = 0x41615252 */
  429.     buffer[0]     = (char)0x52;
  430.     buffer[1]     = (char)0x52;
  431.     buffer[2]     = (char)0x61;
  432.     buffer[3]     = (char)0x41;
  433.     /* StructSig = 0x61417272 */
  434.     buffer[484]   = (char)0x72;
  435.     buffer[485]   = (char)0x72;
  436.     buffer[486]   = (char)0x41;
  437.     buffer[487]   = (char)0x61;
  438.     /* Invalidate last known free cluster count */
  439.     buffer[488]   = (char)0xff;
  440.     buffer[489]   = (char)0xff;
  441.     buffer[490]   = (char)0xff;
  442.     buffer[491]   = (char)0xff;
  443.     /* Give hint for free cluster search */
  444.     buffer[492]   = (char)0xff;
  445.     buffer[493]   = (char)0xff;
  446.     buffer[494]   = (char)0xff;
  447.     buffer[495]   = (char)0xff;
  448.     /* TrailSig = 0xaa550000 */
  449.     buffer[508]   = (char)0x00;
  450.     buffer[509]   = (char)0x00;
  451.     buffer[510]   = (char)0x55;
  452.     buffer[511]   = (char)0xaa;
  453.     i = FS__lb_write(pDriver, Unit, bpb.FSInfo, (void*)buffer);
  454.     if (i < 0) {
  455.       FS__fat_free(buffer);
  456.       return -1;
  457.     }
  458.   }
  459. #endif /* FS_FAT_NOFAT32==0 */
  460.   FS__fat_free(buffer);
  461.   return 0;
  462. }
  463. /*********************************************************************
  464. *
  465. *             _FS_FAT_AutoFormat
  466. *
  467.   Description:
  468.   FS internal function. Get information about the media from the 
  469.   device driver. Based on that informaton, calculate parameters for
  470.   formatting that media and call the format routine.
  471.   Parameters:
  472.   Idx         - Index of device in the device information table 
  473.                 referred by FS__pDevInfo.
  474.   Unit        - Unit number.
  475.   
  476.   Return value:
  477.   >=0         - Media has been formatted.
  478.   <0          - An error has occured.
  479. */
  480. static int _FS_FAT_AutoFormat(int Idx, FS_u32 Unit) {
  481.   struct {
  482.     FS_u32 hiddennum;
  483.     FS_u32 headnum;
  484.     FS_u32 secnum;
  485.     FS_u32 partsize;
  486.   } devinfo;
  487.   FS_u32 rootentcnt;
  488.   FS_u32 fatsz;
  489.   FS_u32 rootdirsectors;
  490.   FS_u32 tmpval1;
  491.   FS_u32 tmpval2;
  492.   FS_u32 fatsz32;
  493.   FS_u32 totsec32;
  494.   FS_u32 resvdseccnt;
  495.   FS_u16 totsec16;
  496.   FS_u16 fatsz16;
  497.   int i;
  498.   unsigned char secperclust;
  499.   char fsystype;
  500.   /* Get info from device */
  501.   devinfo.hiddennum = 0x00001111UL;
  502.   devinfo.headnum   = 0x00002222UL;
  503.   devinfo.secnum    = 0x00003333UL;
  504.   devinfo.partsize  = 0x00004444UL;
  505.   i = FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_GET_DEVINFO, 0, (void*)&devinfo);
  506.   if (i) {
  507.     return -1;
  508.   }
  509.   /* Check if the driver really supports FS_CMD_GET_DEVINFO */
  510.   if (devinfo.hiddennum == 0x00001111UL) {
  511.     if (devinfo.headnum == 0x00002222UL) {
  512.       if (devinfo.secnum == 0x00003333UL) {
  513.         if (devinfo.partsize == 0x00004444UL) {
  514.           return -1;
  515.         }
  516.       }
  517.     }
  518.   }
  519.   if (devinfo.partsize <= 1048576UL) {
  520.     fsystype = 1;   /* FAT16 */
  521.   }
  522. #if (FS_FAT_NOFAT32==0)
  523.   else {
  524.     fsystype = 2;   /* FAT32 */
  525.   }
  526. #else
  527.   else {
  528.     /* FAT32 disabled */
  529.     return -1;
  530.   }
  531. #endif /* FS_FAT_NOFAT32==0 */
  532.   /* Set correct RootEntCnt & ResvdSecCnt */ 
  533.   if (fsystype != 2) {
  534.     /* FAT16 */
  535.     i = 0;
  536.     while (_FS_auto_rootcnt[i].SecNum < devinfo.partsize) {
  537.       i++;
  538.     }
  539.     rootentcnt = (FS_u16)_FS_auto_rootcnt[i].Num;
  540.     resvdseccnt = 1;
  541.   }
  542. #if (FS_FAT_NOFAT32==0)
  543.   else {
  544.     /* FAT32 */
  545.     rootentcnt = 0;
  546.     resvdseccnt = 0x20;
  547.   }
  548. #endif /* FS_FAT_NOFAT32==0 */
  549.   /* Determinate SecPerClust */
  550.   i = 0;
  551.   while (_FS_auto_secperclust[i].SecNum < devinfo.partsize) {
  552.     i++;
  553.   }
  554.   secperclust = (unsigned char) _FS_auto_secperclust[i].Num;
  555.   /* 
  556.      FAT16/FAT32 FAT size calculation 
  557.      The formula used is following the Microsoft specification
  558.      version 1.03 very closely. Therefore the calculated FAT
  559.      size can be up to 8 sectors bigger than required for the 
  560.      media. This is a waste of up to 8 sectors, but not a problem
  561.      regarding correctness of the media's data.
  562.   */
  563.   rootdirsectors = ((rootentcnt * 32 ) + 511) / 512;
  564.   tmpval1 = devinfo.partsize - (resvdseccnt + rootdirsectors);
  565.   tmpval2 = (256 * secperclust) + 2;
  566. #if (FS_FAT_NOFAT32==0)
  567.   if (fsystype == 2) {
  568.     tmpval2 = tmpval2 / 2;
  569.   }
  570. #endif /* FS_FAT_NOFAT32==0 */
  571.   fatsz = (tmpval1 + (tmpval2 - 1)) / tmpval2;
  572.   if (fsystype != 2) {
  573.     fatsz16 = (FS_u16)fatsz;
  574.     fatsz32 = 0;
  575.   }
  576. #if (FS_FAT_NOFAT32==0)
  577.   else {
  578.     fatsz16 = 0;
  579.     fatsz32 = fatsz;
  580.   }
  581. #endif /* FS_FAT_NOFAT32==0 */
  582.   /* Number of total sectors (512 byte units) of the media
  583.      This is independent of FAT type (FAT12/FAT16/FAT32) */
  584.   if (devinfo.partsize < 0x10000UL) {
  585.     totsec16 = (FS_u16)devinfo.partsize;
  586.     totsec32 = 0;
  587.   }
  588.   else {
  589.     totsec16 = 0;
  590.     totsec32 = devinfo.partsize;
  591.   }
  592.   /* Format media using calculated values */
  593.   i = _FS_fat_format(FS__pDevInfo[Idx].devdriver,
  594.                         Unit,
  595.                         secperclust,
  596.                         (FS_u16)rootentcnt,
  597.                         totsec16,
  598.                         totsec32,
  599.                         (char)0xf8,
  600.                         fatsz16,
  601.                         fatsz32,
  602.                         (FS_u16)devinfo.secnum,
  603.                         (FS_u16)devinfo.headnum,
  604.                         devinfo.hiddennum,
  605.                         fsystype);
  606.   return i;
  607. }
  608. #endif /* FS_FAT_NOFORMAT==0 */
  609. #if FS_FAT_DISKINFO
  610. /*********************************************************************
  611. *
  612. *             _FS_fat_GetTotalFree
  613. *
  614.   Description:
  615.   FS internal function. Store information about used/unused clusters
  616.   in a FS_DISKFREE_T data structure.
  617.   Parameters:
  618.   Idx         - Index of device in the device information table 
  619.                 referred by FS__pDevInfo.
  620.   Unit        - Unit number.
  621.   pDiskData   - Pointer to a FS_DISKFREE_T data structure.
  622.   
  623.   Return value:
  624.   ==0         - Information is stored in pDiskData.
  625.   <0          - An error has occured.
  626. */
  627. static int _FS_fat_GetTotalFree(int Idx, FS_u32 Unit, FS_DISKFREE_T *pDiskData) {
  628.   FS_u32 freeclust;
  629.   FS_u32 usedclust;
  630.   FS_u32 totclust;
  631.   FS_u32 fatentry;
  632.   FS_u32 fatsize;
  633.   FS_i32 fatoffs;
  634.   FS_i32 bytespersec;
  635.   FS_i32 cursec;
  636.   FS_i32 fatsec;
  637.   FS_i32 lastsec;
  638.   FS_i32 fatindex;
  639.   int fattype;
  640.   int err;
  641.   char *buffer;
  642.   unsigned char a;
  643.   unsigned char b;
  644. #if (FS_FAT_NOFAT32==0)
  645.   unsigned char c;
  646.   unsigned char d;
  647. #endif
  648.   
  649.   if (!pDiskData) {
  650.     return -1;  /* No pointer to a FS_DISKFREE_T structure */
  651.   }
  652.   buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
  653.   if (!buffer) {
  654.     return -1;
  655.   }
  656.   fattype = FS__fat_which_type(Idx, Unit);
  657. #if (FS_FAT_NOFAT32!=0)
  658.   if (fattype == 2) {
  659.     FS__fat_free(buffer);
  660.     return -1;
  661.   }
  662. #endif /* FS_FAT_NOFAT32!=0 */
  663.   fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz16;
  664.   if (fatsize == 0) {
  665.     fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz32;
  666.   }
  667.   bytespersec = (FS_i32)FS__FAT_aBPBUnit[Idx][Unit].BytesPerSec;
  668.   /* Calculate total allocation units on disk */
  669.   totclust = FS__FAT_aBPBUnit[Idx][Unit].TotSec16;
  670.   if (!totclust) {
  671.     totclust = FS__FAT_aBPBUnit[Idx][Unit].TotSec32;
  672.   }
  673.   totclust  -= FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt;
  674.   totclust  -= 2*fatsize;
  675.   usedclust  = FS__FAT_aBPBUnit[Idx][Unit].RootEntCnt;
  676.   usedclust *= 0x20;
  677.   usedclust /= bytespersec;
  678.   totclust  -= usedclust;
  679.   totclust  /= FS__FAT_aBPBUnit[Idx][Unit].SecPerClus;
  680.   /* Scan FAT for free and used entries */
  681.   cursec     = 0;
  682.   fatsec     = 0;
  683.   lastsec    = -1;
  684.   fatentry   = 0xffffUL;
  685.   freeclust  = 0;
  686.   usedclust  = 0;
  687.   while (1) {
  688.     if (cursec >= (FS_i32)totclust) {
  689.       break;  /* Last cluster reached */
  690.     }
  691.     if (fatsec >= (FS_i32)fatsize + FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt) {
  692.       break;  /* End of FAT reached */
  693.     }
  694.     if (fattype == 1) {
  695.       fatindex = (cursec + 2) + ((cursec + 2) / 2);    /* FAT12 */
  696.     }
  697.     else if (fattype == 2) {
  698.       fatindex = (cursec + 2) * 4;               /* FAT32 */
  699.     }
  700.     else {
  701.       fatindex = (cursec + 2) * 2;               /* FAT16 */
  702.     }
  703.     fatsec = FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt + (fatindex / bytespersec);
  704.     fatoffs = fatindex % bytespersec;
  705.     if (fatsec != lastsec) {
  706.       err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
  707.       if (err < 0) {
  708.         err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec, (void*)buffer);
  709.         if (err < 0) {
  710.           FS__fat_free(buffer);
  711.           return -1;
  712.         }
  713.         /* Try to repair original FAT sector with contents of copy */
  714.         FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
  715.       }
  716.       lastsec = fatsec;
  717.     }
  718.     if (fattype == 1) {
  719.       if (fatoffs == (bytespersec - 1)) {
  720.         a = buffer[fatoffs];
  721.         err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec+1, (void*)buffer);
  722.         if (err < 0) {
  723.           err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec + 1, (void*)buffer);
  724.           if (err < 0) {
  725.             FS__fat_free(buffer);
  726.             return -1;
  727.           }
  728.           /* Try to repair original FAT sector with contents of copy */
  729.           FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec + 1, (void*)buffer);
  730.         }
  731.         lastsec = fatsec + 1;
  732.         b = buffer[0];
  733.       }
  734.       else {
  735.         a = buffer[fatoffs];
  736.         b = buffer[fatoffs + 1];
  737.       }
  738.       if (cursec & 1) {
  739.         fatentry = ((a & 0xf0) >> 4 ) + 16 * b;
  740.       }
  741.       else {
  742.         fatentry = a + 256 * (b & 0x0f);
  743.       }
  744.       fatentry &= 0x0fff;
  745.     }
  746. #if (FS_FAT_NOFAT32==0)
  747.     else if (fattype == 2) {
  748.       a = buffer[fatoffs];
  749.       b = buffer[fatoffs + 1];
  750.       c = buffer[fatoffs + 2];
  751.       d = buffer[fatoffs + 3];
  752.       fatentry = a + 0x100UL * b + 0x10000UL * c + 0x1000000UL * d;
  753.       fatentry &= 0x0fffffffUL;
  754.     }
  755. #endif /* FS_FAT_NOFAT32==0 */
  756.     else {
  757.       a = buffer[fatoffs];
  758.       b = buffer[fatoffs + 1];
  759.       fatentry = a + 256 * b;
  760.       fatentry &= 0xffffUL;
  761.     }
  762.     cursec++;
  763.     if (fatentry == 0) {
  764.       freeclust++;
  765.     }
  766.     else {
  767.       usedclust++;
  768.     }
  769.   }
  770.   FS__fat_free(buffer);
  771.   pDiskData->total_clusters      = totclust;
  772.   pDiskData->avail_clusters      = freeclust;
  773.   pDiskData->sectors_per_cluster = FS__FAT_aBPBUnit[Idx][Unit].SecPerClus;
  774.   pDiskData->bytes_per_sector    = (FS_u16)bytespersec;
  775.   return 0;
  776. }
  777. #endif /* FS_FAT_DISKINFO */
  778. /*********************************************************************
  779. *
  780. *             Global functions
  781. *
  782. **********************************************************************
  783. */
  784. /*********************************************************************
  785. *
  786. *             FS__fat_ioctl
  787. *
  788.   Description:
  789.   FS internal function. Execute device command. The FAT layer checks
  790.   first, if it has to process the command (e.g. format). Any other
  791.   command is passed to the device driver.
  792.   Parameters:
  793.   Idx         - Index of device in the device information table 
  794.                 referred by FS__pDevInfo.
  795.   Unit        - Unit number.
  796.   Cmd         - Command to be executed.
  797.   Aux         - Parameter depending on command.
  798.   pBuffer     - Pointer to a buffer used for the command.
  799.   
  800.   Return value:
  801.   Command specific. In general a negative value means an error.
  802. */
  803. int FS__fat_ioctl(int Idx, FS_u32 Unit, FS_i32 Cmd, FS_i32 Aux, void *pBuffer) {
  804.   int x;
  805. #if ((FS_SUPPORT_SEC_ACCESS) || (FS_FAT_NOFORMAT==0))
  806.   int i;
  807. #endif
  808. #if (FS_FAT_NOFORMAT==0)
  809.   int j;
  810. #endif
  811.   FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_INC_BUSYCNT, 0, (void*)0);  /* Turn on busy signal */
  812. #if (FS_FAT_NOFORMAT==0)
  813.   if (Cmd == FS_CMD_FORMAT_MEDIA) {
  814.     j = 0;
  815.     while (1) {
  816.       if (j >= FS_KNOWNMEDIA_NUM) {
  817.         break;  /* Not a known media */
  818.       }
  819.       if (_FS_wd_format_media_table[j].media_id == Aux) {
  820.         break;  /* Media found in the list */
  821.       }
  822.       j++;
  823.     } //find the right media
  824.     if (j >= FS_KNOWNMEDIA_NUM) { //can't find the right media
  825.       FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0);  /* Turn off busy signal */
  826.       return -1;
  827.     }
  828.     i = FS__lb_status(FS__pDevInfo[Idx].devdriver, Unit); //get status of device, if ok return 1
  829.     if (i >= 0) {
  830.       x = _FS_fat_format(FS__pDevInfo[Idx].devdriver,
  831.                           Unit,
  832.                           _FS_wd_format_media_table[j].secperclus,
  833.                           _FS_wd_format_media_table[j].rootentcnt,
  834.                           _FS_wd_format_media_table[j].totsec16,
  835.                           _FS_wd_format_media_table[j].totsec32,
  836.                           _FS_wd_format_media_table[j].media,
  837.                           _FS_wd_format_media_table[j].fatsz16,
  838.                           0,
  839.                           _FS_wd_format_media_table[j].secpertrk,
  840.                           _FS_wd_format_media_table[j].numheads,
  841.                           _FS_wd_format_media_table[j].hiddsec,
  842.                           _FS_wd_format_media_table[j].fsystype);
  843.       i = FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_FLUSH_CACHE, 0, (void*)0);
  844.       if (i < 0) {
  845.         x = i;
  846.       }
  847.       else {
  848.         /* Invalidate BPB */
  849.         for (i = 0; i < (int)FS__maxdev; i++) {
  850.           for (j = 0; j < (int)FS__fat_maxunit; j++) {
  851.               FS__FAT_aBPBUnit[i][j].Signature = 0x0000;
  852.           }
  853.         }
  854.       }
  855.     }
  856.     else {
  857.       FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0);  /* Turn off busy signal */
  858.       return -1;
  859.     }
  860.   }
  861.   else if (Cmd == FS_CMD_FORMAT_AUTO) {
  862.     i = FS__lb_status(FS__pDevInfo[Idx].devdriver, Unit);
  863.     if (i >= 0) {
  864.       x = _FS_FAT_AutoFormat(Idx, Unit);
  865.       i = FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_FLUSH_CACHE, 0, (void*)0);
  866.       if (i < 0) {
  867.         x = i;
  868.       }
  869.     }
  870.     else {
  871.       x = -1;
  872.     }
  873.   }
  874. #else /* FS_FAT_NOFORMAT==0 */
  875.   if (Cmd == FS_CMD_FORMAT_MEDIA) {
  876.     x = -1;  /* Format command is not supported */
  877.   }
  878. #endif /* FS_FAT_NOFORMAT==0 */
  879. #if FS_FAT_DISKINFO
  880.   else if (Cmd == FS_CMD_GET_DISKFREE) {
  881.     i = FS__fat_checkunit(Idx, Unit);
  882.     if (i > 0) {
  883.       x = _FS_fat_GetTotalFree(Idx, Unit, (FS_DISKFREE_T*)pBuffer);
  884.       i = FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_FLUSH_CACHE, 0, (void*)0);
  885.       if (i < 0) {
  886.         x = i;
  887.       }
  888.     }
  889.     else {
  890.       x = -1;
  891.     }
  892.   }
  893. #else /* FS_FAT_DISKINFO==0 */
  894.   else if (Cmd == FS_CMD_GET_DISKFREE) {
  895.     x = -1; /* Diskinfo command not supported */
  896.   }
  897. #endif /* FS_FAT_DISKINFO */
  898. #if FS_SUPPORT_SEC_ACCESS
  899.   else if ((Cmd == FS_CMD_READ_SECTOR) || (Cmd == FS_CMD_WRITE_SECTOR)) {
  900.     if (!pBuffer) {
  901.       FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0);
  902.       return -1;
  903.     }
  904.     i = FS__lb_status(FS__pDevInfo[Idx].devdriver, Unit);
  905.     if (i >= 0) {
  906.       if (Cmd == FS_CMD_READ_SECTOR) {
  907.         x = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, Aux, pBuffer);
  908.       }
  909.       else {
  910.         x = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, Aux, pBuffer);
  911.       }
  912.     }
  913.     else {
  914.       x = -1;
  915.     }
  916.   }
  917. #else /* FS_SUPPORT_SEC_ACCESS */
  918.   else if ((Cmd == FS_CMD_READ_SECTOR) || (Cmd == FS_CMD_WRITE_SECTOR)) {
  919.     FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0);
  920.     return -1;
  921.   }
  922. #endif /* FS_SUPPORT_SEC_ACCESS */
  923.   else {
  924.     /* Maybe command for driver */
  925.     x = FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, Cmd, Aux, (void*)pBuffer);
  926.   }
  927.   FS__lb_ioctl(FS__pDevInfo[Idx].devdriver, Unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0);  /* Turn off busy signal */
  928.   return x;
  929. }