fat.c


1
/*#######################################################################################
2
FAT for AVR (MMC/SD) 
3
4
Copyright (C) 2004 Ulrich Radig
5
6
Bei Fragen und Verbesserungen wendet euch per EMail an
7
8
mail@ulrichradig.de
9
10
oder im Forum meiner Web Page : www.ulrichradig.de
11
12
13
Dieses Programm ist freie Software. Sie können es unter den Bedingungen der 
14
GNU General Public License, wie von der Free Software Foundation veröffentlicht, 
15
weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder 
16
(nach Ihrer Option) jeder späteren Version. 
17
18
Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, 
19
daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, 
20
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT 
21
FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License. 
22
23
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem 
24
Programm erhalten haben. 
25
Falls nicht, schreiben Sie an die Free Software Foundation, 
26
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 
27
#######################################################################################*/
28
29
#include "fat.h"
30
31
unsigned char cluster_size;
32
unsigned int fat_offset;
33
unsigned int cluster_offset;
34
unsigned int volume_boot_record_addr;
35
36
//############################################################################
37
//Auslesen Cluster Size der MMC/SD Karte und Speichern der größe ins EEprom
38
//Auslesen Cluster Offset der MMC/SD Karte und Speichern der größe ins EEprom
39
void fat_init (void)
40
//############################################################################
41
{
42
  struct BootSec *bootp; //Zeiger auf Bootsektor Struktur
43
44
  unsigned char Buffer[BlockSize];
45
46
  //volume_boot_record_addr = fat_addr (Buffer);  
47
     mmc_read_sector (MASTER_BOOT_RECORD,Buffer); //Read Master Boot Record 
48
    if (Buffer[510] == 0x55 && Buffer[511] == 0xAA)
49
    {
50
       FAT_DEBUG("\r\nMBR Signatur found!\r\n"); 
51
    }
52
    else
53
    {
54
       FAT_DEBUG("\r\nMBR Signatur not found!\r\n");
55
       while(1);; 
56
    }
57
58
59
    volume_boot_record_addr = Buffer[VBR_ADDR] + (Buffer[VBR_ADDR+1] << 8);
60
    
61
  mmc_read_sector (volume_boot_record_addr,Buffer);
62
    if (Buffer[510] == 0x55 && Buffer[511] == 0xAA)
63
    {
64
       FAT_DEBUG("\r\nVBR Signatur found!\r\n"); 
65
    }
66
    else
67
    {
68
       FAT_DEBUG("\r\nVBR Signatur not found!\r\n"); 
69
       volume_boot_record_addr = MASTER_BOOT_RECORD;//<- added by Hennie
70
       mmc_read_sector (MASTER_BOOT_RECORD,Buffer); //Read Master Boot Record 
71
    }   
72
    
73
    bootp=(struct BootSec *)Buffer;
74
  cluster_size = bootp->BPB_SecPerClus;
75
  fat_offset = bootp->BPB_RsvdSecCnt;
76
77
  cluster_offset = ((bootp->BPB_BytesPerSec * 32)/BlockSize);  
78
  cluster_offset += fat_root_dir_addr(Buffer);
79
}
80
81
//############################################################################
82
//Auslesen der Adresse des First Root Directory von Volume Boot Record
83
unsigned int fat_root_dir_addr (unsigned char *Buffer) 
84
//############################################################################
85
{
86
  struct BootSec *bootp; //Zeiger auf Bootsektor Struktur
87
  unsigned int FirstRootDirSecNum;
88
  //auslesen des Volume Boot Record von der MMC/SD Karte 
89
  mmc_read_sector (volume_boot_record_addr,Buffer);
90
  bootp=(struct BootSec *)Buffer;
91
92
  //berechnet den ersten Sector des Root Directory
93
  FirstRootDirSecNum = ( bootp->BPB_RsvdSecCnt +
94
                         (bootp->BPB_NumFATs * bootp->BPB_FATSz16));
95
96
  FirstRootDirSecNum+= volume_boot_record_addr;
97
  
98
  return(FirstRootDirSecNum);
99
}
100
101
//############################################################################
102
//  Ausgabe des angegebenen Directory Eintrag in Entry_Count
103
//  ist kein Eintrag vorhanden, ist der Eintrag im 
104
//  Rückgabe Cluster 0xFFFF. Es wird immer nur ein Eintrag ausgegeben
105
//  um Speicherplatz zu sparen um es auch für kleine Atmels zu benutzen
106
unsigned int fat_read_dir_ent (unsigned int dir_cluster, //Angabe Dir Cluster
107
          unsigned char Entry_Count,   //Angabe welcher Direintrag
108
          unsigned long *Size,        //Rückgabe der File Größe
109
          unsigned char *Dir_Attrib,   //Rückgabe des Dir Attributs
110
          unsigned char *Buffer)      //Working Buffer
