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 
00058 #include <errno.h>
00059 
00060 #include <fs/phatfs.h>
00061 #include <fs/phatvol.h>
00062 #include <fs/phatio.h>
00063 
00068 
00080 static void PhatTableLoc(PHATVOL * vol, u_long clust, int tabnum, u_long * sect, u_long * pos)
00081 {
00082     u_long tabpos = clust + (clust / 2);
00083 
00084     *sect = vol->vol_tab_sect[tabnum] + tabpos / vol->vol_sectsz;
00085     *pos = tabpos % vol->vol_sectsz;
00086 }
00087 
00097 int Phat12GetClusterLink(NUTDEVICE * dev, u_long clust, u_long * link)
00098 {
00099     u_long sect;
00100     u_long pos;
00101     int sbn;
00102     PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00103 
00104     /* Do not seek beyond the end of the chain. */
00105     if (clust >= (PHATEOC & PHAT12CMASK)) {
00106         return -1;
00107     }
00108 
00109     /* Load the sector that contains the table entry. */
00110     PhatTableLoc(vol, clust, 0, &sect, &pos);
00111     if ((sbn = PhatSectorLoad(dev, sect)) < 0) {
00112         return -1;
00113     }
00114 
00115     /* Read the link value. Be aware, that entries may cross sector boundaries. */
00116     *link = vol->vol_buf[sbn].sect_data[pos++];
00117     if (pos >= vol->vol_sectsz) {
00118         if ((sbn = PhatSectorLoad(dev, sect + 1)) < 0) {
00119             return -1;
00120         }
00121         pos = 0;
00122     }
00123     *link += (u_long)(vol->vol_buf[sbn].sect_data[pos]) << 8;
00124 
00125     /* Adjust the 12 bit position within the 16 bit result. */
00126     if (clust & 1) {
00127         *link >>= 4;
00128     }
00129     *link &= PHAT12CMASK;
00130 
00131     return 0;
00132 }
00133 
00143 int Phat12SetClusterLink(NUTDEVICE * dev, u_long clust, u_long link)
00144 {
00145     int tabnum;
00146     u_long sect;
00147     u_long pos;
00148     u_long tval;
00149     int sbn;
00150     PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00151 
00152     for (tabnum = 0; tabnum < 2 && vol->vol_tab_sect[tabnum]; tabnum++) {
00153 
00154         /* Load the sector containing the table entry to set. */
00155         PhatTableLoc(vol, clust, tabnum, &sect, &pos);
00156         if ((sbn = PhatSectorLoad(dev, sect)) < 0) {
00157             return -1;
00158         }
00159 
00160         /* The new value is 12 bit only. Thus we must load the
00161          * old value and keep the upper or lower 4 bit part. */
00162         tval = vol->vol_buf[sbn].sect_data[pos];
00163         if (pos + 1 < vol->vol_sectsz) {
00164             tval += (u_long)(vol->vol_buf[sbn].sect_data[pos + 1]) << 8;
00165         } else {
00166             if ((sbn = PhatSectorLoad(dev, sect + 1)) < 0) {
00167                 return -1;
00168             }
00169             tval += (u_long)(vol->vol_buf[sbn].sect_data[0]) << 8;
00170         }
00171 
00172         link &= PHAT12CMASK;
00173         if (clust & 1) {
00174             tval &= 0x000F;
00175             link <<= 4;
00176         } else {
00177             tval &= 0xF000;
00178         }
00179         tval |= link;
00180 
00181         /* Save the modified entry. Again maintain sector boundaries. */
00182         if (pos + 1 < vol->vol_sectsz) {
00183             vol->vol_buf[sbn].sect_data[pos + 1] = (u_char) (tval >> 8);
00184         } else {
00185             vol->vol_buf[sbn].sect_data[0] = (u_char) (tval >> 8);
00186             vol->vol_buf[sbn].sect_dirty = 1;
00187             if ((sbn = PhatSectorLoad(dev, sect)) < 0) {
00188                 return -1;
00189             }
00190         }
00191         vol->vol_buf[sbn].sect_data[pos] = (u_char) tval;
00192         vol->vol_buf[sbn].sect_dirty = 1;
00193     }
00194 
00195     return 0;
00196 }
00197 
00206 int Phat12ReleaseChain(NUTDEVICE * dev, u_long first)
00207 {
00208     u_long next;
00209     PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00210 
00211     while (first < (PHATEOC & PHAT12CMASK)) {
00212         if (Phat12GetClusterLink(dev, first, &next)) {
00213             /* Read error. */
00214             return -1;
00215         }
00216         if (next < 2) {
00217             /* Incomplete chain, should not happen. */
00218             break;
00219         }
00220         if (Phat12SetClusterLink(dev, first, 0)) {
00221             /* Write error. */
00222             return -1;
00223         }
00224         vol->vol_numfree++;
00225         first = next;
00226     }
00227     return 0;
00228 }
00229 

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/