diff options
-rw-r--r-- | firmware/drivers/fat.c | 91 |
1 files changed, 71 insertions, 20 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index a55a8a2864..c663c5d937 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -126,11 +126,17 @@ static int create_dos_name(unsigned char *name, unsigned char *newname); | |||
126 | /* global FAT info struct */ | 126 | /* global FAT info struct */ |
127 | struct bpb fat_bpb; | 127 | struct bpb fat_bpb; |
128 | 128 | ||
129 | /* fat cache */ | 129 | #define FAT_CACHE_SIZE 0x20 |
130 | static unsigned char *fat_cache[256]; | 130 | #define FAT_CACHE_MASK (FAT_CACHE_SIZE-1) |
131 | #ifdef DISK_WRITE | 131 | |
132 | static int fat_cache_dirty[256]; | 132 | struct fat_cache_entry |
133 | #endif | 133 | { |
134 | unsigned char *ptr; | ||
135 | int secnum; | ||
136 | int dirty; | ||
137 | }; | ||
138 | |||
139 | struct fat_cache_entry fat_cache[FAT_CACHE_SIZE]; | ||
134 | 140 | ||
135 | /* sectors cache for longname use */ | 141 | /* sectors cache for longname use */ |
136 | static unsigned char lastsector[SECTOR_SIZE]; | 142 | static unsigned char lastsector[SECTOR_SIZE]; |
@@ -173,6 +179,19 @@ int fat_mount(int startsector) | |||
173 | int err; | 179 | int err; |
174 | int datasec; | 180 | int datasec; |
175 | int countofclusters; | 181 | int countofclusters; |
182 | int i; | ||
183 | |||
184 | /* Clear the cache. Be aware! The bss section MUST have been cleared | ||
185 | at boot. Otherwise we will free() garbage pointers here */ | ||
186 | for(i = 0;i < FAT_CACHE_SIZE;i++) | ||
187 | { | ||
188 | if(fat_cache[i].ptr) | ||
189 | { | ||
190 | free(fat_cache[i].ptr); | ||
191 | } | ||
192 | fat_cache[i].secnum = 8; /* We use a "safe" sector just in case */ | ||
193 | fat_cache[i].dirty = 0; | ||
194 | } | ||
176 | 195 | ||
177 | /* Read the sector */ | 196 | /* Read the sector */ |
178 | err = ata_read_sectors(startsector,1,buf); | 197 | err = ata_read_sectors(startsector,1,buf); |
@@ -308,9 +327,34 @@ static int bpb_is_sane(void) | |||
308 | 327 | ||
309 | static void *cache_fat_sector(int secnum) | 328 | static void *cache_fat_sector(int secnum) |
310 | { | 329 | { |
330 | int cache_index = secnum & FAT_CACHE_MASK; | ||
311 | unsigned char *sec; | 331 | unsigned char *sec; |
312 | 332 | ||
313 | sec = fat_cache[secnum]; | 333 | sec = fat_cache[cache_index].ptr; |
334 | |||
335 | /* Delete the cache entry if it isn't the sector we want */ | ||
336 | if(sec && fat_cache[cache_index].secnum != secnum) | ||
337 | { | ||
338 | #ifdef WRITE | ||
339 | /* Write back if it is dirty */ | ||
340 | if(fat_cache[cache_index].dirty) | ||
341 | { | ||
342 | if(ata_write_sectors(secnum + fat_bpb.bpb_rsvdseccnt + | ||
343 | fat_bpb.startsector, 1, sec)) | ||
344 | { | ||
345 | panic("cache_fat_sector() - Could" | ||
346 | " not write sector %d\n", | ||
347 | secnum); | ||
348 | } | ||
349 | } | ||
350 | free(sec); | ||
351 | |||
352 | fat_cache[cache_index].ptr = NULL; | ||
353 | fat_cache[cache_index].secnum = 8; /* Normally an unused sector */ | ||
354 | fat_cache[cache_index].dirty = 0; | ||
355 | #endif | ||
356 | } | ||
357 | |||
314 | /* Load the sector if it is not cached */ | 358 | /* Load the sector if it is not cached */ |
315 | if(!sec) | 359 | if(!sec) |
316 | { | 360 | { |
@@ -328,7 +372,8 @@ static void *cache_fat_sector(int secnum) | |||
328 | free(sec); | 372 | free(sec); |
329 | return NULL; | 373 | return NULL; |
330 | } | 374 | } |
331 | fat_cache[secnum] = sec; | 375 | fat_cache[cache_index].ptr = sec; |
376 | fat_cache[cache_index].secnum = secnum; | ||
332 | } | 377 | } |
333 | return sec; | 378 | return sec; |
334 | } | 379 | } |
@@ -354,7 +399,9 @@ static int update_entry(int entry, unsigned int val) | |||
354 | return -1; | 399 | return -1; |
355 | } | 400 | } |
356 | 401 | ||
357 | fat_cache_dirty[thisfatsecnum] = 1; | 402 | /* We can safely assume that the correct sector is in the cache, |
403 | so we mark it dirty without checking the sector number */ | ||
404 | fat_cache[thisfatsecnum & FAT_CACHE_MASK].dirty = 1; | ||
358 | 405 | ||
359 | /* don't change top 4 bits */ | 406 | /* don't change top 4 bits */ |
360 | sec[thisfatentoffset/sizeof(int)] &= 0xf000000; | 407 | sec[thisfatentoffset/sizeof(int)] &= 0xf000000; |
@@ -406,36 +453,40 @@ static int flush_fat(struct bpb *bpb) | |||
406 | int i; | 453 | int i; |
407 | int err; | 454 | int err; |
408 | unsigned char *sec; | 455 | unsigned char *sec; |
456 | int secnum; | ||
409 | int fatsz; | 457 | int fatsz; |
410 | unsigned short d, t; | 458 | unsigned short d, t; |
411 | char m; | 459 | char m; |
412 | 460 | ||
413 | fatsz = fat_bpb.fatsize; | 461 | fatsz = fat_bpb.fatsize; |
414 | 462 | ||
415 | for(i = 0;i < 256;i++) | 463 | for(i = 0;i < FAT_CACHE_SIZE;i++) |
416 | { | 464 | { |
417 | if(fat_cache[i] && fat_cache_dirty[i]) | 465 | if(fat_cache[i].ptr && fat_cache[i].dirty) |
418 | { | 466 | { |
419 | DEBUGF("Flushing FAT sector %d\n", i); | 467 | secnum = fat_cache[i].secnum + fat_bpb.bpb_rsvdseccnt + |
420 | sec = fat_cache[i]; | 468 | fat_bpb.startsector; |
421 | err = ata_write_sectors(i + fat_bpb.bpb_rsvdseccnt + fat_bpb.startsector, | 469 | DEBUGF("Flushing FAT sector %d\n", secnum); |
422 | 1,sec); | 470 | sec = fat_cache[i].ptr; |
471 | |||
472 | /* Write to the first FAT */ | ||
473 | err = ata_write_sectors(secnum, 1, sec); | ||
423 | if(err) | 474 | if(err) |
424 | { | 475 | { |
425 | DEBUGF( "flush_fat() - Couldn't write" | 476 | DEBUGF( "flush_fat() - Couldn't write" |
426 | " sector (%d)\n", i + fat_bpb.bpb_rsvdseccnt); | 477 | " sector (%d)\n", secnum); |
427 | return -1; | 478 | return -1; |
428 | } | 479 | } |
429 | err = ata_write_sectors(i + fat_bpb.bpb_rsvdseccnt + fatsz + | 480 | |
430 | fat_bpb.startsector, | 481 | /* Write to the second FAT */ |
431 | 1,sec); | 482 | err = ata_write_sectors(secnum + fatsz, 1, sec); |
432 | if(err) | 483 | if(err) |
433 | { | 484 | { |
434 | DEBUGF( "flush_fat() - Couldn't write" | 485 | DEBUGF( "flush_fat() - Couldn't write" |
435 | " sector (%d)\n", i + fat_bpb.bpb_rsvdseccnt + fatsz); | 486 | " sector (%d)\n", secnum + fatsz); |
436 | return -1; | 487 | return -1; |
437 | } | 488 | } |
438 | fat_cache_dirty[i] = 0; | 489 | fat_cache[i].dirty = 0; |
439 | } | 490 | } |
440 | } | 491 | } |
441 | 492 | ||