diff options
-rw-r--r-- | apps/debug_menu.c | 51 | ||||
-rw-r--r-- | firmware/export/ata.h | 2 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c | 37 |
3 files changed, 50 insertions, 40 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 6676a84d4b..694252a897 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c | |||
@@ -1510,7 +1510,7 @@ static int disk_callback(int btn, struct gui_synclist *lists) | |||
1510 | } | 1510 | } |
1511 | 1511 | ||
1512 | #ifdef HAVE_ATA_SMART | 1512 | #ifdef HAVE_ATA_SMART |
1513 | static struct ata_smart_values *smart_data = NULL; | 1513 | static struct ata_smart_values smart_data STORAGE_ALIGN_ATTR; |
1514 | 1514 | ||
1515 | static const char * ata_smart_get_attr_name(unsigned char id) | 1515 | static const char * ata_smart_get_attr_name(unsigned char id) |
1516 | { | 1516 | { |
@@ -1526,20 +1526,24 @@ static const char * ata_smart_get_attr_name(unsigned char id) | |||
1526 | case 9: return "Power-On Hours Count"; | 1526 | case 9: return "Power-On Hours Count"; |
1527 | case 10: return "Spin-Up Retry Count"; | 1527 | case 10: return "Spin-Up Retry Count"; |
1528 | case 12: return "Power Cycle Count"; | 1528 | case 12: return "Power Cycle Count"; |
1529 | case 191: return "G-Sense Error Rate"; | ||
1529 | case 192: return "Power-Off Retract Count"; | 1530 | case 192: return "Power-Off Retract Count"; |
1530 | case 193: return "Load/Unload Cycle Count"; | 1531 | case 193: return "Load/Unload Cycle Count"; |
1531 | case 194: return "HDA Temperature"; | 1532 | case 194: return "HDA Temperature"; |
1533 | case 195: return "Hardware ECC Recovered"; | ||
1532 | case 196: return "Reallocated Event Count"; | 1534 | case 196: return "Reallocated Event Count"; |
1533 | case 197: return "Current Pending Sector Count"; | 1535 | case 197: return "Current Pending Sector Count"; |
1534 | case 198: return "Uncorrectable Sector Count"; | 1536 | case 198: return "Uncorrectable Sector Count"; |
1535 | case 199: return "UltraDMA CRC Error Count"; | 1537 | case 199: return "UDMA CRC Error Count"; |
1538 | case 200: return "Write Error Rate"; | ||
1539 | case 201: return "TA Counter Detected"; | ||
1536 | case 220: return "Disk Shift"; | 1540 | case 220: return "Disk Shift"; |
1537 | case 222: return "Loaded Hours"; | 1541 | case 222: return "Loaded Hours"; |
1538 | case 223: return "Load/Unload Retry Count"; | 1542 | case 223: return "Load/Unload Retry Count"; |
1539 | case 224: return "Load Friction"; | 1543 | case 224: return "Load Friction"; |
1544 | case 225: return "Load Cycle Count"; | ||
1540 | case 226: return "Load-In Time"; | 1545 | case 226: return "Load-In Time"; |
1541 | case 240: return "Transfer Error Rate"; /* Fujitsu */ | 1546 | case 240: return "Transfer Error Rate"; /* Fujitsu */ |
1542 | /*case 240: return "Head Flying Hours";*/ | ||
1543 | default: return "Unknown Attribute"; | 1547 | default: return "Unknown Attribute"; |
1544 | } | 1548 | } |
1545 | }; | 1549 | }; |
@@ -1639,7 +1643,7 @@ static bool ata_smart_dump(void) | |||
1639 | fd = creat("/smart_data.bin", 0666); | 1643 | fd = creat("/smart_data.bin", 0666); |
1640 | if(fd >= 0) | 1644 | if(fd >= 0) |
1641 | { | 1645 | { |
1642 | write(fd, smart_data, sizeof(struct ata_smart_values)); | 1646 | write(fd, &smart_data, sizeof(struct ata_smart_values)); |
1643 | close(fd); | 1647 | close(fd); |
1644 | } | 1648 | } |
1645 | 1649 | ||
@@ -1651,7 +1655,7 @@ static bool ata_smart_dump(void) | |||
1651 | for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) | 1655 | for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) |
1652 | { | 1656 | { |
1653 | if (ata_smart_attr_to_string( | 1657 | if (ata_smart_attr_to_string( |
1654 | &smart_data->vendor_attributes[i], buf, sizeof(buf))) | 1658 | &smart_data.vendor_attributes[i], buf, sizeof(buf))) |
1655 | { | 1659 | { |
1656 | write(fd, buf, strlen(buf)); | 1660 | write(fd, buf, strlen(buf)); |
1657 | write(fd, "\n", 1); | 1661 | write(fd, "\n", 1); |
@@ -1666,32 +1670,47 @@ static bool ata_smart_dump(void) | |||
1666 | static int ata_smart_callback(int btn, struct gui_synclist *lists) | 1670 | static int ata_smart_callback(int btn, struct gui_synclist *lists) |
1667 | { | 1671 | { |
1668 | (void)lists; | 1672 | (void)lists; |
1673 | static bool read_done = false; | ||
1669 | 1674 | ||
1670 | if (btn == ACTION_STD_CANCEL) | 1675 | if (btn == ACTION_STD_CANCEL) |
1671 | { | 1676 | { |
1672 | smart_data = NULL; | 1677 | read_done = false; |
1673 | return btn; | 1678 | return btn; |
1674 | } | 1679 | } |
1675 | 1680 | ||
1676 | /* read S.M.A.R.T. data only on first redraw */ | 1681 | /* read S.M.A.R.T. data only on first redraw */ |
1677 | if (!smart_data) | 1682 | if (!read_done) |
1678 | { | 1683 | { |
1679 | int i; | 1684 | int rc; |
1680 | char buf[SIMPLELIST_MAX_LINELENGTH]; | 1685 | memset(&smart_data, 0, sizeof(struct ata_smart_values)); |
1681 | smart_data = ata_read_smart(); | 1686 | rc = ata_read_smart(&smart_data); |
1682 | simplelist_set_line_count(0); | 1687 | simplelist_set_line_count(0); |
1683 | simplelist_addline("Id Name: Current,Worst Raw"); | 1688 | if (rc == 0) |
1684 | for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) { | 1689 | { |
1685 | if (ata_smart_attr_to_string( | 1690 | int i; |
1686 | &smart_data->vendor_attributes[i], buf, sizeof(buf))) | 1691 | char buf[SIMPLELIST_MAX_LINELENGTH]; |
1687 | simplelist_addline(buf); | 1692 | simplelist_addline("Id Name: Current,Worst Raw"); |
1693 | for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) | ||
1694 | { | ||
1695 | if (ata_smart_attr_to_string( | ||
1696 | &smart_data.vendor_attributes[i], buf, sizeof(buf))) | ||
1697 | { | ||
1698 | simplelist_addline(buf); | ||
1699 | } | ||
1700 | } | ||
1701 | } | ||
1702 | else | ||
1703 | { | ||
1704 | simplelist_addline("ATA SMART error: 0x%x", rc); | ||
1688 | } | 1705 | } |
1706 | read_done = true; | ||
1689 | } | 1707 | } |
1690 | 1708 | ||
1691 | if (btn == ACTION_STD_CONTEXT) | 1709 | if (btn == ACTION_STD_CONTEXT) |
1692 | { | 1710 | { |
1711 | splash(0, "Dumping data..."); | ||
1693 | ata_smart_dump(); | 1712 | ata_smart_dump(); |
1694 | splashf(HZ, "S.M.A.R.T. data dumped"); | 1713 | splash(HZ, "SMART data dumped"); |
1695 | } | 1714 | } |
1696 | 1715 | ||
1697 | return btn; | 1716 | return btn; |
diff --git a/firmware/export/ata.h b/firmware/export/ata.h index 6f0d0b699f..a1b7ab6372 100644 --- a/firmware/export/ata.h +++ b/firmware/export/ata.h | |||
@@ -172,7 +172,7 @@ int ata_get_dma_mode(void); | |||
172 | 172 | ||
173 | #ifdef HAVE_ATA_SMART | 173 | #ifdef HAVE_ATA_SMART |
174 | /* Returns current S.M.A.R.T. data */ | 174 | /* Returns current S.M.A.R.T. data */ |
175 | void* ata_read_smart(void); | 175 | int ata_read_smart(struct ata_smart_values*); |
176 | #endif | 176 | #endif |
177 | 177 | ||
178 | #endif /* __ATA_H__ */ | 178 | #endif /* __ATA_H__ */ |
diff --git a/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c index 53ec45ec6d..da45906b36 100644 --- a/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c +++ b/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c | |||
@@ -50,9 +50,6 @@ | |||
50 | /** static, private data **/ | 50 | /** static, private data **/ |
51 | static uint8_t ceata_taskfile[16] STORAGE_ALIGN_ATTR; | 51 | static uint8_t ceata_taskfile[16] STORAGE_ALIGN_ATTR; |
52 | static uint16_t ata_identify_data[0x100] STORAGE_ALIGN_ATTR; | 52 | static uint16_t ata_identify_data[0x100] STORAGE_ALIGN_ATTR; |
53 | #ifdef HAVE_ATA_SMART | ||
54 | static uint16_t ata_smart_data[0x100] STORAGE_ALIGN_ATTR; | ||
55 | #endif | ||
56 | static bool ceata; | 53 | static bool ceata; |
57 | static bool ata_swap; | 54 | static bool ata_swap; |
58 | static bool ata_lba48; | 55 | static bool ata_lba48; |
@@ -1217,56 +1214,50 @@ int ata_init(void) | |||
1217 | #ifdef HAVE_ATA_SMART | 1214 | #ifdef HAVE_ATA_SMART |
1218 | static int ata_smart(uint16_t* buf) | 1215 | static int ata_smart(uint16_t* buf) |
1219 | { | 1216 | { |
1220 | mutex_lock(&ata_mutex); | 1217 | if (!ata_powered) PASS_RC(ata_power_up(), 3, 0); |
1221 | ata_power_up(); | ||
1222 | |||
1223 | if (ceata) | 1218 | if (ceata) |
1224 | { | 1219 | { |
1225 | memset(ceata_taskfile, 0, 16); | 1220 | memset(ceata_taskfile, 0, 16); |
1226 | ceata_taskfile[0xc] = 0x4f; | 1221 | ceata_taskfile[0xc] = 0x4f; |
1227 | ceata_taskfile[0xd] = 0xc2; | 1222 | ceata_taskfile[0xd] = 0xc2; |
1228 | ceata_taskfile[0xe] = 0x40; /* Device/Head Register, bit6: 0->CHS, 1->LBA */ | 1223 | ceata_taskfile[0xe] = BIT(6); |
1229 | ceata_taskfile[0xf] = 0xb0; | 1224 | ceata_taskfile[0xf] = 0xb0; |
1230 | PASS_RC(ceata_wait_idle(), 3, 0); | 1225 | PASS_RC(ceata_wait_idle(), 3, 1); |
1231 | if (((uint8_t*)ata_identify_data)[54] != 'A') /* Model != aAmsung */ | 1226 | if (((uint8_t*)ata_identify_data)[54] != 'A') /* Model != aAmsung */ |
1232 | { | 1227 | { |
1233 | ceata_taskfile[0x9] = 0xd8; /* SMART enable operations */ | 1228 | ceata_taskfile[0x9] = 0xd8; /* SMART enable operations */ |
1234 | PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 1); | 1229 | PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 2); |
1235 | PASS_RC(ceata_check_error(), 3, 2); | 1230 | PASS_RC(ceata_check_error(), 3, 3); |
1236 | } | 1231 | } |
1237 | ceata_taskfile[0x9] = 0xd0; /* SMART read data */ | 1232 | ceata_taskfile[0x9] = 0xd0; /* SMART read data */ |
1238 | PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 3); | 1233 | PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 4); |
1239 | PASS_RC(ceata_rw_multiple_block(false, buf, 1, CEATA_COMMAND_TIMEOUT * HZ / 1000000), 3, 4); | 1234 | PASS_RC(ceata_rw_multiple_block(false, buf, 1, CEATA_COMMAND_TIMEOUT * HZ / 1000000), 3, 5); |
1240 | } | 1235 | } |
1241 | else | 1236 | else |
1242 | { | 1237 | { |
1243 | int i; | 1238 | int i; |
1244 | uint32_t old = ATA_CFG; | 1239 | uint32_t old = ATA_CFG; |
1245 | ATA_CFG |= BIT(6); /* 16bit big-endian */ | 1240 | ATA_CFG |= BIT(6); /* 16bit big-endian */ |
1246 | PASS_RC(ata_wait_for_not_bsy(10000000), 3, 5); | 1241 | PASS_RC(ata_wait_for_not_bsy(10000000), 3, 6); |
1247 | ata_write_cbr(&ATA_PIO_DAD, 0); | ||
1248 | ata_write_cbr(&ATA_PIO_FED, 0xd0); | 1242 | ata_write_cbr(&ATA_PIO_FED, 0xd0); |
1249 | ata_write_cbr(&ATA_PIO_SCR, 0); | ||
1250 | ata_write_cbr(&ATA_PIO_LLR, 0); | ||
1251 | ata_write_cbr(&ATA_PIO_LMR, 0x4f); | 1243 | ata_write_cbr(&ATA_PIO_LMR, 0x4f); |
1252 | ata_write_cbr(&ATA_PIO_LHR, 0xc2); | 1244 | ata_write_cbr(&ATA_PIO_LHR, 0xc2); |
1253 | ata_write_cbr(&ATA_PIO_DVR, BIT(6)); | 1245 | ata_write_cbr(&ATA_PIO_DVR, BIT(6)); |
1254 | ata_write_cbr(&ATA_PIO_CSD, 0xb0); | 1246 | ata_write_cbr(&ATA_PIO_CSD, 0xb0); |
1255 | PASS_RC(ata_wait_for_start_of_transfer(10000000), 3, 6); | 1247 | PASS_RC(ata_wait_for_start_of_transfer(10000000), 3, 7); |
1256 | for (i = 0; i < 0x100; i++) buf[i] = ata_read_cbr(&ATA_PIO_DTR); | 1248 | for (i = 0; i < 0x100; i++) buf[i] = ata_read_cbr(&ATA_PIO_DTR); |
1257 | ATA_CFG = old; | 1249 | ATA_CFG = old; |
1258 | } | 1250 | } |
1259 | |||
1260 | ata_set_active(); | 1251 | ata_set_active(); |
1261 | mutex_unlock(&ata_mutex); | ||
1262 | |||
1263 | return 0; | 1252 | return 0; |
1264 | } | 1253 | } |
1265 | 1254 | ||
1266 | void* ata_read_smart(void) | 1255 | int ata_read_smart(struct ata_smart_values* smart_data) |
1267 | { | 1256 | { |
1268 | ata_smart(ata_smart_data); | 1257 | mutex_lock(&ata_mutex); |
1269 | return ata_smart_data; | 1258 | int rc = ata_smart((uint16_t*)smart_data); |
1259 | mutex_unlock(&ata_mutex); | ||
1260 | return rc; | ||
1270 | } | 1261 | } |
1271 | #endif /* HAVE_ATA_SMART */ | 1262 | #endif /* HAVE_ATA_SMART */ |
1272 | 1263 | ||