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

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_misc.c
  15. Purpose     : File system's FAT File System Layer misc routines
  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. #ifndef FS_FAT_NOFAT32
  45.   #define FS_FAT_NOFAT32        0
  46. #endif /* FS_FAT_NOFAT32 */
  47. #ifndef FS_DIR_MAXOPEN
  48.   #define FS_DIR_MAXOPEN        0
  49. #endif /* FS_DIR_MAXOPEN */
  50. #define FS_MEMBLOCK_NUM   (FS_MAXOPEN+FS_DIR_MAXOPEN)*2
  51. /*********************************************************************
  52. *
  53. *             Local data types
  54. *
  55. **********************************************************************
  56. */
  57. typedef struct {
  58.   int status;
  59.   char memory[FS_FAT_SEC_SIZE];
  60. } _FS_FAT_block_type;
  61. /*********************************************************************
  62. *
  63. *             Local Variables        
  64. *
  65. **********************************************************************
  66. */
  67. static _FS_FAT_block_type          _FS_memblock[FS_MEMBLOCK_NUM];
  68. /*********************************************************************
  69. *
  70. *             Local functions section
  71. *
  72. **********************************************************************
  73. */
  74. /*********************************************************************
  75. *
  76. *             _FS_ReadBPB
  77. *
  78.   Description:
  79.   FS internal function. Read Bios-Parameter-Block from a device and
  80.   copy the relevant data to FS__FAT_aBPBUnit.
  81.   Parameters:
  82.   Idx         - Index of device in the device information table 
  83.                 referred by FS__pDevInfo.
  84.   Unit        - Unit number.
  85.  
  86.   Return value:
  87.   ==0         - BPB successfully read.
  88.   <0          - An error has occured.
  89. */
  90. static int _FS_ReadBPB(int Idx, FS_u32 Unit) {
  91.   int err;
  92.   unsigned char *buffer;
  93.   
  94.   buffer = (unsigned char*)FS__fat_malloc(FS_FAT_SEC_SIZE);
  95.   if (!buffer) {
  96.     return -1;
  97.   }
  98.   err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, 0, (void*)buffer);
  99.   if (err < 0) {
  100.     FS__fat_free(buffer);
  101.     return -1;
  102.   }
  103.   /* Assign FS__FAT_aBPBUnit */
  104.   FS__FAT_aBPBUnit[Idx][Unit].BytesPerSec   = buffer[11] + 256 * buffer[12];      /* _512_,1024,2048,4096           */
  105.   FS__FAT_aBPBUnit[Idx][Unit].SecPerClus    = buffer[13];                         /* sec in allocation unit         */
  106.   FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt    = buffer[14] + 256 * buffer[15];      /* 1 for FAT12 & FAT16            */
  107.   FS__FAT_aBPBUnit[Idx][Unit].NumFATs       = buffer[16];                         /* 2                              */
  108.   FS__FAT_aBPBUnit[Idx][Unit].RootEntCnt    = buffer[17] + 256 * buffer[18];      /* number of root dir entries     */
  109.   FS__FAT_aBPBUnit[Idx][Unit].TotSec16      = buffer[19] + 256 * buffer[20];      /* RSVD + FAT + ROOT + FATA (<64k) */
  110.   FS__FAT_aBPBUnit[Idx][Unit].FATSz16       = buffer[22] + 256 * buffer[23];      /* number of FAT sectors          */
  111.   FS__FAT_aBPBUnit[Idx][Unit].TotSec32      = buffer[32] + 0x100UL * buffer[33]   /* RSVD + FAT + ROOT + FATA (>=64k) */
  112.                                               + 0x10000UL * buffer[34] 
  113.                                               + 0x1000000UL * buffer[35];
  114.   if (FS__FAT_aBPBUnit[Idx][Unit].FATSz16 == 0) {
  115.     FS__FAT_aBPBUnit[Idx][Unit].FATSz32       = buffer[36] + 0x100UL * buffer[37]   /* number of FAT sectors          */
  116.                                                 + 0x10000UL * buffer[38] 
  117.                                                 + 0x1000000UL * buffer[39];
  118.     FS__FAT_aBPBUnit[Idx][Unit].ExtFlags      = buffer[40] + 256 * buffer[41];      /* mirroring info                 */
  119.     FS__FAT_aBPBUnit[Idx][Unit].RootClus      = buffer[44] + 0x100UL * buffer[45]   /* root dir clus for FAT32        */
  120.                                                 + 0x10000UL * buffer[46] 
  121.                                                 + 0x1000000UL * buffer[47];
  122.     FS__FAT_aBPBUnit[Idx][Unit].FSInfo        = buffer[48] + 256 * buffer[49];      /* position of FSInfo structure   */
  123.   }
  124.   else {
  125.     FS__FAT_aBPBUnit[Idx][Unit].FATSz32       = 0;
  126.     FS__FAT_aBPBUnit[Idx][Unit].ExtFlags      = 0;
  127.     FS__FAT_aBPBUnit[Idx][Unit].RootClus      = 0;
  128.     FS__FAT_aBPBUnit[Idx][Unit].FSInfo        = 0;
  129.   }
  130.   FS__FAT_aBPBUnit[Idx][Unit].Signature     = buffer[FS_FAT_SEC_SIZE-2] 
  131.                                               + 256 * buffer[FS_FAT_SEC_SIZE-1];
  132.   FS__fat_free(buffer);
  133.   return err;
  134. }
  135. /*********************************************************************
  136. *
  137. *             _FS__fat_FindFreeCluster
  138. *
  139.   Description:
  140.   FS internal function. Find the next free entry in the FAT.
  141.   Parameters:
  142.   Idx         - Index of device in the device information table 
  143.                 referred by FS__pDevInfo.
  144.   Unit        - Unit number.
  145.   pFATSector  - Returns the sector number of the free entry. 
  146.   pLastSector - Returns the sector number of the sector in pBuffer.
  147.   pFATOffset  - Returns the offset of the free FAT entry within the
  148.                 sector pFATSector.
  149.   LastClust   - Cluster, which will be used to link the new allocated
  150.                 cluster to. Here it is used at hint for where to start
  151.                 in the FAT.
  152.   pBuffer     - Pointer to a sector buffer.
  153.   FSysType    - ==1 => FAT12
  154.                 ==0 => FAT16
  155.                 ==2 => FAT32
  156.   FATSize     - Size of one FAT ind sectors.
  157.   BytesPerSec - Number of bytes in each sector.
  158.  
  159.   Return value:
  160.   >=0         - Number of the free cluster.
  161.   <0          - An error has occured.
  162. */
  163. static FS_i32 _FS__fat_FindFreeCluster(int Idx, FS_u32 Unit, FS_i32 *pFATSector, 
  164.                                        FS_i32 *pLastSector, FS_i32 *pFATOffset, 
  165.                                        FS_i32 LastClust, unsigned char *pBuffer, 
  166.                                        int FSysType, FS_u32 FATSize, FS_i32 BytesPerSec) {
  167.   FS_u32 totclst;
  168.   FS_u32 rootdirsize;
  169.   FS_i32 curclst;
  170.   FS_i32 fatindex;
  171.   int err;
  172.   int scan;
  173.   unsigned char fatentry;
  174.   unsigned char a;
  175.   unsigned char b;
  176. #if (FS_FAT_NOFAT32==0)  
  177.   unsigned char c;
  178.   unsigned char d;
  179. #endif  
  180.   
  181.   if (LastClust > 0) {
  182.     curclst = LastClust + 1;  /* Start scan after the previous allocated sector */
  183.   }
  184.   else {
  185.     curclst = 0;  /*  Start scan at the beginning of the media */
  186.   }
  187.   scan          = 0;
  188.   *pFATSector   = 0;
  189.   *pLastSector  = -1;
  190.   fatentry      = 0xff;
  191.   /* Calculate total number of data clusters on the media */
  192.   totclst = (FS_u32)FS__FAT_aBPBUnit[Idx][Unit].TotSec16;
  193.   if (totclst == 0) {
  194.     totclst = FS__FAT_aBPBUnit[Idx][Unit].TotSec32;
  195.   }
  196.   rootdirsize = ((FS_u32)((FS_u32)FS__FAT_aBPBUnit[Idx][Unit].RootEntCnt) * FS_FAT_DENTRY_SIZE) / BytesPerSec;
  197.   totclst     = totclst - (FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt + FS__FAT_aBPBUnit[Idx][Unit].NumFATs * FATSize + rootdirsize);
  198.   totclst    /= FS__FAT_aBPBUnit[Idx][Unit].SecPerClus;
  199.   while (1) {
  200.     if (curclst >= (FS_i32)totclst) {
  201.       scan++;
  202.       if (scan > 1) {
  203.         break;  /* End of clusters reached after 2nd scan */
  204.       }
  205.       if (LastClust <= 0) {
  206.         break;  /* 1st scan started already at zero */
  207.       }
  208.       curclst   = 0;  /* Try again starting at the beginning of the FAT */
  209.       fatentry  = 0xff;
  210.     }
  211.     if (fatentry == 0) {
  212.       break;  /* Free entry found */
  213.     }
  214.     if (FSysType == 1) {
  215.       fatindex = curclst + (curclst / 2);    /* FAT12 */
  216.     }
  217.     else if (FSysType == 2) {
  218.       fatindex = curclst * 4;               /* FAT32 */
  219.     }
  220.     else {
  221.       fatindex = curclst * 2;               /* FAT16 */
  222.     }
  223.     *pFATSector = FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt + (fatindex / BytesPerSec);
  224.     *pFATOffset = fatindex % BytesPerSec;
  225.     if (*pFATSector != *pLastSector) {
  226.       err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, *pFATSector, (void*)pBuffer);
  227.       if (err < 0) {
  228.         err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, FATSize + *pFATSector, (void*)pBuffer);
  229.         if (err < 0) {
  230.           return -1;
  231.         }
  232.         /* Try to repair original FAT sector with contents of copy */
  233.         FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, *pFATSector, (void*)pBuffer);
  234.       }
  235.       *pLastSector = *pFATSector;
  236.     }
  237.     if (FSysType == 1) {
  238.       if (*pFATOffset == (BytesPerSec - 1)) {
  239.         a = pBuffer[*pFATOffset];
  240.         err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, *pFATSector + 1, (void*)pBuffer);
  241.         if (err < 0) {
  242.           err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, FATSize + *pFATSector + 1, (void*)pBuffer);
  243.           if (err < 0) {
  244.             return -1;
  245.           }
  246.           /* Try to repair original FAT sector with contents of copy */
  247.           FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, *pFATSector + 1, (void*)pBuffer);
  248.         }
  249.         *pLastSector = *pFATSector + 1;
  250.         b = pBuffer[0];
  251.       }
  252.       else {
  253.         a = pBuffer[*pFATOffset];
  254.         b = pBuffer[*pFATOffset + 1];
  255.       }
  256.       if (curclst & 1) {
  257.         fatentry = ((a & 0xf0) >> 4 ) | b;
  258.       }
  259.       else {
  260.         fatentry = a | (b & 0x0f);
  261.       }
  262.     }
  263. #if (FS_FAT_NOFAT32==0)
  264.     else if (FSysType == 2) {
  265.       a = pBuffer[*pFATOffset];
  266.       b = pBuffer[*pFATOffset + 1];
  267.       c = pBuffer[*pFATOffset + 2];
  268.       d = pBuffer[*pFATOffset + 3];
  269.       fatentry = a | b | c | d;
  270.     }
  271. #endif /* FS_FAT_NOFAT32==0 */
  272.     else {
  273.       a = pBuffer[*pFATOffset];
  274.       b = pBuffer[*pFATOffset + 1];
  275.       fatentry = a | b;
  276.     }
  277.     if (fatentry != 0) {
  278.       curclst++;  /* Cluster is in use or defect, so try the next one */
  279.     }
  280.   }
  281.   if (fatentry == 0) {
  282.     return curclst;  /* Free cluster found */
  283.   }
  284.   return -1;
  285. }
  286. /*********************************************************************
  287. *
  288. *             _FS__fat_SetEOFMark
  289. *
  290.   Description:
  291.   FS internal function. Set the EOF mark in the FAT for a cluster.
  292.   The function does not write the FAT sector. An exception is FAT12,
  293.   if the FAT entry is in two sectors. 
  294.   Parameters:
  295.   Idx         - Index of device in the device information table 
  296.                 referred by FS__pDevInfo.
  297.   Unit        - Unit number.
  298.   FATSector   - FAT sector, where the cluster is located. 
  299.   pLastSector - Pointer to an FS_i32, which contains the number of the 
  300.                 sector in pBuffer.
  301.   FATOffset   - Offset of the cluster in the FAT sector.
  302.   Cluster     - Cluster number, where to set the EOF mark.
  303.   pBuffer     - Pointer to a sector buffer.
  304.   FSysType    - ==1 => FAT12
  305.                 ==0 => FAT16
  306.                 ==2 => FAT32
  307.   FATSize     - Size of one FAT ind sectors.
  308.   BytesPerSec - Number of bytes in each sector.
  309.  
  310.   Return value:
  311.   >=0         - EOF mark set.
  312.   <0          - An error has occured.
  313. */
  314. static int _FS__fat_SetEOFMark(int Idx, FS_u32 Unit, FS_i32 FATSector, 
  315.                                FS_i32 *pLastSector, FS_i32 FATOffset, 
  316.                                FS_i32 Cluster, unsigned char *pBuffer, 
  317.                                int FSysType, FS_u32 FATSize, FS_i32 BytesPerSec) {
  318.   int err1;
  319.   int err2;
  320.   int lexp;
  321.   
  322.   if (FSysType == 1) {
  323.     if (FATOffset == (BytesPerSec - 1)) {
  324.       /* Entry in 2 sectors (we have 2nd sector in buffer) */
  325.       if (Cluster & 1) {
  326.         pBuffer[0]  = (char)0xff;
  327.       }
  328.       else {
  329.         pBuffer[0] |= (char)0x0f;
  330.       }
  331.       err1 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, FATSector + 1, (void*)pBuffer);
  332.       err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, FATSize + FATSector + 1, (void*)pBuffer);
  333.       lexp = (err1 < 0);
  334.       lexp = lexp || (err2 < 0);
  335.       if (lexp) {
  336.         return -1;
  337.       }
  338.       err1 = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, FATSector, (void*)pBuffer);
  339.       if (err1 < 0) {
  340.         err1 = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, FATSize + FATSector, (void*)pBuffer);
  341.         if (err1 < 0) {
  342.           return -1;
  343.         }
  344.         /* Try to repair original FAT sector with contents of copy */
  345.         FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, FATSector, (void*)pBuffer);
  346.       }
  347.       *pLastSector = FATSector;
  348.       if (Cluster & 1) {
  349.         pBuffer[FATOffset] |= (char)0xf0;
  350.       }
  351.       else {
  352.         pBuffer[FATOffset]  = (char)0xff;
  353.       }
  354.     }
  355.     else {
  356.       if (Cluster & 1) {
  357.         pBuffer[FATOffset]   |= (char)0xf0;
  358.         pBuffer[FATOffset+1]  = (char)0xff;
  359.       }
  360.       else {
  361.         pBuffer[FATOffset]    = (char)0xff;
  362.         pBuffer[FATOffset+1] |= (char)0x0f;
  363.       }
  364.     }
  365.   }
  366. #if (FS_FAT_NOFAT32==0)
  367.   else if (FSysType == 2) { /* FAT32 */
  368.     pBuffer[FATOffset]      = (char)0xff;
  369.     pBuffer[FATOffset + 1]  = (char)0xff;
  370.     pBuffer[FATOffset + 2]  = (char)0xff;
  371.     pBuffer[FATOffset + 3]  = (char)0x0f;
  372.   }
  373. #endif /* FS_FAT_NOFAT32==0 */
  374.   else { /* FAT16 */
  375.     pBuffer[FATOffset]      = (char)0xff;
  376.     pBuffer[FATOffset + 1]  = (char)0xff;
  377.   }
  378.   return 0;
  379. }
  380. /*********************************************************************
  381. *
  382. *             _FS__fat_LinkCluster
  383. *
  384.   Description:
  385.   FS internal function. Link the new cluster with the EOF mark to the 
  386.   cluster list.
  387.   Parameters:
  388.   Idx         - Index of device in the device information table 
  389.                 referred by FS__pDevInfo.
  390.   Unit        - Unit number.
  391.   pLastSector - Pointer to an FS_i32, which contains the number of the 
  392.                 sector in pBuffer.
  393.   Cluster     - Cluster number of the new cluster with the EOF mark.
  394.   LastClust   - Number of cluster, to which the new allocated cluster
  395.                 is linked to.
  396.   pBuffer     - Pointer to a sector buffer.
  397.   FSysType    - ==1 => FAT12
  398.                 ==0 => FAT16
  399.                 ==2 => FAT32
  400.   FATSize     - Size of one FAT ind sectors.
  401.   BytesPerSec - Number of bytes in each sector.
  402.  
  403.   Return value:
  404.   >=0         - Link has been made.
  405.   <0          - An error has occured.
  406. */
  407. static int _FS__fat_LinkCluster(int Idx, FS_u32 Unit, FS_i32 *pLastSector, FS_i32 Cluster,
  408.                                 FS_i32 LastClust, unsigned char *pBuffer, int FSysType, 
  409.                                 FS_u32 FATSize, FS_i32 BytesPerSec) {
  410.   FS_i32 fatindex;
  411.   FS_i32 fatoffs;
  412.   FS_i32 fatsec;
  413.   int lexp;
  414.   int err;
  415.   int err2;
  416.   unsigned char a;
  417.   unsigned char b;
  418. #if (FS_FAT_NOFAT32==0)  
  419.   unsigned char c;
  420.   unsigned char d;
  421. #endif
  422.   /* Link old last cluster to this one */
  423.   if (FSysType == 1) {
  424.     fatindex = LastClust + (LastClust / 2); /* FAT12 */
  425.   }
  426.   else if (FSysType == 2) {
  427.     fatindex = LastClust * 4;               /* FAT32 */
  428.   }
  429.   else {
  430.     fatindex = LastClust * 2;               /* FAT16 */
  431.   }
  432.   fatsec = FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt + (fatindex / BytesPerSec);
  433.   fatoffs = fatindex % BytesPerSec;
  434.   if (fatsec != *pLastSector) {
  435.     /* 
  436.        FAT entry, which has to be modified is not in the same FAT sector, which is
  437.        currently in the buffer. So write it to the media now.
  438.     */
  439.     err  = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, *pLastSector, (void*)pBuffer);
  440.     err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, *pLastSector + FATSize, (void*)pBuffer);
  441.     lexp = (err < 0);
  442.     lexp = lexp || (err2 < 0);
  443.     if (lexp) {
  444.       return -1;
  445.     }
  446.     err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)pBuffer);
  447.     if (err < 0) {
  448.       err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, FATSize + fatsec, (void*)pBuffer);
  449.       if (err<0) {
  450.         return -1;
  451.       }
  452.       /* Try to repair original FAT sector with contents of copy */
  453.       FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)pBuffer);
  454.     }
  455.     *pLastSector = fatsec;
  456.   }
  457.   a = Cluster & 0xff;
  458.   b = (Cluster / 0x100L) & 0xff;
  459. #if (FS_FAT_NOFAT32==0)
  460.   c = (Cluster / 0x10000L) & 0xff;
  461.   d = (Cluster / 0x1000000L) & 0x0f;
  462. #endif      
  463.   if (FSysType == 1) {
  464.     if (fatoffs == (BytesPerSec - 1)) {
  465.       /* Entry in 2 sectors (we have 2nd sector in buffer) */
  466.       if (LastClust & 1) {
  467.         pBuffer[fatoffs]   &= (char)0x0f;
  468.         pBuffer[fatoffs]   |= (char)((a << 4) & 0xf0);
  469.       }
  470.       else {
  471.         pBuffer[fatoffs]    = (char)(a & 0xff);
  472.       }
  473.       err  = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)pBuffer);
  474.       err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, FATSize + fatsec, (void*)pBuffer);
  475.       lexp = (err < 0);
  476.       lexp = lexp || (err2 < 0);
  477.       if (lexp) {
  478.         return -1;
  479.       }
  480.       err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec + 1, (void*)pBuffer);
  481.       if (err < 0) {
  482.         return -1;
  483.       }
  484.       *pLastSector = fatsec + 1;
  485.       if (LastClust & 1) {
  486.         pBuffer[0]  = (char)(((a >> 4) & 0x0f) | ((b << 4) & 0xf0));
  487.       }
  488.       else {
  489.         pBuffer[0] &= (char)0xf0;
  490.         pBuffer[0] |= (char)(b & 0x0f);
  491.       }
  492.       err  = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec + 1, (void*)pBuffer);
  493.       err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, FATSize + fatsec + 1, (void*)pBuffer);
  494.       lexp = (err < 0);
  495.       lexp = lexp || (err2 < 0);
  496.       if (lexp) {
  497.         return -1;
  498.       }
  499.     }
  500.     else {
  501.       if (LastClust & 1) {
  502.         pBuffer[fatoffs]     &= (char)0x0f;
  503.         pBuffer[fatoffs]     |= (char)((a << 4) & 0xf0);
  504.         pBuffer[fatoffs + 1]  = (char)(((a >> 4) & 0x0f) | ((b << 4) & 0xf0));
  505.       }
  506.       else {
  507.         pBuffer[fatoffs]      = (char)(a & 0xff);
  508.         pBuffer[fatoffs + 1] &= (char)0xf0;
  509.         pBuffer[fatoffs + 1] |= (char)(b & 0x0f);
  510.       }
  511.       err  = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)pBuffer);
  512.       err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, FATSize + fatsec, (void*)pBuffer);
  513.       lexp = (err < 0);
  514.       lexp = lexp || (err2 < 0);
  515.       if (lexp) {
  516.         return -1;
  517.       }
  518.     }
  519.   }
  520. #if (FS_FAT_NOFAT32==0)
  521.   else if (FSysType == 2) { /* FAT32 */
  522.     pBuffer[fatoffs]      = a;
  523.     pBuffer[fatoffs + 1]  = b;
  524.     pBuffer[fatoffs + 2]  = c;
  525.     pBuffer[fatoffs + 3]  = d;
  526.     err  = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)pBuffer);
  527.     err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, FATSize + fatsec, (void*)pBuffer);
  528.     lexp = (err < 0) ;
  529.     lexp = lexp || (err2 < 0);
  530.     if (lexp) {
  531.       return -1;
  532.     }
  533.   }
  534. #endif /* FS_FAT_NOFAT32==0 */
  535.   else { /* FAT16 */
  536.     pBuffer[fatoffs]      = a;
  537.     pBuffer[fatoffs + 1]  = b;
  538.     err  = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)pBuffer);
  539.     err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, FATSize + fatsec, (void*)pBuffer);
  540.     lexp = (err < 0);
  541.     lexp = lexp || (err2 < 0);
  542.     if (lexp) {
  543.       return -1;
  544.     }
  545.   }
  546.   return 0;
  547. }
  548. /*********************************************************************
  549. *
  550. *             Global functions section
  551. *
  552. **********************************************************************
  553.   Functions in this section are used by FAT File System layer only
  554.   
  555. */
  556. /*********************************************************************
  557. *
  558. *             FS__fat_block_init
  559. *
  560.   Description:
  561.   FS internal function. Init FAT block memory management.
  562.   Parameters:
  563.   None.
  564.  
  565.   Return value:
  566.   None.
  567. */
  568. void FS__fat_block_init(void) {
  569.   int i;
  570.   FS_X_OS_LockMem();
  571.   for (i = 0; i < FS_MEMBLOCK_NUM; i++) {
  572.     _FS_memblock[i].status = 0;
  573.   }
  574.   FS_X_OS_UnlockMem();
  575. }
  576. /*********************************************************************
  577. *
  578. *             FS__fat_malloc
  579. *
  580.   Description:
  581.   FS internal function. Allocate a sector buffer.
  582.   Parameters:
  583.   Size        - Size of the sector buffer. Normally this is 512.
  584.                 Parameter is for future extension.
  585.  
  586.   Return value:
  587.   ==0         - Cannot allocate a buffer.
  588.   !=0         - Address of a buffer.
  589. */
  590. char *FS__fat_malloc(unsigned int Size) {
  591.   int i;
  592.   FS_X_OS_LockMem();
  593.   if (Size <= FS_FAT_SEC_SIZE) {
  594.     for (i = 0; i < FS_MEMBLOCK_NUM; i++) {
  595.       if (_FS_memblock[i].status == 0) {
  596.         _FS_memblock[i].status = 1;
  597.         FS__CLIB_memset((void*)_FS_memblock[i].memory, 0, (FS_size_t)FS_FAT_SEC_SIZE);
  598.         FS_X_OS_UnlockMem();
  599.         return ((void*)_FS_memblock[i].memory);
  600.       }
  601.     }
  602.   }
  603.   FS_X_OS_UnlockMem();
  604.   return 0;
  605. }
  606. /*********************************************************************
  607. *
  608. *             FS__fat_free
  609. *
  610.   Description:
  611.   FS internal function. Free sector buffer.
  612.   Parameters:
  613.   pBuffer     - Pointer to a buffer, which has to be set free.
  614.  
  615.   Return value:
  616.   None.
  617. */
  618. void FS__fat_free(void *pBuffer) {
  619.   int i;
  620.   FS_X_OS_LockMem();
  621.   for (i = 0; i < FS_MEMBLOCK_NUM; i++) {
  622.     if (((void*)_FS_memblock[i].memory) == pBuffer) {
  623.       _FS_memblock[i].status = 0;
  624.       FS_X_OS_UnlockMem();
  625.       return;
  626.     }
  627.   }
  628.   FS_X_OS_UnlockMem();
  629. }
  630. /*********************************************************************
  631. *
  632. *             FS__fat_checkunit
  633. *
  634.   Description:
  635.   FS internal function. Read Bios-Parameter-Block from a device and
  636.   check, if it contains valid data.
  637.   Parameters:
  638.   Idx         - Index of device in the device information table 
  639.                 referred by FS__pDevInfo.
  640.   Unit        - Unit number.
  641.  
  642.   Return value:
  643.   ==1         - BPB is okay.
  644.   ==0         - An error has occured.
  645. */
  646. int FS__fat_checkunit(int Idx, FS_u32 Unit) {
  647.   int err;
  648.   int status;
  649.   int lexp;
  650.   
  651.   status = FS__lb_status(FS__pDevInfo[Idx].devdriver, Unit);
  652.   if (status < 0) {
  653.     return 0;
  654.   }
  655.   if (status == FS_LBL_MEDIACHANGED) {
  656.     /* Mount new volume */
  657.     err = _FS_ReadBPB(Idx, Unit);
  658.     if (err < 0) {
  659.       return 0;
  660.     }
  661.   }
  662.   if (FS__FAT_aBPBUnit[Idx][Unit].Signature != 0xaa55) {
  663.     err = _FS_ReadBPB(Idx, Unit);
  664.     lexp = (err < 0);
  665.     lexp = lexp || (FS__FAT_aBPBUnit[Idx][Unit].Signature != 0xaa55);
  666.     if (lexp) {
  667.       return 0;
  668.     }
  669.   }
  670.   if (FS__FAT_aBPBUnit[Idx][Unit].NumFATs != 2) {
  671.     return 0;  /* Only 2 FATs are supported */
  672.   }
  673.   if (FS__FAT_aBPBUnit[Idx][Unit].FATSz16 == 0) {
  674.     if (FS__FAT_aBPBUnit[Idx][Unit].ExtFlags & 0x0080) {
  675.       return 0;  /* Only mirroring at runtime supported */
  676.     }
  677.   }
  678.   return 1;
  679. }
  680. /*********************************************************************
  681. *
  682. *             FS__fat_which_type
  683. *
  684.   Description:
  685.   FS internal function. Determine FAT type used on a media. This
  686.   function is following the MS specification very closely.
  687.   Parameters:
  688.   Idx         - Index of device in the device information table 
  689.                 referred by FS__pDevInfo.
  690.   Unit        - Unit number.
  691.  
  692.   Return value:
  693.   ==0         - FAT16.
  694.   ==1         - FAT12.
  695.   ==2         - FAT32
  696. */
  697. int FS__fat_which_type(int Idx, FS_u32 Unit) {
  698.   FS_u32 coc;
  699.   FS_u32 fatsize;
  700.   FS_u32 totsec;
  701.   FS_u32 datasec;
  702.   FS_u32 bytespersec;
  703.   FS_u32 dsize;
  704.   bytespersec   = (FS_u32)FS__FAT_aBPBUnit[Idx][Unit].BytesPerSec;
  705.   dsize         = ((FS_u32)((FS_u32)FS__FAT_aBPBUnit[Idx][Unit].RootEntCnt) * FS_FAT_DENTRY_SIZE) / bytespersec;
  706.   fatsize       = FS__FAT_aBPBUnit[Idx][Unit].FATSz16;
  707.   if (fatsize == 0) {
  708.     fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz32;
  709.   }
  710.   totsec = (FS_u32)FS__FAT_aBPBUnit[Idx][Unit].TotSec16;
  711.   if (totsec == 0) {
  712.     totsec = FS__FAT_aBPBUnit[Idx][Unit].TotSec32;
  713.   }
  714.   datasec = totsec - (FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt +
  715.                       FS__FAT_aBPBUnit[Idx][Unit].NumFATs * fatsize + dsize);
  716.   coc     = datasec / FS__FAT_aBPBUnit[Idx][Unit].SecPerClus;
  717.   if (coc < 4085) {
  718.     return 1;  /* FAT12 */
  719.   }
  720.   else if (coc < 65525) {
  721.     return 0;  /* FAT16 */
  722.   }
  723.   return 2;  /* FAT32 */
  724. }
  725. /*********************************************************************
  726. *
  727. *             FS__fat_FAT_find_eof
  728. *
  729.   Description:
  730.   FS internal function. Find the next EOF mark in the FAT.
  731.   Parameters:
  732.   Idx         - Index of device in the device information table 
  733.                 referred by FS__pDevInfo.
  734.   Unit        - Unit number.
  735.   StrtClst    - Starting cluster in FAT.
  736.   pClstCnt    - If not zero, this is a pointer to an FS_u32, which
  737.                 is used to return the number of clusters found
  738.                 between StrtClst and the next EOF mark.
  739.  
  740.   Return value:
  741.   >=0         - Cluster, which contains the EOF mark.
  742.   <0          - An error has occured.
  743. */
  744. FS_i32 FS__fat_FAT_find_eof(int Idx, FS_u32 Unit, FS_i32 StrtClst, FS_u32 *pClstCnt) {
  745.   FS_u32 clstcount;
  746.   FS_u32 fatsize;
  747.   FS_u32 maxclst;
  748.   FS_i32 fatindex;
  749.   FS_i32 fatsec;
  750.   FS_i32 fatoffs;
  751.   FS_i32 lastsec;
  752.   FS_i32 curclst;
  753.   FS_i32 bytespersec;
  754.   FS_i32 eofclst;
  755.   int fattype;
  756.   int err;
  757.   char *buffer;
  758.   unsigned char a;
  759.   unsigned char b;
  760. #if (FS_FAT_NOFAT32==0)
  761.   unsigned char c;
  762.   unsigned char d;
  763. #endif /* FS_FAT_NOFAT32==0 */
  764.   
  765.   fattype = FS__fat_which_type(Idx, Unit);
  766.   if (fattype == 1) {
  767.     maxclst = 4085UL;       /* FAT12 */
  768.   }
  769.   else if (fattype == 2) {
  770. #if (FS_FAT_NOFAT32 == 0)
  771.     maxclst = 0x0ffffff0UL; /* FAT32 */
  772. #else
  773.     return -1;
  774. #endif /* (FS_FAT_NOFAT32==0) */    
  775.   }
  776.   else {
  777.     maxclst = 65525UL;      /* FAT16 */
  778.   }
  779.   buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
  780.   if (!buffer) {
  781.     return -1;
  782.   }
  783.   fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz16;
  784.   if (fatsize == 0) {
  785.     fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz32;
  786.   }
  787.   bytespersec   = (FS_i32)FS__FAT_aBPBUnit[Idx][Unit].BytesPerSec;
  788.   curclst       = StrtClst;
  789.   lastsec       = -1;
  790.   clstcount     = 0;
  791.   while (clstcount < maxclst) {
  792.     eofclst = curclst;
  793.     clstcount++;
  794.     if (fattype == 1) {
  795.       fatindex = curclst + (curclst / 2);   /* FAT12 */
  796.     }
  797. #if (FS_FAT_NOFAT32==0)    
  798.     else if (fattype == 2) {
  799.       fatindex = curclst * 4;               /* FAT32 */
  800.     }
  801. #endif /* FS_FAT_NOFAT32==0 */    
  802.     else {
  803.       fatindex = curclst * 2;               /* FAT16 */
  804.     }
  805.     fatsec  = FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt + (fatindex / bytespersec);
  806.     fatoffs = fatindex % bytespersec;
  807.     if (fatsec != lastsec) {
  808.       err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
  809.       if (err < 0) {
  810.         err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec, (void*)buffer);
  811.         if (err < 0) {
  812.           FS__fat_free(buffer);
  813.           return -1;
  814.         }
  815.         /* Try to repair original FAT sector with contents of copy */
  816.         FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
  817.       }
  818.       lastsec = fatsec;
  819.     }
  820.     if (fattype == 1) {
  821.       if (fatoffs == (bytespersec - 1)) {
  822.         a   = buffer[fatoffs];
  823.         err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec + 1, (void*)buffer);
  824.         if (err < 0) {
  825.           err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec + 1, (void*)buffer);
  826.           if (err < 0) {
  827.             FS__fat_free(buffer);
  828.             return -1;
  829.           }
  830.           /* Try to repair original FAT sector with contents of copy */
  831.           FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec + 1, (void*)buffer);
  832.         }
  833.         lastsec = fatsec + 1;
  834.         b       = buffer[0];
  835.       }
  836.       else {
  837.         a = buffer[fatoffs];
  838.         b = buffer[fatoffs + 1];
  839.       }
  840.       if (curclst & 1) {
  841.         curclst = ((a & 0xf0) >> 4 ) + 16 * b;
  842.       }
  843.       else {
  844.         curclst = a + 256 * (b & 0x0f);
  845.       }
  846.       curclst &= 0x0fffL;
  847.       if (curclst >= 0x0ff8L) {
  848.         /* EOF found */
  849.         FS__fat_free(buffer);
  850.         if (pClstCnt) {
  851.           *pClstCnt = clstcount;
  852.         }
  853.         return eofclst;
  854.       }
  855.     }
  856. #if (FS_FAT_NOFAT32==0)
  857.     else if (fattype == 2) {
  858.       a         = buffer[fatoffs];
  859.       b         = buffer[fatoffs + 1];
  860.       c         = buffer[fatoffs + 2];
  861.       d         = buffer[fatoffs + 3];
  862.       curclst   = a + 0x100L * b + 0x10000L * c + 0x1000000L * d;
  863.       curclst  &= 0x0fffffffL;
  864.       if (curclst >= (FS_i32)0x0ffffff8L) {
  865.         /* EOF found */
  866.         FS__fat_free(buffer);
  867.         if (pClstCnt) {
  868.           *pClstCnt = clstcount;
  869.         }
  870.         return eofclst;
  871.       }
  872.     }
  873. #endif /* FS_FAT_NOFAT32==0 */
  874.     else {
  875.       a         = buffer[fatoffs];
  876.       b         = buffer[fatoffs + 1];
  877.       curclst   = a + 256 * b;
  878.       curclst  &= 0xffffL;
  879.       if (curclst >= (FS_i32)0xfff8L) {
  880.         /* EOF found */
  881.         FS__fat_free(buffer);
  882.         if (pClstCnt) {
  883.           *pClstCnt = clstcount;
  884.         }
  885.         return eofclst;
  886.       }
  887.     }
  888.   } /* while (clstcount<maxclst) */
  889.   FS__fat_free(buffer);
  890.   return -1;
  891. }
  892. /*********************************************************************
  893. *
  894. *             FS__fat_FAT_alloc
  895. *
  896.   Description:
  897.   FS internal function. Allocate a new cluster in the FAT and link it
  898.   to LastClust. Assign an EOF mark to the new allocated cluster.
  899.   The function has grown a lot, since it supports all FAT types (FAT12,
  900.   FAT16 & FAT32). There is also room for performance improvement, when
  901.   makeing the new FAT entry and the old entry is within the same FAT
  902.   sector.
  903.   Parameters:
  904.   Idx         - Index of device in the device information table 
  905.                 referred by FS__pDevInfo.
  906.   Unit        - Unit number.
  907.   LastClust   - Number of cluster, to which the new allocated cluster
  908.                 is linked to. If this is negative, the new cluster is
  909.                 not linked to anything and only the EOF mark is set.
  910.  
  911.   Return value:
  912.   >=0         - Number of new allocated cluster, which contains the 
  913.                 EOF mark.
  914.   <0          - An error has occured.
  915. */
  916. FS_i32 FS__fat_FAT_alloc(int Idx, FS_u32 Unit, FS_i32 LastClust) {
  917.   FS_u32 fatsize;
  918.   FS_i32 fatoffs = 0;
  919.   FS_i32 bytespersec;
  920.   FS_i32 curclst;
  921.   FS_i32 fatsec;
  922.   FS_i32 lastsec;
  923.   unsigned char *buffer;
  924.   int fattype;
  925.   int err;
  926.   int err2;
  927.   int lexp;
  928.   
  929.   buffer = (unsigned char*)FS__fat_malloc(FS_FAT_SEC_SIZE);
  930.   if (!buffer) {
  931.     return -1;
  932.   }
  933.   fattype = FS__fat_which_type(Idx, Unit);
  934. #if (FS_FAT_NOFAT32!=0)
  935.   if (fattype == 2) {
  936.     FS__fat_free(buffer);
  937.     return -1;
  938.   }
  939. #endif /* FS_FAT_NOFAT32!=0 */
  940.   fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz16;
  941.   if (fatsize == 0) {
  942.     fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz32;
  943.   }
  944.   bytespersec   = (FS_i32)FS__FAT_aBPBUnit[Idx][Unit].BytesPerSec;
  945.   /* Find a free cluster in the FAT */
  946.   curclst       = _FS__fat_FindFreeCluster(Idx, Unit, &fatsec, &lastsec, &fatoffs, LastClust, buffer, fattype, fatsize, bytespersec);
  947.   if (curclst < 0) {
  948.     FS__fat_free(buffer);   /* No free cluster found. */
  949.     return -1;
  950.   }
  951.   /* Make an EOF entry for the new cluster */
  952.   err = _FS__fat_SetEOFMark(Idx, Unit, fatsec, &lastsec, fatoffs, curclst, buffer, fattype, fatsize, bytespersec);
  953.   if (err < 0) {
  954.     FS__fat_free(buffer);
  955.     return -1;
  956.   }
  957.   /* Link the new cluster to the cluster list */
  958.   if (LastClust < 0) {
  959.     err  = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, lastsec, (void*)buffer);
  960.     err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsize + lastsec, (void*)buffer);
  961.     lexp = (err < 0);
  962.     lexp = lexp || (err2 < 0);
  963.     if (lexp) {
  964.       FS__fat_free(buffer);
  965.       return -1;
  966.     }
  967.   }
  968.   else {
  969.     err = _FS__fat_LinkCluster(Idx, Unit, &lastsec, curclst, LastClust, buffer, fattype, fatsize, bytespersec);
  970.     if (err < 0) {
  971.       FS__fat_free(buffer);
  972.       return -1;
  973.     }
  974.   }
  975.   
  976. #if (FS_FAT_NOFAT32==0)
  977.   /* Update the FSInfo structure */
  978.   if (fattype == 2) {  /* FAT32 */
  979.     /* Modify FSInfo */
  980.     err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, FS__FAT_aBPBUnit[Idx][Unit].FSInfo, (void*)buffer);
  981.     if (err < 0) {
  982.       FS__fat_free(buffer);
  983.       return -1;
  984.     }
  985.     /* Check for FSInfo structure in buffer */
  986.     if (buffer[0] == (char)0x52) {
  987.       if (buffer[1] == (char)0x52) {
  988.         if (buffer[2] == (char)0x61) {
  989.           if (buffer[3] == (char)0x41) {
  990.             if (buffer[484] == (char)0x72) {
  991.               if (buffer[485] == (char)0x72) {
  992.                 if (buffer[486] == (char)0x41) {
  993.                   if (buffer[487] == (char)0x61) {
  994.                     if (buffer[508] == (char)0x00) {
  995.                       if (buffer[509] == (char)0x00) {
  996.                         if (buffer[510] == (char)0x55) {
  997.                           if (buffer[511] == (char)0xaa) {
  998.                             /* Invalidate last known free cluster count */
  999.                             buffer[488] = (char)0xff;
  1000.                             buffer[489] = (char)0xff;
  1001.                             buffer[490] = (char)0xff;
  1002.                             buffer[491] = (char)0xff;
  1003.                             /* Give hint for free cluster search */
  1004.                             buffer[492] = curclst & 0xff;
  1005.                             buffer[493] = (curclst / 0x100L) & 0xff;
  1006.                             buffer[494] = (curclst / 0x10000L) & 0xff;
  1007.                             buffer[495] = (curclst / 0x1000000L) & 0x0f;
  1008.                             err  = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, FS__FAT_aBPBUnit[Idx][Unit].FSInfo, (void*)buffer);
  1009.                             if (err < 0) {
  1010.                               FS__fat_free(buffer);
  1011.                               return -1;
  1012.                             }
  1013.                           }
  1014.                         }
  1015.                       }
  1016.                     }
  1017.                   }
  1018.                 }
  1019.               }
  1020.             }
  1021.           }
  1022.         }
  1023.       }
  1024.     } /* buffer contains FSInfo structure */
  1025.   } /* FS_Info modification for fattype==2 */
  1026. #endif /* FS_FAT_NOFAT32==0 */
  1027.   FS__fat_free(buffer);
  1028.   return curclst;
  1029. }
  1030. /*********************************************************************
  1031. *
  1032. *             FS__fat_diskclust
  1033. *
  1034.   Description:
  1035.   FS internal function. Walk through the FAT starting at StrtClst for
  1036.   ClstNum times. Return the found cluster number of the media. This is
  1037.   very similar to FS__fat_FAT_find_eof.
  1038.   
  1039.   Parameters:
  1040.   Idx         - Index of device in the device information table 
  1041.                 referred by FS__pDevInfo.
  1042.   Unit        - Unit number.
  1043.   StrtClst    - Starting point for FAT walk.
  1044.   ClstNum     - Number of steps.
  1045.  
  1046.   Return value:
  1047.   > 0         - Number of cluster found after ClstNum steps.
  1048.   ==0         - An error has occured.
  1049. */
  1050. FS_i32 FS__fat_diskclust(int Idx, FS_u32 Unit, FS_i32 StrtClst, FS_i32 ClstNum) {
  1051.   FS_u32 fatsize;
  1052.   FS_i32 fatindex;
  1053.   FS_i32 fatsec;
  1054.   FS_i32 fatoffs;
  1055.   FS_i32 lastsec;
  1056.   FS_i32 curclst;
  1057.   FS_i32 todo;
  1058.   FS_i32 bytespersec;
  1059.   int err;
  1060.   int fattype;
  1061.   char *buffer;
  1062.   unsigned char a;
  1063.   unsigned char b;
  1064. #if (FS_FAT_NOFAT32==0)
  1065.   unsigned char c;
  1066.   unsigned char d;
  1067. #endif /* FS_FAT_NOFAT32==0 */
  1068.   fattype = FS__fat_which_type(Idx, Unit);
  1069. #if (FS_FAT_NOFAT32!=0)
  1070.   if (fattype == 2) {
  1071.     return 0;
  1072.   }
  1073. #endif  /* FS_FAT_NOFAT32!=0 */
  1074.   buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
  1075.   if (!buffer) {
  1076.     return 0;
  1077.   }
  1078.   fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz16;
  1079.   if (fatsize == 0) {
  1080.     fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz32;
  1081.   }
  1082.   bytespersec = (FS_i32)FS__FAT_aBPBUnit[Idx][Unit].BytesPerSec;
  1083.   todo        = ClstNum;
  1084.   curclst     = StrtClst;
  1085.   lastsec     = -1;
  1086.   while (todo) {
  1087.     if (fattype == 1) {
  1088.       fatindex = curclst + (curclst / 2);    /* FAT12 */
  1089.     }
  1090. #if (FS_FAT_NOFAT32==0)
  1091.     else if (fattype == 2) {
  1092.       fatindex = curclst * 4;               /* FAT32 */
  1093.     }
  1094. #endif /* FS_FAT_NOFAT32==0 */
  1095.     else {
  1096.       fatindex = curclst * 2;               /* FAT16 */
  1097.     }
  1098.     fatsec  = FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt + (fatindex / bytespersec);
  1099.     fatoffs = fatindex % bytespersec;
  1100.     if (fatsec != lastsec) {
  1101.       err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
  1102.       if (err < 0) {
  1103.         err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec, (void*)buffer);
  1104.         if (err < 0) {
  1105.           FS__fat_free(buffer);
  1106.           return 0;
  1107.         }
  1108.         /* Try to repair original FAT sector with contents of copy */
  1109.         FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
  1110.       }
  1111.       lastsec = fatsec;
  1112.     }
  1113.     if (fattype == 1) {
  1114.       if (fatoffs == (bytespersec - 1)) {
  1115.         a = buffer[fatoffs];
  1116.         err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec + 1, (void*)buffer);
  1117.         if (err < 0) {
  1118.           err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec + 1, (void*)buffer);
  1119.           if (err < 0) {
  1120.             FS__fat_free(buffer);
  1121.             return 0;
  1122.           }
  1123.           /* Try to repair original FAT sector with contents of copy */
  1124.           FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec + 1, (void*)buffer);
  1125.         }
  1126.         lastsec = fatsec + 1;
  1127.         b = buffer[0];
  1128.       }
  1129.       else {
  1130.         a = buffer[fatoffs];
  1131.         b = buffer[fatoffs + 1];
  1132.       }
  1133.       if (curclst & 1) {
  1134.         curclst = ((a & 0xf0) >> 4) + 16 * b;
  1135.       }
  1136.       else {
  1137.         curclst = a + 256 * (b & 0x0f);
  1138.       }
  1139.       curclst &= 0x0fffL;
  1140.       if (curclst >= 0x0ff8L) {
  1141.         FS__fat_free(buffer);
  1142.         return 0;
  1143.       }
  1144.     }
  1145. #if (FS_FAT_NOFAT32==0)
  1146.     else if (fattype == 2) {
  1147.       a = buffer[fatoffs];
  1148.       b = buffer[fatoffs + 1];
  1149.       c = buffer[fatoffs + 2];
  1150.       d = buffer[fatoffs + 3];
  1151.       curclst = a + 0x100L * b + 0x10000L * c + 0x1000000L * d;
  1152.       curclst &= 0x0fffffffL;
  1153.       if (curclst >= (FS_i32)0x0ffffff8L) {
  1154.         FS__fat_free(buffer);
  1155.         return 0;
  1156.       }
  1157.     }
  1158. #endif /* FS_FAT_NOFAT32==0 */
  1159.     else {
  1160.       a = buffer[fatoffs];
  1161.       b = buffer[fatoffs + 1];
  1162.       curclst  = a + 256 * b;
  1163.       curclst &= 0xffffL;
  1164.       if (curclst >= (FS_i32)0xfff8L) {
  1165.         FS__fat_free(buffer);
  1166.         return 0;
  1167.       }
  1168.     }
  1169.     todo--;
  1170.   }
  1171.   FS__fat_free(buffer);
  1172.   return curclst;
  1173. }
  1174. /*********************************************************************
  1175. *
  1176. *             Global Variables
  1177. *
  1178. **********************************************************************
  1179. */
  1180. const FS__fsl_type FS__fat_functable = {
  1181. #if (FS_FAT_NOFAT32==0)
  1182.   "FAT12/FAT16/FAT32",
  1183. #else
  1184.   "FAT12/FAT16",
  1185. #endif /* FS_FAT_NOFAT32==0 */
  1186.   FS__fat_fopen,        /* open  */
  1187.   FS__fat_fclose,       /* close */
  1188.   FS__fat_fread,        /* read  */
  1189.   FS__fat_fwrite,       /* write */
  1190.   0,                    /* tell  */
  1191.   0,                    /* seek  */
  1192.   FS__fat_ioctl,        /* ioctl */
  1193. #if FS_POSIX_DIR_SUPPORT
  1194.   FS__fat_opendir,      /* opendir   */
  1195.   FS__fat_closedir,     /* closedir  */
  1196.   FS__fat_readdir,      /* readdir   */
  1197.   0,                    /* rewinddir */
  1198.   FS__fat_MkRmDir,      /* mkdir     */
  1199.   FS__fat_MkRmDir,      /* rmdir     */
  1200. #endif  /* FS_POSIX_DIR_SUPPORT */
  1201. };