111
//############################################################################
112
{
113
  unsigned char *pointer;
114
  unsigned int TMP_Entry_Count = 0;
115
  unsigned long Block = 0;
116
  struct DirEntry *dir; //Zeiger auf einen Verzeichniseintrag
117
118
  pointer = Buffer;
119
120
  if (dir_cluster == 0)
121
    {
122
    Block = fat_root_dir_addr(Buffer);
123
    }
124
  else
125
    {
126
    //Berechnung des Blocks aus BlockCount und Cluster aus FATTabelle
127
    //Berechnung welcher Cluster zu laden ist
128
    //Auslesen der FAT - Tabelle
129
    fat_load (dir_cluster,&Block,Buffer);       
130
    Block = ((Block-2) * cluster_size) + cluster_offset;
131
    }
132
133
  //auslesen des gesamten Root Directory
134
  for (unsigned int blk = Block;;blk++)
135
  {
136
    mmc_read_sector (blk,Buffer);  //Lesen eines Blocks des Root Directory
137
    for (unsigned int a=0;a<BlockSize; a = a + 32)
138
    {
139
     dir=(struct DirEntry *)&Buffer[a]; //Zeiger auf aktuellen Verzeichniseintrag holen
140
     
141
      if (dir->DIR_Name[0] == 0) //Kein weiterer Eintrag wenn erstes Zeichen des Namens 0 ist
142
      {
143
      return (0xFFFF);
144
      }
145
      
146
      //Prüfen ob es ein 8.3 Eintrag ist
147
      //Das ist der Fall wenn es sich nicht um einen Eintrag für lange Dateinamen
148
      //oder um einen als gelöscht markierten Eintrag handelt.
149
         if ((dir->DIR_Attr != ATTR_LONG_NAME) &&
150
        (dir->DIR_Name[0] != DIR_ENTRY_IS_FREE)) 
151
      {
152
        //Ist es der gewünschte Verzeichniseintrag
153
        if (TMP_Entry_Count == Entry_Count) 
154
        {
155
          //Speichern des Verzeichnis Eintrages in den Rückgabe Buffer
156
          for(unsigned char b=0;b<11;b++)
157
          {
158
          if (dir->DIR_Name[b] != SPACE)
159
            {
160
            if (b == 8)
161
              {
162
              *pointer++= '.';
163
              }
164
            *pointer++=dir->DIR_Name[b];
165
            }
166
          }            
167
          *pointer++='\0';
168
          *Dir_Attrib = dir->DIR_Attr;
169
170
          //Speichern der Filegröße
171
          *Size=dir->DIR_FileSize;
172
          
173
          //Speichern des Clusters des Verzeichniseintrages
174
          dir_cluster = dir->DIR_FstClusLO;
175
176
          //Eintrag gefunden Rücksprung mit Cluster File Start
177
          return(dir_cluster);
178
        }
179
      TMP_Entry_Count++;
180
      }
181
    }
182
  }
183
  return (0xFFFF); //Kein Eintrag mehr gefunden Rücksprung mit 0xFFFF
184
}
185
186
//############################################################################
187
//  Auslesen der Cluster für ein File aus der FAT
188
//  in den Buffer(512Byte). Bei einer 128MB MMC/SD 
189
//  Karte ist die Cluster größe normalerweise 16KB groß
190
//  das bedeutet das File kann max. 4MByte groß sein.
191
//  Bei größeren Files muß der Buffer größer definiert
192
//  werden! (Ready)
193
//  Cluster = Start Clusterangabe aus dem Directory  
194
void fat_load (  unsigned int Cluster,     //Angabe Startcluster
195
        unsigned long *Block,
196
        unsigned char *TMP_Buffer)   //Workingbuffer
