summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c161
1 files changed, 117 insertions, 44 deletions
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
index 2a9b41d08b..a964dcaeb6 100644
--- a/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
+++ b/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
@@ -1137,7 +1137,7 @@ struct ftl_log_type* ftl_get_log_entry(uint32_t block)
1137/* Exposed function: Read highlevel sectors */ 1137/* Exposed function: Read highlevel sectors */
1138uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer) 1138uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer)
1139{ 1139{
1140 uint32_t i; 1140 uint32_t i, j;
1141 uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; 1141 uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1142 uint32_t error = 0; 1142 uint32_t error = 0;
1143 1143
@@ -1163,13 +1163,35 @@ uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer)
1163 + (*logentry).pageoffsets[page]; 1163 + (*logentry).pageoffsets[page];
1164#endif 1164#endif
1165 1165
1166 uint32_t ret = ftl_vfl_read(abspage, &((uint8_t*)buffer)[i << 11], 1166#ifndef FTL_READONLY
1167 &ftl_sparebuffer[0], 1, 1); 1167 if (count >= i + ftl_banks && !(page & (ftl_banks - 1))
1168 if ((ret & 2) != 0) memset(&((uint8_t*)buffer)[i << 11], 0, 0x800); 1168 && logentry == (struct ftl_log_type*)0)
1169 else if ((ret & 0x11D) != 0 || ftl_sparebuffer[0].user.eccmark != 0xFF) 1169#else
1170 if (count >= i + ftl_banks && !(page & (ftl_banks - 1)))
1171#endif
1170 { 1172 {
1171 error = 1; 1173 uint32_t ret = ftl_vfl_read_fast(abspage, &((uint8_t*)buffer)[i << 11],
1172 memset(&((uint8_t*)buffer)[i << 11], 0, 0x800); 1174 &ftl_sparebuffer[0], 1, 1);
1175 for (j = 0; j < ftl_banks; j++)
1176 if (ret & (2 << (j << 2)))
1177 memset(&((uint8_t*)buffer)[(i + j) << 11], 0, 0x800);
1178 else if ((ret & (0xd << (j << 2))) || ftl_sparebuffer[j].user.eccmark != 0xFF)
1179 {
1180 error = 1;
1181 memset(&((uint8_t*)buffer)[(i + j) << 11], 0, 0x800);
1182 }
1183 i += ftl_banks - 1;
1184 }
1185 else
1186 {
1187 uint32_t ret = ftl_vfl_read(abspage, &((uint8_t*)buffer)[i << 11],
1188 &ftl_sparebuffer[0], 1, 1);
1189 if (ret & 2) memset(&((uint8_t*)buffer)[i << 11], 0, 0x800);
1190 else if ((ret & 0x11D) != 0 || ftl_sparebuffer[0].user.eccmark != 0xFF)
1191 {
1192 error = 1;
1193 memset(&((uint8_t*)buffer)[i << 11], 0, 0x800);
1194 }
1173 } 1195 }
1174 } 1196 }
1175 1197
@@ -1387,21 +1409,29 @@ uint32_t ftl_copy_page(uint32_t source, uint32_t destination,
1387/* Copies a pBlock to a vBlock */ 1409/* Copies a pBlock to a vBlock */
1388uint32_t ftl_copy_block(uint32_t source, uint32_t destination) 1410uint32_t ftl_copy_block(uint32_t source, uint32_t destination)
1389{ 1411{
1390 uint32_t i; 1412 uint32_t i, j;
1391 uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; 1413 uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1392 uint32_t error = 0; 1414 uint32_t error = 0;
1393 ftl_cxt.nextblockusn++; 1415 ftl_cxt.nextblockusn++;
1394 for (i = 0; i < ppb; i++) 1416 for (i = 0; i < ppb; i += FTL_COPYBUF_SIZE)
1395 { 1417 {
1396 uint32_t rc = ftl_read(source * ppb + i, 1, ftl_copybuffer[0]); 1418 uint32_t rc = ftl_read(source * ppb + i,
1397 memset(&ftl_sparebuffer[0], 0xFF, 0x40); 1419 FTL_COPYBUF_SIZE, ftl_copybuffer[0]);
1398 ftl_sparebuffer[0].user.lpn = source * ppb + i; 1420 memset(&ftl_copyspare[0], 0xFF, 0x40 * FTL_COPYBUF_SIZE);
1399 ftl_sparebuffer[0].user.usn = ftl_cxt.nextblockusn; 1421 for (j = 0; j < FTL_COPYBUF_SIZE; j++)
1400 ftl_sparebuffer[0].user.type = 0x40; 1422 {
1401 if (rc != 0) ftl_sparebuffer[0].user.eccmark = 0x55; 1423 ftl_copyspare[j].user.lpn = source * ppb + i + j;
1402 if (i == ppb - 1) ftl_sparebuffer[0].user.type = 0x41; 1424 ftl_copyspare[j].user.usn = ftl_cxt.nextblockusn;
1403 if (ftl_vfl_write(destination * ppb + i, 1, 1425 ftl_copyspare[j].user.type = 0x40;
1404 ftl_copybuffer[0], &ftl_sparebuffer[0]) != 0) 1426 if (rc)
1427 {
1428 if (ftl_read(source * ppb + i + j, 1, ftl_copybuffer[j]))
1429 ftl_copyspare[j].user.eccmark = 0x55;
1430 }
1431 if (i + j == ppb - 1) ftl_copyspare[j].user.type = 0x41;
1432 }
1433 if (ftl_vfl_write(destination * ppb + i, FTL_COPYBUF_SIZE,
1434 ftl_copybuffer[0], &ftl_copyspare[0]))
1405 { 1435 {
1406 error = 1; 1436 error = 1;
1407 break; 1437 break;
@@ -1522,22 +1552,37 @@ uint32_t ftl_commit_scattered(struct ftl_log_type* entry)
1522 If this fails for whichever reason, it will be committed the usual way. */ 1552 If this fails for whichever reason, it will be committed the usual way. */
1523uint32_t ftl_commit_sequential(struct ftl_log_type* entry) 1553uint32_t ftl_commit_sequential(struct ftl_log_type* entry)
1524{ 1554{
1555 uint32_t i;
1525 uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; 1556 uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1526 1557
1527 if ((*entry).issequential != 1 1558 if ((*entry).issequential != 1
1528 || (*entry).pagescurrent != (*entry).pagesused) 1559 || (*entry).pagescurrent != (*entry).pagesused)
1529 return 1; 1560 return 1;
1530 1561
1531 for (; (*entry).pagesused < ppb; (*entry).pagesused++) 1562 for (; (*entry).pagesused < ppb; )
1532 { 1563 {
1533 uint32_t lpn = (*entry).logicalvblock * ppb + (*entry).pagesused; 1564 uint32_t lpn = (*entry).logicalvblock * ppb + (*entry).pagesused;
1534 uint32_t newpage = (*entry).scatteredvblock * ppb 1565 uint32_t newpage = (*entry).scatteredvblock * ppb
1535 + (*entry).pagesused; 1566 + (*entry).pagesused;
1536 uint32_t oldpage = ftl_map[(*entry).logicalvblock] * ppb 1567 uint32_t count = FTL_COPYBUF_SIZE < ppb - (*entry).pagesused
1537 + (*entry).pagesused; 1568 ? FTL_COPYBUF_SIZE : ppb - (*entry).pagesused;
1538 if ((*entry).pageoffsets[(*entry).pagesused] != 0xFFFF 1569 for (i = 0; i < count; i++)
1539 || ftl_copy_page(oldpage, newpage, lpn, 1) != 0) 1570 if ((*entry).pageoffsets[(*entry).pagesused + i] != 0xFFFF)
1571 return ftl_commit_scattered(entry);
1572 uint32_t rc = ftl_read(lpn, count, ftl_copybuffer[0]);
1573 memset(&ftl_copyspare[0], 0xFF, 0x40 * FTL_COPYBUF_SIZE);
1574 for (i = 0; i < count; i++)
1575 {
1576 ftl_copyspare[i].user.lpn = lpn + i;
1577 ftl_copyspare[i].user.usn = ++ftl_cxt.nextblockusn;
1578 ftl_copyspare[i].user.type = 0x40;
1579 if (rc) ftl_copyspare[i].user.eccmark = 0x55;
1580 if ((*entry).pagesused + i == ppb - 1)
1581 ftl_copyspare[i].user.type = 0x41;
1582 }
1583 if (ftl_vfl_write(newpage, count, ftl_copybuffer[0], &ftl_copyspare[0]))
1540 return ftl_commit_scattered(entry); 1584 return ftl_commit_scattered(entry);
1585 (*entry).pagesused += count;
1541 } 1586 }
1542 ftl_release_pool_block(ftl_map[(*entry).logicalvblock]); 1587 ftl_release_pool_block(ftl_map[(*entry).logicalvblock]);
1543 ftl_map[(*entry).logicalvblock] = (*entry).scatteredvblock; 1588 ftl_map[(*entry).logicalvblock] = (*entry).scatteredvblock;
@@ -1726,7 +1771,7 @@ uint32_t ftl_swap_blocks(void)
1726/* Exposed function: Write highlevel sectors */ 1771/* Exposed function: Write highlevel sectors */
1727uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer) 1772uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
1728{ 1773{
1729 uint32_t i, j; 1774 uint32_t i, j, k;
1730 uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; 1775 uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1731 1776
1732 if (sector + count > (*ftl_nand_type).userblocks * ppb) 1777 if (sector + count > (*ftl_nand_type).userblocks * ppb)
@@ -1787,16 +1832,27 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
1787 } 1832 }
1788 } 1833 }
1789 ftl_cxt.nextblockusn++; 1834 ftl_cxt.nextblockusn++;
1790 for (j = 0; j < ppb; j++) 1835 for (j = 0; j < ppb; j += FTL_WRITESPARE_SIZE)
1791 { 1836 {
1792 memset(&ftl_sparebuffer[0], 0xFF, 0x40); 1837 memset(&ftl_sparebuffer[0], 0xFF, 0x40 * FTL_WRITESPARE_SIZE);
1793 ftl_sparebuffer[0].user.lpn = sector + i + j; 1838 for (k = 0; k < FTL_WRITESPARE_SIZE; k++)
1794 ftl_sparebuffer[0].user.usn = ftl_cxt.nextblockusn; 1839 {
1795 ftl_sparebuffer[0].user.type = 0x40; 1840 ftl_sparebuffer[k].user.lpn = sector + i + j + k;
1796 if (j == ppb - 1) ftl_sparebuffer[0].user.type = 0x41; 1841 ftl_sparebuffer[k].user.usn = ftl_cxt.nextblockusn;
1797 while (ftl_vfl_write(vblock * ppb + j, 1, 1842 ftl_sparebuffer[k].user.type = 0x40;
1798 &((uint8_t*)buffer)[(i + j) << 11], 1843 if (j == ppb - 1) ftl_sparebuffer[k].user.type = 0x41;
1799 &ftl_sparebuffer[0]) != 0); 1844 }
1845 uint32_t rc = ftl_vfl_write(vblock * ppb + j, FTL_WRITESPARE_SIZE,
1846 &((uint8_t*)buffer)[(i + j) << 11],
1847 &ftl_sparebuffer[0]);
1848 if (rc)
1849 for (k = 0; k < ftl_banks; k++)
1850 if (rc & (1 << k))
1851 {
1852 while (ftl_vfl_write(vblock * ppb + j + k, 1,
1853 &((uint8_t*)buffer)[(i + j + k) << 11],
1854 &ftl_sparebuffer[k]));
1855 }
1800 } 1856 }
1801 ftl_release_pool_block(ftl_map[block]); 1857 ftl_release_pool_block(ftl_map[block]);
1802 ftl_map[block] = vblock; 1858 ftl_map[block] = vblock;
@@ -1814,21 +1870,38 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
1814 return 1; 1870 return 1;
1815 } 1871 }
1816 } 1872 }
1817 memset(&ftl_sparebuffer[0], 0xFF, 0x40); 1873 uint32_t cnt = FTL_WRITESPARE_SIZE;
1818 ftl_sparebuffer[0].user.lpn = sector + i; 1874 if (cnt > count - i) cnt = count - i;
1819 ftl_sparebuffer[0].user.usn = ++ftl_cxt.nextblockusn; 1875 if (cnt > ppb - (*logentry).pagesused) cnt = ppb - (*logentry).pagesused;
1820 ftl_sparebuffer[0].user.type = 0x40; 1876 if (cnt > ppb - page) cnt = ppb - page;
1877 memset(&ftl_sparebuffer[0], 0xFF, 0x40 * cnt);
1878 for (j = 0; j < cnt; j++)
1879 {
1880 ftl_sparebuffer[j].user.lpn = sector + i + j;
1881 ftl_sparebuffer[j].user.usn = ++ftl_cxt.nextblockusn;
1882 ftl_sparebuffer[j].user.type = 0x40;
1883 if ((*logentry).pagesused + j == ppb - 1 && (*logentry).issequential)
1884 ftl_sparebuffer[j].user.type = 0x41;
1885 }
1821 uint32_t abspage = (*logentry).scatteredvblock * ppb 1886 uint32_t abspage = (*logentry).scatteredvblock * ppb
1822 + (*logentry).pagesused++; 1887 + (*logentry).pagesused;
1823 if (ftl_vfl_write(abspage, 1, &((uint8_t*)buffer)[i << 11], 1888 (*logentry).pagesused += cnt;
1889 if (ftl_vfl_write(abspage, cnt, &((uint8_t*)buffer)[i << 11],
1824 &ftl_sparebuffer[0]) == 0) 1890 &ftl_sparebuffer[0]) == 0)
1825 { 1891 {
1826 if ((*logentry).pageoffsets[page] == 0xFFFF) 1892 for (j = 0; j < cnt; j++)
1827 (*logentry).pagescurrent++; 1893 {
1828 (*logentry).pageoffsets[page] = (*logentry).pagesused - 1; 1894 if ((*logentry).pageoffsets[page + j] == 0xFFFF)
1829 ftl_check_still_sequential(logentry, page); 1895 (*logentry).pagescurrent++;
1830 i++; 1896 (*logentry).pageoffsets[page + j] = (*logentry).pagesused - cnt + j;
1897 if ((*logentry).pagesused - cnt + j + 1 != (*logentry).pagescurrent
1898 || (*logentry).pageoffsets[page + j] != page + j)
1899 (*logentry).issequential = 0;
1900 }
1901 i += cnt;
1831 } 1902 }
1903 else panicf("FTL: Write error: %u %u %u!",
1904 (unsigned)sector, (unsigned)count, (unsigned)i);
1832 } 1905 }
1833 if ((*logentry).pagesused == ppb) ftl_remove_scattered_block(logentry); 1906 if ((*logentry).pagesused == ppb) ftl_remove_scattered_block(logentry);
1834 } 1907 }