Fix ATA SMART and CHECK POWER MODE
This patch fixes two things: 1) CHECK POWER MODE The error return value wasn't always zero, so it would show up as offline. Error is now explicitly set to zero. 2) SMART The smart values that were returned were invalid and tools like skdump would not recognize that the smart data was actually valid and would dump weird output. The data has been fixed up and raw value support was added. Tools like skdump and palimpsest work as expected. Signed-off-by: Brian Wheeler <bdwheele@indiana.edu> Acked-by: Ryan Harper <ryanh@us.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
301db7c2dd
commit
b93af93d2b
|
@ -34,13 +34,26 @@
|
||||||
|
|
||||||
#include <hw/ide/internal.h>
|
#include <hw/ide/internal.h>
|
||||||
|
|
||||||
static const int smart_attributes[][5] = {
|
/* These values were based on a Seagate ST3500418AS but have been modified
|
||||||
/* id, flags, val, wrst, thrsh */
|
to make more sense in QEMU */
|
||||||
{ 0x01, 0x03, 0x64, 0x64, 0x06}, /* raw read */
|
static const int smart_attributes[][12] = {
|
||||||
{ 0x03, 0x03, 0x64, 0x64, 0x46}, /* spin up */
|
/* id, flags, hflags, val, wrst, raw (6 bytes), threshold */
|
||||||
{ 0x04, 0x02, 0x64, 0x64, 0x14}, /* start stop count */
|
/* raw read error rate*/
|
||||||
{ 0x05, 0x03, 0x64, 0x64, 0x36}, /* remapped sectors */
|
{ 0x01, 0x03, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06},
|
||||||
{ 0x00, 0x00, 0x00, 0x00, 0x00}
|
/* spin up */
|
||||||
|
{ 0x03, 0x03, 0x00, 0x64, 0x64, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
/* start stop count */
|
||||||
|
{ 0x04, 0x02, 0x00, 0x64, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14},
|
||||||
|
/* remapped sectors */
|
||||||
|
{ 0x05, 0x03, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24},
|
||||||
|
/* power on hours */
|
||||||
|
{ 0x09, 0x03, 0x00, 0x64, 0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
/* power cycle count */
|
||||||
|
{ 0x0c, 0x03, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
/* airflow-temperature-celsius */
|
||||||
|
{ 190, 0x03, 0x00, 0x45, 0x45, 0x1f, 0x00, 0x1f, 0x1f, 0x00, 0x00, 0x32},
|
||||||
|
/* end of list */
|
||||||
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* XXX: DVDs that could fit on a CD will be reported as a CD */
|
/* XXX: DVDs that could fit on a CD will be reported as a CD */
|
||||||
|
@ -1843,6 +1856,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
|
||||||
break;
|
break;
|
||||||
case WIN_CHECKPOWERMODE1:
|
case WIN_CHECKPOWERMODE1:
|
||||||
case WIN_CHECKPOWERMODE2:
|
case WIN_CHECKPOWERMODE2:
|
||||||
|
s->error = 0;
|
||||||
s->nsector = 0xff; /* device active or idle */
|
s->nsector = 0xff; /* device active or idle */
|
||||||
s->status = READY_STAT | SEEK_STAT;
|
s->status = READY_STAT | SEEK_STAT;
|
||||||
ide_set_irq(s->bus);
|
ide_set_irq(s->bus);
|
||||||
|
@ -2097,7 +2111,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
|
||||||
if (smart_attributes[n][0] == 0)
|
if (smart_attributes[n][0] == 0)
|
||||||
break;
|
break;
|
||||||
s->io_buffer[2+0+(n*12)] = smart_attributes[n][0];
|
s->io_buffer[2+0+(n*12)] = smart_attributes[n][0];
|
||||||
s->io_buffer[2+1+(n*12)] = smart_attributes[n][4];
|
s->io_buffer[2+1+(n*12)] = smart_attributes[n][11];
|
||||||
}
|
}
|
||||||
for (n=0; n<511; n++) /* checksum */
|
for (n=0; n<511; n++) /* checksum */
|
||||||
s->io_buffer[511] += s->io_buffer[n];
|
s->io_buffer[511] += s->io_buffer[n];
|
||||||
|
@ -2110,12 +2124,13 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
|
||||||
memset(s->io_buffer, 0, 0x200);
|
memset(s->io_buffer, 0, 0x200);
|
||||||
s->io_buffer[0] = 0x01; /* smart struct version */
|
s->io_buffer[0] = 0x01; /* smart struct version */
|
||||||
for (n=0; n<30; n++) {
|
for (n=0; n<30; n++) {
|
||||||
if (smart_attributes[n][0] == 0)
|
if (smart_attributes[n][0] == 0) {
|
||||||
break;
|
break;
|
||||||
s->io_buffer[2+0+(n*12)] = smart_attributes[n][0];
|
}
|
||||||
s->io_buffer[2+1+(n*12)] = smart_attributes[n][1];
|
int i;
|
||||||
s->io_buffer[2+3+(n*12)] = smart_attributes[n][2];
|
for(i = 0; i < 11; i++) {
|
||||||
s->io_buffer[2+4+(n*12)] = smart_attributes[n][3];
|
s->io_buffer[2+i+(n*12)] = smart_attributes[n][i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
s->io_buffer[362] = 0x02 | (s->smart_autosave?0x80:0x00);
|
s->io_buffer[362] = 0x02 | (s->smart_autosave?0x80:0x00);
|
||||||
if (s->smart_selftest_count == 0) {
|
if (s->smart_selftest_count == 0) {
|
||||||
|
|
Loading…
Reference in a new issue