summaryrefslogtreecommitdiff
path: root/apps/debug_menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/debug_menu.c')
-rw-r--r--apps/debug_menu.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index e602b713c3..2b9702299b 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -1507,6 +1507,205 @@ static int disk_callback(int btn, struct gui_synclist *lists)
1507#endif /* HAVE_ATA_DMA */ 1507#endif /* HAVE_ATA_DMA */
1508 return btn; 1508 return btn;
1509} 1509}
1510
1511#ifdef HAVE_ATA_SMART
1512static struct ata_smart_values *smart_data = NULL;
1513
1514static const char * ata_smart_get_attr_name(unsigned char id)
1515{
1516 switch (id)
1517 {
1518 case 1: return "Raw Read Error Rate";
1519 case 2: return "Throughput Performance";
1520 case 3: return "Spin-Up Time";
1521 case 4: return "Start/Stop Count";
1522 case 5: return "Reallocated Sector Count";
1523 case 7: return "Seek Error Rate";
1524 case 8: return "Seek Time Performance";
1525 case 9: return "Power-On Hours Count";
1526 case 10: return "Spin-Up Retry Count";
1527 case 12: return "Power Cycle Count";
1528 case 192: return "Power-Off Retract Count";
1529 case 193: return "Load/Unload Cycle Count";
1530 case 194: return "HDA Temperature";
1531 case 196: return "Reallocated Event Count";
1532 case 197: return "Current Pending Sector Count";
1533 case 198: return "Uncorrectable Sector Count";
1534 case 199: return "UltraDMA CRC Error Count";
1535 case 220: return "Disk Shift";
1536 case 222: return "Loaded Hours";
1537 case 223: return "Load/Unload Retry Count";
1538 case 224: return "Load Friction";
1539 case 226: return "Load-In Time";
1540 case 240: return "Transfer Error Rate"; /* Fujitsu */
1541 /*case 240: return "Head Flying Hours";*/
1542 default: return "Unknown Attribute";
1543 }
1544};
1545
1546static int ata_smart_get_attr_rawfmt(unsigned char id)
1547{
1548 switch (id)
1549 {
1550 case 3: /* Spin-up time */
1551 return RAWFMT_RAW16_OPT_AVG16;
1552
1553 case 5: /* Reallocated sector count */
1554 case 196: /* Reallocated event count */
1555 return RAWFMT_RAW16_OPT_RAW16;
1556
1557 case 190: /* Airflow Temperature */
1558 case 194: /* HDA Temperature */
1559 return RAWFMT_TEMPMINMAX;
1560
1561 default:
1562 return RAWFMT_RAW48;
1563 }
1564};
1565
1566static int ata_smart_attr_to_string(
1567 struct ata_smart_attribute *attr, char *str, int size)
1568{
1569 uint16_t w[3]; /* 3 words to store 6 bytes of raw data */
1570 char buf[size]; /* temp string to store attribute data */
1571 int len, slen;
1572 int id = attr->id;
1573
1574 if (id == 0)
1575 return 0; /* null attribute */
1576
1577 /* align and convert raw data */
1578 memcpy(w, attr->raw, 6);
1579 w[0] = letoh16(w[0]);
1580 w[1] = letoh16(w[1]);
1581 w[2] = letoh16(w[2]);
1582
1583 len = snprintf(buf, size, ": %u,%u ", attr->current, attr->worst);
1584
1585 switch (ata_smart_get_attr_rawfmt(id))
1586 {
1587 case RAWFMT_RAW16_OPT_RAW16:
1588 len += snprintf(buf+len, size-len, "%u", w[0]);
1589 if ((w[1] || w[2]) && (len < size))
1590 len += snprintf(buf+len, size-len, " %u %u", w[1],w[2]);
1591 break;
1592
1593 case RAWFMT_RAW16_OPT_AVG16:
1594 len += snprintf(buf+len, size-len, "%u", w[0]);
1595 if (w[1] && (len < size))
1596 len += snprintf(buf+len, size-len, " Avg: %u", w[1]);
1597 break;
1598
1599 case RAWFMT_TEMPMINMAX:
1600 len += snprintf(buf+len, size-len, "%u -/+: %u/%u", w[0],w[1],w[2]);
1601 break;
1602
1603 case RAWFMT_RAW48:
1604 default:
1605 /* shows first 4 bytes of raw data as uint32 LE,
1606 and the ramaining 2 bytes as uint16 LE */
1607 len += snprintf(buf+len, size-len, "%lu", letoh32(*((uint32_t*)w)));
1608 if (w[2] && (len < size))
1609 len += snprintf(buf+len, size-len, " %u", w[2]);
1610 break;
1611 }
1612 /* ignore trailing \0 when truncated */
1613 if (len >= size) len = size-1;
1614
1615 /* fill return string; when max. size is exceded: first truncate
1616 attribute name, then attribute data and finally attribute id */
1617 slen = snprintf(str, size, "%d ", id);
1618 if (slen < size) {
1619 /* maximum space disponible for attribute name,
1620 including initial space separator */
1621 int name_sz = size - (slen + len);
1622 if (name_sz > 1) {
1623 len = snprintf(str+slen, name_sz, " %s",
1624 ata_smart_get_attr_name(id));
1625 if (len >= name_sz) len = name_sz-1;
1626 slen += len;
1627 }
1628 snprintf(str+slen, size-slen, "%s", buf);
1629 }
1630
1631 return 1; /* ok */
1632}
1633
1634static bool ata_smart_dump(void)
1635{
1636 int fd;
1637
1638 fd = creat("/smart_data.bin", 0666);
1639 if(fd >= 0)
1640 {
1641 write(fd, smart_data, sizeof(struct ata_smart_values));
1642 close(fd);
1643 }
1644
1645 fd = creat("/smart_data.txt", 0666);
1646 if(fd >= 0)
1647 {
1648 int i;
1649 char buf[128];
1650 for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++)
1651 {
1652 if (ata_smart_attr_to_string(
1653 &smart_data->vendor_attributes[i], buf, sizeof(buf)))
1654 {
1655 write(fd, buf, strlen(buf));
1656 write(fd, "\n", 1);
1657 }
1658 }
1659 close(fd);
1660 }
1661
1662 return false;
1663}
1664
1665static int ata_smart_callback(int btn, struct gui_synclist *lists)
1666{
1667 (void)lists;
1668
1669 if (btn == ACTION_STD_CANCEL)
1670 {
1671 smart_data = NULL;
1672 return btn;
1673 }
1674
1675 /* read S.M.A.R.T. data only on first redraw */
1676 if (!smart_data)
1677 {
1678 int i;
1679 char buf[SIMPLELIST_MAX_LINELENGTH];
1680 smart_data = ata_read_smart();
1681 simplelist_set_line_count(0);
1682 simplelist_addline("Id Name: Current,Worst Raw");
1683 for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) {
1684 if (ata_smart_attr_to_string(
1685 &smart_data->vendor_attributes[i], buf, sizeof(buf)))
1686 simplelist_addline(buf);
1687 }
1688 }
1689
1690 if (btn == ACTION_STD_CONTEXT)
1691 {
1692 ata_smart_dump();
1693 splashf(HZ, "S.M.A.R.T. data dumped");
1694 }
1695
1696 return btn;
1697}
1698
1699static bool dbg_ata_smart(void)
1700{
1701 struct simplelist_info info;
1702 simplelist_info_init(&info, "S.M.A.R.T. Data [CONTEXT to dump]", 1, NULL);
1703 info.action_callback = ata_smart_callback;
1704 info.hide_selection = true;
1705 info.scroll_all = true;
1706 return simplelist_show_list(&info);
1707}
1708#endif /* HAVE_ATA_SMART */
1510#else /* No SD, MMC or ATA */ 1709#else /* No SD, MMC or ATA */
1511static int disk_callback(int btn, struct gui_synclist *lists) 1710static int disk_callback(int btn, struct gui_synclist *lists)
1512{ 1711{
@@ -2383,6 +2582,9 @@ static const struct {
2383 { "View disk info", dbg_disk_info }, 2582 { "View disk info", dbg_disk_info },
2384#if (CONFIG_STORAGE & STORAGE_ATA) 2583#if (CONFIG_STORAGE & STORAGE_ATA)
2385 { "Dump ATA identify info", dbg_identify_info}, 2584 { "Dump ATA identify info", dbg_identify_info},
2585#ifdef HAVE_ATA_SMART
2586 { "View/Dump S.M.A.R.T. data", dbg_ata_smart},
2587#endif
2386#endif 2588#endif
2387#endif 2589#endif
2388 { "Metadata log", dbg_metadatalog }, 2590 { "Metadata log", dbg_metadatalog },