phat32.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * Copyright (C) 2005 by egnite Software GmbH. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. */
  32. /*!
  33. * \file fs/phat32.c
  34. * \brief PHAT32 specific routines.
  35. *
  36. * \verbatim
  37. *
  38. * $Log$
  39. * Revision 1.6 2008/08/11 06:59:42 haraldkipp
  40. * BSD types replaced by stdint types (feature request #1282721).
  41. *
  42. * Revision 1.5 2006/02/23 15:45:21 haraldkipp
  43. * PHAT file system now supports configurable number of sector buffers.
  44. * This dramatically increased write rates of no-name cards.
  45. * AVR compile errors corrected.
  46. *
  47. * Revision 1.4 2006/01/23 19:52:10 haraldkipp
  48. * Added required typecasts before left shift.
  49. *
  50. * Revision 1.3 2006/01/23 17:33:47 haraldkipp
  51. * Avoid memory alignment errors.
  52. *
  53. * Revision 1.2 2006/01/22 17:43:46 haraldkipp
  54. * Bugfix. Deleting files sometimes corrupted a volume.
  55. *
  56. * Revision 1.1 2006/01/05 16:31:22 haraldkipp
  57. * First check-in.
  58. *
  59. *
  60. * \endverbatim
  61. */
  62. #include <errno.h>
  63. #include <fs/phatfs.h>
  64. #include <fs/phatvol.h>
  65. #include <fs/phatio.h>
  66. /*!
  67. * \addtogroup xgPhat32
  68. */
  69. /*@{*/
  70. /*!
  71. * \brief Counts the number of free clusters in a fat32 volume, fast version.
  72. *
  73. * \param dev Specifies the file system device.
  74. *
  75. * \return The number of free clusters.
  76. */
  77. uint32_t Phat32FreeClusters(NUTDEVICE * dev)
  78. {
  79. PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
  80. uint32_t rc = 0;
  81. uint32_t clust;
  82. uint32_t clustlast;
  83. uint32_t pos = -4;
  84. uint32_t sect;
  85. int sbn;
  86. uint8_t * sdata;
  87. /* Do not seek beyond the end of the chain. */
  88. clustlast = vol->vol_last_clust;
  89. if (clustlast >= (PHATEOC & PHAT32CMASK)) {
  90. clustlast = (PHATEOC & PHAT32CMASK) -1;
  91. }
  92. sect = vol->vol_tab_sect[0];
  93. sbn = PhatSectorLoad(dev, sect);
  94. if (sbn >= 0) {
  95. sdata = vol->vol_buf[sbn].sect_data;
  96. for (clust = 0; clust < clustlast; clust++) {
  97. pos += 4;
  98. /* Load the sector that contains the table entry. */
  99. if (pos >= vol->vol_sectsz) {
  100. PhatSectorBufferRelease(dev, sbn);
  101. pos = 0;
  102. sect++;
  103. sbn = PhatSectorLoad(dev, sect);
  104. if (sbn < 0) {
  105. break;
  106. }
  107. sdata = vol->vol_buf[sbn].sect_data;
  108. }
  109. /* Check if the 32 bit link value is zero */
  110. if ((sdata[pos] | sdata[pos + 1] | sdata[pos + 2] | sdata[pos + 3]) == 0) {
  111. rc++;
  112. }
  113. }
  114. PhatSectorBufferRelease(dev, sbn);
  115. }
  116. return rc;
  117. }
  118. /*!
  119. * \brief Calculate table location of a specified cluster.
  120. *
  121. * \param vol Mounted volume.
  122. * \param clust Cluster number of the entry to locate.
  123. * \param tabnum Number of the table.
  124. * \param sect Pointer to the variable that receives the sector of the
  125. * table entry.
  126. * \param pos Pointer to the variable that receives position within
  127. * the sector.
  128. */
  129. static void PhatTableLoc(PHATVOL * vol, uint32_t clust, int tabnum, uint32_t * sect, uint32_t * pos)
  130. {
  131. uint32_t tabpos = clust * 4;
  132. *sect = vol->vol_tab_sect[tabnum] + tabpos / vol->vol_sectsz;
  133. *pos = tabpos % vol->vol_sectsz;
  134. }
  135. /*!
  136. * \brief Get link value of a specified cluster.
  137. *
  138. * \param dev Specifies the file system device.
  139. * \param clust Get the link of this cluster.
  140. * \param link Pointer to a variable which will receive the link.
  141. *
  142. * \return 0 on success or -1 on failure.
  143. */
  144. int Phat32GetClusterLink(NUTDEVICE * dev, uint32_t clust, uint32_t * link)
  145. {
  146. uint32_t sect, pos;
  147. int sbn;
  148. PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
  149. /* Do not seek beyond the end of the chain. */
  150. if (clust >= (PHATEOC & PHAT32CMASK)) {
  151. return -1;
  152. }
  153. /* Load the sector that contains the table entry. */
  154. PhatTableLoc(vol, clust, 0, &sect, &pos);
  155. if ((sbn = PhatSectorLoad(dev, sect)) < 0) {
  156. return -1;
  157. }
  158. /* Get the 32 bit link value. */
  159. *link = vol->vol_buf[sbn].sect_data[pos];
  160. *link += (uint32_t)(vol->vol_buf[sbn].sect_data[pos + 1]) << 8;
  161. *link += (uint32_t)(vol->vol_buf[sbn].sect_data[pos + 2]) << 16;
  162. *link += (uint32_t)(vol->vol_buf[sbn].sect_data[pos + 3]) << 24;
  163. PhatSectorBufferRelease(dev, sbn);
  164. return 0;
  165. }
  166. /*!
  167. * \brief Set link value of a specified cluster.
  168. *
  169. * \param dev Specifies the file system device.
  170. * \param clust This cluster will be linked.
  171. * \param link Link to this cluster.
  172. *
  173. * \return 0 on success or -1 on failure.
  174. */
  175. int Phat32SetClusterLink(NUTDEVICE * dev, uint32_t clust, uint32_t link)
  176. {
  177. int tabnum;
  178. uint32_t sect;
  179. uint32_t pos;
  180. int sbn;
  181. PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
  182. for (tabnum = 0; tabnum < 2 && vol->vol_tab_sect[tabnum]; tabnum++) {
  183. link &= PHAT32CMASK;
  184. PhatTableLoc(vol, clust, tabnum, &sect, &pos);
  185. if ((sbn = PhatSectorLoad(dev, sect)) < 0) {
  186. return -1;
  187. }
  188. vol->vol_buf[sbn].sect_data[pos] = (uint8_t) link;
  189. vol->vol_buf[sbn].sect_data[pos + 1] = (uint8_t) (link >> 8);
  190. vol->vol_buf[sbn].sect_data[pos + 2] = (uint8_t) (link >> 16);
  191. vol->vol_buf[sbn].sect_data[pos + 3] = (uint8_t) (link >> 24);
  192. vol->vol_buf[sbn].sect_dirty = 1;
  193. PhatSectorBufferRelease(dev, sbn);
  194. }
  195. return 0;
  196. }
  197. /*!
  198. * \brief Release a cluster chain.
  199. *
  200. * \param dev Specifies the file system device.
  201. * \param first First cluster of the chain to release.
  202. *
  203. * \return 0 on success or -1 on failure.
  204. */
  205. int Phat32ReleaseChain(NUTDEVICE * dev, uint32_t first)
  206. {
  207. uint32_t next;
  208. PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
  209. while (first < (PHATEOC & PHAT32CMASK)) {
  210. if (Phat32GetClusterLink(dev, first, &next)) {
  211. /* Read error. */
  212. return -1;
  213. }
  214. if (next < 2) {
  215. /* Incomplete chain, should not happen. */
  216. break;
  217. }
  218. if (Phat32SetClusterLink(dev, first, 0)) {
  219. /* Write error. */
  220. return -1;
  221. }
  222. vol->vol_numfree++;
  223. first = next;
  224. }
  225. return 0;
  226. }
  227. /*@}*/