1 | /*! \file fat.c \brief FAT-Functions */
|
2 | //###########################################################
|
3 | /// \ingroup singlefat
|
4 | /// \defgroup FAT FAT-Functions (fat.c)
|
5 | /// \code #include "fat.h" \endcode
|
6 | /// \code #include "dos.h" \endcode
|
7 | /// \par Uebersicht
|
8 | //###########################################################
|
9 | // For FAT12, FAT16 and FAT32
|
10 | // Only for first Partition
|
11 | // Only for drives with 512 bytes per sector (the most)
|
12 | //
|
13 | // Based on a White Paper from MS
|
14 | // FAT: General Overview of On-Disk Format
|
15 | // Version 1.03, December 6, 2000
|
16 | //
|
17 | // MBR MasterBootRecord
|
18 | // PC intern 4
|
19 | // M.Tischer
|
20 | // Data Becker
|
21 | //
|
22 | // 17.09.2007 Removed most #ifdef USE_FATBUFFER. See dos.h.
|
23 | // Sourcecode looks much better now.
|
24 | //
|
25 | // 11.10.2006 Replaced "% BYTE_PER_SEC" with "& (BYTE_PER_SEC-1)".
|
26 | // Typecast variables from "unsigned long" to "unsigned int" before:
|
27 | // secoffset = (unsigned int)fatoffset & (BYTE_PER_SEC-1);
|
28 | // Use "unsigned int" for indexing arrays. Does not really speed up,
|
29 | // but reduces code size ;)
|
30 | //
|
31 | // 25.09.2006 Initialize all global variables to zero for better compatibility
|
32 | // with other compilers.
|
33 | //
|
34 | // Benutzung auf eigene Gefahr !
|
35 | //
|
36 | // Use at your own risk !
|
37 | //
|
38 | //#########################################################################
|
39 | // Last change: 17.09.2007
|
40 | //#########################################################################
|
41 | // hk@holger-klabunde.de
|
42 | // http://www.holger-klabunde.de/index.html
|
43 | //#########################################################################
|
44 | // Compiler: AVR-GCC 4.1.1
|
45 | //#########################################################################
|
46 | //@{
|
47 | #include <stdlib.h>
|
48 | #include <string.h>
|
49 | #include <ctype.h>
|
50 |
|
51 | #include "dos.h"
|
52 |
|
53 | #if defined (FAT_DEBUG_SHOW_FAT_INFO) || defined (FAT_DEBUG_RW_HITS) || defined (FAT_DEBUG_CLUSTERS)
|
54 | #include "serial.h" //for testing only
|
55 | #include "printf.h" //for testing only
|
56 | #endif
|
57 |
|
58 | U8 iob[BYTE_PER_SEC]; //file i/o buffer
|
59 |
|
60 | U32 FirstDataSector=0;
|
61 | U32 FirstRootSector=0;
|
62 | U32 FATFirstSector=0;
|
63 | U8 FATtype=0;
|
64 |
|
65 | #ifdef USE_FAT32
|
66 | U32 FAT32RootCluster=0;
|
67 | U32 endofclusterchain=0; //value for END_OF_CLUSTERCHAIN
|
68 | U32 maxcluster=0; // last usable cluster+1
|
69 |
|
70 | #ifdef FAT_DEBUG_RW_HITS
|
71 | U32 FATWRHits=0;
|
72 | U32 FATRDHits=0;
|
73 | #endif
|
74 |
|
75 | #else
|
76 | U16 endofclusterchain=0; //value for END_OF_CLUSTERCHAIN
|
77 | U16 maxcluster=0; // last usable cluster+1
|
78 |
|
79 | #ifdef FAT_DEBUG_RW_HITS
|
80 | U16 FATWRHits=0;
|
81 | U16 FATRDHits=0;
|
82 | #endif
|
83 | #endif
|
84 |
|
85 | U8 iob_status=0;
|
86 | U32 FATCurrentSector=0;
|
87 |
|
88 | #ifdef DOS_WRITE
|
89 | U8 FATStatus=0; // only for FAT write buffering
|
90 | #endif
|
91 |
|
92 | #ifdef USE_FATBUFFER
|
93 | U8 fatbuf[BYTE_PER_SEC]; //buffer for FAT sectors
|
94 | #endif
|
95 |
|
96 | U8 secPerCluster=0;
|
97 |
|
98 | #ifdef USE_64k_CLUSTERS
|
99 | U32 BytesPerCluster=0; //bytes per cluster
|
100 | #else
|
101 | U16 BytesPerCluster=0; //bytes per cluster
|
102 | #endif
|
103 |
|
104 | //U32 RootDirSectors=0; // to big !
|
105 | //U16 RootDirSectors=0; // maybe U8 is enough.
|
106 | U8 RootDirSectors=0; // never saw more then 32 sectors
|
107 |
|
108 |
|
109 | //############################################################
|
110 | /*!\brief Decide if we have to write a used fat sector or read a new fat sector
|
111 | * \param newsector Actual sector number
|
112 | * \return Nothing
|
113 | */
|
114 | void UpdateFATBuffer(U32 newsector)
|
115 | //############################################################
|
116 | {
|
117 | #ifdef USE_FATBUFFER
|
118 | #else
|
119 | if(iob_status!=IOB_FAT) // We have to read a FAT sector first if this is true
|
120 | {
|
121 | ReadFATSector(newsector,iob); //read FAT sector
|
122 | #ifdef FAT_DEBUG_RW_HITS
|
123 | FATRDHits++;
|
124 | #endif
|
125 | FATCurrentSector=newsector;
|
126 | }
|
127 | #endif //#ifdef USE_FATBUFFER
|
128 |
|
129 | if(newsector!=FATCurrentSector) // do we need to update the FAT buffer ?
|
130 | {
|
131 | #ifdef DOS_WRITE
|
132 | if(FATStatus>0)
|
133 | {
|
134 | WriteFATSector(FATCurrentSector,FAT_IO_BUFFER); // write the old FAT buffer
|
135 | #ifdef FAT_DEBUG_RW_HITS
|
136 | FATWRHits++;
|
137 | #endif
|
138 | FATStatus=0; // flag FAT buffer is save
|
139 | }
|
140 | #endif
|
141 | ReadFATSector(newsector,FAT_IO_BUFFER); //read FAT sector
|
142 | #ifdef FAT_DEBUG_RW_HITS
|
143 | FATRDHits++;
|
144 | #endif
|
145 |
|
146 | FATCurrentSector=newsector;
|
147 | }
|
148 | }
|
149 |
|
150 | //############################################################
|
151 | /*!\brief Get back next cluster number from fat cluster chain
|
152 | * \param cluster Actual cluster number
|
153 | * \return Next cluster number
|
154 | */
|
155 | #ifdef USE_FAT32
|
156 | U32 GetNextClusterNumber(U32 cluster)
|
157 | #else
|
158 | U16 GetNextClusterNumber(U16 cluster)
|
159 | #endif
|
160 | //############################################################
|
161 | {
|
162 | #ifdef USE_FAT12
|
163 | U16 tmp, secoffset;
|
164 | U8 fatoffset;
|
165 | #endif
|
166 |
|
167 | union Convert *cv;
|
168 |
|
169 | #ifdef FAT_DEBUG_CLUSTERS
|
170 | #ifdef USE_FAT32
|
171 | printf("GNCN %lu\n",cluster);
|
172 | #else
|
173 | printf("GNCN %u\n",cluster);
|
174 | #endif
|
175 | #endif
|
176 |
|
177 | if(cluster<maxcluster) //we need to check this ;-)
|
178 | {
|
179 |
|
180 | #ifdef USE_FAT12
|
181 | if(FATtype==FAT12)
|
182 | {
|
183 | // FAT12 has 1.5 Bytes per FAT entry
|
184 | // FAT12 can only have 4085 clusters. So cluster * 3 is 16 bit
|
185 | tmp = ((U16)cluster * 3) >>1 ; //multiply by 1.5 (rounds down)
|
186 | secoffset = (U16)tmp & (BYTE_PER_SEC-1); //we need this for later
|
187 |
|
188 | // FAT12 4085 Cluster * 1.5Bytes = 6127.5 Bytes => max 12 FAT sectors
|
189 | // FAT sector offset is 8 Bit
|
190 | // fatoffset = (U8)(tmp / BYTE_PER_SEC); //sector offset from FATFirstSector
|
191 | fatoffset = (U8)(tmp >> 9); //sector offset from FATFirstSector
|
192 |
|
193 | UpdateFATBuffer(FATFirstSector + fatoffset); //read FAT sector
|
194 |
|
195 | if(secoffset == (BYTE_PER_SEC-1)) //if this is the case, cluster number is
|
196 | //on a sector boundary. read the next sector too
|
197 | {
|
198 | tmp = FAT_IO_BUFFER[BYTE_PER_SEC-1]; //keep first part of cluster number
|
199 | UpdateFATBuffer(FATFirstSector + fatoffset +1 ); //read next FAT sector
|
200 | tmp += (U16)FAT_IO_BUFFER[0] << 8; //second part of cluster number
|
201 | }
|
202 | else
|
203 | {
|
204 | cv=(union Convert *)&FAT_IO_BUFFER[secoffset];
|
205 | tmp=cv->ui;
|
206 | }
|
207 |
|
208 | if((U8)cluster & 0x01) tmp>>=4; //shift to right position
|
209 | else tmp&=0xFFF; //delete high nibble
|
210 |
|
211 | return (tmp);
|
212 | }//if(FATtype==FAT12)
|
213 | #endif //#ifdef USE_FAT12
|
214 |
|
215 | #ifdef USE_FAT16
|
216 | if(FATtype==FAT16)
|
217 | {
|
218 | //two bytes per FAT entry
|
219 | // UpdateFATBuffer(FATFirstSector + ((U32)cluster * 2) / BYTE_PER_SEC);
|
220 | // UpdateFATBuffer(FATFirstSector + ((unsigned int)cluster) / (BYTE_PER_SEC/2));
|
221 |
|
222 | UpdateFATBuffer(FATFirstSector + (U8)( (U16)cluster >> 8 ));
|
223 |
|
224 | // Buffer index is max 511. So in any case we loose upper bits. typecast cluster to U16
|
225 | // cv=(union Convert *)&fatbuf[((U32)cluster * 2) % BYTE_PER_SEC];
|
226 | cv=(union Convert *)&FAT_IO_BUFFER[((U16)cluster << 1) & (BYTE_PER_SEC-1)];
|
227 | return(cv->ui);
|
228 | }//if(FATtype==FAT16)
|
229 | #endif //#ifdef USE_FAT16
|
230 |
|
231 | #ifdef USE_FAT32
|
232 | if(FATtype==FAT32)
|
233 | {
|
234 | //four bytes per FAT entry
|
235 | // UpdateFATBuffer(FATFirstSector + (cluster * 4) / BYTE_PER_SEC);
|
236 | // UpdateFATBuffer(FATFirstSector + cluster / (BYTE_PER_SEC/4));
|
237 |
|
238 | UpdateFATBuffer(FATFirstSector + ( cluster >> 7 ));
|
239 |
|
240 | // Buffer index is max 511. So in any case we loose upper bits. typecast cluster to U16
|
241 | cv=(union Convert *)&FAT_IO_BUFFER[((U16)cluster << 2) & (BYTE_PER_SEC-1)];
|
242 | return( cv->ul & 0x0FFFFFFF );
|
243 | }//if(FATtype==FAT32)
|
244 | #endif //#ifdef USE_FAT32
|
245 | }
|
246 |
|
247 | return DISK_FULL; //return impossible cluster number
|
248 | }
|
249 |
|
250 | //###########################################################
|
251 | /*!\brief Get back number of first sector of cluster
|
252 | * \param cluster Actual cluster number
|
253 | * \return Sector number
|
254 | */
|
255 | #ifdef USE_FAT32
|
256 | U32 GetFirstSectorOfCluster(U32 cluster)
|
257 | #else
|
258 | U32 GetFirstSectorOfCluster(U16 cluster)
|
259 | #endif
|
260 | //###########################################################
|
261 | {
|
262 | // Komische Sache: Die Schieberei hier bringt bei ATmega32 ca. 200 Byte weniger Code.
|
263 | // Bei ATmega644 wird der Code dadurch ca. 20 Bytes größer !
|
264 |
|
265 | U8 temp;
|
266 | U32 templong;
|
267 |
|
268 | templong = cluster-2;
|
269 |
|
270 | // secPerCluster is always power of two
|
271 | temp = secPerCluster>>1; // don't multiply with 1 ;)
|
272 |
|
273 | while(temp)
|
274 | {
|
275 | templong <<= 1;
|
276 | temp >>= 1;
|
277 | }
|
278 |
|
279 | return (templong + FirstDataSector);
|
280 |
|
281 | // return (((U32)(cluster - 2) * secPerCluster) + FirstDataSector);
|
282 | }
|
283 |
|
284 | #ifdef DOS_WRITE
|
285 | //###########################################################
|
286 | /*!\brief Allocate a new cluster in cluster chain
|
287 | * \param currentcluster Actual cluster number
|
288 | * \return New cluster number or DISK_FULL
|
289 | */
|
290 | #ifdef USE_FAT32
|
291 | U32 AllocCluster(U32 currentcluster)
|
292 | #else
|
293 | U16 AllocCluster(U16 currentcluster)
|
294 | #endif
|
295 | //###########################################################
|
296 | {
|
297 | #ifdef USE_FAT32
|
298 | U32 cluster;
|
299 | #else
|
300 | U16 cluster;
|
301 | #endif
|
302 |
|
303 | // do this if you want to search from beginning of FAT
|
304 | // cluster=FindFreeCluster(0); //get next free cluster number
|
305 | cluster=FindFreeCluster(currentcluster); // get next free cluster number
|
306 | if(cluster!=DISK_FULL && cluster<=maxcluster) // disk full ?
|
307 | {
|
308 | // insert new cluster number into chain
|
309 | // currentcluster=0 means: this is a new cluster chain
|
310 | if(currentcluster>0) WriteClusterNumber(currentcluster,cluster);
|
311 |
|
312 | // mark end of cluster chain
|
313 | #ifdef USE_FAT12
|
314 | if(FATtype==FAT12) WriteClusterNumber(cluster,0xFFF);
|
315 | #endif
|
316 | #ifdef USE_FAT16
|
317 | if(FATtype==FAT16) WriteClusterNumber(cluster,0xFFFF);
|
318 | #endif
|
319 | #ifdef USE_FAT32
|
320 | if(FATtype==FAT32) WriteClusterNumber(cluster,0x0FFFFFFF);
|
321 | #endif
|
322 | }
|
323 |
|
324 | #ifdef USE_FATBUFFER
|
325 | #else
|
326 | // We should flush the temporary fatbuffer now because next action is
|
327 | // filling iob[] with new data !
|
328 | if(FATStatus>0)
|
329 | {
|
330 | WriteFATSector(FATCurrentSector,iob); // write the FAT buffer
|
331 | #ifdef FAT_DEBUG_RW_HITS
|
332 | FATWRHits++;
|
333 | #endif
|
334 | FATStatus=0; // flag FAT buffer is save
|
335 | }
|
336 | #endif
|
337 |
|
338 | return cluster;
|
339 | }
|
340 | #endif //DOS_WRITE
|
341 |
|
342 | #ifdef DOS_WRITE
|
343 | //###########################################################
|
344 | /*!\brief Find a free cluster in FAT
|
345 | * \param currentcluster Actual cluster number
|
346 | * \return Number of a free cluster or DISK_FULL
|
347 | */
|
348 | #ifdef USE_FAT32
|
349 | U32 FindFreeCluster(U32 currentcluster)
|
350 | #else
|
351 | U16 FindFreeCluster(U16 currentcluster)
|
352 | #endif
|
353 | //###########################################################
|
354 | {
|
355 | #ifdef USE_FAT32
|
356 | U32 cluster;
|
357 | #else
|
358 | U16 cluster;
|
359 | #endif
|
360 |
|
361 | cluster=currentcluster+1; // its a good idea to look here first
|
362 | // maybe we do not need to search the whole FAT
|
363 | // and can speed up free cluster search
|
364 | // if you do not want this call FindFreeCluster(0)
|
365 | // search til end of FAT
|
366 | while(cluster<maxcluster)
|
367 | {
|
368 | if(GetNextClusterNumber(cluster)==0) break;
|
369 | cluster++;
|
370 | }
|
371 |
|
372 | // if we have not found a free cluster til end of FAT
|
373 | // lets start a new search at beginning of FAT
|
374 | if(cluster>=maxcluster)
|
375 | {
|
376 | cluster=2; // first possible free cluster
|
377 | while(cluster<=currentcluster) // search til we come to where we have started
|
378 | {
|
379 | if(GetNextClusterNumber(cluster)==0) break;
|
380 | cluster++;
|
381 | }
|
382 |
|
383 | if(cluster>=currentcluster) return DISK_FULL; // no free cluster found
|
384 | }
|
385 |
|
386 | if(cluster>=maxcluster) return DISK_FULL;
|
387 |
|
388 | return cluster;
|
389 | }
|
390 | #endif //DOS_WRITE
|
391 |
|
392 | #ifdef DOS_WRITE
|
393 | //############################################################
|
394 | /*!\brief Insert a new cluster number into cluster chain
|
395 | * \param cluster Actual cluster number
|
396 | * \param number Cluster number to append to cluster chain
|
397 | * \return Nothing til now (0)
|
398 | */
|
399 | #ifdef USE_FAT32
|
400 | U8 WriteClusterNumber(U32 cluster, U32 number)
|
401 | #else
|
402 | U8 WriteClusterNumber(U16 cluster, U16 number)
|
403 | #endif
|
404 | //############################################################
|
405 | {
|
406 | #ifdef USE_FAT12
|
407 | U16 tmp, secoffset;
|
408 | U8 fatoffset;
|
409 | U8 lo,hi;
|
410 | U32 sector;
|
411 | #endif
|
412 |
|
413 | U8 *p;
|
414 |
|
415 | #ifdef FAT_DEBUG_CLUSTERS
|
416 | #ifdef USE_FAT32
|
417 | printf("WCN %lu\n",cluster);
|
418 | #else
|
419 | printf("WCN %u\n",cluster);
|
420 | #endif
|
421 | #endif
|
422 |
|
423 | if(cluster<maxcluster) //we need to check this ;-)
|
424 | {
|
425 |
|
426 | #ifdef USE_FAT12
|
427 | if(FATtype==FAT12)
|
428 | {
|
429 | //FAT12 has 1.5 Bytes per FAT entry
|
430 | // FAT12 can only have 4085 clusters. So cluster * 3 is 16 bit
|
431 | tmp= ((U16)cluster * 3) >>1 ; //multiply by 1.5 (rounds down)
|
432 | secoffset = (U16)tmp & (BYTE_PER_SEC-1); //we need this for later
|
433 | // FAT12 4085 Cluster * 1.5Bytes = 6127.5 Bytes => max 12 FAT sectors
|
434 | // FAT sector offset is 8 Bit
|
435 | // fatoffset = (U8)(tmp / BYTE_PER_SEC); //sector offset from FATFirstSector
|
436 | fatoffset = (U8)(tmp >> 9); //sector offset from FATFirstSector
|
437 | sector=FATFirstSector + fatoffset;
|
438 |
|
439 | tmp=(U16)number;
|
440 | if((U8)cluster & 0x01) tmp<<=4; //shift to right position
|
441 | lo=(U8)tmp;
|
442 | hi=(U8)(tmp>>8);
|
443 |
|
444 | UpdateFATBuffer(sector); //read FAT sector
|
445 |
|
446 | if(secoffset == (BYTE_PER_SEC-1)) //if this is the case, cluster number is
|
447 | //on a sector boundary. read the next sector too
|
448 | {
|
449 |
|
450 | p = &FAT_IO_BUFFER[BYTE_PER_SEC-1]; //keep first part of cluster number
|
451 |
|
452 | if((U8)cluster & 0x01)
|
453 | {
|
454 | *p&=0x0F;
|
455 | *p|=lo;
|
456 | }
|
457 | else *p=lo;
|
458 |
|
459 | FATStatus=1; // we have made an entry, so write before next FAT sector read
|
460 | UpdateFATBuffer(sector+1); //read FAT sector
|
461 |
|
462 | p = &FAT_IO_BUFFER[0]; //second part of cluster number
|
463 |
|
464 | if((U8)cluster & 0x01) *p=hi;
|
465 | else
|
466 | {
|
467 | *p&=0xF0;
|
468 | *p|=hi;
|
469 | }
|
470 |
|
471 | FATStatus=1; // we have made an entry, so write before next FAT sector read
|
472 | }
|
473 | else
|
474 | {
|
475 | p = &FAT_IO_BUFFER[secoffset];
|
476 |
|
477 | if((U8)cluster & 0x01)
|
478 | {
|
479 | *p&=0x0F;
|
480 | *p++|=lo;
|
481 | *p=hi;
|
482 | }
|
483 | else
|
484 | {
|
485 | *p++=lo;
|
486 | *p&=0xF0;
|
487 | *p|=hi;
|
488 | }
|
489 |
|
490 | FATStatus=1; // we have made an entry, so write before next FAT sector read
|
491 | }
|
492 |
|
493 | }//if(FATtype==FAT12)
|
494 | #endif
|
495 |
|
496 | #ifdef USE_FAT16
|
497 | if(FATtype==FAT16)
|
498 | {
|
499 | //two bytes per FAT entry
|
500 | // sector=FATFirstSector + ((U32)cluster * 2) / BYTE_PER_SEC;
|
501 | // sector=FATFirstSector + ((unsigned int)cluster) / (BYTE_PER_SEC/2);
|
502 | UpdateFATBuffer(FATFirstSector + (U8)( (U16)cluster >> 8 ));
|
503 |
|
504 | // Buffer index is max 511. So in any case we loose upper bits. typecast cluster to U16
|
505 | p = &FAT_IO_BUFFER[((U16)cluster << 1) & (BYTE_PER_SEC-1)];
|
506 |
|
507 | *p++ = (U8)(number);
|
508 | *p = (U8)(number >> 8);
|
509 |
|
510 | FATStatus=1; // we have made an entry, so write before next FAT sector read
|
511 | }// if(FATtype==FAT16)
|
512 | #endif //#ifdef USE_FAT16
|
513 |
|
514 | #ifdef USE_FAT32
|
515 | if(FATtype==FAT32)
|
516 | {
|
517 | //four bytes per FAT entry
|
518 | // sector=FATFirstSector + (cluster * 4) / BYTE_PER_SEC;
|
519 | // sector=FATFirstSector + cluster / (BYTE_PER_SEC/4);
|
520 | UpdateFATBuffer(FATFirstSector + ( cluster >> 7 ));
|
521 |
|
522 | // Buffer index is max 511. So in any case we loose upper bits. typecast cluster to U16
|
523 | p = &FAT_IO_BUFFER[((U16)cluster << 2) & (BYTE_PER_SEC-1)];
|
524 |
|
525 | number&=0x0FFFFFFF;
|
526 |
|
527 | *p++ = (U8)( number);
|
528 | *p++ = (U8)(number >> 8);
|
529 | *p++ = (U8)(number >> 16);
|
530 | *p = (U8)(number >> 24);
|
531 |
|
532 | FATStatus=1; // we have made an entry, so write before next FAT sector read
|
533 |
|
534 | }// if(FATtype==FAT32)
|
535 | #endif //#ifdef USE_FAT32
|
536 | } // if(cluster<maxcluster) //we need to check this ;-)
|
537 |
|
538 | return 0;
|
539 | }
|
540 | #endif //DOS_WRITE
|
541 |
|
542 | //###########################################################
|
543 | /*!\brief Get drive informations
|
544 | * \return F_OK if successfull, F_ERROR if not
|
545 | *
|
546 | * This function is most important for the FAT filesystem.
|
547 | * Following values will be read out:
|
548 | * Type of the FAT filesystem.
|
549 | * Number of sectors for the partition (if there is one).
|
550 | * Number of clusters of the drive.
|
551 | * Where is the rootdirectory. And many more.
|
552 | * When using MMC/SD cards, call MMC_IO_Init() BEFORE GetDriveInformation() !
|
553 | */
|
554 | U8 GetDriveInformation(void)
|
555 | //###########################################################
|
556 | {
|
557 | U8 by;
|
558 | U32 DataSec,TotSec;
|
559 | U32 bootSecOffset;
|
560 | U32 FATSz; // FATSize
|
561 | U8 loop;
|
562 |
|
563 | #ifdef USE_FAT32
|
564 | U32 CountofClusters;
|
565 | #else
|
566 | // U16 CountofClusters; // for standard division
|
567 | U32 CountofClusters; // for shifting division
|
568 | #endif
|
569 |
|
570 | U16 RootEntrys;
|
571 |
|
572 | struct MBR *mbr;
|
573 | struct BootSec *boot;
|
574 |
|
575 | by=IdentifyMedia(); //LaufwerksInformationen holen
|
576 | if(by==0)
|
577 | {
|
578 | FATtype=0; //Unknown FAT type
|
579 | bootSecOffset=0; //erstmal
|
580 |
|
581 | by=ReadSector(0,iob); //Lese den MBR. Erster Sektor auf der Platte
|
582 | //enthält max. 4 Partitionstabellen mit jeweils 16Bytes
|
583 | //Die erste fängt bei 0x01BE an, und nur die nehme ich !
|
584 |
|
585 | //Erstmal checken ob wir nicht schon einen Bootsektor gelesen haben.
|
586 | boot=(struct BootSec *)iob;
|
587 |
|
588 | loop=0;
|
589 | do
|
590 | {
|
591 | // Jetzt checke ich doch den FAT-String im Bootsektor um den Typ der FAT
|
592 | // zu bestimmen. Einen besseren Weg sehe ich im Moment nicht.
|
593 | if( boot->eb.rm.BS_FilSysType[0]=='F'
|
594 | // && boot->eb.rm.BS_FilSysType[1]=='A'
|
595 | // && boot->eb.rm.BS_FilSysType[2]=='T'
|
596 | && boot->eb.rm.BS_FilSysType[3]=='1' )
|
597 | {
|
598 | //Wenn ich hier ankomme habe ich entweder FAT12 oder FAT16
|
599 | #ifdef USE_FAT12
|
600 | if(boot->eb.rm.BS_FilSysType[4]=='2') FATtype=FAT12;
|
601 | #endif
|
602 | #ifdef USE_FAT16
|
603 | if(boot->eb.rm.BS_FilSysType[4]=='6') FATtype=FAT16;
|
604 | #endif
|
605 | }
|
606 | else
|
607 | {
|
608 | #ifdef USE_FAT32
|
609 | if( boot->eb.rm32.BS_FilSysType[0]=='F'
|
610 | // && boot->eb.rm32.BS_FilSysType[1]=='A'
|
611 | // && boot->eb.rm32.BS_FilSysType[2]=='T'
|
612 | && boot->eb.rm32.BS_FilSysType[3]=='3'
|
613 | && boot->eb.rm32.BS_FilSysType[4]=='2'
|
614 | )
|
615 | {
|
616 | FATtype=FAT32;
|
617 | }
|
618 | else //war kein Bootsektor, also feststellen wo der liegt
|
619 | #endif
|
620 | {
|
621 | mbr=(struct MBR *)iob; //Pointer auf die Partitionstabelle
|
622 | bootSecOffset=mbr->part1.bootoffset; //Nur den brauche ich
|
623 |
|
624 | by=ReadSector(bootSecOffset,iob); //read bootsector
|
625 | boot=(struct BootSec *)iob;
|
626 | }
|
627 | }
|
628 |
|
629 | loop++;
|
630 | }while(loop<2 && FATtype==0); //Bis zu zwei Versuche den Bootsektor zu lesen
|
631 |
|
632 | if(FATtype==0)
|
633 | {
|
634 | #ifdef FAT_DEBUG_SHOW_FAT_INFO
|
635 | puts("FAT unknown\n");
|
636 | #endif
|
637 | return F_ERROR; // FAT-Typ nicht erkannt
|
638 | }
|
639 |
|
640 | secPerCluster=boot->BPB_SecPerClus; //Sectors per Cluster
|
641 | RootEntrys=boot->BPB_RootEntCnt; //32 Byte Root Directory Entrys
|
642 | RootDirSectors = (unsigned char)( ((RootEntrys * 32) + (BYTE_PER_SEC - 1)) / BYTE_PER_SEC);
|
643 |
|
644 | //Number of sectors for FAT
|
645 | if(boot->BPB_FATSz16 != 0) FATSz = boot->BPB_FATSz16;
|
646 | else FATSz = boot->eb.rm32.BPB_FATSz32; //Für FAT32
|
647 |
|
648 | if(boot->BPB_TotSec16 != 0) TotSec = boot->BPB_TotSec16;
|
649 | else TotSec = boot->BPB_TotSec32;
|
650 |
|
651 | FATFirstSector= bootSecOffset + boot->BPB_RsvdSecCnt;
|
652 | FirstRootSector = FATFirstSector + (boot->BPB_NumFATs * FATSz);
|
653 |
|
654 | //Number of data sectors
|
655 | DataSec = TotSec - (boot->BPB_RsvdSecCnt + (boot->BPB_NumFATs * FATSz) + RootDirSectors);
|
656 |
|
657 | FirstDataSector = FirstRootSector + RootDirSectors;
|
658 |
|
659 | //Number of valid clusters
|
660 | //CountofClusters = DataSec / secPerCluster;
|
661 | U8 temp;
|
662 |
|
663 | // secPerCluster is always power of two
|
664 | temp = secPerCluster>>1; // don't divide by 1 ;)
|
665 | CountofClusters = DataSec;
|
666 |
|
667 | while(temp)
|
668 | {
|
669 | CountofClusters >>= 1;
|
670 | temp >>= 1;
|
671 | }
|
672 |
|
673 | maxcluster = CountofClusters + 2;
|
674 |
|
675 | //Note also that the CountofClusters value is exactly that: the count of data clusters
|
676 | //starting at cluster 2. The maximum valid cluster number for the volume is
|
677 | //CountofClusters + 1, and the "count of clusters including the two reserved clusters"
|
678 | // is CountofClusters + 2.
|
679 |
|
680 | FirstDirCluster=0; // for FAT12 and FAT16
|
681 |
|
682 | #ifdef USE_FAT12
|
683 | if(FATtype==FAT12)
|
684 | {
|
685 | endofclusterchain=EOC12;
|
686 | }
|
687 | #endif
|
688 | #ifdef USE_FAT16
|
689 | if(FATtype==FAT16)
|
690 | {
|
691 | endofclusterchain=EOC16;
|
692 | }
|
693 | #endif
|
694 | #ifdef USE_FAT32
|
695 | if(FATtype==FAT32)
|
696 | {
|
697 | endofclusterchain=EOC32;
|
698 | FAT32RootCluster=boot->eb.rm32.BPB_RootClus;
|
699 | FirstDirCluster=FAT32RootCluster;
|
700 | FirstRootSector=GetFirstSectorOfCluster(FAT32RootCluster);
|
701 | }
|
702 | #endif
|
703 |
|
704 | }
|
705 | else
|
706 | {
|
707 | return F_ERROR; // CF gives no answer
|
708 | }
|
709 |
|
710 | FileFirstCluster=0;
|
711 | FileSize=0;
|
712 | FileFlag=0;
|
713 |
|
714 | BytesPerCluster=BYTE_PER_SEC * secPerCluster; //bytes per cluster
|
715 |
|
716 | FATCurrentSector=FATFirstSector;
|
717 |
|
718 | // for debugging only
|
719 | #ifdef FAT_DEBUG_SHOW_FAT_INFO
|
720 | if(FATtype==FAT12) puts("FAT12\n");
|
721 | if(FATtype==FAT16) puts("FAT16\n");
|
722 | if(FATtype==FAT32) puts("FAT32\n");
|
723 |
|
724 | printf("bootSecOffset %lu\n",bootSecOffset);
|
725 | printf("Reserved Sectors %u\n",boot->BPB_RsvdSecCnt);
|
726 | printf("FAT Sectors %lu\n",FATSz);
|
727 | printf("Num. of FAT's %u\n",(U16)boot->BPB_NumFATs);
|
728 | printf("secPerCluster %u\n",(U16)secPerCluster);
|
729 |
|
730 | #ifdef USE_64k_CLUSTERS
|
731 | printf("BytesPerCluster %lu\n",BytesPerCluster);
|
732 | #else
|
733 | printf("BytesPerCluster %u\n",BytesPerCluster);
|
734 | #endif
|
735 |
|
736 | printf("FATFirstSector %lu\n",FATFirstSector);
|
737 | printf("FirstRootSector %lu\n",FirstRootSector);
|
738 | printf("RootDirSectors %u\n",(U16)RootDirSectors);
|
739 | printf("FirstDataSector %lu\n",FirstDataSector);
|
740 | printf("maxsect %lu\n",maxsect);
|
741 | #ifdef USE_FAT32
|
742 | printf("FirstDirCluster %lu\n",FirstDirCluster);
|
743 | printf("maxcluster %lu\n",maxcluster);
|
744 | #else
|
745 | printf("FirstDirCluster %u\n",FirstDirCluster);
|
746 | printf("maxcluster %u\n",maxcluster);
|
747 | #endif
|
748 |
|
749 | #endif //#ifdef FAT_DEBUG_SHOW_FAT_INFO
|
750 |
|
751 | #ifdef DOS_WRITE
|
752 | FATStatus=0; // nothing to write til here
|
753 | #endif
|
754 |
|
755 | ReadFATSector(FATCurrentSector,FAT_IO_BUFFER); //read first FAT sector
|
756 |
|
757 | return F_OK;
|
758 | }
|
759 |
|
760 | #ifndef USE_FATBUFFER
|
761 | #ifdef DOS_WRITE
|
762 | //#########################################################################
|
763 | U8 WriteFATSector(U32 sector, U8 *buf)
|
764 | //#########################################################################
|
765 | {
|
766 | iob_status=IOB_FAT; // we have to track this
|
767 | return WriteSector(sector,buf); //write sector
|
768 | }
|
769 | #endif
|
770 |
|
771 | //#########################################################################
|
772 | U8 ReadFATSector(U32 sector, U8 *buf)
|
773 | //#########################################################################
|
774 | {
|
775 | iob_status=IOB_FAT; // we have to track this
|
776 | return ReadSector(sector,buf); //read sector
|
777 | }
|
778 |
|
779 | #ifdef DOS_WRITE // Better keep this as a function !
|
780 | //#########################################################################
|
781 | U8 WriteDirSector(U32 sector, U8 *buf)
|
782 | //#########################################################################
|
783 | {
|
784 | iob_status=IOB_DIR; // we have to track this
|
785 | return WriteSector(sector,buf); //write sector
|
786 | }
|
787 | #endif
|
788 |
|
789 | //#########################################################################
|
790 | U8 ReadDirSector(U32 sector, U8 *buf)
|
791 | //#########################################################################
|
792 | {
|
793 | iob_status=IOB_DIR; // we have to track this
|
794 | return ReadSector(sector,buf); //read sector
|
795 | }
|
796 |
|
797 | #ifdef DOS_WRITE // This has to be a function for Fwrite(), Fclose() !
|
798 | //#########################################################################
|
799 | U8 WriteFileSector(U32 sector, U8 *buf)
|
800 | //#########################################################################
|
801 | {
|
802 | iob_status=IOB_DATA; // we have to track this
|
803 | return WriteSector(sector,buf); //write sector
|
804 | }
|
805 | #endif
|
806 |
|
807 | //#########################################################################
|
808 | U8 ReadFileSector(U32 sector, U8 *buf)
|
809 | //#########################################################################
|
810 | {
|
811 | iob_status=IOB_DATA; // we have to track this
|
812 | return ReadSector(sector,buf); //read sector
|
813 | }
|
814 |
|
815 | #endif //#ifndef USE_FATBUFFER
|
816 | //@}
|