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 |
|
558 | // DEBUG-Info:
|
559 | printf("Beginn GDI\r\n");
|
560 |
|
561 | U8 by;
|
562 | U32 DataSec,TotSec;
|
563 | U32 bootSecOffset;
|
564 | U32 FATSz; // FATSize
|
565 | U8 loop;
|
566 |
|
567 | #ifdef USE_FAT32
|
568 | U32 CountofClusters;
|
569 | #else
|
570 | // U16 CountofClusters; // for standard division
|
571 | U32 CountofClusters; // for shifting division
|
572 | #endif
|
573 |
|
574 | U16 RootEntrys;
|
575 |
|
576 | struct MBR *mbr;
|
577 | struct BootSec *boot;
|
578 |
|
579 | by=IdentifyMedia(); //LaufwerksInformationen holen
|
580 |
|
581 | // DEBUG-Info:
|
582 | printf("GDI: Laufwerksinfo geholt\r\n");
|
583 |
|
584 | if(by==0)
|
585 | {
|
586 | FATtype=0; //Unknown FAT type
|
587 | bootSecOffset=0; //erstmal
|
588 |
|
589 | by=ReadSector(0,iob); //Lese den MBR. Erster Sektor auf der Platte
|
590 | //enthält max. 4 Partitionstabellen mit jeweils 16Bytes
|
591 | //Die erste fängt bei 0x01BE an, und nur die nehme ich !
|
592 |
|
593 | //Erstmal checken ob wir nicht schon einen Bootsektor gelesen haben.
|
594 | boot=(struct BootSec *)iob;
|
595 |
|
596 | loop=0;
|
597 | do
|
598 | {
|
599 | // Jetzt checke ich doch den FAT-String im Bootsektor um den Typ der FAT
|
600 | // zu bestimmen. Einen besseren Weg sehe ich im Moment nicht.
|
601 | if( boot->eb.rm.BS_FilSysType[0]=='F'
|
602 | // && boot->eb.rm.BS_FilSysType[1]=='A'
|
603 | // && boot->eb.rm.BS_FilSysType[2]=='T'
|
604 | && boot->eb.rm.BS_FilSysType[3]=='1' )
|
605 | {
|
606 | //Wenn ich hier ankomme habe ich entweder FAT12 oder FAT16
|
607 |
|
608 | // DEBUG-Info:
|
609 | printf("GDI: FAT identifiziert.\r\n");
|
610 |
|
611 | #ifdef USE_FAT12
|
612 | if(boot->eb.rm.BS_FilSysType[4]=='2') FATtype=FAT12;
|
613 | #endif
|
614 | #ifdef USE_FAT16
|
615 | if(boot->eb.rm.BS_FilSysType[4]=='6') FATtype=FAT16;
|
616 | #endif
|
617 | }
|
618 | else
|
619 | {
|
620 | #ifdef USE_FAT32
|
621 | if( boot->eb.rm32.BS_FilSysType[0]=='F'
|
622 | // && boot->eb.rm32.BS_FilSysType[1]=='A'
|
623 | // && boot->eb.rm32.BS_FilSysType[2]=='T'
|
624 | && boot->eb.rm32.BS_FilSysType[3]=='3'
|
625 | && boot->eb.rm32.BS_FilSysType[4]=='2'
|
626 | )
|
627 | {
|
628 | FATtype=FAT32;
|
629 | }
|
630 | else //war kein Bootsektor, also feststellen wo der liegt
|
631 | #endif
|
632 | {
|
633 | mbr=(struct MBR *)iob; //Pointer auf die Partitionstabelle
|
634 | bootSecOffset=mbr->part1.bootoffset; //Nur den brauche ich
|
635 |
|
636 | by=ReadSector(bootSecOffset,iob); //read bootsector
|
637 | boot=(struct BootSec *)iob;
|
638 | }
|
639 | }
|
640 |
|
641 | loop++;
|
642 | }while(loop<2 && FATtype==0); //Bis zu zwei Versuche den Bootsektor zu lesen
|
643 |
|
644 | // DEBUG-Info:
|
645 | printf("GDI: Versuche Bootsektor zu lesen.\r\n");
|
646 |
|
647 | if(FATtype==0)
|
648 | {
|
649 | #ifdef FAT_DEBUG_SHOW_FAT_INFO
|
650 | puts("FAT unknown\n");
|
651 | // DEBUG-Info:
|
652 | printf("GDI: FAT unbekannt.\r\n");
|
653 | #endif
|
654 | return F_ERROR; // FAT-Typ nicht erkannt
|
655 | }
|
656 |
|
657 | secPerCluster=boot->BPB_SecPerClus; //Sectors per Cluster
|
658 | RootEntrys=boot->BPB_RootEntCnt; //32 Byte Root Directory Entrys
|
659 | RootDirSectors = (unsigned char)( ((RootEntrys * 32) + (BYTE_PER_SEC - 1)) / BYTE_PER_SEC);
|
660 |
|
661 | //Number of sectors for FAT
|
662 | if(boot->BPB_FATSz16 != 0) FATSz = boot->BPB_FATSz16;
|
663 | else FATSz = boot->eb.rm32.BPB_FATSz32; //Für FAT32
|
664 |
|
665 | if(boot->BPB_TotSec16 != 0) TotSec = boot->BPB_TotSec16;
|
666 | else TotSec = boot->BPB_TotSec32;
|
667 |
|
668 | FATFirstSector= bootSecOffset + boot->BPB_RsvdSecCnt;
|
669 | FirstRootSector = FATFirstSector + (boot->BPB_NumFATs * FATSz);
|
670 |
|
671 | //Number of data sectors
|
672 | DataSec = TotSec - (boot->BPB_RsvdSecCnt + (boot->BPB_NumFATs * FATSz) + RootDirSectors);
|
673 |
|
674 | FirstDataSector = FirstRootSector + RootDirSectors;
|
675 |
|
676 | //Number of valid clusters
|
677 | //CountofClusters = DataSec / secPerCluster;
|
678 | U8 temp;
|
679 |
|
680 | // secPerCluster is always power of two
|
681 | temp = secPerCluster>>1; // don't divide by 1 ;)
|
682 | CountofClusters = DataSec;
|
683 |
|
684 | while(temp)
|
685 | {
|
686 | CountofClusters >>= 1;
|
687 | temp >>= 1;
|
688 | }
|
689 |
|
690 | maxcluster = CountofClusters + 2;
|
691 |
|
692 | //Note also that the CountofClusters value is exactly that: the count of data clusters
|
693 | //starting at cluster 2. The maximum valid cluster number for the volume is
|
694 | //CountofClusters + 1, and the "count of clusters including the two reserved clusters"
|
695 | // is CountofClusters + 2.
|
696 |
|
697 | FirstDirCluster=0; // for FAT12 and FAT16
|
698 |
|
699 | #ifdef USE_FAT12
|
700 | if(FATtype==FAT12)
|
701 | {
|
702 | endofclusterchain=EOC12;
|
703 | }
|
704 | #endif
|
705 | #ifdef USE_FAT16
|
706 | if(FATtype==FAT16)
|
707 | {
|
708 | endofclusterchain=EOC16;
|
709 | }
|
710 | #endif
|
711 | #ifdef USE_FAT32
|
712 | if(FATtype==FAT32)
|
713 | {
|
714 | endofclusterchain=EOC32;
|
715 | FAT32RootCluster=boot->eb.rm32.BPB_RootClus;
|
716 | FirstDirCluster=FAT32RootCluster;
|
717 | FirstRootSector=GetFirstSectorOfCluster(FAT32RootCluster);
|
718 | }
|
719 | #endif
|
720 |
|
721 | }
|
722 | else
|
723 | {
|
724 | return F_ERROR; // CF gives no answer
|
725 | // DEBUG-Info:
|
726 | printf("GDI: Karte reagiert nicht.\r\n");
|
727 | }
|
728 |
|
729 | FileFirstCluster=0;
|
730 | FileSize=0;
|
731 | FileFlag=0;
|
732 |
|
733 | BytesPerCluster=BYTE_PER_SEC * secPerCluster; //bytes per cluster
|
734 |
|
735 | FATCurrentSector=FATFirstSector;
|
736 |
|
737 | // for debugging only
|
738 | #ifdef FAT_DEBUG_SHOW_FAT_INFO
|
739 | if(FATtype==FAT12) puts("FAT12\n");
|
740 | if(FATtype==FAT16) puts("FAT16\n");
|
741 | if(FATtype==FAT32) puts("FAT32\n");
|
742 |
|
743 | printf("bootSecOffset %lu\n",bootSecOffset);
|
744 | printf("Reserved Sectors %u\n",boot->BPB_RsvdSecCnt);
|
745 | printf("FAT Sectors %lu\n",FATSz);
|
746 | printf("Num. of FAT's %u\n",(U16)boot->BPB_NumFATs);
|
747 | printf("secPerCluster %u\n",(U16)secPerCluster);
|
748 |
|
749 | #ifdef USE_64k_CLUSTERS
|
750 | printf("BytesPerCluster %lu\n",BytesPerCluster);
|
751 | #else
|
752 | printf("BytesPerCluster %u\n",BytesPerCluster);
|
753 | #endif
|
754 |
|
755 | printf("FATFirstSector %lu\n",FATFirstSector);
|
756 | printf("FirstRootSector %lu\n",FirstRootSector);
|
757 | printf("RootDirSectors %u\n",(U16)RootDirSectors);
|
758 | printf("FirstDataSector %lu\n",FirstDataSector);
|
759 | printf("maxsect %lu\n",maxsect);
|
760 | #ifdef USE_FAT32
|
761 | printf("FirstDirCluster %lu\n",FirstDirCluster);
|
762 | printf("maxcluster %lu\n",maxcluster);
|
763 | #else
|
764 | printf("FirstDirCluster %u\n",FirstDirCluster);
|
765 | printf("maxcluster %u\n",maxcluster);
|
766 | #endif
|
767 |
|
768 | #endif //#ifdef FAT_DEBUG_SHOW_FAT_INFO
|
769 |
|
770 | #ifdef DOS_WRITE
|
771 | FATStatus=0; // nothing to write til here
|
772 | #endif
|
773 |
|
774 | ReadFATSector(FATCurrentSector,FAT_IO_BUFFER); //read first FAT sector
|
775 |
|
776 | return F_OK;
|
777 | }
|
778 |
|
779 | #ifndef USE_FATBUFFER
|
780 | #ifdef DOS_WRITE
|
781 | //#########################################################################
|
782 | U8 WriteFATSector(U32 sector, U8 *buf)
|
783 | //#########################################################################
|
784 | {
|
785 | iob_status=IOB_FAT; // we have to track this
|
786 | return WriteSector(sector,buf); //write sector
|
787 | }
|
788 | #endif
|
789 |
|
790 | //#########################################################################
|
791 | U8 ReadFATSector(U32 sector, U8 *buf)
|
792 | //#########################################################################
|
793 | {
|
794 | iob_status=IOB_FAT; // we have to track this
|
795 | return ReadSector(sector,buf); //read sector
|
796 | }
|
797 |
|
798 | #ifdef DOS_WRITE // Better keep this as a function !
|
799 | //#########################################################################
|
800 | U8 WriteDirSector(U32 sector, U8 *buf)
|
801 | //#########################################################################
|
802 | {
|
803 | iob_status=IOB_DIR; // we have to track this
|
804 | return WriteSector(sector,buf); //write sector
|
805 | }
|
806 | #endif
|
807 |
|
808 | //#########################################################################
|
809 | U8 ReadDirSector(U32 sector, U8 *buf)
|
810 | //#########################################################################
|
811 | {
|
812 | iob_status=IOB_DIR; // we have to track this
|
813 | return ReadSector(sector,buf); //read sector
|
814 | }
|
815 |
|
816 | #ifdef DOS_WRITE // This has to be a function for Fwrite(), Fclose() !
|
817 | //#########################################################################
|
818 | U8 WriteFileSector(U32 sector, U8 *buf)
|
819 | //#########################################################################
|
820 | {
|
821 | iob_status=IOB_DATA; // we have to track this
|
822 | return WriteSector(sector,buf); //write sector
|
823 | }
|
824 | #endif
|
825 |
|
826 | //#########################################################################
|
827 | U8 ReadFileSector(U32 sector, U8 *buf)
|
828 | //#########################################################################
|
829 | {
|
830 | iob_status=IOB_DATA; // we have to track this
|
831 | return ReadSector(sector,buf); //read sector
|
832 | }
|
833 |
|
834 | #endif //#ifndef USE_FATBUFFER
|
835 | //@}
|