diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG index 2dcc0fe8bb9b8712576545d7f74ec82a045f51f7..1a3be759f14e8607da8bef457bc987cd3dd65b14 100644 --- a/sm5/CHANGELOG +++ b/sm5/CHANGELOG @@ -1,6 +1,6 @@ CHANGELOG for smartmontools -$Id: CHANGELOG,v 1.656 2008/02/26 13:47:58 guidog Exp $ +$Id: CHANGELOG,v 1.657 2008/03/03 22:29:02 shattered Exp $ The most recent version of this file is: http://smartmontools.cvs.sourceforge.net/smartmontools/sm5/CHANGELOG?view=markup @@ -38,6 +38,12 @@ NOTES FOR FUTURE RELEASES: see TODO file. SMARTMONTOOLS STABLE RELEASE 5.38 2008/02/24 + [SS] Major NetBSD-specific bugfixes: + - handle actual SCSI and ATA errors and not only ioctl() errors; + - set up I/O request properly for AUTO_OFFLINE and AUTOSAVE commands (inspired by + similar change in os_freebsd.cpp); + - handle AUTO_OFFLINE and AUTOSAVE like STATUS_CHECK (like os_linux.cpp does). + [GG] add kfreebsd gnu support to configure.in [BA] Fix auto-offline support in FreeBSD. Thanks to diff --git a/sm5/os_netbsd.cpp b/sm5/os_netbsd.cpp index 8e179b3e285281b37bcb40d44900ce0237163ad8..0d76c639a9d5aaf51b3f5f3359992bd3dbd15256 100644 --- a/sm5/os_netbsd.cpp +++ b/sm5/os_netbsd.cpp @@ -24,7 +24,7 @@ #include "os_netbsd.h" #include <unistd.h> -const char *os_XXXX_c_cvsid = "$Id: os_netbsd.cpp,v 1.19 2006/09/20 16:17:31 shattered Exp $" \ +const char *os_XXXX_c_cvsid = "$Id: os_netbsd.cpp,v 1.20 2008/03/03 22:29:02 shattered Exp $" \ ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_NETBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID; /* global variable holding byte count of allocated memory */ @@ -171,10 +171,9 @@ int marvell_command_interface(int fd, smart_command_set command, int select, char *data) { return -1; } -int highpoint_command_interface(int fd, smart_command_set command, int select, char *data) -{ - return -1; -} +int +highpoint_command_interface(int fd, smart_command_set command, int select, char *data) +{ return -1; } int ata_command_interface(int fd, smart_command_set command, int select, char *data) @@ -248,14 +247,14 @@ ata_command_interface(int fd, smart_command_set command, int select, char *data) copydata = 1; break; case ENABLE: - req.flags = ATACMD_READ; + req.flags = ATACMD_READREG; req.features = WDSM_ENABLE_OPS; req.command = WDCC_SMART; req.cylinder = WDSMART_CYL; req.timeout = 1000; break; case DISABLE: - req.flags = ATACMD_READ; + req.flags = ATACMD_READREG; req.features = WDSM_DISABLE_OPS; req.command = WDCC_SMART; req.cylinder = WDSMART_CYL; @@ -263,28 +262,24 @@ ata_command_interface(int fd, smart_command_set command, int select, char *data) break; case AUTO_OFFLINE: /* NOTE: According to ATAPI 4 and UP, this command is obsolete */ - req.flags = ATACMD_READ; + req.flags = ATACMD_READREG; req.features = ATA_SMART_AUTO_OFFLINE; /* XXX missing from wdcreg.h */ req.command = WDCC_SMART; - req.databuf = (char *)inbuf; - req.datalen = sizeof(inbuf); req.cylinder = WDSMART_CYL; - req.sec_num = select; - req.sec_count = 1; + req.sec_count = select; req.timeout = 1000; break; case AUTOSAVE: - req.flags = ATACMD_READ; + req.flags = ATACMD_READREG; req.features = ATA_SMART_AUTOSAVE; /* XXX missing from wdcreg.h */ req.command = WDCC_SMART; req.cylinder = WDSMART_CYL; - req.sec_count = 0xf1; - /* to enable autosave */ + req.sec_count = select; req.timeout = 1000; break; case IMMEDIATE_OFFLINE: /* NOTE: According to ATAPI 4 and UP, this command is obsolete */ - req.flags = ATACMD_READ; + req.flags = ATACMD_READREG; req.features = ATA_SMART_IMMEDIATE_OFFLINE; /* XXX missing from wdcreg.h */ req.command = WDCC_SMART; req.databuf = (char *)inbuf; @@ -294,10 +289,9 @@ ata_command_interface(int fd, smart_command_set command, int select, char *data) req.sec_count = 1; req.timeout = 1000; break; - case STATUS_CHECK: - /* same command, no HDIO in NetBSD */ - case STATUS: - req.flags = ATACMD_READ; + case STATUS: /* should return 0 if SMART is enabled at all */ + case STATUS_CHECK: /* should return 0 if disk's health is ok */ + req.flags = ATACMD_READREG; req.features = WDSM_STATUS; req.command = WDCC_SMART; req.cylinder = WDSMART_CYL; @@ -314,7 +308,7 @@ ata_command_interface(int fd, smart_command_set command, int select, char *data) return -1; } - if (command == STATUS_CHECK) { + if (command == STATUS_CHECK || command == AUTOSAVE || command == AUTO_OFFLINE) { char buf[512]; unsigned const short normal = WDSMART_CYL, failed = 0x2cf4; @@ -323,6 +317,9 @@ ata_command_interface(int fd, smart_command_set command, int select, char *data) perror("Failed command"); return -1; } + if (req.retsts != ATACMD_OK) { + return -1; + } /* Cyl low and Cyl high unchanged means "Good SMART status" */ if (req.cylinder == normal) return 0; @@ -341,10 +338,15 @@ ata_command_interface(int fd, smart_command_set command, int select, char *data) printwarning(BAD_SMART, buf); return 0; } + if ((retval = ioctl(fd, ATAIOCCOMMAND, &req))) { perror("Failed command"); return -1; } + if (req.retsts != ATACMD_OK) { + return -1; + } + if (command == CHECK_POWER_MODE) data[0] = req.sec_count; @@ -417,7 +419,16 @@ do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) (trunc ? " [only first 256 bytes shown]" : "")); dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len), 1); } - return 0; + switch (sc.retsts) { + case SCCMD_OK: + return 0; + case SCCMD_TIMEOUT: + return -ETIMEDOUT; + case SCCMD_BUSY: + return -EBUSY; + default: + return -EIO; + } } /* print examples for smartctl */