summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sparmann <theseven@rockbox.org>2009-10-21 15:28:11 +0000
committerMichael Sparmann <theseven@rockbox.org>2009-10-21 15:28:11 +0000
commit0c89c0ef7cd2439fe74ef57ac408733aef8fd313 (patch)
treec529e5e2327e44eac990e06e4056936919cbdd30
parent3ddbe63ff50dbf882e7c1bd4a2b23bdf8713765e (diff)
downloadrockbox-0c89c0ef7cd2439fe74ef57ac408733aef8fd313.tar.gz
rockbox-0c89c0ef7cd2439fe74ef57ac408733aef8fd313.zip
Fix another bunch of iPod Nano 2G FTL bugs. It seems to work fine for me now, but this doesn't necessarily mean that it's bug-free.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23307 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/powermgmt.c5
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c75
2 files changed, 55 insertions, 25 deletions
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index e756bac3c2..041fed0361 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -806,7 +806,12 @@ void sys_poweroff(void)
806 if (audio_status() & AUDIO_STATUS_RECORD) 806 if (audio_status() & AUDIO_STATUS_RECORD)
807 shutdown_timeout += HZ*8; 807 shutdown_timeout += HZ*8;
808#endif 808#endif
809#ifdef IPOD_NANO2G
810 /* The FTL alone may take half a minute to shut down cleanly. */
811 shutdown_timeout += HZ*60;
812#else
809 shutdown_timeout += HZ*20; 813 shutdown_timeout += HZ*20;
814#endif
810 } 815 }
811 816
812 queue_broadcast(SYS_POWEROFF, 0); 817 queue_broadcast(SYS_POWEROFF, 0);
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
index e3bdca6b30..2c11ab5340 100644
--- a/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
+++ b/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
@@ -498,6 +498,7 @@ uint32_t ftl_vfl_verify_checksum(uint32_t bank)
498 /* The following line is pretty obviously a bug in Whimory, 498 /* The following line is pretty obviously a bug in Whimory,
499 but we do it the same way for compatibility. */ 499 but we do it the same way for compatibility. */
500 if (checksum2 != ftl_vfl_cxt[bank].checksum2) return 0; 500 if (checksum2 != ftl_vfl_cxt[bank].checksum2) return 0;
501 panicf("FTL: Bad VFL CXT checksum!");
501 return 1; 502 return 1;
502} 503}
503 504
@@ -579,6 +580,7 @@ uint32_t ftl_vfl_commit_cxt(uint32_t bank)
579 ftl_vfl_cxt[bank].nextcxtpage = 0; 580 ftl_vfl_cxt[bank].nextcxtpage = 0;
580 if (ftl_vfl_store_cxt(bank) == 0) return 0; 581 if (ftl_vfl_store_cxt(bank) == 0) return 0;
581 } 582 }
583 panicf("FTL: Failed to commit VFL CXT!");
582 return 1; 584 return 1;
583} 585}
584#endif 586#endif
@@ -804,7 +806,8 @@ uint32_t ftl_vfl_read(uint32_t vpage, void* buffer, void* sparebuffer,
804 - (*ftl_nand_type).userblocks - 0x17; 806 - (*ftl_nand_type).userblocks - 0x17;
805 uint32_t abspage = vpage + ppb * syshyperblocks; 807 uint32_t abspage = vpage + ppb * syshyperblocks;
806 if (abspage >= (*ftl_nand_type).blocks * ppb || abspage < ppb) 808 if (abspage >= (*ftl_nand_type).blocks * ppb || abspage < ppb)
807 return 4; 809 panicf("FTL: Trying to read out-of-bounds vPage %u", (unsigned)vpage);
810 //return 4;
808 811
809 uint32_t bank = abspage % ftl_banks; 812 uint32_t bank = abspage % ftl_banks;
810 uint32_t block = abspage / ((*ftl_nand_type).pagesperblock * ftl_banks); 813 uint32_t block = abspage / ((*ftl_nand_type).pagesperblock * ftl_banks);
@@ -842,7 +845,9 @@ uint32_t ftl_vfl_write(uint32_t vpage, void* buffer, void* sparebuffer)
842 - (*ftl_nand_type).userblocks - 0x17; 845 - (*ftl_nand_type).userblocks - 0x17;
843 uint32_t abspage = vpage + ppb * syshyperblocks; 846 uint32_t abspage = vpage + ppb * syshyperblocks;
844 if (abspage >= (*ftl_nand_type).blocks * ppb || abspage < ppb) 847 if (abspage >= (*ftl_nand_type).blocks * ppb || abspage < ppb)
845 return 1; 848 panicf("FTL: Trying to write out-of-bounds vPage %u",
849 (unsigned)vpage);
850 //return 4;
846 851
847 uint32_t bank = abspage % ftl_banks; 852 uint32_t bank = abspage % ftl_banks;
848 uint32_t block = abspage / ((*ftl_nand_type).pagesperblock * ftl_banks); 853 uint32_t block = abspage / ((*ftl_nand_type).pagesperblock * ftl_banks);
@@ -857,6 +862,8 @@ uint32_t ftl_vfl_write(uint32_t vpage, void* buffer, void* sparebuffer)
857 &ftl_sparebuffer, 1, 1) & 0x11F) == 0) 862 &ftl_sparebuffer, 1, 1) & 0x11F) == 0)
858 return 0; 863 return 0;
859 864
865 panicf("FTL: write error on vPage %u, bank %u, pPage %u",
866 (unsigned)vpage, (unsigned)bank, (unsigned)physpage);
860 ftl_vfl_log_trouble(bank, block); 867 ftl_vfl_log_trouble(bank, block);
861 return 1; 868 return 1;
862} 869}
@@ -913,7 +920,9 @@ uint32_t ftl_vfl_open(void)
913 minusn = ftl_sparebuffer.meta.usn; 920 minusn = ftl_sparebuffer.meta.usn;
914 vflcxtidx = k; 921 vflcxtidx = k;
915 } 922 }
916 if (vflcxtidx == 4) return 1; 923 if (vflcxtidx == 4) //return 1;
924 panicf("FTL: No VFL CXT block found on bank %u!",
925 (unsigned)i);
917 last = 0; 926 last = 0;
918 uint32_t max = (*ftl_nand_type).pagesperblock; 927 uint32_t max = (*ftl_nand_type).pagesperblock;
919 for (k = 8; k < max; k += 8) 928 for (k = 8; k < max; k += 8)
@@ -927,7 +936,9 @@ uint32_t ftl_vfl_open(void)
927 if (ftl_vfl_read_page(i, vflcxtblock[vflcxtidx], 936 if (ftl_vfl_read_page(i, vflcxtblock[vflcxtidx],
928 last, ftl_buffer, 937 last, ftl_buffer,
929 &ftl_sparebuffer) != 0) 938 &ftl_sparebuffer) != 0)
930 return 1; 939 panicf("FTL: Re-reading VFL CXT block "
940 "on bank %u failed!?", (unsigned)i);
941 //return 1;
931 memcpy(&ftl_vfl_cxt[i], ftl_buffer, 0x800); 942 memcpy(&ftl_vfl_cxt[i], ftl_buffer, 0x800);
932 if (ftl_vfl_verify_checksum(i) != 0) return 1; 943 if (ftl_vfl_verify_checksum(i) != 0) return 1;
933#ifndef FTL_READONLY 944#ifndef FTL_READONLY
@@ -937,7 +948,8 @@ uint32_t ftl_vfl_open(void)
937 break; 948 break;
938 } 949 }
939 } 950 }
940 else return 1; 951 else //return 1;
952 panicf("FTL: Couldn't load bank %u lowlevel BBT!", (unsigned)i);
941 cxt = ftl_vfl_get_newest_cxt(); 953 cxt = ftl_vfl_get_newest_cxt();
942 for (i = 0; i < ftl_banks; i++) 954 for (i = 0; i < ftl_banks; i++)
943 memcpy(ftl_vfl_cxt[i].ftlctrlblocks, (*cxt).ftlctrlblocks, 6); 955 memcpy(ftl_vfl_cxt[i].ftlctrlblocks, (*cxt).ftlctrlblocks, 6);
@@ -967,7 +979,8 @@ uint32_t ftl_open(void)
967 ftlcxtblock = (*cxt).ftlctrlblocks[i]; 979 ftlcxtblock = (*cxt).ftlctrlblocks[i];
968 } 980 }
969 981
970 if (ftlcxtblock == 0xffffffff) return 1; 982 if (ftlcxtblock == 0xffffffff) //return 1;
983 panicf("FTL: Couldn't find readable FTL CXT block!");
971 984
972 uint32_t ftlcxtfound = 0; 985 uint32_t ftlcxtfound = 0;
973 for (i = (*ftl_nand_type).pagesperblock * ftl_banks - 1; i > 0; i--) 986 for (i = (*ftl_nand_type).pagesperblock * ftl_banks - 1; i > 0; i--)
@@ -985,12 +998,14 @@ uint32_t ftl_open(void)
985 { 998 {
986 /* This will trip if there was an unclean unmount before. */ 999 /* This will trip if there was an unclean unmount before. */
987#ifndef FTL_FORCEMOUNT 1000#ifndef FTL_FORCEMOUNT
1001 panicf("FTL: Unclean shutdown before!");
988 break; 1002 break;
989#endif 1003#endif
990 } 1004 }
991 } 1005 }
992 1006
993 if (ftlcxtfound == 0) return 1; 1007 if (ftlcxtfound == 0) //return 1;
1008 panicf("FTL: Couldn't find FTL CXT page!");
994 1009
995 uint32_t pagestoread = (*ftl_nand_type).userblocks >> 10; 1010 uint32_t pagestoread = (*ftl_nand_type).userblocks >> 10;
996 if (((*ftl_nand_type).userblocks & 0x1FF) != 0) pagestoread++; 1011 if (((*ftl_nand_type).userblocks & 0x1FF) != 0) pagestoread++;
@@ -999,7 +1014,8 @@ uint32_t ftl_open(void)
999 { 1014 {
1000 if ((ftl_vfl_read(ftl_cxt.ftl_map_pages[i], 1015 if ((ftl_vfl_read(ftl_cxt.ftl_map_pages[i],
1001 ftl_buffer, &ftl_sparebuffer, 1, 1) & 0x11F) != 0) 1016 ftl_buffer, &ftl_sparebuffer, 1, 1) & 0x11F) != 0)
1002 return 1; 1017 panicf("FTL: Failed to read block map page %u", (unsigned)i);
1018 //return 1;
1003 1019
1004 uint32_t toread = 2048; 1020 uint32_t toread = 2048;
1005 if (toread > ((*ftl_nand_type).userblocks << 1) - (i << 11)) 1021 if (toread > ((*ftl_nand_type).userblocks << 1) - (i << 11))
@@ -1016,7 +1032,8 @@ uint32_t ftl_open(void)
1016 { 1032 {
1017 if ((ftl_vfl_read(ftl_cxt.ftl_erasectr_pages[i], 1033 if ((ftl_vfl_read(ftl_cxt.ftl_erasectr_pages[i],
1018 ftl_buffer, &ftl_sparebuffer, 1, 1) & 0x11F) != 0) 1034 ftl_buffer, &ftl_sparebuffer, 1, 1) & 0x11F) != 0)
1019 return 1; 1035 panicf("FTL: Failed to read erase counter page %u", (unsigned)i);
1036 //return 1;
1020 1037
1021 uint32_t toread = 2048; 1038 uint32_t toread = 2048;
1022 if (toread > (((*ftl_nand_type).userblocks + 23) << 1) - (i << 11)) 1039 if (toread > (((*ftl_nand_type).userblocks + 23) << 1) - (i << 11))
@@ -1087,7 +1104,7 @@ uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer)
1087 uint32_t ret = ftl_vfl_read(abspage, &((uint8_t*)buffer)[i << 11], 1104 uint32_t ret = ftl_vfl_read(abspage, &((uint8_t*)buffer)[i << 11],
1088 &ftl_sparebuffer, 1, 1); 1105 &ftl_sparebuffer, 1, 1);
1089 if ((ret & 2) != 0) memset(&((uint8_t*)buffer)[i << 11], 0, 0x800); 1106 if ((ret & 2) != 0) memset(&((uint8_t*)buffer)[i << 11], 0, 0x800);
1090 if ((ret & 0x11F) != 0 || ftl_sparebuffer.user.eccmark != 0xFF) 1107 else if ((ret & 0x11D) != 0 || ftl_sparebuffer.user.eccmark != 0xFF)
1091 { 1108 {
1092 error = 1; 1109 error = 1;
1093 memset(&((uint8_t*)buffer)[i << 11], 0, 0x800); 1110 memset(&((uint8_t*)buffer)[i << 11], 0, 0x800);
@@ -1126,6 +1143,8 @@ uint32_t ftl_erase_block_internal(uint32_t block)
1126 } 1143 }
1127 if (rc != 0) 1144 if (rc != 0)
1128 { 1145 {
1146 panicf("FTL: Block erase failed on bank %u block %u",
1147 (unsigned)i, (unsigned)block);
1129 if (pblock != block) 1148 if (pblock != block)
1130 { 1149 {
1131 uint32_t spareindex = pblock - ftl_vfl_cxt[i].firstspare; 1150 uint32_t spareindex = pblock - ftl_vfl_cxt[i].firstspare;
@@ -1315,7 +1334,7 @@ uint32_t ftl_copy_block(uint32_t source, uint32_t destination)
1315 ftl_cxt.nextblockusn++; 1334 ftl_cxt.nextblockusn++;
1316 for (i = 0; i < ppb; i++) 1335 for (i = 0; i < ppb; i++)
1317 { 1336 {
1318 uint32_t rc = ftl_read(source * ppb + i, 1, buffer) & 0x11D; 1337 uint32_t rc = ftl_read(source * ppb + i, 1, buffer);
1319 memset(&ftl_sparebuffer, 0xFF, 0x40); 1338 memset(&ftl_sparebuffer, 0xFF, 0x40);
1320 ftl_sparebuffer.user.lpn = source * ppb + i; 1339 ftl_sparebuffer.user.lpn = source * ppb + i;
1321 ftl_sparebuffer.user.usn = ftl_cxt.nextblockusn; 1340 ftl_sparebuffer.user.usn = ftl_cxt.nextblockusn;
@@ -1362,9 +1381,9 @@ uint32_t ftl_compact_scattered(struct ftl_log_type* entry)
1362{ 1381{
1363 uint32_t i, j; 1382 uint32_t i, j;
1364 uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; 1383 uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1365 uint32_t pagecount = (*entry).pagescurrent;
1366 uint32_t error; 1384 uint32_t error;
1367 struct ftl_log_type backup; 1385 struct ftl_log_type backup;
1386 uint16_t backup_pageoffsets[0x200];
1368 if ((*entry).pagescurrent == 0) 1387 if ((*entry).pagescurrent == 0)
1369 { 1388 {
1370 ftl_release_pool_block((*entry).scatteredvblock); 1389 ftl_release_pool_block((*entry).scatteredvblock);
@@ -1372,6 +1391,7 @@ uint32_t ftl_compact_scattered(struct ftl_log_type* entry)
1372 return 0; 1391 return 0;
1373 } 1392 }
1374 backup = *entry; 1393 backup = *entry;
1394 memcpy(backup_pageoffsets, (*entry).pageoffsets, 0x400);
1375 for (i = 0; i < 4; i++) 1395 for (i = 0; i < 4; i++)
1376 { 1396 {
1377 uint32_t block = ftl_allocate_pool_block(); 1397 uint32_t block = ftl_allocate_pool_block();
@@ -1386,7 +1406,7 @@ uint32_t ftl_compact_scattered(struct ftl_log_type* entry)
1386 { 1406 {
1387 uint32_t lpn = (*entry).logicalvblock * ppb + j; 1407 uint32_t lpn = (*entry).logicalvblock * ppb + j;
1388 uint32_t newpage = block * ppb + (*entry).pagesused; 1408 uint32_t newpage = block * ppb + (*entry).pagesused;
1389 uint32_t oldpage = (*entry).scatteredvblock * ppb 1409 uint32_t oldpage = backup.scatteredvblock * ppb
1390 + (*entry).pageoffsets[j]; 1410 + (*entry).pageoffsets[j];
1391 if (ftl_copy_page(oldpage, newpage, lpn, 1411 if (ftl_copy_page(oldpage, newpage, lpn,
1392 (*entry).issequential) != 0) 1412 (*entry).issequential) != 0)
@@ -1398,9 +1418,14 @@ uint32_t ftl_compact_scattered(struct ftl_log_type* entry)
1398 (*entry).pagescurrent++; 1418 (*entry).pagescurrent++;
1399 ftl_check_still_sequential(entry, j); 1419 ftl_check_still_sequential(entry, j);
1400 } 1420 }
1401 if (pagecount != (*entry).pagescurrent) error = 1; 1421 if (backup.pagescurrent != (*entry).pagescurrent) error = 1;
1402 if (error == 0) break; 1422 if (error == 0)
1423 {
1424 ftl_release_pool_block(backup.scatteredvblock);
1425 break;
1426 }
1403 *entry = backup; 1427 *entry = backup;
1428 memcpy((*entry).pageoffsets, backup_pageoffsets, 0x400);
1404 } 1429 }
1405 return error; 1430 return error;
1406} 1431}
@@ -1440,7 +1465,6 @@ uint32_t ftl_commit_scattered(struct ftl_log_type* entry)
1440uint32_t ftl_commit_sequential(struct ftl_log_type* entry) 1465uint32_t ftl_commit_sequential(struct ftl_log_type* entry)
1441{ 1466{
1442 uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; 1467 uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1443 uint32_t error = 0;
1444 1468
1445 if ((*entry).issequential != 1 1469 if ((*entry).issequential != 1
1446 || (*entry).pagescurrent != (*entry).pagesused) 1470 || (*entry).pagescurrent != (*entry).pagesused)
@@ -1455,12 +1479,8 @@ uint32_t ftl_commit_sequential(struct ftl_log_type* entry)
1455 + (*entry).pagesused; 1479 + (*entry).pagesused;
1456 if ((*entry).pageoffsets[(*entry).pagesused] != 0xFFFF 1480 if ((*entry).pageoffsets[(*entry).pagesused] != 0xFFFF
1457 || ftl_copy_page(oldpage, newpage, lpn, 1) != 0) 1481 || ftl_copy_page(oldpage, newpage, lpn, 1) != 0)
1458 { 1482 return ftl_commit_scattered(entry);
1459 error = 1;
1460 break;
1461 }
1462 } 1483 }
1463 if (error != 0) return ftl_commit_scattered(entry);
1464 ftl_release_pool_block(ftl_map[(*entry).logicalvblock]); 1484 ftl_release_pool_block(ftl_map[(*entry).logicalvblock]);
1465 ftl_map[(*entry).logicalvblock] = (*entry).scatteredvblock; 1485 ftl_map[(*entry).logicalvblock] = (*entry).scatteredvblock;
1466 (*entry).scatteredvblock = 0xFFFF; 1486 (*entry).scatteredvblock = 0xFFFF;
@@ -1540,7 +1560,8 @@ struct ftl_log_type* ftl_allocate_log_entry(uint32_t block)
1540 1560
1541 if (entry == (struct ftl_log_type*)0) 1561 if (entry == (struct ftl_log_type*)0)
1542 { 1562 {
1543 while (ftl_cxt.freecount <= 3) 1563 if (ftl_cxt.freecount < 3) panicf("FTL: Detected a pool block leak!");
1564 else if (ftl_cxt.freecount == 3)
1544 if (ftl_remove_scattered_block((struct ftl_log_type*)0) != 0) 1565 if (ftl_remove_scattered_block((struct ftl_log_type*)0) != 0)
1545 return (struct ftl_log_type*)0; 1566 return (struct ftl_log_type*)0;
1546 entry = ftl_log; 1567 entry = ftl_log;
@@ -1831,7 +1852,8 @@ uint32_t ftl_init(void)
1831 uint32_t i; 1852 uint32_t i;
1832 uint32_t result = 0; 1853 uint32_t result = 0;
1833 uint32_t foundsignature, founddevinfo, blockwiped, repaired, skip; 1854 uint32_t foundsignature, founddevinfo, blockwiped, repaired, skip;
1834 if (nand_device_init() != 0) return 1; 1855 if (nand_device_init() != 0) //return 1;
1856 panicf("FTL: Lowlevel NAND driver init failed!");
1835 ftl_banks = 0; 1857 ftl_banks = 0;
1836 for (i = 0; i < 4; i++) 1858 for (i = 0; i < 4; i++)
1837 if (nand_get_device_type(i) != 0) ftl_banks = i + 1; 1859 if (nand_get_device_type(i) != 0) ftl_banks = i + 1;
@@ -1859,12 +1881,14 @@ uint32_t ftl_init(void)
1859 if (founddevinfo == 0) 1881 if (founddevinfo == 0)
1860 { 1882 {
1861 mutex_unlock(&ftl_mtx); 1883 mutex_unlock(&ftl_mtx);
1862 return 1; 1884 panicf("FTL: No DEVICEINFO found!");
1885 //return 1;
1863 } 1886 }
1864 if (foundsignature != 0 && (result & 0x11F) != 0) 1887 if (foundsignature != 0 && (result & 0x11F) != 0)
1865 { 1888 {
1866 mutex_unlock(&ftl_mtx); 1889 mutex_unlock(&ftl_mtx);
1867 return 1; 1890 panicf("FTL: Problem with the signature!");
1891 //return 1;
1868 } 1892 }
1869 if (ftl_vfl_open() == 0) 1893 if (ftl_vfl_open() == 0)
1870 if (ftl_open() == 0) 1894 if (ftl_open() == 0)
@@ -1873,6 +1897,7 @@ uint32_t ftl_init(void)
1873 return 0; 1897 return 0;
1874 } 1898 }
1875 1899
1900 panicf("FTL: Initialization failed!");
1876 1901
1877/* Something went terribly wrong. We may want to allow the user to erase 1902/* Something went terribly wrong. We may want to allow the user to erase
1878 block zero in that condition, to make norboot reinitialize the FTL. 1903 block zero in that condition, to make norboot reinitialize the FTL.