summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCástor Muñoz <cmvidal@gmail.com>2016-02-13 18:28:46 +0100
committerCástor Muñoz <cmvidal@gmail.com>2016-02-14 15:17:42 +0100
commite9497dbf6d4d0e7ceead8397a736b1efc13ee120 (patch)
tree89efe15d5dff3d94900df72b078f1eb699a1352b
parent31d9084a8ce925c513abe37f0a7e9522925f7791 (diff)
downloadrockbox-e9497dbf6d4d0e7ceead8397a736b1efc13ee120.tar.gz
rockbox-e9497dbf6d4d0e7ceead8397a736b1efc13ee120.zip
iPod Classic: ATA SMART updates
- Add description for attributes supported by Samsung HS081HA (80Gb) and HS161JQ (CEATA 160Gb). - Show error code when ata_read_smart() fails. Change-Id: I618cc4f37d139fc90f596e2cf3a751346b27deb6
-rw-r--r--apps/debug_menu.c51
-rw-r--r--firmware/export/ata.h2
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c37
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
1513static struct ata_smart_values *smart_data = NULL; 1513static struct ata_smart_values smart_data STORAGE_ALIGN_ATTR;
1514 1514
1515static const char * ata_smart_get_attr_name(unsigned char id) 1515static 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)
1666static int ata_smart_callback(int btn, struct gui_synclist *lists) 1670static 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 */
175void* ata_read_smart(void); 175int 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 **/
51static uint8_t ceata_taskfile[16] STORAGE_ALIGN_ATTR; 51static uint8_t ceata_taskfile[16] STORAGE_ALIGN_ATTR;
52static uint16_t ata_identify_data[0x100] STORAGE_ALIGN_ATTR; 52static uint16_t ata_identify_data[0x100] STORAGE_ALIGN_ATTR;
53#ifdef HAVE_ATA_SMART
54static uint16_t ata_smart_data[0x100] STORAGE_ALIGN_ATTR;
55#endif
56static bool ceata; 53static bool ceata;
57static bool ata_swap; 54static bool ata_swap;
58static bool ata_lba48; 55static bool ata_lba48;
@@ -1217,56 +1214,50 @@ int ata_init(void)
1217#ifdef HAVE_ATA_SMART 1214#ifdef HAVE_ATA_SMART
1218static int ata_smart(uint16_t* buf) 1215static 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
1266void* ata_read_smart(void) 1255int 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