Nut/OS  4.10.3
API Reference
phat12.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  */
00032 
00061 #include <errno.h>
00062 
00063 #include <fs/phatfs.h>
00064 #include <fs/phatvol.h>
00065 #include <fs/phatio.h>
00066 
00071 
00083 static void PhatTableLoc(PHATVOL * vol, uint32_t clust, int tabnum, uint32_t * sect, uint32_t * pos)
00084 {
00085     uint32_t tabpos = clust + (clust / 2);
00086 
00087     *sect = vol->vol_tab_sect[tabnum] + tabpos / vol->vol_sectsz;
00088     *pos = tabpos % vol->vol_sectsz;
00089 }
00090 
00100 int Phat12GetClusterLink(NUTDEVICE * dev, uint32_t clust, uint32_t * link)
00101 {
00102     uint32_t sect;
00103     uint32_t pos;
00104     int sbn;
00105     PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00106 
00107     /* Do not seek beyond the end of the chain. */
00108     if (clust >= (PHATEOC & PHAT12CMASK)) {
00109         return -1;
00110     }
00111 
00112     /* Load the sector that contains the table entry. */
00113     PhatTableLoc(vol, clust, 0, &sect, &pos);
00114     if ((sbn = PhatSectorLoad(dev, sect)) < 0) {
00115         return -1;
00116     }
00117 
00118     /* Read the link value. Be aware, that entries may cross sector boundaries. */
00119     *link = vol->vol_buf[sbn].sect_data[pos++];
00120     if (pos >= vol->vol_sectsz) {
00121         if ((sbn = PhatSectorLoad(dev, sect + 1)) < 0) {
00122             return -1;
00123         }
00124         pos = 0;
00125     }
00126     *link += (uint32_t)(vol->vol_buf[sbn].sect_data[pos]) << 8;
00127 
00128     /* Adjust the 12 bit position within the 16 bit result. */
00129     if (clust & 1) {
00130         *link >>= 4;
00131     }
00132     *link &= PHAT12CMASK;
00133 
00134     return 0;
00135 }
00136 
00146 int Phat12SetClusterLink(NUTDEVICE * dev, uint32_t clust, uint32_t link)
00147 {
00148     int tabnum;
00149     uint32_t sect;
00150     uint32_t pos;
00151     uint32_t tval;
00152     int sbn;
00153     PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00154 
00155     for (tabnum = 0; tabnum < 2 && vol->vol_tab_sect[tabnum]; tabnum++) {
00156 
00157         /* Load the sector containing the table entry to set. */
00158         PhatTableLoc(vol, clust, tabnum, &sect, &pos);
00159         if ((sbn = PhatSectorLoad(dev, sect)) < 0) {
00160             return -1;
00161         }
00162 
00163         /* The new value is 12 bit only. Thus we must load the
00164          * old value and keep the upper or lower 4 bit part. */
00165         tval = vol->vol_buf[sbn].sect_data[pos];
00166         if (pos + 1 < vol->vol_sectsz) {
00167             tval += (uint32_t)(vol->vol_buf[sbn].sect_data[pos + 1]) << 8;
00168         } else {
00169             if ((sbn = PhatSectorLoad(dev, sect + 1)) < 0) {
00170                 return -1;
00171             }
00172             tval += (uint32_t)(vol->vol_buf[sbn].sect_data[0]) << 8;
00173         }
00174 
00175         link &= PHAT12CMASK;
00176         if (clust & 1) {
00177             tval &= 0x000F;
00178             link <<= 4;
00179         } else {
00180             tval &= 0xF000;
00181         }
00182         tval |= link;
00183 
00184         /* Save the modified entry. Again maintain sector boundaries. */
00185         if (pos + 1 < vol->vol_sectsz) {
00186             vol->vol_buf[sbn].sect_data[pos + 1] = (uint8_t) (tval >> 8);
00187         } else {
00188             vol->vol_buf[sbn].sect_data[0] = (uint8_t) (tval >> 8);
00189             vol->vol_buf[sbn].sect_dirty = 1;
00190             if ((sbn = PhatSectorLoad(dev, sect)) < 0) {
00191                 return -1;
00192             }
00193         }
00194         vol->vol_buf[sbn].sect_data[pos] = (uint8_t) tval;
00195         vol->vol_buf[sbn].sect_dirty = 1;
00196     }
00197 
00198     return 0;
00199 }
00200 
00209 int Phat12ReleaseChain(NUTDEVICE * dev, uint32_t first)
00210 {
00211     uint32_t next;
00212     PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00213 
00214     while (first < (PHATEOC & PHAT12CMASK)) {
00215         if (Phat12GetClusterLink(dev, first, &next)) {
00216             /* Read error. */
00217             return -1;
00218         }
00219         if (next < 2) {
00220             /* Incomplete chain, should not happen. */
00221             break;
00222         }
00223         if (Phat12SetClusterLink(dev, first, 0)) {
00224             /* Write error. */
00225             return -1;
00226         }
00227         vol->vol_numfree++;
00228         first = next;
00229     }
00230     return 0;
00231 }
00232