1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Cástor Muñoz 2016-02-13 18:28:46 +01:00
parent 31d9084a8c
commit e9497dbf6d
3 changed files with 50 additions and 40 deletions

View file

@ -1510,7 +1510,7 @@ static int disk_callback(int btn, struct gui_synclist *lists)
} }
#ifdef HAVE_ATA_SMART #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) 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 9: return "Power-On Hours Count";
case 10: return "Spin-Up Retry Count"; case 10: return "Spin-Up Retry Count";
case 12: return "Power Cycle Count"; case 12: return "Power Cycle Count";
case 191: return "G-Sense Error Rate";
case 192: return "Power-Off Retract Count"; case 192: return "Power-Off Retract Count";
case 193: return "Load/Unload Cycle Count"; case 193: return "Load/Unload Cycle Count";
case 194: return "HDA Temperature"; case 194: return "HDA Temperature";
case 195: return "Hardware ECC Recovered";
case 196: return "Reallocated Event Count"; case 196: return "Reallocated Event Count";
case 197: return "Current Pending Sector Count"; case 197: return "Current Pending Sector Count";
case 198: return "Uncorrectable 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 220: return "Disk Shift";
case 222: return "Loaded Hours"; case 222: return "Loaded Hours";
case 223: return "Load/Unload Retry Count"; case 223: return "Load/Unload Retry Count";
case 224: return "Load Friction"; case 224: return "Load Friction";
case 225: return "Load Cycle Count";
case 226: return "Load-In Time"; case 226: return "Load-In Time";
case 240: return "Transfer Error Rate"; /* Fujitsu */ case 240: return "Transfer Error Rate"; /* Fujitsu */
/*case 240: return "Head Flying Hours";*/
default: return "Unknown Attribute"; default: return "Unknown Attribute";
} }
}; };
@ -1639,7 +1643,7 @@ static bool ata_smart_dump(void)
fd = creat("/smart_data.bin", 0666); fd = creat("/smart_data.bin", 0666);
if(fd >= 0) if(fd >= 0)
{ {
write(fd, smart_data, sizeof(struct ata_smart_values)); write(fd, &smart_data, sizeof(struct ata_smart_values));
close(fd); close(fd);
} }
@ -1651,7 +1655,7 @@ static bool ata_smart_dump(void)
for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++)
{ {
if (ata_smart_attr_to_string( 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, buf, strlen(buf));
write(fd, "\n", 1); 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) static int ata_smart_callback(int btn, struct gui_synclist *lists)
{ {
(void)lists; (void)lists;
static bool read_done = false;
if (btn == ACTION_STD_CANCEL) if (btn == ACTION_STD_CANCEL)
{ {
smart_data = NULL; read_done = false;
return btn; return btn;
} }
/* read S.M.A.R.T. data only on first redraw */ /* read S.M.A.R.T. data only on first redraw */
if (!smart_data) if (!read_done)
{
int rc;
memset(&smart_data, 0, sizeof(struct ata_smart_values));
rc = ata_read_smart(&smart_data);
simplelist_set_line_count(0);
if (rc == 0)
{ {
int i; int i;
char buf[SIMPLELIST_MAX_LINELENGTH]; char buf[SIMPLELIST_MAX_LINELENGTH];
smart_data = ata_read_smart();
simplelist_set_line_count(0);
simplelist_addline("Id Name: Current,Worst Raw"); simplelist_addline("Id Name: Current,Worst Raw");
for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) { for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++)
{
if (ata_smart_attr_to_string( if (ata_smart_attr_to_string(
&smart_data->vendor_attributes[i], buf, sizeof(buf))) &smart_data.vendor_attributes[i], buf, sizeof(buf)))
{
simplelist_addline(buf); simplelist_addline(buf);
} }
} }
}
else
{
simplelist_addline("ATA SMART error: 0x%x", rc);
}
read_done = true;
}
if (btn == ACTION_STD_CONTEXT) if (btn == ACTION_STD_CONTEXT)
{ {
splash(0, "Dumping data...");
ata_smart_dump(); ata_smart_dump();
splashf(HZ, "S.M.A.R.T. data dumped"); splash(HZ, "SMART data dumped");
} }
return btn; return btn;

View file

@ -172,7 +172,7 @@ int ata_get_dma_mode(void);
#ifdef HAVE_ATA_SMART #ifdef HAVE_ATA_SMART
/* Returns current S.M.A.R.T. data */ /* Returns current S.M.A.R.T. data */
void* ata_read_smart(void); int ata_read_smart(struct ata_smart_values*);
#endif #endif
#endif /* __ATA_H__ */ #endif /* __ATA_H__ */

View file

@ -50,9 +50,6 @@
/** static, private data **/ /** static, private data **/
static uint8_t ceata_taskfile[16] STORAGE_ALIGN_ATTR; static uint8_t ceata_taskfile[16] STORAGE_ALIGN_ATTR;
static uint16_t ata_identify_data[0x100] 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 ceata;
static bool ata_swap; static bool ata_swap;
static bool ata_lba48; static bool ata_lba48;
@ -1217,56 +1214,50 @@ int ata_init(void)
#ifdef HAVE_ATA_SMART #ifdef HAVE_ATA_SMART
static int ata_smart(uint16_t* buf) static int ata_smart(uint16_t* buf)
{ {
mutex_lock(&ata_mutex); if (!ata_powered) PASS_RC(ata_power_up(), 3, 0);
ata_power_up();
if (ceata) if (ceata)
{ {
memset(ceata_taskfile, 0, 16); memset(ceata_taskfile, 0, 16);
ceata_taskfile[0xc] = 0x4f; ceata_taskfile[0xc] = 0x4f;
ceata_taskfile[0xd] = 0xc2; 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; 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 */ if (((uint8_t*)ata_identify_data)[54] != 'A') /* Model != aAmsung */
{ {
ceata_taskfile[0x9] = 0xd8; /* SMART enable operations */ ceata_taskfile[0x9] = 0xd8; /* SMART enable operations */
PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 1); PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 2);
PASS_RC(ceata_check_error(), 3, 2); PASS_RC(ceata_check_error(), 3, 3);
} }
ceata_taskfile[0x9] = 0xd0; /* SMART read data */ ceata_taskfile[0x9] = 0xd0; /* SMART read data */
PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 3); 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, 4); PASS_RC(ceata_rw_multiple_block(false, buf, 1, CEATA_COMMAND_TIMEOUT * HZ / 1000000), 3, 5);
} }
else else
{ {
int i; int i;
uint32_t old = ATA_CFG; uint32_t old = ATA_CFG;
ATA_CFG |= BIT(6); /* 16bit big-endian */ ATA_CFG |= BIT(6); /* 16bit big-endian */
PASS_RC(ata_wait_for_not_bsy(10000000), 3, 5); PASS_RC(ata_wait_for_not_bsy(10000000), 3, 6);
ata_write_cbr(&ATA_PIO_DAD, 0);
ata_write_cbr(&ATA_PIO_FED, 0xd0); 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_LMR, 0x4f);
ata_write_cbr(&ATA_PIO_LHR, 0xc2); ata_write_cbr(&ATA_PIO_LHR, 0xc2);
ata_write_cbr(&ATA_PIO_DVR, BIT(6)); ata_write_cbr(&ATA_PIO_DVR, BIT(6));
ata_write_cbr(&ATA_PIO_CSD, 0xb0); 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); for (i = 0; i < 0x100; i++) buf[i] = ata_read_cbr(&ATA_PIO_DTR);
ATA_CFG = old; ATA_CFG = old;
} }
ata_set_active(); ata_set_active();
mutex_unlock(&ata_mutex);
return 0; return 0;
} }
void* ata_read_smart(void) int ata_read_smart(struct ata_smart_values* smart_data)
{ {
ata_smart(ata_smart_data); mutex_lock(&ata_mutex);
return ata_smart_data; int rc = ata_smart((uint16_t*)smart_data);
mutex_unlock(&ata_mutex);
return rc;
} }
#endif /* HAVE_ATA_SMART */ #endif /* HAVE_ATA_SMART */