From e9497dbf6d4d0e7ceead8397a736b1efc13ee120 Mon Sep 17 00:00:00 2001 From: Cástor Muñoz Date: Sat, 13 Feb 2016 18:28:46 +0100 Subject: 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 --- apps/debug_menu.c | 51 +++++++++++++++------- firmware/export/ata.h | 2 +- .../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) } #ifdef HAVE_ATA_SMART -static struct ata_smart_values *smart_data = NULL; +static struct ata_smart_values smart_data STORAGE_ALIGN_ATTR; static const char * ata_smart_get_attr_name(unsigned char id) { @@ -1526,20 +1526,24 @@ static const char * ata_smart_get_attr_name(unsigned char id) case 9: return "Power-On Hours Count"; case 10: return "Spin-Up Retry Count"; case 12: return "Power Cycle Count"; + case 191: return "G-Sense Error Rate"; case 192: return "Power-Off Retract Count"; case 193: return "Load/Unload Cycle Count"; case 194: return "HDA Temperature"; + case 195: return "Hardware ECC Recovered"; case 196: return "Reallocated Event Count"; case 197: return "Current Pending Sector Count"; case 198: return "Uncorrectable Sector Count"; - case 199: return "UltraDMA CRC Error Count"; + case 199: return "UDMA CRC Error Count"; + case 200: return "Write Error Rate"; + case 201: return "TA Counter Detected"; case 220: return "Disk Shift"; case 222: return "Loaded Hours"; case 223: return "Load/Unload Retry Count"; case 224: return "Load Friction"; + case 225: return "Load Cycle Count"; case 226: return "Load-In Time"; case 240: return "Transfer Error Rate"; /* Fujitsu */ - /*case 240: return "Head Flying Hours";*/ default: return "Unknown Attribute"; } }; @@ -1639,7 +1643,7 @@ static bool ata_smart_dump(void) fd = creat("/smart_data.bin", 0666); if(fd >= 0) { - write(fd, smart_data, sizeof(struct ata_smart_values)); + write(fd, &smart_data, sizeof(struct ata_smart_values)); close(fd); } @@ -1651,7 +1655,7 @@ static bool ata_smart_dump(void) for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) { if (ata_smart_attr_to_string( - &smart_data->vendor_attributes[i], buf, sizeof(buf))) + &smart_data.vendor_attributes[i], buf, sizeof(buf))) { write(fd, buf, strlen(buf)); write(fd, "\n", 1); @@ -1666,32 +1670,47 @@ static bool ata_smart_dump(void) static int ata_smart_callback(int btn, struct gui_synclist *lists) { (void)lists; + static bool read_done = false; if (btn == ACTION_STD_CANCEL) { - smart_data = NULL; + read_done = false; return btn; } /* read S.M.A.R.T. data only on first redraw */ - if (!smart_data) + if (!read_done) { - int i; - char buf[SIMPLELIST_MAX_LINELENGTH]; - smart_data = ata_read_smart(); + int rc; + memset(&smart_data, 0, sizeof(struct ata_smart_values)); + rc = ata_read_smart(&smart_data); simplelist_set_line_count(0); - simplelist_addline("Id Name: Current,Worst Raw"); - for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) { - if (ata_smart_attr_to_string( - &smart_data->vendor_attributes[i], buf, sizeof(buf))) - simplelist_addline(buf); + if (rc == 0) + { + int i; + char buf[SIMPLELIST_MAX_LINELENGTH]; + simplelist_addline("Id Name: Current,Worst Raw"); + for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) + { + if (ata_smart_attr_to_string( + &smart_data.vendor_attributes[i], buf, sizeof(buf))) + { + simplelist_addline(buf); + } + } + } + else + { + simplelist_addline("ATA SMART error: 0x%x", rc); } + read_done = true; } if (btn == ACTION_STD_CONTEXT) { + splash(0, "Dumping data..."); ata_smart_dump(); - splashf(HZ, "S.M.A.R.T. data dumped"); + splash(HZ, "SMART data dumped"); } 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); #ifdef HAVE_ATA_SMART /* Returns current S.M.A.R.T. data */ -void* ata_read_smart(void); +int ata_read_smart(struct ata_smart_values*); #endif #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 @@ /** static, private data **/ static uint8_t ceata_taskfile[16] STORAGE_ALIGN_ATTR; static uint16_t ata_identify_data[0x100] STORAGE_ALIGN_ATTR; -#ifdef HAVE_ATA_SMART -static uint16_t ata_smart_data[0x100] STORAGE_ALIGN_ATTR; -#endif static bool ceata; static bool ata_swap; static bool ata_lba48; @@ -1217,56 +1214,50 @@ int ata_init(void) #ifdef HAVE_ATA_SMART static int ata_smart(uint16_t* buf) { - mutex_lock(&ata_mutex); - ata_power_up(); - + if (!ata_powered) PASS_RC(ata_power_up(), 3, 0); if (ceata) { memset(ceata_taskfile, 0, 16); ceata_taskfile[0xc] = 0x4f; ceata_taskfile[0xd] = 0xc2; - ceata_taskfile[0xe] = 0x40; /* Device/Head Register, bit6: 0->CHS, 1->LBA */ + ceata_taskfile[0xe] = BIT(6); ceata_taskfile[0xf] = 0xb0; - PASS_RC(ceata_wait_idle(), 3, 0); + PASS_RC(ceata_wait_idle(), 3, 1); if (((uint8_t*)ata_identify_data)[54] != 'A') /* Model != aAmsung */ { ceata_taskfile[0x9] = 0xd8; /* SMART enable operations */ - PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 1); - PASS_RC(ceata_check_error(), 3, 2); + PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 2); + PASS_RC(ceata_check_error(), 3, 3); } ceata_taskfile[0x9] = 0xd0; /* SMART read data */ - PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 3); - PASS_RC(ceata_rw_multiple_block(false, buf, 1, CEATA_COMMAND_TIMEOUT * HZ / 1000000), 3, 4); + PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 4); + PASS_RC(ceata_rw_multiple_block(false, buf, 1, CEATA_COMMAND_TIMEOUT * HZ / 1000000), 3, 5); } else { int i; uint32_t old = ATA_CFG; ATA_CFG |= BIT(6); /* 16bit big-endian */ - PASS_RC(ata_wait_for_not_bsy(10000000), 3, 5); - ata_write_cbr(&ATA_PIO_DAD, 0); + PASS_RC(ata_wait_for_not_bsy(10000000), 3, 6); ata_write_cbr(&ATA_PIO_FED, 0xd0); - ata_write_cbr(&ATA_PIO_SCR, 0); - ata_write_cbr(&ATA_PIO_LLR, 0); ata_write_cbr(&ATA_PIO_LMR, 0x4f); ata_write_cbr(&ATA_PIO_LHR, 0xc2); ata_write_cbr(&ATA_PIO_DVR, BIT(6)); ata_write_cbr(&ATA_PIO_CSD, 0xb0); - PASS_RC(ata_wait_for_start_of_transfer(10000000), 3, 6); + PASS_RC(ata_wait_for_start_of_transfer(10000000), 3, 7); for (i = 0; i < 0x100; i++) buf[i] = ata_read_cbr(&ATA_PIO_DTR); ATA_CFG = old; } - ata_set_active(); - mutex_unlock(&ata_mutex); - return 0; } -void* ata_read_smart(void) +int ata_read_smart(struct ata_smart_values* smart_data) { - ata_smart(ata_smart_data); - return ata_smart_data; + mutex_lock(&ata_mutex); + int rc = ata_smart((uint16_t*)smart_data); + mutex_unlock(&ata_mutex); + return rc; } #endif /* HAVE_ATA_SMART */ -- cgit v1.2.3