summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2002-05-09 21:27:49 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2002-05-09 21:27:49 +0000
commit114fce01dd992e1547ef3ce21f954c4f2666c047 (patch)
tree44fedacaa7e34cdaaf1a4d570e97f4b13035b8fa /firmware
parent063a85c66f59e27c262b13e28b7167c254e83990 (diff)
downloadrockbox-114fce01dd992e1547ef3ce21f954c4f2666c047.tar.gz
rockbox-114fce01dd992e1547ef3ce21f954c4f2666c047.zip
New cache algorithm
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@526 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/fat.c91
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 */
127struct bpb fat_bpb; 127struct bpb fat_bpb;
128 128
129/* fat cache */ 129#define FAT_CACHE_SIZE 0x20
130static unsigned char *fat_cache[256]; 130#define FAT_CACHE_MASK (FAT_CACHE_SIZE-1)
131#ifdef DISK_WRITE 131
132static int fat_cache_dirty[256]; 132struct fat_cache_entry
133#endif 133{
134 unsigned char *ptr;
135 int secnum;
136 int dirty;
137};
138
139struct fat_cache_entry fat_cache[FAT_CACHE_SIZE];
134 140
135/* sectors cache for longname use */ 141/* sectors cache for longname use */
136static unsigned char lastsector[SECTOR_SIZE]; 142static 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
309static void *cache_fat_sector(int secnum) 328static 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