197
//############################################################################
198
{
199
  //Zum Überprüfen ob der FAT Block schon geladen wurde
200
  unsigned int FAT_Block_Store = 0;  
201
202
  //Byte Adresse innerhalb des Fat Blocks
203
  unsigned int FAT_Byte_Addresse;  
204
205
  //FAT Block Adresse
206
  unsigned int FAT_Block_Addresse;
207
  
208
  //Berechnung für den ersten FAT Block (FAT Start Addresse)
209
  for (unsigned int a = 0;;a++)
210
  {  
211
    if (a == *Block)
212
      {
213
      *Block = (0x0000FFFF & Cluster);
214
      return;
215
      }
216
    
217
    if (Cluster == 0xFFFF)
218
      {
219
      break; //Ist das Ende des Files erreicht Schleife beenden
220
      }
221
    //Berechnung des Bytes innerhalb des FAT BlockŽs
222
    FAT_Byte_Addresse = (Cluster*2) % BlockSize;
223
      
224
    //Berechnung des Blocks der gelesen werden muß
225
    FAT_Block_Addresse = ((Cluster*2) / BlockSize) + 
226
                volume_boot_record_addr + fat_offset;  
227
    //Lesen des FAT Blocks
228
    //Überprüfung ob dieser Block schon gelesen wurde
229
    if (FAT_Block_Addresse != FAT_Block_Store)
230
      {
231
      FAT_Block_Store = FAT_Block_Addresse;
232
      //Lesen des FAT Blocks
233
      mmc_read_sector (FAT_Block_Addresse,TMP_Buffer);  
234
      }
235
236
    //Lesen der nächsten Clusternummer
237
    Cluster = (TMP_Buffer[FAT_Byte_Addresse + 1] << 8) + 
238
          TMP_Buffer[FAT_Byte_Addresse];    
239
  }
240
  return;
241
}
242
243
//############################################################################
244
//Lesen eines 512Bytes Blocks von einem File
245
void fat_read_file (unsigned int Cluster,//Angabe des Startclusters vom File
246
         unsigned char *Buffer,    //Workingbuffer
247
         unsigned long BlockCount)    //Angabe welcher Bock vom File geladen 
248
                          //werden soll a 512 Bytes
249
//############################################################################
250
{
251
  //Berechnung des Blocks aus BlockCount und Cluster aus FATTabelle
252
  //Berechnung welcher Cluster zu laden ist
253
  
254
  unsigned long Block = (BlockCount/cluster_size);
255
  
256
  //Auslesen der FAT - Tabelle
257
  fat_load (Cluster,&Block,Buffer);       
258
  Block = ((Block-2) * cluster_size) + cluster_offset;
259
  //Berechnung des Blocks innerhalb des Cluster
260
  Block += (BlockCount % cluster_size);
261
  //Read Data Block from Device
262
  mmc_read_sector (Block,Buffer);  
263
  return;
264
}
265
266
//############################################################################
267
//Lesen eines 512Bytes Blocks von einem File
268
void fat_write_file (unsigned int cluster,//Angabe des Startclusters vom File
269
          unsigned char *buffer,    //Workingbuffer
270
          unsigned long blockCount)    //Angabe welcher Bock vom File gespeichert 
271
                    //werden soll a 512 Bytes
272
//############################################################################
273
{
274
  //Berechnung des Blocks aus BlockCount und Cluster aus FATTabelle
275
  //Berechnung welcher Cluster zu speichern ist
276
  unsigned char tmp_buffer[513];  
277
  unsigned long block = (blockCount/cluster_size);
278
  
279
  //Auslesen der FAT - Tabelle
280
  fat_load (cluster,&block,tmp_buffer);       
281
  block = ((block-2) * cluster_size) + cluster_offset;
282
  //Berechnung des Blocks innerhalb des Cluster
283
  block += (blockCount % cluster_size);
284
  //Write Data Block to Device
285
  mmc_write_sector (block,buffer);  
286
  return;
287
}
288
289
//####################################################################################
290
//Sucht ein File im Directory
291
unsigned char fat_search_file (unsigned char *File_Name,    //Name des zu suchenden Files
292
              unsigned int *Cluster,   //Angabe Dir Cluster welches
293
                      //durchsucht werden soll
294
                      //und Rückgabe des clusters
295
                      //vom File welches gefunden
296
                      //wurde
297
              unsigned long *Size,     //Rückgabe der File Größe
298
              unsigned char *Dir_Attrib,//Rückgabe des Dir Attributs
299
              unsigned char *Buffer)   //Working Buffer
300
//####################################################################################
301
{
302
  unsigned int Dir_Cluster_Store = *Cluster;
303
  for (unsigned char a = 0;a < 100;a++)
304
  {
305
    *Cluster = fat_read_dir_ent(Dir_Cluster_Store,a,Size,Dir_Attrib,Buffer);
306
    if (*Cluster == 0xffff)
307
      {
308
      return(0); //File not Found
309
      }
310
    if(strcasecmp((char *)File_Name,(char *)Buffer) == 0)
311
      {
312
      return(1); //File Found
313
      }
314
  }
315
  return(2); //Error
316
}