diff options
author | Michael Sparmann <theseven@rockbox.org> | 2010-03-13 20:31:18 +0000 |
---|---|---|
committer | Michael Sparmann <theseven@rockbox.org> | 2010-03-13 20:31:18 +0000 |
commit | 1fd3221198df995f50c5fcd8a7e7245c7931874a (patch) | |
tree | b1d5fc492d4dbe7d486fbf31872a72befda403e9 /firmware/target/arm | |
parent | a9e732c6df2a83d1c5c31a3d44299ec9e640f467 (diff) | |
download | rockbox-1fd3221198df995f50c5fcd8a7e7245c7931874a.tar.gz rockbox-1fd3221198df995f50c5fcd8a7e7245c7931874a.zip |
Use the new read API and introduce fast highlevel FTL code.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25149 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c | 161 |
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 */ |
1138 | uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer) | 1138 | uint32_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 */ |
1388 | uint32_t ftl_copy_block(uint32_t source, uint32_t destination) | 1410 | uint32_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. */ |
1523 | uint32_t ftl_commit_sequential(struct ftl_log_type* entry) | 1553 | uint32_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 */ |
1727 | uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer) | 1772 | uint32_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 | } |