diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG index ff5c32a8c9e0bde9bd09753de635204a7eb832c0..87d3e33d5b5f8e12215c41ea0bdc1b58a7a7c294 100644 --- a/sm5/CHANGELOG +++ b/sm5/CHANGELOG @@ -1,6 +1,6 @@ CHANGELOG for smartmontools -$Id: CHANGELOG,v 1.583 2006/10/27 21:30:02 chrfranke Exp $ +$Id: CHANGELOG,v 1.584 2006/10/27 21:49:41 chrfranke Exp $ The most recent version of this file is: http://smartmontools.cvs.sourceforge.net/smartmontools/sm5/CHANGELOG?view=markup @@ -33,6 +33,8 @@ NOTES FOR FUTURE RELEASES: see TODO file. <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE> + [CF] Windows: Added WRITE LOG to support selective self tests. + [CF] Fix selective self test log revision number if '-T permissive' is specified (Tested with Samsung HD401LJ). diff --git a/sm5/TODO b/sm5/TODO index 6d9bcb230e9cb6d2958a029c1c9a8834d09c3476..3f7b2e82724f463fa2dee2a90ebb0f405214d916 100644 --- a/sm5/TODO +++ b/sm5/TODO @@ -1,6 +1,6 @@ TODO list for smartmontools: -$Id: TODO,v 1.61 2006/10/21 14:30:20 chrfranke Exp $ +$Id: TODO,v 1.62 2006/10/27 21:49:42 chrfranke Exp $ SATA devices under Linux ------------------------ @@ -126,8 +126,6 @@ Add support for 3ware 9000 series SATA controllers. Cygwin and Windows ------------------ -Add IDE/ATA selective self test. - Support DEVICESCAN for SPT (IOCTL_SCSI_PASS_THROUGH). Packaging diff --git a/sm5/os_win32.cpp b/sm5/os_win32.cpp index 4acf03e11b496a3e3b35a349ff82454d9abe88f8..4df00914e7b9c5f8501446815af5e28461ce983f 100644 --- a/sm5/os_win32.cpp +++ b/sm5/os_win32.cpp @@ -46,7 +46,7 @@ extern int64_t bytes; // malloc() byte count // Needed by '-V' option (CVS versioning) of smartd/smartctl -const char *os_XXXX_c_cvsid="$Id: os_win32.cpp,v 1.48 2006/10/21 20:02:17 dpgilbert Exp $" +const char *os_XXXX_c_cvsid="$Id: os_win32.cpp,v 1.49 2006/10/27 21:49:41 chrfranke Exp $" ATACMDS_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID; @@ -672,6 +672,10 @@ ASSERT_SIZEOF(ATA_PASS_THROUGH, 12+1); static int ide_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, unsigned datasize) { + if (datasize > 512) { + errno = EINVAL; + return -1; + } unsigned int size = sizeof(ATA_PASS_THROUGH)-1 + datasize; ATA_PASS_THROUGH * buf = (ATA_PASS_THROUGH *)VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); DWORD num_out; @@ -781,23 +785,19 @@ static int ata_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, i UCHAR ucDataBuf[512]; } ATA_PASS_THROUGH_EX_WITH_BUFFERS; - ATA_PASS_THROUGH_EX_WITH_BUFFERS ab; - IDEREGS * ctfregs; - unsigned int size; - DWORD num_out; const unsigned char magic = 0xcf; - memset(&ab, 0, sizeof(ab)); + ATA_PASS_THROUGH_EX_WITH_BUFFERS ab; memset(&ab, 0, sizeof(ab)); ab.apt.Length = sizeof(ATA_PASS_THROUGH_EX); //ab.apt.PathId = 0; //ab.apt.TargetId = 0; //ab.apt.Lun = 0; ab.apt.TimeOutValue = 10; - size = offsetof(ATA_PASS_THROUGH_EX_WITH_BUFFERS, ucDataBuf); + unsigned size = offsetof(ATA_PASS_THROUGH_EX_WITH_BUFFERS, ucDataBuf); ab.apt.DataBufferOffset = size; - if (datasize) { - if (!(0 <= datasize && datasize <= (int)sizeof(ab.ucDataBuf))) { + if (datasize > 0) { + if (datasize > (int)sizeof(ab.ucDataBuf)) { errno = EINVAL; return -1; } @@ -806,15 +806,26 @@ static int ata_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, i size += datasize; ab.ucDataBuf[0] = magic; } + else if (datasize < 0) { + if (-datasize > (int)sizeof(ab.ucDataBuf)) { + errno = EINVAL; + return -1; + } + ab.apt.AtaFlags = ATA_FLAGS_DATA_OUT; + ab.apt.DataTransferLength = -datasize; + size += -datasize; + memcpy(ab.ucDataBuf, data, -datasize); + } else { - //ab.apt.AtaFlags = 0; - //ab.apt.DataTransferLength = 0; + assert(ab.apt.AtaFlags == 0); + assert(ab.apt.DataTransferLength == 0); } assert(sizeof(ab.apt.CurrentTaskFile) == sizeof(IDEREGS)); - ctfregs = (IDEREGS *)ab.apt.CurrentTaskFile; + IDEREGS * ctfregs = (IDEREGS *)ab.apt.CurrentTaskFile; *ctfregs = *regs; + DWORD num_out; if (!DeviceIoControl(hdevice, IOCTL_ATA_PASS_THROUGH, &ab, size, &ab, size, &num_out, NULL)) { long err = GetLastError(); @@ -837,7 +848,7 @@ static int ata_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, i } // Check and copy data - if (datasize) { + if (datasize > 0) { if ( num_out != size || (ab.ucDataBuf[0] == magic && !nonempty(ab.ucDataBuf+1, datasize-1))) { if (con->reportataioctl) { @@ -1447,11 +1458,6 @@ static int ata_scan(unsigned long * drives, int * rdriveno, unsigned long * rdri // Interface to ATA devices. See os_linux.c int ata_command_interface(int fd, smart_command_set command, int select, char * data) { - IDEREGS regs; - int datasize; - const char * valid_options; - int i; - int port = -1; if ((fd & ~0x1f) == ATARAID_FDOFFSET) { // RAID Port encoded into pseudo fd @@ -1465,19 +1471,15 @@ int ata_command_interface(int fd, smart_command_set command, int select, char * } // CMD,CYL default to SMART, changed by P?IDENTIFY and CHECK_POWER_MODE - memset(®s, 0, sizeof(regs)); + IDEREGS regs; memset(®s, 0, sizeof(regs)); regs.bCommandReg = ATA_SMART_CMD; regs.bCylHighReg = SMART_CYL_HI; regs.bCylLowReg = SMART_CYL_LOW; - datasize = 0; + int datasize = 0; // Try all IOCTLS by default: SMART_*, ATA_, IDE_, SCSI_PASS_THROUGH - valid_options = "saic"; + const char * valid_options = "saic"; switch (command) { - case WRITE_LOG: - // TODO. Requires DATA OUT support - errno = ENOSYS; - return -1; case CHECK_POWER_MODE: // Not a SMART command, needs IDE register return regs.bCommandReg = ATA_CHECK_POWER_MODE; @@ -1503,6 +1505,13 @@ int ata_command_interface(int fd, smart_command_set command, int select, char * // Note: SMART_RCV_DRIVE_DATA supports this only on Win9x/ME datasize = 512; break; + case WRITE_LOG: + regs.bFeaturesReg = ATA_SMART_WRITE_LOG_SECTOR; + regs.bSectorNumberReg = select; + regs.bSectorCountReg = 1; + valid_options = "a"; // ATA_PASS_THROUGH only, others don't support DATA_OUT + datasize = -512; // DATA_OUT! + break; case IDENTIFY: // Note: WinNT4/2000/XP return identify data cached during boot // (true for SMART_RCV_DRIVE_DATA and IOCTL_IDE_PASS_THROUGH) @@ -1553,7 +1562,7 @@ int ata_command_interface(int fd, smart_command_set command, int select, char * // Try all valid ioctls in the order specified in dev_ioctls; bool powered_up = false; - for (i = 0; ; i++) { + for (int i = 0; ; i++) { char opt = ata_cur_options[i]; if (!opt) { @@ -1572,7 +1581,7 @@ int ata_command_interface(int fd, smart_command_set command, int select, char * continue; errno = 0; - assert(datasize == 0 || datasize == 512); + assert(datasize == 0 || datasize == 512 || (opt == 'a' && datasize == -512)); int rc; switch (opt) { default: assert(0);