?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{FILE START}

library

?curdirlinks? - Rev 6

?prevdifflink? - Blame - ?getfile?

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>Procyon AVRlib: fat.c Source File</title>
<link href="dox.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.4.2 -->
<div class="qindex"><a class="qindex" href="main.html">Main&nbsp;Page</a> | <a class="qindex" href="modules.html">Modules</a> | <a class="qindex" href="annotated.html">Data&nbsp;Structures</a> | <a class="qindex" href="dirs.html">Directories</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Data&nbsp;Fields</a> | <a class="qindex" href="globals.html">Globals</a> | <a class="qindex" href="pages.html">Related&nbsp;Pages</a></div>
<h1>fat.c</h1><a href="fat_8c.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment">00001 <span class="comment">/*! \file fat.c \brief FAT16/32 file system driver. */</span>
00002 <span class="comment">//*****************************************************************************</span>
00003 <span class="comment">//</span>
00004 <span class="comment">// File Name    : 'fat.c'</span>
00005 <span class="comment">// Title        : FAT16/32 file system driver</span>
00006 <span class="comment">// Author       : Pascal Stang</span>
00007 <span class="comment">// Date         : 11/07/2000</span>
00008 <span class="comment">// Revised      : 12/12/2000</span>
00009 <span class="comment">// Version      : 0.3</span>
00010 <span class="comment">// Target MCU   : ATmega103 (should work for Atmel AVR Series)</span>
00011 <span class="comment">// Editor Tabs  : 4</span>
00012 <span class="comment">//</span>
00013 <span class="comment">// This code is based in part on work done by Jesper Hansen for his</span>
00014 <span class="comment">//      YAMPP MP3 player project.</span>
00015 <span class="comment">//</span>
00016 <span class="comment">// NOTE: This code is currently below version 1.0, and therefore is considered</span>
00017 <span class="comment">// to be lacking in some functionality or documentation, or may not be fully</span>
00018 <span class="comment">// tested.  Nonetheless, you can expect most functions to work.</span>
00019 <span class="comment">//</span>
00020 <span class="comment">// This code is distributed under the GNU Public License</span>
00021 <span class="comment">//      which can be found at http://www.gnu.org/licenses/gpl.txt</span>
00022 <span class="comment">//</span>
00023 <span class="comment">//*****************************************************************************</span>
00024 
00025 
00026 <span class="preprocessor">#include &lt;avr/io.h&gt;</span>
00027 <span class="preprocessor">#include &lt;avr/pgmspace.h&gt;</span>
00028 <span class="preprocessor">#include &lt;string.h&gt;</span>
00029 
00030 <span class="preprocessor">#include "<a class="code" href="ata_8h.html">ata.h</a>"</span>
00031 <span class="preprocessor">#include "<a class="code" href="rprintf_8h.html">rprintf.h</a>"</span>
00032 <span class="preprocessor">#include "<a class="code" href="debug_8h.html">debug.h</a>"</span>
00033 
00034 <span class="preprocessor">#include "<a class="code" href="fat_8h.html">fat.h</a>"</span>
00035 <span class="preprocessor">#include "<a class="code" href="fatconf_8h.html">fatconf.h</a>"</span>
00036 
00037 <span class="comment">// globals</span>
00038 <span class="comment">// buffers</span>
00039 <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> *SectorBuffer  =      (<span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> *) FAT_SECTOR_BUFFER_ADDR;
00040 <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> *FileNameBuffer =     (<span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> *) FAT_FILENAME_BUFFER_ADDR;
00041 <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> *PathNameBuffer =     (<span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> *) FAT_PATHNAME_BUFFER_ADDR;
00042 
00043 <span class="comment">// filesystem constants/metrics</span>
00044 <span class="keyword">struct </span>partrecord PartInfo;
00045 <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> Fat32Enabled;
00046 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> FirstDataSector;
00047 <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> BytesPerSector;
00048 <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> SectorsPerCluster;
00049 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> FirstFATSector;
00050 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> RootDirStartCluster;
00051 
00052 <span class="comment">// operating variables</span>
00053 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> CurrentDirStartCluster;   <span class="comment">//&lt; current directory starting cluster</span>
00054 <span class="keyword">struct </span>FileInfoStruct FileInfo;         <span class="comment">//&lt; file information for last file accessed</span>
00055 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> FatInCache = 0;
00056 
00057 
00058 <span class="comment">/*************************************************************************/</span>
00059 <span class="comment">/*************************************************************************/</span>
00060 
00061 
00062 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> fatClustToSect(<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> clust)
00063 {
00064     <span class="keywordflow">return</span> ((clust-2) * SectorsPerCluster) + FirstDataSector;
00065 }
00066 
00067 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> fatClusterSize(<span class="keywordtype">void</span>)
00068 {
00069     <span class="comment">// return the number of sectors in a disk cluster</span>
00070     <span class="keywordflow">return</span> SectorsPerCluster;
00071 }
00072 
00073 <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> fatInit( <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> device)
00074 {
00075     <span class="comment">//struct partrecord *pr;</span>
00076     <span class="keyword">struct </span>bpb710 *bpb;
00077 
00078     <span class="comment">// read partition table</span>
00079     <span class="comment">// TODO.... error checking</span>
00080     ataReadSectors(DRIVE0, 0, 1, SectorBuffer);
00081     <span class="comment">// map first partition record   </span>
00082     <span class="comment">// save partition information to global PartInfo</span>
00083     PartInfo = *((<span class="keyword">struct </span>partrecord *) ((<span class="keyword">struct </span>partsector *) SectorBuffer)-&gt;psPart);
00084 <span class="comment">//  PartInfo = *pr;</span>
00085     
00086     <span class="comment">// Read the Partition BootSector</span>
00087     <span class="comment">// **first sector of partition in PartInfo.prStartLBA</span>
00088     ataReadSectors( DRIVE0, PartInfo.prStartLBA, 1, SectorBuffer );
00089     bpb = (<span class="keyword">struct </span>bpb710 *) ((<span class="keyword">struct </span>bootsector710 *) SectorBuffer)-&gt;bsBPB;
00090 
00091     <span class="comment">// setup global disk constants</span>
00092     FirstDataSector = PartInfo.prStartLBA;
00093     <span class="keywordflow">if</span>(bpb-&gt;bpbFATsecs)
00094     {
00095         <span class="comment">// bpbFATsecs is non-zero and is therefore valid</span>
00096         FirstDataSector += bpb-&gt;bpbResSectors + bpb-&gt;bpbFATs * bpb-&gt;bpbFATsecs;
00097     }
00098     <span class="keywordflow">else</span>
00099     {
00100         <span class="comment">// bpbFATsecs is zero, real value is in bpbBigFATsecs</span>
00101         FirstDataSector += bpb-&gt;bpbResSectors + bpb-&gt;bpbFATs * bpb-&gt;bpbBigFATsecs;
00102     }
00103     SectorsPerCluster   = bpb-&gt;bpbSecPerClust;
00104     BytesPerSector      = bpb-&gt;bpbBytesPerSec;
00105     FirstFATSector      = bpb-&gt;bpbResSectors + PartInfo.prStartLBA;
00106 
00107     <span class="keywordflow">switch</span> (PartInfo.prPartType)
00108     {
00109         <span class="keywordflow">case</span> PART_TYPE_DOSFAT16:
00110         <span class="keywordflow">case</span> PART_TYPE_FAT16:
00111         <span class="keywordflow">case</span> PART_TYPE_FAT16LBA:
00112             <span class="comment">// first directory cluster is 2 by default (clusters range 2-&gt;big)</span>
00113             RootDirStartCluster = CLUST_FIRST;
00114             <span class="comment">// push data sector pointer to end of root directory area</span>
00115             <span class="comment">//FirstDataSector += (bpb-&gt;bpbRootDirEnts)/DIRENTRIES_PER_SECTOR;</span>
00116             Fat32Enabled = FALSE;
00117             <span class="keywordflow">break</span>;
00118         <span class="keywordflow">case</span> PART_TYPE_FAT32LBA:
00119         <span class="keywordflow">case</span> PART_TYPE_FAT32:
00120             <span class="comment">// bpbRootClust field exists in FAT32 bpb710, but not in lesser bpb's</span>
00121             RootDirStartCluster = bpb-&gt;bpbRootClust;
00122             <span class="comment">// push data sector pointer to end of root directory area</span>
00123             <span class="comment">// need this? FirstDataSector += (bpb-&gt;bpbRootDirEnts)/DIRENTRIES_PER_SECTOR;</span>
00124             Fat32Enabled = TRUE;
00125             <span class="keywordflow">break</span>;
00126         <span class="keywordflow">default</span>:
00127             <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"Found: No Partition!\r\n"</span>);
00128             <span class="comment">//return 1;</span>
00129             <span class="keywordflow">break</span>;
00130     }
00131 
00132     <span class="comment">// set current directory to root (\)</span>
00133     CurrentDirStartCluster = RootDirStartCluster;
00134     PathNameBuffer[0] = <span class="charliteral">'\\'</span>;
00135     PathNameBuffer[1] = 0;
00136 
00137 
00138     <span class="comment">// do debug</span>
00139 <span class="preprocessor">#ifdef DEBUG_FAT</span>
00140 <span class="preprocessor"></span>    <span class="keywordflow">switch</span> (PartInfo.prPartType)
00141     {
00142         <span class="keywordflow">case</span> PART_TYPE_DOSFAT16:
00143                 <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"Found: DOSFAT 16\r\n"</span>);
00144                 <span class="keywordflow">break</span>;
00145         <span class="keywordflow">case</span> PART_TYPE_FAT16:
00146                 <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"Found: FAT16\r\n"</span>);
00147                 <span class="keywordflow">break</span>;
00148         <span class="keywordflow">case</span> PART_TYPE_FAT16LBA:
00149                 <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"Found: FAT16 LBA\r\n"</span>);
00150                 <span class="keywordflow">break</span>;
00151         <span class="keywordflow">case</span> PART_TYPE_FAT32LBA:
00152                 <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"Found: FAT32 LBA\r\n"</span>);
00153                 <span class="keywordflow">break</span>;
00154         <span class="keywordflow">case</span> PART_TYPE_FAT32:
00155                 <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"Found: FAT32\r\n"</span>);
00156                 <span class="comment">//return 1; </span>
00157                 <span class="keywordflow">break</span>;
00158         <span class="keywordflow">default</span>:
00159                 <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"Found: No Partition!\r\n"</span>);
00160                 <span class="comment">//return 1;</span>
00161                 <span class="keywordflow">break</span>;
00162     }
00163 
00164     <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"First sector    : "</span>);  <a class="code" href="group__rprintf.html#ga9">rprintfu32</a>(PartInfo.prStartLBA);    <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00165     <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"Size            : "</span>);  <a class="code" href="group__rprintf.html#ga9">rprintfu32</a>(PartInfo.prSize);        <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00166     <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"bytes/sector    : "</span>);  <a class="code" href="group__rprintf.html#ga8">rprintfu16</a>(bpb-&gt;bpbBytesPerSec);    <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00167     <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"sectors/cluster : "</span>);  <a class="code" href="group__rprintf.html#ga7">rprintfu08</a>(bpb-&gt;bpbSecPerClust);    <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00168     <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"reserved sectors: "</span>);  <a class="code" href="group__rprintf.html#ga8">rprintfu16</a>(bpb-&gt;bpbResSectors);     <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00169     <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"FatSectors      : "</span>);  <a class="code" href="group__rprintf.html#ga8">rprintfu16</a>(bpb-&gt;bpbFATsecs);        <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00170     <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"BigFatSectors   : "</span>);  <a class="code" href="group__rprintf.html#ga9">rprintfu32</a>(bpb-&gt;bpbBigFATsecs);     <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00171     <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"Number of Fats  : "</span>);  <a class="code" href="group__rprintf.html#ga7">rprintfu08</a>(bpb-&gt;bpbFATs);           <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00172     <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"First Fat Sector: "</span>);  <a class="code" href="group__rprintf.html#ga9">rprintfu32</a>(FirstFATSector);         <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00173     <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"First Data Sect : "</span>);  <a class="code" href="group__rprintf.html#ga9">rprintfu32</a>(FirstDataSector);        <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00174     <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"RootDirStartClus: "</span>);  <a class="code" href="group__rprintf.html#ga9">rprintfu32</a>(RootDirStartCluster);    <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00175 <span class="preprocessor">#endif</span>
00176 <span class="preprocessor"></span>
00177     <span class="keywordflow">return</span> 0;   
00178 }
00179 <span class="comment"></span>
00180 <span class="comment">//////////////////////////////////////////////////////////////</span>
00181 <span class="comment"></span>
00182 <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> fatGetDirEntry(<span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> entry)
00183 {
00184     <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> sector;
00185     <span class="keyword">struct </span>direntry *de = 0;    <span class="comment">// avoid compiler warning by initializing</span>
00186     <span class="keyword">struct </span>winentry *we;
00187     <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> haveLongNameEntry;
00188     <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> gotEntry;
00189     <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> b;
00190     <span class="keywordtype">int</span> i,index;
00191     <span class="keywordtype">char</span> *fnbPtr;
00192     <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> entrycount = 0;
00193 
00194     <span class="comment">// read dir data</span>
00195     sector = fatClustToSect(CurrentDirStartCluster);
00196 
00197     haveLongNameEntry = 0;
00198     gotEntry = 0;
00199 
00200     index = 16; <span class="comment">// crank it up</span>
00201     
00202     <span class="comment">//while(entrycount &lt; entry) </span>
00203     <span class="keywordflow">while</span>(1)
00204     {
00205         <span class="keywordflow">if</span>(index == 16) <span class="comment">// time for next sector ?</span>
00206         {
00207             ataReadSectors( DRIVE0, sector++, 1, SectorBuffer);
00208             de = (<span class="keyword">struct </span>direntry *) SectorBuffer;
00209             index = 0;
00210         }
00211         
00212         <span class="comment">// check the status of this directory entry slot</span>
00213         <span class="keywordflow">if</span>(de-&gt;deName[0] == 0x00)
00214         {
00215             <span class="comment">// slot is empty and this is the end of directory</span>
00216             gotEntry = 0;
00217             <span class="keywordflow">break</span>;
00218         }
00219         <span class="keywordflow">else</span> <span class="keywordflow">if</span>(de-&gt;deName[0] == 0xE5)
00220         {
00221             <span class="comment">// this is an empty slot</span>
00222             <span class="comment">// do nothing and move to the next one</span>
00223         }
00224         <span class="keywordflow">else</span>
00225         {
00226             <span class="comment">// this is a valid and occupied entry</span>
00227             <span class="comment">// is it a part of a long file/dir name?</span>
00228             <span class="keywordflow">if</span>(de-&gt;deAttributes == ATTR_LONG_FILENAME)
00229             {
00230                 <span class="comment">// we have a long name entry</span>
00231                 <span class="comment">// cast this directory entry as a "windows" (LFN: LongFileName) entry</span>
00232                 we = (<span class="keyword">struct </span>winentry *) de;
00233                 
00234                 b = WIN_ENTRY_CHARS*( (we-&gt;weCnt-1) &amp; 0x0f);        <span class="comment">// index into string</span>
00235                 fnbPtr = &amp;FileNameBuffer[b];
00236                 <span class="keywordflow">for</span> (i=0;i&lt;5;i++)   *fnbPtr++ = we-&gt;wePart1[i*2];   <span class="comment">// copy first part</span>
00237                 <span class="keywordflow">for</span> (i=0;i&lt;6;i++)   *fnbPtr++ = we-&gt;wePart2[i*2];   <span class="comment">// second part</span>
00238                 <span class="keywordflow">for</span> (i=0;i&lt;2;i++)   *fnbPtr++ = we-&gt;wePart3[i*2];   <span class="comment">// and third part</span>
00239                 <span class="keywordflow">if</span> (we-&gt;weCnt &amp; WIN_LAST) *fnbPtr = 0;              <span class="comment">// in case dirnamelength is multiple of 13, add termination</span>
00240                 if ((we-&gt;weCnt &amp; 0x0f) == 1) haveLongNameEntry = 1; <span class="comment">// flag that we have a complete long name entry set</span>
00241             }
00242             <span class="keywordflow">else</span>
00243             {
00244                 <span class="comment">// we have a short name entry</span>
00245                 
00246                 <span class="comment">// check if this is the short name entry corresponding</span>
00247                 <span class="comment">// to the end of a multi-part long name entry</span>
00248                 <span class="keywordflow">if</span>(haveLongNameEntry)
00249                 {
00250                     <span class="comment">// a long entry name has been collected</span>
00251                     <span class="keywordflow">if</span>(entrycount == entry)     
00252                     {
00253                         <span class="comment">// desired entry has been found, break out</span>
00254                         gotEntry = 1;
00255                         <span class="keywordflow">break</span>;
00256                     }
00257                     <span class="comment">// otherwise</span>
00258                     haveLongNameEntry = 0;  <span class="comment">// clear long name flag</span>
00259                     entrycount++;           <span class="comment">// increment entry counter      </span>
00260                 }
00261                 <span class="keywordflow">else</span>
00262                 {
00263                     <span class="comment">// entry is a short name (8.3 format) without a</span>
00264                     <span class="comment">// corresponding multi-part long name entry</span>
00265                     fnbPtr = FileNameBuffer;
00266                     <span class="keywordflow">for</span> (i=0;i&lt;8;i++)   *fnbPtr++ = de-&gt;deName[i];      <span class="comment">// copy name</span>
00267                     *fnbPtr++ = <span class="charliteral">'.'</span>;                                    <span class="comment">// insert '.'</span>
00268                     <span class="keywordflow">for</span> (i=0;i&lt;3;i++)   *fnbPtr++ = de-&gt;deExtension[i]; <span class="comment">// copy extension</span>
00269                     *fnbPtr = 0;                                        <span class="comment">// null-terminate</span>
00270 
00271                     <span class="keywordflow">if</span>(entrycount == entry)     
00272                     {
00273                         <span class="comment">// desired entry has been found, break out</span>
00274                         gotEntry = 1;
00275                         <span class="keywordflow">break</span>;
00276                     }
00277                     <span class="comment">// otherwise</span>
00278                     entrycount++;           <span class="comment">// increment entry counter      </span>
00279                 }
00280             }
00281         }
00282         <span class="comment">// next directory entry</span>
00283         de++;
00284         <span class="comment">// next index</span>
00285         index++;
00286     }
00287     
00288     <span class="comment">// we have a file/dir to return</span>
00289     <span class="comment">// store file/dir starting cluster (start of data)</span>
00290     FileInfo.StartCluster = (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>) ((<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>)de-&gt;deHighClust &lt;&lt; 16) + de-&gt;deStartCluster;
00291     <span class="comment">// store file/dir size</span>
00292     <span class="comment">// (note: size field for subdirectory entries is always zero)</span>
00293     FileInfo.Size = de-&gt;deFileSize;
00294     <span class="comment">// store file/dir attributes</span>
00295     FileInfo.Attr = de-&gt;deAttributes;
00296     <span class="comment">// store file/dir creation time</span>
00297     FileInfo.CreateTime = de-&gt;deCTime[0] | de-&gt;deCTime[1]&lt;&lt;8;
00298     <span class="comment">// store file/dir creation date</span>
00299     FileInfo.CreateTime = de-&gt;deCDate[0] | de-&gt;deCDate[1]&lt;&lt;8;
00300 
00301     <span class="keywordflow">return</span> gotEntry;
00302 }
00303 
00304 <span class="comment">// change directory into </span>
00305 <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> fatChangeDirectory(<span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> entry)
00306 {
00307     <span class="comment">// get the requested directory entry</span>
00308     <span class="keywordflow">if</span>( fatGetDirEntry(entry) )
00309     {
00310         <span class="comment">// make sure the entry is a directory</span>
00311         <span class="keywordflow">if</span>(FileInfo.Attr &amp; ATTR_DIRECTORY)
00312         {
00313             <span class="comment">// change directories into this directory</span>
00314             <span class="comment">// check to see if we are changing back to root directory</span>
00315             <span class="keywordflow">if</span>(FileInfo.StartCluster)
00316             {
00317                 <span class="comment">// standard change directory</span>
00318                 CurrentDirStartCluster = FileInfo.StartCluster;
00319             }
00320             <span class="keywordflow">else</span>
00321             {
00322                 <span class="comment">// if startCluster pointer is zero,</span>
00323                 <span class="comment">// a change to the root directory is intended</span>
00324                 <span class="comment">// change directory to root</span>
00325                 CurrentDirStartCluster = RootDirStartCluster;
00326             }
00327             <span class="comment">// TODO: handle pathname properly for going up a directory</span>
00328             <span class="comment">// set path string</span>
00329             strcat(PathNameBuffer, FileNameBuffer);
00330             strcat(PathNameBuffer, <span class="stringliteral">"\\"</span>);
00331             <span class="comment">// return success</span>
00332             <span class="keywordflow">return</span> TRUE;
00333         }
00334         <span class="keywordflow">else</span>
00335         {
00336             <span class="comment">// not a directory, cannot CD into a file!</span>
00337             <span class="keywordflow">return</span> FALSE;
00338         }
00339     }
00340     <span class="keywordflow">else</span>
00341     {
00342         <span class="comment">// not a valid entry, cannot CD!</span>
00343         <span class="keywordflow">return</span> FALSE;
00344     }
00345 }
00346 
00347 <span class="keywordtype">void</span> fatPrintDirEntry(<span class="keywordtype">void</span>)
00348 {
00349     <span class="comment">// print a formatted dir-style output for most recent file</span>
00350     <span class="comment">// print date</span>
00351     <a class="code" href="group__rprintf.html#ga10">rprintfNum</a>(10, 2, FALSE, <span class="charliteral">'0'</span>, (FileInfo.CreateDate&amp;DD_MONTH_MASK)&gt;&gt;DD_MONTH_SHIFT );    <span class="comment">// month</span>
00352     <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">'/'</span>);
00353     <a class="code" href="group__rprintf.html#ga10">rprintfNum</a>(10, 2, FALSE, <span class="charliteral">'0'</span>, (FileInfo.CreateDate&amp;DD_DAY_MASK)&gt;&gt;DD_DAY_SHIFT );        <span class="comment">// day</span>
00354     <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">'/'</span>);
00355     <a class="code" href="group__rprintf.html#ga10">rprintfNum</a>(10, 4, FALSE, <span class="charliteral">'0'</span>, (FileInfo.CreateDate&amp;DD_YEAR_MASK)&gt;&gt;DD_YEAR_SHIFT );  <span class="comment">// year</span>
00356     <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">' '</span>);
00357 
00358     <span class="comment">// print time</span>
00359     <a class="code" href="group__rprintf.html#ga10">rprintfNum</a>(10, 2, FALSE, <span class="charliteral">'0'</span>, (FileInfo.CreateTime&amp;DT_HOURS_MASK)&gt;&gt;DT_HOURS_SHIFT );    <span class="comment">// month</span>
00360     <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">':'</span>);
00361     <a class="code" href="group__rprintf.html#ga10">rprintfNum</a>(10, 2, FALSE, <span class="charliteral">'0'</span>, (FileInfo.CreateTime&amp;DT_MINUTES_MASK)&gt;&gt;DT_MINUTES_SHIFT );        <span class="comment">// day</span>
00362     <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">':'</span>);
00363     <a class="code" href="group__rprintf.html#ga10">rprintfNum</a>(10, 2, FALSE, <span class="charliteral">'0'</span>, 2*(FileInfo.CreateTime&amp;DT_2SECONDS_MASK)&gt;&gt;DT_2SECONDS_SHIFT );    <span class="comment">// seconds</span>
00364     <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">' '</span>);
00365 
00366     <span class="comment">// print attributes</span>
00367     <span class="keywordflow">if</span>(FileInfo.Attr &amp; ATTR_VOLUME)     <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">'V'</span>); <span class="keywordflow">else</span> <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">'-'</span>);
00368     <span class="keywordflow">if</span>(FileInfo.Attr &amp; ATTR_DIRECTORY)  <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">'D'</span>); <span class="keywordflow">else</span> <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">'-'</span>);
00369     <span class="keywordflow">if</span>(FileInfo.Attr &amp; ATTR_READONLY)   <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">'R'</span>); <span class="keywordflow">else</span> <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">'-'</span>);
00370     <span class="keywordflow">if</span>(FileInfo.Attr &amp; ATTR_HIDDEN)     <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">'H'</span>); <span class="keywordflow">else</span> <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">'-'</span>);
00371     <span class="keywordflow">if</span>(FileInfo.Attr &amp; ATTR_SYSTEM)     <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">'S'</span>); <span class="keywordflow">else</span> <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">'-'</span>);
00372     <span class="keywordflow">if</span>(FileInfo.Attr &amp; ATTR_ARCHIVE)    <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">'A'</span>); <span class="keywordflow">else</span> <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">'-'</span>);
00373     <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">' '</span>);
00374 
00375     <span class="comment">// print filesize</span>
00376     <a class="code" href="group__rprintf.html#ga10">rprintfNum</a>(10, 8, FALSE, <span class="charliteral">' '</span>, FileInfo.Size);   <span class="comment">// filesize</span>
00377     <a class="code" href="group__rprintf.html#ga1">rprintfChar</a>(<span class="charliteral">' '</span>);
00378 
00379     <span class="comment">// print filename</span>
00380     <a class="code" href="group__rprintf.html#ga2">rprintfStr</a>(FileNameBuffer);
00381 }
00382 
00383 <span class="keywordtype">void</span> fatDumpDirSlot(<span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> slot)
00384 {
00385     <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> sector;
00386     <span class="comment">// load correct sector</span>
00387     sector = fatClustToSect(CurrentDirStartCluster);
00388     sector += slot/DIRENTRIES_PER_SECTOR;
00389     <span class="comment">// print the entry as a hex table</span>
00390     <a class="code" href="debug_8c.html#a0">debugPrintHexTable</a>(32, SectorBuffer+(slot&lt;&lt;5) );
00391 }
00392 
00393 <span class="keyword">struct </span>FileInfoStruct* fatGetFileInfo(<span class="keywordtype">void</span>)
00394 {
00395     <span class="keywordflow">return</span> &amp;FileInfo;
00396 }
00397 
00398 <span class="comment">// return the size of the last directory entry</span>
00399 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> fatGetFilesize(<span class="keywordtype">void</span>)
00400 {
00401     <span class="keywordflow">return</span> FileInfo.Size;
00402 }
00403 
00404 <span class="comment">// return the long name of the last directory entry</span>
00405 <span class="keywordtype">char</span>* fatGetFilename(<span class="keywordtype">void</span>)
00406 {   
00407     <span class="keywordflow">return</span> FileNameBuffer;
00408 }
00409 
00410 <span class="comment">// return the directory of the last directory entry</span>
00411 <span class="keywordtype">char</span>* fatGetDirname(<span class="keywordtype">void</span>)
00412 {   
00413     <span class="keywordflow">return</span> PathNameBuffer;
00414 }
00415 
00416 <span class="comment">// load a clusterfull of data</span>
00417 <span class="keywordtype">void</span> fatLoadCluster(<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> cluster, <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> *buffer)
00418 {
00419     <span class="keyword">register</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> i;
00420     <span class="comment">// read cluster</span>
00421     <span class="comment">//while ( ataReadSectors( DRIVE0, clust2sect(cluster), SectorsPerCluster, buffer) != 0);</span>
00422     <span class="keywordflow">for</span>(i=0; i&lt;SectorsPerCluster; i++)
00423     {
00424         ataReadSectors( DRIVE0, fatClustToSect(cluster)+i, 1, buffer+(i&lt;&lt;9) );
00425         <span class="comment">// temporary fix for wierd misaligned cluster problem</span>
00426         <span class="comment">// (only when using FAT16?)</span>
00427 <span class="comment">//      ataReadSectors( DRIVE0, fatClustToSect(cluster+8)+i, 1, buffer+(i&lt;&lt;9) );</span>
00428     }
00429 }
00430 
00431 
00432 <span class="comment">// find next cluster in the FAT chain</span>
00433 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> fatNextCluster(<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> cluster)
00434 {
00435     <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> nextCluster;
00436     <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> fatMask;
00437     <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> fatOffset;
00438     <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> sector;
00439     <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> offset;
00440     
00441     <span class="comment">// get fat offset in bytes</span>
00442     <span class="keywordflow">if</span>(Fat32Enabled)
00443     {
00444         <span class="comment">// four FAT bytes (32 bits) for every cluster</span>
00445         fatOffset = cluster &lt;&lt; 2;
00446         <span class="comment">// set the FAT bit mask</span>
00447         fatMask = FAT32_MASK;
00448     }
00449     <span class="keywordflow">else</span>
00450     {
00451         <span class="comment">// two FAT bytes (16 bits) for every cluster</span>
00452         fatOffset = cluster &lt;&lt; 1;
00453         <span class="comment">// set the FAT bit mask</span>
00454         fatMask = FAT16_MASK;
00455     }
00456     
00457     <span class="comment">// calculate the FAT sector that we're interested in</span>
00458     sector = FirstFATSector + (fatOffset / BytesPerSector);
00459     <span class="comment">// calculate offset of the our entry within that FAT sector</span>
00460     offset = fatOffset % BytesPerSector;
00461 
00462     <span class="comment">// if we don't already have this FAT chunk loaded, go get it</span>
00463     <span class="keywordflow">if</span> (sector != FatInCache)
00464     {
00465         <span class="comment">// read sector of FAT table</span>
00466         <span class="keywordflow">while</span> (ataReadSectors( DRIVE0, sector, 1, (<span class="keywordtype">unsigned</span> <span class="keywordtype">char</span>*)FAT_CACHE_ADDR) != 0);
00467         FatInCache = sector;
00468     }
00469 
00470     <span class="comment">// read the nextCluster value</span>
00471     nextCluster = (*((<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>*) &amp;((<span class="keywordtype">char</span>*)FAT_CACHE_ADDR)[offset])) &amp; fatMask;
00472 
00473     <span class="comment">// check to see if we're at the end of the chain</span>
00474     <span class="keywordflow">if</span> (nextCluster == (CLUST_EOFE &amp; fatMask))
00475         nextCluster = 0;
00476 
00477 <span class="preprocessor">#ifdef DEBUG_FAT</span>
00478 <span class="preprocessor"></span>    <a class="code" href="group__rprintf.html#ga15">rprintfProgStrM</a>(<span class="stringliteral">"&gt;"</span>);
00479     <a class="code" href="group__rprintf.html#ga9">rprintfu32</a>(nextCluster);
00480     <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00481 <span class="preprocessor">#endif</span>
00482 <span class="preprocessor"></span>    
00483     <span class="keywordflow">return</span> nextCluster;
00484 }
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Sun Oct 29 03:41:06 2006 for Procyon AVRlib by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.4.2 </small></address>
</body>
</html>
{FILE END}
{FOOTER START}

Powered by WebSVN v2.8.3